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.
- package/CHANGELOG.md +27 -0
- package/README.md +28 -2
- package/dist/js/billing-blocked-CwfG1BTR.mjs +71 -0
- package/dist/js/billing-blocked-euid6MN9.mjs +4 -0
- package/dist/js/bin.mjs +247 -89
- package/dist/js/{boot-HAgDg_b4.mjs → boot-on5ucI_Z.mjs} +228 -50
- package/dist/js/chat/tui/chunks/grammars/assets/bash.highlights.scm +56 -0
- package/dist/js/chat/tui/chunks/grammars/assets/bash.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/c.highlights.scm +81 -0
- package/dist/js/chat/tui/chunks/grammars/assets/c.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/cpp.highlights.scm +70 -0
- package/dist/js/chat/tui/chunks/grammars/assets/cpp.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/css.highlights.scm +76 -0
- package/dist/js/chat/tui/chunks/grammars/assets/css.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/go.highlights.scm +123 -0
- package/dist/js/chat/tui/chunks/grammars/assets/go.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/html.highlights.scm +13 -0
- package/dist/js/chat/tui/chunks/grammars/assets/html.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/java.highlights.scm +149 -0
- package/dist/js/chat/tui/chunks/grammars/assets/java.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/json.highlights.scm +16 -0
- package/dist/js/chat/tui/chunks/grammars/assets/json.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/lua.highlights.scm +201 -0
- package/dist/js/chat/tui/chunks/grammars/assets/lua.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/python.highlights.scm +137 -0
- package/dist/js/chat/tui/chunks/grammars/assets/python.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/ruby.highlights.scm +154 -0
- package/dist/js/chat/tui/chunks/grammars/assets/ruby.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/rust.highlights.scm +161 -0
- package/dist/js/chat/tui/chunks/grammars/assets/rust.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/toml.highlights.scm +53 -0
- package/dist/js/chat/tui/chunks/grammars/assets/toml.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/assets/yaml.highlights.scm +79 -0
- package/dist/js/chat/tui/chunks/grammars/assets/yaml.wasm +0 -0
- package/dist/js/chat/tui/chunks/grammars/grammars.ts +146 -0
- package/dist/js/{client-Dc7GZ3PG.mjs → client-CKzK-12y.mjs} +1 -1
- package/dist/js/client-D6apKmV0.mjs +6 -0
- package/dist/js/daemon-BADmpJAs.mjs +7 -0
- package/dist/js/{daemon-Co4CtpXZ.mjs → daemon-CaFz7Wtw.mjs} +2 -2
- package/dist/js/{install-CMYBFvR2.mjs → install-Ba-UTi-l.mjs} +2 -2
- package/dist/js/{print-CPCFci60.mjs → print-BXNq9UxE.mjs} +3 -2
- package/dist/js/{print-Cd-bVSEJ.mjs → print-X2N5wJ5l.mjs} +84 -2
- package/dist/js/{print-share-7qfpQtWK.mjs → print-share-D72CfWJk.mjs} +1 -1
- package/dist/js/{raw-pty-BcjbTjHJ.mjs → raw-pty-DAmb8uqt.mjs} +1 -1
- package/dist/js/raw-pty-t5DC-e1T.mjs +5 -0
- package/dist/js/rest-Br2eFTlj.mjs +5 -0
- package/dist/js/{rest-BlN_uWmL.mjs → rest-imDZZGQA.mjs} +10 -2
- package/package.json +1 -1
- package/dist/js/client-DuwxEDG4.mjs +0 -5
- package/dist/js/daemon-Ch_MSDmQ.mjs +0 -6
- package/dist/js/raw-pty-ChUHav4d.mjs +0 -5
- package/dist/js/rest-CDTXCmUb.mjs +0 -4
- /package/dist/js/{client-DfcJFEbh.mjs → client-D8s9vY4p.mjs} +0 -0
|
@@ -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-
|
|
3
|
-
import {
|
|
4
|
-
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { t as
|
|
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-Ba-UTi-l.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 { i as billingBlockedOutcomeFromSendResponse } from "./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";
|
|
@@ -16,7 +17,7 @@ import { execFile, spawn } from "node:child_process";
|
|
|
16
17
|
import { createHash, randomUUID } from "node:crypto";
|
|
17
18
|
import { connect, createConnection } from "node:net";
|
|
18
19
|
import { access, appendFile, mkdir, mkdtemp, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
19
|
-
import { MarkdownRenderable, RenderableEvents, StyledText, SyntaxStyle, createCliRenderer, decodePasteBytes, detectLinks, fg, link } from "@opentui/core";
|
|
20
|
+
import { MarkdownRenderable, RenderableEvents, StyledText, SyntaxStyle, addDefaultParsers, createCliRenderer, decodePasteBytes, detectLinks, fg, link } from "@opentui/core";
|
|
20
21
|
import { createRoot, extend, useKeyboard, usePaste, useRenderer, useTerminalDimensions } from "@opentui/react";
|
|
21
22
|
import { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
22
23
|
import { create } from "zustand";
|
|
@@ -69,6 +70,7 @@ const useStore = create((set, get) => ({
|
|
|
69
70
|
themeLocked: false,
|
|
70
71
|
appUrl: null,
|
|
71
72
|
sessionToken: null,
|
|
73
|
+
authKind: "session",
|
|
72
74
|
workspaceName: null,
|
|
73
75
|
rest: null,
|
|
74
76
|
promptHistoryPath: null,
|
|
@@ -437,10 +439,11 @@ function createPortalClient(opts) {
|
|
|
437
439
|
* user turns sharing on from the chat screen. Detaching on unmount leaves the
|
|
438
440
|
* daemon running for any other attached CLIs.
|
|
439
441
|
*/
|
|
440
|
-
function usePortal({ appUrl, sessionToken, shareMachine }) {
|
|
442
|
+
function usePortal({ appUrl, sessionToken, shareMachine, enabled = true }) {
|
|
441
443
|
const syncPortal = useStore((s) => s.syncPortal);
|
|
442
444
|
const setPortalClient = useStore((s) => s.setPortalClient);
|
|
443
445
|
useEffect(() => {
|
|
446
|
+
if (!enabled) return;
|
|
444
447
|
const client = createPortalClient({
|
|
445
448
|
appUrl,
|
|
446
449
|
sessionToken,
|
|
@@ -463,6 +466,7 @@ function usePortal({ appUrl, sessionToken, shareMachine }) {
|
|
|
463
466
|
appUrl,
|
|
464
467
|
sessionToken,
|
|
465
468
|
shareMachine,
|
|
469
|
+
enabled,
|
|
466
470
|
syncPortal,
|
|
467
471
|
setPortalClient
|
|
468
472
|
]);
|
|
@@ -1687,8 +1691,13 @@ function AgentPickerScreen() {
|
|
|
1687
1691
|
const [cache, setCache] = useState({});
|
|
1688
1692
|
const [state, setState] = useState({ kind: "loading" });
|
|
1689
1693
|
useKeyboard((key) => {
|
|
1690
|
-
if (key.name === "w" && key.ctrl)
|
|
1691
|
-
|
|
1694
|
+
if (key.name === "w" && key.ctrl) {
|
|
1695
|
+
if (useStore.getState().authKind === "api-key") {
|
|
1696
|
+
useStore.getState().showToast({ message: "API keys are pinned to one workspace. Run `skydive auth login --web` to switch workspaces." });
|
|
1697
|
+
return;
|
|
1698
|
+
}
|
|
1699
|
+
goTo({ kind: "workspace-picker" });
|
|
1700
|
+
} else if (key.name === "n" && key.ctrl) goTo({ kind: "agent-create" });
|
|
1692
1701
|
else if (key.name === "tab") setScope((s) => s === "mine" ? "org" : "mine");
|
|
1693
1702
|
});
|
|
1694
1703
|
useEffect(() => {
|
|
@@ -1797,6 +1806,8 @@ function FilterableAgentList({ agents, scope, onPick }) {
|
|
|
1797
1806
|
useKeyboard((key) => {
|
|
1798
1807
|
if (key.name === "up") setHighlight(Math.max(0, clamped - 1));
|
|
1799
1808
|
else if (key.name === "down") setHighlight(Math.min(Math.max(0, filtered.length - 1), clamped + 1));
|
|
1809
|
+
else if (key.name === "pageup" || key.name === "pgup") setHighlight(Math.max(0, clamped - Math.max(1, visibleRows - 1)));
|
|
1810
|
+
else if (key.name === "pagedown" || key.name === "pgdn") setHighlight(Math.min(Math.max(0, filtered.length - 1), clamped + Math.max(1, visibleRows - 1)));
|
|
1800
1811
|
else if (key.name === "return") {
|
|
1801
1812
|
const agent = filtered[clamped];
|
|
1802
1813
|
if (!agent) return;
|
|
@@ -2269,6 +2280,31 @@ function CollapseHint() {
|
|
|
2269
2280
|
children: "· click to collapse"
|
|
2270
2281
|
});
|
|
2271
2282
|
}
|
|
2283
|
+
/** Collapsed line cap for tool error output. */
|
|
2284
|
+
const maxErrorLines = 8;
|
|
2285
|
+
/**
|
|
2286
|
+
* Tool error output, clamped like ok output: collapsed it clips to
|
|
2287
|
+
* `maxErrorLines` with the "+N more · click to expand" tail; expanded it
|
|
2288
|
+
* renders in full, word-wrapped. Same click-to-toggle box as the rest of
|
|
2289
|
+
* the block — a failing command's output shouldn't flood the scrollback
|
|
2290
|
+
* just because it arrived on the error channel.
|
|
2291
|
+
*/
|
|
2292
|
+
function ErrorLines({ text, expanded }) {
|
|
2293
|
+
if (expanded) return /* @__PURE__ */ jsx(ExpandedLines, {
|
|
2294
|
+
text,
|
|
2295
|
+
fg: theme.error
|
|
2296
|
+
});
|
|
2297
|
+
return /* @__PURE__ */ jsx("box", {
|
|
2298
|
+
style: { flexDirection: "column" },
|
|
2299
|
+
children: clipLines(text, {
|
|
2300
|
+
maxLines: maxErrorLines,
|
|
2301
|
+
maxLineLen: 100
|
|
2302
|
+
}).map((line, idx) => /* @__PURE__ */ jsx("text", {
|
|
2303
|
+
fg: theme.error,
|
|
2304
|
+
children: line
|
|
2305
|
+
}, idx))
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2272
2308
|
/** Indents tool output two columns under its header — no rule, just space. */
|
|
2273
2309
|
function Indented({ children }) {
|
|
2274
2310
|
return /* @__PURE__ */ jsx("box", {
|
|
@@ -2669,6 +2705,8 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
|
|
|
2669
2705
|
if (key.name === "escape") onPick({ kind: "agent-picker" });
|
|
2670
2706
|
else if (key.name === "up") setHighlight(Math.max(0, clamped - 1));
|
|
2671
2707
|
else if (key.name === "down") setHighlight(Math.min(Math.max(0, rows.length - 1), clamped + 1));
|
|
2708
|
+
else if (key.name === "pageup" || key.name === "pgup") setHighlight(Math.max(0, clamped - Math.max(1, visibleRows - 1)));
|
|
2709
|
+
else if (key.name === "pagedown" || key.name === "pgdn") setHighlight(Math.min(Math.max(0, rows.length - 1), clamped + Math.max(1, visibleRows - 1)));
|
|
2672
2710
|
else if (key.name === "d" && key.ctrl) {
|
|
2673
2711
|
const row = rows[clamped];
|
|
2674
2712
|
if (row?.kind === "conv") {
|
|
@@ -3056,8 +3094,13 @@ function syntaxStyleTable() {
|
|
|
3056
3094
|
"keyword.function": { fg: theme.syntaxMagenta },
|
|
3057
3095
|
"keyword.return": { fg: theme.syntaxMagenta },
|
|
3058
3096
|
"keyword.operator": { fg: theme.syntaxMagenta },
|
|
3097
|
+
conditional: { fg: theme.syntaxMagenta },
|
|
3098
|
+
repeat: { fg: theme.syntaxMagenta },
|
|
3099
|
+
preproc: { fg: theme.syntaxMagenta },
|
|
3059
3100
|
string: { fg: theme.syntaxGreen },
|
|
3060
3101
|
"string.special": { fg: theme.syntaxTeal },
|
|
3102
|
+
escape: { fg: theme.syntaxTeal },
|
|
3103
|
+
"string.escape": { fg: theme.syntaxTeal },
|
|
3061
3104
|
character: { fg: theme.syntaxGreen },
|
|
3062
3105
|
comment: {
|
|
3063
3106
|
fg: theme.dim,
|
|
@@ -3066,10 +3109,13 @@ function syntaxStyleTable() {
|
|
|
3066
3109
|
function: { fg: theme.syntaxBlue },
|
|
3067
3110
|
"function.method": { fg: theme.syntaxBlue },
|
|
3068
3111
|
"function.builtin": { fg: theme.syntaxCyan },
|
|
3112
|
+
method: { fg: theme.syntaxBlue },
|
|
3069
3113
|
variable: { fg: theme.fg },
|
|
3070
3114
|
"variable.builtin": { fg: theme.syntaxRed },
|
|
3071
3115
|
"variable.parameter": { fg: theme.syntaxYellow },
|
|
3072
3116
|
"variable.member": { fg: theme.syntaxTeal },
|
|
3117
|
+
parameter: { fg: theme.syntaxYellow },
|
|
3118
|
+
field: { fg: theme.syntaxTeal },
|
|
3073
3119
|
type: { fg: theme.syntaxCyan },
|
|
3074
3120
|
"type.builtin": { fg: theme.syntaxCyan },
|
|
3075
3121
|
constant: { fg: theme.syntaxOrange },
|
|
@@ -3084,6 +3130,7 @@ function syntaxStyleTable() {
|
|
|
3084
3130
|
"punctuation.bracket": { fg: theme.muted },
|
|
3085
3131
|
"punctuation.delimiter": { fg: theme.muted },
|
|
3086
3132
|
"punctuation.special": { fg: theme.syntaxCyan },
|
|
3133
|
+
delimiter: { fg: theme.muted },
|
|
3087
3134
|
constructor: { fg: theme.syntaxBlue },
|
|
3088
3135
|
module: { fg: theme.syntaxBlue },
|
|
3089
3136
|
label: { fg: theme.syntaxCyan },
|
|
@@ -3199,6 +3246,22 @@ function StatusLine({ item }) {
|
|
|
3199
3246
|
}
|
|
3200
3247
|
}
|
|
3201
3248
|
|
|
3249
|
+
//#endregion
|
|
3250
|
+
//#region src/chat/tui/chunks/system-notice-item.tsx
|
|
3251
|
+
/**
|
|
3252
|
+
* Platform system-notice row: the server stopped or refused work for a
|
|
3253
|
+
* platform reason (today: billing-blocked), so it reads as a warning-toned
|
|
3254
|
+
* notice — visually distinct from the ✗ transport/agent error row. The text
|
|
3255
|
+
* already carries the full guidance, produced server-side or derived from a
|
|
3256
|
+
* typed outcome by the producer that pushed the item.
|
|
3257
|
+
*/
|
|
3258
|
+
function SystemNoticeItem({ item }) {
|
|
3259
|
+
return /* @__PURE__ */ jsxs("text", {
|
|
3260
|
+
fg: theme.warning,
|
|
3261
|
+
children: ["◆ ", item.text.trim()]
|
|
3262
|
+
});
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3202
3265
|
//#endregion
|
|
3203
3266
|
//#region src/chat/tui/chunks/error-item.tsx
|
|
3204
3267
|
/**
|
|
@@ -3331,9 +3394,9 @@ function ToolGeneric({ item }) {
|
|
|
3331
3394
|
fg: theme.dim,
|
|
3332
3395
|
children: " · click to expand"
|
|
3333
3396
|
})]
|
|
3334
|
-
}) : /* @__PURE__ */ jsx(
|
|
3335
|
-
|
|
3336
|
-
|
|
3397
|
+
}) : /* @__PURE__ */ jsx(ErrorLines, {
|
|
3398
|
+
text: item.output.errorText,
|
|
3399
|
+
expanded
|
|
3337
3400
|
}) }) : null,
|
|
3338
3401
|
expanded && /* @__PURE__ */ jsx(Indented, { children: /* @__PURE__ */ jsx(CollapseHint, {}) })
|
|
3339
3402
|
]
|
|
@@ -3480,10 +3543,16 @@ function trimCommonIndent(hunks) {
|
|
|
3480
3543
|
for (const hunk of hunks) hunk.lines = hunk.lines.map((line) => isContentLine(line) ? line[0] + line.slice(1 + min) : line);
|
|
3481
3544
|
}
|
|
3482
3545
|
/**
|
|
3483
|
-
*
|
|
3484
|
-
*
|
|
3485
|
-
*
|
|
3486
|
-
*
|
|
3546
|
+
* Maps a file extension to the tree-sitter filetype used to highlight it in
|
|
3547
|
+
* diffs and the file/review pane. OpenTUI bundles parsers for
|
|
3548
|
+
* javascript(+react), typescript(+react), markdown, and zig; the rest are
|
|
3549
|
+
* registered by ./grammars. An extension absent here returns
|
|
3550
|
+
* undefined, which skips the highlight pass (the diff still renders red/green)
|
|
3551
|
+
* rather than asking the client for a parser it doesn't have.
|
|
3552
|
+
*
|
|
3553
|
+
* Keep the filetype values in sync with the canonical `filetype`/`aliases`
|
|
3554
|
+
* registered in ./grammars/grammars.ts — an extension mapping to a filetype no
|
|
3555
|
+
* parser is registered for just renders plain.
|
|
3487
3556
|
*/
|
|
3488
3557
|
const FILETYPE_BY_EXT = {
|
|
3489
3558
|
ts: "typescript",
|
|
@@ -3496,7 +3565,34 @@ const FILETYPE_BY_EXT = {
|
|
|
3496
3565
|
jsx: "javascriptreact",
|
|
3497
3566
|
md: "markdown",
|
|
3498
3567
|
markdown: "markdown",
|
|
3499
|
-
zig: "zig"
|
|
3568
|
+
zig: "zig",
|
|
3569
|
+
py: "python",
|
|
3570
|
+
pyi: "python",
|
|
3571
|
+
pyw: "python",
|
|
3572
|
+
sh: "bash",
|
|
3573
|
+
bash: "bash",
|
|
3574
|
+
zsh: "bash",
|
|
3575
|
+
go: "go",
|
|
3576
|
+
rs: "rust",
|
|
3577
|
+
c: "c",
|
|
3578
|
+
h: "c",
|
|
3579
|
+
cpp: "cpp",
|
|
3580
|
+
cxx: "cpp",
|
|
3581
|
+
cc: "cpp",
|
|
3582
|
+
hpp: "cpp",
|
|
3583
|
+
hxx: "cpp",
|
|
3584
|
+
hh: "cpp",
|
|
3585
|
+
java: "java",
|
|
3586
|
+
rb: "ruby",
|
|
3587
|
+
css: "css",
|
|
3588
|
+
html: "html",
|
|
3589
|
+
htm: "html",
|
|
3590
|
+
json: "json",
|
|
3591
|
+
jsonc: "json",
|
|
3592
|
+
yaml: "yaml",
|
|
3593
|
+
yml: "yaml",
|
|
3594
|
+
toml: "toml",
|
|
3595
|
+
lua: "lua"
|
|
3500
3596
|
};
|
|
3501
3597
|
function filetypeForPath(filePath) {
|
|
3502
3598
|
const base = filePath.split("/").pop() ?? filePath;
|
|
@@ -3711,10 +3807,10 @@ function ToolEdit({ item }) {
|
|
|
3711
3807
|
fg: theme.muted,
|
|
3712
3808
|
children: "(no changes)"
|
|
3713
3809
|
}) }) : null,
|
|
3714
|
-
item.output?.kind === "error" && /* @__PURE__ */
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
}) }),
|
|
3810
|
+
item.output?.kind === "error" && /* @__PURE__ */ jsxs(Indented, { children: [/* @__PURE__ */ jsx(ErrorLines, {
|
|
3811
|
+
text: item.output.errorText,
|
|
3812
|
+
expanded
|
|
3813
|
+
}), expanded && isClipped(item.output.errorText, maxErrorLines) && /* @__PURE__ */ jsx(CollapseHint, {})] }),
|
|
3718
3814
|
item.output?.kind === "ok" && pairs === null && inputReady && /* @__PURE__ */ jsx(Indented, { children: /* @__PURE__ */ jsx("text", {
|
|
3719
3815
|
fg: theme.muted,
|
|
3720
3816
|
children: summarize(item.output.value, 60)
|
|
@@ -3840,12 +3936,13 @@ function PlainDiff({ diff }) {
|
|
|
3840
3936
|
//#endregion
|
|
3841
3937
|
//#region src/chat/tui/chunks/tool-bash.tsx
|
|
3842
3938
|
const maxLines$1 = 8;
|
|
3939
|
+
const maxCommandLines = 3;
|
|
3843
3940
|
/**
|
|
3844
3941
|
* Rich view for the `bash`/`shell` tool. Leads with the model-authored
|
|
3845
3942
|
* summary when present (mirroring web chat's activity labels), with the
|
|
3846
3943
|
* command on its own dim line beneath; then its output
|
|
3847
3944
|
* (truncated to keep the scrollback usable — click the block to toggle the
|
|
3848
|
-
* full output
|
|
3945
|
+
* full command and output).
|
|
3849
3946
|
*/
|
|
3850
3947
|
function ToolBash({ item }) {
|
|
3851
3948
|
const glyph = toolGlyph(item.state);
|
|
@@ -3854,6 +3951,10 @@ function ToolBash({ item }) {
|
|
|
3854
3951
|
const output = item.output?.kind === "ok" ? typeof item.output.value === "string" ? item.output.value : extractStdout(item.output.value) : null;
|
|
3855
3952
|
const summary = getToolCallSummary(item.input);
|
|
3856
3953
|
const [expanded, setExpanded] = useState(false);
|
|
3954
|
+
const commandText = command || "(empty command)";
|
|
3955
|
+
const headerCommandLine = commandText.split("\n", 1)[0] ?? commandText;
|
|
3956
|
+
const commandBlockText = summary !== null ? `$ ${commandText}` : commandText.slice(headerCommandLine.length + 1);
|
|
3957
|
+
const showCommandBlock = commandBlockText.length > 0;
|
|
3857
3958
|
return /* @__PURE__ */ jsxs("box", {
|
|
3858
3959
|
style: {
|
|
3859
3960
|
flexDirection: "column",
|
|
@@ -3866,14 +3967,19 @@ function ToolBash({ item }) {
|
|
|
3866
3967
|
children: [glyph.ch, " "]
|
|
3867
3968
|
}), /* @__PURE__ */ jsx("span", {
|
|
3868
3969
|
fg: theme.tool,
|
|
3869
|
-
children: summary !== null ? summary : `$ ${
|
|
3970
|
+
children: summary !== null ? summary : `$ ${headerCommandLine}`
|
|
3870
3971
|
})] }),
|
|
3871
|
-
|
|
3972
|
+
showCommandBlock && /* @__PURE__ */ jsx(Indented, { children: expanded ? /* @__PURE__ */ jsx(ExpandedLines, {
|
|
3973
|
+
text: commandBlockText,
|
|
3974
|
+
fg: theme.muted
|
|
3975
|
+
}) : clipLines(commandBlockText, {
|
|
3976
|
+
maxLines: maxCommandLines,
|
|
3977
|
+
maxLineLen: 100
|
|
3978
|
+
}).map((line, idx) => /* @__PURE__ */ jsx("text", {
|
|
3872
3979
|
fg: theme.muted,
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
output !== null && output.length > 0 && /* @__PURE__ */ jsxs(Indented, { children: [expanded ? /* @__PURE__ */ jsx(ExpandedLines, {
|
|
3980
|
+
children: line
|
|
3981
|
+
}, idx)) }),
|
|
3982
|
+
output !== null && output.length > 0 && /* @__PURE__ */ jsx(Indented, { children: expanded ? /* @__PURE__ */ jsx(ExpandedLines, {
|
|
3877
3983
|
text: output,
|
|
3878
3984
|
fg: theme.muted
|
|
3879
3985
|
}) : clipLines(output, {
|
|
@@ -3882,11 +3988,12 @@ function ToolBash({ item }) {
|
|
|
3882
3988
|
}).map((line, idx) => /* @__PURE__ */ jsx("text", {
|
|
3883
3989
|
fg: theme.muted,
|
|
3884
3990
|
children: line
|
|
3885
|
-
}, idx))
|
|
3886
|
-
item.output?.kind === "error" && /* @__PURE__ */ jsx(Indented, { children: /* @__PURE__ */ jsx(
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
}) })
|
|
3991
|
+
}, idx)) }),
|
|
3992
|
+
item.output?.kind === "error" && /* @__PURE__ */ jsx(Indented, { children: /* @__PURE__ */ jsx(ErrorLines, {
|
|
3993
|
+
text: item.output.errorText,
|
|
3994
|
+
expanded
|
|
3995
|
+
}) }),
|
|
3996
|
+
expanded && (showCommandBlock && isClipped(commandBlockText, maxCommandLines) || output !== null && isClipped(output, maxLines$1) || item.output?.kind === "error" && isClipped(item.output.errorText, maxErrorLines)) && /* @__PURE__ */ jsx(Indented, { children: /* @__PURE__ */ jsx(CollapseHint, {}) })
|
|
3890
3997
|
]
|
|
3891
3998
|
});
|
|
3892
3999
|
}
|
|
@@ -3954,10 +4061,10 @@ function ToolRead({ item }) {
|
|
|
3954
4061
|
fg: theme.muted,
|
|
3955
4062
|
children: line
|
|
3956
4063
|
}, idx)), expanded && isClipped(preview, maxLines) && /* @__PURE__ */ jsx(CollapseHint, {})] }),
|
|
3957
|
-
item.output?.kind === "error" && /* @__PURE__ */
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
}) })
|
|
4064
|
+
item.output?.kind === "error" && /* @__PURE__ */ jsxs(Indented, { children: [/* @__PURE__ */ jsx(ErrorLines, {
|
|
4065
|
+
text: item.output.errorText,
|
|
4066
|
+
expanded
|
|
4067
|
+
}), expanded && isClipped(item.output.errorText, maxErrorLines) && /* @__PURE__ */ jsx(CollapseHint, {})] })
|
|
3961
4068
|
]
|
|
3962
4069
|
});
|
|
3963
4070
|
}
|
|
@@ -4038,10 +4145,10 @@ function ToolGrep({ item }) {
|
|
|
4038
4145
|
}),
|
|
4039
4146
|
expanded && matches.length > maxMatches && /* @__PURE__ */ jsx(CollapseHint, {})
|
|
4040
4147
|
] }),
|
|
4041
|
-
item.output?.kind === "error" && /* @__PURE__ */
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
}) })
|
|
4148
|
+
item.output?.kind === "error" && /* @__PURE__ */ jsxs(Indented, { children: [/* @__PURE__ */ jsx(ErrorLines, {
|
|
4149
|
+
text: item.output.errorText,
|
|
4150
|
+
expanded
|
|
4151
|
+
}), expanded && isClipped(item.output.errorText, maxErrorLines) && /* @__PURE__ */ jsx(CollapseHint, {})] })
|
|
4045
4152
|
]
|
|
4046
4153
|
});
|
|
4047
4154
|
}
|
|
@@ -4165,6 +4272,10 @@ function RenderItem({ item }) {
|
|
|
4165
4272
|
barColor: null,
|
|
4166
4273
|
children: /* @__PURE__ */ jsx(ErrorItem, { item })
|
|
4167
4274
|
});
|
|
4275
|
+
case "system-notice": return /* @__PURE__ */ jsx(Row, {
|
|
4276
|
+
barColor: null,
|
|
4277
|
+
children: /* @__PURE__ */ jsx(SystemNoticeItem, { item })
|
|
4278
|
+
});
|
|
4168
4279
|
case "card": return /* @__PURE__ */ jsx(Row, {
|
|
4169
4280
|
barColor: null,
|
|
4170
4281
|
children: /* @__PURE__ */ jsx(CardItem, { item })
|
|
@@ -4804,6 +4915,15 @@ function uiMessagesToItems(messages) {
|
|
|
4804
4915
|
const out = [];
|
|
4805
4916
|
for (const m of messages) {
|
|
4806
4917
|
if (m.role === "user") {
|
|
4918
|
+
const billingNotice = billingBlockedNoticeText(m.parts);
|
|
4919
|
+
if (billingNotice) {
|
|
4920
|
+
out.push({
|
|
4921
|
+
kind: "system-notice",
|
|
4922
|
+
id: m.id,
|
|
4923
|
+
text: billingNotice
|
|
4924
|
+
});
|
|
4925
|
+
continue;
|
|
4926
|
+
}
|
|
4807
4927
|
const text = m.parts.map((p) => p.type === "text" ? p.text : "").join("").trim();
|
|
4808
4928
|
const attachments = m.parts.filter((p) => p.type === "data-anyone-attachment").map((p) => {
|
|
4809
4929
|
const data = isRecord(p) && "data" in p && isRecord(p.data) ? p.data : null;
|
|
@@ -4898,6 +5018,14 @@ function uiMessagesToItems(messages) {
|
|
|
4898
5018
|
}
|
|
4899
5019
|
return out.map(clampItem);
|
|
4900
5020
|
}
|
|
5021
|
+
function billingBlockedNoticeText(parts) {
|
|
5022
|
+
for (const part of parts) {
|
|
5023
|
+
if (part.type !== "data-anyone-system-notification") continue;
|
|
5024
|
+
const data = isRecord(part) && isRecord(part.data) ? part.data : null;
|
|
5025
|
+
if (data && data.kind === "billing-blocked" && typeof data.text === "string" && data.text.trim()) return data.text;
|
|
5026
|
+
}
|
|
5027
|
+
return null;
|
|
5028
|
+
}
|
|
4901
5029
|
function mapToolState(raw) {
|
|
4902
5030
|
switch (raw) {
|
|
4903
5031
|
case "output-error": return "error";
|
|
@@ -5711,6 +5839,10 @@ const keybindGroups = [
|
|
|
5711
5839
|
keys: "↑ / ↓",
|
|
5712
5840
|
action: "move selection"
|
|
5713
5841
|
},
|
|
5842
|
+
{
|
|
5843
|
+
keys: "pgup / pgdn",
|
|
5844
|
+
action: "move selection a page at a time"
|
|
5845
|
+
},
|
|
5714
5846
|
{
|
|
5715
5847
|
keys: "↵",
|
|
5716
5848
|
action: "open agent"
|
|
@@ -5736,6 +5868,10 @@ const keybindGroups = [
|
|
|
5736
5868
|
keys: "↑ / ↓",
|
|
5737
5869
|
action: "move selection"
|
|
5738
5870
|
},
|
|
5871
|
+
{
|
|
5872
|
+
keys: "pgup / pgdn",
|
|
5873
|
+
action: "move selection a page at a time"
|
|
5874
|
+
},
|
|
5739
5875
|
{
|
|
5740
5876
|
keys: "↵",
|
|
5741
5877
|
action: "open conversation"
|
|
@@ -9651,8 +9787,14 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9651
9787
|
setItems((prev) => applyChunk(prev, event.chunk, streamAgentName));
|
|
9652
9788
|
return;
|
|
9653
9789
|
}
|
|
9790
|
+
const billingOutcome = event.outcome;
|
|
9654
9791
|
const errorText = event.error;
|
|
9655
|
-
if (
|
|
9792
|
+
if (billingOutcome) setItems((prev) => [...prev, {
|
|
9793
|
+
kind: "system-notice",
|
|
9794
|
+
id: crypto.randomUUID(),
|
|
9795
|
+
text: billingOutcome.message
|
|
9796
|
+
}]);
|
|
9797
|
+
else if (event.status !== "ok" && errorText) setItems((prev) => [...prev, {
|
|
9656
9798
|
kind: "error",
|
|
9657
9799
|
id: crypto.randomUUID(),
|
|
9658
9800
|
text: errorText
|
|
@@ -9787,7 +9929,15 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9787
9929
|
}
|
|
9788
9930
|
attachToRun(result.runId, result.agentName ?? null);
|
|
9789
9931
|
} catch (err) {
|
|
9790
|
-
|
|
9932
|
+
const billing = err instanceof HttpError ? billingBlockedOutcomeFromSendResponse({
|
|
9933
|
+
status: err.status,
|
|
9934
|
+
body: err.body
|
|
9935
|
+
}) : null;
|
|
9936
|
+
setItems((prev) => [...prev.filter((m) => m.id !== optimisticId), billing ? {
|
|
9937
|
+
kind: "system-notice",
|
|
9938
|
+
id: crypto.randomUUID(),
|
|
9939
|
+
text: billing.message
|
|
9940
|
+
} : {
|
|
9791
9941
|
kind: "error",
|
|
9792
9942
|
id: crypto.randomUUID(),
|
|
9793
9943
|
text: sendErrorMessage(err)
|
|
@@ -10434,7 +10584,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10434
10584
|
leaveForScreen
|
|
10435
10585
|
]);
|
|
10436
10586
|
const toggleShare = useCallback(() => {
|
|
10437
|
-
if (!portalClient)
|
|
10587
|
+
if (!portalClient) {
|
|
10588
|
+
useStore.getState().showToast({ message: useStore.getState().authKind === "api-key" ? "local access needs a browser session — run `skydive auth login --web`" : "local access is unavailable in this session" });
|
|
10589
|
+
return;
|
|
10590
|
+
}
|
|
10438
10591
|
if (portal.status === "off") {
|
|
10439
10592
|
declinedRef.current.delete(agent.id);
|
|
10440
10593
|
portalClient.enable();
|
|
@@ -10475,7 +10628,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
10475
10628
|
}, [agent.id, setPortalPrompt]);
|
|
10476
10629
|
const openPortalAccess = useCallback(() => {
|
|
10477
10630
|
if (!portalClient) {
|
|
10478
|
-
useStore.getState().showToast({ message: "local access is unavailable in this session" });
|
|
10631
|
+
useStore.getState().showToast({ message: useStore.getState().authKind === "api-key" ? "local access needs a browser session — run `skydive auth login --web`" : "local access is unavailable in this session" });
|
|
10479
10632
|
return;
|
|
10480
10633
|
}
|
|
10481
10634
|
switch (portal.status) {
|
|
@@ -11486,6 +11639,7 @@ function ToastView() {
|
|
|
11486
11639
|
maxWidth: Math.min(60, Math.max(20, width - 6)),
|
|
11487
11640
|
border: true,
|
|
11488
11641
|
borderColor: toastColor(toast.variant),
|
|
11642
|
+
backgroundColor: theme.surface ?? "#1a1a1a",
|
|
11489
11643
|
paddingLeft: 1,
|
|
11490
11644
|
paddingRight: 1
|
|
11491
11645
|
},
|
|
@@ -11499,7 +11653,7 @@ function ToastView() {
|
|
|
11499
11653
|
|
|
11500
11654
|
//#endregion
|
|
11501
11655
|
//#region src/chat/tui/app.tsx
|
|
11502
|
-
function App({ appUrl, sessionToken, shareMachine, promptHistoryPath, notifications, agentSelector, conversationId, newConversation }) {
|
|
11656
|
+
function App({ appUrl, sessionToken, authKind, shareMachine, promptHistoryPath, notifications, agentSelector, conversationId, newConversation }) {
|
|
11503
11657
|
const renderer = useRenderer();
|
|
11504
11658
|
const screen = useStore((s) => s.screen);
|
|
11505
11659
|
const chatTitle = useStore((s) => s.chatTitle);
|
|
@@ -11515,7 +11669,8 @@ function App({ appUrl, sessionToken, shareMachine, promptHistoryPath, notificati
|
|
|
11515
11669
|
usePortal({
|
|
11516
11670
|
appUrl,
|
|
11517
11671
|
sessionToken,
|
|
11518
|
-
shareMachine
|
|
11672
|
+
shareMachine,
|
|
11673
|
+
enabled: authKind === "session"
|
|
11519
11674
|
});
|
|
11520
11675
|
useEffect(() => {
|
|
11521
11676
|
agentHost.transition({ state: "idle" });
|
|
@@ -11543,6 +11698,7 @@ function App({ appUrl, sessionToken, shareMachine, promptHistoryPath, notificati
|
|
|
11543
11698
|
const fail = useStore((s) => s.fail);
|
|
11544
11699
|
const setWorkspaceName = useStore((s) => s.setWorkspaceName);
|
|
11545
11700
|
useEffect(() => {
|
|
11701
|
+
if (authKind !== "session") return;
|
|
11546
11702
|
let cancelled = false;
|
|
11547
11703
|
(async () => {
|
|
11548
11704
|
const [activeId, workspaces] = await Promise.all([getActiveWorkspaceId({
|
|
@@ -11561,6 +11717,7 @@ function App({ appUrl, sessionToken, shareMachine, promptHistoryPath, notificati
|
|
|
11561
11717
|
}, [
|
|
11562
11718
|
appUrl,
|
|
11563
11719
|
sessionToken,
|
|
11720
|
+
authKind,
|
|
11564
11721
|
setWorkspaceName
|
|
11565
11722
|
]);
|
|
11566
11723
|
useEffect(() => {
|
|
@@ -11899,6 +12056,24 @@ var LinkifiedMarkdownRenderable = class extends MarkdownRenderable {
|
|
|
11899
12056
|
}
|
|
11900
12057
|
};
|
|
11901
12058
|
|
|
12059
|
+
//#endregion
|
|
12060
|
+
//#region src/chat/tui/chunks/grammars/index.ts
|
|
12061
|
+
/**
|
|
12062
|
+
* Register the extra tree-sitter grammars (python, go, rust, bash, …) before
|
|
12063
|
+
* the renderer boots its tree-sitter client, so fenced code blocks and diffs
|
|
12064
|
+
* in those languages highlight instead of rendering as plain text.
|
|
12065
|
+
*
|
|
12066
|
+
* `addDefaultParsers` merges by filetype into the set the client registers on
|
|
12067
|
+
* init, so this must run BEFORE `createCliRenderer`. The grammar definitions
|
|
12068
|
+
* live in ./grammars.ts, which is externalized from the tsdown bundle (it
|
|
12069
|
+
* imports `.wasm`/`.scm` assets rolldown can't parse) — so we reach it through
|
|
12070
|
+
* a dynamic import that both Bun-runtime (npm) and the compiled binary resolve.
|
|
12071
|
+
*/
|
|
12072
|
+
async function registerGrammars() {
|
|
12073
|
+
const { EXTRA_GRAMMARS } = await import("./chat/tui/chunks/grammars/grammars.js");
|
|
12074
|
+
addDefaultParsers(EXTRA_GRAMMARS);
|
|
12075
|
+
}
|
|
12076
|
+
|
|
11902
12077
|
//#endregion
|
|
11903
12078
|
//#region src/chat/memory-watchdog.ts
|
|
11904
12079
|
const MB = 1024 * 1024;
|
|
@@ -12066,12 +12241,14 @@ async function settleBootThemeMode({ source, applyThemeMode, graceMs = THEME_QUE
|
|
|
12066
12241
|
* module — and the heavy OpenTUI dependency graph it pulls in — is
|
|
12067
12242
|
* dynamically imported and never loaded on the Node management path.
|
|
12068
12243
|
*/
|
|
12069
|
-
async function runChat({ appUrl, sessionToken, shareMachine, promptHistoryPath, theme: themeOverride, notifications, agentSelector, conversationId, newConversation, seedPrompt }) {
|
|
12244
|
+
async function runChat({ appUrl, sessionToken, authKind = "session", shareMachine, promptHistoryPath, theme: themeOverride, notifications, agentSelector, conversationId, newConversation, seedPrompt }) {
|
|
12245
|
+
await registerGrammars();
|
|
12070
12246
|
const watchdog = startMemoryWatchdog();
|
|
12071
12247
|
installCrashHandler({ memoryProvider: () => watchdog.snapshot() });
|
|
12072
12248
|
const renderer = await createCliRenderer({ exitOnCtrlC: false });
|
|
12073
12249
|
extend({ markdown: LinkifiedMarkdownRenderable });
|
|
12074
12250
|
useStore.setState({
|
|
12251
|
+
authKind,
|
|
12075
12252
|
seedPrompt: seedPrompt ?? null,
|
|
12076
12253
|
autoGrantMachine: Boolean(seedPrompt && shareMachine),
|
|
12077
12254
|
newConversationIntent: newConversation
|
|
@@ -12091,6 +12268,7 @@ async function runChat({ appUrl, sessionToken, shareMachine, promptHistoryPath,
|
|
|
12091
12268
|
createRoot(renderer).render(/* @__PURE__ */ jsx(App, {
|
|
12092
12269
|
appUrl,
|
|
12093
12270
|
sessionToken,
|
|
12271
|
+
authKind,
|
|
12094
12272
|
shareMachine,
|
|
12095
12273
|
promptHistoryPath,
|
|
12096
12274
|
notifications,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[
|
|
2
|
+
(string)
|
|
3
|
+
(raw_string)
|
|
4
|
+
(heredoc_body)
|
|
5
|
+
(heredoc_start)
|
|
6
|
+
] @string
|
|
7
|
+
|
|
8
|
+
(command_name) @function
|
|
9
|
+
|
|
10
|
+
(variable_name) @property
|
|
11
|
+
|
|
12
|
+
[
|
|
13
|
+
"case"
|
|
14
|
+
"do"
|
|
15
|
+
"done"
|
|
16
|
+
"elif"
|
|
17
|
+
"else"
|
|
18
|
+
"esac"
|
|
19
|
+
"export"
|
|
20
|
+
"fi"
|
|
21
|
+
"for"
|
|
22
|
+
"function"
|
|
23
|
+
"if"
|
|
24
|
+
"in"
|
|
25
|
+
"select"
|
|
26
|
+
"then"
|
|
27
|
+
"unset"
|
|
28
|
+
"until"
|
|
29
|
+
"while"
|
|
30
|
+
] @keyword
|
|
31
|
+
|
|
32
|
+
(comment) @comment
|
|
33
|
+
|
|
34
|
+
(function_definition name: (word) @function)
|
|
35
|
+
|
|
36
|
+
(file_descriptor) @number
|
|
37
|
+
|
|
38
|
+
[
|
|
39
|
+
(command_substitution)
|
|
40
|
+
(process_substitution)
|
|
41
|
+
(expansion)
|
|
42
|
+
]@embedded
|
|
43
|
+
|
|
44
|
+
[
|
|
45
|
+
"$"
|
|
46
|
+
"&&"
|
|
47
|
+
">"
|
|
48
|
+
">>"
|
|
49
|
+
"<"
|
|
50
|
+
"|"
|
|
51
|
+
] @operator
|
|
52
|
+
|
|
53
|
+
(
|
|
54
|
+
(command (_) @constant)
|
|
55
|
+
(#match? @constant "^-")
|
|
56
|
+
)
|
|
Binary file
|