skydive-cli 0.3.0 → 0.4.0

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +28 -2
  3. package/dist/js/billing-blocked-CwfG1BTR.mjs +71 -0
  4. package/dist/js/billing-blocked-euid6MN9.mjs +4 -0
  5. package/dist/js/bin.mjs +247 -89
  6. package/dist/js/{boot-HAgDg_b4.mjs → boot-on5ucI_Z.mjs} +228 -50
  7. package/dist/js/chat/tui/chunks/grammars/assets/bash.highlights.scm +56 -0
  8. package/dist/js/chat/tui/chunks/grammars/assets/bash.wasm +0 -0
  9. package/dist/js/chat/tui/chunks/grammars/assets/c.highlights.scm +81 -0
  10. package/dist/js/chat/tui/chunks/grammars/assets/c.wasm +0 -0
  11. package/dist/js/chat/tui/chunks/grammars/assets/cpp.highlights.scm +70 -0
  12. package/dist/js/chat/tui/chunks/grammars/assets/cpp.wasm +0 -0
  13. package/dist/js/chat/tui/chunks/grammars/assets/css.highlights.scm +76 -0
  14. package/dist/js/chat/tui/chunks/grammars/assets/css.wasm +0 -0
  15. package/dist/js/chat/tui/chunks/grammars/assets/go.highlights.scm +123 -0
  16. package/dist/js/chat/tui/chunks/grammars/assets/go.wasm +0 -0
  17. package/dist/js/chat/tui/chunks/grammars/assets/html.highlights.scm +13 -0
  18. package/dist/js/chat/tui/chunks/grammars/assets/html.wasm +0 -0
  19. package/dist/js/chat/tui/chunks/grammars/assets/java.highlights.scm +149 -0
  20. package/dist/js/chat/tui/chunks/grammars/assets/java.wasm +0 -0
  21. package/dist/js/chat/tui/chunks/grammars/assets/json.highlights.scm +16 -0
  22. package/dist/js/chat/tui/chunks/grammars/assets/json.wasm +0 -0
  23. package/dist/js/chat/tui/chunks/grammars/assets/lua.highlights.scm +201 -0
  24. package/dist/js/chat/tui/chunks/grammars/assets/lua.wasm +0 -0
  25. package/dist/js/chat/tui/chunks/grammars/assets/python.highlights.scm +137 -0
  26. package/dist/js/chat/tui/chunks/grammars/assets/python.wasm +0 -0
  27. package/dist/js/chat/tui/chunks/grammars/assets/ruby.highlights.scm +154 -0
  28. package/dist/js/chat/tui/chunks/grammars/assets/ruby.wasm +0 -0
  29. package/dist/js/chat/tui/chunks/grammars/assets/rust.highlights.scm +161 -0
  30. package/dist/js/chat/tui/chunks/grammars/assets/rust.wasm +0 -0
  31. package/dist/js/chat/tui/chunks/grammars/assets/toml.highlights.scm +53 -0
  32. package/dist/js/chat/tui/chunks/grammars/assets/toml.wasm +0 -0
  33. package/dist/js/chat/tui/chunks/grammars/assets/yaml.highlights.scm +79 -0
  34. package/dist/js/chat/tui/chunks/grammars/assets/yaml.wasm +0 -0
  35. package/dist/js/chat/tui/chunks/grammars/grammars.ts +146 -0
  36. package/dist/js/{client-Dc7GZ3PG.mjs → client-CKzK-12y.mjs} +1 -1
  37. package/dist/js/client-D6apKmV0.mjs +6 -0
  38. package/dist/js/daemon-BADmpJAs.mjs +7 -0
  39. package/dist/js/{daemon-Co4CtpXZ.mjs → daemon-CaFz7Wtw.mjs} +2 -2
  40. package/dist/js/{install-CMYBFvR2.mjs → install-Ba-UTi-l.mjs} +2 -2
  41. package/dist/js/{print-CPCFci60.mjs → print-BXNq9UxE.mjs} +3 -2
  42. package/dist/js/{print-Cd-bVSEJ.mjs → print-X2N5wJ5l.mjs} +84 -2
  43. package/dist/js/{print-share-7qfpQtWK.mjs → print-share-D72CfWJk.mjs} +1 -1
  44. package/dist/js/{raw-pty-BcjbTjHJ.mjs → raw-pty-DAmb8uqt.mjs} +1 -1
  45. package/dist/js/raw-pty-t5DC-e1T.mjs +5 -0
  46. package/dist/js/rest-Br2eFTlj.mjs +5 -0
  47. package/dist/js/{rest-BlN_uWmL.mjs → rest-imDZZGQA.mjs} +10 -2
  48. package/package.json +1 -1
  49. package/dist/js/client-DuwxEDG4.mjs +0 -5
  50. package/dist/js/daemon-Ch_MSDmQ.mjs +0 -6
  51. package/dist/js/raw-pty-ChUHav4d.mjs +0 -5
  52. package/dist/js/rest-CDTXCmUb.mjs +0 -4
  53. /package/dist/js/{client-DfcJFEbh.mjs → client-D8s9vY4p.mjs} +0 -0
