deepline 0.3.290 → 0.3.291
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/bundling-sources/sdk/src/client.ts +8 -6
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/runs/overview.ts +16 -6
- package/dist/bundling-sources/sdk/src/types.ts +21 -2
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +11 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +209 -51
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +10 -2
- package/dist/bundling-sources/shared_libs/play-runtime/log-context.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/log-provenance.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +5 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +54 -41
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +50 -3
- package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +9 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +35 -7
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +55 -9
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +16 -4
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +140 -4
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +559 -313
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +116 -24
- package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +22 -5
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +35 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +68 -8
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +2 -0
- package/dist/cli/index.js +193 -582
- package/dist/cli/index.mjs +193 -582
- package/dist/{client-FR_u0dxT.d.ts → client-Ct4jmvAg.d.ts} +29 -8
- package/dist/{client-phK1Ixcl.d.mts → client-Ct9GKrwu.d.mts} +29 -8
- package/dist/{compiler-manifest-9SQtUuKb.d.mts → compiler-manifest-qtTNYvBl.d.mts} +2 -0
- package/dist/{compiler-manifest-9SQtUuKb.d.ts → compiler-manifest-qtTNYvBl.d.ts} +2 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +12 -5
- package/dist/index.mjs +12 -5
- package/dist/install-integrity.json +4 -4
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -5,6 +5,42 @@
|
|
|
5
5
|
export type PlayLogContextValue = string | number | boolean;
|
|
6
6
|
export type PlayLogContext = Readonly<Record<string, PlayLogContextValue>>;
|
|
7
7
|
|
|
8
|
+
/** Producer-owned facts for one line, separate from authored context. */
|
|
9
|
+
export type PlayLogMetadata = {
|
|
10
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
11
|
+
occurredAt: number;
|
|
12
|
+
stepId?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function normalizePlayLogMetadata(
|
|
16
|
+
value: unknown,
|
|
17
|
+
): PlayLogMetadata | null {
|
|
18
|
+
if (value === undefined || value === null) return null;
|
|
19
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
20
|
+
throw new TypeError('Run log metadata must be an object.');
|
|
21
|
+
}
|
|
22
|
+
const entry = value as Record<string, unknown>;
|
|
23
|
+
if (
|
|
24
|
+
!['debug', 'info', 'warn', 'error'].includes(String(entry.level)) ||
|
|
25
|
+
typeof entry.occurredAt !== 'number' ||
|
|
26
|
+
!Number.isSafeInteger(entry.occurredAt) ||
|
|
27
|
+
entry.occurredAt <= 0 ||
|
|
28
|
+
(entry.stepId !== undefined &&
|
|
29
|
+
(typeof entry.stepId !== 'string' ||
|
|
30
|
+
!entry.stepId.trim() ||
|
|
31
|
+
entry.stepId.length > 256))
|
|
32
|
+
) {
|
|
33
|
+
throw new TypeError(
|
|
34
|
+
'Run log metadata requires a severity, timestamp and optional step ID.',
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
level: entry.level as PlayLogMetadata['level'],
|
|
39
|
+
occurredAt: entry.occurredAt,
|
|
40
|
+
...(typeof entry.stepId === 'string' ? { stepId: entry.stepId } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
8
44
|
export const PLAY_LOG_CONTEXT_LIMITS = {
|
|
9
45
|
fields: 8,
|
|
10
46
|
keyBytes: 64,
|
|
@@ -341,7 +341,8 @@ export function classifyLegacyLogLine(line: string): LogProvenance {
|
|
|
341
341
|
|
|
342
342
|
// Scheduler / sandbox / worker internals.
|
|
343
343
|
if (
|
|
344
|
-
/^\[perf\]
|
|
344
|
+
/^\[perf\]/i.test(message) ||
|
|
345
|
+
/^\[runtime\.(?:phase_summary|logs|log_transport)\]/i.test(message) ||
|
|
345
346
|
/\[worker\] picked up run\b/.test(message) ||
|
|
346
347
|
/\[worker\] heartbeat\b/.test(message) ||
|
|
347
348
|
/\[worker\] progress completedRows=\d+ totalRows=\d+ rowUpdates=\d+/.test(
|
|
@@ -14,7 +14,7 @@ import type {
|
|
|
14
14
|
import type { PlayExecutionSuspension } from './suspension';
|
|
15
15
|
import type { PlayStaticPipeline } from '../plays/static-pipeline';
|
|
16
16
|
import type { PlayLiveEventSource } from './live-events';
|
|
17
|
-
import type { PlayLogContext } from './log-context';
|
|
17
|
+
import type { PlayLogContext, PlayLogMetadata } from './log-context';
|
|
18
18
|
import type { PreloadedRuntimeDbSession } from './db-session';
|
|
19
19
|
import type { PacingRule } from './governor/rate-state-backend';
|
|
20
20
|
import type { GovernanceSnapshot } from './governor/governor';
|
|
@@ -326,6 +326,7 @@ export type PlayRunnerLogEvent = {
|
|
|
326
326
|
entryId?: string;
|
|
327
327
|
/** Search-only context; omitted before the compatible Convex projection. */
|
|
328
328
|
context?: PlayLogContext;
|
|
329
|
+
metadata?: PlayLogMetadata;
|
|
329
330
|
};
|
|
330
331
|
|
|
331
332
|
export type PlayRunnerEvent =
|
|
@@ -418,6 +419,7 @@ export type PlayRunnerResult =
|
|
|
418
419
|
logIds?: string[];
|
|
419
420
|
/** Search-only context aligned to logs; omitted when every entry is null. */
|
|
420
421
|
logContexts?: Array<PlayLogContext | null>;
|
|
422
|
+
logMetadata?: Array<PlayLogMetadata | null>;
|
|
421
423
|
stats: Record<string, unknown>;
|
|
422
424
|
steps: PlayStep[];
|
|
423
425
|
checkpoint: PlayCheckpoint;
|
|
@@ -434,6 +436,7 @@ export type PlayRunnerResult =
|
|
|
434
436
|
logIds?: string[];
|
|
435
437
|
/** Search-only context aligned to logs; omitted when every entry is null. */
|
|
436
438
|
logContexts?: Array<PlayLogContext | null>;
|
|
439
|
+
logMetadata?: Array<PlayLogMetadata | null>;
|
|
437
440
|
stats: Record<string, unknown>;
|
|
438
441
|
steps: PlayStep[];
|
|
439
442
|
checkpoint: PlayCheckpoint;
|
|
@@ -451,6 +454,7 @@ export type PlayRunnerResult =
|
|
|
451
454
|
logIds?: string[];
|
|
452
455
|
/** Search-only context aligned to logs; omitted when every entry is null. */
|
|
453
456
|
logContexts?: Array<PlayLogContext | null>;
|
|
457
|
+
logMetadata?: Array<PlayLogMetadata | null>;
|
|
454
458
|
stats: Record<string, unknown>;
|
|
455
459
|
steps: PlayStep[];
|
|
456
460
|
checkpoint?: PlayCheckpoint | null;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { normalizeRunLogIds } from './run-log-buffer';
|
|
2
2
|
import { RUN_EVENT_KIND } from './run-event-catalog';
|
|
3
3
|
import type { PlayRunLedgerIngressEvent } from './run-ledger';
|
|
4
|
-
import type { PlayLogContext } from './log-context';
|
|
5
4
|
import type { RunLedgerProjectionChunk } from './run-ledger-projection-contract';
|
|
6
5
|
|
|
7
6
|
const APP_RUNTIME_LOG_EVENT_MAX_JSON_BYTES = 128 * 1024;
|
|
@@ -30,25 +29,27 @@ function splitRunEventForAppRuntime(
|
|
|
30
29
|
: [];
|
|
31
30
|
if (eventType !== RUN_EVENT_KIND.logAppended || lines.length === 0)
|
|
32
31
|
return [event];
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
? payload?.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
32
|
+
const alignedFields = ['lineContexts', 'lineMetadata'] as const;
|
|
33
|
+
const aligned = alignedFields.map((key) => {
|
|
34
|
+
const label = key === 'lineContexts' ? 'contexts' : 'metadata';
|
|
35
|
+
const inPayload = payload !== null && Object.hasOwn(payload, key);
|
|
36
|
+
const inEvent = Object.hasOwn(event, key);
|
|
37
|
+
if (inPayload && inEvent)
|
|
38
|
+
throw new TypeError(`Run log ${label} must have one event owner.`);
|
|
39
|
+
const value = inPayload ? payload?.[key] : event[key];
|
|
40
|
+
if (
|
|
41
|
+
(inPayload || inEvent) &&
|
|
42
|
+
(!Array.isArray(value) || value.length !== lines.length)
|
|
43
|
+
) {
|
|
44
|
+
throw new TypeError(`Run log ${label} must align with their lines.`);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
key,
|
|
48
|
+
inPayload,
|
|
49
|
+
inEvent,
|
|
50
|
+
value: Array.isArray(value) ? value : undefined,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
52
53
|
const payloadOwnsLineIds =
|
|
53
54
|
payload !== null && Object.hasOwn(payload, 'lineIds');
|
|
54
55
|
if (payloadOwnsLineIds && Object.hasOwn(event, 'lineIds'))
|
|
@@ -67,6 +68,7 @@ function splitRunEventForAppRuntime(
|
|
|
67
68
|
const {
|
|
68
69
|
lines: _outerLines,
|
|
69
70
|
lineContexts: _outerLineContexts,
|
|
71
|
+
lineMetadata: _outerLineMetadata,
|
|
70
72
|
lineIds: _outerLineIds,
|
|
71
73
|
...eventWithoutOuterLines
|
|
72
74
|
} = event;
|
|
@@ -75,18 +77,20 @@ function splitRunEventForAppRuntime(
|
|
|
75
77
|
const start = index;
|
|
76
78
|
let bytes = 2;
|
|
77
79
|
while (index < lines.length) {
|
|
78
|
-
const lineBytes =
|
|
79
|
-
JSON.stringify(lines[index]!)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
const lineBytes =
|
|
81
|
+
appRuntimeTextEncoder.encode(JSON.stringify(lines[index]!)).length +
|
|
82
|
+
aligned.reduce(
|
|
83
|
+
(total, field) =>
|
|
84
|
+
total +
|
|
85
|
+
(field.value
|
|
86
|
+
? appRuntimeTextEncoder.encode(JSON.stringify(field.value[index]))
|
|
87
|
+
.length + 1
|
|
88
|
+
: 0),
|
|
89
|
+
0,
|
|
90
|
+
);
|
|
91
|
+
const metadataBytes = lineIds
|
|
92
|
+
? appRuntimeTextEncoder.encode(JSON.stringify(lineIds[index])).length + 1
|
|
93
|
+
: 0;
|
|
90
94
|
if (
|
|
91
95
|
index > start &&
|
|
92
96
|
bytes + lineBytes + metadataBytes + 1 >
|
|
@@ -98,15 +102,22 @@ function splitRunEventForAppRuntime(
|
|
|
98
102
|
index += 1;
|
|
99
103
|
}
|
|
100
104
|
const batchLines = lines.slice(start, index);
|
|
101
|
-
const batchLineContexts = lineContexts?.slice(start, index);
|
|
102
105
|
const batchLineIds = lineIds?.slice(start, index);
|
|
106
|
+
const eventFields = Object.fromEntries(
|
|
107
|
+
aligned
|
|
108
|
+
.filter((field) => field.inEvent)
|
|
109
|
+
.map((field) => [field.key, field.value!.slice(start, index)]),
|
|
110
|
+
);
|
|
111
|
+
const payloadFields = Object.fromEntries(
|
|
112
|
+
aligned
|
|
113
|
+
.filter((field) => field.inPayload)
|
|
114
|
+
.map((field) => [field.key, field.value!.slice(start, index)]),
|
|
115
|
+
);
|
|
103
116
|
split.push(
|
|
104
117
|
payload
|
|
105
118
|
? {
|
|
106
119
|
...eventWithoutOuterLines,
|
|
107
|
-
...
|
|
108
|
-
? { lineContexts: batchLineContexts }
|
|
109
|
-
: {}),
|
|
120
|
+
...eventFields,
|
|
110
121
|
...(payloadOwnsLines ? {} : { lines: batchLines }),
|
|
111
122
|
...(!payloadOwnsLineIds && batchLineIds
|
|
112
123
|
? { lineIds: batchLineIds }
|
|
@@ -114,16 +125,18 @@ function splitRunEventForAppRuntime(
|
|
|
114
125
|
payload: {
|
|
115
126
|
...Object.fromEntries(
|
|
116
127
|
Object.entries(payload).filter(
|
|
117
|
-
([key]) =>
|
|
128
|
+
([key]) =>
|
|
129
|
+
key !== 'lineIds' &&
|
|
130
|
+
!alignedFields.includes(
|
|
131
|
+
key as (typeof alignedFields)[number],
|
|
132
|
+
),
|
|
118
133
|
),
|
|
119
134
|
),
|
|
120
135
|
...(payloadOwnsLines ? { lines: batchLines } : {}),
|
|
136
|
+
...payloadFields,
|
|
121
137
|
...(payloadOwnsLineIds && batchLineIds
|
|
122
138
|
? { lineIds: batchLineIds }
|
|
123
139
|
: {}),
|
|
124
|
-
...(payloadOwnsLineContexts && batchLineContexts
|
|
125
|
-
? { lineContexts: batchLineContexts }
|
|
126
|
-
: {}),
|
|
127
140
|
...(payloadChannelOffset === undefined
|
|
128
141
|
? {}
|
|
129
142
|
: { channelOffset: payloadChannelOffset + start }),
|
|
@@ -135,7 +148,7 @@ function splitRunEventForAppRuntime(
|
|
|
135
148
|
: {
|
|
136
149
|
...eventWithoutOuterLines,
|
|
137
150
|
lines: batchLines,
|
|
138
|
-
...
|
|
151
|
+
...eventFields,
|
|
139
152
|
...(batchLineIds ? { lineIds: batchLineIds } : {}),
|
|
140
153
|
...(eventChannelOffset === undefined
|
|
141
154
|
? {}
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
type PlayConditionCounts,
|
|
25
25
|
} from './cell-provenance';
|
|
26
26
|
import { isLedgerTerminalResultRef } from './output-size-limits';
|
|
27
|
-
import type { PlayLogContext } from './log-context';
|
|
27
|
+
import type { PlayLogContext, PlayLogMetadata } from './log-context';
|
|
28
28
|
import { RUN_EVENT_KIND, type RunEventSource } from './run-event-catalog';
|
|
29
29
|
|
|
30
30
|
export type PlayRunLedgerStatus =
|
|
@@ -100,6 +100,8 @@ export type PlayRunLedgerStepProgress = {
|
|
|
100
100
|
completedAt?: number | null;
|
|
101
101
|
updatedAt?: number | null;
|
|
102
102
|
nodeIo?: PlayDocflowNodeIoState;
|
|
103
|
+
/** Error reported by this step, distinct from a run stopping other work. */
|
|
104
|
+
error?: string;
|
|
103
105
|
conditionCounts?: PlayConditionCounts;
|
|
104
106
|
};
|
|
105
107
|
|
|
@@ -320,6 +322,7 @@ export type PlayRunLedgerEvent =
|
|
|
320
322
|
lines: string[];
|
|
321
323
|
/** Search-only context aligned to `lines`; stripped before Convex. */
|
|
322
324
|
lineContexts?: Array<PlayLogContext | null>;
|
|
325
|
+
lineMetadata?: Array<PlayLogMetadata | null>;
|
|
323
326
|
lineIds?: Array<string | null>;
|
|
324
327
|
/**
|
|
325
328
|
* Absolute per-run sequence (1-based) of `lines[0]`. Assigned by Run
|
|
@@ -431,6 +434,7 @@ export type PlayRunLedgerStatusPatch = {
|
|
|
431
434
|
liveLogs?: readonly string[] | null;
|
|
432
435
|
/** Search-only context aligned to `liveLogs`; stripped before Convex. */
|
|
433
436
|
liveLogContexts?: readonly (PlayLogContext | null)[] | null;
|
|
437
|
+
liveLogMetadata?: readonly (PlayLogMetadata | null)[] | null;
|
|
434
438
|
liveLogIds?: readonly (string | null)[] | null;
|
|
435
439
|
/**
|
|
436
440
|
* Positional cursor for `liveLogs[0]` on this producer's log channel (the
|
|
@@ -1383,6 +1387,9 @@ function normalizeStepProgress(
|
|
|
1383
1387
|
...(optionalFiniteNumber(value.supersededRows) !== undefined
|
|
1384
1388
|
? { supersededRows: optionalFiniteNumber(value.supersededRows) }
|
|
1385
1389
|
: {}),
|
|
1390
|
+
...(optionalString(value.error)
|
|
1391
|
+
? { error: optionalString(value.error) }
|
|
1392
|
+
: {}),
|
|
1386
1393
|
...(optionalString(value.message)
|
|
1387
1394
|
? { message: optionalString(value.message) }
|
|
1388
1395
|
: {}),
|
|
@@ -2329,6 +2336,7 @@ function progressSignature(
|
|
|
2329
2336
|
completedRows: progress?.completedRows ?? null,
|
|
2330
2337
|
supersededRows: progress?.supersededRows ?? null,
|
|
2331
2338
|
message: progress?.message ?? null,
|
|
2339
|
+
error: progress?.error ?? null,
|
|
2332
2340
|
artifactTableNamespace: progress?.artifactTableNamespace ?? null,
|
|
2333
2341
|
startedAt: progress?.startedAt ?? null,
|
|
2334
2342
|
completedAt: progress?.completedAt ?? null,
|
|
@@ -2371,6 +2379,7 @@ function terminalEventTypeForStatus(
|
|
|
2371
2379
|
export function slicePositionalLogLines(input: {
|
|
2372
2380
|
bufferLines: readonly string[];
|
|
2373
2381
|
bufferContexts?: readonly (PlayLogContext | null)[];
|
|
2382
|
+
bufferMetadata?: readonly (PlayLogMetadata | null)[];
|
|
2374
2383
|
bufferIds?: readonly (string | null)[];
|
|
2375
2384
|
bufferTotalCount: number;
|
|
2376
2385
|
sentCount: number;
|
|
@@ -2378,6 +2387,7 @@ export function slicePositionalLogLines(input: {
|
|
|
2378
2387
|
lines: string[];
|
|
2379
2388
|
channelOffset: number;
|
|
2380
2389
|
lineContexts?: Array<PlayLogContext | null>;
|
|
2390
|
+
lineMetadata?: Array<PlayLogMetadata | null>;
|
|
2381
2391
|
lineIds?: Array<string | null>;
|
|
2382
2392
|
} | null {
|
|
2383
2393
|
if (
|
|
@@ -2386,6 +2396,11 @@ export function slicePositionalLogLines(input: {
|
|
|
2386
2396
|
) {
|
|
2387
2397
|
throw new TypeError('Run log contexts must align with the retained lines.');
|
|
2388
2398
|
}
|
|
2399
|
+
if (
|
|
2400
|
+
input.bufferMetadata !== undefined &&
|
|
2401
|
+
input.bufferMetadata.length !== input.bufferLines.length
|
|
2402
|
+
)
|
|
2403
|
+
throw new TypeError('Run log metadata must align with lines.');
|
|
2389
2404
|
if (input.bufferIds && input.bufferIds.length !== input.bufferLines.length) {
|
|
2390
2405
|
throw new TypeError('Run log identities must align with retained lines.');
|
|
2391
2406
|
}
|
|
@@ -2402,11 +2417,13 @@ export function slicePositionalLogLines(input: {
|
|
|
2402
2417
|
}
|
|
2403
2418
|
const start = sendFromOffset - bufferFirstOffset;
|
|
2404
2419
|
const lineContexts = input.bufferContexts?.slice(start);
|
|
2420
|
+
const lineMetadata = input.bufferMetadata?.slice(start);
|
|
2405
2421
|
return {
|
|
2406
2422
|
lines: [...lines],
|
|
2407
2423
|
channelOffset: sendFromOffset,
|
|
2408
2424
|
...(input.bufferIds ? { lineIds: input.bufferIds.slice(start) } : {}),
|
|
2409
2425
|
...(lineContexts?.some(Boolean) ? { lineContexts: [...lineContexts] } : {}),
|
|
2426
|
+
...(lineMetadata?.some(Boolean) ? { lineMetadata: [...lineMetadata] } : {}),
|
|
2410
2427
|
};
|
|
2411
2428
|
}
|
|
2412
2429
|
|
|
@@ -2435,6 +2452,7 @@ export function buildPlayRunLedgerEventsFromLogLines(input: {
|
|
|
2435
2452
|
runId: string;
|
|
2436
2453
|
lines: readonly string[];
|
|
2437
2454
|
lineContexts?: readonly (PlayLogContext | null)[];
|
|
2455
|
+
lineMetadata?: readonly (PlayLogMetadata | null)[];
|
|
2438
2456
|
lineIds?: readonly (string | null)[];
|
|
2439
2457
|
source?: PlayRunLedgerEventSource;
|
|
2440
2458
|
occurredAt?: number;
|
|
@@ -2457,6 +2475,11 @@ export function buildPlayRunLedgerEventsFromLogLines(input: {
|
|
|
2457
2475
|
) {
|
|
2458
2476
|
throw new TypeError('Run log contexts must align with their lines.');
|
|
2459
2477
|
}
|
|
2478
|
+
if (
|
|
2479
|
+
input.lineMetadata !== undefined &&
|
|
2480
|
+
input.lineMetadata.length !== input.lines.length
|
|
2481
|
+
)
|
|
2482
|
+
throw new TypeError('Run log metadata must align with lines.');
|
|
2460
2483
|
if (input.lineIds && input.lineIds.length !== input.lines.length) {
|
|
2461
2484
|
throw new TypeError('Run log identities must align with their lines.');
|
|
2462
2485
|
}
|
|
@@ -2464,6 +2487,7 @@ export function buildPlayRunLedgerEventsFromLogLines(input: {
|
|
|
2464
2487
|
.map((line, index) => ({
|
|
2465
2488
|
line: positional ? line.trim() || '(blank log line)' : line.trim(),
|
|
2466
2489
|
context: input.lineContexts?.[index] ?? null,
|
|
2490
|
+
metadata: input.lineMetadata?.[index] ?? null,
|
|
2467
2491
|
entryId: input.lineIds?.[index] ?? null,
|
|
2468
2492
|
}))
|
|
2469
2493
|
.filter((entry) => positional || entry.line.length > 0);
|
|
@@ -2499,6 +2523,15 @@ export function buildPlayRunLedgerEventsFromLogLines(input: {
|
|
|
2499
2523
|
.map((entry) => entry.context),
|
|
2500
2524
|
}
|
|
2501
2525
|
: {}),
|
|
2526
|
+
...(entries
|
|
2527
|
+
.slice(index, index + MAX_LEDGER_LOG_LINES_PER_EVENT)
|
|
2528
|
+
.some((entry) => entry.metadata)
|
|
2529
|
+
? {
|
|
2530
|
+
lineMetadata: entries
|
|
2531
|
+
.slice(index, index + MAX_LEDGER_LOG_LINES_PER_EVENT)
|
|
2532
|
+
.map((entry) => entry.metadata),
|
|
2533
|
+
}
|
|
2534
|
+
: {}),
|
|
2502
2535
|
...(positional ? { channelOffset: input.channelOffset! + index } : {}),
|
|
2503
2536
|
...(positional &&
|
|
2504
2537
|
typeof input.producerAttempt === 'number' &&
|
|
@@ -2527,6 +2560,7 @@ export function buildTerminalLogReplayEvents(input: {
|
|
|
2527
2560
|
runId: string;
|
|
2528
2561
|
lines: readonly string[];
|
|
2529
2562
|
lineContexts?: readonly (PlayLogContext | null)[];
|
|
2563
|
+
lineMetadata?: readonly (PlayLogMetadata | null)[];
|
|
2530
2564
|
lineIds?: readonly (string | null)[];
|
|
2531
2565
|
source?: PlayRunLedgerEventSource;
|
|
2532
2566
|
occurredAt?: number;
|
|
@@ -2542,6 +2576,7 @@ export function buildTerminalLogReplayEvents(input: {
|
|
|
2542
2576
|
runId: input.runId,
|
|
2543
2577
|
lines: input.lines,
|
|
2544
2578
|
lineContexts: input.lineContexts,
|
|
2579
|
+
lineMetadata: input.lineMetadata,
|
|
2545
2580
|
lineIds: input.lineIds,
|
|
2546
2581
|
source: 'coordinator',
|
|
2547
2582
|
occurredAt: input.occurredAt,
|
|
@@ -2584,6 +2619,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2584
2619
|
runId: patch.runId,
|
|
2585
2620
|
lines: patch.liveLogs,
|
|
2586
2621
|
lineContexts: patch.liveLogContexts ?? undefined,
|
|
2622
|
+
lineMetadata: patch.liveLogMetadata ?? undefined,
|
|
2587
2623
|
lineIds: patch.liveLogIds ?? undefined,
|
|
2588
2624
|
source,
|
|
2589
2625
|
occurredAt: checkpointAt,
|
|
@@ -2666,6 +2702,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2666
2702
|
? { supersededRows: progress.supersededRows }
|
|
2667
2703
|
: {}),
|
|
2668
2704
|
...(progress.message !== undefined ? { message: progress.message } : {}),
|
|
2705
|
+
...(progress.error !== undefined ? { error: progress.error } : {}),
|
|
2669
2706
|
...(progress.artifactTableNamespace !== undefined
|
|
2670
2707
|
? { artifactTableNamespace: progress.artifactTableNamespace }
|
|
2671
2708
|
: {}),
|
|
@@ -2692,6 +2729,7 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2692
2729
|
occurredAt: progress.updatedAt ?? checkpointAt,
|
|
2693
2730
|
stepId,
|
|
2694
2731
|
status:
|
|
2732
|
+
typeof progress.error === 'string' ||
|
|
2695
2733
|
typeof progress.nodeIo?.error === 'string'
|
|
2696
2734
|
? 'failed'
|
|
2697
2735
|
: typeof progress.completedAt === 'number'
|
|
@@ -2703,9 +2741,18 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2703
2741
|
});
|
|
2704
2742
|
}
|
|
2705
2743
|
|
|
2706
|
-
|
|
2744
|
+
const stepError = progress.error ?? progress.nodeIo?.error;
|
|
2745
|
+
if (
|
|
2746
|
+
progress.completedAt &&
|
|
2747
|
+
(!previousStep?.completedAt ||
|
|
2748
|
+
(typeof stepError === 'string' && previousStep.status !== 'failed'))
|
|
2749
|
+
) {
|
|
2707
2750
|
events.push({
|
|
2708
|
-
type:
|
|
2751
|
+
type:
|
|
2752
|
+
typeof stepError === 'string'
|
|
2753
|
+
? RUN_EVENT_KIND.stepFailed
|
|
2754
|
+
: RUN_EVENT_KIND.stepCompleted,
|
|
2755
|
+
...(typeof stepError === 'string' ? { error: stepError } : {}),
|
|
2709
2756
|
runId: patch.runId,
|
|
2710
2757
|
source,
|
|
2711
2758
|
occurredAt: progress.completedAt,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import type { PlayLogContext } from './log-context';
|
|
2
|
-
import {
|
|
1
|
+
import type { PlayLogContext, PlayLogMetadata } from './log-context';
|
|
2
|
+
import {
|
|
3
|
+
normalizePlayLogContext,
|
|
4
|
+
normalizePlayLogMetadata,
|
|
5
|
+
} from './log-context';
|
|
3
6
|
|
|
4
7
|
/** Limits apply before logs enter runner memory or a transport request. */
|
|
5
8
|
export const RUNNER_LOG_MAX_CHARS = 2_000;
|
|
@@ -28,6 +31,7 @@ export class RunLogBuffer {
|
|
|
28
31
|
readonly ids: string[] = [];
|
|
29
32
|
private readonly origin = crypto.randomUUID();
|
|
30
33
|
readonly contexts: Array<PlayLogContext | null> = [];
|
|
34
|
+
readonly metadata: Array<PlayLogMetadata | null> = [];
|
|
31
35
|
private bytes = 0;
|
|
32
36
|
private contextBytes = 0;
|
|
33
37
|
private omittedContexts = 0;
|
|
@@ -38,10 +42,12 @@ export class RunLogBuffer {
|
|
|
38
42
|
raw: string,
|
|
39
43
|
terminal = false,
|
|
40
44
|
context?: PlayLogContext | null,
|
|
45
|
+
metadata?: PlayLogMetadata | null,
|
|
41
46
|
): string[] {
|
|
42
47
|
const line = boundRunLogLine(raw);
|
|
43
48
|
const bytes = encoder.encode(line).byteLength;
|
|
44
49
|
const normalizedContext = normalizePlayLogContext(context);
|
|
50
|
+
const normalizedMetadata = normalizePlayLogMetadata(metadata);
|
|
45
51
|
const contextBytes = normalizedContext
|
|
46
52
|
? encoder.encode(JSON.stringify(normalizedContext)).byteLength
|
|
47
53
|
: 0;
|
|
@@ -60,6 +66,7 @@ export class RunLogBuffer {
|
|
|
60
66
|
}
|
|
61
67
|
this.ids.push(`${this.origin}:${this.lines.length}`);
|
|
62
68
|
this.lines.push(line);
|
|
69
|
+
this.metadata.push(normalizedMetadata);
|
|
63
70
|
const retainContext =
|
|
64
71
|
normalizedContext !== null &&
|
|
65
72
|
this.contextBytes + contextBytes <= RUNNER_LOG_CONTEXT_MAX_BYTES;
|
|
@@ -36,7 +36,10 @@ import {
|
|
|
36
36
|
DURABLE_INVOCATION_FENCE_ATTESTATION_VALUE,
|
|
37
37
|
} from '../durable-invocation-fence';
|
|
38
38
|
import type { PlayRunInputPayload } from '../play-input';
|
|
39
|
-
import type {
|
|
39
|
+
import type {
|
|
40
|
+
PlayLogContext,
|
|
41
|
+
PlayLogMetadata,
|
|
42
|
+
} from '../log-context';
|
|
40
43
|
import { playRunInputObjectView } from '../play-input';
|
|
41
44
|
import {
|
|
42
45
|
normalizePlayRunFailure,
|
|
@@ -1737,6 +1740,13 @@ async function executeRuntimePlayCode(input: {
|
|
|
1737
1740
|
}
|
|
1738
1741
|
|
|
1739
1742
|
const CAPTURED_CONSOLE_MAX_CHARS = 2_000;
|
|
1743
|
+
const CAPTURED_CONSOLE_PREFIX_RESERVE_CHARS = 64;
|
|
1744
|
+
const CAPTURED_CONSOLE_SHORTENED_MARKER =
|
|
1745
|
+
'… [log shortened; save complete values in a dataset and use runs export]';
|
|
1746
|
+
const CAPTURED_CONSOLE_MAX_MESSAGE_CHARS =
|
|
1747
|
+
CAPTURED_CONSOLE_MAX_CHARS - CAPTURED_CONSOLE_PREFIX_RESERVE_CHARS;
|
|
1748
|
+
const CAPTURED_CONSOLE_FORMAT_TRUNCATION =
|
|
1749
|
+
/(\.\.\.|…)\s*\d+\s+more\s+(?:characters?|items?)/i;
|
|
1740
1750
|
|
|
1741
1751
|
function logLevelForCapturedConsoleMethod(
|
|
1742
1752
|
method: string,
|
|
@@ -1763,14 +1773,20 @@ function createCapturedCustomerConsole(
|
|
|
1763
1773
|
compact: true,
|
|
1764
1774
|
depth: 4,
|
|
1765
1775
|
maxArrayLength: 20,
|
|
1766
|
-
maxStringLength:
|
|
1776
|
+
maxStringLength: CAPTURED_CONSOLE_MAX_MESSAGE_CHARS,
|
|
1767
1777
|
},
|
|
1768
1778
|
...args,
|
|
1769
1779
|
);
|
|
1770
|
-
const
|
|
1771
|
-
formatted.length >
|
|
1772
|
-
|
|
1773
|
-
|
|
1780
|
+
const shortened =
|
|
1781
|
+
formatted.length > CAPTURED_CONSOLE_MAX_MESSAGE_CHARS ||
|
|
1782
|
+
CAPTURED_CONSOLE_FORMAT_TRUNCATION.test(formatted);
|
|
1783
|
+
const message = shortened
|
|
1784
|
+
? `${formatted.slice(
|
|
1785
|
+
0,
|
|
1786
|
+
CAPTURED_CONSOLE_MAX_MESSAGE_CHARS -
|
|
1787
|
+
CAPTURED_CONSOLE_SHORTENED_MARKER.length,
|
|
1788
|
+
)}${CAPTURED_CONSOLE_SHORTENED_MARKER}`
|
|
1789
|
+
: formatted;
|
|
1774
1790
|
ctx.log(`[console.${method}] ${message}`, {
|
|
1775
1791
|
level: logLevelForCapturedConsoleMethod(method),
|
|
1776
1792
|
});
|
|
@@ -1923,6 +1939,13 @@ function terminalLogsWithPhaseSummary(ctx: {
|
|
|
1923
1939
|
];
|
|
1924
1940
|
}
|
|
1925
1941
|
|
|
1942
|
+
function terminalLogMetadataWithPhaseSummary(ctx: {
|
|
1943
|
+
getLogMetadata(): Array<PlayLogMetadata | null>;
|
|
1944
|
+
}): Array<PlayLogMetadata | null> | undefined {
|
|
1945
|
+
const metadata = ctx.getLogMetadata();
|
|
1946
|
+
return metadata.some(Boolean) ? [...metadata, null, null] : undefined;
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1926
1949
|
function terminalLogContextsWithPhaseSummary(ctx: {
|
|
1927
1950
|
getLogContexts(): Array<PlayLogContext | null>;
|
|
1928
1951
|
}): Array<PlayLogContext | null> | undefined {
|
|
@@ -2496,7 +2519,7 @@ async function run(
|
|
|
2496
2519
|
});
|
|
2497
2520
|
}
|
|
2498
2521
|
: undefined,
|
|
2499
|
-
onLog: (line, context, entryId) => {
|
|
2522
|
+
onLog: (line, context, entryId, metadata) => {
|
|
2500
2523
|
const timestampMatch = line.match(/^\[([^\]]+)\]/);
|
|
2501
2524
|
const timestamp = timestampMatch?.[1];
|
|
2502
2525
|
const at =
|
|
@@ -2513,6 +2536,7 @@ async function run(
|
|
|
2513
2536
|
? { entryId }
|
|
2514
2537
|
: {}),
|
|
2515
2538
|
...(context ? { context } : {}),
|
|
2539
|
+
...(metadata ? { metadata } : {}),
|
|
2516
2540
|
},
|
|
2517
2541
|
options,
|
|
2518
2542
|
);
|
|
@@ -3143,6 +3167,7 @@ async function run(
|
|
|
3143
3167
|
? { logIds: terminalLogIdsWithPhaseSummary(ctx) }
|
|
3144
3168
|
: {}),
|
|
3145
3169
|
logContexts: terminalLogContextsWithPhaseSummary(ctx),
|
|
3170
|
+
logMetadata: terminalLogMetadataWithPhaseSummary(ctx),
|
|
3146
3171
|
stats: runtimeStats(),
|
|
3147
3172
|
steps: ctx.getSteps(),
|
|
3148
3173
|
tableNamespace: null,
|
|
@@ -3390,6 +3415,7 @@ async function run(
|
|
|
3390
3415
|
? { logIds: terminalLogIdsWithPhaseSummary(ctx) }
|
|
3391
3416
|
: {}),
|
|
3392
3417
|
logContexts: terminalLogContextsWithPhaseSummary(ctx),
|
|
3418
|
+
logMetadata: terminalLogMetadataWithPhaseSummary(ctx),
|
|
3393
3419
|
...(runtimeDiagnostics.length > 0 ? { runtimeDiagnostics } : {}),
|
|
3394
3420
|
...(rowOutcomes ? { rowOutcomes } : {}),
|
|
3395
3421
|
stats: runtimeStats(),
|
|
@@ -3448,6 +3474,7 @@ async function run(
|
|
|
3448
3474
|
? { logIds: terminalLogIdsWithPhaseSummary(ctx) }
|
|
3449
3475
|
: {}),
|
|
3450
3476
|
logContexts: terminalLogContextsWithPhaseSummary(ctx),
|
|
3477
|
+
logMetadata: terminalLogMetadataWithPhaseSummary(ctx),
|
|
3451
3478
|
stats: runtimeStats(),
|
|
3452
3479
|
steps: ctx.getSteps(),
|
|
3453
3480
|
checkpoint: ctx.getCheckpoint(),
|
|
@@ -3487,6 +3514,7 @@ async function run(
|
|
|
3487
3514
|
? { logIds: terminalLogIdsWithPhaseSummary(ctx) }
|
|
3488
3515
|
: {}),
|
|
3489
3516
|
logContexts: terminalLogContextsWithPhaseSummary(ctx),
|
|
3517
|
+
logMetadata: terminalLogMetadataWithPhaseSummary(ctx),
|
|
3490
3518
|
...(rowOutcomes ? { rowOutcomes } : {}),
|
|
3491
3519
|
stats: runtimeStats(),
|
|
3492
3520
|
steps: ctx.getSteps(),
|