Commit Graph
12717 Commits
Author SHA1 Message Date
Brennan Benson 8fa5974453 fix(native-chat): a refused Stop is said even when the refusal answers a resend
When the first Stop's answer was lost, the press stayed quiet because Orca would send the Stop
again, but a refusal answering that resend was never said either, so the person was never told
the agent wasn't stopped. A refusal is now said on any attempt; a lost answer stays quiet only
while a resend is still owed.
2026-10-04 04:02:52 -07:00
Brennan Benson 7cfc4b3d08 fix(native-chat): while Orca keeps sending a message, the chat line names no step
The line under a message Orca keeps resending said things like "Send your message again" or
"Start a new chat" beside "Orca will keep trying to send it." Following that step while Orca
resends could send the message twice. The line now keeps only what stopped it (when the refusal
names a cause) and that Orca keeps trying:
- an "outcome unknown" the request threw says nothing, as the same answer returned does;
- a stage that couldn't be saved also says Orca keeps trying, which it does;
- a Stop that takes back the message the line is about clears the line.
Also corrects a comment: this build's replay makes the same stand-in record as an older host's,
for an accepted send whose row a new journal epoch dropped.
2026-10-04 04:02:51 -07:00
Brennan Benson ee4dbf021c test(native-chat): read sent requests through checked helpers instead of casts 2026-10-04 03:48:38 -07:00
Brennan Benson 0f7a1eb4c7 fix(native-chat): a command blocked behind an unsettled message says to wait, not retry
Desktop and the phone have no Retry on a message any more. Also passes the journal rows on every
render in the conversation Stop tests.
2026-10-04 03:47:08 -07:00
Brennan Benson e05dbe7943 fix(native-chat): a launch prompt reports delivery only once the chat finally settles it
The launch caller was answered after the prompt's first attempt. When that attempt got no answer,
the chat kept resending the prompt, but the caller had already given up: the notes stayed on the
shelf and could be sent a second time. Each outbox entry's final ending (the host holds it, or it
came back, was withdrawn or was discarded) is now published per entry, and the launch settlement
waits through resends for it. Delivered fires onPromptDelivered once; anything else reports that
the chat already said what happened.
2026-10-04 03:43:41 -07:00
Brennan Benson dc0a426d0a refactor(native-chat): the launch prompt's in-flight sends get their own module
The outbox sender imported the launch prompt's shared in-flight map from the launch prompt module,
which imports the sender: a dependency cycle CI's lint rejects. The map now lives in
structured-agent-launch-prompt-in-flight-dispatches, which both import. No behaviour change.
2026-10-04 03:42:58 -07:00
Brennan Benson 5bd5879ab7 fix(native-chat): the host-window timer waits only for windows still open
A window that had already closed while the journal was still loading would arm a zero-delay timer
that re-armed itself every tick. Only windows still open arm one now; a closed one is settled when
the journal loads. Adds a test that a Stop-outrun send comes back once its window closes.
2026-10-04 03:35:56 -07:00
Brennan Benson 04f3468f15 test(native-chat): two older tests follow the new hand-back and launch prompt rules
A repeated hand-back is the same text, so the repeat no longer adds leading spaces (the first
line's indentation is now kept). A launch prompt the host refused comes back to the chat, which
says why, so its caller is told the failure was already shown.
2026-10-04 03:34:28 -07:00
Brennan Benson 565b740c25 test(native-chat): "Not confirmed" waits while the agent works or the chat is still starting 2026-10-04 03:33:25 -07:00
Brennan Benson 589bfad798 docs(native-chat): comments no longer describe the removed Retry or id rotation 2026-10-04 03:32:26 -07:00
Brennan Benson 937e79ea29 fix(native-chat): an answer that proves nothing never hands a message back, and every held send ends
What one send attempt's answer may conclude, tightened where it could duplicate, lose, or strand
a message:
- A request the host turned away (unknown method, bad params, not authorized) proves no record
  only on a first attempt; on a resend an earlier attempt may have landed, so it is sent again.
- "First attempt" is checked again when the answer arrives: another view that staged the same id
  meanwhile makes it a resend.
- A reused message id on a resend is settled by the journal, as a conflict is.
- An older host's made-up record for a row its journal lost is the chat's only when a loaded row
  shows it; otherwise the message comes back with "couldn't confirm" words instead of vanishing.
- A stage that can't be saved no longer hands the message back (an earlier attempt may have
  landed): it waits, says "Couldn't save your message." once, and is tried again.
