Commit Graph
12711 Commits
Author SHA1 Message Date
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
Neil 3cc5e1dac6 Avoid duplicate ripgrep scans for full file inventories (#23490)
* Avoid duplicate ripgrep scans for unbounded file inventories

* Pin the broad ripgrep pass superset contract
2026-10-03 22:47:26 -07:00
Brennan Benson 87f2c0f92a fix(native-chat): read an older host's restart answer as recovered when sending, too
Hosts from before the recovered marker publish only the restart reason. The
working-state rule already read that reason as recovered; the send answer now
uses the same predicate, so both agree on those hosts.
2026-10-03 22:46:54 -07:00
Brennan Benson 9fcb3b629a Merge remote-tracking branch 'origin/main' into brennanb2025/chat-failed-send-returns-to-composer 2026-10-03 22:46:28 -07:00
Brennan Benson 1dc6157614 ci: run the cross-version tests when the chat send builders or the RPC request path change (#25061)
* ci: run cross-version wire suites when agent sends or orchestration change

The selector skipped the cross-version wire job for #24901, which changed the
shared agent-send path, the structured send envelope builders, and orchestration
RPC code. Route the send payload/fingerprint builders, src/main/runtime/orchestration/,
and the orchestration RPC methods to the job, and pin each rule in a test.

* ci: run cross-version wire suites only for code they execute

The agent-session suites now build their send through the shared outbox
builder and check it against the release host's schema and fingerprint,
so the send builder and outbox are selected exactly. Load-only
orchestration rules are dropped; the dispatcher-path files every suite
request runs through are selected instead.

* ci: run the release's own send admission, cover queued sends and the RPC reply builder

* test(cross-version): a wrong send fingerprint must be refused, so an agreed one is not vacuous
2026-10-03 22:23:01 -07:00
f199a20c3a Preserve OpenCode reasoning and recorded patches in native history (#24790)
* Use bounded OpenCode context for vault session continuation

OpenCode database and synthetic row paths are not text transcripts. Use the
vault preview or captured pane context, preserving actual transcript paths
containing a hash and supporting both OpenCode lanes and Windows paths.

Adapted the intent of #11859 and extended it to actual installed v2 vault rows.

Co-authored-by: mrcha033 <mrcha033@users.noreply.github.com>

* Read real OpenCode sessions in terminal-backed native Chat

Reuse the bounded AI Vault SQLite worker for v1 and v2 session pages and live updates. Keep terminal input as the real execution path and pace OpenCode Stop through its two-Escape interrupt.

Co-authored-by: xodmd45-ctrl <xodmd45-ctrl@users.noreply.github.com>

* fix(opencode): publish approval cards for permission requests

* Send OpenCode native approval through its Enter selector

* Resolve mobile Chat readability for folder workspaces

* Bound OpenCode part batches and preserve v2 image attachments

* Prefer live migrated OpenCode sessions over legacy copies

* Consolidate mobile Chat eligibility test imports

* Consolidate OpenCode SQLite protocol type imports

* fix(native-chat): preserve OpenCode reasoning and patch parts

Separate genuine reasoning from answer blocks in both native SQLite schemas and retain recorded patches as completed patch tools. Keep each database row together at page boundaries so the existing raw-row cursors cannot drop half of a mixed row.

Adapted from @akhan157's OpenCode native history work in #13287 at bb661d10d716764fb472d824cd434678875b1947; retains the current bounded reader and account discovery instead of restoring the older capture and cursor implementation.

Verified against genuine private installed 2.0.16 and official 1.18.30 CLI ingestion.

Co-authored-by: Adnan Khan <adnank11427@gmail.com>

* fix(native-chat): keep split OpenCode rows intact on desktop and mobile

Preserve the native reader's bounded OpenCode row groups in paired reads and snapshot/replacement frames so a second presentation-count slice cannot drop reasoning while advancing the database cursor. Sort derived reasoning before its answer under the same provider timestamp while retaining journal order.

These two boundaries were reproduced with genuine installed 2.0.16 and official 1.18.30 sessions in a hidden desktop renderer and the current mobile view over an actual authenticated encrypted pairing.

Completes the semantic presentation from @akhan157's #13287 without importing its older clipping or cursor implementation.

Co-authored-by: Adnan Khan <adnank11427@gmail.com>

* fix(native-chat): keep reasoning and answers together in live windows

* Bound OpenCode transcript RPC pages and present omission notices

* Bound OpenCode transcript RPC pages and present omission notices

* Bound OpenCode transcript RPC pages and present omission notices

* Update native worker oversized-history notice contract

---------

Co-authored-by: mrcha033 <mrcha033@users.noreply.github.com>
Co-authored-by: xodmd45-ctrl <xodmd45-ctrl@users.noreply.github.com>
Co-authored-by: nwparker <nwparker@users.noreply.github.com>
2026-10-03 22:04:52 -07:00
Neilandnwparker 136b990a05 fix(search): negotiate supported agents across mixed host versions (#25009)
Keep older request and reply parsers usable while current peers retain all supported history.

Co-authored-by: nwparker <nwparker@users.noreply.github.com>
2026-10-03 22:03:11 -07:00