deepline 0.3.286 → 0.3.287
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/client.ts +47 -24
- package/dist/bundling-sources/sdk/src/index.ts +4 -0
- package/dist/bundling-sources/sdk/src/release.ts +7 -1
- package/dist/bundling-sources/sdk/src/types.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/cell-provenance.ts +16 -0
- package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +38 -3
- package/dist/bundling-sources/shared_libs/play-runtime/run-observation.ts +12 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +43 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +88 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +53 -25
- package/dist/bundling-sources/shared_libs/play-runtime/step-progress.ts +83 -1
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +2 -0
- package/dist/cli/index.js +579 -628
- package/dist/cli/index.mjs +456 -506
- package/dist/{client-B7ic-kY5.d.ts → client-FR_u0dxT.d.ts} +38 -1
- package/dist/{client-Dzf_KovW.d.mts → client-phK1Ixcl.d.mts} +38 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +48 -25
- package/dist/index.mjs +48 -25
- package/dist/install-integrity.json +2 -2
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +5 -1
- package/dist/release.d.ts +5 -1
- package/dist/release.js +6 -1
- package/dist/release.mjs +6 -1
- package/package.json +1 -1
|
@@ -117,6 +117,8 @@ import type {
|
|
|
117
117
|
DeeplineAgentModelDescription,
|
|
118
118
|
InferenceQuote,
|
|
119
119
|
ChildRunSummary,
|
|
120
|
+
SearchOptions,
|
|
121
|
+
SearchResult,
|
|
120
122
|
} from './types.js';
|
|
121
123
|
import { isStopAllPlayRunsDryRunResult } from './types.js';
|
|
122
124
|
import type { MonitorDefinition } from './monitors.js';
|
|
@@ -610,6 +612,29 @@ function chunkRegisterPlayArtifacts<T>(artifacts: T[]): T[][] {
|
|
|
610
612
|
return chunks;
|
|
611
613
|
}
|
|
612
614
|
|
|
615
|
+
/** Query parameters shared by every search route. */
|
|
616
|
+
function searchParams(options: ToolSearchOptions): URLSearchParams {
|
|
617
|
+
const params = new URLSearchParams();
|
|
618
|
+
params.set('q', options.query?.trim() ?? '');
|
|
619
|
+
params.set(
|
|
620
|
+
'include_search_debug',
|
|
621
|
+
options.includeSearchDebug ? 'true' : 'false',
|
|
622
|
+
);
|
|
623
|
+
params.set('search_mode', options.searchMode ?? 'v2');
|
|
624
|
+
if (options.limit !== undefined) params.set('limit', String(options.limit));
|
|
625
|
+
if (options.offset !== undefined) {
|
|
626
|
+
params.set('offset', String(options.offset));
|
|
627
|
+
}
|
|
628
|
+
if (options.categories?.trim()) {
|
|
629
|
+
params.set('categories', options.categories.trim());
|
|
630
|
+
}
|
|
631
|
+
if (options.searchTerms?.trim()) {
|
|
632
|
+
params.set('search_terms', options.searchTerms.trim());
|
|
633
|
+
}
|
|
634
|
+
if (options.task?.trim()) params.set('task', options.task.trim());
|
|
635
|
+
return params;
|
|
636
|
+
}
|
|
637
|
+
|
|
613
638
|
/** Filters for `client.runs.list(...)`. */
|
|
614
639
|
export type RunsListOptions = {
|
|
615
640
|
play?: string;
|
|
@@ -3195,34 +3220,32 @@ export class DeeplineClient {
|
|
|
3195
3220
|
async searchTools(
|
|
3196
3221
|
options: ToolSearchOptions = {},
|
|
3197
3222
|
): Promise<ToolSearchResult> {
|
|
3198
|
-
const params = new URLSearchParams();
|
|
3199
|
-
const query = options.query?.trim() ?? '';
|
|
3200
|
-
params.set('q', query);
|
|
3201
|
-
params.set(
|
|
3202
|
-
'include_search_debug',
|
|
3203
|
-
options.includeSearchDebug ? 'true' : 'false',
|
|
3204
|
-
);
|
|
3205
|
-
params.set('search_mode', options.searchMode ?? 'v2');
|
|
3206
|
-
if (options.limit !== undefined) {
|
|
3207
|
-
params.set('limit', String(options.limit));
|
|
3208
|
-
}
|
|
3209
|
-
if (options.offset !== undefined) {
|
|
3210
|
-
params.set('offset', String(options.offset));
|
|
3211
|
-
}
|
|
3212
|
-
if (options.categories?.trim()) {
|
|
3213
|
-
params.set('categories', options.categories.trim());
|
|
3214
|
-
}
|
|
3215
|
-
if (options.searchTerms?.trim()) {
|
|
3216
|
-
params.set('search_terms', options.searchTerms.trim());
|
|
3217
|
-
}
|
|
3218
|
-
if (options.task?.trim()) {
|
|
3219
|
-
params.set('task', options.task.trim());
|
|
3220
|
-
}
|
|
3221
3223
|
return this.http.get<ToolSearchResult>(
|
|
3222
|
-
`/api/v2/tools/search?${
|
|
3224
|
+
`/api/v2/tools/search?${searchParams(options).toString()}`,
|
|
3223
3225
|
);
|
|
3224
3226
|
}
|
|
3225
3227
|
|
|
3228
|
+
/**
|
|
3229
|
+
* Search everything Deepline can run or deploy in one ranked list: tools,
|
|
3230
|
+
* monitor types, prebuilt plays, and your workspace's own plays.
|
|
3231
|
+
*
|
|
3232
|
+
* @example
|
|
3233
|
+
* ```typescript
|
|
3234
|
+
* const { results } = await client.search({
|
|
3235
|
+
* query: 'find work email',
|
|
3236
|
+
* types: ['tools', 'prebuilts'],
|
|
3237
|
+
* });
|
|
3238
|
+
* ```
|
|
3239
|
+
*/
|
|
3240
|
+
async search(options: SearchOptions = {}): Promise<SearchResult> {
|
|
3241
|
+
const params = searchParams(options);
|
|
3242
|
+
if (options.types?.length) params.set('types', options.types.join(','));
|
|
3243
|
+
if (options.exclude?.length) {
|
|
3244
|
+
params.set('exclude', options.exclude.join(','));
|
|
3245
|
+
}
|
|
3246
|
+
return this.http.get<SearchResult>(`/api/v2/search?${params.toString()}`);
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3226
3249
|
/**
|
|
3227
3250
|
* Get detailed metadata for a single tool.
|
|
3228
3251
|
*
|
|
@@ -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.287',
|
|
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: {
|
|
@@ -235,6 +235,12 @@ export const SDK_RELEASE = {
|
|
|
235
235
|
minimumSupported: '0.1.53',
|
|
236
236
|
deprecatedBelow: '0.3.1',
|
|
237
237
|
commandIntroducedIn: [
|
|
238
|
+
{
|
|
239
|
+
command: 'search',
|
|
240
|
+
introducedIn: '0.3.91',
|
|
241
|
+
reason:
|
|
242
|
+
'deepline search was added in SDK CLI 0.3.91 as the one search across tools, monitors, and plays. On an older version run deepline tools search or deepline plays search, or update.',
|
|
243
|
+
},
|
|
238
244
|
{
|
|
239
245
|
command: 'notifications',
|
|
240
246
|
introducedIn: '0.2.40',
|
|
@@ -488,6 +488,42 @@ export interface ToolSearchOptions {
|
|
|
488
488
|
includeSearchDebug?: boolean;
|
|
489
489
|
}
|
|
490
490
|
|
|
491
|
+
/** What a search can be narrowed to. `plays` is `prebuilts` plus `custom`. */
|
|
492
|
+
export type SearchType =
|
|
493
|
+
| 'tools'
|
|
494
|
+
| 'plays'
|
|
495
|
+
| 'monitors'
|
|
496
|
+
| 'prebuilts'
|
|
497
|
+
| 'custom';
|
|
498
|
+
|
|
499
|
+
/** Options for {@link DeeplineClient.search}. */
|
|
500
|
+
export interface SearchOptions extends ToolSearchOptions {
|
|
501
|
+
/** Kinds of result to search. Omit to search everything. */
|
|
502
|
+
types?: readonly SearchType[];
|
|
503
|
+
/** Kinds of result to leave out; the opposite of `types`. */
|
|
504
|
+
exclude?: readonly SearchType[];
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** One ranked search result; `kind` says which fields accompany it. */
|
|
508
|
+
export interface SearchResultItem {
|
|
509
|
+
/** Tool id for tools and monitor types, or play reference. */
|
|
510
|
+
id: string;
|
|
511
|
+
kind: 'tool' | 'monitor_type' | 'prebuilt_play' | 'custom_play';
|
|
512
|
+
displayName?: string;
|
|
513
|
+
description?: string;
|
|
514
|
+
[field: string]: unknown;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/** Ranked results across tools, monitor types, and plays. */
|
|
518
|
+
export interface SearchResult extends Omit<
|
|
519
|
+
ToolSearchResult,
|
|
520
|
+
'tools' | 'omitted_plays_hint' | 'commandTemplates'
|
|
521
|
+
> {
|
|
522
|
+
results: SearchResultItem[];
|
|
523
|
+
/** The result kinds this search covered. */
|
|
524
|
+
kinds: SearchResultItem['kind'][];
|
|
525
|
+
}
|
|
526
|
+
|
|
491
527
|
/**
|
|
492
528
|
* Ranked tool/provider discovery response.
|
|
493
529
|
*
|
|
@@ -45,6 +45,22 @@ export interface PlayCellDecision {
|
|
|
45
45
|
reads: PlayCellReadRef[];
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/** One persisted outcome per row and predicate, never evaluation attempts. */
|
|
49
|
+
export type PlayConditionCounts = { true: number; false: number };
|
|
50
|
+
|
|
51
|
+
export function normalizePlayConditionCounts(
|
|
52
|
+
value: unknown,
|
|
53
|
+
): PlayConditionCounts | undefined {
|
|
54
|
+
if (!value || typeof value !== 'object') return undefined;
|
|
55
|
+
const counts = value as PlayConditionCounts;
|
|
56
|
+
return Number.isSafeInteger(counts.true) &&
|
|
57
|
+
counts.true >= 0 &&
|
|
58
|
+
Number.isSafeInteger(counts.false) &&
|
|
59
|
+
counts.false >= 0
|
|
60
|
+
? { true: counts.true, false: counts.false }
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
48
64
|
/** Row-grain birth: the source row the runtime held while building this row. */
|
|
49
65
|
export type PlayRowBornFromRow = { table: string; rowKey: string };
|
|
50
66
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PlayRunLifecycleStatus } from './run-lifecycle-policy';
|
|
2
2
|
import type { PlayDocflowNodeIoState } from './docflow-node-io';
|
|
3
3
|
import type { RunStopCause } from './run-execution-state';
|
|
4
|
+
import type { PlayConditionCounts } from './cell-provenance';
|
|
4
5
|
import type {
|
|
5
6
|
PlayActivityObservation,
|
|
6
7
|
PlayRunActivityProjection,
|
|
@@ -31,6 +32,7 @@ export type PlayVisualNodeProgressSnapshot = {
|
|
|
31
32
|
completedAt?: number | null;
|
|
32
33
|
artifactTableNamespace?: string | null;
|
|
33
34
|
nodeIo?: PlayDocflowNodeIoState;
|
|
35
|
+
conditionCounts?: PlayConditionCounts;
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
mergeDatasetBornFrom,
|
|
21
21
|
normalizeDatasetBornFrom,
|
|
22
22
|
type PlayDatasetBornFrom,
|
|
23
|
+
normalizePlayConditionCounts,
|
|
24
|
+
type PlayConditionCounts,
|
|
23
25
|
} from './cell-provenance';
|
|
24
26
|
import { isLedgerTerminalResultRef } from './output-size-limits';
|
|
25
27
|
import type { PlayLogContext } from './log-context';
|
|
@@ -98,6 +100,7 @@ export type PlayRunLedgerStepProgress = {
|
|
|
98
100
|
completedAt?: number | null;
|
|
99
101
|
updatedAt?: number | null;
|
|
100
102
|
nodeIo?: PlayDocflowNodeIoState;
|
|
103
|
+
conditionCounts?: PlayConditionCounts;
|
|
101
104
|
};
|
|
102
105
|
|
|
103
106
|
export type PlayRunLedgerStepSnapshot = {
|
|
@@ -1400,6 +1403,9 @@ function normalizeStepProgress(
|
|
|
1400
1403
|
...(normalizePlayDocflowNodeIoState(value.nodeIo)
|
|
1401
1404
|
? { nodeIo: normalizePlayDocflowNodeIoState(value.nodeIo) }
|
|
1402
1405
|
: {}),
|
|
1406
|
+
...(normalizePlayConditionCounts(value.conditionCounts)
|
|
1407
|
+
? { conditionCounts: normalizePlayConditionCounts(value.conditionCounts) }
|
|
1408
|
+
: {}),
|
|
1403
1409
|
};
|
|
1404
1410
|
}
|
|
1405
1411
|
|
|
@@ -1760,11 +1766,36 @@ export function reducePlayRunLedgerEvent(
|
|
|
1760
1766
|
// Detached runners can race their best-effort progress transport against the
|
|
1761
1767
|
// terminal outbox, and gateway processes can restart or split that traffic.
|
|
1762
1768
|
// The Play Run Ledger is the durable projection authority, so late
|
|
1763
|
-
//
|
|
1764
|
-
// process to remember terminal state.
|
|
1769
|
+
// lifecycle facts must be a true no-op here rather than relying on a gateway
|
|
1770
|
+
// process to remember terminal state. Settled condition counts may arrive
|
|
1771
|
+
// after that claim and fill an absent summary without changing lifecycle.
|
|
1765
1772
|
if (isTerminalPlayRunLedgerStatus(snapshot.status)) {
|
|
1766
1773
|
if (event.type === RUN_EVENT_KIND.stepProgress) {
|
|
1767
|
-
|
|
1774
|
+
const refined =
|
|
1775
|
+
refineTerminalSyntheticStepStart(snapshot, event) ?? snapshot;
|
|
1776
|
+
const current = refined.stepsById[event.stepId];
|
|
1777
|
+
const conditionCounts = normalizePlayConditionCounts(
|
|
1778
|
+
event.progress.conditionCounts,
|
|
1779
|
+
);
|
|
1780
|
+
// Sheet reconciliation follows the fenced terminal claim. Accept its
|
|
1781
|
+
// first settled predicate pair without reopening lifecycle or timestamps.
|
|
1782
|
+
if (conditionCounts && !current?.progress?.conditionCounts) {
|
|
1783
|
+
return {
|
|
1784
|
+
...refined,
|
|
1785
|
+
orderedStepIds: appendOrderedStepId(refined, event.stepId),
|
|
1786
|
+
stepsById: {
|
|
1787
|
+
...refined.stepsById,
|
|
1788
|
+
[event.stepId]: {
|
|
1789
|
+
...(current ?? {
|
|
1790
|
+
stepId: event.stepId,
|
|
1791
|
+
status: 'completed' as const,
|
|
1792
|
+
}),
|
|
1793
|
+
progress: { ...current?.progress, conditionCounts },
|
|
1794
|
+
},
|
|
1795
|
+
},
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
return refined;
|
|
1768
1799
|
}
|
|
1769
1800
|
if (isStepLifecycleEvent(event)) return snapshot;
|
|
1770
1801
|
}
|
|
@@ -2300,6 +2331,7 @@ function progressSignature(
|
|
|
2300
2331
|
startedAt: progress?.startedAt ?? null,
|
|
2301
2332
|
completedAt: progress?.completedAt ?? null,
|
|
2302
2333
|
nodeIo: progress?.nodeIo ?? null,
|
|
2334
|
+
conditionCounts: progress?.conditionCounts ?? null,
|
|
2303
2335
|
});
|
|
2304
2336
|
}
|
|
2305
2337
|
|
|
@@ -2621,6 +2653,9 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2621
2653
|
? { completedAt: progress.completedAt }
|
|
2622
2654
|
: {}),
|
|
2623
2655
|
...(progress.nodeIo !== undefined ? { nodeIo: progress.nodeIo } : {}),
|
|
2656
|
+
...(progress.conditionCounts !== undefined
|
|
2657
|
+
? { conditionCounts: progress.conditionCounts }
|
|
2658
|
+
: {}),
|
|
2624
2659
|
updatedAt: progress.updatedAt ?? checkpointAt,
|
|
2625
2660
|
};
|
|
2626
2661
|
if (
|
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
isTerminalPlayRunLifecycleStatus,
|
|
10
10
|
type PlayRunPublicStatus,
|
|
11
11
|
} from './run-lifecycle-policy';
|
|
12
|
+
import {
|
|
13
|
+
normalizePlayConditionCounts,
|
|
14
|
+
type PlayConditionCounts,
|
|
15
|
+
} from './cell-provenance';
|
|
12
16
|
import type { RunStopCause } from './run-execution-state';
|
|
13
17
|
|
|
14
18
|
/**
|
|
@@ -64,6 +68,7 @@ export type RunObservationNode = {
|
|
|
64
68
|
* Run Snapshot fact `deriveNodeExecutionState` reads. Absent otherwise.
|
|
65
69
|
*/
|
|
66
70
|
stoppedBy?: RunStopCause;
|
|
71
|
+
conditionCounts?: PlayConditionCounts;
|
|
67
72
|
};
|
|
68
73
|
|
|
69
74
|
export type RunObservation = {
|
|
@@ -204,6 +209,13 @@ function projectNode(node: PlayRunStreamNodeState): RunObservationNode {
|
|
|
204
209
|
total: finite(node.progress?.total),
|
|
205
210
|
settled: nonNegative(node.progress?.completed),
|
|
206
211
|
failed: nonNegative(node.progress?.failed),
|
|
212
|
+
...(normalizePlayConditionCounts(node.progress?.conditionCounts)
|
|
213
|
+
? {
|
|
214
|
+
conditionCounts: normalizePlayConditionCounts(
|
|
215
|
+
node.progress?.conditionCounts,
|
|
216
|
+
),
|
|
217
|
+
}
|
|
218
|
+
: {}),
|
|
207
219
|
...(node.stoppedBy ? { stoppedBy: node.stoppedBy } : {}),
|
|
208
220
|
};
|
|
209
221
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from './run-lifecycle-policy';
|
|
19
19
|
import type { PlayDocflowNodeIoState } from './docflow-node-io';
|
|
20
20
|
import type { RunStopCause } from './run-execution-state';
|
|
21
|
+
import type { PlayConditionCounts } from './cell-provenance';
|
|
21
22
|
import type { PlayVisualNodeUsageSnapshot } from './live-state-contract';
|
|
22
23
|
import {
|
|
23
24
|
projectPlayRunActivity,
|
|
@@ -53,6 +54,7 @@ export type PlayRunStreamNodeProgress = {
|
|
|
53
54
|
completedAt?: number | null;
|
|
54
55
|
artifactTableNamespace?: string | null;
|
|
55
56
|
nodeIo?: PlayDocflowNodeIoState;
|
|
57
|
+
conditionCounts?: PlayConditionCounts;
|
|
56
58
|
};
|
|
57
59
|
|
|
58
60
|
export type PlayRunStreamNodeState = {
|
|
@@ -250,6 +252,7 @@ function buildSnapshotFromLedger(
|
|
|
250
252
|
completedAt: step.completedAt ?? null,
|
|
251
253
|
updatedAt: step.progress.updatedAt ?? step.updatedAt ?? null,
|
|
252
254
|
nodeIo: step.progress.nodeIo,
|
|
255
|
+
conditionCounts: step.progress.conditionCounts,
|
|
253
256
|
}
|
|
254
257
|
: null,
|
|
255
258
|
startedAt: step.startedAt ?? null,
|
|
@@ -116,6 +116,7 @@ import {
|
|
|
116
116
|
resolveMapRowOutcomeKey,
|
|
117
117
|
} from './map-row-outcome';
|
|
118
118
|
import { DEEPLINE_CELL_META_FIELD } from '../plays/cell-staleness';
|
|
119
|
+
import type { PlayConditionCounts } from './cell-provenance';
|
|
119
120
|
import {
|
|
120
121
|
LEGACY_RUNTIME_RECEIPT_WIRE_FORMAT,
|
|
121
122
|
LEGACY_RUNTIME_RECEIPT_WIRE_HEADER,
|
|
@@ -9207,6 +9208,7 @@ export type RuntimeSheetRowOutcomeCounts = {
|
|
|
9207
9208
|
completed: number;
|
|
9208
9209
|
failed: number;
|
|
9209
9210
|
total: number;
|
|
9211
|
+
conditions?: Record<string, PlayConditionCounts>;
|
|
9210
9212
|
};
|
|
9211
9213
|
|
|
9212
9214
|
/**
|
|
@@ -9231,6 +9233,7 @@ export async function countRuntimeSheetRowOutcomes(
|
|
|
9231
9233
|
runId: string;
|
|
9232
9234
|
playName?: string;
|
|
9233
9235
|
tableNamespace?: string;
|
|
9236
|
+
includeConditions?: boolean;
|
|
9234
9237
|
},
|
|
9235
9238
|
): Promise<RuntimeSheetRowOutcomeCounts> {
|
|
9236
9239
|
const { rows } = await client.query<{
|
|
@@ -9247,13 +9250,51 @@ export async function countRuntimeSheetRowOutcomes(
|
|
|
9247
9250
|
[input.runId],
|
|
9248
9251
|
);
|
|
9249
9252
|
const row = rows[0];
|
|
9253
|
+
const conditions = input.includeConditions
|
|
9254
|
+
? await countRuntimeSheetConditionOutcomes(client, input)
|
|
9255
|
+
: undefined;
|
|
9250
9256
|
return {
|
|
9251
9257
|
completed: Math.max(0, Number(row?.completed ?? 0) || 0),
|
|
9252
9258
|
failed: Math.max(0, Number(row?.failed ?? 0) || 0),
|
|
9253
9259
|
total: Math.max(0, Number(row?.total ?? 0) || 0),
|
|
9260
|
+
...(conditions ? { conditions } : {}),
|
|
9254
9261
|
};
|
|
9255
9262
|
}
|
|
9256
9263
|
|
|
9264
|
+
/** Aggregate durable witnesses, including false/skipped and true/failed cells. */
|
|
9265
|
+
export async function countRuntimeSheetConditionOutcomes(
|
|
9266
|
+
client: {
|
|
9267
|
+
query<Row extends Record<string, unknown> = Record<string, unknown>>(
|
|
9268
|
+
sql: string,
|
|
9269
|
+
params?: unknown[],
|
|
9270
|
+
): Promise<{ rows: Row[] }>;
|
|
9271
|
+
},
|
|
9272
|
+
input: { schema: string; table: string; runId: string },
|
|
9273
|
+
): Promise<Record<string, PlayConditionCounts>> {
|
|
9274
|
+
const { rows } = await client.query<{
|
|
9275
|
+
field: string;
|
|
9276
|
+
true_count: number | string;
|
|
9277
|
+
false_count: number | string;
|
|
9278
|
+
}>(
|
|
9279
|
+
`SELECT cell.key AS field,
|
|
9280
|
+
count(*) FILTER (WHERE cell.value #>> '{decide,branch}' = 'run') AS true_count,
|
|
9281
|
+
count(*) FILTER (WHERE cell.value #>> '{decide,branch}' = 'else') AS false_count
|
|
9282
|
+
FROM ${quoteIdentifier(input.schema)}.${quoteIdentifier(input.table)} AS sheet
|
|
9283
|
+
CROSS JOIN LATERAL jsonb_each(coalesce(sheet._cell_meta, '{}'::jsonb)) AS cell(key, value)
|
|
9284
|
+
WHERE sheet._run_id = $1::text
|
|
9285
|
+
AND cell.value ->> 'runId' = $1::text
|
|
9286
|
+
AND cell.value #>> '{decide,branch}' IN ('run', 'else')
|
|
9287
|
+
GROUP BY cell.key`,
|
|
9288
|
+
[input.runId],
|
|
9289
|
+
);
|
|
9290
|
+
return Object.fromEntries(
|
|
9291
|
+
rows.map((row) => [
|
|
9292
|
+
row.field,
|
|
9293
|
+
{ true: Number(row.true_count), false: Number(row.false_count) },
|
|
9294
|
+
]),
|
|
9295
|
+
);
|
|
9296
|
+
}
|
|
9297
|
+
|
|
9257
9298
|
/**
|
|
9258
9299
|
* Read the settled row-outcome counts for a dataset's runtime sheet through the
|
|
9259
9300
|
* run's preloaded DB session. Used by the scheduler worker at terminal finalize
|
|
@@ -9265,7 +9306,7 @@ export async function countRuntimeSheetRowOutcomes(
|
|
|
9265
9306
|
*/
|
|
9266
9307
|
export async function readRuntimeSheetRowOutcomeCounts(
|
|
9267
9308
|
context: RuntimeApiContext & { playName: string; runId: string },
|
|
9268
|
-
input: { tableNamespace: string },
|
|
9309
|
+
input: { tableNamespace: string; includeConditions?: boolean },
|
|
9269
9310
|
): Promise<RuntimeSheetRowOutcomeCounts> {
|
|
9270
9311
|
if (context.dbSessionStrategy === 'gateway_only') {
|
|
9271
9312
|
throw new Error(
|
|
@@ -9290,6 +9331,7 @@ export async function readRuntimeSheetRowOutcomeCounts(
|
|
|
9290
9331
|
runId: context.runId,
|
|
9291
9332
|
playName: context.playName,
|
|
9292
9333
|
tableNamespace: input.tableNamespace,
|
|
9334
|
+
includeConditions: input.includeConditions,
|
|
9293
9335
|
}),
|
|
9294
9336
|
);
|
|
9295
9337
|
}
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts
CHANGED
|
@@ -1947,6 +1947,10 @@ async function readTerminalSheetRowOutcomes(input: {
|
|
|
1947
1947
|
completed: number;
|
|
1948
1948
|
failed: number;
|
|
1949
1949
|
total: number;
|
|
1950
|
+
conditions?: Record<
|
|
1951
|
+
string,
|
|
1952
|
+
import('../cell-provenance').PlayConditionCounts
|
|
1953
|
+
>;
|
|
1950
1954
|
}>
|
|
1951
1955
|
> {
|
|
1952
1956
|
const sheetNamespaces = [
|
|
@@ -1981,11 +1985,26 @@ async function readTerminalSheetRowOutcomes(input: {
|
|
|
1981
1985
|
completed: number;
|
|
1982
1986
|
failed: number;
|
|
1983
1987
|
total: number;
|
|
1988
|
+
conditions?: Record<
|
|
1989
|
+
string,
|
|
1990
|
+
import('../cell-provenance').PlayConditionCounts
|
|
1991
|
+
>;
|
|
1984
1992
|
}> = [];
|
|
1985
1993
|
for (const tableNamespace of sheetNamespaces) {
|
|
1986
1994
|
try {
|
|
1987
1995
|
const counts = await readRuntimeSheetRowOutcomeCounts(runtimeContext, {
|
|
1988
1996
|
tableNamespace,
|
|
1997
|
+
includeConditions: Boolean(
|
|
1998
|
+
(
|
|
1999
|
+
input.launch.contractSnapshot as {
|
|
2000
|
+
staticPipeline?: {
|
|
2001
|
+
docflow?: { nodes?: Array<{ kind: string; sketch?: boolean }> };
|
|
2002
|
+
};
|
|
2003
|
+
} | null
|
|
2004
|
+
)?.staticPipeline?.docflow?.nodes?.some(
|
|
2005
|
+
(node) => node.kind === 'decision' && !node.sketch,
|
|
2006
|
+
),
|
|
2007
|
+
),
|
|
1989
2008
|
});
|
|
1990
2009
|
outcomes.push({ tableNamespace, ...counts });
|
|
1991
2010
|
} catch (error) {
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts
CHANGED
|
@@ -43,7 +43,12 @@ import {
|
|
|
43
43
|
type PlayStaticPipeline,
|
|
44
44
|
type PlayStaticSubstep,
|
|
45
45
|
} from '../../plays/static-pipeline';
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
getStaticSubstepNodeId,
|
|
48
|
+
projectDocflowConditionCounts,
|
|
49
|
+
} from '../step-progress';
|
|
50
|
+
import type { PlayConditionCounts } from '../cell-provenance';
|
|
51
|
+
import { readRuntimeSheetRowOutcomeCounts } from '../runtime-api';
|
|
47
52
|
import { runtimeApiBaseUrlFromLaunch } from './runtime-api-origin';
|
|
48
53
|
|
|
49
54
|
// Patterns mirrored from runner events — they parse
|
|
@@ -232,6 +237,7 @@ export type PostgresSchedulerProgressReporter = {
|
|
|
232
237
|
completed: number;
|
|
233
238
|
failed: number;
|
|
234
239
|
total: number;
|
|
240
|
+
conditions?: Record<string, PlayConditionCounts>;
|
|
235
241
|
}>,
|
|
236
242
|
): void;
|
|
237
243
|
/**
|
|
@@ -737,6 +743,9 @@ export function createPostgresSchedulerProgressReporter(input: {
|
|
|
737
743
|
? { completedAt: current.completedAt }
|
|
738
744
|
: {}),
|
|
739
745
|
...(current.nodeIo !== undefined ? { nodeIo: current.nodeIo } : {}),
|
|
746
|
+
...(current.conditionCounts !== undefined
|
|
747
|
+
? { conditionCounts: current.conditionCounts }
|
|
748
|
+
: {}),
|
|
740
749
|
...(patch.completed !== undefined
|
|
741
750
|
? { completed: patch.completed }
|
|
742
751
|
: {}),
|
|
@@ -783,6 +792,9 @@ export function createPostgresSchedulerProgressReporter(input: {
|
|
|
783
792
|
? { completedAt: patch.completedAt }
|
|
784
793
|
: {}),
|
|
785
794
|
...(patch.nodeIo !== undefined ? { nodeIo: patch.nodeIo } : {}),
|
|
795
|
+
...(patch.conditionCounts !== undefined
|
|
796
|
+
? { conditionCounts: patch.conditionCounts }
|
|
797
|
+
: {}),
|
|
786
798
|
updatedAt: Date.now(),
|
|
787
799
|
},
|
|
788
800
|
};
|
|
@@ -1474,6 +1486,7 @@ export function createPostgresSchedulerProgressReporter(input: {
|
|
|
1474
1486
|
completed: number;
|
|
1475
1487
|
failed: number;
|
|
1476
1488
|
total: number;
|
|
1489
|
+
conditions?: Record<string, PlayConditionCounts>;
|
|
1477
1490
|
}> = [];
|
|
1478
1491
|
|
|
1479
1492
|
const applyTerminalSheetOutcomes = (
|
|
@@ -1482,6 +1495,7 @@ export function createPostgresSchedulerProgressReporter(input: {
|
|
|
1482
1495
|
completed: number;
|
|
1483
1496
|
failed: number;
|
|
1484
1497
|
total: number;
|
|
1498
|
+
conditions?: Record<string, PlayConditionCounts>;
|
|
1485
1499
|
}>,
|
|
1486
1500
|
): void => {
|
|
1487
1501
|
terminalSheetOutcomes = outcomes;
|
|
@@ -1491,6 +1505,13 @@ export function createPostgresSchedulerProgressReporter(input: {
|
|
|
1491
1505
|
// the two disagree; also the only terminal source when frames are missing
|
|
1492
1506
|
// (detached push runs) and liveNodeProgress is empty (zero-event runs).
|
|
1493
1507
|
const reconcileTerminalMapProgressFromSheetOutcomes = (): void => {
|
|
1508
|
+
const conditionCounts = projectDocflowConditionCounts(
|
|
1509
|
+
staticPipelineFromContractSnapshot(launch.contractSnapshot),
|
|
1510
|
+
terminalSheetOutcomes,
|
|
1511
|
+
);
|
|
1512
|
+
for (const [nodeId, counts] of Object.entries(conditionCounts)) {
|
|
1513
|
+
setNodeProgress(nodeId, { conditionCounts: counts });
|
|
1514
|
+
}
|
|
1494
1515
|
for (const outcome of terminalSheetOutcomes) {
|
|
1495
1516
|
const tableNamespace = outcome.tableNamespace.trim();
|
|
1496
1517
|
if (!tableNamespace) continue;
|
|
@@ -1650,6 +1671,7 @@ export function buildFailedTerminalSettledProgressEvents(input: {
|
|
|
1650
1671
|
tableNamespace: string;
|
|
1651
1672
|
completed: number;
|
|
1652
1673
|
failed: number;
|
|
1674
|
+
conditions?: Record<string, PlayConditionCounts>;
|
|
1653
1675
|
}>;
|
|
1654
1676
|
occurredAt: number;
|
|
1655
1677
|
}): PlayRunLedgerEvent[] {
|
|
@@ -1680,6 +1702,21 @@ export function buildFailedTerminalSettledProgressEvents(input: {
|
|
|
1680
1702
|
},
|
|
1681
1703
|
});
|
|
1682
1704
|
}
|
|
1705
|
+
for (const [stepId, conditionCounts] of Object.entries(
|
|
1706
|
+
projectDocflowConditionCounts(
|
|
1707
|
+
staticPipelineFromContractSnapshot(input.launch.contractSnapshot),
|
|
1708
|
+
input.outcomes,
|
|
1709
|
+
),
|
|
1710
|
+
)) {
|
|
1711
|
+
events.push({
|
|
1712
|
+
type: 'step.progress',
|
|
1713
|
+
runId: input.launch.runId,
|
|
1714
|
+
source: 'worker',
|
|
1715
|
+
occurredAt: input.occurredAt,
|
|
1716
|
+
stepId,
|
|
1717
|
+
progress: { conditionCounts },
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1683
1720
|
return events;
|
|
1684
1721
|
}
|
|
1685
1722
|
|
|
@@ -1724,6 +1761,56 @@ export async function collectGatewayRunnerTerminalProgressLedgerEvents(input: {
|
|
|
1724
1761
|
captured.update = update;
|
|
1725
1762
|
},
|
|
1726
1763
|
});
|
|
1764
|
+
// The gateway can win terminal before the worker reconciles the sheet.
|
|
1765
|
+
// Carry predicate summaries in that same durable terminal outbox prefix.
|
|
1766
|
+
const pipeline = staticPipelineFromContractSnapshot(
|
|
1767
|
+
input.launch.contractSnapshot,
|
|
1768
|
+
);
|
|
1769
|
+
if (
|
|
1770
|
+
pipeline?.docflow?.nodes.some(
|
|
1771
|
+
(node) => node.kind === 'decision' && !node.sketch,
|
|
1772
|
+
)
|
|
1773
|
+
) {
|
|
1774
|
+
const outcomes = [];
|
|
1775
|
+
const namespaces = new Set(
|
|
1776
|
+
(input.launch.preloadedDbSessions ?? [])
|
|
1777
|
+
.filter((session) => session.logicalTable === 'sheet_rows')
|
|
1778
|
+
.map((session) => session.tableNamespace),
|
|
1779
|
+
);
|
|
1780
|
+
for (const tableNamespace of namespaces) {
|
|
1781
|
+
try {
|
|
1782
|
+
outcomes.push({
|
|
1783
|
+
tableNamespace,
|
|
1784
|
+
...(await readRuntimeSheetRowOutcomeCounts(
|
|
1785
|
+
{
|
|
1786
|
+
baseUrl: input.launch.baseUrl,
|
|
1787
|
+
executorToken: input.launch.executorToken,
|
|
1788
|
+
orgId: input.launch.orgId,
|
|
1789
|
+
playName: input.launch.playName,
|
|
1790
|
+
runId: input.launch.runId,
|
|
1791
|
+
dbSessionStrategy: 'preloaded',
|
|
1792
|
+
preloadedDbSessions:
|
|
1793
|
+
input.launch.preloadedDbSessions ?? undefined,
|
|
1794
|
+
postgresSessionUnwrapKey:
|
|
1795
|
+
input.launch.preloadedDbSessionUnwrapKey ??
|
|
1796
|
+
input.launch.executorToken,
|
|
1797
|
+
},
|
|
1798
|
+
{ tableNamespace, includeConditions: true },
|
|
1799
|
+
)),
|
|
1800
|
+
});
|
|
1801
|
+
} catch (error) {
|
|
1802
|
+
console.warn(
|
|
1803
|
+
'[postgres-scheduler.terminal_condition_reconcile_failed]',
|
|
1804
|
+
{
|
|
1805
|
+
runId: input.launch.runId,
|
|
1806
|
+
tableNamespace,
|
|
1807
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1808
|
+
},
|
|
1809
|
+
);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
reporter.applyTerminalSheetOutcomes(outcomes);
|
|
1813
|
+
}
|
|
1727
1814
|
for (const event of input.events) reporter.onRunnerEvent(event);
|
|
1728
1815
|
await reporter.finalize(input.result, {
|
|
1729
1816
|
status: 'running',
|
|
@@ -334,7 +334,9 @@ const POSTGRES_SCHEDULER_SCHEMA_INIT_STATEMENT_TIMEOUT_MS = 60_000;
|
|
|
334
334
|
// index stays operator-prepared concurrently before marked-run admission.
|
|
335
335
|
// v56 adds a release-leading index for fixed-controller runner-terminal
|
|
336
336
|
// recovery, which scans only active runs for each release lane.
|
|
337
|
-
|
|
337
|
+
// v57 refreshes log-position lookups after the operator concurrently prepares
|
|
338
|
+
// channel-specific indexes; outgoing readers retain the existing GIN index.
|
|
339
|
+
export const POSTGRES_SCHEDULER_SCHEMA_VERSION = 57;
|
|
338
340
|
const POSTGRES_SCHEDULER_SCHEMA_MIGRATIONS_TABLE =
|
|
339
341
|
'scheduler_schema_migrations';
|
|
340
342
|
export const POSTGRES_SCHEDULER_OPEN_RECOVERY_INDEX =
|