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,398 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// WP-0 (docs/remote-session-hub-bridge-2026-10-30.html §5 R-2/R-7/R-8, §6.1, §6.2, §6.3, §8 WP-0):
|
|
4
|
+
// the HUB side of the box -> hub request lane.
|
|
5
|
+
//
|
|
6
|
+
// Every hub<->box channel before this was hub-initiated: the hub dials each pooled box's /ws and
|
|
7
|
+
// keeps one CONTROL link per machine (lib/remote-machine-link.js `openLink`). This module is the
|
|
8
|
+
// far end of a request/response lane that flows the OTHER way over that SAME socket — a process on
|
|
9
|
+
// the BOX asks the HUB that dialled it. There is no new connection, no inbound port, and no
|
|
10
|
+
// fallback: a request that cannot be answered on the link is a NAMED error (R-7), never a local run.
|
|
11
|
+
//
|
|
12
|
+
// box --hub-bridge-request{v:1,rid,callerSessionId,op,args,deadlineMs}--> hub
|
|
13
|
+
// hub --hub-bridge-response{v:1,rid,ok,result|error}--> box
|
|
14
|
+
//
|
|
15
|
+
// Identity comes from the LINK, not the body (R-2): `link.machineInstanceId` is the id the hub
|
|
16
|
+
// pinned at dial time, and a request naming a session the hub does not mirror from that machine is
|
|
17
|
+
// refused with `caller_session_not_on_machine`. Nothing in the frame is trusted for identity.
|
|
18
|
+
//
|
|
19
|
+
// Bounded (R-8): args <= 256 KiB, result <= 1 MiB (truncated), at most 4 in flight per machine.
|
|
20
|
+
//
|
|
21
|
+
// Everything is injectable for tests; the process singleton is configured once at boot
|
|
22
|
+
// (server.js) with the same identity the instance manifest publishes and the catalog's
|
|
23
|
+
// `getMirrorSessionMachine` ownership resolver.
|
|
24
|
+
|
|
25
|
+
const { boolFlag, registerFlag } = require('./env-flags');
|
|
26
|
+
|
|
27
|
+
const BRIDGE_VERSION = 1;
|
|
28
|
+
const RID_MAX = 80;
|
|
29
|
+
const ARGS_MAX_BYTES = 256 * 1024;
|
|
30
|
+
const RESULT_MAX_BYTES = 1024 * 1024;
|
|
31
|
+
const MAX_IN_FLIGHT = 4;
|
|
32
|
+
// WP-5 (R-2 freshness): the refresh budget used when the frame names no deadline, and the ceiling a
|
|
33
|
+
// frame's deadline can never raise the refresh above (a request is answered well inside its own
|
|
34
|
+
// deadline, so the refresh can only ever be a fraction of it).
|
|
35
|
+
const REFRESH_DEFAULT_BUDGET_MS = 5000;
|
|
36
|
+
const REFRESH_MAX_BUDGET_MS = 15000;
|
|
37
|
+
|
|
38
|
+
// Default ON (design §5 R-8 / §8 "Flag"): `CTM_HUB_BRIDGE=0` turns the lane off on either side and
|
|
39
|
+
// every request answers the named `hub_bridge_disabled`.
|
|
40
|
+
registerFlag('CTM_HUB_BRIDGE', {
|
|
41
|
+
kind: 'bool',
|
|
42
|
+
default: true,
|
|
43
|
+
desc: 'Box->hub request lane over the hub-dialed CONTROL WebSocket (docs/remote-session-hub-bridge-2026-10-30.html §5 R-2/R-8); 0 disables it and answers hub_bridge_disabled',
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// name -> { tier, run(args, callCtx) }. WP-0 registers only `ping`; later WPs add ops through
|
|
47
|
+
// `registerOp` (the exported seam the design names).
|
|
48
|
+
const OPS = new Map();
|
|
49
|
+
// machineInstanceId -> in-flight count. A per-process bound, never persisted (R-8).
|
|
50
|
+
const _inFlight = new Map();
|
|
51
|
+
|
|
52
|
+
let _deps = null;
|
|
53
|
+
|
|
54
|
+
const DEFAULT_DEPS = {
|
|
55
|
+
selfIdentity: () => ({ instanceId: '', displayName: '' }),
|
|
56
|
+
getMirrorSessionMachine: () => null,
|
|
57
|
+
now: () => Date.now(),
|
|
58
|
+
// R-9: (entry) => void. Wired to lib/hub-bridge-access.js's `audit` at boot; absent in the unit
|
|
59
|
+
// tests that drive the dispatcher directly (a missing sink is a no-op, never a crash).
|
|
60
|
+
audit: null,
|
|
61
|
+
// R-4/R-11 (WP-2): ({machineId, callerSessionId, tier, op, machineName, args}) => decision. Wired to
|
|
62
|
+
// lib/hub-bridge-access.js's `decide` at boot. Absent -> a gated op is refused, never run ungated.
|
|
63
|
+
decide: null,
|
|
64
|
+
// WP-5 (§5 R-2 freshness): (machineInstanceId) => Promise. Wired to the catalog's fetchCatalog at
|
|
65
|
+
// boot; the ONE bounded refresh a missed caller-session check is allowed. Absent -> no refresh at
|
|
66
|
+
// all (the pre-WP-5 behaviour: a miss is refused outright).
|
|
67
|
+
refreshMachineCatalog: null,
|
|
68
|
+
setTimeoutFn: (fn, ms) => setTimeout(fn, ms),
|
|
69
|
+
clearTimeoutFn: (timer) => clearTimeout(timer),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function configure(deps = {}) {
|
|
73
|
+
_deps = { ...DEFAULT_DEPS, ...(deps || {}) };
|
|
74
|
+
return _deps;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function _d() {
|
|
78
|
+
return _deps || DEFAULT_DEPS;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Flag read at CALL time so a test can flip CTM_HUB_BRIDGE per-process (never at module load). */
|
|
82
|
+
function isEnabled() {
|
|
83
|
+
return boolFlag('CTM_HUB_BRIDGE', true);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** This hub's own identity ({instanceId, displayName}); '' when identity is not ready yet. */
|
|
87
|
+
function selfIdentity() {
|
|
88
|
+
const d = _d();
|
|
89
|
+
try {
|
|
90
|
+
const identity = typeof d.selfIdentity === 'function' ? d.selfIdentity() : null;
|
|
91
|
+
return {
|
|
92
|
+
instanceId: String((identity && identity.instanceId) || ''),
|
|
93
|
+
displayName: String((identity && identity.displayName) || ''),
|
|
94
|
+
};
|
|
95
|
+
} catch {
|
|
96
|
+
// expected: identity is unready early in boot — the hello is simply not sent (see below).
|
|
97
|
+
return { instanceId: '', displayName: '' };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The `hub-bridge-hello` frame the CONTROL link sends right after its client-info (§6.1), or `null`
|
|
103
|
+
* when this process has no identity to name yet. A hello that names no hub would be worse than no
|
|
104
|
+
* hello: the box would key a socket to '' and could never route a request back to it.
|
|
105
|
+
*/
|
|
106
|
+
function controlHelloFrame() {
|
|
107
|
+
const self = selfIdentity();
|
|
108
|
+
if (!self.instanceId) return null;
|
|
109
|
+
return {
|
|
110
|
+
type: 'hub-bridge-hello',
|
|
111
|
+
v: BRIDGE_VERSION,
|
|
112
|
+
hubInstanceId: self.instanceId,
|
|
113
|
+
hubDisplayName: self.displayName,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Register an op. `def.run(args, callCtx)` is async and its resolved value is the response
|
|
119
|
+
* `result`; a throw carrying a protocol-shaped `error.code` becomes that named code, and any other
|
|
120
|
+
* throw becomes `{ok:false, error:{code:'op_failed'}}` (never a crash).
|
|
121
|
+
*/
|
|
122
|
+
function registerOp(name, def) {
|
|
123
|
+
if (typeof name !== 'string' || !name) throw new TypeError('registerOp: name must be a non-empty string');
|
|
124
|
+
if (!def || typeof def.run !== 'function') throw new TypeError(`registerOp(${name}): def.run must be a function`);
|
|
125
|
+
OPS.set(name, { tier: String(def.tier || 'none'), run: def.run });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function listOps() {
|
|
129
|
+
return [...OPS.keys()].sort();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** The machine that owns `callerSessionId`, or '' — the R-2 ownership resolver (read off the link). */
|
|
133
|
+
function _ownerMachine(callerSessionId) {
|
|
134
|
+
const d = _d();
|
|
135
|
+
if (!callerSessionId || typeof d.getMirrorSessionMachine !== 'function') return '';
|
|
136
|
+
try {
|
|
137
|
+
const mirror = d.getMirrorSessionMachine(callerSessionId);
|
|
138
|
+
if (!mirror) return '';
|
|
139
|
+
// WP-3's resolver returns `machineInstanceId`; accept `instanceId` too so a caller that
|
|
140
|
+
// forwards the raw catalog row is not silently refused.
|
|
141
|
+
return String(mirror.machineInstanceId || mirror.instanceId || '');
|
|
142
|
+
} catch {
|
|
143
|
+
// REPORT via the refusal below: a resolver fault is "cannot prove ownership", which is a refusal.
|
|
144
|
+
return '';
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** R-8: a result over 1 MiB is truncated, never silently dropped. */
|
|
149
|
+
function _capResult(result) {
|
|
150
|
+
const value = result === undefined ? null : result;
|
|
151
|
+
let text;
|
|
152
|
+
try {
|
|
153
|
+
text = JSON.stringify(value);
|
|
154
|
+
} catch {
|
|
155
|
+
// A result that is not JSON-serialisable can never cross the lane: report it as a truncation
|
|
156
|
+
// rather than throwing inside the reply.
|
|
157
|
+
return { ok: true, truncated: true, result: { truncated: true, preview: '' } };
|
|
158
|
+
}
|
|
159
|
+
if (Buffer.byteLength(text, 'utf8') <= RESULT_MAX_BYTES) return { ok: true, result: value };
|
|
160
|
+
const preview = Buffer.from(text, 'utf8').subarray(0, RESULT_MAX_BYTES).toString('utf8');
|
|
161
|
+
return { ok: true, truncated: true, result: { truncated: true, preview } };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _audit(entry) {
|
|
165
|
+
const d = _d();
|
|
166
|
+
if (typeof d.audit !== 'function') return;
|
|
167
|
+
try {
|
|
168
|
+
d.audit(entry);
|
|
169
|
+
} catch {
|
|
170
|
+
// expected: the audit sink is best-effort (R-9) — a sink fault must never fail a reply.
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* WP-2 (§5 R-4/R-11): the access decision for a gated op. `deps.decide` is lib/hub-bridge-access.js's
|
|
176
|
+
* `decide` in production; a missing dep FAILS CLOSED (`hub_bridge_denied`) rather than running a
|
|
177
|
+
* gated op ungated — an unwired bridge must never be an ambient grant.
|
|
178
|
+
*/
|
|
179
|
+
function _decide(request) {
|
|
180
|
+
const d = _d();
|
|
181
|
+
if (typeof d.decide !== 'function') return { allow: false, code: 'hub_bridge_denied' };
|
|
182
|
+
try {
|
|
183
|
+
const decision = d.decide(request);
|
|
184
|
+
if (decision && typeof decision === 'object') return decision;
|
|
185
|
+
} catch {
|
|
186
|
+
// REPORT via the refusal below: a fault inside the access decider is "cannot prove a grant".
|
|
187
|
+
return { allow: false, code: 'hub_bridge_denied' };
|
|
188
|
+
}
|
|
189
|
+
return { allow: false, code: 'hub_bridge_denied' };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function _decrement(machineInstanceId) {
|
|
193
|
+
const left = Math.max(0, (Number(_inFlight.get(machineInstanceId)) || 1) - 1);
|
|
194
|
+
if (left) _inFlight.set(machineInstanceId, left);
|
|
195
|
+
else _inFlight.delete(machineInstanceId);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* WP-5 (§5 R-2 freshness): ONE catalog refresh for the machine behind this request, bounded by the
|
|
200
|
+
* request's own deadline. A caller session created moments ago may simply be newer than this hub's
|
|
201
|
+
* copy of that machine's session list, so a miss is worth one refresh — never a loop, and never
|
|
202
|
+
* unbounded: the refresh races a timer, the timer is cleared either way, and a fault reads as "no
|
|
203
|
+
* refresh happened" (the caller is then refused exactly as before).
|
|
204
|
+
*
|
|
205
|
+
* @returns {Promise<boolean>} true when the refresh finished inside its budget (its own result is
|
|
206
|
+
* irrelevant — the caller re-checks ownership, which is the only authority).
|
|
207
|
+
*/
|
|
208
|
+
async function _refreshCatalogOnce(machineInstanceId, deadlineMs) {
|
|
209
|
+
const d = _d();
|
|
210
|
+
if (!machineInstanceId || typeof d.refreshMachineCatalog !== 'function') return false;
|
|
211
|
+
const requested = Number(deadlineMs);
|
|
212
|
+
const budget = Math.max(
|
|
213
|
+
1,
|
|
214
|
+
Math.min(Number.isFinite(requested) && requested > 0 ? requested : REFRESH_DEFAULT_BUDGET_MS, REFRESH_MAX_BUDGET_MS),
|
|
215
|
+
);
|
|
216
|
+
let timer = null;
|
|
217
|
+
const expired = Symbol('refresh_expired');
|
|
218
|
+
const timeout = new Promise((resolve) => {
|
|
219
|
+
timer = d.setTimeoutFn(() => resolve(expired), budget);
|
|
220
|
+
if (timer && typeof timer.unref === 'function') timer.unref();
|
|
221
|
+
});
|
|
222
|
+
try {
|
|
223
|
+
const outcome = await Promise.race([
|
|
224
|
+
Promise.resolve().then(() => d.refreshMachineCatalog(machineInstanceId)),
|
|
225
|
+
timeout,
|
|
226
|
+
]);
|
|
227
|
+
return outcome !== expired;
|
|
228
|
+
} catch {
|
|
229
|
+
// REPORT via the caller's refusal: a refresh fault is "cannot prove ownership", which is a refusal.
|
|
230
|
+
return false;
|
|
231
|
+
} finally {
|
|
232
|
+
if (timer) {
|
|
233
|
+
try {
|
|
234
|
+
d.clearTimeoutFn(timer);
|
|
235
|
+
} catch {
|
|
236
|
+
// expected: the injected timer already fired.
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Handle one `hub-bridge-request` off `link`, writing EXACTLY ONE `hub-bridge-response` through
|
|
244
|
+
* `send` (wired to the link's upstream send). Never throws and never rejects.
|
|
245
|
+
*
|
|
246
|
+
* @param {object} link the hub's CONTROL link (its `machineInstanceId` is the pinned identity)
|
|
247
|
+
* @param {object} frame the box's request frame
|
|
248
|
+
* @param {(frame: object) => any} send the upstream send for that link
|
|
249
|
+
* @returns {Promise<object|null>} the frame that was sent (null when there is nothing to send to)
|
|
250
|
+
*/
|
|
251
|
+
async function handleRequest(link, frame, send) {
|
|
252
|
+
if (typeof send !== 'function') return null;
|
|
253
|
+
const rid = frame && typeof frame.rid === 'string' ? frame.rid : '';
|
|
254
|
+
const reply = (payload) => {
|
|
255
|
+
const body = { type: 'hub-bridge-response', v: BRIDGE_VERSION, rid, ...payload };
|
|
256
|
+
try {
|
|
257
|
+
send(body);
|
|
258
|
+
} catch {
|
|
259
|
+
// expected: the CONTROL link died mid-reply; the box's own deadline owns that case (R-7).
|
|
260
|
+
}
|
|
261
|
+
return body;
|
|
262
|
+
};
|
|
263
|
+
const fail = (code, message, extra) => reply({
|
|
264
|
+
ok: false,
|
|
265
|
+
error: { code, message: String(message == null ? code : message), ...(extra || {}) },
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
if (!isEnabled()) return fail('hub_bridge_disabled', 'CTM_HUB_BRIDGE=0 on the hub');
|
|
269
|
+
if (!frame || typeof frame !== 'object' || frame.v !== BRIDGE_VERSION) {
|
|
270
|
+
return fail('bad_request', `unsupported bridge version: ${frame && frame.v}`);
|
|
271
|
+
}
|
|
272
|
+
if (!rid || rid.length > RID_MAX) {
|
|
273
|
+
return fail('bad_request', `rid must be a non-empty string of at most ${RID_MAX} characters`);
|
|
274
|
+
}
|
|
275
|
+
const op = typeof frame.op === 'string' ? frame.op : '';
|
|
276
|
+
const def = OPS.get(op);
|
|
277
|
+
if (!def) return fail('op_unknown', `unknown bridge op: ${op}`);
|
|
278
|
+
let argsText;
|
|
279
|
+
try {
|
|
280
|
+
argsText = JSON.stringify(frame.args === undefined ? null : frame.args);
|
|
281
|
+
} catch {
|
|
282
|
+
return fail('bad_request', 'args is not JSON-serialisable');
|
|
283
|
+
}
|
|
284
|
+
if (Buffer.byteLength(argsText, 'utf8') > ARGS_MAX_BYTES) {
|
|
285
|
+
return fail('args_too_large', `args exceeds ${ARGS_MAX_BYTES} bytes`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const machineInstanceId = String((link && link.machineInstanceId) || '');
|
|
289
|
+
const callerSessionId = typeof frame.callerSessionId === 'string' ? frame.callerSessionId : '';
|
|
290
|
+
// R-2: identity comes from the LINK, never the body. A session this hub does not mirror from
|
|
291
|
+
// THIS machine is refused — the caller can act only for its own sessions.
|
|
292
|
+
let owner = callerSessionId && machineInstanceId ? _ownerMachine(callerSessionId) : '';
|
|
293
|
+
if (owner !== machineInstanceId && machineInstanceId && callerSessionId) {
|
|
294
|
+
// WP-5 (§5 R-2 freshness): the caller session may just be newer than this hub's copy of that
|
|
295
|
+
// machine's session list. ONE bounded refresh of THAT machine, then re-check. No loop: a second
|
|
296
|
+
// miss is the refusal below, and the refresh never widens the deadline the caller set.
|
|
297
|
+
await _refreshCatalogOnce(machineInstanceId, frame.deadlineMs);
|
|
298
|
+
owner = callerSessionId ? _ownerMachine(callerSessionId) : '';
|
|
299
|
+
}
|
|
300
|
+
if (!callerSessionId || !machineInstanceId || owner !== machineInstanceId) {
|
|
301
|
+
return fail('caller_session_not_on_machine', `session ${callerSessionId || '(none)'} is not mirrored from machine ${machineInstanceId || '(unknown)'}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if ((Number(_inFlight.get(machineInstanceId)) || 0) >= MAX_IN_FLIGHT) {
|
|
305
|
+
return fail('hub_busy', `${MAX_IN_FLIGHT} requests already in flight for machine ${machineInstanceId}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// WP-2 (§5 R-4/R-5/R-11): a gated op (tier !== 'none') needs an access decision BEFORE it runs.
|
|
309
|
+
// A refusal is a NAMED, non-executed outcome — no audit line, and `tier`/`pendingId` ride the
|
|
310
|
+
// error so the box's tool can tell the user exactly what to approve.
|
|
311
|
+
let via = 'none';
|
|
312
|
+
if (def.tier !== 'none') {
|
|
313
|
+
const decision = _decide({
|
|
314
|
+
machineId: machineInstanceId,
|
|
315
|
+
machineName: String((link && link.machineName) || ''),
|
|
316
|
+
callerSessionId,
|
|
317
|
+
tier: def.tier,
|
|
318
|
+
op,
|
|
319
|
+
args: frame.args === undefined ? {} : frame.args,
|
|
320
|
+
});
|
|
321
|
+
if (decision.allow !== true) {
|
|
322
|
+
const code = typeof decision.code === 'string' && decision.code ? decision.code : 'hub_grant_required';
|
|
323
|
+
const extra = { tier: def.tier };
|
|
324
|
+
if (code === 'hub_grant_required') extra.pendingId = String(decision.pendingId || '');
|
|
325
|
+
return fail(code, `${def.tier} is not granted for session ${callerSessionId} on ${String((link && link.machineName) || machineInstanceId)}`, extra);
|
|
326
|
+
}
|
|
327
|
+
via = typeof decision.via === 'string' && decision.via ? decision.via : 'none';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const startedAt = _d().now();
|
|
331
|
+
_inFlight.set(machineInstanceId, (Number(_inFlight.get(machineInstanceId)) || 0) + 1);
|
|
332
|
+
let outcome;
|
|
333
|
+
try {
|
|
334
|
+
const result = await def.run(frame.args === undefined ? {} : frame.args, {
|
|
335
|
+
link,
|
|
336
|
+
machineInstanceId,
|
|
337
|
+
callerSessionId,
|
|
338
|
+
op,
|
|
339
|
+
tier: def.tier,
|
|
340
|
+
now: startedAt,
|
|
341
|
+
hubInstanceId: selfIdentity().instanceId,
|
|
342
|
+
});
|
|
343
|
+
outcome = { ok: true, result };
|
|
344
|
+
} catch (error) {
|
|
345
|
+
// §6.3: an op refuses with a NAMED code by throwing `Object.assign(new Error(msg), {code})`
|
|
346
|
+
// (lib/hub-bridge-ops.js). A throw with no usable code stays `op_failed` — the lane never
|
|
347
|
+
// invents a code, and never leaks a non-protocol string into the frame.
|
|
348
|
+
const raw = error && typeof error.code === 'string' ? error.code : '';
|
|
349
|
+
const code = /^[a-z][a-z0-9_]{0,39}$/.test(raw) ? raw : 'op_failed';
|
|
350
|
+
outcome = { ok: false, error: { code, message: (error && error.message) || String(error) } };
|
|
351
|
+
} finally {
|
|
352
|
+
_decrement(machineInstanceId);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// R-9: every EXECUTED op is audited, tier-'none' ones included. The sink digests `args`; the raw
|
|
356
|
+
// args never leave this process.
|
|
357
|
+
_audit({
|
|
358
|
+
at: startedAt,
|
|
359
|
+
machineId: machineInstanceId,
|
|
360
|
+
callerSessionId,
|
|
361
|
+
op,
|
|
362
|
+
tier: def.tier,
|
|
363
|
+
via,
|
|
364
|
+
args: frame.args === undefined ? {} : frame.args,
|
|
365
|
+
ok: outcome.ok,
|
|
366
|
+
code: outcome.ok ? '' : outcome.error.code,
|
|
367
|
+
ms: Math.max(0, _d().now() - startedAt),
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (!outcome.ok) return reply({ ok: false, error: outcome.error });
|
|
371
|
+
return reply(_capResult(outcome.result));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// WP-0 (§8): the ONLY op this package ships. Later WPs register session.read / fs.* / exec / mcp.*.
|
|
375
|
+
registerOp('ping', {
|
|
376
|
+
tier: 'none',
|
|
377
|
+
run: async (args, callCtx) => ({ hubInstanceId: callCtx.hubInstanceId, at: callCtx.now }),
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
function _resetForTests() {
|
|
381
|
+
_deps = null;
|
|
382
|
+
_inFlight.clear();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
module.exports = {
|
|
386
|
+
BRIDGE_VERSION,
|
|
387
|
+
MAX_IN_FLIGHT,
|
|
388
|
+
ARGS_MAX_BYTES,
|
|
389
|
+
RESULT_MAX_BYTES,
|
|
390
|
+
configure,
|
|
391
|
+
isEnabled,
|
|
392
|
+
selfIdentity,
|
|
393
|
+
controlHelloFrame,
|
|
394
|
+
registerOp,
|
|
395
|
+
listOps,
|
|
396
|
+
handleRequest,
|
|
397
|
+
_resetForTests,
|
|
398
|
+
};
|