@mono-agent/agent-app 0.5.1 → 0.6.1
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 +7 -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/channels.js +3 -3
- package/dist/channels.js.map +1 -1
- package/dist/cli.d.ts +28 -10
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +287 -164
- 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 +131 -7
- 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 +17 -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/provider-setup.d.ts +44 -0
- package/dist/provider-setup.d.ts.map +1 -0
- package/dist/provider-setup.js +174 -0
- package/dist/provider-setup.js.map +1 -0
- package/dist/wizard/answers.d.ts +87 -0
- package/dist/wizard/answers.d.ts.map +1 -0
- package/dist/wizard/answers.js +244 -0
- package/dist/wizard/answers.js.map +1 -0
- package/dist/wizard/from-flags.d.ts +27 -0
- package/dist/wizard/from-flags.d.ts.map +1 -0
- package/dist/wizard/from-flags.js +45 -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/model-discovery.d.ts +35 -0
- package/dist/wizard/model-discovery.d.ts.map +1 -0
- package/dist/wizard/model-discovery.js +239 -0
- package/dist/wizard/model-discovery.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 +55 -0
- package/dist/wizard/prompts.d.ts.map +1 -0
- package/dist/wizard/prompts.js +152 -0
- package/dist/wizard/prompts.js.map +1 -0
- package/dist/wizard/run.d.ts +20 -0
- package/dist/wizard/run.d.ts.map +1 -0
- package/dist/wizard/run.js +374 -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 +8 -8
- package/skills/mono-agent-composer/references/config-blueprint.md +7 -7
- package/skills/mono-agent-composer/references/discovery-questions.md +13 -10
- package/skills/mono-agent-composer/references/feature-coverage.md +12 -10
- package/skills/mono-agent-composer/references/package-map.md +7 -6
- 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,11 +1,10 @@
|
|
|
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";
|
|
6
5
|
import process from "node:process";
|
|
7
6
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { buildMonoAgentConfigView, findJsonSecretConfigWarnings, findRemovedConfigWarnings, readMonoAgentConfigJson, redactMonoAgentConfig, } from "@mono-agent/config";
|
|
7
|
+
import { buildMonoAgentConfigView, EFFORT_LEVELS, findJsonSecretConfigWarnings, findRemovedConfigWarnings, readMonoAgentConfigJson, redactMonoAgentConfig, } from "@mono-agent/config";
|
|
9
8
|
import { listRecordedRuns } from "@mono-agent/observability";
|
|
10
9
|
import { describeSandboxEffectiveState, sandboxEffectiveStateWarning, } from "@mono-agent/runtime-adapter";
|
|
11
10
|
import { startMonoAgentApp } from "./app.js";
|
|
@@ -18,13 +17,16 @@ import { formatChannelFactValue } from "./channel-fact-format.js";
|
|
|
18
17
|
import { resolveChannelDrivers } from "./channels.js";
|
|
19
18
|
import { findUnknownAppConfigWarnings } from "./config-reference.js";
|
|
20
19
|
import { validateMonoAgentFolder } from "./doctor.js";
|
|
21
|
-
import { initMonoAgentFolder
|
|
20
|
+
import { initMonoAgentFolder } from "./init.js";
|
|
22
21
|
import { installComposerSkill } from "./install-skill.js";
|
|
23
22
|
import { runMetrics } from "./metrics.js";
|
|
24
|
-
import { findRecipe, RECIPE_CATALOG, recipeIds, resolveRecipeInputs } from "./recipes/index.js";
|
|
25
23
|
import { buildRunsHealthDisplay, RUNS_HEALTH_MAX_RUNS } from "./runs-health.js";
|
|
26
24
|
import { purgeSessions } from "./sessions.js";
|
|
27
|
-
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";
|
|
29
|
+
import { executeProviderSetupPlan, planProviderSetup, providerSetupActionCommandLine } from "./provider-setup.js";
|
|
28
30
|
import * as ui from "./ui.js";
|
|
29
31
|
const DEFAULT_LOG_LINES = 200;
|
|
30
32
|
// Node's maximum setInterval/setTimeout delay (2^31 - 1 ms, ~24.8 days). A
|
|
@@ -32,7 +34,7 @@ const DEFAULT_LOG_LINES = 200;
|
|
|
32
34
|
// busy-waiting; larger values silently overflow to a 1ms delay.
|
|
33
35
|
const KEEP_ALIVE_INTERVAL_MS = 2_147_483_647;
|
|
34
36
|
const BACKGROUND_COMMANDS = ["start", "restart", "stop", "status", "logs"];
|
|
35
|
-
const KNOWN_COMMANDS = ["init", "setup", "validate", "doctor", "config", "recipes", "start", "restart", "stop", "status", "logs", "tui", "web", "install-skill", "backfill", "audit-runs", "metrics", "memory"];
|
|
37
|
+
const KNOWN_COMMANDS = ["init", "setup", "validate", "doctor", "config", "recipes", "presets", "start", "restart", "stop", "status", "logs", "tui", "web", "install-skill", "backfill", "audit-runs", "metrics", "memory"];
|
|
36
38
|
export function parseCliArgs(argv) {
|
|
37
39
|
const [command, ...rest] = argv;
|
|
38
40
|
if (command === undefined || command === "help" || command === "--help" || command === "-h") {
|
|
@@ -44,16 +46,27 @@ export function parseCliArgs(argv) {
|
|
|
44
46
|
if (!KNOWN_COMMANDS.includes(command)) {
|
|
45
47
|
throw new Error(`Unknown command \`${command}\`. Expected ${KNOWN_COMMANDS.join(", ")}.`);
|
|
46
48
|
}
|
|
47
|
-
// `doctor`
|
|
48
|
-
//
|
|
49
|
-
|
|
49
|
+
// `doctor`/`setup`/`recipes` are aliases; normalize here so every downstream
|
|
50
|
+
// path (routing, env-file resolution, --consumer) applies unchanged. `doctor`
|
|
51
|
+
// → `validate`, `setup` → `init`, `recipes` → `presets`.
|
|
52
|
+
const cmd = (command === "doctor"
|
|
53
|
+
? "validate"
|
|
54
|
+
: command === "setup"
|
|
55
|
+
? "init"
|
|
56
|
+
: command === "recipes"
|
|
57
|
+
? "presets"
|
|
58
|
+
: command);
|
|
50
59
|
const isLogs = cmd === "logs";
|
|
51
60
|
let configPath;
|
|
52
61
|
let model;
|
|
53
62
|
let fallbackModels;
|
|
63
|
+
let effort;
|
|
54
64
|
let memory;
|
|
65
|
+
let preset;
|
|
55
66
|
let recipe;
|
|
56
67
|
let withChannels;
|
|
68
|
+
let yes = false;
|
|
69
|
+
let auth = false;
|
|
57
70
|
const positionals = [];
|
|
58
71
|
let envFile;
|
|
59
72
|
let target;
|
|
@@ -184,6 +197,14 @@ export function parseCliArgs(argv) {
|
|
|
184
197
|
.map((entry) => entry.trim())
|
|
185
198
|
.filter((entry) => entry.length > 0);
|
|
186
199
|
break;
|
|
200
|
+
case "--effort": {
|
|
201
|
+
const raw = requireValue(rest, ++i, flag);
|
|
202
|
+
if (!EFFORT_LEVELS.includes(raw)) {
|
|
203
|
+
throw new Error(`--effort must be ${EFFORT_LEVELS.join(", ")}.`);
|
|
204
|
+
}
|
|
205
|
+
effort = raw;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
187
208
|
case "--memory": {
|
|
188
209
|
const raw = requireValue(rest, ++i, flag);
|
|
189
210
|
if (raw !== "lite" && raw !== "journal" && raw !== "bujo") {
|
|
@@ -192,9 +213,18 @@ export function parseCliArgs(argv) {
|
|
|
192
213
|
memory = raw;
|
|
193
214
|
break;
|
|
194
215
|
}
|
|
216
|
+
case "--preset":
|
|
217
|
+
preset = requireValue(rest, ++i, flag);
|
|
218
|
+
break;
|
|
195
219
|
case "--recipe":
|
|
196
220
|
recipe = requireValue(rest, ++i, flag);
|
|
197
221
|
break;
|
|
222
|
+
case "--yes":
|
|
223
|
+
yes = true;
|
|
224
|
+
break;
|
|
225
|
+
case "--auth":
|
|
226
|
+
auth = true;
|
|
227
|
+
break;
|
|
198
228
|
case "--with":
|
|
199
229
|
withChannels = requireValue(rest, ++i, flag)
|
|
200
230
|
.split(",")
|
|
@@ -264,14 +294,21 @@ export function parseCliArgs(argv) {
|
|
|
264
294
|
if (limit !== undefined && cmd !== "memory") {
|
|
265
295
|
throw new Error("--limit is only supported for `mono-agent memory`.");
|
|
266
296
|
}
|
|
297
|
+
if (auth && cmd !== "init") {
|
|
298
|
+
throw new Error("--auth is only supported for `mono-agent init`.");
|
|
299
|
+
}
|
|
267
300
|
return {
|
|
268
301
|
command: cmd,
|
|
269
302
|
...(configPath === undefined ? {} : { configPath }),
|
|
270
303
|
...(model === undefined ? {} : { model }),
|
|
271
304
|
...(fallbackModels === undefined ? {} : { fallbackModels }),
|
|
305
|
+
...(effort === undefined ? {} : { effort }),
|
|
272
306
|
...(memory === undefined ? {} : { memory }),
|
|
307
|
+
...(preset === undefined ? {} : { preset }),
|
|
273
308
|
...(recipe === undefined ? {} : { recipe }),
|
|
274
309
|
...(withChannels === undefined ? {} : { withChannels }),
|
|
310
|
+
...(yes ? { yes } : {}),
|
|
311
|
+
...(auth ? { auth } : {}),
|
|
275
312
|
positionals,
|
|
276
313
|
...(envFile === undefined ? {} : { envFile }),
|
|
277
314
|
...(target === undefined ? {} : { target }),
|
|
@@ -332,36 +369,34 @@ function requireValue(args, index, flag) {
|
|
|
332
369
|
}
|
|
333
370
|
const HELP_COMMANDS = [
|
|
334
371
|
{
|
|
335
|
-
signature: "mono-agent init [--
|
|
336
|
-
" [--model <ref>] [--fallback-models <csv>] [--
|
|
372
|
+
signature: "mono-agent init [--preset <id>] [--with <csv>] [--yes] [--auth] [--dry-run]\n" +
|
|
373
|
+
" [--model <ref>] [--fallback-models <csv>] [--effort <level>]\n" +
|
|
374
|
+
" [--memory lite|journal|bujo]",
|
|
337
375
|
lines: [
|
|
338
|
-
"Scaffold mono-agent
|
|
339
|
-
"
|
|
340
|
-
"
|
|
376
|
+
"Scaffold a mono-agent in the current folder. On a TTY with no flags, launches",
|
|
377
|
+
"the step-by-step wizard; with --yes or any flag, writes the default/preset",
|
|
378
|
+
"scaffold non-interactively. --preset seeds a blueprint, --with adds channels,",
|
|
379
|
+
"--effort writes runtime.effort, --auth runs supported provider auth/preflight",
|
|
380
|
+
"commands before writing, and --dry-run previews only. Existing files are never overwritten.",
|
|
341
381
|
],
|
|
342
382
|
},
|
|
343
383
|
{
|
|
344
|
-
signature: "mono-agent setup
|
|
345
|
-
|
|
346
|
-
lines: [
|
|
347
|
-
"Guided setup when attached to a TTY: choose a recipe, answer non-secret",
|
|
348
|
-
"inputs, select channel add-ons, scaffold, validate, and print the secrets",
|
|
349
|
-
"checklist. In non-TTY contexts it falls back to init-style flags.",
|
|
350
|
-
],
|
|
384
|
+
signature: "mono-agent setup",
|
|
385
|
+
lines: ["Alias of `init`."],
|
|
351
386
|
},
|
|
352
387
|
{
|
|
353
|
-
signature: "mono-agent
|
|
388
|
+
signature: "mono-agent presets list | show <id>",
|
|
354
389
|
lines: [
|
|
355
|
-
"List the
|
|
390
|
+
"List the built-in setup presets, or show one's generated config,",
|
|
356
391
|
".env.example, and follow-up checklist.",
|
|
357
392
|
],
|
|
358
393
|
},
|
|
359
394
|
{
|
|
360
|
-
signature: "mono-agent validate [--
|
|
395
|
+
signature: "mono-agent validate [--preset <id>] [--consumer <path>] [--config <path>] [--env-file <path>]",
|
|
361
396
|
lines: [
|
|
362
397
|
"Load every config section and report what would run, wait, or fail.",
|
|
363
398
|
"--consumer validates another agent folder read-only, including its .env.",
|
|
364
|
-
"With --
|
|
399
|
+
"With --preset, also report whether the preset's capabilities are live.",
|
|
365
400
|
"`mono-agent doctor` is an alias for this command.",
|
|
366
401
|
],
|
|
367
402
|
},
|
|
@@ -473,8 +508,12 @@ const HELP_NOTES = `Background mode runs the agent under launchd, keeping it ali
|
|
|
473
508
|
.env file in the working directory, the same as foreground mode. The background
|
|
474
509
|
commands require macOS; elsewhere use start --foreground.
|
|
475
510
|
|
|
476
|
-
|
|
477
|
-
pi:<provider>:<model> (e.g. pi:
|
|
511
|
+
Init model references look like claude:claude-sonnet-4-6, codex:gpt-5.5,
|
|
512
|
+
or pi:<provider>:<model> (e.g. pi:openai-codex:gpt-5.5,
|
|
513
|
+
pi:opencode-go:kimi-k2.6, or pi:ollama:gemma4:31b). The init wizard prefers
|
|
514
|
+
Pi OpenAI-Codex when that auth is configured, while direct codex:gpt-5.5
|
|
515
|
+
remains selectable as a Codex CLI fallback path. Direct opencode:<provider>:<model>
|
|
516
|
+
refs are for hand-authored runtime backend config.
|
|
478
517
|
|
|
479
518
|
A .env file in the current folder is loaded automatically when present;
|
|
480
519
|
already-exported shell variables take precedence.
|
|
@@ -536,14 +575,12 @@ export async function runCli(argv) {
|
|
|
536
575
|
return 0;
|
|
537
576
|
case "init":
|
|
538
577
|
return await runInit(args);
|
|
539
|
-
case "setup":
|
|
540
|
-
return await runSetup(args);
|
|
541
578
|
case "validate":
|
|
542
579
|
return await runValidate(args);
|
|
543
580
|
case "config":
|
|
544
581
|
return await runConfig(args);
|
|
545
|
-
case "
|
|
546
|
-
return
|
|
582
|
+
case "presets":
|
|
583
|
+
return runPresets(args);
|
|
547
584
|
case "start":
|
|
548
585
|
return await runStart(args);
|
|
549
586
|
case "restart":
|
|
@@ -623,93 +660,146 @@ export async function runCli(argv) {
|
|
|
623
660
|
}
|
|
624
661
|
}
|
|
625
662
|
async function runInit(args) {
|
|
626
|
-
|
|
627
|
-
|
|
663
|
+
// On an interactive TTY with no overriding flags, walk the step-by-step wizard;
|
|
664
|
+
// any flag (or a piped/non-TTY invocation) takes the silent default/preset path.
|
|
665
|
+
const wantsWizard = process.stdin.isTTY === true && process.stdout.isTTY === true
|
|
666
|
+
&& args.yes !== true && args.preset === undefined && args.recipe === undefined
|
|
667
|
+
&& args.model === undefined && args.fallbackModels === undefined
|
|
668
|
+
&& args.effort === undefined && args.memory === undefined && args.withChannels === undefined && args.dryRun !== true;
|
|
669
|
+
if (wantsWizard) {
|
|
670
|
+
// Existing-config pre-check — don't walk the wizard into a guaranteed no-op.
|
|
671
|
+
if (await pathExists(resolve(process.cwd(), "mono-agent.config.json"))) {
|
|
672
|
+
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"));
|
|
673
|
+
return 0;
|
|
674
|
+
}
|
|
675
|
+
const outcome = await runInitWizard({ cwd: process.cwd() });
|
|
676
|
+
if (outcome.status === "cancelled") {
|
|
677
|
+
return 1;
|
|
678
|
+
}
|
|
679
|
+
if (outcome.runProviderSetup) {
|
|
680
|
+
const previewPlan = composeWizardPlan(outcome.answers, {
|
|
681
|
+
dirBasename: basename(process.cwd()),
|
|
682
|
+
skillsRootExists: await pathExists(resolve(process.cwd(), "skills")),
|
|
683
|
+
});
|
|
684
|
+
const setup = await runProviderSetupBeforeInit({
|
|
685
|
+
modelRefs: [outcome.answers.model, ...outcome.answers.fallbackModels],
|
|
686
|
+
cwd: process.cwd(),
|
|
687
|
+
auth: true,
|
|
688
|
+
dryRun: false,
|
|
689
|
+
...(typeof previewPlan.configJson.providers?.piAuthPath === "string" ? { piAuthPath: previewPlan.configJson.providers.piAuthPath } : {}),
|
|
690
|
+
});
|
|
691
|
+
if (setup === "failed") {
|
|
692
|
+
return 1;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
const result = await initMonoAgentFolder({ dir: process.cwd(), answers: outcome.answers });
|
|
696
|
+
printInitResult(result);
|
|
697
|
+
const report = await validateMonoAgentFolder({ env: process.env, cwd: process.cwd(), configPath: result.configPath });
|
|
698
|
+
process.stdout.write("\n" + ui.heading("Validation"));
|
|
699
|
+
for (const section of report.sections) {
|
|
700
|
+
process.stdout.write(formatSection(section));
|
|
701
|
+
}
|
|
702
|
+
process.stdout.write(renderPlanCompleteness(result.plan.validateExpectations, "Selected capabilities", report));
|
|
703
|
+
printSecretsChecklist(result.plan.secrets);
|
|
704
|
+
printNextSteps(result.configPath);
|
|
705
|
+
return report.ok ? 0 : 1;
|
|
706
|
+
}
|
|
707
|
+
const presetId = resolveInitPresetId(args);
|
|
708
|
+
if (presetId === "unknown") {
|
|
628
709
|
return 1;
|
|
629
710
|
}
|
|
630
711
|
const withChannels = resolveWithChannels(args);
|
|
631
712
|
if (withChannels === "invalid") {
|
|
632
713
|
return 1;
|
|
633
714
|
}
|
|
634
|
-
const
|
|
635
|
-
dir: process.cwd(),
|
|
715
|
+
const answers = answersFromCli({
|
|
636
716
|
...(args.model === undefined ? {} : { model: args.model }),
|
|
637
717
|
...(args.fallbackModels === undefined ? {} : { fallbackModels: args.fallbackModels }),
|
|
718
|
+
...(args.effort === undefined ? {} : { effort: args.effort }),
|
|
638
719
|
...(args.memory === undefined ? {} : { memory: args.memory }),
|
|
639
|
-
...(recipe === undefined ? {} : { recipe }),
|
|
640
720
|
...(withChannels === undefined ? {} : { withChannels }),
|
|
641
|
-
|
|
721
|
+
...(presetId === undefined ? {} : { presetId }),
|
|
642
722
|
});
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const recipeArg = resolveRecipeArg(args);
|
|
652
|
-
if (recipeArg === "unknown") {
|
|
653
|
-
return 1;
|
|
654
|
-
}
|
|
655
|
-
const withChannelsArg = resolveWithChannels(args);
|
|
656
|
-
if (withChannelsArg === "invalid") {
|
|
657
|
-
return 1;
|
|
658
|
-
}
|
|
659
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
660
|
-
let collected;
|
|
661
|
-
try {
|
|
662
|
-
collected = await collectSetupOptions({
|
|
663
|
-
prompt: { question: (prompt) => rl.question(prompt) },
|
|
664
|
-
...(recipeArg === undefined ? {} : { recipe: recipeArg }),
|
|
665
|
-
...(args.model === undefined ? {} : { model: args.model }),
|
|
666
|
-
...(args.fallbackModels === undefined ? {} : { fallbackModels: args.fallbackModels }),
|
|
667
|
-
...(withChannelsArg === undefined ? {} : { withChannels: withChannelsArg }),
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
finally {
|
|
671
|
-
rl.close();
|
|
672
|
-
}
|
|
673
|
-
const result = await initMonoAgentFolder({
|
|
674
|
-
dir: process.cwd(),
|
|
675
|
-
...(collected.fallbackModels.length === 0 ? {} : { fallbackModels: collected.fallbackModels }),
|
|
676
|
-
...(args.memory === undefined ? {} : { memory: args.memory }),
|
|
677
|
-
recipe: collected.recipe,
|
|
678
|
-
recipeInputs: collected.recipeInputs,
|
|
679
|
-
withChannels: collected.withChannels,
|
|
723
|
+
const previewPlan = composeWizardPlan(answers, {
|
|
724
|
+
dirBasename: basename(process.cwd()),
|
|
725
|
+
skillsRootExists: await pathExists(resolve(process.cwd(), "skills")),
|
|
726
|
+
});
|
|
727
|
+
const setup = await runProviderSetupBeforeInit({
|
|
728
|
+
modelRefs: [answers.model, ...answers.fallbackModels],
|
|
729
|
+
cwd: process.cwd(),
|
|
730
|
+
auth: args.auth === true,
|
|
680
731
|
dryRun: args.dryRun,
|
|
732
|
+
...(typeof previewPlan.configJson.providers?.piAuthPath === "string" ? { piAuthPath: previewPlan.configJson.providers.piAuthPath } : {}),
|
|
681
733
|
});
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
const report = await validateMonoAgentFolder({
|
|
685
|
-
env: process.env,
|
|
686
|
-
cwd: process.cwd(),
|
|
687
|
-
configPath: result.configPath,
|
|
688
|
-
});
|
|
689
|
-
process.stdout.write("\n" + ui.heading("Validation"));
|
|
690
|
-
for (const section of report.sections) {
|
|
691
|
-
process.stdout.write(formatSection(section));
|
|
692
|
-
}
|
|
693
|
-
process.stdout.write(renderRecipeCompleteness(collected.recipe, report));
|
|
694
|
-
printSecretsChecklist(collected.secrets);
|
|
695
|
-
printNextSteps(result.configPath, collected.recipe);
|
|
696
|
-
return report.ok ? 0 : 1;
|
|
734
|
+
if (setup === "failed") {
|
|
735
|
+
return 1;
|
|
697
736
|
}
|
|
698
|
-
|
|
699
|
-
|
|
737
|
+
const result = await initMonoAgentFolder({ dir: process.cwd(), answers, dryRun: args.dryRun });
|
|
738
|
+
printInitResult(result);
|
|
739
|
+
printSecretsChecklist(result.plan.secrets);
|
|
740
|
+
printNextSteps(result.configPath);
|
|
700
741
|
return 0;
|
|
701
742
|
}
|
|
702
|
-
function
|
|
703
|
-
|
|
704
|
-
|
|
743
|
+
export async function runProviderSetupBeforeInit(options) {
|
|
744
|
+
const plan = planProviderSetup(options);
|
|
745
|
+
if (plan.actions.length === 0) {
|
|
746
|
+
return "skipped";
|
|
747
|
+
}
|
|
748
|
+
if (options.dryRun) {
|
|
749
|
+
process.stdout.write("\n" + ui.heading("Provider setup"));
|
|
750
|
+
process.stdout.write(ui.style.dim("Dry run - provider auth/preflight commands were not launched.\n"));
|
|
751
|
+
printProviderSetupPlan(plan);
|
|
752
|
+
return "skipped";
|
|
753
|
+
}
|
|
754
|
+
if (!options.auth) {
|
|
755
|
+
return "skipped";
|
|
756
|
+
}
|
|
757
|
+
process.stdout.write("\n" + ui.heading("Provider setup"));
|
|
758
|
+
printProviderSetupPlan(plan);
|
|
759
|
+
const results = await (options.execute ?? executeProviderSetupPlan)(plan);
|
|
760
|
+
for (const result of results) {
|
|
761
|
+
const badge = result.status === "ok" ? ui.badge("ok") : ui.badge("error");
|
|
762
|
+
process.stdout.write(`${badge}${result.action.label}: ${result.detail}\n`);
|
|
763
|
+
}
|
|
764
|
+
if (results.some((result) => result.status === "failed")) {
|
|
765
|
+
process.stderr.write(ui.errorLine("Provider setup failed; init stopped before writing files."));
|
|
766
|
+
return "failed";
|
|
767
|
+
}
|
|
768
|
+
return "ok";
|
|
769
|
+
}
|
|
770
|
+
function printProviderSetupPlan(plan) {
|
|
771
|
+
for (const action of plan.actions) {
|
|
772
|
+
process.stdout.write(` ${action.label}: ${providerSetupActionCommandLine(action)} ${ui.style.dim(`(cwd: ${action.cwd})`)}\n`);
|
|
705
773
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Resolve the preset id for `init`: `--preset` wins, `--recipe` is a deprecated
|
|
777
|
+
* alias mapped to the preset that replaced it. Returns the preset id to compose
|
|
778
|
+
* from, `undefined` for the default scaffold, or `"unknown"` after emitting the
|
|
779
|
+
* error/hint (an unknown preset, or a retired recipe with no replacement).
|
|
780
|
+
*/
|
|
781
|
+
function resolveInitPresetId(args) {
|
|
782
|
+
if (args.preset !== undefined) {
|
|
783
|
+
const preset = findPreset(args.preset);
|
|
784
|
+
if (preset === undefined) {
|
|
785
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${args.preset}\`.`));
|
|
786
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
787
|
+
return "unknown";
|
|
788
|
+
}
|
|
789
|
+
return preset.id;
|
|
711
790
|
}
|
|
712
|
-
|
|
791
|
+
if (args.recipe !== undefined) {
|
|
792
|
+
const preset = RECIPE_TO_PRESET.get(args.recipe);
|
|
793
|
+
if (preset === undefined) {
|
|
794
|
+
process.stderr.write(ui.errorLine(`Recipe \`${args.recipe}\` was retired; the wizard composes capabilities directly.`));
|
|
795
|
+
process.stderr.write(ui.hint(`Use \`mono-agent init --preset <id>\` (${presetIds().join(", ")}), or \`mono-agent init\` for the step-by-step wizard.`));
|
|
796
|
+
process.stderr.write(ui.hint("See the mono-agent-composer skill and docs/playbooks for capability recipes."));
|
|
797
|
+
return "unknown";
|
|
798
|
+
}
|
|
799
|
+
process.stderr.write(ui.hint(`--recipe is deprecated; using preset ${preset.id}. See \`mono-agent presets list\`.`));
|
|
800
|
+
return preset.id;
|
|
801
|
+
}
|
|
802
|
+
return undefined;
|
|
713
803
|
}
|
|
714
804
|
function resolveWithChannels(args) {
|
|
715
805
|
if (args.withChannels === undefined) {
|
|
@@ -723,7 +813,7 @@ function resolveWithChannels(args) {
|
|
|
723
813
|
}
|
|
724
814
|
return args.withChannels.filter(isWithChannel);
|
|
725
815
|
}
|
|
726
|
-
function printInitResult(result
|
|
816
|
+
function printInitResult(result) {
|
|
727
817
|
if (result.dryRun) {
|
|
728
818
|
process.stdout.write(ui.style.dim("Dry run — nothing was written.\n"));
|
|
729
819
|
}
|
|
@@ -737,31 +827,35 @@ function printInitResult(result, recipe) {
|
|
|
737
827
|
if (result.knowledgeFiles.length > 0) {
|
|
738
828
|
process.stdout.write(`\nIdentity references existing knowledge: ${ui.style.cyan(result.knowledgeFiles.join(", "))}\n`);
|
|
739
829
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
830
|
+
// Internal `provider:*` modules are auto-added for local models; they are an
|
|
831
|
+
// implementation detail, not a user-facing capability, so exclude them here.
|
|
832
|
+
const capabilities = result.plan.selectedModules.filter((module) => module.kind !== "provider");
|
|
833
|
+
if (capabilities.length > 0) {
|
|
834
|
+
process.stdout.write("\n" + ui.heading("Capabilities"));
|
|
835
|
+
for (const module of capabilities) {
|
|
836
|
+
process.stdout.write(` ${ui.style.cyan(module.title)} ${ui.style.dim(`(risk: ${riskColor(module.riskLevel)})`)}\n`);
|
|
744
837
|
}
|
|
745
838
|
}
|
|
839
|
+
if (result.plan.envExample !== undefined) {
|
|
840
|
+
process.stdout.write("\n" + ui.style.dim("Fill the secret placeholders in .env.example, then copy it to .env.\n"));
|
|
841
|
+
}
|
|
746
842
|
}
|
|
747
843
|
function printSecretsChecklist(secrets) {
|
|
748
844
|
process.stdout.write("\n" + ui.heading("Secrets checklist"));
|
|
749
845
|
if (secrets.length === 0) {
|
|
750
|
-
process.stdout.write(ui.style.dim("No
|
|
846
|
+
process.stdout.write(ui.style.dim("No secrets required by the selected capabilities.\n"));
|
|
751
847
|
return;
|
|
752
848
|
}
|
|
753
|
-
process.stdout.write(ui.style.dim("Copy .env.example to .env, then fill these variables. Secret values
|
|
849
|
+
process.stdout.write(ui.style.dim("Copy .env.example to .env, then fill these variables. Secret values are never written to JSON.\n"));
|
|
754
850
|
for (const secret of secrets) {
|
|
755
|
-
|
|
756
|
-
process.stdout.write(` ${ui.style.bold(key)} ${ui.style.dim(`- ${secret.label}: ${secret.description}`)}\n`);
|
|
851
|
+
process.stdout.write(` ${ui.style.bold(secret.envVar)} ${ui.style.dim(`- ${secret.label}: ${secret.description}`)}\n`);
|
|
757
852
|
}
|
|
758
853
|
}
|
|
759
|
-
function printNextSteps(configPath
|
|
760
|
-
const validateCmd = recipe === undefined ? "mono-agent validate" : `mono-agent validate --recipe ${recipe.id}`;
|
|
854
|
+
function printNextSteps(configPath) {
|
|
761
855
|
process.stdout.write("\n" +
|
|
762
856
|
ui.heading("Next steps") +
|
|
763
857
|
` ${ui.style.bold("1.")} Edit ${configPath} ${ui.style.dim("(model, channels, skills, memory, sandbox)")}\n` +
|
|
764
|
-
` ${ui.style.bold("2.")}
|
|
858
|
+
` ${ui.style.bold("2.")} mono-agent validate\n` +
|
|
765
859
|
` ${ui.style.bold("3.")} mono-agent start\n`);
|
|
766
860
|
}
|
|
767
861
|
async function runInstallSkill(args) {
|
|
@@ -792,14 +886,16 @@ async function runValidate(args) {
|
|
|
792
886
|
for (const section of report.sections) {
|
|
793
887
|
process.stdout.write(formatSection(section));
|
|
794
888
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
889
|
+
const preset = resolveValidatePreset(args);
|
|
890
|
+
if (preset === "unknown") {
|
|
891
|
+
return 1;
|
|
892
|
+
}
|
|
893
|
+
if (preset !== undefined) {
|
|
894
|
+
const plan = composeWizardPlan(presetAnswers(preset), {
|
|
895
|
+
dirBasename: basename(context.cwd),
|
|
896
|
+
skillsRootExists: false,
|
|
897
|
+
});
|
|
898
|
+
process.stdout.write(renderPlanCompleteness(plan.validateExpectations, `Preset: ${preset.id}`, report));
|
|
803
899
|
}
|
|
804
900
|
process.stdout.write(report.ok
|
|
805
901
|
? `\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`
|
|
@@ -808,15 +904,42 @@ async function runValidate(args) {
|
|
|
808
904
|
return report.ok ? 0 : 1;
|
|
809
905
|
}
|
|
810
906
|
/**
|
|
811
|
-
*
|
|
812
|
-
*
|
|
813
|
-
*
|
|
814
|
-
|
|
907
|
+
* Resolve the preset to check `validate` against: `--preset` wins, `--recipe` is a
|
|
908
|
+
* deprecated alias. Returns the preset, `undefined` (no capability check), or
|
|
909
|
+
* `"unknown"` after emitting the error/hint.
|
|
910
|
+
*/
|
|
911
|
+
function resolveValidatePreset(args) {
|
|
912
|
+
if (args.preset !== undefined) {
|
|
913
|
+
const preset = findPreset(args.preset);
|
|
914
|
+
if (preset === undefined) {
|
|
915
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${args.preset}\`.`));
|
|
916
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
917
|
+
return "unknown";
|
|
918
|
+
}
|
|
919
|
+
return preset;
|
|
920
|
+
}
|
|
921
|
+
if (args.recipe !== undefined) {
|
|
922
|
+
const preset = RECIPE_TO_PRESET.get(args.recipe);
|
|
923
|
+
if (preset === undefined) {
|
|
924
|
+
process.stderr.write(ui.errorLine(`Recipe \`${args.recipe}\` was retired; validate against a preset instead.`));
|
|
925
|
+
process.stderr.write(ui.hint(`Available presets: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
926
|
+
return "unknown";
|
|
927
|
+
}
|
|
928
|
+
process.stderr.write(ui.hint(`--recipe is deprecated; using preset ${preset.id}. See \`mono-agent presets list\`.`));
|
|
929
|
+
return preset;
|
|
930
|
+
}
|
|
931
|
+
return undefined;
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* Capability-aware completeness check: for each capability a preset (or module
|
|
935
|
+
* set) promises, report whether the matching doctor section reached the expected
|
|
936
|
+
* status. `waiting` stays non-fatal (it never changes the validate exit code) but
|
|
937
|
+
* is surfaced as "incomplete" so the operator knows what is left to wire up.
|
|
815
938
|
*/
|
|
816
|
-
function
|
|
817
|
-
let out = "\n" + ui.heading(
|
|
939
|
+
function renderPlanCompleteness(expectations, label, report) {
|
|
940
|
+
let out = "\n" + ui.heading(label);
|
|
818
941
|
let incomplete = 0;
|
|
819
|
-
for (const expectation of
|
|
942
|
+
for (const expectation of expectations) {
|
|
820
943
|
const section = report.sections.find((entry) => entry.id === expectation.sectionId);
|
|
821
944
|
const status = section?.status ?? "missing";
|
|
822
945
|
const met = status === expectation.mustBe;
|
|
@@ -830,8 +953,8 @@ function renderRecipeCompleteness(recipe, report) {
|
|
|
830
953
|
}
|
|
831
954
|
}
|
|
832
955
|
out += incomplete === 0
|
|
833
|
-
? `${ui.style.green(`✓
|
|
834
|
-
: ui.style.yellow(`⚠
|
|
956
|
+
? `${ui.style.green(`✓ ${label} is fully configured.`)}\n`
|
|
957
|
+
: ui.style.yellow(`⚠ ${label} incomplete: ${incomplete} capability(ies) not yet live.\n`);
|
|
835
958
|
return out;
|
|
836
959
|
}
|
|
837
960
|
function riskColor(risk) {
|
|
@@ -843,72 +966,72 @@ function riskColor(risk) {
|
|
|
843
966
|
}
|
|
844
967
|
return ui.style.green(risk);
|
|
845
968
|
}
|
|
846
|
-
/** `mono-agent
|
|
847
|
-
export function
|
|
848
|
-
let out = ui.banner("mono-agent", "
|
|
849
|
-
for (const
|
|
850
|
-
out += `${ui.style.bold(ui.style.cyan(
|
|
851
|
-
out += ` ${
|
|
852
|
-
out += ` ${ui.style.dim(
|
|
853
|
-
}
|
|
854
|
-
out += "\n" + ui.style.dim("Scaffold one with: mono-agent init --
|
|
969
|
+
/** `mono-agent presets list` — one block per preset. */
|
|
970
|
+
export function renderPresetList() {
|
|
971
|
+
let out = ui.banner("mono-agent", "presets") + "\n";
|
|
972
|
+
for (const preset of PRESET_CATALOG) {
|
|
973
|
+
out += `${ui.style.bold(ui.style.cyan(preset.id))} ${ui.style.dim(`[${riskColor(preset.riskLevel)}]`)}\n`;
|
|
974
|
+
out += ` ${preset.title}\n`;
|
|
975
|
+
out += ` ${ui.style.dim(preset.description)}\n`;
|
|
976
|
+
}
|
|
977
|
+
out += "\n" + ui.style.dim("Scaffold one with: mono-agent init --preset <id>\n");
|
|
978
|
+
out += ui.style.dim("Build interactively with: mono-agent init\n");
|
|
855
979
|
return out;
|
|
856
980
|
}
|
|
857
|
-
/** `mono-agent
|
|
858
|
-
export function
|
|
859
|
-
const
|
|
860
|
-
let out = ui.banner("mono-agent", `
|
|
861
|
-
out += `${ui.style.bold(
|
|
862
|
-
out += `${
|
|
863
|
-
if (
|
|
864
|
-
out += ui.style.dim(`Playbook: docs/playbooks/${
|
|
981
|
+
/** `mono-agent presets show <id>` — description, composed JSON, env example, checklist. */
|
|
982
|
+
export function renderPresetShow(preset) {
|
|
983
|
+
const plan = composeWizardPlan(presetAnswers(preset), { dirBasename: "your-agent", skillsRootExists: false });
|
|
984
|
+
let out = ui.banner("mono-agent", `preset: ${preset.id}`) + "\n";
|
|
985
|
+
out += `${ui.style.bold(preset.title)} ${ui.style.dim(`(risk: ${riskColor(preset.riskLevel)})`)}\n`;
|
|
986
|
+
out += `${preset.description}\n`;
|
|
987
|
+
if (preset.playbook !== undefined) {
|
|
988
|
+
out += ui.style.dim(`Playbook: docs/playbooks/${preset.playbook}\n`);
|
|
865
989
|
}
|
|
866
990
|
out += "\n" + ui.heading("Generated mono-agent.config.json");
|
|
867
|
-
out += JSON.stringify(
|
|
868
|
-
const envExample =
|
|
991
|
+
out += JSON.stringify(plan.configJson, null, 2) + "\n";
|
|
992
|
+
const envExample = plan.envExample;
|
|
869
993
|
if (envExample !== undefined && envExample.trim().length > 0) {
|
|
870
994
|
out += "\n" + ui.heading(".env.example");
|
|
871
995
|
out += envExample.endsWith("\n") ? envExample : envExample + "\n";
|
|
872
996
|
}
|
|
873
|
-
|
|
874
|
-
if (files.length > 0) {
|
|
997
|
+
if (plan.files.length > 0) {
|
|
875
998
|
out += "\n" + ui.heading("Scaffolded files");
|
|
876
|
-
for (const file of files) {
|
|
999
|
+
for (const file of plan.files) {
|
|
877
1000
|
out += ` ${ui.style.cyan(file.path)}\n`;
|
|
878
1001
|
}
|
|
879
1002
|
}
|
|
880
|
-
if (
|
|
1003
|
+
if (plan.validateExpectations.length > 0) {
|
|
881
1004
|
out += "\n" + ui.heading("Follow-up checklist");
|
|
882
|
-
for (const expectation of
|
|
1005
|
+
for (const expectation of plan.validateExpectations) {
|
|
883
1006
|
const note = expectation.note === undefined ? "" : ` — ${expectation.note}`;
|
|
884
1007
|
out += ` ${ui.style.gray("•")} ${expectation.sectionId} ${ui.style.dim(`must be ${expectation.mustBe}`)}${ui.style.dim(note)}\n`;
|
|
885
1008
|
}
|
|
886
1009
|
}
|
|
887
1010
|
return out;
|
|
888
1011
|
}
|
|
889
|
-
/** Dispatch `mono-agent
|
|
890
|
-
function
|
|
1012
|
+
/** Dispatch `mono-agent presets list|show <id>`. */
|
|
1013
|
+
function runPresets(args) {
|
|
891
1014
|
const [sub, id] = args.positionals;
|
|
892
1015
|
if (sub === undefined || sub === "list") {
|
|
893
|
-
process.stdout.write(
|
|
1016
|
+
process.stdout.write(renderPresetList());
|
|
894
1017
|
return 0;
|
|
895
1018
|
}
|
|
896
1019
|
if (sub === "show") {
|
|
897
1020
|
if (id === undefined) {
|
|
898
|
-
process.stderr.write(ui.errorLine("Usage: mono-agent
|
|
899
|
-
process.stderr.write(ui.hint(`Available: ${
|
|
1021
|
+
process.stderr.write(ui.errorLine("Usage: mono-agent presets show <id>."));
|
|
1022
|
+
process.stderr.write(ui.hint(`Available: ${presetIds().join(", ")}.`));
|
|
900
1023
|
return 2;
|
|
901
1024
|
}
|
|
902
|
-
const
|
|
903
|
-
if (
|
|
904
|
-
process.stderr.write(ui.errorLine(`Unknown
|
|
905
|
-
process.stderr.write(ui.hint("Run
|
|
1025
|
+
const preset = findPreset(id);
|
|
1026
|
+
if (preset === undefined) {
|
|
1027
|
+
process.stderr.write(ui.errorLine(`Unknown preset \`${id}\`.`));
|
|
1028
|
+
process.stderr.write(ui.hint(`Available: ${presetIds().join(", ")}. Run \`mono-agent presets list\`.`));
|
|
906
1029
|
return 1;
|
|
907
1030
|
}
|
|
908
|
-
process.stdout.write(
|
|
1031
|
+
process.stdout.write(renderPresetShow(preset));
|
|
909
1032
|
return 0;
|
|
910
1033
|
}
|
|
911
|
-
process.stderr.write(ui.errorLine(`Unknown
|
|
1034
|
+
process.stderr.write(ui.errorLine(`Unknown presets subcommand \`${sub}\`. Expected list or show.`));
|
|
912
1035
|
return 2;
|
|
913
1036
|
}
|
|
914
1037
|
const SOURCE_TAG = {
|