@bonginkan/maria 4.3.26 → 4.3.28

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # MARIA - AI Development Platform v4.3.26
1
+ # MARIA - AI Development Platform v4.3.28
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@bonginkan/maria.svg)](https://www.npmjs.com/package/@bonginkan/maria)
4
4
  [![License](https://img.shields.io/badge/license-Multi--tier-blue.svg)](LICENSE)
@@ -10,7 +10,7 @@
10
10
 
11
11
  > **Enterprise-grade AI development platform with 100% command availability and comprehensive fallback support**
12
12
 
13
- ## 🚀 What's New in v4.3.26 (September 16, 2025)
13
+ ## 🚀 What's New in v4.3.28 (September 16, 2025)
14
14
 
15
15
  ### 🎯 Interactive Improvements & Choice Memory
16
16
  - **Choice Memory System**: Smart persistence of user selections across sessions
@@ -922,7 +922,7 @@ await secureWorkflow.executeWithAuth(workflowDefinition, securityContext);
922
922
  ### Quick Installation
923
923
  ```bash
924
924
  # Install globally (recommended)
925
- npm install -g @bonginkan/maria@4.3.26
925
+ npm install -g @bonginkan/maria@4.3.28
926
926
 
927
927
  # Verify installation
928
928
  maria --version # Should show v4.3.9
@@ -1126,7 +1126,7 @@ MARIA CODE is distributed under a comprehensive licensing system designed for in
1126
1126
 
1127
1127
  *MARIA v4.1.4 represents the pinnacle of multimodal AI development platform evolution - combining revolutionary voice-to-code capabilities, advanced memory systems, and comprehensive command ecosystems with enterprise-grade security and performance. This release establishes MARIA as the definitive choice for developers and Fortune 500 enterprises seeking intelligent, multimodal development experiences with GraphRAG intelligence, multilingual support, and zero-anxiety coding workflows.*
1128
1128
 
1129
- **Transform your development experience today**: `npm install -g @bonginkan/maria@4.3.26`
1129
+ **Transform your development experience today**: `npm install -g @bonginkan/maria@4.3.28`
1130
1130
 
1131
1131
  🌐 **Official Website**: [https://maria-code.ai](https://maria-code.ai)
1132
1132
  💬 **Community**: [https://discord.gg/SMSmSGcEQy](https://discord.gg/SMSmSGcEQy)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "lite-1.0.0",
3
- "generatedAt": "2025-09-25T02:54:50.028Z",
3
+ "generatedAt": "2025-09-26T05:40:48.488Z",
4
4
  "totalCommands": 16,
5
5
  "readyCount": 16,
6
6
  "partialCount": 0,
@@ -26066,8 +26066,8 @@ var require_package = __commonJS({
26066
26066
  "package.json"(exports, module) {
26067
26067
  module.exports = {
26068
26068
  name: "@bonginkan/maria",
26069
- version: "4.3.26",
26070
- description: "\u{1F680} MARIA v4.3.26 - 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.",
26069
+ version: "4.3.28",
26070
+ description: "\u{1F680} MARIA v4.3.28 - 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.",
26071
26071
  keywords: [
26072
26072
  "ai",
26073
26073
  "cli",
@@ -28099,7 +28099,7 @@ var init_AuthenticationManager = __esm({
28099
28099
  const response = await fetch(`${this.apiBase}/api/user/profile`, {
28100
28100
  headers: {
28101
28101
  "Authorization": `Bearer ${tokens2.accessToken}`,
28102
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.26"}`
28102
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.28"}`
28103
28103
  }
28104
28104
  });
28105
28105
  if (response.status === 401) {
@@ -28731,7 +28731,7 @@ async function callApi(path60, init3 = {}) {
28731
28731
  "Authorization": `Bearer ${token}`,
28732
28732
  "X-Device-Id": getDeviceId(),
28733
28733
  "X-Session-Id": getSessionId() || "",
28734
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.26"}`,
28734
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.28"}`,
28735
28735
  "Content-Type": init3.headers?.["Content-Type"] || "application/json"
28736
28736
  });
