@gobing-ai/ts-llm-jsonl-importer 0.4.52 → 0.4.54
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/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/jsonl-importer-dao.d.ts +1 -1
- package/dist/jsonl-importer-dao.d.ts.map +1 -1
- package/dist/jsonl-importer-dao.js +1 -1
- package/dist/mappers.d.ts +34 -3
- package/dist/mappers.d.ts.map +1 -1
- package/dist/mappers.js +300 -10
- package/dist/opencode-importer.js +36 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +8 -1
- package/src/jsonl-importer-dao.ts +2 -2
- package/src/mappers.ts +330 -11
- package/src/opencode-importer.ts +41 -2
- package/src/types.ts +22 -0
package/dist/index.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ export { HistoryImportError } from './errors';
|
|
|
2
2
|
export { sha256, stableJson } from './hash';
|
|
3
3
|
export { runJsonlImport } from './importer';
|
|
4
4
|
export { applyHistoryImportSchema, normalizeSourceFilePaths } from './jsonl-importer-dao';
|
|
5
|
-
export { sessionIdFromSourcePath } from './mappers';
|
|
5
|
+
export { canonicalizeSkillName, extractSkillCalls, type SkillCallIdentity, sessionIdFromSourcePath, skillCallEntry, } from './mappers';
|
|
6
6
|
export { type OpenCodeImportOptions, runOpenCodeImport } from './opencode-importer';
|
|
7
7
|
export { DEFAULT_REDACTION_RULES, redactRecord, redactValue } from './redaction';
|
|
8
8
|
export { HISTORY_IMPORT_SCHEMA_SQL } from './schema-sql';
|
|
9
9
|
export { getSourceDefinition, resolveSourceDefinition, SOURCE_DEFINITIONS, VALID_TABLE_NAME, validateSourceDefinition, } from './sources';
|
|
10
|
-
export type { FieldTransform, ImportIssue, ImportMode, ImportOptions, ImportResult, JsonObject, LlmJsonlSource, ReconcileSummary, RedactionRule, SkillCall, SourceDefinition, SplitConfig, SplitEntry, TransformContext, } from './types';
|
|
10
|
+
export type { FieldTransform, ImportIssue, ImportMode, ImportOptions, ImportResult, JsonObject, LlmJsonlSource, ReconcileSummary, RedactionRule, SkillCall, SkillCallSplitRecord, SourceDefinition, SplitConfig, SplitEntry, TransformContext, } from './types';
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EACH,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,uBAAuB,EACvB,cAAc,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,GAC3B,MAAM,WAAW,CAAC;AACnB,YAAY,EACR,cAAc,EACd,WAAW,EACX,UAAU,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,oBAAoB,EACpB,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,gBAAgB,GACnB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { HistoryImportError } from './errors.js';
|
|
|
2
2
|
export { sha256, stableJson } from './hash.js';
|
|
3
3
|
export { runJsonlImport } from './importer.js';
|
|
4
4
|
export { applyHistoryImportSchema, normalizeSourceFilePaths } from './jsonl-importer-dao.js';
|
|
5
|
-
export { sessionIdFromSourcePath } from './mappers.js';
|
|
5
|
+
export { canonicalizeSkillName, extractSkillCalls, sessionIdFromSourcePath, skillCallEntry, } from './mappers.js';
|
|
6
6
|
export { runOpenCodeImport } from './opencode-importer.js';
|
|
7
7
|
export { DEFAULT_REDACTION_RULES, redactRecord, redactValue } from './redaction.js';
|
|
8
8
|
export { HISTORY_IMPORT_SCHEMA_SQL } from './schema-sql.js';
|
|
@@ -149,7 +149,7 @@ export interface OpenCodeExistingEntry {
|
|
|
149
149
|
}
|
|
150
150
|
/** Normalized OpenCode entry awaiting a history-table write. */
|
|
151
151
|
export interface OpenCodeQueuedEntry {
|
|
152
|
-
targetTable: 'history_message' | 'history_tool_call';
|
|
152
|
+
targetTable: 'history_message' | 'history_tool_call' | 'history_skill_call';
|
|
153
153
|
splitIndex: number;
|
|
154
154
|
record: JsonObject;
|
|
155
155
|
recordHash: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsonl-importer-dao.d.ts","sourceRoot":"","sources":["../src/jsonl-importer-dao.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"jsonl-importer-dao.d.ts","sourceRoot":"","sources":["../src/jsonl-importer-dao.ts"],"names":[],"mappings":"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"}
|
|
@@ -502,7 +502,7 @@ export function deleteCheckpointOperation(source, sourceFile) {
|
|
|
502
502
|
export function openCodeBulkWriteOperations(entries, checkpointFiles, now) {
|
|
503
503
|
const importedAt = timestamp(now);
|
|
504
504
|
const operations = [];
|
|
505
|
-
for (const table of ['history_message', 'history_tool_call']) {
|
|
505
|
+
for (const table of ['history_message', 'history_tool_call', 'history_skill_call']) {
|
|
506
506
|
const tableEntries = entries.filter((entry) => entry.targetTable === table);
|
|
507
507
|
for (let offset = 0; offset < tableEntries.length; offset += 100) {
|
|
508
508
|
const chunk = tableEntries.slice(offset, offset + 100);
|
package/dist/mappers.d.ts
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import type { JsonObject, SplitEntry, TransformContext } from './types';
|
|
2
|
+
import type { JsonObject, SkillCallSplitRecord, SplitEntry, TransformContext } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Canonicalize a harness skill name: `sp-dev-run` / `$sp-dev-run` / `/skill:sp-dev-run` →
|
|
5
|
+
* `sp:dev-run`; `rd3-*` → `rd3:*`. Only the frozen harness package set is rewritten — an
|
|
6
|
+
* unqualified name like `code-review` is kept verbatim (exact structural match, 0736 R4).
|
|
7
|
+
*/
|
|
8
|
+
export declare function canonicalizeSkillName(raw: string): string;
|
|
9
|
+
/** Identity fields a split already computed for its parent message (skill rows join it). */
|
|
10
|
+
export interface SkillCallIdentity {
|
|
11
|
+
readonly sessionId: string;
|
|
12
|
+
readonly seq: number;
|
|
13
|
+
/** Split index of the parent message entry in the same split batch (_messageSplitIndex). */
|
|
14
|
+
readonly messageSplitIndex: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Detect skill-load events in one raw source record (0736 R1/R2). Dispatches on the source in
|
|
18
|
+
* the transform context; unknown sources return nothing. Detection signatures per source are
|
|
19
|
+
* the verified ones from the storm report §10.3:
|
|
20
|
+
*
|
|
21
|
+
* - L1 native load tool is authoritative (claude/omp `Skill`, agy `view_file` skill reads,
|
|
22
|
+
* grok `read_file` on SKILL.md, opencode native `skill`).
|
|
23
|
+
* - Sources with no L1 trigger on their structural signal: pi's `<skill name= location=>`
|
|
24
|
+
* wrapper, codex's `<skill><name>/<path>` block, gemini's L0 harness prefix.
|
|
25
|
+
* - L0/L2 never trigger for agents that have an L1 (false-positive suppression, 0736 R4).
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractSkillCalls(raw: JsonObject, context: TransformContext | undefined, identity: SkillCallIdentity): readonly SkillCallSplitRecord[];
|
|
28
|
+
/**
|
|
29
|
+
* Route one skill-load row to `history_skill_call` exactly like tool calls route to
|
|
30
|
+
* `history_tool_call`: a SplitEntry whose record the importer normalizes, hashes, dedups,
|
|
31
|
+
* and inserts through the typed-column path.
|
|
32
|
+
*/
|
|
33
|
+
export declare function skillCallEntry(record: SkillCallSplitRecord): SplitEntry;
|
|
3
34
|
/** Compute args_digest: sha256 of stable-jsonified, key-sorted, redacted args. */
|
|
4
35
|
export declare function argsDigest(args: unknown): string;
|
|
5
36
|
/**
|
|
@@ -9,7 +40,7 @@ export declare function argsDigest(args: unknown): string;
|
|
|
9
40
|
*/
|
|
10
41
|
export declare function maybeArgsRaw(_source: string, toolName: string, args: unknown): string | undefined;
|
|
11
42
|
/** Map a Claude Code JSONL record into one or more ETL split entries. */
|
|
12
|
-
export declare function claudeSplit(raw: Record<string, unknown
|
|
43
|
+
export declare function claudeSplit(raw: Record<string, unknown>, context?: TransformContext): readonly SplitEntry[];
|
|
13
44
|
/** Map a Pi JSONL record into one or more ETL split entries. */
|
|
14
45
|
export declare function piSplit(raw: Record<string, unknown>, context?: TransformContext): readonly SplitEntry[];
|
|
15
46
|
/** Map an OMP JSONL record into one or more ETL split entries. */
|
|
@@ -70,7 +101,7 @@ export declare function geminiSplit(raw: Record<string, unknown>, context?: Tran
|
|
|
70
101
|
*/
|
|
71
102
|
export declare function sessionIdFromSourcePath(source: string, sourceFile: string): string | undefined;
|
|
72
103
|
/** Map a Grok JSONL record into one or more ETL split entries. */
|
|
73
|
-
export declare function grokSplit(raw: Record<string, unknown
|
|
104
|
+
export declare function grokSplit(raw: Record<string, unknown>, context?: TransformContext): readonly SplitEntry[];
|
|
74
105
|
/** Compute a stable field-shape key from a JSON object: sorted, lowercased, +-joined top-level keys. */
|
|
75
106
|
export declare function stableFieldShape(raw: JsonObject): string;
|
|
76
107
|
/** Identity field map for the Claude mapper. */
|
package/dist/mappers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mappers.d.ts","sourceRoot":"","sources":["../src/mappers.ts"],"names":[],"mappings":"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"}
|
package/dist/mappers.js
CHANGED
|
@@ -45,6 +45,22 @@ const TOOL_CALL_MAPPER_KEYS = [
|
|
|
45
45
|
'result_bytes',
|
|
46
46
|
'error_text',
|
|
47
47
|
];
|
|
48
|
+
/** Columns the mapper may produce for history_skill_call (0736). */
|
|
49
|
+
const SKILL_CALL_MAPPER_KEYS = [
|
|
50
|
+
'_messageSplitIndex',
|
|
51
|
+
'session_id',
|
|
52
|
+
'seq',
|
|
53
|
+
'skill_name',
|
|
54
|
+
'invocation_kind',
|
|
55
|
+
'skill_path',
|
|
56
|
+
'args_raw',
|
|
57
|
+
'args_digest',
|
|
58
|
+
'call_id',
|
|
59
|
+
'status',
|
|
60
|
+
'started_at',
|
|
61
|
+
'completed_at',
|
|
62
|
+
'duration_ms',
|
|
63
|
+
];
|
|
48
64
|
/** Build an identity fieldMap for the given column list. */
|
|
49
65
|
function identityFieldMap(keys) {
|
|
50
66
|
const map = {};
|
|
@@ -54,6 +70,251 @@ function identityFieldMap(keys) {
|
|
|
54
70
|
return map;
|
|
55
71
|
}
|
|
56
72
|
// ---------------------------------------------------------------------------
|
|
73
|
+
// Skill-load extraction (0736)
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
/** Harness skill packages whose dialect spelling swaps ':' for '-' (storm report §10.1). */
|
|
76
|
+
const HARNESS_SKILL_PACKAGES = new Set(['sp', 'rd3']);
|
|
77
|
+
/**
|
|
78
|
+
* Canonicalize a harness skill name: `sp-dev-run` / `$sp-dev-run` / `/skill:sp-dev-run` →
|
|
79
|
+
* `sp:dev-run`; `rd3-*` → `rd3:*`. Only the frozen harness package set is rewritten — an
|
|
80
|
+
* unqualified name like `code-review` is kept verbatim (exact structural match, 0736 R4).
|
|
81
|
+
*/
|
|
82
|
+
export function canonicalizeSkillName(raw) {
|
|
83
|
+
let name = raw.trim();
|
|
84
|
+
if (name.startsWith('/') || name.startsWith('$'))
|
|
85
|
+
name = name.slice(1);
|
|
86
|
+
if (name.startsWith('skill:'))
|
|
87
|
+
name = name.slice('skill:'.length);
|
|
88
|
+
const canonical = name.match(/^([a-z][a-z0-9]*):([a-z0-9-]+)$/);
|
|
89
|
+
if (canonical !== null && HARNESS_SKILL_PACKAGES.has(canonical[1] ?? ''))
|
|
90
|
+
return name;
|
|
91
|
+
const dialect = name.match(/^([a-z][a-z0-9]*)-([a-z0-9-]+)$/);
|
|
92
|
+
if (dialect !== null && HARNESS_SKILL_PACKAGES.has(dialect[1] ?? ''))
|
|
93
|
+
return `${dialect[1]}:${dialect[2]}`;
|
|
94
|
+
return name;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Detect skill-load events in one raw source record (0736 R1/R2). Dispatches on the source in
|
|
98
|
+
* the transform context; unknown sources return nothing. Detection signatures per source are
|
|
99
|
+
* the verified ones from the storm report §10.3:
|
|
100
|
+
*
|
|
101
|
+
* - L1 native load tool is authoritative (claude/omp `Skill`, agy `view_file` skill reads,
|
|
102
|
+
* grok `read_file` on SKILL.md, opencode native `skill`).
|
|
103
|
+
* - Sources with no L1 trigger on their structural signal: pi's `<skill name= location=>`
|
|
104
|
+
* wrapper, codex's `<skill><name>/<path>` block, gemini's L0 harness prefix.
|
|
105
|
+
* - L0/L2 never trigger for agents that have an L1 (false-positive suppression, 0736 R4).
|
|
106
|
+
*/
|
|
107
|
+
export function extractSkillCalls(raw, context, identity) {
|
|
108
|
+
switch (context?.source) {
|
|
109
|
+
case 'claude':
|
|
110
|
+
return detectClaudeSkillCalls(raw, identity);
|
|
111
|
+
case 'pi':
|
|
112
|
+
return detectPiSkillCalls(raw, identity);
|
|
113
|
+
case 'omp':
|
|
114
|
+
return detectOmpSkillCalls(raw, identity);
|
|
115
|
+
case 'codex':
|
|
116
|
+
return detectCodexSkillCalls(raw, identity);
|
|
117
|
+
case 'agy':
|
|
118
|
+
return detectAgySkillCalls(raw, identity);
|
|
119
|
+
case 'gemini':
|
|
120
|
+
return detectGeminiSkillCalls(raw, identity);
|
|
121
|
+
case 'grok':
|
|
122
|
+
return detectGrokSkillCalls(raw, identity);
|
|
123
|
+
default:
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Route one skill-load row to `history_skill_call` exactly like tool calls route to
|
|
129
|
+
* `history_tool_call`: a SplitEntry whose record the importer normalizes, hashes, dedups,
|
|
130
|
+
* and inserts through the typed-column path.
|
|
131
|
+
*/
|
|
132
|
+
export function skillCallEntry(record) {
|
|
133
|
+
// The split record's keys are exactly the history_skill_call typed columns; the index
|
|
134
|
+
// signature is supplied at this boundary (runtime shape is JSON-compatible by construction).
|
|
135
|
+
return { targetTable: 'history_skill_call', record: record };
|
|
136
|
+
}
|
|
137
|
+
/** Build a fully-populated skill row: every optional column set explicitly for hash stability. */
|
|
138
|
+
function skillRecord(identity, skillName, invocationKind, extra = {}) {
|
|
139
|
+
return {
|
|
140
|
+
_messageSplitIndex: identity.messageSplitIndex,
|
|
141
|
+
session_id: identity.sessionId,
|
|
142
|
+
seq: identity.seq,
|
|
143
|
+
skill_name: canonicalizeSkillName(skillName),
|
|
144
|
+
invocation_kind: invocationKind,
|
|
145
|
+
skill_path: null,
|
|
146
|
+
args_raw: null,
|
|
147
|
+
args_digest: null,
|
|
148
|
+
call_id: null,
|
|
149
|
+
status: 'ok',
|
|
150
|
+
started_at: null,
|
|
151
|
+
completed_at: null,
|
|
152
|
+
duration_ms: null,
|
|
153
|
+
...extra,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** Skill name from a `.../skills/<name>/SKILL.md` path; falls back to the SKILL.md sibling. */
|
|
157
|
+
function skillNameFromPath(path) {
|
|
158
|
+
const normalized = path.replace(/\\/g, '/');
|
|
159
|
+
const bySkillsSegment = normalized.match(/\/skills\/([^/]+)\/SKILL\.md$/i);
|
|
160
|
+
if (bySkillsSegment !== null)
|
|
161
|
+
return bySkillsSegment[1] ?? '';
|
|
162
|
+
const stem = normalized.slice(0, normalized.length - '/SKILL.md'.length);
|
|
163
|
+
return stem.split('/').pop() ?? stem;
|
|
164
|
+
}
|
|
165
|
+
function detectClaudeSkillCalls(raw, identity) {
|
|
166
|
+
const contentBlocks = raw.content ?? o(raw.message).content;
|
|
167
|
+
if (!Array.isArray(contentBlocks))
|
|
168
|
+
return [];
|
|
169
|
+
const rows = [];
|
|
170
|
+
for (const block of contentBlocks) {
|
|
171
|
+
if (typeof block !== 'object' || block === null)
|
|
172
|
+
continue;
|
|
173
|
+
const b = block;
|
|
174
|
+
if (b.type !== 'tool_use' || b.name !== 'Skill')
|
|
175
|
+
continue;
|
|
176
|
+
const input = (b.input ?? {});
|
|
177
|
+
const skill = s(input.skill);
|
|
178
|
+
if (skill === undefined)
|
|
179
|
+
continue;
|
|
180
|
+
// caller.type "direct" = user-invoked (storm report §10.3); absence = model-invoked.
|
|
181
|
+
rows.push(skillRecord(identity, skill, s(o(b.caller).type) === 'direct' ? 'user' : 'model', {
|
|
182
|
+
args_raw: maybeArgsRaw('claude', 'Skill', input) ?? null,
|
|
183
|
+
args_digest: argsDigest(input),
|
|
184
|
+
call_id: s(b.id) ?? null,
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
187
|
+
return rows;
|
|
188
|
+
}
|
|
189
|
+
/** pi is inline-only: the `<skill name= location=>` wrapper in a user message is the sole trigger. */
|
|
190
|
+
const PI_SKILL_WRAPPER = /<skill\s+name="([^"]+)"(?:\s+location="([^"]*)")?\s*>/g;
|
|
191
|
+
function detectPiSkillCalls(raw, identity) {
|
|
192
|
+
const msg = raw.message;
|
|
193
|
+
if (piRole(msg?.role ?? raw.role ?? raw.recordType ?? raw.type) !== 'user')
|
|
194
|
+
return [];
|
|
195
|
+
const text = extractContentText(msg?.content ?? raw.content);
|
|
196
|
+
if (text === undefined)
|
|
197
|
+
return [];
|
|
198
|
+
const rows = [];
|
|
199
|
+
for (const match of text.matchAll(PI_SKILL_WRAPPER)) {
|
|
200
|
+
rows.push(skillRecord(identity, match[1] ?? '', 'user', { skill_path: match[2] || null }));
|
|
201
|
+
}
|
|
202
|
+
return rows;
|
|
203
|
+
}
|
|
204
|
+
function detectOmpSkillCalls(raw, identity) {
|
|
205
|
+
const msg = raw.message;
|
|
206
|
+
if (mapRole(msg?.role ?? raw.type ?? raw.role) !== 'assistant')
|
|
207
|
+
return [];
|
|
208
|
+
const contentBlocks = msg?.content ?? raw.content;
|
|
209
|
+
if (!Array.isArray(contentBlocks))
|
|
210
|
+
return [];
|
|
211
|
+
const rows = [];
|
|
212
|
+
for (const block of contentBlocks) {
|
|
213
|
+
const call = normalizeOmpToolCall(block);
|
|
214
|
+
if (call === null || call.name !== 'Skill')
|
|
215
|
+
continue;
|
|
216
|
+
const input = call.input ?? call.arguments;
|
|
217
|
+
const skill = s(input?.skill);
|
|
218
|
+
if (skill === undefined)
|
|
219
|
+
continue;
|
|
220
|
+
rows.push(skillRecord(identity, skill, 'model', {
|
|
221
|
+
args_raw: maybeArgsRaw('omp', 'Skill', input) ?? null,
|
|
222
|
+
args_digest: argsDigest(input),
|
|
223
|
+
call_id: s(call.id) ?? null,
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
return rows;
|
|
227
|
+
}
|
|
228
|
+
/** Codex has no native load tool call: the child-element `<skill>` block is the trigger. */
|
|
229
|
+
const CODEX_SKILL_BLOCK = /<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>\s*<\/skill>/g;
|
|
230
|
+
function detectCodexSkillCalls(raw, identity) {
|
|
231
|
+
const payload = (raw.payload ?? raw);
|
|
232
|
+
const recordType = String(raw.type ?? '');
|
|
233
|
+
const payloadType = String(payload.type ?? '');
|
|
234
|
+
let role;
|
|
235
|
+
if (recordType === 'response_item') {
|
|
236
|
+
role =
|
|
237
|
+
payloadType === 'message' ? mapRole(payload.role) : payloadType === 'agent_message' ? 'assistant' : 'meta';
|
|
238
|
+
}
|
|
239
|
+
else if (recordType === 'user' || recordType === 'assistant') {
|
|
240
|
+
role = mapRole(recordType);
|
|
241
|
+
}
|
|
242
|
+
else if (recordType === 'message') {
|
|
243
|
+
role = mapRole(raw.role ?? payload.role);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
if (role !== 'user')
|
|
249
|
+
return [];
|
|
250
|
+
const text = extractContentText(payload.content ?? raw.content) ?? s(payload.text, raw.text);
|
|
251
|
+
if (text === undefined)
|
|
252
|
+
return [];
|
|
253
|
+
const rows = [];
|
|
254
|
+
for (const match of text.matchAll(CODEX_SKILL_BLOCK)) {
|
|
255
|
+
rows.push(skillRecord(identity, match[1] ?? '', 'user', { skill_path: match[2] ?? null }));
|
|
256
|
+
}
|
|
257
|
+
return rows;
|
|
258
|
+
}
|
|
259
|
+
/** agy loads skills via `view_file` with toolAction "Viewing skill file" on a SKILL.md path. */
|
|
260
|
+
function detectAgySkillCalls(raw, identity) {
|
|
261
|
+
if (String(raw.type ?? '') !== 'PLANNER_RESPONSE' || !Array.isArray(raw.tool_calls))
|
|
262
|
+
return [];
|
|
263
|
+
const rows = [];
|
|
264
|
+
for (const tc of raw.tool_calls) {
|
|
265
|
+
const tool = s(tc.name, tc.tool_name);
|
|
266
|
+
if (tool !== 'view_file')
|
|
267
|
+
continue;
|
|
268
|
+
const args = (tc.args ?? tc.arguments ?? {});
|
|
269
|
+
if (args.toolAction !== 'Viewing skill file')
|
|
270
|
+
continue;
|
|
271
|
+
const path = s(args.AbsolutePath, args.absolute_path);
|
|
272
|
+
if (path === undefined || !path.replace(/\\/g, '/').endsWith('/SKILL.md'))
|
|
273
|
+
continue;
|
|
274
|
+
const summary = s(args.toolSummary);
|
|
275
|
+
const skillName = summary?.match(/SKILL\.md for (.+)$/)?.[1] ?? skillNameFromPath(path);
|
|
276
|
+
rows.push(skillRecord(identity, skillName, 'model', {
|
|
277
|
+
skill_path: path,
|
|
278
|
+
args_raw: maybeArgsRaw('agy', 'view_file', args) ?? null,
|
|
279
|
+
args_digest: argsDigest(args),
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
return rows;
|
|
283
|
+
}
|
|
284
|
+
/** Gemini has no verified L1: the L0 harness prefix in a user message is the trigger. */
|
|
285
|
+
const GEMINI_L0_PREFIX = /^\s*\/((?:sp|rd3)-[a-z0-9-]+)/;
|
|
286
|
+
function detectGeminiSkillCalls(raw, identity) {
|
|
287
|
+
if (String(raw.type ?? '') !== 'user')
|
|
288
|
+
return [];
|
|
289
|
+
const content = geminiContent(raw);
|
|
290
|
+
if (content === null)
|
|
291
|
+
return [];
|
|
292
|
+
const match = content.match(GEMINI_L0_PREFIX);
|
|
293
|
+
if (match === null)
|
|
294
|
+
return [];
|
|
295
|
+
return [skillRecord(identity, match[1] ?? '', 'user')];
|
|
296
|
+
}
|
|
297
|
+
/** grok loads skills via `read_file` (grok_build namespace) targeting a SKILL.md path. */
|
|
298
|
+
function detectGrokSkillCalls(raw, identity) {
|
|
299
|
+
const n = normalizeGrokRecord(raw);
|
|
300
|
+
if (n.recordType !== 'tool_call' || n.toolName !== 'read_file')
|
|
301
|
+
return [];
|
|
302
|
+
const meta = (n.body._meta ?? raw._meta ?? {});
|
|
303
|
+
if (o(meta['x.ai/tool']).namespace !== 'grok_build')
|
|
304
|
+
return [];
|
|
305
|
+
const targetFile = s(o(n.toolArgs).target_file);
|
|
306
|
+
if (targetFile === undefined || !targetFile.replace(/\\/g, '/').endsWith('/SKILL.md'))
|
|
307
|
+
return [];
|
|
308
|
+
return [
|
|
309
|
+
skillRecord(identity, skillNameFromPath(targetFile), 'model', {
|
|
310
|
+
skill_path: targetFile,
|
|
311
|
+
args_raw: maybeArgsRaw('grok', 'read_file', n.toolArgs) ?? null,
|
|
312
|
+
args_digest: argsDigest(n.toolArgs),
|
|
313
|
+
started_at: n.ts ?? null,
|
|
314
|
+
}),
|
|
315
|
+
];
|
|
316
|
+
}
|
|
317
|
+
// ---------------------------------------------------------------------------
|
|
57
318
|
// Source-specific helpers
|
|
58
319
|
// ---------------------------------------------------------------------------
|
|
59
320
|
// Launch provenance (`spur-run` vs `ambient`) is a fact only the import host knows:
|
|
@@ -212,7 +473,7 @@ export function maybeArgsRaw(_source, toolName, args) {
|
|
|
212
473
|
// Claude mapper
|
|
213
474
|
// ---------------------------------------------------------------------------
|
|
214
475
|
/** Map a Claude Code JSONL record into one or more ETL split entries. */
|
|
215
|
-
export function claudeSplit(raw) {
|
|
476
|
+
export function claudeSplit(raw, context) {
|
|
216
477
|
const entries = [];
|
|
217
478
|
const sessionId = s(raw.sessionId, raw.conversation_uuid) ?? 'unknown';
|
|
218
479
|
const seq = typeof raw.seq === 'number' ? raw.seq : typeof raw.messageIndex === 'number' ? raw.messageIndex : 0;
|
|
@@ -316,6 +577,10 @@ export function claudeSplit(raw) {
|
|
|
316
577
|
}
|
|
317
578
|
}
|
|
318
579
|
}
|
|
580
|
+
// Skill-load rows (0736): claude's L1 is the native Skill tool_use; L0/L2 never trigger.
|
|
581
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
582
|
+
entries.push(skillCallEntry(record));
|
|
583
|
+
}
|
|
319
584
|
return entries;
|
|
320
585
|
}
|
|
321
586
|
// ---------------------------------------------------------------------------
|
|
@@ -429,6 +694,10 @@ export function piSplit(raw, context) {
|
|
|
429
694
|
});
|
|
430
695
|
}
|
|
431
696
|
}
|
|
697
|
+
// Skill-load rows (0736): pi is inline-only — the user-message wrapper is the sole trigger.
|
|
698
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
699
|
+
entries.push(skillCallEntry(record));
|
|
700
|
+
}
|
|
432
701
|
return entries;
|
|
433
702
|
}
|
|
434
703
|
/**
|
|
@@ -552,6 +821,10 @@ export function ompSplit(raw, context) {
|
|
|
552
821
|
});
|
|
553
822
|
}
|
|
554
823
|
}
|
|
824
|
+
// Skill-load rows (0736): omp's L1 is the native Skill toolCall; the L2 wrapper never triggers.
|
|
825
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
826
|
+
entries.push(skillCallEntry(record));
|
|
827
|
+
}
|
|
555
828
|
return entries;
|
|
556
829
|
}
|
|
557
830
|
/**
|
|
@@ -824,6 +1097,10 @@ export function codexSplit(raw, context) {
|
|
|
824
1097
|
},
|
|
825
1098
|
});
|
|
826
1099
|
}
|
|
1100
|
+
// Skill-load rows (0736): codex has no native load call — the child-element block is the trigger.
|
|
1101
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1102
|
+
entries.push(skillCallEntry(record));
|
|
1103
|
+
}
|
|
827
1104
|
return entries;
|
|
828
1105
|
}
|
|
829
1106
|
// ---------------------------------------------------------------------------
|
|
@@ -955,6 +1232,10 @@ export function agySplit(raw, context) {
|
|
|
955
1232
|
});
|
|
956
1233
|
}
|
|
957
1234
|
}
|
|
1235
|
+
// Skill-load rows (0736): agy's L1 is the view_file "Viewing skill file" tool call.
|
|
1236
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1237
|
+
entries.push(skillCallEntry(record));
|
|
1238
|
+
}
|
|
958
1239
|
return entries;
|
|
959
1240
|
}
|
|
960
1241
|
// ---------------------------------------------------------------------------
|
|
@@ -1037,6 +1318,11 @@ export function geminiSplit(raw, context) {
|
|
|
1037
1318
|
});
|
|
1038
1319
|
}
|
|
1039
1320
|
}
|
|
1321
|
+
// Skill-load rows (0736): gemini has no verified L1 — the L0 prefix in a user message triggers.
|
|
1322
|
+
// messageSplitIndex stays the literal 0, matching the gemini tool-call linkage above.
|
|
1323
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex: 0 })) {
|
|
1324
|
+
entries.push(skillCallEntry(record));
|
|
1325
|
+
}
|
|
1040
1326
|
return entries;
|
|
1041
1327
|
}
|
|
1042
1328
|
const UUID_PATTERN = '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
|
|
@@ -1075,7 +1361,7 @@ function sessionIdFromContext(context, raw) {
|
|
|
1075
1361
|
return s(raw.sessionId, raw.id) ?? 'unknown';
|
|
1076
1362
|
}
|
|
1077
1363
|
function geminiContent(raw) {
|
|
1078
|
-
const content = extractContentText(raw.content);
|
|
1364
|
+
const content = extractContentText(raw.content) ?? s(raw.text);
|
|
1079
1365
|
const thoughts = Array.isArray(raw.thoughts)
|
|
1080
1366
|
? raw.thoughts
|
|
1081
1367
|
.map((value) => (value !== null && typeof value === 'object' ? s(o(value).description) : undefined))
|
|
@@ -1222,7 +1508,7 @@ const GROK_META_TYPES = new Set([
|
|
|
1222
1508
|
'yolo_toggled',
|
|
1223
1509
|
]);
|
|
1224
1510
|
/** Map a Grok JSONL record into one or more ETL split entries. */
|
|
1225
|
-
export function grokSplit(raw) {
|
|
1511
|
+
export function grokSplit(raw, context) {
|
|
1226
1512
|
const entries = [];
|
|
1227
1513
|
const n = normalizeGrokRecord(raw);
|
|
1228
1514
|
const { recordType, sessionId, ts, seq } = n;
|
|
@@ -1385,6 +1671,10 @@ export function grokSplit(raw) {
|
|
|
1385
1671
|
error_text: n.errorText,
|
|
1386
1672
|
},
|
|
1387
1673
|
});
|
|
1674
|
+
// Skill-load rows (0736): grok's L1 is a grok_build read_file targeting SKILL.md.
|
|
1675
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1676
|
+
entries.push(skillCallEntry(record));
|
|
1677
|
+
}
|
|
1388
1678
|
return entries;
|
|
1389
1679
|
}
|
|
1390
1680
|
if (recordType === 'user' ||
|
|
@@ -1601,19 +1891,19 @@ export function stableFieldShape(raw) {
|
|
|
1601
1891
|
// Identity field maps for the six source mappers
|
|
1602
1892
|
// ---------------------------------------------------------------------------
|
|
1603
1893
|
/** Identity field map for the Claude mapper. */
|
|
1604
|
-
export const CLAUDE_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1894
|
+
export const CLAUDE_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1605
1895
|
/** Identity field map for the Pi mapper. */
|
|
1606
|
-
export const PI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1896
|
+
export const PI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1607
1897
|
/** Identity field map for the OMP mapper. */
|
|
1608
|
-
export const OMP_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1898
|
+
export const OMP_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1609
1899
|
/** Identity field map for the Codex mapper. */
|
|
1610
|
-
export const CODEX_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1900
|
+
export const CODEX_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1611
1901
|
/** Identity field map for the AGY mapper. */
|
|
1612
|
-
export const AGY_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1902
|
+
export const AGY_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1613
1903
|
/** Identity field map for the Grok mapper. */
|
|
1614
|
-
export const GROK_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1904
|
+
export const GROK_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1615
1905
|
/** Identity field map for the Gemini mapper. */
|
|
1616
|
-
export const GEMINI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
1906
|
+
export const GEMINI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1617
1907
|
// ---------------------------------------------------------------------------
|
|
1618
1908
|
// Zod schemas for the six source mappers
|
|
1619
1909
|
// ---------------------------------------------------------------------------
|
|
@@ -197,6 +197,41 @@ function prepareEntries(row, data, parts, sourceFile, redactionRules) {
|
|
|
197
197
|
const output = stringValue(state.output);
|
|
198
198
|
const status = stringValue(state.status) ?? 'unknown';
|
|
199
199
|
const splitIndex = entries.length;
|
|
200
|
+
const toolName = stringValue(part.tool) ?? 'unknown';
|
|
201
|
+
// 0736: OpenCode's native `skill({name})` load tool is the skill-call trigger; it gets a
|
|
202
|
+
// history_skill_call row instead of a tool-call row (one row per load, same provenance).
|
|
203
|
+
if (toolName === 'skill') {
|
|
204
|
+
const input = objectValue(state.input);
|
|
205
|
+
const skillName = stringValue(input.name);
|
|
206
|
+
if (skillName !== undefined) {
|
|
207
|
+
const skillRecord = redactRecord({
|
|
208
|
+
message_hash: messageHash,
|
|
209
|
+
source: SOURCE,
|
|
210
|
+
source_file: sourceFile,
|
|
211
|
+
source_line: 1,
|
|
212
|
+
session_id: row.session_id,
|
|
213
|
+
seq: started ?? created,
|
|
214
|
+
skill_name: skillName,
|
|
215
|
+
invocation_kind: 'model',
|
|
216
|
+
skill_path: null,
|
|
217
|
+
args_raw: maybeArgsRaw(SOURCE, 'skill', state.input) ?? null,
|
|
218
|
+
args_digest: sha256(state.input ?? null),
|
|
219
|
+
status,
|
|
220
|
+
started_at: started === undefined ? null : isoTime(started),
|
|
221
|
+
completed_at: completedAt === undefined ? null : isoTime(completedAt),
|
|
222
|
+
duration_ms: started === undefined || completedAt === undefined
|
|
223
|
+
? null
|
|
224
|
+
: Math.max(0, completedAt - started),
|
|
225
|
+
}, redactionRules);
|
|
226
|
+
entries.push({
|
|
227
|
+
targetTable: 'history_skill_call',
|
|
228
|
+
splitIndex,
|
|
229
|
+
record: skillRecord,
|
|
230
|
+
recordHash: recordHash(sourceFile, splitIndex, skillRecord),
|
|
231
|
+
});
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
200
235
|
const toolRecord = redactRecord({
|
|
201
236
|
message_hash: messageHash,
|
|
202
237
|
source: SOURCE,
|
|
@@ -204,7 +239,7 @@ function prepareEntries(row, data, parts, sourceFile, redactionRules) {
|
|
|
204
239
|
source_line: 1,
|
|
205
240
|
session_id: row.session_id,
|
|
206
241
|
seq: started ?? created,
|
|
207
|
-
tool_name:
|
|
242
|
+
tool_name: toolName,
|
|
208
243
|
args_raw: maybeArgsRaw(SOURCE, stringValue(part.tool) ?? 'unknown', state.input),
|
|
209
244
|
args_digest: sha256(state.input ?? null),
|
|
210
245
|
status,
|
package/dist/types.d.ts
CHANGED
|
@@ -128,6 +128,27 @@ export interface ImportResult {
|
|
|
128
128
|
* load tool); `skill_path` is nullable because some producers inline the skill body without
|
|
129
129
|
* a resolvable path.
|
|
130
130
|
*/
|
|
131
|
+
/**
|
|
132
|
+
* Split-time skill-load record routed to `history_skill_call` (0736). The importer/DAO manage
|
|
133
|
+
* `record_hash`, `message_hash` (resolved from `_messageSplitIndex`), the source identity
|
|
134
|
+
* columns, and `imported_at`; keeping them out of the split record also keeps them out of the
|
|
135
|
+
* record_hash input, so re-imports hash identically (0736 R5 idempotency).
|
|
136
|
+
*/
|
|
137
|
+
export interface SkillCallSplitRecord {
|
|
138
|
+
readonly _messageSplitIndex?: number;
|
|
139
|
+
readonly session_id: string;
|
|
140
|
+
readonly seq: number;
|
|
141
|
+
readonly skill_name: string;
|
|
142
|
+
readonly invocation_kind: 'user' | 'model';
|
|
143
|
+
readonly skill_path?: string | null;
|
|
144
|
+
readonly args_raw?: string | null;
|
|
145
|
+
readonly args_digest?: string | null;
|
|
146
|
+
readonly call_id?: string | null;
|
|
147
|
+
readonly status?: string | null;
|
|
148
|
+
readonly started_at?: string | null;
|
|
149
|
+
readonly completed_at?: string | null;
|
|
150
|
+
readonly duration_ms?: number | null;
|
|
151
|
+
}
|
|
131
152
|
export interface SkillCall {
|
|
132
153
|
readonly record_hash: string;
|
|
133
154
|
readonly message_hash: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-llm-jsonl-importer",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.54",
|
|
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.4.
|
|
51
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
52
|
-
"@gobing-ai/ts-utils": "^0.4.
|
|
50
|
+
"@gobing-ai/ts-db": "^0.4.54",
|
|
51
|
+
"@gobing-ai/ts-runtime": "^0.4.54",
|
|
52
|
+
"@gobing-ai/ts-utils": "^0.4.54",
|
|
53
53
|
"zod": "^4.1.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,13 @@ export { HistoryImportError } from './errors';
|
|
|
2
2
|
export { sha256, stableJson } from './hash';
|
|
3
3
|
export { runJsonlImport } from './importer';
|
|
4
4
|
export { applyHistoryImportSchema, normalizeSourceFilePaths } from './jsonl-importer-dao';
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
canonicalizeSkillName,
|
|
7
|
+
extractSkillCalls,
|
|
8
|
+
type SkillCallIdentity,
|
|
9
|
+
sessionIdFromSourcePath,
|
|
10
|
+
skillCallEntry,
|
|
11
|
+
} from './mappers';
|
|
6
12
|
export { type OpenCodeImportOptions, runOpenCodeImport } from './opencode-importer';
|
|
7
13
|
export { DEFAULT_REDACTION_RULES, redactRecord, redactValue } from './redaction';
|
|
8
14
|
export { HISTORY_IMPORT_SCHEMA_SQL } from './schema-sql';
|
|
@@ -24,6 +30,7 @@ export type {
|
|
|
24
30
|
ReconcileSummary,
|
|
25
31
|
RedactionRule,
|
|
26
32
|
SkillCall,
|
|
33
|
+
SkillCallSplitRecord,
|
|
27
34
|
SourceDefinition,
|
|
28
35
|
SplitConfig,
|
|
29
36
|
SplitEntry,
|
|
@@ -667,7 +667,7 @@ export interface OpenCodeExistingEntry {
|
|
|
667
667
|
|
|
668
668
|
/** Normalized OpenCode entry awaiting a history-table write. */
|
|
669
669
|
export interface OpenCodeQueuedEntry {
|
|
670
|
-
targetTable: 'history_message' | 'history_tool_call';
|
|
670
|
+
targetTable: 'history_message' | 'history_tool_call' | 'history_skill_call';
|
|
671
671
|
splitIndex: number;
|
|
672
672
|
record: JsonObject;
|
|
673
673
|
recordHash: string;
|
|
@@ -752,7 +752,7 @@ export function openCodeBulkWriteOperations(
|
|
|
752
752
|
): DbBatchOp[] {
|
|
753
753
|
const importedAt = timestamp(now);
|
|
754
754
|
const operations: DbBatchOp[] = [];
|
|
755
|
-
for (const table of ['history_message', 'history_tool_call'] as const) {
|
|
755
|
+
for (const table of ['history_message', 'history_tool_call', 'history_skill_call'] as const) {
|
|
756
756
|
const tableEntries = entries.filter((entry) => entry.targetTable === table);
|
|
757
757
|
for (let offset = 0; offset < tableEntries.length; offset += 100) {
|
|
758
758
|
const chunk = tableEntries.slice(offset, offset + 100);
|
package/src/mappers.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { sha256 } from './hash';
|
|
3
|
-
import type { JsonObject, SplitEntry, TransformContext } from './types';
|
|
3
|
+
import type { JsonObject, SkillCallSplitRecord, SplitEntry, TransformContext } from './types';
|
|
4
4
|
|
|
5
5
|
// ---------------------------------------------------------------------------
|
|
6
6
|
// Helper: identity field map for typed columns
|
|
@@ -50,6 +50,23 @@ const TOOL_CALL_MAPPER_KEYS: readonly string[] = [
|
|
|
50
50
|
'error_text',
|
|
51
51
|
];
|
|
52
52
|
|
|
53
|
+
/** Columns the mapper may produce for history_skill_call (0736). */
|
|
54
|
+
const SKILL_CALL_MAPPER_KEYS: readonly string[] = [
|
|
55
|
+
'_messageSplitIndex',
|
|
56
|
+
'session_id',
|
|
57
|
+
'seq',
|
|
58
|
+
'skill_name',
|
|
59
|
+
'invocation_kind',
|
|
60
|
+
'skill_path',
|
|
61
|
+
'args_raw',
|
|
62
|
+
'args_digest',
|
|
63
|
+
'call_id',
|
|
64
|
+
'status',
|
|
65
|
+
'started_at',
|
|
66
|
+
'completed_at',
|
|
67
|
+
'duration_ms',
|
|
68
|
+
];
|
|
69
|
+
|
|
53
70
|
/** Build an identity fieldMap for the given column list. */
|
|
54
71
|
function identityFieldMap(keys: readonly string[]): Record<string, string> {
|
|
55
72
|
const map: Record<string, string> = {};
|
|
@@ -59,6 +76,261 @@ function identityFieldMap(keys: readonly string[]): Record<string, string> {
|
|
|
59
76
|
return map;
|
|
60
77
|
}
|
|
61
78
|
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Skill-load extraction (0736)
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
/** Harness skill packages whose dialect spelling swaps ':' for '-' (storm report §10.1). */
|
|
84
|
+
const HARNESS_SKILL_PACKAGES = new Set(['sp', 'rd3']);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Canonicalize a harness skill name: `sp-dev-run` / `$sp-dev-run` / `/skill:sp-dev-run` →
|
|
88
|
+
* `sp:dev-run`; `rd3-*` → `rd3:*`. Only the frozen harness package set is rewritten — an
|
|
89
|
+
* unqualified name like `code-review` is kept verbatim (exact structural match, 0736 R4).
|
|
90
|
+
*/
|
|
91
|
+
export function canonicalizeSkillName(raw: string): string {
|
|
92
|
+
let name = raw.trim();
|
|
93
|
+
if (name.startsWith('/') || name.startsWith('$')) name = name.slice(1);
|
|
94
|
+
if (name.startsWith('skill:')) name = name.slice('skill:'.length);
|
|
95
|
+
const canonical = name.match(/^([a-z][a-z0-9]*):([a-z0-9-]+)$/);
|
|
96
|
+
if (canonical !== null && HARNESS_SKILL_PACKAGES.has(canonical[1] ?? '')) return name;
|
|
97
|
+
const dialect = name.match(/^([a-z][a-z0-9]*)-([a-z0-9-]+)$/);
|
|
98
|
+
if (dialect !== null && HARNESS_SKILL_PACKAGES.has(dialect[1] ?? '')) return `${dialect[1]}:${dialect[2]}`;
|
|
99
|
+
return name;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Identity fields a split already computed for its parent message (skill rows join it). */
|
|
103
|
+
export interface SkillCallIdentity {
|
|
104
|
+
readonly sessionId: string;
|
|
105
|
+
readonly seq: number;
|
|
106
|
+
/** Split index of the parent message entry in the same split batch (_messageSplitIndex). */
|
|
107
|
+
readonly messageSplitIndex: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Detect skill-load events in one raw source record (0736 R1/R2). Dispatches on the source in
|
|
112
|
+
* the transform context; unknown sources return nothing. Detection signatures per source are
|
|
113
|
+
* the verified ones from the storm report §10.3:
|
|
114
|
+
*
|
|
115
|
+
* - L1 native load tool is authoritative (claude/omp `Skill`, agy `view_file` skill reads,
|
|
116
|
+
* grok `read_file` on SKILL.md, opencode native `skill`).
|
|
117
|
+
* - Sources with no L1 trigger on their structural signal: pi's `<skill name= location=>`
|
|
118
|
+
* wrapper, codex's `<skill><name>/<path>` block, gemini's L0 harness prefix.
|
|
119
|
+
* - L0/L2 never trigger for agents that have an L1 (false-positive suppression, 0736 R4).
|
|
120
|
+
*/
|
|
121
|
+
export function extractSkillCalls(
|
|
122
|
+
raw: JsonObject,
|
|
123
|
+
context: TransformContext | undefined,
|
|
124
|
+
identity: SkillCallIdentity,
|
|
125
|
+
): readonly SkillCallSplitRecord[] {
|
|
126
|
+
switch (context?.source) {
|
|
127
|
+
case 'claude':
|
|
128
|
+
return detectClaudeSkillCalls(raw, identity);
|
|
129
|
+
case 'pi':
|
|
130
|
+
return detectPiSkillCalls(raw, identity);
|
|
131
|
+
case 'omp':
|
|
132
|
+
return detectOmpSkillCalls(raw, identity);
|
|
133
|
+
case 'codex':
|
|
134
|
+
return detectCodexSkillCalls(raw, identity);
|
|
135
|
+
case 'agy':
|
|
136
|
+
return detectAgySkillCalls(raw, identity);
|
|
137
|
+
case 'gemini':
|
|
138
|
+
return detectGeminiSkillCalls(raw, identity);
|
|
139
|
+
case 'grok':
|
|
140
|
+
return detectGrokSkillCalls(raw, identity);
|
|
141
|
+
default:
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Route one skill-load row to `history_skill_call` exactly like tool calls route to
|
|
148
|
+
* `history_tool_call`: a SplitEntry whose record the importer normalizes, hashes, dedups,
|
|
149
|
+
* and inserts through the typed-column path.
|
|
150
|
+
*/
|
|
151
|
+
export function skillCallEntry(record: SkillCallSplitRecord): SplitEntry {
|
|
152
|
+
// The split record's keys are exactly the history_skill_call typed columns; the index
|
|
153
|
+
// signature is supplied at this boundary (runtime shape is JSON-compatible by construction).
|
|
154
|
+
return { targetTable: 'history_skill_call', record: record as unknown as JsonObject };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Build a fully-populated skill row: every optional column set explicitly for hash stability. */
|
|
158
|
+
function skillRecord(
|
|
159
|
+
identity: SkillCallIdentity,
|
|
160
|
+
skillName: string,
|
|
161
|
+
invocationKind: 'user' | 'model',
|
|
162
|
+
extra: Partial<SkillCallSplitRecord> = {},
|
|
163
|
+
): SkillCallSplitRecord {
|
|
164
|
+
return {
|
|
165
|
+
_messageSplitIndex: identity.messageSplitIndex,
|
|
166
|
+
session_id: identity.sessionId,
|
|
167
|
+
seq: identity.seq,
|
|
168
|
+
skill_name: canonicalizeSkillName(skillName),
|
|
169
|
+
invocation_kind: invocationKind,
|
|
170
|
+
skill_path: null,
|
|
171
|
+
args_raw: null,
|
|
172
|
+
args_digest: null,
|
|
173
|
+
call_id: null,
|
|
174
|
+
status: 'ok',
|
|
175
|
+
started_at: null,
|
|
176
|
+
completed_at: null,
|
|
177
|
+
duration_ms: null,
|
|
178
|
+
...extra,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Skill name from a `.../skills/<name>/SKILL.md` path; falls back to the SKILL.md sibling. */
|
|
183
|
+
function skillNameFromPath(path: string): string {
|
|
184
|
+
const normalized = path.replace(/\\/g, '/');
|
|
185
|
+
const bySkillsSegment = normalized.match(/\/skills\/([^/]+)\/SKILL\.md$/i);
|
|
186
|
+
if (bySkillsSegment !== null) return bySkillsSegment[1] ?? '';
|
|
187
|
+
const stem = normalized.slice(0, normalized.length - '/SKILL.md'.length);
|
|
188
|
+
return stem.split('/').pop() ?? stem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function detectClaudeSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
192
|
+
const contentBlocks = raw.content ?? o(raw.message).content;
|
|
193
|
+
if (!Array.isArray(contentBlocks)) return [];
|
|
194
|
+
const rows: SkillCallSplitRecord[] = [];
|
|
195
|
+
for (const block of contentBlocks) {
|
|
196
|
+
if (typeof block !== 'object' || block === null) continue;
|
|
197
|
+
const b = block as Record<string, unknown>;
|
|
198
|
+
if (b.type !== 'tool_use' || b.name !== 'Skill') continue;
|
|
199
|
+
const input = (b.input ?? {}) as Record<string, unknown>;
|
|
200
|
+
const skill = s(input.skill);
|
|
201
|
+
if (skill === undefined) continue;
|
|
202
|
+
// caller.type "direct" = user-invoked (storm report §10.3); absence = model-invoked.
|
|
203
|
+
rows.push(
|
|
204
|
+
skillRecord(identity, skill, s(o(b.caller).type) === 'direct' ? 'user' : 'model', {
|
|
205
|
+
args_raw: maybeArgsRaw('claude', 'Skill', input) ?? null,
|
|
206
|
+
args_digest: argsDigest(input),
|
|
207
|
+
call_id: s(b.id) ?? null,
|
|
208
|
+
}),
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return rows;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** pi is inline-only: the `<skill name= location=>` wrapper in a user message is the sole trigger. */
|
|
215
|
+
const PI_SKILL_WRAPPER = /<skill\s+name="([^"]+)"(?:\s+location="([^"]*)")?\s*>/g;
|
|
216
|
+
|
|
217
|
+
function detectPiSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
218
|
+
const msg = raw.message as Record<string, unknown> | undefined;
|
|
219
|
+
if (piRole(msg?.role ?? raw.role ?? raw.recordType ?? raw.type) !== 'user') return [];
|
|
220
|
+
const text = extractContentText(msg?.content ?? raw.content);
|
|
221
|
+
if (text === undefined) return [];
|
|
222
|
+
const rows: SkillCallSplitRecord[] = [];
|
|
223
|
+
for (const match of text.matchAll(PI_SKILL_WRAPPER)) {
|
|
224
|
+
rows.push(skillRecord(identity, match[1] ?? '', 'user', { skill_path: match[2] || null }));
|
|
225
|
+
}
|
|
226
|
+
return rows;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function detectOmpSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
230
|
+
const msg = raw.message as Record<string, unknown> | undefined;
|
|
231
|
+
if (mapRole(msg?.role ?? raw.type ?? raw.role) !== 'assistant') return [];
|
|
232
|
+
const contentBlocks = msg?.content ?? raw.content;
|
|
233
|
+
if (!Array.isArray(contentBlocks)) return [];
|
|
234
|
+
const rows: SkillCallSplitRecord[] = [];
|
|
235
|
+
for (const block of contentBlocks as Record<string, unknown>[]) {
|
|
236
|
+
const call = normalizeOmpToolCall(block);
|
|
237
|
+
if (call === null || call.name !== 'Skill') continue;
|
|
238
|
+
const input = call.input ?? call.arguments;
|
|
239
|
+
const skill = s((input as Record<string, unknown> | undefined)?.skill);
|
|
240
|
+
if (skill === undefined) continue;
|
|
241
|
+
rows.push(
|
|
242
|
+
skillRecord(identity, skill, 'model', {
|
|
243
|
+
args_raw: maybeArgsRaw('omp', 'Skill', input) ?? null,
|
|
244
|
+
args_digest: argsDigest(input),
|
|
245
|
+
call_id: s(call.id) ?? null,
|
|
246
|
+
}),
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
return rows;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** Codex has no native load tool call: the child-element `<skill>` block is the trigger. */
|
|
253
|
+
const CODEX_SKILL_BLOCK = /<skill>\s*<name>([^<]+)<\/name>\s*<path>([^<]+)<\/path>\s*<\/skill>/g;
|
|
254
|
+
|
|
255
|
+
function detectCodexSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
256
|
+
const payload = (raw.payload ?? raw) as Record<string, unknown>;
|
|
257
|
+
const recordType = String(raw.type ?? '');
|
|
258
|
+
const payloadType = String(payload.type ?? '');
|
|
259
|
+
let role: string;
|
|
260
|
+
if (recordType === 'response_item') {
|
|
261
|
+
role =
|
|
262
|
+
payloadType === 'message' ? mapRole(payload.role) : payloadType === 'agent_message' ? 'assistant' : 'meta';
|
|
263
|
+
} else if (recordType === 'user' || recordType === 'assistant') {
|
|
264
|
+
role = mapRole(recordType);
|
|
265
|
+
} else if (recordType === 'message') {
|
|
266
|
+
role = mapRole(raw.role ?? payload.role);
|
|
267
|
+
} else {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
if (role !== 'user') return [];
|
|
271
|
+
const text = extractContentText(payload.content ?? raw.content) ?? s(payload.text, raw.text);
|
|
272
|
+
if (text === undefined) return [];
|
|
273
|
+
const rows: SkillCallSplitRecord[] = [];
|
|
274
|
+
for (const match of text.matchAll(CODEX_SKILL_BLOCK)) {
|
|
275
|
+
rows.push(skillRecord(identity, match[1] ?? '', 'user', { skill_path: match[2] ?? null }));
|
|
276
|
+
}
|
|
277
|
+
return rows;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** agy loads skills via `view_file` with toolAction "Viewing skill file" on a SKILL.md path. */
|
|
281
|
+
function detectAgySkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
282
|
+
if (String(raw.type ?? '') !== 'PLANNER_RESPONSE' || !Array.isArray(raw.tool_calls)) return [];
|
|
283
|
+
const rows: SkillCallSplitRecord[] = [];
|
|
284
|
+
for (const tc of raw.tool_calls as Record<string, unknown>[]) {
|
|
285
|
+
const tool = s(tc.name, tc.tool_name);
|
|
286
|
+
if (tool !== 'view_file') continue;
|
|
287
|
+
const args = (tc.args ?? tc.arguments ?? {}) as Record<string, unknown>;
|
|
288
|
+
if (args.toolAction !== 'Viewing skill file') continue;
|
|
289
|
+
const path = s(args.AbsolutePath, args.absolute_path);
|
|
290
|
+
if (path === undefined || !path.replace(/\\/g, '/').endsWith('/SKILL.md')) continue;
|
|
291
|
+
const summary = s(args.toolSummary);
|
|
292
|
+
const skillName = summary?.match(/SKILL\.md for (.+)$/)?.[1] ?? skillNameFromPath(path);
|
|
293
|
+
rows.push(
|
|
294
|
+
skillRecord(identity, skillName, 'model', {
|
|
295
|
+
skill_path: path,
|
|
296
|
+
args_raw: maybeArgsRaw('agy', 'view_file', args) ?? null,
|
|
297
|
+
args_digest: argsDigest(args),
|
|
298
|
+
}),
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
return rows;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** Gemini has no verified L1: the L0 harness prefix in a user message is the trigger. */
|
|
305
|
+
const GEMINI_L0_PREFIX = /^\s*\/((?:sp|rd3)-[a-z0-9-]+)/;
|
|
306
|
+
|
|
307
|
+
function detectGeminiSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
308
|
+
if (String(raw.type ?? '') !== 'user') return [];
|
|
309
|
+
const content = geminiContent(raw);
|
|
310
|
+
if (content === null) return [];
|
|
311
|
+
const match = content.match(GEMINI_L0_PREFIX);
|
|
312
|
+
if (match === null) return [];
|
|
313
|
+
return [skillRecord(identity, match[1] ?? '', 'user')];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** grok loads skills via `read_file` (grok_build namespace) targeting a SKILL.md path. */
|
|
317
|
+
function detectGrokSkillCalls(raw: JsonObject, identity: SkillCallIdentity): readonly SkillCallSplitRecord[] {
|
|
318
|
+
const n = normalizeGrokRecord(raw);
|
|
319
|
+
if (n.recordType !== 'tool_call' || n.toolName !== 'read_file') return [];
|
|
320
|
+
const meta = (n.body._meta ?? raw._meta ?? {}) as Record<string, unknown>;
|
|
321
|
+
if (o(meta['x.ai/tool']).namespace !== 'grok_build') return [];
|
|
322
|
+
const targetFile = s(o(n.toolArgs).target_file);
|
|
323
|
+
if (targetFile === undefined || !targetFile.replace(/\\/g, '/').endsWith('/SKILL.md')) return [];
|
|
324
|
+
return [
|
|
325
|
+
skillRecord(identity, skillNameFromPath(targetFile), 'model', {
|
|
326
|
+
skill_path: targetFile,
|
|
327
|
+
args_raw: maybeArgsRaw('grok', 'read_file', n.toolArgs) ?? null,
|
|
328
|
+
args_digest: argsDigest(n.toolArgs),
|
|
329
|
+
started_at: n.ts ?? null,
|
|
330
|
+
}),
|
|
331
|
+
];
|
|
332
|
+
}
|
|
333
|
+
|
|
62
334
|
// ---------------------------------------------------------------------------
|
|
63
335
|
// Source-specific helpers
|
|
64
336
|
// ---------------------------------------------------------------------------
|
|
@@ -231,7 +503,7 @@ export function maybeArgsRaw(_source: string, toolName: string, args: unknown):
|
|
|
231
503
|
// ---------------------------------------------------------------------------
|
|
232
504
|
|
|
233
505
|
/** Map a Claude Code JSONL record into one or more ETL split entries. */
|
|
234
|
-
export function claudeSplit(raw: Record<string, unknown
|
|
506
|
+
export function claudeSplit(raw: Record<string, unknown>, context?: TransformContext): readonly SplitEntry[] {
|
|
235
507
|
const entries: SplitEntry[] = [];
|
|
236
508
|
const sessionId = s(raw.sessionId, raw.conversation_uuid) ?? 'unknown';
|
|
237
509
|
const seq = typeof raw.seq === 'number' ? raw.seq : typeof raw.messageIndex === 'number' ? raw.messageIndex : 0;
|
|
@@ -344,6 +616,11 @@ export function claudeSplit(raw: Record<string, unknown>): readonly SplitEntry[]
|
|
|
344
616
|
}
|
|
345
617
|
}
|
|
346
618
|
|
|
619
|
+
// Skill-load rows (0736): claude's L1 is the native Skill tool_use; L0/L2 never trigger.
|
|
620
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
621
|
+
entries.push(skillCallEntry(record));
|
|
622
|
+
}
|
|
623
|
+
|
|
347
624
|
return entries;
|
|
348
625
|
}
|
|
349
626
|
|
|
@@ -466,6 +743,11 @@ export function piSplit(raw: Record<string, unknown>, context?: TransformContext
|
|
|
466
743
|
}
|
|
467
744
|
}
|
|
468
745
|
|
|
746
|
+
// Skill-load rows (0736): pi is inline-only — the user-message wrapper is the sole trigger.
|
|
747
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
748
|
+
entries.push(skillCallEntry(record));
|
|
749
|
+
}
|
|
750
|
+
|
|
469
751
|
return entries;
|
|
470
752
|
}
|
|
471
753
|
|
|
@@ -597,6 +879,11 @@ export function ompSplit(raw: Record<string, unknown>, context?: TransformContex
|
|
|
597
879
|
}
|
|
598
880
|
}
|
|
599
881
|
|
|
882
|
+
// Skill-load rows (0736): omp's L1 is the native Skill toolCall; the L2 wrapper never triggers.
|
|
883
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
884
|
+
entries.push(skillCallEntry(record));
|
|
885
|
+
}
|
|
886
|
+
|
|
600
887
|
return entries;
|
|
601
888
|
}
|
|
602
889
|
|
|
@@ -908,6 +1195,11 @@ export function codexSplit(raw: Record<string, unknown>, context?: TransformCont
|
|
|
908
1195
|
});
|
|
909
1196
|
}
|
|
910
1197
|
|
|
1198
|
+
// Skill-load rows (0736): codex has no native load call — the child-element block is the trigger.
|
|
1199
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1200
|
+
entries.push(skillCallEntry(record));
|
|
1201
|
+
}
|
|
1202
|
+
|
|
911
1203
|
return entries;
|
|
912
1204
|
}
|
|
913
1205
|
|
|
@@ -1046,6 +1338,11 @@ export function agySplit(raw: Record<string, unknown>, context?: TransformContex
|
|
|
1046
1338
|
}
|
|
1047
1339
|
}
|
|
1048
1340
|
|
|
1341
|
+
// Skill-load rows (0736): agy's L1 is the view_file "Viewing skill file" tool call.
|
|
1342
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1343
|
+
entries.push(skillCallEntry(record));
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1049
1346
|
return entries;
|
|
1050
1347
|
}
|
|
1051
1348
|
|
|
@@ -1134,6 +1431,12 @@ export function geminiSplit(raw: Record<string, unknown>, context?: TransformCon
|
|
|
1134
1431
|
}
|
|
1135
1432
|
}
|
|
1136
1433
|
|
|
1434
|
+
// Skill-load rows (0736): gemini has no verified L1 — the L0 prefix in a user message triggers.
|
|
1435
|
+
// messageSplitIndex stays the literal 0, matching the gemini tool-call linkage above.
|
|
1436
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex: 0 })) {
|
|
1437
|
+
entries.push(skillCallEntry(record));
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1137
1440
|
return entries;
|
|
1138
1441
|
}
|
|
1139
1442
|
|
|
@@ -1175,7 +1478,7 @@ function sessionIdFromContext(context: TransformContext | undefined, raw: Record
|
|
|
1175
1478
|
}
|
|
1176
1479
|
|
|
1177
1480
|
function geminiContent(raw: Record<string, unknown>): string | null {
|
|
1178
|
-
const content = extractContentText(raw.content);
|
|
1481
|
+
const content = extractContentText(raw.content) ?? s(raw.text);
|
|
1179
1482
|
const thoughts = Array.isArray(raw.thoughts)
|
|
1180
1483
|
? raw.thoughts
|
|
1181
1484
|
.map((value) => (value !== null && typeof value === 'object' ? s(o(value).description) : undefined))
|
|
@@ -1358,7 +1661,7 @@ const GROK_META_TYPES = new Set([
|
|
|
1358
1661
|
]);
|
|
1359
1662
|
|
|
1360
1663
|
/** Map a Grok JSONL record into one or more ETL split entries. */
|
|
1361
|
-
export function grokSplit(raw: Record<string, unknown
|
|
1664
|
+
export function grokSplit(raw: Record<string, unknown>, context?: TransformContext): readonly SplitEntry[] {
|
|
1362
1665
|
const entries: SplitEntry[] = [];
|
|
1363
1666
|
const n = normalizeGrokRecord(raw);
|
|
1364
1667
|
const { recordType, sessionId, ts, seq } = n;
|
|
@@ -1527,6 +1830,10 @@ export function grokSplit(raw: Record<string, unknown>): readonly SplitEntry[] {
|
|
|
1527
1830
|
error_text: n.errorText,
|
|
1528
1831
|
},
|
|
1529
1832
|
});
|
|
1833
|
+
// Skill-load rows (0736): grok's L1 is a grok_build read_file targeting SKILL.md.
|
|
1834
|
+
for (const record of extractSkillCalls(raw, context, { sessionId, seq, messageSplitIndex })) {
|
|
1835
|
+
entries.push(skillCallEntry(record));
|
|
1836
|
+
}
|
|
1530
1837
|
return entries;
|
|
1531
1838
|
}
|
|
1532
1839
|
|
|
@@ -1753,19 +2060,31 @@ export function stableFieldShape(raw: JsonObject): string {
|
|
|
1753
2060
|
// ---------------------------------------------------------------------------
|
|
1754
2061
|
|
|
1755
2062
|
/** Identity field map for the Claude mapper. */
|
|
1756
|
-
export const CLAUDE_FIELD_MAP = identityFieldMap(
|
|
2063
|
+
export const CLAUDE_FIELD_MAP = identityFieldMap(
|
|
2064
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2065
|
+
);
|
|
1757
2066
|
/** Identity field map for the Pi mapper. */
|
|
1758
|
-
export const PI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS));
|
|
2067
|
+
export const PI_FIELD_MAP = identityFieldMap(MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS));
|
|
1759
2068
|
/** Identity field map for the OMP mapper. */
|
|
1760
|
-
export const OMP_FIELD_MAP = identityFieldMap(
|
|
2069
|
+
export const OMP_FIELD_MAP = identityFieldMap(
|
|
2070
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2071
|
+
);
|
|
1761
2072
|
/** Identity field map for the Codex mapper. */
|
|
1762
|
-
export const CODEX_FIELD_MAP = identityFieldMap(
|
|
2073
|
+
export const CODEX_FIELD_MAP = identityFieldMap(
|
|
2074
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2075
|
+
);
|
|
1763
2076
|
/** Identity field map for the AGY mapper. */
|
|
1764
|
-
export const AGY_FIELD_MAP = identityFieldMap(
|
|
2077
|
+
export const AGY_FIELD_MAP = identityFieldMap(
|
|
2078
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2079
|
+
);
|
|
1765
2080
|
/** Identity field map for the Grok mapper. */
|
|
1766
|
-
export const GROK_FIELD_MAP = identityFieldMap(
|
|
2081
|
+
export const GROK_FIELD_MAP = identityFieldMap(
|
|
2082
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2083
|
+
);
|
|
1767
2084
|
/** Identity field map for the Gemini mapper. */
|
|
1768
|
-
export const GEMINI_FIELD_MAP = identityFieldMap(
|
|
2085
|
+
export const GEMINI_FIELD_MAP = identityFieldMap(
|
|
2086
|
+
MESSAGE_MAPPER_KEYS.concat(TOOL_CALL_MAPPER_KEYS, SKILL_CALL_MAPPER_KEYS),
|
|
2087
|
+
);
|
|
1769
2088
|
|
|
1770
2089
|
// ---------------------------------------------------------------------------
|
|
1771
2090
|
// Zod schemas for the six source mappers
|
package/src/opencode-importer.ts
CHANGED
|
@@ -27,7 +27,7 @@ const SOURCE = 'opencode';
|
|
|
27
27
|
const PAGE_SIZE = 250;
|
|
28
28
|
|
|
29
29
|
interface PreparedEntry {
|
|
30
|
-
targetTable: 'history_message' | 'history_tool_call';
|
|
30
|
+
targetTable: 'history_message' | 'history_tool_call' | 'history_skill_call';
|
|
31
31
|
splitIndex: number;
|
|
32
32
|
record: JsonObject;
|
|
33
33
|
recordHash: string;
|
|
@@ -256,6 +256,45 @@ function prepareEntries(
|
|
|
256
256
|
const output = stringValue(state.output);
|
|
257
257
|
const status = stringValue(state.status) ?? 'unknown';
|
|
258
258
|
const splitIndex = entries.length;
|
|
259
|
+
const toolName = stringValue(part.tool) ?? 'unknown';
|
|
260
|
+
// 0736: OpenCode's native `skill({name})` load tool is the skill-call trigger; it gets a
|
|
261
|
+
// history_skill_call row instead of a tool-call row (one row per load, same provenance).
|
|
262
|
+
if (toolName === 'skill') {
|
|
263
|
+
const input = objectValue(state.input);
|
|
264
|
+
const skillName = stringValue(input.name);
|
|
265
|
+
if (skillName !== undefined) {
|
|
266
|
+
const skillRecord = redactRecord(
|
|
267
|
+
{
|
|
268
|
+
message_hash: messageHash,
|
|
269
|
+
source: SOURCE,
|
|
270
|
+
source_file: sourceFile,
|
|
271
|
+
source_line: 1,
|
|
272
|
+
session_id: row.session_id,
|
|
273
|
+
seq: started ?? created,
|
|
274
|
+
skill_name: skillName,
|
|
275
|
+
invocation_kind: 'model',
|
|
276
|
+
skill_path: null,
|
|
277
|
+
args_raw: maybeArgsRaw(SOURCE, 'skill', state.input) ?? null,
|
|
278
|
+
args_digest: sha256(state.input ?? null),
|
|
279
|
+
status,
|
|
280
|
+
started_at: started === undefined ? null : isoTime(started),
|
|
281
|
+
completed_at: completedAt === undefined ? null : isoTime(completedAt),
|
|
282
|
+
duration_ms:
|
|
283
|
+
started === undefined || completedAt === undefined
|
|
284
|
+
? null
|
|
285
|
+
: Math.max(0, completedAt - started),
|
|
286
|
+
},
|
|
287
|
+
redactionRules,
|
|
288
|
+
);
|
|
289
|
+
entries.push({
|
|
290
|
+
targetTable: 'history_skill_call',
|
|
291
|
+
splitIndex,
|
|
292
|
+
record: skillRecord,
|
|
293
|
+
recordHash: recordHash(sourceFile, splitIndex, skillRecord),
|
|
294
|
+
});
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
259
298
|
const toolRecord = redactRecord(
|
|
260
299
|
{
|
|
261
300
|
message_hash: messageHash,
|
|
@@ -264,7 +303,7 @@ function prepareEntries(
|
|
|
264
303
|
source_line: 1,
|
|
265
304
|
session_id: row.session_id,
|
|
266
305
|
seq: started ?? created,
|
|
267
|
-
tool_name:
|
|
306
|
+
tool_name: toolName,
|
|
268
307
|
args_raw: maybeArgsRaw(SOURCE, stringValue(part.tool) ?? 'unknown', state.input),
|
|
269
308
|
args_digest: sha256(state.input ?? null),
|
|
270
309
|
status,
|
package/src/types.ts
CHANGED
|
@@ -155,6 +155,28 @@ export interface ImportResult {
|
|
|
155
155
|
* load tool); `skill_path` is nullable because some producers inline the skill body without
|
|
156
156
|
* a resolvable path.
|
|
157
157
|
*/
|
|
158
|
+
/**
|
|
159
|
+
* Split-time skill-load record routed to `history_skill_call` (0736). The importer/DAO manage
|
|
160
|
+
* `record_hash`, `message_hash` (resolved from `_messageSplitIndex`), the source identity
|
|
161
|
+
* columns, and `imported_at`; keeping them out of the split record also keeps them out of the
|
|
162
|
+
* record_hash input, so re-imports hash identically (0736 R5 idempotency).
|
|
163
|
+
*/
|
|
164
|
+
export interface SkillCallSplitRecord {
|
|
165
|
+
readonly _messageSplitIndex?: number;
|
|
166
|
+
readonly session_id: string;
|
|
167
|
+
readonly seq: number;
|
|
168
|
+
readonly skill_name: string;
|
|
169
|
+
readonly invocation_kind: 'user' | 'model';
|
|
170
|
+
readonly skill_path?: string | null;
|
|
171
|
+
readonly args_raw?: string | null;
|
|
172
|
+
readonly args_digest?: string | null;
|
|
173
|
+
readonly call_id?: string | null;
|
|
174
|
+
readonly status?: string | null;
|
|
175
|
+
readonly started_at?: string | null;
|
|
176
|
+
readonly completed_at?: string | null;
|
|
177
|
+
readonly duration_ms?: number | null;
|
|
178
|
+
}
|
|
179
|
+
|
|
158
180
|
export interface SkillCall {
|
|
159
181
|
readonly record_hash: string;
|
|
160
182
|
readonly message_hash: string;
|