@gajae-code/coding-agent 0.2.5 → 0.3.1
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/CHANGELOG.md +28 -0
- package/dist/types/async/job-manager.d.ts +91 -2
- package/dist/types/cli/args.d.ts +1 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/commands/harness.d.ts +37 -0
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +10 -4
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/debug/crash-diagnostics.d.ts +45 -0
- package/dist/types/debug/runtime-gauges.d.ts +6 -0
- package/dist/types/deep-interview/render-middleware.d.ts +6 -0
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/eval/py/kernel.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +10 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +1 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/extensibility/shared-events.d.ts +1 -0
- package/dist/types/gjc-runtime/cli-write-receipt.d.ts +24 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +1 -0
- package/dist/types/gjc-runtime/state-graph.d.ts +4 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +33 -0
- package/dist/types/gjc-runtime/state-renderer.d.ts +65 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/state-schema.d.ts +317 -0
- package/dist/types/gjc-runtime/state-validation.d.ts +6 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +147 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +81 -7
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +43 -0
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +54 -0
- package/dist/types/harness-control-plane/classifier.d.ts +13 -0
- package/dist/types/harness-control-plane/control-endpoint.d.ts +31 -0
- package/dist/types/harness-control-plane/finalize.d.ts +47 -0
- package/dist/types/harness-control-plane/frame-mapper.d.ts +29 -0
- package/dist/types/harness-control-plane/operate.d.ts +35 -0
- package/dist/types/harness-control-plane/owner.d.ts +46 -0
- package/dist/types/harness-control-plane/preserve.d.ts +19 -0
- package/dist/types/harness-control-plane/receipts.d.ts +88 -0
- package/dist/types/harness-control-plane/rpc-adapter.d.ts +66 -0
- package/dist/types/harness-control-plane/seams.d.ts +21 -0
- package/dist/types/harness-control-plane/session-lease.d.ts +65 -0
- package/dist/types/harness-control-plane/state-machine.d.ts +19 -0
- package/dist/types/harness-control-plane/storage.d.ts +53 -0
- package/dist/types/harness-control-plane/types.d.ts +162 -0
- package/dist/types/hooks/skill-keywords.d.ts +2 -1
- package/dist/types/hooks/skill-state.d.ts +23 -29
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -2
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/registry-helpers.d.ts +8 -7
- package/dist/types/internal-urls/types.d.ts +4 -0
- package/dist/types/lsp/index.d.ts +10 -10
- package/dist/types/modes/bridge/auth.d.ts +12 -0
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +9 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +44 -0
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +88 -0
- package/dist/types/modes/bridge/event-stream.d.ts +8 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/hook-selector.d.ts +1 -0
- package/dist/types/modes/components/jobs-overlay-model.d.ts +31 -0
- package/dist/types/modes/components/jobs-overlay.d.ts +30 -0
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +8 -0
- package/dist/types/modes/index.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/jobs-observer.d.ts +57 -0
- package/dist/types/modes/rpc/host-tools.d.ts +1 -16
- package/dist/types/modes/rpc/host-uris.d.ts +1 -38
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +20 -0
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +24 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +46 -0
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +16 -0
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +17 -0
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +44 -0
- package/dist/types/modes/shared/agent-wire/responses.d.ts +4 -0
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +18 -0
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +42 -0
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +27 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +4 -0
- package/dist/types/session/agent-session.d.ts +19 -1
- package/dist/types/skill-state/active-state.d.ts +2 -0
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +1 -1
- package/dist/types/skill-state/workflow-state-contract.d.ts +25 -2
- package/dist/types/skill-state/workflow-state-version.d.ts +3 -0
- package/dist/types/task/executor.d.ts +3 -0
- package/dist/types/task/id.d.ts +7 -0
- package/dist/types/task/index.d.ts +5 -0
- package/dist/types/task/receipt.d.ts +85 -0
- package/dist/types/task/spawn-gate.d.ts +38 -0
- package/dist/types/task/types.d.ts +198 -14
- package/dist/types/tools/cron.d.ts +6 -0
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +26 -1
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +334 -6
- package/src/cli/args.ts +9 -2
- package/src/cli/auth-broker-cli.ts +1 -0
- package/src/cli/config-cli.ts +10 -2
- package/src/cli.ts +2 -0
- package/src/commands/deep-interview.ts +1 -0
- package/src/commands/harness.ts +862 -0
- package/src/commands/launch.ts +2 -2
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +54 -39
- package/src/config/keybindings.ts +6 -0
- package/src/config/settings-schema.ts +13 -3
- package/src/config/settings.ts +5 -0
- package/src/dap/client.ts +17 -3
- package/src/debug/crash-diagnostics.ts +223 -0
- package/src/debug/runtime-gauges.ts +20 -0
- package/src/deep-interview/render-middleware.ts +372 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/defaults/gjc/skills/ralplan/SKILL.md +31 -2
- package/src/defaults/gjc/skills/team/SKILL.md +47 -21
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +106 -13
- package/src/eval/py/executor.ts +21 -1
- package/src/eval/py/kernel.ts +15 -0
- package/src/exec/bash-executor.ts +41 -0
- package/src/extensibility/custom-tools/types.ts +1 -0
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/extensibility/shared-events.ts +1 -0
- package/src/gjc-runtime/cli-write-receipt.ts +31 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +98 -42
- package/src/gjc-runtime/goal-mode-request.ts +11 -3
- package/src/gjc-runtime/ralplan-runtime.ts +235 -43
- package/src/gjc-runtime/state-graph.ts +86 -0
- package/src/gjc-runtime/state-migrations.ts +179 -0
- package/src/gjc-runtime/state-renderer.ts +345 -0
- package/src/gjc-runtime/state-runtime.ts +1155 -46
- package/src/gjc-runtime/state-schema.ts +192 -0
- package/src/gjc-runtime/state-validation.ts +49 -0
- package/src/gjc-runtime/state-writer.ts +749 -0
- package/src/gjc-runtime/team-runtime.ts +1255 -189
- package/src/gjc-runtime/ultragoal-runtime.ts +460 -43
- package/src/gjc-runtime/workflow-command-ref.ts +239 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +1601 -0
- package/src/gjc-runtime/workflow-manifest.ts +427 -0
- package/src/harness-control-plane/classifier.ts +128 -0
- package/src/harness-control-plane/control-endpoint.ts +148 -0
- package/src/harness-control-plane/finalize.ts +222 -0
- package/src/harness-control-plane/frame-mapper.ts +286 -0
- package/src/harness-control-plane/operate.ts +225 -0
- package/src/harness-control-plane/owner.ts +600 -0
- package/src/harness-control-plane/preserve.ts +102 -0
- package/src/harness-control-plane/receipts.ts +216 -0
- package/src/harness-control-plane/rpc-adapter.ts +276 -0
- package/src/harness-control-plane/seams.ts +39 -0
- package/src/harness-control-plane/session-lease.ts +388 -0
- package/src/harness-control-plane/state-machine.ts +98 -0
- package/src/harness-control-plane/storage.ts +257 -0
- package/src/harness-control-plane/types.ts +214 -0
- package/src/hooks/skill-keywords.ts +4 -2
- package/src/hooks/skill-state.ts +197 -64
- package/src/internal-urls/agent-protocol.ts +68 -21
- package/src/internal-urls/artifact-protocol.ts +12 -17
- package/src/internal-urls/docs-index.generated.ts +3 -2
- package/src/internal-urls/registry-helpers.ts +19 -16
- package/src/internal-urls/types.ts +4 -0
- package/src/lsp/client.ts +18 -2
- package/src/main.ts +21 -5
- package/src/modes/bridge/auth.ts +41 -0
- package/src/modes/bridge/bridge-client-bridge.ts +47 -0
- package/src/modes/bridge/bridge-mode.ts +520 -0
- package/src/modes/bridge/bridge-ui-context.ts +200 -0
- package/src/modes/bridge/event-stream.ts +70 -0
- package/src/modes/components/assistant-message.ts +5 -1
- package/src/modes/components/custom-editor.ts +101 -0
- package/src/modes/components/hook-selector.ts +133 -20
- package/src/modes/components/jobs-overlay-model.ts +109 -0
- package/src/modes/components/jobs-overlay.ts +172 -0
- package/src/modes/components/status-line/presets.ts +7 -5
- package/src/modes/components/status-line/segments.ts +25 -0
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/status-line.ts +9 -1
- package/src/modes/controllers/event-controller.ts +71 -6
- package/src/modes/controllers/extension-ui-controller.ts +43 -1
- package/src/modes/controllers/input-controller.ts +105 -9
- package/src/modes/controllers/selector-controller.ts +31 -1
- package/src/modes/index.ts +1 -0
- package/src/modes/interactive-mode.ts +28 -0
- package/src/modes/jobs-observer.ts +204 -0
- package/src/modes/rpc/host-tools.ts +1 -186
- package/src/modes/rpc/host-uris.ts +1 -235
- package/src/modes/rpc/rpc-client.ts +25 -10
- package/src/modes/rpc/rpc-mode.ts +12 -381
- package/src/modes/shared/agent-wire/command-dispatch.ts +341 -0
- package/src/modes/shared/agent-wire/command-validation.ts +131 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +108 -0
- package/src/modes/shared/agent-wire/handshake.ts +117 -0
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +194 -0
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +236 -0
- package/src/modes/shared/agent-wire/protocol.ts +96 -0
- package/src/modes/shared/agent-wire/responses.ts +17 -0
- package/src/modes/shared/agent-wire/scopes.ts +89 -0
- package/src/modes/shared/agent-wire/ui-request-broker.ts +150 -0
- package/src/modes/shared/agent-wire/ui-result.ts +48 -0
- package/src/modes/types.ts +2 -0
- package/src/prompts/agents/executor.md +13 -0
- package/src/prompts/tools/subagent.md +39 -4
- package/src/prompts/tools/task-summary.md +3 -9
- package/src/prompts/tools/task.md +5 -1
- package/src/sdk.ts +8 -0
- package/src/session/agent-session.ts +445 -71
- package/src/session/session-manager.ts +13 -1
- package/src/skill-state/active-state.ts +58 -65
- package/src/skill-state/deep-interview-mutation-guard.ts +114 -17
- package/src/skill-state/initial-phase.ts +2 -0
- package/src/skill-state/workflow-state-contract.ts +33 -4
- package/src/skill-state/workflow-state-version.ts +3 -0
- package/src/slash-commands/builtin-registry.ts +8 -0
- package/src/task/executor.ts +79 -13
- package/src/task/id.ts +33 -0
- package/src/task/index.ts +376 -74
- package/src/task/output-manager.ts +5 -4
- package/src/task/receipt.ts +297 -0
- package/src/task/render.ts +54 -134
- package/src/task/spawn-gate.ts +132 -0
- package/src/task/types.ts +104 -10
- package/src/tools/ask.ts +88 -27
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash.ts +1 -1
- package/src/tools/cron.ts +48 -0
- package/src/tools/find.ts +4 -1
- package/src/tools/index.ts +2 -0
- package/src/tools/path-utils.ts +3 -2
- package/src/tools/read.ts +1 -0
- package/src/tools/search.ts +1 -0
- package/src/tools/skill.ts +6 -1
- package/src/tools/subagent.ts +423 -79
package/src/task/executor.ts
CHANGED
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
* Runs each subagent on the main thread and forwards AgentEvents for progress tracking.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import * as fs from "node:fs/promises";
|
|
7
9
|
import path from "node:path";
|
|
8
10
|
import type { AgentEvent, AgentIdentity, AgentTelemetryConfig, ThinkingLevel } from "@gajae-code/agent-core";
|
|
9
11
|
import { recordHandoff, resolveTelemetry } from "@gajae-code/agent-core";
|
|
10
12
|
import { type JsonSchemaValidationIssue, validateJsonSchemaValue } from "@gajae-code/ai/utils/schema";
|
|
11
13
|
import { logger, prompt, untilAborted } from "@gajae-code/utils";
|
|
14
|
+
import { AsyncJobManager } from "../async";
|
|
12
15
|
import { ModelRegistry } from "../config/model-registry";
|
|
13
16
|
import { resolveModelOverrideWithAuthFallback } from "../config/model-resolver";
|
|
14
17
|
import type { PromptTemplate } from "../config/prompt-templates";
|
|
@@ -112,6 +115,9 @@ export interface ExecutorOptions {
|
|
|
112
115
|
index: number;
|
|
113
116
|
id: string;
|
|
114
117
|
modelOverride?: string | string[];
|
|
118
|
+
runMode?: "initial" | "resume" | "message";
|
|
119
|
+
resumeMessage?: string;
|
|
120
|
+
subagentId?: string;
|
|
115
121
|
/**
|
|
116
122
|
* Active model selector of the parent session, used as an auth-aware fallback
|
|
117
123
|
* if the resolved subagent model has no working credentials. See #985.
|
|
@@ -550,8 +556,8 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
550
556
|
}
|
|
551
557
|
|
|
552
558
|
// Set up artifact paths and write input file upfront if artifacts dir provided
|
|
553
|
-
let subtaskSessionFile: string | undefined;
|
|
554
|
-
if (options.artifactsDir) {
|
|
559
|
+
let subtaskSessionFile: string | undefined = options.sessionFile ?? undefined;
|
|
560
|
+
if (!subtaskSessionFile && options.artifactsDir) {
|
|
555
561
|
subtaskSessionFile = path.join(options.artifactsDir, `${id}.jsonl`);
|
|
556
562
|
}
|
|
557
563
|
|
|
@@ -617,6 +623,8 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
617
623
|
let activeSession: AgentSession | null = null;
|
|
618
624
|
let unsubscribe: (() => void) | null = null;
|
|
619
625
|
let yieldCalled = false;
|
|
626
|
+
let pauseRequested = false;
|
|
627
|
+
let paused = false;
|
|
620
628
|
|
|
621
629
|
// Accumulate usage incrementally from message_end events (no memory for streaming events)
|
|
622
630
|
const accumulatedUsage = {
|
|
@@ -1006,6 +1014,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1006
1014
|
}
|
|
1007
1015
|
}
|
|
1008
1016
|
}
|
|
1017
|
+
paused = (event as { stopReason?: string }).stopReason === "paused";
|
|
1009
1018
|
flushProgress = true;
|
|
1010
1019
|
break;
|
|
1011
1020
|
}
|
|
@@ -1182,6 +1191,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1182
1191
|
hasUI: false,
|
|
1183
1192
|
spawns: spawnsEnv,
|
|
1184
1193
|
taskDepth: childDepth,
|
|
1194
|
+
currentAgentType: agent.name,
|
|
1185
1195
|
parentHindsightSessionState: options.parentHindsightSessionState,
|
|
1186
1196
|
parentTaskPrefix: id,
|
|
1187
1197
|
agentId: id,
|
|
@@ -1193,10 +1203,27 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1193
1203
|
localProtocolOptions: options.localProtocolOptions,
|
|
1194
1204
|
telemetry: subagentTelemetry,
|
|
1195
1205
|
forkContextSeed: options.forkContextSeed,
|
|
1206
|
+
shouldPause: () => pauseRequested,
|
|
1196
1207
|
}),
|
|
1197
1208
|
);
|
|
1198
1209
|
|
|
1199
1210
|
activeSession = session;
|
|
1211
|
+
const liveSubagentId = options.subagentId ?? id;
|
|
1212
|
+
const manager = AsyncJobManager.instance();
|
|
1213
|
+
if (manager) {
|
|
1214
|
+
manager.registerLiveHandle(liveSubagentId, {
|
|
1215
|
+
requestPause: () => {
|
|
1216
|
+
pauseRequested = true;
|
|
1217
|
+
},
|
|
1218
|
+
injectMessage: async (content, deliverAs) => {
|
|
1219
|
+
if (deliverAs === "nextTurn") {
|
|
1220
|
+
await session.prompt(content, { attribution: "agent" });
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
await session.sendUserMessage(content, { deliverAs });
|
|
1224
|
+
},
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1200
1227
|
|
|
1201
1228
|
// Emit lifecycle start event
|
|
1202
1229
|
if (options.eventBus) {
|
|
@@ -1306,6 +1333,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1306
1333
|
progress.retryState = {
|
|
1307
1334
|
attempt: event.attempt,
|
|
1308
1335
|
maxAttempts: event.maxAttempts,
|
|
1336
|
+
unbounded: event.unbounded,
|
|
1309
1337
|
delayMs: event.delayMs,
|
|
1310
1338
|
errorMessage: event.errorMessage,
|
|
1311
1339
|
startedAtMs: Date.now(),
|
|
@@ -1354,13 +1382,24 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1354
1382
|
);
|
|
1355
1383
|
}
|
|
1356
1384
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1385
|
+
const runMode = options.runMode ?? "initial";
|
|
1386
|
+
if (runMode === "message") {
|
|
1387
|
+
await awaitAbortable(session.prompt(options.resumeMessage ?? "", { attribution: "agent" }));
|
|
1388
|
+
await awaitAbortable(session.waitForIdle());
|
|
1389
|
+
} else if (runMode === "resume") {
|
|
1390
|
+
await awaitAbortable(
|
|
1391
|
+
session.prompt("Continue from the paused subagent session state.", { attribution: "agent" }),
|
|
1392
|
+
);
|
|
1393
|
+
await awaitAbortable(session.waitForIdle());
|
|
1394
|
+
} else {
|
|
1395
|
+
await awaitAbortable(session.prompt(task, { attribution: "agent" }));
|
|
1396
|
+
await awaitAbortable(session.waitForIdle());
|
|
1397
|
+
}
|
|
1359
1398
|
|
|
1360
1399
|
const reminderToolChoice = buildNamedToolChoice("yield", session.model);
|
|
1361
1400
|
|
|
1362
1401
|
let retryCount = 0;
|
|
1363
|
-
while (!yieldCalled && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
|
|
1402
|
+
while (!paused && !yieldCalled && retryCount < MAX_YIELD_RETRIES && !abortSignal.aborted) {
|
|
1364
1403
|
// Skip reminders when the model returned a terminal error (e.g.
|
|
1365
1404
|
// rate-limit cap hit, auth failure). Re-prompting would just
|
|
1366
1405
|
// hit the same wall, multiplying the failure noise without
|
|
@@ -1390,7 +1429,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1390
1429
|
}
|
|
1391
1430
|
|
|
1392
1431
|
await awaitAbortable(session.waitForIdle());
|
|
1393
|
-
if (!yieldCalled && !abortSignal.aborted) {
|
|
1432
|
+
if (!paused && !yieldCalled && !abortSignal.aborted) {
|
|
1394
1433
|
exitCode = 0;
|
|
1395
1434
|
}
|
|
1396
1435
|
|
|
@@ -1406,6 +1445,10 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1406
1445
|
exitCode = 1;
|
|
1407
1446
|
error ??= lastAssistant.errorMessage || "Subagent failed";
|
|
1408
1447
|
}
|
|
1448
|
+
if (paused) {
|
|
1449
|
+
exitCode = 0;
|
|
1450
|
+
error = undefined;
|
|
1451
|
+
}
|
|
1409
1452
|
}
|
|
1410
1453
|
} catch (err) {
|
|
1411
1454
|
exitCode = 1;
|
|
@@ -1421,6 +1464,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1421
1464
|
if (exitCode === 0) exitCode = 1;
|
|
1422
1465
|
}
|
|
1423
1466
|
sessionAbortController.abort();
|
|
1467
|
+
AsyncJobManager.instance()?.removeLiveHandle(options.subagentId ?? id);
|
|
1424
1468
|
if (unsubscribe) {
|
|
1425
1469
|
try {
|
|
1426
1470
|
unsubscribe();
|
|
@@ -1495,18 +1539,39 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1495
1539
|
|
|
1496
1540
|
// Write output artifact (input and jsonl already written in real-time)
|
|
1497
1541
|
// Compute output metadata for agent:// URL integration
|
|
1498
|
-
let outputMeta: { lineCount: number; charCount: number } | undefined;
|
|
1542
|
+
let outputMeta: { lineCount: number; charCount: number; byteSize?: number; sha256?: string } | undefined;
|
|
1499
1543
|
let outputPath: string | undefined;
|
|
1500
1544
|
if (options.artifactsDir) {
|
|
1501
|
-
|
|
1545
|
+
const candidateOutputPath = path.join(options.artifactsDir, `${id}.md`);
|
|
1502
1546
|
try {
|
|
1503
|
-
await Bun.write(
|
|
1547
|
+
await Bun.write(candidateOutputPath, rawOutput);
|
|
1548
|
+
const byteSize = Buffer.byteLength(rawOutput, "utf8");
|
|
1549
|
+
const lineCount = rawOutput.split("\n").length;
|
|
1550
|
+
const sha256 = createHash("sha256").update(rawOutput).digest("hex");
|
|
1551
|
+
const createdAt = new Date().toISOString();
|
|
1552
|
+
await Bun.write(
|
|
1553
|
+
`${candidateOutputPath}.meta.json`,
|
|
1554
|
+
JSON.stringify({ id, kind: "agent-output", sizeBytes: byteSize, lineCount, sha256, createdAt }, null, 2),
|
|
1555
|
+
);
|
|
1556
|
+
outputPath = candidateOutputPath;
|
|
1504
1557
|
outputMeta = {
|
|
1505
|
-
lineCount
|
|
1558
|
+
lineCount,
|
|
1506
1559
|
charCount: rawOutput.length,
|
|
1560
|
+
byteSize,
|
|
1561
|
+
sha256,
|
|
1507
1562
|
};
|
|
1508
1563
|
} catch {
|
|
1509
|
-
//
|
|
1564
|
+
// Output or metadata write failed: never advertise an unverifiable
|
|
1565
|
+
// artifact. Best-effort remove any orphaned `.md`/sidecar so a later
|
|
1566
|
+
// agent:// read cannot serve unverified content. Non-fatal.
|
|
1567
|
+
outputPath = undefined;
|
|
1568
|
+
outputMeta = undefined;
|
|
1569
|
+
try {
|
|
1570
|
+
await fs.rm(candidateOutputPath, { force: true });
|
|
1571
|
+
await fs.rm(`${candidateOutputPath}.meta.json`, { force: true });
|
|
1572
|
+
} catch {
|
|
1573
|
+
// best-effort cleanup; ignore
|
|
1574
|
+
}
|
|
1510
1575
|
}
|
|
1511
1576
|
}
|
|
1512
1577
|
|
|
@@ -1527,7 +1592,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1527
1592
|
? yieldAbortReason
|
|
1528
1593
|
: (done.abortReason ?? (signal?.aborted ? resolveSignalAbortReason() : resolveAbortReasonText()))
|
|
1529
1594
|
: undefined;
|
|
1530
|
-
progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
1595
|
+
progress.status = paused ? "paused" : wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
1531
1596
|
scheduleProgress(true);
|
|
1532
1597
|
|
|
1533
1598
|
// Emit lifecycle end event after finalization so yield status is reflected
|
|
@@ -1537,7 +1602,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1537
1602
|
agent: agent.name,
|
|
1538
1603
|
agentSource: agent.source,
|
|
1539
1604
|
description: options.description,
|
|
1540
|
-
status: progress.status as "completed" | "failed" | "aborted",
|
|
1605
|
+
status: progress.status as "completed" | "failed" | "aborted" | "paused",
|
|
1541
1606
|
sessionFile: subtaskSessionFile,
|
|
1542
1607
|
index,
|
|
1543
1608
|
});
|
|
@@ -1564,6 +1629,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1564
1629
|
error: exitCode !== 0 && stderr ? stderr : undefined,
|
|
1565
1630
|
aborted: wasAborted,
|
|
1566
1631
|
abortReason: finalAbortReason,
|
|
1632
|
+
paused,
|
|
1567
1633
|
usage: hasUsage ? accumulatedUsage : undefined,
|
|
1568
1634
|
outputPath,
|
|
1569
1635
|
extractedToolData: progress.extractedToolData,
|
package/src/task/id.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const TASK_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_-]{0,47}$/;
|
|
2
|
+
export const TASK_ID_DESCRIPTION = "filesystem-safe identifier matching ^[A-Za-z0-9][A-Za-z0-9_-]{0,47}$";
|
|
3
|
+
|
|
4
|
+
const ALLOCATED_TASK_ID_PATTERN = new RegExp(
|
|
5
|
+
`^\\d+-${TASK_ID_PATTERN.source.slice(1, -1)}(?:\\.\\d+-${TASK_ID_PATTERN.source.slice(1, -1)})*$`,
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export function isValidTaskId(id: string): boolean {
|
|
9
|
+
return TASK_ID_PATTERN.test(id);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function getTaskIdValidationError(id: unknown): string | undefined {
|
|
13
|
+
if (typeof id !== "string") return "Task id must be a string.";
|
|
14
|
+
if (isValidTaskId(id)) return undefined;
|
|
15
|
+
return `Task id ${JSON.stringify(id)} is invalid. Use ${TASK_ID_DESCRIPTION}.`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function validateTaskId(id: string): string {
|
|
19
|
+
const error = getTaskIdValidationError(id);
|
|
20
|
+
if (error) throw new Error(error);
|
|
21
|
+
return id;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isValidAllocatedTaskId(id: string): boolean {
|
|
25
|
+
return ALLOCATED_TASK_ID_PATTERN.test(id);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function validateAllocatedTaskId(id: string): string {
|
|
29
|
+
if (!isValidAllocatedTaskId(id)) {
|
|
30
|
+
throw new Error(`Allocated task id ${JSON.stringify(id)} is invalid for filesystem artifact paths.`);
|
|
31
|
+
}
|
|
32
|
+
return id;
|
|
33
|
+
}
|