deepline 0.3.266 → 0.3.268

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.
@@ -114,6 +114,7 @@ import type {
114
114
  CustomerDbQueryResult,
115
115
  DeeplineAgentModelDescription,
116
116
  InferenceQuote,
117
+ ChildRunSummary,
117
118
  } from './types.js';
118
119
  import { isStopAllPlayRunsDryRunResult } from './types.js';
119
120
  import type { MonitorDefinition } from './monitors.js';
@@ -662,6 +663,22 @@ export type RunsGetOptions = {
662
663
  failedLogLimit?: number;
663
664
  };
664
665
 
666
+ export type RunsChildrenOptions = {
667
+ /** Required authored `ctx.runPlayAsync` launch key. */
668
+ launchKey: string;
669
+ /** Opaque cursor returned by the preceding page. */
670
+ cursor?: string;
671
+ /** Rows to request (1–50; defaults to 50). */
672
+ limit?: number;
673
+ };
674
+
675
+ /** One bounded page of direct child Runs for one async launch. */
676
+ export type RunChildrenPage = {
677
+ children: ChildRunSummary[];
678
+ nextCursor: string | null;
679
+ hasMore: boolean;
680
+ };
681
+
665
682
  export type RunGetStatus =
666
683
  | {
667
684
  available: false;
@@ -890,6 +907,11 @@ export type RunsNamespace = {
890
907
  ) => Promise<import('./runs/receipts').RunToolReceiptsResponse>;
891
908
  /** Get current run status by public run id. */
892
909
  get: (runId: string, options?: RunsGetOptions) => Promise<PlayStatus>;
910
+ /** Read one bounded page of direct children for an async launch. */
911
+ children: (
912
+ parentRunId: string,
913
+ options: RunsChildrenOptions,
914
+ ) => Promise<RunChildrenPage>;
893
915
  /**
894
916
  * @deprecated Use `client.runs.get(runId)` for status, progress, logs, and results.
895
917
  * This scalar-only reader remains for compatibility with existing callers.
@@ -2648,6 +2670,8 @@ export class DeeplineClient {
2648
2670
  this.runs = {
2649
2671
  getReceipts: (runId, options) => this.getRunReceipts(runId, options),
2650
2672
  get: (runId, options) => this.getRunStatus(runId, options),
2673
+ children: (parentRunId, options) =>
2674
+ this.getRunChildren(parentRunId, options),
2651
2675
  status: (runId) => this.getRunLifecycleStatus(runId),
2652
2676
  list: (options) => this.listRuns(options),
2653
2677
  listPage: (options) => this.listRunsPage(options),
@@ -4220,6 +4244,39 @@ export class DeeplineClient {
4220
4244
  };
4221
4245
  }
4222
4246
 
4247
+ /** Read one paginated, launch-scoped page of direct child Runs. */
4248
+ async getRunChildren(
4249
+ parentRunId: string,
4250
+ options: RunsChildrenOptions,
4251
+ ): Promise<RunChildrenPage> {
4252
+ const launchKey = options.launchKey.trim();
4253
+ if (!launchKey) {
4254
+ throw new DeeplineError(
4255
+ 'runs.children requires a nonempty launchKey.',
4256
+ undefined,
4257
+ 'INVALID_CHILD_RUN_LAUNCH_KEY',
4258
+ );
4259
+ }
4260
+ if (
4261
+ options.limit !== undefined &&
4262
+ (!Number.isInteger(options.limit) ||
4263
+ options.limit < 1 ||
4264
+ options.limit > 50)
4265
+ ) {
4266
+ throw new DeeplineError(
4267
+ 'runs.children limit must be an integer from 1 to 50.',
4268
+ undefined,
4269
+ 'INVALID_CHILD_RUN_PAGE_LIMIT',
4270
+ );
4271
+ }
4272
+ const params = new URLSearchParams({ launchKey });
4273
+ if (options.cursor !== undefined) params.set('cursor', options.cursor);
4274
+ if (options.limit !== undefined) params.set('limit', String(options.limit));
4275
+ return this.http.get<RunChildrenPage>(
4276
+ `/api/v2/runs/${encodeURIComponent(parentRunId)}/children?${params.toString()}`,
4277
+ );
4278
+ }
4279
+
4223
4280
  /** Fetch only the legacy scalar lifecycle status for a run.
4224
4281
  *
4225
4282
  * @deprecated Use `client.runs.get(runId)` for the canonical run read.
@@ -144,6 +144,8 @@ export type {
144
144
  PlaysListPage,
145
145
  RunsLogsOptions,
146
146
  RunsLogsResult,
147
+ RunChildrenPage,
148
+ RunsChildrenOptions,
147
149
  RunsEventSearchOptions,
148
150
  RunsEventSearchEntry,
149
151
  RunsEventSearchResult,
@@ -156,6 +158,7 @@ export type {
156
158
  ExecutionRecovery,
157
159
  ExecutionByKeyResult,
158
160
  } from './client.js';
161
+ export type { ChildRunSummary } from './types.js';
159
162
 
160
163
  // ——— Monitors framework ———
161
164
  export { defineMonitor } from './monitors.js';
@@ -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.266',
203
+ version: '0.3.268',
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: {
@@ -265,6 +265,7 @@ type RuntimeApiRequest =
265
265
  schedulerBackend?: string | null;
266
266
  schedulerSchema?: string | null;
267
267
  runLogStore?: 'planet_scale';
268
+ runEventStore?: 'planet_scale';
268
269
  executionProfile?: string | null;
269
270
  runtimeReleaseId?: string | null;
270
271
  runtimeDeployVersion?: string | null;
@@ -25,7 +25,10 @@ import type {
25
25
  PlayRunnerRuntimeTiming,
26
26
  } from '../protocol';
27
27
  import { PROD_DEFAULT_RUNTIME_SCHEDULER_SCHEMA } from '../runtime-scheduler-topology';
28
- import { RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER } from './runtime-event-search';
28
+ import {
29
+ RUNTIME_EVENT_CANONICAL_RETENTION_INDEX_READY_MARKER,
30
+ RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER,
31
+ } from './runtime-event-search';
29
32
  import type { PlayRunnerRuntimeResource } from '../runner-backends/types';
30
33
  import {
31
34
  RuntimeSandboxOperationState,
@@ -317,7 +320,9 @@ const POSTGRES_SCHEDULER_SCHEMA_INIT_STATEMENT_TIMEOUT_MS = 60_000;
317
320
  // v53 refreshes the indexed runtime log reconciliation projection. Its query
318
321
  // indexes remain operator-prepared concurrently, outside shared bootstrap.
319
322
  // v54 expands the optional per-run canonical event-store marker.
320
- export const POSTGRES_SCHEDULER_SCHEMA_VERSION = 54;
323
+ // v55 refreshes the unified event journal projection. The canonical retention
324
+ // index stays operator-prepared concurrently before marked-run admission.
325
+ export const POSTGRES_SCHEDULER_SCHEMA_VERSION = 55;
321
326
  const POSTGRES_SCHEDULER_SCHEMA_MIGRATIONS_TABLE =
322
327
  'scheduler_schema_migrations';
323
328
  export const POSTGRES_SCHEDULER_OPEN_RECOVERY_INDEX =
@@ -985,6 +990,36 @@ function newRunLogStoreSql(
985
990
  ) THEN 'planet_scale' END`;
986
991
  }
987
992
 
993
+ /** Only new immutable admissions opt into the full typed event journal. */
994
+ function newRunEventStoreSql(
995
+ launchSql: 'launch_payload.launch_json',
996
+ options?: Pick<PostgresSchedulerOptions, 'schema'>,
997
+ ): string {
998
+ return `CASE WHEN ${launchSql} ? 'playReference' AND EXISTS (
999
+ SELECT 1 FROM pg_proc AS proc
1000
+ JOIN pg_namespace AS namespace ON namespace.oid = proc.pronamespace
1001
+ WHERE namespace.nspname = '${schemaName(options).replace(/'/g, "''")}'
1002
+ AND proc.proname = 'search_outbox_event'
1003
+ AND obj_description(proc.oid, 'pg_proc') = '${RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER.replace(/'/g, "''")}'
1004
+ ) AND EXISTS (
1005
+ SELECT 1 FROM pg_index AS index_row
1006
+ WHERE index_row.indexrelid = to_regclass('runtime_observability.runtime_events_canonical_retention_idx')
1007
+ AND index_row.indisready AND index_row.indisvalid
1008
+ AND obj_description(index_row.indexrelid, 'pg_class') = '${RUNTIME_EVENT_CANONICAL_RETENTION_INDEX_READY_MARKER.replace(/'/g, "''")}'
1009
+ ) AND to_regclass('runtime_observability.runtime_event_order_seq') IS NOT NULL
1010
+ AND EXISTS (
1011
+ SELECT 1 FROM pg_attribute AS event_column
1012
+ WHERE event_column.attrelid = to_regclass('runtime_observability.events')
1013
+ AND event_column.attname = 'event_seq' AND event_column.attnum > 0
1014
+ AND NOT event_column.attisdropped
1015
+ ) AND EXISTS (
1016
+ SELECT 1 FROM pg_attribute AS payload_column
1017
+ WHERE payload_column.attrelid = to_regclass('runtime_observability.events')
1018
+ AND payload_column.attname = 'event_payload' AND payload_column.attnum > 0
1019
+ AND NOT payload_column.attisdropped
1020
+ ) THEN 'planet_scale' END`;
1021
+ }
1022
+
988
1023
  function tableName(
989
1024
  table: string,
990
1025
  options?: Pick<PostgresSchedulerOptions, 'schema'>,
@@ -5041,7 +5076,8 @@ async function submitPostgresSchedulerRunTransaction(
5041
5076
  status,
5042
5077
  absurd_task_id,
5043
5078
  admission_json,
5044
- run_log_store
5079
+ run_log_store,
5080
+ run_event_store
5045
5081
  )
5046
5082
  SELECT $1, $2, $3, $4, $5, $6, $7, launch_payload.launch_json, coalesce(nullif(launch_payload.launch_json -> 'input', 'null'::jsonb), '{}'::jsonb), 'queued',
5047
5083
  (SELECT task_id FROM task_spawn),
@@ -5054,7 +5090,8 @@ async function submitPostgresSchedulerRunTransaction(
5054
5090
  'coordinatorInternalToken',
5055
5091
  'vercelProtectionBypassToken'
5056
5092
  ]::text[],
5057
- ${newRunLogStoreSql('launch_payload.launch_json', options)}
5093
+ ${newRunLogStoreSql('launch_payload.launch_json', options)},
5094
+ ${newRunEventStoreSql('launch_payload.launch_json', options)}
5058
5095
  FROM admission
5059
5096
  CROSS JOIN launch_payload
5060
5097
  WHERE NOT existing_run
@@ -5062,7 +5099,7 @@ async function submitPostgresSchedulerRunTransaction(
5062
5099
  AND parent_accepting
5063
5100
  AND NOT ${existingOnlySql}
5064
5101
  ON CONFLICT (run_id) DO NOTHING
5065
- RETURNING run_id, absurd_task_id, run_log_store
5102
+ RETURNING run_id, absurd_task_id, run_log_store, run_event_store
5066
5103
  ), run_recovery AS (
5067
5104
  UPDATE ${tableName('runs', options)} AS runs
5068
5105
  SET absurd_task_id = (SELECT task_id FROM task_spawn),
@@ -5111,6 +5148,7 @@ async function submitPostgresSchedulerRunTransaction(
5111
5148
  'schedulerBackend', launch_payload.launch_json ->> 'schedulerBackend',
5112
5149
  'schedulerSchema', COALESCE(launch_payload.launch_json ->> 'schedulerSchema', '${schemaName(options)}'),
5113
5150
  'runLogStore', run_insert.run_log_store,
5151
+ 'runEventStore', run_insert.run_event_store,
5114
5152
  'executionProfile', launch_payload.launch_json ->> 'executionProfile',
5115
5153
  'runtimeReleaseId', launch_payload.launch_json ->> 'runtimeReleaseId',
5116
5154
  'runtimeDeployVersion', launch_payload.launch_json ->> 'runtimeDeployVersion',
@@ -6113,7 +6151,7 @@ export async function firePostgresSchedulerCronSchedule(
6113
6151
  INSERT INTO ${tableName('runs', options)} (
6114
6152
  run_id, org_id, play_id, play_name, graph_hash, runtime_profile,
6115
6153
  artifact_storage_key, launch_json, input_json, status,
6116
- absurd_task_id, admission_json, run_log_store
6154
+ absurd_task_id, admission_json, run_log_store, run_event_store
6117
6155
  )
6118
6156
  SELECT $5::text,
6119
6157
  launch_payload.launch_json ->> 'orgId',
@@ -6135,12 +6173,13 @@ export async function firePostgresSchedulerCronSchedule(
6135
6173
  'coordinatorInternalToken',
6136
6174
  'vercelProtectionBypassToken'
6137
6175
  ]::text[],
6138
- ${newRunLogStoreSql('launch_payload.launch_json', options)}
6176
+ ${newRunLogStoreSql('launch_payload.launch_json', options)},
6177
+ ${newRunEventStoreSql('launch_payload.launch_json', options)}
6139
6178
  FROM occurrence
6140
6179
  CROSS JOIN launch_payload
6141
6180
  WHERE occurrence.schedule_current
6142
6181
  AND NOT occurrence.existing_run
6143
- RETURNING run_id, run_log_store
6182
+ RETURNING run_id, run_log_store, run_event_store
6144
6183
  ), occurrence_admitted AS MATERIALIZED (
6145
6184
  SELECT true AS admitted
6146
6185
  FROM occurrence
@@ -6188,6 +6227,7 @@ export async function firePostgresSchedulerCronSchedule(
6188
6227
  'schedulerBackend', launch_payload.launch_json ->> 'schedulerBackend',
6189
6228
  'schedulerSchema', COALESCE(launch_payload.launch_json ->> 'schedulerSchema', '${schemaName(options)}'),
6190
6229
  'runLogStore', run_insert.run_log_store,
6230
+ 'runEventStore', run_insert.run_event_store,
6191
6231
  'executionProfile', launch_payload.launch_json ->> 'executionProfile',
6192
6232
  'runtimeReleaseId', launch_payload.launch_json ->> 'runtimeReleaseId',
6193
6233
  'runtimeDeployVersion', launch_payload.launch_json ->> 'runtimeDeployVersion',
@@ -18040,18 +18080,23 @@ export async function markPostgresSchedulerOutboxDeliveredRows(
18040
18080
  }>(
18041
18081
  `
18042
18082
  WITH delivered AS (
18043
- UPDATE ${tableName('outbox', options)}
18083
+ UPDATE ${tableName('outbox', options)} AS outbox
18044
18084
  SET delivered_at = now(),
18045
18085
  next_attempt_at = NULL,
18046
18086
  last_error_json = NULL,
18047
18087
  lease_owner = NULL,
18048
- lease_expires_at = NULL
18049
- WHERE event_id = ANY($1::text[])
18050
- AND delivered_at IS NULL
18051
- AND ($2::text IS NULL OR lease_owner = $2)
18052
- RETURNING event_id,
18053
- event_type,
18054
- (extract(epoch FROM (delivered_at - created_at)) * 1000)::float8
18088
+ lease_expires_at = NULL,
18089
+ payload_json = CASE WHEN EXISTS (
18090
+ SELECT 1 FROM ${tableName('runs', options)} AS run
18091
+ WHERE run.run_id = outbox.run_id
18092
+ AND run.run_event_store = 'planet_scale'
18093
+ ) THEN '{}'::jsonb ELSE outbox.payload_json END
18094
+ WHERE outbox.event_id = ANY($1::text[])
18095
+ AND outbox.delivered_at IS NULL
18096
+ AND ($2::text IS NULL OR outbox.lease_owner = $2)
18097
+ RETURNING outbox.event_id,
18098
+ outbox.event_type,
18099
+ (extract(epoch FROM (outbox.delivered_at - outbox.created_at)) * 1000)::float8
18055
18100
  AS lag_ms
18056
18101
  )
18057
18102
  SELECT event_id,
@@ -19238,6 +19283,9 @@ async function projectPostgresSchedulerCreatedEvent(
19238
19283
  ...(value('runLogStore') === 'planet_scale'
19239
19284
  ? { runLogStore: 'planet_scale' as const }
19240
19285
  : {}),
19286
+ ...(value('runEventStore') === 'planet_scale'
19287
+ ? { runEventStore: 'planet_scale' as const }
19288
+ : {}),
19241
19289
  executionProfile: value('executionProfile'),
19242
19290
  runtimeReleaseId: value('runtimeReleaseId'),
19243
19291
  runtimeDeployVersion: value('runtimeDeployVersion'),