@polderlabs/bizar-omp 0.7.0 → 0.7.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 +8 -4
- package/dist/cli/agents-ink.d.ts.map +1 -1
- package/dist/cli/agents-ink.js +5 -3
- package/dist/cli/agents-ink.js.map +1 -1
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +27 -9
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/doctor.d.ts +4 -4
- package/dist/cli/main.js +0 -0
- package/dist/cli/omb.js +0 -0
- package/dist/core/recovery.d.ts.map +1 -1
- package/dist/core/recovery.js +10 -5
- package/dist/core/recovery.js.map +1 -1
- package/dist/core/transitions.d.ts +4 -0
- package/dist/core/transitions.d.ts.map +1 -1
- package/dist/core/transitions.js +12 -2
- package/dist/core/transitions.js.map +1 -1
- package/dist/core/types.d.ts +46 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/extension.d.ts +4 -0
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +308 -23
- package/dist/extension.js.map +1 -1
- package/dist/omp/compatibility.d.ts +5 -5
- package/dist/omp/compatibility.d.ts.map +1 -1
- package/dist/omp/compatibility.js +2 -2
- package/dist/omp/compatibility.js.map +1 -1
- package/dist/omp/daemon-service.d.ts.map +1 -1
- package/dist/omp/daemon-service.js +54 -21
- package/dist/omp/daemon-service.js.map +1 -1
- package/dist/omp/daemon.d.ts.map +1 -1
- package/dist/omp/daemon.js +109 -21
- package/dist/omp/daemon.js.map +1 -1
- package/dist/omp/dashboard-html.js +5 -5
- package/dist/omp/dispatch-admission.js +1 -1
- package/dist/omp/dispatch-admission.js.map +1 -1
- package/dist/omp/model-role-assignment.d.ts +4 -0
- package/dist/omp/model-role-assignment.d.ts.map +1 -1
- package/dist/omp/model-role-assignment.js +52 -7
- package/dist/omp/model-role-assignment.js.map +1 -1
- package/dist/omp/omb-sessions.d.ts +65 -7
- package/dist/omp/omb-sessions.d.ts.map +1 -1
- package/dist/omp/omb-sessions.js +329 -34
- package/dist/omp/omb-sessions.js.map +1 -1
- package/dist/omp/omb-settings.d.ts +15 -1
- package/dist/omp/omb-settings.d.ts.map +1 -1
- package/dist/omp/omb-settings.js +107 -31
- package/dist/omp/omb-settings.js.map +1 -1
- package/dist/omp/rpc.d.ts +8 -0
- package/dist/omp/rpc.d.ts.map +1 -1
- package/dist/omp/session-activity.d.ts +5 -0
- package/dist/omp/session-activity.d.ts.map +1 -1
- package/dist/omp/session-activity.js +17 -0
- package/dist/omp/session-activity.js.map +1 -1
- package/dist/omp/tmux.d.ts +3 -1
- package/dist/omp/tmux.d.ts.map +1 -1
- package/dist/omp/tmux.js +195 -31
- package/dist/omp/tmux.js.map +1 -1
- package/dist/services/candidate-verify.d.ts.map +1 -1
- package/dist/services/candidate-verify.js +44 -1
- package/dist/services/candidate-verify.js.map +1 -1
- package/dist/services/inspector.d.ts +5 -1
- package/dist/services/inspector.d.ts.map +1 -1
- package/dist/services/inspector.js +11 -2
- package/dist/services/inspector.js.map +1 -1
- package/dist/services/native-review-ingest.d.ts +35 -0
- package/dist/services/native-review-ingest.d.ts.map +1 -0
- package/dist/services/native-review-ingest.js +14 -0
- package/dist/services/native-review-ingest.js.map +1 -0
- package/dist/storage/journal-recovery.js +1 -1
- package/dist/storage/journal-recovery.js.map +1 -1
- package/dist/storage/resources.js +1 -1
- package/dist/storage/resources.js.map +1 -1
- package/dist/tools/integrate.d.ts.map +1 -1
- package/dist/tools/integrate.js +13 -0
- package/dist/tools/integrate.js.map +1 -1
- package/dist/tools/workflow.d.ts +9 -0
- package/dist/tools/workflow.d.ts.map +1 -1
- package/dist/tools/workflow.js +25 -2
- package/dist/tools/workflow.js.map +1 -1
- package/docs/compatibility/baseline.json +8 -7
- package/docs/compatibility/supported-surfaces.json +2 -1
- package/docs/development/ci-release-implementation-guide.md +1261 -0
- package/docs/development/contributing-and-releasing.md +117 -0
- package/docs/development/omp-compatibility-update-guide.md +117 -0
- package/docs/releases/0.7.1.md +15 -0
- package/docs/releases/0.7.2.md +32 -0
- package/docs/releases/native-stable.md +11 -1
- package/docs/releases/npm-publishing.md +31 -4
- package/docs/releases/support-matrix.md +1 -1
- package/package.json +2 -1
- package/rules/oflow-gitlab.md +6 -0
- package/skills/oflow-gitlab-context/SKILL.md +49 -0
- package/skills/omp-native-development/SKILL.md +1 -1
- package/skills/omp-native-development/references/accuracy-and-versioning.md +1 -1
- package/skills/omp-native-development/references/source-manifest.json +3 -3
- package/dist/src/cli/agents-ink.d.ts +0 -25
- package/dist/src/cli/agents-ink.js +0 -517
- package/dist/src/cli/agents-ink.js.map +0 -1
- package/dist/src/cli/agents.d.ts +0 -14
- package/dist/src/cli/agents.js +0 -197
- package/dist/src/cli/agents.js.map +0 -1
- package/dist/src/cli/directory-selector.d.ts +0 -60
- package/dist/src/cli/directory-selector.js +0 -208
- package/dist/src/cli/directory-selector.js.map +0 -1
- package/dist/src/cli/doctor.d.ts +0 -41
- package/dist/src/cli/doctor.js +0 -31
- package/dist/src/cli/doctor.js.map +0 -1
- package/dist/src/cli/install.d.ts +0 -129
- package/dist/src/cli/install.js +0 -164
- package/dist/src/cli/install.js.map +0 -1
- package/dist/src/cli/main.d.ts +0 -2
- package/dist/src/cli/main.js +0 -117
- package/dist/src/cli/main.js.map +0 -1
- package/dist/src/cli/migrate.d.ts +0 -18
- package/dist/src/cli/migrate.js +0 -14
- package/dist/src/cli/migrate.js.map +0 -1
- package/dist/src/cli/omb-commands.d.ts +0 -29
- package/dist/src/cli/omb-commands.js +0 -107
- package/dist/src/cli/omb-commands.js.map +0 -1
- package/dist/src/cli/omb-daemon.d.ts +0 -2
- package/dist/src/cli/omb-daemon.js +0 -135
- package/dist/src/cli/omb-daemon.js.map +0 -1
- package/dist/src/cli/omb-dashboard.d.ts +0 -12
- package/dist/src/cli/omb-dashboard.js +0 -113
- package/dist/src/cli/omb-dashboard.js.map +0 -1
- package/dist/src/cli/omb-invocation.d.ts +0 -8
- package/dist/src/cli/omb-invocation.js +0 -41
- package/dist/src/cli/omb-invocation.js.map +0 -1
- package/dist/src/cli/omb-runtime.d.ts +0 -41
- package/dist/src/cli/omb-runtime.js +0 -371
- package/dist/src/cli/omb-runtime.js.map +0 -1
- package/dist/src/cli/omb-tray.d.ts +0 -2
- package/dist/src/cli/omb-tray.js +0 -38
- package/dist/src/cli/omb-tray.js.map +0 -1
- package/dist/src/cli/omb.d.ts +0 -2
- package/dist/src/cli/omb.js +0 -31
- package/dist/src/cli/omb.js.map +0 -1
- package/dist/src/cli/omp-theme.d.ts +0 -17
- package/dist/src/cli/omp-theme.js +0 -22
- package/dist/src/cli/omp-theme.js.map +0 -1
- package/dist/src/cli/process.d.ts +0 -6
- package/dist/src/cli/process.js +0 -54
- package/dist/src/cli/process.js.map +0 -1
- package/dist/src/cli/run.d.ts +0 -2
- package/dist/src/cli/run.js +0 -5
- package/dist/src/cli/run.js.map +0 -1
- package/dist/src/cli/setup-ui.d.ts +0 -37
- package/dist/src/cli/setup-ui.js +0 -90
- package/dist/src/cli/setup-ui.js.map +0 -1
- package/dist/src/core/acceptance.d.ts +0 -32
- package/dist/src/core/acceptance.js +0 -87
- package/dist/src/core/acceptance.js.map +0 -1
- package/dist/src/core/errors.d.ts +0 -20
- package/dist/src/core/errors.js +0 -30
- package/dist/src/core/errors.js.map +0 -1
- package/dist/src/core/evidence.d.ts +0 -10
- package/dist/src/core/evidence.js +0 -35
- package/dist/src/core/evidence.js.map +0 -1
- package/dist/src/core/policies.d.ts +0 -10
- package/dist/src/core/policies.js +0 -60
- package/dist/src/core/policies.js.map +0 -1
- package/dist/src/core/recovery.d.ts +0 -6
- package/dist/src/core/recovery.js +0 -56
- package/dist/src/core/recovery.js.map +0 -1
- package/dist/src/core/transitions.d.ts +0 -13
- package/dist/src/core/transitions.js +0 -59
- package/dist/src/core/transitions.js.map +0 -1
- package/dist/src/core/types.d.ts +0 -256
- package/dist/src/core/types.js +0 -2
- package/dist/src/core/types.js.map +0 -1
- package/dist/src/extension.d.ts +0 -60
- package/dist/src/extension.js +0 -538
- package/dist/src/extension.js.map +0 -1
- package/dist/src/index.d.ts +0 -29
- package/dist/src/index.js +0 -30
- package/dist/src/index.js.map +0 -1
- package/dist/src/omp/autonomous-settings.d.ts +0 -14
- package/dist/src/omp/autonomous-settings.js +0 -65
- package/dist/src/omp/autonomous-settings.js.map +0 -1
- package/dist/src/omp/capabilities.d.ts +0 -23
- package/dist/src/omp/capabilities.js +0 -6
- package/dist/src/omp/capabilities.js.map +0 -1
- package/dist/src/omp/compatibility.d.ts +0 -30
- package/dist/src/omp/compatibility.js +0 -34
- package/dist/src/omp/compatibility.js.map +0 -1
- package/dist/src/omp/completion.d.ts +0 -7
- package/dist/src/omp/completion.js +0 -10
- package/dist/src/omp/completion.js.map +0 -1
- package/dist/src/omp/config.d.ts +0 -10
- package/dist/src/omp/config.js +0 -14
- package/dist/src/omp/config.js.map +0 -1
- package/dist/src/omp/context.d.ts +0 -15
- package/dist/src/omp/context.js +0 -3
- package/dist/src/omp/context.js.map +0 -1
- package/dist/src/omp/daemon-service.d.ts +0 -25
- package/dist/src/omp/daemon-service.js +0 -483
- package/dist/src/omp/daemon-service.js.map +0 -1
- package/dist/src/omp/daemon.d.ts +0 -48
- package/dist/src/omp/daemon.js +0 -194
- package/dist/src/omp/daemon.js.map +0 -1
- package/dist/src/omp/dashboard-html.d.ts +0 -3
- package/dist/src/omp/dashboard-html.js +0 -419
- package/dist/src/omp/dashboard-html.js.map +0 -1
- package/dist/src/omp/dispatch-admission.d.ts +0 -2
- package/dist/src/omp/dispatch-admission.js +0 -12
- package/dist/src/omp/dispatch-admission.js.map +0 -1
- package/dist/src/omp/integration-recovery.d.ts +0 -10
- package/dist/src/omp/integration-recovery.js +0 -18
- package/dist/src/omp/integration-recovery.js.map +0 -1
- package/dist/src/omp/isolation-policy.d.ts +0 -14
- package/dist/src/omp/isolation-policy.js +0 -9
- package/dist/src/omp/isolation-policy.js.map +0 -1
- package/dist/src/omp/lifecycle.d.ts +0 -14
- package/dist/src/omp/lifecycle.js +0 -14
- package/dist/src/omp/lifecycle.js.map +0 -1
- package/dist/src/omp/memory.d.ts +0 -16
- package/dist/src/omp/memory.js +0 -4
- package/dist/src/omp/memory.js.map +0 -1
- package/dist/src/omp/model-role-assignment.d.ts +0 -296
- package/dist/src/omp/model-role-assignment.js +0 -559
- package/dist/src/omp/model-role-assignment.js.map +0 -1
- package/dist/src/omp/model-roles.d.ts +0 -19
- package/dist/src/omp/model-roles.js +0 -6
- package/dist/src/omp/model-roles.js.map +0 -1
- package/dist/src/omp/omb-sessions.d.ts +0 -122
- package/dist/src/omp/omb-sessions.js +0 -512
- package/dist/src/omp/omb-sessions.js.map +0 -1
- package/dist/src/omp/omb-settings.d.ts +0 -35
- package/dist/src/omp/omb-settings.js +0 -104
- package/dist/src/omp/omb-settings.js.map +0 -1
- package/dist/src/omp/result-reconciliation.d.ts +0 -2
- package/dist/src/omp/result-reconciliation.js +0 -9
- package/dist/src/omp/result-reconciliation.js.map +0 -1
- package/dist/src/omp/rpc.d.ts +0 -67
- package/dist/src/omp/rpc.js +0 -4
- package/dist/src/omp/rpc.js.map +0 -1
- package/dist/src/omp/run-log.d.ts +0 -25
- package/dist/src/omp/run-log.js +0 -24
- package/dist/src/omp/run-log.js.map +0 -1
- package/dist/src/omp/session-activity.d.ts +0 -70
- package/dist/src/omp/session-activity.js +0 -361
- package/dist/src/omp/session-activity.js.map +0 -1
- package/dist/src/omp/session-controls.d.ts +0 -17
- package/dist/src/omp/session-controls.js +0 -14
- package/dist/src/omp/session-controls.js.map +0 -1
- package/dist/src/omp/tmux.d.ts +0 -89
- package/dist/src/omp/tmux.js +0 -445
- package/dist/src/omp/tmux.js.map +0 -1
- package/dist/src/omp/tray-icons.d.ts +0 -5
- package/dist/src/omp/tray-icons.js +0 -78
- package/dist/src/omp/tray-icons.js.map +0 -1
- package/dist/src/omp/tray.d.ts +0 -23
- package/dist/src/omp/tray.js +0 -167
- package/dist/src/omp/tray.js.map +0 -1
- package/dist/src/services/budget.d.ts +0 -19
- package/dist/src/services/budget.js +0 -10
- package/dist/src/services/budget.js.map +0 -1
- package/dist/src/services/candidate-local.d.ts +0 -13
- package/dist/src/services/candidate-local.js +0 -15
- package/dist/src/services/candidate-local.js.map +0 -1
- package/dist/src/services/candidates.d.ts +0 -20
- package/dist/src/services/candidates.js +0 -100
- package/dist/src/services/candidates.js.map +0 -1
- package/dist/src/services/evidence-bundle.d.ts +0 -17
- package/dist/src/services/evidence-bundle.js +0 -21
- package/dist/src/services/evidence-bundle.js.map +0 -1
- package/dist/src/services/inspector.d.ts +0 -11
- package/dist/src/services/inspector.js +0 -6
- package/dist/src/services/inspector.js.map +0 -1
- package/dist/src/services/lessons.d.ts +0 -13
- package/dist/src/services/lessons.js +0 -11
- package/dist/src/services/lessons.js.map +0 -1
- package/dist/src/services/projection.d.ts +0 -21
- package/dist/src/services/projection.js +0 -10
- package/dist/src/services/projection.js.map +0 -1
- package/dist/src/services/readiness.d.ts +0 -4
- package/dist/src/services/readiness.js +0 -35
- package/dist/src/services/readiness.js.map +0 -1
- package/dist/src/services/recipes.d.ts +0 -15
- package/dist/src/services/recipes.js +0 -42
- package/dist/src/services/recipes.js.map +0 -1
- package/dist/src/services/recovery.d.ts +0 -19
- package/dist/src/services/recovery.js +0 -9
- package/dist/src/services/recovery.js.map +0 -1
- package/dist/src/services/review.d.ts +0 -15
- package/dist/src/services/review.js +0 -9
- package/dist/src/services/review.js.map +0 -1
- package/dist/src/storage/journal-recovery.d.ts +0 -10
- package/dist/src/storage/journal-recovery.js +0 -33
- package/dist/src/storage/journal-recovery.js.map +0 -1
- package/dist/src/storage/journal.d.ts +0 -12
- package/dist/src/storage/journal.js +0 -82
- package/dist/src/storage/journal.js.map +0 -1
- package/dist/src/storage/migrations.d.ts +0 -22
- package/dist/src/storage/migrations.js +0 -107
- package/dist/src/storage/migrations.js.map +0 -1
- package/dist/src/storage/repository-identity.d.ts +0 -11
- package/dist/src/storage/repository-identity.js +0 -67
- package/dist/src/storage/repository-identity.js.map +0 -1
- package/dist/src/storage/resources.d.ts +0 -66
- package/dist/src/storage/resources.js +0 -148
- package/dist/src/storage/resources.js.map +0 -1
- package/dist/src/tools/evidence.d.ts +0 -8
- package/dist/src/tools/evidence.js +0 -9
- package/dist/src/tools/evidence.js.map +0 -1
- package/dist/src/tools/integrate.d.ts +0 -13
- package/dist/src/tools/integrate.js +0 -90
- package/dist/src/tools/integrate.js.map +0 -1
- package/dist/src/tools/result.d.ts +0 -9
- package/dist/src/tools/result.js +0 -2
- package/dist/src/tools/result.js.map +0 -1
- package/dist/src/tools/verify.d.ts +0 -13
- package/dist/src/tools/verify.js +0 -61
- package/dist/src/tools/verify.js.map +0 -1
- package/dist/src/tools/workflow.d.ts +0 -8
- package/dist/src/tools/workflow.js +0 -65
- package/dist/src/tools/workflow.js.map +0 -1
- package/dist/src/workflows/direct.d.ts +0 -9
- package/dist/src/workflows/direct.js +0 -2
- package/dist/src/workflows/direct.js.map +0 -1
- package/dist/src/workflows/implement.d.ts +0 -2
- package/dist/src/workflows/implement.js +0 -4
- package/dist/src/workflows/implement.js.map +0 -1
- package/dist/src/workflows/plan.d.ts +0 -17
- package/dist/src/workflows/plan.js +0 -6
- package/dist/src/workflows/plan.js.map +0 -1
- package/dist/src/workflows/research.d.ts +0 -15
- package/dist/src/workflows/research.js +0 -2
- package/dist/src/workflows/research.js.map +0 -1
- package/dist/src/workflows/review.d.ts +0 -15
- package/dist/src/workflows/review.js +0 -2
- package/dist/src/workflows/review.js.map +0 -1
- package/dist/src/workflows/verify.d.ts +0 -9
- package/dist/src/workflows/verify.js +0 -2
- package/dist/src/workflows/verify.js.map +0 -1
- package/dist/tests/acceptance.test.d.ts +0 -1
- package/dist/tests/acceptance.test.js +0 -27
- package/dist/tests/acceptance.test.js.map +0 -1
- package/dist/tests/agents.test.d.ts +0 -1
- package/dist/tests/agents.test.js +0 -369
- package/dist/tests/agents.test.js.map +0 -1
- package/dist/tests/candidates.test.d.ts +0 -1
- package/dist/tests/candidates.test.js +0 -60
- package/dist/tests/candidates.test.js.map +0 -1
- package/dist/tests/core.test.d.ts +0 -1
- package/dist/tests/core.test.js +0 -39
- package/dist/tests/core.test.js.map +0 -1
- package/dist/tests/daemon.test.d.ts +0 -1
- package/dist/tests/daemon.test.js +0 -157
- package/dist/tests/daemon.test.js.map +0 -1
- package/dist/tests/dashboard.test.d.ts +0 -1
- package/dist/tests/dashboard.test.js +0 -414
- package/dist/tests/dashboard.test.js.map +0 -1
- package/dist/tests/directory-selector.test.d.ts +0 -1
- package/dist/tests/directory-selector.test.js +0 -93
- package/dist/tests/directory-selector.test.js.map +0 -1
- package/dist/tests/doctor.test.d.ts +0 -1
- package/dist/tests/doctor.test.js +0 -32
- package/dist/tests/doctor.test.js.map +0 -1
- package/dist/tests/install.test.d.ts +0 -1
- package/dist/tests/install.test.js +0 -101
- package/dist/tests/install.test.js.map +0 -1
- package/dist/tests/integration.test.d.ts +0 -1
- package/dist/tests/integration.test.js +0 -49
- package/dist/tests/integration.test.js.map +0 -1
- package/dist/tests/journal.test.d.ts +0 -1
- package/dist/tests/journal.test.js +0 -50
- package/dist/tests/journal.test.js.map +0 -1
- package/dist/tests/model-role-assignment.test.d.ts +0 -1
- package/dist/tests/model-role-assignment.test.js +0 -294
- package/dist/tests/model-role-assignment.test.js.map +0 -1
- package/dist/tests/omb-runtime.test.d.ts +0 -1
- package/dist/tests/omb-runtime.test.js +0 -554
- package/dist/tests/omb-runtime.test.js.map +0 -1
- package/dist/tests/omb-session-actions.test.d.ts +0 -1
- package/dist/tests/omb-session-actions.test.js +0 -191
- package/dist/tests/omb-session-actions.test.js.map +0 -1
- package/dist/tests/omb-settings.test.d.ts +0 -1
- package/dist/tests/omb-settings.test.js +0 -82
- package/dist/tests/omb-settings.test.js.map +0 -1
- package/dist/tests/omp-contract.test.d.ts +0 -1
- package/dist/tests/omp-contract.test.js +0 -362
- package/dist/tests/omp-contract.test.js.map +0 -1
- package/dist/tests/process.test.d.ts +0 -1
- package/dist/tests/process.test.js +0 -12
- package/dist/tests/process.test.js.map +0 -1
- package/dist/tests/psmux-windows.test.d.ts +0 -1
- package/dist/tests/psmux-windows.test.js +0 -105
- package/dist/tests/psmux-windows.test.js.map +0 -1
- package/dist/tests/recovery.test.d.ts +0 -1
- package/dist/tests/recovery.test.js +0 -9
- package/dist/tests/recovery.test.js.map +0 -1
- package/dist/tests/resources.test.d.ts +0 -1
- package/dist/tests/resources.test.js +0 -55
- package/dist/tests/resources.test.js.map +0 -1
- package/dist/tests/session-activity.test.d.ts +0 -1
- package/dist/tests/session-activity.test.js +0 -159
- package/dist/tests/session-activity.test.js.map +0 -1
- package/dist/tests/setup-ui.test.d.ts +0 -1
- package/dist/tests/setup-ui.test.js +0 -37
- package/dist/tests/setup-ui.test.js.map +0 -1
- package/dist/tests/storage-integrity.test.d.ts +0 -1
- package/dist/tests/storage-integrity.test.js +0 -88
- package/dist/tests/storage-integrity.test.js.map +0 -1
- package/dist/tests/tmux.test.d.ts +0 -1
- package/dist/tests/tmux.test.js +0 -239
- package/dist/tests/tmux.test.js.map +0 -1
- package/dist/tests/tray.test.d.ts +0 -1
- package/dist/tests/tray.test.js +0 -37
- package/dist/tests/tray.test.js.map +0 -1
- package/dist/tests/verification.test.d.ts +0 -1
- package/dist/tests/verification.test.js +0 -61
- package/dist/tests/verification.test.js.map +0 -1
- package/dist/tests/workflow-features.test.d.ts +0 -1
- package/dist/tests/workflow-features.test.js +0 -82
- package/dist/tests/workflow-features.test.js.map +0 -1
- package/dist/tests/workflow-safety.test.d.ts +0 -1
- package/dist/tests/workflow-safety.test.js +0 -57
- package/dist/tests/workflow-safety.test.js.map +0 -1
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { type OmbSessionActivity } from "./session-activity.js";
|
|
2
|
-
export declare const BIZAR_SESSION_PREFIX = "bizar-";
|
|
3
|
-
/**
|
|
4
|
-
* Connection and activity state of one Bizar-owned session.
|
|
5
|
-
*
|
|
6
|
-
* `working` and `waiting` describe what the agent is doing, `connected` and
|
|
7
|
-
* `disconnected` describe whether an interactive client is attached to an idle
|
|
8
|
-
* session, and `stopped` means no host is observed and the journal is silent.
|
|
9
|
-
*/
|
|
10
|
-
export type OmbSessionState = "working" | "waiting" | "connected" | "disconnected" | "stopped";
|
|
11
|
-
export interface OmbSessionInfo {
|
|
12
|
-
name: string;
|
|
13
|
-
cwd: string;
|
|
14
|
-
project: string;
|
|
15
|
-
id: string;
|
|
16
|
-
/**
|
|
17
|
-
* Human label for this row: the native OMP title when the session has one,
|
|
18
|
-
* otherwise a readable derivation (first prompt, generated session label, or
|
|
19
|
-
* project-scoped fallback). Every row carries it, so no renderer has to
|
|
20
|
-
* invent a name from `id`.
|
|
21
|
-
*/
|
|
22
|
-
displayName?: string;
|
|
23
|
-
state: OmbSessionState;
|
|
24
|
-
/** Privacy-safe live activity, when the session journal exposes it. */
|
|
25
|
-
activity?: OmbSessionActivity;
|
|
26
|
-
/**
|
|
27
|
-
* True when tmux currently hosts this session.
|
|
28
|
-
*
|
|
29
|
-
* A live OMP process whose host `omb` never created, or whose host died
|
|
30
|
-
* while the agent kept working, has no attachable tmux session. Absent for
|
|
31
|
-
* synthetic records, which are treated as hosted.
|
|
32
|
-
*/
|
|
33
|
-
hosted?: boolean;
|
|
34
|
-
command: string;
|
|
35
|
-
pid: string;
|
|
36
|
-
/** Native OMP session id, when its journal is available. */
|
|
37
|
-
nativeId?: string;
|
|
38
|
-
/** Native OMP session title, when configured or auto-generated. */
|
|
39
|
-
nativeName?: string;
|
|
40
|
-
/** First user prompt, used as a stable local fallback before auto-titling. */
|
|
41
|
-
firstMessage?: string;
|
|
42
|
-
/** True when this host has a Bizar-owned isolated native session directory. */
|
|
43
|
-
nativeSessionAvailable?: boolean;
|
|
44
|
-
/**
|
|
45
|
-
* True when tmux has a client attached to this session right now.
|
|
46
|
-
*
|
|
47
|
-
* Distinct from `state`: an attached session that is still working reports
|
|
48
|
-
* `working`, so only this field answers "would stopping it disconnect
|
|
49
|
-
* somebody?".
|
|
50
|
-
*/
|
|
51
|
-
attached?: boolean;
|
|
52
|
-
createdAt?: number;
|
|
53
|
-
lastAttachedAt?: number;
|
|
54
|
-
}
|
|
55
|
-
export interface ListOmbSessionsOptions {
|
|
56
|
-
/** Include Bizar sessions whose tmux host exited and whose journal is silent. Defaults to false. */
|
|
57
|
-
includeStopped?: boolean;
|
|
58
|
-
}
|
|
59
|
-
/** Keep native OMP journals separate so each durable `omb` host has one exact session. */
|
|
60
|
-
export declare function ombSessionDir(session: string, env?: NodeJS.ProcessEnv): string;
|
|
61
|
-
/**
|
|
62
|
-
* Whether a name is one of the sessions Bizar owns, and may therefore kill,
|
|
63
|
-
* rename, tombstone, or adopt as its own native journal.
|
|
64
|
-
*/
|
|
65
|
-
export declare function isOmbSessionName(session: string): boolean;
|
|
66
|
-
/** Keep an intentionally removed session out of journal-based discovery. */
|
|
67
|
-
export declare function markOmbSessionDeleted(session: string, env?: NodeJS.ProcessEnv): boolean;
|
|
68
|
-
/** Reusing a session name makes its native journal discoverable again. */
|
|
69
|
-
export declare function clearOmbSessionDeleted(session: string, env?: NodeJS.ProcessEnv): void;
|
|
70
|
-
/** Native OMP title first, then a deterministic prompt/project fallback. */
|
|
71
|
-
export declare function ombSessionDisplayName(session: Pick<OmbSessionInfo, "project" | "id" | "nativeName" | "firstMessage" | "nativeSessionAvailable">): string;
|
|
72
|
-
/**
|
|
73
|
-
* Resolve the tmux-compatible multiplexer binary. `BIZAR_TMUX_BIN` always
|
|
74
|
-
* wins. On Windows, psmux is the supported native multiplexer (it ships a
|
|
75
|
-
* `tmux` command alias, but resolving `tmux` on PATH could pick unrelated
|
|
76
|
-
* binaries), so prefer `psmux` and fall back to the generic `tmux` name;
|
|
77
|
-
* elsewhere the standard `tmux` binary is used.
|
|
78
|
-
*/
|
|
79
|
-
export declare function resolveMultiplexerBin(env?: NodeJS.ProcessEnv): string;
|
|
80
|
-
/**
|
|
81
|
-
* Resolve the hub state from tmux liveness, client attachment, and journal
|
|
82
|
-
* activity.
|
|
83
|
-
*
|
|
84
|
-
* Work wins over attachment: a detached client must never hide an agent that
|
|
85
|
-
* is still processing, which is the failure this hub exists to prevent.
|
|
86
|
-
* `waiting` refines an attached session that finished its turn, `connected`
|
|
87
|
-
* covers an attached session with no structured activity yet, and
|
|
88
|
-
* `disconnected` covers a live session with no client and no work in flight.
|
|
89
|
-
*/
|
|
90
|
-
export declare function ombSessionState(input: {
|
|
91
|
-
dead: boolean;
|
|
92
|
-
attached: boolean;
|
|
93
|
-
activity?: OmbSessionActivity;
|
|
94
|
-
}): OmbSessionState;
|
|
95
|
-
/**
|
|
96
|
-
* Session names whose journal the pane of one live tmux session writes.
|
|
97
|
-
*
|
|
98
|
-
* Deletion uses this before killing the session, because a renamed session's
|
|
99
|
-
* journal lives in the directory it was started with rather than the one named
|
|
100
|
-
* after the current tmux session.
|
|
101
|
-
*/
|
|
102
|
-
export declare function ombSessionBoundNames(session: string, cwd: string, env?: NodeJS.ProcessEnv): Promise<string[]>;
|
|
103
|
-
/**
|
|
104
|
-
* Where this process runs from, as far as the multiplexer can tell.
|
|
105
|
-
*
|
|
106
|
-
* `omb stop` needs `unknown` to exist: when `TMUX` is set but the multiplexer
|
|
107
|
-
* cannot answer, the hosting session is unidentified, and a kill verb must
|
|
108
|
-
* assume that one of the sessions it is about to stop could be its own.
|
|
109
|
-
*/
|
|
110
|
-
export type OmbHostSession = {
|
|
111
|
-
kind: "not-bizar";
|
|
112
|
-
} | {
|
|
113
|
-
kind: "bizar";
|
|
114
|
-
name: string;
|
|
115
|
-
} | {
|
|
116
|
-
kind: "unknown";
|
|
117
|
-
};
|
|
118
|
-
export declare function currentOmbHostSession(cwd?: string, env?: NodeJS.ProcessEnv): Promise<OmbHostSession>;
|
|
119
|
-
/** Discover Bizar-owned tmux sessions without touching unrelated tmux sessions. */
|
|
120
|
-
export declare function listOmbSessions(cwd?: string, env?: NodeJS.ProcessEnv, options?: ListOmbSessionsOptions): Promise<OmbSessionInfo[]>;
|
|
121
|
-
/** Return the most recently attached live session for one exact project path. */
|
|
122
|
-
export declare function findLastOmbSession(cwd: string, env?: NodeJS.ProcessEnv): Promise<OmbSessionInfo | undefined>;
|
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { access, readdir, stat } from "node:fs/promises";
|
|
3
|
-
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { basename, join, relative, resolve } from "node:path";
|
|
5
|
-
import { homedir, tmpdir } from "node:os";
|
|
6
|
-
import { deriveSessionActivity, listSessionJournals, readJournalHead, readJournalTail, } from "./session-activity.js";
|
|
7
|
-
export const BIZAR_SESSION_PREFIX = "bizar-";
|
|
8
|
-
/** Most recent stopped sessions to surface when stopped sessions are enabled. */
|
|
9
|
-
const STOPPED_SESSION_LIMIT = 6;
|
|
10
|
-
const DELETED_SESSION_MARKER = ".bizar-deleted";
|
|
11
|
-
function nativeSessionRoot(env) {
|
|
12
|
-
const stateHome = env.XDG_STATE_HOME || join(env.HOME || homedir(), ".local", "state");
|
|
13
|
-
return join(stateHome, "bizar-omp", "native-sessions");
|
|
14
|
-
}
|
|
15
|
-
/** Keep native OMP journals separate so each durable `omb` host has one exact session. */
|
|
16
|
-
export function ombSessionDir(session, env = process.env) {
|
|
17
|
-
return join(nativeSessionRoot(env), session);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Whether a name is one of the sessions Bizar owns, and may therefore kill,
|
|
21
|
-
* rename, tombstone, or adopt as its own native journal.
|
|
22
|
-
*/
|
|
23
|
-
export function isOmbSessionName(session) {
|
|
24
|
-
return /^bizar-[A-Za-z0-9_.-]+$/.test(session);
|
|
25
|
-
}
|
|
26
|
-
function markDirectoryDeleted(directory) {
|
|
27
|
-
try {
|
|
28
|
-
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
29
|
-
writeFileSync(join(directory, DELETED_SESSION_MARKER), `${Date.now()}\n`, { mode: 0o600 });
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/** Keep an intentionally removed session out of journal-based discovery. */
|
|
37
|
-
export function markOmbSessionDeleted(session, env = process.env) {
|
|
38
|
-
return isOmbSessionName(session) && markDirectoryDeleted(ombSessionDir(session, env));
|
|
39
|
-
}
|
|
40
|
-
/** Reusing a session name makes its native journal discoverable again. */
|
|
41
|
-
export function clearOmbSessionDeleted(session, env = process.env) {
|
|
42
|
-
if (!isOmbSessionName(session))
|
|
43
|
-
return;
|
|
44
|
-
try {
|
|
45
|
-
rmSync(join(ombSessionDir(session, env), DELETED_SESSION_MARKER), { force: true });
|
|
46
|
-
}
|
|
47
|
-
catch { /* discovery remains conservative */ }
|
|
48
|
-
}
|
|
49
|
-
async function isOmbSessionDeleted(session, env) {
|
|
50
|
-
try {
|
|
51
|
-
await access(join(ombSessionDir(session, env), DELETED_SESSION_MARKER));
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function ompAgentDir(env) {
|
|
59
|
-
if (env.PI_CODING_AGENT_DIR)
|
|
60
|
-
return resolve(env.PI_CODING_AGENT_DIR);
|
|
61
|
-
return join(env.HOME || homedir(), env.PI_CONFIG_DIR || ".omp", "agent");
|
|
62
|
-
}
|
|
63
|
-
function defaultOmpSessionDir(cwd, env) {
|
|
64
|
-
const resolvedCwd = resolve(cwd);
|
|
65
|
-
const home = resolve(env.HOME || homedir());
|
|
66
|
-
const temp = resolve(tmpdir());
|
|
67
|
-
const encode = (value) => value.replace(/[\\/:]/g, "-");
|
|
68
|
-
const homeRelative = relative(home, resolvedCwd);
|
|
69
|
-
if (homeRelative === "" || (!homeRelative.startsWith("..") && !homeRelative.startsWith("/"))) {
|
|
70
|
-
return join(ompAgentDir(env), "sessions", homeRelative ? `-${encode(homeRelative)}` : "-");
|
|
71
|
-
}
|
|
72
|
-
const tempRelative = relative(temp, resolvedCwd);
|
|
73
|
-
if (tempRelative === "" || (!tempRelative.startsWith("..") && !tempRelative.startsWith("/"))) {
|
|
74
|
-
return join(ompAgentDir(env), "sessions", tempRelative ? `-tmp-${encode(tempRelative)}` : "-tmp");
|
|
75
|
-
}
|
|
76
|
-
return join(ompAgentDir(env), "sessions", `--${encode(resolvedCwd).replace(/^-/, "")}--`);
|
|
77
|
-
}
|
|
78
|
-
function cleanText(value) {
|
|
79
|
-
if (typeof value !== "string")
|
|
80
|
-
return undefined;
|
|
81
|
-
const cleaned = value
|
|
82
|
-
.split(/\r?\n/, 1)[0]
|
|
83
|
-
.replace(/[\x00-\x1F\x7F]/g, "")
|
|
84
|
-
.replace(/\s+/g, " ")
|
|
85
|
-
.trim();
|
|
86
|
-
return cleaned || undefined;
|
|
87
|
-
}
|
|
88
|
-
function asRecord(value) {
|
|
89
|
-
return typeof value === "object" && value !== null ? value : undefined;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Parse one journal's session header, title, and first user prompt.
|
|
93
|
-
*
|
|
94
|
-
* Current journals open with a `title` entry that is rewritten in place, so
|
|
95
|
-
* the session header is the first `session` entry rather than the first line.
|
|
96
|
-
*/
|
|
97
|
-
async function readNativeSessionFile(journal) {
|
|
98
|
-
const content = await readJournalHead(journal);
|
|
99
|
-
if (!content)
|
|
100
|
-
return undefined;
|
|
101
|
-
let header;
|
|
102
|
-
const entries = [];
|
|
103
|
-
for (const line of content.split("\n")) {
|
|
104
|
-
const trimmed = line.trim();
|
|
105
|
-
if (!trimmed || trimmed[0] !== "{")
|
|
106
|
-
continue;
|
|
107
|
-
let entry;
|
|
108
|
-
try {
|
|
109
|
-
entry = JSON.parse(trimmed);
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
// A partially written final line must not hide the entries before it.
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (!header && entry.type === "session") {
|
|
116
|
-
header = entry;
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
entries.push(entry);
|
|
120
|
-
}
|
|
121
|
-
if (!header)
|
|
122
|
-
return undefined;
|
|
123
|
-
let latestTitle = cleanText(header.title);
|
|
124
|
-
let latestTitleAt = Number.NEGATIVE_INFINITY;
|
|
125
|
-
let firstMessage;
|
|
126
|
-
for (const entry of entries) {
|
|
127
|
-
if (entry.type === "title" || entry.type === "title_change") {
|
|
128
|
-
const title = cleanText(entry.title);
|
|
129
|
-
const raw = entry.updatedAt ?? entry.timestamp;
|
|
130
|
-
const at = typeof raw === "string" ? Date.parse(raw) : NaN;
|
|
131
|
-
// OMP rewrites the opening `title` entry in place and appends
|
|
132
|
-
// `title_change` history, so the newest timestamp — not file order —
|
|
133
|
-
// names the title the session currently has.
|
|
134
|
-
if (title && (!Number.isFinite(at) || at >= latestTitleAt)) {
|
|
135
|
-
latestTitle = title;
|
|
136
|
-
if (Number.isFinite(at))
|
|
137
|
-
latestTitleAt = at;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (firstMessage || entry.type !== "message")
|
|
141
|
-
continue;
|
|
142
|
-
const message = asRecord(entry.message);
|
|
143
|
-
if (message?.role !== "user")
|
|
144
|
-
continue;
|
|
145
|
-
if (typeof message.content === "string")
|
|
146
|
-
firstMessage = cleanText(message.content);
|
|
147
|
-
else if (Array.isArray(message.content)) {
|
|
148
|
-
firstMessage = cleanText(message.content
|
|
149
|
-
.filter(item => asRecord(item)?.type === "text")
|
|
150
|
-
.map(item => asRecord(item)?.text)
|
|
151
|
-
.filter((item) => typeof item === "string")
|
|
152
|
-
.join(" "));
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const timestamp = typeof header.timestamp === "string" ? Date.parse(header.timestamp) : NaN;
|
|
156
|
-
return {
|
|
157
|
-
id: cleanText(header.id),
|
|
158
|
-
title: latestTitle,
|
|
159
|
-
cwd: cleanText(header.cwd),
|
|
160
|
-
firstMessage,
|
|
161
|
-
createdAt: Number.isFinite(timestamp) ? Math.floor(timestamp / 1000) : undefined,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
/** Metadata plus live activity for a Bizar-owned native session directory. */
|
|
165
|
-
async function readNativeSessionSnapshot(sessionDir, now) {
|
|
166
|
-
const journals = await listSessionJournals(sessionDir);
|
|
167
|
-
const newest = journals.at(-1);
|
|
168
|
-
if (!newest)
|
|
169
|
-
return {};
|
|
170
|
-
const [entries, modifiedAt, ...candidates] = await Promise.all([
|
|
171
|
-
readJournalTail(newest),
|
|
172
|
-
stat(newest).then(file => file.mtimeMs).catch(() => undefined),
|
|
173
|
-
...journals.slice(-3).reverse().map(journal => readNativeSessionFile(journal)),
|
|
174
|
-
]);
|
|
175
|
-
let metadata;
|
|
176
|
-
for (const candidate of candidates) {
|
|
177
|
-
if (candidate) {
|
|
178
|
-
metadata = candidate;
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return {
|
|
183
|
-
metadata,
|
|
184
|
-
activity: entries.length > 0 ? deriveSessionActivity(entries, { now, fallbackUpdatedAt: modifiedAt }) : undefined,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
async function readLegacyNativeSessionMetadata(cwd, sessionCreatedAt, env) {
|
|
188
|
-
const sessionDir = defaultOmpSessionDir(cwd, env);
|
|
189
|
-
const journals = await listSessionJournals(sessionDir);
|
|
190
|
-
if (journals.length === 0)
|
|
191
|
-
return undefined;
|
|
192
|
-
const candidates = (await Promise.all(journals.map(async (journal) => {
|
|
193
|
-
const metadata = await readNativeSessionFile(journal);
|
|
194
|
-
return metadata ? { journal, metadata } : undefined;
|
|
195
|
-
}))).filter((candidate) => Boolean(candidate));
|
|
196
|
-
if (candidates.length === 0)
|
|
197
|
-
return undefined;
|
|
198
|
-
if (candidates.length === 1 || sessionCreatedAt === undefined)
|
|
199
|
-
return candidates[0]?.metadata;
|
|
200
|
-
candidates.sort((a, b) => Math.abs((a.metadata.createdAt ?? 0) - sessionCreatedAt) - Math.abs((b.metadata.createdAt ?? 0) - sessionCreatedAt));
|
|
201
|
-
return candidates[0]?.metadata;
|
|
202
|
-
}
|
|
203
|
-
function compactPrompt(prompt) {
|
|
204
|
-
const words = prompt.replace(/^[-*#>]+\s*/, "").split(/\s+/).filter(Boolean);
|
|
205
|
-
const compact = words.slice(0, 7).join(" ").replace(/[.!?]+$/, "");
|
|
206
|
-
return compact.length > 48 ? `${compact.slice(0, 47).trimEnd()}…` : compact;
|
|
207
|
-
}
|
|
208
|
-
function generatedSessionLabel(project, id) {
|
|
209
|
-
const match = id.match(/^s-(.+)-([a-z0-9]{4,})$/);
|
|
210
|
-
if (!match)
|
|
211
|
-
return undefined;
|
|
212
|
-
const stem = match[1];
|
|
213
|
-
const normalizedProject = project.toLocaleLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
214
|
-
if (stem === "session" || stem === normalizedProject || /^[a-z0-9]{7,}$/.test(stem))
|
|
215
|
-
return `New ${project} session`;
|
|
216
|
-
return `${project} · ${stem.replace(/-/g, " ")}`;
|
|
217
|
-
}
|
|
218
|
-
/** Session ids that carry no readable meaning on their own. */
|
|
219
|
-
const OPAQUE_SESSION_ID = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{16,})$/i;
|
|
220
|
-
/** Native OMP title first, then a deterministic prompt/project fallback. */
|
|
221
|
-
export function ombSessionDisplayName(session) {
|
|
222
|
-
if (session.nativeName)
|
|
223
|
-
return session.nativeName;
|
|
224
|
-
if (session.firstMessage)
|
|
225
|
-
return compactPrompt(session.firstMessage);
|
|
226
|
-
const generatedLabel = generatedSessionLabel(session.project, session.id);
|
|
227
|
-
if (generatedLabel)
|
|
228
|
-
return generatedLabel;
|
|
229
|
-
if (session.nativeSessionAvailable)
|
|
230
|
-
return `New ${session.project} session`;
|
|
231
|
-
// A raw UUID (or another opaque token) is never a readable session name.
|
|
232
|
-
if (OPAQUE_SESSION_ID.test(session.id))
|
|
233
|
-
return `New ${session.project} session`;
|
|
234
|
-
return `${session.project}/${session.id || "main"}`;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Resolve the tmux-compatible multiplexer binary. `BIZAR_TMUX_BIN` always
|
|
238
|
-
* wins. On Windows, psmux is the supported native multiplexer (it ships a
|
|
239
|
-
* `tmux` command alias, but resolving `tmux` on PATH could pick unrelated
|
|
240
|
-
* binaries), so prefer `psmux` and fall back to the generic `tmux` name;
|
|
241
|
-
* elsewhere the standard `tmux` binary is used.
|
|
242
|
-
*/
|
|
243
|
-
export function resolveMultiplexerBin(env = process.env) {
|
|
244
|
-
if (env.BIZAR_TMUX_BIN)
|
|
245
|
-
return env.BIZAR_TMUX_BIN;
|
|
246
|
-
return process.platform === "win32" ? "psmux" : "tmux";
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Resolve the hub state from tmux liveness, client attachment, and journal
|
|
250
|
-
* activity.
|
|
251
|
-
*
|
|
252
|
-
* Work wins over attachment: a detached client must never hide an agent that
|
|
253
|
-
* is still processing, which is the failure this hub exists to prevent.
|
|
254
|
-
* `waiting` refines an attached session that finished its turn, `connected`
|
|
255
|
-
* covers an attached session with no structured activity yet, and
|
|
256
|
-
* `disconnected` covers a live session with no client and no work in flight.
|
|
257
|
-
*/
|
|
258
|
-
export function ombSessionState(input) {
|
|
259
|
-
if (input.dead)
|
|
260
|
-
return "stopped";
|
|
261
|
-
const activity = input.activity;
|
|
262
|
-
if (activity && activity.phase !== "unknown" && !activity.awaitingInput)
|
|
263
|
-
return "working";
|
|
264
|
-
if (!input.attached)
|
|
265
|
-
return "disconnected";
|
|
266
|
-
return activity?.awaitingInput ? "waiting" : "connected";
|
|
267
|
-
}
|
|
268
|
-
const STATE_RANK = {
|
|
269
|
-
working: 0,
|
|
270
|
-
waiting: 1,
|
|
271
|
-
connected: 2,
|
|
272
|
-
disconnected: 3,
|
|
273
|
-
stopped: 4,
|
|
274
|
-
};
|
|
275
|
-
function exitCode(code, signal) {
|
|
276
|
-
if (code !== null)
|
|
277
|
-
return code;
|
|
278
|
-
return signal ? 1 : 1;
|
|
279
|
-
}
|
|
280
|
-
function readTmux(command, args, cwd, env) {
|
|
281
|
-
const child = spawn(command, args, { cwd, env, stdio: ["ignore", "pipe", "ignore"] });
|
|
282
|
-
let output = "";
|
|
283
|
-
child.stdout?.setEncoding("utf8");
|
|
284
|
-
child.stdout?.on("data", chunk => { output += chunk; });
|
|
285
|
-
return new Promise((resolve, reject) => {
|
|
286
|
-
// A missing multiplexer binary means "no sessions", not a crash:
|
|
287
|
-
// discovery callers treat any nonzero code as an empty listing. Any
|
|
288
|
-
// other spawn failure (EACCES, EPERM, ...) is still a hard error.
|
|
289
|
-
child.once("error", (error) => {
|
|
290
|
-
if (error.code === "ENOENT" || error.code === "EINVAL")
|
|
291
|
-
resolve({ code: 127, output: "" });
|
|
292
|
-
else
|
|
293
|
-
reject(error);
|
|
294
|
-
});
|
|
295
|
-
child.once("close", (code, signal) => resolve({ code: exitCode(code, signal), output }));
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
function sessionId(name) {
|
|
299
|
-
const match = name.match(/-[a-f0-9]{10}(?:-(.*))?$/);
|
|
300
|
-
return match?.[1] || "main";
|
|
301
|
-
}
|
|
302
|
-
/** Project slug encoded in the Bizar session name, without the digest. */
|
|
303
|
-
function sessionProject(name) {
|
|
304
|
-
const trimmed = name.slice(BIZAR_SESSION_PREFIX.length);
|
|
305
|
-
return trimmed.replace(/-[a-f0-9]{10}(?:-.*)?$/, "") || trimmed || "session";
|
|
306
|
-
}
|
|
307
|
-
/**
|
|
308
|
-
* One pane's fields, including the command tmux started it with. Bizar launches
|
|
309
|
-
* every host as `omp --session-dir <native root>/<session>`, so that command is
|
|
310
|
-
* the only exact record of which journal a live row owns.
|
|
311
|
-
*/
|
|
312
|
-
const PANE_FORMAT = "#{pane_dead}\t#{pane_current_path}\t#{pane_current_command}\t#{pane_pid}\t#{pane_start_command}";
|
|
313
|
-
/**
|
|
314
|
-
* Session whose native directory a pane command declares.
|
|
315
|
-
*
|
|
316
|
-
* A renamed tmux session keeps the directory its host was started with, so
|
|
317
|
-
* discovery reads the binding from the pane instead of assuming the directory
|
|
318
|
-
* matches the session name. Paths outside the Bizar native root, or names
|
|
319
|
-
* Bizar does not own, are ignored so unrelated OMP hosts are never adopted.
|
|
320
|
-
*/
|
|
321
|
-
function paneBoundSession(startCommand, env) {
|
|
322
|
-
const declared = startCommand?.match(/--session-dir(?:=|\s+)(?:"([^"]*)"|'([^']*)'|(\S+))/);
|
|
323
|
-
const value = declared?.[1] ?? declared?.[2] ?? declared?.[3];
|
|
324
|
-
if (!value)
|
|
325
|
-
return undefined;
|
|
326
|
-
const directory = relative(resolve(nativeSessionRoot(env)), resolve(value));
|
|
327
|
-
if (!directory || directory.startsWith("..") || directory.includes("/") || !isOmbSessionName(directory))
|
|
328
|
-
return undefined;
|
|
329
|
-
return directory;
|
|
330
|
-
}
|
|
331
|
-
function parsePane(output, env) {
|
|
332
|
-
const [line = ""] = output.trim().split("\n");
|
|
333
|
-
const [dead, cwd, command, pid, startCommand] = line.split("\t");
|
|
334
|
-
return {
|
|
335
|
-
dead: dead === "1",
|
|
336
|
-
cwd: cwd || "?",
|
|
337
|
-
command: command || "?",
|
|
338
|
-
pid: pid || "?",
|
|
339
|
-
bound: paneBoundSession(startCommand, env),
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
function parseSessionList(output) {
|
|
343
|
-
return output
|
|
344
|
-
.split("\n")
|
|
345
|
-
.map(line => line.trim())
|
|
346
|
-
.filter(Boolean)
|
|
347
|
-
.map(line => line.split("\t"))
|
|
348
|
-
.filter(parts => parts[0]?.startsWith(BIZAR_SESSION_PREFIX))
|
|
349
|
-
.map(parts => ({
|
|
350
|
-
name: parts[0],
|
|
351
|
-
createdAt: Number.isFinite(Number(parts[1])) ? Number(parts[1]) : undefined,
|
|
352
|
-
lastAttachedAt: Number.isFinite(Number(parts[2])) ? Number(parts[2]) : undefined,
|
|
353
|
-
attached: parts[3] !== "0",
|
|
354
|
-
}));
|
|
355
|
-
}
|
|
356
|
-
function sessionRecord(name, fields) {
|
|
357
|
-
const record = {
|
|
358
|
-
name,
|
|
359
|
-
project: fields.cwd === "?" ? sessionProject(name) : basename(fields.cwd),
|
|
360
|
-
id: sessionId(name),
|
|
361
|
-
...fields,
|
|
362
|
-
};
|
|
363
|
-
return { ...record, displayName: ombSessionDisplayName(record) };
|
|
364
|
-
}
|
|
365
|
-
async function describeLiveSession(tmux, session, cwd, childEnv, env, now) {
|
|
366
|
-
const pane = await readTmux(tmux, ["list-panes", "-t", session.name, "-F", PANE_FORMAT], cwd, childEnv);
|
|
367
|
-
const details = parsePane(pane.output, env);
|
|
368
|
-
// Prefer the journal the pane command names: after a rename the tmux session
|
|
369
|
-
// and its native directory differ, and the host keeps writing the directory
|
|
370
|
-
// it was started with.
|
|
371
|
-
const declared = details.bound && details.bound !== session.name
|
|
372
|
-
? await readNativeSessionSnapshot(ombSessionDir(details.bound, env), now)
|
|
373
|
-
: undefined;
|
|
374
|
-
const snapshot = declared?.metadata ? declared : await readNativeSessionSnapshot(ombSessionDir(session.name, env), now);
|
|
375
|
-
const native = snapshot.metadata ?? await readLegacyNativeSessionMetadata(details.cwd, session.createdAt, env);
|
|
376
|
-
return {
|
|
377
|
-
// A live session owns the directory its pane declared, so it must not also
|
|
378
|
-
// be listed from that directory as a second, unopenable session.
|
|
379
|
-
binding: declared?.metadata ? details.bound : undefined,
|
|
380
|
-
session: sessionRecord(session.name, {
|
|
381
|
-
cwd: details.cwd,
|
|
382
|
-
state: ombSessionState({ dead: details.dead, attached: session.attached, activity: snapshot.activity }),
|
|
383
|
-
attached: session.attached,
|
|
384
|
-
activity: snapshot.activity,
|
|
385
|
-
hosted: true,
|
|
386
|
-
command: details.command,
|
|
387
|
-
pid: details.pid,
|
|
388
|
-
nativeId: native?.id,
|
|
389
|
-
nativeName: native?.title,
|
|
390
|
-
firstMessage: native?.firstMessage,
|
|
391
|
-
nativeSessionAvailable: Boolean(snapshot.metadata || native),
|
|
392
|
-
createdAt: session.createdAt ?? native?.createdAt,
|
|
393
|
-
lastAttachedAt: session.lastAttachedAt,
|
|
394
|
-
}),
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Session names whose journal the pane of one live tmux session writes.
|
|
399
|
-
*
|
|
400
|
-
* Deletion uses this before killing the session, because a renamed session's
|
|
401
|
-
* journal lives in the directory it was started with rather than the one named
|
|
402
|
-
* after the current tmux session.
|
|
403
|
-
*/
|
|
404
|
-
export async function ombSessionBoundNames(session, cwd, env = process.env) {
|
|
405
|
-
if (!isOmbSessionName(session))
|
|
406
|
-
return [];
|
|
407
|
-
const childEnv = { ...env, BIZAR_OMP_NO_TMUX: "1" };
|
|
408
|
-
const panes = await readTmux(resolveMultiplexerBin(env), ["list-panes", "-t", session, "-F", PANE_FORMAT], cwd, childEnv);
|
|
409
|
-
if (panes.code !== 0)
|
|
410
|
-
return [];
|
|
411
|
-
const bound = parsePane(panes.output, env).bound;
|
|
412
|
-
return bound && bound !== session ? [bound] : [];
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Bizar sessions that tmux no longer hosts.
|
|
416
|
-
*
|
|
417
|
-
* tmux removes a session as soon as its pane exits, so a terminated session
|
|
418
|
-
* only remains discoverable through the native state directory that `omb`
|
|
419
|
-
* gives every durable host. A journal written inside the stale window proves
|
|
420
|
-
* the agent is still running — a host started outside `omb`, or one whose pane
|
|
421
|
-
* died while the agent kept working — so those sessions stay live instead of
|
|
422
|
-
* being reported as stopped.
|
|
423
|
-
*/
|
|
424
|
-
async function listUnhostedSessions(env, claimed, now) {
|
|
425
|
-
let entries;
|
|
426
|
-
try {
|
|
427
|
-
entries = await readdir(nativeSessionRoot(env), { withFileTypes: true });
|
|
428
|
-
}
|
|
429
|
-
catch {
|
|
430
|
-
return [];
|
|
431
|
-
}
|
|
432
|
-
const unhosted = (await Promise.all(entries.map(async (entry) => {
|
|
433
|
-
if (!entry.isDirectory() || !entry.name.startsWith(BIZAR_SESSION_PREFIX) || claimed.has(entry.name) || await isOmbSessionDeleted(entry.name, env))
|
|
434
|
-
return undefined;
|
|
435
|
-
const snapshot = await readNativeSessionSnapshot(join(nativeSessionRoot(env), entry.name), now);
|
|
436
|
-
const metadata = snapshot.metadata;
|
|
437
|
-
// A directory with no readable session header holds no session: it is an
|
|
438
|
-
// emptied tombstone or a directory created before OMP journaled anything.
|
|
439
|
-
// Listing it would resurrect a session that is gone.
|
|
440
|
-
if (!metadata)
|
|
441
|
-
return undefined;
|
|
442
|
-
const activity = snapshot.activity;
|
|
443
|
-
const alive = Boolean(activity && !activity.stale);
|
|
444
|
-
return sessionRecord(entry.name, {
|
|
445
|
-
cwd: metadata.cwd ?? "?",
|
|
446
|
-
state: alive ? ombSessionState({ dead: false, attached: false, activity }) : "stopped",
|
|
447
|
-
attached: false,
|
|
448
|
-
activity,
|
|
449
|
-
hosted: false,
|
|
450
|
-
command: alive ? "unattached" : "exited",
|
|
451
|
-
pid: "?",
|
|
452
|
-
nativeId: metadata.id,
|
|
453
|
-
nativeName: metadata.title,
|
|
454
|
-
firstMessage: metadata.firstMessage,
|
|
455
|
-
nativeSessionAvailable: true,
|
|
456
|
-
createdAt: metadata.createdAt,
|
|
457
|
-
});
|
|
458
|
-
}))).filter((session) => Boolean(session));
|
|
459
|
-
unhosted.sort((a, b) => (b.activity?.updatedAt ?? 0) - (a.activity?.updatedAt ?? 0));
|
|
460
|
-
const live = unhosted.filter(session => session.state !== "stopped");
|
|
461
|
-
return [...live, ...unhosted.filter(session => session.state === "stopped").slice(0, STOPPED_SESSION_LIMIT)];
|
|
462
|
-
}
|
|
463
|
-
export async function currentOmbHostSession(cwd = process.cwd(), env = process.env) {
|
|
464
|
-
if (!env.TMUX)
|
|
465
|
-
return { kind: "not-bizar" };
|
|
466
|
-
const args = ["display-message", "-p"];
|
|
467
|
-
if (env.TMUX_PANE)
|
|
468
|
-
args.push("-t", env.TMUX_PANE);
|
|
469
|
-
args.push("#{session_name}");
|
|
470
|
-
let result;
|
|
471
|
-
try {
|
|
472
|
-
result = await readTmux(resolveMultiplexerBin(env), args, cwd, { ...env, BIZAR_OMP_NO_TMUX: "1" });
|
|
473
|
-
}
|
|
474
|
-
catch {
|
|
475
|
-
return { kind: "unknown" };
|
|
476
|
-
}
|
|
477
|
-
if (result.code !== 0)
|
|
478
|
-
return { kind: "unknown" };
|
|
479
|
-
const [name = ""] = result.output.trim().split("\n");
|
|
480
|
-
// A session Bizar does not own cannot be one of the sessions a stop targets.
|
|
481
|
-
return isOmbSessionName(name) ? { kind: "bizar", name } : { kind: "not-bizar" };
|
|
482
|
-
}
|
|
483
|
-
/** Discover Bizar-owned tmux sessions without touching unrelated tmux sessions. */
|
|
484
|
-
export async function listOmbSessions(cwd = process.cwd(), env = process.env, options = {}) {
|
|
485
|
-
const tmux = resolveMultiplexerBin(env);
|
|
486
|
-
const childEnv = { ...env, BIZAR_OMP_NO_TMUX: "1" };
|
|
487
|
-
const now = Date.now();
|
|
488
|
-
const sessions = await readTmux(tmux, ["list-sessions", "-F", "#{session_name}\t#{session_created}\t#{session_last_attached}\t#{session_attached}"], cwd, childEnv);
|
|
489
|
-
const live = sessions.code === 0 ? parseSessionList(sessions.output) : [];
|
|
490
|
-
const described = await Promise.all(live.map(session => describeLiveSession(tmux, session, cwd, childEnv, env, now)));
|
|
491
|
-
// Every live session claims the directory its pane writes (its own, or the one
|
|
492
|
-
// a rename left behind), so one session is never listed twice under two names.
|
|
493
|
-
const claimed = new Set([
|
|
494
|
-
...live.map(session => session.name),
|
|
495
|
-
...described.map(item => item.binding).filter((name) => Boolean(name)),
|
|
496
|
-
]);
|
|
497
|
-
const unhosted = await listUnhostedSessions(env, claimed, now);
|
|
498
|
-
const stopped = options.includeStopped ? unhosted.filter(session => session.state === "stopped") : [];
|
|
499
|
-
return [...described.map(item => item.session), ...unhosted.filter(session => session.state !== "stopped"), ...stopped].sort((a, b) => STATE_RANK[a.state] - STATE_RANK[b.state] ||
|
|
500
|
-
a.project.localeCompare(b.project) ||
|
|
501
|
-
a.name.localeCompare(b.name));
|
|
502
|
-
}
|
|
503
|
-
/** Return the most recently attached live session for one exact project path. */
|
|
504
|
-
export async function findLastOmbSession(cwd, env = process.env) {
|
|
505
|
-
const sessions = await listOmbSessions(cwd, env);
|
|
506
|
-
return sessions
|
|
507
|
-
// Only a session tmux still hosts can be reattached. Resuming a live but
|
|
508
|
-
// unhosted session would put a second writer on its journal.
|
|
509
|
-
.filter(session => session.cwd === cwd && session.state !== "stopped" && session.hosted !== false)
|
|
510
|
-
.sort((a, b) => (b.lastAttachedAt ?? b.createdAt ?? 0) - (a.lastAttachedAt ?? a.createdAt ?? 0))[0];
|
|
511
|
-
}
|
|
512
|
-
//# sourceMappingURL=omb-sessions.js.map
|