@vendian/cli 0.0.9 → 0.0.10
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 +1020 -137
- 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;
|
|
@@ -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,14 +36720,19 @@ 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
|
}
|
|
@@ -36725,16 +36741,12 @@ function maybeAutoUpdateManagedEnv({ env: env3 = process.env, platform: platform
|
|
|
36725
36741
|
import fs11 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.10" : 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,9 @@ function initialServeState() {
|
|
|
37047
37092
|
retry: null,
|
|
37048
37093
|
errors: [],
|
|
37049
37094
|
logs: [],
|
|
37095
|
+
agentLogs: {},
|
|
37096
|
+
// per-agent logs keyed by relativePath
|
|
37097
|
+
newAgents: [],
|
|
37050
37098
|
stopped: false,
|
|
37051
37099
|
jobsRun: 0
|
|
37052
37100
|
};
|
|
@@ -37062,6 +37110,19 @@ function parseServeEventLine(line) {
|
|
|
37062
37110
|
}
|
|
37063
37111
|
return parsed;
|
|
37064
37112
|
}
|
|
37113
|
+
function serveProcessExitMessage({ stderr = "", code = 0, signal = "" } = {}) {
|
|
37114
|
+
const text = String(stderr || "");
|
|
37115
|
+
if (/unrecognized arguments:\s*--event-stream/i.test(text)) {
|
|
37116
|
+
return "Managed Vendian runtime is too old for the local serve dashboard. Run `vendian update`, then start Serve Agents again.";
|
|
37117
|
+
}
|
|
37118
|
+
if (code && code !== 0) {
|
|
37119
|
+
return `Local serve exited with code ${code}. Toggle details for stderr.`;
|
|
37120
|
+
}
|
|
37121
|
+
if (signal && signal !== "SIGINT" && signal !== "SIGTERM") {
|
|
37122
|
+
return `Local serve exited from ${signal}. Toggle details for stderr.`;
|
|
37123
|
+
}
|
|
37124
|
+
return "";
|
|
37125
|
+
}
|
|
37065
37126
|
function applyServeEvent(state, event) {
|
|
37066
37127
|
if (!event || typeof event.type !== "string") {
|
|
37067
37128
|
return state;
|
|
@@ -37093,10 +37154,13 @@ function applyServeEvent(state, event) {
|
|
|
37093
37154
|
};
|
|
37094
37155
|
}
|
|
37095
37156
|
if (event.type === "inventory_synced") {
|
|
37157
|
+
const agents = Array.isArray(event.agents) ? event.agents : state.agents;
|
|
37158
|
+
const newAgents = state.agents.length > 0 ? findNewAgents(state.agents, agents) : [];
|
|
37096
37159
|
return {
|
|
37097
37160
|
...next,
|
|
37098
|
-
agents
|
|
37099
|
-
|
|
37161
|
+
agents,
|
|
37162
|
+
newAgents,
|
|
37163
|
+
activity: newAgents.length ? `${newAgents.length} new agent${newAgents.length === 1 ? "" : "s"} synced` : `Inventory synced (${Number(event.agentCount ?? agents.length ?? 0)} agent(s))`
|
|
37100
37164
|
};
|
|
37101
37165
|
}
|
|
37102
37166
|
if (event.type === "job_started") {
|
|
@@ -37140,6 +37204,12 @@ function applyServeEvent(state, event) {
|
|
|
37140
37204
|
jobsRun: Number(event.jobsRun ?? state.jobsRun)
|
|
37141
37205
|
};
|
|
37142
37206
|
}
|
|
37207
|
+
if (event.type === "run_log") {
|
|
37208
|
+
return {
|
|
37209
|
+
...next,
|
|
37210
|
+
agentLogs: appendAgentLog(state.agentLogs, event)
|
|
37211
|
+
};
|
|
37212
|
+
}
|
|
37143
37213
|
return next;
|
|
37144
37214
|
}
|
|
37145
37215
|
function agentSummary(agents = []) {
|
|
@@ -37161,9 +37231,45 @@ function agentSummary(agents = []) {
|
|
|
37161
37231
|
function appendLog(logs, event) {
|
|
37162
37232
|
return [...logs, event].slice(-200);
|
|
37163
37233
|
}
|
|
37234
|
+
function appendAgentLog(agentLogs, event) {
|
|
37235
|
+
const key = stringValue(event.relativePath || ".");
|
|
37236
|
+
const existing = agentLogs[key] || [];
|
|
37237
|
+
const entry = {
|
|
37238
|
+
timestamp: event.timestamp || (/* @__PURE__ */ new Date()).toISOString(),
|
|
37239
|
+
runId: stringValue(event.runId),
|
|
37240
|
+
eventType: stringValue(event.eventType),
|
|
37241
|
+
level: stringValue(event.level || "info"),
|
|
37242
|
+
message: stringValue(event.message),
|
|
37243
|
+
stepId: event.stepId ? stringValue(event.stepId) : null,
|
|
37244
|
+
current: event.current ?? null,
|
|
37245
|
+
total: event.total ?? null,
|
|
37246
|
+
success: event.success ?? null,
|
|
37247
|
+
error: event.error ?? null
|
|
37248
|
+
};
|
|
37249
|
+
return {
|
|
37250
|
+
...agentLogs,
|
|
37251
|
+
[key]: [...existing, entry].slice(-100)
|
|
37252
|
+
};
|
|
37253
|
+
}
|
|
37254
|
+
function agentLogEntries(agentLogs, relativePath) {
|
|
37255
|
+
return (agentLogs || {})[relativePath] || [];
|
|
37256
|
+
}
|
|
37164
37257
|
function appendError(errors, scope, message) {
|
|
37165
37258
|
return [...errors, { scope, message: stringValue(message) }].slice(-20);
|
|
37166
37259
|
}
|
|
37260
|
+
function findNewAgents(previous, next) {
|
|
37261
|
+
const seen = new Set(previous.map(agentKey).filter(Boolean));
|
|
37262
|
+
return next.filter((agent) => {
|
|
37263
|
+
const key = agentKey(agent);
|
|
37264
|
+
return key && !seen.has(key);
|
|
37265
|
+
}).slice(0, 8);
|
|
37266
|
+
}
|
|
37267
|
+
function agentKey(agent) {
|
|
37268
|
+
if (!agent || typeof agent !== "object") {
|
|
37269
|
+
return "";
|
|
37270
|
+
}
|
|
37271
|
+
return stringValue(agent.localAgentId || agent.relativePath || agent.path || agent.manifestName || agent.id);
|
|
37272
|
+
}
|
|
37167
37273
|
function agentLabel(event) {
|
|
37168
37274
|
return stringValue(event.relativePath || event.path || ".");
|
|
37169
37275
|
}
|
|
@@ -37182,27 +37288,152 @@ function formatSeconds(value) {
|
|
|
37182
37288
|
import { spawn as spawn2 } from "node:child_process";
|
|
37183
37289
|
async function spawnLocalServeEventStream({
|
|
37184
37290
|
agentsDir = "./agents",
|
|
37291
|
+
collectionId = "",
|
|
37185
37292
|
env: env3 = process.env,
|
|
37186
37293
|
platform: platform2 = process.platform
|
|
37187
37294
|
} = {}) {
|
|
37188
|
-
const invocation = await preparePythonVendianInvocation(
|
|
37295
|
+
const invocation = await preparePythonVendianInvocation(buildLocalServeEventStreamArgs({ agentsDir, collectionId }), { env: env3, platform: platform2 });
|
|
37296
|
+
return spawn2(invocation.command, invocation.args, {
|
|
37297
|
+
env: invocation.env,
|
|
37298
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
37299
|
+
shell: false
|
|
37300
|
+
});
|
|
37301
|
+
}
|
|
37302
|
+
function buildLocalServeEventStreamArgs({ agentsDir = "./agents", collectionId = "" } = {}) {
|
|
37303
|
+
const args = [
|
|
37189
37304
|
"cloud",
|
|
37190
37305
|
"local",
|
|
37191
37306
|
"serve",
|
|
37192
37307
|
"--agents-dir",
|
|
37193
37308
|
agentsDir || "./agents",
|
|
37194
37309
|
"--event-stream"
|
|
37195
|
-
]
|
|
37196
|
-
|
|
37197
|
-
|
|
37198
|
-
|
|
37199
|
-
|
|
37200
|
-
|
|
37310
|
+
];
|
|
37311
|
+
if (collectionId) {
|
|
37312
|
+
args.push("--collection-id", collectionId);
|
|
37313
|
+
}
|
|
37314
|
+
return args;
|
|
37315
|
+
}
|
|
37316
|
+
|
|
37317
|
+
// src/workspaces.js
|
|
37318
|
+
async function listCloudWorkspaces({
|
|
37319
|
+
env: env3 = process.env,
|
|
37320
|
+
platform: platform2 = process.platform,
|
|
37321
|
+
prepareInvocation = preparePythonVendianInvocation,
|
|
37322
|
+
run: run2 = runCapture
|
|
37323
|
+
} = {}) {
|
|
37324
|
+
const invocation = await prepareInvocation(["cloud", "collections", "list", "--json"], { env: env3, platform: platform2 });
|
|
37325
|
+
const result = run2(invocation.command, invocation.args, { env: invocation.env });
|
|
37326
|
+
if (!result.ok) {
|
|
37327
|
+
return {
|
|
37328
|
+
ok: false,
|
|
37329
|
+
workspaces: [],
|
|
37330
|
+
error: (result.stderr || result.stdout || `workspace list exited with code ${result.status}`).trim()
|
|
37331
|
+
};
|
|
37332
|
+
}
|
|
37333
|
+
try {
|
|
37334
|
+
return { ok: true, workspaces: normalizeWorkspaceList(JSON.parse(result.stdout)), error: "" };
|
|
37335
|
+
} catch (error) {
|
|
37336
|
+
const message = error && typeof error.message === "string" ? error.message : String(error);
|
|
37337
|
+
return { ok: false, workspaces: [], error: `Could not parse workspace list: ${message}` };
|
|
37338
|
+
}
|
|
37201
37339
|
}
|
|
37340
|
+
function normalizeWorkspaceList(payload) {
|
|
37341
|
+
const data = payload && typeof payload === "object" && "data" in payload ? payload.data : payload;
|
|
37342
|
+
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 : [];
|
|
37343
|
+
return raw.filter((item) => item && typeof item === "object").map((item) => ({
|
|
37344
|
+
id: stringValue2(item.id),
|
|
37345
|
+
name: stringValue2(item.name || item.slug || item.id || "Unnamed workspace"),
|
|
37346
|
+
slug: stringValue2(item.slug)
|
|
37347
|
+
})).filter((item) => item.id);
|
|
37348
|
+
}
|
|
37349
|
+
function workspaceLabel(workspace) {
|
|
37350
|
+
const name = workspace?.name || workspace?.slug || workspace?.id || "Unnamed workspace";
|
|
37351
|
+
const slug = workspace?.slug && workspace.slug !== name ? ` (${workspace.slug})` : "";
|
|
37352
|
+
return `${name}${slug}`;
|
|
37353
|
+
}
|
|
37354
|
+
function stringValue2(value) {
|
|
37355
|
+
return value == null ? "" : String(value).trim();
|
|
37356
|
+
}
|
|
37357
|
+
|
|
37358
|
+
// src/ui/theme.js
|
|
37359
|
+
var colors = {
|
|
37360
|
+
brand: "cyan",
|
|
37361
|
+
brandBold: "cyanBright",
|
|
37362
|
+
success: "green",
|
|
37363
|
+
error: "red",
|
|
37364
|
+
warning: "yellow",
|
|
37365
|
+
muted: "gray",
|
|
37366
|
+
accent: "blueBright",
|
|
37367
|
+
text: "white",
|
|
37368
|
+
dim: "gray"
|
|
37369
|
+
};
|
|
37370
|
+
var spacing = {
|
|
37371
|
+
labelWidth: 14,
|
|
37372
|
+
indent: 2
|
|
37373
|
+
};
|
|
37374
|
+
|
|
37375
|
+
// src/ui/figures.js
|
|
37376
|
+
var supportsUnicode = process.platform !== "win32" || Boolean(
|
|
37377
|
+
process.env.WT_SESSION || // Windows Terminal
|
|
37378
|
+
process.env.TERM_PROGRAM === "vscode" || // VS Code terminal
|
|
37379
|
+
process.env.TERM === "xterm-256color" || process.env.ConEmuTask || process.env.TERMINAL_EMULATOR
|
|
37380
|
+
);
|
|
37381
|
+
var unicode = {
|
|
37382
|
+
dot: "\u25CF",
|
|
37383
|
+
dotEmpty: "\u25CB",
|
|
37384
|
+
check: "\u2714",
|
|
37385
|
+
cross: "\u2716",
|
|
37386
|
+
warning: "\u26A0",
|
|
37387
|
+
arrow: "\u25B6",
|
|
37388
|
+
arrowRight: "\u203A",
|
|
37389
|
+
arrowUp: "\u25B2",
|
|
37390
|
+
dash: "\u2500",
|
|
37391
|
+
ellipsis: "\u2026",
|
|
37392
|
+
topLeft: "\u256D",
|
|
37393
|
+
topRight: "\u256E",
|
|
37394
|
+
bottomLeft: "\u2570",
|
|
37395
|
+
bottomRight: "\u256F",
|
|
37396
|
+
horizontal: "\u2500",
|
|
37397
|
+
vertical: "\u2502",
|
|
37398
|
+
teeRight: "\u251C",
|
|
37399
|
+
teeLeft: "\u2524",
|
|
37400
|
+
teeDown: "\u252C",
|
|
37401
|
+
teeUp: "\u2534",
|
|
37402
|
+
cross_join: "\u253C",
|
|
37403
|
+
bar: "\u2588",
|
|
37404
|
+
barEmpty: "\u2591"
|
|
37405
|
+
};
|
|
37406
|
+
var ascii = {
|
|
37407
|
+
dot: "*",
|
|
37408
|
+
dotEmpty: "o",
|
|
37409
|
+
check: "+",
|
|
37410
|
+
cross: "x",
|
|
37411
|
+
warning: "!",
|
|
37412
|
+
arrow: ">",
|
|
37413
|
+
arrowRight: ">",
|
|
37414
|
+
arrowUp: "^",
|
|
37415
|
+
dash: "-",
|
|
37416
|
+
ellipsis: "...",
|
|
37417
|
+
topLeft: "+",
|
|
37418
|
+
topRight: "+",
|
|
37419
|
+
bottomLeft: "+",
|
|
37420
|
+
bottomRight: "+",
|
|
37421
|
+
horizontal: "-",
|
|
37422
|
+
vertical: "|",
|
|
37423
|
+
teeRight: "+",
|
|
37424
|
+
teeLeft: "+",
|
|
37425
|
+
teeDown: "+",
|
|
37426
|
+
teeUp: "+",
|
|
37427
|
+
cross_join: "+",
|
|
37428
|
+
bar: "#",
|
|
37429
|
+
barEmpty: "."
|
|
37430
|
+
};
|
|
37431
|
+
var fig = supportsUnicode ? unicode : ascii;
|
|
37202
37432
|
|
|
37203
37433
|
// src/tui.js
|
|
37204
37434
|
var h;
|
|
37205
37435
|
var useEffect6;
|
|
37436
|
+
var useRef2;
|
|
37206
37437
|
var useState5;
|
|
37207
37438
|
var Box2;
|
|
37208
37439
|
var Text2;
|
|
@@ -37219,15 +37450,25 @@ var ENDPOINTS = [
|
|
|
37219
37450
|
{ key: "prod", label: "Production" }
|
|
37220
37451
|
];
|
|
37221
37452
|
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" }
|
|
37453
|
+
{ value: "connect", label: "Connect Endpoint", desc: "Switch between environments" },
|
|
37454
|
+
{ value: "init", label: "Initialize Docs", desc: "Set up SDK documentation workspace" },
|
|
37455
|
+
{ value: "create", label: "Create Agent", desc: "Scaffold a new agent from templates" },
|
|
37456
|
+
{ value: "serve", label: "Serve Agents", desc: "Start local development server" },
|
|
37457
|
+
{ value: "doctor", label: "Doctor", desc: "Check system health" },
|
|
37458
|
+
{ value: "update", label: "Update", desc: "Update runtime & packages" },
|
|
37459
|
+
{ value: "commands", label: "Commands", desc: "Show CLI command reference" },
|
|
37460
|
+
{ value: "exit", label: "Exit", desc: "Close interactive shell" }
|
|
37230
37461
|
];
|
|
37462
|
+
var SCREEN_TITLES = {
|
|
37463
|
+
home: "Home",
|
|
37464
|
+
connect: "Connect Endpoint",
|
|
37465
|
+
init: "Initialize Docs",
|
|
37466
|
+
create: "Create Agent",
|
|
37467
|
+
serve: "Serve Agents",
|
|
37468
|
+
doctor: "Doctor",
|
|
37469
|
+
update: "Update",
|
|
37470
|
+
commands: "Commands"
|
|
37471
|
+
};
|
|
37231
37472
|
var COMMANDS = [
|
|
37232
37473
|
"vendian login",
|
|
37233
37474
|
"vendian init --output-dir ./agents",
|
|
@@ -37247,6 +37488,7 @@ async function runTui({ env: env3 = process.env, platform: platform2 = process.p
|
|
|
37247
37488
|
`);
|
|
37248
37489
|
return;
|
|
37249
37490
|
}
|
|
37491
|
+
await refreshInteractiveManagedRuntime({ env: env3, platform: platform2, output });
|
|
37250
37492
|
await loadInkRuntime();
|
|
37251
37493
|
const app = renderInk(h(VendianShell, { env: env3, platform: platform2, input, output }), {
|
|
37252
37494
|
stdin: input,
|
|
@@ -37255,6 +37497,25 @@ async function runTui({ env: env3 = process.env, platform: platform2 = process.p
|
|
|
37255
37497
|
});
|
|
37256
37498
|
await app.waitUntilExit();
|
|
37257
37499
|
}
|
|
37500
|
+
async function refreshInteractiveManagedRuntime({
|
|
37501
|
+
env: env3 = process.env,
|
|
37502
|
+
platform: platform2 = process.platform,
|
|
37503
|
+
output = process.stderr,
|
|
37504
|
+
refreshPackageAccess = refreshPackageAccessFromCloudAuth,
|
|
37505
|
+
autoUpdate = maybeAutoUpdateManagedEnv
|
|
37506
|
+
} = {}) {
|
|
37507
|
+
if (env3.VENDIAN_SKIP_AUTO_UPDATE === "1") {
|
|
37508
|
+
return false;
|
|
37509
|
+
}
|
|
37510
|
+
try {
|
|
37511
|
+
await refreshPackageAccess({ env: env3, platform: platform2 });
|
|
37512
|
+
} catch (error) {
|
|
37513
|
+
const message = errorMessage2(error);
|
|
37514
|
+
output.write(`[vendian] Package access refresh failed; continuing with installed runtime. ${message}
|
|
37515
|
+
`);
|
|
37516
|
+
}
|
|
37517
|
+
return autoUpdate({ env: env3, platform: platform2, force: true });
|
|
37518
|
+
}
|
|
37258
37519
|
async function loadInkRuntime() {
|
|
37259
37520
|
if (h) {
|
|
37260
37521
|
return;
|
|
@@ -37268,6 +37529,7 @@ async function loadInkRuntime() {
|
|
|
37268
37529
|
]);
|
|
37269
37530
|
h = reactModule.default.createElement;
|
|
37270
37531
|
useEffect6 = reactModule.useEffect;
|
|
37532
|
+
useRef2 = reactModule.useRef;
|
|
37271
37533
|
useState5 = reactModule.useState;
|
|
37272
37534
|
Box2 = inkModule.Box;
|
|
37273
37535
|
Text2 = inkModule.Text;
|
|
@@ -37278,6 +37540,20 @@ async function loadInkRuntime() {
|
|
|
37278
37540
|
TextInput2 = textInputModule.default;
|
|
37279
37541
|
Spinner2 = spinnerModule.default;
|
|
37280
37542
|
}
|
|
37543
|
+
function endpointRows({ env: env3 = process.env, platform: platform2 = process.platform } = {}) {
|
|
37544
|
+
return ENDPOINTS.map((endpoint) => {
|
|
37545
|
+
const status = cloudAuthStatus({ backend: endpoint.key, env: env3, platform: platform2 });
|
|
37546
|
+
const active = status.activeApiUrl === status.apiUrl;
|
|
37547
|
+
return {
|
|
37548
|
+
key: endpoint.key,
|
|
37549
|
+
label: endpoint.label,
|
|
37550
|
+
apiUrl: status.apiUrl,
|
|
37551
|
+
active,
|
|
37552
|
+
status: status.authenticated ? active ? "connected" : "signed in" : "not signed in",
|
|
37553
|
+
detail: status.authenticated ? status.email || status.apiUrl : status.apiUrl
|
|
37554
|
+
};
|
|
37555
|
+
});
|
|
37556
|
+
}
|
|
37281
37557
|
function runtimeSummary({ env: env3 = process.env, platform: platform2 = process.platform, now = Date.now() } = {}) {
|
|
37282
37558
|
const config = loadConfig(env3, platform2);
|
|
37283
37559
|
const venvPath = managedVenvPath(env3, platform2);
|
|
@@ -37298,37 +37574,92 @@ function packageAccessSummary({ env: env3 = process.env, platform: platform2 = p
|
|
|
37298
37574
|
source: registry.tokenSource || "local config"
|
|
37299
37575
|
};
|
|
37300
37576
|
}
|
|
37577
|
+
function isCtrlCInput(input = "", key = {}) {
|
|
37578
|
+
return input === "" || input === "" || Boolean(key?.ctrl && (key.name === "c" || input === "c"));
|
|
37579
|
+
}
|
|
37301
37580
|
function VendianShell({ env: env3, platform: platform2, input, output }) {
|
|
37302
37581
|
const app = useApp2();
|
|
37303
37582
|
const [screen, setScreen] = useState5("home");
|
|
37304
37583
|
const [serveState, setServeState] = useState5(null);
|
|
37305
|
-
|
|
37306
|
-
|
|
37584
|
+
const [exitArmed, setExitArmed] = useState5(false);
|
|
37585
|
+
const exitTimer = useRef2(null);
|
|
37586
|
+
const lastInterruptAt = useRef2(0);
|
|
37587
|
+
function armExit() {
|
|
37588
|
+
if (exitArmed) {
|
|
37307
37589
|
app.exit();
|
|
37590
|
+
return;
|
|
37591
|
+
}
|
|
37592
|
+
setExitArmed(true);
|
|
37593
|
+
if (exitTimer.current) {
|
|
37594
|
+
clearTimeout(exitTimer.current);
|
|
37595
|
+
}
|
|
37596
|
+
exitTimer.current = setTimeout(() => setExitArmed(false), 1500);
|
|
37597
|
+
}
|
|
37598
|
+
function handleInterrupt() {
|
|
37599
|
+
const now = Date.now();
|
|
37600
|
+
if (now - lastInterruptAt.current < 75) {
|
|
37601
|
+
return;
|
|
37602
|
+
}
|
|
37603
|
+
lastInterruptAt.current = now;
|
|
37604
|
+
if (screen === "serve") {
|
|
37605
|
+
return;
|
|
37606
|
+
}
|
|
37607
|
+
armExit();
|
|
37608
|
+
}
|
|
37609
|
+
useEffect6(() => () => {
|
|
37610
|
+
if (exitTimer.current) {
|
|
37611
|
+
clearTimeout(exitTimer.current);
|
|
37612
|
+
}
|
|
37613
|
+
}, []);
|
|
37614
|
+
useEffect6(() => {
|
|
37615
|
+
const onData = (chunk) => {
|
|
37616
|
+
if (isCtrlCInput(String(chunk || ""))) {
|
|
37617
|
+
handleInterrupt();
|
|
37618
|
+
}
|
|
37619
|
+
};
|
|
37620
|
+
input?.on?.("data", onData);
|
|
37621
|
+
process.on("SIGINT", handleInterrupt);
|
|
37622
|
+
return () => {
|
|
37623
|
+
input?.off?.("data", onData);
|
|
37624
|
+
process.off("SIGINT", handleInterrupt);
|
|
37625
|
+
};
|
|
37626
|
+
}, [input, screen, exitArmed]);
|
|
37627
|
+
useInput2((typedInput, key) => {
|
|
37628
|
+
if (isCtrlCInput(typedInput, key)) {
|
|
37629
|
+
handleInterrupt();
|
|
37308
37630
|
}
|
|
37309
37631
|
});
|
|
37310
37632
|
const goHome = () => setScreen("home");
|
|
37633
|
+
const breadcrumb = screen !== "home" ? ["Home", SCREEN_TITLES[screen] || screen] : ["Home"];
|
|
37311
37634
|
return h(
|
|
37312
37635
|
Box2,
|
|
37313
37636
|
{ flexDirection: "column" },
|
|
37314
|
-
h(Header, { env: env3, platform: platform2, serveState }),
|
|
37637
|
+
h(Header, { env: env3, platform: platform2, serveState, screen }),
|
|
37638
|
+
h(
|
|
37639
|
+
Text2,
|
|
37640
|
+
{ color: colors.muted },
|
|
37641
|
+
breadcrumb.map(
|
|
37642
|
+
(part, i) => i < breadcrumb.length - 1 ? `${part} ${fig.arrowRight} ` : part
|
|
37643
|
+
).join("")
|
|
37644
|
+
),
|
|
37645
|
+
h(Text2, null, ""),
|
|
37315
37646
|
screen === "home" && h(HomeScreen, { onSelect: (value) => value === "exit" ? app.exit() : setScreen(value) }),
|
|
37316
37647
|
screen === "connect" && h(ConnectScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37317
37648
|
screen === "init" && h(InitScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37318
37649
|
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 }),
|
|
37650
|
+
screen === "serve" && h(ServeScreen, { env: env3, platform: platform2, input, output, onBack: goHome, onState: setServeState, onExitApp: app.exit }),
|
|
37320
37651
|
screen === "doctor" && h(DoctorScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37321
37652
|
screen === "update" && h(UpdateScreen, { env: env3, platform: platform2, onBack: goHome }),
|
|
37322
|
-
screen === "commands" && h(CommandsScreen, { onBack: goHome })
|
|
37653
|
+
screen === "commands" && h(CommandsScreen, { onBack: goHome }),
|
|
37654
|
+
exitArmed && screen !== "serve" && h(Text2, { color: colors.warning, bold: true }, " Press Ctrl+C again to exit.")
|
|
37323
37655
|
);
|
|
37324
37656
|
}
|
|
37325
|
-
function Header({ env: env3, platform: platform2, serveState }) {
|
|
37657
|
+
function Header({ env: env3, platform: platform2, serveState, screen }) {
|
|
37326
37658
|
const active = activeCloudAuthStatus({ env: env3, platform: platform2 });
|
|
37327
37659
|
const runtime = runtimeSummary({ env: env3, platform: platform2 });
|
|
37328
37660
|
const [npmUpdate, setNpmUpdate] = useState5(() => npmPackageUpdateSummary({ config: loadConfig(env3, platform2) }));
|
|
37329
37661
|
const [npmCheckStarted, setNpmCheckStarted] = useState5(false);
|
|
37330
37662
|
const pkg = packageAccessSummary({ env: env3, platform: platform2 });
|
|
37331
|
-
const daemon = serveState?.daemonId ? `Daemon ${serveState.daemonId} | ${serveState.activity}` : "Daemon idle";
|
|
37332
37663
|
useEffect6(() => {
|
|
37333
37664
|
let cancelled = false;
|
|
37334
37665
|
if (!npmUpdate.stale || npmCheckStarted) {
|
|
@@ -37344,29 +37675,111 @@ function Header({ env: env3, platform: platform2, serveState }) {
|
|
|
37344
37675
|
cancelled = true;
|
|
37345
37676
|
};
|
|
37346
37677
|
}, [env3, platform2, npmCheckStarted, npmUpdate.stale]);
|
|
37678
|
+
const connStatus = active.authenticated ? "ok" : "error";
|
|
37679
|
+
const connValue = active.authenticated ? `${active.email || "Authenticated"} ${fig.dash} ${active.apiUrl}` : "Not connected \u2014 run vendian login";
|
|
37680
|
+
const rtStatus = runtime.installed ? "ok" : "error";
|
|
37681
|
+
const rtValue = runtime.installed ? "Ready" : "Missing \u2014 run vendian login";
|
|
37682
|
+
const pkgStatus = pkg.configured ? "ok" : "warning";
|
|
37683
|
+
const pkgValue = pkg.configured ? `Configured (${pkg.source})` : "Missing";
|
|
37684
|
+
const updValue = updateLabel({ runtime, npmUpdate });
|
|
37685
|
+
const updStatus = updValue.includes("available") ? "warning" : "ok";
|
|
37686
|
+
const w = Math.min(process.stdout.columns || 80, 90);
|
|
37687
|
+
const inner = w - 2;
|
|
37688
|
+
const titleLeft = `${fig.vertical} ${fig.arrowUp} VENDIAN`;
|
|
37689
|
+
const titleRight = `v${CLI_VERSION} ${fig.vertical}`;
|
|
37690
|
+
const titlePad = Math.max(0, inner - titleLeft.length - titleRight.length + 2);
|
|
37347
37691
|
return h(
|
|
37348
37692
|
Box2,
|
|
37349
37693
|
{ flexDirection: "column", marginBottom: 1 },
|
|
37350
|
-
h(Text2, {
|
|
37351
|
-
h(
|
|
37352
|
-
|
|
37353
|
-
|
|
37694
|
+
h(Text2, { color: colors.muted }, `${fig.topLeft}${fig.horizontal.repeat(inner)}${fig.topRight}`),
|
|
37695
|
+
h(
|
|
37696
|
+
Text2,
|
|
37697
|
+
null,
|
|
37698
|
+
h(Text2, { color: colors.muted }, fig.vertical),
|
|
37699
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.arrowUp} VENDIAN`),
|
|
37700
|
+
h(Text2, null, " ".repeat(titlePad)),
|
|
37701
|
+
h(Text2, { color: colors.muted }, `v${CLI_VERSION} `),
|
|
37702
|
+
h(Text2, { color: colors.muted }, fig.vertical)
|
|
37703
|
+
),
|
|
37704
|
+
h(Text2, { color: colors.muted }, `${fig.teeRight}${fig.horizontal.repeat(inner)}${fig.teeLeft}`),
|
|
37705
|
+
h(StatusRow, { status: connStatus, label: "Endpoint", value: connValue, width: inner }),
|
|
37706
|
+
h(StatusRow, { status: rtStatus, label: "Runtime", value: rtValue, width: inner }),
|
|
37707
|
+
h(StatusRow, { status: pkgStatus, label: "Packages", value: pkgValue, width: inner }),
|
|
37708
|
+
h(StatusRow, { status: updStatus, label: "Updates", value: updValue, width: inner }),
|
|
37709
|
+
serveState?.daemonId && h(StatusRow, {
|
|
37710
|
+
status: serveState.connected ? "ok" : "warning",
|
|
37711
|
+
label: "Daemon",
|
|
37712
|
+
value: serveState.activity || "Running",
|
|
37713
|
+
width: inner
|
|
37714
|
+
}),
|
|
37715
|
+
h(Text2, { color: colors.muted }, `${fig.bottomLeft}${fig.horizontal.repeat(inner)}${fig.bottomRight}`)
|
|
37716
|
+
);
|
|
37717
|
+
}
|
|
37718
|
+
function StatusRow({ status, label, value, width }) {
|
|
37719
|
+
const dotColor = status === "ok" ? colors.success : status === "warning" ? colors.warning : colors.error;
|
|
37720
|
+
const dot = status === "ok" ? fig.dot : status === "warning" ? fig.dot : fig.dot;
|
|
37721
|
+
const paddedLabel = String(label).padEnd(spacing.labelWidth);
|
|
37722
|
+
const maxVal = Math.max(0, (width || 70) - spacing.labelWidth - 6);
|
|
37723
|
+
const clipped = clip(value || "", maxVal);
|
|
37724
|
+
return h(
|
|
37725
|
+
Text2,
|
|
37726
|
+
null,
|
|
37727
|
+
h(Text2, { color: colors.muted }, `${fig.vertical} `),
|
|
37728
|
+
h(Text2, { color: dotColor }, `${dot} `),
|
|
37729
|
+
h(Text2, { bold: true }, paddedLabel),
|
|
37730
|
+
h(Text2, null, clipped),
|
|
37731
|
+
h(Text2, { color: colors.muted }, ` ${fig.vertical}`)
|
|
37354
37732
|
);
|
|
37355
37733
|
}
|
|
37356
37734
|
function HomeScreen({ onSelect }) {
|
|
37735
|
+
const [activeIndex, setActiveIndex] = useState5(0);
|
|
37736
|
+
useInput2((input, key) => {
|
|
37737
|
+
if (key.upArrow) {
|
|
37738
|
+
setActiveIndex((i) => (i - 1 + ACTIONS.length) % ACTIONS.length);
|
|
37739
|
+
} else if (key.downArrow) {
|
|
37740
|
+
setActiveIndex((i) => (i + 1) % ACTIONS.length);
|
|
37741
|
+
} else if (key.return) {
|
|
37742
|
+
onSelect(ACTIONS[activeIndex].value);
|
|
37743
|
+
}
|
|
37744
|
+
});
|
|
37357
37745
|
return h(
|
|
37358
37746
|
Box2,
|
|
37359
37747
|
{ flexDirection: "column" },
|
|
37360
|
-
|
|
37361
|
-
|
|
37748
|
+
...ACTIONS.map((action, i) => {
|
|
37749
|
+
const isActive = i === activeIndex;
|
|
37750
|
+
const isSeparator = action.value === "doctor";
|
|
37751
|
+
return h(
|
|
37752
|
+
Box2,
|
|
37753
|
+
{ key: action.value, flexDirection: "column" },
|
|
37754
|
+
isSeparator && h(Text2, { color: colors.muted }, ` ${fig.horizontal.repeat(40)}`),
|
|
37755
|
+
h(
|
|
37756
|
+
Text2,
|
|
37757
|
+
null,
|
|
37758
|
+
h(Text2, { color: isActive ? colors.accent : colors.muted }, isActive ? ` ${fig.arrow} ` : " "),
|
|
37759
|
+
h(Text2, { bold: isActive, color: isActive ? colors.text : colors.muted }, action.label.padEnd(22)),
|
|
37760
|
+
h(Text2, { color: colors.dim }, action.desc)
|
|
37761
|
+
)
|
|
37762
|
+
);
|
|
37763
|
+
}),
|
|
37764
|
+
h(Text2, null, ""),
|
|
37765
|
+
h(FooterBar, { items: [
|
|
37766
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
37767
|
+
{ key: "\u23CE", label: "Select" },
|
|
37768
|
+
{ key: "^c ^c", label: "Exit" }
|
|
37769
|
+
] })
|
|
37362
37770
|
);
|
|
37363
37771
|
}
|
|
37364
37772
|
function ConnectScreen({ env: env3, platform: platform2, onBack }) {
|
|
37365
37773
|
const [mode, setMode] = useState5("select");
|
|
37366
37774
|
const [apiUrl, setApiUrl] = useState5("");
|
|
37367
37775
|
const [status, setStatus] = useState5("");
|
|
37776
|
+
const rows = endpointRows({ env: env3, platform: platform2 });
|
|
37368
37777
|
const items = [
|
|
37369
|
-
...ENDPOINTS.map((endpoint) =>
|
|
37778
|
+
...ENDPOINTS.map((endpoint) => {
|
|
37779
|
+
const row = rows.find((r) => r.key === endpoint.key);
|
|
37780
|
+
const statusLabel = row ? row.active ? "\u25CF Connected" : row.status : "";
|
|
37781
|
+
return { label: `${endpoint.label.padEnd(12)} ${BACKEND_TARGETS[endpoint.key]} ${statusLabel}`, value: endpoint.key };
|
|
37782
|
+
}),
|
|
37370
37783
|
{ label: "Custom API URL", value: "custom" },
|
|
37371
37784
|
{ label: "Back", value: "back" }
|
|
37372
37785
|
];
|
|
@@ -37379,41 +37792,47 @@ function ConnectScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37379
37792
|
setMode("custom");
|
|
37380
37793
|
return;
|
|
37381
37794
|
}
|
|
37382
|
-
setStatus(`Connecting ${value}
|
|
37795
|
+
setStatus(`Connecting to ${value}...`);
|
|
37383
37796
|
await setup({ backend: value, forceAuth: true, env: env3, platform: platform2 });
|
|
37384
|
-
setStatus(
|
|
37797
|
+
setStatus(`${fig.check} Connected`);
|
|
37385
37798
|
}
|
|
37386
37799
|
if (mode === "custom") {
|
|
37387
37800
|
return h(
|
|
37388
37801
|
Box2,
|
|
37389
37802
|
{ flexDirection: "column" },
|
|
37390
|
-
h(Text2, { bold: true }, "
|
|
37803
|
+
h(Text2, { bold: true }, " Enter custom API URL:"),
|
|
37804
|
+
h(Text2, null, ""),
|
|
37391
37805
|
h(TextInput2, {
|
|
37392
37806
|
value: apiUrl,
|
|
37393
37807
|
placeholder: "https://api.example.test",
|
|
37394
37808
|
onChange: setApiUrl,
|
|
37395
37809
|
onSubmit: async (value) => {
|
|
37396
37810
|
if (!value) return;
|
|
37397
|
-
setStatus("Connecting
|
|
37811
|
+
setStatus("Connecting...");
|
|
37398
37812
|
await setup({ apiUrl: value, forceAuth: true, env: env3, platform: platform2 });
|
|
37399
|
-
setStatus(
|
|
37813
|
+
setStatus(`${fig.check} Connected`);
|
|
37400
37814
|
}
|
|
37401
37815
|
}),
|
|
37402
|
-
h(Text2,
|
|
37816
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
37817
|
+
h(Text2, null, ""),
|
|
37818
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Submit" }, { key: "esc", label: "Back" }] }),
|
|
37403
37819
|
h(BackHint, { onBack })
|
|
37404
37820
|
);
|
|
37405
37821
|
}
|
|
37406
37822
|
return h(
|
|
37407
37823
|
Box2,
|
|
37408
37824
|
{ flexDirection: "column" },
|
|
37409
|
-
h(Text2, { bold: true }, "
|
|
37825
|
+
h(Text2, { bold: true }, " Select environment:"),
|
|
37826
|
+
h(Text2, null, ""),
|
|
37410
37827
|
h(SelectInput2, { items, onSelect: (item) => connect(item.value) }),
|
|
37411
|
-
status && h(Text2,
|
|
37828
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
37829
|
+
h(Text2, null, ""),
|
|
37830
|
+
h(FooterBar, { items: [{ key: "\u2191\u2193", label: "Navigate" }, { key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] })
|
|
37412
37831
|
);
|
|
37413
37832
|
}
|
|
37414
37833
|
function InitScreen({ env: env3, platform: platform2, onBack }) {
|
|
37415
37834
|
return h(CommandPromptScreen, {
|
|
37416
|
-
title: "Initialize Docs",
|
|
37835
|
+
title: " Initialize Docs",
|
|
37417
37836
|
label: "Workspace directory",
|
|
37418
37837
|
initialValue: ".",
|
|
37419
37838
|
onBack,
|
|
@@ -37453,53 +37872,165 @@ function CreateScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37453
37872
|
h(BackHint, { onBack })
|
|
37454
37873
|
);
|
|
37455
37874
|
}
|
|
37456
|
-
function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
37875
|
+
function ServeScreen({ env: env3, platform: platform2, input, onBack, onState, onExitApp }) {
|
|
37457
37876
|
const [agentDirCandidates] = useState5(() => findAgentDirectoryCandidates());
|
|
37458
37877
|
const [agentsDir, setAgentsDir] = useState5(() => defaultAgentsDir(agentDirCandidates));
|
|
37459
37878
|
const [selectingDir, setSelectingDir] = useState5(() => agentDirCandidates.length > 0);
|
|
37879
|
+
const [workspaceChoices, setWorkspaceChoices] = useState5([]);
|
|
37880
|
+
const [pendingAgentsDir, setPendingAgentsDir] = useState5("");
|
|
37881
|
+
const [loadingWorkspaces, setLoadingWorkspaces] = useState5(false);
|
|
37460
37882
|
const [started, setStarted] = useState5(false);
|
|
37461
37883
|
const [state, setState] = useState5(initialServeState());
|
|
37462
37884
|
const [child, setChild] = useState5(null);
|
|
37463
|
-
const [
|
|
37885
|
+
const [logMode, setLogMode] = useState5(null);
|
|
37464
37886
|
const [confirmExit, setConfirmExit] = useState5(false);
|
|
37887
|
+
const [exitArmed, setExitArmed] = useState5(false);
|
|
37465
37888
|
const [startupError, setStartupError] = useState5("");
|
|
37889
|
+
const exitTimer = useRef2(null);
|
|
37890
|
+
const lastInterruptAt = useRef2(0);
|
|
37466
37891
|
useEffect6(() => {
|
|
37467
37892
|
onState(state);
|
|
37468
37893
|
}, [state, onState]);
|
|
37469
|
-
|
|
37894
|
+
useEffect6(() => () => {
|
|
37895
|
+
if (exitTimer.current) {
|
|
37896
|
+
clearTimeout(exitTimer.current);
|
|
37897
|
+
}
|
|
37898
|
+
}, []);
|
|
37899
|
+
function armExit() {
|
|
37900
|
+
if (exitArmed) {
|
|
37901
|
+
child?.kill("SIGINT");
|
|
37902
|
+
onState(null);
|
|
37903
|
+
onExitApp();
|
|
37904
|
+
return;
|
|
37905
|
+
}
|
|
37906
|
+
setExitArmed(true);
|
|
37907
|
+
setConfirmExit(false);
|
|
37908
|
+
if (exitTimer.current) {
|
|
37909
|
+
clearTimeout(exitTimer.current);
|
|
37910
|
+
}
|
|
37911
|
+
exitTimer.current = setTimeout(() => setExitArmed(false), 1500);
|
|
37912
|
+
}
|
|
37913
|
+
function handleInterrupt() {
|
|
37914
|
+
const now = Date.now();
|
|
37915
|
+
if (now - lastInterruptAt.current < 75) {
|
|
37916
|
+
return;
|
|
37917
|
+
}
|
|
37918
|
+
lastInterruptAt.current = now;
|
|
37919
|
+
armExit();
|
|
37920
|
+
}
|
|
37921
|
+
useEffect6(() => {
|
|
37922
|
+
const onData = (chunk) => {
|
|
37923
|
+
if (isCtrlCInput(String(chunk || ""))) {
|
|
37924
|
+
handleInterrupt();
|
|
37925
|
+
}
|
|
37926
|
+
};
|
|
37927
|
+
input?.on?.("data", onData);
|
|
37928
|
+
process.on("SIGINT", handleInterrupt);
|
|
37929
|
+
return () => {
|
|
37930
|
+
input?.off?.("data", onData);
|
|
37931
|
+
process.off("SIGINT", handleInterrupt);
|
|
37932
|
+
};
|
|
37933
|
+
}, [input, exitArmed, child]);
|
|
37934
|
+
useInput2((input2, key) => {
|
|
37935
|
+
if (isCtrlCInput(input2, key)) {
|
|
37936
|
+
handleInterrupt();
|
|
37937
|
+
return;
|
|
37938
|
+
}
|
|
37470
37939
|
if (!started) return;
|
|
37940
|
+
if (logMode !== null) {
|
|
37941
|
+
if (key.escape) {
|
|
37942
|
+
if (logMode === "picker") {
|
|
37943
|
+
setLogMode(null);
|
|
37944
|
+
} else {
|
|
37945
|
+
setLogMode("picker");
|
|
37946
|
+
}
|
|
37947
|
+
}
|
|
37948
|
+
return;
|
|
37949
|
+
}
|
|
37471
37950
|
if (confirmExit) {
|
|
37472
|
-
if (
|
|
37951
|
+
if (input2.toLowerCase() === "y" || key.return) {
|
|
37473
37952
|
child?.kill("SIGINT");
|
|
37474
37953
|
onState(null);
|
|
37475
37954
|
onBack();
|
|
37476
|
-
} else if (
|
|
37955
|
+
} else if (input2.toLowerCase() === "n" || key.escape) {
|
|
37477
37956
|
setConfirmExit(false);
|
|
37478
37957
|
}
|
|
37479
37958
|
return;
|
|
37480
37959
|
}
|
|
37481
|
-
if (
|
|
37482
|
-
|
|
37483
|
-
} else if (
|
|
37960
|
+
if (input2 === "l") {
|
|
37961
|
+
setLogMode("picker");
|
|
37962
|
+
} else if (input2 === "q") {
|
|
37484
37963
|
setConfirmExit(true);
|
|
37485
37964
|
}
|
|
37486
37965
|
});
|
|
37487
|
-
async function start(selectedAgentsDir = agentsDir) {
|
|
37966
|
+
async function start(selectedAgentsDir = agentsDir, collectionId = "") {
|
|
37488
37967
|
const serveRoot = selectedAgentsDir || "./agents";
|
|
37489
37968
|
setAgentsDir(serveRoot);
|
|
37490
37969
|
setStarted(true);
|
|
37491
37970
|
setStartupError("");
|
|
37492
37971
|
try {
|
|
37493
|
-
const nextChild = await spawnLocalServeEventStream({ agentsDir: serveRoot, env: env3, platform: platform2 });
|
|
37972
|
+
const nextChild = await spawnLocalServeEventStream({ agentsDir: serveRoot, collectionId, env: env3, platform: platform2 });
|
|
37494
37973
|
setChild(nextChild);
|
|
37495
|
-
attachServeChild(nextChild, setState, setStartupError, () => {
|
|
37496
|
-
setState((current) => current.stopped ? current : { ...current, stopped: true, activity: "Process exited" });
|
|
37974
|
+
attachServeChild(nextChild, setState, setStartupError, ({ message } = {}) => {
|
|
37975
|
+
setState((current) => current.stopped ? current : { ...current, stopped: true, activity: message ? "Runtime update required" : "Process exited" });
|
|
37497
37976
|
});
|
|
37498
37977
|
} catch (error) {
|
|
37499
37978
|
setStartupError(errorMessage2(error));
|
|
37500
37979
|
}
|
|
37501
37980
|
}
|
|
37981
|
+
async function chooseWorkspaceThenStart(selectedAgentsDir = agentsDir) {
|
|
37982
|
+
const serveRoot = selectedAgentsDir || "./agents";
|
|
37983
|
+
setAgentsDir(serveRoot);
|
|
37984
|
+
setPendingAgentsDir(serveRoot);
|
|
37985
|
+
setStartupError("");
|
|
37986
|
+
setLoadingWorkspaces(true);
|
|
37987
|
+
try {
|
|
37988
|
+
const result = await listCloudWorkspaces({ env: env3, platform: platform2 });
|
|
37989
|
+
if (!result.ok) {
|
|
37990
|
+
setStartupError(result.error || "Could not list workspaces.");
|
|
37991
|
+
return;
|
|
37992
|
+
}
|
|
37993
|
+
if (result.workspaces.length > 1) {
|
|
37994
|
+
setWorkspaceChoices(result.workspaces);
|
|
37995
|
+
return;
|
|
37996
|
+
}
|
|
37997
|
+
await start(serveRoot, result.workspaces[0]?.id || "");
|
|
37998
|
+
} catch (error) {
|
|
37999
|
+
setStartupError(errorMessage2(error));
|
|
38000
|
+
} finally {
|
|
38001
|
+
setLoadingWorkspaces(false);
|
|
38002
|
+
}
|
|
38003
|
+
}
|
|
37502
38004
|
if (!started) {
|
|
38005
|
+
if (workspaceChoices.length > 1) {
|
|
38006
|
+
return h(
|
|
38007
|
+
Box2,
|
|
38008
|
+
{ flexDirection: "column" },
|
|
38009
|
+
h(Text2, { bold: true }, "Select workspace:"),
|
|
38010
|
+
h(SelectInput2, {
|
|
38011
|
+
items: [
|
|
38012
|
+
...workspaceChoices.map((workspace) => ({
|
|
38013
|
+
label: workspaceLabel(workspace),
|
|
38014
|
+
value: workspace.id
|
|
38015
|
+
})),
|
|
38016
|
+
{ label: "Back", value: "__back__" }
|
|
38017
|
+
],
|
|
38018
|
+
onSelect: (item) => {
|
|
38019
|
+
if (item.value === "__back__") {
|
|
38020
|
+
setWorkspaceChoices([]);
|
|
38021
|
+
return;
|
|
38022
|
+
}
|
|
38023
|
+
start(pendingAgentsDir || agentsDir, item.value);
|
|
38024
|
+
}
|
|
38025
|
+
}),
|
|
38026
|
+
h(Text2, null, ""),
|
|
38027
|
+
h(FooterBar, { items: [
|
|
38028
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38029
|
+
{ key: "\u23CE", label: "Select" },
|
|
38030
|
+
{ key: "esc", label: "Back" }
|
|
38031
|
+
] })
|
|
38032
|
+
);
|
|
38033
|
+
}
|
|
37503
38034
|
const items = [
|
|
37504
38035
|
...agentDirCandidates.map((candidate) => ({
|
|
37505
38036
|
label: `${candidate.path} (${candidate.agentCount} ${candidate.agentCount === 1 ? "agent" : "agents"})`,
|
|
@@ -37511,7 +38042,7 @@ function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
|
37511
38042
|
return h(
|
|
37512
38043
|
Box2,
|
|
37513
38044
|
{ flexDirection: "column" },
|
|
37514
|
-
h(Text2, { bold: true }, "
|
|
38045
|
+
h(Text2, { bold: true }, "Select agent directory:"),
|
|
37515
38046
|
selectingDir && h(SelectInput2, {
|
|
37516
38047
|
items,
|
|
37517
38048
|
onSelect: (item) => {
|
|
@@ -37525,77 +38056,378 @@ function ServeScreen({ env: env3, platform: platform2, onBack, onState }) {
|
|
|
37525
38056
|
return;
|
|
37526
38057
|
}
|
|
37527
38058
|
setAgentsDir(item.value);
|
|
37528
|
-
|
|
38059
|
+
chooseWorkspaceThenStart(item.value);
|
|
37529
38060
|
}
|
|
37530
38061
|
}),
|
|
37531
38062
|
!selectingDir && h(TextInput2, {
|
|
37532
38063
|
value: agentsDir,
|
|
37533
38064
|
placeholder: "./agents",
|
|
37534
38065
|
onChange: setAgentsDir,
|
|
37535
|
-
onSubmit: (value) =>
|
|
38066
|
+
onSubmit: (value) => chooseWorkspaceThenStart(value)
|
|
37536
38067
|
}),
|
|
37537
|
-
h(
|
|
38068
|
+
loadingWorkspaces && h(
|
|
38069
|
+
Box2,
|
|
38070
|
+
null,
|
|
38071
|
+
h(Text2, { color: colors.brand }, " "),
|
|
38072
|
+
h(Spinner2, { type: "dots" }),
|
|
38073
|
+
h(Text2, { color: colors.brand }, " Loading workspaces")
|
|
38074
|
+
),
|
|
38075
|
+
startupError && h(Text2, { color: colors.error }, ` ${fig.cross} ${startupError}`),
|
|
38076
|
+
h(Text2, null, ""),
|
|
38077
|
+
h(FooterBar, { items: [
|
|
38078
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38079
|
+
{ key: "\u23CE", label: "Select" },
|
|
38080
|
+
{ key: "esc", label: "Back" }
|
|
38081
|
+
] })
|
|
37538
38082
|
);
|
|
37539
38083
|
}
|
|
37540
38084
|
const summary = agentSummary(state.agents);
|
|
38085
|
+
if (logMode !== null) {
|
|
38086
|
+
return h(
|
|
38087
|
+
Box2,
|
|
38088
|
+
{ flexDirection: "column" },
|
|
38089
|
+
h(AgentLogViewer, {
|
|
38090
|
+
agents: state.agents,
|
|
38091
|
+
agentLogs: state.agentLogs,
|
|
38092
|
+
logMode,
|
|
38093
|
+
onSelectAgent: (path7) => setLogMode(path7),
|
|
38094
|
+
onBack: () => {
|
|
38095
|
+
if (logMode === "picker") {
|
|
38096
|
+
setLogMode(null);
|
|
38097
|
+
} else {
|
|
38098
|
+
setLogMode("picker");
|
|
38099
|
+
}
|
|
38100
|
+
}
|
|
38101
|
+
})
|
|
38102
|
+
);
|
|
38103
|
+
}
|
|
37541
38104
|
return h(
|
|
37542
38105
|
Box2,
|
|
37543
38106
|
{ flexDirection: "column" },
|
|
37544
|
-
h(Text2, {
|
|
37545
|
-
|
|
37546
|
-
|
|
38107
|
+
startupError ? h(Text2, { color: colors.error }, ` ${fig.cross} ${startupError}`) : h(
|
|
38108
|
+
Box2,
|
|
38109
|
+
null,
|
|
38110
|
+
h(Text2, { color: colors.brand }, " "),
|
|
38111
|
+
h(Spinner2, { type: "dots" }),
|
|
38112
|
+
h(Text2, { color: colors.brand }, ` ${state.activity}`)
|
|
38113
|
+
),
|
|
38114
|
+
h(Text2, null, ""),
|
|
38115
|
+
h(
|
|
38116
|
+
Text2,
|
|
38117
|
+
null,
|
|
38118
|
+
h(Text2, { color: colors.muted }, " Agents: "),
|
|
38119
|
+
h(Text2, { color: colors.success, bold: true }, `${summary.ready} ready`),
|
|
38120
|
+
summary.needsSetup > 0 && h(Text2, { color: colors.warning }, ` ${fig.dot} ${summary.needsSetup} needs setup`),
|
|
38121
|
+
summary.errors > 0 && h(Text2, { color: colors.error }, ` ${fig.dot} ${summary.errors} errors`),
|
|
38122
|
+
h(Text2, { color: colors.muted }, ` ${fig.dot} ${summary.total} total`)
|
|
38123
|
+
),
|
|
38124
|
+
h(Text2, null, ""),
|
|
38125
|
+
state.newAgents?.length > 0 && h(
|
|
38126
|
+
Text2,
|
|
38127
|
+
{ color: colors.success },
|
|
38128
|
+
` ${fig.check} New agents synced automatically: ${state.newAgents.map((agent) => agent.relativePath || agent.manifestName || agent.path || "agent").join(", ")}`
|
|
38129
|
+
),
|
|
37547
38130
|
h(AgentTable, { agents: state.agents }),
|
|
37548
|
-
state.retry && h(Text2, { color:
|
|
37549
|
-
state.errors.
|
|
37550
|
-
|
|
37551
|
-
|
|
37552
|
-
|
|
38131
|
+
state.retry && h(Text2, { color: colors.warning }, ` ${fig.warning} Retry: ${state.retry.activity} in ${Number(state.retry.delaySeconds || 0).toFixed(1)}s`),
|
|
38132
|
+
state.errors.length > 0 && h(
|
|
38133
|
+
Box2,
|
|
38134
|
+
{ flexDirection: "column", marginTop: 1 },
|
|
38135
|
+
...state.errors.slice(-3).map((item, index) => h(Text2, { key: `error-${index}`, color: colors.error }, ` ${fig.cross} ${item.scope}: ${item.message}`))
|
|
38136
|
+
),
|
|
38137
|
+
h(Text2, null, ""),
|
|
38138
|
+
confirmExit ? h(
|
|
38139
|
+
Text2,
|
|
38140
|
+
{ color: colors.warning, bold: true },
|
|
38141
|
+
" Stop local serve? ",
|
|
38142
|
+
h(Text2, { color: colors.accent }, "y"),
|
|
38143
|
+
h(Text2, { color: colors.muted }, "/"),
|
|
38144
|
+
h(Text2, { color: colors.accent }, "n")
|
|
38145
|
+
) : h(FooterBar, { items: [
|
|
38146
|
+
{ key: "l", label: "Agent logs" },
|
|
38147
|
+
{ key: "q", label: "Stop" },
|
|
38148
|
+
{ key: "^c ^c", label: "Exit" }
|
|
38149
|
+
] }),
|
|
38150
|
+
exitArmed && h(Text2, { color: colors.warning, bold: true }, " Press Ctrl+C again to exit.")
|
|
37553
38151
|
);
|
|
37554
38152
|
}
|
|
37555
38153
|
function AgentTable({ agents }) {
|
|
37556
38154
|
if (!agents.length) {
|
|
37557
|
-
return h(Text2, {
|
|
38155
|
+
return h(Text2, { color: colors.muted }, ` ${fig.dotEmpty} No agents discovered yet.`);
|
|
38156
|
+
}
|
|
38157
|
+
const termWidth = Math.min(process.stdout.columns || 80, 100);
|
|
38158
|
+
const pathW = Math.min(22, Math.floor(termWidth * 0.25));
|
|
38159
|
+
const nameW = Math.min(28, Math.floor(termWidth * 0.32));
|
|
38160
|
+
const credW = 10;
|
|
38161
|
+
const statusW = 10;
|
|
38162
|
+
const headerLine = ` ${"Path".padEnd(pathW)} ${"Name".padEnd(nameW)} ${"Creds".padEnd(credW)} ${"Status".padEnd(statusW)}`;
|
|
38163
|
+
const separator = ` ${fig.horizontal.repeat(pathW + nameW + credW + statusW + 3)}`;
|
|
38164
|
+
const rows = agents.slice(0, 16).map((agent) => {
|
|
38165
|
+
const path7 = clip(agent.relativePath || ".", pathW);
|
|
38166
|
+
const name = clip(agent.manifestName || agent.manifest?.name || "-", nameW);
|
|
38167
|
+
const creds = credentialLabel(agent);
|
|
38168
|
+
const status = String(agent.status || "-");
|
|
38169
|
+
const statusColor = status === "online" ? colors.success : status === "error" ? colors.error : colors.warning;
|
|
38170
|
+
const statusIcon = status === "online" ? fig.dot : status === "error" ? fig.cross : fig.dotEmpty;
|
|
38171
|
+
return h(
|
|
38172
|
+
Text2,
|
|
38173
|
+
{ key: agent.localAgentId || agent.relativePath },
|
|
38174
|
+
h(Text2, { color: colors.muted }, " "),
|
|
38175
|
+
h(Text2, null, path7.padEnd(pathW)),
|
|
38176
|
+
h(Text2, null, " "),
|
|
38177
|
+
h(Text2, null, name.padEnd(nameW)),
|
|
38178
|
+
h(Text2, null, " "),
|
|
38179
|
+
h(Text2, { color: colors.muted }, creds.padEnd(credW)),
|
|
38180
|
+
h(Text2, null, " "),
|
|
38181
|
+
h(Text2, { color: statusColor }, `${statusIcon} ${status}`)
|
|
38182
|
+
);
|
|
38183
|
+
});
|
|
38184
|
+
const hiddenCount = agents.length - 16;
|
|
38185
|
+
return h(
|
|
38186
|
+
Box2,
|
|
38187
|
+
{ flexDirection: "column" },
|
|
38188
|
+
h(Text2, { color: colors.muted, bold: true }, headerLine),
|
|
38189
|
+
h(Text2, { color: colors.muted }, separator),
|
|
38190
|
+
...rows,
|
|
38191
|
+
hiddenCount > 0 && h(Text2, { color: colors.muted }, ` ${fig.ellipsis} and ${hiddenCount} more`)
|
|
38192
|
+
);
|
|
38193
|
+
}
|
|
38194
|
+
function FooterBar({ items }) {
|
|
38195
|
+
if (!items || !items.length) return null;
|
|
38196
|
+
return h(
|
|
38197
|
+
Text2,
|
|
38198
|
+
{ color: colors.muted },
|
|
38199
|
+
" ",
|
|
38200
|
+
...items.map((item, i) => [
|
|
38201
|
+
h(Text2, { key: `k-${i}`, color: colors.accent, bold: true }, item.key),
|
|
38202
|
+
h(Text2, { key: `l-${i}`, color: colors.muted }, ` ${item.label}`),
|
|
38203
|
+
i < items.length - 1 ? h(Text2, { key: `s-${i}` }, " ") : null
|
|
38204
|
+
]).flat().filter(Boolean)
|
|
38205
|
+
);
|
|
38206
|
+
}
|
|
38207
|
+
function AgentLogViewer({ agents, agentLogs, logMode, onSelectAgent, onBack }) {
|
|
38208
|
+
if (logMode === "picker") {
|
|
38209
|
+
return h(AgentLogPicker, { agents, agentLogs, onSelectAgent, onBack });
|
|
38210
|
+
}
|
|
38211
|
+
return h(AgentLogDetail, { relativePath: logMode, agentLogs, agents, onBack });
|
|
38212
|
+
}
|
|
38213
|
+
function AgentLogPicker({ agents, agentLogs, onSelectAgent, onBack }) {
|
|
38214
|
+
const [selectedIndex, setSelectedIndex] = useState5(0);
|
|
38215
|
+
const agentList = agents.map((agent) => {
|
|
38216
|
+
const path7 = agent.relativePath || ".";
|
|
38217
|
+
const logs = agentLogEntries(agentLogs, path7);
|
|
38218
|
+
const lastLog = logs.length > 0 ? logs[logs.length - 1] : null;
|
|
38219
|
+
const hasErrors = logs.some((l) => l.level === "error" || l.eventType === "completion" && l.success === false);
|
|
38220
|
+
return {
|
|
38221
|
+
path: path7,
|
|
38222
|
+
name: agent.manifestName || agent.manifest?.name || path7,
|
|
38223
|
+
logCount: logs.length,
|
|
38224
|
+
lastLog,
|
|
38225
|
+
hasErrors,
|
|
38226
|
+
status: agent.status || "-"
|
|
38227
|
+
};
|
|
38228
|
+
});
|
|
38229
|
+
const inventoryPaths = new Set(agentList.map((a) => a.path));
|
|
38230
|
+
for (const path7 of Object.keys(agentLogs || {})) {
|
|
38231
|
+
if (!inventoryPaths.has(path7)) {
|
|
38232
|
+
const logs = agentLogEntries(agentLogs, path7);
|
|
38233
|
+
agentList.push({
|
|
38234
|
+
path: path7,
|
|
38235
|
+
name: path7,
|
|
38236
|
+
logCount: logs.length,
|
|
38237
|
+
lastLog: logs.length > 0 ? logs[logs.length - 1] : null,
|
|
38238
|
+
hasErrors: logs.some((l) => l.level === "error"),
|
|
38239
|
+
status: "offline"
|
|
38240
|
+
});
|
|
38241
|
+
}
|
|
37558
38242
|
}
|
|
38243
|
+
useInput2((input, key) => {
|
|
38244
|
+
if (key.upArrow) {
|
|
38245
|
+
setSelectedIndex((i) => (i - 1 + agentList.length) % agentList.length);
|
|
38246
|
+
} else if (key.downArrow) {
|
|
38247
|
+
setSelectedIndex((i) => (i + 1) % agentList.length);
|
|
38248
|
+
} else if (key.return) {
|
|
38249
|
+
if (agentList.length > 0) {
|
|
38250
|
+
onSelectAgent(agentList[selectedIndex].path);
|
|
38251
|
+
}
|
|
38252
|
+
} else if (key.escape) {
|
|
38253
|
+
onBack();
|
|
38254
|
+
}
|
|
38255
|
+
});
|
|
38256
|
+
if (agentList.length === 0) {
|
|
38257
|
+
return h(
|
|
38258
|
+
Box2,
|
|
38259
|
+
{ flexDirection: "column" },
|
|
38260
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} Agent Logs`),
|
|
38261
|
+
h(Text2, null, ""),
|
|
38262
|
+
h(Text2, { color: colors.muted }, " No agent logs yet. Logs appear when agents run."),
|
|
38263
|
+
h(Text2, null, ""),
|
|
38264
|
+
h(FooterBar, { items: [{ key: "esc", label: "Back to serve" }] })
|
|
38265
|
+
);
|
|
38266
|
+
}
|
|
38267
|
+
const pathW = 24;
|
|
38268
|
+
const nameW = 26;
|
|
37559
38269
|
return h(
|
|
37560
38270
|
Box2,
|
|
37561
38271
|
{ flexDirection: "column" },
|
|
37562
|
-
h(Text2, {
|
|
37563
|
-
|
|
37564
|
-
|
|
37565
|
-
|
|
37566
|
-
|
|
37567
|
-
|
|
38272
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} Agent Logs ${fig.horizontal.repeat(20)}`),
|
|
38273
|
+
h(Text2, null, ""),
|
|
38274
|
+
h(Text2, { color: colors.muted }, ` ${"Agent".padEnd(nameW)} ${"Logs".padEnd(6)} ${"Last event"}`),
|
|
38275
|
+
h(Text2, { color: colors.muted }, ` ${fig.horizontal.repeat(nameW + 6 + 30)}`),
|
|
38276
|
+
...agentList.map((agent, i) => {
|
|
38277
|
+
const isActive = i === selectedIndex;
|
|
38278
|
+
const logCountColor = agent.hasErrors ? colors.error : agent.logCount > 0 ? colors.success : colors.muted;
|
|
38279
|
+
const lastEvent = agent.lastLog ? formatAgentLogEntry(agent.lastLog) : "No logs";
|
|
38280
|
+
return h(
|
|
38281
|
+
Text2,
|
|
38282
|
+
{ key: agent.path },
|
|
38283
|
+
h(Text2, { color: isActive ? colors.accent : colors.muted }, isActive ? ` ${fig.arrow} ` : " "),
|
|
38284
|
+
h(Text2, { bold: isActive }, clip(agent.name, nameW - 2).padEnd(nameW)),
|
|
38285
|
+
h(Text2, { color: logCountColor }, String(agent.logCount).padEnd(6)),
|
|
38286
|
+
h(Text2, { color: colors.muted }, clip(lastEvent, 36))
|
|
38287
|
+
);
|
|
38288
|
+
}),
|
|
38289
|
+
h(Text2, null, ""),
|
|
38290
|
+
h(FooterBar, { items: [
|
|
38291
|
+
{ key: "\u2191\u2193", label: "Navigate" },
|
|
38292
|
+
{ key: "\u23CE", label: "View logs" },
|
|
38293
|
+
{ key: "esc", label: "Back to serve" }
|
|
38294
|
+
] })
|
|
37568
38295
|
);
|
|
37569
38296
|
}
|
|
37570
|
-
function
|
|
38297
|
+
function AgentLogDetail({ relativePath, agentLogs, agents, onBack }) {
|
|
38298
|
+
const logs = agentLogEntries(agentLogs, relativePath);
|
|
38299
|
+
const agent = agents.find((a) => (a.relativePath || ".") === relativePath);
|
|
38300
|
+
const agentName = agent?.manifestName || agent?.manifest?.name || relativePath;
|
|
38301
|
+
const [scrollOffset, setScrollOffset] = useState5(0);
|
|
38302
|
+
const visibleCount = Math.min(20, Math.max(8, (process.stdout.rows || 24) - 10));
|
|
38303
|
+
useInput2((input, key) => {
|
|
38304
|
+
if (key.escape) {
|
|
38305
|
+
onBack();
|
|
38306
|
+
} else if (key.upArrow) {
|
|
38307
|
+
setScrollOffset((o) => Math.max(0, o - 1));
|
|
38308
|
+
} else if (key.downArrow) {
|
|
38309
|
+
setScrollOffset((o) => Math.min(Math.max(0, logs.length - visibleCount), o + 1));
|
|
38310
|
+
} else if (key.pageDown || input === " ") {
|
|
38311
|
+
setScrollOffset((o) => Math.min(Math.max(0, logs.length - visibleCount), o + visibleCount));
|
|
38312
|
+
} else if (key.pageUp) {
|
|
38313
|
+
setScrollOffset((o) => Math.max(0, o - visibleCount));
|
|
38314
|
+
}
|
|
38315
|
+
});
|
|
38316
|
+
const effectiveOffset = logs.length <= visibleCount ? 0 : scrollOffset >= logs.length - visibleCount - 2 ? Math.max(0, logs.length - visibleCount) : scrollOffset;
|
|
38317
|
+
const visibleLogs = logs.slice(effectiveOffset, effectiveOffset + visibleCount);
|
|
37571
38318
|
return h(
|
|
37572
38319
|
Box2,
|
|
37573
|
-
{ flexDirection: "column"
|
|
37574
|
-
h(Text2, { bold: true },
|
|
37575
|
-
|
|
37576
|
-
|
|
37577
|
-
|
|
37578
|
-
|
|
37579
|
-
|
|
38320
|
+
{ flexDirection: "column" },
|
|
38321
|
+
h(Text2, { bold: true, color: colors.brand }, ` ${fig.horizontal.repeat(3)} ${agentName}`),
|
|
38322
|
+
h(Text2, { color: colors.muted }, ` ${relativePath} ${fig.dash} ${logs.length} log entries`),
|
|
38323
|
+
h(Text2, null, ""),
|
|
38324
|
+
logs.length === 0 ? h(Text2, { color: colors.muted }, " No logs recorded yet for this agent. Logs appear during runs.") : h(
|
|
38325
|
+
Box2,
|
|
38326
|
+
{ flexDirection: "column" },
|
|
38327
|
+
...visibleLogs.map((entry, i) => {
|
|
38328
|
+
const levelColor = entry.level === "error" ? colors.error : entry.level === "warning" ? colors.warning : entry.level === "debug" ? colors.dim : colors.muted;
|
|
38329
|
+
const timeStr = formatLogTime(entry.timestamp);
|
|
38330
|
+
const icon = entry.eventType === "completion" ? entry.success ? fig.check : fig.cross : entry.eventType === "step_event" ? fig.arrow : entry.eventType === "progress" ? fig.dotEmpty : entry.level === "error" ? fig.cross : fig.dash;
|
|
38331
|
+
const iconColor = entry.eventType === "completion" ? entry.success ? colors.success : colors.error : levelColor;
|
|
38332
|
+
return h(
|
|
38333
|
+
Text2,
|
|
38334
|
+
{ key: `${effectiveOffset + i}` },
|
|
38335
|
+
h(Text2, { color: colors.dim }, ` ${timeStr} `),
|
|
38336
|
+
h(Text2, { color: iconColor }, `${icon} `),
|
|
38337
|
+
h(
|
|
38338
|
+
Text2,
|
|
38339
|
+
{ color: entry.level === "error" ? colors.error : colors.text },
|
|
38340
|
+
clip(formatAgentLogEntry(entry), 60)
|
|
38341
|
+
)
|
|
38342
|
+
);
|
|
38343
|
+
}),
|
|
38344
|
+
logs.length > visibleCount && h(
|
|
38345
|
+
Text2,
|
|
38346
|
+
{ color: colors.muted },
|
|
38347
|
+
` ${fig.ellipsis} Showing ${effectiveOffset + 1}-${effectiveOffset + visibleLogs.length} of ${logs.length}`
|
|
38348
|
+
)
|
|
38349
|
+
),
|
|
38350
|
+
h(Text2, null, ""),
|
|
38351
|
+
h(FooterBar, { items: [
|
|
38352
|
+
{ key: "\u2191\u2193", label: "Scroll" },
|
|
38353
|
+
{ key: "PgUp/Dn", label: "Page" },
|
|
38354
|
+
{ key: "esc", label: "Back to agents" }
|
|
38355
|
+
] })
|
|
37580
38356
|
);
|
|
37581
38357
|
}
|
|
38358
|
+
function formatAgentLogEntry(entry) {
|
|
38359
|
+
if (!entry) return "";
|
|
38360
|
+
const type = entry.eventType || "";
|
|
38361
|
+
switch (type) {
|
|
38362
|
+
case "log":
|
|
38363
|
+
return entry.message || "";
|
|
38364
|
+
case "progress": {
|
|
38365
|
+
const prog = entry.current != null && entry.total != null ? `${entry.current}/${entry.total}` : "";
|
|
38366
|
+
return `${prog}${entry.message ? ` ${entry.message}` : ""}`.trim() || "progress";
|
|
38367
|
+
}
|
|
38368
|
+
case "completion":
|
|
38369
|
+
if (entry.success) return "Completed successfully";
|
|
38370
|
+
if (entry.error && typeof entry.error === "object") return `Failed: ${entry.error.message || "error"}`;
|
|
38371
|
+
return `Failed: ${entry.error || "unknown error"}`;
|
|
38372
|
+
case "step_event":
|
|
38373
|
+
return `Step: ${entry.stepId || "unknown"}${entry.message ? ` - ${entry.message}` : ""}`;
|
|
38374
|
+
case "step_checkpoint":
|
|
38375
|
+
return `Checkpoint: ${entry.stepId || "unknown"}`;
|
|
38376
|
+
case "step_heartbeat":
|
|
38377
|
+
return `Heartbeat: ${entry.stepId || ""}${entry.message ? ` - ${entry.message}` : ""}`;
|
|
38378
|
+
case "artifact":
|
|
38379
|
+
return `Artifact: ${entry.message || "data"}`;
|
|
38380
|
+
default:
|
|
38381
|
+
return entry.message || type || "event";
|
|
38382
|
+
}
|
|
38383
|
+
}
|
|
38384
|
+
function formatLogTime(timestamp) {
|
|
38385
|
+
if (!timestamp) return " ";
|
|
38386
|
+
try {
|
|
38387
|
+
const d = new Date(timestamp);
|
|
38388
|
+
const h2 = String(d.getHours()).padStart(2, "0");
|
|
38389
|
+
const m = String(d.getMinutes()).padStart(2, "0");
|
|
38390
|
+
const s = String(d.getSeconds()).padStart(2, "0");
|
|
38391
|
+
return `${h2}:${m}:${s}`;
|
|
38392
|
+
} catch {
|
|
38393
|
+
return " ";
|
|
38394
|
+
}
|
|
38395
|
+
}
|
|
37582
38396
|
function DoctorScreen({ env: env3, platform: platform2, onBack }) {
|
|
37583
38397
|
const runtime = runtimeSummary({ env: env3, platform: platform2 });
|
|
37584
38398
|
const pkg = packageAccessSummary({ env: env3, platform: platform2 });
|
|
38399
|
+
const checks = [
|
|
38400
|
+
{ label: "Managed Python", passed: runtime.installed, value: runtime.installed ? "Present" : "Missing" },
|
|
38401
|
+
{ label: "Managed Env", passed: runtime.installed, value: runtime.detail },
|
|
38402
|
+
{ label: "Package Access", passed: pkg.configured, value: pkg.configured ? `Configured (${pkg.source})` : "Missing" }
|
|
38403
|
+
];
|
|
38404
|
+
const allPassed = checks.every((c) => c.passed);
|
|
37585
38405
|
return h(
|
|
37586
38406
|
Box2,
|
|
37587
38407
|
{ flexDirection: "column" },
|
|
37588
|
-
h(Text2, { bold: true }, "
|
|
37589
|
-
h(Text2, null,
|
|
37590
|
-
|
|
37591
|
-
|
|
38408
|
+
h(Text2, { bold: true }, " System Health"),
|
|
38409
|
+
h(Text2, null, ""),
|
|
38410
|
+
...checks.map((check) => h(
|
|
38411
|
+
Text2,
|
|
38412
|
+
{ key: check.label },
|
|
38413
|
+
h(Text2, { color: check.passed ? colors.success : colors.error }, ` ${check.passed ? fig.check : fig.cross} `),
|
|
38414
|
+
h(Text2, null, `${check.label.padEnd(18)}${check.value}`)
|
|
38415
|
+
)),
|
|
38416
|
+
h(Text2, null, ""),
|
|
38417
|
+
h(
|
|
38418
|
+
Text2,
|
|
38419
|
+
{ color: allPassed ? colors.success : colors.warning, bold: true },
|
|
38420
|
+
allPassed ? ` ${fig.check} All checks passed` : ` ${fig.warning} Some checks need attention`
|
|
38421
|
+
),
|
|
38422
|
+
h(Text2, null, ""),
|
|
37592
38423
|
h(SelectInput2, {
|
|
37593
|
-
items: [{ label: "Run
|
|
38424
|
+
items: [{ label: "Run full doctor output", value: "run" }, { label: "Back", value: "back" }],
|
|
37594
38425
|
onSelect: async (item) => {
|
|
37595
38426
|
if (item.value === "back") onBack();
|
|
37596
38427
|
else doctor({ env: env3, platform: platform2 });
|
|
37597
38428
|
}
|
|
37598
|
-
})
|
|
38429
|
+
}),
|
|
38430
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] })
|
|
37599
38431
|
);
|
|
37600
38432
|
}
|
|
37601
38433
|
function UpdateScreen({ env: env3, platform: platform2, onBack }) {
|
|
@@ -37603,29 +38435,65 @@ function UpdateScreen({ env: env3, platform: platform2, onBack }) {
|
|
|
37603
38435
|
return h(
|
|
37604
38436
|
Box2,
|
|
37605
38437
|
{ flexDirection: "column" },
|
|
37606
|
-
h(Text2, { bold: true }, "Update"),
|
|
38438
|
+
h(Text2, { bold: true }, " Update Runtime"),
|
|
38439
|
+
h(Text2, null, ""),
|
|
37607
38440
|
h(SelectInput2, {
|
|
37608
|
-
items: [{ label: "Update managed runtime", value: "run" }, { label: "Back", value: "back" }],
|
|
38441
|
+
items: [{ label: "Update managed runtime & packages", value: "run" }, { label: "Back", value: "back" }],
|
|
37609
38442
|
onSelect: async (item) => {
|
|
37610
38443
|
if (item.value === "back") {
|
|
37611
38444
|
onBack();
|
|
37612
38445
|
return;
|
|
37613
38446
|
}
|
|
37614
|
-
setStatus(
|
|
38447
|
+
setStatus(`${fig.dotEmpty} Updating managed runtime...`);
|
|
37615
38448
|
await setup({ nonInteractive: true, env: env3, platform: platform2 });
|
|
37616
|
-
setStatus(
|
|
38449
|
+
setStatus(`${fig.check} Update finished`);
|
|
37617
38450
|
}
|
|
37618
38451
|
}),
|
|
37619
|
-
status && h(Text2,
|
|
38452
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38453
|
+
h(Text2, null, ""),
|
|
38454
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Select" }, { key: "esc", label: "Back" }] }),
|
|
38455
|
+
h(BackHint, { onBack })
|
|
37620
38456
|
);
|
|
37621
38457
|
}
|
|
37622
38458
|
function CommandsScreen({ onBack }) {
|
|
38459
|
+
const grouped = [
|
|
38460
|
+
{ section: "Getting Started", commands: [
|
|
38461
|
+
{ cmd: "vendian login", desc: "Sign in and prepare runtime" },
|
|
38462
|
+
{ cmd: "vendian init --output-dir ./agents", desc: "Initialize docs workspace" }
|
|
38463
|
+
] },
|
|
38464
|
+
{ section: "Agent Development", commands: [
|
|
38465
|
+
{ cmd: 'vendian create "My Agent" --output-dir .', desc: "Scaffold new agent" },
|
|
38466
|
+
{ cmd: "vendian validate ./agents/my-agent --runtime", desc: "Validate manifest" },
|
|
38467
|
+
{ cmd: "vendian test ./agents/my-agent --dry-run", desc: "Test locally" },
|
|
38468
|
+
{ cmd: "vendian models", desc: "List available models" }
|
|
38469
|
+
] },
|
|
38470
|
+
{ section: "Cloud & Deploy", commands: [
|
|
38471
|
+
{ cmd: "vendian cloud local serve --agents-dir .", desc: "Start cloud-connected serve" },
|
|
38472
|
+
{ cmd: "vendian login --backend staging", desc: "Connect to staging" }
|
|
38473
|
+
] },
|
|
38474
|
+
{ section: "Maintenance", commands: [
|
|
38475
|
+
{ cmd: "vendian doctor", desc: "Check system health" },
|
|
38476
|
+
{ cmd: "vendian update", desc: "Update runtime & packages" }
|
|
38477
|
+
] }
|
|
38478
|
+
];
|
|
37623
38479
|
return h(
|
|
37624
38480
|
Box2,
|
|
37625
38481
|
{ flexDirection: "column" },
|
|
37626
|
-
h(Text2, { bold: true }, "
|
|
37627
|
-
|
|
37628
|
-
|
|
38482
|
+
h(Text2, { bold: true }, " Quick Reference"),
|
|
38483
|
+
h(Text2, null, ""),
|
|
38484
|
+
...grouped.map((group) => [
|
|
38485
|
+
h(Text2, { key: `title-${group.section}`, color: colors.accent, bold: true }, ` ${group.section}`),
|
|
38486
|
+
...group.commands.map((item) => h(
|
|
38487
|
+
Text2,
|
|
38488
|
+
{ key: item.cmd },
|
|
38489
|
+
h(Text2, { color: colors.muted }, " "),
|
|
38490
|
+
h(Text2, { color: colors.brand }, item.cmd.padEnd(44)),
|
|
38491
|
+
h(Text2, { color: colors.muted }, item.desc)
|
|
38492
|
+
)),
|
|
38493
|
+
h(Text2, { key: `gap-${group.section}` }, "")
|
|
38494
|
+
]).flat(),
|
|
38495
|
+
h(FooterBar, { items: [{ key: "esc", label: "Back" }] }),
|
|
38496
|
+
h(BackHint, { onBack })
|
|
37629
38497
|
);
|
|
37630
38498
|
}
|
|
37631
38499
|
function CommandPromptScreen({ title, label, initialValue, onSubmit, onBack }) {
|
|
@@ -37635,17 +38503,20 @@ function CommandPromptScreen({ title, label, initialValue, onSubmit, onBack }) {
|
|
|
37635
38503
|
Box2,
|
|
37636
38504
|
{ flexDirection: "column" },
|
|
37637
38505
|
h(Text2, { bold: true }, title),
|
|
38506
|
+
h(Text2, null, ""),
|
|
37638
38507
|
h(TextInput2, {
|
|
37639
38508
|
value,
|
|
37640
38509
|
placeholder: label,
|
|
37641
38510
|
onChange: setValue,
|
|
37642
38511
|
onSubmit: async (submitted) => {
|
|
37643
|
-
setStatus(
|
|
38512
|
+
setStatus(`${fig.dotEmpty} Running...`);
|
|
37644
38513
|
await onSubmit(submitted);
|
|
37645
|
-
setStatus(
|
|
38514
|
+
setStatus(`${fig.check} Done`);
|
|
37646
38515
|
}
|
|
37647
38516
|
}),
|
|
37648
|
-
status && h(Text2,
|
|
38517
|
+
status && h(Text2, { color: status.includes(fig.check) ? colors.success : colors.muted }, ` ${status}`),
|
|
38518
|
+
h(Text2, null, ""),
|
|
38519
|
+
h(FooterBar, { items: [{ key: "\u23CE", label: "Submit" }, { key: "esc", label: "Back" }] }),
|
|
37649
38520
|
h(BackHint, { onBack })
|
|
37650
38521
|
);
|
|
37651
38522
|
}
|
|
@@ -37653,10 +38524,11 @@ function BackHint({ onBack }) {
|
|
|
37653
38524
|
useInput2((input, key) => {
|
|
37654
38525
|
if (key.escape || input === "\x1B") onBack();
|
|
37655
38526
|
});
|
|
37656
|
-
return
|
|
38527
|
+
return null;
|
|
37657
38528
|
}
|
|
37658
38529
|
function attachServeChild(child, setState, setStartupError, onExit) {
|
|
37659
38530
|
let buffer = "";
|
|
38531
|
+
const stderrChunks = [];
|
|
37660
38532
|
child.stdout.setEncoding("utf8");
|
|
37661
38533
|
child.stdout.on("data", (chunk) => {
|
|
37662
38534
|
buffer += chunk;
|
|
@@ -37677,6 +38549,7 @@ function attachServeChild(child, setState, setStartupError, onExit) {
|
|
|
37677
38549
|
child.stderr.on("data", (chunk) => {
|
|
37678
38550
|
const text = String(chunk).trim();
|
|
37679
38551
|
if (text) {
|
|
38552
|
+
stderrChunks.push(text);
|
|
37680
38553
|
setState((current) => ({
|
|
37681
38554
|
...current,
|
|
37682
38555
|
logs: [...current.logs, { type: "stderr", message: text }].slice(-200)
|
|
@@ -37684,23 +38557,33 @@ function attachServeChild(child, setState, setStartupError, onExit) {
|
|
|
37684
38557
|
}
|
|
37685
38558
|
});
|
|
37686
38559
|
child.on("error", (error) => setStartupError(errorMessage2(error)));
|
|
37687
|
-
child.on("exit",
|
|
38560
|
+
child.on("exit", (code, signal) => {
|
|
38561
|
+
const message = serveProcessExitMessage({ stderr: stderrChunks.join("\n"), code, signal });
|
|
38562
|
+
if (message) {
|
|
38563
|
+
setStartupError(message);
|
|
38564
|
+
}
|
|
38565
|
+
onExit({ code, signal, message });
|
|
38566
|
+
});
|
|
37688
38567
|
}
|
|
37689
38568
|
function helpText() {
|
|
37690
38569
|
return [
|
|
37691
|
-
"Vendian CLI",
|
|
37692
38570
|
"",
|
|
37693
|
-
|
|
37694
|
-
"
|
|
37695
|
-
"
|
|
37696
|
-
"
|
|
37697
|
-
"
|
|
37698
|
-
"
|
|
37699
|
-
|
|
37700
|
-
"
|
|
38571
|
+
` ${fig.arrowUp} VENDIAN CLI v${CLI_VERSION}`,
|
|
38572
|
+
"",
|
|
38573
|
+
" Usage:",
|
|
38574
|
+
" vendian Open the interactive shell",
|
|
38575
|
+
" vendian login Sign in and prepare the local runtime",
|
|
38576
|
+
" vendian doctor Check local bootstrap health",
|
|
38577
|
+
" vendian update Update the managed runtime",
|
|
38578
|
+
" vendian init Write SDK agent docs into a workspace",
|
|
38579
|
+
' vendian create "My Agent" Scaffold a new agent from templates',
|
|
38580
|
+
" vendian <command> Run a managed Python SDK/cloud command",
|
|
38581
|
+
"",
|
|
38582
|
+
" Examples:",
|
|
38583
|
+
...COMMANDS.map((command) => ` ${command}`),
|
|
37701
38584
|
"",
|
|
37702
|
-
|
|
37703
|
-
|
|
38585
|
+
` Run ${fig.arrowRight} vendian ${fig.arrowRight} to open the interactive TUI`,
|
|
38586
|
+
""
|
|
37704
38587
|
].join("\n");
|
|
37705
38588
|
}
|
|
37706
38589
|
function credentialLabel(agent) {
|