@aiwg/cli 2026.7.21 → 2026.7.23
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 +14 -3
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/cli/handlers/sessions.js +339 -40
- package/dist/src/config/aiwg-config.js +12 -0
- package/dist/src/config/cli.js +16 -3
- package/dist/src/security/threat-assessment-config.js +296 -0
- package/dist/src/sessions/adapters/claude.js +37 -9
- package/dist/src/sessions/adapters/codex.js +38 -11
- package/dist/src/sessions/adapters/cursor.js +166 -10
- package/dist/src/sessions/adapters/factory.js +50 -9
- package/dist/src/sessions/batch-contracts.js +121 -0
- package/dist/src/sessions/batch-import.js +265 -0
- package/dist/src/sessions/contracts.js +32 -5
- package/dist/src/sessions/import-lease.js +152 -0
- package/dist/src/sessions/importer.js +163 -14
- package/dist/src/sessions/index.js +6 -0
- package/dist/src/sessions/origin.js +117 -0
- package/dist/src/sessions/readers.js +1 -1
- package/dist/src/sessions/repository.js +354 -13
- package/dist/src/sessions/timeline.js +148 -0
- package/dist/src/sessions/workspace-discovery.js +319 -0
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SESSION_CONTRACT_VERSION, SessionEventSchema, SessionSchema, assertSupportedSchemaMajor, sha256, stableEventId, stableSessionId, SessionContractError, } from './contracts.js';
|
|
2
2
|
import { redactSessionText, sanitizeNativeExtensions } from './policy.js';
|
|
3
3
|
import { fingerprintSourcePrefix } from './readers.js';
|
|
4
|
+
import { classifySessionEventOrigin, deriveSessionIntent, } from './origin.js';
|
|
4
5
|
const DEFAULT_LIMITS = {
|
|
5
6
|
maxRecords: 1_000_000,
|
|
6
|
-
maxRecordBytes:
|
|
7
|
+
maxRecordBytes: 8 * 1024 * 1024,
|
|
7
8
|
maxTotalBytes: 1024 * 1024 * 1024,
|
|
8
9
|
batchSize: 1_000,
|
|
9
10
|
};
|
|
@@ -22,12 +23,21 @@ export class IncrementalSessionImporter {
|
|
|
22
23
|
}
|
|
23
24
|
async import(request) {
|
|
24
25
|
assertSupportedSchemaMajor(request.source.sourceSchemaVersion);
|
|
26
|
+
if (request.inactivityThresholdMs !== undefined
|
|
27
|
+
&& (!Number.isFinite(request.inactivityThresholdMs) || request.inactivityThresholdMs < 0)) {
|
|
28
|
+
throw new SessionContractError('INVALID_ARGUMENT', 'session inactivity threshold must be a non-negative duration');
|
|
29
|
+
}
|
|
25
30
|
if (request.workspaceId !== request.selectedSource.authorizedScope.workspaceId) {
|
|
26
31
|
throw new SessionContractError('SOURCE_NOT_AUTHORIZED', 'session import workspace is outside the authorized source scope');
|
|
27
32
|
}
|
|
28
33
|
const limits = { ...DEFAULT_LIMITS, ...request.limits };
|
|
29
|
-
const previous =
|
|
34
|
+
const previous = request.batchRunId
|
|
35
|
+
? this.repository.getBatchCheckpoint(request.source.sourceId, request.adapter.adapterVersion, request.batchRunId) ?? this.repository.getCheckpoint(request.source.sourceId, request.adapter.adapterVersion)
|
|
36
|
+
: this.repository.getCheckpoint(request.source.sourceId, request.adapter.adapterVersion);
|
|
30
37
|
const continuity = await sourceContinuity(request, previous);
|
|
38
|
+
const sourceObservedAt = continuity
|
|
39
|
+
? new Date(continuity.mtimeMs).toISOString()
|
|
40
|
+
: undefined;
|
|
31
41
|
const sourceGeneration = continuity?.sourceGeneration ?? sourceGenerationDigest(request);
|
|
32
42
|
if (previous?.sourceGeneration && previous.sourceGeneration !== sourceGeneration) {
|
|
33
43
|
throw new SessionContractError('SCHEMA_DRIFT', 'session source generation changed; explicit restart or migration is required');
|
|
@@ -73,12 +83,15 @@ export class IncrementalSessionImporter {
|
|
|
73
83
|
const flush = () => {
|
|
74
84
|
if (batch.length === 0)
|
|
75
85
|
return;
|
|
86
|
+
if (request.signal?.aborted) {
|
|
87
|
+
throw new SessionContractError('IMPORT_INTERRUPTED', 'session import was cancelled at a durable batch boundary');
|
|
88
|
+
}
|
|
76
89
|
const runId = sha256([
|
|
77
90
|
request.source.sourceId, request.adapter.adapterVersion,
|
|
78
91
|
batchStart, checkpoint.recordsRead,
|
|
79
92
|
...batch.map((record) => sha256(JSON.stringify(record))),
|
|
80
93
|
].join('\0'));
|
|
81
|
-
const normalized = normalizeBatch(request, batch, runId);
|
|
94
|
+
const normalized = normalizeBatch(request, batch, runId, sourceObservedAt);
|
|
82
95
|
const run = {
|
|
83
96
|
contractVersion: SESSION_CONTRACT_VERSION,
|
|
84
97
|
importRunId: runId,
|
|
@@ -101,7 +114,8 @@ export class IncrementalSessionImporter {
|
|
|
101
114
|
const receipt = this.repository.applyImport({
|
|
102
115
|
source: sanitizedSource, run,
|
|
103
116
|
sessions: normalized.sessions, events: normalized.events,
|
|
104
|
-
|
|
117
|
+
batchRunId: request.batchRunId,
|
|
118
|
+
}, { ...checkpoint }, request.publish ?? request.source.consistency !== 'complete');
|
|
105
119
|
const memory = process.memoryUsage();
|
|
106
120
|
peakHeap = Math.max(peakHeap, memory.heapUsed);
|
|
107
121
|
peakRss = Math.max(peakRss, memory.rss);
|
|
@@ -122,6 +136,9 @@ export class IncrementalSessionImporter {
|
|
|
122
136
|
};
|
|
123
137
|
try {
|
|
124
138
|
for await (const record of request.adapter.stream(request.selectedSource, previous ? { value: previous.cursor } : undefined)) {
|
|
139
|
+
if (request.signal?.aborted) {
|
|
140
|
+
throw new SessionContractError('IMPORT_INTERRUPTED', 'session import was cancelled and can resume from its durable checkpoint');
|
|
141
|
+
}
|
|
125
142
|
const bytes = Buffer.byteLength(JSON.stringify(record));
|
|
126
143
|
if (bytes > limits.maxRecordBytes
|
|
127
144
|
|| checkpoint.bytesRead + bytes > limits.maxTotalBytes
|
|
@@ -145,7 +162,8 @@ export class IncrementalSessionImporter {
|
|
|
145
162
|
flush();
|
|
146
163
|
}
|
|
147
164
|
catch (error) {
|
|
148
|
-
const
|
|
165
|
+
const published = request.publish ?? request.source.consistency !== 'complete';
|
|
166
|
+
const committed = published ? receipts : [];
|
|
149
167
|
throw new SessionImportFailure({
|
|
150
168
|
contractVersion: '1.0.0',
|
|
151
169
|
outcome: 'terminal-failure',
|
|
@@ -157,7 +175,7 @@ export class IncrementalSessionImporter {
|
|
|
157
175
|
records: committed.reduce((total, receipt) => total + (receipt.metrics?.records ?? 0), 0),
|
|
158
176
|
events: committed.reduce((total, receipt) => total + receipt.eventsInserted, 0),
|
|
159
177
|
},
|
|
160
|
-
resumableCheckpoint:
|
|
178
|
+
resumableCheckpoint: !published
|
|
161
179
|
? {
|
|
162
180
|
...durableCheckpoint,
|
|
163
181
|
cursor: '',
|
|
@@ -170,7 +188,7 @@ export class IncrementalSessionImporter {
|
|
|
170
188
|
? error.code : 'IMPORT_INTERRUPTED',
|
|
171
189
|
}, error);
|
|
172
190
|
}
|
|
173
|
-
if (request.source.consistency === 'complete') {
|
|
191
|
+
if (request.publish !== false && request.source.consistency === 'complete') {
|
|
174
192
|
this.repository.commitStagedImports(request.source.sourceId, request.adapter.adapterVersion);
|
|
175
193
|
for (const receipt of receipts) {
|
|
176
194
|
if (receipt.outcome === 'staged')
|
|
@@ -180,22 +198,31 @@ export class IncrementalSessionImporter {
|
|
|
180
198
|
return receipts;
|
|
181
199
|
}
|
|
182
200
|
}
|
|
183
|
-
function normalizeBatch(request, records, importRunId) {
|
|
201
|
+
function normalizeBatch(request, records, importRunId, sourceObservedAt) {
|
|
184
202
|
const sessions = new Map();
|
|
185
203
|
const events = records.map((record) => {
|
|
186
204
|
const sessionId = stableSessionId(request.source.provider, request.source.sourceId, record.nativeSessionId);
|
|
187
205
|
const redacted = redactSessionText(record.text);
|
|
188
206
|
const native = sanitizeNativeExtensions(record.extensions ?? {});
|
|
189
207
|
const digest = sha256(JSON.stringify(record));
|
|
208
|
+
const origin = classifySessionEventOrigin(request.source.provider, record);
|
|
209
|
+
const lifecycle = sessionLifecycle(request, record, sourceObservedAt);
|
|
210
|
+
const lifecycleEvidence = sessionLifecycleEvidence(request, record, sourceObservedAt);
|
|
190
211
|
const extensions = {
|
|
191
212
|
[`native.${request.source.provider}`]: native.value,
|
|
192
213
|
};
|
|
193
214
|
const event = SessionEventSchema.parse({
|
|
194
215
|
contractVersion: SESSION_CONTRACT_VERSION,
|
|
195
|
-
eventId: stableEventId(request.source.sourceId, record, digest),
|
|
216
|
+
eventId: stableEventId(request.source.provider, request.source.sourceId, record, digest),
|
|
196
217
|
sessionId, sourceId: request.source.sourceId, importRunId,
|
|
197
218
|
nativeId: record.nativeEventId ?? null, sequence: record.sequence,
|
|
198
219
|
kind: record.kind, role: record.role ?? null, occurredAt: record.occurredAt ?? null,
|
|
220
|
+
activityBoundary: record.activityBoundary ?? null,
|
|
221
|
+
activityBoundaryBasis: record.activityBoundaryBasis ?? null,
|
|
222
|
+
activityBoundaryConfidence: record.activityBoundaryConfidence ?? null,
|
|
223
|
+
origin: origin.origin,
|
|
224
|
+
originRule: origin.rule,
|
|
225
|
+
originClassifierVersion: origin.classifierVersion,
|
|
199
226
|
participant: record.participant ?? null,
|
|
200
227
|
toolName: record.toolName ?? null,
|
|
201
228
|
toolCallId: record.toolCallId ?? null,
|
|
@@ -220,9 +247,13 @@ function normalizeBatch(request, records, importRunId) {
|
|
|
220
247
|
nativeSessionId: record.nativeSessionId, workspaceId: request.workspaceId,
|
|
221
248
|
startedAt: record.occurredAt ?? null, updatedAt: record.occurredAt ?? null,
|
|
222
249
|
consistency: request.source.consistency,
|
|
223
|
-
lifecycle
|
|
250
|
+
lifecycle,
|
|
224
251
|
sourceDigest: sha256(`${sourceGenerationDigest(request)}\0${record.nativeSessionId}`),
|
|
225
|
-
extensions: {
|
|
252
|
+
extensions: {
|
|
253
|
+
[`native.${request.source.provider}`]: {
|
|
254
|
+
lifecycleEvidence,
|
|
255
|
+
},
|
|
256
|
+
},
|
|
226
257
|
}));
|
|
227
258
|
}
|
|
228
259
|
else {
|
|
@@ -230,12 +261,23 @@ function normalizeBatch(request, records, importRunId) {
|
|
|
230
261
|
session.startedAt = earlierTimestamp(session.startedAt, record.occurredAt ?? null);
|
|
231
262
|
session.updatedAt = laterTimestamp(session.updatedAt, record.occurredAt ?? null);
|
|
232
263
|
session.consistency = strongerConsistency(session.consistency, request.source.consistency);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
264
|
+
const nativeKey = `native.${request.source.provider}`;
|
|
265
|
+
const nativeEnvelope = session.extensions[nativeKey];
|
|
266
|
+
const nativeRecord = nativeEnvelope && typeof nativeEnvelope === 'object' && !Array.isArray(nativeEnvelope)
|
|
267
|
+
? nativeEnvelope
|
|
268
|
+
: {};
|
|
269
|
+
const selected = selectLifecycleTransition(session.lifecycle, nativeRecord.lifecycleEvidence, lifecycle, lifecycleEvidence);
|
|
270
|
+
session.lifecycle = selected.lifecycle;
|
|
271
|
+
session.extensions[nativeKey] = {
|
|
272
|
+
...nativeRecord,
|
|
273
|
+
lifecycleEvidence: selected.evidence,
|
|
274
|
+
};
|
|
236
275
|
}
|
|
237
276
|
return event;
|
|
238
277
|
});
|
|
278
|
+
for (const session of sessions.values()) {
|
|
279
|
+
session.intent = deriveSessionIntent(events.filter((event) => event.sessionId === session.sessionId));
|
|
280
|
+
}
|
|
239
281
|
return { sessions: [...sessions.values()], events };
|
|
240
282
|
}
|
|
241
283
|
const KNOWN_EVENT_KINDS = new Set(['message', 'tool-call', 'tool-result', 'artifact', 'attachment', 'summary']);
|
|
@@ -261,6 +303,113 @@ function strongerConsistency(left, right) {
|
|
|
261
303
|
};
|
|
262
304
|
return rank[left] >= rank[right] ? left : right;
|
|
263
305
|
}
|
|
306
|
+
function sessionLifecycle(request, record, sourceObservedAt) {
|
|
307
|
+
const explicit = nativeLifecycle(record.extensions);
|
|
308
|
+
if (explicit)
|
|
309
|
+
return explicit;
|
|
310
|
+
if (request.source.consistency === 'complete')
|
|
311
|
+
return 'complete';
|
|
312
|
+
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
313
|
+
if (observedAt && isStaleHistoricalTimestamp(observedAt, inactivityThresholdMs(request)))
|
|
314
|
+
return 'inactive';
|
|
315
|
+
return 'active';
|
|
316
|
+
}
|
|
317
|
+
function sessionLifecycleEvidence(request, record, sourceObservedAt) {
|
|
318
|
+
const observedAt = record.occurredAt ?? sourceObservedAt;
|
|
319
|
+
const explicit = nativeLifecycle(record.extensions);
|
|
320
|
+
if (explicit) {
|
|
321
|
+
return {
|
|
322
|
+
basis: 'provider-explicit-event',
|
|
323
|
+
state: explicit,
|
|
324
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
325
|
+
confidence: 'high',
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (request.source.consistency === 'complete') {
|
|
329
|
+
return {
|
|
330
|
+
basis: 'complete-source',
|
|
331
|
+
state: 'complete',
|
|
332
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
333
|
+
confidence: 'high',
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
const thresholdMs = inactivityThresholdMs(request);
|
|
337
|
+
if (observedAt && isStaleHistoricalTimestamp(observedAt, thresholdMs)) {
|
|
338
|
+
return {
|
|
339
|
+
basis: 'inactivity-threshold',
|
|
340
|
+
state: 'inactive',
|
|
341
|
+
observedAt,
|
|
342
|
+
confidence: 'medium',
|
|
343
|
+
thresholdMs,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
basis: 'open-provisional-source',
|
|
348
|
+
state: 'active',
|
|
349
|
+
observedAt: observedAt ?? request.source.authorizedAt,
|
|
350
|
+
confidence: 'provisional',
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function nativeLifecycle(extensions) {
|
|
354
|
+
const raw = typeof extensions?.lifecycle === 'string' ? extensions.lifecycle : undefined;
|
|
355
|
+
if (!raw)
|
|
356
|
+
return null;
|
|
357
|
+
const normalized = {
|
|
358
|
+
active: 'active',
|
|
359
|
+
inactive: 'inactive',
|
|
360
|
+
paused: 'paused',
|
|
361
|
+
complete: 'complete',
|
|
362
|
+
completed: 'complete',
|
|
363
|
+
archived: 'archived',
|
|
364
|
+
deleted: 'tombstoned',
|
|
365
|
+
cancelled: 'interrupted',
|
|
366
|
+
canceled: 'interrupted',
|
|
367
|
+
failed: 'interrupted',
|
|
368
|
+
interrupted: 'interrupted',
|
|
369
|
+
unknown: 'unknown',
|
|
370
|
+
'unknown-at-import': 'unknown',
|
|
371
|
+
'completed-at-import': 'complete',
|
|
372
|
+
};
|
|
373
|
+
return normalized[raw] ?? null;
|
|
374
|
+
}
|
|
375
|
+
function selectLifecycleTransition(leftLifecycle, left, rightLifecycle, right) {
|
|
376
|
+
const leftEvidence = asLifecycleEvidence(left);
|
|
377
|
+
if (leftLifecycle === 'tombstoned') {
|
|
378
|
+
return { lifecycle: leftLifecycle, evidence: leftEvidence ?? right };
|
|
379
|
+
}
|
|
380
|
+
if (!leftEvidence)
|
|
381
|
+
return { lifecycle: rightLifecycle, evidence: right };
|
|
382
|
+
const rank = {
|
|
383
|
+
'open-provisional-source': 1,
|
|
384
|
+
'inactivity-threshold': 1,
|
|
385
|
+
'complete-source': 2,
|
|
386
|
+
'provider-explicit-event': 3,
|
|
387
|
+
};
|
|
388
|
+
const leftRank = rank[String(leftEvidence.basis)] ?? 0;
|
|
389
|
+
const rightRank = rank[String(right.basis)] ?? 0;
|
|
390
|
+
const rightIsNewer = evidenceTimestamp(right) > evidenceTimestamp(leftEvidence);
|
|
391
|
+
return rightRank > leftRank || (rightRank === leftRank && rightIsNewer)
|
|
392
|
+
? { lifecycle: rightLifecycle, evidence: right }
|
|
393
|
+
: { lifecycle: leftLifecycle, evidence: leftEvidence };
|
|
394
|
+
}
|
|
395
|
+
function asLifecycleEvidence(value) {
|
|
396
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
397
|
+
? value
|
|
398
|
+
: null;
|
|
399
|
+
}
|
|
400
|
+
function evidenceTimestamp(value) {
|
|
401
|
+
const parsed = Date.parse(String(value.observedAt ?? ''));
|
|
402
|
+
return Number.isFinite(parsed) ? parsed : Number.NEGATIVE_INFINITY;
|
|
403
|
+
}
|
|
404
|
+
const DEFAULT_INACTIVITY_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
405
|
+
function inactivityThresholdMs(request) {
|
|
406
|
+
return request.inactivityThresholdMs ?? DEFAULT_INACTIVITY_THRESHOLD_MS;
|
|
407
|
+
}
|
|
408
|
+
function isStaleHistoricalTimestamp(value, thresholdMs) {
|
|
409
|
+
const timestamp = Date.parse(value);
|
|
410
|
+
return Number.isFinite(timestamp)
|
|
411
|
+
&& Date.now() - timestamp > thresholdMs;
|
|
412
|
+
}
|
|
264
413
|
function sourceGenerationDigest(request) {
|
|
265
414
|
return sha256([
|
|
266
415
|
request.source.sourceId,
|
|
@@ -10,6 +10,12 @@ export * from './knowledge-shard.js';
|
|
|
10
10
|
export * from './candidates.js';
|
|
11
11
|
export * from './promotion.js';
|
|
12
12
|
export * from './importer.js';
|
|
13
|
+
export * from './import-lease.js';
|
|
14
|
+
export * from './batch-contracts.js';
|
|
15
|
+
export * from './batch-import.js';
|
|
16
|
+
export * from './workspace-discovery.js';
|
|
17
|
+
export * from './timeline.js';
|
|
18
|
+
export * from './origin.js';
|
|
13
19
|
export * from './adapters/generic.js';
|
|
14
20
|
export * from './adapters/claude.js';
|
|
15
21
|
export * from './adapters/codex.js';
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export const ORIGIN_CLASSIFIER_VERSION = '1.0.0';
|
|
2
|
+
export function classifySessionEventOrigin(provider, record) {
|
|
3
|
+
const envelope = classifyWholeEnvelope(record.text);
|
|
4
|
+
if (envelope)
|
|
5
|
+
return envelope;
|
|
6
|
+
const kind = record.kind.toLowerCase();
|
|
7
|
+
if (isProviderBootstrap(provider, kind)) {
|
|
8
|
+
return classified('provider-bootstrap', `${provider}:structured-bootstrap`);
|
|
9
|
+
}
|
|
10
|
+
if (isToolControl(kind, record.role)) {
|
|
11
|
+
return classified('tool-control', `${provider}:structured-control`);
|
|
12
|
+
}
|
|
13
|
+
if (record.role === 'assistant') {
|
|
14
|
+
return classified('assistant-generated', `${provider}:assistant-role`);
|
|
15
|
+
}
|
|
16
|
+
if (record.role === 'user' && kind === 'message' && record.text.trim().length > 0) {
|
|
17
|
+
return classified('user-authored', `${provider}:user-message`);
|
|
18
|
+
}
|
|
19
|
+
return classified('unknown', `${provider}:insufficient-authorship-evidence`);
|
|
20
|
+
}
|
|
21
|
+
export function isControlOrigin(origin) {
|
|
22
|
+
return origin === 'provider-bootstrap'
|
|
23
|
+
|| origin === 'workspace-instruction'
|
|
24
|
+
|| origin === 'tool-control';
|
|
25
|
+
}
|
|
26
|
+
export function deriveSessionIntent(events) {
|
|
27
|
+
const eligible = events
|
|
28
|
+
.filter((event) => event.origin === 'user-authored'
|
|
29
|
+
&& event.kind === 'message'
|
|
30
|
+
&& event.searchableText.trim().length > 0)
|
|
31
|
+
.sort((left, right) => left.sequence - right.sequence || left.eventId.localeCompare(right.eventId));
|
|
32
|
+
const selected = eligible[0];
|
|
33
|
+
if (selected) {
|
|
34
|
+
const summary = normalizeExcerpt(selected.searchableText, 240);
|
|
35
|
+
return {
|
|
36
|
+
status: 'selected',
|
|
37
|
+
eventId: selected.eventId,
|
|
38
|
+
sequence: selected.sequence,
|
|
39
|
+
title: normalizeExcerpt(summary.split('\n')[0], 80),
|
|
40
|
+
summary,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const uncertain = events.some((event) => event.origin === 'unknown' && event.searchableText.trim().length > 0);
|
|
44
|
+
return {
|
|
45
|
+
status: uncertain ? 'unknown' : 'absent',
|
|
46
|
+
eventId: null,
|
|
47
|
+
sequence: null,
|
|
48
|
+
title: null,
|
|
49
|
+
summary: null,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function classifyWholeEnvelope(text) {
|
|
53
|
+
const trimmed = text.trim();
|
|
54
|
+
if (!trimmed)
|
|
55
|
+
return null;
|
|
56
|
+
if (/^# AGENTS\.md instructions for [^\n]+\n+<INSTRUCTIONS>\n[\s\S]*\n<\/INSTRUCTIONS>$/.test(trimmed)) {
|
|
57
|
+
return classified('workspace-instruction', 'envelope:agents-instructions');
|
|
58
|
+
}
|
|
59
|
+
for (const tag of [
|
|
60
|
+
'recommended_plugins',
|
|
61
|
+
'codex_internal_context',
|
|
62
|
+
'environment_context',
|
|
63
|
+
]) {
|
|
64
|
+
if (wholeTag(trimmed, tag)) {
|
|
65
|
+
return classified('provider-bootstrap', `envelope:${tag}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (wholeTag(trimmed, 'local-command-caveat')) {
|
|
69
|
+
return classified('tool-control', 'envelope:local-command-caveat');
|
|
70
|
+
}
|
|
71
|
+
if (/^<[A-Za-z_][\w.-]*(?:\s[^>]*)?>[\s\S]*<\/[A-Za-z_][\w.-]*>$/.test(trimmed)) {
|
|
72
|
+
return classified('unknown', 'envelope:unrecognized');
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function wholeTag(value, tag) {
|
|
77
|
+
const escaped = tag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
78
|
+
return new RegExp(`^<${escaped}(?:\\s[^>]*)?>[\\s\\S]*<\\/${escaped}>$`).test(value);
|
|
79
|
+
}
|
|
80
|
+
function isProviderBootstrap(provider, kind) {
|
|
81
|
+
if (provider === 'codex') {
|
|
82
|
+
return kind === 'codex.session_meta'
|
|
83
|
+
|| kind === 'codex.turn_context'
|
|
84
|
+
|| kind === 'codex.thread-state';
|
|
85
|
+
}
|
|
86
|
+
if (provider === 'factory') {
|
|
87
|
+
return kind === 'factory.session_start' || kind === 'factory.settings';
|
|
88
|
+
}
|
|
89
|
+
if (provider === 'cursor')
|
|
90
|
+
return kind === 'system';
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
function isToolControl(kind, role) {
|
|
94
|
+
return role === 'tool'
|
|
95
|
+
|| role === 'system'
|
|
96
|
+
|| kind === 'lifecycle-hook'
|
|
97
|
+
|| kind === 'tool-call'
|
|
98
|
+
|| kind === 'tool-result'
|
|
99
|
+
|| kind === 'summary'
|
|
100
|
+
|| kind.includes('lifecycle')
|
|
101
|
+
|| kind.startsWith('tool.')
|
|
102
|
+
|| kind.startsWith('cursor.cloud.')
|
|
103
|
+
|| kind === 'cursor.agent.turn_ended'
|
|
104
|
+
|| kind === 'factory.session_end';
|
|
105
|
+
}
|
|
106
|
+
function classified(origin, rule) {
|
|
107
|
+
return {
|
|
108
|
+
origin,
|
|
109
|
+
rule,
|
|
110
|
+
classifierVersion: ORIGIN_CLASSIFIER_VERSION,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function normalizeExcerpt(value, max) {
|
|
114
|
+
const normalized = value.replace(/\s+/g, ' ').trim();
|
|
115
|
+
return normalized.length <= max ? normalized : `${normalized.slice(0, max - 1)}…`;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=origin.js.map
|
|
@@ -6,7 +6,7 @@ import { SessionContractError } from './contracts.js';
|
|
|
6
6
|
import { authorizeSourceFile } from './policy.js';
|
|
7
7
|
export const DEFAULT_READER_LIMITS = Object.freeze({
|
|
8
8
|
maxRecords: 1_000_000,
|
|
9
|
-
maxRecordBytes:
|
|
9
|
+
maxRecordBytes: 8 * 1024 * 1024,
|
|
10
10
|
maxTotalBytes: 1024 * 1024 * 1024,
|
|
11
11
|
maxNestingDepth: 64,
|
|
12
12
|
});
|