Merge nucleic/rustic-spruce-weasel-yri3 into dev

This commit is contained in:
2026-07-22 03:55:01 -07:00
parent db7c66b659
commit 9df7156c86
2 changed files with 13 additions and 6 deletions
+10 -5
View File
@@ -13546,16 +13546,21 @@ extension AppStore: SyncHostBridge {
}
/// The `nucleic_monitor` event sink for a session: deliver a fired monitor's output back into
/// the session as a fresh user turn (the cross-turn re-invocation the native `Monitor` can't do
/// the session as a fresh turn (the cross-turn re-invocation the native `Monitor` can't do
/// under Nucleic's single-shot turn model). Injection is an ordinary `sendInput` it starts a
/// turn when the session is idle, queues (and coalesces) when one is in flight and is
/// transcript-visible, so every wake-up is auditable. Supplied unconditionally; the backend only
/// calls it for a monitor the agent itself armed.
/// turn when the session is idle, queues (and coalesces) when one is in flight. The agent sees
/// the wake-up as user-role text, but it is *not* echoed to the transcript as a user message:
/// nobody typed it, and a wall of monitored command output masquerading as the user's own bubble
/// misreads the conversation badly. A muted note carries the same payload instead, so every
/// wake-up stays auditable while reading as what it is machine output. Supplied
/// unconditionally; the backend only calls it for a monitor the agent itself armed.
func monitorEventSink(for sessionID: SessionID) -> MonitorEventSink {
{ [weak self] description, event in
guard let self, let controller = self.controllers[sessionID] else { return }
let header = "[Monitor: \(description)]"
try? await controller.sendInput(AgentInput(text: "\(header)\n\(event)"))
await controller.note("\(header)\n\(event)", icon: "binoculars")
try? await controller.sendInput(
AgentInput(text: "\(header)\n\(event)"), echoToTranscript: false)
}
}
+3 -1
View File
@@ -410,7 +410,9 @@ public typealias OrchestraAskSupervisorHandler =
/// single-shot turn model (each turn is one foreground `claude -p` process that exits at end of
/// turn, with no harness loop to wake the agent later). The monitor's watch is owned by the
/// backend across turns; when its command emits output, the backend calls this sink and the host
/// injects the event via `SessionController.sendInput`, starting (or queuing) a new turn.
/// injects the event via `SessionController.sendInput`, starting (or queuing) a new turn. The
/// injection is silent (`echoToTranscript: false`) and paired with a muted note, so the wake-up
/// stays auditable without impersonating a message the user typed.
/// `(description, event)` `description` labels the watch; `event` is the coalesced output lines.
public typealias MonitorEventSink =
@MainActor @Sendable (_ description: String, _ event: String) async -> Void