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
|
@@ -40,7 +40,7 @@ const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
|
40
40
|
/**
|
|
41
41
|
* One projector can keep this many independent Run Ledger deliveries in
|
|
42
42
|
* flight after it has found durable work. Each delivery owns only short
|
|
43
|
-
* Postgres checkouts: claim
|
|
43
|
+
* Postgres checkouts: claim with routing, renewal, and acknowledgement. It does
|
|
44
44
|
* not hold a scheduler connection across either gateway HTTP request. This is
|
|
45
45
|
* therefore a network/projection concurrency budget, deliberately independent
|
|
46
46
|
* of the projector's much smaller Postgres pool.
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* After reader-first cutover, triggers persist raw input in the existing
|
|
5
5
|
* outbox. The leased dispatcher projects and compacts it before delivery.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* PlanetScale runtime_observability.events is the single log/event/receipt
|
|
7
|
+
* discovery surface. JSONPath runs natively against its indexed search_doc;
|
|
8
|
+
* exact identities use indexed columns on that same table. Full saved results
|
|
9
|
+
* resolve through the scoped fetch_receipt capability, never a second search
|
|
10
|
+
* store or a CLI-side scan. Receipt output remains authoritative in its store.
|
|
11
|
+
* The API uses only the fixed, tenant-scoped readers in this module.
|
|
8
12
|
*/
|
|
9
13
|
import { normalizeRuntimeSchedulerSchema } from '../runtime-scheduler-topology';
|
|
10
14
|
import type { PostgresSchedulerQueryClient } from './postgres';
|
|
@@ -57,7 +61,7 @@ const RUNTIME_EVENT_LOG_POSITION_EXPRESSION = `jsonb_set(
|
|
|
57
61
|
// Migration readiness tracks this projection body independently of scheduler
|
|
58
62
|
// wire and schema versions. Bump when a changed trigger must be reinstalled.
|
|
59
63
|
export const RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER =
|
|
60
|
-
'runtime-event-search-origin-batches-
|
|
64
|
+
'runtime-event-search-origin-batches-log-metadata';
|
|
61
65
|
/** Trusted trigger-authored state; absent on already-projected legacy rows. */
|
|
62
66
|
export const RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD =
|
|
63
67
|
'_runtimeSearchProjectionPending';
|
|
@@ -177,7 +181,7 @@ function parseRuntimeEventJsonpath(value: string): RuntimeEventPredicate[] {
|
|
|
177
181
|
);
|
|
178
182
|
}
|
|
179
183
|
const clause =
|
|
180
|
-
/\$\.(orgId|runId|playName|runtimeScope|producerAttempt|kind|status|source|stepId|stepKind|datasetId|phase|provider|operation|context\.[A-Za-z_][A-Za-z0-9_]{0,63})\s*==\s*("(?:\\.|[^"\\])*"|true|false|-?\d+(?:\.\d+)?)/y;
|
|
184
|
+
/\$\.(eventId|orgId|runId|playName|runtimeScope|producerAttempt|kind|status|source|level|stepId|stepKind|datasetId|phase|provider|operation|context\.[A-Za-z_][A-Za-z0-9_]{0,63})\s*==\s*("(?:\\.|[^"\\])*"|true|false|-?\d+(?:\.\d+)?)/y;
|
|
181
185
|
let position = 0;
|
|
182
186
|
let clauses = 0;
|
|
183
187
|
const predicates: RuntimeEventPredicate[] = [];
|
|
@@ -214,7 +218,9 @@ function parseRuntimeEventJsonpath(value: string): RuntimeEventPredicate[] {
|
|
|
214
218
|
);
|
|
215
219
|
}
|
|
216
220
|
if (
|
|
217
|
-
['orgId', 'runId', 'playName', 'runtimeScope'].includes(
|
|
221
|
+
['eventId', 'orgId', 'runId', 'playName', 'runtimeScope'].includes(
|
|
222
|
+
match[1],
|
|
223
|
+
) &&
|
|
218
224
|
typeof parsed !== 'string'
|
|
219
225
|
) {
|
|
220
226
|
throw new RuntimeEventInputError(
|
|
@@ -231,6 +237,14 @@ function parseRuntimeEventJsonpath(value: string): RuntimeEventPredicate[] {
|
|
|
231
237
|
'Runtime event producerAttempt requires a positive integer.',
|
|
232
238
|
);
|
|
233
239
|
}
|
|
240
|
+
if (
|
|
241
|
+
match[1] === 'level' &&
|
|
242
|
+
!['debug', 'info', 'warn', 'error'].includes(String(parsed))
|
|
243
|
+
) {
|
|
244
|
+
throw new RuntimeEventInputError(
|
|
245
|
+
'Runtime event level requires debug, info, warn or error.',
|
|
246
|
+
);
|
|
247
|
+
}
|
|
234
248
|
predicates.push({ path: match[1], literal: match[2], value: parsed });
|
|
235
249
|
if (
|
|
236
250
|
match[1].startsWith('context.') &&
|
|
@@ -348,6 +362,7 @@ export async function searchRuntimeEvents(
|
|
|
348
362
|
addExact('kind', input.kind);
|
|
349
363
|
if (input.jsonpath !== undefined) {
|
|
350
364
|
const identityColumns = {
|
|
365
|
+
eventId: 'event_id',
|
|
351
366
|
orgId: 'org_id',
|
|
352
367
|
runId: 'run_id',
|
|
353
368
|
playName: 'play_name',
|
|
@@ -1170,7 +1185,19 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1170
1185
|
NEW.updated_at, NEW.run_id, play, 'receipt.' || NEW.status,
|
|
1171
1186
|
ref, NEW.k, jsonb_strip_nulls(jsonb_build_object(
|
|
1172
1187
|
'kind', 'receipt.' || NEW.status, 'status', NEW.status,
|
|
1173
|
-
'source', 'receipt', 'producerAttempt', NEW.lease_owner_attempt
|
|
1188
|
+
'source', 'receipt', 'producerAttempt', NEW.lease_owner_attempt,
|
|
1189
|
+
-- Only the reserved runtime diagnostic record supplies this flat
|
|
1190
|
+
-- context. Ordinary authored receipt outputs are never indexed.
|
|
1191
|
+
'context', CASE WHEN NEW.k LIKE 'tool-evidence:%'
|
|
1192
|
+
AND NEW.output_json->>'kind' = 'tool_call_evidence' THEN jsonb_strip_nulls(jsonb_build_object(
|
|
1193
|
+
'callKey', NEW.output_json#>'{context,callKey}',
|
|
1194
|
+
'toolId', NEW.output_json#>'{context,toolId}',
|
|
1195
|
+
'callStatus', NEW.output_json#>'{context,callStatus}',
|
|
1196
|
+
'stepId', NEW.output_json#>'{context,stepId}',
|
|
1197
|
+
'dataset', NEW.output_json#>'{context,dataset}',
|
|
1198
|
+
'column', NEW.output_json#>'{context,column}',
|
|
1199
|
+
'rowKey', NEW.output_json#>'{context,rowKey}'
|
|
1200
|
+
)) END
|
|
1174
1201
|
))
|
|
1175
1202
|
);
|
|
1176
1203
|
RETURN NEW;
|
|
@@ -1189,6 +1216,41 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1189
1216
|
FOR EACH ROW EXECUTE FUNCTION ${schema}.search_receipt_event();
|
|
1190
1217
|
END IF;
|
|
1191
1218
|
END $create$`);
|
|
1219
|
+
await client.query(`
|
|
1220
|
+
CREATE OR REPLACE FUNCTION ${schema}.run_log_metadata(line text, metadata jsonb, fallback_at timestamptz) RETURNS jsonb
|
|
1221
|
+
LANGUAGE plpgsql IMMUTABLE SET search_path = pg_catalog AS $function$
|
|
1222
|
+
DECLARE clean text; message text; level text; at_time timestamptz := fallback_at;
|
|
1223
|
+
BEGIN
|
|
1224
|
+
clean := regexp_replace(line, '^' || chr(1) || 'prov:[^' || chr(1) || ']*' || chr(1), '');
|
|
1225
|
+
IF metadata IS NOT NULL AND metadata <> 'null'::jsonb THEN
|
|
1226
|
+
IF jsonb_typeof(metadata) IS DISTINCT FROM 'object'
|
|
1227
|
+
OR NOT coalesce(metadata->>'level' IN ('debug','info','warn','error'), false)
|
|
1228
|
+
OR jsonb_typeof(metadata->'occurredAt') IS DISTINCT FROM 'number'
|
|
1229
|
+
OR NOT coalesce(metadata->>'occurredAt' ~ '^[1-9][0-9]{0,15}$', false)
|
|
1230
|
+
OR (metadata ? 'stepId' AND (jsonb_typeof(metadata->'stepId') IS DISTINCT FROM 'string'
|
|
1231
|
+
OR length(metadata->>'stepId') NOT BETWEEN 1 AND 256)) THEN
|
|
1232
|
+
RAISE EXCEPTION 'Run log metadata is invalid';
|
|
1233
|
+
END IF;
|
|
1234
|
+
RETURN jsonb_strip_nulls(jsonb_build_object('level', metadata->'level',
|
|
1235
|
+
'occurredAt', metadata->'occurredAt', 'stepId', metadata->'stepId'));
|
|
1236
|
+
END IF;
|
|
1237
|
+
-- Historical lines already carry the original ISO time and severity.
|
|
1238
|
+
IF clean ~ '^\\[[-0-9]{10}T[0-9:.]+Z\\]' THEN
|
|
1239
|
+
BEGIN at_time := substring(clean from '^\\[([^]]+)\\]')::timestamptz;
|
|
1240
|
+
EXCEPTION WHEN invalid_datetime_format OR datetime_field_overflow THEN at_time := fallback_at; END;
|
|
1241
|
+
END IF;
|
|
1242
|
+
message := regexp_replace(clean, '^\\[[-0-9]{10}T[0-9:.]+Z\\][ ]*', '');
|
|
1243
|
+
level := CASE
|
|
1244
|
+
WHEN message ~* '^\\[(error|console.error)\\]' THEN 'error'
|
|
1245
|
+
WHEN message ~* '^\\[(warn|console.warn)\\]' THEN 'warn'
|
|
1246
|
+
WHEN message ~* '^\\[info\\]' THEN 'info'
|
|
1247
|
+
WHEN message ~* '^\\[(debug|console.debug|perf|runtime.(phase_summary|logs|log_transport))\\]'
|
|
1248
|
+
OR line ~ ('^' || chr(1) || 'prov:(infra|receipt|replay)' || chr(1)) THEN 'debug'
|
|
1249
|
+
ELSE 'info' END;
|
|
1250
|
+
RETURN jsonb_build_object('level', level, 'occurredAt', floor(extract(epoch FROM at_time) * 1000)::bigint);
|
|
1251
|
+
END
|
|
1252
|
+
$function$
|
|
1253
|
+
`);
|
|
1192
1254
|
await client.query(`
|
|
1193
1255
|
CREATE OR REPLACE FUNCTION ${schema}.project_origin_log_batch(observation ${schema}.outbox, item jsonb, run_org text, play text, compact_logs boolean, canonical_events boolean, at_time timestamptz, doc jsonb, closed boolean)
|
|
1194
1256
|
RETURNS text[] LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog AS $function$
|
|
@@ -1221,7 +1283,8 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1221
1283
|
WITH entries AS MATERIALIZED (
|
|
1222
1284
|
SELECT value #>> '{}' AS body, ordinality AS ordinal,
|
|
1223
1285
|
'log-origin:' || observation.run_id || ':' || (item->'lineIds'->>(ordinality-1)::int) AS eid,
|
|
1224
|
-
NULLIF(item->'lineContexts'->(ordinality-1)::int, 'null'::jsonb) AS ctx
|
|
1286
|
+
NULLIF(item->'lineContexts'->(ordinality-1)::int, 'null'::jsonb) AS ctx,
|
|
1287
|
+
${schema}.run_log_metadata(value #>> '{}', item->'lineMetadata'->(ordinality-1)::int, at_time) AS metadata
|
|
1225
1288
|
FROM jsonb_array_elements(item->'lines') WITH ORDINALITY
|
|
1226
1289
|
), inserted AS (
|
|
1227
1290
|
INSERT INTO runtime_observability.events (
|
|
@@ -1229,16 +1292,16 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1229
1292
|
run_id, play_name, kind, level, message, log_body, source_digest, log_text_digest, search_doc
|
|
1230
1293
|
) SELECT ${quoteLiteral(scope)}, run_org, eid,
|
|
1231
1294
|
CASE WHEN canonical_events THEN nextval('runtime_observability.runtime_event_order_seq') END,
|
|
1232
|
-
CASE WHEN canonical_events THEN jsonb_strip_nulls((item - 'lines' - 'lineContexts' - 'lineIds') || jsonb_build_object(
|
|
1295
|
+
CASE WHEN canonical_events THEN jsonb_strip_nulls((item - 'lines' - 'lineContexts' - 'lineIds' - 'lineMetadata') || jsonb_build_object(
|
|
1233
1296
|
'type', ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, 'runId', observation.run_id,
|
|
1234
|
-
'occurredAt',
|
|
1297
|
+
'occurredAt', metadata->'occurredAt', 'level', metadata->'level', 'stepId', metadata->'stepId', 'lineOrdinal', ordinal,
|
|
1235
1298
|
'entryId', item->'lineIds'->(ordinal-1)::int, 'context', ctx)) END,
|
|
1236
|
-
|
|
1299
|
+
to_timestamp((metadata->>'occurredAt')::double precision / 1000), observation.run_id, play, ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, metadata->>'level',
|
|
1237
1300
|
CASE WHEN compact_logs THEN NULL ELSE left(body, 2048) END, body,
|
|
1238
1301
|
CASE WHEN ctx IS NULL THEN encode(sha256(convert_to(body,'UTF8')),'hex')
|
|
1239
1302
|
ELSE encode(sha256(convert_to(jsonb_build_array(body,ctx)::text,'UTF8')),'hex') END,
|
|
1240
1303
|
encode(sha256(convert_to(btrim(body),'UTF8')),'hex'),
|
|
1241
|
-
doc || jsonb_strip_nulls(jsonb_build_object('entryId', item->'lineIds'->(ordinal-1)::int, 'context', ctx))
|
|
1304
|
+
doc || (metadata - 'occurredAt') || jsonb_strip_nulls(jsonb_build_object('entryId', item->'lineIds'->(ordinal-1)::int, 'context', ctx))
|
|
1242
1305
|
FROM entries WHERE NOT closed ORDER BY ordinal
|
|
1243
1306
|
ON CONFLICT (runtime_scope, org_id, event_id) DO NOTHING RETURNING event_id
|
|
1244
1307
|
) SELECT coalesce(array_agg(inserted.event_id ORDER BY entries.ordinal), ARRAY[]::text[])
|
|
@@ -1264,7 +1327,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1264
1327
|
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog AS $function$
|
|
1265
1328
|
DECLARE run_org text; play text; compact_logs boolean; canonical_events boolean; run_status text; item jsonb; line jsonb; event_batch jsonb;
|
|
1266
1329
|
ordinal bigint; line_ordinal bigint; kind text; at_time timestamptz;
|
|
1267
|
-
doc jsonb; line_doc jsonb; line_context jsonb;
|
|
1330
|
+
doc jsonb; line_doc jsonb; line_context jsonb; line_metadata jsonb; line_at timestamptz;
|
|
1268
1331
|
eid text; existing_digest text; digest text; assigned_seq bigint; terminal_progress_identity boolean;
|
|
1269
1332
|
log_channel text; log_position bigint; matched_event_id text; matched_doc jsonb;
|
|
1270
1333
|
legacy_position_prefix text; position_event_ids text[];
|
|
@@ -1349,6 +1412,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1349
1412
|
'producerAttempt', envelope_attempt, 'channelOffset', 0,
|
|
1350
1413
|
'lines', observation.payload_json->'terminalLogLines',
|
|
1351
1414
|
'lineContexts', observation.payload_json->'terminalLogContexts',
|
|
1415
|
+
'lineMetadata', observation.payload_json->'terminalLogMetadata',
|
|
1352
1416
|
'lineIds', NULLIF(observation.payload_json->'terminalLogIds', 'null'::jsonb)
|
|
1353
1417
|
))
|
|
1354
1418
|
);
|
|
@@ -1453,6 +1517,11 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1453
1517
|
OR jsonb_array_length(item->'lineContexts') <> jsonb_array_length(item->'lines')) THEN
|
|
1454
1518
|
RAISE EXCEPTION 'Search projection requires lineContexts aligned to log lines';
|
|
1455
1519
|
END IF;
|
|
1520
|
+
IF kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} AND item ? 'lineMetadata'
|
|
1521
|
+
AND (jsonb_typeof(item->'lineMetadata') IS DISTINCT FROM 'array'
|
|
1522
|
+
OR jsonb_array_length(item->'lineMetadata') <> jsonb_array_length(item->'lines')) THEN
|
|
1523
|
+
RAISE EXCEPTION 'Run log metadata must align with lines';
|
|
1524
|
+
END IF;
|
|
1456
1525
|
IF kind = ${RUN_EVENT_KIND_SQL_LITERAL.logAppended} AND item ? 'lineIds' THEN
|
|
1457
1526
|
IF jsonb_typeof(item->'lineIds') IS DISTINCT FROM 'array' OR jsonb_array_length(item->'lineIds') <> jsonb_array_length(item->'lines') THEN
|
|
1458
1527
|
RAISE EXCEPTION 'Origin log identities must align with lines';
|
|
@@ -1524,8 +1593,10 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1524
1593
|
RAISE EXCEPTION 'Search projection log context has an unsupported key or value';
|
|
1525
1594
|
END IF;
|
|
1526
1595
|
END IF;
|
|
1527
|
-
|
|
1528
|
-
|
|
1596
|
+
line_metadata := ${schema}.run_log_metadata(line #>> '{}', item->'lineMetadata'->((line_ordinal - 1)::int), at_time);
|
|
1597
|
+
line_at := to_timestamp((line_metadata->>'occurredAt')::double precision / 1000);
|
|
1598
|
+
line_doc := (CASE WHEN line_context IS NULL THEN doc
|
|
1599
|
+
ELSE doc || jsonb_build_object('context', line_context) END) || (line_metadata - 'occurredAt');
|
|
1529
1600
|
eid := CASE WHEN (item->>'channelOffset') ~ '^[0-9]{1,12}$'
|
|
1530
1601
|
AND (item->>'producerAttempt') ~ '^[0-9]{1,6}$'
|
|
1531
1602
|
THEN 'log:' || observation.run_id || ':' || (item->>'producerAttempt') || ':' ||
|
|
@@ -1673,14 +1744,14 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1673
1744
|
${quoteLiteral(scope)}, run_org, eid,
|
|
1674
1745
|
CASE WHEN canonical_events THEN nextval('runtime_observability.runtime_event_order_seq') END,
|
|
1675
1746
|
CASE WHEN canonical_events THEN jsonb_strip_nulls(
|
|
1676
|
-
(item - 'lines' - 'lineContexts' - 'lineIds') || jsonb_build_object(
|
|
1747
|
+
(item - 'lines' - 'lineContexts' - 'lineMetadata' - 'lineIds') || jsonb_build_object(
|
|
1677
1748
|
'type', ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, 'runId', observation.run_id,
|
|
1678
|
-
'occurredAt',
|
|
1749
|
+
'occurredAt', line_metadata->'occurredAt', 'level', line_metadata->'level', 'stepId', line_metadata->'stepId',
|
|
1679
1750
|
'lineOrdinal', line_ordinal,
|
|
1680
1751
|
'context', line_context
|
|
1681
1752
|
)) END,
|
|
1682
|
-
|
|
1683
|
-
${RUN_EVENT_KIND_SQL_LITERAL.logAppended},
|
|
1753
|
+
line_at, observation.run_id, play,
|
|
1754
|
+
${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, line_metadata->>'level', CASE WHEN compact_logs THEN NULL ELSE left(line #>> '{}', 2048) END,
|
|
1684
1755
|
line #>> '{}', digest,
|
|
1685
1756
|
encode(sha256(convert_to(btrim(line #>> '{}'), 'UTF8')), 'hex'), line_doc
|
|
1686
1757
|
) ON CONFLICT DO NOTHING;
|
|
@@ -1760,6 +1831,15 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1760
1831
|
AND NOT (observation.payload_json ? 'terminalLogLines') THEN
|
|
1761
1832
|
RAISE EXCEPTION 'Search projection requires terminalLogLines for terminalLogContexts';
|
|
1762
1833
|
END IF;
|
|
1834
|
+
IF observation.payload_json ? 'terminalLogMetadata'
|
|
1835
|
+
AND NOT (observation.payload_json ? 'terminalLogLines') THEN
|
|
1836
|
+
RAISE EXCEPTION 'Search projection requires terminalLogLines for terminalLogMetadata';
|
|
1837
|
+
END IF;
|
|
1838
|
+
IF observation.payload_json ? 'terminalLogMetadata'
|
|
1839
|
+
AND (jsonb_typeof(observation.payload_json->'terminalLogMetadata') IS DISTINCT FROM 'array'
|
|
1840
|
+
OR jsonb_array_length(observation.payload_json->'terminalLogMetadata') <> jsonb_array_length(observation.payload_json->'terminalLogLines')) THEN
|
|
1841
|
+
RAISE EXCEPTION 'Search projection requires terminalLogMetadata aligned to terminalLogLines';
|
|
1842
|
+
END IF;
|
|
1763
1843
|
IF observation.event_type IN (${RUN_EVENT_TERMINAL_LOG_CARRIER_SQL_LIST})
|
|
1764
1844
|
AND observation.payload_json ? 'terminalLogLines'
|
|
1765
1845
|
AND NOT coalesce((envelope_attempt #>> '{}') ~ '^[1-9][0-9]{0,5}$', false) THEN
|
|
@@ -1852,7 +1932,9 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1852
1932
|
RAISE EXCEPTION 'Search projection terminal log context has an unsupported key or value';
|
|
1853
1933
|
END IF;
|
|
1854
1934
|
END IF;
|
|
1855
|
-
|
|
1935
|
+
line_metadata := ${schema}.run_log_metadata(line #>> '{}', observation.payload_json->'terminalLogMetadata'->((line_ordinal - 1)::int), observation.created_at);
|
|
1936
|
+
line_at := to_timestamp((line_metadata->>'occurredAt')::double precision / 1000);
|
|
1937
|
+
line_doc := (line_metadata - 'occurredAt') || jsonb_strip_nulls(jsonb_build_object(
|
|
1856
1938
|
'kind', ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, 'source', 'terminal',
|
|
1857
1939
|
'producerAttempt', observation.payload_json->'producerAttempt'
|
|
1858
1940
|
));
|
|
@@ -1868,11 +1950,11 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1868
1950
|
CASE WHEN canonical_events THEN nextval('runtime_observability.runtime_event_order_seq') END,
|
|
1869
1951
|
CASE WHEN canonical_events THEN jsonb_strip_nulls(jsonb_build_object(
|
|
1870
1952
|
'type', ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, 'runId', observation.run_id,
|
|
1871
|
-
'occurredAt',
|
|
1953
|
+
'occurredAt', line_metadata->'occurredAt', 'level', line_metadata->'level', 'stepId', line_metadata->'stepId',
|
|
1872
1954
|
'source', 'terminal', 'producerAttempt', observation.payload_json->'producerAttempt',
|
|
1873
1955
|
'lineOrdinal', line_ordinal, 'context', line_context
|
|
1874
1956
|
)) END,
|
|
1875
|
-
|
|
1957
|
+
line_at, observation.run_id, play, ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}, line_metadata->>'level',
|
|
1876
1958
|
CASE WHEN compact_logs THEN NULL ELSE left(regexp_replace(line #>> '{}',
|
|
1877
1959
|
'^' || chr(1) || 'prov:[^' || chr(1) || ']*' || chr(1), ''), 2048) END,
|
|
1878
1960
|
line #>> '{}',
|
|
@@ -2019,7 +2101,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2019
2101
|
LANGUAGE sql IMMUTABLE SET search_path = pg_catalog AS $function$
|
|
2020
2102
|
WITH envelope AS (
|
|
2021
2103
|
SELECT CASE WHEN jsonb_typeof(value) = 'object' THEN
|
|
2022
|
-
(value - 'logContexts' - 'logIds') || CASE WHEN value ? 'logs'
|
|
2104
|
+
(value - 'logContexts' - 'logMetadata' - 'logIds') || CASE WHEN value ? 'logs'
|
|
2023
2105
|
THEN jsonb_build_object('logs', '[]'::jsonb) ELSE '{}'::jsonb END
|
|
2024
2106
|
ELSE value END AS result
|
|
2025
2107
|
)
|
|
@@ -2037,7 +2119,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2037
2119
|
INTO compact_logs, canonical_events
|
|
2038
2120
|
FROM ${schema}.runs WHERE run_id = observation.run_id;
|
|
2039
2121
|
IF compact_logs OR canonical_events THEN
|
|
2040
|
-
observation.payload_json := observation.payload_json - 'terminalLogLines' - 'terminalLogContexts' - 'terminalLogIds';
|
|
2122
|
+
observation.payload_json := observation.payload_json - 'terminalLogLines' - 'terminalLogContexts' - 'terminalLogIds' - 'terminalLogMetadata';
|
|
2041
2123
|
IF observation.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents} THEN
|
|
2042
2124
|
observation.payload_json := jsonb_set(observation.payload_json, '{events}',
|
|
2043
2125
|
${schema}.without_log_events(observation.payload_json->'events'))
|
|
@@ -2110,6 +2192,16 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2110
2192
|
NEW.payload_json := NEW.payload_json - '${RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD}' - '_runtimeSearchRunClosed';
|
|
2111
2193
|
PERFORM ${schema}.project_outbox_event(NEW);
|
|
2112
2194
|
NEW.payload_json := ${schema}.compact_runtime_outbox_payload(NEW);
|
|
2195
|
+
-- The search rows above are committed atomically with this outbox row.
|
|
2196
|
+
-- When compaction leaves no ledger event to project, settle the no-op
|
|
2197
|
+
-- receipt here so a delayed log-search fact cannot hold up run terminal
|
|
2198
|
+
-- projection behind the scheduler outbox.
|
|
2199
|
+
IF NEW.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents}
|
|
2200
|
+
AND NEW.payload_json->>'logBodyStore' = 'planet_scale'
|
|
2201
|
+
AND jsonb_typeof(NEW.payload_json->'events') = 'array'
|
|
2202
|
+
AND jsonb_array_length(NEW.payload_json->'events') = 0 THEN
|
|
2203
|
+
NEW.delivered_at := coalesce(NEW.delivered_at, clock_timestamp());
|
|
2204
|
+
END IF;
|
|
2113
2205
|
RETURN NEW;
|
|
2114
2206
|
END
|
|
2115
2207
|
$function$
|
|
@@ -2295,7 +2387,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2295
2387
|
${schema}.accept_runner_log_payload(), ${schema}.search_outbox_event(),
|
|
2296
2388
|
${schema}.compact_run_log_result(), ${schema}.without_log_events(jsonb),
|
|
2297
2389
|
${schema}.convex_projection_event(jsonb), ${schema}.convex_projection_events(jsonb),
|
|
2298
|
-
${schema}.compact_runner_log_envelope(jsonb), ${schema}.without_runtime_log_tail(jsonb)
|
|
2390
|
+
${schema}.run_log_metadata(text, jsonb, timestamptz), ${schema}.compact_runner_log_envelope(jsonb), ${schema}.without_runtime_log_tail(jsonb)
|
|
2299
2391
|
FROM PUBLIC`);
|
|
2300
2392
|
// Publish readiness last, after all acceptance/compaction functions exist.
|
|
2301
2393
|
await client.query(
|
|
@@ -45,6 +45,8 @@ export type PlayVisualNodeProgress = {
|
|
|
45
45
|
completedAt?: number | null;
|
|
46
46
|
artifactTableNamespace?: string | null;
|
|
47
47
|
nodeIo?: PlayDocflowNodeIoState;
|
|
48
|
+
/** Error reported by this step, distinct from a run stopping other work. */
|
|
49
|
+
error?: string;
|
|
48
50
|
conditionCounts?: PlayConditionCounts;
|
|
49
51
|
};
|
|
50
52
|
|
|
@@ -193,6 +195,9 @@ export function normalizePlayVisualNodeProgressMap(
|
|
|
193
195
|
...(startedAt !== undefined ? { startedAt } : {}),
|
|
194
196
|
...(completedAt !== undefined ? { completedAt } : {}),
|
|
195
197
|
...(message !== undefined ? { message } : {}),
|
|
198
|
+
...(typeof rawProgress.error === 'string' && rawProgress.error.trim()
|
|
199
|
+
? { error: rawProgress.error.trim() }
|
|
200
|
+
: {}),
|
|
196
201
|
...(artifactTableNamespace !== undefined
|
|
197
202
|
? { artifactTableNamespace }
|
|
198
203
|
: {}),
|
|
@@ -305,7 +310,7 @@ export function applyVisualNodeProgress(input: {
|
|
|
305
310
|
const completed = Number(progress.completed ?? 0);
|
|
306
311
|
const total = Number(progress.total ?? 0);
|
|
307
312
|
const progressStatus =
|
|
308
|
-
nodeState.status === 'failed'
|
|
313
|
+
nodeState.status === 'failed' || progress.error || progress.nodeIo?.error
|
|
309
314
|
? 'failed'
|
|
310
315
|
: Number.isFinite(total) && total > 0
|
|
311
316
|
? Number.isFinite(completed) && completed >= total
|
package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts
CHANGED
|
@@ -349,10 +349,14 @@ export function createRuntimeStepToolResultReceipts(
|
|
|
349
349
|
// exists to cap how many stored payloads expand at once; holding one
|
|
350
350
|
// of its slots across this gateway round trip only queued unrelated
|
|
351
351
|
// rows behind this row's write, so the mutation runs outside it.
|
|
352
|
+
const storedResult = stampResultReceipt(
|
|
353
|
+
candidate.result,
|
|
354
|
+
record.resultReceiptKey,
|
|
355
|
+
);
|
|
352
356
|
const persisted = await input.store.complete(
|
|
353
357
|
record.resultReceiptKey,
|
|
354
358
|
ownerRunId,
|
|
355
|
-
serializeToolExecuteResult(
|
|
359
|
+
serializeToolExecuteResult(storedResult),
|
|
356
360
|
COMPLETED_RECEIPT_CACHE_INSERT_LEASE_ID,
|
|
357
361
|
);
|
|
358
362
|
// Publication is immutable, but an independent miss keeps the
|
|
@@ -369,10 +373,10 @@ export function createRuntimeStepToolResultReceipts(
|
|
|
369
373
|
}
|
|
370
374
|
}
|
|
371
375
|
await input.onStored?.({
|
|
372
|
-
result:
|
|
376
|
+
result: storedResult,
|
|
373
377
|
resultReceiptKey: record.resultReceiptKey,
|
|
374
378
|
});
|
|
375
|
-
return { kind: 'stored', result:
|
|
379
|
+
return { kind: 'stored', result: storedResult };
|
|
376
380
|
} finally {
|
|
377
381
|
await stopHeartbeat(record);
|
|
378
382
|
await releaseExecutionLock(record);
|
|
@@ -394,6 +398,16 @@ export function createRuntimeStepToolResultReceipts(
|
|
|
394
398
|
};
|
|
395
399
|
}
|
|
396
400
|
|
|
401
|
+
function stampResultReceipt(
|
|
402
|
+
result: ToolExecuteResult,
|
|
403
|
+
resultReceiptKey: string,
|
|
404
|
+
): ToolExecuteResult {
|
|
405
|
+
return deserializeToolExecuteResult({
|
|
406
|
+
...serializeToolExecuteResult(result),
|
|
407
|
+
execution: { ...result._metadata.execution, resultReceiptKey },
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
|
|
397
411
|
function completedResult(
|
|
398
412
|
receipt: RuntimeStepReceipt | null,
|
|
399
413
|
resultReceiptKey: string,
|
|
@@ -402,10 +416,13 @@ function completedResult(
|
|
|
402
416
|
return null;
|
|
403
417
|
}
|
|
404
418
|
if (isSerializedToolExecuteResult(receipt.output)) {
|
|
405
|
-
return
|
|
419
|
+
return stampResultReceipt(
|
|
420
|
+
deserializeToolExecuteResult(receipt.output),
|
|
421
|
+
resultReceiptKey,
|
|
422
|
+
);
|
|
406
423
|
}
|
|
407
424
|
if (isToolExecuteResult(receipt.output)) {
|
|
408
|
-
return receipt.output;
|
|
425
|
+
return stampResultReceipt(receipt.output, resultReceiptKey);
|
|
409
426
|
}
|
|
410
427
|
throw new Error(
|
|
411
428
|
`Completed Tool Result Receipt ${resultReceiptKey} has no valid serialized ToolExecuteResult.`,
|
|
@@ -12,6 +12,41 @@ import {
|
|
|
12
12
|
} from '../plays/tool-execution-error';
|
|
13
13
|
|
|
14
14
|
const TOOL_HTTP_ERROR_BRAND = Symbol.for('deepline.tool-http-error.v1');
|
|
15
|
+
const callEvidenceByError = new WeakMap<object, unknown>();
|
|
16
|
+
|
|
17
|
+
/** Payload evidence stays out of the scalar portable error/status contract. */
|
|
18
|
+
export function attachToolCallFailureEvidence(
|
|
19
|
+
error: object,
|
|
20
|
+
evidence: unknown,
|
|
21
|
+
): void {
|
|
22
|
+
callEvidenceByError.set(error, evidence);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Read the already consumed error body without changing failure classification. */
|
|
26
|
+
export function attachToolCallFailureEvidenceFromResponse(
|
|
27
|
+
error: object,
|
|
28
|
+
body: string,
|
|
29
|
+
): void {
|
|
30
|
+
let response: unknown;
|
|
31
|
+
try {
|
|
32
|
+
response = JSON.parse(body);
|
|
33
|
+
} catch {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!response || typeof response !== 'object') return;
|
|
37
|
+
const meta = (response as Record<string, unknown>).meta;
|
|
38
|
+
if (!meta || typeof meta !== 'object') return;
|
|
39
|
+
attachToolCallFailureEvidence(
|
|
40
|
+
error,
|
|
41
|
+
(meta as Record<string, unknown>).callEvidence,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function readToolCallFailureEvidence(error: unknown): unknown {
|
|
46
|
+
return error && typeof error === 'object'
|
|
47
|
+
? callEvidenceByError.get(error)
|
|
48
|
+
: undefined;
|
|
49
|
+
}
|
|
15
50
|
|
|
16
51
|
type ToolHttpErrorConstructorInput = {
|
|
17
52
|
message: string;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
jsonByteLengthUpTo,
|
|
3
|
+
RUNTIME_RECEIPT_OUTPUT_MAX_BYTES,
|
|
4
|
+
} from './output-size-limits';
|
|
1
5
|
export type {
|
|
2
6
|
SerializedToolExecuteResult,
|
|
3
7
|
ToolExecuteResult,
|
|
@@ -83,6 +87,11 @@ const relayPublishedResultReferences = new WeakMap<
|
|
|
83
87
|
RuntimeReceiptValueReference
|
|
84
88
|
>();
|
|
85
89
|
|
|
90
|
+
// Call evidence belongs to the saved per-call payload. Keep it out of the
|
|
91
|
+
// enumerable Play result so returning a tool result or storing it in a row
|
|
92
|
+
// does not enlarge customer output with diagnostic request bodies.
|
|
93
|
+
const savedToolCallEvidence = new WeakMap<object, unknown>();
|
|
94
|
+
|
|
86
95
|
export function attachRelayPublishedToolResultReference(
|
|
87
96
|
result: ToolExecuteResult,
|
|
88
97
|
reference: RuntimeReceiptValueReference,
|
|
@@ -1271,6 +1280,7 @@ export function createToolExecuteResult<TResult = unknown>(input: {
|
|
|
1271
1280
|
meta?: Record<string, unknown>;
|
|
1272
1281
|
};
|
|
1273
1282
|
}): ToolExecuteResult<TResult> {
|
|
1283
|
+
const { callEvidence, ...publicMeta } = input.meta ?? {};
|
|
1274
1284
|
const result = toResultEnvelope(input.result);
|
|
1275
1285
|
const resultRoot = {
|
|
1276
1286
|
toolResponse: {
|
|
@@ -1320,7 +1330,7 @@ export function createToolExecuteResult<TResult = unknown>(input: {
|
|
|
1320
1330
|
const wrapper = {
|
|
1321
1331
|
status: input.status,
|
|
1322
1332
|
...(input.jobId ? { job_id: input.jobId } : {}),
|
|
1323
|
-
...(input.meta ? { meta:
|
|
1333
|
+
...(input.meta ? { meta: publicMeta } : {}),
|
|
1324
1334
|
...(input.billing ? { billing: input.billing } : {}),
|
|
1325
1335
|
toolResponse,
|
|
1326
1336
|
extractedValues,
|
|
@@ -1336,6 +1346,9 @@ export function createToolExecuteResult<TResult = unknown>(input: {
|
|
|
1336
1346
|
value: metadata,
|
|
1337
1347
|
enumerable: false,
|
|
1338
1348
|
});
|
|
1349
|
+
if (callEvidence !== undefined) {
|
|
1350
|
+
savedToolCallEvidence.set(wrapper, callEvidence);
|
|
1351
|
+
}
|
|
1339
1352
|
return wrapper;
|
|
1340
1353
|
}
|
|
1341
1354
|
|
|
@@ -1976,9 +1989,50 @@ function rawV2WithSerializedListRows(input: {
|
|
|
1976
1989
|
});
|
|
1977
1990
|
}
|
|
1978
1991
|
|
|
1992
|
+
/** Optional call evidence cannot turn a valid provider result into a retry. */
|
|
1993
|
+
function fitSavedCallEvidence(
|
|
1994
|
+
value: SerializedToolExecuteResult,
|
|
1995
|
+
): SerializedToolExecuteResult {
|
|
1996
|
+
if (
|
|
1997
|
+
!value.meta?.callEvidence ||
|
|
1998
|
+
!jsonByteLengthUpTo(value, RUNTIME_RECEIPT_OUTPUT_MAX_BYTES).exceeded
|
|
1999
|
+
)
|
|
2000
|
+
return value;
|
|
2001
|
+
const { callEvidence: _evidence, ...meta } = value.meta;
|
|
2002
|
+
const withoutEvidence = { ...value, meta };
|
|
2003
|
+
// Preserve the original oversized-output failure if the result itself is
|
|
2004
|
+
// invalid. Only newly added diagnostic evidence may be omitted.
|
|
2005
|
+
if (
|
|
2006
|
+
jsonByteLengthUpTo(withoutEvidence, RUNTIME_RECEIPT_OUTPUT_MAX_BYTES)
|
|
2007
|
+
.exceeded
|
|
2008
|
+
)
|
|
2009
|
+
return value;
|
|
2010
|
+
const reason =
|
|
2011
|
+
'Call evidence exceeds the saved-result size limit; the complete tool output is retained.';
|
|
2012
|
+
const unavailable = {
|
|
2013
|
+
...value,
|
|
2014
|
+
meta: { ...meta, callEvidence: { unavailable: reason } },
|
|
2015
|
+
};
|
|
2016
|
+
if (
|
|
2017
|
+
!jsonByteLengthUpTo(unavailable, RUNTIME_RECEIPT_OUTPUT_MAX_BYTES).exceeded
|
|
2018
|
+
)
|
|
2019
|
+
return unavailable;
|
|
2020
|
+
// An output exactly at the historical limit has no room for the marker.
|
|
2021
|
+
// Its original bytes remain legal; the runner retains the warning instead.
|
|
2022
|
+
console.warn(reason);
|
|
2023
|
+
return withoutEvidence;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1979
2026
|
export function serializeToolExecuteResult(
|
|
1980
2027
|
value: ToolExecuteResult,
|
|
2028
|
+
options?: { includeCallEvidence?: boolean },
|
|
1981
2029
|
): SerializedToolExecuteResult {
|
|
2030
|
+
const callEvidence =
|
|
2031
|
+
options?.includeCallEvidence === false
|
|
2032
|
+
? undefined
|
|
2033
|
+
: savedToolCallEvidence.get(value);
|
|
2034
|
+
const meta =
|
|
2035
|
+
callEvidence !== undefined ? { ...value.meta, callEvidence } : value.meta;
|
|
1982
2036
|
const metadata = metadataInputFromToolExecuteResult(value);
|
|
1983
2037
|
const listDatasets = serializedListDatasetsFromResult(value);
|
|
1984
2038
|
const listRows = serializedListRowsFromResult({
|
|
@@ -2007,11 +2061,11 @@ export function serializeToolExecuteResult(
|
|
|
2007
2061
|
view,
|
|
2008
2062
|
meta: value.toolResponse.meta,
|
|
2009
2063
|
});
|
|
2010
|
-
return {
|
|
2064
|
+
return fitSavedCallEvidence({
|
|
2011
2065
|
__kind: SERIALIZED_TOOL_EXECUTE_RESULT_V2_KIND,
|
|
2012
2066
|
status: value.status,
|
|
2013
2067
|
...(typeof value.job_id === 'string' ? { job_id: value.job_id } : {}),
|
|
2014
|
-
...(isRecord(
|
|
2068
|
+
...(isRecord(meta) ? { meta } : {}),
|
|
2015
2069
|
...(isRecord(value.billing) ? { billing: value.billing } : {}),
|
|
2016
2070
|
toolResponse: {
|
|
2017
2071
|
// rawV2 is the canonical complete provider response. Only the legacy
|
|
@@ -2035,13 +2089,13 @@ export function serializeToolExecuteResult(
|
|
|
2035
2089
|
...(targetValues ? { targetValues } : {}),
|
|
2036
2090
|
metadata,
|
|
2037
2091
|
execution: value._metadata.execution,
|
|
2038
|
-
};
|
|
2092
|
+
});
|
|
2039
2093
|
}
|
|
2040
|
-
return {
|
|
2094
|
+
return fitSavedCallEvidence({
|
|
2041
2095
|
__kind: SERIALIZED_TOOL_EXECUTE_RESULT_V1_KIND,
|
|
2042
2096
|
status: value.status,
|
|
2043
2097
|
...(typeof value.job_id === 'string' ? { job_id: value.job_id } : {}),
|
|
2044
|
-
...(isRecord(
|
|
2098
|
+
...(isRecord(meta) ? { meta } : {}),
|
|
2045
2099
|
...(isRecord(value.billing) ? { billing: value.billing } : {}),
|
|
2046
2100
|
toolResponse: {
|
|
2047
2101
|
raw: serializedRaw,
|
|
@@ -2052,7 +2106,7 @@ export function serializeToolExecuteResult(
|
|
|
2052
2106
|
...(targetValues ? { targetValues } : {}),
|
|
2053
2107
|
metadata,
|
|
2054
2108
|
execution: value._metadata.execution,
|
|
2055
|
-
};
|
|
2109
|
+
});
|
|
2056
2110
|
}
|
|
2057
2111
|
|
|
2058
2112
|
export function isSerializedToolExecuteResult(
|
|
@@ -2156,7 +2210,13 @@ export function cloneToolExecuteResultWithExecution<TResult>(
|
|
|
2156
2210
|
): ToolExecuteResult<TResult> {
|
|
2157
2211
|
return deserializeToolExecuteResult({
|
|
2158
2212
|
...serializeToolExecuteResult(value),
|
|
2159
|
-
execution
|
|
2213
|
+
execution: {
|
|
2214
|
+
...execution,
|
|
2215
|
+
...(!execution.resultReceiptKey &&
|
|
2216
|
+
value._metadata.execution.resultReceiptKey
|
|
2217
|
+
? { resultReceiptKey: value._metadata.execution.resultReceiptKey }
|
|
2218
|
+
: {}),
|
|
2219
|
+
},
|
|
2160
2220
|
}) as ToolExecuteResult<TResult>;
|
|
2161
2221
|
}
|
|
2162
2222
|
|
|
@@ -34,6 +34,8 @@ export type PlayVisualNodeProgress = {
|
|
|
34
34
|
completedAt?: number;
|
|
35
35
|
artifactTableNamespace?: string | null;
|
|
36
36
|
nodeIo?: PlayDocflowNodeIoState;
|
|
37
|
+
/** Error reported by this step, distinct from a run stopping other work. */
|
|
38
|
+
error?: string;
|
|
37
39
|
conditionCounts?: PlayConditionCounts;
|
|
38
40
|
};
|
|
39
41
|
|
|
@@ -37,6 +37,8 @@ export type ToolResultExecutionMetadata = {
|
|
|
37
37
|
cacheKey?: string;
|
|
38
38
|
receiptRole?: 'owner' | 'follower';
|
|
39
39
|
receiptKey?: string;
|
|
40
|
+
/** Canonical saved result identity; receiptKey may name a transport alias. */
|
|
41
|
+
resultReceiptKey?: string;
|
|
40
42
|
attachedToReceiptKey?: string;
|
|
41
43
|
};
|
|
42
44
|
|