- When a resend stays unanswered because of a refusal Orca can't trust, the chat line says why
  once, followed by "Orca will keep trying to send it.", and clears once the message lands.
- Sends a Stop outran, and messages an older build left, end when the host's window for their id
  closes, even if nothing else moves by then.
- The queue stays held through the capability check, so a later send can't overtake the head.
- A launch prompt the chat handed back or keeps sending no longer also makes the caller toast
  "could not be sent" with a copy button.
2026-10-04 03:31:23 -07:00
Brennan Benson 6d120ea9e2 fix(native-chat): a Stop gives up on its outrun sends only once its request ends
- A newer message used to make Orca give up on a Stop's outrun sends even while that Stop's own
  request was still out, so a send could come back as "couldn't confirm" before the Stop's real
  answer arrived. It now waits for the request to end.
- The first press no longer shows "The agent wasn't stopped." for a lost answer that Orca is about
  to resend; it still does when nothing will resend it, and always for a refusal.
- This app's own sends are compared with the press by when they were queued, on this machine's
  clock; the comment now says another client's are compared by the time in their id.
2026-10-04 03:20:01 -07:00
Brennan Benson a688ed4ca2 fix(native-chat): sends a Stop outran no longer stall the chat
Two ways a Stop could leave messages stuck on "Sending…":
- the resend timer picked the first message in doubt even when it was one the Stop outran (never
  resent), so a later message in doubt behind it was never resent either; it now resends the
  message the queue is actually waiting on;
- a Stop answered while the agent was idle writes nothing to the journal, so its answer's position
  was one the chat had already read, and the settling step only ran when the journal moved. It now
  also runs when the outbox changes, so the outrun send comes back to the composer at once.
2026-10-04 03:18:30 -07:00
Brennan Benson 1cd798685b fix(native-chat): returned text is skipped only when the draft already ends with it
A message handed back to the composer was dropped whenever its text appeared anywhere in the
draft ("go" inside a longer sentence), and its first line lost its indentation. It is now skipped
only when the draft is that text or ends with it after a blank line, and only the end is trimmed.
2026-10-04 03:17:04 -07:00
Brennan Benson 62ef8e7804 fix(native-chat): every chat send ends one of three ways, decided by the host's answer
A send now ends only by what the host said: it holds a record (the host's row shows the message
from then on), it proved there is no record (the text goes back into the conversation's draft and
the reason is said once), or nothing answered yet (the same id goes again, quietly, as "Sending…").
One shared settlement decides it for the open chat and a launch prompt alike.

Removed: the Retry control and its id rotation, the rejected and held-for-Retry outbox states, the
Stop latch, the per-window failure memory, the parked "unknown" entry, the launch prompt's own send
path, and the error-text regex (errors are read by code). A Stop stamps a send already on its way
with the Stop's own id; the Stop's answer settles it. Drafts of a structured chat are keyed by the
conversation and survive their tab closing. Entries older builds left waiting for a Retry are
settled once the journal loads, never sent again.
2026-10-04 02:58:21 -07:00
Brennan Benson e10d88d6e8 Merge #24918 (recorded rejections stay in the chat) into C2, resolving its conflict with #24606
The row keeps #24606's "Sending…" in the time's slot and #24918's muted not-sent line; the notices
keep both: an entry still sending reads as sending, and a recorded rejection no entry carries reads
as not sent.
2026-10-04 02:01:22 -07:00
Brennan Benson 8c10bc8511 Merge remote-tracking branch 'origin/brennanb2025/chat-drafts-survive-reload' into brennanb2025/chat-send-settles-once 2026-10-04 02:00:08 -07:00
Brennan Benson 138466e7e8 Merge remote-tracking branch 'origin/brennanb2025/chat-failed-send-returns-to-composer' into brennanb2025/chat-send-settles-once 2026-10-04 02:00:08 -07:00
Brennan Benson f63fb59f61 docs(native-chat): say what a replay's preparation does for every plan 2026-10-04 00:57:13 -07:00
Brennan Benson 4b9f91a5a0 test(native-chat): check the outside file by its real path too 2026-10-04 00:46:30 -07:00
Brennan Benson 16c61f6a8d fix(native-chat): grant a paste's stored spelling only when it names the same file
A grant also covers its path's own real path, so a stored spelling that is
itself a link inside the paste folder could have granted an outside file
while the path as restored reached a real paste. The stored spelling is
now granted only when it resolves to the same file; otherwise only the real
path is, and the preview falls back to the generic icon.
2026-10-04 00:46:15 -07:00
Brennan Benson 83dc6b2590 fix(native-chat): a ledger refusal is answered first, and a /clear refuses only a send's first run
An id the ledger refuses (expired, conflict, invalid, capacity) is answered as admission would,
with no journal read, preparation or write, so a closed chat or a read-only store answers it too.
A re-read after the replay open that comes back refused returns that refusal.

Whether a /clear is in flight is read when a send arrives and applied in the send's preparation
for a first run only: an id the ledger holds by the send's turn, including one whose earlier
attempt was queued ahead of the clear, is answered from its record. MutationPlan makes
settlesWithWrite and settledOutcome exclusive; the capability text no longer promises a refused
id never sends.
2026-10-04 00:45:51 -07:00
Brennan Benson c640f75300 fix(native-chat): a restored paste is readable by the path its draft stored
Restore granted only a paste's real path, but the composer reads the
preview by the path its draft stored, so with user data reached through a
link the restored chip showed a generic icon. The stored spelling is
granted too; it is already proven to sit inside the paste folder. A test
also pins that a composer paste asks for the paste folder.
2026-10-04 00:44:40 -07:00
Brennan Benson f6c19952b9 Merge remote-tracking branch 'origin/main' into brennanb2025/chat-recorded-outcomes-from-journal
# Conflicts:
#	mobile/src/session/MobileNativeChatMessage.test.ts
2026-10-04 00:33:03 -07:00
Brennan Benson 0971ba9445 fix(native-chat): only composer pastes use the paste folder, and restore grants only real paths
Every local clipboard image save had moved into the paste folder, whose
macOS path has a space, so a screenshot pasted into a terminal or sent to
a terminal-backed agent no longer attached. Only a native-chat composer
paste goes there now, through an optional field on the existing save
call; terminal, editor and phone pastes stay in the system temp folder as
before. An image path sent to an agent's input is escaped the way a
dropped image is.

The restore re-grant now grants only the file's real path, and only when
both the real path and the path as written are inside the paste folder,
which must not itself be a link. The sweep deletes only Orca's paste
files and skips a linked folder.
2026-10-04 00:32:49 -07:00
Brennan Benson 5ff07e6730 fix(native-chat): placeholder chips say what happened and only a user attach replaces one
A placeholder now shows the image's name and a short hint on the chip
itself, "Attach again" for a file and "Not kept" for a pasted image, with
the longer explanation in its tooltip. The copy no longer says the image
wasn't saved: it says it couldn't be brought back, and for a pasted image
it asks only for removal, since a new paste can't match it. The send
button now says to remove the image to send.

Only an image the user attaches (picking, dropping or pasting) takes the
place of a placeholder with its file name. An image Stop gives back is
added beside it, so a different file with the same name no longer hides
the reminder.
2026-10-04 00:23:49 -07:00
Brennan Benson a45be92c51 fix(native-chat): a send's answer commits with its write, and a resend is answered before any write
A send (and /compact) settles its ledger row `succeeded` in the same SQLite transaction as the
submission or queued draft that accepts it, so a row still `pending` proves nothing was written and
a resend runs it for the first time. The unknown-before-run mark and the per-row journal epoch go.

