byterover-cli 0.2.1 → 0.3.1
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 +56 -56
- package/bin/dev.js +1 -1
- package/dist/commands/cipher-agent/run.d.ts +111 -0
- package/dist/commands/cipher-agent/run.js +493 -0
- package/dist/commands/cipher-agent/set-prompt.d.ts +14 -0
- package/dist/commands/cipher-agent/set-prompt.js +53 -0
- package/dist/commands/cipher-agent/show-prompt.d.ts +11 -0
- package/dist/commands/cipher-agent/show-prompt.js +48 -0
- package/dist/commands/clear.d.ts +6 -0
- package/dist/commands/clear.js +36 -15
- package/dist/commands/curate.d.ts +74 -0
- package/dist/commands/curate.js +396 -0
- package/dist/commands/foo.d.ts +12 -0
- package/dist/commands/foo.js +61 -0
- package/dist/commands/gen-rules.d.ts +3 -0
- package/dist/commands/gen-rules.js +39 -20
- package/dist/commands/init.d.ts +63 -3
- package/dist/commands/init.js +285 -70
- package/dist/commands/login.js +9 -4
- package/dist/commands/pull.d.ts +33 -0
- package/dist/commands/pull.js +115 -0
- package/dist/commands/push.d.ts +13 -13
- package/dist/commands/push.js +81 -101
- package/dist/commands/query.d.ts +63 -0
- package/dist/commands/query.js +349 -0
- package/dist/commands/space/list.d.ts +5 -2
- package/dist/commands/space/list.js +60 -56
- package/dist/commands/space/switch.d.ts +16 -0
- package/dist/commands/space/switch.js +102 -53
- package/dist/commands/status.d.ts +5 -2
- package/dist/commands/status.js +43 -33
- package/dist/commands/watch.d.ts +23 -0
- package/dist/commands/watch.js +171 -0
- package/dist/config/auth.config.js +14 -2
- package/dist/config/context-tree-domains.d.ts +12 -0
- package/dist/config/context-tree-domains.js +29 -0
- package/dist/config/environment.d.ts +6 -0
- package/dist/config/environment.js +9 -2
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +6 -0
- package/dist/core/domain/cipher/agent/agent-state-machine.d.ts +128 -0
- package/dist/core/domain/cipher/agent/agent-state-machine.js +183 -0
- package/dist/core/domain/cipher/agent/agent-state.d.ts +77 -0
- package/dist/core/domain/cipher/agent/agent-state.js +59 -0
- package/dist/core/domain/cipher/agent/index.d.ts +7 -0
- package/dist/core/domain/cipher/agent/index.js +7 -0
- package/dist/core/domain/cipher/agent-events/index.d.ts +8 -0
- package/dist/core/domain/cipher/agent-events/index.js +7 -0
- package/dist/core/domain/cipher/agent-events/types.d.ts +419 -0
- package/dist/core/domain/cipher/agent-events/types.js +42 -0
- package/dist/core/domain/cipher/blob/types.d.ts +108 -0
- package/dist/core/domain/cipher/errors/blob-error.d.ts +36 -0
- package/dist/core/domain/cipher/errors/blob-error.js +68 -0
- package/dist/core/domain/cipher/errors/file-system-error.d.ts +211 -0
- package/dist/core/domain/cipher/errors/file-system-error.js +291 -0
- package/dist/core/domain/cipher/errors/llm-error.d.ts +120 -0
- package/dist/core/domain/cipher/errors/llm-error.js +161 -0
- package/dist/core/domain/cipher/errors/memory-error.d.ts +35 -0
- package/dist/core/domain/cipher/errors/memory-error.js +62 -0
- package/dist/core/domain/cipher/errors/process-error-code.d.ts +97 -0
- package/dist/core/domain/cipher/errors/process-error-code.js +98 -0
- package/dist/core/domain/cipher/errors/process-error.d.ts +135 -0
- package/dist/core/domain/cipher/errors/process-error.js +173 -0
- package/dist/core/domain/cipher/errors/session-error.d.ts +56 -0
- package/dist/core/domain/cipher/errors/session-error.js +74 -0
- package/dist/core/domain/cipher/errors/tool-error.d.ts +57 -0
- package/dist/core/domain/cipher/errors/tool-error.js +81 -0
- package/dist/core/domain/cipher/file-system/types.d.ts +203 -0
- package/dist/core/domain/cipher/memory/types.d.ts +102 -0
- package/dist/core/domain/cipher/memory/types.js +4 -0
- package/dist/core/domain/cipher/parsed-interaction.d.ts +47 -0
- package/dist/core/domain/cipher/parsed-interaction.js +25 -0
- package/dist/core/domain/cipher/process/types.d.ts +286 -0
- package/dist/core/domain/cipher/session/types.d.ts +54 -0
- package/dist/core/domain/cipher/storage/history-types.d.ts +38 -0
- package/dist/core/domain/cipher/system-prompt/types.d.ts +131 -0
- package/dist/core/domain/cipher/todos/index.d.ts +4 -0
- package/dist/core/domain/cipher/todos/index.js +4 -0
- package/dist/core/domain/cipher/todos/types.d.ts +57 -0
- package/dist/core/domain/cipher/todos/types.js +5 -0
- package/dist/core/domain/cipher/tools/constants.d.ts +28 -0
- package/dist/core/domain/cipher/tools/constants.js +24 -0
- package/dist/core/domain/cipher/tools/tool-error.d.ts +183 -0
- package/dist/core/domain/cipher/tools/tool-error.js +246 -0
- package/dist/core/domain/cipher/tools/types.d.ts +145 -0
- package/dist/core/domain/entities/brv-config.d.ts +42 -6
- package/dist/core/domain/entities/brv-config.js +115 -17
- package/dist/core/domain/entities/cogit-push-context.d.ts +38 -0
- package/dist/core/domain/entities/cogit-push-context.js +91 -0
- package/dist/core/domain/entities/cogit-push-response.d.ts +20 -0
- package/dist/core/domain/entities/cogit-push-response.js +31 -0
- package/dist/core/domain/entities/cogit-snapshot-author.d.ts +24 -0
- package/dist/core/domain/entities/cogit-snapshot-author.js +39 -0
- package/dist/core/domain/entities/cogit-snapshot-file.d.ts +34 -0
- package/dist/core/domain/entities/cogit-snapshot-file.js +59 -0
- package/dist/core/domain/entities/cogit-snapshot.d.ts +31 -0
- package/dist/core/domain/entities/cogit-snapshot.js +58 -0
- package/dist/core/domain/entities/context-tree-index.d.ts +26 -0
- package/dist/core/domain/entities/context-tree-index.js +27 -0
- package/dist/core/domain/entities/context-tree-snapshot.d.ts +56 -0
- package/dist/core/domain/entities/context-tree-snapshot.js +83 -0
- package/dist/core/domain/entities/event.d.ts +1 -1
- package/dist/core/domain/entities/event.js +3 -1
- package/dist/core/domain/entities/parser.d.ts +567 -0
- package/dist/core/domain/entities/parser.js +10 -0
- package/dist/core/domain/entities/playbook.d.ts +2 -23
- package/dist/core/domain/entities/playbook.js +2 -70
- package/dist/core/domain/errors/brv-config-version-error.d.ts +16 -0
- package/dist/core/domain/errors/brv-config-version-error.js +21 -0
- package/dist/core/domain/knowledge/directory-manager.d.ts +80 -0
- package/dist/core/domain/knowledge/directory-manager.js +145 -0
- package/dist/core/domain/knowledge/markdown-writer.d.ts +18 -0
- package/dist/core/domain/knowledge/markdown-writer.js +18 -0
- package/dist/core/domain/knowledge/relation-parser.d.ts +90 -0
- package/dist/core/domain/knowledge/relation-parser.js +131 -0
- package/dist/core/interfaces/cipher/cipher-services.d.ts +71 -0
- package/dist/core/interfaces/cipher/cipher-services.js +1 -0
- package/dist/core/interfaces/cipher/i-blob-storage.d.ts +78 -0
- package/dist/core/interfaces/cipher/i-blob-storage.js +1 -0
- package/dist/core/interfaces/cipher/i-chat-session.d.ts +62 -0
- package/dist/core/interfaces/cipher/i-chat-session.js +1 -0
- package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +88 -0
- package/dist/core/interfaces/cipher/i-cipher-agent.js +1 -0
- package/dist/core/interfaces/cipher/i-coding-agent-log-parser.d.ts +20 -0
- package/dist/core/interfaces/cipher/i-coding-agent-log-parser.js +1 -0
- package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.d.ts +31 -0
- package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.js +1 -0
- package/dist/core/interfaces/cipher/i-content-generator.d.ts +120 -0
- package/dist/core/interfaces/cipher/i-content-generator.js +12 -0
- package/dist/core/interfaces/cipher/i-event-emitter.d.ts +76 -0
- package/dist/core/interfaces/cipher/i-event-emitter.js +1 -0
- package/dist/core/interfaces/cipher/i-file-system.d.ts +68 -0
- package/dist/core/interfaces/cipher/i-file-system.js +1 -0
- package/dist/core/interfaces/cipher/i-history-storage.d.ts +53 -0
- package/dist/core/interfaces/cipher/i-history-storage.js +1 -0
- package/dist/core/interfaces/cipher/i-llm-provider.d.ts +14 -0
- package/dist/core/interfaces/cipher/i-llm-provider.js +1 -0
- package/dist/core/interfaces/cipher/i-llm-service.d.ts +62 -0
- package/dist/core/interfaces/cipher/i-llm-service.js +1 -0
- package/dist/core/interfaces/cipher/i-logger.d.ts +78 -0
- package/dist/core/interfaces/cipher/i-logger.js +28 -0
- package/dist/core/interfaces/cipher/i-message-formatter.d.ts +44 -0
- package/dist/core/interfaces/cipher/i-message-formatter.js +1 -0
- package/dist/core/interfaces/cipher/i-policy-engine.d.ts +102 -0
- package/dist/core/interfaces/cipher/i-policy-engine.js +9 -0
- package/dist/core/interfaces/cipher/i-process-service.d.ts +65 -0
- package/dist/core/interfaces/cipher/i-process-service.js +1 -0
- package/dist/core/interfaces/cipher/i-system-prompt-contributor.d.ts +25 -0
- package/dist/core/interfaces/cipher/i-system-prompt-contributor.js +1 -0
- package/dist/core/interfaces/cipher/i-tokenizer.d.ts +15 -0
- package/dist/core/interfaces/cipher/i-tokenizer.js +1 -0
- package/dist/core/interfaces/cipher/i-tool-provider.d.ts +64 -0
- package/dist/core/interfaces/cipher/i-tool-provider.js +1 -0
- package/dist/core/interfaces/cipher/i-tool-scheduler.d.ts +103 -0
- package/dist/core/interfaces/cipher/i-tool-scheduler.js +11 -0
- package/dist/core/interfaces/cipher/llm-types.d.ts +46 -0
- package/dist/core/interfaces/cipher/llm-types.js +5 -0
- package/dist/core/interfaces/cipher/message-types.d.ts +118 -0
- package/dist/core/interfaces/cipher/message-types.js +5 -0
- package/dist/core/interfaces/cipher/tokenizer-types.d.ts +11 -0
- package/dist/core/interfaces/cipher/tokenizer-types.js +14 -0
- package/dist/core/interfaces/i-cogit-pull-service.d.ts +24 -0
- package/dist/core/interfaces/i-cogit-pull-service.js +1 -0
- package/dist/core/interfaces/i-cogit-push-service.d.ts +27 -0
- package/dist/core/interfaces/i-cogit-push-service.js +1 -0
- package/dist/core/interfaces/i-context-file-reader.d.ts +32 -0
- package/dist/core/interfaces/i-context-file-reader.js +1 -0
- package/dist/core/interfaces/i-context-tree-service.d.ts +21 -0
- package/dist/core/interfaces/i-context-tree-service.js +1 -0
- package/dist/core/interfaces/i-context-tree-snapshot-service.d.ts +36 -0
- package/dist/core/interfaces/i-context-tree-snapshot-service.js +1 -0
- package/dist/core/interfaces/i-context-tree-writer-service.d.ts +32 -0
- package/dist/core/interfaces/i-context-tree-writer-service.js +1 -0
- package/dist/core/interfaces/i-file-watcher-service.d.ts +41 -0
- package/dist/core/interfaces/i-file-watcher-service.js +1 -0
- package/dist/core/interfaces/parser/i-clean-parser-service.d.ts +18 -0
- package/dist/core/interfaces/parser/i-clean-parser-service.js +1 -0
- package/dist/core/interfaces/parser/i-raw-parser-service.d.ts +17 -0
- package/dist/core/interfaces/parser/i-raw-parser-service.js +1 -0
- package/dist/core/interfaces/parser/i-session-normalizer.d.ts +56 -0
- package/dist/core/interfaces/parser/i-session-normalizer.js +1 -0
- package/dist/hooks/command_not_found/handle-invalid-commands.d.ts +7 -0
- package/dist/hooks/command_not_found/handle-invalid-commands.js +32 -0
- package/dist/hooks/error/clean-errors.d.ts +7 -0
- package/dist/hooks/error/clean-errors.js +50 -0
- package/dist/hooks/init/welcome.js +72 -1
- package/dist/hooks/prerun/validate-brv-config-version.d.ts +28 -0
- package/dist/hooks/prerun/validate-brv-config-version.js +43 -0
- package/dist/infra/cipher/agent-service-factory.d.ts +86 -0
- package/dist/infra/cipher/agent-service-factory.js +212 -0
- package/dist/infra/cipher/blob/blob-storage-factory.d.ts +13 -0
- package/dist/infra/cipher/blob/blob-storage-factory.js +14 -0
- package/dist/infra/cipher/blob/index.d.ts +10 -0
- package/dist/infra/cipher/blob/index.js +12 -0
- package/dist/infra/cipher/blob/migrations.d.ts +63 -0
- package/dist/infra/cipher/blob/migrations.js +148 -0
- package/dist/infra/cipher/blob/sqlite-blob-storage.d.ts +82 -0
- package/dist/infra/cipher/blob/sqlite-blob-storage.js +307 -0
- package/dist/infra/cipher/cipher-agent-state-manager.d.ts +63 -0
- package/dist/infra/cipher/cipher-agent-state-manager.js +108 -0
- package/dist/infra/cipher/cipher-agent.d.ts +182 -0
- package/dist/infra/cipher/cipher-agent.js +317 -0
- package/dist/infra/cipher/command-parser.d.ts +23 -0
- package/dist/infra/cipher/command-parser.js +85 -0
- package/dist/infra/cipher/display/todo-display.d.ts +23 -0
- package/dist/infra/cipher/display/todo-display.js +129 -0
- package/dist/infra/cipher/events/event-emitter.d.ts +137 -0
- package/dist/infra/cipher/events/event-emitter.js +158 -0
- package/dist/infra/cipher/exit-codes.d.ts +44 -0
- package/dist/infra/cipher/exit-codes.js +58 -0
- package/dist/infra/cipher/file-system/file-system-service.d.ts +105 -0
- package/dist/infra/cipher/file-system/file-system-service.js +641 -0
- package/dist/infra/cipher/file-system/gitignore-filter.d.ts +77 -0
- package/dist/infra/cipher/file-system/gitignore-filter.js +120 -0
- package/dist/infra/cipher/file-system/glob-utils.d.ts +60 -0
- package/dist/infra/cipher/file-system/glob-utils.js +120 -0
- package/dist/infra/cipher/file-system/path-validator.d.ts +69 -0
- package/dist/infra/cipher/file-system/path-validator.js +184 -0
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +149 -0
- package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +364 -0
- package/dist/infra/cipher/grpc/internal-llm-grpc.proto +94 -0
- package/dist/infra/cipher/interactive-commands.d.ts +16 -0
- package/dist/infra/cipher/interactive-commands.js +198 -0
- package/dist/infra/cipher/interactive-loop.d.ts +24 -0
- package/dist/infra/cipher/interactive-loop.js +352 -0
- package/dist/infra/cipher/llm/context/async-mutex.d.ts +59 -0
- package/dist/infra/cipher/llm/context/async-mutex.js +92 -0
- package/dist/infra/cipher/llm/context/compression/index.d.ts +6 -0
- package/dist/infra/cipher/llm/context/compression/index.js +5 -0
- package/dist/infra/cipher/llm/context/compression/middle-removal.d.ts +40 -0
- package/dist/infra/cipher/llm/context/compression/middle-removal.js +76 -0
- package/dist/infra/cipher/llm/context/compression/oldest-removal.d.ts +38 -0
- package/dist/infra/cipher/llm/context/compression/oldest-removal.js +53 -0
- package/dist/infra/cipher/llm/context/compression/types.d.ts +36 -0
- package/dist/infra/cipher/llm/context/compression/types.js +1 -0
- package/dist/infra/cipher/llm/context/context-manager.d.ts +234 -0
- package/dist/infra/cipher/llm/context/context-manager.js +419 -0
- package/dist/infra/cipher/llm/context/index.d.ts +2 -0
- package/dist/infra/cipher/llm/context/index.js +2 -0
- package/dist/infra/cipher/llm/context/loop-detector.d.ts +125 -0
- package/dist/infra/cipher/llm/context/loop-detector.js +194 -0
- package/dist/infra/cipher/llm/context/utils.d.ts +17 -0
- package/dist/infra/cipher/llm/context/utils.js +89 -0
- package/dist/infra/cipher/llm/formatters/claude-formatter.d.ts +54 -0
- package/dist/infra/cipher/llm/formatters/claude-formatter.js +182 -0
- package/dist/infra/cipher/llm/formatters/gemini-formatter.d.ts +69 -0
- package/dist/infra/cipher/llm/formatters/gemini-formatter.js +253 -0
- package/dist/infra/cipher/llm/formatters/openrouter-formatter.d.ts +47 -0
- package/dist/infra/cipher/llm/formatters/openrouter-formatter.js +238 -0
- package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +92 -0
- package/dist/infra/cipher/llm/generators/byterover-content-generator.js +211 -0
- package/dist/infra/cipher/llm/generators/index.d.ts +13 -0
- package/dist/infra/cipher/llm/generators/index.js +13 -0
- package/dist/infra/cipher/llm/generators/logging-content-generator.d.ts +104 -0
- package/dist/infra/cipher/llm/generators/logging-content-generator.js +182 -0
- package/dist/infra/cipher/llm/generators/openrouter-content-generator.d.ts +93 -0
- package/dist/infra/cipher/llm/generators/openrouter-content-generator.js +254 -0
- package/dist/infra/cipher/llm/generators/retryable-content-generator.d.ts +90 -0
- package/dist/infra/cipher/llm/generators/retryable-content-generator.js +157 -0
- package/dist/infra/cipher/llm/index.d.ts +9 -0
- package/dist/infra/cipher/llm/index.js +13 -0
- package/dist/infra/cipher/llm/internal-llm-service.d.ts +308 -0
- package/dist/infra/cipher/llm/internal-llm-service.js +724 -0
- package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +183 -0
- package/dist/infra/cipher/llm/openrouter-llm-service.js +386 -0
- package/dist/infra/cipher/llm/response-validator.d.ts +89 -0
- package/dist/infra/cipher/llm/response-validator.js +157 -0
- package/dist/infra/cipher/llm/retry/index.d.ts +10 -0
- package/dist/infra/cipher/llm/retry/index.js +10 -0
- package/dist/infra/cipher/llm/retry/retry-policy.d.ts +74 -0
- package/dist/infra/cipher/llm/retry/retry-policy.js +146 -0
- package/dist/infra/cipher/llm/retry/retry-with-backoff.d.ts +113 -0
- package/dist/infra/cipher/llm/retry/retry-with-backoff.js +247 -0
- package/dist/infra/cipher/llm/thought-parser.d.ts +145 -0
- package/dist/infra/cipher/llm/thought-parser.js +190 -0
- package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.d.ts +47 -0
- package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.js +55 -0
- package/dist/infra/cipher/llm/tokenizers/default-tokenizer.d.ts +31 -0
- package/dist/infra/cipher/llm/tokenizers/default-tokenizer.js +38 -0
- package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.d.ts +37 -0
- package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.js +45 -0
- package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.d.ts +29 -0
- package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.js +37 -0
- package/dist/infra/cipher/llm/tool-output-processor.d.ts +117 -0
- package/dist/infra/cipher/llm/tool-output-processor.js +153 -0
- package/dist/infra/cipher/logger/console-logger.d.ts +42 -0
- package/dist/infra/cipher/logger/console-logger.js +63 -0
- package/dist/infra/cipher/logger/event-based-logger.d.ts +54 -0
- package/dist/infra/cipher/logger/event-based-logger.js +92 -0
- package/dist/infra/cipher/memory/index.d.ts +6 -0
- package/dist/infra/cipher/memory/index.js +7 -0
- package/dist/infra/cipher/memory/memory-manager.d.ts +136 -0
- package/dist/infra/cipher/memory/memory-manager.js +523 -0
- package/dist/infra/cipher/parsers/coding-agent-log-parser.d.ts +24 -0
- package/dist/infra/cipher/parsers/coding-agent-log-parser.js +51 -0
- package/dist/infra/cipher/process/command-validator.d.ts +59 -0
- package/dist/infra/cipher/process/command-validator.js +266 -0
- package/dist/infra/cipher/process/index.d.ts +8 -0
- package/dist/infra/cipher/process/index.js +8 -0
- package/dist/infra/cipher/process/process-service.d.ts +95 -0
- package/dist/infra/cipher/process/process-service.js +439 -0
- package/dist/infra/cipher/session/chat-session.d.ts +80 -0
- package/dist/infra/cipher/session/chat-session.js +165 -0
- package/dist/infra/cipher/session/index.d.ts +6 -0
- package/dist/infra/cipher/session/index.js +5 -0
- package/dist/infra/cipher/session/session-event-forwarder.d.ts +37 -0
- package/dist/infra/cipher/session/session-event-forwarder.js +83 -0
- package/dist/infra/cipher/session/session-manager.d.ts +109 -0
- package/dist/infra/cipher/session/session-manager.js +172 -0
- package/dist/infra/cipher/storage/blob-history-storage.d.ts +76 -0
- package/dist/infra/cipher/storage/blob-history-storage.js +178 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +105 -0
- package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +290 -0
- package/dist/infra/cipher/tools/core-tool-scheduler.d.ts +99 -0
- package/dist/infra/cipher/tools/core-tool-scheduler.js +161 -0
- package/dist/infra/cipher/tools/default-policy-rules.d.ts +26 -0
- package/dist/infra/cipher/tools/default-policy-rules.js +125 -0
- package/dist/infra/cipher/tools/implementations/bash-exec-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +93 -0
- package/dist/infra/cipher/tools/implementations/bash-output-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/bash-output-tool.js +47 -0
- package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.d.ts +11 -0
- package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.js +142 -0
- package/dist/infra/cipher/tools/implementations/delete-memory-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/delete-memory-tool.js +37 -0
- package/dist/infra/cipher/tools/implementations/detect-domains-tool.d.ts +7 -0
- package/dist/infra/cipher/tools/implementations/detect-domains-tool.js +73 -0
- package/dist/infra/cipher/tools/implementations/edit-file-tool.d.ts +13 -0
- package/dist/infra/cipher/tools/implementations/edit-file-tool.js +50 -0
- package/dist/infra/cipher/tools/implementations/edit-memory-tool.d.ts +13 -0
- package/dist/infra/cipher/tools/implementations/edit-memory-tool.js +53 -0
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.d.ts +7 -0
- package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +421 -0
- package/dist/infra/cipher/tools/implementations/glob-files-tool.d.ts +18 -0
- package/dist/infra/cipher/tools/implementations/glob-files-tool.js +70 -0
- package/dist/infra/cipher/tools/implementations/grep-content-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/grep-content-tool.js +77 -0
- package/dist/infra/cipher/tools/implementations/kill-process-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/kill-process-tool.js +55 -0
- package/dist/infra/cipher/tools/implementations/list-memories-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/list-memories-tool.js +63 -0
- package/dist/infra/cipher/tools/implementations/read-file-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/read-file-tool.js +54 -0
- package/dist/infra/cipher/tools/implementations/read-memory-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/read-memory-tool.js +39 -0
- package/dist/infra/cipher/tools/implementations/search-history-tool.d.ts +10 -0
- package/dist/infra/cipher/tools/implementations/search-history-tool.js +36 -0
- package/dist/infra/cipher/tools/implementations/write-file-tool.d.ts +12 -0
- package/dist/infra/cipher/tools/implementations/write-file-tool.js +52 -0
- package/dist/infra/cipher/tools/implementations/write-memory-tool.d.ts +13 -0
- package/dist/infra/cipher/tools/implementations/write-memory-tool.js +52 -0
- package/dist/infra/cipher/tools/implementations/write-todos-tool.d.ts +10 -0
- package/dist/infra/cipher/tools/implementations/write-todos-tool.js +165 -0
- package/dist/infra/cipher/tools/index.d.ts +18 -0
- package/dist/infra/cipher/tools/index.js +19 -0
- package/dist/infra/cipher/tools/policy-engine.d.ts +80 -0
- package/dist/infra/cipher/tools/policy-engine.js +110 -0
- package/dist/infra/cipher/tools/tool-invocation-queue.d.ts +191 -0
- package/dist/infra/cipher/tools/tool-invocation-queue.js +254 -0
- package/dist/infra/cipher/tools/tool-invocation.d.ts +216 -0
- package/dist/infra/cipher/tools/tool-invocation.js +294 -0
- package/dist/infra/cipher/tools/tool-manager.d.ts +135 -0
- package/dist/infra/cipher/tools/tool-manager.js +209 -0
- package/dist/infra/cipher/tools/tool-markers.d.ts +48 -0
- package/dist/infra/cipher/tools/tool-markers.js +49 -0
- package/dist/infra/cipher/tools/tool-provider.d.ts +77 -0
- package/dist/infra/cipher/tools/tool-provider.js +196 -0
- package/dist/infra/cipher/tools/tool-registry.d.ts +52 -0
- package/dist/infra/cipher/tools/tool-registry.js +144 -0
- package/dist/infra/cipher/tools/utils/schema-converter.d.ts +10 -0
- package/dist/infra/cipher/tools/utils/schema-converter.js +29 -0
- package/dist/infra/cipher/validation/workspace-validator.d.ts +19 -0
- package/dist/infra/cipher/validation/workspace-validator.js +37 -0
- package/dist/infra/cipher/watcher/coding-agent-log-watcher.d.ts +14 -0
- package/dist/infra/cipher/watcher/coding-agent-log-watcher.js +55 -0
- package/dist/infra/cogit/context-tree-to-push-context-mapper.d.ts +21 -0
- package/dist/infra/cogit/context-tree-to-push-context-mapper.js +32 -0
- package/dist/infra/cogit/http-cogit-pull-service.d.ts +15 -0
- package/dist/infra/cogit/http-cogit-pull-service.js +30 -0
- package/dist/infra/cogit/http-cogit-push-service.d.ts +17 -0
- package/dist/infra/cogit/http-cogit-push-service.js +104 -0
- package/dist/infra/config/file-config-store.js +9 -3
- package/dist/infra/context-tree/file-context-file-reader.d.ts +14 -0
- package/dist/infra/context-tree/file-context-file-reader.js +46 -0
- package/dist/infra/context-tree/file-context-tree-service.d.ts +14 -0
- package/dist/infra/context-tree/file-context-tree-service.js +46 -0
- package/dist/infra/context-tree/file-context-tree-snapshot-service.d.ts +34 -0
- package/dist/infra/context-tree/file-context-tree-snapshot-service.js +117 -0
- package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +22 -0
- package/dist/infra/context-tree/file-context-tree-writer-service.js +61 -0
- package/dist/infra/memory/http-memory-retrieval-service.js +2 -1
- package/dist/infra/memory/http-memory-storage-service.js +4 -3
- package/dist/infra/parsers/clean/clean-claude-service.d.ts +111 -0
- package/dist/infra/parsers/clean/clean-claude-service.js +271 -0
- package/dist/infra/parsers/clean/clean-codex-service.d.ts +231 -0
- package/dist/infra/parsers/clean/clean-codex-service.js +534 -0
- package/dist/infra/parsers/clean/clean-copilot-service.d.ts +255 -0
- package/dist/infra/parsers/clean/clean-copilot-service.js +729 -0
- package/dist/infra/parsers/clean/clean-cursor-service.d.ts +161 -0
- package/dist/infra/parsers/clean/clean-cursor-service.js +432 -0
- package/dist/infra/parsers/clean/clean-parser-service-factory.d.ts +54 -0
- package/dist/infra/parsers/clean/clean-parser-service-factory.js +80 -0
- package/dist/infra/parsers/clean/shared.d.ts +84 -0
- package/dist/infra/parsers/clean/shared.js +273 -0
- package/dist/infra/parsers/raw/raw-claude-service.d.ts +195 -0
- package/dist/infra/parsers/raw/raw-claude-service.js +548 -0
- package/dist/infra/parsers/raw/raw-codex-service.d.ts +313 -0
- package/dist/infra/parsers/raw/raw-codex-service.js +782 -0
- package/dist/infra/parsers/raw/raw-copilot-service.d.ts +196 -0
- package/dist/infra/parsers/raw/raw-copilot-service.js +558 -0
- package/dist/infra/parsers/raw/raw-cursor-service.d.ts +316 -0
- package/dist/infra/parsers/raw/raw-cursor-service.js +818 -0
- package/dist/infra/parsers/raw/raw-parser-service-factory.d.ts +54 -0
- package/dist/infra/parsers/raw/raw-parser-service-factory.js +81 -0
- package/dist/infra/space/http-space-service.js +2 -1
- package/dist/infra/team/http-team-service.js +2 -1
- package/dist/infra/user/http-user-service.js +2 -1
- package/dist/infra/watcher/file-watcher-service.d.ts +10 -0
- package/dist/infra/watcher/file-watcher-service.js +81 -0
- package/dist/infra/workspace/workspace-detector-service.d.ts +60 -0
- package/dist/infra/workspace/workspace-detector-service.js +165 -0
- package/dist/resources/prompts/curate-context-tree-curation.yml +48 -0
- package/dist/resources/prompts/modes/autonomous.yml +9 -0
- package/dist/resources/prompts/query-context-tree-retrieval.yml +49 -0
- package/dist/resources/prompts/reflection.yml +27 -0
- package/dist/resources/prompts/system-prompt.yml +82 -0
- package/dist/resources/prompts/tool-outputs.yml +30 -0
- package/dist/templates/README.md +6 -7
- package/dist/templates/sections/command-reference.md +40 -111
- package/dist/templates/sections/workflow.md +3 -30
- package/dist/utils/emoji-helpers.d.ts +38 -0
- package/dist/utils/emoji-helpers.js +42 -0
- package/dist/utils/error-handler.d.ts +51 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-helpers.d.ts +30 -0
- package/dist/utils/error-helpers.js +47 -0
- package/dist/utils/file-helpers.d.ts +15 -0
- package/dist/utils/file-helpers.js +44 -0
- package/dist/utils/oclif-error-helpers.d.ts +40 -0
- package/dist/utils/oclif-error-helpers.js +46 -0
- package/dist/utils/tool-display-formatter.d.ts +53 -0
- package/dist/utils/tool-display-formatter.js +257 -0
- package/oclif.manifest.json +381 -141
- package/package.json +27 -6
- package/dist/commands/add.d.ts +0 -49
- package/dist/commands/add.js +0 -192
- package/dist/commands/complete.d.ts +0 -108
- package/dist/commands/complete.js +0 -340
- package/dist/commands/retrieve.d.ts +0 -26
- package/dist/commands/retrieve.js +0 -101
- package/dist/core/domain/entities/curator-output.d.ts +0 -14
- package/dist/core/domain/entities/curator-output.js +0 -23
- package/dist/core/domain/entities/delta-batch.d.ts +0 -30
- package/dist/core/domain/entities/delta-batch.js +0 -52
- package/dist/core/domain/entities/delta-operation.d.ts +0 -31
- package/dist/core/domain/entities/delta-operation.js +0 -50
- package/dist/core/domain/entities/executor-output.d.ts +0 -27
- package/dist/core/domain/entities/executor-output.js +0 -33
- package/dist/core/domain/entities/reflector-output.d.ts +0 -38
- package/dist/core/domain/entities/reflector-output.js +0 -44
- package/dist/core/interfaces/i-ace-prompt-builder.d.ts +0 -48
- package/dist/core/interfaces/i-bullet-content-store.d.ts +0 -36
- package/dist/core/interfaces/i-delta-store.d.ts +0 -15
- package/dist/core/interfaces/i-executor-output-store.d.ts +0 -14
- package/dist/core/interfaces/i-playbook-service.d.ts +0 -69
- package/dist/core/interfaces/i-playbook-store.d.ts +0 -38
- package/dist/core/interfaces/i-reflection-store.d.ts +0 -21
- package/dist/infra/ace/ace-file-utils.d.ts +0 -46
- package/dist/infra/ace/ace-file-utils.js +0 -83
- package/dist/infra/ace/ace-prompt-templates.d.ts +0 -13
- package/dist/infra/ace/ace-prompt-templates.js +0 -177
- package/dist/infra/ace/file-bullet-content-store.d.ts +0 -27
- package/dist/infra/ace/file-bullet-content-store.js +0 -89
- package/dist/infra/ace/file-delta-store.d.ts +0 -9
- package/dist/infra/ace/file-delta-store.js +0 -26
- package/dist/infra/ace/file-executor-output-store.d.ts +0 -9
- package/dist/infra/ace/file-executor-output-store.js +0 -26
- package/dist/infra/ace/file-playbook-store.d.ts +0 -29
- package/dist/infra/ace/file-playbook-store.js +0 -107
- package/dist/infra/ace/file-reflection-store.d.ts +0 -10
- package/dist/infra/ace/file-reflection-store.js +0 -55
- package/dist/infra/playbook/file-playbook-service.d.ts +0 -42
- package/dist/infra/playbook/file-playbook-service.js +0 -132
- /package/dist/core/{interfaces/i-ace-prompt-builder.js → domain/cipher/blob/types.js} +0 -0
- /package/dist/core/{interfaces/i-bullet-content-store.js → domain/cipher/file-system/types.js} +0 -0
- /package/dist/core/{interfaces/i-delta-store.js → domain/cipher/process/types.js} +0 -0
- /package/dist/core/{interfaces/i-executor-output-store.js → domain/cipher/session/types.js} +0 -0
- /package/dist/core/{interfaces/i-playbook-service.js → domain/cipher/storage/history-types.js} +0 -0
- /package/dist/core/{interfaces/i-playbook-store.js → domain/cipher/system-prompt/types.js} +0 -0
- /package/dist/core/{interfaces/i-reflection-store.js → domain/cipher/tools/types.js} +0 -0
|
@@ -0,0 +1,818 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor IDE Raw Service
|
|
3
|
+
* Consolidates CursorParser + CursorRawParser + Enhanced Bubble Extraction
|
|
4
|
+
* Parses Cursor IDE chat sessions from local storage and workspace data
|
|
5
|
+
*/
|
|
6
|
+
import Database from 'better-sqlite3';
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { basename, dirname, join } from 'node:path';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// CONSTANTS
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Database file paths
|
|
13
|
+
const WORKSPACE_DB_FILE = 'state.vscdb';
|
|
14
|
+
const GLOBAL_STORAGE_DB_PATH = '../globalStorage/state.vscdb';
|
|
15
|
+
// Database query patterns
|
|
16
|
+
const COMPOSER_DATA_KEY = 'composer.composerData';
|
|
17
|
+
const BUBBLE_ID_KEY_PATTERN = 'bubbleId:%';
|
|
18
|
+
const CODE_BLOCK_DIFF_KEY_PATTERN = 'codeBlockDiff:%';
|
|
19
|
+
const CHECKPOINT_ID_KEY_PATTERN = 'checkpointId:%';
|
|
20
|
+
const MESSAGE_REQUEST_CONTEXT_KEY_PATTERN = 'messageRequestContext:%';
|
|
21
|
+
const COMPOSER_DATA_KEY_PATTERN = 'composerData:%';
|
|
22
|
+
const FULL_CONVERSATION_HEADERS_PATTERN = '%fullConversationHeadersOnly%';
|
|
23
|
+
// Database queries
|
|
24
|
+
const SQL_QUERIES = {
|
|
25
|
+
BUBBLE_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${BUBBLE_ID_KEY_PATTERN}'`,
|
|
26
|
+
CHECKPOINT_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${CHECKPOINT_ID_KEY_PATTERN}'`,
|
|
27
|
+
CODE_BLOCK_DIFF_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${CODE_BLOCK_DIFF_KEY_PATTERN}'`,
|
|
28
|
+
COMPOSER_DATA: `SELECT value FROM ItemTable WHERE key = '${COMPOSER_DATA_KEY}'`,
|
|
29
|
+
COMPOSER_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${COMPOSER_DATA_KEY_PATTERN}' AND value LIKE '${FULL_CONVERSATION_HEADERS_PATTERN}'`,
|
|
30
|
+
MESSAGE_REQUEST_CONTEXT_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${MESSAGE_REQUEST_CONTEXT_KEY_PATTERN}'`,
|
|
31
|
+
};
|
|
32
|
+
// Regex patterns
|
|
33
|
+
const PATTERNS = {
|
|
34
|
+
CODE_BLOCK_DIFF_KEY: /^codeBlockDiff:([^:]+):/,
|
|
35
|
+
};
|
|
36
|
+
// Magic numbers
|
|
37
|
+
const HEADER_TYPE_USER = 1;
|
|
38
|
+
const FLOAT_PRECISION = 2;
|
|
39
|
+
// Default values
|
|
40
|
+
const DEFAULT_CONTEXT_ID = 'default';
|
|
41
|
+
const COMPOSER_ID_PREVIEW_LENGTH = 8;
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// CURSOR RAW SERVICE - Orchestration + File I/O
|
|
44
|
+
// ============================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Cursor Raw Service
|
|
47
|
+
* Handles extraction of Cursor sessions from both exported files and raw storage
|
|
48
|
+
*
|
|
49
|
+
* Method Organization:
|
|
50
|
+
* - Constructor
|
|
51
|
+
* - Public Methods: parse(), parseFromDirectory()
|
|
52
|
+
* - Private Workspace Methods: loadWorkspaceComposers(), extractChatIdFromCodeBlockDiffKey()
|
|
53
|
+
* - Private Helper Methods (Bubble Extraction): createEnhancedBubble(), and extraction methods
|
|
54
|
+
* - Private Utility Methods: safeParseJSON()
|
|
55
|
+
*/
|
|
56
|
+
export class CursorRawService {
|
|
57
|
+
ide;
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// CONSTRUCTOR
|
|
60
|
+
// ============================================================================
|
|
61
|
+
/**
|
|
62
|
+
* Initialize Cursor Raw Service
|
|
63
|
+
*
|
|
64
|
+
* @param ide - The IDE type (Cursor)
|
|
65
|
+
*/
|
|
66
|
+
constructor(ide) {
|
|
67
|
+
this.ide = ide;
|
|
68
|
+
}
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// PUBLIC METHODS
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Main entry point - Parse Cursor IDE sessions from a custom directory
|
|
74
|
+
*
|
|
75
|
+
* Parses Cursor IDE chat sessions from workspace storage and exports to JSON files.
|
|
76
|
+
* Handles extraction from database files and raw workspace data structures.
|
|
77
|
+
*
|
|
78
|
+
* @param customDir - Path to directory containing Cursor session data
|
|
79
|
+
* @param outputDir - Optional output directory (defaults to process.cwd()/.brv/logs/{ide}/raw)
|
|
80
|
+
* @returns Promise resolving to true if parsing succeeded, false otherwise
|
|
81
|
+
*/
|
|
82
|
+
async parse(customDir, outputDir) {
|
|
83
|
+
try {
|
|
84
|
+
return this.parseFromDirectory(customDir, outputDir);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error('❌ Error during parsing:', error);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// PRIVATE WORKSPACE METHODS
|
|
93
|
+
// ============================================================================
|
|
94
|
+
/**
|
|
95
|
+
* Parse Cursor IDE sessions from a workspace directory
|
|
96
|
+
*
|
|
97
|
+
* Handles extraction of chat sessions from Cursor's database and storage structures.
|
|
98
|
+
* Processes bubbles, composer data, and other session metadata to create normalized
|
|
99
|
+
* session files. Exports results to workspace-specific output directory.
|
|
100
|
+
*
|
|
101
|
+
* @param customDir - Path to workspace directory containing Cursor session data
|
|
102
|
+
* @param outputDir - Optional output directory (defaults to process.cwd()/.brv/logs/{ide}/raw)
|
|
103
|
+
* @returns Promise resolving to true if parsing succeeded, false otherwise
|
|
104
|
+
*/
|
|
105
|
+
async parseFromDirectory(customDir, outputDir) {
|
|
106
|
+
const baseOutputDir = outputDir || join(process.cwd(), `.brv/logs/${this.ide}/raw`);
|
|
107
|
+
console.log('🔍 Starting Cursor conversation parsing...');
|
|
108
|
+
console.log(`📁 Custom directory: ${customDir}`);
|
|
109
|
+
const workspacePath = customDir;
|
|
110
|
+
const workspaceHash = basename(customDir);
|
|
111
|
+
const workspaceDir = join(baseOutputDir, workspaceHash);
|
|
112
|
+
if (!existsSync(workspaceDir)) {
|
|
113
|
+
mkdirSync(workspaceDir, { recursive: true });
|
|
114
|
+
}
|
|
115
|
+
// Use global database to read all conversations
|
|
116
|
+
const dbPath = join(dirname(customDir), GLOBAL_STORAGE_DB_PATH);
|
|
117
|
+
if (!existsSync(dbPath)) {
|
|
118
|
+
console.error(`❌ Database not found at ${dbPath}`);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
let db = null;
|
|
122
|
+
try {
|
|
123
|
+
console.log('\n🔍 Loading workspace-specific composers...');
|
|
124
|
+
const workspaceComposers = this.loadWorkspaceComposers(customDir);
|
|
125
|
+
if (workspaceComposers.size === 0) {
|
|
126
|
+
console.log('⚠️ No workspace-specific composers found. This workspace may not have any conversations.');
|
|
127
|
+
}
|
|
128
|
+
db = new Database(dbPath, { readonly: true });
|
|
129
|
+
// Load all required data from database
|
|
130
|
+
const { bubbleMap, bubbleWorkspaceMap } = this.loadBubbles(db);
|
|
131
|
+
const codeBlockDiffMap = this.loadCodeBlockDiffs(db);
|
|
132
|
+
const checkpointMap = this.loadCheckpoints(db);
|
|
133
|
+
const messageRequestContextMap = this.loadMessageContext(db);
|
|
134
|
+
// Process conversations and export
|
|
135
|
+
const allConversations = this.processConversations(db, workspacePath, workspaceComposers, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
|
|
136
|
+
// Export conversations to files
|
|
137
|
+
this.exportConversations(allConversations, workspaceDir, workspaceHash, baseOutputDir);
|
|
138
|
+
console.log(`\n🎉 Complete! Conversations exported to: ${baseOutputDir}`);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
const err = error;
|
|
143
|
+
console.error('❌ Error during parsing:', err);
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
if (db) {
|
|
148
|
+
db.close();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create an enhanced chat bubble with all extracted metadata and context
|
|
154
|
+
*
|
|
155
|
+
* Consolidates raw Cursor bubble data with associated tool results, console logs,
|
|
156
|
+
* context information, code diffs, file checkpoints, and code blocks into a single
|
|
157
|
+
* enhanced bubble structure. Extracts optional data from maps if available.
|
|
158
|
+
*
|
|
159
|
+
* @param type - Message type: 'ai' for assistant messages or 'user' for user messages
|
|
160
|
+
* @param text - Raw message text content from the bubble
|
|
161
|
+
* @param timestamp - Unix timestamp in milliseconds when the bubble was created
|
|
162
|
+
* @param bubble - Raw Cursor bubble object containing base message data
|
|
163
|
+
* @param bubbleId - Unique identifier for this bubble, used to look up associated data
|
|
164
|
+
* @param messageContextMap - Optional map of bubble IDs to RawCursorMessageRequestContext arrays
|
|
165
|
+
* @param codeBlockDiffMap - Optional map of bubble IDs to RawCursorCodeDiff arrays
|
|
166
|
+
* @param checkpointMap - Optional map of bubble IDs to RawCursorFileCheckpoint data
|
|
167
|
+
* @returns Enhanced bubble with all extracted metadata and context information
|
|
168
|
+
*/
|
|
169
|
+
// eslint-disable-next-line max-params
|
|
170
|
+
createEnhancedBubble(type, text, timestamp, bubble, bubbleId, messageContextMap, codeBlockDiffMap, checkpointMap) {
|
|
171
|
+
const enhanced = {
|
|
172
|
+
text,
|
|
173
|
+
timestamp,
|
|
174
|
+
type,
|
|
175
|
+
};
|
|
176
|
+
// Extract tool results
|
|
177
|
+
const toolResults = this.extractToolResults(bubble);
|
|
178
|
+
if (toolResults) {
|
|
179
|
+
enhanced.toolResults = toolResults;
|
|
180
|
+
}
|
|
181
|
+
// Extract console logs
|
|
182
|
+
const consoleLogs = this.extractConsoleLogs(bubble);
|
|
183
|
+
if (consoleLogs) {
|
|
184
|
+
enhanced.consoleLogs = consoleLogs;
|
|
185
|
+
}
|
|
186
|
+
// Extract context information
|
|
187
|
+
const context = this.extractContextInfo(bubble, messageContextMap, bubbleId);
|
|
188
|
+
if (context) {
|
|
189
|
+
enhanced.context = context;
|
|
190
|
+
}
|
|
191
|
+
// Extract code diffs (if this bubble is associated with diffs)
|
|
192
|
+
const codeDiffs = this.extractCodeDiffs(bubbleId, codeBlockDiffMap);
|
|
193
|
+
if (codeDiffs) {
|
|
194
|
+
enhanced.codeDiffs = codeDiffs;
|
|
195
|
+
}
|
|
196
|
+
// Extract file checkpoint
|
|
197
|
+
const fileCheckpoint = this.extractFileCheckpoint(bubbleId, checkpointMap);
|
|
198
|
+
if (fileCheckpoint) {
|
|
199
|
+
enhanced.fileCheckpoint = fileCheckpoint;
|
|
200
|
+
}
|
|
201
|
+
// Extract code blocks
|
|
202
|
+
const codeBlocks = this.extractCodeBlocks(bubble);
|
|
203
|
+
if (codeBlocks) {
|
|
204
|
+
enhanced.codeBlocks = codeBlocks;
|
|
205
|
+
}
|
|
206
|
+
return enhanced;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Export parsed conversations to JSON files in workspace-specific output directory
|
|
210
|
+
*
|
|
211
|
+
* Writes each conversation to a separate JSON file named by composer ID, containing
|
|
212
|
+
* bubbles, metadata (id, timestamp, title), workspace hash, and workspace paths.
|
|
213
|
+
* Logs file sizes in KB and exports all conversations with structured formatting.
|
|
214
|
+
*
|
|
215
|
+
* @param allConversations - Array of conversation objects with bubbles and metadata
|
|
216
|
+
* @param workspaceDir - Path to workspace directory for output files
|
|
217
|
+
* @param workspaceHash - Unique hash identifier for the workspace
|
|
218
|
+
* @param _outputDir - Root output directory (used for logging reference)
|
|
219
|
+
*/
|
|
220
|
+
exportConversations(allConversations, workspaceDir, workspaceHash, _outputDir) {
|
|
221
|
+
console.log('\n💾 Exporting conversations...');
|
|
222
|
+
console.log(`\n 📂 Workspace folder (${workspaceHash})`);
|
|
223
|
+
for (const conversation of allConversations) {
|
|
224
|
+
const filename = `${conversation.composerId}.json`;
|
|
225
|
+
const filepath = join(workspaceDir, filename);
|
|
226
|
+
const data = {
|
|
227
|
+
bubbles: conversation.bubbles,
|
|
228
|
+
id: conversation.composerId,
|
|
229
|
+
timestamp: conversation.timestamp,
|
|
230
|
+
title: conversation.name,
|
|
231
|
+
workspaceHash,
|
|
232
|
+
workspacePath: conversation.workspacePath,
|
|
233
|
+
};
|
|
234
|
+
writeFileSync(filepath, JSON.stringify(data, null, 2));
|
|
235
|
+
const fileSize = readFileSync(filepath).length;
|
|
236
|
+
const fileSizeKb = (fileSize / 1024).toFixed(FLOAT_PRECISION);
|
|
237
|
+
console.log(` ✅ ${conversation.name} (${fileSizeKb} KB)`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Extract the composer ID from a code block diff database key
|
|
242
|
+
*
|
|
243
|
+
* Parses the database key pattern "codeBlockDiff:chatId:diffId" to extract
|
|
244
|
+
* the chat/composer ID using regex pattern matching. Returns null if key format
|
|
245
|
+
* doesn't match expected pattern.
|
|
246
|
+
*
|
|
247
|
+
* @param key - Database key string in format "codeBlockDiff:chatId:diffId"
|
|
248
|
+
* @returns The extracted composer/chat ID, or null if pattern doesn't match
|
|
249
|
+
*/
|
|
250
|
+
extractChatIdFromCodeBlockDiffKey(key) {
|
|
251
|
+
const match = key.match(PATTERNS.CODE_BLOCK_DIFF_KEY);
|
|
252
|
+
return match ? match[1] : null;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Extract code blocks from a Cursor bubble's codeBlocks object
|
|
256
|
+
*
|
|
257
|
+
* Retrieves the code blocks map from a bubble if it exists and is non-empty.
|
|
258
|
+
* Code blocks are stored as key-value pairs where keys are block IDs and values
|
|
259
|
+
* are the code content strings. Returns undefined if bubble has no code blocks,
|
|
260
|
+
* codeBlocks property is not an object, or the object is empty.
|
|
261
|
+
*
|
|
262
|
+
* @param bubble - The raw Cursor bubble object to extract code blocks from
|
|
263
|
+
* @returns Object mapping code block IDs to code content strings, or undefined if none exist
|
|
264
|
+
*/
|
|
265
|
+
extractCodeBlocks(bubble) {
|
|
266
|
+
if (bubble.codeBlocks &&
|
|
267
|
+
typeof bubble.codeBlocks === 'object' &&
|
|
268
|
+
Object.keys(bubble.codeBlocks).length > 0) {
|
|
269
|
+
return bubble.codeBlocks;
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Extract code diffs associated with a specific bubble from the code block diff map
|
|
275
|
+
*
|
|
276
|
+
* Looks up code diffs for the given bubble ID in the codeBlockDiffMap. Code diffs
|
|
277
|
+
* represent changes made to files during the conversation, containing both the original
|
|
278
|
+
* and new versions relative to a base version (v0). Returns undefined if the map is
|
|
279
|
+
* unavailable, the bubble has no associated diffs, or the diffs array is empty.
|
|
280
|
+
* Normalizes diff objects to ensure all required fields (diffId, filePath,
|
|
281
|
+
* newModelDiffWrtV0, originalModelDiffWrtV0) are present, using empty string for missing diffId.
|
|
282
|
+
*
|
|
283
|
+
* @param bubbleId - Unique identifier of the bubble to look up diffs for
|
|
284
|
+
* @param codeBlockDiffMap - Optional map of bubble IDs to RawCursorCodeDiff arrays
|
|
285
|
+
* @returns Array of normalized RawCursorCodeDiff objects with all required fields, or undefined if none exist
|
|
286
|
+
*/
|
|
287
|
+
extractCodeDiffs(bubbleId, codeBlockDiffMap) {
|
|
288
|
+
if (!codeBlockDiffMap) {
|
|
289
|
+
return undefined;
|
|
290
|
+
}
|
|
291
|
+
const diffs = codeBlockDiffMap[bubbleId];
|
|
292
|
+
if (!diffs || !Array.isArray(diffs) || diffs.length === 0) {
|
|
293
|
+
return undefined;
|
|
294
|
+
}
|
|
295
|
+
return diffs.map((diff) => ({
|
|
296
|
+
diffId: diff.diffId || '',
|
|
297
|
+
filePath: diff.filePath,
|
|
298
|
+
newModelDiffWrtV0: diff.newModelDiffWrtV0,
|
|
299
|
+
originalModelDiffWrtV0: diff.originalModelDiffWrtV0,
|
|
300
|
+
}));
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Extract console logs from a Cursor bubble's consoleLogs array
|
|
304
|
+
*
|
|
305
|
+
* Retrieves the console logs array from a bubble if it exists and contains entries.
|
|
306
|
+
* Console logs capture terminal or debug output associated with a conversation turn.
|
|
307
|
+
* Returns undefined if the bubble has no console logs, consoleLogs property is not an array,
|
|
308
|
+
* or the array is empty. Used to preserve terminal/console output context in enhanced bubbles.
|
|
309
|
+
*
|
|
310
|
+
* @param bubble - The raw Cursor bubble object to extract console logs from
|
|
311
|
+
* @returns Array of console log strings, or undefined if none exist
|
|
312
|
+
*/
|
|
313
|
+
extractConsoleLogs(bubble) {
|
|
314
|
+
if (bubble.consoleLogs &&
|
|
315
|
+
Array.isArray(bubble.consoleLogs) &&
|
|
316
|
+
bubble.consoleLogs.length > 0) {
|
|
317
|
+
return bubble.consoleLogs;
|
|
318
|
+
}
|
|
319
|
+
return undefined;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Extract and consolidate context information from bubble and message context map
|
|
323
|
+
*
|
|
324
|
+
* Consolidates context data from two sources to create a comprehensive view of the
|
|
325
|
+
* conversation context:
|
|
326
|
+
* 1. Direct bubble properties: attachedFoldersListDirResults, cursorRules
|
|
327
|
+
* 2. Message context map data: gitStatus, knowledgeItems, todos, deletedFiles, terminalFiles
|
|
328
|
+
*
|
|
329
|
+
* When both sources provide the same field, preference is given to the message context map
|
|
330
|
+
* data as it tends to be more complete. Returns undefined if no context data is found from
|
|
331
|
+
* either source. The consolidated context helps understand the environment and state during
|
|
332
|
+
* the conversation turn.
|
|
333
|
+
*
|
|
334
|
+
* @param bubble - The raw Cursor bubble object with inline context data
|
|
335
|
+
* @param messageContextMap - Optional map of bubble IDs to RawCursorMessageRequestContext arrays
|
|
336
|
+
* @param bubbleId - Optional bubble ID to look up context in messageContextMap
|
|
337
|
+
* @returns RawCursorContextInfo object with consolidated context data, or undefined if no data found
|
|
338
|
+
*/
|
|
339
|
+
extractContextInfo(bubble, messageContextMap, bubbleId) {
|
|
340
|
+
const context = {};
|
|
341
|
+
let hasData = false;
|
|
342
|
+
// From bubble itself
|
|
343
|
+
if (bubble.attachedFoldersListDirResults) {
|
|
344
|
+
context.attachedFoldersListDirResults = bubble.attachedFoldersListDirResults;
|
|
345
|
+
hasData = true;
|
|
346
|
+
}
|
|
347
|
+
if (bubble.cursorRules && Array.isArray(bubble.cursorRules)) {
|
|
348
|
+
context.cursorRules = bubble.cursorRules;
|
|
349
|
+
hasData = true;
|
|
350
|
+
}
|
|
351
|
+
// From message request context if available
|
|
352
|
+
if (messageContextMap && bubbleId) {
|
|
353
|
+
const contexts = messageContextMap[bubbleId];
|
|
354
|
+
if (contexts && Array.isArray(contexts) && contexts.length > 0) {
|
|
355
|
+
const msgContext = contexts[0];
|
|
356
|
+
if (msgContext.gitStatusRaw) {
|
|
357
|
+
context.gitStatus = msgContext.gitStatusRaw;
|
|
358
|
+
hasData = true;
|
|
359
|
+
}
|
|
360
|
+
if (msgContext.attachedFoldersListDirResults) {
|
|
361
|
+
context.attachedFoldersListDirResults = msgContext.attachedFoldersListDirResults;
|
|
362
|
+
hasData = true;
|
|
363
|
+
}
|
|
364
|
+
if (msgContext.cursorRules) {
|
|
365
|
+
context.cursorRules = msgContext.cursorRules;
|
|
366
|
+
hasData = true;
|
|
367
|
+
}
|
|
368
|
+
if (msgContext.terminalFiles) {
|
|
369
|
+
context.terminalFiles = msgContext.terminalFiles;
|
|
370
|
+
hasData = true;
|
|
371
|
+
}
|
|
372
|
+
if (msgContext.knowledgeItems) {
|
|
373
|
+
context.knowledgeItems = msgContext.knowledgeItems;
|
|
374
|
+
hasData = true;
|
|
375
|
+
}
|
|
376
|
+
if (msgContext.todos) {
|
|
377
|
+
context.todos = msgContext.todos;
|
|
378
|
+
hasData = true;
|
|
379
|
+
}
|
|
380
|
+
if (msgContext.deletedFiles) {
|
|
381
|
+
context.deletedFiles = msgContext.deletedFiles;
|
|
382
|
+
hasData = true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return hasData ? context : undefined;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Extract file checkpoint state associated with a bubble from the checkpoint map
|
|
390
|
+
*
|
|
391
|
+
* Looks up the file checkpoint for a given bubble ID in the checkpoint map. File checkpoints
|
|
392
|
+
* capture the state of the file system at a particular conversation turn, including which files
|
|
393
|
+
* existed, were newly created, or were non-existent, as well as active inline diff information.
|
|
394
|
+
* Returns undefined if the map is unavailable or the bubble has no associated checkpoint.
|
|
395
|
+
*
|
|
396
|
+
* Normalizes the checkpoint object to ensure all array fields (files, newlyCreatedFolders,
|
|
397
|
+
* nonExistentFiles, activeInlineDiffs) are present, using empty arrays as defaults if not found.
|
|
398
|
+
* This normalization ensures consistent structure for downstream processing. The checkpointId
|
|
399
|
+
* field is intentionally excluded from the returned object.
|
|
400
|
+
*
|
|
401
|
+
* @param bubbleId - Unique identifier of the bubble to look up checkpoint for
|
|
402
|
+
* @param checkpointMap - Optional map of bubble IDs to RawCursorFileCheckpoint objects with checkpointId
|
|
403
|
+
* @returns Normalized RawCursorFileCheckpoint object with all required array fields, or undefined if none exists
|
|
404
|
+
*/
|
|
405
|
+
extractFileCheckpoint(bubbleId, checkpointMap) {
|
|
406
|
+
if (!checkpointMap || !checkpointMap[bubbleId]) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
const checkpoint = checkpointMap[bubbleId];
|
|
410
|
+
return {
|
|
411
|
+
activeInlineDiffs: checkpoint.activeInlineDiffs || [],
|
|
412
|
+
files: checkpoint.files || [],
|
|
413
|
+
inlineDiffNewlyCreatedResources: checkpoint.inlineDiffNewlyCreatedResources,
|
|
414
|
+
newlyCreatedFolders: checkpoint.newlyCreatedFolders || [],
|
|
415
|
+
nonExistentFiles: checkpoint.nonExistentFiles || [],
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Extract tool execution results from a bubble's toolFormerData object
|
|
420
|
+
*
|
|
421
|
+
* Parses tool execution metadata from the bubble, including tool name, status,
|
|
422
|
+
* parameters, results, and additional context. Returns undefined if bubble has no
|
|
423
|
+
* toolFormerData or is missing required fields (name, status). Safely parses JSON
|
|
424
|
+
* strings for params, rawArgs, and result fields that may contain serialized data.
|
|
425
|
+
*
|
|
426
|
+
* @param bubble - The raw Cursor bubble object containing tool execution data
|
|
427
|
+
* @returns RawCursorToolResult object with execution details, or undefined if no valid tool data
|
|
428
|
+
*/
|
|
429
|
+
extractToolResults(bubble) {
|
|
430
|
+
if (!bubble.toolFormerData || typeof bubble.toolFormerData !== 'object') {
|
|
431
|
+
return undefined;
|
|
432
|
+
}
|
|
433
|
+
const tool = bubble.toolFormerData;
|
|
434
|
+
// Only return if it has the required fields for a valid tool result
|
|
435
|
+
if (tool.name && tool.status) {
|
|
436
|
+
return {
|
|
437
|
+
additionalData: tool.additionalData,
|
|
438
|
+
modelCallId: tool.modelCallId || '',
|
|
439
|
+
name: tool.name,
|
|
440
|
+
params: this.safeParseJSON(tool.params) || {},
|
|
441
|
+
rawArgs: this.safeParseJSON(tool.rawArgs) || {},
|
|
442
|
+
result: this.safeParseJSON(tool.result) || {},
|
|
443
|
+
status: tool.status,
|
|
444
|
+
tool: tool.tool || 0,
|
|
445
|
+
toolCallId: tool.toolCallId || '',
|
|
446
|
+
toolIndex: tool.toolIndex || 0,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Load all bubbles from the database and build indexed maps
|
|
453
|
+
*
|
|
454
|
+
* Queries the database for all bubble entries matching the bubble ID pattern,
|
|
455
|
+
* parses JSON values, and builds maps for fast lookups. Creates bubble-to-workspace
|
|
456
|
+
* mapping and tracks unique workspace hashes. Skips invalid or unparseable entries.
|
|
457
|
+
*
|
|
458
|
+
* @param db - Better-sqlite3 database instance with cursorDiskKV table
|
|
459
|
+
* @returns Object containing: bubbleMap (ID -> bubble), bubbleWorkspaceMap (ID -> workspace hash), uniqueWorkspaces set
|
|
460
|
+
*/
|
|
461
|
+
loadBubbles(db) {
|
|
462
|
+
console.log('\n📝 Loading bubbles...');
|
|
463
|
+
const bubbleMap = {};
|
|
464
|
+
const bubbleWorkspaceMap = {};
|
|
465
|
+
const bubblesByWorkspace = {};
|
|
466
|
+
const bubbleRows = db.prepare(SQL_QUERIES.BUBBLE_ROWS).all();
|
|
467
|
+
for (const rowUntyped of bubbleRows) {
|
|
468
|
+
const row = rowUntyped;
|
|
469
|
+
const keyParts = row.key.split(':');
|
|
470
|
+
const bubbleWorkspaceHash = keyParts[1];
|
|
471
|
+
const bubbleId = keyParts[2];
|
|
472
|
+
try {
|
|
473
|
+
const bubble = JSON.parse(row.value);
|
|
474
|
+
if (!bubble || typeof bubble !== 'object')
|
|
475
|
+
continue;
|
|
476
|
+
bubbleMap[bubbleId] = bubble;
|
|
477
|
+
bubbleWorkspaceMap[bubbleId] = bubbleWorkspaceHash;
|
|
478
|
+
if (!bubblesByWorkspace[bubbleWorkspaceHash]) {
|
|
479
|
+
bubblesByWorkspace[bubbleWorkspaceHash] = new Set();
|
|
480
|
+
}
|
|
481
|
+
bubblesByWorkspace[bubbleWorkspaceHash].add(bubbleId);
|
|
482
|
+
}
|
|
483
|
+
catch {
|
|
484
|
+
// Skip parse errors
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const uniqueWorkspaces = new Set(Object.values(bubbleWorkspaceMap));
|
|
488
|
+
console.log(`✅ Loaded ${Object.keys(bubbleMap).length} total bubbles from ${uniqueWorkspaces.size} workspace(s)`);
|
|
489
|
+
return { bubbleMap, bubbleWorkspaceMap, uniqueWorkspaces };
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Load all file checkpoints from the database and build indexed map
|
|
493
|
+
*
|
|
494
|
+
* Queries the database for all checkpoint entries matching the checkpoint ID pattern,
|
|
495
|
+
* parses JSON values, and builds a map for fast lookups. Handles multiple checkpoints
|
|
496
|
+
* per composer by keeping the latest based on checkpoint ID string comparison.
|
|
497
|
+
* Skips invalid or unparseable entries.
|
|
498
|
+
*
|
|
499
|
+
* @param db - Better-sqlite3 database instance with cursorDiskKV table
|
|
500
|
+
* @returns Map of composer IDs to their RawCursorFileCheckpoint objects with checkpointId field
|
|
501
|
+
*/
|
|
502
|
+
loadCheckpoints(db) {
|
|
503
|
+
console.log('📝 Loading checkpoints...');
|
|
504
|
+
const checkpointMap = {};
|
|
505
|
+
const checkpointRows = db.prepare(SQL_QUERIES.CHECKPOINT_ROWS).all();
|
|
506
|
+
for (const rowUntyped of checkpointRows) {
|
|
507
|
+
const row = rowUntyped;
|
|
508
|
+
const parts = row.key.split(':');
|
|
509
|
+
if (parts.length < 3)
|
|
510
|
+
continue;
|
|
511
|
+
const composerId = parts[1];
|
|
512
|
+
const checkpointId = parts[2];
|
|
513
|
+
try {
|
|
514
|
+
const checkpoint = JSON.parse(row.value);
|
|
515
|
+
if (!checkpointMap[composerId] || checkpointId > (checkpointMap[composerId].checkpointId || '')) {
|
|
516
|
+
checkpointMap[composerId] = {
|
|
517
|
+
...checkpoint,
|
|
518
|
+
checkpointId,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
catch {
|
|
523
|
+
// Skip parse errors
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
console.log(`✅ Loaded checkpoints`);
|
|
527
|
+
return checkpointMap;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Load all code block diffs from the database and build indexed map
|
|
531
|
+
*
|
|
532
|
+
* Queries the database for all code block diff entries, extracts chat/composer IDs
|
|
533
|
+
* from keys, parses JSON values, and groups diffs by composer ID. Each diff includes
|
|
534
|
+
* the diffId extracted from the database key. Skips invalid or unparseable entries.
|
|
535
|
+
*
|
|
536
|
+
* @param db - Better-sqlite3 database instance with cursorDiskKV table
|
|
537
|
+
* @returns Map of composer IDs to arrays of RawCursorCodeDiff objects with diffId field
|
|
538
|
+
*/
|
|
539
|
+
loadCodeBlockDiffs(db) {
|
|
540
|
+
console.log('📝 Loading code diffs...');
|
|
541
|
+
const codeBlockDiffMap = {};
|
|
542
|
+
const codeBlockDiffRows = db.prepare(SQL_QUERIES.CODE_BLOCK_DIFF_ROWS).all();
|
|
543
|
+
for (const rowUntyped of codeBlockDiffRows) {
|
|
544
|
+
const row = rowUntyped;
|
|
545
|
+
const chatId = this.extractChatIdFromCodeBlockDiffKey(row.key);
|
|
546
|
+
if (!chatId)
|
|
547
|
+
continue;
|
|
548
|
+
try {
|
|
549
|
+
const codeBlockDiff = JSON.parse(row.value);
|
|
550
|
+
if (!codeBlockDiffMap[chatId])
|
|
551
|
+
codeBlockDiffMap[chatId] = [];
|
|
552
|
+
codeBlockDiffMap[chatId].push({
|
|
553
|
+
...codeBlockDiff,
|
|
554
|
+
diffId: row.key.split(':')[2],
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
// Skip parse errors
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
console.log(`✅ Loaded ${Object.keys(codeBlockDiffMap).length} diff groups`);
|
|
562
|
+
return codeBlockDiffMap;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Load all message request context from the database and build indexed map
|
|
566
|
+
*
|
|
567
|
+
* Queries the database for all message request context entries, parses JSON values,
|
|
568
|
+
* and groups contexts by composer ID. Extracts context ID from key parts or uses
|
|
569
|
+
* default context ID if not present. Skips invalid or unparseable entries and keys
|
|
570
|
+
* with insufficient format.
|
|
571
|
+
*
|
|
572
|
+
* @param db - Better-sqlite3 database instance with cursorDiskKV table
|
|
573
|
+
* @returns Map of composer IDs to arrays of RawCursorMessageRequestContext objects with contextId field
|
|
574
|
+
*/
|
|
575
|
+
loadMessageContext(db) {
|
|
576
|
+
console.log('📝 Loading message context...');
|
|
577
|
+
const messageRequestContextMap = {};
|
|
578
|
+
const messageRequestContextRows = db.prepare(SQL_QUERIES.MESSAGE_REQUEST_CONTEXT_ROWS).all();
|
|
579
|
+
for (const rowUntyped of messageRequestContextRows) {
|
|
580
|
+
const row = rowUntyped;
|
|
581
|
+
const parts = row.key.split(':');
|
|
582
|
+
if (parts.length < 2)
|
|
583
|
+
continue;
|
|
584
|
+
const composerId = parts[1];
|
|
585
|
+
const contextId = parts.length >= 3 ? parts[2] : DEFAULT_CONTEXT_ID;
|
|
586
|
+
try {
|
|
587
|
+
const context = JSON.parse(row.value);
|
|
588
|
+
if (!messageRequestContextMap[composerId])
|
|
589
|
+
messageRequestContextMap[composerId] = [];
|
|
590
|
+
messageRequestContextMap[composerId].push({
|
|
591
|
+
...context,
|
|
592
|
+
bubbleId: context.bubbleId,
|
|
593
|
+
contextId,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
catch {
|
|
597
|
+
// Skip parse errors
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
console.log(`✅ Loaded context for ${Object.keys(messageRequestContextMap).length} composers`);
|
|
601
|
+
return messageRequestContextMap;
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Load composer IDs that are specific to a workspace
|
|
605
|
+
*
|
|
606
|
+
* Reads the workspace's state.vscdb database, extracts composer data from the
|
|
607
|
+
* ItemTable, and builds a set of composer IDs that belong to this workspace.
|
|
608
|
+
* Returns empty set if database or composer data is not found. Logs warnings
|
|
609
|
+
* if database or data is unavailable.
|
|
610
|
+
*
|
|
611
|
+
* @param workspacePath - Path to the workspace directory containing state.vscdb
|
|
612
|
+
* @returns Set of composer IDs that belong to this workspace
|
|
613
|
+
*/
|
|
614
|
+
loadWorkspaceComposers(workspacePath) {
|
|
615
|
+
const workspaceComposers = new Set();
|
|
616
|
+
try {
|
|
617
|
+
const workspaceDbPath = join(workspacePath, WORKSPACE_DB_FILE);
|
|
618
|
+
if (!existsSync(workspaceDbPath)) {
|
|
619
|
+
console.log(`⚠️ Workspace database not found at ${workspaceDbPath}`);
|
|
620
|
+
return workspaceComposers;
|
|
621
|
+
}
|
|
622
|
+
const wsDb = new Database(workspaceDbPath, { readonly: true });
|
|
623
|
+
try {
|
|
624
|
+
const result = wsDb
|
|
625
|
+
.prepare(SQL_QUERIES.COMPOSER_DATA)
|
|
626
|
+
.get();
|
|
627
|
+
if (!result || !result.value) {
|
|
628
|
+
console.log('⚠️ No composer data found in workspace ItemTable');
|
|
629
|
+
return workspaceComposers;
|
|
630
|
+
}
|
|
631
|
+
const composerData = JSON.parse(result.value.toString());
|
|
632
|
+
const allComposers = composerData.allComposers || [];
|
|
633
|
+
for (const composer of allComposers) {
|
|
634
|
+
const composerData = composer;
|
|
635
|
+
if (composerData.composerId) {
|
|
636
|
+
workspaceComposers.add(composerData.composerId);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
console.log(`✅ Loaded ${workspaceComposers.size} workspace-specific composers from ItemTable`);
|
|
640
|
+
}
|
|
641
|
+
finally {
|
|
642
|
+
wsDb.close();
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
catch (error) {
|
|
646
|
+
console.log(`⚠️ Could not load workspace composers:`, error instanceof Error ? error.message : String(error));
|
|
647
|
+
}
|
|
648
|
+
return workspaceComposers;
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Log parsing statistics for processed conversations
|
|
652
|
+
*
|
|
653
|
+
* Outputs summary information about conversation parsing results, including both successful
|
|
654
|
+
* parses and various skip conditions. Helps users understand why certain conversations were
|
|
655
|
+
* not included in the output. The function displays:
|
|
656
|
+
* - Total successfully parsed conversations
|
|
657
|
+
* - Conversations skipped because they don't belong to this workspace
|
|
658
|
+
* - Conversations skipped due to having no extractable bubbles (empty conversations)
|
|
659
|
+
* - Conversations skipped due to missing conversation headers (malformed data)
|
|
660
|
+
*
|
|
661
|
+
* Omits zero-count skip reasons from output for cleaner, more focused logging that only
|
|
662
|
+
* shows relevant information.
|
|
663
|
+
*
|
|
664
|
+
* @param parsed - Number of successfully parsed conversations
|
|
665
|
+
* @param skippedNotInWorkspace - Number of conversations skipped (not in this workspace)
|
|
666
|
+
* @param skippedNoBubbles - Number of conversations skipped (no extractable bubbles)
|
|
667
|
+
* @param skippedNoHeaders - Number of conversations skipped (no conversation headers)
|
|
668
|
+
*/
|
|
669
|
+
logConversationStats(parsed, skippedNotInWorkspace, skippedNoBubbles, skippedNoHeaders) {
|
|
670
|
+
console.log(`\n✅ Parsed ${parsed} conversations`);
|
|
671
|
+
if (skippedNotInWorkspace > 0) {
|
|
672
|
+
console.log(`⚠️ Skipped ${skippedNotInWorkspace} conversations not in this workspace`);
|
|
673
|
+
}
|
|
674
|
+
if (skippedNoBubbles > 0) {
|
|
675
|
+
console.log(`⚠️ Skipped ${skippedNoBubbles} conversations with no extractable bubbles`);
|
|
676
|
+
}
|
|
677
|
+
if (skippedNoHeaders > 0) {
|
|
678
|
+
console.log(`⚠️ Skipped ${skippedNoHeaders} conversations with no headers`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Process conversation headers and create enhanced bubbles from raw data
|
|
683
|
+
*
|
|
684
|
+
* This is a core transformation function that converts raw Cursor conversation headers and
|
|
685
|
+
* bubble data into enriched, enhanced bubble objects ready for export. The function:
|
|
686
|
+
* 1. Iterates through conversation headers (which contain bubble IDs and message types)
|
|
687
|
+
* 2. Looks up corresponding raw bubbles by ID in the bubbleMap
|
|
688
|
+
* 3. Determines message type (user vs assistant) based on header type field
|
|
689
|
+
* 4. Creates enhanced bubbles by extracting and consolidating metadata from multiple sources:
|
|
690
|
+
* - Tool results, console logs, code blocks from the bubble itself
|
|
691
|
+
* - Context information from messageRequestContextMap
|
|
692
|
+
* - Code diffs from codeBlockDiffMap
|
|
693
|
+
* - File checkpoints from checkpointMap
|
|
694
|
+
* 5. Filters out empty bubbles (no text, tool results, or console logs) to keep only meaningful content
|
|
695
|
+
* 6. Tracks unique workspace hashes that bubbles belong to for workspace association
|
|
696
|
+
*
|
|
697
|
+
* This process enriches basic bubble data with all available context and metadata, creating
|
|
698
|
+
* a comprehensive representation of each conversation turn.
|
|
699
|
+
*
|
|
700
|
+
* @param conversationHeaders - Array of header objects containing bubble IDs and types (1=user, other=ai)
|
|
701
|
+
* @param bubbleMap - Map of bubble IDs to raw RawCursorBubbleRaw objects
|
|
702
|
+
* @param bubbleWorkspaceMap - Map of bubble IDs to their workspace hash identifiers
|
|
703
|
+
* @param messageRequestContextMap - Map of bubble IDs to RawCursorMessageRequestContext arrays
|
|
704
|
+
* @param codeBlockDiffMap - Map of bubble IDs to RawCursorCodeDiff arrays
|
|
705
|
+
* @param checkpointMap - Map of bubble IDs to RawCursorFileCheckpoint objects with checkpointId
|
|
706
|
+
* @returns Object containing enhanced bubbles array and set of workspace hashes used by these bubbles
|
|
707
|
+
*/
|
|
708
|
+
// eslint-disable-next-line max-params
|
|
709
|
+
processBubbleHeaders(conversationHeaders, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap) {
|
|
710
|
+
const bubbles = [];
|
|
711
|
+
const usedWorkspaces = new Set();
|
|
712
|
+
for (const header of conversationHeaders) {
|
|
713
|
+
const bubbleId = header.bubbleId;
|
|
714
|
+
const bubble = bubbleMap?.[bubbleId];
|
|
715
|
+
if (!bubble)
|
|
716
|
+
continue;
|
|
717
|
+
const bubbleWs = bubbleWorkspaceMap[bubbleId];
|
|
718
|
+
if (bubbleWs) {
|
|
719
|
+
usedWorkspaces.add(bubbleWs);
|
|
720
|
+
}
|
|
721
|
+
const isUser = header.type === HEADER_TYPE_USER;
|
|
722
|
+
const messageType = isUser ? 'user' : 'ai';
|
|
723
|
+
const text = bubble.text?.trim() || '';
|
|
724
|
+
const enhancedBubble = this.createEnhancedBubble(messageType, text, bubble.timestamp || Date.now(), bubble, bubbleId, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
|
|
725
|
+
if (enhancedBubble.text.trim() || enhancedBubble.toolResults || enhancedBubble.consoleLogs) {
|
|
726
|
+
bubbles.push(enhancedBubble);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return { bubbles, usedWorkspaces };
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Load and process all conversations from the database for a specific workspace
|
|
733
|
+
*
|
|
734
|
+
* Queries the database for all composer conversation data, filters to workspace-specific
|
|
735
|
+
* composers, parses each conversation's headers, creates enhanced bubbles, and returns
|
|
736
|
+
* conversation objects with metadata. Tracks and logs statistics on parsed vs skipped
|
|
737
|
+
* conversations (not in workspace, no headers, no extractable bubbles).
|
|
738
|
+
*
|
|
739
|
+
* @param db - Better-sqlite3 database instance
|
|
740
|
+
* @param workspacePath - Path to the workspace directory
|
|
741
|
+
* @param workspaceComposers - Set of composer IDs belonging to this workspace
|
|
742
|
+
* @param bubbleMap - Map of bubble IDs to raw RawCursorBubbleRaw objects
|
|
743
|
+
* @param bubbleWorkspaceMap - Map of bubble IDs to their workspace hashes
|
|
744
|
+
* @param messageRequestContextMap - Map of bubble IDs to RawCursorMessageRequestContext arrays
|
|
745
|
+
* @param codeBlockDiffMap - Map of bubble IDs to RawCursorCodeDiff arrays
|
|
746
|
+
* @param checkpointMap - Map of bubble IDs to RawCursorFileCheckpoint objects
|
|
747
|
+
* @returns Array of conversation objects with bubbles and metadata
|
|
748
|
+
*/
|
|
749
|
+
// eslint-disable-next-line max-params
|
|
750
|
+
processConversations(db, workspacePath, workspaceComposers, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap) {
|
|
751
|
+
console.log('📝 Loading conversations...');
|
|
752
|
+
const composerRows = db.prepare(SQL_QUERIES.COMPOSER_ROWS).all();
|
|
753
|
+
console.log(`📊 Found ${composerRows.length} conversations`);
|
|
754
|
+
let skippedNoHeaders = 0;
|
|
755
|
+
let skippedNoBubbles = 0;
|
|
756
|
+
let skippedNotInWorkspace = 0;
|
|
757
|
+
const allConversations = [];
|
|
758
|
+
for (const rowUntyped of composerRows) {
|
|
759
|
+
const row = rowUntyped;
|
|
760
|
+
const composerId = row.key.split(':')[1];
|
|
761
|
+
if (!workspaceComposers.has(composerId)) {
|
|
762
|
+
skippedNotInWorkspace++;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
try {
|
|
766
|
+
const composerData = JSON.parse(row.value);
|
|
767
|
+
const conversationHeaders = composerData.fullConversationHeadersOnly || [];
|
|
768
|
+
if (conversationHeaders.length === 0) {
|
|
769
|
+
skippedNoHeaders++;
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
const { bubbles } = this.processBubbleHeaders(conversationHeaders, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
|
|
773
|
+
if (bubbles.length > 0) {
|
|
774
|
+
const conversationName = composerData.name || `Conversation ${composerId.slice(0, COMPOSER_ID_PREVIEW_LENGTH)}`;
|
|
775
|
+
allConversations.push({
|
|
776
|
+
bubbles,
|
|
777
|
+
composerId,
|
|
778
|
+
name: conversationName,
|
|
779
|
+
timestamp: composerData.lastUpdatedAt || composerData.createdAt,
|
|
780
|
+
workspacePath,
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
skippedNoBubbles++;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
catch (error) {
|
|
788
|
+
console.error(`⚠️ Error parsing conversation ${composerId}:`, error);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
this.logConversationStats(allConversations.length, skippedNotInWorkspace, skippedNoBubbles, skippedNoHeaders);
|
|
792
|
+
return allConversations;
|
|
793
|
+
}
|
|
794
|
+
// ============================================================================
|
|
795
|
+
// PRIVATE UTILITY METHODS
|
|
796
|
+
// ============================================================================
|
|
797
|
+
/**
|
|
798
|
+
* Safely parse JSON strings with graceful fallback to original value
|
|
799
|
+
*
|
|
800
|
+
* Attempts to parse a string as JSON. If parsing succeeds, returns the parsed object.
|
|
801
|
+
* If parsing fails or value is not a string, returns the original value unchanged.
|
|
802
|
+
* Used for fields that may contain either pre-parsed objects or JSON strings.
|
|
803
|
+
*
|
|
804
|
+
* @param value - Value to parse, may be string, object, or any other type
|
|
805
|
+
* @returns Parsed JSON object if string input, original value otherwise
|
|
806
|
+
*/
|
|
807
|
+
safeParseJSON(value) {
|
|
808
|
+
if (typeof value === 'string') {
|
|
809
|
+
try {
|
|
810
|
+
return JSON.parse(value);
|
|
811
|
+
}
|
|
812
|
+
catch {
|
|
813
|
+
return value; // Return original string if parsing fails
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return value; // Already parsed or not a string
|
|
817
|
+
}
|
|
818
|
+
}
|