@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,39 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
import type { Attachment } from '../../../../domain/session/attachment.js';
|
|
3
|
+
import type { TuiMessage } from '../tui-bridge.js';
|
|
4
|
+
import type { TuiWelcome } from '../tui-bridge.js';
|
|
5
|
+
import { type ActivityStatusProps } from './activity-status.js';
|
|
6
|
+
export interface TuiStatusEntry {
|
|
7
|
+
id: string;
|
|
8
|
+
kind: 'status';
|
|
9
|
+
content: '';
|
|
10
|
+
status: ActivityStatusProps;
|
|
11
|
+
}
|
|
12
|
+
export interface TuiWelcomeEntry {
|
|
13
|
+
id: string;
|
|
14
|
+
kind: 'welcome';
|
|
15
|
+
content: '';
|
|
16
|
+
welcome: TuiWelcome;
|
|
17
|
+
visible?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export type TuiTranscriptEntry = TuiMessage | TuiStatusEntry | TuiWelcomeEntry;
|
|
20
|
+
export interface TranscriptProps {
|
|
21
|
+
messages: readonly TuiTranscriptEntry[];
|
|
22
|
+
showActionDetails?: boolean;
|
|
23
|
+
fill?: boolean;
|
|
24
|
+
height?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function Transcript({ messages, showActionDetails, fill, height }: TranscriptProps): JSX.Element;
|
|
27
|
+
export interface TranscriptViewport {
|
|
28
|
+
messages: readonly TuiTranscriptEntry[];
|
|
29
|
+
firstMessage: number;
|
|
30
|
+
lastMessage: number;
|
|
31
|
+
}
|
|
32
|
+
/** Returns a stable message window, measured from the newest transcript entry. */
|
|
33
|
+
export declare function transcriptViewport(messages: readonly TuiTranscriptEntry[], offset: number, maximumMessages: number): TranscriptViewport;
|
|
34
|
+
/** Returns a viewport measured in terminal rows so wrapped messages scroll predictably. */
|
|
35
|
+
export declare function transcriptViewportByRows(messages: readonly TuiTranscriptEntry[], offsetRows: number, maximumRows: number, columns: number): TranscriptViewport;
|
|
36
|
+
export declare function transcriptTotalRows(messages: readonly TuiTranscriptEntry[], columns: number): number;
|
|
37
|
+
export declare function AttachmentChip({ attachment }: {
|
|
38
|
+
attachment: Attachment;
|
|
39
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { DARK_THEME as palette } from '../../../themes/theme.js';
|
|
4
|
+
import { MarkdownMessage } from '../markdown-message.js';
|
|
5
|
+
import { FileDiff, fileDiffRowCount } from './file-diff.js';
|
|
6
|
+
import { terminalTextWidth, wrapTerminalText } from '../../formatters.js';
|
|
7
|
+
import { ActivityEntry } from './activity-entry.js';
|
|
8
|
+
import { SubagentCreatedEntry } from './subagent-activity.js';
|
|
9
|
+
import { ActivityStatus } from './activity-status.js';
|
|
10
|
+
import { WelcomePanel, WELCOME_PANEL_ROWS } from './welcome-panel.js';
|
|
11
|
+
export function Transcript({ messages, showActionDetails = false, fill = false, height }) {
|
|
12
|
+
return _jsx(Box, { flexDirection: "column", ...(fill ? { flexGrow: 1, overflow: 'hidden' } : {}), ...(height === undefined ? {} : { height }), children: messages.map((message) => _jsx(TranscriptMessage, { message: message, showActionDetails: showActionDetails }, message.id)) });
|
|
13
|
+
}
|
|
14
|
+
/** Returns a stable message window, measured from the newest transcript entry. */
|
|
15
|
+
export function transcriptViewport(messages, offset, maximumMessages) {
|
|
16
|
+
const normalizedOffset = Math.max(0, Math.min(offset, Math.max(0, messages.length - maximumMessages)));
|
|
17
|
+
const end = messages.length - normalizedOffset;
|
|
18
|
+
const start = Math.max(0, end - maximumMessages);
|
|
19
|
+
return { messages: messages.slice(start, end), firstMessage: start + 1, lastMessage: end };
|
|
20
|
+
}
|
|
21
|
+
/** Returns a viewport measured in terminal rows so wrapped messages scroll predictably. */
|
|
22
|
+
export function transcriptViewportByRows(messages, offsetRows, maximumRows, columns) {
|
|
23
|
+
const rowCounts = messages.map((message) => messageRowCount(message, columns));
|
|
24
|
+
const rowOffsets = [];
|
|
25
|
+
const totalRows = rowCounts.reduce((sum, rows) => sum + rows, 0);
|
|
26
|
+
const viewportRows = Math.max(1, Math.floor(maximumRows));
|
|
27
|
+
const clampedOffset = Math.max(0, Math.min(Math.floor(offsetRows), Math.max(0, totalRows - viewportRows)));
|
|
28
|
+
const targetEnd = totalRows - clampedOffset;
|
|
29
|
+
const targetStart = Math.max(0, targetEnd - viewportRows);
|
|
30
|
+
let row = 0;
|
|
31
|
+
let start = messages.length;
|
|
32
|
+
let end = 0;
|
|
33
|
+
for (let index = 0; index < messages.length; index += 1) {
|
|
34
|
+
const messageStart = row;
|
|
35
|
+
rowOffsets[index] = messageStart;
|
|
36
|
+
const messageRows = rowCounts[index] ?? 1;
|
|
37
|
+
row += messageRows;
|
|
38
|
+
if (row > targetStart && messageStart < targetEnd) {
|
|
39
|
+
start = Math.min(start, index);
|
|
40
|
+
end = index + 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (start === messages.length)
|
|
44
|
+
return { messages: [], firstMessage: 0, lastMessage: 0 };
|
|
45
|
+
const visibleMessages = messages.slice(start, end).flatMap((message, index) => {
|
|
46
|
+
const messageIndex = start + index;
|
|
47
|
+
const messageStart = rowOffsets[messageIndex] ?? 0;
|
|
48
|
+
const messageEnd = messageStart + (rowCounts[messageIndex] ?? 1);
|
|
49
|
+
const visibleStart = Math.max(targetStart, messageStart);
|
|
50
|
+
const visibleEnd = Math.min(targetEnd, messageEnd);
|
|
51
|
+
if (visibleEnd <= visibleStart)
|
|
52
|
+
return [];
|
|
53
|
+
return [clipMessageToRows(message, visibleStart - messageStart, visibleEnd - visibleStart, columns)];
|
|
54
|
+
});
|
|
55
|
+
return { messages: visibleMessages, firstMessage: start + 1, lastMessage: end };
|
|
56
|
+
}
|
|
57
|
+
export function transcriptTotalRows(messages, columns) {
|
|
58
|
+
return messages.reduce((sum, message) => sum + messageRowCount(message, columns), 0);
|
|
59
|
+
}
|
|
60
|
+
function messageRowCount(message, columns) {
|
|
61
|
+
if (message.kind === 'welcome')
|
|
62
|
+
return WELCOME_PANEL_ROWS;
|
|
63
|
+
if (message.kind === 'status')
|
|
64
|
+
return 2;
|
|
65
|
+
const width = Math.max(1, columns - 4);
|
|
66
|
+
const contentRows = message.content.split('\n').reduce((sum, line) => sum + Math.max(1, Math.ceil(terminalTextWidth(line) / width)), 0);
|
|
67
|
+
const attachmentRows = (message.attachments?.length ?? 0) * 2;
|
|
68
|
+
const diffRows = message.fileChange === undefined ? 0 : fileDiffRowCount(message.fileChange, columns);
|
|
69
|
+
const subagentRows = message.subagent === undefined ? 0 : 2;
|
|
70
|
+
return Math.max(1, contentRows + attachmentRows + diffRows + subagentRows + 1);
|
|
71
|
+
}
|
|
72
|
+
function clipMessageToRows(message, skipRows, takeRows, columns) {
|
|
73
|
+
if (message.kind === 'welcome') {
|
|
74
|
+
return skipRows <= 0 && takeRows >= WELCOME_PANEL_ROWS ? message : { ...message, visible: false };
|
|
75
|
+
}
|
|
76
|
+
if (message.kind === 'status' || !isTextMessage(message) || (skipRows <= 0 && takeRows >= messageRowCount(message, columns)))
|
|
77
|
+
return message;
|
|
78
|
+
const width = Math.max(1, columns - 4);
|
|
79
|
+
const contentRows = message.content.split('\n').reduce((sum, line) => sum + Math.max(1, Math.ceil(terminalTextWidth(line) / width)), 0);
|
|
80
|
+
const contentStart = Math.max(0, skipRows);
|
|
81
|
+
const contentEnd = Math.min(contentRows, contentStart + Math.max(0, takeRows));
|
|
82
|
+
if (contentEnd <= contentStart)
|
|
83
|
+
return { ...message, content: sliceTextByRows(message.content, Math.max(0, contentRows - 1), 1, width) };
|
|
84
|
+
return { ...message, content: sliceTextByRows(message.content, contentStart, contentEnd - contentStart, width) };
|
|
85
|
+
}
|
|
86
|
+
function isTextMessage(message) {
|
|
87
|
+
return message.kind === 'assistant' || message.kind === 'user' || message.kind === 'notice' || message.kind === 'error' || message.kind === 'command';
|
|
88
|
+
}
|
|
89
|
+
function sliceTextByRows(content, startRow, rowCount, width) {
|
|
90
|
+
const rows = [];
|
|
91
|
+
for (const line of content.split('\n')) {
|
|
92
|
+
const wrapped = wrapTerminalText(line, width);
|
|
93
|
+
rows.push(...wrapped);
|
|
94
|
+
}
|
|
95
|
+
return rows.slice(startRow, startRow + rowCount).join('\n');
|
|
96
|
+
}
|
|
97
|
+
function TranscriptMessage({ message, showActionDetails }) {
|
|
98
|
+
if (message.kind === 'welcome')
|
|
99
|
+
return message.visible === false ? null : _jsx(WelcomePanel, { welcome: message.welcome });
|
|
100
|
+
if (message.kind === 'status')
|
|
101
|
+
return _jsx(ActivityStatus, { ...message.status });
|
|
102
|
+
if (message.kind === 'assistant')
|
|
103
|
+
return _jsxs(Box, { flexDirection: "row", alignItems: "flex-start", marginBottom: 1, children: [_jsx(MessageMarker, {}), _jsx(Box, { flexGrow: 1, children: _jsx(MarkdownMessage, { content: message.content || ' ' }) })] });
|
|
104
|
+
if (message.kind === 'diff' && message.fileChange !== undefined)
|
|
105
|
+
return _jsx(FileDiff, { change: message.fileChange });
|
|
106
|
+
if (message.kind === 'activity' && message.activity !== undefined)
|
|
107
|
+
return _jsx(ActivityEntry, { activity: message.activity, showDetails: showActionDetails });
|
|
108
|
+
if (message.kind === 'subagent' && message.subagent !== undefined)
|
|
109
|
+
return _jsx(SubagentCreatedEntry, { subagent: message.subagent });
|
|
110
|
+
if (message.kind === 'user')
|
|
111
|
+
return _jsxs(Box, { backgroundColor: palette.user, flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { flexDirection: "row", alignItems: "flex-start", children: [_jsx(MessageMarker, {}), _jsx(Box, { flexGrow: 1, children: _jsx(MarkdownMessage, { content: message.content }) })] }), message.attachments?.map((attachment) => _jsx(AttachmentChip, { attachment: attachment }, attachment.id))] });
|
|
112
|
+
const tone = message.kind === 'error' ? palette.error : message.kind === 'command' ? palette.accent : palette.muted;
|
|
113
|
+
const marker = message.kind === 'error' ? '!' : message.kind === 'command' ? '›' : '·';
|
|
114
|
+
return _jsxs(Box, { marginBottom: 1, children: [_jsxs(Text, { color: tone, children: [marker, " "] }), _jsx(Text, { color: tone, wrap: "wrap", children: message.content })] });
|
|
115
|
+
}
|
|
116
|
+
function MessageMarker() {
|
|
117
|
+
return _jsx(Text, { color: palette.text, children: "\u25CF " });
|
|
118
|
+
}
|
|
119
|
+
export function AttachmentChip({ attachment }) {
|
|
120
|
+
return _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: palette.muted, children: ["\u25A3 ", attachment.name] }) });
|
|
121
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { DARK_THEME as palette } from '../../../themes/theme.js';
|
|
4
|
+
import { COMMAND_REGISTRY } from '../../../../application/commands/command-runtime.js';
|
|
5
|
+
import { formatCommandReference } from '../../../../application/commands/command-presentation.js';
|
|
6
|
+
const HELP_COMMAND = commandReference('help');
|
|
7
|
+
const MODEL_COMMAND = commandReference('model.current');
|
|
8
|
+
export const WELCOME_PANEL_ROWS = 10;
|
|
9
|
+
export function WelcomePanel({ welcome }) {
|
|
10
|
+
const model = welcome.model ?? 'Select a model to begin';
|
|
11
|
+
const trustLabel = welcome.trusted ? 'Trusted workspace' : 'Restricted workspace';
|
|
12
|
+
const trustColor = welcome.trusted ? palette.success : palette.warning;
|
|
13
|
+
return _jsxs(Box, { borderStyle: "round", borderColor: palette.accent, flexDirection: "row", marginBottom: 1, paddingX: 1, paddingY: 1, children: [_jsxs(Box, { flexDirection: "column", width: "38%", children: [_jsxs(Text, { color: palette.accent, children: ["LotaGate CLI v", welcome.version] }), _jsx(Text, { bold: true, color: palette.text, children: "Welcome back!" }), _jsx(Text, { color: palette.muted, wrap: "truncate", children: model }), _jsxs(Text, { color: trustColor, children: ["\u25CF ", trustLabel] }), _jsx(Text, { color: palette.muted, wrap: "truncate", children: welcome.cwd })] }), _jsxs(Box, { borderLeft: true, borderColor: palette.border, flexDirection: "column", paddingLeft: 1, width: "62%", children: [_jsx(Text, { bold: true, color: palette.accent, children: "Tips for getting started" }), _jsxs(Text, { color: palette.muted, wrap: "truncate", children: [HELP_COMMAND, " Browse interactive commands"] }), _jsxs(Text, { color: palette.muted, wrap: "truncate", children: [MODEL_COMMAND, " Show the active model"] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { bold: true, color: palette.accent, children: "Recent activity" }) }), _jsx(Text, { color: palette.muted, children: "No recent activity" })] })] });
|
|
14
|
+
}
|
|
15
|
+
function commandReference(actionId) {
|
|
16
|
+
const action = COMMAND_REGISTRY.get(actionId);
|
|
17
|
+
if (action === undefined)
|
|
18
|
+
throw new Error(`Missing command contract: ${actionId}`);
|
|
19
|
+
return formatCommandReference(action, 'tui');
|
|
20
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';
|
|
3
|
+
import { Box, useInput, useStdout } from 'ink';
|
|
4
|
+
import { Transcript, transcriptTotalRows, transcriptViewportByRows } from './components/transcript.js';
|
|
5
|
+
import { Composer } from './components/composer.js';
|
|
6
|
+
import { estimateModalRows, Modal } from './components/modal.js';
|
|
7
|
+
import { SubagentActivity, visibleSubagents } from './components/subagent-activity.js';
|
|
8
|
+
import { parseMouseWheel } from '../terminal-mouse.js';
|
|
9
|
+
const SMOOTH_SCROLL_ROWS = 3;
|
|
10
|
+
export function LotaGateTui({ bridge }) {
|
|
11
|
+
const state = useSyncExternalStore((listener) => bridge.subscribe(listener), () => bridge.snapshot(), () => bridge.snapshot());
|
|
12
|
+
const { stdout } = useStdout();
|
|
13
|
+
const [scrollOffset, setScrollOffset] = useState(0);
|
|
14
|
+
const [selectedSubagentId, setSelectedSubagentId] = useState();
|
|
15
|
+
const [composerRows, setComposerRows] = useState();
|
|
16
|
+
const [modalLayout, setModalLayout] = useState();
|
|
17
|
+
const modal = state.modal;
|
|
18
|
+
const inlineModal = isInlineModal(modal) ? modal : undefined;
|
|
19
|
+
const canCancelActiveRun = state.runActive && state.modal === undefined;
|
|
20
|
+
const terminalRows = stdout.rows ?? 24;
|
|
21
|
+
const estimatedComposerRows = 6 + state.pendingAttachments.length * 2;
|
|
22
|
+
const currentComposerRows = composerRows ?? estimatedComposerRows;
|
|
23
|
+
const currentModalRows = inlineModal === undefined
|
|
24
|
+
? 0
|
|
25
|
+
: modalLayout?.modal === inlineModal ? modalLayout.rows : estimateModalRows(inlineModal);
|
|
26
|
+
const reservedRows = reservedLayoutRows(state, selectableSubagentCount(state.subagents), currentComposerRows, currentModalRows);
|
|
27
|
+
const columns = Math.max(40, stdout.columns ?? 80);
|
|
28
|
+
const timeline = buildTranscriptTimeline(state);
|
|
29
|
+
const totalRows = transcriptTotalRows(timeline, columns);
|
|
30
|
+
const availableTranscriptRows = Math.max(0, terminalRows - reservedRows);
|
|
31
|
+
const minimumTranscriptRows = currentComposerRows > estimatedComposerRows ? 0 : 1;
|
|
32
|
+
const transcriptRows = Math.max(minimumTranscriptRows, availableTranscriptRows);
|
|
33
|
+
const maximumScrollOffset = Math.max(0, totalRows - transcriptRows);
|
|
34
|
+
const viewport = transcriptViewportByRows(timeline, scrollOffset, Math.max(1, transcriptRows), columns);
|
|
35
|
+
const fillTranscript = transcriptRows > 0 && totalRows >= transcriptRows;
|
|
36
|
+
const selectableSubagents = visibleSubagents(state.subagents);
|
|
37
|
+
const handleComposerRowsChange = useCallback((rows) => {
|
|
38
|
+
setComposerRows((current) => current === rows ? current : rows);
|
|
39
|
+
}, []);
|
|
40
|
+
const handleModalRowsChange = useCallback((rows) => {
|
|
41
|
+
if (inlineModal === undefined)
|
|
42
|
+
return;
|
|
43
|
+
setModalLayout((current) => current?.modal === inlineModal && current.rows === rows ? current : { modal: inlineModal, rows });
|
|
44
|
+
}, [inlineModal]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (selectedSubagentId !== undefined && selectableSubagents.some((subagent) => subagent.id === selectedSubagentId))
|
|
47
|
+
return;
|
|
48
|
+
setSelectedSubagentId(selectableSubagents[0]?.id);
|
|
49
|
+
}, [selectableSubagents, selectedSubagentId]);
|
|
50
|
+
useInput((input, key) => {
|
|
51
|
+
const subagentDirection = state.modal === undefined
|
|
52
|
+
? subagentNavigationDirection(input, key, state.runActive)
|
|
53
|
+
: undefined;
|
|
54
|
+
if (key.ctrl && input.toLowerCase() === 'c')
|
|
55
|
+
bridge.interrupt();
|
|
56
|
+
else if ((key.escape || input === '\u001b') && canCancelActiveRun)
|
|
57
|
+
bridge.cancel();
|
|
58
|
+
else if (subagentDirection !== undefined) {
|
|
59
|
+
if (selectableSubagents.length === 0)
|
|
60
|
+
return;
|
|
61
|
+
const current = selectableSubagents.findIndex((subagent) => subagent.id === selectedSubagentId);
|
|
62
|
+
const next = selectableSubagents[(current + subagentDirection + selectableSubagents.length) % selectableSubagents.length];
|
|
63
|
+
setSelectedSubagentId(next?.id);
|
|
64
|
+
}
|
|
65
|
+
else if (state.modal === undefined && key.ctrl && input.toLowerCase() === 'o' && selectedSubagentId !== undefined) {
|
|
66
|
+
bridge.openSubagentDetails(selectedSubagentId);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const wheel = parseMouseWheel(input);
|
|
70
|
+
if (wheel === 'up')
|
|
71
|
+
setScrollOffset((current) => Math.min(maximumScrollOffset, current + 3));
|
|
72
|
+
else if (wheel === 'down')
|
|
73
|
+
setScrollOffset((current) => Math.max(0, current - 3));
|
|
74
|
+
else if (key.pageUp || key.home)
|
|
75
|
+
setScrollOffset(key.home ? maximumScrollOffset : (current) => Math.min(maximumScrollOffset, current + transcriptRows));
|
|
76
|
+
else if (isCtrlArrow(input, key, 'up'))
|
|
77
|
+
setScrollOffset((current) => Math.min(maximumScrollOffset, current + SMOOTH_SCROLL_ROWS));
|
|
78
|
+
else if (key.pageDown || key.end)
|
|
79
|
+
setScrollOffset(key.end ? 0 : (current) => Math.max(0, current - transcriptRows));
|
|
80
|
+
else if (isCtrlArrow(input, key, 'down'))
|
|
81
|
+
setScrollOffset((current) => Math.max(0, current - SMOOTH_SCROLL_ROWS));
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return _jsx(Box, { flexDirection: "column", paddingX: 1, ...(stdout.rows === undefined ? {} : { height: stdout.rows, overflow: 'hidden' }), children: modal !== undefined && inlineModal === undefined
|
|
85
|
+
? _jsx(Modal, { bridge: bridge, modal: modal })
|
|
86
|
+
: _jsxs(_Fragment, { children: [transcriptRows > 0 && _jsx(Transcript, { messages: viewport.messages, showActionDetails: state.actionDetails, fill: fillTranscript, ...(fillTranscript ? { height: transcriptRows } : {}) }), _jsx(SubagentActivity, { subagents: state.subagents, paused: false, ...(selectedSubagentId === undefined ? {} : { selectedId: selectedSubagentId }) }), _jsx(Composer, { bridge: bridge, enabled: state.ready && !state.runActive && inlineModal === undefined, activeRun: canCancelActiveRun, onLayoutRowsChange: handleComposerRowsChange, ...(state.clearBlockedUntil === undefined ? {} : { clearBlockedUntil: state.clearBlockedUntil }), ...(state.footerNotice === undefined ? {} : { footerNotice: state.footerNotice }), ...(state.contextUsage === undefined ? {} : { contextUsage: state.contextUsage }), attachments: state.pendingAttachments, fileChoices: state.fileSuggestions }), inlineModal !== undefined && _jsx(Modal, { bridge: bridge, modal: inlineModal, onLayoutRowsChange: handleModalRowsChange })] }) });
|
|
87
|
+
}
|
|
88
|
+
function isInlineModal(modal) {
|
|
89
|
+
return modal?.kind === 'choice' || modal?.kind === 'approval' || modal?.kind === 'plan';
|
|
90
|
+
}
|
|
91
|
+
function reservedLayoutRows(state, activeSubagents, composerRows, modalRows) {
|
|
92
|
+
const subagentRows = activeSubagents === 0 ? 0 : 4 + activeSubagents * 4;
|
|
93
|
+
return subagentRows + Math.max(composerRows, 6 + state.pendingAttachments.length * 2) + modalRows;
|
|
94
|
+
}
|
|
95
|
+
function buildTranscriptTimeline(state) {
|
|
96
|
+
const welcome = state.welcome === undefined ? [] : [{ id: 'tui-welcome', kind: 'welcome', content: '', welcome: state.welcome }];
|
|
97
|
+
if (state.status === undefined)
|
|
98
|
+
return [...welcome, ...state.messages];
|
|
99
|
+
return [...welcome, ...state.messages, {
|
|
100
|
+
id: 'tui-live-turn-status',
|
|
101
|
+
kind: 'status',
|
|
102
|
+
content: '',
|
|
103
|
+
status: {
|
|
104
|
+
status: state.status,
|
|
105
|
+
...(state.activityStartedAt === undefined ? {} : { activityStartedAt: state.activityStartedAt }),
|
|
106
|
+
...(state.elapsedMs === undefined ? {} : { elapsedMs: state.elapsedMs }),
|
|
107
|
+
...(state.usage === undefined ? {} : { usage: state.usage }),
|
|
108
|
+
paused: state.modal !== undefined,
|
|
109
|
+
},
|
|
110
|
+
}];
|
|
111
|
+
}
|
|
112
|
+
function selectableSubagentCount(subagents) {
|
|
113
|
+
return subagents.filter((subagent) => subagent.status === 'queued' || subagent.status === 'running').length;
|
|
114
|
+
}
|
|
115
|
+
function isCtrlArrow(input, key, direction) {
|
|
116
|
+
if (key.ctrl && (direction === 'up' ? key.upArrow : key.downArrow))
|
|
117
|
+
return true;
|
|
118
|
+
return input === (direction === 'up' ? '\u001b[1;5A' : '\u001b[1;5B');
|
|
119
|
+
}
|
|
120
|
+
function subagentNavigationDirection(input, key, runActive) {
|
|
121
|
+
const value = input.toLowerCase();
|
|
122
|
+
if (key.ctrl && value === 'j')
|
|
123
|
+
return 1;
|
|
124
|
+
if (key.ctrl && value === 'k')
|
|
125
|
+
return -1;
|
|
126
|
+
// Windows terminals commonly encode Ctrl+J/K as LF/VT and omit `key.ctrl`.
|
|
127
|
+
// Only use that fallback while the composer is disabled by an active run so
|
|
128
|
+
// Enter can still submit a normal prompt whenever the composer is available.
|
|
129
|
+
if (!runActive)
|
|
130
|
+
return undefined;
|
|
131
|
+
if (input === '\n')
|
|
132
|
+
return 1;
|
|
133
|
+
if (input === '\v')
|
|
134
|
+
return -1;
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Text } from 'ink';
|
|
3
|
+
import { DARK_THEME as palette } from '../../themes/theme.js';
|
|
4
|
+
import { tokenizeMarkdownInline } from './markdown-inline.js';
|
|
5
|
+
export function MarkdownInline({ value }) {
|
|
6
|
+
return _jsx(_Fragment, { children: tokenizeMarkdownInline(value).map((token, index) => _jsx(InlineToken, { token: token }, index)) });
|
|
7
|
+
}
|
|
8
|
+
function InlineToken({ token }) {
|
|
9
|
+
if (token.kind === 'link')
|
|
10
|
+
return _jsx(Text, { color: palette.link, underline: true, children: token.label });
|
|
11
|
+
if (token.kind === 'code')
|
|
12
|
+
return _jsx(Text, { color: palette.code, backgroundColor: palette.surfaceRaised, children: token.value });
|
|
13
|
+
if (token.kind === 'bold')
|
|
14
|
+
return _jsx(Text, { bold: true, children: token.value });
|
|
15
|
+
if (token.kind === 'italic')
|
|
16
|
+
return _jsx(Text, { italic: true, children: token.value });
|
|
17
|
+
if (token.kind === 'strike')
|
|
18
|
+
return _jsx(Text, { strikethrough: true, children: token.value });
|
|
19
|
+
return _jsx(Text, { children: token.value });
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type MarkdownInlineToken = {
|
|
2
|
+
kind: 'text';
|
|
3
|
+
value: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: 'code' | 'bold' | 'italic' | 'strike';
|
|
6
|
+
value: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'link';
|
|
9
|
+
label: string;
|
|
10
|
+
href: string;
|
|
11
|
+
};
|
|
12
|
+
/** Tokenizes the safe Markdown subset rendered by the terminal UI. */
|
|
13
|
+
export declare function tokenizeMarkdownInline(value: string): readonly MarkdownInlineToken[];
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const INLINE_MARKUP = /(`[^\n`]+`|\*\*[^*\n]+\*\*|__[^_\n]+__|~~[^~\n]+~~|\*[^*\n]+\*|_[^_\n]+_)/gu;
|
|
2
|
+
/** Tokenizes the safe Markdown subset rendered by the terminal UI. */
|
|
3
|
+
export function tokenizeMarkdownInline(value) {
|
|
4
|
+
const tokens = [];
|
|
5
|
+
let cursor = 0;
|
|
6
|
+
let textStart = 0;
|
|
7
|
+
while (cursor < value.length) {
|
|
8
|
+
const link = parseLinkAt(value, cursor);
|
|
9
|
+
if (link !== undefined) {
|
|
10
|
+
pushText(tokens, value, textStart, cursor);
|
|
11
|
+
tokens.push({ kind: 'link', label: link.label, href: link.href });
|
|
12
|
+
cursor = link.end;
|
|
13
|
+
textStart = cursor;
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
INLINE_MARKUP.lastIndex = 0;
|
|
17
|
+
const markup = INLINE_MARKUP.exec(value.slice(cursor));
|
|
18
|
+
if (markup?.index === 0) {
|
|
19
|
+
const raw = markup[0] ?? '';
|
|
20
|
+
pushText(tokens, value, textStart, cursor);
|
|
21
|
+
tokens.push(parseToken(raw));
|
|
22
|
+
cursor += raw.length;
|
|
23
|
+
textStart = cursor;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
cursor += 1;
|
|
27
|
+
}
|
|
28
|
+
pushText(tokens, value, textStart, value.length);
|
|
29
|
+
return tokens;
|
|
30
|
+
}
|
|
31
|
+
function parseToken(value) {
|
|
32
|
+
if (value.startsWith('`'))
|
|
33
|
+
return { kind: 'code', value: value.slice(1, -1) };
|
|
34
|
+
if (value.startsWith('**') || value.startsWith('__'))
|
|
35
|
+
return { kind: 'bold', value: value.slice(2, -2) };
|
|
36
|
+
if (value.startsWith('~~'))
|
|
37
|
+
return { kind: 'strike', value: value.slice(2, -2) };
|
|
38
|
+
if (value.startsWith('*') || value.startsWith('_'))
|
|
39
|
+
return { kind: 'italic', value: value.slice(1, -1) };
|
|
40
|
+
return { kind: 'text', value };
|
|
41
|
+
}
|
|
42
|
+
function parseLinkAt(value, start) {
|
|
43
|
+
if (value[start] !== '[')
|
|
44
|
+
return undefined;
|
|
45
|
+
const labelEnd = findUnescaped(value, ']', start + 1);
|
|
46
|
+
if (labelEnd === -1 || value[labelEnd + 1] !== '(')
|
|
47
|
+
return undefined;
|
|
48
|
+
const destinationStart = labelEnd + 2;
|
|
49
|
+
if (value[destinationStart] === '<') {
|
|
50
|
+
const destinationEnd = findUnescaped(value, '>', destinationStart + 1);
|
|
51
|
+
if (destinationEnd === -1 || value[destinationEnd + 1] !== ')')
|
|
52
|
+
return undefined;
|
|
53
|
+
return { label: value.slice(start + 1, labelEnd), href: value.slice(destinationStart + 1, destinationEnd), end: destinationEnd + 2 };
|
|
54
|
+
}
|
|
55
|
+
let depth = 1;
|
|
56
|
+
for (let index = destinationStart; index < value.length; index += 1) {
|
|
57
|
+
const character = value[index] ?? '';
|
|
58
|
+
if (character === '\\') {
|
|
59
|
+
index += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (/\s/u.test(character))
|
|
63
|
+
return undefined;
|
|
64
|
+
if (character === '(') {
|
|
65
|
+
depth += 1;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (character !== ')')
|
|
69
|
+
continue;
|
|
70
|
+
depth -= 1;
|
|
71
|
+
if (depth === 0) {
|
|
72
|
+
return { label: value.slice(start + 1, labelEnd), href: value.slice(destinationStart, index), end: index + 1 };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
function findUnescaped(value, target, start) {
|
|
78
|
+
for (let index = start; index < value.length; index += 1) {
|
|
79
|
+
if (value[index] === '\\') {
|
|
80
|
+
index += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (value[index] === target)
|
|
84
|
+
return index;
|
|
85
|
+
}
|
|
86
|
+
return -1;
|
|
87
|
+
}
|
|
88
|
+
function pushText(tokens, value, start, end) {
|
|
89
|
+
if (end > start)
|
|
90
|
+
tokens.push({ kind: 'text', value: value.slice(start, end) });
|
|
91
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { DARK_THEME as palette } from '../../themes/theme.js';
|
|
4
|
+
import { MarkdownInline } from './markdown-inline-renderer.js';
|
|
5
|
+
import { MarkdownTable, parseMarkdownTable } from './markdown-table.js';
|
|
6
|
+
/** A deliberately small, safe Markdown subset for streamed terminal text. */
|
|
7
|
+
export function MarkdownMessage({ content }) {
|
|
8
|
+
let inCodeBlock = false;
|
|
9
|
+
const lines = content.split('\n');
|
|
10
|
+
const rendered = [];
|
|
11
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
12
|
+
const line = lines[index] ?? '';
|
|
13
|
+
if (line.startsWith('```')) {
|
|
14
|
+
inCodeBlock = !inCodeBlock;
|
|
15
|
+
rendered.push(_jsx(Text, { color: palette.muted, children: line.length > 3 ? `· ${line.slice(3).trim()}` : '' }, index));
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
if (inCodeBlock) {
|
|
19
|
+
rendered.push(_jsx(Text, { color: palette.code, wrap: "wrap", children: line }, index));
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const table = parseMarkdownTable(lines, index);
|
|
23
|
+
if (table !== undefined) {
|
|
24
|
+
rendered.push(_jsx(MarkdownTable, { table: table.table }, index));
|
|
25
|
+
index = table.nextLine - 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const heading = /^(#{1,6})\s+(.+)$/u.exec(line);
|
|
29
|
+
if (heading !== null) {
|
|
30
|
+
rendered.push(_jsx(Text, { bold: true, color: palette.accent, wrap: "wrap", children: _jsx(MarkdownInline, { value: heading[2] ?? '' }) }, index));
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const list = parseMarkdownListItem(line);
|
|
34
|
+
if (list !== undefined) {
|
|
35
|
+
rendered.push(_jsx(MarkdownListItem, { item: list }, index));
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const quote = /^(\s*)(>+)\s?(.*)$/u.exec(line);
|
|
39
|
+
if (quote !== null) {
|
|
40
|
+
rendered.push(_jsxs(Text, { color: palette.muted, wrap: "wrap", children: [quote[1], '│ '.repeat(quote[2]?.length ?? 1), _jsx(MarkdownInline, { value: quote[3] ?? '' })] }, index));
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (/^([-*_])(?:\s*\1){2,}\s*$/u.test(line)) {
|
|
44
|
+
rendered.push(_jsx(Text, { color: palette.muted, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }, index));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
rendered.push(_jsx(Text, { wrap: "wrap", children: _jsx(MarkdownInline, { value: line }) }, index));
|
|
48
|
+
}
|
|
49
|
+
return _jsx(Box, { flexDirection: "column", children: rendered });
|
|
50
|
+
}
|
|
51
|
+
function parseMarkdownListItem(line) {
|
|
52
|
+
const match = /^(\s*)([-*+]|\d+[.)])\s+(?:(\[(?: |x|X)\])\s+)?(.+)$/u.exec(line);
|
|
53
|
+
if (match === null)
|
|
54
|
+
return undefined;
|
|
55
|
+
const task = match[3];
|
|
56
|
+
return {
|
|
57
|
+
indent: match[1] ?? '',
|
|
58
|
+
marker: match[2] ?? '•',
|
|
59
|
+
content: match[4] ?? '',
|
|
60
|
+
...(task === undefined ? {} : { checked: task.toLowerCase() === '[x]' }),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function MarkdownListItem({ item }) {
|
|
64
|
+
const marker = item.checked === undefined ? /^\d/u.test(item.marker) ? item.marker : '•' : item.checked ? '☑' : '☐';
|
|
65
|
+
return _jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: palette.accent, children: [item.indent, marker, " "] }), _jsx(Box, { flexGrow: 1, children: _jsx(Text, { wrap: "wrap", children: _jsx(MarkdownInline, { value: item.content }) }) })] });
|
|
66
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JSX } from 'react';
|
|
2
|
+
export type MarkdownTableAlignment = 'left' | 'center' | 'right';
|
|
3
|
+
export interface MarkdownTableData {
|
|
4
|
+
headers: readonly string[];
|
|
5
|
+
rows: readonly (readonly string[])[];
|
|
6
|
+
alignments: readonly MarkdownTableAlignment[];
|
|
7
|
+
}
|
|
8
|
+
export interface MarkdownTableMatch {
|
|
9
|
+
table: MarkdownTableData;
|
|
10
|
+
nextLine: number;
|
|
11
|
+
}
|
|
12
|
+
/** Detects a pipe table beginning at the supplied Markdown line. */
|
|
13
|
+
export declare function parseMarkdownTable(lines: readonly string[], startLine: number): MarkdownTableMatch | undefined;
|
|
14
|
+
export declare function MarkdownTable({ table }: {
|
|
15
|
+
table: MarkdownTableData;
|
|
16
|
+
}): JSX.Element;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import { DARK_THEME as palette } from '../../themes/theme.js';
|
|
4
|
+
import { terminalTextWidth } from '../formatters.js';
|
|
5
|
+
import { MarkdownInline } from './markdown-inline-renderer.js';
|
|
6
|
+
import { tokenizeMarkdownInline } from './markdown-inline.js';
|
|
7
|
+
/** Detects a pipe table beginning at the supplied Markdown line. */
|
|
8
|
+
export function parseMarkdownTable(lines, startLine) {
|
|
9
|
+
const header = splitTableRow(lines[startLine] ?? '');
|
|
10
|
+
const separator = splitTableRow(lines[startLine + 1] ?? '');
|
|
11
|
+
if (header.length < 2 || separator.length < 2 || separator.some((cell) => !isSeparatorCell(cell)))
|
|
12
|
+
return undefined;
|
|
13
|
+
const columnCount = Math.max(header.length, separator.length);
|
|
14
|
+
const headers = normalizeRow(header, columnCount);
|
|
15
|
+
const alignments = normalizeAlignments(separator, columnCount);
|
|
16
|
+
const rows = [];
|
|
17
|
+
let nextLine = startLine + 2;
|
|
18
|
+
while (nextLine < lines.length) {
|
|
19
|
+
const row = splitTableRow(lines[nextLine] ?? '');
|
|
20
|
+
if (row.length < 2)
|
|
21
|
+
break;
|
|
22
|
+
rows.push(normalizeRow(row, columnCount));
|
|
23
|
+
nextLine += 1;
|
|
24
|
+
}
|
|
25
|
+
return { table: { headers, rows, alignments }, nextLine };
|
|
26
|
+
}
|
|
27
|
+
export function MarkdownTable({ table }) {
|
|
28
|
+
const widths = table.headers.map((header, column) => Math.max(terminalTextWidth(inlineText(header)), ...table.rows.map((row) => terminalTextWidth(inlineText(row[column] ?? '')))));
|
|
29
|
+
return _jsxs(Box, { flexDirection: "column", children: [renderTableRow(table.headers, widths, table.alignments, true), renderSeparator(widths), table.rows.map((row, index) => renderTableRow(row, widths, table.alignments, false, index))] });
|
|
30
|
+
}
|
|
31
|
+
function renderTableRow(cells, widths, alignments, header, key = 0) {
|
|
32
|
+
return _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: palette.muted, children: "\u2502" }), cells.map((cell, column) => _jsxs(Box, { flexDirection: "row", children: [_jsx(Box, { width: (widths[column] ?? 0) + 2, paddingX: 1, justifyContent: alignments[column] === 'right' ? 'flex-end' : alignments[column] === 'center' ? 'center' : 'flex-start', children: _jsx(Text, { bold: header, wrap: "truncate", children: _jsx(MarkdownInline, { value: cell }) }) }), _jsx(Text, { color: palette.muted, children: "\u2502" })] }, column))] }, key);
|
|
33
|
+
}
|
|
34
|
+
function renderSeparator(widths) {
|
|
35
|
+
return _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: palette.muted, children: "\u251C" }), widths.map((width, index) => _jsxs(Text, { color: palette.muted, children: ['─'.repeat(width + 2), index === widths.length - 1 ? '┤' : '┼'] }, index))] });
|
|
36
|
+
}
|
|
37
|
+
function splitTableRow(line) {
|
|
38
|
+
const trimmed = line.trim();
|
|
39
|
+
if (!trimmed.includes('|'))
|
|
40
|
+
return [];
|
|
41
|
+
const content = trimmed.startsWith('|') ? trimmed.slice(1) : trimmed;
|
|
42
|
+
const withoutTrailingPipe = content.endsWith('|') && !content.endsWith('\\|') ? content.slice(0, -1) : content;
|
|
43
|
+
const cells = [];
|
|
44
|
+
let current = '';
|
|
45
|
+
let escaped = false;
|
|
46
|
+
for (const character of withoutTrailingPipe) {
|
|
47
|
+
if (character === '|' && !escaped) {
|
|
48
|
+
cells.push(current.trim());
|
|
49
|
+
current = '';
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (character === '\\' && !escaped) {
|
|
53
|
+
escaped = true;
|
|
54
|
+
current += character;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
escaped = false;
|
|
58
|
+
current += character;
|
|
59
|
+
}
|
|
60
|
+
cells.push(current.trim());
|
|
61
|
+
return cells;
|
|
62
|
+
}
|
|
63
|
+
function isSeparatorCell(value) { return /^:?-{1,}:?$/u.test(value); }
|
|
64
|
+
function normalizeRow(row, columnCount) {
|
|
65
|
+
return Array.from({ length: columnCount }, (_, index) => row[index] ?? '');
|
|
66
|
+
}
|
|
67
|
+
function normalizeAlignments(row, columnCount) {
|
|
68
|
+
return Array.from({ length: columnCount }, (_, index) => {
|
|
69
|
+
const cell = row[index] ?? '';
|
|
70
|
+
const left = cell.startsWith(':');
|
|
71
|
+
const right = cell.endsWith(':');
|
|
72
|
+
return left && right ? 'center' : right ? 'right' : 'left';
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function inlineText(value) {
|
|
76
|
+
return tokenizeMarkdownInline(value).map((token) => token.kind === 'link' ? token.label : token.value).join('');
|
|
77
|
+
}
|