@@ -0,0 +1,79 @@
1
+ (boolean_scalar) @boolean
2
+
3
+ (null_scalar) @constant.builtin
4
+
5
+ [
6
+ (double_quote_scalar)
7
+ (single_quote_scalar)
8
+ (block_scalar)
9
+ (string_scalar)
10
+ ] @string
11
+
12
+ [
13
+ (integer_scalar)
14
+ (float_scalar)
15
+ ] @number
16
+
17
+ (comment) @comment
18
+
19
+ [
20
+ (anchor_name)
21
+ (alias_name)
22
+ ] @label
23
+
24
+ (tag) @type
25
+
26
+ [
27
+ (yaml_directive)
28
+ (tag_directive)
29
+ (reserved_directive)
30
+ ] @attribute
31
+
32
+ (block_mapping_pair
33
+ key: (flow_node
34
+ [
35
+ (double_quote_scalar)
36
+ (single_quote_scalar)
37
+ ] @property))
38
+
39
+ (block_mapping_pair
40
+ key: (flow_node
41
+ (plain_scalar
42
+ (string_scalar) @property)))
43
+
44
+ (flow_mapping
45
+ (_
46
+ key: (flow_node
47
+ [
48
+ (double_quote_scalar)
49
+ (single_quote_scalar)
50
+ ] @property)))
51
+
52
+ (flow_mapping
53
+ (_
54
+ key: (flow_node
55
+ (plain_scalar
56
+ (string_scalar) @property))))
57
+
58
+ [
59
+ ","
60
+ "-"
61
+ ":"
62
+ ">"
63
+ "?"
64
+ "|"
65
+ ] @punctuation.delimiter
66
+
67
+ [
68
+ "["
69
+ "]"
70
+ "{"
71
+ "}"
72
+ ] @punctuation.bracket
73
+
74
+ [
75
+ "*"
76
+ "&"
77
+ "---"
78
+ "..."
79
+ ] @punctuation.special
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Extra tree-sitter grammars for the chat TUI, on top of OpenTUI's five
3
+ * bundled ones (javascript, typescript, markdown, zig). Without these, every
4
+ * fenced code block and every diff/file-review pane in a non-js/ts language
5
+ * renders unhighlighted.
6
+ *
7
+ * Each entry pairs a prebuilt `.wasm` parser with its co-versioned
8
+ * `highlights.scm` query. `scripts/fetch-grammars.ts` vendors both from the
9
+ * same npm package into ./assets and records the versions in manifest.json —
10
+ * grammar and query MUST match or `Query` compilation throws at runtime.
11
+ *
12
+ * ── Why the `with { type: 'file' }` imports ──────────────────────────────
13
+ * The chat TUI always runs under Bun (the `chat` command re-execs itself
14
+ * under Bun before it touches OpenTUI). Under Bun these imports resolve to a
15
+ * real filesystem path in dev, and `bun build --compile` embeds each asset
16
+ * into the binary's virtual filesystem and rewrites the path to `/$bunfs`.
17
+ * OpenTUI loads its own bundled grammars exactly this way.
18
+ *
19
+ * Rolldown (tsdown, the npm build) CANNOT parse `.wasm`/`.scm` as modules, so
20
+ * this file is externalized in tsdown.config.mts and copied verbatim into
21
+ * dist/js/chat/tui/chunks/grammars/ alongside its assets; the bundled
22
+ * bin.mjs reaches it through a dynamic import that Bun resolves at runtime.
23
+ * Keep every asset reference a static `with { type: 'file' }` import so the
24
+ * compiled binary discovers and embeds them — a runtime `Bun.file(path)` on
25
+ * a computed path would not be embedded.
26
+ */
27
+ import type { FiletypeParserOptions } from '@opentui/core';
28
+
29
+ import python_wasm from './assets/python.wasm' with { type: 'file' };
30
+ import python_scm from './assets/python.highlights.scm' with { type: 'file' };
31
+ import bash_wasm from './assets/bash.wasm' with { type: 'file' };
32
+ import bash_scm from './assets/bash.highlights.scm' with { type: 'file' };
33
+ import go_wasm from './assets/go.wasm' with { type: 'file' };
34
+ import go_scm from './assets/go.highlights.scm' with { type: 'file' };
35
+ import rust_wasm from './assets/rust.wasm' with { type: 'file' };
36
+ import rust_scm from './assets/rust.highlights.scm' with { type: 'file' };
37
+ import c_wasm from './assets/c.wasm' with { type: 'file' };
38
+ import c_scm from './assets/c.highlights.scm' with { type: 'file' };
39
+ import cpp_wasm from './assets/cpp.wasm' with { type: 'file' };
40
+ import cpp_scm from './assets/cpp.highlights.scm' with { type: 'file' };
41
+ import java_wasm from './assets/java.wasm' with { type: 'file' };
42
+ import java_scm from './assets/java.highlights.scm' with { type: 'file' };
43
+ import ruby_wasm from './assets/ruby.wasm' with { type: 'file' };
44
+ import ruby_scm from './assets/ruby.highlights.scm' with { type: 'file' };
45
+ import css_wasm from './assets/css.wasm' with { type: 'file' };
46
+ import css_scm from './assets/css.highlights.scm' with { type: 'file' };
47
+ import html_wasm from './assets/html.wasm' with { type: 'file' };
48
+ import html_scm from './assets/html.highlights.scm' with { type: 'file' };
49
+ import json_wasm from './assets/json.wasm' with { type: 'file' };
50
+ import json_scm from './assets/json.highlights.scm' with { type: 'file' };
51
+ import yaml_wasm from './assets/yaml.wasm' with { type: 'file' };
52
+ import yaml_scm from './assets/yaml.highlights.scm' with { type: 'file' };
53
+ import toml_wasm from './assets/toml.wasm' with { type: 'file' };
54
+ import toml_scm from './assets/toml.highlights.scm' with { type: 'file' };
55
+ import lua_wasm from './assets/lua.wasm' with { type: 'file' };
56
+ import lua_scm from './assets/lua.highlights.scm' with { type: 'file' };
57
+
58
+ /**
59
+ * `aliases` are the alternate names a code fence or file extension may use
60
+ * for the language (```sh → bash, ```py → python). OpenTUI's markdown
61
+ * injection resolver looks up a fence's info-string against each parser's
62
+ * registered aliases, so listing them here is what makes ```sh highlight.
63
+ * The canonical `filetype` need not be repeated in its own alias list.
64
+ */
65
+ export const EXTRA_GRAMMARS: FiletypeParserOptions[] = [
66
+ {
67
+ filetype: 'python',
68
+ aliases: ['py', 'python3'],
69
+ wasm: python_wasm,
70
+ queries: { highlights: [python_scm] },
71
+ },
72
+ {
73
+ filetype: 'bash',
74
+ aliases: ['sh', 'shell', 'zsh', 'shellscript'],
75
+ wasm: bash_wasm,
76
+ queries: { highlights: [bash_scm] },
77
+ },
78
+ {
79
+ filetype: 'go',
80
+ aliases: ['golang'],
81
+ wasm: go_wasm,
82
+ queries: { highlights: [go_scm] },
83
+ },
84
+ {
85
+ filetype: 'rust',
86
+ aliases: ['rs'],
87
+ wasm: rust_wasm,
88
+ queries: { highlights: [rust_scm] },
89
+ },
90
+ {
91
+ filetype: 'c',
92
+ aliases: ['h'],
93
+ wasm: c_wasm,
94
+ queries: { highlights: [c_scm] },
95
+ },
96
+ {
97
+ filetype: 'cpp',
98
+ aliases: ['c++', 'cc', 'cxx', 'hpp', 'hxx', 'hh'],
99
+ wasm: cpp_wasm,
100
+ queries: { highlights: [cpp_scm] },
101
+ },
102
+ {
103
+ filetype: 'java',
104
+ wasm: java_wasm,
105
+ queries: { highlights: [java_scm] },
106
+ },
107
+ {
108
+ filetype: 'ruby',
109
+ aliases: ['rb'],
110
+ wasm: ruby_wasm,
111
+ queries: { highlights: [ruby_scm] },
112
+ },
113
+ {
114
+ filetype: 'css',
115
+ wasm: css_wasm,
116
+ queries: { highlights: [css_scm] },
117
+ },
118
+ {
119
+ filetype: 'html',
120
+ aliases: ['htm'],
121
+ wasm: html_wasm,
122
+ queries: { highlights: [html_scm] },
123
+ },
124
+ {
125
+ filetype: 'json',
126
+ aliases: ['jsonc'],
127
+ wasm: json_wasm,
128
+ queries: { highlights: [json_scm] },
129
+ },
130
+ {
131
+ filetype: 'yaml',
132
+ aliases: ['yml'],
133
+ wasm: yaml_wasm,
134
+ queries: { highlights: [yaml_scm] },
135
+ },
136
+ {
137
+ filetype: 'toml',
138
+ wasm: toml_wasm,
139
+ queries: { highlights: [toml_scm] },
140
+ },
141
+ {
142
+ filetype: 'lua',
143
+ wasm: lua_wasm,
144
+ queries: { highlights: [lua_scm] },
145
+ },
146
+ ];
@@ -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 { x as getConfigPath } from "./print-Cd-bVSEJ.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";
11
+ var version$1 = "0.4.0";
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-Cd-bVSEJ.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";
@@ -153,6 +154,21 @@ function resolveSession(opts) {
153
154
  appUrl
154
155
  });
