deepline 0.1.20 → 0.1.21

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.
@@ -163,6 +163,15 @@ function mapLegacyTemporalStatus(status: string): PlayStatus['status'] {
163
163
  }
164
164
  }
165
165
 
166
+ function decodeBase64Bytes(value: string): Uint8Array {
167
+ const binary = atob(value);
168
+ const bytes = new Uint8Array(binary.length);
169
+ for (let index = 0; index < binary.length; index += 1) {
170
+ bytes[index] = binary.charCodeAt(index);
171
+ }
172
+ return bytes;
173
+ }
174
+
166
175
  /**
167
176
  * Low-level client for the Deepline REST API.
168
177
  *
@@ -849,9 +858,34 @@ export class DeeplineClient {
849
858
  bytes: number;
850
859
  }>,
851
860
  ): Promise<PlayStagedFileRef[]> {
852
- const response = await this.http.post<{ files: PlayStagedFileRef[] }>(
861
+ const formData = new FormData();
862
+ formData.set(
863
+ 'metadata',
864
+ JSON.stringify({
865
+ files: files.map((file, index) => ({
866
+ index,
867
+ logicalPath: file.logicalPath,
868
+ contentHash: file.contentHash,
869
+ contentType: file.contentType,
870
+ bytes: file.bytes,
871
+ })),
872
+ }),
873
+ );
874
+ for (const [index, file] of files.entries()) {
875
+ const bytes = decodeBase64Bytes(file.contentBase64);
876
+ const body = bytes.buffer.slice(
877
+ bytes.byteOffset,
878
+ bytes.byteOffset + bytes.byteLength,
879
+ ) as ArrayBuffer;
880
+ formData.set(
881
+ `file:${index}`,
882
+ new Blob([body], { type: file.contentType }),
883
+ file.logicalPath,
884
+ );
885
+ }
886
+ const response = await this.http.postFormData<{ files: PlayStagedFileRef[] }>(
853
887
  '/api/v2/plays/files/stage',
854
- { files },
888
+ formData,
855
889
  );
856
890
  return response.files;
857
891
  }
@@ -896,9 +930,17 @@ export class DeeplineClient {
896
930
  * console.log(`Logs: ${status.progress?.logs.length ?? 0} lines`);
897
931
  * ```
898
932
  */
899
- async getPlayStatus(workflowId: string): Promise<PlayStatus> {
933
+ async getPlayStatus(
934
+ workflowId: string,
935
+ options?: { billing?: boolean },
936
+ ): Promise<PlayStatus> {
937
+ const params = new URLSearchParams();
938
+ if (options?.billing === false) {
939
+ params.set('billing', 'false');
940
+ }
941
+ const query = params.size > 0 ? `?${params.toString()}` : '';
900
942
  const response = await this.http.get<Record<string, unknown>>(
901
- `/api/v2/plays/run/${encodeURIComponent(workflowId)}`,
943
+ `/api/v2/plays/run/${encodeURIComponent(workflowId)}${query}`,
902
944
  );
903
945
  return normalizePlayStatus(response);
904
946
  }
@@ -31,6 +31,7 @@ import {
31
31
  interface RequestOptions {
32
32
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
33
33
  body?: unknown;
34
+ formData?: FormData;
34
35
  headers?: Record<string, string>;
35
36
  /** Per-request timeout override in milliseconds. */
36
37
  timeout?: number;
@@ -150,7 +151,12 @@ export class HttpClient {
150
151
  const response = await fetch(candidateUrl, {
151
152
  method,
152
153
  headers,
153
- body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,
154
+ body:
155
+ options?.formData !== undefined
156
+ ? options.formData
157
+ : options?.body !== undefined
158
+ ? JSON.stringify(options.body)
159
+ : undefined,
154
160
  signal: controller.signal,
155
161
  });
156
162
 
@@ -317,6 +323,18 @@ export class HttpClient {
317
323
  });
318
324
  }
319
325
 
326
+ async postFormData<T = unknown>(
327
+ path: string,
328
+ formData: FormData,
329
+ headers?: Record<string, string>,
330
+ ): Promise<T> {
331
+ return this.request<T>(path, {
332
+ method: 'POST',
333
+ formData,
334
+ headers,
335
+ });
336
+ }
337
+
320
338
  /**
321
339
  * Send a DELETE request.
322
340
  *
@@ -33,6 +33,7 @@
33
33
 
34
34
  import type {
35
35
  PlayHarnessRpc,
36
+ PreloadedRuntimeDbSessionInput,
36
37
  RuntimeApiCallInput,
37
38
  RuntimeApiCallResult,
38
39
  RuntimePayloadSchemaId,
@@ -121,6 +122,17 @@ export async function harnessRuntimeApiCall(
121
122
  return requireBinding().runtimeApiCall(input);
122
123
  }
123
124
 
125
+ /**
126
+ * Warm Postgres sessions in the long-lived harness Worker. This preserves the
127
+ * map fast path without bundling the Neon client into every dynamic play.
128
+ */
129
+ export async function harnessPrewarmPostgresSessions(input: {
130
+ executorToken: string;
131
+ sessions: PreloadedRuntimeDbSessionInput[];
132
+ }): Promise<{ ok: true; sessions: number }> {
133
+ return requireBinding().prewarmPostgresSessions(input);
134
+ }
135
+
124
136
  /**
125
137
  * Start or continue a map dataset write inside the harness, so this call
126
138
  * skips per-play callback overhead for heavy Postgres writes.
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.20";
1
+ export const SDK_VERSION = "0.1.21";
2
2
  export const SDK_API_CONTRACT = "2026-05-runs-v2";
@@ -17,6 +17,7 @@ import type {
17
17
  } from './ctx-types';
18
18
  import type { ExecutionPlan } from './execution-plan';
19
19
  import type { PlayRuntimeManifestMap } from '../plays/compiler-manifest';
20
+ import type { PreloadedRuntimeDbSession } from './db-session';
20
21
 
21
22
  export const PLAY_SCHEDULER_BACKENDS = {
22
23
  temporal: 'temporal',
@@ -79,6 +80,7 @@ export type PlaySchedulerSubmitInput = {
79
80
  executionPlan?: ExecutionPlan | null;
80
81
  childPlayManifests?: PlayRuntimeManifestMap | null;
81
82
  playCallGovernance?: PlayCallGovernanceSnapshot | null;
83
+ preloadedDbSessions?: PreloadedRuntimeDbSession[] | null;
82
84
  /** Optional immutable Worker module source for local Dynamic Worker loading. */
83
85
  dynamicWorkerCode?: string | null;
84
86
  executorToken: string;
@@ -109,12 +111,6 @@ export type PlaySchedulerProgressEvent =
109
111
 
110
112
  export type PlaySchedulerRunHandle = {
111
113
  runId: string;
112
- /**
113
- * Optional snapshot of the run's state captured during submit() so callers
114
- * can skip an immediate follow-up status read. Populated by backends that
115
- * piggyback the read on the create round-trip (currently cf-workflows).
116
- */
117
- initialState?: Record<string, unknown> | null;
118
114
  /**
119
115
  * Stream live progress events. Implementations may use SSE, polling, etc.
120
116
  * The contract: yields events in order until terminal status.
@@ -156,6 +152,7 @@ export interface PlaySchedulerBackend {
156
152
  options?: {
157
153
  coordinatorUrl?: string | null;
158
154
  coordinatorInternalToken?: string | null;
155
+ initialState?: Record<string, unknown> | null;
159
156
  },
160
157
  ): Promise<PlaySchedulerRunHandle>;
161
158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {