skydive-cli 0.3.0-beta.823 → 0.3.0-beta.853

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 CHANGED
@@ -316,6 +316,18 @@ messageId, text }` instead of streaming the raw text.
316
316
  the full reply whether it's still streaming or already finished. Message ids
317
317
  are the handle this API works in; run ids stay server-side.
318
318
 
319
+ - **Exit codes.** `0` success, `1` any failure, `5` billing-blocked: the
320
+ workspace is paused by billing — either the send was refused before anything
321
+ ran, or the run was stopped at the billing boundary (anything already
322
+ streamed stays on stdout). The guidance and recovery URL print on stderr so
323
+ a scripted caller (an agent driving `-p`) can relay them to a human.
324
+ `messages get` uses the same codes. Treat these values as frozen.
325
+
326
+ With `--json`, a billing block still exits `5` but first emits a structured
327
+ result on stdout: `{ billingBlocked: { code, message }, text, messageId }` —
328
+ `text` is whatever streamed before the block and `messageId` is the handle
329
+ to re-fetch the full reply with `messages get` after billing recovers.
330
+
319
331
  It defaults to the production API (`https://api.skydive.com`). For local
320
332
  dev, point it at your stack:
321
333
 
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+ import { z } from "zod";
3
+
4
+ //#region src/chat/api/billing-blocked.ts
5
+ const billingBlockedOutcomeSchema = z.object({
6
+ code: z.literal("billing_blocked"),
7
+ message: z.string().min(1)
8
+ });
9
+ const billingBlockedSendResponseSchema = z.object({
10
+ error: z.literal("billing_blocked"),
11
+ outcome: billingBlockedOutcomeSchema
12
+ });
13
+ /**
14
+ * The typed billing outcome out of a failed send response, or null when the
15
+ * failure isn't a billing block. HTTP 402 + the discriminated body above is
16
+ * the whole check; anything else (a non-billing 402, an edge HTML page) is
17
+ * someone else's error and keeps its existing handling.
18
+ */
19
+ function billingBlockedOutcomeFromSendResponse({ status, body }) {
20
+ if (status !== 402) return null;
21
+ let parsed;
22
+ try {
23
+ parsed = JSON.parse(body);
24
+ } catch (_error) {
25
+ return null;
26
+ }
27
+ const response = billingBlockedSendResponseSchema.safeParse(parsed);
28
+ return response.success ? response.data.outcome : null;
29
+ }
30
+ /**
31
+ * A billing block surfaced on the headless path (`chat -p`, `messages get`).
32
+ * Distinct from a plain Error so the command layer can exit with
33
+ * {@link BILLING_BLOCKED_EXIT_CODE}; `message` is the server-authored
34
+ * guidance verbatim (state, recovery step, and manage-billing URL). The
35
+ * context preserves what the run produced before the block so `--json`
36
+ * callers get a structured result instead of losing the buffered output.
37
+ */
38
+ var BillingBlockedError = class extends Error {
39
+ constructor(outcome, context) {
40
+ super(outcome.message);
41
+ this.outcome = outcome;
42
+ this.context = context;
43
+ this.name = "BillingBlockedError";
44
+ }
45
+ };
46
+ /**
47
+ * The `--json` envelope for a billing-blocked headless invocation, emitted on
48
+ * stdout before exiting with {@link BILLING_BLOCKED_EXIT_CODE}. Additive
49
+ * contract: scripted callers get the server guidance, whatever text streamed
50
+ * before the block, and the message id to re-fetch after recovery.
51
+ */
52
+ function billingBlockedJsonResult(error, fallbackMessageId) {
53
+ return {
54
+ billingBlocked: {
55
+ code: error.outcome.code,
56
+ message: error.outcome.message
57
+ },
58
+ text: error.context.partialText ?? "",
59
+ messageId: error.context.messageId ?? fallbackMessageId
60
+ };
61
+ }
62
+ /**
63
+ * Headless exit code for a billing-blocked send or run — distinct from the
64
+ * generic `1` so scripted callers (Claude Code / Codex driving `chat -p`) can
65
+ * tell "the workspace is paused by billing, relay the recovery URL" from an
66
+ * ordinary failure. Documented in the CLI README; treat as frozen.
67
+ */
68
+ const BILLING_BLOCKED_EXIT_CODE = 5;
69
+
70
+ //#endregion
71
+ export { billingBlockedOutcomeSchema as a, billingBlockedOutcomeFromSendResponse as i, BillingBlockedError as n, billingBlockedJsonResult as r, BILLING_BLOCKED_EXIT_CODE as t };
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { a as billingBlockedOutcomeSchema, i as billingBlockedOutcomeFromSendResponse, n as BillingBlockedError, r as billingBlockedJsonResult, t as BILLING_BLOCKED_EXIT_CODE } from "./billing-blocked-CwfG1BTR.mjs";
3
+
4
+ export { BILLING_BLOCKED_EXIT_CODE, BillingBlockedError, billingBlockedJsonResult };
package/dist/js/bin.mjs CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { C as setActiveWorkspace, S as listWorkspaces, T as version, _ as themes, b as getActiveWorkspaceId, o as brandHelpArt, t as installCrashHandler, w as name, x as getSessionIdentity, y as ensureActiveOrganization } from "./install-DrX2_gs-.mjs";
3
- import { A as getStoredApiKeyWorkspaceName, C as getLastSeenVersion, F as resolveManagementAuth, I as resolveSession, M as resolveAppUrl, N as resolveChatAuth, O as getShareMachineDefault, P as resolveConfig, R as saveConfig, S as getConfigPath, T as getPromptHistoryPath, V as setLastSeenVersion, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getUpdateCheckDisabled, k as getStoredApiKeyId, v as DEFAULT_API_URL, w as getPreference, x as deleteConfig, z as saveSession } from "./print-Bs_6CrTC.mjs";
2
+ import { C as setActiveWorkspace, S as listWorkspaces, T as version, _ as themes, b as getActiveWorkspaceId, o as brandHelpArt, t as installCrashHandler, w as name, x as getSessionIdentity, y as ensureActiveOrganization } from "./install-mpXV2NVA.mjs";
3
+ import { A as getStoredApiKeyWorkspaceName, C as getLastSeenVersion, F as resolveManagementAuth, I as resolveSession, M as resolveAppUrl, N as resolveChatAuth, O as getShareMachineDefault, P as resolveConfig, R as saveConfig, S as getConfigPath, T as getPromptHistoryPath, V as setLastSeenVersion, _ as API_KEY_PREFIX, b as PREFERENCES, g as API_KEY_FAMILY_PREFIX, h as API_KEYS_URL, i as resolveAgent, j as getUpdateCheckDisabled, k as getStoredApiKeyId, v as DEFAULT_API_URL, w as getPreference, x as deleteConfig, z as saveSession } from "./print-X2N5wJ5l.mjs";
4
4
  import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
