@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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentMessage } from "@gajae-code/agent-core";
|
|
2
2
|
import type { AssistantMessage, ImageContent, Message } from "@gajae-code/ai";
|
|
3
|
-
import { type Component, Spacer, Text, TruncatedText, type TUI, truncateToWidth } from "@gajae-code/tui";
|
|
3
|
+
import { type Component, Loader, Spacer, Text, TruncatedText, type TUI, truncateToWidth } from "@gajae-code/tui";
|
|
4
4
|
import { settings } from "../../config/settings";
|
|
5
5
|
import { resolveSubskillActivationForSkillInvocation } from "../../extensibility/gjc-plugins";
|
|
6
6
|
import { buildSkillPromptMessage, parseSkillInvocations } from "../../extensibility/skills";
|
|
@@ -85,6 +85,99 @@ export function prepareTranscriptRebuild(ui: TUI, policy: TranscriptRebuildPolic
|
|
|
85
85
|
if (policy === "replace-identity") ui.resetViewportAnchorIntent();
|
|
86
86
|
else ui.prepareViewportAnchorForTranscriptRebuild();
|
|
87
87
|
}
|
|
88
|
+
|
|
89
|
+
export const RESUME_PROGRESS_COMMIT_TIMEOUT_MS = 250;
|
|
90
|
+
|
|
91
|
+
export interface ResumeProgressLease {
|
|
92
|
+
readonly committed: Promise<boolean>;
|
|
93
|
+
clear(): void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Mount a resume loader on the live status rail and wait for its render generation
|
|
98
|
+
* to commit before session I/O begins. The commit is advisory: a stopped or
|
|
99
|
+
* unavailable terminal resolves false and callers continue without blocking.
|
|
100
|
+
*
|
|
101
|
+
* Fail open (no-op lease, committed=false) when the status rail or UI lacks the
|
|
102
|
+
* child-mutation/render-commit surface required to mount progress. Headless and
|
|
103
|
+
* minimal controller contexts keep resume/migration semantics; full interactive
|
|
104
|
+
* TUI containers retain progress-before-switch.
|
|
105
|
+
*/
|
|
106
|
+
export function acquireResumeProgressLease(
|
|
107
|
+
ctx: Pick<InteractiveModeContext, "ui" | "statusContainer">,
|
|
108
|
+
): ResumeProgressLease {
|
|
109
|
+
if (!canMountResumeProgressLease(ctx)) {
|
|
110
|
+
return {
|
|
111
|
+
committed: Promise.resolve(false),
|
|
112
|
+
clear(): void {},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const statusContainer = ctx.statusContainer as ResumeProgressStatusSurface;
|
|
117
|
+
const ui = ctx.ui as ResumeProgressUiSurface;
|
|
118
|
+
const loader = new Loader(
|
|
119
|
+
ui,
|
|
120
|
+
spinner => theme?.fg?.("accent", spinner) ?? spinner,
|
|
121
|
+
message => theme?.fg?.("muted", message) ?? message,
|
|
122
|
+
"Resuming session…",
|
|
123
|
+
);
|
|
124
|
+
statusContainer.addChild(loader);
|
|
125
|
+
const generation = ui.requestRenderWithGeneration(false, "resume-progress");
|
|
126
|
+
let active = true;
|
|
127
|
+
const committed = ui.waitForRenderCommit(generation, RESUME_PROGRESS_COMMIT_TIMEOUT_MS).catch(() => false);
|
|
128
|
+
return {
|
|
129
|
+
committed,
|
|
130
|
+
clear(): void {
|
|
131
|
+
if (!active) return;
|
|
132
|
+
active = false;
|
|
133
|
+
if (statusContainer.children.includes(loader)) statusContainer.removeChild(loader);
|
|
134
|
+
else loader.stop();
|
|
135
|
+
ui.requestRender(false, "resume-progress-clear");
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
type ResumeProgressStatusSurface = {
|
|
141
|
+
addChild: (child: Component) => void;
|
|
142
|
+
removeChild: (child: Component) => void;
|
|
143
|
+
children: Component[];
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
type ResumeProgressUiSurface = InteractiveModeContext["ui"] & {
|
|
147
|
+
requestRenderWithGeneration: (force?: boolean, source?: string) => number;
|
|
148
|
+
waitForRenderCommit: (generation: number, timeoutMs?: number) => Promise<boolean>;
|
|
149
|
+
requestRender: (force?: boolean, source?: string) => void;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
function canMountResumeProgressLease(ctx: Pick<InteractiveModeContext, "ui" | "statusContainer">): boolean {
|
|
153
|
+
const status = ctx.statusContainer as
|
|
154
|
+
| Partial<{
|
|
155
|
+
addChild: unknown;
|
|
156
|
+
removeChild: unknown;
|
|
157
|
+
children: unknown;
|
|
158
|
+
}>
|
|
159
|
+
| null
|
|
160
|
+
| undefined;
|
|
161
|
+
const ui = ctx.ui as
|
|
162
|
+
| Partial<{
|
|
163
|
+
requestRenderWithGeneration: unknown;
|
|
164
|
+
waitForRenderCommit: unknown;
|
|
165
|
+
requestRender: unknown;
|
|
166
|
+
}>
|
|
167
|
+
| null
|
|
168
|
+
| undefined;
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
!!status &&
|
|
172
|
+
typeof status.addChild === "function" &&
|
|
173
|
+
typeof status.removeChild === "function" &&
|
|
174
|
+
Array.isArray(status.children) &&
|
|
175
|
+
!!ui &&
|
|
176
|
+
typeof ui.requestRenderWithGeneration === "function" &&
|
|
177
|
+
typeof ui.waitForRenderCommit === "function" &&
|
|
178
|
+
typeof ui.requestRender === "function"
|
|
179
|
+
);
|
|
180
|
+
}
|
|
88
181
|
type TextBlock = { type: "text"; text: string };
|
|
89
182
|
interface RenderInitialMessagesOptions {
|
|
90
183
|
preserveExistingChat?: boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Persistence (ralplan runs only):
|
|
2
|
-
- Only when the assignment references a ralplan stage or `stage_n`, persist the
|
|
2
|
+
- Only when the assignment references a ralplan stage or `stage_n`, it must also provide the ralplan owner `session_id` and `run_id`. If either identifier is missing, do not persist; return a compact error asking the caller to supply both.
|
|
3
|
+
- Persist the full artifact through:
|
|
3
4
|
|
|
4
|
-
gjc ralplan --write --stage {{stage}} --stage_n <N> --artifact-env GJC_RALPLAN_ARTIFACT --json
|
|
5
|
+
gjc ralplan --write --session-id <owner-session-id> --run-id <run-id> --stage {{stage}} --stage_n <N> --artifact-env GJC_RALPLAN_ARTIFACT --json
|
|
5
6
|
|
|
6
|
-
Use the assignment-provided `stage_n`;
|
|
7
|
+
Use the assignment-provided owner `session_id`, `run_id`, and `stage_n`; never substitute the role subagent's own session id. On a duplicate-write error retry with the incremented N. Return the write receipt (`session_id`, `run_id`, `path`, `sha256`, `stage`, `stage_n`) and the role's compact verdict only. Otherwise, do not call `gjc ralplan --write`; return the full result in `yield.result.data`.
|
|
@@ -37,11 +37,19 @@ You may receive a forked parent-conversation snapshot as background. Your read-o
|
|
|
37
37
|
{{restrictedBash}}
|
|
38
38
|
- Never approve code or plans you have not grounded in inspected files.
|
|
39
39
|
- Never give generic advice detached from this codebase.
|
|
40
|
-
- Never approve CRITICAL or HIGH severity issues.
|
|
40
|
+
- Never approve carryover CRITICAL or HIGH severity issues (raised in a prior pass and still unresolved). A fresh CRITICAL/HIGH minted from pass 2 on previously-approved ground blocks only with an explicit why-not-visible-earlier justification (rule 2); without that justification, record it as a non-blocking caveat with its severity noted. On pass 1 every CRITICAL/HIGH blocks.
|
|
41
41
|
- Do not skip spec compliance to jump to style nitpicks.
|
|
42
42
|
- Be constructive: explain why an issue matters and how to fix it or strengthen the design.
|
|
43
43
|
</constraints>
|
|
44
44
|
|
|
45
|
+
<re_review_ratchet>
|
|
46
|
+
- Rule 1 (delta-only): from pass 2, review only the delta against the prior pass plus the resolution of previously raised findings; do not re-litigate previously-approved ground. The prior pass is identified by the re-review context bundle: prior reviewed-plan path, prior same-lane review path, and the explicit run-level pass number supplied in the assignment.
|
|
47
|
+
- Rule 2 (novelty justification): a new blocker on previously-reviewed ground requires an explicit "why this was not visible in the prior pass" justification (e.g. revealed by a fix, new file evidence); without it, demote to a non-blocking caveat.
|
|
48
|
+
- Rule 3 (verdict monotonicity): once all blockers from the prior pass are resolved, neither Architectural Status (`CLEAR`/`WATCH`/`BLOCK`) nor Code Review Recommendation (`APPROVE`/`COMMENT`/`REQUEST CHANGES`) may worsen absent a rule-2-justified new blocker.
|
|
49
|
+
- Rule 4 (severity discipline): carryover CRITICAL or HIGH severity issues (raised in a prior pass and still unresolved) remain blocking regardless of pass number. A fresh CRITICAL/HIGH minted from pass 2 on previously-approved ground blocks only with an explicit why-not-visible-earlier justification (rule 2); without that justification, record it as a non-blocking caveat with its severity noted. On pass 1 every CRITICAL/HIGH blocks.
|
|
50
|
+
- Rule 5 (counter-review awareness): From pass 2 your output is counter-reviewed by Critic for over-engineering and unnecessary scope expansion; unjustified scope inflation is flagged as a review defect and does not force revision passes. On pass 2+, do not broaden scope, add options, or demand synthesis beyond what resolves prior findings; constructive synthesis (Stage 3) stays full-strength on pass 1 only.
|
|
51
|
+
</re_review_ratchet>
|
|
52
|
+
|
|
45
53
|
<review_stages>
|
|
46
54
|
1. Understand the request, spec, plan, or diff.
|
|
47
55
|
2. Gather file-backed evidence.
|
|
@@ -32,6 +32,15 @@ Review plan clarity, completeness, verification, big-picture fit, referenced fil
|
|
|
32
32
|
- For consensus planning, reject shallow alternatives, driver contradictions, vague risks, weak verification, missing acceptance criteria, or under-specified areas needing expansion before execution.
|
|
33
33
|
</constraints>
|
|
34
34
|
|
|
35
|
+
<re_review_ratchet>
|
|
36
|
+
- Rule 1 (delta-only): from pass 2, review only the delta against the prior pass plus the resolution of previously raised findings; do not re-litigate previously-approved ground. The prior pass is identified by the re-review context bundle (WI-3): prior reviewed-plan path, prior same-lane review path, and the explicit run-level pass number supplied in the assignment.
|
|
37
|
+
- Rule 2 (novelty justification): a new blocker on previously-reviewed ground requires an explicit "why this was not visible in the prior pass" justification (e.g. revealed by a fix, new file evidence); without it, demote to a non-blocking caveat.
|
|
38
|
+
- Rule 3 (verdict monotonicity): once all blockers from the prior pass are resolved, the verdict must not worsen (e.g. ITERATE -> REJECT) absent a rule-2-justified new blocker.
|
|
39
|
+
- Rule 4 (severity discipline): carryover blockers (raised in a prior pass, still unresolved) remain blocking regardless of pass number. A fresh high-severity concern minted from pass 2 on previously-approved ground follows rule 2: it blocks only with the why-not-visible-earlier justification, else it is recorded as a non-blocking caveat with severity noted.
|
|
40
|
+
- Rule 5 (counter-review duty): from pass 2, Critic also reviews the Architect output (routed via the context bundle) for over-engineering and unnecessary scope expansion; flag inflation as a review defect and do NOT convert unjustified Architect demands into ITERATE — inflating demands must not force revision passes.
|
|
41
|
+
- Enrichment lane ("spec too thin — expand") preserved verbatim but justification-gated from pass 2: expansion requests on already-reviewed ground need the rule-2 justification.
|
|
42
|
+
</re_review_ratchet>
|
|
43
|
+
|
|
35
44
|
<execution_loop>
|
|
36
45
|
1. Read the plan and referenced artifacts.
|
|
37
46
|
2. Extract and verify file references.
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
Before substantive work, create a phased todo.
|
|
3
3
|
|
|
4
4
|
You MUST call `todo_write` first in this turn.
|
|
5
|
-
|
|
5
|
+
Your call MUST use the top-level `ops` array with exactly one `init` operation.
|
|
6
|
+
The `init` operation MUST contain `list`, whose entries each have a unique `phase` and an `items` array of task strings.
|
|
7
|
+
Use this canonical shape:
|
|
8
|
+
```json
|
|
9
|
+
{"ops":[{"op":"init","list":[{"phase":"Investigation","items":["Locate relevant source and existing tests","Reproduce failure with focused contract test"]},{"phase":"Implementation","items":["Apply root cause fix across callsites"]},{"phase":"Verification","items":["Run focused tests and static checks"]}]}]}
|
|
10
|
+
```
|
|
6
11
|
You MUST cover the entire request from investigation through implementation and verification — not just the next immediate step.
|
|
7
|
-
Task
|
|
8
|
-
|
|
9
|
-
You MUST keep exactly one task `in_progress` and all later tasks `pending`.
|
|
12
|
+
Task strings MUST be specific, unique labels of 5-10 words. A future turn MUST execute them without re-planning.
|
|
13
|
+
The tool automatically promotes the first task after initialization. Add extra context later with a separate `note` operation only when needed.
|
|
10
14
|
|
|
11
15
|
After `todo_write` succeeds, continue the request in the same turn.
|
|
12
16
|
Do not call `todo_write` again unless task state materially changed.
|
|
@@ -22,13 +22,13 @@ Optimize for correctness first, maintainability second, and brevity third. Prefe
|
|
|
22
22
|
- Clear, low-risk implementation requests use direct tools and focused verification; do not invoke workflows or role agents for ceremony. Small verification needs do not turn a clear request into a planning workflow.
|
|
23
23
|
- Ambiguous implementation asks with a missing target, scope, acceptance criteria, or safety boundary require clarification or the appropriate planning workflow before mutation.
|
|
24
24
|
- Informational questions are answer-only/read-only unless the user explicitly requests a change, command, or execution.
|
|
25
|
-
- Vague requirements use `/skill:deep-interview`: a requirements-only workflow that must not mutate product code. Its spec hands off as deep-interview → ralplan consensus →
|
|
26
|
-
- Clear work with non-trivial architecture or sequencing risk uses `/skill:ralplan --deliberate
|
|
27
|
-
- Deep-interview state is runtime-owned: diagnose with `gjc deep-interview sanity-check`, inspect only the affected bounded selector, and repair through typed operations using CLI-generated/edited drafts (`draft create|edit|show|check|rebase|discard`) consumed with `--draft-id`. Inline JSON request flags are compatibility-only; normal flow must never reconstruct a payload or full envelope.
|
|
25
|
+
- Vague requirements use `/skill:deep-interview`: a requirements-only workflow that must not mutate product code. Its spec hands off as deep-interview → ralplan consensus → final receipt → approval or valid non-off runtime admission → separately authorized execution.
|
|
26
|
+
- Clear work with non-trivial architecture or sequencing risk uses `/skill:ralplan --deliberate`; reconciliation must persist its final receipt before choosing approval or an admitted handoff. A valid non-off final runtime receipt enters the existing handoff chain; otherwise it stops pending approval.
|
|
28
27
|
- Use `/skill:ultragoal` for durable goal ledgers and `/skill:team` for approved coordinated persistent work.
|
|
29
28
|
- Delegate large implementation slices to `executor`; use `planner`, `architect`, or `critic` for bounded planning and review.
|
|
29
|
+
- An explicit user request to use a worktree (for example, "use worktree") overrides direct editing: delegate implementation through `task` with `isolated: true`. This is the in-session counterpart of launching `gjc --worktree`; if task isolation is unavailable, report that conflict instead of editing in the parent session.
|
|
30
30
|
- Active skills are authoritative: never ignore an invoked skill; read the full skill text and follow it exactly.
|
|
31
|
-
- Before explicit execution approval, planning and interview workflows NEVER edit product source, run mutating shell commands, commit, push, open PRs, or delegate implementation.
|
|
31
|
+
- Before explicit execution approval or a valid non-off ralplan final runtime receipt, planning and interview workflows NEVER edit product source, run mutating shell commands, commit, push, open PRs, or delegate implementation.
|
|
32
32
|
</routing>
|
|
33
33
|
</gjc-runtime>
|
|
34
34
|
{{/unless}}
|
|
@@ -83,8 +83,14 @@ Use tools whenever they materially improve correctness, completeness, or groundi
|
|
|
83
83
|
|
|
84
84
|
{{#if toolDiscoveryActive}}
|
|
85
85
|
<tool-discovery>
|
|
86
|
-
Use `{{toolRefs.search_tool_bm25}}` to activate hidden tools when a purpose-built capability would improve the task; then call the activated tool. Essential tools stay loaded up front.
|
|
86
|
+
Use `{{toolRefs.search_tool_bm25}}` to activate hidden tools when a purpose-built capability would improve the task; then call the activated tool. Activation makes a tool available, but does not perform its action. Essential tools stay loaded up front.
|
|
87
87
|
Discoverable capabilities include browser automation, scheduling, debugging, and external integrations.
|
|
88
|
+
{{#has tools "task"}}
|
|
89
|
+
For requested subagents, delegation, or independent parallel lanes, call `{{toolRefs.task}}` before saying agents are running.
|
|
90
|
+
{{else}}
|
|
91
|
+
For requested subagents, delegation, or independent parallel lanes, search for `subagent delegation` before saying agents are running.
|
|
92
|
+
{{/has}}
|
|
93
|
+
Do not claim a web search, browser action, integration, or subagent ran without that tool's result.
|
|
88
94
|
</tool-discovery>
|
|
89
95
|
{{/if}}
|
|
90
96
|
|
|
@@ -44,13 +44,13 @@ Use it only for sanctioned GJC workflow CLI persistence or state read/write/cont
|
|
|
44
44
|
{{else}}
|
|
45
45
|
- Use bash only for terminal operations that dedicated tools do not cover.
|
|
46
46
|
{{/when}}
|
|
47
|
-
- Never pipe through `| head -n N` or `| tail -n N` — output is already truncated
|
|
47
|
+
- Never pipe through `| head -n N` or `| tail -n N` — output is already truncated. Recover omitted output only when the result includes an `artifact://<id>` footer or metadata reference; truncation without a reference leaves the visible output incomplete with no recoverable artifact.
|
|
48
48
|
- Never redirect with `2>&1` or `2>/dev/null` — stdout and stderr are already merged.
|
|
49
49
|
</critical>
|
|
50
50
|
|
|
51
51
|
<output>
|
|
52
52
|
- Returns output and exit code.
|
|
53
|
-
- Truncated output is
|
|
53
|
+
- Truncated output is recoverable only when the result includes an `artifact://<id>` footer or metadata reference; truncation evidence without such a reference means the visible output is incomplete and no artifact is recoverable.
|
|
54
54
|
- Exit codes shown on non-zero exit
|
|
55
55
|
</output>
|
|
56
56
|
|
|
@@ -64,6 +64,6 @@ Use it only for sanctioned GJC workflow CLI persistence or state read/write/cont
|
|
|
64
64
|
|
|
65
65
|
# Output minimizer
|
|
66
66
|
|
|
67
|
-
- Bash stdout/stderr may be rewritten before you see it: long output
|
|
68
|
-
- When the minimizer changes
|
|
69
|
-
-
|
|
67
|
+
- Bash stdout/stderr may be rewritten before you see it: long output keeps only the last 1 KiB by default to reduce noise and input-token use. Explicit `tools.artifactTailBytes` / `tools.artifactHeadBytes` settings can set the tail budget or retain both ends. Prefer focused commands and dedicated `search`/`find` tools over producing broad output. Test/lint runners (e.g. `bun test`, `cargo test`, ESLint) are also passed through heuristic filters that drop noise and keep failures.
|
|
68
|
+
- When the local minimizer changes visible text, successful artifact storage appends a footer containing an `artifact://<id>` reference. Complete artifacts are labeled as full output; hard-capped artifacts report omitted bytes instead. If artifact allocation/storage is unavailable before a writer/save operation is attempted, truncation may have no reference or diagnostic. If an artifact writer/save operation is attempted and fails, a bounded diagnostic is emitted without inventing an artifact URI.
|
|
69
|
+
- ACP/client-terminal output can arrive already truncated from the beginning. Treat any truncation notice or metadata as evidence that the visible tail is incomplete. Recover omitted output only when an `artifact://` footer or metadata reference is present; truncation evidence without a reference means the visible output is incomplete and no artifact is recoverable. Output with neither truncation evidence nor an artifact reference is the complete emitted output.
|
|
@@ -9,12 +9,13 @@ Read files, directories, archives, SQLite databases, images, documents, internal
|
|
|
9
9
|
## Parameters
|
|
10
10
|
|
|
11
11
|
- `path` — required. Local path, internal URI (`agent://`, `artifact://`, `rule://`, `local://`), or URL. Append `:<sel>` for line ranges, raw mode, or special modes (e.g. `src/foo.ts:50-200`, `src/foo.ts:raw`, `db.sqlite:users:42`).
|
|
12
|
+
- `truncation` — optional `head` | `last` | `both`; selects which end of an over-budget result to retain. Configured default: {{TRUNCATION_DEFAULT}} (factory default: `last`); non-file routes such as URLs, directories and converted documents default to `head`. A line-range selector still bounds the selection — this only picks which end of that selection survives the byte/line cap. SQLite row queries page via their own `limit`/`offset` and ignore it.
|
|
12
13
|
|
|
13
|
-
## Selectors
|
|
14
14
|
|
|
15
|
+
## Selectors
|
|
15
16
|
Append `:<sel>` to `path`. The bare path falls back to the default mode.
|
|
16
17
|
|
|
17
|
-
- _(none)_ — parseable code → structural summary (signatures kept, bodies elided);
|
|
18
|
+
- _(none)_ — parseable code → structural summary (signatures kept, bodies elided); a plain text file → a bounded receipt of about {{RECEIPT_LINES}} lines or {{RECEIPT_KIB}} KiB, whichever is smaller; the configured truncation direction is {{TRUNCATION_DEFAULT}} (factory default: last). Line+hash anchors keep their real file line numbers and a footer names the omitted range. Archive members use the larger {{DEFAULT_MAX_LINES}}-line / 50 KiB budget. Converted documents, notebooks, URLs and directory listings still start from the beginning.
|
|
18
19
|
- `:50` / `:50-` — read from line 50 onward.
|
|
19
20
|
- `:50-200` — lines 50–200 inclusive.
|
|
20
21
|
- `:50+150` — 150 lines starting at line 50.
|
|
@@ -39,6 +40,7 @@ Append `:<sel>` to `path`. The bare path falls back to the default mode.
|
|
|
39
40
|
`[NN lines across MM elided regions; read <path>:raw or a line range like <path>:1-9999 for verbatim content]`
|
|
40
41
|
|
|
41
42
|
If the elided body is what you actually need, re-issue the **exact selector the footer names**. NEVER guess what's inside `..` / `…` — those markers carry no content.
|
|
43
|
+
- Directional windows identify the retained first/last lines and the omitted range; use the `re-read <path>:1-<total>` or `:raw` hint in the footer to recover the full content.
|
|
42
44
|
|
|
43
45
|
# Documents & Notebooks
|
|
44
46
|
|
|
@@ -12,6 +12,11 @@ Behavior:
|
|
|
12
12
|
- Repeated searches add to the active tool set; they do not remove earlier selections
|
|
13
13
|
- Newly activated tools become available before the next model call in the same overall turn
|
|
14
14
|
|
|
15
|
+
Follow-through:
|
|
16
|
+
- Activation only changes the active tool set; it does not execute a discovered tool or complete its work.
|
|
17
|
+
- If the task still needs a newly activated capability, call that tool in the next model turn. Do not claim that a browser action, web search, integration, or subagent ran until its tool result is present.
|
|
18
|
+
- If discovery was the only requested action, report availability as availability, not as completed work.
|
|
19
|
+
|
|
15
20
|
Not for repository/file/code search. Tool discovery only.
|
|
16
21
|
|
|
17
22
|
Returns JSON with:
|
|
@@ -28,7 +28,7 @@ Subagents have no conversation history. Every fact, file path, and direction the
|
|
|
28
28
|
{{#if independentMode}}- `.inheritContext`: independent mode cannot inherit parent conversation. Omit it or set `"none"`; any non-`none` value is rejected before scheduling.{{/if}}
|
|
29
29
|
{{#if customSchemaEnabled}}- `schema`: JTD schema for expected structured output (do not put format rules in assignments){{/if}}
|
|
30
30
|
- `spawnPlan` (optional): required before any batch with more than 4 tasks; include whyParallel, whyNotLocal, independence, expectedReceiptShape, and maxInlineTokens.
|
|
31
|
-
{{#if isolationEnabled}}- `isolated`: run in isolated
|
|
31
|
+
{{#if isolationEnabled}}- `isolated`: run in an isolated environment; REQUIRED when the user explicitly requests a worktree (for example, "use worktree"), and use when tasks edit overlapping files{{/if}}
|
|
32
32
|
</parameters>
|
|
33
33
|
|
|
34
34
|
<rules>
|
|
@@ -18,6 +18,10 @@ import type { ImageContent, MessageAttribution } from "@gajae-code/ai";
|
|
|
18
18
|
import { getConfigRootDir, isEnoent } from "@gajae-code/utils";
|
|
19
19
|
import { withFileLock } from "../config/file-lock";
|
|
20
20
|
import type { CustomMessage } from "../session/messages";
|
|
21
|
+
import { type GhResult, type RunGh, runGhDefault } from "../utils/gh";
|
|
22
|
+
|
|
23
|
+
export type { GhResult, RunGh };
|
|
24
|
+
export { runGhDefault };
|
|
21
25
|
|
|
22
26
|
export const STAR_REMINDER_REPO = "Yeachan-Heo/gajae-code";
|
|
23
27
|
export const STAR_REMINDER_CUSTOM_TYPE = "star-reminder";
|
|
@@ -34,15 +38,6 @@ export interface StarReminderState {
|
|
|
34
38
|
|
|
35
39
|
export type StarCheckStatus = "starred" | "unstarred" | "unavailable";
|
|
36
40
|
|
|
37
|
-
export interface GhResult {
|
|
38
|
-
exitCode: number;
|
|
39
|
-
stdout: string;
|
|
40
|
-
stderr: string;
|
|
41
|
-
timedOut?: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export type RunGh = (args: string[], options?: { timeoutMs?: number }) => Promise<GhResult>;
|
|
45
|
-
|
|
46
41
|
export interface StarReminderDeps {
|
|
47
42
|
statePath?: string;
|
|
48
43
|
now?: () => Date;
|
|
@@ -187,39 +182,6 @@ export async function recordDeclinedAfterNo(deps?: StarReminderDeps): Promise<St
|
|
|
187
182
|
}, deps);
|
|
188
183
|
}
|
|
189
184
|
|
|
190
|
-
// --------------------------------------------------------------------------
|
|
191
|
-
// gh helpers
|
|
192
|
-
// --------------------------------------------------------------------------
|
|
193
|
-
|
|
194
|
-
/** Default `gh` runner. Returns an unavailable-style result instead of throwing. */
|
|
195
|
-
export async function runGhDefault(args: string[], options?: { timeoutMs?: number }): Promise<GhResult> {
|
|
196
|
-
const ghPath = Bun.which("gh");
|
|
197
|
-
if (!ghPath) {
|
|
198
|
-
return { exitCode: -1, stdout: "", stderr: "gh not found", timedOut: false };
|
|
199
|
-
}
|
|
200
|
-
const timeoutMs = options?.timeoutMs ?? GH_TIMEOUT_MS;
|
|
201
|
-
let timedOut = false;
|
|
202
|
-
try {
|
|
203
|
-
const proc = Bun.spawn([ghPath, ...args], { stdout: "pipe", stderr: "pipe", stdin: "ignore" });
|
|
204
|
-
const timer = setTimeout(() => {
|
|
205
|
-
timedOut = true;
|
|
206
|
-
proc.kill();
|
|
207
|
-
}, timeoutMs);
|
|
208
|
-
try {
|
|
209
|
-
const [stdout, stderr] = await Promise.all([
|
|
210
|
-
new Response(proc.stdout).text(),
|
|
211
|
-
new Response(proc.stderr).text(),
|
|
212
|
-
]);
|
|
213
|
-
const exitCode = await proc.exited;
|
|
214
|
-
return { exitCode, stdout, stderr, timedOut };
|
|
215
|
-
} finally {
|
|
216
|
-
clearTimeout(timer);
|
|
217
|
-
}
|
|
218
|
-
} catch (err) {
|
|
219
|
-
return { exitCode: -1, stdout: "", stderr: err instanceof Error ? err.message : String(err), timedOut };
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
185
|
function resolveRunGh(deps?: StarReminderDeps): RunGh {
|
|
224
186
|
return deps?.runGh ?? runGhDefault;
|
|
225
187
|
}
|
|
@@ -75,6 +75,7 @@ const STARTUP_TIMEOUT_GRACE_MS = 500;
|
|
|
75
75
|
* budget derived from the readiness deadline (see `maxStartupTimeoutMs`).
|
|
76
76
|
*/
|
|
77
77
|
const MAX_STARTUP_TIMEOUT_MS = 1_750;
|
|
78
|
+
const DEFAULT_EXACT_CONFIG_STARTUP_TIMEOUT_MS = 30_000;
|
|
78
79
|
|
|
79
80
|
export function resolveStartupTimeoutMs(configs: MCPServerConfig[], maxStartupTimeoutMs?: number): number {
|
|
80
81
|
const ceiling =
|
|
@@ -88,6 +89,17 @@ export function resolveStartupTimeoutMs(configs: MCPServerConfig[], maxStartupTi
|
|
|
88
89
|
return Math.min(ceiling, Math.max(STARTUP_TIMEOUT_MS, Math.max(...configuredTimeouts) + STARTUP_TIMEOUT_GRACE_MS));
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
export function resolveExactConfigStartupTimeoutMs(configs: MCPServerConfig[]): number {
|
|
93
|
+
const effectiveTimeouts = configs.map(config => {
|
|
94
|
+
const timeout = config.timeout;
|
|
95
|
+
return typeof timeout === "number" && Number.isFinite(timeout) && timeout > 0
|
|
96
|
+
? timeout
|
|
97
|
+
: DEFAULT_EXACT_CONFIG_STARTUP_TIMEOUT_MS;
|
|
98
|
+
});
|
|
99
|
+
if (effectiveTimeouts.length === 0) return STARTUP_TIMEOUT_MS;
|
|
100
|
+
return Math.max(...effectiveTimeouts) + STARTUP_TIMEOUT_GRACE_MS;
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
function trackPromise<T>(promise: Promise<T>): TrackedPromise<T> {
|
|
92
104
|
const tracked: TrackedPromise<T> = { promise, status: "pending" };
|
|
93
105
|
promise.then(
|
|
@@ -650,10 +662,13 @@ export class MCPManager {
|
|
|
650
662
|
}
|
|
651
663
|
|
|
652
664
|
if (connectionTasks.length > 0) {
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
665
|
+
const configs = connectionTasks.map(task => task.config);
|
|
666
|
+
// An exact config is explicit operator intent, so its declared connection
|
|
667
|
+
// windows govern startup. Ordinary discovery keeps the short ceiling.
|
|
668
|
+
const startupTimeoutMs =
|
|
669
|
+
this.#toolsOnly && this.#maxStartupTimeoutMs === undefined
|
|
670
|
+
? resolveExactConfigStartupTimeoutMs(configs)
|
|
671
|
+
: resolveStartupTimeoutMs(configs, this.#maxStartupTimeoutMs);
|
|
657
672
|
const firstUnexpectedFailure = Promise.withResolvers<{ reason: unknown }>();
|
|
658
673
|
if (this.#toolsOnly) {
|
|
659
674
|
for (const task of connectionTasks) {
|
|
@@ -2,9 +2,18 @@ import * as fs from "node:fs/promises";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { isEnoent, logger } from "@gajae-code/utils";
|
|
4
4
|
import { getAgentDir } from "@gajae-code/utils/dirs";
|
|
5
|
+
import { $credentialEnv } from "@gajae-code/utils/env";
|
|
5
6
|
|
|
6
7
|
const SMITHERY_AUTH_FILENAME = "smithery.json";
|
|
7
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Smithery web origin, from trusted environment sources only.
|
|
10
|
+
*
|
|
11
|
+
* This origin serves the CLI auth session and the verification URL the user is
|
|
12
|
+
* sent to, so whatever can set it can drive the login flow. `$env` merges the
|
|
13
|
+
* caller's `cwd/.env` into `process.env`, so reading it there would let
|
|
14
|
+
* repository content redirect that flow.
|
|
15
|
+
*/
|
|
16
|
+
const SMITHERY_URL = $credentialEnv("SMITHERY_URL") || "https://smithery.ai";
|
|
8
17
|
|
|
9
18
|
type SmitheryCliAuthSession = {
|
|
10
19
|
sessionId: string;
|
|
@@ -31,6 +40,11 @@ function normalizeApiKey(value: string | undefined): string | undefined {
|
|
|
31
40
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
/** Test seam: the Smithery origin and env API key as resolved from trusted env. */
|
|
44
|
+
export function resolveSmitheryEnvForTest(): { url: string; apiKey: string | undefined } {
|
|
45
|
+
return { url: SMITHERY_URL, apiKey: normalizeApiKey($credentialEnv("SMITHERY_API_KEY")) };
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
export function getSmitheryLoginUrl(): string {
|
|
35
49
|
return SMITHERY_URL;
|
|
36
50
|
}
|
|
@@ -62,7 +76,8 @@ export async function pollSmitheryCliAuthSession(
|
|
|
62
76
|
}
|
|
63
77
|
|
|
64
78
|
export async function getSmitheryApiKey(): Promise<string | undefined> {
|
|
65
|
-
|
|
79
|
+
// Trusted sources only: this key authenticates every Smithery API call.
|
|
80
|
+
const envKey = normalizeApiKey($credentialEnv("SMITHERY_API_KEY"));
|
|
66
81
|
if (envKey) return envKey;
|
|
67
82
|
|
|
68
83
|
const authPath = getSmitheryAuthPath();
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import { $credentialEnv } from "@gajae-code/utils/env";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Smithery API base, from trusted environment sources only.
|
|
5
|
+
*
|
|
6
|
+
* Every request to this base carries `Authorization: Bearer <apiKey>` and the
|
|
7
|
+
* `/connect` routes return the connection records the agent consumes, so
|
|
8
|
+
* whatever can set it receives the key and supplies those records. `$env` merges
|
|
9
|
+
* the caller's `cwd/.env` into `process.env`.
|
|
10
|
+
*/
|
|
11
|
+
const SMITHERY_API_BASE_URL = ($credentialEnv("SMITHERY_API_URL") || "https://api.smithery.ai").replace(/\/+$/, "");
|
|
2
12
|
|
|
3
13
|
export class SmitheryConnectError extends Error {
|
|
4
14
|
status: number;
|
package/src/sdk/acp/adapter.ts
CHANGED
|
@@ -8,7 +8,7 @@ type JsonObject = Record<string, unknown>;
|
|
|
8
8
|
|
|
9
9
|
/** The small agent-side ACP surface used for reverse requests. */
|
|
10
10
|
export interface AcpReverseConnection {
|
|
11
|
-
request?(method: string, params: JsonObject): Promise<unknown>;
|
|
11
|
+
request?(method: string, params: JsonObject, options?: { cancellationSignal?: AbortSignal }): Promise<unknown>;
|
|
12
12
|
[key: string]: unknown;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -42,6 +42,7 @@ export type AcpReconnectFailedHandler = (error: SdkClientError) => void;
|
|
|
42
42
|
export type AcpFrameHandler = (frame: SdkFrame) => void;
|
|
43
43
|
type ReverseRequest = {
|
|
44
44
|
state: "pending" | "cancelled";
|
|
45
|
+
controller?: AbortController;
|
|
45
46
|
cancelTimer?: NodeJS.Timeout;
|
|
46
47
|
};
|
|
47
48
|
|
|
@@ -142,7 +143,10 @@ export class AcpSdkAdapter {
|
|
|
142
143
|
if (this.#closed) return;
|
|
143
144
|
this.#closed = true;
|
|
144
145
|
if (this.#heartbeat) clearInterval(this.#heartbeat);
|
|
145
|
-
for (const request of this.#reverseRequests.values())
|
|
146
|
+
for (const request of this.#reverseRequests.values()) {
|
|
147
|
+
request.controller?.abort();
|
|
148
|
+
if (request.cancelTimer) clearTimeout(request.cancelTimer);
|
|
149
|
+
}
|
|
146
150
|
this.#reverseRequests.clear();
|
|
147
151
|
this.#unsubscribe?.();
|
|
148
152
|
this.#unsubscribeReconnect?.();
|
|
@@ -263,6 +267,7 @@ export class AcpSdkAdapter {
|
|
|
263
267
|
if (this.#closed || !this.#providers.length) return;
|
|
264
268
|
if (this.#reclaiming) return await this.#reclaiming;
|
|
265
269
|
this.#reclaiming = (async () => {
|
|
270
|
+
this.#abortActiveReverseRequests();
|
|
266
271
|
this.#connectionId = this.#client.connectionId;
|
|
267
272
|
if (!this.#connectionId) this.#connectionId = await this.#waitForConnectionId();
|
|
268
273
|
for (const provider of this.#providers) await this.registerProvider(provider);
|
|
@@ -349,13 +354,14 @@ export class AcpSdkAdapter {
|
|
|
349
354
|
!this.#ownsReverseLease(connectionId, capability, leaseId)
|
|
350
355
|
)
|
|
351
356
|
return;
|
|
352
|
-
const
|
|
357
|
+
const controller = new AbortController();
|
|
358
|
+
const active: ReverseRequest = { state: "pending", controller };
|
|
353
359
|
this.#reverseRequests.set(id, active);
|
|
354
360
|
try {
|
|
355
361
|
const request = frame.payload as JsonObject | undefined;
|
|
356
362
|
const method = typeof request?.method === "string" ? request.method : "";
|
|
357
363
|
const payload = request?.payload && typeof request.payload === "object" ? (request.payload as JsonObject) : {};
|
|
358
|
-
const result = await this.#forwardReverse(method, payload);
|
|
364
|
+
const result = await this.#forwardReverse(method, payload, controller.signal);
|
|
359
365
|
if (!this.#canRespondToReverse(id, active, connectionId, capability, leaseId)) return;
|
|
360
366
|
|
|
361
367
|
this.#client.send({ type: "reverse_response", id, connectionId, leaseId, ok: true, result });
|
|
@@ -404,6 +410,7 @@ export class AcpSdkAdapter {
|
|
|
404
410
|
const request: ReverseRequest = this.#reverseRequests.get(id) ?? { state: "pending" };
|
|
405
411
|
if (request.state === "cancelled") return;
|
|
406
412
|
request.state = "cancelled";
|
|
413
|
+
request.controller?.abort();
|
|
407
414
|
request.cancelTimer = setTimeout(() => this.#finishReverse(id, request), this.#reverseCancelTtlMs);
|
|
408
415
|
this.#reverseRequests.set(id, request);
|
|
409
416
|
}
|
|
@@ -414,9 +421,18 @@ export class AcpSdkAdapter {
|
|
|
414
421
|
this.#reverseRequests.delete(id);
|
|
415
422
|
}
|
|
416
423
|
|
|
417
|
-
|
|
424
|
+
#abortActiveReverseRequests(): void {
|
|
425
|
+
for (const [id, request] of this.#reverseRequests) {
|
|
426
|
+
request.state = "cancelled";
|
|
427
|
+
request.controller?.abort();
|
|
428
|
+
this.#finishReverse(id, request);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
async #forwardReverse(method: string, payload: JsonObject, signal: AbortSignal): Promise<unknown> {
|
|
418
433
|
if (!method || !this.#connection) throw new AcpSdkAdapterError("acp_reverse_unavailable");
|
|
419
|
-
if (this.#connection.request)
|
|
434
|
+
if (this.#connection.request)
|
|
435
|
+
return await this.#connection.request(method, payload, { cancellationSignal: signal });
|
|
420
436
|
const target = this.#connection[method];
|
|
421
437
|
if (typeof target !== "function")
|
|
422
438
|
throw new AcpSdkAdapterError("acp_reverse_unsupported", `ACP client does not support ${method}.`);
|
|
@@ -5,7 +5,7 @@ import * as fs from "node:fs/promises";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import type { NativeExactUnlinkResult } from "@gajae-code/natives";
|
|
7
7
|
import * as native from "@gajae-code/natives";
|
|
8
|
-
import { resolveEquivalentPath } from "@gajae-code/utils";
|
|
8
|
+
import { $credentialEnv, resolveEquivalentPath } from "@gajae-code/utils";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
isModelProfileError,
|
|
@@ -706,12 +706,31 @@ async function reconcileReadyScope(broker: Broker, id: string, scope: string | u
|
|
|
706
706
|
});
|
|
707
707
|
}
|
|
708
708
|
|
|
709
|
+
/**
|
|
710
|
+
* Operator override for the session-host command, resolved from trusted
|
|
711
|
+
* environment sources only.
|
|
712
|
+
*
|
|
713
|
+
* The result is spawned directly, so whatever can set it chooses which binary
|
|
714
|
+
* the broker runs. `$env` merges the caller's `cwd/.env` into `process.env`, so
|
|
715
|
+
* reading it there would let repository content replace the session host;
|
|
716
|
+
* resolve it the same way provider credentials are (launching shell plus
|
|
717
|
+
* GJC/user-owned `.env` files, never the project `.env`).
|
|
718
|
+
*/
|
|
719
|
+
function sdkSessionCommandOverride(): { file: string; args: string[] } | undefined {
|
|
720
|
+
const configured = $credentialEnv("GJC_SDK_SESSION_COMMAND");
|
|
721
|
+
if (!configured) return undefined;
|
|
722
|
+
const [file, ...args] = configured.trim().split(/\s+/);
|
|
723
|
+
return file ? { file, args } : undefined;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/** Test seam: the session-host command override as resolved from trusted env. */
|
|
727
|
+
export function sdkSessionCommandOverrideForTest(): { file: string; args: string[] } | undefined {
|
|
728
|
+
return sdkSessionCommandOverride();
|
|
729
|
+
}
|
|
730
|
+
|
|
709
731
|
function command(broker: Broker): LifecycleCommand {
|
|
710
|
-
const configured =
|
|
711
|
-
if (configured)
|
|
712
|
-
const [file, ...args] = configured.trim().split(/\s+/);
|
|
713
|
-
if (file) return { file, args };
|
|
714
|
-
}
|
|
732
|
+
const configured = sdkSessionCommandOverride();
|
|
733
|
+
if (configured) return configured;
|
|
715
734
|
return lifecycleCommandResolversForTest.get(broker)?.() ?? resolveSdkInternalSpawnCommand("session-host-internal");
|
|
716
735
|
}
|
|
717
736
|
|