@gobing-ai/ts-llm-jsonl-importer 0.4.19 → 0.4.21

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/src/schema-sql.ts CHANGED
@@ -80,4 +80,61 @@ CREATE TABLE IF NOT EXISTS history_etl_openclaw (
80
80
  payload_json TEXT NOT NULL,
81
81
  imported_at TEXT NOT NULL
82
82
  );
83
+
84
+ CREATE TABLE IF NOT EXISTS history_message (
85
+ record_hash TEXT PRIMARY KEY,
86
+ source TEXT NOT NULL,
87
+ source_file TEXT NOT NULL,
88
+ source_line INTEGER NOT NULL,
89
+ session_id TEXT NOT NULL,
90
+ seq INTEGER NOT NULL,
91
+ turn_index INTEGER,
92
+ role TEXT NOT NULL,
93
+ record_type TEXT NOT NULL,
94
+ disposition TEXT NOT NULL,
95
+ ts TEXT NOT NULL,
96
+ duration_ms INTEGER,
97
+ model TEXT,
98
+ input_tokens INTEGER,
99
+ output_tokens INTEGER,
100
+ cache_read_tokens INTEGER,
101
+ cache_write_tokens INTEGER,
102
+ cost_usd REAL,
103
+ content_text TEXT,
104
+ cwd TEXT,
105
+ provenance TEXT NOT NULL,
106
+ run_id TEXT,
107
+ task_wbs TEXT,
108
+ imported_at TEXT NOT NULL
109
+ );
110
+
111
+ CREATE TABLE IF NOT EXISTS history_tool_call (
112
+ record_hash TEXT PRIMARY KEY,
113
+ message_hash TEXT NOT NULL,
114
+ source TEXT NOT NULL,
115
+ source_file TEXT NOT NULL,
116
+ source_line INTEGER NOT NULL,
117
+ session_id TEXT NOT NULL,
118
+ seq INTEGER NOT NULL,
119
+ tool_name TEXT NOT NULL,
120
+ args_digest TEXT,
121
+ status TEXT NOT NULL,
122
+ started_at TEXT,
123
+ completed_at TEXT,
124
+ duration_ms INTEGER,
125
+ result_bytes INTEGER,
126
+ error_text TEXT,
127
+ imported_at TEXT NOT NULL
128
+ );
129
+
130
+ CREATE INDEX IF NOT EXISTS idx_history_message_session
131
+ ON history_message(source, session_id, seq);
132
+ CREATE INDEX IF NOT EXISTS idx_history_message_ts
133
+ ON history_message(ts);
134
+ CREATE INDEX IF NOT EXISTS idx_history_tool_call_session
135
+ ON history_tool_call(source, session_id, seq);
136
+ CREATE INDEX IF NOT EXISTS idx_history_tool_call_tool_name
137
+ ON history_tool_call(tool_name);
138
+ CREATE INDEX IF NOT EXISTS idx_history_tool_call_message_hash
139
+ ON history_tool_call(message_hash);
83
140
  `.trim();
package/src/sources.ts CHANGED
@@ -1,5 +1,25 @@
1
1
  import { z } from 'zod';
2
2
  import { HistoryImportError } from './errors';
3
+ import {
4
+ AGY_FIELD_MAP,
5
+ AGY_SCHEMA,
6
+ agySplit,
7
+ CLAUDE_FIELD_MAP,
8
+ CLAUDE_SCHEMA,
9
+ CODEX_FIELD_MAP,
10
+ CODEX_SCHEMA,
11
+ claudeSplit,
12
+ codexSplit,
13
+ GROK_FIELD_MAP,
14
+ GROK_SCHEMA,
15
+ grokSplit,
16
+ OMP_FIELD_MAP,
17
+ OMP_SCHEMA,
18
+ ompSplit,
19
+ PI_FIELD_MAP,
20
+ PI_SCHEMA,
21
+ piSplit,
22
+ } from './mappers';
3
23
  import type { FieldTransform, JsonObject, LlmJsonlSource, SourceDefinition, TransformContext } from './types';
4
24
 
5
25
  const sourceRecordSchema = z
@@ -94,6 +114,30 @@ function sourceDefinition(
94
114
  schema: sourceRecordSchema,
95
115
  };
96
116
  }
117
+
118
+ /** Build a source definition with a typed custom split for the forensic contract tables. */
119
+ function customSourceDefinition(
120
+ source: LlmJsonlSource,
121
+ displayName: string,
122
+ defaultRoots: readonly string[],
123
+ filePatterns: readonly string[],
124
+ split: (raw: JsonObject) => readonly import('./types').SplitEntry[],
125
+ fieldMap: Readonly<Record<string, string>>,
126
+ schema: z.ZodType<JsonObject>,
127
+ ): SourceDefinition {
128
+ return {
129
+ source,
130
+ displayName,
131
+ defaultRoots,
132
+ filePatterns,
133
+ targetTable: `history_etl_${source}`,
134
+ splitConfig: { mode: 'custom', split },
135
+ fieldMap,
136
+ fieldTransforms: {},
137
+ schema,
138
+ };
139
+ }
140
+
97
141
  /**
98
142
  * Pattern every importer-owned table must match.
99
143
  *
@@ -102,13 +146,56 @@ function sourceDefinition(
102
146
  * namespaces importer tables away from consumer schemas. Both built-in and
103
147
  * custom source definitions are held to this rule.
104
148
  */
105
- export const VALID_TABLE_NAME = /^history_etl_[a-z_]+$/;
149
+ export const VALID_TABLE_NAME = /^history_[a-z_]+$/;
106
150
 
107
151
  /** Built-in source definitions keyed by source identifier. */
108
152
  export const SOURCE_DEFINITIONS: Readonly<Record<LlmJsonlSource, SourceDefinition>> = {
109
- pi: sourceDefinition('pi', 'Pi', ['.pi/history', '.pi'], ['*.jsonl', '*.json']),
110
- claude: sourceDefinition('claude', 'Claude Code', ['.claude/projects', '.claude'], ['*.jsonl']),
111
- codex: sourceDefinition('codex', 'Codex', ['.codex/sessions', '.codex'], ['*.jsonl']),
153
+ pi: customSourceDefinition('pi', 'Pi', ['.pi/agent/sessions'], ['*.jsonl'], piSplit, PI_FIELD_MAP, PI_SCHEMA),
154
+ claude: customSourceDefinition(
155
+ 'claude',
156
+ 'Claude Code',
157
+ ['.claude/projects'],
158
+ ['*.jsonl'],
159
+ claudeSplit,
160
+ CLAUDE_FIELD_MAP,
161
+ CLAUDE_SCHEMA,
162
+ ),
163
+ codex: customSourceDefinition(
164
+ 'codex',
165
+ 'Codex',
166
+ ['.codex/sessions'],
167
+ ['*.jsonl'],
168
+ codexSplit,
169
+ CODEX_FIELD_MAP,
170
+ CODEX_SCHEMA,
171
+ ),
172
+ omp: customSourceDefinition(
173
+ 'omp',
174
+ 'OMP',
175
+ ['.omp/agent/sessions'],
176
+ ['*.jsonl'],
177
+ ompSplit,
178
+ OMP_FIELD_MAP,
179
+ OMP_SCHEMA,
180
+ ),
181
+ grok: customSourceDefinition(
182
+ 'grok',
183
+ 'Grok',
184
+ ['.grok/sessions'],
185
+ ['*.jsonl'],
186
+ grokSplit,
187
+ GROK_FIELD_MAP,
188
+ GROK_SCHEMA,
189
+ ),
190
+ agy: customSourceDefinition(
191
+ 'agy',
192
+ 'Antigravity CLI',
193
+ ['.gemini/antigravity-cli/brain'],
194
+ ['*.jsonl'],
195
+ agySplit,
196
+ AGY_FIELD_MAP,
197
+ AGY_SCHEMA,
198
+ ),
112
199
  gemini: sourceDefinition('gemini', 'Gemini CLI', ['.gemini', '.config/gemini'], ['*.jsonl']),
113
200
  opencode: sourceDefinition('opencode', 'OpenCode', ['.opencode', '.local/share/opencode'], ['*.jsonl']),
114
201
  antigravity: sourceDefinition('antigravity', 'Antigravity', ['.antigravity'], ['*.jsonl']),
@@ -186,7 +273,7 @@ export function resolveSourceDefinition(input: string | SourceDefinition): Sourc
186
273
  function assertValidTable(table: string, source: string): void {
187
274
  if (!VALID_TABLE_NAME.test(table)) {
188
275
  throw new HistoryImportError(
189
- `Invalid history ETL target table for source "${source}": ${table}. Must match ${VALID_TABLE_NAME.source}.`,
276
+ `Invalid history target table for source "${source}": ${table}. Must match ${VALID_TABLE_NAME.source}.`,
190
277
  { source, table },
191
278
  );
192
279
  }
package/src/types.ts CHANGED
@@ -3,11 +3,27 @@ import type { FileSystem, RuntimePaths } from '@gobing-ai/ts-runtime';
3
3
  import type { z } from 'zod';
4
4
 
5
5
  /** Built-in source identifiers supported by the importer. */
6
- export type LlmJsonlSource = 'pi' | 'claude' | 'codex' | 'gemini' | 'opencode' | 'antigravity' | 'openclaw';
6
+ export type LlmJsonlSource =
7
+ | 'pi'
8
+ | 'claude'
9
+ | 'codex'
10
+ | 'gemini'
11
+ | 'opencode'
12
+ | 'antigravity'
13
+ | 'openclaw'
14
+ | 'omp'
15
+ | 'grok'
16
+ | 'agy';
7
17
 
8
18
  /** Import mode controlling checkpoint behavior. */
9
19
  export type ImportMode = 'full' | 'incremental' | 'force-file';
10
20
 
21
+ /** One record emitted by a custom split, optionally routed to its own table. */
22
+ export interface SplitEntry {
23
+ readonly targetTable?: string;
24
+ readonly record: JsonObject;
25
+ }
26
+
11
27
  /** Split strategy for turning a raw JSONL object into one or more ETL records. */
12
28
  export type SplitConfig =
13
29
  | {
@@ -20,7 +36,7 @@ export type SplitConfig =
20
36
  }
21
37
  | {
22
38
  readonly mode: 'custom';
23
- readonly split: (raw: JsonObject) => readonly JsonObject[];
39
+ readonly split: (raw: JsonObject) => readonly (JsonObject | SplitEntry)[];
24
40
  readonly targetTable?: string;
25
41
  };
26
42
 
@@ -94,6 +110,7 @@ export interface ImportResult {
94
110
  readonly processedLines: number;
95
111
  readonly importedRecords: number;
96
112
  readonly skippedDuplicates: number;
113
+ readonly unknownRecords: number;
97
114
  readonly parseErrors: readonly ImportIssue[];
98
115
  readonly validationErrors: readonly ImportIssue[];
99
116
  readonly checkpointUpdates: number;