@tetherto/mdk-cli 0.0.0-stage → 0.12.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/LICENSE +202 -0
- package/README.md +446 -2
- package/dist/commands/add.js +61 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/agent.js +42 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/create.js +261 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/inspect.js +171 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/meta.js +12 -0
- package/dist/commands/meta.js.map +1 -0
- package/dist/commands/onboard.js +447 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/run.js +203 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/validate.js +125 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/add-package.js +148 -0
- package/dist/lib/add-package.js.map +1 -0
- package/dist/lib/app-package.js +182 -0
- package/dist/lib/app-package.js.map +1 -0
- package/dist/lib/app-scaffold.js +221 -0
- package/dist/lib/app-scaffold.js.map +1 -0
- package/dist/lib/app-ui-check.js +178 -0
- package/dist/lib/app-ui-check.js.map +1 -0
- package/dist/lib/app-ui-runner.js +122 -0
- package/dist/lib/app-ui-runner.js.map +1 -0
- package/dist/lib/catalog.js +69 -0
- package/dist/lib/catalog.js.map +1 -0
- package/dist/lib/checkout.js +14 -0
- package/dist/lib/checkout.js.map +1 -0
- package/dist/lib/dashboard-apps.js +71 -0
- package/dist/lib/dashboard-apps.js.map +1 -0
- package/dist/lib/dashboard.js +318 -0
- package/dist/lib/dashboard.js.map +1 -0
- package/dist/lib/detect.js +38 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/env-file.js +57 -0
- package/dist/lib/env-file.js.map +1 -0
- package/dist/lib/fetch-template.js +33 -0
- package/dist/lib/fetch-template.js.map +1 -0
- package/dist/lib/help.js +22 -0
- package/dist/lib/help.js.map +1 -0
- package/dist/lib/names.js +36 -0
- package/dist/lib/names.js.map +1 -0
- package/dist/lib/npm.js +113 -0
- package/dist/lib/npm.js.map +1 -0
- package/dist/lib/package-source.js +76 -0
- package/dist/lib/package-source.js.map +1 -0
- package/dist/lib/pkg.js +5 -0
- package/dist/lib/pkg.js.map +1 -0
- package/dist/lib/plugin-setup.js +204 -0
- package/dist/lib/plugin-setup.js.map +1 -0
- package/dist/lib/ports.js +31 -0
- package/dist/lib/ports.js.map +1 -0
- package/dist/lib/project.js +297 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/run-lock.js +188 -0
- package/dist/lib/run-lock.js.map +1 -0
- package/dist/lib/runtime.js +683 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/scaffold.js +82 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/shutdown.js +53 -0
- package/dist/lib/shutdown.js.map +1 -0
- package/dist/lib/skill.js +38 -0
- package/dist/lib/skill.js.map +1 -0
- package/dist/lib/spec.js +375 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/status.js +245 -0
- package/dist/lib/status.js.map +1 -0
- package/dist/lib/theme.js +50 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/lib/worker-package.js +74 -0
- package/dist/lib/worker-package.js.map +1 -0
- package/dist/lib/worker-scaffold.js +122 -0
- package/dist/lib/worker-scaffold.js.map +1 -0
- package/dist/lib/worker-smoke.js +243 -0
- package/dist/lib/worker-smoke.js.map +1 -0
- package/dist/program.js +58 -0
- package/dist/program.js.map +1 -0
- package/package.json +57 -4
- package/templates/app/README.md +66 -0
- package/templates/app/mdk-app.yaml +10 -0
- package/templates/app/package.json +17 -0
- package/templates/app/plugin/controllers/summary.js +36 -0
- package/templates/app/plugin/lib/client.js +11 -0
- package/templates/app/plugin/mdk-plugin.json +16 -0
- package/templates/app-ui/tsconfig.json +29 -0
- package/templates/app-ui/ui-src/components/summary-panel.tsx +24 -0
- package/templates/app-ui/ui-src/data/summary.ts +18 -0
- package/templates/app-ui/ui-src/hooks/use-summary.ts +54 -0
- package/templates/app-ui/ui-src/index.tsx +15 -0
- package/templates/app-ui/ui-src/pages/overview-page.tsx +18 -0
- package/templates/app-ui/ui-src/styles.css +13 -0
- package/templates/app-ui/ui-src/styles.d.ts +3 -0
- package/templates/app-ui/ui-src/vite.config.ts +26 -0
- package/templates/worker/README.md +93 -0
- package/templates/worker/mdk-contract.json +26 -0
- package/templates/worker/mock/server.js +93 -0
- package/templates/worker/package.json +23 -0
- package/templates/worker/smoke.config.js +31 -0
- package/templates/worker/src/client.js +47 -0
- package/templates/worker/src/commands/reboot.js +5 -0
- package/templates/worker/src/commands/set-power-mode.js +10 -0
- package/templates/worker/src/telemetry/hashrate-rt.js +5 -0
- package/templates/worker/src/telemetry/power-mode.js +5 -0
- package/templates/worker/src/telemetry/power.js +5 -0
- package/templates/worker/src/telemetry/temperature.js +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.js","sourceRoot":"","sources":["../../src/commands/inspect.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from 'commander';\nimport { examples } from '../lib/help.js';\nimport { stringify as toYaml } from 'yaml';\nimport { collectStatus, type AppReport, type StatusReport, type WorkerReport } from '../lib/status.js';\nimport { STACK_FILE } from '../lib/spec.js';\nimport { theme, tick } from '../lib/theme.js';\n\n// Group C — Run & manage (read-only inspection commands)\nconst OUTPUT_FORMATS = ['table', 'json', 'yaml'];\n\n/** Green when healthy, yellow otherwise — the same convention across sections. */\nfunction flag(ok: boolean, label: string): string {\n return ok ? theme.ok(label) : theme.warn(label);\n}\n\n/**\n * Renders a probe failure for humans. Bare error codes (`ERR_MDK_STATUS_TIMEOUT`,\n * `CHANNEL_CLOSED: channel closed`) mean nothing on their own, so they get a\n * plain-English lead-in; anything already written as prose is shown as-is. The\n * untouched value stays in `-o json` for scripts.\n */\nfunction humanError(error: string | null): string | null {\n if (!error) return null;\n const first = error.split('\\n')[0] ?? '';\n const code = (first.split(':')[0] ?? '').trim();\n return /^[A-Z][A-Z0-9_]*$/.test(code) ? `unreachable (${code})` : first;\n}\n\n/**\n * Left-aligned columns padded to the widest cell, with an optional header row.\n * Padding counts raw string length, so only the last column may carry color.\n */\nfunction columns(headers: string[] | null, rows: string[][]): string {\n const count = Math.max(headers?.length ?? 0, ...rows.map((r) => r.length));\n const widths = Array.from({ length: count }, (_, i) =>\n Math.max(headers?.[i]?.length ?? 0, ...rows.map((r) => (r[i] ?? '').length)),\n );\n const line = (cells: string[]): string =>\n cells\n .map((c, i) => (i === count - 1 ? c : c.padEnd(widths[i] ?? 0)))\n .join(' ')\n .trimEnd();\n\n const body = rows.map((r) => ` ${line(r)}`);\n return headers ? [` ${theme.muted(line(headers))}`, ...body].join('\\n') : body.join('\\n');\n}\n\nfunction workerRows(items: WorkerReport[]): string[][] {\n return items.map((w) => [\n w.name,\n w.registered ? 'yes' : 'no',\n w.state ?? '-',\n w.health ?? '-',\n String(w.devices),\n w.declared ? '' : 'not in spec',\n ]);\n}\n\nfunction appRows(items: AppReport[]): string[][] {\n return items.map((a) => [\n a.name,\n a.running ? 'yes' : 'no',\n a.pid === null ? '-' : String(a.pid),\n a.version ?? '-',\n a.mount,\n a.package,\n ]);\n}\n\n/** Human-readable report: environment first, then the running stack. */\nfunction renderTable(report: StatusReport): string {\n const { environment: env, stack } = report;\n const out: string[] = [];\n\n const title = [\n theme.brand('MDK status'),\n env.spec.stack ? theme.value(env.spec.stack) : theme.muted('(no stack)'),\n ]\n .filter(Boolean)\n .join(' ');\n // The project path goes on its own line so it cannot stretch the table below.\n out.push('', title, theme.muted(report.project), '');\n\n out.push(theme.label('Environment'));\n out.push(\n columns(null, [\n [\n 'Node',\n `v${env.node.version}`,\n flag(env.node.ok, env.node.ok ? 'ok' : `need ${env.node.required}`),\n ],\n ['Package manager', env.packageManager, ''],\n [\n 'Spec',\n STACK_FILE,\n env.spec.valid ? theme.ok('ok') : theme.warn(env.spec.found ? 'invalid' : 'missing'),\n ],\n [\n 'Dependencies',\n `${env.dependencies.checked} declared`,\n flag(\n env.dependencies.ok,\n env.dependencies.ok ? 'ok' : `${env.dependencies.missing.length} not installed`,\n ),\n ],\n ]),\n );\n if (env.spec.error) {\n for (const line of env.spec.error.split('\\n')) out.push(theme.muted(` ${line}`));\n }\n for (const pkg of env.dependencies.missing) {\n out.push(theme.muted(` not installed: ${pkg}`));\n }\n\n // Only the trailing cell is colored, so the columns stay aligned.\n const detail = (component: { state: string; error: string | null }, upDetail: string): string => {\n const note =\n component.state === 'up' ? upDetail : humanError(component.error) ?? 'not running';\n return `${flag(component.state === 'up', component.state.padEnd(4))} ${theme.muted(note)}`;\n };\n\n out.push('', theme.label('Stack'));\n out.push(\n columns(null, [\n ['Kernel', detail(stack.kernel, stack.kernel.key?.slice(0, 16) ?? '')],\n ['Gateway', detail(stack.gateway, stack.gateway.url ?? '')],\n [\n 'Workers',\n `${stack.workers.registered}/${stack.workers.declared} registered ` +\n theme.muted(\n `${stack.workers.totalDevices} device${stack.workers.totalDevices === 1 ? '' : 's'}`,\n ),\n ],\n ['Apps', `${stack.apps.running}/${stack.apps.declared} running`],\n ]),\n );\n\n if (stack.workers.items.length) {\n out.push(\n '',\n columns(\n ['WORKER', 'REGISTERED', 'STATE', 'HEALTH', 'DEVICES', ''],\n workerRows(stack.workers.items),\n ),\n );\n }\n if (stack.apps.items.length) {\n out.push('', columns(['APP', 'RUNNING', 'PID', 'VERSION', 'MOUNT', 'PACKAGE'], appRows(stack.apps.items)));\n }\n\n const health =\n report.health === 'healthy'\n ? theme.ok('healthy')\n : report.health === 'degraded'\n ? theme.warn('degraded')\n : theme.warn('down');\n out.push('', `${report.ok ? tick : theme.warn('!')} Health: ${health}`, '');\n\n return out.join('\\n');\n}\n\n/**\n * Exit codes are part of the CLI contract (see the HLD §3.3):\n * 4 — precondition not met (old Node, missing/invalid spec, packages not installed)\n * 5 — stack not fully up (Kernel/Gateway unreachable, a declared worker is\n * not registered/serving, or a declared app is not running)\n */\nfunction exitCodeFor(report: StatusReport): number {\n const env = report.environment;\n if (!env.node.ok || !env.spec.valid || !env.dependencies.ok) return 4;\n return report.health === 'healthy' ? 0 : 5;\n}\n\nexport function registerStatus(program: Command): void {\n program\n .command('status')\n .summary('Check the environment and every component')\n .description(\n 'One-shot check of the environment and every component (Kernel, Gateway, workers and their device ' +\n 'counts, apps). Starts, stops and repairs nothing; its only write is the CLI key it publishes to ' +\n '.mdk/trusted-keys so the Kernel answers it. Use the global -o json | yaml for machine-readable output.',\n )\n .addHelpText('after', examples('mdk status', 'mdk status -o json'))\n .option('-d, --dir <path>', 'Project directory containing mdk.yaml', '.')\n .action(async (options: { dir: string }, cmd: Command) => {\n const output = String(cmd.optsWithGlobals().output ?? 'table');\n if (!OUTPUT_FORMATS.includes(output)) {\n process.stderr.write(\n `${theme.warn('error')}: unknown --output \"${output}\". Use one of: ${OUTPUT_FORMATS.join(' | ')}.\\n`,\n );\n process.exit(2);\n }\n\n let report: StatusReport;\n try {\n report = await collectStatus(options.dir);\n } catch (error) {\n process.stderr.write(\n `${theme.warn('error')}: ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exit(1);\n }\n\n if (output === 'json') process.stdout.write(`${JSON.stringify(report, null, 2)}\\n`);\n else if (output === 'yaml') process.stdout.write(toYaml(report));\n else process.stdout.write(`${renderTable(report)}\\n`);\n\n process.exitCode = exitCodeFor(report);\n });\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { pkg } from '../lib/pkg.js';
|
|
2
|
+
// Group G — Meta & agent discovery
|
|
3
|
+
export function registerVersion(program) {
|
|
4
|
+
program
|
|
5
|
+
.command('version')
|
|
6
|
+
.description('Print the CLI version')
|
|
7
|
+
.action(() => {
|
|
8
|
+
// Data command: the version string goes to stdout.
|
|
9
|
+
process.stdout.write(`${pkg.name} ${pkg.version}\n`);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=meta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/commands/meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,mCAAmC;AACnC,MAAM,UAAU,eAAe,CAAC,OAAgB;IAC9C,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,uBAAuB,CAAC;SACpC,MAAM,CAAC,GAAG,EAAE;QACX,mDAAmD;QACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import type { Command } from 'commander';\nimport { pkg } from '../lib/pkg.js';\n\n// Group G — Meta & agent discovery\nexport function registerVersion(program: Command): void {\n program\n .command('version')\n .description('Print the CLI version')\n .action(() => {\n // Data command: the version string goes to stdout.\n process.stdout.write(`${pkg.name} ${pkg.version}\\n`);\n });\n}\n"]}
|
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
import { examples } from '../lib/help.js';
|
|
2
|
+
import { intro, outro, text, select, multiselect, confirm, spinner, note, log, isCancel, cancel, } from '@clack/prompts';
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { relative, resolve } from 'node:path';
|
|
5
|
+
import { stringify as toYaml } from 'yaml';
|
|
6
|
+
import { detectEnvironment, NODE_MIN_MAJOR } from '../lib/detect.js';
|
|
7
|
+
import { buildStackSpec, isLocalPackagePath } from '../lib/spec.js';
|
|
8
|
+
import { findCatalogApp, findCatalogWorker, resolveCatalogPackage, APP_CATALOG, WORKER_CATALOG, } from '../lib/catalog.js';
|
|
9
|
+
import { installSkill as installSkillSuite } from '../lib/skill.js';
|
|
10
|
+
import { installDeps, installPackages } from '../lib/npm.js';
|
|
11
|
+
import { applySetupAnswers, applySetupAnswersToStackFile, externalizeSecrets, promptSetup, readSetupQuestions, } from '../lib/plugin-setup.js';
|
|
12
|
+
import { writeProjectEnv } from '../lib/env-file.js';
|
|
13
|
+
import { resolveProjectPackageDir } from '../lib/runtime.js';
|
|
14
|
+
import { createDashboard, dashboardNameFromStack } from '../lib/dashboard.js';
|
|
15
|
+
import { addFileDependency, ensureProjectGitignore, ensureProjectManifest, ensureProjectReadme, } from '../lib/project.js';
|
|
16
|
+
import { theme, badge, banner, kvBlock, cmdBlock, tick } from '../lib/theme.js';
|
|
17
|
+
import { pkg } from '../lib/pkg.js';
|
|
18
|
+
import { NAME_RE } from '../lib/names.js';
|
|
19
|
+
const AGENT_CLIENTS = [
|
|
20
|
+
{ value: 'cursor', label: 'Cursor' },
|
|
21
|
+
{ value: 'claude', label: 'Claude Code' },
|
|
22
|
+
{ value: 'all', label: 'Both (Cursor + Claude)' },
|
|
23
|
+
];
|
|
24
|
+
const delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
25
|
+
function bail() {
|
|
26
|
+
cancel('Onboarding cancelled — no files were changed.');
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
/** Lightweight section divider so related prompts read as a group. */
|
|
30
|
+
function section(title) {
|
|
31
|
+
log.step(theme.brand(title));
|
|
32
|
+
}
|
|
33
|
+
function shortLabel(pkgName) {
|
|
34
|
+
return pkgName.split('/').pop() ?? pkgName;
|
|
35
|
+
}
|
|
36
|
+
// Group A — Onboarding & project lifecycle
|
|
37
|
+
export function registerOnboard(program) {
|
|
38
|
+
program
|
|
39
|
+
.command('onboard')
|
|
40
|
+
.summary('Set up a new MDK project interactively')
|
|
41
|
+
.description('Set up a new MDK project interactively: checks the environment, asks which workers, apps and ' +
|
|
42
|
+
'dashboard to include, writes mdk.yaml and package.json, and prints the commands to run it. ' +
|
|
43
|
+
'Needs an interactive terminal.')
|
|
44
|
+
.addHelpText('after', examples('mdk onboard'))
|
|
45
|
+
.action(runOnboard);
|
|
46
|
+
}
|
|
47
|
+
async function runOnboard() {
|
|
48
|
+
if (!process.stdin.isTTY) {
|
|
49
|
+
process.stderr.write('mdk onboard needs an interactive terminal (TTY).\n');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
console.log(banner());
|
|
53
|
+
intro(`${badge('MDK')} ${theme.brand('developer onboarding')} ${theme.muted(`v${pkg.version}`)}`);
|
|
54
|
+
log.message(theme.muted('A few quick questions — each has a sensible default. Press Enter to accept.'));
|
|
55
|
+
// 1. Detect environment ---------------------------------------------------
|
|
56
|
+
const s = spinner();
|
|
57
|
+
s.start('Detecting environment');
|
|
58
|
+
await delay(500);
|
|
59
|
+
const env = detectEnvironment();
|
|
60
|
+
s.stop(`${tick} Environment detected`);
|
|
61
|
+
note(kvBlock([
|
|
62
|
+
[
|
|
63
|
+
'Node',
|
|
64
|
+
env.nodeOk ? theme.ok(env.nodeVersion) : theme.warn(`${env.nodeVersion} (need >= ${NODE_MIN_MAJOR})`),
|
|
65
|
+
],
|
|
66
|
+
['Package manager', theme.value(env.packageManager)],
|
|
67
|
+
['Git repo', env.git ? theme.ok('yes') : theme.muted('no')],
|
|
68
|
+
['Existing spec', env.existingSpec ? theme.warn('mdk.yaml present') : theme.muted('none')],
|
|
69
|
+
['Agent client', env.agentClient === 'none' ? theme.muted('none') : theme.ok(env.agentClient)],
|
|
70
|
+
]), theme.accent('environment'));
|
|
71
|
+
// 2. Project --------------------------------------------------------------
|
|
72
|
+
section('Project');
|
|
73
|
+
const projectDir = await text({
|
|
74
|
+
message: 'Project directory',
|
|
75
|
+
placeholder: '.',
|
|
76
|
+
defaultValue: '.',
|
|
77
|
+
initialValue: '.',
|
|
78
|
+
});
|
|
79
|
+
if (isCancel(projectDir))
|
|
80
|
+
bail();
|
|
81
|
+
// The stack name becomes `<stack>-dashboard`, a folder and package name, so it
|
|
82
|
+
// is held to the same rule as worker/plugin/app names.
|
|
83
|
+
const stackNameInput = await text({
|
|
84
|
+
message: 'Stack name',
|
|
85
|
+
placeholder: 'my-stack',
|
|
86
|
+
defaultValue: 'my-stack',
|
|
87
|
+
initialValue: 'my-stack',
|
|
88
|
+
validate: (v) => !v?.trim() || NAME_RE.test(v.trim())
|
|
89
|
+
? undefined
|
|
90
|
+
: "Use lowercase letters, digits, '.', '_' or '-' (starting with a letter or digit).",
|
|
91
|
+
});
|
|
92
|
+
if (isCancel(stackNameInput))
|
|
93
|
+
bail();
|
|
94
|
+
const stackName = stackNameInput.trim() || 'my-stack';
|
|
95
|
+
// 3. Runtime — fixed defaults, not prompted --------------------------------
|
|
96
|
+
// Ports land in `mdk.yaml`, but are not a real upfront decision: whether you
|
|
97
|
+
// run everything together (`mdk run`) or split it across terminals
|
|
98
|
+
// (`mdk run kernel` / `gateway` / `worker <name>`) is just which command(s)
|
|
99
|
+
// you type later, not a spec setting. Custom ports are a one-line edit to
|
|
100
|
+
// `mdk.yaml` if the defaults ever collide with something.
|
|
101
|
+
const gatewayPort = 3847;
|
|
102
|
+
const kernelPort = 3848;
|
|
103
|
+
const workerBasePort = 3850;
|
|
104
|
+
// 4. Workers and apps -----------------------------------------------------
|
|
105
|
+
section('Workers and apps');
|
|
106
|
+
// Nothing to offer while the worker catalog is empty — skip the prompt rather
|
|
107
|
+
// than show a multiselect with no options.
|
|
108
|
+
let workerPackages = [];
|
|
109
|
+
if (WORKER_CATALOG.length > 0) {
|
|
110
|
+
workerPackages = await multiselect({
|
|
111
|
+
message: 'Worker plugins to install',
|
|
112
|
+
options: WORKER_CATALOG.map(({ value, label, hint }) => ({ value, label, hint })),
|
|
113
|
+
required: false,
|
|
114
|
+
});
|
|
115
|
+
if (isCancel(workerPackages))
|
|
116
|
+
bail();
|
|
117
|
+
}
|
|
118
|
+
// A bundled worker is only runnable from an MDK checkout — its device mock
|
|
119
|
+
// loads a framework that sits beside it in the source tree. Say so now rather
|
|
120
|
+
// than letting `mdk run` fail on a package that was never installable.
|
|
121
|
+
for (const pkg of workerPackages) {
|
|
122
|
+
const entry = findCatalogWorker(pkg);
|
|
123
|
+
if (entry && resolveCatalogPackage(entry).unavailable) {
|
|
124
|
+
log.warn(`${shortLabel(pkg)} ships with the MDK source tree, which is not present here — ` +
|
|
125
|
+
'so it cannot be linked, and installing it from the registry will fail.');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const appPackages = await multiselect({
|
|
129
|
+
message: 'Apps to install',
|
|
130
|
+
options: APP_CATALOG.map(({ value, label, hint }) => ({ value, label, hint })),
|
|
131
|
+
required: false,
|
|
132
|
+
});
|
|
133
|
+
if (isCancel(appPackages))
|
|
134
|
+
bail();
|
|
135
|
+
for (const pkg of appPackages) {
|
|
136
|
+
const entry = findCatalogApp(pkg);
|
|
137
|
+
if (entry && resolveCatalogPackage(entry).unavailable) {
|
|
138
|
+
log.warn(`${shortLabel(pkg)} ships with the MDK source tree, which is not present here — ` +
|
|
139
|
+
'so it cannot be linked, and installing it from the registry will fail.');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Bundled apps' manifests are readable from the checkout before any
|
|
143
|
+
// install, so their setup questions are asked now and the answers (defaults
|
|
144
|
+
// included) are part of mdk.yaml from the first write — each app's
|
|
145
|
+
// answers under its own `spec.apps[].config` block, the spec the
|
|
146
|
+
// source of truth and the app's built-in defaults only a fallback.
|
|
147
|
+
const pluginConfigs = {};
|
|
148
|
+
// Secret answers, held until the project files are written (cancelling must
|
|
149
|
+
// leave nothing on disk); mdk.yaml only gets `${MDK_<PLUGIN>_<KEY>}` placeholders.
|
|
150
|
+
const pendingSecrets = {};
|
|
151
|
+
const askedUpfront = new Set();
|
|
152
|
+
for (const pkg of appPackages) {
|
|
153
|
+
const entry = findCatalogApp(pkg);
|
|
154
|
+
const resolved = entry ? resolveCatalogPackage(entry) : undefined;
|
|
155
|
+
if (!resolved?.bundled || !resolved.checkoutDir)
|
|
156
|
+
continue;
|
|
157
|
+
let questions;
|
|
158
|
+
try {
|
|
159
|
+
questions = readSetupQuestions(resolved.checkoutDir);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
continue; // malformed manifest — surfaces at load time, not here
|
|
163
|
+
}
|
|
164
|
+
if (!questions.length)
|
|
165
|
+
continue;
|
|
166
|
+
section(`${shortLabel(pkg)} setup`);
|
|
167
|
+
const { answers, env: secrets } = externalizeSecrets(pkg, questions, await promptSetup(questions, bail));
|
|
168
|
+
Object.assign(pendingSecrets, secrets);
|
|
169
|
+
pluginConfigs[pkg] = applySetupAnswers({}, answers);
|
|
170
|
+
askedUpfront.add(pkg);
|
|
171
|
+
}
|
|
172
|
+
// 5. Developer experience -------------------------------------------------
|
|
173
|
+
section('Developer experience');
|
|
174
|
+
const addUi = await confirm({
|
|
175
|
+
message: 'Add the UI dashboard (MDK UI shell)?',
|
|
176
|
+
initialValue: true,
|
|
177
|
+
});
|
|
178
|
+
if (isCancel(addUi))
|
|
179
|
+
bail();
|
|
180
|
+
const installSkill = await confirm({
|
|
181
|
+
message: 'Install the MDK Developer Skill (makes your coding agent MDK-aware)?',
|
|
182
|
+
initialValue: true,
|
|
183
|
+
});
|
|
184
|
+
if (isCancel(installSkill))
|
|
185
|
+
bail();
|
|
186
|
+
let client = env.agentClient === 'cursor' || env.agentClient === 'claude' ? env.agentClient : 'all';
|
|
187
|
+
if (installSkill) {
|
|
188
|
+
const picked = await select({
|
|
189
|
+
message: 'Coding-agent client',
|
|
190
|
+
options: AGENT_CLIENTS,
|
|
191
|
+
initialValue: client,
|
|
192
|
+
});
|
|
193
|
+
if (isCancel(picked))
|
|
194
|
+
bail();
|
|
195
|
+
client = picked;
|
|
196
|
+
}
|
|
197
|
+
// 6. Build spec + review --------------------------------------------------
|
|
198
|
+
const spec = buildStackSpec({
|
|
199
|
+
stackName,
|
|
200
|
+
gatewayPort,
|
|
201
|
+
kernelPort,
|
|
202
|
+
workerBasePort,
|
|
203
|
+
workerPackages: workerPackages,
|
|
204
|
+
appPackages: appPackages,
|
|
205
|
+
pluginConfigs,
|
|
206
|
+
});
|
|
207
|
+
const workers = spec.spec.workers;
|
|
208
|
+
const targetDir = resolve(projectDir);
|
|
209
|
+
const specPath = resolve(targetDir, 'mdk.yaml');
|
|
210
|
+
const specExists = existsSync(specPath);
|
|
211
|
+
// Summarise by what the user picked, not by the resolved `package` — a bundled
|
|
212
|
+
// worker resolves to a checkout path, which is noise in a review panel.
|
|
213
|
+
const workerSummary = workerPackages.length
|
|
214
|
+
? workerPackages
|
|
215
|
+
.map((pkg) => {
|
|
216
|
+
const entry = findCatalogWorker(pkg);
|
|
217
|
+
const bundled = entry ? resolveCatalogPackage(entry).bundled : false;
|
|
218
|
+
return bundled ? `${shortLabel(pkg)} ${theme.muted('(bundled, with mock)')}` : shortLabel(pkg);
|
|
219
|
+
})
|
|
220
|
+
.join(', ')
|
|
221
|
+
: theme.muted('none');
|
|
222
|
+
const appSummary = appPackages.length
|
|
223
|
+
? appPackages
|
|
224
|
+
.map((pkg) => {
|
|
225
|
+
const entry = findCatalogApp(pkg);
|
|
226
|
+
const bundled = entry ? resolveCatalogPackage(entry).bundled : false;
|
|
227
|
+
return bundled ? `${shortLabel(pkg)} ${theme.muted('(bundled)')}` : shortLabel(pkg);
|
|
228
|
+
})
|
|
229
|
+
.join(', ')
|
|
230
|
+
: theme.muted('none');
|
|
231
|
+
note(kvBlock([
|
|
232
|
+
['Stack', theme.value(stackName)],
|
|
233
|
+
['Ports', theme.value(`gateway ${gatewayPort} · kernel ${kernelPort} · workers ${workerBasePort}+`)],
|
|
234
|
+
['Workers', workerSummary],
|
|
235
|
+
['Apps', appSummary],
|
|
236
|
+
['UI dashboard', addUi ? theme.ok('yes') : theme.muted('no')],
|
|
237
|
+
['Developer Skill', installSkill ? theme.ok(`yes (${client})`) : theme.muted('no')],
|
|
238
|
+
['Spec file', specExists ? theme.warn(`${specPath} (overwrite)`) : theme.value(specPath)],
|
|
239
|
+
]), theme.accent('review'));
|
|
240
|
+
const proceed = await confirm({
|
|
241
|
+
message: specExists
|
|
242
|
+
? 'Overwrite mdk.yaml with these settings?'
|
|
243
|
+
: 'Write mdk.yaml with these settings?',
|
|
244
|
+
initialValue: true,
|
|
245
|
+
});
|
|
246
|
+
if (isCancel(proceed) || !proceed)
|
|
247
|
+
bail();
|
|
248
|
+
// 7. Write the project files ----------------------------------------------
|
|
249
|
+
const w = spinner();
|
|
250
|
+
w.start('Writing project files');
|
|
251
|
+
await delay(400);
|
|
252
|
+
try {
|
|
253
|
+
mkdirSync(targetDir, { recursive: true });
|
|
254
|
+
writeFileSync(specPath, toYaml(spec), 'utf8');
|
|
255
|
+
const manifest = ensureProjectManifest(targetDir, stackName);
|
|
256
|
+
const gitignore = ensureProjectGitignore(targetDir);
|
|
257
|
+
if (Object.keys(pendingSecrets).length)
|
|
258
|
+
writeProjectEnv(targetDir, pendingSecrets);
|
|
259
|
+
w.stop(`${tick} Wrote ${theme.value(specPath)}`);
|
|
260
|
+
if (manifest !== 'present') {
|
|
261
|
+
log.message(theme.muted('Created package.json — path-backed packages use relative file: deps'));
|
|
262
|
+
}
|
|
263
|
+
if (gitignore !== 'present') {
|
|
264
|
+
log.message(theme.muted(`${gitignore === 'created' ? 'Created' : 'Updated'} .gitignore — ignores .mdk/ runtime state`));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
w.stop(theme.warn('Could not write the project files'));
|
|
269
|
+
log.error(error instanceof Error ? error.message : String(error));
|
|
270
|
+
bail();
|
|
271
|
+
}
|
|
272
|
+
// 8. Side-effects ---------------------------------------------------------
|
|
273
|
+
// Install the selected plugins so the runtime can resolve them from the
|
|
274
|
+
// project's node_modules. A bundled package is path-backed with a relative
|
|
275
|
+
// `file:` dependency to its checkout (inside or outside the project folder);
|
|
276
|
+
// no checkout path is written into `workspaces`. `npm install` links it into
|
|
277
|
+
// `node_modules` under the package name; no `workers/<name>`/`apps/<name>`
|
|
278
|
+
// folder is created (those are only for packages the user owns via
|
|
279
|
+
// `mdk create`). Registry packages install normally. Local-path packages
|
|
280
|
+
// (scaffolded workers) are skipped — they are linked by `file:` deps from
|
|
281
|
+
// `mdk create` instead. Best-effort: a failed install is a warning, never a
|
|
282
|
+
// hard stop (the spec is already valid).
|
|
283
|
+
const registryPackages = [];
|
|
284
|
+
let linkedBundled = false;
|
|
285
|
+
const selections = [
|
|
286
|
+
...spec.spec.workers.map((wk) => [
|
|
287
|
+
wk.package,
|
|
288
|
+
findCatalogWorker(wk.package),
|
|
289
|
+
]),
|
|
290
|
+
...spec.spec.apps.map((a) => [
|
|
291
|
+
a.package,
|
|
292
|
+
findCatalogApp(a.package),
|
|
293
|
+
]),
|
|
294
|
+
];
|
|
295
|
+
for (const [pkgName, entry] of selections) {
|
|
296
|
+
if (entry) {
|
|
297
|
+
const resolved = resolveCatalogPackage(entry);
|
|
298
|
+
if (resolved.bundled && resolved.checkoutDir) {
|
|
299
|
+
try {
|
|
300
|
+
addFileDependency(targetDir, pkgName, resolved.checkoutDir);
|
|
301
|
+
linkedBundled = true;
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
log.warn(`Could not link ${shortLabel(pkgName)}: ${error instanceof Error ? error.message : String(error)}`);
|
|
305
|
+
}
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!isLocalPackagePath(pkgName))
|
|
310
|
+
registryPackages.push(pkgName);
|
|
311
|
+
}
|
|
312
|
+
const npmPlugins = [...new Set(registryPackages)];
|
|
313
|
+
const needsInstall = linkedBundled || npmPlugins.length > 0;
|
|
314
|
+
if (needsInstall) {
|
|
315
|
+
const count = (linkedBundled ? 1 : 0) + npmPlugins.length;
|
|
316
|
+
log.step(theme.brand(`Installing ${count} package${count === 1 ? '' : 's'}`));
|
|
317
|
+
const result = npmPlugins.length
|
|
318
|
+
? installPackages(targetDir, npmPlugins)
|
|
319
|
+
: installDeps(targetDir);
|
|
320
|
+
if (result.ok) {
|
|
321
|
+
log.success(`${tick} Packages installed`);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
log.warn(`Package install skipped: ${result.message}`);
|
|
325
|
+
log.message(theme.muted(npmPlugins.length
|
|
326
|
+
? `Install manually: npm install ${npmPlugins.join(' ')}`
|
|
327
|
+
: 'Install manually: npm install'));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Registry-installed apps may declare their own setup questions —
|
|
331
|
+
// only readable now that their packages are in node_modules. Answers are
|
|
332
|
+
// patched into the already-written mdk.yaml under the app's own entry in
|
|
333
|
+
// `spec.apps[].config`. Bundled apps were asked before the
|
|
334
|
+
// spec was written.
|
|
335
|
+
for (const pluginPkg of spec.spec.apps.map((a) => a.package)) {
|
|
336
|
+
if (askedUpfront.has(pluginPkg))
|
|
337
|
+
continue;
|
|
338
|
+
let questions;
|
|
339
|
+
try {
|
|
340
|
+
questions = readSetupQuestions(resolveProjectPackageDir(targetDir, pluginPkg));
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
continue; // not installed or malformed manifest — nothing to ask
|
|
344
|
+
}
|
|
345
|
+
if (!questions.length)
|
|
346
|
+
continue;
|
|
347
|
+
section(`${shortLabel(pluginPkg)} setup`);
|
|
348
|
+
const { answers, env: secrets } = externalizeSecrets(pluginPkg, questions, await promptSetup(questions, bail));
|
|
349
|
+
if (Object.keys(secrets).length) {
|
|
350
|
+
try {
|
|
351
|
+
writeProjectEnv(targetDir, secrets);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
log.warn(`Could not write ${shortLabel(pluginPkg)} secrets to .env: ${error instanceof Error ? error.message : String(error)}`);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (Object.keys(answers).length && !applySetupAnswersToStackFile(targetDir, pluginPkg, answers)) {
|
|
358
|
+
log.warn(`Could not write ${shortLabel(pluginPkg)} setup answers to mdk.yaml — add them manually under its config in spec.apps.`);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (installSkill) {
|
|
362
|
+
const sk = spinner();
|
|
363
|
+
sk.start(`Installing MDK Developer Skill (${client})`);
|
|
364
|
+
const result = installSkillSuite(client, targetDir);
|
|
365
|
+
if (result.ok) {
|
|
366
|
+
sk.stop(`${tick} Developer Skill installed`);
|
|
367
|
+
if (result.message)
|
|
368
|
+
log.message(theme.muted(result.message));
|
|
369
|
+
if (result.detail)
|
|
370
|
+
log.message(theme.muted(result.detail));
|
|
371
|
+
if (result.warning)
|
|
372
|
+
log.warn(result.warning);
|
|
373
|
+
}
|
|
374
|
+
else {
|
|
375
|
+
sk.stop(theme.warn(`Skill install skipped: ${result.message}`));
|
|
376
|
+
if (result.detail)
|
|
377
|
+
log.message(theme.muted(result.detail));
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
log.message(theme.muted('Skipped skill install. Later: mdk skill add'));
|
|
382
|
+
}
|
|
383
|
+
let dashboardPath;
|
|
384
|
+
if (addUi) {
|
|
385
|
+
const ui = spinner();
|
|
386
|
+
ui.start('Downloading UI dashboard (MDK UI shell)');
|
|
387
|
+
const result = await createDashboard({
|
|
388
|
+
name: dashboardNameFromStack(stackName),
|
|
389
|
+
parentDir: targetDir,
|
|
390
|
+
});
|
|
391
|
+
if (result.ok) {
|
|
392
|
+
dashboardPath = result.appPath;
|
|
393
|
+
ui.stop(`${tick} UI dashboard scaffolded${dashboardPath ? ` at ${theme.value(dashboardPath)}` : ''}`);
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
ui.stop(theme.warn(`UI dashboard skipped: ${result.message}`));
|
|
397
|
+
if (result.detail)
|
|
398
|
+
log.message(theme.muted(result.detail));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
// The README documents the layout, so it is written last — once it is known
|
|
402
|
+
// whether this project has a dashboard.
|
|
403
|
+
const readme = ensureProjectReadme(targetDir, {
|
|
404
|
+
stackName,
|
|
405
|
+
workerNames: workers.map((wk) => wk.name),
|
|
406
|
+
dashboardDir: dashboardPath ? relative(targetDir, dashboardPath) : undefined,
|
|
407
|
+
});
|
|
408
|
+
if (readme === 'created') {
|
|
409
|
+
log.message(theme.muted('Created README.md — project layout and commands'));
|
|
410
|
+
}
|
|
411
|
+
// 9. Next steps -----------------------------------------------------------
|
|
412
|
+
const runRows = [
|
|
413
|
+
['mdk run', 'boots Kernel, workers, apps and Gateway together'],
|
|
414
|
+
];
|
|
415
|
+
const perComponentHint = workers.length
|
|
416
|
+
? workers.map((wk) => `mdk run worker ${wk.name}`).join(' · ')
|
|
417
|
+
: 'mdk run worker <name>';
|
|
418
|
+
// A worker is bootable only once its devices are declared. Bundled workers were
|
|
419
|
+
// seeded with one already, so the spec is runnable as written — tell the user
|
|
420
|
+
// which of the two situations they are in.
|
|
421
|
+
const seeded = workers.filter((wk) => Array.isArray(wk.config.devices));
|
|
422
|
+
const specHint = seeded.length === workers.length && workers.length > 0
|
|
423
|
+
? `${seeded.length === 1 ? 'a seed device is' : 'seed devices are'} already declared — runnable as-is`
|
|
424
|
+
: 'add devices & plugin config, then save';
|
|
425
|
+
const parts = [
|
|
426
|
+
theme.label('1. Review your spec'),
|
|
427
|
+
cmdBlock([['mdk.yaml', specHint]]),
|
|
428
|
+
'',
|
|
429
|
+
theme.label('2. Start the stack'),
|
|
430
|
+
cmdBlock(runRows),
|
|
431
|
+
theme.muted(`Or separately: mdk run kernel · ${perComponentHint} · mdk run app <name> · mdk run gateway`),
|
|
432
|
+
'',
|
|
433
|
+
theme.label('3. Manage it'),
|
|
434
|
+
cmdBlock([
|
|
435
|
+
['mdk status', 'check the stack'],
|
|
436
|
+
['mdk create worker', 'scaffold a new worker plugin'],
|
|
437
|
+
['mdk create app', 'scaffold a new app (HTTP routes over your devices)'],
|
|
438
|
+
]),
|
|
439
|
+
];
|
|
440
|
+
if (dashboardPath) {
|
|
441
|
+
const rel = relative(process.cwd(), dashboardPath) || dashboardPath;
|
|
442
|
+
parts.push('', theme.label('4. Start the dashboard'), cmdBlock([[`cd ${rel}`], ['npm run dev', 'dependencies are already installed']]));
|
|
443
|
+
}
|
|
444
|
+
note(parts.join('\n'), theme.accent('next steps'));
|
|
445
|
+
outro(`${tick} ${theme.brand('MDK is ready.')} ${theme.muted('Happy building.')}`);
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=onboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Command } from 'commander';\nimport { examples } from '../lib/help.js';\nimport {\n intro,\n outro,\n text,\n select,\n multiselect,\n confirm,\n spinner,\n note,\n log,\n isCancel,\n cancel,\n} from '@clack/prompts';\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport { stringify as toYaml } from 'yaml';\nimport { detectEnvironment, NODE_MIN_MAJOR } from '../lib/detect.js';\nimport { buildStackSpec, isLocalPackagePath } from '../lib/spec.js';\nimport {\n findCatalogApp,\n findCatalogWorker,\n resolveCatalogPackage,\n APP_CATALOG,\n WORKER_CATALOG,\n type CatalogEntry,\n} from '../lib/catalog.js';\nimport { installSkill as installSkillSuite, type SkillClient } from '../lib/skill.js';\nimport { installDeps, installPackages } from '../lib/npm.js';\nimport {\n applySetupAnswers,\n applySetupAnswersToStackFile,\n externalizeSecrets,\n promptSetup,\n readSetupQuestions,\n} from '../lib/plugin-setup.js';\nimport { writeProjectEnv } from '../lib/env-file.js';\nimport { resolveProjectPackageDir } from '../lib/runtime.js';\nimport { createDashboard, dashboardNameFromStack } from '../lib/dashboard.js';\nimport {\n addFileDependency,\n ensureProjectGitignore,\n ensureProjectManifest,\n ensureProjectReadme,\n} from '../lib/project.js';\nimport { theme, badge, banner, kvBlock, cmdBlock, tick } from '../lib/theme.js';\nimport { pkg } from '../lib/pkg.js';\nimport { NAME_RE } from '../lib/names.js';\n\nconst AGENT_CLIENTS = [\n { value: 'cursor', label: 'Cursor' },\n { value: 'claude', label: 'Claude Code' },\n { value: 'all', label: 'Both (Cursor + Claude)' },\n];\n\nconst delay = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction bail(): never {\n cancel('Onboarding cancelled — no files were changed.');\n process.exit(0);\n}\n\n/** Lightweight section divider so related prompts read as a group. */\nfunction section(title: string): void {\n log.step(theme.brand(title));\n}\n\nfunction shortLabel(pkgName: string): string {\n return pkgName.split('/').pop() ?? pkgName;\n}\n\n// Group A — Onboarding & project lifecycle\nexport function registerOnboard(program: Command): void {\n program\n .command('onboard')\n .summary('Set up a new MDK project interactively')\n .description(\n 'Set up a new MDK project interactively: checks the environment, asks which workers, apps and ' +\n 'dashboard to include, writes mdk.yaml and package.json, and prints the commands to run it. ' +\n 'Needs an interactive terminal.',\n )\n .addHelpText('after', examples('mdk onboard'))\n .action(runOnboard);\n}\n\nasync function runOnboard(): Promise<void> {\n if (!process.stdin.isTTY) {\n process.stderr.write('mdk onboard needs an interactive terminal (TTY).\\n');\n process.exit(1);\n }\n\n console.log(banner());\n intro(`${badge('MDK')} ${theme.brand('developer onboarding')} ${theme.muted(`v${pkg.version}`)}`);\n log.message(\n theme.muted('A few quick questions — each has a sensible default. Press Enter to accept.'),\n );\n\n // 1. Detect environment ---------------------------------------------------\n const s = spinner();\n s.start('Detecting environment');\n await delay(500);\n const env = detectEnvironment();\n s.stop(`${tick} Environment detected`);\n\n note(\n kvBlock([\n [\n 'Node',\n env.nodeOk ? theme.ok(env.nodeVersion) : theme.warn(`${env.nodeVersion} (need >= ${NODE_MIN_MAJOR})`),\n ],\n ['Package manager', theme.value(env.packageManager)],\n ['Git repo', env.git ? theme.ok('yes') : theme.muted('no')],\n ['Existing spec', env.existingSpec ? theme.warn('mdk.yaml present') : theme.muted('none')],\n ['Agent client', env.agentClient === 'none' ? theme.muted('none') : theme.ok(env.agentClient)],\n ]),\n theme.accent('environment'),\n );\n\n // 2. Project --------------------------------------------------------------\n section('Project');\n\n const projectDir = await text({\n message: 'Project directory',\n placeholder: '.',\n defaultValue: '.',\n initialValue: '.',\n });\n if (isCancel(projectDir)) bail();\n\n // The stack name becomes `<stack>-dashboard`, a folder and package name, so it\n // is held to the same rule as worker/plugin/app names.\n const stackNameInput = await text({\n message: 'Stack name',\n placeholder: 'my-stack',\n defaultValue: 'my-stack',\n initialValue: 'my-stack',\n validate: (v) =>\n !v?.trim() || NAME_RE.test(v.trim())\n ? undefined\n : \"Use lowercase letters, digits, '.', '_' or '-' (starting with a letter or digit).\",\n });\n if (isCancel(stackNameInput)) bail();\n const stackName = (stackNameInput as string).trim() || 'my-stack';\n\n // 3. Runtime — fixed defaults, not prompted --------------------------------\n // Ports land in `mdk.yaml`, but are not a real upfront decision: whether you\n // run everything together (`mdk run`) or split it across terminals\n // (`mdk run kernel` / `gateway` / `worker <name>`) is just which command(s)\n // you type later, not a spec setting. Custom ports are a one-line edit to\n // `mdk.yaml` if the defaults ever collide with something.\n const gatewayPort = 3847;\n const kernelPort = 3848;\n const workerBasePort = 3850;\n\n // 4. Workers and apps -----------------------------------------------------\n section('Workers and apps');\n\n // Nothing to offer while the worker catalog is empty — skip the prompt rather\n // than show a multiselect with no options.\n let workerPackages: string[] | symbol = [];\n if (WORKER_CATALOG.length > 0) {\n workerPackages = await multiselect({\n message: 'Worker plugins to install',\n options: WORKER_CATALOG.map(({ value, label, hint }) => ({ value, label, hint })),\n required: false,\n });\n if (isCancel(workerPackages)) bail();\n }\n\n // A bundled worker is only runnable from an MDK checkout — its device mock\n // loads a framework that sits beside it in the source tree. Say so now rather\n // than letting `mdk run` fail on a package that was never installable.\n for (const pkg of workerPackages as string[]) {\n const entry = findCatalogWorker(pkg);\n if (entry && resolveCatalogPackage(entry).unavailable) {\n log.warn(\n `${shortLabel(pkg)} ships with the MDK source tree, which is not present here — ` +\n 'so it cannot be linked, and installing it from the registry will fail.',\n );\n }\n }\n\n const appPackages = await multiselect({\n message: 'Apps to install',\n options: APP_CATALOG.map(({ value, label, hint }) => ({ value, label, hint })),\n required: false,\n });\n if (isCancel(appPackages)) bail();\n\n for (const pkg of appPackages as string[]) {\n const entry = findCatalogApp(pkg);\n if (entry && resolveCatalogPackage(entry).unavailable) {\n log.warn(\n `${shortLabel(pkg)} ships with the MDK source tree, which is not present here — ` +\n 'so it cannot be linked, and installing it from the registry will fail.',\n );\n }\n }\n\n // Bundled apps' manifests are readable from the checkout before any\n // install, so their setup questions are asked now and the answers (defaults\n // included) are part of mdk.yaml from the first write — each app's\n // answers under its own `spec.apps[].config` block, the spec the\n // source of truth and the app's built-in defaults only a fallback.\n const pluginConfigs: Record<string, Record<string, unknown>> = {};\n // Secret answers, held until the project files are written (cancelling must\n // leave nothing on disk); mdk.yaml only gets `${MDK_<PLUGIN>_<KEY>}` placeholders.\n const pendingSecrets: Record<string, string> = {};\n const askedUpfront = new Set<string>();\n for (const pkg of appPackages as string[]) {\n const entry = findCatalogApp(pkg);\n const resolved = entry ? resolveCatalogPackage(entry) : undefined;\n if (!resolved?.bundled || !resolved.checkoutDir) continue;\n let questions;\n try {\n questions = readSetupQuestions(resolved.checkoutDir);\n } catch {\n continue; // malformed manifest — surfaces at load time, not here\n }\n if (!questions.length) continue;\n section(`${shortLabel(pkg)} setup`);\n const { answers, env: secrets } = externalizeSecrets(pkg, questions, await promptSetup(questions, bail));\n Object.assign(pendingSecrets, secrets);\n pluginConfigs[pkg] = applySetupAnswers({}, answers);\n askedUpfront.add(pkg);\n }\n\n // 5. Developer experience -------------------------------------------------\n section('Developer experience');\n\n const addUi = await confirm({\n message: 'Add the UI dashboard (MDK UI shell)?',\n initialValue: true,\n });\n if (isCancel(addUi)) bail();\n\n const installSkill = await confirm({\n message: 'Install the MDK Developer Skill (makes your coding agent MDK-aware)?',\n initialValue: true,\n });\n if (isCancel(installSkill)) bail();\n\n let client: string =\n env.agentClient === 'cursor' || env.agentClient === 'claude' ? env.agentClient : 'all';\n if (installSkill) {\n const picked = await select({\n message: 'Coding-agent client',\n options: AGENT_CLIENTS,\n initialValue: client,\n });\n if (isCancel(picked)) bail();\n client = picked as string;\n }\n\n // 6. Build spec + review --------------------------------------------------\n const spec = buildStackSpec({\n stackName,\n gatewayPort,\n kernelPort,\n workerBasePort,\n workerPackages: workerPackages as string[],\n appPackages: appPackages as string[],\n pluginConfigs,\n });\n const workers = spec.spec.workers;\n\n const targetDir = resolve(projectDir as string);\n const specPath = resolve(targetDir, 'mdk.yaml');\n const specExists = existsSync(specPath);\n\n // Summarise by what the user picked, not by the resolved `package` — a bundled\n // worker resolves to a checkout path, which is noise in a review panel.\n const workerSummary = (workerPackages as string[]).length\n ? (workerPackages as string[])\n .map((pkg) => {\n const entry = findCatalogWorker(pkg);\n const bundled = entry ? resolveCatalogPackage(entry).bundled : false;\n return bundled ? `${shortLabel(pkg)} ${theme.muted('(bundled, with mock)')}` : shortLabel(pkg);\n })\n .join(', ')\n : theme.muted('none');\n const appSummary = (appPackages as string[]).length\n ? (appPackages as string[])\n .map((pkg) => {\n const entry = findCatalogApp(pkg);\n const bundled = entry ? resolveCatalogPackage(entry).bundled : false;\n return bundled ? `${shortLabel(pkg)} ${theme.muted('(bundled)')}` : shortLabel(pkg);\n })\n .join(', ')\n : theme.muted('none');\n\n note(\n kvBlock([\n ['Stack', theme.value(stackName)],\n ['Ports', theme.value(`gateway ${gatewayPort} · kernel ${kernelPort} · workers ${workerBasePort}+`)],\n ['Workers', workerSummary],\n ['Apps', appSummary],\n ['UI dashboard', addUi ? theme.ok('yes') : theme.muted('no')],\n ['Developer Skill', installSkill ? theme.ok(`yes (${client})`) : theme.muted('no')],\n ['Spec file', specExists ? theme.warn(`${specPath} (overwrite)`) : theme.value(specPath)],\n ]),\n theme.accent('review'),\n );\n\n const proceed = await confirm({\n message: specExists\n ? 'Overwrite mdk.yaml with these settings?'\n : 'Write mdk.yaml with these settings?',\n initialValue: true,\n });\n if (isCancel(proceed) || !proceed) bail();\n\n // 7. Write the project files ----------------------------------------------\n const w = spinner();\n w.start('Writing project files');\n await delay(400);\n try {\n mkdirSync(targetDir, { recursive: true });\n writeFileSync(specPath, toYaml(spec), 'utf8');\n const manifest = ensureProjectManifest(targetDir, stackName);\n const gitignore = ensureProjectGitignore(targetDir);\n if (Object.keys(pendingSecrets).length) writeProjectEnv(targetDir, pendingSecrets);\n w.stop(`${tick} Wrote ${theme.value(specPath)}`);\n if (manifest !== 'present') {\n log.message(\n theme.muted('Created package.json — path-backed packages use relative file: deps'),\n );\n }\n if (gitignore !== 'present') {\n log.message(\n theme.muted(\n `${gitignore === 'created' ? 'Created' : 'Updated'} .gitignore — ignores .mdk/ runtime state`,\n ),\n );\n }\n } catch (error) {\n w.stop(theme.warn('Could not write the project files'));\n log.error(error instanceof Error ? error.message : String(error));\n bail();\n }\n\n // 8. Side-effects ---------------------------------------------------------\n // Install the selected plugins so the runtime can resolve them from the\n // project's node_modules. A bundled package is path-backed with a relative\n // `file:` dependency to its checkout (inside or outside the project folder);\n // no checkout path is written into `workspaces`. `npm install` links it into\n // `node_modules` under the package name; no `workers/<name>`/`apps/<name>`\n // folder is created (those are only for packages the user owns via\n // `mdk create`). Registry packages install normally. Local-path packages\n // (scaffolded workers) are skipped — they are linked by `file:` deps from\n // `mdk create` instead. Best-effort: a failed install is a warning, never a\n // hard stop (the spec is already valid).\n const registryPackages: string[] = [];\n let linkedBundled = false;\n\n const selections: Array<[string, CatalogEntry | undefined]> = [\n ...spec.spec.workers.map((wk): [string, CatalogEntry | undefined] => [\n wk.package,\n findCatalogWorker(wk.package),\n ]),\n ...spec.spec.apps.map((a): [string, CatalogEntry | undefined] => [\n a.package,\n findCatalogApp(a.package),\n ]),\n ];\n\n for (const [pkgName, entry] of selections) {\n if (entry) {\n const resolved = resolveCatalogPackage(entry);\n if (resolved.bundled && resolved.checkoutDir) {\n try {\n addFileDependency(targetDir, pkgName, resolved.checkoutDir);\n linkedBundled = true;\n } catch (error) {\n log.warn(\n `Could not link ${shortLabel(pkgName)}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n continue;\n }\n }\n if (!isLocalPackagePath(pkgName)) registryPackages.push(pkgName);\n }\n const npmPlugins = [...new Set(registryPackages)];\n const needsInstall = linkedBundled || npmPlugins.length > 0;\n\n if (needsInstall) {\n const count = (linkedBundled ? 1 : 0) + npmPlugins.length;\n log.step(theme.brand(`Installing ${count} package${count === 1 ? '' : 's'}`));\n const result = npmPlugins.length\n ? installPackages(targetDir, npmPlugins)\n : installDeps(targetDir);\n if (result.ok) {\n log.success(`${tick} Packages installed`);\n } else {\n log.warn(`Package install skipped: ${result.message}`);\n log.message(\n theme.muted(\n npmPlugins.length\n ? `Install manually: npm install ${npmPlugins.join(' ')}`\n : 'Install manually: npm install',\n ),\n );\n }\n }\n\n // Registry-installed apps may declare their own setup questions —\n // only readable now that their packages are in node_modules. Answers are\n // patched into the already-written mdk.yaml under the app's own entry in\n // `spec.apps[].config`. Bundled apps were asked before the\n // spec was written.\n for (const pluginPkg of spec.spec.apps.map((a) => a.package)) {\n if (askedUpfront.has(pluginPkg)) continue;\n let questions;\n try {\n questions = readSetupQuestions(resolveProjectPackageDir(targetDir, pluginPkg));\n } catch {\n continue; // not installed or malformed manifest — nothing to ask\n }\n if (!questions.length) continue;\n section(`${shortLabel(pluginPkg)} setup`);\n const { answers, env: secrets } = externalizeSecrets(\n pluginPkg,\n questions,\n await promptSetup(questions, bail),\n );\n if (Object.keys(secrets).length) {\n try {\n writeProjectEnv(targetDir, secrets);\n } catch (error) {\n log.warn(`Could not write ${shortLabel(pluginPkg)} secrets to .env: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n if (Object.keys(answers).length && !applySetupAnswersToStackFile(targetDir, pluginPkg, answers)) {\n log.warn(`Could not write ${shortLabel(pluginPkg)} setup answers to mdk.yaml — add them manually under its config in spec.apps.`);\n }\n }\n\n if (installSkill) {\n const sk = spinner();\n sk.start(`Installing MDK Developer Skill (${client})`);\n const result = installSkillSuite(client as SkillClient, targetDir);\n if (result.ok) {\n sk.stop(`${tick} Developer Skill installed`);\n if (result.message) log.message(theme.muted(result.message));\n if (result.detail) log.message(theme.muted(result.detail));\n if (result.warning) log.warn(result.warning);\n } else {\n sk.stop(theme.warn(`Skill install skipped: ${result.message}`));\n if (result.detail) log.message(theme.muted(result.detail));\n }\n } else {\n log.message(theme.muted('Skipped skill install. Later: mdk skill add'));\n }\n\n let dashboardPath: string | undefined;\n if (addUi) {\n const ui = spinner();\n ui.start('Downloading UI dashboard (MDK UI shell)');\n const result = await createDashboard({\n name: dashboardNameFromStack(stackName),\n parentDir: targetDir,\n });\n if (result.ok) {\n dashboardPath = result.appPath;\n ui.stop(`${tick} UI dashboard scaffolded${dashboardPath ? ` at ${theme.value(dashboardPath)}` : ''}`);\n } else {\n ui.stop(theme.warn(`UI dashboard skipped: ${result.message}`));\n if (result.detail) log.message(theme.muted(result.detail));\n }\n }\n\n // The README documents the layout, so it is written last — once it is known\n // whether this project has a dashboard.\n const readme = ensureProjectReadme(targetDir, {\n stackName,\n workerNames: workers.map((wk) => wk.name),\n dashboardDir: dashboardPath ? relative(targetDir, dashboardPath) : undefined,\n });\n if (readme === 'created') {\n log.message(theme.muted('Created README.md — project layout and commands'));\n }\n\n // 9. Next steps -----------------------------------------------------------\n const runRows: Array<[string, string?]> = [\n ['mdk run', 'boots Kernel, workers, apps and Gateway together'],\n ];\n const perComponentHint = workers.length\n ? workers.map((wk) => `mdk run worker ${wk.name}`).join(' · ')\n : 'mdk run worker <name>';\n\n // A worker is bootable only once its devices are declared. Bundled workers were\n // seeded with one already, so the spec is runnable as written — tell the user\n // which of the two situations they are in.\n const seeded = workers.filter((wk) => Array.isArray((wk.config as { devices?: unknown }).devices));\n const specHint =\n seeded.length === workers.length && workers.length > 0\n ? `${seeded.length === 1 ? 'a seed device is' : 'seed devices are'} already declared — runnable as-is`\n : 'add devices & plugin config, then save';\n\n const parts = [\n theme.label('1. Review your spec'),\n cmdBlock([['mdk.yaml', specHint]]),\n '',\n theme.label('2. Start the stack'),\n cmdBlock(runRows),\n theme.muted(`Or separately: mdk run kernel · ${perComponentHint} · mdk run app <name> · mdk run gateway`),\n '',\n theme.label('3. Manage it'),\n cmdBlock([\n ['mdk status', 'check the stack'],\n ['mdk create worker', 'scaffold a new worker plugin'],\n ['mdk create app', 'scaffold a new app (HTTP routes over your devices)'],\n ]),\n ];\n if (dashboardPath) {\n const rel = relative(process.cwd(), dashboardPath) || dashboardPath;\n parts.push(\n '',\n theme.label('4. Start the dashboard'),\n cmdBlock([[`cd ${rel}`], ['npm run dev', 'dependencies are already installed']]),\n );\n }\n\n note(parts.join('\\n'), theme.accent('next steps'));\n\n outro(`${tick} ${theme.brand('MDK is ready.')} ${theme.muted('Happy building.')}`);\n}\n"]}
|