@bonginkan/maria 4.3.37 → 4.3.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/READY.manifest.json +19 -3
- package/dist/bin/maria.cjs +1130 -768
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +1127 -765
- 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 +155 -24
- package/dist/server/express-server.js +155 -24
- package/dist/server-express.cjs +155 -24
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +19 -3
package/dist/cli.cjs
CHANGED
|
@@ -189,13 +189,13 @@ function getPackageJson() {
|
|
|
189
189
|
)
|
|
190
190
|
];
|
|
191
191
|
let packageJsonPath = null;
|
|
192
|
-
for (const
|
|
193
|
-
if (fs19.existsSync(
|
|
192
|
+
for (const path65 of possiblePaths) {
|
|
193
|
+
if (fs19.existsSync(path65)) {
|
|
194
194
|
try {
|
|
195
|
-
const content = fs19.readFileSync(
|
|
195
|
+
const content = fs19.readFileSync(path65, "utf-8");
|
|
196
196
|
const parsed = JSON.parse(content);
|
|
197
197
|
if (parsed.name === "@bonginkan/maria") {
|
|
198
|
-
packageJsonPath =
|
|
198
|
+
packageJsonPath = path65;
|
|
199
199
|
break;
|
|
200
200
|
}
|
|
201
201
|
} catch {
|
|
@@ -1709,7 +1709,7 @@ var init_AuthenticationManager = __esm({
|
|
|
1709
1709
|
const response = await fetch(`${this.apiBase}/api/user/profile`, {
|
|
1710
1710
|
headers: {
|
|
1711
1711
|
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
1712
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
1712
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.39"}`
|
|
1713
1713
|
}
|
|
1714
1714
|
});
|
|
1715
1715
|
if (response.status === 401) {
|
|
@@ -2421,9 +2421,9 @@ function clientThrottle(endpoint) {
|
|
|
2421
2421
|
}
|
|
2422
2422
|
rateLimitMap.set(endpoint, now2);
|
|
2423
2423
|
}
|
|
2424
|
-
async function callApi(
|
|
2424
|
+
async function callApi(path65, init3 = {}) {
|
|
2425
2425
|
const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
2426
|
-
const fullUrl = `${apiBase}${
|
|
2426
|
+
const fullUrl = `${apiBase}${path65}`;
|
|
2427
2427
|
let tokens2 = await authManager.getValidTokens();
|
|
2428
2428
|
if (!tokens2) {
|
|
2429
2429
|
console.log(chalk40__default.default.red(ERR.AUTH_REQUIRED.msg));
|
|
@@ -2434,7 +2434,7 @@ async function callApi(path64, init3 = {}) {
|
|
|
2434
2434
|
"Authorization": `Bearer ${token}`,
|
|
2435
2435
|
"X-Device-Id": getDeviceId(),
|
|
2436
2436
|
"X-Session-Id": getSessionId() || "",
|
|
2437
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
2437
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.39"}`,
|
|
2438
2438
|
"Content-Type": init3.headers?.["Content-Type"] || "application/json"
|
|
2439
2439
|
});
|
|
2440
2440
|
const doFetch = async (token) => {
|
|
@@ -2492,8 +2492,8 @@ async function callApi(path64, init3 = {}) {
|
|
|
2492
2492
|
}
|
|
2493
2493
|
return response;
|
|
2494
2494
|
}
|
|
2495
|
-
async function callApiJson(
|
|
2496
|
-
const response = await callApi(
|
|
2495
|
+
async function callApiJson(path65, init3 = {}) {
|
|
2496
|
+
const response = await callApi(path65, init3);
|
|
2497
2497
|
if (!response.ok) {
|
|
2498
2498
|
const error2 = await response.json().catch(() => ({
|
|
2499
2499
|
message: `API error: ${response.status} ${response.statusText}`
|
|
@@ -2502,8 +2502,8 @@ async function callApiJson(path64, init3 = {}) {
|
|
|
2502
2502
|
}
|
|
2503
2503
|
return response.json();
|
|
2504
2504
|
}
|
|
2505
|
-
async function* streamApi(
|
|
2506
|
-
const response = await callApi(
|
|
2505
|
+
async function* streamApi(path65, init3 = {}) {
|
|
2506
|
+
const response = await callApi(path65, {
|
|
2507
2507
|
...init3,
|
|
2508
2508
|
headers: {
|
|
2509
2509
|
...init3.headers,
|
|
@@ -2529,13 +2529,13 @@ async function* streamApi(path64, init3 = {}) {
|
|
|
2529
2529
|
reader.releaseLock();
|
|
2530
2530
|
}
|
|
2531
2531
|
}
|
|
2532
|
-
async function uploadFile(
|
|
2532
|
+
async function uploadFile(path65, file, metadata5 = {}) {
|
|
2533
2533
|
const formData = new FormData();
|
|
2534
2534
|
formData.append("file", new Blob([file]));
|
|
2535
2535
|
Object.entries(metadata5).forEach(([key, value]) => {
|
|
2536
2536
|
formData.append(key, String(value));
|
|
2537
2537
|
});
|
|
2538
|
-
return callApiJson(
|
|
2538
|
+
return callApiJson(path65, {
|
|
2539
2539
|
method: "POST",
|
|
2540
2540
|
body: formData,
|
|
2541
2541
|
headers: {
|
|
@@ -3208,7 +3208,7 @@ async function mapInputToTopLevelCommand(input3) {
|
|
|
3208
3208
|
const system = [
|
|
3209
3209
|
"You are a router for the MARIA CLI.",
|
|
3210
3210
|
"Decide the best command for a single user input.",
|
|
3211
|
-
"Allowed commands: /help, /image, /code, /video, /whoami, /login, /logout, /evaluate, chat.",
|
|
3211
|
+
"Allowed commands: /help, /image, /code, /video, /whoami, /login, /logout, /evaluate, /research, /novel, chat.",
|
|
3212
3212
|
"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).",
|
|
3213
3213
|
'Return JSON only with keys: { "command": string, "args"?: string[], "confidence": number }.',
|
|
3214
3214
|
"Select chat when the input is a general question or conversation rather than a specific slash command.",
|
|
@@ -3236,7 +3236,7 @@ ${input3}`,
|
|
|
3236
3236
|
}
|
|
3237
3237
|
if (!parsed || typeof parsed.command !== "string") return null;
|
|
3238
3238
|
const cmd = parsed.command;
|
|
3239
|
-
if (!["/help", "/image", "/code", "/video", "/whoami", "/login", "/logout", "/evaluate", "chat"].includes(cmd)) return null;
|
|
3239
|
+
if (!["/help", "/image", "/code", "/video", "/whoami", "/login", "/logout", "/evaluate", "/research", "/novel", "chat"].includes(cmd)) return null;
|
|
3240
3240
|
const out = { command: cmd };
|
|
3241
3241
|
if (Array.isArray(parsed.args)) {
|
|
3242
3242
|
out.args = parsed.args.filter((a) => typeof a === "string" && a.trim()).map((s2) => s2.trim());
|
|
@@ -8114,12 +8114,12 @@ var init_esm4 = __esm({
|
|
|
8114
8114
|
/**
|
|
8115
8115
|
* Get the Path object referenced by the string path, resolved from this Path
|
|
8116
8116
|
*/
|
|
8117
|
-
resolve(
|
|
8118
|
-
if (!
|
|
8117
|
+
resolve(path65) {
|
|
8118
|
+
if (!path65) {
|
|
8119
8119
|
return this;
|
|
8120
8120
|
}
|
|
8121
|
-
const rootPath = this.getRootString(
|
|
8122
|
-
const dir =
|
|
8121
|
+
const rootPath = this.getRootString(path65);
|
|
8122
|
+
const dir = path65.substring(rootPath.length);
|
|
8123
8123
|
const dirParts = dir.split(this.splitSep);
|
|
8124
8124
|
const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
|
|
8125
8125
|
return result;
|
|
@@ -8871,8 +8871,8 @@ var init_esm4 = __esm({
|
|
|
8871
8871
|
/**
|
|
8872
8872
|
* @internal
|
|
8873
8873
|
*/
|
|
8874
|
-
getRootString(
|
|
8875
|
-
return path10.win32.parse(
|
|
8874
|
+
getRootString(path65) {
|
|
8875
|
+
return path10.win32.parse(path65).root;
|
|
8876
8876
|
}
|
|
8877
8877
|
/**
|
|
8878
8878
|
* @internal
|
|
@@ -8918,8 +8918,8 @@ var init_esm4 = __esm({
|
|
|
8918
8918
|
/**
|
|
8919
8919
|
* @internal
|
|
8920
8920
|
*/
|
|
8921
|
-
getRootString(
|
|
8922
|
-
return
|
|
8921
|
+
getRootString(path65) {
|
|
8922
|
+
return path65.startsWith("/") ? "/" : "";
|
|
8923
8923
|
}
|
|
8924
8924
|
/**
|
|
8925
8925
|
* @internal
|
|
@@ -8968,8 +8968,8 @@ var init_esm4 = __esm({
|
|
|
8968
8968
|
*
|
|
8969
8969
|
* @internal
|
|
8970
8970
|
*/
|
|
8971
|
-
constructor(cwd2 = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs:
|
|
8972
|
-
this.#fs = fsFromOption(
|
|
8971
|
+
constructor(cwd2 = process.cwd(), pathImpl, sep4, { nocase, childrenCacheSize = 16 * 1024, fs: fs52 = defaultFS } = {}) {
|
|
8972
|
+
this.#fs = fsFromOption(fs52);
|
|
8973
8973
|
if (cwd2 instanceof URL || cwd2.startsWith("file://")) {
|
|
8974
8974
|
cwd2 = url.fileURLToPath(cwd2);
|
|
8975
8975
|
}
|
|
@@ -9008,11 +9008,11 @@ var init_esm4 = __esm({
|
|
|
9008
9008
|
/**
|
|
9009
9009
|
* Get the depth of a provided path, string, or the cwd
|
|
9010
9010
|
*/
|
|
9011
|
-
depth(
|
|
9012
|
-
if (typeof
|
|
9013
|
-
|
|
9011
|
+
depth(path65 = this.cwd) {
|
|
9012
|
+
if (typeof path65 === "string") {
|
|
9013
|
+
path65 = this.cwd.resolve(path65);
|
|
9014
9014
|
}
|
|
9015
|
-
return
|
|
9015
|
+
return path65.depth();
|
|
9016
9016
|
}
|
|
9017
9017
|
/**
|
|
9018
9018
|
* Return the cache of child entries. Exposed so subclasses can create
|
|
@@ -9499,9 +9499,9 @@ var init_esm4 = __esm({
|
|
|
9499
9499
|
process11();
|
|
9500
9500
|
return results;
|
|
9501
9501
|
}
|
|
9502
|
-
chdir(
|
|
9502
|
+
chdir(path65 = this.cwd) {
|
|
9503
9503
|
const oldCwd = this.cwd;
|
|
9504
|
-
this.cwd = typeof
|
|
9504
|
+
this.cwd = typeof path65 === "string" ? this.cwd.resolve(path65) : path65;
|
|
9505
9505
|
this.cwd[setAsCwd](oldCwd);
|
|
9506
9506
|
}
|
|
9507
9507
|
};
|
|
@@ -9527,8 +9527,8 @@ var init_esm4 = __esm({
|
|
|
9527
9527
|
/**
|
|
9528
9528
|
* @internal
|
|
9529
9529
|
*/
|
|
9530
|
-
newRoot(
|
|
9531
|
-
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
9530
|
+
newRoot(fs52) {
|
|
9531
|
+
return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs52 });
|
|
9532
9532
|
}
|
|
9533
9533
|
/**
|
|
9534
9534
|
* Return true if the provided path string is an absolute path
|
|
@@ -9556,8 +9556,8 @@ var init_esm4 = __esm({
|
|
|
9556
9556
|
/**
|
|
9557
9557
|
* @internal
|
|
9558
9558
|
*/
|
|
9559
|
-
newRoot(
|
|
9560
|
-
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs:
|
|
9559
|
+
newRoot(fs52) {
|
|
9560
|
+
return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs52 });
|
|
9561
9561
|
}
|
|
9562
9562
|
/**
|
|
9563
9563
|
* Return true if the provided path string is an absolute path
|
|
@@ -9876,8 +9876,8 @@ var init_processor = __esm({
|
|
|
9876
9876
|
}
|
|
9877
9877
|
// match, absolute, ifdir
|
|
9878
9878
|
entries() {
|
|
9879
|
-
return [...this.store.entries()].map(([
|
|
9880
|
-
|
|
9879
|
+
return [...this.store.entries()].map(([path65, n]) => [
|
|
9880
|
+
path65,
|
|
9881
9881
|
!!(n & 2),
|
|
9882
9882
|
!!(n & 1)
|
|
9883
9883
|
]);
|
|
@@ -10090,9 +10090,9 @@ var init_walker = __esm({
|
|
|
10090
10090
|
signal;
|
|
10091
10091
|
maxDepth;
|
|
10092
10092
|
includeChildMatches;
|
|
10093
|
-
constructor(patterns,
|
|
10093
|
+
constructor(patterns, path65, opts) {
|
|
10094
10094
|
this.patterns = patterns;
|
|
10095
|
-
this.path =
|
|
10095
|
+
this.path = path65;
|
|
10096
10096
|
this.opts = opts;
|
|
10097
10097
|
this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
|
|
10098
10098
|
this.includeChildMatches = opts.includeChildMatches !== false;
|
|
@@ -10111,11 +10111,11 @@ var init_walker = __esm({
|
|
|
10111
10111
|
});
|
|
10112
10112
|
}
|
|
10113
10113
|
}
|
|
10114
|
-
#ignored(
|
|
10115
|
-
return this.seen.has(
|
|
10114
|
+
#ignored(path65) {
|
|
10115
|
+
return this.seen.has(path65) || !!this.#ignore?.ignored?.(path65);
|
|
10116
10116
|
}
|
|
10117
|
-
#childrenIgnored(
|
|
10118
|
-
return !!this.#ignore?.childrenIgnored?.(
|
|
10117
|
+
#childrenIgnored(path65) {
|
|
10118
|
+
return !!this.#ignore?.childrenIgnored?.(path65);
|
|
10119
10119
|
}
|
|
10120
10120
|
// backpressure mechanism
|
|
10121
10121
|
pause() {
|
|
@@ -10330,8 +10330,8 @@ var init_walker = __esm({
|
|
|
10330
10330
|
};
|
|
10331
10331
|
GlobWalker = class extends GlobUtil {
|
|
10332
10332
|
matches = /* @__PURE__ */ new Set();
|
|
10333
|
-
constructor(patterns,
|
|
10334
|
-
super(patterns,
|
|
10333
|
+
constructor(patterns, path65, opts) {
|
|
10334
|
+
super(patterns, path65, opts);
|
|
10335
10335
|
}
|
|
10336
10336
|
matchEmit(e2) {
|
|
10337
10337
|
this.matches.add(e2);
|
|
@@ -10368,8 +10368,8 @@ var init_walker = __esm({
|
|
|
10368
10368
|
};
|
|
10369
10369
|
GlobStream = class extends GlobUtil {
|
|
10370
10370
|
results;
|
|
10371
|
-
constructor(patterns,
|
|
10372
|
-
super(patterns,
|
|
10371
|
+
constructor(patterns, path65, opts) {
|
|
10372
|
+
super(patterns, path65, opts);
|
|
10373
10373
|
this.results = new Minipass({
|
|
10374
10374
|
signal: this.signal,
|
|
10375
10375
|
objectMode: true
|
|
@@ -16225,9 +16225,9 @@ var init_SafetyGuard = __esm({
|
|
|
16225
16225
|
}
|
|
16226
16226
|
}
|
|
16227
16227
|
if (action.args.paths && Array.isArray(action.args.paths)) {
|
|
16228
|
-
for (const
|
|
16229
|
-
if (!this.validatePath(
|
|
16230
|
-
violations.push(`Invalid path: ${
|
|
16228
|
+
for (const path65 of action.args.paths) {
|
|
16229
|
+
if (!this.validatePath(path65)) {
|
|
16230
|
+
violations.push(`Invalid path: ${path65}`);
|
|
16231
16231
|
}
|
|
16232
16232
|
}
|
|
16233
16233
|
}
|
|
@@ -16283,15 +16283,15 @@ var init_SafetyGuard = __esm({
|
|
|
16283
16283
|
* Validate file path against allowed/blocked lists
|
|
16284
16284
|
*/
|
|
16285
16285
|
validatePath(filePath) {
|
|
16286
|
-
const
|
|
16287
|
-
const resolvedPath =
|
|
16286
|
+
const path65 = __require("path");
|
|
16287
|
+
const resolvedPath = path65.resolve(filePath);
|
|
16288
16288
|
for (const blockedPath of this.constraints.blockedPaths) {
|
|
16289
|
-
if (resolvedPath.startsWith(
|
|
16289
|
+
if (resolvedPath.startsWith(path65.resolve(blockedPath))) {
|
|
16290
16290
|
return false;
|
|
16291
16291
|
}
|
|
16292
16292
|
}
|
|
16293
16293
|
for (const allowedPath of this.constraints.allowedPaths) {
|
|
16294
|
-
if (resolvedPath.startsWith(
|
|
16294
|
+
if (resolvedPath.startsWith(path65.resolve(allowedPath))) {
|
|
16295
16295
|
return true;
|
|
16296
16296
|
}
|
|
16297
16297
|
}
|
|
@@ -16320,9 +16320,9 @@ var init_SafetyGuard = __esm({
|
|
|
16320
16320
|
violations.push(`Invalid path in ${action.type}: ${action.args.path}`);
|
|
16321
16321
|
}
|
|
16322
16322
|
if (action.args.paths && Array.isArray(action.args.paths)) {
|
|
16323
|
-
for (const
|
|
16324
|
-
if (!this.validatePath(
|
|
16325
|
-
violations.push(`Invalid path in ${action.type}: ${
|
|
16323
|
+
for (const path65 of action.args.paths) {
|
|
16324
|
+
if (!this.validatePath(path65)) {
|
|
16325
|
+
violations.push(`Invalid path in ${action.type}: ${path65}`);
|
|
16326
16326
|
}
|
|
16327
16327
|
}
|
|
16328
16328
|
}
|
|
@@ -16382,8 +16382,8 @@ var require_package = __commonJS({
|
|
|
16382
16382
|
"package.json"(exports, module) {
|
|
16383
16383
|
module.exports = {
|
|
16384
16384
|
name: "@bonginkan/maria",
|
|
16385
|
-
version: "4.3.
|
|
16386
|
-
description: "\u{1F680} MARIA v4.3.
|
|
16385
|
+
version: "4.3.39",
|
|
16386
|
+
description: "\u{1F680} MARIA v4.3.39 - Enterprise AI Development Platform with identity system and character voice implementation. Features 74 production-ready commands with comprehensive fallback implementation, local LLM support, and zero external dependencies. Includes natural language coding, AI safety evaluation, intelligent evolution system, episodic memory with PII masking, and real-time monitoring dashboard. Built with TypeScript AST-powered code generation, OAuth2.0 + PKCE authentication, quantum-resistant cryptography, and enterprise-grade performance.",
|
|
16387
16387
|
keywords: [
|
|
16388
16388
|
"ai",
|
|
16389
16389
|
"cli",
|
|
@@ -17817,8 +17817,8 @@ var init_ConfigActionExecutor = __esm({
|
|
|
17817
17817
|
/**
|
|
17818
17818
|
* Set nested configuration value using dot notation
|
|
17819
17819
|
*/
|
|
17820
|
-
setNestedValue(obj,
|
|
17821
|
-
const keys =
|
|
17820
|
+
setNestedValue(obj, path65, value) {
|
|
17821
|
+
const keys = path65.split(".");
|
|
17822
17822
|
let current = obj;
|
|
17823
17823
|
for (let i2 = 0; i2 < keys.length - 1; i2++) {
|
|
17824
17824
|
const key = keys[i2];
|
|
@@ -26389,7 +26389,7 @@ var init_about_command = __esm({
|
|
|
26389
26389
|
async execute(args2, context2) {
|
|
26390
26390
|
const output3 = [];
|
|
26391
26391
|
output3.push("");
|
|
26392
|
-
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.
|
|
26392
|
+
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.39"));
|
|
26393
26393
|
output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
|
|
26394
26394
|
output3.push("");
|
|
26395
26395
|
output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -33959,22 +33959,22 @@ var init_from = __esm({
|
|
|
33959
33959
|
init_file();
|
|
33960
33960
|
init_fetch_blob();
|
|
33961
33961
|
({ stat: stat9 } = fs19.promises);
|
|
33962
|
-
blobFromSync = (
|
|
33963
|
-
blobFrom = (
|
|
33964
|
-
fileFrom = (
|
|
33965
|
-
fileFromSync = (
|
|
33966
|
-
fromBlob = (stat13,
|
|
33967
|
-
path:
|
|
33962
|
+
blobFromSync = (path65, type) => fromBlob(fs19.statSync(path65), path65, type);
|
|
33963
|
+
blobFrom = (path65, type) => stat9(path65).then((stat13) => fromBlob(stat13, path65, type));
|
|
33964
|
+
fileFrom = (path65, type) => stat9(path65).then((stat13) => fromFile(stat13, path65, type));
|
|
33965
|
+
fileFromSync = (path65, type) => fromFile(fs19.statSync(path65), path65, type);
|
|
33966
|
+
fromBlob = (stat13, path65, type = "") => new fetch_blob_default([new BlobDataItem({
|
|
33967
|
+
path: path65,
|
|
33968
33968
|
size: stat13.size,
|
|
33969
33969
|
lastModified: stat13.mtimeMs,
|
|
33970
33970
|
start: 0
|
|
33971
33971
|
})], { type });
|
|
33972
|
-
fromFile = (stat13,
|
|
33973
|
-
path:
|
|
33972
|
+
fromFile = (stat13, path65, type = "") => new file_default([new BlobDataItem({
|
|
33973
|
+
path: path65,
|
|
33974
33974
|
size: stat13.size,
|
|
33975
33975
|
lastModified: stat13.mtimeMs,
|
|
33976
33976
|
start: 0
|
|
33977
|
-
})], path10.basename(
|
|
33977
|
+
})], path10.basename(path65), { type, lastModified: stat13.mtimeMs });
|
|
33978
33978
|
BlobDataItem = class _BlobDataItem {
|
|
33979
33979
|
#path;
|
|
33980
33980
|
#start;
|
|
@@ -37743,12 +37743,12 @@ ${this.toYamlLike(value, indent + 1)}`;
|
|
|
37743
37743
|
}
|
|
37744
37744
|
static async loadFromFile(configPath) {
|
|
37745
37745
|
const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
|
|
37746
|
-
const
|
|
37746
|
+
const fs52 = await importNodeBuiltin2("fs");
|
|
37747
37747
|
const _path = await importNodeBuiltin2("_path");
|
|
37748
37748
|
const os23 = await importNodeBuiltin2("os");
|
|
37749
37749
|
const targetPath = configPath || _path.join(os23.homedir(), ".maria", "config.json");
|
|
37750
37750
|
try {
|
|
37751
|
-
const data = await
|
|
37751
|
+
const data = await fs52.promises.readFile(targetPath, "utf-8");
|
|
37752
37752
|
return JSON.parse(data);
|
|
37753
37753
|
} catch (innerError) {
|
|
37754
37754
|
if (innerError?.code === "ENOENT") {
|
|
@@ -37762,25 +37762,25 @@ ${this.toYamlLike(value, indent + 1)}`;
|
|
|
37762
37762
|
}
|
|
37763
37763
|
async save(configPath, options) {
|
|
37764
37764
|
const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
|
|
37765
|
-
const
|
|
37765
|
+
const fs52 = await importNodeBuiltin2("fs");
|
|
37766
37766
|
const _path = await importNodeBuiltin2("_path");
|
|
37767
37767
|
const os23 = await importNodeBuiltin2("os");
|
|
37768
37768
|
const targetPath = configPath || _path.join(os23.homedir(), ".maria", "config.json");
|
|
37769
37769
|
try {
|
|
37770
37770
|
if (options?.backup) {
|
|
37771
37771
|
try {
|
|
37772
|
-
await
|
|
37772
|
+
await fs52.promises.access(targetPath);
|
|
37773
37773
|
const backupPath = `${targetPath}.backup.${Date.now()}`;
|
|
37774
|
-
await
|
|
37774
|
+
await fs52.promises.copyFile(targetPath, backupPath);
|
|
37775
37775
|
} catch {
|
|
37776
37776
|
}
|
|
37777
37777
|
}
|
|
37778
|
-
await
|
|
37778
|
+
await fs52.promises.mkdir(_path.dirname(targetPath), { recursive: true });
|
|
37779
37779
|
const dataToSave = this.getAll({
|
|
37780
37780
|
maskSensitive: options?.maskSensitive ?? true,
|
|
37781
37781
|
includeSourceMap: options?.includeSourceMap ?? false
|
|
37782
37782
|
});
|
|
37783
|
-
await
|
|
37783
|
+
await fs52.promises.writeFile(
|
|
37784
37784
|
targetPath,
|
|
37785
37785
|
JSON.stringify(dataToSave, null, 2),
|
|
37786
37786
|
{ mode: 384 }
|
|
@@ -37824,12 +37824,12 @@ ${this.toYamlLike(value, indent + 1)}`;
|
|
|
37824
37824
|
}
|
|
37825
37825
|
if (outputPath) {
|
|
37826
37826
|
const { importNodeBuiltin: importNodeBuiltin2 } = await Promise.resolve().then(() => (init_import_helper(), import_helper_exports));
|
|
37827
|
-
const
|
|
37827
|
+
const fs52 = await importNodeBuiltin2("fs");
|
|
37828
37828
|
const _path = await importNodeBuiltin2(
|
|
37829
37829
|
"_path"
|
|
37830
37830
|
);
|
|
37831
|
-
await
|
|
37832
|
-
await
|
|
37831
|
+
await fs52.promises.mkdir(_path.dirname(outputPath), { recursive: true });
|
|
37832
|
+
await fs52.promises.writeFile(outputPath, content, "utf-8");
|
|
37833
37833
|
console.log(`\u2705 Configuration exported to ${outputPath}`);
|
|
37834
37834
|
}
|
|
37835
37835
|
return content;
|
|
@@ -38216,88 +38216,6 @@ var init_SystemCommandFactory = __esm({
|
|
|
38216
38216
|
};
|
|
38217
38217
|
}
|
|
38218
38218
|
});
|
|
38219
|
-
function handleRateLimitError(error2) {
|
|
38220
|
-
console.log();
|
|
38221
|
-
console.log(chalk40__default.default.yellow("\u23F1\uFE0F Rate Limit Exceeded"));
|
|
38222
|
-
console.log(chalk40__default.default.gray("\u2501".repeat(50)));
|
|
38223
|
-
const route = error2.route || error2.details?.endpoint || "API";
|
|
38224
|
-
const plan = error2.plan || error2.details?.plan || "Unknown";
|
|
38225
|
-
const limit = error2.limit || (error2.details?.limit ? parseInt(error2.details.limit) : null);
|
|
38226
|
-
const retryAfter = error2.retryAfter || error2.details?.retryAfterSeconds;
|
|
38227
|
-
const resetAt = error2.resetAt || (error2.details?.resetAt ? Date.parse(error2.details.resetAt) : null);
|
|
38228
|
-
const waitTime = Number.isFinite(retryAfter) ? `${retryAfter} second${retryAfter > 1 ? "s" : ""}` : "a few seconds";
|
|
38229
|
-
let resetTime = "";
|
|
38230
|
-
if (resetAt && Number.isFinite(resetAt)) {
|
|
38231
|
-
const resetDate = new Date(resetAt);
|
|
38232
|
-
const now2 = /* @__PURE__ */ new Date();
|
|
38233
|
-
const diffMs = resetDate.getTime() - now2.getTime();
|
|
38234
|
-
if (diffMs > 0 && diffMs < 6e4) {
|
|
38235
|
-
resetTime = `in ${Math.ceil(diffMs / 1e3)} seconds`;
|
|
38236
|
-
} else if (diffMs > 0) {
|
|
38237
|
-
resetTime = `at ${resetDate.toLocaleTimeString()}`;
|
|
38238
|
-
}
|
|
38239
|
-
}
|
|
38240
|
-
console.log(chalk40__default.default.white(`Plan: ${chalk40__default.default.bold(plan)}`));
|
|
38241
|
-
console.log(chalk40__default.default.white(`Endpoint: ${chalk40__default.default.bold(route)}`));
|
|
38242
|
-
if (limit !== null) {
|
|
38243
|
-
console.log(chalk40__default.default.white(`Limit: ${chalk40__default.default.bold(limit)} requests`));
|
|
38244
|
-
}
|
|
38245
|
-
if (error2.remaining !== void 0) {
|
|
38246
|
-
console.log(chalk40__default.default.white(`Remaining: ${chalk40__default.default.bold(error2.remaining)} requests`));
|
|
38247
|
-
}
|
|
38248
|
-
console.log();
|
|
38249
|
-
console.log(chalk40__default.default.cyan(`Please wait ${chalk40__default.default.bold(waitTime)} before trying again`));
|
|
38250
|
-
if (resetTime) {
|
|
38251
|
-
console.log(chalk40__default.default.gray(`Rate limit resets ${resetTime}`));
|
|
38252
|
-
}
|
|
38253
|
-
if (error2.hint) {
|
|
38254
|
-
console.log();
|
|
38255
|
-
console.log(chalk40__default.default.magenta("\u{1F4A1} " + error2.hint));
|
|
38256
|
-
}
|
|
38257
|
-
console.log(chalk40__default.default.gray("\u2501".repeat(50)));
|
|
38258
|
-
console.log();
|
|
38259
|
-
}
|
|
38260
|
-
async function parseRateLimitResponse(response) {
|
|
38261
|
-
if (response.status !== 429) {
|
|
38262
|
-
return null;
|
|
38263
|
-
}
|
|
38264
|
-
const rateLimitInfo = {
|
|
38265
|
-
limit: parseInt(response.headers.get("RateLimit-Limit") || "0") || void 0,
|
|
38266
|
-
remaining: parseInt(response.headers.get("RateLimit-Remaining") || "0") || void 0,
|
|
38267
|
-
resetAt: parseInt(response.headers.get("RateLimit-Reset") || "0") || void 0,
|
|
38268
|
-
retryAfter: parseInt(response.headers.get("Retry-After") || "0") || void 0
|
|
38269
|
-
};
|
|
38270
|
-
try {
|
|
38271
|
-
const data = await response.json();
|
|
38272
|
-
if (data.error === "rate_limited" || data.error === "rate_limit_exceeded") {
|
|
38273
|
-
return {
|
|
38274
|
-
...data,
|
|
38275
|
-
// Merge header info if not in body
|
|
38276
|
-
limit: data.limit || rateLimitInfo.limit,
|
|
38277
|
-
remaining: data.remaining || rateLimitInfo.remaining,
|
|
38278
|
-
resetAt: data.resetAt || rateLimitInfo.resetAt,
|
|
38279
|
-
retryAfter: data.retryAfter || rateLimitInfo.retryAfter
|
|
38280
|
-
};
|
|
38281
|
-
}
|
|
38282
|
-
return {
|
|
38283
|
-
error: "rate_limited",
|
|
38284
|
-
message: data.message || "Rate limit exceeded. Please wait and try again.",
|
|
38285
|
-
hint: data.hint || "Consider upgrading your plan for higher limits.",
|
|
38286
|
-
...rateLimitInfo
|
|
38287
|
-
};
|
|
38288
|
-
} catch {
|
|
38289
|
-
return {
|
|
38290
|
-
error: "rate_limited",
|
|
38291
|
-
message: "Rate limit exceeded. Please wait and try again.",
|
|
38292
|
-
hint: "Consider upgrading your plan for higher limits.",
|
|
38293
|
-
...rateLimitInfo
|
|
38294
|
-
};
|
|
38295
|
-
}
|
|
38296
|
-
}
|
|
38297
|
-
var init_rate_limit_handler = __esm({
|
|
38298
|
-
"src/services/api-client/rate-limit-handler.ts"() {
|
|
38299
|
-
}
|
|
38300
|
-
});
|
|
38301
38219
|
function extractCodeInfo(codeBlock) {
|
|
38302
38220
|
const match2 = codeBlock.match(/```([^\n]*)\n?([\s\S]*?)```/);
|
|
38303
38221
|
if (!match2) {
|
|
@@ -38542,8 +38460,408 @@ var init_code_utils = __esm({
|
|
|
38542
38460
|
}
|
|
38543
38461
|
});
|
|
38544
38462
|
|
|
38545
|
-
// src/services/
|
|
38463
|
+
// src/services/creative/NovelArgumentInference.ts
|
|
38546
38464
|
function extractFirstJson4(text) {
|
|
38465
|
+
if (!text) return null;
|
|
38466
|
+
const start = text.indexOf("{");
|
|
38467
|
+
const end = text.lastIndexOf("}");
|
|
38468
|
+
if (start !== -1 && end !== -1 && end > start) {
|
|
38469
|
+
const cand = text.slice(start, end + 1);
|
|
38470
|
+
try {
|
|
38471
|
+
JSON.parse(cand);
|
|
38472
|
+
return cand;
|
|
38473
|
+
} catch {
|
|
38474
|
+
}
|
|
38475
|
+
}
|
|
38476
|
+
return null;
|
|
38477
|
+
}
|
|
38478
|
+
async function inferNovelArgs(rawText) {
|
|
38479
|
+
const system = [
|
|
38480
|
+
"You extract structured options for a novel generation command.",
|
|
38481
|
+
'Return JSON ONLY with keys among: { "title"?: string, "lang"?: string, "format"?: "md"|"markdown"|"txt"|"plaintext", "genre"?: string, "planOnly"?: boolean, "chapters"?: number }.',
|
|
38482
|
+
'Infer reasonable values from natural language. Keep chapters between 3 and 50 if specified. If format suggests plain text, choose "plaintext".',
|
|
38483
|
+
"If the user requests outline only, set planOnly=true.",
|
|
38484
|
+
"Do not add commentary."
|
|
38485
|
+
].join("\n");
|
|
38486
|
+
const resp = await callAPI("/v1/ai-proxy", {
|
|
38487
|
+
method: "POST",
|
|
38488
|
+
body: {
|
|
38489
|
+
prompt: `${system}
|
|
38490
|
+
|
|
38491
|
+
---
|
|
38492
|
+
|
|
38493
|
+
${rawText}`,
|
|
38494
|
+
taskType: "creative"
|
|
38495
|
+
}
|
|
38496
|
+
});
|
|
38497
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
38498
|
+
const jsonText = extractFirstJson4(raw) || raw;
|
|
38499
|
+
let parsed = {};
|
|
38500
|
+
try {
|
|
38501
|
+
parsed = JSON.parse(jsonText);
|
|
38502
|
+
} catch {
|
|
38503
|
+
return {};
|
|
38504
|
+
}
|
|
38505
|
+
const out = {};
|
|
38506
|
+
if (typeof parsed.title === "string" && parsed.title.trim()) out.title = parsed.title.trim();
|
|
38507
|
+
if (typeof parsed.lang === "string" && parsed.lang.trim()) out.lang = parsed.lang.trim().toLowerCase();
|
|
38508
|
+
if (typeof parsed.format === "string") {
|
|
38509
|
+
const f3 = parsed.format.toLowerCase();
|
|
38510
|
+
if (f3 === "md" || f3 === "markdown") out.format = "md";
|
|
38511
|
+
else if (f3 === "txt" || f3 === "plaintext" || f3 === "text") out.format = "txt";
|
|
38512
|
+
}
|
|
38513
|
+
if (typeof parsed.genre === "string" && parsed.genre.trim()) out.genre = parsed.genre.trim();
|
|
38514
|
+
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
38515
|
+
if (typeof parsed.chapters === "number" && Number.isFinite(parsed.chapters)) {
|
|
38516
|
+
const n = Math.max(1, Math.min(100, Math.floor(parsed.chapters)));
|
|
38517
|
+
out.chapters = n;
|
|
38518
|
+
}
|
|
38519
|
+
return out;
|
|
38520
|
+
}
|
|
38521
|
+
var init_NovelArgumentInference = __esm({
|
|
38522
|
+
"src/services/creative/NovelArgumentInference.ts"() {
|
|
38523
|
+
init_api_caller();
|
|
38524
|
+
}
|
|
38525
|
+
});
|
|
38526
|
+
|
|
38527
|
+
// src/slash-commands/categories/creative/novel.command.ts
|
|
38528
|
+
var novel_command_exports = {};
|
|
38529
|
+
__export(novel_command_exports, {
|
|
38530
|
+
NovelCommand: () => NovelCommand,
|
|
38531
|
+
default: () => novel_command_default
|
|
38532
|
+
});
|
|
38533
|
+
function normalizeFormat(fmt) {
|
|
38534
|
+
const f3 = (fmt).toLowerCase();
|
|
38535
|
+
if (f3 === "txt" || f3 === "plaintext" || f3 === "text") return "txt";
|
|
38536
|
+
return "md";
|
|
38537
|
+
}
|
|
38538
|
+
function normalizeLang(lang) {
|
|
38539
|
+
const l = (lang).toLowerCase();
|
|
38540
|
+
if (!l) return "en";
|
|
38541
|
+
if (["en", "ja", "jp", "zh", "ko", "fr", "de", "es", "it", "pt"].includes(l)) {
|
|
38542
|
+
return l === "jp" ? "ja" : l;
|
|
38543
|
+
}
|
|
38544
|
+
return "en";
|
|
38545
|
+
}
|
|
38546
|
+
async function writeText(filePath, content) {
|
|
38547
|
+
const dir = path10__namespace.dirname(filePath);
|
|
38548
|
+
await fsp__namespace.mkdir(dir, { recursive: true });
|
|
38549
|
+
await fsp__namespace.writeFile(filePath, content, "utf8");
|
|
38550
|
+
}
|
|
38551
|
+
function extractFirstJsonArray(text) {
|
|
38552
|
+
if (!text) return null;
|
|
38553
|
+
const t2 = text.trim();
|
|
38554
|
+
const fenced = t2.match(/```json\s*([\s\S]*?)```/i) || t2.match(/```\s*([\s\S]*?)```/);
|
|
38555
|
+
if (fenced && fenced[1]) {
|
|
38556
|
+
const body = fenced[1].trim();
|
|
38557
|
+
try {
|
|
38558
|
+
const arr = JSON.parse(body);
|
|
38559
|
+
return Array.isArray(arr) ? arr : null;
|
|
38560
|
+
} catch {
|
|
38561
|
+
}
|
|
38562
|
+
}
|
|
38563
|
+
const defenced = t2.replace(/```json|```/gi, "").trim();
|
|
38564
|
+
try {
|
|
38565
|
+
const arr = JSON.parse(defenced);
|
|
38566
|
+
return Array.isArray(arr) ? arr : null;
|
|
38567
|
+
} catch {
|
|
38568
|
+
}
|
|
38569
|
+
const s2 = t2.indexOf("[");
|
|
38570
|
+
const e2 = t2.lastIndexOf("]");
|
|
38571
|
+
if (s2 !== -1 && e2 !== -1 && e2 > s2) {
|
|
38572
|
+
const slice = t2.slice(s2, e2 + 1);
|
|
38573
|
+
try {
|
|
38574
|
+
const arr = JSON.parse(slice);
|
|
38575
|
+
return Array.isArray(arr) ? arr : null;
|
|
38576
|
+
} catch {
|
|
38577
|
+
}
|
|
38578
|
+
}
|
|
38579
|
+
return null;
|
|
38580
|
+
}
|
|
38581
|
+
async function generatePlan(prompt, lang, title, genre) {
|
|
38582
|
+
const system = [
|
|
38583
|
+
"You generate a detailed novel outline (plot).",
|
|
38584
|
+
"Return Markdown with clear sections: Title, Logline, Themes, Characters, Chapter Outline.",
|
|
38585
|
+
"The language should match the requested language."
|
|
38586
|
+
].join("\n");
|
|
38587
|
+
const user = [
|
|
38588
|
+
`Language: ${lang}`,
|
|
38589
|
+
`Title: ${title}`,
|
|
38590
|
+
genre ? `Genre: ${genre}` : "",
|
|
38591
|
+
"Prompt:",
|
|
38592
|
+
prompt
|
|
38593
|
+
].filter(Boolean).join("\n");
|
|
38594
|
+
const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt: `${system}
|
|
38595
|
+
|
|
38596
|
+
---
|
|
38597
|
+
|
|
38598
|
+
${user}`, taskType: "creative" } });
|
|
38599
|
+
const out = (resp?.data?.content || resp?.output || "").trim();
|
|
38600
|
+
return out;
|
|
38601
|
+
}
|
|
38602
|
+
async function generateChapters(planMarkdown, lang, chapters) {
|
|
38603
|
+
const system = [
|
|
38604
|
+
"You expand a novel outline into chapter texts.",
|
|
38605
|
+
"Return only JSON array: [{ index: number, title: string, content: string }].",
|
|
38606
|
+
"Write in the requested language and maintain consistency with the outline."
|
|
38607
|
+
].join("\n");
|
|
38608
|
+
const prompt = `${system}
|
|
38609
|
+
|
|
38610
|
+
LANG=${lang}
|
|
38611
|
+
CHAPTERS=${chapters}
|
|
38612
|
+
|
|
38613
|
+
OUTLINE:
|
|
38614
|
+
${planMarkdown}`;
|
|
38615
|
+
const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt, taskType: "creative" } });
|
|
38616
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
38617
|
+
const arr = extractFirstJsonArray(raw);
|
|
38618
|
+
if (Array.isArray(arr)) {
|
|
38619
|
+
return arr.map((it, i2) => ({
|
|
38620
|
+
index: typeof it.index === "number" ? it.index : i2,
|
|
38621
|
+
title: typeof it.title === "string" ? it.title : `Chapter ${i2 + 1}`,
|
|
38622
|
+
content: typeof it.content === "string" ? it.content : ""
|
|
38623
|
+
}));
|
|
38624
|
+
}
|
|
38625
|
+
return [{ index: 0, title: "Chapter 1", content: raw }];
|
|
38626
|
+
}
|
|
38627
|
+
async function generateTitle(idea, lang, genre) {
|
|
38628
|
+
const system = [
|
|
38629
|
+
"You craft a concise, compelling novel title. Return only the title string.",
|
|
38630
|
+
"Consider the idea and genre. Use the requested language."
|
|
38631
|
+
].join("\n");
|
|
38632
|
+
const user = [
|
|
38633
|
+
`Language: ${lang}`,
|
|
38634
|
+
genre ? `Genre: ${genre}` : "",
|
|
38635
|
+
"Idea:",
|
|
38636
|
+
idea
|
|
38637
|
+
].filter(Boolean).join("\n");
|
|
38638
|
+
const resp = await callAPI("/v1/ai-proxy", { method: "POST", body: { prompt: `${system}
|
|
38639
|
+
|
|
38640
|
+
---
|
|
38641
|
+
|
|
38642
|
+
${user}`, taskType: "creative" } });
|
|
38643
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
38644
|
+
try {
|
|
38645
|
+
const obj = JSON.parse(raw);
|
|
38646
|
+
if (typeof obj?.title === "string") return obj.title.trim();
|
|
38647
|
+
} catch {
|
|
38648
|
+
}
|
|
38649
|
+
const matched = raw.match(/```[a-z]*\s*([\s\S]*?)```/i);
|
|
38650
|
+
const text = matched ? matched[1].trim() : raw;
|
|
38651
|
+
return text.split("\n")[0].trim();
|
|
38652
|
+
}
|
|
38653
|
+
var NovelCommand, novel_command_default;
|
|
38654
|
+
var init_novel_command = __esm({
|
|
38655
|
+
"src/slash-commands/categories/creative/novel.command.ts"() {
|
|
38656
|
+
init_base_command();
|
|
38657
|
+
init_code_utils();
|
|
38658
|
+
init_api_caller();
|
|
38659
|
+
init_NovelArgumentInference();
|
|
38660
|
+
init_animations();
|
|
38661
|
+
NovelCommand = class extends BaseCommand {
|
|
38662
|
+
name = "novel";
|
|
38663
|
+
category = "creative";
|
|
38664
|
+
description = "Generate a novel: outline plan and full chapters with language/format options";
|
|
38665
|
+
aliases = ["story"];
|
|
38666
|
+
usage = "<idea or title> [--lang <code>] [--format md|txt] [--genre <name>] [--plan-only] [--chapters <n>]";
|
|
38667
|
+
examples = [
|
|
38668
|
+
{ 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" },
|
|
38669
|
+
{ 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" },
|
|
38670
|
+
{ input: "/novel detective mystery --plan-only", description: "\u30D7\u30ED\u30C3\u30C8\u306E\u307F\u3092\u4F5C\u6210\u3057\u3066\u4FDD\u5B58" }
|
|
38671
|
+
];
|
|
38672
|
+
async execute(args2, context2) {
|
|
38673
|
+
const raw = Array.isArray(args2.raw) ? args2.raw : [];
|
|
38674
|
+
const ideaText = raw.join(" ").trim();
|
|
38675
|
+
if (!ideaText) {
|
|
38676
|
+
return this.error("Usage: /novel <idea or title> [--lang <code>] [--format md|txt] [--genre <name>] [--plan-only] [--chapters <n>]");
|
|
38677
|
+
}
|
|
38678
|
+
const explicit = {
|
|
38679
|
+
lang: typeof args2.options["lang"] === "string" ? String(args2.options["lang"]) : void 0,
|
|
38680
|
+
format: typeof args2.options["format"] === "string" ? String(args2.options["format"]) : void 0,
|
|
38681
|
+
genre: typeof args2.options["genre"] === "string" ? String(args2.options["genre"]) : void 0,
|
|
38682
|
+
chapters: typeof args2.options["chapters"] === "string" ? Number(args2.options["chapters"]) : void 0,
|
|
38683
|
+
planOnly: args2.flags["plan-only"] === true || args2.flags["sow"] === true
|
|
38684
|
+
};
|
|
38685
|
+
let inferred = {};
|
|
38686
|
+
try {
|
|
38687
|
+
const spin = new ProcessAnimation();
|
|
38688
|
+
spin.start();
|
|
38689
|
+
try {
|
|
38690
|
+
inferred = await inferNovelArgs(ideaText);
|
|
38691
|
+
} finally {
|
|
38692
|
+
try {
|
|
38693
|
+
spin.stop();
|
|
38694
|
+
} catch {
|
|
38695
|
+
}
|
|
38696
|
+
}
|
|
38697
|
+
} catch {
|
|
38698
|
+
}
|
|
38699
|
+
const lang = normalizeLang(explicit.lang || inferred.lang || "en");
|
|
38700
|
+
const format = normalizeFormat(explicit.format || inferred.format || "md");
|
|
38701
|
+
const planOnly = explicit.planOnly || inferred.planOnly === true;
|
|
38702
|
+
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;
|
|
38703
|
+
const genre = explicit.genre || inferred.genre;
|
|
38704
|
+
let generatedTitle = inferred.title;
|
|
38705
|
+
if (!generatedTitle) {
|
|
38706
|
+
const spin = new ProcessAnimation();
|
|
38707
|
+
spin.start();
|
|
38708
|
+
try {
|
|
38709
|
+
generatedTitle = await generateTitle(ideaText, lang, genre);
|
|
38710
|
+
} finally {
|
|
38711
|
+
try {
|
|
38712
|
+
spin.stop();
|
|
38713
|
+
} catch {
|
|
38714
|
+
}
|
|
38715
|
+
}
|
|
38716
|
+
}
|
|
38717
|
+
const titleRaw = (generatedTitle || "novel").slice(0, 120);
|
|
38718
|
+
const title = sanitizeFilenameStrict(titleRaw);
|
|
38719
|
+
const root = process.cwd();
|
|
38720
|
+
const novelDir = await ensureUniquePath(safeResolve(root, path10__namespace.join("novel", title)));
|
|
38721
|
+
await fsp__namespace.mkdir(novelDir, { recursive: true });
|
|
38722
|
+
let plan = "";
|
|
38723
|
+
{
|
|
38724
|
+
const spin = new ProcessAnimation();
|
|
38725
|
+
spin.start();
|
|
38726
|
+
try {
|
|
38727
|
+
plan = await generatePlan(ideaText, lang, title, genre);
|
|
38728
|
+
} finally {
|
|
38729
|
+
try {
|
|
38730
|
+
spin.stop();
|
|
38731
|
+
} catch {
|
|
38732
|
+
}
|
|
38733
|
+
}
|
|
38734
|
+
}
|
|
38735
|
+
const planExt = format === "txt" ? ".txt" : ".md";
|
|
38736
|
+
const planPath = await ensureUniquePath(path10__namespace.join(novelDir, `00_plan${planExt}`));
|
|
38737
|
+
await writeText(planPath, plan);
|
|
38738
|
+
if (planOnly) {
|
|
38739
|
+
const msg2 = [`Saved plan to ${planPath}`, "", "Files:", `- ${planPath}`].join("\n");
|
|
38740
|
+
return this.success(msg2, { dir: novelDir, plan: planPath });
|
|
38741
|
+
}
|
|
38742
|
+
const chapterObjs = await (async () => {
|
|
38743
|
+
const spin = new ProcessAnimation();
|
|
38744
|
+
spin.start();
|
|
38745
|
+
try {
|
|
38746
|
+
return await generateChapters(plan, lang, chapters);
|
|
38747
|
+
} finally {
|
|
38748
|
+
try {
|
|
38749
|
+
spin.stop();
|
|
38750
|
+
} catch {
|
|
38751
|
+
}
|
|
38752
|
+
}
|
|
38753
|
+
})();
|
|
38754
|
+
let index = 1;
|
|
38755
|
+
const saved = [planPath];
|
|
38756
|
+
for (const ch of chapterObjs) {
|
|
38757
|
+
const num = String(index).padStart(2, "0");
|
|
38758
|
+
const chTitle = sanitizeFilenameStrict(ch.title || `chapter-${index}`);
|
|
38759
|
+
const file = path10__namespace.join(novelDir, `${num}_${chTitle}${planExt}`);
|
|
38760
|
+
const finalPath = await ensureUniquePath(file);
|
|
38761
|
+
const content = format === "md" ? `# ${ch.title}
|
|
38762
|
+
|
|
38763
|
+
${ch.content}` : ch.content;
|
|
38764
|
+
await writeText(finalPath, content);
|
|
38765
|
+
saved.push(finalPath);
|
|
38766
|
+
index++;
|
|
38767
|
+
}
|
|
38768
|
+
const msg = [
|
|
38769
|
+
`Saved novel to ${novelDir}`,
|
|
38770
|
+
"",
|
|
38771
|
+
"Files:",
|
|
38772
|
+
...saved.map((p) => `- ${p}`)
|
|
38773
|
+
].join("\n");
|
|
38774
|
+
return this.success(msg, { dir: novelDir, files: saved });
|
|
38775
|
+
}
|
|
38776
|
+
};
|
|
38777
|
+
novel_command_default = NovelCommand;
|
|
38778
|
+
}
|
|
38779
|
+
});
|
|
38780
|
+
function handleRateLimitError(error2) {
|
|
38781
|
+
console.log();
|
|
38782
|
+
console.log(chalk40__default.default.yellow("\u23F1\uFE0F Rate Limit Exceeded"));
|
|
38783
|
+
console.log(chalk40__default.default.gray("\u2501".repeat(50)));
|
|
38784
|
+
const route = error2.route || error2.details?.endpoint || "API";
|
|
38785
|
+
const plan = error2.plan || error2.details?.plan || "Unknown";
|
|
38786
|
+
const limit = error2.limit || (error2.details?.limit ? parseInt(error2.details.limit) : null);
|
|
38787
|
+
const retryAfter = error2.retryAfter || error2.details?.retryAfterSeconds;
|
|
38788
|
+
const resetAt = error2.resetAt || (error2.details?.resetAt ? Date.parse(error2.details.resetAt) : null);
|
|
38789
|
+
const waitTime = Number.isFinite(retryAfter) ? `${retryAfter} second${retryAfter > 1 ? "s" : ""}` : "a few seconds";
|
|
38790
|
+
let resetTime = "";
|
|
38791
|
+
if (resetAt && Number.isFinite(resetAt)) {
|
|
38792
|
+
const resetDate = new Date(resetAt);
|
|
38793
|
+
const now2 = /* @__PURE__ */ new Date();
|
|
38794
|
+
const diffMs = resetDate.getTime() - now2.getTime();
|
|
38795
|
+
if (diffMs > 0 && diffMs < 6e4) {
|
|
38796
|
+
resetTime = `in ${Math.ceil(diffMs / 1e3)} seconds`;
|
|
38797
|
+
} else if (diffMs > 0) {
|
|
38798
|
+
resetTime = `at ${resetDate.toLocaleTimeString()}`;
|
|
38799
|
+
}
|
|
38800
|
+
}
|
|
38801
|
+
console.log(chalk40__default.default.white(`Plan: ${chalk40__default.default.bold(plan)}`));
|
|
38802
|
+
console.log(chalk40__default.default.white(`Endpoint: ${chalk40__default.default.bold(route)}`));
|
|
38803
|
+
if (limit !== null) {
|
|
38804
|
+
console.log(chalk40__default.default.white(`Limit: ${chalk40__default.default.bold(limit)} requests`));
|
|
38805
|
+
}
|
|
38806
|
+
if (error2.remaining !== void 0) {
|
|
38807
|
+
console.log(chalk40__default.default.white(`Remaining: ${chalk40__default.default.bold(error2.remaining)} requests`));
|
|
38808
|
+
}
|
|
38809
|
+
console.log();
|
|
38810
|
+
console.log(chalk40__default.default.cyan(`Please wait ${chalk40__default.default.bold(waitTime)} before trying again`));
|
|
38811
|
+
if (resetTime) {
|
|
38812
|
+
console.log(chalk40__default.default.gray(`Rate limit resets ${resetTime}`));
|
|
38813
|
+
}
|
|
38814
|
+
if (error2.hint) {
|
|
38815
|
+
console.log();
|
|
38816
|
+
console.log(chalk40__default.default.magenta("\u{1F4A1} " + error2.hint));
|
|
38817
|
+
}
|
|
38818
|
+
console.log(chalk40__default.default.gray("\u2501".repeat(50)));
|
|
38819
|
+
console.log();
|
|
38820
|
+
}
|
|
38821
|
+
async function parseRateLimitResponse(response) {
|
|
38822
|
+
if (response.status !== 429) {
|
|
38823
|
+
return null;
|
|
38824
|
+
}
|
|
38825
|
+
const rateLimitInfo = {
|
|
38826
|
+
limit: parseInt(response.headers.get("RateLimit-Limit") || "0") || void 0,
|
|
38827
|
+
remaining: parseInt(response.headers.get("RateLimit-Remaining") || "0") || void 0,
|
|
38828
|
+
resetAt: parseInt(response.headers.get("RateLimit-Reset") || "0") || void 0,
|
|
38829
|
+
retryAfter: parseInt(response.headers.get("Retry-After") || "0") || void 0
|
|
38830
|
+
};
|
|
38831
|
+
try {
|
|
38832
|
+
const data = await response.json();
|
|
38833
|
+
if (data.error === "rate_limited" || data.error === "rate_limit_exceeded") {
|
|
38834
|
+
return {
|
|
38835
|
+
...data,
|
|
38836
|
+
// Merge header info if not in body
|
|
38837
|
+
limit: data.limit || rateLimitInfo.limit,
|
|
38838
|
+
remaining: data.remaining || rateLimitInfo.remaining,
|
|
38839
|
+
resetAt: data.resetAt || rateLimitInfo.resetAt,
|
|
38840
|
+
retryAfter: data.retryAfter || rateLimitInfo.retryAfter
|
|
38841
|
+
};
|
|
38842
|
+
}
|
|
38843
|
+
return {
|
|
38844
|
+
error: "rate_limited",
|
|
38845
|
+
message: data.message || "Rate limit exceeded. Please wait and try again.",
|
|
38846
|
+
hint: data.hint || "Consider upgrading your plan for higher limits.",
|
|
38847
|
+
...rateLimitInfo
|
|
38848
|
+
};
|
|
38849
|
+
} catch {
|
|
38850
|
+
return {
|
|
38851
|
+
error: "rate_limited",
|
|
38852
|
+
message: "Rate limit exceeded. Please wait and try again.",
|
|
38853
|
+
hint: "Consider upgrading your plan for higher limits.",
|
|
38854
|
+
...rateLimitInfo
|
|
38855
|
+
};
|
|
38856
|
+
}
|
|
38857
|
+
}
|
|
38858
|
+
var init_rate_limit_handler = __esm({
|
|
38859
|
+
"src/services/api-client/rate-limit-handler.ts"() {
|
|
38860
|
+
}
|
|
38861
|
+
});
|
|
38862
|
+
|
|
38863
|
+
// src/services/code-orchestrator/ArgumentInference.ts
|
|
38864
|
+
function extractFirstJson5(text) {
|
|
38547
38865
|
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
38548
38866
|
if (fence) return fence[1];
|
|
38549
38867
|
const start = text.indexOf("{");
|
|
@@ -38577,7 +38895,7 @@ ${rawText}`,
|
|
|
38577
38895
|
}
|
|
38578
38896
|
});
|
|
38579
38897
|
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
38580
|
-
const jsonText =
|
|
38898
|
+
const jsonText = extractFirstJson5(raw) || raw;
|
|
38581
38899
|
let parsed = {};
|
|
38582
38900
|
try {
|
|
38583
38901
|
parsed = JSON.parse(jsonText);
|
|
@@ -38689,10 +39007,10 @@ function suggestName(fp, p) {
|
|
|
38689
39007
|
const base = (fp.description || "file").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
38690
39008
|
return base || "file";
|
|
38691
39009
|
}
|
|
38692
|
-
function guessKindByPath(
|
|
38693
|
-
if (/__tests__|\.spec\.(t|j)sx?$|^tests\//.test(
|
|
38694
|
-
if (/^docs\//.test(
|
|
38695
|
-
if (/\.(json|cjs|js|ts)$/.test(
|
|
39010
|
+
function guessKindByPath(path65) {
|
|
39011
|
+
if (/__tests__|\.spec\.(t|j)sx?$|^tests\//.test(path65)) return "test";
|
|
39012
|
+
if (/^docs\//.test(path65) || /\.md$/.test(path65)) return "doc";
|
|
39013
|
+
if (/\.(json|cjs|js|ts)$/.test(path65) && !/src\//.test(path65)) return "config";
|
|
38696
39014
|
return "source";
|
|
38697
39015
|
}
|
|
38698
39016
|
var init_PathInferencer = __esm({
|
|
@@ -38956,9 +39274,9 @@ function formatPlanAsDiff(files, opts) {
|
|
|
38956
39274
|
function readCurrentFileSafe(root, rel, abs) {
|
|
38957
39275
|
if (!root && !abs) return "";
|
|
38958
39276
|
try {
|
|
38959
|
-
const
|
|
39277
|
+
const fs52 = __require("fs");
|
|
38960
39278
|
const p = abs ? abs : __require("path").join(root, rel);
|
|
38961
|
-
return
|
|
39279
|
+
return fs52.existsSync(p) ? fs52.readFileSync(p, "utf8") : "";
|
|
38962
39280
|
} catch {
|
|
38963
39281
|
return "";
|
|
38964
39282
|
}
|
|
@@ -39293,7 +39611,8 @@ async function listRepoFiles(root) {
|
|
|
39293
39611
|
}
|
|
39294
39612
|
for (const e2 of entries) {
|
|
39295
39613
|
const name2 = e2.name;
|
|
39296
|
-
if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === ".maria"
|
|
39614
|
+
if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === ".maria" || // macOS system/hidden dirs that shouldn't be scanned
|
|
39615
|
+
name2 === ".DS_Store" || name2 === ".Spotlight-V100" || name2 === ".Trashes" || name2 === ".fseventsd" || name2 === ".TemporaryItems") continue;
|
|
39297
39616
|
const full = path10__namespace.default.join(dir, name2);
|
|
39298
39617
|
const rel = path10__namespace.default.relative(root, full).replace(/\\/g, "/");
|
|
39299
39618
|
if (e2.isDirectory()) {
|
|
@@ -39546,6 +39865,60 @@ var Orchestrator_exports = {};
|
|
|
39546
39865
|
__export(Orchestrator_exports, {
|
|
39547
39866
|
orchestrate: () => orchestrate
|
|
39548
39867
|
});
|
|
39868
|
+
async function getRepoFiles(root) {
|
|
39869
|
+
if (_repoFileIndexCache && _repoFileIndexCache.root === root) return _repoFileIndexCache.files;
|
|
39870
|
+
const fs52 = await import('fs/promises');
|
|
39871
|
+
const pathMod = await import('path');
|
|
39872
|
+
const ignoreDir = /* @__PURE__ */ new Set([
|
|
39873
|
+
".git",
|
|
39874
|
+
"node_modules",
|
|
39875
|
+
"dist",
|
|
39876
|
+
"build",
|
|
39877
|
+
".maria",
|
|
39878
|
+
".next",
|
|
39879
|
+
"coverage",
|
|
39880
|
+
".DS_Store",
|
|
39881
|
+
".Spotlight-V100",
|
|
39882
|
+
".Trashes",
|
|
39883
|
+
".fseventsd",
|
|
39884
|
+
".TemporaryItems"
|
|
39885
|
+
]);
|
|
39886
|
+
const out = [];
|
|
39887
|
+
async function walk2(dir) {
|
|
39888
|
+
let entries = [];
|
|
39889
|
+
try {
|
|
39890
|
+
entries = await fs52.readdir(dir, { withFileTypes: true });
|
|
39891
|
+
} catch {
|
|
39892
|
+
return;
|
|
39893
|
+
}
|
|
39894
|
+
for (const e2 of entries) {
|
|
39895
|
+
const name2 = e2.name;
|
|
39896
|
+
if (ignoreDir.has(name2)) continue;
|
|
39897
|
+
const full = pathMod.join(dir, name2);
|
|
39898
|
+
if (e2.isDirectory()) {
|
|
39899
|
+
await walk2(full);
|
|
39900
|
+
continue;
|
|
39901
|
+
}
|
|
39902
|
+
out.push(pathMod.relative(root, full).replace(/\\/g, "/"));
|
|
39903
|
+
}
|
|
39904
|
+
}
|
|
39905
|
+
await walk2(root);
|
|
39906
|
+
_repoFileIndexCache = { root, files: out };
|
|
39907
|
+
return out;
|
|
39908
|
+
}
|
|
39909
|
+
function languageFromExt(ext2) {
|
|
39910
|
+
const e2 = ext2.toLowerCase().replace(/^\./, "");
|
|
39911
|
+
if (e2 === "ts") return "typescript";
|
|
39912
|
+
if (e2 === "tsx") return "tsx";
|
|
39913
|
+
if (e2 === "js" || e2 === "mjs" || e2 === "cjs") return "javascript";
|
|
39914
|
+
if (e2 === "jsx") return "jsx";
|
|
39915
|
+
if (e2 === "json") return "json";
|
|
39916
|
+
if (e2 === "html") return "html";
|
|
39917
|
+
if (e2 === "css" || e2 === "scss") return "css";
|
|
39918
|
+
if (e2 === "md") return "markdown";
|
|
39919
|
+
if (e2 === "yaml" || e2 === "yml") return "yaml";
|
|
39920
|
+
return void 0;
|
|
39921
|
+
}
|
|
39549
39922
|
async function ensureCodeFallbackManager() {
|
|
39550
39923
|
const policy = await loadFallbackPolicy().catch(() => getDefaultFallbackPolicy());
|
|
39551
39924
|
const signature = JSON.stringify(policy);
|
|
@@ -39584,11 +39957,19 @@ async function orchestrate(request, opts) {
|
|
|
39584
39957
|
explicitAbsMap[rel] = pathMod.join(opts.root, rel);
|
|
39585
39958
|
}
|
|
39586
39959
|
}
|
|
39587
|
-
const isEditIntent =
|
|
39960
|
+
const isEditIntent = await detectEditIntentEnhanced(opts.root, request, {
|
|
39588
39961
|
hasAttachments: !!(opts.attachedFiles && opts.attachedFiles.length > 0),
|
|
39589
|
-
|
|
39590
|
-
|
|
39591
|
-
|
|
39962
|
+
explicitFiles});
|
|
39963
|
+
let editTargets = explicitFiles;
|
|
39964
|
+
if (isEditIntent && editTargets.length === 0) {
|
|
39965
|
+
try {
|
|
39966
|
+
const repoFiles = await getRepoFiles(opts.root);
|
|
39967
|
+
const likely = repoFiles.filter((p) => /\.(ts|tsx|js|jsx|html|css|scss|json|md)$/i.test(p));
|
|
39968
|
+
editTargets = likely.slice(0, 20);
|
|
39969
|
+
} catch {
|
|
39970
|
+
}
|
|
39971
|
+
}
|
|
39972
|
+
const editContext = isEditIntent && editTargets.length > 0 ? await buildEditContext(opts.root, editTargets, 200, 512 * 1024) : "";
|
|
39592
39973
|
if (opts.attachedFiles && opts.attachedFiles.length > 0) {
|
|
39593
39974
|
const mapRes = await mapAttachmentsToTargets(opts.attachedFiles, {
|
|
39594
39975
|
root: opts.root,
|
|
@@ -39647,14 +40028,14 @@ ${editContext}`;
|
|
|
39647
40028
|
const pathAttachments = [];
|
|
39648
40029
|
if (explicitFiles.length > 0) {
|
|
39649
40030
|
try {
|
|
39650
|
-
const
|
|
40031
|
+
const fs52 = await import('fs/promises');
|
|
39651
40032
|
const pathMod = await import('path');
|
|
39652
40033
|
for (const rel of explicitFiles) {
|
|
39653
40034
|
try {
|
|
39654
40035
|
const full = explicitAbsMap[rel] || pathMod.join(opts.root, rel);
|
|
39655
|
-
const stat13 = await
|
|
40036
|
+
const stat13 = await fs52.stat(full).catch(() => null);
|
|
39656
40037
|
if (!stat13 || !stat13.isFile()) continue;
|
|
39657
|
-
const buf = await
|
|
40038
|
+
const buf = await fs52.readFile(full);
|
|
39658
40039
|
const ext2 = (pathMod.extname(full) || "").toLowerCase();
|
|
39659
40040
|
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";
|
|
39660
40041
|
pathAttachments.push({
|
|
@@ -39672,7 +40053,7 @@ ${editContext}`;
|
|
|
39672
40053
|
const hydratedCtx = [];
|
|
39673
40054
|
if (ctxAttachments.length > 0) {
|
|
39674
40055
|
try {
|
|
39675
|
-
const
|
|
40056
|
+
const fs52 = await import('fs/promises');
|
|
39676
40057
|
for (const a of ctxAttachments) {
|
|
39677
40058
|
if (a.data_base64) {
|
|
39678
40059
|
hydratedCtx.push(a);
|
|
@@ -39683,12 +40064,12 @@ ${editContext}`;
|
|
|
39683
40064
|
continue;
|
|
39684
40065
|
}
|
|
39685
40066
|
try {
|
|
39686
|
-
const stat13 = await
|
|
40067
|
+
const stat13 = await fs52.stat(p).catch(() => null);
|
|
39687
40068
|
if (!stat13 || !stat13.isFile()) {
|
|
39688
40069
|
hydratedCtx.push(a);
|
|
39689
40070
|
continue;
|
|
39690
40071
|
}
|
|
39691
|
-
const buf = await
|
|
40072
|
+
const buf = await fs52.readFile(p);
|
|
39692
40073
|
hydratedCtx.push({ ...a, data_base64: buf.toString("base64") });
|
|
39693
40074
|
} catch {
|
|
39694
40075
|
hydratedCtx.push(a);
|
|
@@ -39738,40 +40119,44 @@ ${editContext}`;
|
|
|
39738
40119
|
codeOutput = outcome.data?.output || "";
|
|
39739
40120
|
}
|
|
39740
40121
|
const blocks = extractBlocks(codeOutput);
|
|
39741
|
-
if (explicitFiles.length > 0) {
|
|
40122
|
+
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
39742
40123
|
const mapped = /* @__PURE__ */ new Set();
|
|
40124
|
+
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
40125
|
+
const absMap = explicitFiles.length > 0 ? explicitAbsMap : /* @__PURE__ */ Object.create(null);
|
|
39743
40126
|
const htmlIdx = blocks.findIndex((b) => /html/i.test(b.language));
|
|
39744
|
-
const htmlFile =
|
|
40127
|
+
const htmlFile = targets.find((f3) => f3.toLowerCase().endsWith(".html"));
|
|
39745
40128
|
if (htmlIdx >= 0 && htmlFile) {
|
|
39746
|
-
initial.push({ path: htmlFile, absPath:
|
|
40129
|
+
initial.push({ path: htmlFile, absPath: absMap[htmlFile], noNormalize: true, kind: "source", action: "modify", description: "HTML page", language: "html", preview: blocks[htmlIdx].code });
|
|
39747
40130
|
mapped.add(htmlFile);
|
|
39748
40131
|
}
|
|
39749
40132
|
const jsIdx = blocks.findIndex((b) => /(ts|tsx|jsx|javascript|js)/i.test(b.language));
|
|
39750
|
-
const jsFile =
|
|
40133
|
+
const jsFile = targets.find((f3) => f3.toLowerCase().endsWith(".js"));
|
|
39751
40134
|
if (jsIdx >= 0 && jsFile && !mapped.has(jsFile)) {
|
|
39752
|
-
initial.push({ path: jsFile, absPath:
|
|
40135
|
+
initial.push({ path: jsFile, absPath: absMap[jsFile], noNormalize: true, kind: "source", action: "modify", description: "Script", language: "javascript", preview: blocks[jsIdx].code });
|
|
39753
40136
|
mapped.add(jsFile);
|
|
39754
40137
|
}
|
|
39755
40138
|
const cssIdx = blocks.findIndex((b) => /css/i.test(b.language));
|
|
39756
|
-
const cssFile =
|
|
40139
|
+
const cssFile = targets.find((f3) => f3.toLowerCase().endsWith(".css"));
|
|
39757
40140
|
if (cssIdx >= 0 && cssFile && !mapped.has(cssFile)) {
|
|
39758
|
-
initial.push({ path: cssFile, absPath:
|
|
40141
|
+
initial.push({ path: cssFile, absPath: absMap[cssFile], noNormalize: true, kind: "source", action: "modify", description: "Stylesheet", language: "css", preview: blocks[cssIdx].code });
|
|
39759
40142
|
mapped.add(cssFile);
|
|
39760
40143
|
}
|
|
39761
|
-
for (const f3 of
|
|
40144
|
+
for (const f3 of targets) {
|
|
39762
40145
|
if (mapped.has(f3)) continue;
|
|
39763
|
-
const
|
|
39764
|
-
|
|
39765
|
-
|
|
39766
|
-
|
|
40146
|
+
const ext2 = (() => {
|
|
40147
|
+
const m2 = f3.lastIndexOf(".");
|
|
40148
|
+
return m2 >= 0 ? f3.slice(m2) : "";
|
|
40149
|
+
})();
|
|
40150
|
+
const lang = languageFromExt(ext2);
|
|
40151
|
+
initial.push({ path: f3, absPath: absMap[f3], noNormalize: true, kind: "source", action: "modify", description: "Edit target", language: lang, preview: "" });
|
|
39767
40152
|
}
|
|
39768
40153
|
} else {
|
|
39769
40154
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
39770
40155
|
const b = blocks[i2];
|
|
39771
40156
|
const desired = typeof b.filename === "string" && b.filename.trim() ? b.filename.trim() : null;
|
|
39772
|
-
const
|
|
40157
|
+
const path65 = desired || suggestName2(request, b.language, i2);
|
|
39773
40158
|
initial.push({
|
|
39774
|
-
path:
|
|
40159
|
+
path: path65,
|
|
39775
40160
|
kind: "source",
|
|
39776
40161
|
action: "create",
|
|
39777
40162
|
description: describe2(b.language, ""),
|
|
@@ -39802,13 +40187,13 @@ ${editContext}`;
|
|
|
39802
40187
|
{ root: opts.root }
|
|
39803
40188
|
);
|
|
39804
40189
|
try {
|
|
39805
|
-
const [{ access: access18 },
|
|
40190
|
+
const [{ access: access18 }, path65] = await Promise.all([
|
|
39806
40191
|
import('fs/promises'),
|
|
39807
40192
|
import('path')
|
|
39808
40193
|
]);
|
|
39809
40194
|
for (const p of normalized) {
|
|
39810
40195
|
try {
|
|
39811
|
-
const absCandidate = p.absPath ? p.absPath :
|
|
40196
|
+
const absCandidate = p.absPath ? p.absPath : path65.join(opts.root, p.path);
|
|
39812
40197
|
await access18(absCandidate);
|
|
39813
40198
|
p.action = "modify";
|
|
39814
40199
|
if (isEditIntent) {
|
|
@@ -40046,12 +40431,12 @@ function languageExt(lang) {
|
|
|
40046
40431
|
}
|
|
40047
40432
|
async function journalResume(root, request, files) {
|
|
40048
40433
|
try {
|
|
40049
|
-
const
|
|
40434
|
+
const fs52 = await import('fs/promises');
|
|
40050
40435
|
const dir = path10__namespace.default.join(root, ".maria", "memory");
|
|
40051
|
-
await
|
|
40436
|
+
await fs52.mkdir(dir, { recursive: true });
|
|
40052
40437
|
const out = path10__namespace.default.join(dir, "resume-plan.json");
|
|
40053
40438
|
const payload = { request, createdAt: (/* @__PURE__ */ new Date()).toISOString(), files };
|
|
40054
|
-
await
|
|
40439
|
+
await fs52.writeFile(out, JSON.stringify(payload, null, 2), "utf8");
|
|
40055
40440
|
} catch {
|
|
40056
40441
|
}
|
|
40057
40442
|
}
|
|
@@ -40179,6 +40564,68 @@ function detectEditIntent(request, ctx2) {
|
|
|
40179
40564
|
const mentionsEdit = editKeywords.some((k) => r2.includes(k));
|
|
40180
40565
|
return ctx2.hasAttachments || ctx2.explicitFilesCount > 0 || mentionsEdit;
|
|
40181
40566
|
}
|
|
40567
|
+
async function detectEditIntentEnhanced(root, request, ctx2) {
|
|
40568
|
+
const baseline = detectEditIntent(request, { hasAttachments: ctx2.hasAttachments, explicitFilesCount: ctx2.explicitFiles.length });
|
|
40569
|
+
if (baseline) return true;
|
|
40570
|
+
const r2 = request.toLowerCase();
|
|
40571
|
+
const softHints = ["improve", "enhance", "make it", "change the", "adjust", "tweak", "rework", "revamp", "retro", "modernize", "clean up", "polish"];
|
|
40572
|
+
const hasSoftHint = softHints.some((k) => r2.includes(k));
|
|
40573
|
+
if (!hasSoftHint) return false;
|
|
40574
|
+
try {
|
|
40575
|
+
const fs52 = await import('fs/promises');
|
|
40576
|
+
const pathMod = await import('path');
|
|
40577
|
+
const { loadGlobby: loadGlobby2 } = await Promise.resolve().then(() => (init_esm_compat(), esm_compat_exports));
|
|
40578
|
+
const globby = await loadGlobby2();
|
|
40579
|
+
const ignore = [
|
|
40580
|
+
"**/node_modules/**",
|
|
40581
|
+
"**/.git/**",
|
|
40582
|
+
"**/dist/**",
|
|
40583
|
+
"**/build/**",
|
|
40584
|
+
"**/.maria/**",
|
|
40585
|
+
"**/.next/**",
|
|
40586
|
+
"**/coverage/**",
|
|
40587
|
+
"**/.DS_Store/**",
|
|
40588
|
+
"**/.DS_Store",
|
|
40589
|
+
"**/.Spotlight-V100/**",
|
|
40590
|
+
"**/.Spotlight-V100",
|
|
40591
|
+
"**/.Trashes/**",
|
|
40592
|
+
"**/.Trashes",
|
|
40593
|
+
"**/.fseventsd/**",
|
|
40594
|
+
"**/.fseventsd",
|
|
40595
|
+
"**/.TemporaryItems/**",
|
|
40596
|
+
"**/.TemporaryItems"
|
|
40597
|
+
];
|
|
40598
|
+
const candidates = await globby(["**/*.{html,css,js,ts,tsx}"], { cwd: root, absolute: true, gitignore: true, ignore, deep: 3 });
|
|
40599
|
+
if (candidates && candidates.length > 0) return true;
|
|
40600
|
+
} catch {
|
|
40601
|
+
}
|
|
40602
|
+
try {
|
|
40603
|
+
const short = request.trim().length <= 160;
|
|
40604
|
+
if (!short) return false;
|
|
40605
|
+
const system = [
|
|
40606
|
+
"You are classifying whether the user intends to EDIT existing files vs CREATE a new project.",
|
|
40607
|
+
'Return JSON: { "edit": true|false } only.'
|
|
40608
|
+
].join("\n");
|
|
40609
|
+
const user = `Instruction: ${request}`;
|
|
40610
|
+
const resp = await executeChat([
|
|
40611
|
+
{ role: "system", content: system },
|
|
40612
|
+
{ role: "user", content: user }
|
|
40613
|
+
]);
|
|
40614
|
+
const raw = (resp?.output || "").trim();
|
|
40615
|
+
const jsonText = (() => {
|
|
40616
|
+
try {
|
|
40617
|
+
const m2 = raw.match(/\{[\s\S]*\}/);
|
|
40618
|
+
return m2 ? m2[0] : raw;
|
|
40619
|
+
} catch {
|
|
40620
|
+
return raw;
|
|
40621
|
+
}
|
|
40622
|
+
})();
|
|
40623
|
+
const parsed = JSON.parse(jsonText);
|
|
40624
|
+
if (typeof parsed?.edit === "boolean") return !!parsed.edit;
|
|
40625
|
+
} catch {
|
|
40626
|
+
}
|
|
40627
|
+
return false;
|
|
40628
|
+
}
|
|
40182
40629
|
function sanitizeFolderName(name2) {
|
|
40183
40630
|
const base = name2.toLowerCase().replace(/[`~!@#$%^&*()+=\[\]{}|;:'",<>/?\\]/g, " ").replace(/\s+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
40184
40631
|
return base || "project";
|
|
@@ -40211,14 +40658,14 @@ async function ensureTopFolder(root, proposed, plans) {
|
|
|
40211
40658
|
return { folderName: unique };
|
|
40212
40659
|
}
|
|
40213
40660
|
async function ensureUniqueFolder(root, base) {
|
|
40214
|
-
const
|
|
40661
|
+
const fs52 = await import('fs/promises');
|
|
40215
40662
|
const pathMod = await import('path');
|
|
40216
40663
|
let name2 = sanitizeFolderName(base);
|
|
40217
40664
|
let suffix = 0;
|
|
40218
40665
|
for (; suffix < Number.MAX_SAFE_INTEGER; ) {
|
|
40219
40666
|
const candidate = suffix === 0 ? name2 : `${name2}-${String(suffix).padStart(2, "0")}`;
|
|
40220
40667
|
try {
|
|
40221
|
-
await
|
|
40668
|
+
await fs52.access(pathMod.join(root, candidate));
|
|
40222
40669
|
suffix += 1;
|
|
40223
40670
|
} catch {
|
|
40224
40671
|
return candidate;
|
|
@@ -40228,13 +40675,13 @@ async function ensureUniqueFolder(root, base) {
|
|
|
40228
40675
|
}
|
|
40229
40676
|
async function buildEditContext(root, files, maxLines, maxBytes) {
|
|
40230
40677
|
try {
|
|
40231
|
-
const
|
|
40678
|
+
const fs52 = await import('fs/promises');
|
|
40232
40679
|
const pathMod = await import('path');
|
|
40233
40680
|
const sections = [];
|
|
40234
40681
|
for (const rel of files) {
|
|
40235
40682
|
const full = pathMod.join(root, rel);
|
|
40236
40683
|
try {
|
|
40237
|
-
const buf = await
|
|
40684
|
+
const buf = await fs52.readFile(full);
|
|
40238
40685
|
const clipped = buf.length > maxBytes ? buf.subarray(0, maxBytes) : buf;
|
|
40239
40686
|
const text = clipped.toString("utf8").replace(/\r\n/g, "\n");
|
|
40240
40687
|
const lines = text.split("\n").slice(0, maxLines).join("\n");
|
|
@@ -40251,84 +40698,58 @@ ${lines}
|
|
|
40251
40698
|
}
|
|
40252
40699
|
}
|
|
40253
40700
|
async function resolveExplicitPaths(root, files, hintText) {
|
|
40254
|
-
const
|
|
40701
|
+
const fs52 = await import('fs/promises');
|
|
40255
40702
|
const pathMod = await import('path');
|
|
40256
|
-
const
|
|
40257
|
-
|
|
40258
|
-
|
|
40259
|
-
"
|
|
40260
|
-
"
|
|
40261
|
-
"
|
|
40262
|
-
"
|
|
40263
|
-
"
|
|
40264
|
-
"
|
|
40265
|
-
"
|
|
40266
|
-
|
|
40267
|
-
|
|
40268
|
-
|
|
40269
|
-
|
|
40270
|
-
|
|
40271
|
-
|
|
40272
|
-
|
|
40273
|
-
|
|
40274
|
-
|
|
40703
|
+
const ignoreDir = /* @__PURE__ */ new Set([
|
|
40704
|
+
".git",
|
|
40705
|
+
"node_modules",
|
|
40706
|
+
"dist",
|
|
40707
|
+
"build",
|
|
40708
|
+
".maria",
|
|
40709
|
+
".next",
|
|
40710
|
+
"coverage",
|
|
40711
|
+
".DS_Store",
|
|
40712
|
+
".Spotlight-V100",
|
|
40713
|
+
".Trashes",
|
|
40714
|
+
".fseventsd",
|
|
40715
|
+
".TemporaryItems"
|
|
40716
|
+
]);
|
|
40717
|
+
async function buildRepoIndex() {
|
|
40718
|
+
if (_repoFileIndexCache && _repoFileIndexCache.root === root) return _repoFileIndexCache.files;
|
|
40719
|
+
const out2 = [];
|
|
40720
|
+
async function walk2(dir) {
|
|
40721
|
+
let entries = [];
|
|
40722
|
+
try {
|
|
40723
|
+
entries = await fs52.readdir(dir, { withFileTypes: true });
|
|
40724
|
+
} catch {
|
|
40725
|
+
return;
|
|
40726
|
+
}
|
|
40727
|
+
for (const e2 of entries) {
|
|
40728
|
+
const name2 = e2.name;
|
|
40729
|
+
if (ignoreDir.has(name2)) continue;
|
|
40730
|
+
const full = pathMod.join(dir, name2);
|
|
40731
|
+
if (e2.isDirectory()) {
|
|
40732
|
+
await walk2(full);
|
|
40733
|
+
continue;
|
|
40734
|
+
}
|
|
40735
|
+
out2.push(pathMod.relative(root, full).replace(/\\/g, "/"));
|
|
40736
|
+
}
|
|
40275
40737
|
}
|
|
40738
|
+
await walk2(root);
|
|
40739
|
+
_repoFileIndexCache = { root, files: out2 };
|
|
40740
|
+
return out2;
|
|
40741
|
+
}
|
|
40742
|
+
const allFiles = await buildRepoIndex();
|
|
40743
|
+
const hintTokens = Array.from(new Set(hintText.toLowerCase().replace(/[^a-z0-9_/.-]+/g, " ").split(/\s+/).filter(Boolean)));
|
|
40744
|
+
async function rankCandidates(candidates, desired) {
|
|
40745
|
+
const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
40276
40746
|
const lowerRel = normalized.toLowerCase();
|
|
40277
40747
|
const ext2 = (pathMod.extname(normalized) || "").toLowerCase();
|
|
40278
40748
|
const base = pathMod.basename(normalized);
|
|
40279
|
-
|
|
40749
|
+
base.replace(/\.[^.]+$/, "").toLowerCase();
|
|
40280
40750
|
const parentPath = pathMod.dirname(normalized);
|
|
40281
40751
|
const parent = parentPath.split("/").pop() || "";
|
|
40282
40752
|
const dirParts = parentPath === "." ? [] : parentPath.split("/").filter(Boolean).map((s2) => s2.toLowerCase());
|
|
40283
|
-
const patterns = [];
|
|
40284
|
-
patterns.push(`**/${normalized}`);
|
|
40285
|
-
if (parent && parent !== "." && parent !== "/") patterns.push(`**/${parent}/${base}`);
|
|
40286
|
-
if (base) patterns.push(`**/${base}`);
|
|
40287
|
-
patterns.push(`**/*${base}`);
|
|
40288
|
-
if (!ext2) {
|
|
40289
|
-
patterns.push(`**/${nameNoExt}.*`);
|
|
40290
|
-
}
|
|
40291
|
-
const uniqPatterns = Array.from(new Set(patterns));
|
|
40292
|
-
const candidatesSet = /* @__PURE__ */ new Set();
|
|
40293
|
-
for (const pat of uniqPatterns) {
|
|
40294
|
-
const found = await globby(pat, { cwd: root, absolute: false, gitignore: true, ignore });
|
|
40295
|
-
for (const f3 of found) {
|
|
40296
|
-
candidatesSet.add(f3.replace(/\\/g, "/"));
|
|
40297
|
-
}
|
|
40298
|
-
if (candidatesSet.size > 200) break;
|
|
40299
|
-
}
|
|
40300
|
-
let candidates = Array.from(candidatesSet);
|
|
40301
|
-
if (dirParts.length > 0) {
|
|
40302
|
-
const filtered = candidates.filter((relp) => {
|
|
40303
|
-
const segs = relp.toLowerCase().split("/");
|
|
40304
|
-
let pos = -1;
|
|
40305
|
-
for (const part of dirParts) {
|
|
40306
|
-
const next = segs.indexOf(part, pos + 1);
|
|
40307
|
-
if (next === -1) return false;
|
|
40308
|
-
pos = next;
|
|
40309
|
-
}
|
|
40310
|
-
return true;
|
|
40311
|
-
});
|
|
40312
|
-
if (filtered.length > 0) candidates = filtered;
|
|
40313
|
-
}
|
|
40314
|
-
if (candidates.length === 0) {
|
|
40315
|
-
const prefixes = ["", "src/", "app/", "pages/"];
|
|
40316
|
-
for (const pre of prefixes) {
|
|
40317
|
-
const cand = pathMod.join(root, pre + normalized);
|
|
40318
|
-
try {
|
|
40319
|
-
await fs51.access(cand);
|
|
40320
|
-
return (pre + normalized).replace(/^\/+/, "");
|
|
40321
|
-
} catch {
|
|
40322
|
-
}
|
|
40323
|
-
}
|
|
40324
|
-
if (dirParts.length > 0) {
|
|
40325
|
-
if (/^(src|app|pages)\//i.test(normalized)) return normalized;
|
|
40326
|
-
const pref = await pickExistingFolderPrefix(root, parentPath);
|
|
40327
|
-
const combined = (pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1");
|
|
40328
|
-
return combined;
|
|
40329
|
-
}
|
|
40330
|
-
return normalized.replace(/^(src\/)src\//i, "$1");
|
|
40331
|
-
}
|
|
40332
40753
|
function score(relPath) {
|
|
40333
40754
|
const lower2 = relPath.toLowerCase();
|
|
40334
40755
|
let s2 = 0;
|
|
@@ -40352,10 +40773,36 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
40352
40773
|
s2 -= Math.min(10, Math.floor(relPath.length / 80));
|
|
40353
40774
|
return s2;
|
|
40354
40775
|
}
|
|
40355
|
-
|
|
40776
|
+
const limited = candidates.slice(0, Math.min(50, candidates.length));
|
|
40777
|
+
if (limited.length > 1) {
|
|
40778
|
+
try {
|
|
40779
|
+
const ranked = limited.map((p) => ({ p, s: score(p) })).sort((a, b) => b.s - a.s).slice(0, 5).map((x2) => x2.p);
|
|
40780
|
+
const system = [
|
|
40781
|
+
"You are helping choose the most relevant target file path for an edit operation.",
|
|
40782
|
+
"Given a user request and several candidate repo-relative paths, pick ONE best path.",
|
|
40783
|
+
"Return ONLY the raw path text. No code blocks. No explanations."
|
|
40784
|
+
].join("\n");
|
|
40785
|
+
const user = [
|
|
40786
|
+
`User request: ${hintText}`,
|
|
40787
|
+
"Candidates:",
|
|
40788
|
+
...ranked.map((r2, i2) => `${i2 + 1}. ${r2}`),
|
|
40789
|
+
"",
|
|
40790
|
+
"Answer with exactly one of the candidate paths."
|
|
40791
|
+
].join("\n");
|
|
40792
|
+
const chat = await executeChat([
|
|
40793
|
+
{ role: "system", content: system },
|
|
40794
|
+
{ role: "user", content: user }
|
|
40795
|
+
]);
|
|
40796
|
+
const raw = (chat.output || "").trim();
|
|
40797
|
+
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
40798
|
+
return pick.replace(/^\/+/, "");
|
|
40799
|
+
} catch {
|
|
40800
|
+
}
|
|
40801
|
+
}
|
|
40802
|
+
let best = limited[0];
|
|
40356
40803
|
let bestScore = score(best);
|
|
40357
|
-
for (let i2 = 1; i2 <
|
|
40358
|
-
const c =
|
|
40804
|
+
for (let i2 = 1; i2 < limited.length; i2++) {
|
|
40805
|
+
const c = limited[i2];
|
|
40359
40806
|
const sc = score(c);
|
|
40360
40807
|
if (sc > bestScore) {
|
|
40361
40808
|
best = c;
|
|
@@ -40365,20 +40812,41 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
40365
40812
|
return best.replace(/^\/+/, "");
|
|
40366
40813
|
}
|
|
40367
40814
|
const out = [];
|
|
40368
|
-
for (const
|
|
40369
|
-
|
|
40815
|
+
for (const desired of files) {
|
|
40816
|
+
const normalized = desired.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
40817
|
+
if (allFiles.includes(normalized)) {
|
|
40818
|
+
out.push(normalized);
|
|
40819
|
+
continue;
|
|
40820
|
+
}
|
|
40821
|
+
const base = pathMod.basename(normalized).toLowerCase();
|
|
40822
|
+
const nameNoExt = base.replace(/\.[^.]+$/, "");
|
|
40823
|
+
const candidates = allFiles.filter((p) => {
|
|
40824
|
+
const b = pathMod.basename(p).toLowerCase();
|
|
40825
|
+
return b === base || b.includes(base) || !base.includes(".") && (b === `${nameNoExt}.ts` || b === `${nameNoExt}.js` || b.startsWith(nameNoExt));
|
|
40826
|
+
});
|
|
40827
|
+
if (candidates.length === 0) {
|
|
40828
|
+
const parentPath = pathMod.dirname(normalized);
|
|
40829
|
+
if (parentPath && parentPath !== ".") {
|
|
40830
|
+
const pref = await pickExistingFolderPrefix(root, parentPath);
|
|
40831
|
+
out.push((pref + normalized).replace(/^\/+/, "").replace(/^(src\/)src\//i, "$1"));
|
|
40832
|
+
} else {
|
|
40833
|
+
out.push(normalized.replace(/^(src\/)src\//i, "$1"));
|
|
40834
|
+
}
|
|
40835
|
+
continue;
|
|
40836
|
+
}
|
|
40837
|
+
out.push(await rankCandidates(candidates, normalized));
|
|
40370
40838
|
}
|
|
40371
40839
|
return out;
|
|
40372
40840
|
}
|
|
40373
40841
|
async function pickExistingFolderPrefix(root, parentPath) {
|
|
40374
|
-
const
|
|
40842
|
+
const fs52 = await import('fs/promises');
|
|
40375
40843
|
const pathMod = await import('path');
|
|
40376
40844
|
const parts = parentPath.replace(/^\/+/, "").split("/").filter(Boolean);
|
|
40377
40845
|
const prefixes = ["src", "app", "pages", ""];
|
|
40378
40846
|
for (const pre of prefixes) {
|
|
40379
40847
|
const test = pre ? pathMod.join(root, pre, ...parts) : pathMod.join(root, ...parts);
|
|
40380
40848
|
try {
|
|
40381
|
-
await
|
|
40849
|
+
await fs52.access(test);
|
|
40382
40850
|
return pre ? `${pre}/` : "";
|
|
40383
40851
|
} catch {
|
|
40384
40852
|
}
|
|
@@ -40425,7 +40893,7 @@ requestAnimationFrame(step);`;
|
|
|
40425
40893
|
}
|
|
40426
40894
|
return { path: filename, kind: "source", action: "create", description: "Source file", preview: "" };
|
|
40427
40895
|
}
|
|
40428
|
-
var codeFallbackManager, codeFallbackPolicySignature;
|
|
40896
|
+
var codeFallbackManager, _repoFileIndexCache, codeFallbackPolicySignature;
|
|
40429
40897
|
var init_Orchestrator = __esm({
|
|
40430
40898
|
"src/services/code-orchestrator/Orchestrator.ts"() {
|
|
40431
40899
|
init_RepoScanner();
|
|
@@ -40440,6 +40908,7 @@ var init_Orchestrator = __esm({
|
|
|
40440
40908
|
init_FallbackManager();
|
|
40441
40909
|
init_policy();
|
|
40442
40910
|
codeFallbackManager = null;
|
|
40911
|
+
_repoFileIndexCache = null;
|
|
40443
40912
|
codeFallbackPolicySignature = null;
|
|
40444
40913
|
}
|
|
40445
40914
|
});
|
|
@@ -40552,8 +41021,8 @@ var init_code_command = __esm({
|
|
|
40552
41021
|
try {
|
|
40553
41022
|
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 });
|
|
40554
41023
|
if (opts.planOnly) {
|
|
40555
|
-
const
|
|
40556
|
-
const
|
|
41024
|
+
const fs52 = await import('fs/promises');
|
|
41025
|
+
const path65 = await import('path');
|
|
40557
41026
|
const spec = res?.specMarkdown;
|
|
40558
41027
|
const lines = Array.isArray(res?.summaryLines) ? res.summaryLines : [];
|
|
40559
41028
|
const planItems = [];
|
|
@@ -40587,13 +41056,13 @@ var init_code_command = __esm({
|
|
|
40587
41056
|
if (planItems.length) md.push(...planItems);
|
|
40588
41057
|
else md.push("- (no summary available)");
|
|
40589
41058
|
}
|
|
40590
|
-
const plansDir =
|
|
40591
|
-
await
|
|
41059
|
+
const plansDir = path65.join(root, ".maria", "plans");
|
|
41060
|
+
await fs52.mkdir(plansDir, { recursive: true });
|
|
40592
41061
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
40593
41062
|
const fileName = `code-plan-${ts}.md`;
|
|
40594
|
-
const outPath =
|
|
40595
|
-
await
|
|
40596
|
-
const rel =
|
|
41063
|
+
const outPath = path65.join(plansDir, fileName);
|
|
41064
|
+
await fs52.writeFile(outPath, md.join("\n") + "\n", "utf8");
|
|
41065
|
+
const rel = path65.relative(root, outPath);
|
|
40597
41066
|
return this.success(`Code plan saved: ${rel}`);
|
|
40598
41067
|
}
|
|
40599
41068
|
const detail = res?.detailLines;
|
|
@@ -40653,6 +41122,97 @@ ${pretty}`);
|
|
|
40653
41122
|
// Add default language hints when not specified by the user (LLM-assisted detection)
|
|
40654
41123
|
async ensureLanguageDefaults(raw) {
|
|
40655
41124
|
try {
|
|
41125
|
+
const fs52 = await import('fs/promises');
|
|
41126
|
+
const pathMod = await import('path');
|
|
41127
|
+
const cwd2 = process.cwd();
|
|
41128
|
+
const ignoreDir = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".maria", ".next", "coverage", ".DS_Store", ".Spotlight-V100", ".Trashes", ".fseventsd", ".TemporaryItems"]);
|
|
41129
|
+
const pathTokens = /* @__PURE__ */ new Set();
|
|
41130
|
+
const fileLike = raw.match(/([\w\-./\\:]+\.[A-Za-z0-9]{1,10})/g) || [];
|
|
41131
|
+
for (const t2 of fileLike) pathTokens.add(t2);
|
|
41132
|
+
const slashLike = raw.match(/[^\s"']*[\\/][^\s"']+/g) || [];
|
|
41133
|
+
for (const t2 of slashLike) pathTokens.add(t2);
|
|
41134
|
+
const listFilesUnder = async (dir, maxCount) => {
|
|
41135
|
+
const out = [];
|
|
41136
|
+
const walk2 = async (d) => {
|
|
41137
|
+
if (out.length >= maxCount) return;
|
|
41138
|
+
let entries = [];
|
|
41139
|
+
try {
|
|
41140
|
+
entries = await fs52.readdir(d, { withFileTypes: true });
|
|
41141
|
+
} catch {
|
|
41142
|
+
return;
|
|
41143
|
+
}
|
|
41144
|
+
for (const e2 of entries) {
|
|
41145
|
+
const name2 = e2.name;
|
|
41146
|
+
if (ignoreDir.has(name2)) continue;
|
|
41147
|
+
const full = pathMod.join(d, name2);
|
|
41148
|
+
if (e2.isDirectory()) {
|
|
41149
|
+
await walk2(full);
|
|
41150
|
+
if (out.length >= maxCount) break;
|
|
41151
|
+
continue;
|
|
41152
|
+
}
|
|
41153
|
+
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)) {
|
|
41154
|
+
out.push(full);
|
|
41155
|
+
if (out.length >= maxCount) break;
|
|
41156
|
+
}
|
|
41157
|
+
}
|
|
41158
|
+
};
|
|
41159
|
+
await walk2(dir);
|
|
41160
|
+
return out;
|
|
41161
|
+
};
|
|
41162
|
+
const readHead = async (full, lines) => {
|
|
41163
|
+
try {
|
|
41164
|
+
const buf = await fs52.readFile(full, "utf8");
|
|
41165
|
+
return buf.split(/\r?\n/).slice(0, lines).join("\n");
|
|
41166
|
+
} catch {
|
|
41167
|
+
return "";
|
|
41168
|
+
}
|
|
41169
|
+
};
|
|
41170
|
+
const samples = [];
|
|
41171
|
+
for (const tok of Array.from(pathTokens)) {
|
|
41172
|
+
const abs = pathMod.isAbsolute(tok) ? tok : pathMod.join(cwd2, tok);
|
|
41173
|
+
try {
|
|
41174
|
+
const st = await fs52.stat(abs);
|
|
41175
|
+
if (st.isFile()) {
|
|
41176
|
+
samples.push(await readHead(abs, 10));
|
|
41177
|
+
} else if (st.isDirectory()) {
|
|
41178
|
+
const files = await listFilesUnder(abs, 25);
|
|
41179
|
+
for (const f3 of files) samples.push(await readHead(f3, 10));
|
|
41180
|
+
}
|
|
41181
|
+
} catch {
|
|
41182
|
+
}
|
|
41183
|
+
if (samples.length >= 50) break;
|
|
41184
|
+
}
|
|
41185
|
+
if (samples.length > 0) {
|
|
41186
|
+
const preSpin = new ProcessAnimation();
|
|
41187
|
+
preSpin.start();
|
|
41188
|
+
let llmLang = null;
|
|
41189
|
+
try {
|
|
41190
|
+
llmLang = await this.detectLanguageLLMFromSamples(samples);
|
|
41191
|
+
} finally {
|
|
41192
|
+
try {
|
|
41193
|
+
preSpin.stop();
|
|
41194
|
+
} catch {
|
|
41195
|
+
}
|
|
41196
|
+
}
|
|
41197
|
+
if (llmLang) {
|
|
41198
|
+
const hint2 = (() => {
|
|
41199
|
+
const l = llmLang.toLowerCase();
|
|
41200
|
+
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
41201
|
+
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
41202
|
+
if (l === "typescript") return "TypeScript";
|
|
41203
|
+
if (l === "javascript") return "JavaScript";
|
|
41204
|
+
if (l === "html") return "HTML";
|
|
41205
|
+
if (l === "css") return "CSS";
|
|
41206
|
+
return llmLang;
|
|
41207
|
+
})();
|
|
41208
|
+
return raw + ` (Use ${hint2})`;
|
|
41209
|
+
}
|
|
41210
|
+
}
|
|
41211
|
+
} catch {
|
|
41212
|
+
}
|
|
41213
|
+
try {
|
|
41214
|
+
const preSpin = new ProcessAnimation();
|
|
41215
|
+
preSpin.start();
|
|
40656
41216
|
const system = [
|
|
40657
41217
|
"You analyze a user's code-generation request.",
|
|
40658
41218
|
"Decide if the user explicitly specified a programming language or framework/tooling (e.g., TypeScript, Python, Rust, Java, React, Vue, Node, etc.).",
|
|
@@ -40671,8 +41231,12 @@ ${pretty}`);
|
|
|
40671
41231
|
${user}`
|
|
40672
41232
|
}
|
|
40673
41233
|
});
|
|
41234
|
+
try {
|
|
41235
|
+
preSpin.stop();
|
|
41236
|
+
} catch {
|
|
41237
|
+
}
|
|
40674
41238
|
const content = (resp?.data?.content || resp?.content || "").trim();
|
|
40675
|
-
const
|
|
41239
|
+
const extractFirstJson7 = (text) => {
|
|
40676
41240
|
const fence = /```\s*json\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
40677
41241
|
if (fence) return fence[1];
|
|
40678
41242
|
const generic = /```\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
@@ -40695,7 +41259,7 @@ ${user}`
|
|
|
40695
41259
|
}
|
|
40696
41260
|
return null;
|
|
40697
41261
|
};
|
|
40698
|
-
const jsonText =
|
|
41262
|
+
const jsonText = extractFirstJson7(content) || content;
|
|
40699
41263
|
let parsed = {};
|
|
40700
41264
|
try {
|
|
40701
41265
|
parsed = JSON.parse(jsonText);
|
|
@@ -40708,6 +41272,76 @@ ${user}`
|
|
|
40708
41272
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
40709
41273
|
return raw + hint;
|
|
40710
41274
|
}
|
|
41275
|
+
// LLM-based language detection from sample code heads (top-10 lines per file)
|
|
41276
|
+
async detectLanguageLLMFromSamples(samples) {
|
|
41277
|
+
try {
|
|
41278
|
+
const system = [
|
|
41279
|
+
"You are a programming language classifier.",
|
|
41280
|
+
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
41281
|
+
"Respond with ONLY a single token language name from this set:",
|
|
41282
|
+
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
41283
|
+
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
41284
|
+
].join("\n");
|
|
41285
|
+
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
41286
|
+
${s2}`).join("\n\n");
|
|
41287
|
+
const { callAPI: callAPI2 } = await Promise.resolve().then(() => (init_api_caller(), api_caller_exports));
|
|
41288
|
+
const resp = await callAPI2("/v1/ai-proxy", {
|
|
41289
|
+
method: "POST",
|
|
41290
|
+
body: {
|
|
41291
|
+
provider: "google",
|
|
41292
|
+
model: "gemini-2.5-flash",
|
|
41293
|
+
taskType: "chat",
|
|
41294
|
+
prompt: `${system}
|
|
41295
|
+
|
|
41296
|
+
${joined}`
|
|
41297
|
+
}
|
|
41298
|
+
});
|
|
41299
|
+
const content = (resp?.data?.content || resp?.content || "").trim();
|
|
41300
|
+
const token = content.replace(/```[\s\S]*?```/g, "").trim().toLowerCase();
|
|
41301
|
+
const norm = this.normalizeLanguageName(token);
|
|
41302
|
+
return norm || null;
|
|
41303
|
+
} catch {
|
|
41304
|
+
return null;
|
|
41305
|
+
}
|
|
41306
|
+
}
|
|
41307
|
+
normalizeLanguageName(lang) {
|
|
41308
|
+
const l = (lang || "").toLowerCase().trim();
|
|
41309
|
+
if (!l) return null;
|
|
41310
|
+
const map = {
|
|
41311
|
+
"ts": "typescript",
|
|
41312
|
+
"typescript": "typescript",
|
|
41313
|
+
"tsx": "tsx",
|
|
41314
|
+
"jsx": "jsx",
|
|
41315
|
+
"js": "javascript",
|
|
41316
|
+
"javascript": "javascript",
|
|
41317
|
+
"py": "python",
|
|
41318
|
+
"python": "python",
|
|
41319
|
+
"java": "java",
|
|
41320
|
+
"go": "go",
|
|
41321
|
+
"rust": "rust",
|
|
41322
|
+
"rs": "rust",
|
|
41323
|
+
"php": "php",
|
|
41324
|
+
"c++": "cpp",
|
|
41325
|
+
"cpp": "cpp",
|
|
41326
|
+
"c": "c",
|
|
41327
|
+
"swift": "swift",
|
|
41328
|
+
"kotlin": "kotlin",
|
|
41329
|
+
"rb": "ruby",
|
|
41330
|
+
"ruby": "ruby",
|
|
41331
|
+
"cs": "csharp",
|
|
41332
|
+
"c#": "csharp",
|
|
41333
|
+
"csharp": "csharp",
|
|
41334
|
+
"html": "html",
|
|
41335
|
+
"css": "css",
|
|
41336
|
+
"scss": "scss",
|
|
41337
|
+
"json": "json",
|
|
41338
|
+
"yaml": "yaml",
|
|
41339
|
+
"yml": "yaml",
|
|
41340
|
+
"markdown": "markdown",
|
|
41341
|
+
"md": "markdown"
|
|
41342
|
+
};
|
|
41343
|
+
return map[l] || null;
|
|
41344
|
+
}
|
|
40711
41345
|
// v2.0 helpers
|
|
40712
41346
|
parseV2Options(raw) {
|
|
40713
41347
|
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 };
|
|
@@ -40903,16 +41537,16 @@ ${user}`
|
|
|
40903
41537
|
}
|
|
40904
41538
|
async persistLastPlan(root, plans) {
|
|
40905
41539
|
try {
|
|
40906
|
-
const
|
|
41540
|
+
const fs52 = await import('fs/promises');
|
|
40907
41541
|
const p = path10__namespace.join(root, ".maria");
|
|
40908
|
-
await
|
|
41542
|
+
await fs52.mkdir(p, { recursive: true });
|
|
40909
41543
|
const out = path10__namespace.join(p, "last-plan.json");
|
|
40910
|
-
await
|
|
41544
|
+
await fs52.writeFile(out, JSON.stringify({ createdAt: (/* @__PURE__ */ new Date()).toISOString(), plans }, null, 2), "utf8");
|
|
40911
41545
|
} catch {
|
|
40912
41546
|
}
|
|
40913
41547
|
}
|
|
40914
41548
|
async applyPlan(plans, options) {
|
|
40915
|
-
const
|
|
41549
|
+
const fs52 = await import('fs/promises');
|
|
40916
41550
|
const created = [];
|
|
40917
41551
|
const modified = [];
|
|
40918
41552
|
const skipped = [];
|
|
@@ -40931,9 +41565,9 @@ ${user}`
|
|
|
40931
41565
|
continue;
|
|
40932
41566
|
}
|
|
40933
41567
|
const tmp = full + `.tmp-${process.pid}-${Date.now()}`;
|
|
40934
|
-
await
|
|
40935
|
-
await
|
|
40936
|
-
await
|
|
41568
|
+
await fs52.mkdir(path10__namespace.dirname(full), { recursive: true });
|
|
41569
|
+
await fs52.writeFile(tmp, plan.preview || "", "utf8");
|
|
41570
|
+
await fs52.rename(tmp, full);
|
|
40937
41571
|
if (exists2) modified.push(plan.path);
|
|
40938
41572
|
else created.push(plan.path);
|
|
40939
41573
|
written++;
|
|
@@ -40944,7 +41578,7 @@ ${user}`
|
|
|
40944
41578
|
if (options.rollback) {
|
|
40945
41579
|
for (const p of [...created, ...modified]) {
|
|
40946
41580
|
try {
|
|
40947
|
-
await
|
|
41581
|
+
await fs52.unlink(path10__namespace.join(options.root, p));
|
|
40948
41582
|
} catch {
|
|
40949
41583
|
}
|
|
40950
41584
|
}
|
|
@@ -40954,8 +41588,8 @@ ${user}`
|
|
|
40954
41588
|
}
|
|
40955
41589
|
async pathExists(p) {
|
|
40956
41590
|
try {
|
|
40957
|
-
const
|
|
40958
|
-
await
|
|
41591
|
+
const fs52 = await import('fs/promises');
|
|
41592
|
+
await fs52.access(p);
|
|
40959
41593
|
return true;
|
|
40960
41594
|
} catch {
|
|
40961
41595
|
return false;
|
|
@@ -41066,17 +41700,17 @@ ${user}`
|
|
|
41066
41700
|
// Attempt to collect attached files from context; map to AttachedFileContext
|
|
41067
41701
|
async collectAttachedFiles(context2) {
|
|
41068
41702
|
const list = [];
|
|
41069
|
-
const
|
|
41070
|
-
const
|
|
41703
|
+
const fs52 = await import('fs/promises');
|
|
41704
|
+
const path65 = await import('path');
|
|
41071
41705
|
const att = context2 && (context2.attachments || context2.input?.attachments) || [];
|
|
41072
41706
|
for (const a of att) {
|
|
41073
41707
|
try {
|
|
41074
41708
|
const p = a.path || a.filePath || a.name || "";
|
|
41075
|
-
const originalName = a.name ||
|
|
41709
|
+
const originalName = a.name || path65.basename(p || `attachment_${Date.now().toString(36)}`);
|
|
41076
41710
|
let content = a.content;
|
|
41077
41711
|
if (!content && p) {
|
|
41078
|
-
const abs =
|
|
41079
|
-
content = await
|
|
41712
|
+
const abs = path65.isAbsolute(p) ? p : path65.join(process.cwd(), p);
|
|
41713
|
+
content = await fs52.readFile(abs, "utf8");
|
|
41080
41714
|
}
|
|
41081
41715
|
if (!content) continue;
|
|
41082
41716
|
list.push({ originalName, pathHint: p || void 0, content, size: Buffer.byteLength(content, "utf8"), mime: a.mime || a.type });
|
|
@@ -50659,17 +51293,17 @@ var init_GraphEngine = __esm({
|
|
|
50659
51293
|
const visited = /* @__PURE__ */ new Set();
|
|
50660
51294
|
const queue = [{ id: from, path: [from] }];
|
|
50661
51295
|
while (queue.length) {
|
|
50662
|
-
const { id, path:
|
|
51296
|
+
const { id, path: path65 } = queue.shift();
|
|
50663
51297
|
if (visited.has(id)) continue;
|
|
50664
51298
|
visited.add(id);
|
|
50665
51299
|
const neighbors = this.edges.get(id) || /* @__PURE__ */ new Set();
|
|
50666
51300
|
for (const e2 of neighbors) {
|
|
50667
51301
|
if (e2.to === to) {
|
|
50668
|
-
const res = [...
|
|
51302
|
+
const res = [...path65, to];
|
|
50669
51303
|
this.recordQueryTime(Date.now() - start);
|
|
50670
51304
|
return res;
|
|
50671
51305
|
}
|
|
50672
|
-
if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...
|
|
51306
|
+
if (!visited.has(e2.to)) queue.push({ id: e2.to, path: [...path65, e2.to] });
|
|
50673
51307
|
}
|
|
50674
51308
|
}
|
|
50675
51309
|
this.recordQueryTime(Date.now() - start);
|
|
@@ -53336,12 +53970,12 @@ This will:
|
|
|
53336
53970
|
};
|
|
53337
53971
|
const result = await this.deltaDetector.detectDelta(root, deltaOptions);
|
|
53338
53972
|
const files = [
|
|
53339
|
-
...result.changed.map((
|
|
53340
|
-
_path:
|
|
53341
|
-
type: previousState?.fileHashes?.[
|
|
53973
|
+
...result.changed.map((path65) => ({
|
|
53974
|
+
_path: path65,
|
|
53975
|
+
type: previousState?.fileHashes?.[path65] ? "modified" : "added"
|
|
53342
53976
|
})),
|
|
53343
|
-
...result.deleted.map((
|
|
53344
|
-
_path:
|
|
53977
|
+
...result.deleted.map((path65) => ({
|
|
53978
|
+
_path: path65,
|
|
53345
53979
|
type: "deleted"
|
|
53346
53980
|
}))
|
|
53347
53981
|
];
|
|
@@ -54017,50 +54651,6 @@ var init_UpdateCommand = __esm({
|
|
|
54017
54651
|
}
|
|
54018
54652
|
});
|
|
54019
54653
|
|
|
54020
|
-
// src/slash-commands/categories/research/utils/HeadlessBrowser.ts
|
|
54021
|
-
var HeadlessBrowser;
|
|
54022
|
-
var init_HeadlessBrowser = __esm({
|
|
54023
|
-
"src/slash-commands/categories/research/utils/HeadlessBrowser.ts"() {
|
|
54024
|
-
HeadlessBrowser = class {
|
|
54025
|
-
constructor(config2 = {}) {
|
|
54026
|
-
this.config = config2;
|
|
54027
|
-
}
|
|
54028
|
-
async execute(params2 = {}) {
|
|
54029
|
-
return {
|
|
54030
|
-
success: true,
|
|
54031
|
-
message: "Headless browser utility placeholder",
|
|
54032
|
-
data: null
|
|
54033
|
-
};
|
|
54034
|
-
}
|
|
54035
|
-
async process(input3) {
|
|
54036
|
-
return this.execute(input3);
|
|
54037
|
-
}
|
|
54038
|
-
};
|
|
54039
|
-
}
|
|
54040
|
-
});
|
|
54041
|
-
|
|
54042
|
-
// src/slash-commands/categories/research/utils/ContentExtractor.ts
|
|
54043
|
-
var ContentExtractor;
|
|
54044
|
-
var init_ContentExtractor = __esm({
|
|
54045
|
-
"src/slash-commands/categories/research/utils/ContentExtractor.ts"() {
|
|
54046
|
-
ContentExtractor = class {
|
|
54047
|
-
constructor(config2 = {}) {
|
|
54048
|
-
this.config = config2;
|
|
54049
|
-
}
|
|
54050
|
-
async execute(params2 = {}) {
|
|
54051
|
-
return {
|
|
54052
|
-
success: true,
|
|
54053
|
-
message: "Content extraction utility placeholder",
|
|
54054
|
-
data: null
|
|
54055
|
-
};
|
|
54056
|
-
}
|
|
54057
|
-
async process(input3) {
|
|
54058
|
-
return this.execute(input3);
|
|
54059
|
-
}
|
|
54060
|
-
};
|
|
54061
|
-
}
|
|
54062
|
-
});
|
|
54063
|
-
|
|
54064
54654
|
// src/slash-commands/categories/research/handlers/ResearchCommand.ts
|
|
54065
54655
|
var ResearchCommand_exports = {};
|
|
54066
54656
|
__export(ResearchCommand_exports, {
|
|
@@ -54071,8 +54661,8 @@ var init_ResearchCommand = __esm({
|
|
|
54071
54661
|
"src/slash-commands/categories/research/handlers/ResearchCommand.ts"() {
|
|
54072
54662
|
init_base_command();
|
|
54073
54663
|
init_logger();
|
|
54074
|
-
|
|
54075
|
-
|
|
54664
|
+
init_api_client();
|
|
54665
|
+
init_animations();
|
|
54076
54666
|
ResearchCommand = class extends BaseCommand {
|
|
54077
54667
|
name = "research";
|
|
54078
54668
|
category = "analysis";
|
|
@@ -54106,17 +54696,13 @@ var init_ResearchCommand = __esm({
|
|
|
54106
54696
|
author: "MARIA Team",
|
|
54107
54697
|
since: "2.0.0"
|
|
54108
54698
|
};
|
|
54109
|
-
browser = null;
|
|
54110
|
-
contentExtractor;
|
|
54111
54699
|
knowledgeBasePath;
|
|
54112
54700
|
constructor() {
|
|
54113
54701
|
super();
|
|
54114
|
-
this.contentExtractor = new ContentExtractor();
|
|
54115
54702
|
this.knowledgeBasePath = path10__namespace.default.join(os10__namespace.default.homedir(), ".maria", "knowledge-base");
|
|
54116
54703
|
}
|
|
54117
54704
|
async initialize() {
|
|
54118
54705
|
try {
|
|
54119
|
-
this.browser = new HeadlessBrowser();
|
|
54120
54706
|
await this.ensureKnowledgeBaseDirectory();
|
|
54121
54707
|
logger.debug("Research command initialized");
|
|
54122
54708
|
} catch (error2) {
|
|
@@ -54125,53 +54711,74 @@ var init_ResearchCommand = __esm({
|
|
|
54125
54711
|
}
|
|
54126
54712
|
}
|
|
54127
54713
|
async execute(_args, context2) {
|
|
54714
|
+
const spinner = new ThinkingAnimation("Researching");
|
|
54128
54715
|
try {
|
|
54129
|
-
const
|
|
54130
|
-
const
|
|
54131
|
-
const
|
|
54132
|
-
|
|
54133
|
-
|
|
54134
|
-
|
|
54135
|
-
|
|
54136
|
-
|
|
54137
|
-
|
|
54138
|
-
|
|
54139
|
-
|
|
54140
|
-
|
|
54141
|
-
const
|
|
54142
|
-
|
|
54143
|
-
|
|
54144
|
-
|
|
54145
|
-
|
|
54146
|
-
|
|
54147
|
-
|
|
54148
|
-
|
|
54149
|
-
|
|
54716
|
+
const startedAt = Date.now();
|
|
54717
|
+
const first = _args.parsed?.positional?.[0] || "";
|
|
54718
|
+
const isUrl = this.isValidUrl(first);
|
|
54719
|
+
if (!isUrl && first && ["kb", "batch", "export", "import", "status", "help"].includes(first.toLowerCase())) {
|
|
54720
|
+
return await this.handleAction(first.toLowerCase(), _args, context2);
|
|
54721
|
+
}
|
|
54722
|
+
spinner.start();
|
|
54723
|
+
const payload = isUrl ? { url: first, topK: 5 } : { query: _args.raw?.join(" ") || (_args.parsed?.positional || []).join(" "), topK: 5 };
|
|
54724
|
+
if (!payload.url && !payload.query) {
|
|
54725
|
+
spinner.stop();
|
|
54726
|
+
return this.error("URL or query required. Usage: /research <url> | /research <query>", "MISSING_INPUT");
|
|
54727
|
+
}
|
|
54728
|
+
const resp = await callApiJson(
|
|
54729
|
+
"/api/v1/research",
|
|
54730
|
+
{
|
|
54731
|
+
method: "POST",
|
|
54732
|
+
body: JSON.stringify(payload),
|
|
54733
|
+
headers: { "Content-Type": "application/json" }
|
|
54734
|
+
}
|
|
54735
|
+
);
|
|
54736
|
+
spinner.stop();
|
|
54737
|
+
if (!resp?.success || !resp?.data) {
|
|
54738
|
+
return this.error("Research failed", "RESEARCH_ERROR");
|
|
54739
|
+
}
|
|
54740
|
+
const lines = [];
|
|
54741
|
+
lines.push(resp.data.summary?.trim() || "");
|
|
54742
|
+
if (Array.isArray(resp.data.sources) && resp.data.sources.length > 0) {
|
|
54743
|
+
lines.push("\nSources:");
|
|
54744
|
+
resp.data.sources.slice(0, 5).forEach((s2, idx) => {
|
|
54745
|
+
lines.push(` ${idx + 1}. ${s2.title ? `${s2.title} - ` : ""}${s2.url}`);
|
|
54746
|
+
});
|
|
54747
|
+
}
|
|
54748
|
+
const message = lines.filter(Boolean).join("\n");
|
|
54749
|
+
const result = this.success(message);
|
|
54750
|
+
result.metadata = { executionTime: Date.now() - startedAt };
|
|
54751
|
+
this.logExecution(_args, context2, result);
|
|
54752
|
+
return result;
|
|
54753
|
+
} catch (error2) {
|
|
54754
|
+
try {
|
|
54755
|
+
spinner.stop();
|
|
54756
|
+
} catch {
|
|
54757
|
+
}
|
|
54758
|
+
logger.error("Research command execution failed:", error2);
|
|
54150
54759
|
return this.error(
|
|
54151
|
-
`Research
|
|
54760
|
+
`Research failed: ${error2 instanceof Error ? error2.message : "Unknown error"}`,
|
|
54152
54761
|
"RESEARCH_ERROR",
|
|
54153
|
-
|
|
54762
|
+
error2
|
|
54154
54763
|
);
|
|
54155
54764
|
}
|
|
54156
54765
|
}
|
|
54157
54766
|
async validate(args2) {
|
|
54158
|
-
const
|
|
54159
|
-
if (!
|
|
54767
|
+
const first = args2.parsed?.positional?.[0] || "";
|
|
54768
|
+
if (!first) {
|
|
54160
54769
|
return {
|
|
54161
54770
|
success: false,
|
|
54162
|
-
error: "URL or
|
|
54163
|
-
suggestions: [
|
|
54771
|
+
error: "URL or query required",
|
|
54772
|
+
suggestions: [
|
|
54773
|
+
"Provide a URL to research: /research https://example.com",
|
|
54774
|
+
'Or provide a query: /research "React performance optimization"',
|
|
54775
|
+
"Or use an action: /research kb list"
|
|
54776
|
+
]
|
|
54164
54777
|
};
|
|
54165
54778
|
}
|
|
54166
|
-
|
|
54167
|
-
|
|
54168
|
-
|
|
54169
|
-
return {
|
|
54170
|
-
success: false,
|
|
54171
|
-
error: `Invalid URL or _action: ${_url}`,
|
|
54172
|
-
suggestions: [`Provide a valid URL starting with http:// or https://`, `Or use one of: ${_validActions.join(", ")}`]
|
|
54173
|
-
};
|
|
54174
|
-
}
|
|
54779
|
+
const _validActions = ["kb", "batch", "export", "import", "status", "help"];
|
|
54780
|
+
if (_validActions.includes(first.toLowerCase())) {
|
|
54781
|
+
return { success: true };
|
|
54175
54782
|
}
|
|
54176
54783
|
return { success: true };
|
|
54177
54784
|
}
|
|
@@ -54200,101 +54807,7 @@ var init_ResearchCommand = __esm({
|
|
|
54200
54807
|
/**
|
|
54201
54808
|
* Perform the main research operation
|
|
54202
54809
|
*/
|
|
54203
|
-
|
|
54204
|
-
const _startTime = Date.now();
|
|
54205
|
-
const id = this.generateResearchId();
|
|
54206
|
-
try {
|
|
54207
|
-
logger.info(`Starting research for: ${_url}`);
|
|
54208
|
-
const browserOptions = {
|
|
54209
|
-
headless: true,
|
|
54210
|
-
timeout: _options.timeout,
|
|
54211
|
-
javascript: _options.javascript,
|
|
54212
|
-
waitFor: "domcontentloaded",
|
|
54213
|
-
viewport: { width: 1920, height: 1080 }
|
|
54214
|
-
};
|
|
54215
|
-
if (!this.browser) {
|
|
54216
|
-
this.browser = new HeadlessBrowser(browserOptions);
|
|
54217
|
-
}
|
|
54218
|
-
const _scrapingResult = await this.browser.scrape(_url, browserOptions);
|
|
54219
|
-
if (!_scrapingResult.html) {
|
|
54220
|
-
throw new Error(`Failed to retrieve _content from ${_url}: ${_scrapingResult.error || "Unknown error"}`);
|
|
54221
|
-
}
|
|
54222
|
-
const extractionOptions = {
|
|
54223
|
-
includeImages: _options.includeImages,
|
|
54224
|
-
includeLinks: _options.includeLinks,
|
|
54225
|
-
includeTables: true,
|
|
54226
|
-
includeCode: true,
|
|
54227
|
-
minTextLength: 50,
|
|
54228
|
-
language: _options.language,
|
|
54229
|
-
extractKeywords: _options.depth !== "basic",
|
|
54230
|
-
extractEntities: _options.depth === "comprehensive",
|
|
54231
|
-
analyzeSentiment: _options.depth === "comprehensive",
|
|
54232
|
-
preserveFormatting: _options._format === "markdown"
|
|
54233
|
-
};
|
|
54234
|
-
const _extractedContent = await this.contentExtractor.extractFromHtml(
|
|
54235
|
-
_scrapingResult.html,
|
|
54236
|
-
_url,
|
|
54237
|
-
extractionOptions
|
|
54238
|
-
);
|
|
54239
|
-
const _summary = await this.generateSummary(_extractedContent, _options);
|
|
54240
|
-
let knowledgeBaseId;
|
|
54241
|
-
if (_options.save) {
|
|
54242
|
-
knowledgeBaseId = await this.saveToKnowledgeBase(_extractedContent, _options);
|
|
54243
|
-
}
|
|
54244
|
-
const _processingTime = Date.now() - _startTime;
|
|
54245
|
-
logger.info(`Research completed for ${_url} in ${_processingTime}ms`);
|
|
54246
|
-
return {
|
|
54247
|
-
id,
|
|
54248
|
-
_url,
|
|
54249
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
54250
|
-
_processingTime,
|
|
54251
|
-
success: true,
|
|
54252
|
-
_content: _extractedContent,
|
|
54253
|
-
_summary,
|
|
54254
|
-
knowledgeBaseId
|
|
54255
|
-
};
|
|
54256
|
-
} catch (error2) {
|
|
54257
|
-
const _processingTime = Date.now() - _startTime;
|
|
54258
|
-
logger.error(`Research _failed for ${_url}:`, error2);
|
|
54259
|
-
return {
|
|
54260
|
-
id,
|
|
54261
|
-
_url,
|
|
54262
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
54263
|
-
_processingTime,
|
|
54264
|
-
success: false,
|
|
54265
|
-
error: error2 instanceof Error ? error2.message : "Unknown error"
|
|
54266
|
-
};
|
|
54267
|
-
}
|
|
54268
|
-
}
|
|
54269
|
-
/**
|
|
54270
|
-
* Format research results for display
|
|
54271
|
-
*/
|
|
54272
|
-
async formatResult(_result, _options) {
|
|
54273
|
-
if (!_result.success) {
|
|
54274
|
-
return this.error(`Research _failed: ${_result.error}`, "RESEARCH_FAILED", _result);
|
|
54275
|
-
}
|
|
54276
|
-
if (!_result._content) {
|
|
54277
|
-
return this.error("No _content extracted", "NO_CONTENT");
|
|
54278
|
-
}
|
|
54279
|
-
let message = "";
|
|
54280
|
-
switch (_options.format) {
|
|
54281
|
-
case "json":
|
|
54282
|
-
message = this.formatAsJson(_result);
|
|
54283
|
-
break;
|
|
54284
|
-
case "markdown":
|
|
54285
|
-
message = this.formatAsMarkdown(_result);
|
|
54286
|
-
break;
|
|
54287
|
-
case "structured":
|
|
54288
|
-
message = this.formatAsStructured(_result);
|
|
54289
|
-
break;
|
|
54290
|
-
default:
|
|
54291
|
-
message = this.formatAsText(_result);
|
|
54292
|
-
}
|
|
54293
|
-
if (_options.output) {
|
|
54294
|
-
await this.saveToFile(message, _options.output, _options.format);
|
|
54295
|
-
}
|
|
54296
|
-
return this.success(message, _result);
|
|
54297
|
-
}
|
|
54810
|
+
// Legacy local scraping implementation removed in favor of server API
|
|
54298
54811
|
/**
|
|
54299
54812
|
* Handle knowledge base operations
|
|
54300
54813
|
*/
|
|
@@ -54321,8 +54834,9 @@ var init_ResearchCommand = __esm({
|
|
|
54321
54834
|
* Handle batch research
|
|
54322
54835
|
*/
|
|
54323
54836
|
async handleBatchResearch(args2) {
|
|
54324
|
-
const
|
|
54325
|
-
const
|
|
54837
|
+
const positional = args2.parsed?.positional || [];
|
|
54838
|
+
const _filePath = positional[1];
|
|
54839
|
+
const _concurrent = args2.options && args2.options._concurrent ? parseInt(String(args2.options._concurrent)) : 3;
|
|
54326
54840
|
if (!_filePath) {
|
|
54327
54841
|
return this.error("File path required for batch processing", "FILE_PATH_REQUIRED");
|
|
54328
54842
|
}
|
|
@@ -54341,7 +54855,34 @@ var init_ResearchCommand = __esm({
|
|
|
54341
54855
|
}
|
|
54342
54856
|
let processed = 0;
|
|
54343
54857
|
for (const batch of batches) {
|
|
54344
|
-
const _batchPromises = batch.map((_url) =>
|
|
54858
|
+
const _batchPromises = batch.map(async (_url) => {
|
|
54859
|
+
try {
|
|
54860
|
+
const r2 = await callApiJson(
|
|
54861
|
+
"/api/v1/research",
|
|
54862
|
+
{ method: "POST", body: JSON.stringify({ url: _url, topK: 1 }), headers: { "Content-Type": "application/json" } }
|
|
54863
|
+
);
|
|
54864
|
+
const ok = !!r2?.success;
|
|
54865
|
+
const now2 = Date.now();
|
|
54866
|
+
const base = {
|
|
54867
|
+
id: this.generateResearchId(),
|
|
54868
|
+
_url,
|
|
54869
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
54870
|
+
_processingTime: 0,
|
|
54871
|
+
success: ok,
|
|
54872
|
+
_summary: (r2?.data?.summary || "").trim()
|
|
54873
|
+
};
|
|
54874
|
+
return base;
|
|
54875
|
+
} catch (e2) {
|
|
54876
|
+
return {
|
|
54877
|
+
id: this.generateResearchId(),
|
|
54878
|
+
_url,
|
|
54879
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
54880
|
+
_processingTime: 0,
|
|
54881
|
+
success: false,
|
|
54882
|
+
error: e2 instanceof Error ? e2.message : "Unknown error"
|
|
54883
|
+
};
|
|
54884
|
+
}
|
|
54885
|
+
});
|
|
54345
54886
|
const _batchResults = await Promise.allSettled(_batchPromises);
|
|
54346
54887
|
_batchResults.forEach((_result, _index) => {
|
|
54347
54888
|
if (_result.status === "fulfilled") {
|
|
@@ -54392,7 +54933,7 @@ var init_ResearchCommand = __esm({
|
|
|
54392
54933
|
|
|
54393
54934
|
`;
|
|
54394
54935
|
results.filter((r2) => r2.success).forEach((_result) => {
|
|
54395
|
-
message += `\u2022 **${_result.
|
|
54936
|
+
message += `\u2022 **${_result._url}**
|
|
54396
54937
|
`;
|
|
54397
54938
|
message += ` URL: ${_result._url}
|
|
54398
54939
|
`;
|
|
@@ -54406,192 +54947,8 @@ var init_ResearchCommand = __esm({
|
|
|
54406
54947
|
});
|
|
54407
54948
|
return this.success(message, { results, _summary: { total: _urls.length, _successful, _failed } });
|
|
54408
54949
|
} catch (innerError) {
|
|
54409
|
-
return this.error(`Batch research _failed: ${
|
|
54410
|
-
}
|
|
54411
|
-
}
|
|
54412
|
-
/**
|
|
54413
|
-
* Generate a _summary based on extracted _content
|
|
54414
|
-
*/
|
|
54415
|
-
async generateSummary(_content, _options) {
|
|
54416
|
-
try {
|
|
54417
|
-
let _summary = "";
|
|
54418
|
-
_summary += `**${_content.title}**
|
|
54419
|
-
`;
|
|
54420
|
-
if (_content.description) {
|
|
54421
|
-
_summary += `${_content.description}
|
|
54422
|
-
|
|
54423
|
-
`;
|
|
54424
|
-
}
|
|
54425
|
-
_summary += `**Domain**: ${_content.metadata.domain}
|
|
54426
|
-
`;
|
|
54427
|
-
_summary += `**Word Count**: ${_content.metadata.wordCount}
|
|
54428
|
-
`;
|
|
54429
|
-
_summary += `**Reading Time**: ${_content.metadata.readingTime} minutes
|
|
54430
|
-
`;
|
|
54431
|
-
if (_content.metadata.author) {
|
|
54432
|
-
_summary += `**Author**: ${_content.metadata.author}
|
|
54433
|
-
`;
|
|
54434
|
-
}
|
|
54435
|
-
if (_content.metadata.publishDate) {
|
|
54436
|
-
_summary += `**Published**: ${new Date(_content.metadata.publishDate).toLocaleDateString()}
|
|
54437
|
-
`;
|
|
54438
|
-
}
|
|
54439
|
-
if (_content.analysis.topics.length > 0) {
|
|
54440
|
-
_summary += `**Topics**: ${_content.analysis.topics.join(", ")}
|
|
54441
|
-
`;
|
|
54442
|
-
}
|
|
54443
|
-
if (_content.analysis.keywords.length > 0) {
|
|
54444
|
-
_summary += `**Keywords**: ${_content.analysis.keywords.slice(0, 10).join(", ")}
|
|
54445
|
-
`;
|
|
54446
|
-
}
|
|
54447
|
-
if (_options.depth !== "basic") {
|
|
54448
|
-
_summary += "\n**Content Structure**:\n";
|
|
54449
|
-
_summary += `\u2022 Headings: ${_content.structure.headings.length}
|
|
54450
|
-
`;
|
|
54451
|
-
_summary += `\u2022 Paragraphs: ${_content.structure.paragraphs.length}
|
|
54452
|
-
`;
|
|
54453
|
-
_summary += `\u2022 Images: ${_content.media.images.length}
|
|
54454
|
-
`;
|
|
54455
|
-
_summary += `\u2022 External links: ${_content.links.external.length}
|
|
54456
|
-
`;
|
|
54457
|
-
}
|
|
54458
|
-
return _summary;
|
|
54459
|
-
} catch (error2) {
|
|
54460
|
-
logger.error("Summary generation _failed:", error2);
|
|
54461
|
-
return "Summary generation _failed";
|
|
54462
|
-
}
|
|
54463
|
-
}
|
|
54464
|
-
// Format methods
|
|
54465
|
-
formatAsText(_result) {
|
|
54466
|
-
_result._content;
|
|
54467
|
-
let message = `# \u{1F50D} Research Results
|
|
54468
|
-
|
|
54469
|
-
`;
|
|
54470
|
-
message += _result._summary || "No _summary available";
|
|
54471
|
-
if (_result.knowledgeBaseId) {
|
|
54472
|
-
message += `
|
|
54473
|
-
|
|
54474
|
-
*Saved to knowledge base: ${_result.knowledgeBaseId}*`;
|
|
54950
|
+
return this.error(`Batch research _failed: ${innerError instanceof Error ? innerError.message : "Unknown error"}`, "BATCH_ERROR");
|
|
54475
54951
|
}
|
|
54476
|
-
return message;
|
|
54477
|
-
}
|
|
54478
|
-
formatAsJson(_result) {
|
|
54479
|
-
return `\`\`\`json
|
|
54480
|
-
${JSON.stringify(_result, null, 2)}
|
|
54481
|
-
\`\`\``;
|
|
54482
|
-
}
|
|
54483
|
-
formatAsMarkdown(_result) {
|
|
54484
|
-
const _content = _result._content;
|
|
54485
|
-
let markdown = `# ${_content.title}
|
|
54486
|
-
|
|
54487
|
-
`;
|
|
54488
|
-
if (_content.description) {
|
|
54489
|
-
markdown += `${_content.description}
|
|
54490
|
-
|
|
54491
|
-
`;
|
|
54492
|
-
}
|
|
54493
|
-
markdown += `**URL**: [${_result._url}](${_result._url})
|
|
54494
|
-
`;
|
|
54495
|
-
markdown += `**Domain**: ${_content.metadata.domain}
|
|
54496
|
-
`;
|
|
54497
|
-
markdown += `**Research Date**: ${_result.timestamp.toLocaleDateString()}
|
|
54498
|
-
|
|
54499
|
-
`;
|
|
54500
|
-
if (_content.structure.headings.length > 0) {
|
|
54501
|
-
markdown += `## Content Structure
|
|
54502
|
-
|
|
54503
|
-
`;
|
|
54504
|
-
_content.structure.headings.forEach((_heading) => {
|
|
54505
|
-
markdown += `${"#".repeat(_heading.level + 1)} ${_heading.text}
|
|
54506
|
-
`;
|
|
54507
|
-
});
|
|
54508
|
-
markdown += "\n";
|
|
54509
|
-
}
|
|
54510
|
-
if (_content.structure.paragraphs.length > 0) {
|
|
54511
|
-
markdown += `## Key Content
|
|
54512
|
-
|
|
54513
|
-
`;
|
|
54514
|
-
_content.structure.paragraphs.slice(0, 3).forEach((_para) => {
|
|
54515
|
-
markdown += `${_para}
|
|
54516
|
-
|
|
54517
|
-
`;
|
|
54518
|
-
});
|
|
54519
|
-
}
|
|
54520
|
-
return markdown;
|
|
54521
|
-
}
|
|
54522
|
-
formatAsStructured(_result) {
|
|
54523
|
-
const _content = _result._content;
|
|
54524
|
-
let message = `# \u{1F4CB} Structured Analysis
|
|
54525
|
-
|
|
54526
|
-
`;
|
|
54527
|
-
message += `## \u{1F4CA} Metadata
|
|
54528
|
-
|
|
54529
|
-
`;
|
|
54530
|
-
message += `| Field | Value |
|
|
54531
|
-
`;
|
|
54532
|
-
message += `|-------|-------|
|
|
54533
|
-
`;
|
|
54534
|
-
message += `| Title | ${_content.title} |
|
|
54535
|
-
`;
|
|
54536
|
-
message += `| URL | ${_result._url} |
|
|
54537
|
-
`;
|
|
54538
|
-
message += `| Domain | ${_content.metadata.domain} |
|
|
54539
|
-
`;
|
|
54540
|
-
message += `| Language | ${_content.metadata.language} |
|
|
54541
|
-
`;
|
|
54542
|
-
message += `| Word Count | ${_content.metadata.wordCount} |
|
|
54543
|
-
`;
|
|
54544
|
-
message += `| Reading Time | ${_content.metadata.readingTime} min |
|
|
54545
|
-
`;
|
|
54546
|
-
message += `
|
|
54547
|
-
## \u{1F3D7}\uFE0F Content Structure
|
|
54548
|
-
|
|
54549
|
-
`;
|
|
54550
|
-
message += `- **Headings**: ${_content.structure.headings.length}
|
|
54551
|
-
`;
|
|
54552
|
-
message += `- **Paragraphs**: ${_content.structure.paragraphs.length}
|
|
54553
|
-
`;
|
|
54554
|
-
message += `- **Lists**: ${_content.structure.lists.length}
|
|
54555
|
-
`;
|
|
54556
|
-
message += `- **Tables**: ${_content.structure.tables.length}
|
|
54557
|
-
`;
|
|
54558
|
-
message += `- **Code Blocks**: ${_content.structure.codeBlocks.length}
|
|
54559
|
-
`;
|
|
54560
|
-
message += `
|
|
54561
|
-
## \u{1F5BC}\uFE0F Media Content
|
|
54562
|
-
|
|
54563
|
-
`;
|
|
54564
|
-
message += `- **Images**: ${_content.media.images.length}
|
|
54565
|
-
`;
|
|
54566
|
-
message += `- **Videos**: ${_content.media.videos.length}
|
|
54567
|
-
`;
|
|
54568
|
-
message += `- **Documents**: ${_content.media.documents.length}
|
|
54569
|
-
`;
|
|
54570
|
-
message += `
|
|
54571
|
-
## \u{1F517} Links
|
|
54572
|
-
|
|
54573
|
-
`;
|
|
54574
|
-
message += `- **Internal**: ${_content.links.internal.length}
|
|
54575
|
-
`;
|
|
54576
|
-
message += `- **External**: ${_content.links.external.length}
|
|
54577
|
-
`;
|
|
54578
|
-
if (_content.analysis.topics.length > 0 || _content.analysis.keywords.length > 0) {
|
|
54579
|
-
message += `
|
|
54580
|
-
## \u{1F9E0} Analysis
|
|
54581
|
-
|
|
54582
|
-
`;
|
|
54583
|
-
if (_content.analysis.topics.length > 0) {
|
|
54584
|
-
message += `**Topics**: ${_content.analysis.topics.join(", ")}
|
|
54585
|
-
|
|
54586
|
-
`;
|
|
54587
|
-
}
|
|
54588
|
-
if (_content.analysis.keywords.length > 0) {
|
|
54589
|
-
message += `**Top Keywords**: ${_content.analysis.keywords.slice(0, 15).join(", ")}
|
|
54590
|
-
|
|
54591
|
-
`;
|
|
54592
|
-
}
|
|
54593
|
-
}
|
|
54594
|
-
return message;
|
|
54595
54952
|
}
|
|
54596
54953
|
// Helper methods
|
|
54597
54954
|
parseResearchOptions(args2) {
|
|
@@ -54622,25 +54979,25 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54622
54979
|
type: "research",
|
|
54623
54980
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
54624
54981
|
source: {
|
|
54625
|
-
_url: _content
|
|
54626
|
-
domain: _content
|
|
54982
|
+
_url: String(_content?.metadata?._url || ""),
|
|
54983
|
+
domain: String(_content?.metadata?.domain || ""),
|
|
54627
54984
|
accessDate: (/* @__PURE__ */ new Date()).toISOString()
|
|
54628
54985
|
},
|
|
54629
54986
|
_content: {
|
|
54630
|
-
title: _content
|
|
54631
|
-
_summary: _content
|
|
54632
|
-
keyPoints: _content.analysis.keywords.slice(0, 10),
|
|
54633
|
-
fullText: _content
|
|
54987
|
+
title: String(_content?.title || ""),
|
|
54988
|
+
_summary: String(_content?.description || ""),
|
|
54989
|
+
keyPoints: Array.isArray(_content?.analysis?.keywords) ? _content.analysis.keywords.slice(0, 10) : [],
|
|
54990
|
+
fullText: String(_content?.cleanText || "")
|
|
54634
54991
|
},
|
|
54635
54992
|
classification: {
|
|
54636
54993
|
category: _options.category || "general",
|
|
54637
|
-
topics: _content.analysis.topics,
|
|
54994
|
+
topics: Array.isArray(_content?.analysis?.topics) ? _content.analysis.topics : [],
|
|
54638
54995
|
tags: _options.tags || []
|
|
54639
54996
|
},
|
|
54640
54997
|
metadata: {
|
|
54641
|
-
language: _content
|
|
54642
|
-
wordCount: _content
|
|
54643
|
-
readingTime: _content
|
|
54998
|
+
language: String(_content?.metadata?.language || ""),
|
|
54999
|
+
wordCount: Number(_content?.metadata?.wordCount || 0),
|
|
55000
|
+
readingTime: Number(_content?.metadata?.readingTime || 0)
|
|
54644
55001
|
}
|
|
54645
55002
|
};
|
|
54646
55003
|
const _entryPath = path10__namespace.default.join(this.knowledgeBasePath, "entries", `${id}.json`);
|
|
@@ -54649,8 +55006,8 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54649
55006
|
logger.info(`Saved to knowledge base: ${id}`);
|
|
54650
55007
|
return id;
|
|
54651
55008
|
} catch (innerError) {
|
|
54652
|
-
logger.error("Failed to save to knowledge base:",
|
|
54653
|
-
throw
|
|
55009
|
+
logger.error("Failed to save to knowledge base:", innerError);
|
|
55010
|
+
throw innerError;
|
|
54654
55011
|
}
|
|
54655
55012
|
}
|
|
54656
55013
|
async updateKnowledgeBaseIndex(_entry) {
|
|
@@ -54659,11 +55016,11 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54659
55016
|
const _indexContent = await fsp__namespace.default.readFile(_indexPath, "utf-8");
|
|
54660
55017
|
const _index = JSON.parse(_indexContent);
|
|
54661
55018
|
_index.entries[_entry.id] = {
|
|
54662
|
-
title: _entry
|
|
54663
|
-
type: _entry
|
|
54664
|
-
category: _entry
|
|
54665
|
-
topics: _entry.classification.topics,
|
|
54666
|
-
timestamp: _entry.
|
|
55019
|
+
title: String(_entry?._content?.title || ""),
|
|
55020
|
+
type: String(_entry?.type || "research"),
|
|
55021
|
+
category: String(_entry?.classification?.category || "general"),
|
|
55022
|
+
topics: Array.isArray(_entry?.classification?.topics) ? _entry.classification.topics : [],
|
|
55023
|
+
timestamp: String(_entry?.timestamp || (/* @__PURE__ */ new Date()).toISOString())
|
|
54667
55024
|
};
|
|
54668
55025
|
_index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
54669
55026
|
await fsp__namespace.default.writeFile(_indexPath, JSON.stringify(_index, null, 2));
|
|
@@ -54676,7 +55033,7 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54676
55033
|
await fsp__namespace.default.mkdir(this.knowledgeBasePath, { recursive: true });
|
|
54677
55034
|
await fsp__namespace.default.mkdir(path10__namespace.default.join(this.knowledgeBasePath, "entries"), { recursive: true });
|
|
54678
55035
|
} catch (innerError) {
|
|
54679
|
-
logger.error("Failed to create knowledge base directory:",
|
|
55036
|
+
logger.error("Failed to create knowledge base directory:", innerError);
|
|
54680
55037
|
}
|
|
54681
55038
|
}
|
|
54682
55039
|
isValidUrl(_url) {
|
|
@@ -54727,20 +55084,10 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54727
55084
|
let message = `# \u{1F4CA} Research Service Status
|
|
54728
55085
|
|
|
54729
55086
|
`;
|
|
54730
|
-
|
|
54731
|
-
const _browserInfo = await this.browser.getBrowserInfo();
|
|
54732
|
-
message += `**Browser Engine**: ${_browserInfo.engine}
|
|
54733
|
-
`;
|
|
54734
|
-
message += `**Browser Status**: ${_browserInfo.ready ? "\u2705 Ready" : "\u274C Not Ready"}
|
|
55087
|
+
message += `**Server Endpoint**: /api/v1/research
|
|
54735
55088
|
`;
|
|
54736
|
-
|
|
54737
|
-
message += `**Version**: ${_browserInfo.version}
|
|
55089
|
+
message += `**Grounding**: Gemini googleSearch enabled
|
|
54738
55090
|
`;
|
|
54739
|
-
}
|
|
54740
|
-
} else {
|
|
54741
|
-
message += `**Browser Status**: \u274C Not Initialized
|
|
54742
|
-
`;
|
|
54743
|
-
}
|
|
54744
55091
|
try {
|
|
54745
55092
|
const _indexPath = path10__namespace.default.join(this.knowledgeBasePath, "index.json");
|
|
54746
55093
|
const _indexContent = await fsp__namespace.default.readFile(_indexPath, "utf-8");
|
|
@@ -54758,10 +55105,6 @@ ${JSON.stringify(_result, null, 2)}
|
|
|
54758
55105
|
return this.success(message);
|
|
54759
55106
|
}
|
|
54760
55107
|
async cleanup() {
|
|
54761
|
-
if (this.browser) {
|
|
54762
|
-
await this.browser.close();
|
|
54763
|
-
this.browser = null;
|
|
54764
|
-
}
|
|
54765
55108
|
logger.debug("Research command cleaned up");
|
|
54766
55109
|
}
|
|
54767
55110
|
};
|
|
@@ -57068,13 +57411,13 @@ async function checkShield(commandName, userPlan = "free") {
|
|
|
57068
57411
|
}
|
|
57069
57412
|
async function loadManifest() {
|
|
57070
57413
|
try {
|
|
57071
|
-
const
|
|
57072
|
-
const
|
|
57073
|
-
const manifestPath =
|
|
57414
|
+
const fs52 = await import('fs');
|
|
57415
|
+
const path65 = await import('path');
|
|
57416
|
+
const manifestPath = path65.join(
|
|
57074
57417
|
__dirname,
|
|
57075
57418
|
"../command-manifest-v2.1.json"
|
|
57076
57419
|
);
|
|
57077
|
-
const content =
|
|
57420
|
+
const content = fs52.readFileSync(manifestPath, "utf-8");
|
|
57078
57421
|
return JSON.parse(content);
|
|
57079
57422
|
} catch {
|
|
57080
57423
|
return { commands: [] };
|
|
@@ -58569,7 +58912,7 @@ ${user}`,
|
|
|
58569
58912
|
};
|
|
58570
58913
|
}
|
|
58571
58914
|
});
|
|
58572
|
-
function
|
|
58915
|
+
function extractFirstJson6(text) {
|
|
58573
58916
|
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
58574
58917
|
if (fence) return fence[1];
|
|
58575
58918
|
const start = text.indexOf("{");
|
|
@@ -58616,7 +58959,7 @@ ${user}`,
|
|
|
58616
58959
|
}
|
|
58617
58960
|
});
|
|
58618
58961
|
const raw = (response?.data?.content || response?.output || "").trim();
|
|
58619
|
-
const jsonText =
|
|
58962
|
+
const jsonText = extractFirstJson6(raw) || raw;
|
|
58620
58963
|
let parsed = {};
|
|
58621
58964
|
try {
|
|
58622
58965
|
parsed = JSON.parse(jsonText);
|
|
@@ -59476,6 +59819,15 @@ async function registerBuiltInCommands() {
|
|
|
59476
59819
|
} catch (error2) {
|
|
59477
59820
|
console.error("Failed to register media commands:", error2);
|
|
59478
59821
|
}
|
|
59822
|
+
try {
|
|
59823
|
+
const NovelModule = await Promise.resolve().then(() => (init_novel_command(), novel_command_exports));
|
|
59824
|
+
const NovelClass = NovelModule.NovelCommand || NovelModule.default;
|
|
59825
|
+
const novel = new NovelClass();
|
|
59826
|
+
if (novel.initialize) await novel.initialize();
|
|
59827
|
+
commandRegistry.register(novel);
|
|
59828
|
+
} catch (error2) {
|
|
59829
|
+
console.error("Failed to register novel command:", error2);
|
|
59830
|
+
}
|
|
59479
59831
|
try {
|
|
59480
59832
|
const { codeCommand: codeCommand2 } = await Promise.resolve().then(() => (init_code_command(), code_command_exports));
|
|
59481
59833
|
try {
|
|
@@ -62071,16 +62423,16 @@ var init_ai_response_service = __esm({
|
|
|
62071
62423
|
if (p) candidates.add(p);
|
|
62072
62424
|
}
|
|
62073
62425
|
if (candidates.size > 0) {
|
|
62074
|
-
const
|
|
62426
|
+
const fs52 = await import('fs/promises');
|
|
62075
62427
|
const pathMod = await import('path');
|
|
62076
62428
|
const cwd2 = process.cwd();
|
|
62077
62429
|
for (const cand of candidates) {
|
|
62078
62430
|
try {
|
|
62079
62431
|
const normalized = cand.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
62080
62432
|
const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(cwd2, normalized);
|
|
62081
|
-
const st = await
|
|
62433
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
62082
62434
|
if (!st || !st.isFile()) continue;
|
|
62083
|
-
const buf = await
|
|
62435
|
+
const buf = await fs52.readFile(abs);
|
|
62084
62436
|
const ext2 = (pathMod.extname(abs) || "").toLowerCase();
|
|
62085
62437
|
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";
|
|
62086
62438
|
autoAttachments.push({ name: pathMod.basename(abs), path: abs, mime, data_base64: buf.toString("base64") });
|
|
@@ -70425,8 +70777,8 @@ var init_ConfigService = __esm({
|
|
|
70425
70777
|
/**
|
|
70426
70778
|
* ネストされた設定値の取得
|
|
70427
70779
|
*/
|
|
70428
|
-
getNestedValue(
|
|
70429
|
-
const keys =
|
|
70780
|
+
getNestedValue(path65) {
|
|
70781
|
+
const keys = path65.split(".");
|
|
70430
70782
|
let value = this._config;
|
|
70431
70783
|
for (const key of keys) {
|
|
70432
70784
|
if (value && typeof value === "object" && key in value) {
|
|
@@ -70456,8 +70808,8 @@ var init_ConfigService = __esm({
|
|
|
70456
70808
|
/**
|
|
70457
70809
|
* ネストされた設定値の更新
|
|
70458
70810
|
*/
|
|
70459
|
-
async setNestedValue(
|
|
70460
|
-
const keys =
|
|
70811
|
+
async setNestedValue(path65, value) {
|
|
70812
|
+
const keys = path65.split(".");
|
|
70461
70813
|
const lastKey = keys.pop();
|
|
70462
70814
|
let target = this._config;
|
|
70463
70815
|
for (const key of keys) {
|
|
@@ -70470,7 +70822,7 @@ var init_ConfigService = __esm({
|
|
|
70470
70822
|
target[lastKey] = value;
|
|
70471
70823
|
this.validateConfig();
|
|
70472
70824
|
this.emitChange({
|
|
70473
|
-
path:
|
|
70825
|
+
path: path65,
|
|
70474
70826
|
oldValue,
|
|
70475
70827
|
newValue: value,
|
|
70476
70828
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -70515,8 +70867,8 @@ var init_ConfigService = __esm({
|
|
|
70515
70867
|
setupAutoSave() {
|
|
70516
70868
|
process.on("exit", () => {
|
|
70517
70869
|
if (this._isDirty) {
|
|
70518
|
-
const
|
|
70519
|
-
|
|
70870
|
+
const fs52 = __require("fs");
|
|
70871
|
+
fs52.writeFileSync(
|
|
70520
70872
|
this._userConfigPath,
|
|
70521
70873
|
JSON.stringify(this._config, null, 2),
|
|
70522
70874
|
"utf-8"
|
|
@@ -70527,13 +70879,13 @@ var init_ConfigService = __esm({
|
|
|
70527
70879
|
/**
|
|
70528
70880
|
* 変更リスナーの登録
|
|
70529
70881
|
*/
|
|
70530
|
-
onChange(
|
|
70531
|
-
if (!this._listeners.has(
|
|
70532
|
-
this._listeners.set(
|
|
70882
|
+
onChange(path65, listener) {
|
|
70883
|
+
if (!this._listeners.has(path65)) {
|
|
70884
|
+
this._listeners.set(path65, []);
|
|
70533
70885
|
}
|
|
70534
|
-
this._listeners.get(
|
|
70886
|
+
this._listeners.get(path65).push(listener);
|
|
70535
70887
|
return () => {
|
|
70536
|
-
const listeners = this._listeners.get(
|
|
70888
|
+
const listeners = this._listeners.get(path65);
|
|
70537
70889
|
if (listeners) {
|
|
70538
70890
|
const index = listeners.indexOf(listener);
|
|
70539
70891
|
if (index !== -1) {
|
|
@@ -71022,7 +71374,7 @@ var init_ValidationService = __esm({
|
|
|
71022
71374
|
);
|
|
71023
71375
|
this._schemas.set(
|
|
71024
71376
|
"filePath",
|
|
71025
|
-
zod.z.string().min(1).max(this._config.maxFilePathLength).refine((
|
|
71377
|
+
zod.z.string().min(1).max(this._config.maxFilePathLength).refine((path65) => !this.containsPathTraversal(path65), {
|
|
71026
71378
|
message: "Path traversal detected"
|
|
71027
71379
|
})
|
|
71028
71380
|
);
|
|
@@ -71161,11 +71513,11 @@ var init_ValidationService = __esm({
|
|
|
71161
71513
|
/**
|
|
71162
71514
|
* ファイルパス検証
|
|
71163
71515
|
*/
|
|
71164
|
-
validateFilePath(
|
|
71516
|
+
validateFilePath(path65) {
|
|
71165
71517
|
try {
|
|
71166
71518
|
const schema = this._schemas.get("filePath");
|
|
71167
|
-
const result = schema.parse(
|
|
71168
|
-
if (this.isSystemPath(
|
|
71519
|
+
const result = schema.parse(path65);
|
|
71520
|
+
if (this.isSystemPath(path65)) {
|
|
71169
71521
|
return {
|
|
71170
71522
|
valid: false,
|
|
71171
71523
|
errors: [
|
|
@@ -71311,8 +71663,8 @@ var init_ValidationService = __esm({
|
|
|
71311
71663
|
/**
|
|
71312
71664
|
* パストラバーサルの検出
|
|
71313
71665
|
*/
|
|
71314
|
-
containsPathTraversal(
|
|
71315
|
-
return /\.\.[/\\]/.test(
|
|
71666
|
+
containsPathTraversal(path65) {
|
|
71667
|
+
return /\.\.[/\\]/.test(path65) || path65.includes("..\\") || path65.includes("../");
|
|
71316
71668
|
}
|
|
71317
71669
|
/**
|
|
71318
71670
|
* 危険なコマンドの判定
|
|
@@ -71339,7 +71691,7 @@ var init_ValidationService = __esm({
|
|
|
71339
71691
|
/**
|
|
71340
71692
|
* システムパスの判定
|
|
71341
71693
|
*/
|
|
71342
|
-
isSystemPath(
|
|
71694
|
+
isSystemPath(path65) {
|
|
71343
71695
|
const systemPaths = [
|
|
71344
71696
|
"/etc",
|
|
71345
71697
|
"/sys",
|
|
@@ -71353,7 +71705,7 @@ var init_ValidationService = __esm({
|
|
|
71353
71705
|
"/sbin"
|
|
71354
71706
|
];
|
|
71355
71707
|
return systemPaths.some(
|
|
71356
|
-
(sysPath) =>
|
|
71708
|
+
(sysPath) => path65.toLowerCase().startsWith(sysPath.toLowerCase())
|
|
71357
71709
|
);
|
|
71358
71710
|
}
|
|
71359
71711
|
/**
|
|
@@ -75880,10 +76232,10 @@ Run /doctor --fix to automatically fix ${fixableCount} issue(s)`
|
|
|
75880
76232
|
const finalize = async (text, data) => {
|
|
75881
76233
|
if (outputPath) {
|
|
75882
76234
|
try {
|
|
75883
|
-
const
|
|
75884
|
-
const
|
|
75885
|
-
const abs =
|
|
75886
|
-
await
|
|
76235
|
+
const fs52 = await import('fs/promises');
|
|
76236
|
+
const path65 = await import('path');
|
|
76237
|
+
const abs = path65.resolve(outputPath);
|
|
76238
|
+
await fs52.writeFile(abs, text, "utf-8");
|
|
75887
76239
|
const msg = `Saved doctor report to ${abs}`;
|
|
75888
76240
|
return { ok: true, message: msg, data: { path: abs, bytes: Buffer.byteLength(text, "utf-8") } };
|
|
75889
76241
|
} catch (e2) {
|
|
@@ -75973,10 +76325,10 @@ Run /doctor --fix to automatically fix ${fixableCount} issue(s)`
|
|
|
75973
76325
|
const finalize = async (text, data) => {
|
|
75974
76326
|
if (outputPath) {
|
|
75975
76327
|
try {
|
|
75976
|
-
const
|
|
75977
|
-
const
|
|
75978
|
-
const abs =
|
|
75979
|
-
await
|
|
76328
|
+
const fs52 = await import('fs/promises');
|
|
76329
|
+
const path65 = await import('path');
|
|
76330
|
+
const abs = path65.resolve(outputPath);
|
|
76331
|
+
await fs52.writeFile(abs, text, "utf-8");
|
|
75980
76332
|
const msg = `Saved metrics to ${abs}`;
|
|
75981
76333
|
return { ok: true, message: msg, data: { path: abs, bytes: Buffer.byteLength(text, "utf-8") } };
|
|
75982
76334
|
} catch (e2) {
|
|
@@ -76365,15 +76717,15 @@ var init_SessionOrchestrator = __esm({
|
|
|
76365
76717
|
/**
|
|
76366
76718
|
* 設定の取得
|
|
76367
76719
|
*/
|
|
76368
|
-
getConfig(
|
|
76369
|
-
return this._configService?.getNestedValue(
|
|
76720
|
+
getConfig(path65) {
|
|
76721
|
+
return this._configService?.getNestedValue(path65);
|
|
76370
76722
|
}
|
|
76371
76723
|
/**
|
|
76372
76724
|
* 設定の更新
|
|
76373
76725
|
*/
|
|
76374
|
-
async setConfig(
|
|
76726
|
+
async setConfig(path65, value) {
|
|
76375
76727
|
if (this._configService) {
|
|
76376
|
-
await this._configService.setNestedValue(
|
|
76728
|
+
await this._configService.setNestedValue(path65, value);
|
|
76377
76729
|
}
|
|
76378
76730
|
}
|
|
76379
76731
|
/**
|
|
@@ -76491,11 +76843,11 @@ var init_interactive_session2 = __esm({
|
|
|
76491
76843
|
getStats() {
|
|
76492
76844
|
return this.orchestrator.getSessionStats();
|
|
76493
76845
|
}
|
|
76494
|
-
getConfig(
|
|
76495
|
-
return this.orchestrator.getConfig(
|
|
76846
|
+
getConfig(path65) {
|
|
76847
|
+
return this.orchestrator.getConfig(path65);
|
|
76496
76848
|
}
|
|
76497
|
-
async setConfig(
|
|
76498
|
-
await this.orchestrator.setConfig(
|
|
76849
|
+
async setConfig(path65, value) {
|
|
76850
|
+
await this.orchestrator.setConfig(path65, value);
|
|
76499
76851
|
}
|
|
76500
76852
|
};
|
|
76501
76853
|
}
|
|
@@ -76769,7 +77121,13 @@ async function handleLine(line, options = {}) {
|
|
|
76769
77121
|
const consumed = await handleSlash(input3);
|
|
76770
77122
|
if (consumed) return;
|
|
76771
77123
|
if (!input3.startsWith("/")) {
|
|
77124
|
+
const spinner = new ProcessAnimation();
|
|
77125
|
+
spinner.start();
|
|
76772
77126
|
const mapped = await mapInputToTopLevelCommand(input3);
|
|
77127
|
+
try {
|
|
77128
|
+
spinner.stop();
|
|
77129
|
+
} catch {
|
|
77130
|
+
}
|
|
76773
77131
|
if (process.env.MARIA_DEBUG === "1") {
|
|
76774
77132
|
console.log(chalk40__default.default.white(`Command: {command: '${mapped.command}', args: '${mapped.args}', confidence: '${mapped.confidence}'}`));
|
|
76775
77133
|
}
|
|
@@ -76785,6 +77143,10 @@ async function handleLine(line, options = {}) {
|
|
|
76785
77143
|
}
|
|
76786
77144
|
}
|
|
76787
77145
|
} finally {
|
|
77146
|
+
try {
|
|
77147
|
+
spinner.stop();
|
|
77148
|
+
} catch {
|
|
77149
|
+
}
|
|
76788
77150
|
}
|
|
76789
77151
|
}
|
|
76790
77152
|
const isAuthenticated = await authManager.isAuthenticated();
|