@gajae-code/coding-agent 0.18.11 → 0.18.12
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 +293 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +1 -0
- package/dist/types/cli/update-cli.d.ts +14 -1
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +5 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/config/autorouting-tier-map.d.ts +30 -0
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +39 -0
- package/dist/types/config/file-lock.d.ts +8 -1
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -6
- package/dist/types/config/model-registry.d.ts +56 -5
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +46 -3
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/modes/patch.d.ts +5 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +10 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/types.d.ts +15 -3
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
- package/dist/types/sdk/broker/broker.d.ts +7 -1
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +136 -7
- package/dist/types/sdk/broker/hop.d.ts +36 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +4 -1
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +23 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.d.ts +32 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +58 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +13 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
- package/dist/types/tools/descriptors.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +8 -8
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +22 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +27 -19
- package/src/capability/index.ts +2 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +7 -5
- package/src/cli/public-command-errors.ts +4 -0
- package/src/cli/root-flags.ts +2 -2
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +224 -7
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +199 -42
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/message.ts +10 -3
- package/src/config/autorouting-tier-map.ts +30 -0
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +734 -0
- package/src/config/file-lock.ts +216 -56
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +716 -113
- package/src/config/model-registry.ts +1334 -158
- package/src/config/model-resolver.ts +3 -1
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +60 -3
- package/src/config/settings.ts +458 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/crash/sanitize.ts +4 -0
- package/src/customization/import.ts +3 -1
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/debug/crash-diagnostics.ts +2 -1
- package/src/debug/report-bundle.ts +19 -0
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/helpers.ts +1 -2
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +13 -17
- package/src/edit/modes/patch.ts +187 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/export/html/index.ts +46 -6
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +8 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/gjc-runtime/gc-runtime.ts +33 -6
- package/src/gjc-runtime/launch-tmux.ts +7 -2
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/hooks/native-skill-hook.ts +14 -11
- package/src/internal-urls/docs-index.generated.ts +14 -13
- package/src/internal-urls/local-protocol.ts +142 -8
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/migrate/action-planner.ts +57 -0
- package/src/migrate/adapters/claude-code.ts +23 -4
- package/src/migrate/adapters/codex.ts +22 -4
- package/src/migrate/adapters/index.ts +22 -4
- package/src/migrate/adapters/opencode.ts +6 -1
- package/src/migrate/executor.ts +84 -7
- package/src/migrate/report.ts +19 -2
- package/src/migrate/types.ts +14 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/controllers/command-controller.ts +38 -2
- package/src/modes/controllers/plan-mode-controller.ts +17 -7
- package/src/modes/controllers/selector-controller.ts +62 -6
- package/src/modes/interactive-mode.ts +68 -0
- package/src/modes/theme/theme.ts +15 -0
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +32 -0
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +126 -17
- package/src/sdk/broker/broker-exit.ts +8 -5
- package/src/sdk/broker/broker.ts +342 -82
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1143 -265
- package/src/sdk/broker/hop.ts +274 -0
- package/src/sdk/broker/lifecycle-ledger.ts +35 -11
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +62 -12
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/index.ts +52 -21
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/cli/session-cli.ts +21 -6
- package/src/sdk/host/session-runtime.test.ts +118 -23
- package/src/sdk/host/session-runtime.ts +352 -47
- package/src/sdk/lifecycle/service.ts +1 -0
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/protocol/adapter-validation.ts +53 -11
- package/src/sdk/protocol/operation-inventory.generated.json +101 -2
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +114 -61
- package/src/session/agent-session.ts +1043 -81
- package/src/session/internal/managed-session-scope.ts +126 -39
- package/src/session/internal/managed-session-storage.ts +14 -11
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +236 -14
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +491 -32
- package/src/slash-commands/builtin-registry.ts +15 -3
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/task/executor.ts +103 -12
- package/src/task/index.ts +389 -175
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +3 -0
- package/src/tools/bash-allowed-prefixes.ts +153 -5
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash.ts +14 -0
- package/src/tools/debug.ts +7 -6
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +34 -2
- package/src/tools/fetch.ts +3 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/output-meta.ts +23 -2
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +17 -35
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +108 -1
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +31 -3
- package/src/tools/write.ts +35 -3
- package/src/utils/commit-message-generator.ts +9 -2
- package/src/utils/file-mentions.ts +29 -1
- package/src/utils/title-generator.ts +7 -2
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
|
@@ -45,7 +45,9 @@ import {
|
|
|
45
45
|
createInvocationReconciliation,
|
|
46
46
|
createSdkSessionRuntimeExtension,
|
|
47
47
|
createSdkSurfaceFactory,
|
|
48
|
+
type PersistenceInstrumentationEvent,
|
|
48
49
|
RetainedTerminalBoundaryRegistry,
|
|
50
|
+
type SdkOnlyDeadlineRecoveryCheckpoint,
|
|
49
51
|
type SdkOnlyInvocationRecord,
|
|
50
52
|
type SdkOnlyReconciliationStore,
|
|
51
53
|
type SdkOnlyTerminalAbortSeams,
|
|
@@ -143,7 +145,11 @@ test("thinking.set uses the control setter and reports the applied session level
|
|
|
143
145
|
const transport = memoryTransport(frame => {
|
|
144
146
|
if (frame.type === "control_response" && frame.id === "thinking-set") response.resolve(frame);
|
|
145
147
|
});
|
|
146
|
-
createSdkSessionRuntimeExtension(api, {
|
|
148
|
+
createSdkSessionRuntimeExtension(api, {
|
|
149
|
+
agentDir: cwd,
|
|
150
|
+
ensureBrokerImpl: async () => testBrokerDiscovery,
|
|
151
|
+
createTransport: async () => transport,
|
|
152
|
+
});
|
|
147
153
|
const ctx = extensionContext(transport.sessionId, cwd);
|
|
148
154
|
try {
|
|
149
155
|
await handlers.get("session_start")?.({}, ctx);
|
|
@@ -4443,7 +4449,10 @@ describe("SessionSdkSessionRuntime", () => {
|
|
|
4443
4449
|
function createTestRuntimeExtension(api: ExtensionAPI, options: CreateSdkSessionRuntimeOptions): void {
|
|
4444
4450
|
createSdkSessionRuntimeExtension(api, {
|
|
4445
4451
|
...options,
|
|
4446
|
-
ensureBrokerImpl:
|
|
4452
|
+
ensureBrokerImpl: async input => {
|
|
4453
|
+
if (options.ensureBrokerImpl) return await options.ensureBrokerImpl(input);
|
|
4454
|
+
return testBrokerDiscovery;
|
|
4455
|
+
},
|
|
4447
4456
|
});
|
|
4448
4457
|
}
|
|
4449
4458
|
|
|
@@ -4609,6 +4618,8 @@ async function invocationHarness(
|
|
|
4609
4618
|
}) => void;
|
|
4610
4619
|
branch?: unknown[];
|
|
4611
4620
|
onInvocationCompletionReconciled?: (kind: string, correlation: { commandId: string; turnId: string }) => void;
|
|
4621
|
+
/** Test-only instrumentation of the persistence chain. */
|
|
4622
|
+
onPersistenceInstrumentation?: (event: PersistenceInstrumentationEvent) => void;
|
|
4612
4623
|
/** Override/extend the INTERNAL terminal-abort seams the runtime is threaded. */
|
|
4613
4624
|
terminalAbortSeams?: Partial<SdkOnlyTerminalAbortSeams>;
|
|
4614
4625
|
},
|
|
@@ -4640,7 +4651,7 @@ async function invocationHarness(
|
|
|
4640
4651
|
createTestRuntimeExtension(api, {
|
|
4641
4652
|
agentDir: cwd,
|
|
4642
4653
|
...(hooks.onLifecycleDrainTimeout ? { onLifecycleDrainTimeoutForTests: hooks.onLifecycleDrainTimeout } : {}),
|
|
4643
|
-
...(interceptorStore || hooks.terminalAbortSeams
|
|
4654
|
+
...(interceptorStore || hooks.terminalAbortSeams || hooks.onPersistenceInstrumentation
|
|
4644
4655
|
? {
|
|
4645
4656
|
terminalAbortSeams: {
|
|
4646
4657
|
getTerminalTurnEpoch: () => undefined,
|
|
@@ -4648,6 +4659,9 @@ async function invocationHarness(
|
|
|
4648
4659
|
cancelPendingPreflightForTerminalAbort: () => {},
|
|
4649
4660
|
abortPromptAndWaitWithTerminal: async () => ({ status: "settled", terminalScope: {} }),
|
|
4650
4661
|
...(interceptorStore ? { getReconciliationStore: () => interceptorStore } : {}),
|
|
4662
|
+
...(hooks.onPersistenceInstrumentation
|
|
4663
|
+
? { onPersistenceInstrumentationForTests: hooks.onPersistenceInstrumentation }
|
|
4664
|
+
: {}),
|
|
4651
4665
|
...hooks.terminalAbortSeams,
|
|
4652
4666
|
},
|
|
4653
4667
|
}
|
|
@@ -6176,6 +6190,7 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
6176
6190
|
let harness: InvocationHarness | undefined;
|
|
6177
6191
|
let session: AgentSession | undefined;
|
|
6178
6192
|
let authStorage: AuthStorage | undefined;
|
|
6193
|
+
let restoreEmission: (() => void) | undefined;
|
|
6179
6194
|
let providerCalls = 0;
|
|
6180
6195
|
try {
|
|
6181
6196
|
const real = await createTerminalizationSession(
|
|
@@ -6186,6 +6201,7 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
6186
6201
|
return createMockModel({ responses: [{ content: ["started"] }] }).stream(model, context, options);
|
|
6187
6202
|
},
|
|
6188
6203
|
{ "todo.enabled": true, "todo.reminders": true, "todo.reminders.max": 1, "retry.enabled": false },
|
|
6204
|
+
true,
|
|
6189
6205
|
);
|
|
6190
6206
|
session = real.session;
|
|
6191
6207
|
session.setConfiguredModelChain("default", [selector(real.model)], "terminal-throw-test");
|
|
@@ -6197,9 +6213,16 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
6197
6213
|
isIdle: () => !session?.isStreaming,
|
|
6198
6214
|
sendUserMessage: realSendUserMessage(session),
|
|
6199
6215
|
});
|
|
6200
|
-
|
|
6201
|
-
|
|
6216
|
+
const runner = session.extensionRunner;
|
|
6217
|
+
if (!runner) throw new Error("Expected the real awaited terminal extension bridge.");
|
|
6218
|
+
const emit = runner.emit.bind(runner);
|
|
6219
|
+
const emission = spyOn(runner, "emit").mockImplementation(async event => {
|
|
6220
|
+
const result = await emit(event);
|
|
6221
|
+
if (event.type === "agent_start" || event.type === "agent_failed" || event.type === "agent_end")
|
|
6222
|
+
await harness?.emit(event.type, event);
|
|
6223
|
+
return result;
|
|
6202
6224
|
});
|
|
6225
|
+
restoreEmission = () => emission.mockRestore();
|
|
6203
6226
|
const accepted = await harness.control("turn.prompt", { text: "finish the outstanding work" });
|
|
6204
6227
|
expect(accepted.ok).toBe(true);
|
|
6205
6228
|
const correlation = { commandId: accepted.result?.commandId, turnId: accepted.result?.turnId };
|
|
@@ -6226,6 +6249,7 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
6226
6249
|
outcome: { kind: "failed" },
|
|
6227
6250
|
});
|
|
6228
6251
|
} finally {
|
|
6252
|
+
restoreEmission?.();
|
|
6229
6253
|
await session?.dispose();
|
|
6230
6254
|
authStorage?.close();
|
|
6231
6255
|
await harness?.stop();
|
|
@@ -8521,8 +8545,23 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8521
8545
|
const sessionId = "deadline-captured-uncertain";
|
|
8522
8546
|
const sessionFile = path.join(cwd, ".gjc", "state", `${sessionId}.jsonl`);
|
|
8523
8547
|
await Bun.write(sessionFile, "");
|
|
8524
|
-
|
|
8548
|
+
// Chain-level evidence for the CI-only hang: every serialized store op
|
|
8549
|
+
// (including the terminal variants the runtime persistence log cannot see).
|
|
8550
|
+
const storeLog: string[] = [];
|
|
8551
|
+
const store = createReconciliationStore({
|
|
8552
|
+
sessionFile,
|
|
8553
|
+
sessionId,
|
|
8554
|
+
onInstrumentationForTests: event => {
|
|
8555
|
+
storeLog.push(
|
|
8556
|
+
`${event.at}:${event.phase}:${event.operation ?? ""}:${event.substep ?? ""}:${event.detail ?? ""}${event.error ? `:${event.error}` : ""}`,
|
|
8557
|
+
);
|
|
8558
|
+
},
|
|
8559
|
+
});
|
|
8525
8560
|
const activeTools = new Set(["unfenced-tool"]);
|
|
8561
|
+
const toolDrainObserved = Promise.withResolvers<void>();
|
|
8562
|
+
const terminalPublication = Promise.withResolvers<SdkOnlyDeadlineRecoveryCheckpoint>();
|
|
8563
|
+
const recoveryCheckpoints: SdkOnlyDeadlineRecoveryCheckpoint[] = [];
|
|
8564
|
+
const persistenceLog: Array<PersistenceInstrumentationEvent & { label: string }> = [];
|
|
8526
8565
|
let boundaryWaitStarted = false;
|
|
8527
8566
|
let abortCalls = 0;
|
|
8528
8567
|
let harness: InvocationHarness | undefined;
|
|
@@ -8531,25 +8570,30 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8531
8570
|
settings: {
|
|
8532
8571
|
// This test covers deferred terminal recovery, not deadline-triggered worktree persistence.
|
|
8533
8572
|
get: (key: string) =>
|
|
8534
|
-
key === "sdk.promptDeadlineMs"
|
|
8535
|
-
? 150
|
|
8536
|
-
: key === "sdk.promptMaxRuntimeMs"
|
|
8537
|
-
? 60_000
|
|
8538
|
-
: key === "sdk.flushWorktreeOnDeadline"
|
|
8539
|
-
? false
|
|
8540
|
-
: undefined,
|
|
8573
|
+
key === "sdk.promptDeadlineMs" ? 150 : key === "sdk.promptMaxRuntimeMs" ? 60_000 : undefined,
|
|
8541
8574
|
} as unknown as Settings,
|
|
8542
8575
|
sendUserMessage: async (_content, options) => {
|
|
8543
8576
|
await options?.onPreflightAcceptCommit?.();
|
|
8544
8577
|
await neverSettlingPromise();
|
|
8545
8578
|
},
|
|
8579
|
+
onPersistenceInstrumentation: event => {
|
|
8580
|
+
const label = `${event.phase}:${event.operation ?? "main"}:${event.substep ?? ""}`;
|
|
8581
|
+
persistenceLog.push({ ...event, label });
|
|
8582
|
+
},
|
|
8546
8583
|
terminalAbortSeams: {
|
|
8547
8584
|
getReconciliationStore: () => store,
|
|
8548
8585
|
getTerminalTurnEpoch: () => 109,
|
|
8549
8586
|
getActivePromptHandle: () => "deadline-captured-uncertain-run",
|
|
8587
|
+
onDeadlineRecoveryCheckpointForTests: checkpoint => {
|
|
8588
|
+
recoveryCheckpoints.push(checkpoint);
|
|
8589
|
+
if (checkpoint.stage === "publication-result" && checkpoint.result === "published")
|
|
8590
|
+
terminalPublication.resolve(checkpoint);
|
|
8591
|
+
},
|
|
8550
8592
|
pendingToolExecutions: () => {
|
|
8551
8593
|
if (activeTools.size > 0) boundaryWaitStarted = true;
|
|
8552
|
-
|
|
8594
|
+
const pending = [...activeTools];
|
|
8595
|
+
if (pending.length === 0) toolDrainObserved.resolve();
|
|
8596
|
+
return pending;
|
|
8553
8597
|
},
|
|
8554
8598
|
abortPromptAndWaitWithTerminal: async () => {
|
|
8555
8599
|
abortCalls += 1;
|
|
@@ -8559,7 +8603,10 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8559
8603
|
});
|
|
8560
8604
|
const accepted = await harness.control("turn.prompt", { text: "capture uncertain end" });
|
|
8561
8605
|
expect(accepted.ok).toBe(true);
|
|
8562
|
-
const
|
|
8606
|
+
const commandId = accepted.result?.commandId;
|
|
8607
|
+
const turnId = accepted.result?.turnId;
|
|
8608
|
+
if (commandId === undefined || turnId === undefined) throw new Error("Expected prompt correlation");
|
|
8609
|
+
const correlation = { commandId, turnId };
|
|
8563
8610
|
await harness.emit("agent_start");
|
|
8564
8611
|
await harness.emit("tool_execution_start", {
|
|
8565
8612
|
type: "tool_execution_start",
|
|
@@ -8597,8 +8644,37 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8597
8644
|
});
|
|
8598
8645
|
|
|
8599
8646
|
activeTools.clear();
|
|
8600
|
-
//
|
|
8601
|
-
|
|
8647
|
+
// Wait until the deadline recovery loop has actually observed the exact
|
|
8648
|
+
// tool-set drain; clearing the test seam alone does not wake its bounded
|
|
8649
|
+
// retry timer.
|
|
8650
|
+
await toolDrainObserved.promise;
|
|
8651
|
+
// Wait for the durable terminal boundary itself, not an arbitrary status
|
|
8652
|
+
// polling budget that can expire while a slow CI filesystem is flushing it.
|
|
8653
|
+
const published = await terminalPublication.promise;
|
|
8654
|
+
expect(published.correlation).toEqual(correlation);
|
|
8655
|
+
let terminalStatus: NonNullable<ResponseFrame["result"]>;
|
|
8656
|
+
try {
|
|
8657
|
+
terminalStatus = await settledStatus(harness, "turn.prompt_status", correlation);
|
|
8658
|
+
} catch (error) {
|
|
8659
|
+
const finalRecord = store.snapshot().find(record => record.commandId === correlation.commandId) as
|
|
8660
|
+
| (SdkOnlyInvocationRecord & {
|
|
8661
|
+
pendingOutcome?: unknown;
|
|
8662
|
+
deadlineRecoveryPending?: boolean;
|
|
8663
|
+
terminalAt?: number;
|
|
8664
|
+
})
|
|
8665
|
+
| undefined;
|
|
8666
|
+
throw new Error(
|
|
8667
|
+
`${error instanceof Error ? error.message : String(error)}; persistence_log=${JSON.stringify(persistenceLog)}; store_log=${JSON.stringify(storeLog)}; deadline checkpoints=${JSON.stringify(recoveryCheckpoints)}; durable=${JSON.stringify(
|
|
8668
|
+
{
|
|
8669
|
+
status: finalRecord?.status,
|
|
8670
|
+
terminalAt: finalRecord?.terminalAt,
|
|
8671
|
+
deadlineRecoveryPending: finalRecord?.deadlineRecoveryPending,
|
|
8672
|
+
pendingOutcome: finalRecord?.pendingOutcome,
|
|
8673
|
+
},
|
|
8674
|
+
)}`,
|
|
8675
|
+
);
|
|
8676
|
+
}
|
|
8677
|
+
expect(terminalStatus).toMatchObject({
|
|
8602
8678
|
status: "terminal_ok",
|
|
8603
8679
|
outcome: { kind: "stopped", reason: "cancelled" },
|
|
8604
8680
|
});
|
|
@@ -8618,6 +8694,7 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8618
8694
|
const sessionFile = path.join(cwd, "session.json");
|
|
8619
8695
|
await Bun.write(sessionFile, "");
|
|
8620
8696
|
const store = createReconciliationStore({ sessionFile, sessionId });
|
|
8697
|
+
const deadlineStarted = Promise.withResolvers<void>();
|
|
8621
8698
|
let abortCalls = 0;
|
|
8622
8699
|
let harness: InvocationHarness | undefined;
|
|
8623
8700
|
try {
|
|
@@ -8633,7 +8710,10 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8633
8710
|
terminalAbortSeams: {
|
|
8634
8711
|
getReconciliationStore: () => store,
|
|
8635
8712
|
getTerminalTurnEpoch: () => 17,
|
|
8636
|
-
getActivePromptHandle: () =>
|
|
8713
|
+
getActivePromptHandle: () => {
|
|
8714
|
+
deadlineStarted.resolve();
|
|
8715
|
+
return "unobservable-tool-run";
|
|
8716
|
+
},
|
|
8637
8717
|
abortPromptAndWaitWithTerminal: async () => {
|
|
8638
8718
|
abortCalls += 1;
|
|
8639
8719
|
return { status: "settled" };
|
|
@@ -8647,7 +8727,10 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8647
8727
|
await harness.emit("agent_failed", {
|
|
8648
8728
|
error: Object.assign(new Error("provider unavailable"), { code: "provider_unavailable" }),
|
|
8649
8729
|
});
|
|
8650
|
-
|
|
8730
|
+
// Expiry must install its recoverable observation before the real end
|
|
8731
|
+
// arrives; otherwise an end racing the durable uncertainty write can
|
|
8732
|
+
// terminalize from the diagnostic alone.
|
|
8733
|
+
await deadlineStarted.promise;
|
|
8651
8734
|
expect(abortCalls).toBe(0);
|
|
8652
8735
|
expect(await harness.query("turn.prompt_status", correlation)).toMatchObject({
|
|
8653
8736
|
result: { status: "in_flight" },
|
|
@@ -8655,7 +8738,6 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8655
8738
|
expect(correlatedFrames(harness, correlation).filter(frame => frame.kind === "agent_failed")).toHaveLength(1);
|
|
8656
8739
|
expect(correlatedFrames(harness, correlation).filter(frame => frame.kind === "agent_end")).toEqual([]);
|
|
8657
8740
|
await harness.emit("agent_end", { stopReason: "cancelled" });
|
|
8658
|
-
await Bun.sleep(100);
|
|
8659
8741
|
expect(await harness.query("turn.prompt_status", correlation)).toMatchObject({
|
|
8660
8742
|
result: { status: "in_flight" },
|
|
8661
8743
|
});
|
|
@@ -8794,7 +8876,9 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
8794
8876
|
: key === "sdk.flushWorktreeOnDeadline"
|
|
8795
8877
|
? true
|
|
8796
8878
|
: undefined,
|
|
8797
|
-
|
|
8879
|
+
// Primary checkout: only a user/global true opts in. `has()` would
|
|
8880
|
+
// also be true for a project file, which must not authorize this.
|
|
8881
|
+
getGlobal: (key: string) => (key === "sdk.flushWorktreeOnDeadline" ? true : undefined),
|
|
8798
8882
|
getAgentDir: () => path.join(cwd, ".gjc", "agent"),
|
|
8799
8883
|
} as unknown as Settings,
|
|
8800
8884
|
sendUserMessage: async (_content, options) => {
|
|
@@ -9003,8 +9087,11 @@ describe("accepted-control zero-execution bound (#4668)", () => {
|
|
|
9003
9087
|
expect(await harness.query("turn.prompt_status", queuedIds)).toMatchObject({ result: { status: "accepted" } });
|
|
9004
9088
|
expect(abortCalls).toBe(0);
|
|
9005
9089
|
expect(correlatedFrames(harness, queuedIds).filter(frame => frame.kind === "agent_failed")).toHaveLength(0);
|
|
9006
|
-
promoted
|
|
9090
|
+
// The lease is captured when the follow-up is promoted, not when the
|
|
9091
|
+
// setting later changes. Restore the long deadline first so this run
|
|
9092
|
+
// does not inherit the 100ms queue probe and expire under settledStatus.
|
|
9007
9093
|
promptDeadlineMs = 600_000;
|
|
9094
|
+
promoted?.({ startsOwnRun: true });
|
|
9008
9095
|
await Bun.sleep(150);
|
|
9009
9096
|
expect((await harness.query("turn.prompt_status", queuedIds)).result?.status).toMatch(/accepted|in_flight/);
|
|
9010
9097
|
expect(await harness.query("turn.prompt_status", activeIds)).toMatchObject({
|
|
@@ -11489,6 +11576,7 @@ test.each([
|
|
|
11489
11576
|
let transportCreations = 0;
|
|
11490
11577
|
createSdkSessionRuntimeExtension(api, {
|
|
11491
11578
|
agentDir: cwd,
|
|
11579
|
+
ensureBrokerImpl: async () => testBrokerDiscovery,
|
|
11492
11580
|
createTransport: async () => {
|
|
11493
11581
|
transportCreations++;
|
|
11494
11582
|
return transport;
|
|
@@ -11631,6 +11719,7 @@ test.each([
|
|
|
11631
11719
|
])("SDK-only queued terminal recovery permits replacement after EIO (early shutdown=%s)", async earlyShutdown => {
|
|
11632
11720
|
const cwd = await mkdtemp(path.join(os.tmpdir(), "gjc-sdk-terminal-recovery-"));
|
|
11633
11721
|
const handlers = new Map<string, (event: unknown, ctx: ExtensionContext) => Promise<void> | void>();
|
|
11722
|
+
const recoveryRetired = Promise.withResolvers<SdkOnlyDeadlineRecoveryCheckpoint>();
|
|
11634
11723
|
let transport = memoryTransport();
|
|
11635
11724
|
const sessionId = transport.sessionId;
|
|
11636
11725
|
const sessionFile = path.join(cwd, `${sessionId}.json`);
|
|
@@ -11665,6 +11754,7 @@ test.each([
|
|
|
11665
11754
|
get: (key: string) =>
|
|
11666
11755
|
key === "sdk.promptDeadlineMs" ? 1_500 : key === "sdk.promptMaxRuntimeMs" ? 15_000 : undefined,
|
|
11667
11756
|
} as unknown as Settings,
|
|
11757
|
+
ensureBrokerImpl: async () => testBrokerDiscovery,
|
|
11668
11758
|
createTransport: async () => {
|
|
11669
11759
|
creations++;
|
|
11670
11760
|
transport = memoryTransport();
|
|
@@ -11676,6 +11766,9 @@ test.each([
|
|
|
11676
11766
|
getActivePromptHandle: () => "unrelated-handle",
|
|
11677
11767
|
cancelPendingPreflightForTerminalAbort: () => {},
|
|
11678
11768
|
abortPromptAndWaitWithTerminal: async () => ({ status: "settled", terminalScope: {} }),
|
|
11769
|
+
onDeadlineRecoveryCheckpointForTests: checkpoint => {
|
|
11770
|
+
if (checkpoint.stage === "deadline-recovery-retired") recoveryRetired.resolve(checkpoint);
|
|
11771
|
+
},
|
|
11679
11772
|
},
|
|
11680
11773
|
});
|
|
11681
11774
|
const ctx = { ...extensionContext(sessionId, cwd), isIdle: () => true } as unknown as ExtensionContext;
|
|
@@ -11717,7 +11810,7 @@ test.each([
|
|
|
11717
11810
|
expect(accepted.ok).toBe(true);
|
|
11718
11811
|
commandId = accepted.result?.commandId;
|
|
11719
11812
|
const turnId = accepted.result?.turnId;
|
|
11720
|
-
|
|
11813
|
+
if (commandId === undefined || turnId === undefined) throw new Error("Expected queued prompt correlation");
|
|
11721
11814
|
await waitFor(() => queued && queueSignal !== undefined, "queued admission");
|
|
11722
11815
|
expect(await request({ type: "control_request", operation: "turn.abort", input: {} })).toMatchObject({
|
|
11723
11816
|
ok: true,
|
|
@@ -11742,6 +11835,8 @@ test.each([
|
|
|
11742
11835
|
status: "failed",
|
|
11743
11836
|
error: { code: "cancelled" },
|
|
11744
11837
|
});
|
|
11838
|
+
const retired = await recoveryRetired.promise;
|
|
11839
|
+
expect(retired.correlation).toEqual({ commandId, turnId });
|
|
11745
11840
|
if (!earlyShutdown) await handlers.get("session_shutdown")?.({}, ctx);
|
|
11746
11841
|
await handlers.get("session_start")?.({}, ctx);
|
|
11747
11842
|
expect(creations).toBe(2);
|