@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
|
@@ -3,12 +3,13 @@ import { logger } from "@gajae-code/utils";
|
|
|
3
3
|
/**
|
|
4
4
|
* Idle reaper for coordinator-managed GJC worker sessions.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* New coordinator-owned sessions created by `gjc_coordinator_start_session` or by a
|
|
7
|
+
* `gjc_delegate_*` call that omits `session_id` are ephemeral. Nothing in the
|
|
8
|
+
* coordinator ever tore those down, so completed/crashed sessions accumulated
|
|
9
|
+
* (RAM + worktrees) until something killed them by hand.
|
|
9
10
|
*
|
|
10
11
|
* This is the automatic backstop (defense-in-depth): a periodic sweep force-closes
|
|
11
|
-
* sessions that are (a) ephemeral — coordinator
|
|
12
|
+
* sessions that are (a) ephemeral — coordinator-created, never a user's
|
|
12
13
|
* registered resident session, (b) not mid-turn, and (c) idle past a TTL.
|
|
13
14
|
*
|
|
14
15
|
* The controller is pure + fully injectable (clock / list / reap side-effects) so
|
|
@@ -21,11 +22,13 @@ export const DEFAULT_SESSION_IDLE_TTL_MS = 30 * 60_000; // 30 min idle → reap
|
|
|
21
22
|
export const DEFAULT_SESSION_SWEEP_INTERVAL_MS = 5 * 60_000; // sweep every 5 min
|
|
22
23
|
export const MIN_SESSION_IDLE_TTL_MS = 60_000; // never reap a <1min-idle session
|
|
23
24
|
export const MIN_SESSION_SWEEP_INTERVAL_MS = 30_000;
|
|
25
|
+
/** After this many consecutive reap failures the session is force-evicted from the index. */
|
|
26
|
+
export const MAX_REAP_FAILURES = 3;
|
|
24
27
|
|
|
25
28
|
/** Minimal projection of a coordinator session the reaper needs to decide. */
|
|
26
29
|
export interface ReapableSession {
|
|
27
30
|
sessionId: string;
|
|
28
|
-
/** True
|
|
31
|
+
/** True for newly coordinator-created sessions. User-registered resident sessions are false and never reaped. */
|
|
29
32
|
ephemeral: boolean;
|
|
30
33
|
/** Epoch ms of last observed activity (turn update / session-state write / session creation). */
|
|
31
34
|
lastActivityMs: number;
|
|
@@ -51,10 +54,29 @@ export function selectReapableSessions(
|
|
|
51
54
|
return sessions.filter(s => s.ephemeral && !s.hasActiveTurn && now - s.lastActivityMs >= ttl);
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Only a stale/absent endpoint makes a session permanently unreapable, so it is
|
|
59
|
+
* the sole failure that advances the force-eviction counter. Every other reap
|
|
60
|
+
* failure (close_failed, broker unavailability, filesystem errors) is transient
|
|
61
|
+
* and must keep retrying without ever escalating to force eviction. The server
|
|
62
|
+
* wires `reapSession` to throw `new Error(reason)`, so the reason code is the
|
|
63
|
+
* error message here.
|
|
64
|
+
*/
|
|
65
|
+
function isEndpointStaleReapError(err: unknown): boolean {
|
|
66
|
+
return (err instanceof Error ? err.message : String(err)) === "endpoint_stale";
|
|
67
|
+
}
|
|
68
|
+
|
|
54
69
|
/** Injectable side-effects so the controller runs in tests without tmux/fs/real time. */
|
|
55
70
|
export interface SessionReaperDeps {
|
|
56
71
|
listSessions: () => Promise<ReapableSession[]>;
|
|
57
72
|
reapSession: (sessionId: string) => Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Force-evict a session from the coordinator index when it has exceeded the
|
|
75
|
+
* consecutive-failure limit and cannot be reaped normally (e.g. endpoint_stale).
|
|
76
|
+
* Called exactly once per session-id at the eviction boundary; the session must
|
|
77
|
+
* not appear in future listSessions() results after this resolves.
|
|
78
|
+
*/
|
|
79
|
+
markSessionDead: (sessionId: string) => Promise<void>;
|
|
58
80
|
now: () => number;
|
|
59
81
|
}
|
|
60
82
|
|
|
@@ -72,6 +94,8 @@ export function createSessionReaper(deps: SessionReaperDeps, policy: SessionReap
|
|
|
72
94
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
73
95
|
let generation = 0;
|
|
74
96
|
let inProgress = false;
|
|
97
|
+
/** Consecutive reap-failure count per session-id. Cleared on success or eviction. */
|
|
98
|
+
const failureCounts = new Map<string, number>();
|
|
75
99
|
|
|
76
100
|
async function sweepOnce(): Promise<number> {
|
|
77
101
|
if (inProgress) return 0; // never overlap sweeps
|
|
@@ -83,12 +107,44 @@ export function createSessionReaper(deps: SessionReaperDeps, policy: SessionReap
|
|
|
83
107
|
for (const session of targets) {
|
|
84
108
|
try {
|
|
85
109
|
await deps.reapSession(session.sessionId);
|
|
110
|
+
// Success — clear any accumulated failure count.
|
|
111
|
+
failureCounts.delete(session.sessionId);
|
|
86
112
|
reaped += 1;
|
|
87
113
|
} catch (err) {
|
|
88
114
|
// One wedged session must not abort the rest of the sweep.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
115
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
116
|
+
if (!isEndpointStaleReapError(err)) {
|
|
117
|
+
// Transient failure (close_failed, broker/filesystem error): a non-stale
|
|
118
|
+
// outcome breaks the consecutive-stale streak, so clear the counter and
|
|
119
|
+
// retry on the next sweep. Only genuinely consecutive endpoint_stale
|
|
120
|
+
// failures may accumulate toward force eviction.
|
|
121
|
+
logger.warn(`session-reaper: failed to reap ${session.sessionId}: ${msg}`);
|
|
122
|
+
failureCounts.delete(session.sessionId);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const prev = failureCounts.get(session.sessionId) ?? 0;
|
|
126
|
+
const count = prev + 1;
|
|
127
|
+
if (count < MAX_REAP_FAILURES) {
|
|
128
|
+
// First failure(s): log at warn and keep retrying next sweep.
|
|
129
|
+
logger.warn(`session-reaper: failed to reap ${session.sessionId}: ${msg}`);
|
|
130
|
+
failureCounts.set(session.sessionId, count);
|
|
131
|
+
} else {
|
|
132
|
+
// Hit the limit — evict unconditionally and silence future attempts.
|
|
133
|
+
logger.warn(
|
|
134
|
+
`session-reaper: session ${session.sessionId} evicted after ${count} consecutive failures (${msg})`,
|
|
135
|
+
);
|
|
136
|
+
failureCounts.delete(session.sessionId);
|
|
137
|
+
try {
|
|
138
|
+
await deps.markSessionDead(session.sessionId);
|
|
139
|
+
} catch (evictErr) {
|
|
140
|
+
// Eviction failure is non-fatal; the session will be retried next
|
|
141
|
+
// sweep and the counter has been cleared, so it will get MAX_REAP_FAILURES
|
|
142
|
+
// fresh chances before the next eviction attempt.
|
|
143
|
+
logger.warn(
|
|
144
|
+
`session-reaper: markSessionDead failed for ${session.sessionId}: ${evictErr instanceof Error ? evictErr.message : String(evictErr)}`,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
92
148
|
}
|
|
93
149
|
}
|
|
94
150
|
return reaped;
|
package/src/cursor.ts
CHANGED
|
@@ -71,19 +71,30 @@ function buildToolErrorResult(message: string): AgentToolResult<unknown> {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/** Admission markers are control flow, not user-facing tool failures. */
|
|
75
|
+
function isCursorExecAdmissionClosedError(error: unknown): boolean {
|
|
76
|
+
return (
|
|
77
|
+
typeof error === "object" &&
|
|
78
|
+
error !== null &&
|
|
79
|
+
(error as { name?: unknown }).name === "CursorExecAdmissionClosedError"
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
async function executeTool(
|
|
75
84
|
options: CursorExecBridgeOptions,
|
|
76
85
|
toolName: string,
|
|
77
86
|
toolCallId: string,
|
|
78
87
|
args: Record<string, unknown>,
|
|
79
88
|
overrideTool?: AgentTool,
|
|
89
|
+
execSignal?: AbortSignal,
|
|
90
|
+
markNonAbortable?: () => void,
|
|
80
91
|
): Promise<ToolResultMessage> {
|
|
92
|
+
if (execSignal?.aborted) throw cursorAbortError(execSignal);
|
|
81
93
|
const tool = overrideTool ?? options.tools.get(toolName);
|
|
82
94
|
if (!tool) {
|
|
83
95
|
const result = buildToolErrorResult(`Tool "${toolName}" not available`);
|
|
84
96
|
return createToolResultMessage(toolCallId, toolName, result, true);
|
|
85
97
|
}
|
|
86
|
-
|
|
87
98
|
// `tool` is the object this call will run; pass it so the start event carries proven
|
|
88
99
|
// provenance instead of a name a consumer would have to re-resolve later.
|
|
89
100
|
options.emitEvent?.({ type: "tool_execution_start", toolCallId, toolName, args }, tool);
|
|
@@ -108,14 +119,23 @@ async function executeTool(
|
|
|
108
119
|
: undefined;
|
|
109
120
|
|
|
110
121
|
try {
|
|
122
|
+
if (execSignal?.aborted) throw cursorAbortError(execSignal);
|
|
123
|
+
const toolContext = options.getToolContext?.();
|
|
124
|
+
if (execSignal?.aborted) throw cursorAbortError(execSignal);
|
|
125
|
+
if (tool.nonAbortable) markNonAbortable?.();
|
|
111
126
|
result = await tool.execute(
|
|
112
127
|
toolCallId,
|
|
113
128
|
args as Record<string, unknown>,
|
|
114
|
-
|
|
129
|
+
// Non-abortable tools receive NO signal, matching agent-loop.ts: their
|
|
130
|
+
// returned promise must represent actual mutation settlement, so an
|
|
131
|
+
// untilAborted(signal, ...) rejection cannot make the settlement fence
|
|
132
|
+
// publish the terminal while the mutation is still running.
|
|
133
|
+
tool.nonAbortable ? undefined : (execSignal ?? undefined),
|
|
115
134
|
onUpdate,
|
|
116
|
-
|
|
135
|
+
toolContext,
|
|
117
136
|
);
|
|
118
137
|
} catch (error) {
|
|
138
|
+
if (isCursorExecAdmissionClosedError(error)) throw error;
|
|
119
139
|
const message = error instanceof Error ? error.message : String(error);
|
|
120
140
|
result = buildToolErrorResult(message);
|
|
121
141
|
isError = true;
|
|
@@ -131,9 +151,23 @@ async function executeTool(
|
|
|
131
151
|
return createToolResultMessage(toolCallId, toolName, result, isError);
|
|
132
152
|
}
|
|
133
153
|
|
|
134
|
-
async function executeDelete(
|
|
154
|
+
async function executeDelete(
|
|
155
|
+
options: CursorExecBridgeOptions,
|
|
156
|
+
pathArg: string,
|
|
157
|
+
toolCallId: string,
|
|
158
|
+
execSignal?: AbortSignal,
|
|
159
|
+
markNonAbortable?: () => void,
|
|
160
|
+
) {
|
|
135
161
|
const toolName = "delete";
|
|
162
|
+
if (execSignal?.aborted) throw cursorAbortError(execSignal);
|
|
163
|
+
// Register the non-abortable mutation before notifying observers: a synchronous
|
|
164
|
+
// tool_execution_start subscriber may abort the run.
|
|
165
|
+
markNonAbortable?.();
|
|
136
166
|
options.emitEvent?.({ type: "tool_execution_start", toolCallId, toolName, args: { path: pathArg } });
|
|
167
|
+
if (execSignal?.aborted) throw cursorAbortError(execSignal);
|
|
168
|
+
// Delete is a filesystem mutation with no cooperative cancellation point:
|
|
169
|
+
// mark it non-abortable so the settlement fence publishes the exec terminal
|
|
170
|
+
// only once the unlink is final, matching write/edit dispatch.
|
|
137
171
|
|
|
138
172
|
const absolutePath = resolveToCwd(pathArg, options.cwd);
|
|
139
173
|
let isError = false;
|
|
@@ -201,6 +235,11 @@ function shellTimeoutSeconds(timeout: number | undefined): number | undefined {
|
|
|
201
235
|
return Math.max(1, Math.ceil(timeout / 1000));
|
|
202
236
|
}
|
|
203
237
|
|
|
238
|
+
function cursorAbortError(signal: AbortSignal): Error {
|
|
239
|
+
const reason = signal.reason;
|
|
240
|
+
return reason instanceof Error ? reason : new Error("Request was aborted");
|
|
241
|
+
}
|
|
242
|
+
|
|
204
243
|
export class CursorExecHandlers implements ICursorExecHandlers {
|
|
205
244
|
constructor(private options: CursorExecBridgeOptions) {
|
|
206
245
|
// Bind every native handler so methods stay instance-safe when invoked
|
|
@@ -242,20 +281,44 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
242
281
|
};
|
|
243
282
|
}
|
|
244
283
|
|
|
245
|
-
async read(
|
|
284
|
+
async read(
|
|
285
|
+
args: Parameters<NonNullable<ICursorExecHandlers["read"]>>[0],
|
|
286
|
+
signal?: AbortSignal,
|
|
287
|
+
markNonAbortable?: () => void,
|
|
288
|
+
) {
|
|
246
289
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
247
|
-
const toolResultMessage = await executeTool(
|
|
290
|
+
const toolResultMessage = await executeTool(
|
|
291
|
+
this.#optionsForCall(),
|
|
292
|
+
"read",
|
|
293
|
+
toolCallId,
|
|
294
|
+
{ path: args.path },
|
|
295
|
+
undefined,
|
|
296
|
+
signal,
|
|
297
|
+
markNonAbortable,
|
|
298
|
+
);
|
|
248
299
|
return toolResultMessage;
|
|
249
300
|
}
|
|
250
301
|
|
|
251
|
-
async ls(
|
|
302
|
+
async ls(
|
|
303
|
+
args: Parameters<NonNullable<ICursorExecHandlers["ls"]>>[0],
|
|
304
|
+
signal?: AbortSignal,
|
|
305
|
+
markNonAbortable?: () => void,
|
|
306
|
+
) {
|
|
252
307
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
253
308
|
// Redirect ls to read tool, which handles directories
|
|
254
|
-
const toolResultMessage = await executeTool(
|
|
309
|
+
const toolResultMessage = await executeTool(
|
|
310
|
+
this.#optionsForCall(),
|
|
311
|
+
"read",
|
|
312
|
+
toolCallId,
|
|
313
|
+
{ path: args.path },
|
|
314
|
+
undefined,
|
|
315
|
+
signal,
|
|
316
|
+
markNonAbortable,
|
|
317
|
+
);
|
|
255
318
|
return toolResultMessage;
|
|
256
319
|
}
|
|
257
320
|
|
|
258
|
-
async grep(args: Parameters<NonNullable<ICursorExecHandlers["grep"]>>[0]) {
|
|
321
|
+
async grep(args: Parameters<NonNullable<ICursorExecHandlers["grep"]>>[0], signal?: AbortSignal) {
|
|
259
322
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
260
323
|
// Cursor's native Glob tool arrives as a grep exec with a glob but no content
|
|
261
324
|
// pattern. The search tool requires a non-empty pattern, so an empty pattern
|
|
@@ -265,7 +328,7 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
265
328
|
if (pattern.trim().length === 0) {
|
|
266
329
|
if (args.glob) {
|
|
267
330
|
const globPath = `${args.path || "."}/${args.glob}`;
|
|
268
|
-
return executeTool(this.#optionsForCall(), "find", toolCallId, { paths: [globPath] });
|
|
331
|
+
return executeTool(this.#optionsForCall(), "find", toolCallId, { paths: [globPath] }, undefined, signal);
|
|
269
332
|
}
|
|
270
333
|
const result = buildToolErrorResult(
|
|
271
334
|
"Cursor grep request rejected: pattern must not be empty. Provide a non-empty search pattern.",
|
|
@@ -273,45 +336,90 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
273
336
|
return createToolResultMessage(toolCallId, "search", result, true);
|
|
274
337
|
}
|
|
275
338
|
const searchPath = args.glob ? `${args.path || "."}/${args.glob}` : args.path || ".";
|
|
276
|
-
const toolResultMessage = await executeTool(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
339
|
+
const toolResultMessage = await executeTool(
|
|
340
|
+
this.#optionsForCall(),
|
|
341
|
+
"search",
|
|
342
|
+
toolCallId,
|
|
343
|
+
{
|
|
344
|
+
pattern,
|
|
345
|
+
paths: [searchPath],
|
|
346
|
+
i: args.caseInsensitive || undefined,
|
|
347
|
+
},
|
|
348
|
+
undefined,
|
|
349
|
+
signal,
|
|
350
|
+
);
|
|
281
351
|
return toolResultMessage;
|
|
282
352
|
}
|
|
283
353
|
|
|
284
|
-
async write(
|
|
354
|
+
async write(
|
|
355
|
+
args: Parameters<NonNullable<ICursorExecHandlers["write"]>>[0],
|
|
356
|
+
signal?: AbortSignal,
|
|
357
|
+
markNonAbortable?: () => void,
|
|
358
|
+
) {
|
|
285
359
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
286
360
|
const content = args.fileText ?? new TextDecoder().decode(args.fileBytes ?? new Uint8Array());
|
|
287
|
-
const toolResultMessage = await executeTool(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
361
|
+
const toolResultMessage = await executeTool(
|
|
362
|
+
this.#optionsForCall(),
|
|
363
|
+
"write",
|
|
364
|
+
toolCallId,
|
|
365
|
+
{
|
|
366
|
+
path: args.path,
|
|
367
|
+
content,
|
|
368
|
+
},
|
|
369
|
+
undefined,
|
|
370
|
+
signal,
|
|
371
|
+
markNonAbortable,
|
|
372
|
+
);
|
|
291
373
|
return toolResultMessage;
|
|
292
374
|
}
|
|
293
375
|
|
|
294
|
-
async delete(
|
|
376
|
+
async delete(
|
|
377
|
+
args: Parameters<NonNullable<ICursorExecHandlers["delete"]>>[0],
|
|
378
|
+
signal?: AbortSignal,
|
|
379
|
+
markNonAbortable?: () => void,
|
|
380
|
+
) {
|
|
381
|
+
if (signal?.aborted) throw cursorAbortError(signal);
|
|
295
382
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
296
|
-
const toolResultMessage = await executeDelete(
|
|
383
|
+
const toolResultMessage = await executeDelete(
|
|
384
|
+
this.#optionsForCall(),
|
|
385
|
+
args.path,
|
|
386
|
+
toolCallId,
|
|
387
|
+
signal,
|
|
388
|
+
markNonAbortable,
|
|
389
|
+
);
|
|
297
390
|
return toolResultMessage;
|
|
298
391
|
}
|
|
299
392
|
|
|
300
|
-
async shell(
|
|
393
|
+
async shell(
|
|
394
|
+
args: Parameters<NonNullable<ICursorExecHandlers["shell"]>>[0],
|
|
395
|
+
signal?: AbortSignal,
|
|
396
|
+
markNonAbortable?: () => void,
|
|
397
|
+
) {
|
|
301
398
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
302
399
|
const timeoutSeconds = shellTimeoutSeconds(args.timeout);
|
|
303
|
-
const toolResultMessage = await executeTool(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
400
|
+
const toolResultMessage = await executeTool(
|
|
401
|
+
this.#optionsForCall(),
|
|
402
|
+
"bash",
|
|
403
|
+
toolCallId,
|
|
404
|
+
{
|
|
405
|
+
command: args.command,
|
|
406
|
+
cwd: args.workingDirectory || undefined,
|
|
407
|
+
timeout: timeoutSeconds,
|
|
408
|
+
},
|
|
409
|
+
undefined,
|
|
410
|
+
signal,
|
|
411
|
+
markNonAbortable,
|
|
412
|
+
);
|
|
308
413
|
return toolResultMessage;
|
|
309
414
|
}
|
|
310
415
|
|
|
311
416
|
async shellStream(
|
|
312
417
|
args: Parameters<NonNullable<ICursorExecHandlers["shellStream"]>>[0],
|
|
313
418
|
callbacks: CursorShellStreamCallbacks,
|
|
419
|
+
signal?: AbortSignal,
|
|
420
|
+
markNonAbortable?: () => void,
|
|
314
421
|
) {
|
|
422
|
+
if (signal?.aborted) throw cursorAbortError(signal);
|
|
315
423
|
const options = this.#optionsForCall();
|
|
316
424
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
317
425
|
const toolName = "bash";
|
|
@@ -329,6 +437,7 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
329
437
|
};
|
|
330
438
|
|
|
331
439
|
options.emitEvent?.({ type: "tool_execution_start", toolCallId, toolName, args: toolArgs }, tool);
|
|
440
|
+
if (signal?.aborted) throw cursorAbortError(signal);
|
|
332
441
|
|
|
333
442
|
let result: AgentToolResult<unknown>;
|
|
334
443
|
let isError = false;
|
|
@@ -373,8 +482,13 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
373
482
|
};
|
|
374
483
|
|
|
375
484
|
try {
|
|
376
|
-
|
|
485
|
+
const nonAbortable = tool.nonAbortable === true;
|
|
486
|
+
const toolContext = options.getToolContext?.();
|
|
487
|
+
if (signal?.aborted) throw cursorAbortError(signal);
|
|
488
|
+
if (nonAbortable) markNonAbortable?.();
|
|
489
|
+
result = await tool.execute(toolCallId, toolArgs, nonAbortable ? undefined : signal, onUpdate, toolContext);
|
|
377
490
|
} catch (error) {
|
|
491
|
+
if (isCursorExecAdmissionClosedError(error)) throw error;
|
|
378
492
|
const message = error instanceof Error ? error.message : String(error);
|
|
379
493
|
result = buildToolErrorResult(message);
|
|
380
494
|
isError = true;
|
|
@@ -414,14 +528,30 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
414
528
|
if (composed === null) {
|
|
415
529
|
return createToolResultMessage(call.toolCallId, "read", { content: [{ type: "text", text: "" }] }, false);
|
|
416
530
|
}
|
|
417
|
-
return executeTool(
|
|
531
|
+
return executeTool(
|
|
532
|
+
this.#optionsForCall(),
|
|
533
|
+
"read",
|
|
534
|
+
call.toolCallId,
|
|
535
|
+
{ path: composed },
|
|
536
|
+
undefined,
|
|
537
|
+
call.signal,
|
|
538
|
+
call.markNonAbortable,
|
|
539
|
+
);
|
|
418
540
|
}
|
|
419
541
|
|
|
420
542
|
async piBash(call: Parameters<NonNullable<ICursorExecHandlers["piBash"]>>[0]) {
|
|
421
|
-
return executeTool(
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
543
|
+
return executeTool(
|
|
544
|
+
this.#optionsForCall(),
|
|
545
|
+
"bash",
|
|
546
|
+
call.toolCallId,
|
|
547
|
+
{
|
|
548
|
+
command: call.args.command,
|
|
549
|
+
timeout: piTimeout(call.args.timeout),
|
|
550
|
+
},
|
|
551
|
+
undefined,
|
|
552
|
+
call.signal,
|
|
553
|
+
call.markNonAbortable,
|
|
554
|
+
);
|
|
425
555
|
}
|
|
426
556
|
|
|
427
557
|
async piEdit(call: Parameters<NonNullable<ICursorExecHandlers["piEdit"]>>[0]) {
|
|
@@ -435,14 +565,24 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
435
565
|
call.toolCallId,
|
|
436
566
|
{ path: call.args.path, edits },
|
|
437
567
|
this.options.getEditReplaceTool?.(),
|
|
568
|
+
call.signal,
|
|
569
|
+
call.markNonAbortable,
|
|
438
570
|
);
|
|
439
571
|
}
|
|
440
572
|
|
|
441
573
|
async piWrite(call: Parameters<NonNullable<ICursorExecHandlers["piWrite"]>>[0]) {
|
|
442
|
-
return executeTool(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
574
|
+
return executeTool(
|
|
575
|
+
this.#optionsForCall(),
|
|
576
|
+
"write",
|
|
577
|
+
call.toolCallId,
|
|
578
|
+
{
|
|
579
|
+
path: call.args.path,
|
|
580
|
+
content: call.args.content,
|
|
581
|
+
},
|
|
582
|
+
undefined,
|
|
583
|
+
call.signal,
|
|
584
|
+
call.markNonAbortable,
|
|
585
|
+
);
|
|
446
586
|
}
|
|
447
587
|
|
|
448
588
|
async piGrep(call: Parameters<NonNullable<ICursorExecHandlers["piGrep"]>>[0]) {
|
|
@@ -456,33 +596,55 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
456
596
|
paths: [glob ? piJoinPath(path, glob) : path || "."],
|
|
457
597
|
};
|
|
458
598
|
if (ignoreCase === true) args.i = true;
|
|
459
|
-
return executeTool(this.#optionsForCall(), "search", call.toolCallId, args, perCallSearch);
|
|
599
|
+
return executeTool(this.#optionsForCall(), "search", call.toolCallId, args, perCallSearch, call.signal);
|
|
460
600
|
}
|
|
461
601
|
|
|
462
602
|
async piFind(call: Parameters<NonNullable<ICursorExecHandlers["piFind"]>>[0]) {
|
|
463
603
|
const { pattern, path, limit } = call.args;
|
|
464
|
-
return executeTool(
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
604
|
+
return executeTool(
|
|
605
|
+
this.#optionsForCall(),
|
|
606
|
+
"find",
|
|
607
|
+
call.toolCallId,
|
|
608
|
+
{
|
|
609
|
+
paths: [piJoinPath(path, pattern)],
|
|
610
|
+
limit: piLimit(limit),
|
|
611
|
+
},
|
|
612
|
+
undefined,
|
|
613
|
+
call.signal,
|
|
614
|
+
);
|
|
468
615
|
}
|
|
469
616
|
|
|
470
617
|
async piLs(call: Parameters<NonNullable<ICursorExecHandlers["piLs"]>>[0]) {
|
|
471
|
-
return executeTool(
|
|
472
|
-
|
|
473
|
-
|
|
618
|
+
return executeTool(
|
|
619
|
+
this.#optionsForCall(),
|
|
620
|
+
"read",
|
|
621
|
+
call.toolCallId,
|
|
622
|
+
{
|
|
623
|
+
path: piLsPath(call.args.path),
|
|
624
|
+
},
|
|
625
|
+
undefined,
|
|
626
|
+
call.signal,
|
|
627
|
+
call.markNonAbortable,
|
|
628
|
+
);
|
|
474
629
|
}
|
|
475
630
|
|
|
476
|
-
async diagnostics(args: Parameters<NonNullable<ICursorExecHandlers["diagnostics"]>>[0]) {
|
|
631
|
+
async diagnostics(args: Parameters<NonNullable<ICursorExecHandlers["diagnostics"]>>[0], signal?: AbortSignal) {
|
|
477
632
|
const toolCallId = decodeToolCallId(args.toolCallId);
|
|
478
|
-
const toolResultMessage = await executeTool(
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
633
|
+
const toolResultMessage = await executeTool(
|
|
634
|
+
this.#optionsForCall(),
|
|
635
|
+
"lsp",
|
|
636
|
+
toolCallId,
|
|
637
|
+
{
|
|
638
|
+
action: "diagnostics",
|
|
639
|
+
file: args.path,
|
|
640
|
+
},
|
|
641
|
+
undefined,
|
|
642
|
+
signal,
|
|
643
|
+
);
|
|
482
644
|
return toolResultMessage;
|
|
483
645
|
}
|
|
484
646
|
|
|
485
|
-
async mcp(call: CursorMcpCall) {
|
|
647
|
+
async mcp(call: CursorMcpCall, signal?: AbortSignal, markNonAbortable?: () => void) {
|
|
486
648
|
const options = this.#optionsForCall();
|
|
487
649
|
const toolName = call.toolName || call.name;
|
|
488
650
|
const toolCallId = decodeToolCallId(call.toolCallId);
|
|
@@ -495,7 +657,15 @@ export class CursorExecHandlers implements ICursorExecHandlers {
|
|
|
495
657
|
}
|
|
496
658
|
|
|
497
659
|
const args = Object.keys(call.args ?? {}).length > 0 ? call.args : decodeMcpArgs(call.rawArgs ?? {});
|
|
498
|
-
const toolResultMessage = await executeTool(
|
|
660
|
+
const toolResultMessage = await executeTool(
|
|
661
|
+
options,
|
|
662
|
+
toolName,
|
|
663
|
+
toolCallId,
|
|
664
|
+
args,
|
|
665
|
+
undefined,
|
|
666
|
+
signal,
|
|
667
|
+
markNonAbortable,
|
|
668
|
+
);
|
|
499
669
|
return toolResultMessage;
|
|
500
670
|
}
|
|
501
671
|
}
|