@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.
@@ -26038,8 +26038,8 @@ var require_package = __commonJS({
26038
26038
  "package.json"(exports, module) {
26039
26039
  module.exports = {
26040
26040
  name: "@bonginkan/maria",
26041
- version: "4.3.16",
26042
- 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.",
26041
+ version: "4.3.18",
26042
+ 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.",
26043
26043
  keywords: [
26044
26044
  "ai",
26045
26045
  "cli",
@@ -28071,7 +28071,7 @@ var init_AuthenticationManager = __esm({
28071
28071
  const response = await fetch(`${this.apiBase}/api/user/profile`, {
28072
28072
  headers: {
28073
28073
  "Authorization": `Bearer ${tokens2.accessToken}`,
28074
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.16"}`
28074
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.18"}`
28075
28075
  }
28076
28076
  });
28077
28077
  if (response.status === 401) {
@@ -28703,7 +28703,7 @@ async function callApi(path60, init3 = {}) {
28703
28703
  "Authorization": `Bearer ${token}`,
28704
28704
  "X-Device-Id": getDeviceId(),
28705
28705
  "X-Session-Id": getSessionId() || "",
28706
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.16"}`,
28706
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.18"}`,
28707
28707
  "Content-Type": init3.headers?.["Content-Type"] || "application/json"
28708
28708
  });
28709
28709
  const doFetch = async (token) => {
@@ -47567,6 +47567,15 @@ async function hasCaseInsensitiveCollision(dirFull, targetFile) {
47567
47567
  async function atomicRename(stage, dest) {
47568
47568
  try {
47569
47569
  await fsp__namespace.rename(stage, dest);
47570
+ try {
47571
+ const fd = await fsp__namespace.open(dest, "r");
47572
+ try {
47573
+ await fd.sync();
47574
+ } finally {
47575
+ await fd.close();
47576
+ }
47577
+ } catch {
47578
+ }
47570
47579
  } catch (e2) {
47571
47580
  if (e2 && e2.code === "EXDEV") {
47572
47581
  await fsp__namespace.copyFile(stage, dest);
@@ -47621,7 +47630,8 @@ async function saveArtifacts(ctx2, items, manifest) {
47621
47630
  }
47622
47631
  await fsp__namespace.writeFile(stg, it.bytes);
47623
47632
  await atomicRename(stg, dest.full);
47624
- saved.push(dest.rel);
47633
+ const relPosix = dest.rel.replace(/\\/g, "/");
47634
+ saved.push(relPosix);
47625
47635
  }
47626
47636
  if (!ctx2.skipManifest) {
47627
47637
  const manifestObj = {
@@ -47640,7 +47650,7 @@ async function saveArtifacts(ctx2, items, manifest) {
47640
47650
  }
47641
47651
  await atomicRename(manifestStage, manifestFull);
47642
47652
  await fsp__namespace.rm(stage, { recursive: true, force: true });
47643
- return { files: saved, manifestPath: manifestPathRel };
47653
+ return { files: saved, manifestPath: manifestPathRel.replace(/\\/g, "/") };
47644
47654
  } else {
47645
47655
  await fsp__namespace.rm(stage, { recursive: true, force: true });
47646
47656
  return { files: saved, manifestPath: "" };
@@ -47752,6 +47762,13 @@ var init_gemini_media = __esm({
47752
47762
  `GeminiMediaProvider.generateImage request failed: model=${modelName}; prompt="${promptPreview}"; error=${errMsg}`
47753
47763
  );
47754
47764
  }
47765
+ const feedback = resp?.response?.promptFeedback;
47766
+ const blockReason = feedback?.blockReason || feedback?.block_reason;
47767
+ if (blockReason) {
47768
+ const modelName2 = this.primaryModel;
47769
+ const reason = String(blockReason);
47770
+ throw new Error(`GeminiMediaProvider.policy_violation: model=${modelName2}; reason=${reason}`);
47771
+ }
47755
47772
  const parts = resp?.response?.candidates?.[0]?.content?.parts || [];
47756
47773
  for (const p of parts) {
47757
47774
  const data = p?.inlineData?.data || p?.inline_data?.data;
@@ -48663,7 +48680,8 @@ async function runVideoPipeline(params2, opts) {
48663
48680
  metrics: { durationMs: Date.now() - started, retries: 0, fallbacks: 0 },
48664
48681
  trace: Math.random().toString(36).slice(2, 8).toUpperCase()
48665
48682
  };
48666
- const saved2 = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, [{ bytes, ext: ext2 }], manifest2);
48683
+ const baseDir = opts.outDir || path11__namespace.join("artifacts", "media", "videos", String(manifest2.trace));
48684
+ const saved2 = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, [{ bytes, ext: ext2 }], manifest2);
48667
48685
  return { saved: saved2, durationMs: Date.now() - started, frames: 0, warnFallback: false, retries: 0 };
48668
48686
  }
48669
48687
  } catch {
@@ -48708,11 +48726,17 @@ async function runVideoPipeline(params2, opts) {
48708
48726
  await fsp__namespace.writeFile(path11__namespace.join(tmpDir, fname), frames[i2]);
48709
48727
  }
48710
48728
  const outBuf = await muxFramesToMp4(tmpDir, params2.fps);
48711
- saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, [{ bytes: outBuf, ext: ".mp4" }], manifest);
48729
+ {
48730
+ const baseDir = opts.outDir || path11__namespace.join("artifacts", "media", "videos", String(manifest.trace));
48731
+ saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, [{ bytes: outBuf, ext: ".mp4" }], manifest);
48732
+ }
48712
48733
  await fsp__namespace.rm(tmpDir, { recursive: true, force: true });
48713
48734
  } else {
48714
48735
  const items = frames.map((b, i2) => ({ bytes: b, ext: `.png`, logicalName: `frame-${String(i2 + 1).padStart(4, "0")}` }));
48715
- saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir: opts.outDir, flat: true, skipManifest: true }, items, manifest);
48736
+ {
48737
+ const baseDir = opts.outDir || path11__namespace.join("artifacts", "media", "videos", String(manifest.trace));
48738
+ saved = await saveArtifacts({ root: opts.root, kind: "video", baseDir, flat: true }, items, manifest);
48739
+ }
48716
48740
  warnFallback = true;
48717
48741
  }
48718
48742
  progress.done();
@@ -50535,7 +50559,7 @@ var init_about_command = __esm({
50535
50559
  async execute(args2, context2) {
50536
50560
  const output3 = [];
50537
50561
  output3.push("");
50538
- output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.16"));
50562
+ output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.18"));
50539
50563
  output3.push(chalk14__default.default.gray("\u2550".repeat(40)));
50540
50564
  output3.push("");
50541
50565
  output3.push(chalk14__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -53681,6 +53705,249 @@ var init_rate_limit_handler = __esm({
53681
53705
  "src/services/api-client/rate-limit-handler.ts"() {
53682
53706
  }
53683
53707
  });
53708
+ function extractCodeInfo(codeBlock) {
53709
+ const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
53710
+ if (!match2) {
53711
+ return { language: "text", code: codeBlock, extension: "txt" };
53712
+ }
53713
+ const fenceHeader = match2[1] || "";
53714
+ const language = fenceHeader.split(/\s+/)[0] || "text";
53715
+ const code = match2[2] || "";
53716
+ let filename;
53717
+ const fnameHeader = fenceHeader.match(/filename\s*=\s*([^\s]+)/i);
53718
+ if (fnameHeader) filename = sanitizeFilename(fnameHeader[1]);
53719
+ if (!filename) {
53720
+ const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
53721
+ 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);
53722
+ if (commentName && commentName[1]) filename = sanitizeFilename(commentName[1]);
53723
+ }
53724
+ const extension = inferExtensionFromContent(language, code) || "txt";
53725
+ return { language, code, extension, filename };
53726
+ }
53727
+ function extractAllCodeInfos(markdown) {
53728
+ const out = [];
53729
+ const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
53730
+ const protoMatches = markdown.matchAll(proto);
53731
+ let anyProto = false;
53732
+ for (const m2 of protoMatches) {
53733
+ anyProto = true;
53734
+ const fname = (m2[1] || "").trim();
53735
+ const body = m2[2] || "";
53736
+ const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
53737
+ out.push({ language: ext2, code: body, extension: ext2, filename: sanitizeFilenameStrict(fname) });
53738
+ }
53739
+ if (anyProto) return out;
53740
+ const blocks = [];
53741
+ const re = /```[^`]*\n[\s\S]*?```/g;
53742
+ const matches = markdown.match(re);
53743
+ if (matches && matches.length > 0) {
53744
+ for (const m2 of matches) {
53745
+ try {
53746
+ blocks.push(extractCodeInfo(m2));
53747
+ } catch {
53748
+ }
53749
+ }
53750
+ } else {
53751
+ blocks.push(extractCodeInfo(`\`\`\`text
53752
+ ${markdown}
53753
+ \`\`\``));
53754
+ }
53755
+ return blocks;
53756
+ }
53757
+ function sanitizeFilename(name2) {
53758
+ const base = name2.replace(/^[\\/]+/, "").replace(/[\0<>:"|?*]/g, "").trim();
53759
+ return base || "file";
53760
+ }
53761
+ function inferExtensionFromContent(language, code) {
53762
+ const lowerLang = (language || "").toLowerCase();
53763
+ code.toLowerCase();
53764
+ if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "html";
53765
+ if (/^\s*\{[\s\S]*\}\s*$/.test(code.trim())) return "json";
53766
+ if (/^\s*#include\s+</m.test(code)) return "c";
53767
+ const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
53768
+ const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
53769
+ 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);
53770
+ if (hasReact || /jsx|tsx/.test(lowerLang) || hasJSX) {
53771
+ if (lowerLang.includes("tsx") || hasTypeScriptHints) return "tsx";
53772
+ return "jsx";
53773
+ }
53774
+ if (/^\s*<\?xml/m.test(code)) return "xml";
53775
+ if (/^#!/.test(code)) return "sh";
53776
+ if (/^\s*package\s+[a-zA-Z0-9_.]+;/.test(code)) return "java";
53777
+ const map = {
53778
+ javascript: "js",
53779
+ typescript: "ts",
53780
+ jsx: "jsx",
53781
+ tsx: "tsx",
53782
+ python: "py",
53783
+ java: "java",
53784
+ cpp: "cpp",
53785
+ c: "c",
53786
+ csharp: "cs",
53787
+ php: "php",
53788
+ ruby: "rb",
53789
+ go: "go",
53790
+ rust: "rs",
53791
+ swift: "swift",
53792
+ kotlin: "kt",
53793
+ html: "html",
53794
+ css: "css",
53795
+ scss: "scss",
53796
+ json: "json",
53797
+ yaml: "yaml",
53798
+ yml: "yml",
53799
+ xml: "xml",
53800
+ sql: "sql",
53801
+ bash: "sh",
53802
+ shell: "sh",
53803
+ sh: "sh",
53804
+ dockerfile: "dockerfile",
53805
+ makefile: "makefile",
53806
+ markdown: "md",
53807
+ md: "md",
53808
+ text: "txt"
53809
+ };
53810
+ return map[lowerLang];
53811
+ }
53812
+ function sanitizeFilenameStrict(name2) {
53813
+ const RESERVED = /* @__PURE__ */ new Set([
53814
+ "con",
53815
+ "prn",
53816
+ "aux",
53817
+ "nul",
53818
+ "com1",
53819
+ "com2",
53820
+ "com3",
53821
+ "com4",
53822
+ "com5",
53823
+ "com6",
53824
+ "com7",
53825
+ "com8",
53826
+ "com9",
53827
+ "lpt1",
53828
+ "lpt2",
53829
+ "lpt3",
53830
+ "lpt4",
53831
+ "lpt5",
53832
+ "lpt6",
53833
+ "lpt7",
53834
+ "lpt8",
53835
+ "lpt9"
53836
+ ]);
53837
+ const cleaned = name2.replace(/[\u0000-\u001F\x7F<>:"/\\|?*]/g, "-").replace(/\s+/g, " ").trim();
53838
+ const leaf = cleaned.split(/[\\/]/).pop() || "file";
53839
+ const stem = leaf.replace(/\.[^.]+$/, "");
53840
+ if (leaf.includes("..") || RESERVED.has(stem.toLowerCase())) return "file";
53841
+ return leaf.length > 128 ? leaf.slice(0, 120) : leaf;
53842
+ }
53843
+ function coerceExtension(ext2, fallback2) {
53844
+ const e2 = (ext2 || "").toLowerCase().replace(/^\./, "");
53845
+ if (ALLOWED_EXTS.has(e2)) return e2;
53846
+ return fallback2;
53847
+ }
53848
+ function safeResolve(root, fname) {
53849
+ const abs = path11__namespace.resolve(root, fname);
53850
+ const base = path11__namespace.resolve(root);
53851
+ if (!(abs + path11__namespace.sep).startsWith(base + path11__namespace.sep) && abs !== base) {
53852
+ throw new Error("Path traversal detected");
53853
+ }
53854
+ return abs;
53855
+ }
53856
+ async function ensureUniquePath(absPath) {
53857
+ const dir = path11__namespace.dirname(absPath);
53858
+ const ext2 = path11__namespace.extname(absPath);
53859
+ const base = path11__namespace.basename(absPath, ext2);
53860
+ let candidate = absPath;
53861
+ let i2 = 1;
53862
+ while (true) {
53863
+ try {
53864
+ await fsp__namespace.access(candidate);
53865
+ candidate = path11__namespace.join(dir, `${base}(${i2})${ext2}`);
53866
+ i2++;
53867
+ } catch {
53868
+ return candidate;
53869
+ }
53870
+ }
53871
+ }
53872
+ function isLikelyBinary(text) {
53873
+ if (text.includes("\0")) return true;
53874
+ const len = Math.min(text.length, 8192);
53875
+ let nonText = 0;
53876
+ for (let i2 = 0; i2 < len; i2++) {
53877
+ const code = text.charCodeAt(i2);
53878
+ const isPrintable = code >= 9 && code <= 13 || code >= 32 && code <= 126 || code >= 160;
53879
+ if (!isPrintable) nonText++;
53880
+ }
53881
+ return nonText / Math.max(1, len) > 0.15;
53882
+ }
53883
+ function generateCodeFilename(prompt, language, extension, code, suggested) {
53884
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
53885
+ if (suggested) return sanitizeFilename(suggested);
53886
+ if (code) {
53887
+ if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "index.html";
53888
+ if (/^\s*import\s+react/m.test(code)) return "App." + (extension || "tsx");
53889
+ if (/express\(\)/.test(code) || /from\s+express/.test(code)) return `server.${extension || "js"}`;
53890
+ if (/^#!\//.test(code)) return `script.${extension || "sh"}`;
53891
+ }
53892
+ const promptLower = (prompt || "").toLowerCase();
53893
+ let baseName = "code";
53894
+ if (promptLower.includes("api")) baseName = "api";
53895
+ else if (promptLower.includes("server")) baseName = "server";
53896
+ else if (promptLower.includes("client")) baseName = "client";
53897
+ else if (promptLower.includes("component")) baseName = "component";
53898
+ else if (promptLower.includes("function")) baseName = "function";
53899
+ else if (promptLower.includes("class")) baseName = "class";
53900
+ else if (promptLower.includes("test")) baseName = "test";
53901
+ else if (promptLower.includes("script")) baseName = "script";
53902
+ else if (promptLower.includes("app")) baseName = "app";
53903
+ else if (promptLower.includes("main")) baseName = "main";
53904
+ else if (promptLower.includes("index")) baseName = "index";
53905
+ else if (promptLower.includes("util")) baseName = "utils";
53906
+ else if (promptLower.includes("helper")) baseName = "helper";
53907
+ else if (promptLower.includes("service")) baseName = "service";
53908
+ else if (promptLower.includes("model")) baseName = "model";
53909
+ else if (promptLower.includes("controller")) baseName = "controller";
53910
+ else if (promptLower.includes("route")) baseName = "routes";
53911
+ else if (promptLower.includes("config")) baseName = "config";
53912
+ if (baseName === "index" && extension) return `index.${extension}`;
53913
+ return `${baseName}_${timestamp}.${extension}`;
53914
+ }
53915
+ var ALLOWED_EXTS;
53916
+ var init_code_utils = __esm({
53917
+ "src/cli/code-utils.ts"() {
53918
+ ALLOWED_EXTS = /* @__PURE__ */ new Set([
53919
+ "ts",
53920
+ "tsx",
53921
+ "js",
53922
+ "jsx",
53923
+ "mjs",
53924
+ "cjs",
53925
+ "json",
53926
+ "yml",
53927
+ "yaml",
53928
+ "md",
53929
+ "html",
53930
+ "css",
53931
+ "scss",
53932
+ "py",
53933
+ "java",
53934
+ "kt",
53935
+ "rb",
53936
+ "go",
53937
+ "rs",
53938
+ "swift",
53939
+ "c",
53940
+ "cpp",
53941
+ "cs",
53942
+ "sh",
53943
+ "xml",
53944
+ "sql",
53945
+ "dockerfile",
53946
+ "makefile",
53947
+ "txt"
53948
+ ]);
53949
+ }
53950
+ });
53684
53951
  async function scanRepo(cwd2) {
53685
53952
  if (_cache && _cache.root === cwd2) return _cache;
53686
53953
  const root = cwd2;
@@ -54772,7 +55039,18 @@ async function orchestrate(request, opts) {
54772
55039
  async () => {
54773
55040
  const started = Date.now();
54774
55041
  try {
54775
- const response = await executeCode(request);
55042
+ const FILE_FORMAT_INSTRUCTIONS = [
55043
+ "You are a senior software engineer. Respond with CODE ONLY.",
55044
+ "At the very start of each file, include a filename hint as a comment on the first line:",
55045
+ "// filename: <name.ext> (or # filename: <name.ext> for Python, <!-- filename: name.ext --> for HTML/CSS)",
55046
+ "If multiple files are required, use the strict multi-file protocol with one or more file sections:",
55047
+ "[BEGIN file: path]\n<content>\n[END]",
55048
+ "Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
55049
+ ].join("\n");
55050
+ const enriched = `${FILE_FORMAT_INSTRUCTIONS}
55051
+
55052
+ ${request}`;
55053
+ const response = await executeCode(enriched);
54776
55054
  const raw = (response.output || response?.data?.content || "").trim();
54777
55055
  if (!raw) {
54778
55056
  return {
@@ -54838,8 +55116,10 @@ async function orchestrate(request, opts) {
54838
55116
  } else {
54839
55117
  for (let i2 = 0; i2 < blocks.length; i2++) {
54840
55118
  const b = blocks[i2];
55119
+ const desired = typeof b.filename === "string" && b.filename.trim() ? b.filename.trim() : null;
55120
+ const path60 = desired || suggestName2(request, b.language, i2);
54841
55121
  initial.push({
54842
- path: suggestName2(request, b.language, i2),
55122
+ path: path60,
54843
55123
  kind: "source",
54844
55124
  action: "create",
54845
55125
  description: describe2(b.language, ""),
@@ -54855,6 +55135,21 @@ async function orchestrate(request, opts) {
54855
55135
  }
54856
55136
  }
54857
55137
  const normalized = await normalizePlans(initial, { root: opts.root });
55138
+ try {
55139
+ const [{ access: access18 }, path60] = await Promise.all([
55140
+ import('fs/promises'),
55141
+ import('path')
55142
+ ]);
55143
+ for (const p of normalized) {
55144
+ try {
55145
+ await access18(path60.join(opts.root, p.path));
55146
+ p.action = "modify";
55147
+ } catch {
55148
+ p.action = "create";
55149
+ }
55150
+ }
55151
+ } catch {
55152
+ }
54858
55153
  const validated = await validatePlan(normalized, { root: opts.root, profile, flags: { maxFiles: opts.flags.maxFiles, yes: opts.flags.yes, interactive: !!opts.flags.interactive, ...opts.flags } });
54859
55154
  const outputMode = resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
54860
55155
  const displayFiles = validated.files.concat(
@@ -54988,6 +55283,15 @@ function mapCodeErrorToReason(err) {
54988
55283
  }
54989
55284
  function extractBlocks(content) {
54990
55285
  const blocks = [];
55286
+ const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
55287
+ let pm;
55288
+ while ((pm = proto.exec(content)) !== null) {
55289
+ const fname = (pm[1] || "").trim();
55290
+ const body = (pm[2] || "").trim();
55291
+ const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
55292
+ blocks.push({ language: ext2 || "text", code: body, filename: fname });
55293
+ }
55294
+ if (blocks.length > 0) return blocks;
54991
55295
  const re = /```(\w*)\n([\s\S]*?)```/g;
54992
55296
  let m2;
54993
55297
  while ((m2 = re.exec(content)) !== null) blocks.push({ language: m2[1] || "javascript", code: m2[2].trim() });
@@ -55226,6 +55530,7 @@ var init_code_command = __esm({
55226
55530
  init_base_command();
55227
55531
  init_rate_limit_handler();
55228
55532
  init_animations();
55533
+ init_code_utils();
55229
55534
  LANGUAGE_EXTENSIONS = {
55230
55535
  javascript: ".js",
55231
55536
  typescript: ".ts",
@@ -55458,10 +55763,19 @@ ${pretty}`);
55458
55763
  const count = Math.min(blocks.length, limit);
55459
55764
  for (let i2 = 0; i2 < count; i2++) {
55460
55765
  const block = blocks[i2];
55461
- const filename = this.generateFilename(request, block.language);
55462
- const ext2 = LANGUAGE_EXTENSIONS[block.language] || ".txt";
55463
- const naive = i2 === 0 ? `${filename}${ext2}` : `${filename}_${i2 + 1}${ext2}`;
55464
- plans.push({ path: naive, kind: "source", action: "create", description: this.describeBrief(block.language, naive), language: block.language, preview: block.code });
55766
+ const suggested = this.extractSuggestedFilename(block.code);
55767
+ const inferredExt = inferExtensionFromContent(block.language, block.code) || "txt";
55768
+ let finalName;
55769
+ if (suggested) {
55770
+ const clean = sanitizeFilenameStrict(suggested);
55771
+ const hasExt = /\.[A-Za-z0-9._-]+$/.test(clean);
55772
+ finalName = hasExt ? clean : `${clean}.${inferredExt}`;
55773
+ } else {
55774
+ const base = this.generateFilename(request, block.language);
55775
+ const ext2 = LANGUAGE_EXTENSIONS[block.language] || `.${inferredExt}`;
55776
+ finalName = i2 === 0 ? `${base}${ext2}` : `${base}_${i2 + 1}${ext2}`;
55777
+ }
55778
+ plans.push({ path: finalName, kind: "source", action: "create", description: this.describeBrief(block.language, finalName), language: block.language, preview: block.code });
55465
55779
  }
55466
55780
  const { normalizePlans: normalizePlans2 } = await Promise.resolve().then(() => (init_FilePlanBuilder(), FilePlanBuilder_exports));
55467
55781
  const normalized = await normalizePlans2(plans, { root });
@@ -55471,6 +55785,18 @@ ${pretty}`);
55471
55785
  }
55472
55786
  return normalized;
55473
55787
  }
55788
+ extractSuggestedFilename(code) {
55789
+ const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
55790
+ const m1 = firstLine.match(/^\/\/\s*filename:\s*(.+)$/i);
55791
+ if (m1?.[1]) return m1[1].trim();
55792
+ const m2 = firstLine.match(/^#\s*filename:\s*(.+)$/i);
55793
+ if (m2?.[1]) return m2[1].trim();
55794
+ const m3 = firstLine.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i);
55795
+ if (m3?.[1]) return m3[1].trim();
55796
+ const m4 = firstLine.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
55797
+ if (m4?.[1]) return m4[1].trim();
55798
+ return void 0;
55799
+ }
55474
55800
  describeBrief(language, final) {
55475
55801
  const l = language.toLowerCase();
55476
55802
  if (/tsx|jsx/.test(l) || /\.tsx$|\.jsx$/.test(final)) return "UI component";
@@ -55585,7 +55911,10 @@ ${pretty}`);
55585
55911
  * Detect programming language from content
55586
55912
  */
55587
55913
  detectLanguage(code) {
55588
- if (code.includes("import React") || code.includes("<")) return "jsx";
55914
+ const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
55915
+ const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
55916
+ const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
55917
+ if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
55589
55918
  if (code.includes("interface ") || code.includes(": string")) return "typescript";
55590
55919
  if (code.includes("def ") || code.includes("print(")) return "python";
55591
55920
  if (code.includes("func ") || code.includes("package main")) return "go";
@@ -72477,7 +72806,7 @@ var init_ai_response_service = __esm({
72477
72806
  */
72478
72807
  async callLLM(prompt, opts = {}) {
72479
72808
  const {
72480
- 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.",
72809
+ 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.",
72481
72810
  model = void 0,
72482
72811
  provider = DEFAULT_PROVIDER2,
72483
72812
  temperature = 0.2,
@@ -73716,243 +74045,6 @@ var init_server = __esm({
73716
74045
  init_text_logger();
73717
74046
  }
73718
74047
  });
73719
- function extractCodeInfo(codeBlock) {
73720
- const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
73721
- if (!match2) {
73722
- return { language: "text", code: codeBlock, extension: "txt" };
73723
- }
73724
- const fenceHeader = match2[1] || "";
73725
- const language = fenceHeader.split(/\s+/)[0] || "text";
73726
- const code = match2[2] || "";
73727
- let filename;
73728
- const fnameHeader = fenceHeader.match(/filename\s*=\s*([^\s]+)/i);
73729
- if (fnameHeader) filename = sanitizeFilename(fnameHeader[1]);
73730
- if (!filename) {
73731
- const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
73732
- 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);
73733
- if (commentName && commentName[1]) filename = sanitizeFilename(commentName[1]);
73734
- }
73735
- const extension = inferExtensionFromContent(language, code) || "txt";
73736
- return { language, code, extension, filename };
73737
- }
73738
- function extractAllCodeInfos(markdown) {
73739
- const out = [];
73740
- const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
73741
- const protoMatches = markdown.matchAll(proto);
73742
- let anyProto = false;
73743
- for (const m2 of protoMatches) {
73744
- anyProto = true;
73745
- const fname = (m2[1] || "").trim();
73746
- const body = m2[2] || "";
73747
- const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
73748
- out.push({ language: ext2, code: body, extension: ext2, filename: sanitizeFilenameStrict(fname) });
73749
- }
73750
- if (anyProto) return out;
73751
- const blocks = [];
73752
- const re = /```[^`]*\n[\s\S]*?```/g;
73753
- const matches = markdown.match(re);
73754
- if (matches && matches.length > 0) {
73755
- for (const m2 of matches) {
73756
- try {
73757
- blocks.push(extractCodeInfo(m2));
73758
- } catch {
73759
- }
73760
- }
73761
- } else {
73762
- blocks.push(extractCodeInfo(`\`\`\`text
73763
- ${markdown}
73764
- \`\`\``));
73765
- }
73766
- return blocks;
73767
- }
73768
- function sanitizeFilename(name2) {
73769
- const base = name2.replace(/^[\\/]+/, "").replace(/[\0<>:"|?*]/g, "").trim();
73770
- return base || "file";
73771
- }
73772
- function inferExtensionFromContent(language, code) {
73773
- const lowerLang = (language || "").toLowerCase();
73774
- code.toLowerCase();
73775
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "html";
73776
- if (/^\s*\{[\s\S]*\}\s*$/.test(code.trim())) return "json";
73777
- if (/^\s*#include\s+</m.test(code)) return "c";
73778
- if (/^\s*import\s+react/m.test(code) || /jsx/m.test(lowerLang)) return "jsx";
73779
- if (/^\s*<\?xml/m.test(code)) return "xml";
73780
- if (/^#!/.test(code)) return "sh";
73781
- if (/^\s*package\s+[a-zA-Z0-9_.]+;/.test(code)) return "java";
73782
- const map = {
73783
- javascript: "js",
73784
- typescript: "ts",
73785
- jsx: "jsx",
73786
- tsx: "tsx",
73787
- python: "py",
73788
- java: "java",
73789
- cpp: "cpp",
73790
- c: "c",
73791
- csharp: "cs",
73792
- php: "php",
73793
- ruby: "rb",
73794
- go: "go",
73795
- rust: "rs",
73796
- swift: "swift",
73797
- kotlin: "kt",
73798
- html: "html",
73799
- css: "css",
73800
- scss: "scss",
73801
- json: "json",
73802
- yaml: "yaml",
73803
- yml: "yml",
73804
- xml: "xml",
73805
- sql: "sql",
73806
- bash: "sh",
73807
- shell: "sh",
73808
- sh: "sh",
73809
- dockerfile: "dockerfile",
73810
- makefile: "makefile",
73811
- markdown: "md",
73812
- md: "md",
73813
- text: "txt"
73814
- };
73815
- return map[lowerLang];
73816
- }
73817
- function sanitizeFilenameStrict(name2) {
73818
- const RESERVED = /* @__PURE__ */ new Set([
73819
- "con",
73820
- "prn",
73821
- "aux",
73822
- "nul",
73823
- "com1",
73824
- "com2",
73825
- "com3",
73826
- "com4",
73827
- "com5",
73828
- "com6",
73829
- "com7",
73830
- "com8",
73831
- "com9",
73832
- "lpt1",
73833
- "lpt2",
73834
- "lpt3",
73835
- "lpt4",
73836
- "lpt5",
73837
- "lpt6",
73838
- "lpt7",
73839
- "lpt8",
73840
- "lpt9"
73841
- ]);
73842
- const cleaned = name2.replace(/[\u0000-\u001F\x7F<>:"/\\|?*]/g, "-").replace(/\s+/g, " ").trim();
73843
- const leaf = cleaned.split(/[\\/]/).pop() || "file";
73844
- const stem = leaf.replace(/\.[^.]+$/, "");
73845
- if (leaf.includes("..") || RESERVED.has(stem.toLowerCase())) return "file";
73846
- return leaf.length > 128 ? leaf.slice(0, 120) : leaf;
73847
- }
73848
- function coerceExtension(ext2, fallback2) {
73849
- const e2 = (ext2 || "").toLowerCase().replace(/^\./, "");
73850
- if (ALLOWED_EXTS.has(e2)) return e2;
73851
- return fallback2;
73852
- }
73853
- function safeResolve(root, fname) {
73854
- const abs = path11__namespace.resolve(root, fname);
73855
- const base = path11__namespace.resolve(root);
73856
- if (!(abs + path11__namespace.sep).startsWith(base + path11__namespace.sep) && abs !== base) {
73857
- throw new Error("Path traversal detected");
73858
- }
73859
- return abs;
73860
- }
73861
- async function ensureUniquePath(absPath) {
73862
- const dir = path11__namespace.dirname(absPath);
73863
- const ext2 = path11__namespace.extname(absPath);
73864
- const base = path11__namespace.basename(absPath, ext2);
73865
- let candidate = absPath;
73866
- let i2 = 1;
73867
- while (true) {
73868
- try {
73869
- await fsp__namespace.access(candidate);
73870
- candidate = path11__namespace.join(dir, `${base}(${i2})${ext2}`);
73871
- i2++;
73872
- } catch {
73873
- return candidate;
73874
- }
73875
- }
73876
- }
73877
- function isLikelyBinary(text) {
73878
- if (text.includes("\0")) return true;
73879
- const len = Math.min(text.length, 8192);
73880
- let nonText = 0;
73881
- for (let i2 = 0; i2 < len; i2++) {
73882
- const code = text.charCodeAt(i2);
73883
- const isPrintable = code >= 9 && code <= 13 || code >= 32 && code <= 126 || code >= 160;
73884
- if (!isPrintable) nonText++;
73885
- }
73886
- return nonText / Math.max(1, len) > 0.15;
73887
- }
73888
- function generateCodeFilename(prompt, language, extension, code, suggested) {
73889
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
73890
- if (suggested) return sanitizeFilename(suggested);
73891
- if (code) {
73892
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "index.html";
73893
- if (/^\s*import\s+react/m.test(code)) return "App." + (extension || "tsx");
73894
- if (/express\(\)/.test(code) || /from\s+express/.test(code)) return `server.${extension || "js"}`;
73895
- if (/^#!\//.test(code)) return `script.${extension || "sh"}`;
73896
- }
73897
- const promptLower = (prompt || "").toLowerCase();
73898
- let baseName = "code";
73899
- if (promptLower.includes("api")) baseName = "api";
73900
- else if (promptLower.includes("server")) baseName = "server";
73901
- else if (promptLower.includes("client")) baseName = "client";
73902
- else if (promptLower.includes("component")) baseName = "component";
73903
- else if (promptLower.includes("function")) baseName = "function";
73904
- else if (promptLower.includes("class")) baseName = "class";
73905
- else if (promptLower.includes("test")) baseName = "test";
73906
- else if (promptLower.includes("script")) baseName = "script";
73907
- else if (promptLower.includes("app")) baseName = "app";
73908
- else if (promptLower.includes("main")) baseName = "main";
73909
- else if (promptLower.includes("index")) baseName = "index";
73910
- else if (promptLower.includes("util")) baseName = "utils";
73911
- else if (promptLower.includes("helper")) baseName = "helper";
73912
- else if (promptLower.includes("service")) baseName = "service";
73913
- else if (promptLower.includes("model")) baseName = "model";
73914
- else if (promptLower.includes("controller")) baseName = "controller";
73915
- else if (promptLower.includes("route")) baseName = "routes";
73916
- else if (promptLower.includes("config")) baseName = "config";
73917
- if (baseName === "index" && extension) return `index.${extension}`;
73918
- return `${baseName}_${timestamp}.${extension}`;
73919
- }
73920
- var ALLOWED_EXTS;
73921
- var init_code_utils = __esm({
73922
- "src/cli/code-utils.ts"() {
73923
- ALLOWED_EXTS = /* @__PURE__ */ new Set([
73924
- "ts",
73925
- "tsx",
73926
- "js",
73927
- "jsx",
73928
- "mjs",
73929
- "cjs",
73930
- "json",
73931
- "yml",
73932
- "yaml",
73933
- "md",
73934
- "html",
73935
- "css",
73936
- "scss",
73937
- "py",
73938
- "java",
73939
- "kt",
73940
- "rb",
73941
- "go",
73942
- "rs",
73943
- "swift",
73944
- "c",
73945
- "cpp",
73946
- "cs",
73947
- "sh",
73948
- "xml",
73949
- "sql",
73950
- "dockerfile",
73951
- "makefile",
73952
- "txt"
73953
- ]);
73954
- }
73955
- });
73956
74048
 
73957
74049
  // src/cli.ts
73958
74050
  var cli_exports = {};
@@ -74194,13 +74286,10 @@ async function handleComplexChat(request, triageResult) {
74194
74286
  } catch {
74195
74287
  }
74196
74288
  }
74197
- if (!content && ai?.generateResponse) {
74198
- content = await ai.generateResponse({
74199
- userInput: `Create a concise plan and next steps for: ${request}`,
74200
- sessionMemory: [],
74201
- provider: process.env.MARIA_PROVIDER || "google",
74202
- model: process.env.MARIA_MODEL || "gemini-2.5-flash"
74203
- });
74289
+ if (!content) {
74290
+ animation.stop();
74291
+ await streamAnswer(request, { triage: triageResult });
74292
+ return;
74204
74293
  }
74205
74294
  animation.stop();
74206
74295
  const cleaned = content && typeof content === "string" ? content : buildComplexPlanSteps(request).join("\n");