deepline 0.3.49 → 0.3.51
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/index.ts +1 -0
- package/dist/bundling-sources/sdk/src/play.ts +1 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +106 -89
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +0 -2
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +52 -21
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +45 -5
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +11 -3
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +0 -2
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/secret-capability.ts +5 -1
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +1 -14
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/contract.ts +17 -7
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +0 -1
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +112 -5
- package/dist/bundling-sources/shared_libs/security/safe-fetch.ts +6 -1
- package/dist/cli/index.js +837 -3147
- package/dist/cli/index.mjs +704 -3010
- package/dist/{compiler-manifest-CbzdZrJj.d.mts → compiler-manifest-B47AA7As.d.mts} +46 -4
- package/dist/{compiler-manifest-CbzdZrJj.d.ts → compiler-manifest-B47AA7As.d.ts} +46 -4
- package/dist/index.d.mts +151 -149
- package/dist/index.d.ts +151 -149
- package/dist/index.js +1515 -117
- package/dist/index.mjs +1514 -117
- package/dist/install-integrity.json +2 -2
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +5 -2614
- package/package.json +2 -1
|
@@ -36,8 +36,6 @@ type ValidatedRuntimeTestFaultHeader =
|
|
|
36
36
|
export type RuntimeTestPolicyOverrides = {
|
|
37
37
|
/** Opt-in bounded runner map latency profile for local/preview diagnosis. */
|
|
38
38
|
mapLatencyProfile?: boolean;
|
|
39
|
-
/** Exercise provider pacing during fixture runs without dispatching provider traffic. */
|
|
40
|
-
enforceFixtureProviderPacing?: boolean;
|
|
41
39
|
receiptLeaseTtlMs?: number;
|
|
42
40
|
sheetAttemptLeaseMs?: number;
|
|
43
41
|
heartbeatIntervalMs?: number;
|
|
@@ -258,8 +256,7 @@ function parseRuntimeTestPolicyOverrides(
|
|
|
258
256
|
(key) =>
|
|
259
257
|
!RUNTIME_TEST_POLICY_MS_FIELDS.has(key) &&
|
|
260
258
|
key !== 'workBudgetYieldLimits' &&
|
|
261
|
-
key !== 'mapLatencyProfile'
|
|
262
|
-
key !== 'enforceFixtureProviderPacing',
|
|
259
|
+
key !== 'mapLatencyProfile',
|
|
263
260
|
);
|
|
264
261
|
if (unknownKeys.length > 0) {
|
|
265
262
|
return {
|
|
@@ -276,16 +273,6 @@ function parseRuntimeTestPolicyOverrides(
|
|
|
276
273
|
}
|
|
277
274
|
overrides.mapLatencyProfile = record.mapLatencyProfile;
|
|
278
275
|
}
|
|
279
|
-
if ('enforceFixtureProviderPacing' in record) {
|
|
280
|
-
if (typeof record.enforceFixtureProviderPacing !== 'boolean') {
|
|
281
|
-
return {
|
|
282
|
-
error:
|
|
283
|
-
'testPolicyOverrides.enforceFixtureProviderPacing must be a boolean.',
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
overrides.enforceFixtureProviderPacing =
|
|
287
|
-
record.enforceFixtureProviderPacing;
|
|
288
|
-
}
|
|
289
276
|
for (const field of RUNTIME_TEST_POLICY_MS_FIELDS) {
|
|
290
277
|
if (!(field in record)) continue;
|
|
291
278
|
const parsed = readPositiveIntegerField({
|
|
@@ -105,15 +105,25 @@ export type ToolResultReceipts = {
|
|
|
105
105
|
}): Promise<void>;
|
|
106
106
|
};
|
|
107
107
|
|
|
108
|
+
export type AlwaysFreshToolCallDispatch = {
|
|
109
|
+
call: ToolCallInput;
|
|
110
|
+
/** An always-fresh call must not claim a provider idempotency identity. */
|
|
111
|
+
providerOperationKey: null;
|
|
112
|
+
/** Receiptless means structurally absent, not a nullable lease. */
|
|
113
|
+
receipt?: never;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type ReceiptBackedToolCallDispatch = {
|
|
117
|
+
call: ToolCallInput;
|
|
118
|
+
providerOperationKey: string;
|
|
119
|
+
receipt: ToolCallReceiptLease;
|
|
120
|
+
};
|
|
121
|
+
|
|
108
122
|
/** Direct and map execution are Adapter choices, never separate public jobs. */
|
|
109
123
|
export type ToolCallDispatcher = {
|
|
110
|
-
dispatch(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
providerOperationKey: string | null;
|
|
114
|
-
/** Null means this is a receiptless, always-fresh physical call. */
|
|
115
|
-
receipt: ToolCallReceiptLease | null;
|
|
116
|
-
}): Promise<ToolExecuteResult>;
|
|
124
|
+
dispatch(
|
|
125
|
+
input: AlwaysFreshToolCallDispatch | ReceiptBackedToolCallDispatch,
|
|
126
|
+
): Promise<ToolExecuteResult>;
|
|
117
127
|
};
|
|
118
128
|
|
|
119
129
|
export type ToolCallDependencies = {
|
|
@@ -7,9 +7,11 @@ import type { ToolExecutionErrorSchemaVersion } from './tool-execution-error';
|
|
|
7
7
|
import type { PlayDataset, PlayDatasetInput, PlayDatasetRow } from './dataset';
|
|
8
8
|
|
|
9
9
|
export const LEGACY_PLAY_AUTHORING_CONTRACT_EDITION = 1 as const;
|
|
10
|
-
export const PLAY_AUTHORING_CONTRACT_EDITION =
|
|
10
|
+
export const PLAY_AUTHORING_CONTRACT_EDITION = 5 as const;
|
|
11
11
|
export const PLAY_AUTHORING_INPUT_SCHEMA_SNAPSHOT_EDITION = 3 as const;
|
|
12
|
-
export const SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS = [
|
|
12
|
+
export const SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS = [
|
|
13
|
+
1, 2, 3, 4, 5,
|
|
14
|
+
] as const;
|
|
13
15
|
|
|
14
16
|
export type PlayAuthoringContractEdition =
|
|
15
17
|
(typeof SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS)[number];
|
|
@@ -49,6 +51,47 @@ export const PLAY_AUTHORING_CONTRACT_CHANGELOG = [
|
|
|
49
51
|
newWritesEnd: null,
|
|
50
52
|
readerRemoval: null,
|
|
51
53
|
},
|
|
54
|
+
{
|
|
55
|
+
edition: 5,
|
|
56
|
+
changed:
|
|
57
|
+
'ctx.fetch throws a typed, redacted CtxFetchHttpError for non-2xx responses. Editions 1–4 continue to return the response record for every HTTP status.',
|
|
58
|
+
compatibilityOwner: 'Plays Runtime',
|
|
59
|
+
newWritesEnd: null,
|
|
60
|
+
readerRemoval: null,
|
|
61
|
+
},
|
|
62
|
+
] as const;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Customer-visible runtime capabilities that are not expressible as one
|
|
66
|
+
* `ctx.*` signature. The generated authoring reference renders this inventory
|
|
67
|
+
* directly; add a row here alongside any new supported runtime global or
|
|
68
|
+
* execution-boundary guarantee.
|
|
69
|
+
*/
|
|
70
|
+
export const PLAY_AUTHORING_RUNTIME_CAPABILITIES = [
|
|
71
|
+
{
|
|
72
|
+
capability: 'Durable external I/O',
|
|
73
|
+
surface: '`ctx.fetch`, `ctx.tools.execute`, `ctx.step`, `ctx.runPlay`',
|
|
74
|
+
contract:
|
|
75
|
+
'Use a `ctx.*` primitive for external work. Each primitive owns durable receipt identity and replay; raw I/O in an authored handler does not.',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
capability: 'Web Crypto',
|
|
79
|
+
surface: '`crypto.subtle`',
|
|
80
|
+
contract:
|
|
81
|
+
'WebCrypto is available for standards-based signing, verification, encryption, and key import. Keep private material in `ctx.secrets`; `docs-examples/sdk-v2/github-app-jwt.play.ts` signs an RS256 GitHub App JWT and uses `staleAfterSeconds: 0` for its time-varying auth exchange.',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
capability: 'Workspace secrets',
|
|
85
|
+
surface: '`ctx.secrets.get`, `.bearer`, `.header`',
|
|
86
|
+
contract:
|
|
87
|
+
'Declare the secret at the Play boundary, read it only at runtime, and never return or log it. Secret-bearing HTTP requests require HTTPS.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
capability: 'Freshness',
|
|
91
|
+
surface: '`staleAfterSeconds` on durable calls',
|
|
92
|
+
contract:
|
|
93
|
+
'This is call-receipt freshness: omitted/null reuses forever, zero always executes, and a positive integer is a TTL in seconds. It never changes dataset or request identity.',
|
|
94
|
+
},
|
|
52
95
|
] as const;
|
|
53
96
|
|
|
54
97
|
export const PLAY_AUTHORING_CONTRACT_ISSUE_CODES = [
|
|
@@ -78,6 +121,7 @@ export const PLAY_AUTHORING_CONTRACT_ISSUE_CODES = [
|
|
|
78
121
|
'play_authoring_fetch_secret_requires_tls',
|
|
79
122
|
'play_authoring_fetch_idempotency_required',
|
|
80
123
|
'play_authoring_fetch_key_reused_in_loop',
|
|
124
|
+
'play_authoring_fetch_http_error_branch',
|
|
81
125
|
'play_authoring_binding_invalid',
|
|
82
126
|
'play_authoring_input_schema_unresolved',
|
|
83
127
|
'tool_response_raw_access',
|
|
@@ -842,12 +886,24 @@ export type PlayAuthoringRuntimeStepOptions = {
|
|
|
842
886
|
staleAfterSeconds?: DurableCallStaleAfterSeconds;
|
|
843
887
|
};
|
|
844
888
|
|
|
889
|
+
/**
|
|
890
|
+
* Durable freshness for one `ctx.fetch` call. The key identifies the request;
|
|
891
|
+
* `staleAfterSeconds` controls when that completed request may be reused across
|
|
892
|
+
* Play runs. Omit it (or pass `null`) to reuse indefinitely, pass `0` to
|
|
893
|
+
* execute on every new run, or pass a positive number of seconds for a TTL.
|
|
894
|
+
*
|
|
895
|
+
* Use this for polling or periodically refreshing one external resource. It
|
|
896
|
+
* does not change dataset row identity.
|
|
897
|
+
*
|
|
898
|
+
*/
|
|
845
899
|
export type PlayAuthoringFetchOptions = {
|
|
846
900
|
staleAfterSeconds?: DurableCallStaleAfterSeconds;
|
|
901
|
+
/** Run through Deepline's guarded outbound path without retaining a response receipt or checkpoint. Use this for short-lived credential exchanges or other response data that should stay in the running Play only. */
|
|
902
|
+
transient?: boolean;
|
|
847
903
|
};
|
|
848
904
|
|
|
849
905
|
/**
|
|
850
|
-
*
|
|
906
|
+
* A durable response record, not a WHATWG `Response`: read the already-materialized `bodyText` and `json` properties; do not call `.json()`, `.text()`, or `.body`.
|
|
851
907
|
*
|
|
852
908
|
* @sdkReference runtime 175 PlayFetchResponse
|
|
853
909
|
*/
|
|
@@ -870,6 +926,55 @@ export type PlayAuthoringFetchResponse = {
|
|
|
870
926
|
json: unknown | null;
|
|
871
927
|
};
|
|
872
928
|
|
|
929
|
+
/**
|
|
930
|
+
* Edition 5+ `ctx.fetch` error for a non-2xx response. Its full readable body is secret-redacted; editions 1–4 retain `PlayFetchResponse { ok: false }`.
|
|
931
|
+
*
|
|
932
|
+
* @sdkReference runtime 178 CtxFetchHttpError
|
|
933
|
+
*/
|
|
934
|
+
export class CtxFetchHttpError extends Error {
|
|
935
|
+
/**
|
|
936
|
+
* Play source and the runtime are separately bundled. Recognize the stable
|
|
937
|
+
* public error code so `instanceof` works across that boundary as well.
|
|
938
|
+
*/
|
|
939
|
+
static [Symbol.hasInstance](value: unknown): boolean {
|
|
940
|
+
return (
|
|
941
|
+
value !== null &&
|
|
942
|
+
typeof value === 'object' &&
|
|
943
|
+
(value as { code?: unknown }).code === 'CTX_FETCH_HTTP_ERROR'
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/** Stable machine-readable HTTP-failure code. */
|
|
948
|
+
readonly code = 'CTX_FETCH_HTTP_ERROR' as const;
|
|
949
|
+
/** Upstream HTTP status. */
|
|
950
|
+
readonly status: number;
|
|
951
|
+
/** Upstream HTTP status text. */
|
|
952
|
+
readonly statusText: string;
|
|
953
|
+
/** Final response URL after redirects. */
|
|
954
|
+
readonly url: string;
|
|
955
|
+
/** Secret-redacted response headers. */
|
|
956
|
+
readonly headers: Record<string, string>;
|
|
957
|
+
/** Complete secret-redacted response body. */
|
|
958
|
+
readonly bodyText: string;
|
|
959
|
+
/** Eagerly parsed secret-redacted JSON, or null. */
|
|
960
|
+
readonly json: unknown | null;
|
|
961
|
+
|
|
962
|
+
/** Build the error from the durable response record. */
|
|
963
|
+
constructor(readonly response: PlayAuthoringFetchResponse) {
|
|
964
|
+
const body = response.bodyText || 'empty response body';
|
|
965
|
+
super(
|
|
966
|
+
`ctx.fetch(${response.url}) returned HTTP ${response.status}${response.statusText ? ` ${response.statusText}` : ''}: ${body}`,
|
|
967
|
+
);
|
|
968
|
+
this.name = 'CtxFetchHttpError';
|
|
969
|
+
this.status = response.status;
|
|
970
|
+
this.statusText = response.statusText;
|
|
971
|
+
this.url = response.url;
|
|
972
|
+
this.headers = response.headers;
|
|
973
|
+
this.bodyText = response.bodyText;
|
|
974
|
+
this.json = response.json;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
|
|
873
978
|
export type PlayAuthoringCustomerDbQueryOptions = {
|
|
874
979
|
maxRows?: number;
|
|
875
980
|
timeoutMs?: number;
|
|
@@ -1008,7 +1113,8 @@ export interface PlayAuthoringRuntimeContext {
|
|
|
1008
1113
|
): Promise<T>;
|
|
1009
1114
|
|
|
1010
1115
|
/**
|
|
1011
|
-
* Execute a durable
|
|
1116
|
+
* Execute a guarded HTTP request. By default it is durable and replay-safe; `staleAfterSeconds` governs only that completed call receipt, never dataset/request identity. Pass `{ transient: true }` for short-lived credential exchanges or other response data that must not be retained in a receipt or checkpoint. Edition 5+ throws `CtxFetchHttpError` for non-2xx; catch it only when the Play intentionally recovers, otherwise let it fail the Play. Editions 1–4 retain their previous response projections.
|
|
1117
|
+
*
|
|
1012
1118
|
* @sdkReference runtime 170 ctx.fetch(key, url, init)
|
|
1013
1119
|
*/
|
|
1014
1120
|
fetch(
|
|
@@ -2541,8 +2647,9 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
2541
2647
|
"export type PlayCallExecution = 'inline';",
|
|
2542
2648
|
`export type PlayCallOptions = { description: ${cloudReferenceType('ctx.runPlay.options.description')}; execution?: ${cloudReferenceType('ctx.runPlay.options.execution')}; timeoutMs?: ${cloudReferenceType('ctx.runPlay.options.timeoutMs')} };`,
|
|
2543
2649
|
`export type RuntimeStepOptions = { semanticKey?: ${cloudReferenceType('ctx.step.semanticKey')}; staleAfterSeconds?: ${cloudReferenceType('ctx.step.staleAfterSeconds')} };`,
|
|
2544
|
-
`export type FetchOptions = { staleAfterSeconds?: ${cloudReferenceType('ctx.fetch.staleAfterSeconds')} };`,
|
|
2650
|
+
`export type FetchOptions = { staleAfterSeconds?: ${cloudReferenceType('ctx.fetch.staleAfterSeconds')}; transient?: boolean };`,
|
|
2545
2651
|
'export type PlayFetchResponse = { ok: boolean; status: number; statusText: string; url: string; headers: Record<string, string>; bodyText: string; json: unknown | null };',
|
|
2652
|
+
"export declare class CtxFetchHttpError extends Error { readonly code: 'CTX_FETCH_HTTP_ERROR'; readonly response: PlayFetchResponse; readonly status: number; readonly statusText: string; readonly url: string; readonly headers: Record<string, string>; readonly bodyText: string; readonly json: unknown | null; }",
|
|
2546
2653
|
'export type StepResolver<Row, Value> = (row: Row, ctx: DeeplinePlayRuntimeContext, index: number, previousCell?: PreviousCell<Value>) => Value | Promise<Value>;',
|
|
2547
2654
|
'export type DatasetColumnRunInput<Row, Value> = { readonly row: Row; readonly ctx: DeeplinePlayRuntimeContext; readonly index: number; readonly previousCell?: PreviousCell<Value> };',
|
|
2548
2655
|
'export type DatasetColumnDefinition<Row, Value> = { readonly run: (input: DatasetColumnRunInput<Row, Value>) => Value | Promise<Value>; readonly runIf?: (row: Row, index: number) => boolean | Promise<boolean> };',
|
|
@@ -15,6 +15,8 @@ export type SafeFetchOptions = {
|
|
|
15
15
|
sensitiveHeaders?: Iterable<string>;
|
|
16
16
|
/** Drop every caller-supplied header when a redirect changes origin. */
|
|
17
17
|
stripHeadersOnCrossOriginRedirect?: boolean;
|
|
18
|
+
/** Headers the trusted runtime may add after caller headers are stripped. */
|
|
19
|
+
headersOnCrossOriginRedirect?: HeadersInit;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
22
|
function removeHeader(headers: Headers, name: string) {
|
|
@@ -32,6 +34,7 @@ function requestInitForRedirect(
|
|
|
32
34
|
status: number,
|
|
33
35
|
sensitiveHeaders: Iterable<string>,
|
|
34
36
|
stripHeadersOnCrossOriginRedirect: boolean,
|
|
37
|
+
headersOnCrossOriginRedirect: HeadersInit | undefined,
|
|
35
38
|
): RequestInit {
|
|
36
39
|
let headers = new Headers(init.headers);
|
|
37
40
|
let method = String(init.method ?? 'GET').toUpperCase();
|
|
@@ -57,7 +60,7 @@ function requestInitForRedirect(
|
|
|
57
60
|
// Callers that can construct credentials from plaintext secrets cannot
|
|
58
61
|
// reliably identify every transformed value. Do not forward any caller
|
|
59
62
|
// header across an origin boundary in that trust model.
|
|
60
|
-
headers = new Headers();
|
|
63
|
+
headers = new Headers(headersOnCrossOriginRedirect);
|
|
61
64
|
} else {
|
|
62
65
|
removeHeader(headers, 'authorization');
|
|
63
66
|
removeHeader(headers, 'cookie');
|
|
@@ -88,6 +91,7 @@ export async function safePublicFetch(
|
|
|
88
91
|
const sensitiveHeaders = options.sensitiveHeaders ?? [];
|
|
89
92
|
const stripHeadersOnCrossOriginRedirect =
|
|
90
93
|
options.stripHeadersOnCrossOriginRedirect === true;
|
|
94
|
+
const headersOnCrossOriginRedirect = options.headersOnCrossOriginRedirect;
|
|
91
95
|
let currentUrl = assertPublicHttpUrl(input);
|
|
92
96
|
let currentInit: RequestInit = {
|
|
93
97
|
...init,
|
|
@@ -135,6 +139,7 @@ export async function safePublicFetch(
|
|
|
135
139
|
response.status,
|
|
136
140
|
sensitiveHeaders,
|
|
137
141
|
stripHeadersOnCrossOriginRedirect,
|
|
142
|
+
headersOnCrossOriginRedirect,
|
|
138
143
|
);
|
|
139
144
|
currentUrl = nextUrl;
|
|
140
145
|
}
|