skydive-cli 0.4.0-beta.1173 → 0.4.0-beta.1319
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/js/bin.mjs +17 -17
- package/dist/js/{boot-e-aTvP3w.mjs → boot-COm0nT7p.mjs} +396 -60
- package/dist/js/client-BhdMLYEe.mjs +6 -0
- package/dist/js/{client-DiaJZQG6.mjs → client-C5O0ZhxP.mjs} +1 -1
- package/dist/js/{daemon-BSSZpzto.mjs → daemon-CgLbaJ9_.mjs} +2 -2
- package/dist/js/{daemon-ybnlDUgi.mjs → daemon-qBD3Zd-l.mjs} +3 -3
- package/dist/js/{print-CswnhVUN.mjs → print-DA8WzgzH.mjs} +1 -1
- package/dist/js/{print-LoJjA8FM.mjs → print-DwQoTays.mjs} +2 -2
- package/dist/js/{print-share-DCmeJC5e.mjs → print-share-FHUrtd8x.mjs} +1 -1
- package/dist/js/{profiler-BgGRyc5q.mjs → profiler-C4l07OBf.mjs} +2 -2
- package/dist/js/{rest-CG7VpQ56.mjs → rest-CtEF_ZDf.mjs} +12 -0
- package/dist/js/{rest-DfpoRJ_Q.mjs → rest-aXwyxWX0.mjs} +1 -1
- package/package.json +1 -1
- package/dist/js/client-BpAnESuq.mjs +0 -6
package/dist/js/bin.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-
|
|
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-
|
|
2
|
+
import { C as ensureActiveOrganization, D as setActiveWorkspace, E as listWorkspaces, O as name, T as getSessionIdentity, a as installCrashHandler, k as version, t as maybeStartProfiling, u as brandHelpArt, w as getActiveWorkspaceId, x as themes } from "./profiler-C4l07OBf.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-DA8WzgzH.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-
|
|
5
|
+
import { n as createRestClient, t as HttpError } from "./rest-CtEF_ZDf.mjs";
|
|
6
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-
|
|
8
|
-
import { c as PORTAL_DAEMON_FLAG, i as queryDaemonStatus, l as daemonPaths, n as ensureDaemonRunning, o as stopDaemon } from "./daemon-
|
|
7
|
+
import { a as registerPortalDevice, i as grantPortalAccess, n as fetchPortalDevices, o as revokePortalAccess, r as findThisDevice, s as machineIdentity } from "./client-C5O0ZhxP.mjs";
|
|
8
|
+
import { c as PORTAL_DAEMON_FLAG, i as queryDaemonStatus, l as daemonPaths, n as ensureDaemonRunning, o as stopDaemon } from "./daemon-CgLbaJ9_.mjs";
|
|
9
9
|
import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
|
|
10
10
|
import { hideBin } from "yargs/helpers";
|
|
11
11
|
import yargs from "yargs";
|
|
@@ -1514,7 +1514,7 @@ const importCommand = {
|
|
|
1514
1514
|
process.exit(1);
|
|
1515
1515
|
}
|
|
1516
1516
|
}
|
|
1517
|
-
const { runChat } = await import("./boot-
|
|
1517
|
+
const { runChat } = await import("./boot-COm0nT7p.mjs");
|
|
1518
1518
|
await runChat({
|
|
1519
1519
|
appUrl,
|
|
1520
1520
|
sessionToken: session.value.sessionToken,
|
|
@@ -1541,7 +1541,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1541
1541
|
printError(`${session.error.message} For non-interactive use, run \`skydive auth login --web\` first, or set SKYDIVE_SESSION_TOKEN.`);
|
|
1542
1542
|
process.exit(1);
|
|
1543
1543
|
}
|
|
1544
|
-
const { connectMachineShare } = await import("./print-share-
|
|
1544
|
+
const { connectMachineShare } = await import("./print-share-FHUrtd8x.mjs");
|
|
1545
1545
|
const machineShare = await connectMachineShare({
|
|
1546
1546
|
appUrl,
|
|
1547
1547
|
sessionToken: session.value.sessionToken,
|
|
@@ -1549,7 +1549,7 @@ async function runImportPrintMode({ argv, appUrl }) {
|
|
|
1549
1549
|
});
|
|
1550
1550
|
const extra = (argv.print ?? "").trim();
|
|
1551
1551
|
const prompt = buildImportSeedPrompt(process.cwd()) + (extra ? `\n\nAdditional instructions: ${extra}` : "");
|
|
1552
|
-
const { runPrint } = await import("./print-
|
|
1552
|
+
const { runPrint } = await import("./print-DwQoTays.mjs");
|
|
1553
1553
|
try {
|
|
1554
1554
|
const result = await runPrint({
|
|
1555
1555
|
appUrl,
|
|
@@ -1926,7 +1926,7 @@ const chatCommand = {
|
|
|
1926
1926
|
sessionToken: auth.value.token,
|
|
1927
1927
|
agentSelector: argv.agent ?? null
|
|
1928
1928
|
});
|
|
1929
|
-
const { runChat } = await import("./boot-
|
|
1929
|
+
const { runChat } = await import("./boot-COm0nT7p.mjs");
|
|
1930
1930
|
await runChat({
|
|
1931
1931
|
appUrl: auth.value.appUrl,
|
|
1932
1932
|
sessionToken: auth.value.token,
|
|
@@ -1993,7 +1993,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
1993
1993
|
printError(`${auth.error.message} For non-interactive use, run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
1994
1994
|
process.exit(1);
|
|
1995
1995
|
}
|
|
1996
|
-
const { runPrint, readStdin } = await import("./print-
|
|
1996
|
+
const { runPrint, readStdin } = await import("./print-DwQoTays.mjs");
|
|
1997
1997
|
await ensureAgentWorkspace({
|
|
1998
1998
|
appUrl,
|
|
1999
1999
|
sessionToken: auth.value.token,
|
|
@@ -2018,7 +2018,7 @@ async function runPrintMode({ argv, appUrl }) {
|
|
|
2018
2018
|
process.exit(1);
|
|
2019
2019
|
}
|
|
2020
2020
|
} else {
|
|
2021
|
-
const { connectMachineShare } = await import("./print-share-
|
|
2021
|
+
const { connectMachineShare } = await import("./print-share-FHUrtd8x.mjs");
|
|
2022
2022
|
machineShare = await connectMachineShare({
|
|
2023
2023
|
appUrl: auth.value.appUrl,
|
|
2024
2024
|
sessionToken: auth.value.token,
|
|
@@ -2082,7 +2082,7 @@ const getCommand$1 = {
|
|
|
2082
2082
|
printError(`${auth.error.message} Run \`skydive auth login\` first, or set SKYDIVE_API_KEY / SKYDIVE_SESSION_TOKEN.`);
|
|
2083
2083
|
process.exit(1);
|
|
2084
2084
|
}
|
|
2085
|
-
const { messageGet } = await import("./print-
|
|
2085
|
+
const { messageGet } = await import("./print-DwQoTays.mjs");
|
|
2086
2086
|
try {
|
|
2087
2087
|
const result = await messageGet({
|
|
2088
2088
|
appUrl: auth.value.appUrl,
|
|
@@ -2285,7 +2285,7 @@ const switchCommand = {
|
|
|
2285
2285
|
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.");
|
|
2286
2286
|
process.exit(1);
|
|
2287
2287
|
}
|
|
2288
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
2288
|
+
const { runWorkspacePicker } = await import("./boot-COm0nT7p.mjs");
|
|
2289
2289
|
await runWorkspacePicker(session);
|
|
2290
2290
|
return;
|
|
2291
2291
|
}
|
|
@@ -2363,7 +2363,7 @@ const openCommand = {
|
|
|
2363
2363
|
const agent = argv.agent ? resolveAgent((await fetchPortalDevices(session)).agents, argv.agent) : null;
|
|
2364
2364
|
const cwd = argv.cwd ? path.resolve(argv.cwd) : process.cwd();
|
|
2365
2365
|
const { machineName } = machineIdentity();
|
|
2366
|
-
const { PortalClient } = await import("./client-
|
|
2366
|
+
const { PortalClient } = await import("./client-BhdMLYEe.mjs");
|
|
2367
2367
|
let lastLine = "";
|
|
2368
2368
|
let signalConnected;
|
|
2369
2369
|
const connected = new Promise((resolve) => {
|
|
@@ -2636,8 +2636,8 @@ const sandboxCommand = {
|
|
|
2636
2636
|
}).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`"),
|
|
2637
2637
|
handler: async (argv) => {
|
|
2638
2638
|
const session = requireSession(argv);
|
|
2639
|
-
const { createRestClient } = await import("./rest-
|
|
2640
|
-
const { resolveAgent } = await import("./print-
|
|
2639
|
+
const { createRestClient } = await import("./rest-aXwyxWX0.mjs");
|
|
2640
|
+
const { resolveAgent } = await import("./print-DwQoTays.mjs");
|
|
2641
2641
|
const client = createRestClient({
|
|
2642
2642
|
appUrl: session.appUrl,
|
|
2643
2643
|
sessionToken: session.sessionToken
|
|
@@ -3896,7 +3896,7 @@ if (process.argv.includes(UPDATE_WORKER_FLAG)) {
|
|
|
3896
3896
|
process.exit(0);
|
|
3897
3897
|
}
|
|
3898
3898
|
if (process.argv.includes(PORTAL_DAEMON_FLAG)) {
|
|
3899
|
-
const { runPortalDaemon } = await import("./daemon-
|
|
3899
|
+
const { runPortalDaemon } = await import("./daemon-qBD3Zd-l.mjs");
|
|
3900
3900
|
runPortalDaemon(process.argv);
|
|
3901
3901
|
} else runCli();
|
|
3902
3902
|
function runCli() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-
|
|
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-
|
|
4
|
-
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-
|
|
2
|
+
import { D as setActiveWorkspace, E as listWorkspaces, S as themesForMode, _ as themeForMode, a as installCrashHandler, b as themeVersion, c as MARK_CELLS, d as DEFAULT_THEME_ID, f as applyTheme, g as theme, h as noColorRequested, i as writeArtifact, l as WORDMARK, m as monoTheme, n as profilingEnabled, o as buildCrashReport, p as findTheme, r as record, s as writeCrashReport, v as themeMode, w as getActiveWorkspaceId, y as themeModeFromColorFgBg } from "./profiler-C4l07OBf.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-DA8WzgzH.mjs";
|
|
4
|
+
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-CtEF_ZDf.mjs";
|
|
5
5
|
import { i as billingBlockedOutcomeFromSendResponse } from "./billing-blocked-CwfG1BTR.mjs";
|
|
6
|
-
import { t as PortalClient } from "./client-
|
|
7
|
-
import { d as makeLineParser, f as parseDaemonMessage, l as daemonPaths, n as ensureDaemonRunning, s as LOCAL_PROTOCOL_VERSION, u as encodeLine } from "./daemon-
|
|
6
|
+
import { t as PortalClient } from "./client-C5O0ZhxP.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-CgLbaJ9_.mjs";
|
|
8
8
|
import { t as SandboxStream } from "./client-D8s9vY4p.mjs";
|
|
9
9
|
import { t as runRawPtyPassthrough } from "./raw-pty-DAmb8uqt.mjs";
|
|
10
10
|
import * as os$1 from "node:os";
|
|
@@ -48,6 +48,58 @@ function toastColor(variant) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/chat/tui/early-input.ts
|
|
53
|
+
/**
|
|
54
|
+
* Buffering for keystrokes typed BEFORE the chat composer exists.
|
|
55
|
+
*
|
|
56
|
+
* When the CLI boots straight into a conversation (`skydive chat --new`, or a
|
|
57
|
+
* seeded `skydive import`), it must resolve the agent roster over the network
|
|
58
|
+
* before the chat screen — and its composer — can mount. During that window
|
|
59
|
+
* the splash screen is up and there is no textarea to receive input, so a user
|
|
60
|
+
* who starts typing immediately would lose every character.
|
|
61
|
+
*
|
|
62
|
+
* These helpers accumulate that early input as plain text; the chat screen
|
|
63
|
+
* drains it into the composer on mount so nothing typed during the load is
|
|
64
|
+
* dropped. This is deliberately a text buffer, not a queue of key events: the
|
|
65
|
+
* composer is a plain single-field editor here, so replaying the resulting
|
|
66
|
+
* string (via `composer.setText`) reproduces exactly what the user meant to
|
|
67
|
+
* type, and stays trivially unit-testable without an OpenTUI renderer.
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* Whether a key is an ordinary printable character we should buffer as text.
|
|
71
|
+
*
|
|
72
|
+
* Excludes anything with a modifier (ctrl/meta/super/hyper — those are
|
|
73
|
+
* shortcuts, not text) and any named non-character key (enter, arrows, tab,
|
|
74
|
+
* escape, function keys, …). A printable stroke arrives with its character in
|
|
75
|
+
* `sequence` and a `name` that is that same single character (or empty for
|
|
76
|
+
* some symbols), never a multi-letter key name like `return`/`backspace`.
|
|
77
|
+
*/
|
|
78
|
+
function isTextKey(key) {
|
|
79
|
+
if (key.ctrl || key.meta || key.super || key.hyper) return false;
|
|
80
|
+
const seq = key.sequence;
|
|
81
|
+
if (seq.length !== 1) return false;
|
|
82
|
+
const code = seq.codePointAt(0);
|
|
83
|
+
if (code === void 0) return false;
|
|
84
|
+
if (code < 32 || code === 127) return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
/** Whether a key is Backspace/Delete-left (erase one buffered character). */
|
|
88
|
+
function isBackspaceKey(key) {
|
|
89
|
+
return !key.ctrl && !key.meta && key.name === "backspace";
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fold one key into the early-input buffer. Printable characters append,
|
|
93
|
+
* backspace erases the last character, everything else (enter, arrows,
|
|
94
|
+
* shortcuts) is ignored — we only reconstruct the draft text, not caret moves
|
|
95
|
+
* or submission, which the real composer owns once it takes over.
|
|
96
|
+
*/
|
|
97
|
+
function reduceEarlyInput(buffer, key) {
|
|
98
|
+
if (isTextKey(key)) return buffer + key.sequence;
|
|
99
|
+
if (isBackspaceKey(key)) return buffer.slice(0, -1);
|
|
100
|
+
return buffer;
|
|
101
|
+
}
|
|
102
|
+
|
|
51
103
|
//#endregion
|
|
52
104
|
//#region src/chat/state/store.ts
|
|
53
105
|
const initialPortalUi = {
|
|
@@ -81,6 +133,7 @@ const useStore = create((set, get) => ({
|
|
|
81
133
|
seedPrompt: null,
|
|
82
134
|
autoGrantMachine: false,
|
|
83
135
|
newConversationIntent: false,
|
|
136
|
+
earlyInput: "",
|
|
84
137
|
goTo: (screen) => set({
|
|
85
138
|
screen,
|
|
86
139
|
chatTitle: initialChatTitle(screen)
|
|
@@ -138,7 +191,16 @@ const useStore = create((set, get) => ({
|
|
|
138
191
|
prompt
|
|
139
192
|
} })),
|
|
140
193
|
showToast: (input) => set({ toast: createToast(input) }),
|
|
141
|
-
dismissToast: (id) => set((state) => state.toast?.id === id ? { toast: null } : {})
|
|
194
|
+
dismissToast: (id) => set((state) => state.toast?.id === id ? { toast: null } : {}),
|
|
195
|
+
appendEarlyInput: (key) => set((state) => {
|
|
196
|
+
const next = reduceEarlyInput(state.earlyInput, key);
|
|
197
|
+
return next === state.earlyInput ? {} : { earlyInput: next };
|
|
198
|
+
}),
|
|
199
|
+
takeEarlyInput: () => {
|
|
200
|
+
const { earlyInput } = get();
|
|
201
|
+
if (earlyInput !== "") set({ earlyInput: "" });
|
|
202
|
+
return earlyInput;
|
|
203
|
+
}
|
|
142
204
|
}));
|
|
143
205
|
|
|
144
206
|
//#endregion
|
|
@@ -1472,7 +1534,7 @@ function StatusBar({ rightHint }) {
|
|
|
1472
1534
|
const portal = useStore((s) => s.portal);
|
|
1473
1535
|
const left = headerLeftLabel(appUrl, workspaceName);
|
|
1474
1536
|
const middle = screenLabel(screen, chatTitle);
|
|
1475
|
-
const share = portalIndicator(portal);
|
|
1537
|
+
const share = portalIndicator(portal, screenAgentId(screen));
|
|
1476
1538
|
return /* @__PURE__ */ jsxs("box", {
|
|
1477
1539
|
style: {
|
|
1478
1540
|
flexDirection: "row",
|
|
@@ -1504,23 +1566,40 @@ function StatusBar({ rightHint }) {
|
|
|
1504
1566
|
]
|
|
1505
1567
|
});
|
|
1506
1568
|
}
|
|
1507
|
-
|
|
1569
|
+
/**
|
|
1570
|
+
* The share indicator, which answers exactly one question: can the agent on
|
|
1571
|
+
* screen run commands on this machine right now? Not "is the portal
|
|
1572
|
+
* connected" — the connection is a per-machine fact, access is per agent, and
|
|
1573
|
+
* a badge that tracks the former tells a user who just declined that the agent
|
|
1574
|
+
* is in.
|
|
1575
|
+
*
|
|
1576
|
+
* So it is scoped to the current agent and shown only once that agent holds a
|
|
1577
|
+
* grant. Everything else — no agent on screen, portal off, connected but this
|
|
1578
|
+
* agent ungranted, still connecting — renders as the off state (nothing), which
|
|
1579
|
+
* is the truthful reading: this agent cannot reach the machine.
|
|
1580
|
+
*
|
|
1581
|
+
* The one exception is an error, and only for an agent that IS granted: its
|
|
1582
|
+
* access is supposed to be live and isn't, which the user needs to see.
|
|
1583
|
+
*/
|
|
1584
|
+
function portalIndicator(portal, agentId) {
|
|
1585
|
+
if (!agentId || !portal.grantedAgentIds.includes(agentId)) return null;
|
|
1508
1586
|
switch (portal.status) {
|
|
1509
|
-
case "off":
|
|
1510
|
-
case "connecting": return
|
|
1511
|
-
text: "◌ sharing…",
|
|
1512
|
-
color: theme.warning
|
|
1513
|
-
};
|
|
1587
|
+
case "off":
|
|
1588
|
+
case "connecting": return null;
|
|
1514
1589
|
case "connected": return {
|
|
1515
|
-
text: "● machine
|
|
1590
|
+
text: "● machine connected",
|
|
1516
1591
|
color: theme.success
|
|
1517
1592
|
};
|
|
1518
1593
|
case "error": return {
|
|
1519
|
-
text: "●
|
|
1594
|
+
text: "● machine error",
|
|
1520
1595
|
color: theme.error
|
|
1521
1596
|
};
|
|
1522
1597
|
}
|
|
1523
1598
|
}
|
|
1599
|
+
/** The agent whose access the indicator speaks for, if a screen names one. */
|
|
1600
|
+
function screenAgentId(screen) {
|
|
1601
|
+
return screen.kind === "chat" || screen.kind === "conversation-picker" ? screen.agent.id : null;
|
|
1602
|
+
}
|
|
1524
1603
|
/**
|
|
1525
1604
|
* The per-screen label, split into its parts: the screen's own `title` and,
|
|
1526
1605
|
* when the screen belongs to an agent, that `agentName`. Kept structured so the
|
|
@@ -4223,6 +4302,292 @@ function parseMatches(output) {
|
|
|
4223
4302
|
return null;
|
|
4224
4303
|
}
|
|
4225
4304
|
|
|
4305
|
+
//#endregion
|
|
4306
|
+
//#region src/chat/tui/chat/conversation-context.tsx
|
|
4307
|
+
const ConversationContext = createContext({
|
|
4308
|
+
rest: null,
|
|
4309
|
+
conversationId: null
|
|
4310
|
+
});
|
|
4311
|
+
function useConversationContext() {
|
|
4312
|
+
return useContext(ConversationContext);
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
//#endregion
|
|
4316
|
+
//#region src/chat/tui/spinner-frames.ts
|
|
4317
|
+
/** Braille dot-cycle frames — the classic smooth terminal spinner. */
|
|
4318
|
+
const SPINNER_FRAMES = [
|
|
4319
|
+
"⠋",
|
|
4320
|
+
"⠙",
|
|
4321
|
+
"⠹",
|
|
4322
|
+
"⠸",
|
|
4323
|
+
"⠼",
|
|
4324
|
+
"⠴",
|
|
4325
|
+
"⠦",
|
|
4326
|
+
"⠧",
|
|
4327
|
+
"⠇",
|
|
4328
|
+
"⠏"
|
|
4329
|
+
];
|
|
4330
|
+
/** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
|
|
4331
|
+
const SPINNER_INTERVAL_MS = 80;
|
|
4332
|
+
/** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
|
|
4333
|
+
function spinnerFrame(tick) {
|
|
4334
|
+
const n = SPINNER_FRAMES.length;
|
|
4335
|
+
return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
4336
|
+
}
|
|
4337
|
+
|
|
4338
|
+
//#endregion
|
|
4339
|
+
//#region src/chat/tui/spinner.tsx
|
|
4340
|
+
/**
|
|
4341
|
+
* An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
|
|
4342
|
+
* a self-owned interval that's cleared on unmount, so the animation runs only
|
|
4343
|
+
* while the component is mounted. Returns a <span>, so render it inside a
|
|
4344
|
+
* <text> (matching how the rest of the TUI composes inline glyphs).
|
|
4345
|
+
*/
|
|
4346
|
+
function Spinner({ color }) {
|
|
4347
|
+
const [tick, setTick] = useState(0);
|
|
4348
|
+
useEffect(() => {
|
|
4349
|
+
const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
|
|
4350
|
+
return () => clearInterval(id);
|
|
4351
|
+
}, []);
|
|
4352
|
+
return /* @__PURE__ */ jsx("span", {
|
|
4353
|
+
fg: color,
|
|
4354
|
+
children: spinnerFrame(tick)
|
|
4355
|
+
});
|
|
4356
|
+
}
|
|
4357
|
+
|
|
4358
|
+
//#endregion
|
|
4359
|
+
//#region src/chat/tui/chat/subagents.ts
|
|
4360
|
+
/** A run the platform hasn't settled yet — still queued or mid-run. */
|
|
4361
|
+
function isLiveStatus(status) {
|
|
4362
|
+
return status === "queued" || status === "running";
|
|
4363
|
+
}
|
|
4364
|
+
function toTaskStatus(raw) {
|
|
4365
|
+
switch (raw) {
|
|
4366
|
+
case "queued":
|
|
4367
|
+
case "running":
|
|
4368
|
+
case "completed":
|
|
4369
|
+
case "failed":
|
|
4370
|
+
case "canceled": return raw;
|
|
4371
|
+
default: return "queued";
|
|
4372
|
+
}
|
|
4373
|
+
}
|
|
4374
|
+
const FALLBACK_TITLE = "Subagent task";
|
|
4375
|
+
/**
|
|
4376
|
+
* Each delegated task's display title from the `subagent` call's input, in
|
|
4377
|
+
* call order — the short name the tool requires per task. A malformed entry
|
|
4378
|
+
* yields a fallback label rather than being dropped, so the row count always
|
|
4379
|
+
* matches the fan-out width. Mirrors the web client's `subagentTaskTitles`.
|
|
4380
|
+
*/
|
|
4381
|
+
function subagentTaskTitles(input) {
|
|
4382
|
+
if (!isRecord(input)) return [];
|
|
4383
|
+
const tasks = input["tasks"];
|
|
4384
|
+
if (!Array.isArray(tasks)) return [];
|
|
4385
|
+
return tasks.map((task) => {
|
|
4386
|
+
if (!isRecord(task)) return FALLBACK_TITLE;
|
|
4387
|
+
const title = task["title"];
|
|
4388
|
+
return typeof title === "string" && title.trim() ? title.trim() : FALLBACK_TITLE;
|
|
4389
|
+
});
|
|
4390
|
+
}
|
|
4391
|
+
const QUEUED_TASK_ID_LINE = /^\s*-\s*([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}):\s/i;
|
|
4392
|
+
/**
|
|
4393
|
+
* The ids of the runs a `subagent` call queued, read back out of its own
|
|
4394
|
+
* output. The call returns the moment the runs exist, so the ids are there
|
|
4395
|
+
* long before any child finishes — they are what ties this card to the task
|
|
4396
|
+
* rows the status poll returns, and their order is the tasks' call order.
|
|
4397
|
+
*/
|
|
4398
|
+
function queuedSubagentTaskIds(output) {
|
|
4399
|
+
const text = flattenOutputText(output);
|
|
4400
|
+
if (!text) return [];
|
|
4401
|
+
return text.split("\n").map((line) => line.match(QUEUED_TASK_ID_LINE)?.[1] ?? null).filter((id) => id !== null);
|
|
4402
|
+
}
|
|
4403
|
+
/**
|
|
4404
|
+
* Tool output reaches the TUI as `unknown`: the raw string live, possibly
|
|
4405
|
+
* wrapped in content parts or arrays when loaded from history. Walk it for
|
|
4406
|
+
* string leaves, newline-joined — the PR scanner's `stringifyToolOutput`
|
|
4407
|
+
* shape, bounded small because the id list sits at the top of the output.
|
|
4408
|
+
*/
|
|
4409
|
+
function flattenOutputText(value) {
|
|
4410
|
+
const MAX_LEN = 2e4;
|
|
4411
|
+
const parts = [];
|
|
4412
|
+
let total = 0;
|
|
4413
|
+
const visit = (v, depth) => {
|
|
4414
|
+
if (total >= MAX_LEN || depth > 4) return;
|
|
4415
|
+
if (typeof v === "string") {
|
|
4416
|
+
parts.push(v);
|
|
4417
|
+
total += v.length;
|
|
4418
|
+
return;
|
|
4419
|
+
}
|
|
4420
|
+
if (Array.isArray(v)) {
|
|
4421
|
+
for (const item of v) visit(item, depth + 1);
|
|
4422
|
+
return;
|
|
4423
|
+
}
|
|
4424
|
+
if (isRecord(v)) for (const item of Object.values(v)) visit(item, depth + 1);
|
|
4425
|
+
};
|
|
4426
|
+
visit(value, 0);
|
|
4427
|
+
return parts.join("\n");
|
|
4428
|
+
}
|
|
4429
|
+
/**
|
|
4430
|
+
* The card's rows: one per queued run id (call order), each carrying the
|
|
4431
|
+
* freshest known state. A task the status fetch hasn't returned yet falls
|
|
4432
|
+
* back to the input's title and reads as queued; a fetched row's own title
|
|
4433
|
+
* wins over the input's (the server's copy is the one the child actually
|
|
4434
|
+
* ran under). Before the ids exist — the call is still streaming — rows come
|
|
4435
|
+
* from the input titles alone, so the card never renders empty mid-turn.
|
|
4436
|
+
*/
|
|
4437
|
+
function subagentRows({ titles, ids, fetched }) {
|
|
4438
|
+
if (ids.length === 0) return titles.map((title, index) => ({
|
|
4439
|
+
id: `queued:${index}`,
|
|
4440
|
+
title,
|
|
4441
|
+
status: "queued",
|
|
4442
|
+
createdAt: null,
|
|
4443
|
+
completedAt: null
|
|
4444
|
+
}));
|
|
4445
|
+
return ids.map((id, index) => {
|
|
4446
|
+
const row = fetched?.get(id) ?? null;
|
|
4447
|
+
return {
|
|
4448
|
+
id,
|
|
4449
|
+
title: row?.title ?? titles[index] ?? FALLBACK_TITLE,
|
|
4450
|
+
status: row ? toTaskStatus(row.status) : "queued",
|
|
4451
|
+
createdAt: row?.createdAt ?? null,
|
|
4452
|
+
completedAt: row?.completedAt ?? null
|
|
4453
|
+
};
|
|
4454
|
+
});
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
//#endregion
|
|
4458
|
+
//#region src/chat/tui/chunks/tool-subagent.tsx
|
|
4459
|
+
/** How often a live batch re-reads its tasks' status. */
|
|
4460
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
4461
|
+
function rowGlyph(status) {
|
|
4462
|
+
switch (status) {
|
|
4463
|
+
case "completed": return {
|
|
4464
|
+
ch: "✔",
|
|
4465
|
+
fg: theme.success
|
|
4466
|
+
};
|
|
4467
|
+
case "failed":
|
|
4468
|
+
case "canceled": return {
|
|
4469
|
+
ch: "✗",
|
|
4470
|
+
fg: theme.error
|
|
4471
|
+
};
|
|
4472
|
+
case "running": return {
|
|
4473
|
+
ch: "▶",
|
|
4474
|
+
fg: theme.accent
|
|
4475
|
+
};
|
|
4476
|
+
case "queued": return {
|
|
4477
|
+
ch: "○",
|
|
4478
|
+
fg: theme.dim
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
4481
|
+
}
|
|
4482
|
+
function rowColor$1(status) {
|
|
4483
|
+
switch (status) {
|
|
4484
|
+
case "running": return theme.fg;
|
|
4485
|
+
case "completed": return theme.dim;
|
|
4486
|
+
default: return theme.muted;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
function headerLabel(rows) {
|
|
4490
|
+
const subject = rows.length === 1 ? "Subagent" : `${rows.length} subagents`;
|
|
4491
|
+
return rows.some((row) => isLiveStatus(row.status)) ? `${subject} running` : subject;
|
|
4492
|
+
}
|
|
4493
|
+
/**
|
|
4494
|
+
* The transcript block for a `subagent` tool call — the TUI analog of the web
|
|
4495
|
+
* chat's fan-out card. One row per delegated run: status glyph, the short
|
|
4496
|
+
* title the delegating agent wrote, ticking over live as children settle.
|
|
4497
|
+
*
|
|
4498
|
+
* Rows are seeded from the call itself (titles from its input, task ids from
|
|
4499
|
+
* its own output), so the card renders the moment the call does. Status then
|
|
4500
|
+
* comes from the server's task rows, polled while any run is live — the
|
|
4501
|
+
* delegated runs outlive the call that spawned them, so the transcript stream
|
|
4502
|
+
* carries nothing more about them. The poll stops the moment the batch
|
|
4503
|
+
* settles; reopening an old conversation does one fetch and stops there. A
|
|
4504
|
+
* failed poll is skipped silently (the next tick retries; stale rows beat an
|
|
4505
|
+
* error row in the scrollback).
|
|
4506
|
+
*/
|
|
4507
|
+
function ToolSubagent({ item }) {
|
|
4508
|
+
const { rest, conversationId } = useConversationContext();
|
|
4509
|
+
const titles = subagentTaskTitles(item.input);
|
|
4510
|
+
const ids = item.output?.kind === "ok" ? queuedSubagentTaskIds(item.output.value) : [];
|
|
4511
|
+
const idsKey = ids.join(",");
|
|
4512
|
+
const [fetched, setFetched] = useState(null);
|
|
4513
|
+
const rows = subagentRows({
|
|
4514
|
+
titles,
|
|
4515
|
+
ids,
|
|
4516
|
+
fetched
|
|
4517
|
+
});
|
|
4518
|
+
const live = rows.length === 0 || rows.some((row) => isLiveStatus(row.status));
|
|
4519
|
+
useEffect(() => {
|
|
4520
|
+
if (!rest || !conversationId || idsKey.length === 0 || !live) return;
|
|
4521
|
+
let cancelled = false;
|
|
4522
|
+
let timer = null;
|
|
4523
|
+
const tick = async () => {
|
|
4524
|
+
try {
|
|
4525
|
+
const tasks = await rest.listSubagentTasks({ conversationId });
|
|
4526
|
+
if (cancelled) return;
|
|
4527
|
+
setFetched(tasks);
|
|
4528
|
+
} catch (_error) {}
|
|
4529
|
+
if (!cancelled) timer = setTimeout(tick, POLL_INTERVAL_MS);
|
|
4530
|
+
};
|
|
4531
|
+
tick();
|
|
4532
|
+
return () => {
|
|
4533
|
+
cancelled = true;
|
|
4534
|
+
if (timer !== null) clearTimeout(timer);
|
|
4535
|
+
};
|
|
4536
|
+
}, [
|
|
4537
|
+
rest,
|
|
4538
|
+
conversationId,
|
|
4539
|
+
idsKey,
|
|
4540
|
+
live
|
|
4541
|
+
]);
|
|
4542
|
+
if (rows.length === 0) return /* @__PURE__ */ jsxs("text", { children: [/* @__PURE__ */ jsx("span", {
|
|
4543
|
+
fg: theme.warning,
|
|
4544
|
+
children: "◐ "
|
|
4545
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4546
|
+
fg: theme.tool,
|
|
4547
|
+
children: "Delegating to subagents…"
|
|
4548
|
+
})] });
|
|
4549
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4550
|
+
style: { flexDirection: "column" },
|
|
4551
|
+
children: [/* @__PURE__ */ jsxs("text", { children: [
|
|
4552
|
+
live ? /* @__PURE__ */ jsx(Spinner, { color: theme.accent }) : /* @__PURE__ */ jsx("span", {
|
|
4553
|
+
fg: theme.success,
|
|
4554
|
+
children: "✓"
|
|
4555
|
+
}),
|
|
4556
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4557
|
+
fg: theme.tool,
|
|
4558
|
+
children: [" ", /* @__PURE__ */ jsx("b", { children: headerLabel(rows) })]
|
|
4559
|
+
}),
|
|
4560
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4561
|
+
fg: theme.dim,
|
|
4562
|
+
children: [
|
|
4563
|
+
" ",
|
|
4564
|
+
rows.filter((row) => row.status === "completed").length,
|
|
4565
|
+
"/",
|
|
4566
|
+
rows.length
|
|
4567
|
+
]
|
|
4568
|
+
})
|
|
4569
|
+
] }), /* @__PURE__ */ jsx("box", {
|
|
4570
|
+
style: {
|
|
4571
|
+
flexDirection: "column",
|
|
4572
|
+
paddingLeft: 2
|
|
4573
|
+
},
|
|
4574
|
+
children: rows.map((row) => {
|
|
4575
|
+
const glyph = rowGlyph(row.status);
|
|
4576
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4577
|
+
style: { flexDirection: "row" },
|
|
4578
|
+
children: [/* @__PURE__ */ jsxs("text", {
|
|
4579
|
+
fg: glyph.fg,
|
|
4580
|
+
children: [glyph.ch, " "]
|
|
4581
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
4582
|
+
fg: rowColor$1(row.status),
|
|
4583
|
+
children: row.title
|
|
4584
|
+
})]
|
|
4585
|
+
}, row.id);
|
|
4586
|
+
})
|
|
4587
|
+
})]
|
|
4588
|
+
});
|
|
4589
|
+
}
|
|
4590
|
+
|
|
4226
4591
|
//#endregion
|
|
4227
4592
|
//#region src/chat/tui/chunks/shell-local.tsx
|
|
4228
4593
|
/**
|
|
@@ -4446,6 +4811,7 @@ function ToolItem({ item }) {
|
|
|
4446
4811
|
case "read": return /* @__PURE__ */ jsx(ToolRead, { item });
|
|
4447
4812
|
case "grep":
|
|
4448
4813
|
case "glob": return /* @__PURE__ */ jsx(ToolGrep, { item });
|
|
4814
|
+
case "subagent": return /* @__PURE__ */ jsx(ToolSubagent, { item });
|
|
4449
4815
|
default: return /* @__PURE__ */ jsx(ToolGeneric, { item });
|
|
4450
4816
|
}
|
|
4451
4817
|
}
|
|
@@ -5786,49 +6152,6 @@ function createResponsePreview() {
|
|
|
5786
6152
|
};
|
|
5787
6153
|
}
|
|
5788
6154
|
|
|
5789
|
-
//#endregion
|
|
5790
|
-
//#region src/chat/tui/spinner-frames.ts
|
|
5791
|
-
/** Braille dot-cycle frames — the classic smooth terminal spinner. */
|
|
5792
|
-
const SPINNER_FRAMES = [
|
|
5793
|
-
"⠋",
|
|
5794
|
-
"⠙",
|
|
5795
|
-
"⠹",
|
|
5796
|
-
"⠸",
|
|
5797
|
-
"⠼",
|
|
5798
|
-
"⠴",
|
|
5799
|
-
"⠦",
|
|
5800
|
-
"⠧",
|
|
5801
|
-
"⠇",
|
|
5802
|
-
"⠏"
|
|
5803
|
-
];
|
|
5804
|
-
/** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
|
|
5805
|
-
const SPINNER_INTERVAL_MS = 80;
|
|
5806
|
-
/** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
|
|
5807
|
-
function spinnerFrame(tick) {
|
|
5808
|
-
const n = SPINNER_FRAMES.length;
|
|
5809
|
-
return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
5810
|
-
}
|
|
5811
|
-
|
|
5812
|
-
//#endregion
|
|
5813
|
-
//#region src/chat/tui/spinner.tsx
|
|
5814
|
-
/**
|
|
5815
|
-
* An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
|
|
5816
|
-
* a self-owned interval that's cleared on unmount, so the animation runs only
|
|
5817
|
-
* while the component is mounted. Returns a <span>, so render it inside a
|
|
5818
|
-
* <text> (matching how the rest of the TUI composes inline glyphs).
|
|
5819
|
-
*/
|
|
5820
|
-
function Spinner({ color }) {
|
|
5821
|
-
const [tick, setTick] = useState(0);
|
|
5822
|
-
useEffect(() => {
|
|
5823
|
-
const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
|
|
5824
|
-
return () => clearInterval(id);
|
|
5825
|
-
}, []);
|
|
5826
|
-
return /* @__PURE__ */ jsx("span", {
|
|
5827
|
-
fg: color,
|
|
5828
|
-
children: spinnerFrame(tick)
|
|
5829
|
-
});
|
|
5830
|
-
}
|
|
5831
|
-
|
|
5832
6155
|
//#endregion
|
|
5833
6156
|
//#region src/chat/tui/prompt-history.ts
|
|
5834
6157
|
/**
|
|
@@ -9930,7 +10253,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
9930
10253
|
hadTodosRef.current = hasTodos;
|
|
9931
10254
|
}, [todos]);
|
|
9932
10255
|
const [historyLoaded, setHistoryLoaded] = useState(initialConversationId === null);
|
|
9933
|
-
const [input, setInput] = useState(
|
|
10256
|
+
const [input, setInput] = useState(() => useStore.getState().takeEarlyInput());
|
|
9934
10257
|
const [run, setRun] = useState({ kind: "idle" });
|
|
9935
10258
|
const [model, setModel] = useState(agent.model ?? null);
|
|
9936
10259
|
const [cardPickerOpen, setCardPickerOpen] = useState(false);
|
|
@@ -11477,6 +11800,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11477
11800
|
}
|
|
11478
11801
|
});
|
|
11479
11802
|
const hasPendingSteer = items.some((m) => m.kind === "pending-steer");
|
|
11803
|
+
const conversationContext = useMemo(() => ({
|
|
11804
|
+
rest,
|
|
11805
|
+
conversationId
|
|
11806
|
+
}), [rest, conversationId]);
|
|
11480
11807
|
const actionableCards = useMemo(() => items.filter(isActionableCard), [items]);
|
|
11481
11808
|
const statusText = useMemo(() => formatChatFooterStatus({
|
|
11482
11809
|
runKind: run.kind,
|
|
@@ -11559,7 +11886,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11559
11886
|
setReviewFocused(false);
|
|
11560
11887
|
}
|
|
11561
11888
|
}) : null;
|
|
11562
|
-
const
|
|
11889
|
+
const chatViewBody = /* @__PURE__ */ jsxs("box", {
|
|
11563
11890
|
onMouseDown: (event) => {
|
|
11564
11891
|
const paneBox = reviewBelowBoxRef.current;
|
|
11565
11892
|
if (reviewOpen && reviewPlacement === "below" && paneBox && event.y === paneBox.screenY + paneBox.height - 1) {
|
|
@@ -11849,6 +12176,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11849
12176
|
})
|
|
11850
12177
|
]
|
|
11851
12178
|
});
|
|
12179
|
+
const chatView = /* @__PURE__ */ jsx(ConversationContext.Provider, {
|
|
12180
|
+
value: conversationContext,
|
|
12181
|
+
children: chatViewBody
|
|
12182
|
+
});
|
|
11852
12183
|
if (!reviewView || reviewPlacement === "below") return chatView;
|
|
11853
12184
|
const fullscreen = reviewPlacement === "fullscreen";
|
|
11854
12185
|
return /* @__PURE__ */ jsxs("box", {
|
|
@@ -12193,7 +12524,12 @@ function App({ appUrl, sessionToken, authKind, shareMachine, promptHistoryPath,
|
|
|
12193
12524
|
setClients,
|
|
12194
12525
|
fail
|
|
12195
12526
|
]);
|
|
12527
|
+
const appendEarlyInput = useStore((s) => s.appendEarlyInput);
|
|
12196
12528
|
useKeyboard((key) => {
|
|
12529
|
+
if (screen.kind === "splash" && !(key.name === "c" && key.ctrl)) {
|
|
12530
|
+
appendEarlyInput(key);
|
|
12531
|
+
return;
|
|
12532
|
+
}
|
|
12197
12533
|
if (key.name === "c" && key.ctrl && screen.kind !== "chat") {
|
|
12198
12534
|
useStore.getState().portalClient?.dispose();
|
|
12199
12535
|
agentHost.dispose();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as errorMessage, t as HttpError } from "./rest-
|
|
2
|
+
import { a as errorMessage, t as HttpError } from "./rest-CtEF_ZDf.mjs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { o as isRecord } from "./rest-
|
|
3
|
-
import { t as PortalClient } from "./client-
|
|
2
|
+
import { o as isRecord } from "./rest-CtEF_ZDf.mjs";
|
|
3
|
+
import { t as PortalClient } from "./client-C5O0ZhxP.mjs";
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { z } from "zod";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import "./rest-
|
|
2
|
+
import "./rest-CtEF_ZDf.mjs";
|
|
3
3
|
import "./billing-blocked-CwfG1BTR.mjs";
|
|
4
|
-
import "./client-
|
|
5
|
-
import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as stopDaemon, r as isDaemonListening, t as PortalDaemon } from "./daemon-
|
|
4
|
+
import "./client-C5O0ZhxP.mjs";
|
|
5
|
+
import { a as runPortalDaemon, i as queryDaemonStatus, n as ensureDaemonRunning, o as stopDaemon, r as isDaemonListening, t as PortalDaemon } from "./daemon-CgLbaJ9_.mjs";
|
|
6
6
|
|
|
7
7
|
export { runPortalDaemon };
|
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
2
|
+
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, t as HttpError } from "./rest-CtEF_ZDf.mjs";
|
|
3
3
|
import { i as billingBlockedOutcomeFromSendResponse, n as BillingBlockedError } from "./billing-blocked-CwfG1BTR.mjs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import Conf from "conf";
|
|
@@ -1,6 +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-
|
|
3
|
-
import "./rest-
|
|
2
|
+
import { a as runPrint, i as resolveAgent, n as messageGet, o as toPrintError, r as readStdin, t as collectRunText } from "./print-DA8WzgzH.mjs";
|
|
3
|
+
import "./rest-CtEF_ZDf.mjs";
|
|
4
4
|
import "./billing-blocked-CwfG1BTR.mjs";
|
|
5
5
|
|
|
6
6
|
export { messageGet, readStdin, resolveAgent, runPrint };
|
|
@@ -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-
|
|
17
|
+
const { PortalClient } = await import("./client-BhdMLYEe.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 { S as getConfigPath } from "./print-
|
|
2
|
+
import { S as getConfigPath } from "./print-DA8WzgzH.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.4.0-beta.
|
|
11
|
+
var version$1 = "0.4.0-beta.1319";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/auth/organization.ts
|
|
@@ -294,6 +294,10 @@ function createRestClient({ appUrl, sessionToken, workspaceId }) {
|
|
|
294
294
|
const { recap } = await get(`/api/v1/conversations/${encodeURIComponent(conversationId)}/recap`, recapResponseSchema);
|
|
295
295
|
return recap?.text ?? null;
|
|
296
296
|
},
|
|
297
|
+
listSubagentTasks: async ({ conversationId }) => {
|
|
298
|
+
const { result } = await get(`/api/v1/trpc/v2.subagentTasks.list?input=${encodeURIComponent(JSON.stringify({ conversationId }))}`, subagentTasksResponseSchema);
|
|
299
|
+
return new Map(result.data.subagentTasks.map((task) => [task.id, task]));
|
|
300
|
+
},
|
|
297
301
|
uploadAttachment: async ({ agentId, fileName, mediaType, data }) => {
|
|
298
302
|
const size = data.byteLength;
|
|
299
303
|
const presign = await post("/api/v1/attachments/presign", {
|
|
@@ -530,6 +534,14 @@ const uiMessageSchema = z.object({
|
|
|
530
534
|
}).passthrough().optional() }).passthrough().optional()
|
|
531
535
|
});
|
|
532
536
|
const recapResponseSchema = z.object({ recap: z.object({ text: z.string() }).nullable() });
|
|
537
|
+
const subagentTaskSnapshotSchema = z.object({
|
|
538
|
+
id: z.string(),
|
|
539
|
+
status: z.string(),
|
|
540
|
+
title: z.string().nullable(),
|
|
541
|
+
createdAt: z.string(),
|
|
542
|
+
completedAt: z.string().nullable()
|
|
543
|
+
});
|
|
544
|
+
const subagentTasksResponseSchema = z.object({ result: z.object({ data: z.object({ subagentTasks: z.array(subagentTaskSnapshotSchema) }) }) });
|
|
533
545
|
const listMessagesResponseSchema = z.object({ messages: z.array(uiMessageSchema) });
|
|
534
546
|
const workspaceFileSchema = z.object({
|
|
535
547
|
id: z.string(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-
|
|
2
|
+
import { i as sendErrorMessage, n as createRestClient, r as errorDetail, t as HttpError } from "./rest-CtEF_ZDf.mjs";
|
|
3
3
|
import "./billing-blocked-CwfG1BTR.mjs";
|
|
4
4
|
|
|
5
5
|
export { createRestClient };
|
package/package.json
CHANGED