@bonginkan/maria 4.3.38 → 4.3.39

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.
@@ -235,13 +235,13 @@ function getPackageJson() {
235
235
  )
236
236
  ];
237
237
  let packageJsonPath = null;
238
- for (const path64 of possiblePaths) {
239
- if (fs21.existsSync(path64)) {
238
+ for (const path65 of possiblePaths) {
239
+ if (fs21.existsSync(path65)) {
240
240
  try {
241
- const content = fs21.readFileSync(path64, "utf-8");
241
+ const content = fs21.readFileSync(path65, "utf-8");
242
242
  const parsed = JSON.parse(content);
243
243
  if (parsed.name === "@bonginkan/maria") {
244
- packageJsonPath = path64;
244
+ packageJsonPath = path65;
245
245
  break;
246
246
  }
247
247
  } catch {
@@ -5314,22 +5314,22 @@ var init_from = __esm({
5314
5314
  init_file();
5315
5315
  init_fetch_blob();
5316
5316
  ({ stat } = fs21.promises);
5317
- blobFromSync = (path64, type) => fromBlob(fs21.statSync(path64), path64, type);
5318
- blobFrom = (path64, type) => stat(path64).then((stat13) => fromBlob(stat13, path64, type));
5319
- fileFrom = (path64, type) => stat(path64).then((stat13) => fromFile(stat13, path64, type));
5320
- fileFromSync = (path64, type) => fromFile(fs21.statSync(path64), path64, type);
5321
- fromBlob = (stat13, path64, type = "") => new fetch_blob_default([new BlobDataItem({
5322
- path: path64,
5317
+ blobFromSync = (path65, type) => fromBlob(fs21.statSync(path65), path65, type);
5318
+ blobFrom = (path65, type) => stat(path65).then((stat13) => fromBlob(stat13, path65, type));
5319
+ fileFrom = (path65, type) => stat(path65).then((stat13) => fromFile(stat13, path65, type));
5320
+ fileFromSync = (path65, type) => fromFile(fs21.statSync(path65), path65, type);
5321
+ fromBlob = (stat13, path65, type = "") => new fetch_blob_default([new BlobDataItem({
5322
+ path: path65,
5323
5323
  size: stat13.size,
5324
5324
  lastModified: stat13.mtimeMs,
5325
5325
  start: 0
5326
5326
  })], { type });
5327
- fromFile = (stat13, path64, type = "") => new file_default([new BlobDataItem({
5328
- path: path64,
5327
+ fromFile = (stat13, path65, type = "") => new file_default([new BlobDataItem({
5328
+ path: path65,
5329
5329
  size: stat13.size,
5330
5330
  lastModified: stat13.mtimeMs,
5331
5331
  start: 0
5332
- })], path11.basename(path64), { type, lastModified: stat13.mtimeMs });
5332
+ })], path11.basename(path65), { type, lastModified: stat13.mtimeMs });
5333
5333
  BlobDataItem = class _BlobDataItem {
5334
5334
  #path;
5335
5335
  #start;
@@ -9563,12 +9563,12 @@ ${this.toYamlLike(value, indent + 1)}`;
9563
9563
  }
9564
9564
  static async loadFromFile(configPath) {
9565
9565
  const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
9566
- const fs51 = await importNodeBuiltin2("fs");
9566
+ const fs52 = await importNodeBuiltin2("fs");
9567
9567
  const _path = await importNodeBuiltin2("_path");
9568
9568
  const os23 = await importNodeBuiltin2("os");
9569
9569
  const targetPath = configPath || _path.join(os23.homedir(), ".maria", "config.json");
9570
9570
  try {
9571
- const data = await fs51.promises.readFile(targetPath, "utf-8");
9571
+ const data = await fs52.promises.readFile(targetPath, "utf-8");
9572
9572
  return JSON.parse(data);
9573
9573
  } catch (innerError) {
9574
9574
  if (innerError?.code === "ENOENT") {
@@ -9582,25 +9582,25 @@ ${this.toYamlLike(value, indent + 1)}`;
9582
9582
  }
9583
9583
  async save(configPath, options) {
9584
9584
  const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
9585
- const fs51 = await importNodeBuiltin2("fs");
9585
+ const fs52 = await importNodeBuiltin2("fs");
9586
9586
  const _path = await importNodeBuiltin2("_path");
9587
9587
  const os23 = await importNodeBuiltin2("os");
9588
9588
  const targetPath = configPath || _path.join(os23.homedir(), ".maria", "config.json");
9589
9589
  try {
9590
9590
  if (options?.backup) {
9591
9591
  try {
9592
- await fs51.promises.access(targetPath);
9592
+ await fs52.promises.access(targetPath);
9593
9593
  const backupPath = `${targetPath}.backup.${Date.now()}`;
9594
- await fs51.promises.copyFile(targetPath, backupPath);
9594
+ await fs52.promises.copyFile(targetPath, backupPath);
9595
9595
  } catch {
9596
9596
  }
9597
9597
  }
9598
- await fs51.promises.mkdir(_path.dirname(targetPath), { recursive: true });
9598
+ await fs52.promises.mkdir(_path.dirname(targetPath), { recursive: true });
9599
9599
  const dataToSave = this.getAll({
9600
9600
  maskSensitive: options?.maskSensitive ?? true,
9601
9601
  includeSourceMap: options?.includeSourceMap ?? false
9602
9602
  });
9603
- await fs51.promises.writeFile(
9603
+ await fs52.promises.writeFile(
9604
9604
  targetPath,
9605
9605
  JSON.stringify(dataToSave, null, 2),
9606
9606
  { mode: 384 }
@@ -9644,12 +9644,12 @@ ${this.toYamlLike(value, indent + 1)}`;
9644
9644
  }
9645
9645
  if (outputPath) {
9646
9646
  const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
9647
- const fs51 = await importNodeBuiltin2("fs");
9647
+ const fs52 = await importNodeBuiltin2("fs");
9648
9648
  const _path = await importNodeBuiltin2(
9649
9649
  "_path"
9650
9650
  );
9651
- await fs51.promises.mkdir(_path.dirname(outputPath), { recursive: true });
9652
- await fs51.promises.writeFile(outputPath, content, "utf-8");
9651
+ await fs52.promises.mkdir(_path.dirname(outputPath), { recursive: true });
9652
+ await fs52.promises.writeFile(outputPath, content, "utf-8");
9653
9653
  console.log(`\u2705 Configuration exported to ${outputPath}`);
9654
9654
  }
9655
9655
  return content;
@@ -9958,13 +9958,13 @@ async function loadEnvironmentConfig() {
9958
9958
  }
9959
9959
  try {
9960
9960
  const { importNodeBuiltin: importNodeBuiltin2, safeDynamicImport: safeDynamicImport2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
9961
- const fs51 = await safeDynamicImport2("fs-extra").catch(
9961
+ const fs52 = await safeDynamicImport2("fs-extra").catch(
9962
9962
  () => importNodeBuiltin2("fs")
9963
9963
  );
9964
9964
  const _path = await importNodeBuiltin2("_path");
9965
9965
  const _envPath = _path.join(process.cwd(), ".env.local");
9966
- if (await fs51.pathExists(_envPath)) {
9967
- const _envContent = await fs51.readFile(_envPath, "utf-8");
9966
+ if (await fs52.pathExists(_envPath)) {
9967
+ const _envContent = await fs52.readFile(_envPath, "utf-8");
9968
9968
  console.log("Loading environment from:", _envPath);
9969
9969
  environmentLoaded = true;
9970
9970
  const _lines = _envContent.split("\n");
@@ -19536,8 +19536,8 @@ var init_ConfigService = __esm({
19536
19536
  /**
19537
19537
  * ネストされた設定値の取得
19538
19538
  */
19539
- getNestedValue(path64) {
19540
- const keys = path64.split(".");
19539
+ getNestedValue(path65) {
19540
+ const keys = path65.split(".");
19541
19541
  let value = this._config;
19542
19542
  for (const key of keys) {
19543
19543
  if (value && typeof value === "object" && key in value) {
@@ -19567,8 +19567,8 @@ var init_ConfigService = __esm({
19567
19567
  /**
19568
19568
  * ネストされた設定値の更新
19569
19569
  */
19570
- async setNestedValue(path64, value) {
19571
- const keys = path64.split(".");
19570
+ async setNestedValue(path65, value) {
19571
+ const keys = path65.split(".");
19572
19572
  const lastKey = keys.pop();
19573
19573
  let target = this._config;
19574
19574
  for (const key of keys) {
@@ -19581,7 +19581,7 @@ var init_ConfigService = __esm({
19581
19581
  target[lastKey] = value;
19582
19582
  this.validateConfig();
19583
19583
  this.emitChange({
19584
- path: path64,
19584
+ path: path65,
19585
19585
  oldValue,
19586
19586
  newValue: value,
19587
19587
  timestamp: /* @__PURE__ */ new Date()
@@ -19626,8 +19626,8 @@ var init_ConfigService = __esm({
19626
19626
  setupAutoSave() {
19627
19627
  process.on("exit", () => {
19628
19628
  if (this._isDirty) {
19629
- const fs51 = __require("fs");
19630
- fs51.writeFileSync(
19629
+ const fs52 = __require("fs");
19630
+ fs52.writeFileSync(
19631
19631
  this._userConfigPath,
19632
19632
  JSON.stringify(this._config, null, 2),
19633
19633
  "utf-8"
@@ -19638,13 +19638,13 @@ var init_ConfigService = __esm({
19638
19638
  /**
19639
19639
  * 変更リスナーの登録
19640
19640
  */
19641
- onChange(path64, listener) {
19642
- if (!this._listeners.has(path64)) {
19643
- this._listeners.set(path64, []);
19641
+ onChange(path65, listener) {
19642
+ if (!this._listeners.has(path65)) {
19643
+ this._listeners.set(path65, []);
19644
19644
  }
19645
- this._listeners.get(path64).push(listener);
19645
+ this._listeners.get(path65).push(listener);
19646
19646
  return () => {
19647
- const listeners = this._listeners.get(path64);
19647
+ const listeners = this._listeners.get(path65);
19648
19648
  if (listeners) {
19649
19649
  const index = listeners.indexOf(listener);
19650
19650
  if (index !== -1) {
@@ -20133,7 +20133,7 @@ var init_ValidationService = __esm({
20133
20133
  );
20134
20134
  this._schemas.set(
20135
20135
  "filePath",
20136
- zod.z.string().min(1).max(this._config.maxFilePathLength).refine((path64) => !this.containsPathTraversal(path64), {
20136
+ zod.z.string().min(1).max(this._config.maxFilePathLength).refine((path65) => !this.containsPathTraversal(path65), {
20137
20137
  message: "Path traversal detected"
20138
20138
  })
20139
20139
  );
@@ -20272,11 +20272,11 @@ var init_ValidationService = __esm({
20272
20272
  /**
20273
20273
  * ファイルパス検証
20274
20274
  */
20275
- validateFilePath(path64) {
20275
+ validateFilePath(path65) {
20276
20276
  try {
20277
20277
  const schema = this._schemas.get("filePath");
20278
- const result = schema.parse(path64);
20279
- if (this.isSystemPath(path64)) {
20278
+ const result = schema.parse(path65);
20279
+ if (this.isSystemPath(path65)) {
20280
20280
  return {
20281
20281
  valid: false,
20282
20282
  errors: [
@@ -20422,8 +20422,8 @@ var init_ValidationService = __esm({
20422
20422
  /**
20423
20423
  * パストラバーサルの検出
20424
20424
  */
20425
- containsPathTraversal(path64) {
20426
- return /\.\.[/\\]/.test(path64) || path64.includes("..\\") || path64.includes("../");
20425
+ containsPathTraversal(path65) {
20426
+ return /\.\.[/\\]/.test(path65) || path65.includes("..\\") || path65.includes("../");
20427
20427
  }
20428
20428
  /**
20429
20429
  * 危険なコマンドの判定
@@ -20450,7 +20450,7 @@ var init_ValidationService = __esm({
20450
20450
  /**
20451
20451
  * システムパスの判定
20452
20452
  */
20453
- isSystemPath(path64) {
20453
+ isSystemPath(path65) {
20454
20454
  const systemPaths = [
20455
20455
  "/etc",
20456
20456
  "/sys",
@@ -20464,7 +20464,7 @@ var init_ValidationService = __esm({
20464
20464
  "/sbin"
20465
20465
  ];
20466
20466
  return systemPaths.some(
20467
- (sysPath) => path64.toLowerCase().startsWith(sysPath.toLowerCase())
20467
+ (sysPath) => path65.toLowerCase().startsWith(sysPath.toLowerCase())
20468
20468
  );
20469
20469
  }
20470
20470
  /**
@@ -25440,10 +25440,10 @@ Run /doctor --fix to automatically fix ${fixableCount} issue(s)`
25440
25440
  const finalize = async (text, data) => {
25441
25441
  if (outputPath) {
25442
25442
  try {
25443
- const fs51 = await import('fs/promises');
25444
- const path64 = await import('path');
25445
- const abs = path64.resolve(outputPath);
25446
- await fs51.writeFile(abs, text, "utf-8");
25443
+ const fs52 = await import('fs/promises');
25444
+ const path65 = await import('path');
25445
+ const abs = path65.resolve(outputPath);
25446
+ await fs52.writeFile(abs, text, "utf-8");
25447
25447
  const msg = `Saved doctor report to ${abs}`;
25448
25448
  return { ok: true, message: msg, data: { path: abs, bytes: Buffer.byteLength(text, "utf-8") } };
25449
25449
  } catch (e2) {
@@ -25533,10 +25533,10 @@ Run /doctor --fix to automatically fix ${fixableCount} issue(s)`
25533
25533
  const finalize = async (text, data) => {
25534
25534
  if (outputPath) {
25535
25535
  try {
25536
- const fs51 = await import('fs/promises');
25537
- const path64 = await import('path');
25538
- const abs = path64.resolve(outputPath);
25539
- await fs51.writeFile(abs, text, "utf-8");
25536
+ const fs52 = await import('fs/promises');
25537
+ const path65 = await import('path');
25538
+ const abs = path65.resolve(outputPath);
25539
+ await fs52.writeFile(abs, text, "utf-8");
25540
25540
  const msg = `Saved metrics to ${abs}`;
25541
25541
  return { ok: true, message: msg, data: { path: abs, bytes: Buffer.byteLength(text, "utf-8") } };
25542
25542
  } catch (e2) {
@@ -25925,15 +25925,15 @@ var init_SessionOrchestrator = __esm({
25925
25925
  /**
25926
25926
  * 設定の取得
25927
25927
  */
25928
- getConfig(path64) {
25929
- return this._configService?.getNestedValue(path64);
25928
+ getConfig(path65) {
25929
+ return this._configService?.getNestedValue(path65);
25930
25930
  }
25931
25931
  /**
25932
25932
  * 設定の更新
25933
25933
  */
25934
- async setConfig(path64, value) {
25934
+ async setConfig(path65, value) {
25935
25935
  if (this._configService) {
25936
- await this._configService.setNestedValue(path64, value);
25936
+ await this._configService.setNestedValue(path65, value);
25937
25937
  }
25938
25938
  }
25939
25939
  /**
@@ -26051,11 +26051,11 @@ var init_interactive_session = __esm({
26051
26051
  getStats() {
26052
26052
  return this.orchestrator.getSessionStats();
26053
26053
  }
26054
- getConfig(path64) {
26055
- return this.orchestrator.getConfig(path64);
26054
+ getConfig(path65) {
26055
+ return this.orchestrator.getConfig(path65);
26056
26056
  }
26057
- async setConfig(path64, value) {
26058
- await this.orchestrator.setConfig(path64, value);
26057
+ async setConfig(path65, value) {
26058
+ await this.orchestrator.setConfig(path65, value);
26059
26059
  }
26060
26060
  };
26061
26061
  }
@@ -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.38",
26070
- description: "\u{1F680} MARIA v4.3.38 - 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.39",
26070
+ description: "\u{1F680} MARIA v4.3.39 - 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",
@@ -28104,7 +28104,7 @@ var init_AuthenticationManager = __esm({
28104
28104
  const response = await fetch(`${this.apiBase}/api/user/profile`, {
28105
28105
  headers: {
28106
28106
  "Authorization": `Bearer ${tokens2.accessToken}`,
28107
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.38"}`
28107
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.39"}`
28108
28108
  }
28109
28109
  });
28110
28110
  if (response.status === 401) {
@@ -28745,9 +28745,9 @@ function clientThrottle(endpoint) {
28745
28745
  }
28746
28746
  rateLimitMap.set(endpoint, now2);
28747
28747
  }
28748
- async function callApi(path64, init3 = {}) {
28748
+ async function callApi(path65, init3 = {}) {
28749
28749
  const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
28750
- const fullUrl = `${apiBase}${path64}`;
28750
+ const fullUrl = `${apiBase}${path65}`;
28751
28751
  let tokens2 = await authManager.getValidTokens();
28752
28752
  if (!tokens2) {
28753
28753
  console.log(chalk14__default.default.red(ERR.AUTH_REQUIRED.msg));
@@ -28758,7 +28758,7 @@ async function callApi(path64, init3 = {}) {
28758
28758
  "Authorization": `Bearer ${token}`,
28759
28759
  "X-Device-Id": getDeviceId(),
28760
28760
  "X-Session-Id": getSessionId() || "",
28761
- "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.38"}`,
28761
+ "User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.39"}`,
28762
28762
  "Content-Type": init3.headers?.["Content-Type"] || "application/json"
28763
28763
  });
28764
28764
  const doFetch = async (token) => {
@@ -28816,8 +28816,8 @@ async function callApi(path64, init3 = {}) {
28816
28816
  }
28817
28817
  return response;
28818
28818
  }
28819
- async function callApiJson(path64, init3 = {}) {
28820
- const response = await callApi(path64, init3);
28819
+ async function callApiJson(path65, init3 = {}) {
28820
+ const response = await callApi(path65, init3);
28821
28821
  if (!response.ok) {
28822
28822
  const error2 = await response.json().catch(() => ({
28823
28823
  message: `API error: ${response.status} ${response.statusText}`
@@ -28826,8 +28826,8 @@ async function callApiJson(path64, init3 = {}) {
28826
28826
  }
28827
28827
  return response.json();
28828
28828
  }
28829
- async function* streamApi(path64, init3 = {}) {
28830
- const response = await callApi(path64, {
28829
+ async function* streamApi(path65, init3 = {}) {
28830
+ const response = await callApi(path65, {
28831
28831
  ...init3,
28832
28832
  headers: {
28833
28833
  ...init3.headers,
@@ -28853,13 +28853,13 @@ async function* streamApi(path64, init3 = {}) {
28853
28853
  reader.releaseLock();
28854
28854
  }
28855
28855
  }
28856
- async function uploadFile(path64, file, metadata5 = {}) {
28856
+ async function uploadFile(path65, file, metadata5 = {}) {
28857
28857
  const formData = new FormData();
28858
28858
  formData.append("file", new Blob([file]));
28859
28859
  Object.entries(metadata5).forEach(([key, value]) => {
28860
28860
  formData.append(key, String(value));
28861
28861
  });
28862
- return callApiJson(path64, {
28862
+ return callApiJson(path65, {
28863
28863
  method: "POST",
28864
28864
  body: formData,
28865
28865
  headers: {
@@ -29175,7 +29175,7 @@ async function mapInputToTopLevelCommand(input3) {
29175
29175
  const system = [
29176
29176
  "You are a router for the MARIA CLI.",
29177
29177
  "Decide the best command for a single user input.",
29178
- "Allowed commands: /help, /image, /code, /video, /whoami, /login, /logout, /evaluate, /research, chat.",
29178
+ "Allowed commands: /help, /image, /code, /video, /whoami, /login, /logout, /evaluate, /research, /novel, chat.",
29179
29179
  "Note that /image and /video are for generating them. If a path of a file is provided, you should double think why it's referenced (it may be for coding or chatting or other commands, regarding on the context).",
29180
29180
  'Return JSON only with keys: { "command": string, "args"?: string[], "confidence": number }.',
29181
29181
  "Select chat when the input is a general question or conversation rather than a specific slash command.",
@@ -29203,7 +29203,7 @@ ${input3}`,
29203
29203
  }
29204
29204
  if (!parsed || typeof parsed.command !== "string") return null;
29205
29205
  const cmd = parsed.command;
29206
- if (!["/help", "/image", "/code", "/video", "/whoami", "/login", "/logout", "/evaluate", "/research", "chat"].includes(cmd)) return null;
29206
+ if (!["/help", "/image", "/code", "/video", "/whoami", "/login", "/logout", "/evaluate", "/research", "/novel", "chat"].includes(cmd)) return null;
29207
29207
  const out = { command: cmd };
29208
29208
  if (Array.isArray(parsed.args)) {
29209
29209
  out.args = parsed.args.filter((a) => typeof a === "string" && a.trim()).map((s2) => s2.trim());
@@ -33819,12 +33819,12 @@ var init_esm4 = __esm({
33819
33819
  /**
33820
33820
  * Get the Path object referenced by the string path, resolved from this Path
33821
33821
  */
33822
- resolve(path64) {
33823
- if (!path64) {
33822
+ resolve(path65) {
33823
+ if (!path65) {
33824
33824
  return this;
33825
33825
  }
33826
- const rootPath = this.getRootString(path64);
33827
- const dir = path64.substring(rootPath.length);
33826
+ const rootPath = this.getRootString(path65);
33827
+ const dir = path65.substring(rootPath.length);
33828
33828
  const dirParts = dir.split(this.splitSep);
33829
33829
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
33830
33830
  return result;
@@ -34576,8 +34576,8 @@ var init_esm4 = __esm({
34576
34576
  /**
34577
34577
  * @internal
34578
34578
  */
34579
- getRootString(path64) {
34580
- return path11.win32.parse(path64).root;
34579
+ getRootString(path65) {
34580
+ return path11.win32.parse(path65).root;
34581
34581
  }
34582
34582
  /**
34583
34583
  * @internal
@@ -34623,8 +34623,8 @@ var init_esm4 = __esm({
34623
34623
  /**
34624
34624
  * @internal
34625
34625
  */
34626
- getRootString(path64) {
34627
- return path64.startsWith("/") ? "/" : "";
34626
+ getRootString(path65) {
34627
+ return path65.startsWith("/") ? "/" : "";
34628
34628
  }
34629
34629
  /**
34630
34630
  * @internal
@@ -34673,8 +34673,8 @@ var init_esm4 = __esm({
34673
34673
  *
34674
34674
  * @internal
34675
34675
  */
34676
- constructor(cwd2 = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs: fs51 = defaultFS } = {}) {
34677
- this.#fs = fsFromOption(fs51);
34676
+ constructor(cwd2 = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs: fs52 = defaultFS } = {}) {
34677
+ this.#fs = fsFromOption(fs52);
34678
34678
  if (cwd2 instanceof URL || cwd2.startsWith("file://")) {
34679
34679
  cwd2 = url.fileURLToPath(cwd2);
34680
34680
  }
@@ -34713,11 +34713,11 @@ var init_esm4 = __esm({
34713
34713
  /**
34714
34714
  * Get the depth of a provided path, string, or the cwd
34715
34715
  */
34716
- depth(path64 = this.cwd) {
34717
- if (typeof path64 === "string") {
34718
- path64 = this.cwd.resolve(path64);
34716
+ depth(path65 = this.cwd) {
34717
+ if (typeof path65 === "string") {
34718
+ path65 = this.cwd.resolve(path65);
34719
34719
  }
34720
- return path64.depth();
34720
+ return path65.depth();
34721
34721
  }
34722
34722
  /**
34723
34723
  * Return the cache of child entries. Exposed so subclasses can create
@@ -35204,9 +35204,9 @@ var init_esm4 = __esm({
35204
35204
  process11();
35205
35205
  return results;
35206
35206
  }
35207
- chdir(path64 = this.cwd) {
35207
+ chdir(path65 = this.cwd) {
35208
35208
  const oldCwd = this.cwd;
35209
- this.cwd = typeof path64 === "string" ? this.cwd.resolve(path64) : path64;
35209
+ this.cwd = typeof path65 === "string" ? this.cwd.resolve(path65) : path65;
35210
35210
  this.cwd[setAsCwd](oldCwd);
35211
35211
  }
35212
35212
  };
@@ -35232,8 +35232,8 @@ var init_esm4 = __esm({
35232
35232
  /**
35233
35233
  * @internal
35234
35234
  */
35235
- newRoot(fs51) {
35236
- return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs51 });
35235
+ newRoot(fs52) {
35236
+ return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs52 });
35237
35237
  }
35238
35238
  /**
35239
35239
  * Return true if the provided path string is an absolute path
@@ -35261,8 +35261,8 @@ var init_esm4 = __esm({
35261
35261
  /**
35262
35262
  * @internal
35263
35263
  */
35264
- newRoot(fs51) {
35265
- return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs51 });
35264
+ newRoot(fs52) {
35265
+ return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs52 });
35266
35266
  }
35267
35267
  /**
35268
35268
  * Return true if the provided path string is an absolute path
@@ -35581,8 +35581,8 @@ var init_processor = __esm({
35581
35581
  }
35582
35582
  // match, absolute, ifdir
35583
35583
  entries() {
35584
- return [...this.store.entries()].map(([path64, n]) => [
35585
- path64,
35584
+ return [...this.store.entries()].map(([path65, n]) => [
35585
+ path65,
35586
35586
  !!(n & 2),
35587
35587
  !!(n & 1)
35588
35588
  ]);
@@ -35795,9 +35795,9 @@ var init_walker = __esm({
35795
35795
  signal;
35796
35796
  maxDepth;
35797
35797
  includeChildMatches;
35798
- constructor(patterns, path64, opts) {
35798
+ constructor(patterns, path65, opts) {
35799
35799
  this.patterns = patterns;
35800
- this.path = path64;
35800
+ this.path = path65;
35801
35801
  this.opts = opts;
35802
35802
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
35803
35803
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -35816,11 +35816,11 @@ var init_walker = __esm({
35816
35816
  });
35817
35817
  }
35818
35818
  }
35819
- #ignored(path64) {
35820
- return this.seen.has(path64) || !!this.#ignore?.ignored?.(path64);
35819
+ #ignored(path65) {
35820
+ return this.seen.has(path65) || !!this.#ignore?.ignored?.(path65);
35821
35821
  }
35822
- #childrenIgnored(path64) {
35823
- return !!this.#ignore?.childrenIgnored?.(path64);
35822
+ #childrenIgnored(path65) {
35823
+ return !!this.#ignore?.childrenIgnored?.(path65);
35824
35824
  }
35825
35825
  // backpressure mechanism
35826
35826
  pause() {
@@ -36035,8 +36035,8 @@ var init_walker = __esm({
36035
36035
  };
36036
36036
  GlobWalker = class extends GlobUtil {
36037
36037
  matches = /* @__PURE__ */ new Set();
36038
- constructor(patterns, path64, opts) {
36039
- super(patterns, path64, opts);
36038
+ constructor(patterns, path65, opts) {
36039
+ super(patterns, path65, opts);
36040
36040
  }
36041
36041
  matchEmit(e2) {
36042
36042
  this.matches.add(e2);
@@ -36073,8 +36073,8 @@ var init_walker = __esm({
36073
36073
  };
36074
36074
  GlobStream = class extends GlobUtil {
36075
36075
  results;
36076
- constructor(patterns, path64, opts) {
36077
- super(patterns, path64, opts);
36076
+ constructor(patterns, path65, opts) {
36077
+ super(patterns, path65, opts);
36078
36078
  this.results = new Minipass({
36079
36079
  signal: this.signal,
36080
36080
  objectMode: true
@@ -41909,9 +41909,9 @@ var init_SafetyGuard = __esm({
41909
41909
  }
41910
41910
  }
41911
41911
  if (action.args.paths && Array.isArray(action.args.paths)) {
41912
- for (const path64 of action.args.paths) {
41913
- if (!this.validatePath(path64)) {
41914
- violations.push(`Invalid path: ${path64}`);
41912
+ for (const path65 of action.args.paths) {
41913
+ if (!this.validatePath(path65)) {
41914
+ violations.push(`Invalid path: ${path65}`);
41915
41915
  }
41916
41916
  }
41917
41917
  }
@@ -41967,15 +41967,15 @@ var init_SafetyGuard = __esm({
41967
41967
  * Validate file path against allowed/blocked lists
41968
41968
  */
41969
41969
  validatePath(filePath) {
41970
- const path64 = __require("path");
41971
- const resolvedPath = path64.resolve(filePath);
41970
+ const path65 = __require("path");
41971
+ const resolvedPath = path65.resolve(filePath);
41972
41972
  for (const blockedPath of this.constraints.blockedPaths) {
41973
- if (resolvedPath.startsWith(path64.resolve(blockedPath))) {
41973
+ if (resolvedPath.startsWith(path65.resolve(blockedPath))) {
41974
41974
  return false;
41975
41975
  }
41976
41976
  }
41977
41977
  for (const allowedPath of this.constraints.allowedPaths) {
41978
- if (resolvedPath.startsWith(path64.resolve(allowedPath))) {
41978
+ if (resolvedPath.startsWith(path65.resolve(allowedPath))) {
41979
41979
  return true;
41980
41980
  }
41981
41981
  }
@@ -42004,9 +42004,9 @@ var init_SafetyGuard = __esm({
42004
42004
  violations.push(`Invalid path in ${action.type}: ${action.args.path}`);
42005
42005
  }
42006
42006
  if (action.args.paths && Array.isArray(action.args.paths)) {
42007
- for (const path64 of action.args.paths) {
42008
- if (!this.validatePath(path64)) {
42009
- violations.push(`Invalid path in ${action.type}: ${path64}`);
42007
+ for (const path65 of action.args.paths) {
42008
+ if (!this.validatePath(path65)) {
42009
+ violations.push(`Invalid path in ${action.type}: ${path65}`);
42010
42010
  }
42011
42011
  }
42012
42012
  }
@@ -42975,8 +42975,8 @@ var init_ConfigActionExecutor = __esm({
42975
42975
  /**
42976
42976
  * Set nested configuration value using dot notation
42977
42977
  */
42978
- setNestedValue(obj, path64, value) {
42979
- const keys = path64.split(".");
42978
+ setNestedValue(obj, path65, value) {
42979
+ const keys = path65.split(".");
42980
42980
  let current = obj;
42981
42981
  for (let i2 = 0; i2 < keys.length - 1; i2++) {
42982
42982
  const key = keys[i2];
@@ -51261,7 +51261,7 @@ var init_about_command = __esm({
51261
51261
  async execute(args2, context2) {
51262
51262
  const output3 = [];
51263
51263
  output3.push("");
51264
- output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.38"));
51264
+ output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.39"));
51265
51265
  output3.push(chalk14__default.default.gray("\u2550".repeat(40)));
51266
51266
  output3.push("");
51267
51267
  output3.push(chalk14__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
@@ -54325,88 +54325,6 @@ var init_SystemCommandFactory = __esm({
54325
54325
  };
54326
54326
  }
54327
54327
  });
54328
- function handleRateLimitError(error2) {
54329
- console.log();
54330
- console.log(chalk14__default.default.yellow("\u23F1\uFE0F Rate Limit Exceeded"));
54331
- console.log(chalk14__default.default.gray("\u2501".repeat(50)));
54332
- const route = error2.route || error2.details?.endpoint || "API";
54333
- const plan = error2.plan || error2.details?.plan || "Unknown";
54334
- const limit = error2.limit || (error2.details?.limit ? parseInt(error2.details.limit) : null);
54335
- const retryAfter = error2.retryAfter || error2.details?.retryAfterSeconds;
54336
- const resetAt = error2.resetAt || (error2.details?.resetAt ? Date.parse(error2.details.resetAt) : null);
54337
- const waitTime = Number.isFinite(retryAfter) ? `${retryAfter} second${retryAfter > 1 ? "s" : ""}` : "a few seconds";
54338
- let resetTime = "";
54339
- if (resetAt && Number.isFinite(resetAt)) {
54340
- const resetDate = new Date(resetAt);
54341
- const now2 = /* @__PURE__ */ new Date();
54342
- const diffMs = resetDate.getTime() - now2.getTime();
54343
- if (diffMs > 0 && diffMs < 6e4) {
54344
- resetTime = `in ${Math.ceil(diffMs / 1e3)} seconds`;
54345
- } else if (diffMs > 0) {
54346
- resetTime = `at ${resetDate.toLocaleTimeString()}`;
54347
- }
54348
- }
54349
- console.log(chalk14__default.default.white(`Plan: ${chalk14__default.default.bold(plan)}`));
54350
- console.log(chalk14__default.default.white(`Endpoint: ${chalk14__default.default.bold(route)}`));
54351
- if (limit !== null) {
54352
- console.log(chalk14__default.default.white(`Limit: ${chalk14__default.default.bold(limit)} requests`));
54353
- }
54354
- if (error2.remaining !== void 0) {
54355
- console.log(chalk14__default.default.white(`Remaining: ${chalk14__default.default.bold(error2.remaining)} requests`));
54356
- }
54357
- console.log();
54358
- console.log(chalk14__default.default.cyan(`Please wait ${chalk14__default.default.bold(waitTime)} before trying again`));
54359
- if (resetTime) {
54360
- console.log(chalk14__default.default.gray(`Rate limit resets ${resetTime}`));
54361
- }
54362
- if (error2.hint) {
54363
- console.log();
54364
- console.log(chalk14__default.default.magenta("\u{1F4A1} " + error2.hint));
54365
- }
54366
- console.log(chalk14__default.default.gray("\u2501".repeat(50)));
54367
- console.log();
54368
- }
54369
- async function parseRateLimitResponse(response) {
54370
- if (response.status !== 429) {
54371
- return null;
54372
- }
54373
- const rateLimitInfo = {
54374
- limit: parseInt(response.headers.get("RateLimit-Limit") || "0") || void 0,
54375
- remaining: parseInt(response.headers.get("RateLimit-Remaining") || "0") || void 0,
54376
- resetAt: parseInt(response.headers.get("RateLimit-Reset") || "0") || void 0,
54377
- retryAfter: parseInt(response.headers.get("Retry-After") || "0") || void 0
54378
- };
54379
- try {
54380
- const data = await response.json();
54381
- if (data.error === "rate_limited" || data.error === "rate_limit_exceeded") {
54382
- return {
54383
- ...data,
54384
- // Merge header info if not in body
54385
- limit: data.limit || rateLimitInfo.limit,
54386
- remaining: data.remaining || rateLimitInfo.remaining,
54387
- resetAt: data.resetAt || rateLimitInfo.resetAt,
54388
- retryAfter: data.retryAfter || rateLimitInfo.retryAfter
54389
- };
54390
- }
54391
- return {
54392
- error: "rate_limited",
54393
- message: data.message || "Rate limit exceeded. Please wait and try again.",
54394
- hint: data.hint || "Consider upgrading your plan for higher limits.",
54395
- ...rateLimitInfo
54396
- };
54397
- } catch {
54398
- return {
54399
- error: "rate_limited",
54400
- message: "Rate limit exceeded. Please wait and try again.",
54401
- hint: "Consider upgrading your plan for higher limits.",
54402
- ...rateLimitInfo
54403
- };
54404
- }
54405
- }
54406
- var init_rate_limit_handler = __esm({
54407
- "src/services/api-client/rate-limit-handler.ts"() {
54408
- }
54409
- });
54410
54328
  function extractCodeInfo(codeBlock) {
54411
54329
  const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
54412
54330
  if (!match2) {
@@ -54651,8 +54569,408 @@ var init_code_utils = __esm({
54651
54569
  }
54652
54570
  });
54653
54571
 
54654
- // src/services/code-orchestrator/ArgumentInference.ts
54572
+ // src/services/creative/NovelArgumentInference.ts
54655
54573
  function extractFirstJson4(text) {
54574
+ if (!text) return null;
54575
+ const start = text.indexOf("{");
54576
+ const end = text.lastIndexOf("}");
54577
+ if (start !== -1 && end !== -1 && end > start) {
54578
+ const cand = text.slice(start, end + 1);
54579
+ try {
54580
+ JSON.parse(cand);
54581
+ return cand;
54582
+ } catch {
54583
+ }
54584
+ }
54585
+ return null;
54586
+ }
54587
+ async function inferNovelArgs(rawText) {
54588
+ const system = [
54589
+ "You extract structured options for a novel generation command.",
54590
+ 'Return JSON ONLY with keys among: { "title"?: string, "lang"?: string, "format"?: "md"|"markdown"|"txt"|"plaintext", "genre"?: string, "planOnly"?: boolean, "chapters"?: number }.',
54591
+ 'Infer reasonable values from natural language. Keep chapters between 3 and 50 if specified. If format suggests plain text, choose "plaintext".',
54592
+ "If the user requests outline only, set planOnly=true.",
54593
+ "Do not add commentary."
54594
+ ].join("\n");
54595
+ const resp = await callAPI("/v1/ai-proxy", {
54596
+ method: "POST",
54597
+ body: {
54598
+ prompt: `${system}
54599
+
54600
+ ---
54601
+
54602
+ ${rawText}`,
54603
+ taskType: "creative"
54604
+ }
54605
+ });
54606
+ const raw = (resp?.data?.content || resp?.output || "").trim();
54607
+ const jsonText = extractFirstJson4(raw) || raw;
54608
+ let parsed = {};
54609
+ try {
54610
+ parsed = JSON.parse(jsonText);
54611
+ } catch {
54612
+ return {};
54613
+ }
54614
+ const out = {};
54615
+ if (typeof parsed.title === "string" && parsed.title.trim()) out.title = parsed.title.trim();
54616
+ if (typeof parsed.lang === "string" && parsed.lang.trim()) out.lang = parsed.lang.trim().toLowerCase();
54617
+ if (typeof parsed.format === "string") {
54618
+ const f3 = parsed.format.toLowerCase();
54619
+ if (f3 === "md" || f3 === "markdown") out.format = "md";
54620
+ else if (f3 === "txt" || f3 === "plaintext" || f3 === "text") out.format = "txt";
54621
+ }
54622
+ if (typeof parsed.genre === "string" && parsed.genre.trim()) out.genre = parsed.genre.trim();
54623
+ if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
54624
+ if (typeof parsed.chapters === "number" && Number.isFinite(parsed.chapters)) {
54625
+ const n = Math.max(1, Math.min(100, Math.floor(parsed.chapters)));
54626
+ out.chapters = n;
54627
+ }
54628
+ return out;
54629
+ }
54630
+ var init_NovelArgumentInference = __esm({
54631
+ "src/services/creative/NovelArgumentInference.ts"() {
54632
+ init_api_caller();
54633
+ }
54634
+ });
54635
+
54636
+ // src/slash-commands/categories/creative/novel.command.ts
54637
+ var novel_command_exports = {};
54638
+ __export(novel_command_exports, {
54639
+ NovelCommand: () => NovelCommand,
54640
+ default: () => novel_command_default
54641
+ });
54642
+ function normalizeFormat(fmt) {
54643
+ const f3 = (fmt).toLowerCase();
54644
+ if (f3 === "txt" || f3 === "plaintext" || f3 === "text") return "txt";
54645
+ return "md";
54646
+ }
54647
+ function normalizeLang(lang) {
54648
+ const l = (lang).toLowerCase();
54649
+ if (!l) return "en";
54650
+ if (["en", "ja", "jp", "zh", "ko", "fr", "de", "es", "it", "pt"].includes(l)) {
54651
+ return l === "jp" ? "ja" : l;
54652
+ }
54653
+ return "en";
54654
+ }
54655
+ async function writeText(filePath, content) {
54656
+ const dir = path11__namespace.dirname(filePath);
54657
+ await fsp__namespace.mkdir(dir, { recursive: true });
54658
+ await fsp__namespace.writeFile(filePath, content, "utf8");
54659
+ }
54660
+ function extractFirstJsonArray(text) {
54661
+ if (!text) return null;
54662
+ const t2 = text.trim();
54663
+ const fenced = t2.match(/```json\s*([\s\S]*?)```/i) || t2.match(/```\s*([\s\S]*?)```/);
54664
+ if (fenced && fenced[1]) {
54665
+ const body = fenced[1].trim();
54666
+ try {
54667
+ const arr = JSON.parse(body);
54668
+ return Array.isArray(arr) ? arr : null;
54669
+ } catch {
54670
+ }
54671
+ }
54672
+ const defenced = t2.replace(/```json|```/gi, "").trim();
54673
+ try {
54674
+ const arr = JSON.parse(defenced);
54675
+ return Array.isArray(arr) ? arr : null;
54676
+ } catch {
54677
+ }
54678
+ const s2 = t2.indexOf("[");
54679
+ const e2 = t2.lastIndexOf("]");
54680
+ if (s2 !== -1 && e2 !== -1 && e2 > s2) {
54681
+ const slice = t2.slice(s2, e2 + 1);
54682
+ try {
54683
+ const arr = JSON.parse(slice);
54684
+ return Array.isArray(arr) ? arr : null;
54685
+ } catch {
54686
+ }
54687
+ }
54688
+ return null;
54689
+ }
54690
+ async function generatePlan(prompt, lang, title, genre) {
54691
+ const system = [
54692
+ "You generate a detailed novel outline (plot).",
54693
+ "Return Markdown with clear sections: Title, Logline, Themes, Characters, Chapter Outline.",
54694
+ "The language should match the requested language."
54695
+ ].join("\n");
54696
+ const user = [
54697
+ `Language: ${lang}`,
54698
+ `Title: ${title}`,
54699
+ genre ? `Genre: ${genre}` : "",
54700
+ "Prompt:",
54701
+ prompt
54702
+ ].filter(Boolean).join("\n");
54703
+ const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt: `${system}
54704
+
54705
+ ---
54706
+
54707
+ ${user}`, taskType: "creative" } });
54708
+ const out = (resp?.data?.content || resp?.output || "").trim();
54709
+ return out;
54710
+ }
54711
+ async function generateChapters(planMarkdown, lang, chapters) {
54712
+ const system = [
54713
+ "You expand a novel outline into chapter texts.",
54714
+ "Return only JSON array: [{ index: number, title: string, content: string }].",
54715
+ "Write in the requested language and maintain consistency with the outline."
54716
+ ].join("\n");
54717
+ const prompt = `${system}
54718
+
54719
+ LANG=${lang}
54720
+ CHAPTERS=${chapters}
54721
+
54722
+ OUTLINE:
54723
+ ${planMarkdown}`;
54724
+ const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt, taskType: "creative" } });
54725
+ const raw = (resp?.data?.content || resp?.output || "").trim();
54726
+ const arr = extractFirstJsonArray(raw);
54727
+ if (Array.isArray(arr)) {
54728
+ return arr.map((it, i2) => ({
54729
+ index: typeof it.index === "number" ? it.index : i2,
54730
+ title: typeof it.title === "string" ? it.title : `Chapter ${i2 + 1}`,
54731
+ content: typeof it.content === "string" ? it.content : ""
54732
+ }));
54733
+ }
54734
+ return [{ index: 0, title: "Chapter 1", content: raw }];
54735
+ }
54736
+ async function generateTitle(idea, lang, genre) {
54737
+ const system = [
54738
+ "You craft a concise, compelling novel title. Return only the title string.",
54739
+ "Consider the idea and genre. Use the requested language."
54740
+ ].join("\n");
54741
+ const user = [
54742
+ `Language: ${lang}`,
54743
+ genre ? `Genre: ${genre}` : "",
54744
+ "Idea:",
54745
+ idea
54746
+ ].filter(Boolean).join("\n");
54747
+ const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt: `${system}
54748
+
54749
+ ---
54750
+
54751
+ ${user}`, taskType: "creative" } });
54752
+ const raw = (resp?.data?.content || resp?.output || "").trim();
54753
+ try {
54754
+ const obj = JSON.parse(raw);
54755
+ if (typeof obj?.title === "string") return obj.title.trim();
54756
+ } catch {
54757
+ }
54758
+ const matched = raw.match(/```[a-z]*\s*([\s\S]*?)```/i);
54759
+ const text = matched ? matched[1].trim() : raw;
54760
+ return text.split("\n")[0].trim();
54761
+ }
54762
+ var NovelCommand, novel_command_default;
54763
+ var init_novel_command = __esm({
54764
+ "src/slash-commands/categories/creative/novel.command.ts"() {
54765
+ init_base_command();
54766
+ init_code_utils();
54767
+ init_api_caller();
54768
+ init_NovelArgumentInference();
54769
+ init_animations();
54770
+ NovelCommand = class extends BaseCommand {
54771
+ name = "novel";
54772
+ category = "creative";
54773
+ description = "Generate a novel: outline plan and full chapters with language/format options";
54774
+ aliases = ["story"];
54775
+ usage = "<idea or title> [--lang <code>] [--format md|txt] [--genre <name>] [--plan-only] [--chapters <n>]";
54776
+ examples = [
54777
+ { input: "/novel cyberpunk heist in Tokyo --lang ja", description: "\u65E5\u672C\u8A9E\u3067\u30B5\u30A4\u30D0\u30FC\u30D1\u30F3\u30AF\u5C0F\u8AAC\u3092\u751F\u6210" },
54778
+ { input: '/novel "A voyage to Europa" --format txt --genre sci-fi', description: "\u82F1\u8A9E\u30FB\u30D7\u30EC\u30FC\u30F3\u30C6\u30AD\u30B9\u30C8\u3067\u751F\u6210" },
54779
+ { input: "/novel detective mystery --plan-only", description: "\u30D7\u30ED\u30C3\u30C8\u306E\u307F\u3092\u4F5C\u6210\u3057\u3066\u4FDD\u5B58" }
54780
+ ];
54781
+ async execute(args2, context2) {
54782
+ const raw = Array.isArray(args2.raw) ? args2.raw : [];
54783
+ const ideaText = raw.join(" ").trim();
54784
+ if (!ideaText) {
54785
+ return this.error("Usage: /novel <idea or title> [--lang <code>] [--format md|txt] [--genre <name>] [--plan-only] [--chapters <n>]");
54786
+ }
54787
+ const explicit = {
54788
+ lang: typeof args2.options["lang"] === "string" ? String(args2.options["lang"]) : void 0,
54789
+ format: typeof args2.options["format"] === "string" ? String(args2.options["format"]) : void 0,
54790
+ genre: typeof args2.options["genre"] === "string" ? String(args2.options["genre"]) : void 0,
54791
+ chapters: typeof args2.options["chapters"] === "string" ? Number(args2.options["chapters"]) : void 0,
54792
+ planOnly: args2.flags["plan-only"] === true || args2.flags["sow"] === true
54793
+ };
54794
+ let inferred = {};
54795
+ try {
54796
+ const spin = new ProcessAnimation();
54797
+ spin.start();
54798
+ try {
54799
+ inferred = await inferNovelArgs(ideaText);
54800
+ } finally {
54801
+ try {
54802
+ spin.stop();
54803
+ } catch {
54804
+ }
54805
+ }
54806
+ } catch {
54807
+ }
54808
+ const lang = normalizeLang(explicit.lang || inferred.lang || "en");
54809
+ const format = normalizeFormat(explicit.format || inferred.format || "md");
54810
+ const planOnly = explicit.planOnly || inferred.planOnly === true;
54811
+ const chapters = Number.isFinite(explicit.chapters) && explicit.chapters > 0 ? Math.floor(explicit.chapters) : typeof inferred.chapters === "number" && inferred.chapters > 0 ? Math.floor(inferred.chapters) : 8;
54812
+ const genre = explicit.genre || inferred.genre;
54813
+ let generatedTitle = inferred.title;
54814
+ if (!generatedTitle) {
54815
+ const spin = new ProcessAnimation();
54816
+ spin.start();
54817
+ try {
54818
+ generatedTitle = await generateTitle(ideaText, lang, genre);
54819
+ } finally {
54820
+ try {
54821
+ spin.stop();
54822
+ } catch {
54823
+ }
54824
+ }
54825
+ }
54826
+ const titleRaw = (generatedTitle || "novel").slice(0, 120);
54827
+ const title = sanitizeFilenameStrict(titleRaw);
54828
+ const root = process.cwd();
54829
+ const novelDir = await ensureUniquePath(safeResolve(root, path11__namespace.join("novel", title)));
54830
+ await fsp__namespace.mkdir(novelDir, { recursive: true });
54831
+ let plan = "";
54832
+ {
54833
+ const spin = new ProcessAnimation();
54834
+ spin.start();
54835
+ try {
54836
+ plan = await generatePlan(ideaText, lang, title, genre);
54837
+ } finally {
54838
+ try {
54839
+ spin.stop();
54840
+ } catch {
54841
+ }
54842
+ }
54843
+ }
54844
+ const planExt = format === "txt" ? ".txt" : ".md";
54845
+ const planPath = await ensureUniquePath(path11__namespace.join(novelDir, `00_plan${planExt}`));
54846
+ await writeText(planPath, plan);
54847
+ if (planOnly) {
54848
+ const msg2 = [`Saved plan to ${planPath}`, "", "Files:", `- ${planPath}`].join("\n");
54849
+ return this.success(msg2, { dir: novelDir, plan: planPath });
54850
+ }
54851
+ const chapterObjs = await (async () => {
54852
+ const spin = new ProcessAnimation();
54853
+ spin.start();
54854
+ try {
54855
+ return await generateChapters(plan, lang, chapters);
54856
+ } finally {
54857
+ try {
54858
+ spin.stop();
54859
+ } catch {
54860
+ }
54861
+ }
54862
+ })();
54863
+ let index = 1;
54864
+ const saved = [planPath];
54865
+ for (const ch of chapterObjs) {
54866
+ const num = String(index).padStart(2, "0");
54867
+ const chTitle = sanitizeFilenameStrict(ch.title || `chapter-${index}`);
54868
+ const file = path11__namespace.join(novelDir, `${num}_${chTitle}${planExt}`);
54869
+ const finalPath = await ensureUniquePath(file);
54870
+ const content = format === "md" ? `# ${ch.title}
54871
+
54872
+ ${ch.content}` : ch.content;
54873
+ await writeText(finalPath, content);
54874
+ saved.push(finalPath);
54875
+ index++;
54876
+ }
54877
+ const msg = [
54878
+ `Saved novel to ${novelDir}`,
54879
+ "",
54880
+ "Files:",
54881
+ ...saved.map((p) => `- ${p}`)
54882
+ ].join("\n");
54883
+ return this.success(msg, { dir: novelDir, files: saved });
54884
+ }
54885
+ };
54886
+ novel_command_default = NovelCommand;
54887
+ }
54888
+ });
54889
+ function handleRateLimitError(error2) {
54890
+ console.log();
54891
+ console.log(chalk14__default.default.yellow("\u23F1\uFE0F Rate Limit Exceeded"));
54892
+ console.log(chalk14__default.default.gray("\u2501".repeat(50)));
54893
+ const route = error2.route || error2.details?.endpoint || "API";
54894
+ const plan = error2.plan || error2.details?.plan || "Unknown";
54895
+ const limit = error2.limit || (error2.details?.limit ? parseInt(error2.details.limit) : null);
54896
+ const retryAfter = error2.retryAfter || error2.details?.retryAfterSeconds;
54897
+ const resetAt = error2.resetAt || (error2.details?.resetAt ? Date.parse(error2.details.resetAt) : null);
54898
+ const waitTime = Number.isFinite(retryAfter) ? `${retryAfter} second${retryAfter > 1 ? "s" : ""}` : "a few seconds";
54899
+ let resetTime = "";
54900
+ if (resetAt && Number.isFinite(resetAt)) {
54901
+ const resetDate = new Date(resetAt);
54902
+ const now2 = /* @__PURE__ */ new Date();
54903
+ const diffMs = resetDate.getTime() - now2.getTime();
54904
+ if (diffMs > 0 && diffMs < 6e4) {
54905
+ resetTime = `in ${Math.ceil(diffMs / 1e3)} seconds`;
54906
+ } else if (diffMs > 0) {
54907
+ resetTime = `at ${resetDate.toLocaleTimeString()}`;
54908
+ }
54909
+ }
54910
+ console.log(chalk14__default.default.white(`Plan: ${chalk14__default.default.bold(plan)}`));
54911
+ console.log(chalk14__default.default.white(`Endpoint: ${chalk14__default.default.bold(route)}`));
54912
+ if (limit !== null) {
54913
+ console.log(chalk14__default.default.white(`Limit: ${chalk14__default.default.bold(limit)} requests`));
54914
+ }
54915
+ if (error2.remaining !== void 0) {
54916
+ console.log(chalk14__default.default.white(`Remaining: ${chalk14__default.default.bold(error2.remaining)} requests`));
54917
+ }
54918
+ console.log();
54919
+ console.log(chalk14__default.default.cyan(`Please wait ${chalk14__default.default.bold(waitTime)} before trying again`));
54920
+ if (resetTime) {
54921
+ console.log(chalk14__default.default.gray(`Rate limit resets ${resetTime}`));
54922
+ }
54923
+ if (error2.hint) {
54924
+ console.log();
54925
+ console.log(chalk14__default.default.magenta("\u{1F4A1} " + error2.hint));
54926
+ }
54927
+ console.log(chalk14__default.default.gray("\u2501".repeat(50)));
54928
+ console.log();
54929
+ }
54930
+ async function parseRateLimitResponse(response) {
54931
+ if (response.status !== 429) {
54932
+ return null;
54933
+ }
54934
+ const rateLimitInfo = {
54935
+ limit: parseInt(response.headers.get("RateLimit-Limit") || "0") || void 0,
54936
+ remaining: parseInt(response.headers.get("RateLimit-Remaining") || "0") || void 0,
54937
+ resetAt: parseInt(response.headers.get("RateLimit-Reset") || "0") || void 0,
54938
+ retryAfter: parseInt(response.headers.get("Retry-After") || "0") || void 0
54939
+ };
54940
+ try {
54941
+ const data = await response.json();
54942
+ if (data.error === "rate_limited" || data.error === "rate_limit_exceeded") {
54943
+ return {
54944
+ ...data,
54945
+ // Merge header info if not in body
54946
+ limit: data.limit || rateLimitInfo.limit,
54947
+ remaining: data.remaining || rateLimitInfo.remaining,
54948
+ resetAt: data.resetAt || rateLimitInfo.resetAt,
54949
+ retryAfter: data.retryAfter || rateLimitInfo.retryAfter
54950
+ };
54951
+ }
54952
+ return {
54953
+ error: "rate_limited",
54954
+ message: data.message || "Rate limit exceeded. Please wait and try again.",
54955
+ hint: data.hint || "Consider upgrading your plan for higher limits.",
54956
+ ...rateLimitInfo
54957
+ };
54958
+ } catch {
54959
+ return {
54960
+ error: "rate_limited",
54961
+ message: "Rate limit exceeded. Please wait and try again.",
54962
+ hint: "Consider upgrading your plan for higher limits.",
54963
+ ...rateLimitInfo
54964
+ };
54965
+ }
54966
+ }
54967
+ var init_rate_limit_handler = __esm({
54968
+ "src/services/api-client/rate-limit-handler.ts"() {
54969
+ }
54970
+ });
54971
+
54972
+ // src/services/code-orchestrator/ArgumentInference.ts
54973
+ function extractFirstJson5(text) {
54656
54974
  const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
54657
54975
  if (fence) return fence[1];
54658
54976
  const start = text.indexOf("{");
@@ -54686,7 +55004,7 @@ ${rawText}`,
54686
55004
  }
54687
55005
  });
54688
55006
  const raw = (resp?.data?.content || resp?.output || "").trim();
54689
- const jsonText = extractFirstJson4(raw) || raw;
55007
+ const jsonText = extractFirstJson5(raw) || raw;
54690
55008
  let parsed = {};
54691
55009
  try {
54692
55010
  parsed = JSON.parse(jsonText);
@@ -54798,10 +55116,10 @@ function suggestName(fp, p) {
54798
55116
  const base = (fp.description || "file").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
54799
55117
  return base || "file";
54800
55118
  }
54801
- function guessKindByPath(path64) {
54802
- if (/__tests__|\.spec\.(t|j)sx?$|^tests\//.test(path64)) return "test";
54803
- if (/^docs\//.test(path64) || /\.md$/.test(path64)) return "doc";
54804
- if (/\.(json|cjs|js|ts)$/.test(path64) && !/src\//.test(path64)) return "config";
55119
+ function guessKindByPath(path65) {
55120
+ if (/__tests__|\.spec\.(t|j)sx?$|^tests\//.test(path65)) return "test";
55121
+ if (/^docs\//.test(path65) || /\.md$/.test(path65)) return "doc";
55122
+ if (/\.(json|cjs|js|ts)$/.test(path65) && !/src\//.test(path65)) return "config";
54805
55123
  return "source";
54806
55124
  }
54807
55125
  var init_PathInferencer = __esm({
@@ -55065,9 +55383,9 @@ function formatPlanAsDiff(files, opts) {
55065
55383
  function readCurrentFileSafe(root, rel, abs) {
55066
55384
  if (!root && !abs) return "";
55067
55385
  try {
55068
- const fs51 = __require("fs");
55386
+ const fs52 = __require("fs");
55069
55387
  const p = abs ? abs : __require("path").join(root, rel);
55070
- return fs51.existsSync(p) ? fs51.readFileSync(p, "utf8") : "";
55388
+ return fs52.existsSync(p) ? fs52.readFileSync(p, "utf8") : "";
55071
55389
  } catch {
55072
55390
  return "";
55073
55391
  }
@@ -55402,7 +55720,8 @@ async function listRepoFiles(root) {
55402
55720
  }
55403
55721
  for (const e2 of entries) {
55404
55722
  const name2 = e2.name;
55405
- if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === ".maria") continue;
55723
+ if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === ".maria" || // macOS system/hidden dirs that shouldn't be scanned
55724
+ name2 === ".DS_Store" || name2 === ".Spotlight-V100" || name2 === ".Trashes" || name2 === ".fseventsd" || name2 === ".TemporaryItems") continue;
55406
55725
  const full = path11__namespace.default.join(dir, name2);
55407
55726
  const rel = path11__namespace.default.relative(root, full).replace(/\\/g, "/");
55408
55727
  if (e2.isDirectory()) {
@@ -55655,6 +55974,60 @@ var Orchestrator_exports = {};
55655
55974
  __export(Orchestrator_exports, {
55656
55975
  orchestrate: () => orchestrate
55657
55976
  });
55977
+ async function getRepoFiles(root) {
55978
+ if (_repoFileIndexCache && _repoFileIndexCache.root === root) return _repoFileIndexCache.files;
55979
+ const fs52 = await import('fs/promises');
55980
+ const pathMod = await import('path');
55981
+ const ignoreDir = /* @__PURE__ */ new Set([
55982
+ ".git",
55983
+ "node_modules",
55984
+ "dist",
55985
+ "build",
55986
+ ".maria",
55987
+ ".next",
55988
+ "coverage",
55989
+ ".DS_Store",
55990
+ ".Spotlight-V100",
55991
+ ".Trashes",
55992
+ ".fseventsd",
55993
+ ".TemporaryItems"
55994
+ ]);
55995
+ const out = [];
55996
+ async function walk2(dir) {
55997
+ let entries = [];
55998
+ try {
55999
+ entries = await fs52.readdir(dir, { withFileTypes: true });
56000
+ } catch {
56001
+ return;
56002
+ }
56003
+ for (const e2 of entries) {
56004
+ const name2 = e2.name;
56005
+ if (ignoreDir.has(name2)) continue;
56006
+ const full = pathMod.join(dir, name2);
56007
+ if (e2.isDirectory()) {
56008
+ await walk2(full);
56009
+ continue;
56010
+ }
56011
+ out.push(pathMod.relative(root, full).replace(/\\/g, "/"));
56012
+ }
56013
+ }
56014
+ await walk2(root);
56015
+ _repoFileIndexCache = { root, files: out };
56016
+ return out;
56017
+ }
56018
+ function languageFromExt(ext2) {
56019
+ const e2 = ext2.toLowerCase().replace(/^\./, "");
56020
+ if (e2 === "ts") return "typescript";
56021
+ if (e2 === "tsx") return "tsx";
56022
+ if (e2 === "js" || e2 === "mjs" || e2 === "cjs") return "javascript";
56023
+ if (e2 === "jsx") return "jsx";
56024
+ if (e2 === "json") return "json";
56025
+ if (e2 === "html") return "html";
56026
+ if (e2 === "css" || e2 === "scss") return "css";
56027
+ if (e2 === "md") return "markdown";
56028
+ if (e2 === "yaml" || e2 === "yml") return "yaml";
56029
+ return void 0;
56030
+ }
55658
56031
  async function ensureCodeFallbackManager() {
55659
56032
  const policy = await loadFallbackPolicy().catch(() => getDefaultFallbackPolicy());
55660
56033
  const signature = JSON.stringify(policy);
@@ -55693,11 +56066,19 @@ async function orchestrate(request, opts) {
55693
56066
  explicitAbsMap[rel] = pathMod.join(opts.root, rel);
55694
56067
  }
55695
56068
  }
55696
- const isEditIntent = detectEditIntent(request, {
56069
+ const isEditIntent = await detectEditIntentEnhanced(opts.root, request, {
55697
56070
  hasAttachments: !!(opts.attachedFiles && opts.attachedFiles.length > 0),
55698
- explicitFilesCount: explicitFiles.length
55699
- });
55700
- const editContext = isEditIntent && explicitFiles.length > 0 ? await buildEditContext(opts.root, explicitFiles, 200, 512 * 1024) : "";
56071
+ explicitFiles});
56072
+ let editTargets = explicitFiles;
56073
+ if (isEditIntent && editTargets.length === 0) {
56074
+ try {
56075
+ const repoFiles = await getRepoFiles(opts.root);
56076
+ const likely = repoFiles.filter((p) => /\.(ts|tsx|js|jsx|html|css|scss|json|md)$/i.test(p));
56077
+ editTargets = likely.slice(0, 20);
56078
+ } catch {
56079
+ }
56080
+ }
56081
+ const editContext = isEditIntent && editTargets.length > 0 ? await buildEditContext(opts.root, editTargets, 200, 512 * 1024) : "";
55701
56082
  if (opts.attachedFiles && opts.attachedFiles.length > 0) {
55702
56083
  const mapRes = await mapAttachmentsToTargets(opts.attachedFiles, {
55703
56084
  root: opts.root,
@@ -55756,14 +56137,14 @@ ${editContext}`;
55756
56137
  const pathAttachments = [];
55757
56138
  if (explicitFiles.length > 0) {
55758
56139
  try {
55759
- const fs51 = await import('fs/promises');
56140
+ const fs52 = await import('fs/promises');
55760
56141
  const pathMod = await import('path');
55761
56142
  for (const rel of explicitFiles) {
55762
56143
  try {
55763
56144
  const full = explicitAbsMap[rel] || pathMod.join(opts.root, rel);
55764
- const stat13 = await fs51.stat(full).catch(() => null);
56145
+ const stat13 = await fs52.stat(full).catch(() => null);
55765
56146
  if (!stat13 || !stat13.isFile()) continue;
55766
- const buf = await fs51.readFile(full);
56147
+ const buf = await fs52.readFile(full);
55767
56148
  const ext2 = (pathMod.extname(full) || "").toLowerCase();
55768
56149
  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";
55769
56150
  pathAttachments.push({
@@ -55781,7 +56162,7 @@ ${editContext}`;
55781
56162
  const hydratedCtx = [];
55782
56163
  if (ctxAttachments.length > 0) {
55783
56164
  try {
55784
- const fs51 = await import('fs/promises');
56165
+ const fs52 = await import('fs/promises');
55785
56166
  for (const a of ctxAttachments) {
55786
56167
  if (a.data_base64) {
55787
56168
  hydratedCtx.push(a);
@@ -55792,12 +56173,12 @@ ${editContext}`;
55792
56173
  continue;
55793
56174
  }
55794
56175
  try {
55795
- const stat13 = await fs51.stat(p).catch(() => null);
56176
+ const stat13 = await fs52.stat(p).catch(() => null);
55796
56177
  if (!stat13 || !stat13.isFile()) {
55797
56178
  hydratedCtx.push(a);
55798
56179
  continue;
55799
56180
  }
55800
- const buf = await fs51.readFile(p);
56181
+ const buf = await fs52.readFile(p);
55801
56182
  hydratedCtx.push({ ...a, data_base64: buf.toString("base64") });
55802
56183
  } catch {
55803
56184
  hydratedCtx.push(a);
@@ -55847,40 +56228,44 @@ ${editContext}`;
55847
56228
  codeOutput = outcome.data?.output || "";
55848
56229
  }
55849
56230
  const blocks = extractBlocks(codeOutput);
55850
- if (explicitFiles.length > 0) {
56231
+ if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
55851
56232
  const mapped = /* @__PURE__ */ new Set();
56233
+ const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
56234
+ const absMap = explicitFiles.length > 0 ? explicitAbsMap : /* @__PURE__ */ Object.create(null);
55852
56235
  const htmlIdx = blocks.findIndex((b) => /html/i.test(b.language));
55853
- const htmlFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".html"));
56236
+ const htmlFile = targets.find((f3) => f3.toLowerCase().endsWith(".html"));
55854
56237
  if (htmlIdx >= 0 && htmlFile) {
55855
- initial.push({ path: htmlFile, absPath: explicitAbsMap[htmlFile], noNormalize: true, kind: "source", action: "create", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
56238
+ initial.push({ path: htmlFile, absPath: absMap[htmlFile], noNormalize: true, kind: "source", action: "modify", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
55856
56239
  mapped.add(htmlFile);
55857
56240
  }
55858
56241
  const jsIdx = blocks.findIndex((b) => /(ts|tsx|jsx|javascript|js)/i.test(b.language));
55859
- const jsFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".js"));
56242
+ const jsFile = targets.find((f3) => f3.toLowerCase().endsWith(".js"));
55860
56243
  if (jsIdx >= 0 && jsFile && !mapped.has(jsFile)) {
55861
- initial.push({ path: jsFile, absPath: explicitAbsMap[jsFile], noNormalize: true, kind: "source", action: "create", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
56244
+ initial.push({ path: jsFile, absPath: absMap[jsFile], noNormalize: true, kind: "source", action: "modify", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
55862
56245
  mapped.add(jsFile);
55863
56246
  }
55864
56247
  const cssIdx = blocks.findIndex((b) => /css/i.test(b.language));
55865
- const cssFile = explicitFiles.find((f3) => f3.toLowerCase().endsWith(".css"));
56248
+ const cssFile = targets.find((f3) => f3.toLowerCase().endsWith(".css"));
55866
56249
  if (cssIdx >= 0 && cssFile && !mapped.has(cssFile)) {
55867
- initial.push({ path: cssFile, absPath: explicitAbsMap[cssFile], noNormalize: true, kind: "source", action: "create", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
56250
+ initial.push({ path: cssFile, absPath: absMap[cssFile], noNormalize: true, kind: "source", action: "modify", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
55868
56251
  mapped.add(cssFile);
55869
56252
  }
55870
- for (const f3 of explicitFiles) {
56253
+ for (const f3 of targets) {
55871
56254
  if (mapped.has(f3)) continue;
55872
- const plan = scaffoldForFilename(f3, explicitFiles);
55873
- plan.absPath = explicitAbsMap[f3];
55874
- plan.noNormalize = true;
55875
- initial.push(plan);
56255
+ const ext2 = (() => {
56256
+ const m2 = f3.lastIndexOf(".");
56257
+ return m2 >= 0 ? f3.slice(m2) : "";
56258
+ })();
56259
+ const lang = languageFromExt(ext2);
56260
+ initial.push({ path: f3, absPath: absMap[f3], noNormalize: true, kind: "source", action: "modify", description: "Edit target", language: lang, preview: "" });
55876
56261
  }
55877
56262
  } else {
55878
56263
  for (let i2 = 0; i2 < blocks.length; i2++) {
55879
56264
  const b = blocks[i2];
55880
56265
  const desired = typeof b.filename === "string" && b.filename.trim() ? b.filename.trim() : null;
55881
- const path64 = desired || suggestName2(request, b.language, i2);
56266
+ const path65 = desired || suggestName2(request, b.language, i2);
55882
56267
  initial.push({
55883
- path: path64,
56268
+ path: path65,
55884
56269
  kind: "source",
55885
56270
  action: "create",
55886
56271
  description: describe2(b.language, ""),
@@ -55911,13 +56296,13 @@ ${editContext}`;
55911
56296
  { root: opts.root }
55912
56297
  );
55913
56298
  try {
55914
- const [{ access: access18 }, path64] = await Promise.all([
56299
+ const [{ access: access18 }, path65] = await Promise.all([
55915
56300
  import('fs/promises'),
55916
56301
  import('path')
55917
56302
  ]);
55918
56303
  for (const p of normalized) {
55919
56304
  try {
55920
- const absCandidate = p.absPath ? p.absPath : path64.join(opts.root, p.path);
56305
+ const absCandidate = p.absPath ? p.absPath : path65.join(opts.root, p.path);
55921
56306
  await access18(absCandidate);
55922
56307
  p.action = "modify";
55923
56308
  if (isEditIntent) {
@@ -56155,12 +56540,12 @@ function languageExt(lang) {
56155
56540
  }
56156
56541
  async function journalResume(root, request, files) {
56157
56542
  try {
56158
- const fs51 = await import('fs/promises');
56543
+ const fs52 = await import('fs/promises');
56159
56544
  const dir = path11__namespace.default.join(root, ".maria", "memory");
56160
- await fs51.mkdir(dir, { recursive: true });
56545
+ await fs52.mkdir(dir, { recursive: true });
56161
56546
  const out = path11__namespace.default.join(dir, "resume-plan.json");
56162
56547
  const payload = { request, createdAt: (/* @__PURE__ */ new Date()).toISOString(), files };
56163
- await fs51.writeFile(out, JSON.stringify(payload, null, 2), "utf8");
56548
+ await fs52.writeFile(out, JSON.stringify(payload, null, 2), "utf8");
56164
56549
  } catch {
56165
56550
  }
56166
56551
  }
@@ -56288,6 +56673,68 @@ function detectEditIntent(request, ctx2) {
56288
56673
  const mentionsEdit = editKeywords.some((k) => r2.includes(k));
56289
56674
  return ctx2.hasAttachments || ctx2.explicitFilesCount > 0 || mentionsEdit;
56290
56675
  }
56676
+ async function detectEditIntentEnhanced(root, request, ctx2) {
56677
+ const baseline = detectEditIntent(request, { hasAttachments: ctx2.hasAttachments, explicitFilesCount: ctx2.explicitFiles.length });
56678
+ if (baseline) return true;
56679
+ const r2 = request.toLowerCase();
56680
+ const softHints = ["improve", "enhance", "make it", "change the", "adjust", "tweak", "rework", "revamp", "retro", "modernize", "clean up", "polish"];
56681
+ const hasSoftHint = softHints.some((k) => r2.includes(k));
56682
+ if (!hasSoftHint) return false;
56683
+ try {
56684
+ const fs52 = await import('fs/promises');
56685
+ const pathMod = await import('path');
56686
+ const { loadGlobby: loadGlobby2 } = await Promise.resolve().then(() => (init_esm_compat(), esm_compat_exports));
56687
+ const globby = await loadGlobby2();
56688
+ const ignore = [
56689
+ "**/node_modules/**",
56690
+ "**/.git/**",
56691
+ "**/dist/**",
56692
+ "**/build/**",
56693
+ "**/.maria/**",
56694
+ "**/.next/**",
56695
+ "**/coverage/**",
56696
+ "**/.DS_Store/**",
56697
+ "**/.DS_Store",
56698
+ "**/.Spotlight-V100/**",
56699
+ "**/.Spotlight-V100",
56700
+ "**/.Trashes/**",
56701
+ "**/.Trashes",
56702
+ "**/.fseventsd/**",
56703
+ "**/.fseventsd",
56704
+ "**/.TemporaryItems/**",
56705
+ "**/.TemporaryItems"
56706
+ ];
56707
+ const candidates = await globby(["**/*.{html,css,js,ts,tsx}"], { cwd: root, absolute: true, gitignore: true, ignore, deep: 3 });
56708
+ if (candidates && candidates.length > 0) return true;
56709
+ } catch {
56710
+ }
56711
+ try {
56712
+ const short = request.trim().length <= 160;
56713
+ if (!short) return false;
56714
+ const system = [
56715
+ "You are classifying whether the user intends to EDIT existing files vs CREATE a new project.",
56716
+ 'Return JSON: { "edit": true|false } only.'
56717
+ ].join("\n");
56718
+ const user = `Instruction: ${request}`;
56719
+ const resp = await executeChat([
56720
+ { role: "system", content: system },
56721
+ { role: "user", content: user }
56722
+ ]);
56723
+ const raw = (resp?.output || "").trim();
56724
+ const jsonText = (() => {
56725
+ try {
56726
+ const m2 = raw.match(/\{[\s\S]*\}/);
56727
+ return m2 ? m2[0] : raw;
56728
+ } catch {
56729
+ return raw;
56730
+ }
56731
+ })();
56732
+ const parsed = JSON.parse(jsonText);
56733
+ if (typeof parsed?.edit === "boolean") return !!parsed.edit;
56734
+ } catch {
56735
+ }
56736
+ return false;
56737
+ }
56291
56738
  function sanitizeFolderName(name2) {
56292
56739
  const base = name2.toLowerCase().replace(/[`~!@#$%^&*()+=\[\]{}|;:'",<>/?\\]/g, " ").replace(/\s+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
56293
56740
  return base || "project";
@@ -56320,14 +56767,14 @@ async function ensureTopFolder(root, proposed, plans) {
56320
56767
  return { folderName: unique };
56321
56768
  }
56322
56769
  async function ensureUniqueFolder(root, base) {
56323
- const fs51 = await import('fs/promises');
56770
+ const fs52 = await import('fs/promises');
56324
56771
  const pathMod = await import('path');
56325
56772
  let name2 = sanitizeFolderName(base);
56326
56773
  let suffix = 0;
56327
56774
  for (; suffix < Number.MAX_SAFE_INTEGER; ) {
56328
56775
  const candidate = suffix === 0 ? name2 : `${name2}-${String(suffix).padStart(2, "0")}`;
56329
56776
  try {
56330
- await fs51.access(pathMod.join(root, candidate));
56777
+ await fs52.access(pathMod.join(root, candidate));
56331
56778
  suffix += 1;
56332
56779
  } catch {
56333
56780
  return candidate;
@@ -56337,13 +56784,13 @@ async function ensureUniqueFolder(root, base) {
56337
56784
  }
56338
56785
  async function buildEditContext(root, files, maxLines, maxBytes) {
56339
56786
  try {
56340
- const fs51 = await import('fs/promises');
56787
+ const fs52 = await import('fs/promises');
56341
56788
  const pathMod = await import('path');
56342
56789
  const sections = [];
56343
56790
  for (const rel of files) {
56344
56791
  const full = pathMod.join(root, rel);
56345
56792
  try {
56346
- const buf = await fs51.readFile(full);
56793
+ const buf = await fs52.readFile(full);
56347
56794
  const clipped = buf.length > maxBytes ? buf.subarray(0, maxBytes) : buf;
56348
56795
  const text = clipped.toString("utf8").replace(/\r\n/g, "\n");
56349
56796
  const lines = text.split("\n").slice(0, maxLines).join("\n");
@@ -56360,84 +56807,58 @@ ${lines}
56360
56807
  }
56361
56808
  }
56362
56809
  async function resolveExplicitPaths(root, files, hintText) {
56363
- const fs51 = await import('fs/promises');
56810
+ const fs52 = await import('fs/promises');
56364
56811
  const pathMod = await import('path');
56365
- const { loadGlobby: loadGlobby2 } = await Promise.resolve().then(() => (init_esm_compat(), esm_compat_exports));
56366
- const globby = await loadGlobby2();
56367
- const ignore = [
56368
- "**/node_modules/**",
56369
- "**/.git/**",
56370
- "**/dist/**",
56371
- "**/build/**",
56372
- "**/.maria/**",
56373
- "**/.next/**",
56374
- "**/coverage/**"
56375
- ];
56376
- const hintTokens = Array.from(new Set(hintText.toLowerCase().replace(/[^a-z0-9_/.-]+/g, " ").split(/\s+/).filter(Boolean)));
56377
- async function findBest(rel) {
56378
- const normalized = rel.replace(/^\/+/, "").replace(/\\/g, "/");
56379
- const fullExact = pathMod.join(root, normalized);
56380
- try {
56381
- await fs51.access(fullExact);
56382
- return normalized;
56383
- } catch {
56812
+ const ignoreDir = /* @__PURE__ */ new Set([
56813
+ ".git",
56814
+ "node_modules",
56815
+ "dist",
56816
+ "build",
56817
+ ".maria",
56818
+ ".next",
56819
+ "coverage",
56820
+ ".DS_Store",
56821
+ ".Spotlight-V100",
56822
+ ".Trashes",
56823
+ ".fseventsd",
56824
+ ".TemporaryItems"
56825
+ ]);
56826
+ async function buildRepoIndex() {
56827
+ if (_repoFileIndexCache && _repoFileIndexCache.root === root) return _repoFileIndexCache.files;
56828
+ const out2 = [];
56829
+ async function walk2(dir) {
56830
+ let entries = [];
56831
+ try {
56832
+ entries = await fs52.readdir(dir, { withFileTypes: true });
56833
+ } catch {
56834
+ return;
56835
+ }
56836
+ for (const e2 of entries) {
56837
+ const name2 = e2.name;
56838
+ if (ignoreDir.has(name2)) continue;
56839
+ const full = pathMod.join(dir, name2);
56840
+ if (e2.isDirectory()) {
56841
+ await walk2(full);
56842
+ continue;
56843
+ }
56844
+ out2.push(pathMod.relative(root, full).replace(/\\/g, "/"));
56845
+ }
56384
56846
  }
56847
+ await walk2(root);
56848
+ _repoFileIndexCache = { root, files: out2 };
56849
+ return out2;
56850
+ }
56851
+ const allFiles = await buildRepoIndex();
56852
+ const hintTokens = Array.from(new Set(hintText.toLowerCase().replace(/[^a-z0-9_/.-]+/g, " ").split(/\s+/).filter(Boolean)));
56853
+ async function rankCandidates(candidates, desired) {
56854
+ const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
56385
56855
  const lowerRel = normalized.toLowerCase();
56386
56856
  const ext2 = (pathMod.extname(normalized) || "").toLowerCase();
56387
56857
  const base = pathMod.basename(normalized);
56388
- const nameNoExt = base.replace(/\.[^.]+$/, "").toLowerCase();
56858
+ base.replace(/\.[^.]+$/, "").toLowerCase();
56389
56859
  const parentPath = pathMod.dirname(normalized);
56390
56860
  const parent = parentPath.split("/").pop() || "";
56391
56861
  const dirParts = parentPath === "." ? [] : parentPath.split("/").filter(Boolean).map((s2) => s2.toLowerCase());
56392
- const patterns = [];
56393
- patterns.push(`**/${normalized}`);
56394
- if (parent && parent !== "." && parent !== "/") patterns.push(`**/${parent}/${base}`);
56395
- if (base) patterns.push(`**/${base}`);
56396
- patterns.push(`**/*${base}`);
56397
- if (!ext2) {
56398
- patterns.push(`**/${nameNoExt}.*`);
56399
- }
56400
- const uniqPatterns = Array.from(new Set(patterns));
56401
- const candidatesSet = /* @__PURE__ */ new Set();
56402
- for (const pat of uniqPatterns) {
56403
- const found = await globby(pat, { cwd: root, absolute: false, gitignore: true, ignore });
56404
- for (const f3 of found) {
56405
- candidatesSet.add(f3.replace(/\\/g, "/"));
56406
- }
56407
- if (candidatesSet.size > 200) break;
56408
- }
56409
- let candidates = Array.from(candidatesSet);
56410
- if (dirParts.length > 0) {
56411
- const filtered = candidates.filter((relp) => {
56412
- const segs = relp.toLowerCase().split("/");
56413
- let pos = -1;
56414
- for (const part of dirParts) {
56415
- const next = segs.indexOf(part, pos + 1);
56416
- if (next === -1) return false;
56417
- pos = next;
56418
- }
56419
- return true;
56420
- });
56421
- if (filtered.length > 0) candidates = filtered;
56422
- }
56423
- if (candidates.length === 0) {
56424
- const prefixes = ["", "src/", "app/", "pages/"];
56425
- for (const pre of prefixes) {
56426
- const cand = pathMod.join(root, pre + normalized);
56427
- try {
56428
- await fs51.access(cand);
56429
- return (pre + normalized).replace(/^\/+/, "");
56430
- } catch {
56431
- }
56432
- }
56433
- if (dirParts.length > 0) {
56434
- if (/^(src|app|pages)\//i.test(normalized)) return normalized;
56435
- const pref = await pickExistingFolderPrefix(root, parentPath);
56436
- const combined = (pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1");
56437
- return combined;
56438
- }
56439
- return normalized.replace(/^(src\/)src\//i, "$1");
56440
- }
56441
56862
  function score(relPath) {
56442
56863
  const lower2 = relPath.toLowerCase();
56443
56864
  let s2 = 0;
@@ -56461,10 +56882,36 @@ async function resolveExplicitPaths(root, files, hintText) {
56461
56882
  s2 -= Math.min(10, Math.floor(relPath.length / 80));
56462
56883
  return s2;
56463
56884
  }
56464
- let best = candidates[0];
56885
+ const limited = candidates.slice(0, Math.min(50, candidates.length));
56886
+ if (limited.length > 1) {
56887
+ try {
56888
+ const ranked = limited.map((p) => ({ p, s: score(p) })).sort((a, b) => b.s - a.s).slice(0, 5).map((x2) => x2.p);
56889
+ const system = [
56890
+ "You are helping choose the most relevant target file path for an edit operation.",
56891
+ "Given a user request and several candidate repo-relative paths, pick ONE best path.",
56892
+ "Return ONLY the raw path text. No code blocks. No explanations."
56893
+ ].join("\n");
56894
+ const user = [
56895
+ `User request: ${hintText}`,
56896
+ "Candidates:",
56897
+ ...ranked.map((r2, i2) => `${i2 + 1}. ${r2}`),
56898
+ "",
56899
+ "Answer with exactly one of the candidate paths."
56900
+ ].join("\n");
56901
+ const chat = await executeChat([
56902
+ { role: "system", content: system },
56903
+ { role: "user", content: user }
56904
+ ]);
56905
+ const raw = (chat.output || "").trim();
56906
+ const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
56907
+ return pick.replace(/^\/+/, "");
56908
+ } catch {
56909
+ }
56910
+ }
56911
+ let best = limited[0];
56465
56912
  let bestScore = score(best);
56466
- for (let i2 = 1; i2 < candidates.length; i2++) {
56467
- const c = candidates[i2];
56913
+ for (let i2 = 1; i2 < limited.length; i2++) {
56914
+ const c = limited[i2];
56468
56915
  const sc = score(c);
56469
56916
  if (sc > bestScore) {
56470
56917
  best = c;
@@ -56474,20 +56921,41 @@ async function resolveExplicitPaths(root, files, hintText) {
56474
56921
  return best.replace(/^\/+/, "");
56475
56922
  }
56476
56923
  const out = [];
56477
- for (const f3 of files) {
56478
- out.push(await findBest(f3));
56924
+ for (const desired of files) {
56925
+ const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
56926
+ if (allFiles.includes(normalized)) {
56927
+ out.push(normalized);
56928
+ continue;
56929
+ }
56930
+ const base = pathMod.basename(normalized).toLowerCase();
56931
+ const nameNoExt = base.replace(/\.[^.]+$/, "");
56932
+ const candidates = allFiles.filter((p) => {
56933
+ const b = pathMod.basename(p).toLowerCase();
56934
+ return b === base || b.includes(base) || !base.includes(".") && (b === `${nameNoExt}.ts` || b === `${nameNoExt}.js` || b.startsWith(nameNoExt));
56935
+ });
56936
+ if (candidates.length === 0) {
56937
+ const parentPath = pathMod.dirname(normalized);
56938
+ if (parentPath && parentPath !== ".") {
56939
+ const pref = await pickExistingFolderPrefix(root, parentPath);
56940
+ out.push((pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1"));
56941
+ } else {
56942
+ out.push(normalized.replace(/^(src\/)src\//i, "$1"));
56943
+ }
56944
+ continue;
56945
+ }
56946
+ out.push(await rankCandidates(candidates, normalized));
56479
56947
  }
56480
56948
  return out;
56481
56949
  }
56482
56950
  async function pickExistingFolderPrefix(root, parentPath) {
56483
- const fs51 = await import('fs/promises');
56951
+ const fs52 = await import('fs/promises');
56484
56952
  const pathMod = await import('path');
56485
56953
  const parts = parentPath.replace(/^\/+/, "").split("/").filter(Boolean);
56486
56954
  const prefixes = ["src", "app", "pages", ""];
56487
56955
  for (const pre of prefixes) {
56488
56956
  const test = pre ? pathMod.join(root, pre, ...parts) : pathMod.join(root, ...parts);
56489
56957
  try {
56490
- await fs51.access(test);
56958
+ await fs52.access(test);
56491
56959
  return pre ? `${pre}/` : "";
56492
56960
  } catch {
56493
56961
  }
@@ -56534,7 +57002,7 @@ requestAnimationFrame(step);`;
56534
57002
  }
56535
57003
  return { path: filename, kind: "source", action: "create", description: "Source file", preview: "" };
56536
57004
  }
56537
- var codeFallbackManager, codeFallbackPolicySignature;
57005
+ var codeFallbackManager, _repoFileIndexCache, codeFallbackPolicySignature;
56538
57006
  var init_Orchestrator = __esm({
56539
57007
  "src/services/code-orchestrator/Orchestrator.ts"() {
56540
57008
  init_RepoScanner();
@@ -56549,6 +57017,7 @@ var init_Orchestrator = __esm({
56549
57017
  init_FallbackManager();
56550
57018
  init_policy();
56551
57019
  codeFallbackManager = null;
57020
+ _repoFileIndexCache = null;
56552
57021
  codeFallbackPolicySignature = null;
56553
57022
  }
56554
57023
  });
@@ -56661,8 +57130,8 @@ var init_code_command = __esm({
56661
57130
  try {
56662
57131
  const res = await orchestrate2(request, { root, flags: { planOnly: opts.planOnly, apply: opts.apply, dryRun: opts.dryRun, interactive: opts.interactive, yes: opts.yes, maxFiles: opts.maxFiles, output: opts.output, hideCode: opts.noCode, previewLines: this.normalizePreviewLines(opts.previewLines), verbose: opts.verbose, onlyAttached: opts.onlyAttached, attachMode: opts.attachMode, maxAttachments: opts.maxAttachments, diffLines: opts.diffLines, diffBytes: opts.diffBytes, diffHunks: opts.diffHunks, diffGlobalMaxFiles: opts.diffGlobalMaxFiles, diffGlobalMaxBytes: opts.diffGlobalMaxBytes, allowDotfiles: opts.allowDotfiles }, abortSignal: abort.signal, attachedFiles: attachments });
56663
57132
  if (opts.planOnly) {
56664
- const fs51 = await import('fs/promises');
56665
- const path64 = await import('path');
57133
+ const fs52 = await import('fs/promises');
57134
+ const path65 = await import('path');
56666
57135
  const spec = res?.specMarkdown;
56667
57136
  const lines = Array.isArray(res?.summaryLines) ? res.summaryLines : [];
56668
57137
  const planItems = [];
@@ -56696,13 +57165,13 @@ var init_code_command = __esm({
56696
57165
  if (planItems.length) md.push(...planItems);
56697
57166
  else md.push("- (no summary available)");
56698
57167
  }
56699
- const plansDir = path64.join(root, ".maria", "plans");
56700
- await fs51.mkdir(plansDir, { recursive: true });
57168
+ const plansDir = path65.join(root, ".maria", "plans");
57169
+ await fs52.mkdir(plansDir, { recursive: true });
56701
57170
  const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
56702
57171
  const fileName = `code-plan-${ts}.md`;
56703
- const outPath = path64.join(plansDir, fileName);
56704
- await fs51.writeFile(outPath, md.join("\n") + "\n", "utf8");
56705
- const rel = path64.relative(root, outPath);
57172
+ const outPath = path65.join(plansDir, fileName);
57173
+ await fs52.writeFile(outPath, md.join("\n") + "\n", "utf8");
57174
+ const rel = path65.relative(root, outPath);
56706
57175
  return this.success(`Code plan saved: ${rel}`);
56707
57176
  }
56708
57177
  const detail = res?.detailLines;
@@ -56762,6 +57231,97 @@ ${pretty}`);
56762
57231
  // Add default language hints when not specified by the user (LLM-assisted detection)
56763
57232
  async ensureLanguageDefaults(raw) {
56764
57233
  try {
57234
+ const fs52 = await import('fs/promises');
57235
+ const pathMod = await import('path');
57236
+ const cwd2 = process.cwd();
57237
+ const ignoreDir = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".maria", ".next", "coverage", ".DS_Store", ".Spotlight-V100", ".Trashes", ".fseventsd", ".TemporaryItems"]);
57238
+ const pathTokens = /* @__PURE__ */ new Set();
57239
+ const fileLike = raw.match(/([\w\-./\\:]+\.[A-Za-z0-9]{1,10})/g) || [];
57240
+ for (const t2 of fileLike) pathTokens.add(t2);
57241
+ const slashLike = raw.match(/[^\s"']*[\\/][^\s"']+/g) || [];
57242
+ for (const t2 of slashLike) pathTokens.add(t2);
57243
+ const listFilesUnder = async (dir, maxCount) => {
57244
+ const out = [];
57245
+ const walk2 = async (d) => {
57246
+ if (out.length >= maxCount) return;
57247
+ let entries = [];
57248
+ try {
57249
+ entries = await fs52.readdir(d, { withFileTypes: true });
57250
+ } catch {
57251
+ return;
57252
+ }
57253
+ for (const e2 of entries) {
57254
+ const name2 = e2.name;
57255
+ if (ignoreDir.has(name2)) continue;
57256
+ const full = pathMod.join(d, name2);
57257
+ if (e2.isDirectory()) {
57258
+ await walk2(full);
57259
+ if (out.length >= maxCount) break;
57260
+ continue;
57261
+ }
57262
+ if (/\.(ts|tsx|js|jsx|py|java|kt|go|rs|rb|swift|cs|c|cpp|hpp|php|scala|hs|ex|exs|dart|lua|zig|sol|sql|html|css|scss|md|json)$/i.test(name2)) {
57263
+ out.push(full);
57264
+ if (out.length >= maxCount) break;
57265
+ }
57266
+ }
57267
+ };
57268
+ await walk2(dir);
57269
+ return out;
57270
+ };
57271
+ const readHead = async (full, lines) => {
57272
+ try {
57273
+ const buf = await fs52.readFile(full, "utf8");
57274
+ return buf.split(/\r?\n/).slice(0, lines).join("\n");
57275
+ } catch {
57276
+ return "";
57277
+ }
57278
+ };
57279
+ const samples = [];
57280
+ for (const tok of Array.from(pathTokens)) {
57281
+ const abs = pathMod.isAbsolute(tok) ? tok : pathMod.join(cwd2, tok);
57282
+ try {
57283
+ const st = await fs52.stat(abs);
57284
+ if (st.isFile()) {
57285
+ samples.push(await readHead(abs, 10));
57286
+ } else if (st.isDirectory()) {
57287
+ const files = await listFilesUnder(abs, 25);
57288
+ for (const f3 of files) samples.push(await readHead(f3, 10));
57289
+ }
57290
+ } catch {
57291
+ }
57292
+ if (samples.length >= 50) break;
57293
+ }
57294
+ if (samples.length > 0) {
57295
+ const preSpin = new ProcessAnimation();
57296
+ preSpin.start();
57297
+ let llmLang = null;
57298
+ try {
57299
+ llmLang = await this.detectLanguageLLMFromSamples(samples);
57300
+ } finally {
57301
+ try {
57302
+ preSpin.stop();
57303
+ } catch {
57304
+ }
57305
+ }
57306
+ if (llmLang) {
57307
+ const hint2 = (() => {
57308
+ const l = llmLang.toLowerCase();
57309
+ if (l === "tsx") return "TypeScript (React/TSX)";
57310
+ if (l === "jsx") return "JavaScript (React/JSX)";
57311
+ if (l === "typescript") return "TypeScript";
57312
+ if (l === "javascript") return "JavaScript";
57313
+ if (l === "html") return "HTML";
57314
+ if (l === "css") return "CSS";
57315
+ return llmLang;
57316
+ })();
57317
+ return raw + ` (Use ${hint2})`;
57318
+ }
57319
+ }
57320
+ } catch {
57321
+ }
57322
+ try {
57323
+ const preSpin = new ProcessAnimation();
57324
+ preSpin.start();
56765
57325
  const system = [
56766
57326
  "You analyze a user's code-generation request.",
56767
57327
  "Decide if the user explicitly specified a programming language or framework/tooling (e.g., TypeScript, Python, Rust, Java, React, Vue, Node, etc.).",
@@ -56780,8 +57340,12 @@ ${pretty}`);
56780
57340
  ${user}`
56781
57341
  }
56782
57342
  });
57343
+ try {
57344
+ preSpin.stop();
57345
+ } catch {
57346
+ }
56783
57347
  const content = (resp?.data?.content || resp?.content || "").trim();
56784
- const extractFirstJson6 = (text) => {
57348
+ const extractFirstJson7 = (text) => {
56785
57349
  const fence = /```\s*json\s*\r?\n([\s\S]*?)```/i.exec(text);
56786
57350
  if (fence) return fence[1];
56787
57351
  const generic = /```\s*\r?\n([\s\S]*?)```/i.exec(text);
@@ -56804,7 +57368,7 @@ ${user}`
56804
57368
  }
56805
57369
  return null;
56806
57370
  };
56807
- const jsonText = extractFirstJson6(content) || content;
57371
+ const jsonText = extractFirstJson7(content) || content;
56808
57372
  let parsed = {};
56809
57373
  try {
56810
57374
  parsed = JSON.parse(jsonText);
@@ -56817,6 +57381,76 @@ ${user}`
56817
57381
  const hint = " (Use TypeScript and React; prefer functional components and node)";
56818
57382
  return raw + hint;
56819
57383
  }
57384
+ // LLM-based language detection from sample code heads (top-10 lines per file)
57385
+ async detectLanguageLLMFromSamples(samples) {
57386
+ try {
57387
+ const system = [
57388
+ "You are a programming language classifier.",
57389
+ "Given multiple short code excerpts, determine the dominant language across them.",
57390
+ "Respond with ONLY a single token language name from this set:",
57391
+ "[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
57392
+ "If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
57393
+ ].join("\n");
57394
+ const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
57395
+ ${s2}`).join("\n\n");
57396
+ const { callAPI: callAPI2 } = await Promise.resolve().then(() => (init_api_caller(), api_caller_exports));
57397
+ const resp = await callAPI2("/v1/ai-proxy", {
57398
+ method: "POST",
57399
+ body: {
57400
+ provider: "google",
57401
+ model: "gemini-2.5-flash",
57402
+ taskType: "chat",
57403
+ prompt: `${system}
57404
+
57405
+ ${joined}`
57406
+ }
57407
+ });
57408
+ const content = (resp?.data?.content || resp?.content || "").trim();
57409
+ const token = content.replace(/```[\s\S]*?```/g, "").trim().toLowerCase();
57410
+ const norm = this.normalizeLanguageName(token);
57411
+ return norm || null;
57412
+ } catch {
57413
+ return null;
57414
+ }
57415
+ }
57416
+ normalizeLanguageName(lang) {
57417
+ const l = (lang || "").toLowerCase().trim();
57418
+ if (!l) return null;
57419
+ const map = {
57420
+ "ts": "typescript",
57421
+ "typescript": "typescript",
57422
+ "tsx": "tsx",
57423
+ "jsx": "jsx",
57424
+ "js": "javascript",
57425
+ "javascript": "javascript",
57426
+ "py": "python",
57427
+ "python": "python",
57428
+ "java": "java",
57429
+ "go": "go",
57430
+ "rust": "rust",
57431
+ "rs": "rust",
57432
+ "php": "php",
57433
+ "c++": "cpp",
57434
+ "cpp": "cpp",
57435
+ "c": "c",
57436
+ "swift": "swift",
57437
+ "kotlin": "kotlin",
57438
+ "rb": "ruby",
57439
+ "ruby": "ruby",
57440
+ "cs": "csharp",
57441
+ "c#": "csharp",
57442
+ "csharp": "csharp",
57443
+ "html": "html",
57444
+ "css": "css",
57445
+ "scss": "scss",
57446
+ "json": "json",
57447
+ "yaml": "yaml",
57448
+ "yml": "yaml",
57449
+ "markdown": "markdown",
57450
+ "md": "markdown"
57451
+ };
57452
+ return map[l] || null;
57453
+ }
56820
57454
  // v2.0 helpers
56821
57455
  parseV2Options(raw) {
56822
57456
  const opts = { planOnly: false, apply: false, dryRun: false, interactive: false, yes: false, rollback: true, output: void 0, noCode: false, previewLines: 0, root: void 0, maxFiles: void 0, verbose: false, gitGuard: void 0, allowDotfiles: false, confirmOverwrites: [], gitCommit: void 0, gitBranch: void 0, gitTag: void 0, gitTagPrefix: void 0, gitPush: void 0, gitPushRemote: void 0, onlyAttached: false, attachMode: "assist", maxAttachments: 50, diffLines: void 0, diffBytes: void 0, diffHunks: void 0, diffGlobalMaxFiles: void 0, diffGlobalMaxBytes: void 0 };
@@ -57012,16 +57646,16 @@ ${user}`
57012
57646
  }
57013
57647
  async persistLastPlan(root, plans) {
57014
57648
  try {
57015
- const fs51 = await import('fs/promises');
57649
+ const fs52 = await import('fs/promises');
57016
57650
  const p = path11__namespace.join(root, ".maria");
57017
- await fs51.mkdir(p, { recursive: true });
57651
+ await fs52.mkdir(p, { recursive: true });
57018
57652
  const out = path11__namespace.join(p, "last-plan.json");
57019
- await fs51.writeFile(out, JSON.stringify({ createdAt: (/* @__PURE__ */ new Date()).toISOString(), plans }, null, 2), "utf8");
57653
+ await fs52.writeFile(out, JSON.stringify({ createdAt: (/* @__PURE__ */ new Date()).toISOString(), plans }, null, 2), "utf8");
57020
57654
  } catch {
57021
57655
  }
57022
57656
  }
57023
57657
  async applyPlan(plans, options) {
57024
- const fs51 = await import('fs/promises');
57658
+ const fs52 = await import('fs/promises');
57025
57659
  const created = [];
57026
57660
  const modified = [];
57027
57661
  const skipped = [];
@@ -57040,9 +57674,9 @@ ${user}`
57040
57674
  continue;
57041
57675
  }
57042
57676
  const tmp = full + `.tmp-${process.pid}-${Date.now()}`;
57043
- await fs51.mkdir(path11__namespace.dirname(full), { recursive: true });
57044
- await fs51.writeFile(tmp, plan.preview || "", "utf8");
57045
- await fs51.rename(tmp, full);
57677
+ await fs52.mkdir(path11__namespace.dirname(full), { recursive: true });
57678
+ await fs52.writeFile(tmp, plan.preview || "", "utf8");
57679
+ await fs52.rename(tmp, full);
57046
57680
  if (exists2) modified.push(plan.path);
57047
57681
  else created.push(plan.path);
57048
57682
  written++;
@@ -57053,7 +57687,7 @@ ${user}`
57053
57687
  if (options.rollback) {
57054
57688
  for (const p of [...created, ...modified]) {
57055
57689
  try {
57056
- await fs51.unlink(path11__namespace.join(options.root, p));
57690
+ await fs52.unlink(path11__namespace.join(options.root, p));
57057
57691
  } catch {
57058
57692
  }
57059
57693
  }
@@ -57063,8 +57697,8 @@ ${user}`
57063
57697
  }
57064
57698
  async pathExists(p) {
57065
57699
  try {
57066
- const fs51 = await import('fs/promises');
57067
- await fs51.access(p);
57700
+ const fs52 = await import('fs/promises');
57701
+ await fs52.access(p);
57068
57702
  return true;
57069
57703
  } catch {
57070
57704
  return false;
@@ -57175,17 +57809,17 @@ ${user}`
57175
57809
  // Attempt to collect attached files from context; map to AttachedFileContext
57176
57810
  async collectAttachedFiles(context2) {
57177
57811
  const list = [];
57178
- const fs51 = await import('fs/promises');
57179
- const path64 = await import('path');
57812
+ const fs52 = await import('fs/promises');
57813
+ const path65 = await import('path');
57180
57814
  const att = context2 && (context2.attachments || context2.input?.attachments) || [];
57181
57815
  for (const a of att) {
57182
57816
  try {
57183
57817
  const p = a.path || a.filePath || a.name || "";
57184
- const originalName = a.name || path64.basename(p || `attachment_${Date.now().toString(36)}`);
57818
+ const originalName = a.name || path65.basename(p || `attachment_${Date.now().toString(36)}`);
57185
57819
  let content = a.content;
57186
57820
  if (!content && p) {
57187
- const abs = path64.isAbsolute(p) ? p : path64.join(process.cwd(), p);
57188
- content = await fs51.readFile(abs, "utf8");
57821
+ const abs = path65.isAbsolute(p) ? p : path65.join(process.cwd(), p);
57822
+ content = await fs52.readFile(abs, "utf8");
57189
57823
  }
57190
57824
  if (!content) continue;
57191
57825
  list.push({ originalName, pathHint: p || void 0, content, size: Buffer.byteLength(content, "utf8"), mime: a.mime || a.type });
@@ -63874,17 +64508,17 @@ var init_GraphEngine = __esm({
63874
64508
  const visited = /* @__PURE__ */ new Set();
63875
64509
  const queue = [{ id: from, path: [from] }];
63876
64510
  while (queue.length) {
63877
- const { id, path: path64 } = queue.shift();
64511
+ const { id, path: path65 } = queue.shift();
63878
64512
  if (visited.has(id)) continue;
63879
64513
  visited.add(id);
63880
64514
  const neighbors = this.edges.get(id) || /* @__PURE__ */ new Set();
63881
64515
  for (const e2 of neighbors) {
63882
64516
  if (e2.to === to) {
63883
- const res = [...path64, to];
64517
+ const res = [...path65, to];
63884
64518
  this.recordQueryTime(Date.now() - start);
63885
64519
  return res;
63886
64520
  }
63887
- if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...path64, e2.to] });
64521
+ if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...path65, e2.to] });
63888
64522
  }
63889
64523
  }
63890
64524
  this.recordQueryTime(Date.now() - start);
@@ -66551,12 +67185,12 @@ This will:
66551
67185
  };
66552
67186
  const result = await this.deltaDetector.detectDelta(root, deltaOptions);
66553
67187
  const files = [
66554
- ...result.changed.map((path64) => ({
66555
- _path: path64,
66556
- type: previousState?.fileHashes?.[path64] ? "modified" : "added"
67188
+ ...result.changed.map((path65) => ({
67189
+ _path: path65,
67190
+ type: previousState?.fileHashes?.[path65] ? "modified" : "added"
66557
67191
  })),
66558
- ...result.deleted.map((path64) => ({
66559
- _path: path64,
67192
+ ...result.deleted.map((path65) => ({
67193
+ _path: path65,
66560
67194
  type: "deleted"
66561
67195
  }))
66562
67196
  ];
@@ -69992,13 +70626,13 @@ async function checkShield(commandName, userPlan = "free") {
69992
70626
  }
69993
70627
  async function loadManifest() {
69994
70628
  try {
69995
- const fs51 = await import('fs');
69996
- const path64 = await import('path');
69997
- const manifestPath = path64.join(
70629
+ const fs52 = await import('fs');
70630
+ const path65 = await import('path');
70631
+ const manifestPath = path65.join(
69998
70632
  __dirname,
69999
70633
  "../command-manifest-v2.1.json"
70000
70634
  );
70001
- const content = fs51.readFileSync(manifestPath, "utf-8");
70635
+ const content = fs52.readFileSync(manifestPath, "utf-8");
70002
70636
  return JSON.parse(content);
70003
70637
  } catch {
70004
70638
  return { commands: [] };
@@ -71493,7 +72127,7 @@ ${user}`,
71493
72127
  };
71494
72128
  }
71495
72129
  });
71496
- function extractFirstJson5(text) {
72130
+ function extractFirstJson6(text) {
71497
72131
  const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
71498
72132
  if (fence) return fence[1];
71499
72133
  const start = text.indexOf("{");
@@ -71540,7 +72174,7 @@ ${user}`,
71540
72174
  }
71541
72175
  });
71542
72176
  const raw = (response?.data?.content || response?.output || "").trim();
71543
- const jsonText = extractFirstJson5(raw) || raw;
72177
+ const jsonText = extractFirstJson6(raw) || raw;
71544
72178
  let parsed = {};
71545
72179
  try {
71546
72180
  parsed = JSON.parse(jsonText);
@@ -72400,6 +73034,15 @@ async function registerBuiltInCommands() {
72400
73034
  } catch (error2) {
72401
73035
  console.error("Failed to register media commands:", error2);
72402
73036
  }
73037
+ try {
73038
+ const NovelModule = await Promise.resolve().then(() => (init_novel_command(), novel_command_exports));
73039
+ const NovelClass = NovelModule.NovelCommand || NovelModule.default;
73040
+ const novel = new NovelClass();
73041
+ if (novel.initialize) await novel.initialize();
73042
+ commandRegistry.register(novel);
73043
+ } catch (error2) {
73044
+ console.error("Failed to register novel command:", error2);
73045
+ }
72403
73046
  try {
72404
73047
  const { codeCommand: codeCommand2 } = await Promise.resolve().then(() => (init_code_command(), code_command_exports));
72405
73048
  try {
@@ -74932,16 +75575,16 @@ var init_ai_response_service = __esm({
74932
75575
  if (p) candidates.add(p);
74933
75576
  }
74934
75577
  if (candidates.size > 0) {
74935
- const fs51 = await import('fs/promises');
75578
+ const fs52 = await import('fs/promises');
74936
75579
  const pathMod = await import('path');
74937
75580
  const cwd2 = process.cwd();
74938
75581
  for (const cand of candidates) {
74939
75582
  try {
74940
75583
  const normalized = cand.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
74941
75584
  const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(cwd2, normalized);
74942
- const st = await fs51.stat(abs).catch(() => null);
75585
+ const st = await fs52.stat(abs).catch(() => null);
74943
75586
  if (!st || !st.isFile()) continue;
74944
- const buf = await fs51.readFile(abs);
75587
+ const buf = await fs52.readFile(abs);
74945
75588
  const ext2 = (pathMod.extname(abs) || "").toLowerCase();
74946
75589
  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";
74947
75590
  autoAttachments.push({ name: pathMod.basename(abs), path: abs, mime, data_base64: buf.toString("base64") });