@code-yeongyu/senpi 2026.9.10 → 2026.9.11
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 +83 -0
- package/dist/core/agent-session.d.ts +57 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +130 -20
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +2 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +49 -17
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/brand.d.ts +5 -0
- package/dist/core/brand.d.ts.map +1 -1
- package/dist/core/brand.js +13 -0
- package/dist/core/brand.js.map +1 -1
- package/dist/core/changelog-source.d.ts +8 -0
- package/dist/core/changelog-source.d.ts.map +1 -0
- package/dist/core/changelog-source.js +19 -0
- package/dist/core/changelog-source.js.map +1 -0
- package/dist/core/credential-accounts.d.ts +3 -0
- package/dist/core/credential-accounts.d.ts.map +1 -1
- package/dist/core/credential-accounts.js +20 -1
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +8 -0
- package/dist/core/credential-pool/classify.js.map +1 -1
- package/dist/core/extensions/builtin/account/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/account/index.js +7 -3
- package/dist/core/extensions/builtin/account/index.js.map +1 -1
- package/dist/core/extensions/builtin/account-display-name.d.ts +7 -0
- package/dist/core/extensions/builtin/account-display-name.d.ts.map +1 -0
- package/dist/core/extensions/builtin/account-display-name.js +40 -0
- package/dist/core/extensions/builtin/account-display-name.js.map +1 -0
- package/dist/core/extensions/builtin/ask-user/format.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/format.js +7 -2
- package/dist/core/extensions/builtin/ask-user/format.js.map +1 -1
- package/dist/core/extensions/builtin/ask-user/pending.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ask-user/pending.js +3 -0
- package/dist/core/extensions/builtin/ask-user/pending.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js +21 -9
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-command.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js +11 -6
- package/dist/core/extensions/builtin/claude-sdk-oauth/account-management.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts +9 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js +10 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/accounts.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js +3 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-binding.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js +19 -10
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-reattach.js.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js +3 -9
- package/dist/core/extensions/builtin/claude-sdk-oauth/settings.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/routine-settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/config-reload/routine-settings.js +1 -0
- package/dist/core/extensions/builtin/config-reload/routine-settings.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js +5 -3
- package/dist/core/extensions/builtin/cursor-cli-oauth/account-command.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/accounts.js.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js +3 -9
- package/dist/core/extensions/builtin/cursor-cli-oauth/settings.js.map +1 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.js +13 -1
- package/dist/core/extensions/builtin/goal/agent-end-continuation.js.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/prompt.js +11 -8
- package/dist/core/extensions/builtin/goal/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/terminal-provider-error.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/terminal-provider-error.js +28 -0
- package/dist/core/extensions/builtin/goal/terminal-provider-error.js.map +1 -1
- package/dist/core/extensions/builtin/goal/todo-gate.js +2 -2
- package/dist/core/extensions/builtin/goal/todo-gate.js.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js +2 -2
- package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
- package/dist/core/extensions/builtin/gpt-account.d.ts.map +1 -1
- package/dist/core/extensions/builtin/gpt-account.js +19 -8
- package/dist/core/extensions/builtin/gpt-account.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js +19 -0
- package/dist/core/extensions/builtin/prompt-preset/deepseek-v4-1-flash.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts +6 -6
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +26 -7
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +29 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
- package/dist/core/high-reasoning-warning.d.ts.map +1 -1
- package/dist/core/high-reasoning-warning.js +5 -1
- package/dist/core/high-reasoning-warning.js.map +1 -1
- package/dist/core/manual-continue.d.ts +14 -0
- package/dist/core/manual-continue.d.ts.map +1 -1
- package/dist/core/manual-continue.js +13 -0
- package/dist/core/manual-continue.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +2 -2
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/remote-catalog-merge.d.ts +16 -0
- package/dist/core/remote-catalog-merge.d.ts.map +1 -0
- package/dist/core/remote-catalog-merge.js +75 -0
- package/dist/core/remote-catalog-merge.js.map +1 -0
- package/dist/core/remote-catalog-provider.d.ts +3 -0
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +12 -40
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/session-entry-materializer.d.ts +12 -0
- package/dist/core/session-entry-materializer.d.ts.map +1 -0
- package/dist/core/session-entry-materializer.js +26 -0
- package/dist/core/session-entry-materializer.js.map +1 -0
- package/dist/core/session-manager.d.ts +36 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +38 -8
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +10 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/app-server/daemon/process.d.ts +6 -1
- package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
- package/dist/modes/app-server/daemon/process.js +23 -4
- package/dist/modes/app-server/daemon/process.js.map +1 -1
- package/dist/modes/app-server/protocol/account.d.ts +2 -0
- package/dist/modes/app-server/protocol/account.d.ts.map +1 -1
- package/dist/modes/app-server/protocol/account.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-keys.d.ts +1 -1
- package/dist/modes/interactive/components/ask-user-question-keys.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-keys.js +65 -17
- package/dist/modes/interactive/components/ask-user-question-keys.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-render.d.ts +2 -1
- package/dist/modes/interactive/components/ask-user-question-render.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-render.js +39 -9
- package/dist/modes/interactive/components/ask-user-question-render.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-state.d.ts +14 -4
- package/dist/modes/interactive/components/ask-user-question-state.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-question-state.js +63 -6
- package/dist/modes/interactive/components/ask-user-question-state.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-question.d.ts +2 -0
- package/dist/modes/interactive/components/ask-user-question.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-question.js +27 -14
- package/dist/modes/interactive/components/ask-user-question.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +51 -19
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +11 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +29 -9
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +7 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/help-content.d.ts.map +1 -1
- package/dist/modes/interactive/help-content.js +4 -0
- package/dist/modes/interactive/help-content.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +13 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +44 -15
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/input-tips.js +1 -1
- package/dist/modes/interactive/tips/catalog/input-tips.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +3 -1
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/connection-question-bridge.js +1 -1
- package/dist/modes/rpc/connection-question-bridge.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +33 -11
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +14 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +31 -5
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +2 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/changelog.d.ts +3 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +89 -23
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/paths.d.ts +5 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -1
- package/dist/utils/paths.js.map +1 -1
- package/docs/app-server.md +6 -0
- package/docs/extensions.md +19 -3
- package/docs/rpc.md +10 -0
- package/docs/settings.md +2 -1
- package/docs/tui.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +28 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +5 -4
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output-buffer.ts +58 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/output/streaming-output.ts +9 -64
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt-template.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts +17 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js +90 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js +71 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/frames.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts +873 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js +303 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts +12 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js +35 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js +116 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js +153 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts +12 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/types.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts +14 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js +162 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.lazy.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts +25 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js +124 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-callback.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js +101 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin-token.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts +14 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js +111 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-coding.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js +86 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/kimi-identity.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/load.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts +51 -4
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js +196 -7
- package/node_modules/@earendil-works/pi-ai/dist/auth/pool/slots.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/resolve.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts +9 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/bun-oauth.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat.js +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +4 -4
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +14 -5
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/huggingface.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts +12 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js +62 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +10 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +28 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +3 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js +55 -16
- package/node_modules/@earendil-works/pi-tui/dist/dollar-invocation-autocomplete.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -12,10 +12,12 @@ export type QuestionDraft = {
|
|
|
12
12
|
answers?: QuestionAnswers;
|
|
13
13
|
comment?: string;
|
|
14
14
|
};
|
|
15
|
-
export type QuestionFocus = "options" | "own-answer" | "
|
|
16
|
-
export declare const COMMENT_LABEL = "Comment (
|
|
15
|
+
export type QuestionFocus = "options" | "own-answer" | "submit";
|
|
16
|
+
export declare const COMMENT_LABEL = "Comment (optional; unanswered questions are reported)";
|
|
17
17
|
export declare const OWN_ANSWER_LABEL = "Type your own answer...";
|
|
18
18
|
export declare const NOT_ANSWERED_NOTICE = "You have not answered all questions";
|
|
19
|
+
export declare const DISMISS_NOTICE = "Press Esc again to dismiss (answers will be discarded)";
|
|
20
|
+
export declare const PARTIAL_SUBMIT_NOTICE = "Press Enter again to submit with unanswered questions";
|
|
19
21
|
/** Countdown chip label: minutes above five minutes, mm:ss at or below. */
|
|
20
22
|
export declare function formatCountdownLabel(remainingMs: number): string;
|
|
21
23
|
export declare class AskUserQuestionState {
|
|
@@ -25,6 +27,7 @@ export declare class AskUserQuestionState {
|
|
|
25
27
|
focus: QuestionFocus;
|
|
26
28
|
notice: string | undefined;
|
|
27
29
|
comment: string | undefined;
|
|
30
|
+
private dismissPending;
|
|
28
31
|
private readonly selected;
|
|
29
32
|
private readonly texts;
|
|
30
33
|
constructor(request: QuestionRequest);
|
|
@@ -32,7 +35,14 @@ export declare class AskUserQuestionState {
|
|
|
32
35
|
/** Highlightable rows for the active question: options plus the own-answer row. */
|
|
33
36
|
get ownAnswerRowIndex(): number;
|
|
34
37
|
get rowCount(): number;
|
|
38
|
+
get activeTabIndex(): number;
|
|
35
39
|
switchQuestion(delta: number): void;
|
|
40
|
+
switchTab(delta: number): void;
|
|
41
|
+
advance(): void;
|
|
42
|
+
returnToOptions(): void;
|
|
43
|
+
requestDismiss(): "confirm" | "cancel";
|
|
44
|
+
acceptPartialSubmit(): void;
|
|
45
|
+
private hasDraft;
|
|
36
46
|
selectedFor(questionId: string): string[];
|
|
37
47
|
textFor(questionId: string): string | undefined;
|
|
38
48
|
isSelected(questionId: string, label: string): boolean;
|
|
@@ -44,8 +54,8 @@ export declare class AskUserQuestionState {
|
|
|
44
54
|
setOwnAnswer(questionId: string, text: string): void;
|
|
45
55
|
answers(): QuestionAnswers;
|
|
46
56
|
unanswered(): string[];
|
|
47
|
-
/** Submit outcome: comment wins, then
|
|
48
|
-
submitOutcome(): "answered" | "comment-submitted" | undefined;
|
|
57
|
+
/** Submit outcome: comment wins, then answers; undefined means stay open. */
|
|
58
|
+
submitOutcome(forcePartial?: boolean): "answered" | "comment-submitted" | undefined;
|
|
49
59
|
buildResponse(status: QuestionResponse["status"], autoResolvedAfterMs?: number): QuestionResponse;
|
|
50
60
|
refreshDraft(): QuestionDraft;
|
|
51
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user-question-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE3F,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"ask-user-question-state.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAE3F,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC1D,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC5E,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEhE,eAAO,MAAM,aAAa,0DAA0D,CAAC;AACrF,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAC1D,eAAO,MAAM,mBAAmB,wCAAwC,CAAC;AACzE,eAAO,MAAM,cAAc,2DAA2D,CAAC;AACvF,eAAO,MAAM,qBAAqB,0DAA0D,CAAC;AAE7F,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED,qBAAa,oBAAoB;IAChC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,WAAW,SAAK;IAChB,cAAc,SAAK;IACnB,KAAK,EAAE,aAAa,CAAa;IACjC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAEnD,YAAY,OAAO,EAAE,eAAe,EAEnC;IAED,IAAI,cAAc,IAAI,eAAe,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAEzD;IAED,mFAAmF;IACnF,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAElC;IAED,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAY7B;IAED,OAAO,IAAI,IAAI,CAYd;IAED,eAAe,IAAI,IAAI,CAKtB;IAED,cAAc,IAAI,SAAS,GAAG,QAAQ,CAQrC;IAED,mBAAmB,IAAI,IAAI,CAG1B;IAED,OAAO,CAAC,QAAQ;IAKhB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAExC;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE9C;IAED,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;IAED,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAGtC;IAED,aAAa,IAAI,MAAM,CAEtB;IAED,0EAA0E;IAC1E,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAatD;IAED,2EAA2E;IAC3E,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnD;IAED,OAAO,IAAI,eAAe,CASzB;IAED,UAAU,IAAI,MAAM,EAAE,CAErB;IAED,6EAA6E;IAC7E,aAAa,CAAC,YAAY,UAAQ,GAAG,UAAU,GAAG,mBAAmB,GAAG,SAAS,CAMhF;IAED,aAAa,CAAC,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAShG;IAED,YAAY,IAAI,aAAa,CAM5B;CACD"}
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* live in ask-user-question.ts; this module must stay free of pi-tui imports
|
|
7
7
|
* so the rules are unit-testable headless.
|
|
8
8
|
*/
|
|
9
|
-
export const COMMENT_LABEL = "Comment (
|
|
9
|
+
export const COMMENT_LABEL = "Comment (optional; unanswered questions are reported)";
|
|
10
10
|
export const OWN_ANSWER_LABEL = "Type your own answer...";
|
|
11
11
|
export const NOT_ANSWERED_NOTICE = "You have not answered all questions";
|
|
12
|
+
export const DISMISS_NOTICE = "Press Esc again to dismiss (answers will be discarded)";
|
|
13
|
+
export const PARTIAL_SUBMIT_NOTICE = "Press Enter again to submit with unanswered questions";
|
|
12
14
|
/** Countdown chip label: minutes above five minutes, mm:ss at or below. */
|
|
13
15
|
export function formatCountdownLabel(remainingMs) {
|
|
14
16
|
const totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));
|
|
@@ -23,6 +25,7 @@ export class AskUserQuestionState {
|
|
|
23
25
|
this.activeIndex = 0;
|
|
24
26
|
this.highlightIndex = 0;
|
|
25
27
|
this.focus = "options";
|
|
28
|
+
this.dismissPending = false;
|
|
26
29
|
this.selected = new Map();
|
|
27
30
|
this.texts = new Map();
|
|
28
31
|
this.request = request;
|
|
@@ -37,13 +40,63 @@ export class AskUserQuestionState {
|
|
|
37
40
|
get rowCount() {
|
|
38
41
|
return this.ownAnswerRowIndex + 1;
|
|
39
42
|
}
|
|
43
|
+
get activeTabIndex() {
|
|
44
|
+
return this.focus === "submit" ? this.request.questions.length : this.activeIndex;
|
|
45
|
+
}
|
|
40
46
|
switchQuestion(delta) {
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
this.switchTab(delta);
|
|
48
|
+
}
|
|
49
|
+
switchTab(delta) {
|
|
50
|
+
const count = this.request.questions.length + 1;
|
|
51
|
+
const next = (this.activeTabIndex + delta + count) % count;
|
|
52
|
+
if (next === this.request.questions.length) {
|
|
53
|
+
this.focus = "submit";
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.focus = "options";
|
|
57
|
+
this.activeIndex = next;
|
|
58
|
+
this.highlightIndex = 0;
|
|
59
|
+
}
|
|
60
|
+
this.dismissPending = false;
|
|
61
|
+
this.notice = undefined;
|
|
62
|
+
}
|
|
63
|
+
advance() {
|
|
64
|
+
if (this.activeIndex + 1 < this.request.questions.length) {
|
|
65
|
+
this.activeIndex += 1;
|
|
66
|
+
this.highlightIndex = 0;
|
|
67
|
+
this.notice = undefined;
|
|
68
|
+
this.dismissPending = false;
|
|
43
69
|
return;
|
|
44
|
-
|
|
70
|
+
}
|
|
71
|
+
this.focus = "submit";
|
|
72
|
+
this.highlightIndex = 0;
|
|
73
|
+
this.notice = undefined;
|
|
74
|
+
this.dismissPending = false;
|
|
75
|
+
}
|
|
76
|
+
returnToOptions() {
|
|
77
|
+
this.focus = "options";
|
|
45
78
|
this.highlightIndex = 0;
|
|
46
79
|
this.notice = undefined;
|
|
80
|
+
this.dismissPending = false;
|
|
81
|
+
}
|
|
82
|
+
requestDismiss() {
|
|
83
|
+
if (!this.hasDraft())
|
|
84
|
+
return "cancel";
|
|
85
|
+
if (!this.dismissPending) {
|
|
86
|
+
this.dismissPending = true;
|
|
87
|
+
this.notice = DISMISS_NOTICE;
|
|
88
|
+
return "confirm";
|
|
89
|
+
}
|
|
90
|
+
return "cancel";
|
|
91
|
+
}
|
|
92
|
+
acceptPartialSubmit() {
|
|
93
|
+
this.dismissPending = false;
|
|
94
|
+
this.notice = undefined;
|
|
95
|
+
}
|
|
96
|
+
hasDraft() {
|
|
97
|
+
if ((this.comment ?? "").trim() !== "")
|
|
98
|
+
return true;
|
|
99
|
+
return this.request.questions.some((question) => this.isAnswered(question.id));
|
|
47
100
|
}
|
|
48
101
|
selectedFor(questionId) {
|
|
49
102
|
return this.selected.get(questionId) ?? [];
|
|
@@ -105,12 +158,16 @@ export class AskUserQuestionState {
|
|
|
105
158
|
unanswered() {
|
|
106
159
|
return this.request.questions.filter((question) => !this.isAnswered(question.id)).map((q) => q.id);
|
|
107
160
|
}
|
|
108
|
-
/** Submit outcome: comment wins, then
|
|
109
|
-
submitOutcome() {
|
|
161
|
+
/** Submit outcome: comment wins, then answers; undefined means stay open. */
|
|
162
|
+
submitOutcome(forcePartial = false) {
|
|
110
163
|
if ((this.comment ?? "").trim() !== "")
|
|
111
164
|
return "comment-submitted";
|
|
112
165
|
if (this.unanswered().length === 0)
|
|
113
166
|
return "answered";
|
|
167
|
+
if (this.answeredCount() > 0)
|
|
168
|
+
return "answered";
|
|
169
|
+
if (forcePartial)
|
|
170
|
+
return "answered";
|
|
114
171
|
return undefined;
|
|
115
172
|
}
|
|
116
173
|
buildResponse(status, autoResolvedAfterMs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user-question-state.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure interaction state for the ask-user question overlay.\n *\n * Owns per-question selections, own-answer texts, the active tab, the\n * highlighted row and the response-building rules. Rendering and key decoding\n * live in ask-user-question.ts; this module must stay free of pi-tui imports\n * so the rules are unit-testable headless.\n */\n\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\n\nexport type QuestionAnswers = QuestionResponse[\"answers\"];\nexport type QuestionDraft = { answers?: QuestionAnswers; comment?: string };\nexport type QuestionFocus = \"options\" | \"own-answer\" | \"comment\";\n\nexport const COMMENT_LABEL = \"Comment (sent as your reply; other questions stay unanswered)\";\nexport const OWN_ANSWER_LABEL = \"Type your own answer...\";\nexport const NOT_ANSWERED_NOTICE = \"You have not answered all questions\";\n\n/** Countdown chip label: minutes above five minutes, mm:ss at or below. */\nexport function formatCountdownLabel(remainingMs: number): string {\n\tconst totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));\n\tif (totalSeconds >= 300) return `${Math.ceil(totalSeconds / 60)}m`;\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst seconds = totalSeconds % 60;\n\treturn `${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nexport class AskUserQuestionState {\n\treadonly request: QuestionRequest;\n\tactiveIndex = 0;\n\thighlightIndex = 0;\n\tfocus: QuestionFocus = \"options\";\n\tnotice: string | undefined;\n\tcomment: string | undefined;\n\tprivate readonly selected = new Map<string, string[]>();\n\tprivate readonly texts = new Map<string, string>();\n\n\tconstructor(request: QuestionRequest) {\n\t\tthis.request = request;\n\t}\n\n\tget activeQuestion(): QuestionRequest[\"questions\"][number] {\n\t\treturn this.request.questions[this.activeIndex];\n\t}\n\n\t/** Highlightable rows for the active question: options plus the own-answer row. */\n\tget ownAnswerRowIndex(): number {\n\t\treturn this.activeQuestion.options.length;\n\t}\n\n\tget rowCount(): number {\n\t\treturn this.ownAnswerRowIndex + 1;\n\t}\n\n\tswitchQuestion(delta: number): void {\n\t\tconst count = this.request.questions.length;\n\t\tif (count <= 1) return;\n\t\tthis.activeIndex = (this.activeIndex + delta + count) % count;\n\t\tthis.highlightIndex = 0;\n\t\tthis.notice = undefined;\n\t}\n\n\tselectedFor(questionId: string): string[] {\n\t\treturn this.selected.get(questionId) ?? [];\n\t}\n\n\ttextFor(questionId: string): string | undefined {\n\t\treturn this.texts.get(questionId);\n\t}\n\n\tisSelected(questionId: string, label: string): boolean {\n\t\treturn this.selectedFor(questionId).includes(label);\n\t}\n\n\tisAnswered(questionId: string): boolean {\n\t\tif (this.selectedFor(questionId).length > 0) return true;\n\t\treturn (this.texts.get(questionId) ?? \"\").trim() !== \"\";\n\t}\n\n\tansweredCount(): number {\n\t\treturn this.request.questions.filter((question) => this.isAnswered(question.id)).length;\n\t}\n\n\t/** Select (single) or toggle (multi) an option of the active question. */\n\tactivateOption(questionId: string, label: string): void {\n\t\tconst question = this.request.questions.find((entry) => entry.id === questionId);\n\t\tif (!question?.options.some((option) => option.label === label)) return;\n\t\tif (question.multiSelect) {\n\t\t\tconst next = [...this.selectedFor(questionId)];\n\t\t\tconst index = next.indexOf(label);\n\t\t\tif (index >= 0) next.splice(index, 1);\n\t\t\telse next.push(label);\n\t\t\tthis.selected.set(questionId, next);\n\t\t} else {\n\t\t\tthis.selected.set(questionId, [label]);\n\t\t}\n\t\tthis.notice = undefined;\n\t}\n\n\t/** Replace the question's answer with typed text; empty text clears it. */\n\tsetOwnAnswer(questionId: string, text: string): void {\n\t\tconst trimmed = text.trim();\n\t\tthis.selected.delete(questionId);\n\t\tif (trimmed === \"\") this.texts.delete(questionId);\n\t\telse this.texts.set(questionId, trimmed);\n\t\tthis.notice = undefined;\n\t}\n\n\tanswers(): QuestionAnswers {\n\t\tconst result: QuestionAnswers = {};\n\t\tfor (const question of this.request.questions) {\n\t\t\tconst selected = this.selectedFor(question.id);\n\t\t\tconst text = this.texts.get(question.id);\n\t\t\tif (selected.length === 0 && text === undefined) continue;\n\t\t\tresult[question.id] = { selected, ...(text !== undefined ? { text } : {}) };\n\t\t}\n\t\treturn result;\n\t}\n\n\tunanswered(): string[] {\n\t\treturn this.request.questions.filter((question) => !this.isAnswered(question.id)).map((q) => q.id);\n\t}\n\n\t/** Submit outcome: comment wins, then completeness; undefined means stay open. */\n\tsubmitOutcome(): \"answered\" | \"comment-submitted\" | undefined {\n\t\tif ((this.comment ?? \"\").trim() !== \"\") return \"comment-submitted\";\n\t\tif (this.unanswered().length === 0) return \"answered\";\n\t\treturn undefined;\n\t}\n\n\tbuildResponse(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): QuestionResponse {\n\t\tconst comment = this.comment !== undefined && this.comment.trim() !== \"\" ? this.comment : undefined;\n\t\treturn {\n\t\t\tstatus,\n\t\t\tanswers: this.answers(),\n\t\t\t...(comment !== undefined ? { comment } : {}),\n\t\t\tunanswered: this.unanswered(),\n\t\t\t...(autoResolvedAfterMs !== undefined ? { autoResolvedAfterMs } : {}),\n\t\t};\n\t}\n\n\trefreshDraft(): QuestionDraft {\n\t\tconst comment = this.comment !== undefined && this.comment.trim() !== \"\" ? this.comment : undefined;\n\t\treturn {\n\t\t\tanswers: this.answers(),\n\t\t\t...(comment !== undefined ? { comment } : {}),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ask-user-question-state.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pure interaction state for the ask-user question overlay.\n *\n * Owns per-question selections, own-answer texts, the active tab, the\n * highlighted row and the response-building rules. Rendering and key decoding\n * live in ask-user-question.ts; this module must stay free of pi-tui imports\n * so the rules are unit-testable headless.\n */\n\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\n\nexport type QuestionAnswers = QuestionResponse[\"answers\"];\nexport type QuestionDraft = { answers?: QuestionAnswers; comment?: string };\nexport type QuestionFocus = \"options\" | \"own-answer\" | \"submit\";\n\nexport const COMMENT_LABEL = \"Comment (optional; unanswered questions are reported)\";\nexport const OWN_ANSWER_LABEL = \"Type your own answer...\";\nexport const NOT_ANSWERED_NOTICE = \"You have not answered all questions\";\nexport const DISMISS_NOTICE = \"Press Esc again to dismiss (answers will be discarded)\";\nexport const PARTIAL_SUBMIT_NOTICE = \"Press Enter again to submit with unanswered questions\";\n\n/** Countdown chip label: minutes above five minutes, mm:ss at or below. */\nexport function formatCountdownLabel(remainingMs: number): string {\n\tconst totalSeconds = Math.max(0, Math.ceil(remainingMs / 1000));\n\tif (totalSeconds >= 300) return `${Math.ceil(totalSeconds / 60)}m`;\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst seconds = totalSeconds % 60;\n\treturn `${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`;\n}\n\nexport class AskUserQuestionState {\n\treadonly request: QuestionRequest;\n\tactiveIndex = 0;\n\thighlightIndex = 0;\n\tfocus: QuestionFocus = \"options\";\n\tnotice: string | undefined;\n\tcomment: string | undefined;\n\tprivate dismissPending = false;\n\tprivate readonly selected = new Map<string, string[]>();\n\tprivate readonly texts = new Map<string, string>();\n\n\tconstructor(request: QuestionRequest) {\n\t\tthis.request = request;\n\t}\n\n\tget activeQuestion(): QuestionRequest[\"questions\"][number] {\n\t\treturn this.request.questions[this.activeIndex];\n\t}\n\n\t/** Highlightable rows for the active question: options plus the own-answer row. */\n\tget ownAnswerRowIndex(): number {\n\t\treturn this.activeQuestion.options.length;\n\t}\n\n\tget rowCount(): number {\n\t\treturn this.ownAnswerRowIndex + 1;\n\t}\n\n\tget activeTabIndex(): number {\n\t\treturn this.focus === \"submit\" ? this.request.questions.length : this.activeIndex;\n\t}\n\n\tswitchQuestion(delta: number): void {\n\t\tthis.switchTab(delta);\n\t}\n\n\tswitchTab(delta: number): void {\n\t\tconst count = this.request.questions.length + 1;\n\t\tconst next = (this.activeTabIndex + delta + count) % count;\n\t\tif (next === this.request.questions.length) {\n\t\t\tthis.focus = \"submit\";\n\t\t} else {\n\t\t\tthis.focus = \"options\";\n\t\t\tthis.activeIndex = next;\n\t\t\tthis.highlightIndex = 0;\n\t\t}\n\t\tthis.dismissPending = false;\n\t\tthis.notice = undefined;\n\t}\n\n\tadvance(): void {\n\t\tif (this.activeIndex + 1 < this.request.questions.length) {\n\t\t\tthis.activeIndex += 1;\n\t\t\tthis.highlightIndex = 0;\n\t\t\tthis.notice = undefined;\n\t\t\tthis.dismissPending = false;\n\t\t\treturn;\n\t\t}\n\t\tthis.focus = \"submit\";\n\t\tthis.highlightIndex = 0;\n\t\tthis.notice = undefined;\n\t\tthis.dismissPending = false;\n\t}\n\n\treturnToOptions(): void {\n\t\tthis.focus = \"options\";\n\t\tthis.highlightIndex = 0;\n\t\tthis.notice = undefined;\n\t\tthis.dismissPending = false;\n\t}\n\n\trequestDismiss(): \"confirm\" | \"cancel\" {\n\t\tif (!this.hasDraft()) return \"cancel\";\n\t\tif (!this.dismissPending) {\n\t\t\tthis.dismissPending = true;\n\t\t\tthis.notice = DISMISS_NOTICE;\n\t\t\treturn \"confirm\";\n\t\t}\n\t\treturn \"cancel\";\n\t}\n\n\tacceptPartialSubmit(): void {\n\t\tthis.dismissPending = false;\n\t\tthis.notice = undefined;\n\t}\n\n\tprivate hasDraft(): boolean {\n\t\tif ((this.comment ?? \"\").trim() !== \"\") return true;\n\t\treturn this.request.questions.some((question) => this.isAnswered(question.id));\n\t}\n\n\tselectedFor(questionId: string): string[] {\n\t\treturn this.selected.get(questionId) ?? [];\n\t}\n\n\ttextFor(questionId: string): string | undefined {\n\t\treturn this.texts.get(questionId);\n\t}\n\n\tisSelected(questionId: string, label: string): boolean {\n\t\treturn this.selectedFor(questionId).includes(label);\n\t}\n\n\tisAnswered(questionId: string): boolean {\n\t\tif (this.selectedFor(questionId).length > 0) return true;\n\t\treturn (this.texts.get(questionId) ?? \"\").trim() !== \"\";\n\t}\n\n\tansweredCount(): number {\n\t\treturn this.request.questions.filter((question) => this.isAnswered(question.id)).length;\n\t}\n\n\t/** Select (single) or toggle (multi) an option of the active question. */\n\tactivateOption(questionId: string, label: string): void {\n\t\tconst question = this.request.questions.find((entry) => entry.id === questionId);\n\t\tif (!question?.options.some((option) => option.label === label)) return;\n\t\tif (question.multiSelect) {\n\t\t\tconst next = [...this.selectedFor(questionId)];\n\t\t\tconst index = next.indexOf(label);\n\t\t\tif (index >= 0) next.splice(index, 1);\n\t\t\telse next.push(label);\n\t\t\tthis.selected.set(questionId, next);\n\t\t} else {\n\t\t\tthis.selected.set(questionId, [label]);\n\t\t}\n\t\tthis.notice = undefined;\n\t}\n\n\t/** Replace the question's answer with typed text; empty text clears it. */\n\tsetOwnAnswer(questionId: string, text: string): void {\n\t\tconst trimmed = text.trim();\n\t\tthis.selected.delete(questionId);\n\t\tif (trimmed === \"\") this.texts.delete(questionId);\n\t\telse this.texts.set(questionId, trimmed);\n\t\tthis.notice = undefined;\n\t}\n\n\tanswers(): QuestionAnswers {\n\t\tconst result: QuestionAnswers = {};\n\t\tfor (const question of this.request.questions) {\n\t\t\tconst selected = this.selectedFor(question.id);\n\t\t\tconst text = this.texts.get(question.id);\n\t\t\tif (selected.length === 0 && text === undefined) continue;\n\t\t\tresult[question.id] = { selected, ...(text !== undefined ? { text } : {}) };\n\t\t}\n\t\treturn result;\n\t}\n\n\tunanswered(): string[] {\n\t\treturn this.request.questions.filter((question) => !this.isAnswered(question.id)).map((q) => q.id);\n\t}\n\n\t/** Submit outcome: comment wins, then answers; undefined means stay open. */\n\tsubmitOutcome(forcePartial = false): \"answered\" | \"comment-submitted\" | undefined {\n\t\tif ((this.comment ?? \"\").trim() !== \"\") return \"comment-submitted\";\n\t\tif (this.unanswered().length === 0) return \"answered\";\n\t\tif (this.answeredCount() > 0) return \"answered\";\n\t\tif (forcePartial) return \"answered\";\n\t\treturn undefined;\n\t}\n\n\tbuildResponse(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): QuestionResponse {\n\t\tconst comment = this.comment !== undefined && this.comment.trim() !== \"\" ? this.comment : undefined;\n\t\treturn {\n\t\t\tstatus,\n\t\t\tanswers: this.answers(),\n\t\t\t...(comment !== undefined ? { comment } : {}),\n\t\t\tunanswered: this.unanswered(),\n\t\t\t...(autoResolvedAfterMs !== undefined ? { autoResolvedAfterMs } : {}),\n\t\t};\n\t}\n\n\trefreshDraft(): QuestionDraft {\n\t\tconst comment = this.comment !== undefined && this.comment.trim() !== \"\" ? this.comment : undefined;\n\t\treturn {\n\t\t\tanswers: this.answers(),\n\t\t\t...(comment !== undefined ? { comment } : {}),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -27,8 +27,10 @@ export declare class AskUserQuestionComponent extends Container implements Focus
|
|
|
27
27
|
private readonly questionText;
|
|
28
28
|
private readonly listContainer;
|
|
29
29
|
private readonly ownAnswerContainer;
|
|
30
|
+
private readonly submitContainer;
|
|
30
31
|
private readonly noticeText;
|
|
31
32
|
private readonly submitText;
|
|
33
|
+
private readonly hintsText;
|
|
32
34
|
private readonly keyHandlerContext;
|
|
33
35
|
private countdownLabel;
|
|
34
36
|
private settled;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user-question.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAuB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"ask-user-question.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAuB,KAAK,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAc3F,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,8BAA8B,CAAC;AAItC,MAAM,WAAW,sBAAsB;IACtC,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kFAAkF;IAClF,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC5C;AAED,qBAAa,wBAAyB,SAAQ,SAAU,YAAW,SAAS;IAC3E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuC;IACpE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAe;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAO;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAO;IAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAO;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IACjD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAmB;IACtD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAO;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAO;IACjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA2B;IAC7D,OAAO,CAAC,cAAc,CAAM;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IAEzB,YACC,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,EAC1C,IAAI,GAAE,sBAA2B,EAoDjC;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE9B;IAED,OAAO,IAAI,IAAI,CAEd;IAED,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;CA+BjB"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Container, Input, Spacer, Text } from "@earendil-works/pi-tui";
|
|
9
9
|
import { handleAskUserKeyInput } from "./ask-user-question-keys.js";
|
|
10
|
-
import { renderCommentLabel, renderHintsLine, renderNotice, renderOwnAnswerLabel, renderQuestionLine, renderQuestionList, renderSubmitLine, renderTabBar, renderTitle, } from "./ask-user-question-render.js";
|
|
10
|
+
import { renderCommentLabel, renderHintsLine, renderNotice, renderOwnAnswerLabel, renderQuestionLine, renderQuestionList, renderSubmitLine, renderSubmitSummary, renderTabBar, renderTitle, } from "./ask-user-question-render.js";
|
|
11
11
|
import { AskUserQuestionState, formatCountdownLabel, NOT_ANSWERED_NOTICE, } from "./ask-user-question-state.js";
|
|
12
12
|
import { CountdownTimer } from "./countdown-timer.js";
|
|
13
13
|
import { DynamicBorder } from "./dynamic-border.js";
|
|
@@ -18,6 +18,7 @@ export class AskUserQuestionComponent extends Container {
|
|
|
18
18
|
this.commentInput = new Input();
|
|
19
19
|
this.listContainer = new Container();
|
|
20
20
|
this.ownAnswerContainer = new Container();
|
|
21
|
+
this.submitContainer = new Container();
|
|
21
22
|
this.countdownLabel = "";
|
|
22
23
|
this.settled = false;
|
|
23
24
|
this._focused = false;
|
|
@@ -30,7 +31,7 @@ export class AskUserQuestionComponent extends Container {
|
|
|
30
31
|
commentInput: this.commentInput,
|
|
31
32
|
finish: (status, autoResolvedAfterMs) => this.finish(status, autoResolvedAfterMs),
|
|
32
33
|
attemptSubmit: () => this.attemptSubmit(),
|
|
33
|
-
openOwnAnswer: () => this.openOwnAnswer(),
|
|
34
|
+
openOwnAnswer: (initialText) => this.openOwnAnswer(initialText),
|
|
34
35
|
commitOwnAnswer: () => this.commitOwnAnswer(),
|
|
35
36
|
emitProgress: () => this.emitProgress(),
|
|
36
37
|
updateAll: () => this.updateAll(),
|
|
@@ -45,14 +46,13 @@ export class AskUserQuestionComponent extends Container {
|
|
|
45
46
|
this.addChild(this.questionText);
|
|
46
47
|
this.addChild(this.listContainer);
|
|
47
48
|
this.addChild(this.ownAnswerContainer);
|
|
48
|
-
this.addChild(
|
|
49
|
-
this.addChild(new Text(renderCommentLabel(), 1, 0));
|
|
50
|
-
this.addChild(this.commentInput);
|
|
49
|
+
this.addChild(this.submitContainer);
|
|
51
50
|
this.noticeText = new Text("", 1, 0);
|
|
52
51
|
this.addChild(this.noticeText);
|
|
53
52
|
this.submitText = new Text("", 1, 0);
|
|
54
53
|
this.addChild(this.submitText);
|
|
55
|
-
this.
|
|
54
|
+
this.hintsText = new Text("", 1, 0);
|
|
55
|
+
this.addChild(this.hintsText);
|
|
56
56
|
this.addChild(new Spacer(1));
|
|
57
57
|
this.addChild(new DynamicBorder());
|
|
58
58
|
const timeoutMs = opts.timeoutMs ?? request.timeoutMs;
|
|
@@ -78,25 +78,29 @@ export class AskUserQuestionComponent extends Container {
|
|
|
78
78
|
dispose() {
|
|
79
79
|
this.countdown?.dispose();
|
|
80
80
|
}
|
|
81
|
-
openOwnAnswer() {
|
|
81
|
+
openOwnAnswer(initialText) {
|
|
82
82
|
this.state.focus = "own-answer";
|
|
83
|
-
this.
|
|
83
|
+
const existing = this.state.textFor(this.state.activeQuestion.id) ?? "";
|
|
84
|
+
this.ownAnswerInput.setValue("");
|
|
85
|
+
if (existing !== "")
|
|
86
|
+
this.ownAnswerInput.handleInput(existing);
|
|
87
|
+
if (initialText !== undefined)
|
|
88
|
+
this.ownAnswerInput.handleInput(initialText);
|
|
84
89
|
this.updateAll();
|
|
85
90
|
}
|
|
86
91
|
commitOwnAnswer() {
|
|
87
92
|
this.state.setOwnAnswer(this.state.activeQuestion.id, this.ownAnswerInput.getValue());
|
|
88
|
-
this.state.focus = "options";
|
|
89
93
|
this.emitProgress();
|
|
90
|
-
this.updateAll();
|
|
91
94
|
}
|
|
92
95
|
attemptSubmit() {
|
|
93
96
|
this.state.comment = this.commentInput.getValue();
|
|
94
|
-
const outcome = this.state.submitOutcome();
|
|
97
|
+
const outcome = this.state.submitOutcome(this.state.notice !== undefined);
|
|
95
98
|
if (!outcome) {
|
|
96
99
|
this.state.notice = NOT_ANSWERED_NOTICE;
|
|
97
100
|
this.updateAll();
|
|
98
101
|
return;
|
|
99
102
|
}
|
|
103
|
+
this.state.acceptPartialSubmit();
|
|
100
104
|
this.finish(outcome);
|
|
101
105
|
}
|
|
102
106
|
emitProgress() {
|
|
@@ -122,7 +126,7 @@ export class AskUserQuestionComponent extends Container {
|
|
|
122
126
|
}
|
|
123
127
|
applyFocusFlags() {
|
|
124
128
|
this.ownAnswerInput.focused = this._focused && this.state.focus === "own-answer";
|
|
125
|
-
this.commentInput.focused = this._focused && this.state.focus === "
|
|
129
|
+
this.commentInput.focused = this._focused && this.state.focus === "submit";
|
|
126
130
|
}
|
|
127
131
|
updateTitle() {
|
|
128
132
|
this.titleText.setText(renderTitle(this.countdownLabel));
|
|
@@ -131,9 +135,11 @@ export class AskUserQuestionComponent extends Container {
|
|
|
131
135
|
this.updateTitle();
|
|
132
136
|
this.applyFocusFlags();
|
|
133
137
|
this.tabText.setText(renderTabBar(this.state));
|
|
134
|
-
this.questionText.setText(renderQuestionLine(this.state.activeQuestion));
|
|
138
|
+
this.questionText.setText(this.state.focus === "submit" ? "Review your answers" : renderQuestionLine(this.state.activeQuestion));
|
|
135
139
|
this.listContainer.clear();
|
|
136
|
-
for (const line of
|
|
140
|
+
for (const line of this.state.focus === "submit"
|
|
141
|
+
? renderSubmitSummary(this.state)
|
|
142
|
+
: renderQuestionList(this.state)) {
|
|
137
143
|
this.listContainer.addChild(new Text(line, 1, 0));
|
|
138
144
|
}
|
|
139
145
|
this.ownAnswerContainer.clear();
|
|
@@ -141,8 +147,15 @@ export class AskUserQuestionComponent extends Container {
|
|
|
141
147
|
this.ownAnswerContainer.addChild(new Text(renderOwnAnswerLabel(), 1, 0));
|
|
142
148
|
this.ownAnswerContainer.addChild(this.ownAnswerInput);
|
|
143
149
|
}
|
|
150
|
+
this.submitContainer.clear();
|
|
151
|
+
if (this.state.focus === "submit") {
|
|
152
|
+
this.submitContainer.addChild(new Spacer(1));
|
|
153
|
+
this.submitContainer.addChild(new Text(renderCommentLabel(), 1, 0));
|
|
154
|
+
this.submitContainer.addChild(this.commentInput);
|
|
155
|
+
}
|
|
144
156
|
this.noticeText.setText(renderNotice(this.state.notice));
|
|
145
157
|
this.submitText.setText(renderSubmitLine(this.state));
|
|
158
|
+
this.hintsText.setText(renderHintsLine(this.state));
|
|
146
159
|
}
|
|
147
160
|
}
|
|
148
161
|
//# sourceMappingURL=ask-user-question.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-user-question.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ask-user question overlay: tab bar of question headers, numbered options\n * with descriptions, per-question own-answer editor, one always-visible\n * comment editor, submit footer and a countdown chip. Layout lives in\n * ask-user-question-render.ts, interaction rules in ask-user-question-state.ts\n * and key dispatch in ask-user-question-keys.ts.\n */\n\nimport { Container, type Focusable, Input, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport { type AskUserKeyHandlerContext, handleAskUserKeyInput } from \"./ask-user-question-keys.ts\";\nimport {\n\trenderCommentLabel,\n\trenderHintsLine,\n\trenderNotice,\n\trenderOwnAnswerLabel,\n\trenderQuestionLine,\n\trenderQuestionList,\n\trenderSubmitLine,\n\trenderTabBar,\n\trenderTitle,\n} from \"./ask-user-question-render.ts\";\nimport {\n\tAskUserQuestionState,\n\tformatCountdownLabel,\n\tNOT_ANSWERED_NOTICE,\n\ttype QuestionDraft,\n} from \"./ask-user-question-state.ts\";\nimport { CountdownTimer } from \"./countdown-timer.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nexport interface AskUserQuestionOptions {\n\ttui?: TUI;\n\t/** Idle countdown duration; defaults to the request's timeoutMs. */\n\ttimeoutMs?: number;\n\t/** Draft notification on every selection or keystroke (drives the idle timer). */\n\tonProgress?: (draft: QuestionDraft) => void;\n}\n\nexport class AskUserQuestionComponent extends Container implements Focusable {\n\tprivate readonly state: AskUserQuestionState;\n\tprivate readonly doneCallback: (response: QuestionResponse) => void;\n\tprivate readonly options: AskUserQuestionOptions;\n\tprivate readonly ownAnswerInput = new Input();\n\tprivate readonly commentInput = new Input();\n\tprivate readonly countdown: CountdownTimer | undefined;\n\tprivate readonly titleText: Text;\n\tprivate readonly tabText: Text;\n\tprivate readonly questionText: Text;\n\tprivate readonly listContainer = new Container();\n\tprivate readonly ownAnswerContainer = new Container();\n\tprivate readonly noticeText: Text;\n\tprivate readonly submitText: Text;\n\tprivate readonly keyHandlerContext: AskUserKeyHandlerContext;\n\tprivate countdownLabel = \"\";\n\tprivate settled = false;\n\tprivate _focused = false;\n\n\tconstructor(\n\t\trequest: QuestionRequest,\n\t\tdone: (response: QuestionResponse) => void,\n\t\topts: AskUserQuestionOptions = {},\n\t) {\n\t\tsuper();\n\t\tthis.state = new AskUserQuestionState(request);\n\t\tthis.doneCallback = done;\n\t\tthis.options = opts;\n\t\tthis.keyHandlerContext = {\n\t\t\tstate: this.state,\n\t\t\townAnswerInput: this.ownAnswerInput,\n\t\t\tcommentInput: this.commentInput,\n\t\t\tfinish: (status, autoResolvedAfterMs) => this.finish(status, autoResolvedAfterMs),\n\t\t\tattemptSubmit: () => this.attemptSubmit(),\n\t\t\topenOwnAnswer: () => this.openOwnAnswer(),\n\t\t\tcommitOwnAnswer: () => this.commitOwnAnswer(),\n\t\t\temitProgress: () => this.emitProgress(),\n\t\t\tupdateAll: () => this.updateAll(),\n\t\t};\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.titleText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.titleText);\n\t\tthis.tabText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.tabText);\n\t\tthis.questionText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.questionText);\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(this.ownAnswerContainer);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new Text(renderCommentLabel(), 1, 0));\n\t\tthis.addChild(this.commentInput);\n\t\tthis.noticeText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.noticeText);\n\t\tthis.submitText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.submitText);\n\t\tthis.addChild(new Text(renderHintsLine(), 1, 0));\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tconst timeoutMs = opts.timeoutMs ?? request.timeoutMs;\n\t\tif (timeoutMs > 0) {\n\t\t\tthis.countdown = new CountdownTimer(\n\t\t\t\ttimeoutMs,\n\t\t\t\topts.tui,\n\t\t\t\t(seconds) => {\n\t\t\t\t\tthis.countdownLabel = formatCountdownLabel(seconds * 1000);\n\t\t\t\t\tthis.updateTitle();\n\t\t\t\t\tthis.options.tui?.requestRender();\n\t\t\t\t},\n\t\t\t\t() => this.finish(\"timed_out\", timeoutMs),\n\t\t\t);\n\t\t}\n\t\tthis.updateAll();\n\t}\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.applyFocusFlags();\n\t}\n\n\thandleInput(data: string): void {\n\t\thandleAskUserKeyInput(this.keyHandlerContext, data);\n\t}\n\n\tdispose(): void {\n\t\tthis.countdown?.dispose();\n\t}\n\n\tprivate openOwnAnswer(): void {\n\t\tthis.state.focus = \"own-answer\";\n\t\tthis.ownAnswerInput.setValue(this.state.textFor(this.state.activeQuestion.id) ?? \"\");\n\t\tthis.updateAll();\n\t}\n\n\tprivate commitOwnAnswer(): void {\n\t\tthis.state.setOwnAnswer(this.state.activeQuestion.id, this.ownAnswerInput.getValue());\n\t\tthis.state.focus = \"options\";\n\t\tthis.emitProgress();\n\t\tthis.updateAll();\n\t}\n\n\tprivate attemptSubmit(): void {\n\t\tthis.state.comment = this.commentInput.getValue();\n\t\tconst outcome = this.state.submitOutcome();\n\t\tif (!outcome) {\n\t\t\tthis.state.notice = NOT_ANSWERED_NOTICE;\n\t\t\tthis.updateAll();\n\t\t\treturn;\n\t\t}\n\t\tthis.finish(outcome);\n\t}\n\n\tprivate emitProgress(): void {\n\t\tconst draft = this.state.refreshDraft();\n\t\tif (this.state.focus === \"own-answer\") {\n\t\t\tconst live = this.ownAnswerInput.getValue().trim();\n\t\t\tif (live !== \"\") {\n\t\t\t\tdraft.answers = {\n\t\t\t\t\t...draft.answers,\n\t\t\t\t\t[this.state.activeQuestion.id]: { selected: [], text: live },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tthis.options.onProgress?.(draft);\n\t}\n\n\tprivate finish(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): void {\n\t\tif (this.settled) return;\n\t\tthis.settled = true;\n\t\tthis.countdown?.dispose();\n\t\tthis.state.comment = this.commentInput.getValue();\n\t\tthis.doneCallback(this.state.buildResponse(status, autoResolvedAfterMs));\n\t}\n\n\tprivate applyFocusFlags(): void {\n\t\tthis.ownAnswerInput.focused = this._focused && this.state.focus === \"own-answer\";\n\t\tthis.commentInput.focused = this._focused && this.state.focus === \"comment\";\n\t}\n\n\tprivate updateTitle(): void {\n\t\tthis.titleText.setText(renderTitle(this.countdownLabel));\n\t}\n\n\tprivate updateAll(): void {\n\t\tthis.updateTitle();\n\t\tthis.applyFocusFlags();\n\t\tthis.tabText.setText(renderTabBar(this.state));\n\t\tthis.questionText.setText(renderQuestionLine(this.state.activeQuestion));\n\n\t\tthis.listContainer.clear();\n\t\tfor (const line of renderQuestionList(this.state)) {\n\t\t\tthis.listContainer.addChild(new Text(line, 1, 0));\n\t\t}\n\n\t\tthis.ownAnswerContainer.clear();\n\t\tif (this.state.focus === \"own-answer\") {\n\t\t\tthis.ownAnswerContainer.addChild(new Text(renderOwnAnswerLabel(), 1, 0));\n\t\t\tthis.ownAnswerContainer.addChild(this.ownAnswerInput);\n\t\t}\n\n\t\tthis.noticeText.setText(renderNotice(this.state.notice));\n\t\tthis.submitText.setText(renderSubmitLine(this.state));\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ask-user-question.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/ask-user-question.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ask-user question overlay: tab bar of question headers, numbered options\n * with descriptions, per-question own-answer editor, one always-visible\n * comment editor, submit footer and a countdown chip. Layout lives in\n * ask-user-question-render.ts, interaction rules in ask-user-question-state.ts\n * and key dispatch in ask-user-question-keys.ts.\n */\n\nimport { Container, type Focusable, Input, Spacer, Text, type TUI } from \"@earendil-works/pi-tui\";\nimport type { QuestionRequest, QuestionResponse } from \"../../../core/extensions/types.ts\";\nimport { type AskUserKeyHandlerContext, handleAskUserKeyInput } from \"./ask-user-question-keys.ts\";\nimport {\n\trenderCommentLabel,\n\trenderHintsLine,\n\trenderNotice,\n\trenderOwnAnswerLabel,\n\trenderQuestionLine,\n\trenderQuestionList,\n\trenderSubmitLine,\n\trenderSubmitSummary,\n\trenderTabBar,\n\trenderTitle,\n} from \"./ask-user-question-render.ts\";\nimport {\n\tAskUserQuestionState,\n\tformatCountdownLabel,\n\tNOT_ANSWERED_NOTICE,\n\ttype QuestionDraft,\n} from \"./ask-user-question-state.ts\";\nimport { CountdownTimer } from \"./countdown-timer.ts\";\nimport { DynamicBorder } from \"./dynamic-border.ts\";\n\nexport interface AskUserQuestionOptions {\n\ttui?: TUI;\n\t/** Idle countdown duration; defaults to the request's timeoutMs. */\n\ttimeoutMs?: number;\n\t/** Draft notification on every selection or keystroke (drives the idle timer). */\n\tonProgress?: (draft: QuestionDraft) => void;\n}\n\nexport class AskUserQuestionComponent extends Container implements Focusable {\n\tprivate readonly state: AskUserQuestionState;\n\tprivate readonly doneCallback: (response: QuestionResponse) => void;\n\tprivate readonly options: AskUserQuestionOptions;\n\tprivate readonly ownAnswerInput = new Input();\n\tprivate readonly commentInput = new Input();\n\tprivate readonly countdown: CountdownTimer | undefined;\n\tprivate readonly titleText: Text;\n\tprivate readonly tabText: Text;\n\tprivate readonly questionText: Text;\n\tprivate readonly listContainer = new Container();\n\tprivate readonly ownAnswerContainer = new Container();\n\tprivate readonly submitContainer = new Container();\n\tprivate readonly noticeText: Text;\n\tprivate readonly submitText: Text;\n\tprivate readonly hintsText: Text;\n\tprivate readonly keyHandlerContext: AskUserKeyHandlerContext;\n\tprivate countdownLabel = \"\";\n\tprivate settled = false;\n\tprivate _focused = false;\n\n\tconstructor(\n\t\trequest: QuestionRequest,\n\t\tdone: (response: QuestionResponse) => void,\n\t\topts: AskUserQuestionOptions = {},\n\t) {\n\t\tsuper();\n\t\tthis.state = new AskUserQuestionState(request);\n\t\tthis.doneCallback = done;\n\t\tthis.options = opts;\n\t\tthis.keyHandlerContext = {\n\t\t\tstate: this.state,\n\t\t\townAnswerInput: this.ownAnswerInput,\n\t\t\tcommentInput: this.commentInput,\n\t\t\tfinish: (status, autoResolvedAfterMs) => this.finish(status, autoResolvedAfterMs),\n\t\t\tattemptSubmit: () => this.attemptSubmit(),\n\t\t\topenOwnAnswer: (initialText) => this.openOwnAnswer(initialText),\n\t\t\tcommitOwnAnswer: () => this.commitOwnAnswer(),\n\t\t\temitProgress: () => this.emitProgress(),\n\t\t\tupdateAll: () => this.updateAll(),\n\t\t};\n\n\t\tthis.addChild(new DynamicBorder());\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.titleText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.titleText);\n\t\tthis.tabText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.tabText);\n\t\tthis.questionText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.questionText);\n\t\tthis.addChild(this.listContainer);\n\t\tthis.addChild(this.ownAnswerContainer);\n\t\tthis.addChild(this.submitContainer);\n\t\tthis.noticeText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.noticeText);\n\t\tthis.submitText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.submitText);\n\t\tthis.hintsText = new Text(\"\", 1, 0);\n\t\tthis.addChild(this.hintsText);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.addChild(new DynamicBorder());\n\n\t\tconst timeoutMs = opts.timeoutMs ?? request.timeoutMs;\n\t\tif (timeoutMs > 0) {\n\t\t\tthis.countdown = new CountdownTimer(\n\t\t\t\ttimeoutMs,\n\t\t\t\topts.tui,\n\t\t\t\t(seconds) => {\n\t\t\t\t\tthis.countdownLabel = formatCountdownLabel(seconds * 1000);\n\t\t\t\t\tthis.updateTitle();\n\t\t\t\t\tthis.options.tui?.requestRender();\n\t\t\t\t},\n\t\t\t\t() => this.finish(\"timed_out\", timeoutMs),\n\t\t\t);\n\t\t}\n\t\tthis.updateAll();\n\t}\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.applyFocusFlags();\n\t}\n\n\thandleInput(data: string): void {\n\t\thandleAskUserKeyInput(this.keyHandlerContext, data);\n\t}\n\n\tdispose(): void {\n\t\tthis.countdown?.dispose();\n\t}\n\n\tprivate openOwnAnswer(initialText?: string): void {\n\t\tthis.state.focus = \"own-answer\";\n\t\tconst existing = this.state.textFor(this.state.activeQuestion.id) ?? \"\";\n\t\tthis.ownAnswerInput.setValue(\"\");\n\t\tif (existing !== \"\") this.ownAnswerInput.handleInput(existing);\n\t\tif (initialText !== undefined) this.ownAnswerInput.handleInput(initialText);\n\t\tthis.updateAll();\n\t}\n\n\tprivate commitOwnAnswer(): void {\n\t\tthis.state.setOwnAnswer(this.state.activeQuestion.id, this.ownAnswerInput.getValue());\n\t\tthis.emitProgress();\n\t}\n\n\tprivate attemptSubmit(): void {\n\t\tthis.state.comment = this.commentInput.getValue();\n\t\tconst outcome = this.state.submitOutcome(this.state.notice !== undefined);\n\t\tif (!outcome) {\n\t\t\tthis.state.notice = NOT_ANSWERED_NOTICE;\n\t\t\tthis.updateAll();\n\t\t\treturn;\n\t\t}\n\t\tthis.state.acceptPartialSubmit();\n\t\tthis.finish(outcome);\n\t}\n\n\tprivate emitProgress(): void {\n\t\tconst draft = this.state.refreshDraft();\n\t\tif (this.state.focus === \"own-answer\") {\n\t\t\tconst live = this.ownAnswerInput.getValue().trim();\n\t\t\tif (live !== \"\") {\n\t\t\t\tdraft.answers = {\n\t\t\t\t\t...draft.answers,\n\t\t\t\t\t[this.state.activeQuestion.id]: { selected: [], text: live },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tthis.options.onProgress?.(draft);\n\t}\n\n\tprivate finish(status: QuestionResponse[\"status\"], autoResolvedAfterMs?: number): void {\n\t\tif (this.settled) return;\n\t\tthis.settled = true;\n\t\tthis.countdown?.dispose();\n\t\tthis.state.comment = this.commentInput.getValue();\n\t\tthis.doneCallback(this.state.buildResponse(status, autoResolvedAfterMs));\n\t}\n\n\tprivate applyFocusFlags(): void {\n\t\tthis.ownAnswerInput.focused = this._focused && this.state.focus === \"own-answer\";\n\t\tthis.commentInput.focused = this._focused && this.state.focus === \"submit\";\n\t}\n\n\tprivate updateTitle(): void {\n\t\tthis.titleText.setText(renderTitle(this.countdownLabel));\n\t}\n\n\tprivate updateAll(): void {\n\t\tthis.updateTitle();\n\t\tthis.applyFocusFlags();\n\t\tthis.tabText.setText(renderTabBar(this.state));\n\t\tthis.questionText.setText(\n\t\t\tthis.state.focus === \"submit\" ? \"Review your answers\" : renderQuestionLine(this.state.activeQuestion),\n\t\t);\n\n\t\tthis.listContainer.clear();\n\t\tfor (const line of this.state.focus === \"submit\"\n\t\t\t? renderSubmitSummary(this.state)\n\t\t\t: renderQuestionList(this.state)) {\n\t\t\tthis.listContainer.addChild(new Text(line, 1, 0));\n\t\t}\n\n\t\tthis.ownAnswerContainer.clear();\n\t\tif (this.state.focus === \"own-answer\") {\n\t\t\tthis.ownAnswerContainer.addChild(new Text(renderOwnAnswerLabel(), 1, 0));\n\t\t\tthis.ownAnswerContainer.addChild(this.ownAnswerInput);\n\t\t}\n\n\t\tthis.submitContainer.clear();\n\t\tif (this.state.focus === \"submit\") {\n\t\t\tthis.submitContainer.addChild(new Spacer(1));\n\t\t\tthis.submitContainer.addChild(new Text(renderCommentLabel(), 1, 0));\n\t\t\tthis.submitContainer.addChild(this.commentInput);\n\t\t}\n\t\tthis.noticeText.setText(renderNotice(this.state.notice));\n\t\tthis.submitText.setText(renderSubmitLine(this.state));\n\t\tthis.hintsText.setText(renderHintsLine(this.state));\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"footer.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,KAAK,SAAS,EAAyD,MAAM,wBAAwB,CAAC;AAC/G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAkBzE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CASlD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAUjG;AAmBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAYhF;AAiCD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAChD,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,mBAAmB,CAAS;IAEpC,YAAY,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,0BAA0B,EAG9E;IAED,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAE5C;IAED,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE5C;IAED;;;;OAIG;IACH,sBAAsB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/C;IAED;;;OAGG;IACH,UAAU,IAAI,IAAI,CAEjB;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI,CAEd;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAkM9B;CACD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
3
3
|
import { rendezvousOrder } from "@earendil-works/pi-ai/auth/pool/select";
|
|
4
|
-
import { listSlots } from "@earendil-works/pi-ai/auth/pool/slots";
|
|
5
|
-
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
4
|
+
import { accountLabel, listSlots } from "@earendil-works/pi-ai/auth/pool/slots";
|
|
5
|
+
import { stripTerminalSequences, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
6
6
|
import { theme } from "../theme/theme.js";
|
|
7
7
|
import { planFooterLayout } from "./footer-layout.js";
|
|
8
8
|
const FAST_MODE_INDICATOR = "\u26a1 ";
|
|
@@ -48,10 +48,20 @@ export function accountFooterSuffix(credential, sessionId) {
|
|
|
48
48
|
if (slots.length < 2)
|
|
49
49
|
return "";
|
|
50
50
|
const pinned = Object.entries(credential ?? {}).find(([key]) => key === "pinned")?.[1];
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const pinnedSlot = slots.find((slot) => slot.name === pinned);
|
|
52
|
+
if (pinnedSlot)
|
|
53
|
+
return `@${footerAccountLabel(pinnedSlot)}`;
|
|
53
54
|
const winner = rendezvousOrder(sessionId, slots, (input) => createHash("sha256").update(input).digest().readBigUInt64BE(0))[0];
|
|
54
|
-
return winner === undefined ? "" : `@${winner
|
|
55
|
+
return winner === undefined ? "" : `@${footerAccountLabel(winner)}`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Widest account label the provider segment carries. A label wider than this
|
|
59
|
+
* is truncated with an ellipsis here rather than pushing the whole provider
|
|
60
|
+
* segment past the layout budget, which would drop the account indicator.
|
|
61
|
+
*/
|
|
62
|
+
const ACCOUNT_FOOTER_MAX_COLUMNS = 24;
|
|
63
|
+
function footerAccountLabel(slot) {
|
|
64
|
+
return truncateToWidth(accountLabel(slot), ACCOUNT_FOOTER_MAX_COLUMNS, "…");
|
|
55
65
|
}
|
|
56
66
|
/** Format with up to 1 decimal place, dropping trailing `.0`. */
|
|
57
67
|
function trim1(n) {
|
|
@@ -72,20 +82,33 @@ export function formatCwdForFooter(cwd, home) {
|
|
|
72
82
|
}
|
|
73
83
|
/**
|
|
74
84
|
* Color the right side of the footer: (provider) muted, model accent, :thinking dim.
|
|
75
|
-
*
|
|
85
|
+
*
|
|
86
|
+
* The runs come from the values that produced the text, never from re-parsing
|
|
87
|
+
* the rendered string: an account display name may legally contain `)` or `:`,
|
|
88
|
+
* and a regex over the rendered segment would then colour the provider prefix
|
|
89
|
+
* as the model, or cut the model id into a "thinking level".
|
|
90
|
+
*
|
|
91
|
+
* `plain` is the rendered segment, which the layout pass may have truncated at
|
|
92
|
+
* the tail (and whose truncation can append reset sequences); each run is
|
|
93
|
+
* clipped to the visible text that survived, so a run boundary can never cut
|
|
94
|
+
* an escape sequence in half.
|
|
76
95
|
*/
|
|
77
|
-
function colorRightSide(
|
|
96
|
+
function colorRightSide(runs, plain) {
|
|
97
|
+
const text = stripTerminalSequences(plain);
|
|
78
98
|
if (!text)
|
|
79
99
|
return "";
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
100
|
+
let offset = 0;
|
|
101
|
+
let colored = "";
|
|
102
|
+
for (const run of runs) {
|
|
103
|
+
if (offset >= text.length)
|
|
104
|
+
break;
|
|
105
|
+
const visible = text.slice(offset, offset + run.text.length);
|
|
106
|
+
if (visible.length === 0)
|
|
107
|
+
break;
|
|
108
|
+
colored += theme.fg(run.color, visible);
|
|
109
|
+
offset += visible.length;
|
|
110
|
+
}
|
|
111
|
+
return colored;
|
|
89
112
|
}
|
|
90
113
|
/**
|
|
91
114
|
* Footer component that shows pwd, token stats, and context usage.
|
|
@@ -199,7 +222,13 @@ export class FooterComponent {
|
|
|
199
222
|
const thinkingLevel = state.thinkingLevel || "off";
|
|
200
223
|
minimalRight = thinkingLevel === "off" ? `${minimalRight}:off` : `${minimalRight}:${thinkingLevel}`;
|
|
201
224
|
}
|
|
202
|
-
const
|
|
225
|
+
const thinkingSuffix = state.model?.reasoning ? `:${state.thinkingLevel || "off"}` : "";
|
|
226
|
+
const modelRuns = [
|
|
227
|
+
...(fastIndicator ? [{ text: fastIndicator, color: "warning" }] : []),
|
|
228
|
+
{ text: modelName, color: "accent" },
|
|
229
|
+
...(thinkingSuffix ? [{ text: thinkingSuffix, color: "dim" }] : []),
|
|
230
|
+
];
|
|
231
|
+
const minimal = { plain: minimalRight, colored: colorRightSide(modelRuns, minimalRight) };
|
|
203
232
|
let accountSuffix = "";
|
|
204
233
|
if (state.model) {
|
|
205
234
|
try {
|
|
@@ -213,7 +242,10 @@ export class FooterComponent {
|
|
|
213
242
|
? `(${state.model.provider}${accountSuffix}) `
|
|
214
243
|
: "";
|
|
215
244
|
const full = providerPrefix
|
|
216
|
-
? {
|
|
245
|
+
? {
|
|
246
|
+
plain: `${providerPrefix}${minimalRight}`,
|
|
247
|
+
colored: colorRightSide([{ text: providerPrefix, color: "muted" }, ...modelRuns], `${providerPrefix}${minimalRight}`),
|
|
248
|
+
}
|
|
217
249
|
: undefined;
|
|
218
250
|
const marker = { plain: "…", colored: theme.fg("dim", "…") };
|
|
219
251
|
const planWithTail = (tailSegment) => planFooterLayout({
|
|
@@ -272,7 +304,7 @@ export class FooterComponent {
|
|
|
272
304
|
}
|
|
273
305
|
else {
|
|
274
306
|
left = { colored: "", width: 0 };
|
|
275
|
-
right = { plain: plan.rightPlain, colored: colorRightSide(plan.rightPlain) };
|
|
307
|
+
right = { plain: plan.rightPlain, colored: colorRightSide(modelRuns, plan.rightPlain) };
|
|
276
308
|
}
|
|
277
309
|
const rightWidth = visibleWidth(right.plain);
|
|
278
310
|
const padding = " ".repeat(Math.max(0, width - left.width - rightWidth));
|