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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_RESTORE_ACTIVITY_SUPPRESSION_MS = 10_000;
|
|
4
|
+
|
|
5
|
+
function numericMs(value) {
|
|
6
|
+
const n = Number(value || 0);
|
|
7
|
+
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function restoreHoldMs(runningHoldMs = 0) {
|
|
11
|
+
return Math.max(DEFAULT_RESTORE_ACTIVITY_SUPPRESSION_MS, numericMs(runningHoldMs));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function beginRestoreState(session, opts = {}) {
|
|
15
|
+
if (!session) return null;
|
|
16
|
+
const now = numericMs(opts.now) || Date.now();
|
|
17
|
+
const until = now + restoreHoldMs(opts.runningHoldMs);
|
|
18
|
+
session._restoredFromStartup = true;
|
|
19
|
+
session._restoreStarting = true;
|
|
20
|
+
session._restoreStartingUntil = until;
|
|
21
|
+
session._restoreActivitySuppressUntil = until;
|
|
22
|
+
session._restoreStartedAt = now;
|
|
23
|
+
return { until };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function restoreStartingActive(session, now = Date.now()) {
|
|
27
|
+
if (!session || !session._restoreStarting) return false;
|
|
28
|
+
const until = numericMs(session._restoreStartingUntil);
|
|
29
|
+
return !until || now < until;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function restoreActivitySuppressed(session, now = Date.now()) {
|
|
33
|
+
if (!session) return false;
|
|
34
|
+
const until = numericMs(session._restoreActivitySuppressUntil);
|
|
35
|
+
if (!until || now >= until) return false;
|
|
36
|
+
const startedAt = numericMs(session._restoreStartedAt);
|
|
37
|
+
const lastUserInputAt = numericMs(session.lastUserInputAt);
|
|
38
|
+
return !(lastUserInputAt && (!startedAt || lastUserInputAt >= startedAt));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function clearRestoreState(session) {
|
|
42
|
+
if (!session) return session;
|
|
43
|
+
session._restoredFromStartup = false;
|
|
44
|
+
session._restoreStarting = false;
|
|
45
|
+
session._restoreStartingUntil = 0;
|
|
46
|
+
session._restoreActivitySuppressUntil = 0;
|
|
47
|
+
session._restoreStartedAt = 0;
|
|
48
|
+
return session;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function markUserInput(session, now = Date.now()) {
|
|
52
|
+
if (!session) return session;
|
|
53
|
+
session.lastUserInputAt = now;
|
|
54
|
+
if (restoreStartingActive(session, now) || restoreActivitySuppressed(session, now)) {
|
|
55
|
+
clearRestoreState(session);
|
|
56
|
+
}
|
|
57
|
+
return session;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
DEFAULT_RESTORE_ACTIVITY_SUPPRESSION_MS,
|
|
62
|
+
beginRestoreState,
|
|
63
|
+
clearRestoreState,
|
|
64
|
+
markUserInput,
|
|
65
|
+
restoreActivitySuppressed,
|
|
66
|
+
restoreHoldMs,
|
|
67
|
+
restoreStartingActive,
|
|
68
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Decision logic for the post-restore read-pool stampede (pure; unit-tested in
|
|
4
|
+
// tests/restore-storm.test.js). See that file's header for the problem statement.
|
|
5
|
+
//
|
|
6
|
+
// Used by server.js to (A) keep the generous off-thread read timeout active through the
|
|
7
|
+
// restore window AND a grace period after it, so cold reads finish ON the pool instead of
|
|
8
|
+
// bailing to a main-thread compute; and (B) when an off-thread read still fails during the
|
|
9
|
+
// storm (pool wedged → breaker open, or even the long timeout exceeded), serve a degraded
|
|
10
|
+
// value instead of freezing the event loop with a synchronous main-thread build.
|
|
11
|
+
|
|
12
|
+
// True for the whole storm window: while the restore loop runs, plus a grace period after
|
|
13
|
+
// it completes. The grace covers the SECOND stampede — the post-restore broadcast +
|
|
14
|
+
// auto-resume + every UI tab cold-loading at once — which lands just after the loop clears
|
|
15
|
+
// _restoreInProgress, exactly when the protection used to switch off.
|
|
16
|
+
function inRestoreStorm({ restoreInProgress, restoreCompletedAt, now, graceMs }) {
|
|
17
|
+
if (restoreInProgress) return true;
|
|
18
|
+
if (!(restoreCompletedAt > 0)) return false;
|
|
19
|
+
return (now - restoreCompletedAt) < graceMs;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Decide what an off-thread read's onFail serves when the pool didn't answer:
|
|
23
|
+
// * a last-good cached value, if present — always preferred, never stale-blocks;
|
|
24
|
+
// * during the storm with no cache — the degraded value (e.g. [] / empty), so the heavy
|
|
25
|
+
// compute NEVER runs on the main loop (the freeze we're eliminating);
|
|
26
|
+
// * only when calm AND cold — build once on the main thread, so a normal cold cache miss
|
|
27
|
+
// still returns an immediate, correct result (boot/first-load recovers without a retry).
|
|
28
|
+
function offthreadFallback({ inStorm, hasCached, cached, mainCompute, stormEmpty }) {
|
|
29
|
+
if (hasCached) return cached;
|
|
30
|
+
if (inStorm) return stormEmpty;
|
|
31
|
+
return mainCompute();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = { inRestoreStorm, offthreadFallback };
|
|
@@ -12,6 +12,37 @@ function normalizeCwd(value) {
|
|
|
12
12
|
return path.normalize(path.isAbsolute(expanded) ? expanded : path.resolve(expanded));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
function canonicalizeClaudeProjectPath(cwd, opts = {}) {
|
|
16
|
+
const home = opts.homeDir || process.env.HOME || '';
|
|
17
|
+
const resolved = path.resolve(normalizeCwd(cwd) || home || '.');
|
|
18
|
+
try {
|
|
19
|
+
// Claude Code records the kernel-resolved cwd in JSONL metadata on macOS
|
|
20
|
+
// (/tmp -> /private/tmp). Use the same path for project-entry prediction;
|
|
21
|
+
// callers still pass the original cwd to the spawned process.
|
|
22
|
+
return fs.realpathSync(resolved);
|
|
23
|
+
} catch {
|
|
24
|
+
return resolved;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function encodeClaudeProjectEntry(cwd, opts = {}) {
|
|
29
|
+
return canonicalizeClaudeProjectPath(cwd, opts)
|
|
30
|
+
.replace(/\/\./g, '/-')
|
|
31
|
+
.replace(/\//g, '-');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function claudeProjectDirForCwd(cwd, opts = {}) {
|
|
35
|
+
const home = opts.homeDir || process.env.HOME || '';
|
|
36
|
+
const configDir = opts.claudeConfigDir || path.join(home, '.claude');
|
|
37
|
+
return path.join(configDir, 'projects', encodeClaudeProjectEntry(cwd, opts));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function samePath(a, b) {
|
|
41
|
+
const left = normalizeCwd(a);
|
|
42
|
+
const right = normalizeCwd(b);
|
|
43
|
+
return !!left && !!right && left === right;
|
|
44
|
+
}
|
|
45
|
+
|
|
15
46
|
function parseAgentWorktreePath(value) {
|
|
16
47
|
const cwd = normalizeCwd(value);
|
|
17
48
|
if (!cwd) return null;
|
|
@@ -70,7 +101,12 @@ function resolveResumeCwdFallback(cwd, opts = {}) {
|
|
|
70
101
|
}
|
|
71
102
|
|
|
72
103
|
module.exports = {
|
|
104
|
+
canonicalizeClaudeProjectPath,
|
|
105
|
+
claudeProjectDirForCwd,
|
|
106
|
+
encodeClaudeProjectEntry,
|
|
107
|
+
normalizeCwd,
|
|
73
108
|
parseAgentWorktreePath,
|
|
74
109
|
resolveResumeCwd,
|
|
75
110
|
resolveResumeCwdFallback,
|
|
111
|
+
samePath,
|
|
76
112
|
};
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const { normalizeAgentType } = require('./agent-capabilities');
|
|
7
|
+
const { claudeProjectDirForCwd, normalizeCwd, samePath } = require('./resume-cwd');
|
|
8
|
+
|
|
9
|
+
function _asString(value) {
|
|
10
|
+
return String(value || '').trim();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function _existingFile(filePath) {
|
|
14
|
+
const clean = _asString(filePath);
|
|
15
|
+
if (!clean) return null;
|
|
16
|
+
try {
|
|
17
|
+
const st = fs.statSync(clean);
|
|
18
|
+
if (!st.isFile()) return null;
|
|
19
|
+
return { path: clean, size: st.size || 0, modifiedAt: st.mtime ? st.mtime.toISOString() : '' };
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function _pushUnique(out, value) {
|
|
26
|
+
const clean = _asString(value);
|
|
27
|
+
if (clean && !out.includes(clean)) out.push(clean);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// A Claude transcript is "real" only if it carries at least one conversation
|
|
31
|
+
// turn. Claude Code / CTM also write metadata-only sidecar lines (ai-title,
|
|
32
|
+
// agent-name, mode, permission-mode, last-prompt, …); a file that holds ONLY
|
|
33
|
+
// those is a stub that `claude --resume` rejects with "No conversation found".
|
|
34
|
+
const CONVERSATION_LINE_TYPES = new Set(['user', 'assistant', 'summary', 'system']);
|
|
35
|
+
// Bound the scan so a healthy multi-MB transcript early-exits on its first turn
|
|
36
|
+
// and a pathological metadata-only file can't force a full read. A real session
|
|
37
|
+
// hits a conversation line within the first handful of lines.
|
|
38
|
+
const CONVERSATION_SCAN_BYTE_CAP = 512 * 1024;
|
|
39
|
+
|
|
40
|
+
function _lineIsConversation(line) {
|
|
41
|
+
// Cheap substring pre-filter before the JSON.parse.
|
|
42
|
+
if (line.indexOf('"type"') === -1) return false;
|
|
43
|
+
try {
|
|
44
|
+
return CONVERSATION_LINE_TYPES.has(JSON.parse(line).type);
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Returns true when `filePath` contains at least one real conversation turn.
|
|
51
|
+
// Conservative on ambiguity: an unreadable file, or one whose first
|
|
52
|
+
// CONVERSATION_SCAN_BYTE_CAP bytes hold no turn but which is larger than the
|
|
53
|
+
// cap (so the scan was incomplete), is reported `true` so callers never
|
|
54
|
+
// overwrite a transcript they could not fully inspect.
|
|
55
|
+
function transcriptHasConversation(filePath, opts = {}) {
|
|
56
|
+
const clean = _asString(filePath);
|
|
57
|
+
if (!clean) return false;
|
|
58
|
+
let st;
|
|
59
|
+
try {
|
|
60
|
+
st = fs.statSync(clean);
|
|
61
|
+
} catch {
|
|
62
|
+
return false; // missing/unstattable → no conversation (nothing to preserve)
|
|
63
|
+
}
|
|
64
|
+
if (!st.isFile() || st.size === 0) return false;
|
|
65
|
+
let fd;
|
|
66
|
+
try {
|
|
67
|
+
const cap = opts.byteCap || CONVERSATION_SCAN_BYTE_CAP;
|
|
68
|
+
const toRead = Math.min(st.size, cap);
|
|
69
|
+
fd = fs.openSync(clean, 'r');
|
|
70
|
+
const buf = Buffer.allocUnsafe(toRead);
|
|
71
|
+
const read = fs.readSync(fd, buf, 0, toRead, 0);
|
|
72
|
+
const text = buf.toString('utf8', 0, read);
|
|
73
|
+
const fullyRead = read >= st.size;
|
|
74
|
+
let lineStart = 0;
|
|
75
|
+
for (let i = 0; i < text.length; i++) {
|
|
76
|
+
if (text[i] !== '\n') continue;
|
|
77
|
+
const line = text.slice(lineStart, i).trim();
|
|
78
|
+
lineStart = i + 1;
|
|
79
|
+
if (line && _lineIsConversation(line)) return true;
|
|
80
|
+
}
|
|
81
|
+
// Trailing line without a newline is only trustworthy on a complete read.
|
|
82
|
+
if (fullyRead && lineStart < text.length) {
|
|
83
|
+
const tail = text.slice(lineStart).trim();
|
|
84
|
+
if (tail && _lineIsConversation(tail)) return true;
|
|
85
|
+
}
|
|
86
|
+
// No turn found. Definitively a stub only if we scanned the whole file;
|
|
87
|
+
// otherwise assume conversation exists (never clobber a large transcript).
|
|
88
|
+
return !fullyRead;
|
|
89
|
+
} catch {
|
|
90
|
+
return true; // unreadable → treat as real so we never overwrite it
|
|
91
|
+
} finally {
|
|
92
|
+
if (fd !== undefined) { try { fs.closeSync(fd); } catch {} }
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Decide whether to (re)hydrate a live `<id>.jsonl` from its `<id>.jsonl.bak`.
|
|
97
|
+
// Restore when the backup carries a real conversation AND the live transcript
|
|
98
|
+
// is either missing OR a metadata-only stub. Never restore from an empty/stub
|
|
99
|
+
// backup, and never overwrite a live transcript that already has turns.
|
|
100
|
+
function claudeLiveTranscriptShouldRestore(jsonlPath, bakPath) {
|
|
101
|
+
if (!_existingFile(bakPath)) return false;
|
|
102
|
+
if (!transcriptHasConversation(bakPath)) return false;
|
|
103
|
+
if (!_existingFile(jsonlPath)) return true;
|
|
104
|
+
return !transcriptHasConversation(jsonlPath);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Synchronous recovery used by the interactive resume / attach paths. Returns
|
|
108
|
+
// { restored, reason }. The `.bak` is only ever read, never modified, so the
|
|
109
|
+
// operation stays reversible. A clobbered stub is preserved as a `.stub-<n>`
|
|
110
|
+
// sibling (best effort) so the overwrite can be inspected after the fact.
|
|
111
|
+
function restoreClaudeLiveTranscriptFromBak(jsonlPath, bakPath, opts = {}) {
|
|
112
|
+
const live = _asString(jsonlPath);
|
|
113
|
+
const bak = _asString(bakPath);
|
|
114
|
+
if (!live || !bak) return { restored: false, reason: 'missing_paths' };
|
|
115
|
+
const liveExisted = !!_existingFile(live);
|
|
116
|
+
if (!claudeLiveTranscriptShouldRestore(live, bak)) {
|
|
117
|
+
return { restored: false, reason: liveExisted ? 'live_ok' : 'no_source' };
|
|
118
|
+
}
|
|
119
|
+
if (liveExisted) {
|
|
120
|
+
try {
|
|
121
|
+
const stamp = typeof opts.now === 'number' ? opts.now : Date.now();
|
|
122
|
+
fs.renameSync(live, `${live}.stub-${stamp}`);
|
|
123
|
+
} catch { /* best effort — proceed to overwrite */ }
|
|
124
|
+
}
|
|
125
|
+
fs.copyFileSync(bak, live);
|
|
126
|
+
return { restored: true, reason: liveExisted ? 'replaced_stub' : 'restored_missing' };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function _candidateClaudeTranscriptPaths(options = {}) {
|
|
130
|
+
const { resumeId, jsonlPath, homeDir, claudeConfigDir } = options;
|
|
131
|
+
const paths = [];
|
|
132
|
+
const id = _asString(resumeId);
|
|
133
|
+
const stored = _asString(jsonlPath);
|
|
134
|
+
if (stored) {
|
|
135
|
+
_pushUnique(paths, stored);
|
|
136
|
+
if (stored.endsWith('.jsonl')) _pushUnique(paths, stored + '.bak');
|
|
137
|
+
if (stored.endsWith('.jsonl.bak')) _pushUnique(paths, stored.replace(/\.bak$/, ''));
|
|
138
|
+
}
|
|
139
|
+
if (!id) return paths;
|
|
140
|
+
|
|
141
|
+
const configDir = _asString(claudeConfigDir) || path.join(homeDir || process.env.HOME || '', '.claude');
|
|
142
|
+
const projectsDir = path.join(configDir, 'projects');
|
|
143
|
+
try {
|
|
144
|
+
for (const entry of fs.readdirSync(projectsDir)) {
|
|
145
|
+
const dir = path.join(projectsDir, entry);
|
|
146
|
+
_pushUnique(paths, path.join(dir, `${id}.jsonl`));
|
|
147
|
+
_pushUnique(paths, path.join(dir, `${id}.jsonl.bak`));
|
|
148
|
+
}
|
|
149
|
+
} catch {
|
|
150
|
+
// Missing ~/.claude/projects is reported as a normal missing-transcript result.
|
|
151
|
+
}
|
|
152
|
+
return paths;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function findClaudeResumeTranscript(options = {}) {
|
|
156
|
+
const paths = _candidateClaudeTranscriptPaths(options);
|
|
157
|
+
for (const candidate of paths) {
|
|
158
|
+
const found = _existingFile(candidate);
|
|
159
|
+
if (found) {
|
|
160
|
+
found.restoreFromBak = candidate.endsWith('.jsonl.bak');
|
|
161
|
+
return found;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function _candidateCwds(options = {}) {
|
|
168
|
+
const candidates = [];
|
|
169
|
+
const row = options.agentRow || {};
|
|
170
|
+
for (const value of [
|
|
171
|
+
options.projectPath,
|
|
172
|
+
row.project_path,
|
|
173
|
+
row.cwd,
|
|
174
|
+
options.cwd,
|
|
175
|
+
]) {
|
|
176
|
+
const clean = normalizeCwd(value);
|
|
177
|
+
if (clean && !candidates.includes(clean)) candidates.push(clean);
|
|
178
|
+
}
|
|
179
|
+
return candidates;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function _existingDirectory(dir, fsExists = fs.existsSync, fsStat = fs.statSync) {
|
|
183
|
+
const clean = normalizeCwd(dir);
|
|
184
|
+
if (!clean) return false;
|
|
185
|
+
try {
|
|
186
|
+
return !!fsExists(clean) && fsStat(clean).isDirectory();
|
|
187
|
+
} catch {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function resolveClaudeResumeCwd(options = {}) {
|
|
193
|
+
const transcriptPath = _asString(options.transcriptPath);
|
|
194
|
+
const currentCwd = normalizeCwd(options.cwd);
|
|
195
|
+
if (!transcriptPath || !currentCwd) {
|
|
196
|
+
return { cwd: currentCwd, changed: false, reason: '' };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const transcriptProjectDir = normalizeCwd(path.dirname(transcriptPath));
|
|
200
|
+
const projectOpts = {
|
|
201
|
+
homeDir: options.homeDir,
|
|
202
|
+
claudeConfigDir: options.claudeConfigDir,
|
|
203
|
+
};
|
|
204
|
+
const currentProjectDir = claudeProjectDirForCwd(currentCwd, projectOpts);
|
|
205
|
+
if (samePath(currentProjectDir, transcriptProjectDir)) {
|
|
206
|
+
return {
|
|
207
|
+
cwd: currentCwd,
|
|
208
|
+
changed: false,
|
|
209
|
+
reason: '',
|
|
210
|
+
transcriptProjectDir,
|
|
211
|
+
cwdProjectDir: currentProjectDir,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const fsExists = options.fsExists || fs.existsSync;
|
|
216
|
+
const fsStat = options.fsStat || fs.statSync;
|
|
217
|
+
for (const candidate of _candidateCwds(options)) {
|
|
218
|
+
if (!_existingDirectory(candidate, fsExists, fsStat)) continue;
|
|
219
|
+
const candidateProjectDir = claudeProjectDirForCwd(candidate, projectOpts);
|
|
220
|
+
if (samePath(candidateProjectDir, transcriptProjectDir)) {
|
|
221
|
+
return {
|
|
222
|
+
cwd: candidate,
|
|
223
|
+
changed: !samePath(candidate, currentCwd),
|
|
224
|
+
reason: 'claude_project_transcript_match',
|
|
225
|
+
transcriptProjectDir,
|
|
226
|
+
cwdProjectDir: currentProjectDir,
|
|
227
|
+
effectiveProjectDir: candidateProjectDir,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
cwd: currentCwd,
|
|
234
|
+
changed: false,
|
|
235
|
+
blocked: true,
|
|
236
|
+
reason: 'claude_resume_project_mismatch',
|
|
237
|
+
transcriptProjectDir,
|
|
238
|
+
cwdProjectDir: currentProjectDir,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function validateResumeTarget(options = {}) {
|
|
243
|
+
const agentType = normalizeAgentType(options.agentType || options.provider || '');
|
|
244
|
+
const resumeId = _asString(options.resumeId);
|
|
245
|
+
if (!resumeId) return { ok: true };
|
|
246
|
+
if (agentType !== 'claude') return { ok: true };
|
|
247
|
+
|
|
248
|
+
const transcript = findClaudeResumeTranscript({
|
|
249
|
+
resumeId,
|
|
250
|
+
jsonlPath: options.jsonlPath || options.agentRow?.jsonl_path,
|
|
251
|
+
homeDir: options.homeDir,
|
|
252
|
+
claudeConfigDir: options.claudeConfigDir,
|
|
253
|
+
});
|
|
254
|
+
if (transcript) {
|
|
255
|
+
const cwdResolution = resolveClaudeResumeCwd({
|
|
256
|
+
...options,
|
|
257
|
+
transcriptPath: transcript.path,
|
|
258
|
+
});
|
|
259
|
+
if (cwdResolution.blocked) {
|
|
260
|
+
const shortId = resumeId.slice(0, 8);
|
|
261
|
+
return {
|
|
262
|
+
ok: false,
|
|
263
|
+
code: 'claude_resume_project_mismatch',
|
|
264
|
+
resumeId,
|
|
265
|
+
storedPath: transcript.path,
|
|
266
|
+
transcriptPath: transcript.path,
|
|
267
|
+
transcriptProjectDir: cwdResolution.transcriptProjectDir || '',
|
|
268
|
+
cwdProjectDir: cwdResolution.cwdProjectDir || '',
|
|
269
|
+
cwd: normalizeCwd(options.cwd),
|
|
270
|
+
message:
|
|
271
|
+
`Cannot resume Claude session ${shortId}: the transcript exists, but CTM would launch ` +
|
|
272
|
+
`Claude Code from a different project directory. Launching from the wrong cwd makes ` +
|
|
273
|
+
`Claude Code report "No conversation found". CTM needs the original project cwd or a ` +
|
|
274
|
+
`matching agent_sessions.project_path before starting this resume.`,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
ok: true,
|
|
279
|
+
transcriptPath: transcript.path,
|
|
280
|
+
transcriptSize: transcript.size,
|
|
281
|
+
transcriptModifiedAt: transcript.modifiedAt,
|
|
282
|
+
restoreFromBak: !!transcript.restoreFromBak,
|
|
283
|
+
effectiveCwd: cwdResolution.changed ? cwdResolution.cwd : undefined,
|
|
284
|
+
cwdChanged: !!cwdResolution.changed,
|
|
285
|
+
cwdChangeReason: cwdResolution.reason || '',
|
|
286
|
+
transcriptProjectDir: cwdResolution.transcriptProjectDir || '',
|
|
287
|
+
cwdProjectDir: cwdResolution.cwdProjectDir || '',
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const storedPath = _asString(options.jsonlPath || options.agentRow?.jsonl_path);
|
|
292
|
+
const shortId = resumeId.slice(0, 8);
|
|
293
|
+
return {
|
|
294
|
+
ok: false,
|
|
295
|
+
code: 'missing_claude_transcript',
|
|
296
|
+
resumeId,
|
|
297
|
+
storedPath,
|
|
298
|
+
message:
|
|
299
|
+
`Cannot resume Claude session ${shortId}: the local Claude transcript file is missing. ` +
|
|
300
|
+
`CTM can still show its cached conversation history, but Claude Code needs ` +
|
|
301
|
+
`~/.claude/projects/<project>/${resumeId}.jsonl to resume. ` +
|
|
302
|
+
`Start a new session from the cached history, or restore the missing transcript from backup.`,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
module.exports = {
|
|
307
|
+
findClaudeResumeTranscript,
|
|
308
|
+
resolveClaudeResumeCwd,
|
|
309
|
+
validateResumeTarget,
|
|
310
|
+
transcriptHasConversation,
|
|
311
|
+
claudeLiveTranscriptShouldRestore,
|
|
312
|
+
restoreClaudeLiveTranscriptFromBak,
|
|
313
|
+
};
|