A resent id is answered from its row and the journal before preparation starts an agent and before
any write transaction: a recorded refusal with nothing opened; otherwise the conversation is opened
(no agent start for a send) and replayed, and a conversation that will not open answers unknown.
2026-10-04 00:21:34 -07:00
Neil ffd23fe25c Avoid repeated runtime imports and recovery fixture seeding (#25155) 2026-10-04 00:18:19 -07:00
Brennan Benson ad7b1a9276 fix(native-chat): type the paste-folder path helper from path.posix 2026-10-04 00:12:29 -07:00
Brennan Benson a938777ea9 fix(native-chat): type the paste-folder path helper with PlatformPath 2026-10-04 00:10:09 -07:00
Brennan Benson 657496ca54 test(native-chat): the paste sweep test ages the link itself 2026-10-04 00:06:48 -07:00
github-actions[bot] b1b78b4d20 Update README downloads badge 2026-10-04 07:06:01 +00:00
Brennan Benson 13672f8267 fix(native-chat): pasted images in a draft come back after a restart
A pasted screenshot lived in the OS temp folder with a read permission held
in memory, so a draft could only bring it back as a placeholder. Local
pastes are now written to Orca's own native-chat-pastes folder under the
app's user data, and a draft keeps them as real images. On restore the
composer asks the main process to re-grant each one; main grants a read
only when the file's real path, symlinks and junctions resolved, is inside
that folder, and reports anything else as not kept, which becomes the
placeholder. Pastes older than 30 days are deleted at startup, far past
the host's 24 hour window for a resent message; the sweep never follows a
link and never blocks startup. SSH pastes and older temp-folder pastes
still come back as placeholders.
2026-10-04 00:01:46 -07:00
Brennan Benson f6784ad53b fix(mobile): resend the same text as a new message when its kept id was rejected
After a lost answer, the phone keeps that message's id for its text. If the
host since recorded and rejected it, sending the same text again replayed the
id, which answered with the same rejection: no banner, no bubble, and an empty
composer, so the press did nothing. Such a replay now goes out under a fresh
id, as a withdrawn one already does.

"Sent, but this phone couldn't update its record" is no longer said for a
resend the host recorded and rejected; its row says it was not sent.
2026-10-04 00:00:21 -07:00
Brennan Benson 7ebec5b869 perf(native-chat): read only status rows when finding command result rows
The scan parsed every journal key on each update while a row showed as not
sent, about 3-17 ms per call at 3000 items. Every result row is a status
row, so the scan now skips the rest before parsing (about 0.02-0.04 ms).
2026-10-04 00:00:20 -07:00
Brennan Benson 059e79e418 fix(native-chat): keep "Sending…" until the host has the message, in the time's slot
A message the user retried, a second message in doubt, or one requeued over a
rejected row had a journal row that did not hold it, so it showed nothing and
looked sent. "Sending…" now stays until the row is pending or accepted.

The marker took the place of the whole meta row, so the copy button went away
while sending and the row jumped when it cleared. The row now stays mounted:
copy keeps its hover reveal and "Sending…" sits where the time goes.
2026-10-03 23:59:31 -07:00
Brennan Benson 94c446afb3 fix(native-chat): a rejected /compact stays in the chat, said once
A /compact the host recorded and then rejected was hidden, so on several paths
(blocked after the reply stopped waiting, rejected on restart, or seen from
another window or the phone) it vanished with nothing saying it failed. It now
stays as a not-sent row for every viewer, like any message the host recorded.

Its line says only "Your message was not sent." when a loaded host row
already says why: its turn's result row (found by the command's id) or the
failed start's row. The sender's command reply no longer repeats it when the
loaded journal shows the host recorded the command under the operation id,
and the text stays the row's rather than coming back to the composer.

The desktop pane's delivery-notice wiring moves into its own hook.
2026-10-03 23:39:09 -07:00
Brennan Benson f7177f2f50 test(native-chat): no send while an image waits to be attached again 2026-10-03 23:35:20 -07:00
Brennan Benson 7336174da3 fix(native-chat): restored images Orca couldn't keep come back to attach again
A pasted screenshot in an unsent draft vanished after a restart with no
notice, and a restored image whose file had been deleted looked fine until
the send failed. Both now come back as a placeholder chip that names the
image and says it wasn't saved with the draft. Send stays disabled, and
the send button says to attach the image again or remove it. Attaching a
file with the same name takes the placeholder's place.

