@bonginkan/maria 4.3.45 → 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 +456 -148
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +456 -148
- 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",
|
|
@@ -26426,7 +26477,7 @@ var init_about_command = __esm({
|
|
|
26426
26477
|
async execute(args2, context2) {
|
|
26427
26478
|
const output3 = [];
|
|
26428
26479
|
output3.push("");
|
|
26429
|
-
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"));
|
|
26430
26481
|
output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
|
|
26431
26482
|
output3.push("");
|
|
26432
26483
|
output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -38916,9 +38967,10 @@ function extractFirstJson5(text) {
|
|
|
38916
38967
|
async function inferCodeArgs(rawText) {
|
|
38917
38968
|
const system = [
|
|
38918
38969
|
"You extract structured options for a code command.",
|
|
38919
|
-
'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 }.',
|
|
38920
38971
|
"Decide from the user text whether planOnly or dryRun should be true. Do not explain.",
|
|
38921
|
-
"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."
|
|
38922
38974
|
].join("\n");
|
|
38923
38975
|
const resp = await callAPI("/v1/ai-proxy", {
|
|
38924
38976
|
method: "POST",
|
|
@@ -38939,11 +38991,19 @@ ${rawText}`,
|
|
|
38939
38991
|
} catch {
|
|
38940
38992
|
return {};
|
|
38941
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
|
+
}
|
|
38942
39001
|
const out = {};
|
|
38943
39002
|
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
38944
39003
|
if (typeof parsed.dryRun === "boolean") out.dryRun = parsed.dryRun;
|
|
38945
39004
|
if (typeof parsed.output === "string" && (parsed.output === "names" || parsed.output === "summary" || parsed.output === "detail")) out.output = parsed.output;
|
|
38946
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;
|
|
38947
39007
|
if (out.planOnly) out.dryRun = false;
|
|
38948
39008
|
return out;
|
|
38949
39009
|
}
|
|
@@ -39091,6 +39151,12 @@ var init_FilePlanBuilder = __esm({
|
|
|
39091
39151
|
}
|
|
39092
39152
|
});
|
|
39093
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
|
+
}
|
|
39094
39160
|
const warnings = [];
|
|
39095
39161
|
const skipped = [];
|
|
39096
39162
|
const seenLC = /* @__PURE__ */ new Set();
|
|
@@ -39107,6 +39173,10 @@ async function validatePlan(plans, opts) {
|
|
|
39107
39173
|
}
|
|
39108
39174
|
const safe = [];
|
|
39109
39175
|
for (const fp of outFiltered) {
|
|
39176
|
+
if (fp.action === "skip") {
|
|
39177
|
+
skipped.push(fp.path);
|
|
39178
|
+
continue;
|
|
39179
|
+
}
|
|
39110
39180
|
const rel = fp.path.replace(/^\/+/, "");
|
|
39111
39181
|
if (rel.includes("..")) {
|
|
39112
39182
|
warnings.push(`Path traversal denied: ${fp.path}`);
|
|
@@ -39188,7 +39258,18 @@ async function validatePlan(plans, opts) {
|
|
|
39188
39258
|
}
|
|
39189
39259
|
result.push({ ...fp, action: willModify ? "modify" : "create" });
|
|
39190
39260
|
}
|
|
39191
|
-
|
|
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;
|
|
39192
39273
|
}
|
|
39193
39274
|
async function exists(p) {
|
|
39194
39275
|
try {
|
|
@@ -39982,7 +40063,7 @@ ${h2.head}`);
|
|
|
39982
40063
|
const resp = await executeChat([
|
|
39983
40064
|
{ role: "system", content: system },
|
|
39984
40065
|
{ role: "user", content: user }
|
|
39985
|
-
]);
|
|
40066
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
39986
40067
|
const raw = (resp?.output || "").trim();
|
|
39987
40068
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
39988
40069
|
const arr = JSON.parse(jsonText);
|
|
@@ -39999,7 +40080,7 @@ ${h2.head}`);
|
|
|
39999
40080
|
return [];
|
|
40000
40081
|
}
|
|
40001
40082
|
}
|
|
40002
|
-
async function llmMapBlocksBatch(root, request, blocks, repoFiles) {
|
|
40083
|
+
async function llmMapBlocksBatch(root, request, blocks, repoFiles, opts) {
|
|
40003
40084
|
try {
|
|
40004
40085
|
const candidates = repoFiles.filter((p) => /\.(html|css|js|ts|tsx)$/i.test(p)).slice(0, 120);
|
|
40005
40086
|
const blockSnippets = blocks.slice(0, 20).map((b, i2) => {
|
|
@@ -40017,26 +40098,43 @@ ${head2}
|
|
|
40017
40098
|
${h2.head}`);
|
|
40018
40099
|
}
|
|
40019
40100
|
const system = [
|
|
40020
|
-
"
|
|
40021
|
-
|
|
40022
|
-
"
|
|
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 }].'
|
|
40023
40109
|
].join("\n");
|
|
40024
40110
|
const user = [
|
|
40025
40111
|
`Request: ${request}`,
|
|
40026
40112
|
"Blocks:",
|
|
40027
40113
|
blockSnippets,
|
|
40028
40114
|
"Candidates:",
|
|
40029
|
-
samples.join("\n\n")
|
|
40115
|
+
samples.join("\n\n"),
|
|
40116
|
+
`TargetDirHints: ${(opts?.dirHints || []).join(", ")}`
|
|
40030
40117
|
].join("\n\n");
|
|
40031
|
-
|
|
40032
|
-
spin
|
|
40033
|
-
|
|
40034
|
-
|
|
40035
|
-
|
|
40036
|
-
|
|
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;
|
|
40037
40126
|
try {
|
|
40038
|
-
|
|
40039
|
-
|
|
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
|
+
}
|
|
40040
40138
|
}
|
|
40041
40139
|
const raw = (resp?.output || "").trim();
|
|
40042
40140
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
@@ -40090,12 +40188,25 @@ function trackCodeFallback(event) {
|
|
|
40090
40188
|
}
|
|
40091
40189
|
}
|
|
40092
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
|
+
};
|
|
40093
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 });
|
|
40094
40204
|
const initial = [];
|
|
40095
40205
|
const fallbackNotices = [];
|
|
40096
40206
|
const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
|
|
40097
40207
|
const explicitFilesRaw = parseExplicitFilenames(request);
|
|
40098
40208
|
const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
|
|
40209
|
+
dbg("explicitFiles", { raw: explicitFilesRaw, resolved: explicitFiles });
|
|
40099
40210
|
const explicitAbsMap = /* @__PURE__ */ Object.create(null);
|
|
40100
40211
|
if (explicitFiles.length > 0) {
|
|
40101
40212
|
const pathMod = await import('path');
|
|
@@ -40107,12 +40218,14 @@ async function orchestrate(request, opts) {
|
|
|
40107
40218
|
explicitFiles,
|
|
40108
40219
|
attachmentsCount: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0
|
|
40109
40220
|
});
|
|
40221
|
+
dbg("intent", { isEditIntent });
|
|
40110
40222
|
let editTargets = explicitFiles;
|
|
40111
40223
|
if (isEditIntent && editTargets.length === 0) {
|
|
40112
40224
|
try {
|
|
40113
40225
|
const repoFiles = await getRepoFiles(opts.root);
|
|
40114
40226
|
const llmTargets = await llmSelectEditTargets(opts.root, request, repoFiles);
|
|
40115
40227
|
editTargets = llmTargets;
|
|
40228
|
+
dbg("llmSelectEditTargets", { editTargets });
|
|
40116
40229
|
} catch {
|
|
40117
40230
|
}
|
|
40118
40231
|
}
|
|
@@ -40124,6 +40237,7 @@ async function orchestrate(request, opts) {
|
|
|
40124
40237
|
maxAttachments: opts.flags.maxAttachments || 50,
|
|
40125
40238
|
allowDotfiles: !!opts.flags.allowDotfiles
|
|
40126
40239
|
});
|
|
40240
|
+
dbg("attachment.map", { mappedCount: mapRes.mapped.length, warnings: mapRes.warnings });
|
|
40127
40241
|
mapRes.warnings.slice();
|
|
40128
40242
|
for (const m2 of mapRes.mapped) {
|
|
40129
40243
|
initial.push({
|
|
@@ -40135,7 +40249,7 @@ async function orchestrate(request, opts) {
|
|
|
40135
40249
|
});
|
|
40136
40250
|
}
|
|
40137
40251
|
}
|
|
40138
|
-
const onlyAttached = !!opts.flags.onlyAttached;
|
|
40252
|
+
const onlyAttached = !!(opts.flags.onlyAttached && Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0);
|
|
40139
40253
|
if (!onlyAttached) {
|
|
40140
40254
|
let codeOutput = "";
|
|
40141
40255
|
if (process.env.MARIA_E2E_FAKE_CODE === "1") {
|
|
@@ -40155,10 +40269,37 @@ async function orchestrate(request, opts) {
|
|
|
40155
40269
|
"[BEGIN file: path]\n<content>\n[END]",
|
|
40156
40270
|
"Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
|
|
40157
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") : "";
|
|
40158
40290
|
const requestPreamble = isEditIntent ? [
|
|
40159
|
-
"// EDIT MODE:
|
|
40160
|
-
"//
|
|
40161
|
-
|
|
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
|
|
40162
40303
|
].filter(Boolean).join("\n") : "";
|
|
40163
40304
|
const enriched = `${FILE_FORMAT_INSTRUCTIONS}
|
|
40164
40305
|
|
|
@@ -40166,6 +40307,7 @@ ${requestPreamble}
|
|
|
40166
40307
|
${request}
|
|
40167
40308
|
|
|
40168
40309
|
${editContext}`;
|
|
40310
|
+
dbg("executeCode.prompt.head", enriched.slice(0, 1400));
|
|
40169
40311
|
const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
|
|
40170
40312
|
name: f3.originalName,
|
|
40171
40313
|
path: f3.pathHint,
|
|
@@ -40199,6 +40341,68 @@ ${editContext}`;
|
|
|
40199
40341
|
} catch {
|
|
40200
40342
|
}
|
|
40201
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
|
+
}
|
|
40202
40406
|
if (isEditIntent && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
40203
40407
|
try {
|
|
40204
40408
|
const fs52 = await import('fs/promises');
|
|
@@ -40253,9 +40457,34 @@ ${editContext}`;
|
|
|
40253
40457
|
hydratedCtx.push(...ctxAttachments);
|
|
40254
40458
|
}
|
|
40255
40459
|
}
|
|
40256
|
-
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
|
+
}));
|
|
40257
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
|
+
}
|
|
40258
40486
|
const raw = (response.output || response?.data?.content || "").trim();
|
|
40487
|
+
dbg("executeCode.output.head", raw.slice(0, 1200));
|
|
40259
40488
|
if (!raw) {
|
|
40260
40489
|
return {
|
|
40261
40490
|
ok: false,
|
|
@@ -40293,6 +40522,7 @@ ${editContext}`;
|
|
|
40293
40522
|
codeOutput = outcome.data?.output || "";
|
|
40294
40523
|
}
|
|
40295
40524
|
const blocks = extractBlocks(codeOutput);
|
|
40525
|
+
dbg("extractBlocks.count", blocks.length);
|
|
40296
40526
|
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
40297
40527
|
const mapped = /* @__PURE__ */ new Set();
|
|
40298
40528
|
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
@@ -40330,23 +40560,49 @@ ${editContext}`;
|
|
|
40330
40560
|
} else {
|
|
40331
40561
|
try {
|
|
40332
40562
|
const repoFiles = await getRepoFiles(opts.root);
|
|
40333
|
-
|
|
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);
|
|
40334
40587
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
40335
40588
|
const b = blocks[i2];
|
|
40336
40589
|
const d = decisions[i2] || { action: "create", path: suggestName2(request, b.language, i2) };
|
|
40337
|
-
|
|
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)) {
|
|
40338
40593
|
const lang = languageFromExt(d.path.replace(/^.*(\.[a-z0-9]+)$/i, "$1"));
|
|
40339
|
-
initial.push({ path:
|
|
40594
|
+
initial.push({ path: finalPath, kind: "source", action: "modify", description: "Modify existing file", language: lang, preview: b.code, noNormalize: true });
|
|
40340
40595
|
} else {
|
|
40341
|
-
const pth = d.path || suggestName2(request, b.language, i2);
|
|
40342
|
-
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 });
|
|
40343
40598
|
}
|
|
40344
40599
|
}
|
|
40345
40600
|
} catch {
|
|
40346
40601
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
40347
40602
|
const b = blocks[i2];
|
|
40348
|
-
const
|
|
40349
|
-
|
|
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 });
|
|
40350
40606
|
}
|
|
40351
40607
|
}
|
|
40352
40608
|
}
|
|
@@ -40362,13 +40618,13 @@ ${editContext}`;
|
|
|
40362
40618
|
}
|
|
40363
40619
|
}
|
|
40364
40620
|
}
|
|
40365
|
-
if (explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
40621
|
+
if (!isEditIntent && explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
40366
40622
|
for (const f3 of explicitFiles) {
|
|
40367
40623
|
initial.push(scaffoldForFilename(f3, explicitFiles));
|
|
40368
40624
|
}
|
|
40369
40625
|
}
|
|
40370
40626
|
const normalized = await normalizePlans(
|
|
40371
|
-
initial.map((p) => p.noNormalize ? p : p),
|
|
40627
|
+
initial.map((p) => p.noNormalize ? { ...p } : p),
|
|
40372
40628
|
{ root: opts.root }
|
|
40373
40629
|
);
|
|
40374
40630
|
try {
|
|
@@ -40393,11 +40649,26 @@ ${editContext}`;
|
|
|
40393
40649
|
}
|
|
40394
40650
|
} catch {
|
|
40395
40651
|
}
|
|
40396
|
-
|
|
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 });
|
|
40397
40668
|
const hasAnyModify = validated.files.some((f3) => f3.action === "modify") || isEditIntent;
|
|
40398
40669
|
const outputMode = !opts.flags.hideCode && hasAnyModify ? "diff" : resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
|
|
40399
40670
|
const skippedSetForLookup = new Set(validated.skipped || []);
|
|
40400
|
-
const skippedPlans =
|
|
40671
|
+
const skippedPlans = filtered.filter((f3) => skippedSetForLookup.has(f3.path));
|
|
40401
40672
|
const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
|
|
40402
40673
|
const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
|
|
40403
40674
|
const summary = summarizePlan(displayFiles);
|
|
@@ -40590,6 +40861,21 @@ function extractBlocks(content) {
|
|
|
40590
40861
|
if (blocks.length === 0 && looksLikeCode(content)) blocks.push({ language: detectLanguage(content), code: content.trim() });
|
|
40591
40862
|
return blocks;
|
|
40592
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
|
+
}
|
|
40593
40879
|
function looksLikeCode(s2) {
|
|
40594
40880
|
return ["function ", "const ", "let ", "var ", "class ", "def ", "import ", "export "].some((k) => s2.includes(k));
|
|
40595
40881
|
}
|
|
@@ -40747,48 +41033,100 @@ function parseExplicitFilenames(request) {
|
|
|
40747
41033
|
return out;
|
|
40748
41034
|
}
|
|
40749
41035
|
async function detectEditIntentLLM(root, request, ctx2) {
|
|
41036
|
+
let existingDirs = [];
|
|
41037
|
+
let existingFiles = [];
|
|
41038
|
+
let anyExistingPathMentioned = false;
|
|
40750
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
|
+
}
|
|
40751
41059
|
const repoFiles = await getRepoFiles(root);
|
|
40752
|
-
|
|
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
|
+
}
|
|
40753
41067
|
const headSnippets = [];
|
|
40754
|
-
for (const p of
|
|
41068
|
+
for (const p of scope) {
|
|
40755
41069
|
const h2 = await readHeadTail(root, p, 5);
|
|
40756
41070
|
headSnippets.push(`- ${p}
|
|
40757
41071
|
${h2.head}`);
|
|
40758
41072
|
}
|
|
40759
41073
|
const system = [
|
|
40760
|
-
"
|
|
40761
|
-
"
|
|
40762
|
-
"
|
|
40763
|
-
"
|
|
40764
|
-
"
|
|
40765
|
-
"
|
|
40766
|
-
"
|
|
40767
|
-
'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" }.'
|
|
40768
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
|
+
};
|
|
40769
41091
|
const user = [
|
|
40770
41092
|
`Request: ${request}`,
|
|
40771
|
-
`
|
|
40772
|
-
|
|
40773
|
-
"Repo snapshot (paths with file heads):",
|
|
41093
|
+
`Evidence: ${JSON.stringify(evidence)}`,
|
|
41094
|
+
"Repo snapshot (trimmed):",
|
|
40774
41095
|
headSnippets.join("\n\n")
|
|
40775
41096
|
].join("\n\n");
|
|
40776
|
-
|
|
40777
|
-
|
|
40778
|
-
|
|
40779
|
-
|
|
40780
|
-
|
|
40781
|
-
|
|
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;
|
|
40782
41108
|
try {
|
|
40783
|
-
|
|
40784
|
-
|
|
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
|
+
}
|
|
40785
41120
|
}
|
|
40786
41121
|
const raw = (resp?.output || "").trim();
|
|
40787
41122
|
const jsonText = extractJsonSafe(raw, "object") || raw;
|
|
40788
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
|
+
}
|
|
40789
41127
|
return parsed?.intent === "EDIT_EXISTING";
|
|
40790
41128
|
} catch {
|
|
40791
|
-
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;
|
|
40792
41130
|
}
|
|
40793
41131
|
}
|
|
40794
41132
|
function sanitizeFolderName(name2) {
|
|
@@ -40956,7 +41294,7 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
40956
41294
|
const chat = await executeChat([
|
|
40957
41295
|
{ role: "system", content: system },
|
|
40958
41296
|
{ role: "user", content: user }
|
|
40959
|
-
]);
|
|
41297
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
40960
41298
|
const raw = (chat.output || "").trim();
|
|
40961
41299
|
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
40962
41300
|
return pick.replace(/^\/+/, "");
|
|
@@ -41131,7 +41469,16 @@ var init_code_command = __esm({
|
|
|
41131
41469
|
}
|
|
41132
41470
|
];
|
|
41133
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
|
+
};
|
|
41134
41480
|
const request = await this.ensureLanguageDefaults(commandArgs.raw.join(" ").trim());
|
|
41481
|
+
debug("request", request);
|
|
41135
41482
|
if (!request) {
|
|
41136
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.");
|
|
41137
41484
|
}
|
|
@@ -41143,6 +41490,7 @@ var init_code_command = __esm({
|
|
|
41143
41490
|
const explicitDry = commandArgs.raw.includes("--dry-run");
|
|
41144
41491
|
const explicitOutput = commandArgs.raw.some((x2) => x2.startsWith("--output") || x2 === "--verbose" || x2 === "-v");
|
|
41145
41492
|
const explicitPreview = commandArgs.raw.some((x2) => x2.startsWith("--preview-lines"));
|
|
41493
|
+
const explicitOnlyAttached = commandArgs.raw.includes("--only-attached");
|
|
41146
41494
|
const preSpin = new ProcessAnimation();
|
|
41147
41495
|
preSpin.start();
|
|
41148
41496
|
let inferred = {};
|
|
@@ -41154,6 +41502,8 @@ var init_code_command = __esm({
|
|
|
41154
41502
|
} catch {
|
|
41155
41503
|
}
|
|
41156
41504
|
}
|
|
41505
|
+
debug("inferCodeArgs.raw", rawText);
|
|
41506
|
+
debug("inferCodeArgs.result", inferred);
|
|
41157
41507
|
if (!explicitPlan && !explicitDry) {
|
|
41158
41508
|
if (typeof inferred.planOnly === "boolean") opts.planOnly = inferred.planOnly;
|
|
41159
41509
|
if (typeof inferred.dryRun === "boolean") opts.dryRun = inferred.dryRun;
|
|
@@ -41164,6 +41514,9 @@ var init_code_command = __esm({
|
|
|
41164
41514
|
if (!explicitPreview && typeof inferred.previewLines === "number") {
|
|
41165
41515
|
opts.previewLines = inferred.previewLines;
|
|
41166
41516
|
}
|
|
41517
|
+
if (!explicitOnlyAttached && typeof inferred.onlyAttached === "boolean") {
|
|
41518
|
+
opts.onlyAttached = inferred.onlyAttached;
|
|
41519
|
+
}
|
|
41167
41520
|
} catch {
|
|
41168
41521
|
}
|
|
41169
41522
|
if (opts.planOnly) {
|
|
@@ -41178,13 +41531,27 @@ var init_code_command = __esm({
|
|
|
41178
41531
|
const root = opts.root || process.cwd();
|
|
41179
41532
|
const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
|
|
41180
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
|
+
}
|
|
41181
41541
|
const abort = new AbortController();
|
|
41182
41542
|
const onSigint = () => abort.abort();
|
|
41183
41543
|
process.once("SIGINT", onSigint);
|
|
41184
|
-
|
|
41185
|
-
spinner
|
|
41544
|
+
let startedLocalSpinner = false;
|
|
41545
|
+
let spinner = null;
|
|
41546
|
+
if (!ProcessAnimation.hasActive()) {
|
|
41547
|
+
spinner = new ProcessAnimation();
|
|
41548
|
+
spinner.start();
|
|
41549
|
+
startedLocalSpinner = true;
|
|
41550
|
+
}
|
|
41186
41551
|
try {
|
|
41187
|
-
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) : []);
|
|
41188
41555
|
if (opts.planOnly) {
|
|
41189
41556
|
const fs52 = await import('fs/promises');
|
|
41190
41557
|
const path65 = await import('path');
|
|
@@ -41237,9 +41604,11 @@ var init_code_command = __esm({
|
|
|
41237
41604
|
const out = Array.isArray(res?.summaryLines) ? res.summaryLines.join("\n") : "";
|
|
41238
41605
|
return this.success(out);
|
|
41239
41606
|
} finally {
|
|
41240
|
-
|
|
41241
|
-
|
|
41242
|
-
|
|
41607
|
+
if (startedLocalSpinner && spinner) {
|
|
41608
|
+
try {
|
|
41609
|
+
spinner.stop();
|
|
41610
|
+
} catch {
|
|
41611
|
+
}
|
|
41243
41612
|
}
|
|
41244
41613
|
process.removeListener("SIGINT", onSigint);
|
|
41245
41614
|
}
|
|
@@ -41362,12 +41731,6 @@ ${pretty}`);
|
|
|
41362
41731
|
if (llmLang) {
|
|
41363
41732
|
const hint2 = (() => {
|
|
41364
41733
|
const l = llmLang.toLowerCase();
|
|
41365
|
-
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
41366
|
-
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
41367
|
-
if (l === "typescript") return "TypeScript";
|
|
41368
|
-
if (l === "javascript") return "JavaScript";
|
|
41369
|
-
if (l === "html") return "HTML";
|
|
41370
|
-
if (l === "css") return "CSS";
|
|
41371
41734
|
return llmLang;
|
|
41372
41735
|
})();
|
|
41373
41736
|
return raw + ` (Use ${hint2})`;
|
|
@@ -41380,7 +41743,7 @@ ${pretty}`);
|
|
|
41380
41743
|
preSpin.start();
|
|
41381
41744
|
const system = [
|
|
41382
41745
|
"You analyze a user's code-generation request.",
|
|
41383
|
-
"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.",
|
|
41384
41747
|
'Return ONLY compact JSON with shape {"explicitLanguage": boolean, "language"?: string}.',
|
|
41385
41748
|
"Do not add any commentary."
|
|
41386
41749
|
].join("\n");
|
|
@@ -41389,7 +41752,7 @@ ${pretty}`);
|
|
|
41389
41752
|
method: "POST",
|
|
41390
41753
|
body: {
|
|
41391
41754
|
provider: "google",
|
|
41392
|
-
model: "gemini-2.5-flash",
|
|
41755
|
+
model: "gemini-2.5-flash-lite",
|
|
41393
41756
|
taskType: "chat",
|
|
41394
41757
|
prompt: `${system}
|
|
41395
41758
|
|
|
@@ -41434,6 +41797,14 @@ ${user}`
|
|
|
41434
41797
|
if (parsed && parsed.explicitLanguage) return raw;
|
|
41435
41798
|
} catch {
|
|
41436
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
|
+
}
|
|
41437
41808
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
41438
41809
|
return raw + hint;
|
|
41439
41810
|
}
|
|
@@ -41443,9 +41814,7 @@ ${user}`
|
|
|
41443
41814
|
const system = [
|
|
41444
41815
|
"You are a programming language classifier.",
|
|
41445
41816
|
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
41446
|
-
"Respond with ONLY
|
|
41447
|
-
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
41448
|
-
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
41817
|
+
"Respond with ONLY language name(s)"
|
|
41449
41818
|
].join("\n");
|
|
41450
41819
|
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
41451
41820
|
${s2}`).join("\n\n");
|
|
@@ -41454,7 +41823,7 @@ ${s2}`).join("\n\n");
|
|
|
41454
41823
|
method: "POST",
|
|
41455
41824
|
body: {
|
|
41456
41825
|
provider: "google",
|
|
41457
|
-
model: "gemini-2.5-flash",
|
|
41826
|
+
model: "gemini-2.5-flash-lite",
|
|
41458
41827
|
taskType: "chat",
|
|
41459
41828
|
prompt: `${system}
|
|
41460
41829
|
|
|
@@ -41760,64 +42129,6 @@ ${joined}`
|
|
|
41760
42129
|
return false;
|
|
41761
42130
|
}
|
|
41762
42131
|
}
|
|
41763
|
-
/**
|
|
41764
|
-
* Extract code blocks from AI response
|
|
41765
|
-
*/
|
|
41766
|
-
extractCodeBlocks(content) {
|
|
41767
|
-
const blocks = [];
|
|
41768
|
-
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
|
41769
|
-
let match2;
|
|
41770
|
-
while ((match2 = codeBlockRegex.exec(content)) !== null) {
|
|
41771
|
-
blocks.push({
|
|
41772
|
-
language: match2[1] || "javascript",
|
|
41773
|
-
code: match2[2].trim()
|
|
41774
|
-
});
|
|
41775
|
-
}
|
|
41776
|
-
if (blocks.length === 0 && this.looksLikeCode(content)) {
|
|
41777
|
-
blocks.push({
|
|
41778
|
-
code: content.trim(),
|
|
41779
|
-
language: this.detectLanguage(content)
|
|
41780
|
-
});
|
|
41781
|
-
}
|
|
41782
|
-
return blocks;
|
|
41783
|
-
}
|
|
41784
|
-
/**
|
|
41785
|
-
* Check if content looks like code
|
|
41786
|
-
*/
|
|
41787
|
-
looksLikeCode(content) {
|
|
41788
|
-
const codeIndicators = [
|
|
41789
|
-
"function ",
|
|
41790
|
-
"const ",
|
|
41791
|
-
"let ",
|
|
41792
|
-
"var ",
|
|
41793
|
-
"class ",
|
|
41794
|
-
"def ",
|
|
41795
|
-
"import ",
|
|
41796
|
-
"export ",
|
|
41797
|
-
"{",
|
|
41798
|
-
"}",
|
|
41799
|
-
";",
|
|
41800
|
-
"//",
|
|
41801
|
-
"/*"
|
|
41802
|
-
];
|
|
41803
|
-
return codeIndicators.some((indicator) => content.includes(indicator));
|
|
41804
|
-
}
|
|
41805
|
-
/**
|
|
41806
|
-
* Detect programming language from content
|
|
41807
|
-
*/
|
|
41808
|
-
detectLanguage(code) {
|
|
41809
|
-
const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
|
|
41810
|
-
const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
|
|
41811
|
-
const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
|
|
41812
|
-
if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
|
|
41813
|
-
if (code.includes("interface ") || code.includes(": string")) return "typescript";
|
|
41814
|
-
if (code.includes("def ") || code.includes("print(")) return "python";
|
|
41815
|
-
if (code.includes("func ") || code.includes("package main")) return "go";
|
|
41816
|
-
if (code.includes("fn ") || code.includes("let mut")) return "rust";
|
|
41817
|
-
if (code.includes("<?php")) return "php";
|
|
41818
|
-
if (code.includes("#include")) return "cpp";
|
|
41819
|
-
return "javascript";
|
|
41820
|
-
}
|
|
41821
42132
|
/**
|
|
41822
42133
|
* Save code block to file
|
|
41823
42134
|
*/
|
|
@@ -50509,11 +50820,10 @@ var init_responsive_width = __esm({
|
|
|
50509
50820
|
}
|
|
50510
50821
|
});
|
|
50511
50822
|
function createSpinner(text) {
|
|
50512
|
-
let frame = 0;
|
|
50513
50823
|
let active = false;
|
|
50514
|
-
let
|
|
50515
|
-
const
|
|
50516
|
-
const f3 = SPINNER_FRAMES[frame
|
|
50824
|
+
let frame = 0;
|
|
50825
|
+
const renderOnce = () => {
|
|
50826
|
+
const f3 = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
50517
50827
|
process6__namespace.default.stdout.write(`\r ${chalk40__default.default.cyan(f3)} ${text}`);
|
|
50518
50828
|
};
|
|
50519
50829
|
return {
|
|
@@ -50523,13 +50833,11 @@ function createSpinner(text) {
|
|
|
50523
50833
|
start() {
|
|
50524
50834
|
if (active) return;
|
|
50525
50835
|
active = true;
|
|
50526
|
-
|
|
50527
|
-
timer = setInterval(render, 80);
|
|
50836
|
+
renderOnce();
|
|
50528
50837
|
},
|
|
50529
50838
|
stop(symbol = "\u2714") {
|
|
50530
50839
|
if (!active) return;
|
|
50531
50840
|
active = false;
|
|
50532
|
-
if (timer) clearInterval(timer);
|
|
50533
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;
|
|
50534
50842
|
process6__namespace.default.stdout.write(`\r ${finalSymbol} ${text}
|
|
50535
50843
|
`);
|