thoth-agents 0.2.10 → 0.3.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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +21 -0
- package/README.md +301 -311
- package/dist/agents/configured-role-prompt.d.ts +9 -0
- package/dist/agents/prompt-sections.d.ts +8 -4
- package/dist/agents/prompt-utils.d.ts +0 -4
- package/dist/{chunk-YYVE7YHR.js → chunk-2MZ5C2RN.js} +1755 -1760
- package/dist/chunk-XO74DXBZ.js +1781 -0
- package/dist/{chunk-MF5NNCPC.js → chunk-YUCGIJPP.js} +12 -30
- package/dist/cli/claude-code-install.d.ts +24 -26
- package/dist/cli/claude-code-paths.d.ts +0 -28
- package/dist/cli/codex-install.d.ts +2 -2
- package/dist/cli/codex-paths.d.ts +0 -2
- package/dist/cli/config-io.d.ts +5 -0
- package/dist/cli/index.js +294 -133
- package/dist/cli/install.d.ts +5 -1
- package/dist/cli/model-catalog/cache.d.ts +1 -1
- package/dist/cli/operations/claude-code.d.ts +6 -3
- package/dist/cli/operations/codex.d.ts +2 -1
- package/dist/cli/operations/opencode.d.ts +2 -1
- package/dist/cli/operations/types.d.ts +11 -1
- package/dist/cli/package-root.d.ts +1 -0
- package/dist/cli/providers.d.ts +6 -116
- package/dist/cli/skills.d.ts +19 -32
- package/dist/cli/thoth-mem-install.d.ts +45 -0
- package/dist/cli/tui/components/StatusView.d.ts +12 -1
- package/dist/cli/tui/index.js +293 -106
- package/dist/cli/tui/operations.d.ts +4 -3
- package/dist/cli/types.d.ts +0 -10
- package/dist/config/constants.d.ts +20 -16
- package/dist/config/index.d.ts +0 -1
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/schema.d.ts +2 -38
- package/dist/config/utils.d.ts +1 -2
- package/dist/harness/adapters/codex-surfaces.d.ts +3 -3
- package/dist/harness/core/agent-pack.d.ts +37 -29
- package/dist/harness/core/memory-governance.d.ts +24 -48
- package/dist/harness/core/sdd.d.ts +364 -131
- package/dist/harness/generate-integration-packages.d.ts +20 -0
- package/dist/harness/opencode-init-command.d.ts +11 -0
- package/dist/harness/types.d.ts +14 -1
- package/dist/harness/writers/claude-code-subagent.d.ts +3 -1
- package/dist/hooks/index.d.ts +0 -5
- package/dist/index.js +562 -1314
- package/dist/mcp/index.d.ts +1 -2
- package/package.json +17 -12
- package/plugin/.claude-plugin/.thoth-agents-plugin-assets.json +50 -0
- package/plugin/.claude-plugin/plugin.json +8 -0
- package/plugin/.codex-plugin/.thoth-agents-plugin-assets.json +16 -0
- package/plugin/.codex-plugin/plugin.json +7 -0
- package/plugin/.mcp.json +19 -0
- package/plugin/agents/deep.md +89 -0
- package/plugin/agents/designer.md +89 -0
- package/plugin/agents/explorer.md +90 -0
- package/plugin/agents/librarian.md +90 -0
- package/plugin/agents/oracle.md +92 -0
- package/plugin/agents/orchestrator.md +128 -0
- package/plugin/agents/quick.md +89 -0
- package/plugin/codex.mcp.json +17 -0
- package/plugin/settings.json +3 -0
- package/plugin/skills/thoth-archive/SKILL.md +40 -0
- package/plugin/skills/thoth-archive/scripts/archive.mjs +748 -0
- package/plugin/skills/thoth-constitution/SKILL.md +45 -0
- package/plugin/skills/thoth-constitution/scripts/validate.mjs +167 -0
- package/plugin/skills/thoth-constitution/templates/constitution.md +54 -0
- package/plugin/skills/thoth-init/SKILL.md +30 -0
- package/plugin/skills/thoth-init/scripts/init.mjs +141 -0
- package/plugin/skills/thoth-sdd/SKILL.md +83 -0
- package/plugin/skills/thoth-sdd/references/phases/analyze.md +21 -0
- package/plugin/skills/thoth-sdd/references/phases/checklist.md +20 -0
- package/plugin/skills/thoth-sdd/references/phases/clarify.md +15 -0
- package/plugin/skills/thoth-sdd/references/phases/converge.md +14 -0
- package/plugin/skills/thoth-sdd/references/phases/explore.md +10 -0
- package/plugin/skills/thoth-sdd/references/phases/implement.md +19 -0
- package/plugin/skills/thoth-sdd/references/phases/plan.md +15 -0
- package/plugin/skills/thoth-sdd/references/phases/specify.md +21 -0
- package/plugin/skills/thoth-sdd/references/phases/tasks.md +20 -0
- package/plugin/skills/thoth-sdd/references/phases/verify.md +22 -0
- package/plugin/skills/thoth-sdd/scripts/validate.mjs +1117 -0
- package/plugin/skills/thoth-sdd/templates/archive-report.md +25 -0
- package/plugin/skills/thoth-sdd/templates/checklist.md +27 -0
- package/plugin/skills/thoth-sdd/templates/plan.md +38 -0
- package/plugin/skills/thoth-sdd/templates/spec.md +54 -0
- package/plugin/skills/thoth-sdd/templates/tasks.md +29 -0
- package/plugin/skills/thoth-sdd/templates/verify-report.md +28 -0
- package/skills/README.md +12 -0
- package/skills/thoth-archive/SKILL.md +40 -0
- package/skills/thoth-archive/scripts/archive.mjs +748 -0
- package/skills/thoth-constitution/SKILL.md +45 -0
- package/skills/thoth-constitution/scripts/validate.mjs +167 -0
- package/skills/thoth-constitution/templates/constitution.md +54 -0
- package/skills/thoth-init/SKILL.md +30 -0
- package/skills/thoth-init/scripts/init.mjs +141 -0
- package/skills/thoth-sdd/SKILL.md +83 -0
- package/skills/thoth-sdd/references/phases/analyze.md +21 -0
- package/skills/thoth-sdd/references/phases/checklist.md +20 -0
- package/skills/thoth-sdd/references/phases/clarify.md +15 -0
- package/skills/thoth-sdd/references/phases/converge.md +14 -0
- package/skills/thoth-sdd/references/phases/explore.md +10 -0
- package/skills/thoth-sdd/references/phases/implement.md +19 -0
- package/skills/thoth-sdd/references/phases/plan.md +15 -0
- package/skills/thoth-sdd/references/phases/specify.md +21 -0
- package/skills/thoth-sdd/references/phases/tasks.md +20 -0
- package/skills/thoth-sdd/references/phases/verify.md +22 -0
- package/skills/thoth-sdd/scripts/validate.mjs +1117 -0
- package/skills/thoth-sdd/templates/archive-report.md +25 -0
- package/skills/thoth-sdd/templates/checklist.md +27 -0
- package/skills/thoth-sdd/templates/plan.md +38 -0
- package/skills/thoth-sdd/templates/spec.md +54 -0
- package/skills/thoth-sdd/templates/tasks.md +29 -0
- package/skills/thoth-sdd/templates/verify-report.md +28 -0
- package/thoth-agents.schema.json +0 -39
- package/dist/chunk-WBRGPRRB.js +0 -2353
- package/dist/cli/custom-skills.d.ts +0 -48
- package/dist/cli/skill-manifest.d.ts +0 -32
- package/dist/harness/core/skills.d.ts +0 -211
- package/dist/harness/generate-codex-plugin.d.ts +0 -9
- package/dist/harness/writers/claude-code-skill-layout.d.ts +0 -16
- package/dist/harness/writers/fs-skill-collect.d.ts +0 -7
- package/dist/harness/writers/skill-layout.d.ts +0 -16
- package/dist/hooks/chat-headers.d.ts +0 -16
- package/dist/hooks/phase-reminder/index.d.ts +0 -28
- package/dist/hooks/post-read-nudge/index.d.ts +0 -18
- package/dist/hooks/skill-sync.d.ts +0 -10
- package/dist/hooks/thoth-mem/index.d.ts +0 -46
- package/dist/hooks/thoth-mem/protocol.d.ts +0 -7
- package/dist/mcp/thoth.d.ts +0 -3
- package/dist/sdd/artifact-governance/artifact-loader.d.ts +0 -130
- package/dist/sdd/artifact-governance/index.d.ts +0 -6
- package/dist/sdd/artifact-governance/tasks-validator.d.ts +0 -17
- package/dist/sdd/artifact-governance/types.d.ts +0 -52
- package/dist/thoth/client.d.ts +0 -14
- package/dist/thoth/index.d.ts +0 -2
- package/src/skills/_shared/openspec-convention.md +0 -350
- package/src/skills/_shared/persistence-contract.md +0 -163
- package/src/skills/_shared/thoth-mem-convention.md +0 -123
- package/src/skills/executing-plans/SKILL.md +0 -288
- package/src/skills/plan-reviewer/SKILL.md +0 -219
- package/src/skills/requirements-interview/SKILL.md +0 -233
- package/src/skills/sdd-apply/SKILL.md +0 -89
- package/src/skills/sdd-archive/SKILL.md +0 -92
- package/src/skills/sdd-clarify/SKILL.md +0 -105
- package/src/skills/sdd-constitution/SKILL.md +0 -107
- package/src/skills/sdd-design/SKILL.md +0 -155
- package/src/skills/sdd-init/SKILL.md +0 -233
- package/src/skills/sdd-propose/SKILL.md +0 -101
- package/src/skills/sdd-spec/SKILL.md +0 -136
- package/src/skills/sdd-tasks/SKILL.md +0 -232
- package/src/skills/sdd-verify/SKILL.md +0 -131
- package/src/skills/thoth-mem-agents/SKILL.md +0 -210
package/dist/cli/tui/index.js
CHANGED
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
defaultTuiOperations,
|
|
3
3
|
effortChoicesForModel,
|
|
4
4
|
listOperationHarnesses
|
|
5
|
-
} from "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
} from "../../chunk-2MZ5C2RN.js";
|
|
6
|
+
import "../../chunk-XO74DXBZ.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/tui/index.tsx
|
|
9
9
|
import { render } from "ink";
|
|
10
10
|
|
|
11
11
|
// src/cli/tui/App.tsx
|
|
12
12
|
import { Box as Box8, Text as Text8, useApp, useInput } from "ink";
|
|
13
|
-
import { useMemo, useRef, useState } from "react";
|
|
13
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
14
14
|
|
|
15
15
|
// src/cli/tui/components/Header.tsx
|
|
16
16
|
import { Box, Text } from "ink";
|
|
@@ -233,7 +233,7 @@ function ModelScreen({
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
// src/cli/tui/components/PlanPreview.tsx
|
|
236
|
-
import { Box as
|
|
236
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
237
237
|
|
|
238
238
|
// src/cli/tui/components/PathLine.tsx
|
|
239
239
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
@@ -253,81 +253,51 @@ function PathLine({ label, value, width }) {
|
|
|
253
253
|
return /* @__PURE__ */ jsx5(Box5, { flexDirection: "column", children: lines.map((line, index) => /* @__PURE__ */ jsx5(Text5, { color: theme.dim, children: index === 0 ? `${label ? `${label}: ` : ""}${line}` : ` ${line}` }, line)) });
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
-
// src/cli/tui/components/
|
|
257
|
-
import {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
256
|
+
// src/cli/tui/components/StatusView.tsx
|
|
257
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
258
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
259
|
+
var unsupportedEvidence = {
|
|
260
|
+
state: "unsupported",
|
|
261
|
+
source: "none",
|
|
262
|
+
basis: []
|
|
263
|
+
};
|
|
264
|
+
function ProviderCapabilityView({
|
|
265
|
+
evidence,
|
|
266
|
+
loading = false,
|
|
267
|
+
error,
|
|
268
|
+
showHeading = true
|
|
262
269
|
}) {
|
|
270
|
+
const capability = evidence ?? unsupportedEvidence;
|
|
263
271
|
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
264
|
-
/* @__PURE__ */ jsx6(Text6, {
|
|
265
|
-
/* @__PURE__ */ jsx6(Text6, {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
plan.action
|
|
273
|
-
] }),
|
|
274
|
-
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
275
|
-
"Can apply: ",
|
|
276
|
-
plan.canApply ? "yes" : "no"
|
|
277
|
-
] }),
|
|
278
|
-
plan.surfaces.length > 0 ? /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Managed surfaces" }) : null,
|
|
279
|
-
plan.surfaces.map((surface) => /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
272
|
+
showHeading ? /* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: "Provider capability" }) : null,
|
|
273
|
+
loading ? /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Loading provider capability evidence\u2026" }) : error ? /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
274
|
+
/* @__PURE__ */ jsxs5(Text6, { color: theme.warning, children: [
|
|
275
|
+
"Provider evidence unavailable: ",
|
|
276
|
+
error
|
|
277
|
+
] }),
|
|
278
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Press r to retry provider evidence." })
|
|
279
|
+
] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
280
280
|
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
281
|
-
"
|
|
282
|
-
|
|
281
|
+
"Provider capability:",
|
|
282
|
+
" ",
|
|
283
|
+
/* @__PURE__ */ jsx6(Text6, { color: stateColor(capability.state), children: capability.state })
|
|
283
284
|
] }),
|
|
284
|
-
surface.path ? /* @__PURE__ */ jsx6(PathLine, { value: surface.path }) : null
|
|
285
|
-
] }, surface.id)),
|
|
286
|
-
/* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
287
|
-
"Backup: ",
|
|
288
|
-
plan.backup.required ? "required" : "not required",
|
|
289
|
-
" (",
|
|
290
|
-
plan.backup.strategy,
|
|
291
|
-
")"
|
|
292
|
-
] }),
|
|
293
|
-
plan.backup.destinations?.map((path) => /* @__PURE__ */ jsx6(PathLine, { label: path.label, value: path.path }, path.path)),
|
|
294
|
-
plan.items.length > 0 ? /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Preview" }) : null,
|
|
295
|
-
plan.items.slice(0, 5).map((item) => /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
296
285
|
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
297
|
-
"
|
|
298
|
-
|
|
286
|
+
"Evidence source:",
|
|
287
|
+
" ",
|
|
288
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: capability.source })
|
|
299
289
|
] }),
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
"
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
"- [",
|
|
310
|
-
warning.severity,
|
|
311
|
-
"] ",
|
|
312
|
-
warning.message
|
|
313
|
-
] }, warning.code ?? warning.message)),
|
|
314
|
-
plan.disclaimers.map((disclaimer) => /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
315
|
-
"- ",
|
|
316
|
-
disclaimer.message
|
|
317
|
-
] }, disclaimer.code ?? disclaimer.message)),
|
|
318
|
-
/* @__PURE__ */ jsxs5(Box6, { marginTop: 1, children: [
|
|
319
|
-
/* @__PURE__ */ jsx6(Text6, { color: selectedAction === "apply" ? theme.accent : void 0, children: "[Apply]" }),
|
|
320
|
-
/* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
321
|
-
/* @__PURE__ */ jsx6(Text6, { color: selectedAction === "cancel" ? theme.accent : void 0, children: "[Cancel]" })
|
|
322
|
-
] }),
|
|
323
|
-
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Enter selects. a applies. c cancels." }),
|
|
324
|
-
result ? /* @__PURE__ */ jsx6(Text6, { color: result.applied ? theme.ok : theme.warning, children: result.summary }) : null
|
|
290
|
+
capability.basis.length > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
291
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Evidence basis" }),
|
|
292
|
+
capability.basis.map((basis) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
293
|
+
"- ",
|
|
294
|
+
basis
|
|
295
|
+
] }, basis))
|
|
296
|
+
] }) : /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "No provider or harness evidence was supplied." }),
|
|
297
|
+
capability.state !== "supported" ? /* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Refer to the installed provider guidance for authoritative capability details." }) : null
|
|
298
|
+
] })
|
|
325
299
|
] });
|
|
326
300
|
}
|
|
327
|
-
|
|
328
|
-
// src/cli/tui/components/StatusView.tsx
|
|
329
|
-
import { Box as Box7, Text as Text7 } from "ink";
|
|
330
|
-
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
331
301
|
function countByState(report) {
|
|
332
302
|
return report.targets.reduce(
|
|
333
303
|
(counts, target) => {
|
|
@@ -348,10 +318,23 @@ var categoryOrder = [
|
|
|
348
318
|
"Model state",
|
|
349
319
|
"Other"
|
|
350
320
|
];
|
|
321
|
+
function titleCasePart(part) {
|
|
322
|
+
const normalized = part.toLowerCase();
|
|
323
|
+
switch (normalized) {
|
|
324
|
+
case "sdd":
|
|
325
|
+
return "SDD";
|
|
326
|
+
case "cli":
|
|
327
|
+
return "CLI";
|
|
328
|
+
case "mcp":
|
|
329
|
+
return "MCP";
|
|
330
|
+
case "opencode":
|
|
331
|
+
return "OpenCode";
|
|
332
|
+
default:
|
|
333
|
+
return `${part.charAt(0).toUpperCase()}${part.slice(1).toLowerCase()}`;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
351
336
|
function titleCase(value, separator = " ") {
|
|
352
|
-
return value.split(/[-_\s]+/).filter(Boolean).map(
|
|
353
|
-
(part) => part.toLowerCase() === "sdd" ? "SDD" : part.toLowerCase() === "cli" ? "CLI" : part.toLowerCase() === "mcp" ? "MCP" : part.toLowerCase() === "opencode" ? "OpenCode" : `${part.charAt(0).toUpperCase()}${part.slice(1).toLowerCase()}`
|
|
354
|
-
).join(separator);
|
|
337
|
+
return value.split(/[-_\s]+/).filter(Boolean).map(titleCasePart).join(separator);
|
|
355
338
|
}
|
|
356
339
|
function compactPath(path) {
|
|
357
340
|
return path.replaceAll("\\", "/");
|
|
@@ -359,45 +342,56 @@ function compactPath(path) {
|
|
|
359
342
|
function categorizeTarget(target) {
|
|
360
343
|
const path = target.path ? compactPath(target.path) : "";
|
|
361
344
|
const label = target.label ?? target.kind;
|
|
345
|
+
const detail = target.state !== "installed" ? target.observed : void 0;
|
|
362
346
|
const agent = path.match(/thoth-agents-([a-z0-9_-]+)\.toml$/i);
|
|
363
347
|
const skill = path.match(/skills\/([^/]+)\/SKILL\.md$/i);
|
|
364
348
|
if (agent?.[1]) {
|
|
365
349
|
return {
|
|
366
350
|
category: "Agents",
|
|
367
351
|
label: titleCase(agent[1]),
|
|
368
|
-
state: target.state
|
|
352
|
+
state: target.state,
|
|
353
|
+
detail
|
|
369
354
|
};
|
|
370
355
|
}
|
|
371
356
|
if (skill?.[1] || target.kind === "skill") {
|
|
372
357
|
return {
|
|
373
358
|
category: "Skills",
|
|
374
|
-
label:
|
|
375
|
-
state: target.state
|
|
359
|
+
label: skill?.[1] ? titleCase(skill[1], "-") : label,
|
|
360
|
+
state: target.state,
|
|
361
|
+
detail
|
|
376
362
|
};
|
|
377
363
|
}
|
|
378
364
|
if (/marketplace\.json$/i.test(path)) {
|
|
379
365
|
return {
|
|
380
366
|
category: "Marketplace",
|
|
381
367
|
label: "Marketplace",
|
|
382
|
-
state: target.state
|
|
368
|
+
state: target.state,
|
|
369
|
+
detail
|
|
383
370
|
};
|
|
384
371
|
}
|
|
385
372
|
if (/\.mcp\.json$/i.test(path) || /plugin\.json$/i.test(path) || /plugin-assets/i.test(path) || /manifest/i.test(path)) {
|
|
386
373
|
return {
|
|
387
374
|
category: "Plugin/MCP",
|
|
388
375
|
label: titleCase(label.replace(/^codex\s+/i, "")),
|
|
389
|
-
state: target.state
|
|
376
|
+
state: target.state,
|
|
377
|
+
detail
|
|
390
378
|
};
|
|
391
379
|
}
|
|
392
380
|
if (/AGENTS\.md$/i.test(path) || /root instructions/i.test(label)) {
|
|
393
381
|
return {
|
|
394
382
|
category: "Root instructions",
|
|
395
383
|
label: "AGENTS.md",
|
|
396
|
-
state: target.state
|
|
384
|
+
state: target.state,
|
|
385
|
+
detail
|
|
397
386
|
};
|
|
398
387
|
}
|
|
399
388
|
if (/config\.toml$/i.test(path) || target.kind === "config") {
|
|
400
|
-
return {
|
|
389
|
+
return {
|
|
390
|
+
category: "Config",
|
|
391
|
+
label: titleCase(label),
|
|
392
|
+
state: target.state,
|
|
393
|
+
detail
|
|
394
|
+
};
|
|
401
395
|
}
|
|
402
396
|
if (target.kind === "memory-state" || /model/i.test(label)) {
|
|
403
397
|
return {
|
|
@@ -433,7 +427,12 @@ function uniqueTargets(targets) {
|
|
|
433
427
|
return true;
|
|
434
428
|
});
|
|
435
429
|
}
|
|
436
|
-
function StatusView({
|
|
430
|
+
function StatusView({
|
|
431
|
+
report,
|
|
432
|
+
providerEvidence = report.providerCapability,
|
|
433
|
+
providerEvidenceLoading = false,
|
|
434
|
+
providerEvidenceError
|
|
435
|
+
}) {
|
|
437
436
|
const counts = countByState(report);
|
|
438
437
|
const countText = Object.entries(counts).map(([state, count]) => `${state}: ${count}`).join(" ");
|
|
439
438
|
const grouped = groupedTargets(report);
|
|
@@ -441,68 +440,92 @@ function StatusView({ report }) {
|
|
|
441
440
|
const hiddenWarnings = report.diagnostics.length - warnings.length;
|
|
442
441
|
const notes = (report.disclaimers ?? []).slice(0, 2);
|
|
443
442
|
const hiddenNotes = (report.disclaimers?.length ?? 0) - notes.length;
|
|
444
|
-
return /* @__PURE__ */
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
"
|
|
447
|
-
|
|
443
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
444
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
445
|
+
"Consumer-managed state:",
|
|
446
|
+
" ",
|
|
447
|
+
/* @__PURE__ */ jsx6(Text6, { color: stateColor(report.state), children: report.state })
|
|
448
448
|
] }),
|
|
449
|
-
/* @__PURE__ */
|
|
450
|
-
/* @__PURE__ */
|
|
451
|
-
/* @__PURE__ */
|
|
449
|
+
/* @__PURE__ */ jsx6(Text6, { children: report.summary }),
|
|
450
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: countText || "No managed targets." }),
|
|
451
|
+
/* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
452
452
|
"Warnings: ",
|
|
453
453
|
report.diagnostics.length,
|
|
454
454
|
" Notes:",
|
|
455
455
|
" ",
|
|
456
456
|
report.disclaimers?.length ?? 0
|
|
457
457
|
] }),
|
|
458
|
+
/* @__PURE__ */ jsx6(
|
|
459
|
+
ProviderCapabilityView,
|
|
460
|
+
{
|
|
461
|
+
evidence: providerEvidence,
|
|
462
|
+
loading: providerEvidenceLoading,
|
|
463
|
+
error: providerEvidenceError
|
|
464
|
+
}
|
|
465
|
+
),
|
|
466
|
+
report.actions.some((action) => action.supported === false) ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
467
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.warning, children: "Unavailable provider-dependent actions" }),
|
|
468
|
+
report.actions.filter((action) => action.supported === false).map((action) => /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
469
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
470
|
+
action.label,
|
|
471
|
+
": unavailable"
|
|
472
|
+
] }),
|
|
473
|
+
action.disabledReason ? /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
474
|
+
"- ",
|
|
475
|
+
action.disabledReason
|
|
476
|
+
] }) : null
|
|
477
|
+
] }, action.id))
|
|
478
|
+
] }) : null,
|
|
458
479
|
categoryOrder.map((category) => {
|
|
459
480
|
const targets = uniqueTargets(grouped.get(category) ?? []);
|
|
460
481
|
if (targets.length === 0) return null;
|
|
461
482
|
const visible = targets.slice(0, 6);
|
|
462
483
|
const hidden = targets.length - visible.length;
|
|
463
|
-
return /* @__PURE__ */
|
|
464
|
-
/* @__PURE__ */
|
|
465
|
-
visible.map((target) => /* @__PURE__ */
|
|
484
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
485
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.accent, children: category }),
|
|
486
|
+
visible.map((target) => /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
466
487
|
"- ",
|
|
467
488
|
target.label,
|
|
468
|
-
target.state ? /* @__PURE__ */
|
|
489
|
+
target.state ? /* @__PURE__ */ jsxs5(Text6, { color: stateColor(target.state), children: [
|
|
469
490
|
": [",
|
|
470
491
|
target.state,
|
|
471
492
|
"]"
|
|
472
493
|
] }) : null,
|
|
473
|
-
target.detail ? /* @__PURE__ */
|
|
494
|
+
target.detail ? /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
474
495
|
" - ",
|
|
475
496
|
target.detail
|
|
476
497
|
] }) : null
|
|
477
498
|
] }, `${category}-${target.label}-${target.state}`)),
|
|
478
|
-
hidden > 0 ? /* @__PURE__ */
|
|
499
|
+
hidden > 0 ? /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
479
500
|
" +",
|
|
480
501
|
hidden,
|
|
481
502
|
" more"
|
|
482
503
|
] }) : null
|
|
483
504
|
] }, category);
|
|
484
505
|
}),
|
|
485
|
-
report.diagnostics.length > 0 ? /* @__PURE__ */
|
|
486
|
-
/* @__PURE__ */
|
|
487
|
-
warnings.map((warning) => /* @__PURE__ */
|
|
506
|
+
report.diagnostics.length > 0 ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
507
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.warning, children: "Warnings" }),
|
|
508
|
+
warnings.map((warning) => /* @__PURE__ */ jsxs5(Text6, { color: theme.warning, children: [
|
|
488
509
|
"- [",
|
|
489
510
|
warning.severity,
|
|
490
|
-
"]
|
|
511
|
+
"]",
|
|
512
|
+
warning.code ? ` [${warning.code}]` : "",
|
|
513
|
+
" ",
|
|
491
514
|
warning.message
|
|
492
515
|
] }, warning.code ?? warning.message)),
|
|
493
|
-
hiddenWarnings > 0 ? /* @__PURE__ */
|
|
516
|
+
hiddenWarnings > 0 ? /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
494
517
|
" +",
|
|
495
518
|
hiddenWarnings,
|
|
496
519
|
" more warnings"
|
|
497
520
|
] }) : null
|
|
498
521
|
] }) : null,
|
|
499
|
-
notes.length > 0 ? /* @__PURE__ */
|
|
500
|
-
/* @__PURE__ */
|
|
501
|
-
notes.map((note) => /* @__PURE__ */
|
|
522
|
+
notes.length > 0 ? /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
523
|
+
/* @__PURE__ */ jsx6(Text6, { color: theme.dim, children: "Notes" }),
|
|
524
|
+
notes.map((note) => /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
502
525
|
"- ",
|
|
503
526
|
note.message
|
|
504
527
|
] }, note.code ?? note.message)),
|
|
505
|
-
hiddenNotes > 0 ? /* @__PURE__ */
|
|
528
|
+
hiddenNotes > 0 ? /* @__PURE__ */ jsxs5(Text6, { color: theme.dim, children: [
|
|
506
529
|
" +",
|
|
507
530
|
hiddenNotes,
|
|
508
531
|
" more notes"
|
|
@@ -511,6 +534,134 @@ function StatusView({ report }) {
|
|
|
511
534
|
] });
|
|
512
535
|
}
|
|
513
536
|
|
|
537
|
+
// src/cli/tui/components/PlanPreview.tsx
|
|
538
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
539
|
+
function targetText(target) {
|
|
540
|
+
const label = target.label ?? target.path ?? target.kind;
|
|
541
|
+
const state = target.state ? `: [${target.state}]` : "";
|
|
542
|
+
const observed = target.observed ? ` - ${target.observed}` : "";
|
|
543
|
+
return `${label}${state}${observed}`;
|
|
544
|
+
}
|
|
545
|
+
function warningText(warning) {
|
|
546
|
+
return `[${warning.severity}]${warning.code ? ` [${warning.code}]` : ""} ${warning.message}`;
|
|
547
|
+
}
|
|
548
|
+
function providerEvidenceFor(value) {
|
|
549
|
+
return value.providerCapability;
|
|
550
|
+
}
|
|
551
|
+
function PlanPreview({
|
|
552
|
+
plan,
|
|
553
|
+
selectedAction,
|
|
554
|
+
result
|
|
555
|
+
}) {
|
|
556
|
+
const blockerTargets = plan.blockerTargets ?? [];
|
|
557
|
+
const providerEvidence = providerEvidenceFor(result ?? plan);
|
|
558
|
+
return /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
559
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: plan.title }),
|
|
560
|
+
/* @__PURE__ */ jsx7(Text7, { children: plan.summary }),
|
|
561
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: "Consumer operation" }),
|
|
562
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
563
|
+
"Target harness: ",
|
|
564
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.accent, children: plan.harness })
|
|
565
|
+
] }),
|
|
566
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
567
|
+
"Managed action: ",
|
|
568
|
+
plan.action
|
|
569
|
+
] }),
|
|
570
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
571
|
+
"Can apply: ",
|
|
572
|
+
plan.canApply ? "yes" : "no"
|
|
573
|
+
] }),
|
|
574
|
+
providerEvidence ? /* @__PURE__ */ jsx7(ProviderCapabilityView, { evidence: providerEvidence }) : null,
|
|
575
|
+
!plan.canApply && blockerTargets.length > 0 ? /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
576
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warning, children: "Blocker targets" }),
|
|
577
|
+
blockerTargets.map((target, index) => /* @__PURE__ */ jsxs6(
|
|
578
|
+
Text7,
|
|
579
|
+
{
|
|
580
|
+
children: [
|
|
581
|
+
"- ",
|
|
582
|
+
targetText(target)
|
|
583
|
+
]
|
|
584
|
+
},
|
|
585
|
+
`${target.label ?? target.path ?? target.kind}-${index}`
|
|
586
|
+
))
|
|
587
|
+
] }) : null,
|
|
588
|
+
plan.surfaces.length > 0 ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Managed surfaces" }) : null,
|
|
589
|
+
plan.surfaces.map((surface) => /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
590
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
591
|
+
"- ",
|
|
592
|
+
surface.label
|
|
593
|
+
] }),
|
|
594
|
+
surface.path ? /* @__PURE__ */ jsx7(PathLine, { value: surface.path }) : null
|
|
595
|
+
] }, surface.id)),
|
|
596
|
+
/* @__PURE__ */ jsxs6(Text7, { color: theme.dim, children: [
|
|
597
|
+
"Backup: ",
|
|
598
|
+
plan.backup.required ? "required" : "not required",
|
|
599
|
+
" (",
|
|
600
|
+
plan.backup.strategy,
|
|
601
|
+
")"
|
|
602
|
+
] }),
|
|
603
|
+
plan.backup.destinations?.map((path) => /* @__PURE__ */ jsx7(PathLine, { label: path.label, value: path.path }, path.path)),
|
|
604
|
+
plan.items.length > 0 ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Preview" }) : null,
|
|
605
|
+
plan.items.slice(0, 5).map((item) => /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
606
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
607
|
+
"- ",
|
|
608
|
+
item.title
|
|
609
|
+
] }),
|
|
610
|
+
item.target.path ? /* @__PURE__ */ jsx7(PathLine, { value: item.target.path }) : null,
|
|
611
|
+
item.preview ? /* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: item.preview.length > 120 ? `${item.preview.slice(0, 120)}...` : item.preview }) : null
|
|
612
|
+
] }, item.title)),
|
|
613
|
+
plan.items.length > 5 ? /* @__PURE__ */ jsxs6(Text7, { color: theme.dim, children: [
|
|
614
|
+
"...",
|
|
615
|
+
plan.items.length - 5,
|
|
616
|
+
" more items"
|
|
617
|
+
] }) : null,
|
|
618
|
+
plan.warnings.map((warning) => /* @__PURE__ */ jsxs6(Text7, { color: theme.warning, children: [
|
|
619
|
+
"- ",
|
|
620
|
+
warningText(warning)
|
|
621
|
+
] }, warning.code ?? warning.message)),
|
|
622
|
+
plan.disclaimers.map((disclaimer) => /* @__PURE__ */ jsxs6(Text7, { color: theme.dim, children: [
|
|
623
|
+
"- ",
|
|
624
|
+
disclaimer.message
|
|
625
|
+
] }, disclaimer.code ?? disclaimer.message)),
|
|
626
|
+
/* @__PURE__ */ jsxs6(Box7, { marginTop: 1, children: [
|
|
627
|
+
/* @__PURE__ */ jsx7(Text7, { color: selectedAction === "apply" ? theme.accent : void 0, children: "[Apply]" }),
|
|
628
|
+
/* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
629
|
+
/* @__PURE__ */ jsx7(Text7, { color: selectedAction === "cancel" ? theme.accent : void 0, children: "[Cancel]" })
|
|
630
|
+
] }),
|
|
631
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.dim, children: "Enter selects. a applies. c cancels." }),
|
|
632
|
+
result ? /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
633
|
+
/* @__PURE__ */ jsxs6(Text7, { color: result.applied ? theme.ok : theme.warning, children: [
|
|
634
|
+
"Consumer result: ",
|
|
635
|
+
result.summary
|
|
636
|
+
] }),
|
|
637
|
+
!result.applied && ((result.diagnosticTargets?.length ?? 0) > 0 || result.warnings.length > 0) ? /* @__PURE__ */ jsxs6(Box7, { flexDirection: "column", children: [
|
|
638
|
+
/* @__PURE__ */ jsx7(Text7, { color: theme.warning, children: "Apply diagnostics" }),
|
|
639
|
+
result.diagnosticTargets?.map((target, index) => /* @__PURE__ */ jsxs6(
|
|
640
|
+
Text7,
|
|
641
|
+
{
|
|
642
|
+
children: [
|
|
643
|
+
"- ",
|
|
644
|
+
targetText(target)
|
|
645
|
+
]
|
|
646
|
+
},
|
|
647
|
+
`${target.label ?? target.path ?? target.kind}-${index}`
|
|
648
|
+
)),
|
|
649
|
+
result.warnings.map((warning) => /* @__PURE__ */ jsxs6(
|
|
650
|
+
Text7,
|
|
651
|
+
{
|
|
652
|
+
color: theme.warning,
|
|
653
|
+
children: [
|
|
654
|
+
"- ",
|
|
655
|
+
warningText(warning)
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
warning.code ?? warning.message
|
|
659
|
+
))
|
|
660
|
+
] }) : null
|
|
661
|
+
] }) : null
|
|
662
|
+
] });
|
|
663
|
+
}
|
|
664
|
+
|
|
514
665
|
// src/cli/tui/App.tsx
|
|
515
666
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
516
667
|
var rootItems = [
|
|
@@ -671,6 +822,10 @@ function App({
|
|
|
671
822
|
const [activeHarness, setActiveHarness] = useState("opencode");
|
|
672
823
|
const [activeAction, setActiveAction] = useState("update");
|
|
673
824
|
const [reportVersion, setReportVersion] = useState(0);
|
|
825
|
+
const [providerEvidence, setProviderEvidence] = useState();
|
|
826
|
+
const [providerEvidenceLoading, setProviderEvidenceLoading] = useState(false);
|
|
827
|
+
const [providerEvidenceError, setProviderEvidenceError] = useState();
|
|
828
|
+
const providerEvidenceRequest = useRef(0);
|
|
674
829
|
const [plan, setPlan] = useState();
|
|
675
830
|
const [result, setResult] = useState();
|
|
676
831
|
const [previewAction, setPreviewAction] = useState(
|
|
@@ -693,6 +848,30 @@ function App({
|
|
|
693
848
|
const [editDraft, setEditDraft] = useState("");
|
|
694
849
|
const [modelResult, setModelResult] = useState();
|
|
695
850
|
const report = view === "status" || view === "manageHarness" ? operations.status(activeHarness) : void 0;
|
|
851
|
+
useEffect(() => {
|
|
852
|
+
if (view !== "status" || !operations.providerCapability) return;
|
|
853
|
+
const request = providerEvidenceRequest.current + 1;
|
|
854
|
+
providerEvidenceRequest.current = request;
|
|
855
|
+
setProviderEvidence(void 0);
|
|
856
|
+
setProviderEvidenceLoading(true);
|
|
857
|
+
setProviderEvidenceError(void 0);
|
|
858
|
+
void operations.providerCapability(activeHarness).then((evidence) => {
|
|
859
|
+
if (providerEvidenceRequest.current !== request) return;
|
|
860
|
+
setProviderEvidence(evidence);
|
|
861
|
+
setProviderEvidenceLoading(false);
|
|
862
|
+
}).catch((error) => {
|
|
863
|
+
if (providerEvidenceRequest.current !== request) return;
|
|
864
|
+
setProviderEvidenceError(
|
|
865
|
+
error instanceof Error ? error.message : String(error)
|
|
866
|
+
);
|
|
867
|
+
setProviderEvidenceLoading(false);
|
|
868
|
+
});
|
|
869
|
+
return () => {
|
|
870
|
+
if (providerEvidenceRequest.current === request) {
|
|
871
|
+
providerEvidenceRequest.current += 1;
|
|
872
|
+
}
|
|
873
|
+
};
|
|
874
|
+
}, [activeHarness, operations, reportVersion, view]);
|
|
696
875
|
const currentManageItems = report?.state === "missing" ? installManageItems : manageItems;
|
|
697
876
|
const modelRows = modelRoles.map((role) => {
|
|
698
877
|
const model = editedModels[role.role] ?? role.model;
|
|
@@ -1258,10 +1437,18 @@ function App({
|
|
|
1258
1437
|
Header,
|
|
1259
1438
|
{
|
|
1260
1439
|
title: `${report.displayName ?? activeHarness} Status`,
|
|
1261
|
-
subtitle: "
|
|
1440
|
+
subtitle: "Consumer-managed state and external provider evidence. Escape returns. r refreshes."
|
|
1262
1441
|
}
|
|
1263
1442
|
),
|
|
1264
|
-
/* @__PURE__ */ jsx8(
|
|
1443
|
+
/* @__PURE__ */ jsx8(
|
|
1444
|
+
StatusView,
|
|
1445
|
+
{
|
|
1446
|
+
report,
|
|
1447
|
+
providerEvidence: operations.providerCapability ? providerEvidence : report.providerCapability,
|
|
1448
|
+
providerEvidenceLoading,
|
|
1449
|
+
providerEvidenceError
|
|
1450
|
+
}
|
|
1451
|
+
)
|
|
1265
1452
|
] }, reportVersion);
|
|
1266
1453
|
}
|
|
1267
1454
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { HarnessId } from '../../harness/types';
|
|
1
|
+
import type { HarnessId, ProviderCapabilityEvidence, ProviderEvidenceInput } from '../../harness/types';
|
|
2
2
|
import { type ClaudeCodeOperationContext } from '../operations/claude-code';
|
|
3
3
|
import { type CodexOperationContext } from '../operations/codex';
|
|
4
4
|
import type { HarnessStatusReport, ModelRoleInput, OperationApplyResult, OperationPlan } from '../operations/types';
|
|
5
5
|
import { type ModelOption } from './model-catalog';
|
|
6
6
|
export type TuiAction = 'status' | 'list' | 'install' | 'update' | 'sync' | 'model';
|
|
7
7
|
export interface TuiOperations {
|
|
8
|
-
status(harness: HarnessId): HarnessStatusReport;
|
|
8
|
+
status(harness: HarnessId, evidence?: ProviderEvidenceInput): HarnessStatusReport;
|
|
9
|
+
providerCapability?(harness: HarnessId): Promise<ProviderCapabilityEvidence>;
|
|
9
10
|
modelRoles(harness: HarnessId): ModelRoleInput[];
|
|
10
11
|
modelOptions(harness: HarnessId): Promise<ModelOption[]>;
|
|
11
12
|
plan(harness: HarnessId, action: Exclude<TuiAction, 'status' | 'list'>): OperationPlan;
|
|
@@ -15,6 +16,6 @@ export interface TuiOperations {
|
|
|
15
16
|
export declare const opencodeModelRoles: ModelRoleInput[];
|
|
16
17
|
export declare const codexModelRoles: ModelRoleInput[];
|
|
17
18
|
export declare function getCodexModelRoles(source?: CodexOperationContext): ModelRoleInput[];
|
|
18
|
-
export declare function getClaudeCodeModelRoles(
|
|
19
|
+
export declare function getClaudeCodeModelRoles(_source?: ClaudeCodeOperationContext): ModelRoleInput[];
|
|
19
20
|
export declare function getOpenCodeModelRoles(): ModelRoleInput[];
|
|
20
21
|
export declare const defaultTuiOperations: TuiOperations;
|
package/dist/cli/types.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export interface InstallArgs {
|
|
|
4
4
|
tui: boolean;
|
|
5
5
|
agent?: InstallAgent;
|
|
6
6
|
tmux?: BooleanArg;
|
|
7
|
-
skills?: BooleanArg;
|
|
8
7
|
dryRun?: boolean;
|
|
9
8
|
reset?: boolean;
|
|
10
9
|
}
|
|
@@ -54,8 +53,6 @@ export interface OpenCodeConfig {
|
|
|
54
53
|
export interface InstallConfig {
|
|
55
54
|
agent: InstallAgent;
|
|
56
55
|
hasTmux: boolean;
|
|
57
|
-
installSkills: boolean;
|
|
58
|
-
installCustomSkills: boolean;
|
|
59
56
|
dryRun?: boolean;
|
|
60
57
|
reset: boolean;
|
|
61
58
|
}
|
|
@@ -66,14 +63,7 @@ export interface ConfigMergeResult {
|
|
|
66
63
|
}
|
|
67
64
|
export interface DetectedConfig {
|
|
68
65
|
isInstalled: boolean;
|
|
69
|
-
hasKimi: boolean;
|
|
70
66
|
hasOpenAI: boolean;
|
|
71
|
-
hasAnthropic?: boolean;
|
|
72
|
-
hasCopilot?: boolean;
|
|
73
|
-
hasZaiPlan?: boolean;
|
|
74
|
-
hasAntigravity: boolean;
|
|
75
|
-
hasChutes?: boolean;
|
|
76
|
-
hasOpencodeZen: boolean;
|
|
77
67
|
hasTmux: boolean;
|
|
78
68
|
}
|
|
79
69
|
import type { EffortSelection } from './model-effort';
|