@bonginkan/maria 4.3.16 → 4.3.18

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/dist/cli.cjs CHANGED
@@ -1704,7 +1704,7 @@ var init_AuthenticationManager = __esm({
1704
1704
  const response = await fetch(`${this.apiBase}/api/user/profile`, {
1705
1705
  headers: {
1706
1706
  "Authorization": `Bearer ${tokens2.accessToken}`,
1707
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.16"}`
1707
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.18"}`
1708
1708
  }
1709
1709
  });
1710
1710
  if (response.status === 401) {
@@ -2407,7 +2407,7 @@ async function callApi(path60, init3 = {}) {
2407
2407
  "Authorization": `Bearer ${token}`,
2408
2408
  "X-Device-Id": getDeviceId(),
2409
2409
  "X-Session-Id": getSessionId() || "",
2410
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.16"}`,
2410
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.18"}`,
2411
2411
  "Content-Type": init3.headers?.["Content-Type"] || "application/json"
2412
2412
  });
2413
2413
  const doFetch = async (token) => {
@@ -16071,8 +16071,8 @@ var require_package = __commonJS({
16071
16071
  "package.json"(exports, module) {
16072
16072
  module.exports = {
16073
16073
  name: "@bonginkan/maria",
16074
- version: "4.3.16",
16075
- description: "\u{1F680} MARIA v4.3.16 - Enterprise AI Development Platform with identity system and character voice implementation. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
16074
+ version: "4.3.18",
16075
+ description: "\u{1F680} MARIA v4.3.18 - Enterprise AI Development Platform with identity system and character voice implementation. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
16076
16076
  keywords: [
16077
16077
  "ai",
16078
16078
  "cli",
@@ -22403,6 +22403,15 @@ async function hasCaseInsensitiveCollision(dirFull, targetFile) {
22403
22403
  async function atomicRename(stage, dest) {
22404
22404
  try {
22405
22405
  await fsp__namespace.rename(stage, dest);
22406
+ try {
22407
+ const fd = await fsp__namespace.open(dest, "r");
22408
+ try {
22409
+ await fd.sync();
22410
+ } finally {
22411
+ await fd.close();
22412
+ }
22413
+ } catch {
22414
+ }
22406
22415
  } catch (e2) {
22407
22416
  if (e2 && e2.code === "EXDEV") {
22408
22417
  await fsp__namespace.copyFile(stage, dest);
@@ -22457,7 +22466,8 @@ async function saveArtifacts(ctx2, items, manifest) {
22457
22466
  }
22458
22467
  await fsp__namespace.writeFile(stg, it.bytes);
22459
22468
  await atomicRename(stg, dest.full);
22460
- saved.push(dest.rel);
22469
+ const relPosix = dest.rel.replace(/\\/g, "/");
22470
+ saved.push(relPosix);
22461
22471
  }
22462
22472
  if (!ctx2.skipManifest) {
22463
22473
  const manifestObj = {
@@ -22476,7 +22486,7 @@ async function saveArtifacts(ctx2, items, manifest) {
22476
22486
  }
22477
22487
  await atomicRename(manifestStage, manifestFull);
22478
22488
  await fsp__namespace.rm(stage, { recursive: true, force: true });
22479
- return { files: saved, manifestPath: manifestPathRel };
22489
+ return { files: saved, manifestPath: manifestPathRel.replace(/\\/g, "/") };
22480
22490
  } else {
22481
22491
  await fsp__namespace.rm(stage, { recursive: true, force: true });
22482
22492
  return { files: saved, manifestPath: "" };
@@ -22588,6 +22598,13 @@ var init_gemini_media = __esm({
22588
22598
  `GeminiMediaProvider.generateImage request failed: model=${modelName}; prompt="${promptPreview}"; error=${errMsg}`
22589
22599
  );
22590
22600
  }
22601
+ const feedback = resp?.response?.promptFeedback;
22602
+ const blockReason = feedback?.blockReason || feedback?.block_reason;
22603
+ if (blockReason) {
22604
+ const modelName2 = this.primaryModel;
22605
+ const reason = String(blockReason);
22606
+ throw new Error(`GeminiMediaProvider.policy_violation: model=${modelName2}; reason=${reason}`);
22607
+ }
22591
22608
  const parts = resp?.response?.candidates?.[0]?.content?.parts || [];
22592
22609
  for (const p of parts) {
22593
22610
  const data = p?.inlineData?.data || p?.inline_data?.data;
@@ -23499,7 +23516,8 @@ async function runVideoPipeline(params2, opts) {
23499
23516
  metrics: { durationMs: Date.now() - started, retries: 0, fallbacks: 0 },
23500
23517
  trace: Math.random().toString(36).slice(2, 8).toUpperCase()
23501
23518
  };
23502
- const saved2 = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, [{ bytes, ext: ext2 }], manifest2);
23519
+ const baseDir = opts.outDir || path10__namespace.join("artifacts", "media", "videos", String(manifest2.trace));
23520
+ const saved2 = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, [{ bytes, ext: ext2 }], manifest2);
23503
23521
  return { saved: saved2, durationMs: Date.now() - started, frames: 0, warnFallback: false, retries: 0 };
23504
23522
  }
23505
23523
  } catch {
@@ -23544,11 +23562,17 @@ async function runVideoPipeline(params2, opts) {
23544
23562
  await fsp__namespace.writeFile(path10__namespace.join(tmpDir, fname), frames[i2]);
23545
23563
  }
23546
23564
  const outBuf = await muxFramesToMp4(tmpDir, params2.fps);
23547
- saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, [{ bytes: outBuf, ext: ".mp4" }], manifest);
23565
+ {
23566
+ const baseDir = opts.outDir || path10__namespace.join("artifacts", "media", "videos", String(manifest.trace));
23567
+ saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, [{ bytes: outBuf, ext: ".mp4" }], manifest);
23568
+ }
23548
23569
  await fsp__namespace.rm(tmpDir, { recursive: true, force: true });
23549
23570
  } else {
23550
23571
  const items = frames.map((b, i2) => ({ bytes: b, ext: `.png`, logicalName: `frame-${String(i2 + 1).padStart(4, "0")}` }));
23551
- saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, items, manifest);
23572
+ {
23573
+ const baseDir = opts.outDir || path10__namespace.join("artifacts", "media", "videos", String(manifest.trace));
23574
+ saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, items, manifest);
23575
+ }
23552
23576
  warnFallback = true;
23553
23577
  }
23554
23578
  progress.done();
@@ -25657,7 +25681,7 @@ var init_about_command = __esm({
25657
25681
  async execute(args2, context2) {
25658
25682
  const output3 = [];
25659
25683
  output3.push("");
25660
- output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.16"));
25684
+ output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.18"));
25661
25685
  output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
25662
25686
  output3.push("");
25663
25687
  output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -37566,6 +37590,249 @@ var init_rate_limit_handler = __esm({
37566
37590
  "src/services/api-client/rate-limit-handler.ts"() {
37567
37591
  }
37568
37592
  });
37593
+ function extractCodeInfo(codeBlock) {
37594
+ const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
37595
+ if (!match2) {
37596
+ return { language: "text", code: codeBlock, extension: "txt" };
37597
+ }
37598
+ const fenceHeader = match2[1] || "";
37599
+ const language = fenceHeader.split(/\s+/)[0] || "text";
37600
+ const code = match2[2] || "";
37601
+ let filename;
37602
+ const fnameHeader = fenceHeader.match(/filename\s*=\s*([^\s]+)/i);
37603
+ if (fnameHeader) filename = sanitizeFilename(fnameHeader[1]);
37604
+ if (!filename) {
37605
+ const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
37606
+ const commentName = firstLine.match(/^\/\/\s*filename:\s*(.+)$/i) || firstLine.match(/^#\s*filename:\s*(.+)$/i) || firstLine.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i) || firstLine.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
37607
+ if (commentName && commentName[1]) filename = sanitizeFilename(commentName[1]);
37608
+ }
37609
+ const extension = inferExtensionFromContent(language, code) || "txt";
37610
+ return { language, code, extension, filename };
37611
+ }
37612
+ function extractAllCodeInfos(markdown) {
37613
+ const out = [];
37614
+ const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
37615
+ const protoMatches = markdown.matchAll(proto);
37616
+ let anyProto = false;
37617
+ for (const m2 of protoMatches) {
37618
+ anyProto = true;
37619
+ const fname = (m2[1] || "").trim();
37620
+ const body = m2[2] || "";
37621
+ const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
37622
+ out.push({ language: ext2, code: body, extension: ext2, filename: sanitizeFilenameStrict(fname) });
37623
+ }
37624
+ if (anyProto) return out;
37625
+ const blocks = [];
37626
+ const re = /```[^`]*\n[\s\S]*?```/g;
37627
+ const matches = markdown.match(re);
37628
+ if (matches && matches.length > 0) {
37629
+ for (const m2 of matches) {
37630
+ try {
37631
+ blocks.push(extractCodeInfo(m2));
37632
+ } catch {
37633
+ }
37634
+ }
37635
+ } else {
37636
+ blocks.push(extractCodeInfo(`\`\`\`text
37637
+ ${markdown}
37638
+ \`\`\``));
37639
+ }
37640
+ return blocks;
37641
+ }
37642
+ function sanitizeFilename(name2) {
37643
+ const base = name2.replace(/^[\\/]+/, "").replace(/[\0<>:"|?*]/g, "").trim();
37644
+ return base || "file";
37645
+ }
37646
+ function inferExtensionFromContent(language, code) {
37647
+ const lowerLang = (language || "").toLowerCase();
37648
+ code.toLowerCase();
37649
+ if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "html";
37650
+ if (/^\s*\{[\s\S]*\}\s*$/.test(code.trim())) return "json";
37651
+ if (/^\s*#include\s+</m.test(code)) return "c";
37652
+ const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
37653
+ const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
37654
+ const hasTypeScriptHints = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code) || /<\w+\s*<\w+>/.test(code);
37655
+ if (hasReact || /jsx|tsx/.test(lowerLang) || hasJSX) {
37656
+ if (lowerLang.includes("tsx") || hasTypeScriptHints) return "tsx";
37657
+ return "jsx";
37658
+ }
37659
+ if (/^\s*<\?xml/m.test(code)) return "xml";
37660
+ if (/^#!/.test(code)) return "sh";
37661
+ if (/^\s*package\s+[a-zA-Z0-9_.]+;/.test(code)) return "java";
37662
+ const map = {
37663
+ javascript: "js",
37664
+ typescript: "ts",
37665
+ jsx: "jsx",
37666
+ tsx: "tsx",
37667
+ python: "py",
37668
+ java: "java",
37669
+ cpp: "cpp",
37670
+ c: "c",
37671
+ csharp: "cs",
37672
+ php: "php",
37673
+ ruby: "rb",
37674
+ go: "go",
37675
+ rust: "rs",
37676
+ swift: "swift",
37677
+ kotlin: "kt",
37678
+ html: "html",
37679
+ css: "css",
37680
+ scss: "scss",
37681
+ json: "json",
37682
+ yaml: "yaml",
37683
+ yml: "yml",
37684
+ xml: "xml",
37685
+ sql: "sql",
37686
+ bash: "sh",
37687
+ shell: "sh",
37688
+ sh: "sh",
37689
+ dockerfile: "dockerfile",
37690
+ makefile: "makefile",
37691
+ markdown: "md",
37692
+ md: "md",
37693
+ text: "txt"
37694
+ };
37695
+ return map[lowerLang];
37696
+ }
37697
+ function sanitizeFilenameStrict(name2) {
37698
+ const RESERVED = /* @__PURE__ */ new Set([
37699
+ "con",
37700
+ "prn",
37701
+ "aux",
37702
+ "nul",
37703
+ "com1",
37704
+ "com2",
37705
+ "com3",
37706
+ "com4",
37707
+ "com5",
37708
+ "com6",
37709
+ "com7",
37710
+ "com8",
37711
+ "com9",
37712
+ "lpt1",
37713
+ "lpt2",
37714
+ "lpt3",
37715
+ "lpt4",
37716
+ "lpt5",
37717
+ "lpt6",
37718
+ "lpt7",
37719
+ "lpt8",
37720
+ "lpt9"
37721
+ ]);
37722
+ const cleaned = name2.replace(/[\u0000-\u001F\x7F<>:"/\\|?*]/g, "-").replace(/\s+/g, " ").trim();
37723
+ const leaf = cleaned.split(/[\\/]/).pop() || "file";
37724
+ const stem = leaf.replace(/\.[^.]+$/, "");
37725
+ if (leaf.includes("..") || RESERVED.has(stem.toLowerCase())) return "file";
37726
+ return leaf.length > 128 ? leaf.slice(0, 120) : leaf;
37727
+ }
37728
+ function coerceExtension(ext2, fallback2) {
37729
+ const e2 = (ext2 || "").toLowerCase().replace(/^\./, "");
37730
+ if (ALLOWED_EXTS.has(e2)) return e2;
37731
+ return fallback2;
37732
+ }
37733
+ function safeResolve(root, fname) {
37734
+ const abs = path10__namespace.resolve(root, fname);
37735
+ const base = path10__namespace.resolve(root);
37736
+ if (!(abs + path10__namespace.sep).startsWith(base + path10__namespace.sep) && abs !== base) {
37737
+ throw new Error("Path traversal detected");
37738
+ }
37739
+ return abs;
37740
+ }
37741
+ async function ensureUniquePath(absPath) {
37742
+ const dir = path10__namespace.dirname(absPath);
37743
+ const ext2 = path10__namespace.extname(absPath);
37744
+ const base = path10__namespace.basename(absPath, ext2);
37745
+ let candidate = absPath;
37746
+ let i2 = 1;
37747
+ while (true) {
37748
+ try {
37749
+ await fsp__namespace.access(candidate);
37750
+ candidate = path10__namespace.join(dir, `${base}(${i2})${ext2}`);
37751
+ i2++;
37752
+ } catch {
37753
+ return candidate;
37754
+ }
37755
+ }
37756
+ }
37757
+ function isLikelyBinary(text) {
37758
+ if (text.includes("\0")) return true;
37759
+ const len = Math.min(text.length, 8192);
37760
+ let nonText = 0;
37761
+ for (let i2 = 0; i2 < len; i2++) {
37762
+ const code = text.charCodeAt(i2);
37763
+ const isPrintable = code >= 9 && code <= 13 || code >= 32 && code <= 126 || code >= 160;
37764
+ if (!isPrintable) nonText++;
37765
+ }
37766
+ return nonText / Math.max(1, len) > 0.15;
37767
+ }
37768
+ function generateCodeFilename(prompt, language, extension, code, suggested) {
37769
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
37770
+ if (suggested) return sanitizeFilename(suggested);
37771
+ if (code) {
37772
+ if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "index.html";
37773
+ if (/^\s*import\s+react/m.test(code)) return "App." + (extension || "tsx");
37774
+ if (/express\(\)/.test(code) || /from\s+express/.test(code)) return `server.${extension || "js"}`;
37775
+ if (/^#!\//.test(code)) return `script.${extension || "sh"}`;
37776
+ }
37777
+ const promptLower = (prompt || "").toLowerCase();
37778
+ let baseName = "code";
37779
+ if (promptLower.includes("api")) baseName = "api";
37780
+ else if (promptLower.includes("server")) baseName = "server";
37781
+ else if (promptLower.includes("client")) baseName = "client";
37782
+ else if (promptLower.includes("component")) baseName = "component";
37783
+ else if (promptLower.includes("function")) baseName = "function";
37784
+ else if (promptLower.includes("class")) baseName = "class";
37785
+ else if (promptLower.includes("test")) baseName = "test";
37786
+ else if (promptLower.includes("script")) baseName = "script";
37787
+ else if (promptLower.includes("app")) baseName = "app";
37788
+ else if (promptLower.includes("main")) baseName = "main";
37789
+ else if (promptLower.includes("index")) baseName = "index";
37790
+ else if (promptLower.includes("util")) baseName = "utils";
37791
+ else if (promptLower.includes("helper")) baseName = "helper";
37792
+ else if (promptLower.includes("service")) baseName = "service";
37793
+ else if (promptLower.includes("model")) baseName = "model";
37794
+ else if (promptLower.includes("controller")) baseName = "controller";
37795
+ else if (promptLower.includes("route")) baseName = "routes";
37796
+ else if (promptLower.includes("config")) baseName = "config";
37797
+ if (baseName === "index" && extension) return `index.${extension}`;
37798
+ return `${baseName}_${timestamp}.${extension}`;
37799
+ }
37800
+ var ALLOWED_EXTS;
37801
+ var init_code_utils = __esm({
37802
+ "src/cli/code-utils.ts"() {
37803
+ ALLOWED_EXTS = /* @__PURE__ */ new Set([
37804
+ "ts",
37805
+ "tsx",
37806
+ "js",
37807
+ "jsx",
37808
+ "mjs",
37809
+ "cjs",
37810
+ "json",
37811
+ "yml",
37812
+ "yaml",
37813
+ "md",
37814
+ "html",
37815
+ "css",
37816
+ "scss",
37817
+ "py",
37818
+ "java",
37819
+ "kt",
37820
+ "rb",
37821
+ "go",
37822
+ "rs",
37823
+ "swift",
37824
+ "c",
37825
+ "cpp",
37826
+ "cs",
37827
+ "sh",
37828
+ "xml",
37829
+ "sql",
37830
+ "dockerfile",
37831
+ "makefile",
37832
+ "txt"
37833
+ ]);
37834
+ }
37835
+ });
37569
37836
  async function scanRepo(cwd2) {
37570
37837
  if (_cache && _cache.root === cwd2) return _cache;
37571
37838
  const root = cwd2;
@@ -38657,7 +38924,18 @@ async function orchestrate(request, opts) {
38657
38924
  async () => {
38658
38925
  const started = Date.now();
38659
38926
  try {
38660
- const response = await executeCode(request);
38927
+ const FILE_FORMAT_INSTRUCTIONS = [
38928
+ "You are a senior software engineer. Respond with CODE ONLY.",
38929
+ "At the very start of each file, include a filename hint as a comment on the first line:",
38930
+ "// filename: <name.ext> (or # filename: <name.ext> for Python, <!-- filename: name.ext --> for HTML/CSS)",
38931
+ "If multiple files are required, use the strict multi-file protocol with one or more file sections:",
38932
+ "[BEGIN file: path]\n<content>\n[END]",
38933
+ "Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
38934
+ ].join("\n");
38935
+ const enriched = `${FILE_FORMAT_INSTRUCTIONS}
38936
+
38937
+ ${request}`;
38938
+ const response = await executeCode(enriched);
38661
38939
  const raw = (response.output || response?.data?.content || "").trim();
38662
38940
  if (!raw) {
38663
38941
  return {
@@ -38723,8 +39001,10 @@ async function orchestrate(request, opts) {
38723
39001
  } else {
38724
39002
  for (let i2 = 0; i2 < blocks.length; i2++) {
38725
39003
  const b = blocks[i2];
39004
+ const desired = typeof b.filename === "string" && b.filename.trim() ? b.filename.trim() : null;
39005
+ const path60 = desired || suggestName2(request, b.language, i2);
38726
39006
  initial.push({
38727
- path: suggestName2(request, b.language, i2),
39007
+ path: path60,
38728
39008
  kind: "source",
38729
39009
  action: "create",
38730
39010
  description: describe2(b.language, ""),
@@ -38740,6 +39020,21 @@ async function orchestrate(request, opts) {
38740
39020
  }
38741
39021
  }
38742
39022
  const normalized = await normalizePlans(initial, { root: opts.root });
39023
+ try {
39024
+ const [{ access: access18 }, path60] = await Promise.all([
39025
+ import('fs/promises'),
39026
+ import('path')
39027
+ ]);
39028
+ for (const p of normalized) {
39029
+ try {
39030
+ await access18(path60.join(opts.root, p.path));
39031
+ p.action = "modify";
39032
+ } catch {
39033
+ p.action = "create";
39034
+ }
39035
+ }
39036
+ } catch {
39037
+ }
38743
39038
  const validated = await validatePlan(normalized, { root: opts.root, profile, flags: { maxFiles: opts.flags.maxFiles, yes: opts.flags.yes, interactive: !!opts.flags.interactive, ...opts.flags } });
38744
39039
  const outputMode = resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
38745
39040
  const displayFiles = validated.files.concat(
@@ -38873,6 +39168,15 @@ function mapCodeErrorToReason(err) {
38873
39168
  }
38874
39169
  function extractBlocks(content) {
38875
39170
  const blocks = [];
39171
+ const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
39172
+ let pm;
39173
+ while ((pm = proto.exec(content)) !== null) {
39174
+ const fname = (pm[1] || "").trim();
39175
+ const body = (pm[2] || "").trim();
39176
+ const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
39177
+ blocks.push({ language: ext2 || "text", code: body, filename: fname });
39178
+ }
39179
+ if (blocks.length > 0) return blocks;
38876
39180
  const re = /```(\w*)\n([\s\S]*?)```/g;
38877
39181
  let m2;
38878
39182
  while ((m2 = re.exec(content)) !== null) blocks.push({ language: m2[1] || "javascript", code: m2[2].trim() });
@@ -39111,6 +39415,7 @@ var init_code_command = __esm({
39111
39415
  init_base_command();
39112
39416
  init_rate_limit_handler();
39113
39417
  init_animations();
39418
+ init_code_utils();
39114
39419
  LANGUAGE_EXTENSIONS = {
39115
39420
  javascript: ".js",
39116
39421
  typescript: ".ts",
@@ -39343,10 +39648,19 @@ ${pretty}`);
39343
39648
  const count = Math.min(blocks.length, limit);
39344
39649
  for (let i2 = 0; i2 < count; i2++) {
39345
39650
  const block = blocks[i2];
39346
- const filename = this.generateFilename(request, block.language);
39347
- const ext2 = LANGUAGE_EXTENSIONS[block.language] || ".txt";
39348
- const naive = i2 === 0 ? `${filename}${ext2}` : `${filename}_${i2 + 1}${ext2}`;
39349
- plans.push({ path: naive, kind: "source", action: "create", description: this.describeBrief(block.language, naive), language: block.language, preview: block.code });
39651
+ const suggested = this.extractSuggestedFilename(block.code);
39652
+ const inferredExt = inferExtensionFromContent(block.language, block.code) || "txt";
39653
+ let finalName;
39654
+ if (suggested) {
39655
+ const clean = sanitizeFilenameStrict(suggested);
39656
+ const hasExt = /\.[A-Za-z0-9._-]+$/.test(clean);
39657
+ finalName = hasExt ? clean : `${clean}.${inferredExt}`;
39658
+ } else {
39659
+ const base = this.generateFilename(request, block.language);
39660
+ const ext2 = LANGUAGE_EXTENSIONS[block.language] || `.${inferredExt}`;
39661
+ finalName = i2 === 0 ? `${base}${ext2}` : `${base}_${i2 + 1}${ext2}`;
39662
+ }
39663
+ plans.push({ path: finalName, kind: "source", action: "create", description: this.describeBrief(block.language, finalName), language: block.language, preview: block.code });
39350
39664
  }
39351
39665
  const { normalizePlans: normalizePlans2 } = await Promise.resolve().then(() => (init_FilePlanBuilder(), FilePlanBuilder_exports));
39352
39666
  const normalized = await normalizePlans2(plans, { root });
@@ -39356,6 +39670,18 @@ ${pretty}`);
39356
39670
  }
39357
39671
  return normalized;
39358
39672
  }
39673
+ extractSuggestedFilename(code) {
39674
+ const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
39675
+ const m1 = firstLine.match(/^\/\/\s*filename:\s*(.+)$/i);
39676
+ if (m1?.[1]) return m1[1].trim();
39677
+ const m2 = firstLine.match(/^#\s*filename:\s*(.+)$/i);
39678
+ if (m2?.[1]) return m2[1].trim();
39679
+ const m3 = firstLine.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i);
39680
+ if (m3?.[1]) return m3[1].trim();
39681
+ const m4 = firstLine.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
39682
+ if (m4?.[1]) return m4[1].trim();
39683
+ return void 0;
39684
+ }
39359
39685
  describeBrief(language, final) {
39360
39686
  const l = language.toLowerCase();
39361
39687
  if (/tsx|jsx/.test(l) || /\.tsx$|\.jsx$/.test(final)) return "UI component";
@@ -39470,7 +39796,10 @@ ${pretty}`);
39470
39796
  * Detect programming language from content
39471
39797
  */
39472
39798
  detectLanguage(code) {
39473
- if (code.includes("import React") || code.includes("<")) return "jsx";
39799
+ const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
39800
+ const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
39801
+ const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
39802
+ if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
39474
39803
  if (code.includes("interface ") || code.includes(": string")) return "typescript";
39475
39804
  if (code.includes("def ") || code.includes("print(")) return "python";
39476
39805
  if (code.includes("func ") || code.includes("package main")) return "go";
@@ -59319,7 +59648,7 @@ var init_ai_response_service = __esm({
59319
59648
  */
59320
59649
  async callLLM(prompt, opts = {}) {
59321
59650
  const {
59322
- system = PLAIN_OUTPUT ? "Return ONLY the answer (or ONLY code). No menus, no lists, no guided flows. Always respond in English." : "You are a helpful senior engineer. Always respond in English. Provide direct, production-quality answers.",
59651
+ system = PLAIN_OUTPUT ? "Return ONLY the answer (or ONLY code). No menus, no lists, no guided flows. Always respond in English." : "You are a helpful senior engineer. Always respond in English. Provide direct, production-quality answers. Make sure you answer in plain text, as a natural chat.",
59323
59652
  model = void 0,
59324
59653
  provider = DEFAULT_PROVIDER2,
59325
59654
  temperature = 0.2,
@@ -60558,243 +60887,6 @@ var init_server = __esm({
60558
60887
  init_text_logger();
60559
60888
  }
60560
60889
  });
60561
- function extractCodeInfo(codeBlock) {
60562
- const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
60563
- if (!match2) {
60564
- return { language: "text", code: codeBlock, extension: "txt" };
60565
- }
60566
- const fenceHeader = match2[1] || "";
60567
- const language = fenceHeader.split(/\s+/)[0] || "text";
60568
- const code = match2[2] || "";
60569
- let filename;
60570
- const fnameHeader = fenceHeader.match(/filename\s*=\s*([^\s]+)/i);
60571
- if (fnameHeader) filename = sanitizeFilename(fnameHeader[1]);
60572
- if (!filename) {
60573
- const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
60574
- const commentName = firstLine.match(/^\/\/\s*filename:\s*(.+)$/i) || firstLine.match(/^#\s*filename:\s*(.+)$/i) || firstLine.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i) || firstLine.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
60575
- if (commentName && commentName[1]) filename = sanitizeFilename(commentName[1]);
60576
- }
60577
- const extension = inferExtensionFromContent(language, code) || "txt";
60578
- return { language, code, extension, filename };
60579
- }
60580
- function extractAllCodeInfos(markdown) {
60581
- const out = [];
60582
- const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
60583
- const protoMatches = markdown.matchAll(proto);
60584
- let anyProto = false;
60585
- for (const m2 of protoMatches) {
60586
- anyProto = true;
60587
- const fname = (m2[1] || "").trim();
60588
- const body = m2[2] || "";
60589
- const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
60590
- out.push({ language: ext2, code: body, extension: ext2, filename: sanitizeFilenameStrict(fname) });
60591
- }
60592
- if (anyProto) return out;
60593
- const blocks = [];
60594
- const re = /```[^`]*\n[\s\S]*?```/g;
60595
- const matches = markdown.match(re);
60596
- if (matches && matches.length > 0) {
60597
- for (const m2 of matches) {
60598
- try {
60599
- blocks.push(extractCodeInfo(m2));
60600
- } catch {
60601
- }
60602
- }
60603
- } else {
60604
- blocks.push(extractCodeInfo(`\`\`\`text
60605
- ${markdown}
60606
- \`\`\``));
60607
- }
60608
- return blocks;
60609
- }
60610
- function sanitizeFilename(name2) {
60611
- const base = name2.replace(/^[\\/]+/, "").replace(/[\0<>:"|?*]/g, "").trim();
60612
- return base || "file";
60613
- }
60614
- function inferExtensionFromContent(language, code) {
60615
- const lowerLang = (language || "").toLowerCase();
60616
- code.toLowerCase();
60617
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "html";
60618
- if (/^\s*\{[\s\S]*\}\s*$/.test(code.trim())) return "json";
60619
- if (/^\s*#include\s+</m.test(code)) return "c";
60620
- if (/^\s*import\s+react/m.test(code) || /jsx/m.test(lowerLang)) return "jsx";
60621
- if (/^\s*<\?xml/m.test(code)) return "xml";
60622
- if (/^#!/.test(code)) return "sh";
60623
- if (/^\s*package\s+[a-zA-Z0-9_.]+;/.test(code)) return "java";
60624
- const map = {
60625
- javascript: "js",
60626
- typescript: "ts",
60627
- jsx: "jsx",
60628
- tsx: "tsx",
60629
- python: "py",
60630
- java: "java",
60631
- cpp: "cpp",
60632
- c: "c",
60633
- csharp: "cs",
60634
- php: "php",
60635
- ruby: "rb",
60636
- go: "go",
60637
- rust: "rs",
60638
- swift: "swift",
60639
- kotlin: "kt",
60640
- html: "html",
60641
- css: "css",
60642
- scss: "scss",
60643
- json: "json",
60644
- yaml: "yaml",
60645
- yml: "yml",
60646
- xml: "xml",
60647
- sql: "sql",
60648
- bash: "sh",
60649
- shell: "sh",
60650
- sh: "sh",
60651
- dockerfile: "dockerfile",
60652
- makefile: "makefile",
60653
- markdown: "md",
60654
- md: "md",
60655
- text: "txt"
60656
- };
60657
- return map[lowerLang];
60658
- }
60659
- function sanitizeFilenameStrict(name2) {
60660
- const RESERVED = /* @__PURE__ */ new Set([
60661
- "con",
60662
- "prn",
60663
- "aux",
60664
- "nul",
60665
- "com1",
60666
- "com2",
60667
- "com3",
60668
- "com4",
60669
- "com5",
60670
- "com6",
60671
- "com7",
60672
- "com8",
60673
- "com9",
60674
- "lpt1",
60675
- "lpt2",
60676
- "lpt3",
60677
- "lpt4",
60678
- "lpt5",
60679
- "lpt6",
60680
- "lpt7",
60681
- "lpt8",
60682
- "lpt9"
60683
- ]);
60684
- const cleaned = name2.replace(/[\u0000-\u001F\x7F<>:"/\\|?*]/g, "-").replace(/\s+/g, " ").trim();
60685
- const leaf = cleaned.split(/[\\/]/).pop() || "file";
60686
- const stem = leaf.replace(/\.[^.]+$/, "");
60687
- if (leaf.includes("..") || RESERVED.has(stem.toLowerCase())) return "file";
60688
- return leaf.length > 128 ? leaf.slice(0, 120) : leaf;
60689
- }
60690
- function coerceExtension(ext2, fallback2) {
60691
- const e2 = (ext2 || "").toLowerCase().replace(/^\./, "");
60692
- if (ALLOWED_EXTS.has(e2)) return e2;
60693
- return fallback2;
60694
- }
60695
- function safeResolve(root, fname) {
60696
- const abs = path10__namespace.resolve(root, fname);
60697
- const base = path10__namespace.resolve(root);
60698
- if (!(abs + path10__namespace.sep).startsWith(base + path10__namespace.sep) && abs !== base) {
60699
- throw new Error("Path traversal detected");
60700
- }
60701
- return abs;
60702
- }
60703
- async function ensureUniquePath(absPath) {
60704
- const dir = path10__namespace.dirname(absPath);
60705
- const ext2 = path10__namespace.extname(absPath);
60706
- const base = path10__namespace.basename(absPath, ext2);
60707
- let candidate = absPath;
60708
- let i2 = 1;
60709
- while (true) {
60710
- try {
60711
- await fsp__namespace.access(candidate);
60712
- candidate = path10__namespace.join(dir, `${base}(${i2})${ext2}`);
60713
- i2++;
60714
- } catch {
60715
- return candidate;
60716
- }
60717
- }
60718
- }
60719
- function isLikelyBinary(text) {
60720
- if (text.includes("\0")) return true;
60721
- const len = Math.min(text.length, 8192);
60722
- let nonText = 0;
60723
- for (let i2 = 0; i2 < len; i2++) {
60724
- const code = text.charCodeAt(i2);
60725
- const isPrintable = code >= 9 && code <= 13 || code >= 32 && code <= 126 || code >= 160;
60726
- if (!isPrintable) nonText++;
60727
- }
60728
- return nonText / Math.max(1, len) > 0.15;
60729
- }
60730
- function generateCodeFilename(prompt, language, extension, code, suggested) {
60731
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
60732
- if (suggested) return sanitizeFilename(suggested);
60733
- if (code) {
60734
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "index.html";
60735
- if (/^\s*import\s+react/m.test(code)) return "App." + (extension || "tsx");
60736
- if (/express\(\)/.test(code) || /from\s+express/.test(code)) return `server.${extension || "js"}`;
60737
- if (/^#!\//.test(code)) return `script.${extension || "sh"}`;
60738
- }
60739
- const promptLower = (prompt || "").toLowerCase();
60740
- let baseName = "code";
60741
- if (promptLower.includes("api")) baseName = "api";
60742
- else if (promptLower.includes("server")) baseName = "server";
60743
- else if (promptLower.includes("client")) baseName = "client";
60744
- else if (promptLower.includes("component")) baseName = "component";
60745
- else if (promptLower.includes("function")) baseName = "function";
60746
- else if (promptLower.includes("class")) baseName = "class";
60747
- else if (promptLower.includes("test")) baseName = "test";
60748
- else if (promptLower.includes("script")) baseName = "script";
60749
- else if (promptLower.includes("app")) baseName = "app";
60750
- else if (promptLower.includes("main")) baseName = "main";
60751
- else if (promptLower.includes("index")) baseName = "index";
60752
- else if (promptLower.includes("util")) baseName = "utils";
60753
- else if (promptLower.includes("helper")) baseName = "helper";
60754
- else if (promptLower.includes("service")) baseName = "service";
60755
- else if (promptLower.includes("model")) baseName = "model";
60756
- else if (promptLower.includes("controller")) baseName = "controller";
60757
- else if (promptLower.includes("route")) baseName = "routes";
60758
- else if (promptLower.includes("config")) baseName = "config";
60759
- if (baseName === "index" && extension) return `index.${extension}`;
60760
- return `${baseName}_${timestamp}.${extension}`;
60761
- }
60762
- var ALLOWED_EXTS;
60763
- var init_code_utils = __esm({
60764
- "src/cli/code-utils.ts"() {
60765
- ALLOWED_EXTS = /* @__PURE__ */ new Set([
60766
- "ts",
60767
- "tsx",
60768
- "js",
60769
- "jsx",
60770
- "mjs",
60771
- "cjs",
60772
- "json",
60773
- "yml",
60774
- "yaml",
60775
- "md",
60776
- "html",
60777
- "css",
60778
- "scss",
60779
- "py",
60780
- "java",
60781
- "kt",
60782
- "rb",
60783
- "go",
60784
- "rs",
60785
- "swift",
60786
- "c",
60787
- "cpp",
60788
- "cs",
60789
- "sh",
60790
- "xml",
60791
- "sql",
60792
- "dockerfile",
60793
- "makefile",
60794
- "txt"
60795
- ]);
60796
- }
60797
- });
60798
60890
 
60799
60891
  // src/services/startup-display.ts
60800
60892
  var startup_display_exports = {};
@@ -74252,13 +74344,10 @@ async function handleComplexChat(request, triageResult) {
74252
74344
  } catch {
74253
74345
  }
74254
74346
  }
74255
- if (!content && ai?.generateResponse) {
74256
- content = await ai.generateResponse({
74257
- userInput: `Create a concise plan and next steps for: ${request}`,
74258
- sessionMemory: [],
74259
- provider: process.env.MARIA_PROVIDER || "google",
74260
- model: process.env.MARIA_MODEL || "gemini-2.5-flash"
74261
- });
74347
+ if (!content) {
74348
+ animation.stop();
74349
+ await streamAnswer(request, { triage: triageResult });
74350
+ return;
74262
74351
  }
74263
74352
  animation.stop();
74264
74353
  const cleaned = content && typeof content === "string" ? content : buildComplexPlanSteps(request).join("\n");