@phnx-labs/agents-cli 1.22.112 → 1.22.114
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/CHANGELOG.md +37 -0
- package/README.md +10 -11
- package/dist/cli/command-registry.d.ts +0 -60
- package/dist/cli/command-registry.js +59 -61
- package/dist/commands/apply.d.ts +0 -4
- package/dist/commands/apply.js +3 -3
- package/dist/commands/browser-picker.d.ts +3 -6
- package/dist/commands/browser-picker.js +2 -2
- package/dist/commands/browser-sessions-picker.d.ts +2 -1
- package/dist/commands/computer-sessions-picker.d.ts +2 -1
- package/dist/commands/computer.d.ts +14 -19
- package/dist/commands/computer.js +65 -10
- package/dist/commands/config.js +46 -2
- package/dist/commands/daemon.d.ts +0 -23
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/detach-core.d.ts +2 -1
- package/dist/commands/detach.d.ts +0 -3
- package/dist/commands/detach.js +3 -3
- package/dist/commands/feed.d.ts +3 -3
- package/dist/commands/feed.js +1 -1
- package/dist/commands/focus.d.ts +4 -4
- package/dist/commands/harness-hooks.d.ts +0 -7
- package/dist/commands/harness-hooks.js +1 -1
- package/dist/commands/harness-wizard.d.ts +2 -2
- package/dist/commands/harness.d.ts +3 -8
- package/dist/commands/harness.js +1 -1
- package/dist/commands/inspect.d.ts +2 -3
- package/dist/commands/inspect.js +1 -1
- package/dist/commands/message.d.ts +1 -1
- package/dist/commands/message.js +3 -3
- package/dist/commands/projects.d.ts +2 -18
- package/dist/commands/projects.js +89 -3
- package/dist/commands/resource-view.d.ts +3 -2
- package/dist/commands/resume.d.ts +0 -1
- package/dist/commands/resume.js +1 -1
- package/dist/commands/routines.d.ts +1 -3
- package/dist/commands/routines.js +1 -1
- package/dist/commands/run-account-picker.d.ts +2 -1
- package/dist/commands/run-broadcast.d.ts +2 -1
- package/dist/commands/run-device-picker.d.ts +2 -1
- package/dist/commands/secrets-passthrough.d.ts +14 -0
- package/dist/commands/secrets-passthrough.js +21 -2
- package/dist/commands/sessions-backfill.d.ts +2 -35
- package/dist/commands/sessions-backfill.js +1 -1
- package/dist/commands/sessions-bookmark.d.ts +0 -10
- package/dist/commands/sessions-bookmark.js +1 -1
- package/dist/commands/sessions-inject.d.ts +2 -3
- package/dist/commands/sessions-inject.js +8 -17
- package/dist/commands/sessions-picker-factory.d.ts +4 -14
- package/dist/commands/sessions-picker-factory.js +2 -2
- package/dist/commands/sessions-picker.d.ts +3 -9
- package/dist/commands/sessions-picker.js +2 -2
- package/dist/commands/sessions-resume.d.ts +2 -4
- package/dist/commands/sessions-resume.js +0 -5
- package/dist/commands/sessions-stats.d.ts +2 -1
- package/dist/commands/sessions-stop.d.ts +0 -3
- package/dist/commands/sessions-stop.js +1 -1
- package/dist/commands/sessions-tail.d.ts +2 -1
- package/dist/commands/sessions-trace.d.ts +4 -6
- package/dist/commands/sessions-trace.js +1 -1
- package/dist/commands/sessions.d.ts +14 -104
- package/dist/commands/sessions.js +22 -10
- package/dist/commands/setup-mine.d.ts +0 -6
- package/dist/commands/setup-mine.js +1 -1
- package/dist/commands/setup.d.ts +3 -4
- package/dist/commands/setup.js +1 -1
- package/dist/commands/share.d.ts +8 -8
- package/dist/commands/teams-picker.d.ts +2 -5
- package/dist/commands/teams-picker.js +2 -2
- package/dist/commands/teams.d.ts +1 -7
- package/dist/commands/teams.js +1 -1
- package/dist/commands/tmux.d.ts +1 -1
- package/dist/commands/tmux.js +1 -1
- package/dist/commands/upgrade.d.ts +2 -1
- package/dist/commands/utils.d.ts +1 -1
- package/dist/commands/utils.js +1 -1
- package/dist/lib/account-capabilities.d.ts +2 -1
- package/dist/lib/account-catalog.d.ts +4 -13
- package/dist/lib/account-catalog.js +1 -1
- package/dist/lib/account-registry.d.ts +3 -4
- package/dist/lib/account-registry.js +1 -1
- package/dist/lib/accounting/account-launch.d.ts +4 -3
- package/dist/lib/accounting/account-pool.d.ts +2 -1
- package/dist/lib/accounting/rotate.d.ts +3 -9
- package/dist/lib/accounting/rotate.js +2 -14
- package/dist/lib/accounting/usage-sync.d.ts +5 -4
- package/dist/lib/accounting/usage.d.ts +7 -31
- package/dist/lib/accounting/usage.js +4 -4
- package/dist/lib/accounts/migrate.d.ts +8 -8
- package/dist/lib/accounts/migrate.js +1 -1
- package/dist/lib/acp/client.d.ts +3 -2
- package/dist/lib/acp/harnesses.d.ts +2 -2
- package/dist/lib/acp/harnesses.js +1 -1
- package/dist/lib/acp/run.d.ts +2 -1
- package/dist/lib/actor.d.ts +3 -2
- package/dist/lib/add-dir.d.ts +2 -17
- package/dist/lib/add-dir.js +2 -6
- package/dist/lib/address.d.ts +56 -0
- package/dist/lib/address.js +143 -0
- package/dist/lib/agent-spec/agents.d.ts +12 -28
- package/dist/lib/agent-spec/agents.js +2 -6
- package/dist/lib/agent-spec/primitives.d.ts +0 -7
- package/dist/lib/agent-spec/primitives.js +0 -6
- package/dist/lib/agent-spec/types.d.ts +2 -1
- package/dist/lib/analytics/dashboard.d.ts +1 -5
- package/dist/lib/analytics/dashboard.js +0 -2
- package/dist/lib/analytics/mix-commands.d.ts +0 -7
- package/dist/lib/analytics/mix-commands.js +3 -3
- package/dist/lib/analytics/recipes.d.ts +0 -12
- package/dist/lib/analytics/recipes.js +7 -31
- package/dist/lib/analytics/usage-db.d.ts +5 -32
- package/dist/lib/analytics/usage-db.js +1 -70
- package/dist/lib/answer-router.d.ts +7 -6
- package/dist/lib/answer-router.js +5 -11
- package/dist/lib/artifact-actions.d.ts +0 -4
- package/dist/lib/ask-classifier.d.ts +3 -4
- package/dist/lib/ask-classifier.js +0 -7
- package/dist/lib/auth-health.d.ts +3 -46
- package/dist/lib/auth-health.js +3 -3
- package/dist/lib/auth-mint.d.ts +6 -6
- package/dist/lib/auth-mint.js +5 -5
- package/dist/lib/bench/runner.d.ts +2 -2
- package/dist/lib/bench/runner.js +1 -1
- package/dist/lib/bench/storage.d.ts +0 -1
- package/dist/lib/bench/storage.js +1 -1
- package/dist/lib/boot-profile.d.ts +0 -2
- package/dist/lib/boot-profile.js +0 -4
- package/dist/lib/brand.d.ts +0 -6
- package/dist/lib/brand.js +1 -1
- package/dist/lib/browser/arc-discovery.d.ts +4 -12
- package/dist/lib/browser/arc-discovery.js +1 -1
- package/dist/lib/browser/cdp.d.ts +1 -1
- package/dist/lib/browser/chrome.d.ts +2 -2
- package/dist/lib/browser/chrome.js +0 -4
- package/dist/lib/browser/chromium-discovery.d.ts +3 -2
- package/dist/lib/browser/drivers/arc.d.ts +3 -20
- package/dist/lib/browser/drivers/arc.js +2 -7
- package/dist/lib/browser/drivers/firefox.d.ts +2 -6
- package/dist/lib/browser/drivers/firefox.js +1 -1
- package/dist/lib/browser/drivers/local.d.ts +2 -1
- package/dist/lib/browser/drivers/ssh.d.ts +2 -3
- package/dist/lib/browser/drivers/ssh.js +0 -7
- package/dist/lib/browser/firefox-discovery.d.ts +4 -3
- package/dist/lib/browser/har.d.ts +8 -7
- package/dist/lib/browser/hygiene.d.ts +2 -3
- package/dist/lib/browser/hygiene.js +1 -1
- package/dist/lib/browser/ipc.d.ts +4 -3
- package/dist/lib/browser/ipc.js +1 -1
- package/dist/lib/browser/login-detection.d.ts +1 -8
- package/dist/lib/browser/registry.d.ts +2 -1
- package/dist/lib/browser/remote-control.d.ts +0 -7
- package/dist/lib/browser/remote-control.js +2 -2
- package/dist/lib/browser/resolve-target.d.ts +2 -6
- package/dist/lib/browser/resolve-target.js +3 -3
- package/dist/lib/browser/runtime-state.d.ts +4 -4
- package/dist/lib/browser/service.d.ts +4 -4
- package/dist/lib/browser/sessions-list.d.ts +0 -10
- package/dist/lib/browser/sessions-list.js +3 -3
- package/dist/lib/browser/stream.d.ts +2 -1
- package/dist/lib/browser/task-index.d.ts +4 -4
- package/dist/lib/browser/task-index.js +1 -1
- package/dist/lib/browser/types.d.ts +0 -20
- package/dist/lib/browser/types.js +1 -34
- package/dist/lib/browser/upload.d.ts +0 -27
- package/dist/lib/budget/ledger.d.ts +0 -2
- package/dist/lib/budget/ledger.js +1 -1
- package/dist/lib/budget/live-cloud.d.ts +2 -1
- package/dist/lib/budget/preflight.d.ts +3 -5
- package/dist/lib/budget/preflight.js +1 -1
- package/dist/lib/catchup.d.ts +2 -1
- package/dist/lib/channels/owner-forward.d.ts +5 -4
- package/dist/lib/channels/owner-sink.js +2 -2
- package/dist/lib/channels/providers/desktop.js +1 -1
- package/dist/lib/channels/providers/rush.d.ts +2 -1
- package/dist/lib/channels/registry.d.ts +1 -1
- package/dist/lib/channels/registry.js +1 -1
- package/dist/lib/channels/resolve.d.ts +3 -2
- package/dist/lib/channels/send.d.ts +5 -4
- package/dist/lib/cli-resources.d.ts +3 -9
- package/dist/lib/cli-resources.js +1 -1
- package/dist/lib/cloud/cursor.d.ts +1 -2
- package/dist/lib/cloud/cursor.js +1 -1
- package/dist/lib/cloud/dispatch.d.ts +2 -1
- package/dist/lib/cloud/factory.d.ts +0 -2
- package/dist/lib/cloud/factory.js +1 -1
- package/dist/lib/cloud/rush.d.ts +3 -11
- package/dist/lib/cloud/rush.js +1 -1
- package/dist/lib/cloud/session-index.d.ts +2 -1
- package/dist/lib/cloud/types.d.ts +2 -1
- package/dist/lib/codex-policy.d.ts +2 -1
- package/dist/lib/commands.d.ts +7 -7
- package/dist/lib/commands.js +1 -1
- package/dist/lib/comms-render.d.ts +1 -1
- package/dist/lib/computer/context.d.ts +11 -3
- package/dist/lib/computer/context.js +2 -2
- package/dist/lib/computer/policy.d.ts +0 -12
- package/dist/lib/computer/policy.js +1 -1
- package/dist/lib/computer-client.d.ts +3 -3
- package/dist/lib/computer-client.js +0 -1
- package/dist/lib/concurrency.d.ts +2 -1
- package/dist/lib/config-keys.d.ts +16 -3
- package/dist/lib/config-keys.js +47 -2
- package/dist/lib/convert.d.ts +0 -12
- package/dist/lib/convert.js +1 -12
- package/dist/lib/crabbox/cli.d.ts +6 -24
- package/dist/lib/crabbox/cli.js +2 -28
- package/dist/lib/crabbox/lease.d.ts +5 -6
- package/dist/lib/crabbox/lease.js +1 -1
- package/dist/lib/crabbox/progress.d.ts +2 -1
- package/dist/lib/crabbox/setup-copy.d.ts +2 -3
- package/dist/lib/crabbox/setup-copy.js +1 -1
- package/dist/lib/daemon/account-state-daemon-service.d.ts +1 -1
- package/dist/lib/daemon/attention-notify-service.d.ts +2 -1
- package/dist/lib/daemon/catchup-service.d.ts +2 -1
- package/dist/lib/daemon/daemon.d.ts +4 -12
- package/dist/lib/daemon/daemon.js +42 -23
- package/dist/lib/daemon/harness-update-service.d.ts +2 -19
- package/dist/lib/daemon/harness-update-service.js +3 -3
- package/dist/lib/daemon/runner.d.ts +3 -3
- package/dist/lib/daemon/self-update-service.d.ts +1 -16
- package/dist/lib/daemon/self-update-service.js +6 -6
- package/dist/lib/daemon/state-dir-check-service.d.ts +2 -1
- package/dist/lib/daemon/supervisor.d.ts +3 -2
- package/dist/lib/daemon/testdata/process-view-daemon.d.ts +1 -0
- package/dist/lib/daemon/testdata/process-view-daemon.js +14 -0
- package/dist/lib/daemon/testdata/process-view-start.d.ts +1 -0
- package/dist/lib/daemon/testdata/process-view-start.js +43 -0
- package/dist/lib/daemon-services.d.ts +2 -1
- package/dist/lib/daemon-webhooks.d.ts +1 -1
- package/dist/lib/deeplink/register.d.ts +3 -13
- package/dist/lib/deeplink/register.js +3 -3
- package/dist/lib/deeplink/url.d.ts +3 -2
- package/dist/lib/device-config.d.ts +4 -15
- package/dist/lib/device-config.js +164 -8
- package/dist/lib/devices/connect.d.ts +2 -1
- package/dist/lib/devices/discovery-policy.d.ts +3 -2
- package/dist/lib/devices/doctor-findings.js +1 -1
- package/dist/lib/devices/doctor-overview-cache.d.ts +3 -2
- package/dist/lib/devices/fleet-divergence.d.ts +2 -1
- package/dist/lib/devices/fleet.d.ts +3 -4
- package/dist/lib/devices/fleet.js +1 -1
- package/dist/lib/devices/harness-inventory.d.ts +3 -2
- package/dist/lib/devices/health-report.d.ts +3 -2
- package/dist/lib/devices/health.d.ts +1 -8
- package/dist/lib/devices/health.js +1 -1
- package/dist/lib/devices/interactive-host.d.ts +0 -2
- package/dist/lib/devices/interactive-host.js +1 -1
- package/dist/lib/devices/known-hosts.d.ts +2 -20
- package/dist/lib/devices/known-hosts.js +2 -2
- package/dist/lib/devices/pool.d.ts +2 -1
- package/dist/lib/devices/resolve-target.d.ts +2 -2
- package/dist/lib/devices/rollout-verify.d.ts +3 -2
- package/dist/lib/devices/stats-cache.d.ts +3 -2
- package/dist/lib/devices/sync.d.ts +6 -5
- package/dist/lib/devices/worker-pick.d.ts +3 -12
- package/dist/lib/devices/worker-pick.js +1 -1
- package/dist/lib/diff-text.d.ts +2 -1
- package/dist/lib/doctor-diff.d.ts +2 -1
- package/dist/lib/drift-sync.d.ts +3 -2
- package/dist/lib/drift.d.ts +3 -3
- package/dist/lib/drift.js +1 -1
- package/dist/lib/event-families.d.ts +0 -6
- package/dist/lib/event-families.js +3 -3
- package/dist/lib/event-provenance.d.ts +4 -1
- package/dist/lib/event-provenance.js +4 -0
- package/dist/lib/events-ingest.d.ts +4 -3
- package/dist/lib/exec-account-home.d.ts +2 -4
- package/dist/lib/exec-account-home.js +1 -1
- package/dist/lib/exec-bounded.d.ts +3 -4
- package/dist/lib/exec-bounded.js +1 -1
- package/dist/lib/exec.d.ts +6 -18
- package/dist/lib/exec.js +28 -8
- package/dist/lib/factory/snapshot.d.ts +2 -2
- package/dist/lib/factory/snapshot.js +1 -1
- package/dist/lib/feed/activity-stream.d.ts +2 -5
- package/dist/lib/feed/activity-stream.js +11 -2
- package/dist/lib/feed/activity.d.ts +16 -33
- package/dist/lib/feed/activity.js +69 -26
- package/dist/lib/feed/answer.d.ts +3 -2
- package/dist/lib/feed/attention.js +5 -1
- package/dist/lib/feed/events.d.ts +2 -47
- package/dist/lib/feed/events.js +1 -141
- package/dist/lib/feed/feed.d.ts +9 -42
- package/dist/lib/feed/feed.js +1 -60
- package/dist/lib/feed/pr-status.d.ts +0 -2
- package/dist/lib/feed/pr-status.js +1 -5
- package/dist/lib/feed/watch.d.ts +10 -2
- package/dist/lib/feed/watch.js +91 -4
- package/dist/lib/feed-broadcast.d.ts +5 -47
- package/dist/lib/feed-broadcast.js +9 -9
- package/dist/lib/feed-outcome.d.ts +3 -6
- package/dist/lib/feed-outcome.js +2 -2
- package/dist/lib/feed-policy.d.ts +5 -6
- package/dist/lib/feed-policy.js +2 -2
- package/dist/lib/feed-post.d.ts +3 -4
- package/dist/lib/feed-post.js +2 -2
- package/dist/lib/feed-ranking.d.ts +2 -2
- package/dist/lib/feed-ranking.js +1 -1
- package/dist/lib/fleet/apply.d.ts +5 -6
- package/dist/lib/fleet/apply.js +4 -4
- package/dist/lib/fleet/manifest.d.ts +2 -1
- package/dist/lib/fleet/remote-login.d.ts +18 -36
- package/dist/lib/fleet/remote-login.js +20 -19
- package/dist/lib/fleet/types.d.ts +0 -8
- package/dist/lib/fleet-cache.d.ts +1 -18
- package/dist/lib/fleet-cache.js +0 -5
- package/dist/lib/fleet-shared-repo-sync.d.ts +3 -3
- package/dist/lib/fleet-shared-repo-sync.js +1 -1
- package/dist/lib/fleet-shared-state.d.ts +3 -2
- package/dist/lib/format.d.ts +2 -1
- package/dist/lib/friction-heuristics.d.ts +2 -1
- package/dist/lib/fs-walk.d.ts +2 -1
- package/dist/lib/fuzzy.d.ts +2 -1
- package/dist/lib/gemini-settings.d.ts +0 -1
- package/dist/lib/gemini-settings.js +1 -1
- package/dist/lib/git.d.ts +7 -65
- package/dist/lib/git.js +3 -142
- package/dist/lib/github/gh-overload.d.ts +0 -4
- package/dist/lib/github/gh-overload.js +2 -2
- package/dist/lib/github/project-prs.d.ts +118 -0
- package/dist/lib/github/project-prs.js +173 -0
- package/dist/lib/github/rest.d.ts +2 -1
- package/dist/lib/harness/exec-config-version.d.ts +2 -1
- package/dist/lib/harness-auth-capabilities.d.ts +5 -4
- package/dist/lib/harness-connection-test.d.ts +2 -1
- package/dist/lib/heal.d.ts +3 -20
- package/dist/lib/heal.js +2 -39
- package/dist/lib/help.d.ts +3 -2
- package/dist/lib/helper-download.d.ts +0 -12
- package/dist/lib/helper-download.js +2 -2
- package/dist/lib/helper-versions.d.ts +2 -1
- package/dist/lib/helper-versions.js +1 -1
- package/dist/lib/hooks/install.d.ts +8 -49
- package/dist/lib/hooks/install.js +2 -96
- package/dist/lib/hooks/match.d.ts +2 -1
- package/dist/lib/hosts/credential-transport.d.ts +0 -2
- package/dist/lib/hosts/credential-transport.js +1 -1
- package/dist/lib/hosts/dispatch.d.ts +2 -34
- package/dist/lib/hosts/dispatch.js +4 -21
- package/dist/lib/hosts/logs.d.ts +2 -1
- package/dist/lib/hosts/passthrough.d.ts +1 -1
- package/dist/lib/hosts/passthrough.js +0 -1
- package/dist/lib/hosts/progress.d.ts +0 -5
- package/dist/lib/hosts/progress.js +1 -1
- package/dist/lib/hosts/ready.d.ts +3 -4
- package/dist/lib/hosts/ready.js +0 -8
- package/dist/lib/hosts/reconcile.d.ts +2 -8
- package/dist/lib/hosts/reconcile.js +1 -1
- package/dist/lib/hosts/reconnect.d.ts +4 -11
- package/dist/lib/hosts/reconnect.js +2 -2
- package/dist/lib/hosts/registry.d.ts +1 -1
- package/dist/lib/hosts/remote-cmd.d.ts +4 -3
- package/dist/lib/hosts/remote-session-id.d.ts +5 -27
- package/dist/lib/hosts/remote-session-id.js +18 -61
- package/dist/lib/hosts/session-index.d.ts +3 -2
- package/dist/lib/hosts/ssh-config.d.ts +2 -3
- package/dist/lib/hosts/ssh-config.js +0 -10
- package/dist/lib/humans.d.ts +0 -2
- package/dist/lib/humans.js +2 -2
- package/dist/lib/import.d.ts +4 -3
- package/dist/lib/installations/installation-lock.d.ts +0 -2
- package/dist/lib/installations/installation-lock.js +2 -2
- package/dist/lib/installations/launch-gate.d.ts +0 -9
- package/dist/lib/installations/launch-gate.js +1 -1
- package/dist/lib/installations/migrate.d.ts +0 -11
- package/dist/lib/installations/migrate.js +1 -1
- package/dist/lib/installations/shims.d.ts +1 -1
- package/dist/lib/installations/shims.js +2 -2
- package/dist/lib/installations/update-runtime.js +1 -1
- package/dist/lib/launch-identity.d.ts +10 -0
- package/dist/lib/launch-identity.js +31 -0
- package/dist/lib/linear-cache.d.ts +2 -1
- package/dist/lib/linux-userns.d.ts +2 -3
- package/dist/lib/linux-userns.js +0 -4
- package/dist/lib/loop.d.ts +2 -1
- package/dist/lib/mailbox-gc.d.ts +2 -1
- package/dist/lib/mailbox-target.d.ts +2 -1
- package/dist/lib/mailbox.d.ts +0 -6
- package/dist/lib/mailbox.js +1 -1
- package/dist/lib/manifest.d.ts +0 -14
- package/dist/lib/manifest.js +2 -2
- package/dist/lib/mcp-registry.d.ts +2 -1
- package/dist/lib/memory.d.ts +2 -13
- package/dist/lib/memory.js +4 -4
- package/dist/lib/menubar/download-menubar.d.ts +0 -2
- package/dist/lib/menubar/download-menubar.js +1 -5
- package/dist/lib/menubar/install-menubar.d.ts +3 -14
- package/dist/lib/menubar/install-menubar.js +3 -3
- package/dist/lib/menubar/migrate-prefs.d.ts +53 -0
- package/dist/lib/menubar/migrate-prefs.js +168 -0
- package/dist/lib/menubar/resolve-version.d.ts +1 -9
- package/dist/lib/menubar/resolve-version.js +4 -4
- package/dist/lib/menubar/snapshot.d.ts +24 -2
- package/dist/lib/menubar/snapshot.js +26 -0
- package/dist/lib/model-tier-overrides.d.ts +3 -2
- package/dist/lib/monitors/config.d.ts +0 -2
- package/dist/lib/monitors/config.js +0 -4
- package/dist/lib/monitors/engine.d.ts +1 -1
- package/dist/lib/monitors/remote.d.ts +3 -2
- package/dist/lib/monitors/sources/webhook.d.ts +2 -15
- package/dist/lib/monitors/sources/webhook.js +1 -38
- package/dist/lib/monitors/state.d.ts +4 -7
- package/dist/lib/monitors/state.js +2 -2
- package/dist/lib/notify.d.ts +1 -1
- package/dist/lib/notify.js +1 -1
- package/dist/lib/onepassword.d.ts +5 -14
- package/dist/lib/onepassword.js +0 -64
- package/dist/lib/open-url.d.ts +3 -2
- package/dist/lib/openclaw-keychain.d.ts +4 -17
- package/dist/lib/openclaw-keychain.js +3 -33
- package/dist/lib/operator.d.ts +2 -2
- package/dist/lib/operator.js +1 -1
- package/dist/lib/output/git-output.d.ts +4 -14
- package/dist/lib/output/git-output.js +1 -1
- package/dist/lib/owner-message.d.ts +3 -29
- package/dist/lib/owner-message.js +3 -3
- package/dist/lib/packages/output-home.d.ts +2 -4
- package/dist/lib/packages/output-home.js +2 -2
- package/dist/lib/perf/db.d.ts +0 -2
- package/dist/lib/perf/db.js +2 -7
- package/dist/lib/permissions-registry.d.ts +2 -3
- package/dist/lib/permissions-registry.js +0 -4
- package/dist/lib/permissions.d.ts +6 -16
- package/dist/lib/permissions.js +2 -15
- package/dist/lib/picker.d.ts +6 -5
- package/dist/lib/placement.d.ts +3 -6
- package/dist/lib/placement.js +0 -17
- package/dist/lib/platform/posixpath.d.ts +2 -1
- package/dist/lib/platform/winpath.d.ts +2 -1
- package/dist/lib/plugins/plugin-marketplace.d.ts +2 -2
- package/dist/lib/plugins/plugin-marketplace.js +1 -1
- package/dist/lib/pr-land-detach.d.ts +2 -1
- package/dist/lib/profiles-presets.d.ts +2 -1
- package/dist/lib/profiles.d.ts +3 -9
- package/dist/lib/profiles.js +1 -9
- package/dist/lib/project-doctor.d.ts +2 -1
- package/dist/lib/project-launch.d.ts +2 -2
- package/dist/lib/project-probe.d.ts +4 -3
- package/dist/lib/project-pull.d.ts +2 -1
- package/dist/lib/project-resources.d.ts +2 -2
- package/dist/lib/project-resources.js +1 -1
- package/dist/lib/project-root.d.ts +2 -6
- package/dist/lib/project-root.js +1 -1
- package/dist/lib/project-schedule.d.ts +2 -1
- package/dist/lib/project-status.d.ts +2 -16
- package/dist/lib/project-status.js +3 -3
- package/dist/lib/reconcile-and-repair.d.ts +5 -4
- package/dist/lib/redact.d.ts +7 -1
- package/dist/lib/redact.js +94 -3
- package/dist/lib/refresh-coordinator.d.ts +2 -1
- package/dist/lib/refresh.d.ts +3 -2
- package/dist/lib/remote-agents-json.d.ts +3 -2
- package/dist/lib/reserved-stores.d.ts +0 -2
- package/dist/lib/reserved-stores.js +3 -5
- package/dist/lib/resource-content-diff.d.ts +0 -2
- package/dist/lib/resource-content-diff.js +1 -1
- package/dist/lib/resource-patterns.d.ts +2 -1
- package/dist/lib/resource-profiles.d.ts +2 -8
- package/dist/lib/resource-profiles.js +3 -27
- package/dist/lib/resources/workflows.d.ts +1 -1
- package/dist/lib/resources.d.ts +4 -9
- package/dist/lib/resources.js +1 -1
- package/dist/lib/routine-context.d.ts +2 -5
- package/dist/lib/routine-context.js +2 -2
- package/dist/lib/routine-notify-owner.d.ts +8 -7
- package/dist/lib/routine-notify-owner.js +5 -5
- package/dist/lib/routine-process-cleanup.d.ts +2 -1
- package/dist/lib/routine-readiness.d.ts +0 -2
- package/dist/lib/routine-readiness.js +0 -7
- package/dist/lib/routines-project.d.ts +3 -4
- package/dist/lib/routines-project.js +1 -1
- package/dist/lib/rules/compile.d.ts +3 -25
- package/dist/lib/rules/compile.js +1 -1
- package/dist/lib/rules/compose.d.ts +3 -9
- package/dist/lib/rules/rules.d.ts +4 -15
- package/dist/lib/rules/rules.js +1 -64
- package/dist/lib/run-defaults.d.ts +1 -1
- package/dist/lib/run-notify.d.ts +2 -1
- package/dist/lib/run-trace-sync.d.ts +1 -1
- package/dist/lib/run-trace-sync.js +1 -1
- package/dist/lib/scheduler.d.ts +2 -1
- package/dist/lib/scheduling/routines.d.ts +9 -21
- package/dist/lib/scheduling/routines.js +3 -46
- package/dist/lib/secrets-client.d.ts +0 -17
- package/dist/lib/secrets-client.js +4 -26
- package/dist/lib/secrets-policy.d.ts +12 -17
- package/dist/lib/secrets-policy.js +5 -5
- package/dist/lib/secrets-types.d.ts +3 -2
- package/dist/lib/secrets-types.js +2 -1
- package/dist/lib/self-heal/checks/install-staging.js +1 -1
- package/dist/lib/self-heal/registry.d.ts +3 -2
- package/dist/lib/self-heal/types.d.ts +1 -1
- package/dist/lib/self-heal/types.js +1 -1
- package/dist/lib/self-update.d.ts +5 -5
- package/dist/lib/self-update.js +4 -4
- package/dist/lib/session/active.js +9 -3
- package/dist/lib/session/actor-sidecar.d.ts +3 -2
- package/dist/lib/session/artifacts.d.ts +0 -2
- package/dist/lib/session/artifacts.js +1 -1
- package/dist/lib/session/bash-command.d.ts +2 -7
- package/dist/lib/session/bundle.d.ts +4 -6
- package/dist/lib/session/bundle.js +1 -5
- package/dist/lib/session/cloud.d.ts +0 -4
- package/dist/lib/session/cloud.js +2 -15
- package/dist/lib/session/db.d.ts +2 -1
- package/dist/lib/session/db.js +39 -4
- package/dist/lib/session/detached.d.ts +2 -1
- package/dist/lib/session/detached.js +2 -2
- package/dist/lib/session/digest.d.ts +2 -2
- package/dist/lib/session/digest.js +1 -1
- package/dist/lib/session/discover.js +7 -2
- package/dist/lib/session/fork.d.ts +3 -2
- package/dist/lib/session/highlights.d.ts +6 -5
- package/dist/lib/session/hook-sessions.d.ts +12 -1
- package/dist/lib/session/hook-sessions.js +139 -6
- package/dist/lib/session/host-link.d.ts +2 -1
- package/dist/lib/session/inject.d.ts +1 -1
- package/dist/lib/session/inject.js +1 -1
- package/dist/lib/session/insights.d.ts +3 -15
- package/dist/lib/session/insights.js +2 -2
- package/dist/lib/session/local-tmux-attach.d.ts +2 -18
- package/dist/lib/session/local-tmux-attach.js +1 -1
- package/dist/lib/session/migrations.d.ts +0 -1
- package/dist/lib/session/migrations.js +1 -1
- package/dist/lib/session/mirror.d.ts +5 -8
- package/dist/lib/session/mirror.js +2 -2
- package/dist/lib/session/parse.d.ts +1 -32
- package/dist/lib/session/parse.js +4 -4
- package/dist/lib/session/pid-registry.d.ts +18 -5
- package/dist/lib/session/pid-registry.js +164 -17
- package/dist/lib/session/presence.d.ts +2 -1
- package/dist/lib/session/process-view.d.ts +25 -0
- package/dist/lib/session/process-view.js +176 -0
- package/dist/lib/session/projection.d.ts +13 -0
- package/dist/lib/session/projection.js +101 -0
- package/dist/lib/session/prompt.d.ts +3 -2
- package/dist/lib/session/prompt.js +38 -1
- package/dist/lib/session/recovery.d.ts +3 -2
- package/dist/lib/session/remote/peer-stream.d.ts +2 -5
- package/dist/lib/session/remote/peer-stream.js +2 -2
- package/dist/lib/session/remote/remote-bundle.d.ts +2 -1
- package/dist/lib/session/remote/remote-list.d.ts +5 -5
- package/dist/lib/session/remote/remote.d.ts +4 -3
- package/dist/lib/session/remote/watch.d.ts +10 -7
- package/dist/lib/session/remote/watch.js +10 -6
- package/dist/lib/session/remote-active.d.ts +2 -1
- package/dist/lib/session/render.d.ts +2 -2
- package/dist/lib/session/render.js +1 -1
- package/dist/lib/session/resume-owner.d.ts +1 -1
- package/dist/lib/session/resume-owner.js +1 -1
- package/dist/lib/session/run-names.d.ts +2 -1
- package/dist/lib/session/session-cache.d.ts +7 -26
- package/dist/lib/session/session-cache.js +17 -8
- package/dist/lib/session/share-html.d.ts +1 -21
- package/dist/lib/session/share-html.js +1 -1
- package/dist/lib/session/shell-programs.d.ts +2 -1
- package/dist/lib/session/state.d.ts +41 -8
- package/dist/lib/session/state.js +112 -11
- package/dist/lib/session/stream-render.d.ts +2 -1
- package/dist/lib/session/sync/agents.d.ts +0 -4
- package/dist/lib/session/sync/agents.js +0 -0
- package/dist/lib/session/sync/backend.d.ts +5 -5
- package/dist/lib/session/sync/managed-config.d.ts +0 -8
- package/dist/lib/session/sync/managed-key.d.ts +0 -2
- package/dist/lib/session/sync/managed-key.js +1 -1
- package/dist/lib/session/sync/r2.d.ts +4 -1
- package/dist/lib/session/sync/r2.js +4 -7
- package/dist/lib/session/sync/transcript-crypto.d.ts +2 -1
- package/dist/lib/session/tail.d.ts +2 -1
- package/dist/lib/session/team-filter.d.ts +1 -1
- package/dist/lib/session/testdata/pid-registry-namespace.d.ts +1 -0
- package/dist/lib/session/testdata/pid-registry-namespace.js +27 -0
- package/dist/lib/session/testdata/process-view-namespace.d.ts +1 -0
- package/dist/lib/session/testdata/process-view-namespace.js +56 -0
- package/dist/lib/session/testdata/process-view-private.d.ts +1 -0
- package/dist/lib/session/testdata/process-view-private.js +12 -0
- package/dist/lib/session/throughput.d.ts +2 -3
- package/dist/lib/session/throughput.js +1 -1
- package/dist/lib/session/timeline-pass.d.ts +3 -42
- package/dist/lib/session/timeline-pass.js +4 -4
- package/dist/lib/session/timeline.d.ts +3 -13
- package/dist/lib/session/timeline.js +3 -3
- package/dist/lib/session/tool-calls.d.ts +2 -2
- package/dist/lib/session/tool-calls.js +1 -1
- package/dist/lib/session/tool-index.d.ts +0 -8
- package/dist/lib/session/tool-index.js +2 -2
- package/dist/lib/session/tool-store.d.ts +2 -1
- package/dist/lib/session/trajectory-compare.d.ts +2 -1
- package/dist/lib/session/trajectory-lineage.d.ts +2 -1
- package/dist/lib/session/trajectory-text.d.ts +3 -2
- package/dist/lib/session/trajectory.d.ts +2 -1
- package/dist/lib/session/viewing-in.d.ts +2 -1
- package/dist/lib/settings-manifest.d.ts +2 -1
- package/dist/lib/share/delete.d.ts +5 -4
- package/dist/lib/share/html.d.ts +0 -2
- package/dist/lib/share/html.js +9 -9
- package/dist/lib/share/http-error.d.ts +3 -2
- package/dist/lib/share/og.d.ts +2 -1
- package/dist/lib/share/provision.d.ts +2 -2
- package/dist/lib/share/publish.d.ts +4 -13
- package/dist/lib/share/publish.js +2 -2
- package/dist/lib/shim-heal.d.ts +1 -5
- package/dist/lib/shim-heal.js +0 -6
- package/dist/lib/smart-launch.d.ts +4 -5
- package/dist/lib/smart-launch.js +1 -1
- package/dist/lib/snapshot.d.ts +3 -2
- package/dist/lib/ssh-exec.d.ts +5 -4
- package/dist/lib/ssh-tunnel.d.ts +3 -2
- package/dist/lib/staleness/checkers/permissions.d.ts +0 -2
- package/dist/lib/staleness/checkers/permissions.js +1 -1
- package/dist/lib/staleness/fingerprint.d.ts +0 -7
- package/dist/lib/staleness/fingerprint.js +1 -1
- package/dist/lib/staleness/prune.d.ts +3 -2
- package/dist/lib/staleness/registry.d.ts +1 -1
- package/dist/lib/staleness/writers/sources.d.ts +0 -8
- package/dist/lib/staleness/writers/sources.js +1 -1
- package/dist/lib/startup/command-registry.js +1 -1
- package/dist/lib/state.d.ts +1 -3
- package/dist/lib/state.js +1 -4
- package/dist/lib/subagents-registry.d.ts +4 -3
- package/dist/lib/subagents.d.ts +2 -1
- package/dist/lib/subagents.js +3 -2
- package/dist/lib/summarizer/pass.d.ts +3 -6
- package/dist/lib/summarizer/pass.js +2 -2
- package/dist/lib/summarizer/summarize.d.ts +4 -3
- package/dist/lib/sync-passphrase.d.ts +3 -2
- package/dist/lib/sync-status.d.ts +3 -16
- package/dist/lib/sync-status.js +2 -2
- package/dist/lib/sync-umbrella.d.ts +4 -3
- package/dist/lib/system-run-sync.d.ts +2 -1
- package/dist/lib/teams/agents.d.ts +2 -4
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/teams/forEach.d.ts +3 -2
- package/dist/lib/teams/pr-watch.d.ts +4 -11
- package/dist/lib/teams/pr-watch.js +4 -4
- package/dist/lib/teams/registry.d.ts +2 -3
- package/dist/lib/teams/registry.js +1 -1
- package/dist/lib/teams/remoteWorktree.d.ts +0 -16
- package/dist/lib/teams/remoteWorktree.js +3 -3
- package/dist/lib/teams/scheduler.d.ts +6 -5
- package/dist/lib/teams/scheduler.js +1 -1
- package/dist/lib/teams/supervisor.d.ts +4 -3
- package/dist/lib/teams/worktree.d.ts +0 -9
- package/dist/lib/teams/worktree.js +0 -32
- package/dist/lib/term-client.d.ts +44 -0
- package/dist/lib/term-client.js +117 -0
- package/dist/lib/terminal/inject.d.ts +3 -16
- package/dist/lib/terminal/inject.js +1 -29
- package/dist/lib/terminal/resolve.d.ts +3 -9
- package/dist/lib/terminal/resolve.js +3 -7
- package/dist/lib/tmux/binary.d.ts +2 -1
- package/dist/lib/tmux/orphan-reap.d.ts +6 -7
- package/dist/lib/tmux/orphan-reap.js +1 -1
- package/dist/lib/tmux/session.d.ts +4 -3
- package/dist/lib/traces/classify.d.ts +3 -2
- package/dist/lib/traces/config.d.ts +0 -8
- package/dist/lib/traces/insights.d.ts +2 -1
- package/dist/lib/traces/phenotype.d.ts +3 -3
- package/dist/lib/traces/provision.d.ts +1 -3
- package/dist/lib/traces/provision.js +1 -1
- package/dist/lib/traces/schema2-build.d.ts +1 -1
- package/dist/lib/traces/schema2-danger.d.ts +2 -1
- package/dist/lib/traces/schema2.d.ts +5 -4
- package/dist/lib/traces/segments.d.ts +4 -20
- package/dist/lib/traces/segments.js +3 -3
- package/dist/lib/traces/sync.d.ts +2 -3
- package/dist/lib/traces/sync.js +1 -1
- package/dist/lib/triggers/handlers.d.ts +4 -13
- package/dist/lib/triggers/handlers.js +1 -1
- package/dist/lib/triggers/webhook.d.ts +5 -27
- package/dist/lib/triggers/webhook.js +4 -4
- package/dist/lib/types.d.ts +3 -3
- package/dist/lib/usage-refresh.d.ts +4 -10
- package/dist/lib/usage-refresh.js +3 -8
- package/dist/lib/verbs.d.ts +2 -1
- package/dist/lib/version-duplicates.d.ts +2 -3
- package/dist/lib/version-duplicates.js +3 -33
- package/dist/lib/version.d.ts +2 -1
- package/dist/lib/warn-unpushed.d.ts +2 -1
- package/dist/lib/watchdog/history.d.ts +3 -2
- package/dist/lib/watchdog/log.d.ts +0 -6
- package/dist/lib/watchdog/log.js +1 -1
- package/dist/lib/watchdog/rotate.d.ts +2 -26
- package/dist/lib/watchdog/rotate.js +4 -12
- package/dist/lib/watchdog/runner.d.ts +0 -7
- package/dist/lib/watchdog/runner.js +4 -4
- package/dist/lib/watchdog/service.d.ts +2 -2
- package/dist/lib/watchdog/service.js +1 -1
- package/dist/lib/watchdog/watchdog-agent.d.ts +2 -1
- package/dist/lib/watchdog/watchdog.d.ts +2 -1
- package/dist/lib/watchdog/watchdogTail.d.ts +2 -1
- package/dist/lib/workflows-registry.d.ts +3 -2
- package/dist/lib/workflows.d.ts +4 -7
- package/dist/lib/workflows.js +1 -1
- package/dist/lib/worktree/held.d.ts +4 -28
- package/dist/lib/worktree/held.js +3 -3
- package/package.json +2 -3
- package/scripts/postinstall.js +5 -4
- package/dist/commands/pty.d.ts +0 -20
- package/dist/commands/pty.js +0 -404
- package/dist/lib/config-machine-keys.d.ts +0 -14
- package/dist/lib/config-machine-keys.js +0 -21
- package/dist/lib/pty-client.d.ts +0 -49
- package/dist/lib/pty-client.js +0 -315
- package/dist/lib/pty-server.d.ts +0 -59
- package/dist/lib/pty-server.js +0 -653
|
@@ -71,17 +71,6 @@ export declare function parseClaude(filePath: string, opts?: ParseSessionOptions
|
|
|
71
71
|
export declare function parseClaudeContent(content: string, opts?: ParseSessionOptions): SessionEvent[];
|
|
72
72
|
/** Parse a Codex JSONL session file into normalized events. */
|
|
73
73
|
export declare function parseCodex(filePath: string): SessionEvent[];
|
|
74
|
-
/**
|
|
75
|
-
* Extract target file path(s) from a Codex apply_patch envelope. The patch body
|
|
76
|
-
* opens with `*** Begin Patch` and carries one or more file ops of the form
|
|
77
|
-
* `*** Update File: <path>` / `*** Add File: <path>` / `*** Delete File: <path>`.
|
|
78
|
-
* Returns every path in order (a multi-file patch emits multiple paths so
|
|
79
|
-
* artifact discovery sees each file — RUSH-1410). Empty when unparseable.
|
|
80
|
-
*/
|
|
81
|
-
export declare function applyPatchTargets(input: string): Array<{
|
|
82
|
-
path: string;
|
|
83
|
-
op: 'Add' | 'Update' | 'Delete';
|
|
84
|
-
}>;
|
|
85
74
|
export declare function applyPatchTargetPaths(input: string): string[];
|
|
86
75
|
/**
|
|
87
76
|
* Codex writes its turn TWICE in one rollout: the raw `response_item` records
|
|
@@ -119,14 +108,6 @@ export declare function parseGemini(filePath: string): SessionEvent[];
|
|
|
119
108
|
* request step and a completion step that share the id).
|
|
120
109
|
*/
|
|
121
110
|
export declare function parseAntigravity(dbPath: string): SessionEvent[];
|
|
122
|
-
/**
|
|
123
|
-
* Separator between a container file and the id it holds inside a *composite*
|
|
124
|
-
* session `file_path`. Some harnesses keep every session in ONE file (OpenCode's
|
|
125
|
-
* single `opencode.db`), so the index stores `<container>#<session-id>` rather
|
|
126
|
-
* than one path per session — e.g.
|
|
127
|
-
* `/home/u/.local/share/opencode/opencode.db#ses_02410a2c…`.
|
|
128
|
-
*/
|
|
129
|
-
export declare const SESSION_FILE_PATH_SEP = "#";
|
|
130
111
|
/**
|
|
131
112
|
* Split a stored session `file_path` into its on-disk container and the optional
|
|
132
113
|
* in-container fragment. For a plain per-session file the container is the path
|
|
@@ -179,7 +160,7 @@ export declare function sessionFilePathContainer(filePath: string): string;
|
|
|
179
160
|
* session that committed / opened / merged a PR and to report a tool-failure
|
|
180
161
|
* count the event stream cannot supply.
|
|
181
162
|
*/
|
|
182
|
-
|
|
163
|
+
interface GrokSessionSignals {
|
|
183
164
|
gitCommitCount: number;
|
|
184
165
|
prCreatedCount: number;
|
|
185
166
|
prMergedCount: number;
|
|
@@ -232,18 +213,6 @@ export declare function parseOpenCode(filePath: string): SessionEvent[];
|
|
|
232
213
|
export declare function parseOpencodeCloud(filePath: string): SessionEvent[];
|
|
233
214
|
/** Parse a Rush JSONL session file into normalized events. */
|
|
234
215
|
export declare function parseRush(filePath: string): SessionEvent[];
|
|
235
|
-
/**
|
|
236
|
-
* Muse Code session.jsonl → normalized events.
|
|
237
|
-
*
|
|
238
|
-
* Muse records an append-only event log. We map:
|
|
239
|
-
* - runtime.command_intake.received / turn_submit → user message
|
|
240
|
-
* - assistant_message_committed → assistant message
|
|
241
|
-
* - model_completed.usage → usage
|
|
242
|
-
* - tool-related events when present
|
|
243
|
-
*/
|
|
244
|
-
export declare function parseMuse(filePath: string): SessionEvent[];
|
|
245
|
-
/** Parse a Hermes session JSON file into normalized events. */
|
|
246
|
-
export declare function parseHermes(filePath: string): SessionEvent[];
|
|
247
216
|
/** Parse a Kimi session state.json file by reading its agents/main/wire.jsonl. */
|
|
248
217
|
export declare function parseKimi(filePath: string): SessionEvent[];
|
|
249
218
|
/** Parse Cursor's Anthropic-shaped message JSONL transcript. */
|
|
@@ -609,7 +609,7 @@ export function parseCodex(filePath) {
|
|
|
609
609
|
* Returns every path in order (a multi-file patch emits multiple paths so
|
|
610
610
|
* artifact discovery sees each file — RUSH-1410). Empty when unparseable.
|
|
611
611
|
*/
|
|
612
|
-
|
|
612
|
+
function applyPatchTargets(input) {
|
|
613
613
|
const targets = [];
|
|
614
614
|
const re = /^\*\*\* (Update|Add|Delete) File: (.+)$/gm;
|
|
615
615
|
for (const m of input.matchAll(re)) {
|
|
@@ -1391,7 +1391,7 @@ export function parseAntigravity(dbPath) {
|
|
|
1391
1391
|
* than one path per session — e.g.
|
|
1392
1392
|
* `/home/u/.local/share/opencode/opencode.db#ses_02410a2c…`.
|
|
1393
1393
|
*/
|
|
1394
|
-
|
|
1394
|
+
const SESSION_FILE_PATH_SEP = '#';
|
|
1395
1395
|
/**
|
|
1396
1396
|
* Split a stored session `file_path` into its on-disk container and the optional
|
|
1397
1397
|
* in-container fragment. For a plain per-session file the container is the path
|
|
@@ -2086,7 +2086,7 @@ export function parseRush(filePath) {
|
|
|
2086
2086
|
* - model_completed.usage → usage
|
|
2087
2087
|
* - tool-related events when present
|
|
2088
2088
|
*/
|
|
2089
|
-
|
|
2089
|
+
function parseMuse(filePath) {
|
|
2090
2090
|
const content = safeReadSessionFile(filePath);
|
|
2091
2091
|
const lines = content.split('\n').filter((l) => l.trim());
|
|
2092
2092
|
const events = [];
|
|
@@ -2166,7 +2166,7 @@ export function parseMuse(filePath) {
|
|
|
2166
2166
|
return events;
|
|
2167
2167
|
}
|
|
2168
2168
|
/** Parse a Hermes session JSON file into normalized events. */
|
|
2169
|
-
|
|
2169
|
+
function parseHermes(filePath) {
|
|
2170
2170
|
let session;
|
|
2171
2171
|
try {
|
|
2172
2172
|
session = JSON.parse(safeReadSessionFile(filePath));
|
|
@@ -49,7 +49,17 @@ export interface PidSessionEntry {
|
|
|
49
49
|
*/
|
|
50
50
|
tmuxPane?: string;
|
|
51
51
|
startedAtMs: number;
|
|
52
|
+
/** Kernel provenance, captured by the writer; absent on legacy records. */
|
|
53
|
+
processIdentity?: {
|
|
54
|
+
bootId?: string;
|
|
55
|
+
pidNamespace?: string;
|
|
56
|
+
initStartTicks?: string;
|
|
57
|
+
startTicks?: string;
|
|
58
|
+
startTime?: string;
|
|
59
|
+
};
|
|
52
60
|
}
|
|
61
|
+
/** Read-only identity proof for exact joins. Unknown is never a positive match. */
|
|
62
|
+
export declare function pidSessionEntryMatchesLiveProcess(entry: PidSessionEntry): boolean | undefined;
|
|
53
63
|
export declare function isSessionIdShape(value: string): boolean;
|
|
54
64
|
export declare function extractSessionIdArg(args: string[]): string | undefined;
|
|
55
65
|
/**
|
|
@@ -76,6 +86,8 @@ export declare function sessionIdFromLivePid(pid: number): string | undefined;
|
|
|
76
86
|
export declare function writePidSessionEntry(entry: PidSessionEntry): void;
|
|
77
87
|
/** Look up a live pid's recorded session. Returns undefined if absent/corrupt. */
|
|
78
88
|
export declare function readPidSessionEntry(pid: number): PidSessionEntry | undefined;
|
|
89
|
+
/** Live consumers require identity proof; raw history is not a PID binding. */
|
|
90
|
+
export declare function readLivePidSessionEntry(pid: number): PidSessionEntry | undefined;
|
|
79
91
|
/**
|
|
80
92
|
* Every recorded launch, one entry per live-or-dead pid. Used to index launches
|
|
81
93
|
* by their `tmuxPane` so the authoritative tmux source can attribute a pane it did
|
|
@@ -87,9 +99,10 @@ export declare function listPidSessionEntries(): PidSessionEntry[];
|
|
|
87
99
|
/**
|
|
88
100
|
* Remove entries whose pid is no longer alive. Best-effort housekeeping.
|
|
89
101
|
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
102
|
+
* Linux deletion requires the writer's boot and PID namespace to match our own
|
|
103
|
+
* trustworthy proc view. ESRCH in another namespace says nothing about the
|
|
104
|
+
* recorded process. Legacy/corrupt/unreadable ownership is unknown, never dead.
|
|
105
|
+
* Kernel start ticks reject PID reuse without wall-clock heuristics. Other
|
|
106
|
+
* platforms retain the caller's start-time check after checking kernel liveness.
|
|
94
107
|
*/
|
|
95
|
-
export declare function prunePidSessionRegistry(isAlive
|
|
108
|
+
export declare function prunePidSessionRegistry(isAlive?: (pid: number, startedAtMs?: number) => boolean | undefined): void;
|
|
@@ -19,7 +19,69 @@
|
|
|
19
19
|
import fs from 'fs';
|
|
20
20
|
import path from 'path';
|
|
21
21
|
import { execFileSync } from 'child_process';
|
|
22
|
+
import { hostProcessView, writerProcessView } from './process-view.js';
|
|
22
23
|
import { getTerminalsDir } from '../state.js';
|
|
24
|
+
import { atomicWriteFileSync, withFileLock } from '../fs-atomic.js';
|
|
25
|
+
function linuxStartTicks(pid) {
|
|
26
|
+
try {
|
|
27
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
28
|
+
// comm (field 2) may contain spaces or parentheses; starttime is field 22.
|
|
29
|
+
const value = stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19];
|
|
30
|
+
return value && /^\d+$/.test(value) ? value : undefined;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function pidExists(pid) {
|
|
37
|
+
try {
|
|
38
|
+
process.kill(pid, 0);
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const code = error.code;
|
|
43
|
+
if (code === 'ESRCH')
|
|
44
|
+
return false;
|
|
45
|
+
if (code === 'EPERM')
|
|
46
|
+
return true;
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function darwinStartTime(pid) {
|
|
51
|
+
try {
|
|
52
|
+
return execFileSync('ps', ['-p', String(pid), '-o', 'lstart='], { encoding: 'utf8', timeout: 2000, stdio: ['ignore', 'pipe', 'ignore'] }).trim() || undefined;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Read-only identity proof for exact joins. Unknown is never a positive match. */
|
|
59
|
+
export function pidSessionEntryMatchesLiveProcess(entry) {
|
|
60
|
+
if (!Number.isInteger(entry.pid) || entry.pid < 1)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (process.platform === 'darwin') {
|
|
63
|
+
const exists = pidExists(entry.pid);
|
|
64
|
+
if (exists !== true)
|
|
65
|
+
return exists;
|
|
66
|
+
const start = darwinStartTime(entry.pid);
|
|
67
|
+
return start && entry.processIdentity?.startTime ? start === entry.processIdentity.startTime : undefined;
|
|
68
|
+
}
|
|
69
|
+
if (process.platform !== 'linux')
|
|
70
|
+
return undefined;
|
|
71
|
+
const scope = hostProcessView();
|
|
72
|
+
if (!scope || entry.processIdentity?.bootId !== scope.bootId
|
|
73
|
+
|| entry.processIdentity?.pidNamespace !== scope.pidNamespace
|
|
74
|
+
|| entry.processIdentity?.initStartTicks !== scope.initStartTicks)
|
|
75
|
+
return undefined;
|
|
76
|
+
const exists = pidExists(entry.pid);
|
|
77
|
+
if (exists !== true)
|
|
78
|
+
return exists;
|
|
79
|
+
const start = linuxStartTicks(entry.pid);
|
|
80
|
+
const recordedStart = entry.processIdentity?.startTicks;
|
|
81
|
+
if (!start || typeof recordedStart !== 'string' || !/^\d+$/.test(recordedStart))
|
|
82
|
+
return undefined;
|
|
83
|
+
return start === recordedStart;
|
|
84
|
+
}
|
|
23
85
|
/**
|
|
24
86
|
* Pull an explicit `--session-id <uuid>` (or `--session-id=<uuid>`) out of a
|
|
25
87
|
* raw agent arg vector. The transparent shim forwards args untouched, but when
|
|
@@ -106,13 +168,46 @@ function pidRegistryDir() {
|
|
|
106
168
|
function entryPath(pid) {
|
|
107
169
|
return path.join(pidRegistryDir(), `${pid}.json`);
|
|
108
170
|
}
|
|
171
|
+
// The deployed SessionStart hook reconstructs by-pid entries from an allowlist.
|
|
172
|
+
// Keep launcher ownership separately, bound to the immutable launch coordinates.
|
|
173
|
+
function ownershipPath(pid) {
|
|
174
|
+
return path.join(getTerminalsDir(), 'by-pid-ownership', `${pid}.json`);
|
|
175
|
+
}
|
|
176
|
+
function persistOwnership(entry) {
|
|
177
|
+
fs.mkdirSync(path.dirname(ownershipPath(entry.pid)), { recursive: true });
|
|
178
|
+
atomicWriteFileSync(ownershipPath(entry.pid), JSON.stringify(entry), 'utf8');
|
|
179
|
+
}
|
|
180
|
+
function restoreOwnership(entry) {
|
|
181
|
+
if (entry.processIdentity)
|
|
182
|
+
return entry;
|
|
183
|
+
try {
|
|
184
|
+
const owner = JSON.parse(fs.readFileSync(ownershipPath(entry.pid), 'utf8'));
|
|
185
|
+
if (owner.pid === entry.pid && owner.launchId === entry.launchId && owner.startedAtMs === entry.startedAtMs) {
|
|
186
|
+
return { ...entry, processIdentity: owner.processIdentity };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch { /* legacy launch */ }
|
|
190
|
+
return entry;
|
|
191
|
+
}
|
|
109
192
|
/** Record a launched agent process. Never throws — the registry is an optimization. */
|
|
110
193
|
export function writePidSessionEntry(entry) {
|
|
111
|
-
if (!entry.pid || entry.pid < 1)
|
|
194
|
+
if (!Number.isInteger(entry.pid) || entry.pid < 1)
|
|
112
195
|
return;
|
|
113
196
|
try {
|
|
197
|
+
const scope = process.platform === 'linux' ? writerProcessView() : undefined;
|
|
198
|
+
if (process.platform === 'linux' && !scope)
|
|
199
|
+
return;
|
|
114
200
|
fs.mkdirSync(pidRegistryDir(), { recursive: true });
|
|
115
|
-
|
|
201
|
+
const processIdentity = scope?.bootId && scope.pidNamespace ? { bootId: scope.bootId, pidNamespace: scope.pidNamespace, initStartTicks: scope.initStartTicks, startTicks: linuxStartTicks(entry.pid) }
|
|
202
|
+
: process.platform === 'darwin' ? { startTime: darwinStartTime(entry.pid) } : undefined;
|
|
203
|
+
const file = entryPath(entry.pid);
|
|
204
|
+
withFileLock(file, () => {
|
|
205
|
+
// The host writer owns numeric PID slots. Old-boot and legacy records
|
|
206
|
+
// must not reserve a recycled slot; restricted namespaces never get here.
|
|
207
|
+
const owned = { ...entry, processIdentity };
|
|
208
|
+
persistOwnership(owned);
|
|
209
|
+
atomicWriteFileSync(file, JSON.stringify(owned), 'utf8');
|
|
210
|
+
}, { realpath: false, acquireTimeoutMs: 0 });
|
|
116
211
|
}
|
|
117
212
|
catch {
|
|
118
213
|
/* degrade to the newest-jsonl heuristic */
|
|
@@ -129,8 +224,8 @@ export function readPidSessionEntry(pid) {
|
|
|
129
224
|
}
|
|
130
225
|
try {
|
|
131
226
|
const parsed = JSON.parse(raw);
|
|
132
|
-
if (parsed && typeof parsed === 'object' &&
|
|
133
|
-
return parsed;
|
|
227
|
+
if (parsed && typeof parsed === 'object' && parsed.pid === pid) {
|
|
228
|
+
return restoreOwnership(parsed);
|
|
134
229
|
}
|
|
135
230
|
}
|
|
136
231
|
catch {
|
|
@@ -138,6 +233,32 @@ export function readPidSessionEntry(pid) {
|
|
|
138
233
|
}
|
|
139
234
|
return undefined;
|
|
140
235
|
}
|
|
236
|
+
/** Live consumers require identity proof; raw history is not a PID binding. */
|
|
237
|
+
export function readLivePidSessionEntry(pid) {
|
|
238
|
+
const entry = readPidSessionEntry(pid);
|
|
239
|
+
if (!entry || !hostProcessView())
|
|
240
|
+
return undefined;
|
|
241
|
+
if (process.platform === 'win32')
|
|
242
|
+
return pidExists(pid) === true ? entry : undefined;
|
|
243
|
+
if (!entry.processIdentity && pidExists(pid) === true) {
|
|
244
|
+
// Upgrade a native legacy launch only after the home namespace is proven,
|
|
245
|
+
// and the actual process start excludes a recycled PID. Hook timestamps may
|
|
246
|
+
// be later than process start, but cannot predate this process incarnation.
|
|
247
|
+
const start = darwinStartTime(pid);
|
|
248
|
+
const startMs = start ? Date.parse(start) : NaN;
|
|
249
|
+
if (Number.isFinite(startMs) && entry.startedAtMs >= startMs - 1000 && entry.startedAtMs <= Date.now()) {
|
|
250
|
+
const scope = hostProcessView();
|
|
251
|
+
entry.processIdentity = process.platform === 'linux'
|
|
252
|
+
? { ...scope, startTicks: linuxStartTicks(pid) }
|
|
253
|
+
: { startTime: start };
|
|
254
|
+
try {
|
|
255
|
+
persistOwnership(entry);
|
|
256
|
+
}
|
|
257
|
+
catch { /* read remains useful */ }
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return pidSessionEntryMatchesLiveProcess(entry) === true ? entry : undefined;
|
|
261
|
+
}
|
|
141
262
|
/**
|
|
142
263
|
* Every recorded launch, one entry per live-or-dead pid. Used to index launches
|
|
143
264
|
* by their `tmuxPane` so the authoritative tmux source can attribute a pane it did
|
|
@@ -158,7 +279,7 @@ export function listPidSessionEntries() {
|
|
|
158
279
|
try {
|
|
159
280
|
const parsed = JSON.parse(fs.readFileSync(path.join(pidRegistryDir(), f), 'utf8'));
|
|
160
281
|
if (parsed && typeof parsed === 'object' && typeof parsed.pid === 'number') {
|
|
161
|
-
out.push(parsed);
|
|
282
|
+
out.push(restoreOwnership(parsed));
|
|
162
283
|
}
|
|
163
284
|
}
|
|
164
285
|
catch {
|
|
@@ -170,10 +291,11 @@ export function listPidSessionEntries() {
|
|
|
170
291
|
/**
|
|
171
292
|
* Remove entries whose pid is no longer alive. Best-effort housekeeping.
|
|
172
293
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
294
|
+
* Linux deletion requires the writer's boot and PID namespace to match our own
|
|
295
|
+
* trustworthy proc view. ESRCH in another namespace says nothing about the
|
|
296
|
+
* recorded process. Legacy/corrupt/unreadable ownership is unknown, never dead.
|
|
297
|
+
* Kernel start ticks reject PID reuse without wall-clock heuristics. Other
|
|
298
|
+
* platforms retain the caller's start-time check after checking kernel liveness.
|
|
177
299
|
*/
|
|
178
300
|
export function prunePidSessionRegistry(isAlive) {
|
|
179
301
|
let files;
|
|
@@ -183,23 +305,48 @@ export function prunePidSessionRegistry(isAlive) {
|
|
|
183
305
|
catch {
|
|
184
306
|
return;
|
|
185
307
|
}
|
|
308
|
+
const scope = process.platform === 'linux' ? hostProcessView() : undefined;
|
|
186
309
|
for (const f of files) {
|
|
187
310
|
const pid = Number(f.slice(0, -'.json'.length));
|
|
188
|
-
if (!Number.isInteger(pid))
|
|
311
|
+
if (!Number.isInteger(pid) || pid < 1)
|
|
189
312
|
continue;
|
|
190
|
-
let
|
|
313
|
+
let raw;
|
|
314
|
+
let entry;
|
|
191
315
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
316
|
+
raw = fs.readFileSync(path.join(pidRegistryDir(), f), 'utf8');
|
|
317
|
+
entry = restoreOwnership(JSON.parse(raw));
|
|
318
|
+
if (entry?.pid !== pid)
|
|
319
|
+
continue;
|
|
195
320
|
}
|
|
196
321
|
catch {
|
|
197
|
-
|
|
322
|
+
continue;
|
|
198
323
|
}
|
|
199
|
-
if (
|
|
324
|
+
if (process.platform === 'linux' && (!scope
|
|
325
|
+
|| entry.processIdentity?.bootId !== scope.bootId
|
|
326
|
+
|| entry.processIdentity?.pidNamespace !== scope.pidNamespace
|
|
327
|
+
|| entry.processIdentity?.initStartTicks !== scope.initStartTicks))
|
|
328
|
+
continue;
|
|
329
|
+
const exists = pidExists(pid);
|
|
330
|
+
if (exists === undefined)
|
|
200
331
|
continue;
|
|
332
|
+
if (exists) {
|
|
333
|
+
if (process.platform === 'linux') {
|
|
334
|
+
const start = linuxStartTicks(pid);
|
|
335
|
+
const recordedStart = entry.processIdentity?.startTicks;
|
|
336
|
+
if (!start || typeof recordedStart !== 'string' || !/^\d+$/.test(recordedStart) || start === recordedStart)
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
else if (!isAlive || isAlive(pid, entry.startedAtMs) !== false)
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
201
342
|
try {
|
|
202
|
-
|
|
343
|
+
const file = path.join(pidRegistryDir(), f);
|
|
344
|
+
// Share the writer's lock so comparison and deletion cannot remove a
|
|
345
|
+
// successor published after the liveness check.
|
|
346
|
+
withFileLock(file, () => {
|
|
347
|
+
if (fs.readFileSync(file, 'utf8') === raw)
|
|
348
|
+
fs.unlinkSync(file);
|
|
349
|
+
}, { realpath: false, acquireTimeoutMs: 0 });
|
|
203
350
|
}
|
|
204
351
|
catch {
|
|
205
352
|
/* raced with another writer/pruner */
|
|
@@ -44,7 +44,7 @@ export declare function loadPresence(dir?: string): Record<string, PresenceRecor
|
|
|
44
44
|
export declare function savePresence(map: Record<string, PresenceRecord>, dir?: string): void;
|
|
45
45
|
/** The subset of an `ActiveSession` the presence adapter reads (structural, so
|
|
46
46
|
* this module doesn't import the heavy active-session graph). */
|
|
47
|
-
|
|
47
|
+
interface ActiveSessionLike {
|
|
48
48
|
sessionId?: string;
|
|
49
49
|
kind: string;
|
|
50
50
|
/** 'terminal' (interactive) | 'headless' | 'teams' | 'cloud' | ... */
|
|
@@ -83,3 +83,4 @@ export declare function reconcilePresence(prev: Record<string, PresenceRecord>,
|
|
|
83
83
|
next: Record<string, PresenceRecord>;
|
|
84
84
|
transitions: PresenceTransition[];
|
|
85
85
|
};
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface HostProcessView {
|
|
2
|
+
bootId?: string;
|
|
3
|
+
pidNamespace?: string;
|
|
4
|
+
/** Namespace inodes can be reused within one boot; its init identifies the incarnation. */
|
|
5
|
+
initStartTicks?: string;
|
|
6
|
+
ownerPid?: number;
|
|
7
|
+
ownerStartTicks?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Measure the calling process, never infer authority from a process name. */
|
|
10
|
+
export declare function currentProcessView(): HostProcessView | undefined;
|
|
11
|
+
/** Read-only ownership check. Observing a HOME never claims or migrates it. */
|
|
12
|
+
export declare function hostProcessView(): HostProcessView | undefined;
|
|
13
|
+
/** Explicit writers may enroll a fresh HOME in their measured namespace.
|
|
14
|
+
* Foreign ownership remains protected even when the prior writer is invisible.
|
|
15
|
+
* The initial host may enroll legacy state before daemon startup. */
|
|
16
|
+
export declare function writerProcessView(): HostProcessView | undefined;
|
|
17
|
+
/** Preflight BEFORE even the PID-keyed legacy lifecycle lock is inspected.
|
|
18
|
+
* The same decision is repeated under that lock before daemon state changes. */
|
|
19
|
+
export declare function daemonProcessViewAllowed(): boolean;
|
|
20
|
+
/** Called by the canonical daemon writer before lifecycle mutation.
|
|
21
|
+
* This is a writer statement, not an observer's guess about a numeric PID.
|
|
22
|
+
* Existing same-boot ownership cannot be taken over from another namespace. */
|
|
23
|
+
export declare function recordDaemonProcessView(): void;
|
|
24
|
+
export declare function requireHostProcessView(): void;
|
|
25
|
+
export declare function requireWriterProcessView(): void;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { getCacheDir, getTerminalsDir, getDaemonDir } from '../state.js';
|
|
5
|
+
import { atomicWriteFileSync, withFileLock } from '../fs-atomic.js';
|
|
6
|
+
// Linux UAPI PID_NS_INIT_INO (include/uapi/linux/nsfs.h; previously
|
|
7
|
+
// PROC_PID_INIT_INO in include/linux/proc_ns.h). This is a kernel-defined
|
|
8
|
+
// namespace identity, independent of PID 1's executable or command name.
|
|
9
|
+
function isInitialPidNamespace(view) {
|
|
10
|
+
return view.pidNamespace === 'pid:[4026531836]';
|
|
11
|
+
}
|
|
12
|
+
function sameProcessView(owner, view) {
|
|
13
|
+
return owner.bootId === view.bootId && owner.pidNamespace === view.pidNamespace
|
|
14
|
+
&& owner.initStartTicks === view.initStartTicks;
|
|
15
|
+
}
|
|
16
|
+
/** Authenticate the legacy singleton with kernel socket credentials. A host
|
|
17
|
+
* daemon invisible in a nested namespace has peer PID 0, never a colliding PID.
|
|
18
|
+
* No socket/PID/command-name guess grants migration authority. */
|
|
19
|
+
function verifiedLegacyDaemon() {
|
|
20
|
+
try {
|
|
21
|
+
execFileSync('python3', ['-c', `import os,socket,struct,sys
|
|
22
|
+
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
|
|
23
|
+
s.settimeout(0.2)
|
|
24
|
+
s.connect(sys.argv[1])
|
|
25
|
+
pid,uid,gid=struct.unpack('3i',s.getsockopt(socket.SOL_SOCKET,socket.SO_PEERCRED,12))
|
|
26
|
+
assert pid>0 and uid==os.getuid()
|
|
27
|
+
assert pid==int(open(sys.argv[2]).read().strip())
|
|
28
|
+
assert os.readlink('/proc/%d/ns/pid'%pid)==os.readlink('/proc/self/ns/pid')
|
|
29
|
+
`, path.join(getCacheDir(), 'helpers', 'browser', 'browser.sock'), path.join(getDaemonDir(), 'daemon.pid')], {
|
|
30
|
+
stdio: 'ignore', timeout: 1000,
|
|
31
|
+
});
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function hasLegacyState() {
|
|
39
|
+
return [path.join(getTerminalsDir(), 'by-pid'), path.join(getCacheDir(), 'state', 'sessions')]
|
|
40
|
+
.some(dir => fs.existsSync(dir) && fs.readdirSync(dir).length > 0)
|
|
41
|
+
// Health/log output records attempted starts, not ownership. The ordinary
|
|
42
|
+
// start path writes health.json BEFORE spawning its first daemon.
|
|
43
|
+
|| ['daemon.pid', 'daemon.lifetime', 'heartbeat.json'].some(file => fs.existsSync(path.join(getDaemonDir(), file)))
|
|
44
|
+
|| fs.existsSync(path.join(getCacheDir(), 'helpers', 'browser', 'browser.sock'))
|
|
45
|
+
|| ['.active-sessions.json', '.active-session-immutable.json'].some(file => fs.existsSync(path.join(getCacheDir(), file)));
|
|
46
|
+
}
|
|
47
|
+
/** Measure the calling process, never infer authority from a process name. */
|
|
48
|
+
export function currentProcessView() {
|
|
49
|
+
if (process.platform !== 'linux')
|
|
50
|
+
return {};
|
|
51
|
+
try {
|
|
52
|
+
if (Number(fs.readFileSync('/proc/self/stat', 'utf8').split(' ', 1)[0]) !== process.pid)
|
|
53
|
+
return undefined;
|
|
54
|
+
const bootId = fs.readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim();
|
|
55
|
+
const pidNamespace = fs.readlinkSync('/proc/self/ns/pid');
|
|
56
|
+
// NSpid is relative to the procfs mount. Multiple coordinates mean this
|
|
57
|
+
// mount exposes an ancestor namespace, even if numeric PIDs happen to match.
|
|
58
|
+
const procPids = fs.readFileSync('/proc/self/status', 'utf8').match(/^NSpid:\s+([^\n]+)$/m)?.[1].trim().split(/\s+/);
|
|
59
|
+
if (procPids?.length !== 1 || Number(procPids[0]) !== process.pid)
|
|
60
|
+
return undefined;
|
|
61
|
+
const initStat = fs.readFileSync('/proc/1/stat', 'utf8');
|
|
62
|
+
const initStartTicks = initStat.slice(initStat.lastIndexOf(')') + 2).split(' ')[19];
|
|
63
|
+
const stat = fs.readFileSync('/proc/self/stat', 'utf8');
|
|
64
|
+
const ownerStartTicks = stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19];
|
|
65
|
+
return bootId && pidNamespace && /^\d+$/.test(initStartTicks) && /^\d+$/.test(ownerStartTicks)
|
|
66
|
+
? { bootId, pidNamespace, initStartTicks, ownerPid: process.pid, ownerStartTicks } : undefined;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Read-only ownership check. Observing a HOME never claims or migrates it. */
|
|
73
|
+
export function hostProcessView() {
|
|
74
|
+
const view = currentProcessView();
|
|
75
|
+
if (!view || process.platform !== 'linux')
|
|
76
|
+
return view;
|
|
77
|
+
try {
|
|
78
|
+
const owner = JSON.parse(fs.readFileSync(path.join(getTerminalsDir(), 'process-view.json'), 'utf8'));
|
|
79
|
+
return sameProcessView(owner, view) ? view : undefined;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
// The initial kernel namespace is authoritative before any daemon has
|
|
83
|
+
// enrolled this HOME. This observation itself must remain read-only.
|
|
84
|
+
return error.code === 'ENOENT' && isInitialPidNamespace(view) ? view : undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Explicit writers may enroll a fresh HOME in their measured namespace.
|
|
88
|
+
* Foreign ownership remains protected even when the prior writer is invisible.
|
|
89
|
+
* The initial host may enroll legacy state before daemon startup. */
|
|
90
|
+
export function writerProcessView() {
|
|
91
|
+
const view = currentProcessView();
|
|
92
|
+
if (!view || process.platform !== 'linux')
|
|
93
|
+
return view;
|
|
94
|
+
const file = path.join(getTerminalsDir(), 'process-view.json');
|
|
95
|
+
try {
|
|
96
|
+
if (fs.existsSync(file)) {
|
|
97
|
+
const owner = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
98
|
+
return sameProcessView(owner, view) ? view : undefined;
|
|
99
|
+
}
|
|
100
|
+
// A foreign observer of legacy state must not even create a directory or
|
|
101
|
+
// claim lock. Repeat this preflight under the lock before enrollment.
|
|
102
|
+
if (hasLegacyState() && !isInitialPidNamespace(view))
|
|
103
|
+
return undefined;
|
|
104
|
+
fs.mkdirSync(getTerminalsDir(), { recursive: true });
|
|
105
|
+
return withFileLock(file, () => {
|
|
106
|
+
if (fs.existsSync(file)) {
|
|
107
|
+
const owner = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
108
|
+
return sameProcessView(owner, view) ? view : undefined;
|
|
109
|
+
}
|
|
110
|
+
// Unowned nonempty registry is not evidence this caller owns the host.
|
|
111
|
+
if (hasLegacyState() && !isInitialPidNamespace(view))
|
|
112
|
+
return undefined;
|
|
113
|
+
atomicWriteFileSync(file, JSON.stringify(view), 'utf8');
|
|
114
|
+
return view;
|
|
115
|
+
}, { realpath: false, acquireTimeoutMs: 0 });
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/** Preflight BEFORE even the PID-keyed legacy lifecycle lock is inspected.
|
|
122
|
+
* The same decision is repeated under that lock before daemon state changes. */
|
|
123
|
+
export function daemonProcessViewAllowed() {
|
|
124
|
+
const view = currentProcessView();
|
|
125
|
+
if (!view)
|
|
126
|
+
return false;
|
|
127
|
+
if (process.platform !== 'linux')
|
|
128
|
+
return true;
|
|
129
|
+
try {
|
|
130
|
+
const file = path.join(getTerminalsDir(), 'process-view.json');
|
|
131
|
+
if (!fs.existsSync(file))
|
|
132
|
+
return !hasLegacyState() || isInitialPidNamespace(view) || verifiedLegacyDaemon();
|
|
133
|
+
const owner = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
134
|
+
if (sameProcessView(owner, view))
|
|
135
|
+
return true;
|
|
136
|
+
return typeof owner.bootId === 'string' && !!owner.bootId && owner.bootId !== view.bootId
|
|
137
|
+
&& (isInitialPidNamespace(view) || verifiedLegacyDaemon());
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/** Called by the canonical daemon writer before lifecycle mutation.
|
|
144
|
+
* This is a writer statement, not an observer's guess about a numeric PID.
|
|
145
|
+
* Existing same-boot ownership cannot be taken over from another namespace. */
|
|
146
|
+
export function recordDaemonProcessView() {
|
|
147
|
+
const view = currentProcessView();
|
|
148
|
+
if (!view)
|
|
149
|
+
throw new Error('Cannot record daemon ownership from an incoherent process namespace');
|
|
150
|
+
if (process.platform !== 'linux')
|
|
151
|
+
return;
|
|
152
|
+
const file = path.join(getTerminalsDir(), 'process-view.json');
|
|
153
|
+
fs.mkdirSync(getTerminalsDir(), { recursive: true });
|
|
154
|
+
withFileLock(file, () => {
|
|
155
|
+
if (fs.existsSync(file)) {
|
|
156
|
+
const owner = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
157
|
+
if (sameProcessView(owner, view))
|
|
158
|
+
return;
|
|
159
|
+
if (typeof owner.bootId !== 'string' || !owner.bootId || owner.bootId === view.bootId || (!isInitialPidNamespace(view) && !verifiedLegacyDaemon())) {
|
|
160
|
+
throw new Error('Another or unverified process namespace owns host session state; automatic reuse of a private-container HOME across namespaces is unsupported. Run in the owning namespace or use a fresh HOME.');
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else if (hasLegacyState() && !isInitialPidNamespace(view) && !verifiedLegacyDaemon()) {
|
|
164
|
+
throw new Error('Legacy session state requires a verified live canonical daemon before namespace migration');
|
|
165
|
+
}
|
|
166
|
+
atomicWriteFileSync(file, JSON.stringify(view), 'utf8');
|
|
167
|
+
}, { realpath: false, acquireTimeoutMs: 0 });
|
|
168
|
+
}
|
|
169
|
+
export function requireHostProcessView() {
|
|
170
|
+
if (!hostProcessView())
|
|
171
|
+
throw new Error('Host session state is unavailable in this process namespace; read the host daemon snapshot or run sessions on the host.');
|
|
172
|
+
}
|
|
173
|
+
export function requireWriterProcessView() {
|
|
174
|
+
if (!writerProcessView())
|
|
175
|
+
throw new Error('Host session state is unavailable in this process namespace; run the writer in its owning namespace or use a fresh HOME. Automatic reuse of a private-container HOME across namespaces is unsupported.');
|
|
176
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SessionWatchEnvelope, SessionWatchRow } from './watch.js';
|
|
2
|
+
/** Device observations are not sessions: a launcher may observe a peer's run.
|
|
3
|
+
* Keep those observations separately and publish execution-owned state once. */
|
|
4
|
+
export declare class SessionProjection {
|
|
5
|
+
private readonly observations;
|
|
6
|
+
private projected;
|
|
7
|
+
private selected;
|
|
8
|
+
private sequence;
|
|
9
|
+
private readonly streamId;
|
|
10
|
+
/** Only the selected observation may publish execution-owned attention. */
|
|
11
|
+
rowForObservation(scope: string, rowKey: string): SessionWatchRow | undefined;
|
|
12
|
+
apply(event: SessionWatchEnvelope): SessionWatchEnvelope[];
|
|
13
|
+
}
|