deepline 0.1.193 → 0.1.195
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/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +38 -351
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +92 -3
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry.ts +27 -7
- package/dist/bundling-sources/sdk/src/client.ts +61 -1
- package/dist/bundling-sources/sdk/src/index.ts +2 -0
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +11 -0
- package/dist/cli/index.js +309 -35
- package/dist/cli/index.mjs +303 -29
- package/dist/index.d.mts +39 -1
- package/dist/index.d.ts +39 -1
- package/dist/index.js +25 -2
- package/dist/index.mjs +25 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -623,10 +623,10 @@ var SDK_RELEASE = {
|
|
|
623
623
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
624
624
|
// fields shipped in 0.1.153.
|
|
625
625
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
626
|
-
version: "0.1.
|
|
626
|
+
version: "0.1.195",
|
|
627
627
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
628
628
|
supportPolicy: {
|
|
629
|
-
latest: "0.1.
|
|
629
|
+
latest: "0.1.195",
|
|
630
630
|
minimumSupported: "0.1.53",
|
|
631
631
|
deprecatedBelow: "0.1.53",
|
|
632
632
|
commandMinimumSupported: [
|
|
@@ -1017,8 +1017,8 @@ var HttpClient = class {
|
|
|
1017
1017
|
}
|
|
1018
1018
|
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
1019
1019
|
const msg = typeof errorValue === "string" ? errorValue : errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string" ? errorValue.message : typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `HTTP ${response.status}`;
|
|
1020
|
-
const
|
|
1021
|
-
lastError = new DeeplineError(msg, response.status,
|
|
1020
|
+
const apiErrorCode2 = errorValue && typeof errorValue === "object" && typeof errorValue.code === "string" ? errorValue.code : typeof parsed === "object" && parsed && typeof parsed.code === "string" ? parsed.code : "API_ERROR";
|
|
1021
|
+
lastError = new DeeplineError(msg, response.status, apiErrorCode2, {
|
|
1022
1022
|
response: parsed
|
|
1023
1023
|
});
|
|
1024
1024
|
if (retryableApiError && attempt < maxRetries) {
|
|
@@ -2554,6 +2554,7 @@ var DeeplineClient = class {
|
|
|
2554
2554
|
stopAll: (options2) => this.stopAllRuns(options2)
|
|
2555
2555
|
};
|
|
2556
2556
|
this.billing = {
|
|
2557
|
+
topUp: (options2) => this.topUpBillingBalance(options2),
|
|
2557
2558
|
plans: () => this.getBillingPlans(),
|
|
2558
2559
|
subscription: {
|
|
2559
2560
|
status: () => this.getBillingSubscriptionStatus(),
|
|
@@ -4235,6 +4236,28 @@ var DeeplineClient = class {
|
|
|
4235
4236
|
async getBillingPlans() {
|
|
4236
4237
|
return this.http.get("/api/v2/billing/catalog/current");
|
|
4237
4238
|
}
|
|
4239
|
+
/**
|
|
4240
|
+
* Charge the saved payment method and add Deepline credits to the active
|
|
4241
|
+
* workspace. Prefer `client.billing.topUp(...)`.
|
|
4242
|
+
*
|
|
4243
|
+
* @throws {@link DeeplineError} with `statusCode: 409` when checkout is
|
|
4244
|
+
* required because the workspace has no saved payment method or the card
|
|
4245
|
+
* requires confirmation.
|
|
4246
|
+
*/
|
|
4247
|
+
async topUpBillingBalance(options) {
|
|
4248
|
+
return this.http.post(
|
|
4249
|
+
"/api/v2/billing/top-up",
|
|
4250
|
+
{
|
|
4251
|
+
credits: options.credits,
|
|
4252
|
+
...options.idempotencyKey ? { idempotency_key: options.idempotencyKey } : {}
|
|
4253
|
+
},
|
|
4254
|
+
void 0,
|
|
4255
|
+
// The idempotency key makes a retry at the product layer safe, but the
|
|
4256
|
+
// CLI should not hide ambiguous local delivery failures behind implicit
|
|
4257
|
+
// transport retries for a payment mutation.
|
|
4258
|
+
{ maxRetries: 0, exactUrlOnly: true }
|
|
4259
|
+
);
|
|
4260
|
+
}
|
|
4238
4261
|
/**
|
|
4239
4262
|
* Subscription state for the active workspace: active plan, whether a
|
|
4240
4263
|
* Stripe subscription backs it, renewal/cancellation facts, and remaining
|
|
@@ -5726,11 +5749,14 @@ Examples:
|
|
|
5726
5749
|
|
|
5727
5750
|
// src/cli/commands/billing.ts
|
|
5728
5751
|
var import_commander = require("commander");
|
|
5752
|
+
var import_node_crypto2 = require("crypto");
|
|
5729
5753
|
var import_promises2 = require("fs/promises");
|
|
5730
5754
|
var import_node_path6 = require("path");
|
|
5731
5755
|
var import_sync3 = require("csv-stringify/sync");
|
|
5732
5756
|
var SUBSCRIPTION_STATUS_NEXT_COMMAND = "deepline billing subscription status --json";
|
|
5733
5757
|
var SUBSCRIPTION_CANCEL_PATH = "/api/v2/billing/subscription/cancel";
|
|
5758
|
+
var BILLING_TOP_UP_PATH = "/api/v2/billing/top-up";
|
|
5759
|
+
var DEFAULT_BALANCE_RECOVERY_CREDITS = 100;
|
|
5734
5760
|
function billingFailureFromError(error, options) {
|
|
5735
5761
|
if (error instanceof AuthError) {
|
|
5736
5762
|
return {
|
|
@@ -5779,6 +5805,107 @@ function reportBillingFailure(failure, options) {
|
|
|
5779
5805
|
);
|
|
5780
5806
|
process.exitCode = failure.exitCode;
|
|
5781
5807
|
}
|
|
5808
|
+
function parseTopUpCredits(raw) {
|
|
5809
|
+
const trimmed = String(raw ?? "").trim();
|
|
5810
|
+
if (!/^\d+$/.test(trimmed)) return null;
|
|
5811
|
+
const parsed = Number(trimmed);
|
|
5812
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) return null;
|
|
5813
|
+
return parsed;
|
|
5814
|
+
}
|
|
5815
|
+
function topUpIdempotencyKey(raw) {
|
|
5816
|
+
if (typeof raw === "string") {
|
|
5817
|
+
const trimmed = raw.trim();
|
|
5818
|
+
if (trimmed) return trimmed.slice(0, 120);
|
|
5819
|
+
}
|
|
5820
|
+
return `cli_topup:${Date.now()}:${(0, import_node_crypto2.randomUUID)()}`;
|
|
5821
|
+
}
|
|
5822
|
+
function checkoutCommandForCredits(credits) {
|
|
5823
|
+
return `deepline billing checkout --credits ${credits} --no-open --json`;
|
|
5824
|
+
}
|
|
5825
|
+
function approvedTopUpCommandForCredits(credits) {
|
|
5826
|
+
return `deepline billing top-up ${credits} --json`;
|
|
5827
|
+
}
|
|
5828
|
+
function balanceRecoveryForCredits(credits = DEFAULT_BALANCE_RECOVERY_CREDITS) {
|
|
5829
|
+
return {
|
|
5830
|
+
recommended_credits: credits,
|
|
5831
|
+
requires_user_approval: true,
|
|
5832
|
+
message: "Ask the user whether they want to add Deepline credits before taking payment-related action.",
|
|
5833
|
+
top_up_command: approvedTopUpCommandForCredits(credits),
|
|
5834
|
+
checkout_command: checkoutCommandForCredits(credits)
|
|
5835
|
+
};
|
|
5836
|
+
}
|
|
5837
|
+
function shellQuote(value) {
|
|
5838
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
5839
|
+
}
|
|
5840
|
+
function topUpRetryCommand(credits, idempotencyKey) {
|
|
5841
|
+
return `deepline billing top-up ${credits} --idempotency-key ${shellQuote(idempotencyKey)} --json`;
|
|
5842
|
+
}
|
|
5843
|
+
function apiErrorCode(error) {
|
|
5844
|
+
const response = error.details?.response;
|
|
5845
|
+
if (response && typeof response === "object" && !Array.isArray(response)) {
|
|
5846
|
+
const code = response.code;
|
|
5847
|
+
if (typeof code === "string" && code.trim()) {
|
|
5848
|
+
return code.trim();
|
|
5849
|
+
}
|
|
5850
|
+
}
|
|
5851
|
+
return error.code ?? "BILLING_API_ERROR";
|
|
5852
|
+
}
|
|
5853
|
+
function billingTopUpFailureFromError(error, input2) {
|
|
5854
|
+
if (error instanceof AuthError || error instanceof ConfigError) {
|
|
5855
|
+
return {
|
|
5856
|
+
exitCode: 3,
|
|
5857
|
+
code: "AUTH_ERROR",
|
|
5858
|
+
message: error.message,
|
|
5859
|
+
next: "deepline auth status --json"
|
|
5860
|
+
};
|
|
5861
|
+
}
|
|
5862
|
+
if (!(error instanceof DeeplineError) || typeof error.statusCode !== "number") {
|
|
5863
|
+
if (error instanceof DeeplineError) {
|
|
5864
|
+
return {
|
|
5865
|
+
exitCode: 5,
|
|
5866
|
+
code: "TOP_UP_STATUS_UNKNOWN",
|
|
5867
|
+
message: `${error.message} The top-up may have reached Deepline. Retry only with the same idempotency key to avoid a duplicate charge.`,
|
|
5868
|
+
next: topUpRetryCommand(input2.credits, input2.idempotencyKey)
|
|
5869
|
+
};
|
|
5870
|
+
}
|
|
5871
|
+
return null;
|
|
5872
|
+
}
|
|
5873
|
+
const code = apiErrorCode(error);
|
|
5874
|
+
if (error.statusCode === 400) {
|
|
5875
|
+
return {
|
|
5876
|
+
exitCode: 2,
|
|
5877
|
+
code: "INVALID_CREDITS",
|
|
5878
|
+
message: error.message,
|
|
5879
|
+
next: "deepline billing plans --json"
|
|
5880
|
+
};
|
|
5881
|
+
}
|
|
5882
|
+
if (error.statusCode === 409) {
|
|
5883
|
+
const checkoutNext = checkoutCommandForCredits(input2.credits);
|
|
5884
|
+
return {
|
|
5885
|
+
exitCode: 4,
|
|
5886
|
+
code: code === "requires_action" ? "PAYMENT_REQUIRES_ACTION" : "MISSING_PAYMENT_METHOD",
|
|
5887
|
+
message: error.message,
|
|
5888
|
+
next: checkoutNext
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
if (error.statusCode === 402) {
|
|
5892
|
+
return {
|
|
5893
|
+
exitCode: 5,
|
|
5894
|
+
code: "PAYMENT_FAILED",
|
|
5895
|
+
message: error.message,
|
|
5896
|
+
next: checkoutCommandForCredits(input2.credits)
|
|
5897
|
+
};
|
|
5898
|
+
}
|
|
5899
|
+
if (error.statusCode >= 500) {
|
|
5900
|
+
return {
|
|
5901
|
+
exitCode: 5,
|
|
5902
|
+
code: "BILLING_SERVER_ERROR",
|
|
5903
|
+
message: `${error.message} Retry only with the same idempotency key to avoid a duplicate charge.`,
|
|
5904
|
+
next: topUpRetryCommand(input2.credits, input2.idempotencyKey)
|
|
5905
|
+
};
|
|
5906
|
+
}
|
|
5907
|
+
return null;
|
|
5908
|
+
}
|
|
5782
5909
|
function humanize(value) {
|
|
5783
5910
|
return String(value || "").split("_").filter(Boolean).map((token) => token[0]?.toUpperCase() + token.slice(1)).join(" ") || "Unknown";
|
|
5784
5911
|
}
|
|
@@ -5876,13 +6003,29 @@ async function handleBalance(options) {
|
|
|
5876
6003
|
"/api/v2/billing/balance"
|
|
5877
6004
|
);
|
|
5878
6005
|
const status = String(payload.balance_status || "");
|
|
5879
|
-
const
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
6006
|
+
const needsCredits = status === "no_billing" || status === "zero_balance" || status === "payment_method_only";
|
|
6007
|
+
const recovery = needsCredits ? balanceRecoveryForCredits() : null;
|
|
6008
|
+
const lines = [`Balance: ${payload.balance ?? "(unknown)"} credits`];
|
|
6009
|
+
if (status === "no_billing") {
|
|
6010
|
+
lines.push(
|
|
6011
|
+
"Billing: No billing account or payment method set up for this workspace."
|
|
6012
|
+
);
|
|
6013
|
+
} else if (status === "zero_balance") {
|
|
6014
|
+
lines.push("Billing: This workspace has no Deepline credits available.");
|
|
6015
|
+
} else if (status === "payment_method_only") {
|
|
6016
|
+
lines.push(
|
|
6017
|
+
"Billing: A payment method is saved, but this workspace has no Deepline credits available."
|
|
6018
|
+
);
|
|
6019
|
+
}
|
|
6020
|
+
if (recovery) {
|
|
6021
|
+
lines.push(recovery.message);
|
|
6022
|
+
lines.push(`If the user approves, run: ${recovery.top_up_command}`);
|
|
6023
|
+
lines.push(`If checkout is required, run: ${recovery.checkout_command}`);
|
|
6024
|
+
}
|
|
5883
6025
|
printCommandEnvelope(
|
|
5884
6026
|
{
|
|
5885
6027
|
...payload,
|
|
6028
|
+
...recovery ? { recovery } : {},
|
|
5886
6029
|
render: { sections: [{ title: "billing balance", lines }] }
|
|
5887
6030
|
},
|
|
5888
6031
|
{ json: options.json }
|
|
@@ -6376,6 +6519,99 @@ async function handleCheckout(options) {
|
|
|
6376
6519
|
{ json: options.json }
|
|
6377
6520
|
);
|
|
6378
6521
|
}
|
|
6522
|
+
async function handleTopUp(creditsRaw, options) {
|
|
6523
|
+
const credits = parseTopUpCredits(creditsRaw);
|
|
6524
|
+
if (credits === null) {
|
|
6525
|
+
reportBillingFailure(
|
|
6526
|
+
{
|
|
6527
|
+
exitCode: 2,
|
|
6528
|
+
code: "INVALID_CREDITS",
|
|
6529
|
+
message: "<credits> must be a positive integer Deepline credit amount.",
|
|
6530
|
+
next: "deepline billing plans --json"
|
|
6531
|
+
},
|
|
6532
|
+
options
|
|
6533
|
+
);
|
|
6534
|
+
return;
|
|
6535
|
+
}
|
|
6536
|
+
const idempotencyKey = topUpIdempotencyKey(options.idempotencyKey);
|
|
6537
|
+
if (options.dryRun) {
|
|
6538
|
+
printCommandEnvelope(
|
|
6539
|
+
{
|
|
6540
|
+
ok: true,
|
|
6541
|
+
dry_run: true,
|
|
6542
|
+
credits,
|
|
6543
|
+
idempotency_key: idempotencyKey,
|
|
6544
|
+
planned_request: {
|
|
6545
|
+
method: "POST",
|
|
6546
|
+
path: BILLING_TOP_UP_PATH,
|
|
6547
|
+
body: { credits, idempotency_key: idempotencyKey }
|
|
6548
|
+
},
|
|
6549
|
+
render: {
|
|
6550
|
+
sections: [
|
|
6551
|
+
{
|
|
6552
|
+
title: "billing top-up (dry run)",
|
|
6553
|
+
lines: [
|
|
6554
|
+
`Credits: ${credits}`,
|
|
6555
|
+
`Idempotency key: ${idempotencyKey}`,
|
|
6556
|
+
`Planned request: POST ${BILLING_TOP_UP_PATH}`,
|
|
6557
|
+
"No payment request was sent. Re-run without --dry-run to apply."
|
|
6558
|
+
]
|
|
6559
|
+
}
|
|
6560
|
+
]
|
|
6561
|
+
}
|
|
6562
|
+
},
|
|
6563
|
+
{ json: options.json }
|
|
6564
|
+
);
|
|
6565
|
+
return;
|
|
6566
|
+
}
|
|
6567
|
+
const client2 = new DeeplineClient();
|
|
6568
|
+
let payload;
|
|
6569
|
+
try {
|
|
6570
|
+
payload = await client2.billing.topUp({ credits, idempotencyKey });
|
|
6571
|
+
} catch (error) {
|
|
6572
|
+
const failure = billingTopUpFailureFromError(error, {
|
|
6573
|
+
credits,
|
|
6574
|
+
idempotencyKey
|
|
6575
|
+
});
|
|
6576
|
+
if (!failure) throw error;
|
|
6577
|
+
reportBillingFailure(failure, options);
|
|
6578
|
+
return;
|
|
6579
|
+
}
|
|
6580
|
+
const amountText = invoiceAmountText(payload.amount_cents, payload.currency);
|
|
6581
|
+
const paymentLabel = payload.payment_method?.label ?? [
|
|
6582
|
+
payload.payment_method?.brand ? humanize(payload.payment_method.brand) : null,
|
|
6583
|
+
payload.payment_method?.last4 ? `ending in ${payload.payment_method.last4}` : null
|
|
6584
|
+
].filter(Boolean).join(" ");
|
|
6585
|
+
const compactEnvelope = {
|
|
6586
|
+
ok: true,
|
|
6587
|
+
credits: payload.credits,
|
|
6588
|
+
amount_cents: payload.amount_cents,
|
|
6589
|
+
currency: payload.currency,
|
|
6590
|
+
balance_credits: payload.balance,
|
|
6591
|
+
idempotency_key: idempotencyKey
|
|
6592
|
+
};
|
|
6593
|
+
const fullEnvelope = {
|
|
6594
|
+
...payload,
|
|
6595
|
+
balance_credits: payload.balance,
|
|
6596
|
+
idempotency_key: idempotencyKey,
|
|
6597
|
+
render: {
|
|
6598
|
+
sections: [
|
|
6599
|
+
{
|
|
6600
|
+
title: "billing top-up",
|
|
6601
|
+
lines: [
|
|
6602
|
+
`Added: ${payload.credits} Deepline Credits`,
|
|
6603
|
+
`Charged: ${amountText}`,
|
|
6604
|
+
`Balance: ${payload.balance} Deepline Credits`,
|
|
6605
|
+
...paymentLabel ? [`Payment method: ${paymentLabel}`] : []
|
|
6606
|
+
]
|
|
6607
|
+
}
|
|
6608
|
+
]
|
|
6609
|
+
}
|
|
6610
|
+
};
|
|
6611
|
+
printCommandEnvelope(options.compact ? compactEnvelope : fullEnvelope, {
|
|
6612
|
+
json: options.json
|
|
6613
|
+
});
|
|
6614
|
+
}
|
|
6379
6615
|
async function handleRedeemCode(code, options) {
|
|
6380
6616
|
const { http } = getAuthedHttpClient();
|
|
6381
6617
|
const payload = await http.post(
|
|
@@ -6412,6 +6648,7 @@ Examples:
|
|
|
6412
6648
|
deepline billing subscription status --json
|
|
6413
6649
|
|
|
6414
6650
|
# Buy credits or a plan
|
|
6651
|
+
deepline billing top-up 1000 --json
|
|
6415
6652
|
deepline billing checkout --credits 1000 --no-open --json
|
|
6416
6653
|
deepline billing subscribe runtime-395-2026-07-v1 --no-open --json
|
|
6417
6654
|
deepline billing redeem-code --code ABC123 --no-open --json
|
|
@@ -6551,6 +6788,25 @@ Examples:
|
|
|
6551
6788
|
deepline billing checkout --credits 1000 --discount-code LAUNCH --no-open
|
|
6552
6789
|
`
|
|
6553
6790
|
).option("--tier <tierId>", "Named pricing tier").option("--credits <credits>", "Custom credit amount").option("--discount-code <code>", "Apply a discount code").option("--no-open", "Print the checkout URL without opening a browser").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleCheckout);
|
|
6791
|
+
billing.command("top-up").description("Charge the saved payment method and add Deepline credits.").addHelpText(
|
|
6792
|
+
"after",
|
|
6793
|
+
`
|
|
6794
|
+
Notes:
|
|
6795
|
+
Mutates workspace billing by charging the saved payment method for the active
|
|
6796
|
+
workspace, then adding purchased Deepline credits. If no saved payment method
|
|
6797
|
+
is available, use the checkout command printed in the error response.
|
|
6798
|
+
--dry-run prints the planned request and idempotency key without charging.
|
|
6799
|
+
|
|
6800
|
+
Examples:
|
|
6801
|
+
deepline billing top-up 1000
|
|
6802
|
+
deepline billing top-up 1000 --json
|
|
6803
|
+
deepline billing top-up 1000 --dry-run --json
|
|
6804
|
+
deepline billing top-up 1000 --idempotency-key refill-2026-07-08 --json
|
|
6805
|
+
`
|
|
6806
|
+
).argument("<credits>", "Positive integer Deepline credit amount").option(
|
|
6807
|
+
"--idempotency-key <key>",
|
|
6808
|
+
"Stable retry key for the same intended top-up"
|
|
6809
|
+
).option("--dry-run", "Print the planned top-up without charging").option("--compact", "Keep only high-signal fields in JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(handleTopUp);
|
|
6554
6810
|
billing.command("plans").description("Show published plans and the plan you are on.").addHelpText(
|
|
6555
6811
|
"after",
|
|
6556
6812
|
`
|
|
@@ -6671,7 +6927,7 @@ Examples:
|
|
|
6671
6927
|
|
|
6672
6928
|
// src/cli/commands/csv.ts
|
|
6673
6929
|
var import_node_child_process = require("child_process");
|
|
6674
|
-
var
|
|
6930
|
+
var import_node_crypto3 = require("crypto");
|
|
6675
6931
|
var import_node_fs7 = require("fs");
|
|
6676
6932
|
var import_node_os7 = require("os");
|
|
6677
6933
|
var import_node_path8 = require("path");
|
|
@@ -7568,7 +7824,7 @@ async function handleCsvRenderStart(options) {
|
|
|
7568
7824
|
ensureCsvRenderStateDir();
|
|
7569
7825
|
const logPath = csvRenderLogPath();
|
|
7570
7826
|
const logFd = (0, import_node_fs7.openSync)(logPath, "w");
|
|
7571
|
-
const token = (0,
|
|
7827
|
+
const token = (0, import_node_crypto3.randomUUID)();
|
|
7572
7828
|
const child = (0, import_node_child_process.spawn)(
|
|
7573
7829
|
process.execPath,
|
|
7574
7830
|
["-e", CSV_RENDER_SERVER_SOURCE],
|
|
@@ -8152,7 +8408,7 @@ var import_node_os8 = require("os");
|
|
|
8152
8408
|
var import_node_path12 = require("path");
|
|
8153
8409
|
|
|
8154
8410
|
// src/cli/commands/play.ts
|
|
8155
|
-
var
|
|
8411
|
+
var import_node_crypto4 = require("crypto");
|
|
8156
8412
|
var import_node_fs10 = require("fs");
|
|
8157
8413
|
var import_node_path11 = require("path");
|
|
8158
8414
|
var import_sync5 = require("csv-parse/sync");
|
|
@@ -10951,7 +11207,7 @@ function stageFile(logicalPath, absolutePath) {
|
|
|
10951
11207
|
return {
|
|
10952
11208
|
logicalPath,
|
|
10953
11209
|
contentBase64: buffer.toString("base64"),
|
|
10954
|
-
contentHash: (0,
|
|
11210
|
+
contentHash: (0, import_node_crypto4.createHash)("sha256").update(buffer).digest("hex"),
|
|
10955
11211
|
contentType: absolutePath.toLowerCase().endsWith(".csv") ? "text/csv" : absolutePath.toLowerCase().endsWith(".json") ? "application/json" : "application/octet-stream",
|
|
10956
11212
|
bytes: buffer.byteLength
|
|
10957
11213
|
};
|
|
@@ -12306,6 +12562,19 @@ function formatCreditAmount(value) {
|
|
|
12306
12562
|
}
|
|
12307
12563
|
return Number(value.toFixed(8)).toString();
|
|
12308
12564
|
}
|
|
12565
|
+
function recommendedTopUpCredits(value) {
|
|
12566
|
+
const parsed = typeof value === "number" && Number.isFinite(value) ? value : typeof value === "string" && value.trim() ? Number(value) : NaN;
|
|
12567
|
+
return Math.max(100, Number.isFinite(parsed) ? Math.ceil(parsed) : 100);
|
|
12568
|
+
}
|
|
12569
|
+
function insufficientCreditsRecoveryCommands(billing) {
|
|
12570
|
+
const topUpCredits = recommendedTopUpCredits(
|
|
12571
|
+
billing.recommended_add_credits ?? billing.needed_credits
|
|
12572
|
+
);
|
|
12573
|
+
return {
|
|
12574
|
+
topUp: `deepline billing top-up ${topUpCredits} --json`,
|
|
12575
|
+
checkout: `deepline billing checkout --credits ${topUpCredits} --no-open --json`
|
|
12576
|
+
};
|
|
12577
|
+
}
|
|
12309
12578
|
function extractJsonObjectFromText(text) {
|
|
12310
12579
|
const start = text.indexOf("{");
|
|
12311
12580
|
if (start < 0) {
|
|
@@ -12398,8 +12667,9 @@ function formatInsufficientCreditsMessage(input2) {
|
|
|
12398
12667
|
const billingUrl = getStringField(input2.billing, "billing_url");
|
|
12399
12668
|
const workspace = getStringField(input2.billing, "workspace_id") ?? getStringField(input2.billing, "workspaceId");
|
|
12400
12669
|
const workspaceSuffix = workspace ? ` (workspace=${workspace})` : "";
|
|
12670
|
+
const recovery = insufficientCreditsRecoveryCommands(input2.billing);
|
|
12401
12671
|
const addSuffix = billingUrl && recommended !== "-" ? ` Add >=${recommended} at ${billingUrl}.` : billingUrl ? ` Add credits at ${billingUrl}.` : "";
|
|
12402
|
-
return `Workspace balance ${balance} < required ${required} for ${operation}${workspaceSuffix}.${addSuffix}
|
|
12672
|
+
return `Workspace balance ${balance} < required ${required} for ${operation}${workspaceSuffix}.${addSuffix} Ask the user if they want to add Deepline credits. If they approve, run: ${recovery.topUp}. If checkout is required, run: ${recovery.checkout}.`;
|
|
12403
12673
|
}
|
|
12404
12674
|
function buildInsufficientCreditsSummaryLines(input2) {
|
|
12405
12675
|
const progress = input2.status.progress;
|
|
@@ -12415,11 +12685,15 @@ function buildInsufficientCreditsSummaryLines(input2) {
|
|
|
12415
12685
|
const recommended = formatCreditAmount(
|
|
12416
12686
|
input2.billing.recommended_add_credits ?? input2.billing.needed_credits
|
|
12417
12687
|
);
|
|
12688
|
+
const recovery = insufficientCreditsRecoveryCommands(input2.billing);
|
|
12418
12689
|
if (billingUrl) {
|
|
12419
12690
|
lines.push(
|
|
12420
12691
|
recommended !== "-" ? ` add credits: add >=${recommended} at ${billingUrl}` : ` add credits: ${billingUrl}`
|
|
12421
12692
|
);
|
|
12422
12693
|
}
|
|
12694
|
+
lines.push(" ask user: ask whether they want to add Deepline credits");
|
|
12695
|
+
lines.push(` top up after approval: ${recovery.topUp}`);
|
|
12696
|
+
lines.push(` checkout fallback: ${recovery.checkout}`);
|
|
12423
12697
|
const runId = input2.status.runId?.trim();
|
|
12424
12698
|
if (runId) {
|
|
12425
12699
|
lines.push(` inspect: deepline runs get ${runId} --json`);
|
|
@@ -21551,7 +21825,7 @@ var import_node_fs11 = require("fs");
|
|
|
21551
21825
|
var import_node_os9 = require("os");
|
|
21552
21826
|
var import_node_path13 = require("path");
|
|
21553
21827
|
var import_node_zlib = require("zlib");
|
|
21554
|
-
var
|
|
21828
|
+
var import_node_crypto5 = require("crypto");
|
|
21555
21829
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21556
21830
|
var UUID_IN_TEXT_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i;
|
|
21557
21831
|
var MAX_SESSION_UPLOAD_BYTES = 35e5;
|
|
@@ -21913,7 +22187,7 @@ async function uploadPayload(path, payload) {
|
|
|
21913
22187
|
return await http.post(path, payload);
|
|
21914
22188
|
}
|
|
21915
22189
|
async function uploadChunkedSessions(sessions, options) {
|
|
21916
|
-
const uploadId = (0,
|
|
22190
|
+
const uploadId = (0, import_node_crypto5.randomUUID)();
|
|
21917
22191
|
for (const session of sessions) {
|
|
21918
22192
|
const bytes = Buffer.from(session.encodedContent, "base64");
|
|
21919
22193
|
const chunks = [];
|
|
@@ -23739,14 +24013,14 @@ Examples:
|
|
|
23739
24013
|
|
|
23740
24014
|
// src/cli/commands/quickstart.ts
|
|
23741
24015
|
var import_node_child_process2 = require("child_process");
|
|
23742
|
-
var
|
|
24016
|
+
var import_node_crypto6 = require("crypto");
|
|
23743
24017
|
var import_node_http = require("http");
|
|
23744
24018
|
var EXIT_OK2 = 0;
|
|
23745
24019
|
var EXIT_AUTH2 = 1;
|
|
23746
24020
|
var EXIT_SERVER3 = 2;
|
|
23747
24021
|
var MAX_PROMPT_LENGTH = 8e3;
|
|
23748
24022
|
var MAX_BODY_BYTES = 64 * 1024;
|
|
23749
|
-
function
|
|
24023
|
+
function shellQuote2(arg) {
|
|
23750
24024
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
23751
24025
|
}
|
|
23752
24026
|
function hasClaudeBinary() {
|
|
@@ -23868,7 +24142,7 @@ async function handleQuickstart(options) {
|
|
|
23868
24142
|
return EXIT_AUTH2;
|
|
23869
24143
|
}
|
|
23870
24144
|
}
|
|
23871
|
-
const state = (0,
|
|
24145
|
+
const state = (0, import_node_crypto6.randomBytes)(32).toString("hex");
|
|
23872
24146
|
let resolveSelection;
|
|
23873
24147
|
const selectionPromise = new Promise((resolve14) => {
|
|
23874
24148
|
resolveSelection = resolve14;
|
|
@@ -23919,7 +24193,7 @@ async function handleQuickstart(options) {
|
|
|
23919
24193
|
}
|
|
23920
24194
|
progress.complete();
|
|
23921
24195
|
const { prompt, workflowId } = outcome;
|
|
23922
|
-
const claudeCommand = `claude ${
|
|
24196
|
+
const claudeCommand = `claude ${shellQuote2(prompt)}`;
|
|
23923
24197
|
const claudeAvailable = hasClaudeBinary();
|
|
23924
24198
|
const willLaunch = options.launch !== false && !jsonOutput && interactive && claudeAvailable;
|
|
23925
24199
|
printCommandEnvelope(
|
|
@@ -25841,7 +26115,7 @@ function parseExecuteOptions(args) {
|
|
|
25841
26115
|
function safeFileStem(value) {
|
|
25842
26116
|
return value.trim().replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "tool";
|
|
25843
26117
|
}
|
|
25844
|
-
function
|
|
26118
|
+
function shellQuote3(value) {
|
|
25845
26119
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
25846
26120
|
}
|
|
25847
26121
|
function powerShellQuote(value) {
|
|
@@ -25911,7 +26185,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
|
|
|
25911
26185
|
path: scriptPath,
|
|
25912
26186
|
sourceCode: script,
|
|
25913
26187
|
projectDir,
|
|
25914
|
-
macCopyCommand: `mkdir -p ${
|
|
26188
|
+
macCopyCommand: `mkdir -p ${shellQuote3(projectDir)} && cp ${shellQuote3(scriptPath)} ${shellQuote3(`${projectDir}/${fileName}`)}`,
|
|
25915
26189
|
windowsCopyCommand: `New-Item -ItemType Directory -Force -Path ${powerShellQuote(projectDir.replace(/\//g, "\\"))} | Out-Null; Copy-Item -LiteralPath ${powerShellQuote(scriptPath)} -Destination ${powerShellQuote(`${projectDir.replace(/\//g, "\\")}\\${fileName}`)}`
|
|
25916
26190
|
};
|
|
25917
26191
|
}
|
|
@@ -25934,7 +26208,7 @@ function buildToolExecuteBaseEnvelope(input2) {
|
|
|
25934
26208
|
envelope,
|
|
25935
26209
|
"output"
|
|
25936
26210
|
);
|
|
25937
|
-
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${
|
|
26211
|
+
const inspectCommand = `deepline tools execute ${input2.toolId} --input ${shellQuote3(JSON.stringify(input2.params))} --json`;
|
|
25938
26212
|
const actions = input2.listConversion ? [
|
|
25939
26213
|
{
|
|
25940
26214
|
label: "next",
|
|
@@ -26240,7 +26514,7 @@ var import_promises5 = require("fs/promises");
|
|
|
26240
26514
|
var import_node_path17 = require("path");
|
|
26241
26515
|
|
|
26242
26516
|
// src/cli/workflow-to-play.ts
|
|
26243
|
-
var
|
|
26517
|
+
var import_node_crypto7 = require("crypto");
|
|
26244
26518
|
|
|
26245
26519
|
// ../shared_libs/plays/secret-guardrails.ts
|
|
26246
26520
|
var SECRET_ENV_PATTERN = /\bprocess(?:\.env|\[['"]env['"]\])(?:\.|\[['"])([A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|ACCESS[_-]?KEY)[A-Z0-9_]*)(?:['"]\])?/g;
|
|
@@ -26383,7 +26657,7 @@ function sanitizePlayNameSegment(value) {
|
|
|
26383
26657
|
}
|
|
26384
26658
|
function deriveWorkflowPlayName(workflowName) {
|
|
26385
26659
|
const base = sanitizePlayNameSegment(workflowName) || "workflow";
|
|
26386
|
-
const suffix = (0,
|
|
26660
|
+
const suffix = (0, import_node_crypto7.createHash)("sha256").update(workflowName).digest("hex").slice(0, 8);
|
|
26387
26661
|
const reserved = suffix.length + 1;
|
|
26388
26662
|
const allowedBase = Math.max(1, MAX_PLAY_NAME_LENGTH - reserved);
|
|
26389
26663
|
let name = `${base.slice(0, allowedBase)}_${suffix}`;
|
|
@@ -27003,7 +27277,7 @@ function hasCommand(command) {
|
|
|
27003
27277
|
});
|
|
27004
27278
|
return result.status === 0;
|
|
27005
27279
|
}
|
|
27006
|
-
function
|
|
27280
|
+
function shellQuote4(arg) {
|
|
27007
27281
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
27008
27282
|
}
|
|
27009
27283
|
function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NAMES) {
|
|
@@ -27011,7 +27285,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
|
|
|
27011
27285
|
const npxInstall = {
|
|
27012
27286
|
command: "npx",
|
|
27013
27287
|
args: npxArgs,
|
|
27014
|
-
manualCommand: `npx ${npxArgs.map(
|
|
27288
|
+
manualCommand: `npx ${npxArgs.map(shellQuote4).join(" ")}`
|
|
27015
27289
|
};
|
|
27016
27290
|
if (hasCommand("bunx")) {
|
|
27017
27291
|
const bunxArgs = buildBunxSkillsInstallArgs(baseUrl, skillNames);
|
|
@@ -27019,7 +27293,7 @@ function resolveSkillsInstallCommands(baseUrl, skillNames = DEFAULT_SDK_SKILL_NA
|
|
|
27019
27293
|
{
|
|
27020
27294
|
command: "bunx",
|
|
27021
27295
|
args: bunxArgs,
|
|
27022
|
-
manualCommand: `bunx ${bunxArgs.map(
|
|
27296
|
+
manualCommand: `bunx ${bunxArgs.map(shellQuote4).join(" ")}`
|
|
27023
27297
|
},
|
|
27024
27298
|
npxInstall
|
|
27025
27299
|
];
|
|
@@ -27186,14 +27460,14 @@ function posixShellQuote(value) {
|
|
|
27186
27460
|
function windowsCmdQuote(value) {
|
|
27187
27461
|
return `"${value.replace(/"/g, '""')}"`;
|
|
27188
27462
|
}
|
|
27189
|
-
function
|
|
27463
|
+
function shellQuote5(value) {
|
|
27190
27464
|
if (process.platform === "win32") {
|
|
27191
27465
|
return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : windowsCmdQuote(value);
|
|
27192
27466
|
}
|
|
27193
27467
|
return posixShellQuote(value);
|
|
27194
27468
|
}
|
|
27195
27469
|
function buildSourceUpdateCommand(sourceRoot) {
|
|
27196
|
-
const quotedRoot =
|
|
27470
|
+
const quotedRoot = shellQuote5(sourceRoot);
|
|
27197
27471
|
const cdCommand = process.platform === "win32" ? `cd /d ${quotedRoot}` : `cd ${quotedRoot}`;
|
|
27198
27472
|
return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
|
|
27199
27473
|
}
|
|
@@ -27205,7 +27479,7 @@ function buildSidecarProjectConfigCommand(versionDir, nodeBin) {
|
|
|
27205
27479
|
"fs.mkdirSync(dir,{recursive:true});",
|
|
27206
27480
|
`fs.writeFileSync(path.join(dir,'package.json'),${JSON.stringify(NPM_SDK_SIDECAR_PACKAGE_JSON)});`
|
|
27207
27481
|
].join("");
|
|
27208
|
-
return `${
|
|
27482
|
+
return `${shellQuote5(nodeBin)} -e ${shellQuote5(script)} ${shellQuote5(versionDir)}`;
|
|
27209
27483
|
}
|
|
27210
27484
|
function sidecarStateDir(input2) {
|
|
27211
27485
|
const scope = input2.env.DEEPLINE_CONFIG_SCOPE?.trim();
|
|
@@ -27244,7 +27518,7 @@ function resolvePythonSidecarUpdatePlan(options) {
|
|
|
27244
27518
|
const packageSpec = options.packageSpec || "deepline@latest";
|
|
27245
27519
|
const npmCommand = "npm";
|
|
27246
27520
|
const versionDir = (0, import_node_path19.join)(stateDir, "versions", "<version>");
|
|
27247
|
-
const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${
|
|
27521
|
+
const manualCommand = `${buildSidecarProjectConfigCommand(versionDir, nodeBin)} && ${npmCommand} install --prefix ${shellQuote5(versionDir)} ${NPM_SDK_INSTALL_COMMON_FLAGS.map(shellQuote5).join(" ")} ${shellQuote5(packageSpec)}`;
|
|
27248
27522
|
return {
|
|
27249
27523
|
kind: "python-sidecar",
|
|
27250
27524
|
stateDir,
|
|
@@ -27324,7 +27598,7 @@ function resolveUpdatePlan(options = {}) {
|
|
|
27324
27598
|
command,
|
|
27325
27599
|
args,
|
|
27326
27600
|
...installPrefix ? { installPrefix } : {},
|
|
27327
|
-
manualCommand: `${command} ${args.map(
|
|
27601
|
+
manualCommand: `${command} ${args.map(shellQuote5).join(" ")}`
|
|
27328
27602
|
};
|
|
27329
27603
|
}
|
|
27330
27604
|
var AUTO_UPDATE_FAILURE_FILE = ".auto-update-failure.json";
|
|
@@ -27485,9 +27759,9 @@ function writeSidecarLauncher(input2) {
|
|
|
27485
27759
|
input2.path,
|
|
27486
27760
|
[
|
|
27487
27761
|
"#!/usr/bin/env sh",
|
|
27488
|
-
`export DEEPLINE_HOST_URL=${
|
|
27489
|
-
`export DEEPLINE_CONFIG_SCOPE=${
|
|
27490
|
-
`exec ${
|
|
27762
|
+
`export DEEPLINE_HOST_URL=${shellQuote5(input2.hostUrl)}`,
|
|
27763
|
+
`export DEEPLINE_CONFIG_SCOPE=${shellQuote5(input2.scope)}`,
|
|
27764
|
+
`exec ${shellQuote5(input2.nodeBin)} ${shellQuote5(input2.entryPath)} "$@"`,
|
|
27491
27765
|
""
|
|
27492
27766
|
].join("\n"),
|
|
27493
27767
|
{ encoding: "utf8", mode: 493 }
|