@autohq/cli 0.1.308 → 0.1.310
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/dist/agent-bridge.js +145 -17
- package/dist/index.js +146 -18
- package/package.json +1 -1
package/dist/agent-bridge.js
CHANGED
|
@@ -19692,7 +19692,12 @@ var RuntimeBridgeOutputEntryEnvelopeWireSchema = external_exports.object({
|
|
|
19692
19692
|
turnStatus: RuntimeTurnStatusSchema.optional(),
|
|
19693
19693
|
// Present only on a turn's terminal result entry; carries the captured
|
|
19694
19694
|
// token/cost usage the persisting side turns into ledger rows.
|
|
19695
|
-
usage: RuntimeBridgeTurnUsageSchema.optional()
|
|
19695
|
+
usage: RuntimeBridgeTurnUsageSchema.optional(),
|
|
19696
|
+
// Present only on a turn's terminal result entry: the commands whose
|
|
19697
|
+
// messages that harness turn consumed, from the runtime's injection-order
|
|
19698
|
+
// ground truth. The persisting side settles exactly these turns; absent
|
|
19699
|
+
// (older runtimes, non-command turns) it falls back to cursor attribution.
|
|
19700
|
+
consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional()
|
|
19696
19701
|
}).strict();
|
|
19697
19702
|
var LegacyRuntimeBridgeOutputEntryEnvelopeSchema = RuntimeBridgeOutputEntryEnvelopeWireSchema.omit({ turnStatus: true }).extend({
|
|
19698
19703
|
sessionStatusAfter: external_exports.enum(["awaiting", "failed"])
|
|
@@ -19752,6 +19757,9 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
|
|
|
19752
19757
|
message: JsonValueSchema,
|
|
19753
19758
|
turnStatus: external_exports.enum(["waiting_for_input", "completed", "failed"]).optional(),
|
|
19754
19759
|
usage: RuntimeBridgeTurnUsageSchema.optional(),
|
|
19760
|
+
// See the conversation.entry envelope: terminal-result-only declaration of
|
|
19761
|
+
// the commands this turn consumed, for exact turn-ledger settlement.
|
|
19762
|
+
consumedCommandIds: external_exports.array(SessionCommandIdSchema).optional(),
|
|
19755
19763
|
createdAt: external_exports.string().datetime(),
|
|
19756
19764
|
completedAt: external_exports.string().datetime().nullable()
|
|
19757
19765
|
}).strict();
|
|
@@ -23399,7 +23407,7 @@ Object.assign(lookup, {
|
|
|
23399
23407
|
// package.json
|
|
23400
23408
|
var package_default = {
|
|
23401
23409
|
name: "@autohq/cli",
|
|
23402
|
-
version: "0.1.
|
|
23410
|
+
version: "0.1.310",
|
|
23403
23411
|
license: "SEE LICENSE IN README.md",
|
|
23404
23412
|
publishConfig: {
|
|
23405
23413
|
access: "public"
|
|
@@ -24616,6 +24624,8 @@ var ConversationRealtimeEventSchema = external_exports.discriminatedUnion("type"
|
|
|
24616
24624
|
|
|
24617
24625
|
// ../../packages/schemas/src/claude-code.ts
|
|
24618
24626
|
var ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
|
|
24627
|
+
var CLAUDE_CODE_INTERRUPT_MARKER_PREFIX = "[Request interrupted by user";
|
|
24628
|
+
var CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
|
|
24619
24629
|
var ClaudeCodeTextBlockSchema = external_exports.object({
|
|
24620
24630
|
type: external_exports.literal("text"),
|
|
24621
24631
|
text: external_exports.string()
|
|
@@ -24684,6 +24694,15 @@ var ClaudeCodeUserRecordSchema = external_exports.object({
|
|
|
24684
24694
|
type: external_exports.literal("user"),
|
|
24685
24695
|
message: ClaudeCodeUserMessageSchema
|
|
24686
24696
|
}).passthrough();
|
|
24697
|
+
var ClaudeCodeInterruptMarkerRecordSchema = external_exports.object({
|
|
24698
|
+
type: external_exports.literal("user"),
|
|
24699
|
+
message: external_exports.object({
|
|
24700
|
+
content: external_exports.union([
|
|
24701
|
+
external_exports.string(),
|
|
24702
|
+
external_exports.array(OptionalClaudeCodeAssistantContentBlockSchema)
|
|
24703
|
+
])
|
|
24704
|
+
}).passthrough()
|
|
24705
|
+
}).passthrough();
|
|
24687
24706
|
var ClaudeCodeAggregateUsageSchema = external_exports.object({
|
|
24688
24707
|
input_tokens: external_exports.number().optional(),
|
|
24689
24708
|
output_tokens: external_exports.number().optional(),
|
|
@@ -24746,6 +24765,26 @@ function parseClaudeCodeStreamRecord(parsed) {
|
|
|
24746
24765
|
}
|
|
24747
24766
|
};
|
|
24748
24767
|
}
|
|
24768
|
+
function isClaudeCodeInterruptMarker(record2) {
|
|
24769
|
+
const parsed = ClaudeCodeInterruptMarkerRecordSchema.safeParse(record2);
|
|
24770
|
+
if (!parsed.success) {
|
|
24771
|
+
return false;
|
|
24772
|
+
}
|
|
24773
|
+
const content = parsed.data.message.content;
|
|
24774
|
+
if (typeof content === "string") {
|
|
24775
|
+
return content.startsWith(CLAUDE_CODE_INTERRUPT_MARKER_PREFIX);
|
|
24776
|
+
}
|
|
24777
|
+
return content.some(
|
|
24778
|
+
(block) => block !== null && block.type === "text" && block.text.startsWith(CLAUDE_CODE_INTERRUPT_MARKER_PREFIX)
|
|
24779
|
+
);
|
|
24780
|
+
}
|
|
24781
|
+
function isClaudeCodeEdeDiagnosticOnlyError(errorMessage4) {
|
|
24782
|
+
if (!errorMessage4) {
|
|
24783
|
+
return false;
|
|
24784
|
+
}
|
|
24785
|
+
const lines = errorMessage4.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
24786
|
+
return lines.length > 0 && lines.every((line) => line.startsWith(CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX));
|
|
24787
|
+
}
|
|
24749
24788
|
function textContent(text2) {
|
|
24750
24789
|
return {
|
|
24751
24790
|
parts: [
|
|
@@ -39504,6 +39543,7 @@ var AgentBridgeOutputBuffer = class {
|
|
|
39504
39543
|
status: terminalEntryStatus(projection),
|
|
39505
39544
|
turnStatus: turnFailed ? void 0 : projection.turnStatus,
|
|
39506
39545
|
usage: turnFailed ? void 0 : projection.usage,
|
|
39546
|
+
consumedCommandIds: turnFailed ? void 0 : projection.consumedCommandIds,
|
|
39507
39547
|
createdAt: completedAt,
|
|
39508
39548
|
completedAt
|
|
39509
39549
|
});
|
|
@@ -39526,6 +39566,7 @@ var AgentBridgeOutputBuffer = class {
|
|
|
39526
39566
|
status: terminalEntryStatus(projection),
|
|
39527
39567
|
...projection.turnStatus ? { turnStatus: projection.turnStatus } : {},
|
|
39528
39568
|
...projection.usage ? { usage: projection.usage } : {},
|
|
39569
|
+
...projection.consumedCommandIds ? { consumedCommandIds: projection.consumedCommandIds } : {},
|
|
39529
39570
|
content: {
|
|
39530
39571
|
parts: [{ type: "text", text: statusText }]
|
|
39531
39572
|
}
|
|
@@ -39922,7 +39963,8 @@ function buildOutputEnvelope(context, outputSeq, projection) {
|
|
|
39922
39963
|
createdAt,
|
|
39923
39964
|
completedAt: entry.status === "in_progress" ? null : createdAt,
|
|
39924
39965
|
...entry.turnStatus ? { turnStatus: entry.turnStatus } : {},
|
|
39925
|
-
...entry.usage ? { usage: entry.usage } : {}
|
|
39966
|
+
...entry.usage ? { usage: entry.usage } : {},
|
|
39967
|
+
...entry.consumedCommandIds ? { consumedCommandIds: entry.consumedCommandIds } : {}
|
|
39926
39968
|
});
|
|
39927
39969
|
}
|
|
39928
39970
|
function buildDeltaOutputEnvelope(input) {
|
|
@@ -39984,6 +40026,7 @@ function buildUiMessageCompletedOutputEnvelope(input) {
|
|
|
39984
40026
|
message: toJsonValue(input.message),
|
|
39985
40027
|
...input.turnStatus ? { turnStatus: input.turnStatus } : {},
|
|
39986
40028
|
...input.usage ? { usage: input.usage } : {},
|
|
40029
|
+
...input.consumedCommandIds ? { consumedCommandIds: input.consumedCommandIds } : {},
|
|
39987
40030
|
createdAt: input.createdAt,
|
|
39988
40031
|
completedAt: input.completedAt
|
|
39989
40032
|
});
|
|
@@ -40016,13 +40059,25 @@ var ClaudeCodeProjector = class {
|
|
|
40016
40059
|
activeParts = /* @__PURE__ */ new Map();
|
|
40017
40060
|
activeToolInputs = /* @__PURE__ */ new Map();
|
|
40018
40061
|
streamedMessageIds = /* @__PURE__ */ new Set();
|
|
40062
|
+
// The SDK's "[Request interrupted by user]" transcript marker was seen since
|
|
40063
|
+
// the last terminal result: the very next diagnostic-only
|
|
40064
|
+
// `error_during_execution` result is that interrupt's cancellation, not a
|
|
40065
|
+
// real turn failure (FRA-3548). Cleared on every result and on the next
|
|
40066
|
+
// message_start so a stale marker can never reclassify a later failure.
|
|
40067
|
+
interruptMarkerSeen = false;
|
|
40019
40068
|
project(message) {
|
|
40069
|
+
if (isClaudeCodeInterruptMarker(message)) {
|
|
40070
|
+
this.interruptMarkerSeen = true;
|
|
40071
|
+
}
|
|
40020
40072
|
if (message.type === "stream_event") {
|
|
40021
40073
|
return this.projectStreamEvent(message);
|
|
40022
40074
|
}
|
|
40023
40075
|
const parsed = parseClaudeCodeStreamRecord(message);
|
|
40024
40076
|
const snapshotMessageId = assistantSnapshotMessageId(message);
|
|
40025
40077
|
const suppressStreamed = snapshotMessageId !== null && this.streamedMessageIds.has(snapshotMessageId);
|
|
40078
|
+
if (message.type === "assistant" && !suppressStreamed) {
|
|
40079
|
+
this.interruptMarkerSeen = false;
|
|
40080
|
+
}
|
|
40026
40081
|
const outputs = !suppressStreamed && message.type === "assistant" ? projectAssistantSnapshot(parsed.projections) : parsed.projections.flatMap((entry) => {
|
|
40027
40082
|
if (suppressStreamed && (entry.kind === "message" || entry.kind === "tool_call")) {
|
|
40028
40083
|
return [];
|
|
@@ -40033,10 +40088,24 @@ var ClaudeCodeProjector = class {
|
|
|
40033
40088
|
outputs.push(...this.endActiveParts(), ...this.finishActiveToolInputs());
|
|
40034
40089
|
this.currentMessageId = null;
|
|
40035
40090
|
this.activeResponseMessageId = null;
|
|
40036
|
-
outputs.push(
|
|
40091
|
+
outputs.push(
|
|
40092
|
+
projectClaudeCodeResult(parsed.result, {
|
|
40093
|
+
interrupted: this.isInterruptCancellation(parsed.result)
|
|
40094
|
+
})
|
|
40095
|
+
);
|
|
40096
|
+
this.interruptMarkerSeen = false;
|
|
40037
40097
|
}
|
|
40038
40098
|
return outputs;
|
|
40039
40099
|
}
|
|
40100
|
+
// An interrupt cancels the running turn cleanly at the transcript level, but
|
|
40101
|
+
// Claude Code has no cancelled result subtype: the turn's terminal result
|
|
40102
|
+
// surfaces as a diagnostic-only `error_during_execution`. Treating that as a
|
|
40103
|
+
// turn failure fed the FRA-3548 redelivery loop (the bridge redelivered a
|
|
40104
|
+
// message the SDK was actively answering), so a failed result bracketed by
|
|
40105
|
+
// the SDK's own interrupt marker is classified as a cancellation instead.
|
|
40106
|
+
isInterruptCancellation(result) {
|
|
40107
|
+
return result.isError && this.interruptMarkerSeen && isClaudeCodeEdeDiagnosticOnlyError(result.errorMessage);
|
|
40108
|
+
}
|
|
40040
40109
|
flushPendingAssistantMessages() {
|
|
40041
40110
|
const outputs = [
|
|
40042
40111
|
...this.endActiveParts(),
|
|
@@ -40044,6 +40113,7 @@ var ClaudeCodeProjector = class {
|
|
|
40044
40113
|
];
|
|
40045
40114
|
this.currentMessageId = null;
|
|
40046
40115
|
this.activeResponseMessageId = null;
|
|
40116
|
+
this.interruptMarkerSeen = false;
|
|
40047
40117
|
return outputs;
|
|
40048
40118
|
}
|
|
40049
40119
|
projectStreamEvent(message) {
|
|
@@ -40052,6 +40122,7 @@ var ClaudeCodeProjector = class {
|
|
|
40052
40122
|
this.streamedMessageIds.add(this.currentMessageId);
|
|
40053
40123
|
this.activeParts.clear();
|
|
40054
40124
|
this.activeToolInputs.clear();
|
|
40125
|
+
this.interruptMarkerSeen = false;
|
|
40055
40126
|
return this.ensureResponseStarted(this.currentMessageId);
|
|
40056
40127
|
}
|
|
40057
40128
|
if (message.event.type === "message_stop") {
|
|
@@ -40142,7 +40213,17 @@ var ClaudeCodeProjector = class {
|
|
|
40142
40213
|
);
|
|
40143
40214
|
}
|
|
40144
40215
|
};
|
|
40145
|
-
function projectClaudeCodeResult(result) {
|
|
40216
|
+
function projectClaudeCodeResult(result, options = {}) {
|
|
40217
|
+
if (options.interrupted) {
|
|
40218
|
+
return {
|
|
40219
|
+
type: "ui_message_chunk",
|
|
40220
|
+
chunk: { type: "finish", finishReason: "stop" },
|
|
40221
|
+
// Neutral wording: the projector sees that an interrupt cancelled the
|
|
40222
|
+
// turn, not why the interrupt was sent.
|
|
40223
|
+
statusText: "claude-code turn interrupted",
|
|
40224
|
+
turnStatus: "completed"
|
|
40225
|
+
};
|
|
40226
|
+
}
|
|
40146
40227
|
return {
|
|
40147
40228
|
type: "ui_message_chunk",
|
|
40148
40229
|
chunk: {
|
|
@@ -60277,6 +60358,13 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60277
60358
|
// settlement after the ack). Flushed once the turn ends and the session is
|
|
60278
60359
|
// idle.
|
|
60279
60360
|
deferredMessages = [];
|
|
60361
|
+
// Consumed-command ids per enqueued turn, in injection order. Results arrive
|
|
60362
|
+
// in turn order, so each terminal `result` settles the OLDEST open entry —
|
|
60363
|
+
// which is also why an interrupted turn's result (arriving after the
|
|
60364
|
+
// interrupter enqueued) still resolves to the interrupted command. A
|
|
60365
|
+
// deferred flush enqueues one concatenated turn, so its entry carries every
|
|
60366
|
+
// flushed command id.
|
|
60367
|
+
openTurnCommandIds = [];
|
|
60280
60368
|
// tool_use ids the assistant has emitted whose tool_result has not yet been
|
|
60281
60369
|
// observed. A non-empty set means a tool call is in flight, so an immediate
|
|
60282
60370
|
// interrupt would append the new user message after an unresolved
|
|
@@ -60338,6 +60426,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60338
60426
|
}
|
|
60339
60427
|
async sendMessage(message, options) {
|
|
60340
60428
|
const mode = options?.mode ?? "interrupt";
|
|
60429
|
+
const commandIds = options?.commandId ? [options.commandId] : [];
|
|
60341
60430
|
const startedAt = Date.now();
|
|
60342
60431
|
this.input.runtimeLogger?.info("agent_bridge_claude_send_message_started", {
|
|
60343
60432
|
delivery_mode: mode,
|
|
@@ -60347,7 +60436,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60347
60436
|
deferred_count: this.deferredMessages.length
|
|
60348
60437
|
});
|
|
60349
60438
|
if (mode === "deferred" && this.hasInterruptibleTurn()) {
|
|
60350
|
-
this.deferredMessages.push(message);
|
|
60439
|
+
this.deferredMessages.push({ text: message, commandIds });
|
|
60351
60440
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_deferred", {
|
|
60352
60441
|
active_turn_count: this.activeTurnCount,
|
|
60353
60442
|
pending_tool_use_count: this.pendingToolUseIds.size,
|
|
@@ -60357,7 +60446,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60357
60446
|
}
|
|
60358
60447
|
const interruption = await this.interruptActiveTurnBeforeMessage();
|
|
60359
60448
|
if (interruption === "defer" && this.hasInterruptibleTurn()) {
|
|
60360
|
-
this.deferredMessages.push(message);
|
|
60449
|
+
this.deferredMessages.push({ text: message, commandIds });
|
|
60361
60450
|
this.input.runtimeLogger?.info(
|
|
60362
60451
|
"agent_bridge_claude_message_deferred_after_interrupt_timeout",
|
|
60363
60452
|
{
|
|
@@ -60369,7 +60458,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60369
60458
|
return;
|
|
60370
60459
|
}
|
|
60371
60460
|
await this.awaitMcpRegistration();
|
|
60372
|
-
this.enqueueUserMessage(message);
|
|
60461
|
+
this.enqueueUserMessage(message, commandIds);
|
|
60373
60462
|
this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
|
|
60374
60463
|
delivery_mode: mode,
|
|
60375
60464
|
duration_ms: Date.now() - startedAt,
|
|
@@ -60379,6 +60468,20 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60379
60468
|
deferred_count: this.deferredMessages.length
|
|
60380
60469
|
});
|
|
60381
60470
|
}
|
|
60471
|
+
noteActiveTurnCommand(commandId) {
|
|
60472
|
+
const activeTurn = this.openTurnCommandIds[0];
|
|
60473
|
+
if (activeTurn) {
|
|
60474
|
+
activeTurn.push(commandId);
|
|
60475
|
+
}
|
|
60476
|
+
this.input.runtimeLogger?.info(
|
|
60477
|
+
"agent_bridge_claude_active_turn_command_noted",
|
|
60478
|
+
{
|
|
60479
|
+
attributed: Boolean(activeTurn),
|
|
60480
|
+
active_turn_count: this.activeTurnCount,
|
|
60481
|
+
open_turn_entries: this.openTurnCommandIds.length
|
|
60482
|
+
}
|
|
60483
|
+
);
|
|
60484
|
+
}
|
|
60382
60485
|
close() {
|
|
60383
60486
|
const previousState = this.state;
|
|
60384
60487
|
if (previousState.kind === "closed") {
|
|
@@ -60394,6 +60497,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60394
60497
|
);
|
|
60395
60498
|
this.deferredMessages.length = 0;
|
|
60396
60499
|
}
|
|
60500
|
+
this.openTurnCommandIds.length = 0;
|
|
60397
60501
|
this.stderr.flush();
|
|
60398
60502
|
this.inputQueue.close();
|
|
60399
60503
|
if (previousState.kind === "started") {
|
|
@@ -60477,8 +60581,12 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60477
60581
|
try {
|
|
60478
60582
|
for await (const message of query) {
|
|
60479
60583
|
this.trackToolUseLifecycle(message);
|
|
60584
|
+
let meta3;
|
|
60480
60585
|
if (isClaudeAgentTurnResult(message)) {
|
|
60481
60586
|
this.activeTurnCount = Math.max(0, this.activeTurnCount - 1);
|
|
60587
|
+
meta3 = {
|
|
60588
|
+
consumedCommandIds: this.openTurnCommandIds.shift() ?? []
|
|
60589
|
+
};
|
|
60482
60590
|
this.pendingToolUseIds.clear();
|
|
60483
60591
|
this.turnResultCount += 1;
|
|
60484
60592
|
this.resolveTurnSettlement(true);
|
|
@@ -60486,7 +60594,8 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60486
60594
|
active_turn_count: this.activeTurnCount,
|
|
60487
60595
|
pending_tool_use_count: this.pendingToolUseIds.size,
|
|
60488
60596
|
turn_result_count: this.turnResultCount,
|
|
60489
|
-
deferred_count: this.deferredMessages.length
|
|
60597
|
+
deferred_count: this.deferredMessages.length,
|
|
60598
|
+
consumed_command_ids: meta3.consumedCommandIds
|
|
60490
60599
|
});
|
|
60491
60600
|
if (this.activeTurnCount === 0) {
|
|
60492
60601
|
this.flushDeferredMessages();
|
|
@@ -60506,7 +60615,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60506
60615
|
this.close();
|
|
60507
60616
|
return;
|
|
60508
60617
|
}
|
|
60509
|
-
await this.input.onMessage(message);
|
|
60618
|
+
await this.input.onMessage(message, meta3);
|
|
60510
60619
|
}
|
|
60511
60620
|
} catch (error51) {
|
|
60512
60621
|
if (this.state.kind !== "closed") {
|
|
@@ -60514,6 +60623,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60514
60623
|
}
|
|
60515
60624
|
} finally {
|
|
60516
60625
|
this.activeTurnCount = 0;
|
|
60626
|
+
this.openTurnCommandIds.length = 0;
|
|
60517
60627
|
this.pendingToolUseIds.clear();
|
|
60518
60628
|
this.resolveTurnSettlement(false);
|
|
60519
60629
|
this.state = { kind: "closed" };
|
|
@@ -60525,9 +60635,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60525
60635
|
// lets injection work while the SDK session is still starting; the queue
|
|
60526
60636
|
// drains once the query attaches. Startup failures surface through onError
|
|
60527
60637
|
// instead of failing injection.
|
|
60528
|
-
enqueueUserMessage(message) {
|
|
60638
|
+
enqueueUserMessage(message, commandIds) {
|
|
60529
60639
|
this.inputQueue.push(claudeAgentUserMessage(message));
|
|
60530
60640
|
this.activeTurnCount += 1;
|
|
60641
|
+
this.openTurnCommandIds.push(commandIds);
|
|
60531
60642
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_enqueued", {
|
|
60532
60643
|
state: this.state.kind,
|
|
60533
60644
|
active_turn_count: this.activeTurnCount,
|
|
@@ -60611,7 +60722,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
60611
60722
|
this.input.writeOutput?.(
|
|
60612
60723
|
`agent_bridge_claude_deferred_flush count=${pending.length}`
|
|
60613
60724
|
);
|
|
60614
|
-
this.enqueueUserMessage(
|
|
60725
|
+
this.enqueueUserMessage(
|
|
60726
|
+
pending.map((entry) => entry.text).join("\n\n"),
|
|
60727
|
+
pending.flatMap((entry) => entry.commandIds)
|
|
60728
|
+
);
|
|
60615
60729
|
}
|
|
60616
60730
|
async interruptActiveTurnBeforeMessage() {
|
|
60617
60731
|
if (!this.hasInterruptibleTurn()) {
|
|
@@ -61278,7 +61392,8 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61278
61392
|
})
|
|
61279
61393
|
);
|
|
61280
61394
|
await this.ensureAgentSession().sendMessage(message, {
|
|
61281
|
-
mode
|
|
61395
|
+
mode,
|
|
61396
|
+
commandId: delivery.commandId
|
|
61282
61397
|
});
|
|
61283
61398
|
this.input.runtimeLogger?.info(
|
|
61284
61399
|
"agent_bridge_claude_command_send_message_ready",
|
|
@@ -61333,6 +61448,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61333
61448
|
const pending = this.pendingQuestions.get(answer.toolCallId);
|
|
61334
61449
|
if (pending) {
|
|
61335
61450
|
this.pendingQuestions.delete(answer.toolCallId);
|
|
61451
|
+
this.agentSession?.noteActiveTurnCommand(delivery.commandId);
|
|
61336
61452
|
pending.resolve({
|
|
61337
61453
|
behavior: "allow",
|
|
61338
61454
|
updatedInput: {
|
|
@@ -61359,7 +61475,9 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61359
61475
|
}
|
|
61360
61476
|
}
|
|
61361
61477
|
});
|
|
61362
|
-
await this.ensureAgentSession().sendMessage(message
|
|
61478
|
+
await this.ensureAgentSession().sendMessage(message, {
|
|
61479
|
+
commandId: delivery.commandId
|
|
61480
|
+
});
|
|
61363
61481
|
this.input.writeOutput?.(
|
|
61364
61482
|
`agent_bridge_question_answer_fallback tool_use_id=${answer.toolCallId}`
|
|
61365
61483
|
);
|
|
@@ -61415,7 +61533,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61415
61533
|
);
|
|
61416
61534
|
}
|
|
61417
61535
|
}
|
|
61418
|
-
async handleAgentMessage(message) {
|
|
61536
|
+
async handleAgentMessage(message, meta3) {
|
|
61419
61537
|
const activeContext = this.context;
|
|
61420
61538
|
if (!activeContext) {
|
|
61421
61539
|
return;
|
|
@@ -61431,7 +61549,10 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61431
61549
|
return;
|
|
61432
61550
|
}
|
|
61433
61551
|
for (const projection of projections) {
|
|
61434
|
-
await this.emitBridgeOutput(
|
|
61552
|
+
await this.emitBridgeOutput(
|
|
61553
|
+
activeContext,
|
|
61554
|
+
withConsumedCommandIds(projection, meta3)
|
|
61555
|
+
);
|
|
61435
61556
|
}
|
|
61436
61557
|
}
|
|
61437
61558
|
async handleAgentError(error51) {
|
|
@@ -61499,7 +61620,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61499
61620
|
claude: this.input.claude,
|
|
61500
61621
|
resumeAgentId: this.storedResumeAgentId(),
|
|
61501
61622
|
canUseTool: this.canUseTool,
|
|
61502
|
-
onMessage: (message) => this.handleAgentMessage(message),
|
|
61623
|
+
onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
|
|
61503
61624
|
onError: (error51) => this.handleAgentError(error51),
|
|
61504
61625
|
onExit: () => {
|
|
61505
61626
|
if (this.agentSession === session) {
|
|
@@ -61514,6 +61635,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
61514
61635
|
return session;
|
|
61515
61636
|
}
|
|
61516
61637
|
};
|
|
61638
|
+
function withConsumedCommandIds(projection, meta3) {
|
|
61639
|
+
const consumedCommandIds = meta3?.consumedCommandIds;
|
|
61640
|
+
if (!consumedCommandIds || consumedCommandIds.length === 0 || projection.type !== "ui_message_chunk" || !projection.turnStatus) {
|
|
61641
|
+
return projection;
|
|
61642
|
+
}
|
|
61643
|
+
return { ...projection, consumedCommandIds };
|
|
61644
|
+
}
|
|
61517
61645
|
function answerFallbackMessage(answer) {
|
|
61518
61646
|
const lines = Object.entries(answer.answers).map(
|
|
61519
61647
|
([question, value2]) => `- ${question}: ${value2}`
|
package/dist/index.js
CHANGED
|
@@ -16004,6 +16004,26 @@ function parseClaudeCodeStreamRecord(parsed) {
|
|
|
16004
16004
|
}
|
|
16005
16005
|
};
|
|
16006
16006
|
}
|
|
16007
|
+
function isClaudeCodeInterruptMarker(record2) {
|
|
16008
|
+
const parsed = ClaudeCodeInterruptMarkerRecordSchema.safeParse(record2);
|
|
16009
|
+
if (!parsed.success) {
|
|
16010
|
+
return false;
|
|
16011
|
+
}
|
|
16012
|
+
const content = parsed.data.message.content;
|
|
16013
|
+
if (typeof content === "string") {
|
|
16014
|
+
return content.startsWith(CLAUDE_CODE_INTERRUPT_MARKER_PREFIX);
|
|
16015
|
+
}
|
|
16016
|
+
return content.some(
|
|
16017
|
+
(block) => block !== null && block.type === "text" && block.text.startsWith(CLAUDE_CODE_INTERRUPT_MARKER_PREFIX)
|
|
16018
|
+
);
|
|
16019
|
+
}
|
|
16020
|
+
function isClaudeCodeEdeDiagnosticOnlyError(errorMessage6) {
|
|
16021
|
+
if (!errorMessage6) {
|
|
16022
|
+
return false;
|
|
16023
|
+
}
|
|
16024
|
+
const lines = errorMessage6.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
16025
|
+
return lines.length > 0 && lines.every((line) => line.startsWith(CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX));
|
|
16026
|
+
}
|
|
16007
16027
|
function textContent(text) {
|
|
16008
16028
|
return {
|
|
16009
16029
|
parts: [
|
|
@@ -16185,7 +16205,7 @@ function usdAmount(value) {
|
|
|
16185
16205
|
}
|
|
16186
16206
|
return value;
|
|
16187
16207
|
}
|
|
16188
|
-
var ASK_USER_QUESTION_TOOL_NAME, ClaudeCodeTextBlockSchema, ClaudeCodeToolUseBlockSchema, ClaudeCodeThinkingBlockSchema, ClaudeCodeToolResultBlockSchema, ClaudeCodeAssistantContentBlockSchema, OptionalClaudeCodeAssistantContentBlockSchema, ClaudeCodeAssistantContentSchema, OptionalClaudeCodeToolResultBlockSchema, ClaudeCodeToolResultContentSchema, ClaudeCodeUserContentSchema, ClaudeCodeAssistantMessageSchema, ClaudeCodeUserMessageSchema, ClaudeCodeSystemRecordSchema, ClaudeCodeAssistantRecordSchema, ClaudeCodeUserRecordSchema, ClaudeCodeAggregateUsageSchema, ClaudeCodeModelUsageSchema, ClaudeCodeResultRecordSchema, ClaudeCodeSessionRecordSchema, ClaudeCodeStreamRecordSchema, AskUserQuestionInputSchema;
|
|
16208
|
+
var ASK_USER_QUESTION_TOOL_NAME, CLAUDE_CODE_INTERRUPT_MARKER_PREFIX, CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX, ClaudeCodeTextBlockSchema, ClaudeCodeToolUseBlockSchema, ClaudeCodeThinkingBlockSchema, ClaudeCodeToolResultBlockSchema, ClaudeCodeAssistantContentBlockSchema, OptionalClaudeCodeAssistantContentBlockSchema, ClaudeCodeAssistantContentSchema, OptionalClaudeCodeToolResultBlockSchema, ClaudeCodeToolResultContentSchema, ClaudeCodeUserContentSchema, ClaudeCodeAssistantMessageSchema, ClaudeCodeUserMessageSchema, ClaudeCodeSystemRecordSchema, ClaudeCodeAssistantRecordSchema, ClaudeCodeUserRecordSchema, ClaudeCodeInterruptMarkerRecordSchema, ClaudeCodeAggregateUsageSchema, ClaudeCodeModelUsageSchema, ClaudeCodeResultRecordSchema, ClaudeCodeSessionRecordSchema, ClaudeCodeStreamRecordSchema, AskUserQuestionInputSchema;
|
|
16189
16209
|
var init_claude_code = __esm({
|
|
16190
16210
|
"../../packages/schemas/src/claude-code.ts"() {
|
|
16191
16211
|
"use strict";
|
|
@@ -16193,6 +16213,8 @@ var init_claude_code = __esm({
|
|
|
16193
16213
|
init_conversation();
|
|
16194
16214
|
init_primitives();
|
|
16195
16215
|
ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion";
|
|
16216
|
+
CLAUDE_CODE_INTERRUPT_MARKER_PREFIX = "[Request interrupted by user";
|
|
16217
|
+
CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX = "[ede_diagnostic]";
|
|
16196
16218
|
ClaudeCodeTextBlockSchema = external_exports.object({
|
|
16197
16219
|
type: external_exports.literal("text"),
|
|
16198
16220
|
text: external_exports.string()
|
|
@@ -16261,6 +16283,15 @@ var init_claude_code = __esm({
|
|
|
16261
16283
|
type: external_exports.literal("user"),
|
|
16262
16284
|
message: ClaudeCodeUserMessageSchema
|
|
16263
16285
|
}).passthrough();
|
|
16286
|
+
ClaudeCodeInterruptMarkerRecordSchema = external_exports.object({
|
|
16287
|
+
type: external_exports.literal("user"),
|
|
16288
|
+
message: external_exports.object({
|
|
16289
|
+
content: external_exports.union([
|
|
16290
|
+
external_exports.string(),
|
|
16291
|
+
external_exports.array(OptionalClaudeCodeAssistantContentBlockSchema)
|
|
16292
|
+
])
|
|
16293
|
+
}).passthrough()
|
|
16294
|
+
}).passthrough();
|
|
16264
16295
|
ClaudeCodeAggregateUsageSchema = external_exports.object({
|
|
16265
16296
|
input_tokens: external_exports.number().optional(),
|
|
16266
16297
|
output_tokens: external_exports.number().optional(),
|
|
@@ -25579,7 +25610,7 @@ var init_package = __esm({
|
|
|
25579
25610
|
"package.json"() {
|
|
25580
25611
|
package_default = {
|
|
25581
25612
|
name: "@autohq/cli",
|
|
25582
|
-
version: "0.1.
|
|
25613
|
+
version: "0.1.310",
|
|
25583
25614
|
license: "SEE LICENSE IN README.md",
|
|
25584
25615
|
publishConfig: {
|
|
25585
25616
|
access: "public"
|
|
@@ -35611,7 +35642,12 @@ var RuntimeBridgeOutputEntryEnvelopeWireSchema = external_exports.object({
|
|
|
35611
35642
|
turnStatus: RuntimeTurnStatusSchema.optional(),
|
|
35612
35643
|
// Present only on a turn's terminal result entry; carries the captured
|
|
35613
35644
|
// token/cost usage the persisting side turns into ledger rows.
|
|
35614
|
-
usage: RuntimeBridgeTurnUsageSchema.optional()
|
|
35645
|
+
usage: RuntimeBridgeTurnUsageSchema.optional(),
|
|
35646
|
+
// Present only on a turn's terminal result entry: the commands whose
|
|
35647
|
+
// messages that harness turn consumed, from the runtime's injection-order
|
|
35648
|
+
// ground truth. The persisting side settles exactly these turns; absent
|
|
35649
|
+
// (older runtimes, non-command turns) it falls back to cursor attribution.
|
|
35650
|
+
consumedCommandIds: external_exports.array(SessionCommandIdSchema2).optional()
|
|
35615
35651
|
}).strict();
|
|
35616
35652
|
var LegacyRuntimeBridgeOutputEntryEnvelopeSchema = RuntimeBridgeOutputEntryEnvelopeWireSchema.omit({ turnStatus: true }).extend({
|
|
35617
35653
|
sessionStatusAfter: external_exports.enum(["awaiting", "failed"])
|
|
@@ -35671,6 +35707,9 @@ var RuntimeBridgeOutputUiMessageCompletedEnvelopeSchema = external_exports.objec
|
|
|
35671
35707
|
message: JsonValueSchema2,
|
|
35672
35708
|
turnStatus: external_exports.enum(["waiting_for_input", "completed", "failed"]).optional(),
|
|
35673
35709
|
usage: RuntimeBridgeTurnUsageSchema.optional(),
|
|
35710
|
+
// See the conversation.entry envelope: terminal-result-only declaration of
|
|
35711
|
+
// the commands this turn consumed, for exact turn-ledger settlement.
|
|
35712
|
+
consumedCommandIds: external_exports.array(SessionCommandIdSchema2).optional(),
|
|
35674
35713
|
createdAt: external_exports.string().datetime(),
|
|
35675
35714
|
completedAt: external_exports.string().datetime().nullable()
|
|
35676
35715
|
}).strict();
|
|
@@ -36601,6 +36640,7 @@ var AgentBridgeOutputBuffer = class {
|
|
|
36601
36640
|
status: terminalEntryStatus(projection),
|
|
36602
36641
|
turnStatus: turnFailed ? void 0 : projection.turnStatus,
|
|
36603
36642
|
usage: turnFailed ? void 0 : projection.usage,
|
|
36643
|
+
consumedCommandIds: turnFailed ? void 0 : projection.consumedCommandIds,
|
|
36604
36644
|
createdAt: completedAt,
|
|
36605
36645
|
completedAt
|
|
36606
36646
|
});
|
|
@@ -36623,6 +36663,7 @@ var AgentBridgeOutputBuffer = class {
|
|
|
36623
36663
|
status: terminalEntryStatus(projection),
|
|
36624
36664
|
...projection.turnStatus ? { turnStatus: projection.turnStatus } : {},
|
|
36625
36665
|
...projection.usage ? { usage: projection.usage } : {},
|
|
36666
|
+
...projection.consumedCommandIds ? { consumedCommandIds: projection.consumedCommandIds } : {},
|
|
36626
36667
|
content: {
|
|
36627
36668
|
parts: [{ type: "text", text: statusText }]
|
|
36628
36669
|
}
|
|
@@ -37019,7 +37060,8 @@ function buildOutputEnvelope(context, outputSeq, projection) {
|
|
|
37019
37060
|
createdAt,
|
|
37020
37061
|
completedAt: entry.status === "in_progress" ? null : createdAt,
|
|
37021
37062
|
...entry.turnStatus ? { turnStatus: entry.turnStatus } : {},
|
|
37022
|
-
...entry.usage ? { usage: entry.usage } : {}
|
|
37063
|
+
...entry.usage ? { usage: entry.usage } : {},
|
|
37064
|
+
...entry.consumedCommandIds ? { consumedCommandIds: entry.consumedCommandIds } : {}
|
|
37023
37065
|
});
|
|
37024
37066
|
}
|
|
37025
37067
|
function buildDeltaOutputEnvelope(input) {
|
|
@@ -37081,6 +37123,7 @@ function buildUiMessageCompletedOutputEnvelope(input) {
|
|
|
37081
37123
|
message: toJsonValue(input.message),
|
|
37082
37124
|
...input.turnStatus ? { turnStatus: input.turnStatus } : {},
|
|
37083
37125
|
...input.usage ? { usage: input.usage } : {},
|
|
37126
|
+
...input.consumedCommandIds ? { consumedCommandIds: input.consumedCommandIds } : {},
|
|
37084
37127
|
createdAt: input.createdAt,
|
|
37085
37128
|
completedAt: input.completedAt
|
|
37086
37129
|
});
|
|
@@ -37114,13 +37157,25 @@ var ClaudeCodeProjector = class {
|
|
|
37114
37157
|
activeParts = /* @__PURE__ */ new Map();
|
|
37115
37158
|
activeToolInputs = /* @__PURE__ */ new Map();
|
|
37116
37159
|
streamedMessageIds = /* @__PURE__ */ new Set();
|
|
37160
|
+
// The SDK's "[Request interrupted by user]" transcript marker was seen since
|
|
37161
|
+
// the last terminal result: the very next diagnostic-only
|
|
37162
|
+
// `error_during_execution` result is that interrupt's cancellation, not a
|
|
37163
|
+
// real turn failure (FRA-3548). Cleared on every result and on the next
|
|
37164
|
+
// message_start so a stale marker can never reclassify a later failure.
|
|
37165
|
+
interruptMarkerSeen = false;
|
|
37117
37166
|
project(message) {
|
|
37167
|
+
if (isClaudeCodeInterruptMarker(message)) {
|
|
37168
|
+
this.interruptMarkerSeen = true;
|
|
37169
|
+
}
|
|
37118
37170
|
if (message.type === "stream_event") {
|
|
37119
37171
|
return this.projectStreamEvent(message);
|
|
37120
37172
|
}
|
|
37121
37173
|
const parsed = parseClaudeCodeStreamRecord(message);
|
|
37122
37174
|
const snapshotMessageId = assistantSnapshotMessageId(message);
|
|
37123
37175
|
const suppressStreamed = snapshotMessageId !== null && this.streamedMessageIds.has(snapshotMessageId);
|
|
37176
|
+
if (message.type === "assistant" && !suppressStreamed) {
|
|
37177
|
+
this.interruptMarkerSeen = false;
|
|
37178
|
+
}
|
|
37124
37179
|
const outputs = !suppressStreamed && message.type === "assistant" ? projectAssistantSnapshot(parsed.projections) : parsed.projections.flatMap((entry) => {
|
|
37125
37180
|
if (suppressStreamed && (entry.kind === "message" || entry.kind === "tool_call")) {
|
|
37126
37181
|
return [];
|
|
@@ -37131,10 +37186,24 @@ var ClaudeCodeProjector = class {
|
|
|
37131
37186
|
outputs.push(...this.endActiveParts(), ...this.finishActiveToolInputs());
|
|
37132
37187
|
this.currentMessageId = null;
|
|
37133
37188
|
this.activeResponseMessageId = null;
|
|
37134
|
-
outputs.push(
|
|
37189
|
+
outputs.push(
|
|
37190
|
+
projectClaudeCodeResult(parsed.result, {
|
|
37191
|
+
interrupted: this.isInterruptCancellation(parsed.result)
|
|
37192
|
+
})
|
|
37193
|
+
);
|
|
37194
|
+
this.interruptMarkerSeen = false;
|
|
37135
37195
|
}
|
|
37136
37196
|
return outputs;
|
|
37137
37197
|
}
|
|
37198
|
+
// An interrupt cancels the running turn cleanly at the transcript level, but
|
|
37199
|
+
// Claude Code has no cancelled result subtype: the turn's terminal result
|
|
37200
|
+
// surfaces as a diagnostic-only `error_during_execution`. Treating that as a
|
|
37201
|
+
// turn failure fed the FRA-3548 redelivery loop (the bridge redelivered a
|
|
37202
|
+
// message the SDK was actively answering), so a failed result bracketed by
|
|
37203
|
+
// the SDK's own interrupt marker is classified as a cancellation instead.
|
|
37204
|
+
isInterruptCancellation(result) {
|
|
37205
|
+
return result.isError && this.interruptMarkerSeen && isClaudeCodeEdeDiagnosticOnlyError(result.errorMessage);
|
|
37206
|
+
}
|
|
37138
37207
|
flushPendingAssistantMessages() {
|
|
37139
37208
|
const outputs = [
|
|
37140
37209
|
...this.endActiveParts(),
|
|
@@ -37142,6 +37211,7 @@ var ClaudeCodeProjector = class {
|
|
|
37142
37211
|
];
|
|
37143
37212
|
this.currentMessageId = null;
|
|
37144
37213
|
this.activeResponseMessageId = null;
|
|
37214
|
+
this.interruptMarkerSeen = false;
|
|
37145
37215
|
return outputs;
|
|
37146
37216
|
}
|
|
37147
37217
|
projectStreamEvent(message) {
|
|
@@ -37150,6 +37220,7 @@ var ClaudeCodeProjector = class {
|
|
|
37150
37220
|
this.streamedMessageIds.add(this.currentMessageId);
|
|
37151
37221
|
this.activeParts.clear();
|
|
37152
37222
|
this.activeToolInputs.clear();
|
|
37223
|
+
this.interruptMarkerSeen = false;
|
|
37153
37224
|
return this.ensureResponseStarted(this.currentMessageId);
|
|
37154
37225
|
}
|
|
37155
37226
|
if (message.event.type === "message_stop") {
|
|
@@ -37240,7 +37311,17 @@ var ClaudeCodeProjector = class {
|
|
|
37240
37311
|
);
|
|
37241
37312
|
}
|
|
37242
37313
|
};
|
|
37243
|
-
function projectClaudeCodeResult(result) {
|
|
37314
|
+
function projectClaudeCodeResult(result, options = {}) {
|
|
37315
|
+
if (options.interrupted) {
|
|
37316
|
+
return {
|
|
37317
|
+
type: "ui_message_chunk",
|
|
37318
|
+
chunk: { type: "finish", finishReason: "stop" },
|
|
37319
|
+
// Neutral wording: the projector sees that an interrupt cancelled the
|
|
37320
|
+
// turn, not why the interrupt was sent.
|
|
37321
|
+
statusText: "claude-code turn interrupted",
|
|
37322
|
+
turnStatus: "completed"
|
|
37323
|
+
};
|
|
37324
|
+
}
|
|
37244
37325
|
return {
|
|
37245
37326
|
type: "ui_message_chunk",
|
|
37246
37327
|
chunk: {
|
|
@@ -37803,6 +37884,13 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37803
37884
|
// settlement after the ack). Flushed once the turn ends and the session is
|
|
37804
37885
|
// idle.
|
|
37805
37886
|
deferredMessages = [];
|
|
37887
|
+
// Consumed-command ids per enqueued turn, in injection order. Results arrive
|
|
37888
|
+
// in turn order, so each terminal `result` settles the OLDEST open entry —
|
|
37889
|
+
// which is also why an interrupted turn's result (arriving after the
|
|
37890
|
+
// interrupter enqueued) still resolves to the interrupted command. A
|
|
37891
|
+
// deferred flush enqueues one concatenated turn, so its entry carries every
|
|
37892
|
+
// flushed command id.
|
|
37893
|
+
openTurnCommandIds = [];
|
|
37806
37894
|
// tool_use ids the assistant has emitted whose tool_result has not yet been
|
|
37807
37895
|
// observed. A non-empty set means a tool call is in flight, so an immediate
|
|
37808
37896
|
// interrupt would append the new user message after an unresolved
|
|
@@ -37864,6 +37952,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37864
37952
|
}
|
|
37865
37953
|
async sendMessage(message, options) {
|
|
37866
37954
|
const mode = options?.mode ?? "interrupt";
|
|
37955
|
+
const commandIds = options?.commandId ? [options.commandId] : [];
|
|
37867
37956
|
const startedAt = Date.now();
|
|
37868
37957
|
this.input.runtimeLogger?.info("agent_bridge_claude_send_message_started", {
|
|
37869
37958
|
delivery_mode: mode,
|
|
@@ -37873,7 +37962,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37873
37962
|
deferred_count: this.deferredMessages.length
|
|
37874
37963
|
});
|
|
37875
37964
|
if (mode === "deferred" && this.hasInterruptibleTurn()) {
|
|
37876
|
-
this.deferredMessages.push(message);
|
|
37965
|
+
this.deferredMessages.push({ text: message, commandIds });
|
|
37877
37966
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_deferred", {
|
|
37878
37967
|
active_turn_count: this.activeTurnCount,
|
|
37879
37968
|
pending_tool_use_count: this.pendingToolUseIds.size,
|
|
@@ -37883,7 +37972,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37883
37972
|
}
|
|
37884
37973
|
const interruption = await this.interruptActiveTurnBeforeMessage();
|
|
37885
37974
|
if (interruption === "defer" && this.hasInterruptibleTurn()) {
|
|
37886
|
-
this.deferredMessages.push(message);
|
|
37975
|
+
this.deferredMessages.push({ text: message, commandIds });
|
|
37887
37976
|
this.input.runtimeLogger?.info(
|
|
37888
37977
|
"agent_bridge_claude_message_deferred_after_interrupt_timeout",
|
|
37889
37978
|
{
|
|
@@ -37895,7 +37984,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37895
37984
|
return;
|
|
37896
37985
|
}
|
|
37897
37986
|
await this.awaitMcpRegistration();
|
|
37898
|
-
this.enqueueUserMessage(message);
|
|
37987
|
+
this.enqueueUserMessage(message, commandIds);
|
|
37899
37988
|
this.input.runtimeLogger?.info("agent_bridge_claude_send_message_queued", {
|
|
37900
37989
|
delivery_mode: mode,
|
|
37901
37990
|
duration_ms: Date.now() - startedAt,
|
|
@@ -37905,6 +37994,20 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37905
37994
|
deferred_count: this.deferredMessages.length
|
|
37906
37995
|
});
|
|
37907
37996
|
}
|
|
37997
|
+
noteActiveTurnCommand(commandId) {
|
|
37998
|
+
const activeTurn = this.openTurnCommandIds[0];
|
|
37999
|
+
if (activeTurn) {
|
|
38000
|
+
activeTurn.push(commandId);
|
|
38001
|
+
}
|
|
38002
|
+
this.input.runtimeLogger?.info(
|
|
38003
|
+
"agent_bridge_claude_active_turn_command_noted",
|
|
38004
|
+
{
|
|
38005
|
+
attributed: Boolean(activeTurn),
|
|
38006
|
+
active_turn_count: this.activeTurnCount,
|
|
38007
|
+
open_turn_entries: this.openTurnCommandIds.length
|
|
38008
|
+
}
|
|
38009
|
+
);
|
|
38010
|
+
}
|
|
37908
38011
|
close() {
|
|
37909
38012
|
const previousState = this.state;
|
|
37910
38013
|
if (previousState.kind === "closed") {
|
|
@@ -37920,6 +38023,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
37920
38023
|
);
|
|
37921
38024
|
this.deferredMessages.length = 0;
|
|
37922
38025
|
}
|
|
38026
|
+
this.openTurnCommandIds.length = 0;
|
|
37923
38027
|
this.stderr.flush();
|
|
37924
38028
|
this.inputQueue.close();
|
|
37925
38029
|
if (previousState.kind === "started") {
|
|
@@ -38003,8 +38107,12 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38003
38107
|
try {
|
|
38004
38108
|
for await (const message of query) {
|
|
38005
38109
|
this.trackToolUseLifecycle(message);
|
|
38110
|
+
let meta3;
|
|
38006
38111
|
if (isClaudeAgentTurnResult(message)) {
|
|
38007
38112
|
this.activeTurnCount = Math.max(0, this.activeTurnCount - 1);
|
|
38113
|
+
meta3 = {
|
|
38114
|
+
consumedCommandIds: this.openTurnCommandIds.shift() ?? []
|
|
38115
|
+
};
|
|
38008
38116
|
this.pendingToolUseIds.clear();
|
|
38009
38117
|
this.turnResultCount += 1;
|
|
38010
38118
|
this.resolveTurnSettlement(true);
|
|
@@ -38012,7 +38120,8 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38012
38120
|
active_turn_count: this.activeTurnCount,
|
|
38013
38121
|
pending_tool_use_count: this.pendingToolUseIds.size,
|
|
38014
38122
|
turn_result_count: this.turnResultCount,
|
|
38015
|
-
deferred_count: this.deferredMessages.length
|
|
38123
|
+
deferred_count: this.deferredMessages.length,
|
|
38124
|
+
consumed_command_ids: meta3.consumedCommandIds
|
|
38016
38125
|
});
|
|
38017
38126
|
if (this.activeTurnCount === 0) {
|
|
38018
38127
|
this.flushDeferredMessages();
|
|
@@ -38032,7 +38141,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38032
38141
|
this.close();
|
|
38033
38142
|
return;
|
|
38034
38143
|
}
|
|
38035
|
-
await this.input.onMessage(message);
|
|
38144
|
+
await this.input.onMessage(message, meta3);
|
|
38036
38145
|
}
|
|
38037
38146
|
} catch (error51) {
|
|
38038
38147
|
if (this.state.kind !== "closed") {
|
|
@@ -38040,6 +38149,7 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38040
38149
|
}
|
|
38041
38150
|
} finally {
|
|
38042
38151
|
this.activeTurnCount = 0;
|
|
38152
|
+
this.openTurnCommandIds.length = 0;
|
|
38043
38153
|
this.pendingToolUseIds.clear();
|
|
38044
38154
|
this.resolveTurnSettlement(false);
|
|
38045
38155
|
this.state = { kind: "closed" };
|
|
@@ -38051,9 +38161,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38051
38161
|
// lets injection work while the SDK session is still starting; the queue
|
|
38052
38162
|
// drains once the query attaches. Startup failures surface through onError
|
|
38053
38163
|
// instead of failing injection.
|
|
38054
|
-
enqueueUserMessage(message) {
|
|
38164
|
+
enqueueUserMessage(message, commandIds) {
|
|
38055
38165
|
this.inputQueue.push(claudeAgentUserMessage(message));
|
|
38056
38166
|
this.activeTurnCount += 1;
|
|
38167
|
+
this.openTurnCommandIds.push(commandIds);
|
|
38057
38168
|
this.input.runtimeLogger?.info("agent_bridge_claude_message_enqueued", {
|
|
38058
38169
|
state: this.state.kind,
|
|
38059
38170
|
active_turn_count: this.activeTurnCount,
|
|
@@ -38137,7 +38248,10 @@ var ClaudeAgentBridgeSessionImpl = class {
|
|
|
38137
38248
|
this.input.writeOutput?.(
|
|
38138
38249
|
`agent_bridge_claude_deferred_flush count=${pending.length}`
|
|
38139
38250
|
);
|
|
38140
|
-
this.enqueueUserMessage(
|
|
38251
|
+
this.enqueueUserMessage(
|
|
38252
|
+
pending.map((entry) => entry.text).join("\n\n"),
|
|
38253
|
+
pending.flatMap((entry) => entry.commandIds)
|
|
38254
|
+
);
|
|
38141
38255
|
}
|
|
38142
38256
|
async interruptActiveTurnBeforeMessage() {
|
|
38143
38257
|
if (!this.hasInterruptibleTurn()) {
|
|
@@ -38804,7 +38918,8 @@ var ClaudeCodeCommandHandler = class {
|
|
|
38804
38918
|
})
|
|
38805
38919
|
);
|
|
38806
38920
|
await this.ensureAgentSession().sendMessage(message, {
|
|
38807
|
-
mode
|
|
38921
|
+
mode,
|
|
38922
|
+
commandId: delivery.commandId
|
|
38808
38923
|
});
|
|
38809
38924
|
this.input.runtimeLogger?.info(
|
|
38810
38925
|
"agent_bridge_claude_command_send_message_ready",
|
|
@@ -38859,6 +38974,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
38859
38974
|
const pending = this.pendingQuestions.get(answer.toolCallId);
|
|
38860
38975
|
if (pending) {
|
|
38861
38976
|
this.pendingQuestions.delete(answer.toolCallId);
|
|
38977
|
+
this.agentSession?.noteActiveTurnCommand(delivery.commandId);
|
|
38862
38978
|
pending.resolve({
|
|
38863
38979
|
behavior: "allow",
|
|
38864
38980
|
updatedInput: {
|
|
@@ -38885,7 +39001,9 @@ var ClaudeCodeCommandHandler = class {
|
|
|
38885
39001
|
}
|
|
38886
39002
|
}
|
|
38887
39003
|
});
|
|
38888
|
-
await this.ensureAgentSession().sendMessage(message
|
|
39004
|
+
await this.ensureAgentSession().sendMessage(message, {
|
|
39005
|
+
commandId: delivery.commandId
|
|
39006
|
+
});
|
|
38889
39007
|
this.input.writeOutput?.(
|
|
38890
39008
|
`agent_bridge_question_answer_fallback tool_use_id=${answer.toolCallId}`
|
|
38891
39009
|
);
|
|
@@ -38941,7 +39059,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
38941
39059
|
);
|
|
38942
39060
|
}
|
|
38943
39061
|
}
|
|
38944
|
-
async handleAgentMessage(message) {
|
|
39062
|
+
async handleAgentMessage(message, meta3) {
|
|
38945
39063
|
const activeContext = this.context;
|
|
38946
39064
|
if (!activeContext) {
|
|
38947
39065
|
return;
|
|
@@ -38957,7 +39075,10 @@ var ClaudeCodeCommandHandler = class {
|
|
|
38957
39075
|
return;
|
|
38958
39076
|
}
|
|
38959
39077
|
for (const projection of projections) {
|
|
38960
|
-
await this.emitBridgeOutput(
|
|
39078
|
+
await this.emitBridgeOutput(
|
|
39079
|
+
activeContext,
|
|
39080
|
+
withConsumedCommandIds(projection, meta3)
|
|
39081
|
+
);
|
|
38961
39082
|
}
|
|
38962
39083
|
}
|
|
38963
39084
|
async handleAgentError(error51) {
|
|
@@ -39025,7 +39146,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
39025
39146
|
claude: this.input.claude,
|
|
39026
39147
|
resumeAgentId: this.storedResumeAgentId(),
|
|
39027
39148
|
canUseTool: this.canUseTool,
|
|
39028
|
-
onMessage: (message) => this.handleAgentMessage(message),
|
|
39149
|
+
onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
|
|
39029
39150
|
onError: (error51) => this.handleAgentError(error51),
|
|
39030
39151
|
onExit: () => {
|
|
39031
39152
|
if (this.agentSession === session) {
|
|
@@ -39040,6 +39161,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
39040
39161
|
return session;
|
|
39041
39162
|
}
|
|
39042
39163
|
};
|
|
39164
|
+
function withConsumedCommandIds(projection, meta3) {
|
|
39165
|
+
const consumedCommandIds = meta3?.consumedCommandIds;
|
|
39166
|
+
if (!consumedCommandIds || consumedCommandIds.length === 0 || projection.type !== "ui_message_chunk" || !projection.turnStatus) {
|
|
39167
|
+
return projection;
|
|
39168
|
+
}
|
|
39169
|
+
return { ...projection, consumedCommandIds };
|
|
39170
|
+
}
|
|
39043
39171
|
function answerFallbackMessage(answer) {
|
|
39044
39172
|
const lines = Object.entries(answer.answers).map(
|
|
39045
39173
|
([question, value]) => `- ${question}: ${value}`
|