harnery 0.38.0 → 0.40.0
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/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +32 -8
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +97 -6
- package/dist/commands/backup.d.ts +16 -0
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +239 -33
- package/dist/commands/browse.d.ts +8 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +466 -231
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +6 -3
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +20 -4
- package/dist/commands/qa-run.d.ts.map +1 -1
- package/dist/commands/qa-run.js +26 -3
- package/dist/commands/qa-status.d.ts.map +1 -1
- package/dist/commands/qa-status.js +7 -2
- package/dist/commands/resources.d.ts.map +1 -1
- package/dist/commands/resources.js +23 -3
- package/dist/commands/review-pack.d.ts.map +1 -1
- package/dist/commands/review-pack.js +98 -23
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +2 -2
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -2
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +2 -0
- package/dist/core/agents/cli.js +13 -6
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +5 -3
- package/dist/core/agents/live-lifecycle-v3.d.ts +2 -2
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.d.ts +7 -5
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +63 -8
- package/dist/core/agents/session-finalizer-v3.d.ts +2 -2
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts +3 -3
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +2 -1
- package/dist/core/agents/state/names.d.ts +35 -2
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +80 -5
- package/dist/core/agents/state/stale-sweep.d.ts +2 -1
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -6
- package/dist/core/agents/turn-elapsed.d.ts +51 -0
- package/dist/core/agents/turn-elapsed.d.ts.map +1 -0
- package/dist/core/agents/turn-elapsed.js +91 -0
- package/dist/core/artifacts/activity.d.ts +14 -0
- package/dist/core/artifacts/activity.d.ts.map +1 -0
- package/dist/core/artifacts/activity.js +52 -0
- package/dist/core/artifacts/delivery-card.d.ts +39 -0
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -0
- package/dist/core/artifacts/delivery-card.js +282 -0
- package/dist/core/artifacts/index.d.ts +42 -7
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +288 -76
- package/dist/core/artifacts/mutation-lock.d.ts +2 -0
- package/dist/core/artifacts/mutation-lock.d.ts.map +1 -0
- package/dist/core/artifacts/mutation-lock.js +91 -0
- package/dist/core/backup/host-snapshot.d.ts +18 -0
- package/dist/core/backup/host-snapshot.d.ts.map +1 -0
- package/dist/core/backup/host-snapshot.js +64 -0
- package/dist/core/config.d.ts +20 -5
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +44 -10
- package/dist/core/diagnostics/advice.d.ts +38 -3
- package/dist/core/diagnostics/advice.d.ts.map +1 -1
- package/dist/core/diagnostics/advice.js +103 -99
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +111 -47
- package/dist/core/diagnostics/comparison.d.ts.map +1 -1
- package/dist/core/diagnostics/comparison.js +3 -2
- package/dist/core/diagnostics/contract.d.ts +15 -31
- package/dist/core/diagnostics/contract.d.ts.map +1 -1
- package/dist/core/diagnostics/contract.js +2 -5
- package/dist/core/diagnostics/index.d.ts +2 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -1
- package/dist/core/diagnostics/index.js +2 -0
- package/dist/core/diagnostics/pressure-contract.d.ts +260 -0
- package/dist/core/diagnostics/pressure-contract.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure-contract.js +70 -0
- package/dist/core/diagnostics/pressure.d.ts +25 -0
- package/dist/core/diagnostics/pressure.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure.js +1138 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -1
- package/dist/core/diagnostics/replay.js +90 -10
- package/dist/core/events/v3/adapter-id.d.ts +6 -0
- package/dist/core/events/v3/adapter-id.d.ts.map +1 -0
- package/dist/core/events/v3/adapter-id.js +7 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -1
- package/dist/core/events/v3/archive-retention.js +3 -2
- package/dist/core/events/v3/bootstrap.d.ts +41 -4
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +120 -17
- package/dist/core/events/v3/capabilities.d.ts +16 -9
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +37 -2
- package/dist/core/events/v3/capability-drift.d.ts +2 -2
- package/dist/core/events/v3/capability-drift.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.d.ts +48 -5
- package/dist/core/events/v3/control-witness.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.js +91 -36
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +22 -2
- package/dist/core/events/v3/index.d.ts +2 -1
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +2 -1
- package/dist/core/events/v3/live-feed.d.ts +7 -1
- package/dist/core/events/v3/live-feed.d.ts.map +1 -1
- package/dist/core/events/v3/live-feed.js +21 -3
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +10 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +2 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +2 -1
- package/dist/core/events/v3/producers/hook-base.d.ts +2 -2
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +15 -5
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook.js +17 -4
- package/dist/core/events/v3/producers/intake.d.ts +4 -4
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +3 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -1
- package/dist/core/events/v3/producers/producer-state-observer.js +2 -1
- package/dist/core/events/v3/producers/recorder.d.ts +16 -5
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +31 -9
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +10 -13
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-build.js +3 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +2 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.d.ts +2 -2
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.d.ts +16 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +36 -38
- package/dist/core/hooks/backup-schedule.d.ts +34 -0
- package/dist/core/hooks/backup-schedule.d.ts.map +1 -0
- package/dist/core/hooks/backup-schedule.js +114 -0
- package/dist/core/hooks/cli.js +61 -18
- package/dist/core/hooks/codex-wsl-bridge.d.ts +2 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -1
- package/dist/core/hooks/codex-wsl-bridge.js +18 -4
- package/dist/core/hooks/index.d.ts +1 -0
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +1 -0
- package/dist/core/hooks/prompt-context/contract.d.ts +61 -0
- package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/contract.js +102 -0
- package/dist/core/hooks/prompt-context/index.d.ts +5 -0
- package/dist/core/hooks/prompt-context/index.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/index.js +2 -0
- package/dist/core/hooks/prompt-context/runner.d.ts +24 -0
- package/dist/core/hooks/prompt-context/runner.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/runner.js +249 -0
- package/dist/core/qa-artifacts.d.ts +3 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -1
- package/dist/core/qa-artifacts.js +25 -3
- package/dist/core/resources/contract.d.ts +69 -3
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/contract.js +1 -1
- package/dist/core/resources/index.d.ts +1 -0
- package/dist/core/resources/index.d.ts.map +1 -1
- package/dist/core/resources/index.js +1 -0
- package/dist/core/resources/native.d.ts +36 -0
- package/dist/core/resources/native.d.ts.map +1 -0
- package/dist/core/resources/native.js +418 -0
- package/dist/core/resources/sampler.d.ts +2 -0
- package/dist/core/resources/sampler.d.ts.map +1 -1
- package/dist/core/resources/sampler.js +31 -1
- package/dist/core/resources/status.d.ts +61 -0
- package/dist/core/resources/status.d.ts.map +1 -0
- package/dist/core/resources/status.js +536 -0
- package/dist/core/resources/system.d.ts +27 -0
- package/dist/core/resources/system.d.ts.map +1 -0
- package/dist/core/resources/system.js +439 -0
- package/dist/core/semantic/contract.d.ts +13 -13
- package/dist/core/semantic/service.d.ts +2 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +27 -4
- package/dist/core/storage/builtins.js +41 -0
- package/dist/core/supervisor/contract.d.ts +41 -3
- package/dist/core/supervisor/contract.d.ts.map +1 -1
- package/dist/core/supervisor/contract.js +3 -2
- package/dist/core/supervisor/findings.d.ts +3 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -1
- package/dist/core/supervisor/findings.js +88 -0
- package/dist/core/supervisor/history.d.ts.map +1 -1
- package/dist/core/supervisor/history.js +14 -0
- package/dist/core/supervisor/ledger-state.d.ts +55 -0
- package/dist/core/supervisor/ledger-state.d.ts.map +1 -0
- package/dist/core/supervisor/ledger-state.js +0 -0
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +120 -7
- package/dist/core/supervisor/storage.d.ts +3 -1
- package/dist/core/supervisor/storage.d.ts.map +1 -1
- package/dist/core/supervisor/storage.js +4 -0
- package/dist/core/workflow/admission.d.ts +3 -0
- package/dist/core/workflow/admission.d.ts.map +1 -1
- package/dist/core/workflow/admission.js +28 -16
- package/dist/core/workflow/engine.js +2 -2
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +6 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +4 -3
- package/dist/lib/browser/capture-fidelity.d.ts +7 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -1
- package/dist/lib/browser/capture-fidelity.js +17 -0
- package/dist/lib/browser/client.d.ts +9 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +85 -37
- package/dist/lib/browser/index.d.ts +3 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -1
- package/dist/lib/browser/page-review-budget.d.ts +13 -0
- package/dist/lib/browser/page-review-budget.d.ts.map +1 -0
- package/dist/lib/browser/page-review-budget.js +251 -0
- package/dist/lib/browser/page-review-contracts.d.ts +127 -0
- package/dist/lib/browser/page-review-contracts.d.ts.map +1 -0
- package/dist/lib/browser/page-review-contracts.js +5 -0
- package/dist/lib/browser/page-review-evidence.d.ts +48 -0
- package/dist/lib/browser/page-review-evidence.d.ts.map +1 -0
- package/dist/lib/browser/page-review-evidence.js +340 -0
- package/dist/lib/browser/page-review-judge.d.ts +1 -1
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +46 -38
- package/dist/lib/browser/page-review-pack.d.ts +44 -22
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
- package/dist/lib/browser/page-review-pack.js +116 -36
- package/dist/lib/browser/page-review-source.d.ts +12 -0
- package/dist/lib/browser/page-review-source.d.ts.map +1 -0
- package/dist/lib/browser/page-review-source.js +22 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +35 -9
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run-contracts.js +48 -14
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +215 -68
- package/dist/lib/browser/qa-snapshot.d.ts +6 -0
- package/dist/lib/browser/qa-snapshot.d.ts.map +1 -1
- package/dist/lib/browser/qa-snapshot.js +259 -48
- package/dist/lib/browser/review-capture-transaction.d.ts +13 -0
- package/dist/lib/browser/review-capture-transaction.d.ts.map +1 -0
- package/dist/lib/browser/review-capture-transaction.js +79 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.js +4 -2
- package/dist/lib/browser/thumbnail-association.d.ts +34 -0
- package/dist/lib/browser/thumbnail-association.d.ts.map +1 -0
- package/dist/lib/browser/thumbnail-association.js +158 -0
- package/dist/lib/browser/tiling.d.ts +30 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +38 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
- package/dist/lib/docs-metadata-managed.js +4 -1
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +7 -1
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +1 -0
- package/dist/lib/local-file-url.d.ts +12 -0
- package/dist/lib/local-file-url.d.ts.map +1 -1
- package/dist/lib/local-file-url.js +16 -2
- package/dist/lib/tunnel/state.d.ts +19 -4
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +53 -13
- package/package.json +7 -4
- package/schemas/config.schema.json +69 -2
- package/src/commands/agents.ts +42 -9
- package/src/commands/artifacts.ts +130 -6
- package/src/commands/backup.ts +287 -34
- package/src/commands/browse.ts +564 -267
- package/src/commands/diagnostics.ts +6 -3
- package/src/commands/ledger-v3.ts +20 -3
- package/src/commands/qa-run.ts +37 -3
- package/src/commands/qa-status.ts +11 -2
- package/src/commands/resources.ts +23 -3
- package/src/commands/review-pack.ts +165 -62
- package/src/commands/tunnel.ts +2 -1
- package/src/core/agents/canonical-emit.ts +4 -2
- package/src/core/agents/cli.ts +14 -6
- package/src/core/agents/live-authority-v3.ts +7 -3
- package/src/core/agents/live-lifecycle-v3.ts +2 -2
- package/src/core/agents/render/prompt-context.ts +68 -14
- package/src/core/agents/session-finalizer-v3.ts +2 -2
- package/src/core/agents/state/live-coordination-view.ts +4 -4
- package/src/core/agents/state/names.ts +92 -7
- package/src/core/agents/state/stale-sweep.ts +22 -8
- package/src/core/agents/turn-elapsed.ts +135 -0
- package/src/core/artifacts/activity.ts +71 -0
- package/src/core/artifacts/delivery-card.ts +375 -0
- package/src/core/artifacts/index.ts +385 -91
- package/src/core/artifacts/mutation-lock.ts +106 -0
- package/src/core/backup/host-snapshot.ts +76 -0
- package/src/core/config.ts +66 -13
- package/src/core/diagnostics/advice.ts +148 -120
- package/src/core/diagnostics/bundle.ts +138 -52
- package/src/core/diagnostics/comparison.ts +6 -2
- package/src/core/diagnostics/contract.ts +39 -42
- package/src/core/diagnostics/index.ts +2 -0
- package/src/core/diagnostics/pressure-contract.ts +294 -0
- package/src/core/diagnostics/pressure.ts +1361 -0
- package/src/core/diagnostics/replay.ts +116 -11
- package/src/core/events/v3/adapter-id.ts +12 -0
- package/src/core/events/v3/archive-retention.ts +3 -6
- package/src/core/events/v3/bootstrap.ts +163 -16
- package/src/core/events/v3/capabilities.ts +75 -25
- package/src/core/events/v3/capability-drift.ts +2 -2
- package/src/core/events/v3/control-witness.ts +172 -41
- package/src/core/events/v3/control.ts +34 -2
- package/src/core/events/v3/index.ts +3 -0
- package/src/core/events/v3/live-feed.ts +23 -5
- package/src/core/events/v3/live-routing.ts +14 -2
- package/src/core/events/v3/producers/command-recorder.ts +4 -4
- package/src/core/events/v3/producers/coordination-recorder.ts +4 -4
- package/src/core/events/v3/producers/hook-base.ts +21 -16
- package/src/core/events/v3/producers/hook.ts +21 -4
- package/src/core/events/v3/producers/intake.ts +6 -6
- package/src/core/events/v3/producers/producer-state-observer.ts +2 -1
- package/src/core/events/v3/producers/recorder.ts +50 -21
- package/src/core/events/v3/reader.ts +14 -13
- package/src/core/events/v3/runtime-build.ts +3 -2
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +3 -3
- package/src/core/events/v3/turn-telemetry.ts +4 -4
- package/src/core/hooks/adapter/output.ts +50 -36
- package/src/core/hooks/backup-schedule.ts +147 -0
- package/src/core/hooks/cli.ts +65 -14
- package/src/core/hooks/codex-wsl-bridge.ts +21 -5
- package/src/core/hooks/index.ts +1 -0
- package/src/core/hooks/prompt-context/contract.ts +177 -0
- package/src/core/hooks/prompt-context/index.ts +22 -0
- package/src/core/hooks/prompt-context/runner.ts +303 -0
- package/src/core/qa-artifacts.ts +29 -3
- package/src/core/resources/contract.ts +76 -3
- package/src/core/resources/index.ts +1 -0
- package/src/core/resources/native.ts +481 -0
- package/src/core/resources/sampler.ts +46 -1
- package/src/core/resources/status.ts +717 -0
- package/src/core/resources/system.ts +530 -0
- package/src/core/semantic/service.ts +37 -3
- package/src/core/storage/builtins.ts +41 -0
- package/src/core/supervisor/contract.ts +45 -3
- package/src/core/supervisor/findings.ts +159 -0
- package/src/core/supervisor/history.ts +15 -0
- package/src/core/supervisor/ledger-state.ts +0 -0
- package/src/core/supervisor/service.ts +133 -5
- package/src/core/supervisor/storage.ts +7 -0
- package/src/core/workflow/admission.ts +33 -17
- package/src/core/workflow/engine.ts +2 -2
- package/src/core/workflow/live-session-v3.ts +6 -8
- package/src/core/workflow/proof.ts +4 -3
- package/src/lib/browser/capture-fidelity.ts +23 -0
- package/src/lib/browser/client.ts +96 -44
- package/src/lib/browser/index.ts +15 -1
- package/src/lib/browser/page-review-budget.ts +309 -0
- package/src/lib/browser/page-review-contracts.ts +129 -0
- package/src/lib/browser/page-review-evidence.ts +465 -0
- package/src/lib/browser/page-review-judge.ts +56 -40
- package/src/lib/browser/page-review-pack.ts +181 -43
- package/src/lib/browser/page-review-source.ts +30 -0
- package/src/lib/browser/qa-run-contracts.ts +62 -18
- package/src/lib/browser/qa-run.ts +259 -71
- package/src/lib/browser/qa-snapshot.ts +289 -48
- package/src/lib/browser/review-capture-transaction.ts +106 -0
- package/src/lib/browser/standalone-html.ts +4 -2
- package/src/lib/browser/thumbnail-association.ts +190 -0
- package/src/lib/browser/tiling.ts +63 -0
- package/src/lib/docs-metadata-managed.ts +4 -1
- package/src/lib/identities/assume.ts +12 -4
- package/src/lib/instructions/templates.ts +1 -0
- package/src/lib/local-file-url.ts +17 -2
- package/src/lib/tunnel/state.ts +70 -13
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
import { closeSync, fstatSync, openSync, readSync, statSync } from "node:fs";
|
|
2
|
+
import { unknownPressureAssessment } from "../diagnostics/advice.js";
|
|
3
|
+
import { PRESSURE_ASSESSMENT_SCHEMA_VERSION, PRESSURE_POLICY, } from "../diagnostics/contract.js";
|
|
4
|
+
import { SUPERVISOR_PRESSURE_SCHEMA_VERSION, } from "../supervisor/contract.js";
|
|
5
|
+
import { readSupervisorStatus } from "../supervisor/status.js";
|
|
6
|
+
import { supervisorPaths } from "../supervisor/storage.js";
|
|
7
|
+
import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
|
|
8
|
+
import { resourcePaths } from "./storage.js";
|
|
9
|
+
export const RESOURCE_STATUS_STALE_MS = 15_000;
|
|
10
|
+
export const RESOURCE_STATUS_MAX_BYTES = 4 * 1024 * 1024;
|
|
11
|
+
export const RESOURCE_STATUS_PROCESS_LIMIT = 20;
|
|
12
|
+
export const RESOURCE_HOST_STATUS_STALE_MS = 30_000;
|
|
13
|
+
const FUTURE_TOLERANCE_MS = 1_000;
|
|
14
|
+
/** A bounded cache-only read. Never samples the OS or starts the writer. */
|
|
15
|
+
export function readResourceStatus(coordRoot, options = {}) {
|
|
16
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
17
|
+
const writerState = readWriterState(coordRoot, nowMs);
|
|
18
|
+
const published = readPublishedPressure(coordRoot, nowMs, writerState);
|
|
19
|
+
const result = {
|
|
20
|
+
schema_version: 2,
|
|
21
|
+
state: "unavailable",
|
|
22
|
+
reason: "snapshot_missing",
|
|
23
|
+
sampled_at: null,
|
|
24
|
+
sample_age_ms: null,
|
|
25
|
+
stale_after_ms: RESOURCE_STATUS_STALE_MS,
|
|
26
|
+
platform: null,
|
|
27
|
+
namespace: "unknown",
|
|
28
|
+
support: null,
|
|
29
|
+
writer: writerState,
|
|
30
|
+
assessment: published.assessment,
|
|
31
|
+
prior_hysteresis: published.prior_hysteresis,
|
|
32
|
+
assessment_capability: published.capability,
|
|
33
|
+
machine: null,
|
|
34
|
+
disks: [],
|
|
35
|
+
pressure: null,
|
|
36
|
+
oom: null,
|
|
37
|
+
io: null,
|
|
38
|
+
host: null,
|
|
39
|
+
};
|
|
40
|
+
let value;
|
|
41
|
+
try {
|
|
42
|
+
value = readBoundedJson(resourcePaths(coordRoot).snapshot);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
result.reason =
|
|
46
|
+
error.code === "ENOENT"
|
|
47
|
+
? "snapshot_missing"
|
|
48
|
+
: error instanceof Error && error.message === "snapshot_too_large"
|
|
49
|
+
? "snapshot_too_large"
|
|
50
|
+
: "snapshot_invalid";
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
if (!validSnapshot(value))
|
|
54
|
+
return { ...result, reason: "snapshot_invalid" };
|
|
55
|
+
const sampleMs = Date.parse(value.sampled_at);
|
|
56
|
+
if (!Number.isFinite(sampleMs) || sampleMs - nowMs > FUTURE_TOLERANCE_MS) {
|
|
57
|
+
return { ...result, reason: "snapshot_clock_invalid" };
|
|
58
|
+
}
|
|
59
|
+
result.sampled_at = value.sampled_at;
|
|
60
|
+
result.sample_age_ms = Math.max(0, nowMs - sampleMs);
|
|
61
|
+
result.platform = value.platform;
|
|
62
|
+
result.namespace = value.namespace;
|
|
63
|
+
result.support = {
|
|
64
|
+
state: value.support.state,
|
|
65
|
+
sampler: value.support.sampler,
|
|
66
|
+
...reason(value.support.reason),
|
|
67
|
+
};
|
|
68
|
+
if (result.sample_age_ms > RESOURCE_STATUS_STALE_MS) {
|
|
69
|
+
return { ...result, state: "stale", reason: "snapshot_stale" };
|
|
70
|
+
}
|
|
71
|
+
if (value.support.state === "error" || value.support.state === "unsupported") {
|
|
72
|
+
return { ...result, reason: `sampler_${value.support.state}` };
|
|
73
|
+
}
|
|
74
|
+
result.state = "fresh";
|
|
75
|
+
result.reason = null;
|
|
76
|
+
result.machine = projectMachine(value.machine);
|
|
77
|
+
result.disks = (value.disks ?? []).map(projectDisk);
|
|
78
|
+
result.pressure = value.pressure
|
|
79
|
+
? {
|
|
80
|
+
state: value.pressure.state,
|
|
81
|
+
...reason(value.pressure.reason),
|
|
82
|
+
cpu: projectWindow(value.pressure.cpu),
|
|
83
|
+
memory: projectWindow(value.pressure.memory),
|
|
84
|
+
io: projectWindow(value.pressure.io),
|
|
85
|
+
memory_full: projectWindow(value.pressure.memory_full),
|
|
86
|
+
io_full: projectWindow(value.pressure.io_full),
|
|
87
|
+
}
|
|
88
|
+
: null;
|
|
89
|
+
result.oom = value.oom
|
|
90
|
+
? {
|
|
91
|
+
state: value.oom.state,
|
|
92
|
+
total_kills: value.oom.total_kills,
|
|
93
|
+
kills_since_last_sample: value.oom.kills_since_last_sample,
|
|
94
|
+
last_kill_age_ms: value.oom.last_kill_age_ms,
|
|
95
|
+
...reason(value.oom.reason),
|
|
96
|
+
}
|
|
97
|
+
: null;
|
|
98
|
+
result.io = value.io
|
|
99
|
+
? {
|
|
100
|
+
state: value.io.state,
|
|
101
|
+
read_bytes_per_second: value.io.read_bytes_per_second,
|
|
102
|
+
write_bytes_per_second: value.io.write_bytes_per_second,
|
|
103
|
+
...reason(value.io.reason),
|
|
104
|
+
}
|
|
105
|
+
: null;
|
|
106
|
+
if (value.host) {
|
|
107
|
+
const hostAge = nowMs - Date.parse(value.host.sampled_at);
|
|
108
|
+
result.host =
|
|
109
|
+
hostAge > RESOURCE_HOST_STATUS_STALE_MS || hostAge < -FUTURE_TOLERANCE_MS
|
|
110
|
+
? {
|
|
111
|
+
platform: "win32",
|
|
112
|
+
sampled_at: value.host.sampled_at,
|
|
113
|
+
state: "error",
|
|
114
|
+
machine: null,
|
|
115
|
+
disks: [],
|
|
116
|
+
reason: "host_snapshot_stale",
|
|
117
|
+
}
|
|
118
|
+
: {
|
|
119
|
+
platform: "win32",
|
|
120
|
+
sampled_at: value.host.sampled_at,
|
|
121
|
+
state: value.host.state,
|
|
122
|
+
machine: value.host.machine ? projectMachine(value.host.machine) : null,
|
|
123
|
+
disks: value.host.disks.map(projectDisk),
|
|
124
|
+
...reason(value.host.reason),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (options.includeProcesses) {
|
|
128
|
+
result.processes = [...value.processes]
|
|
129
|
+
.sort((a, b) => b.rss_bytes - a.rss_bytes)
|
|
130
|
+
.slice(0, RESOURCE_STATUS_PROCESS_LIMIT)
|
|
131
|
+
.map((p) => ({
|
|
132
|
+
pid: p.pid,
|
|
133
|
+
name: text(p.name),
|
|
134
|
+
cpu_percent: p.cpu_percent,
|
|
135
|
+
rss_bytes: p.rss_bytes,
|
|
136
|
+
owner_kind: p.owner_kind,
|
|
137
|
+
owner_id: p.owner_id === null ? null : text(p.owner_id),
|
|
138
|
+
}));
|
|
139
|
+
result.processes_omitted =
|
|
140
|
+
value.omitted_process_count + value.processes.length - result.processes.length;
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}
|
|
144
|
+
export function formatResourceSummary(status) {
|
|
145
|
+
const lead = status.assessment.summary;
|
|
146
|
+
if (status.state !== "fresh" || !status.machine) {
|
|
147
|
+
const age = status.sample_age_ms === null ? "" : ` (${Math.round(status.sample_age_ms / 1_000)}s old)`;
|
|
148
|
+
return `${lead} Measurements are ${status.state}${age}: ${status.reason?.replaceAll("_", " ") ?? "no measurements"}.`;
|
|
149
|
+
}
|
|
150
|
+
const m = status.machine;
|
|
151
|
+
const disk = status.disks
|
|
152
|
+
.filter((d) => d.available_bytes !== null)
|
|
153
|
+
.reduce((least, d) => !least || (d.available_bytes ?? Infinity) < (least.available_bytes ?? Infinity) ? d : least, null);
|
|
154
|
+
const cpu = m.cpu_percent === null ? "warming up" : `${Math.round(m.cpu_percent)}%`;
|
|
155
|
+
const ram = m.memory_available_bytes === null
|
|
156
|
+
? "unknown"
|
|
157
|
+
: `${formatBytes(m.memory_available_bytes)} available`;
|
|
158
|
+
const diskText = disk ? `${formatBytes(disk.available_bytes)} available` : "unknown";
|
|
159
|
+
return `${lead} ${status.namespace}/${status.platform}: CPU ${cpu}, RAM ${ram}, disk ${diskText}; ${Math.round((status.sample_age_ms ?? 0) / 1_000)}s old${status.support?.state === "partial" ? "; partial" : ""}${!status.writer.running ? "; writer stopped" : ""}.`;
|
|
160
|
+
}
|
|
161
|
+
export function formatResourceStatus(status, bin) {
|
|
162
|
+
const a = status.assessment;
|
|
163
|
+
const lines = [formatResourceSummary(status)];
|
|
164
|
+
lines.push(`Assessment: ${a.state} at ${a.scope} scope; limiting resource ${a.limiting_resource}; trend ${a.trend}; evidence ${a.evidence_state}; recommended action ${a.recommended_action}.`);
|
|
165
|
+
lines.push(`Evidence age: ${a.sample_age_ms === null ? "unknown" : `${Math.round(a.sample_age_ms / 1_000)}s`}; assessment source ${status.assessment_capability.state}${status.assessment_capability.reason_code ? ` (${status.assessment_capability.reason_code})` : ""}.`);
|
|
166
|
+
for (const item of a.reasons)
|
|
167
|
+
lines.push(`Reason ${item.code}: ${item.summary}`);
|
|
168
|
+
for (const item of a.guidance)
|
|
169
|
+
lines.push(`Guidance for ${item.workload_class} work: ${item.summary}`);
|
|
170
|
+
if (a.contributors.length) {
|
|
171
|
+
lines.push("Contributors (who is using the resource, never the machine state):");
|
|
172
|
+
for (const item of a.contributors)
|
|
173
|
+
lines.push(` ${formatContributor(item)}`);
|
|
174
|
+
if (a.omitted_contributor_count)
|
|
175
|
+
lines.push(` ${a.omitted_contributor_count} other contributors omitted.`);
|
|
176
|
+
}
|
|
177
|
+
if (a.unattributed_memory_percent !== null)
|
|
178
|
+
lines.push(`Unattributed memory: ${Math.round(a.unattributed_memory_percent)}% of machine memory has no validated owner.`);
|
|
179
|
+
if (status.state !== "fresh" || !status.writer.running)
|
|
180
|
+
lines.push(`Start or inspect the writer with ${bin} supervisor start --keep-alive and ${bin} supervisor status.`);
|
|
181
|
+
if (status.host)
|
|
182
|
+
lines.push(`Windows host: ${status.host.state}${status.host.machine ? `; CPU ${status.host.machine.cpu_percent === null ? "warming up" : `${Math.round(status.host.machine.cpu_percent)}%`}, RAM ${status.host.machine.memory_available_bytes === null ? "unknown" : `${formatBytes(status.host.machine.memory_available_bytes)} available`}` : `; ${status.host.reason ?? "unavailable"}`}`);
|
|
183
|
+
for (const disk of status.disks)
|
|
184
|
+
lines.push(`Disk ${disk.path}: ${disk.available_bytes === null ? (disk.reason ?? disk.state) : `${formatBytes(disk.available_bytes)} available (${disk.used_percent === null ? "unknown" : `${Math.round(disk.used_percent)}%`} used)`}`);
|
|
185
|
+
if (status.pressure)
|
|
186
|
+
lines.push(`Pressure: ${status.pressure.state}${status.pressure.reason ? ` (${status.pressure.reason})` : ""}`);
|
|
187
|
+
for (const [name, window] of [
|
|
188
|
+
["memory", status.pressure?.memory_full],
|
|
189
|
+
["I/O", status.pressure?.io_full],
|
|
190
|
+
]) {
|
|
191
|
+
if (!window)
|
|
192
|
+
continue;
|
|
193
|
+
const direction = window.avg10 > window.avg60 ? "rising" : window.avg10 < window.avg60 ? "falling" : "steady";
|
|
194
|
+
lines.push(`Full ${name} stalls: ${window.avg10}% / ${window.avg60}% / ${window.avg300}% (10s / 60s / 300s; ${direction}).`);
|
|
195
|
+
}
|
|
196
|
+
if (status.oom) {
|
|
197
|
+
const oom = status.oom;
|
|
198
|
+
lines.push(`OOM kills: ${oom.total_kills ?? "unknown"} total; ${oom.kills_since_last_sample ?? "unknown"} since previous sample${oom.last_kill_age_ms === null ? "" : `; last increase ${Math.round(oom.last_kill_age_ms / 1000)}s ago`}${oom.reason ? ` (${oom.reason})` : ""}.`);
|
|
199
|
+
}
|
|
200
|
+
if (status.io)
|
|
201
|
+
lines.push(`Disk I/O: ${status.io.state}; read ${status.io.read_bytes_per_second === null ? "unknown" : `${formatBytes(status.io.read_bytes_per_second)}/s`}, write ${status.io.write_bytes_per_second === null ? "unknown" : `${formatBytes(status.io.write_bytes_per_second)}/s`}`);
|
|
202
|
+
if (status.processes) {
|
|
203
|
+
lines.push("Processes (largest memory first):");
|
|
204
|
+
for (const p of status.processes)
|
|
205
|
+
lines.push(` ${p.pid} ${p.name}: ${formatBytes(p.rss_bytes)}, CPU ${p.cpu_percent === null ? "unknown" : `${Math.round(p.cpu_percent)}%`}, ${p.owner_kind}${p.owner_id ? ` ${p.owner_id}` : ""}`);
|
|
206
|
+
if (status.processes_omitted)
|
|
207
|
+
lines.push(` ${status.processes_omitted} other processes omitted.`);
|
|
208
|
+
}
|
|
209
|
+
return lines.join("\n");
|
|
210
|
+
}
|
|
211
|
+
/** Ownership is stated only when attribution is exact. */
|
|
212
|
+
function formatContributor(item) {
|
|
213
|
+
const owner = item.attribution_confidence === "exact" && item.owner_id
|
|
214
|
+
? `${item.owner_kind ?? "owner"} ${item.owner_id}`
|
|
215
|
+
: item.attribution_state === "unattributed"
|
|
216
|
+
? "no validated owner"
|
|
217
|
+
: "owner not confirmed";
|
|
218
|
+
return `${item.finding_kind} ${item.scope_kind}:${item.scope_id} (${owner}): ${item.summary}`;
|
|
219
|
+
}
|
|
220
|
+
export const PRESSURE_RECORD_MAX_BYTES = 256 * 1024;
|
|
221
|
+
/**
|
|
222
|
+
* Read the assessment the observer published. Bounded, cache only, and never a
|
|
223
|
+
* computation: a missing, stale, or malformed record yields `unknown` with the
|
|
224
|
+
* reason stated, because a gap in the evidence is not a measurement of health.
|
|
225
|
+
*/
|
|
226
|
+
export function readPublishedPressure(coordRoot, nowMs = Date.now(), writer) {
|
|
227
|
+
const sourceKind = "supervisor.pressure";
|
|
228
|
+
const observedAt = new Date(nowMs).toISOString();
|
|
229
|
+
const gap = (state, reasonCode, summary, stale = false) => ({
|
|
230
|
+
assessment: unknownPressureAssessment({
|
|
231
|
+
observedAt,
|
|
232
|
+
reasonCode: stale ? "snapshot_stale" : "evidence_unavailable",
|
|
233
|
+
summary,
|
|
234
|
+
}),
|
|
235
|
+
prior_hysteresis: null,
|
|
236
|
+
capability: { source_kind: sourceKind, state, reason_code: reasonCode },
|
|
237
|
+
record: null,
|
|
238
|
+
});
|
|
239
|
+
// A record can only be trusted while its writer is alive. Every surface makes
|
|
240
|
+
// the same check here so none of them reports a state the others do not.
|
|
241
|
+
if (!(writer ?? readWriterState(coordRoot, nowMs)).running) {
|
|
242
|
+
return gap("expired", "pressure_observer_not_running", "Local resource pressure cannot be determined because the resource observer is not running.");
|
|
243
|
+
}
|
|
244
|
+
const path = supervisorPaths(coordRoot).pressure;
|
|
245
|
+
let record;
|
|
246
|
+
try {
|
|
247
|
+
const age = nowMs - statSync(path).mtimeMs;
|
|
248
|
+
if (age > PRESSURE_POLICY.sample_staleness_ms || age < -FUTURE_TOLERANCE_MS) {
|
|
249
|
+
return gap("expired", "pressure_record_stale", `Local resource pressure cannot be determined because the published assessment is ${Math.round(Math.abs(age) / 1_000)} seconds old.`, true);
|
|
250
|
+
}
|
|
251
|
+
record = readBoundedJson(path, PRESSURE_RECORD_MAX_BYTES);
|
|
252
|
+
}
|
|
253
|
+
catch (error) {
|
|
254
|
+
if (error.code === "ENOENT") {
|
|
255
|
+
return gap("unsupported", "pressure_record_missing", "Local resource pressure cannot be determined because the observer has not published an assessment yet.");
|
|
256
|
+
}
|
|
257
|
+
if (error instanceof Error && error.message === "snapshot_too_large") {
|
|
258
|
+
return gap("error", "pressure_record_too_large", "Local resource pressure cannot be determined because the published assessment is larger than the read limit.");
|
|
259
|
+
}
|
|
260
|
+
return gap("malformed", "pressure_record_malformed", "Local resource pressure cannot be determined because the published assessment could not be parsed.");
|
|
261
|
+
}
|
|
262
|
+
if (!validPressureRecord(record)) {
|
|
263
|
+
return gap("malformed", "pressure_record_malformed", "Local resource pressure cannot be determined because the published assessment did not match the expected shape.");
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
assessment: record.assessment,
|
|
267
|
+
prior_hysteresis: record.prior_hysteresis,
|
|
268
|
+
capability: { source_kind: sourceKind, state: "supported" },
|
|
269
|
+
record,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/** Whether the observer that writes both the snapshot and the record is alive. */
|
|
273
|
+
function readWriterState(coordRoot, nowMs) {
|
|
274
|
+
try {
|
|
275
|
+
// Keep malformed service metadata from making the read expensive. The shared
|
|
276
|
+
// status reader retains ownership of PID/start-token liveness checks.
|
|
277
|
+
if (statSync(supervisorPaths(coordRoot).service).size > 65_536) {
|
|
278
|
+
return { running: false, stale: false };
|
|
279
|
+
}
|
|
280
|
+
const writer = readSupervisorStatus(coordRoot, nowMs);
|
|
281
|
+
const futureHeartbeat = writer.record && Date.parse(writer.record.heartbeat_at) > nowMs + FUTURE_TOLERANCE_MS;
|
|
282
|
+
return {
|
|
283
|
+
running: writer.running && !futureHeartbeat,
|
|
284
|
+
stale: writer.stale || !!futureHeartbeat,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// A missing writer must not break normal coordination.
|
|
289
|
+
return { running: false, stale: false };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function validPressureRecord(v) {
|
|
293
|
+
if (!object(v) ||
|
|
294
|
+
v.schema_version !== SUPERVISOR_PRESSURE_SCHEMA_VERSION ||
|
|
295
|
+
!string(v.published_at) ||
|
|
296
|
+
!string(v.observer_generation) ||
|
|
297
|
+
!validAssessment(v.assessment) ||
|
|
298
|
+
!(v.prior_hysteresis === null || validHysteresis(v.prior_hysteresis)))
|
|
299
|
+
return false;
|
|
300
|
+
return true;
|
|
301
|
+
}
|
|
302
|
+
function validAssessment(v) {
|
|
303
|
+
if (!object(v) ||
|
|
304
|
+
v.schema_version !== PRESSURE_ASSESSMENT_SCHEMA_VERSION ||
|
|
305
|
+
v.observer_only !== true ||
|
|
306
|
+
!["normal", "elevated", "critical", "unknown"].includes(v.state) ||
|
|
307
|
+
!["guest", "native", "windows-host"].includes(v.scope) ||
|
|
308
|
+
!["memory", "cpu", "io", "storage", "none", "unknown"].includes(v.limiting_resource) ||
|
|
309
|
+
!["rising", "steady", "falling", "unknown"].includes(v.trend) ||
|
|
310
|
+
!string(v.observed_at) ||
|
|
311
|
+
!nullable(v.sample_age_ms) ||
|
|
312
|
+
!["complete", "partial", "unavailable"].includes(v.evidence_state) ||
|
|
313
|
+
!boundedArray(v.evidence, PRESSURE_POLICY.limits.max_evidence) ||
|
|
314
|
+
!boundedArray(v.reasons, PRESSURE_POLICY.limits.max_reasons) ||
|
|
315
|
+
!boundedArray(v.contributors, PRESSURE_POLICY.limits.max_contributors) ||
|
|
316
|
+
!number(v.omitted_contributor_count) ||
|
|
317
|
+
!percent(v.unattributed_memory_percent) ||
|
|
318
|
+
!["proceed", "limit-heavy-work", "avoid-new-heavy-work", "unknown"].includes(v.recommended_action) ||
|
|
319
|
+
!string(v.summary) ||
|
|
320
|
+
!boundedArray(v.guidance, 8) ||
|
|
321
|
+
!validHysteresis(v.hysteresis) ||
|
|
322
|
+
!number(v.policy_version))
|
|
323
|
+
return false;
|
|
324
|
+
return (v.reasons.every((row) => object(row) && string(row.code) && string(row.summary)) &&
|
|
325
|
+
v.guidance.every((row) => object(row) && string(row.workload_class) && string(row.summary)) &&
|
|
326
|
+
v.contributors.every((row) => object(row) &&
|
|
327
|
+
string(row.finding_id) &&
|
|
328
|
+
string(row.finding_kind) &&
|
|
329
|
+
string(row.summary) &&
|
|
330
|
+
["exact", "none"].includes(row.attribution_confidence)));
|
|
331
|
+
}
|
|
332
|
+
function validHysteresis(v) {
|
|
333
|
+
return (object(v) &&
|
|
334
|
+
["normal", "elevated", "critical", "unknown"].includes(v.state) &&
|
|
335
|
+
string(v.state_since) &&
|
|
336
|
+
number(v.consecutive_clear_samples) &&
|
|
337
|
+
object(v.dimension_streaks) &&
|
|
338
|
+
(v.oom_baseline_total_kills === null || number(v.oom_baseline_total_kills)) &&
|
|
339
|
+
(v.oom_hold_until === null || string(v.oom_hold_until)) &&
|
|
340
|
+
(v.observer_generation === null || string(v.observer_generation)));
|
|
341
|
+
}
|
|
342
|
+
function boundedArray(v, max) {
|
|
343
|
+
return Array.isArray(v) && v.length <= max;
|
|
344
|
+
}
|
|
345
|
+
function readBoundedJson(path, maxBytes = RESOURCE_STATUS_MAX_BYTES) {
|
|
346
|
+
const fd = openSync(path, "r");
|
|
347
|
+
try {
|
|
348
|
+
const size = fstatSync(fd).size;
|
|
349
|
+
if (size > maxBytes)
|
|
350
|
+
throw new Error("snapshot_too_large");
|
|
351
|
+
const buffer = Buffer.alloc(Math.min(maxBytes + 1, size + 1));
|
|
352
|
+
const length = readSync(fd, buffer, 0, buffer.length, 0);
|
|
353
|
+
if (length > maxBytes)
|
|
354
|
+
throw new Error("snapshot_too_large");
|
|
355
|
+
return JSON.parse(buffer.subarray(0, length).toString("utf8"));
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
closeSync(fd);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function object(v) {
|
|
362
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
363
|
+
}
|
|
364
|
+
function number(v) {
|
|
365
|
+
return typeof v === "number" && Number.isFinite(v) && v >= 0;
|
|
366
|
+
}
|
|
367
|
+
function nullable(v) {
|
|
368
|
+
return v === null || number(v);
|
|
369
|
+
}
|
|
370
|
+
function percent(v) {
|
|
371
|
+
return v === null || (number(v) && v <= 100);
|
|
372
|
+
}
|
|
373
|
+
function support(v) {
|
|
374
|
+
return ["supported", "partial", "unsupported", "error"].includes(v);
|
|
375
|
+
}
|
|
376
|
+
function string(v) {
|
|
377
|
+
return typeof v === "string" && v.length <= 4096;
|
|
378
|
+
}
|
|
379
|
+
function validMachine(v) {
|
|
380
|
+
return (object(v) &&
|
|
381
|
+
percent(v.cpu_percent) &&
|
|
382
|
+
number(v.cpu_logical_count) &&
|
|
383
|
+
(v.cpu_available_parallelism === undefined || number(v.cpu_available_parallelism)) &&
|
|
384
|
+
(v.load_average === null ||
|
|
385
|
+
(Array.isArray(v.load_average) &&
|
|
386
|
+
v.load_average.length === 3 &&
|
|
387
|
+
v.load_average.every(number))) &&
|
|
388
|
+
[
|
|
389
|
+
"memory_total_bytes",
|
|
390
|
+
"memory_available_bytes",
|
|
391
|
+
"memory_used_bytes",
|
|
392
|
+
"swap_total_bytes",
|
|
393
|
+
"swap_used_bytes",
|
|
394
|
+
].every((k) => nullable(v[k])) &&
|
|
395
|
+
percent(v.memory_percent) &&
|
|
396
|
+
nullable(v.process_count) &&
|
|
397
|
+
!(number(v.memory_total_bytes) &&
|
|
398
|
+
number(v.memory_available_bytes) &&
|
|
399
|
+
v.memory_available_bytes > v.memory_total_bytes));
|
|
400
|
+
}
|
|
401
|
+
function validDisk(v) {
|
|
402
|
+
return (object(v) &&
|
|
403
|
+
string(v.path) &&
|
|
404
|
+
support(v.state) &&
|
|
405
|
+
nullable(v.total_bytes) &&
|
|
406
|
+
nullable(v.available_bytes) &&
|
|
407
|
+
percent(v.used_percent) &&
|
|
408
|
+
(v.reason === undefined || string(v.reason)) &&
|
|
409
|
+
!(number(v.total_bytes) && number(v.available_bytes) && v.available_bytes > v.total_bytes));
|
|
410
|
+
}
|
|
411
|
+
function validWindow(v) {
|
|
412
|
+
return (v === null ||
|
|
413
|
+
(object(v) && ["avg10", "avg60", "avg300"].every((k) => number(v[k]) && v[k] <= 100)));
|
|
414
|
+
}
|
|
415
|
+
function validSnapshot(v) {
|
|
416
|
+
if (!object(v) ||
|
|
417
|
+
v.schema_version !== RESOURCE_SNAPSHOT_SCHEMA_VERSION ||
|
|
418
|
+
!string(v.sampled_at) ||
|
|
419
|
+
![
|
|
420
|
+
"aix",
|
|
421
|
+
"android",
|
|
422
|
+
"darwin",
|
|
423
|
+
"freebsd",
|
|
424
|
+
"haiku",
|
|
425
|
+
"linux",
|
|
426
|
+
"openbsd",
|
|
427
|
+
"sunos",
|
|
428
|
+
"win32",
|
|
429
|
+
"cygwin",
|
|
430
|
+
"netbsd",
|
|
431
|
+
].includes(v.platform) ||
|
|
432
|
+
!["host", "wsl", "unknown"].includes(v.namespace) ||
|
|
433
|
+
!object(v.support) ||
|
|
434
|
+
!support(v.support.state) ||
|
|
435
|
+
!["procfs", "darwin", "win32", "unsupported"].includes(v.support.sampler) ||
|
|
436
|
+
(v.support.reason !== undefined && !string(v.support.reason)) ||
|
|
437
|
+
!validMachine(v.machine) ||
|
|
438
|
+
!nullable(v.interval_ms) ||
|
|
439
|
+
!number(v.sample_duration_ms) ||
|
|
440
|
+
!number(v.collector_cpu_ms) ||
|
|
441
|
+
!number(v.omitted_process_count) ||
|
|
442
|
+
!Array.isArray(v.processes) ||
|
|
443
|
+
v.processes.length > 10000)
|
|
444
|
+
return false;
|
|
445
|
+
if (v.disks !== undefined &&
|
|
446
|
+
(!Array.isArray(v.disks) || v.disks.length > 64 || !v.disks.every(validDisk)))
|
|
447
|
+
return false;
|
|
448
|
+
if (v.pressure !== undefined &&
|
|
449
|
+
(!object(v.pressure) ||
|
|
450
|
+
!support(v.pressure.state) ||
|
|
451
|
+
!validWindow(v.pressure.cpu) ||
|
|
452
|
+
!validWindow(v.pressure.memory) ||
|
|
453
|
+
!validWindow(v.pressure.io) ||
|
|
454
|
+
!validWindow(v.pressure.memory_full) ||
|
|
455
|
+
!validWindow(v.pressure.io_full) ||
|
|
456
|
+
(v.pressure.reason !== undefined && !string(v.pressure.reason))))
|
|
457
|
+
return false;
|
|
458
|
+
if (v.oom !== undefined &&
|
|
459
|
+
(!object(v.oom) ||
|
|
460
|
+
!support(v.oom.state) ||
|
|
461
|
+
!["total_kills", "kills_since_last_sample"].every((key) => v.oom !== null &&
|
|
462
|
+
object(v.oom) &&
|
|
463
|
+
(v.oom[key] === null || (number(v.oom[key]) && Number.isSafeInteger(v.oom[key])))) ||
|
|
464
|
+
!nullable(v.oom.last_kill_age_ms) ||
|
|
465
|
+
(v.oom.reason !== undefined && !string(v.oom.reason))))
|
|
466
|
+
return false;
|
|
467
|
+
if (v.io !== undefined &&
|
|
468
|
+
(!object(v.io) ||
|
|
469
|
+
!support(v.io.state) ||
|
|
470
|
+
!nullable(v.io.read_bytes_per_second) ||
|
|
471
|
+
!nullable(v.io.write_bytes_per_second) ||
|
|
472
|
+
(v.io.reason !== undefined && !string(v.io.reason))))
|
|
473
|
+
return false;
|
|
474
|
+
if (v.host !== undefined &&
|
|
475
|
+
(!object(v.host) ||
|
|
476
|
+
v.host.platform !== "win32" ||
|
|
477
|
+
!support(v.host.state) ||
|
|
478
|
+
!string(v.host.sampled_at) ||
|
|
479
|
+
!Number.isFinite(Date.parse(v.host.sampled_at)) ||
|
|
480
|
+
(v.host.machine !== null && !validMachine(v.host.machine)) ||
|
|
481
|
+
!Array.isArray(v.host.disks) ||
|
|
482
|
+
v.host.disks.length > 64 ||
|
|
483
|
+
!v.host.disks.every(validDisk) ||
|
|
484
|
+
(v.host.reason !== undefined && !string(v.host.reason))))
|
|
485
|
+
return false;
|
|
486
|
+
return v.processes.every((p) => object(p) &&
|
|
487
|
+
Number.isSafeInteger(p.pid) &&
|
|
488
|
+
number(p.pid) &&
|
|
489
|
+
string(p.name) &&
|
|
490
|
+
nullable(p.cpu_percent) &&
|
|
491
|
+
number(p.rss_bytes) &&
|
|
492
|
+
["agent", "service", "unattributed"].includes(p.owner_kind) &&
|
|
493
|
+
(p.owner_id === null || string(p.owner_id)));
|
|
494
|
+
}
|
|
495
|
+
function projectMachine(m) {
|
|
496
|
+
return {
|
|
497
|
+
cpu_percent: m.cpu_percent,
|
|
498
|
+
cpu_logical_count: m.cpu_logical_count,
|
|
499
|
+
...(m.cpu_available_parallelism === undefined
|
|
500
|
+
? {}
|
|
501
|
+
: { cpu_available_parallelism: m.cpu_available_parallelism }),
|
|
502
|
+
load_average: m.load_average,
|
|
503
|
+
memory_total_bytes: m.memory_total_bytes,
|
|
504
|
+
memory_available_bytes: m.memory_available_bytes,
|
|
505
|
+
memory_used_bytes: m.memory_used_bytes,
|
|
506
|
+
memory_percent: m.memory_percent,
|
|
507
|
+
swap_total_bytes: m.swap_total_bytes,
|
|
508
|
+
swap_used_bytes: m.swap_used_bytes,
|
|
509
|
+
process_count: m.process_count,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function projectDisk(d) {
|
|
513
|
+
return {
|
|
514
|
+
path: text(d.path),
|
|
515
|
+
state: d.state,
|
|
516
|
+
total_bytes: d.total_bytes,
|
|
517
|
+
available_bytes: d.available_bytes,
|
|
518
|
+
used_percent: d.used_percent,
|
|
519
|
+
...reason(d.reason),
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
function projectWindow(v) {
|
|
523
|
+
return v ? { avg10: v.avg10, avg60: v.avg60, avg300: v.avg300 } : null;
|
|
524
|
+
}
|
|
525
|
+
function text(s) {
|
|
526
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: Cache strings must not inject terminal control sequences.
|
|
527
|
+
return s.replace(/[\x00-\x1f\x7f]/g, " ").slice(0, 240);
|
|
528
|
+
}
|
|
529
|
+
function reason(s) {
|
|
530
|
+
return s === undefined ? {} : { reason: text(s) };
|
|
531
|
+
}
|
|
532
|
+
function formatBytes(bytes) {
|
|
533
|
+
return bytes >= 1024 ** 3
|
|
534
|
+
? `${(bytes / 1024 ** 3).toFixed(1)} GiB`
|
|
535
|
+
: `${Math.round(bytes / 1024 ** 2)} MiB`;
|
|
536
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ResourceDiskSample, ResourceIoSample, ResourceOomSample, ResourcePressureSample, ResourceVmstatSample } from "./contract.js";
|
|
2
|
+
interface FileSystemCapacity {
|
|
3
|
+
bsize: number | bigint;
|
|
4
|
+
blocks: number | bigint;
|
|
5
|
+
bavail: number | bigint;
|
|
6
|
+
bfree: number | bigint;
|
|
7
|
+
}
|
|
8
|
+
export interface SystemResourceOptions {
|
|
9
|
+
platform?: NodeJS.Platform;
|
|
10
|
+
procRoot?: string;
|
|
11
|
+
sysRoot?: string;
|
|
12
|
+
nowMs?: number;
|
|
13
|
+
namespace?: string;
|
|
14
|
+
tmpPath?: string;
|
|
15
|
+
statfs?: (path: string) => FileSystemCapacity;
|
|
16
|
+
filesystemId?: (path: string) => string | number | bigint;
|
|
17
|
+
}
|
|
18
|
+
/** Collect only the workspace and temporary volume; never walk their contents. */
|
|
19
|
+
export declare function collectSystemResources(coordRoot: string, options?: SystemResourceOptions): {
|
|
20
|
+
disks: ResourceDiskSample[];
|
|
21
|
+
pressure: ResourcePressureSample;
|
|
22
|
+
io: ResourceIoSample;
|
|
23
|
+
oom: ResourceOomSample;
|
|
24
|
+
vmstat: ResourceVmstatSample;
|
|
25
|
+
};
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../../src/core/resources/system.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,sBAAsB,EAGtB,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAEvB,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC3D;AAwCD,kFAAkF;AAClF,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,qBAA0B,GAClC;IACD,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,sBAAsB,CAAC;IACjC,EAAE,EAAE,gBAAgB,CAAC;IACrB,GAAG,EAAE,iBAAiB,CAAC;IACvB,MAAM,EAAE,oBAAoB,CAAC;CAC9B,CA6CA"}
|