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
|
@@ -879,7 +879,7 @@ export type RunsEventSearchOptions = {
|
|
|
879
879
|
playName?: string;
|
|
880
880
|
/** Exact dotted event kind, such as `step.failed`. The catalog is discoverable with `runs logs --help`; future stored kinds are accepted too. */
|
|
881
881
|
kind?: string;
|
|
882
|
-
/** JSONPath equality joined with `&&`, at most eight predicates and 512 bytes. See `runs logs --help` for fields and examples. Missing fields do not match; status is not inferred from kind. HTTP `jsonpath`, CLI `--where`. */
|
|
882
|
+
/** JSONPath equality joined with `&&`, at most eight predicates and 512 bytes. `eventId` selects an exact returned event; add `payloads` to retrieve its saved details. See `runs logs --help` for fields and examples. Missing fields do not match; status is not inferred from kind. HTTP `jsonpath`, CLI `--where`. */
|
|
883
883
|
jsonpath?: string;
|
|
884
884
|
/** Include available `eventPayload` details and receipt `payload` results; maximum ten events and 16 MiB. HTTP `payloads=true`, CLI `--payloads`. */
|
|
885
885
|
includePayloads?: boolean;
|
|
@@ -905,7 +905,7 @@ export type RunsEventSearchEntry = {
|
|
|
905
905
|
playName: string;
|
|
906
906
|
/** Exact dotted event kind, such as `step.failed`. */
|
|
907
907
|
kind: string;
|
|
908
|
-
/** Recorded log severity, or null
|
|
908
|
+
/** Recorded log severity, or null on older events. Filter with `$.level == "error"`. */
|
|
909
909
|
level: string | null;
|
|
910
910
|
/** Log message preview of at most 2,048 characters, or null. Use text logs/export for the full retained line. */
|
|
911
911
|
message: string | null;
|
|
@@ -933,7 +933,7 @@ export type RunsEventSearchResult = {
|
|
|
933
933
|
export type RunsEventPayload = {
|
|
934
934
|
/** Recorded terminal work outcome. */
|
|
935
935
|
status: 'completed' | 'failed' | 'skipped';
|
|
936
|
-
/**
|
|
936
|
+
/** Saved result, including available sanitized call input/output details; failed-call records use kind: tool_call_evidence. Null when no output was retained. */
|
|
937
937
|
output: unknown | null;
|
|
938
938
|
/** Stored failure message, or null when absent. */
|
|
939
939
|
error: string | null;
|
|
@@ -3320,8 +3320,10 @@ export class DeeplineClient {
|
|
|
3320
3320
|
/**
|
|
3321
3321
|
* Execute a tool and return the standard execution envelope.
|
|
3322
3322
|
*
|
|
3323
|
-
* The `toolResponse.rawV2` field contains the complete
|
|
3324
|
-
* `
|
|
3323
|
+
* The `toolResponse.rawV2` field contains the complete tool response,
|
|
3324
|
+
* preserving its original nesting. Inspect `getTool().examples` for a full
|
|
3325
|
+
* Deepline response example. Optional `toolResponse.responseMeta` contains
|
|
3326
|
+
* response metadata.
|
|
3325
3327
|
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
3326
3328
|
* Deepline execution envelope.
|
|
3327
3329
|
*/
|
|
@@ -4346,7 +4348,7 @@ export class DeeplineClient {
|
|
|
4346
4348
|
});
|
|
4347
4349
|
} catch (error) {
|
|
4348
4350
|
failedLogsLoaded = false;
|
|
4349
|
-
const retryCommand = `deepline runs
|
|
4351
|
+
const retryCommand = `deepline runs logs ${runId} --failed --json`;
|
|
4350
4352
|
const reason =
|
|
4351
4353
|
error instanceof Error && error.message.trim()
|
|
4352
4354
|
? ` (${error.message.trim().slice(0, 500)})`
|
|
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
|
|
|
200
200
|
// getters keep their established compatibility behavior.
|
|
201
201
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
202
202
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
203
|
-
version: '0.3.
|
|
203
|
+
version: '0.3.291',
|
|
204
204
|
updateSummary:
|
|
205
205
|
'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
|
|
206
206
|
packageCapabilities: {
|
|
@@ -35,7 +35,7 @@ function lifecycleActions(status: PlayStatus, id: string, state?: string) {
|
|
|
35
35
|
: {}),
|
|
36
36
|
...(state === 'failed'
|
|
37
37
|
? {
|
|
38
|
-
getFailedLogsCmd: `deepline runs
|
|
38
|
+
getFailedLogsCmd: `deepline runs logs ${id} --failed --json`,
|
|
39
39
|
...(status.rerunCommand ? { rerunCmd: status.rerunCommand } : {}),
|
|
40
40
|
}
|
|
41
41
|
: {}),
|
|
@@ -149,7 +149,10 @@ function datasetSummary(value: unknown, conflictingPopulation: boolean) {
|
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
/** Action descriptions are affordances, never evidence that an action ran. */
|
|
152
|
-
function actions
|
|
152
|
+
function actions<const Names extends Record<string, string>>(
|
|
153
|
+
value: unknown,
|
|
154
|
+
names: Names,
|
|
155
|
+
): Partial<Record<Names[keyof Names], string>> {
|
|
153
156
|
return Object.fromEntries(
|
|
154
157
|
Object.entries(record(value) ?? {}).flatMap(([name, value]) => {
|
|
155
158
|
const action = record(value);
|
|
@@ -167,7 +170,7 @@ function actions(value: unknown, names: Record<string, string>) {
|
|
|
167
170
|
],
|
|
168
171
|
];
|
|
169
172
|
}),
|
|
170
|
-
)
|
|
173
|
+
) as Partial<Record<Names[keyof Names], string>>;
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
/**
|
|
@@ -175,7 +178,10 @@ function actions(value: unknown, names: Record<string, string>) {
|
|
|
175
178
|
* from a server that predates it, the same derivation over the step's
|
|
176
179
|
* reported status and map progress.
|
|
177
180
|
*/
|
|
178
|
-
function stepExecution(
|
|
181
|
+
function stepExecution(
|
|
182
|
+
step: RecordValue,
|
|
183
|
+
runStatus: string,
|
|
184
|
+
): NodeExecutionState {
|
|
179
185
|
const decoded = decodeNodeExecutionState(step.execution);
|
|
180
186
|
if (decoded) return decoded;
|
|
181
187
|
const progress = record(step.progress);
|
|
@@ -323,7 +329,11 @@ export function buildRunOverview(status: PlayStatus, fullStatus?: PlayStatus) {
|
|
|
323
329
|
);
|
|
324
330
|
return {
|
|
325
331
|
datasetId: dataset.datasetId,
|
|
326
|
-
name:
|
|
332
|
+
name:
|
|
333
|
+
dataset.tableNamespace ??
|
|
334
|
+
(typeof stepOutput?.tableNamespace === 'string'
|
|
335
|
+
? stepOutput.tableNamespace
|
|
336
|
+
: dataset.path),
|
|
327
337
|
stepId: step?.id ?? named[0]?.[1].stepId,
|
|
328
338
|
rowCount: dataset.rowCount ?? null,
|
|
329
339
|
...(dataset.lifecycle ? { lifecycle: dataset.lifecycle } : {}),
|
|
@@ -456,7 +466,7 @@ export function buildRunOverview(status: PlayStatus, fullStatus?: PlayStatus) {
|
|
|
456
466
|
function receiptAction(id: string) {
|
|
457
467
|
const quotedId = `'${id.replace(/'/g, "'\\''")}'`;
|
|
458
468
|
return {
|
|
459
|
-
getReceiptCmd: `deepline runs
|
|
469
|
+
getReceiptCmd: `deepline runs logs ${quotedId} --kind receipt.completed --payloads --json`,
|
|
460
470
|
};
|
|
461
471
|
}
|
|
462
472
|
|
|
@@ -226,6 +226,24 @@ export interface ToolDefinition extends ToolExecutionMetadataFields {
|
|
|
226
226
|
inputSchema?: Record<string, unknown>;
|
|
227
227
|
/** JSON Schema describing the tool's output shape. */
|
|
228
228
|
outputSchema?: Record<string, unknown>;
|
|
229
|
+
/** JSON Schema for the Deepline API execution response, including toolResponse.rawV2. */
|
|
230
|
+
responseSchema?: Record<string, unknown>;
|
|
231
|
+
/** Illustrative input and full API response examples, separate from schemas. */
|
|
232
|
+
examples?: Array<{
|
|
233
|
+
input: Record<string, unknown>;
|
|
234
|
+
inputSource: 'sample' | 'schema';
|
|
235
|
+
responseSource: 'sample' | 'schema' | 'no_result';
|
|
236
|
+
description: string;
|
|
237
|
+
response: {
|
|
238
|
+
job_id: string;
|
|
239
|
+
status: string;
|
|
240
|
+
toolResponse: {
|
|
241
|
+
rawV2: unknown;
|
|
242
|
+
view: 'data' | 'rawV2';
|
|
243
|
+
responseMeta?: Record<string, unknown>;
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
}>;
|
|
229
247
|
/** User-facing pricing summary. Internal provider/settlement costs are intentionally omitted. */
|
|
230
248
|
pricing?: ToolPricingSummary | null;
|
|
231
249
|
/** How to use the tool well: the provider's summary and the tool's own notes. */
|
|
@@ -600,7 +618,8 @@ export interface ToolSearchResult {
|
|
|
600
618
|
* const meta = await client.getTool('dropleads_search_people');
|
|
601
619
|
* console.log(meta.displayName); // "DropLeads People Search"
|
|
602
620
|
* console.log(meta.estimatedCreditsRange); // "1-5"
|
|
603
|
-
* console.log(meta.
|
|
621
|
+
* console.log(meta.examples?.[0].input); // example input payload
|
|
622
|
+
* console.log(meta.examples?.[0].response); // full Deepline execution response
|
|
604
623
|
* ```
|
|
605
624
|
*/
|
|
606
625
|
export interface ToolMetadata extends ToolDefinition {
|
|
@@ -632,7 +651,7 @@ export interface ToolMetadata extends ToolDefinition {
|
|
|
632
651
|
estimateBasedOnTools?: string[];
|
|
633
652
|
/** Individual step cost contributions (for composite tools). */
|
|
634
653
|
stepContributions?: unknown[];
|
|
635
|
-
/**
|
|
654
|
+
/** Tool body samples. Full execution response examples are available in examples. */
|
|
636
655
|
samples?: Record<string, unknown>;
|
|
637
656
|
}
|
|
638
657
|
|
|
@@ -13,7 +13,10 @@ import type { AsyncPlayRunRef } from '../plays/authoring-contract';
|
|
|
13
13
|
import type { PlayRowUpdate } from './/ctx-types';
|
|
14
14
|
import type { PlayRunTimelineEntry } from './/live-events';
|
|
15
15
|
import type { PlayDatasetBornFrom } from './/cell-provenance';
|
|
16
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
PlayLogContext,
|
|
18
|
+
PlayLogMetadata,
|
|
19
|
+
} from './/log-context';
|
|
17
20
|
import {
|
|
18
21
|
routePlayActivityObservation,
|
|
19
22
|
type PlayActivityObservation,
|
|
@@ -111,6 +114,7 @@ export type RuntimeStatusUpdate = {
|
|
|
111
114
|
liveLogs?: string[];
|
|
112
115
|
/** Search-only context aligned to `liveLogs`; stripped before Convex. */
|
|
113
116
|
liveLogContexts?: Array<PlayLogContext | null>;
|
|
117
|
+
liveLogMetadata?: Array<PlayLogMetadata | null>;
|
|
114
118
|
liveLogIds?: Array<string | null>;
|
|
115
119
|
/**
|
|
116
120
|
* Monotonic count of log lines the producer ever emitted on this run's
|
|
@@ -160,6 +164,7 @@ export type RuntimeStatusUpdate = {
|
|
|
160
164
|
terminalLogReplay?: {
|
|
161
165
|
lines: string[];
|
|
162
166
|
lineContexts?: Array<PlayLogContext | null>;
|
|
167
|
+
lineMetadata?: Array<PlayLogMetadata | null>;
|
|
163
168
|
lineIds?: Array<string | null>;
|
|
164
169
|
totalCount?: number;
|
|
165
170
|
dedupeMode?: 'semantic' | 'exact';
|
|
@@ -2219,6 +2224,7 @@ async function updateRunStatusViaAppRuntimeUnlocked(
|
|
|
2219
2224
|
? slicePositionalLogLines({
|
|
2220
2225
|
bufferLines: update.liveLogs,
|
|
2221
2226
|
bufferContexts: update.liveLogContexts,
|
|
2227
|
+
bufferMetadata: update.liveLogMetadata,
|
|
2222
2228
|
bufferIds: update.liveLogIds,
|
|
2223
2229
|
bufferTotalCount: update.liveLogTotalCount ?? update.liveLogs.length,
|
|
2224
2230
|
sentCount,
|
|
@@ -2231,6 +2237,7 @@ async function updateRunStatusViaAppRuntimeUnlocked(
|
|
|
2231
2237
|
? {
|
|
2232
2238
|
lines: update.liveLogs,
|
|
2233
2239
|
lineContexts: update.liveLogContexts,
|
|
2240
|
+
lineMetadata: update.liveLogMetadata,
|
|
2234
2241
|
lineIds: update.liveLogIds,
|
|
2235
2242
|
totalCount: update.liveLogTotalCount,
|
|
2236
2243
|
producerAttempt: update.liveLogProducerAttempt,
|
|
@@ -2256,6 +2263,7 @@ async function updateRunStatusViaAppRuntimeUnlocked(
|
|
|
2256
2263
|
...logSlice,
|
|
2257
2264
|
lines: prefix,
|
|
2258
2265
|
lineContexts: logSlice.lineContexts?.slice(0, prefix.length),
|
|
2266
|
+
lineMetadata: logSlice.lineMetadata?.slice(0, prefix.length),
|
|
2259
2267
|
lineIds: logSlice.lineIds?.slice(0, prefix.length),
|
|
2260
2268
|
};
|
|
2261
2269
|
}
|
|
@@ -2268,6 +2276,7 @@ async function updateRunStatusViaAppRuntimeUnlocked(
|
|
|
2268
2276
|
lastCheckpointAt: update.lastCheckpointAt ?? null,
|
|
2269
2277
|
liveLogs: statusPatchLogSlice?.lines ?? null,
|
|
2270
2278
|
liveLogContexts: statusPatchLogSlice?.lineContexts ?? null,
|
|
2279
|
+
liveLogMetadata: statusPatchLogSlice?.lineMetadata ?? null,
|
|
2271
2280
|
liveLogIds: statusPatchLogSlice?.lineIds ?? null,
|
|
2272
2281
|
liveLogsChannelOffset: statusPatchLogSlice?.channelOffset ?? null,
|
|
2273
2282
|
liveLogsProducerAttempt: update.liveLogProducerAttempt ?? null,
|
|
@@ -2354,6 +2363,7 @@ async function updateRunStatusViaAppRuntimeUnlocked(
|
|
|
2354
2363
|
occurredAt: update.lastCheckpointAt ?? Date.now(),
|
|
2355
2364
|
lines: terminalLogReplay.lines,
|
|
2356
2365
|
lineContexts: terminalLogReplay.lineContexts,
|
|
2366
|
+
lineMetadata: terminalLogReplay.lineMetadata,
|
|
2357
2367
|
lineIds: terminalLogReplay.lineIds,
|
|
2358
2368
|
liveLogTotalCount: terminalLogReplay.totalCount,
|
|
2359
2369
|
dedupeMode: terminalLogReplay.dedupeMode,
|
|
@@ -216,7 +216,11 @@ import {
|
|
|
216
216
|
ToolExecuteAuthScopeChangedError,
|
|
217
217
|
type ToolExecuteHttpFailureOutcome,
|
|
218
218
|
} from './tool-execute-retry-policy';
|
|
219
|
-
import {
|
|
219
|
+
import {
|
|
220
|
+
createToolHttpError,
|
|
221
|
+
attachToolCallFailureEvidenceFromResponse,
|
|
222
|
+
readToolCallFailureEvidence,
|
|
223
|
+
} from './tool-http-errors';
|
|
220
224
|
import {
|
|
221
225
|
describeTransportError,
|
|
222
226
|
transportGatewayOriginForDiagnostic,
|
|
@@ -255,6 +259,7 @@ import {
|
|
|
255
259
|
} from './play-artifact-runtime-contract';
|
|
256
260
|
import {
|
|
257
261
|
LOG_LEVELS,
|
|
262
|
+
classifyLogLine,
|
|
258
263
|
formatCtxFetchHttpFailureDiagnostic,
|
|
259
264
|
tagLogEntry,
|
|
260
265
|
tagLogLevel,
|
|
@@ -446,7 +451,11 @@ import {
|
|
|
446
451
|
RunLogBuffer,
|
|
447
452
|
RUNNER_LOG_CONTEXT_MAX_BYTES,
|
|
448
453
|
} from './run-log-buffer';
|
|
449
|
-
import {
|
|
454
|
+
import {
|
|
455
|
+
normalizePlayLogContext,
|
|
456
|
+
type PlayLogContext,
|
|
457
|
+
type PlayLogMetadata,
|
|
458
|
+
} from './log-context';
|
|
450
459
|
import type { AsyncPlayRunRef } from '../plays/authoring-contract';
|
|
451
460
|
import { admitAsyncPlayLineage } from './async-play-invocation';
|
|
452
461
|
import {
|
|
@@ -536,6 +545,11 @@ type InlineCompositionStore = {
|
|
|
536
545
|
};
|
|
537
546
|
const inlineCompositionContext =
|
|
538
547
|
new AsyncLocalStorage<InlineCompositionStore>();
|
|
548
|
+
// Authored scope is async-local: concurrent steps and rows cannot steal attribution.
|
|
549
|
+
const authoredStepContext = new AsyncLocalStorage<{
|
|
550
|
+
context: PlayContextImpl;
|
|
551
|
+
stepId: string;
|
|
552
|
+
}>();
|
|
539
553
|
const toolExecutionOverrides = new AsyncLocalStorage<{ force: boolean }>();
|
|
540
554
|
const PROGRESS_HEARTBEAT_INTERVAL_MS = 1_000;
|
|
541
555
|
const PURE_JS_HEARTBEAT_ROW_INTERVAL = 250;
|
|
@@ -6387,11 +6401,14 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
6387
6401
|
? {
|
|
6388
6402
|
relayReceiptOutput: {
|
|
6389
6403
|
receiptKey: input.resultReceiptKey,
|
|
6390
|
-
execution:
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6404
|
+
execution: {
|
|
6405
|
+
...toolExecutionMetadataForOutcome({
|
|
6406
|
+
kind: 'live',
|
|
6407
|
+
cacheKey: input.request.cacheKey,
|
|
6408
|
+
receiptKey: input.request.receiptKey,
|
|
6409
|
+
}),
|
|
6410
|
+
resultReceiptKey: input.resultReceiptKey,
|
|
6411
|
+
},
|
|
6395
6412
|
metadata: await this.resolveToolResultMetadata(
|
|
6396
6413
|
input.dispatchToolId,
|
|
6397
6414
|
),
|
|
@@ -6431,11 +6448,16 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
6431
6448
|
meta: execution.meta,
|
|
6432
6449
|
billing: execution.billing,
|
|
6433
6450
|
requestInput: input.dispatchPayload,
|
|
6434
|
-
execution:
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6451
|
+
execution: {
|
|
6452
|
+
...toolExecutionMetadataForOutcome({
|
|
6453
|
+
kind: 'live',
|
|
6454
|
+
cacheKey: input.request.cacheKey,
|
|
6455
|
+
receiptKey: input.request.receiptKey,
|
|
6456
|
+
}),
|
|
6457
|
+
...(!alwaysFresh && input.resultReceiptKey
|
|
6458
|
+
? { resultReceiptKey: input.resultReceiptKey }
|
|
6459
|
+
: {}),
|
|
6460
|
+
},
|
|
6439
6461
|
});
|
|
6440
6462
|
// First sub-phase of `resultDelivery`: the body was parsed above, and
|
|
6441
6463
|
// this is the instant the row's result actually exists. Everything
|
|
@@ -7052,7 +7074,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
7052
7074
|
|
|
7053
7075
|
private async serializeCellValue(value: unknown): Promise<unknown> {
|
|
7054
7076
|
const serialized = isToolExecuteResult(value)
|
|
7055
|
-
? serializeToolExecuteResult(value)
|
|
7077
|
+
? serializeToolExecuteResult(value, { includeCallEvidence: false })
|
|
7056
7078
|
: await this.serializeDatasetCells(value);
|
|
7057
7079
|
try {
|
|
7058
7080
|
stringifyPostgresJson(serialized);
|
|
@@ -7073,7 +7095,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
7073
7095
|
const visiting = new WeakSet<object>();
|
|
7074
7096
|
const visit = async (current: unknown): Promise<unknown> => {
|
|
7075
7097
|
if (isToolExecuteResult(current)) {
|
|
7076
|
-
return serializeToolExecuteResult(current
|
|
7098
|
+
return serializeToolExecuteResult(current, {
|
|
7099
|
+
includeCallEvidence: false,
|
|
7100
|
+
});
|
|
7077
7101
|
}
|
|
7078
7102
|
if (isPlayDataset(current)) {
|
|
7079
7103
|
return await serializePlayDatasetCell(current, visit);
|
|
@@ -7379,7 +7403,20 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
7379
7403
|
input.metadata ??
|
|
7380
7404
|
(await this.resolveToolResultMetadata(input.toolId)),
|
|
7381
7405
|
execution: input.execution,
|
|
7382
|
-
meta:
|
|
7406
|
+
meta: {
|
|
7407
|
+
...input.meta,
|
|
7408
|
+
...(input.execution.source === 'live' &&
|
|
7409
|
+
input.requestInput &&
|
|
7410
|
+
!input.meta?.callEvidence
|
|
7411
|
+
? {
|
|
7412
|
+
callEvidence: {
|
|
7413
|
+
input: this.secretRedactor.redact(input.requestInput),
|
|
7414
|
+
providerRequestsUnavailable:
|
|
7415
|
+
'This response did not retain provider HTTP evidence.',
|
|
7416
|
+
},
|
|
7417
|
+
}
|
|
7418
|
+
: {}),
|
|
7419
|
+
},
|
|
7383
7420
|
billing: input.billing,
|
|
7384
7421
|
}),
|
|
7385
7422
|
);
|
|
@@ -12582,6 +12619,54 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
12582
12619
|
};
|
|
12583
12620
|
}
|
|
12584
12621
|
|
|
12622
|
+
private async saveToolFailureEvidence(input: {
|
|
12623
|
+
toolId: string;
|
|
12624
|
+
callKey: string;
|
|
12625
|
+
input: Record<string, unknown>;
|
|
12626
|
+
error: unknown;
|
|
12627
|
+
context: PlayLogContext;
|
|
12628
|
+
}): Promise<string | undefined> {
|
|
12629
|
+
if (!this.#options.completeRuntimeStepReceipt) return;
|
|
12630
|
+
try {
|
|
12631
|
+
// An immutable diagnostic record in the SAME receipt store, discovered
|
|
12632
|
+
// through runtime_observability.events. It is never an executable result
|
|
12633
|
+
// cache and cannot change provider admission or replay semantics.
|
|
12634
|
+
const receipt = await this.completeRuntimeStepReceipt(
|
|
12635
|
+
`${buildDurableToolReceiptPrefix({
|
|
12636
|
+
orgId: this.#options.orgId ?? 'unknown-org',
|
|
12637
|
+
toolId: 'call-evidence',
|
|
12638
|
+
})}${stableDigest(`${this.currentRunId}:${crypto.randomUUID()}`)}`,
|
|
12639
|
+
this.currentRunId,
|
|
12640
|
+
this.secretRedactor.redact({
|
|
12641
|
+
kind: 'tool_call_evidence',
|
|
12642
|
+
toolId: input.toolId,
|
|
12643
|
+
callKey: input.callKey,
|
|
12644
|
+
status: 'failed',
|
|
12645
|
+
context: input.context,
|
|
12646
|
+
callEvidence: readToolCallFailureEvidence(input.error) ?? {
|
|
12647
|
+
input: input.input,
|
|
12648
|
+
providerRequestsUnavailable:
|
|
12649
|
+
'This failure did not retain provider HTTP evidence.',
|
|
12650
|
+
},
|
|
12651
|
+
error:
|
|
12652
|
+
serializeToolExecutionFailure(input.error) ??
|
|
12653
|
+
this.formatRuntimeError(input.error),
|
|
12654
|
+
}),
|
|
12655
|
+
COMPLETED_RECEIPT_CACHE_INSERT_LEASE_ID,
|
|
12656
|
+
);
|
|
12657
|
+
if (!receipt)
|
|
12658
|
+
throw new Error('Saved failure evidence was not acknowledged.');
|
|
12659
|
+
return receipt.key;
|
|
12660
|
+
} catch (error) {
|
|
12661
|
+
// Keep the original failure and never repeat a paid operation just to
|
|
12662
|
+
// repair observability. A missing record is explicit in retained logs.
|
|
12663
|
+
this.runtimeLog(
|
|
12664
|
+
`Saved call details unavailable: ${this.formatRuntimeError(error)}`,
|
|
12665
|
+
{ level: 'warn' },
|
|
12666
|
+
);
|
|
12667
|
+
}
|
|
12668
|
+
}
|
|
12669
|
+
|
|
12585
12670
|
private async executeTool(
|
|
12586
12671
|
key: string,
|
|
12587
12672
|
toolId: string,
|
|
@@ -12610,13 +12695,31 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
12610
12695
|
!isPlayRowExecutionSuspendedError(error) &&
|
|
12611
12696
|
!(error instanceof PlayRowProviderBackpressureError)
|
|
12612
12697
|
) {
|
|
12698
|
+
const scope = authoredStepContext.getStore();
|
|
12699
|
+
const savedKey = await this.saveToolFailureEvidence({
|
|
12700
|
+
toolId,
|
|
12701
|
+
callKey: context.call_key,
|
|
12702
|
+
context: {
|
|
12703
|
+
callKey: context.call_key,
|
|
12704
|
+
toolId,
|
|
12705
|
+
callStatus: 'failed',
|
|
12706
|
+
...(scope?.context === this ? { stepId: scope.stepId } : {}),
|
|
12707
|
+
...(context.dataset ? { dataset: context.dataset } : {}),
|
|
12708
|
+
...(context.column ? { column: context.column } : {}),
|
|
12709
|
+
...(context.row_key ? { rowKey: context.row_key } : {}),
|
|
12710
|
+
},
|
|
12711
|
+
input,
|
|
12712
|
+
error,
|
|
12713
|
+
});
|
|
12613
12714
|
this.runtimeLog(
|
|
12614
12715
|
JSON.stringify({
|
|
12615
12716
|
event: 'tool_call_failed',
|
|
12616
12717
|
...context,
|
|
12718
|
+
...(savedKey ? { receipt_key: savedKey } : {}),
|
|
12617
12719
|
status: 'failed',
|
|
12618
12720
|
duration_ms: Math.max(0, Date.now() - startedAt),
|
|
12619
12721
|
}),
|
|
12722
|
+
{ level: 'error' },
|
|
12620
12723
|
);
|
|
12621
12724
|
}
|
|
12622
12725
|
throw error;
|
|
@@ -12627,7 +12730,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
12627
12730
|
JSON.stringify({
|
|
12628
12731
|
event: 'tool_call_completed',
|
|
12629
12732
|
...context,
|
|
12630
|
-
...(execution?.
|
|
12733
|
+
...(execution?.resultReceiptKey || execution?.receiptKey
|
|
12734
|
+
? { receipt_key: execution.resultReceiptKey ?? execution.receiptKey }
|
|
12735
|
+
: {}),
|
|
12631
12736
|
...(execution?.source ? { execution_source: execution.source } : {}),
|
|
12632
12737
|
status: toolResult?.status ?? 'completed',
|
|
12633
12738
|
// Caller wall time includes queueing/reuse and result delivery. It is
|
|
@@ -14287,7 +14392,21 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
14287
14392
|
): void {
|
|
14288
14393
|
const boundedLine = boundRunLogLine(line);
|
|
14289
14394
|
const omittedBefore = this.logBuffer.snapshot().omittedLines;
|
|
14290
|
-
|
|
14395
|
+
const scope = authoredStepContext.getStore();
|
|
14396
|
+
const classified = classifyLogLine(line);
|
|
14397
|
+
const timestamp = classified.line.match(/^\[([^\]]+)\]/)?.[1];
|
|
14398
|
+
const parsedAt = timestamp ? Date.parse(timestamp) : NaN;
|
|
14399
|
+
const metadata: PlayLogMetadata = {
|
|
14400
|
+
level: classified.level,
|
|
14401
|
+
occurredAt: Number.isFinite(parsedAt) ? parsedAt : Date.now(),
|
|
14402
|
+
...(scope?.context === this ? { stepId: scope.stepId } : {}),
|
|
14403
|
+
};
|
|
14404
|
+
for (const retained of this.logBuffer.append(
|
|
14405
|
+
line,
|
|
14406
|
+
terminal,
|
|
14407
|
+
context,
|
|
14408
|
+
metadata,
|
|
14409
|
+
)) {
|
|
14291
14410
|
const originalLineWasRetained =
|
|
14292
14411
|
retained === boundedLine &&
|
|
14293
14412
|
this.logBuffer.snapshot().omittedLines === omittedBefore;
|
|
@@ -14297,6 +14416,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
14297
14416
|
? (this.logBuffer.contexts.at(-1) ?? undefined)
|
|
14298
14417
|
: undefined,
|
|
14299
14418
|
this.logBuffer.ids.at(-1),
|
|
14419
|
+
originalLineWasRetained
|
|
14420
|
+
? (this.logBuffer.metadata.at(-1) ?? undefined)
|
|
14421
|
+
: undefined,
|
|
14300
14422
|
);
|
|
14301
14423
|
if (this.#options.verbose) console.log(retained);
|
|
14302
14424
|
}
|
|
@@ -14960,42 +15082,76 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
14960
15082
|
return output;
|
|
14961
15083
|
};
|
|
14962
15084
|
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
this.
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14972
|
-
|
|
14973
|
-
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
|
|
14981
|
-
|
|
14982
|
-
|
|
14983
|
-
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
|
|
14991
|
-
|
|
14992
|
-
|
|
15085
|
+
const observe = !rowStore;
|
|
15086
|
+
const startedAt = Date.now();
|
|
15087
|
+
if (observe)
|
|
15088
|
+
this.emitExecutionEvent({
|
|
15089
|
+
type: 'step.started',
|
|
15090
|
+
stepId: normalizedKey,
|
|
15091
|
+
at: startedAt,
|
|
15092
|
+
});
|
|
15093
|
+
try {
|
|
15094
|
+
const output = await authoredStepContext.run(
|
|
15095
|
+
{ context: this, stepId: normalizedKey },
|
|
15096
|
+
() =>
|
|
15097
|
+
this.executeWithRuntimeReceipt<T>(
|
|
15098
|
+
'step',
|
|
15099
|
+
normalizedKey,
|
|
15100
|
+
this.currentRunId,
|
|
15101
|
+
{
|
|
15102
|
+
semanticKey: rowStore
|
|
15103
|
+
? stableDigest(
|
|
15104
|
+
stableStringify({
|
|
15105
|
+
scope: 'row',
|
|
15106
|
+
tableNamespace: rowStore.tableNamespace ?? null,
|
|
15107
|
+
rowKey: rowStore.rowKey ?? null,
|
|
15108
|
+
rowId: rowStore.rowKey ? null : rowStore.rowId,
|
|
15109
|
+
fieldName: rowStore.fieldName ?? null,
|
|
15110
|
+
callIndex,
|
|
15111
|
+
// Row scope prevents unrelated map cells from sharing a
|
|
15112
|
+
// checkpoint. A supplied semantic key identifies the actual
|
|
15113
|
+
// work (for example, ctx.runSteps hashes its current input),
|
|
15114
|
+
// so it must refine row scope rather than being discarded.
|
|
15115
|
+
semanticKey: options?.semanticKey ?? null,
|
|
15116
|
+
}),
|
|
15117
|
+
)
|
|
15118
|
+
: options?.semanticKey,
|
|
15119
|
+
staleAfterSeconds: options?.staleAfterSeconds,
|
|
15120
|
+
force: this.#options.cachePolicy?.forceStepRefresh === true,
|
|
15121
|
+
markSkipped: (output) => {
|
|
15122
|
+
assertJsonSerializableStepOutput(normalizedKey, output);
|
|
15123
|
+
},
|
|
15124
|
+
execute: executeStep,
|
|
15125
|
+
},
|
|
15126
|
+
),
|
|
15127
|
+
);
|
|
15128
|
+
if (observe)
|
|
15129
|
+
this.emitExecutionEvent({
|
|
15130
|
+
type: 'step.completed',
|
|
15131
|
+
stepId: normalizedKey,
|
|
15132
|
+
at: Date.now(),
|
|
15133
|
+
});
|
|
15134
|
+
return output;
|
|
15135
|
+
} catch (error) {
|
|
15136
|
+
if (observe && !isControlledPlaySuspension(error))
|
|
15137
|
+
this.emitExecutionEvent({
|
|
15138
|
+
type: 'step.failed',
|
|
15139
|
+
stepId: normalizedKey,
|
|
15140
|
+
at: Date.now(),
|
|
15141
|
+
error: buildPlayDocflowNodeErrorPreview(error, this.secretRedactor),
|
|
15142
|
+
});
|
|
15143
|
+
throw error;
|
|
15144
|
+
}
|
|
14993
15145
|
}
|
|
14994
15146
|
|
|
14995
15147
|
getLogs(): string[] {
|
|
14996
15148
|
return this.logBuffer.lines;
|
|
14997
15149
|
}
|
|
14998
15150
|
|
|
15151
|
+
getLogMetadata(): Array<PlayLogMetadata | null> {
|
|
15152
|
+
return this.logBuffer.metadata.slice();
|
|
15153
|
+
}
|
|
15154
|
+
|
|
14999
15155
|
getLogIds(): string[] {
|
|
15000
15156
|
return this.logBuffer.ids.slice();
|
|
15001
15157
|
}
|
|
@@ -15582,15 +15738,16 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
15582
15738
|
source: 'cache' | 'owner',
|
|
15583
15739
|
): Promise<void> => {
|
|
15584
15740
|
const receiptKey = request.receiptKey!;
|
|
15585
|
-
const finalResult = cloneToolExecuteResultWithExecution(
|
|
15586
|
-
|
|
15587
|
-
toolExecutionMetadataForOutcome({
|
|
15741
|
+
const finalResult = cloneToolExecuteResultWithExecution(result, {
|
|
15742
|
+
...toolExecutionMetadataForOutcome({
|
|
15588
15743
|
kind: source === 'owner' ? 'live' : source,
|
|
15589
15744
|
cacheKey: request.cacheKey,
|
|
15590
15745
|
receiptKey,
|
|
15591
15746
|
...(source === 'owner' ? {} : { attachedToReceiptKey: receiptKey }),
|
|
15592
15747
|
}),
|
|
15593
|
-
|
|
15748
|
+
resultReceiptKey:
|
|
15749
|
+
this.mappedToolResultReceiptPolicy(request).resultReceiptKey,
|
|
15750
|
+
});
|
|
15594
15751
|
this.cacheToolResult(toolId, request.cacheKey, finalResult);
|
|
15595
15752
|
const resolver = this.toolCallResolvers.get(request.callId);
|
|
15596
15753
|
if (resolver) {
|
|
@@ -19305,6 +19462,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
19305
19462
|
`gateway=${transportGatewayOriginForDiagnostic(url)} attempt=${httpFailureAttempt})`,
|
|
19306
19463
|
{ level: 'error' },
|
|
19307
19464
|
);
|
|
19465
|
+
attachToolCallFailureEvidenceFromResponse(surfacedError, text);
|
|
19308
19466
|
throw surfacedError;
|
|
19309
19467
|
}
|
|
19310
19468
|
|
|
@@ -11,7 +11,7 @@ import type { PlayRunContractSnapshot } from '../plays/contracts';
|
|
|
11
11
|
import type { PlayDatasetColumnTypes } from '../play-data-plane/contracts';
|
|
12
12
|
import type { PlayStructuredDefinition } from '../plays/definition';
|
|
13
13
|
import type { PlayStaticPipeline } from '../plays/static-pipeline';
|
|
14
|
-
import type { PlayLogContext } from './log-context';
|
|
14
|
+
import type { PlayLogContext, PlayLogMetadata } from './log-context';
|
|
15
15
|
import type {
|
|
16
16
|
AsyncPlayRunRef,
|
|
17
17
|
DurableCallStaleAfterSeconds,
|
|
@@ -514,6 +514,9 @@ export interface MapExecutionScope {
|
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
export type PlayExecutionEvent =
|
|
517
|
+
| { type: 'step.started'; stepId: string; at: number }
|
|
518
|
+
| { type: 'step.completed'; stepId: string; at: number }
|
|
519
|
+
| { type: 'step.failed'; stepId: string; error: string; at: number }
|
|
517
520
|
| PlayActivityEvent
|
|
518
521
|
| {
|
|
519
522
|
type: 'docflow.node.hit';
|
|
@@ -851,7 +854,12 @@ export interface ContextOptions {
|
|
|
851
854
|
/** Called after each durable batch completes for scheduler checkpointing. */
|
|
852
855
|
onBatchComplete?: (checkpoint: PlayCheckpoint) => void;
|
|
853
856
|
/** Called when the runtime emits a new execution log line. */
|
|
854
|
-
onLog?: (
|
|
857
|
+
onLog?: (
|
|
858
|
+
line: string,
|
|
859
|
+
context?: PlayLogContext,
|
|
860
|
+
entryId?: string,
|
|
861
|
+
metadata?: PlayLogMetadata,
|
|
862
|
+
) => void;
|
|
855
863
|
/**
|
|
856
864
|
* Runtime-provided HTTP transport for ctx.fetch. Node runtimes should provide
|
|
857
865
|
* a transport that validates resolved IP addresses at connect time.
|