@lotagate/cli 0.1.20 → 0.1.22
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/dist/application/agent/agent-history.d.ts +3 -0
- package/dist/application/agent/agent-history.js +81 -0
- package/dist/application/agent/agent-input-context.d.ts +9 -0
- package/dist/application/agent/agent-input-context.js +12 -0
- package/dist/application/agent/agent-limit.d.ts +3 -0
- package/dist/application/agent/agent-limit.js +12 -0
- package/dist/application/agent/agent-run-tracker.d.ts +30 -0
- package/dist/application/agent/agent-run-tracker.js +68 -0
- package/dist/application/agent/agent-session-store.d.ts +19 -0
- package/dist/application/agent/agent-session-store.js +74 -0
- package/dist/application/agent/capability-profile.d.ts +37 -0
- package/dist/application/agent/capability-profile.js +13 -0
- package/dist/application/agent/cli-agent-execution-service.d.ts +81 -0
- package/dist/application/agent/cli-agent-execution-service.js +279 -0
- package/dist/application/agent/context-compaction-persistence.d.ts +8 -0
- package/dist/application/agent/context-compaction-persistence.js +27 -0
- package/dist/application/agent/context-compaction.d.ts +20 -0
- package/dist/application/agent/context-compaction.js +114 -0
- package/dist/application/agent/prompt-data-safety.d.ts +14 -0
- package/dist/application/agent/prompt-data-safety.js +38 -0
- package/dist/application/agent/safe-system-prompt.d.ts +3 -0
- package/dist/application/agent/safe-system-prompt.js +19 -0
- package/dist/application/agent/scoped-tool-executor.d.ts +13 -0
- package/dist/application/agent/scoped-tool-executor.js +32 -0
- package/dist/application/agent/system-prompt-builder.d.ts +14 -0
- package/dist/application/agent/system-prompt-builder.js +199 -0
- package/dist/application/agent/tool-catalog.d.ts +14 -0
- package/dist/application/agent/tool-catalog.js +30 -0
- package/dist/application/agent/tool-display.d.ts +6 -0
- package/dist/application/agent/tool-display.js +59 -0
- package/dist/application/agent/tool-hook-lifecycle.d.ts +19 -0
- package/dist/application/agent/tool-hook-lifecycle.js +85 -0
- package/dist/application/auth/authentication-service.d.ts +20 -0
- package/dist/application/auth/authentication-service.js +44 -0
- package/dist/application/chat/chat-service.d.ts +12 -0
- package/dist/application/chat/chat-service.js +19 -0
- package/dist/application/chat/pending-attachment-store.d.ts +12 -0
- package/dist/application/chat/pending-attachment-store.js +28 -0
- package/dist/application/commands/application-command-executor.d.ts +20 -0
- package/dist/application/commands/application-command-executor.js +66 -0
- package/dist/application/commands/cli-args.d.ts +6 -0
- package/dist/application/commands/cli-args.js +43 -0
- package/dist/application/commands/cli-command-services.d.ts +16 -0
- package/dist/application/commands/cli-command-services.js +405 -0
- package/dist/application/commands/command-catalog.d.ts +6 -0
- package/dist/application/commands/command-catalog.js +159 -0
- package/dist/application/commands/command-contract.d.ts +58 -0
- package/dist/application/commands/command-contract.js +1 -0
- package/dist/application/commands/command-hints.d.ts +9 -0
- package/dist/application/commands/command-hints.js +17 -0
- package/dist/application/commands/command-output.d.ts +4 -0
- package/dist/application/commands/command-output.js +1 -0
- package/dist/application/commands/command-parser.d.ts +10 -0
- package/dist/application/commands/command-parser.js +155 -0
- package/dist/application/commands/command-presentation.d.ts +7 -0
- package/dist/application/commands/command-presentation.js +131 -0
- package/dist/application/commands/command-registry.d.ts +11 -0
- package/dist/application/commands/command-registry.js +64 -0
- package/dist/application/commands/command-runtime.d.ts +2 -0
- package/dist/application/commands/command-runtime.js +3 -0
- package/dist/application/commands/goal-command-handlers.d.ts +3 -0
- package/dist/application/commands/goal-command-handlers.js +120 -0
- package/dist/application/commands/media-command-handlers.d.ts +9 -0
- package/dist/application/commands/media-command-handlers.js +307 -0
- package/dist/application/commands/media-command-output.d.ts +11 -0
- package/dist/application/commands/media-command-output.js +8 -0
- package/dist/application/commands/runtime-command-handlers.d.ts +7 -0
- package/dist/application/commands/runtime-command-handlers.js +177 -0
- package/dist/application/commands/stream-output.d.ts +4 -0
- package/dist/application/commands/stream-output.js +10 -0
- package/dist/application/commands/utility-commands.d.ts +6 -0
- package/dist/application/commands/utility-commands.js +81 -0
- package/dist/application/config/execution-config.d.ts +4 -0
- package/dist/application/config/execution-config.js +6 -0
- package/dist/application/extensions/extension-list-contract.d.ts +13 -0
- package/dist/application/extensions/extension-list-contract.js +1 -0
- package/dist/application/extensions/extension-list-formatters.d.ts +31 -0
- package/dist/application/extensions/extension-list-formatters.js +98 -0
- package/dist/application/extensions/extension-list-output.d.ts +3 -0
- package/dist/application/extensions/extension-list-output.js +7 -0
- package/dist/application/extensions/plugin-contribution-registry.d.ts +15 -0
- package/dist/application/extensions/plugin-contribution-registry.js +80 -0
- package/dist/application/extensions/skill-scope-store.d.ts +23 -0
- package/dist/application/extensions/skill-scope-store.js +33 -0
- package/dist/application/formatting/compact-number.d.ts +2 -0
- package/dist/application/formatting/compact-number.js +18 -0
- package/dist/application/formatting/compact-table.d.ts +22 -0
- package/dist/application/formatting/compact-table.js +49 -0
- package/dist/application/media/video-operation-poller.d.ts +5 -0
- package/dist/application/media/video-operation-poller.js +42 -0
- package/dist/application/model/cached-model-catalog.d.ts +13 -0
- package/dist/application/model/cached-model-catalog.js +31 -0
- package/dist/application/model/initial-model-selection.d.ts +10 -0
- package/dist/application/model/initial-model-selection.js +11 -0
- package/dist/application/model/model-catalog-service.d.ts +6 -0
- package/dist/application/model/model-catalog-service.js +13 -0
- package/dist/application/model/model-context-window.d.ts +3 -0
- package/dist/application/model/model-context-window.js +23 -0
- package/dist/application/orchestration/cli-subagent-service.d.ts +70 -0
- package/dist/application/orchestration/cli-subagent-service.js +328 -0
- package/dist/application/orchestration/cli-turn-event-projector.d.ts +12 -0
- package/dist/application/orchestration/cli-turn-event-projector.js +81 -0
- package/dist/application/orchestration/cli-turn-events.d.ts +76 -0
- package/dist/application/orchestration/cli-turn-events.js +39 -0
- package/dist/application/orchestration/cli-turn-persistence.d.ts +6 -0
- package/dist/application/orchestration/cli-turn-persistence.js +14 -0
- package/dist/application/orchestration/goal-evaluator.d.ts +18 -0
- package/dist/application/orchestration/goal-evaluator.js +88 -0
- package/dist/application/orchestration/goal-input.d.ts +3 -0
- package/dist/application/orchestration/goal-input.js +19 -0
- package/dist/application/orchestration/goal-output.d.ts +2 -0
- package/dist/application/orchestration/goal-output.js +11 -0
- package/dist/application/orchestration/goal-runner.d.ts +22 -0
- package/dist/application/orchestration/goal-runner.js +153 -0
- package/dist/application/orchestration/goal-usage.d.ts +9 -0
- package/dist/application/orchestration/goal-usage.js +19 -0
- package/dist/application/orchestration/headless-agent-turn.d.ts +32 -0
- package/dist/application/orchestration/headless-agent-turn.js +82 -0
- package/dist/application/orchestration/plan-generator.d.ts +7 -0
- package/dist/application/orchestration/plan-generator.js +34 -0
- package/dist/application/orchestration/subagent-coordinator.d.ts +33 -0
- package/dist/application/orchestration/subagent-coordinator.js +28 -0
- package/dist/application/orchestration/subagent-handoff.d.ts +2 -0
- package/dist/application/orchestration/subagent-handoff.js +68 -0
- package/dist/application/orchestration/subagent-tool-executor.d.ts +12 -0
- package/dist/application/orchestration/subagent-tool-executor.js +93 -0
- package/dist/application/orchestration/task-assessment.d.ts +4 -0
- package/dist/application/orchestration/task-assessment.js +35 -0
- package/dist/application/orchestration/task-graph.d.ts +13 -0
- package/dist/application/orchestration/task-graph.js +56 -0
- package/dist/application/orchestration/task-scheduler.d.ts +18 -0
- package/dist/application/orchestration/task-scheduler.js +88 -0
- package/dist/application/project/project-trust-service.d.ts +13 -0
- package/dist/application/project/project-trust-service.js +74 -0
- package/dist/application/protocol/browser-host-tool-executor.d.ts +41 -0
- package/dist/application/protocol/browser-host-tool-executor.js +88 -0
- package/dist/application/protocol/desktop-agent-command.d.ts +9 -0
- package/dist/application/protocol/desktop-agent-command.js +663 -0
- package/dist/application/protocol/desktop-attachment-store.d.ts +16 -0
- package/dist/application/protocol/desktop-attachment-store.js +82 -0
- package/dist/application/protocol/desktop-command-catalog.d.ts +2 -0
- package/dist/application/protocol/desktop-command-catalog.js +19 -0
- package/dist/application/protocol/desktop-command-contract.d.ts +22 -0
- package/dist/application/protocol/desktop-command-contract.js +3 -0
- package/dist/application/protocol/desktop-command-executor.d.ts +16 -0
- package/dist/application/protocol/desktop-command-executor.js +47 -0
- package/dist/application/protocol/desktop-command-output.d.ts +15 -0
- package/dist/application/protocol/desktop-command-output.js +24 -0
- package/dist/application/protocol/desktop-execution-policy.d.ts +17 -0
- package/dist/application/protocol/desktop-execution-policy.js +49 -0
- package/dist/application/protocol/desktop-host-tool-executor.d.ts +57 -0
- package/dist/application/protocol/desktop-host-tool-executor.js +53 -0
- package/dist/application/protocol/desktop-orchestration-events.d.ts +5 -0
- package/dist/application/protocol/desktop-orchestration-events.js +37 -0
- package/dist/application/protocol/json-line-writer.d.ts +9 -0
- package/dist/application/protocol/json-line-writer.js +19 -0
- package/dist/application/protocol/jsonl-agent-command.d.ts +3 -0
- package/dist/application/protocol/jsonl-agent-command.js +97 -0
- package/dist/application/protocol/jsonl-protocol.d.ts +52 -0
- package/dist/application/protocol/jsonl-protocol.js +170 -0
- package/dist/application/security/desktop-tool-scope-policy.d.ts +3 -0
- package/dist/application/security/desktop-tool-scope-policy.js +52 -0
- package/dist/application/security/tool-action-risk-analyzer.d.ts +13 -0
- package/dist/application/security/tool-action-risk-analyzer.js +64 -0
- package/dist/application/security/tool-approval-service.d.ts +35 -0
- package/dist/application/security/tool-approval-service.js +97 -0
- package/dist/application/security/tool-risk-classifier.d.ts +11 -0
- package/dist/application/security/tool-risk-classifier.js +65 -0
- package/dist/application/security/workspace-permission-policy.d.ts +10 -0
- package/dist/application/security/workspace-permission-policy.js +50 -0
- package/dist/application/session/project-session-access.d.ts +8 -0
- package/dist/application/session/project-session-access.js +19 -0
- package/dist/application/session/session-compaction-service.d.ts +10 -0
- package/dist/application/session/session-compaction-service.js +43 -0
- package/dist/application/session/session-turn-lifecycle.d.ts +5 -0
- package/dist/application/session/session-turn-lifecycle.js +31 -0
- package/dist/application/workspace/workspace-file-index.d.ts +15 -0
- package/dist/application/workspace/workspace-file-index.js +60 -0
- package/dist/application/workspace/workspace-file-reference-resolver.d.ts +14 -0
- package/dist/application/workspace/workspace-file-reference-resolver.js +123 -0
- package/dist/application/workspace/workspace-instruction-loader.d.ts +8 -0
- package/dist/application/workspace/workspace-instruction-loader.js +55 -0
- package/dist/bootstrap/composition-root.d.ts +6 -0
- package/dist/bootstrap/composition-root.js +4 -0
- package/dist/bootstrap/global-cli-options.d.ts +6 -0
- package/dist/bootstrap/global-cli-options.js +29 -0
- package/dist/bootstrap/native-devtools-stub.d.ts +10 -0
- package/dist/bootstrap/native-devtools-stub.js +10 -0
- package/dist/bootstrap/native-entry.d.ts +1 -0
- package/dist/bootstrap/native-entry.js +6 -0
- package/dist/bootstrap/native-tiktoken.d.ts +4 -0
- package/dist/bootstrap/native-tiktoken.js +5 -0
- package/dist/bootstrap/runtime-factory.d.ts +35 -0
- package/dist/bootstrap/runtime-factory.js +44 -0
- package/dist/bootstrap/shutdown-manager.d.ts +10 -0
- package/dist/bootstrap/shutdown-manager.js +14 -0
- package/dist/bootstrap/startup-sequence.d.ts +5 -0
- package/dist/bootstrap/startup-sequence.js +10 -0
- package/dist/domain/auth/auth-profile.d.ts +14 -0
- package/dist/domain/auth/auth-profile.js +39 -0
- package/dist/domain/config/config-schema.d.ts +17 -0
- package/dist/domain/config/config-schema.js +105 -0
- package/dist/domain/errors/cli-command-hint.d.ts +5 -0
- package/dist/domain/errors/cli-command-hint.js +1 -0
- package/dist/domain/errors/cli-error.d.ts +35 -0
- package/dist/domain/errors/cli-error.js +129 -0
- package/dist/domain/errors/error-codes.d.ts +46 -0
- package/dist/domain/errors/error-codes.js +45 -0
- package/dist/domain/extensions/extension-scope.d.ts +3 -0
- package/dist/domain/extensions/extension-scope.js +23 -0
- package/dist/domain/extensions/extension-state.d.ts +5 -0
- package/dist/domain/extensions/extension-state.js +11 -0
- package/dist/domain/extensions/hook-manifest.d.ts +10 -0
- package/dist/domain/extensions/hook-manifest.js +23 -0
- package/dist/domain/extensions/mcp-config.d.ts +18 -0
- package/dist/domain/extensions/mcp-config.js +111 -0
- package/dist/domain/extensions/plugin-manifest.d.ts +11 -0
- package/dist/domain/extensions/plugin-manifest.js +43 -0
- package/dist/domain/extensions/skill-manifest.d.ts +10 -0
- package/dist/domain/extensions/skill-manifest.js +51 -0
- package/dist/domain/filesystem/file-change-diff.d.ts +21 -0
- package/dist/domain/filesystem/file-change-diff.js +60 -0
- package/dist/domain/media/gateway-media-contract.d.ts +23 -0
- package/dist/domain/media/gateway-media-contract.js +163 -0
- package/dist/domain/media/media-contract.d.ts +28 -0
- package/dist/domain/media/media-contract.js +1 -0
- package/dist/domain/media/media-execution-policy.d.ts +9 -0
- package/dist/domain/media/media-execution-policy.js +31 -0
- package/dist/domain/orchestration/goal.d.ts +58 -0
- package/dist/domain/orchestration/goal.js +113 -0
- package/dist/domain/orchestration/subagent-identity.d.ts +2 -0
- package/dist/domain/orchestration/subagent-identity.js +8 -0
- package/dist/domain/orchestration/subagent.d.ts +33 -0
- package/dist/domain/orchestration/subagent.js +1 -0
- package/dist/domain/orchestration/task.d.ts +31 -0
- package/dist/domain/orchestration/task.js +1 -0
- package/dist/domain/project/project-identity.d.ts +6 -0
- package/dist/domain/project/project-identity.js +4 -0
- package/dist/domain/runtime/assistant-delta-normalizer.d.ts +11 -0
- package/dist/domain/runtime/assistant-delta-normalizer.js +19 -0
- package/dist/domain/runtime/resource-limits.d.ts +60 -0
- package/dist/domain/runtime/resource-limits.js +60 -0
- package/dist/domain/session/attachment.d.ts +13 -0
- package/dist/domain/session/attachment.js +1 -0
- package/dist/domain/session/session-schema.d.ts +6 -0
- package/dist/domain/session/session-schema.js +28 -0
- package/dist/domain/session/session.d.ts +27 -0
- package/dist/domain/session/session.js +1 -0
- package/dist/domain/settings/settings-document.d.ts +8 -0
- package/dist/domain/settings/settings-document.js +36 -0
- package/dist/domain/validation/record-schema.d.ts +4 -0
- package/dist/domain/validation/record-schema.js +9 -0
- package/dist/domain/workspace/workspace-settings.d.ts +12 -0
- package/dist/domain/workspace/workspace-settings.js +44 -0
- package/dist/infrastructure/agent-sdk/agent-instance-factory.d.ts +22 -0
- package/dist/infrastructure/agent-sdk/agent-instance-factory.js +31 -0
- package/dist/infrastructure/agent-sdk/tool-calling-model-client.d.ts +11 -0
- package/dist/infrastructure/agent-sdk/tool-calling-model-client.js +447 -0
- package/dist/infrastructure/cache/cache-policy.d.ts +7 -0
- package/dist/infrastructure/cache/cache-policy.js +18 -0
- package/dist/infrastructure/cache/file-cache-store.d.ts +17 -0
- package/dist/infrastructure/cache/file-cache-store.js +121 -0
- package/dist/infrastructure/clipboard/clipboard-adapter-factory.d.ts +11 -0
- package/dist/infrastructure/clipboard/clipboard-adapter-factory.js +98 -0
- package/dist/infrastructure/clipboard/clipboard-policy.d.ts +8 -0
- package/dist/infrastructure/clipboard/clipboard-policy.js +19 -0
- package/dist/infrastructure/clipboard/clipboard-text-adapter-factory.d.ts +10 -0
- package/dist/infrastructure/clipboard/clipboard-text-adapter-factory.js +94 -0
- package/dist/infrastructure/clipboard/image-normalizer.d.ts +12 -0
- package/dist/infrastructure/clipboard/image-normalizer.js +78 -0
- package/dist/infrastructure/clipboard/windows-clipboard-adapter.d.ts +7 -0
- package/dist/infrastructure/clipboard/windows-clipboard-adapter.js +66 -0
- package/dist/infrastructure/clipboard/windows-clipboard-text-adapter.d.ts +7 -0
- package/dist/infrastructure/clipboard/windows-clipboard-text-adapter.js +70 -0
- package/dist/infrastructure/config/config-loader.d.ts +19 -0
- package/dist/infrastructure/config/config-loader.js +76 -0
- package/dist/infrastructure/config/environment-values.d.ts +2 -0
- package/dist/infrastructure/config/environment-values.js +7 -0
- package/dist/infrastructure/credentials/composite-credential-store.d.ts +11 -0
- package/dist/infrastructure/credentials/composite-credential-store.js +32 -0
- package/dist/infrastructure/credentials/encrypted-file-credential-store.d.ts +17 -0
- package/dist/infrastructure/credentials/encrypted-file-credential-store.js +181 -0
- package/dist/infrastructure/credentials/environment-credential-store.d.ts +11 -0
- package/dist/infrastructure/credentials/environment-credential-store.js +37 -0
- package/dist/infrastructure/credentials/secret-input.d.ts +7 -0
- package/dist/infrastructure/credentials/secret-input.js +44 -0
- package/dist/infrastructure/extensions/composite-mcp-config-store.d.ts +9 -0
- package/dist/infrastructure/extensions/composite-mcp-config-store.js +10 -0
- package/dist/infrastructure/extensions/extension-directory-reader.d.ts +2 -0
- package/dist/infrastructure/extensions/extension-directory-reader.js +15 -0
- package/dist/infrastructure/extensions/extension-source-resolver.d.ts +6 -0
- package/dist/infrastructure/extensions/extension-source-resolver.js +126 -0
- package/dist/infrastructure/extensions/file-mcp-config-store.d.ts +15 -0
- package/dist/infrastructure/extensions/file-mcp-config-store.js +66 -0
- package/dist/infrastructure/extensions/hook-runtime.d.ts +18 -0
- package/dist/infrastructure/extensions/hook-runtime.js +66 -0
- package/dist/infrastructure/extensions/mcp-runtime.d.ts +12 -0
- package/dist/infrastructure/extensions/mcp-runtime.js +52 -0
- package/dist/infrastructure/extensions/plugin-discovery.d.ts +5 -0
- package/dist/infrastructure/extensions/plugin-discovery.js +52 -0
- package/dist/infrastructure/extensions/plugin-manager.d.ts +26 -0
- package/dist/infrastructure/extensions/plugin-manager.js +139 -0
- package/dist/infrastructure/extensions/skill-discovery.d.ts +4 -0
- package/dist/infrastructure/extensions/skill-discovery.js +29 -0
- package/dist/infrastructure/extensions/skill-installer.d.ts +8 -0
- package/dist/infrastructure/extensions/skill-installer.js +88 -0
- package/dist/infrastructure/extensions/skill-manager.d.ts +22 -0
- package/dist/infrastructure/extensions/skill-manager.js +67 -0
- package/dist/infrastructure/extensions/skill-roots.d.ts +19 -0
- package/dist/infrastructure/extensions/skill-roots.js +25 -0
- package/dist/infrastructure/extensions/skill-tool-executor.d.ts +18 -0
- package/dist/infrastructure/extensions/skill-tool-executor.js +53 -0
- package/dist/infrastructure/filesystem/atomic-file-store.d.ts +12 -0
- package/dist/infrastructure/filesystem/atomic-file-store.js +106 -0
- package/dist/infrastructure/filesystem/bounded-file-reader.d.ts +6 -0
- package/dist/infrastructure/filesystem/bounded-file-reader.js +24 -0
- package/dist/infrastructure/filesystem/bounded-json-reader.d.ts +1 -0
- package/dist/infrastructure/filesystem/bounded-json-reader.js +7 -0
- package/dist/infrastructure/filesystem/fs-errors.d.ts +2 -0
- package/dist/infrastructure/filesystem/fs-errors.js +6 -0
- package/dist/infrastructure/filesystem/gateway-media-input-reader.d.ts +12 -0
- package/dist/infrastructure/filesystem/gateway-media-input-reader.js +49 -0
- package/dist/infrastructure/filesystem/local-filesystem-tool-executor.d.ts +21 -0
- package/dist/infrastructure/filesystem/local-filesystem-tool-executor.js +176 -0
- package/dist/infrastructure/filesystem/path-resolver.d.ts +20 -0
- package/dist/infrastructure/filesystem/path-resolver.js +119 -0
- package/dist/infrastructure/filesystem/workspace-media-artifact-store.d.ts +13 -0
- package/dist/infrastructure/filesystem/workspace-media-artifact-store.js +152 -0
- package/dist/infrastructure/logging/daily-rotating-file-writer.d.ts +20 -0
- package/dist/infrastructure/logging/daily-rotating-file-writer.js +75 -0
- package/dist/infrastructure/logging/log-redactor.d.ts +2 -0
- package/dist/infrastructure/logging/log-redactor.js +26 -0
- package/dist/infrastructure/logging/logging-policy.d.ts +6 -0
- package/dist/infrastructure/logging/logging-policy.js +6 -0
- package/dist/infrastructure/logging/structured-logger.d.ts +24 -0
- package/dist/infrastructure/logging/structured-logger.js +40 -0
- package/dist/infrastructure/network/safe-media-downloader.d.ts +23 -0
- package/dist/infrastructure/network/safe-media-downloader.js +239 -0
- package/dist/infrastructure/platform/host-platform.d.ts +14 -0
- package/dist/infrastructure/platform/host-platform.js +23 -0
- package/dist/infrastructure/platform/host-process.d.ts +17 -0
- package/dist/infrastructure/platform/host-process.js +116 -0
- package/dist/infrastructure/platform/platform-paths.d.ts +25 -0
- package/dist/infrastructure/platform/platform-paths.js +33 -0
- package/dist/infrastructure/project/file-project-trust-store.d.ts +12 -0
- package/dist/infrastructure/project/file-project-trust-store.js +59 -0
- package/dist/infrastructure/sdk/chat-completion-adapter.d.ts +8 -0
- package/dist/infrastructure/sdk/chat-completion-adapter.js +115 -0
- package/dist/infrastructure/sdk/lotagate-client-factory.d.ts +3 -0
- package/dist/infrastructure/sdk/lotagate-client-factory.js +8 -0
- package/dist/infrastructure/sdk/model-catalog-adapter.d.ts +19 -0
- package/dist/infrastructure/sdk/model-catalog-adapter.js +28 -0
- package/dist/infrastructure/sdk/sdk-media-gateway-client.d.ts +20 -0
- package/dist/infrastructure/sdk/sdk-media-gateway-client.js +97 -0
- package/dist/infrastructure/sessions/file-goal-store.d.ts +21 -0
- package/dist/infrastructure/sessions/file-goal-store.js +160 -0
- package/dist/infrastructure/sessions/file-session-store.d.ts +48 -0
- package/dist/infrastructure/sessions/file-session-store.js +525 -0
- package/dist/infrastructure/sessions/project-session-paths.d.ts +17 -0
- package/dist/infrastructure/sessions/project-session-paths.js +41 -0
- package/dist/infrastructure/sessions/session-index.d.ts +16 -0
- package/dist/infrastructure/sessions/session-index.js +84 -0
- package/dist/infrastructure/sessions/session-journal.d.ts +22 -0
- package/dist/infrastructure/sessions/session-journal.js +137 -0
- package/dist/infrastructure/sessions/subagent-journal-store.d.ts +28 -0
- package/dist/infrastructure/sessions/subagent-journal-store.js +30 -0
- package/dist/infrastructure/shell/shell-tool-executor.d.ts +17 -0
- package/dist/infrastructure/shell/shell-tool-executor.js +115 -0
- package/dist/infrastructure/tokens/tiktoken-token-estimator.d.ts +18 -0
- package/dist/infrastructure/tokens/tiktoken-token-estimator.js +48 -0
- package/dist/infrastructure/workspace/workspace-settings-store.d.ts +9 -0
- package/dist/infrastructure/workspace/workspace-settings-store.js +75 -0
- package/dist/main.d.ts +7 -0
- package/dist/main.js +66 -0
- package/dist/ports/cache-store.d.ts +10 -0
- package/dist/ports/cache-store.js +1 -0
- package/dist/ports/chat-model.d.ts +30 -0
- package/dist/ports/chat-model.js +1 -0
- package/dist/ports/clipboard-adapter.d.ts +7 -0
- package/dist/ports/clipboard-adapter.js +1 -0
- package/dist/ports/clipboard-text-adapter.d.ts +3 -0
- package/dist/ports/clipboard-text-adapter.js +1 -0
- package/dist/ports/credential-store.d.ts +7 -0
- package/dist/ports/credential-store.js +1 -0
- package/dist/ports/goal-store.d.ts +12 -0
- package/dist/ports/goal-store.js +1 -0
- package/dist/ports/logger.d.ts +8 -0
- package/dist/ports/logger.js +1 -0
- package/dist/ports/media-gateway-client.d.ts +54 -0
- package/dist/ports/media-gateway-client.js +1 -0
- package/dist/ports/model-diagnostics.d.ts +17 -0
- package/dist/ports/model-diagnostics.js +1 -0
- package/dist/ports/project-trust-store.d.ts +12 -0
- package/dist/ports/project-trust-store.js +1 -0
- package/dist/ports/session-store.d.ts +58 -0
- package/dist/ports/session-store.js +1 -0
- package/dist/ports/subagent-lifecycle.d.ts +31 -0
- package/dist/ports/subagent-lifecycle.js +1 -0
- package/dist/ports/tool-activity.d.ts +13 -0
- package/dist/ports/tool-activity.js +1 -0
- package/dist/presentation/themes/theme.d.ts +19 -0
- package/dist/presentation/themes/theme.js +8 -0
- package/dist/presentation/tui/agent-initialization-renderer.d.ts +4 -0
- package/dist/presentation/tui/agent-initialization-renderer.js +37 -0
- package/dist/presentation/tui/context-display.d.ts +21 -0
- package/dist/presentation/tui/context-display.js +33 -0
- package/dist/presentation/tui/formatters.d.ts +6 -0
- package/dist/presentation/tui/formatters.js +60 -0
- package/dist/presentation/tui/ink/choice-window.d.ts +5 -0
- package/dist/presentation/tui/ink/choice-window.js +5 -0
- package/dist/presentation/tui/ink/components/activity-entry.d.ts +6 -0
- package/dist/presentation/tui/ink/components/activity-entry.js +16 -0
- package/dist/presentation/tui/ink/components/activity-status.d.ts +10 -0
- package/dist/presentation/tui/ink/components/activity-status.js +21 -0
- package/dist/presentation/tui/ink/components/choice-modal.d.ts +11 -0
- package/dist/presentation/tui/ink/components/choice-modal.js +29 -0
- package/dist/presentation/tui/ink/components/composer.d.ts +40 -0
- package/dist/presentation/tui/ink/components/composer.js +271 -0
- package/dist/presentation/tui/ink/components/file-diff.d.ts +6 -0
- package/dist/presentation/tui/ink/components/file-diff.js +34 -0
- package/dist/presentation/tui/ink/components/modal.d.ts +8 -0
- package/dist/presentation/tui/ink/components/modal.js +110 -0
- package/dist/presentation/tui/ink/components/shimmer-text.d.ts +6 -0
- package/dist/presentation/tui/ink/components/shimmer-text.js +9 -0
- package/dist/presentation/tui/ink/components/subagent-activity.d.ts +11 -0
- package/dist/presentation/tui/ink/components/subagent-activity.js +61 -0
- package/dist/presentation/tui/ink/components/transcript.d.ts +39 -0
- package/dist/presentation/tui/ink/components/transcript.js +121 -0
- package/dist/presentation/tui/ink/components/welcome-panel.d.ts +6 -0
- package/dist/presentation/tui/ink/components/welcome-panel.js +20 -0
- package/dist/presentation/tui/ink/lotagate-tui.d.ts +6 -0
- package/dist/presentation/tui/ink/lotagate-tui.js +136 -0
- package/dist/presentation/tui/ink/markdown-inline-renderer.d.ts +4 -0
- package/dist/presentation/tui/ink/markdown-inline-renderer.js +20 -0
- package/dist/presentation/tui/ink/markdown-inline.d.ts +13 -0
- package/dist/presentation/tui/ink/markdown-inline.js +91 -0
- package/dist/presentation/tui/ink/markdown-message.d.ts +6 -0
- package/dist/presentation/tui/ink/markdown-message.js +66 -0
- package/dist/presentation/tui/ink/markdown-table.d.ts +16 -0
- package/dist/presentation/tui/ink/markdown-table.js +77 -0
- package/dist/presentation/tui/ink/tui-bridge.d.ts +195 -0
- package/dist/presentation/tui/ink/tui-bridge.js +289 -0
- package/dist/presentation/tui/terminal-capabilities.d.ts +15 -0
- package/dist/presentation/tui/terminal-capabilities.js +7 -0
- package/dist/presentation/tui/terminal-mouse.d.ts +5 -0
- package/dist/presentation/tui/terminal-mouse.js +19 -0
- package/dist/presentation/tui/terminal-screen.d.ts +10 -0
- package/dist/presentation/tui/terminal-screen.js +23 -0
- package/dist/presentation/tui/tui-agent-event-runner.d.ts +24 -0
- package/dist/presentation/tui/tui-agent-event-runner.js +69 -0
- package/dist/presentation/tui/tui-application-contract.d.ts +10 -0
- package/dist/presentation/tui/tui-application-contract.js +8 -0
- package/dist/presentation/tui/tui-application.d.ts +62 -0
- package/dist/presentation/tui/tui-application.js +675 -0
- package/dist/presentation/tui/tui-attachment-input.d.ts +2 -0
- package/dist/presentation/tui/tui-attachment-input.js +5 -0
- package/dist/presentation/tui/tui-clipboard-paste-handlers.d.ts +11 -0
- package/dist/presentation/tui/tui-clipboard-paste-handlers.js +25 -0
- package/dist/presentation/tui/tui-command-context.d.ts +3 -0
- package/dist/presentation/tui/tui-command-context.js +1 -0
- package/dist/presentation/tui/tui-command-executor.d.ts +38 -0
- package/dist/presentation/tui/tui-command-executor.js +214 -0
- package/dist/presentation/tui/tui-command-host-factory.d.ts +40 -0
- package/dist/presentation/tui/tui-command-host-factory.js +23 -0
- package/dist/presentation/tui/tui-context-compaction.d.ts +5 -0
- package/dist/presentation/tui/tui-context-compaction.js +22 -0
- package/dist/presentation/tui/tui-context-service.d.ts +34 -0
- package/dist/presentation/tui/tui-context-service.js +126 -0
- package/dist/presentation/tui/tui-file-suggestions.d.ts +3 -0
- package/dist/presentation/tui/tui-file-suggestions.js +8 -0
- package/dist/presentation/tui/tui-goal-controller.d.ts +14 -0
- package/dist/presentation/tui/tui-goal-controller.js +52 -0
- package/dist/presentation/tui/tui-initial-model.d.ts +3 -0
- package/dist/presentation/tui/tui-initial-model.js +28 -0
- package/dist/presentation/tui/tui-lifecycle-actions.d.ts +13 -0
- package/dist/presentation/tui/tui-lifecycle-actions.js +45 -0
- package/dist/presentation/tui/tui-manual-compaction.d.ts +18 -0
- package/dist/presentation/tui/tui-manual-compaction.js +31 -0
- package/dist/presentation/tui/tui-media-model-selection.d.ts +12 -0
- package/dist/presentation/tui/tui-media-model-selection.js +38 -0
- package/dist/presentation/tui/tui-prompt-dispatcher.d.ts +16 -0
- package/dist/presentation/tui/tui-prompt-dispatcher.js +38 -0
- package/dist/presentation/tui/tui-skill-controller.d.ts +11 -0
- package/dist/presentation/tui/tui-skill-controller.js +13 -0
- package/dist/presentation/tui/tui-tool-approval.d.ts +22 -0
- package/dist/presentation/tui/tui-tool-approval.js +73 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +9 -8
- package/scripts/install-native.mjs +11 -11
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
import { createElement } from 'react';
|
|
2
|
+
import { render } from 'ink';
|
|
3
|
+
import { AuthenticationService } from '../../application/auth/authentication-service.js';
|
|
4
|
+
import { ChatService } from '../../application/chat/chat-service.js';
|
|
5
|
+
import { createLotaGateClient } from '../../infrastructure/sdk/lotagate-client-factory.js';
|
|
6
|
+
import { SdkChatCompletionAdapter } from '../../infrastructure/sdk/chat-completion-adapter.js';
|
|
7
|
+
import { detectTerminalCapabilities } from './terminal-capabilities.js';
|
|
8
|
+
import { enterInteractiveScreen, exitInteractiveScreen } from './terminal-screen.js';
|
|
9
|
+
import { createImageAttachment, normalizeImage } from '../../infrastructure/clipboard/image-normalizer.js';
|
|
10
|
+
import { ToolPolicy } from '@lotagate/agent-sdk';
|
|
11
|
+
import { PlanGenerator } from '../../application/orchestration/plan-generator.js';
|
|
12
|
+
import { PendingAttachmentStore } from '../../application/chat/pending-attachment-store.js';
|
|
13
|
+
import { HookRuntime } from '../../infrastructure/extensions/hook-runtime.js';
|
|
14
|
+
import { ShellToolExecutor } from '../../infrastructure/shell/shell-tool-executor.js';
|
|
15
|
+
import { resolveSkillRootScopes } from '../../infrastructure/extensions/skill-roots.js';
|
|
16
|
+
import { CLI_VERSION } from '../../version.js';
|
|
17
|
+
import { asCliError, CliError } from '../../domain/errors/cli-error.js';
|
|
18
|
+
import { CLI_ERROR_CODES } from '../../domain/errors/error-codes.js';
|
|
19
|
+
import { InkTuiBridge } from './ink/tui-bridge.js';
|
|
20
|
+
import { LotaGateTui } from './ink/lotagate-tui.js';
|
|
21
|
+
import { estimateTurnUsage } from '../../infrastructure/tokens/tiktoken-token-estimator.js';
|
|
22
|
+
import { WorkspaceFileIndex } from '../../application/workspace/workspace-file-index.js';
|
|
23
|
+
import { ProjectSessionAccess } from '../../application/session/project-session-access.js';
|
|
24
|
+
import { PluginContributionRegistry } from '../../application/extensions/plugin-contribution-registry.js';
|
|
25
|
+
import { createCapabilitySnapshot } from '../../application/agent/capability-profile.js';
|
|
26
|
+
import { SystemPromptBuilder } from '../../application/agent/system-prompt-builder.js';
|
|
27
|
+
import { createTuiCommandHost } from './tui-command-host-factory.js';
|
|
28
|
+
import { workspaceFileSuggestions } from './tui-file-suggestions.js';
|
|
29
|
+
import { buildTuiAttachmentInput } from './tui-attachment-input.js';
|
|
30
|
+
import { AUTH_LOGIN_HINT, MODEL_SELECT_HINT, formatCliErrorMessage, formatCommandHint } from '../../application/commands/command-hints.js';
|
|
31
|
+
import { AgentRunTracker } from '../../application/agent/agent-run-tracker.js';
|
|
32
|
+
import { buildAgentInputContext } from '../../application/agent/agent-input-context.js';
|
|
33
|
+
import { prepareCliAgent } from '../../application/agent/cli-agent-execution-service.js';
|
|
34
|
+
import { TuiToolApprovalCoordinator } from './tui-tool-approval.js';
|
|
35
|
+
import { TuiContextService } from './tui-context-service.js';
|
|
36
|
+
import { createTuiClipboardPasteHandlers } from './tui-clipboard-paste-handlers.js';
|
|
37
|
+
import { dispatchTuiPrompt } from './tui-prompt-dispatcher.js';
|
|
38
|
+
import { CliAgentSessionStore, retainLatestCompaction } from '../../application/agent/agent-session-store.js';
|
|
39
|
+
import { createTuiContextManagement } from './tui-context-compaction.js';
|
|
40
|
+
import { compactManualTuiSession } from './tui-manual-compaction.js';
|
|
41
|
+
import { resolveInitialModel } from './tui-initial-model.js';
|
|
42
|
+
import { cancelTuiResponse, handleTuiInterrupt, isAbortError, runTuiHookEvent, throwIfAborted } from './tui-lifecycle-actions.js';
|
|
43
|
+
import { loadExecutionConfig } from '../../application/config/execution-config.js';
|
|
44
|
+
import { resumeTuiGoal, runTuiGoal } from './tui-goal-controller.js';
|
|
45
|
+
import { runTuiSkill } from './tui-skill-controller.js';
|
|
46
|
+
import { SubagentJobRegistry } from '../../application/orchestration/cli-subagent-service.js';
|
|
47
|
+
import { formatResumeCommand } from './tui-application-contract.js';
|
|
48
|
+
import { runTuiAgentEvents } from './tui-agent-event-runner.js';
|
|
49
|
+
import { createTurnId, recordTurnCompletion, recordTurnFailure, recordTurnStart } from '../../application/session/session-turn-lifecycle.js';
|
|
50
|
+
export class TuiApplication {
|
|
51
|
+
runtime;
|
|
52
|
+
cwd;
|
|
53
|
+
options;
|
|
54
|
+
input;
|
|
55
|
+
output;
|
|
56
|
+
renderer;
|
|
57
|
+
pendingAttachments = new PendingAttachmentStore();
|
|
58
|
+
session;
|
|
59
|
+
hookRuntime;
|
|
60
|
+
hooks = [];
|
|
61
|
+
skillRootScopes = [];
|
|
62
|
+
enabledPluginNames = [];
|
|
63
|
+
pluginMcpConfig = {};
|
|
64
|
+
activeAbortController;
|
|
65
|
+
activePromptRun;
|
|
66
|
+
activeForegroundRun;
|
|
67
|
+
exitArmedUntil = 0;
|
|
68
|
+
lastInterruptAt = 0;
|
|
69
|
+
printResumeCommandOnExit = false;
|
|
70
|
+
activeModel = null;
|
|
71
|
+
activeProfile = null;
|
|
72
|
+
approvals;
|
|
73
|
+
contextService;
|
|
74
|
+
agentSessionStore = new CliAgentSessionStore();
|
|
75
|
+
subagentJobs = new SubagentJobRegistry();
|
|
76
|
+
constructor(runtime, cwd, options = {}) {
|
|
77
|
+
this.runtime = runtime;
|
|
78
|
+
this.cwd = cwd;
|
|
79
|
+
this.options = options;
|
|
80
|
+
this.input = options.input ?? process.stdin;
|
|
81
|
+
this.output = options.output ?? process.stdout;
|
|
82
|
+
this.renderer = new InkTuiBridge();
|
|
83
|
+
this.contextService = new TuiContextService(this.runtime, this.cwd);
|
|
84
|
+
this.approvals = new TuiToolApprovalCoordinator({
|
|
85
|
+
renderer: this.renderer,
|
|
86
|
+
runtime: this.runtime,
|
|
87
|
+
getSessionId: () => this.session?.id,
|
|
88
|
+
getActiveSignal: () => this.activeAbortController?.signal,
|
|
89
|
+
});
|
|
90
|
+
this.renderer.setInterruptHandler(() => this.handleInterrupt());
|
|
91
|
+
this.renderer.setCancelHandler(() => cancelTuiResponse(this.activeAbortController, this.renderer));
|
|
92
|
+
const clipboard = createTuiClipboardPasteHandlers({
|
|
93
|
+
platform: this.runtime.platform,
|
|
94
|
+
notify: (message) => this.renderer.notice(message),
|
|
95
|
+
attachImage: (image) => this.attachClipboardImage(image, false),
|
|
96
|
+
});
|
|
97
|
+
this.renderer.setImagePasteHandler(clipboard.image);
|
|
98
|
+
this.renderer.setTextPasteHandler(clipboard.text);
|
|
99
|
+
this.renderer.setClearAttachmentsHandler(() => {
|
|
100
|
+
this.pendingAttachments.clear();
|
|
101
|
+
this.renderer.setPendingAttachments([]);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
async run() {
|
|
105
|
+
const capabilities = detectTerminalCapabilities(this.input, this.output);
|
|
106
|
+
if (!capabilities.isInteractive) {
|
|
107
|
+
this.output.write('Interactive TUI requires a terminal. Use `lotagate chat "prompt"` for non-interactive streaming.\n');
|
|
108
|
+
return 2;
|
|
109
|
+
}
|
|
110
|
+
enterInteractiveScreen(this.output);
|
|
111
|
+
const ink = render(createElement(LotaGateTui, { bridge: this.renderer }), { stdin: this.input, stdout: this.output, exitOnCtrlC: false });
|
|
112
|
+
const onInterrupt = () => this.handleInterrupt();
|
|
113
|
+
process.on('SIGINT', onInterrupt);
|
|
114
|
+
let finalStatus = 'completed';
|
|
115
|
+
try {
|
|
116
|
+
const identity = await this.runtime.projectTrust.inspect(this.cwd);
|
|
117
|
+
let trusted = await this.runtime.projectTrust.isTrusted(identity);
|
|
118
|
+
let loadedConfig = await this.runtime.configLoader.load(this.cwd, { includeProject: trusted });
|
|
119
|
+
let initialModel = await resolveInitialModel(this.runtime, this.cwd, loadedConfig.config);
|
|
120
|
+
let loaded = { ...loadedConfig, config: { ...loadedConfig.config, model: initialModel } };
|
|
121
|
+
this.activeModel = loaded.config.model;
|
|
122
|
+
this.activeProfile = loaded.config.profile;
|
|
123
|
+
this.renderer.setWelcome({ version: CLI_VERSION, cwd: identity.canonicalPath, model: loaded.config.model, profile: loaded.config.profile, trusted });
|
|
124
|
+
this.renderer.setFileSuggestions([]);
|
|
125
|
+
if (!trusted) {
|
|
126
|
+
trusted = await this.renderer.confirmTrust();
|
|
127
|
+
if (trusted) {
|
|
128
|
+
await this.runtime.projectTrust.grant(identity);
|
|
129
|
+
loadedConfig = await this.runtime.configLoader.load(this.cwd);
|
|
130
|
+
initialModel = await resolveInitialModel(this.runtime, this.cwd, loadedConfig.config);
|
|
131
|
+
loaded = { ...loadedConfig, config: { ...loadedConfig.config, model: initialModel } };
|
|
132
|
+
this.activeModel = loaded.config.model;
|
|
133
|
+
this.activeProfile = loaded.config.profile;
|
|
134
|
+
this.renderer.setWelcome({ version: CLI_VERSION, cwd: identity.canonicalPath, model: this.activeModel, profile: this.activeProfile, trusted: true });
|
|
135
|
+
this.renderer.notice('Project trusted.');
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
this.renderer.notice('Project remains untrusted; local tools and extensions stay disabled.');
|
|
139
|
+
}
|
|
140
|
+
if (trusted)
|
|
141
|
+
await this.runtime.workspaceSettings.ensureInitialized(identity.canonicalPath);
|
|
142
|
+
await this.reloadExtensions(trusted, loaded.config.approvalMode, identity.canonicalPath);
|
|
143
|
+
if (this.options.sessionId !== undefined) {
|
|
144
|
+
const resumed = await this.runtime.sessionStore.get(this.options.sessionId);
|
|
145
|
+
if (resumed === undefined)
|
|
146
|
+
throw new Error(`Session not found: ${this.options.sessionId}`);
|
|
147
|
+
if (resumed.projectFingerprint !== identity.fingerprint)
|
|
148
|
+
throw new Error('Session belongs to another project.');
|
|
149
|
+
this.session = resumed;
|
|
150
|
+
this.renderer.status(`Resuming session ${resumed.id}`);
|
|
151
|
+
for (const entry of retainLatestCompaction(await this.runtime.sessionStore.readTranscript(resumed.id))) {
|
|
152
|
+
if (entry.type === 'user')
|
|
153
|
+
this.renderer.userPrompt(entry.content);
|
|
154
|
+
else if (entry.type === 'assistant') {
|
|
155
|
+
this.renderer.beginAssistant();
|
|
156
|
+
this.renderer.assistantDelta(entry.content);
|
|
157
|
+
this.renderer.finishAssistant();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
else
|
|
162
|
+
this.session = await this.runtime.sessionStore.create({ projectFingerprint: identity.fingerprint, cwd: identity.canonicalPath, model: loaded.config.model, profile: loaded.config.profile, status: 'active' });
|
|
163
|
+
await this.refreshContextUsage();
|
|
164
|
+
await this.runHookEvent('session.start', identity.canonicalPath, this.session.id);
|
|
165
|
+
this.renderer.setSubmitHandler(async (input) => { if (await this.processPrompt(input))
|
|
166
|
+
this.renderer.requestExit(); });
|
|
167
|
+
this.renderer.clearActivity();
|
|
168
|
+
this.renderer.setReady();
|
|
169
|
+
void new WorkspaceFileIndex(identity.canonicalPath).listEntries()
|
|
170
|
+
.then((entries) => this.renderer.setFileSuggestions(workspaceFileSuggestions(entries)))
|
|
171
|
+
.catch((error) => this.runtime.logger.debug('Unable to load workspace file suggestions.', { reason: error instanceof Error ? error.message : String(error) }));
|
|
172
|
+
return await this.renderer.waitForExit();
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
finalStatus = isAbortError(error) ? 'cancelled' : 'failed';
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
this.activeAbortController?.abort(new Error('Interactive session is closing.'));
|
|
180
|
+
this.renderer.resolveActiveModal(undefined);
|
|
181
|
+
await this.awaitActiveForegroundRun();
|
|
182
|
+
try {
|
|
183
|
+
await this.subagentJobs.close();
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
this.runtime.logger.warn('Unable to close subagent jobs during TUI shutdown.', { reason: error instanceof Error ? error.message : String(error) });
|
|
187
|
+
}
|
|
188
|
+
if (this.session !== undefined) {
|
|
189
|
+
try {
|
|
190
|
+
await this.runHookEvent('session.end', this.cwd, this.session.id);
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
this.runtime.logger.warn('Session end hook failed during TUI shutdown.', { sessionId: this.session.id, reason: error instanceof Error ? error.message : String(error) });
|
|
194
|
+
}
|
|
195
|
+
try {
|
|
196
|
+
await this.runtime.sessionStore.updateStatus(this.session.id, finalStatus);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
this.runtime.logger.warn('Unable to update TUI session status during shutdown.', { sessionId: this.session.id, reason: error instanceof Error ? error.message : String(error) });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
process.off('SIGINT', onInterrupt);
|
|
203
|
+
this.renderer.dispose();
|
|
204
|
+
ink.unmount();
|
|
205
|
+
exitInteractiveScreen(this.output);
|
|
206
|
+
if (this.printResumeCommandOnExit && this.session !== undefined) {
|
|
207
|
+
this.output.write(`\n${formatResumeCommand(this.session.id)}\n`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async processPrompt(input) {
|
|
212
|
+
if (this.activeForegroundRun !== undefined) {
|
|
213
|
+
this.renderer.notice('An operation is already running. Stop it before starting another one.');
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const run = dispatchTuiPrompt(input, {
|
|
217
|
+
renderer: this.renderer,
|
|
218
|
+
logger: this.runtime.logger,
|
|
219
|
+
commandHost: createTuiCommandHost({
|
|
220
|
+
runtime: this.runtime,
|
|
221
|
+
cwd: this.cwd,
|
|
222
|
+
renderer: this.renderer,
|
|
223
|
+
pendingAttachments: this.pendingAttachments,
|
|
224
|
+
getHooks: () => this.hooks,
|
|
225
|
+
getSession: () => this.session,
|
|
226
|
+
getActiveAbortController: () => this.activeAbortController,
|
|
227
|
+
setActiveAbortController: (controller) => { this.activeAbortController = controller; },
|
|
228
|
+
attachClipboardImage: (image) => this.attachClipboardImage(image),
|
|
229
|
+
runPrompt: (prompt, initialSkill) => this.sendPrompt(prompt, this.pendingAttachments.list(), initialSkill),
|
|
230
|
+
runGoal: (objective, context, limits) => this.runGoal(objective, context, limits),
|
|
231
|
+
resumeGoal: (context) => this.resumeGoal(context),
|
|
232
|
+
runSkill: (name, args, context, availableSkills, scope) => this.runSkill(name, args, context, availableSkills, scope),
|
|
233
|
+
refreshExtensions: () => this.refreshExtensions(),
|
|
234
|
+
compactSession: () => this.compactSession(),
|
|
235
|
+
refreshWelcome: (overrides) => this.refreshWelcome(overrides),
|
|
236
|
+
getContextSnapshot: () => this.getContextSnapshot(),
|
|
237
|
+
resumeSession: (sessionId) => this.resumeSession(sessionId),
|
|
238
|
+
}),
|
|
239
|
+
pendingAttachments: this.pendingAttachments,
|
|
240
|
+
commandContext: () => this.commandContext(),
|
|
241
|
+
sendPrompt: (prompt, attachments) => this.sendPrompt(prompt, attachments),
|
|
242
|
+
resetActiveAbortController: () => { if (this.activePromptRun === undefined)
|
|
243
|
+
this.activeAbortController = undefined; },
|
|
244
|
+
});
|
|
245
|
+
this.activeForegroundRun = run;
|
|
246
|
+
try {
|
|
247
|
+
return await run;
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
if (this.activeForegroundRun === run)
|
|
251
|
+
this.activeForegroundRun = undefined;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
async attachClipboardImage(image, announce = true) {
|
|
255
|
+
if (image === undefined) {
|
|
256
|
+
if (announce)
|
|
257
|
+
this.renderer.notice('Clipboard does not contain an image.');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const normalized = normalizeImage(image.bytes, image.mimeType);
|
|
261
|
+
this.pendingAttachments.assertCanAdd(normalized.bytes.byteLength);
|
|
262
|
+
const id = this.pendingAttachments.nextId();
|
|
263
|
+
const attachment = createImageAttachment(normalized, 'clipboard', id);
|
|
264
|
+
const storedAttachment = this.session === undefined ? attachment : await this.runtime.sessionStore.saveAttachment(this.session.id, attachment, normalized.bytes);
|
|
265
|
+
this.pendingAttachments.add({ attachment: storedAttachment, bytes: normalized.bytes });
|
|
266
|
+
this.renderer.setPendingAttachments(this.pendingAttachments.list().map(({ attachment: item }) => item));
|
|
267
|
+
if (announce)
|
|
268
|
+
this.renderer.notice(`Attached ${attachment.name} · ${attachment.mimeType} · ${attachment.sizeBytes} bytes`);
|
|
269
|
+
}
|
|
270
|
+
async runPrompt(prompt, initialSkill, goalCallbacks) {
|
|
271
|
+
return this.sendPrompt(prompt, this.pendingAttachments.list(), initialSkill, goalCallbacks);
|
|
272
|
+
}
|
|
273
|
+
async runGoal(objective, context, limits = {}) { if (this.activePromptRun !== undefined) {
|
|
274
|
+
context.write('Stop the active response before starting a goal.');
|
|
275
|
+
return;
|
|
276
|
+
} await runTuiGoal({ runtime: this.runtime, cwd: this.cwd, sessionId: this.session?.id, model: this.activeModel ?? this.session?.model ?? null, profile: this.activeProfile ?? this.session?.profile ?? null, runPrompt: (prompt, callbacks) => this.runPrompt(prompt, undefined, callbacks), write: (message) => context.write(message) }, objective, limits); }
|
|
277
|
+
async resumeGoal(context) { if (this.activePromptRun !== undefined) {
|
|
278
|
+
context.write('Stop the active response before resuming a goal.');
|
|
279
|
+
return;
|
|
280
|
+
} await resumeTuiGoal({ runtime: this.runtime, cwd: this.cwd, sessionId: this.session?.id, model: this.activeModel ?? this.session?.model ?? null, profile: this.activeProfile ?? this.session?.profile ?? null, runPrompt: (prompt, callbacks) => this.runPrompt(prompt, undefined, callbacks), write: (message) => context.write(message) }); }
|
|
281
|
+
async sendPrompt(prompt, attachments = [], initialSkill, goalCallbacks) {
|
|
282
|
+
if (this.activePromptRun !== undefined) {
|
|
283
|
+
this.renderer.notice('A response is already running. Stop it before sending another prompt.');
|
|
284
|
+
return '';
|
|
285
|
+
}
|
|
286
|
+
const run = this.executePrompt(prompt, attachments, initialSkill, goalCallbacks);
|
|
287
|
+
this.activePromptRun = run;
|
|
288
|
+
this.renderer.setRunActive(true);
|
|
289
|
+
try {
|
|
290
|
+
return await run;
|
|
291
|
+
}
|
|
292
|
+
finally {
|
|
293
|
+
if (this.activePromptRun === run)
|
|
294
|
+
this.activePromptRun = undefined;
|
|
295
|
+
this.renderer.setRunActive(false);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async executePrompt(prompt, attachments = [], initialSkill, goalCallbacks) {
|
|
299
|
+
const loaded = await loadExecutionConfig(this.runtime, this.cwd);
|
|
300
|
+
const selectedModel = this.activeModel ?? loaded.config.model;
|
|
301
|
+
if (selectedModel === null) {
|
|
302
|
+
this.renderer.error(`No model is selected. ${formatCommandHint(MODEL_SELECT_HINT, 'tui')}`);
|
|
303
|
+
return '';
|
|
304
|
+
}
|
|
305
|
+
const profileName = this.activeProfile ?? loaded.config.profile ?? AuthenticationService.defaultProfileName();
|
|
306
|
+
const credential = await this.runtime.credentialStore.get(profileName);
|
|
307
|
+
if (credential === undefined) {
|
|
308
|
+
this.renderer.error(`No API key is configured. ${formatCommandHint(AUTH_LOGIN_HINT, 'tui')}`);
|
|
309
|
+
return '';
|
|
310
|
+
}
|
|
311
|
+
const plan = new PlanGenerator().generate(prompt);
|
|
312
|
+
if (plan.requiresApproval && !(await this.renderer.confirmPlan(plan))) {
|
|
313
|
+
this.renderer.error('Plan cancelled.');
|
|
314
|
+
return '';
|
|
315
|
+
}
|
|
316
|
+
await this.runHookEvent('prompt.before', this.cwd, this.session?.id ?? 'tui');
|
|
317
|
+
this.renderer.userPrompt(prompt, attachments.map(({ attachment }) => attachment));
|
|
318
|
+
const turnId = createTurnId();
|
|
319
|
+
if (this.session !== undefined)
|
|
320
|
+
await recordTurnStart(this.runtime.sessionStore, this.session.id, turnId, prompt, attachments.map(({ attachment }) => attachment.id));
|
|
321
|
+
const startedAt = Date.now();
|
|
322
|
+
let usage;
|
|
323
|
+
let agentUsageReported = false;
|
|
324
|
+
this.renderer.status('Thinking');
|
|
325
|
+
const abortController = new AbortController();
|
|
326
|
+
this.activeAbortController = abortController;
|
|
327
|
+
const client = createLotaGateClient(credential.profile, credential.apiKey);
|
|
328
|
+
const identity = await this.runtime.projectTrust.inspect(this.cwd);
|
|
329
|
+
const trusted = await this.runtime.projectTrust.isTrusted(identity);
|
|
330
|
+
const activeGoal = this.session === undefined ? undefined : await this.runtime.goalStore.get(this.session.id);
|
|
331
|
+
const canUseAgent = trusted && attachments.length === 0;
|
|
332
|
+
const tracker = new AgentRunTracker();
|
|
333
|
+
const toolActivity = {
|
|
334
|
+
start: (activity) => this.renderer.startToolActivity(activity.key, activity.label),
|
|
335
|
+
};
|
|
336
|
+
const subagentLifecycle = {
|
|
337
|
+
onSubagentLifecycle: (event) => {
|
|
338
|
+
if (event.sessionId === this.session?.id)
|
|
339
|
+
this.renderer.subagentLifecycle(event);
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
const contextWindow = await this.contextService.getModelContextWindow(selectedModel, profileName);
|
|
343
|
+
const onModelComplete = (summary) => {
|
|
344
|
+
tracker.observeModel(summary);
|
|
345
|
+
if (summary.usage !== undefined) {
|
|
346
|
+
agentUsageReported = true;
|
|
347
|
+
goalCallbacks?.onUsage({ usage: summary.usage, modelCalls: 1 });
|
|
348
|
+
}
|
|
349
|
+
this.runtime.logger.debug('Model turn completed.', {
|
|
350
|
+
model: summary.model,
|
|
351
|
+
stream: summary.stream,
|
|
352
|
+
contentLength: summary.contentLength,
|
|
353
|
+
toolCallCount: summary.toolCallCount,
|
|
354
|
+
toolNames: summary.toolNames,
|
|
355
|
+
finishReason: summary.finishReason,
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
const prepared = canUseAgent
|
|
359
|
+
? await prepareCliAgent({
|
|
360
|
+
runtime: this.runtime,
|
|
361
|
+
cwd: this.cwd,
|
|
362
|
+
model: selectedModel,
|
|
363
|
+
client,
|
|
364
|
+
profile: 'interactive-trusted',
|
|
365
|
+
approvalMode: loaded.config.approvalMode,
|
|
366
|
+
subagentJobs: this.subagentJobs,
|
|
367
|
+
...(initialSkill === undefined ? {} : { initialSkill }),
|
|
368
|
+
onWrite: (change) => this.renderer.fileChange(change),
|
|
369
|
+
prompt: (request) => this.approvals.ask(request),
|
|
370
|
+
rememberApproval: (request) => this.approvals.remember(identity.canonicalPath, request),
|
|
371
|
+
onApprovalPersistenceFailure: (_request, error) => this.approvals.rememberFailure(error),
|
|
372
|
+
audit: (decision) => this.approvals.audit(decision),
|
|
373
|
+
onModelComplete,
|
|
374
|
+
onSubagentModelComplete: (summary) => { if (summary.usage !== undefined)
|
|
375
|
+
goalCallbacks?.onUsage({ usage: summary.usage, modelCalls: 1 }); },
|
|
376
|
+
contextManagement: createTuiContextManagement(client, selectedModel, contextWindow, (error) => this.runtime.logger.warn('Context summarization failed; using fallback summary.', { reason: error instanceof Error ? error.message : String(error) })),
|
|
377
|
+
agentSessionStore: this.agentSessionStore,
|
|
378
|
+
toolActivity,
|
|
379
|
+
subagentLifecycle,
|
|
380
|
+
...(activeGoal === undefined ? {} : { goal: {
|
|
381
|
+
objective: activeGoal.objective,
|
|
382
|
+
status: activeGoal.status,
|
|
383
|
+
turns: activeGoal.turns,
|
|
384
|
+
evaluatorRuns: activeGoal.evaluatorRuns,
|
|
385
|
+
tokensUsed: activeGoal.usage.totalTokens,
|
|
386
|
+
...(activeGoal.tokenBudget === undefined ? {} : { tokenBudget: activeGoal.tokenBudget }),
|
|
387
|
+
...(activeGoal.maxTurns === undefined ? {} : { maxTurns: activeGoal.maxTurns }),
|
|
388
|
+
...(activeGoal.maxDurationMs === undefined ? {} : { maxDurationMs: activeGoal.maxDurationMs }),
|
|
389
|
+
...(activeGoal.lastError === undefined ? {} : { lastError: activeGoal.lastError }),
|
|
390
|
+
...(activeGoal.lastEvaluation === undefined ? {} : { lastEvaluation: activeGoal.lastEvaluation.reason }),
|
|
391
|
+
} }),
|
|
392
|
+
})
|
|
393
|
+
: undefined;
|
|
394
|
+
const referenceContext = prepared === undefined
|
|
395
|
+
? await buildAgentInputContext(prompt, identity.canonicalPath, trusted)
|
|
396
|
+
: await prepared.buildInput(prompt);
|
|
397
|
+
const fileReferences = referenceContext.references;
|
|
398
|
+
const agentInput = referenceContext.input;
|
|
399
|
+
const system = prepared?.system ?? new SystemPromptBuilder().build(createCapabilitySnapshot({
|
|
400
|
+
profile: 'interactive-untrusted',
|
|
401
|
+
model: selectedModel,
|
|
402
|
+
cwd: identity.canonicalPath,
|
|
403
|
+
workspaceRoot: identity.canonicalPath,
|
|
404
|
+
trusted: false,
|
|
405
|
+
tools: [],
|
|
406
|
+
skills: [],
|
|
407
|
+
plugins: [],
|
|
408
|
+
}));
|
|
409
|
+
const response = [];
|
|
410
|
+
const appendAssistantDelta = (content) => {
|
|
411
|
+
throwIfAborted(abortController.signal);
|
|
412
|
+
response.push(content);
|
|
413
|
+
this.renderer.assistantDelta(content);
|
|
414
|
+
};
|
|
415
|
+
try {
|
|
416
|
+
if (prepared === undefined) {
|
|
417
|
+
const service = new ChatService(new SdkChatCompletionAdapter(client));
|
|
418
|
+
const attachmentInput = await buildTuiAttachmentInput(prompt, fileReferences, identity.canonicalPath);
|
|
419
|
+
for await (const event of service.stream(selectedModel, attachmentInput, { system, signal: abortController.signal, attachments })) {
|
|
420
|
+
throwIfAborted(abortController.signal);
|
|
421
|
+
if (event.type === 'activity')
|
|
422
|
+
this.renderer.activity(event.state === 'writing' ? 'Writing' : 'Thinking', Date.now() - startedAt, usage);
|
|
423
|
+
if (event.type === 'usage') {
|
|
424
|
+
usage = event.usage;
|
|
425
|
+
this.renderer.activity('Writing', Date.now() - startedAt, usage);
|
|
426
|
+
}
|
|
427
|
+
if (event.type === 'delta')
|
|
428
|
+
appendAssistantDelta(event.content);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
throwIfAborted(abortController.signal);
|
|
433
|
+
await runTuiAgentEvents({
|
|
434
|
+
prepared,
|
|
435
|
+
input: agentInput,
|
|
436
|
+
model: selectedModel,
|
|
437
|
+
...(this.session === undefined ? {} : { sessionId: this.session.id }),
|
|
438
|
+
turnId,
|
|
439
|
+
signal: abortController.signal,
|
|
440
|
+
agentSessionStore: this.agentSessionStore,
|
|
441
|
+
tracker,
|
|
442
|
+
runtime: this.runtime,
|
|
443
|
+
renderer: this.renderer,
|
|
444
|
+
startedAt,
|
|
445
|
+
getUsage: () => usage,
|
|
446
|
+
appendAssistantDelta,
|
|
447
|
+
hasResponse: () => response.length > 0,
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
if (response.join('').trim().length === 0) {
|
|
451
|
+
const snapshot = tracker.snapshot();
|
|
452
|
+
if (snapshot.toolCalls > 0)
|
|
453
|
+
tracker.markStuck();
|
|
454
|
+
const code = snapshot.toolCalls > 0 ? CLI_ERROR_CODES.MODEL_EMPTY_FINAL : CLI_ERROR_CODES.MODEL_PROTOCOL_EMPTY_RESPONSE;
|
|
455
|
+
const message = snapshot.toolCalls > 0
|
|
456
|
+
? 'The model completed its tool work without a final text response.'
|
|
457
|
+
: 'The model returned neither text nor a tool call.';
|
|
458
|
+
throw new CliError(code, message, {
|
|
459
|
+
category: 'model',
|
|
460
|
+
userMessage: `${message} Check the selected model and gateway tool-calling support, then try again.`,
|
|
461
|
+
retryable: true,
|
|
462
|
+
details: {
|
|
463
|
+
modelTurns: snapshot.modelTurns,
|
|
464
|
+
toolCalls: snapshot.toolCalls,
|
|
465
|
+
toolCompletions: snapshot.toolCompletions,
|
|
466
|
+
toolFailures: snapshot.toolFailures,
|
|
467
|
+
toolNames: snapshot.toolNames,
|
|
468
|
+
finishReason: snapshot.lastFinishReason,
|
|
469
|
+
},
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
goalCallbacks?.onSnapshot(tracker.snapshot());
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
const cancelled = abortController.signal.aborted || isAbortError(error);
|
|
476
|
+
if (this.session !== undefined)
|
|
477
|
+
this.agentSessionStore.delete(this.session.id);
|
|
478
|
+
if (cancelled)
|
|
479
|
+
tracker.markCancelled();
|
|
480
|
+
else if (tracker.snapshot().state !== 'stuck')
|
|
481
|
+
tracker.markFailed();
|
|
482
|
+
if (this.session !== undefined)
|
|
483
|
+
await recordTurnFailure(this.runtime.sessionStore, this.session.id, turnId, error, cancelled);
|
|
484
|
+
this.renderer.finishAssistant();
|
|
485
|
+
if (cancelled)
|
|
486
|
+
this.renderer.notice('Interrupted.');
|
|
487
|
+
else {
|
|
488
|
+
const cliError = asCliError(error);
|
|
489
|
+
this.renderer.failed();
|
|
490
|
+
this.runtime.logger.error('Agent run failed.', { code: cliError.code, category: cliError.category, ...(cliError.details ?? {}) });
|
|
491
|
+
this.renderer.error(formatCliErrorMessage(cliError, 'tui'));
|
|
492
|
+
}
|
|
493
|
+
goalCallbacks?.onError(error);
|
|
494
|
+
goalCallbacks?.onSnapshot(tracker.snapshot());
|
|
495
|
+
return '';
|
|
496
|
+
}
|
|
497
|
+
finally {
|
|
498
|
+
if (this.activeAbortController === abortController)
|
|
499
|
+
this.activeAbortController = undefined;
|
|
500
|
+
if (prepared !== undefined) {
|
|
501
|
+
try {
|
|
502
|
+
await prepared.close();
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
// Preserve a completed turn when an MCP or local executor fails during cleanup.
|
|
506
|
+
this.runtime.logger.warn('Agent cleanup failed after a completed turn.', { reason: error instanceof Error ? error.message : String(error) });
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
this.renderer.finishAssistant();
|
|
511
|
+
try {
|
|
512
|
+
if (this.session !== undefined) {
|
|
513
|
+
await recordTurnCompletion(this.runtime.sessionStore, this.session.id, turnId, response.join(''));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
catch (error) {
|
|
517
|
+
this.runtime.logger.warn('Unable to persist the completed turn.', { reason: error instanceof Error ? error.message : String(error) });
|
|
518
|
+
this.renderer.notice('Response completed, but the session state could not be saved.');
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
await this.runHookEvent('response.after', this.cwd, this.session?.id ?? 'tui');
|
|
522
|
+
}
|
|
523
|
+
catch (error) {
|
|
524
|
+
this.runtime.logger.warn('Response hook failed after a completed turn.', { reason: error instanceof Error ? error.message : String(error) });
|
|
525
|
+
this.renderer.notice('Response completed, but the response hook failed.');
|
|
526
|
+
}
|
|
527
|
+
this.pendingAttachments.clear();
|
|
528
|
+
this.renderer.setPendingAttachments([]);
|
|
529
|
+
if (!agentUsageReported && usage !== undefined)
|
|
530
|
+
goalCallbacks?.onUsage({ usage, modelCalls: 1 });
|
|
531
|
+
const finalUsage = usage?.totalTokens === undefined
|
|
532
|
+
? estimateTurnUsage({ model: selectedModel, prompt, response: response.join('') })
|
|
533
|
+
: usage;
|
|
534
|
+
if (!agentUsageReported && usage === undefined && finalUsage !== undefined)
|
|
535
|
+
goalCallbacks?.onUsage({ usage: finalUsage, modelCalls: 1 });
|
|
536
|
+
this.renderer.complete(Date.now() - startedAt, finalUsage);
|
|
537
|
+
await this.refreshContextUsage();
|
|
538
|
+
return response.join('');
|
|
539
|
+
}
|
|
540
|
+
commandContext() {
|
|
541
|
+
return { write: (message) => this.renderer.commandOutput(message) };
|
|
542
|
+
}
|
|
543
|
+
getActiveModel() { return this.activeModel; }
|
|
544
|
+
getActiveProfile() { return this.activeProfile; }
|
|
545
|
+
async refreshExtensions() {
|
|
546
|
+
const identity = await this.runtime.projectTrust.inspect(this.cwd);
|
|
547
|
+
const trusted = await this.runtime.projectTrust.isTrusted(identity);
|
|
548
|
+
const loaded = await this.runtime.configLoader.load(this.cwd, { includeProject: trusted });
|
|
549
|
+
await this.reloadExtensions(trusted, loaded.config.approvalMode, identity.canonicalPath);
|
|
550
|
+
await this.refreshContextUsage();
|
|
551
|
+
}
|
|
552
|
+
async refreshWelcome(overrides = {}) {
|
|
553
|
+
const identity = await this.runtime.projectTrust.inspect(this.cwd);
|
|
554
|
+
const trusted = await this.runtime.projectTrust.isTrusted(identity);
|
|
555
|
+
const loaded = await this.runtime.configLoader.load(this.cwd, { includeProject: trusted });
|
|
556
|
+
this.activeModel = overrides.model === undefined ? (this.activeModel ?? loaded.config.model) : overrides.model;
|
|
557
|
+
this.activeProfile = overrides.profile === undefined ? (this.activeProfile ?? loaded.config.profile) : overrides.profile;
|
|
558
|
+
this.renderer.setWelcome({
|
|
559
|
+
version: CLI_VERSION,
|
|
560
|
+
cwd: identity.canonicalPath,
|
|
561
|
+
model: this.activeModel,
|
|
562
|
+
profile: this.activeProfile,
|
|
563
|
+
trusted,
|
|
564
|
+
});
|
|
565
|
+
await this.refreshContextUsage();
|
|
566
|
+
}
|
|
567
|
+
async getContextSnapshot() {
|
|
568
|
+
const model = this.activeModel ?? this.session?.model ?? null;
|
|
569
|
+
const activeGoal = this.session === undefined ? undefined : await this.runtime.goalStore.get(this.session.id);
|
|
570
|
+
const snapshot = await this.contextService.buildForProject({
|
|
571
|
+
...(this.session === undefined ? {} : { sessionId: this.session.id }),
|
|
572
|
+
model,
|
|
573
|
+
profileName: this.activeProfile ?? this.session?.profile ?? null,
|
|
574
|
+
pluginNames: this.enabledPluginNames,
|
|
575
|
+
pluginMcpConfig: this.pluginMcpConfig,
|
|
576
|
+
pendingAttachments: this.pendingAttachments.size,
|
|
577
|
+
skillRootScopes: this.skillRootScopes,
|
|
578
|
+
agentSessionStore: this.agentSessionStore,
|
|
579
|
+
...(activeGoal === undefined ? {} : { goal: { objective: activeGoal.objective, status: activeGoal.status, turns: activeGoal.turns, evaluatorRuns: activeGoal.evaluatorRuns, tokensUsed: activeGoal.usage.totalTokens, ...(activeGoal.tokenBudget === undefined ? {} : { tokenBudget: activeGoal.tokenBudget }), ...(activeGoal.maxTurns === undefined ? {} : { maxTurns: activeGoal.maxTurns }), ...(activeGoal.maxDurationMs === undefined ? {} : { maxDurationMs: activeGoal.maxDurationMs }), ...(activeGoal.lastError === undefined ? {} : { lastError: activeGoal.lastError }), ...(activeGoal.lastEvaluation === undefined ? {} : { lastEvaluation: activeGoal.lastEvaluation.reason }) } }),
|
|
580
|
+
});
|
|
581
|
+
this.renderer.setContextUsage({ usedTokens: snapshot.usedTokens, ...(snapshot.contextWindow === undefined ? {} : { contextWindow: snapshot.contextWindow }) });
|
|
582
|
+
return snapshot;
|
|
583
|
+
}
|
|
584
|
+
async refreshContextUsage() {
|
|
585
|
+
try {
|
|
586
|
+
await this.getContextSnapshot();
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
this.runtime.logger.debug('Unable to refresh context usage.', { reason: error instanceof Error ? error.message : String(error) });
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
async runSkill(name, args, context, availableSkills, scope) {
|
|
593
|
+
await runTuiSkill({ globalConfigDir: this.runtime.paths.globalConfigDir, skillRootScopes: this.skillRootScopes, runPrompt: (prompt, skill) => this.sendPrompt(prompt, this.pendingAttachments.list(), skill) }, name, args, context, scope, availableSkills);
|
|
594
|
+
}
|
|
595
|
+
async reloadExtensions(trusted, approvalMode, workspaceRoot) {
|
|
596
|
+
const approval = this.approvals.create(approvalMode, trusted, workspaceRoot);
|
|
597
|
+
this.hookRuntime = new HookRuntime(new ShellToolExecutor({ platform: this.runtime.platform }), { trustedProject: trusted, enabled: true, toolPolicy: new ToolPolicy(approval.policy()) });
|
|
598
|
+
this.skillRootScopes = resolveSkillRootScopes(this.cwd, this.runtime.paths.globalConfigDir);
|
|
599
|
+
this.enabledPluginNames = [];
|
|
600
|
+
this.pluginMcpConfig = {};
|
|
601
|
+
this.hooks = [];
|
|
602
|
+
if (!trusted)
|
|
603
|
+
return;
|
|
604
|
+
const contributions = await new PluginContributionRegistry(this.runtime.paths.globalConfigDir).resolve(this.cwd, true);
|
|
605
|
+
this.skillRootScopes = resolveSkillRootScopes(this.cwd, this.runtime.paths.globalConfigDir, contributions.skillRoots);
|
|
606
|
+
this.enabledPluginNames = contributions.plugins.map((plugin) => plugin.name);
|
|
607
|
+
this.pluginMcpConfig = contributions.mcpConfig;
|
|
608
|
+
const discoveredHooks = [...await this.hookRuntime.loadProject(workspaceRoot)];
|
|
609
|
+
for (const plugin of contributions.plugins)
|
|
610
|
+
discoveredHooks.push(...await this.hookRuntime.load(plugin));
|
|
611
|
+
this.hooks = discoveredHooks;
|
|
612
|
+
}
|
|
613
|
+
async compactSession() {
|
|
614
|
+
await compactManualTuiSession({ runtime: this.runtime, cwd: this.cwd, session: this.session, activeModel: this.activeModel, activeProfile: this.activeProfile, activeResponse: this.activeAbortController !== undefined, renderer: this.renderer, contextService: this.contextService, agentSessionStore: this.agentSessionStore, refreshContextUsage: () => this.refreshContextUsage() });
|
|
615
|
+
}
|
|
616
|
+
async resumeSession(sessionId) {
|
|
617
|
+
if (this.activePromptRun !== undefined)
|
|
618
|
+
throw new Error('Stop the active response before resuming another session.');
|
|
619
|
+
const identity = await this.runtime.projectTrust.inspect(this.cwd);
|
|
620
|
+
const next = await new ProjectSessionAccess(this.runtime.sessionStore).require(sessionId, identity.fingerprint);
|
|
621
|
+
if (next.id === this.session?.id) {
|
|
622
|
+
this.renderer.notice(`Already using session: ${next.id}`);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
const transcript = await this.runtime.sessionStore.readTranscript(next.id);
|
|
626
|
+
const previous = this.session;
|
|
627
|
+
if (previous !== undefined) {
|
|
628
|
+
await this.runHookEvent('session.end', this.cwd, previous.id);
|
|
629
|
+
await this.runtime.sessionStore.updateStatus(previous.id, 'completed');
|
|
630
|
+
}
|
|
631
|
+
this.session = await this.runtime.sessionStore.updateStatus(next.id, 'active');
|
|
632
|
+
const loaded = await loadExecutionConfig(this.runtime, this.cwd);
|
|
633
|
+
this.activeModel = next.model ?? loaded.config.model;
|
|
634
|
+
this.activeProfile = next.profile ?? loaded.config.profile;
|
|
635
|
+
this.renderer.setWelcome({
|
|
636
|
+
version: CLI_VERSION,
|
|
637
|
+
cwd: identity.canonicalPath,
|
|
638
|
+
model: this.activeModel,
|
|
639
|
+
profile: this.activeProfile,
|
|
640
|
+
trusted: await this.runtime.projectTrust.isTrusted(identity),
|
|
641
|
+
});
|
|
642
|
+
this.renderer.clearTranscript();
|
|
643
|
+
for (const entry of retainLatestCompaction(transcript)) {
|
|
644
|
+
if (entry.type === 'user')
|
|
645
|
+
this.renderer.userPrompt(entry.content);
|
|
646
|
+
else if (entry.type === 'assistant') {
|
|
647
|
+
this.renderer.beginAssistant();
|
|
648
|
+
this.renderer.assistantDelta(entry.content);
|
|
649
|
+
this.renderer.finishAssistant();
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
await this.refreshContextUsage();
|
|
653
|
+
await this.runHookEvent('session.start', identity.canonicalPath, next.id);
|
|
654
|
+
this.renderer.notice(`Resumed session: ${next.id}`);
|
|
655
|
+
}
|
|
656
|
+
handleInterrupt() {
|
|
657
|
+
const active = this.activeAbortController;
|
|
658
|
+
const next = handleTuiInterrupt({ lastInterruptAt: this.lastInterruptAt, exitArmedUntil: this.exitArmedUntil, printResumeCommandOnExit: this.printResumeCommandOnExit }, active, this.renderer);
|
|
659
|
+
this.lastInterruptAt = next.lastInterruptAt;
|
|
660
|
+
this.exitArmedUntil = next.exitArmedUntil;
|
|
661
|
+
this.printResumeCommandOnExit = next.printResumeCommandOnExit;
|
|
662
|
+
}
|
|
663
|
+
async awaitActiveForegroundRun() {
|
|
664
|
+
const run = this.activeForegroundRun;
|
|
665
|
+
if (run === undefined)
|
|
666
|
+
return;
|
|
667
|
+
try {
|
|
668
|
+
await run;
|
|
669
|
+
}
|
|
670
|
+
catch (error) {
|
|
671
|
+
this.runtime.logger.warn('Foreground TUI operation failed during shutdown.', { reason: error instanceof Error ? error.message : String(error) });
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
async runHookEvent(event, cwd, sessionId) { await runTuiHookEvent(this.hookRuntime, this.hooks, event, cwd, sessionId); }
|
|
675
|
+
}
|