@rallycry/conveyor-agent 7.0.1 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-CYZPFJGN.js +26 -0
- package/dist/chunk-CYZPFJGN.js.map +1 -0
- package/dist/chunk-KNBG2634.js +51 -0
- package/dist/chunk-KNBG2634.js.map +1 -0
- package/dist/{chunk-HAU4E7IA.js → chunk-L7ZH423N.js} +180 -126
- package/dist/chunk-L7ZH423N.js.map +1 -0
- package/dist/cli.js +5 -2
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/tag-audit-handler-4RRGIHVB.js +184 -0
- package/dist/tag-audit-handler-4RRGIHVB.js.map +1 -0
- package/dist/tunnel-client.d.ts +1 -0
- package/dist/tunnel-client.js +212 -0
- package/dist/tunnel-client.js.map +1 -0
- package/package.json +5 -2
- package/dist/chunk-HAU4E7IA.js.map +0 -1
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/utils/logger.ts
|
|
2
|
+
function createServiceLogger(service) {
|
|
3
|
+
const prefix = `[conveyor-agent:${service}]`;
|
|
4
|
+
return {
|
|
5
|
+
info(message, data) {
|
|
6
|
+
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
7
|
+
process.stderr.write(`${prefix} ${message}${extra}
|
|
8
|
+
`);
|
|
9
|
+
},
|
|
10
|
+
warn(message, data) {
|
|
11
|
+
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
12
|
+
process.stderr.write(`${prefix} WARN ${message}${extra}
|
|
13
|
+
`);
|
|
14
|
+
},
|
|
15
|
+
error(message, data) {
|
|
16
|
+
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
17
|
+
process.stderr.write(`${prefix} ERROR ${message}${extra}
|
|
18
|
+
`);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
createServiceLogger
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=chunk-CYZPFJGN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["/** Minimal structured logger for conveyor-agent (writes to stderr). */\nexport function createServiceLogger(service: string) {\n const prefix = `[conveyor-agent:${service}]`;\n return {\n info(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ${message}${extra}\\n`);\n },\n warn(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} WARN ${message}${extra}\\n`);\n },\n error(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ERROR ${message}${extra}\\n`);\n },\n };\n}\n"],"mappings":";AACO,SAAS,oBAAoB,SAAiB;AACnD,QAAM,SAAS,mBAAmB,OAAO;AACzC,SAAO;AAAA,IACL,KAAK,SAAiB,MAAsC;AAC1D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,IAAI,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IACvD;AAAA,IACA,KAAK,SAAiB,MAAsC;AAC1D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,SAAS,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IAC5D;AAAA,IACA,MAAM,SAAiB,MAAsC;AAC3D,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK;AAClD,cAAQ,OAAO,MAAM,GAAG,MAAM,UAAU,OAAO,GAAG,KAAK;AAAA,CAAI;AAAA,IAC7D;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/harness/types.ts
|
|
2
|
+
function defineTool(name, description, schema, handler, options) {
|
|
3
|
+
return {
|
|
4
|
+
name,
|
|
5
|
+
description,
|
|
6
|
+
schema,
|
|
7
|
+
handler,
|
|
8
|
+
annotations: options?.annotations
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/harness/claude-code/index.ts
|
|
13
|
+
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
14
|
+
var ClaudeCodeHarness = class {
|
|
15
|
+
async *executeQuery(opts) {
|
|
16
|
+
const sdkEvents = query({
|
|
17
|
+
prompt: opts.prompt,
|
|
18
|
+
options: {
|
|
19
|
+
...opts.options,
|
|
20
|
+
...opts.resume ? { resume: opts.resume } : {},
|
|
21
|
+
...opts.options.abortController ? { abortController: opts.options.abortController } : {}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
for await (const event of sdkEvents) {
|
|
25
|
+
yield event;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
createMcpServer(config) {
|
|
29
|
+
const sdkTools = config.tools.map(
|
|
30
|
+
(t) => tool(
|
|
31
|
+
t.name,
|
|
32
|
+
t.description,
|
|
33
|
+
t.schema,
|
|
34
|
+
t.handler,
|
|
35
|
+
t.annotations ? { annotations: t.annotations } : void 0
|
|
36
|
+
)
|
|
37
|
+
);
|
|
38
|
+
return createSdkMcpServer({ name: config.name, tools: sdkTools });
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/harness/index.ts
|
|
43
|
+
function createHarness() {
|
|
44
|
+
return new ClaudeCodeHarness();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
defineTool,
|
|
49
|
+
createHarness
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chunk-KNBG2634.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/harness/types.ts","../src/harness/claude-code/index.ts","../src/harness/index.ts"],"sourcesContent":["/**\n * Harness-neutral types for agent query execution.\n *\n * These types abstract the underlying agent SDK so that the runner,\n * execution, and tool layers never reference SDK-specific imports\n * directly. The only place that should import from\n * `@anthropic-ai/claude-agent-sdk` is `harness/claude-code/`.\n */\n\nimport type { z } from \"zod\";\n\n// ── Events emitted by the harness during a query ────────────────────────\n\nexport interface HarnessSystemInitEvent {\n type: \"system\";\n subtype: \"init\";\n session_id?: string;\n model: string;\n}\n\nexport interface HarnessCompactBoundaryEvent {\n type: \"system\";\n subtype: \"compact_boundary\";\n compact_metadata: { trigger: \"manual\" | \"auto\"; pre_tokens: number };\n}\n\nexport interface HarnessTaskStartedEvent {\n type: \"system\";\n subtype: \"task_started\";\n task_id: string;\n description: string;\n}\n\nexport interface HarnessTaskProgressEvent {\n type: \"system\";\n subtype: \"task_progress\";\n task_id: string;\n description: string;\n usage?: { tool_uses: number; duration_ms: number };\n}\n\nexport type HarnessSystemEvent =\n | HarnessSystemInitEvent\n | HarnessCompactBoundaryEvent\n | HarnessTaskStartedEvent\n | HarnessTaskProgressEvent;\n\nexport interface HarnessContentBlock {\n type: string;\n text?: string;\n name?: string;\n input?: unknown;\n id?: string;\n}\n\nexport interface HarnessAssistantEvent {\n type: \"assistant\";\n message: {\n role: \"assistant\";\n content: HarnessContentBlock[];\n usage?: {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n}\n\nexport interface HarnessResultSuccessEvent {\n type: \"result\";\n subtype: \"success\";\n result: string;\n total_cost_usd: number;\n modelUsage?: Record<string, unknown>;\n sessionId?: string;\n}\n\nexport interface HarnessResultErrorEvent {\n type: \"result\";\n subtype: \"error\";\n errors: string[];\n sessionId?: string;\n}\n\nexport type HarnessResultEvent = HarnessResultSuccessEvent | HarnessResultErrorEvent;\n\nexport interface HarnessRateLimitEvent {\n type: \"rate_limit_event\";\n rate_limit_info: {\n status: string;\n rateLimitType?: string;\n utilization?: number;\n resetsAt?: unknown;\n };\n}\n\nexport interface HarnessToolProgressEvent {\n type: \"tool_progress\";\n tool_name?: string;\n elapsed_time_seconds?: number;\n}\n\nexport type HarnessEvent =\n | HarnessSystemEvent\n | HarnessAssistantEvent\n | HarnessResultEvent\n | HarnessRateLimitEvent\n | HarnessToolProgressEvent;\n\n// ── User message fed into a query ───────────────────────────────────────\n\nexport interface HarnessUserMessage {\n type: \"user\";\n session_id: string;\n message: { role: \"user\"; content: string | unknown[] };\n parent_tool_use_id: null;\n}\n\n// ── Tool definition (harness-neutral) ───────────────────────────────────\n\nexport interface HarnessToolAnnotations {\n readOnlyHint?: boolean;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any -- generic tool handler */\nexport interface HarnessToolDefinition {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (\n input: any,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>;\n annotations?: HarnessToolAnnotations;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\n// ── Hook types ──────────────────────────────────────────────────────────\n\nexport interface HarnessHookInput {\n hook_event_name: string;\n tool_name: string;\n tool_response: unknown;\n}\n\nexport interface HarnessHookOutput {\n continue: boolean;\n}\n\nexport type HarnessPostToolUseHook = (input: HarnessHookInput) => Promise<HarnessHookOutput>;\n\n// ── MCP server handle (opaque to the runner) ────────────────────────────\n\n/** Opaque handle returned by `AgentHarness.createMcpServer()`. */\nexport type HarnessMcpServer = unknown;\n\n// ── Query options ───────────────────────────────────────────────────────\n\nexport interface HarnessQueryOptions {\n model: string;\n systemPrompt: unknown;\n cwd: string;\n permissionMode: \"plan\" | \"bypassPermissions\";\n allowDangerouslySkipPermissions: boolean;\n tools: { type: \"preset\"; preset: \"claude_code\" };\n mcpServers: Record<string, HarnessMcpServer>;\n settingSources?: (\"user\" | \"project\" | \"local\")[];\n sandbox?: { enabled: boolean };\n maxTurns?: number;\n maxBudgetUsd?: number;\n effort?: string;\n thinking?: unknown;\n betas?: unknown;\n disallowedTools?: string[];\n abortController?: AbortController;\n enableFileCheckpointing?: boolean;\n canUseTool?: (\n toolName: string,\n input: Record<string, unknown>,\n ) => Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n >;\n hooks?: Record<string, { hooks: HarnessPostToolUseHook[]; timeout: number }[]>;\n resume?: string;\n stderr?: (data: string) => void;\n}\n\n// ── Tool definition helper ──────────────────────────────────────────────\n\n/**\n * Construct a `HarnessToolDefinition` with the same signature as the SDK's\n * `tool()` helper, but without importing the SDK. The harness implementation\n * converts these into SDK-native tools when `createMcpServer()` is called.\n */\nexport function defineTool<T extends z.ZodRawShape>(\n name: string,\n description: string,\n schema: T,\n handler: (\n input: z.infer<z.ZodObject<T>>,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>,\n options?: { annotations?: HarnessToolAnnotations },\n): HarnessToolDefinition {\n return {\n name,\n description,\n schema,\n handler: handler as HarnessToolDefinition[\"handler\"],\n annotations: options?.annotations,\n };\n}\n\n// ── AgentHarness interface ──────────────────────────────────────────────\n\nexport interface AgentHarness {\n /** Start a streaming query and return an async generator of events. */\n executeQuery(options: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void>;\n\n /** Wrap an array of harness-neutral tool definitions into an MCP server. */\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer;\n}\n","/**\n * ClaudeCodeHarness — wraps `@anthropic-ai/claude-agent-sdk` behind the\n * generic `AgentHarness` interface.\n *\n * This is the ONLY module that should import from the SDK.\n */\n\nimport { query, tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n AgentHarness,\n HarnessEvent,\n HarnessQueryOptions,\n HarnessToolDefinition,\n HarnessMcpServer,\n HarnessUserMessage,\n} from \"../types.js\";\n\nexport class ClaudeCodeHarness implements AgentHarness {\n async *executeQuery(opts: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void> {\n const sdkEvents = query({\n prompt: opts.prompt as Parameters<typeof query>[0][\"prompt\"],\n options: {\n ...(opts.options as Parameters<typeof query>[0][\"options\"]),\n ...(opts.resume ? { resume: opts.resume } : {}),\n ...(opts.options.abortController ? { abortController: opts.options.abortController } : {}),\n },\n });\n\n for await (const event of sdkEvents) {\n yield event as unknown as HarnessEvent;\n }\n }\n\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer {\n const sdkTools = config.tools.map((t) =>\n tool(\n t.name,\n t.description,\n t.schema,\n t.handler as Parameters<typeof tool>[3],\n t.annotations ? { annotations: t.annotations } : undefined,\n ),\n );\n return createSdkMcpServer({ name: config.name, tools: sdkTools });\n }\n}\n","export { defineTool } from \"./types.js\";\n\nexport type {\n AgentHarness,\n HarnessEvent,\n HarnessSystemEvent,\n HarnessSystemInitEvent,\n HarnessCompactBoundaryEvent,\n HarnessTaskStartedEvent,\n HarnessTaskProgressEvent,\n HarnessAssistantEvent,\n HarnessContentBlock,\n HarnessResultEvent,\n HarnessResultSuccessEvent,\n HarnessResultErrorEvent,\n HarnessRateLimitEvent,\n HarnessToolProgressEvent,\n HarnessUserMessage,\n HarnessToolDefinition,\n HarnessToolAnnotations,\n HarnessMcpServer,\n HarnessQueryOptions,\n HarnessHookInput,\n HarnessHookOutput,\n HarnessPostToolUseHook,\n} from \"./types.js\";\n\nexport { ClaudeCodeHarness } from \"./claude-code/index.js\";\n\nimport { ClaudeCodeHarness } from \"./claude-code/index.js\";\nimport type { AgentHarness } from \"./types.js\";\n\nexport function createHarness(): AgentHarness {\n return new ClaudeCodeHarness();\n}\n"],"mappings":";AAkMO,SAAS,WACd,MACA,aACA,QACA,SAGA,SACuB;AACvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,SAAS;AAAA,EACxB;AACF;;;AC3MA,SAAS,OAAO,MAAM,0BAA0B;AAUzC,IAAM,oBAAN,MAAgD;AAAA,EACrD,OAAO,aAAa,MAImB;AACrC,UAAM,YAAY,MAAM;AAAA,MACtB,QAAQ,KAAK;AAAA,MACb,SAAS;AAAA,QACP,GAAI,KAAK;AAAA,QACT,GAAI,KAAK,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;AAAA,QAC7C,GAAI,KAAK,QAAQ,kBAAkB,EAAE,iBAAiB,KAAK,QAAQ,gBAAgB,IAAI,CAAC;AAAA,MAC1F;AAAA,IACF,CAAC;AAED,qBAAiB,SAAS,WAAW;AACnC,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,gBAAgB,QAA4E;AAC1F,UAAM,WAAW,OAAO,MAAM;AAAA,MAAI,CAAC,MACjC;AAAA,QACE,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE;AAAA,QACF,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI;AAAA,MACnD;AAAA,IACF;AACA,WAAO,mBAAmB,EAAE,MAAM,OAAO,MAAM,OAAO,SAAS,CAAC;AAAA,EAClE;AACF;;;ACjBO,SAAS,gBAA8B;AAC5C,SAAO,IAAI,kBAAkB;AAC/B;","names":[]}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createHarness,
|
|
3
|
+
defineTool
|
|
4
|
+
} from "./chunk-KNBG2634.js";
|
|
5
|
+
import {
|
|
6
|
+
createServiceLogger
|
|
7
|
+
} from "./chunk-CYZPFJGN.js";
|
|
8
|
+
|
|
1
9
|
// src/connection/agent-connection.ts
|
|
2
10
|
import { io } from "socket.io-client";
|
|
3
11
|
var EVENT_BATCH_MS = 500;
|
|
@@ -133,15 +141,7 @@ var AgentConnection = class {
|
|
|
133
141
|
});
|
|
134
142
|
this.socket.io.on("reconnect", () => {
|
|
135
143
|
process.stderr.write("[conveyor-agent] Reconnected\n");
|
|
136
|
-
void this.
|
|
137
|
-
});
|
|
138
|
-
if (this.lastEmittedStatus) {
|
|
139
|
-
void this.call("reportAgentStatus", {
|
|
140
|
-
sessionId: this.config.sessionId,
|
|
141
|
-
status: this.lastEmittedStatus
|
|
142
|
-
}).catch(() => {
|
|
143
|
-
});
|
|
144
|
-
}
|
|
144
|
+
void this.reconnectToSession();
|
|
145
145
|
});
|
|
146
146
|
this.socket.io.on("reconnect_attempt", () => {
|
|
147
147
|
});
|
|
@@ -156,6 +156,53 @@ var AgentConnection = class {
|
|
|
156
156
|
this.socket = null;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
+
// ── Reconnect with retry ────────────────────────────────────────────
|
|
160
|
+
async reconnectToSession() {
|
|
161
|
+
const maxRetries = 5;
|
|
162
|
+
const baseDelayMs = 2e3;
|
|
163
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
164
|
+
try {
|
|
165
|
+
const { pendingMessages } = await this.call("connectAgent", {
|
|
166
|
+
sessionId: this.config.sessionId
|
|
167
|
+
});
|
|
168
|
+
this.drainPendingMessages(pendingMessages);
|
|
169
|
+
process.stderr.write("[conveyor-agent] Reconnected to session successfully\n");
|
|
170
|
+
if (this.lastEmittedStatus) {
|
|
171
|
+
void this.call("reportAgentStatus", {
|
|
172
|
+
sessionId: this.config.sessionId,
|
|
173
|
+
status: this.lastEmittedStatus
|
|
174
|
+
}).catch(() => {
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
} catch (err) {
|
|
179
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
180
|
+
const delayMs = baseDelayMs * 2 ** (attempt - 1);
|
|
181
|
+
process.stderr.write(
|
|
182
|
+
`[conveyor-agent] connectAgent failed (attempt ${attempt}/${maxRetries}): ${errMsg} \u2014 retrying in ${delayMs / 1e3}s
|
|
183
|
+
`
|
|
184
|
+
);
|
|
185
|
+
await new Promise((resolve2) => {
|
|
186
|
+
setTimeout(resolve2, delayMs);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
process.stderr.write(
|
|
191
|
+
`[conveyor-agent] Failed to reconnect to session after ${maxRetries} attempts, exiting
|
|
192
|
+
`
|
|
193
|
+
);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
drainPendingMessages(messages) {
|
|
197
|
+
for (const msg of messages) {
|
|
198
|
+
if (!msg.content) continue;
|
|
199
|
+
if (this.messageCallback) {
|
|
200
|
+
this.messageCallback({ content: msg.content, userId: msg.userId });
|
|
201
|
+
} else {
|
|
202
|
+
this.earlyMessages.push({ content: msg.content, userId: msg.userId });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
159
206
|
// ── Callback registration with early-buffer draining ───────────────
|
|
160
207
|
onMessage(callback) {
|
|
161
208
|
this.messageCallback = callback;
|
|
@@ -543,28 +590,6 @@ var Lifecycle = class {
|
|
|
543
590
|
}
|
|
544
591
|
};
|
|
545
592
|
|
|
546
|
-
// src/utils/logger.ts
|
|
547
|
-
function createServiceLogger(service) {
|
|
548
|
-
const prefix = `[conveyor-agent:${service}]`;
|
|
549
|
-
return {
|
|
550
|
-
info(message, data) {
|
|
551
|
-
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
552
|
-
process.stderr.write(`${prefix} ${message}${extra}
|
|
553
|
-
`);
|
|
554
|
-
},
|
|
555
|
-
warn(message, data) {
|
|
556
|
-
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
557
|
-
process.stderr.write(`${prefix} WARN ${message}${extra}
|
|
558
|
-
`);
|
|
559
|
-
},
|
|
560
|
-
error(message, data) {
|
|
561
|
-
const extra = data ? ` ${JSON.stringify(data)}` : "";
|
|
562
|
-
process.stderr.write(`${prefix} ERROR ${message}${extra}
|
|
563
|
-
`);
|
|
564
|
-
}
|
|
565
|
-
};
|
|
566
|
-
}
|
|
567
|
-
|
|
568
593
|
// src/runner/git-utils.ts
|
|
569
594
|
import { execSync } from "child_process";
|
|
570
595
|
function hasUncommittedChanges(cwd) {
|
|
@@ -772,52 +797,6 @@ var PlanSync = class {
|
|
|
772
797
|
}
|
|
773
798
|
};
|
|
774
799
|
|
|
775
|
-
// src/harness/types.ts
|
|
776
|
-
function defineTool(name, description, schema, handler, options) {
|
|
777
|
-
return {
|
|
778
|
-
name,
|
|
779
|
-
description,
|
|
780
|
-
schema,
|
|
781
|
-
handler,
|
|
782
|
-
annotations: options?.annotations
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
// src/harness/claude-code/index.ts
|
|
787
|
-
import { query, tool, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
788
|
-
var ClaudeCodeHarness = class {
|
|
789
|
-
async *executeQuery(opts) {
|
|
790
|
-
const sdkEvents = query({
|
|
791
|
-
prompt: opts.prompt,
|
|
792
|
-
options: {
|
|
793
|
-
...opts.options,
|
|
794
|
-
...opts.resume ? { resume: opts.resume } : {},
|
|
795
|
-
...opts.options.abortController ? { abortController: opts.options.abortController } : {}
|
|
796
|
-
}
|
|
797
|
-
});
|
|
798
|
-
for await (const event of sdkEvents) {
|
|
799
|
-
yield event;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
createMcpServer(config) {
|
|
803
|
-
const sdkTools = config.tools.map(
|
|
804
|
-
(t) => tool(
|
|
805
|
-
t.name,
|
|
806
|
-
t.description,
|
|
807
|
-
t.schema,
|
|
808
|
-
t.handler,
|
|
809
|
-
t.annotations ? { annotations: t.annotations } : void 0
|
|
810
|
-
)
|
|
811
|
-
);
|
|
812
|
-
return createSdkMcpServer({ name: config.name, tools: sdkTools });
|
|
813
|
-
}
|
|
814
|
-
};
|
|
815
|
-
|
|
816
|
-
// src/harness/index.ts
|
|
817
|
-
function createHarness() {
|
|
818
|
-
return new ClaudeCodeHarness();
|
|
819
|
-
}
|
|
820
|
-
|
|
821
800
|
// src/execution/pack-runner-prompt.ts
|
|
822
801
|
function findLastAgentMessageIndex(history) {
|
|
823
802
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
@@ -1209,8 +1188,7 @@ function buildAutoPrompt(context) {
|
|
|
1209
1188
|
`You are in Auto mode \u2014 operating autonomously through planning \u2192 building \u2192 PR.`,
|
|
1210
1189
|
``,
|
|
1211
1190
|
`### Phase 1: Discovery & Planning (current)`,
|
|
1212
|
-
`- You
|
|
1213
|
-
`- You can write plan files in .claude/plans/ only \u2014 no other file writes`,
|
|
1191
|
+
`- You are in the SDK's plan mode \u2014 read-only access is enforced automatically`,
|
|
1214
1192
|
`- You have MCP tools for task properties: update_task, update_task_properties`,
|
|
1215
1193
|
``,
|
|
1216
1194
|
`### Required before transitioning:`,
|
|
@@ -2334,7 +2312,16 @@ Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>`;
|
|
|
2334
2312
|
}
|
|
2335
2313
|
}
|
|
2336
2314
|
if (hasUnpushedCommits(cwd)) {
|
|
2337
|
-
const pushSuccess = await pushToOrigin(cwd)
|
|
2315
|
+
const pushSuccess = await pushToOrigin(cwd, async () => {
|
|
2316
|
+
try {
|
|
2317
|
+
const result2 = await connection.call("refreshGithubToken", {
|
|
2318
|
+
sessionId: connection.sessionId
|
|
2319
|
+
});
|
|
2320
|
+
return result2.token;
|
|
2321
|
+
} catch {
|
|
2322
|
+
return void 0;
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2338
2325
|
if (pushSuccess) {
|
|
2339
2326
|
connection.sendEvent({
|
|
2340
2327
|
type: "message",
|
|
@@ -2347,6 +2334,7 @@ Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>`;
|
|
|
2347
2334
|
}
|
|
2348
2335
|
}
|
|
2349
2336
|
const result = await connection.call("createPullRequest", {
|
|
2337
|
+
sessionId: connection.sessionId,
|
|
2350
2338
|
title,
|
|
2351
2339
|
body,
|
|
2352
2340
|
head: branch,
|
|
@@ -4696,18 +4684,12 @@ function handleAutoToolAccess(toolName, input, hasExitedPlanMode, isParentTask)
|
|
|
4696
4684
|
if (hasExitedPlanMode) {
|
|
4697
4685
|
return isParentTask ? handleReviewToolAccess(toolName, input, true) : handleBuildingToolAccess(toolName, input);
|
|
4698
4686
|
}
|
|
4699
|
-
if (PM_PLAN_FILE_TOOLS.has(toolName)) {
|
|
4700
|
-
if (isPlanFile(input)) {
|
|
4701
|
-
return { behavior: "allow", updatedInput: input };
|
|
4702
|
-
}
|
|
4703
|
-
return {
|
|
4704
|
-
behavior: "deny",
|
|
4705
|
-
message: "You are in auto plan mode. File writes are restricted to plan files. Call ExitPlanMode when your plan is ready to start building."
|
|
4706
|
-
};
|
|
4707
|
-
}
|
|
4708
4687
|
return { behavior: "allow", updatedInput: input };
|
|
4709
4688
|
}
|
|
4710
4689
|
async function handleExitPlanMode(host, input) {
|
|
4690
|
+
if (host.hasExitedPlanMode) {
|
|
4691
|
+
return { behavior: "allow", updatedInput: input };
|
|
4692
|
+
}
|
|
4711
4693
|
try {
|
|
4712
4694
|
host.syncPlanFile();
|
|
4713
4695
|
const taskProps = await host.connection.getTaskProperties();
|
|
@@ -5274,6 +5256,8 @@ var QueryBridge = class {
|
|
|
5274
5256
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5275
5257
|
logger2.error("Query execution failed", { error: msg });
|
|
5276
5258
|
this.connection.sendEvent({ type: "error", message: msg });
|
|
5259
|
+
} finally {
|
|
5260
|
+
this.mode.pendingModeRestart = false;
|
|
5277
5261
|
}
|
|
5278
5262
|
}
|
|
5279
5263
|
// ── QueryHost construction ──────────────────────────────────────────
|
|
@@ -5343,6 +5327,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5343
5327
|
callbacks;
|
|
5344
5328
|
_state = "connecting";
|
|
5345
5329
|
stopped = false;
|
|
5330
|
+
hasCompleted = false;
|
|
5346
5331
|
interrupted = false;
|
|
5347
5332
|
taskContext = null;
|
|
5348
5333
|
fullContext = null;
|
|
@@ -5354,7 +5339,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5354
5339
|
this.config = config;
|
|
5355
5340
|
this.callbacks = callbacks;
|
|
5356
5341
|
this.connection = new AgentConnection(config.connection);
|
|
5357
|
-
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? "discovery" : "building");
|
|
5342
|
+
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
|
|
5358
5343
|
this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
|
|
5359
5344
|
const lifecycleConfig = { ...DEFAULT_LIFECYCLE_CONFIG, ...config.lifecycle };
|
|
5360
5345
|
this.lifecycle = new Lifecycle(lifecycleConfig, {
|
|
@@ -5430,6 +5415,9 @@ var SessionRunner = class _SessionRunner {
|
|
|
5430
5415
|
this.queryBridge = this.createQueryBridge();
|
|
5431
5416
|
this.logInitialization();
|
|
5432
5417
|
await this.executeInitialMode();
|
|
5418
|
+
if (!this.stopped && this._state !== "error") {
|
|
5419
|
+
this.hasCompleted = true;
|
|
5420
|
+
}
|
|
5433
5421
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
5434
5422
|
await this.maybeSendPRNudge();
|
|
5435
5423
|
}
|
|
@@ -5459,6 +5447,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
5459
5447
|
}
|
|
5460
5448
|
break;
|
|
5461
5449
|
}
|
|
5450
|
+
if (this.hasCompleted && msg.userId === "system") {
|
|
5451
|
+
continue;
|
|
5452
|
+
}
|
|
5453
|
+
if (msg.userId !== "system") {
|
|
5454
|
+
this.hasCompleted = false;
|
|
5455
|
+
}
|
|
5462
5456
|
await this.setState("running");
|
|
5463
5457
|
this.interrupted = false;
|
|
5464
5458
|
await this.callbacks.onEvent({
|
|
@@ -5472,6 +5466,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
5472
5466
|
if (!this.stopped && this.pendingMessages.length === 0) {
|
|
5473
5467
|
await this.maybeSendPRNudge();
|
|
5474
5468
|
}
|
|
5469
|
+
this.hasCompleted = true;
|
|
5475
5470
|
if (!this.stopped) await this.setState("idle");
|
|
5476
5471
|
} else if (this._state === "error") {
|
|
5477
5472
|
await this.setState("idle");
|
|
@@ -5634,7 +5629,12 @@ var SessionRunner = class _SessionRunner {
|
|
|
5634
5629
|
baseBranch: ctx.baseBranch ?? "",
|
|
5635
5630
|
githubPRUrl: ctx.githubPRUrl,
|
|
5636
5631
|
claudeSessionId: ctx.claudeSessionId ?? null,
|
|
5637
|
-
isParentTask: !!ctx.parentTaskId
|
|
5632
|
+
isParentTask: !!ctx.parentTaskId,
|
|
5633
|
+
storyPoints: ctx.storyPoints ?? void 0,
|
|
5634
|
+
projectAgents: ctx.projectAgents ?? void 0,
|
|
5635
|
+
projectTags: ctx.projectTags ?? void 0,
|
|
5636
|
+
taskTagIds: ctx.taskTagIds ?? void 0,
|
|
5637
|
+
projectObjectives: ctx.projectObjectives ?? void 0
|
|
5638
5638
|
};
|
|
5639
5639
|
}
|
|
5640
5640
|
createQueryBridge() {
|
|
@@ -5833,6 +5833,9 @@ var ProjectConnection = class {
|
|
|
5833
5833
|
onRestartStartCommand(callback) {
|
|
5834
5834
|
this.requireSocket().on("projectRunner:restartStartCommand", callback);
|
|
5835
5835
|
}
|
|
5836
|
+
onAuditTags(callback) {
|
|
5837
|
+
this.requireSocket().on("projectRunner:auditTags", callback);
|
|
5838
|
+
}
|
|
5836
5839
|
// ── Outgoing helpers ───────────────────────────────────────────────────
|
|
5837
5840
|
sendHeartbeat() {
|
|
5838
5841
|
void this.call("projectRunnerHeartbeat", { projectId: this.config.projectId }).catch(() => {
|
|
@@ -6342,21 +6345,24 @@ function buildChatQueryOptions(agentCtx, projectDir, connection) {
|
|
|
6342
6345
|
tools: buildProjectTools(connection)
|
|
6343
6346
|
});
|
|
6344
6347
|
return {
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6348
|
+
options: {
|
|
6349
|
+
model,
|
|
6350
|
+
systemPrompt: {
|
|
6351
|
+
type: "preset",
|
|
6352
|
+
preset: "claude_code",
|
|
6353
|
+
append: buildSystemPrompt2(projectDir, agentCtx)
|
|
6354
|
+
},
|
|
6355
|
+
cwd: projectDir,
|
|
6356
|
+
permissionMode: "bypassPermissions",
|
|
6357
|
+
allowDangerouslySkipPermissions: true,
|
|
6358
|
+
tools: { type: "preset", preset: "claude_code" },
|
|
6359
|
+
mcpServers: { conveyor: mcpServer },
|
|
6360
|
+
maxTurns: settings.maxTurns ?? 30,
|
|
6361
|
+
maxBudgetUsd: settings.maxBudgetUsd ?? 50,
|
|
6362
|
+
effort: settings.effort,
|
|
6363
|
+
thinking: settings.thinking
|
|
6350
6364
|
},
|
|
6351
|
-
|
|
6352
|
-
permissionMode: "bypassPermissions",
|
|
6353
|
-
allowDangerouslySkipPermissions: true,
|
|
6354
|
-
tools: { type: "preset", preset: "claude_code" },
|
|
6355
|
-
mcpServers: { conveyor: mcpServer },
|
|
6356
|
-
maxTurns: settings.maxTurns ?? 30,
|
|
6357
|
-
maxBudgetUsd: settings.maxBudgetUsd ?? 50,
|
|
6358
|
-
effort: settings.effort,
|
|
6359
|
-
thinking: settings.thinking
|
|
6365
|
+
harness
|
|
6360
6366
|
};
|
|
6361
6367
|
}
|
|
6362
6368
|
function processContentBlock(block, responseParts, turnToolCalls) {
|
|
@@ -6405,10 +6411,9 @@ function emitResultCost(event, connection) {
|
|
|
6405
6411
|
}
|
|
6406
6412
|
async function runChatQuery(message, connection, projectDir, sessionId) {
|
|
6407
6413
|
const { agentCtx, chatHistory } = await fetchContext(connection, message.chatId);
|
|
6408
|
-
const options = buildChatQueryOptions(agentCtx, projectDir, connection);
|
|
6414
|
+
const { options, harness } = buildChatQueryOptions(agentCtx, projectDir, connection);
|
|
6409
6415
|
const prompt = buildPrompt(message, chatHistory);
|
|
6410
6416
|
connection.emitStatus("busy");
|
|
6411
|
-
const harness = createHarness();
|
|
6412
6417
|
const events = harness.executeQuery({
|
|
6413
6418
|
prompt,
|
|
6414
6419
|
options,
|
|
@@ -6433,7 +6438,8 @@ async function runChatQuery(message, connection, projectDir, sessionId) {
|
|
|
6433
6438
|
if (responseText) {
|
|
6434
6439
|
await connection.call("postProjectAgentMessage", {
|
|
6435
6440
|
projectId: connection.projectId,
|
|
6436
|
-
content: responseText
|
|
6441
|
+
content: responseText,
|
|
6442
|
+
chatId: message.chatId
|
|
6437
6443
|
});
|
|
6438
6444
|
}
|
|
6439
6445
|
return resultSessionId;
|
|
@@ -6448,7 +6454,8 @@ async function handleProjectChatMessage(message, connection, projectDir, session
|
|
|
6448
6454
|
try {
|
|
6449
6455
|
await connection.call("postProjectAgentMessage", {
|
|
6450
6456
|
projectId: connection.projectId,
|
|
6451
|
-
content: "I encountered an error processing your message. Please try again."
|
|
6457
|
+
content: "I encountered an error processing your message. Please try again.",
|
|
6458
|
+
chatId: message.chatId
|
|
6452
6459
|
});
|
|
6453
6460
|
} catch {
|
|
6454
6461
|
}
|
|
@@ -6580,7 +6587,7 @@ var ProjectRunner = class {
|
|
|
6580
6587
|
await this.connection.connect();
|
|
6581
6588
|
const registration = await this.connection.call("registerProjectAgent", {
|
|
6582
6589
|
projectId: this.connection.projectId,
|
|
6583
|
-
capabilities: ["task", "pm", "code-review"]
|
|
6590
|
+
capabilities: ["task", "pm", "code-review", "audit"]
|
|
6584
6591
|
});
|
|
6585
6592
|
this.branchSwitchCommand = registration.branchSwitchCommand ?? process.env.CONVEYOR_BRANCH_SWITCH_COMMAND;
|
|
6586
6593
|
logger6.info("Registered as project agent", { agentName: registration.agentName });
|
|
@@ -6653,7 +6660,7 @@ var ProjectRunner = class {
|
|
|
6653
6660
|
}
|
|
6654
6661
|
// ── Event wiring ───────────────────────────────────────────────────────
|
|
6655
6662
|
wireEventHandlers() {
|
|
6656
|
-
this.connection.onTaskAssignment((assignment) => this.handleAssignment(assignment));
|
|
6663
|
+
this.connection.onTaskAssignment((assignment) => void this.handleAssignment(assignment));
|
|
6657
6664
|
this.connection.onStopTask((data) => this.handleStopTask(data.taskId));
|
|
6658
6665
|
this.connection.onShutdown(() => void this.stop());
|
|
6659
6666
|
this.connection.onChatMessage((msg) => {
|
|
@@ -6665,6 +6672,7 @@ var ProjectRunner = class {
|
|
|
6665
6672
|
}
|
|
6666
6673
|
);
|
|
6667
6674
|
});
|
|
6675
|
+
this.connection.onAuditTags((request) => void this.handleAuditTags(request));
|
|
6668
6676
|
this.connection.onSwitchBranch((data, cb) => void this.handleSwitchBranch(data, cb));
|
|
6669
6677
|
this.connection.onSyncEnvironment((cb) => void this.handleSyncEnvironment(cb));
|
|
6670
6678
|
this.connection.onRestartStartCommand((cb) => {
|
|
@@ -6677,7 +6685,7 @@ var ProjectRunner = class {
|
|
|
6677
6685
|
try {
|
|
6678
6686
|
await this.connection.call("registerProjectAgent", {
|
|
6679
6687
|
projectId: this.connection.projectId,
|
|
6680
|
-
capabilities: ["task", "pm", "code-review"]
|
|
6688
|
+
capabilities: ["task", "pm", "code-review", "audit"]
|
|
6681
6689
|
});
|
|
6682
6690
|
this.connection.emitStatus(this.activeAgents.size > 0 ? "busy" : "idle");
|
|
6683
6691
|
logger6.info("Re-registered after reconnect");
|
|
@@ -6686,14 +6694,66 @@ var ProjectRunner = class {
|
|
|
6686
6694
|
logger6.error("Failed to re-register after reconnect", { error: msg });
|
|
6687
6695
|
}
|
|
6688
6696
|
}
|
|
6697
|
+
// ── Tag audit ──────────────────────────────────────────────────────────
|
|
6698
|
+
async handleAuditTags(request) {
|
|
6699
|
+
this.connection.emitStatus("busy");
|
|
6700
|
+
try {
|
|
6701
|
+
const { handleTagAudit } = await import("./tag-audit-handler-4RRGIHVB.js");
|
|
6702
|
+
await handleTagAudit(request, this.connection, this.projectDir);
|
|
6703
|
+
} catch (error) {
|
|
6704
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
6705
|
+
logger6.error("Tag audit failed", { error: msg, requestId: request.requestId });
|
|
6706
|
+
try {
|
|
6707
|
+
await this.connection.call("reportTagAuditResult", {
|
|
6708
|
+
projectId: this.connection.projectId,
|
|
6709
|
+
requestId: request.requestId,
|
|
6710
|
+
recommendations: [],
|
|
6711
|
+
summary: `Audit failed: ${msg}`,
|
|
6712
|
+
complete: true
|
|
6713
|
+
});
|
|
6714
|
+
} catch {
|
|
6715
|
+
}
|
|
6716
|
+
} finally {
|
|
6717
|
+
this.connection.emitStatus("idle");
|
|
6718
|
+
}
|
|
6719
|
+
}
|
|
6689
6720
|
// ── Task management ────────────────────────────────────────────────────
|
|
6690
|
-
|
|
6721
|
+
async killAgent(agent, taskId) {
|
|
6722
|
+
const shortId = taskId.slice(0, 8);
|
|
6723
|
+
if (agent.process.exitCode !== null) {
|
|
6724
|
+
logger6.info("Agent process already exited", { taskId: shortId });
|
|
6725
|
+
return;
|
|
6726
|
+
}
|
|
6727
|
+
logger6.info("Killing agent process", { taskId: shortId });
|
|
6728
|
+
agent.process.kill("SIGTERM");
|
|
6729
|
+
await new Promise((resolve2) => {
|
|
6730
|
+
const timer = setTimeout(() => {
|
|
6731
|
+
if (agent.process.exitCode === null) {
|
|
6732
|
+
logger6.warn("Agent did not exit after SIGTERM, sending SIGKILL", { taskId: shortId });
|
|
6733
|
+
agent.process.kill("SIGKILL");
|
|
6734
|
+
}
|
|
6735
|
+
resolve2();
|
|
6736
|
+
}, STOP_TIMEOUT_MS);
|
|
6737
|
+
agent.process.on("exit", () => {
|
|
6738
|
+
clearTimeout(timer);
|
|
6739
|
+
resolve2();
|
|
6740
|
+
});
|
|
6741
|
+
});
|
|
6742
|
+
}
|
|
6743
|
+
// oxlint-disable-next-line max-lines-per-function -- re-assignment logic requires sequential checks
|
|
6744
|
+
async handleAssignment(assignment) {
|
|
6691
6745
|
const { taskId, mode } = assignment;
|
|
6692
6746
|
const shortId = taskId.slice(0, 8);
|
|
6693
6747
|
const agentKey = assignment.agentMode === "code-review" ? `${taskId}:code-review` : taskId;
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6748
|
+
const existing = this.activeAgents.get(agentKey);
|
|
6749
|
+
if (existing) {
|
|
6750
|
+
if (existing.process.exitCode === null) {
|
|
6751
|
+
logger6.info("Re-assignment received, killing existing agent", { taskId: shortId });
|
|
6752
|
+
await this.killAgent(existing, taskId);
|
|
6753
|
+
} else {
|
|
6754
|
+
logger6.info("Stale agent entry (process already exited), cleaning up", { taskId: shortId });
|
|
6755
|
+
}
|
|
6756
|
+
this.activeAgents.delete(agentKey);
|
|
6697
6757
|
}
|
|
6698
6758
|
if (this.activeAgents.size >= MAX_CONCURRENT) {
|
|
6699
6759
|
logger6.warn("Max concurrent agents reached", { maxConcurrent: MAX_CONCURRENT });
|
|
@@ -6735,16 +6795,11 @@ var ProjectRunner = class {
|
|
|
6735
6795
|
}
|
|
6736
6796
|
}
|
|
6737
6797
|
handleStopTask(taskId) {
|
|
6738
|
-
|
|
6739
|
-
|
|
6798
|
+
const agentKey = this.activeAgents.has(taskId) ? taskId : `${taskId}:code-review`;
|
|
6799
|
+
const agent = this.activeAgents.get(agentKey);
|
|
6740
6800
|
if (!agent) return;
|
|
6741
6801
|
logger6.info("Stopping task", { taskId: taskId.slice(0, 8) });
|
|
6742
|
-
agent.
|
|
6743
|
-
const timer = setTimeout(() => {
|
|
6744
|
-
if (this.activeAgents.has(taskId)) agent.process.kill("SIGKILL");
|
|
6745
|
-
}, STOP_TIMEOUT_MS);
|
|
6746
|
-
agent.process.on("exit", () => {
|
|
6747
|
-
clearTimeout(timer);
|
|
6802
|
+
void this.killAgent(agent, taskId).then(() => {
|
|
6748
6803
|
if (agent.usesWorktree) {
|
|
6749
6804
|
try {
|
|
6750
6805
|
removeWorktree(this.projectDir, taskId);
|
|
@@ -7013,7 +7068,6 @@ export {
|
|
|
7013
7068
|
ModeController,
|
|
7014
7069
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
7015
7070
|
Lifecycle,
|
|
7016
|
-
createServiceLogger,
|
|
7017
7071
|
hasUncommittedChanges,
|
|
7018
7072
|
getCurrentBranch,
|
|
7019
7073
|
hasUnpushedCommits,
|
|
@@ -7033,4 +7087,4 @@ export {
|
|
|
7033
7087
|
removeWorktree,
|
|
7034
7088
|
ProjectRunner
|
|
7035
7089
|
};
|
|
7036
|
-
//# sourceMappingURL=chunk-
|
|
7090
|
+
//# sourceMappingURL=chunk-L7ZH423N.js.map
|