@kal-elsam/kairo-runtime 0.14.0 → 0.15.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/CHANGELOG.md +84 -0
- package/bin/kairo-runtime.js +0 -0
- package/bin/kairo.js +0 -0
- package/package.json +1 -1
- package/src/cli.js +172 -8
- package/src/global/check-resolutions.js +31 -0
- package/src/global/cli-help.js +19 -2
- package/src/global/component-ecosystem-checks.js +2 -0
- package/src/global/component-integration-cli.js +29 -10
- package/src/global/components-resolve-cli.js +246 -0
- package/src/global/connection-actions.js +147 -0
- package/src/global/connections.js +269 -0
- package/src/global/fleet-configure-plan.js +123 -0
- package/src/global/fleet-configure.js +303 -0
- package/src/global/fleet-models.js +188 -0
- package/src/global/fleet-set.js +219 -0
- package/src/global/fleet-shared.js +38 -0
- package/src/global/ink/cockpit-controller.js +1 -1
- package/src/global/ink/cockpit-models.js +4 -1
- package/src/global/ink/orchestrator-app.js +21 -2
- package/src/global/ink/ux/live-overview.js +5 -11
- package/src/global/ink/ux/overview-needs.js +1 -1
- package/src/global/integrations/engram-evidence.js +7 -2
- package/src/global/integrations/sdd-apply.js +17 -7
- package/src/global/integrations/sdd-evidence.js +22 -3
- package/src/global/integrations/sdd-plan.js +21 -3
- package/src/global/integrations/sdd-resolutions.js +73 -0
- package/src/global/integrations/sdd-state.js +69 -0
- package/src/global/integrations/sdd-verify.js +9 -4
- package/src/global/mcp/kairo-mcp.js +56 -5
- package/src/global/mcp/resolve-mcp-workspace.js +51 -0
- package/src/global/mcp/work-snapshot-rule.js +89 -0
- package/src/global/mcp/work-snapshot-tool.js +49 -0
- package/src/global/mcp-install.js +239 -0
- package/src/global/next/next-cli.js +35 -0
- package/src/global/next/next-report.js +145 -0
- package/src/global/next/project-key.js +36 -0
- package/src/global/next/publish-work-snapshot.js +116 -0
- package/src/global/next/work-enroll.js +91 -0
- package/src/global/next/work-snapshot.js +216 -0
- package/src/global/observability/fleet-activity.js +197 -0
- package/src/global/observability/fleet-models-catalog.js +137 -0
- package/src/global/observability/fleet-platforms.js +166 -0
- package/src/global/observability/fleet-probe.js +229 -0
- package/src/global/paths.js +2 -1
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declared fleet topology (orchestrator → minions + models) + optional live activity.
|
|
3
|
+
* Read-only probes — writes go through fleet-set.js with consent.
|
|
4
|
+
*/
|
|
5
|
+
import { access, readFile } from "node:fs/promises";
|
|
6
|
+
import { constants as fsConstants } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { resolveHomeDir } from "../paths.js";
|
|
9
|
+
import { isExecutableAvailable } from "../cli-probe.js";
|
|
10
|
+
import { buildOpenCodeActivity } from "./fleet-activity.js";
|
|
11
|
+
import {
|
|
12
|
+
buildClaudeFleet,
|
|
13
|
+
buildCodexFleet,
|
|
14
|
+
buildCursorAgentsFleet
|
|
15
|
+
} from "./fleet-platforms.js";
|
|
16
|
+
|
|
17
|
+
const VARIANT_SUFFIX_RE = /-(?:cheap|zen)$/i;
|
|
18
|
+
|
|
19
|
+
const MINION_ROLES = Object.freeze({
|
|
20
|
+
"sdd-apply": "executor",
|
|
21
|
+
"sdd-explore": "explorer",
|
|
22
|
+
"sdd-verify": "verifier",
|
|
23
|
+
"sdd-design": "designer",
|
|
24
|
+
"sdd-propose": "proposer",
|
|
25
|
+
"sdd-spec": "specifier",
|
|
26
|
+
"sdd-tasks": "planner",
|
|
27
|
+
"sdd-archive": "archiver",
|
|
28
|
+
"sdd-onboard": "onboarder",
|
|
29
|
+
"sdd-init": "initializer"
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
async function pathExists(path) {
|
|
33
|
+
try {
|
|
34
|
+
await access(path, fsConstants.F_OK);
|
|
35
|
+
return true;
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function shortModel(model) {
|
|
42
|
+
if (typeof model !== "string" || !model) return null;
|
|
43
|
+
const slash = model.lastIndexOf("/");
|
|
44
|
+
return slash >= 0 ? model.slice(slash + 1) : model;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function agentEntries(agents) {
|
|
48
|
+
if (!agents || typeof agents !== "object" || Array.isArray(agents)) return [];
|
|
49
|
+
return Object.entries(agents).map(([id, raw]) => ({
|
|
50
|
+
id: String(id),
|
|
51
|
+
mode: typeof raw?.mode === "string" ? raw.mode : null,
|
|
52
|
+
model: typeof raw?.model === "string" ? raw.model : null
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function pickOrchestrator(entries) {
|
|
57
|
+
const gentle = entries.find((e) => e.id === "gentle-orchestrator" && e.mode === "primary");
|
|
58
|
+
if (gentle) return gentle;
|
|
59
|
+
return entries.find((e) => e.mode === "primary") ?? null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function isSddMinion(entry, { includeVariants = false } = {}) {
|
|
63
|
+
if (!entry?.id?.startsWith("sdd-")) return false;
|
|
64
|
+
if (entry.mode !== "subagent") return false;
|
|
65
|
+
if (!includeVariants && VARIANT_SUFFIX_RE.test(entry.id)) return false;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function minionRole(id) {
|
|
70
|
+
return MINION_ROLES[id] ?? (id.startsWith("sdd-") ? "specialist" : "minion");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function parseOpenCodeFleet(config, { includeVariants = false } = {}) {
|
|
74
|
+
const defaultModel = typeof config?.model === "string" ? config.model : null;
|
|
75
|
+
const entries = agentEntries(config?.agent ?? config?.agents);
|
|
76
|
+
if (entries.length === 0) {
|
|
77
|
+
return {
|
|
78
|
+
platform: "opencode",
|
|
79
|
+
orchestrator: null,
|
|
80
|
+
minions: [],
|
|
81
|
+
opaque: false,
|
|
82
|
+
writable: true,
|
|
83
|
+
source: "opencode.json"
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const orch = pickOrchestrator(entries);
|
|
88
|
+
const orchModel = orch?.model ?? defaultModel;
|
|
89
|
+
const minions = entries
|
|
90
|
+
.filter((e) => isSddMinion(e, { includeVariants }))
|
|
91
|
+
.map((e) => {
|
|
92
|
+
const model = e.model ?? defaultModel;
|
|
93
|
+
return {
|
|
94
|
+
id: e.id,
|
|
95
|
+
model,
|
|
96
|
+
modelShort: shortModel(model),
|
|
97
|
+
role: minionRole(e.id),
|
|
98
|
+
mode: e.mode
|
|
99
|
+
};
|
|
100
|
+
})
|
|
101
|
+
.sort((a, b) => a.id.localeCompare(b.id));
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
platform: "opencode",
|
|
105
|
+
orchestrator: orch
|
|
106
|
+
? {
|
|
107
|
+
id: orch.id,
|
|
108
|
+
model: orchModel,
|
|
109
|
+
modelShort: shortModel(orchModel),
|
|
110
|
+
mode: orch.mode ?? "primary",
|
|
111
|
+
opaque: false
|
|
112
|
+
}
|
|
113
|
+
: null,
|
|
114
|
+
minions,
|
|
115
|
+
opaque: false,
|
|
116
|
+
writable: true,
|
|
117
|
+
source: "opencode.json"
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function readJson(path, read = readFile) {
|
|
122
|
+
try {
|
|
123
|
+
return JSON.parse(await read(path, "utf8"));
|
|
124
|
+
} catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function buildFleetReport({
|
|
130
|
+
homeDir = resolveHomeDir(),
|
|
131
|
+
includeVariants = false,
|
|
132
|
+
includeActivity = true,
|
|
133
|
+
read = readFile,
|
|
134
|
+
exists = pathExists,
|
|
135
|
+
gentleAvailable = () => isExecutableAvailable("gentle-ai"),
|
|
136
|
+
buildActivity = buildOpenCodeActivity,
|
|
137
|
+
buildClaude = buildClaudeFleet,
|
|
138
|
+
buildCodex = buildCodexFleet,
|
|
139
|
+
buildCursor = buildCursorAgentsFleet
|
|
140
|
+
} = {}) {
|
|
141
|
+
const fleets = [];
|
|
142
|
+
const openCodePath = join(homeDir, ".config", "opencode", "opencode.json");
|
|
143
|
+
if (await exists(openCodePath)) {
|
|
144
|
+
const config = await readJson(openCodePath, read);
|
|
145
|
+
if (config) {
|
|
146
|
+
const fleet = parseOpenCodeFleet(config, { includeVariants });
|
|
147
|
+
fleet.configPath = openCodePath;
|
|
148
|
+
fleets.push(fleet);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (await exists(join(homeDir, ".cursor"))) {
|
|
153
|
+
fleets.push(await buildCursor({ homeDir, read }));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (await exists(join(homeDir, ".claude"))) {
|
|
157
|
+
const fleet = await buildClaude({ homeDir, read });
|
|
158
|
+
if (fleet) fleets.push(fleet);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (await exists(join(homeDir, ".codex"))) {
|
|
162
|
+
const fleet = await buildCodex({ homeDir, read });
|
|
163
|
+
if (fleet) fleets.push(fleet);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const activity = includeActivity
|
|
167
|
+
? await buildActivity({ homeDir })
|
|
168
|
+
: null;
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
ok: true,
|
|
172
|
+
kind: "declared+activity",
|
|
173
|
+
note: "Declared config topology + OpenCode live activity when available.",
|
|
174
|
+
orchestratorAuthority: gentleAvailable() ? "gentle-ai" : null,
|
|
175
|
+
fleets,
|
|
176
|
+
activity,
|
|
177
|
+
generatedAt: new Date().toISOString()
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function formatFleetText(report, { verbose = false } = {}) {
|
|
182
|
+
const lines = ["Fleet floor", ""];
|
|
183
|
+
if (report.orchestratorAuthority) {
|
|
184
|
+
lines.push(`Authority · ${report.orchestratorAuthority}`);
|
|
185
|
+
lines.push("");
|
|
186
|
+
}
|
|
187
|
+
for (const fleet of report.fleets ?? []) {
|
|
188
|
+
const orch = fleet.orchestrator;
|
|
189
|
+
const modelBit = orch?.opaque
|
|
190
|
+
? "opaque · IDE-managed"
|
|
191
|
+
: (orch?.modelShort ?? orch?.model ?? "—");
|
|
192
|
+
const minionCount = (fleet.minions ?? []).length;
|
|
193
|
+
lines.push(`${fleet.platform} · ${orch?.id ?? "—"} · ${modelBit}`);
|
|
194
|
+
if (verbose) {
|
|
195
|
+
for (const m of fleet.minions ?? []) {
|
|
196
|
+
const opaque = m.opaque ? " · opaque" : "";
|
|
197
|
+
lines.push(` ${m.id} · ${m.modelShort ?? m.model ?? "—"} · ${m.role}${opaque}`);
|
|
198
|
+
}
|
|
199
|
+
if (fleet.note) lines.push(` note: ${fleet.note}`);
|
|
200
|
+
} else if (minionCount > 0) {
|
|
201
|
+
lines.push(` ${minionCount} minions · kairo fleet --verbose`);
|
|
202
|
+
}
|
|
203
|
+
lines.push("");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const act = report.activity;
|
|
207
|
+
if (act?.available) {
|
|
208
|
+
const active = (act.agents ?? []).filter((a) => a.state === "active");
|
|
209
|
+
if (active.length === 0) {
|
|
210
|
+
lines.push("Working floor · quiet (no live OpenCode sessions)");
|
|
211
|
+
lines.push("");
|
|
212
|
+
} else {
|
|
213
|
+
lines.push(`Working floor · ${active.length} live`);
|
|
214
|
+
for (const a of active) {
|
|
215
|
+
lines.push(` ● ${a.id} · ${a.modelShort ?? a.model ?? "—"}`);
|
|
216
|
+
}
|
|
217
|
+
lines.push("");
|
|
218
|
+
}
|
|
219
|
+
} else if (act && !act.available) {
|
|
220
|
+
lines.push(`Working floor · unavailable`);
|
|
221
|
+
lines.push("");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if ((report.fleets ?? []).length === 0) {
|
|
225
|
+
lines.push("No agent platforms detected.");
|
|
226
|
+
}
|
|
227
|
+
lines.push(report.note ?? "");
|
|
228
|
+
return lines.join("\n").trimEnd();
|
|
229
|
+
}
|
package/src/global/paths.js
CHANGED
|
@@ -23,7 +23,8 @@ export function harnessHomePaths(homeDir) {
|
|
|
23
23
|
monitorDir: join(root, "monitor"),
|
|
24
24
|
monitorStatePath: join(root, "monitor", "state.json"),
|
|
25
25
|
coreDir: join(root, "core"),
|
|
26
|
-
backupsDir: join(root, "backups")
|
|
26
|
+
backupsDir: join(root, "backups"),
|
|
27
|
+
sessionsDir: join(root, "sessions")
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
|