skydive-cli 0.4.0-beta.1033 → 0.4.0-beta.1068
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 { C as setActiveWorkspace,
|
|
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-UzSfz08d.mjs";
|
|
3
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-CiaU2ygh.mjs";
|
|
4
4
|
import { n as printError, r as printTable, t as output } from "./output-DYzzdXYV.mjs";
|
|
5
5
|
import { n as createRestClient, t as HttpError } from "./rest-CG7VpQ56.mjs";
|
|
@@ -1505,7 +1505,7 @@ const importCommand = {
|
|
|
1505
1505
|
process.exit(1);
|
|
1506
1506
|
}
|
|
1507
1507
|
}
|
|
1508
|
-
const { runChat } = await import("./boot-
|
|
1508
|
+
const { runChat } = await import("./boot-BLwtCROn.mjs");
|
|
1509
1509
|
await runChat({
|
|
1510
1510
|
appUrl,
|
|
1511
1511
|
sessionToken: session.value.sessionToken,
|
|
@@ -1917,7 +1917,7 @@ const chatCommand = {
|
|
|
1917
1917
|
sessionToken: auth.value.token,
|
|
1918
1918
|
agentSelector: argv.agent ?? null
|
|
1919
1919
|
});
|
|
1920
|
-
const { runChat } = await import("./boot-
|
|
1920
|
+
const { runChat } = await import("./boot-BLwtCROn.mjs");
|
|
1921
1921
|
await runChat({
|
|
1922
1922
|
appUrl: auth.value.appUrl,
|
|
1923
1923
|
sessionToken: auth.value.token,
|
|
@@ -2276,7 +2276,7 @@ const switchCommand = {
|
|
|
2276
2276
|
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.");
|
|
2277
2277
|
process.exit(1);
|
|
2278
2278
|
}
|
|
2279
|
-
const { runWorkspacePicker } = await import("./boot-
|
|
2279
|
+
const { runWorkspacePicker } = await import("./boot-BLwtCROn.mjs");
|
|
2280
2280
|
await runWorkspacePicker(session);
|
|
2281
2281
|
return;
|
|
2282
2282
|
}
|
|
@@ -3881,6 +3881,7 @@ function maybePrintWhatsNew({ stderrIsTTY = process.stderr.isTTY ?? false, nonIn
|
|
|
3881
3881
|
//#endregion
|
|
3882
3882
|
//#region src/bin.ts
|
|
3883
3883
|
installCrashHandler();
|
|
3884
|
+
maybeStartProfiling(hideBin(process.argv), version);
|
|
3884
3885
|
if (process.argv.includes(UPDATE_WORKER_FLAG)) {
|
|
3885
3886
|
await runUpdateCheckWorker();
|
|
3886
3887
|
process.exit(0);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
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-UzSfz08d.mjs";
|
|
3
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-CiaU2ygh.mjs";
|
|
4
4
|
import { a as errorMessage, i as sendErrorMessage, n as createRestClient, o as isRecord, r as errorDetail, t as HttpError } from "./rest-CG7VpQ56.mjs";
|
|
5
5
|
import { i as billingBlockedOutcomeFromSendResponse } from "./billing-blocked-CwfG1BTR.mjs";
|
|
@@ -19,7 +19,7 @@ import { connect, createConnection } from "node:net";
|
|
|
19
19
|
import { access, appendFile, mkdir, mkdtemp, readFile, readdir, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
20
20
|
import { MarkdownRenderable, RenderableEvents, StyledText, SyntaxStyle, addDefaultParsers, createCliRenderer, decodePasteBytes, detectLinks, fg, link } from "@opentui/core";
|
|
21
21
|
import { createRoot, extend, useKeyboard, usePaste, useRenderer, useTerminalDimensions } from "@opentui/react";
|
|
22
|
-
import { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
22
|
+
import { Profiler, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
23
23
|
import { create } from "zustand";
|
|
24
24
|
import { Fragment, jsx, jsxs } from "@opentui/react/jsx-runtime";
|
|
25
25
|
import fuzzysort from "fuzzysort";
|
|
@@ -12317,6 +12317,97 @@ async function settleBootThemeMode({ source, applyThemeMode, graceMs = THEME_QUE
|
|
|
12317
12317
|
if (answered) applyThemeMode(answered);
|
|
12318
12318
|
}
|
|
12319
12319
|
|
|
12320
|
+
//#endregion
|
|
12321
|
+
//#region src/profiling/tui.ts
|
|
12322
|
+
/**
|
|
12323
|
+
* TUI-side profiling instrumentation. Everything here rides on the shared
|
|
12324
|
+
* profile directory created in bin.ts (see profiler.ts) and is inert unless
|
|
12325
|
+
* SKYDIVE_PROFILE is set.
|
|
12326
|
+
*/
|
|
12327
|
+
/**
|
|
12328
|
+
* Renderer options to merge into createCliRenderer when profiling:
|
|
12329
|
+
* gatherStats makes OpenTUI retain per-frame timings (frame time, cells
|
|
12330
|
+
* updated, native render + stdout write time) that getStats() exposes.
|
|
12331
|
+
*/
|
|
12332
|
+
function profilingRendererOptions() {
|
|
12333
|
+
return profilingEnabled() ? { gatherStats: true } : {};
|
|
12334
|
+
}
|
|
12335
|
+
/**
|
|
12336
|
+
* Samples renderer stats periodically and dumps the full series at exit.
|
|
12337
|
+
* The periodic samples give the timeline shape (fps over the session); the
|
|
12338
|
+
* final dump carries the complete frame-time distribution.
|
|
12339
|
+
*/
|
|
12340
|
+
function startRendererStatsCapture(renderer) {
|
|
12341
|
+
if (!profilingEnabled()) return;
|
|
12342
|
+
const sample = () => {
|
|
12343
|
+
const s = renderer.getStats();
|
|
12344
|
+
record("render", {
|
|
12345
|
+
fps: s.fps,
|
|
12346
|
+
frameCount: s.frameCount,
|
|
12347
|
+
averageFrameTime: s.averageFrameTime,
|
|
12348
|
+
maxFrameTime: s.maxFrameTime,
|
|
12349
|
+
cellsUpdated: s.cellsUpdated,
|
|
12350
|
+
nativeRenderTime: s.nativeRenderTime ?? null,
|
|
12351
|
+
nativeStdoutWriteTime: s.nativeStdoutWriteTime ?? null
|
|
12352
|
+
});
|
|
12353
|
+
};
|
|
12354
|
+
const interval = setInterval(sample, 1e3);
|
|
12355
|
+
interval.unref?.();
|
|
12356
|
+
process.on("exit", () => {
|
|
12357
|
+
clearInterval(interval);
|
|
12358
|
+
const s = renderer.getStats();
|
|
12359
|
+
writeArtifact("render.json", {
|
|
12360
|
+
fps: s.fps,
|
|
12361
|
+
frameCount: s.frameCount,
|
|
12362
|
+
frameTimes: s.frameTimes,
|
|
12363
|
+
averageFrameTime: s.averageFrameTime,
|
|
12364
|
+
minFrameTime: s.minFrameTime,
|
|
12365
|
+
maxFrameTime: s.maxFrameTime,
|
|
12366
|
+
cellsUpdated: s.cellsUpdated,
|
|
12367
|
+
averageCellsUpdated: s.averageCellsUpdated
|
|
12368
|
+
});
|
|
12369
|
+
});
|
|
12370
|
+
}
|
|
12371
|
+
/**
|
|
12372
|
+
* Records zustand store transitions. Subscribes to the whole store and
|
|
12373
|
+
* logs a compact diff-flavored event per change: the screen kind always,
|
|
12374
|
+
* plus which top-level keys changed. Gives an agent the "what was the UI
|
|
12375
|
+
* doing at t=X" axis without serializing message payloads.
|
|
12376
|
+
*/
|
|
12377
|
+
function startStateCapture(store) {
|
|
12378
|
+
if (!profilingEnabled()) return;
|
|
12379
|
+
store.subscribe((state, prev) => {
|
|
12380
|
+
const prevEntries = new Map(Object.entries(prev));
|
|
12381
|
+
const changed = [];
|
|
12382
|
+
let screenKind = null;
|
|
12383
|
+
for (const [key, value] of Object.entries(state)) {
|
|
12384
|
+
if (typeof value === "function") continue;
|
|
12385
|
+
if (value !== prevEntries.get(key)) changed.push(key);
|
|
12386
|
+
if (key === "screen" && typeof value === "object" && value !== null && "kind" in value && typeof value.kind === "string") screenKind = value.kind;
|
|
12387
|
+
}
|
|
12388
|
+
if (changed.length === 0) return;
|
|
12389
|
+
record("state", {
|
|
12390
|
+
screen: screenKind,
|
|
12391
|
+
changed
|
|
12392
|
+
});
|
|
12393
|
+
});
|
|
12394
|
+
}
|
|
12395
|
+
/**
|
|
12396
|
+
* React Profiler onRender callback for the <Profiler> wrapping <App>.
|
|
12397
|
+
* One event per commit: which subtree, mount/update, and actual vs base
|
|
12398
|
+
* duration (actualDuration >> baseDuration means memoization is losing).
|
|
12399
|
+
*/
|
|
12400
|
+
function onRenderCommit(id, phase, actualDuration, baseDuration, startTime, commitTime) {
|
|
12401
|
+
record("commits", {
|
|
12402
|
+
id,
|
|
12403
|
+
phase,
|
|
12404
|
+
actualDuration,
|
|
12405
|
+
baseDuration,
|
|
12406
|
+
startTime,
|
|
12407
|
+
commitTime
|
|
12408
|
+
});
|
|
12409
|
+
}
|
|
12410
|
+
|
|
12320
12411
|
//#endregion
|
|
12321
12412
|
//#region src/chat/boot.tsx
|
|
12322
12413
|
/**
|
|
@@ -12329,7 +12420,12 @@ async function runChat({ appUrl, sessionToken, authKind = "session", shareMachin
|
|
|
12329
12420
|
await registerGrammars();
|
|
12330
12421
|
const watchdog = startMemoryWatchdog();
|
|
12331
12422
|
installCrashHandler({ memoryProvider: () => watchdog.snapshot() });
|
|
12332
|
-
const renderer = await createCliRenderer({
|
|
12423
|
+
const renderer = await createCliRenderer({
|
|
12424
|
+
exitOnCtrlC: false,
|
|
12425
|
+
...profilingRendererOptions()
|
|
12426
|
+
});
|
|
12427
|
+
startRendererStatsCapture(renderer);
|
|
12428
|
+
startStateCapture(useStore);
|
|
12333
12429
|
extend({ markdown: LinkifiedMarkdownRenderable });
|
|
12334
12430
|
useStore.setState({
|
|
12335
12431
|
authKind,
|
|
@@ -12349,16 +12445,20 @@ async function runChat({ appUrl, sessionToken, authKind = "session", shareMachin
|
|
|
12349
12445
|
source: renderer,
|
|
12350
12446
|
applyThemeMode: (mode) => useStore.getState().setThemeMode(mode)
|
|
12351
12447
|
});
|
|
12352
|
-
createRoot(renderer).render(/* @__PURE__ */ jsx(
|
|
12353
|
-
|
|
12354
|
-
|
|
12355
|
-
|
|
12356
|
-
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12361
|
-
|
|
12448
|
+
createRoot(renderer).render(/* @__PURE__ */ jsx(Profiler, {
|
|
12449
|
+
id: "app",
|
|
12450
|
+
onRender: onRenderCommit,
|
|
12451
|
+
children: /* @__PURE__ */ jsx(App, {
|
|
12452
|
+
appUrl,
|
|
12453
|
+
sessionToken,
|
|
12454
|
+
authKind,
|
|
12455
|
+
shareMachine,
|
|
12456
|
+
promptHistoryPath,
|
|
12457
|
+
notifications,
|
|
12458
|
+
agentSelector: agentSelector ?? null,
|
|
12459
|
+
conversationId: conversationId ?? null,
|
|
12460
|
+
newConversation
|
|
12461
|
+
})
|
|
12362
12462
|
}));
|
|
12363
12463
|
}
|
|
12364
12464
|
/** Open the same workspace picker used by the initial agent screen. */
|
|
@@ -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.1068";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/auth/organization.ts
|
|
@@ -1057,4 +1057,211 @@ function printFatalNotice(file, memory) {
|
|
|
1057
1057
|
}
|
|
1058
1058
|
|
|
1059
1059
|
//#endregion
|
|
1060
|
-
|
|
1060
|
+
//#region src/profiling/profiler.ts
|
|
1061
|
+
/**
|
|
1062
|
+
* Opt-in session profiling. When SKYDIVE_PROFILE is set, an invocation
|
|
1063
|
+
* records everything needed to reconstruct what happened performance-wise —
|
|
1064
|
+
* designed so the whole directory can be handed to an agent (or a human)
|
|
1065
|
+
* and read without special tooling:
|
|
1066
|
+
*
|
|
1067
|
+
* network.ndjson every fetch: method, url, status, timing, content type
|
|
1068
|
+
* state.ndjson TUI state transitions (screen changes, store updates)
|
|
1069
|
+
* commits.ndjson React commits: which subtree rendered, when, how long
|
|
1070
|
+
* render.ndjson OpenTUI renderer samples: fps, frame times, cells drawn
|
|
1071
|
+
* render.json final renderer stats dump (full frame-time series)
|
|
1072
|
+
* cpu-<pid>.cpuprofile V8 CPU profile (Node-run commands only)
|
|
1073
|
+
* meta-<pid>.json argv, versions, runtime, exit code, wall time
|
|
1074
|
+
*
|
|
1075
|
+
* Every ndjson event carries a wall-clock `t` (epoch ms) and `pid`, so
|
|
1076
|
+
* records from the Node parent and the Bun-re-exec'd chat TUI land in the
|
|
1077
|
+
* same files and stay correlatable on one clock. The profile directory is
|
|
1078
|
+
* created by the first process and shared with children through
|
|
1079
|
+
* SKYDIVE_PROFILE_DIR (the chat re-exec inherits the environment).
|
|
1080
|
+
*
|
|
1081
|
+
* Inert unless SKYDIVE_PROFILE is set: no patched fetch, no subscriptions,
|
|
1082
|
+
* no inspector session.
|
|
1083
|
+
*/
|
|
1084
|
+
const ENV_FLAG = "SKYDIVE_PROFILE";
|
|
1085
|
+
const ENV_DIR = "SKYDIVE_PROFILE_DIR";
|
|
1086
|
+
let activeDir = null;
|
|
1087
|
+
let startedAtMs = 0;
|
|
1088
|
+
/**
|
|
1089
|
+
* Buffered event lines per stream, flushed asynchronously. Events are
|
|
1090
|
+
* appended to an in-memory buffer and written with fs.promises off the
|
|
1091
|
+
* hot path, so recording never blocks the TUI's event loop — high-rate
|
|
1092
|
+
* streams (React commits, renderer samples) stay cheap. Whatever is
|
|
1093
|
+
* still buffered when the process exits is drained synchronously in the
|
|
1094
|
+
* exit handler, where async I/O would never flush.
|
|
1095
|
+
*/
|
|
1096
|
+
const pendingLines = /* @__PURE__ */ new Map();
|
|
1097
|
+
let flushScheduled = false;
|
|
1098
|
+
let flushing = Promise.resolve();
|
|
1099
|
+
function drainBuffersSync() {
|
|
1100
|
+
if (activeDir === null) return;
|
|
1101
|
+
for (const [stream, lines] of pendingLines) {
|
|
1102
|
+
if (lines.length === 0) continue;
|
|
1103
|
+
pendingLines.set(stream, []);
|
|
1104
|
+
try {
|
|
1105
|
+
fs.appendFileSync(path.join(activeDir, `${stream}.ndjson`), lines.join("\n") + "\n");
|
|
1106
|
+
} catch (_error) {}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
function scheduleFlush() {
|
|
1110
|
+
if (flushScheduled || activeDir === null) return;
|
|
1111
|
+
flushScheduled = true;
|
|
1112
|
+
setTimeout(() => {
|
|
1113
|
+
flushScheduled = false;
|
|
1114
|
+
flushing = flushing.then(async () => {
|
|
1115
|
+
if (activeDir === null) return;
|
|
1116
|
+
for (const [stream, lines] of pendingLines) {
|
|
1117
|
+
if (lines.length === 0) continue;
|
|
1118
|
+
pendingLines.set(stream, []);
|
|
1119
|
+
try {
|
|
1120
|
+
await fs.promises.appendFile(path.join(activeDir, `${stream}.ndjson`), lines.join("\n") + "\n");
|
|
1121
|
+
} catch (_error) {}
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
}, 100).unref?.();
|
|
1125
|
+
}
|
|
1126
|
+
function profilingEnabled() {
|
|
1127
|
+
const v = process.env[ENV_FLAG];
|
|
1128
|
+
return v !== void 0 && v !== "" && v !== "0";
|
|
1129
|
+
}
|
|
1130
|
+
function sanitizeToken(token) {
|
|
1131
|
+
return token.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Appends one event to a stream file. Buffered and written asynchronously
|
|
1135
|
+
* so recording never blocks the event loop; the exit handler drains any
|
|
1136
|
+
* remainder synchronously so abrupt exits still keep their events.
|
|
1137
|
+
*/
|
|
1138
|
+
function record(stream, event) {
|
|
1139
|
+
if (activeDir === null) return;
|
|
1140
|
+
const line = JSON.stringify({
|
|
1141
|
+
t: Date.now(),
|
|
1142
|
+
pid: process.pid,
|
|
1143
|
+
...event
|
|
1144
|
+
});
|
|
1145
|
+
const lines = pendingLines.get(stream);
|
|
1146
|
+
if (lines === void 0) pendingLines.set(stream, [line]);
|
|
1147
|
+
else lines.push(line);
|
|
1148
|
+
scheduleFlush();
|
|
1149
|
+
}
|
|
1150
|
+
/** Writes a JSON artifact (non-append) into the profile directory. */
|
|
1151
|
+
function writeArtifact(name, data) {
|
|
1152
|
+
if (activeDir === null) return;
|
|
1153
|
+
try {
|
|
1154
|
+
fs.writeFileSync(path.join(activeDir, name), JSON.stringify(data, null, 2));
|
|
1155
|
+
} catch (_error) {}
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Patches globalThis.fetch to record request timing. A wrapper (not
|
|
1159
|
+
* undici's diagnostics_channel) because chat re-execs under Bun, where
|
|
1160
|
+
* fetch is Bun-native and undici events never fire; the wrapper behaves
|
|
1161
|
+
* identically in both runtimes.
|
|
1162
|
+
*/
|
|
1163
|
+
function installFetchRecorder() {
|
|
1164
|
+
const original = globalThis.fetch;
|
|
1165
|
+
const wrapped = async (...args) => {
|
|
1166
|
+
const [input, init] = args;
|
|
1167
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
1168
|
+
const method = init?.method ?? (input instanceof Request ? input.method : "GET");
|
|
1169
|
+
const started = Date.now();
|
|
1170
|
+
try {
|
|
1171
|
+
const res = await original(...args);
|
|
1172
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
1173
|
+
record("network", {
|
|
1174
|
+
method,
|
|
1175
|
+
url,
|
|
1176
|
+
status: res.status,
|
|
1177
|
+
durationMs: Date.now() - started,
|
|
1178
|
+
contentType,
|
|
1179
|
+
streamed: contentType.includes("text/event-stream")
|
|
1180
|
+
});
|
|
1181
|
+
return res;
|
|
1182
|
+
} catch (err) {
|
|
1183
|
+
record("network", {
|
|
1184
|
+
method,
|
|
1185
|
+
url,
|
|
1186
|
+
status: 0,
|
|
1187
|
+
durationMs: Date.now() - started,
|
|
1188
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1189
|
+
});
|
|
1190
|
+
throw err;
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
globalThis.fetch = Object.assign(wrapped, original);
|
|
1194
|
+
}
|
|
1195
|
+
function isBunRuntime() {
|
|
1196
|
+
return typeof process !== "undefined" && "bun" in process.versions;
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Starts the V8 CPU profiler via node:inspector. Node-run commands only —
|
|
1200
|
+
* Bun does not implement the inspector Profiler domain, so the chat TUI
|
|
1201
|
+
* skips this artifact.
|
|
1202
|
+
*/
|
|
1203
|
+
function startCpuProfile() {
|
|
1204
|
+
if (isBunRuntime()) return;
|
|
1205
|
+
(async () => {
|
|
1206
|
+
try {
|
|
1207
|
+
const { Session } = await import("node:inspector/promises");
|
|
1208
|
+
const session = new Session();
|
|
1209
|
+
session.connect();
|
|
1210
|
+
await session.post("Profiler.enable");
|
|
1211
|
+
await session.post("Profiler.start");
|
|
1212
|
+
process.once("beforeExit", () => {
|
|
1213
|
+
(async () => {
|
|
1214
|
+
try {
|
|
1215
|
+
const { profile } = await session.post("Profiler.stop");
|
|
1216
|
+
writeArtifact(`cpu-${process.pid}.cpuprofile`, profile);
|
|
1217
|
+
session.disconnect();
|
|
1218
|
+
} catch (_error) {}
|
|
1219
|
+
})();
|
|
1220
|
+
});
|
|
1221
|
+
} catch (_error) {}
|
|
1222
|
+
})();
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Activates profiling for this process if SKYDIVE_PROFILE is set. Creates
|
|
1226
|
+
* the profile directory (or joins the one a parent process created),
|
|
1227
|
+
* patches fetch, starts the CPU profiler, and registers the exit-time
|
|
1228
|
+
* meta dump. Call once, as early as possible.
|
|
1229
|
+
*/
|
|
1230
|
+
function maybeStartProfiling(argv, cliVersion) {
|
|
1231
|
+
if (!profilingEnabled() || activeDir !== null) return;
|
|
1232
|
+
const inherited = process.env[ENV_DIR];
|
|
1233
|
+
if (inherited !== void 0 && inherited !== "") activeDir = inherited;
|
|
1234
|
+
else {
|
|
1235
|
+
const flagValue = process.env[ENV_FLAG] ?? "1";
|
|
1236
|
+
const command = argv.find((a) => !a.startsWith("-")) ?? "chat";
|
|
1237
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
1238
|
+
activeDir = flagValue === "1" || flagValue.toLowerCase() === "true" ? path.resolve(process.cwd(), `skydive-profile-${sanitizeToken(command)}-${stamp}`) : path.resolve(process.cwd(), flagValue);
|
|
1239
|
+
process.env[ENV_DIR] = activeDir;
|
|
1240
|
+
}
|
|
1241
|
+
try {
|
|
1242
|
+
fs.mkdirSync(activeDir, { recursive: true });
|
|
1243
|
+
} catch (_error) {
|
|
1244
|
+
activeDir = null;
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
startedAtMs = Date.now();
|
|
1248
|
+
installFetchRecorder();
|
|
1249
|
+
startCpuProfile();
|
|
1250
|
+
process.on("exit", (code) => {
|
|
1251
|
+
drainBuffersSync();
|
|
1252
|
+
writeArtifact(`meta-${process.pid}.json`, {
|
|
1253
|
+
argv,
|
|
1254
|
+
cliVersion,
|
|
1255
|
+
runtime: isBunRuntime() ? `bun ${process.versions["bun"]}` : `node ${process.version}`,
|
|
1256
|
+
platform: process.platform,
|
|
1257
|
+
pid: process.pid,
|
|
1258
|
+
exitCode: code,
|
|
1259
|
+
startedAt: new Date(startedAtMs).toISOString(),
|
|
1260
|
+
wallTimeMs: Date.now() - startedAtMs
|
|
1261
|
+
});
|
|
1262
|
+
if (process.env[ENV_DIR] === activeDir && inherited === void 0) process.stderr.write(`\nprofile written to ${activeDir}\n`);
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
//#endregion
|
|
1267
|
+
export { ensureActiveOrganization as C, setActiveWorkspace as D, listWorkspaces as E, name as O, themesForMode as S, getSessionIdentity as T, themeForMode as _, installCrashHandler as a, themeVersion as b, MARK_CELLS as c, DEFAULT_THEME_ID as d, applyTheme as f, theme as g, noColorRequested as h, writeArtifact as i, version$1 as k, WORDMARK as l, monoTheme as m, profilingEnabled as n, buildCrashReport as o, findTheme as p, record as r, writeCrashReport as s, maybeStartProfiling as t, brandHelpArt as u, themeMode as v, getActiveWorkspaceId as w, themes as x, themeModeFromColorFgBg as y };
|