create-walle 0.10.1 → 0.10.2
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 +4 -0
- package/lib/owner-write-safety.js +135 -0
- package/lib/public-runtime.js +13 -5
- package/lib/release-schema.json +3 -2
- package/lib/runtime-closure-policy.json +6 -4
- package/package.json +1 -1
- package/template/bin/deps-doctor.js +1 -1
- package/template/bin/node-bin.sh +11 -0
- package/template/coding-task-manager/api-prompts.js +10 -22
- package/template/coding-task-manager/bin/claude-hook.js +7 -3
- package/template/coding-task-manager/bin/claude-table-parity.js +307 -0
- package/template/coding-task-manager/bin/conversation-storage-auto-migration-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-generation-evidence.js +9 -2
- package/template/coding-task-manager/bin/conversation-storage-service-entry-lib.js +16 -1
- package/template/coding-task-manager/bin/conversation-storage-walle-owner.js +247 -0
- package/template/coding-task-manager/bin/ctm-machine-pair.js +160 -0
- package/template/coding-task-manager/bin/lead-wait-census.js +1348 -0
- package/template/coding-task-manager/bin/repair-foreign-clone.js +564 -0
- package/template/coding-task-manager/bin/repair-resume-echo-titles.js +248 -0
- package/template/coding-task-manager/bin/write-lock-bench.js +111 -0
- package/template/coding-task-manager/db.js +705 -286
- package/template/coding-task-manager/git-utils.js +44 -0
- package/template/coding-task-manager/lib/adopted-host-redial.js +4 -0
- package/template/coding-task-manager/lib/agent-presets.js +15 -0
- package/template/coding-task-manager/lib/agent-title-apply.js +88 -0
- package/template/coding-task-manager/lib/agent-title-backfill-read.js +92 -0
- package/template/coding-task-manager/lib/api/host-stats.js +98 -0
- package/template/coding-task-manager/lib/api/ingress.js +35 -12
- package/template/coding-task-manager/lib/api/machine-pairing.js +285 -0
- package/template/coding-task-manager/lib/api/machine-pool.js +307 -0
- package/template/coding-task-manager/lib/api/machines.js +461 -0
- package/template/coding-task-manager/lib/api/misc-ops.js +20 -5
- package/template/coding-task-manager/lib/api/providers.js +53 -6
- package/template/coding-task-manager/lib/api/resume-from-store.js +25 -0
- package/template/coding-task-manager/lib/api/sessions.js +160 -8
- package/template/coding-task-manager/lib/api/transcript-history.js +17 -4
- package/template/coding-task-manager/lib/api/worktrees.js +38 -37
- package/template/coding-task-manager/lib/approval-drift.js +16 -1
- package/template/coding-task-manager/lib/approval-logical-frame.js +5 -1
- package/template/coding-task-manager/lib/approval-scope.js +68 -4
- package/template/coding-task-manager/lib/auth-context.js +32 -2
- package/template/coding-task-manager/lib/auth-rate-limit.js +41 -1
- package/template/coding-task-manager/lib/auth-rules.js +186 -45
- package/template/coding-task-manager/lib/broadcast-serialize.js +2 -1
- package/template/coding-task-manager/lib/browser-session-broker.js +9 -1
- package/template/coding-task-manager/lib/browser-use-adapter.js +33 -2
- package/template/coding-task-manager/lib/claude-markdown-ansi.js +27 -85
- package/template/coding-task-manager/lib/claude-session-title.js +6 -30
- package/template/coding-task-manager/lib/claude-table-layout.js +322 -0
- package/template/coding-task-manager/lib/client-diag-handler.js +5 -0
- package/template/coding-task-manager/lib/codex-config-guard.js +33 -3
- package/template/coding-task-manager/lib/codex-harness-qualification.js +12 -0
- package/template/coding-task-manager/lib/codex-launch-health.js +29 -2
- package/template/coding-task-manager/lib/codex-link-preparation.js +9 -8
- package/template/coding-task-manager/lib/codex-paths.js +2 -1
- package/template/coding-task-manager/lib/coding-agent-models.js +21 -30
- package/template/coding-task-manager/lib/coding-session-model-adapters.js +27 -2
- package/template/coding-task-manager/lib/coding-session-model-projection.js +5 -0
- package/template/coding-task-manager/lib/coding-session-model-runtime.js +1 -2
- package/template/coding-task-manager/lib/coding-session-model-state.js +10 -0
- package/template/coding-task-manager/lib/coding-session-model-sync-state.js +0 -1
- package/template/coding-task-manager/lib/conversation-import/cursor-guard-owner.js +10 -0
- package/template/coding-task-manager/lib/create/resolve-launch-params.js +8 -1
- package/template/coding-task-manager/lib/ctm-boot-lifecycle.js +17 -1
- package/template/coding-task-manager/lib/db-domain-tables.js +7 -0
- package/template/coding-task-manager/lib/db-domains.js +21 -2
- package/template/coding-task-manager/lib/db-owner-op-registry.js +7 -0
- package/template/coding-task-manager/lib/db-schema-source-files.js +1 -0
- package/template/coding-task-manager/lib/feature-manifest.js +1 -1
- package/template/coding-task-manager/lib/fs-watcher.js +3 -2
- package/template/coding-task-manager/lib/harness-history-transition.js +3 -3
- package/template/coding-task-manager/lib/headless-inflight-ops.js +203 -0
- package/template/coding-task-manager/lib/headless-missing-reply.js +42 -0
- package/template/coding-task-manager/lib/headless-term-service.js +55 -17
- package/template/coding-task-manager/lib/host-control-dial.js +167 -0
- package/template/coding-task-manager/lib/host-handoff-orchestrator.js +16 -2
- package/template/coding-task-manager/lib/host-handoff.js +51 -13
- package/template/coding-task-manager/lib/host-health-ledger.js +164 -12
- package/template/coding-task-manager/lib/host-self-truth-watchdog.js +4 -0
- package/template/coding-task-manager/lib/host-stats.js +328 -0
- package/template/coding-task-manager/lib/host-threadpool-evacuation.js +160 -0
- package/template/coding-task-manager/lib/host-threadpool-monitor.js +14 -1
- package/template/coding-task-manager/lib/hosted-input-dispatch.js +203 -0
- package/template/coding-task-manager/lib/hosted-sync-worker.js +113 -5
- package/template/coding-task-manager/lib/instance-id-ownership-manifest.js +4 -0
- package/template/coding-task-manager/lib/instance-manifest-runtime.js +3 -0
- package/template/coding-task-manager/lib/instance-manifest.js +13 -1
- package/template/coding-task-manager/lib/instance-sync-status.js +15 -0
- package/template/coding-task-manager/lib/launch-model-override.js +160 -1
- package/template/coding-task-manager/lib/launch-plan-worker.js +59 -2
- package/template/coding-task-manager/lib/lead-model-switch-runtime.js +57 -4
- package/template/coding-task-manager/lib/lead-model-switch.js +3 -2
- package/template/coding-task-manager/lib/lead-model-transition-store.js +61 -3
- package/template/coding-task-manager/lib/legacy-draft-cancellation-recovery.js +111 -0
- package/template/coding-task-manager/lib/login-tripwire.js +1 -0
- package/template/coding-task-manager/lib/machine-pairing.js +238 -0
- package/template/coding-task-manager/lib/machine-pool.js +409 -0
- package/template/coding-task-manager/lib/machine-registry.js +749 -0
- package/template/coding-task-manager/lib/machine-self.js +66 -0
- package/template/coding-task-manager/lib/main-thread-lint-exemptions.json +52 -4
- package/template/coding-task-manager/lib/media-journal-control-reader.js +473 -0
- package/template/coding-task-manager/lib/media-journal.js +84 -27
- package/template/coding-task-manager/lib/media-store-options.js +43 -15
- package/template/coding-task-manager/lib/migrations/v56-host-samples-and-machine-pool.js +76 -0
- package/template/coding-task-manager/lib/mirror-feed-sanitize.js +12 -3
- package/template/coding-task-manager/lib/model-proxy/anthropic-face.js +4 -0
- package/template/coding-task-manager/lib/model-proxy/chat-response-translators.js +3 -0
- package/template/coding-task-manager/lib/model-proxy/handoff.js +494 -0
- package/template/coding-task-manager/lib/model-proxy/lead-worker-picks.js +25 -0
- package/template/coding-task-manager/lib/model-proxy/native-lead-listener.js +61 -7
- package/template/coding-task-manager/lib/model-proxy/proxy-cli.js +200 -0
- package/template/coding-task-manager/lib/model-proxy/proxy-instance-record.js +257 -0
- package/template/coding-task-manager/lib/model-proxy/stream-accounting.js +205 -0
- package/template/coding-task-manager/lib/model-proxy/tokens.js +78 -0
- package/template/coding-task-manager/lib/model-proxy/upstream-outcome.js +9 -0
- package/template/coding-task-manager/lib/native-history-control.js +2 -2
- package/template/coding-task-manager/lib/native-lead-settings-client.js +2 -1
- package/template/coding-task-manager/lib/native-lead-tls.js +18 -4
- package/template/coding-task-manager/lib/oauth-proxy-supervisor.js +628 -64
- package/template/coding-task-manager/lib/owner-action-manifest-data.json +14 -0
- package/template/coding-task-manager/lib/painted-row-recorder.js +9 -1
- package/template/coding-task-manager/lib/prompt-submission-contract.js +21 -1
- package/template/coding-task-manager/lib/provider-login-broker.js +192 -9
- package/template/coding-task-manager/lib/provider-login-capture.js +153 -0
- package/template/coding-task-manager/lib/queue-draft-status-overlay.js +36 -0
- package/template/coding-task-manager/lib/raw-codex-history-window.js +5 -3
- package/template/coding-task-manager/lib/read-pool-client.js +5 -2
- package/template/coding-task-manager/lib/read-pool-op-registry.js +10 -1
- package/template/coding-task-manager/lib/recent-catalog-query.js +26 -0
- package/template/coding-task-manager/lib/recent-session-catalog-response.js +9 -0
- package/template/coding-task-manager/lib/remote-command-context.js +12 -0
- package/template/coding-task-manager/lib/remote-command-runtime.js +13 -1
- package/template/coding-task-manager/lib/remote-machine-catalog.js +1062 -0
- package/template/coding-task-manager/lib/remote-machine-create.js +693 -0
- package/template/coding-task-manager/lib/remote-machine-link.js +939 -0
- package/template/coding-task-manager/lib/remote-machine-proxy.js +520 -0
- package/template/coding-task-manager/lib/remote-session-forward.js +306 -0
- package/template/coding-task-manager/lib/remote-submission-status.js +6 -0
- package/template/coding-task-manager/lib/restart-outcome-truth.js +20 -3
- package/template/coding-task-manager/lib/restart-preflight.js +9 -2
- package/template/coding-task-manager/lib/restore-backoff-gate.js +10 -2
- package/template/coding-task-manager/lib/restore-prepare-retry.js +12 -5
- package/template/coding-task-manager/lib/restore-resume-batch.js +22 -1
- package/template/coding-task-manager/lib/resume-blocked-wire.js +62 -1
- package/template/coding-task-manager/lib/resume-cwd.js +13 -0
- package/template/coding-task-manager/lib/resume-from-store.js +12 -1
- package/template/coding-task-manager/lib/resume-origin-facts.js +38 -1
- package/template/coding-task-manager/lib/resume-preflight.js +21 -16
- package/template/coding-task-manager/lib/review-repo-admission.js +39 -6
- package/template/coding-task-manager/lib/review-repo-registry.js +17 -0
- package/template/coding-task-manager/lib/root-delivery-runtime.js +72 -15
- package/template/coding-task-manager/lib/root-delivery-selection.js +37 -1
- package/template/coding-task-manager/lib/root-prompt-admission.js +33 -2
- package/template/coding-task-manager/lib/root-prompt-flow.js +167 -33
- package/template/coding-task-manager/lib/scrollback-archive-store.js +7 -4
- package/template/coding-task-manager/lib/session-analysis-memory.js +2 -0
- package/template/coding-task-manager/lib/session-create/codex-native-provider-gate.js +218 -0
- package/template/coding-task-manager/lib/session-create/codex-resume-exit-classify.js +52 -0
- package/template/coding-task-manager/lib/session-create/delegate-worker.js +95 -6
- package/template/coding-task-manager/lib/session-create/identity.js +20 -1
- package/template/coding-task-manager/lib/session-create/prepared.js +69 -1
- package/template/coding-task-manager/lib/session-create/provider-launch-context.js +77 -0
- package/template/coding-task-manager/lib/session-create/provider-process.js +34 -37
- package/template/coding-task-manager/lib/session-create/response.js +30 -12
- package/template/coding-task-manager/lib/session-create/transcript.js +13 -4
- package/template/coding-task-manager/lib/session-create/worker-continuation.js +43 -1
- package/template/coding-task-manager/lib/session-create/worker-notices.js +94 -5
- package/template/coding-task-manager/lib/session-create/worker-observability.js +99 -7
- package/template/coding-task-manager/lib/session-create/worker-stop.js +11 -3
- package/template/coding-task-manager/lib/session-create/worker-wait-watcher.js +315 -0
- package/template/coding-task-manager/lib/session-geometry-authority-handler.js +10 -1
- package/template/coding-task-manager/lib/session-host-manager.js +152 -206
- package/template/coding-task-manager/lib/session-jobs.js +17 -9
- package/template/coding-task-manager/lib/session-lifecycle.js +18 -0
- package/template/coding-task-manager/lib/session-model-action-preconditions.js +9 -0
- package/template/coding-task-manager/lib/session-resource-sampler.js +19 -9
- package/template/coding-task-manager/lib/session-standup.js +67 -4
- package/template/coding-task-manager/lib/session-status-ledger.js +42 -3
- package/template/coding-task-manager/lib/session-status-runtime.js +45 -1
- package/template/coding-task-manager/lib/session-title-mirror.js +25 -57
- package/template/coding-task-manager/lib/session-transcript-trash.js +8 -1
- package/template/coding-task-manager/lib/startup-pointer-write.js +57 -0
- package/template/coding-task-manager/lib/state-sync/painted-frame-field.js +11 -0
- package/template/coding-task-manager/lib/storage/coding-session-model-store.js +21 -22
- package/template/coding-task-manager/lib/surviving-owner-bootstrap.js +7 -2
- package/template/coding-task-manager/lib/surviving-owner-recovery.js +2 -1
- package/template/coding-task-manager/lib/terminal-draft-http-status.js +25 -0
- package/template/coding-task-manager/lib/transcript-archiver.js +229 -229
- package/template/coding-task-manager/lib/transcript-frame-cache.js +12 -2
- package/template/coding-task-manager/lib/transcript-guard-job.js +55 -4
- package/template/coding-task-manager/lib/transcript-link.js +77 -0
- package/template/coding-task-manager/lib/transcript-manifest-store.js +8 -4
- package/template/coding-task-manager/lib/transcript-source.js +8 -3
- package/template/coding-task-manager/lib/transcript-store.js +40 -0
- package/template/coding-task-manager/lib/tunnel-lane-governor.js +6 -3
- package/template/coding-task-manager/lib/typing-interaction-trace.js +92 -0
- package/template/coding-task-manager/lib/typing-worker-stages.js +60 -0
- package/template/coding-task-manager/lib/visible-revision-watchdog.js +8 -12
- package/template/coding-task-manager/lib/wake-skip-reasons.js +46 -0
- package/template/coding-task-manager/lib/walle-supervisor.js +98 -14
- package/template/coding-task-manager/lib/worker-failure-classify.js +13 -1
- package/template/coding-task-manager/lib/ws/state-sync.js +19 -2
- package/template/coding-task-manager/lib/ws/terminal-attach.js +32 -1
- package/template/coding-task-manager/lib/ws-router.js +68 -1
- package/template/coding-task-manager/lib/ws-send-admission.js +22 -4
- package/template/coding-task-manager/oauth-proxy.js +99 -55
- package/template/coding-task-manager/package-lock.json +24 -0
- package/template/coding-task-manager/package.json +3 -0
- package/template/coding-task-manager/providers/codex-mcp-extract.js +121 -19
- package/template/coding-task-manager/providers/codex-mcp.js +14 -5
- package/template/coding-task-manager/public/css/app.css +279 -1
- package/template/coding-task-manager/public/css/reviews.css +4 -0
- package/template/coding-task-manager/public/index.html +294 -223
- package/template/coding-task-manager/public/js/app/machines-page.js +1252 -0
- package/template/coding-task-manager/public/js/app/models-tab.js +546 -36
- package/template/coding-task-manager/public/js/app/worktrees-panel.js +7 -5
- package/template/coding-task-manager/public/js/background-work.js +13 -7
- package/template/coding-task-manager/public/js/coding-session-model-presentation.js +44 -4
- package/template/coding-task-manager/public/js/core/session-commands.js +676 -0
- package/template/coding-task-manager/public/js/core/session-selectors.js +5 -1
- package/template/coding-task-manager/public/js/history-app-seam.js +26 -2
- package/template/coding-task-manager/public/js/history-painted-rows.js +17 -2
- package/template/coding-task-manager/public/js/history-reader-park.js +13 -1
- package/template/coding-task-manager/public/js/history-scroller.js +187 -9
- package/template/coding-task-manager/public/js/history-transcript-pages.js +5 -5
- package/template/coding-task-manager/public/js/machine-pool-shared.js +436 -0
- package/template/coding-task-manager/public/js/private-state-scope.js +31 -3
- package/template/coding-task-manager/public/js/prompt-submission-client.js +173 -8
- package/template/coding-task-manager/public/js/prompt-submission-tray.js +281 -0
- package/template/coding-task-manager/public/js/queue-panel-submission-reconcile.js +174 -1
- package/template/coding-task-manager/public/js/reviews.js +7 -3
- package/template/coding-task-manager/public/js/root-draft-lifetime.js +139 -2
- package/template/coding-task-manager/public/js/root-queue-builder-lifetime.js +16 -0
- package/template/coding-task-manager/public/js/row-join.js +4 -2
- package/template/coding-task-manager/public/js/session-model-picker.js +1 -1
- package/template/coding-task-manager/public/js/session-search-utils.js +46 -19
- package/template/coding-task-manager/public/js/state-sync-client.js +4 -0
- package/template/coding-task-manager/public/js/terminal/runtime-02.js +16 -7
- package/template/coding-task-manager/public/js/terminal/runtime-03.js +41 -0
- package/template/coding-task-manager/public/js/terminal/runtime-04.js +41 -4
- package/template/coding-task-manager/public/js/terminal/runtime-12.js +52 -2
- package/template/coding-task-manager/public/js/terminal/runtime-16.js +12 -12
- package/template/coding-task-manager/public/js/terminal/runtime-18.js +14 -0
- package/template/coding-task-manager/public/js/terminal/runtime-19.js +8 -4
- package/template/coding-task-manager/public/js/terminal/runtime-20.js +210 -73
- package/template/coding-task-manager/public/js/terminal/runtime-21.js +19 -6
- package/template/coding-task-manager/public/js/terminal/runtime-22.js +86 -0
- package/template/coding-task-manager/public/js/terminal-history-viewport.js +1 -1
- package/template/coding-task-manager/public/js/terminal-wheel.js +39 -2
- package/template/coding-task-manager/public/js/walle/chat-conversation.js +11 -3
- package/template/coding-task-manager/public/js/walle-session.js +30 -7
- package/template/coding-task-manager/public/m/app.css +226 -8
- package/template/coding-task-manager/public/m/app.js +502 -9
- package/template/coding-task-manager/public/m/index.html +38 -1
- package/template/coding-task-manager/public/m/machines.js +1313 -0
- package/template/coding-task-manager/public/m/pool-failover.js +391 -0
- package/template/coding-task-manager/public/m/private-queue-actions.js +26 -7
- package/template/coding-task-manager/public/m/sw.js +5 -0
- package/template/coding-task-manager/queue-engine.js +13 -0
- package/template/coding-task-manager/server/approvals.js +5 -6
- package/template/coding-task-manager/server/boot.js +136 -17
- package/template/coding-task-manager/server.js +902 -239
- package/template/coding-task-manager/session-integrity.js +7 -9
- package/template/coding-task-manager/workers/db-owner-worker.js +53 -7
- package/template/coding-task-manager/workers/read-pool-worker.js +17 -6
- package/template/coding-task-manager/workers/session-host-pool-process.js +18 -4
- package/template/coding-task-manager/workers/session-host-process.js +14 -3
- package/template/coding-task-manager/workers/transcript-archive-worker.js +1 -1
- package/template/coding-task-manager/workers/worktree-worker.js +34 -0
- package/template/package-lock.json +2 -2
- package/template/package.json +1 -1
- package/template/scripts/conversation-storage-v2-migration.js +78 -11
- package/template/shared/conversation-storage-v2-contract.js +42 -6
- package/template/shared/fixtures/worker-status-payloads.json +392 -0
- package/template/shared/git-remote-key.js +83 -0
- package/template/shared/host-identity.js +98 -2
- package/template/shared/owner-write-safety.js +135 -0
- package/template/shared/public-runtime.js +13 -5
- package/template/shared/release-schema.json +3 -2
- package/template/shared/report-citations.js +14 -0
- package/template/shared/sqlite-write-lock.js +361 -223
- package/template/shared/storage/contract.js +35 -3
- package/template/wall-e/agent.js +21 -0
- package/template/wall-e/api-walle.js +5 -0
- package/template/wall-e/bin/brain-purge-legacy-ctm.js +3 -2
- package/template/wall-e/bin/walle-mcp-stdio.js +12 -6
- package/template/wall-e/brain/helper-rules-schema.js +129 -0
- package/template/wall-e/brain/migrations.js +51 -22
- package/template/wall-e/brain/model-deployment-facts.js +31 -1
- package/template/wall-e/brain/owner-call-whitelist.js +16 -0
- package/template/wall-e/brain/schema-ensures.js +22 -0
- package/template/wall-e/brain.js +1 -1
- package/template/wall-e/coding/journal-dispatcher.js +51 -0
- package/template/wall-e/coding/session-journal.js +28 -40
- package/template/wall-e/coding-orchestrator.js +23 -26
- package/template/wall-e/http/auth.js +18 -1
- package/template/wall-e/http/blog-views-api.js +318 -0
- package/template/wall-e/http/helper-rules-api.js +321 -0
- package/template/wall-e/http/model-proxy-providers.js +3 -1
- package/template/wall-e/http/telemetry-api.js +12 -0
- package/template/wall-e/lib/blog-view-policy.js +88 -0
- package/template/wall-e/lib/blog-view-store.js +169 -0
- package/template/wall-e/lib/client-config-lock.js +2 -1
- package/template/wall-e/lib/coding-journal-writer-child-client.js +67 -18
- package/template/wall-e/lib/error-kinds.js +10 -1
- package/template/wall-e/lib/feature-manifest.js +1 -1
- package/template/wall-e/lib/helper-rules/cell-state.js +123 -0
- package/template/wall-e/lib/helper-rules/evaluate.js +357 -0
- package/template/wall-e/lib/helper-rules/explore-rubric.md +12 -0
- package/template/wall-e/lib/helper-rules/grade.js +277 -0
- package/template/wall-e/lib/helper-rules/label.js +247 -0
- package/template/wall-e/lib/helper-rules/lead-call-hook.js +522 -0
- package/template/wall-e/lib/helper-rules/store.js +667 -0
- package/template/wall-e/lib/mcp-integration.js +5 -6
- package/template/wall-e/lib/runtime-worker-pool.js +1 -0
- package/template/wall-e/lib/scheduler-worker-jobs.js +6 -0
- package/template/wall-e/lib/telemetry-db-schema.js +37 -0
- package/template/wall-e/lib/telemetry-process-client.js +76 -1
- package/template/wall-e/llm/default-fallback.js +4 -0
- package/template/wall-e/llm/model-catalog.js +13 -4
- package/template/wall-e/llm/model-roles.js +6 -0
- package/template/wall-e/llm/portkey-http.js +150 -0
- package/template/wall-e/llm/portkey-sync.js +15 -145
- package/template/wall-e/llm/worker-mcp-routing.js +61 -0
- package/template/wall-e/llm/worker-route.js +43 -1
- package/template/wall-e/loops/brain-custom-writes.js +45 -0
- package/template/wall-e/mcp-protocol-contract.js +41 -1
- package/template/wall-e/mcp-server.js +13 -2
- package/template/wall-e/mcp-worker-schemas.js +20 -2
- package/template/wall-e/memory/ctm-context-client.js +25 -5
- package/template/wall-e/shared/release-schema.json +3 -2
- package/template/wall-e/shared/sqlite-write-lock.js +361 -223
- package/template/wall-e/shared/storage/contract.js +35 -3
- package/template/wall-e/skills/_templates/delegate-worker/VERSION +1 -1
- package/template/wall-e/skills/_templates/delegate-worker/released-sha256.json +6 -0
- package/template/wall-e/skills/_templates/delegate-worker/templates/claude/SKILL.md +7 -2
- package/template/wall-e/skills/_templates/delegate-worker/templates/codex/SKILL.md +7 -2
- package/template/wall-e/tools/local-tools.js +6 -4
- package/template/wall-e/workers/brain-owner-worker.js +9 -0
- package/template/wall-e/workers/coding-journal-writer-child.js +8 -1
- package/template/wall-e/workers/telemetry-worker.js +8 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
// public/js/machine-pool-shared.js — WP-6 (docs/machine-pool-picker-pairing-dashboard-2026-10-24.html
|
|
2
|
+
// §5 D-1/D-2/D-3/D-4/D-9/D-12, P-7, §6.4 client block, §8 WP-6).
|
|
3
|
+
//
|
|
4
|
+
// ONE copy of every DOM-free machine-pool presenter the desktop and the phone both need. It is a
|
|
5
|
+
// classic script (no module system, no bundler) and it is loaded by BOTH pages:
|
|
6
|
+
//
|
|
7
|
+
// desktop public/index.html — before js/core/session-commands.js and js/app/machines-page.js
|
|
8
|
+
// phone public/m/index.html — before /m/app.js
|
|
9
|
+
//
|
|
10
|
+
// Why a shared file and not two copies: the phone is a second renderer of the same machine pool
|
|
11
|
+
// (ruling: phone = desktop parity), so the ORDER (D-1), the SEARCH TEXT (D-2), the GROUPS (D-3),
|
|
12
|
+
// the LOAD LINE (D-12), the sparkline (AC-5b) and the pairing container (§6.3/D-9) must be the same
|
|
13
|
+
// bytes on both. Anything that touches the DOM, the network, a timer or a clock read stays in the
|
|
14
|
+
// surface that owns it; this file is pure and takes `now` from its caller.
|
|
15
|
+
//
|
|
16
|
+
// Nothing here reads localStorage, sessionStorage or a cookie. Nothing here calls Date.now() on a
|
|
17
|
+
// tested path: every presenter that needs a clock is handed one.
|
|
18
|
+
|
|
19
|
+
// D-12: the hub re-reads a box's sample at most once per 60 s, so a sample older than three
|
|
20
|
+
// refreshes is LABELLED, never shown as the box's current number.
|
|
21
|
+
var MACHINE_STATS_STALE_MS = 3 * 60000;
|
|
22
|
+
// D-3 "Recent": a box used within the last 14 days.
|
|
23
|
+
var MACHINE_RECENT_MS = 14 * 24 * 60 * 60 * 1000;
|
|
24
|
+
// D-1: while N = 1 + the visible (non-hidden) registry rows is at most MACHINE_PICKER_CARD_LIMIT the
|
|
25
|
+
// picker keeps the one-click card row; above the limit it keeps This Mac + the top three and adds a
|
|
26
|
+
// fifth "All machines (N)…" card (desktop) or a search sheet (phone).
|
|
27
|
+
var MACHINE_PICKER_CARD_LIMIT = 4;
|
|
28
|
+
|
|
29
|
+
// D-9 verbatim: `ctmpair1:` + base64url(JSON{v,i,n,u,c}).
|
|
30
|
+
var MACHINES_PAGE_PAIR_PREFIX = 'ctmpair1:';
|
|
31
|
+
// RFC 8628 §6.1 (lib/machine-pairing.js CODE_ALPHABET/CODE_LENGTH): the code is 8 characters out of
|
|
32
|
+
// this vowel-free, look-alike-free alphabet, shown as XXXX-XXXX.
|
|
33
|
+
var MACHINES_PAGE_CODE_ALPHABET = 'BCDFGHJKLMNPQRSTVWXZ';
|
|
34
|
+
var MACHINES_PAGE_CODE_LENGTH = 8;
|
|
35
|
+
|
|
36
|
+
// Machine health one-liners. The phone used to carry its own two copies (phoneMachineHealthLabel /
|
|
37
|
+
// phoneMachineLastSeen) — same wording, so they are this pair now.
|
|
38
|
+
function machineHealthLabel(machine) {
|
|
39
|
+
var health = String((machine && machine.health) || 'unknown');
|
|
40
|
+
return health.charAt(0).toUpperCase() + health.slice(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Relative age, owned here so desktop and phone say the same thing (the phone never loads
|
|
44
|
+
// js/core/01-util.js's timeAgo, and its own relativeAgeText is private to m/app.js). Same buckets as
|
|
45
|
+
// timeAgo. `at` is a timestamp or ISO string — 0 means the hub has never seen the box; `now` is
|
|
46
|
+
// injectable for tests.
|
|
47
|
+
function machineAgoText(at, now) {
|
|
48
|
+
var ms = typeof at === 'string' && at && !/^\d+$/.test(at) ? Date.parse(at) : Number(at);
|
|
49
|
+
if (!ms || !Number.isFinite(ms)) return 'never seen';
|
|
50
|
+
// The desktop's own helper when the page has it (same buckets), so the two never drift apart.
|
|
51
|
+
if (now == null && typeof timeAgo === 'function') return timeAgo(ms);
|
|
52
|
+
var seconds = Math.floor(((now == null ? Date.now() : Number(now)) - ms) / 1000);
|
|
53
|
+
if (seconds < 60) return 'just now';
|
|
54
|
+
var minutes = Math.floor(seconds / 60);
|
|
55
|
+
if (minutes < 60) return minutes + 'm ago';
|
|
56
|
+
var hours = Math.floor(minutes / 60);
|
|
57
|
+
if (hours < 24) return hours + 'h ago';
|
|
58
|
+
var days = Math.floor(hours / 24);
|
|
59
|
+
if (days < 30) return days + 'd ago';
|
|
60
|
+
return Math.floor(days / 30) + 'mo ago';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function machineLastSeenText(machine) {
|
|
64
|
+
var at = Number((machine && machine.lastSeenAt) || 0);
|
|
65
|
+
if (!at) return 'never seen';
|
|
66
|
+
return 'last seen ' + machineAgoText(at);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// AC-5a: reachable is selectable; unknown/unhealthy are disabled; unreachable is absent from the
|
|
70
|
+
// card row (HUB AC-5a). `machineIsOffline` is the popover/sheet half of that rule and is the ONE
|
|
71
|
+
// predicate both apps read.
|
|
72
|
+
function machineIsOffline(machine) {
|
|
73
|
+
return String((machine && machine.health) || '').trim() !== 'reachable';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function machineIsFavorite(machine) {
|
|
77
|
+
return !!(machine && (machine.favorite === 1 || machine.favorite === true || Number(machine.favorite) === 1));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// D-4 "hide from picker". Strictly the 1/true spellings: an absent field is visible.
|
|
81
|
+
function machineIsHidden(machine) {
|
|
82
|
+
return !!(machine && (machine.hidden === 1 || machine.hidden === true || Number(machine.hidden) === 1));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// D-1 order: reachable rows first, then favorite DESC, lastUsedAt DESC, displayName ASC. `hidden`
|
|
86
|
+
// rows (D-4 "hide from picker") are dropped here and nowhere else, so no caller can resurrect one.
|
|
87
|
+
function machinePickerOrder(machines) {
|
|
88
|
+
var rows = (Array.isArray(machines) ? machines : []).filter(function (m) { return m && m.instanceId && !machineIsHidden(m); });
|
|
89
|
+
var reachableRank = function (m) { return machineIsOffline(m) ? 1 : 0; };
|
|
90
|
+
var favorite = function (m) { return machineIsFavorite(m) ? 1 : 0; };
|
|
91
|
+
var lastUsed = function (m) { return Number((m && m.lastUsedAt) || 0); };
|
|
92
|
+
var name = function (m) { return String((m && (m.displayName || m.url || m.instanceId)) || ''); };
|
|
93
|
+
return rows.slice().sort(function (a, b) {
|
|
94
|
+
return reachableRank(a) - reachableRank(b)
|
|
95
|
+
|| favorite(b) - favorite(a)
|
|
96
|
+
|| lastUsed(b) - lastUsed(a)
|
|
97
|
+
|| name(a).localeCompare(name(b));
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// D-2 search: the fields people actually remember, lowercased and joined with ' '. Always the same
|
|
102
|
+
// six slots in the same order, so a field the hub did not send can never shift the ones after it.
|
|
103
|
+
function machineSearchText(machine) {
|
|
104
|
+
if (!machine) return '';
|
|
105
|
+
var sample = machine.stats && machine.stats.sample;
|
|
106
|
+
var gpu = sample && sample.gpu ? sample.gpu.name : '';
|
|
107
|
+
return [machine.displayName, machine.hostname, machine.os, machine.arch, machine.url, gpu]
|
|
108
|
+
.map(function (value) { return String(value == null ? '' : value); })
|
|
109
|
+
.join(' ')
|
|
110
|
+
.toLowerCase();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// D-12 load line: 'CPU 12% · 3 running' from the box's newest sample, 'stats stale' once that sample
|
|
114
|
+
// is older than MACHINE_STATS_STALE_MS, '' when the hub holds no sample at all. `now` is passed in
|
|
115
|
+
// by every caller (and by tests), so staleness is never judged against a clock read inside here.
|
|
116
|
+
function machineLoadLine(machine, now) {
|
|
117
|
+
var stats = (machine && machine.stats) || null;
|
|
118
|
+
var sample = stats && stats.sample;
|
|
119
|
+
if (!stats || !sample) return '';
|
|
120
|
+
var at = Number(now == null ? Date.now() : now);
|
|
121
|
+
var checkedAt = Number(stats.checkedAt || 0);
|
|
122
|
+
if (!checkedAt || at - checkedAt > MACHINE_STATS_STALE_MS) return 'stats stale';
|
|
123
|
+
var parts = [];
|
|
124
|
+
var cpu = Number(sample.cpuPct);
|
|
125
|
+
if (sample.cpuPct != null && Number.isFinite(cpu)) parts.push('CPU ' + Math.round(cpu) + '%');
|
|
126
|
+
var running = sample.tasks ? Number(sample.tasks.running) : NaN;
|
|
127
|
+
if (sample.tasks && sample.tasks.running != null && Number.isFinite(running)) parts.push(running + ' running');
|
|
128
|
+
return parts.join(' · ');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// D-3 groups, as bare machine rows (the surface renders them). Favorites and Recent are filtered
|
|
132
|
+
// views of All (a box may legitimately appear in two groups); Offline carries the rows HUB AC-5a
|
|
133
|
+
// keeps out of the card row. `hidden` rows are already gone: machinePickerOrder dropped them.
|
|
134
|
+
function machinePickerGroupRows(machines, now) {
|
|
135
|
+
var at = Number(now == null ? Date.now() : now);
|
|
136
|
+
var order = machinePickerOrder(machines);
|
|
137
|
+
var online = order.filter(function (m) { return !machineIsOffline(m); });
|
|
138
|
+
var offline = order.filter(function (m) { return machineIsOffline(m); });
|
|
139
|
+
return [
|
|
140
|
+
{ id: 'favorites', label: 'Favorites', rows: online.filter(machineIsFavorite) },
|
|
141
|
+
{ id: 'recent', label: 'Recent', rows: online.filter(function (m) {
|
|
142
|
+
var last = Number(m.lastUsedAt || 0);
|
|
143
|
+
return last > 0 && at - last <= MACHINE_RECENT_MS;
|
|
144
|
+
}) },
|
|
145
|
+
{ id: 'all', label: 'All', rows: order },
|
|
146
|
+
{ id: 'offline', label: 'Offline', rows: offline },
|
|
147
|
+
].filter(function (group) { return group.rows.length > 0; });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// P-7 / §6.2 P-4: the public https origin a phone can actually sign in to. `urls` is the dial list
|
|
151
|
+
// (rev 2); `url` is the legacy single address. A plain-http LAN address is not a passkey origin, so
|
|
152
|
+
// only `https:` counts here.
|
|
153
|
+
function machinePoolOrigin(machine) {
|
|
154
|
+
var urls = (machine && Array.isArray(machine.urls) ? machine.urls : []).slice();
|
|
155
|
+
if (machine && machine.url) urls.push(machine.url);
|
|
156
|
+
for (var i = 0; i < urls.length; i += 1) {
|
|
157
|
+
var candidate = String(urls[i] == null ? '' : urls[i]).trim().replace(/\/+$/, '');
|
|
158
|
+
if (/^https:\/\//i.test(candidate)) return candidate;
|
|
159
|
+
}
|
|
160
|
+
return '';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// P-7 "Sign in to <member> too": the origin this device has never reached. `origins` is the parsed
|
|
164
|
+
// ctm.pool.origins dial cache ([{ origin, lastSeenAt }]). '' when the member has no https origin or
|
|
165
|
+
// this device has already been there — i.e. only the unvisited members render the row.
|
|
166
|
+
function machinePoolSignInOrigin(machine, origins) {
|
|
167
|
+
var origin = machinePoolOrigin(machine);
|
|
168
|
+
if (!origin) return '';
|
|
169
|
+
var seen = (Array.isArray(origins) ? origins : []).some(function (row) {
|
|
170
|
+
return row && String(row.origin || '').replace(/\/+$/, '') === origin && Number(row.lastSeenAt || 0) > 0;
|
|
171
|
+
});
|
|
172
|
+
return seen ? '' : origin;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ── AC-5b sparkline ─────────────────────────────────────────────────────────────────────────────
|
|
176
|
+
// ONE <path> per metric. A null sample (a minute the box was off, or the purge gap) CLOSES the run
|
|
177
|
+
// and the next value opens a new one with `M`, so the element count never grows with the data: 1440
|
|
178
|
+
// samples with two gaps is one <path> with three `M` segments.
|
|
179
|
+
function sparklineSvg(values, opts) {
|
|
180
|
+
var options = opts || {};
|
|
181
|
+
var width = Number(options.width || 120) || 120;
|
|
182
|
+
var height = Number(options.height || 28) || 28;
|
|
183
|
+
var raw = Array.isArray(values) ? values : [];
|
|
184
|
+
var nums = raw.map(function (value) {
|
|
185
|
+
if (value == null || value === '') return null;
|
|
186
|
+
var n = Number(value);
|
|
187
|
+
return Number.isFinite(n) ? n : null;
|
|
188
|
+
});
|
|
189
|
+
var present = nums.filter(function (n) { return n != null; });
|
|
190
|
+
var open = '<svg class="machine-spark" width="' + width + '" height="' + height
|
|
191
|
+
+ '" viewBox="0 0 ' + width + ' ' + height + '" aria-hidden="true" focusable="false">';
|
|
192
|
+
if (!present.length) return open + '</svg>';
|
|
193
|
+
var min = Math.min.apply(null, present);
|
|
194
|
+
var max = Math.max.apply(null, present);
|
|
195
|
+
var span = (max - min) || 1;
|
|
196
|
+
var count = nums.length;
|
|
197
|
+
var x = function (index) { return count <= 1 ? 0 : (index / (count - 1)) * width; };
|
|
198
|
+
var y = function (value) { return height - ((value - min) / span) * height; };
|
|
199
|
+
var d = '';
|
|
200
|
+
var run = [];
|
|
201
|
+
var flush = function () {
|
|
202
|
+
if (!run.length) return;
|
|
203
|
+
var segment = run.map(function (point, index) {
|
|
204
|
+
return (index === 0 ? 'M' : 'L') + point[0].toFixed(2) + ' ' + point[1].toFixed(2);
|
|
205
|
+
}).join(' ');
|
|
206
|
+
d += (d ? ' ' : '') + segment;
|
|
207
|
+
run = [];
|
|
208
|
+
};
|
|
209
|
+
for (var i = 0; i < count; i += 1) {
|
|
210
|
+
if (nums[i] == null) { flush(); continue; }
|
|
211
|
+
run.push([x(i), y(nums[i])]);
|
|
212
|
+
}
|
|
213
|
+
flush();
|
|
214
|
+
// A single point has no line: emit a degenerate segment so the path still exists (never a throw).
|
|
215
|
+
return open + '<path d="' + (d || ('M0 ' + (height / 2).toFixed(2))) + '"/></svg>';
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ── D-9 pairing container (the member side, client-only) ────────────────────────────────────────
|
|
219
|
+
// §6.3 verbatim: uppercase, then drop every character outside the alphabet — hyphens and spaces are
|
|
220
|
+
// formatting, not content. Mirrors lib/machine-pairing.js normalizeCode.
|
|
221
|
+
function machinesNormalizeCode(value) {
|
|
222
|
+
var out = '';
|
|
223
|
+
var raw = String(value == null ? '' : value).toUpperCase();
|
|
224
|
+
for (var i = 0; i < raw.length; i += 1) {
|
|
225
|
+
if (MACHINES_PAGE_CODE_ALPHABET.indexOf(raw.charAt(i)) !== -1) out += raw.charAt(i);
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function machinesFormatCode(value) {
|
|
231
|
+
var code = machinesNormalizeCode(value);
|
|
232
|
+
if (code.length !== MACHINES_PAGE_CODE_LENGTH) return code;
|
|
233
|
+
return code.slice(0, 4) + '-' + code.slice(4);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// base64url -> UTF-8. atob() is the browser's decoder; the escape/decodeURIComponent pair is the
|
|
237
|
+
// standard way to recover the UTF-8 bytes it produced (and both exist in a bare vm realm, unlike
|
|
238
|
+
// TextDecoder).
|
|
239
|
+
function machinesBase64UrlDecode(text) {
|
|
240
|
+
var padded = String(text || '').replace(/-/g, '+').replace(/_/g, '/');
|
|
241
|
+
while (padded.length % 4) padded += '=';
|
|
242
|
+
var binary = atob(padded);
|
|
243
|
+
return decodeURIComponent(escape(binary));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// D-9: A hand-edited or truncated string is null, never a throw, so the dialog can render its
|
|
247
|
+
// refusal. One copy: the desktop Add dialog and the phone Add sheet both read this.
|
|
248
|
+
function decodePairingStringClient(value) {
|
|
249
|
+
var raw = String(value == null ? '' : value).trim();
|
|
250
|
+
if (raw.indexOf(MACHINES_PAGE_PAIR_PREFIX) !== 0) return null;
|
|
251
|
+
var parsed = null;
|
|
252
|
+
try {
|
|
253
|
+
parsed = JSON.parse(machinesBase64UrlDecode(raw.slice(MACHINES_PAGE_PAIR_PREFIX.length)));
|
|
254
|
+
} catch (error) {
|
|
255
|
+
return null; // expected: a corrupted container is a client error, not a fault to report
|
|
256
|
+
}
|
|
257
|
+
if (!parsed || typeof parsed !== 'object' || parsed.v !== 1) return null;
|
|
258
|
+
var code = machinesNormalizeCode(parsed.c);
|
|
259
|
+
if (code.length !== MACHINES_PAGE_CODE_LENGTH) return null;
|
|
260
|
+
var urls = (Array.isArray(parsed.u) ? parsed.u : [])
|
|
261
|
+
.map(function (url) { return String(url == null ? '' : url).trim().replace(/\/+$/, ''); })
|
|
262
|
+
.filter(Boolean);
|
|
263
|
+
var instanceId = String(parsed.i || '').trim();
|
|
264
|
+
if (!instanceId && !urls.length) return null;
|
|
265
|
+
return {
|
|
266
|
+
version: 1,
|
|
267
|
+
instanceId: instanceId,
|
|
268
|
+
displayName: String(parsed.n || ''),
|
|
269
|
+
urls: urls,
|
|
270
|
+
code: code,
|
|
271
|
+
codeDisplay: machinesFormatCode(code),
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// What an Add dialog shows while the user pastes (AC-5c): the box's OWN name (`n`) and its first
|
|
276
|
+
// candidate address (`u[0]`) BEFORE Confirm is enabled; a string that does not decode is refused
|
|
277
|
+
// with the same wording the server uses. Shared, so the phone refuses exactly what the desktop does.
|
|
278
|
+
function machinesAddPreview(pairingText, codeText, urlText) {
|
|
279
|
+
var raw = String(pairingText == null ? '' : pairingText).trim();
|
|
280
|
+
if (raw) {
|
|
281
|
+
var parsed = decodePairingStringClient(raw);
|
|
282
|
+
if (!parsed) {
|
|
283
|
+
return { ok: false, mode: 'string', message: 'pairing_string_invalid', name: '', url: '', code: '' };
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
ok: true,
|
|
287
|
+
mode: 'string',
|
|
288
|
+
message: '',
|
|
289
|
+
name: parsed.displayName || parsed.instanceId || '',
|
|
290
|
+
url: parsed.urls[0] || '',
|
|
291
|
+
code: parsed.codeDisplay,
|
|
292
|
+
instanceId: parsed.instanceId,
|
|
293
|
+
pairingString: raw,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
var code = machinesNormalizeCode(codeText);
|
|
297
|
+
var url = String(urlText == null ? '' : urlText).trim().replace(/\/+$/, '');
|
|
298
|
+
if (!code && !url) {
|
|
299
|
+
return { ok: false, mode: 'manual', message: '', name: '', url: '', code: '' };
|
|
300
|
+
}
|
|
301
|
+
if (code.length !== MACHINES_PAGE_CODE_LENGTH) {
|
|
302
|
+
return { ok: false, mode: 'manual', message: 'pairing_code_invalid', name: '', url: url, code: code };
|
|
303
|
+
}
|
|
304
|
+
if (!/^https?:\/\/.+/i.test(url)) {
|
|
305
|
+
return { ok: false, mode: 'manual', message: 'address_required', name: '', url: url, code: code };
|
|
306
|
+
}
|
|
307
|
+
// There is no pre-join name over code + address: the box does not answer its identity until it is
|
|
308
|
+
// dialled with a credential, and there is no server probe route to ask earlier.
|
|
309
|
+
return { ok: false, mode: 'manual', message: '', name: '', url: url, code: code, addressOnly: true };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ── card fact formatters ────────────────────────────────────────────────────────────────────────
|
|
313
|
+
// The Machines page on both apps renders the same facts from the same sample; these are that
|
|
314
|
+
// rendering. They were two copies (machinesCpuSeries/machinesFormatBytes/… in machines-page.js and
|
|
315
|
+
// again in the phone card) — this is the one copy, and both surfaces delegate to it.
|
|
316
|
+
function machineHistoryRows(history) {
|
|
317
|
+
if (Array.isArray(history)) return history;
|
|
318
|
+
if (history && Array.isArray(history.samples)) return history.samples;
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function machineCpuSeries(history) {
|
|
323
|
+
return machineHistoryRows(history).map(function (sample) {
|
|
324
|
+
if (!sample || sample.cpuPct == null) return null;
|
|
325
|
+
var value = Number(sample.cpuPct);
|
|
326
|
+
return Number.isFinite(value) ? value : null;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function machineMemSeries(history) {
|
|
331
|
+
return machineHistoryRows(history).map(function (sample) {
|
|
332
|
+
if (!sample) return null;
|
|
333
|
+
var used = Number(sample.memUsedBytes);
|
|
334
|
+
var total = Number(sample.memTotalBytes);
|
|
335
|
+
if (!Number.isFinite(used) || !Number.isFinite(total) || total <= 0) return null;
|
|
336
|
+
return (used / total) * 100;
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function machineLastValue(series) {
|
|
341
|
+
if (!Array.isArray(series)) return null;
|
|
342
|
+
for (var i = series.length - 1; i >= 0; i -= 1) {
|
|
343
|
+
if (series[i] != null) return series[i];
|
|
344
|
+
}
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function machineFormatBytes(value) {
|
|
349
|
+
var bytes = Number(value);
|
|
350
|
+
if (!Number.isFinite(bytes) || bytes <= 0) return '';
|
|
351
|
+
var units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
352
|
+
var index = 0;
|
|
353
|
+
var scaled = bytes;
|
|
354
|
+
while (scaled >= 1024 && index < units.length - 1) { scaled /= 1024; index += 1; }
|
|
355
|
+
return (scaled >= 10 || index === 0 ? Math.round(scaled) : scaled.toFixed(1)) + ' ' + units[index];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function machineFormatPct(value) {
|
|
359
|
+
// No sample is no number: Number(null) is 0, which would paint a fake "0%".
|
|
360
|
+
if (value == null || value === '') return '';
|
|
361
|
+
var n = Number(value);
|
|
362
|
+
if (!Number.isFinite(n)) return '';
|
|
363
|
+
return Math.round(n) + '%';
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// WP-4: a reachable box whose Claude/Codex CLI is signed out says so on its card. Same labels on both
|
|
367
|
+
// surfaces.
|
|
368
|
+
var MACHINE_AGENT_LABELS = { claude: 'Claude', codex: 'Codex' };
|
|
369
|
+
|
|
370
|
+
function machineAgentText(agents) {
|
|
371
|
+
if (!agents || typeof agents !== 'object') return '';
|
|
372
|
+
var parts = [];
|
|
373
|
+
['claude', 'codex'].forEach(function (key) {
|
|
374
|
+
var state = String(agents[key] || '');
|
|
375
|
+
if (state === 'signed_in') parts.push(MACHINE_AGENT_LABELS[key] + ' signed in');
|
|
376
|
+
else if (state === 'signed_out') parts.push(MACHINE_AGENT_LABELS[key] + ' signed out');
|
|
377
|
+
});
|
|
378
|
+
return parts.join(' · ');
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function machineTaskLine(tasks) {
|
|
382
|
+
if (!tasks || typeof tasks !== 'object') return '';
|
|
383
|
+
var parts = [];
|
|
384
|
+
if (tasks.running != null) parts.push((Number(tasks.running) || 0) + ' running');
|
|
385
|
+
if (tasks.needsYou != null) parts.push((Number(tasks.needsYou) || 0) + ' needs you');
|
|
386
|
+
if (tasks.idle != null) parts.push((Number(tasks.idle) || 0) + ' idle');
|
|
387
|
+
return parts.join(' · ');
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function machineGpuText(gpu) {
|
|
391
|
+
if (!gpu || typeof gpu !== 'object') return '';
|
|
392
|
+
var parts = [String(gpu.name || 'GPU')];
|
|
393
|
+
if (gpu.utilPct != null) parts.push(Math.round(Number(gpu.utilPct)) + '%');
|
|
394
|
+
if (gpu.tempC != null) parts.push(Math.round(Number(gpu.tempC)) + '°C');
|
|
395
|
+
if (gpu.powerW != null) parts.push(Math.round(Number(gpu.powerW)) + 'W');
|
|
396
|
+
return parts.join(' · ');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (typeof module === 'object' && module.exports) {
|
|
400
|
+
module.exports = {
|
|
401
|
+
MACHINE_STATS_STALE_MS: MACHINE_STATS_STALE_MS,
|
|
402
|
+
MACHINE_RECENT_MS: MACHINE_RECENT_MS,
|
|
403
|
+
MACHINE_PICKER_CARD_LIMIT: MACHINE_PICKER_CARD_LIMIT,
|
|
404
|
+
MACHINES_PAGE_PAIR_PREFIX: MACHINES_PAGE_PAIR_PREFIX,
|
|
405
|
+
MACHINES_PAGE_CODE_ALPHABET: MACHINES_PAGE_CODE_ALPHABET,
|
|
406
|
+
MACHINES_PAGE_CODE_LENGTH: MACHINES_PAGE_CODE_LENGTH,
|
|
407
|
+
machineHealthLabel: machineHealthLabel,
|
|
408
|
+
machineAgoText: machineAgoText,
|
|
409
|
+
machineLastSeenText: machineLastSeenText,
|
|
410
|
+
machineIsOffline: machineIsOffline,
|
|
411
|
+
machineIsFavorite: machineIsFavorite,
|
|
412
|
+
machineIsHidden: machineIsHidden,
|
|
413
|
+
machinePickerOrder: machinePickerOrder,
|
|
414
|
+
machineSearchText: machineSearchText,
|
|
415
|
+
machineLoadLine: machineLoadLine,
|
|
416
|
+
machinePickerGroupRows: machinePickerGroupRows,
|
|
417
|
+
machinePoolOrigin: machinePoolOrigin,
|
|
418
|
+
machinePoolSignInOrigin: machinePoolSignInOrigin,
|
|
419
|
+
sparklineSvg: sparklineSvg,
|
|
420
|
+
machinesNormalizeCode: machinesNormalizeCode,
|
|
421
|
+
machinesFormatCode: machinesFormatCode,
|
|
422
|
+
machinesBase64UrlDecode: machinesBase64UrlDecode,
|
|
423
|
+
decodePairingStringClient: decodePairingStringClient,
|
|
424
|
+
machinesAddPreview: machinesAddPreview,
|
|
425
|
+
MACHINE_AGENT_LABELS: MACHINE_AGENT_LABELS,
|
|
426
|
+
machineHistoryRows: machineHistoryRows,
|
|
427
|
+
machineCpuSeries: machineCpuSeries,
|
|
428
|
+
machineMemSeries: machineMemSeries,
|
|
429
|
+
machineLastValue: machineLastValue,
|
|
430
|
+
machineFormatBytes: machineFormatBytes,
|
|
431
|
+
machineFormatPct: machineFormatPct,
|
|
432
|
+
machineAgentText: machineAgentText,
|
|
433
|
+
machineTaskLine: machineTaskLine,
|
|
434
|
+
machineGpuText: machineGpuText,
|
|
435
|
+
};
|
|
436
|
+
}
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
const MAX_ID_LENGTH = 160;
|
|
12
12
|
const MAX_NAME_LENGTH = 256;
|
|
13
13
|
const MAX_ORIGIN_LENGTH = 2048;
|
|
14
|
+
// Every identity read gets a deadline that cancels the request (D-1). The
|
|
15
|
+
// value must exceed the slowest bounded server path on these routes — the ps
|
|
16
|
+
// snapshot cap of 5000 ms (PS_SNAPSHOT_TIMEOUT_MS, lib/walle-supervisor.js:183)
|
|
17
|
+
// — 2 × PS_SNAPSHOT_TIMEOUT_MS, and well under the 60 s test timeout.
|
|
18
|
+
const PRIVATE_SCOPE_READ_TIMEOUT_MS = 10000;
|
|
14
19
|
|
|
15
20
|
function object(value) {
|
|
16
21
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
@@ -98,6 +103,17 @@
|
|
|
98
103
|
const subtle = options.crypto && options.crypto.subtle;
|
|
99
104
|
const storage = options.storage || null;
|
|
100
105
|
const callback = typeof options.onStateChange === 'function' ? options.onStateChange : null;
|
|
106
|
+
// Production passes neither option. Tests inject a short readTimeoutMs, and
|
|
107
|
+
// an AbortSignal-like object with .timeout(ms) when the runtime lacks one.
|
|
108
|
+
const readTimeoutMs = Number.isFinite(options.readTimeoutMs) && options.readTimeoutMs > 0
|
|
109
|
+
? options.readTimeoutMs : PRIVATE_SCOPE_READ_TIMEOUT_MS;
|
|
110
|
+
const abortSignalApi = options.AbortSignal
|
|
111
|
+
|| (typeof globalThis !== 'undefined' ? globalThis.AbortSignal : null);
|
|
112
|
+
function readSignal() {
|
|
113
|
+
// No AbortSignal.timeout in this runtime: send no signal rather than throw.
|
|
114
|
+
if (!abortSignalApi || typeof abortSignalApi.timeout !== 'function') return null;
|
|
115
|
+
return abortSignalApi.timeout(readTimeoutMs);
|
|
116
|
+
}
|
|
101
117
|
let epoch = 0;
|
|
102
118
|
let ready = false;
|
|
103
119
|
let lease = null;
|
|
@@ -163,7 +179,13 @@
|
|
|
163
179
|
if (typeof fetcher !== 'function') throw { code: failureCode };
|
|
164
180
|
let response;
|
|
165
181
|
try {
|
|
166
|
-
|
|
182
|
+
const signal = readSignal();
|
|
183
|
+
response = await fetcher(path, {
|
|
184
|
+
method: 'GET',
|
|
185
|
+
credentials: 'same-origin',
|
|
186
|
+
cache: 'no-store',
|
|
187
|
+
...(signal ? { signal } : {}),
|
|
188
|
+
});
|
|
167
189
|
} catch (error) {
|
|
168
190
|
// An explicit configuration-error discriminator is not a network outage:
|
|
169
191
|
// pass its specific typed code through with NO HTTP status, so it stays
|
|
@@ -186,7 +208,13 @@
|
|
|
186
208
|
let payload;
|
|
187
209
|
try {
|
|
188
210
|
payload = await response.json();
|
|
189
|
-
} catch {
|
|
211
|
+
} catch (error) {
|
|
212
|
+
// The same signal covers the body read, so an aborted body is a
|
|
213
|
+
// transport failure: report it as "no response" (0), exactly like a
|
|
214
|
+
// rejected fetch. Any other body failure stays status-less/non-transport.
|
|
215
|
+
if (error && (error.name === 'TimeoutError' || error.name === 'AbortError')) {
|
|
216
|
+
throw { code: failureCode, status: 0 };
|
|
217
|
+
}
|
|
190
218
|
throw { code: failureCode };
|
|
191
219
|
}
|
|
192
220
|
if (!stillCurrent()) return null;
|
|
@@ -436,5 +464,5 @@
|
|
|
436
464
|
});
|
|
437
465
|
}
|
|
438
466
|
|
|
439
|
-
return { createPrivateStateScope };
|
|
467
|
+
return { createPrivateStateScope, PRIVATE_SCOPE_READ_TIMEOUT_MS };
|
|
440
468
|
});
|