@bonginkan/maria 4.4.6 → 4.4.7

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
@@ -1828,7 +1828,7 @@ var init_AuthenticationManager = __esm({
1828
1828
  const response = await fetch(`${this.apiBase}/api/user/profile`, {
1829
1829
  headers: {
1830
1830
  "Authorization": `Bearer ${tokens2.accessToken}`,
1831
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.4.6"}`
1831
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.4.7"}`
1832
1832
  }
1833
1833
  });
1834
1834
  if (response.status === 401) {
@@ -2576,7 +2576,7 @@ async function callApi(path69, init3 = {}) {
2576
2576
  "Authorization": `Bearer ${token}`,
2577
2577
  "X-Device-Id": getDeviceId(),
2578
2578
  "X-Session-Id": getSessionId() || "",
2579
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.4.6"}`,
2579
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.4.7"}`,
2580
2580
  "Content-Type": init3.headers?.["Content-Type"] || "application/json"
2581
2581
  });
2582
2582
  const doFetch = async (token) => {
@@ -3953,9 +3953,14 @@ async function executeChat(messages, options) {
3953
3953
  } catch {
3954
3954
  }
3955
3955
  }
3956
+ const injectedAtt = globalThis.__maria_attachments_for_next_call__;
3957
+ try {
3958
+ globalThis.__maria_attachments_for_next_call__ = void 0;
3959
+ } catch {
3960
+ }
3956
3961
  const response = await callAPI("/v1/ai-proxy", {
3957
3962
  method: "POST",
3958
- body: { messages, taskType: "chat", ...options?.provider ? { provider: options.provider } : {}, ...options?.model ? { model: options.model } : {} }
3963
+ body: { messages, taskType: "chat", ...options?.provider ? { provider: options.provider } : {}, ...options?.model ? { model: options.model } : {}, ...Array.isArray(injectedAtt) && injectedAtt.length ? { metadata: { attachments: injectedAtt } } : {} }
3959
3964
  });
3960
3965
  if (process.env.MARIA_DEBUG === "1") {
3961
3966
  try {
@@ -4099,7 +4104,7 @@ async function collectFileAttachmentsFromText(text, cwd2 = process.cwd(), option
4099
4104
  continue;
4100
4105
  }
4101
4106
  const ext2 = (path12__namespace.extname(abs) || "").toLowerCase();
4102
- const mime = ext2 === ".pdf" ? "application/pdf" : ext2 === ".png" ? "image/png" : ext2 === ".jpg" || ext2 === ".jpeg" ? "image/jpeg" : ext2 === ".webp" ? "image/webp" : ext2 === ".gif" ? "image/gif" : ext2 === ".bmp" ? "image/bmp" : ext2 === ".svg" ? "image/svg+xml" : ext2 === ".tif" || ext2 === ".tiff" ? "image/tiff" : ext2 === ".heic" ? "image/heic" : ext2 === ".heif" ? "image/heif" : "text/plain";
4107
+ const mime = ext2 === ".pdf" ? "application/pdf" : ext2 === ".png" ? "image/png" : ext2 === ".jpg" || ext2 === ".jpeg" ? "image/jpeg" : ext2 === ".webp" ? "image/webp" : ext2 === ".gif" ? "image/gif" : ext2 === ".bmp" ? "image/bmp" : ext2 === ".svg" ? "image/svg+xml" : ext2 === ".tif" || ext2 === ".tiff" ? "image/tiff" : ext2 === ".heic" ? "image/heic" : ext2 === ".heif" ? "image/heif" : ext2 === ".md" ? "text/markdown" : ext2 === ".txt" ? "text/plain" : ext2 === ".json" ? "application/json" : ext2 === ".yml" || ext2 === ".yaml" ? "application/x-yaml" : ext2 === ".xml" ? "application/xml" : ext2 === ".docx" ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : ext2 === ".doc" ? "application/msword" : "text/plain";
4103
4108
  attachments.push({ name: path12__namespace.basename(abs), path: abs, mime, data_base64: buf.toString("base64") });
4104
4109
  seen.add(key);
4105
4110
  } catch {
@@ -15330,7 +15335,7 @@ var init_about_command = __esm({
15330
15335
  async execute(args2, context2) {
15331
15336
  const output3 = [];
15332
15337
  output3.push("");
15333
- output3.push(chalk49__default.default.cyan.bold("About MARIA v4.4.6"));
15338
+ output3.push(chalk49__default.default.cyan.bold("About MARIA v4.4.7"));
15334
15339
  output3.push(chalk49__default.default.gray("\u2550".repeat(40)));
15335
15340
  output3.push("");
15336
15341
  output3.push(chalk49__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -15410,7 +15415,7 @@ var init_contact_command = __esm({
15410
15415
  output3.push("");
15411
15416
  output3.push(chalk49__default.default.white.bold("\u{1F3E2} Company Information:"));
15412
15417
  output3.push(" Company: Bonginkan");
15413
- output3.push(" Product: MARIA v4.4.6");
15418
+ output3.push(" Product: MARIA v4.4.7");
15414
15419
  output3.push(" Website: https://bonginkan.ai");
15415
15420
  output3.push(" Product Site: https://maria-code.ai");
15416
15421
  output3.push("");
@@ -18707,8 +18712,8 @@ var require_package = __commonJS({
18707
18712
  "package.json"(exports, module) {
18708
18713
  module.exports = {
18709
18714
  name: "@bonginkan/maria",
18710
- version: "4.4.6",
18711
- description: "\u{1F680} MARIA v4.4.6 - 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.",
18715
+ version: "4.4.7",
18716
+ description: "\u{1F680} MARIA v4.4.7 - 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.",
18712
18717
  keywords: [
18713
18718
  "ai",
18714
18719
  "cli",
@@ -40068,6 +40073,32 @@ var init_image_command = __esm({
40068
40073
  try {
40069
40074
  const root = context2.environment.cwd;
40070
40075
  const cli = normalizeImageArgs(args2.raw, root);
40076
+ try {
40077
+ const routed = globalThis.__maria_routed_attachments;
40078
+ if (Array.isArray(routed) && routed.length) {
40079
+ const textSnippets = [];
40080
+ for (const a of routed.slice(0, 4)) {
40081
+ const mime = String(a.mime || "").toLowerCase();
40082
+ const isDoc = /^(text\/|application\/(pdf|json|xml|yaml|yml|msword|vnd\.openxmlformats))/i.test(mime) || /\.(md|txt|json|xml|ya?ml|pdf|docx?)$/i.test(String(a.name || a.path || ""));
40083
+ if (!isDoc) continue;
40084
+ const b64 = String(a.data_base64 || "");
40085
+ if (!b64) continue;
40086
+ try {
40087
+ const buf = Buffer.from(b64, "base64");
40088
+ const text = /pdf/.test(mime) ? "" : buf.toString("utf8");
40089
+ if (text) textSnippets.push(text.slice(0, 800));
40090
+ } catch {
40091
+ }
40092
+ }
40093
+ if (textSnippets.length) {
40094
+ cli.prompt = `${cli.prompt}
40095
+
40096
+ [context]
40097
+ ${textSnippets.join("\n---\n")}`.slice(0, 4e3);
40098
+ }
40099
+ }
40100
+ } catch {
40101
+ }
40071
40102
  if (cli.planOnly || cli.dryRun || !cli.apply) {
40072
40103
  const line = `Plan: ${cli.count} images ${cli.size[0]}x${cli.size[1]} ${cli.format} model=${cli.model || "auto"} concurrency=${cli.concurrency} retry=${cli.retry}`;
40073
40104
  const next = `Next: /image "${cli.prompt}" --size ${cli.size[0]}x${cli.size[1]} --format ${cli.format} --count ${cli.count} --apply`;
@@ -40619,6 +40650,32 @@ var init_video_command = __esm({
40619
40650
  try {
40620
40651
  const root = context2.environment.cwd;
40621
40652
  const cli = normalizeVideoArgs(args2.raw, root);
40653
+ try {
40654
+ const routed = globalThis.__maria_routed_attachments;
40655
+ if (Array.isArray(routed) && routed.length) {
40656
+ const textSnippets = [];
40657
+ for (const a of routed.slice(0, 4)) {
40658
+ const mime = String(a.mime || "").toLowerCase();
40659
+ const isDoc = /^(text\/|application\/(pdf|json|xml|yaml|yml|msword|vnd\.openxmlformats))/i.test(mime) || /\.(md|txt|json|xml|ya?ml|pdf|docx?)$/i.test(String(a.name || a.path || ""));
40660
+ if (!isDoc) continue;
40661
+ const b64 = String(a.data_base64 || "");
40662
+ if (!b64) continue;
40663
+ try {
40664
+ const buf = Buffer.from(b64, "base64");
40665
+ const text = /pdf/.test(mime) ? "" : buf.toString("utf8");
40666
+ if (text) textSnippets.push(text.slice(0, 800));
40667
+ } catch {
40668
+ }
40669
+ }
40670
+ if (textSnippets.length) {
40671
+ cli.prompt = `${cli.prompt}
40672
+
40673
+ [context]
40674
+ ${textSnippets.join("\n---\n")}`.slice(0, 4e3);
40675
+ }
40676
+ }
40677
+ } catch {
40678
+ }
40622
40679
  try {
40623
40680
  const hook = global.__MARIA_VIDEO_LLM_INFER__;
40624
40681
  if (hook) {
@@ -41317,7 +41374,7 @@ function detectChaptersFromIdea(idea, fallback2) {
41317
41374
  }
41318
41375
  return fallback2;
41319
41376
  }
41320
- async function generatePlan(prompt, lang, title, genre, llm, forcedLocal) {
41377
+ async function generatePlan(prompt, lang, title, genre, llm, forcedLocal, attachments) {
41321
41378
  const system = [
41322
41379
  "You generate a detailed novel outline (plot).",
41323
41380
  "Return Markdown with clear sections: Title, Logline, Themes, Characters, Chapter Outline.",
@@ -41354,12 +41411,13 @@ ${user}`;
41354
41411
  ${user}`, taskType: "creative" };
41355
41412
  if (llm?.provider) body.provider = llm.provider;
41356
41413
  if (llm?.model) body.model = llm.model;
41414
+ if (Array.isArray(attachments) && attachments.length) body.metadata = { attachments };
41357
41415
  const resp = await callAPI("/v1/ai-proxy", { method: "POST", body });
41358
41416
  const out = (resp?.data?.content || resp?.output || "").trim();
41359
41417
  return out;
41360
41418
  }
41361
41419
  }
41362
- async function generateChapters(planMarkdown, lang, chapters, llm, forcedLocal) {
41420
+ async function generateChapters(planMarkdown, lang, chapters, llm, forcedLocal, attachments) {
41363
41421
  const system = [
41364
41422
  "You expand a novel outline into chapter texts.",
41365
41423
  "Return only JSON array: [{ index: number, title: string, content: string }].",
@@ -41390,6 +41448,7 @@ ${planMarkdown}`;
41390
41448
  const body = { prompt, taskType: "creative" };
41391
41449
  if (llm?.provider) body.provider = llm.provider;
41392
41450
  if (llm?.model) body.model = llm.model;
41451
+ if (Array.isArray(attachments) && attachments.length) body.metadata = { attachments };
41393
41452
  const resp = await callAPI("/v1/ai-proxy", { method: "POST", body });
41394
41453
  raw = (resp?.data?.content || resp?.output || "").trim();
41395
41454
  }
@@ -41496,6 +41555,12 @@ var init_novel_command = __esm({
41496
41555
  if (Array.isArray(routed) && routed.length) autoAttachments = autoAttachments.concat(routed);
41497
41556
  } catch {
41498
41557
  }
41558
+ let routedAttachments = [];
41559
+ try {
41560
+ const routed = globalThis.__maria_routed_attachments;
41561
+ if (Array.isArray(routed) && routed.length) routedAttachments = routed;
41562
+ } catch {
41563
+ }
41499
41564
  let inferred = {};
41500
41565
  try {
41501
41566
  const spin = new ProcessAnimation();
@@ -41575,7 +41640,7 @@ var init_novel_command = __esm({
41575
41640
  const spin = new ProcessAnimation();
41576
41641
  spin.start();
41577
41642
  try {
41578
- plan = await generatePlan(ideaText, langDetected, title, genre, { provider: effectiveProvider, model: explicitModel }, forcedLocalSel);
41643
+ plan = await generatePlan(ideaText, langDetected, title, genre, { provider: effectiveProvider, model: explicitModel }, forcedLocalSel, routedAttachments);
41579
41644
  } finally {
41580
41645
  try {
41581
41646
  spin.stop();
@@ -41611,7 +41676,7 @@ var init_novel_command = __esm({
41611
41676
  const spin = new ProcessAnimation();
41612
41677
  spin.start();
41613
41678
  try {
41614
- return await generateChapters(plan, langDetected, chapters, { provider: effectiveProvider, model: explicitModel }, forcedLocalSel);
41679
+ return await generateChapters(plan, langDetected, chapters, { provider: effectiveProvider, model: explicitModel }, forcedLocalSel, routedAttachments);
41615
41680
  } finally {
41616
41681
  try {
41617
41682
  spin.stop();
@@ -42199,6 +42264,10 @@ async function getRepoFiles(root) {
42199
42264
  _repoFileIndexCache = { root, files: out };
42200
42265
  return out;
42201
42266
  }
42267
+ function isDocMime(m2) {
42268
+ const s2 = String(m2 || "").toLowerCase();
42269
+ return s2.startsWith("text/") || s2 === "application/pdf" || s2 === "application/json" || s2 === "application/xml" || s2 === "application/x-yaml" || s2 === "application/yaml" || s2 === "application/msword" || s2 === "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
42270
+ }
42202
42271
  function languageFromExt(ext2) {
42203
42272
  const e2 = ext2.toLowerCase().replace(/^\./, "");
42204
42273
  if (e2 === "ts") return "typescript";
@@ -42416,7 +42485,16 @@ async function orchestrate(request, opts) {
42416
42485
  const fallbackNotices = [];
42417
42486
  const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
42418
42487
  const explicitFilesRaw = parseExplicitFilenames(request);
42419
- const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
42488
+ let explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
42489
+ const isDocRelPath = (p2) => {
42490
+ const lower2 = p2.toLowerCase();
42491
+ if (lower2.startsWith(".maria/")) return true;
42492
+ const ext2 = lower2.includes(".") ? lower2.slice(lower2.lastIndexOf(".")) : "";
42493
+ return [".md", ".markdown", ".txt", ".json", ".yaml", ".yml", ".xml"].includes(ext2);
42494
+ };
42495
+ if (explicitFiles.length > 0) {
42496
+ explicitFiles = explicitFiles.filter((p2) => !isDocRelPath(p2));
42497
+ }
42420
42498
  dbg("explicitFiles", { raw: explicitFilesRaw, resolved: explicitFiles });
42421
42499
  const explicitAbsMap = /* @__PURE__ */ Object.create(null);
42422
42500
  if (explicitFiles.length > 0) {
@@ -42427,7 +42505,11 @@ async function orchestrate(request, opts) {
42427
42505
  }
42428
42506
  const isEditIntent = await detectEditIntentLLM(opts.root, request, {
42429
42507
  explicitFiles,
42430
- attachmentsCount: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0
42508
+ attachmentsCount: (() => {
42509
+ if (!Array.isArray(opts.attachedFiles) || opts.attachedFiles.length === 0) return 0;
42510
+ const docOnly = opts.attachedFiles.every((a) => isDocMime(a.mime));
42511
+ return docOnly ? 0 : opts.attachedFiles.length;
42512
+ })()
42431
42513
  });
42432
42514
  dbg("intent", { isEditIntent });
42433
42515
  let editTargets = explicitFiles;
@@ -42451,6 +42533,22 @@ async function orchestrate(request, opts) {
42451
42533
  dbg("attachment.map", { mappedCount: mapRes.mapped.length, warnings: mapRes.warnings });
42452
42534
  mapRes.warnings.slice();
42453
42535
  for (const m2 of mapRes.mapped) {
42536
+ try {
42537
+ const mime = m2?.attachment?.mime;
42538
+ if (isDocMime(mime)) {
42539
+ if (opts.flags.planOnly || opts.flags.dryRun || !opts.flags.apply) {
42540
+ initial.push({
42541
+ path: m2.path,
42542
+ kind: "doc",
42543
+ action: m2.exists ? "modify" : "create",
42544
+ description: m2.exists ? "Documentation (attached)" : "Documentation (attached)",
42545
+ preview: m2.attachment.content
42546
+ });
42547
+ }
42548
+ continue;
42549
+ }
42550
+ } catch {
42551
+ }
42454
42552
  initial.push({
42455
42553
  path: m2.path,
42456
42554
  kind: "source",
@@ -42495,10 +42593,17 @@ async function orchestrate(request, opts) {
42495
42593
  }
42496
42594
  } catch {
42497
42595
  }
42498
- const targetDirsAbs = Array.from(new Set(targetFilesAbs.map((p2) => p2.split("/").slice(0, -1).join("/")).filter(Boolean)));
42499
- const targetFilesSection = targetFilesAbs.length > 0 ? ["// TARGET FILES (absolute):", ...targetFilesAbs.map((p2) => `// - ${p2}`)].join("\n") : "";
42596
+ const isDocPath = (p2) => {
42597
+ const lower2 = p2.toLowerCase();
42598
+ if (lower2.includes("/.maria/")) return true;
42599
+ const ext2 = lower2.includes(".") ? lower2.slice(lower2.lastIndexOf(".")) : "";
42600
+ return [".md", ".markdown", ".txt", ".json", ".yaml", ".yml", ".xml"].includes(ext2);
42601
+ };
42602
+ const docOnlyTargets = targetFilesAbs.length > 0 && targetFilesAbs.every(isDocPath);
42603
+ const targetDirsAbs = docOnlyTargets ? [] : Array.from(new Set(targetFilesAbs.map((p2) => p2.split("/").slice(0, -1).join("/")).filter(Boolean)));
42604
+ const targetFilesSection = !docOnlyTargets && targetFilesAbs.length > 0 ? ["// TARGET FILES (absolute):", ...targetFilesAbs.map((p2) => `// - ${p2}`)].join("\n") : "";
42500
42605
  const targetDirsSection = targetDirsAbs.length > 0 ? ["// TARGET DIRECTORIES (absolute):", ...targetDirsAbs.map((p2) => `// - ${p2}`)].join("\n") : "";
42501
- const requestPreamble = isEditIntent ? [
42606
+ const requestPreamble = isEditIntent && !docOnlyTargets ? [
42502
42607
  "// EDIT MODE RULES:",
42503
42608
  "// 1) Read the entire target file(s) BEFORE making changes. Assume omitted lines must remain exactly as-is.",
42504
42609
  "// 2) Preserve unrelated content and formatting (indentation, EOLs, imports order, license headers, path/file references, and any other unrelated properties). Keep them AS IS.",
@@ -42520,12 +42625,30 @@ ${request}
42520
42625
 
42521
42626
  ${editContext}`;
42522
42627
  dbg("executeCode.prompt.head", enriched.slice(0, 1400));
42523
- const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
42524
- name: f3.originalName,
42525
- path: f3.pathHint,
42526
- mime: f3.mime || "text/plain",
42527
- data_base64: f3.content ? Buffer.from(f3.content, "utf8").toString("base64") : void 0
42528
- })).map((a) => a.data_base64 ? a : { ...a, data_base64: void 0 }) : [];
42628
+ const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? await (async () => {
42629
+ const fs58 = await import('fs/promises');
42630
+ const out = [];
42631
+ for (const f3 of opts.attachedFiles) {
42632
+ try {
42633
+ const name2 = f3.originalName;
42634
+ const p2 = f3.pathHint;
42635
+ const mime = f3.mime || "text/plain";
42636
+ let data_base64 = void 0;
42637
+ if (f3.content && f3.content.length > 0) {
42638
+ data_base64 = Buffer.from(f3.content, "utf8").toString("base64");
42639
+ } else if (p2) {
42640
+ try {
42641
+ const buf = await fs58.readFile(p2);
42642
+ data_base64 = buf.toString("base64");
42643
+ } catch {
42644
+ }
42645
+ }
42646
+ out.push({ name: name2, path: p2, mime, data_base64 });
42647
+ } catch {
42648
+ }
42649
+ }
42650
+ return out;
42651
+ })() : [];
42529
42652
  const pathAttachments = [];
42530
42653
  const attachedPathSet = /* @__PURE__ */ new Set();
42531
42654
  if (explicitFiles.length > 0) {
@@ -43340,7 +43463,7 @@ ${h2.head}`);
43340
43463
  "1) If the request references existing repository directory/file paths, prefer EDIT_EXISTING unless it explicitly asks to scaffold a new project.",
43341
43464
  "2) Phrases like 'fix', 'improve', 'update', 'change', 'patch', 'make it work', or 'by editing the existing files' imply EDIT_EXISTING.",
43342
43465
  "3) Phrases like create/new project/scaffold/from scratch/template imply CREATE_NEW.",
43343
- "4) Attachments or explicit file paths increase likelihood of EDIT_EXISTING.",
43466
+ "4) If the only referenced paths are documentation files (e.g., .md/.txt/.json/.yaml/.yml) or files under hidden planning folders (e.g., .maria/), do NOT treat that as evidence for EDIT_EXISTING; prefer CREATE_NEW unless explicitly asked to edit.",
43344
43467
  'Output MUST be EXACTLY this JSON object with no extra text/code blocks: { "intent": "EDIT_EXISTING" | "CREATE_NEW" }'
43345
43468
  ].join("\n");
43346
43469
  const evidence = {
@@ -43357,7 +43480,16 @@ ${h2.head}`);
43357
43480
  "Repo snapshot (trimmed):",
43358
43481
  headSnippets.join("\n\n")
43359
43482
  ].join("\n\n");
43360
- if (existingDirs.length > 0 || existingFiles.length > 0 || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0 || anyExistingPathMentioned) {
43483
+ const isDocPath = (p2) => {
43484
+ const lower2 = p2.toLowerCase();
43485
+ if (lower2.startsWith(".maria/")) return true;
43486
+ const ext2 = lower2.includes(".") ? lower2.slice(lower2.lastIndexOf(".")) : "";
43487
+ return [".md", ".markdown", ".txt", ".json", ".yaml", ".yml", ".xml"].includes(ext2);
43488
+ };
43489
+ const docExistingCount = existingFiles.filter(isDocPath).length;
43490
+ const codeExistingCount = existingFiles.length - docExistingCount;
43491
+ const explicitDocOnly = Array.isArray(ctx2.explicitFiles) && ctx2.explicitFiles.length > 0 && ctx2.explicitFiles.every(isDocPath);
43492
+ if (existingDirs.length > 0 || codeExistingCount > 0 || ctx2.attachmentsCount > 0 && !explicitDocOnly) {
43361
43493
  return true;
43362
43494
  }
43363
43495
  let startedLocalSpinner = false;
@@ -43388,12 +43520,19 @@ ${h2.head}`);
43388
43520
  if (m2) jsonText = m2[0];
43389
43521
  }
43390
43522
  const parsed = jsonText ? JSON.parse(jsonText) : {};
43391
- if (existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0) {
43392
- return true;
43393
- }
43523
+ if (existingDirs.length > 0 || codeExistingCount > 0) return true;
43524
+ if (explicitDocOnly) return false;
43394
43525
  return parsed?.intent === "EDIT_EXISTING";
43395
43526
  } catch {
43396
- return ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0 || existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned;
43527
+ const isDocPath = (p2) => {
43528
+ const lower2 = p2.toLowerCase();
43529
+ if (lower2.startsWith(".maria/")) return true;
43530
+ const ext2 = lower2.includes(".") ? lower2.slice(lower2.lastIndexOf(".")) : "";
43531
+ return [".md", ".markdown", ".txt", ".json", ".yaml", ".yml", ".xml"].includes(ext2);
43532
+ };
43533
+ const explicitDocOnly = Array.isArray(ctx2.explicitFiles) && ctx2.explicitFiles.length > 0 && ctx2.explicitFiles.every(isDocPath);
43534
+ if (explicitDocOnly) return false;
43535
+ return existingDirs.length > 0;
43397
43536
  }
43398
43537
  }
43399
43538
  function sanitizeFolderName(name2) {
@@ -43583,6 +43722,16 @@ async function resolveExplicitPaths(root, files, hintText) {
43583
43722
  const out = [];
43584
43723
  for (const desired of files) {
43585
43724
  const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
43725
+ try {
43726
+ const pathMod2 = await import('path');
43727
+ if (pathMod2.isAbsolute(normalized)) {
43728
+ const rel = pathMod2.relative(root, normalized).replace(/\\/g, "/");
43729
+ if (!rel || rel.startsWith("..")) {
43730
+ continue;
43731
+ }
43732
+ }
43733
+ } catch {
43734
+ }
43586
43735
  if (allFiles.includes(normalized)) {
43587
43736
  out.push(normalized);
43588
43737
  continue;
@@ -43802,7 +43951,28 @@ var init_code_command = __esm({
43802
43951
  if (opts.dryRun && !opts.previewLines) opts.previewLines = 50;
43803
43952
  const root = opts.root || process.cwd();
43804
43953
  const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
43805
- const attachments = await this.collectAttachedFiles(context2).catch(() => []);
43954
+ let attachments = await this.collectAttachedFiles(context2).catch(() => []);
43955
+ try {
43956
+ const { collectFileAttachmentsFromText: collectFileAttachmentsFromText2 } = await Promise.resolve().then(() => (init_attachment_utils(), attachment_utils_exports));
43957
+ const detected = await collectFileAttachmentsFromText2(request, process.cwd(), { maxBytes: 12 * 1024 * 1024 });
43958
+ if (Array.isArray(detected) && detected.length) {
43959
+ const seen = new Set(attachments.map((a) => (a.pathHint || a.originalName).toLowerCase()));
43960
+ for (const d of detected) {
43961
+ const key = String(d.path || d.name || "").toLowerCase();
43962
+ if (!key || seen.has(key)) continue;
43963
+ let content = "";
43964
+ if (d.data_base64) {
43965
+ try {
43966
+ content = Buffer.from(d.data_base64, "base64").toString("utf8");
43967
+ } catch {
43968
+ }
43969
+ }
43970
+ attachments.push({ originalName: d.name || key, pathHint: d.path, content, size: content ? Buffer.byteLength(content, "utf8") : 0, mime: d.mime });
43971
+ seen.add(key);
43972
+ }
43973
+ }
43974
+ } catch {
43975
+ }
43806
43976
  try {
43807
43977
  if (process.env.MARIA_DEBUG === "1") {
43808
43978
  const attView = attachments.map((a) => ({ name: a.originalName, size: a.size, mime: a.mime, pathHint: a.pathHint })).slice(0, 50);