deepline 0.1.119 → 0.1.121
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/README.md +4 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/README.md +21 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/batching.ts +185 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-batch.ts +107 -0
- package/dist/{repo → bundling-sources}/sdk/src/client.ts +116 -12
- package/dist/bundling-sources/sdk/src/compat.ts +191 -0
- package/dist/bundling-sources/sdk/src/gtm.ts +146 -0
- package/dist/bundling-sources/sdk/src/helpers.ts +12 -0
- package/dist/{repo → bundling-sources}/sdk/src/index.ts +2 -1
- package/dist/{repo → bundling-sources}/sdk/src/play.ts +3 -1
- package/dist/{repo → bundling-sources}/sdk/src/plays/bundle-play-file.ts +17 -5
- package/dist/{repo → bundling-sources}/sdk/src/release.ts +2 -2
- package/dist/{repo → bundling-sources}/sdk/src/runs/observe-transport.ts +2 -3
- package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +838 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5510 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +261 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +828 -0
- package/dist/bundling-sources/shared_libs/play-runtime/dataset-id.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/daytona-runtime-config.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/event-wait-tools.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +171 -0
- package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-diagnosis.ts +321 -0
- package/dist/bundling-sources/shared_libs/play-runtime/hatchet-cold-execution-target.ts +158 -0
- package/dist/bundling-sources/shared_libs/play-runtime/internal-step-ids.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +119 -0
- package/dist/{repo → bundling-sources}/shared_libs/play-runtime/map-row-identity.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +636 -0
- package/dist/bundling-sources/shared_libs/play-runtime/postgres-json.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/progress-emitter.ts +197 -0
- package/dist/bundling-sources/shared_libs/play-runtime/projection.ts +262 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +143 -0
- package/dist/bundling-sources/shared_libs/play-runtime/public-play-contract.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +178 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +4015 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-constraints.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +238 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver-pg.ts +53 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-pg-driver.ts +149 -0
- package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +68 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-batch-executor.ts +149 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +159 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tracing.ts +33 -0
- package/dist/bundling-sources/shared_libs/play-runtime/waterfall-replay.ts +79 -0
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +139 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-transport.ts +14 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +49 -0
- package/dist/bundling-sources/shared_libs/plays/compiler-manifest.ts +41 -0
- package/dist/bundling-sources/shared_libs/plays/dataset-summary.ts +163 -0
- package/dist/bundling-sources/shared_libs/plays/definition.ts +267 -0
- package/dist/bundling-sources/shared_libs/plays/file-refs.ts +11 -0
- package/dist/bundling-sources/shared_libs/plays/input-contract.ts +146 -0
- package/dist/bundling-sources/shared_libs/plays/resolve-static-pipeline.ts +190 -0
- package/dist/bundling-sources/shared_libs/plays/runtime-validation.ts +417 -0
- package/dist/bundling-sources/shared_libs/plays/tool-codegen.ts +142 -0
- package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +274 -0
- package/dist/bundling-sources/shared_libs/temporal/preview-config.ts +150 -0
- package/dist/cli/index.js +811 -2207
- package/dist/cli/index.mjs +847 -2258
- package/dist/compiler-manifest-BjoRENv9.d.mts +227 -0
- package/dist/compiler-manifest-BjoRENv9.d.ts +227 -0
- package/dist/index.d.mts +8 -231
- package/dist/index.d.ts +8 -231
- package/dist/index.js +101 -15
- package/dist/index.mjs +101 -15
- package/dist/plays/bundle-play-file.d.mts +120 -0
- package/dist/plays/bundle-play-file.d.ts +120 -0
- package/dist/plays/bundle-play-file.mjs +1830 -0
- package/package.json +4 -9
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-await.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/child-play-submit.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/coordinator-entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/dedup-do.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/csv-rows.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/dataset-handles.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/live-progress.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/receipts.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/row-isolation.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/runtime/tool-http-errors.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-instance-create.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry-state.ts +0 -0
- /package/dist/{repo → bundling-sources}/apps/play-runner-workers/src/workflow-retry.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/agent-runtime.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/config.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/errors.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/http.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/plays/harness-stub.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/plays/local-file-discovery.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/stream-reconnect.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/tool-output.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/types.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/version.ts +0 -0
- /package/dist/{repo → bundling-sources}/sdk/src/worker-play-entry.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/cell-policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/column-names.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-data-plane/sheet-contract.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batch-runtime.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/batching-types.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/cell-staleness.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/coordinator-headers.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/csv-rename.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-crypto.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/db-session.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/dedup-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/default-batch-strategies.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/email-status.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/execution-plan.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/extractor-targets.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/fullenrich-batching.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/coordinator-rate-state-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/governor.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/governor/rate-state-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/live-events.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/play-runtime-batching-registry.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/profiles.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/providers.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-failure.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-ledger.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/run-snapshot-stream.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/scheduler-backend.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-capability.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/secret-redaction.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-lifecycle-tracker.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/step-program-dataset-builder.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/submit-limits.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/tool-result.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/play-runtime/work-receipts.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bootstrap-routes.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/index.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/bundling/limits.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/contracts.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/dataset.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/row-identity.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/secret-guardrails.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/plays/static-pipeline.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/security/outbound-url-policy.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/security/safe-fetch.ts +0 -0
- /package/dist/{repo → bundling-sources}/shared_libs/temporal/constants.ts +0 -0
package/dist/cli/index.mjs
CHANGED
|
@@ -158,9 +158,9 @@ function configureProxyFromEnv() {
|
|
|
158
158
|
configureProxyFromEnv();
|
|
159
159
|
|
|
160
160
|
// src/cli/index.ts
|
|
161
|
-
import { mkdtemp as mkdtemp2, rm as rm2, writeFile as
|
|
162
|
-
import { join as
|
|
163
|
-
import { tmpdir as
|
|
161
|
+
import { mkdtemp as mkdtemp2, rm as rm2, writeFile as writeFile5 } from "fs/promises";
|
|
162
|
+
import { join as join14 } from "path";
|
|
163
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
164
164
|
import { Command as Command3 } from "commander";
|
|
165
165
|
|
|
166
166
|
// src/config.ts
|
|
@@ -380,10 +380,10 @@ var SDK_RELEASE = {
|
|
|
380
380
|
// skill on the sdk sync surface, and the people-search-to-email prebuilt.
|
|
381
381
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
382
382
|
// the SDK enrich generator's one-second stale policy.
|
|
383
|
-
version: "0.1.
|
|
383
|
+
version: "0.1.121",
|
|
384
384
|
apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
|
|
385
385
|
supportPolicy: {
|
|
386
|
-
latest: "0.1.
|
|
386
|
+
latest: "0.1.121",
|
|
387
387
|
minimumSupported: "0.1.53",
|
|
388
388
|
deprecatedBelow: "0.1.53",
|
|
389
389
|
commandMinimumSupported: [
|
|
@@ -896,7 +896,7 @@ function decodeSseFrame(frame) {
|
|
|
896
896
|
return parsed;
|
|
897
897
|
}
|
|
898
898
|
function sleep(ms) {
|
|
899
|
-
return new Promise((
|
|
899
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
900
900
|
}
|
|
901
901
|
function withCoworkNetworkHint(message) {
|
|
902
902
|
if (!isCoworkLikeSandbox() || message.includes(COWORK_NETWORK_HINT)) {
|
|
@@ -1653,14 +1653,14 @@ async function* observeRunEvents(options) {
|
|
|
1653
1653
|
try {
|
|
1654
1654
|
for (; ; ) {
|
|
1655
1655
|
if (queue.length === 0) {
|
|
1656
|
-
const waitForItem = new Promise((
|
|
1657
|
-
wake =
|
|
1656
|
+
const waitForItem = new Promise((resolve13) => {
|
|
1657
|
+
wake = resolve13;
|
|
1658
1658
|
});
|
|
1659
1659
|
if (!sawFirstSnapshot) {
|
|
1660
1660
|
const timedOut = await Promise.race([
|
|
1661
1661
|
waitForItem.then(() => false),
|
|
1662
1662
|
new Promise(
|
|
1663
|
-
(
|
|
1663
|
+
(resolve13) => setTimeout(() => resolve13(true), OBSERVE_BOOTSTRAP_TIMEOUT_MS)
|
|
1664
1664
|
)
|
|
1665
1665
|
]);
|
|
1666
1666
|
if (timedOut && queue.length === 0) {
|
|
@@ -1760,7 +1760,7 @@ var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
|
|
|
1760
1760
|
var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_COUNT = 3;
|
|
1761
1761
|
var REGISTER_PLAY_ARTIFACTS_MAX_BATCH_BYTES = 25e5;
|
|
1762
1762
|
function sleep2(ms) {
|
|
1763
|
-
return new Promise((
|
|
1763
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
1764
1764
|
}
|
|
1765
1765
|
function isTransientCompileManifestError(error) {
|
|
1766
1766
|
if (error instanceof DeeplineError && typeof error.statusCode === "number") {
|
|
@@ -2877,20 +2877,105 @@ var DeeplineClient = class {
|
|
|
2877
2877
|
return response.runs ?? [];
|
|
2878
2878
|
}
|
|
2879
2879
|
/**
|
|
2880
|
-
* Observe one run's live events
|
|
2881
|
-
*
|
|
2882
|
-
*
|
|
2883
|
-
*
|
|
2884
|
-
*
|
|
2885
|
-
* unreachable Convex) — callers fall back to the SSE stream with a notice.
|
|
2880
|
+
* Observe one run's live events. Uses the Convex Run Snapshot subscription
|
|
2881
|
+
* transport first (ADR-0008), then falls back to the canonical SSE stream
|
|
2882
|
+
* when the subscription transport or its optional client modules are not
|
|
2883
|
+
* available. Pass `fallback: 'none'` to receive
|
|
2884
|
+
* {@link RunObserveTransportUnavailableError} instead.
|
|
2886
2885
|
*/
|
|
2887
|
-
observeRunEvents(runId, options) {
|
|
2888
|
-
|
|
2889
|
-
|
|
2886
|
+
async *observeRunEvents(runId, options) {
|
|
2887
|
+
let yieldedObserveEvent = false;
|
|
2888
|
+
try {
|
|
2889
|
+
for await (const event of observeRunEvents({
|
|
2890
|
+
http: this.http,
|
|
2891
|
+
runId,
|
|
2892
|
+
signal: options?.signal,
|
|
2893
|
+
onNotice: options?.onNotice
|
|
2894
|
+
})) {
|
|
2895
|
+
yieldedObserveEvent = true;
|
|
2896
|
+
yield event;
|
|
2897
|
+
}
|
|
2898
|
+
} catch (error) {
|
|
2899
|
+
if (!(error instanceof RunObserveTransportUnavailableError) || yieldedObserveEvent || options?.fallback === "none") {
|
|
2900
|
+
throw error;
|
|
2901
|
+
}
|
|
2902
|
+
options?.onNotice?.(
|
|
2903
|
+
`[observe] live subscription unavailable (${error.reason}); falling back to SSE tail (support window, ADR-0008)`
|
|
2904
|
+
);
|
|
2905
|
+
yield* this.streamPlayRunEventsUntilTerminal(runId, options);
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
async *streamPlayRunEventsUntilTerminal(runId, options) {
|
|
2909
|
+
const state = {
|
|
2890
2910
|
runId,
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2911
|
+
status: "running",
|
|
2912
|
+
logs: [],
|
|
2913
|
+
lastLogSeq: 0,
|
|
2914
|
+
latest: null
|
|
2915
|
+
};
|
|
2916
|
+
let lastEventId;
|
|
2917
|
+
let reconnectAttempt = 0;
|
|
2918
|
+
for (; ; ) {
|
|
2919
|
+
if (options?.signal?.aborted) {
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
const connectedAt = Date.now();
|
|
2923
|
+
let sawEvent = false;
|
|
2924
|
+
let endedReason = "stream window ended before a terminal event";
|
|
2925
|
+
try {
|
|
2926
|
+
for await (const event of this.streamPlayRunEvents(runId, {
|
|
2927
|
+
mode: "cli",
|
|
2928
|
+
signal: options?.signal,
|
|
2929
|
+
...lastEventId ? { lastEventId } : {}
|
|
2930
|
+
})) {
|
|
2931
|
+
sawEvent = true;
|
|
2932
|
+
if (event.cursor?.trim()) {
|
|
2933
|
+
lastEventId = event.cursor;
|
|
2934
|
+
}
|
|
2935
|
+
yield event;
|
|
2936
|
+
const status = updatePlayLiveStatusState(state, event);
|
|
2937
|
+
if (status && TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
2938
|
+
return;
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
} catch (error) {
|
|
2942
|
+
if (options?.signal?.aborted) {
|
|
2943
|
+
return;
|
|
2944
|
+
}
|
|
2945
|
+
if (!isTransientPlayStreamError(error)) {
|
|
2946
|
+
throw error;
|
|
2947
|
+
}
|
|
2948
|
+
endedReason = error instanceof Error ? error.message : String(error);
|
|
2949
|
+
}
|
|
2950
|
+
let refreshed = null;
|
|
2951
|
+
try {
|
|
2952
|
+
refreshed = await this.getRunStatus(runId);
|
|
2953
|
+
} catch (error) {
|
|
2954
|
+
if (!isTransientPlayStreamError(error)) {
|
|
2955
|
+
throw error;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
if (refreshed && TERMINAL_PLAY_STATUSES.has(refreshed.status)) {
|
|
2959
|
+
yield {
|
|
2960
|
+
cursor: String(Date.now()),
|
|
2961
|
+
streamId: `sse-fallback:${runId}`,
|
|
2962
|
+
scope: "play",
|
|
2963
|
+
type: "play.run.status",
|
|
2964
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2965
|
+
payload: refreshed
|
|
2966
|
+
};
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
if (sawEvent || Date.now() - connectedAt >= STREAM_HEALTHY_CONNECTION_MS) {
|
|
2970
|
+
reconnectAttempt = 0;
|
|
2971
|
+
}
|
|
2972
|
+
const delayMs = streamReconnectDelayMs(reconnectAttempt);
|
|
2973
|
+
reconnectAttempt += 1;
|
|
2974
|
+
options?.onNotice?.(
|
|
2975
|
+
`[observe] SSE tail window ended before terminal status (${endedReason}); reconnecting to run ${runId}`
|
|
2976
|
+
);
|
|
2977
|
+
await sleep2(delayMs);
|
|
2978
|
+
}
|
|
2894
2979
|
}
|
|
2895
2980
|
/**
|
|
2896
2981
|
* Tail one run through the subscription transport until terminal, then
|
|
@@ -2906,7 +2991,8 @@ var DeeplineClient = class {
|
|
|
2906
2991
|
};
|
|
2907
2992
|
for await (const event of this.observeRunEvents(runId, {
|
|
2908
2993
|
signal: options?.signal,
|
|
2909
|
-
onNotice: options?.onNotice
|
|
2994
|
+
onNotice: options?.onNotice,
|
|
2995
|
+
fallback: "none"
|
|
2910
2996
|
})) {
|
|
2911
2997
|
const status = updatePlayLiveStatusState(state, event);
|
|
2912
2998
|
if (!status || !TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
@@ -4210,7 +4296,7 @@ function buildCandidateUrls2(url) {
|
|
|
4210
4296
|
}
|
|
4211
4297
|
}
|
|
4212
4298
|
function sleep4(ms) {
|
|
4213
|
-
return new Promise((
|
|
4299
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
4214
4300
|
}
|
|
4215
4301
|
function printDeeplineLogo() {
|
|
4216
4302
|
if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
|
|
@@ -4245,10 +4331,8 @@ async function claimInstallBonus(baseUrl, apiKey) {
|
|
|
4245
4331
|
apiKey,
|
|
4246
4332
|
{}
|
|
4247
4333
|
);
|
|
4248
|
-
if (status !== 200)
|
|
4249
|
-
|
|
4250
|
-
}
|
|
4251
|
-
const granted = Number(data.credits_granted ?? 0);
|
|
4334
|
+
if (status !== 200) return;
|
|
4335
|
+
const granted = typeof data.credits_granted === "number" ? data.credits_granted : 0;
|
|
4252
4336
|
const alreadyGranted = data.already_granted === true;
|
|
4253
4337
|
if (granted > 0) {
|
|
4254
4338
|
console.log(`
|
|
@@ -6162,38 +6246,38 @@ function buildDatasetStats(rows, totalRows = rows.length, columns = inferColumns
|
|
|
6162
6246
|
}
|
|
6163
6247
|
}
|
|
6164
6248
|
const denominator = nonEmpty + empty;
|
|
6165
|
-
const
|
|
6249
|
+
const stat2 = {
|
|
6166
6250
|
non_empty: percentText(nonEmpty, denominator),
|
|
6167
6251
|
unique: valueCounts.size
|
|
6168
6252
|
};
|
|
6169
6253
|
const rawExecutionStats = executionStats?.columnStats[column];
|
|
6170
6254
|
if (rawExecutionStats) {
|
|
6171
|
-
|
|
6255
|
+
stat2.execution = formatDatasetExecutionStats(
|
|
6172
6256
|
rawExecutionStats,
|
|
6173
6257
|
totalRows
|
|
6174
6258
|
);
|
|
6175
6259
|
}
|
|
6176
6260
|
if (sampleValue !== void 0 && sampleValueType) {
|
|
6177
|
-
|
|
6178
|
-
|
|
6261
|
+
stat2.sample_value = sampleValue;
|
|
6262
|
+
stat2.sample_type = sampleValueType;
|
|
6179
6263
|
}
|
|
6180
6264
|
if (valueCounts.size > 0 && valueCounts.size < nonEmpty) {
|
|
6181
6265
|
const top = [...valueCounts.entries()].sort((left, right) => right[1] - left[1]).slice(0, 3);
|
|
6182
6266
|
const topKeys = new Set(top.map(([key]) => key));
|
|
6183
6267
|
const otherCount = [...valueCounts.entries()].filter(([key]) => !topKeys.has(key)).reduce((sum, [, count]) => sum + count, 0);
|
|
6184
|
-
|
|
6268
|
+
stat2.top_values = Object.fromEntries(
|
|
6185
6269
|
top.map(([key, count]) => [key, countPercentText(count, denominator)])
|
|
6186
6270
|
);
|
|
6187
6271
|
if (otherCount > 0) {
|
|
6188
|
-
|
|
6272
|
+
stat2.top_values["(other)"] = countPercentText(otherCount, denominator);
|
|
6189
6273
|
}
|
|
6190
6274
|
if (empty > 0) {
|
|
6191
|
-
|
|
6275
|
+
stat2.top_values["(null)"] = countPercentText(empty, denominator);
|
|
6192
6276
|
}
|
|
6193
6277
|
} else if (empty > 0 && nonEmpty > 0) {
|
|
6194
|
-
|
|
6278
|
+
stat2.top_values = { "(null)": countPercentText(empty, denominator) };
|
|
6195
6279
|
}
|
|
6196
|
-
columnStats[column] =
|
|
6280
|
+
columnStats[column] = stat2;
|
|
6197
6281
|
}
|
|
6198
6282
|
return {
|
|
6199
6283
|
total_rows: totalRows,
|
|
@@ -6679,1938 +6763,123 @@ Examples:
|
|
|
6679
6763
|
|
|
6680
6764
|
// src/cli/commands/enrich.ts
|
|
6681
6765
|
import {
|
|
6682
|
-
mkdir as
|
|
6766
|
+
mkdir as mkdir3,
|
|
6683
6767
|
mkdtemp,
|
|
6684
|
-
readFile
|
|
6768
|
+
readFile,
|
|
6685
6769
|
rm,
|
|
6686
|
-
stat
|
|
6687
|
-
writeFile as
|
|
6770
|
+
stat,
|
|
6771
|
+
writeFile as writeFile3
|
|
6688
6772
|
} from "fs/promises";
|
|
6689
|
-
import { homedir as homedir6, tmpdir
|
|
6690
|
-
import { join as
|
|
6773
|
+
import { homedir as homedir6, tmpdir } from "os";
|
|
6774
|
+
import { join as join6, resolve as resolve8 } from "path";
|
|
6691
6775
|
|
|
6692
6776
|
// src/cli/commands/play.ts
|
|
6693
|
-
import { createHash
|
|
6777
|
+
import { createHash } from "crypto";
|
|
6694
6778
|
import {
|
|
6695
|
-
existsSync as
|
|
6696
|
-
readFileSync as
|
|
6779
|
+
existsSync as existsSync6,
|
|
6780
|
+
readFileSync as readFileSync6,
|
|
6697
6781
|
readdirSync,
|
|
6698
6782
|
realpathSync,
|
|
6699
6783
|
statSync as statSync2,
|
|
6700
6784
|
writeFileSync as writeFileSync8
|
|
6701
6785
|
} from "fs";
|
|
6702
|
-
import { basename
|
|
6786
|
+
import { basename, dirname as dirname6, join as join5, resolve as resolve7 } from "path";
|
|
6703
6787
|
import { parse as parseCsvSync2 } from "csv-parse/sync";
|
|
6704
6788
|
|
|
6705
|
-
// src/plays/
|
|
6706
|
-
import {
|
|
6707
|
-
import {
|
|
6708
|
-
import {
|
|
6709
|
-
import { existsSync as existsSync7 } from "fs";
|
|
6710
|
-
|
|
6711
|
-
// ../shared_libs/plays/bundling/index.ts
|
|
6712
|
-
import { createHash } from "crypto";
|
|
6713
|
-
import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
|
|
6714
|
-
import { mkdir as mkdir3, readFile, realpath, stat, writeFile as writeFile3 } from "fs/promises";
|
|
6715
|
-
import { tmpdir } from "os";
|
|
6716
|
-
import {
|
|
6717
|
-
basename,
|
|
6718
|
-
dirname as dirname6,
|
|
6719
|
-
extname,
|
|
6720
|
-
isAbsolute,
|
|
6721
|
-
join as join5,
|
|
6722
|
-
relative,
|
|
6723
|
-
resolve as resolve6
|
|
6724
|
-
} from "path";
|
|
6725
|
-
import { builtinModules } from "module";
|
|
6726
|
-
import { build } from "esbuild";
|
|
6789
|
+
// src/cli/commands/plays/bootstrap.ts
|
|
6790
|
+
import { closeSync, openSync, readSync, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
6791
|
+
import { isAbsolute, relative, resolve as resolve6 } from "path";
|
|
6792
|
+
import { parse as parseCsvSync } from "csv-parse/sync";
|
|
6727
6793
|
|
|
6728
|
-
// ../shared_libs/
|
|
6729
|
-
var
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6794
|
+
// ../shared_libs/plays/bootstrap-routes.ts
|
|
6795
|
+
var PLAY_BOOTSTRAP_TEMPLATES = [
|
|
6796
|
+
"people-list",
|
|
6797
|
+
"company-list",
|
|
6798
|
+
"people-email",
|
|
6799
|
+
"people-phone",
|
|
6800
|
+
"company-people",
|
|
6801
|
+
"company-people-email",
|
|
6802
|
+
"company-people-phone"
|
|
6803
|
+
];
|
|
6804
|
+
var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
|
|
6805
|
+
var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
|
|
6806
|
+
var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
|
|
6807
|
+
email_finder: "email_finder",
|
|
6808
|
+
phone_finder: "phone_finder"
|
|
6740
6809
|
};
|
|
6741
|
-
var
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
6745
|
-
label: "Local node subprocess"
|
|
6746
|
-
},
|
|
6747
|
-
[PLAY_RUNTIME_BACKENDS.daytona]: {
|
|
6748
|
-
id: PLAY_RUNTIME_BACKENDS.daytona,
|
|
6749
|
-
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
6750
|
-
label: "Daytona sandbox"
|
|
6751
|
-
},
|
|
6752
|
-
[PLAY_RUNTIME_BACKENDS.cloudflareWorkers]: {
|
|
6753
|
-
id: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
6754
|
-
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
6755
|
-
label: "Cloudflare Dynamic Workers"
|
|
6756
|
-
}
|
|
6810
|
+
var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
|
|
6811
|
+
email_finder: "email",
|
|
6812
|
+
phone_finder: "phone"
|
|
6757
6813
|
};
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
var PLAY_PUBLIC_API_VERSION = 1;
|
|
6761
|
-
var PLAY_ARTIFACT_VERSION = 1;
|
|
6762
|
-
var PLAY_MIN_RUNNER_VERSION = 1;
|
|
6763
|
-
var PLAY_RUNTIME_FEATURES = [
|
|
6764
|
-
"artifact_storage",
|
|
6765
|
-
"checkpoint_resume",
|
|
6766
|
-
"durable_sleep",
|
|
6767
|
-
"packaged_files"
|
|
6768
|
-
];
|
|
6769
|
-
function buildPlayContractCompatibility(input2) {
|
|
6770
|
-
return {
|
|
6771
|
-
apiVersion: PLAY_PUBLIC_API_VERSION,
|
|
6772
|
-
artifactVersion: PLAY_ARTIFACT_VERSION,
|
|
6773
|
-
minRunnerVersion: PLAY_MIN_RUNNER_VERSION,
|
|
6774
|
-
runtimeFeatures: [...PLAY_RUNTIME_FEATURES],
|
|
6775
|
-
runtimeBackend: input2?.runtimeBackend ?? null
|
|
6776
|
-
};
|
|
6777
|
-
}
|
|
6778
|
-
|
|
6779
|
-
// ../shared_libs/plays/secret-guardrails.ts
|
|
6780
|
-
var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
|
|
6781
|
-
var PRIVATE_KEY_PATTERN = /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/;
|
|
6782
|
-
var BEARER_LITERAL_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i;
|
|
6783
|
-
var ASSIGNMENT_SECRET_LITERAL_PATTERN = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{12,}['"]/i;
|
|
6784
|
-
var HIGH_ENTROPY_LITERAL_PATTERN = /['"]([A-Za-z0-9+/=_-]{32,})['"]/g;
|
|
6785
|
-
function shannonEntropy(value) {
|
|
6786
|
-
const counts = /* @__PURE__ */ new Map();
|
|
6787
|
-
for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
|
|
6788
|
-
return [...counts.values()].reduce((entropy, count) => {
|
|
6789
|
-
const p = count / value.length;
|
|
6790
|
-
return entropy - p * Math.log2(p);
|
|
6791
|
-
}, 0);
|
|
6792
|
-
}
|
|
6793
|
-
function collectInlineSecretFindings(sourceCode) {
|
|
6794
|
-
const findings = [];
|
|
6795
|
-
for (const match of sourceCode.matchAll(SECRET_ENV_PATTERN)) {
|
|
6796
|
-
findings.push(`process.env.${match[1]}`);
|
|
6797
|
-
}
|
|
6798
|
-
if (PRIVATE_KEY_PATTERN.test(sourceCode)) findings.push("private key block");
|
|
6799
|
-
if (BEARER_LITERAL_PATTERN.test(sourceCode))
|
|
6800
|
-
findings.push("bearer token literal");
|
|
6801
|
-
if (ASSIGNMENT_SECRET_LITERAL_PATTERN.test(sourceCode)) {
|
|
6802
|
-
findings.push("secret-looking assignment literal");
|
|
6803
|
-
}
|
|
6804
|
-
for (const match of sourceCode.matchAll(HIGH_ENTROPY_LITERAL_PATTERN)) {
|
|
6805
|
-
const literal = match[1] ?? "";
|
|
6806
|
-
if (literal.length >= 40 && shannonEntropy(literal) >= 4.2) {
|
|
6807
|
-
findings.push("high-entropy string literal");
|
|
6808
|
-
break;
|
|
6809
|
-
}
|
|
6810
|
-
}
|
|
6811
|
-
return [...new Set(findings)];
|
|
6812
|
-
}
|
|
6813
|
-
function validatePlaySourceHasNoInlineSecrets(input2) {
|
|
6814
|
-
const findings = collectInlineSecretFindings(input2.sourceCode);
|
|
6815
|
-
if (!findings.length) return;
|
|
6816
|
-
throw new Error(
|
|
6817
|
-
[
|
|
6818
|
-
`Play source ${input2.filePath} appears to contain inline secret material: ${[
|
|
6819
|
-
...new Set(findings)
|
|
6820
|
-
].join(", ")}.`,
|
|
6821
|
-
'Author secrets in the dashboard and use ctx.secrets.get("NAME") with an approved helper such as ctx.secrets.bearer(handle).'
|
|
6822
|
-
].join(" ")
|
|
6823
|
-
);
|
|
6814
|
+
function isPlayBootstrapTemplate(value) {
|
|
6815
|
+
return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
|
|
6824
6816
|
}
|
|
6825
|
-
function
|
|
6826
|
-
|
|
6827
|
-
validatePlaySourceHasNoInlineSecrets({ filePath, sourceCode });
|
|
6828
|
-
}
|
|
6817
|
+
function formatPlayBootstrapTemplates() {
|
|
6818
|
+
return PLAY_BOOTSTRAP_TEMPLATES.join("|");
|
|
6829
6819
|
}
|
|
6830
6820
|
|
|
6831
|
-
//
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
var PLAY_ARTIFACT_CACHE_DIR = join5(
|
|
6838
|
-
tmpdir(),
|
|
6839
|
-
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
|
|
6840
|
-
);
|
|
6841
|
-
var PLAY_PROXY_NAMESPACE = "deepline-play-runtime-ref";
|
|
6842
|
-
var SOURCE_EXTENSIONS = [
|
|
6843
|
-
".ts",
|
|
6844
|
-
".tsx",
|
|
6845
|
-
".mts",
|
|
6846
|
-
".cts",
|
|
6847
|
-
".js",
|
|
6848
|
-
".jsx",
|
|
6849
|
-
".mjs",
|
|
6850
|
-
".cjs",
|
|
6851
|
-
".json"
|
|
6852
|
-
];
|
|
6853
|
-
var WORKERS_PLAY_ENTRY_VIRTUAL = "deepline-play-entry";
|
|
6854
|
-
var PLAY_SOURCE_FILE_PATTERN = /\.play\.(?:[cm]?[jt]sx?)$/i;
|
|
6855
|
-
var NODE_BUILTIN_SET = new Set(
|
|
6856
|
-
builtinModules.flatMap(
|
|
6857
|
-
(name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`]
|
|
6858
|
-
)
|
|
6859
|
-
);
|
|
6860
|
-
function assertValidExportName(exportName) {
|
|
6861
|
-
if (exportName === "default") return;
|
|
6862
|
-
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(exportName)) {
|
|
6863
|
-
throw new Error(
|
|
6864
|
-
`Invalid play export name "${exportName}". Named prebuilt exports must be valid JavaScript identifiers.`
|
|
6865
|
-
);
|
|
6866
|
-
}
|
|
6867
|
-
}
|
|
6868
|
-
function sha256(value) {
|
|
6869
|
-
return createHash("sha256").update(value).digest("hex");
|
|
6870
|
-
}
|
|
6871
|
-
function formatEsbuildMessage(message) {
|
|
6872
|
-
const location = message.location ? `${message.location.file}:${message.location.line}:${message.location.column}` : null;
|
|
6873
|
-
return location ? `${location} ${message.text}` : message.text;
|
|
6874
|
-
}
|
|
6875
|
-
function isLocalSpecifier(specifier) {
|
|
6876
|
-
return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || specifier.startsWith("file:");
|
|
6877
|
-
}
|
|
6878
|
-
async function normalizeLocalPath(filePath) {
|
|
6879
|
-
try {
|
|
6880
|
-
return await realpath(filePath);
|
|
6881
|
-
} catch {
|
|
6882
|
-
return resolve6(filePath);
|
|
6821
|
+
// src/cli/commands/plays/bootstrap.ts
|
|
6822
|
+
function parseReferencedPlayTarget(target) {
|
|
6823
|
+
const trimmed = target.trim();
|
|
6824
|
+
const slashIndex = trimmed.indexOf("/");
|
|
6825
|
+
if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
|
|
6826
|
+
return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
|
|
6883
6827
|
}
|
|
6884
|
-
}
|
|
6885
|
-
function createPlayWorkspace(entryFile) {
|
|
6886
6828
|
return {
|
|
6887
|
-
|
|
6888
|
-
|
|
6829
|
+
ownerSlug: trimmed.slice(0, slashIndex),
|
|
6830
|
+
playName: trimmed,
|
|
6831
|
+
unqualifiedPlayName: trimmed.slice(slashIndex + 1)
|
|
6889
6832
|
};
|
|
6890
6833
|
}
|
|
6891
|
-
function
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
|
|
6834
|
+
function parsePositiveInteger2(value, flagName) {
|
|
6835
|
+
const parsed = Number.parseInt(value, 10);
|
|
6836
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
6837
|
+
throw new PlayBootstrapUsageError(
|
|
6838
|
+
`${flagName} must be a positive integer.`
|
|
6839
|
+
);
|
|
6897
6840
|
}
|
|
6898
|
-
|
|
6899
|
-
`${input2.importer}:${input2.line}:${input2.column} Local play imports must stay inside the play workspace (${input2.workspace.rootDir}). Import "${input2.specifier}" resolved to ${input2.resolvedPath}, which crosses into app/backend code. Use the public SDK/API surface or move shared helpers into the play workspace.`
|
|
6900
|
-
);
|
|
6841
|
+
return parsed;
|
|
6901
6842
|
}
|
|
6902
|
-
function
|
|
6903
|
-
|
|
6904
|
-
const [scope, name] = specifier.split("/");
|
|
6905
|
-
return scope && name ? `${scope}/${name}` : specifier;
|
|
6906
|
-
}
|
|
6907
|
-
return specifier.split("/")[0] ?? specifier;
|
|
6843
|
+
function isRecord5(value) {
|
|
6844
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
6908
6845
|
}
|
|
6909
|
-
function
|
|
6910
|
-
return
|
|
6846
|
+
function stringValue(value) {
|
|
6847
|
+
return typeof value === "string" ? value.trim() : "";
|
|
6911
6848
|
}
|
|
6912
|
-
function
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6849
|
+
function extractionEntries(value) {
|
|
6850
|
+
if (Array.isArray(value)) return value.filter(isRecord5);
|
|
6851
|
+
if (!isRecord5(value)) return [];
|
|
6852
|
+
return Object.entries(value).map(
|
|
6853
|
+
([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
|
|
6916
6854
|
);
|
|
6917
6855
|
}
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
}
|
|
6923
|
-
function findSourceImportReferences(sourceCode) {
|
|
6924
|
-
const source = stripCommentsToSpaces(sourceCode);
|
|
6925
|
-
const references = [];
|
|
6926
|
-
const addReference = (specifier, specifierIndex, kind) => {
|
|
6927
|
-
if (!specifier) return;
|
|
6928
|
-
const position = lineAndColumnAt(sourceCode, specifierIndex);
|
|
6929
|
-
references.push({
|
|
6930
|
-
specifier,
|
|
6931
|
-
line: position.line,
|
|
6932
|
-
column: position.column,
|
|
6933
|
-
kind
|
|
6934
|
-
});
|
|
6935
|
-
};
|
|
6936
|
-
const staticImportPattern = /\b(?:import|export)\s+(?!type\b)(?:[\s\S]*?\s+from\s*)?(['"])([^'"\n]+)\1/g;
|
|
6937
|
-
for (const match of source.matchAll(staticImportPattern)) {
|
|
6938
|
-
addReference(
|
|
6939
|
-
match[2],
|
|
6940
|
-
match.index + match[0].lastIndexOf(match[1]),
|
|
6941
|
-
"static"
|
|
6942
|
-
);
|
|
6943
|
-
}
|
|
6944
|
-
const dynamicImportPattern = /\bimport\s*\(\s*(['"])([^'"\n]+)\1/g;
|
|
6945
|
-
for (const match of source.matchAll(dynamicImportPattern)) {
|
|
6946
|
-
addReference(
|
|
6947
|
-
match[2],
|
|
6948
|
-
match.index + match[0].lastIndexOf(match[1]),
|
|
6949
|
-
"dynamic-import"
|
|
6950
|
-
);
|
|
6951
|
-
}
|
|
6952
|
-
const requirePattern = /\brequire\s*\(\s*(['"])([^'"\n]+)\1/g;
|
|
6953
|
-
for (const match of source.matchAll(requirePattern)) {
|
|
6954
|
-
addReference(
|
|
6955
|
-
match[2],
|
|
6956
|
-
match.index + match[0].lastIndexOf(match[1]),
|
|
6957
|
-
"require"
|
|
6958
|
-
);
|
|
6856
|
+
var PlayBootstrapError = class extends Error {
|
|
6857
|
+
constructor(message, exitCode) {
|
|
6858
|
+
super(message);
|
|
6859
|
+
this.exitCode = exitCode;
|
|
6959
6860
|
}
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
const position = lineAndColumnAt(sourceCode, match.index);
|
|
6966
|
-
throw new Error(
|
|
6967
|
-
`:${position.line}:${position.column} Dynamic import() is not allowed in plays. Use static imports instead.`
|
|
6968
|
-
);
|
|
6861
|
+
exitCode;
|
|
6862
|
+
};
|
|
6863
|
+
var PlayBootstrapUsageError = class extends PlayBootstrapError {
|
|
6864
|
+
constructor(message) {
|
|
6865
|
+
super(message, 2);
|
|
6969
6866
|
}
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
)
|
|
6973
|
-
|
|
6974
|
-
if (literalRequireIndexes.has(match.index)) continue;
|
|
6975
|
-
const position = lineAndColumnAt(sourceCode, match.index);
|
|
6976
|
-
throw new Error(
|
|
6977
|
-
`:${position.line}:${position.column} Dynamic require() is not allowed in plays. Use static imports or require("literal") only.`
|
|
6978
|
-
);
|
|
6867
|
+
};
|
|
6868
|
+
var PlayBootstrapValidationError = class extends PlayBootstrapError {
|
|
6869
|
+
constructor(message) {
|
|
6870
|
+
super(message, 7);
|
|
6979
6871
|
}
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6872
|
+
};
|
|
6873
|
+
var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
|
|
6874
|
+
function parseCsvList(value) {
|
|
6875
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
6983
6876
|
}
|
|
6984
|
-
function
|
|
6985
|
-
const
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
return null;
|
|
6989
|
-
}
|
|
6990
|
-
try {
|
|
6991
|
-
return JSON.parse(
|
|
6992
|
-
quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
|
|
6993
|
-
);
|
|
6994
|
-
} catch {
|
|
6995
|
-
return trimmed.slice(1, -1);
|
|
6877
|
+
function parseProviderList(value, flag) {
|
|
6878
|
+
const providers = parseCsvList(value);
|
|
6879
|
+
if (providers.length === 0) {
|
|
6880
|
+
throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
|
|
6996
6881
|
}
|
|
6997
|
-
|
|
6998
|
-
function findMatchingBrace(source, openIndex) {
|
|
6999
|
-
let depth = 0;
|
|
7000
|
-
let quote = null;
|
|
7001
|
-
let escaped = false;
|
|
7002
|
-
for (let index = openIndex; index < source.length; index += 1) {
|
|
7003
|
-
const char = source[index];
|
|
7004
|
-
if (quote) {
|
|
7005
|
-
if (escaped) {
|
|
7006
|
-
escaped = false;
|
|
7007
|
-
} else if (char === "\\") {
|
|
7008
|
-
escaped = true;
|
|
7009
|
-
} else if (char === quote) {
|
|
7010
|
-
quote = null;
|
|
7011
|
-
}
|
|
7012
|
-
continue;
|
|
7013
|
-
}
|
|
7014
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
7015
|
-
quote = char;
|
|
7016
|
-
continue;
|
|
7017
|
-
}
|
|
7018
|
-
if (char === "{") depth += 1;
|
|
7019
|
-
if (char === "}") {
|
|
7020
|
-
depth -= 1;
|
|
7021
|
-
if (depth === 0) return index;
|
|
7022
|
-
}
|
|
7023
|
-
}
|
|
7024
|
-
return -1;
|
|
7025
|
-
}
|
|
7026
|
-
function extractDefinedPlayName(sourceCode) {
|
|
7027
|
-
const source = stripCommentsToSpaces(sourceCode);
|
|
7028
|
-
const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
|
|
7029
|
-
for (const match of source.matchAll(callPattern)) {
|
|
7030
|
-
const openParen = match.index + match[0].length - 1;
|
|
7031
|
-
const firstArgStart = openParen + 1;
|
|
7032
|
-
const firstNonSpace = source.slice(firstArgStart).search(/\S/);
|
|
7033
|
-
if (firstNonSpace < 0) continue;
|
|
7034
|
-
const argIndex = firstArgStart + firstNonSpace;
|
|
7035
|
-
const quote = source[argIndex];
|
|
7036
|
-
if (quote === '"' || quote === "'") {
|
|
7037
|
-
const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
|
|
7038
|
-
const value = literalMatch ? unquoteStringLiteral(literalMatch[0]) : null;
|
|
7039
|
-
if (value?.trim()) return value.trim();
|
|
7040
|
-
}
|
|
7041
|
-
if (quote === "{") {
|
|
7042
|
-
const closeBrace = findMatchingBrace(source, argIndex);
|
|
7043
|
-
if (closeBrace < 0) continue;
|
|
7044
|
-
const objectSource = source.slice(argIndex + 1, closeBrace);
|
|
7045
|
-
const idMatch = objectSource.match(
|
|
7046
|
-
/(?:^|[,{\s])(?:id|['"]id['"])\s*:\s*(['"])([\s\S]*?)\1/
|
|
7047
|
-
);
|
|
7048
|
-
if (idMatch?.[2]?.trim()) {
|
|
7049
|
-
return idMatch[2].trim();
|
|
7050
|
-
}
|
|
7051
|
-
}
|
|
7052
|
-
}
|
|
7053
|
-
return null;
|
|
7054
|
-
}
|
|
7055
|
-
function canonicalizeRootPlayNameForWorkersRuntimeHash(sourceCode) {
|
|
7056
|
-
const source = stripCommentsToSpaces(sourceCode);
|
|
7057
|
-
const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
|
|
7058
|
-
const match = callPattern.exec(source);
|
|
7059
|
-
if (!match) return sourceCode;
|
|
7060
|
-
const openParen = match.index + match[0].length - 1;
|
|
7061
|
-
const firstArgStart = openParen + 1;
|
|
7062
|
-
const firstNonSpace = source.slice(firstArgStart).search(/\S/);
|
|
7063
|
-
if (firstNonSpace < 0) return sourceCode;
|
|
7064
|
-
const argIndex = firstArgStart + firstNonSpace;
|
|
7065
|
-
const quote = source[argIndex];
|
|
7066
|
-
if (quote === '"' || quote === "'") {
|
|
7067
|
-
const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
|
|
7068
|
-
if (!literalMatch) return sourceCode;
|
|
7069
|
-
const replacement = `${quote}__deepline_runtime_play_name__${quote}`;
|
|
7070
|
-
return `${sourceCode.slice(0, argIndex)}${replacement}${sourceCode.slice(argIndex + literalMatch[0].length)}`;
|
|
7071
|
-
}
|
|
7072
|
-
if (quote !== "{") return sourceCode;
|
|
7073
|
-
const closeBrace = findMatchingBrace(source, argIndex);
|
|
7074
|
-
if (closeBrace < 0) return sourceCode;
|
|
7075
|
-
const objectSource = source.slice(argIndex + 1, closeBrace);
|
|
7076
|
-
const idMatch = objectSource.match(
|
|
7077
|
-
/(^|[,{\s])((?:id|['"]id['"])\s*:\s*)(['"])([\s\S]*?)\3/
|
|
7078
|
-
);
|
|
7079
|
-
if (!idMatch || idMatch.index === void 0) return sourceCode;
|
|
7080
|
-
const idValueStart = argIndex + 1 + idMatch.index + idMatch[1].length + idMatch[2].length + idMatch[3].length;
|
|
7081
|
-
return `${sourceCode.slice(0, idValueStart)}__deepline_runtime_play_name__${sourceCode.slice(idValueStart + idMatch[4].length)}`;
|
|
7082
|
-
}
|
|
7083
|
-
function workersRuntimeGraphFilePath(input2) {
|
|
7084
|
-
if (input2.filePath === input2.entryFile) return "<entry>";
|
|
7085
|
-
const entryRelative = relative(dirname6(input2.entryFile), input2.filePath);
|
|
7086
|
-
if (entryRelative && !entryRelative.startsWith("..")) {
|
|
7087
|
-
return entryRelative.replaceAll("\\", "/");
|
|
7088
|
-
}
|
|
7089
|
-
return `<project>/${relative(input2.adapter.projectRoot, input2.filePath).replaceAll("\\", "/")}`;
|
|
7090
|
-
}
|
|
7091
|
-
function buildWorkersRuntimeGraphHash(input2) {
|
|
7092
|
-
const sourceFiles = Object.entries(input2.analysis.sourceFiles).map(([filePath, contents]) => ({
|
|
7093
|
-
filePath: workersRuntimeGraphFilePath({
|
|
7094
|
-
entryFile: input2.entryFile,
|
|
7095
|
-
filePath,
|
|
7096
|
-
adapter: input2.adapter
|
|
7097
|
-
}),
|
|
7098
|
-
hash: sha256(
|
|
7099
|
-
filePath === input2.entryFile ? canonicalizeRootPlayNameForWorkersRuntimeHash(contents) : contents
|
|
7100
|
-
)
|
|
7101
|
-
})).sort((left, right) => left.filePath.localeCompare(right.filePath));
|
|
7102
|
-
return sha256(
|
|
7103
|
-
JSON.stringify({
|
|
7104
|
-
entryFile: "<entry>",
|
|
7105
|
-
entryExport: input2.exportName,
|
|
7106
|
-
localFiles: sourceFiles,
|
|
7107
|
-
nodeBuiltins: [...input2.analysis.importPolicy.nodeBuiltins].sort(),
|
|
7108
|
-
packages: input2.analysis.importPolicy.packages.map(({ name, version }) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name)),
|
|
7109
|
-
importedPlayDependencies: input2.analysis.importedPlayDependencies.map((dependency) => ({
|
|
7110
|
-
filePath: workersRuntimeGraphFilePath({
|
|
7111
|
-
entryFile: input2.entryFile,
|
|
7112
|
-
filePath: dependency.filePath,
|
|
7113
|
-
adapter: input2.adapter
|
|
7114
|
-
}),
|
|
7115
|
-
playName: dependency.playName
|
|
7116
|
-
})).sort((left, right) => left.filePath.localeCompare(right.filePath))
|
|
7117
|
-
})
|
|
7118
|
-
);
|
|
7119
|
-
}
|
|
7120
|
-
function readPackageVersionFromPackageJson(packageJsonPath, packageName) {
|
|
7121
|
-
try {
|
|
7122
|
-
const packageJson = JSON.parse(readFileSync6(packageJsonPath, "utf-8"));
|
|
7123
|
-
if (packageJson.name === packageName && typeof packageJson.version === "string") {
|
|
7124
|
-
return packageJson.version;
|
|
7125
|
-
}
|
|
7126
|
-
} catch {
|
|
7127
|
-
return null;
|
|
7128
|
-
}
|
|
7129
|
-
return null;
|
|
7130
|
-
}
|
|
7131
|
-
function findPackageJsonPathFrom(startDir, packageName) {
|
|
7132
|
-
if (!isAbsolute(startDir)) {
|
|
7133
|
-
throw new Error(
|
|
7134
|
-
`Package resolution requires an absolute start directory, got ${startDir}`
|
|
7135
|
-
);
|
|
7136
|
-
}
|
|
7137
|
-
let current = startDir;
|
|
7138
|
-
while (true) {
|
|
7139
|
-
const packageJsonPath = join5(
|
|
7140
|
-
current,
|
|
7141
|
-
"node_modules",
|
|
7142
|
-
packageName,
|
|
7143
|
-
"package.json"
|
|
7144
|
-
);
|
|
7145
|
-
if (existsSync6(packageJsonPath)) {
|
|
7146
|
-
return packageJsonPath;
|
|
7147
|
-
}
|
|
7148
|
-
const parent = dirname6(current);
|
|
7149
|
-
if (parent === current) {
|
|
7150
|
-
return null;
|
|
7151
|
-
}
|
|
7152
|
-
current = parent;
|
|
7153
|
-
}
|
|
7154
|
-
}
|
|
7155
|
-
function findPackageJsonPath(packageName, fromFile, adapter) {
|
|
7156
|
-
const startDirs = [
|
|
7157
|
-
resolve6(dirname6(fromFile)),
|
|
7158
|
-
resolve6(adapter.projectRoot),
|
|
7159
|
-
resolve6(dirname6(adapter.sdkPackageJson))
|
|
7160
|
-
];
|
|
7161
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7162
|
-
for (const startDir of startDirs) {
|
|
7163
|
-
if (seen.has(startDir)) continue;
|
|
7164
|
-
seen.add(startDir);
|
|
7165
|
-
const packageJsonPath = findPackageJsonPathFrom(startDir, packageName);
|
|
7166
|
-
if (packageJsonPath) return packageJsonPath;
|
|
7167
|
-
}
|
|
7168
|
-
const adapterNodeModulesPackageJson = join5(
|
|
7169
|
-
adapter.nodeModulesDir,
|
|
7170
|
-
packageName,
|
|
7171
|
-
"package.json"
|
|
7172
|
-
);
|
|
7173
|
-
return existsSync6(adapterNodeModulesPackageJson) ? adapterNodeModulesPackageJson : null;
|
|
7174
|
-
}
|
|
7175
|
-
function localSdkAliasPlugin(adapter, options) {
|
|
7176
|
-
const entryFile = options?.workersRuntime ? adapter.sdkWorkersEntryFile : adapter.sdkEntryFile;
|
|
7177
|
-
if (!existsSync6(entryFile)) {
|
|
7178
|
-
return null;
|
|
7179
|
-
}
|
|
7180
|
-
return {
|
|
7181
|
-
name: "deepline-sdk-local-alias",
|
|
7182
|
-
setup(buildContext) {
|
|
7183
|
-
buildContext.onResolve({ filter: /^deepline$/ }, () => ({
|
|
7184
|
-
path: entryFile
|
|
7185
|
-
}));
|
|
7186
|
-
buildContext.onResolve({ filter: /^deepline\/helpers$/ }, () => ({
|
|
7187
|
-
path: join5(adapter.sdkSourceRoot, "helpers.ts")
|
|
7188
|
-
}));
|
|
7189
|
-
}
|
|
7190
|
-
};
|
|
7191
|
-
}
|
|
7192
|
-
function workersPlayEntryAliasPlugin(playFilePath) {
|
|
7193
|
-
return {
|
|
7194
|
-
name: "deepline-workers-play-entry-alias",
|
|
7195
|
-
setup(buildContext) {
|
|
7196
|
-
buildContext.onResolve(
|
|
7197
|
-
{ filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
|
|
7198
|
-
() => ({ path: playFilePath })
|
|
7199
|
-
);
|
|
7200
|
-
}
|
|
7201
|
-
};
|
|
7202
|
-
}
|
|
7203
|
-
function workersNamedPlayEntryAliasPlugin(playFilePath, exportName) {
|
|
7204
|
-
return {
|
|
7205
|
-
name: "deepline-workers-named-play-entry-alias",
|
|
7206
|
-
setup(buildContext) {
|
|
7207
|
-
buildContext.onResolve(
|
|
7208
|
-
{ filter: new RegExp(`^${WORKERS_PLAY_ENTRY_VIRTUAL}$`) },
|
|
7209
|
-
() => ({
|
|
7210
|
-
path: `${playFilePath}.${exportName}.entry.ts`,
|
|
7211
|
-
namespace: "deepline-named-play-entry"
|
|
7212
|
-
})
|
|
7213
|
-
);
|
|
7214
|
-
buildContext.onLoad(
|
|
7215
|
-
{ filter: /.*/, namespace: "deepline-named-play-entry" },
|
|
7216
|
-
() => ({
|
|
7217
|
-
contents: `export { ${exportName} as default } from ${JSON.stringify(playFilePath)};
|
|
7218
|
-
`,
|
|
7219
|
-
loader: "ts",
|
|
7220
|
-
resolveDir: dirname6(playFilePath)
|
|
7221
|
-
})
|
|
7222
|
-
);
|
|
7223
|
-
}
|
|
7224
|
-
};
|
|
7225
|
-
}
|
|
7226
|
-
function workersNodeBuiltinStubPlugin() {
|
|
7227
|
-
const UNSUPPORTED = /* @__PURE__ */ new Set([
|
|
7228
|
-
"node:fs",
|
|
7229
|
-
"node:fs/promises",
|
|
7230
|
-
"node:os",
|
|
7231
|
-
"node:child_process"
|
|
7232
|
-
]);
|
|
7233
|
-
return {
|
|
7234
|
-
name: "deepline-workers-node-builtin-stub",
|
|
7235
|
-
setup(buildContext) {
|
|
7236
|
-
buildContext.onResolve({ filter: /^node:/ }, (args) => {
|
|
7237
|
-
if (!UNSUPPORTED.has(args.path)) return null;
|
|
7238
|
-
return { path: args.path, namespace: "deepline-workers-node-stub" };
|
|
7239
|
-
});
|
|
7240
|
-
buildContext.onLoad(
|
|
7241
|
-
{ filter: /.*/, namespace: "deepline-workers-node-stub" },
|
|
7242
|
-
(args) => {
|
|
7243
|
-
const builtinName = args.path;
|
|
7244
|
-
const stubSource = `
|
|
7245
|
-
const message = ${JSON.stringify(
|
|
7246
|
-
`Workers backend: ${builtinName} is not available in Cloudflare Workers (no filesystem / no OS). Run this play on Daytona or local-process backend if it needs node builtins.`
|
|
7247
|
-
)};
|
|
7248
|
-
function makeThrower(name) {
|
|
7249
|
-
return new Proxy(function() { throw new Error(message + ' (called: ' + name + ')'); }, {
|
|
7250
|
-
get(_t, prop) {
|
|
7251
|
-
if (prop === '__esModule') return true;
|
|
7252
|
-
if (typeof prop === 'symbol') return undefined;
|
|
7253
|
-
return makeThrower(name + '.' + String(prop));
|
|
7254
|
-
},
|
|
7255
|
-
apply() { throw new Error(message + ' (called: ' + name + ')'); },
|
|
7256
|
-
construct() { throw new Error(message + ' (constructed: ' + name + ')'); },
|
|
7257
|
-
});
|
|
7258
|
-
}
|
|
7259
|
-
module.exports = makeThrower(${JSON.stringify(builtinName)});
|
|
7260
|
-
`;
|
|
7261
|
-
return { contents: stubSource, loader: "js" };
|
|
7262
|
-
}
|
|
7263
|
-
);
|
|
7264
|
-
}
|
|
7265
|
-
};
|
|
7266
|
-
}
|
|
7267
|
-
function zodNonEnglishLocaleStubPlugin() {
|
|
7268
|
-
const LOCALE_PATH_FILTER = /[\\/]zod[\\/]v4[\\/]locales[\\/][^\\/]+\.(?:c?js|mjs)$/;
|
|
7269
|
-
const NAMESPACE = "deepline-zod-locale-stub";
|
|
7270
|
-
return {
|
|
7271
|
-
name: "deepline-zod-non-english-locale-stub",
|
|
7272
|
-
setup(buildContext) {
|
|
7273
|
-
buildContext.onResolve({ filter: LOCALE_PATH_FILTER }, (args) => {
|
|
7274
|
-
const norm = args.path.replace(/\\/g, "/");
|
|
7275
|
-
const file = norm.slice(norm.lastIndexOf("/") + 1);
|
|
7276
|
-
if (/^en(?:[-_][A-Za-z]+)?\.(?:c?js|mjs)$/.test(file)) {
|
|
7277
|
-
return null;
|
|
7278
|
-
}
|
|
7279
|
-
return { path: args.path, namespace: NAMESPACE };
|
|
7280
|
-
});
|
|
7281
|
-
buildContext.onLoad({ filter: /.*/, namespace: NAMESPACE }, () => ({
|
|
7282
|
-
// zod locales export a default object literal. Empty object is
|
|
7283
|
-
// structurally compatible — accessing any locale key returns
|
|
7284
|
-
// undefined and zod falls back to its built-in English.
|
|
7285
|
-
contents: "export default {};",
|
|
7286
|
-
loader: "js"
|
|
7287
|
-
}));
|
|
7288
|
-
}
|
|
7289
|
-
};
|
|
7290
|
-
}
|
|
7291
|
-
var WORKERS_BANNED_NODE_MODULES = /* @__PURE__ */ new Set([
|
|
7292
|
-
"node:fs",
|
|
7293
|
-
"node:fs/promises",
|
|
7294
|
-
"node:net",
|
|
7295
|
-
"node:child_process",
|
|
7296
|
-
"node:cluster",
|
|
7297
|
-
"node:tls",
|
|
7298
|
-
"node:dgram",
|
|
7299
|
-
"node:dns",
|
|
7300
|
-
"node:dns/promises",
|
|
7301
|
-
"node:repl",
|
|
7302
|
-
"node:vm",
|
|
7303
|
-
"node:worker_threads"
|
|
7304
|
-
]);
|
|
7305
|
-
function workersNodeImportBanlistPlugin(adapter) {
|
|
7306
|
-
return {
|
|
7307
|
-
name: "deepline-workers-node-import-banlist",
|
|
7308
|
-
setup(buildContext) {
|
|
7309
|
-
buildContext.onResolve({ filter: /^node:/ }, (args) => {
|
|
7310
|
-
if (!WORKERS_BANNED_NODE_MODULES.has(args.path)) return null;
|
|
7311
|
-
const importer = args.importer ?? "";
|
|
7312
|
-
if (importer.startsWith(adapter.sdkSourceRoot)) {
|
|
7313
|
-
return null;
|
|
7314
|
-
}
|
|
7315
|
-
return {
|
|
7316
|
-
errors: [
|
|
7317
|
-
{
|
|
7318
|
-
text: `Module "${args.path}" is not allowed in workers_edge plays. See AGENTS.md for the V8 isolate boundary.`,
|
|
7319
|
-
detail: { importer: args.importer, kind: args.kind }
|
|
7320
|
-
}
|
|
7321
|
-
]
|
|
7322
|
-
};
|
|
7323
|
-
});
|
|
7324
|
-
}
|
|
7325
|
-
};
|
|
7326
|
-
}
|
|
7327
|
-
function buildImportedPlayProxyModule(playName) {
|
|
7328
|
-
const serializedName = JSON.stringify(playName);
|
|
7329
|
-
return `
|
|
7330
|
-
const PLAY_METADATA_SYMBOL = Symbol.for('deepline.play.metadata');
|
|
7331
|
-
const importedPlayRef = async function importedPlayRef(ctx, input) {
|
|
7332
|
-
return ctx.runPlay(${JSON.stringify(`imported_${playName.replace(/[^A-Za-z0-9_]+/g, "_")}`)}, importedPlayRef, input, {
|
|
7333
|
-
description: 'Run the imported Deepline play dependency.',
|
|
7334
|
-
});
|
|
7335
|
-
};
|
|
7336
|
-
Object.defineProperty(importedPlayRef, 'playName', {
|
|
7337
|
-
value: ${serializedName},
|
|
7338
|
-
enumerable: true,
|
|
7339
|
-
configurable: false,
|
|
7340
|
-
writable: false,
|
|
7341
|
-
});
|
|
7342
|
-
Object.defineProperty(importedPlayRef, PLAY_METADATA_SYMBOL, {
|
|
7343
|
-
value: { name: ${serializedName} },
|
|
7344
|
-
enumerable: false,
|
|
7345
|
-
configurable: false,
|
|
7346
|
-
writable: false,
|
|
7347
|
-
});
|
|
7348
|
-
export const playName = ${serializedName};
|
|
7349
|
-
export const name = ${serializedName};
|
|
7350
|
-
export default importedPlayRef;
|
|
7351
|
-
`;
|
|
7352
|
-
}
|
|
7353
|
-
function importedPlayProxyPlugin(importedPlayDependencies) {
|
|
7354
|
-
if (importedPlayDependencies.length === 0) {
|
|
7355
|
-
return null;
|
|
7356
|
-
}
|
|
7357
|
-
const dependenciesByPath = new Map(
|
|
7358
|
-
importedPlayDependencies.map((dependency) => [
|
|
7359
|
-
dependency.filePath,
|
|
7360
|
-
dependency
|
|
7361
|
-
])
|
|
7362
|
-
);
|
|
7363
|
-
return {
|
|
7364
|
-
name: "deepline-imported-play-proxy",
|
|
7365
|
-
setup(buildContext) {
|
|
7366
|
-
buildContext.onResolve({ filter: /.*/ }, async (args) => {
|
|
7367
|
-
if (!args.importer || !isLocalSpecifier(args.path)) {
|
|
7368
|
-
return null;
|
|
7369
|
-
}
|
|
7370
|
-
const resolvedPath = await resolveLocalImport(args.importer, args.path);
|
|
7371
|
-
const dependency = dependenciesByPath.get(resolvedPath);
|
|
7372
|
-
if (!dependency) {
|
|
7373
|
-
return null;
|
|
7374
|
-
}
|
|
7375
|
-
return {
|
|
7376
|
-
path: dependency.filePath,
|
|
7377
|
-
namespace: PLAY_PROXY_NAMESPACE,
|
|
7378
|
-
pluginData: dependency
|
|
7379
|
-
};
|
|
7380
|
-
});
|
|
7381
|
-
buildContext.onLoad(
|
|
7382
|
-
{ filter: /.*/, namespace: PLAY_PROXY_NAMESPACE },
|
|
7383
|
-
async (args) => {
|
|
7384
|
-
const dependency = args.pluginData ?? dependenciesByPath.get(args.path);
|
|
7385
|
-
if (!dependency) {
|
|
7386
|
-
return null;
|
|
7387
|
-
}
|
|
7388
|
-
return {
|
|
7389
|
-
contents: buildImportedPlayProxyModule(dependency.playName),
|
|
7390
|
-
loader: "ts",
|
|
7391
|
-
resolveDir: dirname6(args.path)
|
|
7392
|
-
};
|
|
7393
|
-
}
|
|
7394
|
-
);
|
|
7395
|
-
}
|
|
7396
|
-
};
|
|
7397
|
-
}
|
|
7398
|
-
async function fileExists(filePath) {
|
|
7399
|
-
try {
|
|
7400
|
-
await stat(filePath);
|
|
7401
|
-
return true;
|
|
7402
|
-
} catch {
|
|
7403
|
-
return false;
|
|
7404
|
-
}
|
|
7405
|
-
}
|
|
7406
|
-
async function resolveLocalImport(fromFile, specifier) {
|
|
7407
|
-
if (specifier.startsWith("file:")) {
|
|
7408
|
-
return normalizeLocalPath(new URL(specifier).pathname);
|
|
7409
|
-
}
|
|
7410
|
-
const base = isAbsolute(specifier) ? resolve6(specifier) : resolve6(dirname6(fromFile), specifier);
|
|
7411
|
-
const candidates = [base];
|
|
7412
|
-
const explicitExtension = extname(base).toLowerCase();
|
|
7413
|
-
if (!explicitExtension) {
|
|
7414
|
-
candidates.push(
|
|
7415
|
-
...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`)
|
|
7416
|
-
);
|
|
7417
|
-
candidates.push(
|
|
7418
|
-
...SOURCE_EXTENSIONS.map((extension) => join5(base, `index${extension}`))
|
|
7419
|
-
);
|
|
7420
|
-
} else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
|
|
7421
|
-
const stem = base.slice(0, -explicitExtension.length);
|
|
7422
|
-
candidates.push(
|
|
7423
|
-
...SOURCE_EXTENSIONS.map((extension) => `${stem}${extension}`)
|
|
7424
|
-
);
|
|
7425
|
-
}
|
|
7426
|
-
for (const candidate of candidates) {
|
|
7427
|
-
if (await fileExists(candidate)) {
|
|
7428
|
-
return normalizeLocalPath(candidate);
|
|
7429
|
-
}
|
|
7430
|
-
}
|
|
7431
|
-
throw new Error(
|
|
7432
|
-
`Could not resolve local import "${specifier}" from ${fromFile}`
|
|
7433
|
-
);
|
|
7434
|
-
}
|
|
7435
|
-
function resolvePackageImport(specifier, fromFile, adapter) {
|
|
7436
|
-
const packageName = getPackageName(specifier);
|
|
7437
|
-
if (packageName === "deepline" && existsSync6(adapter.sdkPackageJson)) {
|
|
7438
|
-
const packageJson = JSON.parse(
|
|
7439
|
-
readFileSync6(adapter.sdkPackageJson, "utf-8")
|
|
7440
|
-
);
|
|
7441
|
-
return {
|
|
7442
|
-
name: "deepline",
|
|
7443
|
-
version: packageJson.version ?? null
|
|
7444
|
-
};
|
|
7445
|
-
}
|
|
7446
|
-
const packageJsonPath = findPackageJsonPath(packageName, fromFile, adapter);
|
|
7447
|
-
if (!packageJsonPath) {
|
|
7448
|
-
throw new Error(`Could not resolve "${specifier}" from ${fromFile}`);
|
|
7449
|
-
}
|
|
7450
|
-
return {
|
|
7451
|
-
name: packageName,
|
|
7452
|
-
version: readPackageVersionFromPackageJson(packageJsonPath, packageName)
|
|
7453
|
-
};
|
|
7454
|
-
}
|
|
7455
|
-
async function analyzeSourceGraph(entryFile, adapter) {
|
|
7456
|
-
const absoluteEntryFile = await normalizeLocalPath(entryFile);
|
|
7457
|
-
const workspace = createPlayWorkspace(absoluteEntryFile);
|
|
7458
|
-
const localFiles = /* @__PURE__ */ new Map();
|
|
7459
|
-
const nodeBuiltins = /* @__PURE__ */ new Set();
|
|
7460
|
-
const packages = /* @__PURE__ */ new Map();
|
|
7461
|
-
const importedPlayDependencies = /* @__PURE__ */ new Map();
|
|
7462
|
-
const visited = /* @__PURE__ */ new Set();
|
|
7463
|
-
const visitFile = async (filePath) => {
|
|
7464
|
-
const absolutePath = await normalizeLocalPath(filePath);
|
|
7465
|
-
if (visited.has(absolutePath)) {
|
|
7466
|
-
return;
|
|
7467
|
-
}
|
|
7468
|
-
visited.add(absolutePath);
|
|
7469
|
-
const sourceCode2 = await readFile(absolutePath, "utf-8");
|
|
7470
|
-
localFiles.set(absolutePath, sourceCode2);
|
|
7471
|
-
if (extname(absolutePath).toLowerCase() === ".json") {
|
|
7472
|
-
return;
|
|
7473
|
-
}
|
|
7474
|
-
const handleSpecifier = async (specifier, line, column, kind) => {
|
|
7475
|
-
if (kind === "dynamic-import") {
|
|
7476
|
-
throw new Error(
|
|
7477
|
-
`${absolutePath}:${line}:${column} Dynamic import() is not allowed in plays. Use static imports instead.`
|
|
7478
|
-
);
|
|
7479
|
-
}
|
|
7480
|
-
if (NODE_BUILTIN_SET.has(specifier)) {
|
|
7481
|
-
nodeBuiltins.add(
|
|
7482
|
-
specifier.startsWith("node:") ? specifier : `node:${specifier}`
|
|
7483
|
-
);
|
|
7484
|
-
return;
|
|
7485
|
-
}
|
|
7486
|
-
if (isLocalSpecifier(specifier)) {
|
|
7487
|
-
const resolved = await resolveLocalImport(absolutePath, specifier);
|
|
7488
|
-
assertWithinPlayWorkspace({
|
|
7489
|
-
importer: absolutePath,
|
|
7490
|
-
specifier,
|
|
7491
|
-
resolvedPath: resolved,
|
|
7492
|
-
workspace,
|
|
7493
|
-
line,
|
|
7494
|
-
column
|
|
7495
|
-
});
|
|
7496
|
-
if (resolved !== absoluteEntryFile && isPlaySourceFile(resolved)) {
|
|
7497
|
-
const importedSource = await readFile(resolved, "utf-8");
|
|
7498
|
-
const importedPlayName = extractDefinedPlayName(importedSource);
|
|
7499
|
-
if (!importedPlayName) {
|
|
7500
|
-
throw new Error(
|
|
7501
|
-
`${absolutePath}:${line}:${column} Imported play file "${specifier}" must export definePlay(...) so it can be runtime-composed.`
|
|
7502
|
-
);
|
|
7503
|
-
}
|
|
7504
|
-
importedPlayDependencies.set(resolved, {
|
|
7505
|
-
filePath: resolved,
|
|
7506
|
-
playName: importedPlayName
|
|
7507
|
-
});
|
|
7508
|
-
return;
|
|
7509
|
-
}
|
|
7510
|
-
await visitFile(resolved);
|
|
7511
|
-
return;
|
|
7512
|
-
}
|
|
7513
|
-
if (specifier.includes(":")) {
|
|
7514
|
-
throw new Error(
|
|
7515
|
-
`${absolutePath}:${line}:${column} Unsupported import specifier "${specifier}". Allowed imports are relative files, Node builtins, and installed packages.`
|
|
7516
|
-
);
|
|
7517
|
-
}
|
|
7518
|
-
const packageImport = resolvePackageImport(
|
|
7519
|
-
specifier,
|
|
7520
|
-
absolutePath,
|
|
7521
|
-
adapter
|
|
7522
|
-
);
|
|
7523
|
-
packages.set(packageImport.name, packageImport.version);
|
|
7524
|
-
};
|
|
7525
|
-
try {
|
|
7526
|
-
for (const reference of findSourceImportReferences(sourceCode2)) {
|
|
7527
|
-
await handleSpecifier(
|
|
7528
|
-
reference.specifier,
|
|
7529
|
-
reference.line,
|
|
7530
|
-
reference.column,
|
|
7531
|
-
reference.kind
|
|
7532
|
-
);
|
|
7533
|
-
}
|
|
7534
|
-
} catch (error) {
|
|
7535
|
-
if (error instanceof Error && error.message.startsWith(":")) {
|
|
7536
|
-
throw new Error(`${absolutePath}${error.message}`);
|
|
7537
|
-
}
|
|
7538
|
-
throw error;
|
|
7539
|
-
}
|
|
7540
|
-
};
|
|
7541
|
-
await visitFile(absoluteEntryFile);
|
|
7542
|
-
const sourceCode = localFiles.get(absoluteEntryFile) ?? "";
|
|
7543
|
-
const sourceHash = sha256(sourceCode);
|
|
7544
|
-
const graphHash = sha256(
|
|
7545
|
-
JSON.stringify({
|
|
7546
|
-
entryFile: absoluteEntryFile,
|
|
7547
|
-
localFiles: [...localFiles.entries()].map(([filePath, contents]) => ({ filePath, hash: sha256(contents) })).sort((left, right) => left.filePath.localeCompare(right.filePath)),
|
|
7548
|
-
nodeBuiltins: [...nodeBuiltins].sort(),
|
|
7549
|
-
packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name)),
|
|
7550
|
-
importedPlayDependencies: [...importedPlayDependencies.values()].map((dependency) => ({
|
|
7551
|
-
filePath: dependency.filePath,
|
|
7552
|
-
playName: dependency.playName
|
|
7553
|
-
})).sort((left, right) => left.filePath.localeCompare(right.filePath))
|
|
7554
|
-
})
|
|
7555
|
-
);
|
|
7556
|
-
const playName = extractDefinedPlayName(sourceCode);
|
|
7557
|
-
return {
|
|
7558
|
-
sourceCode,
|
|
7559
|
-
sourceFiles: Object.fromEntries(
|
|
7560
|
-
[...localFiles.entries()].sort(
|
|
7561
|
-
(left, right) => left[0].localeCompare(right[0])
|
|
7562
|
-
)
|
|
7563
|
-
),
|
|
7564
|
-
sourceHash,
|
|
7565
|
-
graphHash,
|
|
7566
|
-
importPolicy: {
|
|
7567
|
-
localFiles: [...localFiles.keys()].sort(),
|
|
7568
|
-
nodeBuiltins: [...nodeBuiltins].sort(),
|
|
7569
|
-
packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name))
|
|
7570
|
-
},
|
|
7571
|
-
playName,
|
|
7572
|
-
importedPlayDependencies: [...importedPlayDependencies.values()].sort(
|
|
7573
|
-
(left, right) => left.filePath.localeCompare(right.filePath)
|
|
7574
|
-
)
|
|
7575
|
-
};
|
|
7576
|
-
}
|
|
7577
|
-
async function computeWorkersHarnessFingerprintWithAdapter(adapter) {
|
|
7578
|
-
const { readdir } = await import("fs/promises");
|
|
7579
|
-
const addFilePart = async (parts2, rootDir, filePath) => {
|
|
7580
|
-
const contents = await readFile(filePath, "utf-8");
|
|
7581
|
-
parts2.push({
|
|
7582
|
-
name: `${basename(rootDir)}:${filePath.slice(rootDir.length + 1)}`,
|
|
7583
|
-
hash: sha256(contents)
|
|
7584
|
-
});
|
|
7585
|
-
};
|
|
7586
|
-
const collectTopLevelTsFiles = async (rootDir, parts2) => {
|
|
7587
|
-
if (!await fileExists(rootDir)) return;
|
|
7588
|
-
const entries2 = await readdir(rootDir, { withFileTypes: true });
|
|
7589
|
-
const tsFiles2 = entries2.filter((entry) => entry.isFile() && /\.[cm]?ts$/.test(entry.name)).map((entry) => entry.name).sort();
|
|
7590
|
-
for (const name of tsFiles2) {
|
|
7591
|
-
await addFilePart(parts2, rootDir, join5(rootDir, name));
|
|
7592
|
-
}
|
|
7593
|
-
};
|
|
7594
|
-
const collectIntegrationBatchingFiles = async (rootDir, parts2) => {
|
|
7595
|
-
if (!await fileExists(rootDir)) return;
|
|
7596
|
-
const entries2 = await readdir(rootDir, { withFileTypes: true });
|
|
7597
|
-
const filePaths = [];
|
|
7598
|
-
for (const entry of entries2) {
|
|
7599
|
-
if (entry.isFile() && (entry.name === "play-runtime-batching-registry.ts" || /^batching.*\.ts$/.test(entry.name))) {
|
|
7600
|
-
filePaths.push(join5(rootDir, entry.name));
|
|
7601
|
-
}
|
|
7602
|
-
if (entry.isDirectory()) {
|
|
7603
|
-
const batchingFile = join5(rootDir, entry.name, "batching.ts");
|
|
7604
|
-
if (await fileExists(batchingFile)) {
|
|
7605
|
-
filePaths.push(batchingFile);
|
|
7606
|
-
}
|
|
7607
|
-
}
|
|
7608
|
-
}
|
|
7609
|
-
for (const filePath of filePaths.sort()) {
|
|
7610
|
-
await addFilePart(parts2, rootDir, filePath);
|
|
7611
|
-
}
|
|
7612
|
-
};
|
|
7613
|
-
const entries = await readdir(adapter.workersHarnessFilesDir, {
|
|
7614
|
-
withFileTypes: true
|
|
7615
|
-
});
|
|
7616
|
-
const tsFiles = entries.filter((e) => e.isFile() && /\.[cm]?ts$/.test(e.name)).map((e) => e.name).sort();
|
|
7617
|
-
const parts = [];
|
|
7618
|
-
for (const name of tsFiles) {
|
|
7619
|
-
await addFilePart(
|
|
7620
|
-
parts,
|
|
7621
|
-
adapter.workersHarnessFilesDir,
|
|
7622
|
-
join5(adapter.workersHarnessFilesDir, name)
|
|
7623
|
-
);
|
|
7624
|
-
}
|
|
7625
|
-
for (const dir of adapter.workersRuntimeFingerprintDirs ?? []) {
|
|
7626
|
-
if (basename(dir) === "integrations") {
|
|
7627
|
-
await collectIntegrationBatchingFiles(dir, parts);
|
|
7628
|
-
} else {
|
|
7629
|
-
await collectTopLevelTsFiles(dir, parts);
|
|
7630
|
-
}
|
|
7631
|
-
}
|
|
7632
|
-
return sha256(JSON.stringify(parts));
|
|
7633
|
-
}
|
|
7634
|
-
function artifactCachePath(graphHash, artifactKind, adapter) {
|
|
7635
|
-
return join5(
|
|
7636
|
-
adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR,
|
|
7637
|
-
`${graphHash}.${artifactKind}.json`
|
|
7638
|
-
);
|
|
7639
|
-
}
|
|
7640
|
-
async function readArtifactCache(graphHash, artifactKind, adapter) {
|
|
7641
|
-
try {
|
|
7642
|
-
const serialized = await readFile(
|
|
7643
|
-
artifactCachePath(graphHash, artifactKind, adapter),
|
|
7644
|
-
"utf-8"
|
|
7645
|
-
);
|
|
7646
|
-
return JSON.parse(serialized);
|
|
7647
|
-
} catch {
|
|
7648
|
-
return null;
|
|
7649
|
-
}
|
|
7650
|
-
}
|
|
7651
|
-
async function writeArtifactCache(artifact, adapter) {
|
|
7652
|
-
const cacheDir = adapter.cacheDir ?? PLAY_ARTIFACT_CACHE_DIR;
|
|
7653
|
-
await mkdir3(cacheDir, { recursive: true });
|
|
7654
|
-
await writeFile3(
|
|
7655
|
-
artifactCachePath(
|
|
7656
|
-
artifact.graphHash,
|
|
7657
|
-
artifact.artifactKind ?? PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
7658
|
-
adapter
|
|
7659
|
-
),
|
|
7660
|
-
JSON.stringify(artifact),
|
|
7661
|
-
"utf-8"
|
|
7662
|
-
);
|
|
7663
|
-
}
|
|
7664
|
-
function normalizeSourceMapForRuntime(sourceMapText, projectRoot) {
|
|
7665
|
-
const parsed = JSON.parse(sourceMapText);
|
|
7666
|
-
parsed.sources = (parsed.sources ?? []).map((sourcePath) => {
|
|
7667
|
-
if (sourcePath.startsWith("data:") || sourcePath.startsWith("node:") || sourcePath.startsWith("/") || /^[a-zA-Z]+:\/\//.test(sourcePath)) {
|
|
7668
|
-
return sourcePath;
|
|
7669
|
-
}
|
|
7670
|
-
return join5(projectRoot, sourcePath);
|
|
7671
|
-
});
|
|
7672
|
-
parsed.sourceRoot = void 0;
|
|
7673
|
-
return JSON.stringify(parsed);
|
|
7674
|
-
}
|
|
7675
|
-
function getBundleSizeErrorForBytes(filePath, bundleBytes, artifactKind) {
|
|
7676
|
-
if (bundleBytes > MAX_PLAY_BUNDLE_BYTES) {
|
|
7677
|
-
return `${filePath} Play bundle exceeds the 30 MiB limit (${bundleBytes} bytes > ${MAX_PLAY_BUNDLE_BYTES} bytes).`;
|
|
7678
|
-
}
|
|
7679
|
-
if (artifactKind === PLAY_ARTIFACT_KINDS.esmWorkers && bundleBytes > MAX_ESM_WORKERS_BUNDLE_BYTES) {
|
|
7680
|
-
const mib = (bundleBytes / 1024 / 1024).toFixed(2);
|
|
7681
|
-
const limitMib = (MAX_ESM_WORKERS_BUNDLE_BYTES / 1024 / 1024).toFixed(2);
|
|
7682
|
-
return `${filePath} Cloudflare Workers bundle is ${mib} MiB, above the workerd local-mode threshold of ${limitMib} MiB. Bundles past this size silently hang without executing the workflow body. Reduce dependencies (top offenders are usually date-fns, lodash, large schema libs) or split the play into smaller pieces with ctx.runPlay.`;
|
|
7683
|
-
}
|
|
7684
|
-
return null;
|
|
7685
|
-
}
|
|
7686
|
-
function getBundleSizeError(filePath, bundledCode, artifactKind) {
|
|
7687
|
-
return getBundleSizeErrorForBytes(
|
|
7688
|
-
filePath,
|
|
7689
|
-
Buffer.byteLength(bundledCode, "utf8"),
|
|
7690
|
-
artifactKind
|
|
7691
|
-
);
|
|
7692
|
-
}
|
|
7693
|
-
async function runEsbuildForCjsNode(entryFile, importedPlayDependencies, adapter, exportName) {
|
|
7694
|
-
const sdkAliasPlugin = localSdkAliasPlugin(adapter);
|
|
7695
|
-
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
7696
|
-
const namedExportShim = exportName === "default" ? null : `export { ${exportName} as default } from ${JSON.stringify(entryFile)};
|
|
7697
|
-
`;
|
|
7698
|
-
const result = await build({
|
|
7699
|
-
...namedExportShim ? {
|
|
7700
|
-
stdin: {
|
|
7701
|
-
contents: namedExportShim,
|
|
7702
|
-
resolveDir: dirname6(entryFile),
|
|
7703
|
-
sourcefile: `${basename(entryFile)}.${exportName}.entry.ts`,
|
|
7704
|
-
loader: "ts"
|
|
7705
|
-
}
|
|
7706
|
-
} : { entryPoints: [entryFile] },
|
|
7707
|
-
absWorkingDir: adapter.projectRoot,
|
|
7708
|
-
bundle: true,
|
|
7709
|
-
format: "cjs",
|
|
7710
|
-
nodePaths: [adapter.nodeModulesDir],
|
|
7711
|
-
platform: "node",
|
|
7712
|
-
target: ["node20"],
|
|
7713
|
-
outfile: "play-artifact.cjs",
|
|
7714
|
-
write: false,
|
|
7715
|
-
sourcemap: "external",
|
|
7716
|
-
sourcesContent: false,
|
|
7717
|
-
logLevel: "silent",
|
|
7718
|
-
legalComments: "none",
|
|
7719
|
-
plugins: [sdkAliasPlugin, playProxyPlugin].filter(
|
|
7720
|
-
(plugin) => plugin != null
|
|
7721
|
-
)
|
|
7722
|
-
});
|
|
7723
|
-
const codeFile = result.outputFiles?.find((f) => f.path.endsWith(".cjs"));
|
|
7724
|
-
const mapFile = result.outputFiles?.find((f) => f.path.endsWith(".cjs.map"));
|
|
7725
|
-
if (!codeFile?.text || !mapFile?.text) {
|
|
7726
|
-
return ["Play bundling produced incomplete output."];
|
|
7727
|
-
}
|
|
7728
|
-
return {
|
|
7729
|
-
bundledCode: codeFile.text,
|
|
7730
|
-
sourceMapText: mapFile.text,
|
|
7731
|
-
outputExtension: "cjs"
|
|
7732
|
-
};
|
|
7733
|
-
}
|
|
7734
|
-
async function runEsbuildForEsmWorkers(playEntryFile, importedPlayDependencies, adapter, exportName) {
|
|
7735
|
-
const sdkAliasPlugin = localSdkAliasPlugin(adapter, { workersRuntime: true });
|
|
7736
|
-
const playProxyPlugin = importedPlayProxyPlugin(importedPlayDependencies);
|
|
7737
|
-
const playEntryAlias = exportName === "default" ? workersPlayEntryAliasPlugin(playEntryFile) : workersNamedPlayEntryAliasPlugin(playEntryFile, exportName);
|
|
7738
|
-
const result = await build({
|
|
7739
|
-
// Entry is the Workers harness; it imports the play via the virtual
|
|
7740
|
-
// `deepline-play-entry` alias resolved by workersPlayEntryAliasPlugin.
|
|
7741
|
-
entryPoints: [adapter.workersHarnessEntryFile],
|
|
7742
|
-
absWorkingDir: adapter.projectRoot,
|
|
7743
|
-
bundle: true,
|
|
7744
|
-
format: "esm",
|
|
7745
|
-
nodePaths: [adapter.nodeModulesDir],
|
|
7746
|
-
// Browser platform with workerd + worker conditions matches Cloudflare's
|
|
7747
|
-
// V8-isolate runtime. Avoids accidentally pulling node-only branches of
|
|
7748
|
-
// dual-publish packages.
|
|
7749
|
-
platform: "browser",
|
|
7750
|
-
conditions: ["workerd", "worker", "browser", "import", "default"],
|
|
7751
|
-
mainFields: ["module", "main"],
|
|
7752
|
-
target: ["es2022"],
|
|
7753
|
-
outfile: "play-worker.mjs",
|
|
7754
|
-
write: false,
|
|
7755
|
-
sourcemap: "external",
|
|
7756
|
-
sourcesContent: false,
|
|
7757
|
-
logLevel: "silent",
|
|
7758
|
-
legalComments: "none",
|
|
7759
|
-
// Aggressive minify + treeshake: a tiny play (<1KB source) was producing
|
|
7760
|
-
// an ~870KB bundle, dominated by zod's locale files (~260KB unused) and
|
|
7761
|
-
// dead-code branches across `shared_libs/play-runtime/*` and the SDK.
|
|
7762
|
-
// Both DCE on with these flags. workerd compiles each unique-graphHash
|
|
7763
|
-
// bundle on first dispatch, so bundle bytes translate ~linearly into
|
|
7764
|
-
// per-play cold latency on workers_edge. External sourcemap remains
|
|
7765
|
-
// unchanged (`sourcemap: 'external'`), so debugging is unaffected.
|
|
7766
|
-
minify: true,
|
|
7767
|
-
treeShaking: true,
|
|
7768
|
-
// Most node:* builtins are provided by Cloudflare's `nodejs_compat` flag.
|
|
7769
|
-
// The unsupported subset (fs, fs/promises, os, child_process) gets
|
|
7770
|
-
// replaced with throwing stubs by workersNodeBuiltinStubPlugin so deploy
|
|
7771
|
-
// validation passes; anything supported (path, crypto, buffer, etc.) is
|
|
7772
|
-
// marked external and resolved at runtime by the Workers runtime.
|
|
7773
|
-
external: ["node:*", "cloudflare:workers"],
|
|
7774
|
-
plugins: [
|
|
7775
|
-
// Banlist runs first so a forbidden import errors out before any other
|
|
7776
|
-
// resolver (esp. the workersNodeBuiltinStubPlugin which would silently
|
|
7777
|
-
// turn it into a throwing-stub).
|
|
7778
|
-
workersNodeImportBanlistPlugin(adapter),
|
|
7779
|
-
sdkAliasPlugin,
|
|
7780
|
-
playProxyPlugin,
|
|
7781
|
-
playEntryAlias,
|
|
7782
|
-
workersNodeBuiltinStubPlugin(),
|
|
7783
|
-
// Strip non-English zod locale data from the bundle. zod's locales
|
|
7784
|
-
// are re-exported as a static namespace from `zod/v4/core`, so
|
|
7785
|
-
// tree-shaking can't drop them; this plugin replaces each
|
|
7786
|
-
// non-English locale module with an empty default export at bundle
|
|
7787
|
-
// time. ~150–200 KB savings on every per-play bundle, with no
|
|
7788
|
-
// behavior change (we only surface English messages anyway).
|
|
7789
|
-
// If the bundle suddenly grows back, check whether a new dep added
|
|
7790
|
-
// its own zod copy or whether zod's locale layout changed.
|
|
7791
|
-
zodNonEnglishLocaleStubPlugin()
|
|
7792
|
-
].filter((plugin) => plugin != null)
|
|
7793
|
-
});
|
|
7794
|
-
const codeFile = result.outputFiles?.find((f) => f.path.endsWith(".mjs"));
|
|
7795
|
-
const mapFile = result.outputFiles?.find((f) => f.path.endsWith(".mjs.map"));
|
|
7796
|
-
if (!codeFile?.text || !mapFile?.text) {
|
|
7797
|
-
return ["Workers play bundling produced incomplete output."];
|
|
7798
|
-
}
|
|
7799
|
-
return {
|
|
7800
|
-
bundledCode: codeFile.text,
|
|
7801
|
-
sourceMapText: mapFile.text,
|
|
7802
|
-
outputExtension: "mjs"
|
|
7803
|
-
};
|
|
7804
|
-
}
|
|
7805
|
-
var PLAY_ARTIFACT_TARGET_ADAPTERS = {
|
|
7806
|
-
[PLAY_ARTIFACT_KINDS.cjsNode20]: {
|
|
7807
|
-
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
7808
|
-
codeFormat: "cjs_module",
|
|
7809
|
-
includeWorkersHarnessInGraphHash: false,
|
|
7810
|
-
runEsbuild: ({
|
|
7811
|
-
entryFile,
|
|
7812
|
-
importedPlayDependencies,
|
|
7813
|
-
adapter,
|
|
7814
|
-
exportName
|
|
7815
|
-
}) => runEsbuildForCjsNode(
|
|
7816
|
-
entryFile,
|
|
7817
|
-
importedPlayDependencies,
|
|
7818
|
-
adapter,
|
|
7819
|
-
exportName
|
|
7820
|
-
)
|
|
7821
|
-
},
|
|
7822
|
-
[PLAY_ARTIFACT_KINDS.esmWorkers]: {
|
|
7823
|
-
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
7824
|
-
codeFormat: "esm_module",
|
|
7825
|
-
includeWorkersHarnessInGraphHash: true,
|
|
7826
|
-
runEsbuild: ({
|
|
7827
|
-
entryFile,
|
|
7828
|
-
importedPlayDependencies,
|
|
7829
|
-
adapter,
|
|
7830
|
-
exportName
|
|
7831
|
-
}) => runEsbuildForEsmWorkers(
|
|
7832
|
-
entryFile,
|
|
7833
|
-
importedPlayDependencies,
|
|
7834
|
-
adapter,
|
|
7835
|
-
exportName
|
|
7836
|
-
)
|
|
7837
|
-
}
|
|
7838
|
-
};
|
|
7839
|
-
function resolvePlayArtifactTargetAdapter(artifactKind) {
|
|
7840
|
-
return PLAY_ARTIFACT_TARGET_ADAPTERS[artifactKind];
|
|
7841
|
-
}
|
|
7842
|
-
async function bundlePlayFile(filePath, options) {
|
|
7843
|
-
const adapter = options.adapter;
|
|
7844
|
-
const target = options.target ?? PLAY_ARTIFACT_KINDS.cjsNode20;
|
|
7845
|
-
const targetAdapter = resolvePlayArtifactTargetAdapter(target);
|
|
7846
|
-
const exportName = options.exportName?.trim() || "default";
|
|
7847
|
-
assertValidExportName(exportName);
|
|
7848
|
-
const absolutePath = await normalizeLocalPath(filePath);
|
|
7849
|
-
adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
|
|
7850
|
-
try {
|
|
7851
|
-
const analysis = await analyzeSourceGraph(absolutePath, adapter);
|
|
7852
|
-
analysis.graphHash = target === PLAY_ARTIFACT_KINDS.esmWorkers ? buildWorkersRuntimeGraphHash({
|
|
7853
|
-
analysis,
|
|
7854
|
-
entryFile: absolutePath,
|
|
7855
|
-
adapter,
|
|
7856
|
-
exportName
|
|
7857
|
-
}) : sha256(`${analysis.graphHash}
|
|
7858
|
-
entry-export:${exportName}`);
|
|
7859
|
-
if (targetAdapter.includeWorkersHarnessInGraphHash) {
|
|
7860
|
-
const harnessFingerprint = await computeWorkersHarnessFingerprintWithAdapter(adapter);
|
|
7861
|
-
analysis.graphHash = sha256(
|
|
7862
|
-
`${analysis.graphHash}
|
|
7863
|
-
workers-harness:${harnessFingerprint}`
|
|
7864
|
-
);
|
|
7865
|
-
}
|
|
7866
|
-
try {
|
|
7867
|
-
validatePlaySourceFilesHaveNoInlineSecrets(analysis.sourceFiles);
|
|
7868
|
-
} catch (error) {
|
|
7869
|
-
return {
|
|
7870
|
-
success: false,
|
|
7871
|
-
filePath: absolutePath,
|
|
7872
|
-
errors: [error instanceof Error ? error.message : String(error)]
|
|
7873
|
-
};
|
|
7874
|
-
}
|
|
7875
|
-
const typecheckErrors = [
|
|
7876
|
-
...await adapter.typecheckPlaySource?.({
|
|
7877
|
-
sourceCode: analysis.sourceCode,
|
|
7878
|
-
sourcePath: absolutePath,
|
|
7879
|
-
importedFilePaths: [
|
|
7880
|
-
...analysis.importPolicy.localFiles,
|
|
7881
|
-
...analysis.importedPlayDependencies.map(
|
|
7882
|
-
(dependency) => dependency.filePath
|
|
7883
|
-
)
|
|
7884
|
-
]
|
|
7885
|
-
}) ?? []
|
|
7886
|
-
];
|
|
7887
|
-
if (typecheckErrors.length > 0) {
|
|
7888
|
-
return {
|
|
7889
|
-
success: false,
|
|
7890
|
-
filePath: absolutePath,
|
|
7891
|
-
errors: typecheckErrors
|
|
7892
|
-
};
|
|
7893
|
-
}
|
|
7894
|
-
const canUseArtifactCache = target !== PLAY_ARTIFACT_KINDS.esmWorkers;
|
|
7895
|
-
const cachedArtifact = canUseArtifactCache ? await readArtifactCache(analysis.graphHash, target, adapter) : null;
|
|
7896
|
-
const discoveredFiles = await adapter.discoverPackagedLocalFiles(absolutePath);
|
|
7897
|
-
if (cachedArtifact) {
|
|
7898
|
-
const cachedArtifactSizeError = getBundleSizeError(
|
|
7899
|
-
absolutePath,
|
|
7900
|
-
cachedArtifact.bundledCode,
|
|
7901
|
-
target
|
|
7902
|
-
);
|
|
7903
|
-
if (cachedArtifactSizeError) {
|
|
7904
|
-
return {
|
|
7905
|
-
success: false,
|
|
7906
|
-
filePath: absolutePath,
|
|
7907
|
-
errors: [cachedArtifactSizeError]
|
|
7908
|
-
};
|
|
7909
|
-
}
|
|
7910
|
-
return {
|
|
7911
|
-
success: true,
|
|
7912
|
-
artifact: {
|
|
7913
|
-
...cachedArtifact,
|
|
7914
|
-
entryFile: absolutePath,
|
|
7915
|
-
sourceHash: analysis.sourceHash,
|
|
7916
|
-
importPolicy: analysis.importPolicy,
|
|
7917
|
-
cacheHit: true
|
|
7918
|
-
},
|
|
7919
|
-
sourceCode: analysis.sourceCode,
|
|
7920
|
-
sourceFiles: analysis.sourceFiles,
|
|
7921
|
-
filePath: absolutePath,
|
|
7922
|
-
playName: analysis.playName,
|
|
7923
|
-
packagedFiles: discoveredFiles.files,
|
|
7924
|
-
unresolvedFileReferences: discoveredFiles.unresolved,
|
|
7925
|
-
importedPlayDependencies: analysis.importedPlayDependencies
|
|
7926
|
-
};
|
|
7927
|
-
}
|
|
7928
|
-
const buildOutcome = await targetAdapter.runEsbuild({
|
|
7929
|
-
entryFile: absolutePath,
|
|
7930
|
-
importedPlayDependencies: analysis.importedPlayDependencies,
|
|
7931
|
-
adapter,
|
|
7932
|
-
exportName
|
|
7933
|
-
});
|
|
7934
|
-
if (Array.isArray(buildOutcome)) {
|
|
7935
|
-
return {
|
|
7936
|
-
success: false,
|
|
7937
|
-
filePath: absolutePath,
|
|
7938
|
-
errors: buildOutcome
|
|
7939
|
-
};
|
|
7940
|
-
}
|
|
7941
|
-
const { bundledCode, sourceMapText, outputExtension } = buildOutcome;
|
|
7942
|
-
const normalizedSourceMap = normalizeSourceMapForRuntime(
|
|
7943
|
-
sourceMapText,
|
|
7944
|
-
resolve6(adapter.projectRoot)
|
|
7945
|
-
);
|
|
7946
|
-
const virtualBaseName = exportName === "default" ? basename(absolutePath).replace(/\.[^.]+$/, "") : `${basename(absolutePath).replace(/\.[^.]+$/, "")}.${exportName}`;
|
|
7947
|
-
const virtualFilename = `/virtual/deepline-plays/${analysis.graphHash}/${virtualBaseName}.${outputExtension}`;
|
|
7948
|
-
const executableCode = `${bundledCode}
|
|
7949
|
-
//# sourceMappingURL=${basename(virtualFilename)}.map
|
|
7950
|
-
`;
|
|
7951
|
-
const bundleSizeError = getBundleSizeError(
|
|
7952
|
-
absolutePath,
|
|
7953
|
-
executableCode,
|
|
7954
|
-
target
|
|
7955
|
-
);
|
|
7956
|
-
if (bundleSizeError) {
|
|
7957
|
-
return {
|
|
7958
|
-
success: false,
|
|
7959
|
-
filePath: absolutePath,
|
|
7960
|
-
errors: [bundleSizeError]
|
|
7961
|
-
};
|
|
7962
|
-
}
|
|
7963
|
-
const artifact = {
|
|
7964
|
-
codeFormat: targetAdapter.codeFormat,
|
|
7965
|
-
artifactKind: target,
|
|
7966
|
-
entryFile: absolutePath,
|
|
7967
|
-
virtualFilename,
|
|
7968
|
-
sourceHash: analysis.sourceHash,
|
|
7969
|
-
graphHash: analysis.graphHash,
|
|
7970
|
-
artifactHash: sha256(executableCode),
|
|
7971
|
-
sourceMapHash: sha256(normalizedSourceMap),
|
|
7972
|
-
bundledCode: executableCode,
|
|
7973
|
-
sourceMap: normalizedSourceMap,
|
|
7974
|
-
importPolicy: analysis.importPolicy,
|
|
7975
|
-
compatibility: buildPlayContractCompatibility(),
|
|
7976
|
-
generatedAt: Date.now(),
|
|
7977
|
-
cacheHit: false
|
|
7978
|
-
};
|
|
7979
|
-
if (canUseArtifactCache) {
|
|
7980
|
-
await writeArtifactCache(artifact, adapter);
|
|
7981
|
-
}
|
|
7982
|
-
return {
|
|
7983
|
-
success: true,
|
|
7984
|
-
artifact,
|
|
7985
|
-
sourceCode: analysis.sourceCode,
|
|
7986
|
-
sourceFiles: analysis.sourceFiles,
|
|
7987
|
-
filePath: absolutePath,
|
|
7988
|
-
playName: analysis.playName,
|
|
7989
|
-
packagedFiles: discoveredFiles.files,
|
|
7990
|
-
unresolvedFileReferences: discoveredFiles.unresolved,
|
|
7991
|
-
importedPlayDependencies: analysis.importedPlayDependencies
|
|
7992
|
-
};
|
|
7993
|
-
} catch (error) {
|
|
7994
|
-
if (error && typeof error === "object" && "errors" in error) {
|
|
7995
|
-
const errors = Array.isArray(error.errors) ? error.errors.map(formatEsbuildMessage) : ["Play bundling failed."];
|
|
7996
|
-
return {
|
|
7997
|
-
success: false,
|
|
7998
|
-
filePath: absolutePath,
|
|
7999
|
-
errors
|
|
8000
|
-
};
|
|
8001
|
-
}
|
|
8002
|
-
return {
|
|
8003
|
-
success: false,
|
|
8004
|
-
filePath: absolutePath,
|
|
8005
|
-
errors: [error instanceof Error ? error.message : String(error)]
|
|
8006
|
-
};
|
|
8007
|
-
}
|
|
8008
|
-
}
|
|
8009
|
-
|
|
8010
|
-
// ../shared_libs/play-runtime/dedup-backend.ts
|
|
8011
|
-
var PLAY_DEDUP_BACKENDS = {
|
|
8012
|
-
inMemory: "in_memory",
|
|
8013
|
-
neonTable: "neon_table",
|
|
8014
|
-
durableObject: "durable_object"
|
|
8015
|
-
};
|
|
8016
|
-
|
|
8017
|
-
// ../shared_libs/play-runtime/scheduler-backend.ts
|
|
8018
|
-
var PLAY_SCHEDULER_BACKENDS = {
|
|
8019
|
-
temporal: "temporal",
|
|
8020
|
-
cfWorkflows: "cf-workflows",
|
|
8021
|
-
/**
|
|
8022
|
-
* Private legacy id retained only so old persisted rows can be interpreted.
|
|
8023
|
-
* It is not a selectable scheduler backend after the Hatchet hard cutover.
|
|
8024
|
-
*/
|
|
8025
|
-
postgres: "postgres",
|
|
8026
|
-
hatchet: "hatchet",
|
|
8027
|
-
inProcess: "in-process"
|
|
8028
|
-
};
|
|
8029
|
-
|
|
8030
|
-
// ../shared_libs/play-runtime/providers.ts
|
|
8031
|
-
var PLAY_RUNTIME_PROVIDER_IDS = {
|
|
8032
|
-
workersEdge: "workers_edge",
|
|
8033
|
-
hatchet: "hatchet",
|
|
8034
|
-
local: "local"
|
|
8035
|
-
};
|
|
8036
|
-
var PLAY_RUNTIME_PROVIDERS = {
|
|
8037
|
-
workers_edge: {
|
|
8038
|
-
id: PLAY_RUNTIME_PROVIDER_IDS.workersEdge,
|
|
8039
|
-
scheduler: PLAY_SCHEDULER_BACKENDS.cfWorkflows,
|
|
8040
|
-
runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
8041
|
-
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
8042
|
-
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
8043
|
-
label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
|
|
8044
|
-
},
|
|
8045
|
-
hatchet: {
|
|
8046
|
-
id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
|
|
8047
|
-
scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
|
|
8048
|
-
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
8049
|
-
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
8050
|
-
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8051
|
-
label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
|
|
8052
|
-
},
|
|
8053
|
-
local: {
|
|
8054
|
-
id: PLAY_RUNTIME_PROVIDER_IDS.local,
|
|
8055
|
-
scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
|
|
8056
|
-
runner: PLAY_RUNTIME_BACKENDS.localProcess,
|
|
8057
|
-
dedup: PLAY_DEDUP_BACKENDS.inMemory,
|
|
8058
|
-
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8059
|
-
label: "Local Temporal scheduler + local subprocess runner (tests)"
|
|
8060
|
-
}
|
|
8061
|
-
};
|
|
8062
|
-
function defaultPlayRuntimeProvider() {
|
|
8063
|
-
return PLAY_RUNTIME_PROVIDERS.workers_edge;
|
|
8064
|
-
}
|
|
8065
|
-
function resolvePlayRuntimeProvider(override) {
|
|
8066
|
-
if (override?.trim()) {
|
|
8067
|
-
const id = override.trim();
|
|
8068
|
-
if (id in PLAY_RUNTIME_PROVIDERS) {
|
|
8069
|
-
return PLAY_RUNTIME_PROVIDERS[id];
|
|
8070
|
-
}
|
|
8071
|
-
throw new Error(
|
|
8072
|
-
`Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
|
|
8073
|
-
PLAY_RUNTIME_PROVIDERS
|
|
8074
|
-
).join(", ")}.`
|
|
8075
|
-
);
|
|
8076
|
-
}
|
|
8077
|
-
return defaultPlayRuntimeProvider();
|
|
8078
|
-
}
|
|
8079
|
-
|
|
8080
|
-
// ../shared_libs/play-runtime/profiles.ts
|
|
8081
|
-
var PLAY_EXECUTION_PROFILE_IDS = {
|
|
8082
|
-
...PLAY_RUNTIME_PROVIDER_IDS
|
|
8083
|
-
};
|
|
8084
|
-
var PLAY_EXECUTION_PROFILES = PLAY_RUNTIME_PROVIDERS;
|
|
8085
|
-
function resolveExecutionProfile(override) {
|
|
8086
|
-
try {
|
|
8087
|
-
return resolvePlayRuntimeProvider(override);
|
|
8088
|
-
} catch (error) {
|
|
8089
|
-
if (override?.trim()) {
|
|
8090
|
-
throw new Error(
|
|
8091
|
-
`Unknown execution profile "${override.trim()}". Expected one of: ${Object.keys(
|
|
8092
|
-
PLAY_EXECUTION_PROFILES
|
|
8093
|
-
).join(", ")}.`
|
|
8094
|
-
);
|
|
8095
|
-
}
|
|
8096
|
-
throw error;
|
|
8097
|
-
}
|
|
8098
|
-
}
|
|
8099
|
-
|
|
8100
|
-
// src/plays/local-file-discovery.ts
|
|
8101
|
-
import { createHash as createHash2 } from "crypto";
|
|
8102
|
-
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
8103
|
-
import {
|
|
8104
|
-
basename as basename2,
|
|
8105
|
-
dirname as dirname7,
|
|
8106
|
-
extname as extname2,
|
|
8107
|
-
isAbsolute as isAbsolute2,
|
|
8108
|
-
join as join6,
|
|
8109
|
-
relative as relative2,
|
|
8110
|
-
resolve as resolve7
|
|
8111
|
-
} from "path";
|
|
8112
|
-
var SOURCE_EXTENSIONS2 = [
|
|
8113
|
-
".ts",
|
|
8114
|
-
".tsx",
|
|
8115
|
-
".mts",
|
|
8116
|
-
".cts",
|
|
8117
|
-
".js",
|
|
8118
|
-
".jsx",
|
|
8119
|
-
".mjs",
|
|
8120
|
-
".cjs",
|
|
8121
|
-
".json"
|
|
8122
|
-
];
|
|
8123
|
-
function sha2562(buffer) {
|
|
8124
|
-
return createHash2("sha256").update(buffer).digest("hex");
|
|
8125
|
-
}
|
|
8126
|
-
function contentTypeForFile(filePath) {
|
|
8127
|
-
const extension = extname2(filePath).toLowerCase();
|
|
8128
|
-
if (extension === ".csv") return "text/csv";
|
|
8129
|
-
if (extension === ".json") return "application/json";
|
|
8130
|
-
if (extension === ".txt") return "text/plain";
|
|
8131
|
-
return "application/octet-stream";
|
|
8132
|
-
}
|
|
8133
|
-
function stripCommentsToSpaces2(source) {
|
|
8134
|
-
return source.replace(/\/\*[\s\S]*?\*\//g, (match) => match.replace(/[^\n]/g, " ")).replace(
|
|
8135
|
-
/(^|[^:])\/\/.*$/gm,
|
|
8136
|
-
(match, prefix) => prefix + " ".repeat(Math.max(0, match.length - prefix.length))
|
|
8137
|
-
);
|
|
8138
|
-
}
|
|
8139
|
-
function unquoteStringLiteral2(literal) {
|
|
8140
|
-
const trimmed = literal.trim();
|
|
8141
|
-
const quote = trimmed[0];
|
|
8142
|
-
if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
|
|
8143
|
-
return null;
|
|
8144
|
-
}
|
|
8145
|
-
try {
|
|
8146
|
-
return JSON.parse(
|
|
8147
|
-
quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
|
|
8148
|
-
);
|
|
8149
|
-
} catch {
|
|
8150
|
-
return trimmed.slice(1, -1);
|
|
8151
|
-
}
|
|
8152
|
-
}
|
|
8153
|
-
function splitTopLevelPlus(expression) {
|
|
8154
|
-
const parts = [];
|
|
8155
|
-
let start = 0;
|
|
8156
|
-
let depth = 0;
|
|
8157
|
-
let quote = null;
|
|
8158
|
-
let escaped = false;
|
|
8159
|
-
for (let index = 0; index < expression.length; index += 1) {
|
|
8160
|
-
const char = expression[index];
|
|
8161
|
-
if (quote) {
|
|
8162
|
-
if (escaped) {
|
|
8163
|
-
escaped = false;
|
|
8164
|
-
} else if (char === "\\") {
|
|
8165
|
-
escaped = true;
|
|
8166
|
-
} else if (char === quote) {
|
|
8167
|
-
quote = null;
|
|
8168
|
-
}
|
|
8169
|
-
continue;
|
|
8170
|
-
}
|
|
8171
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
8172
|
-
quote = char;
|
|
8173
|
-
continue;
|
|
8174
|
-
}
|
|
8175
|
-
if (char === "(" || char === "[" || char === "{") depth += 1;
|
|
8176
|
-
if (char === ")" || char === "]" || char === "}") depth -= 1;
|
|
8177
|
-
if (char === "+" && depth === 0) {
|
|
8178
|
-
parts.push(expression.slice(start, index));
|
|
8179
|
-
start = index + 1;
|
|
8180
|
-
}
|
|
8181
|
-
}
|
|
8182
|
-
if (parts.length === 0) return null;
|
|
8183
|
-
parts.push(expression.slice(start));
|
|
8184
|
-
return parts;
|
|
8185
|
-
}
|
|
8186
|
-
function stripOuterParens(expression) {
|
|
8187
|
-
let value = expression.trim();
|
|
8188
|
-
while (value.startsWith("(") && value.endsWith(")")) {
|
|
8189
|
-
value = value.slice(1, -1).trim();
|
|
8190
|
-
}
|
|
8191
|
-
return value;
|
|
8192
|
-
}
|
|
8193
|
-
function isRuntimeInputExpression(expression) {
|
|
8194
|
-
return /(^|[^\w$])input([^\w$]|$)/.test(expression);
|
|
8195
|
-
}
|
|
8196
|
-
function resolveStringExpression(expression, constants) {
|
|
8197
|
-
const value = stripOuterParens(expression);
|
|
8198
|
-
if (/^(['"])(?:\\.|(?!\1)[\s\S])*\1$/.test(value)) {
|
|
8199
|
-
return unquoteStringLiteral2(value);
|
|
8200
|
-
}
|
|
8201
|
-
if (/^`(?:\\.|[^`$]|\$(?!\{))*`$/.test(value)) {
|
|
8202
|
-
return value.slice(1, -1);
|
|
8203
|
-
}
|
|
8204
|
-
if (/^[A-Za-z_$][\w$]*$/.test(value)) {
|
|
8205
|
-
return constants.get(value) ?? null;
|
|
8206
|
-
}
|
|
8207
|
-
const parts = splitTopLevelPlus(value);
|
|
8208
|
-
if (parts) {
|
|
8209
|
-
const resolved = parts.map(
|
|
8210
|
-
(part) => resolveStringExpression(part, constants)
|
|
8211
|
-
);
|
|
8212
|
-
return resolved.every((part) => part != null) ? resolved.join("") : null;
|
|
8213
|
-
}
|
|
8214
|
-
return null;
|
|
8215
|
-
}
|
|
8216
|
-
function collectTopLevelStringConstants(sourceCode) {
|
|
8217
|
-
const constants = /* @__PURE__ */ new Map();
|
|
8218
|
-
const source = stripCommentsToSpaces2(sourceCode);
|
|
8219
|
-
for (const match of source.matchAll(
|
|
8220
|
-
/(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)/g
|
|
8221
|
-
)) {
|
|
8222
|
-
const resolved = resolveStringExpression(match[2], constants);
|
|
8223
|
-
if (resolved != null) {
|
|
8224
|
-
constants.set(match[1], resolved);
|
|
8225
|
-
}
|
|
8226
|
-
}
|
|
8227
|
-
return constants;
|
|
8228
|
-
}
|
|
8229
|
-
function findMatchingGenericEnd(source, openIndex) {
|
|
8230
|
-
let depth = 0;
|
|
8231
|
-
let quote = null;
|
|
8232
|
-
let escaped = false;
|
|
8233
|
-
for (let index = openIndex; index < source.length; index += 1) {
|
|
8234
|
-
const char = source[index];
|
|
8235
|
-
if (quote) {
|
|
8236
|
-
if (escaped) {
|
|
8237
|
-
escaped = false;
|
|
8238
|
-
} else if (char === "\\") {
|
|
8239
|
-
escaped = true;
|
|
8240
|
-
} else if (char === quote) {
|
|
8241
|
-
quote = null;
|
|
8242
|
-
}
|
|
8243
|
-
continue;
|
|
8244
|
-
}
|
|
8245
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
8246
|
-
quote = char;
|
|
8247
|
-
continue;
|
|
8248
|
-
}
|
|
8249
|
-
if (char === "<") depth += 1;
|
|
8250
|
-
if (char === ">") {
|
|
8251
|
-
depth -= 1;
|
|
8252
|
-
if (depth === 0) return index;
|
|
8253
|
-
}
|
|
8254
|
-
}
|
|
8255
|
-
return -1;
|
|
8256
|
-
}
|
|
8257
|
-
function findCallOpenParen(source, afterCsvIndex) {
|
|
8258
|
-
let index = afterCsvIndex;
|
|
8259
|
-
while (/\s/.test(source[index] ?? "")) index += 1;
|
|
8260
|
-
if (source[index] === "<") {
|
|
8261
|
-
const genericEnd = findMatchingGenericEnd(source, index);
|
|
8262
|
-
if (genericEnd < 0) return -1;
|
|
8263
|
-
index = genericEnd + 1;
|
|
8264
|
-
while (/\s/.test(source[index] ?? "")) index += 1;
|
|
8265
|
-
}
|
|
8266
|
-
return source[index] === "(" ? index : -1;
|
|
8267
|
-
}
|
|
8268
|
-
function firstCallArgument(source, openParen) {
|
|
8269
|
-
let depth = 0;
|
|
8270
|
-
let quote = null;
|
|
8271
|
-
let escaped = false;
|
|
8272
|
-
const start = openParen + 1;
|
|
8273
|
-
for (let index = start; index < source.length; index += 1) {
|
|
8274
|
-
const char = source[index];
|
|
8275
|
-
if (quote) {
|
|
8276
|
-
if (escaped) {
|
|
8277
|
-
escaped = false;
|
|
8278
|
-
} else if (char === "\\") {
|
|
8279
|
-
escaped = true;
|
|
8280
|
-
} else if (char === quote) {
|
|
8281
|
-
quote = null;
|
|
8282
|
-
}
|
|
8283
|
-
continue;
|
|
8284
|
-
}
|
|
8285
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
8286
|
-
quote = char;
|
|
8287
|
-
continue;
|
|
8288
|
-
}
|
|
8289
|
-
if (char === "(" || char === "[" || char === "{") depth += 1;
|
|
8290
|
-
if (char === ")" && depth === 0) {
|
|
8291
|
-
const text = source.slice(start, index).trim();
|
|
8292
|
-
return text ? { text, start, end: index } : null;
|
|
8293
|
-
}
|
|
8294
|
-
if (char === "," && depth === 0) {
|
|
8295
|
-
const text = source.slice(start, index).trim();
|
|
8296
|
-
return text ? { text, start, end: index } : null;
|
|
8297
|
-
}
|
|
8298
|
-
if (char === ")" || char === "]" || char === "}") depth -= 1;
|
|
8299
|
-
}
|
|
8300
|
-
return null;
|
|
8301
|
-
}
|
|
8302
|
-
function localImportSpecifiers(sourceCode) {
|
|
8303
|
-
const source = stripCommentsToSpaces2(sourceCode);
|
|
8304
|
-
const specifiers = [];
|
|
8305
|
-
for (const match of source.matchAll(
|
|
8306
|
-
/\b(?:import|export)\s+(?!type\b)(?:[\s\S]*?\s+from\s*)?['"]([^'"]+)['"]/g
|
|
8307
|
-
)) {
|
|
8308
|
-
if (match[1]?.startsWith(".")) specifiers.push(match[1]);
|
|
8309
|
-
}
|
|
8310
|
-
for (const match of source.matchAll(
|
|
8311
|
-
/\brequire\s*\(\s*(['"])(\.[^'"]*)\1\s*\)/g
|
|
8312
|
-
)) {
|
|
8313
|
-
specifiers.push(match[2]);
|
|
8314
|
-
}
|
|
8315
|
-
return specifiers;
|
|
8316
|
-
}
|
|
8317
|
-
async function fileExists2(filePath) {
|
|
8318
|
-
try {
|
|
8319
|
-
await stat2(filePath);
|
|
8320
|
-
return true;
|
|
8321
|
-
} catch {
|
|
8322
|
-
return false;
|
|
8323
|
-
}
|
|
8324
|
-
}
|
|
8325
|
-
function isPathInsideDirectory2(filePath, directory) {
|
|
8326
|
-
const relativePath = relative2(directory, filePath);
|
|
8327
|
-
return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute2(relativePath);
|
|
8328
|
-
}
|
|
8329
|
-
async function resolveLocalImport2(fromFile, specifier) {
|
|
8330
|
-
const base = isAbsolute2(specifier) ? resolve7(specifier) : resolve7(dirname7(fromFile), specifier);
|
|
8331
|
-
const candidates = [base];
|
|
8332
|
-
const explicitExtension = extname2(base).toLowerCase();
|
|
8333
|
-
if (!explicitExtension) {
|
|
8334
|
-
candidates.push(
|
|
8335
|
-
...SOURCE_EXTENSIONS2.map((extension) => `${base}${extension}`)
|
|
8336
|
-
);
|
|
8337
|
-
candidates.push(
|
|
8338
|
-
...SOURCE_EXTENSIONS2.map((extension) => join6(base, `index${extension}`))
|
|
8339
|
-
);
|
|
8340
|
-
} else if ([".js", ".jsx", ".mjs", ".cjs"].includes(explicitExtension)) {
|
|
8341
|
-
const stem = base.slice(0, -explicitExtension.length);
|
|
8342
|
-
candidates.push(
|
|
8343
|
-
...SOURCE_EXTENSIONS2.map((extension) => `${stem}${extension}`)
|
|
8344
|
-
);
|
|
8345
|
-
}
|
|
8346
|
-
for (const candidate of candidates) {
|
|
8347
|
-
if (await fileExists2(candidate)) {
|
|
8348
|
-
return candidate;
|
|
8349
|
-
}
|
|
8350
|
-
}
|
|
8351
|
-
throw new Error(
|
|
8352
|
-
`Could not resolve local import "${specifier}" from ${fromFile}`
|
|
8353
|
-
);
|
|
8354
|
-
}
|
|
8355
|
-
async function discoverPackagedLocalFiles(entryFile) {
|
|
8356
|
-
const absoluteEntryFile = resolve7(entryFile);
|
|
8357
|
-
const packagingRoot = dirname7(absoluteEntryFile);
|
|
8358
|
-
const files = /* @__PURE__ */ new Map();
|
|
8359
|
-
const unresolved = [];
|
|
8360
|
-
const visitedFiles = /* @__PURE__ */ new Set();
|
|
8361
|
-
const visitSourceFile = async (filePath) => {
|
|
8362
|
-
const absolutePath = resolve7(filePath);
|
|
8363
|
-
if (visitedFiles.has(absolutePath)) {
|
|
8364
|
-
return;
|
|
8365
|
-
}
|
|
8366
|
-
visitedFiles.add(absolutePath);
|
|
8367
|
-
const sourceCode = await readFile2(absolutePath, "utf-8");
|
|
8368
|
-
const scanSource = stripCommentsToSpaces2(sourceCode);
|
|
8369
|
-
const constants = collectTopLevelStringConstants(sourceCode);
|
|
8370
|
-
const childVisits = [];
|
|
8371
|
-
for (const match of scanSource.matchAll(
|
|
8372
|
-
/\b([A-Za-z_$][\w$]*)\s*\.\s*csv\b/g
|
|
8373
|
-
)) {
|
|
8374
|
-
const target = match[1];
|
|
8375
|
-
if (target !== "ctx" && !target.endsWith("Ctx")) {
|
|
8376
|
-
continue;
|
|
8377
|
-
}
|
|
8378
|
-
const openParen = findCallOpenParen(
|
|
8379
|
-
scanSource,
|
|
8380
|
-
match.index + match[0].length
|
|
8381
|
-
);
|
|
8382
|
-
if (openParen < 0) {
|
|
8383
|
-
continue;
|
|
8384
|
-
}
|
|
8385
|
-
const argument = firstCallArgument(scanSource, openParen);
|
|
8386
|
-
if (!argument) {
|
|
8387
|
-
unresolved.push({
|
|
8388
|
-
sourceFragment: "ctx.csv()",
|
|
8389
|
-
message: "ctx.csv() requires a file path string or input reference."
|
|
8390
|
-
});
|
|
8391
|
-
} else if (!isRuntimeInputExpression(argument.text)) {
|
|
8392
|
-
const resolvedPath = resolveStringExpression(argument.text, constants);
|
|
8393
|
-
if (resolvedPath == null) {
|
|
8394
|
-
unresolved.push({
|
|
8395
|
-
sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
|
|
8396
|
-
message: "Could not resolve this ctx.csv(...) path at submit time. Use a string literal, a top-level const string, or pass a runtime input like input.file."
|
|
8397
|
-
});
|
|
8398
|
-
} else {
|
|
8399
|
-
const absoluteCsvPath = resolve7(dirname7(absolutePath), resolvedPath);
|
|
8400
|
-
if (isAbsolute2(resolvedPath) || !isPathInsideDirectory2(absoluteCsvPath, packagingRoot)) {
|
|
8401
|
-
unresolved.push({
|
|
8402
|
-
sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
|
|
8403
|
-
message: "ctx.csv(...) packaged file paths must be relative paths inside the play directory. Pass external files at runtime with input.file instead."
|
|
8404
|
-
});
|
|
8405
|
-
continue;
|
|
8406
|
-
}
|
|
8407
|
-
const buffer = await readFile2(absoluteCsvPath);
|
|
8408
|
-
const stats = await stat2(absoluteCsvPath);
|
|
8409
|
-
files.set(absoluteCsvPath, {
|
|
8410
|
-
sourceFragment: sourceCode.slice(argument.start, argument.end).trim(),
|
|
8411
|
-
logicalPath: resolvedPath,
|
|
8412
|
-
absolutePath: absoluteCsvPath,
|
|
8413
|
-
bytes: stats.size,
|
|
8414
|
-
contentHash: sha2562(buffer),
|
|
8415
|
-
contentType: contentTypeForFile(absoluteCsvPath)
|
|
8416
|
-
});
|
|
8417
|
-
}
|
|
8418
|
-
}
|
|
8419
|
-
}
|
|
8420
|
-
for (const specifier of localImportSpecifiers(sourceCode)) {
|
|
8421
|
-
childVisits.push(
|
|
8422
|
-
resolveLocalImport2(absolutePath, specifier).then(
|
|
8423
|
-
(resolvedImport) => visitSourceFile(resolvedImport)
|
|
8424
|
-
)
|
|
8425
|
-
);
|
|
8426
|
-
}
|
|
8427
|
-
await Promise.all(childVisits);
|
|
8428
|
-
};
|
|
8429
|
-
await visitSourceFile(absoluteEntryFile);
|
|
8430
|
-
return {
|
|
8431
|
-
files: [...files.values()],
|
|
8432
|
-
unresolved
|
|
8433
|
-
};
|
|
8434
|
-
}
|
|
8435
|
-
|
|
8436
|
-
// src/plays/bundle-play-file.ts
|
|
8437
|
-
var PLAY_BUNDLE_CACHE_VERSION2 = 30;
|
|
8438
|
-
var MODULE_DIR = dirname8(fileURLToPath(import.meta.url));
|
|
8439
|
-
var SDK_PACKAGE_ROOT = resolve8(MODULE_DIR, "..", "..");
|
|
8440
|
-
var SOURCE_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "..");
|
|
8441
|
-
var HAS_SOURCE_BUNDLING_SOURCES = existsSync7(
|
|
8442
|
-
resolve8(SOURCE_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
8443
|
-
);
|
|
8444
|
-
var PACKAGED_REPO_ROOT = resolve8(SDK_PACKAGE_ROOT, "dist", "repo");
|
|
8445
|
-
var HAS_PACKAGED_BUNDLING_SOURCES = existsSync7(
|
|
8446
|
-
resolve8(PACKAGED_REPO_ROOT, "apps", "play-runner-workers", "src", "entry.ts")
|
|
8447
|
-
);
|
|
8448
|
-
var PROJECT_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? SOURCE_REPO_ROOT : HAS_PACKAGED_BUNDLING_SOURCES ? PACKAGED_REPO_ROOT : resolve8(SDK_PACKAGE_ROOT, "..");
|
|
8449
|
-
var SDK_SOURCE_ROOT = HAS_SOURCE_BUNDLING_SOURCES ? resolve8(SOURCE_REPO_ROOT, "sdk", "src") : HAS_PACKAGED_BUNDLING_SOURCES ? resolve8(PACKAGED_REPO_ROOT, "sdk", "src") : resolve8(SDK_PACKAGE_ROOT, "src");
|
|
8450
|
-
var SDK_PACKAGE_JSON = resolve8(SDK_PACKAGE_ROOT, "package.json");
|
|
8451
|
-
var SDK_ENTRY_FILE = resolve8(SDK_SOURCE_ROOT, "index.ts");
|
|
8452
|
-
var SDK_TYPES_ENTRY_FILE = HAS_SOURCE_BUNDLING_SOURCES ? SDK_ENTRY_FILE : resolve8(SDK_PACKAGE_ROOT, "dist", "index.d.ts");
|
|
8453
|
-
var SDK_WORKERS_ENTRY_FILE = resolve8(SDK_SOURCE_ROOT, "worker-play-entry.ts");
|
|
8454
|
-
var WORKERS_HARNESS_ENTRY_FILE = resolve8(
|
|
8455
|
-
PROJECT_ROOT,
|
|
8456
|
-
"apps",
|
|
8457
|
-
"play-runner-workers",
|
|
8458
|
-
"src",
|
|
8459
|
-
"entry.ts"
|
|
8460
|
-
);
|
|
8461
|
-
var WORKERS_HARNESS_FILES_DIR = resolve8(
|
|
8462
|
-
PROJECT_ROOT,
|
|
8463
|
-
"apps",
|
|
8464
|
-
"play-runner-workers",
|
|
8465
|
-
"src"
|
|
8466
|
-
);
|
|
8467
|
-
var hasWarnedAboutNonDevelopmentBundling = false;
|
|
8468
|
-
function warnAboutNonDevelopmentBundling(filePath) {
|
|
8469
|
-
if (hasWarnedAboutNonDevelopmentBundling) {
|
|
8470
|
-
return;
|
|
8471
|
-
}
|
|
8472
|
-
const nodeEnv = String(process.env.NODE_ENV ?? "").trim().toLowerCase();
|
|
8473
|
-
if (!nodeEnv || nodeEnv === "development" || nodeEnv === "test") {
|
|
8474
|
-
return;
|
|
8475
|
-
}
|
|
8476
|
-
hasWarnedAboutNonDevelopmentBundling = true;
|
|
8477
|
-
console.warn(
|
|
8478
|
-
`[deepline] Warning: live play bundling was invoked while NODE_ENV=${nodeEnv} for ${filePath}. This source-first SDK path is intended for local development. For preview/production, run a published or prebuilt play reference instead of bundling source at runtime.`
|
|
8479
|
-
);
|
|
8480
|
-
console.warn(
|
|
8481
|
-
'[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
|
|
8482
|
-
);
|
|
8483
|
-
}
|
|
8484
|
-
function defaultPlayBundleTarget() {
|
|
8485
|
-
return resolveExecutionProfile(null).artifactKind;
|
|
8486
|
-
}
|
|
8487
|
-
function createSdkPlayBundlingAdapter() {
|
|
8488
|
-
return {
|
|
8489
|
-
projectRoot: PROJECT_ROOT,
|
|
8490
|
-
nodeModulesDir: resolve8(PROJECT_ROOT, "node_modules"),
|
|
8491
|
-
cacheDir: join7(
|
|
8492
|
-
tmpdir2(),
|
|
8493
|
-
`deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
|
|
8494
|
-
),
|
|
8495
|
-
sdkSourceRoot: SDK_SOURCE_ROOT,
|
|
8496
|
-
sdkPackageJson: SDK_PACKAGE_JSON,
|
|
8497
|
-
sdkEntryFile: SDK_ENTRY_FILE,
|
|
8498
|
-
sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !existsSync7(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
|
|
8499
|
-
sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
|
|
8500
|
-
workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
|
|
8501
|
-
workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
|
|
8502
|
-
workersRuntimeFingerprintDirs: [
|
|
8503
|
-
resolve8(PROJECT_ROOT, "shared_libs", "play-runtime")
|
|
8504
|
-
],
|
|
8505
|
-
discoverPackagedLocalFiles,
|
|
8506
|
-
warnAboutNonDevelopmentBundling
|
|
8507
|
-
};
|
|
8508
|
-
}
|
|
8509
|
-
async function bundlePlayFile2(filePath, options = {}) {
|
|
8510
|
-
const result = await bundlePlayFile(filePath, {
|
|
8511
|
-
target: options.target ?? defaultPlayBundleTarget(),
|
|
8512
|
-
exportName: options.exportName,
|
|
8513
|
-
adapter: createSdkPlayBundlingAdapter()
|
|
8514
|
-
});
|
|
8515
|
-
if (result.success)
|
|
8516
|
-
validatePlaySourceFilesHaveNoInlineSecrets(result.sourceFiles);
|
|
8517
|
-
return result;
|
|
8518
|
-
}
|
|
8519
|
-
|
|
8520
|
-
// src/cli/commands/plays/bootstrap.ts
|
|
8521
|
-
import { closeSync, openSync, readSync, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
8522
|
-
import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve9 } from "path";
|
|
8523
|
-
import { parse as parseCsvSync } from "csv-parse/sync";
|
|
8524
|
-
|
|
8525
|
-
// ../shared_libs/plays/bootstrap-routes.ts
|
|
8526
|
-
var PLAY_BOOTSTRAP_TEMPLATES = [
|
|
8527
|
-
"people-list",
|
|
8528
|
-
"company-list",
|
|
8529
|
-
"people-email",
|
|
8530
|
-
"people-phone",
|
|
8531
|
-
"company-people",
|
|
8532
|
-
"company-people-email",
|
|
8533
|
-
"company-people-phone"
|
|
8534
|
-
];
|
|
8535
|
-
var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
|
|
8536
|
-
var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
|
|
8537
|
-
var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
|
|
8538
|
-
email_finder: "email_finder",
|
|
8539
|
-
phone_finder: "phone_finder"
|
|
8540
|
-
};
|
|
8541
|
-
var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
|
|
8542
|
-
email_finder: "email",
|
|
8543
|
-
phone_finder: "phone"
|
|
8544
|
-
};
|
|
8545
|
-
function isPlayBootstrapTemplate(value) {
|
|
8546
|
-
return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
|
|
8547
|
-
}
|
|
8548
|
-
function formatPlayBootstrapTemplates() {
|
|
8549
|
-
return PLAY_BOOTSTRAP_TEMPLATES.join("|");
|
|
8550
|
-
}
|
|
8551
|
-
|
|
8552
|
-
// src/cli/commands/plays/bootstrap.ts
|
|
8553
|
-
function parseReferencedPlayTarget(target) {
|
|
8554
|
-
const trimmed = target.trim();
|
|
8555
|
-
const slashIndex = trimmed.indexOf("/");
|
|
8556
|
-
if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
|
|
8557
|
-
return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
|
|
8558
|
-
}
|
|
8559
|
-
return {
|
|
8560
|
-
ownerSlug: trimmed.slice(0, slashIndex),
|
|
8561
|
-
playName: trimmed,
|
|
8562
|
-
unqualifiedPlayName: trimmed.slice(slashIndex + 1)
|
|
8563
|
-
};
|
|
8564
|
-
}
|
|
8565
|
-
function parsePositiveInteger2(value, flagName) {
|
|
8566
|
-
const parsed = Number.parseInt(value, 10);
|
|
8567
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
8568
|
-
throw new PlayBootstrapUsageError(
|
|
8569
|
-
`${flagName} must be a positive integer.`
|
|
8570
|
-
);
|
|
8571
|
-
}
|
|
8572
|
-
return parsed;
|
|
8573
|
-
}
|
|
8574
|
-
function isRecord5(value) {
|
|
8575
|
-
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
8576
|
-
}
|
|
8577
|
-
function stringValue(value) {
|
|
8578
|
-
return typeof value === "string" ? value.trim() : "";
|
|
8579
|
-
}
|
|
8580
|
-
function extractionEntries(value) {
|
|
8581
|
-
if (Array.isArray(value)) return value.filter(isRecord5);
|
|
8582
|
-
if (!isRecord5(value)) return [];
|
|
8583
|
-
return Object.entries(value).map(
|
|
8584
|
-
([name, entry]) => isRecord5(entry) ? { name, ...entry } : { name }
|
|
8585
|
-
);
|
|
8586
|
-
}
|
|
8587
|
-
var PlayBootstrapError = class extends Error {
|
|
8588
|
-
constructor(message, exitCode) {
|
|
8589
|
-
super(message);
|
|
8590
|
-
this.exitCode = exitCode;
|
|
8591
|
-
}
|
|
8592
|
-
exitCode;
|
|
8593
|
-
};
|
|
8594
|
-
var PlayBootstrapUsageError = class extends PlayBootstrapError {
|
|
8595
|
-
constructor(message) {
|
|
8596
|
-
super(message, 2);
|
|
8597
|
-
}
|
|
8598
|
-
};
|
|
8599
|
-
var PlayBootstrapValidationError = class extends PlayBootstrapError {
|
|
8600
|
-
constructor(message) {
|
|
8601
|
-
super(message, 7);
|
|
8602
|
-
}
|
|
8603
|
-
};
|
|
8604
|
-
var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
|
|
8605
|
-
function parseCsvList(value) {
|
|
8606
|
-
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
8607
|
-
}
|
|
8608
|
-
function parseProviderList(value, flag) {
|
|
8609
|
-
const providers = parseCsvList(value);
|
|
8610
|
-
if (providers.length === 0) {
|
|
8611
|
-
throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
|
|
8612
|
-
}
|
|
8613
|
-
return providers;
|
|
6882
|
+
return providers;
|
|
8614
6883
|
}
|
|
8615
6884
|
function parseBootstrapPrefixedRef(value, flag) {
|
|
8616
6885
|
const separatorIndex = value.indexOf(":");
|
|
@@ -8948,7 +7217,7 @@ function inferCsvColumnSpecs(headers, rows) {
|
|
|
8948
7217
|
}));
|
|
8949
7218
|
}
|
|
8950
7219
|
function readCsvSample(csvPath) {
|
|
8951
|
-
const resolvedPath =
|
|
7220
|
+
const resolvedPath = resolve6(csvPath);
|
|
8952
7221
|
const size = statSync(resolvedPath).size;
|
|
8953
7222
|
const fd = openSync(resolvedPath, "r");
|
|
8954
7223
|
const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
|
|
@@ -9023,9 +7292,9 @@ ${properties}
|
|
|
9023
7292
|
}
|
|
9024
7293
|
function packagedCsvPathForPlay(csvPath) {
|
|
9025
7294
|
const playDir = process.cwd();
|
|
9026
|
-
const absoluteCsvPath =
|
|
9027
|
-
const relativePath =
|
|
9028
|
-
if (relativePath === "" || relativePath.startsWith("..") ||
|
|
7295
|
+
const absoluteCsvPath = resolve6(csvPath);
|
|
7296
|
+
const relativePath = relative(playDir, absoluteCsvPath);
|
|
7297
|
+
if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) {
|
|
9029
7298
|
throw new PlayBootstrapUsageError(
|
|
9030
7299
|
`--from csv:${csvPath} must point to a file inside the directory where you run plays bootstrap. Run bootstrap from the intended play directory and write the play with --out there.`
|
|
9031
7300
|
);
|
|
@@ -9944,8 +8213,8 @@ async function runPlayBootstrap(args) {
|
|
|
9944
8213
|
...csvContext
|
|
9945
8214
|
});
|
|
9946
8215
|
if (options.out) {
|
|
9947
|
-
writeFileSync7(
|
|
9948
|
-
process.stdout.write(`Wrote ${
|
|
8216
|
+
writeFileSync7(resolve6(options.out), source, "utf-8");
|
|
8217
|
+
process.stdout.write(`Wrote ${resolve6(options.out)}
|
|
9949
8218
|
`);
|
|
9950
8219
|
return 0;
|
|
9951
8220
|
}
|
|
@@ -10211,110 +8480,390 @@ async function traceCliSpan(phase, fields, run) {
|
|
|
10211
8480
|
if (!isCliTraceEnabled()) {
|
|
10212
8481
|
return run();
|
|
10213
8482
|
}
|
|
10214
|
-
const startedAt = Date.now();
|
|
8483
|
+
const startedAt = Date.now();
|
|
8484
|
+
try {
|
|
8485
|
+
const result = await run();
|
|
8486
|
+
recordCliTrace({
|
|
8487
|
+
phase,
|
|
8488
|
+
ms: Date.now() - startedAt,
|
|
8489
|
+
ok: true,
|
|
8490
|
+
...fields
|
|
8491
|
+
});
|
|
8492
|
+
return result;
|
|
8493
|
+
} catch (error) {
|
|
8494
|
+
recordCliTrace({
|
|
8495
|
+
phase,
|
|
8496
|
+
ms: Date.now() - startedAt,
|
|
8497
|
+
ok: false,
|
|
8498
|
+
error: error instanceof Error ? error.message : String(error),
|
|
8499
|
+
...fields
|
|
8500
|
+
});
|
|
8501
|
+
throw error;
|
|
8502
|
+
}
|
|
8503
|
+
}
|
|
8504
|
+
|
|
8505
|
+
// src/cli/play-check-hints.ts
|
|
8506
|
+
var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific fields.";
|
|
8507
|
+
var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy and durable. Use `.peek(n)` for a small preview or `.materialize()` when you intentionally need rows in memory; do not use `.rows`, `.toArray()`, or array methods directly on the dataset handle.";
|
|
8508
|
+
var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
|
|
8509
|
+
var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for replay-safe receipts.";
|
|
8510
|
+
var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or map-backed batch plays must be run directly, exported, then consumed by a separate play.";
|
|
8511
|
+
var MAP_BACKED_CHILD_HINT = "Deepline hint: map-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
|
|
8512
|
+
function sourceLineForError(sourceCode, error) {
|
|
8513
|
+
const match = error.match(/:(\d+):(\d+)\s/);
|
|
8514
|
+
const lineNumber = match?.[1] ? Number(match[1]) : NaN;
|
|
8515
|
+
if (!Number.isInteger(lineNumber) || lineNumber < 1) return "";
|
|
8516
|
+
return sourceCode.split(/\r?\n/)[lineNumber - 1] ?? "";
|
|
8517
|
+
}
|
|
8518
|
+
function looksLikeInvalidExtractedGetter(error, sourceLine) {
|
|
8519
|
+
if (!/Property '[^']+' does not exist on type/.test(error)) return false;
|
|
8520
|
+
return /\bextracted(?:Values|Lists)\s*\./.test(sourceLine);
|
|
8521
|
+
}
|
|
8522
|
+
function looksLikeDatasetApiMisuse(error, sourceLine) {
|
|
8523
|
+
return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
|
|
8524
|
+
error
|
|
8525
|
+
) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
|
|
8526
|
+
sourceLine
|
|
8527
|
+
);
|
|
8528
|
+
}
|
|
8529
|
+
function looksLikeRowPropertyMismatch(error, sourceLine) {
|
|
8530
|
+
if (!/Property '[^']+' does not exist on type/.test(error)) return false;
|
|
8531
|
+
if (looksLikeInvalidExtractedGetter(error, sourceLine)) return false;
|
|
8532
|
+
return /\brow\.[A-Za-z_][A-Za-z0-9_]*/.test(sourceLine);
|
|
8533
|
+
}
|
|
8534
|
+
function looksLikeToolsExecuteSignature(error, sourceLine) {
|
|
8535
|
+
return /ctx\.tools\.execute requires a request object/i.test(error) || /Expected 1 arguments?, but got [2-9]/.test(error) && /\btools\.execute\(/.test(sourceLine);
|
|
8536
|
+
}
|
|
8537
|
+
function looksLikeRunPlaySignature(error, sourceLine) {
|
|
8538
|
+
return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
|
|
8539
|
+
}
|
|
8540
|
+
function looksLikeMapBackedChild(error) {
|
|
8541
|
+
return /map-backed child play|direct-run-only|cannot call a map-backed|own durable table/i.test(
|
|
8542
|
+
error
|
|
8543
|
+
);
|
|
8544
|
+
}
|
|
8545
|
+
function hintForError(error, sourceLine) {
|
|
8546
|
+
if (looksLikeInvalidExtractedGetter(error, sourceLine)) {
|
|
8547
|
+
return EXTRACTED_GETTER_ERROR_HINT;
|
|
8548
|
+
}
|
|
8549
|
+
if (looksLikeDatasetApiMisuse(error, sourceLine)) {
|
|
8550
|
+
return DATASET_API_HINT;
|
|
8551
|
+
}
|
|
8552
|
+
if (looksLikeToolsExecuteSignature(error, sourceLine)) {
|
|
8553
|
+
return TOOLS_EXECUTE_SIGNATURE_HINT;
|
|
8554
|
+
}
|
|
8555
|
+
if (looksLikeMapBackedChild(error)) {
|
|
8556
|
+
return MAP_BACKED_CHILD_HINT;
|
|
8557
|
+
}
|
|
8558
|
+
if (looksLikeRunPlaySignature(error, sourceLine)) {
|
|
8559
|
+
return RUN_PLAY_SIGNATURE_HINT;
|
|
8560
|
+
}
|
|
8561
|
+
if (looksLikeRowPropertyMismatch(error, sourceLine)) {
|
|
8562
|
+
return ROW_PROPERTY_HINT;
|
|
8563
|
+
}
|
|
8564
|
+
return null;
|
|
8565
|
+
}
|
|
8566
|
+
function addPlayCheckRepairHints(input2) {
|
|
8567
|
+
const addedHints = /* @__PURE__ */ new Set();
|
|
8568
|
+
return input2.errors.map((error) => {
|
|
8569
|
+
const line = sourceLineForError(input2.sourceCode, error);
|
|
8570
|
+
const hint = hintForError(error, line);
|
|
8571
|
+
if (!hint || addedHints.has(hint) || error.includes(hint)) {
|
|
8572
|
+
return error;
|
|
8573
|
+
}
|
|
8574
|
+
addedHints.add(hint);
|
|
8575
|
+
return `${error}
|
|
8576
|
+
${hint}`;
|
|
8577
|
+
});
|
|
8578
|
+
}
|
|
8579
|
+
|
|
8580
|
+
// ../shared_libs/play-runtime/backend.ts
|
|
8581
|
+
var PLAY_RUNTIME_BACKENDS = {
|
|
8582
|
+
localProcess: "local_process",
|
|
8583
|
+
daytona: "daytona",
|
|
8584
|
+
// Artifact/runtime contract for Cloudflare Dynamic Workers. This is no
|
|
8585
|
+
// longer a standalone runner backend; use profile=workers_edge so the
|
|
8586
|
+
// cf-workflows scheduler owns loading and execution.
|
|
8587
|
+
cloudflareWorkers: "cloudflare_workers"
|
|
8588
|
+
};
|
|
8589
|
+
var PLAY_ARTIFACT_KINDS = {
|
|
8590
|
+
cjsNode20: "cjs_node20",
|
|
8591
|
+
esmWorkers: "esm_workers"
|
|
8592
|
+
};
|
|
8593
|
+
var PLAY_BACKEND_DESCRIPTORS = {
|
|
8594
|
+
[PLAY_RUNTIME_BACKENDS.localProcess]: {
|
|
8595
|
+
id: PLAY_RUNTIME_BACKENDS.localProcess,
|
|
8596
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8597
|
+
label: "Local node subprocess"
|
|
8598
|
+
},
|
|
8599
|
+
[PLAY_RUNTIME_BACKENDS.daytona]: {
|
|
8600
|
+
id: PLAY_RUNTIME_BACKENDS.daytona,
|
|
8601
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8602
|
+
label: "Daytona sandbox"
|
|
8603
|
+
},
|
|
8604
|
+
[PLAY_RUNTIME_BACKENDS.cloudflareWorkers]: {
|
|
8605
|
+
id: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
8606
|
+
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
8607
|
+
label: "Cloudflare Dynamic Workers"
|
|
8608
|
+
}
|
|
8609
|
+
};
|
|
8610
|
+
|
|
8611
|
+
// ../shared_libs/play-runtime/dedup-backend.ts
|
|
8612
|
+
var PLAY_DEDUP_BACKENDS = {
|
|
8613
|
+
inMemory: "in_memory",
|
|
8614
|
+
neonTable: "neon_table",
|
|
8615
|
+
durableObject: "durable_object"
|
|
8616
|
+
};
|
|
8617
|
+
|
|
8618
|
+
// ../shared_libs/play-runtime/scheduler-backend.ts
|
|
8619
|
+
var PLAY_SCHEDULER_BACKENDS = {
|
|
8620
|
+
temporal: "temporal",
|
|
8621
|
+
cfWorkflows: "cf-workflows",
|
|
8622
|
+
/**
|
|
8623
|
+
* Private legacy id retained only so old persisted rows can be interpreted.
|
|
8624
|
+
* It is not a selectable scheduler backend after the Hatchet hard cutover.
|
|
8625
|
+
*/
|
|
8626
|
+
postgres: "postgres",
|
|
8627
|
+
hatchet: "hatchet",
|
|
8628
|
+
inProcess: "in-process"
|
|
8629
|
+
};
|
|
8630
|
+
|
|
8631
|
+
// ../shared_libs/play-runtime/providers.ts
|
|
8632
|
+
var PLAY_RUNTIME_PROVIDER_IDS = {
|
|
8633
|
+
workersEdge: "workers_edge",
|
|
8634
|
+
hatchet: "hatchet",
|
|
8635
|
+
local: "local"
|
|
8636
|
+
};
|
|
8637
|
+
var PLAY_RUNTIME_PROVIDERS = {
|
|
8638
|
+
workers_edge: {
|
|
8639
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.workersEdge,
|
|
8640
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.cfWorkflows,
|
|
8641
|
+
runner: PLAY_RUNTIME_BACKENDS.cloudflareWorkers,
|
|
8642
|
+
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
8643
|
+
artifactKind: PLAY_ARTIFACT_KINDS.esmWorkers,
|
|
8644
|
+
label: "Cloudflare Dynamic Workflows + Dynamic Workers + DO dedup"
|
|
8645
|
+
},
|
|
8646
|
+
hatchet: {
|
|
8647
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.hatchet,
|
|
8648
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.hatchet,
|
|
8649
|
+
runner: PLAY_RUNTIME_BACKENDS.daytona,
|
|
8650
|
+
dedup: PLAY_DEDUP_BACKENDS.durableObject,
|
|
8651
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8652
|
+
label: "Hatchet scheduler + one-shot Daytona runner + DO dedup"
|
|
8653
|
+
},
|
|
8654
|
+
local: {
|
|
8655
|
+
id: PLAY_RUNTIME_PROVIDER_IDS.local,
|
|
8656
|
+
scheduler: PLAY_SCHEDULER_BACKENDS.temporal,
|
|
8657
|
+
runner: PLAY_RUNTIME_BACKENDS.localProcess,
|
|
8658
|
+
dedup: PLAY_DEDUP_BACKENDS.inMemory,
|
|
8659
|
+
artifactKind: PLAY_ARTIFACT_KINDS.cjsNode20,
|
|
8660
|
+
label: "Local Temporal scheduler + local subprocess runner (tests)"
|
|
8661
|
+
}
|
|
8662
|
+
};
|
|
8663
|
+
function defaultPlayRuntimeProvider() {
|
|
8664
|
+
return PLAY_RUNTIME_PROVIDERS.workers_edge;
|
|
8665
|
+
}
|
|
8666
|
+
function resolvePlayRuntimeProvider(override) {
|
|
8667
|
+
if (override?.trim()) {
|
|
8668
|
+
const id = override.trim();
|
|
8669
|
+
if (id in PLAY_RUNTIME_PROVIDERS) {
|
|
8670
|
+
return PLAY_RUNTIME_PROVIDERS[id];
|
|
8671
|
+
}
|
|
8672
|
+
throw new Error(
|
|
8673
|
+
`Unknown play runtime provider "${id}". Expected one of: ${Object.keys(
|
|
8674
|
+
PLAY_RUNTIME_PROVIDERS
|
|
8675
|
+
).join(", ")}.`
|
|
8676
|
+
);
|
|
8677
|
+
}
|
|
8678
|
+
return defaultPlayRuntimeProvider();
|
|
8679
|
+
}
|
|
8680
|
+
|
|
8681
|
+
// ../shared_libs/play-runtime/profiles.ts
|
|
8682
|
+
var PLAY_EXECUTION_PROFILE_IDS = {
|
|
8683
|
+
...PLAY_RUNTIME_PROVIDER_IDS
|
|
8684
|
+
};
|
|
8685
|
+
var PLAY_EXECUTION_PROFILES = PLAY_RUNTIME_PROVIDERS;
|
|
8686
|
+
function resolveExecutionProfile(override) {
|
|
10215
8687
|
try {
|
|
10216
|
-
|
|
10217
|
-
recordCliTrace({
|
|
10218
|
-
phase,
|
|
10219
|
-
ms: Date.now() - startedAt,
|
|
10220
|
-
ok: true,
|
|
10221
|
-
...fields
|
|
10222
|
-
});
|
|
10223
|
-
return result;
|
|
8688
|
+
return resolvePlayRuntimeProvider(override);
|
|
10224
8689
|
} catch (error) {
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
}
|
|
8690
|
+
if (override?.trim()) {
|
|
8691
|
+
throw new Error(
|
|
8692
|
+
`Unknown execution profile "${override.trim()}". Expected one of: ${Object.keys(
|
|
8693
|
+
PLAY_EXECUTION_PROFILES
|
|
8694
|
+
).join(", ")}.`
|
|
8695
|
+
);
|
|
8696
|
+
}
|
|
10232
8697
|
throw error;
|
|
10233
8698
|
}
|
|
10234
8699
|
}
|
|
10235
8700
|
|
|
10236
|
-
//
|
|
10237
|
-
var
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for replay-safe receipts.";
|
|
10241
|
-
var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or map-backed batch plays must be run directly, exported, then consumed by a separate play.";
|
|
10242
|
-
var MAP_BACKED_CHILD_HINT = "Deepline hint: map-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
|
|
10243
|
-
function sourceLineForError(sourceCode, error) {
|
|
10244
|
-
const match = error.match(/:(\d+):(\d+)\s/);
|
|
10245
|
-
const lineNumber = match?.[1] ? Number(match[1]) : NaN;
|
|
10246
|
-
if (!Number.isInteger(lineNumber) || lineNumber < 1) return "";
|
|
10247
|
-
return sourceCode.split(/\r?\n/)[lineNumber - 1] ?? "";
|
|
10248
|
-
}
|
|
10249
|
-
function looksLikeInvalidExtractedGetter(error, sourceLine) {
|
|
10250
|
-
if (!/Property '[^']+' does not exist on type/.test(error)) return false;
|
|
10251
|
-
return /\bextracted(?:Values|Lists)\s*\./.test(sourceLine);
|
|
10252
|
-
}
|
|
10253
|
-
function looksLikeDatasetApiMisuse(error, sourceLine) {
|
|
10254
|
-
return /Property '(?:rows|toArray|forEach|map|filter|reduce)' does not exist on type '[^']*PlayDataset/.test(
|
|
10255
|
-
error
|
|
10256
|
-
) || /\b(?:\.rows|\.toArray\(\)|\.forEach\(|\.map\(|\.filter\(|\.reduce\()/.test(
|
|
10257
|
-
sourceLine
|
|
10258
|
-
);
|
|
10259
|
-
}
|
|
10260
|
-
function looksLikeRowPropertyMismatch(error, sourceLine) {
|
|
10261
|
-
if (!/Property '[^']+' does not exist on type/.test(error)) return false;
|
|
10262
|
-
if (looksLikeInvalidExtractedGetter(error, sourceLine)) return false;
|
|
10263
|
-
return /\brow\.[A-Za-z_][A-Za-z0-9_]*/.test(sourceLine);
|
|
10264
|
-
}
|
|
10265
|
-
function looksLikeToolsExecuteSignature(error, sourceLine) {
|
|
10266
|
-
return /ctx\.tools\.execute requires a request object/i.test(error) || /Expected 1 arguments?, but got [2-9]/.test(error) && /\btools\.execute\(/.test(sourceLine);
|
|
10267
|
-
}
|
|
10268
|
-
function looksLikeRunPlaySignature(error, sourceLine) {
|
|
10269
|
-
return /ctx\.runPlay/i.test(error) || /(?:Expected|Argument of type|No overload matches)/.test(error) && /\brunPlay\(/.test(sourceLine);
|
|
8701
|
+
// ../shared_libs/play-runtime/internal-step-ids.ts
|
|
8702
|
+
var INTERNAL_GLUE_NODE_ID_PREFIX = "run_javascript:";
|
|
8703
|
+
function isInternalGlueStepId(stepId) {
|
|
8704
|
+
return typeof stepId === "string" && stepId.startsWith(INTERNAL_GLUE_NODE_ID_PREFIX);
|
|
10270
8705
|
}
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
8706
|
+
|
|
8707
|
+
// src/cli/commands/play.ts
|
|
8708
|
+
var PLAY_BUNDLER_MODULE_PATHS = [
|
|
8709
|
+
// Built CLI bundle: dist/cli/index.mjs -> dist/plays/bundle-play-file.mjs.
|
|
8710
|
+
["..", "plays", "bundle-play-file.mjs"].join("/"),
|
|
8711
|
+
// Source CLI: src/cli/commands/play.ts -> src/plays/bundle-play-file.ts.
|
|
8712
|
+
["..", "..", "plays", "bundle-play-file.js"].join("/")
|
|
8713
|
+
];
|
|
8714
|
+
var playBundlerPromise = null;
|
|
8715
|
+
async function loadPlayBundler() {
|
|
8716
|
+
playBundlerPromise ??= (async () => {
|
|
8717
|
+
const errors = [];
|
|
8718
|
+
for (const modulePath of PLAY_BUNDLER_MODULE_PATHS) {
|
|
8719
|
+
try {
|
|
8720
|
+
return await import(modulePath);
|
|
8721
|
+
} catch (error) {
|
|
8722
|
+
errors.push(
|
|
8723
|
+
`${modulePath}: ${error instanceof Error ? error.message : String(error)}`
|
|
8724
|
+
);
|
|
8725
|
+
}
|
|
8726
|
+
}
|
|
8727
|
+
playBundlerPromise = null;
|
|
8728
|
+
throw new Error(
|
|
8729
|
+
`Local play-file bundling is unavailable in this Deepline SDK install. Reinstall the package, or run a saved/prebuilt play by name while you repair the install. Bundler load failed: ${errors.join("; ")}`
|
|
8730
|
+
);
|
|
8731
|
+
})();
|
|
8732
|
+
return playBundlerPromise;
|
|
10275
8733
|
}
|
|
10276
|
-
function
|
|
10277
|
-
|
|
10278
|
-
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
8734
|
+
function stripCommentsToSpaces(source) {
|
|
8735
|
+
let output2 = "";
|
|
8736
|
+
let quote = null;
|
|
8737
|
+
let escaped = false;
|
|
8738
|
+
let lineComment = false;
|
|
8739
|
+
let blockComment = false;
|
|
8740
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
8741
|
+
const char = source[index];
|
|
8742
|
+
const next = source[index + 1];
|
|
8743
|
+
if (lineComment) {
|
|
8744
|
+
if (char === "\n" || char === "\r") {
|
|
8745
|
+
lineComment = false;
|
|
8746
|
+
output2 += char;
|
|
8747
|
+
} else {
|
|
8748
|
+
output2 += " ";
|
|
8749
|
+
}
|
|
8750
|
+
continue;
|
|
8751
|
+
}
|
|
8752
|
+
if (blockComment) {
|
|
8753
|
+
if (char === "*" && next === "/") {
|
|
8754
|
+
output2 += " ";
|
|
8755
|
+
index += 1;
|
|
8756
|
+
blockComment = false;
|
|
8757
|
+
} else {
|
|
8758
|
+
output2 += char === "\n" || char === "\r" ? char : " ";
|
|
8759
|
+
}
|
|
8760
|
+
continue;
|
|
8761
|
+
}
|
|
8762
|
+
if (quote) {
|
|
8763
|
+
output2 += char;
|
|
8764
|
+
if (escaped) {
|
|
8765
|
+
escaped = false;
|
|
8766
|
+
} else if (char === "\\") {
|
|
8767
|
+
escaped = true;
|
|
8768
|
+
} else if (char === quote) {
|
|
8769
|
+
quote = null;
|
|
8770
|
+
}
|
|
8771
|
+
continue;
|
|
8772
|
+
}
|
|
8773
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
8774
|
+
quote = char;
|
|
8775
|
+
output2 += char;
|
|
8776
|
+
continue;
|
|
8777
|
+
}
|
|
8778
|
+
if (char === "/" && next === "/") {
|
|
8779
|
+
output2 += " ";
|
|
8780
|
+
index += 1;
|
|
8781
|
+
lineComment = true;
|
|
8782
|
+
continue;
|
|
8783
|
+
}
|
|
8784
|
+
if (char === "/" && next === "*") {
|
|
8785
|
+
output2 += " ";
|
|
8786
|
+
index += 1;
|
|
8787
|
+
blockComment = true;
|
|
8788
|
+
continue;
|
|
8789
|
+
}
|
|
8790
|
+
output2 += char;
|
|
10291
8791
|
}
|
|
10292
|
-
|
|
10293
|
-
|
|
8792
|
+
return output2;
|
|
8793
|
+
}
|
|
8794
|
+
function unquotePlayNameLiteral(raw) {
|
|
8795
|
+
if (raw.length < 2) return null;
|
|
8796
|
+
const quote = raw[0];
|
|
8797
|
+
let value = "";
|
|
8798
|
+
for (let index = 1; index < raw.length - 1; index += 1) {
|
|
8799
|
+
const char = raw[index];
|
|
8800
|
+
if (char !== "\\") {
|
|
8801
|
+
value += char;
|
|
8802
|
+
continue;
|
|
8803
|
+
}
|
|
8804
|
+
index += 1;
|
|
8805
|
+
const escaped = raw[index];
|
|
8806
|
+
if (escaped === void 0) return null;
|
|
8807
|
+
value += escaped === "n" ? "\n" : escaped === "r" ? "\r" : escaped === "t" ? " " : escaped;
|
|
10294
8808
|
}
|
|
10295
|
-
return null;
|
|
8809
|
+
if (quote === "`" && value.includes("${")) return null;
|
|
8810
|
+
return value;
|
|
10296
8811
|
}
|
|
10297
|
-
function
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
8812
|
+
function findMatchingBrace(source, openIndex) {
|
|
8813
|
+
let depth = 0;
|
|
8814
|
+
let quote = null;
|
|
8815
|
+
let escaped = false;
|
|
8816
|
+
for (let index = openIndex; index < source.length; index += 1) {
|
|
8817
|
+
const char = source[index];
|
|
8818
|
+
if (quote) {
|
|
8819
|
+
if (escaped) {
|
|
8820
|
+
escaped = false;
|
|
8821
|
+
} else if (char === "\\") {
|
|
8822
|
+
escaped = true;
|
|
8823
|
+
} else if (char === quote) {
|
|
8824
|
+
quote = null;
|
|
8825
|
+
}
|
|
8826
|
+
continue;
|
|
10304
8827
|
}
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10308
|
-
|
|
8828
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
8829
|
+
quote = char;
|
|
8830
|
+
continue;
|
|
8831
|
+
}
|
|
8832
|
+
if (char === "{") depth += 1;
|
|
8833
|
+
if (char === "}") {
|
|
8834
|
+
depth -= 1;
|
|
8835
|
+
if (depth === 0) return index;
|
|
8836
|
+
}
|
|
8837
|
+
}
|
|
8838
|
+
return -1;
|
|
10309
8839
|
}
|
|
10310
|
-
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
8840
|
+
function extractDefinedPlayName(code) {
|
|
8841
|
+
const source = stripCommentsToSpaces(code);
|
|
8842
|
+
const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
|
|
8843
|
+
for (const match of source.matchAll(callPattern)) {
|
|
8844
|
+
const openParen = match.index + match[0].length - 1;
|
|
8845
|
+
const firstArgStart = openParen + 1;
|
|
8846
|
+
const firstNonSpace = source.slice(firstArgStart).search(/\S/);
|
|
8847
|
+
if (firstNonSpace < 0) continue;
|
|
8848
|
+
const argIndex = firstArgStart + firstNonSpace;
|
|
8849
|
+
const quote = source[argIndex];
|
|
8850
|
+
if (quote === '"' || quote === "'" || quote === "`") {
|
|
8851
|
+
const literalMatch = source.slice(argIndex).match(/^(['"`])(?:\\.|(?!\1)[\s\S])*\1/);
|
|
8852
|
+
const value2 = literalMatch ? unquotePlayNameLiteral(literalMatch[0]) : null;
|
|
8853
|
+
if (value2?.trim()) return value2.trim();
|
|
8854
|
+
}
|
|
8855
|
+
if (quote !== "{") continue;
|
|
8856
|
+
const closeBrace = findMatchingBrace(source, argIndex);
|
|
8857
|
+
if (closeBrace < 0) continue;
|
|
8858
|
+
const objectSource = source.slice(argIndex + 1, closeBrace);
|
|
8859
|
+
const idMatch = objectSource.match(
|
|
8860
|
+
/(?:^|[,{\s])(?:id|name|['"](?:id|name)['"])\s*:\s*(['"`])((?:\\.|(?!\1)[\s\S])*)\1/
|
|
8861
|
+
);
|
|
8862
|
+
const value = idMatch ? unquotePlayNameLiteral(`${idMatch[1]}${idMatch[2]}${idMatch[1]}`) : null;
|
|
8863
|
+
if (value?.trim()) return value.trim();
|
|
8864
|
+
}
|
|
8865
|
+
return null;
|
|
10315
8866
|
}
|
|
10316
|
-
|
|
10317
|
-
// src/cli/commands/play.ts
|
|
10318
8867
|
var PLAY_RUN_RESERVED_BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
10319
8868
|
"--json",
|
|
10320
8869
|
"--wait",
|
|
@@ -10349,7 +8898,7 @@ function traceCliSync(phase, fields, run) {
|
|
|
10349
8898
|
}
|
|
10350
8899
|
}
|
|
10351
8900
|
function sleep5(ms) {
|
|
10352
|
-
return new Promise((
|
|
8901
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
10353
8902
|
}
|
|
10354
8903
|
function parseReferencedPlayTarget2(target) {
|
|
10355
8904
|
const trimmed = target.trim();
|
|
@@ -10393,7 +8942,7 @@ function formatPlayListReference(play) {
|
|
|
10393
8942
|
return play.reference || play.name;
|
|
10394
8943
|
}
|
|
10395
8944
|
function defaultMaterializedPlayPath(reference) {
|
|
10396
|
-
return
|
|
8945
|
+
return resolve7(defaultStarterPlayPath(reference));
|
|
10397
8946
|
}
|
|
10398
8947
|
function defaultStarterPlayPath(reference) {
|
|
10399
8948
|
const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
|
|
@@ -10419,8 +8968,8 @@ function materializeRemotePlaySource(input2) {
|
|
|
10419
8968
|
return null;
|
|
10420
8969
|
}
|
|
10421
8970
|
const outputPath = input2.outPath ?? defaultMaterializedPlayPath(input2.playName);
|
|
10422
|
-
if (
|
|
10423
|
-
const existingSource =
|
|
8971
|
+
if (existsSync6(outputPath)) {
|
|
8972
|
+
const existingSource = readFileSync6(outputPath, "utf-8");
|
|
10424
8973
|
if (existingSource === input2.sourceCode) {
|
|
10425
8974
|
return { path: outputPath, status: "unchanged", created: false };
|
|
10426
8975
|
}
|
|
@@ -10472,7 +9021,7 @@ function extractPlayName(code, filePath) {
|
|
|
10472
9021
|
throw buildMissingDefinePlayError(filePath);
|
|
10473
9022
|
}
|
|
10474
9023
|
function isFileTarget(target) {
|
|
10475
|
-
return
|
|
9024
|
+
return existsSync6(resolve7(target));
|
|
10476
9025
|
}
|
|
10477
9026
|
function looksLikeRunId(target) {
|
|
10478
9027
|
return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
|
|
@@ -10501,7 +9050,7 @@ function parsePositiveInteger3(value, flagName) {
|
|
|
10501
9050
|
return parsed;
|
|
10502
9051
|
}
|
|
10503
9052
|
function parseJsonInput(raw) {
|
|
10504
|
-
const source = raw.startsWith("@") ?
|
|
9053
|
+
const source = raw.startsWith("@") ? readFileSync6(resolve7(raw.slice(1)), "utf-8") : raw;
|
|
10505
9054
|
const parsed = JSON.parse(source);
|
|
10506
9055
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
10507
9056
|
throw new Error("--input must be a JSON object.");
|
|
@@ -10603,7 +9152,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
|
|
|
10603
9152
|
function isLocalFilePathValue(value) {
|
|
10604
9153
|
if (typeof value !== "string" || !value.trim()) return false;
|
|
10605
9154
|
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
|
|
10606
|
-
return
|
|
9155
|
+
return existsSync6(resolve7(value));
|
|
10607
9156
|
}
|
|
10608
9157
|
function inputContainsLocalFilePath(value) {
|
|
10609
9158
|
if (isLocalFilePathValue(value)) {
|
|
@@ -10650,7 +9199,7 @@ function collectLocalFileInputRefs(value, inputPath, key, out) {
|
|
|
10650
9199
|
const looksLikeFile = /\.[a-z0-9]{1,8}$/i.test(trimmed);
|
|
10651
9200
|
if (keyIsCsvData) {
|
|
10652
9201
|
out.push({ inputPath, value: trimmed, isCsvData: true });
|
|
10653
|
-
} else if (endsWithCsv || looksLikeFile &&
|
|
9202
|
+
} else if (endsWithCsv || looksLikeFile && existsSync6(resolve7(trimmed))) {
|
|
10654
9203
|
out.push({ inputPath, value: trimmed, isCsvData: false });
|
|
10655
9204
|
}
|
|
10656
9205
|
return;
|
|
@@ -10692,8 +9241,8 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
10692
9241
|
collectLocalFileInputRefs(value, key, key, refs);
|
|
10693
9242
|
}
|
|
10694
9243
|
for (const ref of refs) {
|
|
10695
|
-
const absolutePath =
|
|
10696
|
-
if (!
|
|
9244
|
+
const absolutePath = resolve7(ref.value);
|
|
9245
|
+
if (!existsSync6(absolutePath)) {
|
|
10697
9246
|
throw new DeeplineError(
|
|
10698
9247
|
`Input ${ref.inputPath} references a local file that does not exist: ${ref.value} (resolved to ${absolutePath}). No run was created.`,
|
|
10699
9248
|
void 0,
|
|
@@ -10701,9 +9250,9 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
10701
9250
|
{ inputPath: ref.inputPath, path: ref.value, resolved: absolutePath }
|
|
10702
9251
|
);
|
|
10703
9252
|
}
|
|
10704
|
-
let
|
|
9253
|
+
let stat2;
|
|
10705
9254
|
try {
|
|
10706
|
-
|
|
9255
|
+
stat2 = statSync2(absolutePath);
|
|
10707
9256
|
} catch (error) {
|
|
10708
9257
|
throw new DeeplineError(
|
|
10709
9258
|
`Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
|
|
@@ -10712,7 +9261,7 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
10712
9261
|
{ inputPath: ref.inputPath, path: ref.value }
|
|
10713
9262
|
);
|
|
10714
9263
|
}
|
|
10715
|
-
if (!
|
|
9264
|
+
if (!stat2.isFile()) {
|
|
10716
9265
|
throw new DeeplineError(
|
|
10717
9266
|
`Input ${ref.inputPath} references ${ref.value}, which is not a file. No run was created.`,
|
|
10718
9267
|
void 0,
|
|
@@ -10729,7 +9278,7 @@ function preflightLocalFileInputs(runtimeInput) {
|
|
|
10729
9278
|
function preflightCsvDataInput(ref, absolutePath) {
|
|
10730
9279
|
let content;
|
|
10731
9280
|
try {
|
|
10732
|
-
content =
|
|
9281
|
+
content = readFileSync6(absolutePath, "utf-8");
|
|
10733
9282
|
} catch (error) {
|
|
10734
9283
|
throw new DeeplineError(
|
|
10735
9284
|
`Input ${ref.inputPath} CSV ${ref.value} is not readable: ${error instanceof Error ? error.message : String(error)}. No run was created.`,
|
|
@@ -10811,8 +9360,8 @@ async function stageFileInputArgs(input2) {
|
|
|
10811
9360
|
const localFiles = uniqueBindings.flatMap((binding) => {
|
|
10812
9361
|
const value = getDottedInputValue(input2.runtimeInput, binding.inputPath);
|
|
10813
9362
|
if (!isLocalFilePathValue(value)) return [];
|
|
10814
|
-
const absolutePath =
|
|
10815
|
-
return [{ binding, absolutePath, logicalPath:
|
|
9363
|
+
const absolutePath = resolve7(value);
|
|
9364
|
+
return [{ binding, absolutePath, logicalPath: basename(absolutePath) }];
|
|
10816
9365
|
});
|
|
10817
9366
|
if (localFiles.length === 0) {
|
|
10818
9367
|
return { inputFile: null, packagedFiles: [] };
|
|
@@ -10844,20 +9393,20 @@ async function stageFileInputArgs(input2) {
|
|
|
10844
9393
|
};
|
|
10845
9394
|
}
|
|
10846
9395
|
function stageFile(logicalPath, absolutePath) {
|
|
10847
|
-
const buffer =
|
|
9396
|
+
const buffer = readFileSync6(absolutePath);
|
|
10848
9397
|
return {
|
|
10849
9398
|
logicalPath,
|
|
10850
9399
|
contentBase64: buffer.toString("base64"),
|
|
10851
|
-
contentHash:
|
|
9400
|
+
contentHash: createHash("sha256").update(buffer).digest("hex"),
|
|
10852
9401
|
contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
|
|
10853
9402
|
bytes: buffer.byteLength
|
|
10854
9403
|
};
|
|
10855
9404
|
}
|
|
10856
9405
|
function normalizePlayPath(filePath) {
|
|
10857
9406
|
try {
|
|
10858
|
-
return realpathSync.native(
|
|
9407
|
+
return realpathSync.native(resolve7(filePath));
|
|
10859
9408
|
} catch {
|
|
10860
|
-
return
|
|
9409
|
+
return resolve7(filePath);
|
|
10861
9410
|
}
|
|
10862
9411
|
}
|
|
10863
9412
|
function formatBundlingErrors(filePath, errors) {
|
|
@@ -10868,6 +9417,7 @@ function formatUnresolvedPackagedFiles(filePath, unresolvedFileReferences) {
|
|
|
10868
9417
|
return `Failed to package local ctx.csv(...) files in ${filePath}: ${details}`;
|
|
10869
9418
|
}
|
|
10870
9419
|
async function collectBundledPlayGraph(entryFile, profile = null) {
|
|
9420
|
+
const playBundler = await loadPlayBundler();
|
|
10871
9421
|
const nodes = /* @__PURE__ */ new Map();
|
|
10872
9422
|
const visiting = /* @__PURE__ */ new Set();
|
|
10873
9423
|
const artifactKind = resolveExecutionProfile(profile).artifactKind;
|
|
@@ -10884,7 +9434,7 @@ async function collectBundledPlayGraph(entryFile, profile = null) {
|
|
|
10884
9434
|
}
|
|
10885
9435
|
visiting.add(absolutePath);
|
|
10886
9436
|
try {
|
|
10887
|
-
const bundleResult = await
|
|
9437
|
+
const bundleResult = await playBundler.bundlePlayFile(absolutePath, {
|
|
10888
9438
|
target: artifactKind
|
|
10889
9439
|
});
|
|
10890
9440
|
if (bundleResult.success === false) {
|
|
@@ -11508,6 +10058,7 @@ async function waitForPlayCompletionByStream(input2) {
|
|
|
11508
10058
|
input2.workflowId,
|
|
11509
10059
|
{
|
|
11510
10060
|
signal: controller.signal,
|
|
10061
|
+
fallback: "none",
|
|
11511
10062
|
onNotice: input2.jsonOutput ? void 0 : (message) => input2.progress.writeLine(message)
|
|
11512
10063
|
}
|
|
11513
10064
|
)) {
|
|
@@ -12521,15 +11072,15 @@ function formatDatasetStatsLines(datasetStats, indent2 = " ") {
|
|
|
12521
11072
|
return [];
|
|
12522
11073
|
}
|
|
12523
11074
|
const lines = [`${indent2}summary:`];
|
|
12524
|
-
for (const [column,
|
|
11075
|
+
for (const [column, stat2] of Object.entries(datasetStats.columnStats).slice(
|
|
12525
11076
|
0,
|
|
12526
11077
|
12
|
|
12527
11078
|
)) {
|
|
12528
|
-
const topValues =
|
|
12529
|
-
const sample =
|
|
12530
|
-
const execution =
|
|
11079
|
+
const topValues = stat2.top_values ? `, top_values=${Object.entries(stat2.top_values).slice(0, 3).map(([value, count]) => `${value}=${count}`).join(", ")}` : "";
|
|
11080
|
+
const sample = stat2.sample_value !== void 0 ? `, sample_value=${JSON.stringify(stat2.sample_value)}` : "";
|
|
11081
|
+
const execution = stat2.execution ? `, execution=${Object.entries(stat2.execution).map(([bucket, count]) => `${bucket}=${count}`).join(", ")}` : "";
|
|
12531
11082
|
lines.push(
|
|
12532
|
-
`${indent2} ${column}: non_empty=${
|
|
11083
|
+
`${indent2} ${column}: non_empty=${stat2.non_empty}, unique=${stat2.unique}${topValues}${sample}${execution}`
|
|
12533
11084
|
);
|
|
12534
11085
|
}
|
|
12535
11086
|
return lines;
|
|
@@ -12842,7 +11393,7 @@ function shellSingleQuote(value) {
|
|
|
12842
11393
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
12843
11394
|
}
|
|
12844
11395
|
function runExportRetryCommand(runId, outPath, datasetPath) {
|
|
12845
|
-
return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(
|
|
11396
|
+
return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve7(outPath))}`;
|
|
12846
11397
|
}
|
|
12847
11398
|
function extractRunPlayName(status) {
|
|
12848
11399
|
const run = status.run;
|
|
@@ -13646,7 +12197,7 @@ async function handlePlayCheck(args) {
|
|
|
13646
12197
|
}
|
|
13647
12198
|
return 0;
|
|
13648
12199
|
} catch (error) {
|
|
13649
|
-
const resolved =
|
|
12200
|
+
const resolved = resolve7(options.target);
|
|
13650
12201
|
const message = error instanceof Error && error.message ? error.message : `File not found: ${resolved}`;
|
|
13651
12202
|
if (options.jsonOutput) {
|
|
13652
12203
|
process.stdout.write(
|
|
@@ -13663,8 +12214,8 @@ async function handlePlayCheck(args) {
|
|
|
13663
12214
|
return 1;
|
|
13664
12215
|
}
|
|
13665
12216
|
}
|
|
13666
|
-
const absolutePlayPath =
|
|
13667
|
-
const sourceCode =
|
|
12217
|
+
const absolutePlayPath = resolve7(options.target);
|
|
12218
|
+
const sourceCode = readFileSync6(absolutePlayPath, "utf-8");
|
|
13668
12219
|
let graph;
|
|
13669
12220
|
try {
|
|
13670
12221
|
graph = await collectBundledPlayGraph(absolutePlayPath);
|
|
@@ -13743,12 +12294,12 @@ async function handleFileBackedRun(options) {
|
|
|
13743
12294
|
}
|
|
13744
12295
|
const client2 = new DeeplineClient();
|
|
13745
12296
|
const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
|
|
13746
|
-
const absolutePlayPath =
|
|
12297
|
+
const absolutePlayPath = resolve7(options.target.path);
|
|
13747
12298
|
progress.phase("compiling play");
|
|
13748
12299
|
const sourceCode = traceCliSync(
|
|
13749
12300
|
"cli.play_file_read_source",
|
|
13750
12301
|
{ targetKind: "file" },
|
|
13751
|
-
() =>
|
|
12302
|
+
() => readFileSync6(absolutePlayPath, "utf-8")
|
|
13752
12303
|
);
|
|
13753
12304
|
const runtimeInput = options.input ? { ...options.input } : {};
|
|
13754
12305
|
try {
|
|
@@ -14067,11 +12618,11 @@ async function handlePlayRun(args) {
|
|
|
14067
12618
|
if (isFileTarget(options.target.path)) {
|
|
14068
12619
|
return handleFileBackedRun(options);
|
|
14069
12620
|
}
|
|
14070
|
-
const resolved =
|
|
12621
|
+
const resolved = resolve7(options.target.path);
|
|
14071
12622
|
console.error(`File not found: ${resolved}`);
|
|
14072
|
-
const dir =
|
|
14073
|
-
if (
|
|
14074
|
-
const base =
|
|
12623
|
+
const dir = dirname6(resolved);
|
|
12624
|
+
if (existsSync6(dir)) {
|
|
12625
|
+
const base = basename(resolved);
|
|
14075
12626
|
try {
|
|
14076
12627
|
const siblings = readdirSync(dir).filter(
|
|
14077
12628
|
(f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
|
|
@@ -14079,7 +12630,7 @@ async function handlePlayRun(args) {
|
|
|
14079
12630
|
if (siblings.length > 0) {
|
|
14080
12631
|
console.error(`Did you mean one of these?`);
|
|
14081
12632
|
for (const s of siblings.slice(0, 5)) {
|
|
14082
|
-
console.error(` ${
|
|
12633
|
+
console.error(` ${join5(dir, s)}`);
|
|
14083
12634
|
}
|
|
14084
12635
|
}
|
|
14085
12636
|
} catch {
|
|
@@ -14234,7 +12785,7 @@ async function handleRunLogs(args) {
|
|
|
14234
12785
|
continue;
|
|
14235
12786
|
}
|
|
14236
12787
|
if (arg === "--out" && args[index + 1]) {
|
|
14237
|
-
outPath =
|
|
12788
|
+
outPath = resolve7(args[++index]);
|
|
14238
12789
|
}
|
|
14239
12790
|
}
|
|
14240
12791
|
const client2 = new DeeplineClient();
|
|
@@ -14366,7 +12917,7 @@ async function handleRunExport(args) {
|
|
|
14366
12917
|
for (let index = 0; index < args.length; index += 1) {
|
|
14367
12918
|
const arg = args[index];
|
|
14368
12919
|
if (arg === "--out" && args[index + 1]) {
|
|
14369
|
-
outPath =
|
|
12920
|
+
outPath = resolve7(args[++index]);
|
|
14370
12921
|
continue;
|
|
14371
12922
|
}
|
|
14372
12923
|
if (arg === "--dataset" && args[index + 1]) {
|
|
@@ -14374,7 +12925,7 @@ async function handleRunExport(args) {
|
|
|
14374
12925
|
continue;
|
|
14375
12926
|
}
|
|
14376
12927
|
if (arg === "--metadata-out" && args[index + 1]) {
|
|
14377
|
-
metadataOutPath =
|
|
12928
|
+
metadataOutPath = resolve7(args[++index]);
|
|
14378
12929
|
}
|
|
14379
12930
|
}
|
|
14380
12931
|
if (!outPath) {
|
|
@@ -14446,10 +12997,10 @@ async function handlePlayGet(args) {
|
|
|
14446
12997
|
for (let index = 1; index < args.length; index += 1) {
|
|
14447
12998
|
const arg = args[index];
|
|
14448
12999
|
if (arg === "--out" && args[index + 1]) {
|
|
14449
|
-
outPath =
|
|
13000
|
+
outPath = resolve7(args[++index]);
|
|
14450
13001
|
}
|
|
14451
13002
|
}
|
|
14452
|
-
const playName = isFileTarget(target) ? extractPlayName(
|
|
13003
|
+
const playName = isFileTarget(target) ? extractPlayName(readFileSync6(resolve7(target), "utf-8"), resolve7(target)) : parseReferencedPlayTarget2(target).playName;
|
|
14453
13004
|
const detail = isFileTarget(target) ? await client2.getPlay(playName) : await assertCanonicalNamedPlayReference(client2, target);
|
|
14454
13005
|
const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
|
|
14455
13006
|
const materializedFile = outPath ? materializeRemotePlaySource({
|
|
@@ -14892,7 +13443,7 @@ async function handlePlayDescribe(args) {
|
|
|
14892
13443
|
const definedName = isFileTarget(playName) ? (() => {
|
|
14893
13444
|
try {
|
|
14894
13445
|
return extractPlayName(
|
|
14895
|
-
|
|
13446
|
+
readFileSync6(resolve7(playName), "utf-8"),
|
|
14896
13447
|
playName
|
|
14897
13448
|
);
|
|
14898
13449
|
} catch {
|
|
@@ -14973,7 +13524,7 @@ async function handlePlayPublish(args) {
|
|
|
14973
13524
|
graph = await traceCliSpan(
|
|
14974
13525
|
"cli.play_publish_bundle_graph",
|
|
14975
13526
|
{ targetKind: "file" },
|
|
14976
|
-
() => collectBundledPlayGraph(
|
|
13527
|
+
() => collectBundledPlayGraph(resolve7(playName))
|
|
14977
13528
|
);
|
|
14978
13529
|
await traceCliSpan(
|
|
14979
13530
|
"cli.play_publish_compile_manifests",
|
|
@@ -15093,14 +13644,15 @@ Concepts:
|
|
|
15093
13644
|
Stable ctx.tools.execute({ id, tool, input }) calls are replay-safe.
|
|
15094
13645
|
ctx.dataset adds row keys and row progress.
|
|
15095
13646
|
Named play runs use the live revision unless --latest or --revision-id is set.
|
|
15096
|
-
|
|
13647
|
+
Installed npm and repo-local CLIs can run saved/prebuilt plays by name or
|
|
13648
|
+
bundle local .play.ts files for development workflows.
|
|
13649
|
+
Running a local file does not make it live; use publish or set-live for that.
|
|
15097
13650
|
|
|
15098
13651
|
Common commands:
|
|
15099
13652
|
deepline plays search email --json
|
|
15100
13653
|
deepline plays describe prebuilt/person-linkedin-to-email --json
|
|
15101
|
-
deepline plays check
|
|
15102
|
-
deepline plays run
|
|
15103
|
-
deepline plays set-live my.play.ts --json
|
|
13654
|
+
deepline plays check prebuilt/name-and-domain-to-email-waterfall-batch
|
|
13655
|
+
deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
|
|
15104
13656
|
deepline plays get prebuilt/person-linkedin-to-email --json
|
|
15105
13657
|
`
|
|
15106
13658
|
);
|
|
@@ -15108,14 +13660,14 @@ Common commands:
|
|
|
15108
13660
|
"after",
|
|
15109
13661
|
`
|
|
15110
13662
|
Notes:
|
|
15111
|
-
Validates a local play without storing it, promoting it, or starting a run.
|
|
15112
|
-
This uses the authoritative cloud preflight path.
|
|
15113
13663
|
For named or prebuilt plays, validates that the contract is discoverable
|
|
15114
13664
|
without starting a run or spending Deepline credits.
|
|
13665
|
+
Local .play.ts checks bundle the play, validate its artifact, and stop before
|
|
13666
|
+
any cloud run is created.
|
|
15115
13667
|
|
|
15116
13668
|
Examples:
|
|
15117
|
-
deepline plays check my.play.ts
|
|
15118
13669
|
deepline plays check prebuilt/name-and-domain-to-email-waterfall-batch
|
|
13670
|
+
deepline plays check my-play --json
|
|
15119
13671
|
deepline plays check my.play.ts --json
|
|
15120
13672
|
`
|
|
15121
13673
|
).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
@@ -15124,11 +13676,10 @@ Examples:
|
|
|
15124
13676
|
...options.json ? ["--json"] : []
|
|
15125
13677
|
]);
|
|
15126
13678
|
});
|
|
15127
|
-
play.command("run [target]").description("Run a play
|
|
13679
|
+
play.command("run [target]").description("Run a named/prebuilt play or local play file.").allowUnknownOption(true).allowExcessArguments(true).addHelpText(
|
|
15128
13680
|
"after",
|
|
15129
13681
|
`
|
|
15130
13682
|
Notes:
|
|
15131
|
-
Local files are bundled, preflighted, then run in Deepline cloud.
|
|
15132
13683
|
Named plays run the live saved revision.
|
|
15133
13684
|
Unknown --foo value and --foo.bar value flags are passed into play input.
|
|
15134
13685
|
Example: --limit 5 becomes input.limit = 5.
|
|
@@ -15168,11 +13719,11 @@ Idempotent execution:
|
|
|
15168
13719
|
.run({ key: 'domain' })
|
|
15169
13720
|
|
|
15170
13721
|
Examples:
|
|
13722
|
+
deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
|
|
13723
|
+
deepline plays run long-background-play --no-wait
|
|
15171
13724
|
deepline plays run my.play.ts --input '{"domain":"stripe.com"}'
|
|
15172
13725
|
deepline plays run my.play.ts --input @input.json --json
|
|
15173
|
-
deepline plays run prebuilt/person-linkedin-to-email --input '{"linkedin_url":"..."}'
|
|
15174
13726
|
deepline plays run cto-search.play.ts --limit 5
|
|
15175
|
-
deepline plays run long-background-play --no-wait
|
|
15176
13727
|
deepline runs export <run-id> --out output.csv
|
|
15177
13728
|
deepline runs get <run-id>
|
|
15178
13729
|
`
|
|
@@ -15365,20 +13916,21 @@ Examples:
|
|
|
15365
13916
|
"after",
|
|
15366
13917
|
`
|
|
15367
13918
|
Notes:
|
|
15368
|
-
Mutates cloud state. For a
|
|
15369
|
-
|
|
15370
|
-
|
|
13919
|
+
Mutates cloud state. For a saved play, --latest or --revision-id promotes an
|
|
13920
|
+
existing saved revision live.
|
|
13921
|
+
Local .play.ts publishing bundles the file, validates it, saves a revision,
|
|
13922
|
+
and promotes that revision live.
|
|
15371
13923
|
Running a local file with plays run does not publish it.
|
|
15372
13924
|
|
|
15373
13925
|
Examples:
|
|
15374
|
-
deepline plays set-live my.play.ts --json
|
|
15375
13926
|
deepline plays set-live my-play --latest --json
|
|
15376
13927
|
deepline plays set-live my-play --revision-id <revision-id> --json
|
|
13928
|
+
deepline plays set-live my.play.ts --json
|
|
15377
13929
|
deepline plays publish my.play.ts --json
|
|
15378
13930
|
`
|
|
15379
13931
|
);
|
|
15380
13932
|
addPublishHelp(
|
|
15381
|
-
play.command("publish <target>").description("
|
|
13933
|
+
play.command("publish <target>").description("Promote a saved play revision or publish a local play file.")
|
|
15382
13934
|
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
15383
13935
|
process.exitCode = await handlePlayPublish([
|
|
15384
13936
|
target,
|
|
@@ -15389,7 +13941,7 @@ Examples:
|
|
|
15389
13941
|
});
|
|
15390
13942
|
addPublishHelp(
|
|
15391
13943
|
play.command("set-live <target>").description(
|
|
15392
|
-
"Promote a
|
|
13944
|
+
"Promote a saved revision or publish a local play file."
|
|
15393
13945
|
)
|
|
15394
13946
|
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
15395
13947
|
process.exitCode = await handlePlayPublish([
|
|
@@ -17264,7 +15816,7 @@ function expandAtFilePath(rawPath) {
|
|
|
17264
15816
|
return homedir6();
|
|
17265
15817
|
}
|
|
17266
15818
|
if (expanded.startsWith("~/") || expanded.startsWith("~\\")) {
|
|
17267
|
-
return
|
|
15819
|
+
return join6(homedir6(), expanded.slice(2));
|
|
17268
15820
|
}
|
|
17269
15821
|
return expanded;
|
|
17270
15822
|
}
|
|
@@ -17277,7 +15829,7 @@ async function readAtFileReference(value, argumentName, strip = true) {
|
|
|
17277
15829
|
throw new Error(`Invalid ${argumentName} value: empty @file path.`);
|
|
17278
15830
|
}
|
|
17279
15831
|
try {
|
|
17280
|
-
const text = await
|
|
15832
|
+
const text = await readFile(filePath, "utf8");
|
|
17281
15833
|
const normalized = text.replace(/^\uFEFF/, "");
|
|
17282
15834
|
return strip ? normalized.trim() : normalized;
|
|
17283
15835
|
} catch (error) {
|
|
@@ -17448,9 +16000,9 @@ async function buildPlanArgs(args) {
|
|
|
17448
16000
|
return planArgs;
|
|
17449
16001
|
}
|
|
17450
16002
|
async function assertInputCsvExists(inputCsv) {
|
|
17451
|
-
const path =
|
|
16003
|
+
const path = resolve8(inputCsv);
|
|
17452
16004
|
try {
|
|
17453
|
-
const info = await
|
|
16005
|
+
const info = await stat(path);
|
|
17454
16006
|
if (info.isFile()) {
|
|
17455
16007
|
return;
|
|
17456
16008
|
}
|
|
@@ -17462,8 +16014,8 @@ async function assertInputCsvExists(inputCsv) {
|
|
|
17462
16014
|
}
|
|
17463
16015
|
}
|
|
17464
16016
|
async function assertSafeOutputPath(inputCsv, outputPath) {
|
|
17465
|
-
const input2 =
|
|
17466
|
-
const output2 =
|
|
16017
|
+
const input2 = resolve8(inputCsv);
|
|
16018
|
+
const output2 = resolve8(outputPath);
|
|
17467
16019
|
if (input2 === output2) {
|
|
17468
16020
|
throw new Error(
|
|
17469
16021
|
"--input and --output must be different files when not using --in-place."
|
|
@@ -17471,8 +16023,8 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
|
|
|
17471
16023
|
}
|
|
17472
16024
|
try {
|
|
17473
16025
|
const [inputInfo, outputInfo] = await Promise.all([
|
|
17474
|
-
|
|
17475
|
-
|
|
16026
|
+
stat(input2),
|
|
16027
|
+
stat(output2)
|
|
17476
16028
|
]);
|
|
17477
16029
|
if (inputInfo.dev === outputInfo.dev && inputInfo.ino === outputInfo.ino) {
|
|
17478
16030
|
throw new Error(
|
|
@@ -17492,7 +16044,7 @@ async function assertSafeOutputPath(inputCsv, outputPath) {
|
|
|
17492
16044
|
}
|
|
17493
16045
|
async function regularFileExists(path) {
|
|
17494
16046
|
try {
|
|
17495
|
-
const info = await
|
|
16047
|
+
const info = await stat(resolve8(path));
|
|
17496
16048
|
return info.isFile();
|
|
17497
16049
|
} catch (error) {
|
|
17498
16050
|
const code = error && typeof error === "object" ? error.code : void 0;
|
|
@@ -17503,7 +16055,7 @@ async function regularFileExists(path) {
|
|
|
17503
16055
|
}
|
|
17504
16056
|
}
|
|
17505
16057
|
async function readConfig(path) {
|
|
17506
|
-
const source = await
|
|
16058
|
+
const source = await readFile(resolve8(path), "utf8");
|
|
17507
16059
|
let parsed;
|
|
17508
16060
|
try {
|
|
17509
16061
|
parsed = JSON.parse(source);
|
|
@@ -17788,7 +16340,7 @@ async function runGeneratedEnrichPlay(runArgs, options = {}) {
|
|
|
17788
16340
|
});
|
|
17789
16341
|
} catch (error) {
|
|
17790
16342
|
if (attempt === 0 && isPlayStartStreamEndedError(error)) {
|
|
17791
|
-
await new Promise((
|
|
16343
|
+
await new Promise((resolve13) => setTimeout(resolve13, 250));
|
|
17792
16344
|
continue;
|
|
17793
16345
|
}
|
|
17794
16346
|
throw error;
|
|
@@ -17819,8 +16371,8 @@ async function writeOutputCsv(outputPath, status, options) {
|
|
|
17819
16371
|
]),
|
|
17820
16372
|
options?.config
|
|
17821
16373
|
);
|
|
17822
|
-
await
|
|
17823
|
-
|
|
16374
|
+
await writeFile3(
|
|
16375
|
+
resolve8(outputPath),
|
|
17824
16376
|
csvStringFromRows(merged.rows, columns),
|
|
17825
16377
|
"utf8"
|
|
17826
16378
|
);
|
|
@@ -17830,7 +16382,7 @@ async function writeOutputCsv(outputPath, status, options) {
|
|
|
17830
16382
|
selectedRows: rowsInfo.totalRows,
|
|
17831
16383
|
enrichedRows: rowsInfo.rows.length,
|
|
17832
16384
|
rows: merged.rows.length,
|
|
17833
|
-
path:
|
|
16385
|
+
path: resolve8(outputPath),
|
|
17834
16386
|
enrichedDataRows: rowsInfo.rows
|
|
17835
16387
|
};
|
|
17836
16388
|
}
|
|
@@ -18019,12 +16571,12 @@ function firstAliasExecutionCounts(input2) {
|
|
|
18019
16571
|
const aliases = collectConfigScalarAliasOrder(input2.config);
|
|
18020
16572
|
const summaries = collectColumnStats(input2.status);
|
|
18021
16573
|
for (const alias of aliases) {
|
|
18022
|
-
const
|
|
18023
|
-
if (!
|
|
16574
|
+
const stat2 = summaries.map((summary) => summary[alias]).find(isRecord7);
|
|
16575
|
+
if (!stat2) continue;
|
|
18024
16576
|
if (input2.forceAliases.has(normalizeAlias2(alias))) {
|
|
18025
16577
|
return { executed: input2.selectedRows, reused: 0 };
|
|
18026
16578
|
}
|
|
18027
|
-
const execution = isRecord7(
|
|
16579
|
+
const execution = isRecord7(stat2.execution) ? stat2.execution : null;
|
|
18028
16580
|
if (!execution) continue;
|
|
18029
16581
|
return {
|
|
18030
16582
|
executed: parseExecutionCount(execution["completed:executed"]),
|
|
@@ -18084,11 +16636,11 @@ function rewriteEnrichJsonStatus(input2) {
|
|
|
18084
16636
|
if (isRecord7(next.columnStats) && selectedRows > 0) {
|
|
18085
16637
|
const columnStats = { ...next.columnStats };
|
|
18086
16638
|
for (const alias of forcedAliases) {
|
|
18087
|
-
const
|
|
18088
|
-
const execution = isRecord7(
|
|
18089
|
-
if (!
|
|
16639
|
+
const stat2 = isRecord7(columnStats[alias]) ? columnStats[alias] : null;
|
|
16640
|
+
const execution = isRecord7(stat2?.execution) ? stat2.execution : null;
|
|
16641
|
+
if (!stat2 || !execution) continue;
|
|
18090
16642
|
columnStats[alias] = {
|
|
18091
|
-
...
|
|
16643
|
+
...stat2,
|
|
18092
16644
|
execution: {
|
|
18093
16645
|
...execution,
|
|
18094
16646
|
"completed:executed": executionSummaryText(
|
|
@@ -18125,9 +16677,9 @@ async function persistEnrichFailureReport(input2) {
|
|
|
18125
16677
|
if (input2.jobs.length === 0) {
|
|
18126
16678
|
return null;
|
|
18127
16679
|
}
|
|
18128
|
-
const stateDir =
|
|
18129
|
-
await
|
|
18130
|
-
const reportPath =
|
|
16680
|
+
const stateDir = join6(homedir6(), ".local", "deepline", "runtime", "state");
|
|
16681
|
+
await mkdir3(stateDir, { recursive: true });
|
|
16682
|
+
const reportPath = join6(
|
|
18131
16683
|
stateDir,
|
|
18132
16684
|
`run-block-failures-${Math.floor(Date.now() / 1e3)}-${process.pid}.json`
|
|
18133
16685
|
);
|
|
@@ -18151,7 +16703,7 @@ async function persistEnrichFailureReport(input2) {
|
|
|
18151
16703
|
if (input2.rows.rowStart !== null && input2.rows.rowEnd !== null) {
|
|
18152
16704
|
report.rows = { start: input2.rows.rowStart, end: input2.rows.rowEnd };
|
|
18153
16705
|
}
|
|
18154
|
-
await
|
|
16706
|
+
await writeFile3(reportPath, `${JSON.stringify(report, null, 2)}
|
|
18155
16707
|
`, "utf8");
|
|
18156
16708
|
return reportPath;
|
|
18157
16709
|
}
|
|
@@ -18564,8 +17116,8 @@ function registerEnrichCommand(program) {
|
|
|
18564
17116
|
if (options.json) {
|
|
18565
17117
|
printJson({
|
|
18566
17118
|
dryRun: true,
|
|
18567
|
-
input:
|
|
18568
|
-
output: options.output ?
|
|
17119
|
+
input: resolve8(inputCsv),
|
|
17120
|
+
output: options.output ? resolve8(options.output) : null,
|
|
18569
17121
|
plan: summary
|
|
18570
17122
|
});
|
|
18571
17123
|
return;
|
|
@@ -18589,12 +17141,12 @@ function registerEnrichCommand(program) {
|
|
|
18589
17141
|
forceAliases,
|
|
18590
17142
|
playName: options.name
|
|
18591
17143
|
});
|
|
18592
|
-
const tempDir = await mkdtemp(
|
|
18593
|
-
const tempPlay =
|
|
17144
|
+
const tempDir = await mkdtemp(join6(tmpdir(), "deepline-enrich-play-"));
|
|
17145
|
+
const tempPlay = join6(tempDir, "deepline-enrich.play.ts");
|
|
18594
17146
|
try {
|
|
18595
|
-
await
|
|
17147
|
+
await writeFile3(tempPlay, playSource, "utf8");
|
|
18596
17148
|
const runtimeInput = {
|
|
18597
|
-
file:
|
|
17149
|
+
file: resolve8(sourceCsvPath),
|
|
18598
17150
|
...rows.rowStart !== null ? { rowStart: rows.rowStart } : {},
|
|
18599
17151
|
...rows.rowEnd !== null ? { rowEnd: rows.rowEnd } : {}
|
|
18600
17152
|
};
|
|
@@ -18756,15 +17308,15 @@ Examples:
|
|
|
18756
17308
|
|
|
18757
17309
|
// src/cli/commands/sessions.ts
|
|
18758
17310
|
import {
|
|
18759
|
-
existsSync as
|
|
17311
|
+
existsSync as existsSync7,
|
|
18760
17312
|
mkdirSync as mkdirSync5,
|
|
18761
17313
|
readdirSync as readdirSync2,
|
|
18762
|
-
readFileSync as
|
|
17314
|
+
readFileSync as readFileSync7,
|
|
18763
17315
|
statSync as statSync3,
|
|
18764
17316
|
writeFileSync as writeFileSync9
|
|
18765
17317
|
} from "fs";
|
|
18766
17318
|
import { homedir as homedir7, platform } from "os";
|
|
18767
|
-
import { basename as
|
|
17319
|
+
import { basename as basename2, dirname as dirname7, join as join7, resolve as resolve9 } from "path";
|
|
18768
17320
|
import { gzipSync } from "zlib";
|
|
18769
17321
|
import { randomUUID } from "crypto";
|
|
18770
17322
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -18783,36 +17335,36 @@ function homeDir() {
|
|
|
18783
17335
|
function detectShellContext() {
|
|
18784
17336
|
const shellPath = process.env.SHELL?.trim() || process.env.ComSpec?.trim() || process.env.COMSPEC?.trim() || "";
|
|
18785
17337
|
return {
|
|
18786
|
-
shell: shellPath ?
|
|
17338
|
+
shell: shellPath ? basename2(shellPath).replace(/\.exe$/i, "") : "unknown",
|
|
18787
17339
|
shell_path: shellPath || null,
|
|
18788
17340
|
os: platform(),
|
|
18789
17341
|
cwd: process.cwd()
|
|
18790
17342
|
};
|
|
18791
17343
|
}
|
|
18792
17344
|
function claudeProjectsRoot() {
|
|
18793
|
-
return
|
|
17345
|
+
return join7(homeDir(), ".claude", "projects");
|
|
18794
17346
|
}
|
|
18795
17347
|
function codexSessionsRoot() {
|
|
18796
|
-
return
|
|
17348
|
+
return join7(homeDir(), ".codex", "sessions");
|
|
18797
17349
|
}
|
|
18798
17350
|
function listClaudeSessionFiles() {
|
|
18799
17351
|
const root = claudeProjectsRoot();
|
|
18800
|
-
if (!
|
|
17352
|
+
if (!existsSync7(root)) return [];
|
|
18801
17353
|
const projectDirs = readDirectoryNames(root);
|
|
18802
17354
|
const files = [];
|
|
18803
17355
|
for (const projectDir of projectDirs) {
|
|
18804
|
-
const fullProjectDir =
|
|
17356
|
+
const fullProjectDir = join7(root, projectDir);
|
|
18805
17357
|
for (const fileName of readDirectoryNames(fullProjectDir)) {
|
|
18806
17358
|
if (fileName.endsWith(".jsonl")) {
|
|
18807
|
-
const filePath =
|
|
17359
|
+
const filePath = join7(fullProjectDir, fileName);
|
|
18808
17360
|
const sessionId = sessionIdFromClaudeFilePath(filePath);
|
|
18809
|
-
const
|
|
18810
|
-
if (sessionId &&
|
|
17361
|
+
const stat2 = statIfReadable(filePath);
|
|
17362
|
+
if (sessionId && stat2) {
|
|
18811
17363
|
files.push({
|
|
18812
17364
|
agent: "claude",
|
|
18813
17365
|
sessionId,
|
|
18814
17366
|
filePath,
|
|
18815
|
-
mtimeMs:
|
|
17367
|
+
mtimeMs: stat2.mtimeMs
|
|
18816
17368
|
});
|
|
18817
17369
|
}
|
|
18818
17370
|
}
|
|
@@ -18822,14 +17374,14 @@ function listClaudeSessionFiles() {
|
|
|
18822
17374
|
}
|
|
18823
17375
|
function listCodexSessionFiles() {
|
|
18824
17376
|
const root = codexSessionsRoot();
|
|
18825
|
-
if (!
|
|
17377
|
+
if (!existsSync7(root)) return [];
|
|
18826
17378
|
const files = [];
|
|
18827
17379
|
for (const filePath of listJsonlFilesRecursive(root, 5)) {
|
|
18828
|
-
const
|
|
18829
|
-
if (!
|
|
17380
|
+
const stat2 = statIfReadable(filePath);
|
|
17381
|
+
if (!stat2) continue;
|
|
18830
17382
|
const sessionId = sessionIdFromCodexFilePath(filePath) ?? readCodexSessionId(filePath);
|
|
18831
17383
|
if (!sessionId) continue;
|
|
18832
|
-
files.push({ agent: "codex", sessionId, filePath, mtimeMs:
|
|
17384
|
+
files.push({ agent: "codex", sessionId, filePath, mtimeMs: stat2.mtimeMs });
|
|
18833
17385
|
}
|
|
18834
17386
|
return files;
|
|
18835
17387
|
}
|
|
@@ -18861,7 +17413,7 @@ function listJsonlFilesRecursive(root, maxDepth) {
|
|
|
18861
17413
|
return;
|
|
18862
17414
|
}
|
|
18863
17415
|
for (const entry of entries) {
|
|
18864
|
-
const fullPath =
|
|
17416
|
+
const fullPath = join7(dir, entry.name);
|
|
18865
17417
|
if (entry.isDirectory()) {
|
|
18866
17418
|
visit(fullPath, depth + 1);
|
|
18867
17419
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
@@ -18889,15 +17441,15 @@ function newestSessionFile(agent) {
|
|
|
18889
17441
|
return newest;
|
|
18890
17442
|
}
|
|
18891
17443
|
function sessionIdFromClaudeFilePath(filePath) {
|
|
18892
|
-
return
|
|
17444
|
+
return basename2(filePath, ".jsonl");
|
|
18893
17445
|
}
|
|
18894
17446
|
function sessionIdFromCodexFilePath(filePath) {
|
|
18895
|
-
const match =
|
|
17447
|
+
const match = basename2(filePath, ".jsonl").match(UUID_IN_TEXT_RE);
|
|
18896
17448
|
return match?.[0] ?? null;
|
|
18897
17449
|
}
|
|
18898
17450
|
function readCodexSessionId(filePath) {
|
|
18899
17451
|
try {
|
|
18900
|
-
for (const line of normalizedJsonLines(
|
|
17452
|
+
for (const line of normalizedJsonLines(readFileSync7(filePath)).slice(
|
|
18901
17453
|
0,
|
|
18902
17454
|
20
|
|
18903
17455
|
)) {
|
|
@@ -19174,25 +17726,25 @@ async function uploadChunkedSessions(sessions, options) {
|
|
|
19174
17726
|
}
|
|
19175
17727
|
async function handleSessionsSend(options) {
|
|
19176
17728
|
if (options.file) {
|
|
19177
|
-
const filePath =
|
|
19178
|
-
if (!
|
|
17729
|
+
const filePath = resolve9(options.file);
|
|
17730
|
+
if (!existsSync7(filePath)) {
|
|
19179
17731
|
throw new Error(`File not found: ${options.file}`);
|
|
19180
17732
|
}
|
|
19181
17733
|
const response2 = await uploadPayload("/api/v2/cli/send-session", {
|
|
19182
|
-
file:
|
|
19183
|
-
filename:
|
|
17734
|
+
file: readFileSync7(filePath).toString("base64"),
|
|
17735
|
+
filename: basename2(filePath)
|
|
19184
17736
|
});
|
|
19185
17737
|
printCommandEnvelope(
|
|
19186
17738
|
{
|
|
19187
17739
|
...response2,
|
|
19188
17740
|
ok: true,
|
|
19189
|
-
filename:
|
|
17741
|
+
filename: basename2(filePath),
|
|
19190
17742
|
render: {
|
|
19191
17743
|
sections: [
|
|
19192
17744
|
{
|
|
19193
17745
|
title: "sessions send",
|
|
19194
17746
|
lines: [
|
|
19195
|
-
`File '${
|
|
17747
|
+
`File '${basename2(filePath)}' uploaded to #internal-reports.`
|
|
19196
17748
|
]
|
|
19197
17749
|
}
|
|
19198
17750
|
]
|
|
@@ -19209,7 +17761,7 @@ async function handleSessionsSend(options) {
|
|
|
19209
17761
|
agent: options.agent
|
|
19210
17762
|
});
|
|
19211
17763
|
const built = targets.map((target) => {
|
|
19212
|
-
const upload = buildSessionUploadContent(
|
|
17764
|
+
const upload = buildSessionUploadContent(readFileSync7(target.filePath));
|
|
19213
17765
|
return { ...target, ...upload };
|
|
19214
17766
|
});
|
|
19215
17767
|
if (built.some((session) => session.needsChunking)) {
|
|
@@ -19273,28 +17825,28 @@ function fallbackViewerAssets() {
|
|
|
19273
17825
|
};
|
|
19274
17826
|
}
|
|
19275
17827
|
function loadViewerAssets() {
|
|
19276
|
-
const cliEntry = process.argv[1]?.trim() ?
|
|
17828
|
+
const cliEntry = process.argv[1]?.trim() ? resolve9(process.argv[1]) : null;
|
|
19277
17829
|
const candidateRoots2 = [
|
|
19278
17830
|
...cliEntry ? [
|
|
19279
|
-
|
|
19280
|
-
|
|
19281
|
-
|
|
17831
|
+
join7(dirname7(dirname7(cliEntry)), "viewer"),
|
|
17832
|
+
join7(
|
|
17833
|
+
dirname7(dirname7(dirname7(cliEntry))),
|
|
19282
17834
|
"src",
|
|
19283
17835
|
"lib",
|
|
19284
17836
|
"cli",
|
|
19285
17837
|
"viewer"
|
|
19286
17838
|
)
|
|
19287
17839
|
] : [],
|
|
19288
|
-
|
|
17840
|
+
join7(process.cwd(), "src", "lib", "cli", "viewer")
|
|
19289
17841
|
];
|
|
19290
17842
|
for (const root of candidateRoots2) {
|
|
19291
17843
|
try {
|
|
19292
|
-
const cssPath =
|
|
19293
|
-
const jsPath =
|
|
19294
|
-
if (!
|
|
17844
|
+
const cssPath = join7(root, "viewer.css");
|
|
17845
|
+
const jsPath = join7(root, "viewer.js");
|
|
17846
|
+
if (!existsSync7(cssPath) || !existsSync7(jsPath)) continue;
|
|
19295
17847
|
return {
|
|
19296
|
-
css:
|
|
19297
|
-
js:
|
|
17848
|
+
css: readFileSync7(cssPath, "utf8"),
|
|
17849
|
+
js: readFileSync7(jsPath, "utf8")
|
|
19298
17850
|
};
|
|
19299
17851
|
} catch {
|
|
19300
17852
|
continue;
|
|
@@ -19318,21 +17870,21 @@ async function handleSessionsRender(options) {
|
|
|
19318
17870
|
currentSession: options.currentSession,
|
|
19319
17871
|
agent: options.agent
|
|
19320
17872
|
});
|
|
19321
|
-
let outputPath = options.output ?
|
|
17873
|
+
let outputPath = options.output ? resolve9(options.output) : "";
|
|
19322
17874
|
if (!outputPath) {
|
|
19323
|
-
const outputDir =
|
|
17875
|
+
const outputDir = join7(process.cwd(), "deepline", "data");
|
|
19324
17876
|
mkdirSync5(outputDir, { recursive: true });
|
|
19325
|
-
outputPath =
|
|
17877
|
+
outputPath = join7(
|
|
19326
17878
|
outputDir,
|
|
19327
17879
|
targets.length > 1 ? "session-viewer.html" : `session-${targets[0]?.sessionId}.html`
|
|
19328
17880
|
);
|
|
19329
17881
|
} else {
|
|
19330
|
-
mkdirSync5(
|
|
17882
|
+
mkdirSync5(dirname7(outputPath), { recursive: true });
|
|
19331
17883
|
}
|
|
19332
17884
|
const sessions = targets.map((target) => ({
|
|
19333
17885
|
label: target.label,
|
|
19334
17886
|
events: parsePreparedEvents(
|
|
19335
|
-
prepareSessionBuffer(
|
|
17887
|
+
prepareSessionBuffer(readFileSync7(target.filePath))
|
|
19336
17888
|
)
|
|
19337
17889
|
}));
|
|
19338
17890
|
const { css, js } = loadViewerAssets();
|
|
@@ -19795,17 +18347,17 @@ function hasClaudeBinary() {
|
|
|
19795
18347
|
}
|
|
19796
18348
|
}
|
|
19797
18349
|
function launchClaude(prompt) {
|
|
19798
|
-
return new Promise((
|
|
18350
|
+
return new Promise((resolve13) => {
|
|
19799
18351
|
const child = spawn("claude", [prompt], {
|
|
19800
18352
|
stdio: "inherit",
|
|
19801
18353
|
shell: process.platform === "win32"
|
|
19802
18354
|
});
|
|
19803
|
-
child.on("error", () =>
|
|
19804
|
-
child.on("close", (status) =>
|
|
18355
|
+
child.on("error", () => resolve13(EXIT_SERVER3));
|
|
18356
|
+
child.on("close", (status) => resolve13(status ?? EXIT_OK2));
|
|
19805
18357
|
});
|
|
19806
18358
|
}
|
|
19807
18359
|
function readBody(req) {
|
|
19808
|
-
return new Promise((
|
|
18360
|
+
return new Promise((resolve13, reject) => {
|
|
19809
18361
|
let raw = "";
|
|
19810
18362
|
req.setEncoding("utf8");
|
|
19811
18363
|
req.on("data", (chunk) => {
|
|
@@ -19815,7 +18367,7 @@ function readBody(req) {
|
|
|
19815
18367
|
req.destroy();
|
|
19816
18368
|
}
|
|
19817
18369
|
});
|
|
19818
|
-
req.on("end", () =>
|
|
18370
|
+
req.on("end", () => resolve13(raw));
|
|
19819
18371
|
req.on("error", reject);
|
|
19820
18372
|
});
|
|
19821
18373
|
}
|
|
@@ -19870,7 +18422,7 @@ function startCallbackServer(input2) {
|
|
|
19870
18422
|
writeJson(res, 400, { error: "Invalid request body." });
|
|
19871
18423
|
});
|
|
19872
18424
|
});
|
|
19873
|
-
return new Promise((
|
|
18425
|
+
return new Promise((resolve13, reject) => {
|
|
19874
18426
|
server.once("error", reject);
|
|
19875
18427
|
server.listen(0, "127.0.0.1", () => {
|
|
19876
18428
|
const address = server.address();
|
|
@@ -19878,7 +18430,7 @@ function startCallbackServer(input2) {
|
|
|
19878
18430
|
reject(new Error("Failed to bind quickstart callback server."));
|
|
19879
18431
|
return;
|
|
19880
18432
|
}
|
|
19881
|
-
|
|
18433
|
+
resolve13({ server, port: address.port });
|
|
19882
18434
|
});
|
|
19883
18435
|
});
|
|
19884
18436
|
}
|
|
@@ -19904,8 +18456,8 @@ async function handleQuickstart(options) {
|
|
|
19904
18456
|
}
|
|
19905
18457
|
const state = randomBytes(32).toString("hex");
|
|
19906
18458
|
let resolveSelection;
|
|
19907
|
-
const selectionPromise = new Promise((
|
|
19908
|
-
resolveSelection =
|
|
18459
|
+
const selectionPromise = new Promise((resolve13) => {
|
|
18460
|
+
resolveSelection = resolve13;
|
|
19909
18461
|
});
|
|
19910
18462
|
let callback;
|
|
19911
18463
|
try {
|
|
@@ -20039,7 +18591,7 @@ async function readHiddenLine(prompt) {
|
|
|
20039
18591
|
if (typeof input.setRawMode === "function") input.setRawMode(true);
|
|
20040
18592
|
let value = "";
|
|
20041
18593
|
input.resume();
|
|
20042
|
-
return await new Promise((
|
|
18594
|
+
return await new Promise((resolve13, reject) => {
|
|
20043
18595
|
let settled = false;
|
|
20044
18596
|
const cleanup = () => {
|
|
20045
18597
|
input.off("data", onData);
|
|
@@ -20054,7 +18606,7 @@ async function readHiddenLine(prompt) {
|
|
|
20054
18606
|
settled = true;
|
|
20055
18607
|
output.write("\n");
|
|
20056
18608
|
cleanup();
|
|
20057
|
-
|
|
18609
|
+
resolve13(line);
|
|
20058
18610
|
};
|
|
20059
18611
|
const fail = (error) => {
|
|
20060
18612
|
if (settled) return;
|
|
@@ -20225,9 +18777,9 @@ Examples:
|
|
|
20225
18777
|
}
|
|
20226
18778
|
|
|
20227
18779
|
// src/cli/commands/switch.ts
|
|
20228
|
-
import { existsSync as
|
|
18780
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync10 } from "fs";
|
|
20229
18781
|
import { homedir as homedir8 } from "os";
|
|
20230
|
-
import { dirname as
|
|
18782
|
+
import { dirname as dirname8, join as join8 } from "path";
|
|
20231
18783
|
function hostSlugFromBaseUrl(baseUrl) {
|
|
20232
18784
|
try {
|
|
20233
18785
|
const url = new URL(baseUrl);
|
|
@@ -20248,7 +18800,7 @@ function resolveConfigScope() {
|
|
|
20248
18800
|
}
|
|
20249
18801
|
function activeFamilyPath() {
|
|
20250
18802
|
const home = process.env.HOME || process.env.USERPROFILE || homedir8();
|
|
20251
|
-
return
|
|
18803
|
+
return join8(
|
|
20252
18804
|
home,
|
|
20253
18805
|
".local",
|
|
20254
18806
|
"deepline",
|
|
@@ -20260,14 +18812,14 @@ function activeFamilyPath() {
|
|
|
20260
18812
|
function readActiveFamily() {
|
|
20261
18813
|
const path = activeFamilyPath();
|
|
20262
18814
|
try {
|
|
20263
|
-
return
|
|
18815
|
+
return readFileSync8(path, "utf-8").trim() || "sdk";
|
|
20264
18816
|
} catch {
|
|
20265
18817
|
return "sdk";
|
|
20266
18818
|
}
|
|
20267
18819
|
}
|
|
20268
18820
|
function writeActiveFamily(family) {
|
|
20269
18821
|
const path = activeFamilyPath();
|
|
20270
|
-
mkdirSync6(
|
|
18822
|
+
mkdirSync6(dirname8(path), { recursive: true });
|
|
20271
18823
|
writeFileSync10(path, `${family}
|
|
20272
18824
|
`, "utf-8");
|
|
20273
18825
|
return path;
|
|
@@ -20285,7 +18837,7 @@ function handleSwitch(action, options) {
|
|
|
20285
18837
|
ok: true,
|
|
20286
18838
|
active_family: activeFamily,
|
|
20287
18839
|
active_family_path: path,
|
|
20288
|
-
active_family_file_exists:
|
|
18840
|
+
active_family_file_exists: existsSync8(path),
|
|
20289
18841
|
render: {
|
|
20290
18842
|
sections: [
|
|
20291
18843
|
{
|
|
@@ -20387,18 +18939,18 @@ Examples:
|
|
|
20387
18939
|
import { Option } from "commander";
|
|
20388
18940
|
import {
|
|
20389
18941
|
chmodSync,
|
|
20390
|
-
existsSync as
|
|
18942
|
+
existsSync as existsSync9,
|
|
20391
18943
|
mkdtempSync,
|
|
20392
|
-
readFileSync as
|
|
18944
|
+
readFileSync as readFileSync9,
|
|
20393
18945
|
writeFileSync as writeFileSync12
|
|
20394
18946
|
} from "fs";
|
|
20395
|
-
import { tmpdir as
|
|
20396
|
-
import { join as
|
|
18947
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
18948
|
+
import { join as join10, resolve as resolve10 } from "path";
|
|
20397
18949
|
|
|
20398
18950
|
// src/tool-output.ts
|
|
20399
18951
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync11 } from "fs";
|
|
20400
18952
|
import { homedir as homedir9 } from "os";
|
|
20401
|
-
import { join as
|
|
18953
|
+
import { join as join9 } from "path";
|
|
20402
18954
|
function isPlainObject(value) {
|
|
20403
18955
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
20404
18956
|
}
|
|
@@ -20494,19 +19046,19 @@ function tryConvertToList(payload, options) {
|
|
|
20494
19046
|
return null;
|
|
20495
19047
|
}
|
|
20496
19048
|
function ensureOutputDir() {
|
|
20497
|
-
const outputDir =
|
|
19049
|
+
const outputDir = join9(homedir9(), ".local", "share", "deepline", "data");
|
|
20498
19050
|
mkdirSync7(outputDir, { recursive: true });
|
|
20499
19051
|
return outputDir;
|
|
20500
19052
|
}
|
|
20501
19053
|
function writeJsonOutputFile(payload, stem) {
|
|
20502
19054
|
const outputDir = ensureOutputDir();
|
|
20503
|
-
const outputPath =
|
|
19055
|
+
const outputPath = join9(outputDir, `${stem}_${Date.now()}.json`);
|
|
20504
19056
|
writeFileSync11(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
20505
19057
|
return outputPath;
|
|
20506
19058
|
}
|
|
20507
19059
|
function writeCsvOutputFile(rows, stem) {
|
|
20508
19060
|
const outputDir = ensureOutputDir();
|
|
20509
|
-
const outputPath =
|
|
19061
|
+
const outputPath = join9(outputDir, `${stem}_${Date.now()}.csv`);
|
|
20510
19062
|
const seen = /* @__PURE__ */ new Set();
|
|
20511
19063
|
const columns = [];
|
|
20512
19064
|
for (const row of rows) {
|
|
@@ -21583,11 +20135,11 @@ function normalizeOutputFormat(raw) {
|
|
|
21583
20135
|
}
|
|
21584
20136
|
function resolveAtFilePath(rawPath) {
|
|
21585
20137
|
const trimmed = rawPath.trim();
|
|
21586
|
-
const resolved =
|
|
21587
|
-
if (
|
|
20138
|
+
const resolved = resolve10(trimmed);
|
|
20139
|
+
if (existsSync9(resolved)) return resolved;
|
|
21588
20140
|
if (process.platform !== "win32" && trimmed.includes("\\")) {
|
|
21589
|
-
const normalized =
|
|
21590
|
-
if (
|
|
20141
|
+
const normalized = resolve10(trimmed.replace(/\\/g, "/"));
|
|
20142
|
+
if (existsSync9(normalized)) return normalized;
|
|
21591
20143
|
}
|
|
21592
20144
|
return resolved;
|
|
21593
20145
|
}
|
|
@@ -21598,7 +20150,7 @@ function readJsonArgument(raw, flagName) {
|
|
|
21598
20150
|
throw new Error(`Invalid ${flagName} value: empty @file path.`);
|
|
21599
20151
|
}
|
|
21600
20152
|
try {
|
|
21601
|
-
return
|
|
20153
|
+
return readFileSync9(resolveAtFilePath(filePath), "utf8").replace(
|
|
21602
20154
|
/^\uFEFF/,
|
|
21603
20155
|
""
|
|
21604
20156
|
);
|
|
@@ -21700,9 +20252,9 @@ function starterScriptJson(script) {
|
|
|
21700
20252
|
function seedToolListScript(input2) {
|
|
21701
20253
|
const stem = safeFileStem(input2.toolId);
|
|
21702
20254
|
const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
|
|
21703
|
-
const scriptDir = mkdtempSync(
|
|
20255
|
+
const scriptDir = mkdtempSync(join10(tmpdir2(), "deepline-workflow-seed-"));
|
|
21704
20256
|
chmodSync(scriptDir, 448);
|
|
21705
|
-
const scriptPath =
|
|
20257
|
+
const scriptPath = join10(scriptDir, fileName);
|
|
21706
20258
|
const projectDir = `deepline/projects/${stem}-workflow`;
|
|
21707
20259
|
const playName = `${stem}-workflow`;
|
|
21708
20260
|
const sampleRows = input2.rows.length > 0 ? `${JSON.stringify(input2.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
|
|
@@ -22002,11 +20554,48 @@ async function executeTool(args) {
|
|
|
22002
20554
|
}
|
|
22003
20555
|
|
|
22004
20556
|
// src/cli/commands/workflow.ts
|
|
22005
|
-
import { mkdir as
|
|
22006
|
-
import { dirname as
|
|
20557
|
+
import { mkdir as mkdir4, readFile as readFile2, writeFile as writeFile4 } from "fs/promises";
|
|
20558
|
+
import { dirname as dirname9, join as join11, resolve as resolve11 } from "path";
|
|
20559
|
+
|
|
20560
|
+
// src/cli/workflow-to-play.ts
|
|
20561
|
+
import { createHash as createHash2 } from "crypto";
|
|
20562
|
+
|
|
20563
|
+
// ../shared_libs/plays/secret-guardrails.ts
|
|
20564
|
+
var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
|
|
20565
|
+
var PRIVATE_KEY_PATTERN = /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/;
|
|
20566
|
+
var BEARER_LITERAL_PATTERN = /\bBearer\s+[A-Za-z0-9._~+/=-]{16,}/i;
|
|
20567
|
+
var ASSIGNMENT_SECRET_LITERAL_PATTERN = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*['"][^'"]{12,}['"]/i;
|
|
20568
|
+
var HIGH_ENTROPY_LITERAL_PATTERN = /['"]([A-Za-z0-9+/=_-]{32,})['"]/g;
|
|
20569
|
+
function shannonEntropy(value) {
|
|
20570
|
+
const counts = /* @__PURE__ */ new Map();
|
|
20571
|
+
for (const char of value) counts.set(char, (counts.get(char) ?? 0) + 1);
|
|
20572
|
+
return [...counts.values()].reduce((entropy, count) => {
|
|
20573
|
+
const p = count / value.length;
|
|
20574
|
+
return entropy - p * Math.log2(p);
|
|
20575
|
+
}, 0);
|
|
20576
|
+
}
|
|
20577
|
+
function collectInlineSecretFindings(sourceCode) {
|
|
20578
|
+
const findings = [];
|
|
20579
|
+
for (const match of sourceCode.matchAll(SECRET_ENV_PATTERN)) {
|
|
20580
|
+
findings.push(`process.env.${match[1]}`);
|
|
20581
|
+
}
|
|
20582
|
+
if (PRIVATE_KEY_PATTERN.test(sourceCode)) findings.push("private key block");
|
|
20583
|
+
if (BEARER_LITERAL_PATTERN.test(sourceCode))
|
|
20584
|
+
findings.push("bearer token literal");
|
|
20585
|
+
if (ASSIGNMENT_SECRET_LITERAL_PATTERN.test(sourceCode)) {
|
|
20586
|
+
findings.push("secret-looking assignment literal");
|
|
20587
|
+
}
|
|
20588
|
+
for (const match of sourceCode.matchAll(HIGH_ENTROPY_LITERAL_PATTERN)) {
|
|
20589
|
+
const literal = match[1] ?? "";
|
|
20590
|
+
if (literal.length >= 40 && shannonEntropy(literal) >= 4.2) {
|
|
20591
|
+
findings.push("high-entropy string literal");
|
|
20592
|
+
break;
|
|
20593
|
+
}
|
|
20594
|
+
}
|
|
20595
|
+
return [...new Set(findings)];
|
|
20596
|
+
}
|
|
22007
20597
|
|
|
22008
20598
|
// src/cli/workflow-to-play.ts
|
|
22009
|
-
import { createHash as createHash4 } from "crypto";
|
|
22010
20599
|
var HITL_WAIT_FOR_SIGNAL_TOOL = "deepline_workflow_wait_for_signal";
|
|
22011
20600
|
var HITL_SLACK_TOOL = "slack_message_with_hitl";
|
|
22012
20601
|
var SUB_WORKFLOW_TOOL_PREFIX = "deepline_workflow_";
|
|
@@ -22112,7 +20701,7 @@ function sanitizePlayNameSegment(value) {
|
|
|
22112
20701
|
}
|
|
22113
20702
|
function deriveWorkflowPlayName(workflowName) {
|
|
22114
20703
|
const base = sanitizePlayNameSegment(workflowName) || "workflow";
|
|
22115
|
-
const suffix =
|
|
20704
|
+
const suffix = createHash2("sha256").update(workflowName).digest("hex").slice(0, 8);
|
|
22116
20705
|
const reserved = suffix.length + 1;
|
|
22117
20706
|
const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
|
|
22118
20707
|
let name = `${base.slice(0, allowedBase)}_${suffix}`;
|
|
@@ -22210,7 +20799,7 @@ function readStatus(payload) {
|
|
|
22210
20799
|
}
|
|
22211
20800
|
async function readJsonOption(payload, file) {
|
|
22212
20801
|
if (file) {
|
|
22213
|
-
const raw = await
|
|
20802
|
+
const raw = await readFile2(resolve11(file), "utf8");
|
|
22214
20803
|
return JSON.parse(raw);
|
|
22215
20804
|
}
|
|
22216
20805
|
if (payload) {
|
|
@@ -22244,9 +20833,9 @@ async function transformOne(api, workflowId, outDir, publish) {
|
|
|
22244
20833
|
revision.config,
|
|
22245
20834
|
{ workflowName: workflow.name, version: revision.version }
|
|
22246
20835
|
);
|
|
22247
|
-
const file =
|
|
22248
|
-
await
|
|
22249
|
-
await
|
|
20836
|
+
const file = join11(resolve11(outDir), `${compiled.playName}.play.ts`);
|
|
20837
|
+
await mkdir4(dirname9(file), { recursive: true });
|
|
20838
|
+
await writeFile4(file, compiled.sourceCode, "utf8");
|
|
22250
20839
|
let published = false;
|
|
22251
20840
|
if (publish) {
|
|
22252
20841
|
const code = await handlePlayPublish([file]);
|
|
@@ -22493,15 +21082,15 @@ Notes:
|
|
|
22493
21082
|
// src/cli/commands/update.ts
|
|
22494
21083
|
import { spawn as spawn2 } from "child_process";
|
|
22495
21084
|
import {
|
|
22496
|
-
existsSync as
|
|
21085
|
+
existsSync as existsSync10,
|
|
22497
21086
|
mkdirSync as mkdirSync8,
|
|
22498
|
-
readFileSync as
|
|
21087
|
+
readFileSync as readFileSync10,
|
|
22499
21088
|
renameSync,
|
|
22500
21089
|
rmSync as rmSync3,
|
|
22501
21090
|
writeFileSync as writeFileSync13
|
|
22502
21091
|
} from "fs";
|
|
22503
21092
|
import { homedir as homedir10 } from "os";
|
|
22504
|
-
import { dirname as
|
|
21093
|
+
import { dirname as dirname10, isAbsolute as isAbsolute2, join as join12, relative as relative2, resolve as resolve12 } from "path";
|
|
22505
21094
|
function posixShellQuote(value) {
|
|
22506
21095
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
22507
21096
|
}
|
|
@@ -22524,11 +21113,11 @@ function sidecarStateDir(input2) {
|
|
|
22524
21113
|
if (!scope || scope.includes("/") || scope.includes("\\")) {
|
|
22525
21114
|
return null;
|
|
22526
21115
|
}
|
|
22527
|
-
return
|
|
21116
|
+
return join12(input2.homeDir, ".local", "deepline", scope, "sdk-cli");
|
|
22528
21117
|
}
|
|
22529
21118
|
function readOptionalText(path) {
|
|
22530
21119
|
try {
|
|
22531
|
-
return
|
|
21120
|
+
return readFileSync10(path, "utf8").trim();
|
|
22532
21121
|
} catch {
|
|
22533
21122
|
return "";
|
|
22534
21123
|
}
|
|
@@ -22536,26 +21125,26 @@ function readOptionalText(path) {
|
|
|
22536
21125
|
function resolvePythonSidecarUpdatePlan(options) {
|
|
22537
21126
|
const stateDir = sidecarStateDir(options);
|
|
22538
21127
|
if (!stateDir) return null;
|
|
22539
|
-
const relativeEntrypoint =
|
|
22540
|
-
|
|
22541
|
-
|
|
21128
|
+
const relativeEntrypoint = relative2(
|
|
21129
|
+
resolve12(stateDir),
|
|
21130
|
+
resolve12(options.entrypoint)
|
|
22542
21131
|
);
|
|
22543
|
-
if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") ||
|
|
21132
|
+
if (!relativeEntrypoint || relativeEntrypoint.startsWith("..") || isAbsolute2(relativeEntrypoint)) {
|
|
22544
21133
|
return null;
|
|
22545
21134
|
}
|
|
22546
|
-
const installMethod = readOptionalText(
|
|
21135
|
+
const installMethod = readOptionalText(join12(stateDir, ".install-method"));
|
|
22547
21136
|
if (installMethod !== "python-sidecar") return null;
|
|
22548
21137
|
const scope = options.env.DEEPLINE_CONFIG_SCOPE?.trim() || "";
|
|
22549
21138
|
const hostUrl = options.env.DEEPLINE_HOST_URL?.trim() || "";
|
|
22550
|
-
const nodeBin = readOptionalText(
|
|
22551
|
-
const sidecarPath = readOptionalText(
|
|
21139
|
+
const nodeBin = readOptionalText(join12(stateDir, ".node-bin")) || process.execPath;
|
|
21140
|
+
const sidecarPath = readOptionalText(join12(stateDir, ".command-path")) || join12(
|
|
22552
21141
|
stateDir,
|
|
22553
21142
|
"bin",
|
|
22554
21143
|
process.platform === "win32" ? "deepline-sdk.cmd" : "deepline-sdk"
|
|
22555
21144
|
);
|
|
22556
21145
|
const packageSpec = options.packageSpec || "deepline@latest";
|
|
22557
21146
|
const npmCommand = "npm";
|
|
22558
|
-
const manualCommand = `${npmCommand} install --prefix ${shellQuote3(
|
|
21147
|
+
const manualCommand = `${npmCommand} install --prefix ${shellQuote3(join12(stateDir, "versions", "<version>"))} --no-audit --no-fund ${shellQuote3(packageSpec)}`;
|
|
22559
21148
|
return {
|
|
22560
21149
|
kind: "python-sidecar",
|
|
22561
21150
|
stateDir,
|
|
@@ -22569,12 +21158,12 @@ function resolvePythonSidecarUpdatePlan(options) {
|
|
|
22569
21158
|
};
|
|
22570
21159
|
}
|
|
22571
21160
|
function findRepoBackedSdkRoot(startPath) {
|
|
22572
|
-
let current =
|
|
21161
|
+
let current = resolve12(startPath);
|
|
22573
21162
|
while (true) {
|
|
22574
|
-
if (
|
|
21163
|
+
if (existsSync10(join12(current, "sdk", "package.json")) && existsSync10(join12(current, "sdk", "bin", "deepline-dev.ts"))) {
|
|
22575
21164
|
return current;
|
|
22576
21165
|
}
|
|
22577
|
-
const parent =
|
|
21166
|
+
const parent = dirname10(current);
|
|
22578
21167
|
if (parent === current) return null;
|
|
22579
21168
|
current = parent;
|
|
22580
21169
|
}
|
|
@@ -22582,8 +21171,8 @@ function findRepoBackedSdkRoot(startPath) {
|
|
|
22582
21171
|
function resolveUpdatePlan(options = {}) {
|
|
22583
21172
|
const env = options.env ?? process.env;
|
|
22584
21173
|
const homeDir2 = options.homeDir ?? homedir10();
|
|
22585
|
-
const entrypoint = options.entrypoint ?? (process.argv[1] ?
|
|
22586
|
-
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(
|
|
21174
|
+
const entrypoint = options.entrypoint ?? (process.argv[1] ? resolve12(process.argv[1]) : "");
|
|
21175
|
+
const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname10(entrypoint)) : null;
|
|
22587
21176
|
if (sourceRoot) {
|
|
22588
21177
|
return {
|
|
22589
21178
|
kind: "source",
|
|
@@ -22613,7 +21202,7 @@ function safeVersionSegment(value) {
|
|
|
22613
21202
|
return /^[0-9A-Za-z._-]+$/.test(normalized) ? normalized : "";
|
|
22614
21203
|
}
|
|
22615
21204
|
function entryPathInVersionDir(versionDir) {
|
|
22616
|
-
return
|
|
21205
|
+
return join12(
|
|
22617
21206
|
versionDir,
|
|
22618
21207
|
"node_modules",
|
|
22619
21208
|
"deepline",
|
|
@@ -22623,14 +21212,14 @@ function entryPathInVersionDir(versionDir) {
|
|
|
22623
21212
|
);
|
|
22624
21213
|
}
|
|
22625
21214
|
function installedPackageVersion(versionDir) {
|
|
22626
|
-
const packageJsonPath =
|
|
21215
|
+
const packageJsonPath = join12(
|
|
22627
21216
|
versionDir,
|
|
22628
21217
|
"node_modules",
|
|
22629
21218
|
"deepline",
|
|
22630
21219
|
"package.json"
|
|
22631
21220
|
);
|
|
22632
21221
|
try {
|
|
22633
|
-
const parsed = JSON.parse(
|
|
21222
|
+
const parsed = JSON.parse(readFileSync10(packageJsonPath, "utf8"));
|
|
22634
21223
|
return typeof parsed.version === "string" ? safeVersionSegment(parsed.version) : "";
|
|
22635
21224
|
} catch {
|
|
22636
21225
|
return "";
|
|
@@ -22654,7 +21243,7 @@ function runCommand(command, args, env = process.env) {
|
|
|
22654
21243
|
});
|
|
22655
21244
|
}
|
|
22656
21245
|
function writeSidecarLauncher(input2) {
|
|
22657
|
-
mkdirSync8(
|
|
21246
|
+
mkdirSync8(dirname10(input2.path), { recursive: true });
|
|
22658
21247
|
if (process.platform === "win32") {
|
|
22659
21248
|
writeFileSync13(
|
|
22660
21249
|
input2.path,
|
|
@@ -22681,17 +21270,17 @@ function writeSidecarLauncher(input2) {
|
|
|
22681
21270
|
);
|
|
22682
21271
|
}
|
|
22683
21272
|
async function runPythonSidecarUpdatePlan(plan) {
|
|
22684
|
-
const versionsDir =
|
|
22685
|
-
const tempDir =
|
|
21273
|
+
const versionsDir = join12(plan.stateDir, "versions");
|
|
21274
|
+
const tempDir = join12(
|
|
22686
21275
|
versionsDir,
|
|
22687
21276
|
`.tmp-sdk-update-${process.pid}-${Date.now()}`
|
|
22688
21277
|
);
|
|
22689
21278
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
22690
21279
|
mkdirSync8(tempDir, { recursive: true });
|
|
22691
|
-
writeFileSync13(
|
|
21280
|
+
writeFileSync13(join12(tempDir, "package.json"), '{"private":true}\n', "utf8");
|
|
22692
21281
|
const env = {
|
|
22693
21282
|
...process.env,
|
|
22694
|
-
PATH: `${
|
|
21283
|
+
PATH: `${dirname10(plan.nodeBin)}${process.platform === "win32" ? ";" : ":"}${process.env.PATH ?? ""}`
|
|
22695
21284
|
};
|
|
22696
21285
|
const installExitCode = await runCommand(
|
|
22697
21286
|
plan.npmCommand,
|
|
@@ -22717,9 +21306,9 @@ async function runPythonSidecarUpdatePlan(plan) {
|
|
|
22717
21306
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
22718
21307
|
return 1;
|
|
22719
21308
|
}
|
|
22720
|
-
const finalDir =
|
|
21309
|
+
const finalDir = join12(versionsDir, installedVersion);
|
|
22721
21310
|
const finalEntryPath = entryPathInVersionDir(finalDir);
|
|
22722
|
-
if (
|
|
21311
|
+
if (existsSync10(finalEntryPath)) {
|
|
22723
21312
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
22724
21313
|
} else {
|
|
22725
21314
|
rmSync3(finalDir, { recursive: true, force: true });
|
|
@@ -22734,7 +21323,7 @@ async function runPythonSidecarUpdatePlan(plan) {
|
|
|
22734
21323
|
return 1;
|
|
22735
21324
|
}
|
|
22736
21325
|
}
|
|
22737
|
-
if (!
|
|
21326
|
+
if (!existsSync10(finalEntryPath)) {
|
|
22738
21327
|
process.stderr.write(
|
|
22739
21328
|
`Updated Deepline SDK CLI entrypoint missing: ${finalEntryPath}
|
|
22740
21329
|
`
|
|
@@ -22749,27 +21338,27 @@ async function runPythonSidecarUpdatePlan(plan) {
|
|
|
22749
21338
|
entryPath: finalEntryPath
|
|
22750
21339
|
});
|
|
22751
21340
|
writeFileSync13(
|
|
22752
|
-
|
|
21341
|
+
join12(plan.stateDir, ".version"),
|
|
22753
21342
|
`${installedVersion}
|
|
22754
21343
|
`,
|
|
22755
21344
|
"utf8"
|
|
22756
21345
|
);
|
|
22757
21346
|
writeFileSync13(
|
|
22758
|
-
|
|
21347
|
+
join12(plan.stateDir, ".install-method"),
|
|
22759
21348
|
"python-sidecar\n",
|
|
22760
21349
|
"utf8"
|
|
22761
21350
|
);
|
|
22762
21351
|
writeFileSync13(
|
|
22763
|
-
|
|
21352
|
+
join12(plan.stateDir, ".command-path"),
|
|
22764
21353
|
`${plan.sidecarPath}
|
|
22765
21354
|
`,
|
|
22766
21355
|
"utf8"
|
|
22767
21356
|
);
|
|
22768
|
-
writeFileSync13(
|
|
22769
|
-
writeFileSync13(
|
|
21357
|
+
writeFileSync13(join12(plan.stateDir, ".runner"), "node\n", "utf8");
|
|
21358
|
+
writeFileSync13(join12(plan.stateDir, ".node-bin"), `${plan.nodeBin}
|
|
22770
21359
|
`, "utf8");
|
|
22771
21360
|
writeFileSync13(
|
|
22772
|
-
|
|
21361
|
+
join12(plan.stateDir, ".entry-path"),
|
|
22773
21362
|
`${finalEntryPath}
|
|
22774
21363
|
`,
|
|
22775
21364
|
"utf8"
|
|
@@ -23056,7 +21645,7 @@ function shouldSkipSelfUpdate() {
|
|
|
23056
21645
|
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || isCi();
|
|
23057
21646
|
}
|
|
23058
21647
|
function relaunchCurrentCommand(plan) {
|
|
23059
|
-
return new Promise((
|
|
21648
|
+
return new Promise((resolve13) => {
|
|
23060
21649
|
const command = plan.kind === "python-sidecar" ? plan.sidecarPath : process.execPath;
|
|
23061
21650
|
const args = plan.kind === "python-sidecar" ? process.argv.slice(2) : process.argv.slice(1);
|
|
23062
21651
|
const child = spawn3(command, args, {
|
|
@@ -23072,9 +21661,9 @@ function relaunchCurrentCommand(plan) {
|
|
|
23072
21661
|
`Deepline SDK/CLI updated, but relaunch failed: ${error.message}
|
|
23073
21662
|
`
|
|
23074
21663
|
);
|
|
23075
|
-
|
|
21664
|
+
resolve13(1);
|
|
23076
21665
|
});
|
|
23077
|
-
child.on("close", (code) =>
|
|
21666
|
+
child.on("close", (code) => resolve13(code ?? 1));
|
|
23078
21667
|
});
|
|
23079
21668
|
}
|
|
23080
21669
|
async function maybeAutoUpdateAndRelaunch(response) {
|
|
@@ -23113,9 +21702,9 @@ async function maybeAutoUpdateAndRelaunch(response) {
|
|
|
23113
21702
|
|
|
23114
21703
|
// src/cli/skills-sync.ts
|
|
23115
21704
|
import { spawn as spawn4, spawnSync as spawnSync2 } from "child_process";
|
|
23116
|
-
import { existsSync as
|
|
21705
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync14 } from "fs";
|
|
23117
21706
|
import { homedir as homedir11 } from "os";
|
|
23118
|
-
import { dirname as
|
|
21707
|
+
import { dirname as dirname11, join as join13 } from "path";
|
|
23119
21708
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
23120
21709
|
var SDK_PLAY_SKILL_NAME = "deepline-plays";
|
|
23121
21710
|
var attemptedSync = false;
|
|
@@ -23129,20 +21718,20 @@ function activePluginSkillsDir() {
|
|
|
23129
21718
|
return "";
|
|
23130
21719
|
}
|
|
23131
21720
|
const dir = process.env.DEEPLINE_PLUGIN_SKILLS_DIR?.trim() ?? "";
|
|
23132
|
-
return dir &&
|
|
21721
|
+
return dir && existsSync11(dir) ? dir : "";
|
|
23133
21722
|
}
|
|
23134
21723
|
function readPluginSkillsVersion() {
|
|
23135
21724
|
const dir = activePluginSkillsDir();
|
|
23136
21725
|
if (!dir) return "";
|
|
23137
21726
|
try {
|
|
23138
|
-
return
|
|
21727
|
+
return readFileSync11(join13(dir, ".version"), "utf-8").trim();
|
|
23139
21728
|
} catch {
|
|
23140
21729
|
return "";
|
|
23141
21730
|
}
|
|
23142
21731
|
}
|
|
23143
21732
|
function sdkSkillsVersionPath(baseUrl) {
|
|
23144
21733
|
const home = process.env.HOME?.trim() || homedir11();
|
|
23145
|
-
return
|
|
21734
|
+
return join13(
|
|
23146
21735
|
home,
|
|
23147
21736
|
".local",
|
|
23148
21737
|
"deepline",
|
|
@@ -23155,16 +21744,16 @@ function readLocalSkillsVersion(baseUrl) {
|
|
|
23155
21744
|
const pluginVersion = readPluginSkillsVersion();
|
|
23156
21745
|
if (pluginVersion) return pluginVersion;
|
|
23157
21746
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
23158
|
-
if (!
|
|
21747
|
+
if (!existsSync11(path)) return "";
|
|
23159
21748
|
try {
|
|
23160
|
-
return
|
|
21749
|
+
return readFileSync11(path, "utf-8").trim();
|
|
23161
21750
|
} catch {
|
|
23162
21751
|
return "";
|
|
23163
21752
|
}
|
|
23164
21753
|
}
|
|
23165
21754
|
function writeLocalSkillsVersion(baseUrl, version) {
|
|
23166
21755
|
const path = sdkSkillsVersionPath(baseUrl);
|
|
23167
|
-
mkdirSync9(
|
|
21756
|
+
mkdirSync9(dirname11(path), { recursive: true });
|
|
23168
21757
|
writeFileSync14(path, `${version}
|
|
23169
21758
|
`, "utf-8");
|
|
23170
21759
|
}
|
|
@@ -23263,7 +21852,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
|
|
|
23263
21852
|
return [npxInstall];
|
|
23264
21853
|
}
|
|
23265
21854
|
function runOneSkillsInstall(install) {
|
|
23266
|
-
return new Promise((
|
|
21855
|
+
return new Promise((resolve13) => {
|
|
23267
21856
|
const child = spawn4(install.command, install.args, {
|
|
23268
21857
|
stdio: ["ignore", "ignore", "pipe"],
|
|
23269
21858
|
env: process.env
|
|
@@ -23273,7 +21862,7 @@ function runOneSkillsInstall(install) {
|
|
|
23273
21862
|
stderr += chunk.toString("utf-8");
|
|
23274
21863
|
});
|
|
23275
21864
|
child.on("error", (error) => {
|
|
23276
|
-
|
|
21865
|
+
resolve13({
|
|
23277
21866
|
ok: false,
|
|
23278
21867
|
detail: `failed to start ${install.command}: ${error.message}`,
|
|
23279
21868
|
manualCommand: install.manualCommand
|
|
@@ -23281,11 +21870,11 @@ function runOneSkillsInstall(install) {
|
|
|
23281
21870
|
});
|
|
23282
21871
|
child.on("close", (code) => {
|
|
23283
21872
|
if (code === 0) {
|
|
23284
|
-
|
|
21873
|
+
resolve13({ ok: true, detail: "", manualCommand: install.manualCommand });
|
|
23285
21874
|
return;
|
|
23286
21875
|
}
|
|
23287
21876
|
const detail = stderr.trim();
|
|
23288
|
-
|
|
21877
|
+
resolve13({
|
|
23289
21878
|
ok: false,
|
|
23290
21879
|
detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
|
|
23291
21880
|
manualCommand: install.manualCommand
|
|
@@ -23631,10 +22220,10 @@ function topLevelCommandKnown(program, commandName) {
|
|
|
23631
22220
|
);
|
|
23632
22221
|
}
|
|
23633
22222
|
async function runPlayRunnerHealthCheck() {
|
|
23634
|
-
const dir = await mkdtemp2(
|
|
23635
|
-
const file =
|
|
22223
|
+
const dir = await mkdtemp2(join14(tmpdir3(), "deepline-health-play-"));
|
|
22224
|
+
const file = join14(dir, "health-check.play.ts");
|
|
23636
22225
|
try {
|
|
23637
|
-
await
|
|
22226
|
+
await writeFile5(
|
|
23638
22227
|
file,
|
|
23639
22228
|
[
|
|
23640
22229
|
"import { definePlay } from 'deepline';",
|