Repository navigation
Fix watcher restart loop - #48
Merged
Merged
Conversation
Previous fix to check existing files caused an infinite restart loop (exit immediately → notification → restart → exit immediately...). Reverted to simple fswatch -1 with --event Created --event Updated filters. Improved dedup to avoid killing own PID/PPID. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…onichi#48) Previous fix to check existing files caused an infinite restart loop (exit immediately → notification → restart → exit immediately...). Reverted to simple fswatch -1 with --event Created --event Updated filters. Improved dedup to avoid killing own PID/PPID. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
that referenced
this pull request
Oct 10, 2026
… agents through a lost upstream 0.4.5 (randombet/bodhi_realtime_agent#52) fixes the #48 review items the relay agent depends on: under upstreamLossPolicy 'hold' a park or provider close is not a session end in actor mode (no agent stop, one redialer), upstreamRecovery requires the recovery primitives, and active silence hears recognized input. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
that referenced
this pull request
Oct 10, 2026
… agents through a lost upstream 0.4.5 (randombet/bodhi_realtime_agent#52) fixes the #48 review items the relay agent depends on: under upstreamLossPolicy 'hold' a park or provider close is not a session end in actor mode (no agent stop, one redialer), upstreamRecovery requires the recovery primitives, and active silence hears recognized input. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
that referenced
this pull request
Oct 10, 2026
…r own results (#5310) * Revert "feat(voice): relay agent — a task table reconciled with the core until the user has heard every outcome (#5290)" This reverts commit e841a92. The relay agent is rebuilt as a bodhi PersistentSubagentInstance in actor mode in the next PR. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(voice): relay agent as a bodhi subagent — work calls return their own results The relay agent is rebuilt as the bodhi PersistentSubagentInstance behind the work tool, in actor mode: - work is a background tool (pending message: the old "working on it" text); RelayAgent.invoke submits the task through the tool's own submission and resolves with that task's core result, which bodhi hands to the model when it is idle (and holds through a meeting). A queue position or an offline core is said at submission. - A result whose call is gone (cancelled, session closed) takes the ordinary delivery path; a voice task that cannot be delivered leaves one DM copy. - Kept from #5290: the voice task table, planReconcile (an unheard result is handed over again at most twice; a task not picked up after 3 min is reported once), and the status answers (get_task_status, the cancel list, the count ahead) read from the table. - Not kept: #5290's own result queue and pacing; bodhi's delivery does that. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * chore(deps): bodhi-realtime-agent 0.4.5 — actor mode under hold keeps agents through a lost upstream 0.4.5 (randombet/bodhi_realtime_agent#52) fixes the #48 review items the relay agent depends on: under upstreamLossPolicy 'hold' a park or provider close is not a session end in actor mode (no agent stop, one redialer), upstreamRecovery requires the recovery primitives, and active silence hears recognized input. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): drop the unused readdirSync import Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): relay agent owns the result queue — heard only when spoken, DM when undeliverable, no pacing The previous head marked a result heard the moment it was handed to bodhi and had no fallback when the session could not take it (a result for a closed page waited in memory, lost on restart). The relay agent now owns #5290's result queue again, minus pacing: - invoke returns the submission status at once (queued, the queue position, a duplicate, a rejection) as the tool result; no pendingMessage. - RelayAgent.attachDelivery binds the queue to the session. Results are handed over through session.tryPublishSystemNotification; a refusal is retried, then the result goes to the DM, one copy per result. - A result is recorded spoken only when the turn ends, handed over again once if the user cuts it off, names the request it answers, and is held through a meeting. Phone-call results go through the same queue. - Not kept: conversation pacing and the 2 s gather window. bodhi delivers when the model is idle; the pacer delayed a result 49 s on room noise. - Tests: the queue, refusal -> DM, the subagent, and the two single-copy guards (an offline copy still in results/, a result already sent to the DM), each failing when its guard is removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): the task table records which result answered a task — a deduped request is never left unheard Live: three PR status requests; the core answered all three in the first task's result and wrote [deduped: <first>] for the other two. The table did not know that, so the first result was handed over naming only its own request (the model spoke only that part) and the other two rows, holding a skip marker, were owed nothing. - A row records answeredBy when its result is [deduped: <task>] (local and relay-mode result paths; dedupTarget in skip_marker_ownership). - A result is handed over naming every request it answers (its own and each unheard row answered by it) and records all of their deliveries together. - Reconcile judges an answeredBy row by its answering task's result: if that was handed over without it (the dedup landed later), it is handed over again, named for this row's request. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): work is a Gemini async call that returns its result; the task table covers what the call cannot Delivery goes back to the work call itself, now declared NON_BLOCKING: invoke waits for its task's result and returns it as the function response, so Gemini decides when to say it and which call it answers. The relay's own result queue is removed. The task table covers what a pending call cannot carry: - a fresh provider connection (session.reconnectBoundary): responses to calls made on the old one would be fenced off, so those calls end quietly and their results go out as a system notice naming the request; - a cancelled call or a restart: same notice path; one DM copy when the session cannot speak; held through a meeting; - a result answering several tasks (answeredBy) ends their waiting calls and records them all; a late dedup is offered to the task's own waiting call by reconcile first. A queue position or an offline core is said at submission. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): work keeps its pending message — the model answers at once while the call waits for the result Live at 5b046c3: with work declared NON_BLOCKING and no pending message the model said nothing after calling it (an empty turn) until the user spoke again; it waited for the function response, which comes only when the core finishes. The pending message is back: bodhi answers the call at once with "still in progress" and hands the result over as a system notification when invoke returns, which a fresh provider connection does not drop, so the reconnect-boundary detach is gone too. invoke still waits for its task's result; the task table and reconcile cover a call that is gone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): a work call always ends — on cancel, on abort, and when its result goes to the DM - Cancel: the core never answers a cancelled task, so its waiting call hung until the session ended. noteVoiceTaskCancelled now tells the relay agent, which ends the call quietly. - Abort: the relay rejected with "aborted", and because work has a pending message bodhi published "Background task failed… aborted. Tell the user" while the task kept running. The call now ends normally with "still running; the result comes separately", and the result goes the usual way. - No client connected: the result watcher sends a voice task's result to the DM (it never offers it to the relay), so the waiting call also hung. It now ends that call and the calls of the tasks answered in the same result. No call ends with a rejection: bodhi reads a rejection out as a failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): a queued voice task is cancelled at once — no instruction whose reply contradicts the table Live on the test Mac: the user cancelled a task still in the queue. cancel_task deleted its file and also wrote a CANCEL_INSTRUCTION, then told the model to wait for the core. The core found no file and replied "Nothing to cancel — task was never queued"; that reply was read out as "the cancellation couldn't be processed". A queued task whose file is deleted never runs, so it is cancelled: the user is told so at once and no instruction is written. If the core took the task in that instant, its result already comes with CANCELLED_BUT_FINISHED_NOTE. The cancel_requested state ("waiting for the core to confirm") is gone with it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes infinite restart loop caused by early-exit-on-existing-files logic. Reverted to clean fswatch -1 with event filters.
🤖 Generated with Claude Code