create-walle 0.10.2 → 0.10.3
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 +3 -1
- package/lib/release-schema.json +2 -2
- package/lib/runtime-closure-policy.json +8 -7
- package/package.json +1 -1
- package/template/coding-task-manager/api-prompts.js +45 -7
- package/template/coding-task-manager/bin/claude-hook.js +55 -1
- package/template/coding-task-manager/bin/ctm-relay-client.js +35 -12
- package/template/coding-task-manager/bin/land.js +2069 -0
- package/template/coding-task-manager/bin/memory-census.js +4 -2
- package/template/coding-task-manager/bin/memory-sync-verify.js +151 -0
- package/template/coding-task-manager/bin/probe-refusal-scope.js +530 -0
- package/template/coding-task-manager/db.js +156 -32
- package/template/coding-task-manager/lib/acp/acp-client.js +383 -0
- package/template/coding-task-manager/lib/acp/dsh-context-truth.js +176 -0
- package/template/coding-task-manager/lib/acp/dsh-launch-model.js +302 -0
- package/template/coding-task-manager/lib/acp/dsh-mcp-servers.js +194 -0
- package/template/coding-task-manager/lib/acp/dsh-prompt-lane.js +616 -0
- package/template/coding-task-manager/lib/acp/dsh-route-patch.js +308 -0
- package/template/coding-task-manager/lib/acp/dsh-session-runtime.js +522 -0
- package/template/coding-task-manager/lib/acp/dsh-transcript.js +395 -0
- package/template/coding-task-manager/lib/acp/dsh-usage-log.js +162 -0
- package/template/coding-task-manager/lib/acp/ndjson-stdio-transport.js +225 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +47 -11
- package/template/coding-task-manager/lib/adopted-launch-environment.js +123 -0
- package/template/coding-task-manager/lib/agent-auto-update-runtime.js +0 -3
- package/template/coding-task-manager/lib/agent-auto-update.js +26 -10
- package/template/coding-task-manager/lib/agent-bundle/build.js +657 -0
- package/template/coding-task-manager/lib/agent-bundle/codex-install.js +558 -0
- package/template/coding-task-manager/lib/agent-bundle/drift.js +120 -0
- package/template/coding-task-manager/lib/agent-bundle/gc.js +522 -0
- package/template/coding-task-manager/lib/agent-bundle/inventory.js +346 -0
- package/template/coding-task-manager/lib/agent-bundle/push.js +717 -0
- package/template/coding-task-manager/lib/agent-bundle/skill-transfer.js +724 -0
- package/template/coding-task-manager/lib/agent-bundle/spawn.js +119 -0
- package/template/coding-task-manager/lib/agent-bundle/store.js +568 -0
- package/template/coding-task-manager/lib/agent-capabilities.js +142 -12
- package/template/coding-task-manager/lib/agent-cli-cache.js +30 -5
- package/template/coding-task-manager/lib/agent-definitions.js +19 -0
- package/template/coding-task-manager/lib/agent-hooks-codex-toml.js +28 -16
- package/template/coding-task-manager/lib/agent-hooks-codex-workspace.js +9 -1
- package/template/coding-task-manager/lib/agent-hooks-installer.js +23 -8
- package/template/coding-task-manager/lib/agent-hooks-prune.js +37 -11
- package/template/coding-task-manager/lib/agent-hooks-shim.js +105 -0
- package/template/coding-task-manager/lib/agent-presets.js +84 -1
- package/template/coding-task-manager/lib/agent-upgrade-jobs.js +12 -1
- package/template/coding-task-manager/lib/agent-version-service.js +74 -11
- package/template/coding-task-manager/lib/all-sessions-query.js +6 -2
- package/template/coding-task-manager/lib/api/agent-bundles.js +436 -0
- package/template/coding-task-manager/lib/api/backup-retention.js +83 -0
- package/template/coding-task-manager/lib/api/conversation-sync-routes.js +124 -0
- package/template/coding-task-manager/lib/api/diagnostics.js +549 -69
- package/template/coding-task-manager/lib/api/fleet.js +118 -0
- package/template/coding-task-manager/lib/api/hub-bridge.js +243 -0
- package/template/coding-task-manager/lib/api/ingress.js +9 -1
- package/template/coding-task-manager/lib/api/landing.js +403 -0
- package/template/coding-task-manager/lib/api/machines.js +691 -2
- package/template/coding-task-manager/lib/api/memory-sync-routes.js +335 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +8 -3
- package/template/coding-task-manager/lib/api/remote-sessions.js +1326 -0
- package/template/coding-task-manager/lib/api/session-attach.js +623 -0
- package/template/coding-task-manager/lib/api/session-messages.js +1384 -0
- package/template/coding-task-manager/lib/api/sessions.js +77 -51
- package/template/coding-task-manager/lib/api/setup-network.js +544 -16
- package/template/coding-task-manager/lib/api/setup-wizard-handlers.js +884 -0
- package/template/coding-task-manager/lib/api/setup.js +829 -10
- package/template/coding-task-manager/lib/api/walle-bridge.js +9 -1
- package/template/coding-task-manager/lib/attachment-reconciler-wiring.js +5 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +23 -0
- package/template/coding-task-manager/lib/auth-rules.js +292 -21
- package/template/coding-task-manager/lib/background-stop.js +369 -0
- package/template/coding-task-manager/lib/best-of-attempts.js +4 -1
- package/template/coding-task-manager/lib/best-of-launch-plan.js +52 -0
- package/template/coding-task-manager/lib/box-keep-awake.js +89 -0
- package/template/coding-task-manager/lib/broadcast-reason-stats.js +152 -0
- package/template/coding-task-manager/lib/broadcast-serialize.js +5 -0
- package/template/coding-task-manager/lib/build-info.js +4 -2
- package/template/coding-task-manager/lib/claude-model-truth.js +13 -2
- package/template/coding-task-manager/lib/claude-transcript-terminal-renderer.js +17 -13
- package/template/coding-task-manager/lib/client-diag-handler.js +64 -2
- package/template/coding-task-manager/lib/codex-app-server-client.js +14 -16
- package/template/coding-task-manager/lib/codex-configuration-history.js +55 -0
- package/template/coding-task-manager/lib/codex-harness-qualification.js +43 -20
- package/template/coding-task-manager/lib/codex-rollout-history.js +743 -0
- package/template/coding-task-manager/lib/coding-agent-models.js +27 -12
- package/template/coding-task-manager/lib/coding-cli-skill-installer.js +44 -14
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +43 -2
- package/template/coding-task-manager/lib/coding-session-model-owner.js +1 -1
- package/template/coding-task-manager/lib/coding-session-model-public.js +7 -1
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +23 -4
- package/template/coding-task-manager/lib/coding-session-model-scan.js +31 -0
- package/template/coding-task-manager/lib/coding-session-model-state.js +7 -0
- package/template/coding-task-manager/lib/conversation-freshness-diagnostics.js +280 -0
- package/template/coding-task-manager/lib/conversation-item-clock.js +261 -0
- package/template/coding-task-manager/lib/conversation-source-registry.js +5 -0
- package/template/coding-task-manager/lib/conversation-store-v2.js +44 -0
- package/template/coding-task-manager/lib/conversation-sync.js +355 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +96 -12
- package/template/coding-task-manager/lib/create/worker-role-profile.js +4 -4
- package/template/coding-task-manager/lib/create-intent-lease.js +51 -0
- package/template/coding-task-manager/lib/ctm-session-context-api.js +97 -6
- package/template/coding-task-manager/lib/db-domain-tables.js +1 -0
- package/template/coding-task-manager/lib/db-domains.js +1 -0
- package/template/coding-task-manager/lib/db-owner-dispatch-probe.js +32 -0
- package/template/coding-task-manager/lib/db-owner-request-counts.js +178 -0
- package/template/coding-task-manager/lib/db-owner-worker-client.js +68 -14
- package/template/coding-task-manager/lib/db-schema-source-files.js +5 -0
- package/template/coding-task-manager/lib/deferred-restore-attempt.js +6 -2
- package/template/coding-task-manager/lib/feature-manifest.js +4 -0
- package/template/coding-task-manager/lib/fleet-conversation-route.js +97 -0
- package/template/coding-task-manager/lib/fleet-fanout.js +78 -0
- package/template/coding-task-manager/lib/fleet-hub.js +762 -0
- package/template/coding-task-manager/lib/fleet-origin-follower.js +252 -0
- package/template/coding-task-manager/lib/fleet-resolver-effects.js +147 -0
- package/template/coding-task-manager/lib/fleet-resolver-tick.js +148 -0
- package/template/coding-task-manager/lib/fleet-resolver.js +454 -0
- package/template/coding-task-manager/lib/fleet-session-list-routes.js +114 -0
- package/template/coding-task-manager/lib/fleet-session-lists.js +672 -0
- package/template/coding-task-manager/lib/fleet-update.js +798 -0
- package/template/coding-task-manager/lib/fs-watcher-root-watch.js +141 -0
- package/template/coding-task-manager/lib/fs-watcher.js +58 -42
- package/template/coding-task-manager/lib/harness-history-transition.js +50 -9
- package/template/coding-task-manager/lib/headless-term-service.js +84 -8
- package/template/coding-task-manager/lib/hermetic-agent-launch-guard.js +10 -0
- package/template/coding-task-manager/lib/history-transition-read-op.js +175 -8
- package/template/coding-task-manager/lib/host-cpu-categories.js +310 -0
- package/template/coding-task-manager/lib/host-fseventsd-sampler.js +399 -0
- package/template/coding-task-manager/lib/host-handoff.js +16 -19
- package/template/coding-task-manager/lib/host-stats.js +150 -3
- package/template/coding-task-manager/lib/hosted-sync-worker.js +43 -320
- package/template/coding-task-manager/lib/hub-bridge-access.js +798 -0
- package/template/coding-task-manager/lib/hub-bridge-box.js +409 -0
- package/template/coding-task-manager/lib/hub-bridge-mcp.js +380 -0
- package/template/coding-task-manager/lib/hub-bridge-mesh.js +313 -0
- package/template/coding-task-manager/lib/hub-bridge-ops.js +721 -0
- package/template/coding-task-manager/lib/hub-bridge.js +398 -0
- package/template/coding-task-manager/lib/idle-notify.js +491 -0
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +8 -0
- package/template/coding-task-manager/lib/instance-manifest.js +5 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +18 -8
- package/template/coding-task-manager/lib/landing/agent-rule.txt +1 -0
- package/template/coding-task-manager/lib/landing/batch-runner.js +366 -0
- package/template/coding-task-manager/lib/landing/config.js +536 -0
- package/template/coding-task-manager/lib/landing/ctm-view.js +256 -0
- package/template/coding-task-manager/lib/landing/gate.js +360 -0
- package/template/coding-task-manager/lib/landing/git.js +344 -0
- package/template/coding-task-manager/lib/landing/lease.js +247 -0
- package/template/coding-task-manager/lib/landing/merge-delta.js +380 -0
- package/template/coding-task-manager/lib/landing/proof.js +223 -0
- package/template/coding-task-manager/lib/landing/queue.js +998 -0
- package/template/coding-task-manager/lib/landing/radar.js +489 -0
- package/template/coding-task-manager/lib/landing/resolve-cli.js +424 -0
- package/template/coding-task-manager/lib/landing/state.js +263 -0
- package/template/coding-task-manager/lib/landing/stop.js +49 -0
- package/template/coding-task-manager/lib/landing/sync-cli.js +475 -0
- package/template/coding-task-manager/lib/landing/sync.js +456 -0
- package/template/coding-task-manager/lib/landing/train.js +885 -0
- package/template/coding-task-manager/lib/landing/window.js +57 -0
- package/template/coding-task-manager/lib/launch-environment.js +121 -0
- package/template/coding-task-manager/lib/launch-model-override.js +36 -10
- package/template/coding-task-manager/lib/launch-plan-pool.js +2 -1
- package/template/coding-task-manager/lib/launch-plan-warm-cache.js +6 -0
- package/template/coding-task-manager/lib/lead-model-observer.js +57 -1
- package/template/coding-task-manager/lib/lead-model-options.js +160 -3
- package/template/coding-task-manager/lib/lead-model-restore-reconciliation.js +106 -24
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +352 -68
- package/template/coding-task-manager/lib/lead-model-switch.js +114 -10
- package/template/coding-task-manager/lib/lead-model-transition-runtime.js +14 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +24 -6
- package/template/coding-task-manager/lib/lead-route-preflight.js +179 -0
- package/template/coding-task-manager/lib/lead-switch-history-mode.js +110 -0
- package/template/coding-task-manager/lib/lead-wire-agent.js +7 -0
- package/template/coding-task-manager/lib/lifecycle-wake-experiment.js +9 -2
- package/template/coding-task-manager/lib/live-defer-announce.js +45 -0
- package/template/coding-task-manager/lib/machine-registry.js +750 -5
- package/template/coding-task-manager/lib/macos-capabilities.js +32 -15
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +433 -53
- package/template/coding-task-manager/lib/mainloop-observability.js +14 -9
- package/template/coding-task-manager/lib/media-draft-owner.js +16 -3
- package/template/coding-task-manager/lib/memory-join.js +337 -0
- package/template/coding-task-manager/lib/memory-sync-verify.js +393 -0
- package/template/coding-task-manager/lib/memory-sync.js +565 -0
- package/template/coding-task-manager/lib/migrations/v57-delegate-pref-mirror-opencode.js +68 -0
- package/template/coding-task-manager/lib/migrations/v58-subagent-launch-native-subagents.js +42 -0
- package/template/coding-task-manager/lib/migrations/v59-coding-session-model-state-dsh.js +73 -0
- package/template/coding-task-manager/lib/migrations/v60-delegate-pref-mirror-dsh.js +78 -0
- package/template/coding-task-manager/lib/migrations/v61-conversation-item-clock.js +71 -0
- package/template/coding-task-manager/lib/model-availability.js +727 -0
- package/template/coding-task-manager/lib/model-execution-recipe-metadata.js +4 -6
- package/template/coding-task-manager/lib/model-host-receipt.js +6 -3
- package/template/coding-task-manager/lib/model-id-rule.js +19 -0
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/auto-mode-review.js +110 -23
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/generation-probe.js +60 -17
- package/template/coding-task-manager/lib/model-proxy/historical-tool-declarations.js +37 -0
- package/template/coding-task-manager/lib/model-proxy/lead-request-validation.js +1 -0
- package/template/coding-task-manager/lib/model-proxy/lead-token-admin.js +130 -0
- package/template/coding-task-manager/lib/model-proxy/refusal-scope.js +151 -0
- package/template/coding-task-manager/lib/model-proxy/request-budget-store.js +11 -2
- package/template/coding-task-manager/lib/model-proxy/tokens.js +69 -5
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-agent-model-args.js +25 -22
- package/template/coding-task-manager/lib/native-history-control.js +6 -4
- package/template/coding-task-manager/lib/native-lead-settings-client.js +44 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +173 -36
- package/template/coding-task-manager/lib/online-backup-worker-client.js +2 -0
- package/template/coding-task-manager/lib/opencode-cli.js +480 -0
- package/template/coding-task-manager/lib/opencode-launch-model.js +471 -0
- package/template/coding-task-manager/lib/opencode-v1-plugin/model-carrier.mjs +35 -0
- package/template/coding-task-manager/lib/opencode-v2-plugin/server.js +118 -0
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +1 -1
- package/template/coding-task-manager/lib/park-composer-draft.js +54 -0
- package/template/coding-task-manager/lib/park-fresh-relaunch.js +41 -10
- package/template/coding-task-manager/lib/perf-phase-trace.js +72 -0
- package/template/coding-task-manager/lib/perf-summary.js +7 -0
- package/template/coding-task-manager/lib/perf-tracker.js +63 -2
- package/template/coding-task-manager/lib/project-config.js +7 -0
- package/template/coding-task-manager/lib/prompt-purge-v2.js +52 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +72 -15
- package/template/coding-task-manager/lib/provider-login-tab.js +10 -2
- package/template/coding-task-manager/lib/read-pool-client.js +89 -2
- package/template/coding-task-manager/lib/read-pool-worker-handle.js +29 -4
- package/template/coding-task-manager/lib/recent-catalog-query.js +15 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +67 -10
- package/template/coding-task-manager/lib/recovery-evidence.js +26 -11
- package/template/coding-task-manager/lib/relay-client.js +57 -3
- package/template/coding-task-manager/lib/relink-audit.js +34 -5
- package/template/coding-task-manager/lib/remote-machine-catalog.js +321 -26
- package/template/coding-task-manager/lib/remote-machine-create.js +576 -36
- package/template/coding-task-manager/lib/remote-machine-link.js +546 -59
- package/template/coding-task-manager/lib/remote-machine-proxy.js +143 -9
- package/template/coding-task-manager/lib/remote-session-forward.js +65 -7
- package/template/coding-task-manager/lib/remote-terminal-target.js +9 -2
- package/template/coding-task-manager/lib/restart-guard.js +18 -6
- package/template/coding-task-manager/lib/restore-seed-modes.js +87 -0
- package/template/coding-task-manager/lib/restored-scrollback-hydration-runtime.js +22 -2
- package/template/coding-task-manager/lib/resume-admission.js +17 -3
- package/template/coding-task-manager/lib/review-repo-registry.js +58 -19
- package/template/coding-task-manager/lib/root-delivery-runtime.js +2 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +1 -1
- package/template/coding-task-manager/lib/runtime-contract.js +3 -1
- package/template/coding-task-manager/lib/schema-indexes.js +1 -0
- package/template/coding-task-manager/lib/session-context-locator.js +742 -0
- package/template/coding-task-manager/lib/session-create/attachment.js +2 -2
- package/template/coding-task-manager/lib/session-create/create-phases.js +118 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +86 -16
- package/template/coding-task-manager/lib/session-create/dsh-session.js +930 -0
- package/template/coding-task-manager/lib/session-create/lead-route-launch.js +186 -13
- package/template/coding-task-manager/lib/session-create/native-lead-lifetime.js +55 -3
- package/template/coding-task-manager/lib/session-create/opencode-lead-provider.js +50 -0
- package/template/coding-task-manager/lib/session-create/prepared.js +162 -38
- package/template/coding-task-manager/lib/session-create/provider-process.js +160 -28
- package/template/coding-task-manager/lib/session-create/response.js +7 -7
- package/template/coding-task-manager/lib/session-create/structured-session.js +27 -0
- package/template/coding-task-manager/lib/session-create/subagent-pick-table.js +3 -1
- package/template/coding-task-manager/lib/session-create/subagent-pick.js +458 -9
- package/template/coding-task-manager/lib/session-create/transcript.js +1 -1
- package/template/coding-task-manager/lib/session-create/worker-budget-setup.js +21 -2
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +7 -1
- package/template/coding-task-manager/lib/session-create/worker-launch-sandbox.js +39 -10
- package/template/coding-task-manager/lib/session-create/worker-observability.js +2 -2
- package/template/coding-task-manager/lib/session-empty.js +13 -10
- package/template/coding-task-manager/lib/session-host-manager.js +60 -0
- package/template/coding-task-manager/lib/session-jobs.js +3 -1
- package/template/coding-task-manager/lib/session-lifecycle.js +10 -4
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +6 -2
- package/template/coding-task-manager/lib/session-model-intent-contract.js +11 -8
- package/template/coding-task-manager/lib/session-park.js +738 -0
- package/template/coding-task-manager/lib/session-path-grant.js +13 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +106 -4
- package/template/coding-task-manager/lib/session-transport.js +17 -0
- package/template/coding-task-manager/lib/session-workspace-projection.js +54 -5
- package/template/coding-task-manager/lib/session-workspace-tracking-runtime.js +213 -1
- package/template/coding-task-manager/lib/skill-autocomplete-query.js +120 -3
- package/template/coding-task-manager/lib/skill-autocomplete.js +15 -1
- package/template/coding-task-manager/lib/sqlite-file-set.js +39 -0
- package/template/coding-task-manager/lib/standup-search-adapter.js +16 -2
- package/template/coding-task-manager/lib/state-sync/client-ledger.js +12 -0
- package/template/coding-task-manager/lib/state-sync/frame-emitter.js +319 -100
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +4 -1
- package/template/coding-task-manager/lib/storage/delegate-pref-mirror-store.js +32 -9
- package/template/coding-task-manager/lib/structured-session-boot-sweep.js +235 -0
- package/template/coding-task-manager/lib/submission-ack.js +90 -2
- package/template/coding-task-manager/lib/systemd-scope.js +115 -0
- package/template/coding-task-manager/lib/telemetry-receiver.js +39 -0
- package/template/coding-task-manager/lib/terminal-attach-geometry.js +985 -0
- package/template/coding-task-manager/lib/terminal-bootstrap.js +30 -0
- package/template/coding-task-manager/lib/terminal-draft-operation.js +357 -0
- package/template/coding-task-manager/lib/terminal-input-admission.js +17 -1
- package/template/coding-task-manager/lib/terminal-input-prepared.js +563 -0
- package/template/coding-task-manager/lib/transcript-cache-temps.js +171 -0
- package/template/coding-task-manager/lib/transcript-frame-cache.js +8 -3
- package/template/coding-task-manager/lib/transcript-source.js +36 -4
- package/template/coding-task-manager/lib/transcript-store.js +9 -0
- package/template/coding-task-manager/lib/typing-interaction-trace.js +106 -3
- package/template/coding-task-manager/lib/usage-ledger/backfill.js +40 -5
- package/template/coding-task-manager/lib/usage-ledger/client.js +4 -1
- package/template/coding-task-manager/lib/usage-ledger/dsh-parse.js +152 -0
- package/template/coding-task-manager/lib/usage-ledger/dsh-read.js +73 -0
- package/template/coding-task-manager/lib/usage-ledger/ingest.js +34 -6
- package/template/coding-task-manager/lib/usage-ledger/live.js +35 -8
- package/template/coding-task-manager/lib/usage-ledger/read.js +29 -20
- package/template/coding-task-manager/lib/usage-ledger/schema.js +61 -1
- package/template/coding-task-manager/lib/usage-ledger/task-coordinator.js +4 -2
- package/template/coding-task-manager/lib/wake-skip-reasons.js +1 -0
- package/template/coding-task-manager/lib/walle/turn.js +1 -1
- package/template/coding-task-manager/lib/walle-history-serve.js +838 -0
- package/template/coding-task-manager/lib/walle-kill-authority.js +2 -2
- package/template/coding-task-manager/lib/walle-log-rotation.js +164 -1
- package/template/coding-task-manager/lib/walle-mcp-auto-config.js +56 -2
- package/template/coding-task-manager/lib/walle-row-history.js +495 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +33 -14
- package/template/coding-task-manager/lib/watch-worker-client.js +203 -0
- package/template/coding-task-manager/lib/worker-terminal-output.js +5 -2
- package/template/coding-task-manager/lib/ws/hub-bridge.js +35 -0
- package/template/coding-task-manager/lib/ws/lifecycle.js +6 -11
- package/template/coding-task-manager/lib/ws/misc.js +1 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +106 -4
- package/template/coding-task-manager/lib/ws/terminal-attach.js +91 -0
- package/template/coding-task-manager/oauth-proxy.js +112 -115
- package/template/coding-task-manager/package-lock.json +10 -94
- package/template/coding-task-manager/package.json +4 -3
- package/template/coding-task-manager/protocol/message-table.json +10 -0
- package/template/coding-task-manager/protocol/messages.js +10 -0
- package/template/coding-task-manager/protocol/ws-schema.json +20 -0
- package/template/coding-task-manager/protocol/ws-schema.md +2 -0
- package/template/coding-task-manager/public/css/app.css +170 -0
- package/template/coding-task-manager/public/css/walle-session.css +4 -0
- package/template/coding-task-manager/public/index.html +473 -243
- package/template/coding-task-manager/public/js/agent-command.js +86 -0
- package/template/coding-task-manager/public/js/app/backups-panel.js +111 -5
- package/template/coding-task-manager/public/js/app/coding-agent-upgrade.js +103 -4
- package/template/coding-task-manager/public/js/app/machines-page.js +1328 -8
- package/template/coding-task-manager/public/js/app/models-tab.js +113 -38
- package/template/coding-task-manager/public/js/app/restart-banner.js +53 -0
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +184 -2
- package/template/coding-task-manager/public/js/background-work.js +196 -27
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +138 -10
- package/template/coding-task-manager/public/js/core/active-session-groups.js +179 -0
- package/template/coding-task-manager/public/js/core/pending-create.js +238 -0
- package/template/coding-task-manager/public/js/core/recent-machine-source.js +228 -0
- package/template/coding-task-manager/public/js/core/session-commands.js +180 -14
- package/template/coding-task-manager/public/js/dashboard-client-function-order.json +8 -0
- package/template/coding-task-manager/public/js/document-review-links.js +9 -1
- package/template/coding-task-manager/public/js/file-resolution-client.js +52 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +22 -2
- package/template/coding-task-manager/public/js/machine-pool-shared.js +558 -3
- package/template/coding-task-manager/public/js/message-renderer.js +4 -3
- package/template/coding-task-manager/public/js/model-picker.js +3 -1
- package/template/coding-task-manager/public/js/native-subagent-review.js +15 -2
- package/template/coding-task-manager/public/js/new-session-agent-grid.js +346 -0
- package/template/coding-task-manager/public/js/pasted-content.js +236 -0
- package/template/coding-task-manager/public/js/pe-private-content-lifetime.js +39 -7
- package/template/coding-task-manager/public/js/private-model-lifetime.js +6 -2
- package/template/coding-task-manager/public/js/prompts.js +11 -10
- package/template/coding-task-manager/public/js/protocol.js +10 -0
- package/template/coding-task-manager/public/js/restart-banner-policy.js +29 -1
- package/template/coding-task-manager/public/js/session-model-picker.js +447 -57
- package/template/coding-task-manager/public/js/session-search-utils.js +18 -2
- package/template/coding-task-manager/public/js/session-usage-view.js +2 -1
- package/template/coding-task-manager/public/js/session-workspace-tracking.js +51 -1
- package/template/coding-task-manager/public/js/state-sync-client.js +10 -1
- package/template/coding-task-manager/public/js/stream-view.js +6 -5
- package/template/coding-task-manager/public/js/terminal/conv-only-session.js +287 -0
- package/template/coding-task-manager/public/js/terminal/runtime-09.js +2 -0
- package/template/coding-task-manager/public/js/terminal/runtime-10.js +5 -5
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +8 -1
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +1 -1
- package/template/coding-task-manager/public/js/terminal-attachment-draft.js +67 -13
- package/template/coding-task-manager/public/js/terminal-image-orchestration.js +52 -6
- package/template/coding-task-manager/public/js/terminal-wheel.js +23 -3
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +4 -4
- package/template/coding-task-manager/public/js/walle.js +6 -0
- package/template/coding-task-manager/public/js/ws/live-dispatch.js +10 -0
- package/template/coding-task-manager/public/m/app.css +140 -0
- package/template/coding-task-manager/public/m/app.js +507 -68
- package/template/coding-task-manager/public/m/index.html +17 -0
- package/template/coding-task-manager/public/m/machines.js +838 -4
- package/template/coding-task-manager/public/m/private-api.js +31 -1
- package/template/coding-task-manager/public/usage.html +1 -0
- package/template/coding-task-manager/scripts/dev-route-fixture/synthetic-route-upstream.js +104 -0
- package/template/coding-task-manager/scripts/dev-route-fixture.js +339 -0
- package/template/coding-task-manager/scripts/opencode-lead-route-probe.js +195 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/fake-anthropic.js +168 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe/probe-plugin/server.js +95 -0
- package/template/coding-task-manager/scripts/opencode-v2-contract-probe.js +673 -0
- package/template/coding-task-manager/server.js +1950 -11679
- package/template/coding-task-manager/session-integrity.js +64 -4
- package/template/coding-task-manager/workers/db-owner-worker.js +19 -2
- package/template/coding-task-manager/workers/online-backup-worker.js +1 -0
- package/template/coding-task-manager/workers/read-pool-model-collector.js +51 -3
- package/template/coding-task-manager/workers/read-pool-worker.js +76 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +6 -6
- package/template/coding-task-manager/workers/session-host-process.js +5 -5
- package/template/coding-task-manager/workers/watch-worker.js +105 -0
- package/template/coding-task-manager/workers/worktree-worker.js +168 -33
- package/template/ctm-relay/lib/protocol.js +14 -1
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/shared/backup-retention.js +82 -0
- package/template/shared/conversation-admission.js +2 -0
- package/template/shared/conversation-provenance.js +3 -7
- package/template/shared/conversation-storage-v2-contract.js +5 -0
- package/template/shared/linked-worktree.js +51 -0
- package/template/shared/macos-fda-target.js +57 -0
- package/template/shared/orphan-parents.js +55 -0
- package/template/shared/release-schema.json +2 -2
- package/template/shared/storage/contract.js +3 -0
- package/template/wall-e/adapters/imessage.js +12 -0
- package/template/wall-e/agent.js +71 -4
- package/template/wall-e/api-walle.js +21 -1
- package/template/wall-e/bin/train-gemma-e4b-tooluse.js +2 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +5 -5
- package/template/wall-e/brain/brain-join.js +859 -0
- package/template/wall-e/brain/brain-sync-membership.js +20 -0
- package/template/wall-e/brain/brain-sync-store.js +131 -77
- package/template/wall-e/brain/brain-sync-v2-schema.js +203 -0
- package/template/wall-e/brain/brain-sync-v2.js +578 -0
- package/template/wall-e/brain/delegate-model-prefs-store.js +13 -4
- package/template/wall-e/brain/deterministic-id.js +51 -0
- package/template/wall-e/brain/memories.js +2 -2
- package/template/wall-e/brain/migrations.js +40 -6
- package/template/wall-e/brain/model-identity-migration.js +1 -1
- package/template/wall-e/brain/owner-call-whitelist.js +23 -7
- package/template/wall-e/brain/schema.js +45 -85
- package/template/wall-e/brain.js +171 -35
- package/template/wall-e/chat.js +3 -3
- package/template/wall-e/coding/agent-shell-env.js +7 -2
- package/template/wall-e/coding/prompt-bundle.js +66 -21
- package/template/wall-e/config/main-loop-exemptions.json +2 -2
- package/template/wall-e/http/admin-api.js +37 -0
- package/template/wall-e/http/gws-api.js +4 -0
- package/template/wall-e/http/helper-rules-api.js +7 -1
- package/template/wall-e/http/model-admin.js +8 -1
- package/template/wall-e/http/model-delegate-pref-admin.js +3 -3
- package/template/wall-e/http/model-proxy-providers.js +174 -1
- package/template/wall-e/http/model-route-health.js +157 -0
- package/template/wall-e/http/sync-api.js +278 -464
- package/template/wall-e/jobs/job-runner.js +28 -1
- package/template/wall-e/lib/brain-owner-op-priority.js +9 -1
- package/template/wall-e/lib/ctm-data-dir.js +26 -0
- package/template/wall-e/lib/derivation-home.js +147 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +50 -9
- package/template/wall-e/lib/helper-rules/grade.js +51 -8
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +38 -5
- package/template/wall-e/lib/helper-rules/store.js +4 -2
- package/template/wall-e/lib/landing-mcp-tools.js +170 -0
- package/template/wall-e/lib/mcp-client-config.js +133 -14
- package/template/wall-e/lib/mcp-gateway-migrate.js +28 -64
- package/template/wall-e/lib/mcp-integration.js +58 -13
- package/template/wall-e/lib/parent-death.js +7 -1
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -4
- package/template/wall-e/llm/delegate-lead-prefs.js +16 -1
- package/template/wall-e/llm/delegate-vendor-default.js +12 -5
- package/template/wall-e/llm/model-roles.js +1 -1
- package/template/wall-e/llm/native-delegate-selection.js +56 -8
- package/template/wall-e/llm/worker-delegate-args.js +72 -7
- package/template/wall-e/llm/worker-mcp-routing.js +66 -17
- package/template/wall-e/loops/brain-custom-writes.js +19 -0
- package/template/wall-e/loops/ingest.js +17 -1
- package/template/wall-e/loops/think.js +19 -4
- package/template/wall-e/mcp-contract.js +222 -6
- package/template/wall-e/mcp-protocol-contract.js +40 -5
- package/template/wall-e/mcp-server.js +128 -29
- package/template/wall-e/mcp-worker-schemas.js +5 -5
- package/template/wall-e/memory/ctm-context-client.js +85 -0
- package/template/wall-e/memory/ctm-session-context.js +9 -3
- package/template/wall-e/memory/hub-bridge-client.js +388 -0
- package/template/wall-e/memory/replica-origin.js +56 -0
- package/template/wall-e/memory/session-pool.js +135 -0
- package/template/wall-e/runtime/live-capabilities.js +8 -3
- package/template/wall-e/server.js +4 -2
- package/template/wall-e/shared/release-schema.json +2 -2
- package/template/wall-e/shared/sqlite-file-set.js +39 -0
- package/template/wall-e/shared/storage/contract.js +3 -0
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +7 -1
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +4 -4
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +6 -6
- package/template/wall-e/skills/_templates/fleet-sync/VERSION +1 -0
- package/template/wall-e/skills/_templates/fleet-sync/released-sha256.json +16 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/claude/SKILL.md +64 -0
- package/template/wall-e/skills/_templates/fleet-sync/templates/codex/SKILL.md +64 -0
- package/template/wall-e/tools/chrome-automation.js +6 -0
- package/template/wall-e/training/setup-cuda-train-env.sh +2 -2
- package/template/wall-e/workers/brain-owner-worker.js +18 -4
- package/template/wall-e/workers/mcp-gateway-process.js +5 -5
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// DeepSeek Harness (`dsh`) usage-row parser for the usage ledger (design
|
|
4
|
+
// docs/deepseek-harness-acp-agent-2026-10-28.html §5 D-19 and §9b L-3..L-8).
|
|
5
|
+
//
|
|
6
|
+
// The ONE source of dsh spend is the model proxy's per-request file,
|
|
7
|
+
// `<dataDir>/dsh-usage/<ctmSessionId>.jsonl` (written by lib/acp/dsh-usage-log.js; that contract is
|
|
8
|
+
// FROZEN -- this parser reads it, it never redefines it). One JSON object per line:
|
|
9
|
+
//
|
|
10
|
+
// {"ts":"<ISO-8601 UTC>","requestId":"<id>","model":"<wire model id>","input_tokens":N,
|
|
11
|
+
// "output_tokens":N,"cache_read_input_tokens":N,"cache_creation_input_tokens":N}
|
|
12
|
+
//
|
|
13
|
+
// A line that is not JSON, or is JSON that is not an object, carries no call: the reader counts it
|
|
14
|
+
// (usage_files.skipped_lines) and keeps going. Nothing a malformed line says is ever guessed at.
|
|
15
|
+
//
|
|
16
|
+
// Pure by construction: it takes an already-parsed JSON object per line and returns facts. No fs, no
|
|
17
|
+
// DB, no try/catch (the caller owns the read loop and the JSON.parse), exactly like codex-parse.js.
|
|
18
|
+
//
|
|
19
|
+
// Unlike a Claude/Codex transcript this file is APPEND-ONLY and holds nothing but calls, so there is
|
|
20
|
+
// no turn, prompt, spawn, delegation or agent fact to derive from it:
|
|
21
|
+
// * `prompt_id` is NULL. The file states spend, not conversation; inventing a prompt identity from
|
|
22
|
+
// a request id would claim an attribution the source cannot support.
|
|
23
|
+
// * `agent_id` is '' -- the ledger's convention for the SESSION's main agent (the same spelling
|
|
24
|
+
// claude-parse.js uses for a root transcript). dsh has no sub-agents of its own.
|
|
25
|
+
//
|
|
26
|
+
// Identity: `requestId` IS the call's identity (the contract says so), so the call key is
|
|
27
|
+
// `dsh:<requestId>` and the same id written twice is ONE call. The id is also stored beside the key
|
|
28
|
+
// as `request_id`, the evidence column every provider's call row carries.
|
|
29
|
+
|
|
30
|
+
// The directory whose `*.jsonl` files are dsh usage rows (ingest.js decides the provider by it).
|
|
31
|
+
const DSH_USAGE_DIR_NAME = 'dsh-usage';
|
|
32
|
+
const DSH_CALL_KEY_PREFIX = 'dsh:';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The CTM session id a dsh usage file belongs to: its own file name without the extension (the
|
|
36
|
+
* frozen contract of lib/acp/dsh-usage-log.js -- the name IS the id, never a directory lookup).
|
|
37
|
+
*
|
|
38
|
+
* @param {string} filePath
|
|
39
|
+
* @returns {string|null}
|
|
40
|
+
*/
|
|
41
|
+
function dshFileSessionId(filePath) {
|
|
42
|
+
const clean = String(filePath || '').replace(/\\/g, '/');
|
|
43
|
+
const base = clean.slice(clean.lastIndexOf('/') + 1);
|
|
44
|
+
const match = /^(.+)\.jsonl$/.exec(base);
|
|
45
|
+
return match ? match[1] : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Non-negative integer token count. A missing, malformed or negative value is 0 -- the columns are
|
|
49
|
+
// NOT NULL integers where 0 already means "the provider reported nothing", never a separate state.
|
|
50
|
+
function count(value) {
|
|
51
|
+
const n = Number(value);
|
|
52
|
+
if (!Number.isFinite(n) || n <= 0) return 0;
|
|
53
|
+
return Math.round(n);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// The call's identity. An absent or non-string `requestId` names no call the proxy could have
|
|
57
|
+
// written twice under one id, so the LINE OFFSET stands in: it is stable for a given append-only
|
|
58
|
+
// file, so a re-read of the same bytes keys identically instead of minting a second call.
|
|
59
|
+
function callKeyFor(requestId, lineOffset) {
|
|
60
|
+
const id = typeof requestId === 'string' ? requestId : (typeof requestId === 'number' && Number.isFinite(requestId) ? String(requestId) : '');
|
|
61
|
+
return id === '' ? `${DSH_CALL_KEY_PREFIX}line:${lineOffset}` : `${DSH_CALL_KEY_PREFIX}${id}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The call-row shape the store accepts, field for field the shape codex-parse.js hands it.
|
|
65
|
+
// * `input` is the UNCACHED input: the Anthropic Messages API (what dsh speaks) reports
|
|
66
|
+
// `input_tokens` WITHOUT the cache read/creation halves, so nothing is subtracted here (Codex's
|
|
67
|
+
// OpenAI-shaped totals, which DO include the cached prefix, are the case that subtracts).
|
|
68
|
+
// * `cache_write_1h` is 0: the contract carries one cache-creation count, and the 5-minute bucket
|
|
69
|
+
// is the only one that backs it.
|
|
70
|
+
function callRowFromRow(record, { callKey, requestId, sessionId, lineOffset }) {
|
|
71
|
+
return {
|
|
72
|
+
call_key: callKey,
|
|
73
|
+
provider: 'dsh',
|
|
74
|
+
session_id: sessionId,
|
|
75
|
+
// '' is the session's MAIN agent (the ledger convention, see claude-parse.js).
|
|
76
|
+
agent_id: '',
|
|
77
|
+
// No prompt attribution is derivable from a usage row alone (see the header).
|
|
78
|
+
prompt_id: null,
|
|
79
|
+
ts: Date.parse(record.ts) || 0,
|
|
80
|
+
model: typeof record.model === 'string' && record.model !== '' ? record.model : null,
|
|
81
|
+
input: count(record.input_tokens),
|
|
82
|
+
output: count(record.output_tokens),
|
|
83
|
+
cache_read: count(record.cache_read_input_tokens),
|
|
84
|
+
cache_write_5m: count(record.cache_creation_input_tokens),
|
|
85
|
+
cache_write_1h: 0,
|
|
86
|
+
reasoning: 0,
|
|
87
|
+
// A dsh row IS the final reading of its own request: the proxy writes it once, when the request
|
|
88
|
+
// completed, so the counts are never a lower bound on a response still being streamed.
|
|
89
|
+
output_final: 1,
|
|
90
|
+
basis: 'record',
|
|
91
|
+
request_id: requestId,
|
|
92
|
+
line_offset: lineOffset,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {{sessionId?: string|null, state?: object|null}} [options]
|
|
98
|
+
* `sessionId` is the CTM session id every call of this file belongs to (its file name).
|
|
99
|
+
* `state` is the checkpoint's parse state. This parser derives nothing across lines, so the state
|
|
100
|
+
* is carried only to keep the checkpoint shape identical to the other parsers'.
|
|
101
|
+
*/
|
|
102
|
+
function createDshFileParser({ sessionId = null, state = null } = {}) {
|
|
103
|
+
const persisted = state && typeof state === 'object' ? state : {};
|
|
104
|
+
let calls = [];
|
|
105
|
+
// The ids this pass has already emitted: a repeated requestId is ONE call, not two rows the store
|
|
106
|
+
// would then have to collapse. Cleared per drain (the batch is the dedup window); a duplicate that
|
|
107
|
+
// straddles a slice boundary still collapses in the store, whose call_key is the durable identity.
|
|
108
|
+
let seen = new Set();
|
|
109
|
+
|
|
110
|
+
function line(record, lineOffset) {
|
|
111
|
+
if (!record || typeof record !== 'object' || Array.isArray(record)) return;
|
|
112
|
+
const offset = Number(lineOffset) || 0;
|
|
113
|
+
const callKey = callKeyFor(record.requestId, offset);
|
|
114
|
+
if (seen.has(callKey)) return;
|
|
115
|
+
seen.add(callKey);
|
|
116
|
+
calls.push(callRowFromRow(record, {
|
|
117
|
+
callKey,
|
|
118
|
+
requestId: typeof record.requestId === 'string' ? record.requestId : (typeof record.requestId === 'number' && Number.isFinite(record.requestId) ? String(record.requestId) : null),
|
|
119
|
+
sessionId,
|
|
120
|
+
lineOffset: offset,
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function drain() {
|
|
125
|
+
const out = {
|
|
126
|
+
calls,
|
|
127
|
+
// dsh states spend only: no prompt, spawn, alias, delegation, attempt or agent fact exists in
|
|
128
|
+
// this source, and an empty array is the honest answer for each (never a fabricated one).
|
|
129
|
+
prompts: [],
|
|
130
|
+
aliases: [],
|
|
131
|
+
spawns: [],
|
|
132
|
+
delegations: [],
|
|
133
|
+
attempts: [],
|
|
134
|
+
agents: [],
|
|
135
|
+
reported: null,
|
|
136
|
+
state: persisted,
|
|
137
|
+
};
|
|
138
|
+
calls = [];
|
|
139
|
+
seen = new Set();
|
|
140
|
+
return out;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { line, drain };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = {
|
|
147
|
+
createDshFileParser,
|
|
148
|
+
dshFileSessionId,
|
|
149
|
+
callKeyFor,
|
|
150
|
+
DSH_USAGE_DIR_NAME,
|
|
151
|
+
DSH_CALL_KEY_PREFIX,
|
|
152
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// The read model's dsh rules (design docs/deepseek-harness-acp-agent-2026-10-28.html §5 D-19, §9b L-8).
|
|
4
|
+
// Path arithmetic only: this module opens no file, so lib/usage-ledger/read.js can load it in the read pool.
|
|
5
|
+
//
|
|
6
|
+
// dsh is the ONE provider whose ledger rows are not keyed by an `agent_sessions.agent_session_id`: the
|
|
7
|
+
// model proxy names a session's usage file `<dataDir>/dsh-usage/<ctmSessionId>.jsonl`
|
|
8
|
+
// (lib/acp/dsh-usage-log.js), so the ledger's `session_id` IS the CTM session id.
|
|
9
|
+
//
|
|
10
|
+
// The usage file is NOT the session's `agent_sessions.jsonl_path`. That column names the CTM-owned
|
|
11
|
+
// TRANSCRIPT (`<dataDir>/dsh-transcripts/<acpSessionId>.jsonl`, design D-8), which carries no token usage
|
|
12
|
+
// AND whose `{type:'user'}` rows the Claude parser would admit as PROMPTS if it were ever handed to the
|
|
13
|
+
// writer as a source. The usage file lives in the sibling directory, named by the CTM session id; it is
|
|
14
|
+
// derived from the transcript path so the SCOPE and the CATALOG cannot disagree about where a session's
|
|
15
|
+
// dsh rows are. tests-integration/usage-ledger-dsh.test.js proves this path equals the ingested one
|
|
16
|
+
// (`coverage.complete` is true only then).
|
|
17
|
+
|
|
18
|
+
const path = require('node:path');
|
|
19
|
+
const { DSH_USAGE_DIR_NAME } = require('./dsh-parse');
|
|
20
|
+
|
|
21
|
+
const DSH_TRANSCRIPT_DIR_NAME = 'dsh-transcripts';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The usage file the ledger stores a dsh session's rows under, or null when the transcript path does not
|
|
25
|
+
* name a `<dataDir>/dsh-transcripts/<acp>.jsonl` file.
|
|
26
|
+
*
|
|
27
|
+
* @param {string|null|undefined} transcriptPath `agent_sessions.jsonl_path` of a dsh row
|
|
28
|
+
* @param {string|null|undefined} ctmSessionId the CTM session id the usage file is named after
|
|
29
|
+
* @returns {string|null}
|
|
30
|
+
*/
|
|
31
|
+
function dshUsageSourcePath(transcriptPath, ctmSessionId) {
|
|
32
|
+
const id = String(ctmSessionId == null ? '' : ctmSessionId);
|
|
33
|
+
const file = String(transcriptPath == null ? '' : transcriptPath);
|
|
34
|
+
if (!id || !file) return null;
|
|
35
|
+
const transcriptDir = path.dirname(file);
|
|
36
|
+
if (path.basename(transcriptDir) !== DSH_TRANSCRIPT_DIR_NAME) return null;
|
|
37
|
+
const dataDir = path.dirname(transcriptDir);
|
|
38
|
+
if (!dataDir || dataDir === '.' || dataDir === path.sep) return null;
|
|
39
|
+
return path.join(dataDir, DSH_USAGE_DIR_NAME, `${id}.jsonl`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A scope entry for a dsh `agent_sessions` row: re-keyed to the CTM session it belongs to, its source the
|
|
44
|
+
* usage file. The core db's size/mtime describe the TRANSCRIPT, so they are reported unknown rather than
|
|
45
|
+
* compared against a different file (which would call every dsh session stale). A session the proxy never
|
|
46
|
+
* wrote a file for reads as no rows, no error.
|
|
47
|
+
*/
|
|
48
|
+
function dshScopeEntry(row, role, ctmId) {
|
|
49
|
+
const sessionId = row.ctm_session_id == null || row.ctm_session_id === '' ? String(ctmId) : String(row.ctm_session_id);
|
|
50
|
+
return {
|
|
51
|
+
session_id: sessionId,
|
|
52
|
+
provider: 'dsh',
|
|
53
|
+
ctm_session_id: sessionId,
|
|
54
|
+
role,
|
|
55
|
+
source_path: dshUsageSourcePath(row.jsonl_path, sessionId),
|
|
56
|
+
expected_size: null,
|
|
57
|
+
expected_modified_at: null,
|
|
58
|
+
expected_compact_bak_size: null,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A source-catalog entry for a dsh row, or null when its usage file cannot be named (an empty path is not
|
|
64
|
+
* ingestable). `session_id` stays the row's `agent_session_id` -- the catalog page's cursor key.
|
|
65
|
+
*/
|
|
66
|
+
function dshCatalogSource(row) {
|
|
67
|
+
const ctmSessionId = row.ctm_session_id == null ? '' : String(row.ctm_session_id);
|
|
68
|
+
const sourcePath = dshUsageSourcePath(row.path, ctmSessionId);
|
|
69
|
+
if (!sourcePath) return null;
|
|
70
|
+
return { provider: 'dsh', session_id: row.session_id == null ? '' : String(row.session_id), path: sourcePath, size: null, modified_at: null };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = { DSH_TRANSCRIPT_DIR_NAME, dshUsageSourcePath, dshScopeEntry, dshCatalogSource };
|
|
@@ -26,6 +26,7 @@ const {
|
|
|
26
26
|
CLAUDE_MARKERS,
|
|
27
27
|
} = require('./claude-parse');
|
|
28
28
|
const { createCodexFileParser, CODEX_MARKERS } = require('./codex-parse');
|
|
29
|
+
const { createDshFileParser, dshFileSessionId, DSH_USAGE_DIR_NAME } = require('./dsh-parse');
|
|
29
30
|
|
|
30
31
|
// Bump when a parser's READING of a record changes: a checkpoint stamped with another
|
|
31
32
|
// version is discarded and the file is re-read from 0 (D-3). Upserts are idempotent,
|
|
@@ -49,7 +50,11 @@ const { createCodexFileParser, CODEX_MARKERS } = require('./codex-parse');
|
|
|
49
50
|
// promptId of the prompt it continues no longer relabels that row's kind, and a `delegate` result
|
|
50
51
|
// with no `generation` key resolves to generation 1 instead of dropping its edge. Both are
|
|
51
52
|
// corrections to facts already stored, so the re-read this version forces is what repairs them.
|
|
52
|
-
|
|
53
|
+
// v8 (deepseek-harness-acp-agent WP-9, design D-19): the dsh provider exists. Its source --
|
|
54
|
+
// `<dataDir>/dsh-usage/<ctmSessionId>.jsonl` -- is a NEW file this reading discovers, so nothing
|
|
55
|
+
// already stored changes shape; the bump is what makes every stored dsh file (should one ever be
|
|
56
|
+
// written before the provider was known) get read through the parser below.
|
|
57
|
+
const PARSER_VERSION = 8;
|
|
53
58
|
// The head fingerprint is the first min(size, 4096) bytes (D-3).
|
|
54
59
|
const HEAD_BYTES = 4096;
|
|
55
60
|
const DEFAULT_SLICE_BYTES = 8 * 1024 * 1024;
|
|
@@ -66,16 +71,22 @@ function sha256Hex(buf) {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/**
|
|
69
|
-
* Which provider owns `sourcePath`: 'codex' for a rollout file, '
|
|
70
|
-
* Claude Code transcript, null for
|
|
74
|
+
* Which provider owns `sourcePath`: 'codex' for a rollout file, 'dsh' for a DeepSeek Harness usage
|
|
75
|
+
* file (`<dataDir>/dsh-usage/<ctmSessionId>.jsonl`), 'claude' for a Claude Code transcript, null for
|
|
76
|
+
* anything else.
|
|
77
|
+
*
|
|
78
|
+
* The dsh test is the PARENT DIRECTORY NAME, and it is evaluated BEFORE the Claude identity: a dsh
|
|
79
|
+
* file is `<session-id>.jsonl`, which `claudeFileIdentity` would otherwise accept as a Claude root
|
|
80
|
+
* transcript (its rule is any `<name>.jsonl`). Only the directory separates the two providers.
|
|
71
81
|
*
|
|
72
82
|
* @param {string} sourcePath
|
|
73
|
-
* @returns {'claude'|'codex'|null}
|
|
83
|
+
* @returns {'claude'|'codex'|'dsh'|null}
|
|
74
84
|
*/
|
|
75
85
|
function fileProvider(sourcePath) {
|
|
76
86
|
const p = String(sourcePath || '');
|
|
77
87
|
if (!p) return null;
|
|
78
88
|
if (CODEX_ROLLOUT_RE.test(path.basename(p))) return 'codex';
|
|
89
|
+
if (/\.jsonl$/i.test(path.basename(p)) && path.basename(path.dirname(p)) === DSH_USAGE_DIR_NAME) return 'dsh';
|
|
79
90
|
if (claudeFileIdentity(p)) return 'claude';
|
|
80
91
|
return null;
|
|
81
92
|
}
|
|
@@ -154,14 +165,21 @@ function createUsageIngestor({ store, sliceBytes = DEFAULT_SLICE_BYTES, pricer =
|
|
|
154
165
|
}
|
|
155
166
|
|
|
156
167
|
const identity = provider === 'claude' ? claudeFileIdentity(sourcePath) : null;
|
|
157
|
-
|
|
168
|
+
// A dsh file's session id IS its file name (the frozen contract of lib/acp/dsh-usage-log.js), so
|
|
169
|
+
// it is known before a single byte is read -- unlike Codex, whose thread ids appear in the file.
|
|
170
|
+
const dshSessionId = provider === 'dsh' ? dshFileSessionId(sourcePath) : null;
|
|
171
|
+
// Every dsh line is a call, so there is no marker to prefilter on (null = deliver every complete
|
|
172
|
+
// line; a line that is not JSON is counted by the read loop, never guessed at).
|
|
173
|
+
const markers = provider === 'claude' ? CLAUDE_MARKERS : (provider === 'codex' ? CODEX_MARKERS : null);
|
|
158
174
|
const metaAgent = provider === 'claude' && identity.agentId && offset === 0
|
|
159
175
|
? readMetaAgent(sourcePath, identity)
|
|
160
176
|
: null;
|
|
161
177
|
|
|
162
178
|
const parser = provider === 'claude'
|
|
163
179
|
? createClaudeFileParser({ sessionId: identity.sessionId, agentId: identity.agentId, state })
|
|
164
|
-
:
|
|
180
|
+
: (provider === 'dsh'
|
|
181
|
+
? createDshFileParser({ sessionId: dshSessionId, state })
|
|
182
|
+
: createCodexFileParser({ state, sourcePath }));
|
|
165
183
|
|
|
166
184
|
// The file identity of a batch. For Codex the root session id and the thread id only
|
|
167
185
|
// appear once session_meta / token_usage_record has been read, so it is recomputed
|
|
@@ -176,6 +194,16 @@ function createUsageIngestor({ store, sliceBytes = DEFAULT_SLICE_BYTES, pricer =
|
|
|
176
194
|
agent_id: identity.agentId,
|
|
177
195
|
};
|
|
178
196
|
}
|
|
197
|
+
if (provider === 'dsh') {
|
|
198
|
+
// A dsh file is ONE session (its name): the id never arrives from a line, so it is the same
|
|
199
|
+
// on every pass and `agent_id` '' names that session's main agent.
|
|
200
|
+
return {
|
|
201
|
+
source_path: sourcePath,
|
|
202
|
+
provider,
|
|
203
|
+
session_id: dshSessionId,
|
|
204
|
+
agent_id: '',
|
|
205
|
+
};
|
|
206
|
+
}
|
|
179
207
|
const s = parserState || {};
|
|
180
208
|
return {
|
|
181
209
|
source_path: sourcePath,
|
|
@@ -29,18 +29,33 @@ const DEFAULT_MAX_BYTES_PER_FILE = 4 * 1024 * 1024;
|
|
|
29
29
|
const MAX_ERRORS = 20;
|
|
30
30
|
const CODEX_ROLLOUT_RE = /^rollout-.*\.jsonl$/;
|
|
31
31
|
const CLAUDE_AGENT_RE = /^agent-.*\.jsonl$/;
|
|
32
|
+
const DSH_USAGE_FILE_RE = /\.jsonl$/i;
|
|
33
|
+
// Every provider this lane can be handed a root for. A root naming anything else is defaulted to
|
|
34
|
+
// 'claude' (the historical spelling) rather than silently admitted as itself.
|
|
35
|
+
const LIVE_PROVIDERS = new Set(['claude', 'codex', 'dsh']);
|
|
32
36
|
|
|
33
37
|
// `<...>/<sid>.jsonl` or `<...>/<sid>.jsonl.bak` -> `<...>/<sid>/subagents`.
|
|
34
38
|
function claudeSubagentsDir(rootPath) {
|
|
35
39
|
return path.join(String(rootPath).replace(/\.jsonl(?:\.bak)?$/i, ''), 'subagents');
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
// The directory a source's SIBLING files live in, and the key that identifies it as a discovery root.
|
|
43
|
+
// Codex and dsh both scan one FLAT directory (Codex `sessions/`, dsh `<dataDir>/dsh-usage/`, whose
|
|
44
|
+
// file names are CTM session ids); Claude's siblings are the `<sid>/subagents` tree beside a root
|
|
45
|
+
// transcript. The key is prefixed per provider so a Codex sessions dir and a dsh dir can never
|
|
46
|
+
// collide.
|
|
47
|
+
function discoveryDirKey(provider, rootPath) {
|
|
48
|
+
if (provider === 'codex') return `codex:${path.dirname(rootPath)}`;
|
|
49
|
+
if (provider === 'dsh') return `dsh:${path.dirname(rootPath)}`;
|
|
50
|
+
return claudeSubagentsDir(rootPath);
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
// A root list normalized to `{provider, path}` with the provider defaulted. Pure and
|
|
39
54
|
// exported so both the lane and the worker's change detector agree on one shape.
|
|
40
55
|
function normalizeRoots(next) {
|
|
41
56
|
return (Array.isArray(next) ? next : [])
|
|
42
57
|
.filter((root) => root && typeof root.path === 'string' && root.path)
|
|
43
|
-
.map((root) => ({ provider: root.provider
|
|
58
|
+
.map((root) => ({ provider: LIVE_PROVIDERS.has(root.provider) ? root.provider : 'claude', path: root.path }));
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
// The identity of a root set: sorted `provider:path`. The worker fires its prompt
|
|
@@ -80,11 +95,16 @@ function createLiveLane({
|
|
|
80
95
|
const priority = new Map();
|
|
81
96
|
function discoveryRoot(source) {
|
|
82
97
|
if (source.provider === 'codex') return null; // inactive Codex sources are supplied by the native catalog
|
|
98
|
+
// dsh has no catalog of its own: one flat directory holds every session's file, so ANY dsh root
|
|
99
|
+
// (the source itself, or a file the caller requested) makes the whole directory discoverable.
|
|
100
|
+
if (source.provider === 'dsh') return { ...source, key: discoveryDirKey('dsh', source.path) };
|
|
83
101
|
const identity = claudeFileIdentity(source.path);
|
|
84
102
|
return identity && !identity.agentId ? { ...source, key: claudeSubagentsDir(source.path) } : null;
|
|
85
103
|
}
|
|
86
104
|
function enqueueDiscovery(source, { active = false, urgent = false } = {}) {
|
|
87
|
-
const root = source.provider === 'codex'
|
|
105
|
+
const root = (source.provider === 'codex' || source.provider === 'dsh') && active
|
|
106
|
+
? { ...source, key: discoveryDirKey(source.provider, source.path) }
|
|
107
|
+
: discoveryRoot(source);
|
|
88
108
|
if (!root) return true;
|
|
89
109
|
const previous = discoveryRoots.get(root.key);
|
|
90
110
|
if (previous) { previous.active ||= active; previous.urgent ||= urgent; return true; }
|
|
@@ -97,7 +117,7 @@ function createLiveLane({
|
|
|
97
117
|
const cap = urgent ? PRIORITY_SOURCE_CAP : SOURCE_QUEUE_CAP;
|
|
98
118
|
const result = (accepted) => ({ accepted, backlog: pending.size + priority.size, priorityBacklog: priority.size, catalogBacklog: pending.size, discoveryBacklog: discoveryRoots.size });
|
|
99
119
|
if (!Array.isArray(sources) || sources.length > SOURCE_BATCH_CAP) return result(false);
|
|
100
|
-
if (sources.some((source) => !source || typeof source.path !== 'string' || !path.isAbsolute(source.path) || !
|
|
120
|
+
if (sources.some((source) => !source || typeof source.path !== 'string' || !path.isAbsolute(source.path) || !LIVE_PROVIDERS.has(source.provider))) return result(false);
|
|
101
121
|
const normalized = normalizeRoots(sources);
|
|
102
122
|
const fresh = normalized.filter((source) => !queue.has(source.path) && (urgent || !priority.has(source.path)));
|
|
103
123
|
if (queue.size + new Set(fresh.map((source) => source.path)).size > cap) return result(false);
|
|
@@ -117,7 +137,7 @@ function createLiveLane({
|
|
|
117
137
|
|
|
118
138
|
function setRoots(next) {
|
|
119
139
|
roots = normalizeRoots(next);
|
|
120
|
-
const activeDirs = new Set(roots.map((root) => root.provider
|
|
140
|
+
const activeDirs = new Set(roots.map((root) => discoveryDirKey(root.provider, root.path)));
|
|
121
141
|
for (const entry of discoveryRoots.values()) entry.active = activeDirs.has(entry.key);
|
|
122
142
|
for (const root of roots) enqueueDiscovery(root, { active: true });
|
|
123
143
|
}
|
|
@@ -136,12 +156,19 @@ function createLiveLane({
|
|
|
136
156
|
}
|
|
137
157
|
{
|
|
138
158
|
yield null; // one root-work unit even when its directories do not exist
|
|
139
|
-
|
|
159
|
+
// Codex and dsh both list ONE flat directory; Claude's siblings live in `<sid>/subagents`.
|
|
160
|
+
// `recentOnly` keeps the Codex sessions tree bounded to recently touched rollouts -- a dsh
|
|
161
|
+
// usage directory holds one small file per session, so every file in it is worth a stat.
|
|
162
|
+
const dir = root.provider === 'codex' || root.provider === 'dsh'
|
|
163
|
+
? path.dirname(root.path)
|
|
164
|
+
: claudeSubagentsDir(root.path);
|
|
165
|
+
const fileRe = root.provider === 'codex' ? CODEX_ROLLOUT_RE
|
|
166
|
+
: (root.provider === 'dsh' ? DSH_USAGE_FILE_RE : CLAUDE_AGENT_RE);
|
|
140
167
|
for (const entry of entries(dir)) {
|
|
141
|
-
yield entry.isFile &&
|
|
168
|
+
yield entry.isFile && fileRe.test(entry.name)
|
|
142
169
|
? { provider: root.provider, path: path.join(dir, entry.name), recentOnly: root.provider === 'codex' } : null;
|
|
143
170
|
}
|
|
144
|
-
if (root.provider === 'codex') return;
|
|
171
|
+
if (root.provider === 'codex' || root.provider === 'dsh') return; // no `workflows/` walk: flat only
|
|
145
172
|
const workflows = path.join(dir, 'workflows');
|
|
146
173
|
for (const workflow of entries(workflows)) {
|
|
147
174
|
yield null;
|
|
@@ -273,4 +300,4 @@ function createLiveLane({
|
|
|
273
300
|
return { setRoots, requestSources, tick, close, currentFiles: () => current };
|
|
274
301
|
}
|
|
275
302
|
|
|
276
|
-
module.exports = { SOURCE_QUEUE_CAP, SOURCE_BATCH_CAP, PRIORITY_SOURCE_CAP, DISCOVERY_ROOT_CAP, OPEN_DISCOVERY_CAP, KNOWN_SWEEP_LIMIT, BACKGROUND_BYTES, createLiveLane, normalizeRoots, rootsKey, claudeSubagentsDir };
|
|
303
|
+
module.exports = { SOURCE_QUEUE_CAP, SOURCE_BATCH_CAP, PRIORITY_SOURCE_CAP, DISCOVERY_ROOT_CAP, OPEN_DISCOVERY_CAP, KNOWN_SWEEP_LIMIT, BACKGROUND_BYTES, createLiveLane, normalizeRoots, rootsKey, claudeSubagentsDir, discoveryDirKey, LIVE_PROVIDERS };
|
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
// (workers/read-pool-worker.js), the same way store.js is loaded only inside the writer worker.
|
|
8
8
|
//
|
|
9
9
|
// Entry points:
|
|
10
|
-
// resolveScope(coreDb, ctmSessionId)
|
|
10
|
+
// resolveScope(coreDb, ctmSessionId) -- CTM id -> the PROVIDER session ids whose
|
|
11
11
|
// ledger rows belong to it (the ledger's
|
|
12
12
|
// session_id is the provider session id: the
|
|
13
|
-
// Claude root transcript uuid,
|
|
14
|
-
// root thread id
|
|
13
|
+
// Claude root transcript uuid, the Codex
|
|
14
|
+
// root thread id, or -- for dsh -- the CTM
|
|
15
|
+
// session id itself, which is what its usage
|
|
16
|
+
// file is NAMED), plus the durable
|
|
15
17
|
// source/mapping coverage of that scope.
|
|
16
18
|
// sourceHints(scope) -- the internal (path-bearing) work hints the
|
|
17
19
|
// runtime WP feeds to the writer. Never public.
|
|
@@ -31,7 +33,9 @@
|
|
|
31
33
|
// `agent_session_id` equals it while a `ctm_sessions` row carries that id
|
|
32
34
|
// (`LEFT JOIN ctm_sessions c ON c.id = a.agent_session_id`) -- role 'self';
|
|
33
35
|
// * the CTM sessions in `worker_sessions WHERE parent_ctm_session_id = <ctm id>`
|
|
34
|
-
// recurse the same mapping with role 'delegated' (depth <= 4, cycle-safe)
|
|
36
|
+
// recurse the same mapping with role 'delegated' (depth <= 4, cycle-safe);
|
|
37
|
+
// * dsh (WP-9, D-19): the ledger's session_id IS the CTM session id (the usage file is named by it);
|
|
38
|
+
// lib/usage-ledger/dsh-read.js owns that mapping.
|
|
35
39
|
//
|
|
36
40
|
// D-1 (durable membership): a worker's UI lifecycle never changes what it COST. A hidden,
|
|
37
41
|
// completed or resumed worker keeps every provider root mapping it ever had, so the
|
|
@@ -78,12 +82,15 @@ const CALLS_MAX_LIMIT = 500;
|
|
|
78
82
|
const SOURCE_CATALOG_DEFAULT_LIMIT = 200;
|
|
79
83
|
const SOURCE_CATALOG_MAX_LIMIT = 200;
|
|
80
84
|
|
|
85
|
+
const { dshScopeEntry, dshCatalogSource } = require('./dsh-read');
|
|
86
|
+
|
|
81
87
|
// The parser version the live ingest lane stamps (lib/usage-ledger/ingest.js PARSER_VERSION).
|
|
82
88
|
// read.js keeps its own copy so the read model stays loadable without the transcript parsers;
|
|
83
89
|
// a checkpoint stamped with any other version was written by an older READING of the record,
|
|
84
90
|
// so its source is stale until the re-read lands. tests/usage-ledger-read.test.js pins the two
|
|
85
91
|
// constants equal, so a parser bump cannot drift silently out of this comparison.
|
|
86
|
-
|
|
92
|
+
// v8 (deepseek-harness-acp-agent WP-9): the dsh provider's usage files are a new reading.
|
|
93
|
+
const CURRENT_PARSER_VERSION = 8;
|
|
87
94
|
|
|
88
95
|
// usage_calls columns the public Call carries -- everything except source_file_id and
|
|
89
96
|
// line_offset (file-storage detail, not part of the read model).
|
|
@@ -392,7 +399,7 @@ function resolveScope(coreDb, ctmSessionId) {
|
|
|
392
399
|
COALESCE(${owner}${hasCtmSessions ? ', c.id' : ''}) AS ctm_session_id${sourceSelect}${tokenSelect}
|
|
393
400
|
FROM agent_sessions a
|
|
394
401
|
${join}
|
|
395
|
-
WHERE lower(COALESCE(a.provider, '')) IN ('claude', 'codex')`;
|
|
402
|
+
WHERE lower(COALESCE(a.provider, '')) IN ('claude', 'codex', 'dsh')`;
|
|
396
403
|
|
|
397
404
|
// One probe row past the cap: the walk stops at exactly MAX_PROVIDER_SESSIONS and says so.
|
|
398
405
|
const providersFor = coreDb.prepare(`${rootSelect}
|
|
@@ -429,7 +436,7 @@ function resolveScope(coreDb, ctmSessionId) {
|
|
|
429
436
|
ORDER BY ctm_session_id LIMIT @limit`)
|
|
430
437
|
: null;
|
|
431
438
|
|
|
432
|
-
const entryFor = (row, role, ctmId) => ({
|
|
439
|
+
const entryFor = (row, role, ctmId) => (row.provider === 'dsh' ? dshScopeEntry(row, role, ctmId) : {
|
|
433
440
|
session_id: String(row.session_id),
|
|
434
441
|
provider: row.provider,
|
|
435
442
|
ctm_session_id: row.ctm_session_id == null ? ctmId : row.ctm_session_id,
|
|
@@ -520,7 +527,8 @@ function resolveScope(coreDb, ctmSessionId) {
|
|
|
520
527
|
}
|
|
521
528
|
|
|
522
529
|
for (const row of providerSessions) {
|
|
523
|
-
|
|
530
|
+
// A dsh source path is derived (lib/usage-ledger/dsh-read.js), never read from a path column.
|
|
531
|
+
if (!hasPathColumn && row.provider !== 'dsh') {
|
|
524
532
|
missingMappings.push({
|
|
525
533
|
ctm_session_id: row.ctm_session_id,
|
|
526
534
|
role: row.role,
|
|
@@ -633,11 +641,13 @@ function sourceHints(scope) {
|
|
|
633
641
|
}
|
|
634
642
|
|
|
635
643
|
/**
|
|
636
|
-
* One keyset page of every supported (Claude/Codex) source the core db knows about, ordered by
|
|
644
|
+
* One keyset page of every supported (Claude/Codex/dsh) source the core db knows about, ordered by
|
|
637
645
|
* agent_session_id (design D-2). Discovery is INDEPENDENT of terminal state: hidden workers and
|
|
638
646
|
* native subagents are sources like any other. No prompt text, no transcript bytes -- metadata
|
|
639
647
|
* only. `next` is the agent_session_id to resume AFTER, or null at the end of the catalog.
|
|
640
648
|
*
|
|
649
|
+
* A dsh row's `path` is its USAGE file, not its transcript (lib/usage-ledger/dsh-read.js).
|
|
650
|
+
*
|
|
641
651
|
* @param {object} coreDb an open READONLY core handle (the read pool's flip-aware routed handle)
|
|
642
652
|
* @param {{after?: string, limit?: number}} [options]
|
|
643
653
|
* @returns {{sources: Array<{provider: string, session_id: string, path: string, size: number|null,
|
|
@@ -657,10 +667,11 @@ function readSourceCatalog(coreDb, { after = '', limit = SOURCE_CATALOG_DEFAULT_
|
|
|
657
667
|
SELECT a.agent_session_id AS session_id,
|
|
658
668
|
lower(COALESCE(a.provider, '')) AS provider,
|
|
659
669
|
a.jsonl_path AS path,
|
|
670
|
+
${cols.has('ctm_session_id') ? 'a.ctm_session_id' : 'NULL'} AS ctm_session_id,
|
|
660
671
|
${cols.has('file_size') ? 'a.file_size' : 'NULL'} AS size,
|
|
661
672
|
${cols.has('modified_at') ? 'a.modified_at' : 'NULL'} AS modified_at
|
|
662
673
|
FROM agent_sessions a
|
|
663
|
-
WHERE lower(COALESCE(a.provider, '')) IN ('claude', 'codex')
|
|
674
|
+
WHERE lower(COALESCE(a.provider, '')) IN ('claude', 'codex', 'dsh')
|
|
664
675
|
AND COALESCE(a.jsonl_path, '') != ''
|
|
665
676
|
AND a.agent_session_id > @after
|
|
666
677
|
ORDER BY a.agent_session_id
|
|
@@ -669,16 +680,14 @@ function readSourceCatalog(coreDb, { after = '', limit = SOURCE_CATALOG_DEFAULT_
|
|
|
669
680
|
const hasMore = rows.length > effective;
|
|
670
681
|
const kept = hasMore ? rows.slice(0, effective) : rows;
|
|
671
682
|
const last = kept[kept.length - 1];
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
next: hasMore && last ? String(last.session_id) : null,
|
|
681
|
-
};
|
|
683
|
+
const sources = kept.map((row) => (row.provider === 'dsh' ? dshCatalogSource(row) : {
|
|
684
|
+
provider: row.provider,
|
|
685
|
+
session_id: row.session_id == null ? '' : String(row.session_id),
|
|
686
|
+
path: row.path == null ? '' : String(row.path),
|
|
687
|
+
size: numberOrNull(row.size),
|
|
688
|
+
modified_at: textOrNull(row.modified_at),
|
|
689
|
+
})).filter(Boolean);
|
|
690
|
+
return { sources, next: hasMore && last ? String(last.session_id) : null };
|
|
682
691
|
}
|
|
683
692
|
|
|
684
693
|
// A reported row's model_usage_json is written by the ingester; a torn or absent value reads
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const { createMigrationRunner, pragmaVersionStore } = require('../../../shared/db-migration-runner');
|
|
17
17
|
|
|
18
|
-
const USAGE_LEDGER_SCHEMA_VERSION =
|
|
18
|
+
const USAGE_LEDGER_SCHEMA_VERSION = 9;
|
|
19
19
|
|
|
20
20
|
// The complete v1 schema, in one place. Each statement is idempotent
|
|
21
21
|
// (IF NOT EXISTS) so a re-run of the baseline against a partially-created file
|
|
@@ -348,6 +348,62 @@ function createV8(db) {
|
|
|
348
348
|
`);
|
|
349
349
|
}
|
|
350
350
|
|
|
351
|
+
// v9 (deepseek-harness-acp-agent WP-9, design D-19 / §9b L-3): `usage_files.provider` must admit
|
|
352
|
+
// 'dsh'. D-19 gives dsh spend a source of its own -- the model proxy appends one row per completed
|
|
353
|
+
// lead request to `<dataDir>/dsh-usage/<ctmSessionId>.jsonl` -- and the ledger ingests that file
|
|
354
|
+
// under `provider='dsh'`, which the v1 CHECK `provider IN ('claude','codex')` refuses by SQLite
|
|
355
|
+
// itself. SQLite cannot ALTER a CHECK, so the table is REBUILT: rename, recreate with the widened
|
|
356
|
+
// CHECK, copy every row and every column, drop the staging table. v1 is left untouched: it stays the
|
|
357
|
+
// published record of the schema IT created.
|
|
358
|
+
//
|
|
359
|
+
// Idempotence is decided by the SCHEMA, never by the version counter: a table whose sqlite_master.sql
|
|
360
|
+
// already admits 'dsh' is left byte-for-byte alone. So a fresh file (the runner's isFresh path runs
|
|
361
|
+
// the whole baseline, v9 included), a restored snapshot, and a file that already took this step all
|
|
362
|
+
// converge on the same shape, and a re-run of the ladder body writes nothing.
|
|
363
|
+
//
|
|
364
|
+
// The recreate text is the table's OWN stored DDL with only the provider CHECK widened, so no column,
|
|
365
|
+
// default, ordinal position or other constraint can drift from what the database already has. Copying
|
|
366
|
+
// by position is what makes that mandatory, and `usage_files.file_id` is an INTEGER PRIMARY KEY
|
|
367
|
+
// (rowid alias), so the copy preserves every id `usage_calls.source_file_id` already points at.
|
|
368
|
+
//
|
|
369
|
+
// The v9 step writes DDL only: nothing here inserts a 'dsh' row.
|
|
370
|
+
const DSH_USAGE_FILES_TABLE = 'usage_files';
|
|
371
|
+
// The exact v1 text of the provider CHECK. v1 is frozen, so this literal is stable; a table whose DDL
|
|
372
|
+
// does not match it is refused rather than silently rebuilt with a guessed shape.
|
|
373
|
+
const PROVIDER_CHECK = "CHECK(provider IN ('claude','codex'))";
|
|
374
|
+
const PROVIDER_CHECK_DSH = "CHECK(provider IN ('claude','codex','dsh'))";
|
|
375
|
+
|
|
376
|
+
function tableSql(db, table) {
|
|
377
|
+
const row = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?").get(table);
|
|
378
|
+
return row && typeof row.sql === 'string' ? row.sql : null;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// The EXPLICIT indexes of a table, in creation order. A PRIMARY KEY's implicit autoindex has sql =
|
|
382
|
+
// NULL and must never be recreated by name, so it is filtered out. Captured BEFORE the rename, while
|
|
383
|
+
// each index's SQL still names the real table: ALTER TABLE RENAME would rewrite that reference to the
|
|
384
|
+
// staging name, and the DROP of the staging table takes the indexes with it.
|
|
385
|
+
function tableIndexes(db, table) {
|
|
386
|
+
return db.prepare("SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = ? AND sql IS NOT NULL").all(table)
|
|
387
|
+
.map((row) => ({ name: row.name, sql: row.sql }));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function createV9(db) {
|
|
391
|
+
const sql = tableSql(db, DSH_USAGE_FILES_TABLE);
|
|
392
|
+
if (!sql) return; // no such table: nothing to widen
|
|
393
|
+
if (sql.includes("'dsh'")) return; // already widened: idempotent on schema
|
|
394
|
+
const widened = sql.split(PROVIDER_CHECK).join(PROVIDER_CHECK_DSH);
|
|
395
|
+
if (widened === sql) {
|
|
396
|
+
throw new Error(`v9: ${DSH_USAGE_FILES_TABLE} has no claude/codex provider CHECK to widen`);
|
|
397
|
+
}
|
|
398
|
+
const staging = `${DSH_USAGE_FILES_TABLE}__v9`;
|
|
399
|
+
const indexes = tableIndexes(db, DSH_USAGE_FILES_TABLE);
|
|
400
|
+
db.exec(`ALTER TABLE ${DSH_USAGE_FILES_TABLE} RENAME TO ${staging}`);
|
|
401
|
+
db.exec(widened);
|
|
402
|
+
db.exec(`INSERT INTO ${DSH_USAGE_FILES_TABLE} SELECT * FROM ${staging}`);
|
|
403
|
+
db.exec(`DROP TABLE ${staging}`);
|
|
404
|
+
for (const index of indexes) db.exec(index.sql);
|
|
405
|
+
}
|
|
406
|
+
|
|
351
407
|
// Built lazily on first use so merely requiring this module has no side effects
|
|
352
408
|
// (no module-level runner construction, no DDL, no env reads).
|
|
353
409
|
let _runner = null;
|
|
@@ -370,6 +426,7 @@ function runner() {
|
|
|
370
426
|
6: { up: createV6, label: 'v6 delegation edges' },
|
|
371
427
|
7: { up: createV7, label: 'v7 delegation launch attempts' },
|
|
372
428
|
8: { up: createV8, label: 'v8 claude re-read snapshot' },
|
|
429
|
+
9: { up: createV9, label: 'v9 dsh provider' },
|
|
373
430
|
},
|
|
374
431
|
baseline: (db) => {
|
|
375
432
|
createV1(db);
|
|
@@ -380,6 +437,9 @@ function runner() {
|
|
|
380
437
|
createV6(db);
|
|
381
438
|
createV7(db);
|
|
382
439
|
createV8(db);
|
|
440
|
+
// The baseline must produce the FULL current shape: for a fresh file this widens the v1
|
|
441
|
+
// provider CHECK in place (the table is empty, so the rebuild is a no-op on data).
|
|
442
|
+
createV9(db);
|
|
383
443
|
},
|
|
384
444
|
versionStore: pragmaVersionStore(),
|
|
385
445
|
});
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// One lifecycle-owned background round, driven by the existing client's hint tick. No interval,
|
|
4
4
|
// transcript reads or model call on the configuration/status path.
|
|
5
5
|
const { applyJudgeAnswer, JUDGE_QUESTIONS } = require('./task-grouping');
|
|
6
|
+
// D-2: the ONE model-id rule (docs/lead-model-id-rule-at-tilde-prefix-2026-10-28.html §5).
|
|
7
|
+
const { isValidOverrideModel } = require('../model-id-rule');
|
|
6
8
|
const PROBE_INTERVAL_MS = 5000;
|
|
7
9
|
const STATUS_TIMEOUT_MS = 2000;
|
|
8
10
|
const DECISION_TIMEOUT_MS = 5000;
|
|
@@ -12,12 +14,12 @@ const BACKOFF_MS = 60000;
|
|
|
12
14
|
// maker policy. Validated here (the ONE place) so the coordinator snapshot and the
|
|
13
15
|
// /api/usage/task-grouping/status reader cannot disagree about what is safe to publish.
|
|
14
16
|
const ROUTE_PROVIDER_ID_RE = /^[A-Za-z0-9._:@+-]{1,160}$/;
|
|
15
|
-
const ROUTE_MODEL_ID_RE = /^[~A-Za-z0-9._:\/@+-]{1,160}$/;
|
|
16
17
|
const ROUTE_POLICIES = new Set(['auto', 'direct', 'portkey']);
|
|
17
18
|
function routeDetail(json) {
|
|
18
19
|
return {
|
|
19
20
|
provider_id: typeof json?.provider_id === 'string' && ROUTE_PROVIDER_ID_RE.test(json.provider_id) ? json.provider_id : null,
|
|
20
|
-
|
|
21
|
+
// D-2: the ONE model-id rule (it also refuses a leading dash, which the forked rule admitted).
|
|
22
|
+
model_id: typeof json?.model_id === 'string' && isValidOverrideModel(json.model_id) ? json.model_id : null,
|
|
21
23
|
policy: ROUTE_POLICIES.has(json?.policy) ? json.policy : null,
|
|
22
24
|
};
|
|
23
25
|
}
|