@mindees/cli 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
package/dist/banner.js ADDED
@@ -0,0 +1,40 @@
1
+ //#region src/banner.ts
2
+ const RESET = "\x1B[0m";
3
+ const DIM = "\x1B[2m";
4
+ const paint = (on, code, text) => on ? `${code}${text}${RESET}` : text;
5
+ /** The ANSI wordmark (always portable — works in every terminal, CI, and piped output). */
6
+ function wordmark(opts = {}) {
7
+ const on = opts.color !== false;
8
+ const ver = opts.version ? paint(on, DIM, `v${opts.version}`) : "";
9
+ return [
10
+ `${paint(on, "\x1B[38;2;99;102;241m\x1B[1m", "◆ MindeesNative")}${ver ? ` ${ver}` : ""}`,
11
+ paint(on, DIM, "The cross-platform framework built to make React Native & Flutter obsolete."),
12
+ paint(on, DIM, "One language · native performance · native look · instant updates")
13
+ ].join("\n");
14
+ }
15
+ /** The full banner: the inline logo image (if provided) above the {@link wordmark}. */
16
+ function renderBanner(opts = {}) {
17
+ const wm = wordmark(opts);
18
+ return opts.image ? `${opts.image}\n${wm}` : wm;
19
+ }
20
+ /**
21
+ * Build an iTerm2 / WezTerm inline-image escape (OSC 1337) for a base64-encoded PNG. The image is
22
+ * sized in terminal cells so the logo stays small.
23
+ */
24
+ function itermImage(base64, opts = {}) {
25
+ const args = ["inline=1", "preserveAspectRatio=1"];
26
+ if (opts.width) args.push(`width=${opts.width}`);
27
+ if (opts.height) args.push(`height=${opts.height}`);
28
+ return `\x1b]1337;File=${args.join(";")}:${base64}\x07`;
29
+ }
30
+ /** Detect terminal inline-image (iTerm2-protocol) support from environment variables. */
31
+ function detectImageSupport(env) {
32
+ if (env.LC_TERMINAL === "iTerm2") return "iterm";
33
+ const program = env.TERM_PROGRAM ?? "";
34
+ if (/iTerm|WezTerm|vscode/i.test(program)) return "iterm";
35
+ return null;
36
+ }
37
+ //#endregion
38
+ export { detectImageSupport, itermImage, renderBanner };
39
+
40
+ //# sourceMappingURL=banner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"banner.js","names":[],"sources":["../src/banner.ts"],"sourcesContent":["/**\n * The `mindees` CLI banner — shows the MindeesNative logo in a friendly way. On image-capable\n * terminals (iTerm2 / WezTerm / VS Code) it prints the actual logo PNG inline; everywhere else it\n * prints an ANSI wordmark. Pure functions only — the real terminal detection + file read live in\n * `bin.ts` and inject the result, so this stays testable.\n *\n * @module\n */\n\n/** Inputs for {@link renderBanner}. */\nexport interface BannerOptions {\n /** Emit ANSI color. `false` for piped output / `NO_COLOR`. */\n readonly color?: boolean\n /** A pre-built terminal inline-image escape (see {@link itermImage}); printed above the wordmark. */\n readonly image?: string | null\n /** Version string, shown next to the wordmark. */\n readonly version?: string\n}\n\nconst RESET = '\\x1b[0m'\nconst BRAND = '\\x1b[38;2;99;102;241m' // indigo — the flat-vector logo's accent\nconst BOLD = '\\x1b[1m'\nconst DIM = '\\x1b[2m'\n\nconst paint = (on: boolean, code: string, text: string): string =>\n on ? `${code}${text}${RESET}` : text\n\n/** The ANSI wordmark (always portable — works in every terminal, CI, and piped output). */\nexport function wordmark(opts: BannerOptions = {}): string {\n const on = opts.color !== false\n const ver = opts.version ? paint(on, DIM, `v${opts.version}`) : ''\n const title = `${paint(on, BRAND + BOLD, '◆ MindeesNative')}${ver ? ` ${ver}` : ''}`\n return [\n title,\n paint(on, DIM, 'The cross-platform framework built to make React Native & Flutter obsolete.'),\n paint(on, DIM, 'One language · native performance · native look · instant updates'),\n ].join('\\n')\n}\n\n/** The full banner: the inline logo image (if provided) above the {@link wordmark}. */\nexport function renderBanner(opts: BannerOptions = {}): string {\n const wm = wordmark(opts)\n return opts.image ? `${opts.image}\\n${wm}` : wm\n}\n\n/**\n * Build an iTerm2 / WezTerm inline-image escape (OSC 1337) for a base64-encoded PNG. The image is\n * sized in terminal cells so the logo stays small.\n */\nexport function itermImage(base64: string, opts: { width?: number; height?: number } = {}): string {\n const args = ['inline=1', 'preserveAspectRatio=1']\n if (opts.width) args.push(`width=${opts.width}`)\n if (opts.height) args.push(`height=${opts.height}`)\n return `\\x1b]1337;File=${args.join(';')}:${base64}\\x07`\n}\n\n/** Detect terminal inline-image (iTerm2-protocol) support from environment variables. */\nexport function detectImageSupport(env: Record<string, string | undefined>): 'iterm' | null {\n if (env.LC_TERMINAL === 'iTerm2') return 'iterm'\n const program = env.TERM_PROGRAM ?? ''\n if (/iTerm|WezTerm|vscode/i.test(program)) return 'iterm'\n return null\n}\n"],"mappings":";AAmBA,MAAM,QAAQ;AAGd,MAAM,MAAM;AAEZ,MAAM,SAAS,IAAa,MAAc,SACxC,KAAK,GAAG,OAAO,OAAO,UAAU;;AAGlC,SAAgB,SAAS,OAAsB,CAAC,GAAW;CACzD,MAAM,KAAK,KAAK,UAAU;CAC1B,MAAM,MAAM,KAAK,UAAU,MAAM,IAAI,KAAK,IAAI,KAAK,SAAS,IAAI;CAEhE,OAAO;EACL,GAFe,MAAM,IAAI,gCAAc,iBAAiB,IAAI,MAAM,KAAK,QAAQ;EAG/E,MAAM,IAAI,KAAK,6EAA6E;EAC5F,MAAM,IAAI,KAAK,mEAAmE;CACpF,EAAE,KAAK,IAAI;AACb;;AAGA,SAAgB,aAAa,OAAsB,CAAC,GAAW;CAC7D,MAAM,KAAK,SAAS,IAAI;CACxB,OAAO,KAAK,QAAQ,GAAG,KAAK,MAAM,IAAI,OAAO;AAC/C;;;;;AAMA,SAAgB,WAAW,QAAgB,OAA4C,CAAC,GAAW;CACjG,MAAM,OAAO,CAAC,YAAY,uBAAuB;CACjD,IAAI,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,OAAO;CAC/C,IAAI,KAAK,QAAQ,KAAK,KAAK,UAAU,KAAK,QAAQ;CAClD,OAAO,kBAAkB,KAAK,KAAK,GAAG,EAAE,GAAG,OAAO;AACpD;;AAGA,SAAgB,mBAAmB,KAAyD;CAC1F,IAAI,IAAI,gBAAgB,UAAU,OAAO;CACzC,MAAM,UAAU,IAAI,gBAAgB;CACpC,IAAI,wBAAwB,KAAK,OAAO,GAAG,OAAO;CAClD,OAAO;AACT"}
package/dist/bin.js CHANGED
@@ -3,6 +3,7 @@ import { VERSION } from "./version.js";
3
3
  import { runCliAsync } from "./cli.js";
