deepline 0.1.7 → 0.1.9

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.
@@ -89,6 +89,7 @@ import {
89
89
  type ToolExecuteResult,
90
90
  type ToolResultMetadataInput,
91
91
  } from './runtime/tool-result';
92
+ import { coordinatorRequestHeaders } from '../../../shared_libs/play-runtime/coordinator-headers';
92
93
 
93
94
  // The play's default export. The bundler injects this — see bundle-play-file.ts.
94
95
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -130,6 +131,8 @@ type RunRequest = {
130
131
  playCallGovernance?: PlayCallGovernanceSnapshot | null;
131
132
  /** Cloudflare coordinator URL for direct Workflow control-plane signals. */
132
133
  coordinatorUrl?: string | null;
134
+ /** Request-scoped coordinator auth token for preview/dev direct control calls. */
135
+ coordinatorInternalToken?: string | null;
133
136
  /**
134
137
  * Total input rows known at submit time, when the dispatcher can count them.
135
138
  * `undefined` when the input streams from R2 (unknown row count).
@@ -761,6 +764,12 @@ async function submitChildPlayThroughCoordinator(input: {
761
764
  logs?: string[];
762
765
  timings?: Array<{ phase: string; ms: number }>;
763
766
  }> {
767
+ if (cachedCoordinatorBinding) {
768
+ if (!isRecord(input.body)) {
769
+ throw new Error('ctx.runPlay child submit requires an object body.');
770
+ }
771
+ return cachedCoordinatorBinding.submitChild(input.req.runId, input.body);
772
+ }
764
773
  const coordinatorUrl = input.req.coordinatorUrl?.trim();
765
774
  if (coordinatorUrl) {
766
775
  // Keep child plays on the same coordinator/Workflow submit path as
@@ -772,8 +781,12 @@ async function submitChildPlayThroughCoordinator(input: {
772
781
  {
773
782
  method: 'POST',
774
783
  headers: {
775
- 'content-type': 'application/json',
776
784
  'x-deepline-request-id': makeRequestId(),
785
+ ...coordinatorRequestHeaders({
786
+ runId: input.req.runId,
787
+ contentType: 'application/json',
788
+ internalToken: input.req.coordinatorInternalToken,
789
+ }),
777
790
  },
778
791
  body: JSON.stringify(input.body),
779
792
  },
@@ -796,14 +809,8 @@ async function submitChildPlayThroughCoordinator(input: {
796
809
  }
797
810
  return parsed;
798
811
  }
799
- if (cachedCoordinatorBinding) {
800
- if (!isRecord(input.body)) {
801
- throw new Error('ctx.runPlay child submit requires an object body.');
802
- }
803
- return cachedCoordinatorBinding.submitChild(input.req.runId, input.body);
804
- }
805
812
  throw new Error(
806
- 'ctx.runPlay child submit requires coordinatorUrl in the cf-workflows runtime.',
813
+ 'ctx.runPlay child submit requires a coordinator binding in the cf-workflows runtime.',
807
814
  );
808
815
  }
809
816
 
@@ -948,7 +955,6 @@ async function signalParentPlayTerminal(input: {
948
955
  : {}),
949
956
  emittedAt: nowMs(),
950
957
  };
951
- const coordinatorUrl = input.req.coordinatorUrl?.trim();
952
958
  const signalBody = {
953
959
  signal: 'integration_event',
954
960
  eventKey,
@@ -958,6 +964,7 @@ async function signalParentPlayTerminal(input: {
958
964
  await cachedCoordinatorBinding.signal(governance.parentRunId, signalBody);
959
965
  return;
960
966
  }
967
+ const coordinatorUrl = input.req.coordinatorUrl?.trim();
961
968
  if (coordinatorUrl) {
962
969
  const res = await fetch(
963
970
  `${coordinatorUrl.replace(/\/$/, '')}/workflow/${encodeURIComponent(
@@ -966,26 +973,27 @@ async function signalParentPlayTerminal(input: {
966
973
  {
967
974
  method: 'POST',
968
975
  headers: {
969
- 'content-type': 'application/json',
970
976
  'x-deepline-request-id': makeRequestId(),
977
+ ...coordinatorRequestHeaders({
978
+ runId: governance.parentRunId,
979
+ contentType: 'application/json',
980
+ internalToken: input.req.coordinatorInternalToken,
981
+ }),
971
982
  },
972
983
  body: JSON.stringify(signalBody),
973
984
  },
974
985
  );
975
- if (!res.ok) {
976
- const text = await res.text().catch(() => '');
977
- throw new Error(
978
- `Coordinator signal ${res.status}: ${text.slice(0, 800)}`,
979
- );
986
+ if (res.ok) {
987
+ return;
980
988
  }
981
- return;
989
+ const text = await res.text().catch(() => '');
990
+ throw new Error(
991
+ text.slice(0, 800) || `Coordinator parent signal failed with ${res.status}.`,
992
+ );
982
993
  }
983
- await postDeeplineApi(input.req, '/api/v2/plays/run/signal', {
984
- workflowId: governance.parentRunId,
985
- signal: 'integration_event',
986
- eventKey,
987
- data,
988
- });
994
+ throw new Error(
995
+ 'Child play terminal signaling requires a coordinator binding in the cf-workflows runtime.',
996
+ );
989
997
  }
990
998
 
991
999
  async function executeTool(
@@ -4483,6 +4491,11 @@ function runRequestFromWorkflowParams(
4483
4491
  typeof params.coordinatorUrl === 'string' && params.coordinatorUrl.trim()
4484
4492
  ? params.coordinatorUrl.trim()
4485
4493
  : null,
4494
+ coordinatorInternalToken:
4495
+ typeof params.coordinatorInternalToken === 'string' &&
4496
+ params.coordinatorInternalToken.trim()
4497
+ ? params.coordinatorInternalToken.trim()
4498
+ : null,
4486
4499
  totalRows:
4487
4500
  typeof params.totalRows === 'number' && Number.isFinite(params.totalRows)
4488
4501
  ? params.totalRows
@@ -968,9 +968,16 @@ async function startAndWaitForPlayCompletionByStream(input: {
968
968
  const dashboardUrl =
969
969
  getDashboardUrlFromLiveEvent(event) ??
970
970
  buildPlayDashboardUrl(input.client.baseUrl, input.playName);
971
- input.progress.phase(
972
- `loading play on ${dashboardUrl}`,
973
- );
971
+ if (!input.jsonOutput) {
972
+ writeStartedPlayRun({
973
+ runId: workflowId,
974
+ playName: input.playName,
975
+ dashboardUrl,
976
+ jsonOutput: false,
977
+ progress: input.progress,
978
+ });
979
+ }
980
+ input.progress.phase(`loading play on ${dashboardUrl}`);
974
981
  emittedDashboardUrl = true;
975
982
  }
976
983
  assertPlayWaitNotTimedOut({
@@ -1100,8 +1107,8 @@ async function waitForPlayCompletionByPolling(input: {
1100
1107
  const now = Date.now();
1101
1108
  if (now - lastTransientPollWarningAt >= 30_000) {
1102
1109
  const message = error instanceof Error ? error.message : String(error);
1103
- process.stderr.write(
1104
- `[play tail] transient status poll failed; retrying: ${message}\n`,
1110
+ input.progress.writeLine(
1111
+ `[play tail] transient status poll failed; retrying: ${message}`,
1105
1112
  );
1106
1113
  lastTransientPollWarningAt = now;
1107
1114
  }
@@ -1787,6 +1794,7 @@ function writeStartedPlayRun(input: {
1787
1794
  statusUrl?: string;
1788
1795
  dashboardUrl?: string;
1789
1796
  jsonOutput: boolean;
1797
+ progress?: CliProgress;
1790
1798
  }): void {
1791
1799
  const payload = {
1792
1800
  runId: input.runId,
@@ -1815,7 +1823,12 @@ function writeStartedPlayRun(input: {
1815
1823
  lines.push(` play page: ${input.dashboardUrl}`);
1816
1824
  }
1817
1825
 
1818
- console.log(lines.join('\n'));
1826
+ const output = lines.join('\n');
1827
+ if (input.progress) {
1828
+ input.progress.writeLine(output, process.stdout);
1829
+ return;
1830
+ }
1831
+ console.log(output);
1819
1832
  }
1820
1833
 
1821
1834
  function parsePlayRunOptions(args: string[]): PlayRunCommandOptions {
@@ -2188,6 +2201,7 @@ async function handleFileBackedRun(
2188
2201
  statusUrl: started.statusUrl,
2189
2202
  dashboardUrl,
2190
2203
  jsonOutput: options.jsonOutput,
2204
+ progress,
2191
2205
  });
2192
2206
  return 0;
2193
2207
  }
@@ -2303,6 +2317,7 @@ async function handleNamedRun(options: PlayRunCommandOptions): Promise<number> {
2303
2317
  statusUrl: started.statusUrl,
2304
2318
  dashboardUrl,
2305
2319
  jsonOutput: options.jsonOutput,
2320
+ progress,
2306
2321
  });
2307
2322
  return 0;
2308
2323
  }
@@ -56,6 +56,20 @@ export class CliProgress {
56
56
  }
57
57
  }
58
58
 
59
+ writeLine(line: string, stream: NodeJS.WriteStream = process.stderr): void {
60
+ if (!this.enabled || !this.interactive) {
61
+ stream.write(`${line}\n`);
62
+ return;
63
+ }
64
+ const activeMessage = this.lastMessage;
65
+ this.worker?.terminate().catch(() => undefined);
66
+ this.worker = null;
67
+ stream.write(`\r\x1b[2K${line}\n`);
68
+ if (activeMessage) {
69
+ this.startWorker().postMessage({ type: 'phase', message: activeMessage });
70
+ }
71
+ }
72
+
59
73
  private settle(mark: '✓' | '✗'): void {
60
74
  if (!this.enabled || !this.lastMessage) {
61
75
  return;
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
+ import { getActiveCliProgress } from './progress.js';
5
6
  import { baseUrlSlug } from '../config.js';
6
7
 
7
8
  const CHECK_TIMEOUT_MS = 3_000;
@@ -128,10 +129,13 @@ export async function syncSdkSkillsIfNeeded(baseUrl: string): Promise<void> {
128
129
  const update = await fetchSkillsUpdate(baseUrl, localVersion);
129
130
  if (!update?.needsUpdate || !update.remoteVersion) return;
130
131
 
131
- process.stderr.write('SDK skills changed; syncing deepline-sdk skill...\n');
132
+ const progress = getActiveCliProgress();
133
+ progress?.writeLine('SDK skills changed; syncing deepline-sdk skill...') ??
134
+ process.stderr.write('SDK skills changed; syncing deepline-sdk skill...\n');
132
135
  const installed = await runSkillsInstall(baseUrl);
133
136
  if (!installed) return;
134
137
 
135
138
  writeLocalSkillsVersion(baseUrl, update.remoteVersion);
136
- process.stderr.write('SDK skills are up to date.\n');
139
+ progress?.writeLine('SDK skills are up to date.') ??
140
+ process.stderr.write('SDK skills are up to date.\n');
137
141
  }
@@ -23,6 +23,7 @@ import { AuthError, DeeplineError, RateLimitError } from './errors.js';
23
23
  import { SDK_API_CONTRACT, SDK_VERSION } from './version.js';
24
24
  import type { LiveEventEnvelope } from './types.js';
25
25
  import {
26
+ COORDINATOR_INTERNAL_TOKEN_HEADER,
26
27
  COORDINATOR_URL_OVERRIDE_HEADER,
27
28
  WORKER_CALLBACK_URL_OVERRIDE_HEADER,
28
29
  } from '../../shared_libs/play-runtime/coordinator-headers.js';
@@ -84,6 +85,13 @@ export class HttpClient {
84
85
  : undefined;
85
86
  if (coordinatorUrl?.trim()) {
86
87
  headers[COORDINATOR_URL_OVERRIDE_HEADER] = coordinatorUrl.trim();
88
+ const coordinatorInternalToken = typeof process !== 'undefined'
89
+ ? process.env?.DEEPLINE_INTERNAL_TOKEN
90
+ : undefined;
91
+ if (coordinatorInternalToken?.trim()) {
92
+ headers[COORDINATOR_INTERNAL_TOKEN_HEADER] =
93
+ coordinatorInternalToken.trim();
94
+ }
87
95
  }
88
96
  const workerCallbackUrl = typeof process !== 'undefined'
89
97
  ? process.env?.DEEPLINE_WORKER_CALLBACK_URL
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.7";
1
+ export const SDK_VERSION = "0.1.9";
2
2
  export const SDK_API_CONTRACT = "2026-04-plays-v1";
@@ -51,6 +51,7 @@ function resolveInternalCoordinatorToken(): string | null {
51
51
  export function coordinatorRequestHeaders(input: {
52
52
  runId: string;
53
53
  contentType?: string | null;
54
+ internalToken?: string | null;
54
55
  /**
55
56
  * When set, the coordinator validates this matches the runId in the URL.
56
57
  * Pass the runId on `/cancel` / `/signal` calls so a leaked dispatcher
@@ -66,7 +67,8 @@ export function coordinatorRequestHeaders(input: {
66
67
  if (trimmed) {
67
68
  headers[COORDINATOR_VERSION_KEY_HEADER] = trimmed;
68
69
  }
69
- const internalToken = resolveInternalCoordinatorToken();
70
+ const internalToken =
71
+ input.internalToken?.trim() || resolveInternalCoordinatorToken();
70
72
  if (internalToken) {
71
73
  headers[COORDINATOR_INTERNAL_TOKEN_HEADER] = internalToken;
72
74
  }
@@ -94,6 +94,8 @@ export type PlaySchedulerSubmitInput = {
94
94
  totalRows?: number;
95
95
  /** Internal scheduler/coordinator URL for Worker-side capabilities. */
96
96
  coordinatorUrl?: string | null;
97
+ /** Request-scoped coordinator auth token for non-production preview/dev runs. */
98
+ coordinatorInternalToken?: string | null;
97
99
  };
98
100
 
99
101
  export type PlaySchedulerProgressEvent =
@@ -151,7 +153,10 @@ export interface PlaySchedulerBackend {
151
153
  /** Open a handle to an already-submitted run (e.g. for tail-reconnect). */
152
154
  attach(
153
155
  runId: string,
154
- options?: { coordinatorUrl?: string | null },
156
+ options?: {
157
+ coordinatorUrl?: string | null;
158
+ coordinatorInternalToken?: string | null;
159
+ },
155
160
  ): Promise<PlaySchedulerRunHandle>;
156
161
  }
157
162
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {