byterover-cli 0.4.0 → 1.0.0
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/README.md +1 -9
- package/dist/commands/curate.d.ts +1 -3
- package/dist/commands/curate.js +14 -51
- package/dist/commands/main.d.ts +8 -0
- package/dist/commands/main.js +29 -8
- package/dist/commands/query.d.ts +1 -3
- package/dist/commands/query.js +8 -35
- package/dist/config/context-tree-domains.d.ts +5 -0
- package/dist/config/context-tree-domains.js +6 -1
- package/dist/config/environment.js +9 -9
- package/dist/constants.d.ts +14 -0
- package/dist/constants.js +18 -0
- package/dist/core/domain/cipher/agent/agent-info.d.ts +199 -0
- package/dist/core/domain/cipher/agent/agent-info.js +143 -0
- package/dist/core/domain/cipher/agent/agent-registry.d.ts +96 -0
- package/dist/core/domain/cipher/agent/agent-registry.js +254 -0
- package/dist/core/domain/cipher/agent/index.d.ts +4 -1
- package/dist/core/domain/cipher/agent/index.js +7 -1
- package/dist/core/domain/cipher/agent-events/types.d.ts +355 -2
- package/dist/core/domain/cipher/agent-events/types.js +11 -0
- package/dist/core/domain/cipher/errors/error-normalizer.d.ts +156 -0
- package/dist/core/domain/cipher/errors/error-normalizer.js +379 -0
- package/dist/core/domain/cipher/errors/file-system-error.d.ts +2 -1
- package/dist/core/domain/cipher/errors/file-system-error.js +3 -2
- package/dist/core/domain/cipher/errors/system-prompt-error-codes.d.ts +79 -0
- package/dist/core/domain/cipher/errors/system-prompt-error-codes.js +80 -0
- package/dist/core/domain/cipher/errors/system-prompt-error.d.ts +114 -0
- package/dist/core/domain/cipher/errors/system-prompt-error.js +144 -0
- package/dist/core/domain/cipher/file-system/types.d.ts +57 -0
- package/dist/core/domain/cipher/llm/error-codes.d.ts +51 -0
- package/dist/core/domain/cipher/llm/error-codes.js +51 -0
- package/dist/core/domain/cipher/llm/index.d.ts +9 -0
- package/dist/core/domain/cipher/llm/index.js +13 -0
- package/dist/core/domain/cipher/llm/registry.d.ts +113 -0
- package/dist/core/domain/cipher/llm/registry.js +244 -0
- package/dist/core/domain/cipher/llm/schemas.d.ts +155 -0
- package/dist/core/domain/cipher/llm/schemas.js +151 -0
- package/dist/core/domain/cipher/llm/types.d.ts +121 -0
- package/dist/core/domain/cipher/llm/types.js +60 -0
- package/dist/core/domain/cipher/storage/message-storage-types.d.ts +114 -5
- package/dist/core/domain/cipher/streaming/types.d.ts +119 -0
- package/dist/core/domain/cipher/streaming/types.js +16 -0
- package/dist/core/domain/cipher/system-prompt/types.d.ts +44 -0
- package/dist/core/domain/cipher/todos/types.d.ts +34 -0
- package/dist/core/domain/cipher/tools/constants.d.ts +5 -2
- package/dist/core/domain/cipher/tools/constants.js +5 -2
- package/dist/core/domain/cipher/tools/types.d.ts +31 -0
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +3 -1
- package/dist/core/domain/errors/connection-error.d.ts +33 -0
- package/dist/core/domain/errors/connection-error.js +54 -0
- package/dist/core/domain/errors/core-process-error.d.ts +27 -0
- package/dist/core/domain/errors/core-process-error.js +43 -0
- package/dist/core/domain/errors/task-error.d.ts +64 -0
- package/dist/core/domain/errors/task-error.js +116 -0
- package/dist/core/domain/errors/transport-error.d.ts +72 -0
- package/dist/core/domain/errors/transport-error.js +114 -0
- package/dist/core/domain/instance/index.d.ts +1 -0
- package/dist/core/domain/instance/index.js +1 -0
- package/dist/core/domain/instance/types.d.ts +57 -0
- package/dist/core/domain/instance/types.js +72 -0
- package/dist/core/domain/knowledge/directory-manager.d.ts +16 -0
- package/dist/core/domain/knowledge/directory-manager.js +31 -0
- package/dist/core/domain/transport/index.d.ts +2 -0
- package/dist/core/domain/transport/index.js +2 -0
- package/dist/core/domain/transport/schemas.d.ts +1149 -0
- package/dist/core/domain/transport/schemas.js +554 -0
- package/dist/core/domain/transport/types.d.ts +67 -0
- package/dist/core/domain/transport/types.js +7 -0
- package/dist/core/interfaces/cipher/cipher-services.d.ts +15 -3
- package/dist/core/interfaces/cipher/i-chat-session.d.ts +47 -5
- package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +39 -4
- package/dist/core/interfaces/cipher/i-content-generator.d.ts +3 -5
- package/dist/core/interfaces/cipher/i-file-system.d.ts +12 -1
- package/dist/core/interfaces/cipher/i-llm-service.d.ts +4 -5
- package/dist/core/interfaces/cipher/i-todo-storage.d.ts +24 -0
- package/dist/core/interfaces/cipher/i-todo-storage.js +1 -0
- package/dist/core/interfaces/cipher/i-tool-plugin.d.ts +90 -0
- package/dist/core/interfaces/cipher/i-tool-plugin.js +1 -0
- package/dist/core/interfaces/cipher/i-tool-provider.d.ts +3 -2
- package/dist/core/interfaces/cipher/i-tool-scheduler.d.ts +4 -0
- package/dist/core/interfaces/cipher/index.d.ts +35 -0
- package/dist/core/interfaces/cipher/index.js +11 -0
- package/dist/core/interfaces/cipher/message-factory.d.ts +155 -0
- package/dist/core/interfaces/cipher/message-factory.js +252 -0
- package/dist/core/interfaces/cipher/message-type-guards.d.ts +139 -0
- package/dist/core/interfaces/cipher/message-type-guards.js +173 -0
- package/dist/core/interfaces/cipher/message-types.d.ts +279 -5
- package/dist/core/interfaces/cipher/message-types.js +6 -0
- package/dist/core/interfaces/cipher/sanitization-types.d.ts +147 -0
- package/dist/core/interfaces/cipher/sanitization-types.js +46 -0
- package/dist/core/interfaces/executor/i-curate-executor.d.ts +34 -0
- package/dist/core/interfaces/executor/i-curate-executor.js +1 -0
- package/dist/core/interfaces/executor/i-query-executor.d.ts +32 -0
- package/dist/core/interfaces/executor/i-query-executor.js +1 -0
- package/dist/core/interfaces/executor/index.d.ts +2 -0
- package/dist/core/interfaces/executor/index.js +2 -0
- package/dist/core/interfaces/instance/i-instance-discovery.d.ts +45 -0
- package/dist/core/interfaces/instance/i-instance-discovery.js +1 -0
- package/dist/core/interfaces/instance/i-instance-manager.d.ts +58 -0
- package/dist/core/interfaces/instance/i-instance-manager.js +1 -0
- package/dist/core/interfaces/instance/index.d.ts +2 -0
- package/dist/core/interfaces/instance/index.js +2 -0
- package/dist/core/interfaces/noop-implementations.d.ts +53 -0
- package/dist/core/interfaces/noop-implementations.js +62 -0
- package/dist/core/interfaces/transport/i-transport-client.d.ts +97 -0
- package/dist/core/interfaces/transport/i-transport-client.js +1 -0
- package/dist/core/interfaces/transport/i-transport-server.d.ts +93 -0
- package/dist/core/interfaces/transport/i-transport-server.js +1 -0
- package/dist/core/interfaces/transport/index.d.ts +2 -0
- package/dist/core/interfaces/transport/index.js +2 -0
- package/dist/hooks/init/welcome.js +9 -24
- package/dist/infra/cipher/agent/agent-error-codes.d.ts +16 -0
- package/dist/infra/cipher/agent/agent-error-codes.js +17 -0
- package/dist/infra/cipher/agent/agent-error.d.ts +54 -0
- package/dist/infra/cipher/agent/agent-error.js +79 -0
- package/dist/infra/cipher/agent/agent-schemas.d.ts +264 -0
- package/dist/infra/cipher/agent/agent-schemas.js +97 -0
- package/dist/infra/cipher/agent/agent-state-manager.d.ts +140 -0
- package/dist/infra/cipher/agent/agent-state-manager.js +275 -0
- package/dist/infra/cipher/agent/base-agent.d.ts +118 -0
- package/dist/infra/cipher/agent/base-agent.js +240 -0
- package/dist/infra/cipher/agent/cipher-agent.d.ts +165 -0
- package/dist/infra/cipher/agent/cipher-agent.js +546 -0
- package/dist/infra/cipher/agent/index.d.ts +22 -0
- package/dist/infra/cipher/agent/index.js +24 -0
- package/dist/infra/cipher/agent/service-initializer.d.ts +79 -0
- package/dist/infra/cipher/{agent-service-factory.js → agent/service-initializer.js} +117 -68
- package/dist/infra/cipher/agent/types.d.ts +35 -0
- package/dist/infra/cipher/agent/types.js +1 -0
- package/dist/infra/cipher/blob/blob-reference-resolver.d.ts +107 -0
- package/dist/infra/cipher/blob/blob-reference-resolver.js +228 -0
- package/dist/infra/cipher/blob/blob-reference-utils.d.ts +117 -0
- package/dist/infra/cipher/blob/blob-reference-utils.js +230 -0
- package/dist/infra/cipher/consumer/consumer-lock.js +1 -0
- package/dist/infra/cipher/consumer/consumer-service.js +1 -0
- package/dist/infra/cipher/consumer/execution-consumer.d.ts +6 -1
- package/dist/infra/cipher/consumer/execution-consumer.js +54 -16
- package/dist/infra/cipher/consumer/index.d.ts +1 -1
- package/dist/infra/cipher/consumer/index.js +2 -1
- package/dist/infra/cipher/consumer/queue-polling-service.js +1 -0
- package/dist/infra/cipher/file-system/binary-utils.d.ts +43 -0
- package/dist/infra/cipher/file-system/binary-utils.js +164 -0
- package/dist/infra/cipher/file-system/context-tree-file-system-factory.d.ts +9 -0
- package/dist/infra/cipher/file-system/context-tree-file-system-factory.js +24 -0
- package/dist/infra/cipher/file-system/file-system-service.d.ts +17 -1
- package/dist/infra/cipher/file-system/file-system-service.js +327 -36
- package/dist/infra/cipher/file-system/path-validator.d.ts +32 -0
- package/dist/infra/cipher/file-system/path-validator.js +111 -6
- package/dist/infra/cipher/interactive-loop.js +41 -33
- package/dist/infra/cipher/llm/capability-cache.d.ts +87 -0
- package/dist/infra/cipher/llm/capability-cache.js +125 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.d.ts +32 -0
- package/dist/infra/cipher/llm/context/compaction/compaction-service.js +44 -3
- package/dist/infra/cipher/llm/context/compression/enhanced-compaction.d.ts +112 -0
- package/dist/infra/cipher/llm/context/compression/enhanced-compaction.js +175 -0
- package/dist/infra/cipher/llm/context/compression/filter-compacted.d.ts +83 -0
- package/dist/infra/cipher/llm/context/compression/filter-compacted.js +150 -0
- package/dist/infra/cipher/llm/context/compression/index.d.ts +5 -0
- package/dist/infra/cipher/llm/context/compression/index.js +6 -0
- package/dist/infra/cipher/llm/context/compression/reactive-overflow.d.ts +107 -0
- package/dist/infra/cipher/llm/context/compression/reactive-overflow.js +272 -0
- package/dist/infra/cipher/llm/context/context-manager.d.ts +47 -1
- package/dist/infra/cipher/llm/context/context-manager.js +129 -0
- package/dist/infra/cipher/llm/context/utils.js +17 -4
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +4 -2
- package/dist/infra/cipher/llm/internal-llm-service.d.ts +50 -17
- package/dist/infra/cipher/llm/internal-llm-service.js +273 -50
- package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +6 -8
- package/dist/infra/cipher/llm/openrouter-llm-service.js +14 -16
- package/dist/infra/cipher/llm/retry/retry-policy.d.ts +1 -0
- package/dist/infra/cipher/llm/retry/retry-policy.js +11 -0
- package/dist/infra/cipher/llm/retry/retry-with-backoff.js +3 -2
- package/dist/infra/cipher/llm/sanitization/base64-utils.d.ts +102 -0
- package/dist/infra/cipher/llm/sanitization/base64-utils.js +182 -0
- package/dist/infra/cipher/llm/sanitization/index.d.ts +12 -0
- package/dist/infra/cipher/llm/sanitization/index.js +13 -0
- package/dist/infra/cipher/llm/sanitization/tool-sanitizer.d.ts +74 -0
- package/dist/infra/cipher/llm/sanitization/tool-sanitizer.js +398 -0
- package/dist/infra/cipher/llm/stream-processor.d.ts +158 -0
- package/dist/infra/cipher/llm/stream-processor.js +276 -0
- package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.d.ts +13 -20
- package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.js +17 -24
- package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.d.ts +12 -11
- package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.js +16 -15
- package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.d.ts +15 -7
- package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.js +22 -10
- package/dist/infra/cipher/llm/tool-output-processor.d.ts +51 -0
- package/dist/infra/cipher/llm/tool-output-processor.js +139 -0
- package/dist/infra/cipher/process/command-validator.d.ts +23 -0
- package/dist/infra/cipher/process/command-validator.js +75 -0
- package/dist/infra/cipher/process/path-utils.d.ts +66 -0
- package/dist/infra/cipher/process/path-utils.js +94 -0
- package/dist/infra/cipher/process/process-service.d.ts +32 -0
- package/dist/infra/cipher/process/process-service.js +98 -17
- package/dist/infra/cipher/session/chat-session.d.ts +56 -7
- package/dist/infra/cipher/session/chat-session.js +163 -13
- package/dist/infra/cipher/session/index.d.ts +1 -0
- package/dist/infra/cipher/session/index.js +2 -0
- package/dist/infra/cipher/session/message-queue.d.ts +65 -0
- package/dist/infra/cipher/session/message-queue.js +90 -0
- package/dist/infra/cipher/session/session-manager.d.ts +106 -5
- package/dist/infra/cipher/session/session-manager.js +254 -7
- package/dist/infra/cipher/session/session-status.d.ts +137 -0
- package/dist/infra/cipher/session/session-status.js +184 -0
- package/dist/infra/cipher/session/title-generator.d.ts +8 -0
- package/dist/infra/cipher/session/title-generator.js +31 -0
- package/dist/infra/cipher/storage/message-storage-service.d.ts +65 -2
- package/dist/infra/cipher/storage/message-storage-service.js +300 -54
- package/dist/infra/cipher/storage/tool-part-factory.d.ts +116 -0
- package/dist/infra/cipher/storage/tool-part-factory.js +197 -0
- package/dist/infra/cipher/system-prompt/contributor-schemas.d.ts +516 -0
- package/dist/infra/cipher/system-prompt/contributor-schemas.js +85 -0
- package/dist/infra/cipher/system-prompt/contributors/agent-prompt-contributor.d.ts +59 -0
- package/dist/infra/cipher/system-prompt/contributors/agent-prompt-contributor.js +131 -0
- package/dist/infra/cipher/system-prompt/contributors/companion-contributor.d.ts +54 -0
- package/dist/infra/cipher/system-prompt/contributors/companion-contributor.js +107 -0
- package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.d.ts +68 -0
- package/dist/infra/cipher/system-prompt/contributors/context-tree-structure-contributor.js +179 -0
- package/dist/infra/cipher/system-prompt/contributors/datetime-contributor.d.ts +25 -0
- package/dist/infra/cipher/system-prompt/contributors/datetime-contributor.js +29 -0
- package/dist/infra/cipher/system-prompt/contributors/environment-contributor.d.ts +25 -0
- package/dist/infra/cipher/system-prompt/contributors/environment-contributor.js +54 -0
- package/dist/infra/cipher/system-prompt/contributors/file-contributor.d.ts +60 -0
- package/dist/infra/cipher/system-prompt/contributors/file-contributor.js +128 -0
- package/dist/infra/cipher/system-prompt/contributors/index.d.ts +13 -0
- package/dist/infra/cipher/system-prompt/contributors/index.js +8 -0
- package/dist/infra/cipher/system-prompt/contributors/memory-contributor.d.ts +40 -0
- package/dist/infra/cipher/system-prompt/contributors/memory-contributor.js +56 -0
- package/dist/infra/cipher/system-prompt/contributors/static-contributor.d.ts +26 -0
- package/dist/infra/cipher/system-prompt/contributors/static-contributor.js +31 -0
- package/dist/infra/cipher/system-prompt/environment-context-builder.d.ts +112 -0
- package/dist/infra/cipher/system-prompt/environment-context-builder.js +256 -0
- package/dist/infra/cipher/system-prompt/prompt-cache.d.ts +102 -0
- package/dist/infra/cipher/system-prompt/prompt-cache.js +156 -0
- package/dist/infra/cipher/system-prompt/schemas.d.ts +151 -0
- package/dist/infra/cipher/system-prompt/schemas.js +94 -0
- package/dist/infra/cipher/system-prompt/system-prompt-manager.d.ts +136 -0
- package/dist/infra/cipher/system-prompt/system-prompt-manager.js +307 -0
- package/dist/infra/cipher/todos/todo-storage-service.d.ts +26 -0
- package/dist/infra/cipher/todos/todo-storage-service.js +28 -0
- package/dist/infra/cipher/tools/core-tool-scheduler.js +5 -1
- package/dist/infra/cipher/tools/default-policy-rules.js +1 -1
- package/dist/infra/cipher/tools/implementations/bash-exec-tool.d.ts +1 -0
- package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +27 -10
- package/dist/infra/cipher/tools/implementations/bash-output-tool.js +1 -5
- package/dist/infra/cipher/tools/implementations/batch-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/batch-tool.js +142 -0
- package/dist/infra/cipher/tools/implementations/curate-tool.js +195 -68
- package/dist/infra/cipher/tools/implementations/list-directory-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/list-directory-tool.js +52 -0
- package/dist/infra/cipher/tools/implementations/read-file-tool.d.ts +8 -1
- package/dist/infra/cipher/tools/implementations/read-file-tool.js +17 -7
- package/dist/infra/cipher/tools/implementations/read-todos-tool.d.ts +11 -0
- package/dist/infra/cipher/tools/implementations/read-todos-tool.js +39 -0
- package/dist/infra/cipher/tools/implementations/{detect-domains-tool.d.ts → spec-analyze-tool.d.ts} +1 -1
- package/dist/infra/cipher/tools/implementations/{detect-domains-tool.js → spec-analyze-tool.js} +9 -7
- package/dist/infra/cipher/tools/implementations/task-tool.d.ts +34 -0
- package/dist/infra/cipher/tools/implementations/task-tool.js +207 -0
- package/dist/infra/cipher/tools/implementations/write-todos-tool.d.ts +4 -1
- package/dist/infra/cipher/tools/implementations/write-todos-tool.js +19 -63
- package/dist/infra/cipher/tools/index.d.ts +1 -1
- package/dist/infra/cipher/tools/index.js +1 -1
- package/dist/infra/cipher/tools/plugins/index.d.ts +3 -0
- package/dist/infra/cipher/tools/plugins/index.js +2 -0
- package/dist/infra/cipher/tools/plugins/logging-plugin.d.ts +28 -0
- package/dist/infra/cipher/tools/plugins/logging-plugin.js +66 -0
- package/dist/infra/cipher/tools/plugins/plugin-manager.d.ts +81 -0
- package/dist/infra/cipher/tools/plugins/plugin-manager.js +122 -0
- package/dist/infra/cipher/tools/streaming/index.d.ts +1 -0
- package/dist/infra/cipher/tools/streaming/index.js +1 -0
- package/dist/infra/cipher/tools/streaming/metadata-handler.d.ts +31 -0
- package/dist/infra/cipher/tools/streaming/metadata-handler.js +39 -0
- package/dist/infra/cipher/tools/tool-description-loader.d.ts +57 -0
- package/dist/infra/cipher/tools/tool-description-loader.js +108 -0
- package/dist/infra/cipher/tools/tool-manager.d.ts +38 -4
- package/dist/infra/cipher/tools/tool-manager.js +107 -11
- package/dist/infra/cipher/tools/tool-provider-getter.d.ts +6 -0
- package/dist/infra/cipher/tools/tool-provider-getter.js +1 -0
- package/dist/infra/cipher/tools/tool-provider.d.ts +32 -7
- package/dist/infra/cipher/tools/tool-provider.js +81 -25
- package/dist/infra/cipher/tools/tool-registry.d.ts +23 -0
- package/dist/infra/cipher/tools/tool-registry.js +58 -16
- package/dist/infra/context-tree/file-context-tree-snapshot-service.js +10 -4
- package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +4 -3
- package/dist/infra/context-tree/file-context-tree-writer-service.js +6 -4
- package/dist/infra/context-tree/path-utils.d.ts +7 -0
- package/dist/infra/context-tree/path-utils.js +7 -0
- package/dist/infra/core/executors/curate-executor.d.ts +35 -0
- package/dist/infra/core/executors/curate-executor.js +123 -0
- package/dist/infra/core/executors/index.d.ts +2 -0
- package/dist/infra/core/executors/index.js +2 -0
- package/dist/infra/core/executors/query-executor.d.ts +23 -0
- package/dist/infra/core/executors/query-executor.js +51 -0
- package/dist/infra/core/task-processor.d.ts +81 -0
- package/dist/infra/core/task-processor.js +115 -0
- package/dist/infra/instance/file-instance-discovery.d.ts +31 -0
- package/dist/infra/instance/file-instance-discovery.js +84 -0
- package/dist/infra/instance/file-instance-manager.d.ts +46 -0
- package/dist/infra/instance/file-instance-manager.js +123 -0
- package/dist/infra/instance/index.d.ts +3 -0
- package/dist/infra/instance/index.js +3 -0
- package/dist/infra/instance/process-utils.d.ts +14 -0
- package/dist/infra/instance/process-utils.js +39 -0
- package/dist/infra/process/agent-worker.d.ts +20 -0
- package/dist/infra/process/agent-worker.js +602 -0
- package/dist/infra/process/index.d.ts +12 -0
- package/dist/infra/process/index.js +11 -0
- package/dist/infra/process/ipc-types.d.ts +55 -0
- package/dist/infra/process/ipc-types.js +12 -0
- package/dist/infra/process/process-manager.d.ts +154 -0
- package/dist/infra/process/process-manager.js +471 -0
- package/dist/infra/process/task-queue-manager.d.ts +123 -0
- package/dist/infra/process/task-queue-manager.js +226 -0
- package/dist/infra/process/transport-handlers.d.ts +124 -0
- package/dist/infra/process/transport-handlers.js +348 -0
- package/dist/infra/process/transport-worker.d.ts +20 -0
- package/dist/infra/process/transport-worker.js +168 -0
- package/dist/infra/repl/commands/curate-command.js +0 -5
- package/dist/infra/repl/commands/query-command.js +0 -3
- package/dist/infra/repl/repl-startup.d.ts +4 -0
- package/dist/infra/repl/repl-startup.js +10 -1
- package/dist/infra/repl/transport-client-helper.d.ts +9 -0
- package/dist/infra/repl/transport-client-helper.js +96 -0
- package/dist/infra/transport/index.d.ts +4 -0
- package/dist/infra/transport/index.js +4 -0
- package/dist/infra/transport/port-utils.d.ts +42 -0
- package/dist/infra/transport/port-utils.js +84 -0
- package/dist/infra/transport/socket-io-transport-client.d.ts +45 -0
- package/dist/infra/transport/socket-io-transport-client.js +270 -0
- package/dist/infra/transport/socket-io-transport-server.d.ts +35 -0
- package/dist/infra/transport/socket-io-transport-server.js +207 -0
- package/dist/infra/transport/transport-client-factory.d.ts +76 -0
- package/dist/infra/transport/transport-client-factory.js +168 -0
- package/dist/infra/transport/transport-factory.d.ts +33 -0
- package/dist/infra/transport/transport-factory.js +59 -0
- package/dist/infra/usecase/curate-use-case.d.ts +8 -55
- package/dist/infra/usecase/curate-use-case.js +73 -259
- package/dist/infra/usecase/init-use-case.js +19 -8
- package/dist/infra/usecase/login-use-case.js +9 -3
- package/dist/infra/usecase/query-use-case.d.ts +18 -45
- package/dist/infra/usecase/query-use-case.js +251 -326
- package/dist/infra/usecase/status-use-case.js +1 -1
- package/dist/resources/prompts/{curate-context-tree-curation.yml → curate.yml} +25 -22
- package/dist/resources/prompts/explore.yml +78 -0
- package/dist/resources/prompts/plan.yml +114 -0
- package/dist/resources/prompts/reflection.yml +1 -1
- package/dist/resources/prompts/system-prompt.yml +15 -8
- package/dist/resources/prompts/tool-outputs.yml +0 -5
- package/dist/resources/tools/bash_exec.txt +98 -0
- package/dist/resources/tools/bash_output.txt +40 -0
- package/dist/resources/tools/batch.txt +28 -0
- package/dist/resources/tools/create_knowledge_topic.txt +23 -0
- package/dist/resources/tools/curate.txt +22 -0
- package/dist/resources/tools/delete_memory.txt +1 -0
- package/dist/resources/tools/detect_domains.txt +11 -0
- package/dist/resources/tools/edit_file.txt +1 -0
- package/dist/resources/tools/edit_memory.txt +1 -0
- package/dist/resources/tools/glob_files.txt +20 -0
- package/dist/resources/tools/grep_content.txt +18 -0
- package/dist/resources/tools/kill_process.txt +16 -0
- package/dist/resources/tools/list_directory.txt +16 -0
- package/dist/resources/tools/list_memories.txt +1 -0
- package/dist/resources/tools/read_file.txt +31 -0
- package/dist/resources/tools/read_memory.txt +1 -0
- package/dist/resources/tools/read_todos.txt +17 -0
- package/dist/resources/tools/search_history.txt +1 -0
- package/dist/resources/tools/task.txt +23 -0
- package/dist/resources/tools/write_file.txt +1 -0
- package/dist/resources/tools/write_memory.txt +1 -0
- package/dist/resources/tools/write_todos.txt +29 -0
- package/dist/tui/app.js +9 -13
- package/dist/tui/components/command-details.d.ts +14 -0
- package/dist/tui/components/command-details.js +35 -0
- package/dist/tui/components/execution/execution-changes.d.ts +5 -0
- package/dist/tui/components/execution/execution-changes.js +19 -4
- package/dist/tui/components/execution/execution-content.d.ts +4 -2
- package/dist/tui/components/execution/execution-content.js +26 -13
- package/dist/tui/components/execution/execution-input.js +3 -3
- package/dist/tui/components/execution/execution-progress.d.ts +2 -2
- package/dist/tui/components/execution/execution-progress.js +8 -6
- package/dist/tui/components/execution/log-item.d.ts +3 -4
- package/dist/tui/components/execution/log-item.js +2 -5
- package/dist/tui/components/footer.js +9 -4
- package/dist/tui/components/header.d.ts +3 -3
- package/dist/tui/components/header.js +5 -3
- package/dist/tui/components/index.d.ts +1 -0
- package/dist/tui/components/index.js +1 -0
- package/dist/tui/components/onboarding/copyable-prompt.d.ts +5 -3
- package/dist/tui/components/onboarding/copyable-prompt.js +7 -8
- package/dist/tui/components/onboarding/onboarding-flow.js +35 -25
- package/dist/tui/components/scrollable-list.js +12 -10
- package/dist/tui/components/suggestions.js +39 -41
- package/dist/tui/components/tab-bar.d.ts +2 -1
- package/dist/tui/components/tab-bar.js +3 -4
- package/dist/tui/constants.d.ts +0 -5
- package/dist/tui/constants.js +0 -5
- package/dist/tui/contexts/auth-context.js +9 -2
- package/dist/tui/contexts/{use-commands.js → commands-context.js} +6 -5
- package/dist/tui/contexts/index.d.ts +6 -1
- package/dist/tui/contexts/index.js +6 -1
- package/dist/tui/contexts/onboarding-context.d.ts +1 -1
- package/dist/tui/contexts/onboarding-context.js +9 -9
- package/dist/tui/contexts/tasks-context.d.ts +84 -0
- package/dist/tui/contexts/tasks-context.js +218 -0
- package/dist/tui/contexts/transport-context.d.ts +29 -0
- package/dist/tui/contexts/transport-context.js +82 -0
- package/dist/tui/hooks/index.d.ts +10 -6
- package/dist/tui/hooks/index.js +7 -6
- package/dist/tui/hooks/use-activity-logs.d.ts +3 -11
- package/dist/tui/hooks/use-activity-logs.js +87 -34
- package/dist/tui/hooks/use-auth-polling.d.ts +24 -0
- package/dist/tui/hooks/use-auth-polling.js +104 -0
- package/dist/tui/hooks/use-slash-command-processor.js +0 -1
- package/dist/tui/hooks/use-slash-completion.js +1 -1
- package/dist/tui/hooks/use-tab-navigation.d.ts +2 -1
- package/dist/tui/hooks/use-tab-navigation.js +16 -7
- package/dist/tui/hooks/use-terminal-breakpoint.d.ts +21 -0
- package/dist/tui/hooks/use-terminal-breakpoint.js +38 -0
- package/dist/tui/hooks/use-ui-heights.d.ts +120 -0
- package/dist/tui/hooks/use-ui-heights.js +88 -0
- package/dist/tui/providers/app-providers.js +2 -6
- package/dist/tui/types/commands.d.ts +0 -26
- package/dist/tui/types/index.d.ts +1 -1
- package/dist/tui/types/ui.d.ts +9 -4
- package/dist/tui/utils/line.d.ts +11 -0
- package/dist/tui/utils/line.js +16 -0
- package/dist/tui/utils/log.d.ts +27 -0
- package/dist/tui/utils/log.js +114 -0
- package/dist/tui/views/command-view.d.ts +7 -0
- package/dist/tui/views/command-view.js +103 -80
- package/dist/tui/views/login-view.js +7 -4
- package/dist/tui/views/logs-view.d.ts +13 -0
- package/dist/tui/views/logs-view.js +27 -52
- package/dist/utils/connection-error-handler.d.ts +16 -0
- package/dist/utils/connection-error-handler.js +49 -0
- package/dist/utils/crash-log.d.ts +14 -0
- package/dist/utils/crash-log.js +19 -0
- package/dist/utils/file-helpers.d.ts +14 -0
- package/dist/utils/file-helpers.js +21 -0
- package/dist/utils/global-logs-path.d.ts +11 -0
- package/dist/utils/global-logs-path.js +37 -0
- package/dist/utils/process-logger.d.ts +53 -0
- package/dist/utils/process-logger.js +253 -0
- package/dist/utils/sandbox-detector.d.ts +31 -0
- package/dist/utils/sandbox-detector.js +122 -0
- package/oclif.manifest.json +10 -198
- package/package.json +5 -1
- package/dist/commands/cipher-agent/run.d.ts +0 -142
- package/dist/commands/cipher-agent/run.js +0 -555
- package/dist/commands/cipher-agent/set-prompt.d.ts +0 -16
- package/dist/commands/cipher-agent/set-prompt.js +0 -58
- package/dist/commands/cipher-agent/show-prompt.d.ts +0 -13
- package/dist/commands/cipher-agent/show-prompt.js +0 -53
- package/dist/commands/foo.d.ts +0 -14
- package/dist/commands/foo.js +0 -66
- package/dist/infra/cipher/agent-service-factory.d.ts +0 -93
- package/dist/infra/cipher/cipher-agent-state-manager.d.ts +0 -63
- package/dist/infra/cipher/cipher-agent-state-manager.js +0 -108
- package/dist/infra/cipher/cipher-agent.d.ts +0 -182
- package/dist/infra/cipher/cipher-agent.js +0 -317
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +0 -106
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +0 -297
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.d.ts +0 -7
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +0 -424
- package/dist/resources/prompts/modes/autonomous.yml +0 -9
- package/dist/resources/prompts/query-context-tree-retrieval.yml +0 -48
- package/dist/tui/contexts/consumer.d.ts +0 -31
- package/dist/tui/contexts/consumer.js +0 -56
- package/dist/tui/hooks/use-consumer.d.ts +0 -12
- package/dist/tui/hooks/use-consumer.js +0 -50
- package/dist/tui/hooks/use-queue-polling.d.ts +0 -31
- package/dist/tui/hooks/use-queue-polling.js +0 -90
- /package/dist/tui/contexts/{use-commands.d.ts → commands-context.d.ts} +0 -0
- /package/dist/tui/contexts/{use-mode.d.ts → mode-context.d.ts} +0 -0
- /package/dist/tui/contexts/{use-mode.js → mode-context.js} +0 -0
- /package/dist/tui/contexts/{use-theme.d.ts → theme-context.d.ts} +0 -0
- /package/dist/tui/contexts/{use-theme.js → theme-context.js} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport Client Helper for TUI (v0.5.0 architecture).
|
|
3
|
+
*
|
|
4
|
+
* TODO(v0.5.0): This is a temporary helper for TUI team to monitor events.
|
|
5
|
+
* Remove when TUI fully integrates with Transport via React context.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { isDevelopment } from '../../config/environment.js';
|
|
10
|
+
import { BRV_DIR } from '../../constants.js';
|
|
11
|
+
import { TransportAgentEventNames, TransportLlmEventList, TransportSessionEventNames, TransportTaskEventNames, } from '../../core/domain/transport/schemas.js';
|
|
12
|
+
import { createTransportClientFactory } from '../transport/transport-client-factory.js';
|
|
13
|
+
const TRANSPORT_LOG_FILE = path.join(BRV_DIR, 'transport-events.log');
|
|
14
|
+
/**
|
|
15
|
+
* Transport events that TUI subscribes to via "broadcast-room".
|
|
16
|
+
*
|
|
17
|
+
* Event naming convention:
|
|
18
|
+
* - task:* events are Transport-generated (lifecycle)
|
|
19
|
+
* - llmservice:* events are forwarded from Agent with ORIGINAL names
|
|
20
|
+
*
|
|
21
|
+
* This means FE receives the SAME event names that Agent emits internally.
|
|
22
|
+
* No mapping needed - what you see is what Agent does.
|
|
23
|
+
*/
|
|
24
|
+
const TRANSPORT_EVENTS = [
|
|
25
|
+
// Task lifecycle (Transport-generated) - using constants from schemas
|
|
26
|
+
TransportTaskEventNames.ACK,
|
|
27
|
+
TransportTaskEventNames.CREATED,
|
|
28
|
+
TransportTaskEventNames.STARTED,
|
|
29
|
+
TransportTaskEventNames.COMPLETED,
|
|
30
|
+
TransportTaskEventNames.ERROR,
|
|
31
|
+
TransportTaskEventNames.CANCELLED,
|
|
32
|
+
// LLM events (using constants from schemas)
|
|
33
|
+
...TransportLlmEventList,
|
|
34
|
+
// Connection events (internal)
|
|
35
|
+
TransportAgentEventNames.CONNECTED,
|
|
36
|
+
TransportAgentEventNames.DISCONNECTED,
|
|
37
|
+
TransportSessionEventNames.SWITCHED,
|
|
38
|
+
// Agent control events
|
|
39
|
+
TransportAgentEventNames.RESTARTING,
|
|
40
|
+
TransportAgentEventNames.RESTARTED,
|
|
41
|
+
];
|
|
42
|
+
function formatTimestamp() {
|
|
43
|
+
return new Date().toISOString();
|
|
44
|
+
}
|
|
45
|
+
function logEvent(eventName, data) {
|
|
46
|
+
if (!isDevelopment())
|
|
47
|
+
return;
|
|
48
|
+
const line = JSON.stringify({ data, event: eventName, timestamp: formatTimestamp() }, null, 2) + '\n';
|
|
49
|
+
try {
|
|
50
|
+
fs.appendFileSync(TRANSPORT_LOG_FILE, line);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Ignore
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Connect to Transport and join TUI room for event monitoring.
|
|
58
|
+
*/
|
|
59
|
+
export async function connectTransportClient() {
|
|
60
|
+
if (isDevelopment()) {
|
|
61
|
+
try {
|
|
62
|
+
fs.writeFileSync(TRANSPORT_LOG_FILE, `# Transport Events - ${formatTimestamp()}\n`);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Ignore
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const factory = createTransportClientFactory();
|
|
70
|
+
const { client } = await factory.connect();
|
|
71
|
+
client.onStateChange((state) => {
|
|
72
|
+
logEvent('_connection', { clientId: client.getClientId(), state });
|
|
73
|
+
});
|
|
74
|
+
for (const event of TRANSPORT_EVENTS) {
|
|
75
|
+
client.on(event, (data) => logEvent(event, data));
|
|
76
|
+
}
|
|
77
|
+
logEvent('_connection', { clientId: client.getClientId(), state: 'initialized' });
|
|
78
|
+
await client.joinRoom('broadcast-room');
|
|
79
|
+
logEvent('_room', { room: 'broadcast-room', state: 'joined' });
|
|
80
|
+
return client;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
84
|
+
logEvent('_connection', { error: msg, state: 'failed' });
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Disconnect transport client.
|
|
90
|
+
*/
|
|
91
|
+
export async function disconnectTransportClient(client) {
|
|
92
|
+
if (client) {
|
|
93
|
+
logEvent('_connection', { state: 'closing' });
|
|
94
|
+
await client.disconnect();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if a port is available for binding.
|
|
3
|
+
*
|
|
4
|
+
* @param port - The port number to check
|
|
5
|
+
* @returns Promise resolving to true if available, false otherwise
|
|
6
|
+
*/
|
|
7
|
+
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
8
|
+
/**
|
|
9
|
+
* Generates a random port within the safe range.
|
|
10
|
+
*
|
|
11
|
+
* @returns A random port number between PORT_RANGE_MIN and PORT_RANGE_MAX
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRandomPort(): number;
|
|
14
|
+
/**
|
|
15
|
+
* Finds an available port for the transport server.
|
|
16
|
+
*
|
|
17
|
+
* Uses a random selection strategy within the safe port range (49152-60000)
|
|
18
|
+
* to avoid conflicts with:
|
|
19
|
+
* - Well-known ports (0-1023): HTTP, HTTPS, SSH, etc.
|
|
20
|
+
* - Common dev ports: 3000, 5000, 8080, etc.
|
|
21
|
+
* - Database ports: 3306, 5432, 27017, 6379, etc.
|
|
22
|
+
*
|
|
23
|
+
* @returns Promise resolving to an available port number
|
|
24
|
+
* @throws Error if no available port found after MAX_PORT_ATTEMPTS
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* const port = await findAvailablePort();
|
|
28
|
+
* await server.start(port);
|
|
29
|
+
*/
|
|
30
|
+
export declare function findAvailablePort(): Promise<number>;
|
|
31
|
+
/**
|
|
32
|
+
* Finds an available port, starting from a preferred port.
|
|
33
|
+
* If the preferred port is not available, falls back to random selection.
|
|
34
|
+
*
|
|
35
|
+
* @param preferredPort - The preferred port to try first
|
|
36
|
+
* @returns Promise resolving to an available port number
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Try 9847 first, fallback to random if unavailable
|
|
40
|
+
* const port = await findAvailablePortWithPreference(9847);
|
|
41
|
+
*/
|
|
42
|
+
export declare function findAvailablePortWithPreference(preferredPort: number): Promise<number>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { createServer } from 'node:net';
|
|
2
|
+
import { TRANSPORT_HOST } from '../../constants.js';
|
|
3
|
+
/**
|
|
4
|
+
* Port range for transport server.
|
|
5
|
+
* Using high ports (49152-65535) which are "dynamic/private" per IANA.
|
|
6
|
+
* We use a subset to avoid potential conflicts.
|
|
7
|
+
*/
|
|
8
|
+
const PORT_RANGE_MIN = 49_152;
|
|
9
|
+
const PORT_RANGE_MAX = 60_000;
|
|
10
|
+
/**
|
|
11
|
+
* Maximum attempts to find an available port.
|
|
12
|
+
*/
|
|
13
|
+
const MAX_PORT_ATTEMPTS = 20;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if a port is available for binding.
|
|
16
|
+
*
|
|
17
|
+
* @param port - The port number to check
|
|
18
|
+
* @returns Promise resolving to true if available, false otherwise
|
|
19
|
+
*/
|
|
20
|
+
export function isPortAvailable(port) {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const server = createServer();
|
|
23
|
+
server.once('error', () => {
|
|
24
|
+
resolve(false);
|
|
25
|
+
});
|
|
26
|
+
server.once('listening', () => {
|
|
27
|
+
server.close(() => {
|
|
28
|
+
resolve(true);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
server.listen(port, TRANSPORT_HOST);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generates a random port within the safe range.
|
|
36
|
+
*
|
|
37
|
+
* @returns A random port number between PORT_RANGE_MIN and PORT_RANGE_MAX
|
|
38
|
+
*/
|
|
39
|
+
export function getRandomPort() {
|
|
40
|
+
return Math.floor(Math.random() * (PORT_RANGE_MAX - PORT_RANGE_MIN + 1)) + PORT_RANGE_MIN;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Finds an available port for the transport server.
|
|
44
|
+
*
|
|
45
|
+
* Uses a random selection strategy within the safe port range (49152-60000)
|
|
46
|
+
* to avoid conflicts with:
|
|
47
|
+
* - Well-known ports (0-1023): HTTP, HTTPS, SSH, etc.
|
|
48
|
+
* - Common dev ports: 3000, 5000, 8080, etc.
|
|
49
|
+
* - Database ports: 3306, 5432, 27017, 6379, etc.
|
|
50
|
+
*
|
|
51
|
+
* @returns Promise resolving to an available port number
|
|
52
|
+
* @throws Error if no available port found after MAX_PORT_ATTEMPTS
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const port = await findAvailablePort();
|
|
56
|
+
* await server.start(port);
|
|
57
|
+
*/
|
|
58
|
+
export async function findAvailablePort() {
|
|
59
|
+
for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt++) {
|
|
60
|
+
const port = getRandomPort();
|
|
61
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential check is intentional: find first available port
|
|
62
|
+
if (await isPortAvailable(port)) {
|
|
63
|
+
return port;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw new Error(`Failed to find available port after ${MAX_PORT_ATTEMPTS} attempts in range ${PORT_RANGE_MIN}-${PORT_RANGE_MAX}`);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Finds an available port, starting from a preferred port.
|
|
70
|
+
* If the preferred port is not available, falls back to random selection.
|
|
71
|
+
*
|
|
72
|
+
* @param preferredPort - The preferred port to try first
|
|
73
|
+
* @returns Promise resolving to an available port number
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* // Try 9847 first, fallback to random if unavailable
|
|
77
|
+
* const port = await findAvailablePortWithPreference(9847);
|
|
78
|
+
*/
|
|
79
|
+
export async function findAvailablePortWithPreference(preferredPort) {
|
|
80
|
+
if (await isPortAvailable(preferredPort)) {
|
|
81
|
+
return preferredPort;
|
|
82
|
+
}
|
|
83
|
+
return findAvailablePort();
|
|
84
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { TransportClientConfig } from '../../core/domain/transport/types.js';
|
|
2
|
+
import type { ConnectionState, ConnectionStateHandler, EventHandler, ITransportClient, RequestOptions } from '../../core/interfaces/transport/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Socket.IO implementation of ITransportClient.
|
|
5
|
+
*
|
|
6
|
+
* Architecture notes:
|
|
7
|
+
* - Auto-reconnects with exponential backoff
|
|
8
|
+
* - Request/response uses Socket.IO acknowledgements (callbacks)
|
|
9
|
+
* - Connection state is tracked and exposed via onStateChange
|
|
10
|
+
*/
|
|
11
|
+
export declare class SocketIOTransportClient implements ITransportClient {
|
|
12
|
+
private readonly config;
|
|
13
|
+
private eventHandlers;
|
|
14
|
+
/** Track which events have socket listeners registered (prevents duplicates on reconnect) */
|
|
15
|
+
private registeredSocketEvents;
|
|
16
|
+
private socket;
|
|
17
|
+
private state;
|
|
18
|
+
private stateHandlers;
|
|
19
|
+
constructor(config?: TransportClientConfig);
|
|
20
|
+
connect(url: string): Promise<void>;
|
|
21
|
+
disconnect(): Promise<void>;
|
|
22
|
+
getClientId(): string | undefined;
|
|
23
|
+
getState(): ConnectionState;
|
|
24
|
+
joinRoom(room: string): Promise<void>;
|
|
25
|
+
leaveRoom(room: string): Promise<void>;
|
|
26
|
+
on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
|
|
27
|
+
once<T = unknown>(event: string, handler: EventHandler<T>): void;
|
|
28
|
+
onStateChange(handler: ConnectionStateHandler): () => void;
|
|
29
|
+
request<TResponse = unknown, TRequest = unknown>(event: string, data?: TRequest, options?: RequestOptions): Promise<TResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Register all pending event handlers on the socket.
|
|
32
|
+
* Called after successful connection to handle handlers added before connect().
|
|
33
|
+
*/
|
|
34
|
+
private registerPendingEventHandlers;
|
|
35
|
+
/**
|
|
36
|
+
* Register a socket listener for an event if not already registered.
|
|
37
|
+
* Uses registeredSocketEvents set to prevent duplicates.
|
|
38
|
+
*/
|
|
39
|
+
private registerSocketEventIfNeeded;
|
|
40
|
+
/**
|
|
41
|
+
* Remove socket listener for an event and clear tracking.
|
|
42
|
+
*/
|
|
43
|
+
private removeSocketEventListener;
|
|
44
|
+
private setState;
|
|
45
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { io } from 'socket.io-client';
|
|
2
|
+
import { TRANSPORT_CONNECT_TIMEOUT_MS, TRANSPORT_DEFAULT_TRANSPORTS, TRANSPORT_RECONNECTION_ATTEMPTS, TRANSPORT_RECONNECTION_DELAY_MAX_MS, TRANSPORT_RECONNECTION_DELAY_MS, TRANSPORT_REQUEST_TIMEOUT_MS, TRANSPORT_ROOM_TIMEOUT_MS, } from '../../constants.js';
|
|
3
|
+
import { TransportConnectionError, TransportNotConnectedError, TransportRequestError, TransportRequestTimeoutError, TransportRoomError, TransportRoomTimeoutError, } from '../../core/domain/errors/transport-error.js';
|
|
4
|
+
/**
|
|
5
|
+
* Socket.IO implementation of ITransportClient.
|
|
6
|
+
*
|
|
7
|
+
* Architecture notes:
|
|
8
|
+
* - Auto-reconnects with exponential backoff
|
|
9
|
+
* - Request/response uses Socket.IO acknowledgements (callbacks)
|
|
10
|
+
* - Connection state is tracked and exposed via onStateChange
|
|
11
|
+
*/
|
|
12
|
+
export class SocketIOTransportClient {
|
|
13
|
+
config;
|
|
14
|
+
eventHandlers = new Map();
|
|
15
|
+
/** Track which events have socket listeners registered (prevents duplicates on reconnect) */
|
|
16
|
+
registeredSocketEvents = new Set();
|
|
17
|
+
socket;
|
|
18
|
+
state = 'disconnected';
|
|
19
|
+
stateHandlers = new Set();
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = {
|
|
22
|
+
connectTimeoutMs: config?.connectTimeoutMs ?? TRANSPORT_CONNECT_TIMEOUT_MS,
|
|
23
|
+
reconnectionAttempts: config?.reconnectionAttempts ?? TRANSPORT_RECONNECTION_ATTEMPTS,
|
|
24
|
+
reconnectionDelayMaxMs: config?.reconnectionDelayMaxMs ?? TRANSPORT_RECONNECTION_DELAY_MAX_MS,
|
|
25
|
+
reconnectionDelayMs: config?.reconnectionDelayMs ?? TRANSPORT_RECONNECTION_DELAY_MS,
|
|
26
|
+
requestTimeoutMs: config?.requestTimeoutMs ?? TRANSPORT_REQUEST_TIMEOUT_MS,
|
|
27
|
+
roomTimeoutMs: config?.roomTimeoutMs ?? TRANSPORT_ROOM_TIMEOUT_MS,
|
|
28
|
+
transports: config?.transports ?? TRANSPORT_DEFAULT_TRANSPORTS,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async connect(url) {
|
|
32
|
+
if (this.socket?.connected) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
this.setState('connecting');
|
|
37
|
+
this.socket = io(url, {
|
|
38
|
+
randomizationFactor: 0,
|
|
39
|
+
reconnection: true,
|
|
40
|
+
reconnectionAttempts: this.config.reconnectionAttempts,
|
|
41
|
+
reconnectionDelay: this.config.reconnectionDelayMs,
|
|
42
|
+
reconnectionDelayMax: this.config.reconnectionDelayMaxMs,
|
|
43
|
+
timeout: this.config.connectTimeoutMs,
|
|
44
|
+
// Use WebSocket-only by default to avoid HTTP polling issues in sandboxed environments
|
|
45
|
+
transports: this.config.transports,
|
|
46
|
+
});
|
|
47
|
+
const onConnect = () => {
|
|
48
|
+
this.setState('connected');
|
|
49
|
+
cleanup();
|
|
50
|
+
// Register any handlers that were added before connect() was called.
|
|
51
|
+
// This fixes the issue where on() called before connect() would not
|
|
52
|
+
// actually register handlers on the socket.
|
|
53
|
+
this.registerPendingEventHandlers();
|
|
54
|
+
resolve();
|
|
55
|
+
};
|
|
56
|
+
const onConnectError = (error) => {
|
|
57
|
+
this.setState('disconnected');
|
|
58
|
+
cleanup();
|
|
59
|
+
// Properly disconnect and cleanup socket to prevent leaks.
|
|
60
|
+
// Without this, the socket continues attempting reconnection
|
|
61
|
+
// even after we reject the promise.
|
|
62
|
+
if (this.socket) {
|
|
63
|
+
this.socket.removeAllListeners();
|
|
64
|
+
this.socket.io.removeAllListeners();
|
|
65
|
+
this.socket.disconnect();
|
|
66
|
+
this.socket = undefined;
|
|
67
|
+
}
|
|
68
|
+
reject(new TransportConnectionError(url, error));
|
|
69
|
+
};
|
|
70
|
+
const cleanup = () => {
|
|
71
|
+
this.socket?.off('connect', onConnect);
|
|
72
|
+
this.socket?.off('connect_error', onConnectError);
|
|
73
|
+
};
|
|
74
|
+
this.socket.on('connect', onConnect);
|
|
75
|
+
this.socket.once('connect_error', onConnectError);
|
|
76
|
+
// Set up persistent event handlers
|
|
77
|
+
this.socket.on('disconnect', () => {
|
|
78
|
+
if (this.socket?.active) {
|
|
79
|
+
// Socket.IO is attempting to reconnect
|
|
80
|
+
this.setState('reconnecting');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
this.setState('disconnected');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
this.socket.io.on('reconnect', () => {
|
|
87
|
+
this.setState('connected');
|
|
88
|
+
// Re-register event handlers after reconnect
|
|
89
|
+
// Clear tracking first since socket listeners were reset during reconnect
|
|
90
|
+
this.registeredSocketEvents.clear();
|
|
91
|
+
this.registerPendingEventHandlers();
|
|
92
|
+
});
|
|
93
|
+
this.socket.io.on('reconnect_failed', () => {
|
|
94
|
+
this.setState('disconnected');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async disconnect() {
|
|
99
|
+
const { socket } = this;
|
|
100
|
+
if (!socket) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
return new Promise((resolve) => {
|
|
104
|
+
// Remove all listeners to prevent memory leaks
|
|
105
|
+
socket.removeAllListeners();
|
|
106
|
+
socket.io.removeAllListeners();
|
|
107
|
+
socket.disconnect();
|
|
108
|
+
this.socket = undefined;
|
|
109
|
+
this.setState('disconnected');
|
|
110
|
+
// Clear all tracking state to prevent leaks
|
|
111
|
+
this.eventHandlers.clear();
|
|
112
|
+
this.registeredSocketEvents.clear();
|
|
113
|
+
this.stateHandlers.clear();
|
|
114
|
+
resolve();
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
getClientId() {
|
|
118
|
+
return this.socket?.id;
|
|
119
|
+
}
|
|
120
|
+
getState() {
|
|
121
|
+
return this.state;
|
|
122
|
+
}
|
|
123
|
+
async joinRoom(room) {
|
|
124
|
+
const { socket } = this;
|
|
125
|
+
if (!socket?.connected) {
|
|
126
|
+
throw new TransportNotConnectedError('joinRoom');
|
|
127
|
+
}
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
const timer = setTimeout(() => {
|
|
130
|
+
reject(new TransportRoomTimeoutError(room, 'join', this.config.roomTimeoutMs));
|
|
131
|
+
}, this.config.roomTimeoutMs);
|
|
132
|
+
socket.emit('room:join', room, (response) => {
|
|
133
|
+
clearTimeout(timer);
|
|
134
|
+
if (response.success) {
|
|
135
|
+
resolve();
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
reject(new TransportRoomError(room, 'join'));
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async leaveRoom(room) {
|
|
144
|
+
const { socket } = this;
|
|
145
|
+
if (!socket?.connected) {
|
|
146
|
+
throw new TransportNotConnectedError('leaveRoom');
|
|
147
|
+
}
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
const timer = setTimeout(() => {
|
|
150
|
+
reject(new TransportRoomTimeoutError(room, 'leave', this.config.roomTimeoutMs));
|
|
151
|
+
}, this.config.roomTimeoutMs);
|
|
152
|
+
socket.emit('room:leave', room, (response) => {
|
|
153
|
+
clearTimeout(timer);
|
|
154
|
+
if (response.success) {
|
|
155
|
+
resolve();
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
reject(new TransportRoomError(room, 'leave'));
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
on(event, handler) {
|
|
164
|
+
if (!this.eventHandlers.has(event)) {
|
|
165
|
+
this.eventHandlers.set(event, new Set());
|
|
166
|
+
}
|
|
167
|
+
// Register socket listener if connected and not already registered
|
|
168
|
+
// Use registeredSocketEvents to prevent duplicates across reconnects
|
|
169
|
+
this.registerSocketEventIfNeeded(event);
|
|
170
|
+
// Wrap handler to store without type assertion
|
|
171
|
+
const wrappedHandler = (data) => handler(data);
|
|
172
|
+
const handlers = this.eventHandlers.get(event);
|
|
173
|
+
handlers?.add(wrappedHandler);
|
|
174
|
+
// Return unsubscribe function that also cleans up socket listener if no handlers remain
|
|
175
|
+
return () => {
|
|
176
|
+
handlers?.delete(wrappedHandler);
|
|
177
|
+
// Clean up socket listener and map entry if no handlers remain
|
|
178
|
+
if (handlers && handlers.size === 0) {
|
|
179
|
+
this.eventHandlers.delete(event);
|
|
180
|
+
this.removeSocketEventListener(event);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
once(event, handler) {
|
|
185
|
+
const { socket } = this;
|
|
186
|
+
if (!socket) {
|
|
187
|
+
throw new TransportNotConnectedError('once');
|
|
188
|
+
}
|
|
189
|
+
socket.once(event, handler);
|
|
190
|
+
}
|
|
191
|
+
onStateChange(handler) {
|
|
192
|
+
this.stateHandlers.add(handler);
|
|
193
|
+
return () => {
|
|
194
|
+
this.stateHandlers.delete(handler);
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async request(event, data, options) {
|
|
198
|
+
const { socket } = this;
|
|
199
|
+
if (!socket?.connected) {
|
|
200
|
+
throw new TransportNotConnectedError('request');
|
|
201
|
+
}
|
|
202
|
+
const timeout = options?.timeout ?? this.config.requestTimeoutMs;
|
|
203
|
+
return new Promise((resolve, reject) => {
|
|
204
|
+
const timer = setTimeout(() => {
|
|
205
|
+
reject(new TransportRequestTimeoutError(event, timeout));
|
|
206
|
+
}, timeout);
|
|
207
|
+
socket.emit(event, data, (response) => {
|
|
208
|
+
clearTimeout(timer);
|
|
209
|
+
if (response.success && response.data !== undefined) {
|
|
210
|
+
resolve(response.data);
|
|
211
|
+
}
|
|
212
|
+
else if (response.success) {
|
|
213
|
+
// Response success but data is undefined - resolve with undefined cast
|
|
214
|
+
// This is a boundary case where server returns void
|
|
215
|
+
resolve(undefined);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
reject(new TransportRequestError(event, response.error));
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Register all pending event handlers on the socket.
|
|
225
|
+
* Called after successful connection to handle handlers added before connect().
|
|
226
|
+
*/
|
|
227
|
+
registerPendingEventHandlers() {
|
|
228
|
+
for (const event of this.eventHandlers.keys()) {
|
|
229
|
+
this.registerSocketEventIfNeeded(event);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Register a socket listener for an event if not already registered.
|
|
234
|
+
* Uses registeredSocketEvents set to prevent duplicates.
|
|
235
|
+
*/
|
|
236
|
+
registerSocketEventIfNeeded(event) {
|
|
237
|
+
const { socket } = this;
|
|
238
|
+
if (!socket || this.registeredSocketEvents.has(event)) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
// Register the dispatch listener on socket
|
|
242
|
+
socket.on(event, (data) => {
|
|
243
|
+
const handlers = this.eventHandlers.get(event);
|
|
244
|
+
if (handlers) {
|
|
245
|
+
for (const h of handlers) {
|
|
246
|
+
h(data);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
this.registeredSocketEvents.add(event);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Remove socket listener for an event and clear tracking.
|
|
254
|
+
*/
|
|
255
|
+
removeSocketEventListener(event) {
|
|
256
|
+
const { socket } = this;
|
|
257
|
+
if (socket && this.registeredSocketEvents.has(event)) {
|
|
258
|
+
socket.off(event);
|
|
259
|
+
this.registeredSocketEvents.delete(event);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
setState(state) {
|
|
263
|
+
if (this.state !== state) {
|
|
264
|
+
this.state = state;
|
|
265
|
+
for (const handler of this.stateHandlers) {
|
|
266
|
+
handler(state);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { TransportServerConfig } from '../../core/domain/transport/types.js';
|
|
2
|
+
import type { ConnectionHandler, ITransportServer, RequestHandler } from '../../core/interfaces/transport/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Socket.IO implementation of ITransportServer.
|
|
5
|
+
*
|
|
6
|
+
* Architecture notes:
|
|
7
|
+
* - Uses an HTTP server internally for Socket.IO
|
|
8
|
+
* - Request/response pattern: client emits "event", server emits "event:response" or "event:error"
|
|
9
|
+
* - Rooms are used for targeted broadcasts (e.g., per-task events)
|
|
10
|
+
*/
|
|
11
|
+
export declare class SocketIOTransportServer implements ITransportServer {
|
|
12
|
+
private readonly config;
|
|
13
|
+
private connectionHandlers;
|
|
14
|
+
private disconnectionHandlers;
|
|
15
|
+
private httpServer;
|
|
16
|
+
private io;
|
|
17
|
+
private port;
|
|
18
|
+
private requestHandlers;
|
|
19
|
+
private running;
|
|
20
|
+
private sockets;
|
|
21
|
+
constructor(config?: TransportServerConfig);
|
|
22
|
+
addToRoom(clientId: string, room: string): void;
|
|
23
|
+
broadcast<T = unknown>(event: string, data: T): void;
|
|
24
|
+
broadcastTo<T = unknown>(room: string, event: string, data: T): void;
|
|
25
|
+
getPort(): number | undefined;
|
|
26
|
+
isRunning(): boolean;
|
|
27
|
+
onConnection(handler: ConnectionHandler): void;
|
|
28
|
+
onDisconnection(handler: ConnectionHandler): void;
|
|
29
|
+
onRequest<TRequest = unknown, TResponse = unknown>(event: string, handler: RequestHandler<TRequest, TResponse>): void;
|
|
30
|
+
removeFromRoom(clientId: string, room: string): void;
|
|
31
|
+
sendTo<T = unknown>(clientId: string, event: string, data: T): void;
|
|
32
|
+
start(port: number): Promise<void>;
|
|
33
|
+
stop(): Promise<void>;
|
|
34
|
+
private registerEventHandler;
|
|
35
|
+
}
|