deepline 0.1.251 → 0.1.253
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/release.ts +5 -2
- package/dist/bundling-sources/sdk/src/types.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +79 -64
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +37 -35
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +20 -5
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +462 -29
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +44 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +7 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +98 -13
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +117 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +19 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constants.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +22 -0
- package/dist/cli/index.js +47 -23
- package/dist/cli/index.mjs +47 -23
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +10 -5
- package/dist/index.mjs +10 -5
- package/package.json +2 -2
|
@@ -113,8 +113,11 @@ export const SDK_RELEASE = {
|
|
|
113
113
|
// runtime intentionally no longer compiles at publish or launch time.
|
|
114
114
|
// 0.1.242 removes the retired Workers/ESM compiler, generated bundles, and
|
|
115
115
|
// deploy-time artifact migration. Play authoring now has one CJS contract.
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
// 0.1.252 hard-cuts the customer Monitor catalog to the two launched
|
|
117
|
+
// Deepline-native radars. Older clients must update before discovering,
|
|
118
|
+
// checking, or deploying an unlaunched monitor integration.
|
|
119
|
+
version: '0.1.253',
|
|
120
|
+
apiContract: '2026-07-native-monitor-launch-hard-cutover',
|
|
118
121
|
supportPolicy: {
|
|
119
122
|
minimumSupported: '0.1.53',
|
|
120
123
|
deprecatedBelow: '0.1.219',
|
|
@@ -551,6 +551,8 @@ export interface PlayRunPackage {
|
|
|
551
551
|
durationMs?: number | null;
|
|
552
552
|
error?: string;
|
|
553
553
|
};
|
|
554
|
+
/** Bounded customer-safe warnings about output projection or availability. */
|
|
555
|
+
warnings?: string[];
|
|
554
556
|
/** Step-level summaries emitted by the runtime. */
|
|
555
557
|
steps: Array<Record<string, unknown>>;
|
|
556
558
|
/** Named output summaries, including dataset handles and scalar outputs. */
|
|
@@ -8282,9 +8282,9 @@ export class PlayContextImpl {
|
|
|
8282
8282
|
const url = `${this.#options.baseUrl}/api/v2/integrations/${encodeURIComponent(toolId)}/execute`;
|
|
8283
8283
|
const timeoutMs = resolveToolRuntimeTimeoutMs(toolId, options?.timeoutMs);
|
|
8284
8284
|
|
|
8285
|
-
//
|
|
8286
|
-
//
|
|
8287
|
-
//
|
|
8285
|
+
// Hold one logical tool slot and charge one logical tool call for this
|
|
8286
|
+
// execution. Per-provider rate admission is intentionally deferred until
|
|
8287
|
+
// each physical fetch is ready to leave this process.
|
|
8288
8288
|
const admissionStartedAt = Date.now();
|
|
8289
8289
|
const toolSlot = await this.resourceGovernor.acquireTool({
|
|
8290
8290
|
orgId: this.#options.orgId ?? null,
|
|
@@ -8408,7 +8408,6 @@ export class PlayContextImpl {
|
|
|
8408
8408
|
`[perf] tool call id=${toolId} phase=before_provider_ownership elapsed_ms=${Date.now() - ownershipStartedAt}`,
|
|
8409
8409
|
);
|
|
8410
8410
|
}
|
|
8411
|
-
providerCallStartedAt = Date.now();
|
|
8412
8411
|
const heartbeatIntervalMs = hasReceiptHeartbeat
|
|
8413
8412
|
? runtimeLeaseHeartbeatIntervalFromExpiry({
|
|
8414
8413
|
leaseExpiresAt: options?.receiptLeaseExpiresAt,
|
|
@@ -8438,71 +8437,87 @@ export class PlayContextImpl {
|
|
|
8438
8437
|
: null;
|
|
8439
8438
|
receiptHeartbeatSupervisor?.start();
|
|
8440
8439
|
try {
|
|
8440
|
+
// Complete all local/receipt preparation before taking the
|
|
8441
|
+
// shared provider permit. Once admitted, the next awaited work
|
|
8442
|
+
// is the fetch itself, so independently delayed runners cannot
|
|
8443
|
+
// compress real provider arrivals after their tickets.
|
|
8444
|
+
const protectionHeaders = await this.vercelProtectionHeaders();
|
|
8445
|
+
const providerPermit =
|
|
8446
|
+
await this.resourceGovernor.acquireProviderPermit({
|
|
8447
|
+
toolId,
|
|
8448
|
+
signal: abortController?.signal,
|
|
8449
|
+
});
|
|
8441
8450
|
const integrationFetchStartedAt = Date.now();
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
}
|
|
8457
|
-
: {}),
|
|
8458
|
-
...(await this.vercelProtectionHeaders()),
|
|
8459
|
-
},
|
|
8460
|
-
body: JSON.stringify({
|
|
8461
|
-
payload: input,
|
|
8462
|
-
metadata: {
|
|
8463
|
-
parent_run_id: this.#options.runId,
|
|
8464
|
-
...(durableCallReceiptKey
|
|
8465
|
-
? {
|
|
8466
|
-
durable_call_receipt_key: durableCallReceiptKey,
|
|
8467
|
-
...(executionAuthScopeDigest
|
|
8468
|
-
? {
|
|
8469
|
-
execution_auth_scope_digest:
|
|
8470
|
-
executionAuthScopeDigest,
|
|
8471
|
-
}
|
|
8472
|
-
: {}),
|
|
8473
|
-
}
|
|
8474
|
-
: {}),
|
|
8475
|
-
...(options?.customerDbDataset
|
|
8451
|
+
providerCallStartedAt = integrationFetchStartedAt;
|
|
8452
|
+
try {
|
|
8453
|
+
response = await fetch(url, {
|
|
8454
|
+
method: 'POST',
|
|
8455
|
+
signal: abortController?.signal,
|
|
8456
|
+
headers: {
|
|
8457
|
+
'Content-Type': 'application/json',
|
|
8458
|
+
Authorization: `Bearer ${this.#options.executorToken}`,
|
|
8459
|
+
[EXECUTE_RESPONSE_CONTRACT_HEADER]:
|
|
8460
|
+
V2_EXECUTE_RESPONSE_CONTRACT,
|
|
8461
|
+
[EXECUTE_RESPONSE_INTENT_HEADER]: 'dataset',
|
|
8462
|
+
[EXECUTE_TOOL_METADATA_HEADER]: 'true',
|
|
8463
|
+
'x-deepline-request-id': deeplineRequestId,
|
|
8464
|
+
...(providerIdempotencyKey
|
|
8476
8465
|
? {
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
offset: options.customerDbDataset.offset,
|
|
8480
|
-
page_size: options.customerDbDataset.pageSize,
|
|
8481
|
-
total_rows: options.customerDbDataset.totalRows,
|
|
8482
|
-
},
|
|
8483
|
-
...(isCustomerDbDatasetTool(toolId)
|
|
8484
|
-
? {
|
|
8485
|
-
customer_db_dataset: {
|
|
8486
|
-
limit: options.customerDbDataset.limit,
|
|
8487
|
-
offset: options.customerDbDataset.offset,
|
|
8488
|
-
page_size:
|
|
8489
|
-
options.customerDbDataset.pageSize,
|
|
8490
|
-
total_rows:
|
|
8491
|
-
options.customerDbDataset.totalRows,
|
|
8492
|
-
},
|
|
8493
|
-
}
|
|
8494
|
-
: {}),
|
|
8466
|
+
'x-deepline-idempotency-key':
|
|
8467
|
+
providerIdempotencyKey,
|
|
8495
8468
|
}
|
|
8496
8469
|
: {}),
|
|
8497
|
-
...
|
|
8498
|
-
? { provider_idempotency_key: providerIdempotencyKey }
|
|
8499
|
-
: {}),
|
|
8470
|
+
...protectionHeaders,
|
|
8500
8471
|
},
|
|
8501
|
-
|
|
8502
|
-
|
|
8503
|
-
: {
|
|
8504
|
-
|
|
8505
|
-
|
|
8472
|
+
body: JSON.stringify({
|
|
8473
|
+
payload: input,
|
|
8474
|
+
metadata: {
|
|
8475
|
+
parent_run_id: this.#options.runId,
|
|
8476
|
+
...(durableCallReceiptKey
|
|
8477
|
+
? {
|
|
8478
|
+
durable_call_receipt_key: durableCallReceiptKey,
|
|
8479
|
+
...(executionAuthScopeDigest
|
|
8480
|
+
? {
|
|
8481
|
+
execution_auth_scope_digest:
|
|
8482
|
+
executionAuthScopeDigest,
|
|
8483
|
+
}
|
|
8484
|
+
: {}),
|
|
8485
|
+
}
|
|
8486
|
+
: {}),
|
|
8487
|
+
...(options?.customerDbDataset
|
|
8488
|
+
? {
|
|
8489
|
+
query_result_dataset: {
|
|
8490
|
+
limit: options.customerDbDataset.limit,
|
|
8491
|
+
offset: options.customerDbDataset.offset,
|
|
8492
|
+
page_size: options.customerDbDataset.pageSize,
|
|
8493
|
+
total_rows: options.customerDbDataset.totalRows,
|
|
8494
|
+
},
|
|
8495
|
+
...(isCustomerDbDatasetTool(toolId)
|
|
8496
|
+
? {
|
|
8497
|
+
customer_db_dataset: {
|
|
8498
|
+
limit: options.customerDbDataset.limit,
|
|
8499
|
+
offset: options.customerDbDataset.offset,
|
|
8500
|
+
page_size:
|
|
8501
|
+
options.customerDbDataset.pageSize,
|
|
8502
|
+
total_rows:
|
|
8503
|
+
options.customerDbDataset.totalRows,
|
|
8504
|
+
},
|
|
8505
|
+
}
|
|
8506
|
+
: {}),
|
|
8507
|
+
}
|
|
8508
|
+
: {}),
|
|
8509
|
+
...(providerIdempotencyKey
|
|
8510
|
+
? { provider_idempotency_key: providerIdempotencyKey }
|
|
8511
|
+
: {}),
|
|
8512
|
+
},
|
|
8513
|
+
...(this.#options.integrationMode
|
|
8514
|
+
? { integration_mode: this.#options.integrationMode }
|
|
8515
|
+
: {}),
|
|
8516
|
+
}),
|
|
8517
|
+
});
|
|
8518
|
+
} finally {
|
|
8519
|
+
providerPermit.release();
|
|
8520
|
+
}
|
|
8506
8521
|
if (runtimeReceiptReadTraceEnabled) {
|
|
8507
8522
|
this.log(
|
|
8508
8523
|
`[perf] tool call id=${toolId} phase=integration_fetch_headers elapsed_ms=${Date.now() - integrationFetchStartedAt} status=${response.status}`,
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* at once" policy. See ADR 0007 + CONTEXT.md.
|
|
7
7
|
*
|
|
8
8
|
* Surface (small, by design):
|
|
9
|
-
* - acquireRowSlot / acquireToolSlot →
|
|
9
|
+
* - acquireRowSlot / acquireToolSlot → local execution leases
|
|
10
|
+
* - acquireProviderPermit → per-attempt provider admission
|
|
10
11
|
* - chargeBudget → throws on breach
|
|
11
12
|
* - forkInlineChild → inline recursion scope
|
|
12
13
|
* - resolveRowConcurrency / reportProviderBackpressure / snapshot
|
|
@@ -102,15 +103,24 @@ export interface PlayExecutionGovernor {
|
|
|
102
103
|
/** Block until a map-row slot is free. */
|
|
103
104
|
acquireRowSlot(opts?: { signal?: AbortSignal }): Promise<WorkLease>;
|
|
104
105
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* lease. Parked future permits never consume scarce execution slots.
|
|
106
|
+
* Acquire the local execution slot and charge one logical tool-call budget.
|
|
107
|
+
* Provider pacing deliberately happens separately at the HTTP-attempt edge.
|
|
108
108
|
*/
|
|
109
109
|
acquireToolSlot(
|
|
110
110
|
toolId: string,
|
|
111
111
|
opts?: { signal?: AbortSignal },
|
|
112
112
|
): Promise<WorkLease>;
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Block until one physical provider HTTP attempt is admitted under the
|
|
116
|
+
* provider's shared rate/concurrency rules. Call this immediately before the
|
|
117
|
+
* outbound request and again for every retry.
|
|
118
|
+
*/
|
|
119
|
+
acquireProviderPermit(
|
|
120
|
+
toolId: string,
|
|
121
|
+
opts?: { signal?: AbortSignal },
|
|
122
|
+
): Promise<WorkLease>;
|
|
123
|
+
|
|
114
124
|
/**
|
|
115
125
|
* Suggested batch parallelism for a tool: the provider's own rate hints
|
|
116
126
|
* tightened to the policy's suggested ceiling. No hints → the fallback.
|
|
@@ -373,44 +383,34 @@ export function createPlayExecutionGovernor(
|
|
|
373
383
|
policy,
|
|
374
384
|
|
|
375
385
|
acquireRowSlot: (opts) => rowSlots.acquire(opts?.signal),
|
|
376
|
-
async acquireToolSlot(
|
|
377
|
-
|
|
378
|
-
//
|
|
386
|
+
async acquireToolSlot(_toolId, opts) {
|
|
387
|
+
const slot = await toolSlots.acquire(opts?.signal);
|
|
388
|
+
// Charge the logical call only after its local execution slot is held, so
|
|
389
|
+
// a failed/aborted slot acquisition never consumes the budget. The
|
|
390
|
+
// physical provider admission is intentionally deferred to
|
|
391
|
+
// acquireProviderPermit at the outbound HTTP edge.
|
|
392
|
+
try {
|
|
393
|
+
await chargeBudget('toolCall');
|
|
394
|
+
} catch (error) {
|
|
395
|
+
slot.release();
|
|
396
|
+
throw error;
|
|
397
|
+
}
|
|
398
|
+
return slot;
|
|
399
|
+
},
|
|
400
|
+
|
|
401
|
+
async acquireProviderPermit(toolId, opts) {
|
|
402
|
+
// The rate ticket is an admission for a physical outbound attempt, not a
|
|
403
|
+
// reservation made while receipt ownership, headers, or local tool slots
|
|
404
|
+
// may still be waiting. This is what keeps real provider arrivals inside
|
|
405
|
+
// the declared rolling window under concurrent runners.
|
|
379
406
|
const pacing = await resolveAdaptivePacing(toolId);
|
|
380
407
|
const rateScope = await resolveScope(toolId, pacing.provider);
|
|
381
|
-
|
|
408
|
+
return await input.rateState.acquire({
|
|
382
409
|
bucketId: rateScope[0],
|
|
383
410
|
rateScopeToken: rateScope[1],
|
|
384
411
|
rules: pacing.rules,
|
|
385
412
|
signal: opts?.signal,
|
|
386
413
|
});
|
|
387
|
-
// 2. Acquire a scarce execution slot only after the provider permit is
|
|
388
|
-
// due. If the slot wait aborts, refund any concurrency-bearing permit.
|
|
389
|
-
let slot: WorkLease;
|
|
390
|
-
try {
|
|
391
|
-
slot = await toolSlots.acquire(opts?.signal);
|
|
392
|
-
} catch (error) {
|
|
393
|
-
permit.release();
|
|
394
|
-
throw error;
|
|
395
|
-
}
|
|
396
|
-
// 3. Charge the budget only once the call is actually cleared to run, so a
|
|
397
|
-
// failed/aborted acquisition never permanently consumes tool budget.
|
|
398
|
-
try {
|
|
399
|
-
await chargeBudget('toolCall');
|
|
400
|
-
} catch (error) {
|
|
401
|
-
permit.release();
|
|
402
|
-
slot.release();
|
|
403
|
-
throw error;
|
|
404
|
-
}
|
|
405
|
-
let released = false;
|
|
406
|
-
return {
|
|
407
|
-
release: () => {
|
|
408
|
-
if (released) return;
|
|
409
|
-
released = true;
|
|
410
|
-
permit.release();
|
|
411
|
-
slot.release();
|
|
412
|
-
},
|
|
413
|
-
};
|
|
414
414
|
},
|
|
415
415
|
|
|
416
416
|
async suggestedParallelism(toolId, fallback) {
|
|
@@ -541,6 +541,8 @@ function createInlineChildGovernor(
|
|
|
541
541
|
policy: root.policy,
|
|
542
542
|
acquireRowSlot: (opts) => root.acquireRowSlot(opts),
|
|
543
543
|
acquireToolSlot: (toolId, opts) => root.acquireToolSlot(toolId, opts),
|
|
544
|
+
acquireProviderPermit: (toolId, opts) =>
|
|
545
|
+
root.acquireProviderPermit(toolId, opts),
|
|
544
546
|
suggestedParallelism: (toolId, fallback) =>
|
|
545
547
|
root.suggestedParallelism(toolId, fallback),
|
|
546
548
|
chargeBudget: (kind, amount) => root.chargeBudget(kind, amount),
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { createSecretRedactionContext } from './secret-redaction';
|
|
2
2
|
import {
|
|
3
3
|
assertRuntimeReceiptOutputWithinLimit,
|
|
4
|
-
|
|
4
|
+
jsonByteLengthUpTo,
|
|
5
|
+
LEDGER_TERMINAL_RESULT_MAX_BYTES,
|
|
5
6
|
} from './output-size-limits';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// This is an inline Convex event limit, not the durable scheduler-terminal
|
|
9
|
+
// envelope. A full terminal return is projected to an out-of-line reference
|
|
10
|
+
// before it reaches here.
|
|
11
|
+
export const MAX_LEDGER_RESULT_PAYLOAD_BYTES = LEDGER_TERMINAL_RESULT_MAX_BYTES;
|
|
8
12
|
export const MAX_LEDGER_LOG_LINES_PER_EVENT = 500;
|
|
9
13
|
export const MAX_LEDGER_LOG_LINE_LENGTH = 2_000;
|
|
10
14
|
|
|
@@ -17,8 +21,11 @@ export function redactLedgerString(value: unknown): string | null {
|
|
|
17
21
|
|
|
18
22
|
export function sanitizeLedgerPayload(value: unknown): unknown {
|
|
19
23
|
if (value === undefined) return undefined;
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
const measurement = jsonByteLengthUpTo(
|
|
25
|
+
value,
|
|
26
|
+
MAX_LEDGER_RESULT_PAYLOAD_BYTES,
|
|
27
|
+
);
|
|
28
|
+
if (measurement.exceeded) {
|
|
22
29
|
throw new Error('run event result payload is too large');
|
|
23
30
|
}
|
|
24
31
|
return ledgerIngressRedactor.redact(value);
|
|
@@ -26,11 +33,19 @@ export function sanitizeLedgerPayload(value: unknown): unknown {
|
|
|
26
33
|
|
|
27
34
|
/** Secret-redact a receipt payload without coupling its 10 MiB cell limit to the ledger. */
|
|
28
35
|
export function sanitizeRuntimeReceiptPayload(value: unknown): unknown {
|
|
36
|
+
// Reject an obviously oversized source before doing redaction work, then
|
|
37
|
+
// validate the exact value that will be persisted. Redaction normally shrinks
|
|
38
|
+
// credential-shaped values but can expand short matched strings.
|
|
29
39
|
assertRuntimeReceiptOutputWithinLimit({
|
|
30
40
|
output: value,
|
|
31
41
|
path: 'runtime receipt output',
|
|
32
42
|
});
|
|
33
|
-
|
|
43
|
+
const redacted = ledgerIngressRedactor.redact(value);
|
|
44
|
+
assertRuntimeReceiptOutputWithinLimit({
|
|
45
|
+
output: redacted,
|
|
46
|
+
path: 'runtime receipt output after secret redaction',
|
|
47
|
+
});
|
|
48
|
+
return redacted;
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
export function sanitizeLedgerLogLines(value: unknown): string[] {
|