@gobing-ai/ts-llm-jsonl-importer 0.5.18 → 0.5.20

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.
@@ -1 +1 @@
1
- {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../src/importer.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAER,aAAa,EACb,YAAY,EAGZ,gBAAgB,EAEnB,MAAM,SAAS,CAAC;AA4JjB;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAoerH"}
1
+ {"version":3,"file":"importer.d.ts","sourceRoot":"","sources":["../src/importer.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAER,aAAa,EACb,YAAY,EAGZ,gBAAgB,EAEnB,MAAM,SAAS,CAAC;AAkKjB;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAwerH"}
package/dist/importer.js CHANGED
@@ -95,8 +95,14 @@ async function resolveToolCallRow(db, source, sessionId, callId) {
95
95
  */
96
96
  function attachableDuration(timing, messageTsMs) {
97
97
  if (timing.wallTimeMs !== undefined) {
98
- // The tool's own measurement — no clamping, no sanity check.
99
- return { startedAt: null, completedAt: null, durationMs: Math.round(timing.wallTimeMs) };
98
+ // The tool's own measurement — no clamping, no sanity check. pi carries
99
+ // native bounds in details.toolMetadata (task 1131 R2); persist them when
100
+ // present so native and fallback durations stay distinguishable.
101
+ return {
102
+ startedAt: timing.startedAtMs !== undefined ? new Date(timing.startedAtMs).toISOString() : null,
103
+ completedAt: timing.completedAtMs !== undefined ? new Date(timing.completedAtMs).toISOString() : null,
104
+ durationMs: Math.round(timing.wallTimeMs),
105
+ };
100
106
  }
101
107
  if (timing.timestampMs === undefined || messageTsMs === undefined)
102
108
  return null;
@@ -382,10 +388,14 @@ export async function runJsonlImport(source, options) {
382
388
  // an implausible fallback delta stays NULL (unmeasured). The UPDATEs ride
383
389
  // this line's batch — idempotent, so re-imports and post-resume tail
384
390
  // reprocessing write the same values.
385
- if (definition.source === 'omp') {
391
+ if (definition.source === 'omp' || definition.source === 'pi') {
386
392
  const timing = ompToolResultTiming(raw);
387
393
  if (timing !== null) {
388
- const resultEntry = prepared.find((entry) => entry.split.targetTable === 'history_message' && entry.normalized.role === 'toolresult');
394
+ // pi normalizes toolResult envelopes to role `user` (piRole), so the
395
+ // role match must accept both shapes (task 1131 R2).
396
+ const resultEntry = prepared.find((entry) => entry.split.targetTable === 'history_message' &&
397
+ (entry.normalized.role === 'toolresult' ||
398
+ (definition.source === 'pi' && entry.normalized.role === 'user')));
389
399
  const sessionId = resultEntry?.normalized.session_id;
390
400
  if (typeof sessionId === 'string') {
391
401
  let pending = toolCallRows.get(toolCallKey(resolvedSource, sessionId, timing.toolCallId));
package/dist/mappers.d.ts CHANGED
@@ -54,16 +54,22 @@ export interface OmpToolResultTiming {
54
54
  wallTimeMs: number | undefined;
55
55
  /** Message timestamp as epoch millis, when parseable. */
56
56
  timestampMs: number | undefined;
57
+ /** Native start bound from pi `details.toolMetadata.startedAt` (task 1131 R2). */
58
+ startedAtMs: number | undefined;
59
+ /** Native completion bound from pi `details.toolMetadata.completedAt` (task 1131 R2). */
60
+ completedAtMs: number | undefined;
57
61
  }
58
62
  /** Parse a message timestamp (epoch-millis number, numeric string, or ISO) to epoch millis. */
59
63
  export declare function timestampToEpochMs(value: unknown): number | undefined;
60
64
  /**
61
- * Extract toolResult timing signals from a raw OMP record (task 0564 R1), or null
62
- * when the record is not a toolResult message or carries no toolCallId. Live OMP
63
- * emits `role: "toolResult"` message envelopes with `{toolCallId, toolName,
64
- * content, details, isError, timestamp}`; `details.wallTimeMs` is the tool's own
65
- * measured wall time (48% of results in the sampled session) and `toolCallId`
66
- * joins the originating `toolCall.id` exactly.
65
+ * Extract toolResult timing signals from a raw OMP or pi record (task 0564 R1,
66
+ * generalized for pi in task 1131 R2), or null when the record is not a
67
+ * toolResult message or carries no toolCallId. Both sources emit
68
+ * `role: "toolResult"` message envelopes with `{toolCallId, toolName, content,
69
+ * details, isError, timestamp}`; the tool's own wall time resolves from
70
+ * `details.wallTimeMs`, falling back to pi's `message.durationMs` and
71
+ * `details.toolMetadata.durationMs`, and `toolCallId` joins the originating
72
+ * `toolCall.id` exactly.
67
73
  */
68
74
  export declare function ompToolResultTiming(raw: Record<string, unknown>): OmpToolResultTiming | null;
69
75
  /** Signals carried by a Claude tool_result user line (task 0624 R2). */
@@ -1 +1 @@
1
- {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,OAAO,KAAK,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA0F9F;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CASzD;AAED,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,gBAAgB,GAAG,SAAS,EACrC,QAAQ,EAAE,iBAAiB,GAC5B,SAAS,oBAAoB,EAAE,CAmBjC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,UAAU,CAIvE;AAy2BD,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAGhD;AAwHD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAwBjG;AAMD,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAuH3G;AAMD,gEAAgE;AAChE,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAwHvG;AAmBD,kEAAkE;AAClE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAoHxG;AAoBD,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAChC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,OAAO,EAAE,OAAO,CAAC;IACjB,wEAAwE;IACxE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CASrE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,GAAG,IAAI,CAc5F;AAMD,wEAAwE;AACxE,MAAM,WAAW,sBAAsB;IACnC,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,wDAAwD;IACxD,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,2DAA2D;IAC3D,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,sBAAsB,GAAG,IAAI,CA+BlG;AAMD,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAiM1G;AAMD,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAwIxG;AAMD,gGAAgG;AAChG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAuF3G;AAMD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAgExG;AAQD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAoB9F;AAiMD,kEAAkE;AAClE,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,UAAU,EAAE,CAkTzG;AAgFD,wGAAwG;AACxG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAKxD;AAMD,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,wBAE5B,CAAC;AACF,4CAA4C;AAC5C,eAAO,MAAM,YAAY,wBAA8F,CAAC;AACxH,6CAA6C;AAC7C,eAAO,MAAM,aAAa,wBAEzB,CAAC;AACF,+CAA+C;AAC/C,eAAO,MAAM,eAAe,wBAE3B,CAAC;AACF,6CAA6C;AAC7C,eAAO,MAAM,aAAa,wBAEzB,CAAC;AACF,8CAA8C;AAC9C,eAAO,MAAM,cAAc,wBAE1B,CAAC;AACF,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,wBAE5B,CAAC;AACF,6FAA6F;AAC7F,eAAO,MAAM,aAAa,wBAAqE,CAAC;AAQhG,oDAAoD;AACpD,eAAO,MAAM,aAAa,gCAAoB,CAAC;AAC/C,gDAAgD;AAChD,eAAO,MAAM,SAAS,gCAAoB,CAAC;AAC3C,iDAAiD;AACjD,eAAO,MAAM,UAAU,gCAAoB,CAAC;AAC5C,mDAAmD;AACnD,eAAO,MAAM,YAAY,gCAAoB,CAAC;AAC9C,iDAAiD;AACjD,eAAO,MAAM,UAAU,gCAAoB,CAAC;AAC5C,kDAAkD;AAClD,eAAO,MAAM,WAAW,gCAAoB,CAAC;AAC7C,oDAAoD;AACpD,eAAO,MAAM,aAAa,gCAAoB,CAAC;AAC/C,0DAA0D;AAC1D,eAAO,MAAM,UAAU,gCAAoB,CAAC"}
1
+ {"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"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"}
package/dist/mappers.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { capabilityInvocationId, extractNestedExecCommandLiterals, matchCapabilityOrigin, parseLiteralReadTargets, } from './capability.js';
3
3
  import { sha256, sha256Text } from './hash.js';
4
+ import { applyRules } from './redaction.js';
4
5
  // ---------------------------------------------------------------------------
5
6
  // Helper: identity field map for typed columns
6
7
  // ---------------------------------------------------------------------------
@@ -940,14 +941,15 @@ export function argsDigest(args) {
940
941
  const redacted = redactArgs(args);
941
942
  return sha256(redacted);
942
943
  }
943
- /** Redact tool arguments for digest: replace string values > 80 chars or containing secrets. */
944
+ /**
945
+ * Redact tool arguments for digest: every string leaf gets the same secret
946
+ * replacement the persistence layer applies (task 1131 R1) — no length-based
947
+ * collapse, so two distinct long commands keep distinct digests and a token the
948
+ * shape rules catch never leaks into the digest input.
949
+ */
944
950
  function redactArgs(args) {
945
951
  if (typeof args === 'string') {
946
- if (args.length > 80)
947
- return '[REDACTED:long]';
948
- if (/[A-Za-z0-9+/]{40,}=*|[A-Za-z0-9_-]{20,}/.test(args))
949
- return '[REDACTED:secret]';
950
- return args;
952
+ return applyRules(args);
951
953
  }
952
954
  if (Array.isArray(args))
953
955
  return args.map(redactArgs);
@@ -1469,12 +1471,14 @@ export function timestampToEpochMs(value) {
1469
1471
  return undefined;
1470
1472
  }
1471
1473
  /**
1472
- * Extract toolResult timing signals from a raw OMP record (task 0564 R1), or null
1473
- * when the record is not a toolResult message or carries no toolCallId. Live OMP
1474
- * emits `role: "toolResult"` message envelopes with `{toolCallId, toolName,
1475
- * content, details, isError, timestamp}`; `details.wallTimeMs` is the tool's own
1476
- * measured wall time (48% of results in the sampled session) and `toolCallId`
1477
- * joins the originating `toolCall.id` exactly.
1474
+ * Extract toolResult timing signals from a raw OMP or pi record (task 0564 R1,
1475
+ * generalized for pi in task 1131 R2), or null when the record is not a
1476
+ * toolResult message or carries no toolCallId. Both sources emit
1477
+ * `role: "toolResult"` message envelopes with `{toolCallId, toolName, content,
1478
+ * details, isError, timestamp}`; the tool's own wall time resolves from
1479
+ * `details.wallTimeMs`, falling back to pi's `message.durationMs` and
1480
+ * `details.toolMetadata.durationMs`, and `toolCallId` joins the originating
1481
+ * `toolCall.id` exactly.
1478
1482
  */
1479
1483
  export function ompToolResultTiming(raw) {
1480
1484
  const msg = o(raw.message);
@@ -1484,12 +1488,15 @@ export function ompToolResultTiming(raw) {
1484
1488
  if (toolCallId === undefined)
1485
1489
  return null;
1486
1490
  const details = o(msg.details);
1487
- const wallTimeMs = typeof details.wallTimeMs === 'number' && Number.isFinite(details.wallTimeMs) ? details.wallTimeMs : undefined;
1491
+ const toolMetadata = o(details.toolMetadata);
1492
+ const finite = (value) => typeof value === 'number' && Number.isFinite(value) ? value : undefined;
1488
1493
  return {
1489
1494
  toolCallId,
1490
1495
  isError: msg.isError === true,
1491
- wallTimeMs,
1496
+ wallTimeMs: finite(details.wallTimeMs) ?? finite(msg.durationMs) ?? finite(toolMetadata.durationMs),
1492
1497
  timestampMs: timestampToEpochMs(raw.timestamp ?? msg.timestamp),
1498
+ startedAtMs: timestampToEpochMs(toolMetadata.startedAt),
1499
+ completedAtMs: timestampToEpochMs(toolMetadata.completedAt),
1493
1500
  };
1494
1501
  }
1495
1502
  /**
@@ -1,6 +1,8 @@
1
1
  import type { JsonObject, RedactionRule } from './types';
2
2
  /** Default redaction rules for common token, key, and email shapes in agent logs. */
3
3
  export declare const DEFAULT_REDACTION_RULES: readonly RedactionRule[];
4
+ /** Apply the rules' substring replacement to a single string leaf. */
5
+ export declare function applyRules(value: string, rules?: readonly RedactionRule[]): string;
4
6
  /** Redact supported scalar and composite JSON values recursively. */
5
7
  export declare function redactValue(value: unknown, rules?: readonly RedactionRule[]): unknown;
6
8
  /** Redact a normalized ETL record before hashing or writing it to the database. */
@@ -1 +1 @@
1
- {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEzD,qFAAqF;AACrF,eAAO,MAAM,uBAAuB,EAAE,SAAS,aAAa,EAwC3D,CAAC;AAUF,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,SAAS,aAAa,EAA4B,GAAG,OAAO,CAgB9G;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,OAAO,SAAS,UAAU,EACnD,MAAM,EAAE,OAAO,EACf,KAAK,GAAE,SAAS,aAAa,EAA4B,GAC1D,OAAO,CAET"}
1
+ {"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEzD,qFAAqF;AACrF,eAAO,MAAM,uBAAuB,EAAE,SAAS,aAAa,EAwC3D,CAAC;AAUF,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,aAAa,EAA4B,GAAG,MAAM,CAE3G;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,SAAS,aAAa,EAA4B,GAAG,OAAO,CAgB9G;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,OAAO,SAAS,UAAU,EACnD,MAAM,EAAE,OAAO,EACf,KAAK,GAAE,SAAS,aAAa,EAA4B,GAC1D,OAAO,CAET"}
package/dist/redaction.js CHANGED
@@ -45,10 +45,14 @@ export const DEFAULT_REDACTION_RULES = [
45
45
  * NOT redacted — those appear in LLM usage records.
46
46
  */
47
47
  const SECRET_KEY = /^(?:api[_-]?key|apikey|api[_-]?secret|token|access[_-]?token|refresh[_-]?token|auth[_-]?token|secret|secret[_-]?key|client[_-]?secret|private[_-]?key|session[_-]?token|password|passwd|authorization)$/i;
48
+ /** Apply the rules' substring replacement to a single string leaf. */
49
+ export function applyRules(value, rules = DEFAULT_REDACTION_RULES) {
50
+ return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
51
+ }
48
52
  /** Redact supported scalar and composite JSON values recursively. */
49
53
  export function redactValue(value, rules = DEFAULT_REDACTION_RULES) {
50
54
  if (typeof value === 'string') {
51
- return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
55
+ return applyRules(value, rules);
52
56
  }
53
57
  if (Array.isArray(value)) {
54
58
  return value.map((entry) => redactValue(entry, rules));
@@ -4,7 +4,7 @@
4
4
  * Guaranteed to match the package version; a bump-or-fail test enforces that
5
5
  * any modification to HISTORY_IMPORT_SCHEMA_SQL must be accompanied by a version bump.
6
6
  */
7
- export declare const HISTORY_IMPORT_SCHEMA_VERSION = "0.5.18";
7
+ export declare const HISTORY_IMPORT_SCHEMA_VERSION = "0.5.20";
8
8
  /**
9
9
  * DDL string that creates the history import checkpoint, ledger, and typed contract tables.
10
10
  *
@@ -4,7 +4,7 @@
4
4
  * Guaranteed to match the package version; a bump-or-fail test enforces that
5
5
  * any modification to HISTORY_IMPORT_SCHEMA_SQL must be accompanied by a version bump.
6
6
  */
7
- export const HISTORY_IMPORT_SCHEMA_VERSION = '0.5.18';
7
+ export const HISTORY_IMPORT_SCHEMA_VERSION = '0.5.20';
8
8
  /**
9
9
  * DDL string that creates the history import checkpoint, ledger, and typed contract tables.
10
10
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobing-ai/ts-llm-jsonl-importer",
3
- "version": "0.5.18",
3
+ "version": "0.5.20",
4
4
  "description": "@gobing-ai/ts-llm-jsonl-importer — Generic JSONL importer for LLM agent history files.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -47,9 +47,9 @@
47
47
  "release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-llm-jsonl-importer-v<version> && git push --tags' && exit 1"
48
48
  },
49
49
  "dependencies": {
50
- "@gobing-ai/ts-db": "^0.5.18",
51
- "@gobing-ai/ts-runtime": "^0.5.18",
52
- "@gobing-ai/ts-utils": "^0.5.18",
50
+ "@gobing-ai/ts-db": "^0.5.20",
51
+ "@gobing-ai/ts-runtime": "^0.5.20",
52
+ "@gobing-ai/ts-utils": "^0.5.20",
53
53
  "zod": "^4.1.0"
54
54
  },
55
55
  "devDependencies": {
package/src/importer.ts CHANGED
@@ -181,8 +181,14 @@ function attachableDuration(
181
181
  messageTsMs: number | undefined,
182
182
  ): { startedAt: string | null; completedAt: string | null; durationMs: number } | null {
183
183
  if (timing.wallTimeMs !== undefined) {
184
- // The tool's own measurement — no clamping, no sanity check.
185
- return { startedAt: null, completedAt: null, durationMs: Math.round(timing.wallTimeMs) };
184
+ // The tool's own measurement — no clamping, no sanity check. pi carries
185
+ // native bounds in details.toolMetadata (task 1131 R2); persist them when
186
+ // present so native and fallback durations stay distinguishable.
187
+ return {
188
+ startedAt: timing.startedAtMs !== undefined ? new Date(timing.startedAtMs).toISOString() : null,
189
+ completedAt: timing.completedAtMs !== undefined ? new Date(timing.completedAtMs).toISOString() : null,
190
+ durationMs: Math.round(timing.wallTimeMs),
191
+ };
186
192
  }
187
193
  if (timing.timestampMs === undefined || messageTsMs === undefined) return null;
188
194
  const delta = timing.timestampMs - messageTsMs;
@@ -526,12 +532,16 @@ export async function runJsonlImport(source: string | SourceDefinition, options:
526
532
  // an implausible fallback delta stays NULL (unmeasured). The UPDATEs ride
527
533
  // this line's batch — idempotent, so re-imports and post-resume tail
528
534
  // reprocessing write the same values.
529
- if (definition.source === 'omp') {
535
+ if (definition.source === 'omp' || definition.source === 'pi') {
530
536
  const timing = ompToolResultTiming(raw);
531
537
  if (timing !== null) {
538
+ // pi normalizes toolResult envelopes to role `user` (piRole), so the
539
+ // role match must accept both shapes (task 1131 R2).
532
540
  const resultEntry = prepared.find(
533
541
  (entry) =>
534
- entry.split.targetTable === 'history_message' && entry.normalized.role === 'toolresult',
542
+ entry.split.targetTable === 'history_message' &&
543
+ (entry.normalized.role === 'toolresult' ||
544
+ (definition.source === 'pi' && entry.normalized.role === 'user')),
535
545
  );
536
546
  const sessionId = resultEntry?.normalized.session_id;
537
547
  if (typeof sessionId === 'string') {
package/src/mappers.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  parseLiteralReadTargets,
8
8
  } from './capability';
9
9
  import { sha256, sha256Text } from './hash';
10
+ import { applyRules } from './redaction';
10
11
  import type { JsonObject, SkillCallSplitRecord, SplitEntry, TransformContext } from './types';
11
12
 
12
13
  // ---------------------------------------------------------------------------
@@ -1047,12 +1048,15 @@ export function argsDigest(args: unknown): string {
1047
1048
  /** Redacted tool args: JSON shape preserved, string leaves possibly elided. */
1048
1049
  type RedactedValue = string | number | boolean | null | RedactedValue[] | { [key: string]: RedactedValue };
1049
1050
 
1050
- /** Redact tool arguments for digest: replace string values > 80 chars or containing secrets. */
1051
+ /**
1052
+ * Redact tool arguments for digest: every string leaf gets the same secret
1053
+ * replacement the persistence layer applies (task 1131 R1) — no length-based
1054
+ * collapse, so two distinct long commands keep distinct digests and a token the
1055
+ * shape rules catch never leaks into the digest input.
1056
+ */
1051
1057
  function redactArgs(args: unknown): RedactedValue {
1052
1058
  if (typeof args === 'string') {
1053
- if (args.length > 80) return '[REDACTED:long]';
1054
- if (/[A-Za-z0-9+/]{40,}=*|[A-Za-z0-9_-]{20,}/.test(args)) return '[REDACTED:secret]';
1055
- return args;
1059
+ return applyRules(args);
1056
1060
  }
1057
1061
  if (Array.isArray(args)) return args.map(redactArgs);
1058
1062
  if (args !== null && typeof args === 'object') {
@@ -1610,6 +1614,10 @@ export interface OmpToolResultTiming {
1610
1614
  wallTimeMs: number | undefined;
1611
1615
  /** Message timestamp as epoch millis, when parseable. */
1612
1616
  timestampMs: number | undefined;
1617
+ /** Native start bound from pi `details.toolMetadata.startedAt` (task 1131 R2). */
1618
+ startedAtMs: number | undefined;
1619
+ /** Native completion bound from pi `details.toolMetadata.completedAt` (task 1131 R2). */
1620
+ completedAtMs: number | undefined;
1613
1621
  }
1614
1622
 
1615
1623
  /** Parse a message timestamp (epoch-millis number, numeric string, or ISO) to epoch millis. */
@@ -1625,12 +1633,14 @@ export function timestampToEpochMs(value: unknown): number | undefined {
1625
1633
  }
1626
1634
 
1627
1635
  /**
1628
- * Extract toolResult timing signals from a raw OMP record (task 0564 R1), or null
1629
- * when the record is not a toolResult message or carries no toolCallId. Live OMP
1630
- * emits `role: "toolResult"` message envelopes with `{toolCallId, toolName,
1631
- * content, details, isError, timestamp}`; `details.wallTimeMs` is the tool's own
1632
- * measured wall time (48% of results in the sampled session) and `toolCallId`
1633
- * joins the originating `toolCall.id` exactly.
1636
+ * Extract toolResult timing signals from a raw OMP or pi record (task 0564 R1,
1637
+ * generalized for pi in task 1131 R2), or null when the record is not a
1638
+ * toolResult message or carries no toolCallId. Both sources emit
1639
+ * `role: "toolResult"` message envelopes with `{toolCallId, toolName, content,
1640
+ * details, isError, timestamp}`; the tool's own wall time resolves from
1641
+ * `details.wallTimeMs`, falling back to pi's `message.durationMs` and
1642
+ * `details.toolMetadata.durationMs`, and `toolCallId` joins the originating
1643
+ * `toolCall.id` exactly.
1634
1644
  */
1635
1645
  export function ompToolResultTiming(raw: Record<string, unknown>): OmpToolResultTiming | null {
1636
1646
  const msg = o(raw.message);
@@ -1638,13 +1648,16 @@ export function ompToolResultTiming(raw: Record<string, unknown>): OmpToolResult
1638
1648
  const toolCallId = s(msg.toolCallId);
1639
1649
  if (toolCallId === undefined) return null;
1640
1650
  const details = o(msg.details);
1641
- const wallTimeMs =
1642
- typeof details.wallTimeMs === 'number' && Number.isFinite(details.wallTimeMs) ? details.wallTimeMs : undefined;
1651
+ const toolMetadata = o(details.toolMetadata);
1652
+ const finite = (value: unknown): number | undefined =>
1653
+ typeof value === 'number' && Number.isFinite(value) ? value : undefined;
1643
1654
  return {
1644
1655
  toolCallId,
1645
1656
  isError: msg.isError === true,
1646
- wallTimeMs,
1657
+ wallTimeMs: finite(details.wallTimeMs) ?? finite(msg.durationMs) ?? finite(toolMetadata.durationMs),
1647
1658
  timestampMs: timestampToEpochMs(raw.timestamp ?? msg.timestamp),
1659
+ startedAtMs: timestampToEpochMs(toolMetadata.startedAt),
1660
+ completedAtMs: timestampToEpochMs(toolMetadata.completedAt),
1648
1661
  };
1649
1662
  }
1650
1663
 
package/src/redaction.ts CHANGED
@@ -51,10 +51,15 @@ export const DEFAULT_REDACTION_RULES: readonly RedactionRule[] = [
51
51
  const SECRET_KEY =
52
52
  /^(?:api[_-]?key|apikey|api[_-]?secret|token|access[_-]?token|refresh[_-]?token|auth[_-]?token|secret|secret[_-]?key|client[_-]?secret|private[_-]?key|session[_-]?token|password|passwd|authorization)$/i;
53
53
 
54
+ /** Apply the rules' substring replacement to a single string leaf. */
55
+ export function applyRules(value: string, rules: readonly RedactionRule[] = DEFAULT_REDACTION_RULES): string {
56
+ return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
57
+ }
58
+
54
59
  /** Redact supported scalar and composite JSON values recursively. */
55
60
  export function redactValue(value: unknown, rules: readonly RedactionRule[] = DEFAULT_REDACTION_RULES): unknown {
56
61
  if (typeof value === 'string') {
57
- return rules.reduce((current, rule) => current.replace(rule.pattern, rule.replacement), value);
62
+ return applyRules(value, rules);
58
63
  }
59
64
  if (Array.isArray(value)) {
60
65
  return value.map((entry) => redactValue(entry, rules));
package/src/schema-sql.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Guaranteed to match the package version; a bump-or-fail test enforces that
5
5
  * any modification to HISTORY_IMPORT_SCHEMA_SQL must be accompanied by a version bump.
6
6
  */
7
- export const HISTORY_IMPORT_SCHEMA_VERSION = '0.5.18';
7
+ export const HISTORY_IMPORT_SCHEMA_VERSION = '0.5.20';
8
8
 
9
9
  /**
10
10
  * DDL string that creates the history import checkpoint, ledger, and typed contract tables.