@wrongstack/core 0.313.1 → 0.316.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chronicle/index.js +31 -31
- package/dist/chronicle/legacy-journal-import.d.ts +0 -6
- package/dist/chronicle/metrics-ingest.d.ts +14 -0
- package/dist/chronicle/metrics-schema.d.ts +10 -1
- package/dist/chronicle/metrics-store.d.ts +20 -2
- package/dist/chronicle/project-server.js +39 -31
- package/dist/chronicle/sink.d.ts +13 -0
- package/dist/chronicle/sqlite-journal.d.ts +20 -2
- package/dist/{chunk-WOEZV3Q4.js → chunk-25LSLC3G.js} +2 -1
- package/dist/{chunk-AI4LLQ2U.js → chunk-27QIURLN.js} +229 -12
- package/dist/{chunk-I45KAW2N.js → chunk-3AGWVSS7.js} +38 -450
- package/dist/chunk-3BDV7RL3.js +211 -0
- package/dist/{chunk-NFAYHPRH.js → chunk-3ECENVHL.js} +10 -8
- package/dist/{chunk-FW5LDDMJ.js → chunk-45WI72ZB.js} +1576 -1156
- package/dist/{chunk-AT4V4XGI.js → chunk-4BMVPOHO.js} +539 -313
- package/dist/{chunk-YBUJCZ57.js → chunk-4I7HGVVA.js} +17 -5
- package/dist/{chunk-JVGPR3TS.js → chunk-4LCZVJVF.js} +7 -55
- package/dist/{chunk-4ZHTKJHM.js → chunk-4SJNS7OB.js} +36 -2
- package/dist/{chunk-AD7ZFZCS.js → chunk-5BMIE7QG.js} +3 -3
- package/dist/{chunk-IQ35HMQL.js → chunk-5YPSXQXM.js} +71 -24
- package/dist/chunk-6FHWXLPT.js +10 -0
- package/dist/{chunk-FIV4IJL7.js → chunk-6H5GEOET.js} +163 -20
- package/dist/{chunk-VB3H5WWB.js → chunk-6NWEVFEL.js} +2 -2
- package/dist/{chunk-E6I5RXVK.js → chunk-AYW5YINX.js} +2 -2
- package/dist/{chunk-DEIQMBD2.js → chunk-B7F4WVP4.js} +2 -2
- package/dist/{chunk-XQ2XGIBF.js → chunk-BPBKKBUK.js} +6 -7
- package/dist/{chunk-K4YUNKU7.js → chunk-BYD345OX.js} +2 -2
- package/dist/{chunk-LZDDLNCZ.js → chunk-C27KDLOX.js} +4 -4
- package/dist/{chunk-6AKOTGLM.js → chunk-CU546ESW.js} +7 -7
- package/dist/{chunk-ZZ4V3WIZ.js → chunk-DLHHXUAM.js} +10 -1
- package/dist/{chunk-BAKVJLEV.js → chunk-DOTHQSJ2.js} +28 -16
- package/dist/{chunk-KBZGE6LN.js → chunk-DYLPMV4Q.js} +4 -3
- package/dist/{chunk-52RTVH4M.js → chunk-F3JWNST7.js} +2 -2
- package/dist/{chunk-WEBMSQP2.js → chunk-FC2ZGRF3.js} +21 -4
- package/dist/{chunk-FHAMQS7Q.js → chunk-FCBTO76Z.js} +76 -146
- package/dist/{chunk-4LJJYBAU.js → chunk-FHZVFYSL.js} +9 -1
- package/dist/{chunk-W4A6QA3D.js → chunk-FWNLEZYG.js} +4 -3
- package/dist/{chunk-OJZEX73F.js → chunk-GDQ7CZRQ.js} +5 -1
- package/dist/{chunk-QVOVMXJR.js → chunk-GJJGJB2R.js} +32 -9
- package/dist/{chunk-4XV6IR37.js → chunk-HI3JGZR2.js} +7 -6
- package/dist/{chunk-FSWCWSTS.js → chunk-HMLIGAU7.js} +26 -26
- package/dist/{chunk-PFXFQQRT.js → chunk-HXKZ7OBQ.js} +7 -43
- package/dist/{chunk-2FQL4PDC.js → chunk-I7DALG7J.js} +5 -5
- package/dist/{chunk-GM54GJBU.js → chunk-IRUTEHCE.js} +3 -3
- package/dist/{chunk-TYW2GI5I.js → chunk-J2WRWR37.js} +40 -13
- package/dist/{chunk-ZEHUCJHY.js → chunk-JFPJ6LLQ.js} +2 -2
- package/dist/chunk-JMULFFLN.js +9 -0
- package/dist/{chunk-RD6DEE36.js → chunk-JO4MGB6Z.js} +94 -8
- package/dist/{chunk-5DSMEVA4.js → chunk-K6BXGITA.js} +7 -7
- package/dist/{chunk-O74MJHXU.js → chunk-KZMSZV32.js} +2 -2
- package/dist/{chunk-GFJOMSHG.js → chunk-LA7CLDRW.js} +6 -2
- package/dist/{chunk-M2WF6AXG.js → chunk-LSMMOS2Z.js} +7 -3
- package/dist/{chunk-ASX6AW36.js → chunk-LXWCMQNJ.js} +3 -3
- package/dist/{chunk-WZO23AWO.js → chunk-M27LIEKV.js} +72 -22
- package/dist/{chunk-JTHKOYWU.js → chunk-MJPHJRAL.js} +15 -15
- package/dist/{chunk-G5AAKEEZ.js → chunk-MTL4O5YR.js} +5 -5
- package/dist/chunk-NHJ75HXY.js +1 -0
- package/dist/{chunk-ZYU2YOJ6.js → chunk-NIOAGFPB.js} +29 -15
- package/dist/{chunk-Y2GE5TSI.js → chunk-NS52ISWS.js} +2 -2
- package/dist/{chunk-UIWONWVG.js → chunk-NSOFPKGT.js} +541 -148
- package/dist/{chunk-RCQYT2I4.js → chunk-NVIZG63R.js} +2 -2
- package/dist/{chunk-EPC3GZD4.js → chunk-OOYZPOXM.js} +2 -2
- package/dist/{chunk-7ZHZE5EO.js → chunk-OSGLYW5J.js} +2 -2
- package/dist/{chunk-CE4ZOCOI.js → chunk-PFCMSSUF.js} +9 -9
- package/dist/{chunk-GFXZTHNI.js → chunk-PGRVXIMY.js} +5 -5
- package/dist/{chunk-JJPMWPB6.js → chunk-PISBFBJN.js} +6 -6
- package/dist/chunk-POOOIWE5.js +9 -0
- package/dist/{chunk-5RP3QTRL.js → chunk-PQNS3U7Z.js} +20 -3
- package/dist/{chunk-3E244UDA.js → chunk-QSTSJOCK.js} +52 -6
- package/dist/{chunk-YUPMXOGP.js → chunk-RFQMOKWK.js} +3 -3
- package/dist/chunk-RTOTNK3P.js +484 -0
- package/dist/{chunk-SN2DQRL6.js → chunk-RXKSDUAU.js} +7 -7
- package/dist/{chunk-T3KGZBU5.js → chunk-S45JPKQN.js} +189 -43
- package/dist/{chunk-YNCVSFGF.js → chunk-SAFHACFA.js} +4 -1
- package/dist/{chunk-KI4L2DUL.js → chunk-TCCHINEF.js} +114 -19
- package/dist/{chunk-AWNQ6ED6.js → chunk-THEGTRAG.js} +7 -2
- package/dist/{chunk-2KKODIQU.js → chunk-TR4LQE7L.js} +15 -15
- package/dist/{chunk-GPQ3NJPR.js → chunk-TWJMGXCI.js} +3 -3
- package/dist/{chunk-H72H4XDU.js → chunk-U45AXT5D.js} +9 -9
- package/dist/{chunk-62V2AFVG.js → chunk-U4FWBSO3.js} +160 -73
- package/dist/{chunk-A455ATZB.js → chunk-UBGDX6FI.js} +8 -1
- package/dist/chunk-UJILKYES.js +75 -0
- package/dist/{chunk-KSJ5UTP7.js → chunk-ULMAQV3T.js} +84 -4
- package/dist/{chunk-CB2HFKTP.js → chunk-VVBP6KGT.js} +1 -1
- package/dist/{chunk-RPOA7IAE.js → chunk-W5VITDM2.js} +43 -25
- package/dist/{chunk-QRTG4XTI.js → chunk-WAHQVNWT.js} +7 -1
- package/dist/{chunk-SQP64RCS.js → chunk-WGGYRBXH.js} +3019 -2976
- package/dist/{chunk-K3G6JBUC.js → chunk-WLYKU45P.js} +679 -141
- package/dist/chunk-WP7BVANJ.js +53 -0
- package/dist/{chunk-GAZEWQEZ.js → chunk-XF4VUMKW.js} +2 -2
- package/dist/{chunk-PAAWLLZX.js → chunk-Y5YXDM7D.js} +2 -2
- package/dist/{chunk-65RDIOR2.js → chunk-YOPAUVU4.js} +162 -44
- package/dist/{chunk-FFSX2QDQ.js → chunk-YPT4A46F.js} +3 -3
- package/dist/chunk-YWXT3JNM.js +425 -0
- package/dist/{chunk-EFEHDQGY.js → chunk-ZHZ2Y2DH.js} +64 -10
- package/dist/{chunk-CQQL4ZOQ.js → chunk-ZT7JNIGX.js} +4 -3
- package/dist/coordination/agent-monitor.d.ts +9 -1
- package/dist/coordination/agent-subagent-runner.d.ts +1 -1
- package/dist/coordination/agents/agent-prompts.d.ts +8 -0
- package/dist/coordination/agents/index.d.ts +33 -1
- package/dist/coordination/agents/index.js +52 -22
- package/dist/coordination/agents/phase3-wave1-platform.d.ts +1 -3
- package/dist/coordination/agents/phase3-wave2-meta.d.ts +1 -3
- package/dist/coordination/agents/phase8-wave3-products.d.ts +1 -3
- package/dist/coordination/agents/phase9-wave4-platform-meta.d.ts +1 -3
- package/dist/coordination/agents/project-agent-identity.d.ts +11 -11
- package/dist/coordination/agents/types.d.ts +13 -2
- package/dist/coordination/brain-monitor.d.ts +30 -7
- package/dist/coordination/collab-debug.d.ts +1 -1
- package/dist/coordination/collab-pause.d.ts +1 -1
- package/dist/coordination/delegate-tool.d.ts +7 -5
- package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -0
- package/dist/coordination/director-options.d.ts +7 -0
- package/dist/coordination/director-spawn-model.d.ts +17 -0
- package/dist/coordination/director-tools.d.ts +2 -2
- package/dist/coordination/director.d.ts +12 -0
- package/dist/coordination/dispatcher.d.ts +8 -0
- package/dist/coordination/fleet-bus.d.ts +35 -4
- package/dist/coordination/fleet-supervisor.d.ts +10 -2
- package/dist/coordination/fleet.d.ts +16 -7
- package/dist/coordination/index.d.ts +4 -0
- package/dist/coordination/index.js +86 -49
- package/dist/coordination/kanban-dispatch-port.d.ts +2 -2
- package/dist/coordination/mailbox-http-router.d.ts +4 -3
- package/dist/coordination/mailbox-http-validation.d.ts +1 -1
- package/dist/coordination/mailbox-project-server.js +15 -15
- package/dist/coordination/mailbox-types.d.ts +24 -6
- package/dist/coordination/model-tier-leader.d.ts +122 -0
- package/dist/coordination/model-tier.d.ts +122 -0
- package/dist/coordination/multi-agent-coordinator.d.ts +24 -0
- package/dist/coordination/origin-session.d.ts +16 -0
- package/dist/coordination/provider-status-tracker.d.ts +37 -5
- package/dist/coordination/session-note-hub.d.ts +44 -0
- package/dist/coordination/session-note-tool.d.ts +10 -0
- package/dist/core/agent.d.ts +1 -1
- package/dist/core/context.d.ts +22 -3
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +130 -38
- package/dist/core/request-conversation-binding.d.ts +37 -0
- package/dist/core/session-notes.d.ts +25 -0
- package/dist/core/system-prompt-builder.d.ts +11 -2
- package/dist/core/system-prompt-variants.d.ts +78 -0
- package/dist/design/index.js +3 -3
- package/dist/execution/auto-compaction-middleware.d.ts +11 -0
- package/dist/execution/autonomy-brain.d.ts +2 -1
- package/dist/execution/autonomy-prompt-contributor.d.ts +7 -2
- package/dist/execution/compaction-core.d.ts +4 -4
- package/dist/execution/eternal-autonomy.d.ts +1 -1
- package/dist/execution/index.js +138 -129
- package/dist/execution/model-runtime.d.ts +0 -7
- package/dist/execution/parallel-eternal-engine.d.ts +7 -7
- package/dist/extension/index.js +3 -3
- package/dist/goal/index.js +6 -6
- package/dist/hooks/index.js +3 -3
- package/dist/hq/index.js +14 -12
- package/dist/hq/persistence/event-log.d.ts +0 -1
- package/dist/hq/persistence.d.ts +4 -4
- package/dist/hq/publisher.d.ts +2 -0
- package/dist/index.d.ts +14 -11
- package/dist/index.js +728 -635
- package/dist/infrastructure/index.d.ts +4 -4
- package/dist/infrastructure/index.js +281 -260
- package/dist/infrastructure/token-counter.d.ts +9 -0
- package/dist/kernel/events/agent-events.d.ts +77 -3
- package/dist/kernel/events/brain-events.d.ts +12 -0
- package/dist/kernel/events/provider-events.d.ts +7 -1
- package/dist/kernel/events/session-events.d.ts +14 -0
- package/dist/kernel/events/tool-events.d.ts +13 -0
- package/dist/kernel/index.js +4 -4
- package/dist/mailbox-attach.d.ts +1 -1
- package/dist/models/index.js +10 -9
- package/dist/observability/event-bridge.d.ts +25 -5
- package/dist/observability/index.d.ts +9 -8
- package/dist/observability/index.js +459 -351
- package/dist/observability/tool-usage-source.d.ts +65 -0
- package/dist/plugin/index.d.ts +5 -0
- package/dist/plugin/index.js +66 -50
- package/dist/plugins/auto-review-plugin.d.ts +3 -2
- package/dist/plugins/review-finding-commands.d.ts +0 -8
- package/dist/{review-finding-store-DKAV3AS6.js → plugins/review-finding-store.js} +7 -6
- package/dist/plugins/review-finding-types.js +19 -0
- package/dist/plugins/review-report-integration.js +21 -0
- package/dist/{review-report-store-OWY3EC3N.js → plugins/review-report-store.js} +7 -6
- package/dist/plugins/review-report-types.js +13 -0
- package/dist/prompts/index.js +5 -5
- package/dist/registry/index.js +3 -3
- package/dist/registry/tool-registry.d.ts +59 -9
- package/dist/{registry-R23UBE7H.js → registry-7N4O3E7W.js} +5 -5
- package/dist/security/capabilities.d.ts +6 -0
- package/dist/security/file-permissions.d.ts +1 -1
- package/dist/security/index.js +47 -33
- package/dist/security/permission-policy.d.ts +12 -1
- package/dist/security/secret-scrubber.d.ts +15 -0
- package/dist/session-catalog/index.d.ts +1 -0
- package/dist/session-catalog/index.js +19 -14
- package/dist/session-catalog/project-server.js +30 -13
- package/dist/session-catalog/protocol.d.ts +32 -1
- package/dist/session-catalog/registry.d.ts +17 -1
- package/dist/session-catalog/session-agents.d.ts +56 -0
- package/dist/session-catalog/store-rebuild.d.ts +14 -0
- package/dist/session-catalog/store-schema.d.ts +26 -0
- package/dist/session-catalog/store.d.ts +27 -1
- package/dist/session-note-attach.d.ts +9 -0
- package/dist/skills/index.js +5 -5
- package/dist/statusline/index.d.ts +43 -0
- package/dist/statusline/index.js +102 -0
- package/dist/storage/board-store-port.d.ts +2 -2
- package/dist/storage/config-loader/in-project-policy.d.ts +29 -0
- package/dist/storage/config-loader.d.ts +3 -2
- package/dist/storage/file-session-writer.d.ts +4 -2
- package/dist/storage/goal-coordination.d.ts +6 -1
- package/dist/storage/goal-kanban.d.ts +4 -1
- package/dist/storage/index.d.ts +12 -4
- package/dist/storage/index.js +76 -61
- package/dist/storage/input-history-store.d.ts +2 -4
- package/dist/storage/memory-curator.d.ts +133 -0
- package/dist/storage/session-agent-attribution.d.ts +39 -0
- package/dist/storage/session-doctor.d.ts +109 -0
- package/dist/storage/session-event-bridge.d.ts +5 -7
- package/dist/storage/session-outcome.d.ts +42 -0
- package/dist/storage/session-recovery.d.ts +55 -0
- package/dist/storage/session-store/load-session-data.d.ts +11 -0
- package/dist/storage/session-store/prune-helpers.d.ts +1 -1
- package/dist/storage/session-store/resume-session.d.ts +0 -2
- package/dist/storage/session-store/types.d.ts +8 -0
- package/dist/storage/session-store.d.ts +3 -3
- package/dist/storage/session-summary-tracker.d.ts +8 -1
- package/dist/storage/session-write-buffer.d.ts +18 -0
- package/dist/storage/session-writer-truncate.d.ts +2 -0
- package/dist/tasking/index.js +2 -2
- package/dist/tools/fallback-manage-tools.d.ts +6 -4
- package/dist/tools/index.js +21 -21
- package/dist/tools/model-tier-set-tool.d.ts +66 -0
- package/dist/types/agent-bridge.d.ts +2 -1
- package/dist/types/config/mcp-features.d.ts +7 -0
- package/dist/types/config/model-tiers.d.ts +148 -0
- package/dist/types/config/root.d.ts +9 -0
- package/dist/types/config/tools.d.ts +73 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/context.d.ts +2 -0
- package/dist/types/default-config.d.ts +6 -0
- package/dist/types/errors.d.ts +2 -1
- package/dist/types/index.d.ts +11 -9
- package/dist/types/index.js +25 -15
- package/dist/types/multi-agent.d.ts +43 -0
- package/dist/types/plugin.d.ts +1 -1
- package/dist/types/provider.d.ts +15 -0
- package/dist/types/runtime-capability-manifest.d.ts +1 -1
- package/dist/types/secret-scrubber.d.ts +15 -0
- package/dist/types/session-markers.d.ts +37 -10
- package/dist/types/session-markers.js +1 -1
- package/dist/types/session-timeline.d.ts +197 -0
- package/dist/types/session-timeline.js +12 -0
- package/dist/types/session.d.ts +172 -11
- package/dist/types/system-prompt.d.ts +27 -0
- package/dist/utils/config-backup.d.ts +9 -1
- package/dist/utils/heap-watchdog.js +2 -2
- package/dist/utils/index.js +50 -48
- package/dist/utils/message-invariants.d.ts +4 -1
- package/dist/utils/regex-guard.d.ts +1 -1
- package/dist/utils/socket-path.d.ts +1 -1
- package/dist/utils/token-estimate.d.ts +6 -2
- package/dist/utils/wstack-paths.d.ts +2 -0
- package/dist/wiring/proxy-rewrite.d.ts +28 -0
- package/dist/wiring/proxy-rewrite.js +7 -1
- package/dist/worktree/index.js +2 -2
- package/instructions/agents/explore-companion.md +45 -18
- package/instructions/agents/memory-curator.md +34 -22
- package/instructions/coordination/director-preamble.md +12 -7
- package/instructions/coordination/subagent-baseline.md +26 -5
- package/instructions/leader-after-task.md +4 -1
- package/instructions/llm/chimera-review.md +30 -9
- package/instructions/llm/memory-curator.md +31 -0
- package/instructions/sections/tool/delegation-compact.md +2 -0
- package/instructions/sections/tool/delegation-full.md +5 -1
- package/instructions/sections/tool/mailbox-compact.md +5 -1
- package/instructions/sections/tool/mailbox-full.md +3 -0
- package/instructions/sections/tool/session-note-compact.md +3 -0
- package/instructions/sections/tool/session-note-full.md +15 -0
- package/instructions/system-lite.md +9 -4
- package/instructions/system-pro.md +66 -143
- package/instructions/system.md +73 -175
- package/package.json +33 -5
- package/dist/chunk-2BUUIMQB.js +0 -225
- package/dist/chunk-FAYRX2AD.js +0 -13
- package/dist/chunk-H5E77KUJ.js +0 -15
- package/dist/chunk-M7BS2K6U.js +0 -1
- package/dist/coordination/agents.d.ts +0 -8
- package/dist/coordination/transport.d.ts +0 -2
- package/dist/storage/session-writer/session-writer-summary-tracker.d.ts +0 -28
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SECRET_FILE_MODE
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6FHWXLPT.js";
|
|
4
4
|
import {
|
|
5
5
|
withSqliteExperimentalWarningSuppressed
|
|
6
6
|
} from "./chunk-LX5QWLBL.js";
|
|
7
7
|
import {
|
|
8
8
|
atomicWrite,
|
|
9
9
|
withFileLock
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OSGLYW5J.js";
|
|
11
11
|
|
|
12
12
|
// src/chronicle/identity.ts
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
@@ -27,6 +27,15 @@ function stableId(prefix, value) {
|
|
|
27
27
|
return `${prefix}_${createHash("sha256").update(value).digest("hex").slice(0, 24)}`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// src/chronicle/project-server-protocol.ts
|
|
31
|
+
var CHRONICLE_PROJECT_SERVER_PROTOCOL_VERSION = 2;
|
|
32
|
+
var CHRONICLE_PROJECT_SERVER_MAX_FRAME_CHARS = 64 * 1024 * 1024;
|
|
33
|
+
var CHRONICLE_MAX_APPEND_BATCH = 1e4;
|
|
34
|
+
function encodeChronicleProjectServerMessage(message) {
|
|
35
|
+
return `${JSON.stringify(message)}
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
// src/chronicle/event-hash.ts
|
|
31
40
|
import { createHash as createHash2 } from "node:crypto";
|
|
32
41
|
var GENESIS_HASH = "0".repeat(64);
|
|
@@ -664,6 +673,217 @@ function errorMessage(error) {
|
|
|
664
673
|
return error instanceof Error ? error.message : String(error);
|
|
665
674
|
}
|
|
666
675
|
|
|
676
|
+
// src/chronicle/metrics-schema.ts
|
|
677
|
+
import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
|
|
678
|
+
var SCHEMA_VERSION = 6;
|
|
679
|
+
var READ_CHUNK_BYTES = 1024 * 1024;
|
|
680
|
+
var SQLITE_SOURCE_PREFIX = "sqlite:";
|
|
681
|
+
var SQLITE_INGEST_BATCH = 2e3;
|
|
682
|
+
var EMPTY_FAMILIES = {
|
|
683
|
+
llm: 0,
|
|
684
|
+
agent: 0,
|
|
685
|
+
tool: 0,
|
|
686
|
+
file: 0,
|
|
687
|
+
memory: 0,
|
|
688
|
+
task: 0,
|
|
689
|
+
decision: 0,
|
|
690
|
+
runtime: 0,
|
|
691
|
+
finding: 0
|
|
692
|
+
};
|
|
693
|
+
var Ctor;
|
|
694
|
+
function loadDatabaseSync() {
|
|
695
|
+
if (Ctor) return Ctor;
|
|
696
|
+
if (Ctor === null) throw new Error("SQLite is unavailable in this runtime");
|
|
697
|
+
try {
|
|
698
|
+
Ctor = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync);
|
|
699
|
+
return Ctor;
|
|
700
|
+
} catch (error) {
|
|
701
|
+
Ctor = null;
|
|
702
|
+
throw new Error(
|
|
703
|
+
"Chronicle metrics need node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function isChronicleMetricsAvailable() {
|
|
708
|
+
try {
|
|
709
|
+
loadDatabaseSync();
|
|
710
|
+
return true;
|
|
711
|
+
} catch {
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
function ensureMetricsSchema(db) {
|
|
716
|
+
const version = db.prepare("PRAGMA user_version").get().user_version;
|
|
717
|
+
if (version !== 0 && version !== SCHEMA_VERSION) {
|
|
718
|
+
db.exec(
|
|
719
|
+
"DROP TABLE IF EXISTS ingest_state; DROP TABLE IF EXISTS provider_daily;DROP TABLE IF EXISTS task_outcomes; DROP TABLE IF EXISTS file_lineage;DROP TABLE IF EXISTS token_cost; DROP TABLE IF EXISTS daily_counters;DROP TABLE IF EXISTS family_daily; DROP TABLE IF EXISTS agent_daily;DROP TABLE IF EXISTS logical_request_daily; DROP TABLE IF EXISTS file_seen_daily;DROP TABLE IF EXISTS tool_daily;"
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
db.exec(`
|
|
723
|
+
CREATE TABLE IF NOT EXISTS ingest_state (
|
|
724
|
+
file TEXT PRIMARY KEY,
|
|
725
|
+
bytes INTEGER NOT NULL
|
|
726
|
+
);
|
|
727
|
+
CREATE TABLE IF NOT EXISTS provider_daily (
|
|
728
|
+
day TEXT NOT NULL,
|
|
729
|
+
provider_id TEXT NOT NULL,
|
|
730
|
+
model_id TEXT NOT NULL,
|
|
731
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
732
|
+
completed INTEGER NOT NULL DEFAULT 0,
|
|
733
|
+
failed INTEGER NOT NULL DEFAULT 0,
|
|
734
|
+
retries INTEGER NOT NULL DEFAULT 0,
|
|
735
|
+
fallbacks INTEGER NOT NULL DEFAULT 0,
|
|
736
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
737
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
738
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
739
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
740
|
+
duration_ms_total REAL NOT NULL DEFAULT 0,
|
|
741
|
+
duration_ms_max REAL NOT NULL DEFAULT 0,
|
|
742
|
+
duration_count INTEGER NOT NULL DEFAULT 0,
|
|
743
|
+
PRIMARY KEY (day, provider_id, model_id)
|
|
744
|
+
);
|
|
745
|
+
CREATE TABLE IF NOT EXISTS task_outcomes (
|
|
746
|
+
task_id TEXT PRIMARY KEY,
|
|
747
|
+
run_id TEXT NOT NULL DEFAULT '',
|
|
748
|
+
board_id TEXT NOT NULL DEFAULT '',
|
|
749
|
+
session_id TEXT NOT NULL DEFAULT '',
|
|
750
|
+
agent_id TEXT NOT NULL DEFAULT '',
|
|
751
|
+
status TEXT NOT NULL DEFAULT 'started',
|
|
752
|
+
started_at TEXT,
|
|
753
|
+
ended_at TEXT,
|
|
754
|
+
duration_ms REAL,
|
|
755
|
+
retries INTEGER NOT NULL DEFAULT 0,
|
|
756
|
+
verification_failures INTEGER NOT NULL DEFAULT 0
|
|
757
|
+
);
|
|
758
|
+
CREATE TABLE IF NOT EXISTS file_lineage (
|
|
759
|
+
event_id TEXT PRIMARY KEY,
|
|
760
|
+
path TEXT NOT NULL,
|
|
761
|
+
path_key TEXT NOT NULL,
|
|
762
|
+
operation TEXT NOT NULL,
|
|
763
|
+
occurred_at TEXT NOT NULL,
|
|
764
|
+
session_id TEXT NOT NULL DEFAULT '',
|
|
765
|
+
agent_id TEXT NOT NULL DEFAULT '',
|
|
766
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
767
|
+
board_id TEXT NOT NULL DEFAULT '',
|
|
768
|
+
run_id TEXT NOT NULL DEFAULT '',
|
|
769
|
+
tool_name TEXT NOT NULL DEFAULT '',
|
|
770
|
+
provider_id TEXT NOT NULL DEFAULT '',
|
|
771
|
+
model_id TEXT NOT NULL DEFAULT '',
|
|
772
|
+
logical_request_id TEXT NOT NULL DEFAULT '',
|
|
773
|
+
prompt_manifest_id TEXT NOT NULL DEFAULT '',
|
|
774
|
+
provenance_confidence TEXT NOT NULL DEFAULT 'unknown',
|
|
775
|
+
source TEXT NOT NULL DEFAULT ''
|
|
776
|
+
);
|
|
777
|
+
CREATE INDEX IF NOT EXISTS idx_file_lineage_path ON file_lineage(path_key, occurred_at);
|
|
778
|
+
CREATE INDEX IF NOT EXISTS idx_file_lineage_task ON file_lineage(task_id);
|
|
779
|
+
-- Latest cumulative token snapshot per (project, session, agent) scope.
|
|
780
|
+
-- token.accounted carries a running total, so last-write-wins is the
|
|
781
|
+
-- correct reduction; the WHERE guard on ingest keeps it order-independent.
|
|
782
|
+
--
|
|
783
|
+
-- The token columns exist because cost alone was unusable: subscription
|
|
784
|
+
-- providers price at 0, so a table holding only cost reported nothing for
|
|
785
|
+
-- most real sessions while the token counts it was derived from were
|
|
786
|
+
-- discarded. provider/model are recorded for the same reason the session
|
|
787
|
+
-- journal now stamps them on llm_response: a spend row that cannot name
|
|
788
|
+
-- the model it paid for cannot be attributed.
|
|
789
|
+
CREATE TABLE IF NOT EXISTS token_cost (
|
|
790
|
+
scope_key TEXT PRIMARY KEY,
|
|
791
|
+
day TEXT NOT NULL,
|
|
792
|
+
occurred_at TEXT NOT NULL,
|
|
793
|
+
sequence INTEGER NOT NULL,
|
|
794
|
+
cost REAL NOT NULL,
|
|
795
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
796
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
797
|
+
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
798
|
+
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
799
|
+
provider TEXT NOT NULL DEFAULT '',
|
|
800
|
+
model TEXT NOT NULL DEFAULT ''
|
|
801
|
+
);
|
|
802
|
+
CREATE INDEX IF NOT EXISTS idx_token_cost_model ON token_cost(provider, model);
|
|
803
|
+
CREATE TABLE IF NOT EXISTS daily_counters (
|
|
804
|
+
day TEXT PRIMARY KEY,
|
|
805
|
+
tool_calls INTEGER NOT NULL DEFAULT 0,
|
|
806
|
+
completed_tools INTEGER NOT NULL DEFAULT 0,
|
|
807
|
+
failed_tools INTEGER NOT NULL DEFAULT 0,
|
|
808
|
+
tool_duration_ms_total REAL NOT NULL DEFAULT 0,
|
|
809
|
+
tool_duration_ms_max REAL NOT NULL DEFAULT 0,
|
|
810
|
+
tool_duration_count INTEGER NOT NULL DEFAULT 0,
|
|
811
|
+
processes INTEGER NOT NULL DEFAULT 0,
|
|
812
|
+
failed_processes INTEGER NOT NULL DEFAULT 0,
|
|
813
|
+
file_events_all INTEGER NOT NULL DEFAULT 0,
|
|
814
|
+
decisions INTEGER NOT NULL DEFAULT 0,
|
|
815
|
+
escalations INTEGER NOT NULL DEFAULT 0,
|
|
816
|
+
agent_events INTEGER NOT NULL DEFAULT 0,
|
|
817
|
+
failures INTEGER NOT NULL DEFAULT 0,
|
|
818
|
+
cancellations INTEGER NOT NULL DEFAULT 0
|
|
819
|
+
);
|
|
820
|
+
CREATE TABLE IF NOT EXISTS family_daily (
|
|
821
|
+
day TEXT NOT NULL,
|
|
822
|
+
family TEXT NOT NULL,
|
|
823
|
+
count INTEGER NOT NULL DEFAULT 0,
|
|
824
|
+
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
825
|
+
PRIMARY KEY (day, family)
|
|
826
|
+
);
|
|
827
|
+
CREATE TABLE IF NOT EXISTS agent_daily (day TEXT NOT NULL, agent_id TEXT NOT NULL, PRIMARY KEY (day, agent_id));
|
|
828
|
+
CREATE TABLE IF NOT EXISTS logical_request_daily (day TEXT NOT NULL, logical_request_id TEXT NOT NULL, PRIMARY KEY (day, logical_request_id));
|
|
829
|
+
CREATE TABLE IF NOT EXISTS file_seen_daily (day TEXT NOT NULL, path_key TEXT NOT NULL, PRIMARY KEY (day, path_key));
|
|
830
|
+
-- Per-tool daily rollup for the auto-thinning pipeline. Distinct from
|
|
831
|
+
-- daily_counters (which is name-agnostic): this is keyed by tool_name so
|
|
832
|
+
-- underusedTools() can pick candidates without scanning the journal.
|
|
833
|
+
CREATE TABLE IF NOT EXISTS tool_daily (
|
|
834
|
+
day TEXT NOT NULL,
|
|
835
|
+
tool_name TEXT NOT NULL,
|
|
836
|
+
invocations INTEGER NOT NULL DEFAULT 0,
|
|
837
|
+
failures INTEGER NOT NULL DEFAULT 0,
|
|
838
|
+
duration_ms_total REAL NOT NULL DEFAULT 0,
|
|
839
|
+
duration_ms_max REAL NOT NULL DEFAULT 0,
|
|
840
|
+
last_invoked_at INTEGER,
|
|
841
|
+
PRIMARY KEY (day, tool_name)
|
|
842
|
+
);
|
|
843
|
+
CREATE INDEX IF NOT EXISTS idx_tool_daily_name ON tool_daily(tool_name, day);
|
|
844
|
+
PRAGMA user_version = ${SCHEMA_VERSION};
|
|
845
|
+
`);
|
|
846
|
+
}
|
|
847
|
+
function eventDay(event) {
|
|
848
|
+
return (event.occurredAt ?? event.observedAt).slice(0, 10);
|
|
849
|
+
}
|
|
850
|
+
function durationMs(event) {
|
|
851
|
+
const value = Number(event.durationNs ?? 0) / 1e6;
|
|
852
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
853
|
+
}
|
|
854
|
+
function numberOrDuration(event, attributes) {
|
|
855
|
+
const explicit = attributes.durationMs;
|
|
856
|
+
if (typeof explicit === "number" && Number.isFinite(explicit)) return explicit;
|
|
857
|
+
return durationMs(event);
|
|
858
|
+
}
|
|
859
|
+
function numberAt(event, dotPath) {
|
|
860
|
+
const value = readPath(event.attributes ?? {}, dotPath);
|
|
861
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
862
|
+
}
|
|
863
|
+
function readPath(value, key) {
|
|
864
|
+
return key.split(".").reduce(
|
|
865
|
+
(current, part) => current && typeof current === "object" ? current[part] : void 0,
|
|
866
|
+
value
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
function stringAt(record, key) {
|
|
870
|
+
const value = record[key];
|
|
871
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
872
|
+
}
|
|
873
|
+
function asString(value) {
|
|
874
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
875
|
+
}
|
|
876
|
+
function clampLimit(limit, fallback) {
|
|
877
|
+
if (typeof limit !== "number" || !Number.isFinite(limit) || limit <= 0) return fallback;
|
|
878
|
+
return Math.min(Math.floor(limit), 1e4);
|
|
879
|
+
}
|
|
880
|
+
function normalizeKey(value) {
|
|
881
|
+
return value.replaceAll("\\", "/");
|
|
882
|
+
}
|
|
883
|
+
function normalizePathKey(value) {
|
|
884
|
+
return value.replaceAll("\\", "/").replace(/^\.\//, "").toLowerCase();
|
|
885
|
+
}
|
|
886
|
+
|
|
667
887
|
// src/chronicle/partition-range-cache.ts
|
|
668
888
|
import * as fs2 from "node:fs/promises";
|
|
669
889
|
import * as path4 from "node:path";
|
|
@@ -901,13 +1121,15 @@ var ChronicleQueryEngine = class _ChronicleQueryEngine {
|
|
|
901
1121
|
events: pageEvents,
|
|
902
1122
|
total: totalCount,
|
|
903
1123
|
summary: finalizeSummary(summaryAcc),
|
|
904
|
-
...lastEvent && pageEvents.length < remainingCount ? {
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
1124
|
+
...lastEvent && pageEvents.length < remainingCount ? {
|
|
1125
|
+
nextCursor: encodeCursor({
|
|
1126
|
+
version: 1,
|
|
1127
|
+
order,
|
|
1128
|
+
queryHash,
|
|
1129
|
+
after: orderKey(lastEvent),
|
|
1130
|
+
snapshot: snapshotFiles.map(({ id, size }) => ({ id, size }))
|
|
1131
|
+
})
|
|
1132
|
+
} : {},
|
|
911
1133
|
scannedEvents,
|
|
912
1134
|
sourceFiles: snapshotFiles.length,
|
|
913
1135
|
invalidLines
|
|
@@ -975,7 +1197,9 @@ var ChronicleQueryEngine = class _ChronicleQueryEngine {
|
|
|
975
1197
|
let frontier = [...selected.values()];
|
|
976
1198
|
const depthLimit = Math.max(0, Math.min(hops, 10));
|
|
977
1199
|
for (let depth = 0; depth < depthLimit && frontier.length > 0 && selected.size < nodeLimit; depth++) {
|
|
978
|
-
const frontierKeys = new Set(
|
|
1200
|
+
const frontierKeys = new Set(
|
|
1201
|
+
frontier.flatMap((event) => relationKeys(event).map((relation) => relation.key))
|
|
1202
|
+
);
|
|
979
1203
|
const next = [];
|
|
980
1204
|
for await (const event of streamEvents(this.partitionFiles)) {
|
|
981
1205
|
if (selected.has(event.eventId)) continue;
|
|
@@ -988,22 +1212,30 @@ var ChronicleQueryEngine = class _ChronicleQueryEngine {
|
|
|
988
1212
|
}
|
|
989
1213
|
const nodes = [...selected.values()].sort(compareEvents);
|
|
990
1214
|
const byKey = /* @__PURE__ */ new Map();
|
|
991
|
-
for (const node of nodes)
|
|
992
|
-
const
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1215
|
+
for (const node of nodes)
|
|
1216
|
+
for (const relation of relationKeys(node)) {
|
|
1217
|
+
const related = byKey.get(relation.key) ?? [];
|
|
1218
|
+
related.push(node);
|
|
1219
|
+
byKey.set(relation.key, related);
|
|
1220
|
+
}
|
|
996
1221
|
const edges = [];
|
|
997
1222
|
const seen = /* @__PURE__ */ new Set();
|
|
998
|
-
for (const node of nodes)
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1223
|
+
for (const node of nodes)
|
|
1224
|
+
for (const relation of relationKeys(node))
|
|
1225
|
+
for (const candidate of byKey.get(relation.key) ?? []) {
|
|
1226
|
+
if (candidate.eventId === node.eventId) continue;
|
|
1227
|
+
const [from, to] = compareEvents(node, candidate) <= 0 ? [node, candidate] : [candidate, node];
|
|
1228
|
+
const id = `${from.eventId}:${to.eventId}:${relation.kind}`;
|
|
1229
|
+
if (!seen.has(id)) {
|
|
1230
|
+
seen.add(id);
|
|
1231
|
+
edges.push({
|
|
1232
|
+
from: from.eventId,
|
|
1233
|
+
to: to.eventId,
|
|
1234
|
+
kind: relation.kind,
|
|
1235
|
+
confidence: relation.confidence
|
|
1236
|
+
});
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1007
1239
|
return { nodes, edges, truncated: seedCount > nodeLimit || selected.size >= nodeLimit };
|
|
1008
1240
|
}
|
|
1009
1241
|
};
|
|
@@ -1089,47 +1321,69 @@ function createSummaryAccumulator() {
|
|
|
1089
1321
|
escalations: 0,
|
|
1090
1322
|
failures: 0,
|
|
1091
1323
|
cancellations: 0,
|
|
1092
|
-
families: {
|
|
1093
|
-
|
|
1324
|
+
families: {
|
|
1325
|
+
llm: 0,
|
|
1326
|
+
agent: 0,
|
|
1327
|
+
tool: 0,
|
|
1328
|
+
file: 0,
|
|
1329
|
+
memory: 0,
|
|
1330
|
+
task: 0,
|
|
1331
|
+
decision: 0,
|
|
1332
|
+
runtime: 0,
|
|
1333
|
+
finding: 0
|
|
1334
|
+
},
|
|
1335
|
+
failuresByFamily: {
|
|
1336
|
+
llm: 0,
|
|
1337
|
+
agent: 0,
|
|
1338
|
+
tool: 0,
|
|
1339
|
+
file: 0,
|
|
1340
|
+
memory: 0,
|
|
1341
|
+
task: 0,
|
|
1342
|
+
decision: 0,
|
|
1343
|
+
runtime: 0,
|
|
1344
|
+
finding: 0
|
|
1345
|
+
}
|
|
1094
1346
|
};
|
|
1095
1347
|
}
|
|
1096
1348
|
function updateSummary(acc, event) {
|
|
1097
1349
|
const family = signalFamily(event);
|
|
1098
1350
|
acc.families[family]++;
|
|
1099
1351
|
if (isTerminalFailure(event)) acc.failuresByFamily[family]++;
|
|
1100
|
-
if (event.correlation.logicalRequestId)
|
|
1352
|
+
if (event.correlation.logicalRequestId)
|
|
1353
|
+
acc.logicalRequestIds.add(event.correlation.logicalRequestId);
|
|
1101
1354
|
if (event.runtime?.providerId) acc.providers.add(event.runtime.providerId);
|
|
1102
1355
|
if (event.runtime?.modelId) acc.models.add(event.runtime.modelId);
|
|
1103
1356
|
if (event.eventType === "provider.attempt.started") acc.modelAttempts++;
|
|
1104
1357
|
else if (event.eventType === "provider.attempt.completed") {
|
|
1105
1358
|
acc.completedAttempts++;
|
|
1106
|
-
acc.inputTokens +=
|
|
1107
|
-
acc.outputTokens +=
|
|
1108
|
-
acc.cacheReadTokens +=
|
|
1109
|
-
acc.cacheWriteTokens +=
|
|
1110
|
-
const dur =
|
|
1359
|
+
acc.inputTokens += numberAt2(event, "usage.input");
|
|
1360
|
+
acc.outputTokens += numberAt2(event, "usage.output");
|
|
1361
|
+
acc.cacheReadTokens += numberAt2(event, "usage.cacheRead");
|
|
1362
|
+
acc.cacheWriteTokens += numberAt2(event, "usage.cacheWrite");
|
|
1363
|
+
const dur = durationMs2(event);
|
|
1111
1364
|
if (dur > 0) acc.providerDurations.push(dur);
|
|
1112
1365
|
} else if (event.eventType === "provider.attempt.failed") {
|
|
1113
1366
|
acc.failedAttempts++;
|
|
1114
1367
|
if (event.attributes?.retryScheduled === true) acc.scheduledRetries++;
|
|
1115
|
-
const dur =
|
|
1368
|
+
const dur = durationMs2(event);
|
|
1116
1369
|
if (dur > 0) acc.providerDurations.push(dur);
|
|
1117
1370
|
} else if (event.eventType === "provider.fallback") acc.fallbacks++;
|
|
1118
1371
|
else if (event.eventType === "tool.started") acc.toolCalls++;
|
|
1119
1372
|
else if (event.eventType === "tool.executed") {
|
|
1120
1373
|
acc.completedTools++;
|
|
1121
|
-
const dur =
|
|
1374
|
+
const dur = durationMs2(event);
|
|
1122
1375
|
if (dur > 0) acc.toolDurations.push(dur);
|
|
1123
1376
|
} else if (event.eventType === "tool.failed") {
|
|
1124
1377
|
acc.failedTools++;
|
|
1125
|
-
const dur =
|
|
1378
|
+
const dur = durationMs2(event);
|
|
1126
1379
|
if (dur > 0) acc.toolDurations.push(dur);
|
|
1127
1380
|
} else if (event.eventType === "process.started") acc.processes++;
|
|
1128
|
-
else if (event.eventType === "process.completed" && event.outcome === "failure")
|
|
1381
|
+
else if (event.eventType === "process.completed" && event.outcome === "failure")
|
|
1382
|
+
acc.failedProcesses++;
|
|
1129
1383
|
else if (event.eventType === "decision.requested") acc.decisions++;
|
|
1130
1384
|
else if (event.eventType === "decision.escalated") acc.escalations++;
|
|
1131
|
-
if (event.eventType === "token.accounted") {
|
|
1132
|
-
const cost =
|
|
1385
|
+
if (event.eventType === "token.accounted" || event.eventType === "subagent.token_accounted") {
|
|
1386
|
+
const cost = readPath2(event.attributes ?? {}, "cost.total");
|
|
1133
1387
|
if (typeof cost === "number" && Number.isFinite(cost)) {
|
|
1134
1388
|
const key = scopeKey(event);
|
|
1135
1389
|
const existing = acc.costByScope.get(key);
|
|
@@ -1187,10 +1441,16 @@ function finalizeSummary(acc) {
|
|
|
1187
1441
|
}
|
|
1188
1442
|
Object.defineProperty(ChronicleQueryEngine.prototype, "partitionFiles", {
|
|
1189
1443
|
get() {
|
|
1190
|
-
throw new Error(
|
|
1444
|
+
throw new Error(
|
|
1445
|
+
"ChronicleQueryEngine no longer loads events on construction. Use async query()."
|
|
1446
|
+
);
|
|
1191
1447
|
},
|
|
1192
1448
|
set(_val) {
|
|
1193
|
-
Object.defineProperty(this, "partitionFiles", {
|
|
1449
|
+
Object.defineProperty(this, "partitionFiles", {
|
|
1450
|
+
value: _val,
|
|
1451
|
+
writable: false,
|
|
1452
|
+
configurable: false
|
|
1453
|
+
});
|
|
1194
1454
|
}
|
|
1195
1455
|
});
|
|
1196
1456
|
async function findChroniclePartitions(root) {
|
|
@@ -1214,11 +1474,11 @@ async function findPartitions(root) {
|
|
|
1214
1474
|
await visit(root);
|
|
1215
1475
|
return result.sort(comparePartitionPaths);
|
|
1216
1476
|
}
|
|
1217
|
-
function
|
|
1218
|
-
const value =
|
|
1477
|
+
function numberAt2(event, dotPath) {
|
|
1478
|
+
const value = readPath2(event.attributes ?? {}, dotPath);
|
|
1219
1479
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
1220
1480
|
}
|
|
1221
|
-
function
|
|
1481
|
+
function durationMs2(event) {
|
|
1222
1482
|
const value = Number(event.durationNs ?? 0) / 1e6;
|
|
1223
1483
|
return Number.isFinite(value) ? value : 0;
|
|
1224
1484
|
}
|
|
@@ -1233,23 +1493,29 @@ function scopeKey(event) {
|
|
|
1233
1493
|
}
|
|
1234
1494
|
function signalFamily(event) {
|
|
1235
1495
|
if (/^(?:decision|brain|permission)\./.test(event.eventType)) return "decision";
|
|
1236
|
-
if (event.resource?.kind === "file" || event.resource?.kind === "symbol" || /^(?:file|worktree)\./.test(event.eventType))
|
|
1496
|
+
if (event.resource?.kind === "file" || event.resource?.kind === "symbol" || /^(?:file|worktree)\./.test(event.eventType))
|
|
1497
|
+
return "file";
|
|
1237
1498
|
if (/^(?:provider|token|context|ctx|compaction)\./.test(event.eventType)) return "llm";
|
|
1238
1499
|
if (/^(?:agent|subagent|delegate|fleet|concurrency)\./.test(event.eventType)) return "agent";
|
|
1239
1500
|
if (/^(?:tool|process|mcp|network)\./.test(event.eventType)) return "tool";
|
|
1240
1501
|
if (/^(?:memory|storage|trust)\./.test(event.eventType)) return "memory";
|
|
1241
|
-
if (/^(?:sdd|task|kanban|checkpoint|session|iteration|in_flight)\./.test(event.eventType))
|
|
1502
|
+
if (/^(?:sdd|task|kanban|checkpoint|session|iteration|in_flight)\./.test(event.eventType))
|
|
1503
|
+
return "task";
|
|
1242
1504
|
if (/^(?:finding|review)\./.test(event.eventType)) return "finding";
|
|
1243
1505
|
return "runtime";
|
|
1244
1506
|
}
|
|
1245
1507
|
function isTerminalFailure(event) {
|
|
1246
|
-
if (event.eventType === "provider.attempt.failed")
|
|
1247
|
-
|
|
1508
|
+
if (event.eventType === "provider.attempt.failed")
|
|
1509
|
+
return event.attributes?.retryScheduled !== true;
|
|
1510
|
+
return event.eventType === "tool.failed" || event.eventType === "process.completed" && event.outcome === "failure" || /^(?:agent\.run\.error|sdd\.task\.failed|compaction\.failed|network\.request\.failed)$/.test(
|
|
1511
|
+
event.eventType
|
|
1512
|
+
);
|
|
1248
1513
|
}
|
|
1249
1514
|
function relationKeys(event) {
|
|
1250
1515
|
const result = [];
|
|
1251
1516
|
const add = (kind, value, confidence) => {
|
|
1252
|
-
if (typeof value === "string" && value)
|
|
1517
|
+
if (typeof value === "string" && value)
|
|
1518
|
+
result.push({ key: `${kind}:${value}`, kind, confidence });
|
|
1253
1519
|
};
|
|
1254
1520
|
add("trace", event.correlation.traceId, "correlated");
|
|
1255
1521
|
add("tool_call", event.correlation.toolCallId, "explicit");
|
|
@@ -1269,7 +1535,8 @@ function relationKeys(event) {
|
|
|
1269
1535
|
if (typeof resource?.id === "string") add("resource_lineage", resource.id, "inferred");
|
|
1270
1536
|
}
|
|
1271
1537
|
}
|
|
1272
|
-
if (event.correlation.parentSpanId)
|
|
1538
|
+
if (event.correlation.parentSpanId)
|
|
1539
|
+
add("parent_span", event.correlation.parentSpanId, "explicit");
|
|
1273
1540
|
add("parent_span", event.correlation.spanId, "explicit");
|
|
1274
1541
|
return result;
|
|
1275
1542
|
}
|
|
@@ -1279,18 +1546,25 @@ function matches(event, query) {
|
|
|
1279
1546
|
if (query.outcomes && (!event.outcome || !query.outcomes.includes(event.outcome))) return false;
|
|
1280
1547
|
const occurredAt = event.occurredAt ?? event.observedAt;
|
|
1281
1548
|
if (query.from && occurredAt < query.from || query.to && occurredAt > query.to) return false;
|
|
1282
|
-
if (!equal(query.projectId, event.scope.projectId) || !equal(query.sessionId, event.scope.sessionId))
|
|
1283
|
-
|
|
1284
|
-
if (!equal(query.
|
|
1285
|
-
|
|
1549
|
+
if (!equal(query.projectId, event.scope.projectId) || !equal(query.sessionId, event.scope.sessionId))
|
|
1550
|
+
return false;
|
|
1551
|
+
if (!equal(query.agentId, event.scope.agentId) || !equal(query.taskId, event.scope.taskId))
|
|
1552
|
+
return false;
|
|
1553
|
+
if (!equal(query.providerId, event.runtime?.providerId) || !equal(query.modelId, event.runtime?.modelId))
|
|
1554
|
+
return false;
|
|
1555
|
+
if (!equal(query.traceId, event.correlation.traceId) || !equal(query.logicalRequestId, event.correlation.logicalRequestId))
|
|
1556
|
+
return false;
|
|
1286
1557
|
if (!equal(query.promptManifestId, event.correlation.promptManifestId)) return false;
|
|
1287
|
-
if (!equal(query.attemptId, event.correlation.attemptId) || !equal(query.toolCallId, event.correlation.toolCallId))
|
|
1288
|
-
|
|
1558
|
+
if (!equal(query.attemptId, event.correlation.attemptId) || !equal(query.toolCallId, event.correlation.toolCallId))
|
|
1559
|
+
return false;
|
|
1560
|
+
if (!equal(query.resourceKind, event.resource?.kind) || !equal(query.resourceId, event.resource?.id))
|
|
1561
|
+
return false;
|
|
1289
1562
|
if (query.path && normalize(event.resource?.path) !== normalize(query.path)) return false;
|
|
1290
1563
|
if (query.line !== void 0 && !lineContains(event, query.line)) return false;
|
|
1291
1564
|
if (query.tags && !objectContains(event.tags, query.tags)) return false;
|
|
1292
1565
|
if (query.attributes && !objectContains(event.attributes, query.attributes)) return false;
|
|
1293
|
-
if (query.text && !JSON.stringify(event).toLocaleLowerCase().includes(query.text.toLocaleLowerCase()))
|
|
1566
|
+
if (query.text && !JSON.stringify(event).toLocaleLowerCase().includes(query.text.toLocaleLowerCase()))
|
|
1567
|
+
return false;
|
|
1294
1568
|
return true;
|
|
1295
1569
|
}
|
|
1296
1570
|
function equal(expected, actual) {
|
|
@@ -1305,10 +1579,15 @@ function lineContains(event, line) {
|
|
|
1305
1579
|
return start !== void 0 && end !== void 0 && line >= start && line <= end;
|
|
1306
1580
|
}
|
|
1307
1581
|
function objectContains(actual, expected) {
|
|
1308
|
-
return Boolean(
|
|
1582
|
+
return Boolean(
|
|
1583
|
+
actual && Object.entries(expected).every(([key, value]) => deepEqual(readPath2(actual, key), value))
|
|
1584
|
+
);
|
|
1309
1585
|
}
|
|
1310
|
-
function
|
|
1311
|
-
return key.split(".").reduce(
|
|
1586
|
+
function readPath2(value, key) {
|
|
1587
|
+
return key.split(".").reduce(
|
|
1588
|
+
(current, part) => current && typeof current === "object" ? current[part] : void 0,
|
|
1589
|
+
value
|
|
1590
|
+
);
|
|
1312
1591
|
}
|
|
1313
1592
|
function deepEqual(left, right) {
|
|
1314
1593
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
@@ -1354,17 +1633,21 @@ function decodeCursor(encoded, order, queryHash) {
|
|
|
1354
1633
|
}
|
|
1355
1634
|
return parsed;
|
|
1356
1635
|
} catch (error) {
|
|
1357
|
-
throw new Error(
|
|
1636
|
+
throw new Error(
|
|
1637
|
+
`Invalid Chronicle cursor: ${error instanceof Error ? error.message : String(error)}`
|
|
1638
|
+
);
|
|
1358
1639
|
}
|
|
1359
1640
|
}
|
|
1360
1641
|
function isCursor(value) {
|
|
1361
1642
|
if (!value || typeof value !== "object") return false;
|
|
1362
1643
|
const cursor = value;
|
|
1363
1644
|
const after = cursor.after;
|
|
1364
|
-
if (cursor.version !== 1 || cursor.order !== "asc" && cursor.order !== "desc" || typeof cursor.queryHash !== "string" || !after || typeof after.occurredAt !== "string" || typeof after.persistedAt !== "string" || !Number.isSafeInteger(after.sequence) || typeof after.eventId !== "string" || !Array.isArray(cursor.snapshot) || cursor.snapshot.length > MAX_CURSOR_SNAPSHOT_ENTRIES)
|
|
1645
|
+
if (cursor.version !== 1 || cursor.order !== "asc" && cursor.order !== "desc" || typeof cursor.queryHash !== "string" || !after || typeof after.occurredAt !== "string" || typeof after.persistedAt !== "string" || !Number.isSafeInteger(after.sequence) || typeof after.eventId !== "string" || !Array.isArray(cursor.snapshot) || cursor.snapshot.length > MAX_CURSOR_SNAPSHOT_ENTRIES)
|
|
1646
|
+
return false;
|
|
1365
1647
|
const snapshotIds = /* @__PURE__ */ new Set();
|
|
1366
1648
|
for (const entry of cursor.snapshot) {
|
|
1367
|
-
if (!entry || typeof entry.id !== "string" || !entry.id || !Number.isSafeInteger(entry.size) || entry.size < 0 || snapshotIds.has(entry.id))
|
|
1649
|
+
if (!entry || typeof entry.id !== "string" || !entry.id || !Number.isSafeInteger(entry.size) || entry.size < 0 || snapshotIds.has(entry.id))
|
|
1650
|
+
return false;
|
|
1368
1651
|
snapshotIds.add(entry.id);
|
|
1369
1652
|
}
|
|
1370
1653
|
return true;
|
|
@@ -1373,29 +1656,33 @@ async function captureSnapshot(files) {
|
|
|
1373
1656
|
if (files.length > MAX_CURSOR_SNAPSHOT_ENTRIES) {
|
|
1374
1657
|
throw new Error("Chronicle snapshot contains too many partitions");
|
|
1375
1658
|
}
|
|
1376
|
-
return Promise.all(
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1659
|
+
return Promise.all(
|
|
1660
|
+
files.map(async (file) => {
|
|
1661
|
+
let size = 0;
|
|
1662
|
+
try {
|
|
1663
|
+
size = (await fs3.stat(file)).size;
|
|
1664
|
+
} catch {
|
|
1665
|
+
}
|
|
1666
|
+
return { file, id: fileId(file), size };
|
|
1667
|
+
})
|
|
1668
|
+
);
|
|
1384
1669
|
}
|
|
1385
1670
|
async function resolveSnapshotFiles(files, snapshot) {
|
|
1386
1671
|
const currentFiles = new Map(files.map((file) => [fileId(file), file]));
|
|
1387
|
-
return Promise.all(
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1672
|
+
return Promise.all(
|
|
1673
|
+
snapshot.map(async (entry) => {
|
|
1674
|
+
const file = currentFiles.get(entry.id);
|
|
1675
|
+
if (!file) throw new Error("Chronicle cursor snapshot has expired");
|
|
1676
|
+
let currentSize;
|
|
1677
|
+
try {
|
|
1678
|
+
currentSize = (await fs3.stat(file)).size;
|
|
1679
|
+
} catch {
|
|
1680
|
+
throw new Error("Chronicle cursor snapshot has expired");
|
|
1681
|
+
}
|
|
1682
|
+
if (currentSize < entry.size) throw new Error("Chronicle cursor snapshot has expired");
|
|
1683
|
+
return { file, ...entry };
|
|
1684
|
+
})
|
|
1685
|
+
);
|
|
1399
1686
|
}
|
|
1400
1687
|
function fileId(file) {
|
|
1401
1688
|
return createHash3("sha256").update(path5.resolve(file), "utf8").digest("base64url");
|
|
@@ -1444,14 +1731,17 @@ function isResource(value) {
|
|
|
1444
1731
|
"network",
|
|
1445
1732
|
"artifact",
|
|
1446
1733
|
"other"
|
|
1447
|
-
].includes(String(value.kind)) || typeof value.id !== "string")
|
|
1734
|
+
].includes(String(value.kind)) || typeof value.id !== "string")
|
|
1735
|
+
return false;
|
|
1448
1736
|
return optionalStrings(value, ["path", "contentHashBefore", "contentHashAfter"]) && optionalFiniteNumbers(value, ["lineStart", "lineEnd"]);
|
|
1449
1737
|
}
|
|
1450
1738
|
function optionalStrings(value, keys) {
|
|
1451
1739
|
return keys.every((key) => value[key] === void 0 || typeof value[key] === "string");
|
|
1452
1740
|
}
|
|
1453
1741
|
function optionalFiniteNumbers(value, keys) {
|
|
1454
|
-
return keys.every(
|
|
1742
|
+
return keys.every(
|
|
1743
|
+
(key) => value[key] === void 0 || typeof value[key] === "number" && Number.isFinite(value[key])
|
|
1744
|
+
);
|
|
1455
1745
|
}
|
|
1456
1746
|
function isStringRecord(value) {
|
|
1457
1747
|
return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
@@ -1614,21 +1904,21 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
1614
1904
|
import * as path6 from "node:path";
|
|
1615
1905
|
|
|
1616
1906
|
// src/chronicle/sqlite-journal-schema.ts
|
|
1617
|
-
import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
|
|
1907
|
+
import { loadRuntimeDatabaseSync as loadRuntimeDatabaseSync2 } from "@wrongstack/persistence";
|
|
1618
1908
|
var CHRONICLE_SQLITE_FILE = "chronicle.sqlite";
|
|
1619
1909
|
var LEGACY_JSONL_MIGRATION_KEY = "legacy-jsonl-v1";
|
|
1620
1910
|
var LEGACY_JSONL_QUARANTINE_KEY = "legacy-jsonl-v1:quarantine";
|
|
1621
1911
|
var LEGACY_JSONL_BOUNDARY_KEY = "legacy-jsonl-v1:boundary";
|
|
1622
|
-
var
|
|
1623
|
-
var
|
|
1624
|
-
function
|
|
1625
|
-
if (
|
|
1626
|
-
if (
|
|
1912
|
+
var SCHEMA_VERSION2 = 3;
|
|
1913
|
+
var Ctor2;
|
|
1914
|
+
function loadDatabaseSync2() {
|
|
1915
|
+
if (Ctor2) return Ctor2;
|
|
1916
|
+
if (Ctor2 === null) throw new Error("SQLite is unavailable in this runtime");
|
|
1627
1917
|
try {
|
|
1628
|
-
|
|
1629
|
-
return
|
|
1918
|
+
Ctor2 = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync2);
|
|
1919
|
+
return Ctor2;
|
|
1630
1920
|
} catch (error) {
|
|
1631
|
-
|
|
1921
|
+
Ctor2 = null;
|
|
1632
1922
|
throw new Error(
|
|
1633
1923
|
"The Chronicle journal needs node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
|
|
1634
1924
|
);
|
|
@@ -1702,8 +1992,8 @@ function ensureChronicleSchema(db) {
|
|
|
1702
1992
|
db.exec("ALTER TABLE events ADD COLUMN prompt_manifest_id TEXT");
|
|
1703
1993
|
}
|
|
1704
1994
|
db.exec("CREATE INDEX IF NOT EXISTS events_prompt_manifest ON events(prompt_manifest_id)");
|
|
1705
|
-
if (version !==
|
|
1706
|
-
db.exec(`PRAGMA user_version = ${
|
|
1995
|
+
if (version !== SCHEMA_VERSION2) {
|
|
1996
|
+
db.exec(`PRAGMA user_version = ${SCHEMA_VERSION2}`);
|
|
1707
1997
|
}
|
|
1708
1998
|
}
|
|
1709
1999
|
|
|
@@ -2011,10 +2301,12 @@ var ChronicleSqliteJournal = class {
|
|
|
2011
2301
|
this.maxEvents = options.maxEvents;
|
|
2012
2302
|
this.retentionCheckIntervalMs = options.retentionCheckIntervalMs ?? 60 * 60 * 1e3;
|
|
2013
2303
|
this.trimSlack = this.maxEvents === void 0 ? 0 : Math.min(MAX_TRIM_SLACK_EVENTS, Math.floor(this.maxEvents * TRIM_SLACK_RATIO));
|
|
2014
|
-
const Database =
|
|
2304
|
+
const Database = loadDatabaseSync2();
|
|
2015
2305
|
this.db = new Database(this.dbPath);
|
|
2016
2306
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
2017
|
-
this.db.exec(
|
|
2307
|
+
this.db.exec(
|
|
2308
|
+
options.durability === "full" ? "PRAGMA synchronous = FULL" : "PRAGMA synchronous = NORMAL"
|
|
2309
|
+
);
|
|
2018
2310
|
this.db.exec(`PRAGMA wal_autocheckpoint = ${WAL_AUTOCHECKPOINT_PAGES}`);
|
|
2019
2311
|
this.db.exec(`PRAGMA journal_size_limit = ${WAL_SIZE_LIMIT_BYTES}`);
|
|
2020
2312
|
ensureChronicleSchema(this.db);
|
|
@@ -2415,186 +2707,6 @@ var ChronicleSqliteJournal = class {
|
|
|
2415
2707
|
}
|
|
2416
2708
|
};
|
|
2417
2709
|
|
|
2418
|
-
// src/chronicle/metrics-schema.ts
|
|
2419
|
-
import { loadRuntimeDatabaseSync as loadRuntimeDatabaseSync2 } from "@wrongstack/persistence";
|
|
2420
|
-
var SCHEMA_VERSION2 = 4;
|
|
2421
|
-
var READ_CHUNK_BYTES = 1024 * 1024;
|
|
2422
|
-
var SQLITE_SOURCE_PREFIX = "sqlite:";
|
|
2423
|
-
var SQLITE_INGEST_BATCH = 2e3;
|
|
2424
|
-
var EMPTY_FAMILIES = {
|
|
2425
|
-
llm: 0,
|
|
2426
|
-
agent: 0,
|
|
2427
|
-
tool: 0,
|
|
2428
|
-
file: 0,
|
|
2429
|
-
memory: 0,
|
|
2430
|
-
task: 0,
|
|
2431
|
-
decision: 0,
|
|
2432
|
-
runtime: 0,
|
|
2433
|
-
finding: 0
|
|
2434
|
-
};
|
|
2435
|
-
var Ctor2;
|
|
2436
|
-
function loadDatabaseSync2() {
|
|
2437
|
-
if (Ctor2) return Ctor2;
|
|
2438
|
-
if (Ctor2 === null) throw new Error("SQLite is unavailable in this runtime");
|
|
2439
|
-
try {
|
|
2440
|
-
Ctor2 = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync2);
|
|
2441
|
-
return Ctor2;
|
|
2442
|
-
} catch (error) {
|
|
2443
|
-
Ctor2 = null;
|
|
2444
|
-
throw new Error(
|
|
2445
|
-
"Chronicle metrics need node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
|
|
2446
|
-
);
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
|
-
function isChronicleMetricsAvailable() {
|
|
2450
|
-
try {
|
|
2451
|
-
loadDatabaseSync2();
|
|
2452
|
-
return true;
|
|
2453
|
-
} catch {
|
|
2454
|
-
return false;
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
|
-
function ensureMetricsSchema(db) {
|
|
2458
|
-
const version = db.prepare("PRAGMA user_version").get().user_version;
|
|
2459
|
-
if (version !== 0 && version !== SCHEMA_VERSION2) {
|
|
2460
|
-
db.exec(
|
|
2461
|
-
"DROP TABLE IF EXISTS ingest_state; DROP TABLE IF EXISTS provider_daily;DROP TABLE IF EXISTS task_outcomes; DROP TABLE IF EXISTS file_lineage;DROP TABLE IF EXISTS token_cost; DROP TABLE IF EXISTS daily_counters;DROP TABLE IF EXISTS family_daily; DROP TABLE IF EXISTS agent_daily;DROP TABLE IF EXISTS logical_request_daily; DROP TABLE IF EXISTS file_seen_daily;"
|
|
2462
|
-
);
|
|
2463
|
-
}
|
|
2464
|
-
db.exec(`
|
|
2465
|
-
CREATE TABLE IF NOT EXISTS ingest_state (
|
|
2466
|
-
file TEXT PRIMARY KEY,
|
|
2467
|
-
bytes INTEGER NOT NULL
|
|
2468
|
-
);
|
|
2469
|
-
CREATE TABLE IF NOT EXISTS provider_daily (
|
|
2470
|
-
day TEXT NOT NULL,
|
|
2471
|
-
provider_id TEXT NOT NULL,
|
|
2472
|
-
model_id TEXT NOT NULL,
|
|
2473
|
-
attempts INTEGER NOT NULL DEFAULT 0,
|
|
2474
|
-
completed INTEGER NOT NULL DEFAULT 0,
|
|
2475
|
-
failed INTEGER NOT NULL DEFAULT 0,
|
|
2476
|
-
retries INTEGER NOT NULL DEFAULT 0,
|
|
2477
|
-
fallbacks INTEGER NOT NULL DEFAULT 0,
|
|
2478
|
-
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2479
|
-
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2480
|
-
cache_read_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2481
|
-
cache_write_tokens INTEGER NOT NULL DEFAULT 0,
|
|
2482
|
-
duration_ms_total REAL NOT NULL DEFAULT 0,
|
|
2483
|
-
duration_ms_max REAL NOT NULL DEFAULT 0,
|
|
2484
|
-
duration_count INTEGER NOT NULL DEFAULT 0,
|
|
2485
|
-
PRIMARY KEY (day, provider_id, model_id)
|
|
2486
|
-
);
|
|
2487
|
-
CREATE TABLE IF NOT EXISTS task_outcomes (
|
|
2488
|
-
task_id TEXT PRIMARY KEY,
|
|
2489
|
-
run_id TEXT NOT NULL DEFAULT '',
|
|
2490
|
-
board_id TEXT NOT NULL DEFAULT '',
|
|
2491
|
-
session_id TEXT NOT NULL DEFAULT '',
|
|
2492
|
-
agent_id TEXT NOT NULL DEFAULT '',
|
|
2493
|
-
status TEXT NOT NULL DEFAULT 'started',
|
|
2494
|
-
started_at TEXT,
|
|
2495
|
-
ended_at TEXT,
|
|
2496
|
-
duration_ms REAL,
|
|
2497
|
-
retries INTEGER NOT NULL DEFAULT 0,
|
|
2498
|
-
verification_failures INTEGER NOT NULL DEFAULT 0
|
|
2499
|
-
);
|
|
2500
|
-
CREATE TABLE IF NOT EXISTS file_lineage (
|
|
2501
|
-
event_id TEXT PRIMARY KEY,
|
|
2502
|
-
path TEXT NOT NULL,
|
|
2503
|
-
path_key TEXT NOT NULL,
|
|
2504
|
-
operation TEXT NOT NULL,
|
|
2505
|
-
occurred_at TEXT NOT NULL,
|
|
2506
|
-
session_id TEXT NOT NULL DEFAULT '',
|
|
2507
|
-
agent_id TEXT NOT NULL DEFAULT '',
|
|
2508
|
-
task_id TEXT NOT NULL DEFAULT '',
|
|
2509
|
-
board_id TEXT NOT NULL DEFAULT '',
|
|
2510
|
-
run_id TEXT NOT NULL DEFAULT '',
|
|
2511
|
-
tool_name TEXT NOT NULL DEFAULT '',
|
|
2512
|
-
provider_id TEXT NOT NULL DEFAULT '',
|
|
2513
|
-
model_id TEXT NOT NULL DEFAULT '',
|
|
2514
|
-
logical_request_id TEXT NOT NULL DEFAULT '',
|
|
2515
|
-
prompt_manifest_id TEXT NOT NULL DEFAULT '',
|
|
2516
|
-
provenance_confidence TEXT NOT NULL DEFAULT 'unknown',
|
|
2517
|
-
source TEXT NOT NULL DEFAULT ''
|
|
2518
|
-
);
|
|
2519
|
-
CREATE INDEX IF NOT EXISTS idx_file_lineage_path ON file_lineage(path_key, occurred_at);
|
|
2520
|
-
CREATE INDEX IF NOT EXISTS idx_file_lineage_task ON file_lineage(task_id);
|
|
2521
|
-
CREATE TABLE IF NOT EXISTS token_cost (
|
|
2522
|
-
scope_key TEXT PRIMARY KEY,
|
|
2523
|
-
day TEXT NOT NULL,
|
|
2524
|
-
occurred_at TEXT NOT NULL,
|
|
2525
|
-
sequence INTEGER NOT NULL,
|
|
2526
|
-
cost REAL NOT NULL
|
|
2527
|
-
);
|
|
2528
|
-
CREATE TABLE IF NOT EXISTS daily_counters (
|
|
2529
|
-
day TEXT PRIMARY KEY,
|
|
2530
|
-
tool_calls INTEGER NOT NULL DEFAULT 0,
|
|
2531
|
-
completed_tools INTEGER NOT NULL DEFAULT 0,
|
|
2532
|
-
failed_tools INTEGER NOT NULL DEFAULT 0,
|
|
2533
|
-
tool_duration_ms_total REAL NOT NULL DEFAULT 0,
|
|
2534
|
-
tool_duration_ms_max REAL NOT NULL DEFAULT 0,
|
|
2535
|
-
tool_duration_count INTEGER NOT NULL DEFAULT 0,
|
|
2536
|
-
processes INTEGER NOT NULL DEFAULT 0,
|
|
2537
|
-
failed_processes INTEGER NOT NULL DEFAULT 0,
|
|
2538
|
-
file_events_all INTEGER NOT NULL DEFAULT 0,
|
|
2539
|
-
decisions INTEGER NOT NULL DEFAULT 0,
|
|
2540
|
-
escalations INTEGER NOT NULL DEFAULT 0,
|
|
2541
|
-
agent_events INTEGER NOT NULL DEFAULT 0,
|
|
2542
|
-
failures INTEGER NOT NULL DEFAULT 0,
|
|
2543
|
-
cancellations INTEGER NOT NULL DEFAULT 0
|
|
2544
|
-
);
|
|
2545
|
-
CREATE TABLE IF NOT EXISTS family_daily (
|
|
2546
|
-
day TEXT NOT NULL,
|
|
2547
|
-
family TEXT NOT NULL,
|
|
2548
|
-
count INTEGER NOT NULL DEFAULT 0,
|
|
2549
|
-
failure_count INTEGER NOT NULL DEFAULT 0,
|
|
2550
|
-
PRIMARY KEY (day, family)
|
|
2551
|
-
);
|
|
2552
|
-
CREATE TABLE IF NOT EXISTS agent_daily (day TEXT NOT NULL, agent_id TEXT NOT NULL, PRIMARY KEY (day, agent_id));
|
|
2553
|
-
CREATE TABLE IF NOT EXISTS logical_request_daily (day TEXT NOT NULL, logical_request_id TEXT NOT NULL, PRIMARY KEY (day, logical_request_id));
|
|
2554
|
-
CREATE TABLE IF NOT EXISTS file_seen_daily (day TEXT NOT NULL, path_key TEXT NOT NULL, PRIMARY KEY (day, path_key));
|
|
2555
|
-
PRAGMA user_version = ${SCHEMA_VERSION2};
|
|
2556
|
-
`);
|
|
2557
|
-
}
|
|
2558
|
-
function eventDay(event) {
|
|
2559
|
-
return (event.occurredAt ?? event.observedAt).slice(0, 10);
|
|
2560
|
-
}
|
|
2561
|
-
function durationMs2(event) {
|
|
2562
|
-
const value = Number(event.durationNs ?? 0) / 1e6;
|
|
2563
|
-
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
2564
|
-
}
|
|
2565
|
-
function numberOrDuration(event, attributes) {
|
|
2566
|
-
const explicit = attributes.durationMs;
|
|
2567
|
-
if (typeof explicit === "number" && Number.isFinite(explicit)) return explicit;
|
|
2568
|
-
return durationMs2(event);
|
|
2569
|
-
}
|
|
2570
|
-
function numberAt2(event, dotPath) {
|
|
2571
|
-
const value = readPath2(event.attributes ?? {}, dotPath);
|
|
2572
|
-
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
2573
|
-
}
|
|
2574
|
-
function readPath2(value, key) {
|
|
2575
|
-
return key.split(".").reduce(
|
|
2576
|
-
(current, part) => current && typeof current === "object" ? current[part] : void 0,
|
|
2577
|
-
value
|
|
2578
|
-
);
|
|
2579
|
-
}
|
|
2580
|
-
function stringAt(record, key) {
|
|
2581
|
-
const value = record[key];
|
|
2582
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2583
|
-
}
|
|
2584
|
-
function asString(value) {
|
|
2585
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
2586
|
-
}
|
|
2587
|
-
function clampLimit(limit, fallback) {
|
|
2588
|
-
if (typeof limit !== "number" || !Number.isFinite(limit) || limit <= 0) return fallback;
|
|
2589
|
-
return Math.min(Math.floor(limit), 1e4);
|
|
2590
|
-
}
|
|
2591
|
-
function normalizeKey(value) {
|
|
2592
|
-
return value.replaceAll("\\", "/");
|
|
2593
|
-
}
|
|
2594
|
-
function normalizePathKey(value) {
|
|
2595
|
-
return value.replaceAll("\\", "/").replace(/^\.\//, "").toLowerCase();
|
|
2596
|
-
}
|
|
2597
|
-
|
|
2598
2710
|
// src/chronicle/metrics-store.ts
|
|
2599
2711
|
import * as path8 from "node:path";
|
|
2600
2712
|
|
|
@@ -2638,7 +2750,7 @@ var ChronicleMetricsIngester = class {
|
|
|
2638
2750
|
const journalPath = path7.join(this.directory, CHRONICLE_SQLITE_FILE);
|
|
2639
2751
|
let source = null;
|
|
2640
2752
|
try {
|
|
2641
|
-
source = new (
|
|
2753
|
+
source = new (loadDatabaseSync())(journalPath, { readOnly: true });
|
|
2642
2754
|
} catch {
|
|
2643
2755
|
}
|
|
2644
2756
|
try {
|
|
@@ -2731,7 +2843,7 @@ var ChronicleMetricsIngester = class {
|
|
|
2731
2843
|
}
|
|
2732
2844
|
rebuildFromSqliteJournal(source, result) {
|
|
2733
2845
|
this.db.exec(
|
|
2734
|
-
"DELETE FROM ingest_state; DELETE FROM provider_daily; DELETE FROM task_outcomes; DELETE FROM file_lineage; DELETE FROM token_cost; DELETE FROM daily_counters; DELETE FROM family_daily; DELETE FROM agent_daily; DELETE FROM logical_request_daily; DELETE FROM file_seen_daily;"
|
|
2846
|
+
"DELETE FROM ingest_state; DELETE FROM provider_daily; DELETE FROM task_outcomes; DELETE FROM file_lineage; DELETE FROM token_cost; DELETE FROM daily_counters; DELETE FROM family_daily; DELETE FROM agent_daily; DELETE FROM logical_request_daily; DELETE FROM file_seen_daily; DELETE FROM tool_daily;"
|
|
2735
2847
|
);
|
|
2736
2848
|
this.ingestSqliteJournal(source, /* @__PURE__ */ new Map(), result, true);
|
|
2737
2849
|
this.ensureRebuildMarker();
|
|
@@ -2867,7 +2979,7 @@ var ChronicleMetricsIngester = class {
|
|
|
2867
2979
|
const type = event.eventType;
|
|
2868
2980
|
if (type.startsWith("provider.attempt.") || type === "provider.fallback") {
|
|
2869
2981
|
this.ingestProvider(event);
|
|
2870
|
-
} else if (type === "token.accounted") {
|
|
2982
|
+
} else if (type === "token.accounted" || type === "subagent.token_accounted") {
|
|
2871
2983
|
this.ingestTokenCost(event);
|
|
2872
2984
|
} else if (/^(?:sdd|subagent|kanban)\.task[._]/.test(type)) {
|
|
2873
2985
|
this.ingestTask(event);
|
|
@@ -2903,17 +3015,29 @@ var ChronicleMetricsIngester = class {
|
|
|
2903
3015
|
const type = event.eventType;
|
|
2904
3016
|
if (type === "decision.requested") bump("decisions = decisions + 1");
|
|
2905
3017
|
else if (type === "decision.escalated") bump("escalations = escalations + 1");
|
|
2906
|
-
else if (type === "tool.started")
|
|
2907
|
-
|
|
2908
|
-
|
|
3018
|
+
else if (type === "tool.started") {
|
|
3019
|
+
bump("tool_calls = tool_calls + 1");
|
|
3020
|
+
this.ingestToolDaily(event, day, "invocation", 0);
|
|
3021
|
+
} else if (type === "tool.executed") {
|
|
3022
|
+
const dur = durationMs(event);
|
|
3023
|
+
const durationCount = dur > 0 ? 1 : 0;
|
|
3024
|
+
bump(
|
|
3025
|
+
"completed_tools = completed_tools + 1, tool_duration_ms_total = tool_duration_ms_total + ?, tool_duration_ms_max = MAX(tool_duration_ms_max, ?), tool_duration_count = tool_duration_count + ?",
|
|
3026
|
+
dur,
|
|
3027
|
+
dur,
|
|
3028
|
+
durationCount
|
|
3029
|
+
);
|
|
3030
|
+
this.ingestToolDaily(event, day, "invocation", dur);
|
|
3031
|
+
} else if (type === "tool.failed") {
|
|
3032
|
+
const dur = durationMs(event);
|
|
2909
3033
|
const durationCount = dur > 0 ? 1 : 0;
|
|
2910
3034
|
bump(
|
|
2911
|
-
|
|
2912
|
-
tool_duration_ms_total = tool_duration_ms_total + ?, tool_duration_ms_max = MAX(tool_duration_ms_max, ?), tool_duration_count = tool_duration_count + ?`,
|
|
3035
|
+
"failed_tools = failed_tools + 1, tool_duration_ms_total = tool_duration_ms_total + ?, tool_duration_ms_max = MAX(tool_duration_ms_max, ?), tool_duration_count = tool_duration_count + ?",
|
|
2913
3036
|
dur,
|
|
2914
3037
|
dur,
|
|
2915
3038
|
durationCount
|
|
2916
3039
|
);
|
|
3040
|
+
this.ingestToolDaily(event, day, "failure", dur);
|
|
2917
3041
|
} else if (type === "process.started") bump("processes = processes + 1");
|
|
2918
3042
|
else if (type === "process.completed" && event.outcome === "failure")
|
|
2919
3043
|
bump("failed_processes = failed_processes + 1");
|
|
@@ -2927,10 +3051,41 @@ var ChronicleMetricsIngester = class {
|
|
|
2927
3051
|
}
|
|
2928
3052
|
}
|
|
2929
3053
|
}
|
|
3054
|
+
/**
|
|
3055
|
+
* Per-tool fold used by the auto-thinning pipeline. Distinct from
|
|
3056
|
+
* `daily_counters` (which is name-agnostic): keyed by `(day, tool_name)`
|
|
3057
|
+
* so `underusedTools()` can pick candidates without scanning the journal.
|
|
3058
|
+
*
|
|
3059
|
+
* `kind` selects which counter increments:
|
|
3060
|
+
* - `invocation` — `tool.started` and `tool.executed` (success)
|
|
3061
|
+
* - `failure` — `tool.failed` and `tool.executed` with `!ok`
|
|
3062
|
+
*
|
|
3063
|
+
* `lastInvokedAt` is the event's wall-clock at fold time, not the tool's
|
|
3064
|
+
* internal duration; the auto-thinning policy uses it to compute
|
|
3065
|
+
* "days since last use" relative to the request's anchor day.
|
|
3066
|
+
*/
|
|
3067
|
+
ingestToolDaily(event, day, kind, durationMs3) {
|
|
3068
|
+
const toolName = stringAt(event.attributes ?? {}, "toolName");
|
|
3069
|
+
if (!toolName) return;
|
|
3070
|
+
const occurredAtMs = Date.parse(event.occurredAt ?? event.observedAt);
|
|
3071
|
+
const lastInvokedAt = Number.isFinite(occurredAtMs) ? occurredAtMs : Date.now();
|
|
3072
|
+
this.stmt("INSERT OR IGNORE INTO tool_daily (day, tool_name) VALUES (?, ?)").run(day, toolName);
|
|
3073
|
+
const invocations = kind === "invocation" ? 1 : 0;
|
|
3074
|
+
const failures = kind === "failure" ? 1 : 0;
|
|
3075
|
+
this.stmt(
|
|
3076
|
+
`UPDATE tool_daily
|
|
3077
|
+
SET invocations = invocations + ?,
|
|
3078
|
+
failures = failures + ?,
|
|
3079
|
+
duration_ms_total = duration_ms_total + ?,
|
|
3080
|
+
duration_ms_max = MAX(duration_ms_max, ?),
|
|
3081
|
+
last_invoked_at = MAX(COALESCE(last_invoked_at, 0), ?)
|
|
3082
|
+
WHERE day = ? AND tool_name = ?`
|
|
3083
|
+
).run(invocations, failures, durationMs3, durationMs3, lastInvokedAt, day, toolName);
|
|
3084
|
+
}
|
|
2930
3085
|
ingestProvider(event) {
|
|
2931
3086
|
const day = eventDay(event);
|
|
2932
|
-
const providerId = event.runtime?.providerId ?? asString(
|
|
2933
|
-
const modelId = event.runtime?.modelId ?? asString(
|
|
3087
|
+
const providerId = event.runtime?.providerId ?? asString(readPath(event.attributes ?? {}, "from.providerId")) ?? "";
|
|
3088
|
+
const modelId = event.runtime?.modelId ?? asString(readPath(event.attributes ?? {}, "from.model")) ?? "";
|
|
2934
3089
|
if (!providerId && !modelId) return;
|
|
2935
3090
|
this.stmt(
|
|
2936
3091
|
"INSERT OR IGNORE INTO provider_daily (day, provider_id, model_id) VALUES (?, ?, ?)"
|
|
@@ -2938,7 +3093,7 @@ var ChronicleMetricsIngester = class {
|
|
|
2938
3093
|
const update = (sql, ...params) => this.stmt(
|
|
2939
3094
|
`UPDATE provider_daily SET ${sql} WHERE day = ? AND provider_id = ? AND model_id = ?`
|
|
2940
3095
|
).run(...params, day, providerId, modelId);
|
|
2941
|
-
const duration =
|
|
3096
|
+
const duration = durationMs(event);
|
|
2942
3097
|
switch (event.eventType) {
|
|
2943
3098
|
case "provider.attempt.started":
|
|
2944
3099
|
update("attempts = attempts + 1");
|
|
@@ -2946,10 +3101,10 @@ var ChronicleMetricsIngester = class {
|
|
|
2946
3101
|
case "provider.attempt.completed":
|
|
2947
3102
|
update(
|
|
2948
3103
|
"completed = completed + 1, input_tokens = input_tokens + ?, output_tokens = output_tokens + ?, cache_read_tokens = cache_read_tokens + ?, cache_write_tokens = cache_write_tokens + ?, duration_ms_total = duration_ms_total + ?, duration_ms_max = MAX(duration_ms_max, ?), duration_count = duration_count + ?",
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
3104
|
+
numberAt(event, "usage.input"),
|
|
3105
|
+
numberAt(event, "usage.output"),
|
|
3106
|
+
numberAt(event, "usage.cacheRead"),
|
|
3107
|
+
numberAt(event, "usage.cacheWrite"),
|
|
2953
3108
|
duration,
|
|
2954
3109
|
duration,
|
|
2955
3110
|
duration > 0 ? 1 : 0
|
|
@@ -2972,18 +3127,47 @@ var ChronicleMetricsIngester = class {
|
|
|
2972
3127
|
}
|
|
2973
3128
|
}
|
|
2974
3129
|
ingestTokenCost(event) {
|
|
2975
|
-
const
|
|
2976
|
-
|
|
3130
|
+
const attributes = event.attributes ?? {};
|
|
3131
|
+
const cost = readPath(attributes, "cost.total");
|
|
3132
|
+
const usage = {
|
|
3133
|
+
input: numberAt(event, "usage.input"),
|
|
3134
|
+
output: numberAt(event, "usage.output"),
|
|
3135
|
+
cacheRead: numberAt(event, "usage.cacheRead"),
|
|
3136
|
+
cacheWrite: numberAt(event, "usage.cacheWrite")
|
|
3137
|
+
};
|
|
3138
|
+
const finiteCost = typeof cost === "number" && Number.isFinite(cost) ? cost : void 0;
|
|
3139
|
+
const anyTokens = usage.input > 0 || usage.output > 0 || usage.cacheRead > 0 || usage.cacheWrite > 0;
|
|
3140
|
+
if (finiteCost === void 0 && !anyTokens) return;
|
|
2977
3141
|
const scopeKey2 = `${event.scope.projectId ?? ""}\0${event.scope.sessionId ?? ""}\0${event.scope.agentId ?? ""}`;
|
|
2978
3142
|
const occurredAt = event.occurredAt ?? event.observedAt;
|
|
2979
3143
|
this.stmt(
|
|
2980
|
-
`INSERT INTO token_cost (
|
|
3144
|
+
`INSERT INTO token_cost (
|
|
3145
|
+
scope_key, day, occurred_at, sequence, cost,
|
|
3146
|
+
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
3147
|
+
provider, model
|
|
3148
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
2981
3149
|
ON CONFLICT(scope_key) DO UPDATE SET
|
|
2982
3150
|
day = excluded.day, occurred_at = excluded.occurred_at,
|
|
2983
|
-
sequence = excluded.sequence, cost = excluded.cost
|
|
3151
|
+
sequence = excluded.sequence, cost = excluded.cost,
|
|
3152
|
+
input_tokens = excluded.input_tokens, output_tokens = excluded.output_tokens,
|
|
3153
|
+
cache_read_tokens = excluded.cache_read_tokens,
|
|
3154
|
+
cache_write_tokens = excluded.cache_write_tokens,
|
|
3155
|
+
provider = excluded.provider, model = excluded.model
|
|
2984
3156
|
WHERE excluded.occurred_at > token_cost.occurred_at
|
|
2985
3157
|
OR (excluded.occurred_at = token_cost.occurred_at AND excluded.sequence > token_cost.sequence)`
|
|
2986
|
-
).run(
|
|
3158
|
+
).run(
|
|
3159
|
+
scopeKey2,
|
|
3160
|
+
eventDay(event),
|
|
3161
|
+
occurredAt,
|
|
3162
|
+
event.sequence,
|
|
3163
|
+
finiteCost ?? 0,
|
|
3164
|
+
usage.input,
|
|
3165
|
+
usage.output,
|
|
3166
|
+
usage.cacheRead,
|
|
3167
|
+
usage.cacheWrite,
|
|
3168
|
+
event.runtime?.providerId ?? stringAt(attributes, "provider") ?? "",
|
|
3169
|
+
event.runtime?.modelId ?? stringAt(attributes, "model") ?? ""
|
|
3170
|
+
);
|
|
2987
3171
|
}
|
|
2988
3172
|
ingestTask(event) {
|
|
2989
3173
|
const attributes = event.attributes ?? {};
|
|
@@ -3079,9 +3263,11 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
|
|
|
3079
3263
|
constructor(directory) {
|
|
3080
3264
|
this.directory = path8.resolve(directory);
|
|
3081
3265
|
this.dbPath = path8.join(this.directory, "metrics.db");
|
|
3082
|
-
const Database =
|
|
3266
|
+
const Database = loadDatabaseSync();
|
|
3083
3267
|
this.db = new Database(this.dbPath);
|
|
3084
3268
|
this.db.exec("PRAGMA journal_mode = WAL");
|
|
3269
|
+
this.db.exec("PRAGMA synchronous = NORMAL");
|
|
3270
|
+
this.db.exec("PRAGMA busy_timeout = 5000");
|
|
3085
3271
|
ensureMetricsSchema(this.db);
|
|
3086
3272
|
this.ingester = new ChronicleMetricsIngester(this.db, this.directory, this.dbPath);
|
|
3087
3273
|
}
|
|
@@ -3251,6 +3437,55 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
|
|
|
3251
3437
|
estimatedCostUsd: Number(cost.c)
|
|
3252
3438
|
};
|
|
3253
3439
|
}
|
|
3440
|
+
/**
|
|
3441
|
+
* Per-tool candidates for the auto-thinning pipeline. Returns one row per
|
|
3442
|
+
* tool that has at least one day in `[fromDay, toDay]` (default: last 30
|
|
3443
|
+
* days), with `invocations` summed across the window and `lastInvokedAt`
|
|
3444
|
+
* taken as the max. The caller is responsible for the "underused" filter
|
|
3445
|
+
* (`invocations <= maxInvocations`, `lastInvokedAt` older than
|
|
3446
|
+
* `toDay - idleDays`) and for excluding tools still active in the window.
|
|
3447
|
+
*
|
|
3448
|
+
* The query intentionally does NOT pre-filter by threshold — the policy
|
|
3449
|
+
* layer owns that decision so the same data feeds both the dry-run
|
|
3450
|
+
* (`/tool autothin candidates`) and the apply path.
|
|
3451
|
+
*/
|
|
3452
|
+
underusedTools(options = {}) {
|
|
3453
|
+
const fromDay = options.from?.slice(0, 10);
|
|
3454
|
+
const toDay = options.to?.slice(0, 10);
|
|
3455
|
+
const clauses = [];
|
|
3456
|
+
const params = [];
|
|
3457
|
+
if (fromDay) {
|
|
3458
|
+
clauses.push("day >= ?");
|
|
3459
|
+
params.push(fromDay);
|
|
3460
|
+
}
|
|
3461
|
+
if (toDay) {
|
|
3462
|
+
clauses.push("day <= ?");
|
|
3463
|
+
params.push(toDay);
|
|
3464
|
+
}
|
|
3465
|
+
const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
3466
|
+
params.push(clampLimit(options.limit, 500));
|
|
3467
|
+
const rows = this.db.prepare(
|
|
3468
|
+
`SELECT tool_name, SUM(invocations) invocations, SUM(failures) failures,
|
|
3469
|
+
SUM(duration_ms_total) duration_total, MAX(last_invoked_at) last_invoked
|
|
3470
|
+
FROM tool_daily${where}
|
|
3471
|
+
GROUP BY tool_name
|
|
3472
|
+
ORDER BY invocations ASC, tool_name ASC
|
|
3473
|
+
LIMIT ?`
|
|
3474
|
+
).all(...params);
|
|
3475
|
+
const anchorMs = Date.now();
|
|
3476
|
+
return rows.map((row) => {
|
|
3477
|
+
const lastInvokedAt = row.last_invoked === null ? null : Number(row.last_invoked);
|
|
3478
|
+
const daysSinceLastUse = lastInvokedAt === null ? null : Math.max(0, Math.floor((anchorMs - lastInvokedAt) / 864e5));
|
|
3479
|
+
return {
|
|
3480
|
+
toolName: String(row.tool_name),
|
|
3481
|
+
invocations: Number(row.invocations),
|
|
3482
|
+
failures: Number(row.failures),
|
|
3483
|
+
durationMsTotal: Number(row.duration_total),
|
|
3484
|
+
lastInvokedAt,
|
|
3485
|
+
daysSinceLastUse
|
|
3486
|
+
};
|
|
3487
|
+
});
|
|
3488
|
+
}
|
|
3254
3489
|
/**
|
|
3255
3490
|
* A `ChronicleSummary` for the default/unfiltered dashboard view — only
|
|
3256
3491
|
* `from`/`to` (day-precision) narrow it.
|
|
@@ -3461,15 +3696,6 @@ async function importLegacyChronicleJournal(journal, directory) {
|
|
|
3461
3696
|
};
|
|
3462
3697
|
}
|
|
3463
3698
|
|
|
3464
|
-
// src/chronicle/project-server-protocol.ts
|
|
3465
|
-
var CHRONICLE_PROJECT_SERVER_PROTOCOL_VERSION = 2;
|
|
3466
|
-
var CHRONICLE_PROJECT_SERVER_MAX_FRAME_CHARS = 64 * 1024 * 1024;
|
|
3467
|
-
var CHRONICLE_MAX_APPEND_BATCH = 1e4;
|
|
3468
|
-
function encodeChronicleProjectServerMessage(message) {
|
|
3469
|
-
return `${JSON.stringify(message)}
|
|
3470
|
-
`;
|
|
3471
|
-
}
|
|
3472
|
-
|
|
3473
3699
|
// src/chronicle/project-server-endpoint.ts
|
|
3474
3700
|
import { createHash as createHash4 } from "node:crypto";
|
|
3475
3701
|
import * as os2 from "node:os";
|
|
@@ -3499,24 +3725,24 @@ function chronicleProjectServerMetadataPath(projectDir) {
|
|
|
3499
3725
|
|
|
3500
3726
|
export {
|
|
3501
3727
|
resolveChronicleRuntimeLocation,
|
|
3728
|
+
CHRONICLE_PROJECT_SERVER_PROTOCOL_VERSION,
|
|
3729
|
+
CHRONICLE_PROJECT_SERVER_MAX_FRAME_CHARS,
|
|
3730
|
+
CHRONICLE_MAX_APPEND_BATCH,
|
|
3731
|
+
encodeChronicleProjectServerMessage,
|
|
3502
3732
|
GENESIS_HASH,
|
|
3503
3733
|
CHRONICLE_SCHEMA_VERSION,
|
|
3504
3734
|
ChronicleJournal,
|
|
3735
|
+
isChronicleMetricsAvailable,
|
|
3505
3736
|
ChroniclePartitionRangeCache,
|
|
3506
3737
|
CHRONICLE_FACET_FIELDS,
|
|
3507
3738
|
ChronicleQueryEngine,
|
|
3508
3739
|
findChroniclePartitions,
|
|
3509
3740
|
ChronicleStorageQuotaError,
|
|
3510
3741
|
ChronicleSqliteJournal,
|
|
3511
|
-
isChronicleMetricsAvailable,
|
|
3512
3742
|
ChronicleMetricsStore,
|
|
3513
3743
|
importLegacyChronicleJournal,
|
|
3514
|
-
CHRONICLE_PROJECT_SERVER_PROTOCOL_VERSION,
|
|
3515
|
-
CHRONICLE_PROJECT_SERVER_MAX_FRAME_CHARS,
|
|
3516
|
-
CHRONICLE_MAX_APPEND_BATCH,
|
|
3517
|
-
encodeChronicleProjectServerMessage,
|
|
3518
3744
|
chronicleProjectServerKey,
|
|
3519
3745
|
chronicleProjectServerEndpoint,
|
|
3520
3746
|
chronicleProjectServerMetadataPath
|
|
3521
3747
|
};
|
|
3522
|
-
//# sourceMappingURL=chunk-
|
|
3748
|
+
//# sourceMappingURL=chunk-4BMVPOHO.js.map
|