28737
28737
  const doFetch = async (token) => {
@@ -44443,7 +44443,7 @@ async function applyPlans(plans, opts) {
44443
44443
  try {
44444
44444
  for (const plan of plans) {
44445
44445
  if (opts.signal?.aborted) throw abortErr();
44446
- const target = path11__namespace.default.join(opts.root, plan.path);
44446
+ const target = plan.absPath ? plan.absPath : path11__namespace.default.join(opts.root, plan.path);
44447
44447
  const dir = path11__namespace.default.dirname(target);
44448
44448
  await fs21.promises.mkdir(dir, { recursive: true });
44449
44449
  const exists2 = await fileExists(target);
@@ -50625,7 +50625,7 @@ var init_about_command = __esm({
50625
50625
  async execute(args2, context2) {
50626
50626
  const output3 = [];
50627
50627
  output3.push("");
50628
- output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.26"));
50628
+ output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.28"));
50629
50629
  output3.push(chalk14__default.default.gray("\u2550".repeat(40)));
50630
50630
  output3.push("");
50631
50631
  output3.push(chalk14__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -54127,6 +54127,10 @@ async function normalizePlans(plans, opts) {
54127
54127
  const profile = await scanRepo(opts.root);
54128
54128
  const out = [];
54129
54129
  for (const fp of plans) {
54130
+ if (fp.noNormalize) {
54131
+ out.push(fp);
54132
+ continue;
54133
+ }
54130
54134
  const n = normalizePlanItem(fp, profile);
54131
54135
  if (!n.kind) n.kind = guessKindByPath(n.path);
54132
54136
  out.push(n);
@@ -54171,7 +54175,7 @@ async function validatePlan(plans, opts) {
54171
54175
  skipped.push(fp.path);
54172
54176
  continue;
54173
54177
  }
54174
- const full = path11__namespace.default.join(opts.root, rel);
54178
+ const full = fp.absPath ? fp.absPath : path11__namespace.default.join(opts.root, rel);
54175
54179
  if (!full.startsWith(path11__namespace.default.resolve(opts.root))) {
54176
54180
  warnings.push(`Outside root denied: ${fp.path}`);
54177
54181
  skipped.push(fp.path);
@@ -54302,10 +54306,10 @@ function formatPlan(summary, opts) {
54302
54306
  budget.diffLines = Math.min(budget.diffLines, 20);
54303
54307
  lines.push("", `Diff preview (truncated to ${budget.diffLines} lines per file):`);
54304
54308
  for (const f3 of summary.files) {
54305
- if (f3.action === "skip") continue;
54306
- const before = readCurrentFileSafe(opts.root, f3.path);
54309
+ if (f3.action !== "modify") continue;
54310
+ const before = readCurrentFileSafe(opts.root, f3.path, f3.absPath);
54307
54311
  const after = f3.preview || "";
54308
- const diff = buildUnifiedDiff(f3.path, before, after, budget);
54312
+ const diff = buildUnifiedDiff(f3.path, before, after, budget, f3.absPath);
54309
54313
  lines.push(diff, "");
54310
54314
  }
54311
54315
  }
@@ -54342,9 +54346,10 @@ function formatPlanAsDiff(files, opts) {
54342
54346
  let shownFiles = 0;
54343
54347
  for (const f3 of files) {
54344
54348
  if (budget.globalMaxFiles !== void 0 && shownFiles >= budget.globalMaxFiles) break;
54345
- const before = readCurrentFileSafe(opts.root, f3.path);
54349
+ if (f3.action !== "modify") continue;
54350
+ const before = readCurrentFileSafe(opts.root, f3.path, f3.absPath);
54346
54351
  const after = f3.preview || "";
54347
- const diff = buildUnifiedDiff(f3.path, before, after, budget);
54352
+ const diff = buildUnifiedDiff(f3.path, before, after, budget, f3.absPath);
54348
54353
  const diffBytes = Buffer.byteLength(diff, "utf8");
54349
54354
  if (budget.globalMaxBytes !== void 0 && bytesUsed + diffBytes > budget.globalMaxBytes && shownFiles > 0) {
54350
54355
  lines.push(`
@@ -54361,11 +54366,11 @@ function formatPlanAsDiff(files, opts) {
54361
54366
  }
54362
54367
  return lines.join("\n");
54363
54368
  }
54364
- function readCurrentFileSafe(root, rel) {
54365
- if (!root) return "";
54369
+ function readCurrentFileSafe(root, rel, abs) {
54370
+ if (!root && !abs) return "";
54366
54371
  try {
54367
54372
  const fs49 = __require("fs");
54368
- const p = __require("path").join(root, rel);
54373
+ const p = abs ? abs : __require("path").join(root, rel);
54369
54374
  return fs49.existsSync(p) ? fs49.readFileSync(p, "utf8") : "";
54370
54375
  } catch {
54371
54376
  return "";
@@ -54382,7 +54387,7 @@ function normalizeDiffBudget(b) {
54382
54387
  globalMaxFiles: Number.isFinite(b?.globalMaxFiles) ? b.globalMaxFiles : envGlobalFiles
54383
54388
  };
54384
54389
  }
54385
- function buildUnifiedDiff(relPath, before, after, b) {
54390
+ function buildUnifiedDiff(relPath, before, after, b, abs) {
54386
54391
  const beforeLines = before.split(/\r?\n/);
54387
54392
  const afterLines = after.split(/\r?\n/);
54388
54393
  let i2 = 0;
@@ -54391,14 +54396,15 @@ function buildUnifiedDiff(relPath, before, after, b) {
54391
54396
  while (j < beforeLines.length - i2 && j < afterLines.length - i2 && beforeLines[beforeLines.length - 1 - j] === afterLines[afterLines.length - 1 - j]) j++;
54392
54397
  const oldMid = beforeLines.slice(i2, beforeLines.length - j);
54393
54398
  const newMid = afterLines.slice(i2, afterLines.length - j);
54394
- const header = [`--- a/${relPath}`, `+++ b/${relPath}`];
54399
+ const headerPath = abs ? abs : relPath;
54400
+ const header = [`--- ${headerPath}`, `+++ ${headerPath}`];
54395
54401
  const body = [];
54396
54402
  const ctxPrefix = Math.max(0, i2 - 3);
54397
54403
  Math.min(beforeLines.length, beforeLines.length - j + 3);
54398
54404
  const preCtx = beforeLines.slice(ctxPrefix, i2).map((l) => ` ${l}`);
54399
54405
  const postCtx = beforeLines.slice(beforeLines.length - j, Math.min(beforeLines.length - j + 3, beforeLines.length)).map((l) => ` ${l}`);
54400
- const del = oldMid.map((l) => `-${l}`);
54401
- const add = newMid.map((l) => `+${l}`);
54406
+ const del = oldMid.map((l) => colorRed(`-${l}`));
54407
+ const add = newMid.map((l) => colorGreen(`+${l}`));
54402
54408
  body.push(...preCtx);
54403
54409
  body.push(...del);
54404
54410
  body.push(...add);
@@ -54415,6 +54421,22 @@ function buildUnifiedDiff(relPath, before, after, b) {
54415
54421
  }
54416
54422
  return out;
54417
54423
  }
54424
+ function colorGreen(s2) {
54425
+ try {
54426
+ const chalk44 = __require("chalk");
54427
+ return chalk44.green(s2);
54428
+ } catch {
54429
+ return s2;
54430
+ }
54431
+ }
54432
+ function colorRed(s2) {
54433
+ try {
54434
+ const chalk44 = __require("chalk");
54435
+ return chalk44.red(s2);
54436
+ } catch {
54437
+ return s2;
54438
+ }
54439
+ }
54418
54440
  function languageLabel(lang, filePath) {
54419
54441
  if (lang) {
54420
54442
  const l = lang.toLowerCase();
@@ -55041,6 +55063,20 @@ var init_policy = __esm({
55041
55063
  }
55042
55064
  });
55043
55065
 
55066
+ // src/utils/esm-compat.ts
55067
+ var esm_compat_exports = {};
55068
+ __export(esm_compat_exports, {
55069
+ loadGlobby: () => loadGlobby
55070
+ });
55071
+ async function loadGlobby() {
55072
+ const mod = await import('globby');
55073
+ return mod?.globby ?? mod?.default ?? mod;
55074
+ }
55075
+ var init_esm_compat = __esm({
55076
+ "src/utils/esm-compat.ts"() {
55077
+ }
55078
+ });
55079
+
55044
55080
  // src/services/code-orchestrator/Orchestrator.ts
55045
55081
  var Orchestrator_exports = {};
55046
55082
  __export(Orchestrator_exports, {
@@ -55075,6 +55111,20 @@ async function orchestrate(request, opts) {
55075
55111
  const initial = [];
55076
55112
  const fallbackNotices = [];
55077
55113
  const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
55114
+ const explicitFilesRaw = parseExplicitFilenames(request);
55115
+ const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
55116
+ const explicitAbsMap = /* @__PURE__ */ Object.create(null);
55117
+ if (explicitFiles.length > 0) {
55118
+ const pathMod = await import('path');
55119
+ for (const rel of explicitFiles) {
55120
+ explicitAbsMap[rel] = pathMod.join(opts.root, rel);
55121
+ }
55122
+ }
55123
+ const isEditIntent = detectEditIntent(request, {
55124
+ hasAttachments: !!(opts.attachedFiles && opts.attachedFiles.length > 0),
55125
+ explicitFilesCount: explicitFiles.length
55126
+ });
55127
+ const editContext = isEditIntent && explicitFiles.length > 0 ? await buildEditContext(opts.root, explicitFiles, 200, 512 * 1024) : "";
55078
55128
  if (opts.attachedFiles && opts.attachedFiles.length > 0) {
55079
55129
  const mapRes = await mapAttachmentsToTargets(opts.attachedFiles, {
55080
55130
  root: opts.root,
@@ -55094,7 +55144,6 @@ async function orchestrate(request, opts) {
55094
55144
  }
55095
55145
  }
55096
55146
  const onlyAttached = !!opts.flags.onlyAttached;
55097
- const explicitFiles = parseExplicitFilenames(request);
55098
55147
  if (!onlyAttached) {
55099
55148
  let codeOutput = "";
55100
55149
  if (process.env.MARIA_E2E_FAKE_CODE === "1") {
@@ -55110,12 +55159,21 @@ async function orchestrate(request, opts) {
55110
55159
  "At the very start of each file, include a filename hint as a comment on the first line:",
55111
55160
  "// filename: <name.ext> (or # filename: <name.ext> for Python, <!-- filename: name.ext --> for HTML/CSS)",
55112
55161
  "If multiple files are required, use the strict multi-file protocol with one or more file sections:",
55162
+ "Make sure you place every file in a structured folders, with the top level folder being '{project_name: proper project name per request}'.",
55113
55163
  "[BEGIN file: path]\n<content>\n[END]",
55114
55164
  "Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
55115
55165
  ].join("\n");
55166
+ const requestPreamble = isEditIntent ? [
55167
+ "// EDIT MODE: modify existing files, preserve unrelated content.",
55168
+ "// Follow existing structure and only touch requested files.",
55169
+ editContext ? "// Current file snapshots provided below." : ""
55170
+ ].filter(Boolean).join("\n") : "";
55116
55171
  const enriched = `${FILE_FORMAT_INSTRUCTIONS}
55117
55172
 
55118
- ${request}`;
55173
+ ${requestPreamble}
55174
+ ${request}
55175
+
55176
+ ${editContext}`;
55119
55177
  const response = await executeCode(enriched);
55120
55178
  const raw = (response.output || response?.data?.content || "").trim();
55121
55179
  if (!raw) {
@@ -55160,24 +55218,27 @@ ${request}`;
55160
55218
  const htmlIdx = blocks.findIndex((b) => /html/i.test(b.language));
55161
55219
  const htmlFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".html"));
55162
55220
  if (htmlIdx >= 0 && htmlFile) {
55163
- initial.push({ path: htmlFile, kind: "source", action: "create", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
55221
+ initial.push({ path: htmlFile, absPath: explicitAbsMap[htmlFile], noNormalize: true, kind: "source", action: "create", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
55164
55222
  mapped.add(htmlFile);
55165
55223
  }
55166
55224
  const jsIdx = blocks.findIndex((b) => /(ts|tsx|jsx|javascript|js)/i.test(b.language));
55167
55225
  const jsFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".js"));
55168
55226
  if (jsIdx >= 0 && jsFile && !mapped.has(jsFile)) {
55169
- initial.push({ path: jsFile, kind: "source", action: "create", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
55227
+ initial.push({ path: jsFile, absPath: explicitAbsMap[jsFile], noNormalize: true, kind: "source", action: "create", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
55170
55228
  mapped.add(jsFile);
55171
55229
  }
55172
55230
  const cssIdx = blocks.findIndex((b) => /css/i.test(b.language));
55173
55231
  const cssFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".css"));
55174
55232
  if (cssIdx >= 0 && cssFile && !mapped.has(cssFile)) {
55175
- initial.push({ path: cssFile, kind: "source", action: "create", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
55233
+ initial.push({ path: cssFile, absPath: explicitAbsMap[cssFile], noNormalize: true, kind: "source", action: "create", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
55176
55234
  mapped.add(cssFile);
55177
55235
  }
55178
55236
  for (const f3 of explicitFiles) {
55179
55237
  if (mapped.has(f3)) continue;
55180
- initial.push(scaffoldForFilename(f3, explicitFiles));
55238
+ const plan = scaffoldForFilename(f3, explicitFiles);
55239
+ plan.absPath = explicitAbsMap[f3];
55240
+ plan.noNormalize = true;
55241
+ initial.push(plan);
55181
55242
  }
55182
55243
  } else {
55183
55244
  for (let i2 = 0; i2 < blocks.length; i2++) {
@@ -55195,12 +55256,26 @@ ${request}`;
55195
55256
  }
55196
55257
  }
55197
55258
  }
55259
+ if (!isEditIntent) {
55260
+ const proposedTop = deriveProjectFolderName(request);
55261
+ const { folderName, detectedTop } = await ensureTopFolder(opts.root, proposedTop, initial);
55262
+ if (folderName) {
55263
+ for (const p of initial) {
55264
+ if (!startsWithTopFolder(p.path, detectedTop || folderName)) {
55265
+ p.path = prefixWithTopFolder(p.path, folderName);
55266
+ }
55267
+ }
55268
+ }
55269
+ }
55198
55270
  if (explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
55199
55271
  for (const f3 of explicitFiles) {
55200
55272
  initial.push(scaffoldForFilename(f3, explicitFiles));
55201
55273
  }
55202
55274
  }
55203
- const normalized = await normalizePlans(initial, { root: opts.root });
55275
+ const normalized = await normalizePlans(
55276
+ initial.map((p) => p.noNormalize ? p : p),
55277
+ { root: opts.root }
55278
+ );
55204
55279
  try {
55205
55280
  const [{ access: access18 }, path60] = await Promise.all([
55206
55281
  import('fs/promises'),
@@ -55208,8 +55283,12 @@ ${request}`;
55208
55283
  ]);
55209
55284
  for (const p of normalized) {
55210
55285
  try {
55211
- await access18(path60.join(opts.root, p.path));
55286
+ const absCandidate = p.absPath ? p.absPath : path60.join(opts.root, p.path);
55287
+ await access18(absCandidate);
55212
55288
  p.action = "modify";
55289
+ if (isEditIntent) {
55290
+ p.overwritePolicy = "allow";
55291
+ }
55213
55292
  } catch {
55214
55293
  p.action = "create";
55215
55294
  }
@@ -55217,10 +55296,12 @@ ${request}`;
55217
55296
  } catch {
55218
55297
  }
55219
55298
  const validated = await validatePlan(normalized, { root: opts.root, profile, flags: { maxFiles: opts.flags.maxFiles, yes: opts.flags.yes, interactive: !!opts.flags.interactive, ...opts.flags } });
55220
- const outputMode = resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
55221
- const displayFiles = validated.files.concat(
55222
- (validated.skipped || []).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }))
55223
- );
55299
+ const hasAnyModify = validated.files.some((f3) => f3.action === "modify") || isEditIntent;
55300
+ const outputMode = !opts.flags.hideCode && hasAnyModify ? "diff" : resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
55301
+ const skippedSetForLookup = new Set(validated.skipped || []);
55302
+ const skippedPlans = normalized.filter((f3) => skippedSetForLookup.has(f3.path));
55303
+ const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
55304
+ const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
55224
55305
  const summary = summarizePlan(displayFiles);
55225
55306
  const lines = [
55226
55307
  formatPlan(summary, {
@@ -55258,6 +55339,7 @@ ${request}`;
55258
55339
  if (softIssues.hasTrailingWhitespace) lines.push(warnLine("Proposed changes contain trailing whitespace"));
55259
55340
  if (softIssues.hasConflictMarkers) lines.push(warnLine("Proposed changes contain conflict markers"));
55260
55341
  }
55342
+ const preApplyOutput = withNotices(lines);
55261
55343
  let appliedCount = 0;
55262
55344
  let durationMs = 0;
55263
55345
  let rolledBack = false;
@@ -55269,7 +55351,7 @@ ${request}`;
55269
55351
  return { plan: normalized, validated, summaryLines: withNotices([errorLine("working tree not clean (commit or stash first). Re-run after cleaning your git status.")]) };
55270
55352
  }
55271
55353
  }
55272
- const allowOverwrite = opts.flags.overwriteAllowed === true || !!opts.flags.yes;
55354
+ const allowOverwrite = opts.flags.overwriteAllowed === true || !!opts.flags.yes || isEditIntent;
55273
55355
  const applyRes = await applyPlans(approved, { root: opts.root, overwriteAllowed: allowOverwrite, rollback: opts.flags.rollback !== false, signal: opts.abortSignal, onProgress: (w, t2) => {
55274
55356
  }, eol: profile.eol });
55275
55357
  appliedCount = applyRes.appliedCount;
@@ -55299,7 +55381,7 @@ ${request}`;
55299
55381
  const savedList = [].concat(applyRes.created, applyRes.modified);
55300
55382
  const savedAbs = savedList.map((rel) => path11__namespace.default.resolve(opts.root, rel));
55301
55383
  const footer = savedAbs.length > 0 ? ["Saved files (full paths):", ...savedAbs.map((p) => `- ${p}`)] : [];
55302
- return { plan: normalized, validated, applied: { count: appliedCount, durationMs, rolledBack }, summaryLines: withNotices([msg, ...footer]) };
55384
+ return { plan: normalized, validated, applied: { count: appliedCount, durationMs, rolledBack }, summaryLines: [...preApplyOutput, "", msg, ...footer] };
55303
55385
  } catch (e2) {
55304
55386
  if (e2?.name === "AbortError") {
55305
55387
  await journalResume(opts.root, request, validated.files);
@@ -55520,6 +55602,218 @@ function parseExplicitFilenames(request) {
55520
55602
  }
55521
55603
  return out;
55522
55604
  }
55605
+ function detectEditIntent(request, ctx2) {
55606
+ const r2 = request.toLowerCase();
55607
+ const editKeywords = ["modify", "edit", "update", "fix", "refactor", "change", "patch", "\u5DEE\u5206", "\u4FEE\u6B63", "\u5909\u66F4", "\u65E2\u5B58", "\u8FFD\u8A18"];
55608
+ const mentionsEdit = editKeywords.some((k) => r2.includes(k));
55609
+ return ctx2.hasAttachments || ctx2.explicitFilesCount > 0 || mentionsEdit;
55610
+ }
55611
+ function sanitizeFolderName(name2) {
55612
+ const base = name2.toLowerCase().replace(/[`~!@#$%^&*()+=\[\]{}|;:'",<>/?\\]/g, " ").replace(/\s+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
55613
+ return base || "project";
55614
+ }
55615
+ function deriveProjectFolderName(request) {
55616
+ const words = request.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2).slice(0, 4).join("-");
55617
+ return sanitizeFolderName(words || "project");
55618
+ }
55619
+ function startsWithTopFolder(p, folder) {
55620
+ if (!folder) return false;
55621
+ const seg = p.replace(/^\/+/, "").split("/")[0];
55622
+ return seg.toLowerCase() === folder.toLowerCase();
55623
+ }
55624
+ function prefixWithTopFolder(p, folder) {
55625
+ const rel = p.replace(/^\/+/, "");
55626
+ return `${folder}/${rel}`;
55627
+ }
55628
+ async function ensureTopFolder(root, proposed, plans) {
55629
+ const tops = /* @__PURE__ */ new Set();
55630
+ for (const p of plans) {
55631
+ const seg = p.path.replace(/^\/+/, "").split("/")[0] || "";
55632
+ if (seg) tops.add(seg);
55633
+ }
55634
+ if (tops.size === 1) {
55635
+ const only = Array.from(tops)[0];
55636
+ const unique2 = await ensureUniqueFolder(root, only);
55637
+ return { folderName: unique2, detectedTop: only };
55638
+ }
55639
+ const unique = await ensureUniqueFolder(root, proposed);
55640
+ return { folderName: unique };
55641
+ }
55642
+ async function ensureUniqueFolder(root, base) {
55643
+ const fs49 = await import('fs/promises');
55644
+ const pathMod = await import('path');
55645
+ let name2 = sanitizeFolderName(base);
55646
+ let suffix = 0;
55647
+ for (; suffix < Number.MAX_SAFE_INTEGER; ) {
55648
+ const candidate = suffix === 0 ? name2 : `${name2}-${String(suffix).padStart(2, "0")}`;
55649
+ try {
55650
+ await fs49.access(pathMod.join(root, candidate));
55651
+ suffix += 1;
55652
+ } catch {
55653
+ return candidate;
55654
+ }
55655
+ }
55656
+ throw new Error("ensureUniqueFolder: exhausted attempts to find a unique folder name");
55657
+ }
55658
+ async function buildEditContext(root, files, maxLines, maxBytes) {
55659
+ try {
55660
+ const fs49 = await import('fs/promises');
55661
+ const pathMod = await import('path');
55662
+ const sections = [];
55663
+ for (const rel of files) {
55664
+ const full = pathMod.join(root, rel);
55665
+ try {
55666
+ const buf = await fs49.readFile(full);
55667
+ const clipped = buf.length > maxBytes ? buf.subarray(0, maxBytes) : buf;
55668
+ const text = clipped.toString("utf8").replace(/\r\n/g, "\n");
55669
+ const lines = text.split("\n").slice(0, maxLines).join("\n");
55670
+ sections.push(`[BEGIN file: ${rel}]
55671
+ ${lines}
55672
+ [END]`);
55673
+ } catch {
55674
+ }
55675
+ }
55676
+ if (sections.length === 0) return "";
55677
+ return ["// Current repository files (read-only context):", ...sections].join("\n");
55678
+ } catch {
55679
+ return "";
55680
+ }
55681
+ }
55682
+ async function resolveExplicitPaths(root, files, hintText) {
55683
+ const fs49 = await import('fs/promises');
55684
+ const pathMod = await import('path');
55685
+ const { loadGlobby: loadGlobby2 } = await Promise.resolve().then(() => (init_esm_compat(), esm_compat_exports));
55686
+ const globby = await loadGlobby2();
55687
+ const ignore = [
55688
+ "**/node_modules/**",
55689
+ "**/.git/**",
55690
+ "**/dist/**",
55691
+ "**/build/**",
55692
+ "**/.maria/**",
55693
+ "**/.next/**",
55694
+ "**/coverage/**"
55695
+ ];
55696
+ const hintTokens = Array.from(new Set(hintText.toLowerCase().replace(/[^a-z0-9_/.-]+/g, " ").split(/\s+/).filter(Boolean)));
55697
+ async function findBest(rel) {
55698
+ const normalized = rel.replace(/^\/+/, "").replace(/\\/g, "/");
55699
+ const fullExact = pathMod.join(root, normalized);
55700
+ try {
55701
+ await fs49.access(fullExact);
55702
+ return normalized;
55703
+ } catch {
55704
+ }
55705
+ const lowerRel = normalized.toLowerCase();
55706
+ const ext2 = (pathMod.extname(normalized) || "").toLowerCase();
55707
+ const base = pathMod.basename(normalized);
55708
+ const nameNoExt = base.replace(/\.[^.]+$/, "").toLowerCase();
55709
+ const parentPath = pathMod.dirname(normalized);
55710
+ const parent = parentPath.split("/").pop() || "";
55711
+ const dirParts = parentPath === "." ? [] : parentPath.split("/").filter(Boolean).map((s2) => s2.toLowerCase());
55712
+ const patterns = [];
55713
+ patterns.push(`**/${normalized}`);
55714
+ if (parent && parent !== "." && parent !== "/") patterns.push(`**/${parent}/${base}`);
55715
+ if (base) patterns.push(`**/${base}`);
55716
+ patterns.push(`**/*${base}`);
55717
+ if (!ext2) {
55718
+ patterns.push(`**/${nameNoExt}.*`);
55719
+ }
55720
+ const uniqPatterns = Array.from(new Set(patterns));
55721
+ const candidatesSet = /* @__PURE__ */ new Set();
55722
+ for (const pat of uniqPatterns) {
55723
+ const found = await globby(pat, { cwd: root, absolute: false, gitignore: true, ignore });
55724
+ for (const f3 of found) {
55725
+ candidatesSet.add(f3.replace(/\\/g, "/"));
55726
+ }
55727
+ if (candidatesSet.size > 200) break;
55728
+ }
55729
+ let candidates = Array.from(candidatesSet);
55730
+ if (dirParts.length > 0) {
55731
+ const filtered = candidates.filter((relp) => {
55732
+ const segs = relp.toLowerCase().split("/");
55733
+ let pos = -1;
55734
+ for (const part of dirParts) {
55735
+ const next = segs.indexOf(part, pos + 1);
55736
+ if (next === -1) return false;
55737
+ pos = next;
55738
+ }
55739
+ return true;
55740
+ });
55741
+ if (filtered.length > 0) candidates = filtered;
55742
+ }
55743
+ if (candidates.length === 0) {
55744
+ const prefixes = ["", "src/", "app/", "pages/"];
55745
+ for (const pre of prefixes) {
55746
+ const cand = pathMod.join(root, pre + normalized);
55747
+ try {
55748
+ await fs49.access(cand);
55749
+ return (pre + normalized).replace(/^\/+/, "");
55750
+ } catch {
55751
+ }
55752
+ }
55753
+ if (dirParts.length > 0) {
55754
+ if (/^(src|app|pages)\//i.test(normalized)) return normalized;
55755
+ const pref = await pickExistingFolderPrefix(root, parentPath);
55756
+ const combined = (pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1");
55757
+ return combined;
55758
+ }
55759
+ return normalized.replace(/^(src\/)src\//i, "$1");
55760
+ }
55761
+ function score(relPath) {
55762
+ const lower2 = relPath.toLowerCase();
55763
+ let s2 = 0;
55764
+ if (lower2.endsWith(lowerRel)) s2 += 80;
55765
+ if (lower2.split("/").pop() === base.toLowerCase()) s2 += 40;
55766
+ if (ext2 && lower2.endsWith(ext2)) s2 += 10;
55767
+ if (lower2.startsWith("src/")) s2 += 18;
55768
+ if (parent && lower2.includes(`/${parent.toLowerCase()}/`)) s2 += 15;
55769
+ if (parentPath && lower2.endsWith(`/${parentPath.toLowerCase()}/${base.toLowerCase()}`)) s2 += 40;
55770
+ if (dirParts.length > 0) {
55771
+ for (const part of dirParts) {
55772
+ if (lower2.includes(`/${part}/`)) s2 += 20;
55773
+ else s2 -= 120;
55774
+ }
55775
+ }
55776
+ for (const t2 of hintTokens) {
55777
+ if (t2.length >= 3 && lower2.includes(`/${t2}/`)) {
55778
+ s2 += 2;
55779
+ }
55780
+ }
55781
+ s2 -= Math.min(10, Math.floor(relPath.length / 80));
55782
+ return s2;
55783
+ }
55784
+ let best = candidates[0];
55785
+ let bestScore = score(best);
55786
+ for (let i2 = 1; i2 < candidates.length; i2++) {
55787
+ const c = candidates[i2];
55788
+ const sc = score(c);
55789
+ if (sc > bestScore) {
55790
+ best = c;
55791
+ bestScore = sc;
55792
+ }
55793
+ }
55794
+ return best.replace(/^\/+/, "");
55795
+ }
55796
+ const out = [];
55797
+ for (const f3 of files) {
55798
+ out.push(await findBest(f3));
55799
+ }
55800
+ return out;
55801
+ }
55802
+ async function pickExistingFolderPrefix(root, parentPath) {
55803
+ const fs49 = await import('fs/promises');
55804
+ const pathMod = await import('path');
55805
+ const parts = parentPath.replace(/^\/+/, "").split("/").filter(Boolean);
55806
+ const prefixes = ["src", "app", "pages", ""];
55807
+ for (const pre of prefixes) {
55808
+ const test = pre ? pathMod.join(root, pre, ...parts) : pathMod.join(root, ...parts);
55809
+ try {
55810
+ await fs49.access(test);
55811
+ return pre ? `${pre}/` : "";
55812
+ } catch {
55813
+ }
55814
+ }
55815
+ return "src/";
55816
+ }
55523
55817
  function scaffoldForFilename(filename, all) {
55524
55818
  const lower2 = filename.toLowerCase();
55525
55819
  if (lower2.endsWith(".html")) {
@@ -56494,16 +56788,6 @@ var init_resume_command = __esm({
56494
56788
  }
56495
56789
  });
56496
56790
 
56497
- // src/utils/esm-compat.ts
56498
- async function loadGlobby() {
56499
- const mod = await import('globby');
56500
- return mod?.globby ?? mod?.default ?? mod;
56501
- }
56502
- var init_esm_compat = __esm({
56503
- "src/utils/esm-compat.ts"() {
56504
- }
56505
- });
56506
-
56507
56791
  // src/services/init/scanner.ts
56508
56792
  var scanner_exports = {};
56509
56793
  __export(scanner_exports, {
@@ -72891,7 +73175,7 @@ var init_ai_response_service = __esm({
72891
73175
  */
72892
73176
  async callLLM(prompt, opts = {}) {
72893
73177
  const {
72894
- 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.",
73178
+ 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 named Maria. Always respond in English. Provide direct, production-quality answers. Make sure you answer in plain text, as a natural chat.",
72895
73179
  model = void 0,
72896
73180
  provider = DEFAULT_PROVIDER2,
72897
73181
  temperature = 0.2,