4
4
  import { startDev } from "./dev.js";
5
5
  import { createDevServer, createNodeWatcher, renderDevPage } from "./dev-server.js";
6
+ import { detectImageSupport, itermImage, renderBanner } from "./banner.js";
6
7
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, watch, writeFileSync } from "node:fs";
7
8
  import { createServer } from "node:http";
8
9
  import { dirname, join, relative, sep } from "node:path";
@@ -102,19 +103,41 @@ function runDevServer(ctx) {
102
103
  });
103
104
  });
104
105
  }
106
+ /**
107
+ * Build the welcome banner for an interactive (TTY) session: the ANSI wordmark always, plus the
108
+ * actual logo PNG inline on image-capable terminals (iTerm2 / WezTerm). Returns `undefined` when
109
+ * stdout is piped (scripts get clean, parseable output).
110
+ */
111
+ function buildBanner() {
112
+ if (!process.stdout.isTTY) return void 0;
113
+ const color = !process.env.NO_COLOR;
114
+ let image = null;
115
+ if (detectImageSupport(process.env)) try {
116
+ image = itermImage(readFileSync(new URL("../assets/logo.png", import.meta.url)).toString("base64"), { width: 14 });
117
+ } catch {
118
+ image = null;
119
+ }
120
+ return renderBanner({
121
+ color,
122
+ image,
123
+ version: VERSION
124
+ });
125
+ }
105
126
  async function main() {
106
127
  const cwd = process.cwd();
107
128
  const write = (line) => {
108
129
  (line.stream === "err" ? process.stderr : process.stdout).write(`${line.text}\n`);
109
130
  };
110
131
  const backend = aiBackendFromEnv();
132
+ const banner = buildBanner();
111
133
  const ctx = {
112
134
  fs: nodeFileSystem(),
113
135
  env: probeEnv(cwd),
114
136
  cwd,
115
137
  version: VERSION,
116
138
  write,
117
- ...backend ? { aiBackend: backend } : {}
139
+ ...backend ? { aiBackend: backend } : {},
140
+ ...banner ? { banner } : {}
118
141
  };
119
142
  if (process.argv[2] === "dev") {
120
143
  runDevServer(ctx);
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","names":["fsWatch"],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * The `mindees` executable — a thin adapter that wires real Node capabilities\n * (filesystem, environment probe, stdout/stderr, AI backend) into the tested\n * {@link runCliAsync} core. All logic lives in the core; this file only does I/O wiring.\n *\n * @module\n */\n\nimport {\n existsSync,\n watch as fsWatch,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { createServer } from 'node:http'\nimport { dirname, join, relative, sep } from 'node:path'\nimport process from 'node:process'\nimport type { AiBackend } from '@mindees/ai'\nimport { type AdapterName, createServerBackend, type FetchLike } from '@mindees/ai/server'\nimport { type CliContext, runCliAsync } from './cli'\nimport { startDev } from './dev'\nimport { createDevServer, createNodeWatcher, renderDevPage } from './dev-server'\nimport type { FileSystem } from './fs'\nimport { VERSION } from './index'\nimport type { EnvProbe, OutputLine } from './types'\n\n/** A `node:fs`-backed {@link FileSystem}. */\nfunction nodeFileSystem(): FileSystem {\n return {\n exists: (path) => existsSync(path),\n readFile: (path) => readFileSync(path, 'utf8'),\n writeFile: (path, contents) => {\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n },\n mkdir: (path) => {\n mkdirSync(path, { recursive: true })\n },\n readDir: (dir) => {\n const walk = (current: string, acc: string[]): string[] => {\n if (!existsSync(current)) return acc\n for (const entry of readdirSync(current)) {\n const full = join(current, entry)\n if (statSync(full).isDirectory()) walk(full, acc)\n else acc.push(relative(dir, full).split(sep).join('/'))\n }\n return acc\n }\n return walk(dir, []).sort()\n },\n }\n}\n\n/** Probe the real environment for `doctor`/`info`. */\nfunction probeEnv(cwd: string): EnvProbe {\n const pmSpec = process.env.npm_config_user_agent ?? ''\n // user agent looks like \"pnpm/11.5.0 npm/? node/v24 ...\".\n const pmMatch = pmSpec.match(/^(\\w+)\\/(\\S+)/)\n return {\n nodeVersion: process.version,\n packageManager: pmMatch?.[1] && pmMatch[2] ? { name: pmMatch[1], version: pmMatch[2] } : null,\n hasPackageJson: existsSync(join(cwd, 'package.json')),\n hasNodeModules: existsSync(join(cwd, 'node_modules')),\n }\n}\n\n/** Build a server AI backend from `MINDEES_AI_*` env, or `undefined` if not configured. */\nfunction aiBackendFromEnv(): AiBackend | undefined {\n const baseUrl = process.env.MINDEES_AI_BASE_URL\n const model = process.env.MINDEES_AI_MODEL\n if (!baseUrl || !model) return undefined\n // Fail loud on a mistyped adapter rather than silently defaulting to openai (which would\n // build the wrong auth headers and yield confusing HTTP errors). Empty/unset → openai.\n const adapterEnv = process.env.MINDEES_AI_ADAPTER\n if (adapterEnv && adapterEnv !== 'openai' && adapterEnv !== 'anthropic') {\n process.stderr.write(\n `mindees: unknown MINDEES_AI_ADAPTER \"${adapterEnv}\" (expected \"openai\" or \"anthropic\"); AI backend not configured.\\n`,\n )\n return undefined\n }\n const adapter: AdapterName = adapterEnv === 'anthropic' ? 'anthropic' : 'openai'\n return createServerBackend({\n // The global `fetch` is structurally compatible at runtime; the minimal FetchLike\n // intentionally avoids the DOM lib, so cast rather than pull in those types.\n fetch: globalThis.fetch as unknown as FetchLike,\n baseUrl,\n model,\n adapter,\n ...(process.env.MINDEES_AI_API_KEY ? { apiKey: process.env.MINDEES_AI_API_KEY } : {}),\n })\n}\n\n/**\n * `mindees dev` — the long-running transport over the tested {@link startDev} orchestrator:\n * build + watch `src/`, serve a live-reload preview, and reload the browser on each rebuild. This\n * is the I/O glue; the watcher, server, and orchestrator it wires are unit-tested in their modules.\n */\nfunction runDevServer(ctx: CliContext): void {\n const port = Number(process.env.MINDEES_DEV_PORT ?? 3000) || 3000\n const server = createDevServer({ html: '<body>MindeesNative dev — building…</body>' })\n const watcher = createNodeWatcher(['src'], {\n watch: (path, opts, listener) =>\n fsWatch(path, { recursive: opts.recursive ?? false }, (event, filename) =>\n listener(event, typeof filename === 'string' ? filename : null),\n ),\n })\n startDev(ctx.fs, watcher, {\n onRebuild: (result) => {\n server.setHtml(renderDevPage(result))\n server.bump()\n ctx.write({\n text: result.ok\n ? `rebuilt: ${result.compiled.length} file(s) ok`\n : `rebuild failed: ${result.diagnostics.filter((d) => d.severity === 'error').length} error(s)`,\n stream: result.ok ? 'out' : 'err',\n })\n },\n })\n createServer((req, res) => {\n const out = server.handle(req.method ?? 'GET', req.url ?? '/')\n res.writeHead(out.status, out.headers)\n res.end(out.body)\n }).listen(port, () => {\n ctx.write({\n text: `mindees dev — serving http://localhost:${port} (live reload on)`,\n stream: 'out',\n })\n })\n}\n\nasync function main(): Promise<void> {\n const cwd = process.cwd()\n const write = (line: OutputLine): void => {\n const stream = line.stream === 'err' ? process.stderr : process.stdout\n stream.write(`${line.text}\\n`)\n }\n const backend = aiBackendFromEnv()\n const ctx: CliContext = {\n fs: nodeFileSystem(),\n env: probeEnv(cwd),\n cwd,\n version: VERSION,\n write,\n ...(backend ? { aiBackend: backend } : {}),\n }\n // `dev` is a long-running transport (not a one-shot command), so it's wired here in the I/O entry\n // rather than the synchronous CLI dispatch. Everything else goes through the tested core.\n if (process.argv[2] === 'dev') {\n runDevServer(ctx)\n return\n }\n const { exitCode } = await runCliAsync(process.argv.slice(2), ctx)\n process.exitCode = exitCode\n}\n\nmain()\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","names":["fsWatch"],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * The `mindees` executable — a thin adapter that wires real Node capabilities\n * (filesystem, environment probe, stdout/stderr, AI backend) into the tested\n * {@link runCliAsync} core. All logic lives in the core; this file only does I/O wiring.\n *\n * @module\n */\n\nimport {\n existsSync,\n watch as fsWatch,\n mkdirSync,\n readdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from 'node:fs'\nimport { createServer } from 'node:http'\nimport { dirname, join, relative, sep } from 'node:path'\nimport process from 'node:process'\nimport type { AiBackend } from '@mindees/ai'\nimport { type AdapterName, createServerBackend, type FetchLike } from '@mindees/ai/server'\nimport { detectImageSupport, itermImage, renderBanner } from './banner'\nimport { type CliContext, runCliAsync } from './cli'\nimport { startDev } from './dev'\nimport { createDevServer, createNodeWatcher, renderDevPage } from './dev-server'\nimport type { FileSystem } from './fs'\nimport { VERSION } from './index'\nimport type { EnvProbe, OutputLine } from './types'\n\n/** A `node:fs`-backed {@link FileSystem}. */\nfunction nodeFileSystem(): FileSystem {\n return {\n exists: (path) => existsSync(path),\n readFile: (path) => readFileSync(path, 'utf8'),\n writeFile: (path, contents) => {\n mkdirSync(dirname(path), { recursive: true })\n writeFileSync(path, contents, 'utf8')\n },\n mkdir: (path) => {\n mkdirSync(path, { recursive: true })\n },\n readDir: (dir) => {\n const walk = (current: string, acc: string[]): string[] => {\n if (!existsSync(current)) return acc\n for (const entry of readdirSync(current)) {\n const full = join(current, entry)\n if (statSync(full).isDirectory()) walk(full, acc)\n else acc.push(relative(dir, full).split(sep).join('/'))\n }\n return acc\n }\n return walk(dir, []).sort()\n },\n }\n}\n\n/** Probe the real environment for `doctor`/`info`. */\nfunction probeEnv(cwd: string): EnvProbe {\n const pmSpec = process.env.npm_config_user_agent ?? ''\n // user agent looks like \"pnpm/11.5.0 npm/? node/v24 ...\".\n const pmMatch = pmSpec.match(/^(\\w+)\\/(\\S+)/)\n return {\n nodeVersion: process.version,\n packageManager: pmMatch?.[1] && pmMatch[2] ? { name: pmMatch[1], version: pmMatch[2] } : null,\n hasPackageJson: existsSync(join(cwd, 'package.json')),\n hasNodeModules: existsSync(join(cwd, 'node_modules')),\n }\n}\n\n/** Build a server AI backend from `MINDEES_AI_*` env, or `undefined` if not configured. */\nfunction aiBackendFromEnv(): AiBackend | undefined {\n const baseUrl = process.env.MINDEES_AI_BASE_URL\n const model = process.env.MINDEES_AI_MODEL\n if (!baseUrl || !model) return undefined\n // Fail loud on a mistyped adapter rather than silently defaulting to openai (which would\n // build the wrong auth headers and yield confusing HTTP errors). Empty/unset → openai.\n const adapterEnv = process.env.MINDEES_AI_ADAPTER\n if (adapterEnv && adapterEnv !== 'openai' && adapterEnv !== 'anthropic') {\n process.stderr.write(\n `mindees: unknown MINDEES_AI_ADAPTER \"${adapterEnv}\" (expected \"openai\" or \"anthropic\"); AI backend not configured.\\n`,\n )\n return undefined\n }\n const adapter: AdapterName = adapterEnv === 'anthropic' ? 'anthropic' : 'openai'\n return createServerBackend({\n // The global `fetch` is structurally compatible at runtime; the minimal FetchLike\n // intentionally avoids the DOM lib, so cast rather than pull in those types.\n fetch: globalThis.fetch as unknown as FetchLike,\n baseUrl,\n model,\n adapter,\n ...(process.env.MINDEES_AI_API_KEY ? { apiKey: process.env.MINDEES_AI_API_KEY } : {}),\n })\n}\n\n/**\n * `mindees dev` — the long-running transport over the tested {@link startDev} orchestrator:\n * build + watch `src/`, serve a live-reload preview, and reload the browser on each rebuild. This\n * is the I/O glue; the watcher, server, and orchestrator it wires are unit-tested in their modules.\n */\nfunction runDevServer(ctx: CliContext): void {\n const port = Number(process.env.MINDEES_DEV_PORT ?? 3000) || 3000\n const server = createDevServer({ html: '<body>MindeesNative dev — building…</body>' })\n const watcher = createNodeWatcher(['src'], {\n watch: (path, opts, listener) =>\n fsWatch(path, { recursive: opts.recursive ?? false }, (event, filename) =>\n listener(event, typeof filename === 'string' ? filename : null),\n ),\n })\n startDev(ctx.fs, watcher, {\n onRebuild: (result) => {\n server.setHtml(renderDevPage(result))\n server.bump()\n ctx.write({\n text: result.ok\n ? `rebuilt: ${result.compiled.length} file(s) ok`\n : `rebuild failed: ${result.diagnostics.filter((d) => d.severity === 'error').length} error(s)`,\n stream: result.ok ? 'out' : 'err',\n })\n },\n })\n createServer((req, res) => {\n const out = server.handle(req.method ?? 'GET', req.url ?? '/')\n res.writeHead(out.status, out.headers)\n res.end(out.body)\n }).listen(port, () => {\n ctx.write({\n text: `mindees dev — serving http://localhost:${port} (live reload on)`,\n stream: 'out',\n })\n })\n}\n\n/**\n * Build the welcome banner for an interactive (TTY) session: the ANSI wordmark always, plus the\n * actual logo PNG inline on image-capable terminals (iTerm2 / WezTerm). Returns `undefined` when\n * stdout is piped (scripts get clean, parseable output).\n */\nfunction buildBanner(): string | undefined {\n if (!process.stdout.isTTY) return undefined\n const color = !process.env.NO_COLOR\n let image: string | null = null\n if (detectImageSupport(process.env)) {\n try {\n const bytes = readFileSync(new URL('../assets/logo.png', import.meta.url))\n image = itermImage(bytes.toString('base64'), { width: 14 })\n } catch {\n image = null // asset missing → wordmark only\n }\n }\n return renderBanner({ color, image, version: VERSION })\n}\n\nasync function main(): Promise<void> {\n const cwd = process.cwd()\n const write = (line: OutputLine): void => {\n const stream = line.stream === 'err' ? process.stderr : process.stdout\n stream.write(`${line.text}\\n`)\n }\n const backend = aiBackendFromEnv()\n const banner = buildBanner()\n const ctx: CliContext = {\n fs: nodeFileSystem(),\n env: probeEnv(cwd),\n cwd,\n version: VERSION,\n write,\n ...(backend ? { aiBackend: backend } : {}),\n ...(banner ? { banner } : {}),\n }\n // `dev` is a long-running transport (not a one-shot command), so it's wired here in the I/O entry\n // rather than the synchronous CLI dispatch. Everything else goes through the tested core.\n if (process.argv[2] === 'dev') {\n runDevServer(ctx)\n return\n }\n const { exitCode } = await runCliAsync(process.argv.slice(2), ctx)\n process.exitCode = exitCode\n}\n\nmain()\n"],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -15,6 +15,8 @@ interface CliContext {
15
15
  write: Writer;
16
16
  /** AI backend for `ai` commands (wired from `MINDEES_AI_*` env in `bin`). */
17
17
  aiBackend?: AiBackend;
18
+ /** Pre-rendered welcome banner (the MindeesNative logo). Shown on `help` + `create` success; injected by `bin` for TTYs. */
19
+ banner?: string;
18
20
  }
19
21
  /**
20
22
  * Run the CLI. Returns a {@link CommandResult} with the process exit code.
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli.ts"],"mappings":";;;;;;UAwBiB,UAAA;EACf,EAAA,EAAI,UAAA;EACJ,GAAA,EAAK,QAAA;EAAA;EAEL,GAAA;EAEA;EAAA,OAAA;EAEO;EAAP,KAAA,EAAO,MAAA;EAEK;EAAZ,SAAA,GAAY,SAAA;AAAA;AAqCd;;;;AAAA,iBAAgB,MAAA,CAAO,IAAA,qBAAyB,GAAA,EAAK,UAAA,GAAa,aAAa;;;;;AAAA;iBAmC/D,WAAA,CAAY,IAAA,qBAAyB,GAAA,EAAK,UAAA,GAAa,OAAA,CAAQ,aAAA"}
1
+ {"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli.ts"],"mappings":";;;;;;UAwBiB,UAAA;EACf,EAAA,EAAI,UAAA;EACJ,GAAA,EAAK,QAAA;EAAA;EAEL,GAAA;EAEA;EAAA,OAAA;EAEO;EAAP,KAAA,EAAO,MAAA;EAEK;EAAZ,SAAA,GAAY,SAAA;EAEN;EAAN,MAAA;AAAA;;;;;iBAyCc,MAAA,CAAO,IAAA,qBAAyB,GAAA,EAAK,UAAA,GAAa,aAAa;;;;AAAA;AAoC/E;iBAAgB,WAAA,CAAY,IAAA,qBAAyB,GAAA,EAAK,UAAA,GAAa,OAAA,CAAQ,aAAA"}
package/dist/cli.js CHANGED
@@ -44,6 +44,10 @@ function out(write, text) {
44
44
  text
45
45
  });
46
46
  }
47
+ /** Print the welcome banner (the logo), if one was injected (TTY sessions). */
48
+ function printBanner(ctx) {
49
+ if (ctx.banner) out(ctx.write, ctx.banner);
50
+ }
47
51
  function err(write, text) {
48
52
  write({
49
53
  stream: "err",
@@ -57,6 +61,7 @@ function err(write, text) {
57
61
  function runCli(argv, ctx) {
58
62
  const [command, ...rest] = argv;
59
63
  if (!command || command === "help" || command === "--help" || command === "-h") {
64
+ printBanner(ctx);
60
65
  out(ctx.write, HELP);
61
66
  return { exitCode: 0 };
62
67
  }
@@ -140,6 +145,7 @@ function cmdCreate(args, ctx) {
140
145
  err(ctx.write, result.error ?? "create failed");
141
146
  return { exitCode: 1 };
142
147
  }
148
+ printBanner(ctx);
143
149
  out(ctx.write, `Created "${target.packageName}" from the ${result.template} template (${result.written.length} files).`);
144
150
  out(ctx.write, `Next: cd ${quoteShellPath(target.displayDir)} && pnpm install && mindees dev`);
145
151
  return { exitCode: 0 };
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["/**\n * Forge CLI dispatch — `mindees <command> [args]`.\n *\n * `runCli` is a pure function of (argv, context) → exit code, writing structured\n * output through an injected {@link Writer}. All side-effecting capabilities\n * (filesystem, env probe) are injected via {@link CliContext}, so the entire CLI\n * is deterministically testable; the thin `bin` entrypoint wires real adapters.\n *\n * @module\n */\n\nimport { parseArgs } from 'node:util'\nimport type { AiBackend } from '@mindees/ai'\nimport { runAiCommand } from './ai'\nimport { buildProject } from './build'\nimport { quoteShellPath, resolveCreateTarget } from './create-target'\nimport { doctorSummary, renderDoctor, runDoctor } from './doctor'\nimport type { FileSystem } from './fs'\nimport { naturalLanguageToTemplate } from './nl'\nimport { scaffold } from './scaffold'\nimport { DEFAULT_TEMPLATE, templateNames } from './templates'\nimport type { CommandResult, EnvProbe, Writer } from './types'\n\n/** Everything the CLI needs from the outside world (injected for testability). */\nexport interface CliContext {\n fs: FileSystem\n env: EnvProbe\n /** Working directory (where `create` writes, what `build` reads). */\n cwd: string\n /** CLI version string (from package metadata). */\n version: string\n /** Output sink. */\n write: Writer\n /** AI backend for `ai` commands (wired from `MINDEES_AI_*` env in `bin`). */\n aiBackend?: AiBackend\n}\n\nconst HELP = `mindees — the MindeesNative CLI (Forge)\n\nUsage: mindees <command> [options]\n\nCommands:\n create <name> Scaffold a new app (--template <name>, --force)\n build Type-check + compile the project (--out-dir <dir>)\n dev Build and rebuild on change (developer preview)\n doctor Diagnose your environment\n info Show CLI + environment info\n ai explain <err> Explain an error with AI (needs MINDEES_AI_* env)\n help Show this help\n\nRun \\`mindees create --help\\` style flags inline. Templates: ${templateNames().join(', ')}.`\n\nconst CREATE_HELP = `Usage: mindees create <name-or-path> [options]\n\nOptions:\n -t, --template <name> Template to scaffold (${templateNames().join(', ')})\n -p, --prompt <text> Pick a template from a short prompt\n --force Overwrite a non-empty target directory\n -h, --help Show this help`\n\nfunction out(write: Writer, text: string): void {\n write({ stream: 'out', text })\n}\nfunction err(write: Writer, text: string): void {\n write({ stream: 'err', text })\n}\n\n/**\n * Run the CLI. Returns a {@link CommandResult} with the process exit code.\n * Never throws for expected failures — it reports them and returns non-zero.\n */\nexport function runCli(argv: readonly string[], ctx: CliContext): CommandResult {\n const [command, ...rest] = argv\n\n if (!command || command === 'help' || command === '--help' || command === '-h') {\n out(ctx.write, HELP)\n return { exitCode: 0 }\n }\n\n if (command === '--version' || command === '-v' || command === 'version') {\n out(ctx.write, ctx.version)\n return { exitCode: 0 }\n }\n\n switch (command) {\n case 'create':\n return cmdCreate(rest, ctx)\n case 'build':\n return cmdBuild(rest, ctx)\n case 'dev':\n return cmdDev(ctx)\n case 'doctor':\n return cmdDoctor(ctx)\n case 'info':\n return cmdInfo(ctx)\n default:\n err(ctx.write, `Unknown command \"${command}\". Run \\`mindees help\\`.`)\n return { exitCode: 1 }\n }\n}\n\n/**\n * The async CLI entry. Handles the model-calling `ai` command (which is asynchronous) and\n * delegates every synchronous command to {@link runCli}. The `bin` calls this; tests can call\n * either (sync commands stay testable through `runCli`).\n */\nexport function runCliAsync(argv: readonly string[], ctx: CliContext): Promise<CommandResult> {\n const [command, ...rest] = argv\n if (command === 'ai') {\n return runAiCommand(rest, {\n write: ctx.write,\n ...(ctx.aiBackend ? { backend: ctx.aiBackend } : {}),\n })\n }\n return Promise.resolve(runCli(argv, ctx))\n}\n\nfunction cmdCreate(args: readonly string[], ctx: CliContext): CommandResult {\n const { values, positionals } = parseArgs({\n args: [...args],\n allowPositionals: true,\n strict: false,\n options: {\n help: { type: 'boolean', short: 'h' },\n template: { type: 'string', short: 't' },\n force: { type: 'boolean' },\n prompt: { type: 'string', short: 'p' },\n },\n })\n\n if (values.help === true || positionals[0] === 'help') {\n out(ctx.write, CREATE_HELP)\n return { exitCode: 0 }\n }\n\n const name = positionals[0]\n if (!name) {\n err(ctx.write, 'create: missing app name or target path. Usage: mindees create <name-or-path>')\n return { exitCode: 1 }\n }\n\n // NL → template: `--prompt \"a counter app\"` picks a template deterministically\n // (offline). Real AI generation arrives with Synapse in Phase 10; until then\n // this is an honest keyword-based mapping that never blocks `create`. An\n // explicit `--template` always wins; the prompt only resolves a template when\n // the caller didn't choose one (mirrors `create-mindees`'s runCreate so both\n // entrypoints agree on precedence).\n // Treat a present-but-empty `--template \"\"` as \"not chosen\" (defer to prompt/default),\n // matching create-mindees's runCreate so both entrypoints agree on precedence.\n const explicitTemplate =\n typeof values.template === 'string' && values.template.length > 0 ? values.template : undefined\n let template = explicitTemplate ?? DEFAULT_TEMPLATE\n if (\n explicitTemplate === undefined &&\n typeof values.prompt === 'string' &&\n values.prompt.length > 0\n ) {\n const picked = naturalLanguageToTemplate(values.prompt)\n template = picked.template\n out(ctx.write, `Interpreted prompt → \"${picked.template}\" template (${picked.reason}).`)\n }\n\n const target = resolveCreateTarget(name, ctx.cwd)\n if (!target.ok) {\n err(ctx.write, target.error)\n return { exitCode: 1 }\n }\n\n const result = scaffold(ctx.fs, {\n appName: target.packageName,\n targetDir: target.targetDir,\n template,\n force: values.force === true,\n })\n\n if (!result.ok) {\n err(ctx.write, result.error ?? 'create failed')\n return { exitCode: 1 }\n }\n\n out(\n ctx.write,\n `Created \"${target.packageName}\" from the ${result.template} template (${result.written.length} files).`,\n )\n out(ctx.write, `Next: cd ${quoteShellPath(target.displayDir)} && pnpm install && mindees dev`)\n return { exitCode: 0 }\n}\n\nfunction cmdBuild(args: readonly string[], ctx: CliContext): CommandResult {\n const { values } = parseArgs({\n args: [...args],\n allowPositionals: true,\n strict: false,\n options: { 'out-dir': { type: 'string' }, 'no-source-map': { type: 'boolean' } },\n })\n\n const result = buildProject(ctx.fs, {\n root: ctx.cwd,\n outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : `${ctx.cwd}/dist`,\n sourceMap: values['no-source-map'] !== true,\n })\n\n for (const d of result.diagnostics) {\n const where = d.file ? `${d.file}${d.position ? `:${d.position.line}` : ''}: ` : ''\n err(ctx.write, `${d.severity} ${d.code} ${where}${d.message}`)\n }\n\n if (!result.ok) {\n err(ctx.write, 'Build failed: fix the type errors above.')\n return { exitCode: 1 }\n }\n out(\n ctx.write,\n `Built ${result.compiled.length} module(s); flattened ${result.stats.flattenedNodes}/${result.stats.totalElements} elements.`,\n )\n return { exitCode: 0 }\n}\n\nfunction cmdDev(ctx: CliContext): CommandResult {\n // The dev server transport (HTTP + HMR socket) is a developer-preview layer in\n // `bin`. The CLI command here reports how to use it; the tested rebuild\n // orchestrator lives in `dev.ts` (`startDev`).\n out(ctx.write, 'mindees dev — build + watch + live-reload preview.')\n out(\n ctx.write,\n 'Run via the `mindees` binary (it starts the HTTP server); set MINDEES_DEV_PORT to',\n )\n out(\n ctx.write,\n 'override the port (default 3000). The browser reloads automatically on each rebuild.',\n )\n return { exitCode: 0 }\n}\n\nfunction cmdDoctor(ctx: CliContext): CommandResult {\n const checks = runDoctor(ctx.env)\n for (const line of renderDoctor(checks)) out(ctx.write, line)\n const summary = doctorSummary(checks)\n return { exitCode: summary === 'fail' ? 1 : 0 }\n}\n\nfunction cmdInfo(ctx: CliContext): CommandResult {\n out(ctx.write, `mindees CLI ${ctx.version}`)\n out(ctx.write, `Node ${ctx.env.nodeVersion}`)\n out(\n ctx.write,\n `Package manager: ${ctx.env.packageManager ? `${ctx.env.packageManager.name} ${ctx.env.packageManager.version}` : 'none'}`,\n )\n out(ctx.write, `Templates: ${templateNames().join(', ')}`)\n return { exitCode: 0 }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["/**\n * Forge CLI dispatch — `mindees <command> [args]`.\n *\n * `runCli` is a pure function of (argv, context) → exit code, writing structured\n * output through an injected {@link Writer}. All side-effecting capabilities\n * (filesystem, env probe) are injected via {@link CliContext}, so the entire CLI\n * is deterministically testable; the thin `bin` entrypoint wires real adapters.\n *\n * @module\n */\n\nimport { parseArgs } from 'node:util'\nimport type { AiBackend } from '@mindees/ai'\nimport { runAiCommand } from './ai'\nimport { buildProject } from './build'\nimport { quoteShellPath, resolveCreateTarget } from './create-target'\nimport { doctorSummary, renderDoctor, runDoctor } from './doctor'\nimport type { FileSystem } from './fs'\nimport { naturalLanguageToTemplate } from './nl'\nimport { scaffold } from './scaffold'\nimport { DEFAULT_TEMPLATE, templateNames } from './templates'\nimport type { CommandResult, EnvProbe, Writer } from './types'\n\n/** Everything the CLI needs from the outside world (injected for testability). */\nexport interface CliContext {\n fs: FileSystem\n env: EnvProbe\n /** Working directory (where `create` writes, what `build` reads). */\n cwd: string\n /** CLI version string (from package metadata). */\n version: string\n /** Output sink. */\n write: Writer\n /** AI backend for `ai` commands (wired from `MINDEES_AI_*` env in `bin`). */\n aiBackend?: AiBackend\n /** Pre-rendered welcome banner (the MindeesNative logo). Shown on `help` + `create` success; injected by `bin` for TTYs. */\n banner?: string\n}\n\nconst HELP = `mindees — the MindeesNative CLI (Forge)\n\nUsage: mindees <command> [options]\n\nCommands:\n create <name> Scaffold a new app (--template <name>, --force)\n build Type-check + compile the project (--out-dir <dir>)\n dev Build and rebuild on change (developer preview)\n doctor Diagnose your environment\n info Show CLI + environment info\n ai explain <err> Explain an error with AI (needs MINDEES_AI_* env)\n help Show this help\n\nRun \\`mindees create --help\\` style flags inline. Templates: ${templateNames().join(', ')}.`\n\nconst CREATE_HELP = `Usage: mindees create <name-or-path> [options]\n\nOptions:\n -t, --template <name> Template to scaffold (${templateNames().join(', ')})\n -p, --prompt <text> Pick a template from a short prompt\n --force Overwrite a non-empty target directory\n -h, --help Show this help`\n\nfunction out(write: Writer, text: string): void {\n write({ stream: 'out', text })\n}\n/** Print the welcome banner (the logo), if one was injected (TTY sessions). */\nfunction printBanner(ctx: CliContext): void {\n if (ctx.banner) out(ctx.write, ctx.banner)\n}\nfunction err(write: Writer, text: string): void {\n write({ stream: 'err', text })\n}\n\n/**\n * Run the CLI. Returns a {@link CommandResult} with the process exit code.\n * Never throws for expected failures — it reports them and returns non-zero.\n */\nexport function runCli(argv: readonly string[], ctx: CliContext): CommandResult {\n const [command, ...rest] = argv\n\n if (!command || command === 'help' || command === '--help' || command === '-h') {\n printBanner(ctx)\n out(ctx.write, HELP)\n return { exitCode: 0 }\n }\n\n if (command === '--version' || command === '-v' || command === 'version') {\n out(ctx.write, ctx.version)\n return { exitCode: 0 }\n }\n\n switch (command) {\n case 'create':\n return cmdCreate(rest, ctx)\n case 'build':\n return cmdBuild(rest, ctx)\n case 'dev':\n return cmdDev(ctx)\n case 'doctor':\n return cmdDoctor(ctx)\n case 'info':\n return cmdInfo(ctx)\n default:\n err(ctx.write, `Unknown command \"${command}\". Run \\`mindees help\\`.`)\n return { exitCode: 1 }\n }\n}\n\n/**\n * The async CLI entry. Handles the model-calling `ai` command (which is asynchronous) and\n * delegates every synchronous command to {@link runCli}. The `bin` calls this; tests can call\n * either (sync commands stay testable through `runCli`).\n */\nexport function runCliAsync(argv: readonly string[], ctx: CliContext): Promise<CommandResult> {\n const [command, ...rest] = argv\n if (command === 'ai') {\n return runAiCommand(rest, {\n write: ctx.write,\n ...(ctx.aiBackend ? { backend: ctx.aiBackend } : {}),\n })\n }\n return Promise.resolve(runCli(argv, ctx))\n}\n\nfunction cmdCreate(args: readonly string[], ctx: CliContext): CommandResult {\n const { values, positionals } = parseArgs({\n args: [...args],\n allowPositionals: true,\n strict: false,\n options: {\n help: { type: 'boolean', short: 'h' },\n template: { type: 'string', short: 't' },\n force: { type: 'boolean' },\n prompt: { type: 'string', short: 'p' },\n },\n })\n\n if (values.help === true || positionals[0] === 'help') {\n out(ctx.write, CREATE_HELP)\n return { exitCode: 0 }\n }\n\n const name = positionals[0]\n if (!name) {\n err(ctx.write, 'create: missing app name or target path. Usage: mindees create <name-or-path>')\n return { exitCode: 1 }\n }\n\n // NL → template: `--prompt \"a counter app\"` picks a template deterministically\n // (offline). Real AI generation arrives with Synapse in Phase 10; until then\n // this is an honest keyword-based mapping that never blocks `create`. An\n // explicit `--template` always wins; the prompt only resolves a template when\n // the caller didn't choose one (mirrors `create-mindees`'s runCreate so both\n // entrypoints agree on precedence).\n // Treat a present-but-empty `--template \"\"` as \"not chosen\" (defer to prompt/default),\n // matching create-mindees's runCreate so both entrypoints agree on precedence.\n const explicitTemplate =\n typeof values.template === 'string' && values.template.length > 0 ? values.template : undefined\n let template = explicitTemplate ?? DEFAULT_TEMPLATE\n if (\n explicitTemplate === undefined &&\n typeof values.prompt === 'string' &&\n values.prompt.length > 0\n ) {\n const picked = naturalLanguageToTemplate(values.prompt)\n template = picked.template\n out(ctx.write, `Interpreted prompt → \"${picked.template}\" template (${picked.reason}).`)\n }\n\n const target = resolveCreateTarget(name, ctx.cwd)\n if (!target.ok) {\n err(ctx.write, target.error)\n return { exitCode: 1 }\n }\n\n const result = scaffold(ctx.fs, {\n appName: target.packageName,\n targetDir: target.targetDir,\n template,\n force: values.force === true,\n })\n\n if (!result.ok) {\n err(ctx.write, result.error ?? 'create failed')\n return { exitCode: 1 }\n }\n\n printBanner(ctx)\n out(\n ctx.write,\n `Created \"${target.packageName}\" from the ${result.template} template (${result.written.length} files).`,\n )\n out(ctx.write, `Next: cd ${quoteShellPath(target.displayDir)} && pnpm install && mindees dev`)\n return { exitCode: 0 }\n}\n\nfunction cmdBuild(args: readonly string[], ctx: CliContext): CommandResult {\n const { values } = parseArgs({\n args: [...args],\n allowPositionals: true,\n strict: false,\n options: { 'out-dir': { type: 'string' }, 'no-source-map': { type: 'boolean' } },\n })\n\n const result = buildProject(ctx.fs, {\n root: ctx.cwd,\n outDir: typeof values['out-dir'] === 'string' ? values['out-dir'] : `${ctx.cwd}/dist`,\n sourceMap: values['no-source-map'] !== true,\n })\n\n for (const d of result.diagnostics) {\n const where = d.file ? `${d.file}${d.position ? `:${d.position.line}` : ''}: ` : ''\n err(ctx.write, `${d.severity} ${d.code} ${where}${d.message}`)\n }\n\n if (!result.ok) {\n err(ctx.write, 'Build failed: fix the type errors above.')\n return { exitCode: 1 }\n }\n out(\n ctx.write,\n `Built ${result.compiled.length} module(s); flattened ${result.stats.flattenedNodes}/${result.stats.totalElements} elements.`,\n )\n return { exitCode: 0 }\n}\n\nfunction cmdDev(ctx: CliContext): CommandResult {\n // The dev server transport (HTTP + HMR socket) is a developer-preview layer in\n // `bin`. The CLI command here reports how to use it; the tested rebuild\n // orchestrator lives in `dev.ts` (`startDev`).\n out(ctx.write, 'mindees dev — build + watch + live-reload preview.')\n out(\n ctx.write,\n 'Run via the `mindees` binary (it starts the HTTP server); set MINDEES_DEV_PORT to',\n )\n out(\n ctx.write,\n 'override the port (default 3000). The browser reloads automatically on each rebuild.',\n )\n return { exitCode: 0 }\n}\n\nfunction cmdDoctor(ctx: CliContext): CommandResult {\n const checks = runDoctor(ctx.env)\n for (const line of renderDoctor(checks)) out(ctx.write, line)\n const summary = doctorSummary(checks)\n return { exitCode: summary === 'fail' ? 1 : 0 }\n}\n\nfunction cmdInfo(ctx: CliContext): CommandResult {\n out(ctx.write, `mindees CLI ${ctx.version}`)\n out(ctx.write, `Node ${ctx.env.nodeVersion}`)\n out(\n ctx.write,\n `Package manager: ${ctx.env.packageManager ? `${ctx.env.packageManager.name} ${ctx.env.packageManager.version}` : 'none'}`,\n )\n out(ctx.write, `Templates: ${templateNames().join(', ')}`)\n return { exitCode: 0 }\n}\n"],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -11,7 +11,7 @@
11
11
  * @module
12
12
  */
13
13
  /** The package version. All `@mindees/*` packages share one locked version line. */
14
- declare const VERSION = "0.5.0";
14
+ declare const VERSION = "0.7.0";
15
15
  //#endregion
16
16
  export { VERSION };
17
17
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * @module
12
12
  */
13
13
  /** The package version. All `@mindees/*` packages share one locked version line. */
14
- const VERSION = "0.5.0";
14
+ const VERSION = "0.7.0";
15
15
  //#endregion
16
16
  export { VERSION };
17
17
 
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the `@mindees/cli` package version.\n *\n * All `@mindees/*` packages share one locked version line (Changesets, fixed\n * group). Keeping it in its own dependency-free module lets both the public\n * package metadata ({@link index}) and the scaffolder's generated\n * `package.json` ({@link templates}) pin to the same value without a circular\n * import.\n *\n * @module\n */\n\n/** The package version. All `@mindees/*` packages share one locked version line. */\nexport const VERSION = '0.5.0'\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,UAAU"}
1
+ {"version":3,"file":"version.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["/**\n * Single source of truth for the `@mindees/cli` package version.\n *\n * All `@mindees/*` packages share one locked version line (Changesets, fixed\n * group). Keeping it in its own dependency-free module lets both the public\n * package metadata ({@link index}) and the scaffolder's generated\n * `package.json` ({@link templates}) pin to the same value without a circular\n * import.\n *\n * @module\n */\n\n/** The package version. All `@mindees/*` packages share one locked version line. */\nexport const VERSION = '0.7.0'\n"],"mappings":";;;;;;;;;;;;;AAaA,MAAa,UAAU"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindees/cli",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "MindeesNative Forge — the `mindees` CLI: create, build (via the compiler), dev (rebuild orchestrator), doctor, info.",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "type": "module",
@@ -9,7 +9,8 @@
9
9
  "mindees": "./dist/bin.js"
10
10
  },
11
11
  "files": [
12
- "dist"
12
+ "dist",
13
+ "assets"
13
14
  ],
14
15
  "exports": {
15
16
  ".": {
@@ -26,9 +27,9 @@
26
27
  "directory": "packages/cli"
27
28
  },
28
29
  "dependencies": {
29
- "@mindees/core": "0.5.0",
30
- "@mindees/compiler": "0.5.0",
31
- "@mindees/ai": "0.5.0"
30
+ "@mindees/core": "0.7.0",
31
+ "@mindees/compiler": "0.7.0",
32
+ "@mindees/ai": "0.7.0"
32
33
  },
33
34
  "scripts": {
34
35
  "build": "tsdown",