@wrongstack/core 0.309.1 → 0.310.1
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 +113 -41
- package/dist/chronicle/metrics-ingest.d.ts +7 -0
- package/dist/chronicle/metrics-schema.d.ts +4 -1
- package/dist/chronicle/project-server.js +94 -38
- package/dist/chronicle/query.d.ts +1 -0
- package/dist/chronicle/sqlite-journal-schema.d.ts +2 -1
- package/dist/chronicle/types.d.ts +2 -0
- package/dist/{agent-status-helpers.d.ts → coordination/agent-status-helpers.d.ts} +1 -1
- package/dist/{agent-status-tracker.d.ts → coordination/agent-status-tracker.d.ts} +2 -2
- package/dist/{middleware → coordination}/collab-pause.d.ts +1 -1
- package/dist/coordination/director-kanban-queue-helpers.d.ts +1 -1
- package/dist/coordination/fleet-status-tool.d.ts +1 -1
- package/dist/coordination/index.d.ts +5 -1
- package/dist/coordination/index.js +2061 -346
- package/dist/coordination/kanban-dispatch-port.d.ts +30 -0
- package/dist/coordination/kanban-ops-port.d.ts +21 -0
- package/dist/coordination/mailbox-hooks.d.ts +1 -1
- package/dist/coordination/mailbox-project-server.js +14 -9
- package/dist/core/context.d.ts +35 -44
- package/dist/core/conversation-state.d.ts +16 -52
- package/dist/core/index.js +53 -16
- package/dist/core/provider-runner.d.ts +2 -2
- package/dist/core/run-env.d.ts +7 -28
- package/dist/core/streaming-response-builder.d.ts +2 -2
- package/dist/execution/index.js +111 -153
- package/dist/goal/index.js +100 -22
- package/dist/hq/auth-store.d.ts +9 -0
- package/dist/hq/cost-bridge.d.ts +1 -1
- package/dist/hq/index.js +24 -2
- package/dist/index.d.ts +12 -5
- package/dist/index.js +27808 -33937
- package/dist/infrastructure/index.js +210 -132
- package/dist/infrastructure/provider-cache-ledger.d.ts +1 -1
- package/dist/infrastructure/token-counter.d.ts +5 -1
- package/dist/kernel/events/file-events.d.ts +6 -0
- package/dist/kernel/events/provider-events.d.ts +10 -7
- package/dist/kernel/events/session-events.d.ts +4 -4
- package/dist/kernel/events/tool-events.d.ts +12 -2
- package/dist/plugin/index.js +105 -35
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.js +47 -18
- package/dist/security/kanban-boundary.d.ts +1 -1
- package/dist/security/kanban-governance-port.d.ts +28 -0
- package/dist/session-catalog/index.js +2 -3
- package/dist/session-catalog/project-server.js +2 -3
- package/dist/session-catalog/protocol.d.ts +1 -1
- package/dist/session-catalog/registry.d.ts +1 -1
- package/dist/session-catalog/store-schema.d.ts +1 -1
- package/dist/session-catalog/store.d.ts +1 -1
- package/dist/storage/annotations-store.d.ts +1 -1
- package/dist/storage/board-store-port.d.ts +45 -0
- package/dist/storage/completed-work-checkpoint.d.ts +1 -1
- package/dist/storage/config-loader/types.d.ts +1 -1
- package/dist/storage/event-bus-port.d.ts +27 -0
- package/dist/storage/file-session-writer.d.ts +47 -5
- package/dist/storage/goal-coordination.d.ts +1 -1
- package/dist/storage/goal-store.d.ts +1 -1
- package/dist/storage/index.d.ts +3 -4
- package/dist/storage/index.js +1063 -1459
- package/dist/storage/plan-store.d.ts +1 -1
- package/dist/storage/queue-store.d.ts +1 -1
- package/dist/storage/replay-log-store.d.ts +1 -1
- package/dist/storage/session-recovery.d.ts +10 -0
- package/dist/storage/session-resume-validation.d.ts +13 -1
- package/dist/storage/session-store/events.d.ts +1 -1
- package/dist/storage/session-store/load-session-data.d.ts +1 -1
- package/dist/storage/session-store/rename-session.d.ts +1 -1
- package/dist/storage/session-store/resume-session.d.ts +3 -1
- package/dist/storage/session-store/session-store-index.d.ts +2 -1
- package/dist/storage/session-store/types.d.ts +1 -1
- package/dist/storage/session-store.d.ts +70 -0
- package/dist/storage/session-summary-tracker.d.ts +8 -0
- package/dist/storage/session-write-buffer.d.ts +31 -2
- package/dist/storage/task-store.d.ts +1 -1
- package/dist/storage/todos-checkpoint.d.ts +1 -1
- package/dist/storage/tool-audit-log.d.ts +1 -1
- package/dist/tasking/index.js +100 -22
- package/dist/tasking/task-tracker.d.ts +24 -1
- package/dist/types/compactor.d.ts +2 -2
- package/dist/types/config/runtime.d.ts +7 -0
- package/dist/types/config/tools.d.ts +30 -0
- package/dist/types/context.d.ts +212 -0
- package/dist/types/conversation-state.d.ts +109 -0
- package/dist/types/error-handler.d.ts +2 -2
- package/dist/types/file-event-record.d.ts +6 -0
- package/dist/types/index.d.ts +4 -4
- package/dist/types/index.js +19 -1
- package/dist/types/permission.d.ts +3 -3
- package/dist/types/plugin.d.ts +3 -3
- package/dist/types/provider-runner.d.ts +2 -2
- package/dist/types/provider.d.ts +10 -0
- package/dist/types/run-env.d.ts +32 -0
- package/dist/types/session.d.ts +3 -0
- package/dist/types/slash-command.d.ts +2 -2
- package/dist/types/token-counter.d.ts +30 -1
- package/dist/types/tool-executor.d.ts +2 -2
- package/dist/types/tool.d.ts +5 -5
- package/dist/utils/context-breakdown.d.ts +2 -2
- package/dist/utils/context-evidence.d.ts +12 -12
- package/dist/utils/crash-shield.d.ts +9 -0
- package/dist/utils/heap-watchdog.js +11 -3
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +72 -156
- package/dist/utils/regex-guard.d.ts +7 -30
- package/dist/utils/todos-format.d.ts +1 -1
- package/dist/utils/tree-kill.d.ts +2 -0
- package/dist/utils/tree-kill.js +1 -0
- package/dist/wiring/proxy-rewrite.d.ts +76 -0
- package/dist/wiring/proxy-rewrite.js +70 -0
- package/instructions/coordination/subagent-baseline.md +10 -0
- package/instructions/system-lite.md +2 -0
- package/instructions/system-pro.md +40 -0
- package/instructions/system.md +15 -0
- package/package.json +10 -9
- package/dist/defaults/index.d.ts +0 -69
- package/dist/defaults/index.js +0 -38133
- /package/dist/{fleet-notifier.d.ts → coordination/fleet-notifier.d.ts} +0 -0
- /package/dist/{session-registry-atomic-file.d.ts → session-catalog/session-registry-atomic-file.d.ts} +0 -0
- /package/dist/{session-registry-types.d.ts → session-catalog/session-registry-types.d.ts} +0 -0
- /package/dist/{session-registry.d.ts → session-catalog/session-registry.d.ts} +0 -0
package/dist/chronicle/index.js
CHANGED
|
@@ -2047,7 +2047,11 @@ function relationKeys(event) {
|
|
|
2047
2047
|
add("attempt", event.correlation.attemptId, "explicit");
|
|
2048
2048
|
add("decision", event.attributes?.decisionId, "explicit");
|
|
2049
2049
|
add("network_request", event.attributes?.requestId, "explicit");
|
|
2050
|
-
add(
|
|
2050
|
+
add(
|
|
2051
|
+
"prompt_manifest",
|
|
2052
|
+
event.correlation.promptManifestId ?? event.attributes?.promptManifest?.manifestId,
|
|
2053
|
+
"explicit"
|
|
2054
|
+
);
|
|
2051
2055
|
add("resource_lineage", event.resource?.id, "inferred");
|
|
2052
2056
|
if (event.eventType === "metrics.rollup" && event.attributes?.signal === "tool.resource.observed") {
|
|
2053
2057
|
const resources = event.attributes.resources;
|
|
@@ -2069,6 +2073,7 @@ function matches(event, query) {
|
|
|
2069
2073
|
if (!equal(query.agentId, event.scope.agentId) || !equal(query.taskId, event.scope.taskId)) return false;
|
|
2070
2074
|
if (!equal(query.providerId, event.runtime?.providerId) || !equal(query.modelId, event.runtime?.modelId)) return false;
|
|
2071
2075
|
if (!equal(query.traceId, event.correlation.traceId) || !equal(query.logicalRequestId, event.correlation.logicalRequestId)) return false;
|
|
2076
|
+
if (!equal(query.promptManifestId, event.correlation.promptManifestId)) return false;
|
|
2072
2077
|
if (!equal(query.attemptId, event.correlation.attemptId) || !equal(query.toolCallId, event.correlation.toolCallId)) return false;
|
|
2073
2078
|
if (!equal(query.resourceKind, event.resource?.kind) || !equal(query.resourceId, event.resource?.id)) return false;
|
|
2074
2079
|
if (query.path && normalize2(event.resource?.path) !== normalize2(query.path)) return false;
|
|
@@ -2209,6 +2214,7 @@ function isChronicleEvent(value) {
|
|
|
2209
2214
|
]) && typeof value.correlation.traceId === "string" && typeof value.correlation.spanId === "string" && optionalStrings(value.correlation, [
|
|
2210
2215
|
"parentSpanId",
|
|
2211
2216
|
"logicalRequestId",
|
|
2217
|
+
"promptManifestId",
|
|
2212
2218
|
"attemptId",
|
|
2213
2219
|
"toolCallId"
|
|
2214
2220
|
]) && isRuntime(value.runtime) && isResource(value.resource) && (value.attributes === void 0 || isRecord(value.attributes)) && (value.tags === void 0 || isStringRecord(value.tags));
|
|
@@ -2398,7 +2404,7 @@ var ChronicleQuotaManager = class {
|
|
|
2398
2404
|
};
|
|
2399
2405
|
|
|
2400
2406
|
// src/chronicle/sqlite-journal-schema.ts
|
|
2401
|
-
import {
|
|
2407
|
+
import { loadRuntimeDatabaseSync } from "@wrongstack/persistence";
|
|
2402
2408
|
|
|
2403
2409
|
// src/utils/pid.ts
|
|
2404
2410
|
function isPidAlive(pid) {
|
|
@@ -2442,20 +2448,18 @@ var CHRONICLE_SQLITE_FILE = "chronicle.sqlite";
|
|
|
2442
2448
|
var LEGACY_JSONL_MIGRATION_KEY = "legacy-jsonl-v1";
|
|
2443
2449
|
var LEGACY_JSONL_QUARANTINE_KEY = "legacy-jsonl-v1:quarantine";
|
|
2444
2450
|
var LEGACY_JSONL_BOUNDARY_KEY = "legacy-jsonl-v1:boundary";
|
|
2445
|
-
var SCHEMA_VERSION =
|
|
2451
|
+
var SCHEMA_VERSION = 3;
|
|
2446
2452
|
var Ctor;
|
|
2447
2453
|
function loadDatabaseSync() {
|
|
2448
2454
|
if (Ctor) return Ctor;
|
|
2449
|
-
if (Ctor === null) throw new Error("
|
|
2455
|
+
if (Ctor === null) throw new Error("SQLite is unavailable in this runtime");
|
|
2450
2456
|
try {
|
|
2451
|
-
Ctor = withSqliteExperimentalWarningSuppressed(
|
|
2452
|
-
() => createRequire(import.meta.url)("node:sqlite").DatabaseSync
|
|
2453
|
-
);
|
|
2457
|
+
Ctor = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync);
|
|
2454
2458
|
return Ctor;
|
|
2455
2459
|
} catch (error) {
|
|
2456
2460
|
Ctor = null;
|
|
2457
2461
|
throw new Error(
|
|
2458
|
-
"The Chronicle journal needs
|
|
2462
|
+
"The Chronicle journal needs node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
|
|
2459
2463
|
);
|
|
2460
2464
|
}
|
|
2461
2465
|
}
|
|
@@ -2470,6 +2474,7 @@ function projectEvent(event) {
|
|
|
2470
2474
|
taskId: event.scope.taskId ?? null,
|
|
2471
2475
|
traceId: event.correlation?.traceId ?? null,
|
|
2472
2476
|
logicalRequestId: event.correlation?.logicalRequestId ?? null,
|
|
2477
|
+
promptManifestId: event.correlation?.promptManifestId ?? null,
|
|
2473
2478
|
resourceKind: event.resource?.kind ?? null,
|
|
2474
2479
|
resourceId: event.resource?.id ?? null,
|
|
2475
2480
|
resourcePath: event.resource?.path ?? null,
|
|
@@ -2494,6 +2499,7 @@ function ensureChronicleSchema(db) {
|
|
|
2494
2499
|
task_id TEXT,
|
|
2495
2500
|
trace_id TEXT,
|
|
2496
2501
|
logical_request_id TEXT,
|
|
2502
|
+
prompt_manifest_id TEXT,
|
|
2497
2503
|
resource_kind TEXT,
|
|
2498
2504
|
resource_id TEXT,
|
|
2499
2505
|
resource_path TEXT,
|
|
@@ -2521,6 +2527,10 @@ function ensureChronicleSchema(db) {
|
|
|
2521
2527
|
if (version < 2) {
|
|
2522
2528
|
db.exec("DROP INDEX IF EXISTS events_resource_path");
|
|
2523
2529
|
}
|
|
2530
|
+
if (version > 0 && version < 3) {
|
|
2531
|
+
db.exec("ALTER TABLE events ADD COLUMN prompt_manifest_id TEXT");
|
|
2532
|
+
}
|
|
2533
|
+
db.exec("CREATE INDEX IF NOT EXISTS events_prompt_manifest ON events(prompt_manifest_id)");
|
|
2524
2534
|
if (version !== SCHEMA_VERSION) {
|
|
2525
2535
|
db.exec(`PRAGMA user_version = ${SCHEMA_VERSION}`);
|
|
2526
2536
|
}
|
|
@@ -2557,6 +2567,7 @@ function pushDown(query) {
|
|
|
2557
2567
|
eq("task_id", query.taskId);
|
|
2558
2568
|
eq("trace_id", query.traceId);
|
|
2559
2569
|
eq("logical_request_id", query.logicalRequestId);
|
|
2570
|
+
eq("prompt_manifest_id", query.promptManifestId);
|
|
2560
2571
|
eq("resource_kind", query.resourceKind);
|
|
2561
2572
|
eq("resource_id", query.resourceId);
|
|
2562
2573
|
if (query.eventTypes?.length) {
|
|
@@ -2913,6 +2924,7 @@ var ChronicleSqliteJournal = class {
|
|
|
2913
2924
|
row.taskId,
|
|
2914
2925
|
row.traceId,
|
|
2915
2926
|
row.logicalRequestId,
|
|
2927
|
+
row.promptManifestId,
|
|
2916
2928
|
row.resourceKind,
|
|
2917
2929
|
row.resourceId,
|
|
2918
2930
|
row.resourcePath,
|
|
@@ -3072,9 +3084,9 @@ var ChronicleSqliteJournal = class {
|
|
|
3072
3084
|
const insert = this.db.prepare(
|
|
3073
3085
|
`INSERT INTO events (
|
|
3074
3086
|
day, sequence, event_id, hash, previous_hash, occurred_at, event_type, outcome,
|
|
3075
|
-
project_id, session_id, agent_id, task_id, trace_id, logical_request_id,
|
|
3087
|
+
project_id, session_id, agent_id, task_id, trace_id, logical_request_id, prompt_manifest_id,
|
|
3076
3088
|
resource_kind, resource_id, resource_path, duration_ns, payload
|
|
3077
|
-
) VALUES (
|
|
3089
|
+
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
|
3078
3090
|
);
|
|
3079
3091
|
const checkpoint = this.db.prepare(
|
|
3080
3092
|
`INSERT INTO chain_checkpoint (day, sequence, hash) VALUES (?, ?, ?)
|
|
@@ -3103,6 +3115,7 @@ var ChronicleSqliteJournal = class {
|
|
|
3103
3115
|
row.taskId,
|
|
3104
3116
|
row.traceId,
|
|
3105
3117
|
row.logicalRequestId,
|
|
3118
|
+
row.promptManifestId,
|
|
3106
3119
|
row.resourceKind,
|
|
3107
3120
|
row.resourceId,
|
|
3108
3121
|
row.resourcePath,
|
|
@@ -3189,9 +3202,9 @@ var ChronicleSqliteJournal = class {
|
|
|
3189
3202
|
insert: this.db.prepare(
|
|
3190
3203
|
`INSERT INTO events (
|
|
3191
3204
|
day, sequence, event_id, hash, previous_hash, occurred_at, event_type, outcome,
|
|
3192
|
-
project_id, session_id, agent_id, task_id, trace_id, logical_request_id,
|
|
3205
|
+
project_id, session_id, agent_id, task_id, trace_id, logical_request_id, prompt_manifest_id,
|
|
3193
3206
|
resource_kind, resource_id, resource_path, duration_ns, payload
|
|
3194
|
-
) VALUES (
|
|
3207
|
+
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
|
3195
3208
|
),
|
|
3196
3209
|
trimBoundary: this.db.prepare(
|
|
3197
3210
|
"SELECT day, sequence, hash FROM events ORDER BY day, sequence LIMIT 1 OFFSET ?"
|
|
@@ -3232,8 +3245,8 @@ var ChronicleSqliteJournal = class {
|
|
|
3232
3245
|
};
|
|
3233
3246
|
|
|
3234
3247
|
// src/chronicle/metrics-schema.ts
|
|
3235
|
-
import {
|
|
3236
|
-
var SCHEMA_VERSION2 =
|
|
3248
|
+
import { loadRuntimeDatabaseSync as loadRuntimeDatabaseSync2 } from "@wrongstack/persistence";
|
|
3249
|
+
var SCHEMA_VERSION2 = 4;
|
|
3237
3250
|
var READ_CHUNK_BYTES = 1024 * 1024;
|
|
3238
3251
|
var SQLITE_SOURCE_PREFIX = "sqlite:";
|
|
3239
3252
|
var SQLITE_INGEST_BATCH = 2e3;
|
|
@@ -3251,16 +3264,14 @@ var EMPTY_FAMILIES = {
|
|
|
3251
3264
|
var Ctor2;
|
|
3252
3265
|
function loadDatabaseSync2() {
|
|
3253
3266
|
if (Ctor2) return Ctor2;
|
|
3254
|
-
if (Ctor2 === null) throw new Error("
|
|
3267
|
+
if (Ctor2 === null) throw new Error("SQLite is unavailable in this runtime");
|
|
3255
3268
|
try {
|
|
3256
|
-
Ctor2 = withSqliteExperimentalWarningSuppressed(
|
|
3257
|
-
() => createRequire2(import.meta.url)("node:sqlite").DatabaseSync
|
|
3258
|
-
);
|
|
3269
|
+
Ctor2 = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync2);
|
|
3259
3270
|
return Ctor2;
|
|
3260
3271
|
} catch (error) {
|
|
3261
3272
|
Ctor2 = null;
|
|
3262
3273
|
throw new Error(
|
|
3263
|
-
"Chronicle metrics need
|
|
3274
|
+
"Chronicle metrics need node:sqlite (Node >= 22.5) or bun:sqlite: " + (error instanceof Error ? error.message : String(error))
|
|
3264
3275
|
);
|
|
3265
3276
|
}
|
|
3266
3277
|
}
|
|
@@ -3329,6 +3340,9 @@ function ensureMetricsSchema(db) {
|
|
|
3329
3340
|
tool_name TEXT NOT NULL DEFAULT '',
|
|
3330
3341
|
provider_id TEXT NOT NULL DEFAULT '',
|
|
3331
3342
|
model_id TEXT NOT NULL DEFAULT '',
|
|
3343
|
+
logical_request_id TEXT NOT NULL DEFAULT '',
|
|
3344
|
+
prompt_manifest_id TEXT NOT NULL DEFAULT '',
|
|
3345
|
+
provenance_confidence TEXT NOT NULL DEFAULT 'unknown',
|
|
3332
3346
|
source TEXT NOT NULL DEFAULT ''
|
|
3333
3347
|
);
|
|
3334
3348
|
CREATE INDEX IF NOT EXISTS idx_file_lineage_path ON file_lineage(path_key, occurred_at);
|
|
@@ -3421,6 +3435,20 @@ var ChronicleMetricsIngester = class {
|
|
|
3421
3435
|
db;
|
|
3422
3436
|
directory;
|
|
3423
3437
|
dbPath;
|
|
3438
|
+
/**
|
|
3439
|
+
* Prepared-statement cache for the per-event ingest hot paths. Preparing
|
|
3440
|
+
* the same SQL on every event was the dominant ingest cost; node:sqlite
|
|
3441
|
+
* statements are reusable, so each distinct SQL string is prepared once.
|
|
3442
|
+
*/
|
|
3443
|
+
stmtCache = /* @__PURE__ */ new Map();
|
|
3444
|
+
stmt(sql) {
|
|
3445
|
+
let s = this.stmtCache.get(sql);
|
|
3446
|
+
if (!s) {
|
|
3447
|
+
s = this.db.prepare(sql);
|
|
3448
|
+
this.stmtCache.set(sql, s);
|
|
3449
|
+
}
|
|
3450
|
+
return s;
|
|
3451
|
+
}
|
|
3424
3452
|
async refresh() {
|
|
3425
3453
|
const result = {
|
|
3426
3454
|
ingestedEvents: 0,
|
|
@@ -3450,7 +3478,7 @@ var ChronicleMetricsIngester = class {
|
|
|
3450
3478
|
let base;
|
|
3451
3479
|
if (!migrated) {
|
|
3452
3480
|
base = offsets.get(key) ?? 0;
|
|
3453
|
-
} else if (boundary
|
|
3481
|
+
} else if (boundary?.has(key)) {
|
|
3454
3482
|
base = Math.max(offsets.get(key) ?? 0, boundary.get(key));
|
|
3455
3483
|
} else {
|
|
3456
3484
|
base = rebuilt ? 0 : offsets.get(key) ?? 0;
|
|
@@ -3673,11 +3701,11 @@ var ChronicleMetricsIngester = class {
|
|
|
3673
3701
|
}
|
|
3674
3702
|
ingestDailyCounters(event) {
|
|
3675
3703
|
const day = eventDay(event);
|
|
3676
|
-
this.
|
|
3677
|
-
const bump = (sql, ...params) => this.
|
|
3704
|
+
this.stmt("INSERT OR IGNORE INTO daily_counters (day) VALUES (?)").run(day);
|
|
3705
|
+
const bump = (sql, ...params) => this.stmt(`UPDATE daily_counters SET ${sql} WHERE day = ?`).run(...params, day);
|
|
3678
3706
|
const family = signalFamily(event);
|
|
3679
3707
|
const failed = isTerminalFailure(event) ? 1 : 0;
|
|
3680
|
-
this.
|
|
3708
|
+
this.stmt(
|
|
3681
3709
|
`INSERT INTO family_daily (day, family, count, failure_count) VALUES (?, ?, 1, ?)
|
|
3682
3710
|
ON CONFLICT(day, family) DO UPDATE SET count = count + 1, failure_count = failure_count + excluded.failure_count`
|
|
3683
3711
|
).run(day, family, failed);
|
|
@@ -3686,12 +3714,15 @@ var ChronicleMetricsIngester = class {
|
|
|
3686
3714
|
bump("cancellations = cancellations + 1");
|
|
3687
3715
|
if (family === "agent") bump("agent_events = agent_events + 1");
|
|
3688
3716
|
if (event.correlation.logicalRequestId) {
|
|
3689
|
-
this.
|
|
3717
|
+
this.stmt(
|
|
3690
3718
|
"INSERT OR IGNORE INTO logical_request_daily (day, logical_request_id) VALUES (?, ?)"
|
|
3691
3719
|
).run(day, event.correlation.logicalRequestId);
|
|
3692
3720
|
}
|
|
3693
3721
|
if (event.scope.agentId) {
|
|
3694
|
-
this.
|
|
3722
|
+
this.stmt("INSERT OR IGNORE INTO agent_daily (day, agent_id) VALUES (?, ?)").run(
|
|
3723
|
+
day,
|
|
3724
|
+
event.scope.agentId
|
|
3725
|
+
);
|
|
3695
3726
|
}
|
|
3696
3727
|
const type = event.eventType;
|
|
3697
3728
|
if (type === "decision.requested") bump("decisions = decisions + 1");
|
|
@@ -3713,7 +3744,10 @@ var ChronicleMetricsIngester = class {
|
|
|
3713
3744
|
if (event.resource?.kind === "file" || type.startsWith("file.")) {
|
|
3714
3745
|
bump("file_events_all = file_events_all + 1");
|
|
3715
3746
|
if (event.resource?.path) {
|
|
3716
|
-
this.
|
|
3747
|
+
this.stmt("INSERT OR IGNORE INTO file_seen_daily (day, path_key) VALUES (?, ?)").run(
|
|
3748
|
+
day,
|
|
3749
|
+
normalizePathKey(event.resource.path)
|
|
3750
|
+
);
|
|
3717
3751
|
}
|
|
3718
3752
|
}
|
|
3719
3753
|
}
|
|
@@ -3722,8 +3756,10 @@ var ChronicleMetricsIngester = class {
|
|
|
3722
3756
|
const providerId = event.runtime?.providerId ?? asString(readPath2(event.attributes ?? {}, "from.providerId")) ?? "";
|
|
3723
3757
|
const modelId = event.runtime?.modelId ?? asString(readPath2(event.attributes ?? {}, "from.model")) ?? "";
|
|
3724
3758
|
if (!providerId && !modelId) return;
|
|
3725
|
-
this.
|
|
3726
|
-
|
|
3759
|
+
this.stmt(
|
|
3760
|
+
"INSERT OR IGNORE INTO provider_daily (day, provider_id, model_id) VALUES (?, ?, ?)"
|
|
3761
|
+
).run(day, providerId, modelId);
|
|
3762
|
+
const update = (sql, ...params) => this.stmt(
|
|
3727
3763
|
`UPDATE provider_daily SET ${sql} WHERE day = ? AND provider_id = ? AND model_id = ?`
|
|
3728
3764
|
).run(...params, day, providerId, modelId);
|
|
3729
3765
|
const duration = durationMs2(event);
|
|
@@ -3764,7 +3800,7 @@ var ChronicleMetricsIngester = class {
|
|
|
3764
3800
|
if (typeof cost !== "number" || !Number.isFinite(cost)) return;
|
|
3765
3801
|
const scopeKey2 = `${event.scope.projectId ?? ""}\0${event.scope.sessionId ?? ""}\0${event.scope.agentId ?? ""}`;
|
|
3766
3802
|
const occurredAt = event.occurredAt ?? event.observedAt;
|
|
3767
|
-
this.
|
|
3803
|
+
this.stmt(
|
|
3768
3804
|
`INSERT INTO token_cost (scope_key, day, occurred_at, sequence, cost) VALUES (?, ?, ?, ?, ?)
|
|
3769
3805
|
ON CONFLICT(scope_key) DO UPDATE SET
|
|
3770
3806
|
day = excluded.day, occurred_at = excluded.occurred_at,
|
|
@@ -3778,8 +3814,8 @@ var ChronicleMetricsIngester = class {
|
|
|
3778
3814
|
const taskId = event.scope.taskId ?? stringAt(attributes, "taskId");
|
|
3779
3815
|
if (!taskId) return;
|
|
3780
3816
|
const occurredAt = event.occurredAt ?? event.observedAt;
|
|
3781
|
-
this.
|
|
3782
|
-
const set = (sql, ...params) => this.
|
|
3817
|
+
this.stmt("INSERT OR IGNORE INTO task_outcomes (task_id) VALUES (?)").run(taskId);
|
|
3818
|
+
const set = (sql, ...params) => this.stmt(`UPDATE task_outcomes SET ${sql} WHERE task_id = ?`).run(...params, taskId);
|
|
3783
3819
|
const lineage = [
|
|
3784
3820
|
["run_id", stringAt(attributes, "runId")],
|
|
3785
3821
|
["board_id", event.scope.kanbanBoardId ?? stringAt(attributes, "boardId")],
|
|
@@ -3826,11 +3862,12 @@ var ChronicleMetricsIngester = class {
|
|
|
3826
3862
|
if (!operation || operation === "read") return;
|
|
3827
3863
|
const filePath = event.resource?.path ?? stringAt(attributes, "filePath");
|
|
3828
3864
|
if (!filePath) return;
|
|
3829
|
-
this.
|
|
3865
|
+
this.stmt(
|
|
3830
3866
|
`INSERT OR IGNORE INTO file_lineage
|
|
3831
3867
|
(event_id, path, path_key, operation, occurred_at, session_id, agent_id, task_id, board_id, run_id,
|
|
3832
|
-
tool_name, provider_id, model_id,
|
|
3833
|
-
|
|
3868
|
+
tool_name, provider_id, model_id, logical_request_id, prompt_manifest_id,
|
|
3869
|
+
provenance_confidence, source)
|
|
3870
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
3834
3871
|
).run(
|
|
3835
3872
|
event.eventId,
|
|
3836
3873
|
normalizeKey(filePath),
|
|
@@ -3845,10 +3882,17 @@ var ChronicleMetricsIngester = class {
|
|
|
3845
3882
|
stringAt(attributes, "toolName") ?? "",
|
|
3846
3883
|
event.runtime?.providerId ?? stringAt(attributes, "provider") ?? "",
|
|
3847
3884
|
event.runtime?.modelId ?? stringAt(attributes, "model") ?? "",
|
|
3885
|
+
event.correlation.logicalRequestId ?? stringAt(attributes, "logicalRequestId") ?? "",
|
|
3886
|
+
event.correlation.promptManifestId ?? stringAt(attributes, "promptManifestId") ?? "",
|
|
3887
|
+
provenanceConfidence(attributes),
|
|
3848
3888
|
stringAt(attributes, "source") ?? (event.eventType === "file.event" ? "tool" : "external")
|
|
3849
3889
|
);
|
|
3850
3890
|
}
|
|
3851
3891
|
};
|
|
3892
|
+
function provenanceConfidence(attributes) {
|
|
3893
|
+
const value = attributes["provenanceConfidence"];
|
|
3894
|
+
return value === "explicit" || value === "correlated" || value === "inferred" ? value : "unknown";
|
|
3895
|
+
}
|
|
3852
3896
|
|
|
3853
3897
|
// src/chronicle/metrics-store.ts
|
|
3854
3898
|
var ChronicleMetricsStore = class _ChronicleMetricsStore {
|
|
@@ -3980,7 +4024,8 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
|
|
|
3980
4024
|
const where = clauses.length > 0 ? ` WHERE ${clauses.join(" AND ")}` : "";
|
|
3981
4025
|
params.push(clampLimit(options.limit, 200));
|
|
3982
4026
|
const projection = `path, operation, occurred_at, session_id, agent_id, task_id, board_id, run_id,
|
|
3983
|
-
tool_name, provider_id, model_id,
|
|
4027
|
+
tool_name, provider_id, model_id, logical_request_id, prompt_manifest_id,
|
|
4028
|
+
provenance_confidence, source`;
|
|
3984
4029
|
const sql = options.latestPerPath ? `SELECT ${projection} FROM (
|
|
3985
4030
|
SELECT ${projection}, ROW_NUMBER() OVER (
|
|
3986
4031
|
PARTITION BY path_key ORDER BY occurred_at DESC, event_id DESC
|
|
@@ -4001,6 +4046,9 @@ var ChronicleMetricsStore = class _ChronicleMetricsStore {
|
|
|
4001
4046
|
toolName: row.tool_name,
|
|
4002
4047
|
providerId: row.provider_id,
|
|
4003
4048
|
modelId: row.model_id,
|
|
4049
|
+
logicalRequestId: row.logical_request_id,
|
|
4050
|
+
promptManifestId: row.prompt_manifest_id,
|
|
4051
|
+
provenanceConfidence: row.provenance_confidence,
|
|
4004
4052
|
source: row.source
|
|
4005
4053
|
}));
|
|
4006
4054
|
}
|
|
@@ -4845,6 +4893,7 @@ var EMPTY_JOURNAL_STATS = {
|
|
|
4845
4893
|
largestBatch: 0,
|
|
4846
4894
|
partitionRolls: 0
|
|
4847
4895
|
};
|
|
4896
|
+
var MAX_OPEN_JOURNAL_DAYS = 2;
|
|
4848
4897
|
var InlineChronicleProjectAccess = class {
|
|
4849
4898
|
constructor(options) {
|
|
4850
4899
|
this.options = options;
|
|
@@ -4953,6 +5002,26 @@ var InlineChronicleProjectAccess = class {
|
|
|
4953
5002
|
get chronicleDirectory() {
|
|
4954
5003
|
return path15.join(this.options.projectDir, "chronicle");
|
|
4955
5004
|
}
|
|
5005
|
+
/**
|
|
5006
|
+
* Drop journals for days we will not write to again.
|
|
5007
|
+
*
|
|
5008
|
+
* Mirrors the daemon's `pruneJournals` in `project-server.ts`: without a cap
|
|
5009
|
+
* an inline access object that lives across midnight kept one open
|
|
5010
|
+
* `ChronicleJournal` (with its write buffer and file handle) per day, forever.
|
|
5011
|
+
*/
|
|
5012
|
+
pruneJournals(currentDay) {
|
|
5013
|
+
if (this.journals.size <= MAX_OPEN_JOURNAL_DAYS) return;
|
|
5014
|
+
const keep = new Set(
|
|
5015
|
+
[...this.journals.keys()].sort().reverse().slice(0, MAX_OPEN_JOURNAL_DAYS)
|
|
5016
|
+
);
|
|
5017
|
+
keep.add(currentDay);
|
|
5018
|
+
for (const [day, journal] of this.journals) {
|
|
5019
|
+
if (keep.has(day)) continue;
|
|
5020
|
+
this.journals.delete(day);
|
|
5021
|
+
void journal.flush().catch(() => {
|
|
5022
|
+
});
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
4956
5025
|
journalForToday() {
|
|
4957
5026
|
const now = /* @__PURE__ */ new Date();
|
|
4958
5027
|
const day = now.toISOString().slice(0, 10);
|
|
@@ -4969,6 +5038,7 @@ var InlineChronicleProjectAccess = class {
|
|
|
4969
5038
|
retentionDays: this.options.retentionDays
|
|
4970
5039
|
});
|
|
4971
5040
|
this.journals.set(day, journal);
|
|
5041
|
+
this.pruneJournals(day);
|
|
4972
5042
|
}
|
|
4973
5043
|
return journal;
|
|
4974
5044
|
}
|
|
@@ -5016,8 +5086,7 @@ var InlineChronicleProjectAccess = class {
|
|
|
5016
5086
|
|
|
5017
5087
|
// src/chronicle/sqlite-compaction.ts
|
|
5018
5088
|
import { existsSync as existsSync2, readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
|
|
5019
|
-
import {
|
|
5020
|
-
var require2 = createRequire3(import.meta.url);
|
|
5089
|
+
import { loadRuntimeDatabaseSync as loadRuntimeDatabaseSync3 } from "@wrongstack/persistence";
|
|
5021
5090
|
var ChronicleCompactionBusyError = class extends Error {
|
|
5022
5091
|
constructor(pid) {
|
|
5023
5092
|
super(`Chronicle project server is still running (pid ${pid}); stop it before compacting`);
|
|
@@ -5040,9 +5109,7 @@ function compactChronicleSqlite(options) {
|
|
|
5040
5109
|
if (!existsSync2(options.dbPath)) {
|
|
5041
5110
|
return { beforeBytes, afterBytes: beforeBytes, reclaimedBytes: 0 };
|
|
5042
5111
|
}
|
|
5043
|
-
const Database = withSqliteExperimentalWarningSuppressed(
|
|
5044
|
-
() => require2("node:sqlite").DatabaseSync
|
|
5045
|
-
);
|
|
5112
|
+
const Database = withSqliteExperimentalWarningSuppressed(loadRuntimeDatabaseSync3);
|
|
5046
5113
|
const db = new Database(options.dbPath);
|
|
5047
5114
|
try {
|
|
5048
5115
|
db.exec("PRAGMA busy_timeout = 1");
|
|
@@ -5112,6 +5179,7 @@ function persist(options, event, base, seenToolManifests) {
|
|
|
5112
5179
|
...context.correlation,
|
|
5113
5180
|
...event.traceId ? { traceId: event.traceId } : {},
|
|
5114
5181
|
logicalRequestId: event.logicalRequestId,
|
|
5182
|
+
...event.promptManifestId ? { promptManifestId: event.promptManifestId } : {},
|
|
5115
5183
|
attemptId: event.attemptId
|
|
5116
5184
|
},
|
|
5117
5185
|
runtime: { providerId: event.providerId, modelId: event.model },
|
|
@@ -5127,6 +5195,7 @@ function providerAttributes(event, seenToolManifests) {
|
|
|
5127
5195
|
providerId: _providerId,
|
|
5128
5196
|
model: _model,
|
|
5129
5197
|
logicalRequestId: _logicalRequestId,
|
|
5198
|
+
promptManifestId: _promptManifestId,
|
|
5130
5199
|
attemptId: _attemptId,
|
|
5131
5200
|
...rest
|
|
5132
5201
|
} = event;
|
|
@@ -5269,6 +5338,8 @@ function persist2(options, event, fields) {
|
|
|
5269
5338
|
correlation: {
|
|
5270
5339
|
...context.correlation,
|
|
5271
5340
|
...event.traceId ? { traceId: event.traceId } : {},
|
|
5341
|
+
...event.logicalRequestId ? { logicalRequestId: event.logicalRequestId } : {},
|
|
5342
|
+
...event.promptManifestId ? { promptManifestId: event.promptManifestId } : {},
|
|
5272
5343
|
...event.id ? { toolCallId: event.id } : {}
|
|
5273
5344
|
},
|
|
5274
5345
|
...event.provider || event.model ? {
|
|
@@ -5528,7 +5599,8 @@ function wireDomainEventsToChronicle(options) {
|
|
|
5528
5599
|
...stringField(record, "traceId") ? { traceId: stringField(record, "traceId") } : {},
|
|
5529
5600
|
...stringField(record, "toolCallId") ? { toolCallId: stringField(record, "toolCallId") } : {},
|
|
5530
5601
|
...stringField(record, "attemptId") ? { attemptId: stringField(record, "attemptId") } : {},
|
|
5531
|
-
...stringField(record, "logicalRequestId") ? { logicalRequestId: stringField(record, "logicalRequestId") } : {}
|
|
5602
|
+
...stringField(record, "logicalRequestId") ? { logicalRequestId: stringField(record, "logicalRequestId") } : {},
|
|
5603
|
+
...stringField(record, "promptManifestId") ? { promptManifestId: stringField(record, "promptManifestId") } : {}
|
|
5532
5604
|
},
|
|
5533
5605
|
outcome: inferOutcome(eventName, record),
|
|
5534
5606
|
runtime: {
|
|
@@ -4,7 +4,14 @@ export declare class ChronicleMetricsIngester {
|
|
|
4
4
|
private readonly db;
|
|
5
5
|
private readonly directory;
|
|
6
6
|
private readonly dbPath;
|
|
7
|
+
/**
|
|
8
|
+
* Prepared-statement cache for the per-event ingest hot paths. Preparing
|
|
9
|
+
* the same SQL on every event was the dominant ingest cost; node:sqlite
|
|
10
|
+
* statements are reusable, so each distinct SQL string is prepared once.
|
|
11
|
+
*/
|
|
12
|
+
private stmtCache;
|
|
7
13
|
constructor(db: DatabaseSync, directory: string, dbPath: string);
|
|
14
|
+
private stmt;
|
|
8
15
|
refresh(): Promise<ChronicleMetricsRefreshResult>;
|
|
9
16
|
private loadOffsets;
|
|
10
17
|
/** True once the legacy JSONL journal was imported into the SQLite journal
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatabaseSync } from 'node:sqlite';
|
|
2
2
|
import type { ChronicleSignalFamily } from './query.js';
|
|
3
3
|
import type { ChronicleEvent } from './types.js';
|
|
4
|
-
export declare const SCHEMA_VERSION =
|
|
4
|
+
export declare const SCHEMA_VERSION = 4;
|
|
5
5
|
export declare const READ_CHUNK_BYTES: number;
|
|
6
6
|
export declare const SQLITE_SOURCE_PREFIX = "sqlite:";
|
|
7
7
|
export declare const SQLITE_INGEST_BATCH = 2000;
|
|
@@ -54,6 +54,9 @@ export interface ChronicleFileLineageRow {
|
|
|
54
54
|
toolName: string;
|
|
55
55
|
providerId: string;
|
|
56
56
|
modelId: string;
|
|
57
|
+
logicalRequestId: string;
|
|
58
|
+
promptManifestId: string;
|
|
59
|
+
provenanceConfidence: 'explicit' | 'correlated' | 'inferred' | 'unknown';
|
|
57
60
|
source: string;
|
|
58
61
|
}
|
|
59
62
|
export interface ChronicleMetricsSummary {
|