@bonginkan/maria 4.3.35 → 4.3.37
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 +26 -18
- package/dist/bin/maria.cjs +1154 -441
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +1156 -443
- 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 +52 -12
- package/dist/server/express-server.js +52 -12
- package/dist/server-express.cjs +52 -12
- package/dist/server-express.cjs.map +1 -1
- package/package.json +2 -2
- package/src/slash-commands/READY.manifest.json +26 -18
package/dist/cli.cjs
CHANGED
|
@@ -12,6 +12,7 @@ var os10 = require('os');
|
|
|
12
12
|
var child_process = require('child_process');
|
|
13
13
|
var fsp = require('fs/promises');
|
|
14
14
|
var secretManager = require('@google-cloud/secret-manager');
|
|
15
|
+
var https = require('https');
|
|
15
16
|
var events = require('events');
|
|
16
17
|
var Stream2 = require('stream');
|
|
17
18
|
var string_decoder = require('string_decoder');
|
|
@@ -24,7 +25,6 @@ var process6 = require('process');
|
|
|
24
25
|
var readline = require('readline');
|
|
25
26
|
var buffer = require('buffer');
|
|
26
27
|
var net = require('net');
|
|
27
|
-
var https = require('https');
|
|
28
28
|
var zlib = require('zlib');
|
|
29
29
|
var yaml = require('js-yaml');
|
|
30
30
|
var neo4j = require('neo4j-driver');
|
|
@@ -63,12 +63,12 @@ var http2__namespace = /*#__PURE__*/_interopNamespace(http2);
|
|
|
63
63
|
var url__namespace = /*#__PURE__*/_interopNamespace(url);
|
|
64
64
|
var os10__namespace = /*#__PURE__*/_interopNamespace(os10);
|
|
65
65
|
var fsp__namespace = /*#__PURE__*/_interopNamespace(fsp);
|
|
66
|
+
var https__default = /*#__PURE__*/_interopDefault(https);
|
|
66
67
|
var Stream2__default = /*#__PURE__*/_interopDefault(Stream2);
|
|
67
68
|
var fs6__namespace = /*#__PURE__*/_interopNamespace(fs6);
|
|
68
69
|
var dns__default = /*#__PURE__*/_interopDefault(dns);
|
|
69
70
|
var process6__namespace = /*#__PURE__*/_interopNamespace(process6);
|
|
70
71
|
var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
|
|
71
|
-
var https__default = /*#__PURE__*/_interopDefault(https);
|
|
72
72
|
var zlib__default = /*#__PURE__*/_interopDefault(zlib);
|
|
73
73
|
var yaml__namespace = /*#__PURE__*/_interopNamespace(yaml);
|
|
74
74
|
var neo4j__default = /*#__PURE__*/_interopDefault(neo4j);
|
|
@@ -1709,7 +1709,7 @@ var init_AuthenticationManager = __esm({
|
|
|
1709
1709
|
const response = await fetch(`${this.apiBase}/api/user/profile`, {
|
|
1710
1710
|
headers: {
|
|
1711
1711
|
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
1712
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
1712
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.37"}`
|
|
1713
1713
|
}
|
|
1714
1714
|
});
|
|
1715
1715
|
if (response.status === 401) {
|
|
@@ -2390,6 +2390,17 @@ var init_esm_node = __esm({
|
|
|
2390
2390
|
init_v4();
|
|
2391
2391
|
}
|
|
2392
2392
|
});
|
|
2393
|
+
|
|
2394
|
+
// src/services/cli-auth/api-client.ts
|
|
2395
|
+
var api_client_exports = {};
|
|
2396
|
+
__export(api_client_exports, {
|
|
2397
|
+
ERR: () => ERR,
|
|
2398
|
+
callApi: () => callApi,
|
|
2399
|
+
callApiJson: () => callApiJson,
|
|
2400
|
+
clientThrottle: () => clientThrottle,
|
|
2401
|
+
streamApi: () => streamApi,
|
|
2402
|
+
uploadFile: () => uploadFile
|
|
2403
|
+
});
|
|
2393
2404
|
function getDeviceId() {
|
|
2394
2405
|
if (!global.MARIA_DEVICE_ID) {
|
|
2395
2406
|
global.MARIA_DEVICE_ID = v4_default();
|
|
@@ -2399,6 +2410,17 @@ function getDeviceId() {
|
|
|
2399
2410
|
function getSessionId() {
|
|
2400
2411
|
return global.MARIA_SESSION_ID;
|
|
2401
2412
|
}
|
|
2413
|
+
function clientThrottle(endpoint) {
|
|
2414
|
+
const now2 = Date.now();
|
|
2415
|
+
const lastCall = rateLimitMap.get(endpoint) || 0;
|
|
2416
|
+
const wait = MIN_GAP_MS - (now2 - lastCall);
|
|
2417
|
+
if (wait > 0) {
|
|
2418
|
+
const waitSeconds = Math.ceil(wait / 1e3);
|
|
2419
|
+
console.log(chalk40__default.default.yellow(`\u23F1\uFE0F Rate limit: wait ${waitSeconds}s`));
|
|
2420
|
+
throw { ...ERR.RATE, waitTime: waitSeconds };
|
|
2421
|
+
}
|
|
2422
|
+
rateLimitMap.set(endpoint, now2);
|
|
2423
|
+
}
|
|
2402
2424
|
async function callApi(path64, init3 = {}) {
|
|
2403
2425
|
const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
2404
2426
|
const fullUrl = `${apiBase}${path64}`;
|
|
@@ -2412,7 +2434,7 @@ async function callApi(path64, init3 = {}) {
|
|
|
2412
2434
|
"Authorization": `Bearer ${token}`,
|
|
2413
2435
|
"X-Device-Id": getDeviceId(),
|
|
2414
2436
|
"X-Session-Id": getSessionId() || "",
|
|
2415
|
-
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.
|
|
2437
|
+
"User-Agent": `maria-cli/${process.env.CLI_VERSION || "4.3.37"}`,
|
|
2416
2438
|
"Content-Type": init3.headers?.["Content-Type"] || "application/json"
|
|
2417
2439
|
});
|
|
2418
2440
|
const doFetch = async (token) => {
|
|
@@ -2480,7 +2502,48 @@ async function callApiJson(path64, init3 = {}) {
|
|
|
2480
2502
|
}
|
|
2481
2503
|
return response.json();
|
|
2482
2504
|
}
|
|
2483
|
-
|
|
2505
|
+
async function* streamApi(path64, init3 = {}) {
|
|
2506
|
+
const response = await callApi(path64, {
|
|
2507
|
+
...init3,
|
|
2508
|
+
headers: {
|
|
2509
|
+
...init3.headers,
|
|
2510
|
+
"Accept": "text/event-stream"
|
|
2511
|
+
}
|
|
2512
|
+
});
|
|
2513
|
+
if (!response.ok) {
|
|
2514
|
+
throw new Error(`Stream error: ${response.status}`);
|
|
2515
|
+
}
|
|
2516
|
+
const reader = response.body?.getReader();
|
|
2517
|
+
if (!reader) {
|
|
2518
|
+
throw new Error("No response body");
|
|
2519
|
+
}
|
|
2520
|
+
const decoder = new TextDecoder();
|
|
2521
|
+
try {
|
|
2522
|
+
while (true) {
|
|
2523
|
+
const { done, value } = await reader.read();
|
|
2524
|
+
if (done) break;
|
|
2525
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
2526
|
+
yield chunk;
|
|
2527
|
+
}
|
|
2528
|
+
} finally {
|
|
2529
|
+
reader.releaseLock();
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
async function uploadFile(path64, file, metadata5 = {}) {
|
|
2533
|
+
const formData = new FormData();
|
|
2534
|
+
formData.append("file", new Blob([file]));
|
|
2535
|
+
Object.entries(metadata5).forEach(([key, value]) => {
|
|
2536
|
+
formData.append(key, String(value));
|
|
2537
|
+
});
|
|
2538
|
+
return callApiJson(path64, {
|
|
2539
|
+
method: "POST",
|
|
2540
|
+
body: formData,
|
|
2541
|
+
headers: {
|
|
2542
|
+
// Don't set Content-Type, let browser set it with boundary
|
|
2543
|
+
}
|
|
2544
|
+
});
|
|
2545
|
+
}
|
|
2546
|
+
var ERR, rateLimitMap, MIN_GAP_MS;
|
|
2484
2547
|
var init_api_client = __esm({
|
|
2485
2548
|
"src/services/cli-auth/api-client.ts"() {
|
|
2486
2549
|
init_AuthenticationManager();
|
|
@@ -2493,6 +2556,8 @@ var init_api_client = __esm({
|
|
|
2493
2556
|
NETWORK: { msg: "\u{1F310} Network error, check connection", code: 1 },
|
|
2494
2557
|
RATE: { msg: "\u23F3 Rate limited, retrying...", code: 1 }
|
|
2495
2558
|
};
|
|
2559
|
+
rateLimitMap = /* @__PURE__ */ new Map();
|
|
2560
|
+
MIN_GAP_MS = 3e3;
|
|
2496
2561
|
}
|
|
2497
2562
|
});
|
|
2498
2563
|
|
|
@@ -2991,109 +3056,199 @@ var init_choice_memory = __esm({
|
|
|
2991
3056
|
}
|
|
2992
3057
|
});
|
|
2993
3058
|
|
|
2994
|
-
// src/services/
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3059
|
+
// src/services/cli-auth/api-caller.ts
|
|
3060
|
+
var api_caller_exports = {};
|
|
3061
|
+
__export(api_caller_exports, {
|
|
3062
|
+
RateLimitError: () => RateLimitError,
|
|
3063
|
+
callAPI: () => callAPI,
|
|
3064
|
+
executeAIProxy: () => executeAIProxy,
|
|
3065
|
+
executeChat: () => executeChat,
|
|
3066
|
+
executeCode: () => executeCode
|
|
3067
|
+
});
|
|
3068
|
+
async function callAPI(endpoint, options = {}) {
|
|
3069
|
+
const tokens2 = await authManager2.getValidTokens();
|
|
3070
|
+
if (!tokens2) {
|
|
3071
|
+
throw new Error("Authentication required. Please run /login first.");
|
|
2998
3072
|
}
|
|
2999
|
-
|
|
3000
|
-
|
|
3073
|
+
const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
3074
|
+
const url2 = `${apiBase}${endpoint}`;
|
|
3075
|
+
const controller = new AbortController();
|
|
3076
|
+
const defaultMs = 6e5;
|
|
3077
|
+
const envMs = Number(process.env.MARIA_API_TIMEOUT_MS || process.env.MARIA_CODE_TIMEOUT_MS || defaultMs);
|
|
3078
|
+
const timeoutMs = Number.isFinite(envMs) && envMs > 0 ? envMs : defaultMs;
|
|
3079
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
3080
|
+
try {
|
|
3081
|
+
const response = await fetch(url2, {
|
|
3082
|
+
method: options.method || "GET",
|
|
3083
|
+
headers: {
|
|
3084
|
+
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
3085
|
+
"Content-Type": "application/json",
|
|
3086
|
+
...options.headers
|
|
3087
|
+
},
|
|
3088
|
+
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
3089
|
+
// Note: fetch in Node doesn't accept 'agent' in our typing here; relying on global agent not necessary
|
|
3090
|
+
signal: controller.signal
|
|
3091
|
+
});
|
|
3092
|
+
clearTimeout(timeoutId);
|
|
3093
|
+
if (!response) {
|
|
3094
|
+
throw new Error("\u{1F310} Network error, check connection");
|
|
3095
|
+
}
|
|
3096
|
+
if (response.status === 401) {
|
|
3097
|
+
throw new Error("Session expired. Please run /login again.");
|
|
3098
|
+
}
|
|
3099
|
+
if (response.status === 402) {
|
|
3100
|
+
const data2 = await response.json().catch(() => ({}));
|
|
3101
|
+
throw new Error(`Quota exceeded: ${typeof data2?.message === "string" ? data2.message : "Please wait or /upgrade"}`);
|
|
3102
|
+
}
|
|
3103
|
+
if (response.status === 403) {
|
|
3104
|
+
const data2 = await response.json().catch(() => ({}));
|
|
3105
|
+
throw new Error(`Not available on Free plan: ${typeof data2?.message === "string" ? data2.message : "Run /upgrade"}`);
|
|
3106
|
+
}
|
|
3107
|
+
if (response.status === 429) {
|
|
3108
|
+
const h2 = response.headers;
|
|
3109
|
+
const ra = h2.get("Retry-After");
|
|
3110
|
+
const reset = h2.get("RateLimit-Reset") || h2.get("X-RateLimit-Reset");
|
|
3111
|
+
let waitSec = 3;
|
|
3112
|
+
if (ra && /^\d+$/.test(ra)) {
|
|
3113
|
+
waitSec = +ra;
|
|
3114
|
+
} else if (ra) {
|
|
3115
|
+
const t2 = Date.parse(ra);
|
|
3116
|
+
if (!isNaN(t2)) waitSec = Math.max(1, Math.ceil((t2 - Date.now()) / 1e3));
|
|
3117
|
+
} else if (reset) {
|
|
3118
|
+
waitSec = Math.max(1, Math.ceil((+reset - Date.now()) / 1e3));
|
|
3119
|
+
}
|
|
3120
|
+
throw new RateLimitError(`\u23F1 Wait ${waitSec}s`, waitSec);
|
|
3121
|
+
}
|
|
3122
|
+
if (!response.ok) {
|
|
3123
|
+
const data2 = await response.json().catch(() => ({}));
|
|
3124
|
+
const msg = typeof data2?.error === "string" ? data2.error : `Request failed: ${response.statusText}`;
|
|
3125
|
+
throw new Error(msg);
|
|
3126
|
+
}
|
|
3127
|
+
const data = await response.json();
|
|
3128
|
+
return data;
|
|
3129
|
+
} catch (error2) {
|
|
3130
|
+
clearTimeout(timeoutId);
|
|
3131
|
+
const err = error2;
|
|
3132
|
+
if (err && err.name === "AbortError") {
|
|
3133
|
+
throw new Error("\u{1F310} Network error, check connection");
|
|
3134
|
+
}
|
|
3135
|
+
throw err;
|
|
3001
3136
|
}
|
|
3002
|
-
return "low";
|
|
3003
3137
|
}
|
|
3004
|
-
async function
|
|
3005
|
-
const
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3138
|
+
async function executeChat(messages) {
|
|
3139
|
+
const response = await callAPI("/v1/chat", {
|
|
3140
|
+
method: "POST",
|
|
3141
|
+
body: { messages }
|
|
3142
|
+
});
|
|
3143
|
+
return response;
|
|
3144
|
+
}
|
|
3145
|
+
async function executeCode(input3) {
|
|
3146
|
+
const isOptions = typeof input3 === "object";
|
|
3147
|
+
const prompt = isOptions ? input3.prompt : input3;
|
|
3148
|
+
const provider = isOptions ? input3.provider : void 0;
|
|
3149
|
+
const model = isOptions ? input3.model : void 0;
|
|
3150
|
+
const attachments = isOptions ? input3.attachments : void 0;
|
|
3151
|
+
const body = { prompt, taskType: "code" };
|
|
3152
|
+
if (provider) body.provider = provider;
|
|
3153
|
+
if (model) body.model = model;
|
|
3154
|
+
if (attachments && attachments.length > 0) {
|
|
3155
|
+
body.metadata = { attachments };
|
|
3013
3156
|
}
|
|
3014
|
-
const
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
}
|
|
3157
|
+
const response = await callAPI("/v1/ai-proxy", {
|
|
3158
|
+
method: "POST",
|
|
3159
|
+
body
|
|
3160
|
+
});
|
|
3161
|
+
if (response.data?.routedModel) {
|
|
3162
|
+
response.routedModel = response.data.routedModel;
|
|
3021
3163
|
}
|
|
3022
|
-
if (
|
|
3023
|
-
|
|
3024
|
-
return {
|
|
3025
|
-
type: "route-image",
|
|
3026
|
-
confidence: 0.82,
|
|
3027
|
-
rationale,
|
|
3028
|
-
band: "high",
|
|
3029
|
-
next: { route: "/image", args: [question] }
|
|
3030
|
-
};
|
|
3164
|
+
if (response.data?.content) {
|
|
3165
|
+
response.output = response.data.content;
|
|
3031
3166
|
}
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3167
|
+
return response;
|
|
3168
|
+
}
|
|
3169
|
+
async function executeAIProxy(provider, model, messages, options) {
|
|
3170
|
+
return callAPI("/v1/ai-proxy", {
|
|
3171
|
+
method: "POST",
|
|
3172
|
+
body: { provider, model, messages, options }
|
|
3173
|
+
});
|
|
3174
|
+
}
|
|
3175
|
+
var authManager2, RateLimitError;
|
|
3176
|
+
var init_api_caller = __esm({
|
|
3177
|
+
"src/services/cli-auth/api-caller.ts"() {
|
|
3178
|
+
init_AuthenticationManager();
|
|
3179
|
+
new https__default.default.Agent({ keepAlive: true });
|
|
3180
|
+
authManager2 = new AuthenticationManager();
|
|
3181
|
+
RateLimitError = class extends Error {
|
|
3182
|
+
constructor(message, retryAfter) {
|
|
3183
|
+
super(message);
|
|
3184
|
+
this.retryAfter = retryAfter;
|
|
3185
|
+
this.name = "RateLimitError";
|
|
3186
|
+
}
|
|
3040
3187
|
};
|
|
3041
3188
|
}
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3189
|
+
});
|
|
3190
|
+
|
|
3191
|
+
// src/services/intelligent-router/LlmTopLevelRouter.ts
|
|
3192
|
+
function extractFirstJson(text) {
|
|
3193
|
+
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
3194
|
+
if (fence) return fence[1];
|
|
3195
|
+
const start = text.indexOf("{");
|
|
3196
|
+
const end = text.lastIndexOf("}");
|
|
3197
|
+
if (start >= 0 && end > start) {
|
|
3198
|
+
const cand = text.slice(start, end + 1);
|
|
3199
|
+
try {
|
|
3200
|
+
JSON.parse(cand);
|
|
3201
|
+
return cand;
|
|
3202
|
+
} catch {
|
|
3203
|
+
}
|
|
3052
3204
|
}
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
}
|
|
3205
|
+
return null;
|
|
3206
|
+
}
|
|
3207
|
+
async function mapInputToTopLevelCommand(input3) {
|
|
3208
|
+
const system = [
|
|
3209
|
+
"You are a router for the MARIA CLI.",
|
|
3210
|
+
"Decide the best command for a single user input.",
|
|
3211
|
+
"Allowed commands: /help, /image, /code, /video, /whoami, /login, /logout, /evaluate, chat.",
|
|
3212
|
+
"Note that /image and /video are for generating them. If a path of a file is provided, you should double think why it's referenced (it may be for coding or chatting or other commands, regarding on the context).",
|
|
3213
|
+
'Return JSON only with keys: { "command": string, "args"?: string[], "confidence": number }.',
|
|
3214
|
+
"Select chat when the input is a general question or conversation rather than a specific slash command.",
|
|
3215
|
+
"Make sure you set the confidence between 0 and 1.",
|
|
3216
|
+
"Only include args if necessary to pass user content to the command. Do not explain."
|
|
3217
|
+
].join("\n");
|
|
3218
|
+
const resp = await callAPI("/v1/ai-proxy", {
|
|
3219
|
+
method: "POST",
|
|
3220
|
+
body: {
|
|
3221
|
+
prompt: `${system}
|
|
3222
|
+
|
|
3223
|
+
---
|
|
3224
|
+
|
|
3225
|
+
${input3}`,
|
|
3226
|
+
taskType: "routing"
|
|
3227
|
+
}
|
|
3228
|
+
});
|
|
3229
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
3230
|
+
const jsonText = extractFirstJson(raw) || raw;
|
|
3231
|
+
let parsed = {};
|
|
3232
|
+
try {
|
|
3233
|
+
parsed = JSON.parse(jsonText);
|
|
3234
|
+
} catch {
|
|
3235
|
+
return null;
|
|
3062
3236
|
}
|
|
3063
|
-
if (
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
rationale,
|
|
3070
|
-
band: getConfidenceBand(confidence)
|
|
3071
|
-
};
|
|
3237
|
+
if (!parsed || typeof parsed.command !== "string") return null;
|
|
3238
|
+
const cmd = parsed.command;
|
|
3239
|
+
if (!["/help", "/image", "/code", "/video", "/whoami", "/login", "/logout", "/evaluate", "chat"].includes(cmd)) return null;
|
|
3240
|
+
const out = { command: cmd };
|
|
3241
|
+
if (Array.isArray(parsed.args)) {
|
|
3242
|
+
out.args = parsed.args.filter((a) => typeof a === "string" && a.trim()).map((s2) => s2.trim());
|
|
3072
3243
|
}
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
confidence: fallbackConfidence,
|
|
3078
|
-
rationale,
|
|
3079
|
-
band: getConfidenceBand(fallbackConfidence)
|
|
3080
|
-
};
|
|
3081
|
-
}
|
|
3082
|
-
function normalizeRouteArgs(args2 = []) {
|
|
3083
|
-
return args2.map((arg) => arg.trim()).filter((arg) => arg.length > 0);
|
|
3244
|
+
if (typeof parsed.confidence === "number") {
|
|
3245
|
+
out.confidence = Math.max(0, Math.min(1, parsed.confidence));
|
|
3246
|
+
}
|
|
3247
|
+
return out;
|
|
3084
3248
|
}
|
|
3085
|
-
var
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
TRIAGE_THRESHOLDS = Object.freeze({
|
|
3089
|
-
high: 0.7,
|
|
3090
|
-
mid: 0.35
|
|
3091
|
-
});
|
|
3092
|
-
QUESTION_REGEX = /(how|what|why|when|どの|どう|なぜ|いつ|とは)\b/i;
|
|
3093
|
-
CODE_REGEX = /(create|generate|add|refactor|fix|test|route|build|component|migration|implement|実装|生成|追加|修正)/i;
|
|
3094
|
-
IMAGE_REGEX = /(image|画像|svg|png|webp|thumbnail|illustration|アート|描いて)/i;
|
|
3095
|
-
VIDEO_REGEX = /(video|動画|mp4|webm|frames|storyboard|アニメーション)/i;
|
|
3096
|
-
MULTI_SCOPE_REGEX = /(\band\b|\balso\b|\s+,+\s+)/i;
|
|
3249
|
+
var init_LlmTopLevelRouter = __esm({
|
|
3250
|
+
"src/services/intelligent-router/LlmTopLevelRouter.ts"() {
|
|
3251
|
+
init_api_caller();
|
|
3097
3252
|
}
|
|
3098
3253
|
});
|
|
3099
3254
|
|
|
@@ -3425,7 +3580,7 @@ var init_unknown_command = __esm({
|
|
|
3425
3580
|
});
|
|
3426
3581
|
|
|
3427
3582
|
// src/slash-commands/types.ts
|
|
3428
|
-
var CommandError, ValidationError, PermissionError,
|
|
3583
|
+
var CommandError, ValidationError, PermissionError, RateLimitError2;
|
|
3429
3584
|
var init_types2 = __esm({
|
|
3430
3585
|
"src/slash-commands/types.ts"() {
|
|
3431
3586
|
CommandError = class extends Error {
|
|
@@ -3451,7 +3606,7 @@ var init_types2 = __esm({
|
|
|
3451
3606
|
this.name = "PermissionError";
|
|
3452
3607
|
}
|
|
3453
3608
|
};
|
|
3454
|
-
|
|
3609
|
+
RateLimitError2 = class extends CommandError {
|
|
3455
3610
|
constructor(message, retryAfter) {
|
|
3456
3611
|
super(message, "RATE_LIMIT_ERROR", 429);
|
|
3457
3612
|
this.retryAfter = retryAfter;
|
|
@@ -10900,8 +11055,7 @@ var init_registry = __esm({
|
|
|
10900
11055
|
const { ChatContextService: ChatContextService3 } = await Promise.resolve().then(() => (init_chat_context_service(), chat_context_service_exports));
|
|
10901
11056
|
const ctxSvc = ChatContextService3.getInstance();
|
|
10902
11057
|
const usageLine = ctxSvc.getSessionUsageLine();
|
|
10903
|
-
const suffix =
|
|
10904
|
-
${usageLine}`;
|
|
11058
|
+
const suffix = ``;
|
|
10905
11059
|
result.message = (result.message || "").concat(suffix);
|
|
10906
11060
|
} catch {
|
|
10907
11061
|
}
|
|
@@ -10965,7 +11119,7 @@ ${usageLine}`;
|
|
|
10965
11119
|
}
|
|
10966
11120
|
}
|
|
10967
11121
|
} catch (innerError) {
|
|
10968
|
-
logger.error(`Failed to load command from ${file}:`,
|
|
11122
|
+
logger.error(`Failed to load command from ${file}:`, innerError);
|
|
10969
11123
|
}
|
|
10970
11124
|
}
|
|
10971
11125
|
this.initialized = true;
|
|
@@ -11002,8 +11156,8 @@ ${usageLine}`;
|
|
|
11002
11156
|
try {
|
|
11003
11157
|
return await next();
|
|
11004
11158
|
} catch (innerError) {
|
|
11005
|
-
logger.error(`Command ${command.name} failed:`,
|
|
11006
|
-
throw
|
|
11159
|
+
logger.error(`Command ${command.name} failed:`, innerError);
|
|
11160
|
+
throw innerError;
|
|
11007
11161
|
}
|
|
11008
11162
|
}
|
|
11009
11163
|
});
|
|
@@ -11961,6 +12115,7 @@ var init_clear_command = __esm({
|
|
|
11961
12115
|
init_telemetry_helper();
|
|
11962
12116
|
init_subscription_manager();
|
|
11963
12117
|
init_terminal();
|
|
12118
|
+
init_chat_context_service();
|
|
11964
12119
|
ClearCommand = class extends BaseCommand {
|
|
11965
12120
|
name = "clear";
|
|
11966
12121
|
category = "conversation";
|
|
@@ -11977,34 +12132,46 @@ var init_clear_command = __esm({
|
|
|
11977
12132
|
async execute(args2, context2) {
|
|
11978
12133
|
const startTime = Date.now();
|
|
11979
12134
|
try {
|
|
12135
|
+
let mode = "session";
|
|
12136
|
+
const idx = Array.isArray(args2.raw) ? args2.raw.indexOf("--mode") : -1;
|
|
12137
|
+
if (idx >= 0) {
|
|
12138
|
+
const val = String(args2.raw[idx + 1] || "").toLowerCase();
|
|
12139
|
+
if (val === "display" || val === "session" || val === "all") mode = val;
|
|
12140
|
+
}
|
|
11980
12141
|
clearTerminal();
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
context2.session.context = {};
|
|
11987
|
-
}
|
|
11988
|
-
if (context2.session.messages) {
|
|
11989
|
-
context2.session.messages = [];
|
|
11990
|
-
}
|
|
12142
|
+
const chat = ChatContextService.getInstance();
|
|
12143
|
+
if (mode === "display") {
|
|
12144
|
+
chat.clearContext({ soft: true });
|
|
12145
|
+
} else {
|
|
12146
|
+
chat.clearContext();
|
|
11991
12147
|
}
|
|
12148
|
+
const quotaLeft = (() => {
|
|
12149
|
+
const rec = context2;
|
|
12150
|
+
const v = rec && typeof rec["quotaLeft"] === "number" ? rec["quotaLeft"] : 999;
|
|
12151
|
+
return v;
|
|
12152
|
+
})();
|
|
11992
12153
|
await trackCommand({
|
|
11993
12154
|
cmd: "clear",
|
|
11994
12155
|
status: "success",
|
|
11995
12156
|
latencyMs: Date.now() - startTime,
|
|
11996
|
-
plan: getUserPlan(),
|
|
11997
|
-
quotaLeft
|
|
12157
|
+
plan: await getUserPlan(),
|
|
12158
|
+
quotaLeft
|
|
11998
12159
|
});
|
|
11999
|
-
const
|
|
12000
|
-
|
|
12160
|
+
const suffix = mode === "display" ? "display only" : "context reset";
|
|
12161
|
+
const message = chalk40__default.default.green("\u2705 Cleared") + chalk40__default.default.gray(` \xB7 ${suffix}`);
|
|
12162
|
+
return this.success(withQuotaFooter(message, quotaLeft));
|
|
12001
12163
|
} catch (error2) {
|
|
12164
|
+
const quotaLeft = (() => {
|
|
12165
|
+
const rec = context2;
|
|
12166
|
+
const v = rec && typeof rec["quotaLeft"] === "number" ? rec["quotaLeft"] : 999;
|
|
12167
|
+
return v;
|
|
12168
|
+
})();
|
|
12002
12169
|
await trackCommand({
|
|
12003
12170
|
cmd: "clear",
|
|
12004
12171
|
status: "error",
|
|
12005
12172
|
latencyMs: Date.now() - startTime,
|
|
12006
|
-
plan: getUserPlan(),
|
|
12007
|
-
quotaLeft
|
|
12173
|
+
plan: await getUserPlan(),
|
|
12174
|
+
quotaLeft
|
|
12008
12175
|
});
|
|
12009
12176
|
clearTerminal();
|
|
12010
12177
|
return this.success(chalk40__default.default.green("\u2705 Cleared"));
|
|
@@ -12054,7 +12221,7 @@ var init_clear_auto_command = __esm({
|
|
|
12054
12221
|
const args2 = mode === "display" ? ["--mode", "display"] : [];
|
|
12055
12222
|
const res = await commandRegistry2.execute("/clear", args2, context2);
|
|
12056
12223
|
const line = ctx2.getSessionUsageLine();
|
|
12057
|
-
const banner = `Auto clear mode: ${mode}
|
|
12224
|
+
const banner = `Auto clear mode: ${mode}`;
|
|
12058
12225
|
if (res?.success) {
|
|
12059
12226
|
return this.success(`${banner}
|
|
12060
12227
|
${res.message || ""}`.trim());
|
|
@@ -12720,6 +12887,69 @@ var init_ReadyCommandsService = __esm({
|
|
|
12720
12887
|
}
|
|
12721
12888
|
});
|
|
12722
12889
|
|
|
12890
|
+
// src/services/help/HelpArgumentInference.ts
|
|
12891
|
+
function extractFirstJson2(text) {
|
|
12892
|
+
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
12893
|
+
if (fence) return fence[1];
|
|
12894
|
+
const start = text.indexOf("{");
|
|
12895
|
+
const end = text.lastIndexOf("}");
|
|
12896
|
+
if (start >= 0 && end > start) {
|
|
12897
|
+
const cand = text.slice(start, end + 1);
|
|
12898
|
+
try {
|
|
12899
|
+
JSON.parse(cand);
|
|
12900
|
+
return cand;
|
|
12901
|
+
} catch {
|
|
12902
|
+
}
|
|
12903
|
+
}
|
|
12904
|
+
return null;
|
|
12905
|
+
}
|
|
12906
|
+
async function inferHelpTarget(rawText, allowedCommands) {
|
|
12907
|
+
const allowList = allowedCommands.filter((n) => typeof n === "string" && n.trim()).map((n) => n.trim()).slice(0, 200);
|
|
12908
|
+
const system = [
|
|
12909
|
+
"You decide which help to show for the MARIA CLI.",
|
|
12910
|
+
'Allowed results: { target: "general" } or { target: "command", commandName: <one of allowed> }.',
|
|
12911
|
+
'Return JSON only with keys: { "target": "general"|"command", "commandName"?: string, "confidence": number }.',
|
|
12912
|
+
"If the user asks about a specific command (by name or description), select that command. Otherwise choose general.",
|
|
12913
|
+
"Use confidence between 0 and 1. Do not explain."
|
|
12914
|
+
].join("\n");
|
|
12915
|
+
const user = [
|
|
12916
|
+
"User input:",
|
|
12917
|
+
rawText || "(empty)",
|
|
12918
|
+
"",
|
|
12919
|
+
"Allowed command names:",
|
|
12920
|
+
allowList.join(", ")
|
|
12921
|
+
].join("\n");
|
|
12922
|
+
const resp = await callAPI("/v1/ai-proxy", {
|
|
12923
|
+
method: "POST",
|
|
12924
|
+
body: {
|
|
12925
|
+
prompt: `${system}
|
|
12926
|
+
|
|
12927
|
+
---
|
|
12928
|
+
|
|
12929
|
+
${user}`,
|
|
12930
|
+
taskType: "help"
|
|
12931
|
+
}
|
|
12932
|
+
});
|
|
12933
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
12934
|
+
const jsonText = extractFirstJson2(raw) || raw;
|
|
12935
|
+
let parsed = {};
|
|
12936
|
+
try {
|
|
12937
|
+
parsed = JSON.parse(jsonText);
|
|
12938
|
+
} catch {
|
|
12939
|
+
return {};
|
|
12940
|
+
}
|
|
12941
|
+
const out = {};
|
|
12942
|
+
if (parsed.target === "general" || parsed.target === "command") out.target = parsed.target;
|
|
12943
|
+
if (typeof parsed.commandName === "string" && parsed.commandName.trim()) out.commandName = parsed.commandName.trim();
|
|
12944
|
+
if (typeof parsed.confidence === "number") out.confidence = Math.max(0, Math.min(1, parsed.confidence));
|
|
12945
|
+
return out;
|
|
12946
|
+
}
|
|
12947
|
+
var init_HelpArgumentInference = __esm({
|
|
12948
|
+
"src/services/help/HelpArgumentInference.ts"() {
|
|
12949
|
+
init_api_caller();
|
|
12950
|
+
}
|
|
12951
|
+
});
|
|
12952
|
+
|
|
12723
12953
|
// src/slash-commands/categories/core/handlers/HelpCommand.ts
|
|
12724
12954
|
var HelpCommand_exports = {};
|
|
12725
12955
|
__export(HelpCommand_exports, {
|
|
@@ -12733,6 +12963,8 @@ var init_HelpCommand = __esm({
|
|
|
12733
12963
|
init_ReadyCommandsService();
|
|
12734
12964
|
init_telemetry_helper();
|
|
12735
12965
|
init_subscription_manager();
|
|
12966
|
+
init_HelpArgumentInference();
|
|
12967
|
+
init_animations();
|
|
12736
12968
|
HelpCommand = class extends BaseCommand {
|
|
12737
12969
|
name = "help";
|
|
12738
12970
|
category = "core";
|
|
@@ -12781,6 +13013,26 @@ var init_HelpCommand = __esm({
|
|
|
12781
13013
|
await this.trackSuccess(startTime, context2);
|
|
12782
13014
|
return result2;
|
|
12783
13015
|
}
|
|
13016
|
+
const text = (args2.raw || []).join(" ").trim();
|
|
13017
|
+
if (text) {
|
|
13018
|
+
const commandsList = (await this.readyService.getAllReadyCommands()).map((c) => c.name);
|
|
13019
|
+
const spin = new ProcessAnimation();
|
|
13020
|
+
spin.start();
|
|
13021
|
+
try {
|
|
13022
|
+
const inferred = await inferHelpTarget(text, commandsList);
|
|
13023
|
+
const threshold = Number(process.env.MARIA_HELP_CONFIDENCE || "0.7");
|
|
13024
|
+
if (inferred && inferred.target === "command" && inferred.commandName && (inferred.confidence ?? 1) >= threshold) {
|
|
13025
|
+
const result2 = await this.showCommandHelp(inferred.commandName);
|
|
13026
|
+
await this.trackSuccess(startTime, context2);
|
|
13027
|
+
return result2;
|
|
13028
|
+
}
|
|
13029
|
+
} finally {
|
|
13030
|
+
try {
|
|
13031
|
+
spin.stop();
|
|
13032
|
+
} catch {
|
|
13033
|
+
}
|
|
13034
|
+
}
|
|
13035
|
+
}
|
|
12784
13036
|
if (_positional.length > 0) {
|
|
12785
13037
|
const commandName = _positional[0];
|
|
12786
13038
|
if (commandName) {
|
|
@@ -12927,44 +13179,6 @@ var init_HelpCommand = __esm({
|
|
|
12927
13179
|
* Show help for specific command
|
|
12928
13180
|
*/
|
|
12929
13181
|
async showCommandHelp(commandName) {
|
|
12930
|
-
if (commandName.replace(/^\//, "") === "code") {
|
|
12931
|
-
const lines2 = [];
|
|
12932
|
-
lines2.push("Usage: /code <request> [flags]");
|
|
12933
|
-
lines2.push("");
|
|
12934
|
-
lines2.push("Flags:");
|
|
12935
|
-
lines2.push(" --plan-only|--sow Show plan only (no writes)");
|
|
12936
|
-
lines2.push(" --apply Apply plan (use with --yes for non-interactive)");
|
|
12937
|
-
lines2.push(" --dry-run No writes; render output and hints");
|
|
12938
|
-
lines2.push(" --interactive Approve interactively (a=all s=skip v=view d=diff q=cancel)");
|
|
12939
|
-
lines2.push(" --yes Approve all (including overwrites)");
|
|
12940
|
-
lines2.push(" --max-files N Clamp number of files");
|
|
12941
|
-
lines2.push(" --root DIR Output root directory");
|
|
12942
|
-
lines2.push(" --rollback on|off Rollback on failure (default on)");
|
|
12943
|
-
lines2.push(" --output names|summary|detail");
|
|
12944
|
-
lines2.push(" --no-code Hide code blocks entirely");
|
|
12945
|
-
lines2.push(" --preview-lines N Show head of code in detail mode");
|
|
12946
|
-
lines2.push(" --git-guard on|off Check clean git tree before apply (CI default on)");
|
|
12947
|
-
lines2.push(" --git-commit on|off Create a single git commit after apply");
|
|
12948
|
-
lines2.push(" --git-branch <name> Create/switch branch before committing");
|
|
12949
|
-
lines2.push(" --git-tag <name> Create an annotated tag after committing");
|
|
12950
|
-
lines2.push(" --git-tag-prefix <pfx> Use standardized tag when --git-tag auto: <pfx><YYYYMMDD>-<shortsha>");
|
|
12951
|
-
lines2.push(" --git-push on|off Push commit and tag to remote");
|
|
12952
|
-
lines2.push(" --git-push-remote <name> Remote name for push (default origin)");
|
|
12953
|
-
lines2.push(" --allow-dotfiles Allow writing dotfiles (default deny)");
|
|
12954
|
-
lines2.push(" --confirm-overwrites <globs>");
|
|
12955
|
-
lines2.push("");
|
|
12956
|
-
lines2.push("Tips:");
|
|
12957
|
-
lines2.push(' HINT: Try /code --plan-only "your request" before applying changes');
|
|
12958
|
-
lines2.push(" Recipes:");
|
|
12959
|
-
lines2.push(' \u2022 Plan only: /code --plan-only "create auth form + API"');
|
|
12960
|
-
lines2.push(' \u2022 Apply with limit: /code --apply --yes --max-files 5 "react + test"');
|
|
12961
|
-
lines2.push(' \u2022 Interactive: /code --interactive --output detail --preview-lines 20 "routes + guards"');
|
|
12962
|
-
lines2.push(" \u2022 Apply + branch + auto tag + push:");
|
|
12963
|
-
lines2.push(" /code --apply --yes --git-guard on --git-commit on \\");
|
|
12964
|
-
lines2.push(" --git-branch feature/code-plan --git-tag auto --git-tag-prefix code-plan- \\");
|
|
12965
|
-
lines2.push(' --git-push on --git-push-remote origin "implement auth + tests"');
|
|
12966
|
-
return this.success(lines2.join("\n"));
|
|
12967
|
-
}
|
|
12968
13182
|
const command = await this.readyService.getCommand(commandName);
|
|
12969
13183
|
if (!command) {
|
|
12970
13184
|
const searchResults = await this.readyService.searchCommands(commandName, 3);
|
|
@@ -16168,8 +16382,8 @@ var require_package = __commonJS({
|
|
|
16168
16382
|
"package.json"(exports, module) {
|
|
16169
16383
|
module.exports = {
|
|
16170
16384
|
name: "@bonginkan/maria",
|
|
16171
|
-
version: "4.3.
|
|
16172
|
-
description: "\u{1F680} MARIA v4.3.
|
|
16385
|
+
version: "4.3.37",
|
|
16386
|
+
description: "\u{1F680} MARIA v4.3.37 - 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.",
|
|
16173
16387
|
keywords: [
|
|
16174
16388
|
"ai",
|
|
16175
16389
|
"cli",
|
|
@@ -22263,6 +22477,201 @@ var init_types4 = __esm({
|
|
|
22263
22477
|
];
|
|
22264
22478
|
}
|
|
22265
22479
|
});
|
|
22480
|
+
|
|
22481
|
+
// src/services/media-orchestrator/NLInference.ts
|
|
22482
|
+
function clampSize(size) {
|
|
22483
|
+
const clamp = (n) => Math.min(2048, Math.max(256, Math.floor(n)));
|
|
22484
|
+
return [clamp(size[0]), clamp(size[1])];
|
|
22485
|
+
}
|
|
22486
|
+
function parseExplicitSize(text) {
|
|
22487
|
+
const m2 = /(\d{2,4})\s*[x×]\s*(\d{2,4})/i.exec(text);
|
|
22488
|
+
if (m2) {
|
|
22489
|
+
const w = Number(m2[1]);
|
|
22490
|
+
const h2 = Number(m2[2]);
|
|
22491
|
+
if (Number.isFinite(w) && Number.isFinite(h2)) return clampSize([w, h2]);
|
|
22492
|
+
}
|
|
22493
|
+
const p = /(2160|1440|1080|720)\s*p\b/i.exec(text);
|
|
22494
|
+
if (p) {
|
|
22495
|
+
const h2 = Number(p[1]);
|
|
22496
|
+
const map = {
|
|
22497
|
+
2160: [3840, 2160],
|
|
22498
|
+
1440: [2560, 1440],
|
|
22499
|
+
1080: [1920, 1080],
|
|
22500
|
+
720: [1280, 720]
|
|
22501
|
+
};
|
|
22502
|
+
return clampSize(map[h2]);
|
|
22503
|
+
}
|
|
22504
|
+
return void 0;
|
|
22505
|
+
}
|
|
22506
|
+
function parseAspect(text) {
|
|
22507
|
+
if (/16\s*:\s*9/.test(text)) return "16:9";
|
|
22508
|
+
if (/9\s*:\s*16/.test(text)) return "9:16";
|
|
22509
|
+
if (/1\s*:\s*1/.test(text)) return "1:1";
|
|
22510
|
+
if (/(wide|landscape)/i.test(text)) return "16:9";
|
|
22511
|
+
if (/(tall|portrait)/i.test(text)) return "9:16";
|
|
22512
|
+
if (/(landscape|横長|横向き)/i.test(text)) return "16:9";
|
|
22513
|
+
if (/(portrait|縦長|縦向き)/i.test(text)) return "9:16";
|
|
22514
|
+
if (/(square|正方形|スクエア)/i.test(text)) return "1:1";
|
|
22515
|
+
return void 0;
|
|
22516
|
+
}
|
|
22517
|
+
function deriveSizeFromAspect(aspect, base) {
|
|
22518
|
+
const side = 1024;
|
|
22519
|
+
if (aspect === "1:1") return clampSize([side, side]);
|
|
22520
|
+
if (aspect === "16:9") {
|
|
22521
|
+
const w2 = Math.max(side, 1280);
|
|
22522
|
+
const h3 = Math.round(w2 / 16 * 9);
|
|
22523
|
+
return clampSize([w2, h3]);
|
|
22524
|
+
}
|
|
22525
|
+
const h2 = Math.max(side, 1920);
|
|
22526
|
+
const w = Math.round(h2 / 16 * 9);
|
|
22527
|
+
return clampSize([w, h2]);
|
|
22528
|
+
}
|
|
22529
|
+
function parse4KHints(text, aspect) {
|
|
22530
|
+
if (/(\b4k\b|uhd|超高精細|超高解像度)/i.test(text)) {
|
|
22531
|
+
if (aspect === "1:1" || /square|正方形|スクエア/i.test(text)) return clampSize([2048, 2048]);
|
|
22532
|
+
if (aspect === "9:16" || /(portrait|縦長|縦向き)/i.test(text)) return clampSize([1152, 2048]);
|
|
22533
|
+
return clampSize([2048, 1152]);
|
|
22534
|
+
}
|
|
22535
|
+
if (/(2k|1440p)/i.test(text)) {
|
|
22536
|
+
if (aspect === "1:1") return clampSize([1440, 1440]);
|
|
22537
|
+
if (aspect === "9:16") return clampSize([810, 1440]);
|
|
22538
|
+
return clampSize([1440, 810]);
|
|
22539
|
+
}
|
|
22540
|
+
return void 0;
|
|
22541
|
+
}
|
|
22542
|
+
function parseUseCaseSize(text, aspectHint) {
|
|
22543
|
+
if (/(icon|アイコン)/i.test(text)) return [512, 512];
|
|
22544
|
+
if (/(thumbnail|サムネ)/i.test(text)) return [1280, 720];
|
|
22545
|
+
if (/(instagram\s*story|インスタ\s*ストーリー)/i.test(text)) return [1080, 1920];
|
|
22546
|
+
if (/(instagram\s*post|インスタ\s*投稿)/i.test(text)) return [1080, 1080];
|
|
22547
|
+
if (/(twitter\s*header|x\s*header)/i.test(text)) return [1500, 500];
|
|
22548
|
+
if (/(hd|フルhd)/i.test(text)) return [1920, 1080];
|
|
22549
|
+
if (aspectHint) return deriveSizeFromAspect(aspectHint);
|
|
22550
|
+
if (/(portrait|縦長|縦向き)/i.test(text)) return deriveSizeFromAspect("9:16");
|
|
22551
|
+
if (/(landscape|横長|横向き)/i.test(text)) return deriveSizeFromAspect("16:9");
|
|
22552
|
+
if (/(square|正方形|スクエア)/i.test(text)) return [1024, 1024];
|
|
22553
|
+
return void 0;
|
|
22554
|
+
}
|
|
22555
|
+
function inferFormat(text) {
|
|
22556
|
+
if (/(png|透過|alpha)/i.test(text)) return "png";
|
|
22557
|
+
if (/(webp|ウェブピー)/i.test(text)) return "webp";
|
|
22558
|
+
if (/(jpg|jpeg|写真|photo)/i.test(text)) return "jpg";
|
|
22559
|
+
return void 0;
|
|
22560
|
+
}
|
|
22561
|
+
function inferImageOptionsFromText(text) {
|
|
22562
|
+
const lower2 = text.toLowerCase();
|
|
22563
|
+
const aspect = parseAspect(lower2);
|
|
22564
|
+
const exp = parseExplicitSize(lower2);
|
|
22565
|
+
const k4 = parse4KHints(lower2, aspect);
|
|
22566
|
+
const use = parseUseCaseSize(lower2, aspect);
|
|
22567
|
+
const size = exp || k4 || use;
|
|
22568
|
+
const format = inferFormat(lower2);
|
|
22569
|
+
const out = {};
|
|
22570
|
+
if (size) out.size = size;
|
|
22571
|
+
if (format) out.format = format;
|
|
22572
|
+
return out;
|
|
22573
|
+
}
|
|
22574
|
+
var init_NLInference = __esm({
|
|
22575
|
+
"src/services/media-orchestrator/NLInference.ts"() {
|
|
22576
|
+
}
|
|
22577
|
+
});
|
|
22578
|
+
|
|
22579
|
+
// src/services/media-orchestrator/ImageArgumentInference.ts
|
|
22580
|
+
function extractFirstJson3(text) {
|
|
22581
|
+
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
22582
|
+
if (fence) return fence[1];
|
|
22583
|
+
const fencePlain = /```\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
22584
|
+
if (fencePlain) {
|
|
22585
|
+
try {
|
|
22586
|
+
JSON.parse(fencePlain[1]);
|
|
22587
|
+
return fencePlain[1];
|
|
22588
|
+
} catch {
|
|
22589
|
+
}
|
|
22590
|
+
}
|
|
22591
|
+
const start = text.indexOf("{");
|
|
22592
|
+
const end = text.lastIndexOf("}");
|
|
22593
|
+
if (start >= 0 && end > start) {
|
|
22594
|
+
const cand = text.slice(start, end + 1);
|
|
22595
|
+
try {
|
|
22596
|
+
JSON.parse(cand);
|
|
22597
|
+
return cand;
|
|
22598
|
+
} catch {
|
|
22599
|
+
}
|
|
22600
|
+
}
|
|
22601
|
+
return null;
|
|
22602
|
+
}
|
|
22603
|
+
function clampSize2(size) {
|
|
22604
|
+
const clamp = (n) => Math.min(4096, Math.max(256, Math.floor(n)));
|
|
22605
|
+
return [clamp(size[0]), clamp(size[1])];
|
|
22606
|
+
}
|
|
22607
|
+
function parseSizeAny(x2) {
|
|
22608
|
+
if (typeof x2 === "string") {
|
|
22609
|
+
const m2 = /^\s*(\d{2,4})x(\d{2,4})\s*$/i.exec(x2);
|
|
22610
|
+
if (m2) return clampSize2([Number(m2[1]), Number(m2[2])]);
|
|
22611
|
+
}
|
|
22612
|
+
if (x2 && typeof x2 === "object") {
|
|
22613
|
+
const any = x2;
|
|
22614
|
+
const w = Number(any.width ?? any.w);
|
|
22615
|
+
const h2 = Number(any.height ?? any.h);
|
|
22616
|
+
if (Number.isFinite(w) && Number.isFinite(h2)) return clampSize2([w, h2]);
|
|
22617
|
+
}
|
|
22618
|
+
return void 0;
|
|
22619
|
+
}
|
|
22620
|
+
function sanitizeFormat(fmt) {
|
|
22621
|
+
if (typeof fmt !== "string") return void 0;
|
|
22622
|
+
const f3 = fmt.toLowerCase();
|
|
22623
|
+
const mapped = f3 === "jpeg" ? "jpg" : f3;
|
|
22624
|
+
return ["png", "webp", "jpg"].includes(mapped) ? mapped : void 0;
|
|
22625
|
+
}
|
|
22626
|
+
async function inferImageArgsLLM(promptText) {
|
|
22627
|
+
const system = [
|
|
22628
|
+
"You extract image generation options from user natural language.",
|
|
22629
|
+
'Return JSON only with keys: { "size"?: "WIDTHxHEIGHT", "format"?: "png|webp|jpg", "count"?: number }.',
|
|
22630
|
+
'Only include "count" if the user explicitly specifies the number of images (e.g., "2 images"). Otherwise omit (default is 1).',
|
|
22631
|
+
'Only include "format" if the user explicitly specifies a format (e.g., "png", "webp", "jpg", transparency). Otherwise omit (default is png).',
|
|
22632
|
+
'Size must be a single string "WIDTHxHEIGHT". If the user implies aspect/resolution (e.g., "wide"/"landscape" => 16:9, "tall"/"portrait" => 9:16, "square" => 1:1, or 4K/UHD/1080p/720p), select a reasonable resolution within 256..4096 per side and return it as "WIDTHxHEIGHT".',
|
|
22633
|
+
"If size is not specified or implied, omit it (default is 1024x1024).",
|
|
22634
|
+
"Do NOT include model or keepExif unless the user explicitly specified them; otherwise omit.",
|
|
22635
|
+
"Do not include any explanation text; JSON only."
|
|
22636
|
+
].join("\n");
|
|
22637
|
+
const user = promptText;
|
|
22638
|
+
const response = await callAPI("/v1/ai-proxy", {
|
|
22639
|
+
method: "POST",
|
|
22640
|
+
body: {
|
|
22641
|
+
prompt: `${system}
|
|
22642
|
+
|
|
22643
|
+
---
|
|
22644
|
+
|
|
22645
|
+
${user}`,
|
|
22646
|
+
taskType: "media"
|
|
22647
|
+
}
|
|
22648
|
+
});
|
|
22649
|
+
const raw = (response?.data?.content || response?.output || "").trim();
|
|
22650
|
+
const jsonText = extractFirstJson3(raw) || raw;
|
|
22651
|
+
let parsed;
|
|
22652
|
+
try {
|
|
22653
|
+
parsed = JSON.parse(jsonText);
|
|
22654
|
+
} catch {
|
|
22655
|
+
return {};
|
|
22656
|
+
}
|
|
22657
|
+
const out = {};
|
|
22658
|
+
const size = parseSizeAny(parsed?.size);
|
|
22659
|
+
if (size) out.size = size;
|
|
22660
|
+
const fmt = sanitizeFormat(parsed?.format);
|
|
22661
|
+
if (fmt) out.format = fmt;
|
|
22662
|
+
if (Number.isFinite(Number(parsed?.count))) {
|
|
22663
|
+
const n = Math.max(1, Math.min(8, Math.floor(Number(parsed.count))));
|
|
22664
|
+
out.count = n;
|
|
22665
|
+
}
|
|
22666
|
+
if (typeof parsed?.model === "string" && parsed.model.trim()) out.model = String(parsed.model).trim();
|
|
22667
|
+
if (typeof parsed?.keepExif === "boolean") out.keepExif = parsed.keepExif;
|
|
22668
|
+
return out;
|
|
22669
|
+
}
|
|
22670
|
+
var init_ImageArgumentInference = __esm({
|
|
22671
|
+
"src/services/media-orchestrator/ImageArgumentInference.ts"() {
|
|
22672
|
+
init_api_caller();
|
|
22673
|
+
}
|
|
22674
|
+
});
|
|
22266
22675
|
function parseSize(value) {
|
|
22267
22676
|
const m2 = /^\s*(\d{2,4})x(\d{2,4})\s*$/i.exec(value || "");
|
|
22268
22677
|
if (!m2) throw new Error(`invalid size: ${value}`);
|
|
@@ -22295,6 +22704,8 @@ function normalizeImageArgs(raw, root) {
|
|
|
22295
22704
|
planOnly: false,
|
|
22296
22705
|
dryRun: false
|
|
22297
22706
|
};
|
|
22707
|
+
let explicitSize = false;
|
|
22708
|
+
let explicitFormat = false;
|
|
22298
22709
|
while (args2.length) {
|
|
22299
22710
|
const x2 = args2.shift();
|
|
22300
22711
|
if (!x2.startsWith("--")) continue;
|
|
@@ -22303,12 +22714,14 @@ function normalizeImageArgs(raw, root) {
|
|
|
22303
22714
|
switch (k) {
|
|
22304
22715
|
case "size":
|
|
22305
22716
|
out.size = parseSize(String(v));
|
|
22717
|
+
explicitSize = true;
|
|
22306
22718
|
break;
|
|
22307
22719
|
case "format": {
|
|
22308
22720
|
const rawFmt = String(v).toLowerCase();
|
|
22309
22721
|
const mapped = rawFmt === "jpeg" ? "jpg" : rawFmt;
|
|
22310
22722
|
if (!["png", "webp", "jpg"].includes(mapped)) throw new Error("invalid format");
|
|
22311
22723
|
out.format = mapped;
|
|
22724
|
+
explicitFormat = true;
|
|
22312
22725
|
break;
|
|
22313
22726
|
}
|
|
22314
22727
|
case "count": {
|
|
@@ -22349,6 +22762,21 @@ function normalizeImageArgs(raw, root) {
|
|
|
22349
22762
|
break;
|
|
22350
22763
|
}
|
|
22351
22764
|
}
|
|
22765
|
+
try {
|
|
22766
|
+
const inferred = inferImageOptionsFromText(prompt);
|
|
22767
|
+
if (!explicitSize && inferred.size) out.size = inferred.size;
|
|
22768
|
+
if (!explicitFormat && inferred.format) out.format = inferred.format;
|
|
22769
|
+
} catch {
|
|
22770
|
+
}
|
|
22771
|
+
try {
|
|
22772
|
+
if (String(process.env.MARIA_USE_LLM_INFER || "1") === "1" && (!explicitSize || !explicitFormat)) {
|
|
22773
|
+
global.__MARIA_IMAGE_LLM_INFER__ = async () => {
|
|
22774
|
+
const llm = await inferImageArgsLLM(prompt);
|
|
22775
|
+
return llm;
|
|
22776
|
+
};
|
|
22777
|
+
}
|
|
22778
|
+
} catch {
|
|
22779
|
+
}
|
|
22352
22780
|
const pixels = out.size[0] * out.size[1] * out.count;
|
|
22353
22781
|
if (pixels > (out.budgetPixels || 0)) throw new Error("budget exceeded");
|
|
22354
22782
|
if (!out.apply && !out.planOnly && !out.dryRun) {
|
|
@@ -22381,7 +22809,8 @@ function normalizeVideoArgs(raw, root) {
|
|
|
22381
22809
|
retry: 2,
|
|
22382
22810
|
apply: false,
|
|
22383
22811
|
planOnly: false,
|
|
22384
|
-
dryRun: false
|
|
22812
|
+
dryRun: false,
|
|
22813
|
+
aspect: "16:9"
|
|
22385
22814
|
};
|
|
22386
22815
|
while (args2.length) {
|
|
22387
22816
|
const x2 = args2.shift();
|
|
@@ -22395,9 +22824,43 @@ function normalizeVideoArgs(raw, root) {
|
|
|
22395
22824
|
case "fps":
|
|
22396
22825
|
out.fps = clampInt(v, 1, 60, "fps");
|
|
22397
22826
|
break;
|
|
22398
|
-
case "
|
|
22399
|
-
|
|
22827
|
+
case "size": {
|
|
22828
|
+
const sz = parseSize(String(v));
|
|
22829
|
+
out.size = sz;
|
|
22830
|
+
out.aspect = sz[0] >= sz[1] ? "16:9" : "9:16";
|
|
22400
22831
|
break;
|
|
22832
|
+
}
|
|
22833
|
+
case "res": {
|
|
22834
|
+
const sv = String(v).toLowerCase().replace(/p$/, "");
|
|
22835
|
+
if (/^\d+x\d+$/i.test(String(v))) {
|
|
22836
|
+
out.size = parseSize(String(v));
|
|
22837
|
+
out.aspect = out.size[0] >= out.size[1] ? "16:9" : "9:16";
|
|
22838
|
+
} else if (sv === "720") {
|
|
22839
|
+
out.size = out.aspect === "9:16" ? [720, 1280] : [1280, 720];
|
|
22840
|
+
} else if (sv === "1080") {
|
|
22841
|
+
out.size = out.aspect === "9:16" ? [1080, 1920] : [1920, 1080];
|
|
22842
|
+
} else {
|
|
22843
|
+
throw new Error("invalid res (use 720|1080 or WIDTHxHEIGHT)");
|
|
22844
|
+
}
|
|
22845
|
+
break;
|
|
22846
|
+
}
|
|
22847
|
+
case "aspect": {
|
|
22848
|
+
const a = String(v);
|
|
22849
|
+
if (a !== "16:9" && a !== "9:16") throw new Error("invalid aspect (use 16:9|9:16)");
|
|
22850
|
+
out.aspect = a;
|
|
22851
|
+
const [w, h2] = out.size;
|
|
22852
|
+
if (w === 1280 && h2 === 720 || w === 720 && h2 === 1280 || w === 1920 && h2 === 1080 || w === 1080 && h2 === 1920) {
|
|
22853
|
+
if (a === "9:16") {
|
|
22854
|
+
if (h2 === 720) out.size = [720, 1280];
|
|
22855
|
+
else if (h2 === 1080) out.size = [1080, 1920];
|
|
22856
|
+
} else {
|
|
22857
|
+
if (w === 720) out.size = [1280, 720];
|
|
22858
|
+
else if (w === 1080) out.size = [1920, 1080];
|
|
22859
|
+
if (w === 1080 && h2 === 1920) out.size = [1920, 1080];
|
|
22860
|
+
}
|
|
22861
|
+
}
|
|
22862
|
+
break;
|
|
22863
|
+
}
|
|
22401
22864
|
case "format":
|
|
22402
22865
|
if (!["mp4", "webm"].includes(String(v))) throw new Error("invalid format");
|
|
22403
22866
|
out.format = v;
|
|
@@ -22433,7 +22896,11 @@ function normalizeVideoArgs(raw, root) {
|
|
|
22433
22896
|
}
|
|
22434
22897
|
const caps = chooseCaps("video", out.model);
|
|
22435
22898
|
if (caps?.maxVideoSize) {
|
|
22436
|
-
|
|
22899
|
+
const reqMax = Math.max(out.size[0], out.size[1]);
|
|
22900
|
+
const reqMin = Math.min(out.size[0], out.size[1]);
|
|
22901
|
+
const capMax = Math.max(caps.maxVideoSize[0], caps.maxVideoSize[1]);
|
|
22902
|
+
const capMin = Math.min(caps.maxVideoSize[0], caps.maxVideoSize[1]);
|
|
22903
|
+
if (reqMax > capMax || reqMin > capMin) throw new Error("resolution exceeds model capability");
|
|
22437
22904
|
}
|
|
22438
22905
|
if (caps?.maxDuration && out.duration > caps.maxDuration) throw new Error("duration exceeds model capability");
|
|
22439
22906
|
if (caps?.maxFps && out.fps > caps.maxFps) throw new Error("fps exceeds model capability");
|
|
@@ -22461,6 +22928,8 @@ function sanitizeOut(outDir, root) {
|
|
|
22461
22928
|
var init_Normalizer = __esm({
|
|
22462
22929
|
"src/services/media-orchestrator/Normalizer.ts"() {
|
|
22463
22930
|
init_types4();
|
|
22931
|
+
init_NLInference();
|
|
22932
|
+
init_ImageArgumentInference();
|
|
22464
22933
|
}
|
|
22465
22934
|
});
|
|
22466
22935
|
function ensureDirSync(p) {
|
|
@@ -23322,6 +23791,19 @@ var init_image_command = __esm({
|
|
|
23322
23791
|
const spinner = new ProcessAnimation();
|
|
23323
23792
|
spinner.start();
|
|
23324
23793
|
try {
|
|
23794
|
+
try {
|
|
23795
|
+
const hook = global.__MARIA_IMAGE_LLM_INFER__;
|
|
23796
|
+
if (hook) {
|
|
23797
|
+
const llm = await hook();
|
|
23798
|
+
if (llm) {
|
|
23799
|
+
if (llm.size && (!Array.isArray(cli.size) || cli.size.length !== 2)) cli.size = llm.size;
|
|
23800
|
+
if (llm.size && Array.isArray(llm.size)) cli.size = llm.size;
|
|
23801
|
+
if (llm.format) cli.format = llm.format;
|
|
23802
|
+
if (Number.isFinite(Number(llm.count))) cli.count = Math.max(1, Math.min(8, Math.floor(Number(llm.count))));
|
|
23803
|
+
}
|
|
23804
|
+
}
|
|
23805
|
+
} catch {
|
|
23806
|
+
}
|
|
23325
23807
|
const useRemote = String(process.env.MARIA_USE_REMOTE_MEDIA || "").toLowerCase() === "1" && await authManager.isAuthenticated();
|
|
23326
23808
|
if (useRemote) {
|
|
23327
23809
|
try {
|
|
@@ -23633,12 +24115,18 @@ async function runVideoPipeline(params2, opts) {
|
|
|
23633
24115
|
const { GoogleGenAI } = __require("@google/genai");
|
|
23634
24116
|
const ai2 = new GoogleGenAI({ apiKey });
|
|
23635
24117
|
const modelName = params2.model || "veo-3.0-generate-001";
|
|
23636
|
-
const aspectRatio =
|
|
24118
|
+
const aspectRatio = "16:9";
|
|
24119
|
+
const resolution = Math.max(params2.size[0], params2.size[1]) >= 1920 ? "1080p" : "720p";
|
|
23637
24120
|
const effectiveDuration = 8;
|
|
23638
24121
|
let operation = await ai2.models.generateVideos({
|
|
23639
24122
|
model: modelName,
|
|
23640
24123
|
prompt: String(params2.prompt),
|
|
23641
|
-
config: {
|
|
24124
|
+
config: {
|
|
24125
|
+
aspectRatio,
|
|
24126
|
+
/* resolution: resolution, */
|
|
24127
|
+
durationSeconds: effectiveDuration,
|
|
24128
|
+
frameRate: params2.fps
|
|
24129
|
+
}
|
|
23642
24130
|
});
|
|
23643
24131
|
const pollStart = Date.now();
|
|
23644
24132
|
const maxWaitMs = 6 * 60 * 1e3;
|
|
@@ -23790,7 +24278,7 @@ var init_video_command = __esm({
|
|
|
23790
24278
|
category = "media";
|
|
23791
24279
|
description = "Generate videos using Gemini (frames fallback when mux unavailable)";
|
|
23792
24280
|
aliases = [];
|
|
23793
|
-
usage = '/video "prompt" [--duration 8] [--fps 24] [--res
|
|
24281
|
+
usage = '/video "prompt" [--duration 8] [--fps 24] [--aspect 16:9|9:16] [--res 720|1080] [--format mp4|webm] [--model gemini-...] [--seed N] [--out dir] [--apply|--plan-only|--dry-run] [--concurrency N] [--retry N]';
|
|
23794
24282
|
examples = [
|
|
23795
24283
|
{ input: '/video "product demo" --duration 8 --fps 24 --res 1280x720 --apply', description: "Generate a short demo video" }
|
|
23796
24284
|
];
|
|
@@ -23811,11 +24299,15 @@ var init_video_command = __esm({
|
|
|
23811
24299
|
const useRemote = String(process.env.MARIA_USE_REMOTE_MEDIA || "").toLowerCase() === "1" && await authManager.isAuthenticated();
|
|
23812
24300
|
if (useRemote) {
|
|
23813
24301
|
try {
|
|
24302
|
+
const isPortrait = cli.size[1] > cli.size[0];
|
|
24303
|
+
const maxEdge = Math.max(cli.size[0], cli.size[1]);
|
|
24304
|
+
const discrete = maxEdge >= 1920 ? "1080" : maxEdge >= 1280 ? "720" : void 0;
|
|
23814
24305
|
const body = {
|
|
23815
24306
|
prompt: cli.prompt,
|
|
23816
24307
|
duration: cli.duration,
|
|
23817
24308
|
fps: cli.fps,
|
|
23818
|
-
res: `${cli.size[0]}x${cli.size[1]}`,
|
|
24309
|
+
res: discrete ? discrete : `${cli.size[0]}x${cli.size[1]}`,
|
|
24310
|
+
aspect: isPortrait ? "9:16" : "16:9",
|
|
23819
24311
|
format: cli.format,
|
|
23820
24312
|
model: cli.model,
|
|
23821
24313
|
seed: cli.seed
|
|
@@ -25897,7 +26389,7 @@ var init_about_command = __esm({
|
|
|
25897
26389
|
async execute(args2, context2) {
|
|
25898
26390
|
const output3 = [];
|
|
25899
26391
|
output3.push("");
|
|
25900
|
-
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.
|
|
26392
|
+
output3.push(chalk40__default.default.cyan.bold("\u{1F916} About MARIA v4.3.37"));
|
|
25901
26393
|
output3.push(chalk40__default.default.gray("\u2550".repeat(40)));
|
|
25902
26394
|
output3.push("");
|
|
25903
26395
|
output3.push(chalk40__default.default.white.bold("MARIA - Minimal API, Maximum Power"));
|
|
@@ -38049,6 +38541,62 @@ var init_code_utils = __esm({
|
|
|
38049
38541
|
]);
|
|
38050
38542
|
}
|
|
38051
38543
|
});
|
|
38544
|
+
|
|
38545
|
+
// src/services/code-orchestrator/ArgumentInference.ts
|
|
38546
|
+
function extractFirstJson4(text) {
|
|
38547
|
+
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
38548
|
+
if (fence) return fence[1];
|
|
38549
|
+
const start = text.indexOf("{");
|
|
38550
|
+
const end = text.lastIndexOf("}");
|
|
38551
|
+
if (start >= 0 && end > start) {
|
|
38552
|
+
const cand = text.slice(start, end + 1);
|
|
38553
|
+
try {
|
|
38554
|
+
JSON.parse(cand);
|
|
38555
|
+
return cand;
|
|
38556
|
+
} catch {
|
|
38557
|
+
}
|
|
38558
|
+
}
|
|
38559
|
+
return null;
|
|
38560
|
+
}
|
|
38561
|
+
async function inferCodeArgs(rawText) {
|
|
38562
|
+
const system = [
|
|
38563
|
+
"You extract structured options for a code command.",
|
|
38564
|
+
'Return JSON only with keys: { "planOnly"?: boolean, "dryRun"?: boolean, "output"?: "names"|"summary"|"detail", "previewLines"?: number }.',
|
|
38565
|
+
"Decide from the user text whether planOnly or dryRun should be true. Do not explain.",
|
|
38566
|
+
"Only include output if the user requests preview detail or summary mode. Only include previewLines if a specific number of lines is requested."
|
|
38567
|
+
].join("\n");
|
|
38568
|
+
const resp = await callAPI("/v1/ai-proxy", {
|
|
38569
|
+
method: "POST",
|
|
38570
|
+
body: {
|
|
38571
|
+
prompt: `${system}
|
|
38572
|
+
|
|
38573
|
+
---
|
|
38574
|
+
|
|
38575
|
+
${rawText}`,
|
|
38576
|
+
taskType: "code"
|
|
38577
|
+
}
|
|
38578
|
+
});
|
|
38579
|
+
const raw = (resp?.data?.content || resp?.output || "").trim();
|
|
38580
|
+
const jsonText = extractFirstJson4(raw) || raw;
|
|
38581
|
+
let parsed = {};
|
|
38582
|
+
try {
|
|
38583
|
+
parsed = JSON.parse(jsonText);
|
|
38584
|
+
} catch {
|
|
38585
|
+
return {};
|
|
38586
|
+
}
|
|
38587
|
+
const out = {};
|
|
38588
|
+
if (typeof parsed.planOnly === "boolean") out.planOnly = parsed.planOnly;
|
|
38589
|
+
if (typeof parsed.dryRun === "boolean") out.dryRun = parsed.dryRun;
|
|
38590
|
+
if (typeof parsed.output === "string" && (parsed.output === "names" || parsed.output === "summary" || parsed.output === "detail")) out.output = parsed.output;
|
|
38591
|
+
if (typeof parsed.previewLines === "number" && Number.isFinite(parsed.previewLines) && parsed.previewLines > 0) out.previewLines = Math.min(2e3, Math.floor(parsed.previewLines));
|
|
38592
|
+
if (out.planOnly) out.dryRun = false;
|
|
38593
|
+
return out;
|
|
38594
|
+
}
|
|
38595
|
+
var init_ArgumentInference = __esm({
|
|
38596
|
+
"src/services/code-orchestrator/ArgumentInference.ts"() {
|
|
38597
|
+
init_api_caller();
|
|
38598
|
+
}
|
|
38599
|
+
});
|
|
38052
38600
|
async function scanRepo(cwd2) {
|
|
38053
38601
|
if (_cache && _cache.root === cwd2) return _cache;
|
|
38054
38602
|
const root = cwd2;
|
|
@@ -38323,7 +38871,8 @@ function formatPlan(summary, opts) {
|
|
|
38323
38871
|
if (opts.requestText && opts.requestText.trim().length > 0) {
|
|
38324
38872
|
lines.push(opts.requestText.trim(), "");
|
|
38325
38873
|
}
|
|
38326
|
-
|
|
38874
|
+
const headerLabel = opts.planView ? "Planned Artifacts" : "Modified Artifacts";
|
|
38875
|
+
lines.push(`${headerLabel} (${summary.planned} files):`);
|
|
38327
38876
|
const warnMap = buildPerFileWarnings(summary.files, opts.validated);
|
|
38328
38877
|
const skippedSet = new Set(opts.validated?.skipped || []);
|
|
38329
38878
|
for (const f3 of summary.files) {
|
|
@@ -38348,18 +38897,20 @@ function formatPlan(summary, opts) {
|
|
|
38348
38897
|
lines.push(diff, "");
|
|
38349
38898
|
}
|
|
38350
38899
|
}
|
|
38351
|
-
|
|
38352
|
-
|
|
38353
|
-
|
|
38354
|
-
|
|
38355
|
-
|
|
38356
|
-
|
|
38357
|
-
|
|
38358
|
-
|
|
38359
|
-
|
|
38900
|
+
if (!opts.planView) {
|
|
38901
|
+
const created = summary.files.filter((f3) => f3.action === "create").length;
|
|
38902
|
+
const modified = summary.files.filter((f3) => f3.action === "modify").length;
|
|
38903
|
+
const skipped = opts.validated?.skipped?.length || 0;
|
|
38904
|
+
const okPhrase = created > 0 ? `${created + modified} files created/modified` : `${modified} files modified`;
|
|
38905
|
+
lines.push(`OK: ${okPhrase}`);
|
|
38906
|
+
if (skipped > 0) lines.push(`WARN: ${skipped} file${skipped > 1 ? "s" : ""} skipped`);
|
|
38907
|
+
lines.push("Next steps:");
|
|
38908
|
+
if (large) {
|
|
38909
|
+
lines.push('- Large output \u2013 previews suppressed. Use --output diff or press "d" in interactive mode');
|
|
38910
|
+
}
|
|
38911
|
+
lines.push("- If this looks correct, commit the changes");
|
|
38912
|
+
lines.push('- For a full diff: rerun with --output diff or press "d" in interactive mode');
|
|
38360
38913
|
}
|
|
38361
|
-
lines.push("- If this looks correct, commit the changes");
|
|
38362
|
-
lines.push('- For a full diff: rerun with --output diff or press "d" in interactive mode');
|
|
38363
38914
|
return lines.join("\n");
|
|
38364
38915
|
}
|
|
38365
38916
|
function okLine(text) {
|
|
@@ -38395,9 +38946,10 @@ function formatPlanAsDiff(files, opts) {
|
|
|
38395
38946
|
bytesUsed += diffBytes;
|
|
38396
38947
|
shownFiles++;
|
|
38397
38948
|
}
|
|
38398
|
-
|
|
38949
|
+
const totalDiffTargets = files.filter((f3) => f3.action === "modify").length;
|
|
38950
|
+
if (totalDiffTargets > shownFiles) {
|
|
38399
38951
|
lines.push(`
|
|
38400
|
-
[${
|
|
38952
|
+
[${totalDiffTargets - shownFiles} more file(s) omitted; re-run with --output diff --diff-lines ${budget.diffLines ?? 200}]`);
|
|
38401
38953
|
}
|
|
38402
38954
|
return lines.join("\n");
|
|
38403
38955
|
}
|
|
@@ -38639,129 +39191,6 @@ var init_InteractiveController = __esm({
|
|
|
38639
39191
|
init_OutputFormatter();
|
|
38640
39192
|
}
|
|
38641
39193
|
});
|
|
38642
|
-
|
|
38643
|
-
// src/services/cli-auth/api-caller.ts
|
|
38644
|
-
var api_caller_exports = {};
|
|
38645
|
-
__export(api_caller_exports, {
|
|
38646
|
-
RateLimitError: () => RateLimitError2,
|
|
38647
|
-
callAPI: () => callAPI,
|
|
38648
|
-
executeAIProxy: () => executeAIProxy,
|
|
38649
|
-
executeChat: () => executeChat,
|
|
38650
|
-
executeCode: () => executeCode
|
|
38651
|
-
});
|
|
38652
|
-
async function callAPI(endpoint, options = {}) {
|
|
38653
|
-
const tokens2 = await authManager2.getValidTokens();
|
|
38654
|
-
if (!tokens2) {
|
|
38655
|
-
throw new Error("Authentication required. Please run /login first.");
|
|
38656
|
-
}
|
|
38657
|
-
const apiBase = process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
38658
|
-
const url2 = `${apiBase}${endpoint}`;
|
|
38659
|
-
const controller = new AbortController();
|
|
38660
|
-
const defaultMs = 6e5;
|
|
38661
|
-
const envMs = Number(process.env.MARIA_API_TIMEOUT_MS || process.env.MARIA_CODE_TIMEOUT_MS || defaultMs);
|
|
38662
|
-
const timeoutMs = Number.isFinite(envMs) && envMs > 0 ? envMs : defaultMs;
|
|
38663
|
-
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
38664
|
-
try {
|
|
38665
|
-
const response = await fetch(url2, {
|
|
38666
|
-
method: options.method || "GET",
|
|
38667
|
-
headers: {
|
|
38668
|
-
"Authorization": `Bearer ${tokens2.accessToken}`,
|
|
38669
|
-
"Content-Type": "application/json",
|
|
38670
|
-
...options.headers
|
|
38671
|
-
},
|
|
38672
|
-
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
38673
|
-
agent,
|
|
38674
|
-
// Use keep-alive agent
|
|
38675
|
-
signal: controller.signal
|
|
38676
|
-
});
|
|
38677
|
-
clearTimeout(timeoutId);
|
|
38678
|
-
if (!response) {
|
|
38679
|
-
throw new Error("\u{1F310} Network error, check connection");
|
|
38680
|
-
}
|
|
38681
|
-
if (response.status === 401) {
|
|
38682
|
-
throw new Error("Session expired. Please run /login again.");
|
|
38683
|
-
}
|
|
38684
|
-
if (response.status === 402) {
|
|
38685
|
-
const data2 = await response.json().catch(() => ({}));
|
|
38686
|
-
throw new Error(`Quota exceeded: ${data2.message || "Please wait or /upgrade"}`);
|
|
38687
|
-
}
|
|
38688
|
-
if (response.status === 403) {
|
|
38689
|
-
const data2 = await response.json().catch(() => ({}));
|
|
38690
|
-
throw new Error(`Not available on Free plan: ${data2.message || "Run /upgrade"}`);
|
|
38691
|
-
}
|
|
38692
|
-
if (response.status === 429) {
|
|
38693
|
-
const h2 = response.headers;
|
|
38694
|
-
const ra = h2.get("Retry-After");
|
|
38695
|
-
const reset = h2.get("RateLimit-Reset") || h2.get("X-RateLimit-Reset");
|
|
38696
|
-
let waitSec = 3;
|
|
38697
|
-
if (ra && /^\d+$/.test(ra)) {
|
|
38698
|
-
waitSec = +ra;
|
|
38699
|
-
} else if (ra) {
|
|
38700
|
-
const t2 = Date.parse(ra);
|
|
38701
|
-
if (!isNaN(t2)) waitSec = Math.max(1, Math.ceil((t2 - Date.now()) / 1e3));
|
|
38702
|
-
} else if (reset) {
|
|
38703
|
-
waitSec = Math.max(1, Math.ceil((+reset - Date.now()) / 1e3));
|
|
38704
|
-
}
|
|
38705
|
-
throw new RateLimitError2(`\u23F1 Wait ${waitSec}s`, waitSec);
|
|
38706
|
-
}
|
|
38707
|
-
if (!response.ok) {
|
|
38708
|
-
const data2 = await response.json().catch(() => ({}));
|
|
38709
|
-
throw new Error(data2.error || `Request failed: ${response.statusText}`);
|
|
38710
|
-
}
|
|
38711
|
-
const data = await response.json();
|
|
38712
|
-
return data;
|
|
38713
|
-
} catch (error2) {
|
|
38714
|
-
clearTimeout(timeoutId);
|
|
38715
|
-
if (error2.name === "AbortError") {
|
|
38716
|
-
throw new Error("\u{1F310} Network error, check connection");
|
|
38717
|
-
}
|
|
38718
|
-
throw error2;
|
|
38719
|
-
}
|
|
38720
|
-
}
|
|
38721
|
-
async function executeChat(messages) {
|
|
38722
|
-
const response = await callAPI("/v1/chat", {
|
|
38723
|
-
method: "POST",
|
|
38724
|
-
body: { messages }
|
|
38725
|
-
});
|
|
38726
|
-
return response;
|
|
38727
|
-
}
|
|
38728
|
-
async function executeCode(prompt) {
|
|
38729
|
-
const response = await callAPI("/v1/ai-proxy", {
|
|
38730
|
-
method: "POST",
|
|
38731
|
-
body: {
|
|
38732
|
-
prompt,
|
|
38733
|
-
taskType: "code"
|
|
38734
|
-
}
|
|
38735
|
-
});
|
|
38736
|
-
if (response.data?.routedModel) {
|
|
38737
|
-
response.routedModel = response.data.routedModel;
|
|
38738
|
-
}
|
|
38739
|
-
if (response.data?.content) {
|
|
38740
|
-
response.output = response.data.content;
|
|
38741
|
-
}
|
|
38742
|
-
return response;
|
|
38743
|
-
}
|
|
38744
|
-
async function executeAIProxy(provider, model, messages, options) {
|
|
38745
|
-
return callAPI("/v1/ai-proxy", {
|
|
38746
|
-
method: "POST",
|
|
38747
|
-
body: { provider, model, messages, options }
|
|
38748
|
-
});
|
|
38749
|
-
}
|
|
38750
|
-
var agent, authManager2, RateLimitError2;
|
|
38751
|
-
var init_api_caller = __esm({
|
|
38752
|
-
"src/services/cli-auth/api-caller.ts"() {
|
|
38753
|
-
init_AuthenticationManager();
|
|
38754
|
-
agent = new https__default.default.Agent({ keepAlive: true });
|
|
38755
|
-
authManager2 = new AuthenticationManager();
|
|
38756
|
-
RateLimitError2 = class extends Error {
|
|
38757
|
-
constructor(message, retryAfter) {
|
|
38758
|
-
super(message);
|
|
38759
|
-
this.retryAfter = retryAfter;
|
|
38760
|
-
this.name = "RateLimitError";
|
|
38761
|
-
}
|
|
38762
|
-
};
|
|
38763
|
-
}
|
|
38764
|
-
});
|
|
38765
39194
|
async function mapAttachmentsToTargets(attached, opts) {
|
|
38766
39195
|
const warnings = [];
|
|
38767
39196
|
const mapped = [];
|
|
@@ -39209,7 +39638,68 @@ ${requestPreamble}
|
|
|
39209
39638
|
${request}
|
|
39210
39639
|
|
|
39211
39640
|
${editContext}`;
|
|
39212
|
-
const
|
|
39641
|
+
const ctxAttachments = Array.isArray(opts.attachedFiles) && opts.attachedFiles.length > 0 ? opts.attachedFiles.map((f3) => ({
|
|
39642
|
+
name: f3.originalName,
|
|
39643
|
+
path: f3.pathHint,
|
|
39644
|
+
mime: f3.mime || "text/plain",
|
|
39645
|
+
data_base64: f3.content ? Buffer.from(f3.content, "utf8").toString("base64") : void 0
|
|
39646
|
+
})).map((a) => a.data_base64 ? a : { ...a, data_base64: void 0 }) : [];
|
|
39647
|
+
const pathAttachments = [];
|
|
39648
|
+
if (explicitFiles.length > 0) {
|
|
39649
|
+
try {
|
|
39650
|
+
const fs51 = await import('fs/promises');
|
|
39651
|
+
const pathMod = await import('path');
|
|
39652
|
+
for (const rel of explicitFiles) {
|
|
39653
|
+
try {
|
|
39654
|
+
const full = explicitAbsMap[rel] || pathMod.join(opts.root, rel);
|
|
39655
|
+
const stat13 = await fs51.stat(full).catch(() => null);
|
|
39656
|
+
if (!stat13 || !stat13.isFile()) continue;
|
|
39657
|
+
const buf = await fs51.readFile(full);
|
|
39658
|
+
const ext2 = (pathMod.extname(full) || "").toLowerCase();
|
|
39659
|
+
const mime = ext2 === ".pdf" ? "application/pdf" : ext2 === ".png" ? "image/png" : ext2 === ".jpg" || ext2 === ".jpeg" ? "image/jpeg" : ext2 === ".webp" ? "image/webp" : ext2 === ".gif" ? "image/gif" : ext2 === ".bmp" ? "image/bmp" : ext2 === ".svg" ? "image/svg+xml" : ext2 === ".tif" || ext2 === ".tiff" ? "image/tiff" : ext2 === ".heic" ? "image/heic" : ext2 === ".heif" ? "image/heif" : "text/plain";
|
|
39660
|
+
pathAttachments.push({
|
|
39661
|
+
name: pathMod.basename(full),
|
|
39662
|
+
path: full,
|
|
39663
|
+
mime,
|
|
39664
|
+
data_base64: buf.toString("base64")
|
|
39665
|
+
});
|
|
39666
|
+
} catch {
|
|
39667
|
+
}
|
|
39668
|
+
}
|
|
39669
|
+
} catch {
|
|
39670
|
+
}
|
|
39671
|
+
}
|
|
39672
|
+
const hydratedCtx = [];
|
|
39673
|
+
if (ctxAttachments.length > 0) {
|
|
39674
|
+
try {
|
|
39675
|
+
const fs51 = await import('fs/promises');
|
|
39676
|
+
for (const a of ctxAttachments) {
|
|
39677
|
+
if (a.data_base64) {
|
|
39678
|
+
hydratedCtx.push(a);
|
|
39679
|
+
continue;
|
|
39680
|
+
}
|
|
39681
|
+
const p = a.path || "";
|
|
39682
|
+
if (!p) {
|
|
39683
|
+
continue;
|
|
39684
|
+
}
|
|
39685
|
+
try {
|
|
39686
|
+
const stat13 = await fs51.stat(p).catch(() => null);
|
|
39687
|
+
if (!stat13 || !stat13.isFile()) {
|
|
39688
|
+
hydratedCtx.push(a);
|
|
39689
|
+
continue;
|
|
39690
|
+
}
|
|
39691
|
+
const buf = await fs51.readFile(p);
|
|
39692
|
+
hydratedCtx.push({ ...a, data_base64: buf.toString("base64") });
|
|
39693
|
+
} catch {
|
|
39694
|
+
hydratedCtx.push(a);
|
|
39695
|
+
}
|
|
39696
|
+
}
|
|
39697
|
+
} catch {
|
|
39698
|
+
hydratedCtx.push(...ctxAttachments);
|
|
39699
|
+
}
|
|
39700
|
+
}
|
|
39701
|
+
const allAttachments = (hydratedCtx.length ? hydratedCtx : ctxAttachments).concat(pathAttachments);
|
|
39702
|
+
const response = await executeCode(allAttachments.length > 0 ? { prompt: enriched, provider: "google", model: "gemini-2.5-flash", attachments: allAttachments } : enriched);
|
|
39213
39703
|
const raw = (response.output || response?.data?.content || "").trim();
|
|
39214
39704
|
if (!raw) {
|
|
39215
39705
|
return {
|
|
@@ -39338,6 +39828,7 @@ ${editContext}`;
|
|
|
39338
39828
|
const remainingSkipped = (validated.skipped || []).filter((p) => !skippedPlans.some((sp) => sp.path === p)).map((p) => ({ path: p, kind: "source", action: "skip", description: "" }));
|
|
39339
39829
|
const displayFiles = validated.files.concat(skippedPlans).concat(remainingSkipped);
|
|
39340
39830
|
const summary = summarizePlan(displayFiles);
|
|
39831
|
+
const planView = opts.flags.planOnly || opts.flags.dryRun || !opts.flags.apply;
|
|
39341
39832
|
const lines = [
|
|
39342
39833
|
formatPlan(summary, {
|
|
39343
39834
|
mode: outputMode,
|
|
@@ -39345,11 +39836,26 @@ ${editContext}`;
|
|
|
39345
39836
|
diffBudget: collectDiffBudget(opts.flags),
|
|
39346
39837
|
root: opts.root,
|
|
39347
39838
|
requestText: request,
|
|
39348
|
-
validated: { warnings: validated.warnings.slice(), skipped: validated.skipped.slice() }
|
|
39839
|
+
validated: { warnings: validated.warnings.slice(), skipped: validated.skipped.slice() },
|
|
39840
|
+
planView
|
|
39349
39841
|
})
|
|
39350
39842
|
];
|
|
39351
39843
|
if (opts.flags.planOnly || opts.flags.dryRun || !opts.flags.apply) {
|
|
39352
|
-
|
|
39844
|
+
let specMarkdown;
|
|
39845
|
+
try {
|
|
39846
|
+
const prompt = buildSpecPrompt(request, normalized);
|
|
39847
|
+
const { callApiJson: callApiJson4 } = await Promise.resolve().then(() => (init_api_client(), api_client_exports));
|
|
39848
|
+
try {
|
|
39849
|
+
const resp = await callApiJson4("/v1/ai-proxy", { method: "POST", body: JSON.stringify({ prompt, taskType: "chat" }), headers: { "Content-Type": "application/json" } });
|
|
39850
|
+
const content = resp?.data?.content || resp?.content;
|
|
39851
|
+
if (content && typeof content === "string") specMarkdown = content;
|
|
39852
|
+
} catch {
|
|
39853
|
+
}
|
|
39854
|
+
} catch {
|
|
39855
|
+
}
|
|
39856
|
+
const res = { plan: normalized, validated, summaryLines: withNotices(lines) };
|
|
39857
|
+
if (specMarkdown && typeof specMarkdown === "string" && specMarkdown.trim()) res.specMarkdown = specMarkdown;
|
|
39858
|
+
return res;
|
|
39353
39859
|
}
|
|
39354
39860
|
if (opts.flags.interactive && !opts.flags.yes && !process.stdin.isTTY) {
|
|
39355
39861
|
lines.push("", "WARN: Non-TTY interactive request downgraded to plan-only. Re-run with --yes to apply non-interactively.");
|
|
@@ -39429,6 +39935,36 @@ ${editContext}`;
|
|
|
39429
39935
|
return { plan: normalized, validated, summaryLines: withNotices([errorLine(err)]) };
|
|
39430
39936
|
}
|
|
39431
39937
|
}
|
|
39938
|
+
function buildSpecPrompt(request, plan) {
|
|
39939
|
+
const tree = {};
|
|
39940
|
+
for (const f3 of plan) {
|
|
39941
|
+
const dir = f3.path.split("/").slice(0, -1).join("/") || ".";
|
|
39942
|
+
if (!tree[dir]) tree[dir] = [];
|
|
39943
|
+
tree[dir].push(`${f3.action} ${f3.path} ${f3.language ? "(" + f3.language + ")" : ""}`.trim());
|
|
39944
|
+
}
|
|
39945
|
+
const treeLines = [];
|
|
39946
|
+
for (const [dir, items] of Object.entries(tree)) {
|
|
39947
|
+
treeLines.push(`- ${dir}`);
|
|
39948
|
+
for (const it of items) treeLines.push(` - ${it}`);
|
|
39949
|
+
}
|
|
39950
|
+
return [
|
|
39951
|
+
"You are a senior staff engineer. Produce a concise, high-quality Markdown spec for the following code change plan.",
|
|
39952
|
+
"",
|
|
39953
|
+
"Sections:",
|
|
39954
|
+
"- Overview",
|
|
39955
|
+
"- File Tree",
|
|
39956
|
+
"- Per-file Rationale (what/why)",
|
|
39957
|
+
"- Next Steps",
|
|
39958
|
+
"",
|
|
39959
|
+
"Request:",
|
|
39960
|
+
"```",
|
|
39961
|
+
request,
|
|
39962
|
+
"```",
|
|
39963
|
+
"",
|
|
39964
|
+
"Planned files:",
|
|
39965
|
+
treeLines.join("\n")
|
|
39966
|
+
].join("\n");
|
|
39967
|
+
}
|
|
39432
39968
|
function normalizePreviewLines(n) {
|
|
39433
39969
|
return typeof n === "number" && n > 0 ? n : void 0;
|
|
39434
39970
|
}
|
|
@@ -39450,7 +39986,7 @@ function mapCodeErrorToReason(err) {
|
|
|
39450
39986
|
const error2 = err;
|
|
39451
39987
|
const message = typeof error2?.message === "string" ? error2.message.toLowerCase() : "";
|
|
39452
39988
|
const code = typeof error2?.code === "string" ? error2.code.toLowerCase() : "";
|
|
39453
|
-
if (error2 instanceof
|
|
39989
|
+
if (error2 instanceof RateLimitError || message.includes("rate") && message.includes("limit")) {
|
|
39454
39990
|
return "rate-limit";
|
|
39455
39991
|
}
|
|
39456
39992
|
if (message.includes("timeout") || code === "etimedout") {
|
|
@@ -39623,7 +40159,7 @@ function scanSoftIssues(files) {
|
|
|
39623
40159
|
return { hasTrailingWhitespace: tw, hasConflictMarkers: cm };
|
|
39624
40160
|
}
|
|
39625
40161
|
function parseExplicitFilenames(request) {
|
|
39626
|
-
const matches = request.match(/([\w
|
|
40162
|
+
const matches = request.match(/([\w\-./\\:]+\.[A-Za-z0-9]{1,10})/gi);
|
|
39627
40163
|
if (!matches) return [];
|
|
39628
40164
|
const seen = /* @__PURE__ */ new Set();
|
|
39629
40165
|
const out = [];
|
|
@@ -39923,9 +40459,11 @@ var LANGUAGE_EXTENSIONS, CodeCommand, codeCommand, metadata3;
|
|
|
39923
40459
|
var init_code_command = __esm({
|
|
39924
40460
|
"src/slash-commands/categories/code/code.command.ts"() {
|
|
39925
40461
|
init_base_command();
|
|
40462
|
+
init_api_caller();
|
|
39926
40463
|
init_rate_limit_handler();
|
|
39927
40464
|
init_animations();
|
|
39928
40465
|
init_code_utils();
|
|
40466
|
+
init_ArgumentInference();
|
|
39929
40467
|
LANGUAGE_EXTENSIONS = {
|
|
39930
40468
|
javascript: ".js",
|
|
39931
40469
|
typescript: ".ts",
|
|
@@ -39944,7 +40482,7 @@ var init_code_command = __esm({
|
|
|
39944
40482
|
name = "code";
|
|
39945
40483
|
category = "implementation";
|
|
39946
40484
|
description = "Generate code with AI";
|
|
39947
|
-
usage = "<request> [--plan-only|--sow] [--apply] [--dry-run] [--interactive] [--yes] [--max-files N] [--root DIR] [--rollback on|off] [--output names|summary|detail|diff] [--no-code] [--preview-lines N] [--only-attached] [--attach-mode strict|assist] [--max-attachments N] [--diff-lines N] [--diff-bytes N] [--diff-hunks N]";
|
|
40485
|
+
usage = "<request> [--plan-only|--sow] [--apply] [--dry-run] [--interactive] [--yes] [--max-files N] [--root DIR] [--rollback on|off] [--output names|summary|detail|diff] [--no-code] [--preview-lines N] [--only-attached] [--attach-mode strict|assist] [--max-attachments N] [--diff-lines N] [--diff-bytes N] [--diff-hunks N] [--diff-global-max-files N] [--diff-global-max-bytes N]";
|
|
39948
40486
|
aliases = ["c"];
|
|
39949
40487
|
examples = [
|
|
39950
40488
|
{
|
|
@@ -39959,12 +40497,50 @@ var init_code_command = __esm({
|
|
|
39959
40497
|
}
|
|
39960
40498
|
];
|
|
39961
40499
|
async execute(commandArgs, context2) {
|
|
39962
|
-
const request = commandArgs.raw.join(" ").trim();
|
|
40500
|
+
const request = await this.ensureLanguageDefaults(commandArgs.raw.join(" ").trim());
|
|
39963
40501
|
if (!request) {
|
|
39964
40502
|
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.");
|
|
39965
40503
|
}
|
|
39966
40504
|
try {
|
|
39967
40505
|
const opts = this.parseV2Options(commandArgs.raw);
|
|
40506
|
+
try {
|
|
40507
|
+
const rawText = commandArgs.raw.join(" ");
|
|
40508
|
+
const explicitPlan = commandArgs.raw.includes("--plan-only") || commandArgs.raw.includes("--sow");
|
|
40509
|
+
const explicitDry = commandArgs.raw.includes("--dry-run");
|
|
40510
|
+
const explicitOutput = commandArgs.raw.some((x2) => x2.startsWith("--output") || x2 === "--verbose" || x2 === "-v");
|
|
40511
|
+
const explicitPreview = commandArgs.raw.some((x2) => x2.startsWith("--preview-lines"));
|
|
40512
|
+
const preSpin = new ProcessAnimation();
|
|
40513
|
+
preSpin.start();
|
|
40514
|
+
let inferred = {};
|
|
40515
|
+
try {
|
|
40516
|
+
inferred = await inferCodeArgs(rawText);
|
|
40517
|
+
} finally {
|
|
40518
|
+
try {
|
|
40519
|
+
preSpin.stop();
|
|
40520
|
+
} catch {
|
|
40521
|
+
}
|
|
40522
|
+
}
|
|
40523
|
+
if (!explicitPlan && !explicitDry) {
|
|
40524
|
+
if (typeof inferred.planOnly === "boolean") opts.planOnly = inferred.planOnly;
|
|
40525
|
+
if (typeof inferred.dryRun === "boolean") opts.dryRun = inferred.dryRun;
|
|
40526
|
+
}
|
|
40527
|
+
if (!explicitOutput && inferred.output) {
|
|
40528
|
+
opts.output = inferred.output;
|
|
40529
|
+
}
|
|
40530
|
+
if (!explicitPreview && typeof inferred.previewLines === "number") {
|
|
40531
|
+
opts.previewLines = inferred.previewLines;
|
|
40532
|
+
}
|
|
40533
|
+
} catch {
|
|
40534
|
+
}
|
|
40535
|
+
if (opts.planOnly) {
|
|
40536
|
+
opts.apply = false;
|
|
40537
|
+
opts.dryRun = false;
|
|
40538
|
+
}
|
|
40539
|
+
if (opts.dryRun) {
|
|
40540
|
+
opts.apply = false;
|
|
40541
|
+
}
|
|
40542
|
+
if (opts.dryRun && !opts.output) opts.output = "detail";
|
|
40543
|
+
if (opts.dryRun && !opts.previewLines) opts.previewLines = 50;
|
|
39968
40544
|
const root = opts.root || process.cwd();
|
|
39969
40545
|
const { orchestrate: orchestrate2 } = await Promise.resolve().then(() => (init_Orchestrator(), Orchestrator_exports));
|
|
39970
40546
|
const attachments = await this.collectAttachedFiles(context2).catch(() => []);
|
|
@@ -39974,8 +40550,57 @@ var init_code_command = __esm({
|
|
|
39974
40550
|
const spinner = new ProcessAnimation();
|
|
39975
40551
|
spinner.start();
|
|
39976
40552
|
try {
|
|
39977
|
-
const res = await orchestrate2(request, { root, flags: { planOnly: opts.planOnly, apply: opts.apply, dryRun: opts.dryRun, interactive: opts.interactive, yes: opts.yes, maxFiles: opts.maxFiles, output: opts.output, hideCode: opts.noCode, previewLines: this.normalizePreviewLines(opts.previewLines), verbose: opts.verbose, onlyAttached: opts.onlyAttached, attachMode: opts.attachMode, maxAttachments: opts.maxAttachments, diffLines: opts.diffLines, diffBytes: opts.diffBytes, diffHunks: opts.diffHunks, allowDotfiles: opts.allowDotfiles }, abortSignal: abort.signal, attachedFiles: attachments });
|
|
39978
|
-
|
|
40553
|
+
const res = await orchestrate2(request, { root, flags: { planOnly: opts.planOnly, apply: opts.apply, dryRun: opts.dryRun, interactive: opts.interactive, yes: opts.yes, maxFiles: opts.maxFiles, output: opts.output, hideCode: opts.noCode, previewLines: this.normalizePreviewLines(opts.previewLines), verbose: opts.verbose, onlyAttached: opts.onlyAttached, attachMode: opts.attachMode, maxAttachments: opts.maxAttachments, diffLines: opts.diffLines, diffBytes: opts.diffBytes, diffHunks: opts.diffHunks, diffGlobalMaxFiles: opts.diffGlobalMaxFiles, diffGlobalMaxBytes: opts.diffGlobalMaxBytes, allowDotfiles: opts.allowDotfiles }, abortSignal: abort.signal, attachedFiles: attachments });
|
|
40554
|
+
if (opts.planOnly) {
|
|
40555
|
+
const fs51 = await import('fs/promises');
|
|
40556
|
+
const path64 = await import('path');
|
|
40557
|
+
const spec = res?.specMarkdown;
|
|
40558
|
+
const lines = Array.isArray(res?.summaryLines) ? res.summaryLines : [];
|
|
40559
|
+
const planItems = [];
|
|
40560
|
+
for (const l of lines) {
|
|
40561
|
+
const s2 = String(l).trim();
|
|
40562
|
+
if (!s2) continue;
|
|
40563
|
+
if (/^Modified Artifacts/i.test(s2)) continue;
|
|
40564
|
+
if (/^OK:/i.test(s2)) continue;
|
|
40565
|
+
if (/^Next steps:/i.test(s2)) continue;
|
|
40566
|
+
const m2 = /^-\s+(create|modify)\s+(.+)$/i.exec(s2);
|
|
40567
|
+
if (m2) {
|
|
40568
|
+
planItems.push(`- [plan] ${m2[1].toLowerCase()} ${m2[2]}`);
|
|
40569
|
+
continue;
|
|
40570
|
+
}
|
|
40571
|
+
planItems.push(`- ${s2}`);
|
|
40572
|
+
}
|
|
40573
|
+
const md = [];
|
|
40574
|
+
if (spec && spec.trim()) {
|
|
40575
|
+
md.push(spec.trim());
|
|
40576
|
+
} else {
|
|
40577
|
+
md.push("# Code Plan");
|
|
40578
|
+
md.push("");
|
|
40579
|
+
md.push("## Request");
|
|
40580
|
+
md.push("");
|
|
40581
|
+
md.push("```");
|
|
40582
|
+
md.push(request);
|
|
40583
|
+
md.push("```");
|
|
40584
|
+
md.push("");
|
|
40585
|
+
md.push("## Proposed Changes");
|
|
40586
|
+
md.push("");
|
|
40587
|
+
if (planItems.length) md.push(...planItems);
|
|
40588
|
+
else md.push("- (no summary available)");
|
|
40589
|
+
}
|
|
40590
|
+
const plansDir = path64.join(root, ".maria", "plans");
|
|
40591
|
+
await fs51.mkdir(plansDir, { recursive: true });
|
|
40592
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
40593
|
+
const fileName = `code-plan-${ts}.md`;
|
|
40594
|
+
const outPath = path64.join(plansDir, fileName);
|
|
40595
|
+
await fs51.writeFile(outPath, md.join("\n") + "\n", "utf8");
|
|
40596
|
+
const rel = path64.relative(root, outPath);
|
|
40597
|
+
return this.success(`Code plan saved: ${rel}`);
|
|
40598
|
+
}
|
|
40599
|
+
const detail = res?.detailLines;
|
|
40600
|
+
if (opts.dryRun && Array.isArray(detail) && detail.length) {
|
|
40601
|
+
return this.success(detail.join("\n"));
|
|
40602
|
+
}
|
|
40603
|
+
const out = Array.isArray(res?.summaryLines) ? res.summaryLines.join("\n") : "";
|
|
39979
40604
|
return this.success(out);
|
|
39980
40605
|
} finally {
|
|
39981
40606
|
try {
|
|
@@ -40025,9 +40650,68 @@ ${pretty}`);
|
|
|
40025
40650
|
return this.error(parts.join("\n"));
|
|
40026
40651
|
}
|
|
40027
40652
|
}
|
|
40653
|
+
// Add default language hints when not specified by the user (LLM-assisted detection)
|
|
40654
|
+
async ensureLanguageDefaults(raw) {
|
|
40655
|
+
try {
|
|
40656
|
+
const system = [
|
|
40657
|
+
"You analyze a user's code-generation request.",
|
|
40658
|
+
"Decide if the user explicitly specified a programming language or framework/tooling (e.g., TypeScript, Python, Rust, Java, React, Vue, Node, etc.).",
|
|
40659
|
+
'Return ONLY compact JSON with shape {"explicitLanguage": boolean, "language"?: string}.',
|
|
40660
|
+
"Do not add any commentary."
|
|
40661
|
+
].join("\n");
|
|
40662
|
+
const user = `Request: ${raw}`;
|
|
40663
|
+
const resp = await callAPI("/v1/ai-proxy", {
|
|
40664
|
+
method: "POST",
|
|
40665
|
+
body: {
|
|
40666
|
+
provider: "google",
|
|
40667
|
+
model: "gemini-2.5-flash",
|
|
40668
|
+
taskType: "chat",
|
|
40669
|
+
prompt: `${system}
|
|
40670
|
+
|
|
40671
|
+
${user}`
|
|
40672
|
+
}
|
|
40673
|
+
});
|
|
40674
|
+
const content = (resp?.data?.content || resp?.content || "").trim();
|
|
40675
|
+
const extractFirstJson6 = (text) => {
|
|
40676
|
+
const fence = /```\s*json\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
40677
|
+
if (fence) return fence[1];
|
|
40678
|
+
const generic = /```\s*\r?\n([\s\S]*?)```/i.exec(text);
|
|
40679
|
+
if (generic) {
|
|
40680
|
+
try {
|
|
40681
|
+
JSON.parse(generic[1]);
|
|
40682
|
+
return generic[1];
|
|
40683
|
+
} catch {
|
|
40684
|
+
}
|
|
40685
|
+
}
|
|
40686
|
+
const start = text.indexOf("{");
|
|
40687
|
+
const end = text.lastIndexOf("}");
|
|
40688
|
+
if (start >= 0 && end > start) {
|
|
40689
|
+
const cand = text.slice(start, end + 1);
|
|
40690
|
+
try {
|
|
40691
|
+
JSON.parse(cand);
|
|
40692
|
+
return cand;
|
|
40693
|
+
} catch {
|
|
40694
|
+
}
|
|
40695
|
+
}
|
|
40696
|
+
return null;
|
|
40697
|
+
};
|
|
40698
|
+
const jsonText = extractFirstJson6(content) || content;
|
|
40699
|
+
let parsed = {};
|
|
40700
|
+
try {
|
|
40701
|
+
parsed = JSON.parse(jsonText);
|
|
40702
|
+
} catch {
|
|
40703
|
+
parsed.explicitLanguage = /```\s*[a-zA-Z]/.test(raw) || /\.(ts|tsx|js|jsx|py|java|kt|go|rs|rb|swift|cs|c|cpp|hpp|php|scala|hs|ex|exs|dart|lua|zig|sol|sql)\b/i.test(raw);
|
|
40704
|
+
}
|
|
40705
|
+
if (parsed && parsed.explicitLanguage) return raw;
|
|
40706
|
+
} catch {
|
|
40707
|
+
}
|
|
40708
|
+
const hint = " (Use TypeScript and React; prefer functional components and node)";
|
|
40709
|
+
return raw + hint;
|
|
40710
|
+
}
|
|
40028
40711
|
// v2.0 helpers
|
|
40029
40712
|
parseV2Options(raw) {
|
|
40030
|
-
const opts = { planOnly: false, apply: false, dryRun: false, interactive: false, yes: false, rollback: true, output: void 0, noCode: false, previewLines: 0, root: void 0, maxFiles: void 0, verbose: false, gitGuard: void 0, allowDotfiles: false, confirmOverwrites: [], gitCommit: void 0, gitBranch: void 0, gitTag: void 0, gitTagPrefix: void 0, gitPush: void 0, gitPushRemote: void 0, onlyAttached: false, attachMode: "assist", maxAttachments: 50, diffLines: void 0, diffBytes: void 0, diffHunks: void 0 };
|
|
40713
|
+
const opts = { planOnly: false, apply: false, dryRun: false, interactive: false, yes: false, rollback: true, output: void 0, noCode: false, previewLines: 0, root: void 0, maxFiles: void 0, verbose: false, gitGuard: void 0, allowDotfiles: false, confirmOverwrites: [], gitCommit: void 0, gitBranch: void 0, gitTag: void 0, gitTagPrefix: void 0, gitPush: void 0, gitPushRemote: void 0, onlyAttached: false, attachMode: "assist", maxAttachments: 50, diffLines: void 0, diffBytes: void 0, diffHunks: void 0, diffGlobalMaxFiles: void 0, diffGlobalMaxBytes: void 0 };
|
|
40714
|
+
const explicit = { apply: false, planOnly: false, dryRun: false };
|
|
40031
40715
|
const a = raw.slice();
|
|
40032
40716
|
while (a.length) {
|
|
40033
40717
|
const x2 = a.shift();
|
|
@@ -40037,12 +40721,15 @@ ${pretty}`);
|
|
|
40037
40721
|
case "plan-only":
|
|
40038
40722
|
case "sow":
|
|
40039
40723
|
opts.planOnly = true;
|
|
40724
|
+
explicit.planOnly = true;
|
|
40040
40725
|
break;
|
|
40041
40726
|
case "apply":
|
|
40042
40727
|
opts.apply = true;
|
|
40728
|
+
explicit.apply = true;
|
|
40043
40729
|
break;
|
|
40044
40730
|
case "dry-run":
|
|
40045
40731
|
opts.dryRun = true;
|
|
40732
|
+
explicit.dryRun = true;
|
|
40046
40733
|
break;
|
|
40047
40734
|
case "interactive":
|
|
40048
40735
|
opts.interactive = true;
|
|
@@ -40102,6 +40789,12 @@ ${pretty}`);
|
|
|
40102
40789
|
case "diff-hunks":
|
|
40103
40790
|
opts.diffHunks = Number(v || a.shift());
|
|
40104
40791
|
break;
|
|
40792
|
+
case "diff-global-max-files":
|
|
40793
|
+
opts.diffGlobalMaxFiles = Number(v || a.shift());
|
|
40794
|
+
break;
|
|
40795
|
+
case "diff-global-max-bytes":
|
|
40796
|
+
opts.diffGlobalMaxBytes = Number(v || a.shift());
|
|
40797
|
+
break;
|
|
40105
40798
|
case "confirm-overwrites": {
|
|
40106
40799
|
const list = (v || a.shift() || "").split(",").map((s2) => s2.trim()).filter(Boolean);
|
|
40107
40800
|
opts.confirmOverwrites = list;
|
|
@@ -40135,8 +40828,16 @@ ${pretty}`);
|
|
|
40135
40828
|
}
|
|
40136
40829
|
}
|
|
40137
40830
|
}
|
|
40138
|
-
if (
|
|
40139
|
-
opts.apply =
|
|
40831
|
+
if (explicit.planOnly || explicit.dryRun) {
|
|
40832
|
+
opts.apply = false;
|
|
40833
|
+
}
|
|
40834
|
+
if (explicit.planOnly) {
|
|
40835
|
+
opts.dryRun = false;
|
|
40836
|
+
}
|
|
40837
|
+
if (!explicit.apply && !explicit.planOnly && !explicit.dryRun) {
|
|
40838
|
+
if (!opts.apply && !opts.planOnly && !opts.dryRun) {
|
|
40839
|
+
opts.apply = true;
|
|
40840
|
+
}
|
|
40140
40841
|
}
|
|
40141
40842
|
return opts;
|
|
40142
40843
|
}
|
|
@@ -57868,7 +58569,7 @@ ${user}`,
|
|
|
57868
58569
|
};
|
|
57869
58570
|
}
|
|
57870
58571
|
});
|
|
57871
|
-
function
|
|
58572
|
+
function extractFirstJson5(text) {
|
|
57872
58573
|
const fence = /```json\r?\n([\s\S]*?)```/i.exec(text);
|
|
57873
58574
|
if (fence) return fence[1];
|
|
57874
58575
|
const start = text.indexOf("{");
|
|
@@ -57915,7 +58616,7 @@ ${user}`,
|
|
|
57915
58616
|
}
|
|
57916
58617
|
});
|
|
57917
58618
|
const raw = (response?.data?.content || response?.output || "").trim();
|
|
57918
|
-
const jsonText =
|
|
58619
|
+
const jsonText = extractFirstJson5(raw) || raw;
|
|
57919
58620
|
let parsed = {};
|
|
57920
58621
|
try {
|
|
57921
58622
|
parsed = JSON.parse(jsonText);
|
|
@@ -57936,7 +58637,7 @@ ${user}`,
|
|
|
57936
58637
|
}
|
|
57937
58638
|
return out;
|
|
57938
58639
|
}
|
|
57939
|
-
var
|
|
58640
|
+
var init_ArgumentInference2 = __esm({
|
|
57940
58641
|
"src/services/evaluation/ArgumentInference.ts"() {
|
|
57941
58642
|
init_api_caller();
|
|
57942
58643
|
}
|
|
@@ -57957,7 +58658,7 @@ var init_evaluate_command = __esm({
|
|
|
57957
58658
|
init_EvaluationOrchestrator();
|
|
57958
58659
|
init_api_caller();
|
|
57959
58660
|
init_animations();
|
|
57960
|
-
|
|
58661
|
+
init_ArgumentInference2();
|
|
57961
58662
|
EvaluateCommand = class extends BaseCommand {
|
|
57962
58663
|
name = "evaluate";
|
|
57963
58664
|
category = "evaluation";
|
|
@@ -58640,7 +59341,7 @@ __export(slash_commands_exports, {
|
|
|
58640
59341
|
MemoryStatusCommand: () => MemoryStatusCommand,
|
|
58641
59342
|
PermissionError: () => PermissionError,
|
|
58642
59343
|
PlanCommand: () => PlanCommand,
|
|
58643
|
-
RateLimitError: () =>
|
|
59344
|
+
RateLimitError: () => RateLimitError2,
|
|
58644
59345
|
RateLimitMiddleware: () => RateLimitMiddleware,
|
|
58645
59346
|
RecallCommand: () => RecallCommand,
|
|
58646
59347
|
RememberCommand: () => RememberCommand,
|
|
@@ -59202,6 +59903,17 @@ var init_slash_commands = __esm({
|
|
|
59202
59903
|
init_registry();
|
|
59203
59904
|
}
|
|
59204
59905
|
});
|
|
59906
|
+
|
|
59907
|
+
// src/cli/session-state.ts
|
|
59908
|
+
function clearSession() {
|
|
59909
|
+
while (session.length) session.pop();
|
|
59910
|
+
}
|
|
59911
|
+
var session;
|
|
59912
|
+
var init_session_state = __esm({
|
|
59913
|
+
"src/cli/session-state.ts"() {
|
|
59914
|
+
session = [];
|
|
59915
|
+
}
|
|
59916
|
+
});
|
|
59205
59917
|
async function handleSlash(input3) {
|
|
59206
59918
|
if (!input3.startsWith("/")) return false;
|
|
59207
59919
|
const { cmd, args: args2, options, flags } = parseSlash(input3);
|
|
@@ -59210,7 +59922,10 @@ async function handleSlash(input3) {
|
|
|
59210
59922
|
clearTerminal();
|
|
59211
59923
|
} catch {
|
|
59212
59924
|
}
|
|
59213
|
-
|
|
59925
|
+
try {
|
|
59926
|
+
clearSession();
|
|
59927
|
+
} catch {
|
|
59928
|
+
}
|
|
59214
59929
|
}
|
|
59215
59930
|
if (cmd === "doctor") {
|
|
59216
59931
|
console.log(chalk40__default.default.white("Run as subcommand: maria doctor"));
|
|
@@ -59262,6 +59977,7 @@ var init_handle_slash = __esm({
|
|
|
59262
59977
|
init_slash_commands();
|
|
59263
59978
|
init_cli_auth();
|
|
59264
59979
|
init_terminal();
|
|
59980
|
+
init_session_state();
|
|
59265
59981
|
}
|
|
59266
59982
|
});
|
|
59267
59983
|
function formatAnyError(err) {
|
|
@@ -61332,7 +62048,7 @@ var init_ai_response_service = __esm({
|
|
|
61332
62048
|
*/
|
|
61333
62049
|
async callLLM(prompt, opts = {}) {
|
|
61334
62050
|
const {
|
|
61335
|
-
system = PLAIN_OUTPUT ? "Return ONLY the answer (or ONLY code). No menus, no lists, no guided flows. Always respond in English." : "You are a helpful senior engineer named Maria. Always respond in English. Provide direct, production-quality answers. Make sure you answer in plain text, as a natural chat. When asked about the model (not your name or who you are, but the model), say you are a large language model fully trained by Bonginkan.",
|
|
62051
|
+
system = PLAIN_OUTPUT ? "Return ONLY the answer (or ONLY code). No menus, no lists, no guided flows. Always respond in English. If a local file path is provided, make sure you read the uploaded file before taking any actions." : "You are a helpful senior engineer named Maria. Always respond in English. Provide direct, production-quality answers. Make sure you answer in plain text, as a natural chat. When asked about the model (not your name or who you are, but the model), say you are a large language model fully trained by Bonginkan. If a path is provided, return the path as a string. If a local file path is provided, make sure you read the uploaded/attached file (which is likely equivalent to the path) before taking any actions.",
|
|
61336
62052
|
model = void 0,
|
|
61337
62053
|
provider = DEFAULT_PROVIDER2,
|
|
61338
62054
|
temperature = 0.2,
|
|
@@ -61340,14 +62056,63 @@ var init_ai_response_service = __esm({
|
|
|
61340
62056
|
} = opts;
|
|
61341
62057
|
process.env.MARIA_API_BASE || "https://api.maria-code.ai";
|
|
61342
62058
|
const preferApi = String(process.env.MARIA_USE_API || "1") === "1";
|
|
62059
|
+
let effectiveAttachments = Array.isArray(opts.attachments) ? opts.attachments.slice() : [];
|
|
61343
62060
|
if (preferApi) {
|
|
61344
62061
|
try {
|
|
61345
62062
|
const { callAPI: callAPI2 } = await Promise.resolve().then(() => (init_api_caller(), api_caller_exports));
|
|
62063
|
+
let autoAttachments = [];
|
|
62064
|
+
try {
|
|
62065
|
+
const pathPattern = /(?:^|\s)([\w\-\.\/\\:]+\.[A-Za-z0-9]{1,10})(?:\s|$)/gi;
|
|
62066
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
62067
|
+
let m2;
|
|
62068
|
+
const textToScan = `${prompt}`;
|
|
62069
|
+
while ((m2 = pathPattern.exec(textToScan)) !== null) {
|
|
62070
|
+
const p = (m2[1] || "").trim();
|
|
62071
|
+
if (p) candidates.add(p);
|
|
62072
|
+
}
|
|
62073
|
+
if (candidates.size > 0) {
|
|
62074
|
+
const fs51 = await import('fs/promises');
|
|
62075
|
+
const pathMod = await import('path');
|
|
62076
|
+
const cwd2 = process.cwd();
|
|
62077
|
+
for (const cand of candidates) {
|
|
62078
|
+
try {
|
|
62079
|
+
const normalized = cand.replace(/^"|"$/g, "").replace(/^'|'$/g, "");
|
|
62080
|
+
const abs = pathMod.isAbsolute(normalized) ? normalized : pathMod.join(cwd2, normalized);
|
|
62081
|
+
const st = await fs51.stat(abs).catch(() => null);
|
|
62082
|
+
if (!st || !st.isFile()) continue;
|
|
62083
|
+
const buf = await fs51.readFile(abs);
|
|
62084
|
+
const ext2 = (pathMod.extname(abs) || "").toLowerCase();
|
|
62085
|
+
const mime = ext2 === ".pdf" ? "application/pdf" : ext2 === ".png" ? "image/png" : ext2 === ".jpg" || ext2 === ".jpeg" ? "image/jpeg" : ext2 === ".webp" ? "image/webp" : ext2 === ".gif" ? "image/gif" : ext2 === ".bmp" ? "image/bmp" : ext2 === ".svg" ? "image/svg+xml" : ext2 === ".tif" || ext2 === ".tiff" ? "image/tiff" : ext2 === ".heic" ? "image/heic" : ext2 === ".heif" ? "image/heif" : "text/plain";
|
|
62086
|
+
autoAttachments.push({ name: pathMod.basename(abs), path: abs, mime, data_base64: buf.toString("base64") });
|
|
62087
|
+
} catch {
|
|
62088
|
+
}
|
|
62089
|
+
}
|
|
62090
|
+
}
|
|
62091
|
+
} catch {
|
|
62092
|
+
}
|
|
62093
|
+
if (autoAttachments.length > 0) {
|
|
62094
|
+
const existing = new Set(effectiveAttachments.map((a) => (a.path || a.name || "").toLowerCase()));
|
|
62095
|
+
for (const a of autoAttachments) {
|
|
62096
|
+
const key = (a.path || a.name || "").toLowerCase();
|
|
62097
|
+
if (!existing.has(key)) {
|
|
62098
|
+
effectiveAttachments.push(a);
|
|
62099
|
+
existing.add(key);
|
|
62100
|
+
}
|
|
62101
|
+
}
|
|
62102
|
+
}
|
|
62103
|
+
const inlineSection = "";
|
|
61346
62104
|
const r2 = await callAPI2("/v1/ai-proxy", {
|
|
61347
62105
|
method: "POST",
|
|
61348
|
-
body: {
|
|
62106
|
+
body: {
|
|
62107
|
+
// When attachments are present, force an attachments-capable route (mirror /evaluate)
|
|
62108
|
+
...effectiveAttachments.length ? { provider: "google", model: "gemini-2.5-flash" } : {},
|
|
62109
|
+
prompt: `${system}
|
|
61349
62110
|
|
|
61350
|
-
${prompt}`,
|
|
62111
|
+
${prompt}${inlineSection}`,
|
|
62112
|
+
taskType: "chat",
|
|
62113
|
+
// mirror /evaluate: include attachments in metadata
|
|
62114
|
+
...effectiveAttachments.length ? { metadata: { attachments: effectiveAttachments } } : {}
|
|
62115
|
+
}
|
|
61351
62116
|
});
|
|
61352
62117
|
const apiContent = r2?.data?.content || r2?.content;
|
|
61353
62118
|
if (apiContent) return apiContent;
|
|
@@ -61360,10 +62125,42 @@ ${prompt}`, taskType: "chat" }
|
|
|
61360
62125
|
} catch {
|
|
61361
62126
|
}
|
|
61362
62127
|
}
|
|
61363
|
-
|
|
61364
|
-
prompt: `${system}
|
|
62128
|
+
let fallbackPrompt = `${system}
|
|
61365
62129
|
|
|
61366
|
-
${prompt}
|
|
62130
|
+
${prompt}`;
|
|
62131
|
+
try {
|
|
62132
|
+
const attList = effectiveAttachments && effectiveAttachments.length ? effectiveAttachments : [];
|
|
62133
|
+
if (attList.length > 0) {
|
|
62134
|
+
const limitBytes = 128 * 1024;
|
|
62135
|
+
let used = 0;
|
|
62136
|
+
const sections = [];
|
|
62137
|
+
for (const a of attList) {
|
|
62138
|
+
if (!a?.data_base64) continue;
|
|
62139
|
+
try {
|
|
62140
|
+
const buf = Buffer.from(a.data_base64, "base64");
|
|
62141
|
+
const text = /^(application\/pdf)/i.test(String(a.mime || "")) ? "" : buf.toString("utf8");
|
|
62142
|
+
if (!text) continue;
|
|
62143
|
+
const remaining = Math.max(0, limitBytes - used);
|
|
62144
|
+
if (remaining <= 0) break;
|
|
62145
|
+
const slice = text.length > remaining ? text.slice(0, remaining) : text;
|
|
62146
|
+
used += Buffer.byteLength(slice, "utf8");
|
|
62147
|
+
sections.push(`[BEGIN file: ${a.path || a.name || "attachment.txt"}]
|
|
62148
|
+
${slice}
|
|
62149
|
+
[END]`);
|
|
62150
|
+
} catch {
|
|
62151
|
+
}
|
|
62152
|
+
}
|
|
62153
|
+
if (sections.length > 0) {
|
|
62154
|
+
fallbackPrompt = `${fallbackPrompt}
|
|
62155
|
+
|
|
62156
|
+
[ATTACHMENTS]
|
|
62157
|
+
${sections.join("\n\n")}`;
|
|
62158
|
+
}
|
|
62159
|
+
}
|
|
62160
|
+
} catch {
|
|
62161
|
+
}
|
|
62162
|
+
const res = await this.providerManager.complete({
|
|
62163
|
+
prompt: fallbackPrompt,
|
|
61367
62164
|
model,
|
|
61368
62165
|
temperature,
|
|
61369
62166
|
maxTokens
|
|
@@ -75818,7 +76615,7 @@ async function init2() {
|
|
|
75818
76615
|
ai = res.ai;
|
|
75819
76616
|
res.ctx;
|
|
75820
76617
|
store = res.store;
|
|
75821
|
-
|
|
76618
|
+
clearSession();
|
|
75822
76619
|
for (const m2 of res.session) session.push(m2);
|
|
75823
76620
|
await loadServices2();
|
|
75824
76621
|
}
|
|
@@ -75835,6 +76632,9 @@ async function streamAnswer(text, opts = {}) {
|
|
|
75835
76632
|
s2 = s2.replace(/\[BEGIN\s+file:[^\]]+\][\s\S]*?\[END\]/g, "");
|
|
75836
76633
|
return s2;
|
|
75837
76634
|
};
|
|
76635
|
+
const removeAttachmentSections = (s2) => {
|
|
76636
|
+
return s2.replace(/\[ATTACHMENTS\][\s\S]*$/i, "");
|
|
76637
|
+
};
|
|
75838
76638
|
const hasAnyCodeBlocks = (s2) => /```[\s\S]*?```|\[BEGIN\s+file:/i.test(s2);
|
|
75839
76639
|
const envInt = (name2, def) => {
|
|
75840
76640
|
const v = Number(process.env[name2]);
|
|
@@ -75860,10 +76660,11 @@ async function streamAnswer(text, opts = {}) {
|
|
|
75860
76660
|
model: process.env.MARIA_MODEL || "gemini-2.5-flash"
|
|
75861
76661
|
});
|
|
75862
76662
|
animation.stop();
|
|
75863
|
-
const
|
|
75864
|
-
|
|
76663
|
+
const respForArtifactCheck = removeAttachmentSections(resp || "");
|
|
76664
|
+
const containsCode = hasAnyCodeBlocks(respForArtifactCheck);
|
|
76665
|
+
if (containsCode && opts.triage && opts.triage.type === "route-code") {
|
|
75865
76666
|
try {
|
|
75866
|
-
const artifacts = extractAllCodeInfos(
|
|
76667
|
+
const artifacts = extractAllCodeInfos(respForArtifactCheck);
|
|
75867
76668
|
const savedFiles = [];
|
|
75868
76669
|
let okCount = 0, warnCount = 0, errCount = 0;
|
|
75869
76670
|
for (const { language, code, extension, filename: suggested } of artifacts) {
|
|
@@ -75888,7 +76689,7 @@ async function streamAnswer(text, opts = {}) {
|
|
|
75888
76689
|
console.log(chalk40__default.default.white(`ERROR: failed ${filepath} (${language}) - ${msg2}`));
|
|
75889
76690
|
}
|
|
75890
76691
|
}
|
|
75891
|
-
const prose = stripMarkdownForPlainChat(removeCodeBlocks(resp)).trim();
|
|
76692
|
+
const prose = stripMarkdownForPlainChat(removeCodeBlocks(removeAttachmentSections(resp))).trim();
|
|
75892
76693
|
if (prose) {
|
|
75893
76694
|
console.log(chalk40__default.default.white(""));
|
|
75894
76695
|
console.log(chalk40__default.default.white("Chat Response:"));
|
|
@@ -75967,44 +76768,23 @@ async function handleLine(line, options = {}) {
|
|
|
75967
76768
|
}
|
|
75968
76769
|
const consumed = await handleSlash(input3);
|
|
75969
76770
|
if (consumed) return;
|
|
75970
|
-
|
|
75971
|
-
|
|
75972
|
-
|
|
75973
|
-
|
|
75974
|
-
|
|
75975
|
-
|
|
75976
|
-
|
|
75977
|
-
|
|
75978
|
-
|
|
75979
|
-
|
|
75980
|
-
|
|
75981
|
-
|
|
75982
|
-
|
|
75983
|
-
|
|
75984
|
-
|
|
75985
|
-
skipChoiceResolution: true,
|
|
75986
|
-
skipTriage: true
|
|
75987
|
-
});
|
|
75988
|
-
console.log(chalk40__default.default.white(""));
|
|
75989
|
-
console.log(chalk40__default.default.white("Summary:"));
|
|
75990
|
-
if (triageResult.type === "route-code") {
|
|
75991
|
-
console.log(chalk40__default.default.white("OK: routed to /code plan-only"));
|
|
75992
|
-
console.log(chalk40__default.default.white("Next steps:"));
|
|
75993
|
-
console.log(chalk40__default.default.white("- Run /code --apply --yes after reviewing the plan"));
|
|
75994
|
-
} else if (triageResult.type === "route-image") {
|
|
75995
|
-
console.log(chalk40__default.default.white("OK: routed to /image"));
|
|
75996
|
-
console.log(chalk40__default.default.white("Next steps:"));
|
|
75997
|
-
console.log(chalk40__default.default.white("- Review generated images and iterate if needed"));
|
|
75998
|
-
} else if (triageResult.type === "route-video") {
|
|
75999
|
-
console.log(chalk40__default.default.white("OK: routed to /video"));
|
|
76000
|
-
console.log(chalk40__default.default.white("Next steps:"));
|
|
76001
|
-
console.log(chalk40__default.default.white("- Inspect the storyboard or render output"));
|
|
76002
|
-
} else {
|
|
76003
|
-
console.log(chalk40__default.default.white("OK: routed"));
|
|
76004
|
-
console.log(chalk40__default.default.white("Next steps:"));
|
|
76005
|
-
console.log(chalk40__default.default.white("- Follow the routed workflow"));
|
|
76771
|
+
if (!input3.startsWith("/")) {
|
|
76772
|
+
const mapped = await mapInputToTopLevelCommand(input3);
|
|
76773
|
+
if (process.env.MARIA_DEBUG === "1") {
|
|
76774
|
+
console.log(chalk40__default.default.white(`Command: {command: '${mapped.command}', args: '${mapped.args}', confidence: '${mapped.confidence}'}`));
|
|
76775
|
+
}
|
|
76776
|
+
try {
|
|
76777
|
+
const threshold = Number(process.env.MARIA_ROUTE_CONFIDENCE || "0.7");
|
|
76778
|
+
if (mapped && mapped.command) {
|
|
76779
|
+
const conf = typeof mapped.confidence === "number" ? mapped.confidence : 1;
|
|
76780
|
+
if (mapped.command === "chat") {
|
|
76781
|
+
} else if (conf >= threshold) {
|
|
76782
|
+
const routed = [mapped.command, ...mapped.args || [input3]].join(" ").trim();
|
|
76783
|
+
await handleLine(routed, { skipChoiceResolution: true, skipTriage: true });
|
|
76784
|
+
return;
|
|
76785
|
+
}
|
|
76006
76786
|
}
|
|
76007
|
-
|
|
76787
|
+
} finally {
|
|
76008
76788
|
}
|
|
76009
76789
|
}
|
|
76010
76790
|
const isAuthenticated = await authManager.isAuthenticated();
|
|
@@ -76017,73 +76797,7 @@ async function handleLine(line, options = {}) {
|
|
|
76017
76797
|
const user = { role: "user", content: input3, timestamp: /* @__PURE__ */ new Date() };
|
|
76018
76798
|
session.push(user);
|
|
76019
76799
|
if (store?.addMessage) await store.addMessage(user);
|
|
76020
|
-
|
|
76021
|
-
await handleComplexChat(input3, triageResult);
|
|
76022
|
-
return;
|
|
76023
|
-
}
|
|
76024
|
-
await streamAnswer(input3, { triage: triageResult });
|
|
76025
|
-
}
|
|
76026
|
-
async function handleComplexChat(request, triageResult) {
|
|
76027
|
-
const animation = new ProcessAnimation();
|
|
76028
|
-
animation.start();
|
|
76029
|
-
try {
|
|
76030
|
-
const authed = await authManager.isAuthenticated();
|
|
76031
|
-
let content = "";
|
|
76032
|
-
if (authed) {
|
|
76033
|
-
try {
|
|
76034
|
-
const resp = await callApiJson("/api/ai", {
|
|
76035
|
-
method: "POST",
|
|
76036
|
-
body: JSON.stringify({ prompt: request, taskType: "planning" }),
|
|
76037
|
-
headers: { "Content-Type": "application/json" }
|
|
76038
|
-
});
|
|
76039
|
-
content = resp?.data?.response || resp?.data?.content || "";
|
|
76040
|
-
} catch {
|
|
76041
|
-
}
|
|
76042
|
-
}
|
|
76043
|
-
if (!content) {
|
|
76044
|
-
animation.stop();
|
|
76045
|
-
await streamAnswer(request, { triage: triageResult });
|
|
76046
|
-
return;
|
|
76047
|
-
}
|
|
76048
|
-
animation.stop();
|
|
76049
|
-
const cleaned = content && typeof content === "string" ? content : buildComplexPlanSteps(request).join("\n");
|
|
76050
|
-
console.log(chalk40__default.default.white(cleaned));
|
|
76051
|
-
const planMessage = {
|
|
76052
|
-
role: "assistant",
|
|
76053
|
-
content: cleaned,
|
|
76054
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
76055
|
-
metadata: { tag: "complex-chat", triage: triageResult }
|
|
76056
|
-
};
|
|
76057
|
-
session.push(planMessage);
|
|
76058
|
-
if (store?.addMessage) await store.addMessage(planMessage);
|
|
76059
|
-
console.log(chalk40__default.default.white(""));
|
|
76060
|
-
console.log(chalk40__default.default.white("Summary:"));
|
|
76061
|
-
console.log(chalk40__default.default.white("OK: plan prepared"));
|
|
76062
|
-
console.log(chalk40__default.default.white("Next steps:"));
|
|
76063
|
-
console.log(chalk40__default.default.white("- Ask to apply or adjust the plan"));
|
|
76064
|
-
} finally {
|
|
76065
|
-
try {
|
|
76066
|
-
animation.stop();
|
|
76067
|
-
} catch {
|
|
76068
|
-
}
|
|
76069
|
-
}
|
|
76070
|
-
}
|
|
76071
|
-
function buildComplexPlanSteps(request) {
|
|
76072
|
-
const scoped = request.trim();
|
|
76073
|
-
const steps = [
|
|
76074
|
-
`Clarify scope, constraints, and success criteria for "${scoped}"`,
|
|
76075
|
-
`Review existing modules in src/ and docs/ for related work`,
|
|
76076
|
-
`Design the solution with safe defaults and feature flags if needed`,
|
|
76077
|
-
`Implement changes and document decisions`,
|
|
76078
|
-
`Validate with pnpm test and peer review artifacts`
|
|
76079
|
-
];
|
|
76080
|
-
if (/(test|spec|verify|検証)/i.test(scoped)) {
|
|
76081
|
-
steps.push("Extend or add Vitest coverage for new behaviour");
|
|
76082
|
-
}
|
|
76083
|
-
if (/(ui|frontend|component|画面)/i.test(scoped)) {
|
|
76084
|
-
steps.push("Capture CLI or UI snapshots to confirm UX changes");
|
|
76085
|
-
}
|
|
76086
|
-
return steps;
|
|
76800
|
+
await streamAnswer(input3, {});
|
|
76087
76801
|
}
|
|
76088
76802
|
async function tryResolveChoice(rawLine) {
|
|
76089
76803
|
const resolution = choiceMemory.resolve(rawLine);
|
|
@@ -76175,17 +76889,17 @@ MARIA v${getVersion()}
|
|
|
76175
76889
|
registerDoctorSubcommand(program2);
|
|
76176
76890
|
return program2;
|
|
76177
76891
|
}
|
|
76178
|
-
var InteractiveCLI, ai, store,
|
|
76892
|
+
var InteractiveCLI, ai, store, commandManager, startupDisplayed, program;
|
|
76179
76893
|
var init_cli = __esm({
|
|
76180
76894
|
"src/cli.ts"() {
|
|
76181
76895
|
init_env_loader();
|
|
76182
76896
|
init_version();
|
|
76183
76897
|
init_animations();
|
|
76184
76898
|
init_cli_auth();
|
|
76185
|
-
init_api_client();
|
|
76186
76899
|
init_choice_memory();
|
|
76187
|
-
|
|
76900
|
+
init_LlmTopLevelRouter();
|
|
76188
76901
|
init_handle_slash();
|
|
76902
|
+
init_session_state();
|
|
76189
76903
|
init_process_handlers();
|
|
76190
76904
|
init_doctor();
|
|
76191
76905
|
init_services_loader();
|
|
@@ -76193,7 +76907,6 @@ var init_cli = __esm({
|
|
|
76193
76907
|
init_interactive_session();
|
|
76194
76908
|
init_server();
|
|
76195
76909
|
init_code_utils();
|
|
76196
|
-
session = [];
|
|
76197
76910
|
commandManager = null;
|
|
76198
76911
|
startupDisplayed = false;
|
|
76199
76912
|
if (!process.env.GOOGLE_AUTH_DISABLE_GCE_CHECK) {
|