@borgee/agents-host 0.2.101 → 0.2.110
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/README.md +77 -5
- package/dist/agents-host.d.ts +8 -0
- package/dist/agents-host.js +355 -23
- package/dist/catalog-worker.js +21 -0
- package/dist/catalog-worker.js.map +7 -0
- package/dist/chat/chat-control-plane.d.ts +7 -2
- package/dist/chat/normalized-input.d.ts +9 -0
- package/dist/chat/normalized-input.js +24 -0
- package/dist/chat/sdk-chat-control-plane.d.ts +18 -3
- package/dist/chat/sdk-chat-control-plane.js +44 -9
- package/dist/cli-args.d.ts +1 -1
- package/dist/cli-args.js +13 -4
- package/dist/config.d.ts +3 -1
- package/dist/config.js +25 -0
- package/dist/context/injection.d.ts +16 -0
- package/dist/context/injection.js +37 -21
- package/dist/context/prompt.d.ts +12 -0
- package/dist/context/prompt.js +25 -0
- package/dist/context/turn-preparation.d.ts +2 -1
- package/dist/context/turn-preparation.js +15 -0
- package/dist/gateway/localhost-gateway.js +33 -8
- package/dist/hosted-turn-content.js +3 -2
- package/dist/local-config.js +34 -1
- package/dist/managed-daemon.js +15 -0
- package/dist/native-environment.d.ts +2 -0
- package/dist/native-environment.js +9 -0
- package/dist/native-protocol-types/codec.d.ts +49 -0
- package/dist/native-protocol-types/commands.d.ts +71 -0
- package/dist/native-protocol-types/compatibility.d.ts +5 -0
- package/dist/native-protocol-types/cursor.d.ts +7 -0
- package/dist/native-protocol-types/envelope.d.ts +1105 -0
- package/dist/native-protocol-types/file-changes.d.ts +20 -0
- package/dist/native-protocol-types/history.d.ts +487 -0
- package/dist/native-protocol-types/index.d.ts +18 -0
- package/dist/native-protocol-types/interactions.d.ts +619 -0
- package/dist/native-protocol-types/messages.d.ts +2482 -0
- package/dist/native-protocol-types/public-validation.d.ts +10 -0
- package/dist/native-protocol-types/remote-host-uplink.d.ts +67 -0
- package/dist/native-protocol-types/resources.d.ts +126 -0
- package/dist/native-protocol-types/session-settings.d.ts +22 -0
- package/dist/native-protocol-types/snapshot.d.ts +575 -0
- package/dist/native-protocol-types/timeline.d.ts +1503 -0
- package/dist/native-protocol-types/tool-result.d.ts +26 -0
- package/dist/native-protocol-types/uplink.d.ts +56 -0
- package/dist/native-protocol-types/version.d.ts +5 -0
- package/dist/native-provider-types/commands.d.ts +51 -0
- package/dist/native-provider-types/control.d.ts +192 -0
- package/dist/native-provider-types/file-changes.d.ts +9 -0
- package/dist/native-provider-types/index.d.ts +8 -0
- package/dist/native-provider-types/interactions.d.ts +7 -0
- package/dist/native-provider-types/observation.d.ts +209 -0
- package/dist/native-provider-types/provider.d.ts +124 -0
- package/dist/native-provider-types/session-settings.d.ts +17 -0
- package/dist/native-provider-types/testing.d.ts +27 -0
- package/dist/native-provider-types/tool-result.d.ts +21 -0
- package/dist/native-providers.d.ts +21 -0
- package/dist/native-providers.js +18402 -0
- package/dist/native-providers.js.map +7 -0
- package/dist/plugin-sdk.js +10640 -225
- package/dist/plugin-sdk.js.map +4 -4
- package/dist/policy/copilot-permission.js +1 -8
- package/dist/providers/copilot/sdk-session.js +8 -1
- package/dist/providers/create-provider.js +20 -0
- package/dist/providers/normalized/adapter.d.ts +107 -0
- package/dist/providers/normalized/adapter.js +1650 -0
- package/dist/providers/normalized/control-policy.d.ts +5 -0
- package/dist/providers/normalized/control-policy.js +12 -0
- package/dist/providers/normalized/interactions.d.ts +3 -0
- package/dist/providers/normalized/interactions.js +39 -0
- package/dist/providers/normalized/legacy-input-ownership.d.ts +34 -0
- package/dist/providers/normalized/legacy-input-ownership.js +123 -0
- package/dist/providers/normalized/session-management.d.ts +67 -0
- package/dist/providers/normalized/session-management.js +334 -0
- package/dist/providers/normalized/session-ownership.d.ts +3 -0
- package/dist/providers/normalized/session-ownership.js +90 -0
- package/dist/providers/provider-adapter.d.ts +43 -1
- package/dist/providers/provider-adapter.js +8 -0
- package/dist/types.d.ts +34 -9
- package/dist/vendor/agent-provider-codex/LICENSE +211 -0
- package/dist/vendor/agent-provider-codex/NOTICE +13 -0
- package/package.json +22 -13
- package/skills/borgee-agent/SKILL.md +1 -1
- package/skills/borgee-agent/scripts/borgee-agent.mjs +24 -3
- package/skills/borgee-agent/scripts/borgee-agent.py +28 -2
package/dist/agents-host.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readNormalizedInputText, readDurableInputText } from './chat/normalized-input.js';
|
|
1
2
|
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { chmod, link, mkdir, readFile, readdir, rename, unlink, writeFile } from 'node:fs/promises';
|
|
3
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -7,6 +8,8 @@ import { toReportedActivity } from './progress-to-activity.js';
|
|
|
7
8
|
import { BackgroundRunTracker } from './background-runs.js';
|
|
8
9
|
import { ExecutionDeliveryJournal, ExecutionTelemetryReporter, } from './execution-telemetry.js';
|
|
9
10
|
import { startTypingLease } from './typing-lease.js';
|
|
11
|
+
import { recordProtocolTrace, NormalizedActivityPublisher, NormalizedExecutionTelemetry, sessionControlResponse, parseSessionControlRequest } from './plugin-sdk.js';
|
|
12
|
+
import { respondToHostedInteraction } from './providers/normalized/interactions.js';
|
|
10
13
|
import { ATTENTION_FOLLOW_SEMANTICS_COMPATIBILITY_GATE, COLLABORATION_CAPABILITIES_DIAGNOSTICS_COMPATIBILITY_GATE, COLLABORATION_OUTCOME_MODEL_COMPATIBILITY_GATE, COLLABORATION_SKILL_FIRST_COMPATIBILITY_GATE, CONTEXT_INJECTION_COMPATIBILITY_GATE, LOCALHOST_GATEWAY_COMPATIBILITY_GATE, POLICY_AUDIT_ENFORCEMENT_COMPATIBILITY_GATE, resolveInternalPolicyMode, resolveInternalCompatibilityGates, SKILL_RUNTIME_COMPATIBILITY_GATE, TASK_THREAD_COLLABORATION_CONTRACT_COMPATIBILITY_GATE, TOKEN_BINDING_COMPATIBILITY_GATE, } from './compatibility-gates.js';
|
|
11
14
|
import { buildNormalizedAttentionSnapshot, parsePersistedAttentionSnapshot, } from './context/attention.js';
|
|
12
15
|
import { mergeCompactionSnapshot, parsePersistedCompactionSnapshot, } from './context/compaction.js';
|
|
@@ -15,7 +18,7 @@ import { createLocalhostGatewayController, LOCALHOST_GATEWAY_COLLABORATION_TARGE
|
|
|
15
18
|
import { extractTaskIdFromTaskAssignmentContent, resolveTaskAssignmentStatePath, } from './context/injection.js';
|
|
16
19
|
import { AuthorizationAuditSink, } from './policy/authorization-audit.js';
|
|
17
20
|
import { createProvider } from './providers/create-provider.js';
|
|
18
|
-
import { ProviderTurnCancelledError } from './providers/provider-adapter.js';
|
|
21
|
+
import { ProviderInputRejectedError, ProviderTurnCancelledError } from './providers/provider-adapter.js';
|
|
19
22
|
import { resolveAttentionStatePath, resolveCompactionStatePath, resolveExecutionDeliveryJournalPath, resolveExecutionTelemetryOutboxPath, resolveSharedProtocolKickoffDecisionPath, resolveSharedProtocolStatusPath, } from './state-paths.js';
|
|
20
23
|
import { appendVisibleMention as appendVisibleBodyMention, extractVisibleMentionIds as extractCanonicalMentionIds, } from './visible-mentions.js';
|
|
21
24
|
import { buildHostedIncomingContentText, buildHostedTurnContentParts, extractHostedMessageAttachments, normalizeHostedMessageAttachment, } from './hosted-turn-content.js';
|
|
@@ -118,6 +121,18 @@ class DefaultHostRuntime {
|
|
|
118
121
|
error: summarizeError(error),
|
|
119
122
|
});
|
|
120
123
|
},
|
|
124
|
+
providerOutputMode: () => this.provider.outputMode ?? 'legacy',
|
|
125
|
+
connectionLiveness: () => config.agent.provider === 'codex' && this.provider.outputMode === 'normalized'
|
|
126
|
+
? { probeIntervalMs: 30_000, pongTimeoutMs: 10_000, connectTimeoutMs: 30_000 }
|
|
127
|
+
: undefined,
|
|
128
|
+
normalizedActivitySync: () => this.provider.outputMode === 'normalized' && !!this.provider.syncNormalizedActivity,
|
|
129
|
+
sessionControl: () => this.provider.outputMode === 'normalized' && !!this.provider.controlSession,
|
|
130
|
+
sessionBindings: () => this.provider.outputMode === 'normalized' && !!this.provider.setSessionPublication,
|
|
131
|
+
sessionRelations: () => this.provider.outputMode === 'normalized' && !!this.provider.describeSession,
|
|
132
|
+
sessionManagement: () => this.provider.outputMode === 'normalized' && this.provider.supportsSessionManagement === true,
|
|
133
|
+
sessionDirectory: () => this.provider.outputMode === 'normalized' && !!this.provider.listSessions,
|
|
134
|
+
sessionObservation: () => this.provider.outputMode === 'normalized' && !!this.provider.observeSession,
|
|
135
|
+
sessionInputOperations: () => this.provider.outputMode === 'normalized' ? this.provider.sessionInputOperations ?? [] : [],
|
|
121
136
|
});
|
|
122
137
|
this.gateway = createLocalhostGatewayController({
|
|
123
138
|
gateEnabled: localhostGatewayGateEnabled,
|
|
@@ -141,6 +156,12 @@ class DefaultHostRuntime {
|
|
|
141
156
|
stateRootDir: config.stateRootDir,
|
|
142
157
|
agentApiKey: config.agent.agentApiKey,
|
|
143
158
|
resolveStableAgentId: deps.resolveStableAgentId,
|
|
159
|
+
providerOutputMode: config.providerOutputMode,
|
|
160
|
+
nativeProviderCommand: config.nativeProviderCommand,
|
|
161
|
+
sessionWorkspaceRoot: config.sessionWorkspaceRoot,
|
|
162
|
+
codexConnectionMode: config.codexConnectionMode,
|
|
163
|
+
codexSharedSocketPath: config.codexSharedSocketPath,
|
|
164
|
+
codexTrustShared: config.codexTrustShared,
|
|
144
165
|
claudeCommand: config.claudeCommand,
|
|
145
166
|
claudeArgs: config.claudeArgs,
|
|
146
167
|
codexCommand: config.codexCommand,
|
|
@@ -158,16 +179,19 @@ class DefaultHostRuntime {
|
|
|
158
179
|
});
|
|
159
180
|
this.ensureStateRoot = deps.ensureStateRoot ?? ensurePrivateStateRoot;
|
|
160
181
|
}
|
|
161
|
-
async start(onMessage, onStopTurn, onStopBackgroundRun, onActivityTransportReady) {
|
|
182
|
+
async start(onMessage, onStopTurn, onStopBackgroundRun, onActivityTransportReady, onSessionControl) {
|
|
162
183
|
await this.ensureStateRoot(this.config.stateRootDir);
|
|
163
184
|
await this.gateway.start();
|
|
164
185
|
try {
|
|
186
|
+
if (this.provider.outputMode === 'normalized')
|
|
187
|
+
this.controlPlane.onServerRequest?.((action, params, context) => action === 'session_control' && onSessionControl && context ? onSessionControl(parseSessionControlRequest(params), context) : respondToHostedInteraction(this.provider, action, params, context));
|
|
165
188
|
this.controlPlane.onStopTurn?.(onStopTurn);
|
|
166
189
|
this.controlPlane.onStopBackgroundRun?.(onStopBackgroundRun);
|
|
167
190
|
this.controlPlane.onActivityTransportReady?.(onActivityTransportReady);
|
|
168
191
|
await this.controlPlane.connect(onMessage);
|
|
169
192
|
}
|
|
170
193
|
catch (error) {
|
|
194
|
+
this.controlPlane.onServerRequest?.(undefined);
|
|
171
195
|
this.controlPlane.onStopTurn?.(undefined);
|
|
172
196
|
this.controlPlane.onStopBackgroundRun?.(undefined);
|
|
173
197
|
this.controlPlane.onActivityTransportReady?.(undefined);
|
|
@@ -178,6 +202,7 @@ class DefaultHostRuntime {
|
|
|
178
202
|
async stop() {
|
|
179
203
|
let thrown;
|
|
180
204
|
try {
|
|
205
|
+
this.controlPlane.onServerRequest?.(undefined);
|
|
181
206
|
this.controlPlane.onStopTurn?.(undefined);
|
|
182
207
|
this.controlPlane.onStopBackgroundRun?.(undefined);
|
|
183
208
|
this.controlPlane.onActivityTransportReady?.(undefined);
|
|
@@ -294,6 +319,8 @@ const MAX_AUTONOMOUS_REPLY_DEDUPLICATION_KEYS = 256;
|
|
|
294
319
|
*/
|
|
295
320
|
export class AgentsHost {
|
|
296
321
|
config;
|
|
322
|
+
executionTelemetry;
|
|
323
|
+
normalizedStateOwners = new Map();
|
|
297
324
|
runtime;
|
|
298
325
|
provider;
|
|
299
326
|
borgee;
|
|
@@ -408,6 +435,15 @@ export class AgentsHost {
|
|
|
408
435
|
try {
|
|
409
436
|
await this.executionDeliveryJournal.load();
|
|
410
437
|
this.provider.onAutonomousReply?.((reply) => this.dispatchAutonomousReply(reply));
|
|
438
|
+
this.provider.setSessionPublication?.({
|
|
439
|
+
supported: () => this.started && !this.controlPlaneClosed && this.borgee.sessionBindingsSupported === true,
|
|
440
|
+
publish: (channelId, activity) => {
|
|
441
|
+
if (!this.started || this.controlPlaneClosed || !this.borgee.sessionBindingsSupported || !this.borgee.reportActivity)
|
|
442
|
+
return false;
|
|
443
|
+
this.borgee.reportActivity({ channelId, activity });
|
|
444
|
+
return true;
|
|
445
|
+
},
|
|
446
|
+
});
|
|
411
447
|
await this.runtime.start((message) => {
|
|
412
448
|
if (!this.started) {
|
|
413
449
|
return;
|
|
@@ -417,8 +453,24 @@ export class AgentsHost {
|
|
|
417
453
|
return;
|
|
418
454
|
}
|
|
419
455
|
this.dispatchMessage(message);
|
|
420
|
-
}, async (channelId) => this.stopTurn(channelId), async (channelId, runId) => this.backgroundRuns.stop(channelId, runId), () => this.backgroundRuns.replay());
|
|
456
|
+
}, async (channelId) => this.stopTurn(channelId), async (channelId, runId) => this.backgroundRuns.stop(channelId, runId), () => { this.provider.publishSessionBindings?.(); this.backgroundRuns.replay(); }, (request, context) => this.handleSessionControl(request, context));
|
|
421
457
|
const agentId = await this.ensureSelfAgentId();
|
|
458
|
+
if (this.provider.outputMode === 'normalized' && this.borgee.reportExecutionTelemetryFrame && this.borgee.onExecutionTelemetryAck) {
|
|
459
|
+
try {
|
|
460
|
+
this.executionTelemetry = new NormalizedExecutionTelemetry({
|
|
461
|
+
outboxPath: join(this.config.stateRootDir, 'execution-telemetry.json'),
|
|
462
|
+
scope: { serverUrl: this.config.borgeeBaseUrl, agentId },
|
|
463
|
+
transport: {
|
|
464
|
+
report: frame => this.borgee.reportExecutionTelemetryFrame(frame),
|
|
465
|
+
onAck: handler => this.borgee.onExecutionTelemetryAck(handler),
|
|
466
|
+
onReady: handler => this.borgee.onExecutionTransportReady?.(handler) ?? (() => { }),
|
|
467
|
+
},
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
this.logger.error('normalized accounting unavailable', { error: summarizeError(error) });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
422
474
|
bufferingMessages = false;
|
|
423
475
|
while (bufferedMessages.length > 0) {
|
|
424
476
|
const pendingMessages = bufferedMessages.splice(0, bufferedMessages.length);
|
|
@@ -478,6 +530,9 @@ export class AgentsHost {
|
|
|
478
530
|
runtimeStopError = error;
|
|
479
531
|
}
|
|
480
532
|
await Promise.allSettled([...this.activeTurns]);
|
|
533
|
+
this.executionTelemetry?.dispose();
|
|
534
|
+
this.executionTelemetry = undefined;
|
|
535
|
+
this.normalizedStateOwners.clear();
|
|
481
536
|
await Promise.allSettled(pendingCompactionSnapshotWrites);
|
|
482
537
|
this.compactionSnapshotWriteQueueByChannel.clear();
|
|
483
538
|
if (runtimeStopError) {
|
|
@@ -497,6 +552,9 @@ export class AgentsHost {
|
|
|
497
552
|
});
|
|
498
553
|
}
|
|
499
554
|
dispatchMessage(message) {
|
|
555
|
+
// Self echoes must not occupy the channel queue before explicit control admission.
|
|
556
|
+
if (this.selfAgentId && String(message.user_id ?? message.sender_id ?? '') === this.selfAgentId && message.message_type !== 'task_assignment')
|
|
557
|
+
return;
|
|
500
558
|
const executionId = message.execution_grant?.executionId;
|
|
501
559
|
const existing = executionId
|
|
502
560
|
? this.executionDispatches.get(executionId)
|
|
@@ -505,9 +563,15 @@ export class AgentsHost {
|
|
|
505
563
|
this.trackActiveTurn(existing);
|
|
506
564
|
return;
|
|
507
565
|
}
|
|
508
|
-
const run = () =>
|
|
509
|
-
? this.
|
|
510
|
-
: this.
|
|
566
|
+
const run = () => message.sessionTarget
|
|
567
|
+
? this.handleSelectedSessionMessage(message)
|
|
568
|
+
: this.collaborationEnabled
|
|
569
|
+
? this.handleCollaborationMessage(message)
|
|
570
|
+
: this.enqueueChannelTurn(message.channel_id, () => this.handleLegacyMessage(message));
|
|
571
|
+
if (this.provider.outputMode === 'normalized') {
|
|
572
|
+
this.trackActiveTurn(run());
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
511
575
|
const work = executionId
|
|
512
576
|
? this.runClaimedExecution(message, run)
|
|
513
577
|
: this.runMessageWithExecutionTelemetry(message, run).then((result) => {
|
|
@@ -625,6 +689,17 @@ export class AgentsHost {
|
|
|
625
689
|
...usage,
|
|
626
690
|
}));
|
|
627
691
|
}
|
|
692
|
+
async handleSelectedSessionMessage(msg) {
|
|
693
|
+
if (!msg.sessionTarget || !msg.sourceCurrent?.())
|
|
694
|
+
return;
|
|
695
|
+
const normalized = await this.normalizeMessage(msg);
|
|
696
|
+
if (!normalized || !msg.sourceCurrent())
|
|
697
|
+
return;
|
|
698
|
+
await this.executeTurn(msg, normalized.authorId, normalized.content, {
|
|
699
|
+
incomingParts: normalized.incomingParts,
|
|
700
|
+
selectedSession: { ...msg.sessionTarget, sourceCurrent: msg.sourceCurrent },
|
|
701
|
+
});
|
|
702
|
+
}
|
|
628
703
|
dispatchAutonomousReply(reply) {
|
|
629
704
|
if (!this.started
|
|
630
705
|
|| this.controlPlaneClosed
|
|
@@ -2453,6 +2528,254 @@ export class AgentsHost {
|
|
|
2453
2528
|
: {}),
|
|
2454
2529
|
});
|
|
2455
2530
|
}
|
|
2531
|
+
async handleSessionControl(request, context) {
|
|
2532
|
+
const response = (status, reason) => sessionControlResponse(request, status, reason);
|
|
2533
|
+
if (!this.started || this.controlPlaneClosed || context.signal.aborted || Date.now() >= request.deadline_at)
|
|
2534
|
+
return response('unconfirmed', 'session_control_expired');
|
|
2535
|
+
if (this.provider.outputMode !== 'normalized' || !this.provider.controlSession)
|
|
2536
|
+
return response('unsupported', 'session_control_not_supported');
|
|
2537
|
+
if (request.operation.kind === 'send_input')
|
|
2538
|
+
return this.handleNativeInput(request, context);
|
|
2539
|
+
if (this.borgee.sessionBindingsSupported)
|
|
2540
|
+
return this.handleRetainedControl(request, context);
|
|
2541
|
+
if (request.operation.kind === 'list_pending_inputs') {
|
|
2542
|
+
if (!this.provider.supportsSessionInput || !context.isConnectionCurrent)
|
|
2543
|
+
return response('unsupported', 'native_queue_inventory_not_supported');
|
|
2544
|
+
const connected = () => this.started && !this.controlPlaneClosed && this.selfAgentId === request.agent_id && context.isConnectionCurrent();
|
|
2545
|
+
if (!connected())
|
|
2546
|
+
return response('unconfirmed', 'session_control_expired');
|
|
2547
|
+
try {
|
|
2548
|
+
return (await this.provider.controlSession(request, { signal: context.signal, isConnectionCurrent: connected })).response;
|
|
2549
|
+
}
|
|
2550
|
+
catch {
|
|
2551
|
+
return response('unconfirmed', 'native_queue_inventory_unavailable');
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
if (request.operation.kind === 'list_commands') {
|
|
2555
|
+
try {
|
|
2556
|
+
return (await this.provider.controlSession(request, { signal: context.signal })).response;
|
|
2557
|
+
}
|
|
2558
|
+
catch {
|
|
2559
|
+
return response('unconfirmed', 'command_directory_unavailable');
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
const channelId = request.channel_id;
|
|
2563
|
+
const state = this.ensureCollaborationChannelState(channelId);
|
|
2564
|
+
if (state.processor || state.running || state.activeTurn || state.queue.length || this.channelTurnQueues.has(channelId))
|
|
2565
|
+
return response('rejected', 'session_busy');
|
|
2566
|
+
let finish;
|
|
2567
|
+
const ownership = new Promise(resolve => { finish = resolve; });
|
|
2568
|
+
state.processor = ownership;
|
|
2569
|
+
state.running = true;
|
|
2570
|
+
this.channelTurnQueues.set(channelId, ownership);
|
|
2571
|
+
let execution;
|
|
2572
|
+
let active;
|
|
2573
|
+
let retained = false;
|
|
2574
|
+
const release = () => {
|
|
2575
|
+
execution?.close();
|
|
2576
|
+
if (state.activeTurn === active)
|
|
2577
|
+
state.activeTurn = undefined;
|
|
2578
|
+
state.running = false;
|
|
2579
|
+
if (state.processor === ownership)
|
|
2580
|
+
state.processor = undefined;
|
|
2581
|
+
if (this.channelTurnQueues.get(channelId) === ownership)
|
|
2582
|
+
this.channelTurnQueues.delete(channelId);
|
|
2583
|
+
finish();
|
|
2584
|
+
};
|
|
2585
|
+
this.trackActiveTurn(ownership);
|
|
2586
|
+
try {
|
|
2587
|
+
if (request.operation.kind === 'execute_command') {
|
|
2588
|
+
if (!request.admission)
|
|
2589
|
+
return response('rejected', 'command_admission_required');
|
|
2590
|
+
const admission = request.admission;
|
|
2591
|
+
active = { generation: ++state.generation, turnExecutionId: admission.input_message_id, superseded: false, collaborationMessagesSent: 0, targetCooldowns: new Map() };
|
|
2592
|
+
state.activeTurn = active;
|
|
2593
|
+
const inputText = await readDurableInputText(this.borgee, { channelId, inputMessageId: admission.input_message_id, createdAt: admission.input_created_at });
|
|
2594
|
+
if (context.signal.aborted || Date.now() >= request.deadline_at)
|
|
2595
|
+
return response('unconfirmed', 'session_control_expired');
|
|
2596
|
+
execution = this.beginNormalizedExecution({ channelId, taskId: admission.input_message_id, inputMessageId: admission.input_message_id, inputText, activeTurn: active });
|
|
2597
|
+
}
|
|
2598
|
+
const result = await this.provider.controlSession(request, {
|
|
2599
|
+
signal: context.signal, execution: execution?.options,
|
|
2600
|
+
onCompletion: pending => {
|
|
2601
|
+
retained = true;
|
|
2602
|
+
const owner = active;
|
|
2603
|
+
const completion = pending.then(async (reply) => {
|
|
2604
|
+
if (!reply || !hasVisibleText(reply.text) || !(await this.canAcceptCompletedTurnOutput(channelId, owner)))
|
|
2605
|
+
return;
|
|
2606
|
+
await this.postTurnReply({ channelId, body: reply.text, inputMessageId: request.admission?.input_message_id, replyToId: request.admission?.input_message_id, taskId: request.admission.input_message_id, activeTurn: owner });
|
|
2607
|
+
}).catch(error => { this.logger.error('native command completion unavailable', { channelId, error: summarizeError(error) }); }).finally(release);
|
|
2608
|
+
this.trackActiveTurn(completion);
|
|
2609
|
+
},
|
|
2610
|
+
});
|
|
2611
|
+
return result.response;
|
|
2612
|
+
}
|
|
2613
|
+
catch (error) {
|
|
2614
|
+
this.logger.error('native session control unavailable', { channelId, error: summarizeError(error) });
|
|
2615
|
+
return response('unconfirmed', 'native_confirmation_unavailable');
|
|
2616
|
+
}
|
|
2617
|
+
finally {
|
|
2618
|
+
if (!retained)
|
|
2619
|
+
release();
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
async handleRetainedControl(request, context) {
|
|
2623
|
+
const response = (status, reason) => sessionControlResponse(request, status, reason);
|
|
2624
|
+
const connected = () => this.started && !this.controlPlaneClosed && this.selfAgentId === request.agent_id && !!context.isConnectionCurrent?.();
|
|
2625
|
+
let execution;
|
|
2626
|
+
let canPublish = () => false;
|
|
2627
|
+
let retained = false;
|
|
2628
|
+
try {
|
|
2629
|
+
const admission = request.admission;
|
|
2630
|
+
let inputText = null;
|
|
2631
|
+
if (request.operation.kind === 'execute_command') {
|
|
2632
|
+
if (!admission)
|
|
2633
|
+
return response('rejected', 'command_admission_required');
|
|
2634
|
+
inputText = await readDurableInputText(this.borgee, { channelId: request.channel_id, inputMessageId: admission.input_message_id, createdAt: admission.input_created_at });
|
|
2635
|
+
}
|
|
2636
|
+
if (!connected() || context.signal.aborted || Date.now() >= request.deadline_at)
|
|
2637
|
+
return response('unconfirmed', 'session_control_expired');
|
|
2638
|
+
const result = await this.provider.controlSession(request, {
|
|
2639
|
+
signal: context.signal, connectionSignal: context.connectionSignal, isConnectionCurrent: connected,
|
|
2640
|
+
activateExecution: nativeCurrent => {
|
|
2641
|
+
if (!admission)
|
|
2642
|
+
throw new Error('Native command has no admitted input.');
|
|
2643
|
+
canPublish = () => connected() && nativeCurrent();
|
|
2644
|
+
execution = this.beginNormalizedExecution({ channelId: request.channel_id, taskId: admission.input_message_id, inputMessageId: admission.input_message_id, inputText, publicationGuard: canPublish });
|
|
2645
|
+
return execution.options;
|
|
2646
|
+
},
|
|
2647
|
+
onCompletion: pending => {
|
|
2648
|
+
retained = true;
|
|
2649
|
+
const completion = pending.then(async (reply) => {
|
|
2650
|
+
if (!reply || !hasVisibleText(reply.text) || !canPublish())
|
|
2651
|
+
return;
|
|
2652
|
+
await this.postTurnReply({ channelId: request.channel_id, body: reply.text, inputMessageId: admission.input_message_id, replyToId: admission.input_message_id, taskId: admission.input_message_id });
|
|
2653
|
+
}).catch(error => this.logger.error('native command completion unavailable', { channelId: request.channel_id, error: summarizeError(error) })).finally(() => execution?.close());
|
|
2654
|
+
this.trackActiveTurn(completion);
|
|
2655
|
+
},
|
|
2656
|
+
});
|
|
2657
|
+
return result.response;
|
|
2658
|
+
}
|
|
2659
|
+
catch (error) {
|
|
2660
|
+
this.logger.error('native session control unavailable', { channelId: request.channel_id, error: summarizeError(error) });
|
|
2661
|
+
return response('unconfirmed', 'native_confirmation_unavailable');
|
|
2662
|
+
}
|
|
2663
|
+
finally {
|
|
2664
|
+
if (!retained)
|
|
2665
|
+
execution?.close();
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
async handleNativeInput(request, context) {
|
|
2669
|
+
const operation = request.operation;
|
|
2670
|
+
const admission = request.admission;
|
|
2671
|
+
const response = (status, reason) => sessionControlResponse(request, status, reason);
|
|
2672
|
+
if (operation.kind !== 'send_input' || !admission || !context.isConnectionCurrent || !this.provider.supportsSessionInput)
|
|
2673
|
+
return response('unsupported', 'native_input_not_supported');
|
|
2674
|
+
const connected = () => this.started && !this.controlPlaneClosed && this.selfAgentId === request.agent_id && context.isConnectionCurrent();
|
|
2675
|
+
let execution;
|
|
2676
|
+
let canPublish = () => false;
|
|
2677
|
+
let retained = false;
|
|
2678
|
+
try {
|
|
2679
|
+
const inputText = await readDurableInputText(this.borgee, { channelId: request.channel_id, inputMessageId: admission.input_message_id, createdAt: admission.input_created_at });
|
|
2680
|
+
if (inputText !== operation.text || !connected() || context.signal.aborted)
|
|
2681
|
+
return response('unconfirmed', 'native_input_admission_unavailable');
|
|
2682
|
+
const result = await this.provider.controlSession(request, {
|
|
2683
|
+
signal: context.signal, connectionSignal: context.connectionSignal, isConnectionCurrent: connected,
|
|
2684
|
+
activateExecution: async (nativeCurrent) => {
|
|
2685
|
+
canPublish = () => connected() && nativeCurrent();
|
|
2686
|
+
if (!canPublish())
|
|
2687
|
+
throw new Error('Native queued input connection ownership ended.');
|
|
2688
|
+
execution = this.beginNormalizedExecution({ channelId: request.channel_id, taskId: admission.input_message_id, inputMessageId: admission.input_message_id, inputText, publicationGuard: canPublish });
|
|
2689
|
+
return execution.options;
|
|
2690
|
+
},
|
|
2691
|
+
onCompletion: pending => {
|
|
2692
|
+
retained = true;
|
|
2693
|
+
const completion = pending.then(async (reply) => {
|
|
2694
|
+
if (!reply || !hasVisibleText(reply.text) || !canPublish())
|
|
2695
|
+
return;
|
|
2696
|
+
await this.postTurnReply({ channelId: request.channel_id, body: reply.text, inputMessageId: admission.input_message_id, replyToId: admission.input_message_id, taskId: admission.input_message_id });
|
|
2697
|
+
}).catch(error => this.logger.error('native input completion unavailable', { channelId: request.channel_id, error: summarizeError(error) })).finally(() => execution?.close());
|
|
2698
|
+
this.trackActiveTurn(completion);
|
|
2699
|
+
},
|
|
2700
|
+
});
|
|
2701
|
+
return result.response;
|
|
2702
|
+
}
|
|
2703
|
+
catch (error) {
|
|
2704
|
+
this.logger.error('native input confirmation unavailable', { channelId: request.channel_id, error: summarizeError(error) });
|
|
2705
|
+
return response('unconfirmed', 'native_confirmation_unavailable');
|
|
2706
|
+
}
|
|
2707
|
+
finally {
|
|
2708
|
+
if (!retained)
|
|
2709
|
+
execution?.close();
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
async postTurnReply(input, source) {
|
|
2713
|
+
const message = { channelId: input.channelId, body: input.body, replyToId: input.replyToId ?? input.activeTurn?.delivery?.replyToId };
|
|
2714
|
+
const posted = source ? await this.borgee.postMessage(message, source) : await this.borgee.postMessage(message);
|
|
2715
|
+
recordProtocolTrace({ stage: 'host.delivery', kind: 'correlation', correlation: { channelId: input.channelId, agentId: this.selfAgentId ?? undefined, inputMessageId: input.inputMessageId, taskId: input.taskId, turnExecutionId: input.activeTurn?.turnExecutionId ?? undefined, outputMessageId: posted.messageId }, payload: { delivery: 'posted' } });
|
|
2716
|
+
return posted;
|
|
2717
|
+
}
|
|
2718
|
+
beginNormalizedExecution(input) {
|
|
2719
|
+
const { channelId, taskId, activeTurn } = input;
|
|
2720
|
+
let execution;
|
|
2721
|
+
try {
|
|
2722
|
+
execution = this.executionTelemetry?.bind({ bindingId: taskId, channelId, inputMessageId: input.inputMessageId, grant: input.grant });
|
|
2723
|
+
}
|
|
2724
|
+
catch (error) {
|
|
2725
|
+
this.logger.error('normalized accounting binding unavailable', { error: summarizeError(error) });
|
|
2726
|
+
}
|
|
2727
|
+
let publisher;
|
|
2728
|
+
let statePublisher;
|
|
2729
|
+
let stateClosed = false;
|
|
2730
|
+
const owner = Symbol('normalized-state');
|
|
2731
|
+
const stateOwnerKey = input.publicationGuard ? JSON.stringify([channelId, taskId]) : channelId;
|
|
2732
|
+
this.normalizedStateOwners.set(stateOwnerKey, owner);
|
|
2733
|
+
const canPublishState = () => {
|
|
2734
|
+
const current = this.collaborationChannels.get(channelId)?.activeTurn;
|
|
2735
|
+
return !stateClosed && this.started && !this.controlPlaneClosed && this.normalizedStateOwners.get(stateOwnerKey) === owner && (input.publicationGuard ? input.publicationGuard() : !activeTurn?.superseded && (!current || current.generation === activeTurn?.generation));
|
|
2736
|
+
};
|
|
2737
|
+
return {
|
|
2738
|
+
options: {
|
|
2739
|
+
normalizedTaskId: taskId, normalizedInputMessageId: input.inputMessageId, normalizedInputText: input.inputText,
|
|
2740
|
+
normalizedStateSink: input.silent ? undefined : {
|
|
2741
|
+
snapshot: (snapshot, bindingId, timelineEpoch) => {
|
|
2742
|
+
if (!canPublishState())
|
|
2743
|
+
return false;
|
|
2744
|
+
statePublisher ??= new NormalizedActivityPublisher({ client: { reportActivity: value => { this.borgee.reportActivity?.(value); } }, channelId, taskId, agentId: snapshot.payload.id });
|
|
2745
|
+
statePublisher.publish(snapshot, Date.now(), snapshot.payload.providerId, snapshot.payload.capabilities, bindingId, timelineEpoch);
|
|
2746
|
+
return true;
|
|
2747
|
+
},
|
|
2748
|
+
sessionActivity: activity => { if (!canPublishState() || !this.borgee.reportActivity)
|
|
2749
|
+
return false; this.borgee.reportActivity({ channelId, activity }); return true; },
|
|
2750
|
+
observe: (observation, agentId, capabilities, bindingId, timelineEpoch) => {
|
|
2751
|
+
if (observation.event.type !== 'runtime_updated' || !canPublishState() || this.borgee.sessionBindingsSupported)
|
|
2752
|
+
return;
|
|
2753
|
+
statePublisher ??= new NormalizedActivityPublisher({ client: { reportActivity: value => { this.borgee.reportActivity?.(value); } }, channelId, taskId, agentId });
|
|
2754
|
+
statePublisher.observe(observation, capabilities, bindingId, timelineEpoch);
|
|
2755
|
+
},
|
|
2756
|
+
close: () => { stateClosed = true; statePublisher?.close(); if (this.normalizedStateOwners.get(stateOwnerKey) === owner)
|
|
2757
|
+
this.normalizedStateOwners.delete(stateOwnerKey); },
|
|
2758
|
+
},
|
|
2759
|
+
onNormalizedObservation: (event, agentId, observation, capabilities, bindingId, timelineEpoch, sessionPublished) => {
|
|
2760
|
+
if (input.publicationGuard && !input.publicationGuard())
|
|
2761
|
+
return;
|
|
2762
|
+
try {
|
|
2763
|
+
execution?.observe(event, observation?.occurredAt);
|
|
2764
|
+
}
|
|
2765
|
+
catch (error) {
|
|
2766
|
+
this.logger.error('normalized accounting rejected', { error: summarizeError(error) });
|
|
2767
|
+
}
|
|
2768
|
+
const acceptsOutput = !input.silent && this.canAcceptTurnOutput(channelId, activeTurn?.generation);
|
|
2769
|
+
recordProtocolTrace({ stage: 'host.dispatch', kind: 'correlation', correlation: { channelId, agentId, inputMessageId: input.inputMessageId, taskId, turnExecutionId: activeTurn?.turnExecutionId ?? undefined }, payload: { eventType: event.type }, outcome: acceptsOutput ? 'forwarded' : 'suppressed' });
|
|
2770
|
+
if (sessionPublished || !acceptsOutput || event.type === 'runtime_updated' && this.borgee.sessionBindingsSupported)
|
|
2771
|
+
return;
|
|
2772
|
+
publisher ??= new NormalizedActivityPublisher({ client: { reportActivity: value => { this.borgee.reportActivity?.(value); } }, channelId, taskId, agentId });
|
|
2773
|
+
publisher.observe(observation ?? event, capabilities, bindingId, timelineEpoch);
|
|
2774
|
+
},
|
|
2775
|
+
},
|
|
2776
|
+
close: () => { publisher?.close(); execution?.close(); },
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2456
2779
|
async executeTurn(msg, authorId, content, options) {
|
|
2457
2780
|
const channelId = msg.channel_id;
|
|
2458
2781
|
const activeTurn = options?.activeTurn;
|
|
@@ -2460,6 +2783,8 @@ export class AgentsHost {
|
|
|
2460
2783
|
const taskThreadContext = options?.taskThreadContext ?? { state: 'inactive' };
|
|
2461
2784
|
const silentTurn = options?.silent === true;
|
|
2462
2785
|
const deferDelivery = options?.deferDelivery === true;
|
|
2786
|
+
const selectedSourceCurrent = options?.selectedSession?.sourceCurrent;
|
|
2787
|
+
const selectedWriteSource = selectedSourceCurrent ? { isConnectionCurrent: selectedSourceCurrent } : undefined;
|
|
2463
2788
|
const collaborationTurnMode = activeTurn?.protocol
|
|
2464
2789
|
? 'protocol-managed'
|
|
2465
2790
|
: options?.kickoff
|
|
@@ -2478,7 +2803,7 @@ export class AgentsHost {
|
|
|
2478
2803
|
};
|
|
2479
2804
|
const turnStartedAt = Date.now();
|
|
2480
2805
|
this.logger.debug('starting turn', turnContext);
|
|
2481
|
-
const executionTelemetry = msg.execution_grant
|
|
2806
|
+
const executionTelemetry = this.provider.outputMode !== 'normalized' && msg.execution_grant
|
|
2482
2807
|
? this.executionTelemetryByExecutionId.get(msg.execution_grant.executionId)
|
|
2483
2808
|
: undefined;
|
|
2484
2809
|
let executionSucceeded = false;
|
|
@@ -2488,6 +2813,11 @@ export class AgentsHost {
|
|
|
2488
2813
|
let visibleReplyBody;
|
|
2489
2814
|
let activityReporter;
|
|
2490
2815
|
let typingLease;
|
|
2816
|
+
const normalizedTaskId = turnExecutionId ?? randomUUID();
|
|
2817
|
+
recordProtocolTrace({ stage: 'host.dispatch', kind: 'correlation',
|
|
2818
|
+
correlation: { channelId, agentId: this.selfAgentId ?? undefined, inputMessageId: msg.message_id, taskId: normalizedTaskId, turnExecutionId: turnExecutionId ?? undefined },
|
|
2819
|
+
payload: { silentTurn } });
|
|
2820
|
+
let normalizedExecution;
|
|
2491
2821
|
try {
|
|
2492
2822
|
if (!silentTurn) {
|
|
2493
2823
|
typingLease = startTypingLease(() => this.borgee.reportTyping(channelId));
|
|
@@ -2516,6 +2846,7 @@ export class AgentsHost {
|
|
|
2516
2846
|
activityReporter = silentTurn
|
|
2517
2847
|
? undefined
|
|
2518
2848
|
: this.beginTurnActivity(channelId, activeTurn?.generation);
|
|
2849
|
+
normalizedExecution = this.provider.outputMode === 'normalized' ? this.beginNormalizedExecution({ channelId, taskId: normalizedTaskId, inputMessageId: msg.message_id, inputText: await readNormalizedInputText(this.borgee, msg), grant: msg.execution_grant, activeTurn, silent: silentTurn, ...(selectedSourceCurrent ? { publicationGuard: selectedSourceCurrent } : {}) }) : undefined;
|
|
2519
2850
|
await this.ensureCompactionSnapshotLoaded(channelId);
|
|
2520
2851
|
const compactionSnapshot = this.compactionSnapshotByChannel.get(channelId);
|
|
2521
2852
|
if (executionTelemetry) {
|
|
@@ -2539,6 +2870,7 @@ export class AgentsHost {
|
|
|
2539
2870
|
incomingParts,
|
|
2540
2871
|
incomingEventKind: msg.type,
|
|
2541
2872
|
incomingMessageType: msg.message_type,
|
|
2873
|
+
...(options?.selectedSession ? { selectedSession: options.selectedSession } : {}),
|
|
2542
2874
|
collaboration: turnExecutionId || options?.kickoff
|
|
2543
2875
|
? {
|
|
2544
2876
|
enabled: this.collaborationEnabled,
|
|
@@ -2561,7 +2893,8 @@ export class AgentsHost {
|
|
|
2561
2893
|
? {
|
|
2562
2894
|
taskAssignmentContextOverride: {
|
|
2563
2895
|
active: true,
|
|
2564
|
-
...(taskThreadContext.state === 'active'
|
|
2896
|
+
...((taskThreadContext.state === 'active'
|
|
2897
|
+
|| taskThreadContext.state === 'recovered') && taskThreadContext.currentTaskId
|
|
2565
2898
|
? { currentTaskId: taskThreadContext.currentTaskId }
|
|
2566
2899
|
: {}),
|
|
2567
2900
|
},
|
|
@@ -2570,8 +2903,9 @@ export class AgentsHost {
|
|
|
2570
2903
|
: { taskAssignmentContextOverridePersistence: 'ephemeral' }),
|
|
2571
2904
|
}
|
|
2572
2905
|
: {}),
|
|
2573
|
-
}, observeProviderProgress || executionTelemetry
|
|
2906
|
+
}, observeProviderProgress || executionTelemetry || this.provider.outputMode === 'normalized'
|
|
2574
2907
|
? {
|
|
2908
|
+
...normalizedExecution?.options,
|
|
2575
2909
|
...(executionTelemetry
|
|
2576
2910
|
? {
|
|
2577
2911
|
onUsage: (usage) => {
|
|
@@ -2595,7 +2929,7 @@ export class AgentsHost {
|
|
|
2595
2929
|
return;
|
|
2596
2930
|
}
|
|
2597
2931
|
}
|
|
2598
|
-
if (!this.canAcceptTurnOutput(channelId, activeTurn?.generation)) {
|
|
2932
|
+
if ((selectedSourceCurrent && !selectedSourceCurrent()) || !this.canAcceptTurnOutput(channelId, activeTurn?.generation)) {
|
|
2599
2933
|
return;
|
|
2600
2934
|
}
|
|
2601
2935
|
if (update.type === 'text'
|
|
@@ -2610,7 +2944,7 @@ export class AgentsHost {
|
|
|
2610
2944
|
return;
|
|
2611
2945
|
}
|
|
2612
2946
|
const reportedActivity = toReportedActivity(update);
|
|
2613
|
-
if (reportsProviderActivity && reportedActivity) {
|
|
2947
|
+
if (this.provider.outputMode !== 'normalized' && reportsProviderActivity && reportedActivity) {
|
|
2614
2948
|
activityReporter?.progress(reportedActivity);
|
|
2615
2949
|
}
|
|
2616
2950
|
if (!supportsProviderProgress ||
|
|
@@ -2642,7 +2976,7 @@ export class AgentsHost {
|
|
|
2642
2976
|
observedAt: Date.now(),
|
|
2643
2977
|
turnExecutionId: activeTurn?.turnExecutionId ?? undefined,
|
|
2644
2978
|
});
|
|
2645
|
-
if (!(await this.canAcceptCompletedTurnOutput(channelId, activeTurn))) {
|
|
2979
|
+
if ((selectedSourceCurrent && !selectedSourceCurrent()) || !(await this.canAcceptCompletedTurnOutput(channelId, activeTurn))) {
|
|
2646
2980
|
if (activeTurn?.turnExecutionId) {
|
|
2647
2981
|
this.clearCollaborationDraft(channelId, {
|
|
2648
2982
|
generation: activeTurn.generation,
|
|
@@ -2694,11 +3028,7 @@ export class AgentsHost {
|
|
|
2694
3028
|
};
|
|
2695
3029
|
}
|
|
2696
3030
|
if (this.started && !this.controlPlaneClosed && hasVisibleText(publicReplyText)) {
|
|
2697
|
-
const posted = await this.
|
|
2698
|
-
channelId,
|
|
2699
|
-
body: visibleReplyBody,
|
|
2700
|
-
replyToId: activeTurn?.delivery?.replyToId,
|
|
2701
|
-
});
|
|
3031
|
+
const posted = await this.postTurnReply({ channelId, body: visibleReplyBody, inputMessageId: msg.message_id, taskId: normalizedTaskId, activeTurn }, selectedWriteSource);
|
|
2702
3032
|
this.logger.debug('completed turn', {
|
|
2703
3033
|
...turnContext,
|
|
2704
3034
|
durationMs: Date.now() - turnStartedAt,
|
|
@@ -2756,6 +3086,10 @@ export class AgentsHost {
|
|
|
2756
3086
|
if (executionTelemetryStartFailed) {
|
|
2757
3087
|
throw error;
|
|
2758
3088
|
}
|
|
3089
|
+
if (error instanceof ProviderInputRejectedError && !silentTurn && !deferDelivery && (!selectedSourceCurrent || selectedSourceCurrent()) && this.canAcceptTurnOutput(channelId, activeTurn?.generation)) {
|
|
3090
|
+
const posted = await this.postTurnReply({ channelId, body: error.publicReplyText, replyToId: activeTurn?.delivery?.replyToId, inputMessageId: msg.message_id, taskId: normalizedTaskId, activeTurn }, selectedWriteSource);
|
|
3091
|
+
return { reply: { text: error.publicReplyText }, publicReplyText: error.publicReplyText, visibleReplyBody: error.publicReplyText, deliveredMessageId: posted.messageId, deliveryState: 'posted', stale: false, completed: false };
|
|
3092
|
+
}
|
|
2759
3093
|
if (error instanceof ProviderTurnCancelledError) {
|
|
2760
3094
|
const cancelledReplyText = error.publicReplyText?.trim();
|
|
2761
3095
|
if (!silentTurn &&
|
|
@@ -2763,16 +3097,13 @@ export class AgentsHost {
|
|
|
2763
3097
|
typeof cancelledReplyText === 'string' &&
|
|
2764
3098
|
cancelledReplyText.length > 0 &&
|
|
2765
3099
|
this.started &&
|
|
2766
|
-
!this.controlPlaneClosed
|
|
3100
|
+
!this.controlPlaneClosed &&
|
|
3101
|
+
(!selectedSourceCurrent || selectedSourceCurrent())) {
|
|
2767
3102
|
reply = { text: cancelledReplyText };
|
|
2768
3103
|
publicReplyText = cancelledReplyText;
|
|
2769
3104
|
visibleReplyBody = this.resolveVisibleTurnBody(activeTurn, reply, publicReplyText);
|
|
2770
3105
|
try {
|
|
2771
|
-
const posted = await this.
|
|
2772
|
-
channelId,
|
|
2773
|
-
body: visibleReplyBody,
|
|
2774
|
-
replyToId: activeTurn?.delivery?.replyToId,
|
|
2775
|
-
});
|
|
3106
|
+
const posted = await this.postTurnReply({ channelId, body: visibleReplyBody, replyToId: activeTurn?.delivery?.replyToId, inputMessageId: msg.message_id, taskId: normalizedTaskId, activeTurn }, selectedWriteSource);
|
|
2776
3107
|
this.logger.debug('posted cancelled turn feedback', {
|
|
2777
3108
|
...turnContext,
|
|
2778
3109
|
durationMs: Date.now() - turnStartedAt,
|
|
@@ -2838,6 +3169,7 @@ export class AgentsHost {
|
|
|
2838
3169
|
}
|
|
2839
3170
|
typingLease?.stop();
|
|
2840
3171
|
activityReporter?.end();
|
|
3172
|
+
normalizedExecution?.close();
|
|
2841
3173
|
}
|
|
2842
3174
|
}
|
|
2843
3175
|
/**
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire as __nodeCreateRequire } from 'node:module';
|
|
2
|
+
const require = __nodeCreateRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// ../agent-provider-claude/src/catalog-worker.ts
|
|
5
|
+
import { getSessionInfo, getSessionMessages, listSessions, listSubagents, getSubagentMessages } from "@borgee/claude-native-sdk";
|
|
6
|
+
var [operation, sessionId, childId] = process.argv.slice(2);
|
|
7
|
+
try {
|
|
8
|
+
const result = operation === "list" ? await listSessions() : operation === "info" && sessionId ? await getSessionInfo(sessionId) : operation === "messages" && sessionId ? await getSessionMessages(sessionId) : operation === "child-messages" && sessionId && childId ? await getSubagentMessages(sessionId, childId) : operation === "children" && sessionId ? await readChildren(sessionId) : (() => {
|
|
9
|
+
throw new Error("Unknown catalog operation.");
|
|
10
|
+
})();
|
|
11
|
+
process.stdout.write(JSON.stringify(result ?? null));
|
|
12
|
+
} catch {
|
|
13
|
+
process.stderr.write("Claude native catalog could not be read.\n");
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
}
|
|
16
|
+
async function readChildren(parentId) {
|
|
17
|
+
const children = [];
|
|
18
|
+
for (const id of await listSubagents(parentId)) children.push({ id, messages: await getSubagentMessages(parentId, id) });
|
|
19
|
+
return children;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=catalog-worker.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../agent-provider-claude/src/catalog-worker.ts"],
|
|
4
|
+
"sourcesContent": ["import { getSessionInfo, getSessionMessages, listSessions, listSubagents, getSubagentMessages } from '@anthropic-ai/claude-agent-sdk';\n\nconst [operation, sessionId, childId] = process.argv.slice(2);\ntry {\n const result = operation === 'list' ? await listSessions() : operation === 'info' && sessionId ? await getSessionInfo(sessionId)\n : operation === 'messages' && sessionId ? await getSessionMessages(sessionId)\n : operation === 'child-messages' && sessionId && childId ? await getSubagentMessages(sessionId, childId)\n : operation === 'children' && sessionId ? await readChildren(sessionId)\n : (() => { throw new Error('Unknown catalog operation.'); })();\n process.stdout.write(JSON.stringify(result ?? null));\n} catch {\n process.stderr.write('Claude native catalog could not be read.\\n');\n process.exitCode = 1;\n}\n\nasync function readChildren(parentId: string) {\n const children = [];\n for (const id of await listSubagents(parentId)) children.push({ id, messages: await getSubagentMessages(parentId, id) });\n return children;\n}\n"],
|
|
5
|
+
"mappings": ";;;;AAAA,SAAS,gBAAgB,oBAAoB,cAAc,eAAe,2BAA2B;AAErG,IAAM,CAAC,WAAW,WAAW,OAAO,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC5D,IAAI;AACF,QAAM,SAAS,cAAc,SAAS,MAAM,aAAa,IAAI,cAAc,UAAU,YAAY,MAAM,eAAe,SAAS,IAC3H,cAAc,cAAc,YAAY,MAAM,mBAAmB,SAAS,IAC1E,cAAc,oBAAoB,aAAa,UAAU,MAAM,oBAAoB,WAAW,OAAO,IACrG,cAAc,cAAc,YAAY,MAAM,aAAa,SAAS,KACnE,MAAM;AAAE,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAAG,GAAG;AAC/D,UAAQ,OAAO,MAAM,KAAK,UAAU,UAAU,IAAI,CAAC;AACrD,QAAQ;AACN,UAAQ,OAAO,MAAM,4CAA4C;AACjE,UAAQ,WAAW;AACrB;AAEA,eAAe,aAAa,UAAkB;AAC5C,QAAM,WAAW,CAAC;AAClB,aAAW,MAAM,MAAM,cAAc,QAAQ,EAAG,UAAS,KAAK,EAAE,IAAI,UAAU,MAAM,oBAAoB,UAAU,EAAE,EAAE,CAAC;AACvH,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import type { AgentActivity, ExecutionTelemetryFrame, ReportTaskFinishedInput, ReportTurnActivityInput, StopBackgroundRunHandler, StopTurnHandler, TurnActivityReporter } from '../plugin-sdk.js';
|
|
1
|
+
import type { AgentActivity, ExecutionTelemetryFrame, ServerRequestHandler, ReportTaskFinishedInput, ReportTurnActivityInput, StopBackgroundRunHandler, StopTurnHandler, TurnActivityReporter } from '../plugin-sdk.js';
|
|
2
2
|
import type { ChannelSummary, ChannelFileEntry, ChannelFileContent, PublishChannelFileInput, ChannelHistoryEntry, ChannelMessageEvent, CreateTaskInput, DirectoryUser, MeResponseUser, PostMessageInput, PostedMessage, ReadChannelHistoryInput, Task, UpdateTaskInput } from '../types.js';
|
|
3
3
|
export interface ChatControlPlane {
|
|
4
|
+
reportExecutionTelemetryFrame?(frame: ExecutionTelemetryFrame): void;
|
|
5
|
+
onExecutionTelemetryAck?(handler: (ack: import('../plugin-sdk.js').ExecutionTelemetryAck) => void): () => void;
|
|
6
|
+
onExecutionTransportReady?(handler: () => void): () => void;
|
|
7
|
+
onServerRequest?(handler: ServerRequestHandler | undefined): void;
|
|
4
8
|
onStopTurn?(handler: StopTurnHandler | undefined): void;
|
|
5
9
|
onStopBackgroundRun?(handler: StopBackgroundRunHandler | undefined): void;
|
|
6
10
|
onActivityTransportReady?(handler: (() => void) | undefined): void;
|
|
7
11
|
connect(onMessage: (message: ChannelMessageEvent) => void): Promise<void>;
|
|
8
12
|
close(): Promise<void>;
|
|
9
|
-
postMessage(input: PostMessageInput): Promise<PostedMessage>;
|
|
13
|
+
postMessage(input: PostMessageInput, source?: Pick<import('../plugin-sdk.js').ServerRequestContext, 'isConnectionCurrent'>): Promise<PostedMessage>;
|
|
10
14
|
editMessage(messageId: string, content: string): Promise<void>;
|
|
11
15
|
deleteMessage(messageId: string): Promise<void>;
|
|
12
16
|
reportTyping(channelId: string): void;
|
|
@@ -14,6 +18,7 @@ export interface ChatControlPlane {
|
|
|
14
18
|
reportTurnActivity(input: ReportTurnActivityInput): TurnActivityReporter;
|
|
15
19
|
reportExecutionTelemetry?(frame: ExecutionTelemetryFrame): Promise<void>;
|
|
16
20
|
reportTaskFinished?(input: ReportTaskFinishedInput): void;
|
|
21
|
+
readonly sessionBindingsSupported?: boolean;
|
|
17
22
|
reportActivity?(input: {
|
|
18
23
|
channelId: string;
|
|
19
24
|
activity: AgentActivity;
|