@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/bin/maria.cjs
CHANGED
|
@@ -26066,8 +26066,8 @@ var require_package = __commonJS({
|
|
|
26066
26066
|
"package.json"(exports, module) {
|
|
26067
26067
|
module.exports = {
|
|
26068
26068
|
name: "@bonginkan/maria",
|
|
26069
|
-
version: "4.3.
|
|
26070
|
-
description: "\u{1F680} MARIA v4.3.
|
|
26069
|
+
version: "4.3.46",
|
|
26070
|
+
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.",
|
|
26071
26071
|
keywords: [
|
|
26072
26072
|
"ai",
|
|
26073
26073
|
"cli",
|
|
@@ -26619,7 +26619,8 @@ var init_env_loader = __esm({
|
|
|
26619
26619
|
var ThinkingAnimation, ProcessAnimation;
|
|
26620
26620
|
var init_animations = __esm({
|
|
26621
26621
|
"src/utils/animations.ts"() {
|
|
26622
|
-
ThinkingAnimation = class {
|
|
26622
|
+
ThinkingAnimation = class _ThinkingAnimation {
|
|
26623
|
+
static current = null;
|
|
26623
26624
|
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
26624
26625
|
currentFrame = 0;
|
|
26625
26626
|
interval = null;
|
|
@@ -26628,6 +26629,13 @@ var init_animations = __esm({
|
|
|
26628
26629
|
this.message = message;
|
|
26629
26630
|
}
|
|
26630
26631
|
start() {
|
|
26632
|
+
if (_ThinkingAnimation.current && _ThinkingAnimation.current !== this) {
|
|
26633
|
+
try {
|
|
26634
|
+
_ThinkingAnimation.current.stop();
|
|
26635
|
+
} catch {
|
|
26636
|
+
}
|
|
26637
|
+
}
|
|
26638
|
+
_ThinkingAnimation.current = this;
|
|
26631
26639
|
this.interval = setInterval(() => {
|
|
26632
26640
|
process.stdout.write(
|
|
26633
26641
|
`\r${chalk14__default.default.cyan(this.frames[this.currentFrame])} ${chalk14__default.default.gray(this.message)}...`
|
|
@@ -26641,12 +26649,16 @@ var init_animations = __esm({
|
|
|
26641
26649
|
this.interval = null;
|
|
26642
26650
|
process.stdout.write("\r\x1B[K");
|
|
26643
26651
|
}
|
|
26652
|
+
if (_ThinkingAnimation.current === this) {
|
|
26653
|
+
_ThinkingAnimation.current = null;
|
|
26654
|
+
}
|
|
26644
26655
|
}
|
|
26645
26656
|
updateMessage(message) {
|
|
26646
26657
|
this.message = message;
|
|
26647
26658
|
}
|
|
26648
26659
|
};
|
|
26649
|
-
ProcessAnimation = class {
|
|
26660
|
+
ProcessAnimation = class _ProcessAnimation {
|
|
26661
|
+
static current = null;
|
|
26650
26662
|
stages = [
|
|
26651
26663
|
{ icon: "\u{1F9E0}", message: "Understanding your request" },
|
|
26652
26664
|
{ icon: "\u{1F50D}", message: "Analyzing context" },
|
|
@@ -26660,7 +26672,18 @@ var init_animations = __esm({
|
|
|
26660
26672
|
interval = null;
|
|
26661
26673
|
stageInterval = null;
|
|
26662
26674
|
startTime = 0;
|
|
26675
|
+
// Expose whether any ProcessAnimation is currently active
|
|
26676
|
+
static hasActive() {
|
|
26677
|
+
return !!_ProcessAnimation.current;
|
|
26678
|
+
}
|
|
26663
26679
|
start() {
|
|
26680
|
+
if (_ProcessAnimation.current && _ProcessAnimation.current !== this) {
|
|
26681
|
+
try {
|
|
26682
|
+
_ProcessAnimation.current.stop();
|
|
26683
|
+
} catch {
|
|
26684
|
+
}
|
|
26685
|
+
}
|
|
26686
|
+
_ProcessAnimation.current = this;
|
|
26664
26687
|
this.startTime = Date.now();
|
|
26665
26688
|
this.currentStage = 0;
|
|
26666
26689
|
this.currentFrame = 0;
|
|
@@ -26688,6 +26711,9 @@ var init_animations = __esm({
|
|
|
26688
26711
|
this.stageInterval = null;
|
|
26689
26712
|
}
|
|
26690
26713
|
process.stdout.write("\r\x1B[K");
|
|
26714
|
+
if (_ProcessAnimation.current === this) {
|
|
26715
|
+
_ProcessAnimation.current = null;
|
|
26716
|
+
}
|
|
26691
26717
|
}
|
|
26692
26718
|
setStage(stageIndex) {
|
|
26693
26719
|
if (stageIndex >= 0 && stageIndex < this.stages.length) {
|
|
@@ -28104,7 +28130,7 @@ var init_AuthenticationManager = __esm({
|
|
|
28104
28130
|
const response = await fetch(`${this.apiBase}/api/user/profile`, {
|
|
28105
28131
|
headers: {
|
|
28106
28132
|
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
28107
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
28133
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.46"}`
|
|
28108
28134
|
}
|
|
28109
28135
|
});
|
|
28110
28136
|
if (response.status === 401) {
|
|
@@ -28758,7 +28784,7 @@ async function callApi(path65, init3 = {}) {
|
|
|
28758
28784
|
"Authorization": `Bearer ${token}`,
|
|
28759
28785
|
"X-Device-Id": getDeviceId(),
|
|
28760
28786
|
"X-Session-Id": getSessionId() || "",
|
|
28761
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
28787
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.46"}`,
|
|
28762
28788
|
"Content-Type": init3.headers?.["Content-Type"] || "application/json"
|
|
28763
28789
|
});
|
|
28764
28790
|
const doFetch = async (token) => {
|
|
@@ -29102,15 +29128,27 @@ async function callAPI(endpoint, options = {}) {
|
|
|
29102
29128
|
throw err;
|
|
29103
29129
|
}
|
|
29104
29130
|
}
|
|
29105
|
-
async function executeChat(messages) {
|
|
29131
|
+
async function executeChat(messages, options) {
|
|
29106
29132
|
const maxAttempts = 4;
|
|
29107
29133
|
let lastErr;
|
|
29108
29134
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
29109
29135
|
try {
|
|
29136
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
29137
|
+
try {
|
|
29138
|
+
console.log("[DEBUG/ai] chat.request", { attempt, provider: options?.provider, model: options?.model, messages: messages.slice(0, 3) });
|
|
29139
|
+
} catch {
|
|
29140
|
+
}
|
|
29141
|
+
}
|
|
29110
29142
|
const response = await callAPI("/v1/ai-proxy", {
|
|
29111
29143
|
method: "POST",
|
|
29112
|
-
body: { messages, taskType: "chat" }
|
|
29144
|
+
body: { messages, taskType: "chat", ...options?.provider ? { provider: options.provider } : {}, ...options?.model ? { model: options.model } : {} }
|
|
29113
29145
|
});
|
|
29146
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
29147
|
+
try {
|
|
29148
|
+
console.log("[DEBUG/ai] chat.response.head", String(response?.data?.content || response?.output || "").slice(0, 1200));
|
|
29149
|
+
} catch {
|
|
29150
|
+
}
|
|
29151
|
+
}
|
|
29114
29152
|
return response;
|
|
29115
29153
|
} catch (e2) {
|
|
29116
29154
|
lastErr = e2;
|
|
@@ -29142,6 +29180,13 @@ async function executeCode(input3) {
|
|
|
29142
29180
|
let lastErr;
|
|
29143
29181
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
29144
29182
|
try {
|
|
29183
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
29184
|
+
try {
|
|
29185
|
+
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 };
|
|
29186
|
+
console.log("[DEBUG/ai] code.request", { attempt, ...dbg });
|
|
29187
|
+
} catch {
|
|
29188
|
+
}
|
|
29189
|
+
}
|
|
29145
29190
|
const response = await callAPI("/v1/ai-proxy", {
|
|
29146
29191
|
method: "POST",
|
|
29147
29192
|
body
|
|
@@ -29152,6 +29197,12 @@ async function executeCode(input3) {
|
|
|
29152
29197
|
if (response.data?.content) {
|
|
29153
29198
|
response.output = response.data.content;
|
|
29154
29199
|
}
|
|
29200
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
29201
|
+
try {
|
|
29202
|
+
console.log("[DEBUG/ai] code.response.head", String(response?.output || "").slice(0, 1200));
|
|
29203
|
+
} catch {
|
|
29204
|
+
}
|
|
29205
|
+
}
|
|
29155
29206
|
return response;
|
|
29156
29207
|
} catch (e2) {
|
|
29157
29208
|
lastErr = e2;
|
|
@@ -51298,7 +51349,7 @@ var init_about_command = __esm({
|
|
|
51298
51349
|
async execute(args2, context2) {
|
|
51299
51350
|
const output3 = [];
|
|
51300
51351
|
output3.push("");
|
|
51301
|
-
output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.
|
|
51352
|
+
output3.push(chalk14__default.default.cyan.bold("\u{1F916} About MARIA v4.3.46"));
|
|
51302
51353
|
output3.push(chalk14__default.default.gray("\u2550".repeat(40)));
|
|
51303
51354
|
output3.push("");
|
|
51304
51355
|
output3.push(chalk14__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -55025,9 +55076,10 @@ function extractFirstJson5(text) {
|
|
|
55025
55076
|
async function inferCodeArgs(rawText) {
|
|
55026
55077
|
const system = [
|
|
55027
55078
|
"You extract structured options for a code command.",
|
|
55028
|
-
'Return JSON only with keys: { "planOnly"?: boolean, "dryRun"?: boolean, "output"?: "names"|"summary"|"detail", "previewLines"?: number }.',
|
|
55079
|
+
'Return JSON only with keys: { "planOnly"?: boolean, "dryRun"?: boolean, "output"?: "names"|"summary"|"detail", "previewLines"?: number, "onlyAttached"?: boolean }.',
|
|
55029
55080
|
"Decide from the user text whether planOnly or dryRun should be true. Do not explain.",
|
|
55030
|
-
"Only include output if the user requests preview detail or summary mode. Only include previewLines if a specific number of lines is requested."
|
|
55081
|
+
"Only include output if the user requests preview detail or summary mode. Only include previewLines if a specific number of lines is requested.",
|
|
55082
|
+
"Set onlyAttached=true when the user indicates editing only attached/uploaded/provided files, or restrict changes to referenced files."
|
|
55031
55083
|
].join("\n");
|
|
55032
55084
|
const resp = await callAPI("/v1/ai-proxy", {
|
|
55033
55085
|
method: "POST",
|
|
@@ -55048,11 +55100,19 @@ ${rawText}`,
|
|
|
55048
55100
|
} catch {
|
|
55049
55101
|
return {};
|
|
55050
55102
|
}
|
|
55103
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
55104
|
+
try {
|
|
55105
|
+
console.log("[DEBUG/code] inferCodeArgs.response.raw", raw.slice(0, 1200));
|
|
55106
|
+
console.log("[DEBUG/code] inferCodeArgs.parsed", parsed);
|
|
55107
|
+
} catch {
|
|
55108
|
+
}
|
|
55109
|
+
}
|
|
55051
55110
|
const out = {};
|
|
55052
55111
|
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
55053
55112
|
if (typeof parsed.dryRun === "boolean") out.dryRun = parsed.dryRun;
|
|
55054
55113
|
if (typeof parsed.output === "string" && (parsed.output === "names" || parsed.output === "summary" || parsed.output === "detail")) out.output = parsed.output;
|
|
55055
55114
|
if (typeof parsed.previewLines === "number" && Number.isFinite(parsed.previewLines) && parsed.previewLines > 0) out.previewLines = Math.min(2e3, Math.floor(parsed.previewLines));
|
|
55115
|
+
if (typeof parsed.onlyAttached === "boolean") out.onlyAttached = parsed.onlyAttached;
|
|
55056
55116
|
if (out.planOnly) out.dryRun = false;
|
|
55057
55117
|
return out;
|
|
55058
55118
|
}
|
|
@@ -55200,6 +55260,12 @@ var init_FilePlanBuilder = __esm({
|
|
|
55200
55260
|
}
|
|
55201
55261
|
});
|
|
55202
55262
|
async function validatePlan(plans, opts) {
|
|
55263
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
55264
|
+
try {
|
|
55265
|
+
console.log("[DEBUG/orchestrator] validatePlan.input.count", plans.length);
|
|
55266
|
+
} catch {
|
|
55267
|
+
}
|
|
55268
|
+
}
|
|
55203
55269
|
const warnings = [];
|
|
55204
55270
|
const skipped = [];
|
|
55205
55271
|
const seenLC = /* @__PURE__ */ new Set();
|
|
@@ -55216,6 +55282,10 @@ async function validatePlan(plans, opts) {
|
|
|
55216
55282
|
}
|
|
55217
55283
|
const safe = [];
|
|
55218
55284
|
for (const fp of outFiltered) {
|
|
55285
|
+
if (fp.action === "skip") {
|
|
55286
|
+
skipped.push(fp.path);
|
|
55287
|
+
continue;
|
|
55288
|
+
}
|
|
55219
55289
|
const rel = fp.path.replace(/^\/+/, "");
|
|
55220
55290
|
if (rel.includes("..")) {
|
|
55221
55291
|
warnings.push(`Path traversal denied: ${fp.path}`);
|
|
@@ -55297,7 +55367,18 @@ async function validatePlan(plans, opts) {
|
|
|
55297
55367
|
}
|
|
55298
55368
|
result.push({ ...fp, action: willModify ? "modify" : "create" });
|
|
55299
55369
|
}
|
|
55300
|
-
|
|
55370
|
+
const out = { files: result, skipped, warnings };
|
|
55371
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
55372
|
+
try {
|
|
55373
|
+
console.log("[DEBUG/orchestrator] validatePlan.output", {
|
|
55374
|
+
files: out.files.map((f3) => ({ path: f3.path, action: f3.action })),
|
|
55375
|
+
skipped: out.skipped,
|
|
55376
|
+
warnings: out.warnings
|
|
55377
|
+
});
|
|
55378
|
+
} catch {
|
|
55379
|
+
}
|
|
55380
|
+
}
|
|
55381
|
+
return out;
|
|
55301
55382
|
}
|
|
55302
55383
|
async function exists(p) {
|
|
55303
55384
|
try {
|
|
@@ -56091,7 +56172,7 @@ ${h2.head}`);
|
|
|
56091
56172
|
const resp = await executeChat([
|
|
56092
56173
|
{ role: "system", content: system },
|
|
56093
56174
|
{ role: "user", content: user }
|
|
56094
|
-
]);
|
|
56175
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
56095
56176
|
const raw = (resp?.output || "").trim();
|
|
56096
56177
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
56097
56178
|
const arr = JSON.parse(jsonText);
|
|
@@ -56108,7 +56189,7 @@ ${h2.head}`);
|
|
|
56108
56189
|
return [];
|
|
56109
56190
|
}
|
|
56110
56191
|
}
|
|
56111
|
-
async function llmMapBlocksBatch(root, request, blocks, repoFiles) {
|
|
56192
|
+
async function llmMapBlocksBatch(root, request, blocks, repoFiles, opts) {
|
|
56112
56193
|
try {
|
|
56113
56194
|
const candidates = repoFiles.filter((p) => /\.(html|css|js|ts|tsx)$/i.test(p)).slice(0, 120);
|
|
56114
56195
|
const blockSnippets = blocks.slice(0, 20).map((b, i2) => {
|
|
@@ -56126,26 +56207,43 @@ ${head2}
|
|
|
56126
56207
|
${h2.head}`);
|
|
56127
56208
|
}
|
|
56128
56209
|
const system = [
|
|
56129
|
-
"
|
|
56130
|
-
|
|
56131
|
-
"
|
|
56210
|
+
"You act as a precise file mapper for code edits.",
|
|
56211
|
+
"For each provided code block, decide to MODIFY an existing repo file or CREATE a new file.",
|
|
56212
|
+
"Rules:",
|
|
56213
|
+
"- Prefer MODIFY when an existing file in candidates plausibly matches the block (same technology, same area).",
|
|
56214
|
+
"- If any TargetDirHints are provided, prefer files under those directories when choosing MODIFY targets.",
|
|
56215
|
+
"- Only choose CREATE if NO suitable candidate exists. Do NOT invent frameworks or restructure.",
|
|
56216
|
+
"- When MODIFY, the path MUST be one of the candidate repo-relative paths listed.",
|
|
56217
|
+
'Return JSON array: [{ "index": number, "action": "modify"|"create", "path": string }].'
|
|
56132
56218
|
].join("\n");
|
|
56133
56219
|
const user = [
|
|
56134
56220
|
`Request: ${request}`,
|
|
56135
56221
|
"Blocks:",
|
|
56136
56222
|
blockSnippets,
|
|
56137
56223
|
"Candidates:",
|
|
56138
|
-
samples.join("\n\n")
|
|
56224
|
+
samples.join("\n\n"),
|
|
56225
|
+
`TargetDirHints: ${(opts?.dirHints || []).join(", ")}`
|
|
56139
56226
|
].join("\n\n");
|
|
56140
|
-
|
|
56141
|
-
spin
|
|
56142
|
-
|
|
56143
|
-
|
|
56144
|
-
|
|
56145
|
-
|
|
56227
|
+
let startedLocalSpinner = false;
|
|
56228
|
+
let spin = null;
|
|
56229
|
+
if (!ProcessAnimation.hasActive()) {
|
|
56230
|
+
spin = new ProcessAnimation();
|
|
56231
|
+
spin.start();
|
|
56232
|
+
startedLocalSpinner = true;
|
|
56233
|
+
}
|
|
56234
|
+
let resp;
|
|
56146
56235
|
try {
|
|
56147
|
-
|
|
56148
|
-
|
|
56236
|
+
resp = await executeChat([
|
|
56237
|
+
{ role: "system", content: system },
|
|
56238
|
+
{ role: "user", content: user }
|
|
56239
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
56240
|
+
} finally {
|
|
56241
|
+
if (startedLocalSpinner && spin) {
|
|
56242
|
+
try {
|
|
56243
|
+
spin.stop();
|
|
56244
|
+
} catch {
|
|
56245
|
+
}
|
|
56246
|
+
}
|
|
56149
56247
|
}
|
|
56150
56248
|
const raw = (resp?.output || "").trim();
|
|
56151
56249
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
@@ -56199,12 +56297,25 @@ function trackCodeFallback(event) {
|
|
|
56199
56297
|
}
|
|
56200
56298
|
}
|
|
56201
56299
|
async function orchestrate(request, opts) {
|
|
56300
|
+
const dbg = (...a) => {
|
|
56301
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
56302
|
+
try {
|
|
56303
|
+
console.log("[DEBUG/orchestrator]", ...a);
|
|
56304
|
+
} catch {
|
|
56305
|
+
}
|
|
56306
|
+
}
|
|
56307
|
+
};
|
|
56202
56308
|
const profile = await scanRepo(opts.root);
|
|
56309
|
+
dbg("start", { root: opts.root, flags: {
|
|
56310
|
+
...opts.flags
|
|
56311
|
+
/* redact */
|
|
56312
|
+
}, attachedFiles: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0 });
|
|
56203
56313
|
const initial = [];
|
|
56204
56314
|
const fallbackNotices = [];
|
|
56205
56315
|
const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
|
|
56206
56316
|
const explicitFilesRaw = parseExplicitFilenames(request);
|
|
56207
56317
|
const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
|
|
56318
|
+
dbg("explicitFiles", { raw: explicitFilesRaw, resolved: explicitFiles });
|
|
56208
56319
|
const explicitAbsMap = /* @__PURE__ */ Object.create(null);
|
|
56209
56320
|
if (explicitFiles.length > 0) {
|
|
56210
56321
|
const pathMod = await import('path');
|
|
@@ -56216,12 +56327,14 @@ async function orchestrate(request, opts) {
|
|
|
56216
56327
|
explicitFiles,
|
|
56217
56328
|
attachmentsCount: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0
|
|
56218
56329
|
});
|
|
56330
|
+
dbg("intent", { isEditIntent });
|
|
56219
56331
|
let editTargets = explicitFiles;
|
|
56220
56332
|
if (isEditIntent && editTargets.length === 0) {
|
|
56221
56333
|
try {
|
|
56222
56334
|
const repoFiles = await getRepoFiles(opts.root);
|
|
56223
56335
|
const llmTargets = await llmSelectEditTargets(opts.root, request, repoFiles);
|
|
56224
56336
|
editTargets = llmTargets;
|
|
56337
|
+
dbg("llmSelectEditTargets", { editTargets });
|
|
56225
56338
|
} catch {
|
|
56226
56339
|
}
|
|
56227
56340
|
}
|
|
@@ -56233,6 +56346,7 @@ async function orchestrate(request, opts) {
|
|
|
56233
56346
|
maxAttachments: opts.flags.maxAttachments || 50,
|
|
56234
56347
|
allowDotfiles: !!opts.flags.allowDotfiles
|
|
56235
56348
|
});
|
|
56349
|
+
dbg("attachment.map", { mappedCount: mapRes.mapped.length, warnings: mapRes.warnings });
|
|
56236
56350
|
mapRes.warnings.slice();
|
|
56237
56351
|
for (const m2 of mapRes.mapped) {
|
|
56238
56352
|
initial.push({
|
|
@@ -56244,7 +56358,7 @@ async function orchestrate(request, opts) {
|
|
|
56244
56358
|
});
|
|
56245
56359
|
}
|
|
56246
56360
|
}
|
|
56247
|
-
const onlyAttached = !!opts.flags.onlyAttached;
|
|
56361
|
+
const onlyAttached = !!(opts.flags.onlyAttached && Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0);
|
|
56248
56362
|
if (!onlyAttached) {
|
|
56249
56363
|
let codeOutput = "";
|
|
56250
56364
|
if (process.env.MARIA_E2E_FAKE_CODE === "1") {
|
|
@@ -56264,10 +56378,37 @@ async function orchestrate(request, opts) {
|
|
|
56264
56378
|
"[BEGIN file: path]\n<content>\n[END]",
|
|
56265
56379
|
"Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
|
|
56266
56380
|
].join("\n");
|
|
56381
|
+
let targetFilesAbs = [];
|
|
56382
|
+
try {
|
|
56383
|
+
const pathMod = await import('path');
|
|
56384
|
+
const fromExplicit = Array.isArray(explicitFiles) && explicitFiles.length > 0 ? explicitFiles.map((rel) => explicitAbsMap[rel] || pathMod.join(opts.root, rel)) : [];
|
|
56385
|
+
const fromEditTargets = Array.isArray(editTargets) && editTargets.length > 0 ? editTargets.map((rel) => pathMod.isAbsolute(rel) ? rel : pathMod.join(opts.root, rel)) : [];
|
|
56386
|
+
const seen = /* @__PURE__ */ new Set();
|
|
56387
|
+
for (const p of [...fromExplicit, ...fromEditTargets]) {
|
|
56388
|
+
const norm = (p || "").replace(/\\/g, "/");
|
|
56389
|
+
if (!norm) continue;
|
|
56390
|
+
if (seen.has(norm)) continue;
|
|
56391
|
+
seen.add(norm);
|
|
56392
|
+
targetFilesAbs.push(norm);
|
|
56393
|
+
}
|
|
56394
|
+
} catch {
|
|
56395
|
+
}
|
|
56396
|
+
const targetDirsAbs = Array.from(new Set(targetFilesAbs.map((p) => p.split("/").slice(0, -1).join("/")).filter(Boolean)));
|
|
56397
|
+
const targetFilesSection = targetFilesAbs.length > 0 ? ["// TARGET FILES (absolute):", ...targetFilesAbs.map((p) => `// - ${p}`)].join("\n") : "";
|
|
56398
|
+
const targetDirsSection = targetDirsAbs.length > 0 ? ["// TARGET DIRECTORIES (absolute):", ...targetDirsAbs.map((p) => `// - ${p}`)].join("\n") : "";
|
|
56267
56399
|
const requestPreamble = isEditIntent ? [
|
|
56268
|
-
"// EDIT MODE:
|
|
56269
|
-
"//
|
|
56270
|
-
|
|
56400
|
+
"// EDIT MODE RULES:",
|
|
56401
|
+
"// 1) Read the entire target file(s) BEFORE making changes. Assume omitted lines must remain exactly as-is.",
|
|
56402
|
+
"// 2) Preserve unrelated content and formatting (indentation, EOLs, imports order, license headers).",
|
|
56403
|
+
"// 3) Do NOT rename, move, or delete files unless explicitly requested.",
|
|
56404
|
+
"// 4) Apply the MINIMAL necessary change to achieve the request. Avoid broad refactors.",
|
|
56405
|
+
"// 5) When returning a whole file, keep everything identical except for the exact lines you changed.",
|
|
56406
|
+
"// 6) Do NOT introduce unrelated edits or code style churn.",
|
|
56407
|
+
"// 7) Edit ONLY the files listed under TARGET FILES or inside TARGET DIRECTORIES unless explicitly instructed otherwise.",
|
|
56408
|
+
"// 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.",
|
|
56409
|
+
editContext ? "// Current file snapshots provided below." : "",
|
|
56410
|
+
targetFilesSection,
|
|
56411
|
+
targetDirsSection
|
|
56271
56412
|
].filter(Boolean).join("\n") : "";
|
|
56272
56413
|
const enriched = `${FILE_FORMAT_INSTRUCTIONS}
|
|
56273
56414
|
|
|
@@ -56275,6 +56416,7 @@ ${requestPreamble}
|
|
|
56275
56416
|
${request}
|
|
56276
56417
|
|
|
56277
56418
|
${editContext}`;
|
|
56419
|
+
dbg("executeCode.prompt.head", enriched.slice(0, 1400));
|
|
56278
56420
|
const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
|
|
56279
56421
|
name: f3.originalName,
|
|
56280
56422
|
path: f3.pathHint,
|
|
@@ -56308,6 +56450,68 @@ ${editContext}`;
|
|
|
56308
56450
|
} catch {
|
|
56309
56451
|
}
|
|
56310
56452
|
}
|
|
56453
|
+
try {
|
|
56454
|
+
const fs52 = await import('fs/promises');
|
|
56455
|
+
const pathMod = await import('path');
|
|
56456
|
+
const dirCandidates = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
56457
|
+
const maxFilesPerDir = 80;
|
|
56458
|
+
for (const raw2 of dirCandidates) {
|
|
56459
|
+
try {
|
|
56460
|
+
const normalized2 = raw2.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
56461
|
+
const abs = pathMod.isAbsolute(normalized2) ? normalized2 : pathMod.join(opts.root, normalized2);
|
|
56462
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
56463
|
+
if (!st || !st.isDirectory()) continue;
|
|
56464
|
+
const collected = [];
|
|
56465
|
+
const walk2 = async (d) => {
|
|
56466
|
+
if (collected.length >= maxFilesPerDir) return;
|
|
56467
|
+
let entries = [];
|
|
56468
|
+
try {
|
|
56469
|
+
entries = await fs52.readdir(d, { withFileTypes: true });
|
|
56470
|
+
} catch {
|
|
56471
|
+
return;
|
|
56472
|
+
}
|
|
56473
|
+
for (const e2 of entries) {
|
|
56474
|
+
const name2 = e2.name;
|
|
56475
|
+
if (name2 === ".git" || name2 === "node_modules" || name2 === "dist" || name2 === "build" || name2 === ".maria") continue;
|
|
56476
|
+
const full = pathMod.join(d, name2);
|
|
56477
|
+
if (e2.isDirectory()) {
|
|
56478
|
+
await walk2(full);
|
|
56479
|
+
if (collected.length >= maxFilesPerDir) break;
|
|
56480
|
+
continue;
|
|
56481
|
+
}
|
|
56482
|
+
collected.push(full);
|
|
56483
|
+
if (collected.length >= maxFilesPerDir) break;
|
|
56484
|
+
}
|
|
56485
|
+
};
|
|
56486
|
+
await walk2(abs);
|
|
56487
|
+
for (const f3 of collected) {
|
|
56488
|
+
try {
|
|
56489
|
+
const key = f3.toLowerCase();
|
|
56490
|
+
if (attachedPathSet.has(key)) continue;
|
|
56491
|
+
const buf = await fs52.readFile(f3);
|
|
56492
|
+
const head2 = buf.subarray(0, Math.min(buf.length, 4096));
|
|
56493
|
+
let binaryLike = false;
|
|
56494
|
+
for (let i2 = 0; i2 < head2.length; i2++) {
|
|
56495
|
+
if (head2[i2] === 0) {
|
|
56496
|
+
binaryLike = true;
|
|
56497
|
+
break;
|
|
56498
|
+
}
|
|
56499
|
+
}
|
|
56500
|
+
if (binaryLike) continue;
|
|
56501
|
+
const sample = buf.subarray(0, Math.min(buf.length, 8192)).toString("utf8");
|
|
56502
|
+
const printable = sample.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
56503
|
+
const ratio = sample.length === 0 ? 0 : printable.length / sample.length;
|
|
56504
|
+
if (ratio < 0.6 && sample.length > 0) continue;
|
|
56505
|
+
pathAttachments.push({ name: pathMod.basename(f3), path: f3, mime: "text/plain", data_base64: buf.toString("base64") });
|
|
56506
|
+
attachedPathSet.add(key);
|
|
56507
|
+
} catch {
|
|
56508
|
+
}
|
|
56509
|
+
}
|
|
56510
|
+
} catch {
|
|
56511
|
+
}
|
|
56512
|
+
}
|
|
56513
|
+
} catch {
|
|
56514
|
+
}
|
|
56311
56515
|
if (isEditIntent && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
56312
56516
|
try {
|
|
56313
56517
|
const fs52 = await import('fs/promises');
|
|
@@ -56362,9 +56566,34 @@ ${editContext}`;
|
|
|
56362
56566
|
hydratedCtx.push(...ctxAttachments);
|
|
56363
56567
|
}
|
|
56364
56568
|
}
|
|
56365
|
-
const
|
|
56569
|
+
const pathMod2 = await import('path');
|
|
56570
|
+
const normalizeMime = (p, m2) => {
|
|
56571
|
+
if (!p) return m2 || "text/plain";
|
|
56572
|
+
const ext2 = pathMod2.extname(p).toLowerCase();
|
|
56573
|
+
if (m2 && m2 !== "application/octet-stream") return m2;
|
|
56574
|
+
if (ext2 === ".pdf") return "application/pdf";
|
|
56575
|
+
if (ext2 === ".png") return "image/png";
|
|
56576
|
+
if (ext2 === ".jpg" || ext2 === ".jpeg") return "image/jpeg";
|
|
56577
|
+
if (ext2 === ".webp") return "image/webp";
|
|
56578
|
+
if (ext2 === ".gif") return "image/gif";
|
|
56579
|
+
if (ext2 === ".bmp") return "image/bmp";
|
|
56580
|
+
if (ext2 === ".svg") return "image/svg+xml";
|
|
56581
|
+
if (ext2 === ".tif" || ext2 === ".tiff") return "image/tiff";
|
|
56582
|
+
if (ext2 === ".heic") return "image/heic";
|
|
56583
|
+
if (ext2 === ".heif") return "image/heif";
|
|
56584
|
+
return "text/plain";
|
|
56585
|
+
};
|
|
56586
|
+
const allAttachments = (hydratedCtx.length ? hydratedCtx : ctxAttachments).concat(pathAttachments).map((a) => ({
|
|
56587
|
+
...a,
|
|
56588
|
+
mime: normalizeMime(a.path, a.mime)
|
|
56589
|
+
}));
|
|
56366
56590
|
const response = await executeCode(allAttachments.length > 0 ? { prompt: enriched, provider: "google", model: "gemini-2.5-flash", attachments: allAttachments } : enriched);
|
|
56591
|
+
try {
|
|
56592
|
+
dbg("executeCode.attachments.meta", { ctx: (hydratedCtx.length ? hydratedCtx : ctxAttachments).length, path: pathAttachments.length });
|
|
56593
|
+
} catch {
|
|
56594
|
+
}
|
|
56367
56595
|
const raw = (response.output || response?.data?.content || "").trim();
|
|
56596
|
+
dbg("executeCode.output.head", raw.slice(0, 1200));
|
|
56368
56597
|
if (!raw) {
|
|
56369
56598
|
return {
|
|
56370
56599
|
ok: false,
|
|
@@ -56402,6 +56631,7 @@ ${editContext}`;
|
|
|
56402
56631
|
codeOutput = outcome.data?.output || "";
|
|
56403
56632
|
}
|
|
56404
56633
|
const blocks = extractBlocks(codeOutput);
|
|
56634
|
+
dbg("extractBlocks.count", blocks.length);
|
|
56405
56635
|
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
56406
56636
|
const mapped = /* @__PURE__ */ new Set();
|
|
56407
56637
|
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
@@ -56439,23 +56669,49 @@ ${editContext}`;
|
|
|
56439
56669
|
} else {
|
|
56440
56670
|
try {
|
|
56441
56671
|
const repoFiles = await getRepoFiles(opts.root);
|
|
56442
|
-
|
|
56672
|
+
let dirHints = [];
|
|
56673
|
+
try {
|
|
56674
|
+
const fs52 = await import('fs/promises');
|
|
56675
|
+
const pathMod = await import('path');
|
|
56676
|
+
const rawDirs = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
56677
|
+
for (const raw of rawDirs) {
|
|
56678
|
+
try {
|
|
56679
|
+
const normalized2 = raw.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
56680
|
+
const abs = pathMod.isAbsolute(normalized2) ? normalized2 : pathMod.join(opts.root, normalized2);
|
|
56681
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
56682
|
+
if (!st || !st.isDirectory()) continue;
|
|
56683
|
+
const rel = pathMod.relative(opts.root, abs).replace(/\\/g, "/").replace(/^\/+/, "");
|
|
56684
|
+
if (!rel || rel.startsWith("..")) continue;
|
|
56685
|
+
dirHints.push(rel);
|
|
56686
|
+
} catch {
|
|
56687
|
+
}
|
|
56688
|
+
}
|
|
56689
|
+
if (dirHints.length === 0 && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
56690
|
+
dirHints = Array.from(new Set(editTargets.map((p) => (p || "").replace(/^\/+/, "").split("/").slice(0, -1).join("/")).filter(Boolean)));
|
|
56691
|
+
}
|
|
56692
|
+
} catch {
|
|
56693
|
+
}
|
|
56694
|
+
const decisions = await llmMapBlocksBatch(opts.root, request, blocks, repoFiles, { dirHints });
|
|
56695
|
+
dbg("llmMapBlocksBatch.decisions", decisions);
|
|
56443
56696
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56444
56697
|
const b = blocks[i2];
|
|
56445
56698
|
const d = decisions[i2] || { action: "create", path: suggestName2(request, b.language, i2) };
|
|
56446
|
-
|
|
56699
|
+
const hinted = b.filename && String(b.filename).trim() || extractFilenameHintFromComment(b.code);
|
|
56700
|
+
const finalPath = hinted && hinted.trim() || d.path;
|
|
56701
|
+
if (d.action === "modify" && repoFiles.includes(finalPath)) {
|
|
56447
56702
|
const lang = languageFromExt(d.path.replace(/^.*(\.[a-z0-9]+)$/i, "$1"));
|
|
56448
|
-
initial.push({ path:
|
|
56703
|
+
initial.push({ path: finalPath, kind: "source", action: "modify", description: "Modify existing file", language: lang, preview: b.code, noNormalize: true });
|
|
56449
56704
|
} else {
|
|
56450
|
-
const pth = d.path || suggestName2(request, b.language, i2);
|
|
56451
|
-
initial.push({ path: pth, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code });
|
|
56705
|
+
const pth = finalPath && finalPath.trim() || d.path || suggestName2(request, b.language, i2);
|
|
56706
|
+
initial.push({ path: pth, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code, noNormalize: true });
|
|
56452
56707
|
}
|
|
56453
56708
|
}
|
|
56454
56709
|
} catch {
|
|
56455
56710
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56456
56711
|
const b = blocks[i2];
|
|
56457
|
-
const
|
|
56458
|
-
|
|
56712
|
+
const hinted = b.filename && String(b.filename).trim() || extractFilenameHintFromComment(b.code);
|
|
56713
|
+
const path65 = hinted && hinted.trim() || suggestName2(request, b.language, i2);
|
|
56714
|
+
initial.push({ path: path65, kind: "source", action: "create", description: describe2(b.language, ""), language: b.language, preview: b.code, noNormalize: true });
|
|
56459
56715
|
}
|
|
56460
56716
|
}
|
|
56461
56717
|
}
|
|
@@ -56471,13 +56727,13 @@ ${editContext}`;
|
|
|
56471
56727
|
}
|
|
56472
56728
|
}
|
|
56473
56729
|
}
|
|
56474
|
-
if (explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
56730
|
+
if (!isEditIntent && explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
56475
56731
|
for (const f3 of explicitFiles) {
|
|
56476
56732
|
initial.push(scaffoldForFilename(f3, explicitFiles));
|
|
56477
56733
|
}
|
|
56478
56734
|
}
|
|
56479
56735
|
const normalized = await normalizePlans(
|
|
56480
|
-
initial.map((p) => p.noNormalize ? p : p),
|
|
56736
|
+
initial.map((p) => p.noNormalize ? { ...p } : p),
|
|
56481
56737
|
{ root: opts.root }
|
|
56482
56738
|
);
|
|
56483
56739
|
try {
|
|
@@ -56502,11 +56758,26 @@ ${editContext}`;
|
|
|
56502
56758
|
}
|
|
56503
56759
|
} catch {
|
|
56504
56760
|
}
|
|
56505
|
-
|
|
56761
|
+
let filtered = normalized;
|
|
56762
|
+
if (isEditIntent) {
|
|
56763
|
+
const keepCreates = !!opts.flags.onlyAttached;
|
|
56764
|
+
if (!keepCreates) {
|
|
56765
|
+
filtered = normalized.map((f3) => f3.action === "create" ? { ...f3, action: "skip" } : f3);
|
|
56766
|
+
}
|
|
56767
|
+
}
|
|
56768
|
+
const baseFlags = { ...opts.flags };
|
|
56769
|
+
const effectiveFlags = {
|
|
56770
|
+
...baseFlags,
|
|
56771
|
+
maxFiles: opts.flags.maxFiles,
|
|
56772
|
+
interactive: !!opts.flags.interactive,
|
|
56773
|
+
// Force yes when editing; if baseFlags.yes is already true, keep it true
|
|
56774
|
+
yes: baseFlags?.yes === true || isEditIntent
|
|
56775
|
+
};
|
|
56776
|
+
const validated = await validatePlan(filtered, { root: opts.root, profile, flags: effectiveFlags });
|
|
56506
56777
|
const hasAnyModify = validated.files.some((f3) => f3.action === "modify") || isEditIntent;
|
|
56507
56778
|
const outputMode = !opts.flags.hideCode && hasAnyModify ? "diff" : resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
|
|
56508
56779
|
const skippedSetForLookup = new Set(validated.skipped || []);
|
|
56509
|
-
const skippedPlans =
|
|
56780
|
+
const skippedPlans = filtered.filter((f3) => skippedSetForLookup.has(f3.path));
|
|
56510
56781
|
const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
|
|
56511
56782
|
const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
|
|
56512
56783
|
const summary = summarizePlan(displayFiles);
|
|
@@ -56699,6 +56970,21 @@ function extractBlocks(content) {
|
|
|
56699
56970
|
if (blocks.length === 0 && looksLikeCode(content)) blocks.push({ language: detectLanguage(content), code: content.trim() });
|
|
56700
56971
|
return blocks;
|
|
56701
56972
|
}
|
|
56973
|
+
function extractFilenameHintFromComment(code) {
|
|
56974
|
+
try {
|
|
56975
|
+
const first = (code.split(/\r?\n/, 1)[0] || "").trim();
|
|
56976
|
+
let m2 = first.match(/^\/\/\s*filename:\s*(.+)$/i);
|
|
56977
|
+
if (m2?.[1]) return m2[1].trim();
|
|
56978
|
+
m2 = first.match(/^#\s*filename:\s*(.+)$/i);
|
|
56979
|
+
if (m2?.[1]) return m2[1].trim();
|
|
56980
|
+
m2 = first.match(/^<!--\s*filename:\s*(.+?)\s*-->$/i);
|
|
56981
|
+
if (m2?.[1]) return m2[1].trim();
|
|
56982
|
+
m2 = first.match(/^\/\*\s*filename:\s*(.+?)\s*\*\/$/i);
|
|
56983
|
+
if (m2?.[1]) return m2[1].trim();
|
|
56984
|
+
} catch {
|
|
56985
|
+
}
|
|
56986
|
+
return void 0;
|
|
56987
|
+
}
|
|
56702
56988
|
function looksLikeCode(s2) {
|
|
56703
56989
|
return ["function ", "const ", "let ", "var ", "class ", "def ", "import ", "export "].some((k) => s2.includes(k));
|
|
56704
56990
|
}
|
|
@@ -56856,48 +57142,100 @@ function parseExplicitFilenames(request) {
|
|
|
56856
57142
|
return out;
|
|
56857
57143
|
}
|
|
56858
57144
|
async function detectEditIntentLLM(root, request, ctx2) {
|
|
57145
|
+
let existingDirs = [];
|
|
57146
|
+
let existingFiles = [];
|
|
57147
|
+
let anyExistingPathMentioned = false;
|
|
56859
57148
|
try {
|
|
57149
|
+
const fs52 = await import('fs/promises');
|
|
57150
|
+
const pathMod = await import('path');
|
|
57151
|
+
const rawPaths = Array.from(new Set(String(request).match(/[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/g) || []));
|
|
57152
|
+
existingDirs = [];
|
|
57153
|
+
existingFiles = [];
|
|
57154
|
+
for (const raw2 of rawPaths) {
|
|
57155
|
+
try {
|
|
57156
|
+
const normalized = raw2.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
57157
|
+
const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(root, normalized);
|
|
57158
|
+
const st = await fs52.stat(abs).catch(() => null);
|
|
57159
|
+
if (!st) continue;
|
|
57160
|
+
anyExistingPathMentioned = true;
|
|
57161
|
+
const rel = pathMod.relative(root, abs).replace(/\\/g, "/");
|
|
57162
|
+
if (!rel || rel.startsWith("..")) continue;
|
|
57163
|
+
if (st.isDirectory()) existingDirs.push(rel);
|
|
57164
|
+
else if (st.isFile()) existingFiles.push(rel);
|
|
57165
|
+
} catch {
|
|
57166
|
+
}
|
|
57167
|
+
}
|
|
56860
57168
|
const repoFiles = await getRepoFiles(root);
|
|
56861
|
-
|
|
57169
|
+
let scope = [];
|
|
57170
|
+
if (existingDirs.length > 0) {
|
|
57171
|
+
const dirSet = existingDirs.map((d) => d.replace(/\\/g, "/").replace(/^\/+/, "").toLowerCase());
|
|
57172
|
+
scope = repoFiles.filter((p) => dirSet.some((d) => p.toLowerCase().startsWith(d + "/")));
|
|
57173
|
+
} else {
|
|
57174
|
+
scope = repoFiles;
|
|
57175
|
+
}
|
|
56862
57176
|
const headSnippets = [];
|
|
56863
|
-
for (const p of
|
|
57177
|
+
for (const p of scope) {
|
|
56864
57178
|
const h2 = await readHeadTail(root, p, 5);
|
|
56865
57179
|
headSnippets.push(`- ${p}
|
|
56866
57180
|
${h2.head}`);
|
|
56867
57181
|
}
|
|
56868
57182
|
const system = [
|
|
56869
|
-
"
|
|
56870
|
-
"
|
|
56871
|
-
"
|
|
56872
|
-
"
|
|
56873
|
-
"
|
|
56874
|
-
"
|
|
56875
|
-
"
|
|
56876
|
-
'Return JSON: { "intent": "EDIT_EXISTING" | "CREATE_NEW" }
|
|
57183
|
+
"You classify the intent for a code operation in an existing repository.",
|
|
57184
|
+
"Choose strictly one: EDIT_EXISTING (modify existing files) or CREATE_NEW (generate a new project/files).",
|
|
57185
|
+
"Decision rules (apply in order):",
|
|
57186
|
+
"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.",
|
|
57187
|
+
"2) Wording like fix/improve/update/change/patch/make it work/enable X implies EDIT_EXISTING.",
|
|
57188
|
+
"3) Wording like create/new project/scaffold/from scratch/template implies CREATE_NEW.",
|
|
57189
|
+
"4) If attachments or explicit file paths are present, that increases likelihood of EDIT_EXISTING.",
|
|
57190
|
+
'Return ONLY compact JSON: { "intent": "EDIT_EXISTING" | "CREATE_NEW" }.'
|
|
56877
57191
|
].join("\n");
|
|
57192
|
+
const evidence = {
|
|
57193
|
+
explicitFilesCount: (ctx2.explicitFiles || []).length,
|
|
57194
|
+
attachmentsCount: ctx2.attachmentsCount || 0,
|
|
57195
|
+
existingDirCount: existingDirs.length,
|
|
57196
|
+
existingFileMentions: existingFiles.length,
|
|
57197
|
+
existingDirs,
|
|
57198
|
+
existingFiles
|
|
57199
|
+
};
|
|
56878
57200
|
const user = [
|
|
56879
57201
|
`Request: ${request}`,
|
|
56880
|
-
`
|
|
56881
|
-
|
|
56882
|
-
"Repo snapshot (paths with file heads):",
|
|
57202
|
+
`Evidence: ${JSON.stringify(evidence)}`,
|
|
57203
|
+
"Repo snapshot (trimmed):",
|
|
56883
57204
|
headSnippets.join("\n\n")
|
|
56884
57205
|
].join("\n\n");
|
|
56885
|
-
|
|
56886
|
-
|
|
56887
|
-
|
|
56888
|
-
|
|
56889
|
-
|
|
56890
|
-
|
|
57206
|
+
if (existingDirs.length > 0 || existingFiles.length > 0 || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0) {
|
|
57207
|
+
return true;
|
|
57208
|
+
}
|
|
57209
|
+
let startedLocalSpinner = false;
|
|
57210
|
+
let spin1 = null;
|
|
57211
|
+
if (!ProcessAnimation.hasActive()) {
|
|
57212
|
+
spin1 = new ProcessAnimation();
|
|
57213
|
+
spin1.start();
|
|
57214
|
+
startedLocalSpinner = true;
|
|
57215
|
+
}
|
|
57216
|
+
let resp;
|
|
56891
57217
|
try {
|
|
56892
|
-
|
|
56893
|
-
|
|
57218
|
+
resp = await executeChat([
|
|
57219
|
+
{ role: "system", content: system },
|
|
57220
|
+
{ role: "user", content: user }
|
|
57221
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
57222
|
+
} finally {
|
|
57223
|
+
if (startedLocalSpinner && spin1) {
|
|
57224
|
+
try {
|
|
57225
|
+
spin1.stop();
|
|
57226
|
+
} catch {
|
|
57227
|
+
}
|
|
57228
|
+
}
|
|
56894
57229
|
}
|
|
56895
57230
|
const raw = (resp?.output || "").trim();
|
|
56896
57231
|
const jsonText = extractJsonSafe(raw, "object") || raw;
|
|
56897
57232
|
const parsed = JSON.parse(jsonText);
|
|
57233
|
+
if (existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned || ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0) {
|
|
57234
|
+
return true;
|
|
57235
|
+
}
|
|
56898
57236
|
return parsed?.intent === "EDIT_EXISTING";
|
|
56899
57237
|
} catch {
|
|
56900
|
-
return ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0;
|
|
57238
|
+
return ctx2.explicitFiles && ctx2.explicitFiles.length > 0 || ctx2.attachmentsCount > 0 || existingDirs.length > 0 || existingFiles.length > 0 || anyExistingPathMentioned;
|
|
56901
57239
|
}
|
|
56902
57240
|
}
|
|
56903
57241
|
function sanitizeFolderName(name2) {
|
|
@@ -57065,7 +57403,7 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
57065
57403
|
const chat = await executeChat([
|
|
57066
57404
|
{ role: "system", content: system },
|
|
57067
57405
|
{ role: "user", content: user }
|
|
57068
|
-
]);
|
|
57406
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
57069
57407
|
const raw = (chat.output || "").trim();
|
|
57070
57408
|
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
57071
57409
|
return pick.replace(/^\/+/, "");
|
|
@@ -57240,7 +57578,16 @@ var init_code_command = __esm({
|
|
|
57240
57578
|
}
|
|
57241
57579
|
];
|
|
57242
57580
|
async execute(commandArgs, context2) {
|
|
57581
|
+
const debug = (...args2) => {
|
|
57582
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
57583
|
+
try {
|
|
57584
|
+
console.log("[DEBUG/code]", ...args2);
|
|
57585
|
+
} catch {
|
|
57586
|
+
}
|
|
57587
|
+
}
|
|
57588
|
+
};
|
|
57243
57589
|
const request = await this.ensureLanguageDefaults(commandArgs.raw.join(" ").trim());
|
|
57590
|
+
debug("request", request);
|
|
57244
57591
|
if (!request) {
|
|
57245
57592
|
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.");
|
|
57246
57593
|
}
|
|
@@ -57252,6 +57599,7 @@ var init_code_command = __esm({
|
|
|
57252
57599
|
const explicitDry = commandArgs.raw.includes("--dry-run");
|
|
57253
57600
|
const explicitOutput = commandArgs.raw.some((x2) => x2.startsWith("--output") || x2 === "--verbose" || x2 === "-v");
|
|
57254
57601
|
const explicitPreview = commandArgs.raw.some((x2) => x2.startsWith("--preview-lines"));
|
|
57602
|
+
const explicitOnlyAttached = commandArgs.raw.includes("--only-attached");
|
|
57255
57603
|
const preSpin = new ProcessAnimation();
|
|
57256
57604
|
preSpin.start();
|
|
57257
57605
|
let inferred = {};
|
|
@@ -57263,6 +57611,8 @@ var init_code_command = __esm({
|
|
|
57263
57611
|
} catch {
|
|
57264
57612
|
}
|
|
57265
57613
|
}
|
|
57614
|
+
debug("inferCodeArgs.raw", rawText);
|
|
57615
|
+
debug("inferCodeArgs.result", inferred);
|
|
57266
57616
|
if (!explicitPlan && !explicitDry) {
|
|
57267
57617
|
if (typeof inferred.planOnly === "boolean") opts.planOnly = inferred.planOnly;
|
|
57268
57618
|
if (typeof inferred.dryRun === "boolean") opts.dryRun = inferred.dryRun;
|
|
@@ -57273,6 +57623,9 @@ var init_code_command = __esm({
|
|
|
57273
57623
|
if (!explicitPreview && typeof inferred.previewLines === "number") {
|
|
57274
57624
|
opts.previewLines = inferred.previewLines;
|
|
57275
57625
|
}
|
|
57626
|
+
if (!explicitOnlyAttached && typeof inferred.onlyAttached === "boolean") {
|
|
57627
|
+
opts.onlyAttached = inferred.onlyAttached;
|
|
57628
|
+
}
|
|
57276
57629
|
} catch {
|
|
57277
57630
|
}
|
|
57278
57631
|
if (opts.planOnly) {
|
|
@@ -57287,13 +57640,27 @@ var init_code_command = __esm({
|
|
|
57287
57640
|
const root = opts.root || process.cwd();
|
|
57288
57641
|
const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
|
|
57289
57642
|
const attachments = await this.collectAttachedFiles(context2).catch(() => []);
|
|
57643
|
+
try {
|
|
57644
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
57645
|
+
const attView = attachments.map((a) => ({ name: a.originalName, size: a.size, mime: a.mime, pathHint: a.pathHint })).slice(0, 50);
|
|
57646
|
+
console.log("[DEBUG/code] collected.attachments", { count: attachments.length, attachments: attView });
|
|
57647
|
+
}
|
|
57648
|
+
} catch {
|
|
57649
|
+
}
|
|
57290
57650
|
const abort = new AbortController();
|
|
57291
57651
|
const onSigint = () => abort.abort();
|
|
57292
57652
|
process.once("SIGINT", onSigint);
|
|
57293
|
-
|
|
57294
|
-
spinner
|
|
57653
|
+
let startedLocalSpinner = false;
|
|
57654
|
+
let spinner = null;
|
|
57655
|
+
if (!ProcessAnimation.hasActive()) {
|
|
57656
|
+
spinner = new ProcessAnimation();
|
|
57657
|
+
spinner.start();
|
|
57658
|
+
startedLocalSpinner = true;
|
|
57659
|
+
}
|
|
57295
57660
|
try {
|
|
57296
|
-
const
|
|
57661
|
+
const effectiveOnlyAttached = opts.onlyAttached && attachments.length > 0;
|
|
57662
|
+
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 });
|
|
57663
|
+
debug("orchestrate.summaryLines.head", Array.isArray(res?.summaryLines) ? res.summaryLines.slice(0, 10) : []);
|
|
57297
57664
|
if (opts.planOnly) {
|
|
57298
57665
|
const fs52 = await import('fs/promises');
|
|
57299
57666
|
const path65 = await import('path');
|
|
@@ -57346,9 +57713,11 @@ var init_code_command = __esm({
|
|
|
57346
57713
|
const out = Array.isArray(res?.summaryLines) ? res.summaryLines.join("\n") : "";
|
|
57347
57714
|
return this.success(out);
|
|
57348
57715
|
} finally {
|
|
57349
|
-
|
|
57350
|
-
|
|
57351
|
-
|
|
57716
|
+
if (startedLocalSpinner && spinner) {
|
|
57717
|
+
try {
|
|
57718
|
+
spinner.stop();
|
|
57719
|
+
} catch {
|
|
57720
|
+
}
|
|
57352
57721
|
}
|
|
57353
57722
|
process.removeListener("SIGINT", onSigint);
|
|
57354
57723
|
}
|
|
@@ -57471,12 +57840,6 @@ ${pretty}`);
|
|
|
57471
57840
|
if (llmLang) {
|
|
57472
57841
|
const hint2 = (() => {
|
|
57473
57842
|
const l = llmLang.toLowerCase();
|
|
57474
|
-
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
57475
|
-
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
57476
|
-
if (l === "typescript") return "TypeScript";
|
|
57477
|
-
if (l === "javascript") return "JavaScript";
|
|
57478
|
-
if (l === "html") return "HTML";
|
|
57479
|
-
if (l === "css") return "CSS";
|
|
57480
57843
|
return llmLang;
|
|
57481
57844
|
})();
|
|
57482
57845
|
return raw + ` (Use ${hint2})`;
|
|
@@ -57489,7 +57852,7 @@ ${pretty}`);
|
|
|
57489
57852
|
preSpin.start();
|
|
57490
57853
|
const system = [
|
|
57491
57854
|
"You analyze a user's code-generation request.",
|
|
57492
|
-
"Decide if the user explicitly specified a programming language or framework/tooling
|
|
57855
|
+
"Decide if the user explicitly specified a programming language or framework/tooling.",
|
|
57493
57856
|
'Return ONLY compact JSON with shape {"explicitLanguage": boolean, "language"?: string}.',
|
|
57494
57857
|
"Do not add any commentary."
|
|
57495
57858
|
].join("\n");
|
|
@@ -57498,7 +57861,7 @@ ${pretty}`);
|
|
|
57498
57861
|
method: "POST",
|
|
57499
57862
|
body: {
|
|
57500
57863
|
provider: "google",
|
|
57501
|
-
model: "gemini-2.5-flash",
|
|
57864
|
+
model: "gemini-2.5-flash-lite",
|
|
57502
57865
|
taskType: "chat",
|
|
57503
57866
|
prompt: `${system}
|
|
57504
57867
|
|
|
@@ -57543,6 +57906,14 @@ ${user}`
|
|
|
57543
57906
|
if (parsed && parsed.explicitLanguage) return raw;
|
|
57544
57907
|
} catch {
|
|
57545
57908
|
}
|
|
57909
|
+
try {
|
|
57910
|
+
const pathMod = await import('path');
|
|
57911
|
+
const hasPathToken = /[A-Za-z]:\\[^\s"']+|\.?\/?[^\s"']+[\/\\][^\s"']*/.test(raw);
|
|
57912
|
+
if (hasPathToken) {
|
|
57913
|
+
return raw;
|
|
57914
|
+
}
|
|
57915
|
+
} catch {
|
|
57916
|
+
}
|
|
57546
57917
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
57547
57918
|
return raw + hint;
|
|
57548
57919
|
}
|
|
@@ -57552,9 +57923,7 @@ ${user}`
|
|
|
57552
57923
|
const system = [
|
|
57553
57924
|
"You are a programming language classifier.",
|
|
57554
57925
|
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
57555
|
-
"Respond with ONLY
|
|
57556
|
-
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
57557
|
-
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
57926
|
+
"Respond with ONLY language name(s)"
|
|
57558
57927
|
].join("\n");
|
|
57559
57928
|
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
57560
57929
|
${s2}`).join("\n\n");
|
|
@@ -57563,7 +57932,7 @@ ${s2}`).join("\n\n");
|
|
|
57563
57932
|
method: "POST",
|
|
57564
57933
|
body: {
|
|
57565
57934
|
provider: "google",
|
|
57566
|
-
model: "gemini-2.5-flash",
|
|
57935
|
+
model: "gemini-2.5-flash-lite",
|
|
57567
57936
|
taskType: "chat",
|
|
57568
57937
|
prompt: `${system}
|
|
57569
57938
|
|
|
@@ -57869,64 +58238,6 @@ ${joined}`
|
|
|
57869
58238
|
return false;
|
|
57870
58239
|
}
|
|
57871
58240
|
}
|
|
57872
|
-
/**
|
|
57873
|
-
* Extract code blocks from AI response
|
|
57874
|
-
*/
|
|
57875
|
-
extractCodeBlocks(content) {
|
|
57876
|
-
const blocks = [];
|
|
57877
|
-
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
|
57878
|
-
let match2;
|
|
57879
|
-
while ((match2 = codeBlockRegex.exec(content)) !== null) {
|
|
57880
|
-
blocks.push({
|
|
57881
|
-
language: match2[1] || "javascript",
|
|
57882
|
-
code: match2[2].trim()
|
|
57883
|
-
});
|
|
57884
|
-
}
|
|
57885
|
-
if (blocks.length === 0 && this.looksLikeCode(content)) {
|
|
57886
|
-
blocks.push({
|
|
57887
|
-
code: content.trim(),
|
|
57888
|
-
language: this.detectLanguage(content)
|
|
57889
|
-
});
|
|
57890
|
-
}
|
|
57891
|
-
return blocks;
|
|
57892
|
-
}
|
|
57893
|
-
/**
|
|
57894
|
-
* Check if content looks like code
|
|
57895
|
-
*/
|
|
57896
|
-
looksLikeCode(content) {
|
|
57897
|
-
const codeIndicators = [
|
|
57898
|
-
"function ",
|
|
57899
|
-
"const ",
|
|
57900
|
-
"let ",
|
|
57901
|
-
"var ",
|
|
57902
|
-
"class ",
|
|
57903
|
-
"def ",
|
|
57904
|
-
"import ",
|
|
57905
|
-
"export ",
|
|
57906
|
-
"{",
|
|
57907
|
-
"}",
|
|
57908
|
-
";",
|
|
57909
|
-
"//",
|
|
57910
|
-
"/*"
|
|
57911
|
-
];
|
|
57912
|
-
return codeIndicators.some((indicator) => content.includes(indicator));
|
|
57913
|
-
}
|
|
57914
|
-
/**
|
|
57915
|
-
* Detect programming language from content
|
|
57916
|
-
*/
|
|
57917
|
-
detectLanguage(code) {
|
|
57918
|
-
const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
|
|
57919
|
-
const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
|
|
57920
|
-
const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
|
|
57921
|
-
if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
|
|
57922
|
-
if (code.includes("interface ") || code.includes(": string")) return "typescript";
|
|
57923
|
-
if (code.includes("def ") || code.includes("print(")) return "python";
|
|
57924
|
-
if (code.includes("func ") || code.includes("package main")) return "go";
|
|
57925
|
-
if (code.includes("fn ") || code.includes("let mut")) return "rust";
|
|
57926
|
-
if (code.includes("<?php")) return "php";
|
|
57927
|
-
if (code.includes("#include")) return "cpp";
|
|
57928
|
-
return "javascript";
|
|
57929
|
-
}
|
|
57930
58241
|
/**
|
|
57931
58242
|
* Save code block to file
|
|
57932
58243
|
*/
|
|
@@ -63724,11 +64035,10 @@ var init_clients_safe = __esm({
|
|
|
63724
64035
|
}
|
|
63725
64036
|
});
|
|
63726
64037
|
function createSpinner(text) {
|
|
63727
|
-
let frame = 0;
|
|
63728
64038
|
let active = false;
|
|
63729
|
-
let
|
|
63730
|
-
const
|
|
63731
|
-
const f3 = SPINNER_FRAMES[frame
|
|
64039
|
+
let frame = 0;
|
|
64040
|
+
const renderOnce = () => {
|
|
64041
|
+
const f3 = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
63732
64042
|
process5__namespace.default.stdout.write(`\r ${chalk14__default.default.cyan(f3)} ${text}`);
|
|
63733
64043
|
};
|
|
63734
64044
|
return {
|
|
@@ -63738,13 +64048,11 @@ function createSpinner(text) {
|
|
|
63738
64048
|
start() {
|
|
63739
64049
|
if (active) return;
|
|
63740
64050
|
active = true;
|
|
63741
|
-
|
|
63742
|
-
timer = setInterval(render, 80);
|
|
64051
|
+
renderOnce();
|
|
63743
64052
|
},
|
|
63744
64053
|
stop(symbol = "\u2714") {
|
|
63745
64054
|
if (!active) return;
|
|
63746
64055
|
active = false;
|
|
63747
|
-
if (timer) clearInterval(timer);
|
|
63748
64056
|
const finalSymbol = symbol === "\u2714" ? chalk14__default.default.green(symbol) : symbol === "\u26A0" ? chalk14__default.default.yellow(symbol) : symbol === "\u2716" ? chalk14__default.default.red(symbol) : symbol;
|
|
63749
64057
|
process5__namespace.default.stdout.write(`\r ${finalSymbol} ${text}
|
|
63750
64058
|
`);
|