@gajae-code/coding-agent 0.11.11 → 0.12.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 +131 -4
- package/dist/types/async/job-manager.d.ts +17 -3
- package/dist/types/cli/read-cli.d.ts +1 -0
- package/dist/types/commands/deep-interview.d.ts +9 -0
- package/dist/types/commands/harness.d.ts +22 -0
- package/dist/types/commands/read.d.ts +6 -0
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/provider-auth-health.d.ts +14 -0
- package/dist/types/config/provider-ranking.d.ts +59 -0
- package/dist/types/config/settings-schema.d.ts +83 -1
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/exa/mcp-client.d.ts +10 -1
- package/dist/types/exec/bash-executor.d.ts +45 -12
- package/dist/types/extensibility/extensions/types.d.ts +38 -4
- package/dist/types/extensibility/gjc-plugins/index.d.ts +12 -2
- package/dist/types/extensibility/gjc-plugins/installer.d.ts +63 -7
- package/dist/types/extensibility/gjc-plugins/lifecycle-reconciliation.d.ts +55 -0
- package/dist/types/extensibility/gjc-plugins/lifecycle.d.ts +64 -0
- package/dist/types/extensibility/gjc-plugins/runtime-quarantine.d.ts +67 -0
- package/dist/types/extensibility/gjc-plugins/session-validation.d.ts +3 -1
- package/dist/types/extensibility/gjc-plugins/types.d.ts +124 -0
- package/dist/types/extensibility/shared-events.d.ts +6 -0
- package/dist/types/gjc-runtime/deep-interview-ambiguity.d.ts +5 -12
- package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +17 -32
- package/dist/types/gjc-runtime/deep-interview-stage.d.ts +37 -0
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +4 -135
- package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +1 -0
- package/dist/types/gjc-runtime/memory-guard-owner-claims.d.ts +47 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +70 -1
- package/dist/types/gjc-runtime/state-writer.d.ts +5 -46
- package/dist/types/gjc-runtime/team-launch.d.ts +1 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +27 -1
- package/dist/types/gjc-runtime/team-store.d.ts +12 -0
- package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +43 -0
- package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +92 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +17 -0
- package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +8 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +31 -80
- package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -5
- package/dist/types/internal-urls/local-root-gc.d.ts +2 -0
- package/dist/types/main.d.ts +1 -1
- package/dist/types/memories/index.d.ts +2 -0
- package/dist/types/modes/acp/acp-agent.d.ts +10 -19
- package/dist/types/modes/components/assistant-message.d.ts +3 -1
- package/dist/types/modes/components/gjc-bundle-settings.d.ts +34 -0
- package/dist/types/modes/components/irc-sidebar.d.ts +41 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +1 -0
- package/dist/types/modes/components/read-tool-group.d.ts +4 -4
- package/dist/types/modes/components/session-observer-overlay.d.ts +22 -0
- package/dist/types/modes/components/settings-selector.d.ts +11 -0
- package/dist/types/modes/components/status-line/gh.d.ts +5 -0
- package/dist/types/modes/components/tool-execution.d.ts +8 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +18 -1
- package/dist/types/modes/controllers/event-controller.d.ts +3 -0
- package/dist/types/modes/interactive-mode.d.ts +2 -0
- package/dist/types/modes/irc-observation-ledger.d.ts +17 -1
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/modes/utils/ui-helpers.d.ts +16 -0
- package/dist/types/reminders/star-reminder.d.ts +3 -13
- package/dist/types/runtime-mcp/manager.d.ts +1 -0
- package/dist/types/runtime-mcp/smithery-auth.d.ts +5 -0
- package/dist/types/sdk/acp/adapter.d.ts +3 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +5 -0
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/attachment-registry.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -1
- package/dist/types/sdk/bus/config.d.ts +6 -2
- package/dist/types/sdk/bus/control-drain-lease.d.ts +52 -0
- package/dist/types/sdk/bus/index.d.ts +44 -1
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +44 -0
- package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +2 -1
- package/dist/types/sdk/bus/reconciliation-store.d.ts +69 -0
- package/dist/types/sdk/bus/rich-draft.d.ts +1 -0
- package/dist/types/sdk/bus/rich-render.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-adoption-intent.d.ts +165 -0
- package/dist/types/sdk/bus/telegram-cli.d.ts +12 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -1
- package/dist/types/sdk/bus/telegram-reference.d.ts +11 -1
- package/dist/types/sdk/bus/threaded-render.d.ts +3 -2
- package/dist/types/sdk/bus/topic-registry.d.ts +11 -1
- package/dist/types/sdk/host/control/operations.d.ts +1 -1
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/host/query/handlers.d.ts +5 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +2 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +1 -1
- package/dist/types/sdk/prompt-status.d.ts +23 -3
- package/dist/types/sdk/session.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +82 -12
- package/dist/types/session/artifacts.d.ts +8 -0
- package/dist/types/session/blob-store.d.ts +57 -4
- package/dist/types/session/internal/managed-session-storage.d.ts +8 -1
- package/dist/types/session/memory-guard-checkpoint-participant.d.ts +69 -0
- package/dist/types/session/session-manager.d.ts +48 -19
- package/dist/types/session/session-storage.d.ts +4 -0
- package/dist/types/session/streaming-output.d.ts +96 -12
- package/dist/types/setup/credential-import.d.ts +12 -0
- package/dist/types/skill-state/active-state.d.ts +12 -4
- package/dist/types/skill-state/workflow-hud.d.ts +9 -0
- package/dist/types/task/executor.d.ts +3 -2
- package/dist/types/task/index.d.ts +3 -1
- package/dist/types/task/provider-retry-status.d.ts +8 -0
- package/dist/types/task/receipt.d.ts +7 -1
- package/dist/types/task/types.d.ts +23 -0
- package/dist/types/tools/ask-answer-registry.d.ts +2 -2
- package/dist/types/tools/bash-interactive.d.ts +4 -1
- package/dist/types/tools/bash.d.ts +3 -1
- package/dist/types/tools/browser/launch.d.ts +7 -0
- package/dist/types/tools/fetch.d.ts +17 -1
- package/dist/types/tools/image-gen.d.ts +4 -0
- package/dist/types/tools/index.d.ts +4 -0
- package/dist/types/tools/output-meta.d.ts +44 -3
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/read-internals.d.ts +12 -0
- package/dist/types/tools/read.d.ts +45 -7
- package/dist/types/tools/resource-gc.d.ts +4 -0
- package/dist/types/tools/review.d.ts +5 -7
- package/dist/types/tools/subagent.d.ts +2 -0
- package/dist/types/tools/tool-result.d.ts +7 -1
- package/dist/types/utils/gh.d.ts +13 -0
- package/dist/types/utils/image-resize.d.ts +1 -0
- package/dist/types/web/search/providers/kimi.d.ts +2 -0
- package/dist/types/web/search/providers/searxng.d.ts +7 -0
- package/dist/types/web/search/providers/xai.d.ts +2 -0
- package/package.json +11 -13
- package/scripts/acp-conformance-agent.ts +218 -0
- package/scripts/benchmark-sticky-viewport-pr1.ts +239 -0
- package/scripts/capture-gjc-bundle-settings.ts +306 -0
- package/scripts/capture-sticky-viewport-showcase.ts +292 -0
- package/scripts/generate-sdk-operation-inventory.ts +5 -0
- package/scripts/resident-memory-bench.ts +1341 -0
- package/scripts/run-acp-conformance.ts +285 -0
- package/scripts/verify-gjc-sdk-canonicalization.ts +122 -18
- package/scripts/verify-sticky-viewport-showcase.ts +611 -0
- package/src/async/job-manager.ts +78 -20
- package/src/capability/index.ts +8 -0
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/plugin-cli.ts +176 -18
- package/src/cli/read-cli.ts +2 -1
- package/src/cli.ts +1 -0
- package/src/commands/deep-interview.ts +29 -9
- package/src/commands/harness.ts +35 -12
- package/src/commands/read.ts +11 -2
- package/src/commands/team.ts +20 -2
- package/src/config/file-lock.ts +11 -2
- package/src/config/model-registry.ts +21 -2
- package/src/config/provider-auth-health.ts +42 -0
- package/src/config/provider-ranking.ts +119 -0
- package/src/config/settings-schema.ts +74 -1
- package/src/config/settings.ts +246 -108
- package/src/coordinator-mcp/question-gate-codec.ts +1 -1
- package/src/coordinator-mcp/server.ts +5 -12
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +230 -82
- package/src/defaults/gjc/skills/ralplan/SKILL.md +77 -41
- package/src/defaults/gjc/skills/team/SKILL.md +3 -1
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +62 -39
- package/src/defaults/gjc/skills/ultragoal/validation-batch-contracts.md +12 -0
- package/src/defaults/gjc-defaults.ts +4 -4
- package/src/eval/py/executor.ts +7 -2
- package/src/exa/mcp-client.ts +12 -3
- package/src/exec/bash-executor.ts +144 -27
- package/src/extensibility/extensions/runner.ts +15 -0
- package/src/extensibility/extensions/types.ts +46 -5
- package/src/extensibility/gjc-plugins/constrained-hooks.ts +8 -2
- package/src/extensibility/gjc-plugins/index.ts +19 -2
- package/src/extensibility/gjc-plugins/installer.ts +189 -50
- package/src/extensibility/gjc-plugins/lifecycle-reconciliation.ts +199 -0
- package/src/extensibility/gjc-plugins/lifecycle.ts +626 -0
- package/src/extensibility/gjc-plugins/observability.ts +3 -3
- package/src/extensibility/gjc-plugins/prompt-appendix.ts +5 -1
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +12 -2
- package/src/extensibility/gjc-plugins/runtime-quarantine.ts +121 -0
- package/src/extensibility/gjc-plugins/schema.ts +84 -12
- package/src/extensibility/gjc-plugins/session-validation.ts +9 -3
- package/src/extensibility/gjc-plugins/types.ts +141 -0
- package/src/extensibility/gjc-plugins/validation.ts +9 -0
- package/src/extensibility/shared-events.ts +5 -0
- package/src/gjc-runtime/deep-interview-ambiguity.ts +47 -82
- package/src/gjc-runtime/deep-interview-recorder.ts +227 -310
- package/src/gjc-runtime/deep-interview-runtime.ts +109 -270
- package/src/gjc-runtime/deep-interview-stage.ts +1016 -0
- package/src/gjc-runtime/deep-interview-state.ts +12 -943
- package/src/gjc-runtime/gc-render.ts +1 -0
- package/src/gjc-runtime/gc-runtime.ts +11 -1
- package/src/gjc-runtime/launch-tmux.ts +25 -6
- package/src/gjc-runtime/managed-owner-admission.ts +1 -1
- package/src/gjc-runtime/memory-guard-owner-claims.ts +389 -0
- package/src/gjc-runtime/ralplan-runtime.ts +1149 -98
- package/src/gjc-runtime/state-runtime.ts +2 -1
- package/src/gjc-runtime/state-writer.ts +70 -222
- package/src/gjc-runtime/team-launch.ts +42 -5
- package/src/gjc-runtime/team-runtime.ts +1085 -40
- package/src/gjc-runtime/team-store.ts +32 -0
- package/src/gjc-runtime/team-worker-heartbeat.ts +149 -0
- package/src/gjc-runtime/team-worker-memory-guard.ts +363 -0
- package/src/gjc-runtime/team-workers.ts +1 -0
- package/src/gjc-runtime/tmux-owner-isolation.ts +28 -0
- package/src/gjc-runtime/tmux-sessions.ts +58 -13
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +20 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +414 -618
- package/src/gjc-runtime/workflow-manifest.generated.json +105 -449
- package/src/gjc-runtime/workflow-manifest.ts +38 -247
- package/src/hooks/native-skill-hook.ts +17 -4
- package/src/hooks/skill-state.ts +1 -23
- package/src/internal-urls/docs-index.generated.ts +21 -22
- package/src/internal-urls/local-root-gc.ts +127 -0
- package/src/main.ts +9 -5
- package/src/memories/index.ts +10 -0
- package/src/modes/DESIGN.md +98 -0
- package/src/modes/acp/acp-agent.ts +339 -191
- package/src/modes/acp/acp-event-mapper.ts +14 -7
- package/src/modes/acp/acp-mode.ts +39 -3
- package/src/modes/components/assistant-message.ts +123 -22
- package/src/modes/components/gjc-bundle-settings.ts +508 -0
- package/src/modes/components/irc-sidebar.ts +176 -62
- package/src/modes/components/model-selector.ts +61 -4
- package/src/modes/components/notifications-settings-editor.ts +12 -1
- package/src/modes/components/oauth-selector.ts +96 -28
- package/src/modes/components/read-tool-group.ts +82 -14
- package/src/modes/components/session-observer-overlay.ts +457 -83
- package/src/modes/components/settings-selector.ts +116 -23
- package/src/modes/components/status-line/gh.ts +16 -0
- package/src/modes/components/tool-execution.ts +138 -27
- package/src/modes/components/tool-status-header.ts +3 -14
- package/src/modes/components/transcript-viewer-overlay.ts +99 -24
- package/src/modes/controllers/command-controller.ts +4 -0
- package/src/modes/controllers/event-controller.ts +109 -27
- package/src/modes/controllers/extension-ui-controller.ts +26 -2
- package/src/modes/controllers/input-controller.ts +18 -3
- package/src/modes/controllers/selector-controller.ts +127 -36
- package/src/modes/interactive-mode.ts +62 -3
- package/src/modes/irc-observation-ledger.ts +71 -15
- package/src/modes/runtime-init.ts +22 -2
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/ui-helpers.ts +94 -1
- package/src/prompts/agent-fragments/ralplan-persistence.md +4 -3
- package/src/prompts/agents/architect.md +9 -1
- package/src/prompts/agents/critic.md +9 -0
- package/src/prompts/system/eager-todo.md +8 -4
- package/src/prompts/system/system-prompt.md +11 -5
- package/src/prompts/tools/bash.md +5 -5
- package/src/prompts/tools/read.md +4 -2
- package/src/prompts/tools/search-tool-bm25.md +5 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/reminders/star-reminder.ts +4 -42
- package/src/runtime-mcp/manager.ts +19 -4
- package/src/runtime-mcp/smithery-auth.ts +17 -2
- package/src/runtime-mcp/smithery-connect.ts +11 -1
- package/src/sdk/acp/adapter.ts +22 -6
- package/src/sdk/broker/lifecycle.ts +25 -6
- package/src/sdk/broker/transport.ts +35 -3
- package/src/sdk/bus/attachment-registry.ts +5 -1
- package/src/sdk/bus/chat-daemon-cli.ts +4 -39
- package/src/sdk/bus/chat-daemon-control.ts +6 -3
- package/src/sdk/bus/config.ts +18 -2
- package/src/sdk/bus/control-drain-lease.ts +104 -0
- package/src/sdk/bus/index.ts +984 -146
- package/src/sdk/bus/kind-aware-reconciliation.ts +317 -0
- package/src/sdk/bus/lifecycle-commands.ts +4 -1
- package/src/sdk/bus/lifecycle-control-runtime.ts +403 -88
- package/src/sdk/bus/prompt-reconciliation.ts +2 -1
- package/src/sdk/bus/reconciliation-store.ts +303 -0
- package/src/sdk/bus/rich-draft.ts +1 -1
- package/src/sdk/bus/rich-render.ts +2 -2
- package/src/sdk/bus/telegram-adoption-intent.ts +574 -0
- package/src/sdk/bus/telegram-cli.ts +33 -8
- package/src/sdk/bus/telegram-daemon-cli.ts +1 -0
- package/src/sdk/bus/telegram-daemon-contract.ts +11 -4
- package/src/sdk/bus/telegram-daemon.ts +916 -23
- package/src/sdk/bus/telegram-reference.ts +40 -3
- package/src/sdk/bus/threaded-render.ts +48 -3
- package/src/sdk/bus/topic-registry.ts +20 -0
- package/src/sdk/host/control/dispatch.ts +5 -1
- package/src/sdk/host/control/operations.ts +1 -1
- package/src/sdk/host/host.ts +23 -1
- package/src/sdk/host/query/handlers.ts +55 -0
- package/src/sdk/host/query/revision-store.ts +36 -2
- package/src/sdk/host/reverse-leases.ts +44 -7
- package/src/sdk/mcp/server.ts +46 -18
- package/src/sdk/prompt-status.ts +16 -3
- package/src/sdk/protocol/operation-inventory.generated.json +51 -0
- package/src/sdk/protocol/operation-registry.ts +7 -2
- package/src/sdk/session.ts +101 -10
- package/src/session/agent-session.ts +1286 -220
- package/src/session/artifacts.ts +22 -0
- package/src/session/auth-broker-config.ts +10 -3
- package/src/session/blob-store.ts +915 -24
- package/src/session/internal/managed-session-scope.ts +44 -6
- package/src/session/internal/managed-session-storage.ts +48 -6
- package/src/session/memory-guard-checkpoint-participant.ts +131 -0
- package/src/session/session-manager.ts +2364 -438
- package/src/session/session-storage.ts +9 -1
- package/src/session/streaming-output.ts +500 -111
- package/src/setup/credential-import.ts +75 -13
- package/src/setup/provider-onboarding.ts +19 -4
- package/src/skill-state/active-state.ts +32 -10
- package/src/skill-state/workflow-hud.ts +42 -2
- package/src/skill-state/workflow-mutation-guard.ts +560 -8
- package/src/task/executor.ts +122 -39
- package/src/task/index.ts +23 -14
- package/src/task/provider-retry-status.ts +16 -0
- package/src/task/receipt.ts +23 -7
- package/src/task/render.ts +6 -2
- package/src/task/types.ts +108 -0
- package/src/tools/ask-answer-registry.ts +12 -6
- package/src/tools/ask.ts +169 -118
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash-interactive.ts +8 -3
- package/src/tools/bash.ts +503 -60
- package/src/tools/browser/launch.ts +41 -6
- package/src/tools/fetch.ts +114 -23
- package/src/tools/find.ts +1 -0
- package/src/tools/image-gen.ts +29 -5
- package/src/tools/index.ts +4 -0
- package/src/tools/output-meta.ts +281 -20
- package/src/tools/path-utils.ts +8 -3
- package/src/tools/read-internals.ts +44 -0
- package/src/tools/read.ts +1560 -310
- package/src/tools/resource-gc.ts +182 -18
- package/src/tools/review.ts +5 -7
- package/src/tools/search.ts +1 -0
- package/src/tools/subagent-render.ts +6 -2
- package/src/tools/subagent.ts +6 -0
- package/src/tools/telegram-send.ts +6 -3
- package/src/tools/tool-result.ts +14 -1
- package/src/utils/gh.ts +39 -0
- package/src/utils/image-resize.ts +3 -0
- package/src/web/search/providers/anthropic.ts +4 -4
- package/src/web/search/providers/codex.ts +1 -1
- package/src/web/search/providers/kimi.ts +15 -5
- package/src/web/search/providers/searxng.ts +47 -4
- package/src/web/search/providers/xai.ts +7 -2
- package/dist/types/gjc-runtime/deep-interview-draft.d.ts +0 -8
- package/dist/types/gjc-runtime/deep-interview-payload.d.ts +0 -41
- package/dist/types/gjc-runtime/deep-interview-repair.d.ts +0 -17
- package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +0 -23
- package/src/defaults/gjc/skills/ultragoal/pipeline-validation-contracts.md +0 -30
- package/src/gjc-runtime/deep-interview-draft.ts +0 -843
- package/src/gjc-runtime/deep-interview-payload.ts +0 -262
- package/src/gjc-runtime/deep-interview-repair.ts +0 -1674
- package/src/gjc-runtime/ultragoal-pipeline.ts +0 -306
package/src/task/types.ts
CHANGED
|
@@ -212,6 +212,14 @@ export interface ReviewFinding {
|
|
|
212
212
|
line_end: number;
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
/** Durable full-fidelity review findings artifact associated with a task result. */
|
|
216
|
+
export interface ReviewFindingsArtifactRef {
|
|
217
|
+
uri: `artifact://${string}`;
|
|
218
|
+
sizeBytes: number;
|
|
219
|
+
sha256: string;
|
|
220
|
+
findingCount: number;
|
|
221
|
+
}
|
|
222
|
+
|
|
215
223
|
/** Review summary submitted by the reviewer agent */
|
|
216
224
|
export interface ReviewSummary {
|
|
217
225
|
overall_correctness: "correct" | "incorrect";
|
|
@@ -283,6 +291,8 @@ export interface AgentProgress {
|
|
|
283
291
|
durationMs: number;
|
|
284
292
|
modelOverride?: string | string[];
|
|
285
293
|
modelSubstitutionWarning?: ModelSubstitutionWarning;
|
|
294
|
+
/** Whether the resolved subagent model runs under the effective fast service tier. */
|
|
295
|
+
fastMode?: boolean;
|
|
286
296
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
287
297
|
extractedToolData?: Record<string, unknown[]>;
|
|
288
298
|
/**
|
|
@@ -313,6 +323,8 @@ export interface AgentProgress {
|
|
|
313
323
|
attempt: number;
|
|
314
324
|
errorMessage: string;
|
|
315
325
|
};
|
|
326
|
+
/** Safe diagnostic retained in terminal progress when setup fails before the first LLM request. */
|
|
327
|
+
setupFailure?: SetupFailureSummary;
|
|
316
328
|
/**
|
|
317
329
|
* Snapshot of the most recent `task` tool call's in-flight `TaskToolDetails`,
|
|
318
330
|
* captured from `tool_execution_update`. Lets the parent UI surface live
|
|
@@ -323,6 +335,96 @@ export interface AgentProgress {
|
|
|
323
335
|
inflightTaskDetails?: TaskToolDetails;
|
|
324
336
|
}
|
|
325
337
|
|
|
338
|
+
/** Bounded diagnostic retained when subagent setup fails before an LLM request starts. */
|
|
339
|
+
export interface SetupFailureSummary {
|
|
340
|
+
summary: string;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const SETUP_FAILURE_SUMMARY_MAX_CHARS = 280;
|
|
344
|
+
const SETUP_FAILURE_SUMMARY_MAX_BYTES = 1_024;
|
|
345
|
+
const AUTHORIZATION_HEADER_VALUE_PATTERN = /(["']?(?:Proxy-)?Authorization\b["']?\s*:\s*)[^\r\n]*/gi;
|
|
346
|
+
const COOKIE_HEADER_VALUE_PATTERN = /(["']?(?:Set-)?Cookie\b["']?\s*:\s*)[^\r\n]*/gi;
|
|
347
|
+
const URL_CREDENTIAL_PATTERN = /([a-z][a-z0-9+.-]*:\/\/)[^/?#\s:@]+:[^@/?#\s]+@/gi;
|
|
348
|
+
const API_KEY_LABEL_VALUE_PATTERN = /(["']?api\s+key["']?\s*:\s*)(?:"[^"]*"|'[^']*'|[^\s&]+)/gi;
|
|
349
|
+
const SENSITIVE_SETUP_FAILURE_VALUE_PATTERN =
|
|
350
|
+
/(["']?(?:(?:[A-Za-z][A-Za-z0-9]*[_.-])*?)(?:access[_-]?token|refresh[_-]?token|session[_-]?token|id[_-]?token|api[_-]?key|client[_-]?secret|private[_-]?key|signing[_-]?key|secret|password|passwd|pwd|authorization|credential|token)(?:[_.-][A-Za-z0-9]+)*["']?)(\s*[=:]\s*)(?:"[^"]*"|'[^']*'|[^\s&]+)/gi;
|
|
351
|
+
const BARE_PROVIDER_TOKEN_PATTERN =
|
|
352
|
+
/\b(?:gh[pousr]_[A-Za-z0-9_]{20,}|github_pat_[A-Za-z0-9_]{20,}|xox[baprs]-[A-Za-z0-9-]{20,}|sk-(?:proj-)?[A-Za-z0-9_-]{20,}|sk-ant-[A-Za-z0-9_-]{20,}|AIza[A-Za-z0-9_-]{35}|AKIA[A-Z0-9]{16})\b/g;
|
|
353
|
+
const LOCAL_ABSOLUTE_PATH_PATTERN = /(^|[\s("'`=])((?:\/(?!\/)[^\s/:?"'`()[\]{},;<>]+){2,})/g;
|
|
354
|
+
const WINDOWS_ABSOLUTE_PATH_PATTERN =
|
|
355
|
+
/(^|[\s("'`=])([A-Za-z]:\\(?:[^\\/:?"'`()[\]{},;<>\s]+\\)+[^\\/:?"'`()[\]{},;<>\s]+)/g;
|
|
356
|
+
const LOCAL_FILE_URI_PATTERN = /\bfile:\/\/(?:localhost)?(?:\/[^\s/:?"'`()[\]{},;<>]+)+/gi;
|
|
357
|
+
const SENSITIVE_PATH_BASENAME_PATTERN =
|
|
358
|
+
/(?:^|[_.-])(?:access[_-]?token|refresh[_-]?token|session[_-]?token|id[_-]?token|api[_-]?key|client[_-]?secret|private[_-]?key|signing[_-]?key|secrets?|password|passwd|pwd|authorization|credential|token)(?:[_.-]|$)|^(?:\.env(?:\..*)?|credentials?(?:\.[A-Za-z0-9_-]+)?|id_(?:rsa|ed25519)|.+\.(?:pem|p12|pfx|key))$|^(?:sk|pk|rk|gh[opsur]|github_pat|xox[baprs])[_-][A-Za-z0-9_-]+$/i;
|
|
359
|
+
|
|
360
|
+
function redactPathBasename(path: string): string {
|
|
361
|
+
const basename = path.slice(Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1);
|
|
362
|
+
return SENSITIVE_PATH_BASENAME_PATTERN.test(basename) ? "[redacted]" : basename;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function redactLocalAbsolutePath(_match: string, prefix: string, absolutePath: string): string {
|
|
366
|
+
return `${prefix}<path>/${redactPathBasename(absolutePath)}`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function redactLocalFileUri(uri: string): string {
|
|
370
|
+
return `file://<path>/${redactPathBasename(uri)}`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
function normalizeSetupFailureText(value: string): string {
|
|
374
|
+
return value
|
|
375
|
+
.normalize("NFKC")
|
|
376
|
+
.replace(/\u001B(?:\[[0-?]*[ -/]*[@-~]|\][^\u0007\u001B]*(?:\u0007|\u001B\\))/g, "")
|
|
377
|
+
.replace(/[\u200B-\u200D\u2060\uFEFF]/g, "")
|
|
378
|
+
.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "")
|
|
379
|
+
.replace(/\t/g, " ");
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function capSetupFailureSummary(value: string): string {
|
|
383
|
+
const ellipsis = "…";
|
|
384
|
+
const ellipsisBytes = Buffer.byteLength(ellipsis, "utf8");
|
|
385
|
+
const chunks: string[] = [];
|
|
386
|
+
let chars = 0;
|
|
387
|
+
let bytes = 0;
|
|
388
|
+
for (const codePoint of value) {
|
|
389
|
+
const codePointBytes = Buffer.byteLength(codePoint, "utf8");
|
|
390
|
+
if (chars + 1 > SETUP_FAILURE_SUMMARY_MAX_CHARS || bytes + codePointBytes > SETUP_FAILURE_SUMMARY_MAX_BYTES) {
|
|
391
|
+
while (
|
|
392
|
+
chunks.length > 0 &&
|
|
393
|
+
(chars + 1 > SETUP_FAILURE_SUMMARY_MAX_CHARS || bytes + ellipsisBytes > SETUP_FAILURE_SUMMARY_MAX_BYTES)
|
|
394
|
+
) {
|
|
395
|
+
const removed = chunks.pop()!;
|
|
396
|
+
chars -= 1;
|
|
397
|
+
bytes -= Buffer.byteLength(removed, "utf8");
|
|
398
|
+
}
|
|
399
|
+
return `${chunks.join("")}${ellipsis}`;
|
|
400
|
+
}
|
|
401
|
+
chunks.push(codePoint);
|
|
402
|
+
chars += 1;
|
|
403
|
+
bytes += codePointBytes;
|
|
404
|
+
}
|
|
405
|
+
return chunks.join("");
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** Create a bounded diagnostic that preserves a setup failure's cause without exposing credentials or local paths. */
|
|
409
|
+
export function createSetupFailureSummary(error: unknown): SetupFailureSummary {
|
|
410
|
+
const message = normalizeSetupFailureText(error instanceof Error ? error.message : String(error));
|
|
411
|
+
const summary = message
|
|
412
|
+
.replace(AUTHORIZATION_HEADER_VALUE_PATTERN, "$1[redacted]")
|
|
413
|
+
.replace(COOKIE_HEADER_VALUE_PATTERN, "$1[redacted]")
|
|
414
|
+
.replace(URL_CREDENTIAL_PATTERN, "$1[redacted]@")
|
|
415
|
+
.replace(API_KEY_LABEL_VALUE_PATTERN, "$1[redacted]")
|
|
416
|
+
.replace(LOCAL_FILE_URI_PATTERN, redactLocalFileUri)
|
|
417
|
+
.replace(LOCAL_ABSOLUTE_PATH_PATTERN, redactLocalAbsolutePath)
|
|
418
|
+
.replace(WINDOWS_ABSOLUTE_PATH_PATTERN, redactLocalAbsolutePath)
|
|
419
|
+
.replace(SENSITIVE_SETUP_FAILURE_VALUE_PATTERN, "$1$2[redacted]")
|
|
420
|
+
.replace(BARE_PROVIDER_TOKEN_PATTERN, "[redacted]")
|
|
421
|
+
.replace(/\s+/g, " ")
|
|
422
|
+
.trim();
|
|
423
|
+
return {
|
|
424
|
+
summary: capSetupFailureSummary(summary) || "Subagent setup failed.",
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
|
|
326
428
|
/** Result from a single agent execution */
|
|
327
429
|
export interface SingleResult {
|
|
328
430
|
index: number;
|
|
@@ -346,7 +448,11 @@ export interface SingleResult {
|
|
|
346
448
|
contextWindow?: number;
|
|
347
449
|
modelOverride?: string | string[];
|
|
348
450
|
modelSubstitutionWarning?: ModelSubstitutionWarning;
|
|
451
|
+
/** Whether the resolved subagent model ran under the effective fast service tier. */
|
|
452
|
+
fastMode?: boolean;
|
|
349
453
|
error?: string;
|
|
454
|
+
/** Safe diagnostic for a failure before the subagent sent its first LLM request. */
|
|
455
|
+
setupFailure?: SetupFailureSummary;
|
|
350
456
|
aborted?: boolean;
|
|
351
457
|
abortReason?: string;
|
|
352
458
|
paused?: boolean;
|
|
@@ -366,6 +472,8 @@ export interface SingleResult {
|
|
|
366
472
|
producedChanges?: boolean;
|
|
367
473
|
/** Data extracted by registered subprocess tool handlers (keyed by tool name) */
|
|
368
474
|
extractedToolData?: Record<string, unknown[]>;
|
|
475
|
+
/** Full wrapper-owned review evidence, kept separate from caller completion data. */
|
|
476
|
+
reviewFindingsRef?: ReviewFindingsArtifactRef;
|
|
369
477
|
/**
|
|
370
478
|
* Terminal retry failure, when the subagent exited because the auto-retry
|
|
371
479
|
* loop gave up (retry-after exceeded the cap, or all attempts exhausted).
|
|
@@ -11,21 +11,27 @@ import { logger } from "@gajae-code/utils";
|
|
|
11
11
|
import type { WorkflowGateEmitter } from "../modes/shared/agent-wire/workflow-gate-broker";
|
|
12
12
|
import type { AskAnswerSource } from "./index";
|
|
13
13
|
|
|
14
|
-
const sources = new Map<string, AskAnswerSource>();
|
|
14
|
+
const sources = new Map<string, AskAnswerSource[]>();
|
|
15
15
|
const workflowGateEmitters = new Map<string, WorkflowGateEmitter>();
|
|
16
16
|
const workflowGateListeners = new Map<string, Set<(emitter: WorkflowGateEmitter | undefined) => void>>();
|
|
17
17
|
|
|
18
|
-
/** Register `source` for `sessionId`. Returns a disposer that
|
|
18
|
+
/** Register `source` for `sessionId`. Returns a disposer that restores the prior source. */
|
|
19
19
|
export function registerAskAnswerSource(sessionId: string, source: AskAnswerSource): () => void {
|
|
20
|
-
sources.
|
|
20
|
+
const stack = sources.get(sessionId) ?? [];
|
|
21
|
+
stack.push(source);
|
|
22
|
+
sources.set(sessionId, stack);
|
|
21
23
|
return () => {
|
|
22
|
-
|
|
24
|
+
const current = sources.get(sessionId);
|
|
25
|
+
if (!current) return;
|
|
26
|
+
const index = current.lastIndexOf(source);
|
|
27
|
+
if (index >= 0) current.splice(index, 1);
|
|
28
|
+
if (current.length === 0) sources.delete(sessionId);
|
|
23
29
|
};
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
/** The answer source for `sessionId`, if one is registered. */
|
|
32
|
+
/** The highest-priority answer source for `sessionId`, if one is registered. */
|
|
27
33
|
export function getAskAnswerSource(sessionId: string): AskAnswerSource | undefined {
|
|
28
|
-
return sources.get(sessionId);
|
|
34
|
+
return sources.get(sessionId)?.at(-1);
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
/** Publish a session's current workflow-gate emitter after mode initialization. */
|
package/src/tools/ask.ts
CHANGED
|
@@ -351,15 +351,23 @@ function parseEncodedContainer(value: unknown): unknown {
|
|
|
351
351
|
function isRoundZeroRecoveryCandidate(value: unknown): boolean {
|
|
352
352
|
const root = parseEncodedContainer(value);
|
|
353
353
|
if (typeof root !== "object" || root === null || !Object.hasOwn(root, "questions")) return false;
|
|
354
|
-
const
|
|
354
|
+
const rawQuestions = (root as Record<string, unknown>).questions;
|
|
355
|
+
const questionsValue = parseEncodedContainer(rawQuestions);
|
|
355
356
|
if (!Array.isArray(questionsValue)) return questionsValue === null;
|
|
357
|
+
const rootEncoded = typeof value === "string" || typeof rawQuestions === "string";
|
|
356
358
|
return questionsValue.some(rawQuestion => {
|
|
357
359
|
const question = parseEncodedContainer(rawQuestion);
|
|
358
360
|
if (typeof question !== "object" || question === null || !Object.hasOwn(question, "deepInterview")) return false;
|
|
359
|
-
const
|
|
361
|
+
const rawDeepInterview = (question as Record<string, unknown>).deepInterview;
|
|
362
|
+
const deepInterview = parseEncodedContainer(rawDeepInterview);
|
|
360
363
|
if (typeof deepInterview !== "object" || deepInterview === null) return false;
|
|
361
364
|
const metadata = deepInterview as Record<string, unknown>;
|
|
362
|
-
|
|
365
|
+
const hasContract = Object.hasOwn(metadata, "intent_contract");
|
|
366
|
+
const hasReview = Object.hasOwn(metadata, "intent_review");
|
|
367
|
+
// A JSON-string container is terminal only for the retired contract+review
|
|
368
|
+
// pair; canonical single-sided asks stay eligible for generic JSON coercion.
|
|
369
|
+
const encoded = rootEncoded || typeof rawQuestion === "string" || typeof rawDeepInterview === "string";
|
|
370
|
+
return encoded ? hasContract && hasReview : hasContract || hasReview;
|
|
363
371
|
});
|
|
364
372
|
}
|
|
365
373
|
|
|
@@ -1252,6 +1260,14 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1252
1260
|
receipt: AskRemoteReceipt;
|
|
1253
1261
|
settlement?: AskSettlement;
|
|
1254
1262
|
};
|
|
1263
|
+
const ignoreRemoteAnswerFailure = (error: unknown): Promise<never> => {
|
|
1264
|
+
if (!(error instanceof Error && error.name === "AbortError")) {
|
|
1265
|
+
logger.warn("Ask remote answer source failed", {
|
|
1266
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
return new Promise<never>(() => {});
|
|
1270
|
+
};
|
|
1255
1271
|
const settleActiveRemote = async (settlement: AskSettlement): Promise<void> => {
|
|
1256
1272
|
const receipt = activeRemoteReceipt;
|
|
1257
1273
|
activeRemoteReceipt = undefined;
|
|
@@ -1265,9 +1281,11 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1265
1281
|
// attended TUI asks would route to emitGate() and hang forever waiting on
|
|
1266
1282
|
// a remote responder.
|
|
1267
1283
|
const hasInteractiveUi = context?.hasUI === true && !!context.ui;
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1270
|
-
|
|
1284
|
+
const initialAnswerSource = this.session.getAskAnswerSource?.();
|
|
1285
|
+
const canUseWorkflowGate =
|
|
1286
|
+
!hasInteractiveUi && !initialAnswerSource && gateEmitter?.supportsRemoteGateAnswers() === true;
|
|
1287
|
+
// Headless fallback: an SDK answer source or workflow gate is the non-TUI answer path.
|
|
1288
|
+
if (!hasInteractiveUi && !initialAnswerSource && !canUseWorkflowGate) {
|
|
1271
1289
|
context?.abort();
|
|
1272
1290
|
throw new ToolAbortError("Ask tool requires interactive mode");
|
|
1273
1291
|
}
|
|
@@ -1275,9 +1293,11 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1275
1293
|
const extensionUi = context?.ui;
|
|
1276
1294
|
const ui: UIContext = {
|
|
1277
1295
|
select: (prompt, options, dialogOptions) => {
|
|
1278
|
-
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
1279
1296
|
const source = this.session.getAskAnswerSource?.();
|
|
1280
|
-
if (!source)
|
|
1297
|
+
if (!source) {
|
|
1298
|
+
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
1299
|
+
return extensionUi.select(prompt, options, dialogOptions);
|
|
1300
|
+
}
|
|
1281
1301
|
// Race the local UI against a remote answer (e.g. an SDK reply) so asks
|
|
1282
1302
|
// can be answered without local UI interaction. The first valid answer
|
|
1283
1303
|
// wins; the loser is aborted so neither side is left hanging:
|
|
@@ -1304,93 +1324,107 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1304
1324
|
remoteController.signal,
|
|
1305
1325
|
)
|
|
1306
1326
|
: source.awaitAnswer(prompt, options, remoteController.signal)
|
|
1307
|
-
)
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
.then(answer => {
|
|
1365
|
-
if (generation === remoteGeneration) remoteGeneration++;
|
|
1366
|
-
remoteController.abort();
|
|
1367
|
-
return { winner: "local" as const, value: answer };
|
|
1327
|
+
)
|
|
1328
|
+
.then((answer): RemoteRaceResult | Promise<RemoteRaceResult> => {
|
|
1329
|
+
if (answer === undefined) {
|
|
1330
|
+
if (!extensionUi) throw new ToolAbortError("Ask was cancelled by the remote client");
|
|
1331
|
+
return new Promise<never>(() => {});
|
|
1332
|
+
}
|
|
1333
|
+
const receipt = typeof answer === "string" ? legacyAskReceipt(answer) : answer;
|
|
1334
|
+
if (generation !== remoteGeneration) {
|
|
1335
|
+
return receipt
|
|
1336
|
+
.settle({ kind: "resolve_without_commit", reason: "aborted" })
|
|
1337
|
+
.then(() => new Promise<never>(() => {}));
|
|
1338
|
+
}
|
|
1339
|
+
const remoteValue = receipt.interaction.kind === "value" ? receipt.interaction.value : undefined;
|
|
1340
|
+
const value = remoteValue ?? REMOTE_NAVIGATION_FORWARD;
|
|
1341
|
+
const selectedValue =
|
|
1342
|
+
remoteValue === undefined
|
|
1343
|
+
? value
|
|
1344
|
+
: (options.find(
|
|
1345
|
+
option =>
|
|
1346
|
+
option === remoteValue ||
|
|
1347
|
+
option === `${theme.checkbox.checked} ${remoteValue}` ||
|
|
1348
|
+
option === `${theme.checkbox.unchecked} ${remoteValue}`,
|
|
1349
|
+
) ?? value);
|
|
1350
|
+
const normalizedRemoteValue = remoteValue?.startsWith(`${theme.checkbox.checked} `)
|
|
1351
|
+
? remoteValue.slice(`${theme.checkbox.checked} `.length)
|
|
1352
|
+
: remoteValue?.startsWith(`${theme.checkbox.unchecked} `)
|
|
1353
|
+
? remoteValue.slice(`${theme.checkbox.unchecked} `.length)
|
|
1354
|
+
: remoteValue;
|
|
1355
|
+
const semanticRemoteValue = normalizedRemoteValue?.replace(/^\s*\d+[.)]\s+/, "");
|
|
1356
|
+
const transitionReason =
|
|
1357
|
+
semanticRemoteValue === OTHER_OPTION
|
|
1358
|
+
? "other_transition"
|
|
1359
|
+
: semanticRemoteValue === ASK_CLARIFICATION_OPTION
|
|
1360
|
+
? "clarification_transition"
|
|
1361
|
+
: undefined;
|
|
1362
|
+
if (transitionReason) {
|
|
1363
|
+
return {
|
|
1364
|
+
winner: "remote" as const,
|
|
1365
|
+
value: selectedValue,
|
|
1366
|
+
receipt,
|
|
1367
|
+
settlement: { kind: "resolve_without_commit", reason: transitionReason },
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
if (
|
|
1371
|
+
remoteValue !== undefined &&
|
|
1372
|
+
activeRemoteRequest?.interaction === "selector" &&
|
|
1373
|
+
activeRemoteRequest.controls.length > 0 &&
|
|
1374
|
+
activeRemoteRequest.options.includes(remoteValue)
|
|
1375
|
+
) {
|
|
1376
|
+
return {
|
|
1377
|
+
winner: "remote" as const,
|
|
1378
|
+
value: selectedValue,
|
|
1379
|
+
receipt,
|
|
1380
|
+
settlement: { kind: "resolve_without_commit", reason: "toggle" },
|
|
1381
|
+
};
|
|
1382
|
+
}
|
|
1383
|
+
return { winner: "remote" as const, value: selectedValue, receipt };
|
|
1368
1384
|
})
|
|
1369
1385
|
.catch(error => {
|
|
1370
|
-
if (
|
|
1371
|
-
|
|
1372
|
-
throw error;
|
|
1386
|
+
if (!extensionUi) throw error;
|
|
1387
|
+
return ignoreRemoteAnswerFailure(error);
|
|
1373
1388
|
});
|
|
1389
|
+
|
|
1390
|
+
const local = extensionUi
|
|
1391
|
+
? extensionUi
|
|
1392
|
+
.select(prompt, options, { ...dialogOptions, signal: localController.signal })
|
|
1393
|
+
.then(answer => {
|
|
1394
|
+
if (generation === remoteGeneration) remoteGeneration++;
|
|
1395
|
+
remoteController.abort();
|
|
1396
|
+
return { winner: "local" as const, value: answer };
|
|
1397
|
+
})
|
|
1398
|
+
.catch(error => {
|
|
1399
|
+
if (generation === remoteGeneration) remoteGeneration++;
|
|
1400
|
+
remoteController.abort();
|
|
1401
|
+
throw error;
|
|
1402
|
+
})
|
|
1403
|
+
: new Promise<never>(() => {});
|
|
1374
1404
|
// The losing selector may reject when aborted after the race already settled;
|
|
1375
1405
|
// swallow that so it is not an unhandled rejection (the race result is unaffected).
|
|
1376
1406
|
void local.catch(() => undefined);
|
|
1377
|
-
return Promise.race([local, remote])
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1407
|
+
return Promise.race([local, remote])
|
|
1408
|
+
.then(async result => {
|
|
1409
|
+
if (result.winner === "remote") {
|
|
1410
|
+
localController.abort();
|
|
1411
|
+
if (result.settlement) await result.receipt.settle(result.settlement);
|
|
1412
|
+
else activeRemoteReceipt = result.receipt;
|
|
1413
|
+
} else {
|
|
1414
|
+
void remote.then(remoteResult =>
|
|
1415
|
+
remoteResult.receipt.settle({ kind: "resolve_without_commit", reason: "aborted" }),
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1418
|
+
return result.value;
|
|
1419
|
+
})
|
|
1420
|
+
.finally(() => toolSignal?.removeEventListener("abort", abortRace));
|
|
1389
1421
|
},
|
|
1390
1422
|
editor: (title, prefill, dialogOptions, editorOptions) => {
|
|
1391
|
-
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
1392
1423
|
const source = this.session.getAskAnswerSource?.();
|
|
1393
|
-
if (!source)
|
|
1424
|
+
if (!source) {
|
|
1425
|
+
if (!extensionUi) throw new ToolAbortError("Ask tool requires interactive mode");
|
|
1426
|
+
return extensionUi.editor(title, prefill, dialogOptions, editorOptions);
|
|
1427
|
+
}
|
|
1394
1428
|
// Race the local editor against a remote free-text answer so "Other / type
|
|
1395
1429
|
// your own" custom input can be provided remotely (e.g. a typed Telegram
|
|
1396
1430
|
// reply) instead of blocking on the local-only editor. Mirrors `select`.
|
|
@@ -1419,42 +1453,59 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1419
1453
|
remoteController.signal,
|
|
1420
1454
|
)
|
|
1421
1455
|
: source.awaitAnswer(title, [], remoteController.signal)
|
|
1422
|
-
)
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
if (generation === remoteGeneration) remoteGeneration++;
|
|
1438
|
-
remoteController.abort();
|
|
1439
|
-
return { winner: "local" as const, value: answer };
|
|
1456
|
+
)
|
|
1457
|
+
.then((answer): RemoteRaceResult | Promise<RemoteRaceResult> => {
|
|
1458
|
+
if (answer === undefined) {
|
|
1459
|
+
if (!extensionUi) throw new ToolAbortError("Ask was cancelled by the remote client");
|
|
1460
|
+
return new Promise<never>(() => {});
|
|
1461
|
+
}
|
|
1462
|
+
const receipt = typeof answer === "string" ? legacyAskReceipt(answer) : answer;
|
|
1463
|
+
if (generation !== remoteGeneration) {
|
|
1464
|
+
return receipt
|
|
1465
|
+
.settle({ kind: "resolve_without_commit", reason: "aborted" })
|
|
1466
|
+
.then(() => new Promise<never>(() => {}));
|
|
1467
|
+
}
|
|
1468
|
+
const value =
|
|
1469
|
+
receipt.interaction.kind === "control" ? REMOTE_NAVIGATION_FORWARD : receipt.interaction.value;
|
|
1470
|
+
return { winner: "remote" as const, value, receipt };
|
|
1440
1471
|
})
|
|
1441
1472
|
.catch(error => {
|
|
1442
|
-
if (
|
|
1443
|
-
|
|
1444
|
-
throw error;
|
|
1473
|
+
if (!extensionUi) throw error;
|
|
1474
|
+
return ignoreRemoteAnswerFailure(error);
|
|
1445
1475
|
});
|
|
1476
|
+
const local = extensionUi
|
|
1477
|
+
? extensionUi
|
|
1478
|
+
.editor(
|
|
1479
|
+
title,
|
|
1480
|
+
prefill,
|
|
1481
|
+
{ ...(dialogOptions ?? {}), signal: localController.signal },
|
|
1482
|
+
editorOptions,
|
|
1483
|
+
)
|
|
1484
|
+
.then(answer => {
|
|
1485
|
+
if (generation === remoteGeneration) remoteGeneration++;
|
|
1486
|
+
remoteController.abort();
|
|
1487
|
+
return { winner: "local" as const, value: answer };
|
|
1488
|
+
})
|
|
1489
|
+
.catch(error => {
|
|
1490
|
+
if (generation === remoteGeneration) remoteGeneration++;
|
|
1491
|
+
remoteController.abort();
|
|
1492
|
+
throw error;
|
|
1493
|
+
})
|
|
1494
|
+
: new Promise<never>(() => {});
|
|
1446
1495
|
void local.catch(() => undefined);
|
|
1447
|
-
return Promise.race([local, remote])
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1496
|
+
return Promise.race([local, remote])
|
|
1497
|
+
.then(result => {
|
|
1498
|
+
if (result.winner === "remote") {
|
|
1499
|
+
activeRemoteReceipt = result.receipt;
|
|
1500
|
+
localController.abort();
|
|
1501
|
+
} else {
|
|
1502
|
+
void remote.then(remoteResult =>
|
|
1503
|
+
remoteResult.receipt.settle({ kind: "resolve_without_commit", reason: "aborted" }),
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
return result.value;
|
|
1507
|
+
})
|
|
1508
|
+
.finally(() => toolSignal?.removeEventListener("abort", abortRace));
|
|
1458
1509
|
},
|
|
1459
1510
|
};
|
|
1460
1511
|
|
package/src/tools/ast-edit.ts
CHANGED
|
@@ -205,6 +205,7 @@ export class AstEditTool implements AgentTool<typeof astEditSchema, AstEditToolD
|
|
|
205
205
|
rawPaths: params.paths,
|
|
206
206
|
cwd: this.session.cwd,
|
|
207
207
|
getArtifactsDir: this.session.getArtifactsDir,
|
|
208
|
+
getAuthorizedArtifactsDirs: this.session.getAuthorizedArtifactsDirs,
|
|
208
209
|
internalUrlAction: "rewrite",
|
|
209
210
|
});
|
|
210
211
|
const { searchPath: resolvedSearchPath, scopePath, isDirectory, multiTargets, globFilter } = scope;
|
package/src/tools/ast-grep.ts
CHANGED
|
@@ -152,6 +152,7 @@ export class AstGrepTool implements AgentTool<typeof astGrepSchema, AstGrepToolD
|
|
|
152
152
|
rawPaths: params.paths,
|
|
153
153
|
cwd: this.session.cwd,
|
|
154
154
|
getArtifactsDir: this.session.getArtifactsDir,
|
|
155
|
+
getAuthorizedArtifactsDirs: this.session.getAuthorizedArtifactsDirs,
|
|
155
156
|
internalUrlAction: "search",
|
|
156
157
|
});
|
|
157
158
|
const { searchPath: resolvedSearchPath, scopePath, isDirectory, multiTargets, globFilter } = scope;
|
|
@@ -15,9 +15,9 @@ import type { Terminal as XtermTerminalType } from "@xterm/headless";
|
|
|
15
15
|
import { Settings } from "../config/settings";
|
|
16
16
|
import { NON_INTERACTIVE_ENV } from "../exec/non-interactive-env";
|
|
17
17
|
import type { Theme } from "../modes/theme/theme";
|
|
18
|
-
import { OutputSink, type OutputSummary } from "../session/streaming-output";
|
|
18
|
+
import { OutputSink, type OutputSummary, type TerminalArtifactPublisher } from "../session/streaming-output";
|
|
19
19
|
import { sanitizeWithOptionalSixelPassthrough } from "../utils/sixel";
|
|
20
|
-
import {
|
|
20
|
+
import { resolveBashOutputSinkHeadBytes, resolveBashOutputSinkTailBytes, resolveOutputMaxColumns } from "./output-meta";
|
|
21
21
|
import { formatStatusIcon, replaceTabs } from "./render-utils";
|
|
22
22
|
|
|
23
23
|
export interface BashInteractiveResult extends OutputSummary {
|
|
@@ -293,6 +293,9 @@ export async function runInteractiveBashPty(
|
|
|
293
293
|
env?: Record<string, string>;
|
|
294
294
|
artifactPath?: string;
|
|
295
295
|
artifactId?: string;
|
|
296
|
+
artifactPublisher?: TerminalArtifactPublisher;
|
|
297
|
+
spillThreshold?: number;
|
|
298
|
+
headBytes?: number;
|
|
296
299
|
},
|
|
297
300
|
): Promise<BashInteractiveResult> {
|
|
298
301
|
const settings = await Settings.init();
|
|
@@ -300,7 +303,9 @@ export async function runInteractiveBashPty(
|
|
|
300
303
|
const sink = new OutputSink({
|
|
301
304
|
artifactPath: options.artifactPath,
|
|
302
305
|
artifactId: options.artifactId,
|
|
303
|
-
|
|
306
|
+
artifactPublisher: options.artifactPublisher,
|
|
307
|
+
spillThreshold: options.spillThreshold ?? resolveBashOutputSinkTailBytes(settings),
|
|
308
|
+
headBytes: options.headBytes ?? resolveBashOutputSinkHeadBytes(settings),
|
|
304
309
|
maxColumns: resolveOutputMaxColumns(settings),
|
|
305
310
|
});
|
|
306
311
|
const { default: xterm } = await import("@xterm/headless");
|