@bonginkan/maria 4.3.44 → 4.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/READY.manifest.json +1 -1
- package/dist/bin/maria.cjs +460 -149
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +460 -149
- package/dist/cli.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/server/express-server.cjs +8 -5
- package/dist/server/express-server.js +8 -5
- package/dist/server-express.cjs +8 -5
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +1 -1
package/dist/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;
|
|
@@ -49569,7 +49620,10 @@ var init_video_command = __esm({
|
|
|
49569
49620
|
const base = (process.env.MARIA_API_BASE || "https://api.maria-code.ai").replace(/\/$/, "");
|
|
49570
49621
|
const savedPaths = [];
|
|
49571
49622
|
const baseDir = "video";
|
|
49572
|
-
const
|
|
49623
|
+
const rawPrefix = (cli.prompt || "").slice(0, 20).replace(/\s+/g, "_");
|
|
49624
|
+
let promptPrefix = rawPrefix.replace(/[\x00-\x1F<>:"/\\|?*]/g, "_").replace(/[. ]+$/g, "");
|
|
49625
|
+
if (!promptPrefix) promptPrefix = "untitled";
|
|
49626
|
+
if (/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i.test(promptPrefix)) promptPrefix = `${promptPrefix}_`;
|
|
49573
49627
|
const utc = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
49574
49628
|
let idx = 0;
|
|
49575
49629
|
for (const relRaw of filesFromApi) {
|
|
@@ -51295,7 +51349,7 @@ var init_about_command = __esm({
|
|
|
51295
51349
|
async execute(args2, context2) {
|
|
51296
51350
|
const output3 = [];
|
|
51297
51351
|
output3.push("");
|
|
51298
|
-
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"));
|
|
51299
51353
|
output3.push(chalk14__default.default.gray("\u2550".repeat(40)));
|
|
51300
51354
|
output3.push("");
|
|
51301
51355
|
output3.push(chalk14__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -55022,9 +55076,10 @@ function extractFirstJson5(text) {
|
|
|
55022
55076
|
async function inferCodeArgs(rawText) {
|
|
55023
55077
|
const system = [
|
|
55024
55078
|
"You extract structured options for a code command.",
|
|
55025
|
-
'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 }.',
|
|
55026
55080
|
"Decide from the user text whether planOnly or dryRun should be true. Do not explain.",
|
|
55027
|
-
"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."
|
|
55028
55083
|
].join("\n");
|
|
55029
55084
|
const resp = await callAPI("/v1/ai-proxy", {
|
|
55030
55085
|
method: "POST",
|
|
@@ -55045,11 +55100,19 @@ ${rawText}`,
|
|
|
55045
55100
|
} catch {
|
|
55046
55101
|
return {};
|
|
55047
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
|
+
}
|
|
55048
55110
|
const out = {};
|
|
55049
55111
|
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
55050
55112
|
if (typeof parsed.dryRun === "boolean") out.dryRun = parsed.dryRun;
|
|
55051
55113
|
if (typeof parsed.output === "string" && (parsed.output === "names" || parsed.output === "summary" || parsed.output === "detail")) out.output = parsed.output;
|
|
55052
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;
|
|
55053
55116
|
if (out.planOnly) out.dryRun = false;
|
|
55054
55117
|
return out;
|
|
55055
55118
|
}
|
|
@@ -55197,6 +55260,12 @@ var init_FilePlanBuilder = __esm({
|
|
|
55197
55260
|
}
|
|
55198
55261
|
});
|
|
55199
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
|
+
}
|
|
55200
55269
|
const warnings = [];
|
|
55201
55270
|
const skipped = [];
|
|
55202
55271
|
const seenLC = /* @__PURE__ */ new Set();
|
|
@@ -55213,6 +55282,10 @@ async function validatePlan(plans, opts) {
|
|
|
55213
55282
|
}
|
|
55214
55283
|
const safe = [];
|
|
55215
55284
|
for (const fp of outFiltered) {
|
|
55285
|
+
if (fp.action === "skip") {
|
|
55286
|
+
skipped.push(fp.path);
|
|
55287
|
+
continue;
|
|
55288
|
+
}
|
|
55216
55289
|
const rel = fp.path.replace(/^\/+/, "");
|
|
55217
55290
|
if (rel.includes("..")) {
|
|
55218
55291
|
warnings.push(`Path traversal denied: ${fp.path}`);
|
|
@@ -55294,7 +55367,18 @@ async function validatePlan(plans, opts) {
|
|
|
55294
55367
|
}
|
|
55295
55368
|
result.push({ ...fp, action: willModify ? "modify" : "create" });
|
|
55296
55369
|
}
|
|
55297
|
-
|
|
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;
|
|
55298
55382
|
}
|
|
55299
55383
|
async function exists(p) {
|
|
55300
55384
|
try {
|
|
@@ -56088,7 +56172,7 @@ ${h2.head}`);
|
|
|
56088
56172
|
const resp = await executeChat([
|
|
56089
56173
|
{ role: "system", content: system },
|
|
56090
56174
|
{ role: "user", content: user }
|
|
56091
|
-
]);
|
|
56175
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
56092
56176
|
const raw = (resp?.output || "").trim();
|
|
56093
56177
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
56094
56178
|
const arr = JSON.parse(jsonText);
|
|
@@ -56105,7 +56189,7 @@ ${h2.head}`);
|
|
|
56105
56189
|
return [];
|
|
56106
56190
|
}
|
|
56107
56191
|
}
|
|
56108
|
-
async function llmMapBlocksBatch(root, request, blocks, repoFiles) {
|
|
56192
|
+
async function llmMapBlocksBatch(root, request, blocks, repoFiles, opts) {
|
|
56109
56193
|
try {
|
|
56110
56194
|
const candidates = repoFiles.filter((p) => /\.(html|css|js|ts|tsx)$/i.test(p)).slice(0, 120);
|
|
56111
56195
|
const blockSnippets = blocks.slice(0, 20).map((b, i2) => {
|
|
@@ -56123,26 +56207,43 @@ ${head2}
|
|
|
56123
56207
|
${h2.head}`);
|
|
56124
56208
|
}
|
|
56125
56209
|
const system = [
|
|
56126
|
-
"
|
|
56127
|
-
|
|
56128
|
-
"
|
|
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 }].'
|
|
56129
56218
|
].join("\n");
|
|
56130
56219
|
const user = [
|
|
56131
56220
|
`Request: ${request}`,
|
|
56132
56221
|
"Blocks:",
|
|
56133
56222
|
blockSnippets,
|
|
56134
56223
|
"Candidates:",
|
|
56135
|
-
samples.join("\n\n")
|
|
56224
|
+
samples.join("\n\n"),
|
|
56225
|
+
`TargetDirHints: ${(opts?.dirHints || []).join(", ")}`
|
|
56136
56226
|
].join("\n\n");
|
|
56137
|
-
|
|
56138
|
-
spin
|
|
56139
|
-
|
|
56140
|
-
|
|
56141
|
-
|
|
56142
|
-
|
|
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;
|
|
56143
56235
|
try {
|
|
56144
|
-
|
|
56145
|
-
|
|
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
|
+
}
|
|
56146
56247
|
}
|
|
56147
56248
|
const raw = (resp?.output || "").trim();
|
|
56148
56249
|
const jsonText = extractJsonSafe(raw, "array") || raw;
|
|
@@ -56196,12 +56297,25 @@ function trackCodeFallback(event) {
|
|
|
56196
56297
|
}
|
|
56197
56298
|
}
|
|
56198
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
|
+
};
|
|
56199
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 });
|
|
56200
56313
|
const initial = [];
|
|
56201
56314
|
const fallbackNotices = [];
|
|
56202
56315
|
const withNotices = (base) => fallbackNotices.length > 0 ? [...fallbackNotices, ...base] : base;
|
|
56203
56316
|
const explicitFilesRaw = parseExplicitFilenames(request);
|
|
56204
56317
|
const explicitFiles = explicitFilesRaw.length > 0 ? await resolveExplicitPaths(opts.root, explicitFilesRaw, request) : [];
|
|
56318
|
+
dbg("explicitFiles", { raw: explicitFilesRaw, resolved: explicitFiles });
|
|
56205
56319
|
const explicitAbsMap = /* @__PURE__ */ Object.create(null);
|
|
56206
56320
|
if (explicitFiles.length > 0) {
|
|
56207
56321
|
const pathMod = await import('path');
|
|
@@ -56213,12 +56327,14 @@ async function orchestrate(request, opts) {
|
|
|
56213
56327
|
explicitFiles,
|
|
56214
56328
|
attachmentsCount: Array.isArray(opts.attachedFiles) ? opts.attachedFiles.length : 0
|
|
56215
56329
|
});
|
|
56330
|
+
dbg("intent", { isEditIntent });
|
|
56216
56331
|
let editTargets = explicitFiles;
|
|
56217
56332
|
if (isEditIntent && editTargets.length === 0) {
|
|
56218
56333
|
try {
|
|
56219
56334
|
const repoFiles = await getRepoFiles(opts.root);
|
|
56220
56335
|
const llmTargets = await llmSelectEditTargets(opts.root, request, repoFiles);
|
|
56221
56336
|
editTargets = llmTargets;
|
|
56337
|
+
dbg("llmSelectEditTargets", { editTargets });
|
|
56222
56338
|
} catch {
|
|
56223
56339
|
}
|
|
56224
56340
|
}
|
|
@@ -56230,6 +56346,7 @@ async function orchestrate(request, opts) {
|
|
|
56230
56346
|
maxAttachments: opts.flags.maxAttachments || 50,
|
|
56231
56347
|
allowDotfiles: !!opts.flags.allowDotfiles
|
|
56232
56348
|
});
|
|
56349
|
+
dbg("attachment.map", { mappedCount: mapRes.mapped.length, warnings: mapRes.warnings });
|
|
56233
56350
|
mapRes.warnings.slice();
|
|
56234
56351
|
for (const m2 of mapRes.mapped) {
|
|
56235
56352
|
initial.push({
|
|
@@ -56241,7 +56358,7 @@ async function orchestrate(request, opts) {
|
|
|
56241
56358
|
});
|
|
56242
56359
|
}
|
|
56243
56360
|
}
|
|
56244
|
-
const onlyAttached = !!opts.flags.onlyAttached;
|
|
56361
|
+
const onlyAttached = !!(opts.flags.onlyAttached && Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0);
|
|
56245
56362
|
if (!onlyAttached) {
|
|
56246
56363
|
let codeOutput = "";
|
|
56247
56364
|
if (process.env.MARIA_E2E_FAKE_CODE === "1") {
|
|
@@ -56261,10 +56378,37 @@ async function orchestrate(request, opts) {
|
|
|
56261
56378
|
"[BEGIN file: path]\n<content>\n[END]",
|
|
56262
56379
|
"Do not include any prose before/after; no menus/questions/suggestions; start immediately with ``` or [BEGIN file: ...]."
|
|
56263
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") : "";
|
|
56264
56399
|
const requestPreamble = isEditIntent ? [
|
|
56265
|
-
"// EDIT MODE:
|
|
56266
|
-
"//
|
|
56267
|
-
|
|
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
|
|
56268
56412
|
].filter(Boolean).join("\n") : "";
|
|
56269
56413
|
const enriched = `${FILE_FORMAT_INSTRUCTIONS}
|
|
56270
56414
|
|
|
@@ -56272,6 +56416,7 @@ ${requestPreamble}
|
|
|
56272
56416
|
${request}
|
|
56273
56417
|
|
|
56274
56418
|
${editContext}`;
|
|
56419
|
+
dbg("executeCode.prompt.head", enriched.slice(0, 1400));
|
|
56275
56420
|
const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
|
|
56276
56421
|
name: f3.originalName,
|
|
56277
56422
|
path: f3.pathHint,
|
|
@@ -56305,6 +56450,68 @@ ${editContext}`;
|
|
|
56305
56450
|
} catch {
|
|
56306
56451
|
}
|
|
56307
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
|
+
}
|
|
56308
56515
|
if (isEditIntent && Array.isArray(editTargets) && editTargets.length > 0) {
|
|
56309
56516
|
try {
|
|
56310
56517
|
const fs52 = await import('fs/promises');
|
|
@@ -56359,9 +56566,34 @@ ${editContext}`;
|
|
|
56359
56566
|
hydratedCtx.push(...ctxAttachments);
|
|
56360
56567
|
}
|
|
56361
56568
|
}
|
|
56362
|
-
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
|
+
}));
|
|
56363
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
|
+
}
|
|
56364
56595
|
const raw = (response.output || response?.data?.content || "").trim();
|
|
56596
|
+
dbg("executeCode.output.head", raw.slice(0, 1200));
|
|
56365
56597
|
if (!raw) {
|
|
56366
56598
|
return {
|
|
56367
56599
|
ok: false,
|
|
@@ -56399,6 +56631,7 @@ ${editContext}`;
|
|
|
56399
56631
|
codeOutput = outcome.data?.output || "";
|
|
56400
56632
|
}
|
|
56401
56633
|
const blocks = extractBlocks(codeOutput);
|
|
56634
|
+
dbg("extractBlocks.count", blocks.length);
|
|
56402
56635
|
if (explicitFiles.length > 0 || isEditIntent && editTargets.length > 0) {
|
|
56403
56636
|
const mapped = /* @__PURE__ */ new Set();
|
|
56404
56637
|
const targets = explicitFiles.length > 0 ? explicitFiles : editTargets;
|
|
@@ -56436,23 +56669,49 @@ ${editContext}`;
|
|
|
56436
56669
|
} else {
|
|
56437
56670
|
try {
|
|
56438
56671
|
const repoFiles = await getRepoFiles(opts.root);
|
|
56439
|
-
|
|
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);
|
|
56440
56696
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56441
56697
|
const b = blocks[i2];
|
|
56442
56698
|
const d = decisions[i2] || { action: "create", path: suggestName2(request, b.language, i2) };
|
|
56443
|
-
|
|
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)) {
|
|
56444
56702
|
const lang = languageFromExt(d.path.replace(/^.*(\.[a-z0-9]+)$/i, "$1"));
|
|
56445
|
-
initial.push({ path:
|
|
56703
|
+
initial.push({ path: finalPath, kind: "source", action: "modify", description: "Modify existing file", language: lang, preview: b.code, noNormalize: true });
|
|
56446
56704
|
} else {
|
|
56447
|
-
const pth = d.path || suggestName2(request, b.language, i2);
|
|
56448
|
-
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 });
|
|
56449
56707
|
}
|
|
56450
56708
|
}
|
|
56451
56709
|
} catch {
|
|
56452
56710
|
for (let i2 = 0; i2 < blocks.length; i2++) {
|
|
56453
56711
|
const b = blocks[i2];
|
|
56454
|
-
const
|
|
56455
|
-
|
|
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 });
|
|
56456
56715
|
}
|
|
56457
56716
|
}
|
|
56458
56717
|
}
|
|
@@ -56468,13 +56727,13 @@ ${editContext}`;
|
|
|
56468
56727
|
}
|
|
56469
56728
|
}
|
|
56470
56729
|
}
|
|
56471
|
-
if (explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
56730
|
+
if (!isEditIntent && explicitFiles.length > 0 && initial.filter((f3) => !!f3.preview).length === 0) {
|
|
56472
56731
|
for (const f3 of explicitFiles) {
|
|
56473
56732
|
initial.push(scaffoldForFilename(f3, explicitFiles));
|
|
56474
56733
|
}
|
|
56475
56734
|
}
|
|
56476
56735
|
const normalized = await normalizePlans(
|
|
56477
|
-
initial.map((p) => p.noNormalize ? p : p),
|
|
56736
|
+
initial.map((p) => p.noNormalize ? { ...p } : p),
|
|
56478
56737
|
{ root: opts.root }
|
|
56479
56738
|
);
|
|
56480
56739
|
try {
|
|
@@ -56499,11 +56758,26 @@ ${editContext}`;
|
|
|
56499
56758
|
}
|
|
56500
56759
|
} catch {
|
|
56501
56760
|
}
|
|
56502
|
-
|
|
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 });
|
|
56503
56777
|
const hasAnyModify = validated.files.some((f3) => f3.action === "modify") || isEditIntent;
|
|
56504
56778
|
const outputMode = !opts.flags.hideCode && hasAnyModify ? "diff" : resolveOutputMode(opts.flags.output, validated.files.length, !!opts.flags.hideCode);
|
|
56505
56779
|
const skippedSetForLookup = new Set(validated.skipped || []);
|
|
56506
|
-
const skippedPlans =
|
|
56780
|
+
const skippedPlans = filtered.filter((f3) => skippedSetForLookup.has(f3.path));
|
|
56507
56781
|
const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
|
|
56508
56782
|
const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
|
|
56509
56783
|
const summary = summarizePlan(displayFiles);
|
|
@@ -56696,6 +56970,21 @@ function extractBlocks(content) {
|
|
|
56696
56970
|
if (blocks.length === 0 && looksLikeCode(content)) blocks.push({ language: detectLanguage(content), code: content.trim() });
|
|
56697
56971
|
return blocks;
|
|
56698
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
|
+
}
|
|
56699
56988
|
function looksLikeCode(s2) {
|
|
56700
56989
|
return ["function ", "const ", "let ", "var ", "class ", "def ", "import ", "export "].some((k) => s2.includes(k));
|
|
56701
56990
|
}
|
|
@@ -56853,48 +57142,100 @@ function parseExplicitFilenames(request) {
|
|
|
56853
57142
|
return out;
|
|
56854
57143
|
}
|
|
56855
57144
|
async function detectEditIntentLLM(root, request, ctx2) {
|
|
57145
|
+
let existingDirs = [];
|
|
57146
|
+
let existingFiles = [];
|
|
57147
|
+
let anyExistingPathMentioned = false;
|
|
56856
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
|
+
}
|
|
56857
57168
|
const repoFiles = await getRepoFiles(root);
|
|
56858
|
-
|
|
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
|
+
}
|
|
56859
57176
|
const headSnippets = [];
|
|
56860
|
-
for (const p of
|
|
57177
|
+
for (const p of scope) {
|
|
56861
57178
|
const h2 = await readHeadTail(root, p, 5);
|
|
56862
57179
|
headSnippets.push(`- ${p}
|
|
56863
57180
|
${h2.head}`);
|
|
56864
57181
|
}
|
|
56865
57182
|
const system = [
|
|
56866
|
-
"
|
|
56867
|
-
"
|
|
56868
|
-
"
|
|
56869
|
-
"
|
|
56870
|
-
"
|
|
56871
|
-
"
|
|
56872
|
-
"
|
|
56873
|
-
'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" }.'
|
|
56874
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
|
+
};
|
|
56875
57200
|
const user = [
|
|
56876
57201
|
`Request: ${request}`,
|
|
56877
|
-
`
|
|
56878
|
-
|
|
56879
|
-
"Repo snapshot (paths with file heads):",
|
|
57202
|
+
`Evidence: ${JSON.stringify(evidence)}`,
|
|
57203
|
+
"Repo snapshot (trimmed):",
|
|
56880
57204
|
headSnippets.join("\n\n")
|
|
56881
57205
|
].join("\n\n");
|
|
56882
|
-
|
|
56883
|
-
|
|
56884
|
-
|
|
56885
|
-
|
|
56886
|
-
|
|
56887
|
-
|
|
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;
|
|
56888
57217
|
try {
|
|
56889
|
-
|
|
56890
|
-
|
|
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
|
+
}
|
|
56891
57229
|
}
|
|
56892
57230
|
const raw = (resp?.output || "").trim();
|
|
56893
57231
|
const jsonText = extractJsonSafe(raw, "object") || raw;
|
|
56894
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
|
+
}
|
|
56895
57236
|
return parsed?.intent === "EDIT_EXISTING";
|
|
56896
57237
|
} catch {
|
|
56897
|
-
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;
|
|
56898
57239
|
}
|
|
56899
57240
|
}
|
|
56900
57241
|
function sanitizeFolderName(name2) {
|
|
@@ -57062,7 +57403,7 @@ async function resolveExplicitPaths(root, files, hintText) {
|
|
|
57062
57403
|
const chat = await executeChat([
|
|
57063
57404
|
{ role: "system", content: system },
|
|
57064
57405
|
{ role: "user", content: user }
|
|
57065
|
-
]);
|
|
57406
|
+
], { provider: "google", model: "gemini-2.5-flash-lite" });
|
|
57066
57407
|
const raw = (chat.output || "").trim();
|
|
57067
57408
|
const pick = ranked.find((r2) => r2 === raw) || ranked.find((r2) => raw.includes(r2)) || ranked[0];
|
|
57068
57409
|
return pick.replace(/^\/+/, "");
|
|
@@ -57237,7 +57578,16 @@ var init_code_command = __esm({
|
|
|
57237
57578
|
}
|
|
57238
57579
|
];
|
|
57239
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
|
+
};
|
|
57240
57589
|
const request = await this.ensureLanguageDefaults(commandArgs.raw.join(" ").trim());
|
|
57590
|
+
debug("request", request);
|
|
57241
57591
|
if (!request) {
|
|
57242
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.");
|
|
57243
57593
|
}
|
|
@@ -57249,6 +57599,7 @@ var init_code_command = __esm({
|
|
|
57249
57599
|
const explicitDry = commandArgs.raw.includes("--dry-run");
|
|
57250
57600
|
const explicitOutput = commandArgs.raw.some((x2) => x2.startsWith("--output") || x2 === "--verbose" || x2 === "-v");
|
|
57251
57601
|
const explicitPreview = commandArgs.raw.some((x2) => x2.startsWith("--preview-lines"));
|
|
57602
|
+
const explicitOnlyAttached = commandArgs.raw.includes("--only-attached");
|
|
57252
57603
|
const preSpin = new ProcessAnimation();
|
|
57253
57604
|
preSpin.start();
|
|
57254
57605
|
let inferred = {};
|
|
@@ -57260,6 +57611,8 @@ var init_code_command = __esm({
|
|
|
57260
57611
|
} catch {
|
|
57261
57612
|
}
|
|
57262
57613
|
}
|
|
57614
|
+
debug("inferCodeArgs.raw", rawText);
|
|
57615
|
+
debug("inferCodeArgs.result", inferred);
|
|
57263
57616
|
if (!explicitPlan && !explicitDry) {
|
|
57264
57617
|
if (typeof inferred.planOnly === "boolean") opts.planOnly = inferred.planOnly;
|
|
57265
57618
|
if (typeof inferred.dryRun === "boolean") opts.dryRun = inferred.dryRun;
|
|
@@ -57270,6 +57623,9 @@ var init_code_command = __esm({
|
|
|
57270
57623
|
if (!explicitPreview && typeof inferred.previewLines === "number") {
|
|
57271
57624
|
opts.previewLines = inferred.previewLines;
|
|
57272
57625
|
}
|
|
57626
|
+
if (!explicitOnlyAttached && typeof inferred.onlyAttached === "boolean") {
|
|
57627
|
+
opts.onlyAttached = inferred.onlyAttached;
|
|
57628
|
+
}
|
|
57273
57629
|
} catch {
|
|
57274
57630
|
}
|
|
57275
57631
|
if (opts.planOnly) {
|
|
@@ -57284,13 +57640,27 @@ var init_code_command = __esm({
|
|
|
57284
57640
|
const root = opts.root || process.cwd();
|
|
57285
57641
|
const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
|
|
57286
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
|
+
}
|
|
57287
57650
|
const abort = new AbortController();
|
|
57288
57651
|
const onSigint = () => abort.abort();
|
|
57289
57652
|
process.once("SIGINT", onSigint);
|
|
57290
|
-
|
|
57291
|
-
spinner
|
|
57653
|
+
let startedLocalSpinner = false;
|
|
57654
|
+
let spinner = null;
|
|
57655
|
+
if (!ProcessAnimation.hasActive()) {
|
|
57656
|
+
spinner = new ProcessAnimation();
|
|
57657
|
+
spinner.start();
|
|
57658
|
+
startedLocalSpinner = true;
|
|
57659
|
+
}
|
|
57292
57660
|
try {
|
|
57293
|
-
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) : []);
|
|
57294
57664
|
if (opts.planOnly) {
|
|
57295
57665
|
const fs52 = await import('fs/promises');
|
|
57296
57666
|
const path65 = await import('path');
|
|
@@ -57343,9 +57713,11 @@ var init_code_command = __esm({
|
|
|
57343
57713
|
const out = Array.isArray(res?.summaryLines) ? res.summaryLines.join("\n") : "";
|
|
57344
57714
|
return this.success(out);
|
|
57345
57715
|
} finally {
|
|
57346
|
-
|
|
57347
|
-
|
|
57348
|
-
|
|
57716
|
+
if (startedLocalSpinner && spinner) {
|
|
57717
|
+
try {
|
|
57718
|
+
spinner.stop();
|
|
57719
|
+
} catch {
|
|
57720
|
+
}
|
|
57349
57721
|
}
|
|
57350
57722
|
process.removeListener("SIGINT", onSigint);
|
|
57351
57723
|
}
|
|
@@ -57468,12 +57840,6 @@ ${pretty}`);
|
|
|
57468
57840
|
if (llmLang) {
|
|
57469
57841
|
const hint2 = (() => {
|
|
57470
57842
|
const l = llmLang.toLowerCase();
|
|
57471
|
-
if (l === "tsx") return "TypeScript (React/TSX)";
|
|
57472
|
-
if (l === "jsx") return "JavaScript (React/JSX)";
|
|
57473
|
-
if (l === "typescript") return "TypeScript";
|
|
57474
|
-
if (l === "javascript") return "JavaScript";
|
|
57475
|
-
if (l === "html") return "HTML";
|
|
57476
|
-
if (l === "css") return "CSS";
|
|
57477
57843
|
return llmLang;
|
|
57478
57844
|
})();
|
|
57479
57845
|
return raw + ` (Use ${hint2})`;
|
|
@@ -57486,7 +57852,7 @@ ${pretty}`);
|
|
|
57486
57852
|
preSpin.start();
|
|
57487
57853
|
const system = [
|
|
57488
57854
|
"You analyze a user's code-generation request.",
|
|
57489
|
-
"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.",
|
|
57490
57856
|
'Return ONLY compact JSON with shape {"explicitLanguage": boolean, "language"?: string}.',
|
|
57491
57857
|
"Do not add any commentary."
|
|
57492
57858
|
].join("\n");
|
|
@@ -57495,7 +57861,7 @@ ${pretty}`);
|
|
|
57495
57861
|
method: "POST",
|
|
57496
57862
|
body: {
|
|
57497
57863
|
provider: "google",
|
|
57498
|
-
model: "gemini-2.5-flash",
|
|
57864
|
+
model: "gemini-2.5-flash-lite",
|
|
57499
57865
|
taskType: "chat",
|
|
57500
57866
|
prompt: `${system}
|
|
57501
57867
|
|
|
@@ -57540,6 +57906,14 @@ ${user}`
|
|
|
57540
57906
|
if (parsed && parsed.explicitLanguage) return raw;
|
|
57541
57907
|
} catch {
|
|
57542
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
|
+
}
|
|
57543
57917
|
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
57544
57918
|
return raw + hint;
|
|
57545
57919
|
}
|
|
@@ -57549,9 +57923,7 @@ ${user}`
|
|
|
57549
57923
|
const system = [
|
|
57550
57924
|
"You are a programming language classifier.",
|
|
57551
57925
|
"Given multiple short code excerpts, determine the dominant language across them.",
|
|
57552
|
-
"Respond with ONLY
|
|
57553
|
-
"[typescript, tsx, javascript, jsx, python, java, go, rust, php, cpp, c, swift, kotlin, ruby, csharp, html, css, scss, json, yaml, markdown].",
|
|
57554
|
-
"If unsure between tsx and jsx, choose tsx if TypeScript types appear, else jsx."
|
|
57926
|
+
"Respond with ONLY language name(s)"
|
|
57555
57927
|
].join("\n");
|
|
57556
57928
|
const joined = samples.slice(0, 20).map((s2, i2) => `// sample ${i2 + 1}
|
|
57557
57929
|
${s2}`).join("\n\n");
|
|
@@ -57560,7 +57932,7 @@ ${s2}`).join("\n\n");
|
|
|
57560
57932
|
method: "POST",
|
|
57561
57933
|
body: {
|
|
57562
57934
|
provider: "google",
|
|
57563
|
-
model: "gemini-2.5-flash",
|
|
57935
|
+
model: "gemini-2.5-flash-lite",
|
|
57564
57936
|
taskType: "chat",
|
|
57565
57937
|
prompt: `${system}
|
|
57566
57938
|
|
|
@@ -57866,64 +58238,6 @@ ${joined}`
|
|
|
57866
58238
|
return false;
|
|
57867
58239
|
}
|
|
57868
58240
|
}
|
|
57869
|
-
/**
|
|
57870
|
-
* Extract code blocks from AI response
|
|
57871
|
-
*/
|
|
57872
|
-
extractCodeBlocks(content) {
|
|
57873
|
-
const blocks = [];
|
|
57874
|
-
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
|
57875
|
-
let match2;
|
|
57876
|
-
while ((match2 = codeBlockRegex.exec(content)) !== null) {
|
|
57877
|
-
blocks.push({
|
|
57878
|
-
language: match2[1] || "javascript",
|
|
57879
|
-
code: match2[2].trim()
|
|
57880
|
-
});
|
|
57881
|
-
}
|
|
57882
|
-
if (blocks.length === 0 && this.looksLikeCode(content)) {
|
|
57883
|
-
blocks.push({
|
|
57884
|
-
code: content.trim(),
|
|
57885
|
-
language: this.detectLanguage(content)
|
|
57886
|
-
});
|
|
57887
|
-
}
|
|
57888
|
-
return blocks;
|
|
57889
|
-
}
|
|
57890
|
-
/**
|
|
57891
|
-
* Check if content looks like code
|
|
57892
|
-
*/
|
|
57893
|
-
looksLikeCode(content) {
|
|
57894
|
-
const codeIndicators = [
|
|
57895
|
-
"function ",
|
|
57896
|
-
"const ",
|
|
57897
|
-
"let ",
|
|
57898
|
-
"var ",
|
|
57899
|
-
"class ",
|
|
57900
|
-
"def ",
|
|
57901
|
-
"import ",
|
|
57902
|
-
"export ",
|
|
57903
|
-
"{",
|
|
57904
|
-
"}",
|
|
57905
|
-
";",
|
|
57906
|
-
"//",
|
|
57907
|
-
"/*"
|
|
57908
|
-
];
|
|
57909
|
-
return codeIndicators.some((indicator) => content.includes(indicator));
|
|
57910
|
-
}
|
|
57911
|
-
/**
|
|
57912
|
-
* Detect programming language from content
|
|
57913
|
-
*/
|
|
57914
|
-
detectLanguage(code) {
|
|
57915
|
-
const hasReact = /(^|\s)from\s+['"]react['"]|^\s*import\s+React/m.test(code);
|
|
57916
|
-
const hasJSX = /<([A-Za-z][\w:-]*)(\s|>|\/)>?/m.test(code);
|
|
57917
|
-
const hasTS = /(\binterface\s+\w+\b|\btype\s+\w+\s*=|:\s*[A-Za-z_][\w<>\[\]| &?:]*)/m.test(code) || /React\.FC\s*</m.test(code);
|
|
57918
|
-
if (hasReact || hasJSX) return hasTS ? "tsx" : "jsx";
|
|
57919
|
-
if (code.includes("interface ") || code.includes(": string")) return "typescript";
|
|
57920
|
-
if (code.includes("def ") || code.includes("print(")) return "python";
|
|
57921
|
-
if (code.includes("func ") || code.includes("package main")) return "go";
|
|
57922
|
-
if (code.includes("fn ") || code.includes("let mut")) return "rust";
|
|
57923
|
-
if (code.includes("<?php")) return "php";
|
|
57924
|
-
if (code.includes("#include")) return "cpp";
|
|
57925
|
-
return "javascript";
|
|
57926
|
-
}
|
|
57927
58241
|
/**
|
|
57928
58242
|
* Save code block to file
|
|
57929
58243
|
*/
|
|
@@ -63721,11 +64035,10 @@ var init_clients_safe = __esm({
|
|
|
63721
64035
|
}
|
|
63722
64036
|
});
|
|
63723
64037
|
function createSpinner(text) {
|
|
63724
|
-
let frame = 0;
|
|
63725
64038
|
let active = false;
|
|
63726
|
-
let
|
|
63727
|
-
const
|
|
63728
|
-
const f3 = SPINNER_FRAMES[frame
|
|
64039
|
+
let frame = 0;
|
|
64040
|
+
const renderOnce = () => {
|
|
64041
|
+
const f3 = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
63729
64042
|
process5__namespace.default.stdout.write(`\r ${chalk14__default.default.cyan(f3)} ${text}`);
|
|
63730
64043
|
};
|
|
63731
64044
|
return {
|
|
@@ -63735,13 +64048,11 @@ function createSpinner(text) {
|
|
|
63735
64048
|
start() {
|
|
63736
64049
|
if (active) return;
|
|
63737
64050
|
active = true;
|
|
63738
|
-
|
|
63739
|
-
timer = setInterval(render, 80);
|
|
64051
|
+
renderOnce();
|
|
63740
64052
|
},
|
|
63741
64053
|
stop(symbol = "\u2714") {
|
|
63742
64054
|
if (!active) return;
|
|
63743
64055
|
active = false;
|
|
63744
|
-
if (timer) clearInterval(timer);
|
|
63745
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;
|
|
63746
64057
|
process5__namespace.default.stdout.write(`\r ${finalSymbol} ${text}
|
|
63747
64058
|
`);
|