deepline 0.1.235 → 0.1.237
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/apps/play-runner-workers/src/entry.ts +3 -0
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +18 -1
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +88 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +23 -6
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +15 -0
- package/dist/cli/index.js +113 -93
- package/dist/cli/index.mjs +122 -96
- package/dist/index.js +3 -2
- package/dist/index.mjs +3 -2
- package/package.json +1 -1
|
@@ -3828,6 +3828,9 @@ function createWorkerPacingResolver(req: RunRequest): WorkerPacingResolver {
|
|
|
3828
3828
|
if (builtin) {
|
|
3829
3829
|
return Promise.resolve({
|
|
3830
3830
|
...builtin,
|
|
3831
|
+
// Builtin pacing has no per-org coordinator rate scope. Keep the
|
|
3832
|
+
// required resolver contract explicit so the Governor treats it as
|
|
3833
|
+
// intentionally unscoped rather than receiving a malformed policy.
|
|
3831
3834
|
r: null,
|
|
3832
3835
|
retrySafeTransientHttp: false,
|
|
3833
3836
|
});
|
|
@@ -108,10 +108,10 @@ export const SDK_RELEASE = {
|
|
|
108
108
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
109
109
|
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
110
110
|
// automatically without blocking their current command.
|
|
111
|
-
version: '0.1.
|
|
111
|
+
version: '0.1.237',
|
|
112
112
|
apiContract: '2026-06-dataset-handle-results-hard-cutover',
|
|
113
113
|
supportPolicy: {
|
|
114
|
-
latest: '0.1.
|
|
114
|
+
latest: '0.1.237',
|
|
115
115
|
minimumSupported: '0.1.53',
|
|
116
116
|
deprecatedBelow: '0.1.219',
|
|
117
117
|
commandMinimumSupported: [
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
isPlayRowExecutionSuspendedError,
|
|
13
13
|
} from './suspension';
|
|
14
14
|
import { getToolHttpErrorReceiptFailureKind } from './tool-http-errors';
|
|
15
|
+
import { isLegacyRepairableWorkReceiptError } from './work-receipt-state-machine';
|
|
15
16
|
import type { WorkReceiptFailureKind } from './work-receipts';
|
|
16
17
|
import {
|
|
17
18
|
PLAY_RUNTIME_WORK_RECEIPT_LEASE_TTL_MS,
|
|
@@ -63,8 +64,24 @@ export function runtimeReceiptFailureKindForError(
|
|
|
63
64
|
const toolFailureKind = getToolHttpErrorReceiptFailureKind(error);
|
|
64
65
|
if (toolFailureKind) return toolFailureKind;
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
if (
|
|
68
|
+
isPlayExecutionSuspendedError(error) ||
|
|
67
69
|
isPlayRowExecutionSuspendedError(error)
|
|
70
|
+
) {
|
|
71
|
+
return 'repairable';
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Transport/timeout failures never reach a `ToolHttpError` (there was no HTTP
|
|
75
|
+
// response to classify), so they would otherwise default to `terminal` and
|
|
76
|
+
// poison the durable receipt: the next run would replay the cached transport
|
|
77
|
+
// failure instead of re-executing. These are transient infra failures, so
|
|
78
|
+
// mark them repairable. `isLegacyRepairableWorkReceiptError` already encodes
|
|
79
|
+
// the exact transient-string contract (5xx, "transport failed calling",
|
|
80
|
+
// "runtime api call timed out") while excluding hard billing caps, and the
|
|
81
|
+
// read-side SQL predicate uses the same rules, so write and read stay aligned.
|
|
82
|
+
const message =
|
|
83
|
+
error instanceof Error ? error.message : error != null ? String(error) : '';
|
|
84
|
+
return isLegacyRepairableWorkReceiptError(message)
|
|
68
85
|
? 'repairable'
|
|
69
86
|
: 'terminal';
|
|
70
87
|
}
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
const encoder = typeof TextEncoder === 'undefined' ? null : new TextEncoder();
|
|
2
2
|
|
|
3
3
|
export const TERMINAL_RUN_RESULT_MAX_BYTES = 2_500_000;
|
|
4
|
+
/**
|
|
5
|
+
* Convex hard-caps a single document at 1 MiB and rejects nesting deeper than
|
|
6
|
+
* 16 levels. A run-ledger `run.completed` / `run.failed` event embeds its
|
|
7
|
+
* `result` inside one `playRunEvents` document, so the ledger-bound result must
|
|
8
|
+
* stay comfortably under that ceiling (the event also carries seq/type/
|
|
9
|
+
* timestamps and the surrounding doc envelope). Keep well below 1 MiB so no
|
|
10
|
+
* single event can wedge the append mutation with `Value is too large (>1MiB)`.
|
|
11
|
+
* Historically a failed run embedded its full `PlayRunnerResult` — including a
|
|
12
|
+
* `checkpoint` whose `completedToolBatches[*].toolResponse.raw` held megabytes
|
|
13
|
+
* of provider payload — which is durable in scheduler Postgres and never read
|
|
14
|
+
* back from Convex, yet deterministically wedged the append.
|
|
15
|
+
*/
|
|
16
|
+
export const LEDGER_TERMINAL_RESULT_MAX_BYTES = 768 * 1024;
|
|
4
17
|
export const CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
5
18
|
export const CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
6
19
|
/** Inline Postgres receipt contract: one serialized output is at most 10 MiB. */
|
|
@@ -86,6 +99,81 @@ export function persistableTerminalRunResult(value: unknown): unknown {
|
|
|
86
99
|
return valueWithinJsonByteLimit(value, TERMINAL_RUN_RESULT_MAX_BYTES);
|
|
87
100
|
}
|
|
88
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Replay-only keys a terminal `PlayRunnerResult` carries for the scheduler
|
|
104
|
+
* (Postgres) data plane. These are NEVER read back from the Convex run ledger:
|
|
105
|
+
* resume rehydrates the checkpoint/suspension from scheduler Postgres
|
|
106
|
+
* (`work_runs.checkpoint_json` / `suspension_json`), and customer reads use the
|
|
107
|
+
* run's `output`. Embedding them in a `playRunEvents` document only bloats the
|
|
108
|
+
* write and can exceed Convex's 1 MiB / 16-level document limits.
|
|
109
|
+
*/
|
|
110
|
+
const LEDGER_STRIPPED_TERMINAL_RESULT_KEYS = [
|
|
111
|
+
'checkpoint',
|
|
112
|
+
'suspension',
|
|
113
|
+
] as const;
|
|
114
|
+
|
|
115
|
+
/** A tiny reference descriptor left in place of a dropped over-limit result. */
|
|
116
|
+
export type LedgerTerminalResultRef = {
|
|
117
|
+
__kind: 'deepline.ledger_terminal_result_ref.v1';
|
|
118
|
+
/** Where the full terminal result is durably stored. */
|
|
119
|
+
store: 'scheduler_postgres';
|
|
120
|
+
/** Column on the scheduler `work_runs` row that holds the full result. */
|
|
121
|
+
key: 'terminal_result_json';
|
|
122
|
+
/** Serialized byte size of the result that was elided from the ledger. */
|
|
123
|
+
bytes: number;
|
|
124
|
+
reason: 'terminal_result_exceeds_ledger_limit';
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
128
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Shape a terminal run result for the Convex run ledger. Control-plane only:
|
|
133
|
+
*
|
|
134
|
+
* 1. Strip replay-only keys ({@link LEDGER_STRIPPED_TERMINAL_RESULT_KEYS}) from
|
|
135
|
+
* the top-level result object — the scheduler Postgres data plane owns them.
|
|
136
|
+
* 2. If what remains still exceeds {@link LEDGER_TERMINAL_RESULT_MAX_BYTES},
|
|
137
|
+
* replace the whole result with a {@link LedgerTerminalResultRef} pointing at
|
|
138
|
+
* the durable scheduler copy, so the ledger event stays small and the
|
|
139
|
+
* Convex append cannot wedge on an oversized/over-nested document.
|
|
140
|
+
*
|
|
141
|
+
* The full result (including its checkpoint) remains durable in scheduler
|
|
142
|
+
* Postgres regardless; this only governs what the ledger embeds.
|
|
143
|
+
*/
|
|
144
|
+
export function terminalRunResultForLedger(value: unknown): unknown {
|
|
145
|
+
if (value === undefined || value === null) {
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
let candidate = value;
|
|
149
|
+
if (isPlainObject(value)) {
|
|
150
|
+
const stripped: Record<string, unknown> = {};
|
|
151
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
152
|
+
if (
|
|
153
|
+
(LEDGER_STRIPPED_TERMINAL_RESULT_KEYS as readonly string[]).includes(
|
|
154
|
+
key,
|
|
155
|
+
)
|
|
156
|
+
) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
stripped[key] = entry;
|
|
160
|
+
}
|
|
161
|
+
candidate = stripped;
|
|
162
|
+
}
|
|
163
|
+
const bytes = jsonByteLength(candidate);
|
|
164
|
+
if (bytes <= LEDGER_TERMINAL_RESULT_MAX_BYTES) {
|
|
165
|
+
return candidate;
|
|
166
|
+
}
|
|
167
|
+
const ref: LedgerTerminalResultRef = {
|
|
168
|
+
__kind: 'deepline.ledger_terminal_result_ref.v1',
|
|
169
|
+
store: 'scheduler_postgres',
|
|
170
|
+
key: 'terminal_result_json',
|
|
171
|
+
bytes,
|
|
172
|
+
reason: 'terminal_result_exceeds_ledger_limit',
|
|
173
|
+
};
|
|
174
|
+
return ref;
|
|
175
|
+
}
|
|
176
|
+
|
|
89
177
|
export function assertCustomerOutputValueWithinLimit(input: {
|
|
90
178
|
value: unknown;
|
|
91
179
|
path: string;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { RECEIPT_STATUS_CODE } from './receipt-status';
|
|
2
2
|
import { workReceiptFailureKindCode } from './work-receipts';
|
|
3
3
|
|
|
4
|
+
// This predicate MUST stay behaviorally identical to
|
|
5
|
+
// `isLegacyRepairableWorkReceiptError` in ./work-receipt-state-machine.ts.
|
|
6
|
+
// Write-side classification and this read-side reclaim gate share one contract:
|
|
7
|
+
// a receipt is repairable if its failure_kind is repairable, OR it is a legacy
|
|
8
|
+
// terminal receipt whose error text proves a transient-class failure (5xx,
|
|
9
|
+
// transport, timeout, or a transient billing-plane outage). The
|
|
10
|
+
// billing_unavailable clause recovers the poisoned backlog written during a
|
|
11
|
+
// billing-plane incident, where transient 503s were formatted with the hard
|
|
12
|
+
// "billing cap" template — it is checked BEFORE the hard-billing exclusions so
|
|
13
|
+
// those receipts re-execute on the next run instead of replaying the failure.
|
|
4
14
|
export function workReceiptRepairableFailurePredicateSql(
|
|
5
15
|
receiptTable: string,
|
|
6
16
|
): string {
|
|
@@ -9,13 +19,20 @@ export function workReceiptRepairableFailurePredicateSql(
|
|
|
9
19
|
OR (
|
|
10
20
|
${receiptTable}.failure_kind = ${workReceiptFailureKindCode('terminal')}::smallint
|
|
11
21
|
AND ${receiptTable}.error IS NOT NULL
|
|
12
|
-
AND lower(${receiptTable}.error) NOT LIKE '%billing cap%'
|
|
13
|
-
AND lower(${receiptTable}.error) NOT LIKE '%insufficient credits%'
|
|
14
|
-
AND lower(${receiptTable}.error) NOT LIKE '%monthly billing limit%'
|
|
15
22
|
AND (
|
|
16
|
-
${receiptTable}.error
|
|
17
|
-
OR lower(${receiptTable}.error) LIKE '%
|
|
18
|
-
OR lower(${receiptTable}.error) LIKE '%
|
|
23
|
+
lower(${receiptTable}.error) LIKE '%billing_unavailable%'
|
|
24
|
+
OR lower(${receiptTable}.error) LIKE '%billing is temporarily unavailable%'
|
|
25
|
+
OR lower(${receiptTable}.error) LIKE '%billing temporarily unavailable%'
|
|
26
|
+
OR (
|
|
27
|
+
lower(${receiptTable}.error) NOT LIKE '%billing cap%'
|
|
28
|
+
AND lower(${receiptTable}.error) NOT LIKE '%insufficient credits%'
|
|
29
|
+
AND lower(${receiptTable}.error) NOT LIKE '%monthly billing limit%'
|
|
30
|
+
AND (
|
|
31
|
+
${receiptTable}.error ~* '(^|[^0-9])5[0-9]{2}([^0-9]|$)'
|
|
32
|
+
OR lower(${receiptTable}.error) LIKE '%transport failed calling%'
|
|
33
|
+
OR lower(${receiptTable}.error) LIKE '%runtime api call timed out%'
|
|
34
|
+
)
|
|
35
|
+
)
|
|
19
36
|
)
|
|
20
37
|
)
|
|
21
38
|
)`;
|
|
@@ -52,10 +52,40 @@ function isInsufficientCreditsBilling(
|
|
|
52
52
|
return billing?.kind === 'insufficient_credits';
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* A transient failure of the Deepline billing PLANE (Convex outage, OCC
|
|
57
|
+
* exhaustion) surfaced as HTTP 503 `BILLING_UNAVAILABLE` with `retryable: true`
|
|
58
|
+
* and `failure_description` stating no credits were charged. This is NOT a hard
|
|
59
|
+
* credit/cap denial: a funded org is temporarily blocked because our billing
|
|
60
|
+
* store hiccuped, so it must be repairable on the next run rather than cached as
|
|
61
|
+
* a terminal failure. See `billingUnavailableResponse` in
|
|
62
|
+
* src/lib/integrations/execute-billing.ts. This class is the exact incident
|
|
63
|
+
* poison closed by issues #2561/#2706: without this carve-out a billing-plane
|
|
64
|
+
* outage classifies every affected tool call as `hard_billing_error` ->
|
|
65
|
+
* `terminal` and the next run replays the cached failure instead of retrying.
|
|
66
|
+
*/
|
|
67
|
+
export function isTransientBillingFailurePayload(
|
|
68
|
+
payload: Record<string, unknown> | null,
|
|
69
|
+
): boolean {
|
|
70
|
+
if (!payload) return false;
|
|
71
|
+
const code = String(payload.code ?? payload.error_code ?? '').toUpperCase();
|
|
72
|
+
if (code === 'BILLING_UNAVAILABLE') return true;
|
|
73
|
+
// Any billing-origin payload that explicitly declares itself retryable is a
|
|
74
|
+
// billing-infra hiccup, never a hard denial (denials are never retryable).
|
|
75
|
+
const category = String(
|
|
76
|
+
payload.error_category ?? payload.errorCategory ?? '',
|
|
77
|
+
).toLowerCase();
|
|
78
|
+
return category === 'billing' && payload.retryable === true;
|
|
79
|
+
}
|
|
80
|
+
|
|
55
81
|
function isHardBillingFailurePayload(
|
|
56
82
|
payload: Record<string, unknown> | null,
|
|
57
83
|
): payload is Record<string, unknown> {
|
|
58
84
|
if (!payload) return false;
|
|
85
|
+
// Billing-plane outages (503 BILLING_UNAVAILABLE) are transient infra, not
|
|
86
|
+
// hard denials. Never let them reach the terminal, run-fatal hard-billing
|
|
87
|
+
// path — they must stay repairable so the next run retries.
|
|
88
|
+
if (isTransientBillingFailurePayload(payload)) return false;
|
|
59
89
|
const category = String(
|
|
60
90
|
payload.error_category ?? payload.errorCategory ?? '',
|
|
61
91
|
).toLowerCase();
|
|
@@ -100,6 +130,10 @@ function normalizeHardBillingPayload(
|
|
|
100
130
|
function receiptFailureKindForToolErrorPayload(
|
|
101
131
|
payload: Record<string, unknown> | null,
|
|
102
132
|
): WorkReceiptFailureKind {
|
|
133
|
+
// A transient billing-plane outage (503 BILLING_UNAVAILABLE) charged nothing
|
|
134
|
+
// and is explicitly retryable. It must be repairable so the next run
|
|
135
|
+
// re-executes instead of replaying the cached billing-infra failure.
|
|
136
|
+
if (isTransientBillingFailurePayload(payload)) return 'repairable';
|
|
103
137
|
const code = getStringField(payload, 'code')?.toUpperCase();
|
|
104
138
|
// A credential connection can be added or replaced between play runs. Keep
|
|
105
139
|
// the failure terminal within its owning run, but let a later run reclaim
|
|
@@ -22,6 +22,21 @@ export function isLegacyRepairableWorkReceiptError(
|
|
|
22
22
|
): boolean {
|
|
23
23
|
const message = error?.trim().toLowerCase() ?? '';
|
|
24
24
|
if (!message) return false;
|
|
25
|
+
// Transient billing-PLANE outages (503 BILLING_UNAVAILABLE) were historically
|
|
26
|
+
// formatted with the hard "billing cap exceeded" template (see
|
|
27
|
+
// formatHardBillingFailureMessage), so the receipts written during a
|
|
28
|
+
// billing-plane incident carry a "billing cap" string even though they are
|
|
29
|
+
// retryable infra failures that charged nothing. Recognize them BEFORE the
|
|
30
|
+
// hard-billing exclusion below so the poisoned backlog re-executes on the next
|
|
31
|
+
// run instead of replaying the cached failure. Real hard denials never carry a
|
|
32
|
+
// BILLING_UNAVAILABLE code or "temporarily unavailable" text.
|
|
33
|
+
if (
|
|
34
|
+
message.includes('billing_unavailable') ||
|
|
35
|
+
message.includes('billing is temporarily unavailable') ||
|
|
36
|
+
message.includes('billing temporarily unavailable')
|
|
37
|
+
) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
25
40
|
if (
|
|
26
41
|
message.includes('billing cap') ||
|
|
27
42
|
message.includes('insufficient credits') ||
|
package/dist/cli/index.js
CHANGED
|
@@ -625,10 +625,10 @@ var SDK_RELEASE = {
|
|
|
625
625
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
626
626
|
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
627
627
|
// automatically without blocking their current command.
|
|
628
|
-
version: "0.1.
|
|
628
|
+
version: "0.1.237",
|
|
629
629
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
630
630
|
supportPolicy: {
|
|
631
|
-
latest: "0.1.
|
|
631
|
+
latest: "0.1.237",
|
|
632
632
|
minimumSupported: "0.1.53",
|
|
633
633
|
deprecatedBelow: "0.1.219",
|
|
634
634
|
commandMinimumSupported: [
|
|
@@ -1456,6 +1456,7 @@ function createSecretRedactionContext(initialValues = []) {
|
|
|
1456
1456
|
|
|
1457
1457
|
// ../shared_libs/play-runtime/output-size-limits.ts
|
|
1458
1458
|
var encoder = typeof TextEncoder === "undefined" ? null : new TextEncoder();
|
|
1459
|
+
var LEDGER_TERMINAL_RESULT_MAX_BYTES = 768 * 1024;
|
|
1459
1460
|
var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
1460
1461
|
var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
1461
1462
|
var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -12080,6 +12081,9 @@ function getRunIdFromLiveEvent(event) {
|
|
|
12080
12081
|
const packageRunId = getRunRecordFromPackage(payload)?.id;
|
|
12081
12082
|
return typeof packageRunId === "string" && packageRunId.trim() ? packageRunId : null;
|
|
12082
12083
|
}
|
|
12084
|
+
function eventConfirmsPlayRunLaunch(event) {
|
|
12085
|
+
return event.type === "play.run.status" && getEventPayload(event).launchConfirmed === true;
|
|
12086
|
+
}
|
|
12083
12087
|
function getStatusFromLiveEvent(event) {
|
|
12084
12088
|
if (event.type !== "play.run.status" && event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
|
|
12085
12089
|
return null;
|
|
@@ -12506,70 +12510,6 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
12506
12510
|
}
|
|
12507
12511
|
return null;
|
|
12508
12512
|
};
|
|
12509
|
-
const watchViaObserveTransport = async () => {
|
|
12510
|
-
const controller = new AbortController();
|
|
12511
|
-
let timedOut = false;
|
|
12512
|
-
const remaining = remainingWaitMs();
|
|
12513
|
-
const timeout = remaining === null ? null : setTimeout(
|
|
12514
|
-
() => {
|
|
12515
|
-
timedOut = true;
|
|
12516
|
-
controller.abort();
|
|
12517
|
-
},
|
|
12518
|
-
Math.max(1, remaining)
|
|
12519
|
-
);
|
|
12520
|
-
try {
|
|
12521
|
-
for await (const event of input2.client.observeRunEvents(
|
|
12522
|
-
input2.workflowId,
|
|
12523
|
-
{
|
|
12524
|
-
signal: controller.signal,
|
|
12525
|
-
fallback: "none",
|
|
12526
|
-
onNotice: input2.jsonOutput ? void 0 : (message) => input2.progress.writeLine(message)
|
|
12527
|
-
}
|
|
12528
|
-
)) {
|
|
12529
|
-
const terminal2 = await handleLiveEvent(event);
|
|
12530
|
-
if (terminal2) {
|
|
12531
|
-
return terminal2;
|
|
12532
|
-
}
|
|
12533
|
-
}
|
|
12534
|
-
} finally {
|
|
12535
|
-
if (timeout) {
|
|
12536
|
-
clearTimeout(timeout);
|
|
12537
|
-
}
|
|
12538
|
-
}
|
|
12539
|
-
const terminal = await fetchTerminalStatus();
|
|
12540
|
-
if (terminal) {
|
|
12541
|
-
return terminal;
|
|
12542
|
-
}
|
|
12543
|
-
if (timedOut) {
|
|
12544
|
-
assertPlayWaitNotTimedOut({ ...input2, lastPhase });
|
|
12545
|
-
}
|
|
12546
|
-
throw new DeeplineError(
|
|
12547
|
-
`Run observation for ${input2.workflowId} ended before a terminal status.`,
|
|
12548
|
-
void 0,
|
|
12549
|
-
"PLAY_LIVE_STREAM_ENDED",
|
|
12550
|
-
{ runId: input2.workflowId, workflowId: input2.workflowId }
|
|
12551
|
-
);
|
|
12552
|
-
};
|
|
12553
|
-
try {
|
|
12554
|
-
return await watchViaObserveTransport();
|
|
12555
|
-
} catch (error) {
|
|
12556
|
-
if (!(error instanceof RunObserveTransportUnavailableError)) {
|
|
12557
|
-
throw error;
|
|
12558
|
-
}
|
|
12559
|
-
if (!input2.jsonOutput) {
|
|
12560
|
-
input2.progress.writeLine(
|
|
12561
|
-
`[play watch] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
|
|
12562
|
-
);
|
|
12563
|
-
}
|
|
12564
|
-
recordCliTrace({
|
|
12565
|
-
phase: "cli.play_observe_transport_fallback",
|
|
12566
|
-
ms: Date.now() - input2.startedAt,
|
|
12567
|
-
ok: true,
|
|
12568
|
-
playName: input2.playName,
|
|
12569
|
-
workflowId: input2.workflowId,
|
|
12570
|
-
reason: error.reason
|
|
12571
|
-
});
|
|
12572
|
-
}
|
|
12573
12513
|
const streamOneWindow = async () => {
|
|
12574
12514
|
const controller = new AbortController();
|
|
12575
12515
|
let timedOut = false;
|
|
@@ -12702,6 +12642,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12702
12642
|
let launchedRevisionId = input2.request.revisionId?.trim() || null;
|
|
12703
12643
|
let eventCount = 0;
|
|
12704
12644
|
let firstRunIdMs = null;
|
|
12645
|
+
let launchConfirmed = false;
|
|
12705
12646
|
let lastPhase = null;
|
|
12706
12647
|
const timeout = input2.waitTimeoutMs === null ? null : setTimeout(
|
|
12707
12648
|
() => {
|
|
@@ -12752,6 +12693,9 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12752
12693
|
input2.onRunStarted?.(eventRunId);
|
|
12753
12694
|
}
|
|
12754
12695
|
}
|
|
12696
|
+
if (eventConfirmsPlayRunLaunch(event) && eventRunId === lastKnownWorkflowId) {
|
|
12697
|
+
launchConfirmed = true;
|
|
12698
|
+
}
|
|
12755
12699
|
const workflowId = lastKnownWorkflowId || "pending";
|
|
12756
12700
|
if (workflowId !== "pending" && !emittedDashboardUrl) {
|
|
12757
12701
|
if (!input2.jsonOutput) {
|
|
@@ -12828,6 +12772,16 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12828
12772
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
12829
12773
|
if (finalStatus) {
|
|
12830
12774
|
lastKnownWorkflowId ||= finalStatus.runId ?? "";
|
|
12775
|
+
if (finalStatus.status === "failed" && !finalStatus.runId) {
|
|
12776
|
+
return {
|
|
12777
|
+
...finalStatus,
|
|
12778
|
+
runId: "pending",
|
|
12779
|
+
name: input2.playName,
|
|
12780
|
+
playName: input2.playName,
|
|
12781
|
+
dashboardUrl,
|
|
12782
|
+
...launchedRevisionId ? { revisionId: launchedRevisionId } : {}
|
|
12783
|
+
};
|
|
12784
|
+
}
|
|
12831
12785
|
const canonicalTerminal = input2.request.profile === "absurd" ? await fetchKnownTerminalStatus() : {
|
|
12832
12786
|
...finalStatus,
|
|
12833
12787
|
dashboardUrl,
|
|
@@ -12859,6 +12813,34 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12859
12813
|
});
|
|
12860
12814
|
return canonicalTerminal;
|
|
12861
12815
|
}
|
|
12816
|
+
if (lastKnownWorkflowId && launchConfirmed) {
|
|
12817
|
+
if (timeout) {
|
|
12818
|
+
clearTimeout(timeout);
|
|
12819
|
+
}
|
|
12820
|
+
controller.abort();
|
|
12821
|
+
recordCliTrace({
|
|
12822
|
+
phase: "cli.play_start_stream_handoff_to_tail",
|
|
12823
|
+
ms: Date.now() - startedAt,
|
|
12824
|
+
ok: true,
|
|
12825
|
+
playName: input2.playName,
|
|
12826
|
+
workflowId: lastKnownWorkflowId,
|
|
12827
|
+
eventCount,
|
|
12828
|
+
firstRunIdMs,
|
|
12829
|
+
lastPhase
|
|
12830
|
+
});
|
|
12831
|
+
return waitForPlayCompletionByStream({
|
|
12832
|
+
client: input2.client,
|
|
12833
|
+
playName: input2.playName,
|
|
12834
|
+
workflowId: lastKnownWorkflowId,
|
|
12835
|
+
dashboardUrl,
|
|
12836
|
+
jsonOutput: input2.jsonOutput,
|
|
12837
|
+
emitLogs: input2.emitLogs,
|
|
12838
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
12839
|
+
startedAt,
|
|
12840
|
+
state,
|
|
12841
|
+
progress: input2.progress
|
|
12842
|
+
});
|
|
12843
|
+
}
|
|
12862
12844
|
}
|
|
12863
12845
|
} catch (error) {
|
|
12864
12846
|
if (timedOut) {
|
|
@@ -14031,7 +14013,7 @@ function playRunPackageTextLedgerIncomplete(pkg) {
|
|
|
14031
14013
|
}
|
|
14032
14014
|
async function resolvePlayRunOutputStatus(input2) {
|
|
14033
14015
|
const runId = input2.status.runId;
|
|
14034
|
-
if (!runId) {
|
|
14016
|
+
if (!runId || runId === "pending") {
|
|
14035
14017
|
return input2.status;
|
|
14036
14018
|
}
|
|
14037
14019
|
const streamedPackage = getPlayRunPackage(input2.status);
|
|
@@ -26381,7 +26363,9 @@ function printPlayLikeToolExecuteError(toolId, tool) {
|
|
|
26381
26363
|
console.error(playLikeToolExecuteErrorMessage(toolId, tool));
|
|
26382
26364
|
}
|
|
26383
26365
|
function registerToolsCommands(program) {
|
|
26384
|
-
const tools = program.command("tools").description(
|
|
26366
|
+
const tools = program.command("tools").description(
|
|
26367
|
+
"Search by intent or structured filters, describe, and execute atomic provider tools."
|
|
26368
|
+
).addHelpText(
|
|
26385
26369
|
"after",
|
|
26386
26370
|
`
|
|
26387
26371
|
Concepts:
|
|
@@ -26420,30 +26404,34 @@ Examples:
|
|
|
26420
26404
|
...options.json ? ["--json"] : []
|
|
26421
26405
|
]);
|
|
26422
26406
|
});
|
|
26423
|
-
const addToolSearchCommand = (command) => command.description(
|
|
26407
|
+
const addToolSearchCommand = (command) => command.description(
|
|
26408
|
+
"Search available tools by intent query or structured filters."
|
|
26409
|
+
).addHelpText(
|
|
26424
26410
|
"after",
|
|
26425
26411
|
`
|
|
26426
26412
|
Notes:
|
|
26427
26413
|
Ranked discovery for atomic provider/API operations. Results include tool ids
|
|
26428
26414
|
that can be passed to deepline tools describe or deepline tools execute.
|
|
26415
|
+
Provide a query, or omit it only when --categories and/or --search_terms is
|
|
26416
|
+
supplied. Providing neither is a usage error. Both filters accept
|
|
26417
|
+
comma-separated values. Use a provider name in the query; --prefix is not a
|
|
26418
|
+
supported option.
|
|
26429
26419
|
The grep alias is the same ranked retrieval surface with a more literal name
|
|
26430
26420
|
for agents that are filtering a registry rather than choosing a workflow.
|
|
26431
26421
|
|
|
26432
26422
|
Examples:
|
|
26433
26423
|
deepline tools search email
|
|
26424
|
+
deepline tools search --categories company_search --search_terms "investors,funding"
|
|
26434
26425
|
deepline tools grep "company enrichment" --categories enrichment --json
|
|
26435
26426
|
deepline tools search verifier --search-mode v2 --json
|
|
26436
26427
|
`
|
|
26437
26428
|
).option(
|
|
26438
26429
|
"--categories <categories>",
|
|
26439
|
-
"Comma-separated categories
|
|
26430
|
+
"Comma-separated categories; may be used without a query"
|
|
26440
26431
|
).option(
|
|
26441
26432
|
"--search_terms <terms>",
|
|
26442
|
-
"
|
|
26443
|
-
).option(
|
|
26444
|
-
"--search-terms <terms>",
|
|
26445
|
-
"Structured search terms for ranked search"
|
|
26446
|
-
).option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
26433
|
+
"Comma-separated structured search terms; may be used without a query"
|
|
26434
|
+
).option("--search-terms <terms>", "Alias for --search_terms").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
26447
26435
|
process.exitCode = await searchTools(query, {
|
|
26448
26436
|
json: options.json,
|
|
26449
26437
|
compact: options.compact,
|
|
@@ -28390,6 +28378,9 @@ function sdkSkillsVersionPath(baseUrl) {
|
|
|
28390
28378
|
function legacySdkSkillsVersionPath(baseUrl) {
|
|
28391
28379
|
return (0, import_node_path18.join)((0, import_node_path18.dirname)(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
|
|
28392
28380
|
}
|
|
28381
|
+
function unavailableSkillsNoticePath(baseUrl) {
|
|
28382
|
+
return (0, import_node_path18.join)(sdkCliStateDirPath(baseUrl), "skills-sync-unavailable-version");
|
|
28383
|
+
}
|
|
28393
28384
|
function readSdkSkillsLocalVersion(baseUrl) {
|
|
28394
28385
|
const pluginVersion = readPluginSkillsVersion();
|
|
28395
28386
|
if (pluginVersion) return pluginVersion;
|
|
@@ -28407,6 +28398,29 @@ function writeLocalSkillsVersion(baseUrl, version) {
|
|
|
28407
28398
|
(0, import_node_fs16.writeFileSync)(path, `${version}
|
|
28408
28399
|
`, "utf-8");
|
|
28409
28400
|
}
|
|
28401
|
+
function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames) {
|
|
28402
|
+
const path = unavailableSkillsNoticePath(baseUrl);
|
|
28403
|
+
try {
|
|
28404
|
+
if ((0, import_node_fs16.existsSync)(path) && (0, import_node_fs16.readFileSync)(path, "utf-8").trim() === remoteVersion) {
|
|
28405
|
+
return;
|
|
28406
|
+
}
|
|
28407
|
+
(0, import_node_fs16.mkdirSync)((0, import_node_path18.dirname)(path), { recursive: true });
|
|
28408
|
+
(0, import_node_fs16.writeFileSync)(path, `${remoteVersion}
|
|
28409
|
+
`, "utf-8");
|
|
28410
|
+
} catch {
|
|
28411
|
+
}
|
|
28412
|
+
const manualCommand = `npx ${buildSkillsInstallArgs(baseUrl, skillNames).join(" ")}`;
|
|
28413
|
+
writeSdkSkillsStatusLine(
|
|
28414
|
+
`Deepline agent skills are out of date, but neither \`bunx\` nor \`npx\` is available. Install Node.js/npm or Bun, then run:
|
|
28415
|
+
${manualCommand}`
|
|
28416
|
+
);
|
|
28417
|
+
}
|
|
28418
|
+
function clearUnavailableSkillsNotice(baseUrl) {
|
|
28419
|
+
try {
|
|
28420
|
+
(0, import_node_fs16.unlinkSync)(unavailableSkillsNoticePath(baseUrl));
|
|
28421
|
+
} catch {
|
|
28422
|
+
}
|
|
28423
|
+
}
|
|
28410
28424
|
function sortedUniqueSkillNames(names) {
|
|
28411
28425
|
return [...new Set(names.map((name) => name.trim()).filter(Boolean))].sort(
|
|
28412
28426
|
(a, b) => a.localeCompare(b)
|
|
@@ -28482,24 +28496,24 @@ function shellQuote5(arg) {
|
|
|
28482
28496
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
28483
28497
|
}
|
|
28484
28498
|
function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
28485
|
-
const
|
|
28486
|
-
const npxInstall = {
|
|
28487
|
-
command: "npx",
|
|
28488
|
-
args: npxArgs,
|
|
28489
|
-
manualCommand: `npx ${npxArgs.map(shellQuote5).join(" ")}`
|
|
28490
|
-
};
|
|
28499
|
+
const commands = [];
|
|
28491
28500
|
if (hasCommand("bunx")) {
|
|
28492
28501
|
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
|
|
28493
|
-
|
|
28494
|
-
|
|
28495
|
-
|
|
28496
|
-
|
|
28497
|
-
|
|
28498
|
-
},
|
|
28499
|
-
npxInstall
|
|
28500
|
-
];
|
|
28502
|
+
commands.push({
|
|
28503
|
+
command: "bunx",
|
|
28504
|
+
args: bunxArgs,
|
|
28505
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote5).join(" ")}`
|
|
28506
|
+
});
|
|
28501
28507
|
}
|
|
28502
|
-
|
|
28508
|
+
if (hasCommand("npx")) {
|
|
28509
|
+
const npxArgs = buildSkillsInstallArgs(baseUrl, skillNames);
|
|
28510
|
+
commands.push({
|
|
28511
|
+
command: "npx",
|
|
28512
|
+
args: npxArgs,
|
|
28513
|
+
manualCommand: `npx ${npxArgs.map(shellQuote5).join(" ")}`
|
|
28514
|
+
});
|
|
28515
|
+
}
|
|
28516
|
+
return commands;
|
|
28503
28517
|
}
|
|
28504
28518
|
function runOneSkillsInstall(install) {
|
|
28505
28519
|
return new Promise((resolve14) => {
|
|
@@ -28532,9 +28546,9 @@ function runOneSkillsInstall(install) {
|
|
|
28532
28546
|
});
|
|
28533
28547
|
});
|
|
28534
28548
|
}
|
|
28535
|
-
async function runSkillsInstall(
|
|
28549
|
+
async function runSkillsInstall(installs) {
|
|
28536
28550
|
const failures = [];
|
|
28537
|
-
for (const install of
|
|
28551
|
+
for (const install of installs) {
|
|
28538
28552
|
const result = await runOneSkillsInstall(install);
|
|
28539
28553
|
if (result.ok) return true;
|
|
28540
28554
|
failures.push(result);
|
|
@@ -28624,11 +28638,17 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
|
28624
28638
|
remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
|
|
28625
28639
|
);
|
|
28626
28640
|
if (skillNames.length === 0) return;
|
|
28641
|
+
const installs = resolveSkillsInstallCommands(baseUrl, skillNames);
|
|
28642
|
+
if (installs.length === 0) {
|
|
28643
|
+
writeUnavailableSkillsNotice(baseUrl, update.remoteVersion, skillNames);
|
|
28644
|
+
return;
|
|
28645
|
+
}
|
|
28627
28646
|
writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
|
|
28628
|
-
const installed = await runSkillsInstall(
|
|
28647
|
+
const installed = await runSkillsInstall(installs);
|
|
28629
28648
|
if (!installed) return;
|
|
28630
28649
|
runLegacySkillsCleanup();
|
|
28631
28650
|
writeLocalSkillsVersion(baseUrl, update.remoteVersion);
|
|
28651
|
+
clearUnavailableSkillsNotice(baseUrl);
|
|
28632
28652
|
writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
|
|
28633
28653
|
}
|
|
28634
28654
|
|
package/dist/cli/index.mjs
CHANGED
|
@@ -610,10 +610,10 @@ var SDK_RELEASE = {
|
|
|
610
610
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
611
611
|
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
612
612
|
// automatically without blocking their current command.
|
|
613
|
-
version: "0.1.
|
|
613
|
+
version: "0.1.237",
|
|
614
614
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
615
615
|
supportPolicy: {
|
|
616
|
-
latest: "0.1.
|
|
616
|
+
latest: "0.1.237",
|
|
617
617
|
minimumSupported: "0.1.53",
|
|
618
618
|
deprecatedBelow: "0.1.219",
|
|
619
619
|
commandMinimumSupported: [
|
|
@@ -1441,6 +1441,7 @@ function createSecretRedactionContext(initialValues = []) {
|
|
|
1441
1441
|
|
|
1442
1442
|
// ../shared_libs/play-runtime/output-size-limits.ts
|
|
1443
1443
|
var encoder = typeof TextEncoder === "undefined" ? null : new TextEncoder();
|
|
1444
|
+
var LEDGER_TERMINAL_RESULT_MAX_BYTES = 768 * 1024;
|
|
1444
1445
|
var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
1445
1446
|
var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
1446
1447
|
var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -12109,6 +12110,9 @@ function getRunIdFromLiveEvent(event) {
|
|
|
12109
12110
|
const packageRunId = getRunRecordFromPackage(payload)?.id;
|
|
12110
12111
|
return typeof packageRunId === "string" && packageRunId.trim() ? packageRunId : null;
|
|
12111
12112
|
}
|
|
12113
|
+
function eventConfirmsPlayRunLaunch(event) {
|
|
12114
|
+
return event.type === "play.run.status" && getEventPayload(event).launchConfirmed === true;
|
|
12115
|
+
}
|
|
12112
12116
|
function getStatusFromLiveEvent(event) {
|
|
12113
12117
|
if (event.type !== "play.run.status" && event.type !== "play.run.snapshot" && event.type !== "play.run.final_status") {
|
|
12114
12118
|
return null;
|
|
@@ -12535,70 +12539,6 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
12535
12539
|
}
|
|
12536
12540
|
return null;
|
|
12537
12541
|
};
|
|
12538
|
-
const watchViaObserveTransport = async () => {
|
|
12539
|
-
const controller = new AbortController();
|
|
12540
|
-
let timedOut = false;
|
|
12541
|
-
const remaining = remainingWaitMs();
|
|
12542
|
-
const timeout = remaining === null ? null : setTimeout(
|
|
12543
|
-
() => {
|
|
12544
|
-
timedOut = true;
|
|
12545
|
-
controller.abort();
|
|
12546
|
-
},
|
|
12547
|
-
Math.max(1, remaining)
|
|
12548
|
-
);
|
|
12549
|
-
try {
|
|
12550
|
-
for await (const event of input2.client.observeRunEvents(
|
|
12551
|
-
input2.workflowId,
|
|
12552
|
-
{
|
|
12553
|
-
signal: controller.signal,
|
|
12554
|
-
fallback: "none",
|
|
12555
|
-
onNotice: input2.jsonOutput ? void 0 : (message) => input2.progress.writeLine(message)
|
|
12556
|
-
}
|
|
12557
|
-
)) {
|
|
12558
|
-
const terminal2 = await handleLiveEvent(event);
|
|
12559
|
-
if (terminal2) {
|
|
12560
|
-
return terminal2;
|
|
12561
|
-
}
|
|
12562
|
-
}
|
|
12563
|
-
} finally {
|
|
12564
|
-
if (timeout) {
|
|
12565
|
-
clearTimeout(timeout);
|
|
12566
|
-
}
|
|
12567
|
-
}
|
|
12568
|
-
const terminal = await fetchTerminalStatus();
|
|
12569
|
-
if (terminal) {
|
|
12570
|
-
return terminal;
|
|
12571
|
-
}
|
|
12572
|
-
if (timedOut) {
|
|
12573
|
-
assertPlayWaitNotTimedOut({ ...input2, lastPhase });
|
|
12574
|
-
}
|
|
12575
|
-
throw new DeeplineError(
|
|
12576
|
-
`Run observation for ${input2.workflowId} ended before a terminal status.`,
|
|
12577
|
-
void 0,
|
|
12578
|
-
"PLAY_LIVE_STREAM_ENDED",
|
|
12579
|
-
{ runId: input2.workflowId, workflowId: input2.workflowId }
|
|
12580
|
-
);
|
|
12581
|
-
};
|
|
12582
|
-
try {
|
|
12583
|
-
return await watchViaObserveTransport();
|
|
12584
|
-
} catch (error) {
|
|
12585
|
-
if (!(error instanceof RunObserveTransportUnavailableError)) {
|
|
12586
|
-
throw error;
|
|
12587
|
-
}
|
|
12588
|
-
if (!input2.jsonOutput) {
|
|
12589
|
-
input2.progress.writeLine(
|
|
12590
|
-
`[play watch] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
|
|
12591
|
-
);
|
|
12592
|
-
}
|
|
12593
|
-
recordCliTrace({
|
|
12594
|
-
phase: "cli.play_observe_transport_fallback",
|
|
12595
|
-
ms: Date.now() - input2.startedAt,
|
|
12596
|
-
ok: true,
|
|
12597
|
-
playName: input2.playName,
|
|
12598
|
-
workflowId: input2.workflowId,
|
|
12599
|
-
reason: error.reason
|
|
12600
|
-
});
|
|
12601
|
-
}
|
|
12602
12542
|
const streamOneWindow = async () => {
|
|
12603
12543
|
const controller = new AbortController();
|
|
12604
12544
|
let timedOut = false;
|
|
@@ -12731,6 +12671,7 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12731
12671
|
let launchedRevisionId = input2.request.revisionId?.trim() || null;
|
|
12732
12672
|
let eventCount = 0;
|
|
12733
12673
|
let firstRunIdMs = null;
|
|
12674
|
+
let launchConfirmed = false;
|
|
12734
12675
|
let lastPhase = null;
|
|
12735
12676
|
const timeout = input2.waitTimeoutMs === null ? null : setTimeout(
|
|
12736
12677
|
() => {
|
|
@@ -12781,6 +12722,9 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12781
12722
|
input2.onRunStarted?.(eventRunId);
|
|
12782
12723
|
}
|
|
12783
12724
|
}
|
|
12725
|
+
if (eventConfirmsPlayRunLaunch(event) && eventRunId === lastKnownWorkflowId) {
|
|
12726
|
+
launchConfirmed = true;
|
|
12727
|
+
}
|
|
12784
12728
|
const workflowId = lastKnownWorkflowId || "pending";
|
|
12785
12729
|
if (workflowId !== "pending" && !emittedDashboardUrl) {
|
|
12786
12730
|
if (!input2.jsonOutput) {
|
|
@@ -12857,6 +12801,16 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12857
12801
|
const finalStatus = getFinalStatusFromLiveEvent(event);
|
|
12858
12802
|
if (finalStatus) {
|
|
12859
12803
|
lastKnownWorkflowId ||= finalStatus.runId ?? "";
|
|
12804
|
+
if (finalStatus.status === "failed" && !finalStatus.runId) {
|
|
12805
|
+
return {
|
|
12806
|
+
...finalStatus,
|
|
12807
|
+
runId: "pending",
|
|
12808
|
+
name: input2.playName,
|
|
12809
|
+
playName: input2.playName,
|
|
12810
|
+
dashboardUrl,
|
|
12811
|
+
...launchedRevisionId ? { revisionId: launchedRevisionId } : {}
|
|
12812
|
+
};
|
|
12813
|
+
}
|
|
12860
12814
|
const canonicalTerminal = input2.request.profile === "absurd" ? await fetchKnownTerminalStatus() : {
|
|
12861
12815
|
...finalStatus,
|
|
12862
12816
|
dashboardUrl,
|
|
@@ -12888,6 +12842,34 @@ async function startAndWaitForPlayCompletionByStreamOnce(input2) {
|
|
|
12888
12842
|
});
|
|
12889
12843
|
return canonicalTerminal;
|
|
12890
12844
|
}
|
|
12845
|
+
if (lastKnownWorkflowId && launchConfirmed) {
|
|
12846
|
+
if (timeout) {
|
|
12847
|
+
clearTimeout(timeout);
|
|
12848
|
+
}
|
|
12849
|
+
controller.abort();
|
|
12850
|
+
recordCliTrace({
|
|
12851
|
+
phase: "cli.play_start_stream_handoff_to_tail",
|
|
12852
|
+
ms: Date.now() - startedAt,
|
|
12853
|
+
ok: true,
|
|
12854
|
+
playName: input2.playName,
|
|
12855
|
+
workflowId: lastKnownWorkflowId,
|
|
12856
|
+
eventCount,
|
|
12857
|
+
firstRunIdMs,
|
|
12858
|
+
lastPhase
|
|
12859
|
+
});
|
|
12860
|
+
return waitForPlayCompletionByStream({
|
|
12861
|
+
client: input2.client,
|
|
12862
|
+
playName: input2.playName,
|
|
12863
|
+
workflowId: lastKnownWorkflowId,
|
|
12864
|
+
dashboardUrl,
|
|
12865
|
+
jsonOutput: input2.jsonOutput,
|
|
12866
|
+
emitLogs: input2.emitLogs,
|
|
12867
|
+
waitTimeoutMs: input2.waitTimeoutMs,
|
|
12868
|
+
startedAt,
|
|
12869
|
+
state,
|
|
12870
|
+
progress: input2.progress
|
|
12871
|
+
});
|
|
12872
|
+
}
|
|
12891
12873
|
}
|
|
12892
12874
|
} catch (error) {
|
|
12893
12875
|
if (timedOut) {
|
|
@@ -14060,7 +14042,7 @@ function playRunPackageTextLedgerIncomplete(pkg) {
|
|
|
14060
14042
|
}
|
|
14061
14043
|
async function resolvePlayRunOutputStatus(input2) {
|
|
14062
14044
|
const runId = input2.status.runId;
|
|
14063
|
-
if (!runId) {
|
|
14045
|
+
if (!runId || runId === "pending") {
|
|
14064
14046
|
return input2.status;
|
|
14065
14047
|
}
|
|
14066
14048
|
const streamedPackage = getPlayRunPackage(input2.status);
|
|
@@ -26429,7 +26411,9 @@ function printPlayLikeToolExecuteError(toolId, tool) {
|
|
|
26429
26411
|
console.error(playLikeToolExecuteErrorMessage(toolId, tool));
|
|
26430
26412
|
}
|
|
26431
26413
|
function registerToolsCommands(program) {
|
|
26432
|
-
const tools = program.command("tools").description(
|
|
26414
|
+
const tools = program.command("tools").description(
|
|
26415
|
+
"Search by intent or structured filters, describe, and execute atomic provider tools."
|
|
26416
|
+
).addHelpText(
|
|
26433
26417
|
"after",
|
|
26434
26418
|
`
|
|
26435
26419
|
Concepts:
|
|
@@ -26468,30 +26452,34 @@ Examples:
|
|
|
26468
26452
|
...options.json ? ["--json"] : []
|
|
26469
26453
|
]);
|
|
26470
26454
|
});
|
|
26471
|
-
const addToolSearchCommand = (command) => command.description(
|
|
26455
|
+
const addToolSearchCommand = (command) => command.description(
|
|
26456
|
+
"Search available tools by intent query or structured filters."
|
|
26457
|
+
).addHelpText(
|
|
26472
26458
|
"after",
|
|
26473
26459
|
`
|
|
26474
26460
|
Notes:
|
|
26475
26461
|
Ranked discovery for atomic provider/API operations. Results include tool ids
|
|
26476
26462
|
that can be passed to deepline tools describe or deepline tools execute.
|
|
26463
|
+
Provide a query, or omit it only when --categories and/or --search_terms is
|
|
26464
|
+
supplied. Providing neither is a usage error. Both filters accept
|
|
26465
|
+
comma-separated values. Use a provider name in the query; --prefix is not a
|
|
26466
|
+
supported option.
|
|
26477
26467
|
The grep alias is the same ranked retrieval surface with a more literal name
|
|
26478
26468
|
for agents that are filtering a registry rather than choosing a workflow.
|
|
26479
26469
|
|
|
26480
26470
|
Examples:
|
|
26481
26471
|
deepline tools search email
|
|
26472
|
+
deepline tools search --categories company_search --search_terms "investors,funding"
|
|
26482
26473
|
deepline tools grep "company enrichment" --categories enrichment --json
|
|
26483
26474
|
deepline tools search verifier --search-mode v2 --json
|
|
26484
26475
|
`
|
|
26485
26476
|
).option(
|
|
26486
26477
|
"--categories <categories>",
|
|
26487
|
-
"Comma-separated categories
|
|
26478
|
+
"Comma-separated categories; may be used without a query"
|
|
26488
26479
|
).option(
|
|
26489
26480
|
"--search_terms <terms>",
|
|
26490
|
-
"
|
|
26491
|
-
).option(
|
|
26492
|
-
"--search-terms <terms>",
|
|
26493
|
-
"Structured search terms for ranked search"
|
|
26494
|
-
).option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
26481
|
+
"Comma-separated structured search terms; may be used without a query"
|
|
26482
|
+
).option("--search-terms <terms>", "Alias for --search_terms").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
|
|
26495
26483
|
process.exitCode = await searchTools(query, {
|
|
26496
26484
|
json: options.json,
|
|
26497
26485
|
compact: options.compact,
|
|
@@ -28299,7 +28287,7 @@ import {
|
|
|
28299
28287
|
readFileSync as readFileSync13,
|
|
28300
28288
|
renameSync,
|
|
28301
28289
|
rmSync as rmSync4,
|
|
28302
|
-
unlinkSync,
|
|
28290
|
+
unlinkSync as unlinkSync2,
|
|
28303
28291
|
writeFileSync as writeFileSync15
|
|
28304
28292
|
} from "fs";
|
|
28305
28293
|
import { homedir as homedir11 } from "os";
|
|
@@ -28307,7 +28295,13 @@ import { dirname as dirname13, isAbsolute as isAbsolute2, join as join14, relati
|
|
|
28307
28295
|
|
|
28308
28296
|
// src/cli/skills-sync.ts
|
|
28309
28297
|
import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
|
|
28310
|
-
import {
|
|
28298
|
+
import {
|
|
28299
|
+
existsSync as existsSync11,
|
|
28300
|
+
mkdirSync as mkdirSync9,
|
|
28301
|
+
readFileSync as readFileSync12,
|
|
28302
|
+
unlinkSync,
|
|
28303
|
+
writeFileSync as writeFileSync14
|
|
28304
|
+
} from "fs";
|
|
28311
28305
|
import { dirname as dirname12, join as join13 } from "path";
|
|
28312
28306
|
|
|
28313
28307
|
// ../shared_libs/cli/install-commands.json
|
|
@@ -28447,6 +28441,9 @@ function sdkSkillsVersionPath(baseUrl) {
|
|
|
28447
28441
|
function legacySdkSkillsVersionPath(baseUrl) {
|
|
28448
28442
|
return join13(dirname12(sdkCliStateDirPath(baseUrl)), "sdk-skills", ".version");
|
|
28449
28443
|
}
|
|
28444
|
+
function unavailableSkillsNoticePath(baseUrl) {
|
|
28445
|
+
return join13(sdkCliStateDirPath(baseUrl), "skills-sync-unavailable-version");
|
|
28446
|
+
}
|
|
28450
28447
|
function readSdkSkillsLocalVersion(baseUrl) {
|
|
28451
28448
|
const pluginVersion = readPluginSkillsVersion();
|
|
28452
28449
|
if (pluginVersion) return pluginVersion;
|
|
@@ -28464,6 +28461,29 @@ function writeLocalSkillsVersion(baseUrl, version) {
|
|
|
28464
28461
|
writeFileSync14(path, `${version}
|
|
28465
28462
|
`, "utf-8");
|
|
28466
28463
|
}
|
|
28464
|
+
function writeUnavailableSkillsNotice(baseUrl, remoteVersion, skillNames) {
|
|
28465
|
+
const path = unavailableSkillsNoticePath(baseUrl);
|
|
28466
|
+
try {
|
|
28467
|
+
if (existsSync11(path) && readFileSync12(path, "utf-8").trim() === remoteVersion) {
|
|
28468
|
+
return;
|
|
28469
|
+
}
|
|
28470
|
+
mkdirSync9(dirname12(path), { recursive: true });
|
|
28471
|
+
writeFileSync14(path, `${remoteVersion}
|
|
28472
|
+
`, "utf-8");
|
|
28473
|
+
} catch {
|
|
28474
|
+
}
|
|
28475
|
+
const manualCommand = `npx ${buildSkillsInstallArgs(baseUrl, skillNames).join(" ")}`;
|
|
28476
|
+
writeSdkSkillsStatusLine(
|
|
28477
|
+
`Deepline agent skills are out of date, but neither \`bunx\` nor \`npx\` is available. Install Node.js/npm or Bun, then run:
|
|
28478
|
+
${manualCommand}`
|
|
28479
|
+
);
|
|
28480
|
+
}
|
|
28481
|
+
function clearUnavailableSkillsNotice(baseUrl) {
|
|
28482
|
+
try {
|
|
28483
|
+
unlinkSync(unavailableSkillsNoticePath(baseUrl));
|
|
28484
|
+
} catch {
|
|
28485
|
+
}
|
|
28486
|
+
}
|
|
28467
28487
|
function sortedUniqueSkillNames(names) {
|
|
28468
28488
|
return [...new Set(names.map((name) => name.trim()).filter(Boolean))].sort(
|
|
28469
28489
|
(a, b) => a.localeCompare(b)
|
|
@@ -28539,24 +28559,24 @@ function shellQuote5(arg) {
|
|
|
28539
28559
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
28540
28560
|
}
|
|
28541
28561
|
function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
28542
|
-
const
|
|
28543
|
-
const npxInstall = {
|
|
28544
|
-
command: "npx",
|
|
28545
|
-
args: npxArgs,
|
|
28546
|
-
manualCommand: `npx ${npxArgs.map(shellQuote5).join(" ")}`
|
|
28547
|
-
};
|
|
28562
|
+
const commands = [];
|
|
28548
28563
|
if (hasCommand("bunx")) {
|
|
28549
28564
|
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
|
|
28553
|
-
|
|
28554
|
-
|
|
28555
|
-
},
|
|
28556
|
-
npxInstall
|
|
28557
|
-
];
|
|
28565
|
+
commands.push({
|
|
28566
|
+
command: "bunx",
|
|
28567
|
+
args: bunxArgs,
|
|
28568
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote5).join(" ")}`
|
|
28569
|
+
});
|
|
28558
28570
|
}
|
|
28559
|
-
|
|
28571
|
+
if (hasCommand("npx")) {
|
|
28572
|
+
const npxArgs = buildSkillsInstallArgs(baseUrl, skillNames);
|
|
28573
|
+
commands.push({
|
|
28574
|
+
command: "npx",
|
|
28575
|
+
args: npxArgs,
|
|
28576
|
+
manualCommand: `npx ${npxArgs.map(shellQuote5).join(" ")}`
|
|
28577
|
+
});
|
|
28578
|
+
}
|
|
28579
|
+
return commands;
|
|
28560
28580
|
}
|
|
28561
28581
|
function runOneSkillsInstall(install) {
|
|
28562
28582
|
return new Promise((resolve14) => {
|
|
@@ -28589,9 +28609,9 @@ function runOneSkillsInstall(install) {
|
|
|
28589
28609
|
});
|
|
28590
28610
|
});
|
|
28591
28611
|
}
|
|
28592
|
-
async function runSkillsInstall(
|
|
28612
|
+
async function runSkillsInstall(installs) {
|
|
28593
28613
|
const failures = [];
|
|
28594
|
-
for (const install of
|
|
28614
|
+
for (const install of installs) {
|
|
28595
28615
|
const result = await runOneSkillsInstall(install);
|
|
28596
28616
|
if (result.ok) return true;
|
|
28597
28617
|
failures.push(result);
|
|
@@ -28681,11 +28701,17 @@ async function syncSdkSkillsIfNeeded(baseUrl, options = {}) {
|
|
|
28681
28701
|
remoteSkillNames.length > 0 ? remoteSkillNames : DEFAULT_SDK_SKILL_NAMES
|
|
28682
28702
|
);
|
|
28683
28703
|
if (skillNames.length === 0) return;
|
|
28704
|
+
const installs = resolveSkillsInstallCommands(baseUrl, skillNames);
|
|
28705
|
+
if (installs.length === 0) {
|
|
28706
|
+
writeUnavailableSkillsNotice(baseUrl, update.remoteVersion, skillNames);
|
|
28707
|
+
return;
|
|
28708
|
+
}
|
|
28684
28709
|
writeSdkSkillsStatusLine("Deepline skills changed; syncing agent skills...");
|
|
28685
|
-
const installed = await runSkillsInstall(
|
|
28710
|
+
const installed = await runSkillsInstall(installs);
|
|
28686
28711
|
if (!installed) return;
|
|
28687
28712
|
runLegacySkillsCleanup();
|
|
28688
28713
|
writeLocalSkillsVersion(baseUrl, update.remoteVersion);
|
|
28714
|
+
clearUnavailableSkillsNotice(baseUrl);
|
|
28689
28715
|
writeSdkSkillsStatusLine("Deepline agent skills are up to date.");
|
|
28690
28716
|
}
|
|
28691
28717
|
|
|
@@ -28914,7 +28940,7 @@ function clearAutoUpdateFailure(plan) {
|
|
|
28914
28940
|
const path = autoUpdateFailurePath(plan);
|
|
28915
28941
|
if (!path) return;
|
|
28916
28942
|
try {
|
|
28917
|
-
|
|
28943
|
+
unlinkSync2(path);
|
|
28918
28944
|
} catch {
|
|
28919
28945
|
}
|
|
28920
28946
|
}
|
package/dist/index.js
CHANGED
|
@@ -424,10 +424,10 @@ var SDK_RELEASE = {
|
|
|
424
424
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
425
425
|
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
426
426
|
// automatically without blocking their current command.
|
|
427
|
-
version: "0.1.
|
|
427
|
+
version: "0.1.237",
|
|
428
428
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
429
429
|
supportPolicy: {
|
|
430
|
-
latest: "0.1.
|
|
430
|
+
latest: "0.1.237",
|
|
431
431
|
minimumSupported: "0.1.53",
|
|
432
432
|
deprecatedBelow: "0.1.219",
|
|
433
433
|
commandMinimumSupported: [
|
|
@@ -1255,6 +1255,7 @@ function createSecretRedactionContext(initialValues = []) {
|
|
|
1255
1255
|
|
|
1256
1256
|
// ../shared_libs/play-runtime/output-size-limits.ts
|
|
1257
1257
|
var encoder = typeof TextEncoder === "undefined" ? null : new TextEncoder();
|
|
1258
|
+
var LEDGER_TERMINAL_RESULT_MAX_BYTES = 768 * 1024;
|
|
1258
1259
|
var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
1259
1260
|
var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
1260
1261
|
var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
|
package/dist/index.mjs
CHANGED
|
@@ -354,10 +354,10 @@ var SDK_RELEASE = {
|
|
|
354
354
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
355
355
|
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
356
356
|
// automatically without blocking their current command.
|
|
357
|
-
version: "0.1.
|
|
357
|
+
version: "0.1.237",
|
|
358
358
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
359
359
|
supportPolicy: {
|
|
360
|
-
latest: "0.1.
|
|
360
|
+
latest: "0.1.237",
|
|
361
361
|
minimumSupported: "0.1.53",
|
|
362
362
|
deprecatedBelow: "0.1.219",
|
|
363
363
|
commandMinimumSupported: [
|
|
@@ -1185,6 +1185,7 @@ function createSecretRedactionContext(initialValues = []) {
|
|
|
1185
1185
|
|
|
1186
1186
|
// ../shared_libs/play-runtime/output-size-limits.ts
|
|
1187
1187
|
var encoder = typeof TextEncoder === "undefined" ? null : new TextEncoder();
|
|
1188
|
+
var LEDGER_TERMINAL_RESULT_MAX_BYTES = 768 * 1024;
|
|
1188
1189
|
var CUSTOMER_OUTPUT_VALUE_MAX_BYTES = 1 * 1024 * 1024;
|
|
1189
1190
|
var CUSTOMER_OUTPUT_TOTAL_MAX_BYTES = 2 * 1024 * 1024;
|
|
1190
1191
|
var RUNTIME_RECEIPT_OUTPUT_MAX_BYTES = 10 * 1024 * 1024;
|