@vendian/cli 0.0.9 → 0.0.11
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/cli-wrapper.mjs +1505 -167
- package/package.json +2 -1
package/cli-wrapper.mjs
CHANGED
|
@@ -1381,7 +1381,7 @@ var require_react_development = __commonJS({
|
|
|
1381
1381
|
var dispatcher = resolveDispatcher();
|
|
1382
1382
|
return dispatcher.useReducer(reducer, initialArg, init);
|
|
1383
1383
|
}
|
|
1384
|
-
function
|
|
1384
|
+
function useRef3(initialValue) {
|
|
1385
1385
|
var dispatcher = resolveDispatcher();
|
|
1386
1386
|
return dispatcher.useRef(initialValue);
|
|
1387
1387
|
}
|
|
@@ -2175,7 +2175,7 @@ var require_react_development = __commonJS({
|
|
|
2175
2175
|
exports.useLayoutEffect = useLayoutEffect2;
|
|
2176
2176
|
exports.useMemo = useMemo3;
|
|
2177
2177
|
exports.useReducer = useReducer;
|
|
2178
|
-
exports.useRef =
|
|
2178
|
+
exports.useRef = useRef3;
|
|
2179
2179
|
exports.useState = useState6;
|
|
2180
2180
|
exports.useSyncExternalStore = useSyncExternalStore;
|
|
2181
2181
|
exports.useTransition = useTransition;
|
|
@@ -24765,10 +24765,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24765
24765
|
var setErrorHandler = null;
|
|
24766
24766
|
var setSuspenseHandler = null;
|
|
24767
24767
|
{
|
|
24768
|
-
var copyWithDeleteImpl = function(obj,
|
|
24769
|
-
var key =
|
|
24768
|
+
var copyWithDeleteImpl = function(obj, path8, index2) {
|
|
24769
|
+
var key = path8[index2];
|
|
24770
24770
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
24771
|
-
if (index2 + 1 ===
|
|
24771
|
+
if (index2 + 1 === path8.length) {
|
|
24772
24772
|
if (isArray(updated)) {
|
|
24773
24773
|
updated.splice(key, 1);
|
|
24774
24774
|
} else {
|
|
@@ -24776,11 +24776,11 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24776
24776
|
}
|
|
24777
24777
|
return updated;
|
|
24778
24778
|
}
|
|
24779
|
-
updated[key] = copyWithDeleteImpl(obj[key],
|
|
24779
|
+
updated[key] = copyWithDeleteImpl(obj[key], path8, index2 + 1);
|
|
24780
24780
|
return updated;
|
|
24781
24781
|
};
|
|
24782
|
-
var copyWithDelete = function(obj,
|
|
24783
|
-
return copyWithDeleteImpl(obj,
|
|
24782
|
+
var copyWithDelete = function(obj, path8) {
|
|
24783
|
+
return copyWithDeleteImpl(obj, path8, 0);
|
|
24784
24784
|
};
|
|
24785
24785
|
var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
|
|
24786
24786
|
var oldKey = oldPath[index2];
|
|
@@ -24818,17 +24818,17 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24818
24818
|
}
|
|
24819
24819
|
return copyWithRenameImpl(obj, oldPath, newPath, 0);
|
|
24820
24820
|
};
|
|
24821
|
-
var copyWithSetImpl = function(obj,
|
|
24822
|
-
if (index2 >=
|
|
24821
|
+
var copyWithSetImpl = function(obj, path8, index2, value) {
|
|
24822
|
+
if (index2 >= path8.length) {
|
|
24823
24823
|
return value;
|
|
24824
24824
|
}
|
|
24825
|
-
var key =
|
|
24825
|
+
var key = path8[index2];
|
|
24826
24826
|
var updated = isArray(obj) ? obj.slice() : assign({}, obj);
|
|
24827
|
-
updated[key] = copyWithSetImpl(obj[key],
|
|
24827
|
+
updated[key] = copyWithSetImpl(obj[key], path8, index2 + 1, value);
|
|
24828
24828
|
return updated;
|
|
24829
24829
|
};
|
|
24830
|
-
var copyWithSet = function(obj,
|
|
24831
|
-
return copyWithSetImpl(obj,
|
|
24830
|
+
var copyWithSet = function(obj, path8, value) {
|
|
24831
|
+
return copyWithSetImpl(obj, path8, 0, value);
|
|
24832
24832
|
};
|
|
24833
24833
|
var findHook = function(fiber, id) {
|
|
24834
24834
|
var currentHook2 = fiber.memoizedState;
|
|
@@ -24838,10 +24838,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24838
24838
|
}
|
|
24839
24839
|
return currentHook2;
|
|
24840
24840
|
};
|
|
24841
|
-
overrideHookState = function(fiber, id,
|
|
24841
|
+
overrideHookState = function(fiber, id, path8, value) {
|
|
24842
24842
|
var hook = findHook(fiber, id);
|
|
24843
24843
|
if (hook !== null) {
|
|
24844
|
-
var newState = copyWithSet(hook.memoizedState,
|
|
24844
|
+
var newState = copyWithSet(hook.memoizedState, path8, value);
|
|
24845
24845
|
hook.memoizedState = newState;
|
|
24846
24846
|
hook.baseState = newState;
|
|
24847
24847
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -24851,10 +24851,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24851
24851
|
}
|
|
24852
24852
|
}
|
|
24853
24853
|
};
|
|
24854
|
-
overrideHookStateDeletePath = function(fiber, id,
|
|
24854
|
+
overrideHookStateDeletePath = function(fiber, id, path8) {
|
|
24855
24855
|
var hook = findHook(fiber, id);
|
|
24856
24856
|
if (hook !== null) {
|
|
24857
|
-
var newState = copyWithDelete(hook.memoizedState,
|
|
24857
|
+
var newState = copyWithDelete(hook.memoizedState, path8);
|
|
24858
24858
|
hook.memoizedState = newState;
|
|
24859
24859
|
hook.baseState = newState;
|
|
24860
24860
|
fiber.memoizedProps = assign({}, fiber.memoizedProps);
|
|
@@ -24877,8 +24877,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24877
24877
|
}
|
|
24878
24878
|
}
|
|
24879
24879
|
};
|
|
24880
|
-
overrideProps = function(fiber,
|
|
24881
|
-
fiber.pendingProps = copyWithSet(fiber.memoizedProps,
|
|
24880
|
+
overrideProps = function(fiber, path8, value) {
|
|
24881
|
+
fiber.pendingProps = copyWithSet(fiber.memoizedProps, path8, value);
|
|
24882
24882
|
if (fiber.alternate) {
|
|
24883
24883
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
24884
24884
|
}
|
|
@@ -24887,8 +24887,8 @@ var require_react_reconciler_development = __commonJS({
|
|
|
24887
24887
|
scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
|
|
24888
24888
|
}
|
|
24889
24889
|
};
|
|
24890
|
-
overridePropsDeletePath = function(fiber,
|
|
24891
|
-
fiber.pendingProps = copyWithDelete(fiber.memoizedProps,
|
|
24890
|
+
overridePropsDeletePath = function(fiber, path8) {
|
|
24891
|
+
fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path8);
|
|
24892
24892
|
if (fiber.alternate) {
|
|
24893
24893
|
fiber.alternate.pendingProps = fiber.pendingProps;
|
|
24894
24894
|
}
|
|
@@ -32281,7 +32281,7 @@ var init_Text = __esm({
|
|
|
32281
32281
|
});
|
|
32282
32282
|
|
|
32283
32283
|
// node_modules/ink/build/components/ErrorOverview.js
|
|
32284
|
-
import * as
|
|
32284
|
+
import * as fs11 from "node:fs";
|
|
32285
32285
|
import { cwd } from "node:process";
|
|
32286
32286
|
function ErrorOverview({ error }) {
|
|
32287
32287
|
const stack = error.stack ? error.stack.split("\n").slice(1) : void 0;
|
|
@@ -32289,8 +32289,8 @@ function ErrorOverview({ error }) {
|
|
|
32289
32289
|
const filePath = cleanupPath(origin?.file);
|
|
32290
32290
|
let excerpt;
|
|
32291
32291
|
let lineWidth = 0;
|
|
32292
|
-
if (filePath && origin?.line &&
|
|
32293
|
-
const sourceCode =
|
|
32292
|
+
if (filePath && origin?.line && fs11.existsSync(filePath)) {
|
|
32293
|
+
const sourceCode = fs11.readFileSync(filePath, "utf8");
|
|
32294
32294
|
excerpt = dist_default3(sourceCode, origin.line);
|
|
32295
32295
|
if (excerpt) {
|
|
32296
32296
|
for (const { line } of excerpt) {
|
|
@@ -32385,8 +32385,8 @@ var init_ErrorOverview = __esm({
|
|
|
32385
32385
|
init_dist3();
|
|
32386
32386
|
init_Box();
|
|
32387
32387
|
init_Text();
|
|
32388
|
-
cleanupPath = (
|
|
32389
|
-
return
|
|
32388
|
+
cleanupPath = (path8) => {
|
|
32389
|
+
return path8?.replace(`file://${cwd()}/`, "");
|
|
32390
32390
|
};
|
|
32391
32391
|
stackUtils = new import_stack_utils.default({
|
|
32392
32392
|
cwd: cwd(),
|
|
@@ -36691,16 +36691,27 @@ function packageIndexEnv(config = {}, env3 = process.env, platform2 = process.pl
|
|
|
36691
36691
|
function joinIndexUrls(urls) {
|
|
36692
36692
|
return urls.flatMap((value) => String(value || "").split(/\s+/)).map((value) => value.trim()).filter(Boolean).filter((value, index, all) => all.indexOf(value) === index).join(" ");
|
|
36693
36693
|
}
|
|
36694
|
-
function maybeAutoUpdateManagedEnv({
|
|
36694
|
+
function maybeAutoUpdateManagedEnv({
|
|
36695
|
+
env: env3 = process.env,
|
|
36696
|
+
platform: platform2 = process.platform,
|
|
36697
|
+
venvPath = managedVenvPath(env3, platform2),
|
|
36698
|
+
force = false,
|
|
36699
|
+
log = true,
|
|
36700
|
+
load = loadConfig,
|
|
36701
|
+
save = saveConfig,
|
|
36702
|
+
installPackages = installVendianPackages,
|
|
36703
|
+
refreshDocs = refreshAgentDocsWorkspaces,
|
|
36704
|
+
now = Date.now()
|
|
36705
|
+
} = {}) {
|
|
36695
36706
|
if (env3.VENDIAN_SKIP_AUTO_UPDATE === "1") {
|
|
36696
36707
|
return false;
|
|
36697
36708
|
}
|
|
36698
|
-
const config =
|
|
36709
|
+
const config = load(env3, platform2);
|
|
36699
36710
|
const lastUpdate = Date.parse(config.lastManagedUpdateAt || "");
|
|
36700
|
-
if (Number.isFinite(lastUpdate) &&
|
|
36711
|
+
if (!force && Number.isFinite(lastUpdate) && now - lastUpdate < AUTO_UPDATE_INTERVAL_MS) {
|
|
36701
36712
|
return false;
|
|
36702
36713
|
}
|
|
36703
|
-
const registry = registryConfig(config, env3);
|
|
36714
|
+
const registry = registryConfig(config, env3, platform2);
|
|
36704
36715
|
if (!registry.token) {
|
|
36705
36716
|
return false;
|
|
36706
36717
|
}
|
|
@@ -36709,32 +36720,33 @@ function maybeAutoUpdateManagedEnv({ env: env3 = process.env, platform: platform
|
|
|
36709
36720
|
return false;
|
|
36710
36721
|
}
|
|
36711
36722
|
try {
|
|
36712
|
-
|
|
36713
|
-
|
|
36714
|
-
|
|
36715
|
-
|
|
36723
|
+
if (log) {
|
|
36724
|
+
console.error("[vendian] Checking managed CLI/runtime updates...");
|
|
36725
|
+
}
|
|
36726
|
+
installPackages({ pythonPath, venvPath, config, env: env3, platform: platform2 });
|
|
36727
|
+
const next = { ...config, lastManagedUpdateAt: new Date(now).toISOString() };
|
|
36728
|
+
save(next, env3, platform2);
|
|
36729
|
+
refreshDocs({ config: next, venvPath, env: env3, platform: platform2 });
|
|
36716
36730
|
return true;
|
|
36717
36731
|
} catch (error) {
|
|
36718
36732
|
const message = error && typeof error.message === "string" ? error.message : String(error);
|
|
36719
|
-
|
|
36733
|
+
if (log) {
|
|
36734
|
+
console.error(`[vendian] Update check failed; continuing with installed CLI. ${message}`);
|
|
36735
|
+
}
|
|
36720
36736
|
return false;
|
|
36721
36737
|
}
|
|
36722
36738
|
}
|
|
36723
36739
|
|
|
36724
36740
|
// src/tui.js
|
|
36725
|
-
import
|
|
36741
|
+
import fs12 from "node:fs";
|
|
36726
36742
|
import readlinePromises from "node:readline/promises";
|
|
36727
36743
|
|
|
36728
|
-
// src/npm-update.js
|
|
36729
|
-
import { execFile } from "node:child_process";
|
|
36730
|
-
import { promisify } from "node:util";
|
|
36731
|
-
|
|
36732
36744
|
// src/version.js
|
|
36733
|
-
var CLI_VERSION = true ? "0.0.
|
|
36745
|
+
var CLI_VERSION = true ? "0.0.11" : process.env.npm_package_version || "0.0.0-dev";
|
|
36734
36746
|
|
|
36735
36747
|
// src/npm-update.js
|
|
36736
|
-
var execFileAsync = promisify(execFile);
|
|
36737
36748
|
var NPM_CHECK_INTERVAL_MS = 30 * 60 * 1e3;
|
|
36749
|
+
var CLI_PACKAGE_NAME = "@vendian/cli";
|
|
36738
36750
|
function npmPackageUpdateSummary({
|
|
36739
36751
|
config = {},
|
|
36740
36752
|
currentVersion = CLI_VERSION,
|
|
@@ -36757,21 +36769,14 @@ function npmPackageUpdateSummary({
|
|
|
36757
36769
|
async function checkNpmPackageUpdate({
|
|
36758
36770
|
env: env3 = process.env,
|
|
36759
36771
|
platform: platform2 = process.platform,
|
|
36760
|
-
packageName =
|
|
36772
|
+
packageName = CLI_PACKAGE_NAME,
|
|
36761
36773
|
registry = "https://registry.npmjs.org/",
|
|
36762
36774
|
currentVersion = CLI_VERSION,
|
|
36763
|
-
timeoutMs = 4e3
|
|
36775
|
+
timeoutMs = 4e3,
|
|
36776
|
+
fetchImpl = globalThis.fetch
|
|
36764
36777
|
} = {}) {
|
|
36765
|
-
const npm = platform2 === "win32" ? "npm.cmd" : "npm";
|
|
36766
|
-
const args = ["view", packageName, "dist-tags.latest", "--json", `--registry=${registry}`];
|
|
36767
36778
|
try {
|
|
36768
|
-
const
|
|
36769
|
-
env: env3,
|
|
36770
|
-
encoding: "utf8",
|
|
36771
|
-
timeout: timeoutMs,
|
|
36772
|
-
windowsHide: true
|
|
36773
|
-
});
|
|
36774
|
-
const latestVersion = parseNpmLatest(stdout);
|
|
36779
|
+
const latestVersion = await latestNpmPackageVersion({ packageName, registry, timeoutMs, fetchImpl });
|
|
36775
36780
|
const config = {
|
|
36776
36781
|
...loadConfig(env3, platform2),
|
|
36777
36782
|
latestNpmCliVersion: latestVersion,
|
|
@@ -36786,6 +36791,33 @@ async function checkNpmPackageUpdate({
|
|
|
36786
36791
|
};
|
|
36787
36792
|
}
|
|
36788
36793
|
}
|
|
36794
|
+
async function latestNpmPackageVersion({
|
|
36795
|
+
packageName = CLI_PACKAGE_NAME,
|
|
36796
|
+
registry = "https://registry.npmjs.org/",
|
|
36797
|
+
timeoutMs = 4e3,
|
|
36798
|
+
fetchImpl = globalThis.fetch
|
|
36799
|
+
} = {}) {
|
|
36800
|
+
if (typeof fetchImpl !== "function") {
|
|
36801
|
+
throw new Error("fetch is unavailable");
|
|
36802
|
+
}
|
|
36803
|
+
const controller = new AbortController();
|
|
36804
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
36805
|
+
try {
|
|
36806
|
+
const response = await fetchImpl(registryPackageUrl(registry, packageName), {
|
|
36807
|
+
headers: {
|
|
36808
|
+
accept: "application/vnd.npm.install-v1+json, application/json"
|
|
36809
|
+
},
|
|
36810
|
+
signal: controller.signal
|
|
36811
|
+
});
|
|
36812
|
+
if (!response?.ok) {
|
|
36813
|
+
throw new Error(`npm registry returned ${response?.status || "no response"}`);
|
|
36814
|
+
}
|
|
36815
|
+
const metadata = await response.json();
|
|
36816
|
+
return parseNpmLatest(metadata?.["dist-tags"]?.latest);
|
|
36817
|
+
} finally {
|
|
36818
|
+
clearTimeout(timeout);
|
|
36819
|
+
}
|
|
36820
|
+
}
|
|
36789
36821
|
function updateLabel({ runtime, npmUpdate }) {
|
|
36790
36822
|
if (npmUpdate?.updateAvailable) {
|
|
36791
36823
|
return `${npmUpdate.label} (current ${npmUpdate.currentVersion})`;
|
|
@@ -36813,6 +36845,19 @@ function parseNpmLatest(stdout) {
|
|
|
36813
36845
|
return raw.replace(/^"|"$/g, "").trim();
|
|
36814
36846
|
}
|
|
36815
36847
|
}
|
|
36848
|
+
function registryPackageUrl(registry, packageName) {
|
|
36849
|
+
const base = String(registry || "https://registry.npmjs.org/");
|
|
36850
|
+
const normalizedBase = base.endsWith("/") ? base : `${base}/`;
|
|
36851
|
+
return new URL(encodeRegistryPackageName(packageName), normalizedBase).toString();
|
|
36852
|
+
}
|
|
36853
|
+
function encodeRegistryPackageName(packageName) {
|
|
36854
|
+
const name = String(packageName || "").trim();
|
|
36855
|
+
if (!name.startsWith("@")) {
|
|
36856
|
+
return encodeURIComponent(name);
|
|
36857
|
+
}
|
|
36858
|
+
const [scope, pkg] = name.slice(1).split("/");
|
|
36859
|
+
return `@${encodeURIComponent(scope || "")}%2f${encodeURIComponent(pkg || "")}`;
|
|
36860
|
+
}
|
|
36816
36861
|
function compareSemver(left, right) {
|
|
36817
36862
|
const leftParts = semverParts(left);
|
|
36818
36863
|
const rightParts = semverParts(right);
|
|
@@ -37047,6 +37092,10 @@ function initialServeState() {
|
|
|
37047
37092
|
retry: null,
|
|
37048
37093
|
errors: [],
|
|
37049
37094
|
logs: [],
|
|
37095
|
+
agentLogs: {},
|
|
37096
|
+
// per-agent logs keyed by relativePath
|
|
37097
|
+
agentRunState: {},
|
|
37098
|
+
newAgents: [],
|
|
37050
37099
|
stopped: false,
|
|
37051
37100
|
jobsRun: 0
|
|
37052
37101
|
};
|
|
@@ -37062,6 +37111,19 @@ function parseServeEventLine(line) {
|
|
|
37062
37111
|
}
|
|
37063
37112
|
return parsed;
|
|
37064
37113
|
}
|
|
37114
|
+
function serveProcessExitMessage({ stderr = "", code = 0, signal = "" } = {}) {
|
|
37115
|
+
const text = String(stderr || "");
|
|
37116
|
+
if (/unrecognized arguments:\s*--event-stream/i.test(text)) {
|
|
37117
|
+
return "Managed Vendian runtime is too old for the local serve dashboard. Run `vendian update`, then start Serve Agents again.";
|
|
37118
|
+
}
|
|
37119
|
+
if (code && code !== 0) {
|
|
37120
|
+
return `Local serve exited with code ${code}. Toggle details for stderr.`;
|
|
37121
|
+
}
|
|
37122
|
+
if (signal && signal !== "SIGINT" && signal !== "SIGTERM") {
|
|
37123
|
+
return `Local serve exited from ${signal}. Toggle details for stderr.`;
|
|
37124
|
+
}
|
|
37125
|
+
return "";
|
|
37126
|
+
}
|
|
37065
37127
|
function applyServeEvent(state, event) {
|
|
37066
37128
|
if (!event || typeof event.type !== "string") {
|
|
37067
37129
|
return state;
|
|
@@ -37086,29 +37148,66 @@ function applyServeEvent(state, event) {
|
|
|
37086
37148
|
return { ...next, activity: `Preparing ${agentLabel(event)}` };
|
|
37087
37149
|
}
|
|
37088
37150
|
if (event.type === "agent_prepare_completed") {
|
|
37151
|
+
const runState = event.status === "error" ? setAgentRunState(state.agentRunState, agentLabel(event), {
|
|
37152
|
+
status: "error",
|
|
37153
|
+
lastEventAt: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
37154
|
+
errorMessage: stringValue(event.error || event.errorMessage || "Agent setup failed")
|
|
37155
|
+
}) : state.agentRunState;
|
|
37089
37156
|
return {
|
|
37090
37157
|
...next,
|
|
37091
37158
|
activity: `${agentLabel(event)} ${event.status === "error" ? "needs setup" : "ready"}`,
|
|
37159
|
+
agentRunState: runState,
|
|
37092
37160
|
errors: event.error ? appendError(state.errors, agentLabel(event), event.error) : state.errors
|
|
37093
37161
|
};
|
|
37094
37162
|
}
|
|
37095
37163
|
if (event.type === "inventory_synced") {
|
|
37164
|
+
const agents = Array.isArray(event.agents) ? event.agents : state.agents;
|
|
37165
|
+
const newAgents = state.agents.length > 0 ? findNewAgents(state.agents, agents) : [];
|
|
37096
37166
|
return {
|
|
37097
37167
|
...next,
|
|
37098
|
-
agents
|
|
37099
|
-
|
|
37168
|
+
agents,
|
|
37169
|
+
newAgents,
|
|
37170
|
+
agentRunState: reconcileInventoryRunState(state.agentRunState, agents, event.timestamp),
|
|
37171
|
+
activity: newAgents.length ? `${newAgents.length} new agent${newAgents.length === 1 ? "" : "s"} synced` : `Inventory synced (${Number(event.agentCount ?? agents.length ?? 0)} agent(s))`
|
|
37100
37172
|
};
|
|
37101
37173
|
}
|
|
37102
37174
|
if (event.type === "job_started") {
|
|
37175
|
+
const relativePath = agentLabel(event);
|
|
37176
|
+
const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
37103
37177
|
return {
|
|
37104
37178
|
...next,
|
|
37179
|
+
agentLogs: appendAgentLog(state.agentLogs, event),
|
|
37180
|
+
agentRunState: setAgentRunState(state.agentRunState, relativePath, {
|
|
37181
|
+
status: "running",
|
|
37182
|
+
runId: stringValue(event.runId || event.deployRequestId),
|
|
37183
|
+
jobType: stringValue(event.jobType || "run"),
|
|
37184
|
+
startedAt: timestamp,
|
|
37185
|
+
completedAt: null,
|
|
37186
|
+
lastEventAt: timestamp,
|
|
37187
|
+
errorMessage: null
|
|
37188
|
+
}),
|
|
37105
37189
|
currentJob: event,
|
|
37106
37190
|
activity: `Running ${jobLabel(event)}`
|
|
37107
37191
|
};
|
|
37108
37192
|
}
|
|
37109
37193
|
if (event.type === "job_completed") {
|
|
37194
|
+
const relativePath = agentLabel(event);
|
|
37195
|
+
const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
37196
|
+
const success = event.success !== false;
|
|
37197
|
+
const runId = stringValue(event.runId || event.deployRequestId);
|
|
37198
|
+
const previous = (state.agentRunState || {})[relativePath];
|
|
37199
|
+
const effectiveSuccess = success && !(previous?.status === "error" && previous?.runId === runId);
|
|
37110
37200
|
return {
|
|
37111
37201
|
...next,
|
|
37202
|
+
agentLogs: appendAgentLog(state.agentLogs, event),
|
|
37203
|
+
agentRunState: setAgentRunState(state.agentRunState, relativePath, {
|
|
37204
|
+
status: effectiveSuccess ? "completed" : "error",
|
|
37205
|
+
runId,
|
|
37206
|
+
jobType: stringValue(event.jobType || "run"),
|
|
37207
|
+
completedAt: timestamp,
|
|
37208
|
+
lastEventAt: timestamp,
|
|
37209
|
+
errorMessage: effectiveSuccess ? null : previous?.errorMessage || stringValue(event.error || "Job failed")
|
|
37210
|
+
}),
|
|
37112
37211
|
jobsRun: state.jobsRun + 1,
|
|
37113
37212
|
currentJob: null,
|
|
37114
37213
|
activity: `${jobLabel(event)} completed`
|
|
@@ -37124,8 +37223,20 @@ function applyServeEvent(state, event) {
|
|
|
37124
37223
|
return { ...next, retry: event, activity: `Retrying ${stringValue(event.activity)} in ${formatSeconds(event.delaySeconds)}` };
|
|
37125
37224
|
}
|
|
37126
37225
|
if (event.type === "error") {
|
|
37226
|
+
const relativePath = event.relativePath || event.path ? agentLabel(event) : "";
|
|
37227
|
+
const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
37228
|
+
const hasAgentScope = Boolean(relativePath);
|
|
37127
37229
|
return {
|
|
37128
37230
|
...next,
|
|
37231
|
+
agentLogs: hasAgentScope ? appendAgentLog(state.agentLogs, event) : state.agentLogs,
|
|
37232
|
+
agentRunState: hasAgentScope ? setAgentRunState(state.agentRunState, relativePath, {
|
|
37233
|
+
status: "error",
|
|
37234
|
+
runId: stringValue(event.runId || event.deployRequestId),
|
|
37235
|
+
jobType: stringValue(event.jobType || "run"),
|
|
37236
|
+
completedAt: timestamp,
|
|
37237
|
+
lastEventAt: timestamp,
|
|
37238
|
+
errorMessage: stringValue(event.error || event.code || "Unknown error")
|
|
37239
|
+
}) : state.agentRunState,
|
|
37129
37240
|
activity: "Error",
|
|
37130
37241
|
errors: appendError(state.errors, jobLabel(event), event.error || event.code || "Unknown error")
|
|
37131
37242
|
};
|
|
@@ -37140,6 +37251,24 @@ function applyServeEvent(state, event) {
|
|
|
37140
37251
|
jobsRun: Number(event.jobsRun ?? state.jobsRun)
|
|
37141
37252
|
};
|
|
37142
37253
|
}
|
|
37254
|
+
if (event.type === "run_log") {
|
|
37255
|
+
const entry = serveEventAgentLogEntry(event);
|
|
37256
|
+
const nextRunState = entry && entry.entry.eventType === "completion" ? setAgentRunState(state.agentRunState, entry.relativePath, {
|
|
37257
|
+
status: entry.entry.success === false ? "error" : "completed",
|
|
37258
|
+
runId: entry.entry.runId,
|
|
37259
|
+
completedAt: entry.entry.timestamp,
|
|
37260
|
+
lastEventAt: entry.entry.timestamp,
|
|
37261
|
+
errorMessage: entry.entry.success === false ? formatErrorMessage(entry.entry.error) : null
|
|
37262
|
+
}) : entry ? setAgentRunState(state.agentRunState, entry.relativePath, {
|
|
37263
|
+
runId: entry.entry.runId,
|
|
37264
|
+
lastEventAt: entry.entry.timestamp
|
|
37265
|
+
}) : state.agentRunState;
|
|
37266
|
+
return {
|
|
37267
|
+
...next,
|
|
37268
|
+
agentLogs: appendAgentLog(state.agentLogs, event),
|
|
37269
|
+
agentRunState: nextRunState
|
|
37270
|
+
};
|
|
37271
|
+
}
|
|
37143
37272
|
return next;
|
|
37144
37273
|
}
|
|
37145
37274
|
function agentSummary(agents = []) {
|
|
@@ -37161,9 +37290,254 @@ function agentSummary(agents = []) {
|
|
|
37161
37290
|
function appendLog(logs, event) {
|
|
37162
37291
|
return [...logs, event].slice(-200);
|
|
37163
37292
|
}
|
|
37293
|
+
function appendAgentLog(agentLogs, event) {
|
|
37294
|
+
const normalized = serveEventAgentLogEntry(event);
|
|
37295
|
+
if (!normalized) {
|
|
37296
|
+
return agentLogs || {};
|
|
37297
|
+
}
|
|
37298
|
+
const key = normalized.relativePath;
|
|
37299
|
+
const existing = agentLogs[key] || [];
|
|
37300
|
+
return {
|
|
37301
|
+
...agentLogs,
|
|
37302
|
+
[key]: [...existing, normalized.entry].slice(-5e3)
|
|
37303
|
+
};
|
|
37304
|
+
}
|
|
37305
|
+
function agentLogEntries(agentLogs, relativePath) {
|
|
37306
|
+
return (agentLogs || {})[relativePath] || [];
|
|
37307
|
+
}
|
|
37308
|
+
function mergeAgentLogRecords(agentLogs, records = []) {
|
|
37309
|
+
let next = agentLogs || {};
|
|
37310
|
+
for (const record of records) {
|
|
37311
|
+
if (!record || typeof record !== "object") continue;
|
|
37312
|
+
const relativePath = stringValue(record.relativePath || ".");
|
|
37313
|
+
const entry = record.entry && typeof record.entry === "object" ? record.entry : record;
|
|
37314
|
+
const existing = next[relativePath] || [];
|
|
37315
|
+
next = {
|
|
37316
|
+
...next,
|
|
37317
|
+
[relativePath]: [...existing, normalizeStoredAgentLogEntry(entry)].slice(-5e3)
|
|
37318
|
+
};
|
|
37319
|
+
}
|
|
37320
|
+
return next;
|
|
37321
|
+
}
|
|
37322
|
+
function agentRunStateFromLogs(agentLogs, { includeRunning = true } = {}) {
|
|
37323
|
+
let next = {};
|
|
37324
|
+
for (const [relativePath, entries] of Object.entries(agentLogs || {})) {
|
|
37325
|
+
for (const entry of entries || []) {
|
|
37326
|
+
const timestamp = entry.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
37327
|
+
const runId = stringValue(entry.runId);
|
|
37328
|
+
const current = next[relativePath] || {};
|
|
37329
|
+
if (entry.eventType === "job_started") {
|
|
37330
|
+
next = setAgentRunState(next, relativePath, {
|
|
37331
|
+
status: includeRunning ? "running" : current.status,
|
|
37332
|
+
runId,
|
|
37333
|
+
jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
|
|
37334
|
+
startedAt: timestamp,
|
|
37335
|
+
lastEventAt: timestamp
|
|
37336
|
+
});
|
|
37337
|
+
continue;
|
|
37338
|
+
}
|
|
37339
|
+
if (entry.eventType === "completion" || entry.eventType === "job_completed") {
|
|
37340
|
+
const failed = entry.success === false || current.status === "error" && current.runId === runId;
|
|
37341
|
+
next = setAgentRunState(next, relativePath, {
|
|
37342
|
+
status: failed ? "error" : "completed",
|
|
37343
|
+
runId,
|
|
37344
|
+
jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
|
|
37345
|
+
completedAt: timestamp,
|
|
37346
|
+
lastEventAt: timestamp,
|
|
37347
|
+
errorMessage: failed ? formatErrorMessage(entry.error) || current.errorMessage || stringValue(entry.message || "Job failed") : null
|
|
37348
|
+
});
|
|
37349
|
+
continue;
|
|
37350
|
+
}
|
|
37351
|
+
if (entry.eventType === "error" || entry.level === "error" && entry.success === false) {
|
|
37352
|
+
next = setAgentRunState(next, relativePath, {
|
|
37353
|
+
status: "error",
|
|
37354
|
+
runId,
|
|
37355
|
+
jobType: entry.jobType ? stringValue(entry.jobType) : current.jobType,
|
|
37356
|
+
completedAt: timestamp,
|
|
37357
|
+
lastEventAt: timestamp,
|
|
37358
|
+
errorMessage: formatErrorMessage(entry.error) || stringValue(entry.message || "Job failed")
|
|
37359
|
+
});
|
|
37360
|
+
continue;
|
|
37361
|
+
}
|
|
37362
|
+
if (runId || timestamp) {
|
|
37363
|
+
next = setAgentRunState(next, relativePath, {
|
|
37364
|
+
runId: runId || current.runId,
|
|
37365
|
+
lastEventAt: timestamp
|
|
37366
|
+
});
|
|
37367
|
+
}
|
|
37368
|
+
}
|
|
37369
|
+
}
|
|
37370
|
+
return next;
|
|
37371
|
+
}
|
|
37372
|
+
function serveEventAgentLogEntry(event) {
|
|
37373
|
+
if (!event || typeof event !== "object") {
|
|
37374
|
+
return null;
|
|
37375
|
+
}
|
|
37376
|
+
const type = stringValue(event.type);
|
|
37377
|
+
const relativePath = stringValue(event.relativePath || event.path || ".");
|
|
37378
|
+
const timestamp = event.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
37379
|
+
if (type === "run_log") {
|
|
37380
|
+
return {
|
|
37381
|
+
relativePath,
|
|
37382
|
+
entry: {
|
|
37383
|
+
timestamp,
|
|
37384
|
+
runId: stringValue(event.runId),
|
|
37385
|
+
eventType: stringValue(event.eventType || "log"),
|
|
37386
|
+
level: stringValue(event.level || "info"),
|
|
37387
|
+
message: stringValue(event.message),
|
|
37388
|
+
stepId: event.stepId ? stringValue(event.stepId) : null,
|
|
37389
|
+
current: event.current ?? null,
|
|
37390
|
+
total: event.total ?? null,
|
|
37391
|
+
success: event.success ?? null,
|
|
37392
|
+
error: event.error ?? null,
|
|
37393
|
+
jobType: event.jobType ? stringValue(event.jobType) : null
|
|
37394
|
+
}
|
|
37395
|
+
};
|
|
37396
|
+
}
|
|
37397
|
+
if (type === "job_started") {
|
|
37398
|
+
const jobType = stringValue(event.jobType || "run");
|
|
37399
|
+
return {
|
|
37400
|
+
relativePath,
|
|
37401
|
+
entry: {
|
|
37402
|
+
timestamp,
|
|
37403
|
+
runId: stringValue(event.runId || event.deployRequestId),
|
|
37404
|
+
eventType: "job_started",
|
|
37405
|
+
level: "info",
|
|
37406
|
+
message: `Started ${jobType}`,
|
|
37407
|
+
stepId: null,
|
|
37408
|
+
current: null,
|
|
37409
|
+
total: null,
|
|
37410
|
+
success: null,
|
|
37411
|
+
error: null,
|
|
37412
|
+
jobType
|
|
37413
|
+
}
|
|
37414
|
+
};
|
|
37415
|
+
}
|
|
37416
|
+
if (type === "job_completed") {
|
|
37417
|
+
const success = event.success !== false;
|
|
37418
|
+
const jobType = stringValue(event.jobType || "run");
|
|
37419
|
+
return {
|
|
37420
|
+
relativePath,
|
|
37421
|
+
entry: {
|
|
37422
|
+
timestamp,
|
|
37423
|
+
runId: stringValue(event.runId || event.deployRequestId),
|
|
37424
|
+
eventType: "job_completed",
|
|
37425
|
+
level: success ? "info" : "error",
|
|
37426
|
+
message: success ? "Completed successfully" : stringValue(event.error || "Failed"),
|
|
37427
|
+
stepId: null,
|
|
37428
|
+
current: null,
|
|
37429
|
+
total: null,
|
|
37430
|
+
success,
|
|
37431
|
+
error: event.error ?? null,
|
|
37432
|
+
jobType
|
|
37433
|
+
}
|
|
37434
|
+
};
|
|
37435
|
+
}
|
|
37436
|
+
if (type === "error" && (event.relativePath || event.path)) {
|
|
37437
|
+
return {
|
|
37438
|
+
relativePath,
|
|
37439
|
+
entry: {
|
|
37440
|
+
timestamp,
|
|
37441
|
+
runId: stringValue(event.runId || event.deployRequestId),
|
|
37442
|
+
eventType: "error",
|
|
37443
|
+
level: "error",
|
|
37444
|
+
message: stringValue(event.error || event.code || "Unknown error"),
|
|
37445
|
+
stepId: null,
|
|
37446
|
+
current: null,
|
|
37447
|
+
total: null,
|
|
37448
|
+
success: false,
|
|
37449
|
+
error: event.error ?? event.code ?? null,
|
|
37450
|
+
jobType: event.jobType ? stringValue(event.jobType) : null
|
|
37451
|
+
}
|
|
37452
|
+
};
|
|
37453
|
+
}
|
|
37454
|
+
return null;
|
|
37455
|
+
}
|
|
37456
|
+
function agentRuntimeStatus(agent, agentRunState = {}) {
|
|
37457
|
+
const path8 = stringValue(agent?.relativePath || ".");
|
|
37458
|
+
const run2 = (agentRunState || {})[path8];
|
|
37459
|
+
const inventoryStatus = stringValue(agent?.status);
|
|
37460
|
+
if (run2?.status === "running") {
|
|
37461
|
+
return { status: "running", label: "running", run: run2 };
|
|
37462
|
+
}
|
|
37463
|
+
if (run2?.status === "error" || inventoryStatus === "error") {
|
|
37464
|
+
return { status: "error", label: "error", run: run2 };
|
|
37465
|
+
}
|
|
37466
|
+
if (inventoryStatus === "online") {
|
|
37467
|
+
return { status: run2?.status === "completed" ? "completed" : "ready", label: "ready", run: run2 };
|
|
37468
|
+
}
|
|
37469
|
+
if (run2?.status === "completed") {
|
|
37470
|
+
return { status: "completed", label: "ready", run: run2 };
|
|
37471
|
+
}
|
|
37472
|
+
return { status: inventoryStatus || "unknown", label: inventoryStatus || "unknown", run: run2 };
|
|
37473
|
+
}
|
|
37164
37474
|
function appendError(errors, scope, message) {
|
|
37165
37475
|
return [...errors, { scope, message: stringValue(message) }].slice(-20);
|
|
37166
37476
|
}
|
|
37477
|
+
function setAgentRunState(agentRunState, relativePath, patch) {
|
|
37478
|
+
const key = stringValue(relativePath || ".");
|
|
37479
|
+
return {
|
|
37480
|
+
...agentRunState || {},
|
|
37481
|
+
[key]: {
|
|
37482
|
+
...(agentRunState || {})[key] || {},
|
|
37483
|
+
...patch
|
|
37484
|
+
}
|
|
37485
|
+
};
|
|
37486
|
+
}
|
|
37487
|
+
function reconcileInventoryRunState(agentRunState, agents, timestamp) {
|
|
37488
|
+
let next = agentRunState || {};
|
|
37489
|
+
for (const agent of agents || []) {
|
|
37490
|
+
const path8 = stringValue(agent?.relativePath || ".");
|
|
37491
|
+
const current = next[path8];
|
|
37492
|
+
if (agent?.status === "error") {
|
|
37493
|
+
next = setAgentRunState(next, path8, {
|
|
37494
|
+
status: "error",
|
|
37495
|
+
lastEventAt: timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
37496
|
+
errorMessage: stringValue(agent.errorMessage || agent.error || "Agent setup failed")
|
|
37497
|
+
});
|
|
37498
|
+
} else if (agent?.status === "online" && current?.status === "error" && !current?.runId) {
|
|
37499
|
+
next = setAgentRunState(next, path8, {
|
|
37500
|
+
status: "ready",
|
|
37501
|
+
lastEventAt: timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
37502
|
+
errorMessage: null
|
|
37503
|
+
});
|
|
37504
|
+
}
|
|
37505
|
+
}
|
|
37506
|
+
return next;
|
|
37507
|
+
}
|
|
37508
|
+
function normalizeStoredAgentLogEntry(entry) {
|
|
37509
|
+
return {
|
|
37510
|
+
timestamp: entry.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
37511
|
+
runId: stringValue(entry.runId),
|
|
37512
|
+
eventType: stringValue(entry.eventType || "log"),
|
|
37513
|
+
level: stringValue(entry.level || "info"),
|
|
37514
|
+
message: stringValue(entry.message),
|
|
37515
|
+
stepId: entry.stepId ? stringValue(entry.stepId) : null,
|
|
37516
|
+
current: entry.current ?? null,
|
|
37517
|
+
total: entry.total ?? null,
|
|
37518
|
+
success: entry.success ?? null,
|
|
37519
|
+
error: entry.error ?? null,
|
|
37520
|
+
jobType: entry.jobType ? stringValue(entry.jobType) : null
|
|
37521
|
+
};
|
|
37522
|
+
}
|
|
37523
|
+
function formatErrorMessage(error) {
|
|
37524
|
+
if (!error) return null;
|
|
37525
|
+
if (typeof error === "object") return stringValue(error.message || "error");
|
|
37526
|
+
return stringValue(error);
|
|
37527
|
+
}
|
|
37528
|
+
function findNewAgents(previous, next) {
|
|
37529
|
+
const seen = new Set(previous.map(agentKey).filter(Boolean));
|
|
37530
|
+
return next.filter((agent) => {
|
|
37531
|
+
const key = agentKey(agent);
|
|
37532
|
+
return key && !seen.has(key);
|
|
37533
|
+
}).slice(0, 8);
|
|
37534
|
+
}
|
|
37535
|
+
function agentKey(agent) {
|
|
37536
|
+
if (!agent || typeof agent !== "object") {
|
|
37537
|
+
return "";
|
|
37538
|
+
}
|
|
37539
|
+
return stringValue(agent.localAgentId || agent.relativePath || agent.path || agent.manifestName || agent.id);
|
|
37540
|
+
}
|
|
37167
37541
|
function agentLabel(event) {
|
|
37168
37542
|
return stringValue(event.relativePath || event.path || ".");
|
|
37169
37543
|
}
|
|
@@ -37182,27 +37556,260 @@ function formatSeconds(value) {
|
|
|
37182
37556
|
import { spawn as spawn2 } from "node:child_process";
|
|
37183
37557
|
async function spawnLocalServeEventStream({
|
|
37184
37558
|
agentsDir = "./agents",
|
|
37559
|
+
collectionId = "",
|
|
37185
37560
|
env: env3 = process.env,
|
|
37186
37561
|
platform: platform2 = process.platform
|
|
37187
37562
|
} = {}) {
|
|
37188
|
-
const invocation = await preparePythonVendianInvocation(
|
|
37563
|
+
const invocation = await preparePythonVendianInvocation(buildLocalServeEventStreamArgs({ agentsDir, collectionId }), { env: env3, platform: platform2 });
|
|
37564
|
+
return spawn2(invocation.command, invocation.args, {
|
|
37565
|
+
env: invocation.env,
|
|
37566
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
37567
|
+
shell: false
|
|
37568
|
+
});
|
|
37569
|
+
}
|
|
37570
|
+
function buildLocalServeEventStreamArgs({ agentsDir = "./agents", collectionId = "" } = {}) {
|
|
37571
|
+
const args = [
|
|
37189
37572
|
"cloud",
|
|
37190
37573
|
"local",
|
|
37191
37574
|
"serve",
|
|
37192
37575
|
"--agents-dir",
|
|
37193
37576
|
agentsDir || "./agents",
|
|
37194
37577
|
"--event-stream"
|
|
37195
|
-
]
|
|
37196
|
-
|
|
37197
|
-
|
|
37198
|
-
|
|
37199
|
-
|
|
37200
|
-
});
|
|
37578
|
+
];
|
|
37579
|
+
if (collectionId) {
|
|
37580
|
+
args.push("--collection-id", collectionId);
|
|
37581
|
+
}
|
|
37582
|
+
return args;
|
|
37201
37583
|
}
|
|
37202
37584
|
|
|
37585
|
+
// src/serve-log-store.js
|
|
37586
|
+
import crypto2 from "node:crypto";
|
|
37587
|
+
import fs10 from "node:fs";
|
|
37588
|
+
import path7 from "node:path";
|
|
37589
|
+
var MAX_EVENTS = 5e3;
|
|
37590
|
+
var MAX_RUNS = 50;
|
|
37591
|
+
function createServeLogStore({
|
|
37592
|
+
agentsDir = "./agents",
|
|
37593
|
+
collectionId = "",
|
|
37594
|
+
env: env3 = process.env,
|
|
37595
|
+
platform: platform2 = process.platform
|
|
37596
|
+
} = {}) {
|
|
37597
|
+
const file = serveLogFilePath({ agentsDir, collectionId, env: env3, platform: platform2 });
|
|
37598
|
+
let appendCount = 0;
|
|
37599
|
+
return {
|
|
37600
|
+
file,
|
|
37601
|
+
load() {
|
|
37602
|
+
return readServeLogRecords(file);
|
|
37603
|
+
},
|
|
37604
|
+
append(event) {
|
|
37605
|
+
const normalized = serveEventAgentLogEntry(event);
|
|
37606
|
+
if (!normalized) {
|
|
37607
|
+
return false;
|
|
37608
|
+
}
|
|
37609
|
+
fs10.mkdirSync(path7.dirname(file), { recursive: true });
|
|
37610
|
+
const record = {
|
|
37611
|
+
version: 1,
|
|
37612
|
+
collectionId: collectionId || "",
|
|
37613
|
+
agentsDir: String(agentsDir || "./agents"),
|
|
37614
|
+
relativePath: normalized.relativePath,
|
|
37615
|
+
entry: normalized.entry
|
|
37616
|
+
};
|
|
37617
|
+
fs10.appendFileSync(file, `${JSON.stringify(record)}
|
|
37618
|
+
`, "utf8");
|
|
37619
|
+
appendCount += 1;
|
|
37620
|
+
if (appendCount % 50 === 0) {
|
|
37621
|
+
compactServeLogFile(file);
|
|
37622
|
+
}
|
|
37623
|
+
return true;
|
|
37624
|
+
},
|
|
37625
|
+
compact() {
|
|
37626
|
+
compactServeLogFile(file);
|
|
37627
|
+
}
|
|
37628
|
+
};
|
|
37629
|
+
}
|
|
37630
|
+
function serveLogFilePath({
|
|
37631
|
+
agentsDir = "./agents",
|
|
37632
|
+
collectionId = "",
|
|
37633
|
+
env: env3 = process.env,
|
|
37634
|
+
platform: platform2 = process.platform
|
|
37635
|
+
} = {}) {
|
|
37636
|
+
const root = vendianHome(env3, platform2);
|
|
37637
|
+
const resolvedAgentsDir = path7.resolve(String(agentsDir || "./agents"));
|
|
37638
|
+
const hash = crypto2.createHash("sha256").update(`${collectionId || "default"}\0${resolvedAgentsDir}`).digest("hex").slice(0, 16);
|
|
37639
|
+
return path7.join(root, "serve-logs", `${safePathPart(collectionId || "default")}-${hash}.jsonl`);
|
|
37640
|
+
}
|
|
37641
|
+
function readServeLogRecords(file) {
|
|
37642
|
+
if (!file || !fs10.existsSync(file)) {
|
|
37643
|
+
return [];
|
|
37644
|
+
}
|
|
37645
|
+
const records = [];
|
|
37646
|
+
const lines = fs10.readFileSync(file, "utf8").split(/\r?\n/);
|
|
37647
|
+
for (const line of lines) {
|
|
37648
|
+
const value = line.trim();
|
|
37649
|
+
if (!value) continue;
|
|
37650
|
+
try {
|
|
37651
|
+
const record = JSON.parse(value);
|
|
37652
|
+
if (record && typeof record === "object" && record.entry && record.relativePath) {
|
|
37653
|
+
records.push({ relativePath: String(record.relativePath), entry: record.entry });
|
|
37654
|
+
}
|
|
37655
|
+
} catch {
|
|
37656
|
+
}
|
|
37657
|
+
}
|
|
37658
|
+
return trimServeLogRecords(records);
|
|
37659
|
+
}
|
|
37660
|
+
function compactServeLogFile(file) {
|
|
37661
|
+
if (!file || !fs10.existsSync(file)) {
|
|
37662
|
+
return;
|
|
37663
|
+
}
|
|
37664
|
+
const records = readServeLogRecords(file);
|
|
37665
|
+
const tmp = `${file}.tmp`;
|
|
37666
|
+
fs10.writeFileSync(
|
|
37667
|
+
tmp,
|
|
37668
|
+
records.map((record) => JSON.stringify({ version: 1, ...record })).join("\n") + (records.length ? "\n" : ""),
|
|
37669
|
+
"utf8"
|
|
37670
|
+
);
|
|
37671
|
+
fs10.renameSync(tmp, file);
|
|
37672
|
+
}
|
|
37673
|
+
function trimServeLogRecords(records) {
|
|
37674
|
+
const runIds = [];
|
|
37675
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37676
|
+
for (const record of records) {
|
|
37677
|
+
const runId = String(record.entry?.runId || "");
|
|
37678
|
+
if (runId && !seen.has(runId)) {
|
|
37679
|
+
seen.add(runId);
|
|
37680
|
+
runIds.push(runId);
|
|
37681
|
+
}
|
|
37682
|
+
}
|
|
37683
|
+
const keepRuns = new Set(runIds.slice(-MAX_RUNS));
|
|
37684
|
+
return records.filter((record) => {
|
|
37685
|
+
const runId = String(record.entry?.runId || "");
|
|
37686
|
+
return !runId || keepRuns.has(runId);
|
|
37687
|
+
}).slice(-MAX_EVENTS);
|
|
37688
|
+
}
|
|
37689
|
+
function safePathPart(value) {
|
|
37690
|
+
return String(value || "default").replace(/[^a-zA-Z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "default";
|
|
37691
|
+
}
|
|
37692
|
+
|
|
37693
|
+
// src/workspaces.js
|
|
37694
|
+
async function listCloudWorkspaces({
|
|
37695
|
+
env: env3 = process.env,
|
|
37696
|
+
platform: platform2 = process.platform,
|
|
37697
|
+
prepareInvocation = preparePythonVendianInvocation,
|
|
37698
|
+
run: run2 = runCapture
|
|
37699
|
+
} = {}) {
|
|
37700
|
+
const invocation = await prepareInvocation(["cloud", "collections", "list", "--json"], { env: env3, platform: platform2 });
|
|
37701
|
+
const result = run2(invocation.command, invocation.args, { env: invocation.env });
|
|
37702
|
+
if (!result.ok) {
|
|
37703
|
+
return {
|
|
37704
|
+
ok: false,
|
|
37705
|
+
workspaces: [],
|
|
37706
|
+
error: (result.stderr || result.stdout || `workspace list exited with code ${result.status}`).trim()
|
|
37707
|
+
};
|
|
37708
|
+
}
|
|
37709
|
+
try {
|
|
37710
|
+
return { ok: true, workspaces: normalizeWorkspaceList(JSON.parse(result.stdout)), error: "" };
|
|
37711
|
+
} catch (error) {
|
|
37712
|
+
const message = error && typeof error.message === "string" ? error.message : String(error);
|
|
37713
|
+
return { ok: false, workspaces: [], error: `Could not parse workspace list: ${message}` };
|
|
37714
|
+
}
|
|
37715
|
+
}
|
|
37716
|
+
function normalizeWorkspaceList(payload) {
|
|
37717
|
+
const data = payload && typeof payload === "object" && "data" in payload ? payload.data : payload;
|
|
37718
|
+
const raw = Array.isArray(data) ? data : data && typeof data === "object" && Array.isArray(data.data) ? data.data : data && typeof data === "object" && Array.isArray(data.collections) ? data.collections : [];
|
|
37719
|
+
return raw.filter((item) => item && typeof item === "object").map((item) => ({
|
|
37720
|
+
id: stringValue2(item.id),
|
|
37721
|
+
name: stringValue2(item.name || item.slug || item.id || "Unnamed workspace"),
|
|
37722
|
+
slug: stringValue2(item.slug)
|
|
37723
|
+
})).filter((item) => item.id);
|
|
37724
|
+
}
|
|
37725
|
+
function workspaceLabel(workspace) {
|
|
37726
|
+
const name = workspace?.name || workspace?.slug || workspace?.id || "Unnamed workspace";
|
|
37727
|
+
const slug = workspace?.slug && workspace.slug !== name ? ` (${workspace.slug})` : "";
|
|
37728
|
+
return `${name}${slug}`;
|
|
37729
|
+
}
|
|
37730
|
+
function stringValue2(value) {
|
|
37731
|
+
return value == null ? "" : String(value).trim();
|
|
37732
|
+
}
|
|
37733
|
+
|
|
37734
|
+
// src/ui/theme.js
|
|
37735
|
+
var colors = {
|
|
37736
|
+
brand: "cyan",
|
|
37737
|
+
brandBold: "cyanBright",
|
|
37738
|
+
success: "green",
|
|
37739
|
+
error: "red",
|
|
37740
|
+
warning: "yellow",
|
|
37741
|
+
muted: "gray",
|
|
37742
|
+
accent: "blueBright",
|
|
37743
|
+
text: "white",
|
|
37744
|
+
dim: "gray"
|
|
37745
|
+
};
|
|
37746
|
+
var spacing = {
|
|
37747
|
+
labelWidth: 14,
|
|
37748
|
+
indent: 2
|
|
37749
|
+
};
|
|
37750
|
+
|
|
37751
|
+
// src/ui/figures.js
|
|
37752
|
+
var supportsUnicode = process.platform !== "win32" || Boolean(
|
|
37753
|
+
process.env.WT_SESSION || // Windows Terminal
|
|
37754
|
+
process.env.TERM_PROGRAM === "vscode" || // VS Code terminal
|
|
37755
|
+
process.env.TERM === "xterm-256color" || process.env.ConEmuTask || process.env.TERMINAL_EMULATOR
|
|
37756
|
+
);
|
|
37757
|
+
var unicode = {
|
|
37758
|
+
dot: "\u25CF",
|
|
37759
|
+
dotEmpty: "\u25CB",
|
|
37760
|
+
check: "\u2714",
|
|
37761
|
+
cross: "\u2716",
|
|
37762
|
+
warning: "\u26A0",
|
|
37763
|
+
arrow: "\u25B6",
|
|
37764
|
+
arrowRight: "\u203A",
|
|
37765
|
+
arrowUp: "\u25B2",
|
|
37766
|
+
dash: "\u2500",
|
|
37767
|
+
ellipsis: "\u2026",
|
|
37768
|
+
topLeft: "\u256D",
|
|
37769
|
+
topRight: "\u256E",
|
|
37770
|
+
bottomLeft: "\u2570",
|
|
37771
|
+
bottomRight: "\u256F",
|
|
37772
|
+
horizontal: "\u2500",
|
|
37773
|
+
vertical: "\u2502",
|
|
37774
|
+
teeRight: "\u251C",
|
|
37775
|
+
teeLeft: "\u2524",
|
|
37776
|
+
teeDown: "\u252C",
|
|
37777
|
+
teeUp: "\u2534",
|
|
37778
|
+
cross_join: "\u253C",
|
|
37779
|
+
bar: "\u2588",
|
|
37780
|
+
barEmpty: "\u2591"
|
|
37781
|
+
};
|
|
37782
|
+
var ascii = {
|
|
37783
|
+
dot: "*",
|
|
37784
|
+
dotEmpty: "o",
|
|
37785
|
+
check: "+",
|
|
37786
|
+
cross: "x",
|
|
37787
|
+
warning: "!",
|
|
37788
|
+
arrow: ">",
|
|
37789
|
+
arrowRight: ">",
|
|
37790
|
+
arrowUp: "^",
|
|
37791
|
+
dash: "-",
|
|
37792
|
+
ellipsis: "...",
|
|
37793
|
+
topLeft: "+",
|
|
37794
|
+
topRight: "+",
|
|
37795
|
+
bottomLeft: "+",
|
|
37796
|
+
bottomRight: "+",
|
|
37797
|
+
horizontal: "-",
|
|
37798
|
+
vertical: "|",
|
|
37799
|
+
teeRight: "+",
|
|
37800
|
+
teeLeft: "+",
|
|
37801
|
+
teeDown: "+",
|
|
37802
|
+
teeUp: "+",
|
|
37803
|
+
cross_join: "+",
|
|
37804
|
+
bar: "#",
|
|
37805
|
+
barEmpty: "."
|
|
37806
|
+
};
|
|
37807
|
+
var fig = supportsUnicode ? unicode : ascii;
|
|
37808
|
+
|
|
37203
37809
|
// src/tui.js
|
|
37204
37810
|
var h;
|
|
37205
37811
|
var useEffect6;
|
|
37812
|
+
var useRef2;
|
|
37206
37813
|
var useState5;
|
|
37207
37814
|
var Box2;
|
|
37208
37815
|
var Text2;
|
|
@@ -37219,15 +37826,25 @@ var ENDPOINTS = [
|
|
|
37219
37826
|
{ key: "prod", label: "Production" }
|
|
37220
37827
|
];
|
|
37221
37828
|
var ACTIONS = [
|
|
37222
|
-
{ value: "connect", label: "Connect Endpoint" },
|
|
37223
|
-
{ value: "init", label: "Initialize Docs" },
|
|
37224
|
-
{ value: "create", label: "Create Agent" },
|
|
37225
|
-
{ value: "serve", label: "Serve Agents" },
|
|
37226
|
-
{ value: "doctor", label: "Doctor" },
|
|
37227
|
-
{ value: "update", label: "Update" },
|
|
37228
|
-
{ value: "commands", label: "Commands" },
|
|
37229
|
-
{ value: "exit", label: "Exit" }
|
|
37829
|
+
{ value: "connect", label: "Connect Endpoint", desc: "Switch between environments" },
|
|
37830
|
+
{ value: "init", label: "Initialize Docs", desc: "Set up SDK documentation workspace" },
|
|
37831
|
+
{ value: "create", label: "Create Agent", desc: "Scaffold a new agent from templates" },
|
|
37832
|
+
{ value: "serve", label: "Serve Agents", desc: "Start local development server" },
|
|
37833
|
+
{ value: "doctor", label: "Doctor", desc: "Check system health" },
|
|
37834
|
+
{ value: "update", label: "Update", desc: "Update runtime & packages" },
|
|
37835
|
+
{ value: "commands", label: "Commands", desc: "Show CLI command reference" },
|
|
37836
|
+
{ value: "exit", label: "Exit", desc: "Close interactive shell" }
|
|
37230
37837
|
];
|
|
37838
|
+
var SCREEN_TITLES = {
|
|
37839
|
+
home: "Home",
|
|
37840
|
+
connect: "Connect Endpoint",
|
|
37841
|
+
init: "Initialize Docs",
|
|
37842
|
+
create: "Create Agent",
|
|
37843
|
+
serve: "Serve Agents",
|
|
37844
|
+
doctor: "Doctor",
|
|
37845
|
+
update: "Update",
|
|
37846
|
+
commands: "Commands"
|
|
37847
|
+
};
|
|
37231
37848
|
var COMMANDS = [
|
|
37232
37849
|
"vendian login",
|
|
37233
37850
|
"vendian init --output-dir ./agents",
|
|
@@ -37247,6 +37864,7 @@ async function runTui({ env: env3 = process.env, platform: platform2 = process.p
|
|
|
37247
37864
|
`);
|
|
37248
37865
|
return;
|
|
37249
37866
|
}
|
|
37867
|
+
await refreshInteractiveManagedRuntime({ env: env3, platform: platform2, output });
|
|
37250
37868
|
await loadInkRuntime();
|
|
37251
37869
|
const app = renderInk(h(VendianShell, { env: env3, platform: platform2, input, output }), {
|
|
37252
37870
|
stdin: input,
|
|
@@ -37255,6 +37873,25 @@ async function runTui({ env: env3 = process.env, platform: platform2 = process.p
|
|
|
37255
37873
|
});
|
|
37256
37874
|
await app.waitUntilExit();
|
|
37257
37875
|
}
|
|
37876
|
+
async function refreshInteractiveManagedRuntime({
|
|
37877
|
+
env: env3 = process.env,
|
|
37878
|
+
platform: platform2 = process.platform,
|
|
37879
|
+
output = process.stderr,
|
|
37880
|
+
refreshPackageAccess = refreshPackageAccessFromCloudAuth,
|
|
37881
|
+
autoUpdate = maybeAutoUpdateManagedEnv
|
|
37882
|
+
} = {}) {
|
|
37883
|
+
if (env3.VENDIAN_SKIP_AUTO_UPDATE === "1") {
|
|
37884
|
+
return false;
|
|
37885
|
+
}
|
|
37886
|
+
try {
|
|
37887
|
+
await refreshPackageAccess({ env: env3, platform: platform2 });
|
|
37888
|
+
} catch (error) {
|
|
37889
|
+
const message = errorMessage2(error);
|
|
37890
|
+
output.write(`[vendian] Package access refresh failed; continuing with installed runtime. ${message}
|
|
37891
|
+
`);
|
|
37892
|
+
}
|
|
37893
|
+
return autoUpdate({ env: env3, platform: platform2, force: true });
|
|
37894
|
+
}
|
|
37258
37895
|
async function loadInkRuntime() {
|
|
37259
37896
|
if (h) {
|
|
37260
37897
|
return;
|
|
@@ -37268,6 +37905,7 @@ async function loadInkRuntime() {
|
|
|
37268
37905
|
]);
|
|
37269
37906
|
h = reactModule.default.createElement;
|
|
37270
37907
|
useEffect6 = reactModule.useEffect;
|
|
37908
|
+
useRef2 = reactModule.useRef;
|
|
37271
37909
|
useState5 = reactModule.useState;
|
|
37272
37910
|
Box2 = inkModule.Box;
|
|
37273
37911
|
Text2 = inkModule.Text;
|
|
@@ -37278,11 +37916,25 @@ async function loadInkRuntime() {
|
|
|
37278
37916
|
TextInput2 = textInputModule.default;
|
|
37279
37917
|
Spinner2 = spinnerModule.default;
|
|
37280
37918
|
}
|
|
37919
|
+
function endpointRows({ env: env3 = process.env, platform: platform2 = process.platform } = {}) {
|
|
37920
|
+
return ENDPOINTS.map((endpoint) => {
|
|
37921
|
+
const status = cloudAuthStatus({ backend: endpoint.key, env: env3, platform: platform2 });
|
|
37922
|
+
const active = status.activeApiUrl === status.apiUrl;
|
|
37923
|
+
return {
|
|
37924
|
+
key: endpoint.key,
|
|
37925
|
+
label: endpoint.label,
|
|
37926
|
+
apiUrl: status.apiUrl,
|
|
37927
|
+
active,
|
|
37928
|
+
status: status.authenticated ? active ? "connected" : "signed in" : "not signed in",
|
|
37929
|
+
detail: status.authenticated ? status.email || status.apiUrl : status.apiUrl
|
|
37930
|
+
};
|
|
37931
|
+
});
|
|
37932
|
+
}
|
|
37281
37933
|
function runtimeSummary({ env: env3 = process.env, platform: platform2 = process.platform, now = Date.now() } = {}) {
|
|
37282
37934
|
const config = loadConfig(env3, platform2);
|
|
37283
37935
|
const venvPath = managedVenvPath(env3, platform2);
|
|
37284
37936
|
const vendianPath = venvVendian(venvPath, platform2);
|
|
37285
|
-
const installed =
|
|
37937
|
+
const installed = fs12.existsSync(vendianPath);
|
|
37286
37938
|
const lastUpdate = Date.parse(config.lastManagedUpdateAt || "");
|
|
37287
37939
|
const stale = !Number.isFinite(lastUpdate) || now - lastUpdate > 24 * 60 * 60 * 1e3;
|
|
37288
37940
|
return {
|
|
@@ -37298,37 +37950,92 @@ function packageAccessSummary({ env: env3 = process.env, platform: platform2 = p
|
|
|
37298
37950
|
source: registry.tokenSource || "local config"
|
|
37299
37951
|
};
|
|
37300
37952
|
}
|
|
37953
|
+
function isCtrlCInput(input = "", key = {}) {
|
|
37954
|
+
return input === "" || input === "" || Boolean(key?.ctrl && (key.name === "c" || input === "c"));
|
|
37955
|
+
}
|
|
37301
37956
|
function VendianShell({ env: env3, platform: platform2, input, output }) {
|
|
37302
37957
|
const app = useApp2();
|
|
37303
37958
|
const [screen, setScreen] = useState5("home");
|
|
37304
37959
|
const [serveState, setServeState] = useState5(null);
|
|
37305
|
-
|
|
37306
|
-
|
|
37960
|
+
const [exitArmed, setExitArmed] = useState5(false);
|
|
37961
|
+
const exitTimer = useRef2(null);
|
|
37962
|
+
const lastInterruptAt = useRef2(0);
|
|
37963
|
+
function armExit() {
|
|
37964
|
+
if (exitArmed) {
|
|
37307
37965
|
app.exit();
|
|
37966
|
+
return;
|
|
37967
|
+
}
|
|
37968
|
+
setExitArmed(true);
|
|
37969
|
+
if (exitTimer.current) {
|
|
37970
|
+
clearTimeout(exitTimer.current);
|
|
37971
|
+
}
|
|
37972
|
+
exitTimer.current = setTimeout(() => setExitArmed(false), 1500);
|
|
37973
|
+
}
|
|
37974
|
+
function handleInterrupt() {
|
|
37975
|
+
const now = Date.now();
|
|
37976
|
+
if (now - lastInterruptAt.current < 75) {
|
|
37977
|
+
return;
|
|
37978
|
+
}
|
|
37979
|
+
lastInterruptAt.current = now;
|
|
37980
|
+
if (screen === "serve") {
|
|
37981
|
+
return;
|
|
37982
|
+
}
|
|
37983
|
+
armExit();
|
|
37984
|
+
}
|
|
37985
|
+
useEffect6(() => () => {
|
|
37986
|
+
if (exitTimer.current) {
|
|
37987
|
+
clearTimeout(exitTimer.current);
|
|
37988
|
+
}
|
|
37989
|
+
}, []);
|
|
37990
|
+
useEffect6(() => {
|
|
37991
|
+
const onData = (chunk) => {
|
|
37992
|
+
if (isCtrlCInput(String(chunk || ""))) {
|
|
37993
|
+
handleInterrupt();
|
|
37994
|
+
}
|
|
37995
|
+
};
|
|
37996
|
+
input?.on?.("data", onData);
|
|
37997
|
+
process.on("SIGINT", handleInterrupt);
|
|
37998
|
+
return () => {
|
|
37999
|
+
input?.off?.("data", onData);
|
|
38000
|
+
process.off("SIGINT", handleInterrupt);
|
|
38001
|
+
};
|
|
38002
|
+
}, [input, screen, exitArmed]);
|
|
38003
|
+
useInput2((typedInput, key) => {
|
|
38004
|
+
if (isCtrlCInput(typedInput, key)) {
|
|
38005
|
+
handleInterrupt();
|
|
37308
38006
|
}
|
|
37309
38007
|
});
|
|
37310
38008
|
const goHome = () => setScreen("home");
|
|
38009
|
+
const breadcrumb = screen !== "home" ? ["Home", SCREEN_TITLES[screen] || screen] : ["Home"];
|
|
37311
38010
|
return h(
|
|
37312
38011
|
Box2,
|
|
37313
38012
|
{ flexDirection: "column" },
|
|
37314
|
-
h(Header, { env: env3, platform: platform2, serveState }),
|
|
38013
|
+
h(Header, { env: env3, platform: platform2, serveState, screen }),
|
|
38014
|
+
h(
|
|
38015
|
+
Text2,
|
|
38016
|
+
{ color: colors.muted },
|
|
38017
|
+
breadcrumb.map(
|
|
38018
|
+
(part, i) => i < breadcrumb.length - 1 ? `${part} ${fig.arrowRight} ` : part
|
|
38019
|
+
).join("")
|
|
38020
|
+
),
|
|
38021
|
+
h(Text2, null, ""),
|
|
37315
38022
|
screen === "home" && h(HomeScreen, { onSelect: (value) => value === "exit" ? app.exit() : setScreen(value) }),
|
|
37316
38023
|
screen === "connect" && h(ConnectScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37317
38024
|
screen === "init" && h(InitScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37318
38025
|
screen === "create" && h(CreateScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37319
|
-
screen === "serve" && h(ServeScreen, { env: env3, platform: platform2, input, output, onBack: goHome, onState: setServeState }),
|
|
38026
|
+
screen === "serve" && h(ServeScreen, { env: env3, platform: platform2, input, output, onBack: goHome, onState: setServeState, onExitApp: app.exit }),
|
|
37320
38027
|
screen === "doctor" && h(DoctorScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37321
38028
|
screen === "update" && h(UpdateScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37322
|
-
screen === "commands" && h(CommandsScreen, { onBack: goHome })
|
|
38029
|
+
screen === "commands" && h(CommandsScreen, { onBack: goHome }),
|
|
38030
|
+
exitArmed && screen !== "serve" && h(Text2, { color: colors.warning, bold: true }, " Press Ctrl+C again to exit.")
|
|
37323
38031
|
);
|
|
37324
38032
|
}
|
|
37325
|
-
function Header({ env: env3, platform: platform2, serveState }) {
|
|
38033
|
+
function Header({ env: env3, platform: platform2, serveState, screen }) {
|
|
37326
38034
|
const active = activeCloudAuthStatus({ env: env3, platform: platform2 });
|
|
37327
38035
|
const runtime = runtimeSummary({ env: env3, platform: platform2 });
|
|
37328
38036
|
const [npmUpdate, setNpmUpdate] = useState5(() => npmPackageUpdateSummary({ config: loadConfig(env3, platform2) }));
|
|
37329
38037
|
const [npmCheckStarted, setNpmCheckStarted] = useState5(false);
|
|
37330
38038
|
const pkg = packageAccessSummary({ env: env3, platform: platform2 });
|
|
37331
|
-
const daemon = serveState?.daemonId ? `Daemon ${serveState.daemonId} | ${serveState.activity}` : "Daemon idle";
|
|
37332
38039
|
useEffect6(() => {
|
|
37333
38040
|
let cancelled = false;
|
|
37334
38041
|
if (!npmUpdate.stale || npmCheckStarted) {
|
|
@@ -37344,29 +38051,111 @@ function Header({ env: env3, platform: platform2, serveState }) {
|
|
|
37344
38051
|
cancelled = true;
|
|
37345
38052
|
};
|
|
37346
38053
|
}, [env3, platform2, npmCheckStarted, npmUpdate.stale]);
|
|
38054
|
+
const connStatus = active.authenticated ? "ok" : "error";
|
|
38055
|
+
const connValue = active.authenticated ? `${active.email || "Authenticated"} ${fig.dash} ${active.apiUrl}` : "Not connected \u2014 run vendian login";
|
|
38056
|
+
const rtStatus = runtime.installed ? "ok" : "error";
|
|
38057
|
+
const rtValue = runtime.installed ? "Ready" : "Missing \u2014 run vendian login";
|
|
38058
|
+
const pkgStatus = pkg.configured ? "ok" : "warning";
|
|
38059
|
+
const pkgValue = pkg.configured ? `Configured (${pkg.source})` : "Missing";
|
|
38060
|
+
const updValue = updateLabel({ runtime, npmUpdate });
|
|
38061
|
+
const updStatus = updValue.includes("available") ? "warning" : "ok";
|
|
38062
|
+
const w = Math.min(process.stdout.columns || 80, 90);
|
|
38063
|
+
const inner = w - 2;
|
|
38064
|
+
const titleLeft = `${fig.vertical} ${fig.arrowUp} VENDIAN`;
|
|
38065
|
+
const titleRight = `v${CLI_VERSION} ${fig.vertical}`;
|
|
38066
|
+
const titlePad = Math.max(0, inner - titleLeft.length - titleRight.length + 2);
|
|
37347
38067
|
return h(
|
|
37348
38068
|
Box2,
|
|
37349
38069
|
{ flexDirection: "column", marginBottom: 1 },
|
|
37350
|
-
h(Text2, {
|
|
37351
|
-
h(
|
|
37352
|
-
|
|
37353
|
-
|
|
38070
|
+
h(Text2, { color: colors.muted }, `${fig.topLeft}${fig.horizontal.repeat(inner)}${fig.topRight}`),
|
|
38071
|
+
h(
|
|
38072
|
+
Text2,
|
|
38073
|
+
null,
|
|
38074
|
+
h(Text2, { color: colors.muted }, fig.vertical),
|
|
38075
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.arrowUp} VENDIAN`),
|
|
38076
|
+
h(Text2, null, " ".repeat(titlePad)),
|
|
38077
|
+
h(Text2, { color: colors.muted }, `v${CLI_VERSION} `),
|
|
38078
|
+
h(Text2, { color: colors.muted }, fig.vertical)
|
|
38079
|
+
),
|
|
38080
|
+
h(Text2, { color: colors.muted }, `${fig.teeRight}${fig.horizontal.repeat(inner)}${fig.teeLeft}`),
|
|
38081
|
+
h(StatusRow, { status: connStatus, label: "Endpoint", value: connValue, width: inner }),
|
|
38082
|
+
h(StatusRow, { status: rtStatus, label: "Runtime", value: rtValue, width: inner }),
|
|
38083
|
+
h(StatusRow, { status: pkgStatus, label: "Packages", value: pkgValue, width: inner }),
|
|
38084
|
+
h(StatusRow, { status: updStatus, label: "Updates", value: updValue, width: inner }),
|
|
38085
|
+
serveState?.daemonId && h(StatusRow, {
|
|
38086
|
+
status: serveState.connected ? "ok" : "warning",
|
|
38087
|
+
label: "Daemon",
|
|
38088
|
+
value: serveState.activity || "Running",
|
|
38089
|
+
width: inner
|
|
38090
|
+
}),
|
|
38091
|
+
h(Text2, { color: colors.muted }, `${fig.bottomLeft}${fig.horizontal.repeat(inner)}${fig.bottomRight}`)
|
|
38092
|
+
);
|
|
38093
|
+
}
|
|
38094
|
+
function StatusRow({ status, label, value, width }) {
|
|
38095
|
+
const dotColor = status === "ok" ? colors.success : status === "warning" ? colors.warning : colors.error;
|
|
38096
|
+
const dot = status === "ok" ? fig.dot : status === "warning" ? fig.dot : fig.dot;
|
|
38097
|
+
const paddedLabel = String(label).padEnd(spacing.labelWidth);
|
|
38098
|
+
const maxVal = Math.max(0, (width || 70) - spacing.labelWidth - 6);
|
|
38099
|
+
const clipped = clip(value || "", maxVal);
|
|
38100
|
+
return h(
|
|
38101
|
+
Text2,
|
|
38102
|
+
null,
|
|
38103
|
+
h(Text2, { color: colors.muted }, `${fig.vertical} `),
|
|
38104
|
+
h(Text2, { color: dotColor }, `${dot} `),
|
|
38105
|
+
h(Text2, { bold: true }, paddedLabel),
|
|
38106
|
+
h(Text2, null, clipped),
|
|
38107
|
+
h(Text2, { color: colors.muted }, ` ${fig.vertical}`)
|
|
37354
38108
|
);
|
|
37355
38109
|
}
|
|
37356
38110
|
function HomeScreen({ onSelect }) {
|
|
38111
|
+
const [activeIndex, setActiveIndex] = useState5(0);
|
|
38112
|
+
useInput2((input, key) => {
|
|
38113
|
+
if (key.upArrow) {
|
|
38114
|
+
setActiveIndex((i) => (i - 1 + ACTIONS.length) % ACTIONS.length);
|
|
38115
|
+
} else if (key.downArrow) {
|
|
38116
|
+
setActiveIndex((i) => (i + 1) % ACTIONS.length);
|
|
38117
|
+
} else if (key.return) {
|
|
38118
|
+
onSelect(ACTIONS[activeIndex].value);
|
|
38119
|
+
}
|
|
38120
|
+
});
|
|
37357
38121
|
return h(
|
|
37358
38122
|
Box2,
|
|
37359
38123
|
{ flexDirection: "column" },
|
|
37360
|
-
|
|
37361
|
-
|
|
38124
|
+
...ACTIONS.map((action, i) => {
|
|
38125
|
+
const isActive = i === activeIndex;
|
|
38126
|
+
const isSeparator = action.value === "doctor";
|
|
38127
|
+
return h(
|
|
38128
|
+
Box2,
|
|
38129
|
+
{ key: action.value, flexDirection: "column" },
|
|
38130
|
+
isSeparator && h(Text2, { color: colors.muted }, ` ${fig.horizontal.repeat(40)}`),
|
|
38131
|
+
h(
|
|
38132
|
+
Text2,
|
|
38133
|
+
null,
|
|
38134
|
+
h(Text2, { color: isActive ? colors.accent : colors.muted }, isActive ? ` ${fig.arrow} ` : " "),
|
|
38135
|
+
h(Text2, { bold: isActive, color: isActive ? colors.text : colors.muted }, action.label.padEnd(22)),
|
|
38136
|
+
h(Text2, { color: colors.dim }, action.desc)
|
|
38137
|
+
)
|
|
38138
|
+
);
|
|
38139
|
+
}),
|
|
38140
|
+
h(Text2, null, ""),
|
|
38141
|
+
h(FooterBar, { items: [
|
|
38142
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38143
|
+
{ key: "\u23CE", label: "Select" },
|
|
38144
|
+
{ key: "^c ^c", label: "Exit" }
|
|
38145
|
+
] })
|
|
37362
38146
|
);
|
|
37363
38147
|
}
|
|
37364
38148
|
function ConnectScreen({ env: env3, platform: platform2, onBack }) {
|
|
37365
38149
|
const [mode, setMode] = useState5("select");
|
|
37366
38150
|
const [apiUrl, setApiUrl] = useState5("");
|
|
37367
38151
|
const [status, setStatus] = useState5("");
|
|
38152
|
+
const rows = endpointRows({ env: env3, platform: platform2 });
|
|
37368
38153
|
const items = [
|
|
37369
|
-
...ENDPOINTS.map((endpoint) =>
|
|
38154
|
+
...ENDPOINTS.map((endpoint) => {
|
|
38155
|
+
const row = rows.find((r) => r.key === endpoint.key);
|
|
38156
|
+
const statusLabel = row ? row.active ? "\u25CF Connected" : row.status : "";
|
|
38157
|
+
return { label: `${endpoint.label.padEnd(12)} ${BACKEND_TARGETS[endpoint.key]} ${statusLabel}`, value: endpoint.key };
|
|
38158
|
+
}),
|
|
37370
38159
|
{ label: "Custom API URL", value: "custom" },
|
|
37371
38160
|
{ label: "Back", value: "back" }
|
|
37372
38161
|
];
|
|
@@ -37379,41 +38168,47 @@ function ConnectScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37379
38168
|
setMode("custom");
|
|
37380
38169
|
return;
|
|
37381
38170
|
}
|
|
37382
|
-
setStatus(`Connecting ${value}
|
|
38171
|
+
setStatus(`Connecting to ${value}...`);
|
|
37383
38172
|
await setup({ backend: value, forceAuth: true, env: env3, platform: platform2 });
|
|
37384
|
-
setStatus(
|
|
38173
|
+
setStatus(`${fig.check} Connected`);
|
|
37385
38174
|
}
|
|
37386
38175
|
if (mode === "custom") {
|
|
37387
38176
|
return h(
|
|
37388
38177
|
Box2,
|
|
37389
38178
|
{ flexDirection: "column" },
|
|
37390
|
-
h(Text2, { bold: true }, "
|
|
38179
|
+
h(Text2, { bold: true }, " Enter custom API URL:"),
|
|
38180
|
+
h(Text2, null, ""),
|
|
37391
38181
|
h(TextInput2, {
|
|
37392
38182
|
value: apiUrl,
|
|
37393
38183
|
placeholder: "https://api.example.test",
|
|
37394
38184
|
onChange: setApiUrl,
|
|
37395
38185
|
onSubmit: async (value) => {
|
|
37396
38186
|
if (!value) return;
|
|
37397
|
-
setStatus("Connecting
|
|
38187
|
+
setStatus("Connecting...");
|
|
37398
38188
|
await setup({ apiUrl: value, forceAuth: true, env: env3, platform: platform2 });
|
|
37399
|
-
setStatus(
|
|
38189
|
+
setStatus(`${fig.check} Connected`);
|
|
37400
38190
|
}
|
|
37401
38191
|
}),
|
|
37402
|
-
h(Text2,
|
|
38192
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38193
|
+
h(Text2, null, ""),
|
|
38194
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Submit" }, { key: "esc", label: "Back" }] }),
|
|
37403
38195
|
h(BackHint, { onBack })
|
|
37404
38196
|
);
|
|
37405
38197
|
}
|
|
37406
38198
|
return h(
|
|
37407
38199
|
Box2,
|
|
37408
38200
|
{ flexDirection: "column" },
|
|
37409
|
-
h(Text2, { bold: true }, "
|
|
38201
|
+
h(Text2, { bold: true }, " Select environment:"),
|
|
38202
|
+
h(Text2, null, ""),
|
|
37410
38203
|
h(SelectInput2, { items, onSelect: (item) => connect(item.value) }),
|
|
37411
|
-
status && h(Text2,
|
|
38204
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38205
|
+
h(Text2, null, ""),
|
|
38206
|
+
h(FooterBar, { items: [{ key: "\u2191\u2193", label: "Navigate" }, { key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] })
|
|
37412
38207
|
);
|
|
37413
38208
|
}
|
|
37414
38209
|
function InitScreen({ env: env3, platform: platform2, onBack }) {
|
|
37415
38210
|
return h(CommandPromptScreen, {
|
|
37416
|
-
title: "Initialize Docs",
|
|
38211
|
+
title: " Initialize Docs",
|
|
37417
38212
|
label: "Workspace directory",
|
|
37418
38213
|
initialValue: ".",
|
|
37419
38214
|
onBack,
|
|
@@ -37453,53 +38248,180 @@ function CreateScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37453
38248
|
h(BackHint, { onBack })
|
|
37454
38249
|
);
|
|
37455
38250
|
}
|
|
37456
|
-
function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
38251
|
+
function ServeScreen({ env: env3, platform: platform2, input, onBack, onState, onExitApp }) {
|
|
37457
38252
|
const [agentDirCandidates] = useState5(() => findAgentDirectoryCandidates());
|
|
37458
38253
|
const [agentsDir, setAgentsDir] = useState5(() => defaultAgentsDir(agentDirCandidates));
|
|
37459
38254
|
const [selectingDir, setSelectingDir] = useState5(() => agentDirCandidates.length > 0);
|
|
38255
|
+
const [workspaceChoices, setWorkspaceChoices] = useState5([]);
|
|
38256
|
+
const [pendingAgentsDir, setPendingAgentsDir] = useState5("");
|
|
38257
|
+
const [loadingWorkspaces, setLoadingWorkspaces] = useState5(false);
|
|
37460
38258
|
const [started, setStarted] = useState5(false);
|
|
37461
38259
|
const [state, setState] = useState5(initialServeState());
|
|
37462
38260
|
const [child, setChild] = useState5(null);
|
|
37463
|
-
const [
|
|
38261
|
+
const [logMode, setLogMode] = useState5(null);
|
|
37464
38262
|
const [confirmExit, setConfirmExit] = useState5(false);
|
|
38263
|
+
const [exitArmed, setExitArmed] = useState5(false);
|
|
37465
38264
|
const [startupError, setStartupError] = useState5("");
|
|
38265
|
+
const exitTimer = useRef2(null);
|
|
38266
|
+
const lastInterruptAt = useRef2(0);
|
|
37466
38267
|
useEffect6(() => {
|
|
37467
38268
|
onState(state);
|
|
37468
38269
|
}, [state, onState]);
|
|
37469
|
-
|
|
38270
|
+
useEffect6(() => () => {
|
|
38271
|
+
if (exitTimer.current) {
|
|
38272
|
+
clearTimeout(exitTimer.current);
|
|
38273
|
+
}
|
|
38274
|
+
}, []);
|
|
38275
|
+
function armExit() {
|
|
38276
|
+
if (exitArmed) {
|
|
38277
|
+
child?.kill("SIGINT");
|
|
38278
|
+
onState(null);
|
|
38279
|
+
onExitApp();
|
|
38280
|
+
return;
|
|
38281
|
+
}
|
|
38282
|
+
setExitArmed(true);
|
|
38283
|
+
setConfirmExit(false);
|
|
38284
|
+
if (exitTimer.current) {
|
|
38285
|
+
clearTimeout(exitTimer.current);
|
|
38286
|
+
}
|
|
38287
|
+
exitTimer.current = setTimeout(() => setExitArmed(false), 1500);
|
|
38288
|
+
}
|
|
38289
|
+
function handleInterrupt() {
|
|
38290
|
+
const now = Date.now();
|
|
38291
|
+
if (now - lastInterruptAt.current < 75) {
|
|
38292
|
+
return;
|
|
38293
|
+
}
|
|
38294
|
+
lastInterruptAt.current = now;
|
|
38295
|
+
armExit();
|
|
38296
|
+
}
|
|
38297
|
+
useEffect6(() => {
|
|
38298
|
+
const onData = (chunk) => {
|
|
38299
|
+
if (isCtrlCInput(String(chunk || ""))) {
|
|
38300
|
+
handleInterrupt();
|
|
38301
|
+
}
|
|
38302
|
+
};
|
|
38303
|
+
input?.on?.("data", onData);
|
|
38304
|
+
process.on("SIGINT", handleInterrupt);
|
|
38305
|
+
return () => {
|
|
38306
|
+
input?.off?.("data", onData);
|
|
38307
|
+
process.off("SIGINT", handleInterrupt);
|
|
38308
|
+
};
|
|
38309
|
+
}, [input, exitArmed, child]);
|
|
38310
|
+
useInput2((input2, key) => {
|
|
38311
|
+
if (isCtrlCInput(input2, key)) {
|
|
38312
|
+
handleInterrupt();
|
|
38313
|
+
return;
|
|
38314
|
+
}
|
|
37470
38315
|
if (!started) return;
|
|
38316
|
+
if (logMode !== null) {
|
|
38317
|
+
if (key.escape) {
|
|
38318
|
+
if (logMode === "picker") {
|
|
38319
|
+
setLogMode(null);
|
|
38320
|
+
} else {
|
|
38321
|
+
setLogMode("picker");
|
|
38322
|
+
}
|
|
38323
|
+
}
|
|
38324
|
+
return;
|
|
38325
|
+
}
|
|
37471
38326
|
if (confirmExit) {
|
|
37472
|
-
if (
|
|
38327
|
+
if (input2.toLowerCase() === "y" || key.return) {
|
|
37473
38328
|
child?.kill("SIGINT");
|
|
37474
38329
|
onState(null);
|
|
37475
38330
|
onBack();
|
|
37476
|
-
} else if (
|
|
38331
|
+
} else if (input2.toLowerCase() === "n" || key.escape) {
|
|
37477
38332
|
setConfirmExit(false);
|
|
37478
38333
|
}
|
|
37479
38334
|
return;
|
|
37480
38335
|
}
|
|
37481
|
-
if (
|
|
37482
|
-
|
|
37483
|
-
} else if (
|
|
38336
|
+
if (input2 === "l") {
|
|
38337
|
+
setLogMode("picker");
|
|
38338
|
+
} else if (input2 === "q") {
|
|
37484
38339
|
setConfirmExit(true);
|
|
37485
38340
|
}
|
|
37486
38341
|
});
|
|
37487
|
-
async function start(selectedAgentsDir = agentsDir) {
|
|
38342
|
+
async function start(selectedAgentsDir = agentsDir, collectionId = "") {
|
|
37488
38343
|
const serveRoot = selectedAgentsDir || "./agents";
|
|
37489
38344
|
setAgentsDir(serveRoot);
|
|
37490
38345
|
setStarted(true);
|
|
37491
38346
|
setStartupError("");
|
|
37492
38347
|
try {
|
|
37493
|
-
const
|
|
38348
|
+
const logStore = createServeLogStore({ agentsDir: serveRoot, collectionId, env: env3, platform: platform2 });
|
|
38349
|
+
const historicalLogs = logStore.load();
|
|
38350
|
+
if (historicalLogs.length > 0) {
|
|
38351
|
+
setState((current) => {
|
|
38352
|
+
const agentLogs = mergeAgentLogRecords(current.agentLogs, historicalLogs);
|
|
38353
|
+
return {
|
|
38354
|
+
...current,
|
|
38355
|
+
agentLogs,
|
|
38356
|
+
agentRunState: {
|
|
38357
|
+
...agentRunStateFromLogs(agentLogs, { includeRunning: false }),
|
|
38358
|
+
...current.agentRunState
|
|
38359
|
+
}
|
|
38360
|
+
};
|
|
38361
|
+
});
|
|
38362
|
+
}
|
|
38363
|
+
const nextChild = await spawnLocalServeEventStream({ agentsDir: serveRoot, collectionId, env: env3, platform: platform2 });
|
|
37494
38364
|
setChild(nextChild);
|
|
37495
|
-
attachServeChild(nextChild, setState, setStartupError, () => {
|
|
37496
|
-
setState((current) => current.stopped ? current : { ...current, stopped: true, activity: "Process exited" });
|
|
37497
|
-
});
|
|
38365
|
+
attachServeChild(nextChild, setState, setStartupError, ({ message } = {}) => {
|
|
38366
|
+
setState((current) => current.stopped ? current : { ...current, stopped: true, activity: message ? "Runtime update required" : "Process exited" });
|
|
38367
|
+
}, logStore);
|
|
38368
|
+
} catch (error) {
|
|
38369
|
+
setStartupError(errorMessage2(error));
|
|
38370
|
+
}
|
|
38371
|
+
}
|
|
38372
|
+
async function chooseWorkspaceThenStart(selectedAgentsDir = agentsDir) {
|
|
38373
|
+
const serveRoot = selectedAgentsDir || "./agents";
|
|
38374
|
+
setAgentsDir(serveRoot);
|
|
38375
|
+
setPendingAgentsDir(serveRoot);
|
|
38376
|
+
setStartupError("");
|
|
38377
|
+
setLoadingWorkspaces(true);
|
|
38378
|
+
try {
|
|
38379
|
+
const result = await listCloudWorkspaces({ env: env3, platform: platform2 });
|
|
38380
|
+
if (!result.ok) {
|
|
38381
|
+
setStartupError(result.error || "Could not list workspaces.");
|
|
38382
|
+
return;
|
|
38383
|
+
}
|
|
38384
|
+
if (result.workspaces.length > 1) {
|
|
38385
|
+
setWorkspaceChoices(result.workspaces);
|
|
38386
|
+
return;
|
|
38387
|
+
}
|
|
38388
|
+
await start(serveRoot, result.workspaces[0]?.id || "");
|
|
37498
38389
|
} catch (error) {
|
|
37499
38390
|
setStartupError(errorMessage2(error));
|
|
38391
|
+
} finally {
|
|
38392
|
+
setLoadingWorkspaces(false);
|
|
37500
38393
|
}
|
|
37501
38394
|
}
|
|
37502
38395
|
if (!started) {
|
|
38396
|
+
if (workspaceChoices.length > 1) {
|
|
38397
|
+
return h(
|
|
38398
|
+
Box2,
|
|
38399
|
+
{ flexDirection: "column" },
|
|
38400
|
+
h(Text2, { bold: true }, "Select workspace:"),
|
|
38401
|
+
h(SelectInput2, {
|
|
38402
|
+
items: [
|
|
38403
|
+
...workspaceChoices.map((workspace) => ({
|
|
38404
|
+
label: workspaceLabel(workspace),
|
|
38405
|
+
value: workspace.id
|
|
38406
|
+
})),
|
|
38407
|
+
{ label: "Back", value: "__back__" }
|
|
38408
|
+
],
|
|
38409
|
+
onSelect: (item) => {
|
|
38410
|
+
if (item.value === "__back__") {
|
|
38411
|
+
setWorkspaceChoices([]);
|
|
38412
|
+
return;
|
|
38413
|
+
}
|
|
38414
|
+
start(pendingAgentsDir || agentsDir, item.value);
|
|
38415
|
+
}
|
|
38416
|
+
}),
|
|
38417
|
+
h(Text2, null, ""),
|
|
38418
|
+
h(FooterBar, { items: [
|
|
38419
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38420
|
+
{ key: "\u23CE", label: "Select" },
|
|
38421
|
+
{ key: "esc", label: "Back" }
|
|
38422
|
+
] })
|
|
38423
|
+
);
|
|
38424
|
+
}
|
|
37503
38425
|
const items = [
|
|
37504
38426
|
...agentDirCandidates.map((candidate) => ({
|
|
37505
38427
|
label: `${candidate.path} (${candidate.agentCount} ${candidate.agentCount === 1 ? "agent" : "agents"})`,
|
|
@@ -37511,7 +38433,7 @@ function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
|
37511
38433
|
return h(
|
|
37512
38434
|
Box2,
|
|
37513
38435
|
{ flexDirection: "column" },
|
|
37514
|
-
h(Text2, { bold: true }, "
|
|
38436
|
+
h(Text2, { bold: true }, "Select agent directory:"),
|
|
37515
38437
|
selectingDir && h(SelectInput2, {
|
|
37516
38438
|
items,
|
|
37517
38439
|
onSelect: (item) => {
|
|
@@ -37525,77 +38447,434 @@ function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
|
37525
38447
|
return;
|
|
37526
38448
|
}
|
|
37527
38449
|
setAgentsDir(item.value);
|
|
37528
|
-
|
|
38450
|
+
chooseWorkspaceThenStart(item.value);
|
|
37529
38451
|
}
|
|
37530
38452
|
}),
|
|
37531
38453
|
!selectingDir && h(TextInput2, {
|
|
37532
38454
|
value: agentsDir,
|
|
37533
38455
|
placeholder: "./agents",
|
|
37534
38456
|
onChange: setAgentsDir,
|
|
37535
|
-
onSubmit: (value) =>
|
|
38457
|
+
onSubmit: (value) => chooseWorkspaceThenStart(value)
|
|
37536
38458
|
}),
|
|
37537
|
-
h(
|
|
38459
|
+
loadingWorkspaces && h(
|
|
38460
|
+
Box2,
|
|
38461
|
+
null,
|
|
38462
|
+
h(Text2, { color: colors.brand }, " "),
|
|
38463
|
+
h(Spinner2, { type: "dots" }),
|
|
38464
|
+
h(Text2, { color: colors.brand }, " Loading workspaces")
|
|
38465
|
+
),
|
|
38466
|
+
startupError && h(Text2, { color: colors.error }, ` ${fig.cross} ${startupError}`),
|
|
38467
|
+
h(Text2, null, ""),
|
|
38468
|
+
h(FooterBar, { items: [
|
|
38469
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38470
|
+
{ key: "\u23CE", label: "Select" },
|
|
38471
|
+
{ key: "esc", label: "Back" }
|
|
38472
|
+
] })
|
|
37538
38473
|
);
|
|
37539
38474
|
}
|
|
37540
38475
|
const summary = agentSummary(state.agents);
|
|
38476
|
+
if (logMode !== null) {
|
|
38477
|
+
return h(
|
|
38478
|
+
Box2,
|
|
38479
|
+
{ flexDirection: "column" },
|
|
38480
|
+
h(AgentLogViewer, {
|
|
38481
|
+
agents: state.agents,
|
|
38482
|
+
agentLogs: state.agentLogs,
|
|
38483
|
+
agentRunState: state.agentRunState,
|
|
38484
|
+
logMode,
|
|
38485
|
+
onSelectAgent: (path8) => setLogMode(path8),
|
|
38486
|
+
onBack: () => {
|
|
38487
|
+
if (logMode === "picker") {
|
|
38488
|
+
setLogMode(null);
|
|
38489
|
+
} else {
|
|
38490
|
+
setLogMode("picker");
|
|
38491
|
+
}
|
|
38492
|
+
}
|
|
38493
|
+
})
|
|
38494
|
+
);
|
|
38495
|
+
}
|
|
37541
38496
|
return h(
|
|
37542
38497
|
Box2,
|
|
37543
38498
|
{ flexDirection: "column" },
|
|
37544
|
-
h(Text2, {
|
|
37545
|
-
|
|
37546
|
-
|
|
37547
|
-
|
|
37548
|
-
|
|
37549
|
-
|
|
37550
|
-
|
|
37551
|
-
|
|
37552
|
-
h(
|
|
38499
|
+
startupError ? h(Text2, { color: colors.error }, ` ${fig.cross} ${startupError}`) : h(
|
|
38500
|
+
Box2,
|
|
38501
|
+
null,
|
|
38502
|
+
h(Text2, { color: colors.brand }, " "),
|
|
38503
|
+
h(Spinner2, { type: "dots" }),
|
|
38504
|
+
h(Text2, { color: colors.brand }, ` ${state.activity}`)
|
|
38505
|
+
),
|
|
38506
|
+
h(Text2, null, ""),
|
|
38507
|
+
h(
|
|
38508
|
+
Text2,
|
|
38509
|
+
null,
|
|
38510
|
+
h(Text2, { color: colors.muted }, " Agents: "),
|
|
38511
|
+
h(Text2, { color: colors.success, bold: true }, `${summary.ready} ready`),
|
|
38512
|
+
summary.needsSetup > 0 && h(Text2, { color: colors.warning }, ` ${fig.dot} ${summary.needsSetup} needs setup`),
|
|
38513
|
+
summary.errors > 0 && h(Text2, { color: colors.error }, ` ${fig.dot} ${summary.errors} errors`),
|
|
38514
|
+
h(Text2, { color: colors.muted }, ` ${fig.dot} ${summary.total} total`)
|
|
38515
|
+
),
|
|
38516
|
+
h(Text2, null, ""),
|
|
38517
|
+
state.newAgents?.length > 0 && h(
|
|
38518
|
+
Text2,
|
|
38519
|
+
{ color: colors.success },
|
|
38520
|
+
` ${fig.check} New agents synced automatically: ${state.newAgents.map((agent) => agent.relativePath || agent.manifestName || agent.path || "agent").join(", ")}`
|
|
38521
|
+
),
|
|
38522
|
+
h(AgentTable, { agents: state.agents, agentRunState: state.agentRunState }),
|
|
38523
|
+
state.retry && h(Text2, { color: colors.warning }, ` ${fig.warning} Retry: ${state.retry.activity} in ${Number(state.retry.delaySeconds || 0).toFixed(1)}s`),
|
|
38524
|
+
state.errors.length > 0 && h(
|
|
38525
|
+
Box2,
|
|
38526
|
+
{ flexDirection: "column", marginTop: 1 },
|
|
38527
|
+
...state.errors.slice(-3).map((item, index) => h(Text2, { key: `error-${index}`, color: colors.error }, ` ${fig.cross} ${item.scope}: ${item.message}`))
|
|
38528
|
+
),
|
|
38529
|
+
h(Text2, null, ""),
|
|
38530
|
+
confirmExit ? h(
|
|
38531
|
+
Text2,
|
|
38532
|
+
{ color: colors.warning, bold: true },
|
|
38533
|
+
" Stop local serve? ",
|
|
38534
|
+
h(Text2, { color: colors.accent }, "y"),
|
|
38535
|
+
h(Text2, { color: colors.muted }, "/"),
|
|
38536
|
+
h(Text2, { color: colors.accent }, "n")
|
|
38537
|
+
) : h(FooterBar, { items: [
|
|
38538
|
+
{ key: "l", label: "Agent logs" },
|
|
38539
|
+
{ key: "q", label: "Stop" },
|
|
38540
|
+
{ key: "^c ^c", label: "Exit" }
|
|
38541
|
+
] }),
|
|
38542
|
+
exitArmed && h(Text2, { color: colors.warning, bold: true }, " Press Ctrl+C again to exit.")
|
|
37553
38543
|
);
|
|
37554
38544
|
}
|
|
37555
|
-
function AgentTable({ agents }) {
|
|
38545
|
+
function AgentTable({ agents, agentRunState = {} }) {
|
|
37556
38546
|
if (!agents.length) {
|
|
37557
|
-
return h(Text2, {
|
|
38547
|
+
return h(Text2, { color: colors.muted }, ` ${fig.dotEmpty} No agents discovered yet.`);
|
|
38548
|
+
}
|
|
38549
|
+
const termWidth = Math.min(process.stdout.columns || 80, 100);
|
|
38550
|
+
const pathW = Math.min(22, Math.floor(termWidth * 0.25));
|
|
38551
|
+
const nameW = Math.min(28, Math.floor(termWidth * 0.32));
|
|
38552
|
+
const credW = 10;
|
|
38553
|
+
const statusW = 10;
|
|
38554
|
+
const headerLine = ` ${"Path".padEnd(pathW)} ${"Name".padEnd(nameW)} ${"Creds".padEnd(credW)} ${"Status".padEnd(statusW)}`;
|
|
38555
|
+
const separator = ` ${fig.horizontal.repeat(pathW + nameW + credW + statusW + 3)}`;
|
|
38556
|
+
const rows = agents.slice(0, 16).map((agent) => {
|
|
38557
|
+
const path8 = clip(agent.relativePath || ".", pathW);
|
|
38558
|
+
const name = clip(agent.manifestName || agent.manifest?.name || "-", nameW);
|
|
38559
|
+
const creds = credentialLabel(agent);
|
|
38560
|
+
const runtime = agentRuntimeStatus(agent, agentRunState);
|
|
38561
|
+
const status = runtime.label || "-";
|
|
38562
|
+
const statusColor = runtimeStatusColor(runtime.status);
|
|
38563
|
+
const statusIcon = runtimeStatusIcon(runtime.status);
|
|
38564
|
+
return h(
|
|
38565
|
+
Text2,
|
|
38566
|
+
{ key: agent.localAgentId || agent.relativePath },
|
|
38567
|
+
h(Text2, { color: colors.muted }, " "),
|
|
38568
|
+
h(Text2, null, path8.padEnd(pathW)),
|
|
38569
|
+
h(Text2, null, " "),
|
|
38570
|
+
h(Text2, null, name.padEnd(nameW)),
|
|
38571
|
+
h(Text2, null, " "),
|
|
38572
|
+
h(Text2, { color: colors.muted }, creds.padEnd(credW)),
|
|
38573
|
+
h(Text2, null, " "),
|
|
38574
|
+
h(Text2, { color: statusColor }, `${statusIcon} ${status}`)
|
|
38575
|
+
);
|
|
38576
|
+
});
|
|
38577
|
+
const hiddenCount = agents.length - 16;
|
|
38578
|
+
return h(
|
|
38579
|
+
Box2,
|
|
38580
|
+
{ flexDirection: "column" },
|
|
38581
|
+
h(Text2, { color: colors.muted, bold: true }, headerLine),
|
|
38582
|
+
h(Text2, { color: colors.muted }, separator),
|
|
38583
|
+
...rows,
|
|
38584
|
+
hiddenCount > 0 && h(Text2, { color: colors.muted }, ` ${fig.ellipsis} and ${hiddenCount} more`)
|
|
38585
|
+
);
|
|
38586
|
+
}
|
|
38587
|
+
function runtimeStatusColor(status) {
|
|
38588
|
+
if (status === "running") return colors.accent;
|
|
38589
|
+
if (status === "ready" || status === "completed") return colors.success;
|
|
38590
|
+
if (status === "error") return colors.error;
|
|
38591
|
+
return colors.warning;
|
|
38592
|
+
}
|
|
38593
|
+
function runtimeStatusIcon(status) {
|
|
38594
|
+
if (status === "running") return fig.arrow;
|
|
38595
|
+
if (status === "ready" || status === "completed") return fig.dot;
|
|
38596
|
+
if (status === "error") return fig.cross;
|
|
38597
|
+
return fig.dotEmpty;
|
|
38598
|
+
}
|
|
38599
|
+
function FooterBar({ items }) {
|
|
38600
|
+
if (!items || !items.length) return null;
|
|
38601
|
+
return h(
|
|
38602
|
+
Text2,
|
|
38603
|
+
{ color: colors.muted },
|
|
38604
|
+
" ",
|
|
38605
|
+
...items.map((item, i) => [
|
|
38606
|
+
h(Text2, { key: `k-${i}`, color: colors.accent, bold: true }, item.key),
|
|
38607
|
+
h(Text2, { key: `l-${i}`, color: colors.muted }, ` ${item.label}`),
|
|
38608
|
+
i < items.length - 1 ? h(Text2, { key: `s-${i}` }, " ") : null
|
|
38609
|
+
]).flat().filter(Boolean)
|
|
38610
|
+
);
|
|
38611
|
+
}
|
|
38612
|
+
function AgentLogViewer({ agents, agentLogs, agentRunState, logMode, onSelectAgent, onBack }) {
|
|
38613
|
+
if (logMode === "picker") {
|
|
38614
|
+
return h(AgentLogPicker, { agents, agentLogs, agentRunState, onSelectAgent, onBack });
|
|
38615
|
+
}
|
|
38616
|
+
return h(AgentLogDetail, { relativePath: logMode, agentLogs, agentRunState, agents, onBack });
|
|
38617
|
+
}
|
|
38618
|
+
function AgentLogPicker({ agents, agentLogs, agentRunState = {}, onSelectAgent, onBack }) {
|
|
38619
|
+
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
38620
|
+
const agentList = agents.map((agent) => {
|
|
38621
|
+
const path8 = agent.relativePath || ".";
|
|
38622
|
+
const logs = agentLogEntries(agentLogs, path8);
|
|
38623
|
+
const lastLog = logs.length > 0 ? logs[logs.length - 1] : null;
|
|
38624
|
+
const hasErrors = logs.some((l) => l.level === "error" || l.eventType === "completion" && l.success === false);
|
|
38625
|
+
return {
|
|
38626
|
+
path: path8,
|
|
38627
|
+
name: agent.manifestName || agent.manifest?.name || path8,
|
|
38628
|
+
logCount: logs.length,
|
|
38629
|
+
lastLog,
|
|
38630
|
+
hasErrors,
|
|
38631
|
+
status: agentRuntimeStatus(agent, agentRunState)
|
|
38632
|
+
};
|
|
38633
|
+
});
|
|
38634
|
+
const inventoryPaths = new Set(agentList.map((a) => a.path));
|
|
38635
|
+
for (const path8 of Object.keys(agentLogs || {})) {
|
|
38636
|
+
if (!inventoryPaths.has(path8)) {
|
|
38637
|
+
const logs = agentLogEntries(agentLogs, path8);
|
|
38638
|
+
agentList.push({
|
|
38639
|
+
path: path8,
|
|
38640
|
+
name: path8,
|
|
38641
|
+
logCount: logs.length,
|
|
38642
|
+
lastLog: logs.length > 0 ? logs[logs.length - 1] : null,
|
|
38643
|
+
hasErrors: logs.some((l) => l.level === "error"),
|
|
38644
|
+
status: { status: "unknown", label: "offline" }
|
|
38645
|
+
});
|
|
38646
|
+
}
|
|
37558
38647
|
}
|
|
38648
|
+
useInput2((input, key) => {
|
|
38649
|
+
if (key.upArrow) {
|
|
38650
|
+
setSelectedIndex((i) => (i - 1 + agentList.length) % agentList.length);
|
|
38651
|
+
} else if (key.downArrow) {
|
|
38652
|
+
setSelectedIndex((i) => (i + 1) % agentList.length);
|
|
38653
|
+
} else if (key.return) {
|
|
38654
|
+
if (agentList.length > 0) {
|
|
38655
|
+
onSelectAgent(agentList[selectedIndex].path);
|
|
38656
|
+
}
|
|
38657
|
+
} else if (key.escape) {
|
|
38658
|
+
onBack();
|
|
38659
|
+
}
|
|
38660
|
+
});
|
|
38661
|
+
if (agentList.length === 0) {
|
|
38662
|
+
return h(
|
|
38663
|
+
Box2,
|
|
38664
|
+
{ flexDirection: "column" },
|
|
38665
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} Agent Logs`),
|
|
38666
|
+
h(Text2, null, ""),
|
|
38667
|
+
h(Text2, { color: colors.muted }, " No agent logs yet. Logs appear when agents run."),
|
|
38668
|
+
h(Text2, null, ""),
|
|
38669
|
+
h(FooterBar, { items: [{ key: "esc", label: "Back to serve" }] })
|
|
38670
|
+
);
|
|
38671
|
+
}
|
|
38672
|
+
const pathW = 24;
|
|
38673
|
+
const nameW = 24;
|
|
38674
|
+
const statusW = 10;
|
|
37559
38675
|
return h(
|
|
37560
38676
|
Box2,
|
|
37561
38677
|
{ flexDirection: "column" },
|
|
37562
|
-
h(Text2, {
|
|
37563
|
-
|
|
37564
|
-
|
|
37565
|
-
|
|
37566
|
-
|
|
37567
|
-
|
|
38678
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} Agent Logs ${fig.horizontal.repeat(20)}`),
|
|
38679
|
+
h(Text2, null, ""),
|
|
38680
|
+
h(Text2, { color: colors.muted }, ` ${"Agent".padEnd(nameW)} ${"Status".padEnd(statusW)} ${"Logs".padEnd(6)} ${"Last event"}`),
|
|
38681
|
+
h(Text2, { color: colors.muted }, ` ${fig.horizontal.repeat(nameW + statusW + 6 + 32)}`),
|
|
38682
|
+
...agentList.map((agent, i) => {
|
|
38683
|
+
const isActive = i === selectedIndex;
|
|
38684
|
+
const logCountColor = agent.hasErrors ? colors.error : agent.logCount > 0 ? colors.success : colors.muted;
|
|
38685
|
+
const lastEvent = agent.lastLog ? formatAgentLogEntry(agent.lastLog) : "No logs";
|
|
38686
|
+
return h(
|
|
38687
|
+
Text2,
|
|
38688
|
+
{ key: agent.path },
|
|
38689
|
+
h(Text2, { color: isActive ? colors.accent : colors.muted }, isActive ? ` ${fig.arrow} ` : " "),
|
|
38690
|
+
h(Text2, { bold: isActive }, clip(agent.name, nameW - 2).padEnd(nameW)),
|
|
38691
|
+
h(Text2, { color: runtimeStatusColor(agent.status.status) }, `${runtimeStatusIcon(agent.status.status)} ${agent.status.label}`.padEnd(statusW)),
|
|
38692
|
+
h(Text2, { color: logCountColor }, String(agent.logCount).padEnd(6)),
|
|
38693
|
+
h(Text2, { color: colors.muted }, clip(lastEvent, 36))
|
|
38694
|
+
);
|
|
38695
|
+
}),
|
|
38696
|
+
h(Text2, null, ""),
|
|
38697
|
+
h(FooterBar, { items: [
|
|
38698
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38699
|
+
{ key: "\u23CE", label: "View logs" },
|
|
38700
|
+
{ key: "esc", label: "Back to serve" }
|
|
38701
|
+
] })
|
|
37568
38702
|
);
|
|
37569
38703
|
}
|
|
37570
|
-
function
|
|
38704
|
+
function AgentLogDetail({ relativePath, agentLogs, agentRunState = {}, agents, onBack }) {
|
|
38705
|
+
const logs = agentLogEntries(agentLogs, relativePath);
|
|
38706
|
+
const agent = agents.find((a) => (a.relativePath || ".") === relativePath);
|
|
38707
|
+
const agentName = agent?.manifestName || agent?.manifest?.name || relativePath;
|
|
38708
|
+
const runtime = agent ? agentRuntimeStatus(agent, agentRunState) : { status: agentRunState?.[relativePath]?.status || "unknown", label: agentRunState?.[relativePath]?.status || "offline" };
|
|
38709
|
+
const [scrollOffset, setScrollOffset] = useState5(0);
|
|
38710
|
+
const visibleCount = Math.min(20, Math.max(8, (process.stdout.rows || 24) - 10));
|
|
38711
|
+
useInput2((input, key) => {
|
|
38712
|
+
if (key.escape) {
|
|
38713
|
+
onBack();
|
|
38714
|
+
} else if (key.upArrow) {
|
|
38715
|
+
setScrollOffset((o) => Math.max(0, o - 1));
|
|
38716
|
+
} else if (key.downArrow) {
|
|
38717
|
+
setScrollOffset((o) => Math.min(Math.max(0, logs.length - visibleCount), o + 1));
|
|
38718
|
+
} else if (key.pageDown || input === " ") {
|
|
38719
|
+
setScrollOffset((o) => Math.min(Math.max(0, logs.length - visibleCount), o + visibleCount));
|
|
38720
|
+
} else if (key.pageUp) {
|
|
38721
|
+
setScrollOffset((o) => Math.max(0, o - visibleCount));
|
|
38722
|
+
}
|
|
38723
|
+
});
|
|
38724
|
+
const effectiveOffset = logs.length <= visibleCount ? 0 : scrollOffset >= logs.length - visibleCount - 2 ? Math.max(0, logs.length - visibleCount) : scrollOffset;
|
|
38725
|
+
const visibleLogs = logs.slice(effectiveOffset, effectiveOffset + visibleCount);
|
|
38726
|
+
const visibleRows = groupedLogRows(visibleLogs, logs[effectiveOffset - 1]);
|
|
38727
|
+
const messageWidth = Math.max(50, Math.min((process.stdout.columns || 80) - 18, 120));
|
|
37571
38728
|
return h(
|
|
37572
38729
|
Box2,
|
|
37573
|
-
{ flexDirection: "column"
|
|
37574
|
-
h(Text2, { bold: true },
|
|
37575
|
-
|
|
38730
|
+
{ flexDirection: "column" },
|
|
38731
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} ${agentName}`),
|
|
38732
|
+
h(
|
|
37576
38733
|
Text2,
|
|
37577
|
-
|
|
37578
|
-
|
|
37579
|
-
|
|
38734
|
+
null,
|
|
38735
|
+
h(Text2, { color: colors.muted }, ` ${relativePath} ${fig.dash} ${logs.length} log entries ${fig.dash} `),
|
|
38736
|
+
h(Text2, { color: runtimeStatusColor(runtime.status) }, `${runtimeStatusIcon(runtime.status)} ${runtime.label}`)
|
|
38737
|
+
),
|
|
38738
|
+
h(Text2, null, ""),
|
|
38739
|
+
logs.length === 0 ? h(Text2, { color: colors.muted }, " No logs recorded yet for this agent. Logs appear during runs.") : h(
|
|
38740
|
+
Box2,
|
|
38741
|
+
{ flexDirection: "column" },
|
|
38742
|
+
...visibleRows.map((row, i) => {
|
|
38743
|
+
if (row.type === "divider") {
|
|
38744
|
+
return h(
|
|
38745
|
+
Text2,
|
|
38746
|
+
{ key: `divider-${effectiveOffset}-${i}`, color: colors.dim },
|
|
38747
|
+
` ${fig.horizontal.repeat(3)} run ${clip(row.runId, 24)} ${fig.horizontal.repeat(12)}`
|
|
38748
|
+
);
|
|
38749
|
+
}
|
|
38750
|
+
const entry = row.entry;
|
|
38751
|
+
const levelColor = entry.level === "error" ? colors.error : entry.level === "warning" ? colors.warning : entry.level === "debug" ? colors.dim : colors.muted;
|
|
38752
|
+
const timeStr = formatLogTime(entry.timestamp);
|
|
38753
|
+
const icon = entry.eventType === "completion" ? entry.success ? fig.check : fig.cross : entry.eventType === "job_started" ? fig.arrow : entry.eventType === "job_completed" ? entry.success === false ? fig.cross : fig.check : entry.eventType === "step_event" ? fig.arrow : entry.eventType === "progress" ? fig.dotEmpty : entry.eventType === "error" || entry.level === "error" ? fig.cross : fig.dash;
|
|
38754
|
+
const iconColor = entry.eventType === "completion" ? entry.success ? colors.success : colors.error : entry.eventType === "job_started" ? colors.accent : entry.eventType === "job_completed" ? entry.success === false ? colors.error : colors.success : levelColor;
|
|
38755
|
+
return h(
|
|
38756
|
+
Text2,
|
|
38757
|
+
{ key: `entry-${effectiveOffset}-${i}` },
|
|
38758
|
+
h(Text2, { color: colors.dim }, ` ${timeStr} `),
|
|
38759
|
+
h(Text2, { color: iconColor }, `${icon} `),
|
|
38760
|
+
h(
|
|
38761
|
+
Text2,
|
|
38762
|
+
{ color: entry.level === "error" ? colors.error : colors.text },
|
|
38763
|
+
clip(formatAgentLogEntry(entry), messageWidth)
|
|
38764
|
+
)
|
|
38765
|
+
);
|
|
38766
|
+
}),
|
|
38767
|
+
logs.length > visibleCount && h(
|
|
38768
|
+
Text2,
|
|
38769
|
+
{ color: colors.muted },
|
|
38770
|
+
` ${fig.ellipsis} Showing ${effectiveOffset + 1}-${effectiveOffset + visibleLogs.length} of ${logs.length}`
|
|
38771
|
+
)
|
|
38772
|
+
),
|
|
38773
|
+
h(Text2, null, ""),
|
|
38774
|
+
h(FooterBar, { items: [
|
|
38775
|
+
{ key: "\u2191\u2193", label: "Scroll" },
|
|
38776
|
+
{ key: "PgUp/Dn", label: "Page" },
|
|
38777
|
+
{ key: "esc", label: "Back to agents" }
|
|
38778
|
+
] })
|
|
37580
38779
|
);
|
|
37581
38780
|
}
|
|
38781
|
+
function formatAgentLogEntry(entry) {
|
|
38782
|
+
if (!entry) return "";
|
|
38783
|
+
const type = entry.eventType || "";
|
|
38784
|
+
switch (type) {
|
|
38785
|
+
case "job_started":
|
|
38786
|
+
return entry.message || `Started ${entry.jobType || "run"}`;
|
|
38787
|
+
case "job_completed":
|
|
38788
|
+
return entry.success === false ? `Failed: ${formatEntryError(entry.error) || entry.message || "error"}` : entry.message || "Completed successfully";
|
|
38789
|
+
case "error":
|
|
38790
|
+
return `Error: ${entry.message || formatEntryError(entry.error) || "unknown error"}`;
|
|
38791
|
+
case "log":
|
|
38792
|
+
return entry.message || "";
|
|
38793
|
+
case "progress": {
|
|
38794
|
+
const prog = entry.current != null && entry.total != null ? `${entry.current}/${entry.total}` : "";
|
|
38795
|
+
return `${prog}${entry.message ? ` ${entry.message}` : ""}`.trim() || "progress";
|
|
38796
|
+
}
|
|
38797
|
+
case "completion":
|
|
38798
|
+
if (entry.success) return "Completed successfully";
|
|
38799
|
+
if (entry.error && typeof entry.error === "object") return `Failed: ${entry.error.message || "error"}`;
|
|
38800
|
+
return `Failed: ${entry.error || "unknown error"}`;
|
|
38801
|
+
case "step_event":
|
|
38802
|
+
return `Step: ${entry.stepId || "unknown"}${entry.message ? ` - ${entry.message}` : ""}`;
|
|
38803
|
+
case "step_checkpoint":
|
|
38804
|
+
return `Checkpoint: ${entry.stepId || "unknown"}`;
|
|
38805
|
+
case "step_heartbeat":
|
|
38806
|
+
return `Heartbeat: ${entry.stepId || ""}${entry.message ? ` - ${entry.message}` : ""}`;
|
|
38807
|
+
case "artifact":
|
|
38808
|
+
return `Artifact: ${entry.message || "data"}`;
|
|
38809
|
+
default:
|
|
38810
|
+
return entry.message || type || "event";
|
|
38811
|
+
}
|
|
38812
|
+
}
|
|
38813
|
+
function groupedLogRows(logs, previousEntry) {
|
|
38814
|
+
const rows = [];
|
|
38815
|
+
let currentRunId = previousEntry?.runId || "";
|
|
38816
|
+
for (const entry of logs) {
|
|
38817
|
+
const runId = entry.runId || "";
|
|
38818
|
+
if (runId && runId !== currentRunId) {
|
|
38819
|
+
rows.push({ type: "divider", runId });
|
|
38820
|
+
currentRunId = runId;
|
|
38821
|
+
}
|
|
38822
|
+
rows.push({ type: "entry", entry });
|
|
38823
|
+
}
|
|
38824
|
+
return rows;
|
|
38825
|
+
}
|
|
38826
|
+
function formatEntryError(error) {
|
|
38827
|
+
if (!error) return "";
|
|
38828
|
+
if (typeof error === "object") return error.message || "error";
|
|
38829
|
+
return String(error);
|
|
38830
|
+
}
|
|
38831
|
+
function formatLogTime(timestamp) {
|
|
38832
|
+
if (!timestamp) return " ";
|
|
38833
|
+
try {
|
|
38834
|
+
const d = new Date(timestamp);
|
|
38835
|
+
const h2 = String(d.getHours()).padStart(2, "0");
|
|
38836
|
+
const m = String(d.getMinutes()).padStart(2, "0");
|
|
38837
|
+
const s = String(d.getSeconds()).padStart(2, "0");
|
|
38838
|
+
return `${h2}:${m}:${s}`;
|
|
38839
|
+
} catch {
|
|
38840
|
+
return " ";
|
|
38841
|
+
}
|
|
38842
|
+
}
|
|
37582
38843
|
function DoctorScreen({ env: env3, platform: platform2, onBack }) {
|
|
37583
38844
|
const runtime = runtimeSummary({ env: env3, platform: platform2 });
|
|
37584
38845
|
const pkg = packageAccessSummary({ env: env3, platform: platform2 });
|
|
38846
|
+
const checks = [
|
|
38847
|
+
{ label: "Managed Python", passed: runtime.installed, value: runtime.installed ? "Present" : "Missing" },
|
|
38848
|
+
{ label: "Managed Env", passed: runtime.installed, value: runtime.detail },
|
|
38849
|
+
{ label: "Package Access", passed: pkg.configured, value: pkg.configured ? `Configured (${pkg.source})` : "Missing" }
|
|
38850
|
+
];
|
|
38851
|
+
const allPassed = checks.every((c) => c.passed);
|
|
37585
38852
|
return h(
|
|
37586
38853
|
Box2,
|
|
37587
38854
|
{ flexDirection: "column" },
|
|
37588
|
-
h(Text2, { bold: true }, "
|
|
37589
|
-
h(Text2, null,
|
|
37590
|
-
|
|
37591
|
-
|
|
38855
|
+
h(Text2, { bold: true }, " System Health"),
|
|
38856
|
+
h(Text2, null, ""),
|
|
38857
|
+
...checks.map((check) => h(
|
|
38858
|
+
Text2,
|
|
38859
|
+
{ key: check.label },
|
|
38860
|
+
h(Text2, { color: check.passed ? colors.success : colors.error }, ` ${check.passed ? fig.check : fig.cross} `),
|
|
38861
|
+
h(Text2, null, `${check.label.padEnd(18)}${check.value}`)
|
|
38862
|
+
)),
|
|
38863
|
+
h(Text2, null, ""),
|
|
38864
|
+
h(
|
|
38865
|
+
Text2,
|
|
38866
|
+
{ color: allPassed ? colors.success : colors.warning, bold: true },
|
|
38867
|
+
allPassed ? ` ${fig.check} All checks passed` : ` ${fig.warning} Some checks need attention`
|
|
38868
|
+
),
|
|
38869
|
+
h(Text2, null, ""),
|
|
37592
38870
|
h(SelectInput2, {
|
|
37593
|
-
items: [{ label: "Run
|
|
38871
|
+
items: [{ label: "Run full doctor output", value: "run" }, { label: "Back", value: "back" }],
|
|
37594
38872
|
onSelect: async (item) => {
|
|
37595
38873
|
if (item.value === "back") onBack();
|
|
37596
38874
|
else doctor({ env: env3, platform: platform2 });
|
|
37597
38875
|
}
|
|
37598
|
-
})
|
|
38876
|
+
}),
|
|
38877
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] })
|
|
37599
38878
|
);
|
|
37600
38879
|
}
|
|
37601
38880
|
function UpdateScreen({ env: env3, platform: platform2, onBack }) {
|
|
@@ -37603,29 +38882,65 @@ function UpdateScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37603
38882
|
return h(
|
|
37604
38883
|
Box2,
|
|
37605
38884
|
{ flexDirection: "column" },
|
|
37606
|
-
h(Text2, { bold: true }, "Update"),
|
|
38885
|
+
h(Text2, { bold: true }, " Update Runtime"),
|
|
38886
|
+
h(Text2, null, ""),
|
|
37607
38887
|
h(SelectInput2, {
|
|
37608
|
-
items: [{ label: "Update managed runtime", value: "run" }, { label: "Back", value: "back" }],
|
|
38888
|
+
items: [{ label: "Update managed runtime & packages", value: "run" }, { label: "Back", value: "back" }],
|
|
37609
38889
|
onSelect: async (item) => {
|
|
37610
38890
|
if (item.value === "back") {
|
|
37611
38891
|
onBack();
|
|
37612
38892
|
return;
|
|
37613
38893
|
}
|
|
37614
|
-
setStatus(
|
|
38894
|
+
setStatus(`${fig.dotEmpty} Updating managed runtime...`);
|
|
37615
38895
|
await setup({ nonInteractive: true, env: env3, platform: platform2 });
|
|
37616
|
-
setStatus(
|
|
38896
|
+
setStatus(`${fig.check} Update finished`);
|
|
37617
38897
|
}
|
|
37618
38898
|
}),
|
|
37619
|
-
status && h(Text2,
|
|
38899
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38900
|
+
h(Text2, null, ""),
|
|
38901
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] }),
|
|
38902
|
+
h(BackHint, { onBack })
|
|
37620
38903
|
);
|
|
37621
38904
|
}
|
|
37622
38905
|
function CommandsScreen({ onBack }) {
|
|
38906
|
+
const grouped = [
|
|
38907
|
+
{ section: "Getting Started", commands: [
|
|
38908
|
+
{ cmd: "vendian login", desc: "Sign in and prepare runtime" },
|
|
38909
|
+
{ cmd: "vendian init --output-dir ./agents", desc: "Initialize docs workspace" }
|
|
38910
|
+
] },
|
|
38911
|
+
{ section: "Agent Development", commands: [
|
|
38912
|
+
{ cmd: 'vendian create "My Agent" --output-dir .', desc: "Scaffold new agent" },
|
|
38913
|
+
{ cmd: "vendian validate ./agents/my-agent --runtime", desc: "Validate manifest" },
|
|
38914
|
+
{ cmd: "vendian test ./agents/my-agent --dry-run", desc: "Test locally" },
|
|
38915
|
+
{ cmd: "vendian models", desc: "List available models" }
|
|
38916
|
+
] },
|
|
38917
|
+
{ section: "Cloud & Deploy", commands: [
|
|
38918
|
+
{ cmd: "vendian cloud local serve --agents-dir .", desc: "Start cloud-connected serve" },
|
|
38919
|
+
{ cmd: "vendian login --backend staging", desc: "Connect to staging" }
|
|
38920
|
+
] },
|
|
38921
|
+
{ section: "Maintenance", commands: [
|
|
38922
|
+
{ cmd: "vendian doctor", desc: "Check system health" },
|
|
38923
|
+
{ cmd: "vendian update", desc: "Update runtime & packages" }
|
|
38924
|
+
] }
|
|
38925
|
+
];
|
|
37623
38926
|
return h(
|
|
37624
38927
|
Box2,
|
|
37625
38928
|
{ flexDirection: "column" },
|
|
37626
|
-
h(Text2, { bold: true }, "
|
|
37627
|
-
|
|
37628
|
-
|
|
38929
|
+
h(Text2, { bold: true }, " Quick Reference"),
|
|
38930
|
+
h(Text2, null, ""),
|
|
38931
|
+
...grouped.map((group) => [
|
|
38932
|
+
h(Text2, { key: `title-${group.section}`, color: colors.accent, bold: true }, ` ${group.section}`),
|
|
38933
|
+
...group.commands.map((item) => h(
|
|
38934
|
+
Text2,
|
|
38935
|
+
{ key: item.cmd },
|
|
38936
|
+
h(Text2, { color: colors.muted }, " "),
|
|
38937
|
+
h(Text2, { color: colors.brand }, item.cmd.padEnd(44)),
|
|
38938
|
+
h(Text2, { color: colors.muted }, item.desc)
|
|
38939
|
+
)),
|
|
38940
|
+
h(Text2, { key: `gap-${group.section}` }, "")
|
|
38941
|
+
]).flat(),
|
|
38942
|
+
h(FooterBar, { items: [{ key: "esc", label: "Back" }] }),
|
|
38943
|
+
h(BackHint, { onBack })
|
|
37629
38944
|
);
|
|
37630
38945
|
}
|
|
37631
38946
|
function CommandPromptScreen({ title, label, initialValue, onSubmit, onBack }) {
|
|
@@ -37635,17 +38950,20 @@ function CommandPromptScreen({ title, label, initialValue, onSubmit, onBack }) {
|
|
|
37635
38950
|
Box2,
|
|
37636
38951
|
{ flexDirection: "column" },
|
|
37637
38952
|
h(Text2, { bold: true }, title),
|
|
38953
|
+
h(Text2, null, ""),
|
|
37638
38954
|
h(TextInput2, {
|
|
37639
38955
|
value,
|
|
37640
38956
|
placeholder: label,
|
|
37641
38957
|
onChange: setValue,
|
|
37642
38958
|
onSubmit: async (submitted) => {
|
|
37643
|
-
setStatus(
|
|
38959
|
+
setStatus(`${fig.dotEmpty} Running...`);
|
|
37644
38960
|
await onSubmit(submitted);
|
|
37645
|
-
setStatus(
|
|
38961
|
+
setStatus(`${fig.check} Done`);
|
|
37646
38962
|
}
|
|
37647
38963
|
}),
|
|
37648
|
-
status && h(Text2,
|
|
38964
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38965
|
+
h(Text2, null, ""),
|
|
38966
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Submit" }, { key: "esc", label: "Back" }] }),
|
|
37649
38967
|
h(BackHint, { onBack })
|
|
37650
38968
|
);
|
|
37651
38969
|
}
|
|
@@ -37653,10 +38971,11 @@ function BackHint({ onBack }) {
|
|
|
37653
38971
|
useInput2((input, key) => {
|
|
37654
38972
|
if (key.escape || input === "\x1B") onBack();
|
|
37655
38973
|
});
|
|
37656
|
-
return
|
|
38974
|
+
return null;
|
|
37657
38975
|
}
|
|
37658
|
-
function attachServeChild(child, setState, setStartupError, onExit) {
|
|
38976
|
+
function attachServeChild(child, setState, setStartupError, onExit, logStore = null) {
|
|
37659
38977
|
let buffer = "";
|
|
38978
|
+
const stderrChunks = [];
|
|
37660
38979
|
child.stdout.setEncoding("utf8");
|
|
37661
38980
|
child.stdout.on("data", (chunk) => {
|
|
37662
38981
|
buffer += chunk;
|
|
@@ -37666,6 +38985,10 @@ function attachServeChild(child, setState, setStartupError, onExit) {
|
|
|
37666
38985
|
try {
|
|
37667
38986
|
const event = parseServeEventLine(line);
|
|
37668
38987
|
if (event) {
|
|
38988
|
+
try {
|
|
38989
|
+
logStore?.append(event);
|
|
38990
|
+
} catch {
|
|
38991
|
+
}
|
|
37669
38992
|
setState((current) => applyServeEvent(current, event));
|
|
37670
38993
|
}
|
|
37671
38994
|
} catch (error) {
|
|
@@ -37677,6 +39000,7 @@ function attachServeChild(child, setState, setStartupError, onExit) {
|
|
|
37677
39000
|
child.stderr.on("data", (chunk) => {
|
|
37678
39001
|
const text = String(chunk).trim();
|
|
37679
39002
|
if (text) {
|
|
39003
|
+
stderrChunks.push(text);
|
|
37680
39004
|
setState((current) => ({
|
|
37681
39005
|
...current,
|
|
37682
39006
|
logs: [...current.logs, { type: "stderr", message: text }].slice(-200)
|
|
@@ -37684,23 +39008,37 @@ function attachServeChild(child, setState, setStartupError, onExit) {
|
|
|
37684
39008
|
}
|
|
37685
39009
|
});
|
|
37686
39010
|
child.on("error", (error) => setStartupError(errorMessage2(error)));
|
|
37687
|
-
child.on("exit",
|
|
39011
|
+
child.on("exit", (code, signal) => {
|
|
39012
|
+
try {
|
|
39013
|
+
logStore?.compact();
|
|
39014
|
+
} catch {
|
|
39015
|
+
}
|
|
39016
|
+
const message = serveProcessExitMessage({ stderr: stderrChunks.join("\n"), code, signal });
|
|
39017
|
+
if (message) {
|
|
39018
|
+
setStartupError(message);
|
|
39019
|
+
}
|
|
39020
|
+
onExit({ code, signal, message });
|
|
39021
|
+
});
|
|
37688
39022
|
}
|
|
37689
39023
|
function helpText() {
|
|
37690
39024
|
return [
|
|
37691
|
-
"Vendian CLI",
|
|
37692
39025
|
"",
|
|
37693
|
-
|
|
37694
|
-
"
|
|
37695
|
-
"
|
|
37696
|
-
"
|
|
37697
|
-
"
|
|
37698
|
-
"
|
|
37699
|
-
|
|
37700
|
-
"
|
|
39026
|
+
` ${fig.arrowUp} VENDIAN CLI v${CLI_VERSION}`,
|
|
39027
|
+
"",
|
|
39028
|
+
" Usage:",
|
|
39029
|
+
" vendian Open the interactive shell",
|
|
39030
|
+
" vendian login Sign in and prepare the local runtime",
|
|
39031
|
+
" vendian doctor Check local bootstrap health",
|
|
39032
|
+
" vendian update Update the managed runtime",
|
|
39033
|
+
" vendian init Write SDK agent docs into a workspace",
|
|
39034
|
+
' vendian create "My Agent" Scaffold a new agent from templates',
|
|
39035
|
+
" vendian <command> Run a managed Python SDK/cloud command",
|
|
39036
|
+
"",
|
|
39037
|
+
" Examples:",
|
|
39038
|
+
...COMMANDS.map((command) => ` ${command}`),
|
|
37701
39039
|
"",
|
|
37702
|
-
|
|
37703
|
-
|
|
39040
|
+
` Run ${fig.arrowRight} vendian ${fig.arrowRight} to open the interactive TUI`,
|
|
39041
|
+
""
|
|
37704
39042
|
].join("\n");
|
|
37705
39043
|
}
|
|
37706
39044
|
function credentialLabel(agent) {
|