@autohq/cli 0.1.583 → 0.1.585
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 +37634 -27101
- package/dist/index.js +701 -123
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16681,13 +16681,13 @@ function parseClaudeCodeStreamRecord(parsed) {
|
|
|
16681
16681
|
}
|
|
16682
16682
|
const isError = record2.is_error === true || record2.subtype === "error";
|
|
16683
16683
|
const sdkErrorMessage = record2.errors?.map((error51) => error51.trim()).filter(Boolean).join("\n");
|
|
16684
|
-
const
|
|
16684
|
+
const errorMessage7 = isError ? record2.error ?? record2.result ?? (sdkErrorMessage || void 0) ?? "claude-code reported an error" : void 0;
|
|
16685
16685
|
const usage = claudeCodeUsageFromRecord(record2);
|
|
16686
16686
|
return {
|
|
16687
16687
|
projections: [],
|
|
16688
16688
|
result: {
|
|
16689
16689
|
isError,
|
|
16690
|
-
errorMessage:
|
|
16690
|
+
errorMessage: errorMessage7,
|
|
16691
16691
|
...usage ? { usage } : {}
|
|
16692
16692
|
}
|
|
16693
16693
|
};
|
|
@@ -16705,11 +16705,11 @@ function isClaudeCodeInterruptMarker(record2) {
|
|
|
16705
16705
|
(block) => block !== null && block.type === "text" && block.text.startsWith(CLAUDE_CODE_INTERRUPT_MARKER_PREFIX)
|
|
16706
16706
|
);
|
|
16707
16707
|
}
|
|
16708
|
-
function isClaudeCodeEdeDiagnosticOnlyError(
|
|
16709
|
-
if (!
|
|
16708
|
+
function isClaudeCodeEdeDiagnosticOnlyError(errorMessage7) {
|
|
16709
|
+
if (!errorMessage7) {
|
|
16710
16710
|
return false;
|
|
16711
16711
|
}
|
|
16712
|
-
const lines =
|
|
16712
|
+
const lines = errorMessage7.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
16713
16713
|
return lines.length > 0 && lines.every((line) => line.startsWith(CLAUDE_CODE_EDE_DIAGNOSTIC_PREFIX));
|
|
16714
16714
|
}
|
|
16715
16715
|
function isClaudeCodePermissionDenialText(text) {
|
|
@@ -17898,7 +17898,8 @@ var init_connections = __esm({
|
|
|
17898
17898
|
GithubRepositoryPickerDestinationSchema = external_exports.enum([
|
|
17899
17899
|
"settings",
|
|
17900
17900
|
"onboarding",
|
|
17901
|
-
"sessions"
|
|
17901
|
+
"sessions",
|
|
17902
|
+
"agents"
|
|
17902
17903
|
]);
|
|
17903
17904
|
GithubRepositoryPickerContinuationSchema = external_exports.object({
|
|
17904
17905
|
organizationId: OrganizationIdSchema,
|
|
@@ -88606,7 +88607,7 @@ var init_package = __esm({
|
|
|
88606
88607
|
"package.json"() {
|
|
88607
88608
|
package_default = {
|
|
88608
88609
|
name: "@autohq/cli",
|
|
88609
|
-
version: "0.1.
|
|
88610
|
+
version: "0.1.585",
|
|
88610
88611
|
license: "SEE LICENSE IN README.md",
|
|
88611
88612
|
publishConfig: {
|
|
88612
88613
|
access: "public"
|
|
@@ -92337,9 +92338,9 @@ var init_actions = __esm({
|
|
|
92337
92338
|
});
|
|
92338
92339
|
|
|
92339
92340
|
// src/commands/auth/pkce.ts
|
|
92340
|
-
import { createHash as createHash6, randomBytes as
|
|
92341
|
+
import { createHash as createHash6, randomBytes as randomBytes4 } from "crypto";
|
|
92341
92342
|
function pkceVerifier() {
|
|
92342
|
-
return
|
|
92343
|
+
return randomBytes4(32).toString("base64url");
|
|
92343
92344
|
}
|
|
92344
92345
|
function pkceChallenge(verifier) {
|
|
92345
92346
|
return createHash6("sha256").update(verifier).digest("base64url");
|
|
@@ -95904,7 +95905,7 @@ function SessionsView({
|
|
|
95904
95905
|
visibleSessions.map((session, vi) => {
|
|
95905
95906
|
const i = scrollOffset + vi;
|
|
95906
95907
|
const title = sessionDisplayTitle(session);
|
|
95907
|
-
const err = session.status === "failed" ?
|
|
95908
|
+
const err = session.status === "failed" ? errorMessage5(session) : null;
|
|
95908
95909
|
const isSelected = i === safeIndex;
|
|
95909
95910
|
const isMarked = selectedSessionIds.has(session.id);
|
|
95910
95911
|
return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
|
|
@@ -96042,7 +96043,7 @@ function truncateToWidth(value, width) {
|
|
|
96042
96043
|
function agentNameForRun(session) {
|
|
96043
96044
|
return session.snapshot.metadata.name;
|
|
96044
96045
|
}
|
|
96045
|
-
function
|
|
96046
|
+
function errorMessage5(session) {
|
|
96046
96047
|
if (session.error == null) return null;
|
|
96047
96048
|
if (typeof session.error === "string") return session.error;
|
|
96048
96049
|
const msg = readField(session.error, "message");
|
|
@@ -97477,7 +97478,7 @@ function HomeView({
|
|
|
97477
97478
|
if (inspectedResource) {
|
|
97478
97479
|
sectionTitle = `Inspect ${inspectedResource.kind}/${inspectedResource.name}`;
|
|
97479
97480
|
}
|
|
97480
|
-
const runError =
|
|
97481
|
+
const runError = errorMessage6(triggerSession.error) ?? errorMessage6(archiveSessions.error) ?? errorMessage6(unarchiveSessions.error) ?? errorMessage6(stopSessions.error);
|
|
97481
97482
|
const isRunMutationPending = triggerSession.isPending || archiveSessions.isPending || unarchiveSessions.isPending || stopSessions.isPending;
|
|
97482
97483
|
const isConnectionMutationPending = startConnection.isPending || allowConnection.isPending || removeConnection.isPending || createGithubSyncBinding.isPending;
|
|
97483
97484
|
const serviceAccountStatus = createServiceAccount2.error instanceof Error ? createServiceAccount2.error.message : rotateServiceAccount2.error instanceof Error ? rotateServiceAccount2.error.message : removeServiceAccount2.error instanceof Error ? removeServiceAccount2.error.message : serviceAccountNotice;
|
|
@@ -97890,7 +97891,7 @@ function runActionTargetLabel(sessionIds, markedRunCount) {
|
|
|
97890
97891
|
function pluralizeRunCount(count) {
|
|
97891
97892
|
return `${count} ${count === 1 ? "session" : "sessions"}`;
|
|
97892
97893
|
}
|
|
97893
|
-
function
|
|
97894
|
+
function errorMessage6(error51) {
|
|
97894
97895
|
if (error51 instanceof Error) return error51.message;
|
|
97895
97896
|
return error51 ? String(error51) : null;
|
|
97896
97897
|
}
|
|
@@ -100733,7 +100734,7 @@ function jsonRecordString(value, key) {
|
|
|
100733
100734
|
init_src();
|
|
100734
100735
|
|
|
100735
100736
|
// src/commands/agent-bridge/harness/agent-facing-auto-mcp.ts
|
|
100736
|
-
import { randomBytes as randomBytes2
|
|
100737
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
100737
100738
|
import { lstatSync, readFileSync as readFileSync3, realpathSync, statSync } from "fs";
|
|
100738
100739
|
import {
|
|
100739
100740
|
createServer as createServer3
|
|
@@ -100751,7 +100752,17 @@ import {
|
|
|
100751
100752
|
import { parseAllDocuments as parseAllDocuments2 } from "yaml";
|
|
100752
100753
|
|
|
100753
100754
|
// src/commands/agent-bridge/harness/turn-bound-mcp.ts
|
|
100755
|
+
import { timingSafeEqual } from "crypto";
|
|
100754
100756
|
var AGENT_BRIDGE_MCP_CAPABILITY_HEADER = "x-auto-agent-bridge-mcp-capability";
|
|
100757
|
+
function requestHasMcpCapability(headers, expected) {
|
|
100758
|
+
const received = headers[AGENT_BRIDGE_MCP_CAPABILITY_HEADER];
|
|
100759
|
+
if (typeof received !== "string") {
|
|
100760
|
+
return false;
|
|
100761
|
+
}
|
|
100762
|
+
const expectedBytes = Buffer.from(expected);
|
|
100763
|
+
const receivedBytes = Buffer.from(received);
|
|
100764
|
+
return expectedBytes.length === receivedBytes.length && timingSafeEqual(expectedBytes, receivedBytes);
|
|
100765
|
+
}
|
|
100755
100766
|
|
|
100756
100767
|
// src/commands/agent-bridge/harness/agent-facing-auto-mcp.ts
|
|
100757
100768
|
var MAX_DRY_RUN_PATH_FILES = 100;
|
|
@@ -101221,7 +101232,7 @@ async function startAutoMcpProxy(input) {
|
|
|
101221
101232
|
let pathsCompatible = false;
|
|
101222
101233
|
const server = createServer3(async (request, response) => {
|
|
101223
101234
|
try {
|
|
101224
|
-
if (!
|
|
101235
|
+
if (!requestHasMcpCapability(request.headers, input.capability)) {
|
|
101225
101236
|
writeResponse(
|
|
101226
101237
|
response,
|
|
101227
101238
|
401,
|
|
@@ -101427,15 +101438,6 @@ function exactActiveCommandId(activeTurnCommandIds) {
|
|
|
101427
101438
|
const commandIds = activeTurnCommandIds();
|
|
101428
101439
|
return commandIds.length === 1 ? commandIds[0] ?? null : null;
|
|
101429
101440
|
}
|
|
101430
|
-
function requestHasCapability(headers, expected) {
|
|
101431
|
-
const received = headers[AGENT_BRIDGE_MCP_CAPABILITY_HEADER];
|
|
101432
|
-
if (typeof received !== "string") {
|
|
101433
|
-
return false;
|
|
101434
|
-
}
|
|
101435
|
-
const expectedBytes = Buffer.from(expected);
|
|
101436
|
-
const receivedBytes = Buffer.from(received);
|
|
101437
|
-
return expectedBytes.length === receivedBytes.length && timingSafeEqual(expectedBytes, receivedBytes);
|
|
101438
|
-
}
|
|
101439
101441
|
function readRequestBody(request) {
|
|
101440
101442
|
return new Promise((resolveBody, reject) => {
|
|
101441
101443
|
const chunks = [];
|
|
@@ -101468,6 +101470,384 @@ function isRecord2(value) {
|
|
|
101468
101470
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
101469
101471
|
}
|
|
101470
101472
|
|
|
101473
|
+
// src/commands/agent-bridge/harness/ask-user-projection.ts
|
|
101474
|
+
init_src();
|
|
101475
|
+
var ASK_USER_MCP_SERVER_NAME = "user";
|
|
101476
|
+
var ASK_USER_MCP_TOOL_NAME = "ask_question";
|
|
101477
|
+
var ASK_USER_TOOL_NAME = `${ASK_USER_MCP_SERVER_NAME}.${ASK_USER_MCP_TOOL_NAME}`;
|
|
101478
|
+
var CLAUDE_ASK_USER_TOOL_NAME = `mcp__${ASK_USER_MCP_SERVER_NAME}__${ASK_USER_MCP_TOOL_NAME}`;
|
|
101479
|
+
function isAskUserMcpTool(server, tool) {
|
|
101480
|
+
return server === ASK_USER_MCP_SERVER_NAME && tool === ASK_USER_MCP_TOOL_NAME;
|
|
101481
|
+
}
|
|
101482
|
+
function projectAskUserQuestion(input) {
|
|
101483
|
+
return [
|
|
101484
|
+
{
|
|
101485
|
+
type: "entry",
|
|
101486
|
+
entry: {
|
|
101487
|
+
role: "assistant",
|
|
101488
|
+
kind: "question",
|
|
101489
|
+
turnStatus: "waiting_for_input",
|
|
101490
|
+
content: {
|
|
101491
|
+
parts: [
|
|
101492
|
+
{
|
|
101493
|
+
type: "question",
|
|
101494
|
+
toolCallId: input.id,
|
|
101495
|
+
questions: input.questions
|
|
101496
|
+
}
|
|
101497
|
+
]
|
|
101498
|
+
}
|
|
101499
|
+
}
|
|
101500
|
+
},
|
|
101501
|
+
{
|
|
101502
|
+
type: "ui_message_chunk",
|
|
101503
|
+
chunk: {
|
|
101504
|
+
type: "tool-input-available",
|
|
101505
|
+
toolCallId: input.id,
|
|
101506
|
+
toolName: ASK_USER_TOOL_NAME,
|
|
101507
|
+
input: { questions: input.questions }
|
|
101508
|
+
},
|
|
101509
|
+
turnStatus: "waiting_for_input"
|
|
101510
|
+
}
|
|
101511
|
+
];
|
|
101512
|
+
}
|
|
101513
|
+
function projectAskUserAnswer(answer) {
|
|
101514
|
+
return {
|
|
101515
|
+
type: "ui_message_chunk",
|
|
101516
|
+
chunk: {
|
|
101517
|
+
type: "tool-output-available",
|
|
101518
|
+
toolCallId: answer.toolCallId || UNKNOWN_MESSAGE_ID,
|
|
101519
|
+
output: toJsonValue({
|
|
101520
|
+
answers: answer.answers,
|
|
101521
|
+
...answer.response ? { response: answer.response } : {}
|
|
101522
|
+
})
|
|
101523
|
+
}
|
|
101524
|
+
};
|
|
101525
|
+
}
|
|
101526
|
+
|
|
101527
|
+
// src/commands/agent-bridge/harness/ask-user-server.ts
|
|
101528
|
+
init_src();
|
|
101529
|
+
init_zod();
|
|
101530
|
+
import { randomBytes as randomBytes3, randomUUID } from "crypto";
|
|
101531
|
+
import {
|
|
101532
|
+
createServer as createServer4
|
|
101533
|
+
} from "http";
|
|
101534
|
+
import { Server as McpProtocolServer } from "@modelcontextprotocol/sdk/server/index.js";
|
|
101535
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
101536
|
+
import {
|
|
101537
|
+
CallToolRequestSchema as CallToolRequestSchema2,
|
|
101538
|
+
ListToolsRequestSchema as ListToolsRequestSchema2
|
|
101539
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
101540
|
+
var ASK_USER_PROGRESS_INTERVAL_MS = 3e4;
|
|
101541
|
+
var ASK_USER_CALL_DEADLINE_MS = 84e4;
|
|
101542
|
+
var ASK_USER_FALLBACK_MESSAGE = "The question remains pending for the user. Continue this turn; the answer will arrive as a user message.";
|
|
101543
|
+
var AuthoredQuestionSchema = ConversationQuestionSchema.extend({
|
|
101544
|
+
question: external_exports.string().trim().min(1).max(1024),
|
|
101545
|
+
header: external_exports.string().trim().min(1).max(64),
|
|
101546
|
+
options: external_exports.array(
|
|
101547
|
+
external_exports.object({
|
|
101548
|
+
label: external_exports.string().trim().min(1).max(128),
|
|
101549
|
+
description: external_exports.string().trim().max(512)
|
|
101550
|
+
}).strict()
|
|
101551
|
+
).min(2).max(6)
|
|
101552
|
+
}).strict();
|
|
101553
|
+
var AskUserQuestionInputSchema2 = external_exports.object({
|
|
101554
|
+
questions: external_exports.array(AuthoredQuestionSchema).min(1).max(4)
|
|
101555
|
+
}).strict();
|
|
101556
|
+
var AskUserQuestionRegistry = class {
|
|
101557
|
+
pending = /* @__PURE__ */ new Map();
|
|
101558
|
+
deadlineMs;
|
|
101559
|
+
progressIntervalMs;
|
|
101560
|
+
constructor(options = {}) {
|
|
101561
|
+
this.deadlineMs = positiveDuration(
|
|
101562
|
+
options.deadlineMs ?? ASK_USER_CALL_DEADLINE_MS,
|
|
101563
|
+
"ask-user deadline"
|
|
101564
|
+
);
|
|
101565
|
+
this.progressIntervalMs = positiveDuration(
|
|
101566
|
+
options.progressIntervalMs ?? ASK_USER_PROGRESS_INTERVAL_MS,
|
|
101567
|
+
"ask-user progress interval"
|
|
101568
|
+
);
|
|
101569
|
+
}
|
|
101570
|
+
get size() {
|
|
101571
|
+
return this.pending.size;
|
|
101572
|
+
}
|
|
101573
|
+
has(id) {
|
|
101574
|
+
return this.pending.has(id);
|
|
101575
|
+
}
|
|
101576
|
+
park(input) {
|
|
101577
|
+
const { questions } = AskUserQuestionInputSchema2.parse({
|
|
101578
|
+
questions: input.questions
|
|
101579
|
+
});
|
|
101580
|
+
const id = `q_${randomUUID()}`;
|
|
101581
|
+
let resolveWait = () => {
|
|
101582
|
+
};
|
|
101583
|
+
const wait = new Promise((resolve6) => {
|
|
101584
|
+
resolveWait = resolve6;
|
|
101585
|
+
});
|
|
101586
|
+
const progress = setInterval(() => {
|
|
101587
|
+
try {
|
|
101588
|
+
void Promise.resolve(input.onProgress?.()).catch(() => {
|
|
101589
|
+
});
|
|
101590
|
+
} catch {
|
|
101591
|
+
}
|
|
101592
|
+
}, this.progressIntervalMs);
|
|
101593
|
+
const deadline = setTimeout(() => {
|
|
101594
|
+
this.settle(id, {
|
|
101595
|
+
kind: "fallback",
|
|
101596
|
+
message: ASK_USER_FALLBACK_MESSAGE,
|
|
101597
|
+
reason: "deadline"
|
|
101598
|
+
});
|
|
101599
|
+
}, this.deadlineMs);
|
|
101600
|
+
this.pending.set(id, {
|
|
101601
|
+
id,
|
|
101602
|
+
questions,
|
|
101603
|
+
deadline,
|
|
101604
|
+
progress,
|
|
101605
|
+
resolve: resolveWait,
|
|
101606
|
+
onSettled: input.onSettled
|
|
101607
|
+
});
|
|
101608
|
+
return { id, wait };
|
|
101609
|
+
}
|
|
101610
|
+
answer(id, answer) {
|
|
101611
|
+
if (answer.toolCallId !== id) {
|
|
101612
|
+
return false;
|
|
101613
|
+
}
|
|
101614
|
+
return this.settle(id, { kind: "answered", answer });
|
|
101615
|
+
}
|
|
101616
|
+
quarantine(id, reason) {
|
|
101617
|
+
return this.settle(id, {
|
|
101618
|
+
kind: "fallback",
|
|
101619
|
+
message: ASK_USER_FALLBACK_MESSAGE,
|
|
101620
|
+
reason
|
|
101621
|
+
});
|
|
101622
|
+
}
|
|
101623
|
+
quarantineAll(reason) {
|
|
101624
|
+
let settled = 0;
|
|
101625
|
+
for (const id of [...this.pending.keys()]) {
|
|
101626
|
+
if (this.quarantine(id, reason)) {
|
|
101627
|
+
settled += 1;
|
|
101628
|
+
}
|
|
101629
|
+
}
|
|
101630
|
+
return settled;
|
|
101631
|
+
}
|
|
101632
|
+
settle(id, settlement) {
|
|
101633
|
+
const pending = this.pending.get(id);
|
|
101634
|
+
if (!pending || !this.pending.delete(id)) {
|
|
101635
|
+
return false;
|
|
101636
|
+
}
|
|
101637
|
+
clearTimeout(pending.deadline);
|
|
101638
|
+
clearInterval(pending.progress);
|
|
101639
|
+
pending.resolve(settlement);
|
|
101640
|
+
try {
|
|
101641
|
+
pending.onSettled?.(settlement);
|
|
101642
|
+
} catch {
|
|
101643
|
+
}
|
|
101644
|
+
return true;
|
|
101645
|
+
}
|
|
101646
|
+
};
|
|
101647
|
+
var AskUserServer = class {
|
|
101648
|
+
constructor(options) {
|
|
101649
|
+
this.options = options;
|
|
101650
|
+
this.registry = new AskUserQuestionRegistry(options);
|
|
101651
|
+
}
|
|
101652
|
+
options;
|
|
101653
|
+
registry;
|
|
101654
|
+
path = `/mcp/${randomBytes3(24).toString("base64url")}`;
|
|
101655
|
+
capability = randomBytes3(32).toString("base64url");
|
|
101656
|
+
server = null;
|
|
101657
|
+
prepared = null;
|
|
101658
|
+
prepare() {
|
|
101659
|
+
this.prepared ??= this.prepareOnce();
|
|
101660
|
+
return this.prepared;
|
|
101661
|
+
}
|
|
101662
|
+
answer(answer) {
|
|
101663
|
+
return this.registry.answer(answer.toolCallId, answer);
|
|
101664
|
+
}
|
|
101665
|
+
quarantineAll(reason) {
|
|
101666
|
+
return this.registry.quarantineAll(reason);
|
|
101667
|
+
}
|
|
101668
|
+
close() {
|
|
101669
|
+
this.quarantineAll("harness shutdown");
|
|
101670
|
+
this.server?.close();
|
|
101671
|
+
this.server = null;
|
|
101672
|
+
}
|
|
101673
|
+
async prepareOnce() {
|
|
101674
|
+
const server = createServer4((request, response) => {
|
|
101675
|
+
void this.handleRequest(request, response);
|
|
101676
|
+
});
|
|
101677
|
+
this.server = server;
|
|
101678
|
+
await new Promise((resolve6, reject) => {
|
|
101679
|
+
server.once("error", reject);
|
|
101680
|
+
server.listen(0, "127.0.0.1", () => {
|
|
101681
|
+
server.off("error", reject);
|
|
101682
|
+
resolve6();
|
|
101683
|
+
});
|
|
101684
|
+
});
|
|
101685
|
+
const address = server.address();
|
|
101686
|
+
if (!address || typeof address === "string") {
|
|
101687
|
+
server.close();
|
|
101688
|
+
throw new Error("ask-user MCP server did not receive a TCP address");
|
|
101689
|
+
}
|
|
101690
|
+
server.unref();
|
|
101691
|
+
return {
|
|
101692
|
+
url: `http://127.0.0.1:${address.port}${this.path}`,
|
|
101693
|
+
headers: {
|
|
101694
|
+
[AGENT_BRIDGE_MCP_CAPABILITY_HEADER]: this.capability
|
|
101695
|
+
}
|
|
101696
|
+
};
|
|
101697
|
+
}
|
|
101698
|
+
async handleRequest(request, response) {
|
|
101699
|
+
if (request.url !== this.path || request.method !== "POST") {
|
|
101700
|
+
response.writeHead(request.url === this.path ? 405 : 404).end();
|
|
101701
|
+
return;
|
|
101702
|
+
}
|
|
101703
|
+
if (!requestHasMcpCapability(request.headers, this.capability)) {
|
|
101704
|
+
response.writeHead(401, { "content-type": "application/json" }).end(JSON.stringify({ error: "Invalid ask-user MCP capability" }));
|
|
101705
|
+
return;
|
|
101706
|
+
}
|
|
101707
|
+
try {
|
|
101708
|
+
await this.handleMcpRequest(request, response);
|
|
101709
|
+
} catch (error51) {
|
|
101710
|
+
this.options.writeOutput?.(
|
|
101711
|
+
`agent_bridge_ask_user_http_error error=${errorMessage2(error51)}`
|
|
101712
|
+
);
|
|
101713
|
+
if (!response.headersSent) {
|
|
101714
|
+
response.writeHead(500, { "content-type": "application/json" });
|
|
101715
|
+
response.end(
|
|
101716
|
+
JSON.stringify({
|
|
101717
|
+
jsonrpc: "2.0",
|
|
101718
|
+
id: null,
|
|
101719
|
+
error: { code: -32603, message: "Ask-user server failed" }
|
|
101720
|
+
})
|
|
101721
|
+
);
|
|
101722
|
+
}
|
|
101723
|
+
}
|
|
101724
|
+
}
|
|
101725
|
+
async handleMcpRequest(request, response) {
|
|
101726
|
+
const body = await readJsonRequest(request);
|
|
101727
|
+
this.options.writeOutput?.(
|
|
101728
|
+
`agent_bridge_ask_user_mcp_request method=${typeof body.method === "string" ? body.method : "unknown"}`
|
|
101729
|
+
);
|
|
101730
|
+
const server = this.createMcpServer();
|
|
101731
|
+
const transport = new StreamableHTTPServerTransport({
|
|
101732
|
+
sessionIdGenerator: void 0,
|
|
101733
|
+
// Codex 0.145.0 requires ordinary initialize/list responses as JSON. A
|
|
101734
|
+
// parked tool call keeps SSE enabled so progress notifications can flow
|
|
101735
|
+
// over the held response without extending the hard client deadline.
|
|
101736
|
+
enableJsonResponse: body.method !== "tools/call"
|
|
101737
|
+
});
|
|
101738
|
+
response.once("close", () => {
|
|
101739
|
+
void transport.close();
|
|
101740
|
+
void server.close();
|
|
101741
|
+
});
|
|
101742
|
+
await server.connect(transport);
|
|
101743
|
+
await transport.handleRequest(request, response, body);
|
|
101744
|
+
}
|
|
101745
|
+
createMcpServer() {
|
|
101746
|
+
const server = new McpProtocolServer(
|
|
101747
|
+
{ name: "auto-ask-user", version: "1.0.0" },
|
|
101748
|
+
{ capabilities: { tools: {} } }
|
|
101749
|
+
);
|
|
101750
|
+
server.setRequestHandler(ListToolsRequestSchema2, () => ({
|
|
101751
|
+
tools: [
|
|
101752
|
+
{
|
|
101753
|
+
name: ASK_USER_MCP_TOOL_NAME,
|
|
101754
|
+
title: ASK_USER_TOOL_NAME,
|
|
101755
|
+
description: "Ask the user one to four blocking questions and wait for their answer.",
|
|
101756
|
+
inputSchema: external_exports.toJSONSchema(AskUserQuestionInputSchema2)
|
|
101757
|
+
}
|
|
101758
|
+
]
|
|
101759
|
+
}));
|
|
101760
|
+
server.setRequestHandler(
|
|
101761
|
+
CallToolRequestSchema2,
|
|
101762
|
+
async (request, extra) => {
|
|
101763
|
+
if (request.params.name !== ASK_USER_MCP_TOOL_NAME) {
|
|
101764
|
+
throw new Error(`Unknown ask-user tool: ${request.params.name}`);
|
|
101765
|
+
}
|
|
101766
|
+
const { questions } = AskUserQuestionInputSchema2.parse(
|
|
101767
|
+
request.params.arguments
|
|
101768
|
+
);
|
|
101769
|
+
let questionId = "";
|
|
101770
|
+
const parked = this.registry.park({
|
|
101771
|
+
questions,
|
|
101772
|
+
onProgress: async () => {
|
|
101773
|
+
const progressToken = extra._meta?.progressToken;
|
|
101774
|
+
if (progressToken === void 0) {
|
|
101775
|
+
return;
|
|
101776
|
+
}
|
|
101777
|
+
await extra.sendNotification({
|
|
101778
|
+
method: "notifications/progress",
|
|
101779
|
+
params: {
|
|
101780
|
+
progressToken,
|
|
101781
|
+
progress: Date.now(),
|
|
101782
|
+
message: "Waiting for the user to answer"
|
|
101783
|
+
}
|
|
101784
|
+
});
|
|
101785
|
+
},
|
|
101786
|
+
onSettled: (settlement2) => {
|
|
101787
|
+
this.options.onQuestionSettled?.({ id: questionId, settlement: settlement2 });
|
|
101788
|
+
}
|
|
101789
|
+
});
|
|
101790
|
+
questionId = parked.id;
|
|
101791
|
+
try {
|
|
101792
|
+
await this.options.onQuestionPending({
|
|
101793
|
+
id: parked.id,
|
|
101794
|
+
questions
|
|
101795
|
+
});
|
|
101796
|
+
} catch (error51) {
|
|
101797
|
+
this.registry.quarantine(parked.id, "question projection failed");
|
|
101798
|
+
throw error51;
|
|
101799
|
+
}
|
|
101800
|
+
const settlement = await parked.wait;
|
|
101801
|
+
return settlementResult(settlement);
|
|
101802
|
+
}
|
|
101803
|
+
);
|
|
101804
|
+
return server;
|
|
101805
|
+
}
|
|
101806
|
+
};
|
|
101807
|
+
function settlementResult(settlement) {
|
|
101808
|
+
if (settlement.kind === "fallback") {
|
|
101809
|
+
return {
|
|
101810
|
+
content: [{ type: "text", text: settlement.message }]
|
|
101811
|
+
};
|
|
101812
|
+
}
|
|
101813
|
+
const answer = settlement.answer;
|
|
101814
|
+
const lines = Object.entries(answer.answers).map(
|
|
101815
|
+
([question, value]) => `- ${question}: ${value}`
|
|
101816
|
+
);
|
|
101817
|
+
return {
|
|
101818
|
+
content: [
|
|
101819
|
+
{
|
|
101820
|
+
type: "text",
|
|
101821
|
+
text: [
|
|
101822
|
+
"The user answered your questions:",
|
|
101823
|
+
...lines,
|
|
101824
|
+
...answer.response ? [`The user also responded: ${answer.response}`] : []
|
|
101825
|
+
].join("\n")
|
|
101826
|
+
}
|
|
101827
|
+
]
|
|
101828
|
+
};
|
|
101829
|
+
}
|
|
101830
|
+
function positiveDuration(value, label) {
|
|
101831
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
101832
|
+
throw new Error(`${label} must be a positive safe integer`);
|
|
101833
|
+
}
|
|
101834
|
+
return value;
|
|
101835
|
+
}
|
|
101836
|
+
function errorMessage2(error51) {
|
|
101837
|
+
return error51 instanceof Error ? error51.message : String(error51);
|
|
101838
|
+
}
|
|
101839
|
+
async function readJsonRequest(request) {
|
|
101840
|
+
const chunks = [];
|
|
101841
|
+
for await (const chunk of request) {
|
|
101842
|
+
chunks.push(Buffer.from(chunk));
|
|
101843
|
+
}
|
|
101844
|
+
const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
101845
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
101846
|
+
throw new Error("ask-user MCP request body must be a JSON object");
|
|
101847
|
+
}
|
|
101848
|
+
return parsed;
|
|
101849
|
+
}
|
|
101850
|
+
|
|
101471
101851
|
// src/commands/agent-bridge/harness/liveness-ticker.ts
|
|
101472
101852
|
var RUNTIME_LIVENESS_INTERVAL_MS = 2e4;
|
|
101473
101853
|
function startRuntimeLivenessTicker(input) {
|
|
@@ -102597,7 +102977,7 @@ function isTerminalUiMessageChunk(chunk) {
|
|
|
102597
102977
|
function legacyToolEntries(chunk) {
|
|
102598
102978
|
switch (chunk.type) {
|
|
102599
102979
|
case "tool-input-available":
|
|
102600
|
-
if (chunk.toolName === ASK_USER_QUESTION_TOOL_NAME) {
|
|
102980
|
+
if (chunk.toolName === ASK_USER_QUESTION_TOOL_NAME || chunk.toolName === ASK_USER_TOOL_NAME) {
|
|
102601
102981
|
return [];
|
|
102602
102982
|
}
|
|
102603
102983
|
return [
|
|
@@ -102921,6 +103301,111 @@ function jsonRecordString2(value, key) {
|
|
|
102921
103301
|
return typeof field === "string" ? field : void 0;
|
|
102922
103302
|
}
|
|
102923
103303
|
|
|
103304
|
+
// src/commands/agent-bridge/harness/mcp-timeout.ts
|
|
103305
|
+
var HARNESS_MCP_TOOL_TIMEOUT_SECONDS = 900;
|
|
103306
|
+
var MAX_HARNESS_MCP_TOOL_TIMEOUT_SECONDS = 3600;
|
|
103307
|
+
function validatedMcpToolTimeoutSeconds(value) {
|
|
103308
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_HARNESS_MCP_TOOL_TIMEOUT_SECONDS) {
|
|
103309
|
+
throw new Error(
|
|
103310
|
+
`MCP tool timeout must be a safe integer from 1 to ${MAX_HARNESS_MCP_TOOL_TIMEOUT_SECONDS} seconds`
|
|
103311
|
+
);
|
|
103312
|
+
}
|
|
103313
|
+
return value;
|
|
103314
|
+
}
|
|
103315
|
+
function validatedMcpToolTimeoutMilliseconds(value) {
|
|
103316
|
+
return validatedMcpToolTimeoutSeconds(value) * 1e3;
|
|
103317
|
+
}
|
|
103318
|
+
|
|
103319
|
+
// src/commands/agent-bridge/harness/claude-code/options.ts
|
|
103320
|
+
var CLAUDE_AGENT_SDK_CLIENT_APP = "auto-agent-bridge";
|
|
103321
|
+
var CLAUDE_RUNTIME_PROCESS_ENV_KEYS = ["PATH", "HOME"];
|
|
103322
|
+
var CLAUDE_CODE_EXECUTABLE_PATH = "/usr/local/bin/claude";
|
|
103323
|
+
var CLAUDE_CODE_SHELL_PATH = "/bin/bash";
|
|
103324
|
+
var CLAUDE_CODE_DEFAULT_MODEL = "claude-opus-4-8";
|
|
103325
|
+
function claudeAgentOptions(config2, input = {}) {
|
|
103326
|
+
return {
|
|
103327
|
+
...config2.cwd ? { cwd: config2.cwd } : {},
|
|
103328
|
+
...input.resume ? { resume: input.resume } : {},
|
|
103329
|
+
env: claudeProcessEnv(
|
|
103330
|
+
config2.env,
|
|
103331
|
+
input.clientApp ?? CLAUDE_AGENT_SDK_CLIENT_APP
|
|
103332
|
+
),
|
|
103333
|
+
includePartialMessages: true,
|
|
103334
|
+
thinking: { type: "adaptive", display: "summarized" },
|
|
103335
|
+
settings: { showThinkingSummaries: true },
|
|
103336
|
+
model: config2.model?.id ?? CLAUDE_CODE_DEFAULT_MODEL,
|
|
103337
|
+
...config2.reasoningEffort ? { effort: config2.reasoningEffort } : {},
|
|
103338
|
+
permissionMode: "bypassPermissions",
|
|
103339
|
+
allowDangerouslySkipPermissions: true,
|
|
103340
|
+
pathToClaudeCodeExecutable: claudeCodeExecutablePath(),
|
|
103341
|
+
...input.mcpServers ?? config2.mcpServers ? {
|
|
103342
|
+
mcpServers: input.mcpServers ?? config2.mcpServers,
|
|
103343
|
+
strictMcpConfig: true
|
|
103344
|
+
} : {},
|
|
103345
|
+
systemPrompt: {
|
|
103346
|
+
type: "preset",
|
|
103347
|
+
preset: "claude_code",
|
|
103348
|
+
...config2.systemPromptAppend ? { append: config2.systemPromptAppend } : {}
|
|
103349
|
+
},
|
|
103350
|
+
settingSources: [],
|
|
103351
|
+
tools: {
|
|
103352
|
+
type: "preset",
|
|
103353
|
+
preset: "claude_code"
|
|
103354
|
+
},
|
|
103355
|
+
stderr: input.onStderrChunk ?? (() => {
|
|
103356
|
+
})
|
|
103357
|
+
};
|
|
103358
|
+
}
|
|
103359
|
+
function withClaudeAskUserMcpServer(mcpServers, url2, headers) {
|
|
103360
|
+
if (mcpServers?.[ASK_USER_MCP_SERVER_NAME]) {
|
|
103361
|
+
throw new Error(
|
|
103362
|
+
`MCP server name ${ASK_USER_MCP_SERVER_NAME} is reserved by the harness`
|
|
103363
|
+
);
|
|
103364
|
+
}
|
|
103365
|
+
return {
|
|
103366
|
+
...mcpServers,
|
|
103367
|
+
[ASK_USER_MCP_SERVER_NAME]: {
|
|
103368
|
+
type: "http",
|
|
103369
|
+
url: url2,
|
|
103370
|
+
headers,
|
|
103371
|
+
timeout: validatedMcpToolTimeoutMilliseconds(
|
|
103372
|
+
HARNESS_MCP_TOOL_TIMEOUT_SECONDS
|
|
103373
|
+
)
|
|
103374
|
+
}
|
|
103375
|
+
};
|
|
103376
|
+
}
|
|
103377
|
+
function claudeProcessEnv(env, clientApp) {
|
|
103378
|
+
const runtimeEnv = runtimeProcessEnv();
|
|
103379
|
+
return {
|
|
103380
|
+
// Claude Code only needs ambient shell basics from the bridge process.
|
|
103381
|
+
// Dynamic Claude/MCP/session secrets arrive through encrypted bootstrap env.
|
|
103382
|
+
...runtimeEnv,
|
|
103383
|
+
...env,
|
|
103384
|
+
// Claude Code auto-detects a shell when this is absent. Hosted sandboxes run
|
|
103385
|
+
// Bash tool commands, so pin the shell snapshot source to bash instead of
|
|
103386
|
+
// letting zsh profile functions leak into bash snapshots and inherit user
|
|
103387
|
+
// strict-mode options such as `set -u`.
|
|
103388
|
+
CLAUDE_CODE_SHELL: CLAUDE_CODE_SHELL_PATH,
|
|
103389
|
+
CLAUDE_AGENT_SDK_CLIENT_APP: clientApp
|
|
103390
|
+
};
|
|
103391
|
+
}
|
|
103392
|
+
function runtimeProcessEnv() {
|
|
103393
|
+
const selected = {};
|
|
103394
|
+
for (const key of CLAUDE_RUNTIME_PROCESS_ENV_KEYS) {
|
|
103395
|
+
const value = process.env[key];
|
|
103396
|
+
if (value !== void 0) {
|
|
103397
|
+
selected[key] = value;
|
|
103398
|
+
}
|
|
103399
|
+
}
|
|
103400
|
+
return selected;
|
|
103401
|
+
}
|
|
103402
|
+
function claudeCodeExecutablePath() {
|
|
103403
|
+
if (process.env.AUTO_AGENT_BRIDGE_TEST_CLAUDE_COMMAND === "1" && process.env.AUTO_CLAUDE_CODE_COMMAND?.trim()) {
|
|
103404
|
+
return process.env.AUTO_CLAUDE_CODE_COMMAND.trim();
|
|
103405
|
+
}
|
|
103406
|
+
return CLAUDE_CODE_EXECUTABLE_PATH;
|
|
103407
|
+
}
|
|
103408
|
+
|
|
102924
103409
|
// src/commands/agent-bridge/harness/claude-code/projector.ts
|
|
102925
103410
|
init_src();
|
|
102926
103411
|
var ClaudeCodeProjector = class {
|
|
@@ -102939,6 +103424,7 @@ var ClaudeCodeProjector = class {
|
|
|
102939
103424
|
activeResponseMessageId = null;
|
|
102940
103425
|
activeParts = /* @__PURE__ */ new Map();
|
|
102941
103426
|
activeToolInputs = /* @__PURE__ */ new Map();
|
|
103427
|
+
suppressedAskUserToolCallIds = /* @__PURE__ */ new Set();
|
|
102942
103428
|
streamedMessageIds = /* @__PURE__ */ new Set();
|
|
102943
103429
|
// The SDK's "[Request interrupted by user]" transcript marker was seen since
|
|
102944
103430
|
// the last terminal result: the very next diagnostic-only
|
|
@@ -102958,6 +103444,7 @@ var ClaudeCodeProjector = class {
|
|
|
102958
103444
|
bridge: context.bridgeInterruptSettling === true
|
|
102959
103445
|
};
|
|
102960
103446
|
const parsed = parseClaudeCodeStreamRecord(message);
|
|
103447
|
+
parsed.projections = this.suppressAskUserProjections(parsed.projections);
|
|
102961
103448
|
const snapshotMessageId = assistantSnapshotMessageId(message);
|
|
102962
103449
|
const suppressStreamed = snapshotMessageId !== null && this.streamedMessageIds.has(snapshotMessageId);
|
|
102963
103450
|
if (message.type === "assistant" && !suppressStreamed) {
|
|
@@ -102990,6 +103477,7 @@ var ClaudeCodeProjector = class {
|
|
|
102990
103477
|
);
|
|
102991
103478
|
}
|
|
102992
103479
|
outputs.push(projectClaudeCodeResult(parsed.result, { interrupted }));
|
|
103480
|
+
this.suppressedAskUserToolCallIds.clear();
|
|
102993
103481
|
this.interruptMarkerSeen = false;
|
|
102994
103482
|
}
|
|
102995
103483
|
return outputs;
|
|
@@ -103074,6 +103562,11 @@ var ClaudeCodeProjector = class {
|
|
|
103074
103562
|
return [uiChunk({ type: `${type}-end`, id })];
|
|
103075
103563
|
}
|
|
103076
103564
|
startToolInput(message) {
|
|
103565
|
+
const askUserToolCallId = askUserMcpToolCallId(message);
|
|
103566
|
+
if (askUserToolCallId) {
|
|
103567
|
+
this.suppressedAskUserToolCallIds.add(askUserToolCallId);
|
|
103568
|
+
return [];
|
|
103569
|
+
}
|
|
103077
103570
|
const started = toolInputStartFromEvent(message);
|
|
103078
103571
|
if (!started) {
|
|
103079
103572
|
return [];
|
|
@@ -103092,6 +103585,32 @@ var ClaudeCodeProjector = class {
|
|
|
103092
103585
|
})
|
|
103093
103586
|
];
|
|
103094
103587
|
}
|
|
103588
|
+
suppressAskUserProjections(projections) {
|
|
103589
|
+
return projections.flatMap((projection) => {
|
|
103590
|
+
if (projection.kind === "tool_call") {
|
|
103591
|
+
const askUserParts = projection.content.parts.filter(
|
|
103592
|
+
(part) => part.type === "tool_call" && (part.name === ASK_USER_TOOL_NAME || part.name === CLAUDE_ASK_USER_TOOL_NAME)
|
|
103593
|
+
);
|
|
103594
|
+
for (const part of askUserParts) {
|
|
103595
|
+
if (part.type === "tool_call" && part.toolCallId) {
|
|
103596
|
+
this.suppressedAskUserToolCallIds.add(part.toolCallId);
|
|
103597
|
+
}
|
|
103598
|
+
}
|
|
103599
|
+
if (askUserParts.length > 0) {
|
|
103600
|
+
return [];
|
|
103601
|
+
}
|
|
103602
|
+
}
|
|
103603
|
+
if (projection.kind === "tool_result") {
|
|
103604
|
+
const suppressed = projection.content.parts.some(
|
|
103605
|
+
(part) => part.type === "tool_result" && part.toolUseId !== null && this.suppressedAskUserToolCallIds.has(part.toolUseId)
|
|
103606
|
+
);
|
|
103607
|
+
if (suppressed) {
|
|
103608
|
+
return [];
|
|
103609
|
+
}
|
|
103610
|
+
}
|
|
103611
|
+
return [projection];
|
|
103612
|
+
});
|
|
103613
|
+
}
|
|
103095
103614
|
finishActiveToolInput(index) {
|
|
103096
103615
|
const active = this.activeToolInputs.get(index);
|
|
103097
103616
|
if (!active) {
|
|
@@ -103288,6 +103807,17 @@ function toolInputStartFromEvent(message) {
|
|
|
103288
103807
|
input: contentBlock.input
|
|
103289
103808
|
};
|
|
103290
103809
|
}
|
|
103810
|
+
function askUserMcpToolCallId(message) {
|
|
103811
|
+
const event = message.event;
|
|
103812
|
+
if (event.type !== "content_block_start") {
|
|
103813
|
+
return null;
|
|
103814
|
+
}
|
|
103815
|
+
const block = event.content_block;
|
|
103816
|
+
if (block.type !== "mcp_tool_use" || typeof block.id !== "string" || typeof block.server_name !== "string" || typeof block.name !== "string" || !isAskUserMcpTool(block.server_name, block.name)) {
|
|
103817
|
+
return null;
|
|
103818
|
+
}
|
|
103819
|
+
return block.id;
|
|
103820
|
+
}
|
|
103291
103821
|
function toolInputDeltaFromDelta(delta) {
|
|
103292
103822
|
if (delta.type !== "input_json_delta") {
|
|
103293
103823
|
return null;
|
|
@@ -103808,78 +104338,6 @@ function serverStatusList(servers, context) {
|
|
|
103808
104338
|
return reported.map((server) => `${server.name}:${server.status}`).join(",");
|
|
103809
104339
|
}
|
|
103810
104340
|
|
|
103811
|
-
// src/commands/agent-bridge/harness/claude-code/options.ts
|
|
103812
|
-
var CLAUDE_AGENT_SDK_CLIENT_APP = "auto-agent-bridge";
|
|
103813
|
-
var CLAUDE_RUNTIME_PROCESS_ENV_KEYS = ["PATH", "HOME"];
|
|
103814
|
-
var CLAUDE_CODE_EXECUTABLE_PATH = "/usr/local/bin/claude";
|
|
103815
|
-
var CLAUDE_CODE_SHELL_PATH = "/bin/bash";
|
|
103816
|
-
var CLAUDE_CODE_DEFAULT_MODEL = "claude-opus-4-8";
|
|
103817
|
-
function claudeAgentOptions(config2, input = {}) {
|
|
103818
|
-
return {
|
|
103819
|
-
...config2.cwd ? { cwd: config2.cwd } : {},
|
|
103820
|
-
...input.resume ? { resume: input.resume } : {},
|
|
103821
|
-
env: claudeProcessEnv(
|
|
103822
|
-
config2.env,
|
|
103823
|
-
input.clientApp ?? CLAUDE_AGENT_SDK_CLIENT_APP
|
|
103824
|
-
),
|
|
103825
|
-
includePartialMessages: true,
|
|
103826
|
-
thinking: { type: "adaptive", display: "summarized" },
|
|
103827
|
-
settings: { showThinkingSummaries: true },
|
|
103828
|
-
model: config2.model?.id ?? CLAUDE_CODE_DEFAULT_MODEL,
|
|
103829
|
-
...config2.reasoningEffort ? { effort: config2.reasoningEffort } : {},
|
|
103830
|
-
permissionMode: "bypassPermissions",
|
|
103831
|
-
allowDangerouslySkipPermissions: true,
|
|
103832
|
-
pathToClaudeCodeExecutable: claudeCodeExecutablePath(),
|
|
103833
|
-
...input.mcpServers ?? config2.mcpServers ? {
|
|
103834
|
-
mcpServers: input.mcpServers ?? config2.mcpServers,
|
|
103835
|
-
strictMcpConfig: true
|
|
103836
|
-
} : {},
|
|
103837
|
-
systemPrompt: {
|
|
103838
|
-
type: "preset",
|
|
103839
|
-
preset: "claude_code",
|
|
103840
|
-
...config2.systemPromptAppend ? { append: config2.systemPromptAppend } : {}
|
|
103841
|
-
},
|
|
103842
|
-
settingSources: [],
|
|
103843
|
-
tools: {
|
|
103844
|
-
type: "preset",
|
|
103845
|
-
preset: "claude_code"
|
|
103846
|
-
},
|
|
103847
|
-
stderr: input.onStderrChunk ?? (() => {
|
|
103848
|
-
})
|
|
103849
|
-
};
|
|
103850
|
-
}
|
|
103851
|
-
function claudeProcessEnv(env, clientApp) {
|
|
103852
|
-
const runtimeEnv = runtimeProcessEnv();
|
|
103853
|
-
return {
|
|
103854
|
-
// Claude Code only needs ambient shell basics from the bridge process.
|
|
103855
|
-
// Dynamic Claude/MCP/session secrets arrive through encrypted bootstrap env.
|
|
103856
|
-
...runtimeEnv,
|
|
103857
|
-
...env,
|
|
103858
|
-
// Claude Code auto-detects a shell when this is absent. Hosted sandboxes run
|
|
103859
|
-
// Bash tool commands, so pin the shell snapshot source to bash instead of
|
|
103860
|
-
// letting zsh profile functions leak into bash snapshots and inherit user
|
|
103861
|
-
// strict-mode options such as `set -u`.
|
|
103862
|
-
CLAUDE_CODE_SHELL: CLAUDE_CODE_SHELL_PATH,
|
|
103863
|
-
CLAUDE_AGENT_SDK_CLIENT_APP: clientApp
|
|
103864
|
-
};
|
|
103865
|
-
}
|
|
103866
|
-
function runtimeProcessEnv() {
|
|
103867
|
-
const selected = {};
|
|
103868
|
-
for (const key of CLAUDE_RUNTIME_PROCESS_ENV_KEYS) {
|
|
103869
|
-
const value = process.env[key];
|
|
103870
|
-
if (value !== void 0) {
|
|
103871
|
-
selected[key] = value;
|
|
103872
|
-
}
|
|
103873
|
-
}
|
|
103874
|
-
return selected;
|
|
103875
|
-
}
|
|
103876
|
-
function claudeCodeExecutablePath() {
|
|
103877
|
-
if (process.env.AUTO_AGENT_BRIDGE_TEST_CLAUDE_COMMAND === "1" && process.env.AUTO_CLAUDE_CODE_COMMAND?.trim()) {
|
|
103878
|
-
return process.env.AUTO_CLAUDE_CODE_COMMAND.trim();
|
|
103879
|
-
}
|
|
103880
|
-
return CLAUDE_CODE_EXECUTABLE_PATH;
|
|
103881
|
-
}
|
|
103882
|
-
|
|
103883
104341
|
// src/commands/agent-bridge/harness/claude-code/stderr.ts
|
|
103884
104342
|
var STDERR_LINE_MAX_CHARS = 400;
|
|
103885
104343
|
var STDERR_FORWARD_MAX_LINES = 200;
|
|
@@ -105055,6 +105513,10 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105055
105513
|
mcpServers: input.claude.mcpServers,
|
|
105056
105514
|
writeOutput: input.writeOutput
|
|
105057
105515
|
});
|
|
105516
|
+
this.askUserServer = new AskUserServer({
|
|
105517
|
+
onQuestionPending: (question) => this.handleAskUserQuestion(question),
|
|
105518
|
+
writeOutput: input.writeOutput
|
|
105519
|
+
});
|
|
105058
105520
|
this.outputBuffer = new AgentBridgeOutputBuffer(input);
|
|
105059
105521
|
this.projector = new ClaudeCodeProjector({
|
|
105060
105522
|
writeOutput: input.writeOutput
|
|
@@ -105067,6 +105529,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105067
105529
|
claudeConfig;
|
|
105068
105530
|
claudeMcpServers;
|
|
105069
105531
|
autoMcpShim;
|
|
105532
|
+
askUserServer;
|
|
105070
105533
|
// Selection-change restarts happen in-process, so prefer the live SDK id even
|
|
105071
105534
|
// when the file resume store is stale or temporarily unreadable.
|
|
105072
105535
|
lastObservedAgentId = null;
|
|
@@ -105102,7 +105565,13 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105102
105565
|
return this.outputBuffer.pendingOutputStats();
|
|
105103
105566
|
}
|
|
105104
105567
|
async prepare() {
|
|
105105
|
-
|
|
105568
|
+
const mcpServers = await this.autoMcpShim.prepareClaude();
|
|
105569
|
+
const askUserEndpoint = await this.askUserServer.prepare();
|
|
105570
|
+
this.claudeMcpServers = withClaudeAskUserMcpServer(
|
|
105571
|
+
mcpServers,
|
|
105572
|
+
askUserEndpoint.url,
|
|
105573
|
+
askUserEndpoint.headers
|
|
105574
|
+
);
|
|
105106
105575
|
await this.ensureAgentSession().prepare();
|
|
105107
105576
|
}
|
|
105108
105577
|
shutdown() {
|
|
@@ -105111,6 +105580,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105111
105580
|
this.agentSession?.close();
|
|
105112
105581
|
this.agentSession = null;
|
|
105113
105582
|
this.autoMcpShim.close();
|
|
105583
|
+
this.askUserServer.close();
|
|
105114
105584
|
this.settlePendingQuestions("Runtime is shutting down");
|
|
105115
105585
|
}
|
|
105116
105586
|
async handleCommand(rawDelivery) {
|
|
@@ -105170,6 +105640,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105170
105640
|
}
|
|
105171
105641
|
if (delivery.kind === "interrupt") {
|
|
105172
105642
|
this.injectedCommands.add(delivery.commandId);
|
|
105643
|
+
this.askUserServer.quarantineAll("turn interrupted");
|
|
105173
105644
|
await this.agentSession?.interruptActiveTurn();
|
|
105174
105645
|
this.input.runtimeLogger?.info(
|
|
105175
105646
|
"agent_bridge_claude_command_interrupt_ready",
|
|
@@ -105378,6 +105849,17 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105378
105849
|
);
|
|
105379
105850
|
return;
|
|
105380
105851
|
}
|
|
105852
|
+
if (this.askUserServer.answer(answer)) {
|
|
105853
|
+
this.agentSession?.noteActiveTurnCommand(delivery.commandId);
|
|
105854
|
+
await this.emitRequiredBridgeOutput(
|
|
105855
|
+
activeContext,
|
|
105856
|
+
projectAskUserAnswer(answer)
|
|
105857
|
+
);
|
|
105858
|
+
this.input.writeOutput?.(
|
|
105859
|
+
`agent_bridge_question_answered tool_use_id=${answer.toolCallId}`
|
|
105860
|
+
);
|
|
105861
|
+
return;
|
|
105862
|
+
}
|
|
105381
105863
|
const message = answerFallbackMessage(answer);
|
|
105382
105864
|
await this.emitRequiredBridgeOutput(activeContext, {
|
|
105383
105865
|
type: "entry",
|
|
@@ -105408,11 +105890,28 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105408
105890
|
}
|
|
105409
105891
|
this.pendingQuestions.clear();
|
|
105410
105892
|
}
|
|
105893
|
+
async handleAskUserQuestion(input) {
|
|
105894
|
+
const activeContext = this.context;
|
|
105895
|
+
if (!activeContext) {
|
|
105896
|
+
throw new Error(
|
|
105897
|
+
"Cannot publish an ask-user question without bridge context"
|
|
105898
|
+
);
|
|
105899
|
+
}
|
|
105900
|
+
this.input.writeOutput?.(
|
|
105901
|
+
`agent_bridge_question_pending tool_use_id=${input.id}`
|
|
105902
|
+
);
|
|
105903
|
+
for (const projection of projectAskUserQuestion(input)) {
|
|
105904
|
+
await this.emitRequiredBridgeOutput(activeContext, projection);
|
|
105905
|
+
}
|
|
105906
|
+
}
|
|
105411
105907
|
// Permission callback for the Claude Agent SDK session. The sessions with
|
|
105412
105908
|
// bypassPermissions, so regular tools are auto-approved and only the
|
|
105413
105909
|
// AskUserQuestion tool reaches this callback for a real decision: it parks
|
|
105414
105910
|
// the SDK on a promise that an `answer` bridge command later resolves.
|
|
105415
105911
|
canUseTool = (toolName, toolInput, options) => {
|
|
105912
|
+
if (toolName === CLAUDE_ASK_USER_TOOL_NAME) {
|
|
105913
|
+
return Promise.resolve({ behavior: "allow", updatedInput: toolInput });
|
|
105914
|
+
}
|
|
105416
105915
|
if (toolName !== ASK_USER_QUESTION_TOOL_NAME) {
|
|
105417
105916
|
return Promise.resolve({ behavior: "allow", updatedInput: toolInput });
|
|
105418
105917
|
}
|
|
@@ -105491,6 +105990,9 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105491
105990
|
}
|
|
105492
105991
|
this.persistAgentId(activeContext, message);
|
|
105493
105992
|
this.trackReadState(activeContext, message);
|
|
105993
|
+
if (message.type === "result") {
|
|
105994
|
+
this.askUserServer.quarantineAll("turn ended");
|
|
105995
|
+
}
|
|
105494
105996
|
let projections;
|
|
105495
105997
|
try {
|
|
105496
105998
|
projections = this.projector.project(message, {
|
|
@@ -105510,6 +106012,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105510
106012
|
}
|
|
105511
106013
|
}
|
|
105512
106014
|
async handleAgentError(error51) {
|
|
106015
|
+
this.askUserServer.quarantineAll("harness session failed");
|
|
105513
106016
|
this.input.writeOutput?.(
|
|
105514
106017
|
`agent_bridge_claude_sdk_failed error=${error51 instanceof Error ? error51.message : String(error51)}`
|
|
105515
106018
|
);
|
|
@@ -105629,6 +106132,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105629
106132
|
onMessage: (message, meta3) => this.handleAgentMessage(message, meta3),
|
|
105630
106133
|
onError: (error51) => this.handleAgentError(error51),
|
|
105631
106134
|
onExit: () => {
|
|
106135
|
+
this.askUserServer.quarantineAll("harness child exited");
|
|
105632
106136
|
if (this.agentSession === session) {
|
|
105633
106137
|
this.agentSession = null;
|
|
105634
106138
|
}
|
|
@@ -105657,6 +106161,7 @@ var ClaudeCodeCommandHandler = class {
|
|
|
105657
106161
|
this.requireResumeForNextAgentSession = this.lastObservedAgentId !== null;
|
|
105658
106162
|
this.agentSession?.close();
|
|
105659
106163
|
this.agentSession = null;
|
|
106164
|
+
this.askUserServer.quarantineAll("harness session restarted");
|
|
105660
106165
|
this.settlePendingQuestions("The runtime restarted to change model");
|
|
105661
106166
|
this.input.writeOutput?.(
|
|
105662
106167
|
`agent_bridge_claude_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
|
|
@@ -105850,6 +106355,9 @@ var CodexProjector = class {
|
|
|
105850
106355
|
toolMetadata: statusMetadata(item.status)
|
|
105851
106356
|
});
|
|
105852
106357
|
case "mcpToolCall":
|
|
106358
|
+
if (isAskUserMcpTool(item.server, item.tool)) {
|
|
106359
|
+
return [];
|
|
106360
|
+
}
|
|
105853
106361
|
return this.projectToolItem({
|
|
105854
106362
|
phase,
|
|
105855
106363
|
itemId: item.id,
|
|
@@ -106193,6 +106701,9 @@ function renderCodexConfigToml(config2) {
|
|
|
106193
106701
|
lines.push("");
|
|
106194
106702
|
lines.push(`[mcp_servers.${tomlKey(name)}]`);
|
|
106195
106703
|
lines.push(`url = ${tomlString(server.url)}`);
|
|
106704
|
+
lines.push(
|
|
106705
|
+
`tool_timeout_sec = ${validatedMcpToolTimeoutSeconds(HARNESS_MCP_TOOL_TIMEOUT_SECONDS)}`
|
|
106706
|
+
);
|
|
106196
106707
|
const persistedHeaders = Object.fromEntries(
|
|
106197
106708
|
Object.entries(server.headers ?? {}).filter(
|
|
106198
106709
|
([name2]) => name2 !== AGENT_BRIDGE_MCP_CAPABILITY_HEADER
|
|
@@ -106206,20 +106717,30 @@ function renderCodexConfigToml(config2) {
|
|
|
106206
106717
|
`;
|
|
106207
106718
|
}
|
|
106208
106719
|
function turnOnlyMcpConfig(mcpServers) {
|
|
106720
|
+
const hasTurnOnlyCapability = Object.values(mcpServers ?? {}).some(
|
|
106721
|
+
(server) => server.headers?.[AGENT_BRIDGE_MCP_CAPABILITY_HEADER] !== void 0
|
|
106722
|
+
);
|
|
106723
|
+
if (!hasTurnOnlyCapability) {
|
|
106724
|
+
return void 0;
|
|
106725
|
+
}
|
|
106209
106726
|
const servers = Object.fromEntries(
|
|
106210
|
-
Object.entries(mcpServers ?? {}).
|
|
106727
|
+
Object.entries(mcpServers ?? {}).map(([name, server]) => {
|
|
106211
106728
|
const capability = server.headers?.[AGENT_BRIDGE_MCP_CAPABILITY_HEADER];
|
|
106212
|
-
return
|
|
106213
|
-
|
|
106214
|
-
|
|
106215
|
-
|
|
106216
|
-
|
|
106729
|
+
return [
|
|
106730
|
+
name,
|
|
106731
|
+
{
|
|
106732
|
+
url: server.url,
|
|
106733
|
+
tool_timeout_sec: validatedMcpToolTimeoutSeconds(
|
|
106734
|
+
HARNESS_MCP_TOOL_TIMEOUT_SECONDS
|
|
106735
|
+
),
|
|
106736
|
+
...server.headers ? {
|
|
106217
106737
|
http_headers: {
|
|
106218
|
-
|
|
106738
|
+
...server.headers,
|
|
106739
|
+
...capability ? { [AGENT_BRIDGE_MCP_CAPABILITY_HEADER]: capability } : {}
|
|
106219
106740
|
}
|
|
106220
|
-
}
|
|
106221
|
-
|
|
106222
|
-
]
|
|
106741
|
+
} : {}
|
|
106742
|
+
}
|
|
106743
|
+
];
|
|
106223
106744
|
})
|
|
106224
106745
|
);
|
|
106225
106746
|
return Object.keys(servers).length > 0 ? { mcp_servers: servers } : void 0;
|
|
@@ -106813,7 +107334,7 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
106813
107334
|
return;
|
|
106814
107335
|
} catch (error51) {
|
|
106815
107336
|
this.input.writeOutput?.(
|
|
106816
|
-
`agent_bridge_codex_resume_fallback thread_id=${this.input.resumeThreadId} error=${
|
|
107337
|
+
`agent_bridge_codex_resume_fallback thread_id=${this.input.resumeThreadId} error=${errorMessage3(error51)}`
|
|
106817
107338
|
);
|
|
106818
107339
|
}
|
|
106819
107340
|
}
|
|
@@ -106891,7 +107412,7 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
106891
107412
|
this.activeCommandIds = previousCommandIds;
|
|
106892
107413
|
this.publishActiveTurnCommandIds();
|
|
106893
107414
|
this.input.writeOutput?.(
|
|
106894
|
-
`agent_bridge_codex_steer_failed error=${
|
|
107415
|
+
`agent_bridge_codex_steer_failed error=${errorMessage3(error51)}`
|
|
106895
107416
|
);
|
|
106896
107417
|
}
|
|
106897
107418
|
if (this.activeTurnId) {
|
|
@@ -106905,7 +107426,7 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
106905
107426
|
this.input.writeOutput?.("agent_bridge_codex_interrupted");
|
|
106906
107427
|
} catch (error51) {
|
|
106907
107428
|
this.input.writeOutput?.(
|
|
106908
|
-
`agent_bridge_codex_interrupt_failed error=${
|
|
107429
|
+
`agent_bridge_codex_interrupt_failed error=${errorMessage3(error51)}`
|
|
106909
107430
|
);
|
|
106910
107431
|
}
|
|
106911
107432
|
}
|
|
@@ -106980,7 +107501,7 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
106980
107501
|
message = parseCodexServerFrame(JSON.parse(line));
|
|
106981
107502
|
} catch (error51) {
|
|
106982
107503
|
this.input.writeOutput?.(
|
|
106983
|
-
`agent_bridge_codex_parse_failed error=${
|
|
107504
|
+
`agent_bridge_codex_parse_failed error=${errorMessage3(error51)}`
|
|
106984
107505
|
);
|
|
106985
107506
|
return;
|
|
106986
107507
|
}
|
|
@@ -107175,7 +107696,7 @@ var CodexAgentBridgeSessionImpl = class {
|
|
|
107175
107696
|
);
|
|
107176
107697
|
} catch (error51) {
|
|
107177
107698
|
this.input.writeOutput?.(
|
|
107178
|
-
`agent_bridge_codex_turn_retry_failed attempt=${input.attempt} error=${
|
|
107699
|
+
`agent_bridge_codex_turn_retry_failed attempt=${input.attempt} error=${errorMessage3(error51)}`
|
|
107179
107700
|
);
|
|
107180
107701
|
this.turnRetry = null;
|
|
107181
107702
|
this.clearPendingRetryableError();
|
|
@@ -107390,7 +107911,7 @@ function threadIdFromResult(result) {
|
|
|
107390
107911
|
const id = thread.id;
|
|
107391
107912
|
return typeof id === "string" && id.length > 0 ? id : null;
|
|
107392
107913
|
}
|
|
107393
|
-
function
|
|
107914
|
+
function errorMessage3(error51) {
|
|
107394
107915
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
107395
107916
|
}
|
|
107396
107917
|
function toErrnoException(error51) {
|
|
@@ -107416,6 +107937,11 @@ var CodexCommandHandler = class {
|
|
|
107416
107937
|
mcpServers: input.codex.mcpServers,
|
|
107417
107938
|
writeOutput: input.writeOutput
|
|
107418
107939
|
});
|
|
107940
|
+
this.askUserServer = new AskUserServer({
|
|
107941
|
+
onQuestionPending: (question) => this.handleAskUserQuestion(question),
|
|
107942
|
+
onQuestionSettled: ({ id }) => this.pendingQuestions.delete(id),
|
|
107943
|
+
writeOutput: input.writeOutput
|
|
107944
|
+
});
|
|
107419
107945
|
this.outputBuffer = new AgentBridgeOutputBuffer(input);
|
|
107420
107946
|
}
|
|
107421
107947
|
input;
|
|
@@ -107423,10 +107949,12 @@ var CodexCommandHandler = class {
|
|
|
107423
107949
|
session = null;
|
|
107424
107950
|
codexConfig;
|
|
107425
107951
|
autoMcpShim;
|
|
107952
|
+
askUserServer;
|
|
107426
107953
|
injectedCommands = /* @__PURE__ */ new Set();
|
|
107427
107954
|
// itemId -> JSON-RPC request id of the parked approval request, so an `answer`
|
|
107428
107955
|
// command keyed by toolCallId (= itemId) can resolve the right server request.
|
|
107429
107956
|
pendingApprovals = /* @__PURE__ */ new Map();
|
|
107957
|
+
pendingQuestions = /* @__PURE__ */ new Set();
|
|
107430
107958
|
outputBuffer;
|
|
107431
107959
|
projector = new CodexProjector();
|
|
107432
107960
|
livenessTicker = null;
|
|
@@ -107448,9 +107976,23 @@ var CodexCommandHandler = class {
|
|
|
107448
107976
|
return this.outputBuffer.pendingOutputStats();
|
|
107449
107977
|
}
|
|
107450
107978
|
async prepare() {
|
|
107979
|
+
const mcpServers = await this.autoMcpShim.prepare();
|
|
107980
|
+
if (mcpServers?.[ASK_USER_MCP_SERVER_NAME]) {
|
|
107981
|
+
throw new Error(
|
|
107982
|
+
`MCP server name ${ASK_USER_MCP_SERVER_NAME} is reserved by the harness`
|
|
107983
|
+
);
|
|
107984
|
+
}
|
|
107985
|
+
const askUserEndpoint = await this.askUserServer.prepare();
|
|
107451
107986
|
this.codexConfig = {
|
|
107452
107987
|
...this.codexConfig,
|
|
107453
|
-
mcpServers:
|
|
107988
|
+
mcpServers: {
|
|
107989
|
+
...mcpServers,
|
|
107990
|
+
[ASK_USER_MCP_SERVER_NAME]: {
|
|
107991
|
+
type: "http",
|
|
107992
|
+
url: askUserEndpoint.url,
|
|
107993
|
+
headers: askUserEndpoint.headers
|
|
107994
|
+
}
|
|
107995
|
+
}
|
|
107454
107996
|
};
|
|
107455
107997
|
await this.ensureSession().prepare();
|
|
107456
107998
|
}
|
|
@@ -107460,7 +108002,9 @@ var CodexCommandHandler = class {
|
|
|
107460
108002
|
this.session?.close();
|
|
107461
108003
|
this.session = null;
|
|
107462
108004
|
this.autoMcpShim.close();
|
|
108005
|
+
this.askUserServer.close();
|
|
107463
108006
|
this.pendingApprovals.clear();
|
|
108007
|
+
this.pendingQuestions.clear();
|
|
107464
108008
|
}
|
|
107465
108009
|
async handleCommand(rawDelivery) {
|
|
107466
108010
|
const delivery = RuntimeBridgeCommandDeliverySchema.parse(rawDelivery);
|
|
@@ -107477,6 +108021,7 @@ var CodexCommandHandler = class {
|
|
|
107477
108021
|
}
|
|
107478
108022
|
if (delivery.kind === "interrupt") {
|
|
107479
108023
|
this.injectedCommands.add(delivery.commandId);
|
|
108024
|
+
this.askUserServer.quarantineAll("turn interrupted");
|
|
107480
108025
|
await this.session?.interruptActiveTurn();
|
|
107481
108026
|
return commandAck({ delivery, socketId, status: "injected" });
|
|
107482
108027
|
}
|
|
@@ -107520,7 +108065,7 @@ var CodexCommandHandler = class {
|
|
|
107520
108065
|
delivery,
|
|
107521
108066
|
socketId,
|
|
107522
108067
|
status: "failed",
|
|
107523
|
-
error:
|
|
108068
|
+
error: errorMessage4(error51)
|
|
107524
108069
|
});
|
|
107525
108070
|
}
|
|
107526
108071
|
return commandAck({ delivery, socketId, status: "injected" });
|
|
@@ -107553,6 +108098,11 @@ var CodexCommandHandler = class {
|
|
|
107553
108098
|
this.input.writeOutput?.(
|
|
107554
108099
|
`agent_bridge_codex_question_answered tool_use_id=${payload.data.toolCallId} decision=${decision}`
|
|
107555
108100
|
);
|
|
108101
|
+
} else if (this.pendingQuestions.has(payload.data.toolCallId) && this.askUserServer.answer(payload.data)) {
|
|
108102
|
+
await this.emit(activeContext, projectAskUserAnswer(payload.data));
|
|
108103
|
+
this.input.writeOutput?.(
|
|
108104
|
+
`agent_bridge_codex_question_answered tool_use_id=${payload.data.toolCallId} decision=answered`
|
|
108105
|
+
);
|
|
107556
108106
|
} else {
|
|
107557
108107
|
const message = answerFallbackMessage2(payload.data);
|
|
107558
108108
|
await this.emitUserMessageEntry(
|
|
@@ -107570,7 +108120,7 @@ var CodexCommandHandler = class {
|
|
|
107570
108120
|
delivery,
|
|
107571
108121
|
socketId,
|
|
107572
108122
|
status: "failed",
|
|
107573
|
-
error:
|
|
108123
|
+
error: errorMessage4(error51)
|
|
107574
108124
|
});
|
|
107575
108125
|
}
|
|
107576
108126
|
return commandAck({ delivery, socketId, status: "injected" });
|
|
@@ -107598,6 +108148,9 @@ var CodexCommandHandler = class {
|
|
|
107598
108148
|
if (notification.type === "tokenUsage") {
|
|
107599
108149
|
return;
|
|
107600
108150
|
}
|
|
108151
|
+
if (notification.type === "turnCompleted") {
|
|
108152
|
+
this.askUserServer.quarantineAll("turn ended");
|
|
108153
|
+
}
|
|
107601
108154
|
for (const projection of this.projector.project(notification)) {
|
|
107602
108155
|
await this.emit(activeContext, projection);
|
|
107603
108156
|
}
|
|
@@ -107615,9 +108168,25 @@ var CodexCommandHandler = class {
|
|
|
107615
108168
|
await this.emit(activeContext, projection);
|
|
107616
108169
|
}
|
|
107617
108170
|
}
|
|
108171
|
+
async handleAskUserQuestion(input) {
|
|
108172
|
+
const activeContext = this.context;
|
|
108173
|
+
if (!activeContext) {
|
|
108174
|
+
throw new Error(
|
|
108175
|
+
"Cannot publish an ask-user question without bridge context"
|
|
108176
|
+
);
|
|
108177
|
+
}
|
|
108178
|
+
this.pendingQuestions.add(input.id);
|
|
108179
|
+
this.input.writeOutput?.(
|
|
108180
|
+
`agent_bridge_codex_question_pending tool_use_id=${input.id}`
|
|
108181
|
+
);
|
|
108182
|
+
for (const projection of projectAskUserQuestion(input)) {
|
|
108183
|
+
await this.emitRequired(activeContext, projection);
|
|
108184
|
+
}
|
|
108185
|
+
}
|
|
107618
108186
|
async handleSessionError(error51) {
|
|
108187
|
+
this.askUserServer.quarantineAll("harness session failed");
|
|
107619
108188
|
this.input.writeOutput?.(
|
|
107620
|
-
`agent_bridge_codex_session_failed error=${
|
|
108189
|
+
`agent_bridge_codex_session_failed error=${errorMessage4(error51)}`
|
|
107621
108190
|
);
|
|
107622
108191
|
const activeContext = this.context;
|
|
107623
108192
|
if (!activeContext) {
|
|
@@ -107625,7 +108194,7 @@ var CodexCommandHandler = class {
|
|
|
107625
108194
|
}
|
|
107626
108195
|
await this.emit(
|
|
107627
108196
|
activeContext,
|
|
107628
|
-
this.projector.projectSessionFailure(
|
|
108197
|
+
this.projector.projectSessionFailure(errorMessage4(error51))
|
|
107629
108198
|
);
|
|
107630
108199
|
}
|
|
107631
108200
|
async emitLivenessBeat() {
|
|
@@ -107650,10 +108219,16 @@ var CodexCommandHandler = class {
|
|
|
107650
108219
|
await this.outputBuffer.emitProjection(activeContext, projection);
|
|
107651
108220
|
} catch (error51) {
|
|
107652
108221
|
this.input.writeOutput?.(
|
|
107653
|
-
`agent_bridge_output_emit_failed error=${
|
|
108222
|
+
`agent_bridge_output_emit_failed error=${errorMessage4(error51)}`
|
|
107654
108223
|
);
|
|
107655
108224
|
}
|
|
107656
108225
|
}
|
|
108226
|
+
async emitRequired(activeContext, projection) {
|
|
108227
|
+
await this.outputBuffer.emitProjection(activeContext, projection, {
|
|
108228
|
+
discardOnFailure: true,
|
|
108229
|
+
requireDrain: true
|
|
108230
|
+
});
|
|
108231
|
+
}
|
|
107657
108232
|
ensureSession() {
|
|
107658
108233
|
if (this.session) {
|
|
107659
108234
|
return this.session;
|
|
@@ -107670,6 +108245,7 @@ var CodexCommandHandler = class {
|
|
|
107670
108245
|
onUsageTurnChanged: (turnId) => this.emitUsageTurn(turnId),
|
|
107671
108246
|
onError: (error51) => this.handleSessionError(error51),
|
|
107672
108247
|
onExit: () => {
|
|
108248
|
+
this.askUserServer.quarantineAll("harness child exited");
|
|
107673
108249
|
if (this.session === session) {
|
|
107674
108250
|
this.session = null;
|
|
107675
108251
|
}
|
|
@@ -107697,7 +108273,9 @@ var CodexCommandHandler = class {
|
|
|
107697
108273
|
this.skipResumeForNextSession = true;
|
|
107698
108274
|
this.session?.close();
|
|
107699
108275
|
this.session = null;
|
|
108276
|
+
this.askUserServer.quarantineAll("harness session restarted");
|
|
107700
108277
|
this.pendingApprovals.clear();
|
|
108278
|
+
this.pendingQuestions.clear();
|
|
107701
108279
|
this.input.writeOutput?.(
|
|
107702
108280
|
`agent_bridge_codex_model_selection_changed provider=${next.model?.provider ?? ""} model=${next.model?.id ?? ""} reasoning_effort=${next.reasoningEffort ?? ""}`
|
|
107703
108281
|
);
|
|
@@ -107712,7 +108290,7 @@ var CodexCommandHandler = class {
|
|
|
107712
108290
|
return store.read(activeContext.sessionId) ?? void 0;
|
|
107713
108291
|
} catch (error51) {
|
|
107714
108292
|
this.input.writeOutput?.(
|
|
107715
|
-
`agent_bridge_codex_thread_read_failed error=${
|
|
108293
|
+
`agent_bridge_codex_thread_read_failed error=${errorMessage4(error51)}`
|
|
107716
108294
|
);
|
|
107717
108295
|
return void 0;
|
|
107718
108296
|
}
|
|
@@ -107727,7 +108305,7 @@ var CodexCommandHandler = class {
|
|
|
107727
108305
|
store.write({ sessionId: activeContext.sessionId, threadId });
|
|
107728
108306
|
} catch (error51) {
|
|
107729
108307
|
this.input.writeOutput?.(
|
|
107730
|
-
`agent_bridge_codex_thread_persist_failed error=${
|
|
108308
|
+
`agent_bridge_codex_thread_persist_failed error=${errorMessage4(error51)}`
|
|
107731
108309
|
);
|
|
107732
108310
|
}
|
|
107733
108311
|
}
|
|
@@ -107769,7 +108347,7 @@ function deliveryMode2(delivery) {
|
|
|
107769
108347
|
}
|
|
107770
108348
|
return "interrupt";
|
|
107771
108349
|
}
|
|
107772
|
-
function
|
|
108350
|
+
function errorMessage4(error51) {
|
|
107773
108351
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
107774
108352
|
}
|
|
107775
108353
|
|