skydive-cli 0.4.0-beta.1141 → 0.4.0-beta.1174
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-D1iX9oW1.mjs → boot-DFFwwXGr.mjs} +594 -53
- 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-C-hbIwXv.mjs → profiler-TWHjJUji.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-TWHjJUji.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-DFFwwXGr.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-DFFwwXGr.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-DFFwwXGr.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-TWHjJUji.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";
|
|
@@ -4223,6 +4223,292 @@ function parseMatches(output) {
|
|
|
4223
4223
|
return null;
|
|
4224
4224
|
}
|
|
4225
4225
|
|
|
4226
|
+
//#endregion
|
|
4227
|
+
//#region src/chat/tui/chat/conversation-context.tsx
|
|
4228
|
+
const ConversationContext = createContext({
|
|
4229
|
+
rest: null,
|
|
4230
|
+
conversationId: null
|
|
4231
|
+
});
|
|
4232
|
+
function useConversationContext() {
|
|
4233
|
+
return useContext(ConversationContext);
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4236
|
+
//#endregion
|
|
4237
|
+
//#region src/chat/tui/spinner-frames.ts
|
|
4238
|
+
/** Braille dot-cycle frames — the classic smooth terminal spinner. */
|
|
4239
|
+
const SPINNER_FRAMES = [
|
|
4240
|
+
"⠋",
|
|
4241
|
+
"⠙",
|
|
4242
|
+
"⠹",
|
|
4243
|
+
"⠸",
|
|
4244
|
+
"⠼",
|
|
4245
|
+
"⠴",
|
|
4246
|
+
"⠦",
|
|
4247
|
+
"⠧",
|
|
4248
|
+
"⠇",
|
|
4249
|
+
"⠏"
|
|
4250
|
+
];
|
|
4251
|
+
/** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
|
|
4252
|
+
const SPINNER_INTERVAL_MS = 80;
|
|
4253
|
+
/** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
|
|
4254
|
+
function spinnerFrame(tick) {
|
|
4255
|
+
const n = SPINNER_FRAMES.length;
|
|
4256
|
+
return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
//#endregion
|
|
4260
|
+
//#region src/chat/tui/spinner.tsx
|
|
4261
|
+
/**
|
|
4262
|
+
* An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
|
|
4263
|
+
* a self-owned interval that's cleared on unmount, so the animation runs only
|
|
4264
|
+
* while the component is mounted. Returns a <span>, so render it inside a
|
|
4265
|
+
* <text> (matching how the rest of the TUI composes inline glyphs).
|
|
4266
|
+
*/
|
|
4267
|
+
function Spinner({ color }) {
|
|
4268
|
+
const [tick, setTick] = useState(0);
|
|
4269
|
+
useEffect(() => {
|
|
4270
|
+
const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
|
|
4271
|
+
return () => clearInterval(id);
|
|
4272
|
+
}, []);
|
|
4273
|
+
return /* @__PURE__ */ jsx("span", {
|
|
4274
|
+
fg: color,
|
|
4275
|
+
children: spinnerFrame(tick)
|
|
4276
|
+
});
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
//#endregion
|
|
4280
|
+
//#region src/chat/tui/chat/subagents.ts
|
|
4281
|
+
/** A run the platform hasn't settled yet — still queued or mid-run. */
|
|
4282
|
+
function isLiveStatus(status) {
|
|
4283
|
+
return status === "queued" || status === "running";
|
|
4284
|
+
}
|
|
4285
|
+
function toTaskStatus(raw) {
|
|
4286
|
+
switch (raw) {
|
|
4287
|
+
case "queued":
|
|
4288
|
+
case "running":
|
|
4289
|
+
case "completed":
|
|
4290
|
+
case "failed":
|
|
4291
|
+
case "canceled": return raw;
|
|
4292
|
+
default: return "queued";
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
const FALLBACK_TITLE = "Subagent task";
|
|
4296
|
+
/**
|
|
4297
|
+
* Each delegated task's display title from the `subagent` call's input, in
|
|
4298
|
+
* call order — the short name the tool requires per task. A malformed entry
|
|
4299
|
+
* yields a fallback label rather than being dropped, so the row count always
|
|
4300
|
+
* matches the fan-out width. Mirrors the web client's `subagentTaskTitles`.
|
|
4301
|
+
*/
|
|
4302
|
+
function subagentTaskTitles(input) {
|
|
4303
|
+
if (!isRecord(input)) return [];
|
|
4304
|
+
const tasks = input["tasks"];
|
|
4305
|
+
if (!Array.isArray(tasks)) return [];
|
|
4306
|
+
return tasks.map((task) => {
|
|
4307
|
+
if (!isRecord(task)) return FALLBACK_TITLE;
|
|
4308
|
+
const title = task["title"];
|
|
4309
|
+
return typeof title === "string" && title.trim() ? title.trim() : FALLBACK_TITLE;
|
|
4310
|
+
});
|
|
4311
|
+
}
|
|
4312
|
+
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;
|
|
4313
|
+
/**
|
|
4314
|
+
* The ids of the runs a `subagent` call queued, read back out of its own
|
|
4315
|
+
* output. The call returns the moment the runs exist, so the ids are there
|
|
4316
|
+
* long before any child finishes — they are what ties this card to the task
|
|
4317
|
+
* rows the status poll returns, and their order is the tasks' call order.
|
|
4318
|
+
*/
|
|
4319
|
+
function queuedSubagentTaskIds(output) {
|
|
4320
|
+
const text = flattenOutputText(output);
|
|
4321
|
+
if (!text) return [];
|
|
4322
|
+
return text.split("\n").map((line) => line.match(QUEUED_TASK_ID_LINE)?.[1] ?? null).filter((id) => id !== null);
|
|
4323
|
+
}
|
|
4324
|
+
/**
|
|
4325
|
+
* Tool output reaches the TUI as `unknown`: the raw string live, possibly
|
|
4326
|
+
* wrapped in content parts or arrays when loaded from history. Walk it for
|
|
4327
|
+
* string leaves, newline-joined — the PR scanner's `stringifyToolOutput`
|
|
4328
|
+
* shape, bounded small because the id list sits at the top of the output.
|
|
4329
|
+
*/
|
|
4330
|
+
function flattenOutputText(value) {
|
|
4331
|
+
const MAX_LEN = 2e4;
|
|
4332
|
+
const parts = [];
|
|
4333
|
+
let total = 0;
|
|
4334
|
+
const visit = (v, depth) => {
|
|
4335
|
+
if (total >= MAX_LEN || depth > 4) return;
|
|
4336
|
+
if (typeof v === "string") {
|
|
4337
|
+
parts.push(v);
|
|
4338
|
+
total += v.length;
|
|
4339
|
+
return;
|
|
4340
|
+
}
|
|
4341
|
+
if (Array.isArray(v)) {
|
|
4342
|
+
for (const item of v) visit(item, depth + 1);
|
|
4343
|
+
return;
|
|
4344
|
+
}
|
|
4345
|
+
if (isRecord(v)) for (const item of Object.values(v)) visit(item, depth + 1);
|
|
4346
|
+
};
|
|
4347
|
+
visit(value, 0);
|
|
4348
|
+
return parts.join("\n");
|
|
4349
|
+
}
|
|
4350
|
+
/**
|
|
4351
|
+
* The card's rows: one per queued run id (call order), each carrying the
|
|
4352
|
+
* freshest known state. A task the status fetch hasn't returned yet falls
|
|
4353
|
+
* back to the input's title and reads as queued; a fetched row's own title
|
|
4354
|
+
* wins over the input's (the server's copy is the one the child actually
|
|
4355
|
+
* ran under). Before the ids exist — the call is still streaming — rows come
|
|
4356
|
+
* from the input titles alone, so the card never renders empty mid-turn.
|
|
4357
|
+
*/
|
|
4358
|
+
function subagentRows({ titles, ids, fetched }) {
|
|
4359
|
+
if (ids.length === 0) return titles.map((title, index) => ({
|
|
4360
|
+
id: `queued:${index}`,
|
|
4361
|
+
title,
|
|
4362
|
+
status: "queued",
|
|
4363
|
+
createdAt: null,
|
|
4364
|
+
completedAt: null
|
|
4365
|
+
}));
|
|
4366
|
+
return ids.map((id, index) => {
|
|
4367
|
+
const row = fetched?.get(id) ?? null;
|
|
4368
|
+
return {
|
|
4369
|
+
id,
|
|
4370
|
+
title: row?.title ?? titles[index] ?? FALLBACK_TITLE,
|
|
4371
|
+
status: row ? toTaskStatus(row.status) : "queued",
|
|
4372
|
+
createdAt: row?.createdAt ?? null,
|
|
4373
|
+
completedAt: row?.completedAt ?? null
|
|
4374
|
+
};
|
|
4375
|
+
});
|
|
4376
|
+
}
|
|
4377
|
+
|
|
4378
|
+
//#endregion
|
|
4379
|
+
//#region src/chat/tui/chunks/tool-subagent.tsx
|
|
4380
|
+
/** How often a live batch re-reads its tasks' status. */
|
|
4381
|
+
const POLL_INTERVAL_MS = 3e3;
|
|
4382
|
+
function rowGlyph(status) {
|
|
4383
|
+
switch (status) {
|
|
4384
|
+
case "completed": return {
|
|
4385
|
+
ch: "✔",
|
|
4386
|
+
fg: theme.success
|
|
4387
|
+
};
|
|
4388
|
+
case "failed":
|
|
4389
|
+
case "canceled": return {
|
|
4390
|
+
ch: "✗",
|
|
4391
|
+
fg: theme.error
|
|
4392
|
+
};
|
|
4393
|
+
case "running": return {
|
|
4394
|
+
ch: "▶",
|
|
4395
|
+
fg: theme.accent
|
|
4396
|
+
};
|
|
4397
|
+
case "queued": return {
|
|
4398
|
+
ch: "○",
|
|
4399
|
+
fg: theme.dim
|
|
4400
|
+
};
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4403
|
+
function rowColor$1(status) {
|
|
4404
|
+
switch (status) {
|
|
4405
|
+
case "running": return theme.fg;
|
|
4406
|
+
case "completed": return theme.dim;
|
|
4407
|
+
default: return theme.muted;
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
function headerLabel(rows) {
|
|
4411
|
+
const subject = rows.length === 1 ? "Subagent" : `${rows.length} subagents`;
|
|
4412
|
+
return rows.some((row) => isLiveStatus(row.status)) ? `${subject} running` : subject;
|
|
4413
|
+
}
|
|
4414
|
+
/**
|
|
4415
|
+
* The transcript block for a `subagent` tool call — the TUI analog of the web
|
|
4416
|
+
* chat's fan-out card. One row per delegated run: status glyph, the short
|
|
4417
|
+
* title the delegating agent wrote, ticking over live as children settle.
|
|
4418
|
+
*
|
|
4419
|
+
* Rows are seeded from the call itself (titles from its input, task ids from
|
|
4420
|
+
* its own output), so the card renders the moment the call does. Status then
|
|
4421
|
+
* comes from the server's task rows, polled while any run is live — the
|
|
4422
|
+
* delegated runs outlive the call that spawned them, so the transcript stream
|
|
4423
|
+
* carries nothing more about them. The poll stops the moment the batch
|
|
4424
|
+
* settles; reopening an old conversation does one fetch and stops there. A
|
|
4425
|
+
* failed poll is skipped silently (the next tick retries; stale rows beat an
|
|
4426
|
+
* error row in the scrollback).
|
|
4427
|
+
*/
|
|
4428
|
+
function ToolSubagent({ item }) {
|
|
4429
|
+
const { rest, conversationId } = useConversationContext();
|
|
4430
|
+
const titles = subagentTaskTitles(item.input);
|
|
4431
|
+
const ids = item.output?.kind === "ok" ? queuedSubagentTaskIds(item.output.value) : [];
|
|
4432
|
+
const idsKey = ids.join(",");
|
|
4433
|
+
const [fetched, setFetched] = useState(null);
|
|
4434
|
+
const rows = subagentRows({
|
|
4435
|
+
titles,
|
|
4436
|
+
ids,
|
|
4437
|
+
fetched
|
|
4438
|
+
});
|
|
4439
|
+
const live = rows.length === 0 || rows.some((row) => isLiveStatus(row.status));
|
|
4440
|
+
useEffect(() => {
|
|
4441
|
+
if (!rest || !conversationId || idsKey.length === 0 || !live) return;
|
|
4442
|
+
let cancelled = false;
|
|
4443
|
+
let timer = null;
|
|
4444
|
+
const tick = async () => {
|
|
4445
|
+
try {
|
|
4446
|
+
const tasks = await rest.listSubagentTasks({ conversationId });
|
|
4447
|
+
if (cancelled) return;
|
|
4448
|
+
setFetched(tasks);
|
|
4449
|
+
} catch (_error) {}
|
|
4450
|
+
if (!cancelled) timer = setTimeout(tick, POLL_INTERVAL_MS);
|
|
4451
|
+
};
|
|
4452
|
+
tick();
|
|
4453
|
+
return () => {
|
|
4454
|
+
cancelled = true;
|
|
4455
|
+
if (timer !== null) clearTimeout(timer);
|
|
4456
|
+
};
|
|
4457
|
+
}, [
|
|
4458
|
+
rest,
|
|
4459
|
+
conversationId,
|
|
4460
|
+
idsKey,
|
|
4461
|
+
live
|
|
4462
|
+
]);
|
|
4463
|
+
if (rows.length === 0) return /* @__PURE__ */ jsxs("text", { children: [/* @__PURE__ */ jsx("span", {
|
|
4464
|
+
fg: theme.warning,
|
|
4465
|
+
children: "◐ "
|
|
4466
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
4467
|
+
fg: theme.tool,
|
|
4468
|
+
children: "Delegating to subagents…"
|
|
4469
|
+
})] });
|
|
4470
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4471
|
+
style: { flexDirection: "column" },
|
|
4472
|
+
children: [/* @__PURE__ */ jsxs("text", { children: [
|
|
4473
|
+
live ? /* @__PURE__ */ jsx(Spinner, { color: theme.accent }) : /* @__PURE__ */ jsx("span", {
|
|
4474
|
+
fg: theme.success,
|
|
4475
|
+
children: "✓"
|
|
4476
|
+
}),
|
|
4477
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4478
|
+
fg: theme.tool,
|
|
4479
|
+
children: [" ", /* @__PURE__ */ jsx("b", { children: headerLabel(rows) })]
|
|
4480
|
+
}),
|
|
4481
|
+
/* @__PURE__ */ jsxs("span", {
|
|
4482
|
+
fg: theme.dim,
|
|
4483
|
+
children: [
|
|
4484
|
+
" ",
|
|
4485
|
+
rows.filter((row) => row.status === "completed").length,
|
|
4486
|
+
"/",
|
|
4487
|
+
rows.length
|
|
4488
|
+
]
|
|
4489
|
+
})
|
|
4490
|
+
] }), /* @__PURE__ */ jsx("box", {
|
|
4491
|
+
style: {
|
|
4492
|
+
flexDirection: "column",
|
|
4493
|
+
paddingLeft: 2
|
|
4494
|
+
},
|
|
4495
|
+
children: rows.map((row) => {
|
|
4496
|
+
const glyph = rowGlyph(row.status);
|
|
4497
|
+
return /* @__PURE__ */ jsxs("box", {
|
|
4498
|
+
style: { flexDirection: "row" },
|
|
4499
|
+
children: [/* @__PURE__ */ jsxs("text", {
|
|
4500
|
+
fg: glyph.fg,
|
|
4501
|
+
children: [glyph.ch, " "]
|
|
4502
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
4503
|
+
fg: rowColor$1(row.status),
|
|
4504
|
+
children: row.title
|
|
4505
|
+
})]
|
|
4506
|
+
}, row.id);
|
|
4507
|
+
})
|
|
4508
|
+
})]
|
|
4509
|
+
});
|
|
4510
|
+
}
|
|
4511
|
+
|
|
4226
4512
|
//#endregion
|
|
4227
4513
|
//#region src/chat/tui/chunks/shell-local.tsx
|
|
4228
4514
|
/**
|
|
@@ -4446,6 +4732,7 @@ function ToolItem({ item }) {
|
|
|
4446
4732
|
case "read": return /* @__PURE__ */ jsx(ToolRead, { item });
|
|
4447
4733
|
case "grep":
|
|
4448
4734
|
case "glob": return /* @__PURE__ */ jsx(ToolGrep, { item });
|
|
4735
|
+
case "subagent": return /* @__PURE__ */ jsx(ToolSubagent, { item });
|
|
4449
4736
|
default: return /* @__PURE__ */ jsx(ToolGeneric, { item });
|
|
4450
4737
|
}
|
|
4451
4738
|
}
|
|
@@ -4615,6 +4902,270 @@ function clampItem(item) {
|
|
|
4615
4902
|
}
|
|
4616
4903
|
}
|
|
4617
4904
|
|
|
4905
|
+
//#endregion
|
|
4906
|
+
//#region src/chat/tui/chat/fix-json.ts
|
|
4907
|
+
/**
|
|
4908
|
+
* Implemented as a scanner with additional fixing
|
|
4909
|
+
* that performs a single linear time scan pass over the partial JSON.
|
|
4910
|
+
*
|
|
4911
|
+
* The states should ideally match relevant states from the JSON spec:
|
|
4912
|
+
* https://www.json.org/json-en.html
|
|
4913
|
+
*
|
|
4914
|
+
* Please note that invalid JSON is not considered/covered, because it
|
|
4915
|
+
* is assumed that the resulting JSON will be processed by a standard
|
|
4916
|
+
* JSON parser that will detect any invalid JSON.
|
|
4917
|
+
*/
|
|
4918
|
+
function fixJson(input) {
|
|
4919
|
+
const stack = ["ROOT"];
|
|
4920
|
+
let lastValidIndex = -1;
|
|
4921
|
+
let literalStart = null;
|
|
4922
|
+
function processValueStart(char, i, swapState) {
|
|
4923
|
+
switch (char) {
|
|
4924
|
+
case "\"":
|
|
4925
|
+
lastValidIndex = i;
|
|
4926
|
+
stack.pop();
|
|
4927
|
+
stack.push(swapState);
|
|
4928
|
+
stack.push("INSIDE_STRING");
|
|
4929
|
+
break;
|
|
4930
|
+
case "f":
|
|
4931
|
+
case "t":
|
|
4932
|
+
case "n":
|
|
4933
|
+
lastValidIndex = i;
|
|
4934
|
+
literalStart = i;
|
|
4935
|
+
stack.pop();
|
|
4936
|
+
stack.push(swapState);
|
|
4937
|
+
stack.push("INSIDE_LITERAL");
|
|
4938
|
+
break;
|
|
4939
|
+
case "-":
|
|
4940
|
+
stack.pop();
|
|
4941
|
+
stack.push(swapState);
|
|
4942
|
+
stack.push("INSIDE_NUMBER");
|
|
4943
|
+
break;
|
|
4944
|
+
case "0":
|
|
4945
|
+
case "1":
|
|
4946
|
+
case "2":
|
|
4947
|
+
case "3":
|
|
4948
|
+
case "4":
|
|
4949
|
+
case "5":
|
|
4950
|
+
case "6":
|
|
4951
|
+
case "7":
|
|
4952
|
+
case "8":
|
|
4953
|
+
case "9":
|
|
4954
|
+
lastValidIndex = i;
|
|
4955
|
+
stack.pop();
|
|
4956
|
+
stack.push(swapState);
|
|
4957
|
+
stack.push("INSIDE_NUMBER");
|
|
4958
|
+
break;
|
|
4959
|
+
case "{":
|
|
4960
|
+
lastValidIndex = i;
|
|
4961
|
+
stack.pop();
|
|
4962
|
+
stack.push(swapState);
|
|
4963
|
+
stack.push("INSIDE_OBJECT_START");
|
|
4964
|
+
break;
|
|
4965
|
+
case "[":
|
|
4966
|
+
lastValidIndex = i;
|
|
4967
|
+
stack.pop();
|
|
4968
|
+
stack.push(swapState);
|
|
4969
|
+
stack.push("INSIDE_ARRAY_START");
|
|
4970
|
+
break;
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4973
|
+
function processAfterObjectValue(char, i) {
|
|
4974
|
+
switch (char) {
|
|
4975
|
+
case ",":
|
|
4976
|
+
stack.pop();
|
|
4977
|
+
stack.push("INSIDE_OBJECT_AFTER_COMMA");
|
|
4978
|
+
break;
|
|
4979
|
+
case "}":
|
|
4980
|
+
lastValidIndex = i;
|
|
4981
|
+
stack.pop();
|
|
4982
|
+
break;
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
function processAfterArrayValue(char, i) {
|
|
4986
|
+
switch (char) {
|
|
4987
|
+
case ",":
|
|
4988
|
+
stack.pop();
|
|
4989
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
|
4990
|
+
break;
|
|
4991
|
+
case "]":
|
|
4992
|
+
lastValidIndex = i;
|
|
4993
|
+
stack.pop();
|
|
4994
|
+
break;
|
|
4995
|
+
}
|
|
4996
|
+
}
|
|
4997
|
+
for (let i = 0; i < input.length; i++) {
|
|
4998
|
+
const char = input[i];
|
|
4999
|
+
if (!char) continue;
|
|
5000
|
+
switch (stack[stack.length - 1]) {
|
|
5001
|
+
case "ROOT":
|
|
5002
|
+
processValueStart(char, i, "FINISH");
|
|
5003
|
+
break;
|
|
5004
|
+
case "INSIDE_OBJECT_START":
|
|
5005
|
+
switch (char) {
|
|
5006
|
+
case "\"":
|
|
5007
|
+
stack.pop();
|
|
5008
|
+
stack.push("INSIDE_OBJECT_KEY");
|
|
5009
|
+
break;
|
|
5010
|
+
case "}":
|
|
5011
|
+
lastValidIndex = i;
|
|
5012
|
+
stack.pop();
|
|
5013
|
+
break;
|
|
5014
|
+
}
|
|
5015
|
+
break;
|
|
5016
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
|
5017
|
+
switch (char) {
|
|
5018
|
+
case "\"":
|
|
5019
|
+
stack.pop();
|
|
5020
|
+
stack.push("INSIDE_OBJECT_KEY");
|
|
5021
|
+
break;
|
|
5022
|
+
}
|
|
5023
|
+
break;
|
|
5024
|
+
case "INSIDE_OBJECT_KEY":
|
|
5025
|
+
switch (char) {
|
|
5026
|
+
case "\"":
|
|
5027
|
+
stack.pop();
|
|
5028
|
+
stack.push("INSIDE_OBJECT_AFTER_KEY");
|
|
5029
|
+
break;
|
|
5030
|
+
}
|
|
5031
|
+
break;
|
|
5032
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
|
5033
|
+
switch (char) {
|
|
5034
|
+
case ":":
|
|
5035
|
+
stack.pop();
|
|
5036
|
+
stack.push("INSIDE_OBJECT_BEFORE_VALUE");
|
|
5037
|
+
break;
|
|
5038
|
+
}
|
|
5039
|
+
break;
|
|
5040
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
|
5041
|
+
processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
|
|
5042
|
+
break;
|
|
5043
|
+
case "INSIDE_OBJECT_AFTER_VALUE":
|
|
5044
|
+
processAfterObjectValue(char, i);
|
|
5045
|
+
break;
|
|
5046
|
+
case "INSIDE_STRING":
|
|
5047
|
+
switch (char) {
|
|
5048
|
+
case "\"":
|
|
5049
|
+
stack.pop();
|
|
5050
|
+
lastValidIndex = i;
|
|
5051
|
+
break;
|
|
5052
|
+
case "\\":
|
|
5053
|
+
stack.push("INSIDE_STRING_ESCAPE");
|
|
5054
|
+
break;
|
|
5055
|
+
default: lastValidIndex = i;
|
|
5056
|
+
}
|
|
5057
|
+
break;
|
|
5058
|
+
case "INSIDE_ARRAY_START":
|
|
5059
|
+
switch (char) {
|
|
5060
|
+
case "]":
|
|
5061
|
+
lastValidIndex = i;
|
|
5062
|
+
stack.pop();
|
|
5063
|
+
break;
|
|
5064
|
+
default:
|
|
5065
|
+
lastValidIndex = i;
|
|
5066
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
|
5067
|
+
break;
|
|
5068
|
+
}
|
|
5069
|
+
break;
|
|
5070
|
+
case "INSIDE_ARRAY_AFTER_VALUE":
|
|
5071
|
+
switch (char) {
|
|
5072
|
+
case ",":
|
|
5073
|
+
stack.pop();
|
|
5074
|
+
stack.push("INSIDE_ARRAY_AFTER_COMMA");
|
|
5075
|
+
break;
|
|
5076
|
+
case "]":
|
|
5077
|
+
lastValidIndex = i;
|
|
5078
|
+
stack.pop();
|
|
5079
|
+
break;
|
|
5080
|
+
default:
|
|
5081
|
+
lastValidIndex = i;
|
|
5082
|
+
break;
|
|
5083
|
+
}
|
|
5084
|
+
break;
|
|
5085
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
|
5086
|
+
processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
|
|
5087
|
+
break;
|
|
5088
|
+
case "INSIDE_STRING_ESCAPE":
|
|
5089
|
+
stack.pop();
|
|
5090
|
+
lastValidIndex = i;
|
|
5091
|
+
break;
|
|
5092
|
+
case "INSIDE_NUMBER":
|
|
5093
|
+
switch (char) {
|
|
5094
|
+
case "0":
|
|
5095
|
+
case "1":
|
|
5096
|
+
case "2":
|
|
5097
|
+
case "3":
|
|
5098
|
+
case "4":
|
|
5099
|
+
case "5":
|
|
5100
|
+
case "6":
|
|
5101
|
+
case "7":
|
|
5102
|
+
case "8":
|
|
5103
|
+
case "9":
|
|
5104
|
+
lastValidIndex = i;
|
|
5105
|
+
break;
|
|
5106
|
+
case "e":
|
|
5107
|
+
case "E":
|
|
5108
|
+
case "-":
|
|
5109
|
+
case ".": break;
|
|
5110
|
+
case ",":
|
|
5111
|
+
stack.pop();
|
|
5112
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
5113
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
5114
|
+
break;
|
|
5115
|
+
case "}":
|
|
5116
|
+
stack.pop();
|
|
5117
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
5118
|
+
break;
|
|
5119
|
+
case "]":
|
|
5120
|
+
stack.pop();
|
|
5121
|
+
if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
5122
|
+
break;
|
|
5123
|
+
default:
|
|
5124
|
+
stack.pop();
|
|
5125
|
+
break;
|
|
5126
|
+
}
|
|
5127
|
+
break;
|
|
5128
|
+
case "INSIDE_LITERAL": {
|
|
5129
|
+
if (!literalStart) continue;
|
|
5130
|
+
const partialLiteral = input.substring(literalStart, i + 1);
|
|
5131
|
+
if (!"false".startsWith(partialLiteral) && !"true".startsWith(partialLiteral) && !"null".startsWith(partialLiteral)) {
|
|
5132
|
+
stack.pop();
|
|
5133
|
+
if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
|
|
5134
|
+
else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
|
|
5135
|
+
} else lastValidIndex = i;
|
|
5136
|
+
break;
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
5140
|
+
let result = input.slice(0, lastValidIndex + 1);
|
|
5141
|
+
for (let i = stack.length - 1; i >= 0; i--) switch (stack[i]) {
|
|
5142
|
+
case "INSIDE_STRING":
|
|
5143
|
+
result += "\"";
|
|
5144
|
+
break;
|
|
5145
|
+
case "INSIDE_OBJECT_KEY":
|
|
5146
|
+
case "INSIDE_OBJECT_AFTER_KEY":
|
|
5147
|
+
case "INSIDE_OBJECT_AFTER_COMMA":
|
|
5148
|
+
case "INSIDE_OBJECT_START":
|
|
5149
|
+
case "INSIDE_OBJECT_BEFORE_VALUE":
|
|
5150
|
+
case "INSIDE_OBJECT_AFTER_VALUE":
|
|
5151
|
+
result += "}";
|
|
5152
|
+
break;
|
|
5153
|
+
case "INSIDE_ARRAY_START":
|
|
5154
|
+
case "INSIDE_ARRAY_AFTER_COMMA":
|
|
5155
|
+
case "INSIDE_ARRAY_AFTER_VALUE":
|
|
5156
|
+
result += "]";
|
|
5157
|
+
break;
|
|
5158
|
+
case "INSIDE_LITERAL": {
|
|
5159
|
+
if (!literalStart) continue;
|
|
5160
|
+
const partialLiteral = input.substring(literalStart, input.length);
|
|
5161
|
+
if ("true".startsWith(partialLiteral)) result += "true".slice(partialLiteral.length);
|
|
5162
|
+
else if ("false".startsWith(partialLiteral)) result += "false".slice(partialLiteral.length);
|
|
5163
|
+
else if ("null".startsWith(partialLiteral)) result += "null".slice(partialLiteral.length);
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
return result;
|
|
5167
|
+
}
|
|
5168
|
+
|
|
4618
5169
|
//#endregion
|
|
4619
5170
|
//#region src/chat/tui/chat/reducer.ts
|
|
4620
5171
|
function str(chunk, key) {
|
|
@@ -4622,6 +5173,24 @@ function str(chunk, key) {
|
|
|
4622
5173
|
return typeof value === "string" ? value : null;
|
|
4623
5174
|
}
|
|
4624
5175
|
/**
|
|
5176
|
+
* Best-effort parse of a tool call's partial arguments while they stream.
|
|
5177
|
+
* `fixJson` (the vercel/ai scanner) closes off the truncated JSON so a
|
|
5178
|
+
* half-arrived `{"command":"npm ins` parses to `{ command: 'npm ins' }`,
|
|
5179
|
+
* letting the renderers show the structured input filling in live rather
|
|
5180
|
+
* than a raw JSON fragment. Returns null until enough has arrived to parse
|
|
5181
|
+
* (or when the text isn't an object/array), so callers keep their raw
|
|
5182
|
+
* `inputText` fallback for the first few characters.
|
|
5183
|
+
*/
|
|
5184
|
+
function parsePartialInput(text) {
|
|
5185
|
+
const trimmed = text.trimStart();
|
|
5186
|
+
if (trimmed[0] !== "{" && trimmed[0] !== "[") return null;
|
|
5187
|
+
try {
|
|
5188
|
+
return JSON.parse(fixJson(text));
|
|
5189
|
+
} catch (_error) {
|
|
5190
|
+
return null;
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
/**
|
|
4625
5194
|
* `agentName` is the display name of the agent producing this run's stream.
|
|
4626
5195
|
* It's stamped onto each assistant-origin item so a multi-agent conversation
|
|
4627
5196
|
* can attribute live turns; pass null in a solo thread to leave items
|
|
@@ -4689,10 +5258,17 @@ function applyChunk(items, chunk, agentName = null) {
|
|
|
4689
5258
|
const toolCallId = str(chunk, "toolCallId");
|
|
4690
5259
|
const delta = str(chunk, "inputTextDelta") ?? str(chunk, "delta") ?? "";
|
|
4691
5260
|
if (!toolCallId) return [...items];
|
|
4692
|
-
return items.map((m) =>
|
|
4693
|
-
|
|
4694
|
-
inputText
|
|
4695
|
-
|
|
5261
|
+
return items.map((m) => {
|
|
5262
|
+
if (m.kind !== "tool" || m.id !== toolCallId) return m;
|
|
5263
|
+
const inputText = m.inputText + delta;
|
|
5264
|
+
const parsed = parsePartialInput(inputText);
|
|
5265
|
+
const input = parsed == null ? null : clampPayload(parsed);
|
|
5266
|
+
return {
|
|
5267
|
+
...m,
|
|
5268
|
+
inputText,
|
|
5269
|
+
input
|
|
5270
|
+
};
|
|
5271
|
+
});
|
|
4696
5272
|
}
|
|
4697
5273
|
case "tool-input-available": {
|
|
4698
5274
|
const toolCallId = str(chunk, "toolCallId");
|
|
@@ -5497,49 +6073,6 @@ function createResponsePreview() {
|
|
|
5497
6073
|
};
|
|
5498
6074
|
}
|
|
5499
6075
|
|
|
5500
|
-
//#endregion
|
|
5501
|
-
//#region src/chat/tui/spinner-frames.ts
|
|
5502
|
-
/** Braille dot-cycle frames — the classic smooth terminal spinner. */
|
|
5503
|
-
const SPINNER_FRAMES = [
|
|
5504
|
-
"⠋",
|
|
5505
|
-
"⠙",
|
|
5506
|
-
"⠹",
|
|
5507
|
-
"⠸",
|
|
5508
|
-
"⠼",
|
|
5509
|
-
"⠴",
|
|
5510
|
-
"⠦",
|
|
5511
|
-
"⠧",
|
|
5512
|
-
"⠇",
|
|
5513
|
-
"⠏"
|
|
5514
|
-
];
|
|
5515
|
-
/** Milliseconds between frames. ~12.5fps reads as smooth without thrashing. */
|
|
5516
|
-
const SPINNER_INTERVAL_MS = 80;
|
|
5517
|
-
/** Frame for a given tick count. Wraps at the end of the cycle; negative-safe. */
|
|
5518
|
-
function spinnerFrame(tick) {
|
|
5519
|
-
const n = SPINNER_FRAMES.length;
|
|
5520
|
-
return SPINNER_FRAMES[(Math.trunc(tick) % n + n) % n] ?? SPINNER_FRAMES[0];
|
|
5521
|
-
}
|
|
5522
|
-
|
|
5523
|
-
//#endregion
|
|
5524
|
-
//#region src/chat/tui/spinner.tsx
|
|
5525
|
-
/**
|
|
5526
|
-
* An animated spinner glyph. Advances one frame every SPINNER_INTERVAL_MS via
|
|
5527
|
-
* a self-owned interval that's cleared on unmount, so the animation runs only
|
|
5528
|
-
* while the component is mounted. Returns a <span>, so render it inside a
|
|
5529
|
-
* <text> (matching how the rest of the TUI composes inline glyphs).
|
|
5530
|
-
*/
|
|
5531
|
-
function Spinner({ color }) {
|
|
5532
|
-
const [tick, setTick] = useState(0);
|
|
5533
|
-
useEffect(() => {
|
|
5534
|
-
const id = setInterval(() => setTick((t) => t + 1), SPINNER_INTERVAL_MS);
|
|
5535
|
-
return () => clearInterval(id);
|
|
5536
|
-
}, []);
|
|
5537
|
-
return /* @__PURE__ */ jsx("span", {
|
|
5538
|
-
fg: color,
|
|
5539
|
-
children: spinnerFrame(tick)
|
|
5540
|
-
});
|
|
5541
|
-
}
|
|
5542
|
-
|
|
5543
6076
|
//#endregion
|
|
5544
6077
|
//#region src/chat/tui/prompt-history.ts
|
|
5545
6078
|
/**
|
|
@@ -11188,6 +11721,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11188
11721
|
}
|
|
11189
11722
|
});
|
|
11190
11723
|
const hasPendingSteer = items.some((m) => m.kind === "pending-steer");
|
|
11724
|
+
const conversationContext = useMemo(() => ({
|
|
11725
|
+
rest,
|
|
11726
|
+
conversationId
|
|
11727
|
+
}), [rest, conversationId]);
|
|
11191
11728
|
const actionableCards = useMemo(() => items.filter(isActionableCard), [items]);
|
|
11192
11729
|
const statusText = useMemo(() => formatChatFooterStatus({
|
|
11193
11730
|
runKind: run.kind,
|
|
@@ -11270,7 +11807,7 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11270
11807
|
setReviewFocused(false);
|
|
11271
11808
|
}
|
|
11272
11809
|
}) : null;
|
|
11273
|
-
const
|
|
11810
|
+
const chatViewBody = /* @__PURE__ */ jsxs("box", {
|
|
11274
11811
|
onMouseDown: (event) => {
|
|
11275
11812
|
const paneBox = reviewBelowBoxRef.current;
|
|
11276
11813
|
if (reviewOpen && reviewPlacement === "below" && paneBox && event.y === paneBox.screenY + paneBox.height - 1) {
|
|
@@ -11560,6 +12097,10 @@ function ChatScreen({ agent, conversation }) {
|
|
|
11560
12097
|
})
|
|
11561
12098
|
]
|
|
11562
12099
|
});
|
|
12100
|
+
const chatView = /* @__PURE__ */ jsx(ConversationContext.Provider, {
|
|
12101
|
+
value: conversationContext,
|
|
12102
|
+
children: chatViewBody
|
|
12103
|
+
});
|
|
11563
12104
|
if (!reviewView || reviewPlacement === "below") return chatView;
|
|
11564
12105
|
const fullscreen = reviewPlacement === "fullscreen";
|
|
11565
12106
|
return /* @__PURE__ */ jsxs("box", {
|
|
@@ -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.1174";
|
|
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