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,36 @@
|
|
|
1
|
+
import * as os from "node:os";
|
|
2
|
+
import { type ResourceHostSample, type ResourceSampleResult, type ResourceSamplerState } from "./contract.js";
|
|
3
|
+
export type NativeResourceCommand = (file: string, args: readonly string[]) => string | null;
|
|
4
|
+
export interface NativeResourceSamplerOptions {
|
|
5
|
+
nowMs?: number;
|
|
6
|
+
platform?: "darwin" | "win32";
|
|
7
|
+
os?: Partial<Pick<typeof os, "cpus" | "totalmem" | "freemem" | "availableParallelism" | "loadavg">>;
|
|
8
|
+
command?: NativeResourceCommand;
|
|
9
|
+
backgroundHost?: boolean;
|
|
10
|
+
/** Supervisors use the background collector to keep native CPU sampling on cadence. */
|
|
11
|
+
hostCollector?: () => ResourceHostSample;
|
|
12
|
+
}
|
|
13
|
+
export declare function sampleNativeResources(_coordRoot: string, previous?: ResourceSamplerState, options?: NativeResourceSamplerOptions): ResourceSampleResult;
|
|
14
|
+
export declare function parseMacVmStat(output: string): {
|
|
15
|
+
available_bytes: number;
|
|
16
|
+
} | null;
|
|
17
|
+
export declare function parseMacSwapUsage(output: string): {
|
|
18
|
+
total: number;
|
|
19
|
+
used: number;
|
|
20
|
+
} | null;
|
|
21
|
+
export interface WindowsHostOptions {
|
|
22
|
+
nowMs?: number;
|
|
23
|
+
command?: NativeResourceCommand;
|
|
24
|
+
}
|
|
25
|
+
export declare function createWindowsHostCollector(): (options?: WindowsHostOptions) => ResourceHostSample;
|
|
26
|
+
export declare const collectWindowsHost: (options?: WindowsHostOptions) => ResourceHostSample;
|
|
27
|
+
export type NativeResourceAsyncCommand = (file: string, args: readonly string[]) => Promise<string | null>;
|
|
28
|
+
export interface WindowsHostBackgroundOptions {
|
|
29
|
+
nowMs?: number;
|
|
30
|
+
command?: NativeResourceAsyncCommand;
|
|
31
|
+
}
|
|
32
|
+
/** Return immediately; one process-wide probe refreshes all callers' cached host reading. */
|
|
33
|
+
export declare function createWindowsHostBackgroundCollector(): (options?: WindowsHostBackgroundOptions) => ResourceHostSample;
|
|
34
|
+
export declare const collectWindowsHostInBackground: (options?: WindowsHostBackgroundOptions) => ResourceHostSample;
|
|
35
|
+
export declare function parseWindowsResourceOutput(output: string, nowMs?: number): ResourceHostSample;
|
|
36
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/core/resources/native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAGL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;AAE7F,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC9B,EAAE,CAAC,EAAE,OAAO,CACV,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,sBAAsB,GAAG,SAAS,CAAC,CACtF,CAAC;IACF,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,kBAAkB,CAAC;CAC1C;AAuDD,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,OAAO,GAAE,4BAAiC,GACzC,oBAAoB,CA4FtB;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,eAAe,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAejF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAUxF;AAiCD,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED,wBAAgB,0BAA0B,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,KAAK,kBAAkB,CAuBjG;AAED,eAAO,MAAM,kBAAkB,aAzB0B,kBAAkB,KAAK,kBAyBlB,CAAC;AAE/D,MAAM,MAAM,0BAA0B,GAAG,CACvC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,0BAA0B,CAAC;CACtC;AAkBD,6FAA6F;AAC7F,wBAAgB,oCAAoC,IAAI,CACtD,OAAO,CAAC,EAAE,4BAA4B,KACnC,kBAAkB,CAuCtB;AAED,eAAO,MAAM,8BAA8B,aA1C/B,4BAA4B,KACnC,kBAyC+E,CAAC;AAmBrF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAa,GAAG,kBAAkB,CAsEjG"}
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { execFile, spawnSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
|
|
5
|
+
const WINDOWS_CACHE_MS = 15_000;
|
|
6
|
+
const COMMAND_TIMEOUT_MS = 4_000;
|
|
7
|
+
// Queries are static and read-only. Individual optional providers may be absent.
|
|
8
|
+
const WINDOWS_QUERY = `
|
|
9
|
+
$ErrorActionPreference = 'Stop'
|
|
10
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
11
|
+
$osInfo = Get-CimInstance Win32_OperatingSystem -Property TotalVisibleMemorySize,FreePhysicalMemory,NumberOfProcesses
|
|
12
|
+
$processors = $null; $pagefiles = $null; $disks = $null
|
|
13
|
+
try { $processors = @(Get-CimInstance Win32_Processor -Property NumberOfLogicalProcessors,LoadPercentage | Select-Object NumberOfLogicalProcessors,LoadPercentage) } catch {}
|
|
14
|
+
try { $pagefiles = @(Get-CimInstance Win32_PageFileUsage -Property AllocatedBaseSize,CurrentUsage | Select-Object AllocatedBaseSize,CurrentUsage) } catch {}
|
|
15
|
+
try { $disks = @(Get-CimInstance Win32_LogicalDisk -Filter 'DriveType = 3' -Property DeviceID,Size,FreeSpace | Select-Object DeviceID,Size,FreeSpace) } catch {}
|
|
16
|
+
[pscustomobject]@{
|
|
17
|
+
sampled_at = [DateTime]::UtcNow.ToString('o')
|
|
18
|
+
memory_total_kib = $osInfo.TotalVisibleMemorySize
|
|
19
|
+
memory_available_kib = $osInfo.FreePhysicalMemory
|
|
20
|
+
process_count = $osInfo.NumberOfProcesses
|
|
21
|
+
processors = $processors
|
|
22
|
+
pagefiles = $pagefiles
|
|
23
|
+
disks = $disks
|
|
24
|
+
} | ConvertTo-Json -Depth 4 -Compress
|
|
25
|
+
`;
|
|
26
|
+
function runNativeCommand(file, args) {
|
|
27
|
+
const macTools = {
|
|
28
|
+
vm_stat: "/usr/bin/vm_stat",
|
|
29
|
+
sysctl: "/usr/sbin/sysctl",
|
|
30
|
+
ps: "/bin/ps",
|
|
31
|
+
};
|
|
32
|
+
const executable = os.platform() === "darwin" ? (macTools[file] ?? file) : file;
|
|
33
|
+
const result = spawnSync(executable, [...args], {
|
|
34
|
+
encoding: "utf8",
|
|
35
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
36
|
+
maxBuffer: 1_048_576,
|
|
37
|
+
windowsHide: true,
|
|
38
|
+
env: os.platform() === "darwin" ? { ...process.env, LC_ALL: "C" } : undefined,
|
|
39
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
40
|
+
});
|
|
41
|
+
return result.status === 0 && !result.error ? result.stdout : null;
|
|
42
|
+
}
|
|
43
|
+
function readCommand(command, file, args) {
|
|
44
|
+
try {
|
|
45
|
+
return command(file, args);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function sampleNativeResources(_coordRoot, previous, options = {}) {
|
|
52
|
+
const started = performance.now();
|
|
53
|
+
const cpuBefore = process.cpuUsage();
|
|
54
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
55
|
+
const platform = options.platform ?? os.platform();
|
|
56
|
+
if (platform !== "darwin" && platform !== "win32") {
|
|
57
|
+
throw new Error("native_resource_platform_invalid");
|
|
58
|
+
}
|
|
59
|
+
const nativeOs = { ...os, ...options.os };
|
|
60
|
+
const command = options.command ?? runNativeCommand;
|
|
61
|
+
const cpuRows = nativeOs.cpus();
|
|
62
|
+
const cpu = sumCpuCounters(cpuRows);
|
|
63
|
+
const reasons = ["native_process_attribution_unavailable"];
|
|
64
|
+
let available = nonnegative(nativeOs.freemem());
|
|
65
|
+
const total = positive(nativeOs.totalmem());
|
|
66
|
+
let swap = null;
|
|
67
|
+
let processCount = null;
|
|
68
|
+
if (platform === "darwin") {
|
|
69
|
+
const vm = parseMacVmStat(readCommand(command, "vm_stat", []) ?? "");
|
|
70
|
+
if (vm) {
|
|
71
|
+
available = vm.available_bytes;
|
|
72
|
+
reasons.push("memory_available_estimated_from_free_inactive_speculative_pages");
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
reasons.push("vm_stat_unavailable_using_free_memory");
|
|
76
|
+
}
|
|
77
|
+
swap = parseMacSwapUsage(readCommand(command, "sysctl", ["-n", "vm.swapusage"]) ?? "");
|
|
78
|
+
processCount = parseProcessCount(readCommand(command, "ps", ["-axo", "pid="]));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const host = options.hostCollector?.() ??
|
|
82
|
+
(options.backgroundHost
|
|
83
|
+
? collectWindowsHostInBackground({ nowMs })
|
|
84
|
+
: collectWindowsHost({ nowMs, command }));
|
|
85
|
+
if (host.machine) {
|
|
86
|
+
swap =
|
|
87
|
+
host.machine.swap_total_bytes !== null && host.machine.swap_used_bytes !== null
|
|
88
|
+
? { total: host.machine.swap_total_bytes, used: host.machine.swap_used_bytes }
|
|
89
|
+
: null;
|
|
90
|
+
processCount = host.machine.process_count;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
reasons.push(host.reason ?? "windows_auxiliary_metrics_unavailable");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (total !== null && available !== null && available > total)
|
|
97
|
+
available = null;
|
|
98
|
+
const used = total !== null && available !== null ? total - available : null;
|
|
99
|
+
const cpuPercent = cpu ? cpuDeltaPercent(cpu, previous, nowMs) : null;
|
|
100
|
+
if (!cpu)
|
|
101
|
+
reasons.push("cpu_counters_unavailable");
|
|
102
|
+
if (!swap)
|
|
103
|
+
reasons.push("swap_unavailable");
|
|
104
|
+
if (processCount === null)
|
|
105
|
+
reasons.push("process_count_unavailable");
|
|
106
|
+
const collectorCpu = process.cpuUsage(cpuBefore);
|
|
107
|
+
return {
|
|
108
|
+
snapshot: {
|
|
109
|
+
schema_version: RESOURCE_SNAPSHOT_SCHEMA_VERSION,
|
|
110
|
+
sampled_at: new Date(nowMs).toISOString(),
|
|
111
|
+
interval_ms: previous ? Math.max(0, nowMs - previous.sampled_at_ms) : null,
|
|
112
|
+
sample_duration_ms: round1(performance.now() - started),
|
|
113
|
+
collector_cpu_ms: round1((collectorCpu.user + collectorCpu.system) / 1_000),
|
|
114
|
+
platform,
|
|
115
|
+
namespace: "host",
|
|
116
|
+
support: { state: "partial", sampler: platform, reason: reasons.join("; ") },
|
|
117
|
+
machine: {
|
|
118
|
+
cpu_percent: cpuPercent,
|
|
119
|
+
cpu_logical_count: cpuRows.length,
|
|
120
|
+
cpu_available_parallelism: nativeOs.availableParallelism(),
|
|
121
|
+
load_average: platform === "darwin" ? nativeOs.loadavg() : null,
|
|
122
|
+
memory_total_bytes: total,
|
|
123
|
+
memory_available_bytes: available,
|
|
124
|
+
memory_used_bytes: used,
|
|
125
|
+
memory_percent: used !== null && total !== null ? round1((used / total) * 100) : null,
|
|
126
|
+
swap_total_bytes: swap?.total ?? null,
|
|
127
|
+
swap_used_bytes: swap?.used ?? null,
|
|
128
|
+
process_count: processCount,
|
|
129
|
+
},
|
|
130
|
+
groups: [],
|
|
131
|
+
processes: [],
|
|
132
|
+
visible_process_count: 0,
|
|
133
|
+
omitted_process_count: processCount ?? 0,
|
|
134
|
+
unattributed_process_count: 0,
|
|
135
|
+
},
|
|
136
|
+
...(cpu
|
|
137
|
+
? {
|
|
138
|
+
state: {
|
|
139
|
+
sampled_at_ms: nowMs,
|
|
140
|
+
cpu_total_ticks: cpu.total,
|
|
141
|
+
cpu_idle_ticks: cpu.idle,
|
|
142
|
+
process_ticks: new Map(),
|
|
143
|
+
process_owners: new Map(),
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
: {}),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
export function parseMacVmStat(output) {
|
|
150
|
+
const pageSize = positive(output.match(/page size of (\d+) bytes/)?.[1]);
|
|
151
|
+
if (pageSize === null)
|
|
152
|
+
return null;
|
|
153
|
+
const fields = new Map();
|
|
154
|
+
for (const line of output.split(/\r?\n/)) {
|
|
155
|
+
const match = /^Pages (free|inactive|speculative):\s*(\d+)\.?\s*$/.exec(line.trim());
|
|
156
|
+
if (match)
|
|
157
|
+
fields.set(match[1], Number(match[2]));
|
|
158
|
+
else if (/^Pages (free|inactive|speculative):/.test(line.trim()))
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
const free = fields.get("free");
|
|
162
|
+
const inactive = fields.get("inactive");
|
|
163
|
+
if (free === undefined || inactive === undefined)
|
|
164
|
+
return null;
|
|
165
|
+
// Purgeable pages overlap other queues; adding them again would double count.
|
|
166
|
+
const available = (free + inactive + (fields.get("speculative") ?? 0)) * pageSize;
|
|
167
|
+
return Number.isSafeInteger(available) ? { available_bytes: available } : null;
|
|
168
|
+
}
|
|
169
|
+
export function parseMacSwapUsage(output) {
|
|
170
|
+
const values = new Map();
|
|
171
|
+
for (const match of output.matchAll(/\b(total|used)\s*=\s*([\d.]+)([KMGT]?)\b/g)) {
|
|
172
|
+
const multiplier = 1_024 ** (match[3] ? "KMGT".indexOf(match[3]) + 1 : 0);
|
|
173
|
+
const value = nonnegative(Number(match[2]) * multiplier);
|
|
174
|
+
if (value !== null)
|
|
175
|
+
values.set(match[1], Math.round(value));
|
|
176
|
+
}
|
|
177
|
+
const total = values.get("total");
|
|
178
|
+
const used = values.get("used");
|
|
179
|
+
return total !== undefined && used !== undefined && used <= total ? { total, used } : null;
|
|
180
|
+
}
|
|
181
|
+
function parseProcessCount(output) {
|
|
182
|
+
if (!output?.trim())
|
|
183
|
+
return null;
|
|
184
|
+
const rows = output.trim().split(/\r?\n/);
|
|
185
|
+
return rows.every((row) => /^\s*\d+\s*$/.test(row)) ? rows.length : null;
|
|
186
|
+
}
|
|
187
|
+
function sumCpuCounters(rows) {
|
|
188
|
+
let total = 0;
|
|
189
|
+
let idle = 0;
|
|
190
|
+
if (rows.length === 0)
|
|
191
|
+
return null;
|
|
192
|
+
for (const row of rows) {
|
|
193
|
+
const times = [row.times.user, row.times.nice, row.times.sys, row.times.idle, row.times.irq];
|
|
194
|
+
if (times.some((time) => nonnegative(time) === null))
|
|
195
|
+
return null;
|
|
196
|
+
total += times.reduce((sum, value) => sum + value, 0);
|
|
197
|
+
idle += row.times.idle;
|
|
198
|
+
}
|
|
199
|
+
return Number.isSafeInteger(total) && total > 0 ? { total, idle } : null;
|
|
200
|
+
}
|
|
201
|
+
function cpuDeltaPercent(cpu, previous, nowMs) {
|
|
202
|
+
if (!previous || nowMs <= previous.sampled_at_ms)
|
|
203
|
+
return null;
|
|
204
|
+
const totalDelta = cpu.total - previous.cpu_total_ticks;
|
|
205
|
+
const idleDelta = cpu.idle - previous.cpu_idle_ticks;
|
|
206
|
+
if (totalDelta <= 0 || idleDelta < 0 || idleDelta > totalDelta)
|
|
207
|
+
return null;
|
|
208
|
+
return round1(((totalDelta - idleDelta) / totalDelta) * 100);
|
|
209
|
+
}
|
|
210
|
+
export function createWindowsHostCollector() {
|
|
211
|
+
const cache = new WeakMap();
|
|
212
|
+
return (options = {}) => {
|
|
213
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
214
|
+
const command = options.command ?? runNativeCommand;
|
|
215
|
+
const cached = cache.get(command);
|
|
216
|
+
if (cached && nowMs >= cached.at && nowMs - cached.at < WINDOWS_CACHE_MS)
|
|
217
|
+
return cached.sample;
|
|
218
|
+
let sample;
|
|
219
|
+
try {
|
|
220
|
+
const executable = command === runNativeCommand ? windowsPowerShellExecutable() : "powershell.exe";
|
|
221
|
+
const output = command(executable, windowsPowerShellArgs());
|
|
222
|
+
sample =
|
|
223
|
+
output === null
|
|
224
|
+
? unavailableWindowsHost(nowMs, "windows_host_query_failed")
|
|
225
|
+
: parseWindowsResourceOutput(output, nowMs);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
sample = unavailableWindowsHost(nowMs, "windows_host_query_failed");
|
|
229
|
+
}
|
|
230
|
+
// Cache failures too: missing interop/CIM must not launch PowerShell every tick.
|
|
231
|
+
cache.set(command, { at: nowMs, sample });
|
|
232
|
+
return sample;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
export const collectWindowsHost = createWindowsHostCollector();
|
|
236
|
+
function runWindowsCommandAsync(file, args) {
|
|
237
|
+
return new Promise((resolve) => {
|
|
238
|
+
execFile(file, [...args], {
|
|
239
|
+
encoding: "utf8",
|
|
240
|
+
timeout: COMMAND_TIMEOUT_MS,
|
|
241
|
+
maxBuffer: 1_048_576,
|
|
242
|
+
windowsHide: true,
|
|
243
|
+
}, (error, stdout) => resolve(error ? null : stdout));
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/** Return immediately; one process-wide probe refreshes all callers' cached host reading. */
|
|
247
|
+
export function createWindowsHostBackgroundCollector() {
|
|
248
|
+
const cache = new WeakMap();
|
|
249
|
+
return (options = {}) => {
|
|
250
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
251
|
+
const command = options.command ?? runWindowsCommandAsync;
|
|
252
|
+
let entry = cache.get(command);
|
|
253
|
+
if (entry?.pending || (entry && nowMs >= entry.at && nowMs - entry.at < WINDOWS_CACHE_MS))
|
|
254
|
+
return entry.sample;
|
|
255
|
+
entry ??= {
|
|
256
|
+
at: nowMs,
|
|
257
|
+
sample: { ...unavailableWindowsHost(nowMs, "windows_host_query_pending"), state: "partial" },
|
|
258
|
+
pending: false,
|
|
259
|
+
};
|
|
260
|
+
entry.at = nowMs;
|
|
261
|
+
entry.pending = true;
|
|
262
|
+
cache.set(command, entry);
|
|
263
|
+
const current = entry;
|
|
264
|
+
const executable = command === runWindowsCommandAsync ? windowsPowerShellExecutable() : "powershell.exe";
|
|
265
|
+
// Resolve on a microtask so even an injected synchronous throw cannot interrupt a tick.
|
|
266
|
+
void Promise.resolve()
|
|
267
|
+
.then(() => command(executable, windowsPowerShellArgs()))
|
|
268
|
+
.then((output) => {
|
|
269
|
+
current.sample =
|
|
270
|
+
output === null
|
|
271
|
+
? unavailableWindowsHost(nowMs, "windows_host_query_failed")
|
|
272
|
+
: parseWindowsResourceOutput(output, nowMs);
|
|
273
|
+
})
|
|
274
|
+
.catch(() => {
|
|
275
|
+
current.sample = unavailableWindowsHost(nowMs, "windows_host_query_failed");
|
|
276
|
+
})
|
|
277
|
+
.finally(() => {
|
|
278
|
+
current.pending = false;
|
|
279
|
+
});
|
|
280
|
+
return current.sample;
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
export const collectWindowsHostInBackground = createWindowsHostBackgroundCollector();
|
|
284
|
+
function windowsPowerShellExecutable() {
|
|
285
|
+
// A WSL toolchain may deliberately exclude Windows executables from PATH.
|
|
286
|
+
const wslPowerShell = "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe";
|
|
287
|
+
return os.platform() === "linux" && existsSync(wslPowerShell) ? wslPowerShell : "powershell.exe";
|
|
288
|
+
}
|
|
289
|
+
function windowsPowerShellArgs() {
|
|
290
|
+
// Preserve the static multiline program across both Win32 and WSL argument transports.
|
|
291
|
+
return [
|
|
292
|
+
"-NoLogo",
|
|
293
|
+
"-NoProfile",
|
|
294
|
+
"-NonInteractive",
|
|
295
|
+
"-EncodedCommand",
|
|
296
|
+
Buffer.from(WINDOWS_QUERY, "utf16le").toString("base64"),
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
export function parseWindowsResourceOutput(output, nowMs = Date.now()) {
|
|
300
|
+
let row;
|
|
301
|
+
try {
|
|
302
|
+
const parsed = JSON.parse(output.replace(/^\uFEFF/, "").trim());
|
|
303
|
+
if (!isRecord(parsed))
|
|
304
|
+
throw new Error("invalid");
|
|
305
|
+
row = parsed;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return unavailableWindowsHost(nowMs, "windows_host_output_invalid");
|
|
309
|
+
}
|
|
310
|
+
const totalKiB = positive(row.memory_total_kib);
|
|
311
|
+
const availableKiB = nonnegative(row.memory_available_kib);
|
|
312
|
+
if (totalKiB === null || availableKiB === null || availableKiB > totalKiB) {
|
|
313
|
+
return unavailableWindowsHost(nowMs, "windows_host_memory_invalid");
|
|
314
|
+
}
|
|
315
|
+
const processors = records(row.processors);
|
|
316
|
+
let logical = 0;
|
|
317
|
+
let weightedCpu = 0;
|
|
318
|
+
let cpuValid = processors !== null && processors.length > 0;
|
|
319
|
+
for (const processor of processors ?? []) {
|
|
320
|
+
const count = positive(processor.NumberOfLogicalProcessors);
|
|
321
|
+
const percent = nonnegative(processor.LoadPercentage);
|
|
322
|
+
if (count === null || !Number.isInteger(count))
|
|
323
|
+
cpuValid = false;
|
|
324
|
+
else
|
|
325
|
+
logical += count;
|
|
326
|
+
if (count === null || percent === null || percent > 100)
|
|
327
|
+
cpuValid = false;
|
|
328
|
+
else
|
|
329
|
+
weightedCpu += count * percent;
|
|
330
|
+
}
|
|
331
|
+
const pagefiles = records(row.pagefiles);
|
|
332
|
+
let swapTotal = 0;
|
|
333
|
+
let swapUsed = 0;
|
|
334
|
+
let swapValid = pagefiles !== null;
|
|
335
|
+
for (const file of pagefiles ?? []) {
|
|
336
|
+
const total = nonnegative(file.AllocatedBaseSize);
|
|
337
|
+
const used = nonnegative(file.CurrentUsage);
|
|
338
|
+
if (total === null || used === null || used > total)
|
|
339
|
+
swapValid = false;
|
|
340
|
+
else {
|
|
341
|
+
swapTotal += total * 1_048_576;
|
|
342
|
+
swapUsed += used * 1_048_576;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const disks = (records(row.disks) ?? []).map(parseWindowsDisk);
|
|
346
|
+
const processCount = nonnegative(row.process_count);
|
|
347
|
+
const machine = {
|
|
348
|
+
cpu_percent: cpuValid && logical > 0 ? round1(weightedCpu / logical) : null,
|
|
349
|
+
cpu_logical_count: logical,
|
|
350
|
+
load_average: null,
|
|
351
|
+
memory_total_bytes: totalKiB * 1_024,
|
|
352
|
+
memory_available_bytes: availableKiB * 1_024,
|
|
353
|
+
memory_used_bytes: (totalKiB - availableKiB) * 1_024,
|
|
354
|
+
memory_percent: round1(((totalKiB - availableKiB) / totalKiB) * 100),
|
|
355
|
+
swap_total_bytes: swapValid ? swapTotal : null,
|
|
356
|
+
swap_used_bytes: swapValid ? swapUsed : null,
|
|
357
|
+
process_count: processCount !== null && Number.isInteger(processCount) ? processCount : null,
|
|
358
|
+
};
|
|
359
|
+
const complete = cpuValid &&
|
|
360
|
+
swapValid &&
|
|
361
|
+
machine.process_count !== null &&
|
|
362
|
+
disks.length > 0 &&
|
|
363
|
+
disks.every((disk) => disk.state === "supported");
|
|
364
|
+
return {
|
|
365
|
+
platform: "win32",
|
|
366
|
+
sampled_at: typeof row.sampled_at === "string" && Number.isFinite(Date.parse(row.sampled_at))
|
|
367
|
+
? new Date(row.sampled_at).toISOString()
|
|
368
|
+
: new Date(nowMs).toISOString(),
|
|
369
|
+
state: complete ? "supported" : "partial",
|
|
370
|
+
machine,
|
|
371
|
+
disks,
|
|
372
|
+
...(!complete ? { reason: "windows_host_optional_metrics_unavailable" } : {}),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function parseWindowsDisk(row) {
|
|
376
|
+
const total = positive(row.Size);
|
|
377
|
+
const available = nonnegative(row.FreeSpace);
|
|
378
|
+
const valid = typeof row.DeviceID === "string" && total !== null && available !== null && available <= total;
|
|
379
|
+
return {
|
|
380
|
+
path: typeof row.DeviceID === "string" ? `${row.DeviceID}\\` : "unknown",
|
|
381
|
+
state: valid ? "supported" : "error",
|
|
382
|
+
total_bytes: valid ? total : null,
|
|
383
|
+
available_bytes: valid ? available : null,
|
|
384
|
+
used_percent: valid ? round1(((total - available) / total) * 100) : null,
|
|
385
|
+
...(!valid ? { reason: "windows_disk_counters_invalid" } : {}),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function unavailableWindowsHost(nowMs, reason) {
|
|
389
|
+
return {
|
|
390
|
+
platform: "win32",
|
|
391
|
+
sampled_at: new Date(nowMs).toISOString(),
|
|
392
|
+
state: "error",
|
|
393
|
+
machine: null,
|
|
394
|
+
disks: [],
|
|
395
|
+
reason,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function isRecord(value) {
|
|
399
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
400
|
+
}
|
|
401
|
+
function records(value) {
|
|
402
|
+
return Array.isArray(value) && value.every(isRecord) ? value : null;
|
|
403
|
+
}
|
|
404
|
+
function nonnegative(value) {
|
|
405
|
+
if (typeof value !== "number" && !(typeof value === "string" && /^\d+(\.\d+)?$/.test(value)))
|
|
406
|
+
return null;
|
|
407
|
+
const number = Number(value);
|
|
408
|
+
return Number.isFinite(number) && number >= 0 && number <= Number.MAX_SAFE_INTEGER
|
|
409
|
+
? number
|
|
410
|
+
: null;
|
|
411
|
+
}
|
|
412
|
+
function positive(value) {
|
|
413
|
+
const number = nonnegative(value);
|
|
414
|
+
return number !== null && number > 0 ? number : null;
|
|
415
|
+
}
|
|
416
|
+
function round1(value) {
|
|
417
|
+
return Math.round(value * 10) / 10;
|
|
418
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampler.d.ts","sourceRoot":"","sources":["../../../src/core/resources/sampler.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"sampler.d.ts","sourceRoot":"","sources":["../../../src/core/resources/sampler.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAC;AAgCvB,UAAU,sBAAsB;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,oBAAoB,EAC/B,OAAO,GAAE,sBAA2B,GACnC,oBAAoB,CA+BtB;AA2JD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG;IACnD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,IAAI,CA0BP;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAuB7D"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, readlinkSync } from "node:fs";
|
|
3
|
-
import { cpus, loadavg, platform, release } from "node:os";
|
|
3
|
+
import { availableParallelism, cpus, loadavg, platform, release } from "node:os";
|
|
4
4
|
import { basename, join } from "node:path";
|
|
5
5
|
import { performance } from "node:perf_hooks";
|
|
6
6
|
import { readLiveCoordinationRows } from "../agents/state/live-coordination-view.js";
|
|
7
7
|
import { parsePidmapRow } from "../agents/state/pidmap.js";
|
|
8
8
|
import { checkPidToken } from "../agents/state/proc-start.js";
|
|
9
9
|
import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
|
|
10
|
+
import { collectWindowsHost, collectWindowsHostInBackground, sampleNativeResources, } from "./native.js";
|
|
11
|
+
import { collectSystemResources } from "./system.js";
|
|
10
12
|
const DEFAULT_CLOCK_TICKS = 100;
|
|
11
13
|
const DEFAULT_PAGE_SIZE = 4_096;
|
|
12
14
|
const DEFAULT_UNATTRIBUTED_CPU_FLOOR = 0.5;
|
|
@@ -16,6 +18,34 @@ const MAX_COMMAND_CHARS = 240;
|
|
|
16
18
|
let cachedClockTicks;
|
|
17
19
|
let cachedPageSize;
|
|
18
20
|
export function sampleResources(coordRoot, previous, options = {}) {
|
|
21
|
+
const started = performance.now();
|
|
22
|
+
const cpuBefore = process.cpuUsage();
|
|
23
|
+
const currentPlatform = platform();
|
|
24
|
+
const result = currentPlatform === "darwin" || currentPlatform === "win32"
|
|
25
|
+
? sampleNativeResources(coordRoot, previous, {
|
|
26
|
+
nowMs: options.nowMs,
|
|
27
|
+
backgroundHost: options.backgroundHost,
|
|
28
|
+
})
|
|
29
|
+
: sampleProcessResources(coordRoot, previous, options);
|
|
30
|
+
Object.assign(result.snapshot, collectSystemResources(coordRoot, {
|
|
31
|
+
procRoot: options.procRoot,
|
|
32
|
+
sysRoot: options.sysRoot,
|
|
33
|
+
nowMs: options.nowMs,
|
|
34
|
+
namespace: result.snapshot.namespace,
|
|
35
|
+
}));
|
|
36
|
+
result.snapshot.machine.cpu_available_parallelism = availableParallelism();
|
|
37
|
+
// A fixture procfs has no relationship to the actual Windows host.
|
|
38
|
+
if (result.snapshot.namespace === "wsl" && !options.procRoot) {
|
|
39
|
+
result.snapshot.host = options.backgroundHost
|
|
40
|
+
? collectWindowsHostInBackground()
|
|
41
|
+
: collectWindowsHost();
|
|
42
|
+
}
|
|
43
|
+
result.snapshot.sample_duration_ms = round1(performance.now() - started);
|
|
44
|
+
const cpuUsed = process.cpuUsage(cpuBefore);
|
|
45
|
+
result.snapshot.collector_cpu_ms = round1((cpuUsed.user + cpuUsed.system) / 1_000);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
function sampleProcessResources(coordRoot, previous, options = {}) {
|
|
19
49
|
const started = performance.now();
|
|
20
50
|
const cpuBefore = process.cpuUsage();
|
|
21
51
|
const nowMs = options.nowMs ?? Date.now();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type PressureAssessment, type PressureHysteresisState } from "../diagnostics/contract.js";
|
|
2
|
+
import { type SupervisorCapability, type SupervisorPressureRecord } from "../supervisor/contract.js";
|
|
3
|
+
import { type ResourceDiskSample, type ResourceHostSample, type ResourceIoSample, type ResourceMachineSample, type ResourceOomSample, type ResourcePressureSample, type ResourceProcessSample, type ResourceSnapshot } from "./contract.js";
|
|
4
|
+
export declare const RESOURCE_STATUS_STALE_MS = 15000;
|
|
5
|
+
export declare const RESOURCE_STATUS_MAX_BYTES: number;
|
|
6
|
+
export declare const RESOURCE_STATUS_PROCESS_LIMIT = 20;
|
|
7
|
+
export declare const RESOURCE_HOST_STATUS_STALE_MS = 30000;
|
|
8
|
+
export interface ResourceStatus {
|
|
9
|
+
schema_version: 2;
|
|
10
|
+
state: "fresh" | "stale" | "unavailable";
|
|
11
|
+
reason: string | null;
|
|
12
|
+
sampled_at: string | null;
|
|
13
|
+
sample_age_ms: number | null;
|
|
14
|
+
stale_after_ms: number;
|
|
15
|
+
platform: NodeJS.Platform | null;
|
|
16
|
+
namespace: ResourceSnapshot["namespace"];
|
|
17
|
+
support: ResourceSnapshot["support"] | null;
|
|
18
|
+
writer: {
|
|
19
|
+
running: boolean;
|
|
20
|
+
stale: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The one published pressure assessment, read from the observer's record so
|
|
24
|
+
* this surface, the prompt notice, the dashboard, and a diagnostic bundle all
|
|
25
|
+
* report the same answer for the same input.
|
|
26
|
+
*/
|
|
27
|
+
assessment: PressureAssessment;
|
|
28
|
+
/** The state the sample before the published one carried forward. */
|
|
29
|
+
prior_hysteresis: PressureHysteresisState | null;
|
|
30
|
+
/** Where the assessment came from, and why it is missing when it is. */
|
|
31
|
+
assessment_capability: SupervisorCapability;
|
|
32
|
+
machine: ResourceMachineSample | null;
|
|
33
|
+
disks: ResourceDiskSample[];
|
|
34
|
+
pressure: ResourcePressureSample | null;
|
|
35
|
+
oom: ResourceOomSample | null;
|
|
36
|
+
io: ResourceIoSample | null;
|
|
37
|
+
host: ResourceHostSample | null;
|
|
38
|
+
processes?: Array<Pick<ResourceProcessSample, "pid" | "name" | "cpu_percent" | "rss_bytes" | "owner_kind" | "owner_id">>;
|
|
39
|
+
processes_omitted?: number;
|
|
40
|
+
}
|
|
41
|
+
/** A bounded cache-only read. Never samples the OS or starts the writer. */
|
|
42
|
+
export declare function readResourceStatus(coordRoot: string, options?: {
|
|
43
|
+
nowMs?: number;
|
|
44
|
+
includeProcesses?: boolean;
|
|
45
|
+
}): ResourceStatus;
|
|
46
|
+
export declare function formatResourceSummary(status: ResourceStatus): string;
|
|
47
|
+
export declare function formatResourceStatus(status: ResourceStatus, bin: string): string;
|
|
48
|
+
export declare const PRESSURE_RECORD_MAX_BYTES: number;
|
|
49
|
+
export interface PublishedPressure {
|
|
50
|
+
assessment: PressureAssessment;
|
|
51
|
+
prior_hysteresis: PressureHysteresisState | null;
|
|
52
|
+
capability: SupervisorCapability;
|
|
53
|
+
record: SupervisorPressureRecord | null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Read the assessment the observer published. Bounded, cache only, and never a
|
|
57
|
+
* computation: a missing, stale, or malformed record yields `unknown` with the
|
|
58
|
+
* reason stated, because a gap in the evidence is not a measurement of health.
|
|
59
|
+
*/
|
|
60
|
+
export declare function readPublishedPressure(coordRoot: string, nowMs?: number, writer?: ResourceStatus["writer"]): PublishedPressure;
|
|
61
|
+
//# sourceMappingURL=status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EAEtB,MAAM,eAAe,CAAC;AAGvB,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,yBAAyB,QAAkB,CAAC;AACzD,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,6BAA6B,QAAS,CAAC;AAGpD,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,aAAa,CAAC;IACzC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzC,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC5C,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7C;;;;OAIG;IACH,UAAU,EAAE,kBAAkB,CAAC;IAC/B,qEAAqE;IACrE,gBAAgB,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,wEAAwE;IACxE,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACtC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,QAAQ,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACxC,GAAG,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC9B,EAAE,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC5B,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,SAAS,CAAC,EAAE,KAAK,CACf,IAAI,CACF,qBAAqB,EACrB,KAAK,GAAG,MAAM,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,GAAG,UAAU,CACzE,CACF,CAAC;IACF,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3D,cAAc,CA8HhB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAsBpE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAqEhF;AAaD,eAAO,MAAM,yBAAyB,QAAa,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,gBAAgB,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,UAAU,EAAE,oBAAoB,CAAC;IACjC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAChC,iBAAiB,CA0EnB"}
|