@aiwg/cli 2026.7.19 → 2026.7.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/README.md +397 -385
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/browser-export.js +7 -0
- package/dist/src/artifacts/citation-parser.js +96 -35
- package/dist/src/artifacts/cli.js +59 -5
- package/dist/src/artifacts/discover-facets.js +15 -0
- package/dist/src/artifacts/discovery-eval.js +290 -0
- package/dist/src/artifacts/fortemi-core-query-adapter.js +1 -1
- package/dist/src/artifacts/fortemi-shard-export.js +1 -1
- package/dist/src/artifacts/index-builder.js +54 -17
- package/dist/src/artifacts/query-engine.js +10 -6
- package/dist/src/artifacts/state-transfer.js +27 -0
- package/dist/src/artifacts/stats.js +8 -0
- package/dist/src/cli/cli-extension-loader.js +73 -0
- package/dist/src/cli/handlers/help.js +2 -1
- package/dist/src/cli/handlers/index.js +6 -2
- package/dist/src/cli/handlers/resource-versions.js +247 -0
- package/dist/src/cli/handlers/sessions.js +966 -0
- package/dist/src/cli/handlers/skill-lint.js +49 -45
- package/dist/src/cli/handlers/subcommands.js +55 -3
- package/dist/src/cli/handlers/use.js +154 -59
- package/dist/src/cli/handlers/utilities.js +49 -34
- package/dist/src/cli/skill-usage.js +146 -24
- package/dist/src/config/cli.js +13 -9
- package/dist/src/config/project-artifacts-runtime.mjs +68 -0
- package/dist/src/config/project-artifacts.js +1 -68
- package/dist/src/extensions/commands/definitions.js +65 -2
- package/dist/src/extensions/manifest.js +29 -0
- package/dist/src/extensions/project-local-discovery.js +86 -2
- package/dist/src/extensions/project-local-remove.js +52 -56
- package/dist/src/extensions/shadow-resolver.js +3 -1
- package/dist/src/plugins/standalone-packager.js +143 -0
- package/dist/src/resources/cache-cleanup.js +67 -0
- package/dist/src/resources/doctor.js +107 -0
- package/dist/src/resources/lockfile.js +125 -0
- package/dist/src/resources/resolver.js +133 -0
- package/dist/src/resources/web-release.d.ts +8 -0
- package/dist/src/resources/web-release.js +159 -1
- package/dist/src/sessions/adapters/claude.js +357 -0
- package/dist/src/sessions/adapters/codex.js +521 -0
- package/dist/src/sessions/adapters/copilot.js +226 -0
- package/dist/src/sessions/adapters/cursor.js +372 -0
- package/dist/src/sessions/adapters/factory.js +345 -0
- package/dist/src/sessions/adapters/generic.js +225 -0
- package/dist/src/sessions/adapters/hermes.js +341 -0
- package/dist/src/sessions/adapters/openclaw.js +381 -0
- package/dist/src/sessions/adapters/opencode.js +454 -0
- package/dist/src/sessions/adapters/openhuman.js +315 -0
- package/dist/src/sessions/adapters/warp.js +160 -0
- package/dist/src/sessions/adapters/windsurf.js +212 -0
- package/dist/src/sessions/candidates.js +210 -0
- package/dist/src/sessions/contracts.js +310 -0
- package/dist/src/sessions/discovery.js +51 -0
- package/dist/src/sessions/fixtures.js +12 -0
- package/dist/src/sessions/importer.js +315 -0
- package/dist/src/sessions/index.js +25 -0
- package/dist/src/sessions/knowledge-shard.js +61 -0
- package/dist/src/sessions/optional-backends.js +238 -0
- package/dist/src/sessions/policy.js +192 -0
- package/dist/src/sessions/ports.js +2 -0
- package/dist/src/sessions/promotion.js +367 -0
- package/dist/src/sessions/readers.js +176 -0
- package/dist/src/sessions/repository.js +1551 -0
- package/dist/src/skills/adapters/agent-skills.js +59 -0
- package/dist/src/skills/adapters/local.js +19 -1
- package/dist/src/skills/agent-skills.js +249 -0
- package/dist/src/skills/cli.js +463 -7
- package/dist/src/skills/deployer.js +554 -0
- package/dist/src/skills/doctor.js +105 -0
- package/dist/src/skills/exporter.js +382 -0
- package/dist/src/skills/importer.js +921 -0
- package/dist/src/skills/registry.js +19 -0
- package/dist/src/skills/validator.js +323 -0
- package/dist/src/smiths/context-pipeline/aiwg-md.js +5 -1
- package/dist/src/smiths/context-pipeline/claude-hook.js +21 -1
- package/dist/src/smiths/context-pipeline/finalization.js +5 -3
- package/dist/src/smiths/context-pipeline/generator.js +4 -1
- package/dist/src/smiths/context-pipeline/parallelism-section.js +34 -1
- package/dist/src/smiths/context-pipeline/workspace-context.js +15 -3
- package/dist/src/smiths/mcpsmith/example.js +3 -1
- package/dist/src/smiths/mcpsmith/generator.js +3 -1
- package/dist/src/smiths/toolsmith/runtime-discovery.mjs +2 -1
- package/dist/src/storage/cli.js +3 -2
- package/dist/src/storage/subsystem-cli.js +7 -2
- package/dist/src/update/notifier.mjs +1 -1
- package/dist/src/update/service.mjs +123 -0
- package/package.json +3 -2
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { opendir } from 'node:fs/promises';
|
|
2
|
+
import { basename, extname, resolve } from 'node:path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { SessionContractError, assertSupportedSchemaMajor, sha256, } from '../contracts.js';
|
|
5
|
+
import { redactSourceLocator } from '../discovery.js';
|
|
6
|
+
import { readBoundedJsonLines, streamBoundedJsonLines, } from '../readers.js';
|
|
7
|
+
export const CLAUDE_ADAPTER_VERSION = '1.0.0';
|
|
8
|
+
export const CLAUDE_TRANSCRIPT_SCHEMA_VERSION = '1.0.0';
|
|
9
|
+
const ClaudeRecordSchema = z.object({
|
|
10
|
+
type: z.string().min(1),
|
|
11
|
+
subtype: z.string().optional(),
|
|
12
|
+
uuid: z.string().min(1).optional(),
|
|
13
|
+
parentUuid: z.string().min(1).nullable().optional(),
|
|
14
|
+
sessionId: z.string().min(1).optional(),
|
|
15
|
+
session_id: z.string().min(1).optional(),
|
|
16
|
+
timestamp: z.string().datetime({ offset: true }).optional(),
|
|
17
|
+
cwd: z.string().optional(),
|
|
18
|
+
gitBranch: z.string().optional(),
|
|
19
|
+
version: z.string().optional(),
|
|
20
|
+
schemaVersion: z.string().optional(),
|
|
21
|
+
message: z.object({
|
|
22
|
+
id: z.string().min(1).optional(),
|
|
23
|
+
role: z.string().min(1).optional(),
|
|
24
|
+
content: z.union([z.string(), z.array(z.unknown())]).optional(),
|
|
25
|
+
}).passthrough().optional(),
|
|
26
|
+
}).passthrough();
|
|
27
|
+
const ClaudeHookSchema = z.object({
|
|
28
|
+
session_id: z.string().min(1),
|
|
29
|
+
transcript_path: z.string().min(1),
|
|
30
|
+
cwd: z.string().min(1),
|
|
31
|
+
hook_event_name: z.string().min(1),
|
|
32
|
+
permission_mode: z.string().optional(),
|
|
33
|
+
source: z.enum(['startup', 'resume', 'clear', 'compact']).optional(),
|
|
34
|
+
model: z.string().optional(),
|
|
35
|
+
reason: z.string().optional(),
|
|
36
|
+
schemaVersion: z.string().optional(),
|
|
37
|
+
timestamp: z.string().datetime({ offset: true }).optional(),
|
|
38
|
+
}).passthrough();
|
|
39
|
+
export class ClaudeSessionAdapter {
|
|
40
|
+
limits;
|
|
41
|
+
discoveryLimits;
|
|
42
|
+
provider = 'claude';
|
|
43
|
+
adapterVersion = CLAUDE_ADAPTER_VERSION;
|
|
44
|
+
disposition = 'implemented';
|
|
45
|
+
supportedOperations = ['discover', 'inspect', 'stream'];
|
|
46
|
+
acquisitionModes = ['jsonl', 'hook'];
|
|
47
|
+
constructor(limits, discoveryLimits = { maxDepth: 8, maxFiles: 10_000 }) {
|
|
48
|
+
this.limits = limits;
|
|
49
|
+
this.discoveryLimits = discoveryLimits;
|
|
50
|
+
}
|
|
51
|
+
async *discover(scope) {
|
|
52
|
+
if (scope.allowedRoots.length === 0) {
|
|
53
|
+
throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'Claude discovery requires an explicitly authorized projects or hook root');
|
|
54
|
+
}
|
|
55
|
+
let emitted = 0;
|
|
56
|
+
for (const root of [...scope.allowedRoots].sort()) {
|
|
57
|
+
for await (const locator of discoverJsonl(resolve(root), this.discoveryLimits.maxDepth)) {
|
|
58
|
+
emitted += 1;
|
|
59
|
+
if (emitted > this.discoveryLimits.maxFiles) {
|
|
60
|
+
throw new SessionContractError('RESOURCE_LIMIT_EXCEEDED', 'Claude source discovery exceeded the authorized file limit');
|
|
61
|
+
}
|
|
62
|
+
yield {
|
|
63
|
+
provider: 'claude',
|
|
64
|
+
locator,
|
|
65
|
+
locatorClass: isHookLocator(locator) ? 'claude-hook-jsonl' : 'claude-transcript-jsonl',
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async inspect(source) {
|
|
71
|
+
const parsed = await this.readSource(source);
|
|
72
|
+
return {
|
|
73
|
+
sourceSchemaVersion: parsed.schemaVersion,
|
|
74
|
+
consistency: parsed.consistency,
|
|
75
|
+
operationalState: 'available',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async *stream(source, cursor) {
|
|
79
|
+
const start = parseRecordCursor(cursor?.value);
|
|
80
|
+
const input = await streamBoundedJsonLines({
|
|
81
|
+
selectedPath: source.locator,
|
|
82
|
+
allowedRoots: source.authorizedScope.allowedRoots,
|
|
83
|
+
}, { consistency: 'provisional', limits: this.limits });
|
|
84
|
+
const hookSource = isHookLocator(source.locator);
|
|
85
|
+
let outputIndex = 0;
|
|
86
|
+
let sawRecord = false;
|
|
87
|
+
let schemaVersion = null;
|
|
88
|
+
for await (const line of input) {
|
|
89
|
+
sawRecord = true;
|
|
90
|
+
const value = line.value;
|
|
91
|
+
const currentSchema = typeof value.schemaVersion === 'string'
|
|
92
|
+
? value.schemaVersion : CLAUDE_TRANSCRIPT_SCHEMA_VERSION;
|
|
93
|
+
if (schemaVersion && currentSchema !== schemaVersion) {
|
|
94
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'Claude source declares mixed schema versions');
|
|
95
|
+
}
|
|
96
|
+
schemaVersion = currentSchema;
|
|
97
|
+
assertSupportedSchemaMajor(schemaVersion);
|
|
98
|
+
const normalized = hookSource || isHookRecord(line.value)
|
|
99
|
+
? normalizeHooks([line]).records
|
|
100
|
+
: normalizeTranscript([line], source.locator).records;
|
|
101
|
+
for (const record of normalized) {
|
|
102
|
+
if (outputIndex++ >= start)
|
|
103
|
+
yield record;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!sawRecord && !input.incompleteTail) {
|
|
107
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Claude JSONL source is empty');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async readSource(source) {
|
|
111
|
+
const result = await readBoundedJsonLines({
|
|
112
|
+
selectedPath: source.locator,
|
|
113
|
+
allowedRoots: source.authorizedScope.allowedRoots,
|
|
114
|
+
}, { consistency: 'provisional', limits: this.limits });
|
|
115
|
+
if (result.records.length === 0 && !result.incompleteTail) {
|
|
116
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Claude JSONL source is empty');
|
|
117
|
+
}
|
|
118
|
+
const hookSource = isHookLocator(source.locator)
|
|
119
|
+
|| result.records.some((record) => isHookRecord(record.value));
|
|
120
|
+
const normalized = hookSource
|
|
121
|
+
? normalizeHooks(result.records)
|
|
122
|
+
: normalizeTranscript(result.records, source.locator);
|
|
123
|
+
const schemaVersion = declaredSchemaVersion(result.records);
|
|
124
|
+
assertSupportedSchemaMajor(schemaVersion);
|
|
125
|
+
return {
|
|
126
|
+
records: normalized.records,
|
|
127
|
+
schemaVersion,
|
|
128
|
+
consistency: normalized.complete ? 'complete' : 'provisional',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function normalizeTranscript(records, locator) {
|
|
133
|
+
const filenameSessionId = basename(locator, extname(locator));
|
|
134
|
+
const output = [];
|
|
135
|
+
for (const record of records) {
|
|
136
|
+
const parsed = ClaudeRecordSchema.safeParse(record.value);
|
|
137
|
+
if (!parsed.success) {
|
|
138
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Claude transcript record is malformed');
|
|
139
|
+
}
|
|
140
|
+
const value = parsed.data;
|
|
141
|
+
const nativeSessionId = value.sessionId ?? value.session_id ?? filenameSessionId;
|
|
142
|
+
if ((value.sessionId || value.session_id) && nativeSessionId !== filenameSessionId) {
|
|
143
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'Claude transcript session identity differs from its documented filename identity');
|
|
144
|
+
}
|
|
145
|
+
const blocks = messageBlocks(value);
|
|
146
|
+
if (blocks.length === 0) {
|
|
147
|
+
output.push(providerRecord(value, record, nativeSessionId, {
|
|
148
|
+
kind: `claude.${value.type}`,
|
|
149
|
+
text: '',
|
|
150
|
+
opaque: true,
|
|
151
|
+
unknownFields: unknownFields(value, TRANSCRIPT_KEYS),
|
|
152
|
+
}));
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
for (const [blockIndex, block] of blocks.entries()) {
|
|
156
|
+
output.push(providerRecord(value, record, nativeSessionId, {
|
|
157
|
+
kind: block.kind,
|
|
158
|
+
text: block.text,
|
|
159
|
+
blockIndex,
|
|
160
|
+
blockNativeId: block.nativeId,
|
|
161
|
+
opaque: block.opaque,
|
|
162
|
+
unknownFields: block.unknownFields,
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return { records: output, complete: false };
|
|
167
|
+
}
|
|
168
|
+
function normalizeHooks(records) {
|
|
169
|
+
const output = [];
|
|
170
|
+
let complete = false;
|
|
171
|
+
for (const record of records) {
|
|
172
|
+
const parsed = ClaudeHookSchema.safeParse(record.value);
|
|
173
|
+
if (!parsed.success) {
|
|
174
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Claude lifecycle hook record is malformed');
|
|
175
|
+
}
|
|
176
|
+
const hook = parsed.data;
|
|
177
|
+
complete ||= hook.hook_event_name === 'SessionEnd';
|
|
178
|
+
output.push({
|
|
179
|
+
nativeSessionId: hook.session_id,
|
|
180
|
+
nativeEventId: hookNativeId(hook, record.sequence),
|
|
181
|
+
sequence: record.sequence,
|
|
182
|
+
kind: 'lifecycle-hook',
|
|
183
|
+
role: 'system',
|
|
184
|
+
participant: 'claude',
|
|
185
|
+
model: hook.model,
|
|
186
|
+
occurredAt: hook.timestamp,
|
|
187
|
+
text: '',
|
|
188
|
+
rawReference: { locatorClass: 'claude-hook-jsonl', offset: record.byteOffset },
|
|
189
|
+
extensions: {
|
|
190
|
+
hookEventName: hook.hook_event_name,
|
|
191
|
+
lifecycle: hook.hook_event_name === 'SessionEnd' ? 'complete' : 'active',
|
|
192
|
+
startSource: hook.source,
|
|
193
|
+
model: hook.model,
|
|
194
|
+
reason: hook.reason,
|
|
195
|
+
permissionMode: hook.permission_mode,
|
|
196
|
+
workspace: { cwdClass: '<workspace>', transcript: redactSourceLocator(hook.transcript_path) },
|
|
197
|
+
provenance: { acquisition: 'claude-hook', schema: CLAUDE_TRANSCRIPT_SCHEMA_VERSION },
|
|
198
|
+
unknownFields: unknownFields(hook, HOOK_KEYS),
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return { records: output, complete };
|
|
203
|
+
}
|
|
204
|
+
function providerRecord(value, record, nativeSessionId, block) {
|
|
205
|
+
const nativeBase = value.uuid ?? value.message?.id;
|
|
206
|
+
const nativeEventId = block.blockNativeId
|
|
207
|
+
?? (nativeBase ? `${nativeBase}:${block.blockIndex ?? 0}` : undefined);
|
|
208
|
+
return {
|
|
209
|
+
nativeSessionId,
|
|
210
|
+
nativeEventId,
|
|
211
|
+
sequence: record.sequence * 1_000 + (block.blockIndex ?? 0),
|
|
212
|
+
kind: block.kind,
|
|
213
|
+
role: value.message?.role,
|
|
214
|
+
occurredAt: value.timestamp,
|
|
215
|
+
text: block.text,
|
|
216
|
+
rawReference: { locatorClass: 'claude-transcript-jsonl', offset: record.byteOffset },
|
|
217
|
+
extensions: {
|
|
218
|
+
transcriptType: value.type,
|
|
219
|
+
transcriptSubtype: value.subtype,
|
|
220
|
+
parentUuid: value.parentUuid,
|
|
221
|
+
productVersion: value.version,
|
|
222
|
+
workspace: { cwdClass: value.cwd ? '<workspace>' : undefined, gitBranch: value.gitBranch },
|
|
223
|
+
provenance: { acquisition: 'claude-transcript', schema: CLAUDE_TRANSCRIPT_SCHEMA_VERSION },
|
|
224
|
+
opaque: block.opaque,
|
|
225
|
+
unknownFields: {
|
|
226
|
+
...unknownFields(value, TRANSCRIPT_KEYS),
|
|
227
|
+
...block.unknownFields,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function messageBlocks(value) {
|
|
233
|
+
const content = value.message?.content;
|
|
234
|
+
if (typeof content === 'string') {
|
|
235
|
+
return [{ kind: 'message', text: content, opaque: false, unknownFields: {} }];
|
|
236
|
+
}
|
|
237
|
+
if (!Array.isArray(content))
|
|
238
|
+
return [];
|
|
239
|
+
return content.map((input) => {
|
|
240
|
+
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
241
|
+
return { kind: 'claude.unknown-block', text: '', opaque: true, unknownFields: { value: input } };
|
|
242
|
+
}
|
|
243
|
+
const block = input;
|
|
244
|
+
const type = typeof block.type === 'string' ? block.type : 'unknown';
|
|
245
|
+
if (type === 'text' && typeof block.text === 'string') {
|
|
246
|
+
return {
|
|
247
|
+
kind: 'message', text: block.text, opaque: false,
|
|
248
|
+
unknownFields: unknownFields(block, new Set(['type', 'text'])),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (type === 'tool_use') {
|
|
252
|
+
return {
|
|
253
|
+
kind: 'tool-call',
|
|
254
|
+
text: typeof block.name === 'string' ? block.name : '',
|
|
255
|
+
nativeId: typeof block.id === 'string' ? block.id : undefined,
|
|
256
|
+
opaque: false,
|
|
257
|
+
unknownFields: unknownFields(block, new Set(['type', 'id', 'name', 'input'])),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
if (type === 'tool_result') {
|
|
261
|
+
return {
|
|
262
|
+
kind: 'tool-result',
|
|
263
|
+
text: extractToolResultText(block.content),
|
|
264
|
+
nativeId: typeof block.tool_use_id === 'string' ? block.tool_use_id : undefined,
|
|
265
|
+
opaque: false,
|
|
266
|
+
unknownFields: unknownFields(block, new Set(['type', 'tool_use_id', 'content', 'is_error'])),
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
kind: `claude.${type}`,
|
|
271
|
+
text: '',
|
|
272
|
+
opaque: true,
|
|
273
|
+
unknownFields: { ...block },
|
|
274
|
+
};
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
function extractToolResultText(value) {
|
|
278
|
+
if (typeof value === 'string')
|
|
279
|
+
return value;
|
|
280
|
+
if (!Array.isArray(value))
|
|
281
|
+
return '';
|
|
282
|
+
return value
|
|
283
|
+
.filter((item) => Boolean(item) && typeof item === 'object' && !Array.isArray(item))
|
|
284
|
+
.map((item) => typeof item.text === 'string' ? item.text : '')
|
|
285
|
+
.filter(Boolean)
|
|
286
|
+
.join('\n');
|
|
287
|
+
}
|
|
288
|
+
async function* discoverJsonl(root, maxDepth) {
|
|
289
|
+
const pending = [{ path: root, depth: 0 }];
|
|
290
|
+
while (pending.length > 0) {
|
|
291
|
+
const current = pending.shift();
|
|
292
|
+
let directory;
|
|
293
|
+
try {
|
|
294
|
+
directory = await opendir(current.path);
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'authorized Claude source root is inaccessible');
|
|
298
|
+
}
|
|
299
|
+
const childDirectories = [];
|
|
300
|
+
const files = [];
|
|
301
|
+
for await (const entry of directory) {
|
|
302
|
+
const path = resolve(current.path, entry.name);
|
|
303
|
+
if (entry.isSymbolicLink())
|
|
304
|
+
continue;
|
|
305
|
+
if (entry.isDirectory() && current.depth < maxDepth)
|
|
306
|
+
childDirectories.push(path);
|
|
307
|
+
else if (entry.isFile() && entry.name.endsWith('.jsonl'))
|
|
308
|
+
files.push(path);
|
|
309
|
+
}
|
|
310
|
+
for (const file of files.sort())
|
|
311
|
+
yield file;
|
|
312
|
+
for (const path of childDirectories.sort())
|
|
313
|
+
pending.push({ path, depth: current.depth + 1 });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
function declaredSchemaVersion(records) {
|
|
317
|
+
const declared = records
|
|
318
|
+
.map((record) => {
|
|
319
|
+
if (!record.value || typeof record.value !== 'object' || Array.isArray(record.value))
|
|
320
|
+
return undefined;
|
|
321
|
+
return record.value.schemaVersion;
|
|
322
|
+
})
|
|
323
|
+
.find((value) => typeof value === 'string');
|
|
324
|
+
return declared ?? CLAUDE_TRANSCRIPT_SCHEMA_VERSION;
|
|
325
|
+
}
|
|
326
|
+
function parseRecordCursor(value) {
|
|
327
|
+
if (value === undefined || value === '')
|
|
328
|
+
return 0;
|
|
329
|
+
if (!/^\d+$/.test(value))
|
|
330
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'Claude record cursor is invalid');
|
|
331
|
+
return Number(value);
|
|
332
|
+
}
|
|
333
|
+
function hookNativeId(hook, sequence) {
|
|
334
|
+
return sha256([
|
|
335
|
+
hook.session_id, hook.hook_event_name, hook.source ?? '',
|
|
336
|
+
hook.timestamp ?? '', hook.reason ?? '', sequence,
|
|
337
|
+
].join('\0'));
|
|
338
|
+
}
|
|
339
|
+
function isHookLocator(locator) {
|
|
340
|
+
return /\.hooks?\.jsonl$/i.test(locator);
|
|
341
|
+
}
|
|
342
|
+
function isHookRecord(value) {
|
|
343
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
|
344
|
+
&& typeof value.hook_event_name === 'string';
|
|
345
|
+
}
|
|
346
|
+
function unknownFields(value, known) {
|
|
347
|
+
return Object.fromEntries(Object.entries(value).filter(([key]) => !known.has(key)));
|
|
348
|
+
}
|
|
349
|
+
const TRANSCRIPT_KEYS = new Set([
|
|
350
|
+
'type', 'subtype', 'uuid', 'parentUuid', 'sessionId', 'session_id',
|
|
351
|
+
'timestamp', 'cwd', 'gitBranch', 'version', 'schemaVersion', 'message',
|
|
352
|
+
]);
|
|
353
|
+
const HOOK_KEYS = new Set([
|
|
354
|
+
'session_id', 'transcript_path', 'cwd', 'hook_event_name', 'permission_mode',
|
|
355
|
+
'source', 'model', 'reason', 'schemaVersion', 'timestamp',
|
|
356
|
+
]);
|
|
357
|
+
//# sourceMappingURL=claude.js.map
|