@lotagate/cli 0.1.21 → 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 +8 -7
- package/scripts/install-native.mjs +11 -11
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Writable } from 'node:stream';
|
|
2
|
+
import { AuthenticationService } from '../auth/authentication-service.js';
|
|
3
|
+
import { ChatService } from '../chat/chat-service.js';
|
|
4
|
+
import { createLotaGateClient } from '../../infrastructure/sdk/lotagate-client-factory.js';
|
|
5
|
+
import { SdkChatCompletionAdapter } from '../../infrastructure/sdk/chat-completion-adapter.js';
|
|
6
|
+
import { CliError } from '../../domain/errors/cli-error.js';
|
|
7
|
+
import { CLI_ERROR_CODES } from '../../domain/errors/error-codes.js';
|
|
8
|
+
import { MODEL_SELECT_HINT } from './command-hints.js';
|
|
9
|
+
import { createImageAttachment, DEFAULT_MAX_IMAGE_BYTES, normalizeImage } from '../../infrastructure/clipboard/image-normalizer.js';
|
|
10
|
+
import { buildSafeSystemPrompt } from '../agent/safe-system-prompt.js';
|
|
11
|
+
import { readJsonFileBounded } from '../../infrastructure/filesystem/bounded-json-reader.js';
|
|
12
|
+
import { readFileBounded } from '../../infrastructure/filesystem/bounded-file-reader.js';
|
|
13
|
+
import { RESOURCE_LIMITS } from '../../domain/runtime/resource-limits.js';
|
|
14
|
+
import { ProjectSessionAccess } from '../session/project-session-access.js';
|
|
15
|
+
import { compactStoredSession } from '../session/session-compaction-service.js';
|
|
16
|
+
import { requirePositional, getFlag, isFlagEnabled, requireStringFlag } from './cli-args.js';
|
|
17
|
+
import { resolveExternalPath, resolveWorkspacePath } from '../../infrastructure/filesystem/path-resolver.js';
|
|
18
|
+
import { atomicWriteFile } from '../../infrastructure/filesystem/atomic-file-store.js';
|
|
19
|
+
import { loadExecutionConfig } from '../config/execution-config.js';
|
|
20
|
+
import { runHeadlessAgentTurn } from '../orchestration/headless-agent-turn.js';
|
|
21
|
+
import { writeStreamChunk } from './stream-output.js';
|
|
22
|
+
import { formatCompactTable } from '../formatting/compact-table.js';
|
|
23
|
+
export async function runSessionCommand(positionals, flags, runtime, cwd, stdout, resumeInteractive) {
|
|
24
|
+
const action = positionals[0] ?? 'list';
|
|
25
|
+
const identity = await runtime.projectTrust.inspect(cwd);
|
|
26
|
+
if (action === 'list') {
|
|
27
|
+
const sessions = await runtime.sessionStore.list(identity.fingerprint);
|
|
28
|
+
stdout.write(`${formatCompactTable(sessions.map((session) => ({ name: session.name ?? session.id, status: session.status.toUpperCase(), detail: `${session.id} · ${session.model ?? 'no model'} · ${session.updatedAt}` })), { empty: 'No sessions found.' })}\n`);
|
|
29
|
+
return 0;
|
|
30
|
+
}
|
|
31
|
+
if (action === 'import') {
|
|
32
|
+
const file = requireStringFlag(flags, 'file');
|
|
33
|
+
const bundlePath = await resolveWorkspacePath(file, { cwd, workspaceRoot: cwd });
|
|
34
|
+
const bundle = await readJsonFileBounded(bundlePath, RESOURCE_LIMITS.sessionBundleBytes);
|
|
35
|
+
const imported = await runtime.sessionStore.import(bundle, identity.fingerprint, cwd);
|
|
36
|
+
stdout.write(`${JSON.stringify(imported, null, 2)}\n`);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
const sessionId = requirePositional(positionals, 1, 'session id');
|
|
40
|
+
const session = await new ProjectSessionAccess(runtime.sessionStore).require(sessionId, identity.fingerprint);
|
|
41
|
+
if (action === 'show') {
|
|
42
|
+
stdout.write(`${JSON.stringify({ metadata: session, transcript: await runtime.sessionStore.readTranscript(sessionId) }, null, 2)}\n`);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
if (action === 'resume') {
|
|
46
|
+
if (isFlagEnabled(flags, 'interactive')) {
|
|
47
|
+
if (!(stdout instanceof Writable))
|
|
48
|
+
throw new Error('Interactive session resume requires a terminal output stream.');
|
|
49
|
+
if (resumeInteractive === undefined)
|
|
50
|
+
throw new Error('Interactive session resume is unavailable in this command host.');
|
|
51
|
+
return resumeInteractive(sessionId);
|
|
52
|
+
}
|
|
53
|
+
stdout.write(`${JSON.stringify({ metadata: session, transcript: await runtime.sessionStore.readTranscript(sessionId), resumable: session.status !== 'active' }, null, 2)}\n`);
|
|
54
|
+
return 0;
|
|
55
|
+
}
|
|
56
|
+
if (action === 'fork') {
|
|
57
|
+
const forked = await runtime.sessionStore.fork(sessionId);
|
|
58
|
+
stdout.write(`${JSON.stringify(forked, null, 2)}\n`);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
if (action === 'compact') {
|
|
62
|
+
if (positionals.length > 2)
|
|
63
|
+
throw new CliError(CLI_ERROR_CODES.INVALID_ARGUMENT, 'Compaction does not accept a summary.', { category: 'session', userMessage: 'The compact command does not accept a summary. It summarizes the session automatically.' });
|
|
64
|
+
const result = await compactStoredSession(runtime, cwd, sessionId);
|
|
65
|
+
stdout.write(`${result.compacted ? `Compacted session: ${sessionId}` : `No conversation to compact: ${sessionId}`}\n`);
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
if (action === 'export') {
|
|
69
|
+
const bundle = await runtime.sessionStore.export(sessionId);
|
|
70
|
+
const outputPath = getFlag(flags, 'out');
|
|
71
|
+
const serialized = `${JSON.stringify(bundle, null, 2)}\n`;
|
|
72
|
+
if (typeof outputPath === 'string' && outputPath.trim().length > 0) {
|
|
73
|
+
const resolvedOutput = await resolveWorkspacePath(outputPath, { cwd, workspaceRoot: cwd }, true);
|
|
74
|
+
await atomicWriteFile(resolvedOutput, serialized);
|
|
75
|
+
stdout.write(`Exported session: ${resolvedOutput}\n`);
|
|
76
|
+
}
|
|
77
|
+
else
|
|
78
|
+
stdout.write(serialized);
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
if (action === 'recover') {
|
|
82
|
+
stdout.write(`${JSON.stringify({ sessionId, recovered: await runtime.sessionStore.recoverStaleLock(sessionId) })}\n`);
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
if (action === 'repair') {
|
|
86
|
+
stdout.write(`${JSON.stringify(await runtime.sessionStore.repair(sessionId))}\n`);
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
if (action === 'delete') {
|
|
90
|
+
const deleted = await runtime.sessionStore.delete(sessionId);
|
|
91
|
+
stdout.write(`${deleted ? `Deleted session: ${sessionId}` : `Session not found: ${sessionId}`}\n`);
|
|
92
|
+
return deleted ? 0 : 1;
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`Unsupported session action: ${action}`);
|
|
95
|
+
}
|
|
96
|
+
export async function runChatCommand(positionals, runtime, cwd, stdout) {
|
|
97
|
+
const prompt = positionals.join(' ').trim();
|
|
98
|
+
if (prompt.length === 0) {
|
|
99
|
+
stdout.write('Interactive prompt editor requires a terminal. Run `lotagate` in a terminal or use `lotagate chat "prompt"` for streaming.\n');
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
const loaded = await loadExecutionConfig(runtime, cwd);
|
|
103
|
+
if (loaded.config.model === null)
|
|
104
|
+
throw new CliError(CLI_ERROR_CODES.MODEL_NOT_FOUND, 'No model is selected.', { category: 'model', userMessage: 'No model is selected.', hint: MODEL_SELECT_HINT });
|
|
105
|
+
const profileName = loaded.config.profile ?? AuthenticationService.defaultProfileName();
|
|
106
|
+
const credential = await runtime.auth.requireCredential(profileName);
|
|
107
|
+
const client = createLotaGateClient(credential.profile, credential.apiKey);
|
|
108
|
+
const abortController = new AbortController();
|
|
109
|
+
const onInterrupt = () => abortController.abort();
|
|
110
|
+
process.once('SIGINT', onInterrupt);
|
|
111
|
+
try {
|
|
112
|
+
const service = new ChatService(new SdkChatCompletionAdapter(client));
|
|
113
|
+
const system = await buildSafeSystemPrompt(runtime, cwd, loaded.config.model, 'headless-safe');
|
|
114
|
+
for await (const event of service.stream(loaded.config.model, prompt, { system, signal: abortController.signal }))
|
|
115
|
+
if (event.type === 'delta')
|
|
116
|
+
await writeStreamChunk(stdout, event.content);
|
|
117
|
+
await writeStreamChunk(stdout, '\n');
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
process.off('SIGINT', onInterrupt);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export async function runExecCommand(positionals, flags, runtime, cwd, stdout) {
|
|
125
|
+
const prompt = positionals.join(' ').trim();
|
|
126
|
+
if (prompt.length === 0)
|
|
127
|
+
throw new CliError(CLI_ERROR_CODES.MISSING_ARGUMENT, 'Missing prompt.', { category: 'arguments', userMessage: 'A prompt is required for exec.' });
|
|
128
|
+
const loaded = await loadExecutionConfig(runtime, cwd);
|
|
129
|
+
if (loaded.config.model === null)
|
|
130
|
+
throw new CliError(CLI_ERROR_CODES.MODEL_NOT_FOUND, 'No model is selected.', { category: 'model', userMessage: 'No model is selected.', hint: MODEL_SELECT_HINT });
|
|
131
|
+
const profileName = loaded.config.profile ?? AuthenticationService.defaultProfileName();
|
|
132
|
+
const credential = await runtime.auth.requireCredential(profileName);
|
|
133
|
+
const imageFlag = getFlag(flags, 'image');
|
|
134
|
+
const attachments = [];
|
|
135
|
+
let attachmentBytes = 0;
|
|
136
|
+
if (typeof imageFlag === 'string') {
|
|
137
|
+
for (const [index, imagePath] of imageFlag.split(',').map((item) => item.trim()).filter(Boolean).entries()) {
|
|
138
|
+
if (attachments.length >= RESOURCE_LIMITS.pendingAttachments)
|
|
139
|
+
throw new CliError(CLI_ERROR_CODES.ATTACHMENT_TOO_LARGE, 'Too many images were supplied.', { category: 'attachment', userMessage: 'Too many images were supplied. Reduce the image list and retry.' });
|
|
140
|
+
const resolvedImagePath = await resolveExternalPath(imagePath, { cwd });
|
|
141
|
+
const image = await readFileBounded(resolvedImagePath, DEFAULT_MAX_IMAGE_BYTES);
|
|
142
|
+
if (image.truncated)
|
|
143
|
+
throw new CliError(CLI_ERROR_CODES.ATTACHMENT_TOO_LARGE, 'Image exceeds the supported size.', { category: 'attachment', userMessage: 'An image exceeds the supported size limit.' });
|
|
144
|
+
const normalized = normalizeImage(image.bytes);
|
|
145
|
+
attachmentBytes += normalized.bytes.byteLength;
|
|
146
|
+
if (attachmentBytes > RESOURCE_LIMITS.pendingAttachmentTotalBytes)
|
|
147
|
+
throw new CliError(CLI_ERROR_CODES.ATTACHMENT_TOO_LARGE, 'Image attachment total exceeds the supported limit.', { category: 'attachment', userMessage: 'The combined image size is too large. Reduce the image list and retry.' });
|
|
148
|
+
attachments.push({ attachment: createImageAttachment(normalized, 'file', `image-${index + 1}`, imagePath), bytes: normalized.bytes });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const json = isFlagEnabled(flags, 'json') || isFlagEnabled(flags, 'jsonl');
|
|
152
|
+
const abortController = new AbortController();
|
|
153
|
+
const onInterrupt = () => abortController.abort();
|
|
154
|
+
process.once('SIGINT', onInterrupt);
|
|
155
|
+
try {
|
|
156
|
+
const client = createLotaGateClient(credential.profile, credential.apiKey);
|
|
157
|
+
if (attachments.length > 0) {
|
|
158
|
+
const service = new ChatService(new SdkChatCompletionAdapter(client));
|
|
159
|
+
const system = await buildSafeSystemPrompt(runtime, cwd, loaded.config.model, 'headless-safe');
|
|
160
|
+
for await (const event of service.stream(loaded.config.model, prompt, { system, signal: abortController.signal, attachments })) {
|
|
161
|
+
if (json)
|
|
162
|
+
await writeStreamChunk(stdout, `${JSON.stringify(event)}\n`);
|
|
163
|
+
else if (event.type === 'delta')
|
|
164
|
+
await writeStreamChunk(stdout, event.content);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
await runHeadlessAgentTurn({ runtime, cwd, model: loaded.config.model, client, prompt, output: stdout, json, signal: abortController.signal });
|
|
169
|
+
}
|
|
170
|
+
if (!json)
|
|
171
|
+
await writeStreamChunk(stdout, '\n');
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
process.off('SIGINT', onInterrupt);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { once } from 'node:events';
|
|
2
|
+
/** Writes streamed CLI output without allowing a slow pipe to grow memory unboundedly. */
|
|
3
|
+
export async function writeStreamChunk(output, value) {
|
|
4
|
+
if (output.write(value) !== false || !isWritable(output))
|
|
5
|
+
return;
|
|
6
|
+
await once(output, 'drain');
|
|
7
|
+
}
|
|
8
|
+
function isWritable(value) {
|
|
9
|
+
return typeof value.once === 'function';
|
|
10
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
|
|
2
|
+
import type { CommandOutput } from './command-output.js';
|
|
3
|
+
export declare function runDoctorCommand(runtime: CliRuntime, cwd: string, stdout: CommandOutput): Promise<number>;
|
|
4
|
+
export declare function runInspectCommand(runtime: CliRuntime, cwd: string, stdout: CommandOutput): Promise<number>;
|
|
5
|
+
export declare function runCompletionsCommand(positionals: readonly string[], stdout: CommandOutput): Promise<number>;
|
|
6
|
+
export declare function runUpdateCommand(positionals: readonly string[], runtime: CliRuntime, cwd: string, stdout: CommandOutput): Promise<number>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { CLI_ERROR_CODES } from '../../domain/errors/error-codes.js';
|
|
2
|
+
import { CliError } from '../../domain/errors/cli-error.js';
|
|
3
|
+
import { CLI_VERSION } from '../../version.js';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { AuthenticationService } from '../auth/authentication-service.js';
|
|
6
|
+
import { loadExecutionConfig } from '../config/execution-config.js';
|
|
7
|
+
import { formatCompactTable } from '../formatting/compact-table.js';
|
|
8
|
+
import { COMMAND_REGISTRY } from './command-runtime.js';
|
|
9
|
+
export async function runDoctorCommand(runtime, cwd, stdout) {
|
|
10
|
+
const config = await loadExecutionConfig(runtime, cwd);
|
|
11
|
+
const identity = await runtime.projectTrust.inspect(cwd);
|
|
12
|
+
const profile = config.config.profile ?? AuthenticationService.defaultProfileName();
|
|
13
|
+
const credential = await runtime.credentialStore.get(profile);
|
|
14
|
+
const checks = [
|
|
15
|
+
{ name: 'node', ok: Number(process.versions.node.split('.')[0]) >= 22, detail: process.version },
|
|
16
|
+
{ name: 'cwd', ok: path.isAbsolute(cwd), detail: cwd },
|
|
17
|
+
{ name: 'config', ok: true, detail: `${config.sources.length} file(s) loaded` },
|
|
18
|
+
{ name: 'auth', ok: credential !== undefined, detail: credential === undefined ? `profile ${profile} is not configured` : `profile ${profile} configured` },
|
|
19
|
+
{ name: 'project-trust', ok: await runtime.projectTrust.isTrusted(identity), detail: identity.canonicalPath },
|
|
20
|
+
];
|
|
21
|
+
const ok = checks.every((check) => check.ok);
|
|
22
|
+
stdout.write(`Doctor · ${ok ? 'OK' : 'FAIL'}\n${formatCompactTable(checks.map((check) => ({ name: check.name, status: check.ok ? 'OK' : 'FAIL', detail: check.detail })))}\n`);
|
|
23
|
+
return ok ? 0 : 1;
|
|
24
|
+
}
|
|
25
|
+
export async function runInspectCommand(runtime, cwd, stdout) {
|
|
26
|
+
stdout.write(`${JSON.stringify(await runtime.projectTrust.inspect(cwd), null, 2)}\n`);
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
export async function runCompletionsCommand(positionals, stdout) {
|
|
30
|
+
const shell = positionals[0] ?? 'powershell';
|
|
31
|
+
const commands = rootCommandNames();
|
|
32
|
+
const quotedCommands = commands.join(' ');
|
|
33
|
+
const powershellCommands = commands.map((command) => `"${command}"`).join(',');
|
|
34
|
+
const scripts = {
|
|
35
|
+
bash: `_lotagate_complete() { COMPREPLY=( $(compgen -W "${quotedCommands}" -- "\${COMP_WORDS[COMP_CWORD]}") ); }; complete -F _lotagate_complete lotagate\n`,
|
|
36
|
+
zsh: `#compdef lotagate\n_arguments "1:command:(${quotedCommands})"\n`,
|
|
37
|
+
powershell: `Register-ArgumentCompleter -CommandName lotagate -ScriptBlock { param($wordToComplete) ${powershellCommands} | Where-Object { $_ -like "$wordToComplete*" } }\n`,
|
|
38
|
+
};
|
|
39
|
+
const script = scripts[shell];
|
|
40
|
+
if (script === undefined)
|
|
41
|
+
throw new CliError(CLI_ERROR_CODES.INVALID_ARGUMENT, `Unsupported shell: ${shell}`, { category: 'arguments', userMessage: 'Unsupported shell. Choose bash, zsh, or powershell.' });
|
|
42
|
+
stdout.write(script);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
function rootCommandNames() {
|
|
46
|
+
return [...new Set(COMMAND_REGISTRY.list('direct').map((action) => action.path[0]))];
|
|
47
|
+
}
|
|
48
|
+
export async function runUpdateCommand(positionals, runtime, cwd, stdout) {
|
|
49
|
+
if ((positionals[0] ?? 'check') !== 'check')
|
|
50
|
+
throw new CliError(CLI_ERROR_CODES.INVALID_ARGUMENT, 'Unsupported update action.', { category: 'update', userMessage: 'Only `lotagate update check` is supported.' });
|
|
51
|
+
const config = await loadExecutionConfig(runtime, cwd);
|
|
52
|
+
const registry = process.env['LOTAGATE_NPM_REGISTRY']?.trim() || 'https://registry.npmjs.org';
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
55
|
+
try {
|
|
56
|
+
const response = await fetch(`${registry.replace(/\/$/u, '')}/@lotagate%2fcli/latest`, { signal: controller.signal, headers: { accept: 'application/json' } });
|
|
57
|
+
if (!response.ok)
|
|
58
|
+
throw new Error(`Registry returned HTTP ${response.status}.`);
|
|
59
|
+
const payload = await response.json();
|
|
60
|
+
if (typeof payload.version !== 'string' || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u.test(payload.version))
|
|
61
|
+
throw new Error('Registry response did not contain a valid version.');
|
|
62
|
+
stdout.write(`${JSON.stringify({ currentVersion: CLI_VERSION, latestVersion: payload.version, channel: config.config.updateChannel, updateAvailable: compareVersions(payload.version, CLI_VERSION) > 0, installation: 'manual' }, null, 2)}\n`);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
stdout.write(`${JSON.stringify({ currentVersion: CLI_VERSION, channel: config.config.updateChannel, checked: false, reason: error instanceof Error ? error.message : 'Unable to query the registry.', installation: 'manual' }, null, 2)}\n`);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
clearTimeout(timeout);
|
|
69
|
+
}
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
function compareVersions(left, right) {
|
|
73
|
+
const parse = (value) => (value.split('-')[0] ?? '').split('.').map((part) => Number(part));
|
|
74
|
+
const a = parse(left);
|
|
75
|
+
const b = parse(right);
|
|
76
|
+
for (let index = 0; index < 3; index += 1) {
|
|
77
|
+
if ((a[index] ?? 0) !== (b[index] ?? 0))
|
|
78
|
+
return (a[index] ?? 0) - (b[index] ?? 0);
|
|
79
|
+
}
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { createCompositionRoot } from '../../bootstrap/composition-root.js';
|
|
2
|
+
import type { ConfigLoadResult } from '../../infrastructure/config/config-loader.js';
|
|
3
|
+
/** Loads project configuration only after the project trust boundary is known. */
|
|
4
|
+
export declare function loadExecutionConfig(runtime: ReturnType<typeof createCompositionRoot>, cwd: string): Promise<ConfigLoadResult>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Loads project configuration only after the project trust boundary is known. */
|
|
2
|
+
export async function loadExecutionConfig(runtime, cwd) {
|
|
3
|
+
const identity = await runtime.projectTrust.inspect(cwd);
|
|
4
|
+
const trusted = await runtime.projectTrust.isTrusted(identity);
|
|
5
|
+
return runtime.configLoader.load(cwd, { includeProject: trusted });
|
|
6
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExtensionScope } from '../../domain/extensions/extension-scope.js';
|
|
2
|
+
export type ExtensionListKind = 'hook' | 'skill' | 'plugin' | 'mcp';
|
|
3
|
+
export type ExtensionListScope = ExtensionScope | 'plugin' | 'builtin';
|
|
4
|
+
export interface ExtensionListItem {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly status: string;
|
|
7
|
+
readonly detail: string;
|
|
8
|
+
readonly scope?: ExtensionListScope;
|
|
9
|
+
}
|
|
10
|
+
export interface ExtensionListResult {
|
|
11
|
+
readonly kind: ExtensionListKind;
|
|
12
|
+
readonly items: readonly ExtensionListItem[];
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { HookDefinition } from '../../domain/extensions/hook-manifest.js';
|
|
2
|
+
import type { CliMcpConfig, CliMcpServerConfig } from '../../domain/extensions/mcp-config.js';
|
|
3
|
+
import type { InstalledPlugin } from '../../infrastructure/extensions/plugin-manager.js';
|
|
4
|
+
import type { ScopedSkill } from '../../infrastructure/extensions/skill-manager.js';
|
|
5
|
+
import type { ExtensionScope } from '../../domain/extensions/extension-scope.js';
|
|
6
|
+
import type { ExtensionListResult } from './extension-list-contract.js';
|
|
7
|
+
export declare function formatMcpList(entries: readonly {
|
|
8
|
+
scope: ExtensionScope;
|
|
9
|
+
config: CliMcpConfig;
|
|
10
|
+
}[]): string;
|
|
11
|
+
export declare function createMcpListResult(entries: readonly {
|
|
12
|
+
scope: ExtensionScope;
|
|
13
|
+
config: CliMcpConfig;
|
|
14
|
+
}[]): ExtensionListResult;
|
|
15
|
+
export declare function formatExtensionList(result: ExtensionListResult): string;
|
|
16
|
+
export declare function formatMcpDetails(name: string, scope: ExtensionScope, entry: {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
config: CliMcpServerConfig;
|
|
19
|
+
} | undefined): string;
|
|
20
|
+
export declare function formatPluginList(entries: readonly {
|
|
21
|
+
scope: ExtensionScope;
|
|
22
|
+
plugins: readonly InstalledPlugin[];
|
|
23
|
+
}[]): string;
|
|
24
|
+
export declare function createPluginListResult(entries: readonly {
|
|
25
|
+
scope: ExtensionScope;
|
|
26
|
+
plugins: readonly InstalledPlugin[];
|
|
27
|
+
}[]): ExtensionListResult;
|
|
28
|
+
export declare function formatSkillList(skills: readonly ScopedSkill[]): string;
|
|
29
|
+
export declare function createSkillListResult(skills: readonly ScopedSkill[]): ExtensionListResult;
|
|
30
|
+
export declare function formatHookList(hooks: readonly HookDefinition[]): string;
|
|
31
|
+
export declare function createHookListResult(hooks: readonly HookDefinition[]): ExtensionListResult;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { formatCompactTable } from '../formatting/compact-table.js';
|
|
2
|
+
const SKILL_LIST_DESCRIPTION_MAX_CHARACTERS = 240;
|
|
3
|
+
const SKILL_LIST_TABLE_MAX_WIDTH = 280;
|
|
4
|
+
export function formatMcpList(entries) {
|
|
5
|
+
return formatExtensionList(createMcpListResult(entries));
|
|
6
|
+
}
|
|
7
|
+
export function createMcpListResult(entries) {
|
|
8
|
+
const items = entries.flatMap(({ scope, config }) => Object.entries(config).map(([name, entry]) => ({ name, scope, entry })));
|
|
9
|
+
return {
|
|
10
|
+
kind: 'mcp',
|
|
11
|
+
items: items
|
|
12
|
+
.sort((left, right) => left.name.localeCompare(right.name) || left.scope.localeCompare(right.scope))
|
|
13
|
+
.map(({ name, scope, entry }) => ({ name, status: entry.enabled ? 'ENABLED' : 'DISABLED', detail: `${scope} · ${formatMcpTarget(entry.config)}`, scope })),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function formatExtensionList(result) {
|
|
17
|
+
if (result.kind === 'mcp')
|
|
18
|
+
return formatCompactTable(result.items, { empty: 'No MCP servers configured.' });
|
|
19
|
+
if (result.kind === 'plugin')
|
|
20
|
+
return formatCompactTable(result.items, { empty: 'No plugins installed.' });
|
|
21
|
+
if (result.kind === 'skill')
|
|
22
|
+
return formatCompactTable(result.items, { empty: 'No skills available.', maxWidth: SKILL_LIST_TABLE_MAX_WIDTH });
|
|
23
|
+
return formatCompactTable(result.items, { empty: 'No hooks are loaded. Hooks require a trusted project.' });
|
|
24
|
+
}
|
|
25
|
+
export function formatMcpDetails(name, scope, entry) {
|
|
26
|
+
if (entry === undefined)
|
|
27
|
+
return `MCP server not found: ${name}.`;
|
|
28
|
+
const config = entry.config.type === 'stdio'
|
|
29
|
+
? { type: configType(entry.config), command: redact(entry.config.command), args: entry.config.args?.map(redact) ?? [], credentials: hasCredentials(entry.config) }
|
|
30
|
+
: { type: configType(entry.config), url: redactUrl(entry.config.url), credentials: hasCredentials(entry.config) };
|
|
31
|
+
return JSON.stringify({ name, scope, enabled: entry.enabled, ...config });
|
|
32
|
+
}
|
|
33
|
+
export function formatPluginList(entries) {
|
|
34
|
+
return formatExtensionList(createPluginListResult(entries));
|
|
35
|
+
}
|
|
36
|
+
export function createPluginListResult(entries) {
|
|
37
|
+
const items = entries.flatMap(({ scope, plugins }) => plugins.map((plugin) => ({ scope, plugin })));
|
|
38
|
+
return {
|
|
39
|
+
kind: 'plugin',
|
|
40
|
+
items: items
|
|
41
|
+
.sort((left, right) => left.plugin.manifest.name.localeCompare(right.plugin.manifest.name) || left.scope.localeCompare(right.scope))
|
|
42
|
+
.map(({ scope, plugin }) => ({ name: plugin.manifest.name, status: plugin.enabled ? 'ENABLED' : 'DISABLED', detail: `${scope} · v${plugin.manifest.version}`, scope })),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function formatSkillList(skills) {
|
|
46
|
+
return formatExtensionList(createSkillListResult(skills));
|
|
47
|
+
}
|
|
48
|
+
export function createSkillListResult(skills) {
|
|
49
|
+
return {
|
|
50
|
+
kind: 'skill',
|
|
51
|
+
items: [...skills]
|
|
52
|
+
.sort((left, right) => left.skillKey.localeCompare(right.skillKey))
|
|
53
|
+
.map((skill) => ({ name: skill.skillKey, status: skill.enabled ? 'ENABLED' : 'DISABLED', detail: `${skill.scope} · ${truncate(redact(skill.description), SKILL_LIST_DESCRIPTION_MAX_CHARACTERS)}`, scope: skill.scope })),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function formatHookList(hooks) {
|
|
57
|
+
return formatExtensionList(createHookListResult(hooks));
|
|
58
|
+
}
|
|
59
|
+
export function createHookListResult(hooks) {
|
|
60
|
+
return {
|
|
61
|
+
kind: 'hook',
|
|
62
|
+
items: [...hooks]
|
|
63
|
+
.sort((left, right) => left.id.localeCompare(right.id))
|
|
64
|
+
.map((hook) => ({ name: hook.id, status: hook.event, detail: `${truncate(redact([hook.command, ...hook.args].join(' ')), 160)} · ${hook.timeoutMs}ms` })),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function formatMcpTarget(config) {
|
|
68
|
+
if (config.type === 'stdio')
|
|
69
|
+
return truncate(redact([config.command, ...(config.args ?? [])].join(' ')), 160);
|
|
70
|
+
return `${config.type} · ${redactUrl(config.url)}`;
|
|
71
|
+
}
|
|
72
|
+
function configType(config) { return config.type; }
|
|
73
|
+
function hasCredentials(config) {
|
|
74
|
+
return config.type === 'stdio'
|
|
75
|
+
? config.env !== undefined && Object.keys(config.env).length > 0
|
|
76
|
+
: config.auth !== undefined || (config.headers !== undefined && Object.keys(config.headers).length > 0) || /(?:key|token|secret|password|auth)=/iu.test(config.url);
|
|
77
|
+
}
|
|
78
|
+
function redactUrl(value) {
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(value);
|
|
81
|
+
for (const key of url.searchParams.keys())
|
|
82
|
+
if (/(key|token|secret|password|auth)/iu.test(key))
|
|
83
|
+
url.searchParams.set(key, '[REDACTED]');
|
|
84
|
+
return truncate(url.toString(), 180);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return truncate(redact(value), 180);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function redact(value) {
|
|
91
|
+
return value
|
|
92
|
+
.replace(/Bearer\s+[^\s]+/giu, 'Bearer [REDACTED]')
|
|
93
|
+
.replace(/sk-[A-Za-z0-9_-]{8,}/gu, '[REDACTED]')
|
|
94
|
+
.replace(/(api[_-]?key|password|secret|token)\s*[:=]\s*[^\s,]+/giu, '$1=[REDACTED]');
|
|
95
|
+
}
|
|
96
|
+
function truncate(value, maximum) {
|
|
97
|
+
return value.length <= maximum ? value : `${value.slice(0, maximum - 3)}...`;
|
|
98
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CliMcpConfig } from '../../domain/extensions/mcp-config.js';
|
|
2
|
+
import type { PluginManifest } from '../../domain/extensions/plugin-manifest.js';
|
|
3
|
+
import type { PluginSkillRoot } from '../../infrastructure/extensions/skill-roots.js';
|
|
4
|
+
export interface PluginContributions {
|
|
5
|
+
plugins: readonly PluginManifest[];
|
|
6
|
+
skillRoots: readonly PluginSkillRoot[];
|
|
7
|
+
mcpConfig: CliMcpConfig;
|
|
8
|
+
}
|
|
9
|
+
/** Resolves only enabled, trusted declarative plugin contributions. */
|
|
10
|
+
export declare class PluginContributionRegistry {
|
|
11
|
+
private readonly globalConfigDirectory;
|
|
12
|
+
constructor(globalConfigDirectory: string);
|
|
13
|
+
resolve(cwd: string, trustedProject: boolean): Promise<PluginContributions>;
|
|
14
|
+
}
|
|
15
|
+
export declare function mergeMcpConfigContributions(...configs: readonly CliMcpConfig[]): CliMcpConfig;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { mergeMcpConfigs, validateMcpConfig } from '../../domain/extensions/mcp-config.js';
|
|
4
|
+
import { CliError } from '../../domain/errors/cli-error.js';
|
|
5
|
+
import { CLI_ERROR_CODES } from '../../domain/errors/error-codes.js';
|
|
6
|
+
import { PluginManager } from '../../infrastructure/extensions/plugin-manager.js';
|
|
7
|
+
import { readJsonFileBounded } from '../../infrastructure/filesystem/bounded-json-reader.js';
|
|
8
|
+
import { RESOURCE_LIMITS } from '../../domain/runtime/resource-limits.js';
|
|
9
|
+
/** Resolves only enabled, trusted declarative plugin contributions. */
|
|
10
|
+
export class PluginContributionRegistry {
|
|
11
|
+
globalConfigDirectory;
|
|
12
|
+
constructor(globalConfigDirectory) {
|
|
13
|
+
this.globalConfigDirectory = globalConfigDirectory;
|
|
14
|
+
}
|
|
15
|
+
async resolve(cwd, trustedProject) {
|
|
16
|
+
if (!trustedProject)
|
|
17
|
+
return { plugins: [], skillRoots: [], mcpConfig: {} };
|
|
18
|
+
const globalPlugins = path.join(this.globalConfigDirectory, 'plugins');
|
|
19
|
+
const projectPlugins = path.join(cwd, '.lotagate', 'plugins');
|
|
20
|
+
const plugins = selectProjectFirstPlugins([...await new PluginManager(projectPlugins).list(), ...await new PluginManager(globalPlugins).list()]);
|
|
21
|
+
const manifests = plugins.filter((plugin) => plugin.enabled).map((plugin) => plugin.manifest);
|
|
22
|
+
return {
|
|
23
|
+
plugins: manifests,
|
|
24
|
+
skillRoots: manifests.flatMap((plugin) => plugin.skillsDirectory === undefined ? [] : [{ root: path.join(plugin.directory, plugin.skillsDirectory), pluginName: plugin.name }]),
|
|
25
|
+
mcpConfig: await loadPluginMcpConfig(manifests),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function selectProjectFirstPlugins(plugins) {
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
return plugins.filter((plugin) => {
|
|
32
|
+
if (seen.has(plugin.manifest.name))
|
|
33
|
+
return false;
|
|
34
|
+
seen.add(plugin.manifest.name);
|
|
35
|
+
return true;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function loadPluginMcpConfig(plugins) {
|
|
39
|
+
const merged = {};
|
|
40
|
+
for (const plugin of plugins) {
|
|
41
|
+
if (plugin.mcpConfig === undefined)
|
|
42
|
+
continue;
|
|
43
|
+
const config = validateMcpConfig(await readJsonFileBounded(path.join(plugin.directory, plugin.mcpConfig), RESOURCE_LIMITS.mcpConfigBytes));
|
|
44
|
+
for (const [name, entry] of Object.entries(config)) {
|
|
45
|
+
const qualifiedName = qualifyPluginMcpServerName(plugin.name, name);
|
|
46
|
+
if (merged[qualifiedName] !== undefined)
|
|
47
|
+
throw duplicateMcpServer(qualifiedName);
|
|
48
|
+
merged[qualifiedName] = entry;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return merged;
|
|
52
|
+
}
|
|
53
|
+
function qualifyPluginMcpServerName(pluginName, serverName) {
|
|
54
|
+
const pluginToken = pluginName.replace(/^@/u, '').replace('/', '_');
|
|
55
|
+
const readable = `plugin_${pluginToken}_${serverName}`;
|
|
56
|
+
if (readable.length <= 64)
|
|
57
|
+
return readable;
|
|
58
|
+
const digest = createHash('sha256').update(`${pluginName}\0${serverName}`).digest('hex').slice(0, 12);
|
|
59
|
+
const suffix = `_${digest}_${serverName.slice(0, 8)}`;
|
|
60
|
+
const available = Math.max(1, 64 - 'plugin_'.length - suffix.length);
|
|
61
|
+
return `plugin_${pluginToken.slice(0, available)}${suffix}`;
|
|
62
|
+
}
|
|
63
|
+
export function mergeMcpConfigContributions(...configs) {
|
|
64
|
+
try {
|
|
65
|
+
return mergeMcpConfigs(...configs);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error instanceof CliError && error.code === CLI_ERROR_CODES.MCP_CONFIG_INVALID) {
|
|
69
|
+
const message = error.message.replace(/^Invalid MCP configuration: /u, '');
|
|
70
|
+
throw duplicateMcpServer(message.replace(/\.$/u, '').replace(/^MCP server is defined more than once: /u, ''));
|
|
71
|
+
}
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function duplicateMcpServer(name) {
|
|
76
|
+
return new CliError(CLI_ERROR_CODES.MCP_CONFIG_INVALID, `Multiple MCP contributions define server: ${name}`, {
|
|
77
|
+
category: 'extension',
|
|
78
|
+
userMessage: `MCP server \`${name}\` is defined more than once. Rename or remove one contribution.`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { SkillManifest } from '../../domain/extensions/skill-manifest.js';
|
|
2
|
+
export interface ActiveSkillScope {
|
|
3
|
+
skillName: string;
|
|
4
|
+
allowedTools: readonly string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Keeps an in-memory, per-agent-run restriction created by a loaded skill.
|
|
8
|
+
* Instances are owned by one CLI turn and must never be persisted or shared.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SkillScopeStore {
|
|
11
|
+
private readonly scopes;
|
|
12
|
+
private initialScope;
|
|
13
|
+
constructor(initialScope?: ActiveSkillScope);
|
|
14
|
+
activate(runId: string, skill: Pick<SkillManifest, 'name' | 'allowedTools'> & {
|
|
15
|
+
skillKey?: string;
|
|
16
|
+
}): ActiveSkillScope;
|
|
17
|
+
get(runId: string): ActiveSkillScope | undefined;
|
|
18
|
+
clear(runId: string): void;
|
|
19
|
+
clearAll(): void;
|
|
20
|
+
}
|
|
21
|
+
export declare function createSkillScope(skill: Pick<SkillManifest, 'name' | 'allowedTools'> & {
|
|
22
|
+
skillKey?: string;
|
|
23
|
+
}): ActiveSkillScope;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeps an in-memory, per-agent-run restriction created by a loaded skill.
|
|
3
|
+
* Instances are owned by one CLI turn and must never be persisted or shared.
|
|
4
|
+
*/
|
|
5
|
+
export class SkillScopeStore {
|
|
6
|
+
scopes = new Map();
|
|
7
|
+
initialScope;
|
|
8
|
+
constructor(initialScope) {
|
|
9
|
+
this.initialScope = initialScope;
|
|
10
|
+
}
|
|
11
|
+
activate(runId, skill) {
|
|
12
|
+
const scope = normalizeScope(skill);
|
|
13
|
+
this.scopes.set(runId, scope);
|
|
14
|
+
return scope;
|
|
15
|
+
}
|
|
16
|
+
get(runId) {
|
|
17
|
+
return this.scopes.get(runId) ?? this.initialScope;
|
|
18
|
+
}
|
|
19
|
+
clear(runId) { this.scopes.delete(runId); }
|
|
20
|
+
clearAll() {
|
|
21
|
+
this.scopes.clear();
|
|
22
|
+
this.initialScope = undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function createSkillScope(skill) {
|
|
26
|
+
return normalizeScope(skill);
|
|
27
|
+
}
|
|
28
|
+
function normalizeScope(skill) {
|
|
29
|
+
return {
|
|
30
|
+
skillName: skill.skillKey ?? skill.name,
|
|
31
|
+
allowedTools: [...new Set(skill.allowedTools)].sort((left, right) => left.localeCompare(right)),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const COMPACT_UNITS = ['K', 'M', 'B', 'T', 'Qa', 'Qi', 'Sx', 'Sp', 'Oc', 'No', 'Dc'];
|
|
2
|
+
/** Formats large counts for compact terminal and command output. */
|
|
3
|
+
export function formatCompactNumber(value) {
|
|
4
|
+
if (!Number.isFinite(value))
|
|
5
|
+
return '0';
|
|
6
|
+
const sign = value < 0 ? '-' : '';
|
|
7
|
+
let magnitude = Math.abs(value);
|
|
8
|
+
if (magnitude < 1000)
|
|
9
|
+
return `${sign}${Math.round(magnitude)}`;
|
|
10
|
+
let unitIndex = -1;
|
|
11
|
+
while (magnitude >= 1000 && unitIndex < COMPACT_UNITS.length - 1) {
|
|
12
|
+
magnitude /= 1000;
|
|
13
|
+
unitIndex += 1;
|
|
14
|
+
}
|
|
15
|
+
const decimals = magnitude >= 100 ? 0 : magnitude >= 10 ? 1 : 2;
|
|
16
|
+
const formatted = magnitude.toFixed(decimals).replace(/\.0+$|(?<=\.\d)0+$/u, '');
|
|
17
|
+
return `${sign}${formatted}${COMPACT_UNITS[unitIndex]}`;
|
|
18
|
+
}
|