@cotal-ai/cli 0.152.0 → 0.154.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/chat-view.js +2 -2
- package/dist/chat/chat-view.js.map +1 -1
- package/dist/chat/controller.d.ts +4 -3
- package/dist/chat/controller.d.ts.map +1 -1
- package/dist/chat/controller.js +13 -12
- package/dist/chat/controller.js.map +1 -1
- package/dist/chat/plain.js +1 -1
- package/dist/chat/plain.js.map +1 -1
- package/dist/chat/view.d.ts.map +1 -1
- package/dist/chat/view.js +6 -0
- package/dist/chat/view.js.map +1 -1
- package/dist/command.d.ts.map +1 -1
- package/dist/command.js +9 -8
- package/dist/command.js.map +1 -1
- package/dist/commands/down-live-lease.d.ts.map +1 -1
- package/dist/commands/down-live-lease.js +19 -6
- package/dist/commands/down-live-lease.js.map +1 -1
- package/dist/commands/join.d.ts.map +1 -1
- package/dist/commands/join.js +26 -2
- package/dist/commands/join.js.map +1 -1
- package/dist/commands/mint.js +1 -1
- package/dist/commands/mint.js.map +1 -1
- package/dist/commands/reset-space-apply.d.ts.map +1 -1
- package/dist/commands/reset-space-apply.js +5 -2
- package/dist/commands/reset-space-apply.js.map +1 -1
- package/dist/commands/service-registry.d.ts.map +1 -1
- package/dist/commands/service-registry.js +7 -5
- package/dist/commands/service-registry.js.map +1 -1
- package/dist/commands/space.d.ts +3 -3
- package/dist/commands/space.d.ts.map +1 -1
- package/dist/commands/space.js +11 -8
- package/dist/commands/space.js.map +1 -1
- package/dist/commands/spawn.d.ts.map +1 -1
- package/dist/commands/spawn.js +11 -1
- package/dist/commands/spawn.js.map +1 -1
- package/dist/commands/stack-up.d.ts +2 -2
- package/dist/commands/stack-up.d.ts.map +1 -1
- package/dist/commands/stack-up.js +14 -6
- package/dist/commands/stack-up.js.map +1 -1
- package/dist/commands/status.d.ts +3 -2
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +49 -20
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +18 -7
- package/dist/commands/up.js.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +3 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/manifest/prepare.d.ts.map +1 -1
- package/dist/lib/manifest/prepare.js +4 -0
- package/dist/lib/manifest/prepare.js.map +1 -1
- package/dist/lib/team-agent-removal.d.ts +1 -1
- package/package.json +16 -4
package/dist/commands/status.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { accessSync, constants, existsSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { CotalEndpoint, dialerFor, EpEnvelopeError, formatAge, isReachable, mintCreds, mintLifecycleUid, resolveService, realDirNoSymlink, invokeRepairingSplit, standaloneConnectOpts, newIdentity, idFromCreds, principalKey, DEV_OWNER, unansweredRequest, resolveAuthProvider, personaDir, presenceText, } from "@cotal-ai/core";
|
|
5
|
-
import { stoppedLoopbackListener, accountInventory, assessMaintenanceClaim, authDir, isCommandFailure, readMaintenanceJournal, recordsElsewhereError, recordsElsewhereText, restoreRolledBackRuns, targetErrorSpace, brokerAddressForDisplay, canonicalRoot, CLI_USER_ACTOR, codeSpan, CommandFailure, deliveryCredsKey, DELIVERY_PIDFILE, extensionsDir, findCotalRoot, folderSpaceOverSelection, meshesForRoot, resolveReadsLiveness, stoppedStack, unsettledStackOperation, withdrawOperationNote, hasUserAuthState, homeCotalDir, cachedPreferences, resolvePreference, isMeshRegistryError, isWorkspaceTargetError, jsonFlag, loadManagerInstanceIdentity, loadSoleSpaceAuth, localProcessPath, localProcessVisible, MANAGER_PIDFILE, oneLine, PREFERENCE_KEYS, parsePid, plainFlag, preflightTarget, presentationOf, principalFromBearer, probeLiveness, probeWebReadiness, readCurrent, readMeshRegistry, readPidfile, preparedRecordSkipped, readPreparedSpaces, readRenewalRecord, renderWorkspaceError, resolveMeshTarget, serverFlag, spaceFlag, userAuthStateDir, WEB_PIDFILE, WEB_READINESS_HEADER, workspaceSecretStore, writeResult, workspaceErrorParts, preferencesPath, preferencesFolderWarning, cotalDirLink, movedProject, spaceStreamsAbsent, spaceStreamsExpected, resolveControlTarget, } from "@cotal-ai/workspace";
|
|
4
|
+
import { CotalEndpoint, agentFilePath, dialerFor, EpEnvelopeError, formatAge, isReachable, mintCreds, mintLifecycleUid, resolveService, realDirNoSymlink, invokeRepairingSplit, standaloneConnectOpts, newIdentity, idFromCreds, principalKey, DEV_OWNER, unansweredRequest, resolveAuthProvider, personaDir, presenceText, } from "@cotal-ai/core";
|
|
5
|
+
import { stoppedLoopbackListener, accountInventory, assessMaintenanceClaim, authDir, isCommandFailure, readMaintenanceJournal, recordsElsewhereError, recordsElsewhereText, restoreRolledBackRuns, targetErrorSpace, brokerAddressForDisplay, brokerCheck, canonicalRoot, CLI_USER_ACTOR, codeSpan, CommandFailure, deliveryCredsKey, DELIVERY_PIDFILE, extensionsDir, findCotalRoot, folderSpaceOverSelection, meshesForRoot, resolveReadsLiveness, stoppedStack, unsettledStackOperation, withdrawOperationNote, hasUserAuthState, homeCotalDir, cachedPreferences, loadLaunchPersonaFile, resolvePreference, isMeshRegistryError, isWorkspaceTargetError, jsonFlag, loadManagerInstanceIdentity, loadSoleSpaceAuth, localProcessPath, localProcessVisible, MANAGER_PIDFILE, oneLine, PREFERENCE_KEYS, parsePid, plainFlag, preflightTarget, presentationOf, principalFromBearer, probeLiveness, probeWebReadiness, readCurrent, readMeshRegistry, readPidfile, preparedRecordSkipped, readPreparedSpaces, readRenewalRecord, renderWorkspaceError, resolveMeshTarget, serverFlag, spaceFlag, userAuthStateDir, WEB_PIDFILE, WEB_READINESS_HEADER, workspaceSecretStore, writeResult, workspaceErrorParts, preferencesPath, preferencesFolderWarning, cotalDirLink, movedProject, spaceStreamsAbsent, spaceStreamsExpected, resolveControlTarget, } from "@cotal-ai/workspace";
|
|
6
6
|
import { localProcessSurface } from "../ext-loader.js";
|
|
7
7
|
import { cliVersion, cliProvenance, readExtensionVersions } from "../lib/version.js";
|
|
8
8
|
import { agentSkillsSkew } from "../lib/agent-skills.js";
|
|
@@ -162,10 +162,11 @@ export async function status(args) {
|
|
|
162
162
|
// THE RESPONDER AXIS (#1576), read ONCE and threaded into the rows that would otherwise claim
|
|
163
163
|
// health they never checked. It is read before the folder section because that section renders
|
|
164
164
|
// the delivery process row, and a live pid means nothing without it.
|
|
165
|
-
const
|
|
165
|
+
const preflight = selected.ok && selected.target.mode !== "user" ? await preflightTarget(selected.target) : undefined;
|
|
166
|
+
const responder = await readResponderAxis(selected, preflight);
|
|
166
167
|
const folder = blocked ? unreadFolder(root, blocked) : await readFolder(root, selected, values, responder.state, gaps, hints);
|
|
167
|
-
const meshes = await readMeshes(cwd, selected, Boolean(values.all), gaps, offline);
|
|
168
|
-
const target = await readSelected(selected, responder, folder, gaps, hints);
|
|
168
|
+
const meshes = await readMeshes(cwd, selected, Boolean(values.all), gaps, offline, preflight);
|
|
169
|
+
const target = await readSelected(selected, responder, folder, gaps, hints, preflight);
|
|
169
170
|
// The note under the heading sends here for this folder's own stack cut off with no recorded
|
|
170
171
|
// outcome under another selection. A blocked one is named with its block under `This folder's
|
|
171
172
|
// space` and its step first in Next, so that note is left out here, with its --json warning. One
|
|
@@ -326,7 +327,23 @@ async function readMachine(selected, gaps, hints) {
|
|
|
326
327
|
let defaults = null;
|
|
327
328
|
try {
|
|
328
329
|
const context = { preferences: cachedPreferences(), space: selected.ok ? selected.target.space : undefined };
|
|
329
|
-
|
|
330
|
+
const persona = resolvePreference("persona", context);
|
|
331
|
+
defaults = { harness: resolvePreference("harness", context).value, persona: persona.value };
|
|
332
|
+
if (selected.ok) {
|
|
333
|
+
const path = agentFilePath(selected.target.root, persona.value);
|
|
334
|
+
try {
|
|
335
|
+
const definition = loadLaunchPersonaFile(path);
|
|
336
|
+
defaults.harness = resolvePreference("harness", { ...context, pin: definition.agent }).value;
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
// A bare spawn writes the shipped, unpinned default only when the product default is absent.
|
|
340
|
+
// Every other failed read leaves the effective harness unknown, never the saved preference.
|
|
341
|
+
if (error.code !== "ENOENT" || persona.winner?.source !== "default") {
|
|
342
|
+
defaults.harness = null;
|
|
343
|
+
gaps.add("DEFAULT_PERSONA_UNREADABLE", "the default launch persona could not be read and validated; its effective harness is unknown", { path });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
330
347
|
}
|
|
331
348
|
catch (e) {
|
|
332
349
|
// The refusal names the file and its problem, and its remedy is the next step.
|
|
@@ -460,7 +477,7 @@ async function expectedDeliveryHolder(target) {
|
|
|
460
477
|
*
|
|
461
478
|
* `leased` says whether the read found a delivery lease record. An open mesh runs no delivery
|
|
462
479
|
* daemon, so there a missing lease is the normal state rather than an unbound responder. */
|
|
463
|
-
async function readResponderAxis(selected) {
|
|
480
|
+
async function readResponderAxis(selected, preflight) {
|
|
464
481
|
let leased = false;
|
|
465
482
|
if (!selected.ok)
|
|
466
483
|
return { state: "unknown", leased };
|
|
@@ -468,8 +485,7 @@ async function readResponderAxis(selected) {
|
|
|
468
485
|
if (target.mode === "user")
|
|
469
486
|
return { state: "unknown", leased };
|
|
470
487
|
try {
|
|
471
|
-
|
|
472
|
-
if (!preflight.ok)
|
|
488
|
+
if (!preflight?.ok)
|
|
473
489
|
return { state: "unknown", leased };
|
|
474
490
|
const id = newIdentity();
|
|
475
491
|
const creds = target.auth ? await mintCreds(target.auth, id, "observer") : undefined;
|
|
@@ -913,7 +929,7 @@ function deliveryDetail(live, responder) {
|
|
|
913
929
|
* with its own recorded TLS requirement. A bare TCP/INFO probe would green-light a plaintext broker
|
|
914
930
|
* that has substituted for a TLS-required mesh — the FAIL1 attack — so a list that only asks "is
|
|
915
931
|
* anything listening" cannot report on the one property the record claims. */
|
|
916
|
-
async function readMeshes(cwd, selected, all, gaps, offline) {
|
|
932
|
+
async function readMeshes(cwd, selected, all, gaps, offline, preflight) {
|
|
917
933
|
// A registry file that cannot be read is named, and the readable records are still listed and
|
|
918
934
|
// checked. Only an absent directory or pointer is an empty registry or no current mesh.
|
|
919
935
|
const unreadable = [];
|
|
@@ -955,6 +971,18 @@ async function readMeshes(cwd, selected, all, gaps, offline) {
|
|
|
955
971
|
const chosen = selected.ok ? selected.target : undefined;
|
|
956
972
|
// A `--server` that names another address is the only broker dialed for the selected space.
|
|
957
973
|
const checked = (m) => all || (m.space === chosen?.space && m.server === chosen.server);
|
|
974
|
+
const check = async (m) => {
|
|
975
|
+
if (!checked(m))
|
|
976
|
+
return "not-checked";
|
|
977
|
+
if (preflight && m.space === chosen?.space && m.server === chosen.server) {
|
|
978
|
+
if (preflight.ok)
|
|
979
|
+
return "reachable";
|
|
980
|
+
if (preflight.kind === "slow-link" || preflight.kind === "broker-stopped" || preflight.kind === "unreachable")
|
|
981
|
+
return preflight.kind;
|
|
982
|
+
return preflight.kind === "tls-trust" || preflight.kind === "tls-unsupported" ? "unreachable" : "reachable";
|
|
983
|
+
}
|
|
984
|
+
return brokerCheck(m.server, m.tlsRequired);
|
|
985
|
+
};
|
|
958
986
|
const items = await Promise.all(entries.map(async (m) => ({
|
|
959
987
|
space: m.space,
|
|
960
988
|
server: displayStatusBroker(m.server, m.space, gaps),
|
|
@@ -965,7 +993,7 @@ async function readMeshes(cwd, selected, all, gaps, offline) {
|
|
|
965
993
|
eventsRequired: m.policy?.events === "required",
|
|
966
994
|
modeChecked: m.unchecked !== true,
|
|
967
995
|
current: m.space === current,
|
|
968
|
-
check:
|
|
996
|
+
check: await check(m),
|
|
969
997
|
catalog: m.origin === "catalog" ? { name: m.catalogName && m.catalogName !== m.space ? m.catalogName : null, fetchedAt: m.catalogFetchedAt ?? null, error: m.catalogError ?? null } : null,
|
|
970
998
|
})));
|
|
971
999
|
// The prepared spaces folder, or a record in it, that cannot be read is named the same way.
|
|
@@ -1037,7 +1065,7 @@ function rootStoreProblem(root) {
|
|
|
1037
1065
|
return undefined;
|
|
1038
1066
|
}
|
|
1039
1067
|
}
|
|
1040
|
-
async function readSelected(selected, responder, folder, gaps, hints) {
|
|
1068
|
+
async function readSelected(selected, responder, folder, gaps, hints, preflight) {
|
|
1041
1069
|
const cmd = displayCmd();
|
|
1042
1070
|
if (!selected.ok) {
|
|
1043
1071
|
const e = selected.error;
|
|
@@ -1168,7 +1196,8 @@ async function readSelected(selected, responder, folder, gaps, hints) {
|
|
|
1168
1196
|
hints.push(moved.remedy);
|
|
1169
1197
|
return { resolved: false, code: "moved-folder", message: moved.message };
|
|
1170
1198
|
}
|
|
1171
|
-
|
|
1199
|
+
if (preflight === undefined)
|
|
1200
|
+
throw new Error("status: selected non-user target has no preflight observation");
|
|
1172
1201
|
if (!preflight.ok) {
|
|
1173
1202
|
// A `--server` address that is not the one recorded for the space says nothing about whether its
|
|
1174
1203
|
// stack runs, so Next names that address as the refusal of other commands does. A stopped stack
|
|
@@ -1393,7 +1422,7 @@ function folderSection(f, selected) {
|
|
|
1393
1422
|
return { title: "This Folder", blocks: [{ kind: "fields", rows }] };
|
|
1394
1423
|
}
|
|
1395
1424
|
function meshesSections(m) {
|
|
1396
|
-
const check = { reachable: cell("reachable", "ok"), unreachable: cell("down", "failed"), "not-checked": cell("not checked", "hint") };
|
|
1425
|
+
const check = { reachable: cell("reachable", "ok"), unreachable: cell("down", "failed"), "slow-link": cell("not answering", "failed"), "broker-stopped": cell("broker process is stopped", "failed"), "not-checked": cell("not checked", "hint") };
|
|
1397
1426
|
const blocks = [];
|
|
1398
1427
|
if (!m.items.length && !m.unreadable.length)
|
|
1399
1428
|
blocks.push({ kind: "lines", lines: [cell("none", "hint")] });
|
|
@@ -1602,7 +1631,7 @@ function connectionCell(s) {
|
|
|
1602
1631
|
return stateCell("reachable", "ok");
|
|
1603
1632
|
const states = {
|
|
1604
1633
|
unreachable: "unreachable",
|
|
1605
|
-
"slow-link": "
|
|
1634
|
+
"slow-link": "not answering",
|
|
1606
1635
|
"broker-stopped": `broker process ${s.brokerPid} is stopped`,
|
|
1607
1636
|
"tls-trust": "TLS could not be verified",
|
|
1608
1637
|
"tls-unsupported": "listener does not offer required TLS",
|
|
@@ -1639,7 +1668,7 @@ function spaceStateCell(r, entry) {
|
|
|
1639
1668
|
return connectionCell(r.selected);
|
|
1640
1669
|
if (entry.check === "not-checked")
|
|
1641
1670
|
return "";
|
|
1642
|
-
return stateCell(entry.check === "
|
|
1671
|
+
return stateCell(entry.check === "slow-link" ? "not answering" : entry.check === "broker-stopped" ? "broker process is stopped" : entry.check, entry.check === "reachable" ? "ok" : "failed");
|
|
1643
1672
|
}
|
|
1644
1673
|
/**
|
|
1645
1674
|
* The spaces this machine knows: the selected one first with its connection state, then one line
|
|
@@ -1727,7 +1756,7 @@ function selectedOverview(r) {
|
|
|
1727
1756
|
...(r.stackManager ? [["Manager", r.stackManager.endpoint === "answered" ? stateCell("answering", "ok") : r.stackManager.endpoint === "not-answering" ? stateCell(`not answering · stack-manager pid ${r.stackManager.pid}`, "failed") : stateCell("endpoint not checked", "hint")]] : []),
|
|
1728
1757
|
["Access", s.mode === "user" ? "user sign-in" : s.mode === "auth" ? "static auth" : "open"],
|
|
1729
1758
|
["Project", s.rootGone ? stateCell(`${s.root} · folder is gone`, "failed") : s.root],
|
|
1730
|
-
["Default agent", r.machine.defaults ? `${r.machine.defaults.harness ?? "application
|
|
1759
|
+
["Default agent", r.machine.defaults ? `${r.machine.defaults.harness ?? "application unresolved"} · persona ${r.machine.defaults.persona ?? "not set"}` : stateCell("saved defaults could not be read", "failed")],
|
|
1731
1760
|
["Persona catalog", s.personas.default === "valid" ? "default available" : stateCell(s.personas.default === "invalid" ? "default is invalid" : s.personas.default === "unreadable" ? "could not be read" : "no default persona", s.personas.default === "invalid" || s.personas.default === "unreadable" ? "failed" : "hint")],
|
|
1732
1761
|
];
|
|
1733
1762
|
if (s.tlsRequired)
|
|
@@ -2287,15 +2316,15 @@ async function managerHealth(target, context, credential) {
|
|
|
2287
2316
|
}
|
|
2288
2317
|
catch (e) {
|
|
2289
2318
|
// A no-responder service rail or an absent manager registry is definitive no-service evidence.
|
|
2290
|
-
//
|
|
2291
|
-
//
|
|
2319
|
+
// A dead local PID is absent even while its lease awaits expiry. Without a PID record, the
|
|
2320
|
+
// lease still identifies an extant component; any other failed probe remains a refusal.
|
|
2292
2321
|
const noService = managerNoService(e);
|
|
2293
2322
|
facts.push(noService ? "serve no answer" : `serve probe refused: ${e.message}`);
|
|
2294
2323
|
if (!noService)
|
|
2295
2324
|
return { name: "manager", verdict: "refused", facts };
|
|
2296
2325
|
const liveRecord = record.kind === "live";
|
|
2297
2326
|
const hasLease = facts.some((fact) => fact.startsWith("lease holder "));
|
|
2298
|
-
return { name: "manager", verdict: liveRecord || hasLease ? "not-serving" : "absent", facts };
|
|
2327
|
+
return { name: "manager", verdict: liveRecord || (record.kind !== "dead" && hasLease) ? "not-serving" : "absent", facts };
|
|
2299
2328
|
}
|
|
2300
2329
|
finally {
|
|
2301
2330
|
await close?.();
|