@bonginkan/maria 4.3.38 → 4.3.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/READY.manifest.json +11 -3
- package/dist/bin/maria.cjs +1166 -374
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +1163 -371
- package/dist/cli.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/server/express-server.cjs +1 -1
- package/dist/server/express-server.js +1 -1
- package/dist/server-express.cjs +1 -1
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +11 -3
package/dist/bin/maria.cjs
CHANGED
|
@@ -235,13 +235,13 @@ function getPackageJson() {
|
|
|
235
235
|
)
|
|
236
236
|
];
|
|
237
237
|
let packageJsonPath = null;
|
|
238
|
-
for (const
|
|
239
|
-
if (fs21.existsSync(
|
|
238
|
+
for (const path65 of possiblePaths) {
|
|
239
|
+
if (fs21.existsSync(path65)) {
|
|
240
240
|
try {
|
|
241
|
-
const content = fs21.readFileSync(
|
|
241
|
+
const content = fs21.readFileSync(path65, "utf-8");
|
|
242
242
|
const parsed = JSON.parse(content);
|
|
243
243
|
if (parsed.name === "@bonginkan/maria") {
|
|
244
|
-
packageJsonPath =
|
|
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 = (
|
|
5318
|
-
blobFrom = (
|
|
5319
|
-
fileFrom = (
|
|
5320
|
-
fileFromSync = (
|
|
5321
|
-
fromBlob = (stat13,
|
|
5322
|
-
path:
|
|
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,
|
|
5328
|
-
path:
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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
|
|
9592
|
+
await fs52.promises.access(targetPath);
|
|
9593
9593
|
const backupPath = `${targetPath}.backup.${Date.now()}`;
|
|
9594
|
-
await
|
|
9594
|
+
await fs52.promises.copyFile(targetPath, backupPath);
|
|
9595
9595
|
} catch {
|
|
9596
9596
|
}
|
|
9597
9597
|
}
|
|
9598
|
-
await
|
|
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
|
|
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
|
|
9647
|
+
const fs52 = await importNodeBuiltin2("fs");
|
|
9648
9648
|
const _path = await importNodeBuiltin2(
|
|
9649
9649
|
"_path"
|
|
9650
9650
|
);
|
|
9651
|
-
await
|
|
9652
|
-
await
|
|
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
|
|
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
|
|
9967
|
-
const _envContent = await
|
|
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(
|
|
19540
|
-
const keys =
|
|
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(
|
|
19571
|
-
const keys =
|
|
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:
|
|
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
|
|
19630
|
-
|
|
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(
|
|
19642
|
-
if (!this._listeners.has(
|
|
19643
|
-
this._listeners.set(
|
|
19641
|
+
onChange(path65, listener) {
|
|
19642
|
+
if (!this._listeners.has(path65)) {
|
|
19643
|
+
this._listeners.set(path65, []);
|
|
19644
19644
|
}
|
|
19645
|
-
this._listeners.get(
|
|
19645
|
+
this._listeners.get(path65).push(listener);
|
|
19646
19646
|
return () => {
|
|
19647
|
-
const listeners = this._listeners.get(
|
|
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((
|
|
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(
|
|
20275
|
+
validateFilePath(path65) {
|
|
20276
20276
|
try {
|
|
20277
20277
|
const schema = this._schemas.get("filePath");
|
|
20278
|
-
const result = schema.parse(
|
|
20279
|
-
if (this.isSystemPath(
|
|
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(
|
|
20426
|
-
return /\.\.[/\\]/.test(
|
|
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(
|
|
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) =>
|
|
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
|
|
25444
|
-
const
|
|
25445
|
-
const abs =
|
|
25446
|
-
await
|
|
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
|
|
25537
|
-
const
|
|
25538
|
-
const abs =
|
|
25539
|
-
await
|
|
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(
|
|
25929
|
-
return this._configService?.getNestedValue(
|
|
25928
|
+
getConfig(path65) {
|
|
25929
|
+
return this._configService?.getNestedValue(path65);
|
|
25930
25930
|
}
|
|
25931
25931
|
/**
|
|
25932
25932
|
* 設定の更新
|
|
25933
25933
|
*/
|
|
25934
|
-
async setConfig(
|
|
25934
|
+
async setConfig(path65, value) {
|
|
25935
25935
|
if (this._configService) {
|
|
25936
|
-
await this._configService.setNestedValue(
|
|
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(
|
|
26055
|
-
return this.orchestrator.getConfig(
|
|
26054
|
+
getConfig(path65) {
|
|
26055
|
+
return this.orchestrator.getConfig(path65);
|
|
26056
26056
|
}
|
|
26057
|
-
async setConfig(
|
|
26058
|
-
await this.orchestrator.setConfig(
|
|
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.
|
|
26070
|
-
description: "\u{1F680} MARIA v4.3.
|
|
26069
|
+
version: "4.3.40",
|
|
26070
|
+
description: "\u{1F680} MARIA v4.3.40 - 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.
|
|
28107
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.40"}`
|
|
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(
|
|
28748
|
+
async function callApi(path65, init3 = {}) {
|
|
28749
28749
|
const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
28750
|
-
const fullUrl = `${apiBase}${
|
|
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.
|
|
28761
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.40"}`,
|
|
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(
|
|
28820
|
-
const response = await callApi(
|
|
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(
|
|
28830
|
-
const response = await callApi(
|
|
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(
|
|
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(
|
|
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(
|
|
33823
|
-
if (!
|
|
33822
|
+
resolve(path65) {
|
|
33823
|
+
if (!path65) {
|
|
33824
33824
|
return this;
|
|
33825
33825
|
}
|
|
33826
|
-
const rootPath = this.getRootString(
|
|
33827
|
-
const dir =
|
|
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(
|
|
34580
|
-
return path11.win32.parse(
|
|
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(
|
|
34627
|
-
return
|
|
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:
|
|
34677
|
-
this.#fs = fsFromOption(
|
|
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(
|
|
34717
|
-
if (typeof
|
|
34718
|
-
|
|
34716
|
+
depth(path65 = this.cwd) {
|
|
34717
|
+
if (typeof path65 === "string") {
|
|
34718
|
+
path65 = this.cwd.resolve(path65);
|
|
34719
34719
|
}
|
|
34720
|
-
return
|
|
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(
|
|
35207
|
+
chdir(path65 = this.cwd) {
|
|
35208
35208
|
const oldCwd = this.cwd;
|
|
35209
|
-
this.cwd = typeof
|
|
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(
|
|
35236
|
-
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
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(
|
|
35265
|
-
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
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(([
|
|
35585
|
-
|
|
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,
|
|
35798
|
+
constructor(patterns, path65, opts) {
|
|
35799
35799
|
this.patterns = patterns;
|
|
35800
|
-
this.path =
|
|
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(
|
|
35820
|
-
return this.seen.has(
|
|
35819
|
+
#ignored(path65) {
|
|
35820
|
+
return this.seen.has(path65) || !!this.#ignore?.ignored?.(path65);
|
|
35821
35821
|
}
|
|
35822
|
-
#childrenIgnored(
|
|
35823
|
-
return !!this.#ignore?.childrenIgnored?.(
|
|
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,
|
|
36039
|
-
super(patterns,
|
|
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,
|
|
36077
|
-
super(patterns,
|
|
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
|
|
41913
|
-
if (!this.validatePath(
|
|
41914
|
-
violations.push(`Invalid path: ${
|
|
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
|
|
41971
|
-
const resolvedPath =
|
|
41970
|
+
const path65 = __require("path");
|
|
41971
|
+
const resolvedPath = path65.resolve(filePath);
|
|
41972
41972
|
for (const blockedPath of this.constraints.blockedPaths) {
|
|
41973
|
-
if (resolvedPath.startsWith(
|
|
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(
|
|
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
|
|
42008
|
-
if (!this.validatePath(
|
|
42009
|
-
violations.push(`Invalid path in ${action.type}: ${
|
|
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,
|
|
42979
|
-
const keys =
|
|
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.
|
|
51264
|
+
output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.40"));
|
|
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/
|
|
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 =
|
|
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(
|
|
54802
|
-
if (/__tests__|\.spec\.(t|j)sx?$|^tests\//.test(
|
|
54803
|
-
if (/^docs\//.test(
|
|
54804
|
-
if (/\.(json|cjs|js|ts)$/.test(
|
|
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
|
|
55386
|
+
const fs52 = __require("fs");
|
|
55069
55387
|
const p = abs ? abs : __require("path").join(root, rel);
|
|
55070
|
-
return
|
|
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"
|
|
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,168 @@ 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
|
+
}
|
|
56031
|
+
async function readHeadTail(root, rel, n) {
|
|
56032
|
+
try {
|
|
56033
|
+
const fs52 = await import('fs/promises');
|
|
56034
|
+
const pathMod = await import('path');
|
|
56035
|
+
const full = pathMod.join(root, rel);
|
|
56036
|
+
const buf = await fs52.readFile(full, "utf8");
|
|
56037
|
+
const lines = buf.split(/\r?\n/);
|
|
56038
|
+
const head2 = lines.slice(0, n).join("\n");
|
|
56039
|
+
const tail = lines.slice(Math.max(0, lines.length - n)).join("\n");
|
|
56040
|
+
return { head: head2, tail };
|
|
56041
|
+
} catch {
|
|
56042
|
+
return { head: "", tail: "" };
|
|
56043
|
+
}
|
|
56044
|
+
}
|
|
56045
|
+
async function llmSelectEditTargets(root, request, repoFiles) {
|
|
56046
|
+
try {
|
|
56047
|
+
const candidates = repoFiles.filter((p) => /\.(html|css|js|ts|tsx)$/i.test(p)).slice(0, 150);
|
|
56048
|
+
const samples = [];
|
|
56049
|
+
for (const p of candidates.slice(0, 60)) {
|
|
56050
|
+
const h2 = await readHeadTail(root, p, 5);
|
|
56051
|
+
samples.push(`- ${p}
|
|
56052
|
+
${h2.head}`);
|
|
56053
|
+
}
|
|
56054
|
+
const system = [
|
|
56055
|
+
"You select existing repository files that should be EDITED to satisfy a user request.",
|
|
56056
|
+
"Consider path names and the first lines. Return JSON array of repo-relative paths to edit.",
|
|
56057
|
+
"Keep the list short (<= 10). If none are relevant, return []. Do not invent paths."
|
|
56058
|
+
].join("\n");
|
|
56059
|
+
const user = [`Request: ${request}`, "Candidates:", samples.join("\n\n")].join("\n\n");
|
|
56060
|
+
const resp = await executeChat([
|
|
56061
|
+
{ role: "system", content: system },
|
|
56062
|
+
{ role: "user", content: user }
|
|
56063
|
+
]);
|
|
56064
|
+
const raw = (resp?.output || "").trim();
|
|
56065
|
+
const jsonText = (() => {
|
|
56066
|
+
try {
|
|
56067
|
+
const m2 = raw.match(/\[[\s\S]*\]/);
|
|
56068
|
+
return m2 ? m2[0] : raw;
|
|
56069
|
+
} catch {
|
|
56070
|
+
return raw;
|
|
56071
|
+
}
|
|
56072
|
+
})();
|
|
56073
|
+
const arr = JSON.parse(jsonText);
|
|
56074
|
+
const set = new Set(candidates.map((c) => c.toLowerCase()));
|
|
56075
|
+
const out = [];
|
|
56076
|
+
if (Array.isArray(arr)) {
|
|
56077
|
+
for (const v of arr) {
|
|
56078
|
+
if (typeof v === "string" && set.has(v.toLowerCase())) out.push(v);
|
|
56079
|
+
if (out.length >= 10) break;
|
|
56080
|
+
}
|
|
56081
|
+
}
|
|
56082
|
+
return out;
|
|
56083
|
+
} catch {
|
|
56084
|
+
return [];
|
|
56085
|
+
}
|
|
56086
|
+
}
|
|
56087
|
+
async function llmMapBlockToFile(root, request, block, repoFiles) {
|
|
56088
|
+
try {
|
|
56089
|
+
const lang = (block.language || "").toLowerCase();
|
|
56090
|
+
const extFilter = lang.includes("html") ? /\.html$/i : /(ts|tsx)/.test(lang) ? /\.(ts|tsx)$/i : /(js|jsx)/.test(lang) ? /\.(js|jsx)$/i : /\.css$/i;
|
|
56091
|
+
const candidates = repoFiles.filter((p) => extFilter.test(p)).slice(0, 80);
|
|
56092
|
+
const head2 = block.code.split(/\r?\n/).slice(0, 20).join("\n");
|
|
56093
|
+
const samples = [];
|
|
56094
|
+
for (const p of candidates.slice(0, 40)) {
|
|
56095
|
+
const h2 = await readHeadTail(root, p, 8);
|
|
56096
|
+
samples.push(`- ${p}
|
|
56097
|
+
${h2.head}`);
|
|
56098
|
+
}
|
|
56099
|
+
const system = [
|
|
56100
|
+
"Decide where to apply an EDIT vs CREATE for a code block within an existing repository.",
|
|
56101
|
+
'Return JSON: { "action": "modify"|"create", "path": string }.',
|
|
56102
|
+
"If modify, path must be one of the candidate repo-relative paths. If create, propose a sensible repo-relative path."
|
|
56103
|
+
].join("\n");
|
|
56104
|
+
const user = [
|
|
56105
|
+
`Request: ${request}`,
|
|
56106
|
+
"Block:",
|
|
56107
|
+
"```",
|
|
56108
|
+
head2,
|
|
56109
|
+
"```",
|
|
56110
|
+
"Candidates:",
|
|
56111
|
+
samples.join("\n\n")
|
|
56112
|
+
].join("\n");
|
|
56113
|
+
const resp = await executeChat([
|
|
56114
|
+
{ role: "system", content: system },
|
|
56115
|
+
{ role: "user", content: user }
|
|
56116
|
+
]);
|
|
56117
|
+
const raw = (resp?.output || "").trim();
|
|
56118
|
+
const jsonText = (() => {
|
|
56119
|
+
try {
|
|
56120
|
+
const m2 = raw.match(/\{[\s\S]*\}/);
|
|
56121
|
+
return m2 ? m2[0] : raw;
|
|
56122
|
+
} catch {
|
|
56123
|
+
return raw;
|
|
56124
|
+
}
|
|
56125
|
+
})();
|
|
56126
|
+
const parsed = JSON.parse(jsonText);
|
|
56127
|
+
if (parsed && (parsed.action === "modify" || parsed.action === "create") && typeof parsed.path === "string") {
|
|
56128
|
+
return { action: parsed.action, path: parsed.path.replace(/^\/+/, "") };
|
|
56129
|
+
}
|
|
56130
|
+
} catch {
|
|
56131
|
+
}
|
|
56132
|
+
const desired = typeof block.filename === "string" && block.filename.trim() ? block.filename.trim() : null;
|
|
56133
|
+
const fallback2 = desired || suggestName2(request, block.language, 0);
|
|
56134
|
+
return { action: "create", path: fallback2 };
|
|
56135
|
+
}
|
|
56136
|
+
function tokenizeRequest(text) {
|
|
56137
|
+
return Array.from(new Set(text.toLowerCase().replace(/[^a-z0-9_-]+/g, " ").split(/\s+/).filter((t2) => t2.length >= 3)));
|
|
56138
|
+
}
|
|
55658
56139
|
async function ensureCodeFallbackManager() {
|
|
55659
56140
|
const policy = await loadFallbackPolicy().catch(() => getDefaultFallbackPolicy());
|
|
55660
56141
|
const signature = JSON.stringify(policy);
|
|
@@ -55693,11 +56174,19 @@ async function orchestrate(request, opts) {
|
|
|
55693
56174
|
explicitAbsMap[rel] = pathMod.join(opts.root, rel);
|
|
55694
56175
|
}
|
|
55695
56176
|
}
|
|
55696
|
-
const isEditIntent =
|
|
56177
|
+
const isEditIntent = await detectEditIntentEnhanced(opts.root, request, {
|
|
55697
56178
|
hasAttachments: !!(opts.attachedFiles && opts.attachedFiles.length > 0),
|
|
55698
|
-
|
|
55699
|
-
|
|
55700
|
-
|
|
56179
|
+
explicitFiles});
|
|
56180
|
+
let editTargets = explicitFiles;
|
|
56181
|
+
if (isEditIntent && editTargets.length === 0) {
|
|
56182
|
+
try {
|
|
56183
|
+
const repoFiles = await getRepoFiles(opts.root);
|
|
56184
|
+
const llmTargets = await llmSelectEditTargets(opts.root, request, repoFiles);
|
|
56185
|
+
editTargets = llmTargets;
|
|
56186
|
+
} catch {
|
|
56187
|
+
}
|
|
56188
|
+
}
|
|
56189
|
+
const editContext = isEditIntent && editTargets.length > 0 ? await buildEditContext(opts.root, editTargets, 200, 512 * 1024) : "";
|
|
55701
56190
|
if (opts.attachedFiles && opts.attachedFiles.length > 0) {
|
|
55702
56191
|
const mapRes = await mapAttachmentsToTargets(opts.attachedFiles, {
|
|
55703
56192
|
root: opts.root,
|
|
@@ -55754,16 +56243,17 @@ ${editContext}`;
|
|
|
55754
56243
|
data_base64: f3.content ? Buffer.from(f3.content, "utf8").toString("base64") : void 0
|
|
55755
56244
|
})).map((a) => a.data_base64 ? a : { ...a, data_base64: void 0 }) : [];
|
|
55756
56245
|
const pathAttachments = [];
|
|
56246
|
+
const attachedPathSet = /* @__PURE__ */ new Set();
|
|
55757
56247
|
if (explicitFiles.length > 0) {
|
|
55758
56248
|
try {
|
|
55759
|
-
const
|
|
56249
|
+
const fs52 = await import('fs/promises');
|
|
55760
56250
|
const pathMod = await import('path');
|
|
55761
56251
|
for (const rel of explicitFiles) {
|
|
55762
56252
|
try {
|
|
55763
56253
|
const full = explicitAbsMap[rel] || pathMod.join(opts.root, rel);
|
|
55764
|
-
const stat13 = await
|
|
56254
|
+
const stat13 = await fs52.stat(full).catch(() => null);
|
|
55765
56255
|
if (!stat13 || !stat13.isFile()) continue;
|
|
55766
|
-
const buf = await
|
|
56256
|
+
const buf = await fs52.readFile(full);
|
|
55767
56257
|
const ext2 = (pathMod.extname(full) || "").toLowerCase();
|
|
55768
56258
|
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
56259
|
pathAttachments.push({
|
|
@@ -55772,6 +56262,33 @@ ${editContext}`;
|
|
|
55772
56262
|
mime,
|
|
55773
56263
|
data_base64: buf.toString("base64")
|
|
55774
56264
|
});
|
|
56265
|
+
attachedPathSet.add(full.toLowerCase());
|
|
56266
|
+
} catch {
|
|
56267
|
+
}
|
|
56268
|
+
}
|
|
56269
|
+
} catch {
|
|
56270
|
+
}
|
|
56271
|
+
}
|
|
56272
|
+
if (isEditIntent && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
56273
|
+
try {
|
|
56274
|
+
const fs52 = await import('fs/promises');
|
|
56275
|
+
const pathMod = await import('path');
|
|
56276
|
+
for (const rel of editTargets) {
|
|
56277
|
+
try {
|
|
56278
|
+
const full = pathMod.isAbsolute(rel) ? rel : pathMod.join(opts.root, rel);
|
|
56279
|
+
const key = full.toLowerCase();
|
|
56280
|
+
if (attachedPathSet.has(key)) continue;
|
|
56281
|
+
const stat13 = await fs52.stat(full).catch(() => null);
|
|
56282
|
+
if (!stat13 || !stat13.isFile()) continue;
|
|
56283
|
+
const ext2 = (pathMod.extname(full) || "").toLowerCase();
|
|
56284
|
+
const buf = await fs52.readFile(full);
|
|
56285
|
+
pathAttachments.push({
|
|
56286
|
+
name: pathMod.basename(full),
|
|
56287
|
+
path: full,
|
|
56288
|
+
mime: "text/plain",
|
|
56289
|
+
data_base64: buf.toString("base64")
|
|
56290
|
+
});
|
|
56291
|
+
attachedPathSet.add(key);
|
|
55775
56292
|
} catch {
|
|
55776
56293
|
}
|
|
55777
56294
|
}
|
|
@@ -55781,7 +56298,7 @@ ${editContext}`;
|
|
|
55781
56298
|
const hydratedCtx = [];
|
|
55782
56299
|
if (ctxAttachments.length > 0) {
|
|
55783
56300
|
try {
|
|
55784
|
-
const
|
|
56301
|
+
const fs52 = await import('fs/promises');
|
|
55785
56302
|
for (const a of ctxAttachments) {
|
|
55786
56303
|
if (a.data_base64) {
|
|
55787
56304
|
hydratedCtx.push(a);
|
|
@@ -55792,12 +56309,12 @@ ${editContext}`;
|
|
|
55792
56309
|
continue;
|
|
55793
56310
|
}
|
|
55794
56311
|
try {
|
|
55795
|
-
const stat13 = await
|
|
56312
|
+
const stat13 = await fs52.stat(p).catch(() => null);
|
|
55796
56313
|
if (!stat13 || !stat13.isFile()) {
|
|
55797
56314
|
hydratedCtx.push(a);
|
|
55798
56315
|
continue;
|
|
55799
56316
|
}
|
|
55800
|
-
const buf = await
|
|
56317
|
+
const buf = await fs52.readFile(p);
|
|
55801
56318
|
hydratedCtx.push({ ...a, data_base64: buf.toString("base64") });
|
|
55802
56319
|
} catch {
|
|
55803
56320
|
hydratedCtx.push(a);
|
|
@@ -55847,46 +56364,60 @@ ${editContext}`;
|
|
|
55847
56364
|
codeOutput = outcome.data?.output || "";
|
|
55848
56365
|
}
|
|
55849
56366
|
const blocks = extractBlocks(codeOutput);
|
|
55850
|
-
if (explicitFiles.length > 0) {
|
|
56367
|
+
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
55851
56368
|
const mapped = /* @__PURE__ */ new Set();
|
|
56369
|
+
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
56370
|
+
const absMap = explicitFiles.length > 0 ? explicitAbsMap : /* @__PURE__ */ Object.create(null);
|
|
55852
56371
|
const htmlIdx = blocks.findIndex((b) => /html/i.test(b.language));
|
|
55853
|
-
const htmlFile =
|
|
56372
|
+
const htmlFile = targets.find((f3) => f3.toLowerCase().endsWith(".html"));
|
|
55854
56373
|
if (htmlIdx >= 0 && htmlFile) {
|
|
55855
|
-
initial.push({ path: htmlFile, absPath:
|
|
56374
|
+
initial.push({ path: htmlFile, absPath: absMap[htmlFile], noNormalize: true, kind: "source", action: "modify", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
|
|
55856
56375
|
mapped.add(htmlFile);
|
|
55857
56376
|
}
|
|
55858
56377
|
const jsIdx = blocks.findIndex((b) => /(ts|tsx|jsx|javascript|js)/i.test(b.language));
|
|
55859
|
-
const jsFile =
|
|
56378
|
+
const jsFile = targets.find((f3) => f3.toLowerCase().endsWith(".js"));
|
|
55860
56379
|
if (jsIdx >= 0 && jsFile && !mapped.has(jsFile)) {
|
|
55861
|
-
initial.push({ path: jsFile, absPath:
|
|
56380
|
+
initial.push({ path: jsFile, absPath: absMap[jsFile], noNormalize: true, kind: "source", action: "modify", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
|
|
55862
56381
|
mapped.add(jsFile);
|
|
55863
56382
|
}
|
|
55864
56383
|
const cssIdx = blocks.findIndex((b) => /css/i.test(b.language));
|
|
55865
|
-
const cssFile =
|
|
56384
|
+
const cssFile = targets.find((f3) => f3.toLowerCase().endsWith(".css"));
|
|
55866
56385
|
if (cssIdx >= 0 && cssFile && !mapped.has(cssFile)) {
|
|
55867
|
-
initial.push({ path: cssFile, absPath:
|
|
56386
|
+
initial.push({ path: cssFile, absPath: absMap[cssFile], noNormalize: true, kind: "source", action: "modify", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
|
|
55868
56387
|
mapped.add(cssFile);
|
|
55869
56388
|
}
|
|
55870
|
-
for (const f3 of
|
|
56389
|
+
for (const f3 of targets) {
|
|
55871
56390
|
if (mapped.has(f3)) continue;
|
|
55872
|
-
const
|
|
55873
|
-
|
|
55874
|
-
|
|
55875
|
-
|
|
56391
|
+
const ext2 = (() => {
|
|
56392
|
+
const m2 = f3.lastIndexOf(".");
|
|
56393
|
+
return m2 >= 0 ? f3.slice(m2) : "";
|
|
56394
|
+
})();
|
|
56395
|
+
const lang = languageFromExt(ext2);
|
|
56396
|
+
const strongMatch = /pong|retro|game|index\.(html)$|script\.(js|ts)$|style\.css/i.test(f3) || tokenizeRequest(request).some((t2) => f3.toLowerCase().includes(t2));
|
|
56397
|
+
if (strongMatch) {
|
|
56398
|
+
initial.push({ path: f3, absPath: absMap[f3], noNormalize: true, kind: "source", action: "modify", description: "Edit target", language: lang, preview: "" });
|
|
56399
|
+
}
|
|
55876
56400
|
}
|
|
55877
56401
|
} else {
|
|
55878
|
-
|
|
55879
|
-
const
|
|
55880
|
-
|
|
55881
|
-
|
|
55882
|
-
|
|
55883
|
-
path
|
|
55884
|
-
|
|
55885
|
-
|
|
55886
|
-
|
|
55887
|
-
|
|
55888
|
-
|
|
55889
|
-
|
|
56402
|
+
try {
|
|
56403
|
+
const repoFiles = await getRepoFiles(opts.root);
|
|
56404
|
+
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56405
|
+
const b = blocks[i2];
|
|
56406
|
+
const decision = await llmMapBlockToFile(opts.root, request, b, repoFiles);
|
|
56407
|
+
if (decision.action === "modify" && repoFiles.includes(decision.path)) {
|
|
56408
|
+
const lang = languageFromExt(decision.path.replace(/^.*(\.[a-z0-9]+)$/i, "$1"));
|
|
56409
|
+
initial.push({ path: decision.path, kind: "source", action: "modify", description: "Modify existing file", language: lang, preview: b.code });
|
|
56410
|
+
} else {
|
|
56411
|
+
const path65 = decision.path || suggestName2(request, b.language, i2);
|
|
56412
|
+
initial.push({ path: path65, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code });
|
|
56413
|
+
}
|
|
56414
|
+
}
|
|
56415
|
+
} catch {
|
|
56416
|
+
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56417
|
+
const b = blocks[i2];
|
|
56418
|
+
const path65 = suggestName2(request, b.language, i2);
|
|
56419
|
+
initial.push({ path: path65, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code });
|
|
56420
|
+
}
|
|
55890
56421
|
}
|
|
55891
56422
|
}
|
|
55892
56423
|
}
|
|
@@ -55911,13 +56442,13 @@ ${editContext}`;
|
|
|
55911
56442
|
{ root: opts.root }
|
|
55912
56443
|
);
|
|
55913
56444
|
try {
|
|
55914
|
-
const [{ access: access18 },
|
|
56445
|
+
const [{ access: access18 }, path65] = await Promise.all([
|
|
55915
56446
|
import('fs/promises'),
|
|
55916
56447
|
import('path')
|
|
55917
56448
|
]);
|
|
55918
56449
|
for (const p of normalized) {
|
|
55919
56450
|
try {
|
|
55920
|
-
const absCandidate = p.absPath ? p.absPath :
|
|
56451
|
+
const absCandidate = p.absPath ? p.absPath : path65.join(opts.root, p.path);
|
|
55921
56452
|
await access18(absCandidate);
|
|
55922
56453
|
p.action = "modify";
|
|
55923
56454
|
if (isEditIntent) {
|
|
@@ -55926,6 +56457,9 @@ ${editContext}`;
|
|
|
55926
56457
|
} catch {
|
|
55927
56458
|
p.action = "create";
|
|
55928
56459
|
}
|
|
56460
|
+
if (p.action === "modify" && (!p.preview || p.preview.length === 0)) {
|
|
56461
|
+
p.action = "skip";
|
|
56462
|
+
}
|
|
55929
56463
|
}
|
|
55930
56464
|
} catch {
|
|
55931
56465
|
}
|
|
@@ -56155,12 +56689,12 @@ function languageExt(lang) {
|
|
|
56155
56689
|
}
|
|
56156
56690
|
async function journalResume(root, request, files) {
|
|
56157
56691
|
try {
|
|
56158
|
-
const
|
|
56692
|
+
const fs52 = await import('fs/promises');
|
|
56159
56693
|
const dir = path11__namespace.default.join(root, ".maria", "memory");
|
|
56160
|
-
await
|
|
56694
|
+
await fs52.mkdir(dir, { recursive: true });
|
|
56161
56695
|
const out = path11__namespace.default.join(dir, "resume-plan.json");
|
|
56162
56696
|
const payload = { request, createdAt: (/* @__PURE__ */ new Date()).toISOString(), files };
|
|
56163
|
-
await
|
|
56697
|
+
await fs52.writeFile(out, JSON.stringify(payload, null, 2), "utf8");
|
|
56164
56698
|
} catch {
|
|
56165
56699
|
}
|
|
56166
56700
|
}
|
|
@@ -56288,6 +56822,68 @@ function detectEditIntent(request, ctx2) {
|
|
|
56288
56822
|
const mentionsEdit = editKeywords.some((k) => r2.includes(k));
|
|
56289
56823
|
return ctx2.hasAttachments || ctx2.explicitFilesCount > 0 || mentionsEdit;
|
|
56290
56824
|
}
|
|
56825
|
+
async function detectEditIntentEnhanced(root, request, ctx2) {
|
|
56826
|
+
const baseline = detectEditIntent(request, { hasAttachments: ctx2.hasAttachments, explicitFilesCount: ctx2.explicitFiles.length });
|
|
56827
|
+
if (baseline) return true;
|
|
56828
|
+
const r2 = request.toLowerCase();
|
|
56829
|
+
const softHints = ["improve", "enhance", "make it", "change the", "adjust", "tweak", "rework", "revamp", "retro", "modernize", "clean up", "polish"];
|
|
56830
|
+
const hasSoftHint = softHints.some((k) => r2.includes(k));
|
|
56831
|
+
if (!hasSoftHint) return false;
|
|
56832
|
+
try {
|
|
56833
|
+
const fs52 = await import('fs/promises');
|
|
56834
|
+
const pathMod = await import('path');
|
|
56835
|
+
const { loadGlobby: loadGlobby2 } = await Promise.resolve().then(() => (init_esm_compat(), esm_compat_exports));
|
|
56836
|
+
const globby = await loadGlobby2();
|
|
56837
|
+
const ignore = [
|
|
56838
|
+
"**/node_modules/**",
|
|
56839
|
+
"**/.git/**",
|
|
56840
|
+
"**/dist/**",
|
|
56841
|
+
"**/build/**",
|
|
56842
|
+
"**/.maria/**",
|
|
56843
|
+
"**/.next/**",
|
|
56844
|
+
"**/coverage/**",
|
|
56845
|
+
"**/.DS_Store/**",
|
|
56846
|
+
"**/.DS_Store",
|
|
56847
|
+
"**/.Spotlight-V100/**",
|
|
56848
|
+
"**/.Spotlight-V100",
|
|
56849
|
+
"**/.Trashes/**",
|
|
56850
|
+
"**/.Trashes",
|
|
56851
|
+
"**/.fseventsd/**",
|
|
56852
|
+
"**/.fseventsd",
|
|
56853
|
+
"**/.TemporaryItems/**",
|
|
56854
|
+
"**/.TemporaryItems"
|
|
56855
|
+
];
|
|
56856
|
+
const candidates = await globby(["**/*.{html,css,js,ts,tsx}"], { cwd: root, absolute: true, gitignore: true, ignore, deep: 3 });
|
|
56857
|
+
if (candidates && candidates.length > 0) return true;
|
|
56858
|
+
} catch {
|
|
56859
|
+
}
|
|
56860
|
+
try {
|
|
56861
|
+
const short = request.trim().length <= 160;
|
|
56862
|
+
if (!short) return false;
|
|
56863
|
+
const system = [
|
|
56864
|
+
"You are classifying whether the user intends to EDIT existing files vs CREATE a new project.",
|
|
56865
|
+
'Return JSON: { "edit": true|false } only.'
|
|
56866
|
+
].join("\n");
|
|
56867
|
+
const user = `Instruction: ${request}`;
|
|
56868
|
+
const resp = await executeChat([
|
|
56869
|
+
{ role: "system", content: system },
|
|
56870
|
+
{ role: "user", content: user }
|
|
56871
|
+
]);
|
|
56872
|
+
const raw = (resp?.output || "").trim();
|
|
56873
|
+
const jsonText = (() => {
|
|
56874
|
+
try {
|
|
56875
|
+
const m2 = raw.match(/\{[\s\S]*\}/);
|
|
56876
|
+
return m2 ? m2[0] : raw;
|
|
56877
|
+
} catch {
|
|
56878
|
+
return raw;
|
|
56879
|
+
}
|
|
56880
|
+
})();
|
|
56881
|
+
const parsed = JSON.parse(jsonText);
|
|
56882
|
+
if (typeof parsed?.edit === "boolean") return !!parsed.edit;
|
|
56883
|
+
} catch {
|
|
56884
|
+
}
|
|
56885
|
+
return false;
|
|
56886
|
+
}
|
|
56291
56887
|
function sanitizeFolderName(name2) {
|
|
56292
56888
|
const base = name2.toLowerCase().replace(/[`~!@#$%^&*()+=\[\]{}|;:'",<>/?\\]/g, " ").replace(/\s+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
56293
56889
|
return base || "project";
|
|
@@ -56320,14 +56916,14 @@ async function ensureTopFolder(root, proposed, plans) {
|
|
|
56320
56916
|
return { folderName: unique };
|
|
56321
56917
|
}
|
|
56322
56918
|
async function ensureUniqueFolder(root, base) {
|
|
56323
|
-
const
|
|
56919
|
+
const fs52 = await import('fs/promises');
|
|
56324
56920
|
const pathMod = await import('path');
|
|
56325
56921
|
let name2 = sanitizeFolderName(base);
|
|
56326
56922
|
let suffix = 0;
|
|
56327
56923
|
for (; suffix < Number.MAX_SAFE_INTEGER; ) {
|
|
56328
56924
|
const candidate = suffix === 0 ? name2 : `${name2}-${String(suffix).padStart(2, "0")}`;
|
|
56329
56925
|
try {
|
|
56330
|
-
await
|
|
56926
|
+
await fs52.access(pathMod.join(root, candidate));
|
|
56331
56927
|
suffix += 1;
|
|
56332
56928
|
} catch {
|
|
56333
56929
|
return candidate;
|
|
@@ -56337,13 +56933,13 @@ async function ensureUniqueFolder(root, base) {
|
|
|
56337
56933
|
}
|
|
56338
56934
|
async function buildEditContext(root, files, maxLines, maxBytes) {
|
|
56339
56935
|
try {
|
|
56340
|
-
const
|
|
56936
|
+
const fs52 = await import('fs/promises');
|
|
56341
56937
|
const pathMod = await import('path');
|
|
56342
56938
|
const sections = [];
|
|
56343
56939
|
for (const rel of files) {
|
|
56344
56940
|
const full = pathMod.join(root, rel);
|
|
56345
56941
|
try {
|
|
56346
|
-
const buf = await
|
|
56942
|
+
const buf = await fs52.readFile(full);
|
|
56347
56943
|
const clipped = buf.length > maxBytes ? buf.subarray(0, maxBytes) : buf;
|
|
56348
56944
|
const text = clipped.toString("utf8").replace(/\r\n/g, "\n");
|
|
56349
56945
|
const lines = text.split("\n").slice(0, maxLines).join("\n");
|
|
@@ -56360,84 +56956,58 @@ ${lines}
|
|
|
56360
56956
|
}
|
|
56361
56957
|
}
|
|
56362
56958
|
async function resolveExplicitPaths(root, files, hintText) {
|
|
56363
|
-
const
|
|
56959
|
+
const fs52 = await import('fs/promises');
|
|
56364
56960
|
const pathMod = await import('path');
|
|
56365
|
-
const
|
|
56366
|
-
|
|
56367
|
-
|
|
56368
|
-
"
|
|
56369
|
-
"
|
|
56370
|
-
"
|
|
56371
|
-
"
|
|
56372
|
-
"
|
|
56373
|
-
"
|
|
56374
|
-
"
|
|
56375
|
-
|
|
56376
|
-
|
|
56377
|
-
|
|
56378
|
-
|
|
56379
|
-
|
|
56380
|
-
|
|
56381
|
-
|
|
56382
|
-
|
|
56383
|
-
|
|
56961
|
+
const ignoreDir = /* @__PURE__ */ new Set([
|
|
56962
|
+
".git",
|
|
56963
|
+
"node_modules",
|
|
56964
|
+
"dist",
|
|
56965
|
+
"build",
|
|
56966
|
+
".maria",
|
|
56967
|
+
".next",
|
|
56968
|
+
"coverage",
|
|
56969
|
+
".DS_Store",
|
|
56970
|
+
".Spotlight-V100",
|
|
56971
|
+
".Trashes",
|
|
56972
|
+
".fseventsd",
|
|
56973
|
+
".TemporaryItems"
|
|
56974
|
+
]);
|
|
56975
|
+
async function buildRepoIndex() {
|
|
56976
|
+
if (_repoFileIndexCache && _repoFileIndexCache.root === root) return _repoFileIndexCache.files;
|
|
56977
|
+
const out2 = [];
|
|
56978
|
+
async function walk2(dir) {
|
|
56979
|
+
let entries = [];
|
|
56980
|
+
try {
|
|
56981
|
+
entries = await fs52.readdir(dir, { withFileTypes: true });
|
|
56982
|
+
} catch {
|
|
56983
|
+
return;
|
|
56984
|
+
}
|
|
56985
|
+
for (const e2 of entries) {
|
|
56986
|
+
const name2 = e2.name;
|
|
56987
|
+
if (ignoreDir.has(name2)) continue;
|
|
56988
|
+
const full = pathMod.join(dir, name2);
|
|
56989
|
+
if (e2.isDirectory()) {
|
|
56990
|
+
await walk2(full);
|
|
56991
|
+
continue;
|
|
56992
|
+
}
|
|
56993
|
+
out2.push(pathMod.relative(root, full).replace(/\\/g, "/"));
|
|
56994
|
+
}
|
|
56384
56995
|
}
|
|
56996
|
+
await walk2(root);
|
|
56997
|
+
_repoFileIndexCache = { root, files: out2 };
|
|
56998
|
+
return out2;
|
|
56999
|
+
}
|
|
57000
|
+
const allFiles = await buildRepoIndex();
|
|
57001
|
+
const hintTokens = Array.from(new Set(hintText.toLowerCase().replace(/[^a-z0-9_/.-]+/g, " ").split(/\s+/).filter(Boolean)));
|
|
57002
|
+
async function rankCandidates(candidates, desired) {
|
|
57003
|
+
const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
56385
57004
|
const lowerRel = normalized.toLowerCase();
|
|
56386
57005
|
const ext2 = (pathMod.extname(normalized) || "").toLowerCase();
|
|
56387
57006
|
const base = pathMod.basename(normalized);
|
|
56388
|
-
|
|
57007
|
+
base.replace(/\.[^.]+$/, "").toLowerCase();
|
|
56389
57008
|
const parentPath = pathMod.dirname(normalized);
|
|
56390
57009
|
const parent = parentPath.split("/").pop() || "";
|
|
56391
57010
|
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
57011
|
function score(relPath) {
|
|
56442
57012
|
const lower2 = relPath.toLowerCase();
|
|
56443
57013
|
let s2 = 0;
|
|
@@ -56461,10 +57031,36 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
56461
57031
|
s2 -= Math.min(10, Math.floor(relPath.length / 80));
|
|
56462
57032
|
return s2;
|
|
56463
57033
|
}
|
|
56464
|
-
|
|
57034
|
+
const limited = candidates.slice(0, Math.min(50, candidates.length));
|
|
57035
|
+
if (limited.length > 1) {
|
|
57036
|
+
try {
|
|
57037
|
+
const ranked = limited.map((p) => ({ p, s: score(p) })).sort((a, b) => b.s - a.s).slice(0, 5).map((x2) => x2.p);
|
|
57038
|
+
const system = [
|
|
57039
|
+
"You are helping choose the most relevant target file path for an edit operation.",
|
|
57040
|
+
"Given a user request and several candidate repo-relative paths, pick ONE best path.",
|
|
57041
|
+
"Return ONLY the raw path text. No code blocks. No explanations."
|
|
57042
|
+
].join("\n");
|
|
57043
|
+
const user = [
|
|
57044
|
+
`User request: ${hintText}`,
|
|
57045
|
+
"Candidates:",
|
|
57046
|
+
...ranked.map((r2, i2) => `${i2 + 1}. ${r2}`),
|
|
57047
|
+
"",
|
|
57048
|
+
"Answer with exactly one of the candidate paths."
|
|
57049
|
+
].join("\n");
|
|
57050
|
+
const chat = await executeChat([
|
|
57051
|
+
{ role: "system", content: system },
|
|
57052
|
+
{ role: "user", content: user }
|
|
57053
|
+
]);
|
|
57054
|
+
const raw = (chat.output || "").trim();
|
|
57055
|
+
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
57056
|
+
return pick.replace(/^\/+/, "");
|
|
57057
|
+
} catch {
|
|
57058
|
+
}
|
|
57059
|
+
}
|
|
57060
|
+
let best = limited[0];
|
|
56465
57061
|
let bestScore = score(best);
|
|
56466
|
-
for (let i2 = 1; i2 <
|
|
56467
|
-
const c =
|
|
57062
|
+
for (let i2 = 1; i2 < limited.length; i2++) {
|
|
57063
|
+
const c = limited[i2];
|
|
56468
57064
|
const sc = score(c);
|
|
56469
57065
|
if (sc > bestScore) {
|
|
56470
57066
|
best = c;
|
|
@@ -56474,20 +57070,41 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
56474
57070
|
return best.replace(/^\/+/, "");
|
|
56475
57071
|
}
|
|
56476
57072
|
const out = [];
|
|
56477
|
-
for (const
|
|
56478
|
-
|
|
57073
|
+
for (const desired of files) {
|
|
57074
|
+
const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
57075
|
+
if (allFiles.includes(normalized)) {
|
|
57076
|
+
out.push(normalized);
|
|
57077
|
+
continue;
|
|
57078
|
+
}
|
|
57079
|
+
const base = pathMod.basename(normalized).toLowerCase();
|
|
57080
|
+
const nameNoExt = base.replace(/\.[^.]+$/, "");
|
|
57081
|
+
const candidates = allFiles.filter((p) => {
|
|
57082
|
+
const b = pathMod.basename(p).toLowerCase();
|
|
57083
|
+
return b === base || b.includes(base) || !base.includes(".") && (b === `${nameNoExt}.ts` || b === `${nameNoExt}.js` || b.startsWith(nameNoExt));
|
|
57084
|
+
});
|
|
57085
|
+
if (candidates.length === 0) {
|
|
57086
|
+
const parentPath = pathMod.dirname(normalized);
|
|
57087
|
+
if (parentPath && parentPath !== ".") {
|
|
57088
|
+
const pref = await pickExistingFolderPrefix(root, parentPath);
|
|
57089
|
+
out.push((pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1"));
|
|
57090
|
+
} else {
|
|
57091
|
+
out.push(normalized.replace(/^(src\/)src\//i, "$1"));
|
|
57092
|
+
}
|
|
57093
|
+
continue;
|
|
57094
|
+
}
|
|
57095
|
+
out.push(await rankCandidates(candidates, normalized));
|
|
56479
57096
|
}
|
|
56480
57097
|
return out;
|
|
56481
57098
|
}
|
|
56482
57099
|
async function pickExistingFolderPrefix(root, parentPath) {
|
|
56483
|
-
const
|
|
57100
|
+
const fs52 = await import('fs/promises');
|
|
56484
57101
|
const pathMod = await import('path');
|
|
56485
57102
|
const parts = parentPath.replace(/^\/+/, "").split("/").filter(Boolean);
|
|
56486
57103
|
const prefixes = ["src", "app", "pages", ""];
|
|
56487
57104
|
for (const pre of prefixes) {
|
|
56488
57105
|
const test = pre ? pathMod.join(root, pre, ...parts) : pathMod.join(root, ...parts);
|
|
56489
57106
|
try {
|
|
56490
|
-
await
|
|
57107
|
+
await fs52.access(test);
|
|
56491
57108
|
return pre ? `${pre}/` : "";
|
|
56492
57109
|
} catch {
|
|
56493
57110
|
}
|
|
@@ -56534,7 +57151,7 @@ requestAnimationFrame(step);`;
|
|
|
56534
57151
|
}
|
|
56535
57152
|
return { path: filename, kind: "source", action: "create", description: "Source file", preview: "" };
|
|
56536
57153
|
}
|
|
56537
|
-
var codeFallbackManager, codeFallbackPolicySignature;
|
|
57154
|
+
var codeFallbackManager, _repoFileIndexCache, codeFallbackPolicySignature;
|
|
56538
57155
|
var init_Orchestrator = __esm({
|
|
56539
57156
|
"src/services/code-orchestrator/Orchestrator.ts"() {
|
|
56540
57157
|
init_RepoScanner();
|
|
@@ -56549,6 +57166,7 @@ var init_Orchestrator = __esm({
|
|
|
56549
57166
|
init_FallbackManager();
|
|
56550
57167
|
init_policy();
|
|
56551
57168
|
codeFallbackManager = null;
|
|
57169
|
+
_repoFileIndexCache = null;
|
|
56552
57170
|
codeFallbackPolicySignature = null;
|
|
56553
57171
|
}
|
|
56554
57172
|
});
|
|
@@ -56661,8 +57279,8 @@ var init_code_command = __esm({
|
|
|
56661
57279
|
try {
|
|
56662
57280
|
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
57281
|
if (opts.planOnly) {
|
|
56664
|
-
const
|
|
56665
|
-
const
|
|
57282
|
+
const fs52 = await import('fs/promises');
|
|
57283
|
+
const path65 = await import('path');
|
|
56666
57284
|
const spec = res?.specMarkdown;
|
|
56667
57285
|
const lines = Array.isArray(res?.summaryLines) ? res.summaryLines : [];
|
|
56668
57286
|
const planItems = [];
|
|
@@ -56696,13 +57314,13 @@ var init_code_command = __esm({
|
|
|
56696
57314
|
if (planItems.length) md.push(...planItems);
|
|
56697
57315
|
else md.push("- (no summary available)");
|
|
56698
57316
|
}
|
|
56699
|
-
const plansDir =
|
|
56700
|
-
await
|
|
57317
|
+
const plansDir = path65.join(root, ".maria", "plans");
|
|
57318
|
+
await fs52.mkdir(plansDir, { recursive: true });
|
|
56701
57319
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
56702
57320
|
const fileName = `code-plan-${ts}.md`;
|
|
56703
|
-
const outPath =
|
|
56704
|
-
await
|
|
56705
|
-
const rel =
|
|
57321
|
+
const outPath = path65.join(plansDir, fileName);
|
|
57322
|
+
await fs52.writeFile(outPath, md.join("\n") + "\n", "utf8");
|
|
57323
|
+
const rel = path65.relative(root, outPath);
|
|
56706
57324
|
return this.success(`Code plan saved: ${rel}`);
|
|
56707
57325
|
}
|
|
56708
57326
|
const detail = res?.detailLines;
|
|
@@ -56762,6 +57380,97 @@ ${pretty}`);
|
|
|
56762
57380
|
// Add default language hints when not specified by the user (LLM-assisted detection)
|
|
56763
57381
|
async ensureLanguageDefaults(raw) {
|
|
56764
57382
|
try {
|
|
57383
|
+
const fs52 = await import('fs/promises');
|
|
57384
|
+
const pathMod = await import('path');
|
|
57385
|
+
const cwd2 = process.cwd();
|
|
57386
|
+
const ignoreDir = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".maria", ".next", "coverage", ".DS_Store", ".Spotlight-V100", ".Trashes", ".fseventsd", ".TemporaryItems"]);
|
|
57387
|
+
const pathTokens = /* @__PURE__ */ new Set();
|
|
57388
|
+
const fileLike = raw.match(/([\w\-./\\:]+\.[A-Za-z0-9]{1,10})/g) || [];
|
|
57389
|
+
for (const t2 of fileLike) pathTokens.add(t2);
|
|
57390
|
+
const slashLike = raw.match(/[^\s"']*[\\/][^\s"']+/g) || [];
|
|
57391
|
+
for (const t2 of slashLike) pathTokens.add(t2);
|
|
57392
|
+
const listFilesUnder = async (dir, maxCount) => {
|
|
57393
|
+
const out = [];
|
|
57394
|
+
const walk2 = async (d) => {
|
|
57395
|
+
if (out.length >= maxCount) return;
|
|
57396
|
+
let entries = [];
|
|
57397
|
+
try {
|
|
57398
|
+
entries = await fs52.readdir(d, { withFileTypes: true });
|
|
57399
|
+
} catch {
|
|
57400
|
+
return;
|
|
57401
|
+
}
|
|
57402
|
+
for (const e2 of entries) {
|
|
57403
|
+
const name2 = e2.name;
|
|
57404
|
+
if (ignoreDir.has(name2)) continue;
|
|
57405
|
+
const full = pathMod.join(d, name2);
|
|
57406
|
+
if (e2.isDirectory()) {
|
|
57407
|
+
await walk2(full);
|
|
57408
|
+
if (out.length >= maxCount) break;
|
|
57409
|
+
continue;
|
|
57410
|
+
}
|
|
57411
|
+
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)) {
|
|
57412
|
+
out.push(full);
|
|
57413
|
+
if (out.length >= maxCount) break;
|
|
57414
|
+
}
|
|
57415
|
+
}
|
|
57416
|
+
};
|
|
57417
|
+
await walk2(dir);
|
|
57418
|
+
return out;
|
|
57419
|
+
};
|
|
57420
|
+
const readHead = async (full, lines) => {
|
|
57421
|
+
try {
|
|
57422
|
+
const buf = await fs52.readFile(full, "utf8");
|
|
57423
|
+
return buf.split(/\r?\n/).slice(0, lines).join("\n");
|
|
57424
|
+
} catch {
|
|
57425
|
+
return "";
|
|
57426
|
+
}
|
|
57427
|
+
};
|
|
57428
|
+
const samples = [];
|
|
57429
|
+
for (const tok of Array.from(pathTokens)) {
|
|
57430
|
+
const abs = pathMod.isAbsolute(tok) ? tok : pathMod.join(cwd2, tok);
|
|
57431
|
+
try {
|
|
57432
|
+
const st = await fs52.stat(abs);
|
|
57433
|
+
if (st.isFile()) {
|
|
57434
|
+
samples.push(await readHead(abs, 10));
|
|
57435
|
+
} else if (st.isDirectory()) {
|
|
57436
|
+
const files = await listFilesUnder(abs, 25);
|
|
57437
|
+
for (const f3 of files) samples.push(await readHead(f3, 10));
|
|
57438
|
+
}
|
|
57439
|
+
} catch {
|
|
57440
|
+
}
|
|
57441
|
+
if (samples.length >= 50) break;
|
|
57442
|
+
}
|
|
57443
|
+
if (samples.length > 0) {
|
|
57444
|
+
const preSpin = new ProcessAnimation();
|
|
57445
|
+
preSpin.start();
|
|
57446
|
+
let llmLang = null;
|
|
57447
|
+
try {
|
|
57448
|
+
llmLang = await this.detectLanguageLLMFromSamples(samples);
|
|
57449
|
+
} finally {
|
|
57450
|
+
try {
|
|
57451
|
+
preSpin.stop();
|
|
57452
|
+
} catch {
|
|
57453
|
+
}
|
|
57454
|
+
}
|
|
57455
|
+
if (llmLang) {
|
|
57456
|
+
const hint2 = (() => {
|
|
57457
|
+
const l = llmLang.toLowerCase();
|
|
57458
|
+
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
57459
|
+
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
57460
|
+
if (l === "typescript") return "TypeScript";
|
|
57461
|
+
if (l === "javascript") return "JavaScript";
|
|
57462
|
+
if (l === "html") return "HTML";
|
|
57463
|
+
if (l === "css") return "CSS";
|
|
57464
|
+
return llmLang;
|
|
57465
|
+
})();
|
|
57466
|
+
return raw + ` (Use ${hint2})`;
|
|
57467
|
+
}
|
|
57468
|
+
}
|
|
57469
|
+
} catch {
|
|
57470
|
+
}
|
|
57471
|
+
try {
|
|
57472
|
+
const preSpin = new ProcessAnimation();
|
|
57473
|
+
preSpin.start();
|
|
56765
57474
|
const system = [
|
|
56766
57475
|
"You analyze a user's code-generation request.",
|
|
56767
57476
|
"Decide if the user explicitly specified a programming language or framework/tooling (e.g., TypeScript, Python, Rust, Java, React, Vue, Node, etc.).",
|
|
@@ -56780,8 +57489,12 @@ ${pretty}`);
|
|
|
56780
57489
|
${user}`
|
|
56781
57490
|
}
|
|
56782
57491
|
});
|
|
57492
|
+
try {
|
|
57493
|
+
preSpin.stop();
|
|
57494
|
+
} catch {
|
|
57495
|
+
}
|
|
56783
57496
|
const content = (resp?.data?.content || resp?.content || "").trim();
|
|
56784
|
-
const
|
|
57497
|
+
const extractFirstJson7 = (text) => {
|
|
56785
57498
|
const fence = /```\s*json\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
56786
57499
|
if (fence) return fence[1];
|
|
56787
57500
|
const generic = /```\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
@@ -56804,7 +57517,7 @@ ${user}`
|
|
|
56804
57517
|
}
|
|
56805
57518
|
return null;
|
|
56806
57519
|
};
|
|
56807
|
-
const jsonText =
|
|
57520
|
+
const jsonText = extractFirstJson7(content) || content;
|
|
56808
57521
|
let parsed = {};
|
|
56809
57522
|
try {
|
|
56810
57523
|
parsed = JSON.parse(jsonText);
|
|
@@ -56817,6 +57530,76 @@ ${user}`
|
|
|
56817
57530
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
56818
57531
|
return raw + hint;
|
|
56819
57532
|
}
|
|
57533
|
+
// LLM-based language detection from sample code heads (top-10 lines per file)
|
|
57534
|
+
async detectLanguageLLMFromSamples(samples) {
|
|
57535
|
+
try {
|
|
57536
|
+
const system = [
|
|
57537
|
+
"You are a programming language classifier.",
|
|
57538
|
+
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
57539
|
+
"Respond with ONLY a single token language name from this set:",
|
|
57540
|
+
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
57541
|
+
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
57542
|
+
].join("\n");
|
|
57543
|
+
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
57544
|
+
${s2}`).join("\n\n");
|
|
57545
|
+
const { callAPI: callAPI2 } = await Promise.resolve().then(() => (init_api_caller(), api_caller_exports));
|
|
57546
|
+
const resp = await callAPI2("/v1/ai-proxy", {
|
|
57547
|
+
method: "POST",
|
|
57548
|
+
body: {
|
|
57549
|
+
provider: "google",
|
|
57550
|
+
model: "gemini-2.5-flash",
|
|
57551
|
+
taskType: "chat",
|
|
57552
|
+
prompt: `${system}
|
|
57553
|
+
|
|
57554
|
+
${joined}`
|
|
57555
|
+
}
|
|
57556
|
+
});
|
|
57557
|
+
const content = (resp?.data?.content || resp?.content || "").trim();
|
|
57558
|
+
const token = content.replace(/```[\s\S]*?```/g, "").trim().toLowerCase();
|
|
57559
|
+
const norm = this.normalizeLanguageName(token);
|
|
57560
|
+
return norm || null;
|
|
57561
|
+
} catch {
|
|
57562
|
+
return null;
|
|
57563
|
+
}
|
|
57564
|
+
}
|
|
57565
|
+
normalizeLanguageName(lang) {
|
|
57566
|
+
const l = (lang || "").toLowerCase().trim();
|
|
57567
|
+
if (!l) return null;
|
|
57568
|
+
const map = {
|
|
57569
|
+
"ts": "typescript",
|
|
57570
|
+
"typescript": "typescript",
|
|
57571
|
+
"tsx": "tsx",
|
|
57572
|
+
"jsx": "jsx",
|
|
57573
|
+
"js": "javascript",
|
|
57574
|
+
"javascript": "javascript",
|
|
57575
|
+
"py": "python",
|
|
57576
|
+
"python": "python",
|
|
57577
|
+
"java": "java",
|
|
57578
|
+
"go": "go",
|
|
57579
|
+
"rust": "rust",
|
|
57580
|
+
"rs": "rust",
|
|
57581
|
+
"php": "php",
|
|
57582
|
+
"c++": "cpp",
|
|
57583
|
+
"cpp": "cpp",
|
|
57584
|
+
"c": "c",
|
|
57585
|
+
"swift": "swift",
|
|
57586
|
+
"kotlin": "kotlin",
|
|
57587
|
+
"rb": "ruby",
|
|
57588
|
+
"ruby": "ruby",
|
|
57589
|
+
"cs": "csharp",
|
|
57590
|
+
"c#": "csharp",
|
|
57591
|
+
"csharp": "csharp",
|
|
57592
|
+
"html": "html",
|
|
57593
|
+
"css": "css",
|
|
57594
|
+
"scss": "scss",
|
|
57595
|
+
"json": "json",
|
|
57596
|
+
"yaml": "yaml",
|
|
57597
|
+
"yml": "yaml",
|
|
57598
|
+
"markdown": "markdown",
|
|
57599
|
+
"md": "markdown"
|
|
57600
|
+
};
|
|
57601
|
+
return map[l] || null;
|
|
57602
|
+
}
|
|
56820
57603
|
// v2.0 helpers
|
|
56821
57604
|
parseV2Options(raw) {
|
|
56822
57605
|
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 +57795,16 @@ ${user}`
|
|
|
57012
57795
|
}
|
|
57013
57796
|
async persistLastPlan(root, plans) {
|
|
57014
57797
|
try {
|
|
57015
|
-
const
|
|
57798
|
+
const fs52 = await import('fs/promises');
|
|
57016
57799
|
const p = path11__namespace.join(root, ".maria");
|
|
57017
|
-
await
|
|
57800
|
+
await fs52.mkdir(p, { recursive: true });
|
|
57018
57801
|
const out = path11__namespace.join(p, "last-plan.json");
|
|
57019
|
-
await
|
|
57802
|
+
await fs52.writeFile(out, JSON.stringify({ createdAt: (/* @__PURE__ */ new Date()).toISOString(), plans }, null, 2), "utf8");
|
|
57020
57803
|
} catch {
|
|
57021
57804
|
}
|
|
57022
57805
|
}
|
|
57023
57806
|
async applyPlan(plans, options) {
|
|
57024
|
-
const
|
|
57807
|
+
const fs52 = await import('fs/promises');
|
|
57025
57808
|
const created = [];
|
|
57026
57809
|
const modified = [];
|
|
57027
57810
|
const skipped = [];
|
|
@@ -57040,9 +57823,9 @@ ${user}`
|
|
|
57040
57823
|
continue;
|
|
57041
57824
|
}
|
|
57042
57825
|
const tmp = full + `.tmp-${process.pid}-${Date.now()}`;
|
|
57043
|
-
await
|
|
57044
|
-
await
|
|
57045
|
-
await
|
|
57826
|
+
await fs52.mkdir(path11__namespace.dirname(full), { recursive: true });
|
|
57827
|
+
await fs52.writeFile(tmp, plan.preview || "", "utf8");
|
|
57828
|
+
await fs52.rename(tmp, full);
|
|
57046
57829
|
if (exists2) modified.push(plan.path);
|
|
57047
57830
|
else created.push(plan.path);
|
|
57048
57831
|
written++;
|
|
@@ -57053,7 +57836,7 @@ ${user}`
|
|
|
57053
57836
|
if (options.rollback) {
|
|
57054
57837
|
for (const p of [...created, ...modified]) {
|
|
57055
57838
|
try {
|
|
57056
|
-
await
|
|
57839
|
+
await fs52.unlink(path11__namespace.join(options.root, p));
|
|
57057
57840
|
} catch {
|
|
57058
57841
|
}
|
|
57059
57842
|
}
|
|
@@ -57063,8 +57846,8 @@ ${user}`
|
|
|
57063
57846
|
}
|
|
57064
57847
|
async pathExists(p) {
|
|
57065
57848
|
try {
|
|
57066
|
-
const
|
|
57067
|
-
await
|
|
57849
|
+
const fs52 = await import('fs/promises');
|
|
57850
|
+
await fs52.access(p);
|
|
57068
57851
|
return true;
|
|
57069
57852
|
} catch {
|
|
57070
57853
|
return false;
|
|
@@ -57175,17 +57958,17 @@ ${user}`
|
|
|
57175
57958
|
// Attempt to collect attached files from context; map to AttachedFileContext
|
|
57176
57959
|
async collectAttachedFiles(context2) {
|
|
57177
57960
|
const list = [];
|
|
57178
|
-
const
|
|
57179
|
-
const
|
|
57961
|
+
const fs52 = await import('fs/promises');
|
|
57962
|
+
const path65 = await import('path');
|
|
57180
57963
|
const att = context2 && (context2.attachments || context2.input?.attachments) || [];
|
|
57181
57964
|
for (const a of att) {
|
|
57182
57965
|
try {
|
|
57183
57966
|
const p = a.path || a.filePath || a.name || "";
|
|
57184
|
-
const originalName = a.name ||
|
|
57967
|
+
const originalName = a.name || path65.basename(p || `attachment_${Date.now().toString(36)}`);
|
|
57185
57968
|
let content = a.content;
|
|
57186
57969
|
if (!content && p) {
|
|
57187
|
-
const abs =
|
|
57188
|
-
content = await
|
|
57970
|
+
const abs = path65.isAbsolute(p) ? p : path65.join(process.cwd(), p);
|
|
57971
|
+
content = await fs52.readFile(abs, "utf8");
|
|
57189
57972
|
}
|
|
57190
57973
|
if (!content) continue;
|
|
57191
57974
|
list.push({ originalName, pathHint: p || void 0, content, size: Buffer.byteLength(content, "utf8"), mime: a.mime || a.type });
|
|
@@ -63874,17 +64657,17 @@ var init_GraphEngine = __esm({
|
|
|
63874
64657
|
const visited = /* @__PURE__ */ new Set();
|
|
63875
64658
|
const queue = [{ id: from, path: [from] }];
|
|
63876
64659
|
while (queue.length) {
|
|
63877
|
-
const { id, path:
|
|
64660
|
+
const { id, path: path65 } = queue.shift();
|
|
63878
64661
|
if (visited.has(id)) continue;
|
|
63879
64662
|
visited.add(id);
|
|
63880
64663
|
const neighbors = this.edges.get(id) || /* @__PURE__ */ new Set();
|
|
63881
64664
|
for (const e2 of neighbors) {
|
|
63882
64665
|
if (e2.to === to) {
|
|
63883
|
-
const res = [...
|
|
64666
|
+
const res = [...path65, to];
|
|
63884
64667
|
this.recordQueryTime(Date.now() - start);
|
|
63885
64668
|
return res;
|
|
63886
64669
|
}
|
|
63887
|
-
if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...
|
|
64670
|
+
if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...path65, e2.to] });
|
|
63888
64671
|
}
|
|
63889
64672
|
}
|
|
63890
64673
|
this.recordQueryTime(Date.now() - start);
|
|
@@ -66551,12 +67334,12 @@ This will:
|
|
|
66551
67334
|
};
|
|
66552
67335
|
const result = await this.deltaDetector.detectDelta(root, deltaOptions);
|
|
66553
67336
|
const files = [
|
|
66554
|
-
...result.changed.map((
|
|
66555
|
-
_path:
|
|
66556
|
-
type: previousState?.fileHashes?.[
|
|
67337
|
+
...result.changed.map((path65) => ({
|
|
67338
|
+
_path: path65,
|
|
67339
|
+
type: previousState?.fileHashes?.[path65] ? "modified" : "added"
|
|
66557
67340
|
})),
|
|
66558
|
-
...result.deleted.map((
|
|
66559
|
-
_path:
|
|
67341
|
+
...result.deleted.map((path65) => ({
|
|
67342
|
+
_path: path65,
|
|
66560
67343
|
type: "deleted"
|
|
66561
67344
|
}))
|
|
66562
67345
|
];
|
|
@@ -69992,13 +70775,13 @@ async function checkShield(commandName, userPlan = "free") {
|
|
|
69992
70775
|
}
|
|
69993
70776
|
async function loadManifest() {
|
|
69994
70777
|
try {
|
|
69995
|
-
const
|
|
69996
|
-
const
|
|
69997
|
-
const manifestPath =
|
|
70778
|
+
const fs52 = await import('fs');
|
|
70779
|
+
const path65 = await import('path');
|
|
70780
|
+
const manifestPath = path65.join(
|
|
69998
70781
|
__dirname,
|
|
69999
70782
|
"../command-manifest-v2.1.json"
|
|
70000
70783
|
);
|
|
70001
|
-
const content =
|
|
70784
|
+
const content = fs52.readFileSync(manifestPath, "utf-8");
|
|
70002
70785
|
return JSON.parse(content);
|
|
70003
70786
|
} catch {
|
|
70004
70787
|
return { commands: [] };
|
|
@@ -71493,7 +72276,7 @@ ${user}`,
|
|
|
71493
72276
|
};
|
|
71494
72277
|
}
|
|
71495
72278
|
});
|
|
71496
|
-
function
|
|
72279
|
+
function extractFirstJson6(text) {
|
|
71497
72280
|
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
71498
72281
|
if (fence) return fence[1];
|
|
71499
72282
|
const start = text.indexOf("{");
|
|
@@ -71540,7 +72323,7 @@ ${user}`,
|
|
|
71540
72323
|
}
|
|
71541
72324
|
});
|
|
71542
72325
|
const raw = (response?.data?.content || response?.output || "").trim();
|
|
71543
|
-
const jsonText =
|
|
72326
|
+
const jsonText = extractFirstJson6(raw) || raw;
|
|
71544
72327
|
let parsed = {};
|
|
71545
72328
|
try {
|
|
71546
72329
|
parsed = JSON.parse(jsonText);
|
|
@@ -72400,6 +73183,15 @@ async function registerBuiltInCommands() {
|
|
|
72400
73183
|
} catch (error2) {
|
|
72401
73184
|
console.error("Failed to register media commands:", error2);
|
|
72402
73185
|
}
|
|
73186
|
+
try {
|
|
73187
|
+
const NovelModule = await Promise.resolve().then(() => (init_novel_command(), novel_command_exports));
|
|
73188
|
+
const NovelClass = NovelModule.NovelCommand || NovelModule.default;
|
|
73189
|
+
const novel = new NovelClass();
|
|
73190
|
+
if (novel.initialize) await novel.initialize();
|
|
73191
|
+
commandRegistry.register(novel);
|
|
73192
|
+
} catch (error2) {
|
|
73193
|
+
console.error("Failed to register novel command:", error2);
|
|
73194
|
+
}
|
|
72403
73195
|
try {
|
|
72404
73196
|
const { codeCommand: codeCommand2 } = await Promise.resolve().then(() => (init_code_command(), code_command_exports));
|
|
72405
73197
|
try {
|
|
@@ -74932,16 +75724,16 @@ var init_ai_response_service = __esm({
|
|
|
74932
75724
|
if (p) candidates.add(p);
|
|
74933
75725
|
}
|
|
74934
75726
|
if (candidates.size > 0) {
|
|
74935
|
-
const
|
|
75727
|
+
const fs52 = await import('fs/promises');
|
|
74936
75728
|
const pathMod = await import('path');
|
|
74937
75729
|
const cwd2 = process.cwd();
|
|
74938
75730
|
for (const cand of candidates) {
|
|
74939
75731
|
try {
|
|
74940
75732
|
const normalized = cand.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
74941
75733
|
const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(cwd2, normalized);
|
|
74942
|
-
const st = await
|
|
75734
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
74943
75735
|
if (!st || !st.isFile()) continue;
|
|
74944
|
-
const buf = await
|
|
75736
|
+
const buf = await fs52.readFile(abs);
|
|
74945
75737
|
const ext2 = (pathMod.extname(abs) || "").toLowerCase();
|
|
74946
75738
|
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
75739
|
autoAttachments.push({ name: pathMod.basename(abs), path: abs, mime, data_base64: buf.toString("base64") });
|