@mono-agent/agent-app 0.5.0 → 0.6.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/README.md +5 -0
- package/dist/adapter-send-tools.d.ts +7 -7
- package/dist/adapter-send-tools.d.ts.map +1 -1
- package/dist/adapter-send-tools.js +59 -50
- package/dist/adapter-send-tools.js.map +1 -1
- package/dist/app.js +8 -8
- package/dist/app.js.map +1 -1
- package/dist/background.d.ts +4 -0
- package/dist/background.d.ts.map +1 -1
- package/dist/background.js +8 -3
- package/dist/background.js.map +1 -1
- package/dist/channel-fact-format.d.ts +12 -0
- package/dist/channel-fact-format.d.ts.map +1 -0
- package/dist/channel-fact-format.js +24 -0
- package/dist/channel-fact-format.js.map +1 -0
- package/dist/channels.js +3 -3
- package/dist/channels.js.map +1 -1
- package/dist/cli.d.ts +14 -10
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +198 -181
- package/dist/cli.js.map +1 -1
- package/dist/config-reference.js +4 -4
- package/dist/config-reference.js.map +1 -1
- package/dist/consumer-contract.d.ts.map +1 -1
- package/dist/consumer-contract.js +5 -3
- package/dist/consumer-contract.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +126 -5
- package/dist/doctor.js.map +1 -1
- package/dist/init.d.ts +11 -22
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +25 -116
- package/dist/init.js.map +1 -1
- package/dist/interaction-bridge.d.ts +3 -3
- package/dist/interaction-bridge.d.ts.map +1 -1
- package/dist/memory-recall.d.ts +2 -2
- package/dist/memory-recall.d.ts.map +1 -1
- package/dist/memory-recall.js +3 -3
- package/dist/memory-recall.js.map +1 -1
- package/dist/modules/base.d.ts +25 -0
- package/dist/modules/base.d.ts.map +1 -0
- package/dist/{recipes → modules}/base.js +16 -11
- package/dist/modules/base.js.map +1 -0
- package/dist/modules/catalog.d.ts +12 -0
- package/dist/modules/catalog.d.ts.map +1 -0
- package/dist/modules/catalog.js +412 -0
- package/dist/modules/catalog.js.map +1 -0
- package/dist/modules/index.d.ts +8 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +5 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/known-tools.d.ts +44 -0
- package/dist/modules/known-tools.d.ts.map +1 -0
- package/dist/modules/known-tools.js +88 -0
- package/dist/modules/known-tools.js.map +1 -0
- package/dist/modules/types.d.ts +73 -0
- package/dist/modules/types.d.ts.map +1 -0
- package/dist/{recipes → modules}/types.js +3 -3
- package/dist/{recipes → modules}/types.js.map +1 -1
- package/dist/posted-message-index.d.ts +2 -2
- package/dist/posted-message-index.js +2 -2
- package/dist/wizard/answers.d.ts +85 -0
- package/dist/wizard/answers.d.ts.map +1 -0
- package/dist/wizard/answers.js +231 -0
- package/dist/wizard/answers.js.map +1 -0
- package/dist/wizard/from-flags.d.ts +26 -0
- package/dist/wizard/from-flags.d.ts.map +1 -0
- package/dist/wizard/from-flags.js +44 -0
- package/dist/wizard/from-flags.js.map +1 -0
- package/dist/wizard/index.d.ts +11 -0
- package/dist/wizard/index.d.ts.map +1 -0
- package/dist/wizard/index.js +6 -0
- package/dist/wizard/index.js.map +1 -0
- package/dist/wizard/presets.d.ts +40 -0
- package/dist/wizard/presets.d.ts.map +1 -0
- package/dist/wizard/presets.js +85 -0
- package/dist/wizard/presets.js.map +1 -0
- package/dist/wizard/prompts.d.ts +52 -0
- package/dist/wizard/prompts.d.ts.map +1 -0
- package/dist/wizard/prompts.js +141 -0
- package/dist/wizard/prompts.js.map +1 -0
- package/dist/wizard/run.d.ts +19 -0
- package/dist/wizard/run.d.ts.map +1 -0
- package/dist/wizard/run.js +345 -0
- package/dist/wizard/run.js.map +1 -0
- package/package.json +17 -16
- package/schema/mono-agent.config.schema.json +5 -3
- package/skills/mono-agent-composer/SKILL.md +7 -7
- package/skills/mono-agent-composer/references/config-blueprint.md +7 -7
- package/skills/mono-agent-composer/references/discovery-questions.md +8 -6
- package/skills/mono-agent-composer/references/feature-coverage.md +10 -8
- package/skills/mono-agent-composer/references/package-map.md +5 -5
- package/skills/mono-agent-composer/references/playbooks.md +22 -22
- package/skills/mono-agent-composer/references/validation.md +3 -3
- package/dist/recipes/base.d.ts +0 -15
- package/dist/recipes/base.d.ts.map +0 -1
- package/dist/recipes/base.js.map +0 -1
- package/dist/recipes/catalog.d.ts +0 -4
- package/dist/recipes/catalog.d.ts.map +0 -1
- package/dist/recipes/catalog.js +0 -525
- package/dist/recipes/catalog.js.map +0 -1
- package/dist/recipes/index.d.ts +0 -11
- package/dist/recipes/index.d.ts.map +0 -1
- package/dist/recipes/index.js +0 -14
- package/dist/recipes/index.js.map +0 -1
- package/dist/recipes/types.d.ts +0 -70
- package/dist/recipes/types.d.ts.map +0 -1
- package/dist/setup.d.ts +0 -29
- package/dist/setup.d.ts.map +0 -1
- package/dist/setup.js +0 -97
- package/dist/setup.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createInterface } from "node:readline/promises";
|
|
3
2
|
import { stat } from "node:fs/promises";
|
|
4
3
|
import { createRequire } from "node:module";
|
|
5
4
|
import { basename, resolve } from "node:path";
|
|
@@ -14,16 +13,19 @@ import { runAuditRuns } from "./audit-runs.js";
|
|
|
14
13
|
import { runBackfill } from "./backfill.js";
|
|
15
14
|
import { defaultBackgroundDeps, resolveInstanceTarget, restartBackground, startBackground, statusBackground, stopBackground, tailLogs, } from "./background.js";
|
|
16
15
|
import { collectChannelConfigViews } from "./channel-config-view.js";
|
|
16
|
+
import { formatChannelFactValue } from "./channel-fact-format.js";
|
|
17
17
|
import { resolveChannelDrivers } from "./channels.js";
|
|
18
18
|
import { findUnknownAppConfigWarnings } from "./config-reference.js";
|
|
19
19
|
import { validateMonoAgentFolder } from "./doctor.js";
|
|
20
|
-
import { initMonoAgentFolder
|
|
20
|
+
import { initMonoAgentFolder } from "./init.js";
|
|
21
21
|
import { installComposerSkill } from "./install-skill.js";
|
|
22
22
|
import { runMetrics } from "./metrics.js";
|
|
23
|
-
import { findRecipe, RECIPE_CATALOG, recipeIds, resolveRecipeInputs } from "./recipes/index.js";
|
|
24
23
|
import { buildRunsHealthDisplay, RUNS_HEALTH_MAX_RUNS } from "./runs-health.js";
|
|
25
24
|
import { purgeSessions } from "./sessions.js";
|
|
26
|
-
import {
|
|
25
|
+
import { composeWizardPlan } from "./wizard/answers.js";
|
|
26
|
+
import { answersFromCli, isWithChannel } from "./wizard/from-flags.js";
|
|
27
|
+
import { findPreset, PRESET_CATALOG, presetAnswers, presetIds, RECIPE_TO_PRESET } from "./wizard/presets.js";
|
|
28
|
+
import { runInitWizard } from "./wizard/run.js";
|
|
27
29
|
import * as ui from "./ui.js";
|
|
28
30
|
const DEFAULT_LOG_LINES = 200;
|
|
29
31
|
// Node's maximum setInterval/setTimeout delay (2^31 - 1 ms, ~24.8 days). A
|
|
@@ -31,7 +33,7 @@ const DEFAULT_LOG_LINES = 200;
|
|
|
31
33
|
// busy-waiting; larger values silently overflow to a 1ms delay.
|
|
32
34
|
const KEEP_ALIVE_INTERVAL_MS = 2_147_483_647;
|
|
33
35
|
const BACKGROUND_COMMANDS = ["start", "restart", "stop", "status", "logs"];
|
|
34
|
-
const KNOWN_COMMANDS = ["init", "setup", "validate", "doctor", "config", "recipes", "start", "restart", "stop", "status", "logs", "tui", "web", "install-skill", "backfill", "audit-runs", "metrics", "memory"];
|
|
36
|
+
const KNOWN_COMMANDS = ["init", "setup", "validate", "doctor", "config", "recipes", "presets", "start", "restart", "stop", "status", "logs", "tui", "web", "install-skill", "backfill", "audit-runs", "metrics", "memory"];
|
|
35
37
|
export function parseCliArgs(argv) {
|
|
36
38
|
const [command, ...rest] = argv;
|
|
37
39
|
if (command === undefined || command === "help" || command === "--help" || command === "-h") {
|
|
@@ -43,16 +45,25 @@ export function parseCliArgs(argv) {
|
|
|
43
45
|
if (!KNOWN_COMMANDS.includes(command)) {
|
|
44
46
|
throw new Error(`Unknown command \`${command}\`. Expected ${KNOWN_COMMANDS.join(", ")}.`);
|
|
45
47
|
}
|
|
46
|
-
// `doctor`
|
|
47
|
-
//
|
|
48
|
-
|
|
48
|
+
// `doctor`/`setup`/`recipes` are aliases; normalize here so every downstream
|
|
49
|
+
// path (routing, env-file resolution, --consumer) applies unchanged. `doctor`
|
|
50
|
+
// → `validate`, `setup` → `init`, `recipes` → `presets`.
|
|
51
|
+
const cmd = (command === "doctor"
|
|
52
|
+
? "validate"
|
|
53
|
+
: command === "setup"
|
|
54
|
+
? "init"
|
|
55
|
+
: command === "recipes"
|
|
56
|
+
? "presets"
|
|
57
|
+
: command);
|
|
49
58
|
const isLogs = cmd === "logs";
|
|
50
59
|
let configPath;
|
|
51
60
|
let model;
|
|
52
61
|
let fallbackModels;
|
|
53
62
|
let memory;
|
|
63
|
+
let preset;
|
|
54
64
|
let recipe;
|
|
55
65
|
let withChannels;
|
|
66
|
+
let yes = false;
|
|
56
67
|
const positionals = [];
|
|
57
68
|
let envFile;
|
|
58
69
|
let target;
|
|
@@ -191,9 +202,15 @@ export function parseCliArgs(argv) {
|
|
|
191
202
|
memory = raw;
|
|
192
203
|
break;
|
|
193
204
|
}
|
|
205
|
+
case "--preset":
|
|
206
|
+
preset = requireValue(rest, ++i, flag);
|
|
207
|
+
break;
|
|
194
208
|
case "--recipe":
|
|
195
209
|
recipe = requireValue(rest, ++i, flag);
|
|
196
210
|
break;
|
|
211
|
+
case "--yes":
|
|
212
|
+
yes = true;
|
|
213
|
+
break;
|
|
197
214
|
case "--with":
|
|
198
215
|
withChannels = requireValue(rest, ++i, flag)
|
|
199
216
|
.split(",")
|
|
@@ -269,8 +286,10 @@ export function parseCliArgs(argv) {
|
|
|
269
286
|
...(model === undefined ? {} : { model }),
|
|
270
287
|
...(fallbackModels === undefined ? {} : { fallbackModels }),
|
|
271
288
|
...(memory === undefined ? {} : { memory }),
|
|
289
|
+
...(preset === undefined ? {} : { preset }),
|
|
272
290
|
...(recipe === undefined ? {} : { recipe }),
|
|
273
291
|
...(withChannels === undefined ? {} : { withChannels }),
|
|
292
|
+
...(yes ? { yes } : {}),
|
|
274
293
|
positionals,
|
|
275
294
|
...(envFile === undefined ? {} : { envFile }),
|
|
276
295
|
...(target === undefined ? {} : { target }),
|
|
@@ -331,36 +350,32 @@ function requireValue(args, index, flag) {
|
|
|
331
350
|
}
|
|
332
351
|
const HELP_COMMANDS = [
|
|
333
352
|
{
|
|
334
|
-
signature: "mono-agent init [--
|
|
353
|
+
signature: "mono-agent init [--preset <id>] [--with <csv>] [--yes] [--dry-run]\n" +
|
|
335
354
|
" [--model <ref>] [--fallback-models <csv>] [--memory lite|journal|bujo]",
|
|
336
355
|
lines: [
|
|
337
|
-
"Scaffold mono-agent
|
|
338
|
-
"
|
|
339
|
-
"
|
|
356
|
+
"Scaffold a mono-agent in the current folder. On a TTY with no flags, launches",
|
|
357
|
+
"the step-by-step wizard; with --yes or any flag, writes the default/preset",
|
|
358
|
+
"scaffold non-interactively. --preset seeds a blueprint, --with adds channels,",
|
|
359
|
+
"--dry-run previews. Existing files are never overwritten.",
|
|
340
360
|
],
|
|
341
361
|
},
|
|
342
362
|
{
|
|
343
|
-
signature: "mono-agent setup
|
|
344
|
-
|
|
345
|
-
lines: [
|
|
346
|
-
"Guided setup when attached to a TTY: choose a recipe, answer non-secret",
|
|
347
|
-
"inputs, select channel add-ons, scaffold, validate, and print the secrets",
|
|
348
|
-
"checklist. In non-TTY contexts it falls back to init-style flags.",
|
|
349
|
-
],
|
|
363
|
+
signature: "mono-agent setup",
|
|
364
|
+
lines: ["Alias of `init`."],
|
|
350
365
|
},
|
|
351
366
|
{
|
|
352
|
-
signature: "mono-agent
|
|
367
|
+
signature: "mono-agent presets list | show <id>",
|
|
353
368
|
lines: [
|
|
354
|
-
"List the
|
|
369
|
+
"List the built-in setup presets, or show one's generated config,",
|
|
355
370
|
".env.example, and follow-up checklist.",
|
|
356
371
|
],
|
|
357
372
|
},
|
|
358
373
|
{
|
|
359
|
-
signature: "mono-agent validate [--
|
|
374
|
+
signature: "mono-agent validate [--preset <id>] [--consumer <path>] [--config <path>] [--env-file <path>]",
|
|
360
375
|
lines: [
|
|
361
376
|
"Load every config section and report what would run, wait, or fail.",
|
|
362
377
|
"--consumer validates another agent folder read-only, including its .env.",
|
|
363
|
-
"With --
|
|
378
|
+
"With --preset, also report whether the preset's capabilities are live.",
|
|
364
379
|
"`mono-agent doctor` is an alias for this command.",
|
|
365
380
|
],
|
|
366
381
|
},
|
|
@@ -535,14 +550,12 @@ export async function runCli(argv) {
|
|
|
535
550
|
return 0;
|
|
536
551
|
case "init":
|
|
537
552
|
return await runInit(args);
|
|
538
|
-
case "setup":
|
|
539
|
-
return await runSetup(args);
|
|
540
553
|
case "validate":
|
|
541
554
|
return await runValidate(args);
|
|
542
555
|
case "config":
|
|
543
556
|
return await runConfig(args);
|
|
544
|
-
case "
|
|
545
|
-
return
|
|
557
|
+
case "presets":
|
|
558
|
+
return runPresets(args);
|
|
546
559
|
case "start":
|
|
547
560
|
return await runStart(args);
|
|
548
561
|
case "restart":
|
|
@@ -622,93 +635,83 @@ export async function runCli(argv) {
|
|
|
622
635
|
}
|
|
623
636
|
}
|
|
624
637
|
async function runInit(args) {
|
|
625
|
-
|
|
626
|
-
|
|
638
|
+
// On an interactive TTY with no overriding flags, walk the step-by-step wizard;
|
|
639
|
+
// any flag (or a piped/non-TTY invocation) takes the silent default/preset path.
|
|
640
|
+
const wantsWizard = process.stdin.isTTY === true && process.stdout.isTTY === true
|
|
641
|
+
&& args.yes !== true && args.preset === undefined && args.recipe === undefined
|
|
642
|
+
&& args.model === undefined && args.fallbackModels === undefined
|
|
643
|
+
&& args.memory === undefined && args.withChannels === undefined && args.dryRun !== true;
|
|
644
|
+
if (wantsWizard) {
|
|
645
|
+
// Existing-config pre-check — don't walk the wizard into a guaranteed no-op.
|
|
646
|
+
if (await pathExists(resolve(process.cwd(), "mono-agent.config.json"))) {
|
|
647
|
+
process.stdout.write(ui.hint("Found an existing mono-agent.config.json — `mono-agent init` never overwrites. Run `mono-agent validate`, or start in an empty folder.\n"));
|
|
648
|
+
return 0;
|
|
649
|
+
}
|
|
650
|
+
const outcome = await runInitWizard({ cwd: process.cwd() });
|
|
651
|
+
if (outcome.status === "cancelled") {
|
|
652
|
+
return 1;
|
|
653
|
+
}
|
|
654
|
+
const result = await initMonoAgentFolder({ dir: process.cwd(), answers: outcome.answers });
|
|
655
|
+
printInitResult(result);
|
|
656
|
+
const report = await validateMonoAgentFolder({ env: process.env, cwd: process.cwd(), configPath: result.configPath });
|
|
657
|
+
process.stdout.write("\n" + ui.heading("Validation"));
|
|
658
|
+
for (const section of report.sections) {
|
|
659
|
+
process.stdout.write(formatSection(section));
|
|
660
|
+
}
|
|
661
|
+
process.stdout.write(renderPlanCompleteness(result.plan.validateExpectations, "Selected capabilities", report));
|
|
662
|
+
printSecretsChecklist(result.plan.secrets);
|
|
663
|
+
printNextSteps(result.configPath);
|
|
664
|
+
return report.ok ? 0 : 1;
|
|
665
|
+
}
|
|
666
|
+
const presetId = resolveInitPresetId(args);
|
|
667
|
+
if (presetId === "unknown") {
|
|
627
668
|
return 1;
|
|
628
669
|
}
|
|
629
670
|
const withChannels = resolveWithChannels(args);
|
|
630
671
|
if (withChannels === "invalid") {
|
|
631
672
|
return 1;
|
|
632
673
|
}
|
|
633
|
-
const
|
|
634
|
-
dir: process.cwd(),
|
|
674
|
+
const answers = answersFromCli({
|
|
635
675
|
...(args.model === undefined ? {} : { model: args.model }),
|
|
636
676
|
...(args.fallbackModels === undefined ? {} : { fallbackModels: args.fallbackModels }),
|
|
637
677
|
...(args.memory === undefined ? {} : { memory: args.memory }),
|
|
638
|
-
...(recipe === undefined ? {} : { recipe }),
|
|
639
678
|
...(withChannels === undefined ? {} : { withChannels }),
|
|
640
|
-
|
|
679
|
+
...(presetId === undefined ? {} : { presetId }),
|
|
641
680
|
});
|
|
642
|
-
|
|
643
|
-
|
|
681
|
+
const result = await initMonoAgentFolder({ dir: process.cwd(), answers, dryRun: args.dryRun });
|
|
682
|
+
printInitResult(result);
|
|
683
|
+
printSecretsChecklist(result.plan.secrets);
|
|
684
|
+
printNextSteps(result.configPath);
|
|
644
685
|
return 0;
|
|
645
686
|
}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
let collected;
|
|
660
|
-
try {
|
|
661
|
-
collected = await collectSetupOptions({
|
|
662
|
-
prompt: { question: (prompt) => rl.question(prompt) },
|
|
663
|
-
...(recipeArg === undefined ? {} : { recipe: recipeArg }),
|
|
664
|
-
...(args.model === undefined ? {} : { model: args.model }),
|
|
665
|
-
...(args.fallbackModels === undefined ? {} : { fallbackModels: args.fallbackModels }),
|
|
666
|
-
...(withChannelsArg === undefined ? {} : { withChannels: withChannelsArg }),
|
|
667
|
-
});
|
|
668
|
-
}
|
|
669
|
-
finally {
|
|
670
|
-
rl.close();
|
|
671
|
-
}
|
|
672
|
-
const result = await initMonoAgentFolder({
|
|
673
|
-
dir: process.cwd(),
|
|
674
|
-
...(collected.fallbackModels.length === 0 ? {} : { fallbackModels: collected.fallbackModels }),
|
|
675
|
-
...(args.memory === undefined ? {} : { memory: args.memory }),
|
|
676
|
-
recipe: collected.recipe,
|
|
677
|
-
recipeInputs: collected.recipeInputs,
|
|
678
|
-
withChannels: collected.withChannels,
|
|
679
|
-
dryRun: args.dryRun,
|
|
680
|
-
});
|
|
681
|
-
printInitResult(result, collected.recipe);
|
|
682
|
-
if (!result.dryRun) {
|
|
683
|
-
const report = await validateMonoAgentFolder({
|
|
684
|
-
env: process.env,
|
|
685
|
-
cwd: process.cwd(),
|
|
686
|
-
configPath: result.configPath,
|
|
687
|
-
});
|
|
688
|
-
process.stdout.write("\n" + ui.heading("Validation"));
|
|
689
|
-
for (const section of report.sections) {
|
|
690
|
-
process.stdout.write(formatSection(section));
|
|
687
|
+
/**
|
|
688
|
+
* Resolve the preset id for `init`: `--preset` wins, `--recipe` is a deprecated
|
|
689
|
+
* alias mapped to the preset that replaced it. Returns the preset id to compose
|
|
690
|
+
* from, `undefined` for the default scaffold, or `"unknown"` after emitting the
|
|
691
|
+
* error/hint (an unknown preset, or a retired recipe with no replacement).
|
|
692
|
+
*/
|
|
693
|
+
function resolveInitPresetId(args) {
|
|
694
|
+
if (args.preset !== undefined) {
|
|
695
|
+
const preset = findPreset(args.preset);
|
|
696
|
+
if (preset === undefined) {
|
|
697
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${args.preset}\`.`));
|
|
698
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
699
|
+
return "unknown";
|
|
691
700
|
}
|
|
692
|
-
|
|
693
|
-
printSecretsChecklist(collected.secrets);
|
|
694
|
-
printNextSteps(result.configPath, collected.recipe);
|
|
695
|
-
return report.ok ? 0 : 1;
|
|
696
|
-
}
|
|
697
|
-
printSecretsChecklist(collected.secrets);
|
|
698
|
-
printNextSteps(result.configPath, collected.recipe);
|
|
699
|
-
return 0;
|
|
700
|
-
}
|
|
701
|
-
function resolveRecipeArg(args) {
|
|
702
|
-
if (args.recipe === undefined) {
|
|
703
|
-
return undefined;
|
|
701
|
+
return preset.id;
|
|
704
702
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
703
|
+
if (args.recipe !== undefined) {
|
|
704
|
+
const preset = RECIPE_TO_PRESET.get(args.recipe);
|
|
705
|
+
if (preset === undefined) {
|
|
706
|
+
process.stderr.write(ui.errorLine(`Recipe \`${args.recipe}\` was retired; the wizard composes capabilities directly.`));
|
|
707
|
+
process.stderr.write(ui.hint(`Use \`mono-agent init --preset <id>\` (${presetIds().join(", ")}), or \`mono-agent init\` for the step-by-step wizard.`));
|
|
708
|
+
process.stderr.write(ui.hint("See the mono-agent-composer skill and docs/playbooks for capability recipes."));
|
|
709
|
+
return "unknown";
|
|
710
|
+
}
|
|
711
|
+
process.stderr.write(ui.hint(`--recipe is deprecated; using preset ${preset.id}. See \`mono-agent presets list\`.`));
|
|
712
|
+
return preset.id;
|
|
710
713
|
}
|
|
711
|
-
return
|
|
714
|
+
return undefined;
|
|
712
715
|
}
|
|
713
716
|
function resolveWithChannels(args) {
|
|
714
717
|
if (args.withChannels === undefined) {
|
|
@@ -722,7 +725,7 @@ function resolveWithChannels(args) {
|
|
|
722
725
|
}
|
|
723
726
|
return args.withChannels.filter(isWithChannel);
|
|
724
727
|
}
|
|
725
|
-
function printInitResult(result
|
|
728
|
+
function printInitResult(result) {
|
|
726
729
|
if (result.dryRun) {
|
|
727
730
|
process.stdout.write(ui.style.dim("Dry run — nothing was written.\n"));
|
|
728
731
|
}
|
|
@@ -736,31 +739,35 @@ function printInitResult(result, recipe) {
|
|
|
736
739
|
if (result.knowledgeFiles.length > 0) {
|
|
737
740
|
process.stdout.write(`\nIdentity references existing knowledge: ${ui.style.cyan(result.knowledgeFiles.join(", "))}\n`);
|
|
738
741
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
742
|
+
// Internal `provider:*` modules are auto-added for local models; they are an
|
|
743
|
+
// implementation detail, not a user-facing capability, so exclude them here.
|
|
744
|
+
const capabilities = result.plan.selectedModules.filter((module) => module.kind !== "provider");
|
|
745
|
+
if (capabilities.length > 0) {
|
|
746
|
+
process.stdout.write("\n" + ui.heading("Capabilities"));
|
|
747
|
+
for (const module of capabilities) {
|
|
748
|
+
process.stdout.write(` ${ui.style.cyan(module.title)} ${ui.style.dim(`(risk: ${riskColor(module.riskLevel)})`)}\n`);
|
|
743
749
|
}
|
|
744
750
|
}
|
|
751
|
+
if (result.plan.envExample !== undefined) {
|
|
752
|
+
process.stdout.write("\n" + ui.style.dim("Fill the secret placeholders in .env.example, then copy it to .env.\n"));
|
|
753
|
+
}
|
|
745
754
|
}
|
|
746
755
|
function printSecretsChecklist(secrets) {
|
|
747
756
|
process.stdout.write("\n" + ui.heading("Secrets checklist"));
|
|
748
757
|
if (secrets.length === 0) {
|
|
749
|
-
process.stdout.write(ui.style.dim("No
|
|
758
|
+
process.stdout.write(ui.style.dim("No secrets required by the selected capabilities.\n"));
|
|
750
759
|
return;
|
|
751
760
|
}
|
|
752
|
-
process.stdout.write(ui.style.dim("Copy .env.example to .env, then fill these variables. Secret values
|
|
761
|
+
process.stdout.write(ui.style.dim("Copy .env.example to .env, then fill these variables. Secret values are never written to JSON.\n"));
|
|
753
762
|
for (const secret of secrets) {
|
|
754
|
-
|
|
755
|
-
process.stdout.write(` ${ui.style.bold(key)} ${ui.style.dim(`- ${secret.label}: ${secret.description}`)}\n`);
|
|
763
|
+
process.stdout.write(` ${ui.style.bold(secret.envVar)} ${ui.style.dim(`- ${secret.label}: ${secret.description}`)}\n`);
|
|
756
764
|
}
|
|
757
765
|
}
|
|
758
|
-
function printNextSteps(configPath
|
|
759
|
-
const validateCmd = recipe === undefined ? "mono-agent validate" : `mono-agent validate --recipe ${recipe.id}`;
|
|
766
|
+
function printNextSteps(configPath) {
|
|
760
767
|
process.stdout.write("\n" +
|
|
761
768
|
ui.heading("Next steps") +
|
|
762
769
|
` ${ui.style.bold("1.")} Edit ${configPath} ${ui.style.dim("(model, channels, skills, memory, sandbox)")}\n` +
|
|
763
|
-
` ${ui.style.bold("2.")}
|
|
770
|
+
` ${ui.style.bold("2.")} mono-agent validate\n` +
|
|
764
771
|
` ${ui.style.bold("3.")} mono-agent start\n`);
|
|
765
772
|
}
|
|
766
773
|
async function runInstallSkill(args) {
|
|
@@ -791,14 +798,16 @@ async function runValidate(args) {
|
|
|
791
798
|
for (const section of report.sections) {
|
|
792
799
|
process.stdout.write(formatSection(section));
|
|
793
800
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
801
|
+
const preset = resolveValidatePreset(args);
|
|
802
|
+
if (preset === "unknown") {
|
|
803
|
+
return 1;
|
|
804
|
+
}
|
|
805
|
+
if (preset !== undefined) {
|
|
806
|
+
const plan = composeWizardPlan(presetAnswers(preset), {
|
|
807
|
+
dirBasename: basename(context.cwd),
|
|
808
|
+
skillsRootExists: false,
|
|
809
|
+
});
|
|
810
|
+
process.stdout.write(renderPlanCompleteness(plan.validateExpectations, `Preset: ${preset.id}`, report));
|
|
802
811
|
}
|
|
803
812
|
process.stdout.write(report.ok
|
|
804
813
|
? `\n${ui.style.green("✓ Config is ready to start.")}\n${ui.style.dim("Run `mono-agent config` for the full field-by-field view.")}\n`
|
|
@@ -807,15 +816,42 @@ async function runValidate(args) {
|
|
|
807
816
|
return report.ok ? 0 : 1;
|
|
808
817
|
}
|
|
809
818
|
/**
|
|
810
|
-
*
|
|
811
|
-
*
|
|
812
|
-
*
|
|
813
|
-
* "selected recipe incomplete" so the operator knows what is left to wire up.
|
|
819
|
+
* Resolve the preset to check `validate` against: `--preset` wins, `--recipe` is a
|
|
820
|
+
* deprecated alias. Returns the preset, `undefined` (no capability check), or
|
|
821
|
+
* `"unknown"` after emitting the error/hint.
|
|
814
822
|
*/
|
|
815
|
-
function
|
|
816
|
-
|
|
823
|
+
function resolveValidatePreset(args) {
|
|
824
|
+
if (args.preset !== undefined) {
|
|
825
|
+
const preset = findPreset(args.preset);
|
|
826
|
+
if (preset === undefined) {
|
|
827
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${args.preset}\`.`));
|
|
828
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
829
|
+
return "unknown";
|
|
830
|
+
}
|
|
831
|
+
return preset;
|
|
832
|
+
}
|
|
833
|
+
if (args.recipe !== undefined) {
|
|
834
|
+
const preset = RECIPE_TO_PRESET.get(args.recipe);
|
|
835
|
+
if (preset === undefined) {
|
|
836
|
+
process.stderr.write(ui.errorLine(`Recipe \`${args.recipe}\` was retired; validate against a preset instead.`));
|
|
837
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
838
|
+
return "unknown";
|
|
839
|
+
}
|
|
840
|
+
process.stderr.write(ui.hint(`--recipe is deprecated; using preset ${preset.id}. See \`mono-agent presets list\`.`));
|
|
841
|
+
return preset;
|
|
842
|
+
}
|
|
843
|
+
return undefined;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Capability-aware completeness check: for each capability a preset (or module
|
|
847
|
+
* set) promises, report whether the matching doctor section reached the expected
|
|
848
|
+
* status. `waiting` stays non-fatal (it never changes the validate exit code) but
|
|
849
|
+
* is surfaced as "incomplete" so the operator knows what is left to wire up.
|
|
850
|
+
*/
|
|
851
|
+
function renderPlanCompleteness(expectations, label, report) {
|
|
852
|
+
let out = "\n" + ui.heading(label);
|
|
817
853
|
let incomplete = 0;
|
|
818
|
-
for (const expectation of
|
|
854
|
+
for (const expectation of expectations) {
|
|
819
855
|
const section = report.sections.find((entry) => entry.id === expectation.sectionId);
|
|
820
856
|
const status = section?.status ?? "missing";
|
|
821
857
|
const met = status === expectation.mustBe;
|
|
@@ -829,8 +865,8 @@ function renderRecipeCompleteness(recipe, report) {
|
|
|
829
865
|
}
|
|
830
866
|
}
|
|
831
867
|
out += incomplete === 0
|
|
832
|
-
? `${ui.style.green(`✓
|
|
833
|
-
: ui.style.yellow(`⚠
|
|
868
|
+
? `${ui.style.green(`✓ ${label} is fully configured.`)}\n`
|
|
869
|
+
: ui.style.yellow(`⚠ ${label} incomplete: ${incomplete} capability(ies) not yet live.\n`);
|
|
834
870
|
return out;
|
|
835
871
|
}
|
|
836
872
|
function riskColor(risk) {
|
|
@@ -842,72 +878,72 @@ function riskColor(risk) {
|
|
|
842
878
|
}
|
|
843
879
|
return ui.style.green(risk);
|
|
844
880
|
}
|
|
845
|
-
/** `mono-agent
|
|
846
|
-
export function
|
|
847
|
-
let out = ui.banner("mono-agent", "
|
|
848
|
-
for (const
|
|
849
|
-
out += `${ui.style.bold(ui.style.cyan(
|
|
850
|
-
out += ` ${
|
|
851
|
-
out += ` ${ui.style.dim(
|
|
852
|
-
}
|
|
853
|
-
out += "\n" + ui.style.dim("Scaffold one with: mono-agent init --
|
|
881
|
+
/** `mono-agent presets list` — one block per preset. */
|
|
882
|
+
export function renderPresetList() {
|
|
883
|
+
let out = ui.banner("mono-agent", "presets") + "\n";
|
|
884
|
+
for (const preset of PRESET_CATALOG) {
|
|
885
|
+
out += `${ui.style.bold(ui.style.cyan(preset.id))} ${ui.style.dim(`[${riskColor(preset.riskLevel)}]`)}\n`;
|
|
886
|
+
out += ` ${preset.title}\n`;
|
|
887
|
+
out += ` ${ui.style.dim(preset.description)}\n`;
|
|
888
|
+
}
|
|
889
|
+
out += "\n" + ui.style.dim("Scaffold one with: mono-agent init --preset <id>\n");
|
|
890
|
+
out += ui.style.dim("Build interactively with: mono-agent init\n");
|
|
854
891
|
return out;
|
|
855
892
|
}
|
|
856
|
-
/** `mono-agent
|
|
857
|
-
export function
|
|
858
|
-
const
|
|
859
|
-
let out = ui.banner("mono-agent", `
|
|
860
|
-
out += `${ui.style.bold(
|
|
861
|
-
out += `${
|
|
862
|
-
if (
|
|
863
|
-
out += ui.style.dim(`Playbook: docs/playbooks/${
|
|
893
|
+
/** `mono-agent presets show <id>` — description, composed JSON, env example, checklist. */
|
|
894
|
+
export function renderPresetShow(preset) {
|
|
895
|
+
const plan = composeWizardPlan(presetAnswers(preset), { dirBasename: "your-agent", skillsRootExists: false });
|
|
896
|
+
let out = ui.banner("mono-agent", `preset: ${preset.id}`) + "\n";
|
|
897
|
+
out += `${ui.style.bold(preset.title)} ${ui.style.dim(`(risk: ${riskColor(preset.riskLevel)})`)}\n`;
|
|
898
|
+
out += `${preset.description}\n`;
|
|
899
|
+
if (preset.playbook !== undefined) {
|
|
900
|
+
out += ui.style.dim(`Playbook: docs/playbooks/${preset.playbook}\n`);
|
|
864
901
|
}
|
|
865
902
|
out += "\n" + ui.heading("Generated mono-agent.config.json");
|
|
866
|
-
out += JSON.stringify(
|
|
867
|
-
const envExample =
|
|
903
|
+
out += JSON.stringify(plan.configJson, null, 2) + "\n";
|
|
904
|
+
const envExample = plan.envExample;
|
|
868
905
|
if (envExample !== undefined && envExample.trim().length > 0) {
|
|
869
906
|
out += "\n" + ui.heading(".env.example");
|
|
870
907
|
out += envExample.endsWith("\n") ? envExample : envExample + "\n";
|
|
871
908
|
}
|
|
872
|
-
|
|
873
|
-
if (files.length > 0) {
|
|
909
|
+
if (plan.files.length > 0) {
|
|
874
910
|
out += "\n" + ui.heading("Scaffolded files");
|
|
875
|
-
for (const file of files) {
|
|
911
|
+
for (const file of plan.files) {
|
|
876
912
|
out += ` ${ui.style.cyan(file.path)}\n`;
|
|
877
913
|
}
|
|
878
914
|
}
|
|
879
|
-
if (
|
|
915
|
+
if (plan.validateExpectations.length > 0) {
|
|
880
916
|
out += "\n" + ui.heading("Follow-up checklist");
|
|
881
|
-
for (const expectation of
|
|
917
|
+
for (const expectation of plan.validateExpectations) {
|
|
882
918
|
const note = expectation.note === undefined ? "" : ` — ${expectation.note}`;
|
|
883
919
|
out += ` ${ui.style.gray("•")} ${expectation.sectionId} ${ui.style.dim(`must be ${expectation.mustBe}`)}${ui.style.dim(note)}\n`;
|
|
884
920
|
}
|
|
885
921
|
}
|
|
886
922
|
return out;
|
|
887
923
|
}
|
|
888
|
-
/** Dispatch `mono-agent
|
|
889
|
-
function
|
|
924
|
+
/** Dispatch `mono-agent presets list|show <id>`. */
|
|
925
|
+
function runPresets(args) {
|
|
890
926
|
const [sub, id] = args.positionals;
|
|
891
927
|
if (sub === undefined || sub === "list") {
|
|
892
|
-
process.stdout.write(
|
|
928
|
+
process.stdout.write(renderPresetList());
|
|
893
929
|
return 0;
|
|
894
930
|
}
|
|
895
931
|
if (sub === "show") {
|
|
896
932
|
if (id === undefined) {
|
|
897
|
-
process.stderr.write(ui.errorLine("Usage: mono-agent
|
|
898
|
-
process.stderr.write(ui.hint(`Available: ${
|
|
933
|
+
process.stderr.write(ui.errorLine("Usage: mono-agent presets show <id>."));
|
|
934
|
+
process.stderr.write(ui.hint(`Available: ${presetIds().join(", ")}.`));
|
|
899
935
|
return 2;
|
|
900
936
|
}
|
|
901
|
-
const
|
|
902
|
-
if (
|
|
903
|
-
process.stderr.write(ui.errorLine(`Unknown
|
|
904
|
-
process.stderr.write(ui.hint("Run
|
|
937
|
+
const preset = findPreset(id);
|
|
938
|
+
if (preset === undefined) {
|
|
939
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${id}\`.`));
|
|
940
|
+
process.stderr.write(ui.hint(`Available: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
905
941
|
return 1;
|
|
906
942
|
}
|
|
907
|
-
process.stdout.write(
|
|
943
|
+
process.stdout.write(renderPresetShow(preset));
|
|
908
944
|
return 0;
|
|
909
945
|
}
|
|
910
|
-
process.stderr.write(ui.errorLine(`Unknown
|
|
946
|
+
process.stderr.write(ui.errorLine(`Unknown presets subcommand \`${sub}\`. Expected list or show.`));
|
|
911
947
|
return 2;
|
|
912
948
|
}
|
|
913
949
|
const SOURCE_TAG = {
|
|
@@ -1267,25 +1303,6 @@ export function describeChannelStatus(status) {
|
|
|
1267
1303
|
}
|
|
1268
1304
|
return `${status.kind}: ${status.reason}`;
|
|
1269
1305
|
}
|
|
1270
|
-
/**
|
|
1271
|
-
* Render a channel-status summary value for the human-readable status line.
|
|
1272
|
-
* Objects and arrays are expanded to `key: value` pairs instead of the useless
|
|
1273
|
-
* `[object Object]` that a bare `String()` produced (E4: the webhook summary's
|
|
1274
|
-
* `invokeUrls` map printed `invokeUrls=[object Object]`).
|
|
1275
|
-
*/
|
|
1276
|
-
function formatChannelFactValue(value) {
|
|
1277
|
-
if (value === null || typeof value !== "object") {
|
|
1278
|
-
return String(value);
|
|
1279
|
-
}
|
|
1280
|
-
if (Array.isArray(value)) {
|
|
1281
|
-
return `[${value.map(formatChannelFactValue).join(", ")}]`;
|
|
1282
|
-
}
|
|
1283
|
-
const entries = Object.entries(value);
|
|
1284
|
-
if (entries.length === 0) {
|
|
1285
|
-
return "{}";
|
|
1286
|
-
}
|
|
1287
|
-
return `{${entries.map(([key, inner]) => `${key}: ${formatChannelFactValue(inner)}`).join(", ")}}`;
|
|
1288
|
-
}
|
|
1289
1306
|
/**
|
|
1290
1307
|
* Block the foreground process until SIGINT/SIGTERM, then stop the app and
|
|
1291
1308
|
* resolve the exit code. A referenced no-op timer owns the event loop so the
|