create-walle 0.9.21 → 0.9.23
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 +27 -5
- package/package.json +2 -2
- package/template/CLAUDE.md +2 -2
- package/template/LICENSE +1 -1
- package/template/bin/ctm-dev-cleanup.js +24 -3
- package/template/bin/ctm-launch.sh +13 -0
- package/template/bin/dev.sh +156 -18
- package/template/bin/node-bin.sh +84 -0
- package/template/bin/pin-node.sh +51 -0
- package/template/claude-task-manager/api-prompts.js +1203 -182
- package/template/claude-task-manager/api-reviews.js +109 -15
- package/template/claude-task-manager/approval-agent.js +1360 -280
- package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
- package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
- package/template/claude-task-manager/db.js +4417 -295
- package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
- package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
- package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
- package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
- package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
- package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
- package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
- package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
- package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
- package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
- package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
- package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
- package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
- package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
- package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
- package/template/claude-task-manager/docs/phone-access-design.md +53 -15
- package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
- package/template/claude-task-manager/docs/phone-setup.md +3 -0
- package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
- package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
- package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
- package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
- package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
- package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
- package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
- package/template/claude-task-manager/docs/session-title-authority.md +32 -0
- package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
- package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
- package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
- package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
- package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
- package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
- package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
- package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
- package/template/claude-task-manager/git-utils.js +897 -27
- package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
- package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
- package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
- package/template/claude-task-manager/lib/agent-presets.js +17 -1
- package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
- package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
- package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
- package/template/claude-task-manager/lib/async-semaphore.js +44 -0
- package/template/claude-task-manager/lib/auth-context.js +5 -0
- package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
- package/template/claude-task-manager/lib/auth-rules.js +29 -2
- package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
- package/template/claude-task-manager/lib/background-llm.js +144 -17
- package/template/claude-task-manager/lib/branch-inventory.js +212 -0
- package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
- package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
- package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
- package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
- package/template/claude-task-manager/lib/codex-zst.js +124 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
- package/template/claude-task-manager/lib/connection-health.js +232 -0
- package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
- package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
- package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
- package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
- package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
- package/template/claude-task-manager/lib/document-review.js +141 -6
- package/template/claude-task-manager/lib/escalation-review.js +152 -0
- package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
- package/template/claude-task-manager/lib/headless-term-service.js +678 -0
- package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
- package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
- package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
- package/template/claude-task-manager/lib/main-db-census.js +216 -0
- package/template/claude-task-manager/lib/message-pagination.js +106 -4
- package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
- package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
- package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
- package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
- package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
- package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
- package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
- package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
- package/template/claude-task-manager/lib/perf-tracker.js +242 -6
- package/template/claude-task-manager/lib/permission-match.js +76 -0
- package/template/claude-task-manager/lib/permission-sync.js +133 -20
- package/template/claude-task-manager/lib/process-title.js +35 -0
- package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
- package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
- package/template/claude-task-manager/lib/prompt-intent.js +132 -0
- package/template/claude-task-manager/lib/provider-user-context.js +34 -0
- package/template/claude-task-manager/lib/read-pool-client.js +313 -0
- package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
- package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
- package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
- package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
- package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
- package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
- package/template/claude-task-manager/lib/restart-guard.js +109 -0
- package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
- package/template/claude-task-manager/lib/restore-policy.js +13 -0
- package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
- package/template/claude-task-manager/lib/restore-runtime.js +68 -0
- package/template/claude-task-manager/lib/restore-storm.js +34 -0
- package/template/claude-task-manager/lib/resume-cwd.js +36 -0
- package/template/claude-task-manager/lib/resume-preflight.js +313 -0
- package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
- package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
- package/template/claude-task-manager/lib/scheduler.js +21 -1
- package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
- package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
- package/template/claude-task-manager/lib/server-listeners.js +239 -0
- package/template/claude-task-manager/lib/session-capture.js +42 -7
- package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
- package/template/claude-task-manager/lib/session-history.js +388 -43
- package/template/claude-task-manager/lib/session-host-manager.js +287 -0
- package/template/claude-task-manager/lib/session-image-refs.js +209 -0
- package/template/claude-task-manager/lib/session-jobs.js +399 -59
- package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
- package/template/claude-task-manager/lib/session-restore.js +53 -0
- package/template/claude-task-manager/lib/session-standup.js +123 -23
- package/template/claude-task-manager/lib/session-state-bus.js +14 -0
- package/template/claude-task-manager/lib/session-stream.js +64 -16
- package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
- package/template/claude-task-manager/lib/session-token-usage.js +494 -0
- package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
- package/template/claude-task-manager/lib/setup-network-config.js +9 -0
- package/template/claude-task-manager/lib/size-cap.js +45 -0
- package/template/claude-task-manager/lib/size-cap.test.js +62 -0
- package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
- package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
- package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
- package/template/claude-task-manager/lib/standup-attention.js +7 -3
- package/template/claude-task-manager/lib/status-authority.js +39 -0
- package/template/claude-task-manager/lib/status-hooks.js +4 -0
- package/template/claude-task-manager/lib/storage-migration.js +235 -0
- package/template/claude-task-manager/lib/structured-capture.js +298 -0
- package/template/claude-task-manager/lib/sync-io-census.js +163 -0
- package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
- package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
- package/template/claude-task-manager/lib/terminal-choice.js +364 -0
- package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
- package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
- package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
- package/template/claude-task-manager/lib/timeline-order.js +122 -0
- package/template/claude-task-manager/lib/transcript-store.js +348 -43
- package/template/claude-task-manager/lib/transport-security.js +84 -1
- package/template/claude-task-manager/lib/wait-state.js +184 -0
- package/template/claude-task-manager/lib/walle-client.js +47 -5
- package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
- package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
- package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
- package/template/claude-task-manager/lib/walle-native-health.js +403 -0
- package/template/claude-task-manager/lib/walle-repair.js +701 -0
- package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
- package/template/claude-task-manager/lib/walle-session-context.js +57 -21
- package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
- package/template/claude-task-manager/lib/walle-transcript.js +52 -0
- package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
- package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
- package/template/claude-task-manager/package.json +1 -1
- package/template/claude-task-manager/prompt-harvest.js +89 -66
- package/template/claude-task-manager/providers/claude-code.js +51 -3
- package/template/claude-task-manager/providers/cursor.js +140 -45
- package/template/claude-task-manager/public/css/reviews.css +551 -61
- package/template/claude-task-manager/public/css/setup.css +191 -0
- package/template/claude-task-manager/public/css/walle-session.css +865 -10
- package/template/claude-task-manager/public/css/walle.css +154 -0
- package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
- package/template/claude-task-manager/public/index.html +18516 -2058
- package/template/claude-task-manager/public/ipad.html +363 -0
- package/template/claude-task-manager/public/js/document-review-links.js +301 -0
- package/template/claude-task-manager/public/js/image-normalize.js +69 -36
- package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
- package/template/claude-task-manager/public/js/prompts.js +66 -29
- package/template/claude-task-manager/public/js/reviews.js +901 -133
- package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
- package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
- package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
- package/template/claude-task-manager/public/js/setup.js +1273 -176
- package/template/claude-task-manager/public/js/stream-view.js +691 -73
- package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
- package/template/claude-task-manager/public/js/walle-session.js +2455 -158
- package/template/claude-task-manager/public/js/walle.js +455 -28
- package/template/claude-task-manager/public/m/app.css +2909 -262
- package/template/claude-task-manager/public/m/app.js +6601 -398
- package/template/claude-task-manager/public/m/claim.html +224 -17
- package/template/claude-task-manager/public/m/index.html +117 -21
- package/template/claude-task-manager/public/m/sw.js +3 -1
- package/template/claude-task-manager/public/manifest.json +2 -2
- package/template/claude-task-manager/public/prompts.html +30 -14
- package/template/claude-task-manager/queue-engine.js +507 -28
- package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
- package/template/claude-task-manager/server.js +14341 -2197
- package/template/claude-task-manager/session-integrity.js +160 -18
- package/template/claude-task-manager/session-search-ranking.js +1 -0
- package/template/claude-task-manager/session-utils.js +25 -5
- package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
- package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
- package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
- package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
- package/template/claude-task-manager/workers/harvest-worker.js +9 -55
- package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
- package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
- package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
- package/template/claude-task-manager/workers/session-host-process.js +146 -0
- package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
- package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
- package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
- package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
- package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
- package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
- package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
- package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
- package/template/docs/design/markdown-review-pane.md +206 -0
- package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
- package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
- package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
- package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
- package/template/docs/private-memory-and-pii-policy.md +69 -0
- package/template/package.json +2 -1
- package/template/scripts/check-private-data.js +201 -0
- package/template/shared/sqlite-owner-guard.js +30 -0
- package/template/shared/sqlite-owner-write-queue.js +225 -0
- package/template/shared/sqlite-storage-policy.js +111 -0
- package/template/shared/sqlite-write-lock.js +428 -0
- package/template/wall-e/agent-runners/claude-code.js +5 -0
- package/template/wall-e/agent.js +166 -22
- package/template/wall-e/api-walle.js +524 -70
- package/template/wall-e/auth/provider-flows.js +11 -1
- package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
- package/template/wall-e/brain.js +1614 -141
- package/template/wall-e/chat/attachment-blocks.js +96 -0
- package/template/wall-e/chat/attachments.js +2 -1
- package/template/wall-e/chat/capability-resolver.js +7 -7
- package/template/wall-e/chat/context-messages.js +28 -0
- package/template/wall-e/chat/conversation-frame.js +630 -0
- package/template/wall-e/chat/provider-messages.js +125 -0
- package/template/wall-e/chat.js +1002 -233
- package/template/wall-e/coding/acceptance-contract.js +170 -0
- package/template/wall-e/coding/acp-adapter.js +1 -1
- package/template/wall-e/coding/agent-catalog.js +3 -0
- package/template/wall-e/coding/artifact-store.js +93 -0
- package/template/wall-e/coding/capability-router.js +120 -0
- package/template/wall-e/coding/coding-run-controller.js +423 -0
- package/template/wall-e/coding/compaction-service.js +157 -12
- package/template/wall-e/coding/frontend-verification.js +258 -0
- package/template/wall-e/coding/lifecycle-hooks.js +75 -0
- package/template/wall-e/coding/local-preview-contract.js +157 -0
- package/template/wall-e/coding/permission-service.js +57 -13
- package/template/wall-e/coding/prompt-bundle.js +19 -1
- package/template/wall-e/coding/prompt-section-registry.js +227 -0
- package/template/wall-e/coding/provider-compat.js +15 -0
- package/template/wall-e/coding/runtime-events.js +224 -0
- package/template/wall-e/coding/runtime-mode.js +3 -0
- package/template/wall-e/coding/side-git-snapshot.js +160 -4
- package/template/wall-e/coding/snapshot-service.js +143 -1
- package/template/wall-e/coding/stream-processor.js +388 -34
- package/template/wall-e/coding/task-tool.js +141 -4
- package/template/wall-e/coding/tool-execution-controller.js +365 -0
- package/template/wall-e/coding/tool-registry.js +43 -5
- package/template/wall-e/coding/user-hooks.js +217 -0
- package/template/wall-e/coding-orchestrator.js +1330 -221
- package/template/wall-e/coding-prompts.js +20 -4
- package/template/wall-e/context/context-builder.js +15 -2
- package/template/wall-e/decision/confidence.js +1 -1
- package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
- package/template/wall-e/docs/external-action-controller.md +26 -6
- package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
- package/template/wall-e/embeddings.js +591 -53
- package/template/wall-e/external-action-controller.js +12 -0
- package/template/wall-e/http/auth.js +1 -0
- package/template/wall-e/http/chat-api.js +46 -11
- package/template/wall-e/http/model-admin.js +836 -34
- package/template/wall-e/lib/boot-profile.js +88 -0
- package/template/wall-e/lib/event-loop-monitor.js +93 -0
- package/template/wall-e/lib/service-health.js +194 -0
- package/template/wall-e/llm/anthropic.js +130 -5
- package/template/wall-e/llm/client.js +266 -63
- package/template/wall-e/llm/default-fallback.js +382 -0
- package/template/wall-e/llm/health.js +19 -0
- package/template/wall-e/llm/message-guard.js +78 -0
- package/template/wall-e/llm/model-catalog.js +252 -1
- package/template/wall-e/llm/openai.js +26 -4
- package/template/wall-e/llm/portkey-sync.js +654 -0
- package/template/wall-e/llm/provider-error.js +30 -2
- package/template/wall-e/llm/registry.js +5 -1
- package/template/wall-e/llm/request-compat.js +67 -0
- package/template/wall-e/loops/backfill.js +79 -23
- package/template/wall-e/loops/brain-optimize.js +67 -0
- package/template/wall-e/loops/ingest.js +25 -10
- package/template/wall-e/loops/question-digest.js +160 -0
- package/template/wall-e/loops/reflect.js +6 -4
- package/template/wall-e/loops/think.js +39 -12
- package/template/wall-e/mcp-server.js +318 -36
- package/template/wall-e/memory/ctm-context-client.js +52 -14
- package/template/wall-e/memory/ctm-operational-context.js +237 -0
- package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
- package/template/wall-e/memory/ctm-session-context.js +111 -63
- package/template/wall-e/prompts/coding/deepseek.txt +3 -0
- package/template/wall-e/prompts/coding/gemini.txt +6 -0
- package/template/wall-e/prompts/coding/gpt.txt +6 -0
- package/template/wall-e/prompts/coding/local.txt +7 -0
- package/template/wall-e/runtime/decision-hooks.js +115 -0
- package/template/wall-e/runtime/devbox-gateway.js +82 -8
- package/template/wall-e/runtime/prompt-manifest.js +86 -0
- package/template/wall-e/runtime/tool-executor.js +269 -0
- package/template/wall-e/runtime/tool-result-envelope.js +138 -0
- package/template/wall-e/runtime/transcript-projection.js +60 -0
- package/template/wall-e/runtime/walle-runtime.js +224 -0
- package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
- package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
- package/template/wall-e/server.js +15 -0
- package/template/wall-e/session-files.js +9 -0
- package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
- package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
- package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
- package/template/wall-e/skills/claude-code-reader.js +7 -3
- package/template/wall-e/skills/script-skill-runner.js +10 -0
- package/template/wall-e/skills/skill-planner.js +38 -0
- package/template/wall-e/tools/builtin-middleware.js +19 -9
- package/template/wall-e/tools/local-tools.js +1428 -16
- package/template/wall-e/tools/permission-checker.js +73 -5
- package/template/wall-e/tools/question-manager.js +117 -7
- package/template/wall-e/training/harvester.js +12 -28
- package/template/wall-e/training/replay.js +25 -80
- package/template/website/index.html +10 -10
- package/template/wall-e/eval/ab-test.js +0 -203
- package/template/wall-e/eval/agent-runner.js +0 -772
- package/template/wall-e/eval/agent-scorer.js +0 -461
- package/template/wall-e/eval/aggregator.js +0 -414
- package/template/wall-e/eval/allowed-test-commands.js +0 -34
- package/template/wall-e/eval/benchmark-generator.js +0 -113
- package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
- package/template/wall-e/eval/benchmarks/chat.json +0 -82
- package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
- package/template/wall-e/eval/benchmarks/coding.json +0 -122
- package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
- package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
- package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
- package/template/wall-e/eval/benchmarks.js +0 -669
- package/template/wall-e/eval/cc-replay.js +0 -719
- package/template/wall-e/eval/chat-eval.js +0 -525
- package/template/wall-e/eval/check-keys.js +0 -15
- package/template/wall-e/eval/check-providers.js +0 -42
- package/template/wall-e/eval/codex-cli-baseline.js +0 -669
- package/template/wall-e/eval/coding-agent-real.js +0 -570
- package/template/wall-e/eval/context-compactor.js +0 -251
- package/template/wall-e/eval/debug-agent003.js +0 -68
- package/template/wall-e/eval/diagnostics.js +0 -216
- package/template/wall-e/eval/eval-orchestrator.js +0 -642
- package/template/wall-e/eval/evaluate.js +0 -202
- package/template/wall-e/eval/evaluator.js +0 -373
- package/template/wall-e/eval/exporter.js +0 -212
- package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
- package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
- package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
- package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
- package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
- package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
- package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
- package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
- package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
- package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
- package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
- package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
- package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
- package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
- package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
- package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
- package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
- package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
- package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
- package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
- package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
- package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
- package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
- package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
- package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
- package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
- package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
- package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
- package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
- package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
- package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
- package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
- package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
- package/template/wall-e/eval/harvester.js +0 -685
- package/template/wall-e/eval/head-to-head.js +0 -388
- package/template/wall-e/eval/humaneval-adapter.js +0 -321
- package/template/wall-e/eval/list-models.js +0 -31
- package/template/wall-e/eval/livecodebench-adapter.js +0 -291
- package/template/wall-e/eval/mail-integration.js +0 -443
- package/template/wall-e/eval/manifest.js +0 -186
- package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
- package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
- package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
- package/template/wall-e/eval/meta-harness/cli.js +0 -86
- package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
- package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
- package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
- package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
- package/template/wall-e/eval/meta-harness/frontier.js +0 -96
- package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
- package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
- package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
- package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
- package/template/wall-e/eval/meta-harness/reporting.js +0 -58
- package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
- package/template/wall-e/eval/meta-harness/validation.js +0 -81
- package/template/wall-e/eval/promoter.js +0 -228
- package/template/wall-e/eval/provider-normalizer.js +0 -33
- package/template/wall-e/eval/replay.js +0 -395
- package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
- package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
- package/template/wall-e/eval/run-coding-agent-real.js +0 -187
- package/template/wall-e/eval/run-eval.js +0 -435
- package/template/wall-e/eval/run-model-comparison.js +0 -142
- package/template/wall-e/eval/session-evaluator.js +0 -187
- package/template/wall-e/eval/session-miner.js +0 -207
- package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
- package/template/wall-e/eval/session-transcripts.js +0 -509
- package/template/wall-e/eval/shadow.js +0 -161
- package/template/wall-e/eval/swebench-adapter.js +0 -345
- package/template/wall-e/eval/swebench-docker.js +0 -192
- package/template/wall-e/eval/train.py +0 -320
- package/template/wall-e/eval/trainer.js +0 -232
- package/template/wall-e/eval/weekly-eval-loop.js +0 -241
|
@@ -4,11 +4,28 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { StringDecoder } = require('string_decoder');
|
|
6
6
|
const { getResumeSpec: getAgentResumeSpec, normalizeAgentType } = require('./agent-capabilities');
|
|
7
|
+
const structuredCapture = require('./structured-capture');
|
|
8
|
+
const codexZst = require('./codex-zst');
|
|
7
9
|
|
|
8
10
|
const DEFAULT_CODEX_LOOKBACK_SEC = 10;
|
|
9
11
|
const DEFAULT_CODEX_MAX_DELAY_SEC = 180;
|
|
10
12
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11
|
-
const CODEX_ROLLOUT_BASENAME_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl(?:\.bak)?$/i;
|
|
13
|
+
const CODEX_ROLLOUT_BASENAME_RE = /^rollout-(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2})-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl(?:\.bak)?(?:\.zst)?$/i;
|
|
14
|
+
|
|
15
|
+
// Rollout candidates on disk: live `.jsonl` plus zstd-compressed cold
|
|
16
|
+
// archives (`.jsonl.zst`) that newer Codex versions write.
|
|
17
|
+
function isCodexRolloutCandidateName(name) {
|
|
18
|
+
const n = String(name || '');
|
|
19
|
+
return n.endsWith('.jsonl') || codexZst.isZstRolloutFileName(n);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Compressed archives are materialized to a disk cache before any read; a
|
|
23
|
+
// failure (no zstd, too large) makes the file invisible to the reader.
|
|
24
|
+
function _codexReadablePath(filePath) {
|
|
25
|
+
if (!codexZst.isZstRolloutFileName(filePath)) return filePath;
|
|
26
|
+
const mat = codexZst.materializeCodexRollout(filePath);
|
|
27
|
+
return mat.ok ? mat.path : null;
|
|
28
|
+
}
|
|
12
29
|
|
|
13
30
|
function getResumeSpec(agentType, resumeId) {
|
|
14
31
|
return getAgentResumeSpec(agentType || 'claude', resumeId);
|
|
@@ -151,7 +168,7 @@ function findCodexSessionFiles(threadId, sessionsRoot, homeDir = process.env.HOM
|
|
|
151
168
|
if (entry.isFile() && codexRolloutIdFromPath(fullPath) === wanted) {
|
|
152
169
|
if (!codexRolloutFileMatchesThread(fullPath, wanted)) continue;
|
|
153
170
|
matches.push(fullPath);
|
|
154
|
-
} else if (entry.isFile() && entry.name
|
|
171
|
+
} else if (entry.isFile() && isCodexRolloutCandidateName(entry.name)) {
|
|
155
172
|
metadataFallbackCandidates.push(fullPath);
|
|
156
173
|
}
|
|
157
174
|
}
|
|
@@ -161,7 +178,7 @@ function findCodexSessionFiles(threadId, sessionsRoot, homeDir = process.env.HOM
|
|
|
161
178
|
if (codexRolloutFileMatchesThread(fullPath, wanted)) matches.push(fullPath);
|
|
162
179
|
}
|
|
163
180
|
}
|
|
164
|
-
const sorted = sortCodexRolloutFiles(matches);
|
|
181
|
+
const sorted = sortCodexRolloutFiles(codexZst.dropZstWithLiveSibling(matches));
|
|
165
182
|
return indexedPathMatchesWanted
|
|
166
183
|
? [indexedPath, ...sorted.filter((filePath) => filePath !== indexedPath)]
|
|
167
184
|
: sorted;
|
|
@@ -188,7 +205,7 @@ function findCodexSessionFilesByFilename(threadId, sessionsRoot, homeDir = proce
|
|
|
188
205
|
}
|
|
189
206
|
}
|
|
190
207
|
}
|
|
191
|
-
return sortCodexRolloutFiles(matches);
|
|
208
|
+
return sortCodexRolloutFiles(codexZst.dropZstWithLiveSibling(matches));
|
|
192
209
|
}
|
|
193
210
|
|
|
194
211
|
function parseSessionStartMs(value) {
|
|
@@ -454,10 +471,10 @@ function repairCodexStateThreadRollout(threadId, expectedRolloutPath, opts = {})
|
|
|
454
471
|
const wanted = String(threadId || '').trim().toLowerCase();
|
|
455
472
|
const rolloutPath = String(expectedRolloutPath || '').trim();
|
|
456
473
|
const homeDir = opts.homeDir || process.env.HOME;
|
|
457
|
-
if (!UUID_RE.test(wanted)) return { ok: false, repaired: false, mismatch: false, reason: 'invalid_thread_id' };
|
|
458
|
-
if (!rolloutPath || !fs.existsSync(rolloutPath)) return { ok: false, repaired: false, mismatch: false, reason: 'expected_rollout_missing' };
|
|
459
|
-
if (codexRolloutIdFromPath(rolloutPath) !== wanted) return { ok: false, repaired: false, mismatch: false, reason: 'expected_rollout_filename_mismatch' };
|
|
460
|
-
if (!codexRolloutFileMatchesThread(rolloutPath, wanted)) return { ok: false, repaired: false, mismatch: false, reason: 'expected_rollout_metadata_mismatch' };
|
|
474
|
+
if (!UUID_RE.test(wanted)) return { ok: false, repaired: false, mismatch: false, blocked: false, reason: 'invalid_thread_id' };
|
|
475
|
+
if (!rolloutPath || !fs.existsSync(rolloutPath)) return { ok: false, repaired: false, mismatch: false, blocked: false, reason: 'expected_rollout_missing' };
|
|
476
|
+
if (codexRolloutIdFromPath(rolloutPath) !== wanted) return { ok: false, repaired: false, mismatch: false, blocked: false, reason: 'expected_rollout_filename_mismatch' };
|
|
477
|
+
if (!codexRolloutFileMatchesThread(rolloutPath, wanted)) return { ok: false, repaired: false, mismatch: false, blocked: false, reason: 'expected_rollout_metadata_mismatch' };
|
|
461
478
|
|
|
462
479
|
const before = inspectCodexStateThreadRollout(wanted, rolloutPath, { homeDir });
|
|
463
480
|
if (before.ok) return { ...before, repaired: false, blocked: false };
|
|
@@ -656,9 +673,31 @@ function codexThreadPreciseCreatedMs(row, homeDir = process.env.HOME) {
|
|
|
656
673
|
return fallback;
|
|
657
674
|
}
|
|
658
675
|
|
|
676
|
+
function codexSessionLineageFromPayload(payload = {}) {
|
|
677
|
+
const sourcePayload = payload.source && typeof payload.source === 'object' ? payload.source : null;
|
|
678
|
+
const subagent = sourcePayload?.subagent || {};
|
|
679
|
+
const threadSpawn = subagent.thread_spawn || {};
|
|
680
|
+
const parentThreadId = payload.parent_thread_id
|
|
681
|
+
|| payload.parent_agent_session_id
|
|
682
|
+
|| threadSpawn.parent_thread_id
|
|
683
|
+
|| '';
|
|
684
|
+
const threadSource = payload.thread_source
|
|
685
|
+
|| (parentThreadId ? 'subagent' : '');
|
|
686
|
+
return {
|
|
687
|
+
source: typeof payload.source === 'string' ? payload.source : (threadSource || ''),
|
|
688
|
+
thread_source: threadSource,
|
|
689
|
+
parent_agent_session_id: parentThreadId,
|
|
690
|
+
parent_thread_id: parentThreadId,
|
|
691
|
+
agent_nickname: payload.agent_nickname || subagent.agent_nickname || threadSpawn.agent_nickname || '',
|
|
692
|
+
agent_role: payload.agent_role || subagent.agent_role || threadSpawn.agent_role || '',
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
659
696
|
function _readCodexRolloutMetadata(filePath) {
|
|
697
|
+
const readPath = _codexReadablePath(filePath);
|
|
698
|
+
if (!readPath) return null;
|
|
660
699
|
// 512KB covers the large turn_context blob that Codex injects before the user_message event
|
|
661
|
-
const prefix = readFilePrefix(
|
|
700
|
+
const prefix = readFilePrefix(readPath, 512 * 1024);
|
|
662
701
|
if (!prefix) return null;
|
|
663
702
|
let meta = null;
|
|
664
703
|
let firstUser = '';
|
|
@@ -669,12 +708,17 @@ function _readCodexRolloutMetadata(filePath) {
|
|
|
669
708
|
if (!meta && entry?.type === 'session_meta') {
|
|
670
709
|
const payload = entry.payload || {};
|
|
671
710
|
if (!payload.id) return null;
|
|
711
|
+
const lineage = codexSessionLineageFromPayload(payload);
|
|
672
712
|
meta = {
|
|
673
713
|
id: payload.id,
|
|
674
714
|
cwd: payload.cwd || '',
|
|
675
715
|
model: payload.model || payload.model_id || '',
|
|
676
716
|
model_provider: payload.model_provider || '',
|
|
677
|
-
source:
|
|
717
|
+
source: lineage.source,
|
|
718
|
+
thread_source: lineage.thread_source,
|
|
719
|
+
parent_agent_session_id: lineage.parent_agent_session_id,
|
|
720
|
+
agent_nickname: lineage.agent_nickname,
|
|
721
|
+
agent_role: lineage.agent_role,
|
|
678
722
|
cli_version: payload.cli_version || '',
|
|
679
723
|
git_branch: payload.git_branch || '',
|
|
680
724
|
createdMs: parseSessionStartMs(payload.timestamp || entry.timestamp),
|
|
@@ -694,6 +738,11 @@ function _readCodexRolloutMetadata(filePath) {
|
|
|
694
738
|
model: meta.model,
|
|
695
739
|
model_provider: meta.model_provider,
|
|
696
740
|
source: meta.source,
|
|
741
|
+
thread_source: meta.thread_source,
|
|
742
|
+
parent_agent_session_id: meta.parent_agent_session_id,
|
|
743
|
+
parent_thread_id: meta.parent_agent_session_id,
|
|
744
|
+
agent_nickname: meta.agent_nickname,
|
|
745
|
+
agent_role: meta.agent_role,
|
|
697
746
|
cli_version: meta.cli_version,
|
|
698
747
|
cwd: meta.cwd,
|
|
699
748
|
git_branch: meta.git_branch,
|
|
@@ -792,7 +841,7 @@ function findCodexThreadFromRolloutsForSession({
|
|
|
792
841
|
stack.push(fullPath);
|
|
793
842
|
continue;
|
|
794
843
|
}
|
|
795
|
-
if (!entry.isFile() || !entry.name
|
|
844
|
+
if (!entry.isFile() || !isCodexRolloutCandidateName(entry.name)) continue;
|
|
796
845
|
const row = _readCodexRolloutMetadata(fullPath);
|
|
797
846
|
if (!row || !codexCwdMatches(row.cwd, cwd)) continue;
|
|
798
847
|
const ms = row._preciseCreatedMs;
|
|
@@ -922,6 +971,71 @@ function codexUserKey(text) {
|
|
|
922
971
|
return String(text || '').replace(/\s+/g, ' ').trim().slice(0, 500);
|
|
923
972
|
}
|
|
924
973
|
|
|
974
|
+
const CODEX_USER_ECHO_DEDUP_WINDOW_MS = 5000;
|
|
975
|
+
|
|
976
|
+
function _codexTimestampMs(timestamp) {
|
|
977
|
+
const value = String(timestamp || '').trim();
|
|
978
|
+
if (!value) return null;
|
|
979
|
+
const ms = Date.parse(value);
|
|
980
|
+
return Number.isFinite(ms) ? ms : null;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
function createCodexUserDeduper(seedMessages = [], options = {}) {
|
|
984
|
+
const windowMs = Math.max(0, Number(options.windowMs ?? CODEX_USER_ECHO_DEDUP_WINDOW_MS));
|
|
985
|
+
const byText = new Map();
|
|
986
|
+
|
|
987
|
+
const rememberKey = (key, timestamp) => {
|
|
988
|
+
if (!key) return false;
|
|
989
|
+
const tsMs = _codexTimestampMs(timestamp);
|
|
990
|
+
let seen = byText.get(key);
|
|
991
|
+
if (!seen) {
|
|
992
|
+
seen = [];
|
|
993
|
+
byText.set(key, seen);
|
|
994
|
+
}
|
|
995
|
+
for (const prior of seen) {
|
|
996
|
+
if (tsMs == null || prior == null) return false;
|
|
997
|
+
if (Math.abs(tsMs - prior) <= windowMs) return false;
|
|
998
|
+
}
|
|
999
|
+
seen.push(tsMs);
|
|
1000
|
+
if (seen.length > 256) seen.splice(0, seen.length - 256);
|
|
1001
|
+
return true;
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
const deduper = {
|
|
1005
|
+
remember(text, timestamp) {
|
|
1006
|
+
return rememberKey(codexUserKey(text), timestamp);
|
|
1007
|
+
},
|
|
1008
|
+
has(text, timestamp) {
|
|
1009
|
+
const key = codexUserKey(text);
|
|
1010
|
+
if (!key) return false;
|
|
1011
|
+
const tsMs = _codexTimestampMs(timestamp);
|
|
1012
|
+
const seen = byText.get(key) || [];
|
|
1013
|
+
return seen.some((prior) => {
|
|
1014
|
+
if (tsMs == null || prior == null) return true;
|
|
1015
|
+
return Math.abs(tsMs - prior) <= windowMs;
|
|
1016
|
+
});
|
|
1017
|
+
},
|
|
1018
|
+
seed(message) {
|
|
1019
|
+
if (!message) return false;
|
|
1020
|
+
const text = message.text || message.content || message.message || '';
|
|
1021
|
+
const timestamp = message.timestamp || message.created_at || message.createdAt || '';
|
|
1022
|
+
return this.remember(text, timestamp);
|
|
1023
|
+
},
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
if (seedMessages instanceof Set) {
|
|
1027
|
+
for (const key of seedMessages) rememberKey(key, null);
|
|
1028
|
+
} else {
|
|
1029
|
+
for (const message of Array.isArray(seedMessages) ? seedMessages : []) deduper.seed(message);
|
|
1030
|
+
}
|
|
1031
|
+
return deduper;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
function normalizeCodexUserDeduper(value) {
|
|
1035
|
+
if (value && typeof value.remember === 'function') return value;
|
|
1036
|
+
return createCodexUserDeduper(value instanceof Set ? value : []);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
925
1039
|
function codexInputText(content) {
|
|
926
1040
|
if (typeof content === 'string') return content;
|
|
927
1041
|
if (!Array.isArray(content)) return '';
|
|
@@ -940,6 +1054,113 @@ function codexAssistantText(content) {
|
|
|
940
1054
|
.trim();
|
|
941
1055
|
}
|
|
942
1056
|
|
|
1057
|
+
// Structured capture for Codex rollout items the legacy text parser drops:
|
|
1058
|
+
// reasoning, function/tool/shell calls + outputs, apply_patch, web search,
|
|
1059
|
+
// and compaction markers. Returns ONE message, an ARRAY of messages, or null.
|
|
1060
|
+
// Kept separate from codexMessageFromEntry on purpose — session-stream,
|
|
1061
|
+
// transcript-store, and relink-audit consume that function directly and must
|
|
1062
|
+
// keep their user/assistant-only behavior. Only appendCodexEntryMessage (the
|
|
1063
|
+
// conversation parse path) consults this.
|
|
1064
|
+
function codexStructuredMessageFromEntry(entry) {
|
|
1065
|
+
if (!entry || typeof entry !== 'object') return null;
|
|
1066
|
+
const timestamp = entry.timestamp || '';
|
|
1067
|
+
|
|
1068
|
+
if (entry.type === 'compacted') {
|
|
1069
|
+
const out = [structuredCapture.compactBoundaryMessage({ provider: 'codex', timestamp })];
|
|
1070
|
+
const summaryText = typeof entry.payload?.message === 'string' ? entry.payload.message.trim() : '';
|
|
1071
|
+
if (summaryText) {
|
|
1072
|
+
out.push(structuredCapture.compactSummaryMessage({ provider: 'codex', text: summaryText, timestamp }));
|
|
1073
|
+
}
|
|
1074
|
+
return out;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
if (entry.type !== 'response_item' || !entry.payload || typeof entry.payload !== 'object') return null;
|
|
1078
|
+
const p = entry.payload;
|
|
1079
|
+
|
|
1080
|
+
switch (p.type) {
|
|
1081
|
+
case 'reasoning': {
|
|
1082
|
+
const blockText = (blocks) => Array.isArray(blocks)
|
|
1083
|
+
? blocks.filter((b) => b && typeof b.text === 'string' && b.text).map((b) => b.text).join('\n')
|
|
1084
|
+
: '';
|
|
1085
|
+
const text = (blockText(p.summary) || blockText(p.content) || '').trim();
|
|
1086
|
+
if (text) return structuredCapture.reasoningMessage({ provider: 'codex', text, timestamp });
|
|
1087
|
+
if (p.encrypted_content) return structuredCapture.reasoningMessage({ provider: 'codex', encrypted: true, timestamp });
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
case 'function_call': {
|
|
1091
|
+
const name = String(p.name || '').trim();
|
|
1092
|
+
let parsedArgs = null;
|
|
1093
|
+
if (typeof p.arguments === 'string') { try { parsedArgs = JSON.parse(p.arguments); } catch {} }
|
|
1094
|
+
else if (p.arguments && typeof p.arguments === 'object') parsedArgs = p.arguments;
|
|
1095
|
+
const patch = structuredCapture.detectApplyPatch({
|
|
1096
|
+
name,
|
|
1097
|
+
argumentsJson: p.arguments,
|
|
1098
|
+
command: parsedArgs && parsedArgs.command,
|
|
1099
|
+
});
|
|
1100
|
+
if (patch) {
|
|
1101
|
+
return structuredCapture.patchMessage({
|
|
1102
|
+
provider: 'codex', patchText: patch.patchText, files: patch.files, callId: p.call_id, timestamp,
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
if ((name === 'shell' || name === 'container.exec' || name === 'exec_command')
|
|
1106
|
+
&& parsedArgs && parsedArgs.command) {
|
|
1107
|
+
return structuredCapture.shellMessage({ provider: 'codex', command: parsedArgs.command, callId: p.call_id, timestamp });
|
|
1108
|
+
}
|
|
1109
|
+
return structuredCapture.toolCallMessage({ provider: 'codex', tool: name || 'tool', callId: p.call_id, args: p.arguments, timestamp });
|
|
1110
|
+
}
|
|
1111
|
+
case 'function_call_output':
|
|
1112
|
+
case 'custom_tool_call_output': {
|
|
1113
|
+
let outputText = typeof p.output === 'string' ? p.output
|
|
1114
|
+
: (p.output != null ? JSON.stringify(p.output) : '');
|
|
1115
|
+
let exitCode;
|
|
1116
|
+
let durationMs;
|
|
1117
|
+
if (outputText.startsWith('{')) {
|
|
1118
|
+
// Shell outputs arrive as a JSON envelope: {"output", "metadata": {"exit_code", "duration_seconds"}}
|
|
1119
|
+
try {
|
|
1120
|
+
const parsed = JSON.parse(outputText);
|
|
1121
|
+
if (parsed && typeof parsed === 'object') {
|
|
1122
|
+
if (typeof parsed.output === 'string') outputText = parsed.output;
|
|
1123
|
+
const md = parsed.metadata || {};
|
|
1124
|
+
if (Number.isFinite(Number(md.exit_code))) exitCode = Number(md.exit_code);
|
|
1125
|
+
if (Number.isFinite(Number(md.duration_seconds))) durationMs = Math.round(Number(md.duration_seconds) * 1000);
|
|
1126
|
+
}
|
|
1127
|
+
} catch {}
|
|
1128
|
+
}
|
|
1129
|
+
return structuredCapture.toolResultMessage({
|
|
1130
|
+
provider: 'codex', callId: p.call_id, output: outputText, exitCode, durationMs, timestamp,
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
case 'local_shell_call': {
|
|
1134
|
+
const action = p.action || {};
|
|
1135
|
+
const command = Array.isArray(action.command) ? action.command : [];
|
|
1136
|
+
const patch = structuredCapture.detectApplyPatch({ command });
|
|
1137
|
+
if (patch) {
|
|
1138
|
+
return structuredCapture.patchMessage({
|
|
1139
|
+
provider: 'codex', patchText: patch.patchText, files: patch.files, callId: p.call_id, timestamp,
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
return structuredCapture.shellMessage({ provider: 'codex', command, callId: p.call_id, timestamp });
|
|
1143
|
+
}
|
|
1144
|
+
case 'custom_tool_call': {
|
|
1145
|
+
const name = String(p.name || '').trim();
|
|
1146
|
+
const patch = structuredCapture.detectApplyPatch({ name, input: p.input });
|
|
1147
|
+
if (patch) {
|
|
1148
|
+
return structuredCapture.patchMessage({
|
|
1149
|
+
provider: 'codex', patchText: patch.patchText, files: patch.files, callId: p.call_id, timestamp,
|
|
1150
|
+
});
|
|
1151
|
+
}
|
|
1152
|
+
return structuredCapture.toolCallMessage({ provider: 'codex', tool: name || 'tool', callId: p.call_id, args: p.input, timestamp });
|
|
1153
|
+
}
|
|
1154
|
+
case 'web_search_call': {
|
|
1155
|
+
const action = p.action || {};
|
|
1156
|
+
const query = String(action.query || p.query || '').trim();
|
|
1157
|
+
return structuredCapture.webSearchMessage({ provider: 'codex', query: query || 'web search', timestamp });
|
|
1158
|
+
}
|
|
1159
|
+
default:
|
|
1160
|
+
return null;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
943
1164
|
function codexMessageFromEntry(entry) {
|
|
944
1165
|
if (!entry || typeof entry !== 'object') return null;
|
|
945
1166
|
|
|
@@ -964,64 +1185,93 @@ function codexMessageFromEntry(entry) {
|
|
|
964
1185
|
function codexSessionMetaFromEntry(entry) {
|
|
965
1186
|
if (!entry || entry.type !== 'session_meta') return null;
|
|
966
1187
|
const payload = entry.payload || {};
|
|
1188
|
+
const lineage = codexSessionLineageFromPayload(payload);
|
|
967
1189
|
return {
|
|
968
1190
|
id: payload.id || '',
|
|
969
1191
|
cwd: payload.cwd || '',
|
|
970
1192
|
model: payload.model || payload.model_id || '',
|
|
971
1193
|
git_branch: payload.git_branch || '',
|
|
972
1194
|
timestamp: payload.timestamp || entry.timestamp || '',
|
|
1195
|
+
source: lineage.source,
|
|
1196
|
+
thread_source: lineage.thread_source,
|
|
1197
|
+
parent_agent_session_id: lineage.parent_agent_session_id,
|
|
1198
|
+
parent_thread_id: lineage.parent_thread_id,
|
|
1199
|
+
agent_nickname: lineage.agent_nickname,
|
|
1200
|
+
agent_role: lineage.agent_role,
|
|
973
1201
|
};
|
|
974
1202
|
}
|
|
975
1203
|
|
|
976
1204
|
function appendCodexEntryMessage(entry, messages, seenUsers) {
|
|
977
1205
|
if (!entry || typeof entry !== 'object') return false;
|
|
978
1206
|
const msg = codexMessageFromEntry(entry);
|
|
979
|
-
if (!msg)
|
|
1207
|
+
if (!msg) {
|
|
1208
|
+
// Structured capture: items the text parser drops (reasoning, tool/shell
|
|
1209
|
+
// calls + outputs, patches, web search, compaction). role:'system' rows —
|
|
1210
|
+
// the user echo deduper does not apply.
|
|
1211
|
+
if (!structuredCapture.structuredCaptureEnabled()) return false;
|
|
1212
|
+
const structured = codexStructuredMessageFromEntry(entry);
|
|
1213
|
+
if (!structured) return false;
|
|
1214
|
+
for (const m of Array.isArray(structured) ? structured : [structured]) messages.push(m);
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
980
1217
|
if (msg.role === 'user') {
|
|
981
|
-
const
|
|
982
|
-
if (!
|
|
983
|
-
seenUsers.add(key);
|
|
1218
|
+
const deduper = normalizeCodexUserDeduper(seenUsers);
|
|
1219
|
+
if (!deduper.remember(msg.text, msg.timestamp)) return false;
|
|
984
1220
|
}
|
|
985
1221
|
messages.push(msg);
|
|
986
1222
|
return true;
|
|
987
1223
|
}
|
|
988
1224
|
|
|
989
|
-
function
|
|
990
|
-
if (!line || !line.trim()) return false;
|
|
1225
|
+
function parseCodexJsonlRecord(line, messages, state) {
|
|
1226
|
+
if (!line || !line.trim()) return { valid: true, messageAdded: false };
|
|
991
1227
|
let entry;
|
|
992
|
-
try { entry = JSON.parse(line); } catch { return false; }
|
|
993
|
-
if (!entry || typeof entry !== 'object') return false;
|
|
1228
|
+
try { entry = JSON.parse(line); } catch { return { valid: false, messageAdded: false }; }
|
|
1229
|
+
if (!entry || typeof entry !== 'object') return { valid: false, messageAdded: false };
|
|
994
1230
|
if (!state.sessionMeta) {
|
|
995
1231
|
const meta = codexSessionMetaFromEntry(entry);
|
|
996
1232
|
if (meta?.id) state.sessionMeta = meta;
|
|
997
1233
|
}
|
|
998
|
-
return appendCodexEntryMessage(entry, messages, state.seenUsers);
|
|
1234
|
+
return { valid: true, messageAdded: appendCodexEntryMessage(entry, messages, state.seenUsers) };
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
function parseCodexJsonlLine(line, messages, state) {
|
|
1238
|
+
return parseCodexJsonlRecord(line, messages, state).messageAdded;
|
|
999
1239
|
}
|
|
1000
1240
|
|
|
1001
1241
|
function parseCodexJsonlIntoMessages(content, messages, options = {}) {
|
|
1002
1242
|
const raw = String(content || '');
|
|
1003
1243
|
const state = {
|
|
1004
|
-
seenUsers: options.
|
|
1244
|
+
seenUsers: normalizeCodexUserDeduper(options.codexUserDeduper || options.seenUsers),
|
|
1005
1245
|
sessionMeta: null,
|
|
1006
1246
|
};
|
|
1007
1247
|
const before = messages.length;
|
|
1008
1248
|
let linesRead = 0;
|
|
1249
|
+
let completeBytesRead = 0;
|
|
1009
1250
|
|
|
1010
1251
|
let start = 0;
|
|
1011
|
-
while (start
|
|
1012
|
-
|
|
1013
|
-
if (end === -1)
|
|
1252
|
+
while (start < raw.length) {
|
|
1253
|
+
const end = raw.indexOf('\n', start);
|
|
1254
|
+
if (end === -1) {
|
|
1255
|
+
const line = raw.slice(start);
|
|
1256
|
+
if (line) {
|
|
1257
|
+
linesRead++;
|
|
1258
|
+
const parsed = parseCodexJsonlRecord(line, messages, state);
|
|
1259
|
+
if (parsed.valid) completeBytesRead += Buffer.byteLength(line);
|
|
1260
|
+
}
|
|
1261
|
+
break;
|
|
1262
|
+
}
|
|
1014
1263
|
const line = raw.slice(start, end);
|
|
1264
|
+
completeBytesRead += Buffer.byteLength(line) + 1;
|
|
1015
1265
|
if (line) {
|
|
1016
1266
|
linesRead++;
|
|
1017
|
-
|
|
1267
|
+
parseCodexJsonlRecord(line, messages, state);
|
|
1018
1268
|
}
|
|
1019
|
-
if (end === raw.length) break;
|
|
1020
1269
|
start = end + 1;
|
|
1021
1270
|
}
|
|
1022
1271
|
|
|
1023
1272
|
return {
|
|
1024
1273
|
bytesRead: Buffer.byteLength(raw),
|
|
1274
|
+
completeBytesRead,
|
|
1025
1275
|
linesRead,
|
|
1026
1276
|
messagesAdded: messages.length - before,
|
|
1027
1277
|
sessionMeta: state.sessionMeta,
|
|
@@ -1029,8 +1279,12 @@ function parseCodexJsonlIntoMessages(content, messages, options = {}) {
|
|
|
1029
1279
|
}
|
|
1030
1280
|
|
|
1031
1281
|
function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
1282
|
+
const readPath = _codexReadablePath(filePath);
|
|
1283
|
+
if (!readPath) {
|
|
1284
|
+
return { bytesRead: 0, completeBytesRead: 0, linesRead: 0, messagesAdded: 0, sessionMeta: null, failed: 1, compressed: true };
|
|
1285
|
+
}
|
|
1032
1286
|
const state = {
|
|
1033
|
-
seenUsers: options.
|
|
1287
|
+
seenUsers: normalizeCodexUserDeduper(options.codexUserDeduper || options.seenUsers),
|
|
1034
1288
|
sessionMeta: null,
|
|
1035
1289
|
};
|
|
1036
1290
|
const before = messages.length;
|
|
@@ -1038,12 +1292,13 @@ function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1038
1292
|
const buf = Buffer.alloc(chunkSize);
|
|
1039
1293
|
const decoder = new StringDecoder('utf8');
|
|
1040
1294
|
let bytesReadTotal = 0;
|
|
1295
|
+
let completeBytesRead = 0;
|
|
1041
1296
|
let linesRead = 0;
|
|
1042
1297
|
let partial = '';
|
|
1043
1298
|
let fd = null;
|
|
1044
1299
|
|
|
1045
1300
|
try {
|
|
1046
|
-
fd = fs.openSync(
|
|
1301
|
+
fd = fs.openSync(readPath, 'r');
|
|
1047
1302
|
while (true) {
|
|
1048
1303
|
const bytesRead = fs.readSync(fd, buf, 0, buf.length, null);
|
|
1049
1304
|
if (bytesRead <= 0) break;
|
|
@@ -1054,9 +1309,10 @@ function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1054
1309
|
const end = text.indexOf('\n', start);
|
|
1055
1310
|
if (end === -1) break;
|
|
1056
1311
|
const line = text.slice(start, end);
|
|
1312
|
+
completeBytesRead += Buffer.byteLength(line) + 1;
|
|
1057
1313
|
if (line) {
|
|
1058
1314
|
linesRead++;
|
|
1059
|
-
|
|
1315
|
+
parseCodexJsonlRecord(line, messages, state);
|
|
1060
1316
|
}
|
|
1061
1317
|
start = end + 1;
|
|
1062
1318
|
}
|
|
@@ -1066,7 +1322,8 @@ function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1066
1322
|
if (tail) partial += tail;
|
|
1067
1323
|
if (partial && partial.trim()) {
|
|
1068
1324
|
linesRead++;
|
|
1069
|
-
|
|
1325
|
+
const parsed = parseCodexJsonlRecord(partial, messages, state);
|
|
1326
|
+
if (parsed.valid) completeBytesRead += Buffer.byteLength(partial);
|
|
1070
1327
|
}
|
|
1071
1328
|
} finally {
|
|
1072
1329
|
try { if (fd != null) fs.closeSync(fd); } catch {}
|
|
@@ -1074,6 +1331,78 @@ function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1074
1331
|
|
|
1075
1332
|
return {
|
|
1076
1333
|
bytesRead: bytesReadTotal,
|
|
1334
|
+
completeBytesRead,
|
|
1335
|
+
linesRead,
|
|
1336
|
+
messagesAdded: messages.length - before,
|
|
1337
|
+
sessionMeta: state.sessionMeta,
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
async function parseCodexJsonlFileIntoMessagesAsync(filePath, messages, options = {}) {
|
|
1342
|
+
const state = {
|
|
1343
|
+
seenUsers: normalizeCodexUserDeduper(options.codexUserDeduper || options.seenUsers),
|
|
1344
|
+
sessionMeta: null,
|
|
1345
|
+
};
|
|
1346
|
+
const before = messages.length;
|
|
1347
|
+
const chunkSize = options.chunkSize || 1024 * 1024;
|
|
1348
|
+
const yieldAfterMs = Math.max(5, Number(options.yieldAfterMs || 25));
|
|
1349
|
+
const buf = Buffer.alloc(chunkSize);
|
|
1350
|
+
const decoder = new StringDecoder('utf8');
|
|
1351
|
+
let bytesReadTotal = 0;
|
|
1352
|
+
let completeBytesRead = 0;
|
|
1353
|
+
let linesRead = 0;
|
|
1354
|
+
let partial = '';
|
|
1355
|
+
let lastYieldAt = Date.now();
|
|
1356
|
+
let fh = null;
|
|
1357
|
+
|
|
1358
|
+
async function maybeYield() {
|
|
1359
|
+
if (Date.now() - lastYieldAt < yieldAfterMs) return;
|
|
1360
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
1361
|
+
lastYieldAt = Date.now();
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
const readPath = _codexReadablePath(filePath);
|
|
1365
|
+
if (!readPath) {
|
|
1366
|
+
return { bytesRead: 0, completeBytesRead: 0, linesRead: 0, messagesAdded: 0, sessionMeta: null, failed: 1, compressed: true };
|
|
1367
|
+
}
|
|
1368
|
+
try {
|
|
1369
|
+
fh = await fs.promises.open(readPath, 'r');
|
|
1370
|
+
let position = 0;
|
|
1371
|
+
while (true) {
|
|
1372
|
+
const { bytesRead } = await fh.read(buf, 0, buf.length, position);
|
|
1373
|
+
if (bytesRead <= 0) break;
|
|
1374
|
+
position += bytesRead;
|
|
1375
|
+
bytesReadTotal += bytesRead;
|
|
1376
|
+
const text = partial + decoder.write(buf.subarray(0, bytesRead));
|
|
1377
|
+
let start = 0;
|
|
1378
|
+
while (true) {
|
|
1379
|
+
const end = text.indexOf('\n', start);
|
|
1380
|
+
if (end === -1) break;
|
|
1381
|
+
const line = text.slice(start, end);
|
|
1382
|
+
completeBytesRead += Buffer.byteLength(line) + 1;
|
|
1383
|
+
if (line) {
|
|
1384
|
+
linesRead++;
|
|
1385
|
+
parseCodexJsonlRecord(line, messages, state);
|
|
1386
|
+
}
|
|
1387
|
+
start = end + 1;
|
|
1388
|
+
}
|
|
1389
|
+
partial = text.slice(start);
|
|
1390
|
+
await maybeYield();
|
|
1391
|
+
}
|
|
1392
|
+
const tail = decoder.end();
|
|
1393
|
+
if (tail) partial += tail;
|
|
1394
|
+
if (partial && partial.trim()) {
|
|
1395
|
+
linesRead++;
|
|
1396
|
+
const parsed = parseCodexJsonlRecord(partial, messages, state);
|
|
1397
|
+
if (parsed.valid) completeBytesRead += Buffer.byteLength(partial);
|
|
1398
|
+
}
|
|
1399
|
+
} finally {
|
|
1400
|
+
try { if (fh) await fh.close(); } catch {}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
return {
|
|
1404
|
+
bytesRead: bytesReadTotal,
|
|
1405
|
+
completeBytesRead,
|
|
1077
1406
|
linesRead,
|
|
1078
1407
|
messagesAdded: messages.length - before,
|
|
1079
1408
|
sessionMeta: state.sessionMeta,
|
|
@@ -1082,8 +1411,13 @@ function parseCodexJsonlFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1082
1411
|
|
|
1083
1412
|
function parseCodexJsonlTailFileIntoMessages(filePath, messages, options = {}) {
|
|
1084
1413
|
const maxBytes = Math.max(1, Number(options.maxBytes || 10 * 1024 * 1024));
|
|
1414
|
+
// A compressed archive can't be range-read — tail the materialized copy.
|
|
1415
|
+
const readPath = _codexReadablePath(filePath);
|
|
1416
|
+
if (!readPath) {
|
|
1417
|
+
return { bytesRead: 0, linesRead: 0, messagesAdded: 0, fileSize: 0, partial: false, failed: 1, compressed: true };
|
|
1418
|
+
}
|
|
1085
1419
|
let stat;
|
|
1086
|
-
try { stat = fs.statSync(
|
|
1420
|
+
try { stat = fs.statSync(readPath); } catch {
|
|
1087
1421
|
return { bytesRead: 0, linesRead: 0, messagesAdded: 0, fileSize: 0, partial: false, failed: 1 };
|
|
1088
1422
|
}
|
|
1089
1423
|
const size = Number(stat.size || 0);
|
|
@@ -1095,7 +1429,7 @@ function parseCodexJsonlTailFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1095
1429
|
const startOffset = Math.max(0, size - readSize);
|
|
1096
1430
|
let fd = null;
|
|
1097
1431
|
try {
|
|
1098
|
-
fd = fs.openSync(
|
|
1432
|
+
fd = fs.openSync(readPath, 'r');
|
|
1099
1433
|
const buf = Buffer.alloc(readSize);
|
|
1100
1434
|
const bytesRead = fs.readSync(fd, buf, 0, readSize, startOffset);
|
|
1101
1435
|
let content = buf.toString('utf8', 0, bytesRead);
|
|
@@ -1104,7 +1438,7 @@ function parseCodexJsonlTailFileIntoMessages(filePath, messages, options = {}) {
|
|
|
1104
1438
|
content = nlIdx >= 0 ? content.slice(nlIdx + 1) : '';
|
|
1105
1439
|
}
|
|
1106
1440
|
const before = messages.length;
|
|
1107
|
-
const parsed = parseCodexJsonlIntoMessages(content, messages, {
|
|
1441
|
+
const parsed = parseCodexJsonlIntoMessages(content, messages, { codexUserDeduper: options.codexUserDeduper || options.seenUsers });
|
|
1108
1442
|
return {
|
|
1109
1443
|
...parsed,
|
|
1110
1444
|
bytesRead,
|
|
@@ -1164,8 +1498,10 @@ function codexSearchMatchForMessage(msg, terms, order) {
|
|
|
1164
1498
|
}
|
|
1165
1499
|
|
|
1166
1500
|
function searchCodexRolloutFileMessages(filePath, terms, row) {
|
|
1167
|
-
const state = {
|
|
1501
|
+
const state = { codexUserDeduper: createCodexUserDeduper(), sessionMeta: null };
|
|
1168
1502
|
const matches = [];
|
|
1503
|
+
const readPath = _codexReadablePath(filePath);
|
|
1504
|
+
if (!readPath) return matches;
|
|
1169
1505
|
const chunkSize = 1024 * 1024;
|
|
1170
1506
|
const buf = Buffer.alloc(chunkSize);
|
|
1171
1507
|
const decoder = new StringDecoder('utf8');
|
|
@@ -1174,7 +1510,7 @@ function searchCodexRolloutFileMessages(filePath, terms, row) {
|
|
|
1174
1510
|
let order = 0;
|
|
1175
1511
|
|
|
1176
1512
|
try {
|
|
1177
|
-
fd = fs.openSync(
|
|
1513
|
+
fd = fs.openSync(readPath, 'r');
|
|
1178
1514
|
while (true) {
|
|
1179
1515
|
const bytesRead = fs.readSync(fd, buf, 0, buf.length, null);
|
|
1180
1516
|
if (bytesRead <= 0) break;
|
|
@@ -1195,12 +1531,10 @@ function searchCodexRolloutFileMessages(filePath, terms, row) {
|
|
|
1195
1531
|
const msg = codexMessageFromEntry(entry);
|
|
1196
1532
|
if (msg) {
|
|
1197
1533
|
if (msg.role === 'user') {
|
|
1198
|
-
|
|
1199
|
-
if (!key || state.seenUsers.has(key)) {
|
|
1534
|
+
if (!state.codexUserDeduper.remember(msg.text, msg.timestamp)) {
|
|
1200
1535
|
start = end + 1;
|
|
1201
1536
|
continue;
|
|
1202
1537
|
}
|
|
1203
|
-
state.seenUsers.add(key);
|
|
1204
1538
|
}
|
|
1205
1539
|
const match = codexSearchMatchForMessage(msg, terms, order++);
|
|
1206
1540
|
if (match) matches.push(match);
|
|
@@ -1225,11 +1559,8 @@ function searchCodexRolloutFileMessages(filePath, terms, row) {
|
|
|
1225
1559
|
if (msg) {
|
|
1226
1560
|
let shouldConsider = true;
|
|
1227
1561
|
if (msg.role === 'user') {
|
|
1228
|
-
|
|
1229
|
-
if (!key || state.seenUsers.has(key)) {
|
|
1562
|
+
if (!state.codexUserDeduper.remember(msg.text, msg.timestamp)) {
|
|
1230
1563
|
shouldConsider = false;
|
|
1231
|
-
} else {
|
|
1232
|
-
state.seenUsers.add(key);
|
|
1233
1564
|
}
|
|
1234
1565
|
}
|
|
1235
1566
|
const match = shouldConsider ? codexSearchMatchForMessage(msg, terms, order++) : null;
|
|
@@ -1305,6 +1636,11 @@ function mergeCodexRecentThreadRow(existing, incoming) {
|
|
|
1305
1636
|
updated_at: Math.max(base.updated_at || 0, other.updated_at || 0),
|
|
1306
1637
|
providerResumeId: base.providerResumeId || other.providerResumeId || '',
|
|
1307
1638
|
providerResumeIds: [...providerResumeIds],
|
|
1639
|
+
thread_source: base.thread_source || other.thread_source || '',
|
|
1640
|
+
parent_agent_session_id: base.parent_agent_session_id || base.parent_thread_id || other.parent_agent_session_id || other.parent_thread_id || '',
|
|
1641
|
+
parent_thread_id: base.parent_thread_id || base.parent_agent_session_id || other.parent_thread_id || other.parent_agent_session_id || '',
|
|
1642
|
+
agent_nickname: base.agent_nickname || other.agent_nickname || '',
|
|
1643
|
+
agent_role: base.agent_role || other.agent_role || '',
|
|
1308
1644
|
_jsonlPath: base._jsonlPath || other._jsonlPath || '',
|
|
1309
1645
|
_fileSize: base._fileSize || other._fileSize || 0,
|
|
1310
1646
|
_modifiedAt: base._modifiedAt || other._modifiedAt || '',
|
|
@@ -1331,6 +1667,11 @@ function normalizeCodexRecentThreadRows(rows, getRolloutInfo = () => ({})) {
|
|
|
1331
1667
|
id: canonicalId,
|
|
1332
1668
|
providerResumeId,
|
|
1333
1669
|
providerResumeIds,
|
|
1670
|
+
thread_source: row.thread_source || '',
|
|
1671
|
+
parent_agent_session_id: row.parent_agent_session_id || row.parent_thread_id || '',
|
|
1672
|
+
parent_thread_id: row.parent_thread_id || row.parent_agent_session_id || '',
|
|
1673
|
+
agent_nickname: row.agent_nickname || '',
|
|
1674
|
+
agent_role: row.agent_role || '',
|
|
1334
1675
|
_originalThreadId: originalThreadId,
|
|
1335
1676
|
_jsonlPath: rolloutPath,
|
|
1336
1677
|
_fileSize: rolloutInfo.fileSize || row._fileSize || 0,
|
|
@@ -1437,7 +1778,7 @@ function listCodexSessionsFromRollouts(homeDir = process.env.HOME, limit = 50, o
|
|
|
1437
1778
|
for (const entry of entries) {
|
|
1438
1779
|
const fullPath = path.join(dir, entry.name);
|
|
1439
1780
|
if (entry.isDirectory()) { stack.push(fullPath); continue; }
|
|
1440
|
-
if (!entry.isFile() || !entry.name
|
|
1781
|
+
if (!entry.isFile() || !isCodexRolloutCandidateName(entry.name)) continue;
|
|
1441
1782
|
let row = _readCodexRolloutMetadata(fullPath);
|
|
1442
1783
|
if (!row) continue;
|
|
1443
1784
|
row = _codexRolloutRowWithFileInfo(row, fullPath);
|
|
@@ -1474,10 +1815,13 @@ module.exports = {
|
|
|
1474
1815
|
cleanCodexUserText,
|
|
1475
1816
|
codexInputText,
|
|
1476
1817
|
codexMessageFromEntry,
|
|
1818
|
+
codexStructuredMessageFromEntry,
|
|
1819
|
+
isCodexRolloutCandidateName,
|
|
1477
1820
|
codexRolloutFileInfo,
|
|
1478
1821
|
codexRolloutFileMatchesThread,
|
|
1479
1822
|
codexRolloutIdFromPath,
|
|
1480
1823
|
codexUserKey,
|
|
1824
|
+
createCodexUserDeduper,
|
|
1481
1825
|
checkCodexStateIntegrity,
|
|
1482
1826
|
extractResumeTarget,
|
|
1483
1827
|
findCodexSessionFiles,
|
|
@@ -1504,5 +1848,6 @@ module.exports = {
|
|
|
1504
1848
|
parseSessionStartMs,
|
|
1505
1849
|
parseCodexJsonlIntoMessages,
|
|
1506
1850
|
parseCodexJsonlFileIntoMessages,
|
|
1851
|
+
parseCodexJsonlFileIntoMessagesAsync,
|
|
1507
1852
|
parseCodexJsonlTailFileIntoMessages,
|
|
1508
1853
|
};
|