skydive-cli 0.2.0-beta.605 → 0.2.0-beta.608
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
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { A as
|
|
2
|
+
import { A as deleteConfig, B as resolveAppUrl, C as setActiveWorkspace, D as DEFAULT_API_URL, E as API_KEY_PREFIX, G as saveConfig, H as resolveManagementAuth, I as getShareMachineDefault, J as setLastSeenVersion, K as saveSession, L as getStoredApiKeyId, M as getLastSeenVersion, N as getPromptHistoryPath, R as getStoredApiKeyWorkspaceName, S as listWorkspaces, T as API_KEY_FAMILY_PREFIX, U as resolveSession, V as resolveConfig, X as version, Y as name, _ as themes, b as getActiveWorkspaceId, j as getConfigPath, k as DEFAULT_WEB_URL, o as brandHelpArt, t as installCrashHandler, w as API_KEYS_URL, x as getSessionIdentity, y as ensureActiveOrganization, z as getUpdateCheckDisabled } from "./install-B-9AJk0F.mjs";
|
|
3
3
|
import { n as printError, r as printTable, t as output } from "./output-B4cW10Ph.mjs";
|
|
4
4
|
import { n as createRestClient } from "./rest-DMpigwmN.mjs";
|
|
5
5
|
import { i as resolveAgent } from "./print-6Bm51XhR.mjs";
|
|
@@ -18,11 +18,6 @@ import fs from "node:fs";
|
|
|
18
18
|
import zlib from "node:zlib";
|
|
19
19
|
import semver from "semver";
|
|
20
20
|
|
|
21
|
-
//#region package.json
|
|
22
|
-
var name = "skydive-cli";
|
|
23
|
-
var version = "0.2.0-beta.605";
|
|
24
|
-
|
|
25
|
-
//#endregion
|
|
26
21
|
//#region src/types.ts
|
|
27
22
|
const NON_INTERACTIVE_ENV_VARS = [
|
|
28
23
|
"CI",
|
|
@@ -1200,7 +1195,7 @@ const importCommand = {
|
|
|
1200
1195
|
process.exit(1);
|
|
1201
1196
|
}
|
|
1202
1197
|
}
|
|
1203
|
-
const { runChat } = await import("./boot-
|
|
1198
|
+
const { runChat } = await import("./boot-B1AReDlO.mjs");
|
|
1204
1199
|
await runChat({
|
|
1205
1200
|
appUrl,
|
|
1206
1201
|
sessionToken: session.value.sessionToken,
|
|
@@ -1516,7 +1511,7 @@ const chatCommand = {
|
|
|
1516
1511
|
printError(`Unknown theme "${themeId}". Valid themes: ${themes.map((t) => t.id).join(", ")}`);
|
|
1517
1512
|
process.exit(1);
|
|
1518
1513
|
}
|
|
1519
|
-
const { runChat } = await import("./boot-
|
|
1514
|
+
const { runChat } = await import("./boot-B1AReDlO.mjs");
|
|
1520
1515
|
await runChat({
|
|
1521
1516
|
appUrl,
|
|
1522
1517
|
sessionToken: session.value.sessionToken,
|
|
@@ -1824,7 +1819,7 @@ const switchCommand = {
|
|
|
1824
1819
|
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.");
|
|
1825
1820
|
process.exit(1);
|
|
1826
1821
|
}
|
|
1827
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
1822
|
+
const { runWorkspacePicker } = await import("./boot-B1AReDlO.mjs");
|
|
1828
1823
|
await runWorkspacePicker(session);
|
|
1829
1824
|
return;
|
|
1830
1825
|
}
|
|
@@ -2616,6 +2611,7 @@ function maybePrintWhatsNew({ stderrIsTTY = process.stderr.isTTY ?? false, nonIn
|
|
|
2616
2611
|
|
|
2617
2612
|
//#endregion
|
|
2618
2613
|
//#region src/bin.ts
|
|
2614
|
+
installCrashHandler();
|
|
2619
2615
|
if (process.argv.includes(UPDATE_WORKER_FLAG)) {
|
|
2620
2616
|
await runUpdateCheckWorker();
|
|
2621
2617
|
process.exit(0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { C as setActiveWorkspace, D as DEFAULT_API_URL, F as getSavedTheme, O as DEFAULT_APP_URL, P as getReviewStateDir, S as listWorkspaces, W as resolveWebUrl, 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, j as getConfigPath, l as findTheme, m as themeMode, n as buildCrashReport, p as themeForMode, q as saveTheme, r as writeCrashReport, s as DEFAULT_THEME_ID, t as installCrashHandler, u as monoTheme, v as themesForMode } from "./install-B-9AJk0F.mjs";
|
|
3
3
|
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-DMpigwmN.mjs";
|
|
4
4
|
import { 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 } from "./print-6Bm51XhR.mjs";
|
|
5
5
|
import "./api-BGWcPuik.mjs";
|
|
@@ -1884,6 +1884,7 @@ function useDebouncedValue(value, delayMs) {
|
|
|
1884
1884
|
//#endregion
|
|
1885
1885
|
//#region src/chat/tui/screens/conversation-picker.tsx
|
|
1886
1886
|
const SEARCH_DEBOUNCE_MS = 250;
|
|
1887
|
+
const SEARCH_QUERY_MAX_LENGTH = 200;
|
|
1887
1888
|
const humanChannels = [
|
|
1888
1889
|
"web",
|
|
1889
1890
|
"slack",
|
|
@@ -2211,8 +2212,9 @@ function ConversationList({ agent, conversations, complete, showAutomated, onTog
|
|
|
2211
2212
|
placeholder: "type to filter…",
|
|
2212
2213
|
focused: confirmId === null,
|
|
2213
2214
|
width: Math.max(10, width - 12),
|
|
2215
|
+
maxLength: SEARCH_QUERY_MAX_LENGTH,
|
|
2214
2216
|
onInput: (value) => {
|
|
2215
|
-
setQuery(value);
|
|
2217
|
+
setQuery(value.slice(0, SEARCH_QUERY_MAX_LENGTH));
|
|
2216
2218
|
setHighlight(0);
|
|
2217
2219
|
}
|
|
2218
2220
|
})]
|
|
@@ -11216,6 +11218,126 @@ var LinkifiedMarkdownRenderable = class extends MarkdownRenderable {
|
|
|
11216
11218
|
}
|
|
11217
11219
|
};
|
|
11218
11220
|
|
|
11221
|
+
//#endregion
|
|
11222
|
+
//#region src/chat/memory-watchdog.ts
|
|
11223
|
+
const MB = 1024 * 1024;
|
|
11224
|
+
/** How often to sample RSS. */
|
|
11225
|
+
const DEFAULT_SAMPLE_INTERVAL_MS = 15e3;
|
|
11226
|
+
/**
|
|
11227
|
+
* Soft threshold: cross it and we warn the user once. A healthy chat session
|
|
11228
|
+
* sits in the low hundreds of MB, so 2 GB is "something is wrong" without
|
|
11229
|
+
* being so eager it fires on a legitimately large conversation.
|
|
11230
|
+
*/
|
|
11231
|
+
const DEFAULT_WARN_THRESHOLD_BYTES = 2 * 1024 * MB;
|
|
11232
|
+
/**
|
|
11233
|
+
* A clean exit still writes a report if the peak got this high — so we learn
|
|
11234
|
+
* about near-misses that didn't quite OOM, not just the crashes.
|
|
11235
|
+
*/
|
|
11236
|
+
const DEFAULT_REPORT_THRESHOLD_BYTES = 4 * 1024 * MB;
|
|
11237
|
+
/** Keep the last N samples so the report shows a growth curve, not a point. */
|
|
11238
|
+
const MAX_SAMPLES = 240;
|
|
11239
|
+
function envBytes(name, fallback) {
|
|
11240
|
+
const raw = process.env[name];
|
|
11241
|
+
if (!raw) return fallback;
|
|
11242
|
+
const n = Number(raw);
|
|
11243
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
11244
|
+
}
|
|
11245
|
+
function envMs(name, fallback) {
|
|
11246
|
+
const raw = process.env[name];
|
|
11247
|
+
if (!raw) return fallback;
|
|
11248
|
+
const n = Number(raw);
|
|
11249
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
11250
|
+
}
|
|
11251
|
+
/**
|
|
11252
|
+
* Start the memory watchdog. Returns a handle; call `stop()` on teardown.
|
|
11253
|
+
*
|
|
11254
|
+
* Disabled entirely when `SKYDIVE_NO_MEMORY_WATCHDOG` is set — an escape
|
|
11255
|
+
* hatch that also keeps the sampler out of the way in tests and CI.
|
|
11256
|
+
*/
|
|
11257
|
+
function startMemoryWatchdog(opts = {}) {
|
|
11258
|
+
const disabled = Boolean(process.env["SKYDIVE_NO_MEMORY_WATCHDOG"]);
|
|
11259
|
+
const now = opts.now ?? (() => Date.now());
|
|
11260
|
+
const readMemory = opts.readMemory ?? (() => {
|
|
11261
|
+
const u = process.memoryUsage();
|
|
11262
|
+
return {
|
|
11263
|
+
rss: u.rss,
|
|
11264
|
+
heapUsed: u.heapUsed
|
|
11265
|
+
};
|
|
11266
|
+
});
|
|
11267
|
+
const sampleIntervalMs = opts.sampleIntervalMs ?? envMs("SKYDIVE_MEMORY_SAMPLE_MS", DEFAULT_SAMPLE_INTERVAL_MS);
|
|
11268
|
+
const warnThreshold = opts.warnThresholdBytes ?? envBytes("SKYDIVE_MEMORY_WARN_BYTES", DEFAULT_WARN_THRESHOLD_BYTES);
|
|
11269
|
+
const reportThreshold = opts.reportThresholdBytes ?? envBytes("SKYDIVE_MEMORY_REPORT_BYTES", DEFAULT_REPORT_THRESHOLD_BYTES);
|
|
11270
|
+
const startedAt = now();
|
|
11271
|
+
const samples = [];
|
|
11272
|
+
let peakRss = 0;
|
|
11273
|
+
let peakHeapUsed = 0;
|
|
11274
|
+
let warned = false;
|
|
11275
|
+
function sample() {
|
|
11276
|
+
const { rss, heapUsed } = readMemory();
|
|
11277
|
+
if (rss > peakRss) peakRss = rss;
|
|
11278
|
+
if (heapUsed > peakHeapUsed) peakHeapUsed = heapUsed;
|
|
11279
|
+
const s = {
|
|
11280
|
+
at: now() - startedAt,
|
|
11281
|
+
rss,
|
|
11282
|
+
heapUsed
|
|
11283
|
+
};
|
|
11284
|
+
samples.push(s);
|
|
11285
|
+
if (samples.length > MAX_SAMPLES) samples.shift();
|
|
11286
|
+
if (!warned && rss >= warnThreshold) {
|
|
11287
|
+
warned = true;
|
|
11288
|
+
opts.onWarn?.({
|
|
11289
|
+
rss,
|
|
11290
|
+
threshold: warnThreshold
|
|
11291
|
+
});
|
|
11292
|
+
}
|
|
11293
|
+
return s;
|
|
11294
|
+
}
|
|
11295
|
+
function snapshot() {
|
|
11296
|
+
if (disabled) return null;
|
|
11297
|
+
sample();
|
|
11298
|
+
return {
|
|
11299
|
+
peakRss,
|
|
11300
|
+
peakHeapUsed,
|
|
11301
|
+
warnThreshold,
|
|
11302
|
+
uptimeMs: now() - startedAt,
|
|
11303
|
+
samples: samples.slice()
|
|
11304
|
+
};
|
|
11305
|
+
}
|
|
11306
|
+
if (disabled) return {
|
|
11307
|
+
peakRss: () => 0,
|
|
11308
|
+
samples: () => [],
|
|
11309
|
+
snapshot: () => null,
|
|
11310
|
+
stop: () => {}
|
|
11311
|
+
};
|
|
11312
|
+
sample();
|
|
11313
|
+
const timer = setInterval(sample, sampleIntervalMs);
|
|
11314
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
11315
|
+
const onExit = () => {
|
|
11316
|
+
if (peakRss < reportThreshold) return;
|
|
11317
|
+
writeCrashReport(buildCrashReport({
|
|
11318
|
+
reason: "high-memory-exit",
|
|
11319
|
+
memory: {
|
|
11320
|
+
peakRss,
|
|
11321
|
+
peakHeapUsed,
|
|
11322
|
+
warnThreshold,
|
|
11323
|
+
uptimeMs: now() - startedAt,
|
|
11324
|
+
samples: samples.slice()
|
|
11325
|
+
}
|
|
11326
|
+
}));
|
|
11327
|
+
};
|
|
11328
|
+
const installExitHandler = opts.installExitHandler ?? true;
|
|
11329
|
+
if (installExitHandler) process.on("exit", onExit);
|
|
11330
|
+
return {
|
|
11331
|
+
peakRss: () => peakRss,
|
|
11332
|
+
samples: () => samples.slice(),
|
|
11333
|
+
snapshot,
|
|
11334
|
+
stop: () => {
|
|
11335
|
+
clearInterval(timer);
|
|
11336
|
+
if (installExitHandler) process.off("exit", onExit);
|
|
11337
|
+
}
|
|
11338
|
+
};
|
|
11339
|
+
}
|
|
11340
|
+
|
|
11219
11341
|
//#endregion
|
|
11220
11342
|
//#region src/chat/boot.tsx
|
|
11221
11343
|
/**
|
|
@@ -11225,6 +11347,8 @@ var LinkifiedMarkdownRenderable = class extends MarkdownRenderable {
|
|
|
11225
11347
|
* dynamically imported and never loaded on the Node management path.
|
|
11226
11348
|
*/
|
|
11227
11349
|
async function runChat({ appUrl, sessionToken, shareMachine, promptHistoryPath, theme: themeOverride, notifications, agentSelector, conversationId, newConversation, seedPrompt }) {
|
|
11350
|
+
const watchdog = startMemoryWatchdog();
|
|
11351
|
+
installCrashHandler({ memoryProvider: () => watchdog.snapshot() });
|
|
11228
11352
|
const renderer = await createCliRenderer({ exitOnCtrlC: false });
|
|
11229
11353
|
extend({ markdown: LinkifiedMarkdownRenderable });
|
|
11230
11354
|
useStore.setState({
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import Conf from "conf";
|
|
4
5
|
import { err, ok } from "neverthrow";
|
|
5
6
|
import { z } from "zod";
|
|
7
|
+
import fs from "node:fs";
|
|
6
8
|
|
|
9
|
+
//#region package.json
|
|
10
|
+
var name = "skydive-cli";
|
|
11
|
+
var version$1 = "0.2.0-beta.608";
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
7
14
|
//#region src/config.ts
|
|
8
15
|
/** Default host for the public management API (`/v1`, API-key auth). */
|
|
9
16
|
const DEFAULT_API_URL = "https://api.skydive.com";
|
|
@@ -1130,4 +1137,110 @@ function brandHelpArt(stream = process.stdout) {
|
|
|
1130
1137
|
}
|
|
1131
1138
|
|
|
1132
1139
|
//#endregion
|
|
1133
|
-
|
|
1140
|
+
//#region src/crash/report.ts
|
|
1141
|
+
const MB = 1024 * 1024;
|
|
1142
|
+
function currentRuntime() {
|
|
1143
|
+
const bun = process.versions["bun"];
|
|
1144
|
+
return bun ? `bun ${bun}` : `node ${process.version}`;
|
|
1145
|
+
}
|
|
1146
|
+
function serializeError(error) {
|
|
1147
|
+
if (error == null) return null;
|
|
1148
|
+
if (error instanceof Error) return {
|
|
1149
|
+
name: error.name,
|
|
1150
|
+
message: error.message,
|
|
1151
|
+
...error.stack ? { stack: error.stack } : {}
|
|
1152
|
+
};
|
|
1153
|
+
return {
|
|
1154
|
+
name: "NonError",
|
|
1155
|
+
message: String(error)
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
/** Directory where crash/diagnostic reports are written (beside config). */
|
|
1159
|
+
function getCrashDir() {
|
|
1160
|
+
return path.join(path.dirname(getConfigPath()), "crash");
|
|
1161
|
+
}
|
|
1162
|
+
/** Build a report object without touching disk. */
|
|
1163
|
+
function buildCrashReport(args) {
|
|
1164
|
+
return {
|
|
1165
|
+
reason: args.reason,
|
|
1166
|
+
cliVersion: version$1,
|
|
1167
|
+
runtime: currentRuntime(),
|
|
1168
|
+
platform: process.platform,
|
|
1169
|
+
arch: process.arch,
|
|
1170
|
+
nodeVersion: process.version,
|
|
1171
|
+
totalSystemMemory: os.totalmem(),
|
|
1172
|
+
error: serializeError(args.error),
|
|
1173
|
+
memory: args.memory ?? null,
|
|
1174
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Write a report to disk and return its path (or null if writing failed).
|
|
1179
|
+
* Safe to call from a fatal handler: every failure is swallowed so the
|
|
1180
|
+
* diagnostic can never mask the original crash.
|
|
1181
|
+
*/
|
|
1182
|
+
function writeCrashReport(report) {
|
|
1183
|
+
try {
|
|
1184
|
+
const dir = getCrashDir();
|
|
1185
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1186
|
+
const stamp = report.timestamp.replace(/[:.]/g, "-");
|
|
1187
|
+
const file = path.join(dir, `crash-${stamp}.json`);
|
|
1188
|
+
fs.writeFileSync(file, `${JSON.stringify(report, null, 2)}\n`, { mode: 384 });
|
|
1189
|
+
return file;
|
|
1190
|
+
} catch (_error) {
|
|
1191
|
+
return null;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
/** Human-readable MB, one decimal. */
|
|
1195
|
+
function formatMb(bytes) {
|
|
1196
|
+
return `${(bytes / MB).toFixed(1)} MB`;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
//#endregion
|
|
1200
|
+
//#region src/crash/install.ts
|
|
1201
|
+
let installed = false;
|
|
1202
|
+
/**
|
|
1203
|
+
* Install the process-wide fatal crash handler. Idempotent: a second call is
|
|
1204
|
+
* a no-op, and later options (e.g. a memory provider registered once chat
|
|
1205
|
+
* boots) update the live handler in place.
|
|
1206
|
+
*
|
|
1207
|
+
* Disabled entirely by `SKYDIVE_NO_CRASH_REPORT` — the escape hatch, and how
|
|
1208
|
+
* tests keep a real handler off the shared process.
|
|
1209
|
+
*/
|
|
1210
|
+
function installCrashHandler(opts = {}) {
|
|
1211
|
+
if (process.env["SKYDIVE_NO_CRASH_REPORT"]) return;
|
|
1212
|
+
memoryProvider = opts.memoryProvider ?? memoryProvider;
|
|
1213
|
+
writeNotice = opts.writeNotice ?? writeNotice;
|
|
1214
|
+
exitProcess = opts.exit ?? exitProcess;
|
|
1215
|
+
if (installed) return;
|
|
1216
|
+
installed = true;
|
|
1217
|
+
process.on("uncaughtException", (error) => {
|
|
1218
|
+
const memory = safeMemory();
|
|
1219
|
+
printFatalNotice(writeCrashReport(buildCrashReport({
|
|
1220
|
+
reason: "uncaughtException",
|
|
1221
|
+
error,
|
|
1222
|
+
memory
|
|
1223
|
+
})), memory);
|
|
1224
|
+
exitProcess(1);
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
const defaultWriteNotice = (text) => process.stderr.write(text);
|
|
1228
|
+
const defaultExit = (code) => process.exit(code);
|
|
1229
|
+
let memoryProvider = null;
|
|
1230
|
+
let writeNotice = defaultWriteNotice;
|
|
1231
|
+
let exitProcess = defaultExit;
|
|
1232
|
+
function safeMemory() {
|
|
1233
|
+
try {
|
|
1234
|
+
return memoryProvider?.() ?? void 0;
|
|
1235
|
+
} catch (_error) {
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
function printFatalNotice(file, memory) {
|
|
1240
|
+
const peak = memory ? ` (peak memory ${formatMb(memory.peakRss)})` : "";
|
|
1241
|
+
if (file) writeNotice(`\nskydive: the CLI hit a fatal error${peak}. A diagnostic report was written to:\n ${file}\nPlease send this file to the Skydive team so we can investigate.\n`);
|
|
1242
|
+
else writeNotice(`\nskydive: the CLI hit a fatal error${peak}.\n`);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
//#endregion
|
|
1246
|
+
export { deleteConfig as A, resolveAppUrl as B, setActiveWorkspace as C, DEFAULT_API_URL as D, API_KEY_PREFIX as E, getSavedTheme as F, saveConfig as G, resolveManagementAuth as H, getShareMachineDefault as I, setLastSeenVersion as J, saveSession as K, getStoredApiKeyId as L, getLastSeenVersion as M, getPromptHistoryPath as N, DEFAULT_APP_URL as O, getReviewStateDir as P, getStoredApiKeyWorkspaceName as R, listWorkspaces as S, API_KEY_FAMILY_PREFIX as T, resolveSession as U, resolveConfig as V, resolveWebUrl as W, version$1 as X, name as Y, themes as _, WORDMARK as a, getActiveWorkspaceId as b, applyTheme as c, noColorRequested as d, theme as f, themeVersion as g, themeModeFromColorFgBg as h, MARK_CELLS as i, getConfigPath as j, DEFAULT_WEB_URL as k, findTheme as l, themeMode as m, buildCrashReport as n, brandHelpArt as o, themeForMode as p, saveTheme as q, writeCrashReport as r, DEFAULT_THEME_ID as s, installCrashHandler as t, monoTheme as u, themesForMode as v, API_KEYS_URL as w, getSessionIdentity as x, ensureActiveOrganization as y, getUpdateCheckDisabled as z };
|