@vellumai/assistant 0.11.4-staging.2 → 0.11.4-staging.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +8 -2
- package/ARCHITECTURE.md +2 -0
- package/docs/architecture/memory.md +15 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +11 -6
- package/knip.json +3 -0
- package/openapi.yaml +136 -76
- package/package.json +1 -1
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/conversation-agent-loop.test.ts +4 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +39 -62
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +94 -2
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -3
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +4 -7
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +1 -1
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/acp/session-manager.ts +8 -1
- package/src/api/surfaces.ts +5 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +21 -10
- package/src/calls/__tests__/voice-triage-escalate.test.ts +8 -0
- package/src/calls/voice-session-bridge.ts +44 -25
- package/src/calls/voice-triage-escalate.ts +1 -0
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/lib/bundled-marketplace.json +1 -1
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/call-site-defaults.ts +7 -0
- package/src/config/default-profile-catalog.ts +96 -4
- package/src/config/feature-flag-registry.json +11 -11
- package/src/config/skills.ts +9 -2
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/conversation-agent-loop.ts +14 -13
- package/src/daemon/conversation-notifiers.ts +11 -9
- package/src/daemon/conversation-process.ts +0 -27
- package/src/daemon/conversation-store.ts +4 -4
- package/src/daemon/conversation-surfaces.ts +27 -13
- package/src/daemon/conversation-tool-setup.ts +2 -4
- package/src/daemon/conversation.ts +81 -44
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/process-message.ts +0 -13
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +5 -235
- package/src/hooks/types.ts +5 -0
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +118 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-session.ts +63 -9
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/permissions/prompter.ts +1 -5
- package/src/persistence/conversation-queries.ts +66 -16
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/schema/documents.ts +4 -4
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/index.ts +5 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/defaults/main.ts +6 -7
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/mtime-cache.ts +17 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/retry-callsite.test.ts +20 -0
- package/src/providers/openai/chat-completions-provider.ts +11 -1
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +11 -6
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +9 -49
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/agent-wake.ts +15 -12
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +170 -1
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/conversation-list-routes.ts +54 -22
- package/src/runtime/routes/conversation-management-routes.ts +2 -3
- package/src/runtime/routes/conversation-routes.ts +11 -13
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +20 -37
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +8 -6
- package/src/tools/acp/spawn.ts +6 -4
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/daemon/interactive-turn-sender.ts +0 -59
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* the Conversation constructor and dispose/abort methods.
|
|
4
4
|
*
|
|
5
5
|
* Notifier callbacks read from the provided context object at invocation
|
|
6
|
-
* time (not registration time), so they always see the latest
|
|
7
|
-
*
|
|
6
|
+
* time (not registration time), so they always see the latest messages
|
|
7
|
+
* reference. They emit through the conversation, whose sink is fixed for its
|
|
8
|
+
* life, so an out-of-turn notification reaches every subscribed client
|
|
9
|
+
* without any per-turn wiring.
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
import { createAssistantMessage } from "../agent/message-types.js";
|
|
@@ -32,7 +34,7 @@ import { restingTrust } from "./trust-context-types.js";
|
|
|
32
34
|
* invocation time. Properties are read lazily from this reference.
|
|
33
35
|
*/
|
|
34
36
|
export interface NotifierConversationContext {
|
|
35
|
-
|
|
37
|
+
emit: (msg: AssistantEvent) => void;
|
|
36
38
|
messages: Message[];
|
|
37
39
|
trustContext?: TrustContext;
|
|
38
40
|
}
|
|
@@ -77,12 +79,12 @@ export function registerConversationNotifiers(
|
|
|
77
79
|
|
|
78
80
|
ctx.messages.push(createAssistantMessage(questionText));
|
|
79
81
|
|
|
80
|
-
ctx.
|
|
82
|
+
ctx.emit({
|
|
81
83
|
type: "assistant_text_delta",
|
|
82
84
|
text: questionText,
|
|
83
85
|
conversationId: conversationId,
|
|
84
86
|
});
|
|
85
|
-
ctx.
|
|
87
|
+
ctx.emit({
|
|
86
88
|
type: "message_complete",
|
|
87
89
|
conversationId: conversationId,
|
|
88
90
|
messageId: msg.id,
|
|
@@ -97,12 +99,12 @@ export function registerConversationNotifiers(
|
|
|
97
99
|
const speakerLabel = speaker === "caller" ? "Caller" : "Assistant";
|
|
98
100
|
const transcriptText = `**Live call transcript**\n${speakerLabel}: ${text}`;
|
|
99
101
|
|
|
100
|
-
ctx.
|
|
102
|
+
ctx.emit({
|
|
101
103
|
type: "assistant_text_delta",
|
|
102
104
|
text: transcriptText,
|
|
103
105
|
conversationId: conversationId,
|
|
104
106
|
});
|
|
105
|
-
ctx.
|
|
107
|
+
ctx.emit({
|
|
106
108
|
type: "message_complete",
|
|
107
109
|
conversationId: conversationId,
|
|
108
110
|
source: "aux",
|
|
@@ -113,12 +115,12 @@ export function registerConversationNotifiers(
|
|
|
113
115
|
registerCallCompletionNotifier(conversationId, (callSessionId: string) => {
|
|
114
116
|
const summaryText = buildCallCompletionMessage(callSessionId);
|
|
115
117
|
|
|
116
|
-
ctx.
|
|
118
|
+
ctx.emit({
|
|
117
119
|
type: "assistant_text_delta",
|
|
118
120
|
text: summaryText,
|
|
119
121
|
conversationId: conversationId,
|
|
120
122
|
});
|
|
121
|
-
ctx.
|
|
123
|
+
ctx.emit({
|
|
122
124
|
type: "message_complete",
|
|
123
125
|
conversationId: conversationId,
|
|
124
126
|
source: "aux",
|
|
@@ -60,7 +60,6 @@ import {
|
|
|
60
60
|
} from "./conversation-slash.js";
|
|
61
61
|
import { getModelInfo } from "./handlers/config-model.js";
|
|
62
62
|
import { preactivateHostProxySkills } from "./host-proxy-preactivation.js";
|
|
63
|
-
import { bindInteractiveTurnSender } from "./interactive-turn-sender.js";
|
|
64
63
|
import type { UserMessageAttachment } from "./message-protocol.js";
|
|
65
64
|
import { buildTransportHints } from "./transport-hints.js";
|
|
66
65
|
import { sameTrustIdentity, type TrustContext } from "./trust-context-types.js";
|
|
@@ -1293,26 +1292,11 @@ async function drainSingleMessage(
|
|
|
1293
1292
|
drainLoopOptions.isHiddenPrompt = true;
|
|
1294
1293
|
}
|
|
1295
1294
|
|
|
1296
|
-
// By the time the drain runs, the conversation-level sender is usually the
|
|
1297
|
-
// no-op the just-finished interactive turn's restore (or conversation
|
|
1298
|
-
// birth) left behind, and the drain bypasses `processMessage`, so without
|
|
1299
|
-
// a fresh bind the PermissionPrompter's confirmation_request (which reads
|
|
1300
|
-
// the conversation-level sender, not the turn's `onEvent`) would be
|
|
1301
|
-
// emitted into nothing and hang until the permission timeout. Same
|
|
1302
|
-
// bind/restore contract as `processMessage`.
|
|
1303
|
-
const restoreSender =
|
|
1304
|
-
next.isInteractive === true
|
|
1305
|
-
? bindInteractiveTurnSender(conversation)
|
|
1306
|
-
: undefined;
|
|
1307
|
-
|
|
1308
1295
|
conversation
|
|
1309
1296
|
.runAgentLoop(agentLoopContent, userMessageId, {
|
|
1310
1297
|
...drainLoopOptions,
|
|
1311
1298
|
onEvent: next.onEvent,
|
|
1312
1299
|
})
|
|
1313
|
-
.finally(() => {
|
|
1314
|
-
restoreSender?.();
|
|
1315
|
-
})
|
|
1316
1300
|
.catch((err) => {
|
|
1317
1301
|
const message = err instanceof Error ? err.message : String(err);
|
|
1318
1302
|
log.error(
|
|
@@ -1795,14 +1779,6 @@ async function drainBatch(
|
|
|
1795
1779
|
drainLoopOptions.isHiddenPrompt = true;
|
|
1796
1780
|
}
|
|
1797
1781
|
|
|
1798
|
-
// Same sender contract as drainSingleMessage: an interactive drained batch
|
|
1799
|
-
// must rebind the conversation-level sender or prompter confirmations
|
|
1800
|
-
// raised during this turn reach no client.
|
|
1801
|
-
const restoreSender =
|
|
1802
|
-
drainLoopOptions.isInteractive === true
|
|
1803
|
-
? bindInteractiveTurnSender(conversation)
|
|
1804
|
-
: undefined;
|
|
1805
|
-
|
|
1806
1782
|
// Fire-and-forget: runAgentLoop's finally block recursively calls drainQueue
|
|
1807
1783
|
// when this run completes. Mirrors drainSingleMessage.
|
|
1808
1784
|
conversation
|
|
@@ -1810,9 +1786,6 @@ async function drainBatch(
|
|
|
1810
1786
|
...drainLoopOptions,
|
|
1811
1787
|
onEvent: fanOutOnEvent,
|
|
1812
1788
|
})
|
|
1813
|
-
.finally(() => {
|
|
1814
|
-
restoreSender?.();
|
|
1815
|
-
})
|
|
1816
1789
|
.catch((err) => {
|
|
1817
1790
|
const message = err instanceof Error ? err.message : String(err);
|
|
1818
1791
|
log.error(
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "../providers/connection-resolution.js";
|
|
28
28
|
import { RateLimitProvider } from "../providers/ratelimit.js";
|
|
29
29
|
import { listProviders } from "../providers/registry.js";
|
|
30
|
+
import { broadcastMessage } from "../runtime/assistant-event-hub.js";
|
|
30
31
|
import { getSubagentManager } from "../subagent/index.js";
|
|
31
32
|
import { getSandboxWorkingDir } from "../util/platform.js";
|
|
32
33
|
import { Conversation } from "./conversation.js";
|
|
@@ -156,7 +157,6 @@ export async function getOrCreateConversation(
|
|
|
156
157
|
options?: ConversationCreateOptions,
|
|
157
158
|
): Promise<Conversation> {
|
|
158
159
|
let conversation = findConversation(conversationId);
|
|
159
|
-
const sendToClient = () => {};
|
|
160
160
|
|
|
161
161
|
// `taskRunId` and `ephemeral` are per-call scopes, not durable conversation
|
|
162
162
|
// metadata, so they are stripped before the remaining options are merged
|
|
@@ -232,7 +232,9 @@ export async function getOrCreateConversation(
|
|
|
232
232
|
conversationId,
|
|
233
233
|
provider,
|
|
234
234
|
systemPrompt,
|
|
235
|
-
|
|
235
|
+
// Top-level conversations deliver to the SSE hub for their whole life,
|
|
236
|
+
// so every subscribed client sees every event with no per-turn wiring.
|
|
237
|
+
broadcastMessage,
|
|
236
238
|
workingDir,
|
|
237
239
|
{
|
|
238
240
|
maxTokens,
|
|
@@ -240,8 +242,6 @@ export async function getOrCreateConversation(
|
|
|
240
242
|
modelOverride: storedOptions?.modelOverride,
|
|
241
243
|
},
|
|
242
244
|
);
|
|
243
|
-
newConversation.updateClient(sendToClient, true);
|
|
244
|
-
|
|
245
245
|
// Ensure the conversations row exists before hydrating from DB.
|
|
246
246
|
// `getOrCreateConversation` builds the in-memory Conversation, but
|
|
247
247
|
// the persisted row is what `loadFromDb` reads for conversationType,
|
|
@@ -138,6 +138,16 @@ const ModelActionSchema = SurfaceActionSchema.extend({
|
|
|
138
138
|
|
|
139
139
|
const MAX_UNDO_DEPTH = 10;
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Whether a surface-action turn (a user clicked a button or submitted a form on
|
|
143
|
+
* a UI surface) runs with a human declared present. The handler does not yet
|
|
144
|
+
* learn the actor's interface, so it cannot declare presence the way the send
|
|
145
|
+
* route does; the turn runs non-interactive, which is what the state-derived
|
|
146
|
+
* fallback resolved to between turns. Deriving it from the actor's interface
|
|
147
|
+
* is a policy change tracked separately.
|
|
148
|
+
*/
|
|
149
|
+
const SURFACE_ACTION_TURN_IS_INTERACTIVE = false;
|
|
150
|
+
|
|
141
151
|
/**
|
|
142
152
|
* Pending surface types that do not hold the one-interactive-surface-at-a-time
|
|
143
153
|
* lock. Each renders content the user reads (or settles on its own) rather
|
|
@@ -1372,7 +1382,7 @@ export function openChannelSetupPanel(
|
|
|
1372
1382
|
data: safeParseSurfaceData("channel_setup", data) ?? {},
|
|
1373
1383
|
});
|
|
1374
1384
|
|
|
1375
|
-
ctx.
|
|
1385
|
+
ctx.emit({
|
|
1376
1386
|
type: "open_panel",
|
|
1377
1387
|
panelType: "channel_setup",
|
|
1378
1388
|
data,
|
|
@@ -1510,7 +1520,7 @@ function pushUndoState(
|
|
|
1510
1520
|
export function handleSurfaceUndo(ctx: Conversation, surfaceId: string): void {
|
|
1511
1521
|
const stack = ctx.surfaceUndoStacks.get(surfaceId);
|
|
1512
1522
|
if (!stack || stack.length === 0) {
|
|
1513
|
-
ctx.
|
|
1523
|
+
ctx.emit({
|
|
1514
1524
|
type: "ui_surface_undo_result",
|
|
1515
1525
|
conversationId: ctx.conversationId,
|
|
1516
1526
|
surfaceId,
|
|
@@ -1523,7 +1533,7 @@ export function handleSurfaceUndo(ctx: Conversation, surfaceId: string): void {
|
|
|
1523
1533
|
const previousHtml = stack.pop()!;
|
|
1524
1534
|
const stored = ctx.surfaceState.get(surfaceId);
|
|
1525
1535
|
if (!stored || stored.surfaceType !== "dynamic_page") {
|
|
1526
|
-
ctx.
|
|
1536
|
+
ctx.emit({
|
|
1527
1537
|
type: "ui_surface_undo_result",
|
|
1528
1538
|
conversationId: ctx.conversationId,
|
|
1529
1539
|
surfaceId,
|
|
@@ -1557,7 +1567,7 @@ export function handleSurfaceUndo(ctx: Conversation, surfaceId: string): void {
|
|
|
1557
1567
|
html: previousHtml,
|
|
1558
1568
|
};
|
|
1559
1569
|
s.data = revertedData;
|
|
1560
|
-
ctx.
|
|
1570
|
+
ctx.emit({
|
|
1561
1571
|
type: "ui_surface_update",
|
|
1562
1572
|
conversationId: ctx.conversationId,
|
|
1563
1573
|
surfaceId: sid,
|
|
@@ -1594,7 +1604,7 @@ export function handleSurfaceUndo(ctx: Conversation, surfaceId: string): void {
|
|
|
1594
1604
|
html: previousHtml,
|
|
1595
1605
|
};
|
|
1596
1606
|
stored.data = revertedData;
|
|
1597
|
-
ctx.
|
|
1607
|
+
ctx.emit({
|
|
1598
1608
|
type: "ui_surface_update",
|
|
1599
1609
|
conversationId: ctx.conversationId,
|
|
1600
1610
|
surfaceId,
|
|
@@ -1602,7 +1612,7 @@ export function handleSurfaceUndo(ctx: Conversation, surfaceId: string): void {
|
|
|
1602
1612
|
});
|
|
1603
1613
|
}
|
|
1604
1614
|
|
|
1605
|
-
ctx.
|
|
1615
|
+
ctx.emit({
|
|
1606
1616
|
type: "ui_surface_undo_result",
|
|
1607
1617
|
conversationId: ctx.conversationId,
|
|
1608
1618
|
surfaceId,
|
|
@@ -2212,6 +2222,7 @@ export async function handleSurfaceAction(
|
|
|
2212
2222
|
activeSurfaceId: surfaceId,
|
|
2213
2223
|
displayContent,
|
|
2214
2224
|
sourceActorPrincipalId,
|
|
2225
|
+
isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
|
|
2215
2226
|
// Rides the metadata bag rather than a typed option: the queue
|
|
2216
2227
|
// round-trips `metadata` but not `PersistMessageOptions`.
|
|
2217
2228
|
metadata: { scripted: isSyntheticSurfaceActionContent(content) },
|
|
@@ -2274,6 +2285,7 @@ export async function handleSurfaceAction(
|
|
|
2274
2285
|
activeSurfaceId: surfaceId,
|
|
2275
2286
|
displayContent,
|
|
2276
2287
|
sourceActorPrincipalId,
|
|
2288
|
+
isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
|
|
2277
2289
|
scripted: isSyntheticSurfaceActionContent(content),
|
|
2278
2290
|
})
|
|
2279
2291
|
.catch((err) => {
|
|
@@ -2460,6 +2472,7 @@ export async function handleSurfaceAction(
|
|
|
2460
2472
|
activeSurfaceId: surfaceId,
|
|
2461
2473
|
displayContent,
|
|
2462
2474
|
sourceActorPrincipalId,
|
|
2475
|
+
isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
|
|
2463
2476
|
// Rides the metadata bag rather than a typed option: the queue
|
|
2464
2477
|
// round-trips `metadata` but not `PersistMessageOptions`.
|
|
2465
2478
|
metadata: { scripted: isSyntheticSurfaceActionContent(content) },
|
|
@@ -2532,6 +2545,7 @@ export async function handleSurfaceAction(
|
|
|
2532
2545
|
activeSurfaceId: surfaceId,
|
|
2533
2546
|
displayContent,
|
|
2534
2547
|
sourceActorPrincipalId,
|
|
2548
|
+
isInteractive: SURFACE_ACTION_TURN_IS_INTERACTIVE,
|
|
2535
2549
|
scripted: isSyntheticSurfaceActionContent(content),
|
|
2536
2550
|
})
|
|
2537
2551
|
.catch((err) => {
|
|
@@ -2596,7 +2610,7 @@ export function refreshSurfacesForApp(
|
|
|
2596
2610
|
}
|
|
2597
2611
|
|
|
2598
2612
|
// Push the update to the client
|
|
2599
|
-
ctx.
|
|
2613
|
+
ctx.emit({
|
|
2600
2614
|
type: "ui_surface_update",
|
|
2601
2615
|
conversationId: ctx.conversationId,
|
|
2602
2616
|
surfaceId,
|
|
@@ -3433,7 +3447,7 @@ export async function surfaceProxyResolver(
|
|
|
3433
3447
|
"Sending ui_surface_show to client",
|
|
3434
3448
|
);
|
|
3435
3449
|
|
|
3436
|
-
ctx.
|
|
3450
|
+
ctx.emit({
|
|
3437
3451
|
type: "ui_surface_show",
|
|
3438
3452
|
conversationId: ctx.conversationId,
|
|
3439
3453
|
surfaceId,
|
|
@@ -3552,7 +3566,7 @@ export async function surfaceProxyResolver(
|
|
|
3552
3566
|
mergedData = patch;
|
|
3553
3567
|
}
|
|
3554
3568
|
|
|
3555
|
-
ctx.
|
|
3569
|
+
ctx.emit({
|
|
3556
3570
|
type: "ui_surface_update",
|
|
3557
3571
|
conversationId: ctx.conversationId,
|
|
3558
3572
|
surfaceId,
|
|
@@ -3610,7 +3624,7 @@ export async function surfaceProxyResolver(
|
|
|
3610
3624
|
isError: true,
|
|
3611
3625
|
};
|
|
3612
3626
|
}
|
|
3613
|
-
ctx.
|
|
3627
|
+
ctx.emit({
|
|
3614
3628
|
type: "ui_surface_complete",
|
|
3615
3629
|
conversationId: ctx.conversationId,
|
|
3616
3630
|
surfaceId,
|
|
@@ -3618,7 +3632,7 @@ export async function surfaceProxyResolver(
|
|
|
3618
3632
|
submittedData: lastAction.data,
|
|
3619
3633
|
});
|
|
3620
3634
|
} else {
|
|
3621
|
-
ctx.
|
|
3635
|
+
ctx.emit({
|
|
3622
3636
|
type: "ui_surface_dismiss",
|
|
3623
3637
|
conversationId: ctx.conversationId,
|
|
3624
3638
|
surfaceId,
|
|
@@ -3720,7 +3734,7 @@ export async function surfaceProxyResolver(
|
|
|
3720
3734
|
// Inline-only preview card emitted during app_create — do not open a
|
|
3721
3735
|
// workspace panel and do not register surface state. The client renders
|
|
3722
3736
|
// this as a tappable inline card that opens the app on demand.
|
|
3723
|
-
ctx.
|
|
3737
|
+
ctx.emit({
|
|
3724
3738
|
type: "ui_surface_show",
|
|
3725
3739
|
conversationId: ctx.conversationId,
|
|
3726
3740
|
surfaceId,
|
|
@@ -3750,7 +3764,7 @@ export async function surfaceProxyResolver(
|
|
|
3750
3764
|
title: app.name,
|
|
3751
3765
|
});
|
|
3752
3766
|
|
|
3753
|
-
ctx.
|
|
3767
|
+
ctx.emit({
|
|
3754
3768
|
type: "ui_surface_show",
|
|
3755
3769
|
conversationId: ctx.conversationId,
|
|
3756
3770
|
surfaceId,
|
|
@@ -245,9 +245,7 @@ export function createToolExecutor(
|
|
|
245
245
|
toolUseId?: string,
|
|
246
246
|
) => Promise<ToolExecutionResult> {
|
|
247
247
|
// Register the conversation's sendToClient for browser screencast surface messages
|
|
248
|
-
registerConversationSender(ctx.conversationId, (msg) =>
|
|
249
|
-
ctx.sendToClient(msg),
|
|
250
|
-
);
|
|
248
|
+
registerConversationSender(ctx.conversationId, (msg) => ctx.emit(msg));
|
|
251
249
|
|
|
252
250
|
// Execution-layer allowlist gate (`subagentToolGateMode === "execution"`,
|
|
253
251
|
// see {@link SubagentToolGateMode}): rejects non-allowlisted calls BEFORE
|
|
@@ -440,7 +438,7 @@ export function createToolExecutor(
|
|
|
440
438
|
sendToClient: (msg) => {
|
|
441
439
|
// Tool context's sendToClient uses a loose { type: string; [key: string]: unknown }
|
|
442
440
|
// signature, but at runtime these are always AssistantEvent instances.
|
|
443
|
-
ctx.
|
|
441
|
+
ctx.emit(msg as AssistantEvent);
|
|
444
442
|
if (msg.type === "ui_surface_show") {
|
|
445
443
|
// The tool-context sendToClient signature is loose, so the show
|
|
446
444
|
// message's fields are untyped here; map them through the same
|
|
@@ -319,7 +319,21 @@ export class Conversation {
|
|
|
319
319
|
/** @internal */ prompter: PermissionPrompter;
|
|
320
320
|
/** @internal */ secretPrompter: SecretPrompter;
|
|
321
321
|
private executor: ToolExecutor;
|
|
322
|
-
/**
|
|
322
|
+
/**
|
|
323
|
+
* The conversation's event sink, fixed for its whole life. Top-level
|
|
324
|
+
* conversations deliver to the SSE hub, so every subscribed client sees
|
|
325
|
+
* every event without any per-turn wiring; a subagent's sink re-envelopes
|
|
326
|
+
* its events under the parent conversation. Reached only through
|
|
327
|
+
* {@link emit}, which also notifies {@link addEventObserver} observers.
|
|
328
|
+
*/
|
|
329
|
+
private readonly sendToClient: (msg: AssistantEvent) => void;
|
|
330
|
+
/**
|
|
331
|
+
* Observers notified after every {@link emit}, in registration order. An
|
|
332
|
+
* observer sees the event after the sink delivered it, so anything it does
|
|
333
|
+
* in response (e.g. voice auto-resolving a confirmation) lands on the wire
|
|
334
|
+
* after the event itself.
|
|
335
|
+
*/
|
|
336
|
+
private readonly eventObservers = new Set<(msg: AssistantEvent) => void>();
|
|
323
337
|
/** @internal */ workingDir: string;
|
|
324
338
|
/** @internal */ allowedToolNames?: Set<string>;
|
|
325
339
|
/**
|
|
@@ -435,7 +449,18 @@ export class Conversation {
|
|
|
435
449
|
* @internal
|
|
436
450
|
*/
|
|
437
451
|
currentCallSite?: LLMCallSite;
|
|
438
|
-
/**
|
|
452
|
+
/**
|
|
453
|
+
* Whether no human is present to see UI or answer prompts. Derived from the
|
|
454
|
+
* in-flight turn's interactivity ({@link currentTurnIsNonInteractive}); a
|
|
455
|
+
* conversation with no turn in flight has no client. Presence is a property
|
|
456
|
+
* of the turn, never of where events are delivered, so there is no setter:
|
|
457
|
+
* dispatch paths declare interactivity per turn (`isInteractive` on
|
|
458
|
+
* `runAgentLoop`, or a wake's pin), and this reads it.
|
|
459
|
+
* @internal
|
|
460
|
+
*/
|
|
461
|
+
get hasNoClient(): boolean {
|
|
462
|
+
return this.currentTurnIsNonInteractive ?? true;
|
|
463
|
+
}
|
|
439
464
|
/**
|
|
440
465
|
* For subagent conversations, the id of the parent that spawned this one; set
|
|
441
466
|
* once at construction and never reassigned. `undefined` for top-level
|
|
@@ -757,10 +782,10 @@ export class Conversation {
|
|
|
757
782
|
this.workingDir = workingDir;
|
|
758
783
|
this.sendToClient = sendToClient;
|
|
759
784
|
this.graphMemory = new ConversationGraphMemory(conversationId);
|
|
760
|
-
|
|
785
|
+
// The prompter emits through the conversation so its confirmation_request
|
|
786
|
+
// reaches the sink and every observer (voice policy) like any other event.
|
|
787
|
+
this.prompter = new PermissionPrompter((msg) => this.emit(msg));
|
|
761
788
|
this.prompter.setOnStateChanged((requestId, state, source, toolUseId) => {
|
|
762
|
-
// Route through emitConfirmationStateChanged so the event reaches
|
|
763
|
-
// the client via sendToClient (wired to the SSE hub for HTTP conversations).
|
|
764
789
|
this.emitConfirmationStateChanged({
|
|
765
790
|
conversationId: this.conversationId,
|
|
766
791
|
requestId,
|
|
@@ -1489,31 +1514,55 @@ export class Conversation {
|
|
|
1489
1514
|
await this.loadFromDb();
|
|
1490
1515
|
}
|
|
1491
1516
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1517
|
+
/**
|
|
1518
|
+
* Deliver an event through the conversation's sink, then to every observer.
|
|
1519
|
+
* The single emission point for conversation-level events (activity state,
|
|
1520
|
+
* confirmation prompts and state, notifier output, out-of-turn pushes); the
|
|
1521
|
+
* agent loop's own stream rides its per-turn `onEvent`, which defaults to
|
|
1522
|
+
* this when the caller passes none.
|
|
1523
|
+
*/
|
|
1524
|
+
readonly emit = (msg: AssistantEvent): void => {
|
|
1525
|
+
try {
|
|
1526
|
+
this.sendToClient(msg);
|
|
1527
|
+
} catch (err) {
|
|
1528
|
+
log.warn(
|
|
1529
|
+
{ err, conversationId: this.conversationId, type: msg.type },
|
|
1530
|
+
"conversation sink threw",
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
for (const observer of this.eventObservers) {
|
|
1503
1534
|
try {
|
|
1504
|
-
|
|
1535
|
+
observer(msg);
|
|
1505
1536
|
} catch (err) {
|
|
1506
1537
|
log.warn(
|
|
1507
|
-
{ err, conversationId: this.conversationId },
|
|
1508
|
-
"
|
|
1538
|
+
{ err, conversationId: this.conversationId, type: msg.type },
|
|
1539
|
+
"conversation event observer threw",
|
|
1509
1540
|
);
|
|
1510
1541
|
}
|
|
1511
1542
|
}
|
|
1543
|
+
};
|
|
1544
|
+
|
|
1545
|
+
/**
|
|
1546
|
+
* Observe every event this conversation emits, after the sink delivered it.
|
|
1547
|
+
* For policy layered on delivery (voice auto-resolves approval prompts it
|
|
1548
|
+
* has no UI for), not for delivery itself. Returns the disposer.
|
|
1549
|
+
*/
|
|
1550
|
+
addEventObserver(observer: (msg: AssistantEvent) => void): () => void {
|
|
1551
|
+
this.eventObservers.add(observer);
|
|
1552
|
+
return () => {
|
|
1553
|
+
this.eventObservers.delete(observer);
|
|
1554
|
+
};
|
|
1512
1555
|
}
|
|
1513
1556
|
|
|
1514
|
-
/**
|
|
1515
|
-
|
|
1516
|
-
|
|
1557
|
+
/**
|
|
1558
|
+
* Re-emit the last activity state so a client that reconnected mid-phase
|
|
1559
|
+
* sees the current phase instead of the last one it received before
|
|
1560
|
+
* disconnecting. The send route calls this on every interactive send.
|
|
1561
|
+
*/
|
|
1562
|
+
replayActivityState(): void {
|
|
1563
|
+
if (this.lastActivityStateMsg) {
|
|
1564
|
+
this.emit(this.lastActivityStateMsg);
|
|
1565
|
+
}
|
|
1517
1566
|
}
|
|
1518
1567
|
|
|
1519
1568
|
setSubagentAllowedTools(tools: Set<string> | undefined): void {
|
|
@@ -1801,7 +1850,7 @@ export class Conversation {
|
|
|
1801
1850
|
} {
|
|
1802
1851
|
return enqueueMessageImpl(this, {
|
|
1803
1852
|
...options,
|
|
1804
|
-
onEvent: options.onEvent ?? this.
|
|
1853
|
+
onEvent: options.onEvent ?? this.emit,
|
|
1805
1854
|
});
|
|
1806
1855
|
}
|
|
1807
1856
|
|
|
@@ -1976,14 +2025,7 @@ export class Conversation {
|
|
|
1976
2025
|
type: "confirmation_state_changed",
|
|
1977
2026
|
...params,
|
|
1978
2027
|
} as AssistantEvent;
|
|
1979
|
-
|
|
1980
|
-
this.sendToClient(msg);
|
|
1981
|
-
} catch (err) {
|
|
1982
|
-
log.warn(
|
|
1983
|
-
{ err, conversationId: this.conversationId },
|
|
1984
|
-
"sendToClient threw in emitConfirmationStateChanged",
|
|
1985
|
-
);
|
|
1986
|
-
}
|
|
2028
|
+
this.emit(msg);
|
|
1987
2029
|
}
|
|
1988
2030
|
|
|
1989
2031
|
emitActivityState(
|
|
@@ -2008,14 +2050,7 @@ export class Conversation {
|
|
|
2008
2050
|
...(statusText ? { statusText } : {}),
|
|
2009
2051
|
} as AssistantEvent;
|
|
2010
2052
|
this.lastActivityStateMsg = msg;
|
|
2011
|
-
|
|
2012
|
-
this.sendToClient(msg);
|
|
2013
|
-
} catch (err) {
|
|
2014
|
-
log.warn(
|
|
2015
|
-
{ err, conversationId: this.conversationId },
|
|
2016
|
-
"sendToClient threw in emitActivityState",
|
|
2017
|
-
);
|
|
2018
|
-
}
|
|
2053
|
+
this.emit(msg);
|
|
2019
2054
|
}
|
|
2020
2055
|
|
|
2021
2056
|
/**
|
|
@@ -2069,7 +2104,7 @@ export class Conversation {
|
|
|
2069
2104
|
onEvent?: (msg: AssistantEvent) => void,
|
|
2070
2105
|
): void {
|
|
2071
2106
|
try {
|
|
2072
|
-
(onEvent ?? this.
|
|
2107
|
+
(onEvent ?? this.emit)({
|
|
2073
2108
|
type: "context_window_usage",
|
|
2074
2109
|
conversationId: this.conversationId,
|
|
2075
2110
|
tokens,
|
|
@@ -2421,11 +2456,11 @@ export class Conversation {
|
|
|
2421
2456
|
) {
|
|
2422
2457
|
await this.agentLoop.compactionCircuit.recordOutcome(
|
|
2423
2458
|
result.summaryFailed,
|
|
2424
|
-
this.
|
|
2459
|
+
this.emit,
|
|
2425
2460
|
);
|
|
2426
2461
|
}
|
|
2427
2462
|
if (result.compacted) {
|
|
2428
|
-
await applyCompactionResult(this, result, this.
|
|
2463
|
+
await applyCompactionResult(this, result, this.emit, null, {
|
|
2429
2464
|
slackContextCompactionWatermarkTs:
|
|
2430
2465
|
fixedBoundarySlackWatermarkTs ??
|
|
2431
2466
|
getSlackCompactionWatermarkForPrefix(
|
|
@@ -2681,6 +2716,8 @@ export class Conversation {
|
|
|
2681
2716
|
titleText?: string;
|
|
2682
2717
|
/** See {@link runAgentLoopImpl} — hidden machine-signal turn marker. */
|
|
2683
2718
|
isHiddenPrompt?: boolean;
|
|
2719
|
+
/** See {@link runAgentLoopImpl}: triggering row's daemon-authored kind. */
|
|
2720
|
+
messageKind?: string;
|
|
2684
2721
|
/**
|
|
2685
2722
|
* See {@link runAgentLoopImpl}: the row the end-of-turn reply
|
|
2686
2723
|
* notification treats as the prompt this turn answers.
|
|
@@ -2722,7 +2759,7 @@ export class Conversation {
|
|
|
2722
2759
|
this,
|
|
2723
2760
|
content,
|
|
2724
2761
|
userMessageId,
|
|
2725
|
-
onEvent ?? this.
|
|
2762
|
+
onEvent ?? this.emit,
|
|
2726
2763
|
rest,
|
|
2727
2764
|
);
|
|
2728
2765
|
}
|
|
@@ -2748,7 +2785,7 @@ export class Conversation {
|
|
|
2748
2785
|
this.cacheWarmAbort = undefined;
|
|
2749
2786
|
return processMessageImpl(this, {
|
|
2750
2787
|
...options,
|
|
2751
|
-
onEvent: options.onEvent ?? this.
|
|
2788
|
+
onEvent: options.onEvent ?? this.emit,
|
|
2752
2789
|
});
|
|
2753
2790
|
}
|
|
2754
2791
|
|
|
@@ -130,7 +130,7 @@ function pushStepsUpdate(
|
|
|
130
130
|
};
|
|
131
131
|
const updatedData = { ...card, templateData: updatedTemplateData };
|
|
132
132
|
stored.data = updatedData;
|
|
133
|
-
ctx.
|
|
133
|
+
ctx.emit({
|
|
134
134
|
type: "ui_surface_update",
|
|
135
135
|
conversationId: ctx.conversationId,
|
|
136
136
|
surfaceId: SURFACE_ID,
|
|
@@ -218,7 +218,7 @@ export function updateDoordashProgress(
|
|
|
218
218
|
},
|
|
219
219
|
} satisfies CardSurfaceData;
|
|
220
220
|
ctx.surfaceState.set(SURFACE_ID, { surfaceType: "card", data });
|
|
221
|
-
ctx.
|
|
221
|
+
ctx.emit({
|
|
222
222
|
type: "ui_surface_show",
|
|
223
223
|
conversationId: ctx.conversationId,
|
|
224
224
|
surfaceId: SURFACE_ID,
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { reconcileCallsOnStartup } from "../calls/call-recovery.js";
|
|
|
4
4
|
import { TwilioVoiceProvider } from "../calls/twilio-provider.js";
|
|
5
5
|
import { expireInteractionBoundGuardianRequests } from "../channels/gateway-guardian-requests.js";
|
|
6
6
|
import { initFeatureFlagOverrides } from "../config/assistant-feature-flags.js";
|
|
7
|
+
import { getBalancedModelExperimentArm } from "../config/balanced-model-experiment.js";
|
|
7
8
|
import { setIngressPublicBaseUrl, validateEnv } from "../config/env.js";
|
|
8
9
|
import {
|
|
9
10
|
hasPendingDefaultWorkspaceConfig,
|
|
@@ -224,9 +225,21 @@ export async function runDaemon(): Promise<void> {
|
|
|
224
225
|
// a failed fetch leaves the cache unset and resolves `os-beta` to its
|
|
225
226
|
// registry default `false`, which would remove the user's profile and reset
|
|
226
227
|
// their selection.
|
|
228
|
+
// A balanced-model experiment arm arriving in this same load gets the same
|
|
229
|
+
// invalidation. HTTP binds before this resolves, so a client that fetched
|
|
230
|
+
// profiles in that window holds the shipped model; the arm moves nothing on
|
|
231
|
+
// disk, so the reconcile above would not report a change and the listener's
|
|
232
|
+
// own comparison sees the arm on both sides of its refresh.
|
|
233
|
+
const balancedArmBeforeInit = getBalancedModelExperimentArm();
|
|
227
234
|
void initFeatureFlagOverrides()
|
|
228
235
|
.then((loaded) => {
|
|
229
|
-
if (loaded
|
|
236
|
+
if (!loaded) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const profilesChanged = reconcileFlagGatedProfiles();
|
|
240
|
+
const balancedArmChanged =
|
|
241
|
+
getBalancedModelExperimentArm() !== balancedArmBeforeInit;
|
|
242
|
+
if (profilesChanged || balancedArmChanged) {
|
|
230
243
|
publishConfigChanged();
|
|
231
244
|
}
|
|
232
245
|
})
|
|
@@ -69,7 +69,6 @@ import {
|
|
|
69
69
|
preactivateHostProxySkills,
|
|
70
70
|
shouldAttachHostProxyForCapability,
|
|
71
71
|
} from "./host-proxy-preactivation.js";
|
|
72
|
-
import { bindInteractiveTurnSender } from "./interactive-turn-sender.js";
|
|
73
72
|
import type { SubagentToolGateMode } from "./tool-setup-types.js";
|
|
74
73
|
import { restingTrust } from "./trust-context-types.js";
|
|
75
74
|
|
|
@@ -709,11 +708,6 @@ export async function processMessage(
|
|
|
709
708
|
};
|
|
710
709
|
}
|
|
711
710
|
|
|
712
|
-
const restoreSender =
|
|
713
|
-
options?.isInteractive === true
|
|
714
|
-
? bindInteractiveTurnSender(conversation)
|
|
715
|
-
: undefined;
|
|
716
|
-
|
|
717
711
|
const restoreToolScope = applyTurnToolAllowlist(conversation, options);
|
|
718
712
|
try {
|
|
719
713
|
await conversation.runAgentLoop(resolvedContent, messageId, {
|
|
@@ -731,7 +725,6 @@ export async function processMessage(
|
|
|
731
725
|
});
|
|
732
726
|
} finally {
|
|
733
727
|
restoreToolScope();
|
|
734
|
-
restoreSender?.();
|
|
735
728
|
}
|
|
736
729
|
|
|
737
730
|
// Read the just-finished turn's outcome from the stamp `runAgentLoop`'s
|
|
@@ -790,11 +783,6 @@ export async function processMessageInBackground(
|
|
|
790
783
|
return { messageId };
|
|
791
784
|
}
|
|
792
785
|
|
|
793
|
-
const restoreSender =
|
|
794
|
-
options?.isInteractive === true
|
|
795
|
-
? bindInteractiveTurnSender(conversation)
|
|
796
|
-
: undefined;
|
|
797
|
-
|
|
798
786
|
const restoreToolScope = applyTurnToolAllowlist(conversation, options);
|
|
799
787
|
conversation
|
|
800
788
|
.runAgentLoop(content, messageId, {
|
|
@@ -809,7 +797,6 @@ export async function processMessageInBackground(
|
|
|
809
797
|
})
|
|
810
798
|
.finally(() => {
|
|
811
799
|
restoreToolScope();
|
|
812
|
-
restoreSender?.();
|
|
813
800
|
})
|
|
814
801
|
.catch((err) => {
|
|
815
802
|
log.error({ err, conversationId }, "Background agent loop failed");
|