155
156
  }
157
+ function resolveChatAuth(opts) {
158
+ const session = resolveSession({ appUrl: opts.appUrl });
159
+ if (session.isOk()) return ok({
160
+ token: session.value.sessionToken,
161
+ appUrl: session.value.appUrl,
162
+ kind: "session"
163
+ });
164
+ const apiKey = process.env["SKYDIVE_API_KEY"] ?? store.get("apiKey");
165
+ if (apiKey) return ok({
166
+ token: apiKey,
167
+ appUrl: process.env["SKYDIVE_APP_URL"] ?? opts.appUrl ?? store.get("apiUrl") ?? process.env["SKYDIVE_API_URL"] ?? DEFAULT_APP_URL,
168
+ kind: "api-key"
169
+ });
170
+ return err({ message: "Not signed in. Run `skydive auth login` first." });
171
+ }
156
172
  function saveSession(session) {
157
173
  store.set("sessionToken", session.sessionToken);
158
174
  store.set("sessionObtainedAt", (/* @__PURE__ */ new Date()).toISOString());
@@ -175,6 +191,10 @@ function saveTheme(mode, themeId) {
175
191
  function getShareMachineDefault() {
176
192
  return store.get("shareMachineDefault") ?? false;
177
193
  }
194
+ /** Test-only setter; production writes happen by editing config.json. */
195
+ function saveShareMachineDefault(value) {
196
+ store.set("shareMachineDefault", value);
197
+ }
178
198
  /**
179
199
  * Whether the update check is disabled via config.json (`"updateCheck":
180
200
  * false`). The persistent counterpart to the SKYDIVE_NO_UPDATE_CHECK /
@@ -184,6 +204,52 @@ function getShareMachineDefault() {
184
204
  function getUpdateCheckDisabled() {
185
205
  return store.get("updateCheck") === false;
186
206
  }
207
+ /** Test-only setter; production writes happen by editing config.json. */
208
+ function saveUpdateCheck(value) {
209
+ if (value === void 0) {
210
+ store.delete("updateCheck");
211
+ return;
212
+ }
213
+ store.set("updateCheck", value);
214
+ }
215
+ function parseBoolean(raw) {
216
+ const v = raw.trim().toLowerCase();
217
+ if ([
218
+ "true",
219
+ "1",
220
+ "yes",
221
+ "on"
222
+ ].includes(v)) return ok(true);
223
+ if ([
224
+ "false",
225
+ "0",
226
+ "no",
227
+ "off"
228
+ ].includes(v)) return ok(false);
229
+ return err(`Expected a boolean (true/false), got "${raw}".`);
230
+ }
231
+ const PREFERENCES = [{
232
+ key: "shareMachineDefault",
233
+ type: "boolean",
234
+ describe: "Share this machine over the portal on `skydive chat` launch, as if --share-machine were passed. Default false.",
235
+ read: () => getShareMachineDefault(),
236
+ isSet: () => store.has("shareMachineDefault"),
237
+ parse: parseBoolean,
238
+ write: (value) => saveShareMachineDefault(value),
239
+ clear: () => store.delete("shareMachineDefault")
240
+ }, {
241
+ key: "updateCheck",
242
+ type: "boolean",
243
+ describe: "Run the daily background update check and its \"Update available\" notice. Set false to disable. Default true.",
244
+ read: () => !getUpdateCheckDisabled(),
245
+ isSet: () => store.has("updateCheck"),
246
+ parse: parseBoolean,
247
+ write: (value) => saveUpdateCheck(value),
248
+ clear: () => store.delete("updateCheck")
249
+ }];
250
+ function getPreference(key) {
251
+ return PREFERENCES.find((p) => p.key === key);
252
+ }
187
253
 
188
254
  //#endregion
189
255
  //#region src/chat/tui/chat/card.ts
@@ -557,6 +623,16 @@ async function runPrint({ appUrl, sessionToken, prompt, agentSelector, conversat
557
623
  * actionable copy the interactive TUI shows instead of an obtuse blob.
558
624
  */
559
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
+ }
560
636
  if (err instanceof HttpError && err.status >= 500) {
561
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}` : "";
562
638
  return /* @__PURE__ */ new Error(`The request to Skydive timed out at the edge (HTTP ${err.status}).${recovery}`);
@@ -575,9 +651,11 @@ async function collectRunText({ client, appUrl, target, onText, messageIdForHint
575
651
  let text = "";
576
652
  const controller = new AbortController();
577
653
  let streamError = null;
654
+ let billingBlocked = null;
578
655
  const connectCards = [];
579
656
  const onEvent = (event) => {
580
657
  if (event.kind === "finished") {
658
+ if (event.outcome) billingBlocked = event.outcome;
581
659
  if (event.error) streamError = event.error;
582
660
  return;
583
661
  }
@@ -608,6 +686,10 @@ async function collectRunText({ client, appUrl, target, onText, messageIdForHint
608
686
  } catch (err) {
609
687
  throw toPrintError(err, messageIdForHint);
610
688
  }
689
+ if (billingBlocked) throw new BillingBlockedError(billingBlocked, {
690
+ partialText: text || null,
691
+ messageId: messageIdForHint
692
+ });
611
693
  if (streamError) throw new Error(streamError);
612
694
  return {
613
695
  text,
@@ -677,4 +759,4 @@ async function readStdin() {
677
759
  }
678
760
 
679
761
  //#endregion
680
- export { resolveAppUrl as A, getPromptHistoryPath as C, getStoredApiKeyId as D, getShareMachineDefault as E, saveConfig as F, saveSession as I, saveTheme as L, resolveManagementAuth as M, resolveSession as N, getStoredApiKeyWorkspaceName as O, resolveWebUrl as P, setLastSeenVersion as R, getLastSeenVersion as S, getSavedTheme as T, API_KEY_PREFIX as _, runPrint as a, deleteConfig as b, cardActionErrorMessage as c, reconcileMaskedInput as d, resolveConnectUrl as f, API_KEY_FAMILY_PREFIX as g, API_KEYS_URL as h, resolveAgent as i, resolveConfig as j, getUpdateCheckDisabled as k, parseExternalOauthConnectParams as l, specKeyFor as m, messageGet as n, toPrintError as o, parseConnectCard as p, readStdin as r, MASK_CHAR as s, collectRunText as t, parseOauthConnectParams as u, DEFAULT_API_URL as v, getReviewStateDir as w, getConfigPath as x, DEFAULT_APP_URL as y };
762
+ export { getStoredApiKeyWorkspaceName as A, saveTheme as B, getLastSeenVersion as C, getSavedTheme as D, getReviewStateDir as E, resolveManagementAuth as F, resolveSession as I, resolveWebUrl as L, resolveAppUrl as M, resolveChatAuth as N, getShareMachineDefault as O, resolveConfig as P, saveConfig as R, getConfigPath as S, getPromptHistoryPath as T, setLastSeenVersion as V, API_KEY_PREFIX as _, runPrint as a, PREFERENCES as b, cardActionErrorMessage as c, reconcileMaskedInput as d, resolveConnectUrl as f, API_KEY_FAMILY_PREFIX as g, API_KEYS_URL as h, resolveAgent as i, getUpdateCheckDisabled as j, getStoredApiKeyId as k, parseExternalOauthConnectParams as l, specKeyFor as m, messageGet as n, toPrintError as o, parseConnectCard as p, readStdin as r, MASK_CHAR as s, collectRunText as t, parseOauthConnectParams as u, DEFAULT_API_URL as v, getPreference as w, deleteConfig as x, DEFAULT_APP_URL as y, saveSession as z };
@@ -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",
3
+ "version": "0.4.0",
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 };