@gajae-code/coding-agent 0.17.2 → 0.17.5
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 +267 -0
- package/dist/types/cli/daemon-cli.d.ts +3 -1
- package/dist/types/cli/github-release.d.ts +17 -0
- package/dist/types/cli/public-command-entry.d.ts +56 -0
- package/dist/types/cli/public-command-errors.d.ts +126 -0
- package/dist/types/cli/public-command-evidence.d.ts +99 -0
- package/dist/types/cli/public-command-help.d.ts +65 -0
- package/dist/types/cli/public-command-registry.d.ts +69 -0
- package/dist/types/cli/session-picker.d.ts +1 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/cli/skills-cli.d.ts +5 -0
- package/dist/types/cli.d.ts +3 -0
- package/dist/types/commands/daemon.d.ts +4 -50
- package/dist/types/commands/sdk.d.ts +20 -37
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/commands/skills.d.ts +9 -0
- package/dist/types/config/autorouting-tier-map.d.ts +1049 -3
- package/dist/types/config/file-lock.d.ts +13 -3
- package/dist/types/config/model-profile-activation.d.ts +45 -1
- package/dist/types/config/model-registry.d.ts +14 -3
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/settings-schema.d.ts +11 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
- package/dist/types/daemon/operator-contract.d.ts +5 -1
- package/dist/types/eval/js/worker-protocol.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +12 -0
- package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
- package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
- package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
- package/dist/types/extensibility/shared-events.d.ts +3 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
- package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
- package/dist/types/harness-control-plane/finalize.d.ts +14 -3
- package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
- package/dist/types/internal-urls/index.d.ts +1 -0
- package/dist/types/internal-urls/parse.d.ts +9 -1
- package/dist/types/main.d.ts +23 -1
- package/dist/types/modes/acp/acp-agent.d.ts +55 -1
- package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
- package/dist/types/modes/components/session-selector.d.ts +5 -2
- package/dist/types/modes/components/user-message-selector.d.ts +5 -2
- package/dist/types/modes/controllers/command-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
- package/dist/types/modes/types.d.ts +2 -2
- package/dist/types/runtime/process-lifecycle.d.ts +2 -0
- package/dist/types/runtime-mcp/loader.d.ts +2 -0
- package/dist/types/runtime-mcp/manager.d.ts +69 -6
- package/dist/types/runtime-mcp/pool.d.ts +17 -0
- package/dist/types/runtime-mcp/redaction.d.ts +20 -0
- package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
- package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
- package/dist/types/sdk/broker/broker.d.ts +17 -4
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/identity.d.ts +5 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
- package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
- package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
- package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
- package/dist/types/sdk/broker/runtime.d.ts +1 -1
- package/dist/types/sdk/broker/session-index.d.ts +22 -3
- package/dist/types/sdk/broker/spawn-authority.d.ts +12 -0
- package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
- package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
- package/dist/types/sdk/bus/index.d.ts +19 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
- package/dist/types/sdk/cli/master-cli.d.ts +6 -10
- package/dist/types/sdk/cli/rows.d.ts +19 -1
- package/dist/types/sdk/cli/session-cli.d.ts +22 -5
- package/dist/types/sdk/client/client.d.ts +2 -0
- package/dist/types/sdk/guides/cli.d.ts +3 -4
- package/dist/types/sdk/guides/verify.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +9 -0
- package/dist/types/sdk/host/session-runtime.d.ts +31 -0
- package/dist/types/sdk/host/types.d.ts +10 -0
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +85 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
- package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
- package/dist/types/sdk/router/session-router.d.ts +2 -0
- package/dist/types/sdk/session.d.ts +3 -3
- package/dist/types/sdk/startup-capability.d.ts +2 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
- package/dist/types/sdk/transport/stdio.d.ts +5 -1
- package/dist/types/session/agent-session.d.ts +175 -23
- package/dist/types/session/fallback-chain-controller.d.ts +6 -6
- package/dist/types/session/fold-coordinator.d.ts +17 -3
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
- package/dist/types/session/session-manager.d.ts +64 -1
- package/dist/types/session/session-work-lease.d.ts +14 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
- package/dist/types/setup/provider-onboarding.d.ts +81 -1
- package/dist/types/task/types.d.ts +2 -0
- package/dist/types/tools/bash-interactive.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +37 -11
- package/dist/types/tools/fetch.d.ts +10 -1
- package/dist/types/tools/job.d.ts +1 -1
- package/dist/types/tools/steer-fold.d.ts +31 -0
- package/dist/types/tools/subagent.d.ts +8 -1
- package/dist/types/utils/git.d.ts +28 -2
- package/dist/types/utils/mupdf-embedded.d.ts +2 -0
- package/dist/types/utils/mupdf.d.ts +4 -0
- package/dist/types/utils/session-title-generation.d.ts +6 -0
- package/dist/types/utils/title-generator.d.ts +11 -2
- package/dist/types/web/scrapers/types.d.ts +3 -0
- package/package.json +18 -10
- package/scripts/build-binary.ts +9 -3
- package/scripts/compile-args.ts +0 -9
- package/scripts/embed-mupdf.ts +52 -0
- package/scripts/generate-sdk-operation-inventory.ts +31 -1
- package/scripts/vendor-markit.ts +196 -0
- package/src/async/job-manager.ts +22 -1
- package/src/cli/daemon-cli.ts +53 -18
- package/src/cli/github-release.ts +87 -5
- package/src/cli/mcp-cli.ts +38 -4
- package/src/cli/public-command-entry.ts +450 -0
- package/src/cli/public-command-errors.ts +581 -0
- package/src/cli/public-command-evidence.ts +717 -0
- package/src/cli/public-command-help.ts +360 -0
- package/src/cli/public-command-registry.ts +541 -0
- package/src/cli/session-picker.ts +2 -1
- package/src/cli/setup-cli.ts +10 -1
- package/src/cli/skills-cli.ts +46 -2
- package/src/cli/stats-cli.ts +11 -1
- package/src/cli.ts +61 -1
- package/src/commands/daemon.ts +65 -69
- package/src/commands/sdk.ts +175 -117
- package/src/commands/setup.ts +2 -0
- package/src/commands/skills.ts +11 -0
- package/src/config/autorouting-tier-map.ts +543 -3
- package/src/config/file-lock.ts +206 -65
- package/src/config/model-discovery-manager.ts +4 -4
- package/src/config/model-profile-activation.ts +417 -66
- package/src/config/model-registry.ts +254 -36
- package/src/config/model-resolver.ts +6 -1
- package/src/config/settings-schema.ts +26 -2
- package/src/coordinator-mcp/policy.ts +10 -5
- package/src/coordinator-mcp/question-gate-codec.ts +17 -0
- package/src/coordinator-mcp/question-state.ts +179 -9
- package/src/coordinator-mcp/server.ts +521 -87
- package/src/coordinator-mcp/session-reaper.ts +6 -4
- package/src/crash/record-loader.ts +6 -2
- package/src/daemon/operator-contract.ts +26 -12
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
- package/src/eval/js/context-manager.ts +8 -8
- package/src/eval/js/worker-core.ts +9 -4
- package/src/eval/js/worker-protocol.ts +2 -0
- package/src/exec/bash-executor.ts +3 -0
- package/src/extensibility/extensions/runner.ts +52 -4
- package/src/extensibility/extensions/types.ts +10 -0
- package/src/extensibility/gjc-plugins/registry.ts +196 -37
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
- package/src/extensibility/runtime-skill-discovery.ts +61 -3
- package/src/extensibility/shared-events.ts +3 -1
- package/src/gjc-runtime/session-state-lock.ts +165 -24
- package/src/gjc-runtime/state-writer.ts +317 -6
- package/src/gjc-runtime/ultragoal-succession.ts +31 -3
- package/src/harness-control-plane/control-endpoint.ts +24 -6
- package/src/harness-control-plane/finalize.ts +312 -25
- package/src/harness-control-plane/owner.ts +323 -89
- package/src/internal-urls/docs-index.generated.ts +23 -20
- package/src/internal-urls/embedded-protocol.ts +83 -0
- package/src/internal-urls/index.ts +1 -0
- package/src/internal-urls/parse.ts +21 -1
- package/src/internal-urls/router.ts +4 -2
- package/src/main.ts +192 -74
- package/src/modes/acp/acp-agent.ts +973 -56
- package/src/modes/acp/startup-provenance.ts +59 -0
- package/src/modes/components/custom-provider-wizard.ts +308 -7
- package/src/modes/components/gjc-bundle-settings.ts +21 -1
- package/src/modes/components/oauth-selector.ts +9 -0
- package/src/modes/components/session-selector.ts +47 -4
- package/src/modes/components/tool-status-header.ts +72 -6
- package/src/modes/components/user-message-selector.ts +57 -15
- package/src/modes/controllers/command-controller.ts +58 -32
- package/src/modes/controllers/extension-ui-controller.ts +33 -7
- package/src/modes/controllers/input-controller.ts +4 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
- package/src/modes/controllers/selector-controller.ts +161 -15
- package/src/modes/interactive-mode.ts +21 -7
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
- package/src/modes/types.ts +2 -2
- package/src/prompts/agent-fragments/browser-aside.md +1 -0
- package/src/prompts/system/title-system.md +1 -1
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/job.md +1 -1
- package/src/prompts/tools/read.md +2 -0
- package/src/runtime/network-prewarm-service.test.ts +36 -1
- package/src/runtime/network-prewarm-service.ts +28 -3
- package/src/runtime/process-lifecycle.ts +22 -11
- package/src/runtime-mcp/config.ts +16 -1
- package/src/runtime-mcp/loader.ts +6 -3
- package/src/runtime-mcp/manager.ts +845 -109
- package/src/runtime-mcp/pool.test.ts +31 -0
- package/src/runtime-mcp/pool.ts +304 -28
- package/src/runtime-mcp/redaction.ts +42 -0
- package/src/runtime-mcp/startup-policy.ts +7 -0
- package/src/runtime-mcp/tool-bridge.ts +71 -0
- package/src/runtime-mcp/transports/http.ts +108 -25
- package/src/sdk/acp/adapter.ts +27 -8
- package/src/sdk/broker/broker.ts +1431 -198
- package/src/sdk/broker/ensure.ts +21 -3
- package/src/sdk/broker/identity.ts +22 -1
- package/src/sdk/broker/lifecycle-ledger.ts +95 -31
- package/src/sdk/broker/lifecycle.ts +690 -141
- package/src/sdk/broker/managed-task-dag.ts +1927 -0
- package/src/sdk/broker/managed-task-verification.ts +642 -0
- package/src/sdk/broker/runtime.ts +1 -1
- package/src/sdk/broker/session-index.ts +97 -4
- package/src/sdk/broker/spawn-authority.ts +175 -14
- package/src/sdk/broker/startup-failure.ts +80 -1
- package/src/sdk/broker/stderr-drainer.ts +59 -0
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/index.ts +707 -81
- package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
- package/src/sdk/bus/telegram-daemon.ts +10 -3
- package/src/sdk/cli/master-cli.ts +47 -36
- package/src/sdk/cli/rows.ts +30 -7
- package/src/sdk/cli/session-cli.ts +705 -184
- package/src/sdk/client/client.ts +18 -0
- package/src/sdk/guides/catalog.ts +2 -2
- package/src/sdk/guides/cli.ts +20 -62
- package/src/sdk/guides/verify.ts +14 -0
- package/src/sdk/host/host.ts +49 -5
- package/src/sdk/host/session-runtime.test.ts +184 -2
- package/src/sdk/host/session-runtime.ts +322 -101
- package/src/sdk/host/types.ts +12 -1
- package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
- package/src/sdk/host/websocket-transport.ts +40 -6
- package/src/sdk/index.ts +11 -0
- package/src/sdk/lifecycle/service.ts +2 -0
- package/src/sdk/prompt-deadline-flush.ts +356 -0
- package/src/sdk/prompt-deadline-manager.ts +133 -1
- package/src/sdk/prompt-tool-boundary.ts +121 -0
- package/src/sdk/protocol/operation-inventory.generated.json +106 -0
- package/src/sdk/router/session-router.ts +9 -1
- package/src/sdk/session.ts +763 -116
- package/src/sdk/startup-capability.ts +1 -1
- package/src/sdk/transport/relay.ts +71 -6
- package/src/sdk/transport/serve-cli.ts +397 -42
- package/src/sdk/transport/socket.ts +12 -11
- package/src/sdk/transport/stdio.ts +7 -3
- package/src/session/agent-session.ts +2472 -407
- package/src/session/fallback-chain-controller.ts +6 -7
- package/src/session/fold-coordinator.ts +24 -5
- package/src/session/internal/managed-session-scope.ts +68 -18
- package/src/session/internal/managed-session-storage.ts +334 -12
- package/src/session/session-manager.ts +382 -44
- package/src/session/session-work-lease.ts +34 -0
- package/src/setup/model-onboarding-guidance.ts +1 -1
- package/src/setup/provider-onboarding.ts +397 -24
- package/src/setup/provider-presets.json +2 -1
- package/src/slash-commands/builtin-registry.ts +259 -15
- package/src/task/executor.ts +46 -17
- package/src/task/index.ts +14 -2
- package/src/task/types.ts +2 -0
- package/src/tools/bash-interactive.ts +2 -0
- package/src/tools/bash.ts +118 -78
- package/src/tools/fetch.ts +140 -25
- package/src/tools/job.ts +151 -25
- package/src/tools/output-meta.ts +15 -2
- package/src/tools/path-utils.ts +27 -3
- package/src/tools/read.ts +3 -3
- package/src/tools/steer-fold.ts +107 -0
- package/src/tools/subagent-render.ts +24 -1
- package/src/tools/subagent.ts +27 -1
- package/src/tools/tool-catalog.generated.ts +29 -2
- package/src/tools/tool-errors.ts +4 -0
- package/src/utils/git.ts +53 -3
- package/src/utils/markit.ts +55 -41
- package/src/utils/mupdf-assets.d.ts +4 -0
- package/src/utils/mupdf-embedded.ts +4 -0
- package/src/utils/mupdf.ts +136 -0
- package/src/utils/session-title-generation.ts +29 -0
- package/src/utils/title-generator.ts +46 -2
- package/src/web/scrapers/types.ts +24 -3
- package/vendor/markit-ai/LICENSE +21 -0
- package/vendor/markit-ai/MANIFEST.json +412 -0
- package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/config.js +139 -0
- package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
- package/vendor/markit-ai/dist/commands/convert.js +113 -0
- package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/formats.js +92 -0
- package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/init.js +29 -0
- package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
- package/vendor/markit-ai/dist/commands/onboard.js +61 -0
- package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
- package/vendor/markit-ai/dist/commands/plugin.js +58 -0
- package/vendor/markit-ai/dist/config.d.ts +26 -0
- package/vendor/markit-ai/dist/config.js +42 -0
- package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/audio.js +104 -0
- package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
- package/vendor/markit-ai/dist/converters/csv.js +83 -0
- package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/docx.js +57 -0
- package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/epub.js +128 -0
- package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
- package/vendor/markit-ai/dist/converters/github.js +148 -0
- package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/html.js +30 -0
- package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/image.js +124 -0
- package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
- package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
- package/vendor/markit-ai/dist/converters/iwork.js +391 -0
- package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/json.js +21 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
- package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
- package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
- package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
- package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
- package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
- package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
- package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
- package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
- package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
- package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
- package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/pptx.js +289 -0
- package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
- package/vendor/markit-ai/dist/converters/rss.js +138 -0
- package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
- package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
- package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/xml.js +18 -0
- package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
- package/vendor/markit-ai/dist/converters/yaml.js +17 -0
- package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
- package/vendor/markit-ai/dist/converters/zip.js +57 -0
- package/vendor/markit-ai/dist/index.d.ts +30 -0
- package/vendor/markit-ai/dist/index.js +26 -0
- package/vendor/markit-ai/dist/main.d.ts +2 -0
- package/vendor/markit-ai/dist/main.js +191 -0
- package/vendor/markit-ai/dist/markit.d.ts +45 -0
- package/vendor/markit-ai/dist/markit.js +267 -0
- package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
- package/vendor/markit-ai/dist/plugins/api.js +42 -0
- package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
- package/vendor/markit-ai/dist/plugins/index.js +3 -0
- package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/installer.js +176 -0
- package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
- package/vendor/markit-ai/dist/plugins/loader.js +61 -0
- package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
- package/vendor/markit-ai/dist/plugins/types.js +1 -0
- package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
- package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
- package/vendor/markit-ai/dist/providers/index.js +56 -0
- package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
- package/vendor/markit-ai/dist/providers/openai.js +76 -0
- package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
- package/vendor/markit-ai/dist/providers/types.js +1 -0
- package/vendor/markit-ai/dist/types.d.ts +36 -0
- package/vendor/markit-ai/dist/types.js +1 -0
- package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
- package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
- package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
- package/vendor/markit-ai/dist/utils/output.js +31 -0
- package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
- package/vendor/markit-ai/dist/utils/turndown.js +70 -0
- package/vendor/markit-ai/package.json +74 -0
- package/vendor/markit-ai.patch +49 -0
|
@@ -39,6 +39,7 @@ export type SessionInspector = (sessionPath: string) => Promise<ResumeTailInspec
|
|
|
39
39
|
|
|
40
40
|
type SelectorState =
|
|
41
41
|
| { kind: "browsing" }
|
|
42
|
+
| { kind: "starring"; token: number }
|
|
42
43
|
| { kind: "checking"; session: SessionInfo; token: number }
|
|
43
44
|
| { kind: "confirming"; session: SessionInfo; token: number; identity: ResumeSessionIdentity }
|
|
44
45
|
| { kind: "settled" };
|
|
@@ -52,12 +53,13 @@ class SessionList implements Component {
|
|
|
52
53
|
onCancel?: () => void;
|
|
53
54
|
onExit: () => void = () => {};
|
|
54
55
|
onDeleteRequest?: (session: SessionInfo) => void;
|
|
56
|
+
onToggleStarRequest?: (session: SessionInfo) => void;
|
|
55
57
|
|
|
56
58
|
constructor(
|
|
57
59
|
private readonly allSessions: SessionInfo[],
|
|
58
60
|
private readonly showCwd = false,
|
|
59
61
|
) {
|
|
60
|
-
this.#filteredSessions = allSessions;
|
|
62
|
+
this.#filteredSessions = prioritizeStarredSessions(allSessions);
|
|
61
63
|
this.#searchInput.onSubmit = () => {
|
|
62
64
|
const selected = this.#filteredSessions[this.#selectedIndex];
|
|
63
65
|
if (selected) this.onSelect?.(selected);
|
|
@@ -100,6 +102,17 @@ class SessionList implements Component {
|
|
|
100
102
|
this.#filterSessions(this.#searchInput.getValue());
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
setSessionStarred(sessionPath: string, starred: boolean): void {
|
|
106
|
+
const session = this.allSessions.find(session => session.path === sessionPath);
|
|
107
|
+
if (!session) return;
|
|
108
|
+
session.starred = starred;
|
|
109
|
+
this.#filterSessions(this.#searchInput.getValue());
|
|
110
|
+
this.#selectedIndex = Math.max(
|
|
111
|
+
0,
|
|
112
|
+
this.#filteredSessions.findIndex(session => session.path === sessionPath),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
103
116
|
invalidate(): void {}
|
|
104
117
|
|
|
105
118
|
render(width: number): string[] {
|
|
@@ -155,6 +168,8 @@ class SessionList implements Component {
|
|
|
155
168
|
}
|
|
156
169
|
if (start > 0 || end < this.#filteredSessions.length)
|
|
157
170
|
lines.push(theme.fg("muted", ` (${this.#selectedIndex + 1}/${this.#filteredSessions.length})`));
|
|
171
|
+
if (this.onToggleStarRequest)
|
|
172
|
+
lines.push(theme.fg("muted", truncateToWidth(" [Ctrl+S to star/unstar selected session]", width)));
|
|
158
173
|
lines.push(
|
|
159
174
|
"",
|
|
160
175
|
theme.fg("muted", " [Del to delete selected transcript/artifacts, Enter to select, Esc to cancel]"),
|
|
@@ -177,7 +192,10 @@ class SessionList implements Component {
|
|
|
177
192
|
this.#selectedIndex += delta;
|
|
178
193
|
this.#clampSelectedIndex();
|
|
179
194
|
};
|
|
180
|
-
if (matchesKey(keyData, "
|
|
195
|
+
if (matchesKey(keyData, "ctrl+s")) {
|
|
196
|
+
const selected = this.#filteredSessions[this.#selectedIndex];
|
|
197
|
+
if (selected) this.onToggleStarRequest?.(selected);
|
|
198
|
+
} else if (matchesKey(keyData, "delete")) {
|
|
181
199
|
const selected = this.#filteredSessions[this.#selectedIndex];
|
|
182
200
|
if (selected) this.onDeleteRequest?.(selected);
|
|
183
201
|
} else if (matchesKey(keyData, "up")) move(-1);
|
|
@@ -194,7 +212,7 @@ class SessionList implements Component {
|
|
|
194
212
|
}
|
|
195
213
|
}
|
|
196
214
|
|
|
197
|
-
/** A one-shot resume consent selector
|
|
215
|
+
/** A one-shot resume consent selector with host-owned deletion and star persistence. */
|
|
198
216
|
export class SessionSelectorComponent extends Container {
|
|
199
217
|
#sessionList: SessionList;
|
|
200
218
|
#confirmationDialog: HookSelectorComponent | null = null;
|
|
@@ -211,6 +229,7 @@ export class SessionSelectorComponent extends Container {
|
|
|
211
229
|
private readonly onDelete?: (session: SessionInfo) => Promise<boolean>,
|
|
212
230
|
private readonly inspector?: SessionInspector,
|
|
213
231
|
private readonly onSelection?: (selection: SessionSelectionResult) => void,
|
|
232
|
+
private readonly onSetStarred?: (session: SessionInfo, starred: boolean) => Promise<void>,
|
|
214
233
|
) {
|
|
215
234
|
super();
|
|
216
235
|
this.addChild(new Spacer(1));
|
|
@@ -219,7 +238,7 @@ export class SessionSelectorComponent extends Container {
|
|
|
219
238
|
this.addChild(new DynamicBorder());
|
|
220
239
|
this.addChild(new Spacer(1));
|
|
221
240
|
this.addChild(this.#messageContainer);
|
|
222
|
-
this.#sessionList = new SessionList(
|
|
241
|
+
this.#sessionList = new SessionList([...sessions]);
|
|
223
242
|
this.#sessionList.onSelect = session => {
|
|
224
243
|
if (this.inspector) void this.#inspect(session);
|
|
225
244
|
else this.#dispatchSelect(session.path);
|
|
@@ -227,6 +246,7 @@ export class SessionSelectorComponent extends Container {
|
|
|
227
246
|
this.#sessionList.onCancel = () => this.#cancel();
|
|
228
247
|
this.#sessionList.onExit = () => this.#exit();
|
|
229
248
|
this.#sessionList.onDeleteRequest = session => this.#showDeleteConfirmation(session);
|
|
249
|
+
if (this.onSetStarred) this.#sessionList.onToggleStarRequest = session => void this.#toggleStar(session);
|
|
230
250
|
this.addChild(this.#sessionList);
|
|
231
251
|
this.addChild(new Spacer(1));
|
|
232
252
|
this.addChild(new DynamicBorder());
|
|
@@ -294,6 +314,29 @@ export class SessionSelectorComponent extends Container {
|
|
|
294
314
|
this.#sessionList.setInputFrozen(true);
|
|
295
315
|
this.onExit();
|
|
296
316
|
}
|
|
317
|
+
async #toggleStar(session: SessionInfo): Promise<void> {
|
|
318
|
+
if (!this.onSetStarred || this.#state.kind !== "browsing" || this.#confirmationDialog) return;
|
|
319
|
+
const token = ++this.#nextToken;
|
|
320
|
+
const starred = !session.starred;
|
|
321
|
+
this.#state = { kind: "starring", token };
|
|
322
|
+
this.#sessionList.setInputFrozen(true);
|
|
323
|
+
this.#clearError();
|
|
324
|
+
this.#requestRender();
|
|
325
|
+
try {
|
|
326
|
+
await this.onSetStarred(session, starred);
|
|
327
|
+
if (this.#state.kind !== "starring" || this.#state.token !== token) return;
|
|
328
|
+
this.#sessionList.setSessionStarred(session.path, starred);
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (this.#state.kind !== "starring" || this.#state.token !== token) return;
|
|
331
|
+
this.#showError(error instanceof Error ? error.message : String(error));
|
|
332
|
+
} finally {
|
|
333
|
+
if (this.#state.kind === "starring" && this.#state.token === token) {
|
|
334
|
+
this.#state = { kind: "browsing" };
|
|
335
|
+
this.#sessionList.setInputFrozen(false);
|
|
336
|
+
this.#requestRender();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
297
340
|
async #inspect(session: SessionInfo): Promise<void> {
|
|
298
341
|
const inspector = this.inspector;
|
|
299
342
|
if (!inspector || this.#state.kind !== "browsing") return;
|
|
@@ -41,6 +41,33 @@ import { getSeparator } from "./status-line/separators";
|
|
|
41
41
|
import { calculateTokensPerSecond } from "./status-line/token-rate";
|
|
42
42
|
import type { SeparatorDef } from "./status-line/types";
|
|
43
43
|
|
|
44
|
+
function usageReportAccountId(report: unknown): string | undefined {
|
|
45
|
+
if (!report || typeof report !== "object") return undefined;
|
|
46
|
+
const record = report as {
|
|
47
|
+
metadata?: unknown;
|
|
48
|
+
limits?: unknown;
|
|
49
|
+
};
|
|
50
|
+
const metadata = record.metadata;
|
|
51
|
+
const rawMetadataAccountId =
|
|
52
|
+
metadata && typeof metadata === "object" ? (metadata as { accountId?: unknown }).accountId : undefined;
|
|
53
|
+
const metadataAccountId =
|
|
54
|
+
typeof rawMetadataAccountId === "string" && rawMetadataAccountId.trim() ? rawMetadataAccountId.trim() : undefined;
|
|
55
|
+
if (!Array.isArray(record.limits)) return metadataAccountId;
|
|
56
|
+
|
|
57
|
+
const scopeAccountIds = new Set<string>();
|
|
58
|
+
for (const limit of record.limits) {
|
|
59
|
+
if (!limit || typeof limit !== "object") continue;
|
|
60
|
+
const scope = (limit as { scope?: unknown }).scope;
|
|
61
|
+
if (!scope || typeof scope !== "object") continue;
|
|
62
|
+
const accountId = (scope as { accountId?: unknown }).accountId;
|
|
63
|
+
if (typeof accountId === "string" && accountId.trim()) scopeAccountIds.add(accountId.trim());
|
|
64
|
+
}
|
|
65
|
+
if (scopeAccountIds.size > 1) return undefined;
|
|
66
|
+
const [scopeAccountId] = scopeAccountIds;
|
|
67
|
+
if (metadataAccountId && scopeAccountId && metadataAccountId !== scopeAccountId) return undefined;
|
|
68
|
+
return metadataAccountId ?? scopeAccountId;
|
|
69
|
+
}
|
|
70
|
+
|
|
44
71
|
export interface StatusLineSegmentOptions {
|
|
45
72
|
model?: { showThinkingLevel?: boolean; showContextPercent?: boolean };
|
|
46
73
|
path?: { abbreviate?: boolean; maxLength?: number; stripWorkPrefix?: boolean };
|
|
@@ -218,6 +245,7 @@ export class StatusLineComponent implements Component {
|
|
|
218
245
|
#cachedUsage: SegmentContext["usage"] = null;
|
|
219
246
|
#cachedUsageReports: unknown = null;
|
|
220
247
|
#cachedUsageProvider: string | undefined;
|
|
248
|
+
#cachedUsageAccountId: string | undefined;
|
|
221
249
|
#usageFetchedAt = 0;
|
|
222
250
|
#usageInFlight = false;
|
|
223
251
|
|
|
@@ -702,7 +730,12 @@ export class StatusLineComponent implements Component {
|
|
|
702
730
|
.then(reports => {
|
|
703
731
|
this.#cachedUsageReports = reports;
|
|
704
732
|
this.#cachedUsageProvider = this.#activeUsageProvider();
|
|
705
|
-
this.#
|
|
733
|
+
this.#cachedUsageAccountId = this.#activeCodexAccountId(this.#cachedUsageProvider);
|
|
734
|
+
this.#cachedUsage = this.#normalizeUsageReports(
|
|
735
|
+
reports,
|
|
736
|
+
this.#cachedUsageProvider,
|
|
737
|
+
this.#cachedUsageAccountId,
|
|
738
|
+
);
|
|
706
739
|
this.#usageFetchedAt = Date.now();
|
|
707
740
|
if (this.#onBranchChange) {
|
|
708
741
|
this.#onBranchChange();
|
|
@@ -720,10 +753,25 @@ export class StatusLineComponent implements Component {
|
|
|
720
753
|
});
|
|
721
754
|
}
|
|
722
755
|
|
|
723
|
-
#normalizeUsageReports(
|
|
724
|
-
|
|
725
|
-
|
|
756
|
+
#normalizeUsageReports(
|
|
757
|
+
reports: unknown,
|
|
758
|
+
activeProvider = this.#activeUsageProvider(),
|
|
759
|
+
activeCodexAccountId = this.#activeCodexAccountId(activeProvider),
|
|
760
|
+
): SegmentContext["usage"] {
|
|
726
761
|
if (!activeProvider || !Array.isArray(reports)) return null;
|
|
762
|
+
const activeCodexReportCount =
|
|
763
|
+
activeProvider === "openai-codex" && activeCodexAccountId
|
|
764
|
+
? reports.filter(report => {
|
|
765
|
+
if (!report || typeof report !== "object") return false;
|
|
766
|
+
const provider = (report as { provider?: unknown }).provider;
|
|
767
|
+
return (
|
|
768
|
+
typeof provider === "string" &&
|
|
769
|
+
resolveOAuthStorageProvider(provider) === activeProvider &&
|
|
770
|
+
usageReportAccountId(report) === activeCodexAccountId
|
|
771
|
+
);
|
|
772
|
+
}).length
|
|
773
|
+
: 0;
|
|
774
|
+
const ambiguousActiveCodexReports = activeCodexReportCount > 1;
|
|
727
775
|
const windows: NonNullable<SegmentContext["usage"]>["windows"] = [];
|
|
728
776
|
const seen = new Set<string>();
|
|
729
777
|
const now = Date.now();
|
|
@@ -759,6 +807,14 @@ export class StatusLineComponent implements Component {
|
|
|
759
807
|
const provider = (report as { provider?: unknown }).provider;
|
|
760
808
|
const providerId = typeof provider === "string" ? resolveOAuthStorageProvider(provider) : undefined;
|
|
761
809
|
if (providerId !== activeProvider) continue;
|
|
810
|
+
// Codex usage fetches cover every OAuth account; fail closed unless this session's account matches uniquely.
|
|
811
|
+
if (
|
|
812
|
+
providerId === "openai-codex" &&
|
|
813
|
+
(!activeCodexAccountId ||
|
|
814
|
+
ambiguousActiveCodexReports ||
|
|
815
|
+
usageReportAccountId(report) !== activeCodexAccountId)
|
|
816
|
+
)
|
|
817
|
+
continue;
|
|
762
818
|
const limits = (report as { limits?: unknown }).limits;
|
|
763
819
|
if (!Array.isArray(limits)) continue;
|
|
764
820
|
for (const limit of limits) {
|
|
@@ -808,11 +864,21 @@ export class StatusLineComponent implements Component {
|
|
|
808
864
|
return typeof provider === "string" && provider.length > 0 ? resolveOAuthStorageProvider(provider) : undefined;
|
|
809
865
|
}
|
|
810
866
|
|
|
867
|
+
#activeCodexAccountId(activeProvider: string | undefined): string | undefined {
|
|
868
|
+
if (activeProvider !== "openai-codex") return undefined;
|
|
869
|
+
const modelRegistry = this.session.modelRegistry;
|
|
870
|
+
return modelRegistry.authStorage.getOAuthAccountId(activeProvider, this.session.credentialSessionId, {
|
|
871
|
+
owner: modelRegistry.getAuthStorageOwner(),
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
|
|
811
875
|
#syncCachedUsageForActiveProvider(): void {
|
|
812
876
|
const activeProvider = this.#activeUsageProvider();
|
|
813
|
-
|
|
877
|
+
const activeCodexAccountId = this.#activeCodexAccountId(activeProvider);
|
|
878
|
+
if (this.#cachedUsageProvider === activeProvider && this.#cachedUsageAccountId === activeCodexAccountId) return;
|
|
814
879
|
this.#cachedUsageProvider = activeProvider;
|
|
815
|
-
this.#
|
|
880
|
+
this.#cachedUsageAccountId = activeCodexAccountId;
|
|
881
|
+
this.#cachedUsage = this.#normalizeUsageReports(this.#cachedUsageReports, activeProvider, activeCodexAccountId);
|
|
816
882
|
}
|
|
817
883
|
|
|
818
884
|
#buildSegmentContext(
|
|
@@ -14,9 +14,10 @@ interface UserMessageItem {
|
|
|
14
14
|
*/
|
|
15
15
|
class UserMessageList implements Component {
|
|
16
16
|
#selectedIndex: number = 0;
|
|
17
|
+
#selectionInFlight = false;
|
|
17
18
|
onSelect?: (entryId: string) => void;
|
|
18
19
|
onCancel?: () => void;
|
|
19
|
-
#
|
|
20
|
+
#availableRows = Number.POSITIVE_INFINITY;
|
|
20
21
|
|
|
21
22
|
constructor(private readonly messages: UserMessageItem[]) {
|
|
22
23
|
// Store messages in chronological order (oldest to newest)
|
|
@@ -24,6 +25,10 @@ class UserMessageList implements Component {
|
|
|
24
25
|
this.#selectedIndex = Math.max(0, this.messages.length - 1);
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
setAvailableRows(rows: number): void {
|
|
29
|
+
this.#availableRows = Math.max(3, rows);
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
invalidate(): void {
|
|
28
33
|
// No cached state to invalidate currently
|
|
29
34
|
}
|
|
@@ -36,12 +41,15 @@ class UserMessageList implements Component {
|
|
|
36
41
|
return lines;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
//
|
|
44
|
+
// Each entry uses two content rows plus a separator. Leave one row for
|
|
45
|
+
// the scroll position whenever the full history does not fit.
|
|
46
|
+
const needsScrollIndicator = this.messages.length * 3 > this.#availableRows;
|
|
47
|
+
const maxVisible = Math.max(1, Math.floor((this.#availableRows - (needsScrollIndicator ? 1 : 0)) / 3));
|
|
40
48
|
const startIndex = Math.max(
|
|
41
49
|
0,
|
|
42
|
-
Math.min(this.#selectedIndex - Math.floor(
|
|
50
|
+
Math.min(this.#selectedIndex - Math.floor(maxVisible / 2), this.messages.length - maxVisible),
|
|
43
51
|
);
|
|
44
|
-
const endIndex = Math.min(startIndex +
|
|
52
|
+
const endIndex = Math.min(startIndex + maxVisible, this.messages.length);
|
|
45
53
|
|
|
46
54
|
// Render visible messages (2 lines per message + blank line)
|
|
47
55
|
for (let i = startIndex; i < endIndex; i++) {
|
|
@@ -77,6 +85,7 @@ class UserMessageList implements Component {
|
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
handleInput(keyData: string): void {
|
|
88
|
+
if (this.#selectionInFlight) return;
|
|
80
89
|
// Up arrow - go to previous (older) message, wrap to bottom when at top
|
|
81
90
|
if (matchesKey(keyData, "up")) {
|
|
82
91
|
this.#selectedIndex = this.#selectedIndex === 0 ? this.messages.length - 1 : this.#selectedIndex - 1;
|
|
@@ -89,6 +98,7 @@ class UserMessageList implements Component {
|
|
|
89
98
|
else if (matchesKey(keyData, "enter") || matchesKey(keyData, "return") || keyData === "\n") {
|
|
90
99
|
const selected = this.messages[this.#selectedIndex];
|
|
91
100
|
if (selected && this.onSelect) {
|
|
101
|
+
this.#selectionInFlight = true;
|
|
92
102
|
this.onSelect(selected.id);
|
|
93
103
|
}
|
|
94
104
|
}
|
|
@@ -102,21 +112,43 @@ class UserMessageList implements Component {
|
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
/**
|
|
105
|
-
* Component that renders a
|
|
115
|
+
* Component that renders a prompt selector for creating a new session
|
|
106
116
|
*/
|
|
107
117
|
export class UserMessageSelectorComponent extends Container {
|
|
108
118
|
#messageList: UserMessageList;
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
#header: Container;
|
|
120
|
+
#footer: Container;
|
|
121
|
+
|
|
122
|
+
constructor(
|
|
123
|
+
messages: UserMessageItem[],
|
|
124
|
+
onSelect: (entryId: string) => void,
|
|
125
|
+
onCancel: () => void,
|
|
126
|
+
private readonly getViewportRows: () => number,
|
|
127
|
+
) {
|
|
111
128
|
super();
|
|
112
129
|
|
|
113
130
|
// Add header
|
|
114
|
-
this
|
|
115
|
-
this.addChild(new
|
|
116
|
-
this.addChild(new Text(theme.
|
|
117
|
-
this.addChild(
|
|
118
|
-
|
|
119
|
-
|
|
131
|
+
this.#header = new Container();
|
|
132
|
+
this.#header.addChild(new Spacer(1));
|
|
133
|
+
this.#header.addChild(new Text(theme.bold("Fork from Prompt"), 1, 0));
|
|
134
|
+
this.#header.addChild(
|
|
135
|
+
new Text(
|
|
136
|
+
theme.fg(
|
|
137
|
+
"muted",
|
|
138
|
+
"Creates a new session with history before the prompt; shared files stay in the same cwd.",
|
|
139
|
+
),
|
|
140
|
+
1,
|
|
141
|
+
0,
|
|
142
|
+
),
|
|
143
|
+
);
|
|
144
|
+
this.#header.addChild(
|
|
145
|
+
new Text(theme.fg("muted", "The selected prompt is restored for editing, not submitted."), 1, 0),
|
|
146
|
+
);
|
|
147
|
+
this.#header.addChild(new Text(theme.fg("muted", "↑/↓ move · Enter select · Esc cancel"), 1, 0));
|
|
148
|
+
this.#header.addChild(new Spacer(1));
|
|
149
|
+
this.#header.addChild(new DynamicBorder());
|
|
150
|
+
this.#header.addChild(new Spacer(1));
|
|
151
|
+
this.addChild(this.#header);
|
|
120
152
|
|
|
121
153
|
// Create message list
|
|
122
154
|
this.#messageList = new UserMessageList(messages);
|
|
@@ -126,8 +158,10 @@ export class UserMessageSelectorComponent extends Container {
|
|
|
126
158
|
this.addChild(this.#messageList);
|
|
127
159
|
|
|
128
160
|
// Add bottom border
|
|
129
|
-
this
|
|
130
|
-
this.addChild(new
|
|
161
|
+
this.#footer = new Container();
|
|
162
|
+
this.#footer.addChild(new Spacer(1));
|
|
163
|
+
this.#footer.addChild(new DynamicBorder());
|
|
164
|
+
this.addChild(this.#footer);
|
|
131
165
|
|
|
132
166
|
// Auto-cancel if no messages
|
|
133
167
|
if (messages.length === 0) {
|
|
@@ -135,6 +169,14 @@ export class UserMessageSelectorComponent extends Container {
|
|
|
135
169
|
}
|
|
136
170
|
}
|
|
137
171
|
|
|
172
|
+
render(width: number): string[] {
|
|
173
|
+
const chromeRows = this.#header.render(width).length + this.#footer.render(width).length;
|
|
174
|
+
// Reserve the pinned status/composer rows outside the overlay. Recompute
|
|
175
|
+
// against current terminal rows and wrapped header height on every render.
|
|
176
|
+
this.#messageList.setAvailableRows(this.getViewportRows() - chromeRows - 2);
|
|
177
|
+
return super.render(width);
|
|
178
|
+
}
|
|
179
|
+
|
|
138
180
|
getMessageList(): UserMessageList {
|
|
139
181
|
return this.#messageList;
|
|
140
182
|
}
|
|
@@ -38,7 +38,16 @@ import { replaceTabs } from "../../tools/render-utils";
|
|
|
38
38
|
import { getDisplayChangelogEntries } from "../../utils/changelog";
|
|
39
39
|
import { copyToClipboard } from "../../utils/clipboard";
|
|
40
40
|
import { openPath } from "../../utils/open";
|
|
41
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
beginSessionTitleGeneration,
|
|
43
|
+
invalidateSessionTitleGeneration,
|
|
44
|
+
isSessionTitleGenerationCurrent,
|
|
45
|
+
} from "../../utils/session-title-generation";
|
|
46
|
+
import {
|
|
47
|
+
buildConversationTitleInput,
|
|
48
|
+
generateSessionTitle,
|
|
49
|
+
setSessionTerminalTitle,
|
|
50
|
+
} from "../../utils/title-generator";
|
|
42
51
|
import { addChatChild, prepareTranscriptRebuild, syncPendingExecutionComponents } from "../utils/ui-helpers";
|
|
43
52
|
|
|
44
53
|
type HindsightModule = typeof import("../../hindsight");
|
|
@@ -84,6 +93,7 @@ export function buildHelpMarkdown(keybindings: Pick<KeybindingsManager, "getAcce
|
|
|
84
93
|
"| Resume another session | `/resume` |",
|
|
85
94
|
"| Show session details | `/session info` |",
|
|
86
95
|
"| Delete current session transcript/artifacts | `/session delete` |",
|
|
96
|
+
"| Fork from an earlier prompt into a new session | `/fork` |",
|
|
87
97
|
`| Select a model | \`/model\` or ${selectModelKey} |`,
|
|
88
98
|
`| Queue a message for the next turn | ${queueMessageKey} |`,
|
|
89
99
|
`| Select or edit a queued message | ${dequeueMessageKey} |`,
|
|
@@ -1109,31 +1119,7 @@ export class CommandController {
|
|
|
1109
1119
|
}
|
|
1110
1120
|
|
|
1111
1121
|
async handleForkCommand(): Promise<void> {
|
|
1112
|
-
|
|
1113
|
-
this.ctx.showWarning("Wait for the current response to finish or abort it before forking.");
|
|
1114
|
-
return;
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
const success = await this.ctx.session.fork();
|
|
1118
|
-
if (this.ctx.isStopped?.()) return;
|
|
1119
|
-
if (!success) {
|
|
1120
|
-
this.ctx.showError("Fork failed (session not persisted or cancelled)");
|
|
1121
|
-
return;
|
|
1122
|
-
}
|
|
1123
|
-
clearInteractiveActivityLoaders(this.ctx);
|
|
1124
|
-
stopInteractiveActivityIndicator(this.ctx, { foregroundSettled: true });
|
|
1125
|
-
this.ctx.resetIrcSidebarSession();
|
|
1126
|
-
|
|
1127
|
-
this.ctx.statusLine.invalidate();
|
|
1128
|
-
this.ctx.updateEditorTopBorder();
|
|
1129
|
-
|
|
1130
|
-
const sessionFile = this.ctx.session.sessionFile;
|
|
1131
|
-
const shortPath = sessionFile ? sessionFile.split("/").pop() : "new session";
|
|
1132
|
-
this.ctx.chatContainer.addChild(new Spacer(1));
|
|
1133
|
-
this.ctx.chatContainer.addChild(
|
|
1134
|
-
new Text(`${theme.fg("accent", `${theme.status.success} Session forked to ${shortPath}`)}`, 1, 1),
|
|
1135
|
-
);
|
|
1136
|
-
this.ctx.ui.requestRender();
|
|
1122
|
+
this.ctx.showUserMessageSelector();
|
|
1137
1123
|
}
|
|
1138
1124
|
|
|
1139
1125
|
async handleMoveCommand(targetPath: string): Promise<void> {
|
|
@@ -1186,23 +1172,63 @@ export class CommandController {
|
|
|
1186
1172
|
}
|
|
1187
1173
|
}
|
|
1188
1174
|
|
|
1189
|
-
async handleRenameCommand(title
|
|
1175
|
+
async handleRenameCommand(title?: string): Promise<void> {
|
|
1190
1176
|
try {
|
|
1177
|
+
if (!title?.trim()) {
|
|
1178
|
+
const generation = beginSessionTitleGeneration(this.ctx.sessionManager);
|
|
1179
|
+
const input = buildConversationTitleInput(this.ctx.session.messages);
|
|
1180
|
+
if (!input) {
|
|
1181
|
+
this.ctx.showError("Nothing to summarize yet — pass a title: /rename <title>");
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
const generated = await generateSessionTitle(
|
|
1186
|
+
input,
|
|
1187
|
+
this.ctx.session.modelRegistry,
|
|
1188
|
+
this.ctx.settings,
|
|
1189
|
+
this.ctx.session.credentialSessionId,
|
|
1190
|
+
this.ctx.session.model,
|
|
1191
|
+
provider => this.ctx.session.agent.metadataForProvider(provider),
|
|
1192
|
+
);
|
|
1193
|
+
if (
|
|
1194
|
+
!isSessionTitleGenerationCurrent(this.ctx.sessionManager, generation) ||
|
|
1195
|
+
buildConversationTitleInput(this.ctx.session.messages) !== input
|
|
1196
|
+
)
|
|
1197
|
+
return;
|
|
1198
|
+
if (!generated) {
|
|
1199
|
+
this.ctx.showError("Could not generate a session title — pass one: /rename <title>");
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
const stored = await this.ctx.sessionManager.setSessionName(generated, "user");
|
|
1204
|
+
if (!stored) {
|
|
1205
|
+
this.ctx.showError("Session name cannot be empty.");
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
this.#finishRename();
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
invalidateSessionTitleGeneration(this.ctx.sessionManager);
|
|
1191
1213
|
const stored = await this.ctx.sessionManager.setSessionName(title, "user");
|
|
1192
1214
|
if (!stored) {
|
|
1193
1215
|
this.ctx.showError("Session name cannot be empty.");
|
|
1194
1216
|
return;
|
|
1195
1217
|
}
|
|
1196
|
-
|
|
1197
|
-
setSessionTerminalTitle(name, this.ctx.sessionManager.getCwd());
|
|
1198
|
-
this.ctx.statusLine.invalidate();
|
|
1199
|
-
this.ctx.updateEditorBorderColor();
|
|
1200
|
-
this.ctx.showStatus(`Session renamed to "${name}".`);
|
|
1218
|
+
this.#finishRename();
|
|
1201
1219
|
} catch (err) {
|
|
1202
1220
|
this.ctx.showError(`Rename failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1203
1221
|
}
|
|
1204
1222
|
}
|
|
1205
1223
|
|
|
1224
|
+
#finishRename(): void {
|
|
1225
|
+
const name = this.ctx.sessionManager.getSessionName()!;
|
|
1226
|
+
setSessionTerminalTitle(name, this.ctx.sessionManager.getCwd());
|
|
1227
|
+
this.ctx.statusLine.invalidate();
|
|
1228
|
+
this.ctx.updateEditorBorderColor();
|
|
1229
|
+
this.ctx.showStatus(`Session renamed to "${name}".`);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1206
1232
|
async handleBashCommand(command: string, excludeFromContext = false): Promise<void> {
|
|
1207
1233
|
const isDeferred = this.ctx.session.isStreaming;
|
|
1208
1234
|
const component = new BashExecutionComponent(command, this.ctx.ui, excludeFromContext);
|
|
@@ -146,31 +146,55 @@ export class ExtensionUiController {
|
|
|
146
146
|
const widgetsBelow = [...this.#hookWidgetsBelow.entries()];
|
|
147
147
|
const activeHookCustomComponent = this.#activeHookCustomComponent;
|
|
148
148
|
const activeHookCustomOverlay = this.#activeHookCustomOverlay;
|
|
149
|
+
const activeHookCustomCancel = this.#activeHookCustomCancel;
|
|
149
150
|
return () => {
|
|
151
|
+
const errors: unknown[] = [];
|
|
152
|
+
const attempt = (cleanup: () => void): void => {
|
|
153
|
+
try {
|
|
154
|
+
cleanup();
|
|
155
|
+
} catch (error) {
|
|
156
|
+
errors.push(error);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
150
159
|
for (const unsubscribe of terminalInputUnsubscribers) {
|
|
151
|
-
unsubscribe
|
|
152
|
-
|
|
160
|
+
if (!this.#extensionTerminalInputUnsubscribers.delete(unsubscribe)) continue;
|
|
161
|
+
attempt(unsubscribe);
|
|
153
162
|
}
|
|
154
163
|
let widgetsChanged = false;
|
|
155
164
|
for (const [key, widget] of widgetsAbove) {
|
|
156
165
|
if (this.#hookWidgetsAbove.get(key) !== widget) continue;
|
|
157
166
|
this.#hookWidgetsAbove.delete(key);
|
|
158
|
-
widget.dispose?.();
|
|
167
|
+
attempt(() => widget.dispose?.());
|
|
159
168
|
widgetsChanged = true;
|
|
160
169
|
}
|
|
161
170
|
for (const [key, widget] of widgetsBelow) {
|
|
162
171
|
if (this.#hookWidgetsBelow.get(key) !== widget) continue;
|
|
163
172
|
this.#hookWidgetsBelow.delete(key);
|
|
164
|
-
widget.dispose?.();
|
|
173
|
+
attempt(() => widget.dispose?.());
|
|
165
174
|
widgetsChanged = true;
|
|
166
175
|
}
|
|
167
176
|
if (
|
|
168
177
|
this.#activeHookCustomComponent === activeHookCustomComponent &&
|
|
169
|
-
this.#activeHookCustomOverlay === activeHookCustomOverlay
|
|
178
|
+
this.#activeHookCustomOverlay === activeHookCustomOverlay &&
|
|
179
|
+
this.#activeHookCustomCancel === activeHookCustomCancel
|
|
170
180
|
) {
|
|
171
|
-
this.#
|
|
181
|
+
this.#activeHookCustomComponent = undefined;
|
|
182
|
+
this.#activeHookCustomOverlay = undefined;
|
|
183
|
+
this.#activeHookCustomCancel = undefined;
|
|
184
|
+
attempt(() => activeHookCustomCancel?.());
|
|
185
|
+
attempt(() => activeHookCustomComponent?.dispose?.());
|
|
186
|
+
attempt(() => activeHookCustomOverlay?.hide());
|
|
187
|
+
}
|
|
188
|
+
if (widgetsChanged) {
|
|
189
|
+
attempt(() =>
|
|
190
|
+
this.#renderHookWidgetContainer(this.ctx.hookWidgetContainerAbove, this.#hookWidgetsAbove, true),
|
|
191
|
+
);
|
|
192
|
+
attempt(() =>
|
|
193
|
+
this.#renderHookWidgetContainer(this.ctx.hookWidgetContainerBelow, this.#hookWidgetsBelow, false),
|
|
194
|
+
);
|
|
195
|
+
attempt(() => this.ctx.ui.requestRender());
|
|
172
196
|
}
|
|
173
|
-
if (
|
|
197
|
+
if (errors.length > 0) throw new AggregateError(errors, "Previous session extension UI cleanup failed");
|
|
174
198
|
};
|
|
175
199
|
}
|
|
176
200
|
|
|
@@ -551,6 +575,7 @@ export class ExtensionUiController {
|
|
|
551
575
|
getCredentialSessionId: () => this.ctx.session.credentialSessionId,
|
|
552
576
|
isIdle: () => !this.ctx.session.isStreaming,
|
|
553
577
|
getActivePromptHandle: () => this.ctx.session.activePromptHandle,
|
|
578
|
+
getSessionWorkLease: () => this.ctx.session.sessionWorkLease,
|
|
554
579
|
abort: () => this.ctx.session.abort(),
|
|
555
580
|
abortPromptAndWait: (handle, options) => this.ctx.session.abortPromptAndWait(handle, options),
|
|
556
581
|
hasPendingMessages: () => this.ctx.session.queuedMessageCount > 0,
|
|
@@ -781,6 +806,7 @@ export class ExtensionUiController {
|
|
|
781
806
|
getCredentialSessionId: () => this.ctx.session.credentialSessionId,
|
|
782
807
|
isIdle: () => !this.ctx.session.isStreaming,
|
|
783
808
|
getActivePromptHandle: () => this.ctx.session.activePromptHandle,
|
|
809
|
+
getSessionWorkLease: () => this.ctx.session.sessionWorkLease,
|
|
784
810
|
abort: () => this.ctx.session.abort(),
|
|
785
811
|
abortPromptAndWait: (handle, options) => this.ctx.session.abortPromptAndWait(handle, options),
|
|
786
812
|
hasPendingMessages: () => this.ctx.session.queuedMessageCount > 0,
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
locatePastedImageReferenceAroundCursor,
|
|
34
34
|
parsePastedImagePaths,
|
|
35
35
|
} from "../../utils/pasted-image-path";
|
|
36
|
+
import { invalidateSessionTitleGeneration } from "../../utils/session-title-generation";
|
|
36
37
|
import { generateSessionTitle, setSessionTerminalTitle } from "../../utils/title-generator";
|
|
37
38
|
import { ActionRegistry, APP_ACTION_METADATA } from "../action-registry";
|
|
38
39
|
import { CommandPalette, type CommandPaletteAction, type CommandPaletteEntry } from "../components/command-palette";
|
|
@@ -1146,6 +1147,7 @@ export class InputController {
|
|
|
1146
1147
|
|
|
1147
1148
|
// Queue input during compaction
|
|
1148
1149
|
if (this.ctx.session.isCompacting) {
|
|
1150
|
+
invalidateSessionTitleGeneration(this.ctx.sessionManager);
|
|
1149
1151
|
if ((inputImages?.length ?? 0) > 0) {
|
|
1150
1152
|
this.ctx.showStatus("Compaction in progress. Retry after it completes to send images.");
|
|
1151
1153
|
return;
|
|
@@ -1159,6 +1161,7 @@ export class InputController {
|
|
|
1159
1161
|
// prompt to run after the active turn completes (in submission order).
|
|
1160
1162
|
// This handles extension commands (execute immediately), prompt template expansion, and queueing
|
|
1161
1163
|
if (this.ctx.session.isStreaming) {
|
|
1164
|
+
invalidateSessionTitleGeneration(this.ctx.sessionManager);
|
|
1162
1165
|
if (this.#canModifyComposer(composer)) {
|
|
1163
1166
|
this.ctx.editor.addToHistory(text);
|
|
1164
1167
|
this.ctx.editor.setText("");
|
|
@@ -1183,6 +1186,7 @@ export class InputController {
|
|
|
1183
1186
|
}
|
|
1184
1187
|
|
|
1185
1188
|
// Normal message submission
|
|
1189
|
+
invalidateSessionTitleGeneration(this.ctx.sessionManager);
|
|
1186
1190
|
// First, move any pending bash components to chat
|
|
1187
1191
|
this.ctx.flushPendingBashComponents();
|
|
1188
1192
|
|
|
@@ -1606,7 +1606,7 @@ export class MCPCommandController {
|
|
|
1606
1606
|
if (!this.ctx.mcpManager) {
|
|
1607
1607
|
return;
|
|
1608
1608
|
}
|
|
1609
|
-
if (this.ctx.mcpManager.
|
|
1609
|
+
if (this.ctx.mcpManager.isConnectionSetMutationBlocked()) {
|
|
1610
1610
|
throw new Error("This session's plugin-bundle MCP connections are fixed for its lifetime.");
|
|
1611
1611
|
}
|
|
1612
1612
|
|