5
- import { n as createRestClient, t as HttpError } from "./rest-BlN_uWmL.mjs";
6
- import { a as registerPortalDevice, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice, s as machineIdentity } from "./client-Dc7GZ3PG.mjs";
7
- import { c as PORTAL_DAEMON_FLAG, i as queryDaemonStatus, l as daemonPaths, n as ensureDaemonRunning, o as stopDaemon } from "./daemon-Co4CtpXZ.mjs";
8
- import { t as SandboxStream } from "./client-DfcJFEbh.mjs";
5
+ import { n as createRestClient, t as HttpError } from "./rest-imDZZGQA.mjs";
6
+ import "./billing-blocked-CwfG1BTR.mjs";
7
+ import { a as registerPortalDevice, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice, s as machineIdentity } from "./client-CKzK-12y.mjs";
8
+ import { c as PORTAL_DAEMON_FLAG, i as queryDaemonStatus, l as daemonPaths, n as ensureDaemonRunning, o as stopDaemon } from "./daemon-CaFz7Wtw.mjs";
9
+ import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
9
10
  import { hideBin } from "yargs/helpers";
10
11
  import yargs from "yargs";
11
12
  import os, { hostname } from "node:os";
@@ -1504,7 +1505,7 @@ const importCommand = {
1504
1505
  process.exit(1);
1505
1506
  }
