byterover-cli 0.2.0 → 0.3.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 +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 +53 -2
- package/dist/commands/init.js +279 -66
- package/dist/commands/login.js +9 -4
- package/dist/commands/logout.d.ts +16 -0
- package/dist/commands/logout.js +61 -0
- 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 +4 -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/i-rule-template-service.d.ts +0 -4
- package/dist/core/interfaces/i-rule-template-service.js +1 -4
- 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/rule/constants.d.ts +4 -0
- package/dist/infra/rule/constants.js +4 -0
- package/dist/infra/rule/rule-template-service.js +1 -1
- package/dist/infra/rule/rule-writer-service.js +1 -5
- 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 -93
- 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 +422 -142
- package/package.json +29 -10
- 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,782 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Raw Service
|
|
3
|
+
* Consolidates CodexParser + CodexRawParser
|
|
4
|
+
* Parses JSONL transcript files from ~/.codex/sessions/
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
7
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
8
|
+
import path, { join } from 'node:path';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// CONSTANTS
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const TITLE_MAX_LENGTH = 100;
|
|
13
|
+
const SUMMARY_TEXT_TYPE = 'summary_text';
|
|
14
|
+
/**
|
|
15
|
+
* Codex Raw Service
|
|
16
|
+
* Handles extraction of Codex sessions from JSONL transcript files
|
|
17
|
+
*/
|
|
18
|
+
export class CodexRawService {
|
|
19
|
+
ide;
|
|
20
|
+
/**
|
|
21
|
+
* Initialize Codex Raw Service
|
|
22
|
+
*
|
|
23
|
+
* @param ide - The IDE type (Codex)
|
|
24
|
+
*/
|
|
25
|
+
constructor(ide) {
|
|
26
|
+
this.ide = ide;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Main entry point - Parse Codex sessions from a custom directory
|
|
30
|
+
*
|
|
31
|
+
* Parses all JSONL transcript files from a Codex sessions directory,
|
|
32
|
+
* extracts session information, and writes normalized JSON files to output directory.
|
|
33
|
+
* Organizes output by date (YYYY-MM-DD) matching Codex's original directory structure.
|
|
34
|
+
* Returns success status.
|
|
35
|
+
*
|
|
36
|
+
* @param customDir - Path to directory containing Codex session files
|
|
37
|
+
* @param outputDir - Optional output directory (defaults to process.cwd()/.brv/logs/{ide}/raw)
|
|
38
|
+
* @returns Promise resolving to true if parsing succeeded, false otherwise
|
|
39
|
+
*/
|
|
40
|
+
async parse(customDir, outputDir) {
|
|
41
|
+
const baseOutputDir = outputDir || path.join(process.cwd(), `.brv/logs/${this.ide}/raw`);
|
|
42
|
+
console.log('🔍 Starting Codex conversation parsing...');
|
|
43
|
+
console.log(`📁 Custom directory: ${customDir}`);
|
|
44
|
+
try {
|
|
45
|
+
// Parse all sessions from the Codex directory
|
|
46
|
+
const sessions = await this.parseSessionDirectory(customDir);
|
|
47
|
+
if (sessions.length === 0) {
|
|
48
|
+
console.log('ℹ️ No Codex sessions found');
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
console.log(`\n✅ Found ${sessions.length} Codex sessions`);
|
|
52
|
+
// Organize sessions by date (YYYY-MM-DD), matching Codex's original directory structure
|
|
53
|
+
const sessionsByDate = {};
|
|
54
|
+
for (const session of sessions) {
|
|
55
|
+
// Extract date from session's startedAt timestamp
|
|
56
|
+
const date = new Date(session.metadata.startedAt);
|
|
57
|
+
const year = date.getFullYear();
|
|
58
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
59
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
60
|
+
const datePrefix = `${year}-${month}-${day}`;
|
|
61
|
+
if (!sessionsByDate[datePrefix]) {
|
|
62
|
+
sessionsByDate[datePrefix] = [];
|
|
63
|
+
}
|
|
64
|
+
sessionsByDate[datePrefix].push({
|
|
65
|
+
...session,
|
|
66
|
+
datePrefix,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
console.log(`\n📁 Organized into ${Object.keys(sessionsByDate).length} date(s)`);
|
|
70
|
+
// Export sessions organized by date
|
|
71
|
+
console.log('\n💾 Exporting sessions by date...');
|
|
72
|
+
for (const [datePrefix, dateSessions] of Object.entries(sessionsByDate).sort()) {
|
|
73
|
+
const dateDir = path.join(baseOutputDir, datePrefix);
|
|
74
|
+
if (!existsSync(dateDir)) {
|
|
75
|
+
mkdirSync(dateDir, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
console.log(`\n 📅 ${datePrefix}`);
|
|
78
|
+
// Export session files for this date
|
|
79
|
+
for (const session of dateSessions) {
|
|
80
|
+
const filename = `${session.id}.json`;
|
|
81
|
+
const filepath = path.join(dateDir, filename);
|
|
82
|
+
writeFileSync(filepath, JSON.stringify(session, null, 2));
|
|
83
|
+
const fileSize = readFileSync(filepath).length;
|
|
84
|
+
const fileSizeKb = (fileSize / 1024).toFixed(1);
|
|
85
|
+
const truncatedTitle = session.title.slice(0, 50);
|
|
86
|
+
console.log(` ✅ ${truncatedTitle}${session.title.length > 50 ? '...' : ''} (${fileSizeKb} KB)`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
console.log(`\n🎉 Codex export complete! Sessions exported to: ${outputDir}`);
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('❌ Error during parsing:', error);
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Build token usage object with optional cache tokens
|
|
99
|
+
*
|
|
100
|
+
* Constructs a token usage metrics object, including cache tokens only if they're
|
|
101
|
+
* greater than zero. Calculates total tokens as sum of input and output.
|
|
102
|
+
*
|
|
103
|
+
* @param cacheTokens - Number of cached input tokens
|
|
104
|
+
* @param inputTokens - Number of input tokens used
|
|
105
|
+
* @param outputTokens - Number of output tokens generated
|
|
106
|
+
* @returns Token usage object with optional cacheTokens and calculated total
|
|
107
|
+
*/
|
|
108
|
+
buildTokenUsageObject(cacheTokens, inputTokens, outputTokens) {
|
|
109
|
+
return {
|
|
110
|
+
cacheTokens: cacheTokens > 0 ? cacheTokens : undefined,
|
|
111
|
+
inputTokens,
|
|
112
|
+
outputTokens,
|
|
113
|
+
totalTokens: inputTokens + outputTokens,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Calculate aggregate session metadata from transcript entries
|
|
118
|
+
*
|
|
119
|
+
* Aggregates token usage, counts message types, extracts timestamps and workspace information.
|
|
120
|
+
* Returns comprehensive metadata including token costs, message counts, duration, and session details.
|
|
121
|
+
*
|
|
122
|
+
* @param entries - Array of transcript entries from JSONL file
|
|
123
|
+
* @param messages - Parsed messages array (for count verification)
|
|
124
|
+
* @param logPath - Log file path (used to extract workspace information)
|
|
125
|
+
* @param sessionMeta - Extracted session metadata (may be null)
|
|
126
|
+
* @returns RawCodexSessionMetadata object with aggregated statistics
|
|
127
|
+
*/
|
|
128
|
+
calculateMetadata(entries, messages, logPath, sessionMeta) {
|
|
129
|
+
const { cacheTokens, inputTokens, outputTokens } = this.calculateTokenUsage(entries);
|
|
130
|
+
const { assistantCount, userCount } = this.countMessageTypes(messages);
|
|
131
|
+
const { endedAt, startedAt } = this.extractTimestamps(entries, sessionMeta);
|
|
132
|
+
const duration = new Date(endedAt || new Date()).getTime() - new Date(startedAt).getTime();
|
|
133
|
+
return {
|
|
134
|
+
assistantMessageCount: assistantCount,
|
|
135
|
+
cliVersion: sessionMeta?.cli_version,
|
|
136
|
+
duration,
|
|
137
|
+
endedAt,
|
|
138
|
+
messageCount: messages.length,
|
|
139
|
+
model: sessionMeta?.model_provider || 'unknown',
|
|
140
|
+
modelProvider: sessionMeta?.model_provider,
|
|
141
|
+
originator: sessionMeta?.originator,
|
|
142
|
+
sessionId: this.extractSessionId(logPath),
|
|
143
|
+
source: sessionMeta?.source,
|
|
144
|
+
startedAt,
|
|
145
|
+
tokenUsage: this.buildTokenUsageObject(cacheTokens, inputTokens, outputTokens),
|
|
146
|
+
userMessageCount: userCount,
|
|
147
|
+
workspace: this.extractWorkspace(logPath, sessionMeta),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Calculate total token usage from transcript entries
|
|
152
|
+
*
|
|
153
|
+
* Aggregates token counts from all token_count event messages in the transcript.
|
|
154
|
+
* Includes input tokens, output tokens, and cached input tokens.
|
|
155
|
+
*
|
|
156
|
+
* @param entries - Array of transcript entries to analyze
|
|
157
|
+
* @returns Object with aggregated cacheTokens, inputTokens, and outputTokens
|
|
158
|
+
*/
|
|
159
|
+
calculateTokenUsage(entries) {
|
|
160
|
+
let inputTokens = 0;
|
|
161
|
+
let outputTokens = 0;
|
|
162
|
+
let cacheTokens = 0;
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (!this.isTokenCountEntry(entry)) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const usage = entry.payload?.info;
|
|
168
|
+
if (usage?.total_token_usage) {
|
|
169
|
+
const tokenUsage = usage.total_token_usage;
|
|
170
|
+
inputTokens += typeof tokenUsage?.input_tokens === 'number' ? tokenUsage.input_tokens : 0;
|
|
171
|
+
outputTokens += typeof tokenUsage?.output_tokens === 'number' ? tokenUsage.output_tokens : 0;
|
|
172
|
+
cacheTokens += typeof tokenUsage?.cached_input_tokens === 'number' ? tokenUsage.cached_input_tokens : 0;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { cacheTokens, inputTokens, outputTokens };
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Convert Codex content block to normalized content block
|
|
179
|
+
*
|
|
180
|
+
* Transforms a Codex-specific content block into a standardized ContentBlock format.
|
|
181
|
+
* Handles tool_use blocks (preserves id, input, name) and text blocks (normalizes types).
|
|
182
|
+
* Converts input_text type to text type for consistency.
|
|
183
|
+
*
|
|
184
|
+
* @param block - Codex content block to convert
|
|
185
|
+
* @returns Normalized ContentBlock object
|
|
186
|
+
*/
|
|
187
|
+
convertCodexContentBlockToContentBlock(block) {
|
|
188
|
+
const contentBlock = {};
|
|
189
|
+
if (block.type === 'tool_use') {
|
|
190
|
+
contentBlock.id = `tool_${Date.now()}`;
|
|
191
|
+
if (block.input)
|
|
192
|
+
contentBlock.input = block.input;
|
|
193
|
+
if (block.name)
|
|
194
|
+
contentBlock.name = block.name;
|
|
195
|
+
}
|
|
196
|
+
else if (block.text) {
|
|
197
|
+
contentBlock.text = block.text;
|
|
198
|
+
}
|
|
199
|
+
contentBlock.type = block.type === 'input_text' ? 'text' : block.type;
|
|
200
|
+
return contentBlock;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Convert Codex transcript entries to normalized messages
|
|
204
|
+
*
|
|
205
|
+
* Transforms raw JSONL transcript entries (messages, function calls, reasoning, token counts) into
|
|
206
|
+
* standardized RawCodexRawMessage objects. Tracks token usage and reasoning context across entries,
|
|
207
|
+
* maintaining order and relationships between tool calls and responses.
|
|
208
|
+
*
|
|
209
|
+
* @param entries - Array of transcript entries from JSONL file
|
|
210
|
+
* @returns Array of normalized RawCodexRawMessage objects
|
|
211
|
+
*/
|
|
212
|
+
convertToMessages(entries) {
|
|
213
|
+
const messages = [];
|
|
214
|
+
let currentTokenUsage = null;
|
|
215
|
+
let currentReasoning = null;
|
|
216
|
+
for (const entry of entries) {
|
|
217
|
+
// Track token usage and reasoning from event messages
|
|
218
|
+
if (entry.type === 'event_msg' && entry.payload && this.isEventPayload(entry.payload)) {
|
|
219
|
+
if (entry.payload.type === 'token_count' && entry.payload.info) {
|
|
220
|
+
currentTokenUsage = entry.payload.info.total_token_usage;
|
|
221
|
+
}
|
|
222
|
+
if (entry.payload.type === 'agent_reasoning' && entry.payload.text) {
|
|
223
|
+
currentReasoning = entry.payload.text;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Process response items (messages, reasoning, function calls)
|
|
227
|
+
if (entry.type === 'response_item' && entry.payload && this.isResponsePayload(entry.payload)) {
|
|
228
|
+
const { payload } = entry;
|
|
229
|
+
const timestamp = entry.timestamp || new Date().toISOString();
|
|
230
|
+
switch (payload.type) {
|
|
231
|
+
case 'function_call': {
|
|
232
|
+
this.processFunctionCall(payload, messages);
|
|
233
|
+
break;
|
|
234
|
+
}
|
|
235
|
+
case 'function_call_output': {
|
|
236
|
+
this.processFunctionCallOutput(payload, messages);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case 'message': {
|
|
240
|
+
this.processMessage(payload, messages, timestamp, currentTokenUsage, currentReasoning);
|
|
241
|
+
// Reset reasoning after message
|
|
242
|
+
currentReasoning = null;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case 'reasoning': {
|
|
246
|
+
const newReasoning = this.processReasoningPayload(payload);
|
|
247
|
+
if (newReasoning) {
|
|
248
|
+
currentReasoning = newReasoning;
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
// No default
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return messages;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Convert transcript entry to raw entry format
|
|
260
|
+
*
|
|
261
|
+
* Transforms a transcript entry into the raw entry storage format, filtering entries without payloads
|
|
262
|
+
* and converting ISO timestamp strings to millisecond timestamps. Validates entry types and applies
|
|
263
|
+
* fallback type for invalid entries.
|
|
264
|
+
*
|
|
265
|
+
* @param entry - Transcript entry to convert
|
|
266
|
+
* @returns Converted RawCodexRawEntry object, or null if entry has no payload
|
|
267
|
+
*/
|
|
268
|
+
convertTranscriptEntryToRawEntry(entry) {
|
|
269
|
+
// Filter entries that don't have a payload
|
|
270
|
+
if (!entry.payload) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
// Convert timestamp from string to number
|
|
274
|
+
const timestamp = entry.timestamp
|
|
275
|
+
? new Date(entry.timestamp).getTime()
|
|
276
|
+
: Date.now();
|
|
277
|
+
return {
|
|
278
|
+
payload: entry.payload,
|
|
279
|
+
timestamp,
|
|
280
|
+
type: (entry.type === 'event_msg' || entry.type === 'response_item' || entry.type === 'session_meta' || entry.type === 'turn_context')
|
|
281
|
+
? entry.type
|
|
282
|
+
: 'response_item', // Default fallback
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Count user and assistant messages in a message array
|
|
287
|
+
*
|
|
288
|
+
* Iterates through messages and counts the total number of user and assistant messages.
|
|
289
|
+
* Used for metadata tracking and session statistics.
|
|
290
|
+
*
|
|
291
|
+
* @param messages - Array of messages to count
|
|
292
|
+
* @returns Object with assistantCount and userCount totals
|
|
293
|
+
*/
|
|
294
|
+
countMessageTypes(messages) {
|
|
295
|
+
let userCount = 0;
|
|
296
|
+
let assistantCount = 0;
|
|
297
|
+
for (const message of messages) {
|
|
298
|
+
if (message.type === 'user')
|
|
299
|
+
userCount++;
|
|
300
|
+
if (message.type === 'assistant')
|
|
301
|
+
assistantCount++;
|
|
302
|
+
}
|
|
303
|
+
return { assistantCount, userCount };
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Extract and normalize content blocks from message content
|
|
307
|
+
*
|
|
308
|
+
* Handles multiple content formats: null/undefined (empty array), strings (wrapped as text block),
|
|
309
|
+
* arrays of blocks/strings (normalized to RawCodexContentBlock array), and objects.
|
|
310
|
+
* Produces consistent RawCodexContentBlock array output for consistent processing.
|
|
311
|
+
*
|
|
312
|
+
* @param content - Raw message content in various formats
|
|
313
|
+
* @returns Array of normalized RawCodexContentBlock objects
|
|
314
|
+
*/
|
|
315
|
+
extractContentBlocks(content) {
|
|
316
|
+
const blocks = [];
|
|
317
|
+
// If content is a string, wrap it as a text block
|
|
318
|
+
if (typeof content === 'string') {
|
|
319
|
+
return [{ text: content, type: 'output_text' }];
|
|
320
|
+
}
|
|
321
|
+
// If content is already an array of blocks
|
|
322
|
+
if (Array.isArray(content)) {
|
|
323
|
+
for (const block of content) {
|
|
324
|
+
if (typeof block === 'string') {
|
|
325
|
+
blocks.push({ text: block, type: 'output_text' });
|
|
326
|
+
}
|
|
327
|
+
else if (block && typeof block === 'object') {
|
|
328
|
+
// Check if it's a valid block with a type field
|
|
329
|
+
if ('type' in block) {
|
|
330
|
+
blocks.push(block);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Fallback: wrap as text
|
|
334
|
+
blocks.push({ text: JSON.stringify(block), type: 'output_text' });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return blocks;
|
|
339
|
+
}
|
|
340
|
+
return [{ text: JSON.stringify(content), type: 'output_text' }];
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Extract session ID from Codex log file path
|
|
344
|
+
*
|
|
345
|
+
* Parses the filename from the log path to extract the session ID.
|
|
346
|
+
* Codex session IDs are typically UUIDs in the JSONL filename.
|
|
347
|
+
* Removes the .jsonl extension to get the session ID.
|
|
348
|
+
*
|
|
349
|
+
* @param logPath - Path to Codex session log file
|
|
350
|
+
* @returns Session ID extracted from the filename
|
|
351
|
+
*/
|
|
352
|
+
extractSessionId(logPath) {
|
|
353
|
+
// Codex session IDs are typically UUIDs in the filename
|
|
354
|
+
// Format: ~/.codex/sessions/YYYY/MM/DD/{session-id}.jsonl
|
|
355
|
+
const parts = logPath.split('/');
|
|
356
|
+
const filename = parts.at(-1) || '';
|
|
357
|
+
return filename.replace('.jsonl', '');
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Extract session metadata from transcript entries
|
|
361
|
+
*
|
|
362
|
+
* Searches transcript entries for session_meta type entries and validates them.
|
|
363
|
+
* Returns the session metadata payload (containing model, CLI version, timestamp, git info).
|
|
364
|
+
* Returns null if no valid session metadata is found.
|
|
365
|
+
*
|
|
366
|
+
* @param entries - Array of transcript entries to search
|
|
367
|
+
* @returns Extracted RawCodexSessionMeta payload, or null if not found
|
|
368
|
+
*/
|
|
369
|
+
extractSessionMeta(entries) {
|
|
370
|
+
const sessionMetaEntry = entries.find((e) => e.type === 'session_meta');
|
|
371
|
+
if (sessionMetaEntry && sessionMetaEntry.payload && this.isSessionMetaPayload(sessionMetaEntry.payload)) {
|
|
372
|
+
return sessionMetaEntry.payload;
|
|
373
|
+
}
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Extract session start and end timestamps
|
|
378
|
+
*
|
|
379
|
+
* Collects timestamps from transcript entries, filters empty values, sorts chronologically.
|
|
380
|
+
* Prefers session metadata timestamp for start time if available, otherwise uses first entry timestamp.
|
|
381
|
+
* Returns last timestamp as end time, or undefined if only one timestamp exists.
|
|
382
|
+
*
|
|
383
|
+
* @param entries - Array of transcript entries with optional timestamp fields
|
|
384
|
+
* @param sessionMeta - Optional session metadata containing preferred start timestamp
|
|
385
|
+
* @returns Object with startedAt and optional endedAt ISO timestamp strings
|
|
386
|
+
*/
|
|
387
|
+
extractTimestamps(entries, sessionMeta) {
|
|
388
|
+
const validTimestamps = entries
|
|
389
|
+
.filter((e) => e.timestamp)
|
|
390
|
+
.map((e) => e.timestamp || '')
|
|
391
|
+
.filter((t) => t.trim().length > 0)
|
|
392
|
+
.sort();
|
|
393
|
+
return {
|
|
394
|
+
endedAt: validTimestamps.at(-1),
|
|
395
|
+
startedAt: sessionMeta?.timestamp || validTimestamps[0] || new Date().toISOString(),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Extract session title from first user message
|
|
400
|
+
*
|
|
401
|
+
* Uses the first line of the first user message as the session title.
|
|
402
|
+
* Handles both string and array content formats, extracting text blocks from arrays.
|
|
403
|
+
* Truncates to TITLE_MAX_LENGTH (100 chars) and appends "..." if truncated.
|
|
404
|
+
* Returns default title if no user messages found or first message is empty.
|
|
405
|
+
*
|
|
406
|
+
* @param messages - Array of parsed session messages
|
|
407
|
+
* @returns Session title string (max 100 characters)
|
|
408
|
+
*/
|
|
409
|
+
extractTitle(messages) {
|
|
410
|
+
// Use first user message as title
|
|
411
|
+
const firstUserMessage = messages.find((m) => m.type === 'user');
|
|
412
|
+
if (firstUserMessage) {
|
|
413
|
+
let text = '';
|
|
414
|
+
if (typeof firstUserMessage.content === 'string') {
|
|
415
|
+
text = firstUserMessage.content;
|
|
416
|
+
}
|
|
417
|
+
else if (Array.isArray(firstUserMessage.content)) {
|
|
418
|
+
const textBlocks = firstUserMessage.content.filter((b) => typeof b === 'object' && b !== null && 'text' in b && typeof b.text === 'string');
|
|
419
|
+
text = textBlocks.map((b) => b.text).join(' ');
|
|
420
|
+
}
|
|
421
|
+
if (text) {
|
|
422
|
+
const lines = text.split('\n').filter((l) => l.trim());
|
|
423
|
+
if (lines.length > 0) {
|
|
424
|
+
const title = lines[0].slice(0, Math.max(0, TITLE_MAX_LENGTH));
|
|
425
|
+
return title.length === TITLE_MAX_LENGTH ? title + '...' : title;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return 'Codex Session';
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Extract workspace information from session metadata and log path
|
|
433
|
+
*
|
|
434
|
+
* Extracts workspace path and repository information from session metadata (preferred)
|
|
435
|
+
* or falls back to log path if metadata is unavailable. Includes repository name and
|
|
436
|
+
* optional git URL if available in session metadata.
|
|
437
|
+
*
|
|
438
|
+
* @param logPath - Codex session log file path (used as fallback)
|
|
439
|
+
* @param sessionMeta - Optional session metadata containing workspace and git info
|
|
440
|
+
* @returns Object with workspace path and optional repository name/url
|
|
441
|
+
*/
|
|
442
|
+
extractWorkspace(logPath, sessionMeta) {
|
|
443
|
+
// Try to get from session metadata first
|
|
444
|
+
if (sessionMeta?.cwd) {
|
|
445
|
+
const parts = sessionMeta.cwd.split('/');
|
|
446
|
+
const name = parts.at(-1) || 'unknown';
|
|
447
|
+
return {
|
|
448
|
+
path: sessionMeta.cwd,
|
|
449
|
+
repository: {
|
|
450
|
+
name,
|
|
451
|
+
url: sessionMeta.git?.repository_url,
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
// Fallback: use log path
|
|
456
|
+
return {
|
|
457
|
+
path: logPath,
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Type guard for event payload
|
|
462
|
+
*
|
|
463
|
+
* Checks if a payload is a valid RawCodexEventPayload by verifying it's an object
|
|
464
|
+
* with a type field matching token_count or agent_reasoning event types.
|
|
465
|
+
*
|
|
466
|
+
* @param payload - Value to check
|
|
467
|
+
* @returns True if payload is a valid RawCodexEventPayload, false otherwise
|
|
468
|
+
*/
|
|
469
|
+
isEventPayload(payload) {
|
|
470
|
+
return (typeof payload === 'object' &&
|
|
471
|
+
payload !== null &&
|
|
472
|
+
'type' in payload &&
|
|
473
|
+
(payload.type === 'token_count' || payload.type === 'agent_reasoning'));
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Type guard for response payload
|
|
477
|
+
*
|
|
478
|
+
* Checks if a payload is a valid RawCodexResponsePayload by verifying it's an object
|
|
479
|
+
* with a type field matching one of: function_call, function_call_output, message, or reasoning.
|
|
480
|
+
*
|
|
481
|
+
* @param payload - Value to check
|
|
482
|
+
* @returns True if payload is a valid RawCodexResponsePayload, false otherwise
|
|
483
|
+
*/
|
|
484
|
+
isResponsePayload(payload) {
|
|
485
|
+
return (typeof payload === 'object' &&
|
|
486
|
+
payload !== null &&
|
|
487
|
+
'type' in payload &&
|
|
488
|
+
['function_call', 'function_call_output', 'message', 'reasoning'].includes(payload.type));
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Type guard for session meta payload
|
|
492
|
+
*
|
|
493
|
+
* Checks if a payload is a valid RawCodexSessionMetaPayload by verifying it's an object
|
|
494
|
+
* containing at least one of: model_provider, cli_version, or timestamp fields.
|
|
495
|
+
*
|
|
496
|
+
* @param payload - Value to check
|
|
497
|
+
* @returns True if payload is a valid RawCodexSessionMetaPayload, false otherwise
|
|
498
|
+
*/
|
|
499
|
+
isSessionMetaPayload(payload) {
|
|
500
|
+
return (typeof payload === 'object' &&
|
|
501
|
+
payload !== null &&
|
|
502
|
+
('model_provider' in payload || 'cli_version' in payload || 'timestamp' in payload));
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Check if entry is a token count event
|
|
506
|
+
*
|
|
507
|
+
* Validates that an entry is an event_msg type with an event payload of type 'token_count'
|
|
508
|
+
* and contains token usage information (info field).
|
|
509
|
+
*
|
|
510
|
+
* @param entry - Transcript entry to check
|
|
511
|
+
* @returns True if entry is a valid token count event, false otherwise
|
|
512
|
+
*/
|
|
513
|
+
isTokenCountEntry(entry) {
|
|
514
|
+
if (entry.type !== 'event_msg' || !entry.payload || !this.isEventPayload(entry.payload)) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
const payload = entry.payload;
|
|
518
|
+
return payload.type === 'token_count' && payload.info !== undefined;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Parse all Codex session logs in a directory
|
|
522
|
+
*
|
|
523
|
+
* Finds all JSONL files in the directory (including subdirectories), parses them in sequence,
|
|
524
|
+
* and returns array of successfully parsed sessions sorted by start time.
|
|
525
|
+
* Collects and reports any parse errors without failing completely.
|
|
526
|
+
*
|
|
527
|
+
* @param dirPath - Path to directory containing JSONL session files
|
|
528
|
+
* @returns Promise resolving to array of parsed RawCodexRawSession objects
|
|
529
|
+
* @throws Error if directory cannot be read
|
|
530
|
+
*/
|
|
531
|
+
/* eslint-disable no-await-in-loop */
|
|
532
|
+
async parseSessionDirectory(dirPath) {
|
|
533
|
+
try {
|
|
534
|
+
const files = await readdir(dirPath, { recursive: true });
|
|
535
|
+
const jsonlFiles = files.filter((f) => typeof f === 'string' && f.endsWith('.jsonl') && !f.includes('-combined'));
|
|
536
|
+
const sessions = [];
|
|
537
|
+
const errors = [];
|
|
538
|
+
for (const file of jsonlFiles) {
|
|
539
|
+
try {
|
|
540
|
+
const fullPath = join(dirPath, file);
|
|
541
|
+
const session = await this.parseSessionLog(fullPath);
|
|
542
|
+
sessions.push(session);
|
|
543
|
+
}
|
|
544
|
+
catch (error) {
|
|
545
|
+
errors.push(`${file}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
if (sessions.length === 0 && errors.length > 0) {
|
|
549
|
+
console.warn(`Failed to parse some logs: ${errors.join(', ')}`);
|
|
550
|
+
}
|
|
551
|
+
// Sort by start time
|
|
552
|
+
sessions.sort((a, b) => a.metadata.startedAt.localeCompare(b.metadata.startedAt));
|
|
553
|
+
return sessions;
|
|
554
|
+
}
|
|
555
|
+
catch (error) {
|
|
556
|
+
throw new Error(`Failed to parse directory: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
/* eslint-enable no-await-in-loop */
|
|
560
|
+
/**
|
|
561
|
+
* Parse a single Codex session log file
|
|
562
|
+
*
|
|
563
|
+
* Validates log file format, reads JSONL content, parses each line as a transcript entry,
|
|
564
|
+
* converts entries to messages, extracts session metadata, calculates aggregated statistics,
|
|
565
|
+
* and extracts session title. Handles token usage, function calls, and reasoning payloads.
|
|
566
|
+
*
|
|
567
|
+
* @param logPath - Absolute path to Codex session JSONL file
|
|
568
|
+
* @returns Promise resolving to parsed RawCodexRawSession object
|
|
569
|
+
* @throws Error if file is invalid or cannot be parsed
|
|
570
|
+
*/
|
|
571
|
+
async parseSessionLog(logPath) {
|
|
572
|
+
try {
|
|
573
|
+
// Validate first
|
|
574
|
+
const valid = await this.validateLogFile(logPath);
|
|
575
|
+
if (!valid) {
|
|
576
|
+
throw new Error(`Invalid Codex log path: ${logPath}`);
|
|
577
|
+
}
|
|
578
|
+
// Read and parse JSONL file
|
|
579
|
+
const content = await readFile(logPath, 'utf8');
|
|
580
|
+
const lines = content.trim().split('\n').filter((l) => l.trim());
|
|
581
|
+
const entries = [];
|
|
582
|
+
const parseErrors = [];
|
|
583
|
+
for (const [i, line] of lines.entries()) {
|
|
584
|
+
try {
|
|
585
|
+
const entry = JSON.parse(line);
|
|
586
|
+
entries.push(entry);
|
|
587
|
+
}
|
|
588
|
+
catch (error) {
|
|
589
|
+
parseErrors.push(`Line ${i + 1}: ${error instanceof Error ? error.message : 'Parse error'}`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
if (entries.length === 0) {
|
|
593
|
+
throw new Error(`No valid entries found in ${logPath}`);
|
|
594
|
+
}
|
|
595
|
+
// Extract session info
|
|
596
|
+
const sessionId = this.extractSessionId(logPath);
|
|
597
|
+
const sessionMeta = this.extractSessionMeta(entries);
|
|
598
|
+
const messages = this.convertToMessages(entries);
|
|
599
|
+
const metadata = this.calculateMetadata(entries, messages, logPath, sessionMeta);
|
|
600
|
+
const title = this.extractTitle(messages);
|
|
601
|
+
// Convert transcript entries to raw entries, filtering out entries without payloads
|
|
602
|
+
const rawEntries = entries
|
|
603
|
+
.map((entry) => this.convertTranscriptEntryToRawEntry(entry))
|
|
604
|
+
.filter((entry) => entry !== null);
|
|
605
|
+
return {
|
|
606
|
+
id: sessionId,
|
|
607
|
+
messages,
|
|
608
|
+
metadata,
|
|
609
|
+
rawEntries,
|
|
610
|
+
timestamp: new Date(metadata.startedAt).getTime(),
|
|
611
|
+
title,
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
throw new Error(`Failed to parse Codex log: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Process function call payload and add to last message
|
|
620
|
+
*
|
|
621
|
+
* Extracts function call information from a function_call payload and appends it as a tool_use
|
|
622
|
+
* content block to the last message. Converts string arguments to parsed objects.
|
|
623
|
+
* If last message content is a string, converts it to an array before adding tool block.
|
|
624
|
+
*
|
|
625
|
+
* @param payload - Function call payload containing name, arguments, and call ID
|
|
626
|
+
* @param messages - Messages array to update (modifies last message in place)
|
|
627
|
+
*/
|
|
628
|
+
processFunctionCall(payload, messages) {
|
|
629
|
+
if (messages.length === 0)
|
|
630
|
+
return;
|
|
631
|
+
const lastMessage = messages.at(-1);
|
|
632
|
+
if (!lastMessage)
|
|
633
|
+
return;
|
|
634
|
+
const toolBlock = {
|
|
635
|
+
id: `call_${Date.now()}`,
|
|
636
|
+
input: typeof payload.arguments === 'string'
|
|
637
|
+
? this.safeJsonParse(payload.arguments)
|
|
638
|
+
: payload.arguments,
|
|
639
|
+
name: payload.name || 'unknown',
|
|
640
|
+
type: 'tool_use',
|
|
641
|
+
};
|
|
642
|
+
if (Array.isArray(lastMessage.content)) {
|
|
643
|
+
lastMessage.content.push(toolBlock);
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
// Convert string content to array and add tool block
|
|
647
|
+
const textBlock = {
|
|
648
|
+
text: lastMessage.content,
|
|
649
|
+
type: 'output_text',
|
|
650
|
+
};
|
|
651
|
+
lastMessage.content = [textBlock, toolBlock];
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Process function call output and attach to corresponding tool use block
|
|
656
|
+
*
|
|
657
|
+
* Finds the most recent tool_use block in the last message and appends the function output to it.
|
|
658
|
+
* The output field contains the result of the function call execution.
|
|
659
|
+
*
|
|
660
|
+
* @param payload - Function call output payload containing output data
|
|
661
|
+
* @param messages - Messages array to update (modifies last message in place)
|
|
662
|
+
*/
|
|
663
|
+
processFunctionCallOutput(payload, messages) {
|
|
664
|
+
if (messages.length === 0)
|
|
665
|
+
return;
|
|
666
|
+
const lastMessage = messages.at(-1);
|
|
667
|
+
if (!lastMessage || !Array.isArray(lastMessage.content))
|
|
668
|
+
return;
|
|
669
|
+
// Find the tool use block with matching call_id
|
|
670
|
+
const toolBlock = lastMessage.content.find((b) => b.type === 'tool_use');
|
|
671
|
+
if (toolBlock) {
|
|
672
|
+
toolBlock.output = payload.output;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Process message payload and add to messages array
|
|
677
|
+
*
|
|
678
|
+
* Converts a message payload into a normalized RawCodexRawMessage and appends to messages array.
|
|
679
|
+
* Handles content block conversion, attaches token usage and reasoning context if available.
|
|
680
|
+
* Collapses single text blocks to strings for backward compatibility.
|
|
681
|
+
*
|
|
682
|
+
* @param payload - Message payload containing role and content
|
|
683
|
+
* @param messages - Messages array to update (appends new message)
|
|
684
|
+
* @param timestamp - ISO timestamp for the message
|
|
685
|
+
* @param currentTokenUsage - Optional token usage metrics to attach to message
|
|
686
|
+
* @param currentReasoning - Optional reasoning content to attach to message
|
|
687
|
+
*/
|
|
688
|
+
// eslint-disable-next-line max-params
|
|
689
|
+
processMessage(payload, messages, timestamp, currentTokenUsage, currentReasoning) {
|
|
690
|
+
const role = payload.role;
|
|
691
|
+
const codexContentBlocks = this.extractContentBlocks(payload.content);
|
|
692
|
+
// Convert CodexContentBlock array to ContentBlock array
|
|
693
|
+
const contentBlocks = codexContentBlocks.map((block) => this.convertCodexContentBlockToContentBlock(block));
|
|
694
|
+
messages.push({
|
|
695
|
+
content: contentBlocks.length === 1 && contentBlocks[0].type === 'text'
|
|
696
|
+
? contentBlocks[0].text
|
|
697
|
+
: contentBlocks.length === 1 && contentBlocks[0].type === 'output_text'
|
|
698
|
+
? contentBlocks[0].text
|
|
699
|
+
: contentBlocks,
|
|
700
|
+
reasoning: currentReasoning || undefined,
|
|
701
|
+
timestamp,
|
|
702
|
+
tokens: currentTokenUsage
|
|
703
|
+
? {
|
|
704
|
+
input: currentTokenUsage.input_tokens || 0,
|
|
705
|
+
output: currentTokenUsage.output_tokens || 0,
|
|
706
|
+
}
|
|
707
|
+
: undefined,
|
|
708
|
+
type: role,
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Process reasoning payload and extract reasoning text summary
|
|
713
|
+
*
|
|
714
|
+
* Extracts reasoning content from a reasoning payload by filtering summary items of type 'summary_text'
|
|
715
|
+
* and joining their text content. Returns null if no valid reasoning content is found.
|
|
716
|
+
*
|
|
717
|
+
* @param payload - Reasoning payload containing summary array
|
|
718
|
+
* @returns Extracted reasoning text or null if no valid content found
|
|
719
|
+
*/
|
|
720
|
+
processReasoningPayload(payload) {
|
|
721
|
+
if (!payload.summary || !Array.isArray(payload.summary))
|
|
722
|
+
return null;
|
|
723
|
+
const summaryTexts = payload.summary
|
|
724
|
+
.filter((s) => 'type' in s && s.type === SUMMARY_TEXT_TYPE)
|
|
725
|
+
.map((s) => s.text);
|
|
726
|
+
return summaryTexts.length > 0 ? summaryTexts.join('\n') : null;
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Safely parse JSON string or return object as-is
|
|
730
|
+
*
|
|
731
|
+
* Attempts to parse a JSON string. If input is already an object, returns it directly.
|
|
732
|
+
* Returns empty object on parse errors or non-string/object inputs.
|
|
733
|
+
* Used for defensive parsing of tool call arguments.
|
|
734
|
+
*
|
|
735
|
+
* @param jsonString - String to parse or object to validate
|
|
736
|
+
* @returns Parsed object or empty object if parsing fails
|
|
737
|
+
*/
|
|
738
|
+
safeJsonParse(jsonString) {
|
|
739
|
+
if (typeof jsonString === 'object' && jsonString !== null) {
|
|
740
|
+
return jsonString;
|
|
741
|
+
}
|
|
742
|
+
if (typeof jsonString !== 'string') {
|
|
743
|
+
return {};
|
|
744
|
+
}
|
|
745
|
+
try {
|
|
746
|
+
const parsed = JSON.parse(jsonString);
|
|
747
|
+
return typeof parsed === 'object' && parsed !== null ? parsed : {};
|
|
748
|
+
}
|
|
749
|
+
catch {
|
|
750
|
+
return {};
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Validate Codex log file format and existence
|
|
755
|
+
*
|
|
756
|
+
* Checks three validation criteria:
|
|
757
|
+
* 1. Path contains /.codex/sessions/ directory marker
|
|
758
|
+
* 2. File has .jsonl extension
|
|
759
|
+
* 3. File exists on filesystem
|
|
760
|
+
* Returns false silently if any check fails.
|
|
761
|
+
*
|
|
762
|
+
* @param logPath - Path to file to validate
|
|
763
|
+
* @returns Promise resolving to true if file is valid Codex log file, false otherwise
|
|
764
|
+
*/
|
|
765
|
+
async validateLogFile(logPath) {
|
|
766
|
+
try {
|
|
767
|
+
// Check path contains .codex/sessions/
|
|
768
|
+
if (!logPath.includes('/.codex/sessions/')) {
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
// Check file extension is .jsonl
|
|
772
|
+
if (!logPath.endsWith('.jsonl')) {
|
|
773
|
+
return false;
|
|
774
|
+
}
|
|
775
|
+
// Check file exists
|
|
776
|
+
return existsSync(logPath);
|
|
777
|
+
}
|
|
778
|
+
catch {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|