Two browser tabs of the web client on one chat now follow each other: when
one sends or edits the draft, the other drops its copy and shows the new
one, unless it has an edit of its own not yet saved.
2026-10-03 23:34:29 -07:00
Brennan Benson 0be4769322 test(native-chat): pass the ledger row to the thread-goal rerun check 2026-10-03 23:29:59 -07:00
NeilandKatsuma Takehisa ce07786266 Keep opened issue details and edits in the selected repository (#24729)
Keeps a fork issue’s details, metadata and edits bound to the repository the user opened, including same-number issues in fork and upstream. Repairs selected-assignee leakage and delayed failed edits repainting another issue.

Fixes #24378

Incorporates and cross-reviews contributor PR #24379, including its source-resolver correction and regression material. Covers the contributor PR’s Project-row identity and retained-dialog mutation findings. The final published head passes focused tests, hidden macOS rendering and current CI; the callback-timing bot thread has an evidence-based response.

Co-authored-by: Katsuma Takehisa <k.takehisa@nissogr.com>
2026-10-03 23:19:55 -07:00
Brennan Benson b5cc3c8369 fix(native-chat): say "Sending…" on a message until the host confirms it
A send whose answer was lost was resent quietly under the same id but looked
like any delivered message. Every message still in the outbox with no failure
to show now says "Sending…", muted, in place of its time, until the journal
holds a row for it. Rows that say a message did not go through keep only that
line and its Retry. The notices read the outbox through the same reconcile as
the transcript, so a row that lands clears the marker in one step.
2026-10-03 23:18:24 -07:00
Neil 8267b578b2 Fix Markdown Find editing without moving the caret or viewport (#25144)
* Fix Markdown Find editing without changing the caret or viewport

* Preserve Markdown selections across search focus and stale updates
2026-10-03 23:17:52 -07:00
Brennan Benson bdf03f6fda fix(native-chat): a resent send id gets its recorded answer, never an early refusal or a made-up record
The host now looks a resent send id up before preparing the session. A row
that settled refused answers with its refusal before the chat is opened. A
resend whose chat cannot be opened or made ready answers unknown instead of a
refusal. A /clear in flight refuses only ids the ledger does not hold.

A send row now records the journal epoch it was admitted into. An unsettled
row with nothing written in that same epoch runs for the first time; under a
later epoch the host answers unknown instead of reconstructing a submission
it never had. The host advertises agent-session.send-answers-proof.v1.
2026-10-03 23:15:49 -07:00
Neil f8081c5313 Filter Markdown filenames before sending the listing to the app (#25148) 2026-10-03 23:15:48 -07:00
mmarabel 9207aef01d Add an optional shortcut to toggle child workspaces (#24165)
Adds a user-assignable shortcut for the existing child-workspace chip action. It stays unassigned by default on macOS, Linux and Windows. Final-source rendered checks cover Settings recording/reset, guards, scroll preservation and restart.

Fixes #24163

Continues mmarabel’s original contribution in this PR. Issue #24163 has no sibling implementation PR. Existing bot findings are fixed, withdrawn or addressed in the PR review.

Co-authored-by: mmarabel <166927047+mmarabel@users.noreply.github.com>
2026-10-03 23:15:41 -07:00
Neil d5bb69d348 Cut CI time in store, Git contention and readiness tests (#25147)
* Check store retention boundaries with a faster independent oracle

* Replace CI diagnostic sleeps with gated contention and scoped transcript clocks
2026-10-03 23:13:45 -07:00
NeilandBrennan Benson 5a2aa87f1c Select OpenCode plugin exports from the execution host version (#24662)
* fix: wait for OpenCode worker composer before first dispatch

Reuse captured composer readiness on local and paired execution hosts and revoke launching-shell paste anchors.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>

* feat(opencode): probe execution-host CLI capabilities

* fix(opencode): select plugin default for execution host loader

* fix(opencode): limit prompt prefill capability to verified release

* feat(opencode): probe launch capabilities on the execution host

* fix(opencode): select plugin loader for the launched host binary

* fix(opencode): match WSL probe cwd and declared guest environment

* fix(opencode): preserve launch environment deletion boundaries

* STRICT launch CI contract correction

* CAPS launch CI contract correction

* test: initialize Claude prompt state in output retention fixture

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
2026-10-03 23:13:06 -07:00
Brennan Benson e6c5c84546 fix(native-chat): a not-sent line reads muted, not as an error
The line under a message that was not sent, on desktop and phone, used the
error color, as if the user had something to fix. It is a plain label now,
in the muted text color. A line that is still in doubt ("Message delivery is
unconfirmed.", or an expired id Orca can't confirm) keeps the error color,
as does the terminal chat's notice.
2026-10-03 22:54:09 -07:00
Brennan Benson 4f50e40578 fix(mobile): never hand back a message the host recorded and then rejected
The phone put a rejected message's text back in the composer even when the
host had recorded it, so the same text showed in the chat as not sent and in
the composer. The host's row now holds it, as on the desktop: the send reports
that the host holds the text, so the composer and attachments are not
restored. A message a Stop withdrew still goes back with its notice.
2026-10-03 22:48:45 -07:00