harnery 0.34.1 → 0.36.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/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -94
- package/dist/commands/agents.d.ts +37 -6
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +466 -371
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +31 -6
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +2 -2
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/commands/events.js +18 -1
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts +4 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +199 -0
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +84 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +12 -0
- package/dist/core/agents/claim-path.d.ts +11 -0
- package/dist/core/agents/claim-path.d.ts.map +1 -0
- package/dist/core/agents/claim-path.js +22 -0
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/coord-client.d.ts +29 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +88 -9
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +245 -13
- package/dist/core/agents/live-lifecycle-v3.js +9 -4
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +8 -3
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +36 -17
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +115 -22
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/session-name-display.d.ts +1 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +8 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-reader.js +25 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +9 -48
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +34 -34
- package/dist/core/agents/state/live-coordination-view.d.ts +6 -8
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +16 -67
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/agents/state/names.d.ts +9 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +190 -182
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -5
- package/dist/core/artifacts/constants.d.ts +5 -0
- package/dist/core/artifacts/constants.d.ts.map +1 -0
- package/dist/core/artifacts/constants.js +4 -0
- package/dist/core/artifacts/index.d.ts +24 -3
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +96 -8
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +851 -16
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +50 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.d.ts +11 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +26 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +8 -5
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +7 -4
- package/dist/core/events/v3/latency.d.ts +31 -1
- package/dist/core/events/v3/latency.d.ts.map +1 -1
- package/dist/core/events/v3/latency.js +127 -3
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +42 -20
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +153 -41
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +10 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +90 -13
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +83 -2
- package/dist/core/events/v3/producers/intake.d.ts +13 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +36 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +117 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +992 -27
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +52 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +21 -6
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/parse.d.ts +3 -0
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +14 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +142 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +869 -0
- package/dist/core/hooks/cli.js +318 -61
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +39 -0
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
- package/dist/core/hooks/remediation-cap.js +63 -0
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +33 -9
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +33 -10
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +37 -0
- package/dist/core/semantic/adapters.d.ts.map +1 -0
- package/dist/core/semantic/adapters.js +360 -0
- package/dist/core/semantic/contract.d.ts +1072 -0
- package/dist/core/semantic/contract.d.ts.map +1 -0
- package/dist/core/semantic/contract.js +331 -0
- package/dist/core/semantic/evidence.d.ts +11 -0
- package/dist/core/semantic/evidence.d.ts.map +1 -0
- package/dist/core/semantic/evidence.js +262 -0
- package/dist/core/semantic/index.d.ts +14 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +13 -0
- package/dist/core/semantic/once.d.ts +38 -0
- package/dist/core/semantic/once.d.ts.map +1 -0
- package/dist/core/semantic/once.js +364 -0
- package/dist/core/semantic/prompt.d.ts +12 -0
- package/dist/core/semantic/prompt.d.ts.map +1 -0
- package/dist/core/semantic/prompt.js +83 -0
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +27 -0
- package/dist/core/semantic/scheduler.d.ts.map +1 -0
- package/dist/core/semantic/scheduler.js +91 -0
- package/dist/core/semantic/service-status.d.ts +51 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -0
- package/dist/core/semantic/service-status.js +140 -0
- package/dist/core/semantic/service.d.ts +52 -0
- package/dist/core/semantic/service.d.ts.map +1 -0
- package/dist/core/semantic/service.js +559 -0
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +81 -0
- package/dist/core/semantic/storage.d.ts.map +1 -0
- package/dist/core/semantic/storage.js +180 -0
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +18 -0
- package/dist/core/semantic/validate.d.ts.map +1 -0
- package/dist/core/semantic/validate.js +207 -0
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/browser/client.d.ts +11 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +13 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.d.ts +25 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -0
- package/dist/lib/browser/standalone-html.js +284 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +1 -0
- package/dist/lib/instructions/templates.d.ts +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +149 -4
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +34 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +3073 -581
- package/src/commander.ts +462 -93
- package/src/commands/agents.ts +617 -355
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +31 -9
- package/src/commands/conversations.ts +279 -0
- package/src/commands/decision.ts +8 -2
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/events.ts +21 -1
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/presence.ts +7 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +244 -0
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +92 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/canonical-emit.ts +15 -0
- package/src/core/agents/claim-path.ts +23 -0
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/coord-client.ts +92 -8
- package/src/core/agents/live-authority-v3.ts +342 -14
- package/src/core/agents/live-lifecycle-v3.ts +14 -4
- package/src/core/agents/live-observation-v3.ts +13 -3
- package/src/core/agents/render/prompt-context.ts +40 -16
- package/src/core/agents/rules/stop-hook.ts +129 -25
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/session-name-display.ts +9 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-reader.ts +69 -0
- package/src/core/agents/state/heartbeat-writer.ts +47 -84
- package/src/core/agents/state/live-coordination-view.ts +17 -81
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/agents/state/names.ts +190 -182
- package/src/core/agents/state/stale-sweep.ts +25 -5
- package/src/core/artifacts/constants.ts +4 -0
- package/src/core/artifacts/index.ts +113 -8
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +56 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +37 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +26 -2
- package/src/core/events/v3/latency.ts +213 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +182 -45
- package/src/core/events/v3/producers/command-recorder.ts +10 -1
- package/src/core/events/v3/producers/coordination-recorder.ts +112 -15
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +116 -2
- package/src/core/events/v3/producers/intake.ts +48 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +1403 -30
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +143 -0
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +66 -5
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/parse.ts +16 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +1200 -0
- package/src/core/hooks/cli.ts +342 -64
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +83 -0
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +55 -11
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +452 -0
- package/src/core/semantic/contract.ts +430 -0
- package/src/core/semantic/evidence.ts +336 -0
- package/src/core/semantic/index.ts +201 -0
- package/src/core/semantic/once.ts +496 -0
- package/src/core/semantic/prompt.ts +96 -0
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +151 -0
- package/src/core/semantic/service-status.ts +212 -0
- package/src/core/semantic/service.ts +681 -0
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +300 -0
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +243 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/browser/client.ts +21 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/standalone-html.ts +312 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/apply.ts +1 -0
- package/src/lib/instructions/templates.ts +154 -4
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { closeSync, existsSync, openSync, readdirSync, readSync, statSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { transcriptPathCandidates } from "../resolve/transcript.js";
|
|
6
|
+
const DEFAULT_TAIL_BYTES = 256 * 1024;
|
|
7
|
+
/**
|
|
8
|
+
* An active turn can accumulate enough tool traffic to push its native turn
|
|
9
|
+
* ancestor beyond the ordinary status tail. Keep attribution bounded while
|
|
10
|
+
* giving long-running interactive turns a larger matching window.
|
|
11
|
+
*/
|
|
12
|
+
const ACTIVE_TURN_TAIL_BYTES = 4 * 1024 * 1024;
|
|
13
|
+
const DEFAULT_MAX_SAMPLE_AGE_MS = 30_000;
|
|
14
|
+
const DEFAULT_MAX_CURSOR_DATABASES = 8;
|
|
15
|
+
const SESSION_CACHE_LIMIT = 128;
|
|
16
|
+
const codexTranscriptCache = new Map();
|
|
17
|
+
const cursorDatabaseCache = new Map();
|
|
18
|
+
/**
|
|
19
|
+
* Read privacy-safe context telemetry from a local runtime transcript.
|
|
20
|
+
*
|
|
21
|
+
* The returned union contains only numeric measurements, timestamps, bounded
|
|
22
|
+
* I/O counters, and a privacy-safe witness. Transcript bodies and paths never
|
|
23
|
+
* cross this interface.
|
|
24
|
+
*/
|
|
25
|
+
export function readRuntimeContextTelemetry(request, options = {}) {
|
|
26
|
+
const startedAt = performance.now();
|
|
27
|
+
if (!request.session_id)
|
|
28
|
+
return unsupported("runtime_session_id_not_reported", startedAt);
|
|
29
|
+
if (request.mode !== "status" && !request.turn_id && request.adapter !== "cursor") {
|
|
30
|
+
return unsupported("runtime_turn_id_not_reported", startedAt);
|
|
31
|
+
}
|
|
32
|
+
if (request.adapter === "codex")
|
|
33
|
+
return readCodexContext(request, options, startedAt);
|
|
34
|
+
if (request.adapter === "claude-code")
|
|
35
|
+
return readClaudeContext(request, options, startedAt);
|
|
36
|
+
if (request.adapter === "cursor")
|
|
37
|
+
return readCursorContext(request, options, startedAt);
|
|
38
|
+
return unsupported("runtime_adapter_not_supported", startedAt);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Locate a Codex rollout transcript for a session when the hook payload
|
|
42
|
+
* carries no transcript_path. Codex omits the path on its hook events, which
|
|
43
|
+
* leaves transcript-backed evidence unavailable unless Harnery resolves the
|
|
44
|
+
* rollout itself. Discovery reuses the telemetry scanner's roots (native
|
|
45
|
+
* ~/.codex plus WSL-mounted Windows homes) and its process cache, and returns
|
|
46
|
+
* undefined on zero or ambiguous matches.
|
|
47
|
+
*
|
|
48
|
+
* Callers on repeated hook paths must retain the verified result in their
|
|
49
|
+
* owner-only session state. The process cache bounds repeated reads inside one
|
|
50
|
+
* process, but hook processes are intentionally short-lived.
|
|
51
|
+
*/
|
|
52
|
+
export function discoverCodexSessionTranscript(sessionId, transcriptPath, options = {}) {
|
|
53
|
+
if (!sessionId || !/^[0-9a-f][0-9a-f-]{14,62}[0-9a-f]$/i.test(sessionId))
|
|
54
|
+
return undefined;
|
|
55
|
+
const resolution = resolveCodexTranscript({ adapter: "codex", session_id: sessionId, transcript_path: transcriptPath, mode: "status" }, options);
|
|
56
|
+
return resolution.state === "found" ? resolution.path : undefined;
|
|
57
|
+
}
|
|
58
|
+
/** Status compatibility wrapper: exact pairs render; partial values do not. */
|
|
59
|
+
export function readRuntimeContextUsage(adapter, sessionId, options = {}) {
|
|
60
|
+
const result = readRuntimeContextTelemetry({ adapter, session_id: sessionId, mode: "status" }, options);
|
|
61
|
+
return result.state === "observed" && "used_tokens" in result
|
|
62
|
+
? { used: result.used_tokens, window: result.limit_tokens }
|
|
63
|
+
: null;
|
|
64
|
+
}
|
|
65
|
+
export function clearRuntimeTelemetryCachesForTest() {
|
|
66
|
+
codexTranscriptCache.clear();
|
|
67
|
+
cursorDatabaseCache.clear();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Read the newest observed tuning (effort, and speed where reported) for a
|
|
71
|
+
* session from its local runtime transcript.
|
|
72
|
+
*
|
|
73
|
+
* Codex: the newest `turn_context` row carries the EFFECTIVE per-turn effort,
|
|
74
|
+
* including `-c model_reasoning_effort` overrides (the config default is
|
|
75
|
+
* deliberately not consulted — it is the default, not the effective value).
|
|
76
|
+
* CC: the newest assistant row carries effort at the row's top level and
|
|
77
|
+
* speed inside `message.usage`; model, effort, and speed are read from the
|
|
78
|
+
* SAME row so a mid-session model swap cannot blend two rows' values.
|
|
79
|
+
*
|
|
80
|
+
* Same bounded tail-read and privacy posture as `readRuntimeContextTelemetry`:
|
|
81
|
+
* only tokens, timestamps, and I/O counters cross this interface.
|
|
82
|
+
*/
|
|
83
|
+
export function readRuntimeTuning(request, options = {}) {
|
|
84
|
+
const startedAt = performance.now();
|
|
85
|
+
if (request.adapter === "codex") {
|
|
86
|
+
if (!request.session_id)
|
|
87
|
+
return unsupported("runtime_session_id_not_reported", startedAt);
|
|
88
|
+
return readCodexTuning(request, options, startedAt);
|
|
89
|
+
}
|
|
90
|
+
if (request.adapter === "claude-code")
|
|
91
|
+
return readClaudeTuning(request, options, startedAt);
|
|
92
|
+
return unsupported("runtime_adapter_not_supported", startedAt);
|
|
93
|
+
}
|
|
94
|
+
function readCodexTuning(request, options, startedAt) {
|
|
95
|
+
const resolved = resolveCodexTranscript({
|
|
96
|
+
adapter: "codex",
|
|
97
|
+
session_id: request.session_id,
|
|
98
|
+
transcript_path: request.transcript_path,
|
|
99
|
+
mode: "status",
|
|
100
|
+
}, options);
|
|
101
|
+
if (resolved.state === "missing") {
|
|
102
|
+
return unsupported("runtime_context_telemetry_unavailable", startedAt);
|
|
103
|
+
}
|
|
104
|
+
if (resolved.state === "ambiguous") {
|
|
105
|
+
return tuningPartial("codex_transcript_ambiguous", 0, startedAt);
|
|
106
|
+
}
|
|
107
|
+
if (resolved.state === "mismatch") {
|
|
108
|
+
return tuningPartial("codex_transcript_session_mismatch", 0, startedAt);
|
|
109
|
+
}
|
|
110
|
+
const tail = readTail(resolved.path, options.maxTailBytes ?? DEFAULT_TAIL_BYTES);
|
|
111
|
+
if (!tail)
|
|
112
|
+
return tuningPartial("codex_transcript_unreadable", 0, startedAt);
|
|
113
|
+
const fromTail = newestTurnContextTuning(parseRuntimeRows(tail.text), tail.bytes, startedAt);
|
|
114
|
+
if (fromTail)
|
|
115
|
+
return fromTail;
|
|
116
|
+
// `turn_context` is written at the START of a turn, so one long turn pushes
|
|
117
|
+
// it past the bounded tail. The front of the file is then the reliable
|
|
118
|
+
// place, but not a fixed-size head: a real interactive rollout opens with
|
|
119
|
+
// hundreds of KB of session_meta, instruction, and world_state rows before
|
|
120
|
+
// the first turn_context (observed live: 272KB in a desktop session). Scan
|
|
121
|
+
// forward in bounded chunks and keep the LAST match inside the cap; rows
|
|
122
|
+
// between the cap and the tail window stay unscanned, and the stop-time
|
|
123
|
+
// re-read heals any staleness that gap could cause.
|
|
124
|
+
const forward = scanForwardTurnContext(resolved.path, TUNING_FORWARD_SCAN_MAX_BYTES);
|
|
125
|
+
if (forward.row) {
|
|
126
|
+
const fromForward = newestTurnContextTuning([forward.row], tail.bytes + forward.bytes, startedAt);
|
|
127
|
+
if (fromForward)
|
|
128
|
+
return fromForward;
|
|
129
|
+
}
|
|
130
|
+
return tuningPartial("codex_transcript_turn_context_missing", tail.bytes + forward.bytes, startedAt);
|
|
131
|
+
}
|
|
132
|
+
/** Forward-scan budget for the first turn_context; generous against
|
|
133
|
+
* instruction/world_state bloat while still bounding a runaway file. */
|
|
134
|
+
const TUNING_FORWARD_SCAN_MAX_BYTES = 4 * 1024 * 1024;
|
|
135
|
+
const TUNING_FORWARD_CHUNK_BYTES = 256 * 1024;
|
|
136
|
+
/** Stream the file from the start in bounded chunks, returning the last
|
|
137
|
+
* parseable `turn_context` row inside the budget and the bytes read. */
|
|
138
|
+
function scanForwardTurnContext(path, maxBytes) {
|
|
139
|
+
let fd;
|
|
140
|
+
let bytesRead = 0;
|
|
141
|
+
let remainder = "";
|
|
142
|
+
let match;
|
|
143
|
+
try {
|
|
144
|
+
fd = openSync(path, "r");
|
|
145
|
+
const buffer = Buffer.alloc(TUNING_FORWARD_CHUNK_BYTES);
|
|
146
|
+
while (bytesRead < maxBytes) {
|
|
147
|
+
const read = readSync(fd, buffer, 0, buffer.length, bytesRead);
|
|
148
|
+
if (read <= 0)
|
|
149
|
+
break;
|
|
150
|
+
bytesRead += read;
|
|
151
|
+
const text = remainder + buffer.subarray(0, read).toString("utf8");
|
|
152
|
+
const lines = text.split("\n");
|
|
153
|
+
remainder = lines.pop() ?? "";
|
|
154
|
+
for (const line of lines) {
|
|
155
|
+
if (!line.includes('"turn_context"'))
|
|
156
|
+
continue;
|
|
157
|
+
const rows = parseRuntimeRows(line);
|
|
158
|
+
const row = rows.find((candidate) => candidate.type === "turn_context");
|
|
159
|
+
if (row)
|
|
160
|
+
match = row;
|
|
161
|
+
}
|
|
162
|
+
if (read < buffer.length)
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
return { row: match, bytes: bytesRead };
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
return { row: match, bytes: bytesRead };
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
if (fd !== undefined)
|
|
172
|
+
closeSync(fd);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function newestTurnContextTuning(rows, bytesRead, startedAt) {
|
|
176
|
+
for (let index = rows.length - 1; index >= 0; index--) {
|
|
177
|
+
const row = rows[index];
|
|
178
|
+
if (row.type !== "turn_context")
|
|
179
|
+
continue;
|
|
180
|
+
const effort = row.payload?.effort;
|
|
181
|
+
const model = row.payload?.model;
|
|
182
|
+
if (typeof effort !== "string" || effort.length === 0)
|
|
183
|
+
continue;
|
|
184
|
+
return {
|
|
185
|
+
state: "observed",
|
|
186
|
+
effort,
|
|
187
|
+
...(typeof model === "string" && model.length > 0 ? { model } : {}),
|
|
188
|
+
...(row.timestamp ? { measured_at: row.timestamp } : {}),
|
|
189
|
+
method: "codex_transcript_turn_context",
|
|
190
|
+
source_event: "codex.rollout_turn_context",
|
|
191
|
+
bytes_read: bytesRead,
|
|
192
|
+
io_duration_ms: elapsed(startedAt),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
function readClaudeTuning(request, options, startedAt) {
|
|
198
|
+
const readablePath = transcriptPathCandidates(request.transcript_path).find((candidate) => existsSync(candidate));
|
|
199
|
+
if (!readablePath)
|
|
200
|
+
return unsupported("runtime_context_telemetry_unavailable", startedAt);
|
|
201
|
+
const tail = readTail(readablePath, options.maxTailBytes ?? DEFAULT_TAIL_BYTES);
|
|
202
|
+
if (!tail)
|
|
203
|
+
return tuningPartial("claude_transcript_unreadable", 0, startedAt);
|
|
204
|
+
const rows = parseRuntimeRows(tail.text);
|
|
205
|
+
for (let index = rows.length - 1; index >= 0; index--) {
|
|
206
|
+
const row = rows[index];
|
|
207
|
+
if (row.type !== "assistant")
|
|
208
|
+
continue;
|
|
209
|
+
const model = row.payload?.model;
|
|
210
|
+
if (typeof model !== "string" || model.length === 0 || model.startsWith("<"))
|
|
211
|
+
continue;
|
|
212
|
+
const usage = objectValue(row.payload?.usage);
|
|
213
|
+
const speed = usage?.speed;
|
|
214
|
+
return {
|
|
215
|
+
state: "observed",
|
|
216
|
+
model,
|
|
217
|
+
...(row.effort ? { effort: row.effort } : {}),
|
|
218
|
+
...(typeof speed === "string" && speed.length > 0 ? { speed } : {}),
|
|
219
|
+
...(row.timestamp ? { measured_at: row.timestamp } : {}),
|
|
220
|
+
method: "claude_transcript_assistant_row",
|
|
221
|
+
source_event: "claude-code.transcript_assistant_row",
|
|
222
|
+
bytes_read: tail.bytes,
|
|
223
|
+
io_duration_ms: elapsed(startedAt),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return tuningPartial("claude_transcript_assistant_row_missing", tail.bytes, startedAt);
|
|
227
|
+
}
|
|
228
|
+
function tuningPartial(reason, bytesRead, startedAt) {
|
|
229
|
+
return {
|
|
230
|
+
state: "partial",
|
|
231
|
+
reason,
|
|
232
|
+
bytes_read: bytesRead,
|
|
233
|
+
io_duration_ms: elapsed(startedAt),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function readCodexContext(request, options, startedAt) {
|
|
237
|
+
const resolved = resolveCodexTranscript(request, options);
|
|
238
|
+
if (resolved.state === "missing") {
|
|
239
|
+
return unsupported("runtime_context_telemetry_unavailable", startedAt);
|
|
240
|
+
}
|
|
241
|
+
if (resolved.state === "ambiguous") {
|
|
242
|
+
return partial("codex_transcript_ambiguous", 0, startedAt);
|
|
243
|
+
}
|
|
244
|
+
if (resolved.state === "mismatch") {
|
|
245
|
+
return partial("codex_transcript_session_mismatch", 0, startedAt);
|
|
246
|
+
}
|
|
247
|
+
const tail = readTail(resolved.path, options.maxTailBytes ??
|
|
248
|
+
(request.mode === "active_turn" ? ACTIVE_TURN_TAIL_BYTES : DEFAULT_TAIL_BYTES));
|
|
249
|
+
if (!tail)
|
|
250
|
+
return partial("codex_transcript_unreadable", 0, startedAt);
|
|
251
|
+
const rows = parseRuntimeRows(tail.text);
|
|
252
|
+
if (request.mode === "status") {
|
|
253
|
+
const token = newestCodexToken(rows);
|
|
254
|
+
return codexObservation(request, token, undefined, tail.bytes, options, startedAt);
|
|
255
|
+
}
|
|
256
|
+
if (request.mode === "active_turn") {
|
|
257
|
+
const active = tokenWithinActiveTurn(rows, request.turn_id);
|
|
258
|
+
const token = active.state === "found" ? active.token : tokenAtOrAfter(rows, request.turn_started_at);
|
|
259
|
+
if (active.state === "turn_missing" && !token) {
|
|
260
|
+
return partial("codex_transcript_turn_not_found", tail.bytes, startedAt);
|
|
261
|
+
}
|
|
262
|
+
return codexObservation(request, token, undefined, tail.bytes, options, startedAt);
|
|
263
|
+
}
|
|
264
|
+
const turnId = request.turn_id;
|
|
265
|
+
const terminalIndex = findCodexTurnTerminal(rows, turnId);
|
|
266
|
+
if (terminalIndex < 0) {
|
|
267
|
+
const sawStart = rows.some((row) => row.type === "event_msg" &&
|
|
268
|
+
row.payload?.type === "task_started" &&
|
|
269
|
+
row.payload.turn_id === turnId);
|
|
270
|
+
return partial(sawStart ? "codex_transcript_turn_not_terminal" : "codex_transcript_turn_not_found", tail.bytes, startedAt);
|
|
271
|
+
}
|
|
272
|
+
const terminal = rows[terminalIndex];
|
|
273
|
+
const token = tokenBeforeTerminal(rows, terminalIndex);
|
|
274
|
+
return codexObservation(request, token, terminal, tail.bytes, options, startedAt);
|
|
275
|
+
}
|
|
276
|
+
function codexObservation(request, token, terminal, bytesRead, options, startedAt) {
|
|
277
|
+
if (!token)
|
|
278
|
+
return partial("codex_transcript_token_count_missing", bytesRead, startedAt);
|
|
279
|
+
if (token.used_tokens === undefined) {
|
|
280
|
+
return partial("context_used_tokens_not_reported", bytesRead, startedAt);
|
|
281
|
+
}
|
|
282
|
+
if (token.limit_tokens === undefined) {
|
|
283
|
+
return partial("context_limit_tokens_not_reported", bytesRead, startedAt, token);
|
|
284
|
+
}
|
|
285
|
+
if (token.limit_tokens <= 0) {
|
|
286
|
+
return partial("context_limit_tokens_invalid", bytesRead, startedAt, token);
|
|
287
|
+
}
|
|
288
|
+
if (!token.measured_at || !Number.isFinite(Date.parse(token.measured_at))) {
|
|
289
|
+
return partial("codex_transcript_token_count_missing", bytesRead, startedAt);
|
|
290
|
+
}
|
|
291
|
+
if (terminal?.timestamp) {
|
|
292
|
+
const age = Date.parse(terminal.timestamp) - Date.parse(token.measured_at);
|
|
293
|
+
if (age < 0 || age > (options.maxSampleAgeMs ?? DEFAULT_MAX_SAMPLE_AGE_MS)) {
|
|
294
|
+
return partial("codex_transcript_sample_stale", bytesRead, startedAt, token);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if (request.mode === "active_turn" && request.observed_at) {
|
|
298
|
+
const age = Date.parse(request.observed_at) - Date.parse(token.measured_at);
|
|
299
|
+
if (!Number.isFinite(age) ||
|
|
300
|
+
age < -5_000 ||
|
|
301
|
+
age > (options.maxSampleAgeMs ?? DEFAULT_MAX_SAMPLE_AGE_MS)) {
|
|
302
|
+
return partial("codex_transcript_sample_stale", bytesRead, startedAt, token);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const witness = [
|
|
306
|
+
request.session_id,
|
|
307
|
+
request.turn_id ?? "status",
|
|
308
|
+
token.ordinal ?? "unknown",
|
|
309
|
+
token.measured_at,
|
|
310
|
+
token.used_tokens,
|
|
311
|
+
token.limit_tokens,
|
|
312
|
+
].join("\0");
|
|
313
|
+
return {
|
|
314
|
+
state: "observed",
|
|
315
|
+
used_tokens: token.used_tokens,
|
|
316
|
+
limit_tokens: token.limit_tokens,
|
|
317
|
+
measured_at: token.measured_at,
|
|
318
|
+
method: "codex_transcript_token_count",
|
|
319
|
+
source_event: "codex.rollout_token_count",
|
|
320
|
+
source_witness: createHash("sha256").update(witness).digest("hex"),
|
|
321
|
+
attestation: "derived",
|
|
322
|
+
confidence: "exact",
|
|
323
|
+
bytes_read: bytesRead,
|
|
324
|
+
io_duration_ms: elapsed(startedAt),
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function readClaudeContext(request, options, startedAt) {
|
|
328
|
+
const readablePath = transcriptPathCandidates(request.transcript_path).find((candidate) => existsSync(candidate));
|
|
329
|
+
if (!readablePath)
|
|
330
|
+
return unsupported("runtime_context_telemetry_unavailable", startedAt);
|
|
331
|
+
const tail = readTail(readablePath, options.maxTailBytes ??
|
|
332
|
+
(request.mode === "active_turn" ? ACTIVE_TURN_TAIL_BYTES : DEFAULT_TAIL_BYTES));
|
|
333
|
+
if (!tail)
|
|
334
|
+
return partial("claude_transcript_unreadable", 0, startedAt);
|
|
335
|
+
const rows = parseRuntimeRows(tail.text);
|
|
336
|
+
const sessionRows = rows.filter((row) => row.session_id === undefined || row.session_id === request.session_id);
|
|
337
|
+
if (rows.some((row) => row.session_id !== undefined) && sessionRows.length === 0) {
|
|
338
|
+
return partial("claude_transcript_session_mismatch", tail.bytes, startedAt);
|
|
339
|
+
}
|
|
340
|
+
const turnAttributed = request.mode === "turn" || request.mode === "active_turn";
|
|
341
|
+
const candidateRows = turnAttributed
|
|
342
|
+
? claudeAssistantRowsForTurn(sessionRows, request.turn_id)
|
|
343
|
+
: sessionRows.filter((row) => row.type === "assistant");
|
|
344
|
+
if (turnAttributed && candidateRows.length === 0) {
|
|
345
|
+
return partial("claude_transcript_turn_not_found", tail.bytes, startedAt);
|
|
346
|
+
}
|
|
347
|
+
for (let index = candidateRows.length - 1; index >= 0; index--) {
|
|
348
|
+
const row = candidateRows[index];
|
|
349
|
+
if (row.type !== "assistant")
|
|
350
|
+
continue;
|
|
351
|
+
const message = row.payload;
|
|
352
|
+
const usage = objectValue(message?.usage);
|
|
353
|
+
if (!usage)
|
|
354
|
+
continue;
|
|
355
|
+
const used = sumNumbers(usage.input_tokens, usage.cache_creation_input_tokens, usage.cache_read_input_tokens);
|
|
356
|
+
if (used === undefined) {
|
|
357
|
+
return partial("context_used_tokens_not_reported", tail.bytes, startedAt);
|
|
358
|
+
}
|
|
359
|
+
const model = stringValue(message?.model);
|
|
360
|
+
const capability = model ? claudeModelContextCapability(model) : undefined;
|
|
361
|
+
if (capability && row.timestamp) {
|
|
362
|
+
if (request.mode === "active_turn" && request.observed_at) {
|
|
363
|
+
const age = Date.parse(request.observed_at) - Date.parse(row.timestamp);
|
|
364
|
+
if (!Number.isFinite(age) ||
|
|
365
|
+
age < -5_000 ||
|
|
366
|
+
age > (options.maxSampleAgeMs ?? DEFAULT_MAX_SAMPLE_AGE_MS)) {
|
|
367
|
+
return partial("claude_transcript_sample_stale", tail.bytes, startedAt, {
|
|
368
|
+
used_tokens: used,
|
|
369
|
+
measured_at: row.timestamp,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
const witness = [
|
|
374
|
+
request.session_id,
|
|
375
|
+
request.turn_id ?? "status",
|
|
376
|
+
row.timestamp,
|
|
377
|
+
used,
|
|
378
|
+
model,
|
|
379
|
+
capability.limit_tokens,
|
|
380
|
+
capability.authority,
|
|
381
|
+
].join("\0");
|
|
382
|
+
return {
|
|
383
|
+
state: "observed",
|
|
384
|
+
used_tokens: used,
|
|
385
|
+
limit_tokens: capability.limit_tokens,
|
|
386
|
+
measured_at: row.timestamp,
|
|
387
|
+
method: "claude_transcript_usage_model_capability",
|
|
388
|
+
source_event: "claude.transcript_usage_model_capability",
|
|
389
|
+
source_witness: createHash("sha256").update(witness).digest("hex"),
|
|
390
|
+
attestation: "inferred",
|
|
391
|
+
confidence: "high",
|
|
392
|
+
bytes_read: tail.bytes,
|
|
393
|
+
io_duration_ms: elapsed(startedAt),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
return partial("claude_context_limit_tokens_not_reported", tail.bytes, startedAt, {
|
|
397
|
+
used_tokens: used,
|
|
398
|
+
measured_at: row.timestamp,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
return partial("context_used_tokens_not_reported", tail.bytes, startedAt);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Versioned exact-name families from Anthropic's published model capability
|
|
405
|
+
* table. Unknown aliases deliberately stay missing: matching a product label
|
|
406
|
+
* or guessing from a family name would turn an estimate into fake precision.
|
|
407
|
+
*/
|
|
408
|
+
function claudeModelContextCapability(model) {
|
|
409
|
+
const normalized = model.toLowerCase();
|
|
410
|
+
const oneMillionTokenModels = new Set([
|
|
411
|
+
"claude-fable-5",
|
|
412
|
+
"claude-opus-5",
|
|
413
|
+
"claude-sonnet-5",
|
|
414
|
+
"claude-opus-4-8",
|
|
415
|
+
"claude-opus-4-7",
|
|
416
|
+
"claude-opus-4-6",
|
|
417
|
+
"claude-sonnet-4-6",
|
|
418
|
+
]);
|
|
419
|
+
if (oneMillionTokenModels.has(normalized)) {
|
|
420
|
+
return { limit_tokens: 1_000_000, authority: "anthropic_model_capabilities_2026_08" };
|
|
421
|
+
}
|
|
422
|
+
if (normalized === "claude-haiku-4-5" || normalized === "claude-haiku-4-5-20251001") {
|
|
423
|
+
return { limit_tokens: 200_000, authority: "anthropic_model_capabilities_2026_08" };
|
|
424
|
+
}
|
|
425
|
+
return undefined;
|
|
426
|
+
}
|
|
427
|
+
function readCursorContext(request, options, startedAt) {
|
|
428
|
+
const cached = cursorDatabaseCache.get(request.session_id);
|
|
429
|
+
if (cached && existsSync(cached)) {
|
|
430
|
+
const sample = readCursorDatabase(cached, request.session_id);
|
|
431
|
+
if (sample.state === "found") {
|
|
432
|
+
return cursorObservation(request, sample.sample, options, startedAt);
|
|
433
|
+
}
|
|
434
|
+
cursorDatabaseCache.delete(request.session_id);
|
|
435
|
+
}
|
|
436
|
+
const databases = cursorDatabasePaths(options);
|
|
437
|
+
if (databases.length === 0) {
|
|
438
|
+
return partial("cursor_context_database_unavailable", 0, startedAt);
|
|
439
|
+
}
|
|
440
|
+
const matches = [];
|
|
441
|
+
let bytesRead = 0;
|
|
442
|
+
let unreadable = 0;
|
|
443
|
+
for (const databasePath of databases) {
|
|
444
|
+
const result = readCursorDatabase(databasePath, request.session_id);
|
|
445
|
+
bytesRead += result.state === "found" ? result.sample.bytes_read : result.bytes_read;
|
|
446
|
+
if (result.state === "unreadable")
|
|
447
|
+
unreadable += 1;
|
|
448
|
+
if (result.state !== "found")
|
|
449
|
+
continue;
|
|
450
|
+
matches.push(result.sample);
|
|
451
|
+
}
|
|
452
|
+
if (matches.length === 0) {
|
|
453
|
+
return partial(unreadable === databases.length
|
|
454
|
+
? "cursor_context_database_unreadable"
|
|
455
|
+
: "cursor_context_session_not_found", bytesRead, startedAt);
|
|
456
|
+
}
|
|
457
|
+
matches.sort((left, right) => Date.parse(right.measured_at) - Date.parse(left.measured_at));
|
|
458
|
+
const newest = matches[0];
|
|
459
|
+
const tied = matches.filter((sample) => sample.measured_at === newest.measured_at);
|
|
460
|
+
if (tied.some((sample) => sample.used_percent !== newest.used_percent)) {
|
|
461
|
+
return partial("cursor_context_sample_ambiguous", bytesRead, startedAt);
|
|
462
|
+
}
|
|
463
|
+
cacheCursorDatabase(request.session_id, newest.database_path);
|
|
464
|
+
return cursorObservation(request, newest, options, startedAt);
|
|
465
|
+
}
|
|
466
|
+
function cursorObservation(request, sample, options, startedAt) {
|
|
467
|
+
if (!Number.isFinite(sample.used_percent) ||
|
|
468
|
+
sample.used_percent < 0 ||
|
|
469
|
+
sample.used_percent > 100) {
|
|
470
|
+
return partial("cursor_context_usage_invalid", sample.bytes_read, startedAt);
|
|
471
|
+
}
|
|
472
|
+
const sampleMs = Date.parse(sample.measured_at);
|
|
473
|
+
if (!Number.isFinite(sampleMs)) {
|
|
474
|
+
return partial("cursor_context_sample_time_not_reported", sample.bytes_read, startedAt);
|
|
475
|
+
}
|
|
476
|
+
if ((request.mode === "turn" || request.mode === "active_turn") && request.observed_at) {
|
|
477
|
+
const observedMs = Date.parse(request.observed_at);
|
|
478
|
+
const age = observedMs - sampleMs;
|
|
479
|
+
if (!Number.isFinite(observedMs) ||
|
|
480
|
+
age < -5_000 ||
|
|
481
|
+
age > (options.maxSampleAgeMs ?? DEFAULT_MAX_SAMPLE_AGE_MS)) {
|
|
482
|
+
return partial("cursor_context_sample_stale", sample.bytes_read, startedAt);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const witness = [request.session_id, sample.measured_at, sample.used_percent].join("\0");
|
|
486
|
+
return {
|
|
487
|
+
state: "observed",
|
|
488
|
+
used_percent: sample.used_percent,
|
|
489
|
+
measured_at: sample.measured_at,
|
|
490
|
+
method: "cursor_composer_context_percent",
|
|
491
|
+
source_event: "cursor.composer_context_percent",
|
|
492
|
+
source_witness: createHash("sha256").update(witness).digest("hex"),
|
|
493
|
+
attestation: "derived",
|
|
494
|
+
confidence: "high",
|
|
495
|
+
bytes_read: sample.bytes_read,
|
|
496
|
+
io_duration_ms: elapsed(startedAt),
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
function readCursorDatabase(databasePath, sessionId) {
|
|
500
|
+
try {
|
|
501
|
+
// Bun is the primary hook runtime. Node fallback processes fail closed here
|
|
502
|
+
// instead of importing a Bun-only module at startup.
|
|
503
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
504
|
+
const { Database } = require("bun:sqlite");
|
|
505
|
+
const database = new Database(databasePath, { readonly: true });
|
|
506
|
+
const row = database
|
|
507
|
+
.query("SELECT value FROM ItemTable WHERE key = 'composer.composerData'")
|
|
508
|
+
.get();
|
|
509
|
+
database.close();
|
|
510
|
+
if (!row?.value)
|
|
511
|
+
return { state: "missing", bytes_read: 0 };
|
|
512
|
+
const text = typeof row.value === "string" ? row.value : Buffer.from(row.value).toString("utf8");
|
|
513
|
+
const bytesRead = Buffer.byteLength(text);
|
|
514
|
+
const parsed = objectValue(JSON.parse(text));
|
|
515
|
+
const composers = Array.isArray(parsed?.allComposers) ? parsed.allComposers : [];
|
|
516
|
+
for (const candidate of composers) {
|
|
517
|
+
const composer = objectValue(candidate);
|
|
518
|
+
if (stringValue(composer?.composerId) !== sessionId)
|
|
519
|
+
continue;
|
|
520
|
+
const usedPercent = numberValue(composer?.contextUsagePercent);
|
|
521
|
+
if (usedPercent === undefined)
|
|
522
|
+
return { state: "missing", bytes_read: bytesRead };
|
|
523
|
+
const measuredAt = cursorMeasuredAt(composer?.lastUpdatedAt);
|
|
524
|
+
if (!measuredAt)
|
|
525
|
+
return { state: "missing", bytes_read: bytesRead };
|
|
526
|
+
return {
|
|
527
|
+
state: "found",
|
|
528
|
+
sample: {
|
|
529
|
+
used_percent: usedPercent,
|
|
530
|
+
measured_at: measuredAt,
|
|
531
|
+
bytes_read: bytesRead,
|
|
532
|
+
database_path: databasePath,
|
|
533
|
+
},
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
return { state: "missing", bytes_read: bytesRead };
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
return { state: "unreadable", bytes_read: 0 };
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
function cursorMeasuredAt(value) {
|
|
543
|
+
if (typeof value === "string" && Number.isFinite(Date.parse(value))) {
|
|
544
|
+
return new Date(value).toISOString();
|
|
545
|
+
}
|
|
546
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0)
|
|
547
|
+
return undefined;
|
|
548
|
+
const milliseconds = value < 10_000_000_000 ? value * 1_000 : value;
|
|
549
|
+
const date = new Date(milliseconds);
|
|
550
|
+
return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
|
|
551
|
+
}
|
|
552
|
+
function cursorDatabasePaths(options) {
|
|
553
|
+
const roots = options.cursorRoots ?? defaultCursorRoots();
|
|
554
|
+
const limit = Math.max(1, Math.floor(options.maxCursorDatabases ?? DEFAULT_MAX_CURSOR_DATABASES));
|
|
555
|
+
const candidates = [];
|
|
556
|
+
for (const root of roots) {
|
|
557
|
+
let names;
|
|
558
|
+
try {
|
|
559
|
+
names = readdirSync(root).sort();
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
for (const name of names) {
|
|
565
|
+
const databasePath = join(root, name, "state.vscdb");
|
|
566
|
+
try {
|
|
567
|
+
candidates.push({ path: databasePath, modified_ms: statSync(databasePath).mtimeMs });
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
// Removed or unreadable workspaces are not candidates.
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return candidates
|
|
575
|
+
.sort((left, right) => right.modified_ms - left.modified_ms)
|
|
576
|
+
.slice(0, limit)
|
|
577
|
+
.map((candidate) => candidate.path);
|
|
578
|
+
}
|
|
579
|
+
function defaultCursorRoots() {
|
|
580
|
+
const roots = [resolve(homedir(), ".config", "Cursor", "User", "workspaceStorage")];
|
|
581
|
+
try {
|
|
582
|
+
if (existsSync("/mnt/c/Users")) {
|
|
583
|
+
for (const user of readdirSync("/mnt/c/Users")) {
|
|
584
|
+
roots.push(`/mnt/c/Users/${user}/AppData/Roaming/Cursor/User/workspaceStorage`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
catch {
|
|
589
|
+
// Non-WSL hosts do not expose this mount.
|
|
590
|
+
}
|
|
591
|
+
return roots;
|
|
592
|
+
}
|
|
593
|
+
function cacheCursorDatabase(sessionId, databasePath) {
|
|
594
|
+
cursorDatabaseCache.delete(sessionId);
|
|
595
|
+
cursorDatabaseCache.set(sessionId, databasePath);
|
|
596
|
+
while (cursorDatabaseCache.size > SESSION_CACHE_LIMIT) {
|
|
597
|
+
cursorDatabaseCache.delete(cursorDatabaseCache.keys().next().value);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/** Join assistant rows to the native CC prompt id through the transcript's
|
|
601
|
+
* parent UUID chain. No UUID or prompt value crosses the reader boundary. */
|
|
602
|
+
function claudeAssistantRowsForTurn(rows, turnId) {
|
|
603
|
+
const byUuid = new Map(rows.filter((row) => row.uuid).map((row) => [row.uuid, row]));
|
|
604
|
+
return rows.filter((row) => {
|
|
605
|
+
if (row.type !== "assistant")
|
|
606
|
+
return false;
|
|
607
|
+
let parentUuid = row.parent_uuid;
|
|
608
|
+
const seen = new Set();
|
|
609
|
+
for (let depth = 0; parentUuid && depth < 64 && !seen.has(parentUuid); depth += 1) {
|
|
610
|
+
seen.add(parentUuid);
|
|
611
|
+
const parent = byUuid.get(parentUuid);
|
|
612
|
+
if (!parent)
|
|
613
|
+
return false;
|
|
614
|
+
if (parent.type === "user" && parent.prompt_id)
|
|
615
|
+
return parent.prompt_id === turnId;
|
|
616
|
+
parentUuid = parent.parent_uuid;
|
|
617
|
+
}
|
|
618
|
+
return false;
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
function newestCodexToken(rows) {
|
|
622
|
+
for (let index = rows.length - 1; index >= 0; index--) {
|
|
623
|
+
const token = codexToken(rows[index]);
|
|
624
|
+
if (token)
|
|
625
|
+
return token;
|
|
626
|
+
}
|
|
627
|
+
return undefined;
|
|
628
|
+
}
|
|
629
|
+
function tokenWithinActiveTurn(rows, turnId) {
|
|
630
|
+
let startIndex = -1;
|
|
631
|
+
for (let index = rows.length - 1; index >= 0; index -= 1) {
|
|
632
|
+
const row = rows[index];
|
|
633
|
+
if (row.type === "event_msg" &&
|
|
634
|
+
row.payload?.type === "task_started" &&
|
|
635
|
+
row.payload.turn_id === turnId) {
|
|
636
|
+
startIndex = index;
|
|
637
|
+
break;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (startIndex < 0)
|
|
641
|
+
return { state: "turn_missing" };
|
|
642
|
+
let token;
|
|
643
|
+
for (let index = startIndex + 1; index < rows.length; index += 1) {
|
|
644
|
+
const row = rows[index];
|
|
645
|
+
if (row.type === "event_msg" &&
|
|
646
|
+
(row.payload?.type === "task_started" || row.payload?.type === "task_complete")) {
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
token = codexToken(row) ?? token;
|
|
650
|
+
}
|
|
651
|
+
return { state: "found", token };
|
|
652
|
+
}
|
|
653
|
+
function tokenAtOrAfter(rows, turnStartedAt) {
|
|
654
|
+
if (!turnStartedAt || !Number.isFinite(Date.parse(turnStartedAt)))
|
|
655
|
+
return undefined;
|
|
656
|
+
const token = newestCodexToken(rows);
|
|
657
|
+
if (!token?.measured_at)
|
|
658
|
+
return undefined;
|
|
659
|
+
return Date.parse(token.measured_at) >= Date.parse(turnStartedAt) ? token : undefined;
|
|
660
|
+
}
|
|
661
|
+
function tokenBeforeTerminal(rows, terminalIndex) {
|
|
662
|
+
for (let index = terminalIndex - 1; index >= 0; index--) {
|
|
663
|
+
const row = rows[index];
|
|
664
|
+
const type = row.payload?.type;
|
|
665
|
+
if (type === "task_started" || type === "task_complete")
|
|
666
|
+
break;
|
|
667
|
+
const token = codexToken(row);
|
|
668
|
+
if (token)
|
|
669
|
+
return token;
|
|
670
|
+
}
|
|
671
|
+
return undefined;
|
|
672
|
+
}
|
|
673
|
+
function codexToken(row) {
|
|
674
|
+
if (row.type !== "event_msg" || row.payload?.type !== "token_count")
|
|
675
|
+
return undefined;
|
|
676
|
+
const info = objectValue(row.payload.info);
|
|
677
|
+
const usage = objectValue(info?.last_token_usage);
|
|
678
|
+
return {
|
|
679
|
+
used_tokens: safeInteger(usage?.input_tokens),
|
|
680
|
+
limit_tokens: safeInteger(info?.model_context_window),
|
|
681
|
+
measured_at: timestamp(row.timestamp),
|
|
682
|
+
ordinal: safeInteger(row.ordinal),
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function findCodexTurnTerminal(rows, turnId) {
|
|
686
|
+
for (let index = rows.length - 1; index >= 0; index--) {
|
|
687
|
+
const row = rows[index];
|
|
688
|
+
if (row.type === "event_msg" &&
|
|
689
|
+
row.payload?.type === "task_complete" &&
|
|
690
|
+
row.payload.turn_id === turnId) {
|
|
691
|
+
return index;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return -1;
|
|
695
|
+
}
|
|
696
|
+
function parseRuntimeRows(text) {
|
|
697
|
+
const rows = [];
|
|
698
|
+
for (const line of text.split("\n")) {
|
|
699
|
+
if (!line.trim())
|
|
700
|
+
continue;
|
|
701
|
+
try {
|
|
702
|
+
const value = JSON.parse(line);
|
|
703
|
+
const row = objectValue(value);
|
|
704
|
+
if (!row)
|
|
705
|
+
continue;
|
|
706
|
+
rows.push({
|
|
707
|
+
timestamp: timestamp(row.timestamp),
|
|
708
|
+
ordinal: safeInteger(row.ordinal),
|
|
709
|
+
type: typeof row.type === "string" ? row.type : undefined,
|
|
710
|
+
uuid: stringValue(row.uuid),
|
|
711
|
+
parent_uuid: stringValue(row.parentUuid),
|
|
712
|
+
prompt_id: stringValue(row.promptId) ?? stringValue(row.prompt_id),
|
|
713
|
+
session_id: stringValue(row.sessionId) ?? stringValue(row.session_id),
|
|
714
|
+
...(typeof row.effort === "string" && row.effort.length > 0 ? { effort: row.effort } : {}),
|
|
715
|
+
payload: objectValue(row.payload) ?? objectValue(row.message) ?? undefined,
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
catch {
|
|
719
|
+
// The first line may be cut by the bounded tail or a writer may be mid-flush.
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return rows;
|
|
723
|
+
}
|
|
724
|
+
function stringValue(value) {
|
|
725
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
726
|
+
}
|
|
727
|
+
function numberValue(value) {
|
|
728
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
729
|
+
}
|
|
730
|
+
function readTail(path, maxBytes) {
|
|
731
|
+
let fd;
|
|
732
|
+
try {
|
|
733
|
+
const size = statSync(path).size;
|
|
734
|
+
const bytes = Math.max(0, Math.min(size, Math.max(1, Math.floor(maxBytes))));
|
|
735
|
+
const start = size - bytes;
|
|
736
|
+
fd = openSync(path, "r");
|
|
737
|
+
const buffer = Buffer.alloc(bytes);
|
|
738
|
+
const read = readSync(fd, buffer, 0, bytes, start);
|
|
739
|
+
const text = buffer.subarray(0, read).toString("utf8");
|
|
740
|
+
return {
|
|
741
|
+
text: start > 0 ? text.slice(Math.max(0, text.indexOf("\n") + 1)) : text,
|
|
742
|
+
bytes: read,
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
catch {
|
|
746
|
+
return undefined;
|
|
747
|
+
}
|
|
748
|
+
finally {
|
|
749
|
+
if (fd !== undefined)
|
|
750
|
+
closeSync(fd);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
function resolveCodexTranscript(request, options) {
|
|
754
|
+
const sessionId = request.session_id;
|
|
755
|
+
const cached = codexTranscriptCache.get(sessionId);
|
|
756
|
+
if (cached && existsSync(cached))
|
|
757
|
+
return { state: "found", path: cached };
|
|
758
|
+
const supplied = transcriptPathCandidates(request.transcript_path).filter((candidate) => existsSync(candidate));
|
|
759
|
+
const verifiedSupplied = supplied.filter((candidate) => transcriptMatches(candidate, sessionId));
|
|
760
|
+
if (verifiedSupplied.length === 1)
|
|
761
|
+
return cacheTranscript(sessionId, verifiedSupplied[0]);
|
|
762
|
+
if (verifiedSupplied.length > 1)
|
|
763
|
+
return { state: "ambiguous" };
|
|
764
|
+
if (supplied.length > 0)
|
|
765
|
+
return { state: "mismatch" };
|
|
766
|
+
const matches = codexRoots(options)
|
|
767
|
+
.flatMap((root) => findTranscriptMatches(root, sessionId))
|
|
768
|
+
.filter((path, index, values) => values.indexOf(path) === index);
|
|
769
|
+
if (matches.length === 1)
|
|
770
|
+
return cacheTranscript(sessionId, matches[0]);
|
|
771
|
+
if (matches.length > 1)
|
|
772
|
+
return { state: "ambiguous" };
|
|
773
|
+
return { state: "missing" };
|
|
774
|
+
}
|
|
775
|
+
function cacheTranscript(sessionId, path) {
|
|
776
|
+
codexTranscriptCache.delete(sessionId);
|
|
777
|
+
codexTranscriptCache.set(sessionId, path);
|
|
778
|
+
while (codexTranscriptCache.size > SESSION_CACHE_LIMIT) {
|
|
779
|
+
codexTranscriptCache.delete(codexTranscriptCache.keys().next().value);
|
|
780
|
+
}
|
|
781
|
+
return { state: "found", path };
|
|
782
|
+
}
|
|
783
|
+
function codexRoots(options) {
|
|
784
|
+
if (options.codexRoots)
|
|
785
|
+
return options.codexRoots;
|
|
786
|
+
const roots = [resolve(homedir(), ".codex", "sessions")];
|
|
787
|
+
try {
|
|
788
|
+
if (existsSync("/mnt/c/Users")) {
|
|
789
|
+
for (const user of readdirSync("/mnt/c/Users")) {
|
|
790
|
+
roots.push(`/mnt/c/Users/${user}/.codex/sessions`);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
catch {
|
|
795
|
+
// Non-WSL hosts do not expose this mount.
|
|
796
|
+
}
|
|
797
|
+
return roots;
|
|
798
|
+
}
|
|
799
|
+
function findTranscriptMatches(root, sessionId) {
|
|
800
|
+
if (!existsSync(root))
|
|
801
|
+
return [];
|
|
802
|
+
const matches = [];
|
|
803
|
+
const stack = [{ path: root, depth: 0 }];
|
|
804
|
+
while (stack.length > 0) {
|
|
805
|
+
const current = stack.pop();
|
|
806
|
+
if (current.depth > 4)
|
|
807
|
+
continue;
|
|
808
|
+
let names;
|
|
809
|
+
try {
|
|
810
|
+
names = readdirSync(current.path);
|
|
811
|
+
}
|
|
812
|
+
catch {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
for (const name of names) {
|
|
816
|
+
const path = join(current.path, name);
|
|
817
|
+
try {
|
|
818
|
+
const stat = statSync(path);
|
|
819
|
+
if (stat.isDirectory())
|
|
820
|
+
stack.push({ path, depth: current.depth + 1 });
|
|
821
|
+
else if (transcriptMatches(path, sessionId))
|
|
822
|
+
matches.push(path);
|
|
823
|
+
}
|
|
824
|
+
catch {
|
|
825
|
+
// A concurrently removed partition is simply unavailable.
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return matches;
|
|
830
|
+
}
|
|
831
|
+
function transcriptMatches(path, sessionId) {
|
|
832
|
+
return basename(path).endsWith(`-${sessionId}.jsonl`);
|
|
833
|
+
}
|
|
834
|
+
/** Narrow return: this exact shape is a member of both telemetry unions. */
|
|
835
|
+
function unsupported(reason, startedAt) {
|
|
836
|
+
return { state: "unsupported", reason, bytes_read: 0, io_duration_ms: elapsed(startedAt) };
|
|
837
|
+
}
|
|
838
|
+
function partial(reason, bytesRead, startedAt, sample) {
|
|
839
|
+
return {
|
|
840
|
+
state: "partial",
|
|
841
|
+
reason,
|
|
842
|
+
...(sample?.used_tokens !== undefined ? { used_tokens: sample.used_tokens } : {}),
|
|
843
|
+
...(sample?.measured_at ? { measured_at: sample.measured_at } : {}),
|
|
844
|
+
bytes_read: bytesRead,
|
|
845
|
+
io_duration_ms: elapsed(startedAt),
|
|
846
|
+
};
|
|
847
|
+
}
|
|
848
|
+
function elapsed(startedAt) {
|
|
849
|
+
return Math.max(0, Math.round((performance.now() - startedAt) * 1000) / 1000);
|
|
850
|
+
}
|
|
851
|
+
function objectValue(value) {
|
|
852
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
853
|
+
? value
|
|
854
|
+
: null;
|
|
855
|
+
}
|
|
856
|
+
function safeInteger(value) {
|
|
857
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
|
|
858
|
+
}
|
|
859
|
+
function timestamp(value) {
|
|
860
|
+
if (typeof value !== "string" || !Number.isFinite(Date.parse(value)))
|
|
861
|
+
return undefined;
|
|
862
|
+
return new Date(value).toISOString();
|
|
863
|
+
}
|
|
864
|
+
function sumNumbers(...values) {
|
|
865
|
+
const numbers = values.map(safeInteger);
|
|
866
|
+
return numbers.some((value) => value !== undefined)
|
|
867
|
+
? numbers.reduce((total, value) => total + (value ?? 0), 0)
|
|
868
|
+
: undefined;
|
|
869
|
+
}
|