sidekick-shared 0.29.0 → 0.30.0
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/CHANGELOG.md +48 -0
- package/README.md +198 -56
- package/dist/aggregation/EventAggregator.d.ts +96 -2
- package/dist/aggregation/EventAggregator.js +535 -42
- package/dist/aggregation/snapshot.d.ts +37 -8
- package/dist/aggregation/snapshot.js +31 -9
- package/dist/aggregation/types.d.ts +38 -1
- package/dist/browser.d.ts +9 -1
- package/dist/browser.js +29 -3
- package/dist/context/sessionContext.js +8 -0
- package/dist/esm/aggregation/EventAggregator.js +535 -42
- package/dist/esm/aggregation/snapshot.js +31 -9
- package/dist/esm/browser.js +3 -0
- package/dist/esm/context/sessionContext.js +8 -0
- package/dist/esm/fileContinuity.js +149 -0
- package/dist/esm/formatters/toolSummary.js +4 -1
- package/dist/esm/index.js +7 -2
- package/dist/esm/modelCatalog.js +5 -4
- package/dist/esm/modelContext.js +4 -3
- package/dist/esm/modelInfo.js +4 -3
- package/dist/esm/node.js +3 -1
- package/dist/esm/observedContextWindows.js +2 -1
- package/dist/esm/ownKey.js +26 -0
- package/dist/esm/parsers/codexParser.js +372 -7
- package/dist/esm/parsers/openCodeParser.js +2 -1
- package/dist/esm/parsers/subagentEndState.js +61 -0
- package/dist/esm/parsers/subagentScanner.js +37 -12
- package/dist/esm/parsers/subagentTraceParser.js +103 -37
- package/dist/esm/pricingCatalog.js +3 -2
- package/dist/esm/promptHistory.js +22 -11
- package/dist/esm/providers/claudeCode.js +60 -29
- package/dist/esm/providers/codex.js +235 -201
- package/dist/esm/providers/codexCompressedReader.js +184 -0
- package/dist/esm/providers/codexDatabase.js +47 -2
- package/dist/esm/providers/codexRollouts.js +20 -2
- package/dist/esm/providers/codexSubagents.js +456 -0
- package/dist/esm/providers/compressedRollouts.js +330 -0
- package/dist/esm/providers/factory.js +4 -1
- package/dist/esm/providers/rolloutWalker.js +32 -4
- package/dist/esm/schemas/sessionEvent.js +63 -14
- package/dist/esm/sessionMonitor.js +7 -1
- package/dist/esm/sessionPreviews.js +9 -0
- package/dist/esm/sessionPromptHistory.js +5 -3
- package/dist/esm/subagentActivity.js +125 -0
- package/dist/esm/subagentDisplayState.js +81 -0
- package/dist/esm/subagentSpawn.js +363 -0
- package/dist/esm/testing/codexSubagentFixtures.js +336 -0
- package/dist/esm/toolCallOrigins.js +17 -10
- package/dist/esm/toolCategory.js +6 -2
- package/dist/esm/transcript.js +8 -0
- package/dist/esm/turns/assistantTurn.js +6 -2
- package/dist/esm/usage/claudeUsageDedupe.js +68 -0
- package/dist/esm/usage/usageEvents.js +4 -1
- package/dist/esm/watchers/eventBridge.js +45 -0
- package/dist/esm/watchers/factory.js +5 -3
- package/dist/esm/watchers/jsonlTail.js +82 -48
- package/dist/esm/watchers/jsonlWatcher.js +61 -4
- package/dist/esm/watchers/providerReaderWatcher.js +18 -4
- package/dist/esm/zaiQuota.js +2 -1
- package/dist/fileContinuity.d.ts +95 -0
- package/dist/fileContinuity.js +187 -0
- package/dist/formatters/toolSummary.js +4 -1
- package/dist/index.d.ts +19 -7
- package/dist/index.js +48 -10
- package/dist/modelCatalog.js +5 -4
- package/dist/modelContext.js +4 -3
- package/dist/modelInfo.js +4 -3
- package/dist/node.d.ts +5 -1
- package/dist/node.js +18 -2
- package/dist/observedContextWindows.js +2 -1
- package/dist/ownKey.d.ts +16 -0
- package/dist/ownKey.js +30 -0
- package/dist/parsers/codexParser.d.ts +107 -0
- package/dist/parsers/codexParser.js +373 -7
- package/dist/parsers/openCodeParser.js +2 -1
- package/dist/parsers/subagentEndState.d.ts +20 -0
- package/dist/parsers/subagentEndState.js +65 -0
- package/dist/parsers/subagentScanner.d.ts +19 -6
- package/dist/parsers/subagentScanner.js +37 -12
- package/dist/parsers/subagentTraceParser.d.ts +33 -5
- package/dist/parsers/subagentTraceParser.js +103 -37
- package/dist/pricingCatalog.js +3 -2
- package/dist/promptHistory.d.ts +13 -3
- package/dist/promptHistory.js +22 -11
- package/dist/providers/claudeCode.js +59 -28
- package/dist/providers/codex.d.ts +35 -5
- package/dist/providers/codex.js +232 -198
- package/dist/providers/codexCompressedReader.d.ts +58 -0
- package/dist/providers/codexCompressedReader.js +221 -0
- package/dist/providers/codexDatabase.d.ts +25 -0
- package/dist/providers/codexDatabase.js +48 -2
- package/dist/providers/codexRollouts.d.ts +16 -2
- package/dist/providers/codexRollouts.js +20 -2
- package/dist/providers/codexSubagents.d.ts +66 -0
- package/dist/providers/codexSubagents.js +495 -0
- package/dist/providers/compressedRollouts.d.ts +114 -0
- package/dist/providers/compressedRollouts.js +380 -0
- package/dist/providers/factory.d.ts +5 -0
- package/dist/providers/factory.js +4 -1
- package/dist/providers/rolloutWalker.d.ts +15 -2
- package/dist/providers/rolloutWalker.js +33 -4
- package/dist/providers/types.d.ts +36 -1
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/sessionEvent.d.ts +51 -10
- package/dist/schemas/sessionEvent.js +63 -14
- package/dist/sessionMonitor.d.ts +6 -0
- package/dist/sessionMonitor.js +7 -1
- package/dist/sessionPreviews.js +9 -0
- package/dist/sessionPromptHistory.d.ts +5 -0
- package/dist/sessionPromptHistory.js +5 -36
- package/dist/subagentActivity.d.ts +91 -0
- package/dist/subagentActivity.js +132 -0
- package/dist/subagentDisplayState.d.ts +81 -0
- package/dist/subagentDisplayState.js +86 -0
- package/dist/subagentSpawn.d.ts +175 -0
- package/dist/subagentSpawn.js +385 -0
- package/dist/testing/codexSubagentFixtures.d.ts +48 -0
- package/dist/testing/codexSubagentFixtures.js +344 -0
- package/dist/toolCallOrigins.d.ts +5 -0
- package/dist/toolCallOrigins.js +17 -10
- package/dist/toolCategory.js +6 -2
- package/dist/transcript.js +8 -0
- package/dist/turns/assistantTurn.d.ts +4 -0
- package/dist/turns/assistantTurn.js +6 -2
- package/dist/types/codex.d.ts +71 -2
- package/dist/types/sessionEvent.d.ts +38 -3
- package/dist/usage/claudeUsageDedupe.d.ts +31 -0
- package/dist/usage/claudeUsageDedupe.js +68 -0
- package/dist/usage/usageEvents.d.ts +4 -1
- package/dist/usage/usageEvents.js +4 -1
- package/dist/watchers/eventBridge.js +45 -0
- package/dist/watchers/factory.d.ts +6 -0
- package/dist/watchers/factory.js +5 -3
- package/dist/watchers/jsonlTail.d.ts +27 -4
- package/dist/watchers/jsonlTail.js +84 -48
- package/dist/watchers/jsonlWatcher.d.ts +22 -1
- package/dist/watchers/jsonlWatcher.js +60 -3
- package/dist/watchers/providerReaderWatcher.d.ts +7 -0
- package/dist/watchers/providerReaderWatcher.js +18 -4
- package/dist/watchers/types.d.ts +12 -0
- package/dist/zaiQuota.js +2 -1
- package/package.json +1 -1
|
@@ -60,9 +60,11 @@ export declare const sessionMessageSchema: z.ZodObject<{
|
|
|
60
60
|
}, z.core.$strip>;
|
|
61
61
|
export declare const permissionModeSchema: z.ZodEnum<{
|
|
62
62
|
default: "default";
|
|
63
|
+
auto: "auto";
|
|
63
64
|
acceptEdits: "acceptEdits";
|
|
64
65
|
bypassPermissions: "bypassPermissions";
|
|
65
66
|
plan: "plan";
|
|
67
|
+
dontAsk: "dontAsk";
|
|
66
68
|
}>;
|
|
67
69
|
export declare const userSessionEventSchema: z.ZodObject<{
|
|
68
70
|
timestamp: z.ZodString;
|
|
@@ -76,12 +78,14 @@ export declare const userSessionEventSchema: z.ZodObject<{
|
|
|
76
78
|
promptSource: z.ZodOptional<z.ZodString>;
|
|
77
79
|
cwd: z.ZodOptional<z.ZodString>;
|
|
78
80
|
gitBranch: z.ZodOptional<z.ZodString>;
|
|
79
|
-
permissionMode: z.ZodOptional<z.ZodEnum<{
|
|
81
|
+
permissionMode: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
|
|
80
82
|
default: "default";
|
|
83
|
+
auto: "auto";
|
|
81
84
|
acceptEdits: "acceptEdits";
|
|
82
85
|
bypassPermissions: "bypassPermissions";
|
|
83
86
|
plan: "plan";
|
|
84
|
-
|
|
87
|
+
dontAsk: "dontAsk";
|
|
88
|
+
}>>>;
|
|
85
89
|
rateLimits: z.ZodOptional<z.ZodObject<{
|
|
86
90
|
primary: z.ZodOptional<z.ZodObject<{
|
|
87
91
|
usedPercent: z.ZodNumber;
|
|
@@ -165,12 +169,14 @@ export declare const assistantSessionEventSchema: z.ZodObject<{
|
|
|
165
169
|
promptSource: z.ZodOptional<z.ZodString>;
|
|
166
170
|
cwd: z.ZodOptional<z.ZodString>;
|
|
167
171
|
gitBranch: z.ZodOptional<z.ZodString>;
|
|
168
|
-
permissionMode: z.ZodOptional<z.ZodEnum<{
|
|
172
|
+
permissionMode: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
|
|
169
173
|
default: "default";
|
|
174
|
+
auto: "auto";
|
|
170
175
|
acceptEdits: "acceptEdits";
|
|
171
176
|
bypassPermissions: "bypassPermissions";
|
|
172
177
|
plan: "plan";
|
|
173
|
-
|
|
178
|
+
dontAsk: "dontAsk";
|
|
179
|
+
}>>>;
|
|
174
180
|
rateLimits: z.ZodOptional<z.ZodObject<{
|
|
175
181
|
primary: z.ZodOptional<z.ZodObject<{
|
|
176
182
|
usedPercent: z.ZodNumber;
|
|
@@ -244,6 +250,7 @@ export declare const assistantSessionEventSchema: z.ZodObject<{
|
|
|
244
250
|
}, z.core.$strip>;
|
|
245
251
|
export declare const summarySessionEventSchema: z.ZodType<SummarySessionEvent>;
|
|
246
252
|
export declare const systemSessionEventSchema: z.ZodObject<{
|
|
253
|
+
subtype: z.ZodCatch<z.ZodOptional<z.ZodString>>;
|
|
247
254
|
timestamp: z.ZodString;
|
|
248
255
|
entrypoint: z.ZodOptional<z.ZodString>;
|
|
249
256
|
isMeta: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -255,12 +262,14 @@ export declare const systemSessionEventSchema: z.ZodObject<{
|
|
|
255
262
|
promptSource: z.ZodOptional<z.ZodString>;
|
|
256
263
|
cwd: z.ZodOptional<z.ZodString>;
|
|
257
264
|
gitBranch: z.ZodOptional<z.ZodString>;
|
|
258
|
-
permissionMode: z.ZodOptional<z.ZodEnum<{
|
|
265
|
+
permissionMode: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
|
|
259
266
|
default: "default";
|
|
267
|
+
auto: "auto";
|
|
260
268
|
acceptEdits: "acceptEdits";
|
|
261
269
|
bypassPermissions: "bypassPermissions";
|
|
262
270
|
plan: "plan";
|
|
263
|
-
|
|
271
|
+
dontAsk: "dontAsk";
|
|
272
|
+
}>>>;
|
|
264
273
|
rateLimits: z.ZodOptional<z.ZodObject<{
|
|
265
274
|
primary: z.ZodOptional<z.ZodObject<{
|
|
266
275
|
usedPercent: z.ZodNumber;
|
|
@@ -348,12 +357,14 @@ export declare const toolUseSessionEventSchema: z.ZodObject<{
|
|
|
348
357
|
promptSource: z.ZodOptional<z.ZodString>;
|
|
349
358
|
cwd: z.ZodOptional<z.ZodString>;
|
|
350
359
|
gitBranch: z.ZodOptional<z.ZodString>;
|
|
351
|
-
permissionMode: z.ZodOptional<z.ZodEnum<{
|
|
360
|
+
permissionMode: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
|
|
352
361
|
default: "default";
|
|
362
|
+
auto: "auto";
|
|
353
363
|
acceptEdits: "acceptEdits";
|
|
354
364
|
bypassPermissions: "bypassPermissions";
|
|
355
365
|
plan: "plan";
|
|
356
|
-
|
|
366
|
+
dontAsk: "dontAsk";
|
|
367
|
+
}>>>;
|
|
357
368
|
rateLimits: z.ZodOptional<z.ZodObject<{
|
|
358
369
|
primary: z.ZodOptional<z.ZodObject<{
|
|
359
370
|
usedPercent: z.ZodNumber;
|
|
@@ -442,12 +453,14 @@ export declare const toolResultSessionEventSchema: z.ZodObject<{
|
|
|
442
453
|
promptSource: z.ZodOptional<z.ZodString>;
|
|
443
454
|
cwd: z.ZodOptional<z.ZodString>;
|
|
444
455
|
gitBranch: z.ZodOptional<z.ZodString>;
|
|
445
|
-
permissionMode: z.ZodOptional<z.ZodEnum<{
|
|
456
|
+
permissionMode: z.ZodCatch<z.ZodOptional<z.ZodEnum<{
|
|
446
457
|
default: "default";
|
|
458
|
+
auto: "auto";
|
|
447
459
|
acceptEdits: "acceptEdits";
|
|
448
460
|
bypassPermissions: "bypassPermissions";
|
|
449
461
|
plan: "plan";
|
|
450
|
-
|
|
462
|
+
dontAsk: "dontAsk";
|
|
463
|
+
}>>>;
|
|
451
464
|
rateLimits: z.ZodOptional<z.ZodObject<{
|
|
452
465
|
primary: z.ZodOptional<z.ZodObject<{
|
|
453
466
|
usedPercent: z.ZodNumber;
|
|
@@ -520,6 +533,30 @@ export declare const toolResultSessionEventSchema: z.ZodObject<{
|
|
|
520
533
|
}, z.core.$strip>>;
|
|
521
534
|
}, z.core.$strip>;
|
|
522
535
|
export declare const sessionEventSchema: z.ZodType<SessionEvent>;
|
|
536
|
+
/** Options for {@link extractSessionEvents}. */
|
|
537
|
+
export interface ExtractSessionEventsOptions {
|
|
538
|
+
/**
|
|
539
|
+
* Also turn Claude Code's mid-turn task-notification attachments
|
|
540
|
+
* (`{ type: 'attachment', attachment: { type: 'queued_command',
|
|
541
|
+
* commandMode: 'task-notification', prompt } }`) into one `system` event
|
|
542
|
+
* with `origin: { kind: 'task-notification' }`, `message: { role: 'user',
|
|
543
|
+
* sourceLabel: 'task notification', content: <prompt> }`, and the line's
|
|
544
|
+
* timestamp. They report background agents finishing (or, as plain text,
|
|
545
|
+
* the user stopping them: see `parseAgentsStoppedNotice`).
|
|
546
|
+
*
|
|
547
|
+
* Also turns a background agent's `task_status` attachment with a final
|
|
548
|
+
* status (`{ type: 'attachment', attachment: { type: 'task_status',
|
|
549
|
+
* taskType: 'local_agent', taskId, status: 'completed', … } }`) into a
|
|
550
|
+
* `system` event with `origin: { kind: 'task-status' }` and `message: {
|
|
551
|
+
* role: 'system', sourceLabel: 'task status', content: [{ type:
|
|
552
|
+
* 'task_status', taskId, taskType, status, description }] }` (read it with
|
|
553
|
+
* `taskStatusFromEvent`). Default `false`: attachment lines yield no events.
|
|
554
|
+
*
|
|
555
|
+
* System lines (`agents_killed` among them) parse either way and keep
|
|
556
|
+
* their `subtype`.
|
|
557
|
+
*/
|
|
558
|
+
includeTaskNotifications?: boolean;
|
|
559
|
+
}
|
|
523
560
|
/**
|
|
524
561
|
* Extracts canonical SessionEvents from a raw JSONL value.
|
|
525
562
|
*
|
|
@@ -528,5 +565,9 @@ export declare const sessionEventSchema: z.ZodType<SessionEvent>;
|
|
|
528
565
|
* `sessionEventSchema` alone rejects. This helper tries a direct parse,
|
|
529
566
|
* then unwraps progress envelopes (recursively, in case of nesting).
|
|
530
567
|
* Returns zero events for unrecognized input — never throws.
|
|
568
|
+
*
|
|
569
|
+
* The second argument is either the starting progress depth (the original
|
|
570
|
+
* signature) or an options object.
|
|
531
571
|
*/
|
|
532
572
|
export declare function extractSessionEvents(raw: unknown, depth?: number): SessionEvent[];
|
|
573
|
+
export declare function extractSessionEvents(raw: unknown, options?: ExtractSessionEventsOptions): SessionEvent[];
|
|
@@ -12,6 +12,7 @@ exports.sessionEventSchema = exports.toolResultSessionEventSchema = exports.tool
|
|
|
12
12
|
exports.extractSessionEvents = extractSessionEvents;
|
|
13
13
|
const zod_1 = require("zod");
|
|
14
14
|
const usageNormalization_1 = require("./usageNormalization");
|
|
15
|
+
const subagentSpawn_1 = require("../subagentSpawn");
|
|
15
16
|
// ── MessageUsage ──
|
|
16
17
|
exports.messageUsageSchema = zod_1.z.object({
|
|
17
18
|
input_tokens: zod_1.z.number(),
|
|
@@ -44,6 +45,8 @@ exports.permissionModeSchema = zod_1.z.enum([
|
|
|
44
45
|
'acceptEdits',
|
|
45
46
|
'bypassPermissions',
|
|
46
47
|
'plan',
|
|
48
|
+
'auto',
|
|
49
|
+
'dontAsk',
|
|
47
50
|
]);
|
|
48
51
|
// ── SessionEvent ──
|
|
49
52
|
const eventBaseShape = {
|
|
@@ -56,7 +59,9 @@ const eventBaseShape = {
|
|
|
56
59
|
promptSource: zod_1.z.string().optional(),
|
|
57
60
|
cwd: zod_1.z.string().optional(),
|
|
58
61
|
gitBranch: zod_1.z.string().optional(),
|
|
59
|
-
|
|
62
|
+
// A mode this release doesn't know is dropped rather than rejecting the
|
|
63
|
+
// whole line with its prompt or tool results.
|
|
64
|
+
permissionMode: exports.permissionModeSchema.optional().catch(undefined),
|
|
60
65
|
rateLimits: zod_1.z
|
|
61
66
|
.object({
|
|
62
67
|
primary: zod_1.z
|
|
@@ -145,6 +150,9 @@ exports.systemSessionEventSchema = zod_1.z.object({
|
|
|
145
150
|
type: zod_1.z.literal('system'),
|
|
146
151
|
message: exports.sessionMessageSchema.optional(),
|
|
147
152
|
...eventBaseShape,
|
|
153
|
+
// Claude Code's system-line subtype (`agents_killed`, `turn_duration`, …);
|
|
154
|
+
// a malformed one is dropped rather than rejecting the line.
|
|
155
|
+
subtype: zod_1.z.string().optional().catch(undefined),
|
|
148
156
|
});
|
|
149
157
|
exports.toolUseSessionEventSchema = zod_1.z.object({
|
|
150
158
|
type: zod_1.z.literal('tool_use'),
|
|
@@ -173,22 +181,21 @@ exports.sessionEventSchema = zod_1.z.union([
|
|
|
173
181
|
// ── Progress unwrapping ──
|
|
174
182
|
/** Recursion bound for nested progress envelopes; real data nests 1 level. */
|
|
175
183
|
const MAX_PROGRESS_DEPTH = 8;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
* `sessionEventSchema` alone rejects. This helper tries a direct parse,
|
|
182
|
-
* then unwraps progress envelopes (recursively, in case of nesting).
|
|
183
|
-
* Returns zero events for unrecognized input — never throws.
|
|
184
|
-
*/
|
|
185
|
-
function extractSessionEvents(raw, depth = 0) {
|
|
186
|
-
return extractSessionEventsWithProvenance(raw, depth, {});
|
|
184
|
+
function extractSessionEvents(raw, depthOrOptions = 0) {
|
|
185
|
+
if (typeof depthOrOptions === 'number') {
|
|
186
|
+
return extractSessionEventsWithProvenance(raw, depthOrOptions, {}, {});
|
|
187
|
+
}
|
|
188
|
+
return extractSessionEventsWithProvenance(raw, 0, {}, depthOrOptions ?? {});
|
|
187
189
|
}
|
|
188
|
-
function extractSessionEventsWithProvenance(raw, depth, inherited) {
|
|
190
|
+
function extractSessionEventsWithProvenance(raw, depth, inherited, options) {
|
|
189
191
|
const direct = exports.sessionEventSchema.safeParse(raw);
|
|
190
192
|
if (direct.success)
|
|
191
193
|
return [{ ...inherited, ...direct.data }];
|
|
194
|
+
if (options.includeTaskNotifications) {
|
|
195
|
+
const notification = taskNotificationAttachmentEvent(raw) ?? taskStatusAttachmentEvent(raw);
|
|
196
|
+
if (notification)
|
|
197
|
+
return [{ ...inherited, ...notification }];
|
|
198
|
+
}
|
|
192
199
|
if (depth >= MAX_PROGRESS_DEPTH)
|
|
193
200
|
return [];
|
|
194
201
|
if (typeof raw === 'object' && raw !== null && raw.type === 'progress') {
|
|
@@ -197,12 +204,54 @@ function extractSessionEventsWithProvenance(raw, depth, inherited) {
|
|
|
197
204
|
if (typeof data === 'object' && data !== null) {
|
|
198
205
|
const message = data.message;
|
|
199
206
|
if (typeof message === 'object' && message !== null) {
|
|
200
|
-
return extractSessionEventsWithProvenance(message, depth + 1, provenance);
|
|
207
|
+
return extractSessionEventsWithProvenance(message, depth + 1, provenance, options);
|
|
201
208
|
}
|
|
202
209
|
}
|
|
203
210
|
}
|
|
204
211
|
return [];
|
|
205
212
|
}
|
|
213
|
+
/** The `system` event for a task-notification attachment line, or `null`. */
|
|
214
|
+
function taskNotificationAttachmentEvent(raw) {
|
|
215
|
+
const prompt = (0, subagentSpawn_1.taskNotificationPromptFromAttachment)(raw);
|
|
216
|
+
if (prompt === null)
|
|
217
|
+
return null;
|
|
218
|
+
const line = raw;
|
|
219
|
+
const candidate = {
|
|
220
|
+
type: 'system',
|
|
221
|
+
timestamp: line.timestamp,
|
|
222
|
+
origin: { kind: 'task-notification' },
|
|
223
|
+
message: { role: 'user', sourceLabel: 'task notification', content: prompt },
|
|
224
|
+
};
|
|
225
|
+
for (const key of ['entrypoint', 'isSidechain', 'cwd', 'gitBranch']) {
|
|
226
|
+
if (line[key] !== undefined)
|
|
227
|
+
candidate[key] = line[key];
|
|
228
|
+
}
|
|
229
|
+
const parsed = exports.systemSessionEventSchema.safeParse(candidate);
|
|
230
|
+
return parsed.success ? parsed.data : null;
|
|
231
|
+
}
|
|
232
|
+
/** The `system` event for a background agent's final `task_status` attachment, or `null`. */
|
|
233
|
+
function taskStatusAttachmentEvent(raw) {
|
|
234
|
+
const status = (0, subagentSpawn_1.taskStatusFromAttachment)(raw);
|
|
235
|
+
if (!status || !(0, subagentSpawn_1.isFinalTaskStatus)(status.status))
|
|
236
|
+
return null;
|
|
237
|
+
const line = raw;
|
|
238
|
+
const candidate = {
|
|
239
|
+
type: 'system',
|
|
240
|
+
timestamp: line.timestamp,
|
|
241
|
+
origin: { kind: subagentSpawn_1.TASK_STATUS_ORIGIN_KIND },
|
|
242
|
+
message: {
|
|
243
|
+
role: 'system',
|
|
244
|
+
sourceLabel: 'task status',
|
|
245
|
+
content: [{ type: subagentSpawn_1.TASK_STATUS_BLOCK_TYPE, ...status }],
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
for (const key of ['entrypoint', 'isSidechain', 'cwd', 'gitBranch']) {
|
|
249
|
+
if (line[key] !== undefined)
|
|
250
|
+
candidate[key] = line[key];
|
|
251
|
+
}
|
|
252
|
+
const parsed = exports.systemSessionEventSchema.safeParse(candidate);
|
|
253
|
+
return parsed.success ? parsed.data : null;
|
|
254
|
+
}
|
|
206
255
|
function progressProvenance(raw) {
|
|
207
256
|
const value = raw;
|
|
208
257
|
const provenance = {};
|
package/dist/sessionMonitor.d.ts
CHANGED
|
@@ -25,6 +25,12 @@ export declare class SessionMonitor {
|
|
|
25
25
|
constructor(provider: SessionProviderBase, options?: SessionMonitorOptions);
|
|
26
26
|
attach(sessionPath: string, replay?: boolean): AggregatedMetrics;
|
|
27
27
|
attachLatest(workspacePath: string, replay?: boolean): AggregatedMetrics | null;
|
|
28
|
+
/**
|
|
29
|
+
* Reads and aggregates what the session gained since the last call. When
|
|
30
|
+
* the reader had to start over (the file was truncated, rewritten, or
|
|
31
|
+
* replaced) the aggregator is reset first and the returned events are the
|
|
32
|
+
* session from the beginning.
|
|
33
|
+
*/
|
|
28
34
|
poll(): SessionEvent[];
|
|
29
35
|
process(event: SessionEvent): void;
|
|
30
36
|
onEvent(listener: (event: SessionEvent) => void): () => void;
|
package/dist/sessionMonitor.js
CHANGED
|
@@ -67,12 +67,18 @@ class SessionMonitor {
|
|
|
67
67
|
const sessionPath = this.provider.findActiveSession(workspacePath);
|
|
68
68
|
return sessionPath ? this.attach(sessionPath, replay) : null;
|
|
69
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Reads and aggregates what the session gained since the last call. When
|
|
72
|
+
* the reader had to start over (the file was truncated, rewritten, or
|
|
73
|
+
* replaced) the aggregator is reset first and the returned events are the
|
|
74
|
+
* session from the beginning.
|
|
75
|
+
*/
|
|
70
76
|
poll() {
|
|
71
77
|
if (!this.reader)
|
|
72
78
|
return [];
|
|
79
|
+
const events = this.reader.readNew();
|
|
73
80
|
if (this.reader.wasTruncated())
|
|
74
81
|
this.aggregator.reset();
|
|
75
|
-
const events = this.reader.readNew();
|
|
76
82
|
this.consume(events);
|
|
77
83
|
return events;
|
|
78
84
|
}
|
package/dist/sessionPreviews.js
CHANGED
|
@@ -57,6 +57,7 @@ exports.readSessionPreviewAsync = readSessionPreviewAsync;
|
|
|
57
57
|
exports.listSessionPreviews = listSessionPreviews;
|
|
58
58
|
exports.listSessionPreviewsAsync = listSessionPreviewsAsync;
|
|
59
59
|
const fs = __importStar(require("fs"));
|
|
60
|
+
const compressedRollouts_1 = require("./providers/compressedRollouts");
|
|
60
61
|
function emptyPrefixScan() {
|
|
61
62
|
return { firstTimestamp: null, workspacePath: null };
|
|
62
63
|
}
|
|
@@ -454,6 +455,12 @@ function scanPrefix(sessionPath, maxPrefixBytes) {
|
|
|
454
455
|
const result = { firstTimestamp: null, workspacePath: null };
|
|
455
456
|
let content;
|
|
456
457
|
let sawWholeFile;
|
|
458
|
+
if ((0, compressedRollouts_1.isCompressedRolloutPath)(sessionPath)) {
|
|
459
|
+
// A compressed Codex rollout: scan its decompressed prefix.
|
|
460
|
+
const head = (0, compressedRollouts_1.readRolloutHead)(sessionPath, Math.max(1, maxPrefixBytes) + 1);
|
|
461
|
+
parsePrefixInto(result, head.subarray(0, Math.max(1, maxPrefixBytes)).toString('utf8'), head.length <= maxPrefixBytes);
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
457
464
|
try {
|
|
458
465
|
const descriptor = fs.openSync(sessionPath, 'r');
|
|
459
466
|
try {
|
|
@@ -509,6 +516,8 @@ function scanPrefix(sessionPath, maxPrefixBytes) {
|
|
|
509
516
|
}
|
|
510
517
|
async function scanPrefixAsync(sessionPath, maxPrefixBytes) {
|
|
511
518
|
const result = { firstTimestamp: null, workspacePath: null };
|
|
519
|
+
if ((0, compressedRollouts_1.isCompressedRolloutPath)(sessionPath))
|
|
520
|
+
return scanPrefix(sessionPath, maxPrefixBytes);
|
|
512
521
|
let handle = null;
|
|
513
522
|
try {
|
|
514
523
|
handle = await fs.promises.open(sessionPath, 'r');
|
|
@@ -62,6 +62,11 @@ export interface CollectSessionPromptHistoryOptions {
|
|
|
62
62
|
include?: SessionPromptHistoryInclude;
|
|
63
63
|
bounds?: SessionPromptHistoryBounds;
|
|
64
64
|
signal?: AbortSignal;
|
|
65
|
+
/**
|
|
66
|
+
* Codex: also read compressed rollouts (`….jsonl.zst`), as for
|
|
67
|
+
* `collectPromptHistory()`. Default false.
|
|
68
|
+
*/
|
|
69
|
+
includeCompressedRollouts?: boolean;
|
|
65
70
|
}
|
|
66
71
|
export interface PromptHistorySessionPrompt extends Omit<PromptHistoryEntry, 'provider' | 'sessionId' | 'sessionKey'> {
|
|
67
72
|
/** With `include.replies`: the agent's last text for this prompt's turn. */
|
|
@@ -14,42 +14,9 @@
|
|
|
14
14
|
* `sessionIds` continues. Scope fails closed as in `collectPromptHistory()`,
|
|
15
15
|
* and replies or signals that belong to an out-of-scope prompt are dropped.
|
|
16
16
|
*/
|
|
17
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
-
if (k2 === undefined) k2 = k;
|
|
19
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
-
}
|
|
23
|
-
Object.defineProperty(o, k2, desc);
|
|
24
|
-
}) : (function(o, m, k, k2) {
|
|
25
|
-
if (k2 === undefined) k2 = k;
|
|
26
|
-
o[k2] = m[k];
|
|
27
|
-
}));
|
|
28
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
-
}) : function(o, v) {
|
|
31
|
-
o["default"] = v;
|
|
32
|
-
});
|
|
33
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
-
var ownKeys = function(o) {
|
|
35
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
-
var ar = [];
|
|
37
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
-
return ar;
|
|
39
|
-
};
|
|
40
|
-
return ownKeys(o);
|
|
41
|
-
};
|
|
42
|
-
return function (mod) {
|
|
43
|
-
if (mod && mod.__esModule) return mod;
|
|
44
|
-
var result = {};
|
|
45
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
-
__setModuleDefault(result, mod);
|
|
47
|
-
return result;
|
|
48
|
-
};
|
|
49
|
-
})();
|
|
50
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
18
|
exports.collectSessionPromptHistory = collectSessionPromptHistory;
|
|
52
|
-
const
|
|
19
|
+
const compressedRollouts_1 = require("./providers/compressedRollouts");
|
|
53
20
|
const promptHistory_1 = require("./promptHistory");
|
|
54
21
|
const sessionPromptSignals_1 = require("./sessionPromptSignals");
|
|
55
22
|
const DEFAULT_SESSION_BOUNDS = {
|
|
@@ -224,7 +191,9 @@ function definedBounds(bounds) {
|
|
|
224
191
|
async function selectCandidates(options, listingRoots) {
|
|
225
192
|
const sinceMs = options.since ? options.since.getTime() : null;
|
|
226
193
|
const providers = options.providers ?? ['claude-code', 'codex'];
|
|
227
|
-
let candidates = await (0, promptHistory_1.listCandidates)(providers, listingRoots, sinceMs
|
|
194
|
+
let candidates = await (0, promptHistory_1.listCandidates)(providers, listingRoots, sinceMs, {
|
|
195
|
+
includeCompressedRollouts: options.includeCompressedRollouts,
|
|
196
|
+
});
|
|
228
197
|
if (options.sessionIds || options.sessionRefs) {
|
|
229
198
|
const ids = new Set(options.sessionIds ?? []);
|
|
230
199
|
const keys = new Set();
|
|
@@ -242,7 +211,7 @@ async function selectCandidates(options, listingRoots) {
|
|
|
242
211
|
const selected = [];
|
|
243
212
|
for (const candidate of candidates) {
|
|
244
213
|
try {
|
|
245
|
-
selected.push({ candidate, stat: await
|
|
214
|
+
selected.push({ candidate, stat: await (0, compressedRollouts_1.statRolloutContent)(candidate.filePath) });
|
|
246
215
|
}
|
|
247
216
|
catch {
|
|
248
217
|
// Gone since it was listed.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagent lifecycle records as `system` session events.
|
|
3
|
+
*
|
|
4
|
+
* Codex records its multi-agent lifecycle in the parent's rollout:
|
|
5
|
+
* `item_completed` → `SubAgentActivity` items link a `spawn_agent` call to the
|
|
6
|
+
* child thread it started (`started`), mark each finished child turn
|
|
7
|
+
* (`completed`, Codex 0.150+), and note `followup_task` / `send_message`
|
|
8
|
+
* calls (`interacted`) and `interrupt_agent` calls (`interrupted`); a child's
|
|
9
|
+
* report arrives as an `agent_message` whose text starts
|
|
10
|
+
* `Message Type: FINAL_ANSWER`. With
|
|
11
|
+
* `CodexRolloutParserOptions.includeSubagentActivity`, the parser turns each
|
|
12
|
+
* into one `system` event with `origin: { kind: 'subagent-activity' }` whose
|
|
13
|
+
* `message.content` is a single `{ type: 'subagent_activity', ... }` block.
|
|
14
|
+
*
|
|
15
|
+
* Those events are bookkeeping, not messages: transcripts, context
|
|
16
|
+
* attribution, and message counts skip them, as they do task notifications.
|
|
17
|
+
*
|
|
18
|
+
* Pure: no filesystem access. Browser-safe.
|
|
19
|
+
*
|
|
20
|
+
* @module subagentActivity
|
|
21
|
+
*/
|
|
22
|
+
import type { SessionEvent } from './types/sessionEvent';
|
|
23
|
+
/** `origin.kind` of a subagent-activity `system` event. */
|
|
24
|
+
export declare const SUBAGENT_ACTIVITY_ORIGIN_KIND = "subagent-activity";
|
|
25
|
+
/** `type` of the content block that carries the activity. */
|
|
26
|
+
export declare const SUBAGENT_ACTIVITY_BLOCK_TYPE = "subagent_activity";
|
|
27
|
+
/**
|
|
28
|
+
* - `started`: a spawn call started the child thread (`callId` = the spawn
|
|
29
|
+
* call's id, `agentThreadId` = the child's rollout id).
|
|
30
|
+
* - `completed`: one child turn finished (`turnId` = that child turn).
|
|
31
|
+
* - `interacted`: the parent sent the child work or a message (`callId` =
|
|
32
|
+
* the `followup_task` or `send_message` call; `tool` says which, when the
|
|
33
|
+
* call was seen). After `followup_task` the child runs again.
|
|
34
|
+
* - `interrupted`: the parent interrupted the child (`interrupt_agent`).
|
|
35
|
+
* - `final-answer`: the child's final report reached the parent
|
|
36
|
+
* (`agentPath` = its author, `text` = the report).
|
|
37
|
+
*/
|
|
38
|
+
export type SubagentActivityKind = 'started' | 'completed' | 'interacted' | 'interrupted' | 'final-answer';
|
|
39
|
+
export interface SubagentActivity {
|
|
40
|
+
kind: SubagentActivityKind;
|
|
41
|
+
/**
|
|
42
|
+
* The parent's tool call the record refers to: the spawn call for
|
|
43
|
+
* `started`, the `followup_task` / `send_message` call for `interacted`,
|
|
44
|
+
* the `interrupt_agent` call for `interrupted`.
|
|
45
|
+
*/
|
|
46
|
+
callId?: string;
|
|
47
|
+
/**
|
|
48
|
+
* Raw name of the `callId` tool call (`spawn_agent`, `followup_task`,
|
|
49
|
+
* `send_message`, `interrupt_agent`) when the parser saw that call.
|
|
50
|
+
*/
|
|
51
|
+
tool?: string;
|
|
52
|
+
/** `completed`: the child turn that finished. */
|
|
53
|
+
turnId?: string;
|
|
54
|
+
/** The child's thread id, which is its rollout's session id. */
|
|
55
|
+
agentThreadId?: string;
|
|
56
|
+
/** The child's agent path, e.g. `/root/review_builder` (`final-answer`: the author). */
|
|
57
|
+
agentPath?: string;
|
|
58
|
+
/** `final-answer`: the agent path the report went to, e.g. `/root`. */
|
|
59
|
+
recipient?: string;
|
|
60
|
+
/** `started`: the child's model and reasoning effort, when recorded. */
|
|
61
|
+
model?: string;
|
|
62
|
+
reasoningEffort?: string;
|
|
63
|
+
/** The thread and turn that recorded the activity (the parent's). */
|
|
64
|
+
parentThreadId?: string;
|
|
65
|
+
parentTurnId?: string;
|
|
66
|
+
/** `final-answer`: the report text (empty in metadata-only parsing). */
|
|
67
|
+
text?: string;
|
|
68
|
+
}
|
|
69
|
+
/** Whether an event is a subagent-activity `system` event (see the module docs). */
|
|
70
|
+
export declare function isSubagentActivitySystemEvent(event: SessionEvent): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The activity a subagent-activity `system` event carries, copied with only
|
|
73
|
+
* its known string fields; `null` for any other event or a malformed block.
|
|
74
|
+
*/
|
|
75
|
+
export declare function subagentActivityFromEvent(event: SessionEvent): SubagentActivity | null;
|
|
76
|
+
/** A one-line, content-free description, e.g. `Subagent /root/review started`. */
|
|
77
|
+
export declare function describeSubagentActivity(activity: SubagentActivity): string;
|
|
78
|
+
/** Fields of a Codex inter-agent message text (`Message Type: … Payload:\n…`). */
|
|
79
|
+
export interface CodexAgentMessageText {
|
|
80
|
+
/** `MESSAGE`, `NEW_TASK`, `FINAL_ANSWER`, … */
|
|
81
|
+
messageType: string;
|
|
82
|
+
taskName?: string;
|
|
83
|
+
sender?: string;
|
|
84
|
+
/** Everything after the `Payload:` line. */
|
|
85
|
+
payload: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Parses a Codex inter-agent message text. Returns `null` unless it starts
|
|
89
|
+
* with a `Message Type:` line.
|
|
90
|
+
*/
|
|
91
|
+
export declare function parseCodexAgentMessageText(text: unknown): CodexAgentMessageText | null;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Subagent lifecycle records as `system` session events.
|
|
4
|
+
*
|
|
5
|
+
* Codex records its multi-agent lifecycle in the parent's rollout:
|
|
6
|
+
* `item_completed` → `SubAgentActivity` items link a `spawn_agent` call to the
|
|
7
|
+
* child thread it started (`started`), mark each finished child turn
|
|
8
|
+
* (`completed`, Codex 0.150+), and note `followup_task` / `send_message`
|
|
9
|
+
* calls (`interacted`) and `interrupt_agent` calls (`interrupted`); a child's
|
|
10
|
+
* report arrives as an `agent_message` whose text starts
|
|
11
|
+
* `Message Type: FINAL_ANSWER`. With
|
|
12
|
+
* `CodexRolloutParserOptions.includeSubagentActivity`, the parser turns each
|
|
13
|
+
* into one `system` event with `origin: { kind: 'subagent-activity' }` whose
|
|
14
|
+
* `message.content` is a single `{ type: 'subagent_activity', ... }` block.
|
|
15
|
+
*
|
|
16
|
+
* Those events are bookkeeping, not messages: transcripts, context
|
|
17
|
+
* attribution, and message counts skip them, as they do task notifications.
|
|
18
|
+
*
|
|
19
|
+
* Pure: no filesystem access. Browser-safe.
|
|
20
|
+
*
|
|
21
|
+
* @module subagentActivity
|
|
22
|
+
*/
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.SUBAGENT_ACTIVITY_BLOCK_TYPE = exports.SUBAGENT_ACTIVITY_ORIGIN_KIND = void 0;
|
|
25
|
+
exports.isSubagentActivitySystemEvent = isSubagentActivitySystemEvent;
|
|
26
|
+
exports.subagentActivityFromEvent = subagentActivityFromEvent;
|
|
27
|
+
exports.describeSubagentActivity = describeSubagentActivity;
|
|
28
|
+
exports.parseCodexAgentMessageText = parseCodexAgentMessageText;
|
|
29
|
+
/** `origin.kind` of a subagent-activity `system` event. */
|
|
30
|
+
exports.SUBAGENT_ACTIVITY_ORIGIN_KIND = 'subagent-activity';
|
|
31
|
+
/** `type` of the content block that carries the activity. */
|
|
32
|
+
exports.SUBAGENT_ACTIVITY_BLOCK_TYPE = 'subagent_activity';
|
|
33
|
+
const KINDS = new Set([
|
|
34
|
+
'started',
|
|
35
|
+
'completed',
|
|
36
|
+
'interacted',
|
|
37
|
+
'interrupted',
|
|
38
|
+
'final-answer',
|
|
39
|
+
]);
|
|
40
|
+
const STRING_FIELDS = [
|
|
41
|
+
'callId',
|
|
42
|
+
'tool',
|
|
43
|
+
'turnId',
|
|
44
|
+
'agentThreadId',
|
|
45
|
+
'agentPath',
|
|
46
|
+
'recipient',
|
|
47
|
+
'model',
|
|
48
|
+
'reasoningEffort',
|
|
49
|
+
'parentThreadId',
|
|
50
|
+
'parentTurnId',
|
|
51
|
+
'text',
|
|
52
|
+
];
|
|
53
|
+
/** Whether an event is a subagent-activity `system` event (see the module docs). */
|
|
54
|
+
function isSubagentActivitySystemEvent(event) {
|
|
55
|
+
return event.type === 'system' && event.origin?.kind === exports.SUBAGENT_ACTIVITY_ORIGIN_KIND;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The activity a subagent-activity `system` event carries, copied with only
|
|
59
|
+
* its known string fields; `null` for any other event or a malformed block.
|
|
60
|
+
*/
|
|
61
|
+
function subagentActivityFromEvent(event) {
|
|
62
|
+
if (!isSubagentActivitySystemEvent(event))
|
|
63
|
+
return null;
|
|
64
|
+
const content = event.message?.content;
|
|
65
|
+
if (!Array.isArray(content))
|
|
66
|
+
return null;
|
|
67
|
+
for (const block of content) {
|
|
68
|
+
if (!block || typeof block !== 'object')
|
|
69
|
+
continue;
|
|
70
|
+
const raw = block;
|
|
71
|
+
if (raw.type !== exports.SUBAGENT_ACTIVITY_BLOCK_TYPE)
|
|
72
|
+
continue;
|
|
73
|
+
if (typeof raw.kind !== 'string' || !KINDS.has(raw.kind))
|
|
74
|
+
return null;
|
|
75
|
+
const activity = { kind: raw.kind };
|
|
76
|
+
for (const field of STRING_FIELDS) {
|
|
77
|
+
const value = raw[field];
|
|
78
|
+
if (typeof value === 'string' && value.length > 0)
|
|
79
|
+
activity[field] = value;
|
|
80
|
+
}
|
|
81
|
+
return activity;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/** A one-line, content-free description, e.g. `Subagent /root/review started`. */
|
|
86
|
+
function describeSubagentActivity(activity) {
|
|
87
|
+
const who = activity.agentPath ?? activity.agentThreadId ?? 'subagent';
|
|
88
|
+
const name = `Subagent ${who}`;
|
|
89
|
+
switch (activity.kind) {
|
|
90
|
+
case 'started':
|
|
91
|
+
return `${name} started`;
|
|
92
|
+
case 'completed':
|
|
93
|
+
return `${name} finished a turn`;
|
|
94
|
+
case 'interacted':
|
|
95
|
+
return activity.tool === 'send_message'
|
|
96
|
+
? `Message sent to subagent ${who}`
|
|
97
|
+
: `${name} given a follow-up task`;
|
|
98
|
+
case 'interrupted':
|
|
99
|
+
return `${name} interrupted`;
|
|
100
|
+
case 'final-answer':
|
|
101
|
+
return `${name} reported its final answer`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const MESSAGE_HEADER = /^Message Type:[ \t]*([A-Z_]+)[ \t]*(?:\r?\n|$)/;
|
|
105
|
+
/**
|
|
106
|
+
* Parses a Codex inter-agent message text. Returns `null` unless it starts
|
|
107
|
+
* with a `Message Type:` line.
|
|
108
|
+
*/
|
|
109
|
+
function parseCodexAgentMessageText(text) {
|
|
110
|
+
if (typeof text !== 'string')
|
|
111
|
+
return null;
|
|
112
|
+
const header = MESSAGE_HEADER.exec(text);
|
|
113
|
+
if (!header)
|
|
114
|
+
return null;
|
|
115
|
+
const rest = text.slice(header[0].length);
|
|
116
|
+
const payloadAt = /(?:^|\n)Payload:[ \t]*(?:\r?\n|$)/.exec(rest);
|
|
117
|
+
const head = payloadAt ? rest.slice(0, payloadAt.index) : rest;
|
|
118
|
+
const payload = payloadAt ? rest.slice(payloadAt.index + payloadAt[0].length) : '';
|
|
119
|
+
const field = (name) => {
|
|
120
|
+
const match = new RegExp(`(?:^|\\n)${name}:[ \\t]*([^\\n]*)`).exec(head);
|
|
121
|
+
const value = match?.[1]?.trim();
|
|
122
|
+
return value ? value : undefined;
|
|
123
|
+
};
|
|
124
|
+
const taskName = field('Task name');
|
|
125
|
+
const sender = field('Sender');
|
|
126
|
+
return {
|
|
127
|
+
messageType: header[1],
|
|
128
|
+
...(taskName ? { taskName } : {}),
|
|
129
|
+
...(sender ? { sender } : {}),
|
|
130
|
+
payload,
|
|
131
|
+
};
|
|
132
|
+
}
|