@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,22 @@
|
|
|
1
|
+
export interface CompactTableRow {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly status: string;
|
|
4
|
+
readonly detail?: string;
|
|
5
|
+
readonly values?: Readonly<Record<string, string>>;
|
|
6
|
+
}
|
|
7
|
+
export interface CompactTableColumn {
|
|
8
|
+
readonly key: string;
|
|
9
|
+
readonly header: string;
|
|
10
|
+
readonly width?: number;
|
|
11
|
+
readonly minWidth?: number;
|
|
12
|
+
readonly maxWidth?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface CompactTableOptions {
|
|
15
|
+
readonly empty?: string;
|
|
16
|
+
readonly maxWidth?: number;
|
|
17
|
+
readonly nameWidth?: number;
|
|
18
|
+
readonly statusWidth?: number;
|
|
19
|
+
readonly columns?: readonly CompactTableColumn[];
|
|
20
|
+
}
|
|
21
|
+
/** Formats operational command output as a compact, terminal-safe table. */
|
|
22
|
+
export declare function formatCompactTable(rows: readonly CompactTableRow[], options?: CompactTableOptions): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Formats operational command output as a compact, terminal-safe table. */
|
|
2
|
+
export function formatCompactTable(rows, options = {}) {
|
|
3
|
+
if (rows.length === 0)
|
|
4
|
+
return options.empty ?? 'No items.';
|
|
5
|
+
const maxWidth = Math.max(48, options.maxWidth ?? 100);
|
|
6
|
+
const columns = options.columns ?? defaultColumns(options);
|
|
7
|
+
const values = rows.map((row) => columns.map((column) => columnValue(row, column.key)));
|
|
8
|
+
const widths = constrainWidths(columns, values, maxWidth);
|
|
9
|
+
const header = columns.map((column, index) => formatCell(column.header, widths[index], index, columns.length)).join(' ');
|
|
10
|
+
const lines = values.map((row) => row.map((value, index) => formatCell(value, widths[index], index, columns.length)).join(' '));
|
|
11
|
+
return [header, ...lines].join('\n');
|
|
12
|
+
}
|
|
13
|
+
function defaultColumns(options) {
|
|
14
|
+
return [
|
|
15
|
+
{ key: 'name', header: 'Name', minWidth: 4, maxWidth: options.nameWidth ?? 28 },
|
|
16
|
+
{ key: 'status', header: 'Status', minWidth: 6, maxWidth: options.statusWidth ?? 16 },
|
|
17
|
+
{ key: 'detail', header: 'Detail', minWidth: 12 },
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
function columnValue(row, key) {
|
|
21
|
+
if (key === 'name')
|
|
22
|
+
return row.name;
|
|
23
|
+
if (key === 'status')
|
|
24
|
+
return row.status;
|
|
25
|
+
if (key === 'detail')
|
|
26
|
+
return row.detail ?? '';
|
|
27
|
+
return row.values?.[key] ?? '';
|
|
28
|
+
}
|
|
29
|
+
function constrainWidths(columns, values, maxWidth) {
|
|
30
|
+
const widths = columns.map((column, index) => {
|
|
31
|
+
const contentWidth = Math.max(column.header.length, ...values.map((row) => row[index]?.length ?? 0));
|
|
32
|
+
const preferred = column.width ?? contentWidth;
|
|
33
|
+
return Math.max(column.minWidth ?? 4, Math.min(preferred, column.maxWidth ?? Number.POSITIVE_INFINITY));
|
|
34
|
+
});
|
|
35
|
+
let overflow = widths.reduce((total, width) => total + width, 0) + (columns.length - 1) * 2 - maxWidth;
|
|
36
|
+
for (let index = widths.length - 1; index >= 0 && overflow > 0; index -= 1) {
|
|
37
|
+
const minimum = columns[index]?.minWidth ?? 4;
|
|
38
|
+
const reduction = Math.min(overflow, widths[index] - minimum);
|
|
39
|
+
widths[index] = widths[index] - reduction;
|
|
40
|
+
overflow -= reduction;
|
|
41
|
+
}
|
|
42
|
+
return widths;
|
|
43
|
+
}
|
|
44
|
+
function formatCell(value, width, index, columnCount) {
|
|
45
|
+
const truncated = truncate(value, width);
|
|
46
|
+
return index === columnCount - 1 ? truncated : pad(truncated, width);
|
|
47
|
+
}
|
|
48
|
+
function pad(value, width) { return value.padEnd(width, ' '); }
|
|
49
|
+
function truncate(value, width) { return value.length <= width ? value : `${value.slice(0, Math.max(0, width - 3))}...`; }
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { MediaExecutionPolicy } from '../../domain/media/media-execution-policy.js';
|
|
2
|
+
import type { VideoOperation } from '../../domain/media/media-contract.js';
|
|
3
|
+
import type { MediaGatewayClient } from '../../ports/media-gateway-client.js';
|
|
4
|
+
/** Foreground gateway polling. The gateway owns provider polling. */
|
|
5
|
+
export declare function waitForVideoOperation(client: MediaGatewayClient, id: string, policy: Pick<MediaExecutionPolicy, 'videoPollIntervalMs' | 'videoWaitTimeoutMs'>, signal: AbortSignal): Promise<VideoOperation>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CliError } from '../../domain/errors/cli-error.js';
|
|
2
|
+
import { CLI_ERROR_CODES } from '../../domain/errors/error-codes.js';
|
|
3
|
+
/** Foreground gateway polling. The gateway owns provider polling. */
|
|
4
|
+
export async function waitForVideoOperation(client, id, policy, signal) {
|
|
5
|
+
const deadline = Date.now() + policy.videoWaitTimeoutMs;
|
|
6
|
+
while (Date.now() < deadline) {
|
|
7
|
+
await abortableSleep(policy.videoPollIntervalMs, signal);
|
|
8
|
+
const operation = await client.getVideoOperation(id, { signal });
|
|
9
|
+
if (operation.done || operation.errorMessage !== undefined)
|
|
10
|
+
return operation;
|
|
11
|
+
}
|
|
12
|
+
throw new CliError('MEDIA_VIDEO_WAIT_TIMEOUT', `Timed out waiting for video operation: ${id}`, {
|
|
13
|
+
category: 'media',
|
|
14
|
+
retryable: true,
|
|
15
|
+
userMessage: `Video is still processing. Use \`video status ${id}\` or \`video download ${id}\` later.`,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function abortableSleep(milliseconds, signal) {
|
|
19
|
+
if (signal.aborted)
|
|
20
|
+
return Promise.reject(interrupted(signal.reason));
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const timer = setTimeout(onComplete, milliseconds);
|
|
23
|
+
const onAbort = () => {
|
|
24
|
+
clearTimeout(timer);
|
|
25
|
+
signal.removeEventListener('abort', onAbort);
|
|
26
|
+
reject(interrupted(signal.reason));
|
|
27
|
+
};
|
|
28
|
+
function onComplete() {
|
|
29
|
+
signal.removeEventListener('abort', onAbort);
|
|
30
|
+
resolve();
|
|
31
|
+
}
|
|
32
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function interrupted(cause) {
|
|
36
|
+
return new CliError(CLI_ERROR_CODES.INTERRUPTED, 'Media command interrupted.', {
|
|
37
|
+
category: 'media',
|
|
38
|
+
userMessage: 'Media command interrupted.',
|
|
39
|
+
retryable: true,
|
|
40
|
+
cause,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CacheStore } from '../../ports/cache-store.js';
|
|
2
|
+
import type { ModelCatalogAdapter } from '../../infrastructure/sdk/model-catalog-adapter.js';
|
|
3
|
+
type ModelCatalog = Awaited<ReturnType<ModelCatalogAdapter['listModels']>>;
|
|
4
|
+
export declare class CachedModelCatalog {
|
|
5
|
+
private readonly source;
|
|
6
|
+
private readonly cache;
|
|
7
|
+
private readonly cacheKey;
|
|
8
|
+
private readonly ttlMs;
|
|
9
|
+
constructor(source: ModelCatalogAdapter, cache: CacheStore, cacheKey: string, ttlMs: number);
|
|
10
|
+
listModels(forceRefresh?: boolean): Promise<ModelCatalog>;
|
|
11
|
+
}
|
|
12
|
+
export declare function modelCatalogCacheKey(profileName: string, baseUrl: string): string;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class CachedModelCatalog {
|
|
2
|
+
source;
|
|
3
|
+
cache;
|
|
4
|
+
cacheKey;
|
|
5
|
+
ttlMs;
|
|
6
|
+
constructor(source, cache, cacheKey, ttlMs) {
|
|
7
|
+
this.source = source;
|
|
8
|
+
this.cache = cache;
|
|
9
|
+
this.cacheKey = cacheKey;
|
|
10
|
+
this.ttlMs = ttlMs;
|
|
11
|
+
}
|
|
12
|
+
async listModels(forceRefresh = false) {
|
|
13
|
+
if (!forceRefresh) {
|
|
14
|
+
const cached = await this.cache.get('model-catalog', this.cacheKey);
|
|
15
|
+
if (cached !== undefined && isModelCatalog(cached))
|
|
16
|
+
return cached;
|
|
17
|
+
}
|
|
18
|
+
const fresh = await this.source.listModels();
|
|
19
|
+
await this.cache.set('model-catalog', this.cacheKey, fresh, { ttlMs: this.ttlMs }).catch(() => undefined);
|
|
20
|
+
return fresh;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function modelCatalogCacheKey(profileName, baseUrl) {
|
|
24
|
+
return `${profileName}\0${baseUrl}`;
|
|
25
|
+
}
|
|
26
|
+
function isModelCatalog(value) {
|
|
27
|
+
if (typeof value !== 'object' || value === null)
|
|
28
|
+
return false;
|
|
29
|
+
const data = value.data;
|
|
30
|
+
return Array.isArray(data) && data.every((item) => typeof item === 'object' && item !== null && typeof item.id === 'string');
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ModelCandidate {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
}
|
|
4
|
+
export interface ModelCatalogSource {
|
|
5
|
+
list(): Promise<{
|
|
6
|
+
readonly data: readonly ModelCandidate[];
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
/** Selects the server-provided first catalog entry without embedding model ids in the CLI. */
|
|
10
|
+
export declare function selectInitialModel(currentModel: string | null, catalog: ModelCatalogSource, persist: (model: string) => Promise<void>): Promise<string | null>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Selects the server-provided first catalog entry without embedding model ids in the CLI. */
|
|
2
|
+
export async function selectInitialModel(currentModel, catalog, persist) {
|
|
3
|
+
if (currentModel !== null && currentModel.trim().length > 0)
|
|
4
|
+
return currentModel;
|
|
5
|
+
const response = await catalog.list();
|
|
6
|
+
const first = response.data[0]?.id.trim();
|
|
7
|
+
if (first === undefined || first.length === 0)
|
|
8
|
+
return null;
|
|
9
|
+
await persist(first);
|
|
10
|
+
return first;
|
|
11
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
|
|
2
|
+
/** Loads the cached selectable model catalogue for all CLI capabilities. */
|
|
3
|
+
export declare function loadModelCatalog(runtime: CliRuntime, cwd: string, forceRefresh?: boolean): Promise<{
|
|
4
|
+
data: import("@lotagate/sdk").ModelSummary[];
|
|
5
|
+
object: "list" | string;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AuthenticationService } from '../auth/authentication-service.js';
|
|
2
|
+
import { createLotaGateClient } from '../../infrastructure/sdk/lotagate-client-factory.js';
|
|
3
|
+
import { ModelCatalogAdapter } from '../../infrastructure/sdk/model-catalog-adapter.js';
|
|
4
|
+
import { loadExecutionConfig } from '../config/execution-config.js';
|
|
5
|
+
import { CachedModelCatalog, modelCatalogCacheKey } from './cached-model-catalog.js';
|
|
6
|
+
/** Loads the cached selectable model catalogue for all CLI capabilities. */
|
|
7
|
+
export async function loadModelCatalog(runtime, cwd, forceRefresh = false) {
|
|
8
|
+
const loaded = await loadExecutionConfig(runtime, cwd);
|
|
9
|
+
const profileName = loaded.config.profile ?? AuthenticationService.defaultProfileName();
|
|
10
|
+
const credential = await runtime.auth.requireCredential(profileName);
|
|
11
|
+
const catalog = new CachedModelCatalog(new ModelCatalogAdapter(createLotaGateClient(credential.profile, credential.apiKey)), runtime.cache, modelCatalogCacheKey(credential.profile.name, credential.profile.baseUrl), runtime.cachePolicy.modelCatalogTtlMs);
|
|
12
|
+
return catalog.listModels(forceRefresh);
|
|
13
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
|
|
2
|
+
/** Resolves the catalog-provided context window without coupling callers to SDK details. */
|
|
3
|
+
export declare function resolveModelContextWindow(runtime: CliRuntime, model: string | null, profileName?: string | null): Promise<number | undefined>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AuthenticationService } from '../auth/authentication-service.js';
|
|
2
|
+
import { CachedModelCatalog, modelCatalogCacheKey } from './cached-model-catalog.js';
|
|
3
|
+
import { createLotaGateClient } from '../../infrastructure/sdk/lotagate-client-factory.js';
|
|
4
|
+
import { getModelContextWindow, ModelCatalogAdapter } from '../../infrastructure/sdk/model-catalog-adapter.js';
|
|
5
|
+
/** Resolves the catalog-provided context window without coupling callers to SDK details. */
|
|
6
|
+
export async function resolveModelContextWindow(runtime, model, profileName) {
|
|
7
|
+
if (model === null || model.trim().length === 0)
|
|
8
|
+
return undefined;
|
|
9
|
+
const profile = profileName ?? AuthenticationService.defaultProfileName();
|
|
10
|
+
const credential = await runtime.credentialStore.get(profile);
|
|
11
|
+
if (credential === undefined)
|
|
12
|
+
return undefined;
|
|
13
|
+
try {
|
|
14
|
+
const catalog = new CachedModelCatalog(new ModelCatalogAdapter(createLotaGateClient(credential.profile, credential.apiKey)), runtime.cache, modelCatalogCacheKey(credential.profile.name, credential.profile.baseUrl), runtime.cachePolicy.modelCatalogTtlMs);
|
|
15
|
+
const response = await catalog.listModels();
|
|
16
|
+
const selected = response.data.find((candidate) => candidate.id === model);
|
|
17
|
+
return selected === undefined ? undefined : getModelContextWindow(selected);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
runtime.logger.debug('Unable to load model context window.', { model, reason: error instanceof Error ? error.message : String(error) });
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type AgentEvent, type AgentRunRequest, type ToolExecutionContext } from '@lotagate/agent-sdk';
|
|
2
|
+
import type { CliRuntime } from '../../bootstrap/runtime-factory.js';
|
|
3
|
+
import type { SubagentMode, SubagentRequest, SubagentResult } from '../../domain/orchestration/subagent.js';
|
|
4
|
+
import type { AgentTask } from '../../domain/orchestration/task.js';
|
|
5
|
+
import type { SubagentLastAction, SubagentLifecycleObserver } from '../../ports/subagent-lifecycle.js';
|
|
6
|
+
import type { ModelCallSummary } from '../../ports/model-diagnostics.js';
|
|
7
|
+
export interface PreparedSubagent {
|
|
8
|
+
readonly initialize: () => Promise<unknown>;
|
|
9
|
+
readonly run: (request: AgentRunRequest) => AsyncIterable<AgentEvent>;
|
|
10
|
+
readonly close: () => Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export interface CliSubagentServiceOptions {
|
|
13
|
+
readonly runtime: CliRuntime;
|
|
14
|
+
readonly cwd: string;
|
|
15
|
+
readonly model: string;
|
|
16
|
+
readonly allowedModels?: readonly string[];
|
|
17
|
+
readonly createAgent: (input: {
|
|
18
|
+
task: AgentTask;
|
|
19
|
+
displayName: string;
|
|
20
|
+
model: string;
|
|
21
|
+
mode: SubagentMode;
|
|
22
|
+
writeScope?: readonly string[];
|
|
23
|
+
onAction?: (action: SubagentLastAction) => void;
|
|
24
|
+
onUsage?: (summary: ModelCallSummary) => void;
|
|
25
|
+
}) => Promise<PreparedSubagent>;
|
|
26
|
+
readonly jobs?: SubagentJobRegistry;
|
|
27
|
+
readonly lifecycle?: SubagentLifecycleObserver;
|
|
28
|
+
}
|
|
29
|
+
export interface CliSubagentService {
|
|
30
|
+
spawn(request: SubagentRequest, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
31
|
+
wait(id: string, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
32
|
+
cancel(id: string, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
33
|
+
}
|
|
34
|
+
interface SubagentJob {
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly displayName: string;
|
|
37
|
+
readonly parentSessionId: string;
|
|
38
|
+
readonly controller: AbortController;
|
|
39
|
+
promise: Promise<SubagentResult>;
|
|
40
|
+
result?: SubagentResult;
|
|
41
|
+
}
|
|
42
|
+
/** Owns background-job lifetime for one interactive session across agent turns. */
|
|
43
|
+
export declare class SubagentJobRegistry {
|
|
44
|
+
readonly jobs: Map<string, SubagentJob>;
|
|
45
|
+
activeJobs: number;
|
|
46
|
+
private nextDisplayName;
|
|
47
|
+
private closed;
|
|
48
|
+
allocateDisplayName(): string;
|
|
49
|
+
ensureCapacity(): void;
|
|
50
|
+
/** Cancels and observes session-owned background work before the TUI exits. */
|
|
51
|
+
close(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/** Executes least-privileged, bounded child agents and supports resumable background jobs. */
|
|
54
|
+
export declare class DefaultCliSubagentService implements CliSubagentService {
|
|
55
|
+
private readonly options;
|
|
56
|
+
private readonly coordinator;
|
|
57
|
+
private readonly journal;
|
|
58
|
+
private readonly jobs;
|
|
59
|
+
constructor(options: CliSubagentServiceOptions);
|
|
60
|
+
spawn(request: SubagentRequest, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
61
|
+
wait(id: string, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
62
|
+
cancel(id: string, context: ToolExecutionContext): Promise<SubagentResult>;
|
|
63
|
+
private execute;
|
|
64
|
+
private createInstance;
|
|
65
|
+
private resolveModel;
|
|
66
|
+
private ownedJob;
|
|
67
|
+
private writeJournal;
|
|
68
|
+
private notifyLifecycle;
|
|
69
|
+
}
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import { AgentSdkError, AgentSdkErrorCode } from '@lotagate/agent-sdk';
|
|
3
|
+
import { SubagentCoordinator } from './subagent-coordinator.js';
|
|
4
|
+
import { SubagentJournalStore } from '../../infrastructure/sessions/subagent-journal-store.js';
|
|
5
|
+
import { RESOURCE_LIMITS } from '../../domain/runtime/resource-limits.js';
|
|
6
|
+
import { parseSubagentHandoff } from './subagent-handoff.js';
|
|
7
|
+
import { subagentDisplayName } from '../../domain/orchestration/subagent-identity.js';
|
|
8
|
+
import { CliError } from '../../domain/errors/cli-error.js';
|
|
9
|
+
import { formatMcpActivityName } from '../agent/tool-display.js';
|
|
10
|
+
/** Owns background-job lifetime for one interactive session across agent turns. */
|
|
11
|
+
export class SubagentJobRegistry {
|
|
12
|
+
jobs = new Map();
|
|
13
|
+
activeJobs = 0;
|
|
14
|
+
nextDisplayName = 0;
|
|
15
|
+
closed = false;
|
|
16
|
+
allocateDisplayName() {
|
|
17
|
+
return subagentDisplayName(this.nextDisplayName++);
|
|
18
|
+
}
|
|
19
|
+
ensureCapacity() {
|
|
20
|
+
if (this.closed)
|
|
21
|
+
throw new Error('The subagent job registry is closed.');
|
|
22
|
+
while (this.jobs.size >= RESOURCE_LIMITS.subagentMaxRetainedJobs) {
|
|
23
|
+
const removable = [...this.jobs.entries()].find(([, job]) => job.result !== undefined);
|
|
24
|
+
if (removable === undefined)
|
|
25
|
+
throw new Error('The subagent job registry is full; wait for an existing job before starting another.');
|
|
26
|
+
this.jobs.delete(removable[0]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Cancels and observes session-owned background work before the TUI exits. */
|
|
30
|
+
async close() {
|
|
31
|
+
if (this.closed)
|
|
32
|
+
return;
|
|
33
|
+
this.closed = true;
|
|
34
|
+
const pending = [...this.jobs.values()].filter((job) => job.result === undefined);
|
|
35
|
+
for (const job of pending)
|
|
36
|
+
job.controller.abort(new Error('Interactive session is closing.'));
|
|
37
|
+
await Promise.allSettled(pending.map((job) => job.promise));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Executes least-privileged, bounded child agents and supports resumable background jobs. */
|
|
41
|
+
export class DefaultCliSubagentService {
|
|
42
|
+
options;
|
|
43
|
+
coordinator = new SubagentCoordinator();
|
|
44
|
+
journal;
|
|
45
|
+
jobs;
|
|
46
|
+
constructor(options) {
|
|
47
|
+
this.options = options;
|
|
48
|
+
this.journal = new SubagentJournalStore(options.runtime.paths);
|
|
49
|
+
this.jobs = options.jobs ?? new SubagentJobRegistry();
|
|
50
|
+
}
|
|
51
|
+
async spawn(request, context) {
|
|
52
|
+
const normalized = normalizeRequest(request);
|
|
53
|
+
const model = this.resolveModel(normalized.model);
|
|
54
|
+
const id = crypto.randomUUID();
|
|
55
|
+
this.jobs.ensureCapacity();
|
|
56
|
+
const displayName = this.jobs.allocateDisplayName();
|
|
57
|
+
if (this.jobs.activeJobs >= RESOURCE_LIMITS.subagentMaxConcurrent)
|
|
58
|
+
throw new Error('The maximum number of concurrent subagents is already running.');
|
|
59
|
+
this.jobs.activeJobs += 1;
|
|
60
|
+
const controller = linkedAbortController(context.signal);
|
|
61
|
+
const job = { id, displayName, parentSessionId: context.sessionId, controller, promise: Promise.resolve(createRunningResult(id, displayName, normalized, model)) };
|
|
62
|
+
this.jobs.jobs.set(id, job);
|
|
63
|
+
this.notifyLifecycle({ type: 'created', sessionId: context.sessionId, id, displayName: job.displayName, task: normalized.task, mode: normalized.mode, model, status: 'queued', background: normalized.background, timestamp: Date.now() });
|
|
64
|
+
this.options.runtime.logger.info?.('Subagent created.', { subagentId: id, displayName, mode: normalized.mode, model, background: normalized.background });
|
|
65
|
+
const promise = this.execute(id, displayName, normalized, model, context, controller.signal)
|
|
66
|
+
.then((result) => {
|
|
67
|
+
job.result = result;
|
|
68
|
+
this.notifyLifecycle({ type: terminalLifecycleType(result.status), sessionId: context.sessionId, id, displayName: job.displayName, task: normalized.task, mode: normalized.mode, model, status: result.status, background: normalized.background, timestamp: Date.now(), durationMs: result.durationMs, summary: result.summary, handoff: result.handoff });
|
|
69
|
+
this.options.runtime.logger.info?.('Subagent finished.', { subagentId: id, displayName, status: result.status, durationMs: result.durationMs, toolCount: result.toolsUsed.length, ...(result.limitReason === undefined ? {} : { limitReason: result.limitReason }) });
|
|
70
|
+
return result;
|
|
71
|
+
})
|
|
72
|
+
.finally(() => { this.jobs.activeJobs -= 1; controller.dispose(); });
|
|
73
|
+
job.promise = promise;
|
|
74
|
+
if (normalized.background)
|
|
75
|
+
return createRunningResult(id, displayName, normalized, model);
|
|
76
|
+
return promise;
|
|
77
|
+
}
|
|
78
|
+
async wait(id, context) {
|
|
79
|
+
return (await this.ownedJob(id, context)).promise;
|
|
80
|
+
}
|
|
81
|
+
async cancel(id, context) {
|
|
82
|
+
const job = await this.ownedJob(id, context);
|
|
83
|
+
job.controller.abort();
|
|
84
|
+
return job.promise;
|
|
85
|
+
}
|
|
86
|
+
async execute(id, displayName, request, model, context, signal) {
|
|
87
|
+
const startedAt = Date.now();
|
|
88
|
+
const mode = request.mode ?? 'research';
|
|
89
|
+
await this.writeJournal(context.sessionId, { recordType: 'created', id, displayName, task: request.task, mode, model, timestamp: new Date().toISOString() });
|
|
90
|
+
await this.writeJournal(context.sessionId, { recordType: 'started', id, displayName, mode, model, timestamp: new Date().toISOString() });
|
|
91
|
+
this.notifyLifecycle({ type: 'started', sessionId: context.sessionId, id, displayName, task: request.task, mode, model, status: 'running', background: request.background ?? false, timestamp: Date.now() });
|
|
92
|
+
try {
|
|
93
|
+
const planTask = { id, title: mode === 'research' ? 'Research task' : 'Worker task', description: buildChildInput(request), dependencies: [], status: 'queued' };
|
|
94
|
+
const results = await this.coordinator.run({ id: `subagent-plan-${id}`, goal: request.task, tasks: [planTask], requiresApproval: false, maxConcurrency: 1 }, { create: async (childTask) => this.createInstance(childTask, displayName, model, mode, request, context) }, schedulerLimits(), signal);
|
|
95
|
+
const output = results[0]?.output;
|
|
96
|
+
if (output === undefined)
|
|
97
|
+
throw new Error('The subagent completed without a result.');
|
|
98
|
+
const limitReason = output.limitReason;
|
|
99
|
+
const handoff = addLimitWarning(parseSubagentHandoff(output.content), limitReason);
|
|
100
|
+
const status = limitReason === undefined ? 'completed' : 'completed_with_warning';
|
|
101
|
+
const result = {
|
|
102
|
+
id,
|
|
103
|
+
displayName,
|
|
104
|
+
task: request.task,
|
|
105
|
+
status,
|
|
106
|
+
mode,
|
|
107
|
+
model,
|
|
108
|
+
summary: handoff.summary,
|
|
109
|
+
handoff,
|
|
110
|
+
toolsUsed: output.toolsUsed ?? [],
|
|
111
|
+
...(output.tokensEstimated === true && output.tokens !== undefined ? { estimatedTokens: output.tokens } : {}),
|
|
112
|
+
...(limitReason === undefined ? {} : { limitReason }),
|
|
113
|
+
durationMs: Date.now() - startedAt,
|
|
114
|
+
};
|
|
115
|
+
await this.writeJournal(context.sessionId, { recordType: status, result, timestamp: new Date().toISOString() });
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
const cancelled = signal.aborted;
|
|
120
|
+
const limitReason = cancelled ? undefined : classifyLimit(error);
|
|
121
|
+
const handoff = {
|
|
122
|
+
summary: cancelled ? 'Subagent cancelled.' : limitReason === undefined ? error instanceof Error ? error.message : String(error) : `Subagent stopped after reaching its ${limitLabel(limitReason)} limit.`,
|
|
123
|
+
filesInspected: [], filesChanged: [], commandsRun: [], verification: [],
|
|
124
|
+
warnings: [cancelled ? 'The child was cancelled before completing.' : limitReason === undefined ? 'The child failed before producing a verified handoff.' : `The child reached its ${limitLabel(limitReason)} limit before producing a verified handoff.`],
|
|
125
|
+
};
|
|
126
|
+
const terminalStatus = cancelled ? 'cancelled' : limitReason === undefined ? 'failed' : 'completed_with_warning';
|
|
127
|
+
const result = { id, displayName, task: request.task, status: terminalStatus, mode, model, summary: handoff.summary, handoff, toolsUsed: [], ...(limitReason === undefined ? {} : { limitReason }), durationMs: Date.now() - startedAt };
|
|
128
|
+
await this.writeJournal(context.sessionId, { recordType: terminalStatus, result, timestamp: new Date().toISOString() });
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async createInstance(task, displayName, model, mode, request, context) {
|
|
133
|
+
const reportAction = (lastAction) => {
|
|
134
|
+
this.notifyLifecycle({ type: 'activity', sessionId: context.sessionId, id: task.id, displayName, task: request.task, mode, model, status: 'running', background: request.background ?? false, timestamp: Date.now(), lastAction });
|
|
135
|
+
};
|
|
136
|
+
let modelTokens = 0;
|
|
137
|
+
let modelUsageObserved = false;
|
|
138
|
+
const child = await this.options.createAgent({ task, displayName, model, mode, ...(request.writeScope === undefined ? {} : { writeScope: request.writeScope }), onAction: reportAction, onUsage: (summary) => {
|
|
139
|
+
const usage = summary.usage;
|
|
140
|
+
if (usage === undefined)
|
|
141
|
+
return;
|
|
142
|
+
modelUsageObserved = true;
|
|
143
|
+
modelTokens += Math.max(usage.totalTokens ?? 0, (usage.promptTokens ?? 0) + (usage.completionTokens ?? 0));
|
|
144
|
+
} });
|
|
145
|
+
let closed = false;
|
|
146
|
+
return {
|
|
147
|
+
run: async (_task, taskSignal) => {
|
|
148
|
+
await child.initialize();
|
|
149
|
+
const content = [];
|
|
150
|
+
const toolsUsed = new Set();
|
|
151
|
+
const runRequest = {
|
|
152
|
+
input: task.description,
|
|
153
|
+
model,
|
|
154
|
+
sessionId: task.id,
|
|
155
|
+
cwd: context.cwd ?? this.options.cwd,
|
|
156
|
+
workspaceRoot: context.workspaceRoot ?? this.options.cwd,
|
|
157
|
+
stream: true,
|
|
158
|
+
signal: taskSignal,
|
|
159
|
+
limits: { maxIterations: RESOURCE_LIMITS.subagentMaxIterations, maxToolCallsPerTurn: RESOURCE_LIMITS.subagentMaxToolCallsPerTurn, maxToolArgumentBytes: RESOURCE_LIMITS.subagentToolArgumentBytes, maxToolResultBytes: RESOURCE_LIMITS.subagentToolResultBytes },
|
|
160
|
+
metadata: { parentSessionId: context.sessionId, parentRunId: context.runId, subagentMode: mode },
|
|
161
|
+
};
|
|
162
|
+
let limitReason;
|
|
163
|
+
try {
|
|
164
|
+
for await (const event of child.run(runRequest)) {
|
|
165
|
+
if (event.type === 'model.delta')
|
|
166
|
+
content.push(event.content);
|
|
167
|
+
if (event.type === 'session.completed' && content.length === 0)
|
|
168
|
+
content.push(event.content);
|
|
169
|
+
if (event.type === 'tool.called') {
|
|
170
|
+
toolsUsed.add(event.toolName);
|
|
171
|
+
const action = mcpAction(event.toolName);
|
|
172
|
+
if (action !== undefined)
|
|
173
|
+
reportAction(action);
|
|
174
|
+
}
|
|
175
|
+
if (event.type === 'session.failed')
|
|
176
|
+
throw event.error;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (context.signal?.aborted)
|
|
181
|
+
throw error;
|
|
182
|
+
limitReason = taskSignal.aborted ? 'timeout' : classifyLimit(error);
|
|
183
|
+
if (limitReason === undefined)
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
const summary = boundSummary(content.join(''));
|
|
187
|
+
const tokens = modelUsageObserved ? modelTokens : Math.ceil(Buffer.byteLength(summary, 'utf8') / 4);
|
|
188
|
+
return { content: summary, tokens, ...(modelUsageObserved ? {} : { tokensEstimated: true }), toolsUsed: [...toolsUsed].sort(), ...(limitReason === undefined ? {} : { limitReason }) };
|
|
189
|
+
},
|
|
190
|
+
close: async () => {
|
|
191
|
+
if (closed)
|
|
192
|
+
return;
|
|
193
|
+
closed = true;
|
|
194
|
+
await child.close();
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
resolveModel(requested) {
|
|
199
|
+
const model = requested ?? this.options.model;
|
|
200
|
+
const allowed = new Set(this.options.allowedModels ?? [this.options.model]);
|
|
201
|
+
if (!allowed.has(model))
|
|
202
|
+
throw new Error(`Subagent model is not allowed: ${model}`);
|
|
203
|
+
return model;
|
|
204
|
+
}
|
|
205
|
+
async ownedJob(id, context) {
|
|
206
|
+
const normalized = id.trim();
|
|
207
|
+
const job = this.jobs.jobs.get(normalized);
|
|
208
|
+
if (job === undefined || job.parentSessionId !== context.sessionId)
|
|
209
|
+
throw new Error(`Subagent job not found: ${normalized}`);
|
|
210
|
+
return job;
|
|
211
|
+
}
|
|
212
|
+
async writeJournal(parentSessionId, record) {
|
|
213
|
+
try {
|
|
214
|
+
await this.journal.append(parentSessionId, this.options.cwd, record);
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
this.options.runtime.logger.warn('Unable to persist subagent lifecycle record.', { reason: error instanceof Error ? error.message : String(error) });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
notifyLifecycle(event) {
|
|
221
|
+
const observer = this.options.lifecycle;
|
|
222
|
+
if (observer === undefined)
|
|
223
|
+
return;
|
|
224
|
+
void Promise.resolve(observer.onSubagentLifecycle(event)).catch((error) => {
|
|
225
|
+
this.options.runtime.logger.warn('Subagent lifecycle observer failed.', { reason: error instanceof Error ? error.message : String(error) });
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function normalizeRequest(request) {
|
|
230
|
+
const task = request.task.trim();
|
|
231
|
+
if (task.length === 0)
|
|
232
|
+
throw new Error('agent.spawn requires a non-empty task.');
|
|
233
|
+
if (Buffer.byteLength(task, 'utf8') > RESOURCE_LIMITS.subagentTaskBytes)
|
|
234
|
+
throw new Error('agent.spawn task is too large.');
|
|
235
|
+
const context = request.context?.trim();
|
|
236
|
+
if (context !== undefined && Buffer.byteLength(context, 'utf8') > RESOURCE_LIMITS.subagentContextBytes)
|
|
237
|
+
throw new Error('agent.spawn context is too large.');
|
|
238
|
+
const mode = request.mode ?? 'research';
|
|
239
|
+
const writeScope = normalizeWriteScope(request.writeScope);
|
|
240
|
+
if (mode === 'worker' && writeScope.length === 0)
|
|
241
|
+
throw new Error('Worker subagents require a non-empty writeScope.');
|
|
242
|
+
if (mode === 'research' && writeScope.length > 0)
|
|
243
|
+
throw new Error('Research subagents cannot receive a writeScope.');
|
|
244
|
+
return { ...request, task, mode, background: request.background ?? false, ...(context === undefined ? {} : { context }), ...(writeScope.length === 0 ? {} : { writeScope }) };
|
|
245
|
+
}
|
|
246
|
+
function buildChildInput(request) {
|
|
247
|
+
const scope = request.writeScope === undefined ? '' : `\n<write_scope>\n${request.writeScope.join('\n')}\n</write_scope>`;
|
|
248
|
+
if (request.context === undefined)
|
|
249
|
+
return `<delegated_task>\n${request.task}\n</delegated_task>${scope}`;
|
|
250
|
+
return `<parent_context>\n${request.context}\n</parent_context>\n<delegated_task>\n${request.task}\n</delegated_task>${scope}`;
|
|
251
|
+
}
|
|
252
|
+
function normalizeWriteScope(value) {
|
|
253
|
+
if (value === undefined)
|
|
254
|
+
return [];
|
|
255
|
+
if (value.length > RESOURCE_LIMITS.subagentMaxWriteScopeItems)
|
|
256
|
+
throw new Error('agent.spawn writeScope has too many entries.');
|
|
257
|
+
const normalized = value.map((item) => item.trim()).filter(Boolean);
|
|
258
|
+
if (normalized.some((item) => Buffer.byteLength(item, 'utf8') > RESOURCE_LIMITS.subagentWriteScopeItemBytes))
|
|
259
|
+
throw new Error('agent.spawn writeScope entry is too large.');
|
|
260
|
+
if (normalized.some((item) => pathIsAbsolute(item) || item.split(/[\\/]/u).includes('..')))
|
|
261
|
+
throw new Error('agent.spawn writeScope must contain workspace-relative paths without traversal.');
|
|
262
|
+
return [...new Set(normalized)].sort();
|
|
263
|
+
}
|
|
264
|
+
function pathIsAbsolute(value) {
|
|
265
|
+
return value.startsWith('/') || /^[A-Za-z]:[\\/]/u.test(value) || value.startsWith('\\\\');
|
|
266
|
+
}
|
|
267
|
+
function createRunningResult(id, displayName, request, model) {
|
|
268
|
+
const mode = request.mode ?? 'research';
|
|
269
|
+
const handoff = { summary: 'Subagent is running in the background. Call agent.wait with this id when its result is needed.', filesInspected: [], filesChanged: [], commandsRun: [], verification: [], warnings: [] };
|
|
270
|
+
return { id, displayName, task: request.task, status: 'running', mode, model, summary: handoff.summary, handoff, toolsUsed: [], durationMs: 0 };
|
|
271
|
+
}
|
|
272
|
+
function linkedAbortController(parent) {
|
|
273
|
+
const controller = new AbortController();
|
|
274
|
+
const abort = () => controller.abort(parent?.reason);
|
|
275
|
+
if (parent?.aborted)
|
|
276
|
+
abort();
|
|
277
|
+
else
|
|
278
|
+
parent?.addEventListener('abort', abort, { once: true });
|
|
279
|
+
return Object.assign(controller, { dispose: () => parent?.removeEventListener('abort', abort) });
|
|
280
|
+
}
|
|
281
|
+
function boundSummary(value) {
|
|
282
|
+
const text = value.trim() || 'The subagent completed without a text summary.';
|
|
283
|
+
const bytes = Buffer.from(text, 'utf8');
|
|
284
|
+
return bytes.byteLength <= RESOURCE_LIMITS.subagentSummaryBytes ? text : `${bytes.subarray(0, RESOURCE_LIMITS.subagentSummaryBytes).toString('utf8')}\n[truncated]`;
|
|
285
|
+
}
|
|
286
|
+
function schedulerLimits() {
|
|
287
|
+
return { maxConcurrency: 1, maxTasks: 1, maxDurationMs: RESOURCE_LIMITS.subagentMaxDurationMs, maxTokens: RESOURCE_LIMITS.subagentMaxTokens };
|
|
288
|
+
}
|
|
289
|
+
function mcpAction(toolName) {
|
|
290
|
+
if (toolName.startsWith('filesystem.') || toolName === 'shell.exec' || toolName.startsWith('skill.'))
|
|
291
|
+
return undefined;
|
|
292
|
+
return { kind: 'mcp', label: `Using ${redactToolName(formatMcpActivityName(toolName))}` };
|
|
293
|
+
}
|
|
294
|
+
function redactToolName(value) {
|
|
295
|
+
const redacted = value.replace(/Bearer\s+[^\s]+/giu, 'Bearer [REDACTED]').replace(/sk-[A-Za-z0-9_-]{8,}/gu, '[REDACTED]');
|
|
296
|
+
return redacted.length <= 180 ? redacted : `${redacted.slice(0, 177)}...`;
|
|
297
|
+
}
|
|
298
|
+
function terminalLifecycleType(status) {
|
|
299
|
+
if (status === 'completed' || status === 'completed_with_warning' || status === 'failed' || status === 'cancelled')
|
|
300
|
+
return status;
|
|
301
|
+
throw new Error(`Subagent execution returned a non-terminal status: ${status}`);
|
|
302
|
+
}
|
|
303
|
+
function addLimitWarning(handoff, reason) {
|
|
304
|
+
if (reason === undefined)
|
|
305
|
+
return handoff;
|
|
306
|
+
return { ...handoff, warnings: [...handoff.warnings, `The child reached its ${limitLabel(reason)} limit before full completion.`] };
|
|
307
|
+
}
|
|
308
|
+
function classifyLimit(error) {
|
|
309
|
+
if (error instanceof AgentSdkError && error.code === AgentSdkErrorCode.AgentLimitExceeded) {
|
|
310
|
+
if (error.details?.['maxToolCallsPerTurn'] !== undefined || /tool calls/iu.test(error.message))
|
|
311
|
+
return 'tool_calls';
|
|
312
|
+
return 'iteration';
|
|
313
|
+
}
|
|
314
|
+
if (error instanceof CliError && /duration/iu.test(error.message))
|
|
315
|
+
return 'timeout';
|
|
316
|
+
if (error instanceof CliError && /token budget/iu.test(error.message))
|
|
317
|
+
return 'tokens';
|
|
318
|
+
return undefined;
|
|
319
|
+
}
|
|
320
|
+
function limitLabel(reason) {
|
|
321
|
+
if (reason === 'tool_calls')
|
|
322
|
+
return 'tool-call';
|
|
323
|
+
if (reason === 'iteration')
|
|
324
|
+
return 'iteration';
|
|
325
|
+
if (reason === 'tokens')
|
|
326
|
+
return 'token';
|
|
327
|
+
return 'time';
|
|
328
|
+
}
|