@bonginkan/maria 4.3.44 → 4.3.46
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 +1 -1
- package/dist/bin/maria.cjs +460 -149
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +460 -149
- 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 +8 -5
- package/dist/server/express-server.js +8 -5
- package/dist/server-express.cjs +8 -5
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -224,7 +224,8 @@ var init_version = __esm({
|
|
|
224
224
|
var ThinkingAnimation, ProcessAnimation;
|
|
225
225
|
var init_animations = __esm({
|
|
226
226
|
"src/utils/animations.ts"() {
|
|
227
|
-
ThinkingAnimation = class {
|
|
227
|
+
ThinkingAnimation = class _ThinkingAnimation {
|
|
228
|
+
static current = null;
|
|
228
229
|
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
229
230
|
currentFrame = 0;
|
|
230
231
|
interval = null;
|
|
@@ -233,6 +234,13 @@ var init_animations = __esm({
|
|
|
233
234
|
this.message = message;
|
|
234
235
|
}
|
|
235
236
|
start() {
|
|
237
|
+
if (_ThinkingAnimation.current && _ThinkingAnimation.current !== this) {
|
|
238
|
+
try {
|
|
239
|
+
_ThinkingAnimation.current.stop();
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
_ThinkingAnimation.current = this;
|
|
236
244
|
this.interval = setInterval(() => {
|
|
237
245
|
process.stdout.write(
|
|
238
246
|
`\r${chalk40__default.default.cyan(this.frames[this.currentFrame])} ${chalk40__default.default.gray(this.message)}...`
|
|
@@ -246,12 +254,16 @@ var init_animations = __esm({
|
|
|
246
254
|
this.interval = null;
|
|
247
255
|
process.stdout.write("\r\x1B[K");
|
|
248
256
|
}
|
|
257
|
+
if (_ThinkingAnimation.current === this) {
|
|
258
|
+
_ThinkingAnimation.current = null;
|
|
259
|
+
}
|
|
249
260
|
}
|
|
250
261
|
updateMessage(message) {
|
|
251
262
|
this.message = message;
|
|
252
263
|
}
|
|
253
264
|
};
|
|
254
|
-
ProcessAnimation = class {
|
|
265
|
+
ProcessAnimation = class _ProcessAnimation {
|
|
266
|
+
static current = null;
|
|
255
267
|
stages = [
|
|
256
268
|
{ icon: "\u{1F9E0}", message: "Understanding your request" },
|
|
257
269
|
{ icon: "\u{1F50D}", message: "Analyzing context" },
|
|
@@ -265,7 +277,18 @@ var init_animations = __esm({
|
|
|
265
277
|
interval = null;
|
|
266
278
|
stageInterval = null;
|
|
267
279
|
startTime = 0;
|
|
280
|
+
// Expose whether any ProcessAnimation is currently active
|
|
281
|
+
static hasActive() {
|
|
282
|
+
return !!_ProcessAnimation.current;
|
|
283
|
+
}
|
|
268
284
|
start() {
|
|
285
|
+
if (_ProcessAnimation.current && _ProcessAnimation.current !== this) {
|
|
286
|
+
try {
|
|
287
|
+
_ProcessAnimation.current.stop();
|
|
288
|
+
} catch {
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
_ProcessAnimation.current = this;
|
|
269
292
|
this.startTime = Date.now();
|
|
270
293
|
this.currentStage = 0;
|
|
271
294
|
this.currentFrame = 0;
|
|
@@ -293,6 +316,9 @@ var init_animations = __esm({
|
|
|
293
316
|
this.stageInterval = null;
|
|
294
317
|
}
|
|
295
318
|
process.stdout.write("\r\x1B[K");
|
|
319
|
+
if (_ProcessAnimation.current === this) {
|
|
320
|
+
_ProcessAnimation.current = null;
|
|
321
|
+
}
|
|
296
322
|
}
|
|
297
323
|
setStage(stageIndex) {
|
|
298
324
|
if (stageIndex >= 0 && stageIndex < this.stages.length) {
|
|
@@ -1709,7 +1735,7 @@ var init_AuthenticationManager = __esm({
|
|
|
1709
1735
|
const response = await fetch(`${this.apiBase}/api/user/profile`, {
|
|
1710
1736
|
headers: {
|
|
1711
1737
|
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
1712
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
1738
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.46"}`
|
|
1713
1739
|
}
|
|
1714
1740
|
});
|
|
1715
1741
|
if (response.status === 401) {
|
|
@@ -2434,7 +2460,7 @@ async function callApi(path65, init3 = {}) {
|
|
|
2434
2460
|
"Authorization": `Bearer ${token}`,
|
|
2435
2461
|
"X-Device-Id": getDeviceId(),
|
|
2436
2462
|
"X-Session-Id": getSessionId() || "",
|
|
2437
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
2463
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.46"}`,
|
|
2438
2464
|
"Content-Type": init3.headers?.["Content-Type"] || "application/json"
|
|
2439
2465
|
});
|
|
2440
2466
|
const doFetch = async (token) => {
|
|
@@ -3135,15 +3161,27 @@ async function callAPI(endpoint, options = {}) {
|
|
|
3135
3161
|
throw err;
|
|
3136
3162
|
}
|
|
3137
3163
|
}
|
|
3138
|
-
async function executeChat(messages) {
|
|
3164
|
+
async function executeChat(messages, options) {
|
|
3139
3165
|
const maxAttempts = 4;
|
|
3140
3166
|
let lastErr;
|
|
3141
3167
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
3142
3168
|
try {
|
|
3169
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
3170
|
+
try {
|
|
3171
|
+
console.log("[DEBUG/ai] chat.request", { attempt, provider: options?.provider, model: options?.model, messages: messages.slice(0, 3) });
|
|
3172
|
+
} catch {
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3143
3175
|
const response = await callAPI("/v1/ai-proxy", {
|
|
3144
3176
|
method: "POST",
|
|
3145
|
-
body: { messages, taskType: "chat" }
|
|
3177
|
+
body: { messages, taskType: "chat", ...options?.provider ? { provider: options.provider } : {}, ...options?.model ? { model: options.model } : {} }
|
|
3146
3178
|
});
|
|
3179
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
3180
|
+
try {
|
|
3181
|
+
console.log("[DEBUG/ai] chat.response.head", String(response?.data?.content || response?.output || "").slice(0, 1200));
|
|
3182
|
+
} catch {
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3147
3185
|
return response;
|
|
3148
3186
|
} catch (e2) {
|
|
3149
3187
|
lastErr = e2;
|
|
@@ -3175,6 +3213,13 @@ async function executeCode(input3) {
|
|
|
3175
3213
|
let lastErr;
|
|
3176
3214
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
3177
3215
|
try {
|
|
3216
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
3217
|
+
try {
|
|
3218
|
+
const dbg = typeof input3 === "string" ? { prompt: String(input3).slice(0, 800) } : { prompt: input3.prompt.slice(0, 800), provider: input3.provider, model: input3.model, attachments: Array.isArray(input3.attachments) ? input3.attachments.length : 0 };
|
|
3219
|
+
console.log("[DEBUG/ai] code.request", { attempt, ...dbg });
|
|
3220
|
+
} catch {
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3178
3223
|
const response = await callAPI("/v1/ai-proxy", {
|
|
3179
3224
|
method: "POST",
|
|
3180
3225
|
body
|
|
@@ -3185,6 +3230,12 @@ async function executeCode(input3) {
|
|
|
3185
3230
|
if (response.data?.content) {
|
|
3186
3231
|
response.output = response.data.content;
|
|
3187
3232
|
}
|
|
3233
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
3234
|
+
try {
|
|
3235
|
+
console.log("[DEBUG/ai] code.response.head", String(response?.output || "").slice(0, 1200));
|
|
3236
|
+
} catch {
|
|
3237
|
+
}
|
|
3238
|
+
}
|
|
3188
3239
|
return response;
|
|
3189
3240
|
} catch (e2) {
|
|
3190
3241
|
lastErr = e2;
|
|
@@ -16416,8 +16467,8 @@ var require_package = __commonJS({
|
|
|
16416
16467
|
"package.json"(exports, module) {
|
|
16417
16468
|
module.exports = {
|
|
16418
16469
|
name: "@bonginkan/maria",
|
|
16419
|
-
version: "4.3.
|
|
16420
|
-
description: "\u{1F680} MARIA v4.3.
|
|
16470
|
+
version: "4.3.46",
|
|
16471
|
+
description: "\u{1F680} MARIA v4.3.46 - 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.",
|
|
16421
16472
|
keywords: [
|
|
16422
16473
|
"ai",
|
|
16423
16474
|
"cli",
|
|
@@ -24411,7 +24462,10 @@ var init_video_command = __esm({
|
|
|
24411
24462
|
const base = (process.env.MARIA_API_BASE || "https://api.maria-code.ai").replace(/\/$/, "");
|
|
24412
24463
|
const savedPaths = [];
|
|
24413
24464
|
const baseDir = "video";
|
|
24414
|
-
const
|
|
24465
|
+
const rawPrefix = (cli.prompt || "").slice(0, 20).replace(/\s+/g, "_");
|
|
24466
|
+
let promptPrefix = rawPrefix.replace(/[\x00-\x1F<>:"/\\|?*]/g, "_").replace(/[. ]+$/g, "");
|
|
24467
|
+
if (!promptPrefix) promptPrefix = "untitled";
|
|
24468
|
+
if (/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i.test(promptPrefix)) promptPrefix = `${promptPrefix}_`;
|
|
24415
24469
|
const utc = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
24416
24470
|
let idx = 0;
|
|
24417
24471
|
for (const relRaw of filesFromApi) {
|
|
@@ -26423,7 +26477,7 @@ var init_about_command = __esm({
|
|
|
26423
26477
|
async execute(args2, context2) {
|
|
26424
26478
|
const output3 = [];
|
|
26425
26479
|
output3.push("");
|
|
26426
|
-
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.
|
|
26480
|
+
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.46"));
|
|
26427
26481
|
output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
|
|
26428
26482
|
output3.push("");
|
|
26429
26483
|
output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -38913,9 +38967,10 @@ function extractFirstJson5(text) {
|
|
|
38913
38967
|
async function inferCodeArgs(rawText) {
|
|
38914
38968
|
const system = [
|
|
38915
38969
|
"You extract structured options for a code command.",
|
|
38916
|
-
'Return JSON only with keys: { "planOnly"?: boolean, "dryRun"?: boolean, "output"?: "names"|"summary"|"detail", "previewLines"?: number }.',
|
|
38970
|
+
'Return JSON only with keys: { "planOnly"?: boolean, "dryRun"?: boolean, "output"?: "names"|"summary"|"detail", "previewLines"?: number, "onlyAttached"?: boolean }.',
|
|
38917
38971
|
"Decide from the user text whether planOnly or dryRun should be true. Do not explain.",
|
|
38918
|
-
"Only include output if the user requests preview detail or summary mode. Only include previewLines if a specific number of lines is requested."
|
|
38972
|
+
"Only include output if the user requests preview detail or summary mode. Only include previewLines if a specific number of lines is requested.",
|
|
38973
|
+
"Set onlyAttached=true when the user indicates editing only attached/uploaded/provided files, or restrict changes to referenced files."
|
|
38919
38974
|
].join("\n");
|
|
38920
38975
|
const resp = await callAPI("/v1/ai-proxy", {
|
|
38921
38976
|
method: "POST",
|
|
@@ -38936,11 +38991,19 @@ ${rawText}`,
|
|
|
38936
38991
|
} catch {
|
|
38937
38992
|
return {};
|
|
38938
38993
|
}
|
|
38994
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
38995
|
+
try {
|
|
38996
|
+
console.log("[DEBUG/code] inferCodeArgs.response.raw", raw.slice(0, 1200));
|
|
38997
|
+
console.log("[DEBUG/code] inferCodeArgs.parsed", parsed);
|
|
38998
|
+
} catch {
|
|
38999
|
+
}
|
|
39000
|
+
}
|
|
38939
39001
|
const out = {};
|
|
38940
39002
|
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
38941
39003
|
if (typeof parsed.dryRun === "boolean") out.dryRun = parsed.dryRun;
|
|
38942
39004
|
if (typeof parsed.output === "string" && (parsed.output === "names" || parsed.output === "summary" || parsed.output === "detail")) out.output = parsed.output;
|
|
38943
39005
|
if (typeof parsed.previewLines === "number" && Number.isFinite(parsed.previewLines) && parsed.previewLines > 0) out.previewLines = Math.min(2e3, Math.floor(parsed.previewLines));
|
|
39006
|
+
if (typeof parsed.onlyAttached === "boolean") out.onlyAttached = parsed.onlyAttached;
|
|
38944
39007
|
if (out.planOnly) out.dryRun = false;
|
|
38945
39008
|
return out;
|
|
38946
39009
|
}
|
|
@@ -39088,6 +39151,12 @@ var init_FilePlanBuilder = __esm({
|
|
|
39088
39151
|
}
|
|
39089
39152
|
});
|
|
39090
39153
|
async function validatePlan(plans, opts) {
|
|
39154
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
39155
|
+
try {
|
|
39156
|
+
console.log("[DEBUG/orchestrator] validatePlan.input.count", plans.length);
|
|
39157
|
+
} catch {
|
|
39158
|
+
}
|
|
39159
|
+
}
|
|
39091
39160
|
const warnings = [];
|
|
39092
39161
|
const skipped = [];
|
|
39093
39162
|
const seenLC = /* @__PURE__ */ new Set();
|
|
@@ -39104,6 +39173,10 @@ async function validatePlan(plans, opts) {
|
|
|
39104
39173
|
}
|
|
39105
39174
|
const safe = [];
|
|
39106
39175
|
for (const fp of outFiltered) {
|
|
39176
|
+
if (fp.action === "skip") {
|
|
39177
|
+
skipped.push(fp.path);
|
|
39178
|
+
continue;
|
|
39179
|
+
}
|
|
39107
39180
|
const rel = fp.path.replace(/^\/+/, "");
|
|
39108
39181
|
if (rel.includes("..")) {
|
|
39109
39182
|
warnings.push(`Path traversal denied: ${fp.path}`);
|
|
@@ -39185,7 +39258,18 @@ async function validatePlan(plans, opts) {
|
|
|
39185
39258
|
}
|
|
39186
39259
|
result.push({ ...fp, action: willModify ? "modify" : "create" });
|
|
39187
39260
|
}
|
|
39188
|
-
|
|
39261
|
+
const out = { files: result, skipped, warnings };
|
|
39262
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
39263
|
+
try {
|
|
39264
|
+
console.log("[DEBUG/orchestrator] validatePlan.output", {
|
|
39265
|
+
files: out.files.map((f3) => ({ path: f3.path, action: f3.action })),
|
|
39266
|
+
skipped: out.skipped,
|
|
39267
|
+
warnings: out.warnings
|
|
39268
|
+
});
|
|
39269
|
+
} catch {
|
|
39270
|
+
}
|
|
39271
|
+
}
|
|
39272
|
+
return out;
|
|
39189
39273
|
}
|
|
39190
39274
|
async function exists(p) {
|
|
39191
39275
|
try {
|
|
@@ -39979,7 +40063,7 @@ ${h2.head}`);
|
|
|
39979
40063
|
const resp = await executeChat([
|
|
39980
40064
|
{ role: "system", content: system },
|
|
39981
40065
|
{ role: "user", content: user }
|
|
39982
|
-
]);
|
|
40066
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
39983
40067
|
const raw = (resp?.output || "").trim();
|
|
39984
40068
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
39985
40069
|
const arr = JSON.parse(jsonText);
|
|
@@ -39996,7 +40080,7 @@ ${h2.head}`);
|
|
|
39996
40080
|
return [];
|
|
39997
40081
|
}
|
|
39998
40082
|
}
|
|
39999
|
-
async function llmMapBlocksBatch(root, request, blocks, repoFiles) {
|
|
40083
|
+
async function llmMapBlocksBatch(root, request, blocks, repoFiles, opts) {
|
|
40000
40084
|
try {
|
|
40001
40085
|
const candidates = repoFiles.filter((p) => /\.(html|css|js|ts|tsx)$/i.test(p)).slice(0, 120);
|
|
40002
40086
|
const blockSnippets = blocks.slice(0, 20).map((b, i2) => {
|
|
@@ -40014,26 +40098,43 @@ ${head2}
|
|
|
40014
40098
|
${h2.head}`);
|
|
40015
40099
|
}
|
|
40016
40100
|
const system = [
|
|
40017
|
-
"
|
|
40018
|
-
|
|
40019
|
-
"
|
|
40101
|
+
"You act as a precise file mapper for code edits.",
|
|
40102
|
+
"For each provided code block, decide to MODIFY an existing repo file or CREATE a new file.",
|
|
40103
|
+
"Rules:",
|
|
40104
|
+
"- Prefer MODIFY when an existing file in candidates plausibly matches the block (same technology, same area).",
|
|
40105
|
+
"- If any TargetDirHints are provided, prefer files under those directories when choosing MODIFY targets.",
|
|
40106
|
+
"- Only choose CREATE if NO suitable candidate exists. Do NOT invent frameworks or restructure.",
|
|
40107
|
+
"- When MODIFY, the path MUST be one of the candidate repo-relative paths listed.",
|
|
40108
|
+
'Return JSON array: [{ "index": number, "action": "modify"|"create", "path": string }].'
|
|
40020
40109
|
].join("\n");
|
|
40021
40110
|
const user = [
|
|
40022
40111
|
`Request: ${request}`,
|
|
40023
40112
|
"Blocks:",
|
|
40024
40113
|
blockSnippets,
|
|
40025
40114
|
"Candidates:",
|
|
40026
|
-
samples.join("\n\n")
|
|
40115
|
+
samples.join("\n\n"),
|
|
40116
|
+
`TargetDirHints: ${(opts?.dirHints || []).join(", ")}`
|
|
40027
40117
|
].join("\n\n");
|
|
40028
|
-
|
|
40029
|
-
spin
|
|
40030
|
-
|
|
40031
|
-
|
|
40032
|
-
|
|
40033
|
-
|
|
40118
|
+
let startedLocalSpinner = false;
|
|
40119
|
+
let spin = null;
|
|
40120
|
+
if (!ProcessAnimation.hasActive()) {
|
|
40121
|
+
spin = new ProcessAnimation();
|
|
40122
|
+
spin.start();
|
|
40123
|
+
startedLocalSpinner = true;
|
|
40124
|
+
}
|
|
40125
|
+
let resp;
|
|
40034
40126
|
try {
|
|
40035
|
-
|
|
40036
|
-
|
|
40127
|
+
resp = await executeChat([
|
|
40128
|
+
{ role: "system", content: system },
|
|
40129
|
+
{ role: "user", content: user }
|
|
40130
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
40131
|
+
} finally {
|
|
40132
|
+
if (startedLocalSpinner && spin) {
|
|
40133
|
+
try {
|
|
40134
|
+
spin.stop();
|
|
40135
|
+
} catch {
|
|
40136
|
+
}
|
|
40137
|
+
}
|
|
40037
40138
|
}
|
|
40038
40139
|
const raw = (resp?.output || "").trim();
|
|
40039
40140
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
@@ -40087,12 +40188,25 @@ function trackCodeFallback(event) {
|
|
|
40087
40188
|
}
|
|
40088
40189
|
}
|
|
40089
40190
|
async function orchestrate(request, opts) {
|
|
40191
|
+
const dbg = (...a) => {
|
|
40192
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
40193
|
+
try {
|
|
40194
|
+
console.log("[DEBUG/orchestrator]", ...a);
|
|
40195
|
+
} catch {
|
|
40196
|
+
}
|
|
40197
|
+
}
|
|
40198
|
+
};
|
|
40090
40199
|
const profile = await scanRepo(opts.root);
|
|
40200
|
+
dbg("start", { root: opts.root, flags: {
|
|
40201
|
+
...opts.flags
|
|
40202
|
+
/* redact */
|
|
40203
|
+
}, attachedFiles: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0 });
|
|
40091
40204
|
const initial = [];
|
|
40092
40205
|
const fallbackNotices = [];
|
|
40093
40206
|
const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
|
|
40094
40207
|
const explicitFilesRaw = parseExplicitFilenames(request);
|
|
40095
40208
|
const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
|
|
40209
|
+
dbg("explicitFiles", { raw: explicitFilesRaw, resolved: explicitFiles });
|
|
40096
40210
|
const explicitAbsMap = /* @__PURE__ */ Object.create(null);
|
|
40097
40211
|
if (explicitFiles.length > 0) {
|
|
40098
40212
|
const pathMod = await import('path');
|
|
@@ -40104,12 +40218,14 @@ async function orchestrate(request, opts) {
|
|
|
40104
40218
|
explicitFiles,
|
|
40105
40219
|
attachmentsCount: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0
|
|
40106
40220
|
});
|
|
40221
|
+
dbg("intent", { isEditIntent });
|
|
40107
40222
|
let editTargets = explicitFiles;
|
|
40108
40223
|
if (isEditIntent && editTargets.length === 0) {
|
|
40109
40224
|
try {
|
|
40110
40225
|
const repoFiles = await getRepoFiles(opts.root);
|
|
40111
40226
|
const llmTargets = await llmSelectEditTargets(opts.root, request, repoFiles);
|
|
40112
40227
|
editTargets = llmTargets;
|
|
40228
|
+
dbg("llmSelectEditTargets", { editTargets });
|
|
40113
40229
|
} catch {
|
|
40114
40230
|
}
|
|
40115
40231
|
}
|
|
@@ -40121,6 +40237,7 @@ async function orchestrate(request, opts) {
|
|
|
40121
40237
|
maxAttachments: opts.flags.maxAttachments || 50,
|
|
40122
40238
|
allowDotfiles: !!opts.flags.allowDotfiles
|
|
40123
40239
|
});
|
|
40240
|
+
dbg("attachment.map", { mappedCount: mapRes.mapped.length, warnings: mapRes.warnings });
|
|
40124
40241
|
mapRes.warnings.slice();
|
|
40125
40242
|
for (const m2 of mapRes.mapped) {
|
|
40126
40243
|
initial.push({
|
|
@@ -40132,7 +40249,7 @@ async function orchestrate(request, opts) {
|
|
|
40132
40249
|
});
|
|
40133
40250
|
}
|
|
40134
40251
|
}
|
|
40135
|
-
const onlyAttached = !!opts.flags.onlyAttached;
|
|
40252
|
+
const onlyAttached = !!(opts.flags.onlyAttached && Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0);
|
|
40136
40253
|
if (!onlyAttached) {
|
|
40137
40254
|
let codeOutput = "";
|
|
40138
40255
|
if (process.env.MARIA_E2E_FAKE_CODE === "1") {
|
|
@@ -40152,10 +40269,37 @@ async function orchestrate(request, opts) {
|
|
|
40152
40269
|
"[BEGIN file: path]\n<content>\n[END]",
|
|
40153
40270
|
"Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
|
|
40154
40271
|
].join("\n");
|
|
40272
|
+
let targetFilesAbs = [];
|
|
40273
|
+
try {
|
|
40274
|
+
const pathMod = await import('path');
|
|
40275
|
+
const fromExplicit = Array.isArray(explicitFiles) && explicitFiles.length > 0 ? explicitFiles.map((rel) => explicitAbsMap[rel] || pathMod.join(opts.root, rel)) : [];
|
|
40276
|
+
const fromEditTargets = Array.isArray(editTargets) && editTargets.length > 0 ? editTargets.map((rel) => pathMod.isAbsolute(rel) ? rel : pathMod.join(opts.root, rel)) : [];
|
|
40277
|
+
const seen = /* @__PURE__ */ new Set();
|
|
40278
|
+
for (const p of [...fromExplicit, ...fromEditTargets]) {
|
|
40279
|
+
const norm = (p || "").replace(/\\/g, "/");
|
|
40280
|
+
if (!norm) continue;
|
|
40281
|
+
if (seen.has(norm)) continue;
|
|
40282
|
+
seen.add(norm);
|
|
40283
|
+
targetFilesAbs.push(norm);
|
|
40284
|
+
}
|
|
40285
|
+
} catch {
|
|
40286
|
+
}
|
|
40287
|
+
const targetDirsAbs = Array.from(new Set(targetFilesAbs.map((p) => p.split("/").slice(0, -1).join("/")).filter(Boolean)));
|
|
40288
|
+
const targetFilesSection = targetFilesAbs.length > 0 ? ["// TARGET FILES (absolute):", ...targetFilesAbs.map((p) => `// - ${p}`)].join("\n") : "";
|
|
40289
|
+
const targetDirsSection = targetDirsAbs.length > 0 ? ["// TARGET DIRECTORIES (absolute):", ...targetDirsAbs.map((p) => `// - ${p}`)].join("\n") : "";
|
|
40155
40290
|
const requestPreamble = isEditIntent ? [
|
|
40156
|
-
"// EDIT MODE:
|
|
40157
|
-
"//
|
|
40158
|
-
|
|
40291
|
+
"// EDIT MODE RULES:",
|
|
40292
|
+
"// 1) Read the entire target file(s) BEFORE making changes. Assume omitted lines must remain exactly as-is.",
|
|
40293
|
+
"// 2) Preserve unrelated content and formatting (indentation, EOLs, imports order, license headers).",
|
|
40294
|
+
"// 3) Do NOT rename, move, or delete files unless explicitly requested.",
|
|
40295
|
+
"// 4) Apply the MINIMAL necessary change to achieve the request. Avoid broad refactors.",
|
|
40296
|
+
"// 5) When returning a whole file, keep everything identical except for the exact lines you changed.",
|
|
40297
|
+
"// 6) Do NOT introduce unrelated edits or code style churn.",
|
|
40298
|
+
"// 7) Edit ONLY the files listed under TARGET FILES or inside TARGET DIRECTORIES unless explicitly instructed otherwise.",
|
|
40299
|
+
"// 8) Do NOT create or scaffold new projects or files outside these targets (no package.json, no CRA/Vite scaffolds, etc.) unless such files already exist and are being modified.",
|
|
40300
|
+
editContext ? "// Current file snapshots provided below." : "",
|
|
40301
|
+
targetFilesSection,
|
|
40302
|
+
targetDirsSection
|
|
40159
40303
|
].filter(Boolean).join("\n") : "";
|
|
40160
40304
|
const enriched = `${FILE_FORMAT_INSTRUCTIONS}
|
|
40161
40305
|
|
|
@@ -40163,6 +40307,7 @@ ${requestPreamble}
|
|
|
40163
40307
|
${request}
|
|
40164
40308
|
|
|
40165
40309
|
${editContext}`;
|
|
40310
|
+
dbg("executeCode.prompt.head", enriched.slice(0, 1400));
|
|
40166
40311
|
const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
|
|
40167
40312
|
name: f3.originalName,
|
|
40168
40313
|
path: f3.pathHint,
|
|
@@ -40196,6 +40341,68 @@ ${editContext}`;
|
|
|
40196
40341
|
} catch {
|
|
40197
40342
|
}
|
|
40198
40343
|
}
|
|
40344
|
+
try {
|
|
40345
|
+
const fs52 = await import('fs/promises');
|
|
40346
|
+
const pathMod = await import('path');
|
|
40347
|
+
const dirCandidates = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
40348
|
+
const maxFilesPerDir = 80;
|
|
40349
|
+
for (const raw2 of dirCandidates) {
|
|
40350
|
+
try {
|
|
40351
|
+
const normalized2 = raw2.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
40352
|
+
const abs = pathMod.isAbsolute(normalized2) ? normalized2 : pathMod.join(opts.root, normalized2);
|
|
40353
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
40354
|
+
if (!st || !st.isDirectory()) continue;
|
|
40355
|
+
const collected = [];
|
|
40356
|
+
const walk2 = async (d) => {
|
|
40357
|
+
if (collected.length >= maxFilesPerDir) return;
|
|
40358
|
+
let entries = [];
|
|
40359
|
+
try {
|
|
40360
|
+
entries = await fs52.readdir(d, { withFileTypes: true });
|
|
40361
|
+
} catch {
|
|
40362
|
+
return;
|
|
40363
|
+
}
|
|
40364
|
+
for (const e2 of entries) {
|
|
40365
|
+
const name2 = e2.name;
|
|
40366
|
+
if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === "build" || name2 === ".maria") continue;
|
|
40367
|
+
const full = pathMod.join(d, name2);
|
|
40368
|
+
if (e2.isDirectory()) {
|
|
40369
|
+
await walk2(full);
|
|
40370
|
+
if (collected.length >= maxFilesPerDir) break;
|
|
40371
|
+
continue;
|
|
40372
|
+
}
|
|
40373
|
+
collected.push(full);
|
|
40374
|
+
if (collected.length >= maxFilesPerDir) break;
|
|
40375
|
+
}
|
|
40376
|
+
};
|
|
40377
|
+
await walk2(abs);
|
|
40378
|
+
for (const f3 of collected) {
|
|
40379
|
+
try {
|
|
40380
|
+
const key = f3.toLowerCase();
|
|
40381
|
+
if (attachedPathSet.has(key)) continue;
|
|
40382
|
+
const buf = await fs52.readFile(f3);
|
|
40383
|
+
const head2 = buf.subarray(0, Math.min(buf.length, 4096));
|
|
40384
|
+
let binaryLike = false;
|
|
40385
|
+
for (let i2 = 0; i2 < head2.length; i2++) {
|
|
40386
|
+
if (head2[i2] === 0) {
|
|
40387
|
+
binaryLike = true;
|
|
40388
|
+
break;
|
|
40389
|
+
}
|
|
40390
|
+
}
|
|
40391
|
+
if (binaryLike) continue;
|
|
40392
|
+
const sample = buf.subarray(0, Math.min(buf.length, 8192)).toString("utf8");
|
|
40393
|
+
const printable = sample.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
40394
|
+
const ratio = sample.length === 0 ? 0 : printable.length / sample.length;
|
|
40395
|
+
if (ratio < 0.6 && sample.length > 0) continue;
|
|
40396
|
+
pathAttachments.push({ name: pathMod.basename(f3), path: f3, mime: "text/plain", data_base64: buf.toString("base64") });
|
|
40397
|
+
attachedPathSet.add(key);
|
|
40398
|
+
} catch {
|
|
40399
|
+
}
|
|
40400
|
+
}
|
|
40401
|
+
} catch {
|
|
40402
|
+
}
|
|
40403
|
+
}
|
|
40404
|
+
} catch {
|
|
40405
|
+
}
|
|
40199
40406
|
if (isEditIntent && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
40200
40407
|
try {
|
|
40201
40408
|
const fs52 = await import('fs/promises');
|
|
@@ -40250,9 +40457,34 @@ ${editContext}`;
|
|
|
40250
40457
|
hydratedCtx.push(...ctxAttachments);
|
|
40251
40458
|
}
|
|
40252
40459
|
}
|
|
40253
|
-
const
|
|
40460
|
+
const pathMod2 = await import('path');
|
|
40461
|
+
const normalizeMime = (p, m2) => {
|
|
40462
|
+
if (!p) return m2 || "text/plain";
|
|
40463
|
+
const ext2 = pathMod2.extname(p).toLowerCase();
|
|
40464
|
+
if (m2 && m2 !== "application/octet-stream") return m2;
|
|
40465
|
+
if (ext2 === ".pdf") return "application/pdf";
|
|
40466
|
+
if (ext2 === ".png") return "image/png";
|
|
40467
|
+
if (ext2 === ".jpg" || ext2 === ".jpeg") return "image/jpeg";
|
|
40468
|
+
if (ext2 === ".webp") return "image/webp";
|
|
40469
|
+
if (ext2 === ".gif") return "image/gif";
|
|
40470
|
+
if (ext2 === ".bmp") return "image/bmp";
|
|
40471
|
+
if (ext2 === ".svg") return "image/svg+xml";
|
|
40472
|
+
if (ext2 === ".tif" || ext2 === ".tiff") return "image/tiff";
|
|
40473
|
+
if (ext2 === ".heic") return "image/heic";
|
|
40474
|
+
if (ext2 === ".heif") return "image/heif";
|
|
40475
|
+
return "text/plain";
|
|
40476
|
+
};
|
|
40477
|
+
const allAttachments = (hydratedCtx.length ? hydratedCtx : ctxAttachments).concat(pathAttachments).map((a) => ({
|
|
40478
|
+
...a,
|
|
40479
|
+
mime: normalizeMime(a.path, a.mime)
|
|
40480
|
+
}));
|
|
40254
40481
|
const response = await executeCode(allAttachments.length > 0 ? { prompt: enriched, provider: "google", model: "gemini-2.5-flash", attachments: allAttachments } : enriched);
|
|
40482
|
+
try {
|
|
40483
|
+
dbg("executeCode.attachments.meta", { ctx: (hydratedCtx.length ? hydratedCtx : ctxAttachments).length, path: pathAttachments.length });
|
|
40484
|
+
} catch {
|
|
40485
|
+
}
|
|
40255
40486
|
const raw = (response.output || response?.data?.content || "").trim();
|
|
40487
|
+
dbg("executeCode.output.head", raw.slice(0, 1200));
|
|
40256
40488
|
if (!raw) {
|
|
40257
40489
|
return {
|
|
40258
40490
|
ok: false,
|
|
@@ -40290,6 +40522,7 @@ ${editContext}`;
|
|
|
40290
40522
|
codeOutput = outcome.data?.output || "";
|
|
40291
40523
|
}
|
|
40292
40524
|
const blocks = extractBlocks(codeOutput);
|
|
40525
|
+
dbg("extractBlocks.count", blocks.length);
|
|
40293
40526
|
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
40294
40527
|
const mapped = /* @__PURE__ */ new Set();
|
|
40295
40528
|
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
@@ -40327,23 +40560,49 @@ ${editContext}`;
|
|
|
40327
40560
|
} else {
|
|
40328
40561
|
try {
|
|
40329
40562
|
const repoFiles = await getRepoFiles(opts.root);
|
|
40330
|
-
|
|
40563
|
+
let dirHints = [];
|
|
40564
|
+
try {
|
|
40565
|
+
const fs52 = await import('fs/promises');
|
|
40566
|
+
const pathMod = await import('path');
|
|
40567
|
+
const rawDirs = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
40568
|
+
for (const raw of rawDirs) {
|
|
40569
|
+
try {
|
|
40570
|
+
const normalized2 = raw.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
40571
|
+
const abs = pathMod.isAbsolute(normalized2) ? normalized2 : pathMod.join(opts.root, normalized2);
|
|
40572
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
40573
|
+
if (!st || !st.isDirectory()) continue;
|
|
40574
|
+
const rel = pathMod.relative(opts.root, abs).replace(/\\/g, "/").replace(/^\/+/, "");
|
|
40575
|
+
if (!rel || rel.startsWith("..")) continue;
|
|
40576
|
+
dirHints.push(rel);
|
|
40577
|
+
} catch {
|
|
40578
|
+
}
|
|
40579
|
+
}
|
|
40580
|
+
if (dirHints.length === 0 && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
40581
|
+
dirHints = Array.from(new Set(editTargets.map((p) => (p || "").replace(/^\/+/, "").split("/").slice(0, -1).join("/")).filter(Boolean)));
|
|
40582
|
+
}
|
|
40583
|
+
} catch {
|
|
40584
|
+
}
|
|
40585
|
+
const decisions = await llmMapBlocksBatch(opts.root, request, blocks, repoFiles, { dirHints });
|
|
40586
|
+
dbg("llmMapBlocksBatch.decisions", decisions);
|
|
40331
40587
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
40332
40588
|
const b = blocks[i2];
|
|
40333
40589
|
const d = decisions[i2] || { action: "create", path: suggestName2(request, b.language, i2) };
|
|
40334
|
-
|
|
40590
|
+
const hinted = b.filename && String(b.filename).trim() || extractFilenameHintFromComment(b.code);
|
|
40591
|
+
const finalPath = hinted && hinted.trim() || d.path;
|
|
40592
|
+
if (d.action === "modify" && repoFiles.includes(finalPath)) {
|
|
40335
40593
|
const lang = languageFromExt(d.path.replace(/^.*(\.[a-z0-9]+)$/i, "$1"));
|
|
40336
|
-
initial.push({ path:
|
|
40594
|
+
initial.push({ path: finalPath, kind: "source", action: "modify", description: "Modify existing file", language: lang, preview: b.code, noNormalize: true });
|
|
40337
40595
|
} else {
|
|
40338
|
-
const pth = d.path || suggestName2(request, b.language, i2);
|
|
40339
|
-
initial.push({ path: pth, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code });
|
|
40596
|
+
const pth = finalPath && finalPath.trim() || d.path || suggestName2(request, b.language, i2);
|
|
40597
|
+
initial.push({ path: pth, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code, noNormalize: true });
|
|
40340
40598
|
}
|
|
40341
40599
|
}
|
|
40342
40600
|
} catch {
|
|
40343
40601
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
40344
40602
|
const b = blocks[i2];
|
|
40345
|
-
const
|
|
40346
|
-
|
|
40603
|
+
const hinted = b.filename && String(b.filename).trim() || extractFilenameHintFromComment(b.code);
|
|
40604
|
+
const path65 = hinted && hinted.trim() || suggestName2(request, b.language, i2);
|
|
40605
|
+
initial.push({ path: path65, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code, noNormalize: true });
|
|
40347
40606
|
}
|
|
40348
40607
|
}
|
|
40349
40608
|
}
|
|
@@ -40359,13 +40618,13 @@ ${editContext}`;
|
|
|
40359
40618
|
}
|
|
40360
40619
|
}
|
|
40361
40620
|
}
|
|
40362
|
-
if (explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
40621
|
+
if (!isEditIntent && explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
40363
40622
|
for (const f3 of explicitFiles) {
|
|
40364
40623
|
initial.push(scaffoldForFilename(f3, explicitFiles));
|
|
40365
40624
|
}
|
|
40366
40625
|
}
|
|
40367
40626
|
const normalized = await normalizePlans(
|
|
40368
|
-
initial.map((p) => p.noNormalize ? p : p),
|
|
40627
|
+
initial.map((p) => p.noNormalize ? { ...p } : p),
|
|
40369
40628
|
{ root: opts.root }
|
|
40370
40629
|
);
|
|
40371
40630
|
try {
|
|
@@ -40390,11 +40649,26 @@ ${editContext}`;
|
|
|
40390
40649
|
}
|
|
40391
40650
|
} catch {
|
|
40392
40651
|
}
|
|
40393
|
-
|
|
40652
|
+
let filtered = normalized;
|
|
40653
|
+
if (isEditIntent) {
|
|
40654
|
+
const keepCreates = !!opts.flags.onlyAttached;
|
|
40655
|
+
if (!keepCreates) {
|
|
40656
|
+
filtered = normalized.map((f3) => f3.action === "create" ? { ...f3, action: "skip" } : f3);
|
|
40657
|
+
}
|
|
40658
|
+
}
|
|
40659
|
+
const baseFlags = { ...opts.flags };
|
|
40660
|
+
const effectiveFlags = {
|
|
40661
|
+
...baseFlags,
|
|
40662
|
+
maxFiles: opts.flags.maxFiles,
|
|
40663
|
+
interactive: !!opts.flags.interactive,
|
|
40664
|
+
// Force yes when editing; if baseFlags.yes is already true, keep it true
|
|
40665
|
+
yes: baseFlags?.yes === true || isEditIntent
|
|
40666
|
+
};
|
|
40667
|
+
const validated = await validatePlan(filtered, { root: opts.root, profile, flags: effectiveFlags });
|
|
40394
40668
|
const hasAnyModify = validated.files.some((f3) => f3.action === "modify") || isEditIntent;
|
|
40395
40669
|
const outputMode = !opts.flags.hideCode && hasAnyModify ? "diff" : resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
|
|
40396
40670
|
const skippedSetForLookup = new Set(validated.skipped || []);
|
|
40397
|
-
const skippedPlans =
|
|
40671
|
+
const skippedPlans = filtered.filter((f3) => skippedSetForLookup.has(f3.path));
|
|
40398
40672
|
const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
|
|
40399
40673
|
const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
|
|
40400
40674
|
const summary = summarizePlan(displayFiles);
|
|
@@ -40587,6 +40861,21 @@ function extractBlocks(content) {
|
|
|
40587
40861
|
if (blocks.length === 0 && looksLikeCode(content)) blocks.push({ language: detectLanguage(content), code: content.trim() });
|
|
40588
40862
|
return blocks;
|
|
40589
40863
|
}
|
|
40864
|
+
function extractFilenameHintFromComment(code) {
|
|
40865
|
+
try {
|
|
40866
|
+
const first = (code.split(/\r?\n/, 1)[0] || "").trim();
|
|
40867
|
+
let m2 = first.match(/^\/\/\s*filename:\s*(.+)$/i);
|
|
40868
|
+
if (m2?.[1]) return m2[1].trim();
|
|
40869
|
+
m2 = first.match(/^#\s*filename:\s*(.+)$/i);
|
|
40870
|
+
if (m2?.[1]) return m2[1].trim();
|
|
40871
|
+
m2 = first.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i);
|
|
40872
|
+
if (m2?.[1]) return m2[1].trim();
|
|
40873
|
+
m2 = first.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
|
|
40874
|
+
if (m2?.[1]) return m2[1].trim();
|
|
40875
|
+
} catch {
|
|
40876
|
+
}
|
|
40877
|
+
return void 0;
|
|
40878
|
+
}
|
|
40590
40879
|
function looksLikeCode(s2) {
|
|
40591
40880
|
return ["function ", "const ", "let ", "var ", "class ", "def ", "import ", "export "].some((k) => s2.includes(k));
|
|
40592
40881
|
}
|
|
@@ -40744,48 +41033,100 @@ function parseExplicitFilenames(request) {
|
|
|
40744
41033
|
return out;
|
|
40745
41034
|
}
|
|
40746
41035
|
async function detectEditIntentLLM(root, request, ctx2) {
|
|
41036
|
+
let existingDirs = [];
|
|
41037
|
+
let existingFiles = [];
|
|
41038
|
+
let anyExistingPathMentioned = false;
|
|
40747
41039
|
try {
|
|
41040
|
+
const fs52 = await import('fs/promises');
|
|
41041
|
+
const pathMod = await import('path');
|
|
41042
|
+
const rawPaths = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
41043
|
+
existingDirs = [];
|
|
41044
|
+
existingFiles = [];
|
|
41045
|
+
for (const raw2 of rawPaths) {
|
|
41046
|
+
try {
|
|
41047
|
+
const normalized = raw2.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
41048
|
+
const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(root, normalized);
|
|
41049
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
41050
|
+
if (!st) continue;
|
|
41051
|
+
anyExistingPathMentioned = true;
|
|
41052
|
+
const rel = pathMod.relative(root, abs).replace(/\\/g, "/");
|
|
41053
|
+
if (!rel || rel.startsWith("..")) continue;
|
|
41054
|
+
if (st.isDirectory()) existingDirs.push(rel);
|
|
41055
|
+
else if (st.isFile()) existingFiles.push(rel);
|
|
41056
|
+
} catch {
|
|
41057
|
+
}
|
|
41058
|
+
}
|
|
40748
41059
|
const repoFiles = await getRepoFiles(root);
|
|
40749
|
-
|
|
41060
|
+
let scope = [];
|
|
41061
|
+
if (existingDirs.length > 0) {
|
|
41062
|
+
const dirSet = existingDirs.map((d) => d.replace(/\\/g, "/").replace(/^\/+/, "").toLowerCase());
|
|
41063
|
+
scope = repoFiles.filter((p) => dirSet.some((d) => p.toLowerCase().startsWith(d + "/")));
|
|
41064
|
+
} else {
|
|
41065
|
+
scope = repoFiles;
|
|
41066
|
+
}
|
|
40750
41067
|
const headSnippets = [];
|
|
40751
|
-
for (const p of
|
|
41068
|
+
for (const p of scope) {
|
|
40752
41069
|
const h2 = await readHeadTail(root, p, 5);
|
|
40753
41070
|
headSnippets.push(`- ${p}
|
|
40754
41071
|
${h2.head}`);
|
|
40755
41072
|
}
|
|
40756
41073
|
const system = [
|
|
40757
|
-
"
|
|
40758
|
-
"
|
|
40759
|
-
"
|
|
40760
|
-
"
|
|
40761
|
-
"
|
|
40762
|
-
"
|
|
40763
|
-
"
|
|
40764
|
-
'Return JSON: { "intent": "EDIT_EXISTING" | "CREATE_NEW" }
|
|
41074
|
+
"You classify the intent for a code operation in an existing repository.",
|
|
41075
|
+
"Choose strictly one: EDIT_EXISTING (modify existing files) or CREATE_NEW (generate a new project/files).",
|
|
41076
|
+
"Decision rules (apply in order):",
|
|
41077
|
+
"1) If the request references existing repo directory/file paths and does NOT explicitly say to create a new project/template/scaffold, prefer EDIT_EXISTING.",
|
|
41078
|
+
"2) Wording like fix/improve/update/change/patch/make it work/enable X implies EDIT_EXISTING.",
|
|
41079
|
+
"3) Wording like create/new project/scaffold/from scratch/template implies CREATE_NEW.",
|
|
41080
|
+
"4) If attachments or explicit file paths are present, that increases likelihood of EDIT_EXISTING.",
|
|
41081
|
+
'Return ONLY compact JSON: { "intent": "EDIT_EXISTING" | "CREATE_NEW" }.'
|
|
40765
41082
|
].join("\n");
|
|
41083
|
+
const evidence = {
|
|
41084
|
+
explicitFilesCount: (ctx2.explicitFiles || []).length,
|
|
41085
|
+
attachmentsCount: ctx2.attachmentsCount || 0,
|
|
41086
|
+
existingDirCount: existingDirs.length,
|
|
41087
|
+
existingFileMentions: existingFiles.length,
|
|
41088
|
+
existingDirs,
|
|
41089
|
+
existingFiles
|
|
41090
|
+
};
|
|
40766
41091
|
const user = [
|
|
40767
41092
|
`Request: ${request}`,
|
|
40768
|
-
`
|
|
40769
|
-
|
|
40770
|
-
"Repo snapshot (paths with file heads):",
|
|
41093
|
+
`Evidence: ${JSON.stringify(evidence)}`,
|
|
41094
|
+
"Repo snapshot (trimmed):",
|
|
40771
41095
|
headSnippets.join("\n\n")
|
|
40772
41096
|
].join("\n\n");
|
|
40773
|
-
|
|
40774
|
-
|
|
40775
|
-
|
|
40776
|
-
|
|
40777
|
-
|
|
40778
|
-
|
|
41097
|
+
if (existingDirs.length > 0 || existingFiles.length > 0 || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0) {
|
|
41098
|
+
return true;
|
|
41099
|
+
}
|
|
41100
|
+
let startedLocalSpinner = false;
|
|
41101
|
+
let spin1 = null;
|
|
41102
|
+
if (!ProcessAnimation.hasActive()) {
|
|
41103
|
+
spin1 = new ProcessAnimation();
|
|
41104
|
+
spin1.start();
|
|
41105
|
+
startedLocalSpinner = true;
|
|
41106
|
+
}
|
|
41107
|
+
let resp;
|
|
40779
41108
|
try {
|
|
40780
|
-
|
|
40781
|
-
|
|
41109
|
+
resp = await executeChat([
|
|
41110
|
+
{ role: "system", content: system },
|
|
41111
|
+
{ role: "user", content: user }
|
|
41112
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
41113
|
+
} finally {
|
|
41114
|
+
if (startedLocalSpinner && spin1) {
|
|
41115
|
+
try {
|
|
41116
|
+
spin1.stop();
|
|
41117
|
+
} catch {
|
|
41118
|
+
}
|
|
41119
|
+
}
|
|
40782
41120
|
}
|
|
40783
41121
|
const raw = (resp?.output || "").trim();
|
|
40784
41122
|
const jsonText = extractJsonSafe(raw, "object") || raw;
|
|
40785
41123
|
const parsed = JSON.parse(jsonText);
|
|
41124
|
+
if (existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0) {
|
|
41125
|
+
return true;
|
|
41126
|
+
}
|
|
40786
41127
|
return parsed?.intent === "EDIT_EXISTING";
|
|
40787
41128
|
} catch {
|
|
40788
|
-
return ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0;
|
|
41129
|
+
return ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0 || existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned;
|
|
40789
41130
|
}
|
|
40790
41131
|
}
|
|
40791
41132
|
function sanitizeFolderName(name2) {
|
|
@@ -40953,7 +41294,7 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
40953
41294
|
const chat = await executeChat([
|
|
40954
41295
|
{ role: "system", content: system },
|
|
40955
41296
|
{ role: "user", content: user }
|
|
40956
|
-
]);
|
|
41297
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
40957
41298
|
const raw = (chat.output || "").trim();
|
|
40958
41299
|
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
40959
41300
|
return pick.replace(/^\/+/, "");
|
|
@@ -41128,7 +41469,16 @@ var init_code_command = __esm({
|
|
|
41128
41469
|
}
|
|
41129
41470
|
];
|
|
41130
41471
|
async execute(commandArgs, context2) {
|
|
41472
|
+
const debug = (...args2) => {
|
|
41473
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
41474
|
+
try {
|
|
41475
|
+
console.log("[DEBUG/code]", ...args2);
|
|
41476
|
+
} catch {
|
|
41477
|
+
}
|
|
41478
|
+
}
|
|
41479
|
+
};
|
|
41131
41480
|
const request = await this.ensureLanguageDefaults(commandArgs.raw.join(" ").trim());
|
|
41481
|
+
debug("request", request);
|
|
41132
41482
|
if (!request) {
|
|
41133
41483
|
return this.error("Please provide a code request \xB7 Example: /code create button component\nTip: Use --plan-only to safely review the plan, or --output detail to preview snippet heads.");
|
|
41134
41484
|
}
|
|
@@ -41140,6 +41490,7 @@ var init_code_command = __esm({
|
|
|
41140
41490
|
const explicitDry = commandArgs.raw.includes("--dry-run");
|
|
41141
41491
|
const explicitOutput = commandArgs.raw.some((x2) => x2.startsWith("--output") || x2 === "--verbose" || x2 === "-v");
|
|
41142
41492
|
const explicitPreview = commandArgs.raw.some((x2) => x2.startsWith("--preview-lines"));
|
|
41493
|
+
const explicitOnlyAttached = commandArgs.raw.includes("--only-attached");
|
|
41143
41494
|
const preSpin = new ProcessAnimation();
|
|
41144
41495
|
preSpin.start();
|
|
41145
41496
|
let inferred = {};
|
|
@@ -41151,6 +41502,8 @@ var init_code_command = __esm({
|
|
|
41151
41502
|
} catch {
|
|
41152
41503
|
}
|
|
41153
41504
|
}
|
|
41505
|
+
debug("inferCodeArgs.raw", rawText);
|
|
41506
|
+
debug("inferCodeArgs.result", inferred);
|
|
41154
41507
|
if (!explicitPlan && !explicitDry) {
|
|
41155
41508
|
if (typeof inferred.planOnly === "boolean") opts.planOnly = inferred.planOnly;
|
|
41156
41509
|
if (typeof inferred.dryRun === "boolean") opts.dryRun = inferred.dryRun;
|
|
@@ -41161,6 +41514,9 @@ var init_code_command = __esm({
|
|
|
41161
41514
|
if (!explicitPreview && typeof inferred.previewLines === "number") {
|
|
41162
41515
|
opts.previewLines = inferred.previewLines;
|
|
41163
41516
|
}
|
|
41517
|
+
if (!explicitOnlyAttached && typeof inferred.onlyAttached === "boolean") {
|
|
41518
|
+
opts.onlyAttached = inferred.onlyAttached;
|
|
41519
|
+
}
|
|
41164
41520
|
} catch {
|
|
41165
41521
|
}
|
|
41166
41522
|
if (opts.planOnly) {
|
|
@@ -41175,13 +41531,27 @@ var init_code_command = __esm({
|
|
|
41175
41531
|
const root = opts.root || process.cwd();
|
|
41176
41532
|
const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
|
|
41177
41533
|
const attachments = await this.collectAttachedFiles(context2).catch(() => []);
|
|
41534
|
+
try {
|
|
41535
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
41536
|
+
const attView = attachments.map((a) => ({ name: a.originalName, size: a.size, mime: a.mime, pathHint: a.pathHint })).slice(0, 50);
|
|
41537
|
+
console.log("[DEBUG/code] collected.attachments", { count: attachments.length, attachments: attView });
|
|
41538
|
+
}
|
|
41539
|
+
} catch {
|
|
41540
|
+
}
|
|
41178
41541
|
const abort = new AbortController();
|
|
41179
41542
|
const onSigint = () => abort.abort();
|
|
41180
41543
|
process.once("SIGINT", onSigint);
|
|
41181
|
-
|
|
41182
|
-
spinner
|
|
41544
|
+
let startedLocalSpinner = false;
|
|
41545
|
+
let spinner = null;
|
|
41546
|
+
if (!ProcessAnimation.hasActive()) {
|
|
41547
|
+
spinner = new ProcessAnimation();
|
|
41548
|
+
spinner.start();
|
|
41549
|
+
startedLocalSpinner = true;
|
|
41550
|
+
}
|
|
41183
41551
|
try {
|
|
41184
|
-
const
|
|
41552
|
+
const effectiveOnlyAttached = opts.onlyAttached && attachments.length > 0;
|
|
41553
|
+
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: effectiveOnlyAttached, 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 });
|
|
41554
|
+
debug("orchestrate.summaryLines.head", Array.isArray(res?.summaryLines) ? res.summaryLines.slice(0, 10) : []);
|
|
41185
41555
|
if (opts.planOnly) {
|
|
41186
41556
|
const fs52 = await import('fs/promises');
|
|
41187
41557
|
const path65 = await import('path');
|
|
@@ -41234,9 +41604,11 @@ var init_code_command = __esm({
|
|
|
41234
41604
|
const out = Array.isArray(res?.summaryLines) ? res.summaryLines.join("\n") : "";
|
|
41235
41605
|
return this.success(out);
|
|
41236
41606
|
} finally {
|
|
41237
|
-
|
|
41238
|
-
|
|
41239
|
-
|
|
41607
|
+
if (startedLocalSpinner && spinner) {
|
|
41608
|
+
try {
|
|
41609
|
+
spinner.stop();
|
|
41610
|
+
} catch {
|
|
41611
|
+
}
|
|
41240
41612
|
}
|
|
41241
41613
|
process.removeListener("SIGINT", onSigint);
|
|
41242
41614
|
}
|
|
@@ -41359,12 +41731,6 @@ ${pretty}`);
|
|
|
41359
41731
|
if (llmLang) {
|
|
41360
41732
|
const hint2 = (() => {
|
|
41361
41733
|
const l = llmLang.toLowerCase();
|
|
41362
|
-
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
41363
|
-
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
41364
|
-
if (l === "typescript") return "TypeScript";
|
|
41365
|
-
if (l === "javascript") return "JavaScript";
|
|
41366
|
-
if (l === "html") return "HTML";
|
|
41367
|
-
if (l === "css") return "CSS";
|
|
41368
41734
|
return llmLang;
|
|
41369
41735
|
})();
|
|
41370
41736
|
return raw + ` (Use ${hint2})`;
|
|
@@ -41377,7 +41743,7 @@ ${pretty}`);
|
|
|
41377
41743
|
preSpin.start();
|
|
41378
41744
|
const system = [
|
|
41379
41745
|
"You analyze a user's code-generation request.",
|
|
41380
|
-
"Decide if the user explicitly specified a programming language or framework/tooling
|
|
41746
|
+
"Decide if the user explicitly specified a programming language or framework/tooling.",
|
|
41381
41747
|
'Return ONLY compact JSON with shape {"explicitLanguage": boolean, "language"?: string}.',
|
|
41382
41748
|
"Do not add any commentary."
|
|
41383
41749
|
].join("\n");
|
|
@@ -41386,7 +41752,7 @@ ${pretty}`);
|
|
|
41386
41752
|
method: "POST",
|
|
41387
41753
|
body: {
|
|
41388
41754
|
provider: "google",
|
|
41389
|
-
model: "gemini-2.5-flash",
|
|
41755
|
+
model: "gemini-2.5-flash-lite",
|
|
41390
41756
|
taskType: "chat",
|
|
41391
41757
|
prompt: `${system}
|
|
41392
41758
|
|
|
@@ -41431,6 +41797,14 @@ ${user}`
|
|
|
41431
41797
|
if (parsed && parsed.explicitLanguage) return raw;
|
|
41432
41798
|
} catch {
|
|
41433
41799
|
}
|
|
41800
|
+
try {
|
|
41801
|
+
const pathMod = await import('path');
|
|
41802
|
+
const hasPathToken = /[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/.test(raw);
|
|
41803
|
+
if (hasPathToken) {
|
|
41804
|
+
return raw;
|
|
41805
|
+
}
|
|
41806
|
+
} catch {
|
|
41807
|
+
}
|
|
41434
41808
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
41435
41809
|
return raw + hint;
|
|
41436
41810
|
}
|
|
@@ -41440,9 +41814,7 @@ ${user}`
|
|
|
41440
41814
|
const system = [
|
|
41441
41815
|
"You are a programming language classifier.",
|
|
41442
41816
|
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
41443
|
-
"Respond with ONLY
|
|
41444
|
-
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
41445
|
-
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
41817
|
+
"Respond with ONLY language name(s)"
|
|
41446
41818
|
].join("\n");
|
|
41447
41819
|
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
41448
41820
|
${s2}`).join("\n\n");
|
|
@@ -41451,7 +41823,7 @@ ${s2}`).join("\n\n");
|
|
|
41451
41823
|
method: "POST",
|
|
41452
41824
|
body: {
|
|
41453
41825
|
provider: "google",
|
|
41454
|
-
model: "gemini-2.5-flash",
|
|
41826
|
+
model: "gemini-2.5-flash-lite",
|
|
41455
41827
|
taskType: "chat",
|
|
41456
41828
|
prompt: `${system}
|
|
41457
41829
|
|
|
@@ -41757,64 +42129,6 @@ ${joined}`
|
|
|
41757
42129
|
return false;
|
|
41758
42130
|
}
|
|
41759
42131
|
}
|
|
41760
|
-
/**
|
|
41761
|
-
* Extract code blocks from AI response
|
|
41762
|
-
*/
|
|
41763
|
-
extractCodeBlocks(content) {
|
|
41764
|
-
const blocks = [];
|
|
41765
|
-
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
|
41766
|
-
let match2;
|
|
41767
|
-
while ((match2 = codeBlockRegex.exec(content)) !== null) {
|
|
41768
|
-
blocks.push({
|
|
41769
|
-
language: match2[1] || "javascript",
|
|
41770
|
-
code: match2[2].trim()
|
|
41771
|
-
});
|
|
41772
|
-
}
|
|
41773
|
-
if (blocks.length === 0 && this.looksLikeCode(content)) {
|
|
41774
|
-
blocks.push({
|
|
41775
|
-
code: content.trim(),
|
|
41776
|
-
language: this.detectLanguage(content)
|
|
41777
|
-
});
|
|
41778
|
-
}
|
|
41779
|
-
return blocks;
|
|
41780
|
-
}
|
|
41781
|
-
/**
|
|
41782
|
-
* Check if content looks like code
|
|
41783
|
-
*/
|
|
41784
|
-
looksLikeCode(content) {
|
|
41785
|
-
const codeIndicators = [
|
|
41786
|
-
"function ",
|
|
41787
|
-
"const ",
|
|
41788
|
-
"let ",
|
|
41789
|
-
"var ",
|
|
41790
|
-
"class ",
|
|
41791
|
-
"def ",
|
|
41792
|
-
"import ",
|
|
41793
|
-
"export ",
|
|
41794
|
-
"{",
|
|
41795
|
-
"}",
|
|
41796
|
-
";",
|
|
41797
|
-
"//",
|
|
41798
|
-
"/*"
|
|
41799
|
-
];
|
|
41800
|
-
return codeIndicators.some((indicator) => content.includes(indicator));
|
|
41801
|
-
}
|
|
41802
|
-
/**
|
|
41803
|
-
* Detect programming language from content
|
|
41804
|
-
*/
|
|
41805
|
-
detectLanguage(code) {
|
|
41806
|
-
const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
|
|
41807
|
-
const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
|
|
41808
|
-
const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
|
|
41809
|
-
if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
|
|
41810
|
-
if (code.includes("interface ") || code.includes(": string")) return "typescript";
|
|
41811
|
-
if (code.includes("def ") || code.includes("print(")) return "python";
|
|
41812
|
-
if (code.includes("func ") || code.includes("package main")) return "go";
|
|
41813
|
-
if (code.includes("fn ") || code.includes("let mut")) return "rust";
|
|
41814
|
-
if (code.includes("<?php")) return "php";
|
|
41815
|
-
if (code.includes("#include")) return "cpp";
|
|
41816
|
-
return "javascript";
|
|
41817
|
-
}
|
|
41818
42132
|
/**
|
|
41819
42133
|
* Save code block to file
|
|
41820
42134
|
*/
|
|
@@ -50506,11 +50820,10 @@ var init_responsive_width = __esm({
|
|
|
50506
50820
|
}
|
|
50507
50821
|
});
|
|
50508
50822
|
function createSpinner(text) {
|
|
50509
|
-
let frame = 0;
|
|
50510
50823
|
let active = false;
|
|
50511
|
-
let
|
|
50512
|
-
const
|
|
50513
|
-
const f3 = SPINNER_FRAMES[frame
|
|
50824
|
+
let frame = 0;
|
|
50825
|
+
const renderOnce = () => {
|
|
50826
|
+
const f3 = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
50514
50827
|
process6__namespace.default.stdout.write(`\r ${chalk40__default.default.cyan(f3)} ${text}`);
|
|
50515
50828
|
};
|
|
50516
50829
|
return {
|
|
@@ -50520,13 +50833,11 @@ function createSpinner(text) {
|
|
|
50520
50833
|
start() {
|
|
50521
50834
|
if (active) return;
|
|
50522
50835
|
active = true;
|
|
50523
|
-
|
|
50524
|
-
timer = setInterval(render, 80);
|
|
50836
|
+
renderOnce();
|
|
50525
50837
|
},
|
|
50526
50838
|
stop(symbol = "\u2714") {
|
|
50527
50839
|
if (!active) return;
|
|
50528
50840
|
active = false;
|
|
50529
|
-
if (timer) clearInterval(timer);
|
|
50530
50841
|
const finalSymbol = symbol === "\u2714" ? chalk40__default.default.green(symbol) : symbol === "\u26A0" ? chalk40__default.default.yellow(symbol) : symbol === "\u2716" ? chalk40__default.default.red(symbol) : symbol;
|
|
50531
50842
|
process6__namespace.default.stdout.write(`\r ${finalSymbol} ${text}
|
|
50532
50843
|
`);
|