deepline 0.3.122 → 0.3.123
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/README.md +33 -0
- package/dist/bundling-sources/sdk/src/client.ts +87 -26
- package/dist/bundling-sources/sdk/src/index.ts +8 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/types.ts +75 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +37 -0
- package/dist/cli/index.js +219 -16
- package/dist/cli/index.mjs +219 -16
- package/dist/index.d.mts +108 -42
- package/dist/index.d.ts +108 -42
- package/dist/index.js +47 -9
- package/dist/index.mjs +46 -9
- 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
package/README.md
CHANGED
|
@@ -46,4 +46,37 @@ Once setup is complete, tell your agent what you want to do:
|
|
|
46
46
|
deepline doctor --json
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
## Operate runs safely
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
deepline runs get play/my-play/run/20260706t233844-689-b0379871
|
|
53
|
+
deepline runs stop-all --dry-run
|
|
54
|
+
deepline runs stop-all --reason "incident cleanup"
|
|
55
|
+
deepline runs rerun play/my-play/run/20260706t233844-689-b0379871 --idempotency-key incident-42
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`runs get` shows status, current activity, and next steps. `stop-all --dry-run`
|
|
59
|
+
lists what would be stopped (workspace-scoped, child runs included) and never
|
|
60
|
+
cancels anything. A real `stop-all` reports a run as stopped only when the
|
|
61
|
+
scheduler confirmed it and exits nonzero on partial or failed stops. `runs
|
|
62
|
+
rerun` always sends an `Idempotency-Key`; reuse an explicit key to repeat an
|
|
63
|
+
ambiguous result without starting a second rerun (`deduplicated: true` in
|
|
64
|
+
`--json`). From code:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { DeeplineClient } from 'deepline';
|
|
68
|
+
|
|
69
|
+
const client = new DeeplineClient();
|
|
70
|
+
const runId = 'play/my-play/run/20260706t233844-689-b0379871';
|
|
71
|
+
const preview = await client.runs.stopAll({ dryRun: true });
|
|
72
|
+
const rerun = await client.runs.rerun(runId, {
|
|
73
|
+
idempotencyKey: 'incident-42',
|
|
74
|
+
});
|
|
75
|
+
console.log(preview.candidateCount, rerun.deduplicated);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Webhook delivery retries use the existing
|
|
79
|
+
`POST /api/v2/plays/webhook-deliveries/:receiptId` path; there is no separate
|
|
80
|
+
trigger retry, deliveries, health, or debug command.
|
|
81
|
+
|
|
49
82
|
Need help? Visit [code.deepline.com](https://code.deepline.com).
|
|
@@ -76,6 +76,10 @@ import type {
|
|
|
76
76
|
PlayDescription,
|
|
77
77
|
StopPlayRunResult,
|
|
78
78
|
StopAllPlayRunsResult,
|
|
79
|
+
StopAllPlayRunsDryRunResult,
|
|
80
|
+
StopAllPlayRunsStopResult,
|
|
81
|
+
RerunOptions,
|
|
82
|
+
RerunPlayRunResult,
|
|
79
83
|
ClearPlayHistoryRequest,
|
|
80
84
|
ClearPlayHistoryResult,
|
|
81
85
|
PublishPlayVersionRequest,
|
|
@@ -95,6 +99,7 @@ import type {
|
|
|
95
99
|
DeeplineAgentModelDescription,
|
|
96
100
|
InferenceQuote,
|
|
97
101
|
} from './types.js';
|
|
102
|
+
import { isStopAllPlayRunsDryRunResult } from './types.js';
|
|
98
103
|
import type { MonitorDefinition } from './monitors.js';
|
|
99
104
|
import type { MonitorFleetDefinition } from './monitor-fleets.js';
|
|
100
105
|
import type { PlayStagedFileRef } from './plays/local-file-discovery.js';
|
|
@@ -785,13 +790,7 @@ export type RunsNamespace = {
|
|
|
785
790
|
replayedFromRunId: string | null;
|
|
786
791
|
}>;
|
|
787
792
|
/** Start a fresh run from a prior run's retained input and pinned revision. */
|
|
788
|
-
rerun: (runId: string) => Promise<
|
|
789
|
-
runId: string;
|
|
790
|
-
replayedFromRunId: string;
|
|
791
|
-
revisionId: string | null;
|
|
792
|
-
status: string;
|
|
793
|
-
next: { inspect: string; input: string };
|
|
794
|
-
}>;
|
|
793
|
+
rerun: (runId: string, options?: RerunOptions) => Promise<RerunPlayRunResult>;
|
|
795
794
|
/** List runs for one play, optionally filtered by status. */
|
|
796
795
|
list: (options: RunsListOptions) => Promise<PlayRunListItem[]>;
|
|
797
796
|
/** Read one run page with total, offset, limit and completeness metadata. */
|
|
@@ -814,8 +813,27 @@ export type RunsNamespace = {
|
|
|
814
813
|
runId: string,
|
|
815
814
|
options?: { reason?: string },
|
|
816
815
|
) => Promise<StopPlayRunResult>;
|
|
817
|
-
/**
|
|
818
|
-
|
|
816
|
+
/**
|
|
817
|
+
* Stop active runs across the current workspace, or with `dryRun: true`
|
|
818
|
+
* enumerate the exact candidates without cancelling anything.
|
|
819
|
+
*/
|
|
820
|
+
stopAll: {
|
|
821
|
+
(
|
|
822
|
+
options: StopAllRunsOptions & { dryRun: true },
|
|
823
|
+
): Promise<StopAllPlayRunsDryRunResult>;
|
|
824
|
+
(
|
|
825
|
+
options?: StopAllRunsOptions & { dryRun?: false },
|
|
826
|
+
): Promise<StopAllPlayRunsStopResult>;
|
|
827
|
+
(options?: StopAllRunsOptions): Promise<StopAllPlayRunsResult>;
|
|
828
|
+
};
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
/** Options for {@link RunsNamespace.stopAll} / {@link DeeplineClient.stopAllRuns}. */
|
|
832
|
+
export type StopAllRunsOptions = {
|
|
833
|
+
/** Enumerate the candidate runs without cancelling or mutating anything. */
|
|
834
|
+
dryRun?: boolean;
|
|
835
|
+
/** Reason recorded with each stop request. Ignored by a dry run. */
|
|
836
|
+
reason?: string;
|
|
819
837
|
};
|
|
820
838
|
|
|
821
839
|
/** Current mutable customer database namespace exposed as `client.db`. */
|
|
@@ -2513,10 +2531,11 @@ export class DeeplineClient {
|
|
|
2513
2531
|
tail: (runId, options) => this.tailRun(runId, options),
|
|
2514
2532
|
logs: (runId, options) => this.getRunLogs(runId, options),
|
|
2515
2533
|
input: (runId) => this.getRunInput(runId),
|
|
2516
|
-
rerun: (runId) => this.rerun(runId),
|
|
2534
|
+
rerun: (runId, options) => this.rerun(runId, options),
|
|
2517
2535
|
exportDatasetRows: (input) => this.getPlaySheetRows(input),
|
|
2518
2536
|
stop: (runId, options) => this.stopRun(runId, options),
|
|
2519
|
-
stopAll: (options) =>
|
|
2537
|
+
stopAll: ((options?: StopAllRunsOptions) =>
|
|
2538
|
+
this.stopAllRuns(options)) as RunsNamespace['stopAll'],
|
|
2520
2539
|
};
|
|
2521
2540
|
this.db = {
|
|
2522
2541
|
query: (input) => this.queryDb(input),
|
|
@@ -4577,17 +4596,31 @@ export class DeeplineClient {
|
|
|
4577
4596
|
return this.http.get(`/api/v2/runs/${encodeURIComponent(runId)}/input`);
|
|
4578
4597
|
}
|
|
4579
4598
|
|
|
4580
|
-
/**
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4599
|
+
/**
|
|
4600
|
+
* Start a fresh run from a prior run's retained input and pinned revision.
|
|
4601
|
+
*
|
|
4602
|
+
* Every invocation sends an `Idempotency-Key`. When the caller does not
|
|
4603
|
+
* supply one, a fresh key is generated once per call so the transport's own
|
|
4604
|
+
* network retries converge on a single rerun. Pass the same explicit key
|
|
4605
|
+
* across separate invocations to repeat an ambiguous result safely; a
|
|
4606
|
+
* different key intentionally starts another rerun.
|
|
4607
|
+
*/
|
|
4608
|
+
async rerun(
|
|
4609
|
+
runId: string,
|
|
4610
|
+
options?: RerunOptions,
|
|
4611
|
+
): Promise<RerunPlayRunResult> {
|
|
4612
|
+
const idempotencyKey = options?.idempotencyKey?.trim();
|
|
4613
|
+
if (options?.idempotencyKey !== undefined && !idempotencyKey) {
|
|
4614
|
+
throw new DeeplineError(
|
|
4615
|
+
'runs.rerun idempotencyKey must not be empty.',
|
|
4616
|
+
undefined,
|
|
4617
|
+
'INVALID_IDEMPOTENCY_KEY',
|
|
4618
|
+
);
|
|
4619
|
+
}
|
|
4620
|
+
return this.http.post<RerunPlayRunResult>(
|
|
4589
4621
|
`/api/v2/runs/${encodeURIComponent(runId)}/rerun`,
|
|
4590
4622
|
{},
|
|
4623
|
+
{ 'Idempotency-Key': idempotencyKey || globalThis.crypto.randomUUID() },
|
|
4591
4624
|
);
|
|
4592
4625
|
}
|
|
4593
4626
|
|
|
@@ -4771,25 +4804,53 @@ export class DeeplineClient {
|
|
|
4771
4804
|
);
|
|
4772
4805
|
}
|
|
4773
4806
|
|
|
4807
|
+
/** Enumerate the runs a stop-all would target without cancelling any. */
|
|
4808
|
+
async stopAllRuns(
|
|
4809
|
+
options: StopAllRunsOptions & { dryRun: true },
|
|
4810
|
+
): Promise<StopAllPlayRunsDryRunResult>;
|
|
4811
|
+
/** Stop every active run visible to the current workspace. */
|
|
4812
|
+
async stopAllRuns(
|
|
4813
|
+
options?: StopAllRunsOptions & { dryRun?: false },
|
|
4814
|
+
): Promise<StopAllPlayRunsStopResult>;
|
|
4815
|
+
/** Stop, or with `dryRun: true` only enumerate, active workspace runs. */
|
|
4816
|
+
async stopAllRuns(
|
|
4817
|
+
options?: StopAllRunsOptions,
|
|
4818
|
+
): Promise<StopAllPlayRunsResult>;
|
|
4774
4819
|
/**
|
|
4775
|
-
* Stop every active run visible to the current workspace
|
|
4820
|
+
* Stop every active run visible to the current workspace, or with
|
|
4821
|
+
* `dryRun: true` enumerate the exact candidates without cancelling anything.
|
|
4776
4822
|
*
|
|
4777
4823
|
* This is the SDK equivalent of:
|
|
4778
4824
|
*
|
|
4779
4825
|
* ```bash
|
|
4826
|
+
* deepline runs stop-all --dry-run --json
|
|
4780
4827
|
* deepline runs stop-all --reason "stale lock" --json
|
|
4781
4828
|
* ```
|
|
4782
4829
|
*
|
|
4783
4830
|
* Use this when a failed parent run left child or waiting runs active and you
|
|
4784
4831
|
* need to clear the workspace run-slot state without knowing each run id.
|
|
4785
4832
|
*/
|
|
4786
|
-
async stopAllRuns(
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4833
|
+
async stopAllRuns(
|
|
4834
|
+
options?: StopAllRunsOptions,
|
|
4835
|
+
): Promise<StopAllPlayRunsResult> {
|
|
4836
|
+
const dryRun = options?.dryRun === true;
|
|
4837
|
+
const result = await this.http.post<StopAllPlayRunsResult>(
|
|
4790
4838
|
'/api/v2/runs/stop-all',
|
|
4791
|
-
|
|
4839
|
+
{
|
|
4840
|
+
...(options?.reason ? { reason: options.reason } : {}),
|
|
4841
|
+
...(dryRun ? { dryRun: true } : {}),
|
|
4842
|
+
},
|
|
4792
4843
|
);
|
|
4844
|
+
if (dryRun && !isStopAllPlayRunsDryRunResult(result)) {
|
|
4845
|
+
// An older server ignores unknown body fields and would have stopped
|
|
4846
|
+
// runs for real. It cannot un-stop them, so say exactly what happened.
|
|
4847
|
+
throw new DeeplineError(
|
|
4848
|
+
'This Deepline server does not support runs stop-all --dry-run and performed a real stop-all. Update the server before using --dry-run.',
|
|
4849
|
+
undefined,
|
|
4850
|
+
'STOP_ALL_DRY_RUN_UNSUPPORTED',
|
|
4851
|
+
);
|
|
4852
|
+
}
|
|
4853
|
+
return result;
|
|
4793
4854
|
}
|
|
4794
4855
|
|
|
4795
4856
|
/**
|
|
@@ -125,11 +125,13 @@ export type {
|
|
|
125
125
|
RunsLogsResult,
|
|
126
126
|
RunsNamespace,
|
|
127
127
|
RunsTailOptions,
|
|
128
|
+
StopAllRunsOptions,
|
|
128
129
|
ToolExecution,
|
|
129
130
|
} from './client.js';
|
|
130
131
|
|
|
131
132
|
// ——— Monitors framework ———
|
|
132
133
|
export { defineMonitor } from './monitors.js';
|
|
134
|
+
export { isStopAllPlayRunsDryRunResult } from './types.js';
|
|
133
135
|
export type { MonitorDefinition, MonitorPayload } from './monitors.js';
|
|
134
136
|
export {
|
|
135
137
|
lintMonitorBatchInput,
|
|
@@ -267,6 +269,12 @@ export type {
|
|
|
267
269
|
DeeplineToolCategory,
|
|
268
270
|
PlayBootstrapFinderKind,
|
|
269
271
|
PlayBootstrapEntityKind,
|
|
272
|
+
RerunOptions,
|
|
273
|
+
RerunPlayRunResult,
|
|
274
|
+
StopAllCandidate,
|
|
275
|
+
StopAllPlayRunsDryRunResult,
|
|
276
|
+
StopAllPlayRunsResult,
|
|
277
|
+
StopAllPlayRunsStopResult,
|
|
270
278
|
StopPlayRunResult,
|
|
271
279
|
ToolSearchOptions,
|
|
272
280
|
ToolSearchResult,
|
|
@@ -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.123',
|
|
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: {
|
|
@@ -958,14 +958,88 @@ export interface StopPlayRunResult {
|
|
|
958
958
|
error?: string;
|
|
959
959
|
}
|
|
960
960
|
|
|
961
|
-
|
|
961
|
+
/**
|
|
962
|
+
* Result of an actual workspace stop-all. `stopped` counts only runs whose
|
|
963
|
+
* scheduler cancellation was confirmed; a run whose cancel failed stays active
|
|
964
|
+
* and is counted in `failed`.
|
|
965
|
+
*/
|
|
966
|
+
export interface StopAllPlayRunsStopResult {
|
|
962
967
|
stopped: number;
|
|
963
968
|
failed: number;
|
|
964
969
|
skipped: number;
|
|
970
|
+
/** True when the bounded candidate query may have left active runs behind. */
|
|
965
971
|
partial?: boolean;
|
|
966
972
|
runs: Array<StopPlayRunResult & { status?: string | null }>;
|
|
967
973
|
}
|
|
968
974
|
|
|
975
|
+
/** Options for {@link DeeplineClient.rerun} / `runs.rerun`. */
|
|
976
|
+
export interface RerunOptions {
|
|
977
|
+
/**
|
|
978
|
+
* Caller-chosen key sent as `Idempotency-Key`. The same source run and key
|
|
979
|
+
* always resolve to the same rerun; omit it to let the SDK generate one key
|
|
980
|
+
* per invocation.
|
|
981
|
+
*/
|
|
982
|
+
idempotencyKey?: string;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/** Result of {@link DeeplineClient.rerun} / `runs.rerun`. */
|
|
986
|
+
export interface RerunPlayRunResult {
|
|
987
|
+
/** The rerun's public play-run id. */
|
|
988
|
+
runId: string;
|
|
989
|
+
/** The source run whose retained input and revision were replayed. */
|
|
990
|
+
replayedFromRunId: string;
|
|
991
|
+
revisionId: string | null;
|
|
992
|
+
status: string;
|
|
993
|
+
/**
|
|
994
|
+
* True when the server returned an already-admitted rerun for this source
|
|
995
|
+
* run and idempotency key instead of starting another. Absent on older
|
|
996
|
+
* servers.
|
|
997
|
+
*/
|
|
998
|
+
deduplicated?: boolean;
|
|
999
|
+
next: { inspect: string; input: string };
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/** One active run that a workspace stop-all would target. */
|
|
1003
|
+
export interface StopAllCandidate {
|
|
1004
|
+
/** Public play-run id. */
|
|
1005
|
+
runId: string;
|
|
1006
|
+
/** Saved play name for the run, when known. */
|
|
1007
|
+
playName: string | null;
|
|
1008
|
+
/** Current durable status (`running`, `queued`, or `waiting`). */
|
|
1009
|
+
status: string | null;
|
|
1010
|
+
/** Parent play-run id when this is a child run; null for root runs. */
|
|
1011
|
+
parentRunId: string | null;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Result of `runs.stopAll({ dryRun: true })`. Nothing was cancelled or
|
|
1016
|
+
* mutated; the list is the exact candidate set the real stop-all would target,
|
|
1017
|
+
* in the same parent-before-child order.
|
|
1018
|
+
*/
|
|
1019
|
+
export interface StopAllPlayRunsDryRunResult {
|
|
1020
|
+
dryRun: true;
|
|
1021
|
+
scope: 'workspace';
|
|
1022
|
+
includesChildren: true;
|
|
1023
|
+
candidateCount: number;
|
|
1024
|
+
/** True when the bounded query hit its limit and more active runs may exist. */
|
|
1025
|
+
truncated: boolean;
|
|
1026
|
+
runs: StopAllCandidate[];
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Discriminated result of {@link DeeplineClient.stopAllRuns}: narrow on
|
|
1031
|
+
* `'dryRun' in result` to distinguish an enumeration from an actual stop.
|
|
1032
|
+
*/
|
|
1033
|
+
export type StopAllPlayRunsResult =
|
|
1034
|
+
| StopAllPlayRunsStopResult
|
|
1035
|
+
| StopAllPlayRunsDryRunResult;
|
|
1036
|
+
|
|
1037
|
+
export function isStopAllPlayRunsDryRunResult(
|
|
1038
|
+
result: StopAllPlayRunsResult,
|
|
1039
|
+
): result is StopAllPlayRunsDryRunResult {
|
|
1040
|
+
return 'dryRun' in result && result.dryRun === true;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
969
1043
|
/**
|
|
970
1044
|
* Summary of a single play run, returned by {@link DeeplineClient.listPlayRuns}.
|
|
971
1045
|
*/
|
|
@@ -152,6 +152,43 @@ export function buildAsyncPlayRunIdentity(input: {
|
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Build the retry-stable identity for one caller-keyed `runs rerun` request.
|
|
157
|
+
*
|
|
158
|
+
* The digest is namespaced (`-rerun-`) so a keyed replay can never collide
|
|
159
|
+
* with an ordinary entropy-suffixed run, an async child (`-async-`), or a
|
|
160
|
+
* differently keyed replay of the same source run. Everything else about a
|
|
161
|
+
* replay (input, revision, artifact, lane) is fixed by the source run, so the
|
|
162
|
+
* same `sourceRunId + idempotencyKey` always names the same intended Run and
|
|
163
|
+
* the existing run-ledger admission fence resolves repeats to it.
|
|
164
|
+
*/
|
|
165
|
+
export function buildRerunPlayRunIdentity(input: {
|
|
166
|
+
playName: string;
|
|
167
|
+
sourceRunId: string;
|
|
168
|
+
idempotencyKey: string;
|
|
169
|
+
/** Fallback ordering timestamp when the source id carries no canonical one. */
|
|
170
|
+
sourceStartedAtMs?: number | null;
|
|
171
|
+
}): PlayRunIdentity {
|
|
172
|
+
const digest = sha256Hex(
|
|
173
|
+
`rerun\0${input.sourceRunId}\0${input.idempotencyKey}`,
|
|
174
|
+
).slice(0, 20);
|
|
175
|
+
const startedAt =
|
|
176
|
+
canonicalPlayRunStartedAtMs(input.sourceRunId) ??
|
|
177
|
+
(typeof input.sourceStartedAtMs === 'number' &&
|
|
178
|
+
Number.isFinite(input.sourceStartedAtMs)
|
|
179
|
+
? input.sourceStartedAtMs
|
|
180
|
+
: 0);
|
|
181
|
+
const base = buildPlayWorkflowId(input.playName, new Date(startedAt), {
|
|
182
|
+
unique: false,
|
|
183
|
+
});
|
|
184
|
+
const workflowId = `${base}-rerun-${digest}`;
|
|
185
|
+
return {
|
|
186
|
+
workflowId,
|
|
187
|
+
runId: workflowId,
|
|
188
|
+
workflowFamilyKey: buildPlayWorkflowFamilyKey(input.playName),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
155
192
|
/** Immutable authored request identity, separate from the resolved revision. */
|
|
156
193
|
export function buildAsyncPlayRequestFingerprint(input: {
|
|
157
194
|
key: string;
|