@bonginkan/maria 4.3.17 → 4.3.19

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.17"}`
1707
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.19"}`
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.17"}`,
2410
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.19"}`,
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.17",
16075
- description: "\u{1F680} MARIA v4.3.17 - 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.19",
16075
+ description: "\u{1F680} MARIA v4.3.19 - 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",
@@ -25681,7 +25681,7 @@ var init_about_command = __esm({
25681
25681
  async execute(args2, context2) {
25682
25682
  const output3 = [];
25683
25683
  output3.push("");
25684
- output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.17"));
25684
+ output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.19"));
25685
25685
  output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
25686
25686
  output3.push("");
25687
25687
  output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -37590,6 +37590,249 @@ var init_rate_limit_handler = __esm({
37590
37590
  "src/services/api-client/rate-limit-handler.ts"() {
37591
37591
  }
37592
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
+ });
37593
37836
  async function scanRepo(cwd2) {
37594
37837
  if (_cache && _cache.root === cwd2) return _cache;
37595
37838
  const root = cwd2;
@@ -38681,7 +38924,18 @@ async function orchestrate(request, opts) {
38681
38924
  async () => {
38682
38925
  const started = Date.now();
38683
38926
  try {
38684
- 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);
38685
38939
  const raw = (response.output || response?.data?.content || "").trim();
38686
38940
  if (!raw) {
38687
38941
  return {
@@ -38747,8 +39001,10 @@ async function orchestrate(request, opts) {
38747
39001
  } else {
38748
39002
  for (let i2 = 0; i2 < blocks.length; i2++) {
38749
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);
38750
39006
  initial.push({
38751
- path: suggestName2(request, b.language, i2),
39007
+ path: path60,
38752
39008
  kind: "source",
38753
39009
  action: "create",
38754
39010
  description: describe2(b.language, ""),
@@ -38764,6 +39020,21 @@ async function orchestrate(request, opts) {
38764
39020
  }
38765
39021
  }
38766
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
+ }
38767
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 } });
38768
39039
  const outputMode = resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
38769
39040
  const displayFiles = validated.files.concat(
@@ -38897,6 +39168,15 @@ function mapCodeErrorToReason(err) {
38897
39168
  }
38898
39169
  function extractBlocks(content) {
38899
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;
38900
39180
  const re = /```(\w*)\n([\s\S]*?)```/g;
38901
39181
  let m2;
38902
39182
  while ((m2 = re.exec(content)) !== null) blocks.push({ language: m2[1] || "javascript", code: m2[2].trim() });
@@ -39135,6 +39415,7 @@ var init_code_command = __esm({
39135
39415
  init_base_command();
39136
39416
  init_rate_limit_handler();
39137
39417
  init_animations();
39418
+ init_code_utils();
39138
39419
  LANGUAGE_EXTENSIONS = {
39139
39420
  javascript: ".js",
39140
39421
  typescript: ".ts",
@@ -39367,10 +39648,19 @@ ${pretty}`);
39367
39648
  const count = Math.min(blocks.length, limit);
39368
39649
  for (let i2 = 0; i2 < count; i2++) {
39369
39650
  const block = blocks[i2];
39370
- const filename = this.generateFilename(request, block.language);
39371
- const ext2 = LANGUAGE_EXTENSIONS[block.language] || ".txt";
39372
- const naive = i2 === 0 ? `${filename}${ext2}` : `${filename}_${i2 + 1}${ext2}`;
39373
- 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 });
39374
39664
  }
39375
39665
  const { normalizePlans: normalizePlans2 } = await Promise.resolve().then(() => (init_FilePlanBuilder(), FilePlanBuilder_exports));
39376
39666
  const normalized = await normalizePlans2(plans, { root });
@@ -39380,6 +39670,18 @@ ${pretty}`);
39380
39670
  }
39381
39671
  return normalized;
39382
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
+ }
39383
39685
  describeBrief(language, final) {
39384
39686
  const l = language.toLowerCase();
39385
39687
  if (/tsx|jsx/.test(l) || /\.tsx$|\.jsx$/.test(final)) return "UI component";
@@ -39494,7 +39796,10 @@ ${pretty}`);
39494
39796
  * Detect programming language from content
39495
39797
  */
39496
39798
  detectLanguage(code) {
39497
- 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";
39498
39803
  if (code.includes("interface ") || code.includes(": string")) return "typescript";
39499
39804
  if (code.includes("def ") || code.includes("print(")) return "python";
39500
39805
  if (code.includes("func ") || code.includes("package main")) return "go";
@@ -59343,7 +59648,7 @@ var init_ai_response_service = __esm({
59343
59648
  */
59344
59649
  async callLLM(prompt, opts = {}) {
59345
59650
  const {
59346
- 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.",
59347
59652
  model = void 0,
59348
59653
  provider = DEFAULT_PROVIDER2,
59349
59654
  temperature = 0.2,
@@ -60582,243 +60887,6 @@ var init_server = __esm({
60582
60887
  init_text_logger();
60583
60888
  }
60584
60889
  });
60585
- function extractCodeInfo(codeBlock) {
60586
- const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
60587
- if (!match2) {
60588
- return { language: "text", code: codeBlock, extension: "txt" };
60589
- }
60590
- const fenceHeader = match2[1] || "";
60591
- const language = fenceHeader.split(/\s+/)[0] || "text";
60592
- const code = match2[2] || "";
60593
- let filename;
60594
- const fnameHeader = fenceHeader.match(/filename\s*=\s*([^\s]+)/i);
60595
- if (fnameHeader) filename = sanitizeFilename(fnameHeader[1]);
60596
- if (!filename) {
60597
- const firstLine = (code.split(/\r?\n/, 1)[0] || "").trim();
60598
- 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);
60599
- if (commentName && commentName[1]) filename = sanitizeFilename(commentName[1]);
60600
- }
60601
- const extension = inferExtensionFromContent(language, code) || "txt";
60602
- return { language, code, extension, filename };
60603
- }
60604
- function extractAllCodeInfos(markdown) {
60605
- const out = [];
60606
- const proto = /\[BEGIN\s+file:\s*([^\]\n]+)\]\s*\n([\s\S]*?)\[END\]/g;
60607
- const protoMatches = markdown.matchAll(proto);
60608
- let anyProto = false;
60609
- for (const m2 of protoMatches) {
60610
- anyProto = true;
60611
- const fname = (m2[1] || "").trim();
60612
- const body = m2[2] || "";
60613
- const ext2 = (fname.split(".").pop() || "txt").toLowerCase();
60614
- out.push({ language: ext2, code: body, extension: ext2, filename: sanitizeFilenameStrict(fname) });
60615
- }
60616
- if (anyProto) return out;
60617
- const blocks = [];
60618
- const re = /```[^`]*\n[\s\S]*?```/g;
60619
- const matches = markdown.match(re);
60620
- if (matches && matches.length > 0) {
60621
- for (const m2 of matches) {
60622
- try {
60623
- blocks.push(extractCodeInfo(m2));
60624
- } catch {
60625
- }
60626
- }
60627
- } else {
60628
- blocks.push(extractCodeInfo(`\`\`\`text
60629
- ${markdown}
60630
- \`\`\``));
60631
- }
60632
- return blocks;
60633
- }
60634
- function sanitizeFilename(name2) {
60635
- const base = name2.replace(/^[\\/]+/, "").replace(/[\0<>:"|?*]/g, "").trim();
60636
- return base || "file";
60637
- }
60638
- function inferExtensionFromContent(language, code) {
60639
- const lowerLang = (language || "").toLowerCase();
60640
- code.toLowerCase();
60641
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "html";
60642
- if (/^\s*\{[\s\S]*\}\s*$/.test(code.trim())) return "json";
60643
- if (/^\s*#include\s+</m.test(code)) return "c";
60644
- if (/^\s*import\s+react/m.test(code) || /jsx/m.test(lowerLang)) return "jsx";
60645
- if (/^\s*<\?xml/m.test(code)) return "xml";
60646
- if (/^#!/.test(code)) return "sh";
60647
- if (/^\s*package\s+[a-zA-Z0-9_.]+;/.test(code)) return "java";
60648
- const map = {
60649
- javascript: "js",
60650
- typescript: "ts",
60651
- jsx: "jsx",
60652
- tsx: "tsx",
60653
- python: "py",
60654
- java: "java",
60655
- cpp: "cpp",
60656
- c: "c",
60657
- csharp: "cs",
60658
- php: "php",
60659
- ruby: "rb",
60660
- go: "go",
60661
- rust: "rs",
60662
- swift: "swift",
60663
- kotlin: "kt",
60664
- html: "html",
60665
- css: "css",
60666
- scss: "scss",
60667
- json: "json",
60668
- yaml: "yaml",
60669
- yml: "yml",
60670
- xml: "xml",
60671
- sql: "sql",
60672
- bash: "sh",
60673
- shell: "sh",
60674
- sh: "sh",
60675
- dockerfile: "dockerfile",
60676
- makefile: "makefile",
60677
- markdown: "md",
60678
- md: "md",
60679
- text: "txt"
60680
- };
60681
- return map[lowerLang];
60682
- }
60683
- function sanitizeFilenameStrict(name2) {
60684
- const RESERVED = /* @__PURE__ */ new Set([
60685
- "con",
60686
- "prn",
60687
- "aux",
60688
- "nul",
60689
- "com1",
60690
- "com2",
60691
- "com3",
60692
- "com4",
60693
- "com5",
60694
- "com6",
60695
- "com7",
60696
- "com8",
60697
- "com9",
60698
- "lpt1",
60699
- "lpt2",
60700
- "lpt3",
60701
- "lpt4",
60702
- "lpt5",
60703
- "lpt6",
60704
- "lpt7",
60705
- "lpt8",
60706
- "lpt9"
60707
- ]);
60708
- const cleaned = name2.replace(/[\u0000-\u001F\x7F<>:"/\\|?*]/g, "-").replace(/\s+/g, " ").trim();
60709
- const leaf = cleaned.split(/[\\/]/).pop() || "file";
60710
- const stem = leaf.replace(/\.[^.]+$/, "");
60711
- if (leaf.includes("..") || RESERVED.has(stem.toLowerCase())) return "file";
60712
- return leaf.length > 128 ? leaf.slice(0, 120) : leaf;
60713
- }
60714
- function coerceExtension(ext2, fallback2) {
60715
- const e2 = (ext2 || "").toLowerCase().replace(/^\./, "");
60716
- if (ALLOWED_EXTS.has(e2)) return e2;
60717
- return fallback2;
60718
- }
60719
- function safeResolve(root, fname) {
60720
- const abs = path10__namespace.resolve(root, fname);
60721
- const base = path10__namespace.resolve(root);
60722
- if (!(abs + path10__namespace.sep).startsWith(base + path10__namespace.sep) && abs !== base) {
60723
- throw new Error("Path traversal detected");
60724
- }
60725
- return abs;
60726
- }
60727
- async function ensureUniquePath(absPath) {
60728
- const dir = path10__namespace.dirname(absPath);
60729
- const ext2 = path10__namespace.extname(absPath);
60730
- const base = path10__namespace.basename(absPath, ext2);
60731
- let candidate = absPath;
60732
- let i2 = 1;
60733
- while (true) {
60734
- try {
60735
- await fsp__namespace.access(candidate);
60736
- candidate = path10__namespace.join(dir, `${base}(${i2})${ext2}`);
60737
- i2++;
60738
- } catch {
60739
- return candidate;
60740
- }
60741
- }
60742
- }
60743
- function isLikelyBinary(text) {
60744
- if (text.includes("\0")) return true;
60745
- const len = Math.min(text.length, 8192);
60746
- let nonText = 0;
60747
- for (let i2 = 0; i2 < len; i2++) {
60748
- const code = text.charCodeAt(i2);
60749
- const isPrintable = code >= 9 && code <= 13 || code >= 32 && code <= 126 || code >= 160;
60750
- if (!isPrintable) nonText++;
60751
- }
60752
- return nonText / Math.max(1, len) > 0.15;
60753
- }
60754
- function generateCodeFilename(prompt, language, extension, code, suggested) {
60755
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
60756
- if (suggested) return sanitizeFilename(suggested);
60757
- if (code) {
60758
- if (/<!doctype\s+html>/i.test(code) || /<html[\s>]/i.test(code)) return "index.html";
60759
- if (/^\s*import\s+react/m.test(code)) return "App." + (extension || "tsx");
60760
- if (/express\(\)/.test(code) || /from\s+express/.test(code)) return `server.${extension || "js"}`;
60761
- if (/^#!\//.test(code)) return `script.${extension || "sh"}`;
60762
- }
60763
- const promptLower = (prompt || "").toLowerCase();
60764
- let baseName = "code";
60765
- if (promptLower.includes("api")) baseName = "api";
60766
- else if (promptLower.includes("server")) baseName = "server";
60767
- else if (promptLower.includes("client")) baseName = "client";
60768
- else if (promptLower.includes("component")) baseName = "component";
60769
- else if (promptLower.includes("function")) baseName = "function";
60770
- else if (promptLower.includes("class")) baseName = "class";
60771
- else if (promptLower.includes("test")) baseName = "test";
60772
- else if (promptLower.includes("script")) baseName = "script";
60773
- else if (promptLower.includes("app")) baseName = "app";
60774
- else if (promptLower.includes("main")) baseName = "main";
60775
- else if (promptLower.includes("index")) baseName = "index";
60776
- else if (promptLower.includes("util")) baseName = "utils";
60777
- else if (promptLower.includes("helper")) baseName = "helper";
60778
- else if (promptLower.includes("service")) baseName = "service";
60779
- else if (promptLower.includes("model")) baseName = "model";
60780
- else if (promptLower.includes("controller")) baseName = "controller";
60781
- else if (promptLower.includes("route")) baseName = "routes";
60782
- else if (promptLower.includes("config")) baseName = "config";
60783
- if (baseName === "index" && extension) return `index.${extension}`;
60784
- return `${baseName}_${timestamp}.${extension}`;
60785
- }
60786
- var ALLOWED_EXTS;
60787
- var init_code_utils = __esm({
60788
- "src/cli/code-utils.ts"() {
60789
- ALLOWED_EXTS = /* @__PURE__ */ new Set([
60790
- "ts",
60791
- "tsx",
60792
- "js",
60793
- "jsx",
60794
- "mjs",
60795
- "cjs",
60796
- "json",
60797
- "yml",
60798
- "yaml",
60799
- "md",
60800
- "html",
60801
- "css",
60802
- "scss",
60803
- "py",
60804
- "java",
60805
- "kt",
60806
- "rb",
60807
- "go",
60808
- "rs",
60809
- "swift",
60810
- "c",
60811
- "cpp",
60812
- "cs",
60813
- "sh",
60814
- "xml",
60815
- "sql",
60816
- "dockerfile",
60817
- "makefile",
60818
- "txt"
60819
- ]);
60820
- }
60821
- });
60822
60890
 
60823
60891
  // src/services/startup-display.ts
60824
60892
  var startup_display_exports = {};
@@ -74276,13 +74344,10 @@ async function handleComplexChat(request, triageResult) {
74276
74344
  } catch {
74277
74345
  }
74278
74346
  }
74279
- if (!content && ai?.generateResponse) {
74280
- content = await ai.generateResponse({
74281
- userInput: `Create a concise plan and next steps for: ${request}`,
74282
- sessionMemory: [],
74283
- provider: process.env.MARIA_PROVIDER || "google",
74284
- model: process.env.MARIA_MODEL || "gemini-2.5-flash"
74285
- });
74347
+ if (!content) {
74348
+ animation.stop();
74349
+ await streamAnswer(request, { triage: triageResult });
74350
+ return;
74286
74351
  }
74287
74352
  animation.stop();
74288
74353
  const cleaned = content && typeof content === "string" ? content : buildComplexPlanSteps(request).join("\n");