deepline 0.2.20 → 0.2.22

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.
@@ -607,6 +607,22 @@ export type PlaySecretMetadata = {
607
607
  export type RunsNamespace = {
608
608
  /** Get current run status by public run id. */
609
609
  get: (runId: string, options?: RunsGetOptions) => Promise<PlayStatus>;
610
+ /** Explicitly read the retained original input (may include customer data). */
611
+ input: (runId: string) => Promise<{
612
+ runId: string;
613
+ input: Record<string, unknown> | unknown[];
614
+ bytes: number;
615
+ sha256: string | null;
616
+ replayedFromRunId: string | null;
617
+ }>;
618
+ /** Start a fresh run from a prior run's retained input and pinned revision. */
619
+ rerun: (runId: string) => Promise<{
620
+ runId: string;
621
+ replayedFromRunId: string;
622
+ revisionId: string | null;
623
+ status: string;
624
+ next: { inspect: string; input: string };
625
+ }>;
610
626
  /** List runs for one play, optionally filtered by status. */
611
627
  list: (options: RunsListOptions) => Promise<PlayRunListItem[]>;
612
628
  /** Stream run events and return the latest/terminal run status. */
@@ -1569,6 +1585,8 @@ export class DeeplineClient {
1569
1585
  list: (options) => this.listRuns(options),
1570
1586
  tail: (runId, options) => this.tailRun(runId, options),
1571
1587
  logs: (runId, options) => this.getRunLogs(runId, options),
1588
+ input: (runId) => this.getRunInput(runId),
1589
+ rerun: (runId) => this.rerun(runId),
1572
1590
  exportDatasetRows: (input) => this.getPlaySheetRows(input),
1573
1591
  stop: (runId, options) => this.stopRun(runId, options),
1574
1592
  stopAll: (options) => this.stopAllRuns(options),
@@ -3452,6 +3470,31 @@ export class DeeplineClient {
3452
3470
  }
3453
3471
  }
3454
3472
 
3473
+ /** Get the exact original input retained for a run. This is intentionally separate from status. */
3474
+ async getRunInput(runId: string): Promise<{
3475
+ runId: string;
3476
+ input: Record<string, unknown> | unknown[];
3477
+ bytes: number;
3478
+ sha256: string | null;
3479
+ replayedFromRunId: string | null;
3480
+ }> {
3481
+ return this.http.get(`/api/v2/runs/${encodeURIComponent(runId)}/input`);
3482
+ }
3483
+
3484
+ /** Start a fresh run from a prior run's retained input and pinned revision. */
3485
+ async rerun(runId: string): Promise<{
3486
+ runId: string;
3487
+ replayedFromRunId: string;
3488
+ revisionId: string | null;
3489
+ status: string;
3490
+ next: { inspect: string; input: string };
3491
+ }> {
3492
+ return this.http.post(
3493
+ `/api/v2/runs/${encodeURIComponent(runId)}/rerun`,
3494
+ {},
3495
+ );
3496
+ }
3497
+
3455
3498
  /**
3456
3499
  * Fetch persisted logs for a run using the public runs resource model.
3457
3500
  *
@@ -160,7 +160,7 @@ export const SDK_RELEASE = {
160
160
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
161
161
  // exposed storage-dependent synchronous access. This deliberate minor
162
162
  // release keeps lazy paging semantics independent of row residency.
163
- version: '0.2.20',
163
+ version: '0.2.22',
164
164
  contracts: {
165
165
  api: {
166
166
  name: 'sdk-http-api',
@@ -149,6 +149,10 @@ type RuntimeApiRequest =
149
149
  maxCreditsPerRun?: number | null;
150
150
  staticPipeline?: unknown;
151
151
  source?: 'published' | 'ad_hoc' | 'draft';
152
+ inputFileId?: string;
153
+ inputBytes?: number;
154
+ inputSha256?: string;
155
+ replayedFromRunId?: string | null;
152
156
  }
153
157
  | ({
154
158
  action: 'save_results';
@@ -1598,6 +1602,10 @@ export async function startRunViaAppRuntime(
1598
1602
  maxCreditsPerRun?: number | null;
1599
1603
  staticPipeline?: unknown;
1600
1604
  source?: 'published' | 'ad_hoc' | 'draft';
1605
+ inputFileId?: string;
1606
+ inputBytes?: number;
1607
+ inputSha256?: string;
1608
+ replayedFromRunId?: string | null;
1601
1609
  idempotencyKey?: string;
1602
1610
  },
1603
1611
  ): Promise<void> {
@@ -49,6 +49,11 @@ export type PlaySchedulerSubmitInput = {
49
49
  artifactHash: string;
50
50
  graphHash: string;
51
51
  input: PlayRunInputPayload;
52
+ /** Convex metadata for the exact input saved before scheduler submission. */
53
+ inputFileId?: string;
54
+ inputBytes?: number;
55
+ inputSha256?: string;
56
+ replayedFromRunId?: string | null;
52
57
  /** Start a fresh run graph and recompute runtime-sheet rows. */
53
58
  force?: boolean;
54
59
  /** Explicit cache bypass for completed ctx.tools.execute receipts. */
@@ -14,6 +14,7 @@ import {
14
14
  type NodeSafeFetchOptions = {
15
15
  maxRedirects?: number;
16
16
  maxResponseBytes?: number;
17
+ truncateResponseBody?: boolean;
17
18
  sensitiveHeaders?: Iterable<string>;
18
19
  validateUrl?: (url: URL) => void;
19
20
  };
@@ -187,6 +188,7 @@ function createRequest(
187
188
  init: RequestInit,
188
189
  prepared: PreparedBody,
189
190
  maxResponseBytes: number | undefined,
191
+ truncateResponseBody: boolean,
190
192
  ): Promise<Response> {
191
193
  return new Promise((resolve, reject) => {
192
194
  const transport = url.protocol === 'https:' ? https : http;
@@ -208,7 +210,8 @@ function createRequest(
208
210
  !noBodyResponse &&
209
211
  maxResponseBytes !== undefined &&
210
212
  Number.isFinite(contentLength) &&
211
- contentLength > maxResponseBytes
213
+ contentLength > maxResponseBytes &&
214
+ !truncateResponseBody
212
215
  ) {
213
216
  response.resume();
214
217
  reject(
@@ -219,12 +222,27 @@ function createRequest(
219
222
 
220
223
  const chunks: Buffer[] = [];
221
224
  let receivedBytes = 0;
225
+ let settled = false;
226
+ const resolveResponse = () => {
227
+ if (settled) return;
228
+ settled = true;
229
+ resolve(
230
+ new Response(noBodyResponse ? null : Buffer.concat(chunks), {
231
+ status,
232
+ statusText: response.statusMessage,
233
+ headers: response.headers as HeadersInit,
234
+ }),
235
+ );
236
+ };
222
237
  response.on('data', (chunk) => {
238
+ if (settled) return;
223
239
  const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
240
+ const previousReceivedBytes = receivedBytes;
224
241
  receivedBytes += buffer.byteLength;
225
242
  if (
226
243
  maxResponseBytes !== undefined &&
227
- receivedBytes > maxResponseBytes
244
+ receivedBytes > maxResponseBytes &&
245
+ !truncateResponseBody
228
246
  ) {
229
247
  response.destroy(
230
248
  new Error(
@@ -234,19 +252,29 @@ function createRequest(
234
252
  return;
235
253
  }
236
254
  if (!noBodyResponse) {
237
- chunks.push(buffer);
255
+ if (maxResponseBytes !== undefined && truncateResponseBody) {
256
+ const remainingBytes = Math.max(
257
+ 0,
258
+ maxResponseBytes - previousReceivedBytes,
259
+ );
260
+ if (remainingBytes > 0) {
261
+ chunks.push(buffer.subarray(0, remainingBytes));
262
+ }
263
+ if (receivedBytes >= maxResponseBytes) {
264
+ resolveResponse();
265
+ response.destroy();
266
+ }
267
+ } else {
268
+ chunks.push(buffer);
269
+ }
238
270
  }
239
271
  });
240
- response.on('error', reject);
241
- response.on('end', () => {
242
- resolve(
243
- new Response(noBodyResponse ? null : Buffer.concat(chunks), {
244
- status,
245
- statusText: response.statusMessage,
246
- headers: response.headers as HeadersInit,
247
- }),
248
- );
272
+ response.on('error', (error) => {
273
+ if (settled) return;
274
+ settled = true;
275
+ reject(error);
249
276
  });
277
+ response.on('end', resolveResponse);
250
278
  },
251
279
  );
252
280
 
@@ -299,6 +327,7 @@ export async function safeOutboundFetch(
299
327
  const redirectMode = init.redirect ?? 'follow';
300
328
  const maxRedirects = options.maxRedirects ?? 10;
301
329
  const maxResponseBytes = options.maxResponseBytes;
330
+ const truncateResponseBody = options.truncateResponseBody === true;
302
331
  const validateUrl = options.validateUrl;
303
332
  let currentUrl = assertPublicHttpUrl(input);
304
333
  let currentInit: RequestInit = { ...init, redirect: 'manual' };
@@ -321,6 +350,7 @@ export async function safeOutboundFetch(
321
350
  currentInit,
322
351
  await prepareBody(currentInit),
323
352
  maxResponseBytes,
353
+ truncateResponseBody,
324
354
  );
325
355
 
326
356
  Object.defineProperty(response, 'url', {