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,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Brain-DB space optimization core + CLI. Idempotent, safe to run repeatedly.
|
|
3
|
+
// 1. Embeddings: convert embedding_vec_ollama float32 -> int8 IN PLACE (same table name)
|
|
4
|
+
// 2. memories_fts -> external-content + maintenance triggers
|
|
5
|
+
// 3. content_raw: NULL where byte-identical to content (readers use content_raw ?? content)
|
|
6
|
+
// 4. lost_and_found: drop (orphaned .recover residue) — only when opts.dropLostAndFound
|
|
7
|
+
// 5. VACUUM (opts.vacuum)
|
|
8
|
+
//
|
|
9
|
+
// Exposed as a function so the deferred upgrader loop (loops/brain-optimize.js) and the CLI
|
|
10
|
+
// share one implementation. The caller must have sqlite-vec loaded on `db` (the daemon's
|
|
11
|
+
// connection already does; the CLI loads it below).
|
|
12
|
+
//
|
|
13
|
+
// CLI: <node25> migrate.js <dbPath> [--no-vacuum] [--keep-lost-and-found]
|
|
14
|
+
|
|
15
|
+
function declaredVecType(db, t) {
|
|
16
|
+
const r = db.prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name=?").get(t);
|
|
17
|
+
if (!r || !r.sql) return null;
|
|
18
|
+
if (/\bint8\s*\[/.test(r.sql)) return 'int8';
|
|
19
|
+
if (/\bfloat\s*\[/.test(r.sql)) return 'float';
|
|
20
|
+
return '?';
|
|
21
|
+
}
|
|
22
|
+
function has(db, name) { return !!db.prepare("SELECT 1 FROM sqlite_master WHERE name=?").get(name); }
|
|
23
|
+
|
|
24
|
+
// True if any optimization is still pending (used to skip no-op work / gate the loop).
|
|
25
|
+
function needsOptimization(db) {
|
|
26
|
+
if (has(db, 'embedding_vec_ollama') && declaredVecType(db, 'embedding_vec_ollama') === 'float') return true;
|
|
27
|
+
const fts = db.prepare("SELECT sql FROM sqlite_master WHERE name='memories_fts'").get();
|
|
28
|
+
if (fts && !/content\s*=\s*'memories'/.test(fts.sql)) return true;
|
|
29
|
+
if (has(db, 'memories')) {
|
|
30
|
+
const red = db.prepare("SELECT 1 FROM memories WHERE content_raw IS NOT NULL AND content_raw=content LIMIT 1").get();
|
|
31
|
+
if (red) return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function embeddingCount(db) {
|
|
36
|
+
try { return db.prepare("SELECT COUNT(*) c FROM embedding_vec_ollama").get().c; } catch { return 0; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function _migrateEmbeddings(db, log) {
|
|
40
|
+
const T = 'embedding_vec_ollama';
|
|
41
|
+
if (!has(db, T)) { log('embeddings: no', T, '- skip'); return; }
|
|
42
|
+
const type = declaredVecType(db, T);
|
|
43
|
+
if (type === 'int8') { log('embeddings: already int8 - skip'); return; }
|
|
44
|
+
if (type !== 'float') { log('embeddings: unexpected type', type, '- skip'); return; }
|
|
45
|
+
const dims = (db.prepare("SELECT sql FROM sqlite_master WHERE name=?").get(T).sql.match(/\[(\d+)\]/) || [])[1] || '768';
|
|
46
|
+
const n = db.prepare(`SELECT COUNT(*) c FROM ${T}`).get().c;
|
|
47
|
+
const tmp = T + '_i8mig';
|
|
48
|
+
log(`embeddings: quantizing ${n} float32[${dims}] vectors -> int8...`);
|
|
49
|
+
db.exec('BEGIN');
|
|
50
|
+
db.exec(`DROP TABLE IF EXISTS "${tmp}"`);
|
|
51
|
+
db.exec(`CREATE VIRTUAL TABLE "${tmp}" USING vec0(embedding int8[${dims}])`);
|
|
52
|
+
db.exec(`INSERT INTO "${tmp}"(rowid, embedding) SELECT rowid, vec_quantize_int8(embedding,'unit') FROM "${T}"`);
|
|
53
|
+
db.exec(`DROP TABLE "${T}"`);
|
|
54
|
+
db.exec(`CREATE VIRTUAL TABLE "${T}" USING vec0(embedding int8[${dims}])`);
|
|
55
|
+
db.exec(`INSERT INTO "${T}"(rowid, embedding) SELECT rowid, embedding FROM "${tmp}"`);
|
|
56
|
+
db.exec(`DROP TABLE "${tmp}"`);
|
|
57
|
+
db.exec('COMMIT');
|
|
58
|
+
const after = db.prepare(`SELECT COUNT(*) c FROM ${T}`).get().c;
|
|
59
|
+
if (after !== n) throw new Error(`embedding row count changed ${n} -> ${after}`);
|
|
60
|
+
log(`embeddings: done, ${after} int8 vectors`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function _ftsTriggers(db) {
|
|
64
|
+
db.exec(`CREATE TRIGGER memories_fts_insert AFTER INSERT ON memories BEGIN
|
|
65
|
+
INSERT INTO memories_fts(rowid, content, source, participants, source_channel)
|
|
66
|
+
VALUES (NEW.rowid, NEW.content, NEW.source, COALESCE(NEW.participants,''), COALESCE(NEW.source_channel,''));
|
|
67
|
+
END`);
|
|
68
|
+
db.exec(`CREATE TRIGGER memories_fts_delete AFTER DELETE ON memories BEGIN
|
|
69
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, source, participants, source_channel)
|
|
70
|
+
VALUES('delete', OLD.rowid, OLD.content, OLD.source, COALESCE(OLD.participants,''), COALESCE(OLD.source_channel,''));
|
|
71
|
+
END`);
|
|
72
|
+
db.exec(`CREATE TRIGGER memories_fts_update AFTER UPDATE ON memories BEGIN
|
|
73
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, source, participants, source_channel)
|
|
74
|
+
VALUES('delete', OLD.rowid, OLD.content, OLD.source, COALESCE(OLD.participants,''), COALESCE(OLD.source_channel,''));
|
|
75
|
+
INSERT INTO memories_fts(rowid, content, source, participants, source_channel)
|
|
76
|
+
VALUES (NEW.rowid, NEW.content, NEW.source, COALESCE(NEW.participants,''), COALESCE(NEW.source_channel,''));
|
|
77
|
+
END`);
|
|
78
|
+
}
|
|
79
|
+
function _migrateFts(db, log) {
|
|
80
|
+
const cur = db.prepare("SELECT sql FROM sqlite_master WHERE name='memories_fts'").get();
|
|
81
|
+
if (!cur) { log('fts: no memories_fts - skip'); return; }
|
|
82
|
+
if (/content\s*=\s*'memories'/.test(cur.sql)) { log('fts: already external-content - skip'); return; }
|
|
83
|
+
log('fts: converting to external-content...');
|
|
84
|
+
db.exec('BEGIN');
|
|
85
|
+
db.exec('DROP TRIGGER IF EXISTS memories_fts_insert');
|
|
86
|
+
db.exec('DROP TRIGGER IF EXISTS memories_fts_delete');
|
|
87
|
+
db.exec('DROP TRIGGER IF EXISTS memories_fts_update');
|
|
88
|
+
db.exec('DROP TABLE memories_fts');
|
|
89
|
+
db.exec(`CREATE VIRTUAL TABLE memories_fts USING fts5(
|
|
90
|
+
content, source, participants, source_channel,
|
|
91
|
+
content='memories', content_rowid='rowid', tokenize='porter unicode61')`);
|
|
92
|
+
db.exec(`INSERT INTO memories_fts(memories_fts) VALUES('rebuild')`);
|
|
93
|
+
_ftsTriggers(db);
|
|
94
|
+
db.exec('COMMIT');
|
|
95
|
+
log('fts: external-content + triggers installed, rebuilt');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function _migrateContentRaw(db, log) {
|
|
99
|
+
if (!has(db, 'memories')) return;
|
|
100
|
+
const n = db.prepare("SELECT COUNT(*) c FROM memories WHERE content_raw IS NOT NULL AND content_raw=content").get().c;
|
|
101
|
+
if (n === 0) { log('content_raw: nothing redundant - skip'); return; }
|
|
102
|
+
const hadTrig = !!db.prepare("SELECT 1 FROM sqlite_master WHERE name='memories_fts_update'").get();
|
|
103
|
+
db.exec('BEGIN');
|
|
104
|
+
if (hadTrig) db.exec('DROP TRIGGER IF EXISTS memories_fts_update'); // content unchanged -> FTS unaffected
|
|
105
|
+
const r = db.prepare("UPDATE memories SET content_raw=NULL WHERE content_raw IS NOT NULL AND content_raw=content").run();
|
|
106
|
+
if (hadTrig) db.exec(`CREATE TRIGGER memories_fts_update AFTER UPDATE ON memories BEGIN
|
|
107
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, source, participants, source_channel)
|
|
108
|
+
VALUES('delete', OLD.rowid, OLD.content, OLD.source, COALESCE(OLD.participants,''), COALESCE(OLD.source_channel,''));
|
|
109
|
+
INSERT INTO memories_fts(rowid, content, source, participants, source_channel)
|
|
110
|
+
VALUES (NEW.rowid, NEW.content, NEW.source, COALESCE(NEW.participants,''), COALESCE(NEW.source_channel,''));
|
|
111
|
+
END`);
|
|
112
|
+
db.exec('COMMIT');
|
|
113
|
+
log(`content_raw: nulled ${r.changes} redundant rows`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function _dropLostAndFound(db, log) {
|
|
117
|
+
if (!has(db, 'lost_and_found')) { log('lost_and_found: absent - skip'); return; }
|
|
118
|
+
db.exec('DROP TABLE lost_and_found');
|
|
119
|
+
log('lost_and_found: dropped');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Run the space optimization on an open better-sqlite3 `db` that already has sqlite-vec loaded.
|
|
124
|
+
* opts: { vacuum=true, dropLostAndFound=false, log=console.log }
|
|
125
|
+
* Each phase is idempotent and transactional; the float32 vectors are never dropped until the
|
|
126
|
+
* int8 copy is built and verified in the same transaction (a crash rolls back to float32).
|
|
127
|
+
*/
|
|
128
|
+
function optimizeBrain(db, opts = {}) {
|
|
129
|
+
const { vacuum = true, dropLostAndFound = false, log = () => {} } = opts;
|
|
130
|
+
_migrateEmbeddings(db, log);
|
|
131
|
+
_migrateFts(db, log);
|
|
132
|
+
_migrateContentRaw(db, log);
|
|
133
|
+
if (dropLostAndFound) _dropLostAndFound(db, log);
|
|
134
|
+
if (vacuum) { log('vacuuming...'); db.exec('VACUUM'); try { db.pragma('wal_checkpoint(TRUNCATE)'); } catch {} }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports = { optimizeBrain, needsOptimization, embeddingCount, declaredVecType };
|
|
138
|
+
|
|
139
|
+
// ---- CLI ----
|
|
140
|
+
if (require.main === module) {
|
|
141
|
+
const path = require('path');
|
|
142
|
+
const WE = path.resolve(__dirname, '..', '..');
|
|
143
|
+
const Database = require(path.join(WE, 'node_modules', 'better-sqlite3'));
|
|
144
|
+
const vec = require(path.join(WE, 'node_modules', 'sqlite-vec'));
|
|
145
|
+
const DB = process.argv[2];
|
|
146
|
+
if (!DB) { console.error('usage: migrate.js <dbPath> [--no-vacuum] [--keep-lost-and-found]'); process.exit(1); }
|
|
147
|
+
const db = new Database(DB);
|
|
148
|
+
vec.load(db);
|
|
149
|
+
db.pragma('busy_timeout = 60000');
|
|
150
|
+
const MB = b => (b / 1048576).toFixed(0);
|
|
151
|
+
const before = db.prepare('SELECT SUM(pgsize) b FROM dbstat').get().b;
|
|
152
|
+
const t0 = Date.now();
|
|
153
|
+
optimizeBrain(db, {
|
|
154
|
+
vacuum: !process.argv.includes('--no-vacuum'),
|
|
155
|
+
dropLostAndFound: !process.argv.includes('--keep-lost-and-found'),
|
|
156
|
+
log: (...a) => console.log('[migrate]', ...a),
|
|
157
|
+
});
|
|
158
|
+
const after = db.prepare('SELECT SUM(pgsize) b FROM dbstat').get().b;
|
|
159
|
+
console.log(`[migrate] logical size ${MB(before)} -> ${MB(after)} MB in ${((Date.now()-t0)/1000).toFixed(1)}s`);
|
|
160
|
+
db.close();
|
|
161
|
+
console.log('[migrate] DONE');
|
|
162
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Phase 1a — embedding quantization recall eval (decision gate).
|
|
3
|
+
// Runs ONLY on a copy. Builds int8 + binary shadow vec tables from the existing
|
|
4
|
+
// float32 vectors, then measures recall@k by using stored vectors as query probes
|
|
5
|
+
// (this isolates *quantization distortion* — how much the quantized index reorders
|
|
6
|
+
// the same neighbors — without needing ollama to embed fresh queries).
|
|
7
|
+
//
|
|
8
|
+
// Usage: <node25> recall-eval.js [copyPath] [sampleN]
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const WE = path.resolve(__dirname, '..', '..');
|
|
11
|
+
const Database = require(path.join(WE, 'node_modules', 'better-sqlite3'));
|
|
12
|
+
const vec = require(path.join(WE, 'node_modules', 'sqlite-vec'));
|
|
13
|
+
|
|
14
|
+
const COPY = process.argv[2] || path.join(process.env.HOME || process.cwd(), '.walle', 'opt-work', 'wall-e-brain.copy.db');
|
|
15
|
+
const SAMPLE = parseInt(process.argv[3] || '80', 10);
|
|
16
|
+
const KMAX = 30;
|
|
17
|
+
|
|
18
|
+
const db = new Database(COPY);
|
|
19
|
+
vec.load(db);
|
|
20
|
+
db.pragma('cache_size = -200000'); // 200MB page cache for the KNN scans
|
|
21
|
+
|
|
22
|
+
const SRC = 'embedding_vec_ollama'; // float[768]
|
|
23
|
+
const I8 = 'embedding_vec_ollama_i8'; // int8[768]
|
|
24
|
+
const BIT = 'embedding_vec_ollama_bit'; // bit[768]
|
|
25
|
+
|
|
26
|
+
function tableBytes(name) {
|
|
27
|
+
// sum pgsize across the vec0 shadow tables for this logical table
|
|
28
|
+
try {
|
|
29
|
+
const r = db.prepare(
|
|
30
|
+
`SELECT COALESCE(SUM(pgsize),0) AS b FROM dbstat WHERE name LIKE ? OR name LIKE ?`
|
|
31
|
+
).get(name + '%', 'sqlite_autoindex_' + name + '%');
|
|
32
|
+
return r.b;
|
|
33
|
+
} catch (e) { return -1; }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildQuant(target, type, expr) {
|
|
37
|
+
const exists = db.prepare("SELECT 1 FROM sqlite_master WHERE name=?").get(target);
|
|
38
|
+
if (exists) { db.exec(`DROP TABLE ${target}`); }
|
|
39
|
+
db.exec(`CREATE VIRTUAL TABLE ${target} USING vec0(embedding ${type})`);
|
|
40
|
+
const t0 = Date.now();
|
|
41
|
+
try {
|
|
42
|
+
db.exec(`INSERT INTO ${target}(rowid, embedding) SELECT rowid, ${expr} FROM ${SRC}`);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
// fallback: row-by-row
|
|
45
|
+
const sel = db.prepare(`SELECT rowid, embedding FROM ${SRC}`);
|
|
46
|
+
const ins = db.prepare(`INSERT INTO ${target}(rowid, embedding) VALUES (?, ${expr.replace('embedding', '?')})`);
|
|
47
|
+
const tx = db.transaction(() => { for (const r of sel.iterate()) ins.run(r.rowid, r.embedding); });
|
|
48
|
+
tx();
|
|
49
|
+
}
|
|
50
|
+
return Date.now() - t0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(`# Embedding quantization recall eval`);
|
|
54
|
+
console.log(`copy: ${COPY}`);
|
|
55
|
+
const srcN = db.prepare(`SELECT COUNT(*) n FROM ${SRC}`).get().n;
|
|
56
|
+
console.log(`float32 vectors: ${srcN}, sample queries: ${SAMPLE}, k up to ${KMAX}\n`);
|
|
57
|
+
|
|
58
|
+
console.log('building int8 shadow table...');
|
|
59
|
+
const t8 = buildQuant(I8, 'int8[768]', "vec_quantize_int8(embedding,'unit')");
|
|
60
|
+
console.log(` built in ${t8}ms`);
|
|
61
|
+
console.log('building binary(bit) shadow table...');
|
|
62
|
+
const tb = buildQuant(BIT, 'bit[768]', 'vec_quantize_binary(embedding)');
|
|
63
|
+
console.log(` built in ${tb}ms\n`);
|
|
64
|
+
|
|
65
|
+
const bytesF = tableBytes(SRC), bytes8 = tableBytes(I8), bytesB = tableBytes(BIT);
|
|
66
|
+
const MB = b => (b / 1048576).toFixed(1);
|
|
67
|
+
console.log(`size float32: ${MB(bytesF)} MB int8: ${MB(bytes8)} MB (${(bytesF/bytes8).toFixed(1)}x) bit: ${MB(bytesB)} MB (${(bytesF/bytesB).toFixed(1)}x)\n`);
|
|
68
|
+
|
|
69
|
+
// sample rowids
|
|
70
|
+
const allIds = db.prepare(`SELECT rowid FROM ${SRC}`).all().map(r => r.rowid);
|
|
71
|
+
function pick(n) {
|
|
72
|
+
const out = []; const used = new Set(); let seed = 1234567;
|
|
73
|
+
const rnd = () => { seed = (seed * 1103515245 + 12345) & 0x7fffffff; return seed / 0x7fffffff; };
|
|
74
|
+
while (out.length < n && used.size < allIds.length) {
|
|
75
|
+
const i = Math.floor(rnd() * allIds.length);
|
|
76
|
+
if (!used.has(i)) { used.add(i); out.push(allIds[i]); }
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
const sample = pick(SAMPLE);
|
|
81
|
+
|
|
82
|
+
const getVec = db.prepare(`SELECT embedding FROM ${SRC} WHERE rowid=?`);
|
|
83
|
+
const knnF = db.prepare(`SELECT rowid FROM ${SRC} WHERE embedding MATCH ? AND k=? ORDER BY distance`);
|
|
84
|
+
const knn8 = db.prepare(`SELECT rowid FROM ${I8} WHERE embedding MATCH vec_quantize_int8(?,'unit') AND k=? ORDER BY distance`);
|
|
85
|
+
const knnB = db.prepare(`SELECT rowid FROM ${BIT} WHERE embedding MATCH vec_quantize_binary(?) AND k=? ORDER BY distance`);
|
|
86
|
+
|
|
87
|
+
function topk(stmt, qv, k, self) {
|
|
88
|
+
const ids = stmt.all(qv, k + 1).map(r => r.rowid).filter(id => id !== self);
|
|
89
|
+
return ids.slice(0, k);
|
|
90
|
+
}
|
|
91
|
+
function recallAt(gt, cand, k) {
|
|
92
|
+
const g = new Set(gt.slice(0, k));
|
|
93
|
+
let hit = 0; for (const id of cand.slice(0, k)) if (g.has(id)) hit++;
|
|
94
|
+
return hit / k;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let sum8_10 = 0, sum8_30 = 0, sumB_10 = 0, sumB_30 = 0;
|
|
98
|
+
let tF = 0, t8t = 0, tBt = 0, worst8_10 = 1;
|
|
99
|
+
for (const rid of sample) {
|
|
100
|
+
const qv = getVec.get(rid).embedding;
|
|
101
|
+
let s = Date.now(); const gt = topk(knnF, qv, KMAX, rid); tF += Date.now() - s;
|
|
102
|
+
s = Date.now(); const c8 = topk(knn8, qv, KMAX, rid); t8t += Date.now() - s;
|
|
103
|
+
s = Date.now(); const cB = topk(knnB, qv, KMAX, rid); tBt += Date.now() - s;
|
|
104
|
+
const r8_10 = recallAt(gt, c8, 10); const r8_30 = recallAt(gt, c8, 30);
|
|
105
|
+
sum8_10 += r8_10; sum8_30 += r8_30;
|
|
106
|
+
sumB_10 += recallAt(gt, cB, 10); sumB_30 += recallAt(gt, cB, 30);
|
|
107
|
+
if (r8_10 < worst8_10) worst8_10 = r8_10;
|
|
108
|
+
}
|
|
109
|
+
const N = sample.length;
|
|
110
|
+
const pct = x => (100 * x / N).toFixed(1) + '%';
|
|
111
|
+
console.log('## Recall (quantized vs float32 ground truth), averaged over', N, 'real query probes');
|
|
112
|
+
console.log(`int8 recall@10: ${pct(sum8_10)} recall@30: ${pct(sum8_30)} worst@10: ${(100*worst8_10).toFixed(0)}%`);
|
|
113
|
+
console.log(`binary recall@10: ${pct(sumB_10)} recall@30: ${pct(sumB_30)} (binary normally needs a float rerank pass)`);
|
|
114
|
+
console.log();
|
|
115
|
+
console.log('## KNN latency (avg ms/query, exhaustive over', srcN, 'vectors)');
|
|
116
|
+
console.log(`float32: ${(tF/N).toFixed(1)}ms int8: ${(t8t/N).toFixed(1)}ms bit: ${(tBt/N).toFixed(1)}ms`);
|
|
117
|
+
db.close();
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
process.env.WALL_E_PROCESS_ROLE = process.env.WALL_E_PROCESS_ROLE || 'walle-daemon';
|
|
3
|
+
|
|
2
4
|
const http = require('http');
|
|
3
5
|
const { handleWalleApi } = require('./api-walle');
|
|
4
6
|
const { getAllowedOrigin, isAuthorizedRequest } = require('./http/auth');
|
|
7
|
+
const { startPortkeyModelSyncLoop } = require('./llm/portkey-sync');
|
|
5
8
|
|
|
6
9
|
const PORT = parseInt(process.env.WALL_E_PORT) || 3457;
|
|
7
10
|
const HOST = process.env.WALL_E_HOST || '127.0.0.1';
|
|
@@ -155,6 +158,13 @@ function startServer(options = {}) {
|
|
|
155
158
|
readyResolve();
|
|
156
159
|
if (typeof setImmediate === 'function') setImmediate(autoConfigureWallEMcp);
|
|
157
160
|
else setTimeout(autoConfigureWallEMcp, 0);
|
|
161
|
+
if (process.env.WALLE_DISABLE_PORTKEY_SYNC !== '1') {
|
|
162
|
+
try {
|
|
163
|
+
server.stopPortkeyModelSync = startPortkeyModelSyncLoop();
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.warn(`[wall-e] Portkey model sync loop failed to start: ${err.message}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
158
168
|
});
|
|
159
169
|
}
|
|
160
170
|
|
|
@@ -177,6 +187,11 @@ function startServer(options = {}) {
|
|
|
177
187
|
readyReject(err);
|
|
178
188
|
}
|
|
179
189
|
});
|
|
190
|
+
server.on('close', () => {
|
|
191
|
+
try {
|
|
192
|
+
if (typeof server.stopPortkeyModelSync === 'function') server.stopPortkeyModelSync();
|
|
193
|
+
} catch {}
|
|
194
|
+
});
|
|
180
195
|
|
|
181
196
|
tryListen();
|
|
182
197
|
return server;
|
|
@@ -116,6 +116,15 @@ class WallESessionRecorder {
|
|
|
116
116
|
}));
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
appendFrame(frame, extra = {}) {
|
|
120
|
+
if (!this.enabled) return null;
|
|
121
|
+
this.ensureStarted();
|
|
122
|
+
return this._appendRecord(this._baseRecord('frame_update', {
|
|
123
|
+
...extra,
|
|
124
|
+
data: normalizeContent(frame),
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
|
|
119
128
|
appendError(error, extra = {}) {
|
|
120
129
|
if (!this.enabled) return null;
|
|
121
130
|
this.ensureStarted();
|
|
@@ -141,7 +141,7 @@ function storeToBrain(events) {
|
|
|
141
141
|
).all(windowStart, windowEnd);
|
|
142
142
|
for (const row of dbEvents) {
|
|
143
143
|
if (!seenSourceIds.has(row.source_id)) {
|
|
144
|
-
brain.
|
|
144
|
+
brain.deleteMemory(row.id); // cascades to memory_index + embeddings (no orphan leak)
|
|
145
145
|
cleaned++;
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -194,7 +194,7 @@ function syncCalendar(brain, token, profileId) {
|
|
|
194
194
|
).all(timeMin, timeMax);
|
|
195
195
|
for (const row of dbEvents) {
|
|
196
196
|
if (!seenSourceIds.has(row.source_id)) {
|
|
197
|
-
brain.
|
|
197
|
+
brain.deleteMemory(row.id); // cascades to memory_index + embeddings (no orphan leak)
|
|
198
198
|
cleaned++;
|
|
199
199
|
}
|
|
200
200
|
}
|
|
@@ -25,6 +25,9 @@ const {
|
|
|
25
25
|
const {
|
|
26
26
|
parseDsmlToolCallBlocks,
|
|
27
27
|
} = require(path.resolve(__dirname, '..', '..', '..', 'llm', 'text-tool-calls'));
|
|
28
|
+
const ctmOperationalContext = require(path.resolve(__dirname, '..', '..', '..', 'memory', 'ctm-operational-context'));
|
|
29
|
+
let telemetry;
|
|
30
|
+
try { telemetry = require(path.resolve(__dirname, '..', '..', '..', 'telemetry')); } catch { telemetry = { track() {} }; }
|
|
28
31
|
|
|
29
32
|
const WATERMARK_FILE = path.join(__dirname, '.watermark.json');
|
|
30
33
|
const OWNER_HANDLE = process.env.SLACK_OWNER_HANDLE || '';
|
|
@@ -540,6 +543,62 @@ function buildSlackChatOptions(overrides = {}) {
|
|
|
540
543
|
};
|
|
541
544
|
}
|
|
542
545
|
|
|
546
|
+
async function buildSlackCtmContextBlock(text, opts = {}) {
|
|
547
|
+
const classification = ctmOperationalContext.classifyCtmOperationalQuery(text);
|
|
548
|
+
if (!classification.required) {
|
|
549
|
+
return { required: false, ok: true, block: '', result: null };
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
let result;
|
|
553
|
+
try {
|
|
554
|
+
result = await ctmOperationalContext.lookupCtmOperationalContext({
|
|
555
|
+
query: text,
|
|
556
|
+
limit: opts.limit || 5,
|
|
557
|
+
force: true,
|
|
558
|
+
}, {
|
|
559
|
+
timeoutMs: opts.timeoutMs || 6000,
|
|
560
|
+
cooldownMs: opts.cooldownMs ?? 0,
|
|
561
|
+
});
|
|
562
|
+
} catch (err) {
|
|
563
|
+
result = {
|
|
564
|
+
required: true,
|
|
565
|
+
ok: false,
|
|
566
|
+
must_not_guess: true,
|
|
567
|
+
reason: err.message,
|
|
568
|
+
context_text: 'CTM operational context lookup failed. Do not guess; reply ONLY NO_REPLY.',
|
|
569
|
+
sources: {
|
|
570
|
+
remote_access: { searched: true, ok: false, reason: err.message },
|
|
571
|
+
ctm_sessions: { searched: true, ok: false, reason: err.message },
|
|
572
|
+
},
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
telemetry.track('slack_ctm_context_preflight', {
|
|
577
|
+
required: true,
|
|
578
|
+
ok: Boolean(result.ok),
|
|
579
|
+
remote_ok: Boolean(result.sources?.remote_access?.ok),
|
|
580
|
+
session_ok: Boolean(result.sources?.ctm_sessions?.ok),
|
|
581
|
+
session_count: Number(result.sources?.ctm_sessions?.count || 0),
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
if (!result.ok) {
|
|
585
|
+
console.warn(`[slack-mentions] Required CTM context unavailable; suppressing guess (${result.sources?.remote_access?.reason || result.sources?.ctm_sessions?.reason || result.reason || 'unknown'})`);
|
|
586
|
+
return {
|
|
587
|
+
required: true,
|
|
588
|
+
ok: false,
|
|
589
|
+
block: '\n\nRequired CTM operational/session-memory context was unavailable. Reply ONLY NO_REPLY. Do not guess from generic memories, DDEV hosts, localhost, or local IP heuristics.',
|
|
590
|
+
result,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
return {
|
|
595
|
+
required: true,
|
|
596
|
+
ok: true,
|
|
597
|
+
block: `\n\n${result.context_text}`,
|
|
598
|
+
result,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
|
|
543
602
|
function selectThreadMessagesToProcess(replies, thread, opts = {}) {
|
|
544
603
|
const lastSeenTs = thread?.last_seen_ts || thread?.thread_ts || null;
|
|
545
604
|
const ownerReplies = (replies || []).filter(reply => isOwnerReply(reply, opts));
|
|
@@ -577,7 +636,7 @@ async function deliverSlackReply({ channelId, threadTs, message, deliveryId }) {
|
|
|
577
636
|
conversationId: channelId,
|
|
578
637
|
threadId: threadTs,
|
|
579
638
|
source: 'wall_e_outbound',
|
|
580
|
-
extractMessageId: extractSlackMessageTs,
|
|
639
|
+
extractMessageId: (result) => extractSlackMessageTs(result),
|
|
581
640
|
metadata: { slackChannelId: channelId, slackThreadTs: threadTs },
|
|
582
641
|
},
|
|
583
642
|
});
|
|
@@ -605,20 +664,25 @@ async function generateAndSendReply(msg, threadTs, contextBlock, kind, opts = {}
|
|
|
605
664
|
try {
|
|
606
665
|
const today = new Date().toISOString().split('T')[0];
|
|
607
666
|
const instruction = slackResponseInstruction(question);
|
|
667
|
+
const ctmContext = await buildSlackCtmContextBlock(question);
|
|
668
|
+
if (ctmContext.required && !ctmContext.ok) return null;
|
|
669
|
+
const effectiveContextBlock = `${contextBlock || ''}${ctmContext.block || ''}`;
|
|
608
670
|
const locationAware = shouldUseLocationForMessage(question);
|
|
609
671
|
const explicitCalendar = isExplicitCalendarRequest(question);
|
|
610
672
|
const locationInstruction = locationAware
|
|
611
673
|
? 'For physical location/local weather questions, use Wall-E current-location context only. Do not infer location from calendar, timezone, Slack history, or memories.'
|
|
674
|
+
: ctmContext.required
|
|
675
|
+
? 'Use the CTM operational context block as authoritative. Do not answer from generic memories if they conflict. Do not guess DDEV, localhost, or local-IP answers unless the CTM context explicitly says so.'
|
|
612
676
|
: 'Search your memories for relevant info.';
|
|
613
677
|
// Build a context-aware prompt: greetings/welcomes get a warmer, more proactive prompt
|
|
614
678
|
let prompt;
|
|
615
679
|
if (isGreeting) {
|
|
616
|
-
prompt = `[SLACK GREETING] ${actorLabel(msg)} said in Slack:\n\n"${question}"${
|
|
680
|
+
prompt = `[SLACK GREETING] ${actorLabel(msg)} said in Slack:\n\n"${question}"${effectiveContextBlock}\n\nToday is ${today}. This appears to be a greeting or welcome message. Search your memories (e.g. lookup_person) to learn about the people mentioned. Respond warmly — welcome them, share any relevant context you know about them, and proactively offer to help. Be genuine and concise (2-4 sentences). Do NOT mention any tool failures or technical issues in your response.`;
|
|
617
681
|
} else {
|
|
618
|
-
prompt = `[SLACK ${kind.toUpperCase()}] ${actorLabel(msg)} asked in Slack:\n\n${question}${
|
|
682
|
+
prompt = `[SLACK ${kind.toUpperCase()}] ${actorLabel(msg)} asked in Slack:\n\n${question}${effectiveContextBlock}\n\nToday is ${today}. ${locationInstruction} For schedule/calendar questions, search with the specific date (e.g. "calendar 2026-04-13") since calendar events are stored as memories with source=calendar. Use ctm_context for CTM operational/session-memory questions. Use mcp_call only if memories don't have what you need. ${instruction}`;
|
|
619
683
|
}
|
|
620
684
|
|
|
621
|
-
const allowedTools = ['search_memories', 'think', 'lookup_person', 'mcp_call', 'calendar_events', 'mail_messages', 'mail_read', 'mail_search']
|
|
685
|
+
const allowedTools = ['search_memories', 'ctm_context', 'ctm_remote_access_status', 'ctm_session_search', 'think', 'lookup_person', 'mcp_call', 'calendar_events', 'mail_messages', 'mail_read', 'mail_search']
|
|
622
686
|
.filter(tool => !(locationAware && !explicitCalendar && tool === 'calendar_events'));
|
|
623
687
|
const result = await chatModule.chat(prompt, buildSlackChatOptions({
|
|
624
688
|
channel: 'task',
|
|
@@ -675,14 +739,19 @@ async function generateAndSendFollowUp(combinedMessage, thread, threadContext, o
|
|
|
675
739
|
const today = new Date().toISOString().split('T')[0];
|
|
676
740
|
const contextBlock = threadContext ? `\n\nFull Slack thread context:\n${threadContext}` : '';
|
|
677
741
|
const instruction = slackResponseInstruction(combinedMessage);
|
|
742
|
+
const ctmContext = await buildSlackCtmContextBlock(`${combinedMessage}\n${threadContext || ''}`);
|
|
743
|
+
if (ctmContext.required && !ctmContext.ok) return null;
|
|
744
|
+
const effectiveContextBlock = `${contextBlock}${ctmContext.block || ''}`;
|
|
678
745
|
const locationAware = shouldUseLocationForMessage(combinedMessage);
|
|
679
746
|
const explicitCalendar = isExplicitCalendarRequest(combinedMessage);
|
|
680
747
|
const locationInstruction = locationAware
|
|
681
748
|
? 'For physical location/local weather questions, use Wall-E current-location context only. Do not infer location from calendar, timezone, Slack history, or memories.'
|
|
749
|
+
: ctmContext.required
|
|
750
|
+
? 'Use the CTM operational context block as authoritative. Do not answer from generic memories if they conflict. Do not guess DDEV, localhost, or local-IP answers unless the CTM context explicitly says so.'
|
|
682
751
|
: 'Search your memories for relevant info.';
|
|
683
|
-
const prompt = `[SLACK FOLLOW-UP] ${getConfiguredOwnerName() || 'The owner'} replied in a Slack thread:\n\n${combinedMessage}${
|
|
752
|
+
const prompt = `[SLACK FOLLOW-UP] ${getConfiguredOwnerName() || 'The owner'} replied in a Slack thread:\n\n${combinedMessage}${effectiveContextBlock}\n\nToday is ${today}. ${locationInstruction} Use ctm_context for CTM operational/session-memory questions. ${instruction}`;
|
|
684
753
|
|
|
685
|
-
const allowedTools = ['search_memories', 'think', 'lookup_person', 'mcp_call', 'calendar_events', 'mail_messages', 'mail_read', 'mail_search']
|
|
754
|
+
const allowedTools = ['search_memories', 'ctm_context', 'ctm_remote_access_status', 'ctm_session_search', 'think', 'lookup_person', 'mcp_call', 'calendar_events', 'mail_messages', 'mail_read', 'mail_search']
|
|
686
755
|
.filter(tool => !(locationAware && !explicitCalendar && tool === 'calendar_events'));
|
|
687
756
|
const result = await chatModule.chat(prompt, buildSlackChatOptions({
|
|
688
757
|
channel: 'task',
|
|
@@ -1455,6 +1524,7 @@ module.exports = {
|
|
|
1455
1524
|
looksLikeToolControlMarkup,
|
|
1456
1525
|
validateSlackAnswer,
|
|
1457
1526
|
buildSlackChatOptions,
|
|
1527
|
+
buildSlackCtmContextBlock,
|
|
1458
1528
|
generateAndSendReply,
|
|
1459
1529
|
parseChannelMessages,
|
|
1460
1530
|
parseDmMessages,
|
|
@@ -368,10 +368,14 @@ function syncSkillReferences() {
|
|
|
368
368
|
fs.existsSync(skill.path) ? fs.readFileSync(skill.path, 'utf8') : content
|
|
369
369
|
).digest('hex') : null;
|
|
370
370
|
|
|
371
|
-
// Check if this reference already exists
|
|
371
|
+
// Check if this reference already exists.
|
|
372
|
+
// NOTE: filter on `source` too — `WHERE source_id = ?` alone can't use the compound
|
|
373
|
+
// index idx_memories_source(source, source_id) and full-scans the (multi-GB) memories
|
|
374
|
+
// table on EVERY skill, which made boot take ~3min. Skill refs are always stored with
|
|
375
|
+
// source='skill_reference', so this is both correct and index-eligible (SEARCH not SCAN).
|
|
372
376
|
try {
|
|
373
377
|
const existing = brain.getDb().prepare(
|
|
374
|
-
|
|
378
|
+
"SELECT id, content FROM memories WHERE source = 'skill_reference' AND source_id = ? LIMIT 1"
|
|
375
379
|
).get(sourceId);
|
|
376
380
|
|
|
377
381
|
if (existing && existing.content === content) continue; // no change
|
|
@@ -411,7 +415,7 @@ function syncSkillReferences() {
|
|
|
411
415
|
).all();
|
|
412
416
|
for (const row of existing) {
|
|
413
417
|
if (!allIds.has(row.source_id)) {
|
|
414
|
-
brain.
|
|
418
|
+
brain.deleteMemory(row.id); // cascades to memory_index + embeddings (no orphan leak)
|
|
415
419
|
}
|
|
416
420
|
}
|
|
417
421
|
} catch {}
|
|
@@ -30,6 +30,16 @@ function runScriptSkill(skill, task = {}, opts = {}) {
|
|
|
30
30
|
WALL_E_SKILL_CONFIG: JSON.stringify(skillConfig),
|
|
31
31
|
WALL_E_SKILL_DIR: skill.dir,
|
|
32
32
|
WALL_E_SRC_DIR: WALL_E_DIR,
|
|
33
|
+
// Script skills run as dedicated short-lived subprocesses that open their own
|
|
34
|
+
// brain.db connection (brain.initDb()). The daemon's brain lock defaults to a 0ms
|
|
35
|
+
// fail-fast (correct for the daemon event loop, which must never Atomics.wait), but
|
|
36
|
+
// inherited by a subprocess that means it ABORTS the instant the daemon holds the
|
|
37
|
+
// lock for a single statement — observed as ~272 "SQLite write lock busy" aborts
|
|
38
|
+
// (slack-mentions Exit code 1, dropped calendar/email syncs). A subprocess can
|
|
39
|
+
// safely block-wait briefly and retry, so give it a bounded timeout. In practice
|
|
40
|
+
// the lock frees in <100ms; 5s is just the ceiling. Caller env still wins.
|
|
41
|
+
WALL_E_SQLITE_WRITE_LOCK_TIMEOUT_MS:
|
|
42
|
+
process.env.WALL_E_SQLITE_WRITE_LOCK_TIMEOUT_MS || '5000',
|
|
33
43
|
...(opts.env || {}),
|
|
34
44
|
};
|
|
35
45
|
if (task.checkpoint) env.WALL_E_CHECKPOINT = task.checkpoint;
|
|
@@ -154,6 +154,43 @@ function clearResolvedSlackHealthAlerts({ authenticated = false, ownerConfigured
|
|
|
154
154
|
return { cleared: before.length - after.length };
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
function _googleWorkspaceServiceKey(email, profileId) {
|
|
158
|
+
const normalizedEmail = String(email || '').trim().toLowerCase();
|
|
159
|
+
if (!normalizedEmail) return '';
|
|
160
|
+
const normalizedProfile = String(profileId || 'default').trim().toLowerCase() || 'default';
|
|
161
|
+
return `google_workspace:${normalizedProfile}:${normalizedEmail}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _sameGoogleWorkspaceAlertAccount(alert, email, profileId) {
|
|
165
|
+
const normalizedEmail = String(email || '').trim().toLowerCase();
|
|
166
|
+
if (!normalizedEmail || !alert) return false;
|
|
167
|
+
const normalizedProfile = String(profileId || 'default').trim().toLowerCase() || 'default';
|
|
168
|
+
const service = String(alert.service || '').trim().toLowerCase();
|
|
169
|
+
if (service === _googleWorkspaceServiceKey(normalizedEmail, normalizedProfile)) return true;
|
|
170
|
+
const alertEmail = String(alert.account_email || alert.email || '').trim().toLowerCase();
|
|
171
|
+
if (alertEmail !== normalizedEmail) return false;
|
|
172
|
+
const alertProfile = String(alert.profile_id || alert.profileId || 'default').trim().toLowerCase() || 'default';
|
|
173
|
+
return alertProfile === normalizedProfile;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function clearResolvedGoogleWorkspaceHealthAlerts({ email = '', profileId = null, authenticated = false } = {}) {
|
|
177
|
+
if (!authenticated || !email) return { cleared: 0 };
|
|
178
|
+
const before = getServiceAlerts();
|
|
179
|
+
const after = before.filter((a) => {
|
|
180
|
+
if (!_sameGoogleWorkspaceAlertAccount(a, email, profileId)) return true;
|
|
181
|
+
const action = String(a.action || '');
|
|
182
|
+
const type = String(a.type || '');
|
|
183
|
+
const googleWorkspaceAuthAlert =
|
|
184
|
+
action === 'gws_reauth'
|
|
185
|
+
|| type === 'auth_expired';
|
|
186
|
+
return !googleWorkspaceAuthAlert;
|
|
187
|
+
});
|
|
188
|
+
if (after.length !== before.length) {
|
|
189
|
+
brain.setKv('service_alerts', JSON.stringify(after));
|
|
190
|
+
}
|
|
191
|
+
return { cleared: before.length - after.length };
|
|
192
|
+
}
|
|
193
|
+
|
|
157
194
|
function _hasMissingSlackOwner(validation) {
|
|
158
195
|
return !!(validation && Array.isArray(validation.missing)
|
|
159
196
|
&& validation.missing.some(m => m.type === 'env' && m.name === SLACK_OWNER_ENV_KEY));
|
|
@@ -873,6 +910,7 @@ module.exports = {
|
|
|
873
910
|
dismissServiceAlert,
|
|
874
911
|
clearServiceAlerts,
|
|
875
912
|
clearResolvedSlackHealthAlerts,
|
|
913
|
+
clearResolvedGoogleWorkspaceHealthAlerts,
|
|
876
914
|
_test: {
|
|
877
915
|
isAuthError,
|
|
878
916
|
getProviderAuthBlock,
|
|
@@ -99,8 +99,17 @@ function registerBuiltinMiddleware(mw, opts = {}) {
|
|
|
99
99
|
const mode = ctx.mode || opts.mode || 'build';
|
|
100
100
|
const sections = [];
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
// When the orchestrator already built the full agent prompt
|
|
103
|
+
// (buildAgentSystemPrompt), keep it as the base and only append the
|
|
104
|
+
// sections it doesn't cover. Replacing it here silently dropped the
|
|
105
|
+
// workflow/quality/frontend/memory discipline from every loop turn.
|
|
106
|
+
const baseSystem = typeof ctx.system === 'string' && ctx.system.trim() ? ctx.system : '';
|
|
107
|
+
if (baseSystem) {
|
|
108
|
+
sections.push(baseSystem);
|
|
109
|
+
} else {
|
|
110
|
+
sections.push(`You are an expert software engineer executing a coding task.
|
|
103
111
|
Work in: ${cwd}`);
|
|
112
|
+
}
|
|
104
113
|
|
|
105
114
|
// Mode enforcement (belt + suspenders with tool filtering)
|
|
106
115
|
if (mode === 'plan') {
|
|
@@ -111,9 +120,10 @@ You may ONLY read, search, and analyze. This overrides all other instructions.`)
|
|
|
111
120
|
Do not make any edits. Review the diff and assess quality.`);
|
|
112
121
|
}
|
|
113
122
|
|
|
114
|
-
// Project conventions
|
|
115
|
-
|
|
116
|
-
|
|
123
|
+
// Project conventions (skip if the base prompt already carries them)
|
|
124
|
+
const claudeMd = opts.claudeMd || ctx.claudeMd;
|
|
125
|
+
if (claudeMd && !baseSystem.includes(claudeMd)) {
|
|
126
|
+
sections.push(`## Project Conventions (CLAUDE.md)\n${claudeMd}`);
|
|
117
127
|
}
|
|
118
128
|
|
|
119
129
|
// Quality rules (ported from OpenCode's prompt patterns)
|
|
@@ -143,7 +153,7 @@ Do not make any edits. Review the diff and assess quality.`);
|
|
|
143
153
|
if (workflowDocs) sections.push(workflowDocs);
|
|
144
154
|
|
|
145
155
|
const capabilityContext = buildCapabilityContext(ctx.promptCapabilities || opts.promptCapabilities);
|
|
146
|
-
if (capabilityContext) sections.push(capabilityContext);
|
|
156
|
+
if (capabilityContext && !baseSystem.includes(capabilityContext)) sections.push(capabilityContext);
|
|
147
157
|
|
|
148
158
|
ctx.system = sections.join('\n\n');
|
|
149
159
|
});
|
|
@@ -185,11 +195,11 @@ Do not make any edits. Review the diff and assess quality.`);
|
|
|
185
195
|
|
|
186
196
|
// Prioritize tools based on detected coding phase
|
|
187
197
|
const PHASE_PREFERRED = {
|
|
188
|
-
'coding:exploration': new Set(['read_file', 'glob', 'grep_files', 'list_directory', 'lsp_symbols']),
|
|
189
|
-
'coding:generation': new Set(['edit_file', 'write_file', 'apply_patch', 'multi_edit', 'run_shell']),
|
|
198
|
+
'coding:exploration': new Set(['read_file', 'glob', 'grep_files', 'list_directory', 'pdf_info', 'pdf_read_pages', 'pdf_render_pages', 'lsp_symbols']),
|
|
199
|
+
'coding:generation': new Set(['edit_file', 'write_file', 'apply_patch', 'multi_edit', 'run_shell', 'make_pdf']),
|
|
190
200
|
'coding:debugging': new Set(['read_file', 'run_shell', 'grep_files', 'lsp_diagnostics', 'edit_file']),
|
|
191
|
-
'coding:testing': new Set(['run_shell', 'read_file', 'edit_file']),
|
|
192
|
-
'coding:review': new Set(['read_file', 'grep_files', 'lsp_diagnostics', 'lsp_symbols']),
|
|
201
|
+
'coding:testing': new Set(['run_shell', 'read_file', 'edit_file', 'pdf_info', 'pdf_render_pages']),
|
|
202
|
+
'coding:review': new Set(['read_file', 'grep_files', 'pdf_info', 'pdf_read_pages', 'pdf_render_pages', 'lsp_diagnostics', 'lsp_symbols']),
|
|
193
203
|
};
|
|
194
204
|
|
|
195
205
|
const preferred = PHASE_PREFERRED[phase];
|