@gajae-code/coding-agent 0.16.7 → 0.17.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 +180 -1
- package/dist/types/capability/fs.d.ts +37 -4
- package/dist/types/capability/index.d.ts +19 -0
- package/dist/types/capability/types.d.ts +9 -0
- package/dist/types/cli/doctor/args.d.ts +36 -0
- package/dist/types/cli/doctor/checks.d.ts +18 -0
- package/dist/types/cli/doctor/config-repairs.d.ts +38 -0
- package/dist/types/cli/doctor/context.d.ts +89 -0
- package/dist/types/cli/doctor/files.d.ts +27 -0
- package/dist/types/cli/doctor/ids.d.ts +20 -0
- package/dist/types/cli/doctor/install-repairs.d.ts +94 -0
- package/dist/types/cli/doctor/journal.d.ts +43 -0
- package/dist/types/cli/doctor/managed-link.d.ts +39 -0
- package/dist/types/cli/doctor/native-probe.d.ts +2 -0
- package/dist/types/cli/doctor/permission-repairs.d.ts +25 -0
- package/dist/types/cli/doctor/plugin-quarantine.d.ts +77 -0
- package/dist/types/cli/doctor/plugin-restore.d.ts +40 -0
- package/dist/types/cli/doctor/plugin-targets.d.ts +11 -0
- package/dist/types/cli/doctor/probe-client.d.ts +9 -0
- package/dist/types/cli/doctor/probe-types.d.ts +18 -0
- package/dist/types/cli/doctor/probe.d.ts +3 -0
- package/dist/types/cli/doctor/projection-probe.d.ts +2 -0
- package/dist/types/cli/doctor/repairs.d.ts +28 -0
- package/dist/types/cli/doctor/report.d.ts +27 -0
- package/dist/types/cli/doctor/runner.d.ts +4 -0
- package/dist/types/cli/doctor/safety.d.ts +10 -0
- package/dist/types/cli/doctor/service-repairs.d.ts +8 -0
- package/dist/types/cli/doctor/service-targets.d.ts +41 -0
- package/dist/types/cli/doctor/types.d.ts +145 -0
- package/dist/types/cli/doctor-cli.d.ts +7 -0
- package/dist/types/cli/doctor-supervisor.d.ts +121 -0
- package/dist/types/cli/doctor-worker.d.ts +29 -0
- package/dist/types/cli/install-activation.d.ts +158 -0
- package/dist/types/cli/macos-community-app.d.ts +41 -0
- package/dist/types/cli/mcp-cli.d.ts +0 -11
- package/dist/types/cli/update-cli.d.ts +41 -4
- package/dist/types/cli-main.d.ts +174 -0
- package/dist/types/cli.d.ts +1 -171
- package/dist/types/commands/doctor.d.ts +7 -0
- package/dist/types/commands/sdk.d.ts +17 -8
- package/dist/types/config/autorouting-tier-map.d.ts +19 -0
- package/dist/types/config/file-lock.d.ts +27 -3
- package/dist/types/config/model-preset-registry.d.ts +1 -0
- package/dist/types/config/model-registry.d.ts +12 -5
- package/dist/types/config/model-resolver.d.ts +16 -3
- package/dist/types/config/models-config-schema.d.ts +2 -0
- package/dist/types/config/settings-schema.d.ts +1 -1
- package/dist/types/coordinator-mcp/question-gate-codec.d.ts +1 -1
- package/dist/types/coordinator-mcp/session-reaper.d.ts +15 -5
- package/dist/types/cursor.d.ts +9 -9
- package/dist/types/discovery/agents-md.d.ts +6 -1
- package/dist/types/discovery/helpers.d.ts +36 -7
- package/dist/types/discovery/index.d.ts +1 -1
- package/dist/types/discovery/mcp-json.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +22 -1
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +14 -1
- package/dist/types/extensibility/gjc-plugins/paths.d.ts +2 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +25 -0
- package/dist/types/extensibility/plugins/manager.d.ts +33 -4
- package/dist/types/extensibility/plugins/marketplace/cache.d.ts +6 -0
- package/dist/types/extensibility/plugins/marketplace/manager.d.ts +186 -0
- package/dist/types/extensibility/plugins/marketplace/registry.d.ts +27 -0
- package/dist/types/extensibility/plugins/marketplace/source-resolver.d.ts +16 -1
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +16 -3
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +6 -0
- package/dist/types/gjc-runtime/launch-worktree.d.ts +53 -0
- package/dist/types/gjc-runtime/session-layout.d.ts +8 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +15 -0
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +13 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +6 -0
- package/dist/types/main.d.ts +19 -1
- package/dist/types/modes/acp/acp-agent.d.ts +40 -0
- package/dist/types/modes/components/agent-dashboard.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/runtime-mcp/config-writer.d.ts +47 -0
- package/dist/types/runtime-mcp/policy-json-edit.d.ts +60 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +4 -0
- package/dist/types/runtime-mcp/types.d.ts +2 -2
- package/dist/types/sdk/acp/adapter.d.ts +5 -1
- package/dist/types/sdk/broker/broker.d.ts +51 -0
- package/dist/types/sdk/broker/daemon-entry.d.ts +39 -0
- package/dist/types/sdk/broker/discovery.d.ts +38 -0
- package/dist/types/sdk/broker/doctor-restart.d.ts +79 -0
- package/dist/types/sdk/broker/endpoint-authority.d.ts +7 -0
- package/dist/types/sdk/broker/ensure.d.ts +14 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +2 -0
- package/dist/types/sdk/broker/process-incarnation.d.ts +50 -0
- package/dist/types/sdk/broker/runtime.d.ts +26 -0
- package/dist/types/sdk/broker/session-index.d.ts +13 -4
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +14 -0
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +16 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +101 -6
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +16 -0
- package/dist/types/sdk/bus/daemon-startup-exclusion.d.ts +43 -0
- package/dist/types/sdk/bus/doctor-daemon-restart-client.d.ts +51 -0
- package/dist/types/sdk/bus/doctor-daemon-restart.d.ts +39 -0
- package/dist/types/sdk/bus/index.d.ts +2 -0
- package/dist/types/sdk/bus/notification-service.d.ts +3 -0
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +11 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-owner-registry.d.ts +1 -0
- package/dist/types/sdk/bus/telegram-daemon.d.ts +36 -5
- package/dist/types/sdk/cli/session-cli.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +4 -0
- package/dist/types/sdk/host/surface-policy.d.ts +3 -1
- package/dist/types/sdk/lifecycle/service.d.ts +44 -10
- package/dist/types/sdk/prompt-deadline-lease.d.ts +6 -3
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -2
- package/dist/types/sdk/prompt-failure.d.ts +47 -0
- package/dist/types/sdk/prompt-status.d.ts +19 -0
- package/dist/types/sdk/router/session-router.d.ts +3 -4
- package/dist/types/sdk/service-artifact-paths.d.ts +16 -0
- package/dist/types/sdk/session-authority.d.ts +9 -0
- package/dist/types/sdk/session.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +1 -1
- package/dist/types/session/blob-store.d.ts +1 -1
- package/dist/types/session/fallback-chain-controller.d.ts +3 -6
- package/dist/types/session/internal/managed-session-scope.d.ts +44 -0
- package/dist/types/session/primary-control-surface.d.ts +4 -0
- package/dist/types/session/session-manager.d.ts +6 -0
- package/dist/types/system-prompt.d.ts +6 -0
- package/dist/types/tools/ask.d.ts +25 -0
- package/dist/types/tools/image-gen.d.ts +0 -4
- package/dist/types/tools/skill-discovery.d.ts +7 -5
- package/dist/types/tools/ultragoal-ask-guard.d.ts +7 -4
- package/dist/types/utils/changelog.d.ts +0 -9
- package/dist/types/utils/mupdf-wasm.d.ts +1 -0
- package/package.json +9 -8
- package/scripts/compile-args.ts +8 -4
- package/src/capability/fs.ts +395 -17
- package/src/capability/index.ts +273 -10
- package/src/capability/types.ts +9 -0
- package/src/cli/customize-doctor.ts +18 -12
- package/src/cli/doctor/args.ts +236 -0
- package/src/cli/doctor/checks.ts +431 -0
- package/src/cli/doctor/config-repairs.ts +517 -0
- package/src/cli/doctor/context.ts +149 -0
- package/src/cli/doctor/files.ts +149 -0
- package/src/cli/doctor/ids.ts +115 -0
- package/src/cli/doctor/install-repairs.ts +335 -0
- package/src/cli/doctor/journal.ts +423 -0
- package/src/cli/doctor/managed-link.ts +514 -0
- package/src/cli/doctor/native-probe.ts +13 -0
- package/src/cli/doctor/permission-repairs.ts +242 -0
- package/src/cli/doctor/plugin-quarantine.ts +377 -0
- package/src/cli/doctor/plugin-restore.ts +59 -0
- package/src/cli/doctor/plugin-targets.ts +373 -0
- package/src/cli/doctor/probe-client.ts +195 -0
- package/src/cli/doctor/probe-types.ts +21 -0
- package/src/cli/doctor/probe.ts +42 -0
- package/src/cli/doctor/projection-probe.ts +249 -0
- package/src/cli/doctor/repairs.ts +1157 -0
- package/src/cli/doctor/report.ts +176 -0
- package/src/cli/doctor/runner.ts +342 -0
- package/src/cli/doctor/safety.ts +40 -0
- package/src/cli/doctor/service-repairs.ts +452 -0
- package/src/cli/doctor/service-targets.ts +274 -0
- package/src/cli/doctor/types.ts +164 -0
- package/src/cli/doctor-cli.ts +62 -0
- package/src/cli/doctor-supervisor.ts +571 -0
- package/src/cli/doctor-worker.ts +181 -0
- package/src/cli/install-activation.ts +666 -0
- package/src/cli/macos-community-app.ts +1449 -0
- package/src/cli/mcp-cli.ts +11 -21
- package/src/cli/nofile-limit.ts +5 -1
- package/src/cli/plugin-cli.ts +6 -1
- package/src/cli/update-cli.ts +362 -264
- package/src/cli-main.ts +517 -0
- package/src/cli.ts +64 -433
- package/src/commands/autoresearch.ts +11 -5
- package/src/commands/completion.ts +1 -1
- package/src/commands/doctor.ts +13 -0
- package/src/commands/sdk.ts +58 -10
- package/src/commands/ultragoal.ts +11 -5
- package/src/config/autorouting-tier-map.ts +7 -0
- package/src/config/file-lock.ts +736 -71
- package/src/config/mcp-schema.json +3 -3
- package/src/config/model-preset-registry.ts +1 -0
- package/src/config/model-registry.ts +80 -27
- package/src/config/model-resolver.ts +33 -4
- package/src/config/models-config-schema.ts +2 -0
- package/src/config/settings-schema.ts +6 -2
- package/src/coordinator-mcp/question-gate-codec.ts +1 -0
- package/src/coordinator-mcp/server.ts +534 -51
- package/src/coordinator-mcp/session-reaper.ts +64 -8
- package/src/cursor.ts +223 -53
- package/src/discovery/agents-md.ts +74 -8
- package/src/discovery/agents.ts +32 -7
- package/src/discovery/builtin.ts +184 -75
- package/src/discovery/claude-plugins.ts +85 -17
- package/src/discovery/cline.ts +38 -10
- package/src/discovery/cursor.ts +19 -6
- package/src/discovery/gemini.ts +62 -22
- package/src/discovery/github.ts +13 -3
- package/src/discovery/helpers.ts +483 -89
- package/src/discovery/index.ts +1 -0
- package/src/discovery/mcp-json.ts +36 -10
- package/src/discovery/opencode.ts +36 -19
- package/src/discovery/ssh.ts +11 -8
- package/src/discovery/windsurf.ts +12 -3
- package/src/exec/bash-executor.ts +10 -3
- package/src/exec/isolated-shell.ts +15 -2
- package/src/extensibility/extensions/loader.ts +88 -26
- package/src/extensibility/gjc-plugins/lifecycle.ts +189 -0
- package/src/extensibility/gjc-plugins/paths.ts +4 -1
- package/src/extensibility/gjc-plugins/types.ts +27 -0
- package/src/extensibility/plugins/manager.ts +200 -22
- package/src/extensibility/plugins/marketplace/cache.ts +55 -2
- package/src/extensibility/plugins/marketplace/manager.ts +1262 -162
- package/src/extensibility/plugins/marketplace/registry.ts +153 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +116 -10
- package/src/extensibility/runtime-skill-discovery.ts +61 -9
- package/src/extensibility/skill-management.ts +7 -1
- package/src/gjc-runtime/autoresearch-runtime.ts +10 -1
- package/src/gjc-runtime/launch-worktree.test.ts +248 -0
- package/src/gjc-runtime/launch-worktree.ts +275 -38
- package/src/gjc-runtime/repository-binding.ts +26 -1
- package/src/gjc-runtime/session-layout.ts +10 -0
- package/src/gjc-runtime/session-state-lock.ts +330 -23
- package/src/gjc-runtime/session-state-sidecar.ts +328 -80
- package/src/gjc-runtime/ultragoal-runtime.ts +10 -1
- package/src/harness-control-plane/session-lease.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +28 -26
- package/src/main.ts +150 -29
- package/src/memories/index.ts +24 -2
- package/src/modes/acp/acp-agent.ts +522 -68
- package/src/modes/components/agent-dashboard.ts +3 -1
- package/src/modes/components/model-selector.ts +28 -19
- package/src/modes/components/plugin-settings.ts +2 -1
- package/src/modes/controllers/selector-controller.ts +15 -9
- package/src/modes/interactive-mode.ts +21 -3
- package/src/prompts/system/system-prompt.md +5 -1
- package/src/prompts/tools/browser.md +1 -1
- package/src/prompts/tools/move-session.md +4 -0
- package/src/prompts/tools/read.md +2 -1
- package/src/prompts/tools/skill-discovery.md +6 -5
- package/src/prompts/tools/task.md +1 -0
- package/src/runtime-mcp/config-writer.ts +228 -0
- package/src/runtime-mcp/oauth-discovery.ts +114 -14
- package/src/runtime-mcp/policy-json-edit.ts +129 -0
- package/src/runtime-mcp/startup-policy.ts +14 -0
- package/src/runtime-mcp/types.ts +2 -2
- package/src/sdk/acp/adapter.ts +27 -12
- package/src/sdk/broker/broker.ts +273 -44
- package/src/sdk/broker/daemon-entry.ts +119 -0
- package/src/sdk/broker/discovery.ts +173 -20
- package/src/sdk/broker/doctor-restart.ts +206 -0
- package/src/sdk/broker/endpoint-authority.ts +36 -0
- package/src/sdk/broker/ensure.ts +49 -14
- package/src/sdk/broker/lifecycle.ts +174 -42
- package/src/sdk/broker/process-incarnation.ts +86 -2
- package/src/sdk/broker/runtime.ts +145 -21
- package/src/sdk/broker/session-index.ts +136 -22
- package/src/sdk/broker/spawn-substrate.ts +4 -1
- package/src/sdk/broker/transport.ts +5 -0
- package/src/sdk/broker/worktree-occupancy.ts +21 -1
- package/src/sdk/bus/chat-daemon-cli.ts +63 -0
- package/src/sdk/bus/chat-daemon-control.ts +260 -64
- package/src/sdk/bus/chat-daemon-runtime.ts +141 -25
- package/src/sdk/bus/daemon-startup-exclusion.ts +119 -0
- package/src/sdk/bus/doctor-daemon-restart-client.ts +291 -0
- package/src/sdk/bus/doctor-daemon-restart.ts +92 -0
- package/src/sdk/bus/index.ts +252 -51
- package/src/sdk/bus/kind-aware-reconciliation.ts +76 -41
- package/src/sdk/bus/notification-service.ts +21 -3
- package/src/sdk/bus/reconciliation-store.ts +17 -11
- package/src/sdk/bus/telegram-daemon-cli.ts +91 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/bus/telegram-daemon-control.ts +47 -0
- package/src/sdk/bus/telegram-daemon-owner-registry.ts +1 -1
- package/src/sdk/bus/telegram-daemon.ts +178 -13
- package/src/sdk/cli/session-cli.ts +100 -12
- package/src/sdk/host/host.ts +2 -7
- package/src/sdk/host/session-runtime.test.ts +329 -8
- package/src/sdk/host/session-runtime.ts +202 -50
- package/src/sdk/host/surface-policy.ts +8 -1
- package/src/sdk/lifecycle/service.ts +199 -22
- package/src/sdk/mcp/server.ts +1 -1
- package/src/sdk/prompt-deadline-lease.ts +12 -4
- package/src/sdk/prompt-deadline-manager.ts +5 -7
- package/src/sdk/prompt-failure.ts +148 -0
- package/src/sdk/prompt-status.ts +30 -1
- package/src/sdk/prompt-watchdog.ts +11 -3
- package/src/sdk/protocol/operation-inventory.generated.json +18 -0
- package/src/sdk/protocol/operation-registry.ts +20 -8
- package/src/sdk/router/session-router.ts +8 -3
- package/src/sdk/service-artifact-paths.ts +26 -0
- package/src/sdk/session-authority.ts +10 -0
- package/src/sdk/session.ts +361 -194
- package/src/session/agent-session.ts +398 -93
- package/src/session/blob-store.ts +9 -9
- package/src/session/fallback-chain-controller.ts +3 -7
- package/src/session/internal/managed-session-scope.ts +445 -29
- package/src/session/internal/managed-session-storage.ts +38 -6
- package/src/session/primary-control-surface.ts +12 -0
- package/src/session/session-manager.ts +11 -3
- package/src/session/session-storage.ts +1 -1
- package/src/session-import/codex.ts +6 -1
- package/src/session-import/redact.ts +7 -0
- package/src/skill-state/workflow-mutation-guard.ts +645 -39
- package/src/slash-commands/builtin-registry.ts +7 -3
- package/src/system-prompt.ts +8 -0
- package/src/task/executor.ts +36 -3
- package/src/task/types.ts +27 -5
- package/src/tools/ask.ts +114 -34
- package/src/tools/browser/actions.ts +2 -2
- package/src/tools/browser/tab-worker.ts +11 -8
- package/src/tools/descriptors.ts +6 -1
- package/src/tools/fetch.ts +7 -2
- package/src/tools/image-gen.ts +33 -34
- package/src/tools/read.ts +78 -32
- package/src/tools/skill-discovery.ts +17 -7
- package/src/tools/tool-catalog.generated.ts +8 -8
- package/src/tools/ultragoal-ask-guard.ts +16 -26
- package/src/utils/changelog.ts +7 -1
- package/src/utils/git.ts +3 -1
- package/src/utils/markit.ts +24 -2
- package/src/utils/mupdf-wasm.ts +26 -0
- package/src/web/search/providers/openai-compatible.ts +191 -14
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, spyOn, test } from "bun:test";
|
|
1
|
+
import { describe, expect, setDefaultTimeout, spyOn, test } from "bun:test";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import { mkdir, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
4
4
|
import * as os from "node:os";
|
|
@@ -32,6 +32,15 @@ import { createSdkCapabilities, createSdkSurfacePolicy } from "./surface-policy"
|
|
|
32
32
|
import type { SdkFrame } from "./types";
|
|
33
33
|
import { SdkTransportLifecycleError } from "./websocket-transport";
|
|
34
34
|
|
|
35
|
+
setDefaultTimeout(30_000);
|
|
36
|
+
|
|
37
|
+
test("runtime capabilities preserve explicit primary control surface", () => {
|
|
38
|
+
const policy = createSdkSurfacePolicy({ bindings: [], workflowGateAvailable: false });
|
|
39
|
+
expect(createSdkCapabilities(policy)).toMatchObject({ primaryControlSurface: "sdk" });
|
|
40
|
+
expect(createSdkCapabilities(policy, false, "sdk")).toMatchObject({ primaryControlSurface: "sdk" });
|
|
41
|
+
expect(createSdkCapabilities(policy, false, "cli")).toMatchObject({ primaryControlSurface: "cli" });
|
|
42
|
+
});
|
|
43
|
+
|
|
35
44
|
function memoryTransport(): SessionSdkTransport & {
|
|
36
45
|
feed(connectionId: string, frame: SdkFrame): void;
|
|
37
46
|
readonly sent: SdkFrame[];
|
|
@@ -429,7 +438,7 @@ test("SDK-only finalizeOutcome keeps legacy recordError positional compatibility
|
|
|
429
438
|
});
|
|
430
439
|
expect(compatReconciliation.lookup("prompt", { clientRef: "finalize-compat-ref" })).toMatchObject({
|
|
431
440
|
status: "failed",
|
|
432
|
-
error: { code: "legacy_error", message: "
|
|
441
|
+
error: { code: "legacy_error", message: "Prompt submission failed." },
|
|
433
442
|
});
|
|
434
443
|
// The isCurrent callback shape still fences a stale finalize to a no-op.
|
|
435
444
|
const second = createInvocationReconciliation();
|
|
@@ -4040,7 +4049,16 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
4040
4049
|
});
|
|
4041
4050
|
expect(terminal).toMatchObject({
|
|
4042
4051
|
status: "failed",
|
|
4043
|
-
error: { code, message: "
|
|
4052
|
+
error: { code, message: "Provider failure after execution started." },
|
|
4053
|
+
outcome: {
|
|
4054
|
+
kind: "failed",
|
|
4055
|
+
code: "prompt_failed",
|
|
4056
|
+
message: "Provider failure after execution started.",
|
|
4057
|
+
provenance: "agent_failed",
|
|
4058
|
+
phase: "post_start",
|
|
4059
|
+
category: "provider_rejected",
|
|
4060
|
+
providerCode: code,
|
|
4061
|
+
},
|
|
4044
4062
|
terminalAt: expect.any(Number),
|
|
4045
4063
|
});
|
|
4046
4064
|
const stable = await harness.query("turn.result", { kind: "prompt", ...failedIds });
|
|
@@ -4497,10 +4515,8 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
4497
4515
|
messages: [{ role: "assistant", stopReason: "error", errorStatus: status }],
|
|
4498
4516
|
});
|
|
4499
4517
|
await entered.promise;
|
|
4500
|
-
const startedAt = Date.now();
|
|
4501
4518
|
const lifecycleChange = harness[operation](`${operation}-stall-successor`);
|
|
4502
4519
|
await lifecycleChange;
|
|
4503
|
-
expect(Date.now() - startedAt).toBeLessThan(1_500);
|
|
4504
4520
|
expect(timeoutWarnings).toBe(1);
|
|
4505
4521
|
release.resolve();
|
|
4506
4522
|
firstInflight.resolve();
|
|
@@ -4662,7 +4678,16 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
4662
4678
|
// the failure reason survives as the safe-token code.
|
|
4663
4679
|
expect(await settledStatus(harness, "turn.prompt_status", { commandId, turnId })).toMatchObject({
|
|
4664
4680
|
status: "failed",
|
|
4665
|
-
error: { code: "upstream_stream_interrupted", message: "
|
|
4681
|
+
error: { code: "upstream_stream_interrupted", message: "Provider failure after execution started." },
|
|
4682
|
+
outcome: {
|
|
4683
|
+
kind: "failed",
|
|
4684
|
+
code: "prompt_failed",
|
|
4685
|
+
message: "Provider failure after execution started.",
|
|
4686
|
+
provenance: "agent_failed",
|
|
4687
|
+
phase: "post_start",
|
|
4688
|
+
category: "provider_transport",
|
|
4689
|
+
providerCode: "upstream_stream_interrupted",
|
|
4690
|
+
},
|
|
4666
4691
|
});
|
|
4667
4692
|
await harness.stop();
|
|
4668
4693
|
} finally {
|
|
@@ -4955,7 +4980,7 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
4955
4980
|
const cases = [
|
|
4956
4981
|
{ name: "short", agent: "SDK_OK", expected: "SDK_OK", bytes: 6, truncated: false },
|
|
4957
4982
|
{ name: "max", agent: "x".repeat(16_384), expected: "x".repeat(16_384), bytes: 16_384, truncated: false },
|
|
4958
|
-
{ name: "blank", agent: " ", expected: undefined, bytes: 0, truncated: false },
|
|
4983
|
+
{ name: "blank", agent: " ", expected: undefined, bytes: 0, truncated: false, status: "failed" },
|
|
4959
4984
|
{
|
|
4960
4985
|
name: "overflow",
|
|
4961
4986
|
agent: `${"😀".repeat(4_096)}tail`,
|
|
@@ -4982,7 +5007,7 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
4982
5007
|
turnId: accepted.result?.turnId,
|
|
4983
5008
|
});
|
|
4984
5009
|
if (testCase.expected === undefined) {
|
|
4985
|
-
expect(result).toMatchObject({ status:
|
|
5010
|
+
expect(result).toMatchObject({ status: testCase.status });
|
|
4986
5011
|
expect((result as Record<string, unknown>).content).toBeUndefined();
|
|
4987
5012
|
} else {
|
|
4988
5013
|
expect(result).toMatchObject({
|
|
@@ -5000,6 +5025,302 @@ describe("post-acceptance invocation terminalization", () => {
|
|
|
5000
5025
|
}
|
|
5001
5026
|
}
|
|
5002
5027
|
});
|
|
5028
|
+
test("fails closed when an assistant turn has only empty reasoning and zero token usage", async () => {
|
|
5029
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), "gjc-terminal-zero-token-empty-"));
|
|
5030
|
+
try {
|
|
5031
|
+
const harness = await invocationHarness("terminal-zero-token-empty", cwd, {
|
|
5032
|
+
sendUserMessage: async (_content, options) => {
|
|
5033
|
+
await options?.onPreflightAcceptCommit?.();
|
|
5034
|
+
await Promise.withResolvers<void>().promise;
|
|
5035
|
+
},
|
|
5036
|
+
});
|
|
5037
|
+
const accepted = await harness.control("turn.prompt", { text: "hello" });
|
|
5038
|
+
await harness.emit("agent_start");
|
|
5039
|
+
await harness.emit("agent_end", {
|
|
5040
|
+
messages: [
|
|
5041
|
+
{
|
|
5042
|
+
role: "assistant",
|
|
5043
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5044
|
+
usage: {
|
|
5045
|
+
input: 0,
|
|
5046
|
+
output: 0,
|
|
5047
|
+
cacheRead: 0,
|
|
5048
|
+
cacheWrite: 0,
|
|
5049
|
+
totalTokens: 0,
|
|
5050
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
5051
|
+
},
|
|
5052
|
+
stopReason: "stop",
|
|
5053
|
+
},
|
|
5054
|
+
],
|
|
5055
|
+
});
|
|
5056
|
+
const result = await settledStatus(harness, "turn.result", {
|
|
5057
|
+
kind: "prompt",
|
|
5058
|
+
commandId: accepted.result?.commandId,
|
|
5059
|
+
turnId: accepted.result?.turnId,
|
|
5060
|
+
});
|
|
5061
|
+
expect(result).toMatchObject({
|
|
5062
|
+
status: "failed",
|
|
5063
|
+
error: { code: "prompt_failed", message: "Agent run failed after execution started." },
|
|
5064
|
+
outcome: {
|
|
5065
|
+
kind: "failed",
|
|
5066
|
+
code: "prompt_failed",
|
|
5067
|
+
message: "Agent run failed after execution started.",
|
|
5068
|
+
provenance: "agent_failed",
|
|
5069
|
+
phase: "post_start",
|
|
5070
|
+
category: "agent_runtime",
|
|
5071
|
+
},
|
|
5072
|
+
});
|
|
5073
|
+
const successor = await harness.control("turn.prompt", { text: "successor" });
|
|
5074
|
+
expect(successor).toMatchObject({ ok: true, result: { accepted: true } });
|
|
5075
|
+
await harness.emit("agent_start");
|
|
5076
|
+
await harness.emit("agent_end", { messages: [{ role: "assistant", content: "completed" }] });
|
|
5077
|
+
expect(
|
|
5078
|
+
await settledStatus(harness, "turn.result", {
|
|
5079
|
+
kind: "prompt",
|
|
5080
|
+
commandId: successor.result?.commandId,
|
|
5081
|
+
turnId: successor.result?.turnId,
|
|
5082
|
+
}),
|
|
5083
|
+
).toMatchObject({ status: "terminal_ok" });
|
|
5084
|
+
await harness.stop();
|
|
5085
|
+
} finally {
|
|
5086
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5087
|
+
}
|
|
5088
|
+
});
|
|
5089
|
+
test("preserves valid textless terminal evidence", async () => {
|
|
5090
|
+
const cases = [
|
|
5091
|
+
{
|
|
5092
|
+
name: "reasoning-only",
|
|
5093
|
+
content: [{ type: "thinking", thinking: "private reasoning" }],
|
|
5094
|
+
usage: { totalTokens: 0 },
|
|
5095
|
+
},
|
|
5096
|
+
{
|
|
5097
|
+
name: "redacted-reasoning-only",
|
|
5098
|
+
content: [{ type: "redactedThinking", data: "encrypted reasoning" }],
|
|
5099
|
+
usage: { totalTokens: 0 },
|
|
5100
|
+
},
|
|
5101
|
+
{
|
|
5102
|
+
name: "tool-only",
|
|
5103
|
+
content: [{ type: "toolCall", id: "call-1", name: "read", arguments: {} }],
|
|
5104
|
+
usage: { totalTokens: 0 },
|
|
5105
|
+
},
|
|
5106
|
+
{
|
|
5107
|
+
name: "positive-token-usage",
|
|
5108
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5109
|
+
usage: { totalTokens: 1 },
|
|
5110
|
+
},
|
|
5111
|
+
] as const;
|
|
5112
|
+
for (const testCase of cases) {
|
|
5113
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), `gjc-terminal-valid-${testCase.name}-`));
|
|
5114
|
+
try {
|
|
5115
|
+
const harness = await invocationHarness(`terminal-valid-${testCase.name}`, cwd, {
|
|
5116
|
+
sendUserMessage: async (_content, options) => {
|
|
5117
|
+
await options?.onPreflightAcceptCommit?.();
|
|
5118
|
+
await Promise.withResolvers<void>().promise;
|
|
5119
|
+
},
|
|
5120
|
+
});
|
|
5121
|
+
const accepted = await harness.control("turn.prompt", { text: "hello" });
|
|
5122
|
+
await harness.emit("agent_start");
|
|
5123
|
+
await harness.emit("agent_end", {
|
|
5124
|
+
messages: [
|
|
5125
|
+
{
|
|
5126
|
+
role: "assistant",
|
|
5127
|
+
content: testCase.content,
|
|
5128
|
+
...(testCase.usage === undefined ? {} : { usage: testCase.usage }),
|
|
5129
|
+
},
|
|
5130
|
+
],
|
|
5131
|
+
});
|
|
5132
|
+
expect(
|
|
5133
|
+
await settledStatus(harness, "turn.result", {
|
|
5134
|
+
kind: "prompt",
|
|
5135
|
+
commandId: accepted.result?.commandId,
|
|
5136
|
+
turnId: accepted.result?.turnId,
|
|
5137
|
+
}),
|
|
5138
|
+
).toMatchObject({ status: "terminal_ok" });
|
|
5139
|
+
await harness.stop();
|
|
5140
|
+
} finally {
|
|
5141
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
});
|
|
5145
|
+
test("preserves earlier complete tool activity before a trailing empty assistant", async () => {
|
|
5146
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), "gjc-terminal-earlier-tool-activity-"));
|
|
5147
|
+
try {
|
|
5148
|
+
const harness = await invocationHarness("terminal-earlier-tool-activity", cwd, {
|
|
5149
|
+
sendUserMessage: async (_content, options) => {
|
|
5150
|
+
await options?.onPreflightAcceptCommit?.();
|
|
5151
|
+
await Promise.withResolvers<void>().promise;
|
|
5152
|
+
},
|
|
5153
|
+
});
|
|
5154
|
+
const accepted = await harness.control("turn.prompt", { text: "hello" });
|
|
5155
|
+
await harness.emit("agent_start");
|
|
5156
|
+
await harness.emit("agent_end", {
|
|
5157
|
+
messages: [
|
|
5158
|
+
{
|
|
5159
|
+
role: "assistant",
|
|
5160
|
+
content: [{ type: "toolCall", id: "call-1", name: "read", arguments: { path: "file.txt" } }],
|
|
5161
|
+
usage: { totalTokens: 1 },
|
|
5162
|
+
},
|
|
5163
|
+
{
|
|
5164
|
+
role: "toolResult",
|
|
5165
|
+
toolCallId: "call-1",
|
|
5166
|
+
toolName: "read",
|
|
5167
|
+
content: [{ type: "text", text: "contents" }],
|
|
5168
|
+
},
|
|
5169
|
+
{
|
|
5170
|
+
role: "assistant",
|
|
5171
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5172
|
+
usage: { totalTokens: 0 },
|
|
5173
|
+
},
|
|
5174
|
+
],
|
|
5175
|
+
});
|
|
5176
|
+
expect(
|
|
5177
|
+
await settledStatus(harness, "turn.result", {
|
|
5178
|
+
kind: "prompt",
|
|
5179
|
+
commandId: accepted.result?.commandId,
|
|
5180
|
+
turnId: accepted.result?.turnId,
|
|
5181
|
+
}),
|
|
5182
|
+
).toMatchObject({ status: "terminal_ok" });
|
|
5183
|
+
await harness.stop();
|
|
5184
|
+
} finally {
|
|
5185
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5186
|
+
}
|
|
5187
|
+
});
|
|
5188
|
+
test("fails closed without independent terminal evidence", async () => {
|
|
5189
|
+
const cases = [
|
|
5190
|
+
{ name: "usage-omitted", content: [{ type: "thinking", thinking: "" }], omitUsage: true },
|
|
5191
|
+
{ name: "usage-null", content: [{ type: "thinking", thinking: "" }], usage: null },
|
|
5192
|
+
{ name: "primitive-usage", content: [{ type: "thinking", thinking: "" }], usage: "bad" },
|
|
5193
|
+
{ name: "array-usage", content: [{ type: "thinking", thinking: "" }], usage: [] },
|
|
5194
|
+
{ name: "missing-total-tokens", content: [{ type: "thinking", thinking: "" }], usage: { input: 0 } },
|
|
5195
|
+
{
|
|
5196
|
+
name: "undefined-total-tokens",
|
|
5197
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5198
|
+
usage: { totalTokens: undefined },
|
|
5199
|
+
},
|
|
5200
|
+
{ name: "negative-total-tokens", content: [{ type: "thinking", thinking: "" }], usage: { totalTokens: -1 } },
|
|
5201
|
+
{
|
|
5202
|
+
name: "nan-total-tokens",
|
|
5203
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5204
|
+
usage: { totalTokens: Number.NaN },
|
|
5205
|
+
},
|
|
5206
|
+
{
|
|
5207
|
+
name: "infinite-total-tokens",
|
|
5208
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5209
|
+
usage: { totalTokens: Number.POSITIVE_INFINITY },
|
|
5210
|
+
},
|
|
5211
|
+
{
|
|
5212
|
+
name: "incomplete-tool-call",
|
|
5213
|
+
content: [
|
|
5214
|
+
{
|
|
5215
|
+
type: "toolCall",
|
|
5216
|
+
id: "call-1",
|
|
5217
|
+
name: "read",
|
|
5218
|
+
arguments: {},
|
|
5219
|
+
incompleteArguments: true,
|
|
5220
|
+
incompleteArgumentsReason: "truncated",
|
|
5221
|
+
},
|
|
5222
|
+
],
|
|
5223
|
+
usage: { totalTokens: 0 },
|
|
5224
|
+
},
|
|
5225
|
+
{
|
|
5226
|
+
name: "malformed-tool-arguments",
|
|
5227
|
+
content: [{ type: "toolCall", id: "call-1", name: "read", arguments: null }],
|
|
5228
|
+
usage: { totalTokens: 0 },
|
|
5229
|
+
},
|
|
5230
|
+
{
|
|
5231
|
+
name: "orphaned-incomplete-reason",
|
|
5232
|
+
content: [
|
|
5233
|
+
{
|
|
5234
|
+
type: "toolCall",
|
|
5235
|
+
id: "call-1",
|
|
5236
|
+
name: "read",
|
|
5237
|
+
arguments: {},
|
|
5238
|
+
incompleteArgumentsReason: "malformed",
|
|
5239
|
+
},
|
|
5240
|
+
],
|
|
5241
|
+
usage: { totalTokens: 0 },
|
|
5242
|
+
},
|
|
5243
|
+
] as const;
|
|
5244
|
+
for (const testCase of cases) {
|
|
5245
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), `gjc-terminal-malformed-${testCase.name}-`));
|
|
5246
|
+
try {
|
|
5247
|
+
const harness = await invocationHarness(`terminal-malformed-${testCase.name}`, cwd, {
|
|
5248
|
+
sendUserMessage: async (_content, options) => {
|
|
5249
|
+
await options?.onPreflightAcceptCommit?.();
|
|
5250
|
+
await Promise.withResolvers<void>().promise;
|
|
5251
|
+
},
|
|
5252
|
+
});
|
|
5253
|
+
const accepted = await harness.control("turn.prompt", { text: "hello" });
|
|
5254
|
+
await harness.emit("agent_start");
|
|
5255
|
+
await harness.emit("agent_end", {
|
|
5256
|
+
messages: [
|
|
5257
|
+
{
|
|
5258
|
+
role: "assistant",
|
|
5259
|
+
content: testCase.content,
|
|
5260
|
+
...("omitUsage" in testCase ? {} : { usage: testCase.usage }),
|
|
5261
|
+
},
|
|
5262
|
+
],
|
|
5263
|
+
});
|
|
5264
|
+
expect(
|
|
5265
|
+
await settledStatus(harness, "turn.result", {
|
|
5266
|
+
kind: "prompt",
|
|
5267
|
+
commandId: accepted.result?.commandId,
|
|
5268
|
+
turnId: accepted.result?.turnId,
|
|
5269
|
+
}),
|
|
5270
|
+
).toMatchObject({
|
|
5271
|
+
status: "failed",
|
|
5272
|
+
error: { code: "prompt_failed", message: "Agent run failed after execution started." },
|
|
5273
|
+
outcome: {
|
|
5274
|
+
kind: "failed",
|
|
5275
|
+
code: "prompt_failed",
|
|
5276
|
+
message: "Agent run failed after execution started.",
|
|
5277
|
+
provenance: "agent_failed",
|
|
5278
|
+
phase: "post_start",
|
|
5279
|
+
category: "agent_runtime",
|
|
5280
|
+
},
|
|
5281
|
+
});
|
|
5282
|
+
await harness.stop();
|
|
5283
|
+
} finally {
|
|
5284
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
});
|
|
5288
|
+
test("preserves explicit cancellation for an empty zero-token turn", async () => {
|
|
5289
|
+
const cwd = await mkdtemp(path.join(os.tmpdir(), "gjc-terminal-empty-cancelled-"));
|
|
5290
|
+
try {
|
|
5291
|
+
const harness = await invocationHarness("terminal-empty-cancelled", cwd, {
|
|
5292
|
+
sendUserMessage: async (_content, options) => {
|
|
5293
|
+
await options?.onPreflightAcceptCommit?.();
|
|
5294
|
+
await Promise.withResolvers<void>().promise;
|
|
5295
|
+
},
|
|
5296
|
+
});
|
|
5297
|
+
const accepted = await harness.control("turn.prompt", { text: "hello" });
|
|
5298
|
+
await harness.emit("agent_start");
|
|
5299
|
+
await harness.emit("agent_end", {
|
|
5300
|
+
stopReason: "cancelled",
|
|
5301
|
+
messages: [
|
|
5302
|
+
{
|
|
5303
|
+
role: "assistant",
|
|
5304
|
+
content: [{ type: "thinking", thinking: "" }],
|
|
5305
|
+
usage: { totalTokens: 0 },
|
|
5306
|
+
},
|
|
5307
|
+
],
|
|
5308
|
+
});
|
|
5309
|
+
expect(
|
|
5310
|
+
await settledStatus(harness, "turn.result", {
|
|
5311
|
+
kind: "prompt",
|
|
5312
|
+
commandId: accepted.result?.commandId,
|
|
5313
|
+
turnId: accepted.result?.turnId,
|
|
5314
|
+
}),
|
|
5315
|
+
).toMatchObject({
|
|
5316
|
+
status: "terminal_ok",
|
|
5317
|
+
outcome: { kind: "stopped", reason: "cancelled", provenance: "client_cancel" },
|
|
5318
|
+
});
|
|
5319
|
+
await harness.stop();
|
|
5320
|
+
} finally {
|
|
5321
|
+
await rm(cwd, { recursive: true, force: true });
|
|
5322
|
+
}
|
|
5323
|
+
});
|
|
5003
5324
|
test("does not reuse a previous branch assistant for a new textless prompt", async () => {
|
|
5004
5325
|
const cwd = await mkdtemp(path.join(os.tmpdir(), "gjc-terminal-order-previous-assistant-"));
|
|
5005
5326
|
try {
|