1506
1507
  }
1507
- const { runChat } = await import("./boot-BypwzKHP.mjs");
1508
+ const { runChat } = await import("./boot-95ngTnOd.mjs");
1508
1509
  await runChat({
1509
1510
  appUrl,
1510
1511
  sessionToken: session.value.sessionToken,
@@ -1531,7 +1532,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1531
1532
  printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
1532
1533
  process.exit(1);
1533
1534
  }
1534
- const { connectMachineShare } = await import("./print-share-7qfpQtWK.mjs");
1535
+ const { connectMachineShare } = await import("./print-share-D72CfWJk.mjs");
1535
1536
  const machineShare = await connectMachineShare({
1536
1537
  appUrl,
1537
1538
  sessionToken: session.value.sessionToken,
@@ -1539,7 +1540,7 @@ async function runImportPrintMode({ argv, appUrl }) {
1539
1540
  });
1540
1541
  const extra = (argv.print ?? "").trim();
1541
1542
  const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
1542
- const { runPrint } = await import("./print-bhjVgVMK.mjs");
1543
+ const { runPrint } = await import("./print-BXNq9UxE.mjs");
1543
1544
  try {
1544
1545
  const result = await runPrint({
1545
1546
  appUrl,
@@ -1916,7 +1917,7 @@ const chatCommand = {
1916
1917
  sessionToken: auth.value.token,
1917
1918
  agentSelector: argv.agent ?? null
1918
1919
  });
1919
- const { runChat } = await import("./boot-BypwzKHP.mjs");
1920
+ const { runChat } = await import("./boot-95ngTnOd.mjs");
1920
1921
  await runChat({
1921
1922
  appUrl: auth.value.appUrl,
1922
1923
  sessionToken: auth.value.token,
@@ -1983,7 +1984,7 @@ async function runPrintMode({ argv, appUrl }) {
1983
1984
  printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
1984
1985
  process.exit(1);
1985
1986
  }
1986
- const { runPrint, readStdin } = await import("./print-bhjVgVMK.mjs");
1987
+ const { runPrint, readStdin } = await import("./print-BXNq9UxE.mjs");
1987
1988
  await ensureAgentWorkspace({
1988
1989
  appUrl,
1989
1990
  sessionToken: auth.value.token,
@@ -2008,7 +2009,7 @@ async function runPrintMode({ argv, appUrl }) {
2008
2009
  process.exit(1);
2009
2010
  }
2010
2011
  } else {
2011
- const { connectMachineShare } = await import("./print-share-7qfpQtWK.mjs");
2012
+ const { connectMachineShare } = await import("./print-share-D72CfWJk.mjs");
2012
2013
  machineShare = await connectMachineShare({
2013
2014
  appUrl: auth.value.appUrl,
2014
2015
  sessionToken: auth.value.token,
@@ -2028,6 +2029,12 @@ async function runPrintMode({ argv, appUrl }) {
2028
2029
  });
2029
2030
  if (argv.json) output(argv, result);
2030
2031
  } catch (error) {
2032
+ const { BillingBlockedError, BILLING_BLOCKED_EXIT_CODE, billingBlockedJsonResult } = await import("./billing-blocked-euid6MN9.mjs");
2033
+ if (error instanceof BillingBlockedError) {
2034
+ if (argv.json) output(argv, billingBlockedJsonResult(error, null));
2035
+ printError(error.message);
2036
+ process.exit(BILLING_BLOCKED_EXIT_CODE);
2037
+ }
2031
2038
  printError(error instanceof Error ? error.message : String(error));
2032
2039
  process.exit(1);
2033
2040
  } finally {
@@ -2066,7 +2073,7 @@ const getCommand$1 = {
2066
2073
  printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
2067
2074
  process.exit(1);
2068
2075
  }
2069
- const { messageGet } = await import("./print-bhjVgVMK.mjs");
2076
+ const { messageGet } = await import("./print-BXNq9UxE.mjs");
2070
2077
  try {
2071
2078
  const result = await messageGet({
2072
2079
  appUrl: auth.value.appUrl,
@@ -2076,6 +2083,12 @@ const getCommand$1 = {
2076
2083
  });
2077
2084
  if (argv.json) output(argv, result);
2078
2085
  } catch (error) {
2086
+ const { BillingBlockedError, BILLING_BLOCKED_EXIT_CODE, billingBlockedJsonResult } = await import("./billing-blocked-euid6MN9.mjs");
2087
+ if (error instanceof BillingBlockedError) {
2088
+ if (argv.json) output(argv, billingBlockedJsonResult(error, argv["message-id"]));
2089
+ printError(error.message);
2090
+ process.exit(BILLING_BLOCKED_EXIT_CODE);
2091
+ }
2079
2092
  printError(error instanceof Error ? error.message : String(error));
2080
2093
  process.exit(1);
2081
2094
  }
@@ -2263,7 +2276,7 @@ const switchCommand = {
2263
2276
  printError("The workspace picker needs the Bun runtime and it could not be set up automatically. Pass a workspace slug instead, or install Bun and retry.");
2264
2277
  process.exit(1);
2265
2278
  }
2266
- const { runWorkspacePicker } = await import("./boot-BypwzKHP.mjs");
2279
+ const { runWorkspacePicker } = await import("./boot-95ngTnOd.mjs");
2267
2280
  await runWorkspacePicker(session);
2268
2281
  return;
2269
2282
  }
@@ -2341,7 +2354,7 @@ const openCommand = {
2341
2354
  const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
2342
2355
  const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
2343
2356
  const { machineName } = machineIdentity();
2344
- const { PortalClient } = await import("./client-DuwxEDG4.mjs");
2357
+ const { PortalClient } = await import("./client-D6apKmV0.mjs");
2345
2358
  let lastLine = "";
2346
2359
  let signalConnected;
2347
2360
  const connected = new Promise((resolve) => {
@@ -2614,8 +2627,8 @@ const sandboxCommand = {
2614
2627
  }).example("skydive sandbox --agent grace", "Live terminal (Ctrl-] detaches)").example("skydive sandbox --agent grace -- tail -n 50 /tmp/harness.log", "One-shot command (use `--` so its flags reach the sandbox)").example("skydive sandbox --agent grace -- sh -c 'ls /tmp | wc -l'", "Shell features go through an explicit `sh -c`"),
2615
2628
  handler: async (argv) => {
2616
2629
  const session = requireSession(argv);
2617
- const { createRestClient } = await import("./rest-CDTXCmUb.mjs");
2618
- const { resolveAgent } = await import("./print-bhjVgVMK.mjs");
2630
+ const { createRestClient } = await import("./rest-Br2eFTlj.mjs");
2631
+ const { resolveAgent } = await import("./print-BXNq9UxE.mjs");
2619
2632
  const client = createRestClient({
2620
2633
  appUrl: session.appUrl,
2621
2634
  sessionToken: session.sessionToken
@@ -2684,7 +2697,7 @@ async function runPty({ session, agentId, agentName }) {
2684
2697
  return 1;
2685
2698
  }
2686
2699
  console.error(`Connecting to ${agentName}'s sandbox… (Ctrl-] detaches)`);
2687
- const { runRawPtyPassthrough } = await import("./raw-pty-ChUHav4d.mjs");
2700
+ const { runRawPtyPassthrough } = await import("./raw-pty-t5DC-e1T.mjs");
2688
2701
  const result = await runRawPtyPassthrough({
2689
2702
  stdin: process.stdin,
2690
2703
  stdout: process.stdout,
@@ -3873,7 +3886,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
3873
3886
  process.exit(0);
3874
3887
  }
3875
3888
  if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
3876
- const { runPortalDaemon } = await import("./daemon-Ch_MSDmQ.mjs");
3889
+ const { runPortalDaemon } = await import("./daemon-BADmpJAs.mjs");
3877
3890
  runPortalDaemon(process.argv);
3878
3891
  } else runCli();
3879
3892
  function runCli() {
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { C as setActiveWorkspace, S as listWorkspaces, a as WORDMARK, b as getActiveWorkspaceId, c as applyTheme, d as noColorRequested, f as theme, g as themeVersion, h as themeModeFromColorFgBg, i as MARK_CELLS, l as findTheme, m as themeMode, n as buildCrashReport, p as themeForMode, r as writeCrashReport, s as DEFAULT_THEME_ID, t as installCrashHandler, u as monoTheme, v as themesForMode } from "./install-DrX2_gs-.mjs";
3
- import { B as saveTheme, D as getSavedTheme, E as getReviewStateDir, L as resolveWebUrl, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL } from "./print-Bs_6CrTC.mjs";
4
- import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-BlN_uWmL.mjs";
5
- import { t as PortalClient } from "./client-Dc7GZ3PG.mjs";
6
- import { d as makeLineParser, f as parseDaemonMessage, l as daemonPaths, n as ensureDaemonRunning, s as LOCAL_PROTOCOL_VERSION, u as encodeLine } from "./daemon-Co4CtpXZ.mjs";
7
- import { t as SandboxStream } from "./client-DfcJFEbh.mjs";
8
- import { t as runRawPtyPassthrough } from "./raw-pty-BcjbTjHJ.mjs";
2
+ import { C as setActiveWorkspace, S as listWorkspaces, a as WORDMARK, b as getActiveWorkspaceId, c as applyTheme, d as noColorRequested, f as theme, g as themeVersion, h as themeModeFromColorFgBg, i as MARK_CELLS, l as findTheme, m as themeMode, n as buildCrashReport, p as themeForMode, r as writeCrashReport, s as DEFAULT_THEME_ID, t as installCrashHandler, u as monoTheme, v as themesForMode } from "./install-mpXV2NVA.mjs";
3
+ import { B as saveTheme, D as getSavedTheme, E as getReviewStateDir, L as resolveWebUrl, S as getConfigPath, c as cardActionErrorMessage, d as reconcileMaskedInput, f as resolveConnectUrl, i as resolveAgent, l as parseExternalOauthConnectParams, m as specKeyFor, p as parseConnectCard, s as MASK_CHAR, u as parseOauthConnectParams, v as DEFAULT_API_URL, y as DEFAULT_APP_URL } from "./print-X2N5wJ5l.mjs";
4
+ import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-imDZZGQA.mjs";
5
+ import "./billing-blocked-CwfG1BTR.mjs";
6
+ import { t as PortalClient } from "./client-CKzK-12y.mjs";
7
+ import { d as makeLineParser, f as parseDaemonMessage, l as daemonPaths, n as ensureDaemonRunning, s as LOCAL_PROTOCOL_VERSION, u as encodeLine } from "./daemon-CaFz7Wtw.mjs";
8
+ import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
9
+ import { t as runRawPtyPassthrough } from "./raw-pty-DAmb8uqt.mjs";
9
10
  import * as os$1 from "node:os";
10
11
  import { homedir, platform, release, tmpdir } from "node:os";
11
12
  import path, { basename, extname, isAbsolute, join, win32 } from "node:path";
@@ -11539,6 +11540,7 @@ function ToastView() {
11539
11540
  maxWidth: Math.min(60, Math.max(20, width - 6)),
11540
11541
  border: true,
11541
11542
  borderColor: toastColor(toast.variant),
11543
+ backgroundColor: theme.surface ?? "#1a1a1a",
11542
11544
  paddingLeft: 1,
11543
11545
  paddingRight: 1
11544
11546
  },
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage, t as HttpError } from "./rest-BlN_uWmL.mjs";
2
+ import { a as errorMessage, t as HttpError } from "./rest-imDZZGQA.mjs";
3
3
  import os from "node:os";
4
4
  import { z } from "zod";
5
5
  import { spawn } from "node:child_process";
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import "./rest-imDZZGQA.mjs";
3
+ import "./billing-blocked-CwfG1BTR.mjs";
4
+ import { t as PortalClient } from "./client-CKzK-12y.mjs";
5
+
6
+ export { PortalClient };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import "./rest-imDZZGQA.mjs";
3
+ import "./billing-blocked-CwfG1BTR.mjs";
4
+ import "./client-CKzK-12y.mjs";
5
+ import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as stopDaemon, r as isDaemonListening, t as PortalDaemon } from "./daemon-CaFz7Wtw.mjs";
6
+
7
+ export { runPortalDaemon };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { o as isRecord } from "./rest-BlN_uWmL.mjs";
3
- import { t as PortalClient } from "./client-Dc7GZ3PG.mjs";
2
+ import { o as isRecord } from "./rest-imDZZGQA.mjs";
3
+ import { t as PortalClient } from "./client-CKzK-12y.mjs";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { z } from "zod";
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { S as getConfigPath } from "./print-Bs_6CrTC.mjs";
2
+ import { S as getConfigPath } from "./print-X2N5wJ5l.mjs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { err, ok } from "neverthrow";
@@ -8,7 +8,7 @@ import fs from "node:fs";
8
8
 
9
9
  //#region package.json
10
10
  var name = "skydive-cli";
11
- var version$1 = "0.3.0-beta.823";
11
+ var version$1 = "0.3.0-beta.853";
12
12
 
13
13
  //#endregion
14
14
  //#region src/auth/organization.ts
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-Bs_6CrTC.mjs";
3
- import "./rest-BlN_uWmL.mjs";
2
+ import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-X2N5wJ5l.mjs";
3
+ import "./rest-imDZZGQA.mjs";
4
+ import "./billing-blocked-CwfG1BTR.mjs";
4
5
 
5
6
  export { messageGet, readStdin, resolveAgent, runPrint };
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, t as HttpError } from "./rest-BlN_uWmL.mjs";
2
+ import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, t as HttpError } from "./rest-imDZZGQA.mjs";
3
+ import { i as billingBlockedOutcomeFromSendResponse, n as BillingBlockedError } from "./billing-blocked-CwfG1BTR.mjs";
3
4
  import path from "node:path";
4
5
  import Conf from "conf";
5
6
  import { err, ok } from "neverthrow";
@@ -622,6 +623,16 @@ async function runPrint({ appUrl, sessionToken, prompt, agentSelector, conversat
622
623
  * actionable copy the interactive TUI shows instead of an obtuse blob.
623
624
  */
624
625
  function toPrintError(err, messageId) {
626
+ if (err instanceof HttpError) {
627
+ const billing = billingBlockedOutcomeFromSendResponse({
628
+ status: err.status,
629
+ body: err.body
630
+ });
631
+ if (billing) return new BillingBlockedError(billing, {
632
+ partialText: null,
633
+ messageId: messageId ?? null
634
+ });
635
+ }
625
636
  if (err instanceof HttpError && err.status >= 500) {
626
637
  const recovery = messageId ? ` The run may still be completing server-side. Do NOT blindly retry (it would re-run the agent). Fetch the result with: skydive messages get ${messageId}` : "";
627
638
  return /* @__PURE__ */ new Error(`The request to Skydive timed out at the edge (HTTP ${err.status}).${recovery}`);
@@ -640,9 +651,11 @@ async function collectRunText({ client, appUrl, target, onText, messageIdForHint
640
651
  let text = "";
641
652
  const controller = new AbortController();
642
653
  let streamError = null;
654
+ let billingBlocked = null;
643
655
  const connectCards = [];
644
656
  const onEvent = (event) => {
645
657
  if (event.kind === "finished") {
658
+ if (event.outcome) billingBlocked = event.outcome;
646
659
  if (event.error) streamError = event.error;
647
660
  return;
648
661
  }
@@ -673,6 +686,10 @@ async function collectRunText({ client, appUrl, target, onText, messageIdForHint
673
686
  } catch (err) {
674
687
  throw toPrintError(err, messageIdForHint);
675
688
  }
689
+ if (billingBlocked) throw new BillingBlockedError(billingBlocked, {
690
+ partialText: text || null,
691
+ messageId: messageIdForHint
692
+ });
676
693
  if (streamError) throw new Error(streamError);
677
694
  return {
678
695
  text,
@@ -14,7 +14,7 @@ import { n as printError } from "./output-DYzzdXYV.mjs";
14
14
  * the reply (and to --json).
15
15
  */
16
16
  async function connectMachineShare({ appUrl, sessionToken, timeoutHint }) {
17
- const { PortalClient } = await import("./client-DuwxEDG4.mjs");
17
+ const { PortalClient } = await import("./client-D6apKmV0.mjs");
18
18
  let signalConnected;
19
19
  const connected = new Promise((resolve) => {
20
20
  signalConnected = resolve;
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as SandboxStream } from "./client-DfcJFEbh.mjs";
2
+ import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
3
3
 
4
4
  //#region src/chat/sandbox/raw-pty.ts
5
5
  /**
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import "./client-D8s9vY4p.mjs";
3
+ import { t as runRawPtyPassthrough } from "./raw-pty-DAmb8uqt.mjs";
4
+
5
+ export { runRawPtyPassthrough };
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-imDZZGQA.mjs";
3
+ import "./billing-blocked-CwfG1BTR.mjs";
4
+
5
+ export { createRestClient };
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { a as billingBlockedOutcomeSchema } from "./billing-blocked-CwfG1BTR.mjs";
2
3
  import { z } from "zod";
3
4
  import { createParser } from "eventsource-parser";
4
5
 
@@ -82,6 +83,11 @@ function serverErrorMessage(body) {
82
83
  * line from the HTTP status when the body carried nothing usable. This keeps
83
84
  * new server-side error copy flowing through without a CLI change, while never
84
85
  * leaving the user staring at a bare status code.
86
+ *
87
+ * Billing-blocked (typed 402) is deliberately NOT handled here: both callers
88
+ * detect it first via billingBlockedOutcomeFromSendResponse and render the
89
+ * richer billing surface (system-notice row / distinct exit code), so this
90
+ * stays a purely generic mapper.
85
91
  */
86
92
  function sendErrorMessage(err) {
87
93
  if (!(err instanceof HttpError)) return `Couldn't reach Skydive (${err instanceof Error ? err.message : String(err)}). Check your connection and try again.`;
@@ -161,7 +167,8 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
161
167
  if (event.kind === "finished") finished = true;
162
168
  onEvent(event.kind === "finished" ? {
163
169
  ...event,
164
- error: event.error ?? null
170
+ error: event.error ?? null,
171
+ outcome: event.outcome ?? null
165
172
  } : event);
166
173
  } });
167
174
  const decoder = new TextDecoder();
@@ -560,7 +567,8 @@ const runStreamEventSchema = z.union([z.object({
560
567
  }), z.object({
561
568
  kind: z.literal("finished"),
562
569
  status: z.string(),
563
- error: z.string().nullish()
570
+ error: z.string().nullish(),
571
+ outcome: billingBlockedOutcomeSchema.nullish()
564
572
  })]);
565
573
  const streamErrorSchema = z.object({ error: z.string() });
566
574
  const conversationStreamEventSchema = z.discriminatedUnion("kind", [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skydive-cli",
3
- "version": "0.3.0-beta.823",
3
+ "version": "0.3.0-beta.853",
4
4
  "description": "Skydive CLI — cloud agents from the command line",
5
5
  "homepage": "https://skydive.com",
6
6
  "license": "MIT",
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./rest-BlN_uWmL.mjs";
3
- import { t as PortalClient } from "./client-Dc7GZ3PG.mjs";
4
-
5
- export { PortalClient };
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./rest-BlN_uWmL.mjs";
3
- import "./client-Dc7GZ3PG.mjs";
4
- import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as stopDaemon, r as isDaemonListening, t as PortalDaemon } from "./daemon-Co4CtpXZ.mjs";
5
-
6
- export { runPortalDaemon };
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./client-DfcJFEbh.mjs";
3
- import { t as runRawPtyPassthrough } from "./raw-pty-BcjbTjHJ.mjs";
4
-
5
- export { runRawPtyPassthrough };
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-BlN_uWmL.mjs";
3
-
4
- export { createRestClient };