@defai.digital/automatosx 11.3.1 → 11.3.2
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 +1 -1
- package/dist/index.js +728 -382
- package/dist/mcp/index.js +174 -144
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as path4 from 'path';
|
|
|
3
3
|
import path4__default, { dirname, join, extname as extname$1, basename, resolve, relative, isAbsolute, sep, parse, delimiter } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { mkdir, appendFile, readFile, readdir, writeFile, rename, unlink, copyFile, access, stat, realpath } from 'fs/promises';
|
|
6
|
+
import * as fs3 from 'fs';
|
|
6
7
|
import { existsSync, readFileSync, promises, mkdirSync, createWriteStream, writeFileSync, unlinkSync, constants } from 'fs';
|
|
7
8
|
import Database2 from 'better-sqlite3';
|
|
8
9
|
import { glob } from 'glob';
|
|
@@ -23,9 +24,7 @@ import { randomUUID } from 'crypto';
|
|
|
23
24
|
import yaml from 'yaml';
|
|
24
25
|
|
|
25
26
|
var __defProp = Object.defineProperty;
|
|
26
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
27
27
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
28
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
29
28
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
30
29
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
31
30
|
}) : x)(function(x) {
|
|
@@ -39,15 +38,6 @@ var __export = (target, all) => {
|
|
|
39
38
|
for (var name in all)
|
|
40
39
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
41
40
|
};
|
|
42
|
-
var __copyProps = (to, from, except, desc) => {
|
|
43
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
44
|
-
for (let key of __getOwnPropNames(from))
|
|
45
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
46
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
47
|
-
}
|
|
48
|
-
return to;
|
|
49
|
-
};
|
|
50
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
51
41
|
var init_esm_shims = __esm({
|
|
52
42
|
"node_modules/tsup/assets/esm_shims.js"() {
|
|
53
43
|
}
|
|
@@ -328,16 +318,16 @@ var init_errors = __esm({
|
|
|
328
318
|
constructor(message, code = "E1001" /* CONFIG_INVALID */, suggestions = [], context) {
|
|
329
319
|
super(message, code, suggestions, context);
|
|
330
320
|
}
|
|
331
|
-
static notFound(
|
|
321
|
+
static notFound(path6) {
|
|
332
322
|
return new _ConfigError(
|
|
333
|
-
`Configuration file not found: ${
|
|
323
|
+
`Configuration file not found: ${path6}`,
|
|
334
324
|
"E1000" /* CONFIG_NOT_FOUND */,
|
|
335
325
|
[
|
|
336
326
|
'Run "automatosx setup" to create a new configuration',
|
|
337
327
|
"Specify a custom config path with --config option",
|
|
338
328
|
"Check that you are in a valid AutomatosX project directory"
|
|
339
329
|
],
|
|
340
|
-
{ path:
|
|
330
|
+
{ path: path6 }
|
|
341
331
|
);
|
|
342
332
|
}
|
|
343
333
|
static invalid(reason, context) {
|
|
@@ -352,7 +342,7 @@ var init_errors = __esm({
|
|
|
352
342
|
context
|
|
353
343
|
);
|
|
354
344
|
}
|
|
355
|
-
static parseError(error,
|
|
345
|
+
static parseError(error, path6) {
|
|
356
346
|
return new _ConfigError(
|
|
357
347
|
`Failed to parse configuration: ${error.message}`,
|
|
358
348
|
"E1002" /* CONFIG_PARSE_ERROR */,
|
|
@@ -361,7 +351,7 @@ var init_errors = __esm({
|
|
|
361
351
|
"Use a JSON validator to find syntax errors",
|
|
362
352
|
'Reset to default with "automatosx setup --force"'
|
|
363
353
|
],
|
|
364
|
-
{ path:
|
|
354
|
+
{ path: path6, originalError: error.message }
|
|
365
355
|
);
|
|
366
356
|
}
|
|
367
357
|
};
|
|
@@ -1174,11 +1164,11 @@ var init_workspace_indexer = __esm({
|
|
|
1174
1164
|
/**
|
|
1175
1165
|
* Detect file type and language
|
|
1176
1166
|
*/
|
|
1177
|
-
detectTypeAndLanguage(
|
|
1178
|
-
if (
|
|
1167
|
+
detectTypeAndLanguage(path6, ext) {
|
|
1168
|
+
if (path6.match(/package\.json|tsconfig\.json|\.config\.(js|ts|json|yaml|yml)|\.eslintrc|\.prettierrc/)) {
|
|
1179
1169
|
return { type: "config", language: "json" };
|
|
1180
1170
|
}
|
|
1181
|
-
if (
|
|
1171
|
+
if (path6.match(/\.(test|spec)\.(ts|js|tsx|jsx)$/) || path6.includes("__tests__")) {
|
|
1182
1172
|
const lang = LANGUAGE_MAP[ext];
|
|
1183
1173
|
return { type: "test", language: lang };
|
|
1184
1174
|
}
|
|
@@ -1195,15 +1185,15 @@ var init_workspace_indexer = __esm({
|
|
|
1195
1185
|
*
|
|
1196
1186
|
* Higher score = more likely to be relevant
|
|
1197
1187
|
*/
|
|
1198
|
-
calculateImportance(
|
|
1188
|
+
calculateImportance(path6, type, size) {
|
|
1199
1189
|
let score = 0.5;
|
|
1200
|
-
if (
|
|
1201
|
-
if (
|
|
1202
|
-
if (
|
|
1190
|
+
if (path6.match(/^(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 1;
|
|
1191
|
+
if (path6.match(/^src\/(index|main|app)\.(ts|js|tsx|jsx)$/)) score = 0.95;
|
|
1192
|
+
if (path6.match(/^src\/cli\/(index|main)\.(ts|js)$/)) score = 0.9;
|
|
1203
1193
|
if (type === "config") score = 0.85;
|
|
1204
|
-
if (
|
|
1205
|
-
if (
|
|
1206
|
-
if (
|
|
1194
|
+
if (path6.includes("/core/")) score += 0.15;
|
|
1195
|
+
if (path6.includes("/types/")) score += 0.1;
|
|
1196
|
+
if (path6.includes("/utils/")) score += 0.05;
|
|
1207
1197
|
if (type === "test") score = Math.max(0.3, score - 0.3);
|
|
1208
1198
|
if (type === "doc") score = Math.max(0.4, score - 0.2);
|
|
1209
1199
|
if (size > 1e4) score += 0.05;
|
|
@@ -1679,10 +1669,10 @@ function findOnPathUnix(cmdBase) {
|
|
|
1679
1669
|
try {
|
|
1680
1670
|
const which = spawnSync("which", [cmdBase], { timeout: 3e3 });
|
|
1681
1671
|
if (which.status === 0) {
|
|
1682
|
-
const
|
|
1683
|
-
if (
|
|
1684
|
-
logger.debug("Found via which", { cmdBase, path:
|
|
1685
|
-
return { found: true, path:
|
|
1672
|
+
const path6 = which.stdout.toString().trim();
|
|
1673
|
+
if (path6) {
|
|
1674
|
+
logger.debug("Found via which", { cmdBase, path: path6 });
|
|
1675
|
+
return { found: true, path: path6 };
|
|
1686
1676
|
}
|
|
1687
1677
|
}
|
|
1688
1678
|
} catch (error) {
|
|
@@ -1981,15 +1971,6 @@ var init_streaming_progress_parser = __esm({
|
|
|
1981
1971
|
});
|
|
1982
1972
|
|
|
1983
1973
|
// src/providers/error-patterns.ts
|
|
1984
|
-
var error_patterns_exports = {};
|
|
1985
|
-
__export(error_patterns_exports, {
|
|
1986
|
-
GENERIC_ERROR_PATTERNS: () => GENERIC_ERROR_PATTERNS,
|
|
1987
|
-
PROVIDER_ERROR_PATTERNS: () => PROVIDER_ERROR_PATTERNS,
|
|
1988
|
-
getProviderErrorPatterns: () => getProviderErrorPatterns,
|
|
1989
|
-
isLimitError: () => isLimitError,
|
|
1990
|
-
isQuotaError: () => isQuotaError,
|
|
1991
|
-
isRateLimitError: () => isRateLimitError
|
|
1992
|
-
});
|
|
1993
1974
|
function isQuotaError(error, providerName) {
|
|
1994
1975
|
const patterns = PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
|
|
1995
1976
|
const message = (error?.message || "").toLowerCase();
|
|
@@ -2031,9 +2012,6 @@ function isRateLimitError(error, providerName) {
|
|
|
2031
2012
|
function isLimitError(error, providerName) {
|
|
2032
2013
|
return isQuotaError(error, providerName) || isRateLimitError(error, providerName);
|
|
2033
2014
|
}
|
|
2034
|
-
function getProviderErrorPatterns(providerName) {
|
|
2035
|
-
return PROVIDER_ERROR_PATTERNS[providerName] || GENERIC_ERROR_PATTERNS;
|
|
2036
|
-
}
|
|
2037
2015
|
var PROVIDER_ERROR_PATTERNS, GENERIC_ERROR_PATTERNS;
|
|
2038
2016
|
var init_error_patterns = __esm({
|
|
2039
2017
|
"src/providers/error-patterns.ts"() {
|
|
@@ -2254,6 +2232,7 @@ var init_base_provider = __esm({
|
|
|
2254
2232
|
init_provider_schemas();
|
|
2255
2233
|
init_streaming_progress_parser();
|
|
2256
2234
|
init_verbosity_manager();
|
|
2235
|
+
init_error_patterns();
|
|
2257
2236
|
BaseProvider = class _BaseProvider {
|
|
2258
2237
|
/**
|
|
2259
2238
|
* Whitelist of allowed provider names for security
|
|
@@ -2286,6 +2265,10 @@ var init_base_provider = __esm({
|
|
|
2286
2265
|
NO_UPDATE_NOTIFIER: "1",
|
|
2287
2266
|
DEBIAN_FRONTEND: "noninteractive"
|
|
2288
2267
|
};
|
|
2268
|
+
/** Default CLI execution timeout in milliseconds */
|
|
2269
|
+
static DEFAULT_TIMEOUT_MS = 12e4;
|
|
2270
|
+
/** Time to wait after SIGTERM before escalating to SIGKILL */
|
|
2271
|
+
static SIGKILL_ESCALATION_MS = 5e3;
|
|
2289
2272
|
config;
|
|
2290
2273
|
logger = logger;
|
|
2291
2274
|
health;
|
|
@@ -2343,7 +2326,7 @@ var init_base_provider = __esm({
|
|
|
2343
2326
|
useStdin,
|
|
2344
2327
|
streaming: process.env.AUTOMATOSX_SHOW_PROVIDER_OUTPUT === "true"
|
|
2345
2328
|
});
|
|
2346
|
-
const result = useStdin ? await this.executeWithStdin(cliCommand,
|
|
2329
|
+
const result = useStdin ? await this.executeWithStdin(cliCommand, cliArgs, prompt) : await this.executeWithSpawn(fullCommand, cliCommand);
|
|
2347
2330
|
if (!result.stdout) {
|
|
2348
2331
|
throw new Error(`${cliCommand} CLI returned empty output. stderr: ${result.stderr || "none"}`);
|
|
2349
2332
|
}
|
|
@@ -2365,8 +2348,8 @@ var init_base_provider = __esm({
|
|
|
2365
2348
|
/**
|
|
2366
2349
|
* Execute command using spawn() with streaming support (v8.4.18)
|
|
2367
2350
|
*
|
|
2368
|
-
*
|
|
2369
|
-
*
|
|
2351
|
+
* Supports real-time line-by-line output streaming with proper timeout
|
|
2352
|
+
* and cleanup behaviors (SIGTERM → SIGKILL escalation pattern).
|
|
2370
2353
|
*
|
|
2371
2354
|
* @param command - Full command string to execute
|
|
2372
2355
|
* @param cliCommand - CLI command name (for logging)
|
|
@@ -2377,7 +2360,7 @@ var init_base_provider = __esm({
|
|
|
2377
2360
|
const child = spawn(command, [], {
|
|
2378
2361
|
shell: true,
|
|
2379
2362
|
// Auto-detects: cmd.exe on Windows, /bin/sh on Unix
|
|
2380
|
-
timeout: this.config.timeout ||
|
|
2363
|
+
timeout: this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS,
|
|
2381
2364
|
env: { ...process.env, ..._BaseProvider.NON_INTERACTIVE_ENV }
|
|
2382
2365
|
});
|
|
2383
2366
|
let stdout = "";
|
|
@@ -2488,7 +2471,7 @@ var init_base_provider = __esm({
|
|
|
2488
2471
|
});
|
|
2489
2472
|
reject(new Error(`Failed to spawn ${cliCommand} CLI: ${error.message}`));
|
|
2490
2473
|
});
|
|
2491
|
-
const timeout = this.config.timeout ||
|
|
2474
|
+
const timeout = this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS;
|
|
2492
2475
|
timeoutId = setTimeout(() => {
|
|
2493
2476
|
if (child.pid && !child.killed) {
|
|
2494
2477
|
logger.warn("Killing child process due to timeout", {
|
|
@@ -2502,7 +2485,7 @@ var init_base_provider = __esm({
|
|
|
2502
2485
|
logger.warn("Force killing child process", { pid: child.pid });
|
|
2503
2486
|
child.kill("SIGKILL");
|
|
2504
2487
|
}
|
|
2505
|
-
},
|
|
2488
|
+
}, _BaseProvider.SIGKILL_ESCALATION_MS);
|
|
2506
2489
|
}
|
|
2507
2490
|
}, timeout);
|
|
2508
2491
|
});
|
|
@@ -2520,14 +2503,13 @@ var init_base_provider = __esm({
|
|
|
2520
2503
|
*/
|
|
2521
2504
|
async executeWithStdin(cliCommand, cliArgs, prompt) {
|
|
2522
2505
|
return new Promise((resolve5, reject) => {
|
|
2523
|
-
const commandArgs = cliArgs ? cliArgs.split(" ").filter(Boolean) : [];
|
|
2524
2506
|
logger.debug(`Executing ${cliCommand} CLI with stdin`, {
|
|
2525
2507
|
command: cliCommand,
|
|
2526
|
-
args:
|
|
2508
|
+
args: cliArgs,
|
|
2527
2509
|
promptLength: prompt.length
|
|
2528
2510
|
});
|
|
2529
|
-
const child = spawn(cliCommand,
|
|
2530
|
-
timeout: this.config.timeout ||
|
|
2511
|
+
const child = spawn(cliCommand, cliArgs, {
|
|
2512
|
+
timeout: this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS,
|
|
2531
2513
|
env: { ...process.env, ..._BaseProvider.NON_INTERACTIVE_ENV }
|
|
2532
2514
|
});
|
|
2533
2515
|
let stdout = "";
|
|
@@ -2663,7 +2645,7 @@ var init_base_provider = __esm({
|
|
|
2663
2645
|
});
|
|
2664
2646
|
reject(new Error(`Failed to spawn ${cliCommand} CLI: ${error.message}`));
|
|
2665
2647
|
});
|
|
2666
|
-
const timeout = this.config.timeout ||
|
|
2648
|
+
const timeout = this.config.timeout || _BaseProvider.DEFAULT_TIMEOUT_MS;
|
|
2667
2649
|
timeoutId = setTimeout(() => {
|
|
2668
2650
|
if (child.pid && !child.killed) {
|
|
2669
2651
|
logger.warn("Killing child process due to timeout", {
|
|
@@ -2677,7 +2659,7 @@ var init_base_provider = __esm({
|
|
|
2677
2659
|
logger.warn("Force killing child process", { pid: child.pid });
|
|
2678
2660
|
child.kill("SIGKILL");
|
|
2679
2661
|
}
|
|
2680
|
-
},
|
|
2662
|
+
}, _BaseProvider.SIGKILL_ESCALATION_MS);
|
|
2681
2663
|
}
|
|
2682
2664
|
}, timeout);
|
|
2683
2665
|
});
|
|
@@ -2743,9 +2725,7 @@ var init_base_provider = __esm({
|
|
|
2743
2725
|
${request.prompt}`;
|
|
2744
2726
|
}
|
|
2745
2727
|
if (process.env.AUTOMATOSX_DEBUG_PROMPT === "true") {
|
|
2746
|
-
const
|
|
2747
|
-
const path5 = await import('path');
|
|
2748
|
-
const debugPath = path5.join(process.cwd(), "automatosx/tmp/debug-prompt.txt");
|
|
2728
|
+
const debugPath = path4.join(process.cwd(), "automatosx/tmp/debug-prompt.txt");
|
|
2749
2729
|
fs3.writeFileSync(debugPath, `=== FULL PROMPT SENT TO ${this.getCLICommand()} ===
|
|
2750
2730
|
|
|
2751
2731
|
${fullPrompt}
|
|
@@ -2869,26 +2849,16 @@ ${fullPrompt}
|
|
|
2869
2849
|
* @returns true if this is a rate limit or quota error
|
|
2870
2850
|
*/
|
|
2871
2851
|
detectRateLimitError(error) {
|
|
2872
|
-
const
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
if (isLimited) {
|
|
2876
|
-
this.logger.debug("Rate limit error detected", {
|
|
2877
|
-
provider: this.config.name,
|
|
2878
|
-
message: error?.message,
|
|
2879
|
-
code: error?.code,
|
|
2880
|
-
status: error?.status || error?.statusCode
|
|
2881
|
-
});
|
|
2882
|
-
}
|
|
2883
|
-
return isLimited;
|
|
2884
|
-
} catch (detectionError) {
|
|
2885
|
-
this.logger.warn("Rate limit detection failed, using fallback", {
|
|
2852
|
+
const isLimited = isLimitError(error, this.config.name);
|
|
2853
|
+
if (isLimited) {
|
|
2854
|
+
this.logger.debug("Rate limit error detected", {
|
|
2886
2855
|
provider: this.config.name,
|
|
2887
|
-
|
|
2856
|
+
message: error?.message,
|
|
2857
|
+
code: error?.code,
|
|
2858
|
+
status: error?.status || error?.statusCode
|
|
2888
2859
|
});
|
|
2889
|
-
const message = (error?.message || "").toLowerCase();
|
|
2890
|
-
return message.includes("rate limit") || message.includes("quota") || message.includes("resource_exhausted") || message.includes("too many requests");
|
|
2891
2860
|
}
|
|
2861
|
+
return isLimited;
|
|
2892
2862
|
}
|
|
2893
2863
|
/**
|
|
2894
2864
|
* Escape shell command arguments to prevent injection
|
|
@@ -4578,11 +4548,11 @@ var VALIDATION_LIMITS = {
|
|
|
4578
4548
|
MAX_PORT: 65535
|
|
4579
4549
|
// Maximum port number
|
|
4580
4550
|
};
|
|
4581
|
-
function isValidRelativePath(
|
|
4582
|
-
if (!
|
|
4551
|
+
function isValidRelativePath(path6) {
|
|
4552
|
+
if (!path6 || typeof path6 !== "string") {
|
|
4583
4553
|
return false;
|
|
4584
4554
|
}
|
|
4585
|
-
const normalizedPath =
|
|
4555
|
+
const normalizedPath = path6.replace(/\\/g, "/");
|
|
4586
4556
|
if (normalizedPath.startsWith("/")) {
|
|
4587
4557
|
return false;
|
|
4588
4558
|
}
|
|
@@ -5212,11 +5182,16 @@ var PRECOMPILED_CONFIG = {
|
|
|
5212
5182
|
},
|
|
5213
5183
|
"advanced": {
|
|
5214
5184
|
"embedding": {
|
|
5185
|
+
"model": "text-embedding-3-small",
|
|
5215
5186
|
"timeout": 3e4,
|
|
5216
5187
|
"retryDelay": 1e3,
|
|
5217
5188
|
"dimensions": 1536,
|
|
5218
5189
|
"maxRetries": 3
|
|
5219
5190
|
},
|
|
5191
|
+
"projectContext": {
|
|
5192
|
+
"maxSizeBytes": 102400,
|
|
5193
|
+
"cacheTtlMs": 3e5
|
|
5194
|
+
},
|
|
5220
5195
|
"security": {
|
|
5221
5196
|
"enablePathValidation": true,
|
|
5222
5197
|
"allowedExtensions": [
|
|
@@ -5272,7 +5247,23 @@ var PRECOMPILED_CONFIG = {
|
|
|
5272
5247
|
"enableFreeTierPrioritization": true,
|
|
5273
5248
|
"enableWorkloadAwareRouting": true
|
|
5274
5249
|
},
|
|
5275
|
-
"
|
|
5250
|
+
"axCliSdk": {
|
|
5251
|
+
"maxToolRounds": 400,
|
|
5252
|
+
"checkpoint": {
|
|
5253
|
+
"maxCheckpoints": 10,
|
|
5254
|
+
"flushTimeoutMs": 5e3
|
|
5255
|
+
},
|
|
5256
|
+
"subagent": {
|
|
5257
|
+
"maxParallel": 4,
|
|
5258
|
+
"timeoutMs": 3e5,
|
|
5259
|
+
"maxToolRounds": 100
|
|
5260
|
+
},
|
|
5261
|
+
"instructions": {
|
|
5262
|
+
"cacheTtlMs": 3e5,
|
|
5263
|
+
"maxContextLength": 32e3
|
|
5264
|
+
}
|
|
5265
|
+
},
|
|
5266
|
+
"version": "11.3.2"
|
|
5276
5267
|
};
|
|
5277
5268
|
|
|
5278
5269
|
// src/core/config/schemas.ts
|
|
@@ -5299,7 +5290,7 @@ var safeNameSchema = z.string().min(1).max(VALIDATION_LIMITS.MAX_NAME_LENGTH).re
|
|
|
5299
5290
|
"Name must be alphanumeric with dash/underscore only"
|
|
5300
5291
|
).describe("Safe identifier name");
|
|
5301
5292
|
var relativePathSchema = z.string().min(1).refine(
|
|
5302
|
-
(
|
|
5293
|
+
(path6) => !path6.includes("..") && !path6.startsWith("/"),
|
|
5303
5294
|
"Path must be relative (no ../, no absolute paths)"
|
|
5304
5295
|
).describe("Relative path within project");
|
|
5305
5296
|
var fileExtensionSchema = z.string().regex(
|
|
@@ -5639,16 +5630,16 @@ async function loadConfigUncached(projectDir) {
|
|
|
5639
5630
|
});
|
|
5640
5631
|
return config;
|
|
5641
5632
|
}
|
|
5642
|
-
async function loadConfigFile(
|
|
5633
|
+
async function loadConfigFile(path6) {
|
|
5643
5634
|
try {
|
|
5644
|
-
const content = await readFile(
|
|
5635
|
+
const content = await readFile(path6, "utf-8");
|
|
5645
5636
|
if (content.length > VALIDATION_LIMITS.MAX_CONFIG_FILE_SIZE) {
|
|
5646
5637
|
throw ConfigError.parseError(
|
|
5647
5638
|
new Error(`Config file too large (max ${VALIDATION_LIMITS.MAX_CONFIG_FILE_SIZE / 1024}KB, got ${Math.ceil(content.length / 1024)}KB)`),
|
|
5648
|
-
|
|
5639
|
+
path6
|
|
5649
5640
|
);
|
|
5650
5641
|
}
|
|
5651
|
-
const ext = extname(
|
|
5642
|
+
const ext = extname(path6).toLowerCase();
|
|
5652
5643
|
let userConfig;
|
|
5653
5644
|
try {
|
|
5654
5645
|
if (ext === ".yaml" || ext === ".yml") {
|
|
@@ -5657,7 +5648,7 @@ async function loadConfigFile(path5) {
|
|
|
5657
5648
|
userConfig = JSON.parse(content);
|
|
5658
5649
|
}
|
|
5659
5650
|
} catch (parseError) {
|
|
5660
|
-
throw ConfigError.parseError(parseError,
|
|
5651
|
+
throw ConfigError.parseError(parseError, path6);
|
|
5661
5652
|
}
|
|
5662
5653
|
const config = mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
5663
5654
|
if (config.execution && userConfig.execution?.maxConcurrentAgents === void 0) {
|
|
@@ -5673,35 +5664,35 @@ async function loadConfigFile(path5) {
|
|
|
5673
5664
|
if (validationErrors.length > 0) {
|
|
5674
5665
|
throw ConfigError.invalid(
|
|
5675
5666
|
validationErrors.join("; "),
|
|
5676
|
-
{ path:
|
|
5667
|
+
{ path: path6, errors: validationErrors }
|
|
5677
5668
|
);
|
|
5678
5669
|
}
|
|
5679
|
-
logger.info("Config loaded successfully", { path: normalizePath(
|
|
5670
|
+
logger.info("Config loaded successfully", { path: normalizePath(path6), format: ext });
|
|
5680
5671
|
return config;
|
|
5681
5672
|
} catch (error) {
|
|
5682
5673
|
if (error instanceof ConfigError) {
|
|
5683
5674
|
throw error;
|
|
5684
5675
|
}
|
|
5685
5676
|
if (error.code === "ENOENT") {
|
|
5686
|
-
throw ConfigError.notFound(
|
|
5677
|
+
throw ConfigError.notFound(path6);
|
|
5687
5678
|
}
|
|
5688
5679
|
if (error.code === "EACCES") {
|
|
5689
5680
|
throw new ConfigError(
|
|
5690
|
-
`Permission denied reading config: ${
|
|
5681
|
+
`Permission denied reading config: ${path6}`,
|
|
5691
5682
|
"E1002" /* CONFIG_PARSE_ERROR */,
|
|
5692
5683
|
[
|
|
5693
5684
|
"Check file permissions",
|
|
5694
5685
|
"Run with appropriate user privileges",
|
|
5695
5686
|
"Verify the file is accessible"
|
|
5696
5687
|
],
|
|
5697
|
-
{ path:
|
|
5688
|
+
{ path: path6, error: error.message }
|
|
5698
5689
|
);
|
|
5699
5690
|
}
|
|
5700
5691
|
throw new ConfigError(
|
|
5701
5692
|
`Failed to load config: ${error.message}`,
|
|
5702
5693
|
"E1002" /* CONFIG_PARSE_ERROR */,
|
|
5703
5694
|
["Check file format and permissions"],
|
|
5704
|
-
{ path:
|
|
5695
|
+
{ path: path6, originalError: error.message }
|
|
5705
5696
|
);
|
|
5706
5697
|
}
|
|
5707
5698
|
}
|
|
@@ -5717,8 +5708,8 @@ function validateConfigWithZod(config) {
|
|
|
5717
5708
|
return ["Configuration validation failed with unknown error structure"];
|
|
5718
5709
|
}
|
|
5719
5710
|
return result.error.issues.map((err) => {
|
|
5720
|
-
const
|
|
5721
|
-
return `${
|
|
5711
|
+
const path6 = err.path.join(".");
|
|
5712
|
+
return `${path6}: ${err.message}`;
|
|
5722
5713
|
});
|
|
5723
5714
|
}
|
|
5724
5715
|
function validateConfig(config) {
|
|
@@ -6128,8 +6119,8 @@ var PathError = class extends Error {
|
|
|
6128
6119
|
};
|
|
6129
6120
|
|
|
6130
6121
|
// src/shared/validation/path-resolver.ts
|
|
6131
|
-
function isWindowsPath(
|
|
6132
|
-
return /^[a-zA-Z]:[/\\]/.test(
|
|
6122
|
+
function isWindowsPath(path6) {
|
|
6123
|
+
return /^[a-zA-Z]:[/\\]/.test(path6);
|
|
6133
6124
|
}
|
|
6134
6125
|
async function detectProjectRoot(startDir = process.cwd()) {
|
|
6135
6126
|
if (process.env.AUTOMATOSX_PROJECT_ROOT) {
|
|
@@ -6229,8 +6220,8 @@ var PathResolver = class {
|
|
|
6229
6220
|
/**
|
|
6230
6221
|
* Validate path is within allowed base directory
|
|
6231
6222
|
*/
|
|
6232
|
-
validatePath(
|
|
6233
|
-
const normalized = normalizePath(resolvePath(
|
|
6223
|
+
validatePath(path6, baseDir) {
|
|
6224
|
+
const normalized = normalizePath(resolvePath(path6));
|
|
6234
6225
|
const base = normalizePath(resolvePath(baseDir));
|
|
6235
6226
|
const separator = "/";
|
|
6236
6227
|
const pathWithSep = normalized + separator;
|
|
@@ -6240,15 +6231,15 @@ var PathResolver = class {
|
|
|
6240
6231
|
/**
|
|
6241
6232
|
* Check if path is within allowed boundaries
|
|
6242
6233
|
*/
|
|
6243
|
-
isPathAllowed(
|
|
6244
|
-
const boundary = this.checkBoundaries(
|
|
6234
|
+
isPathAllowed(path6) {
|
|
6235
|
+
const boundary = this.checkBoundaries(path6);
|
|
6245
6236
|
return boundary === "agent_workspace" || boundary === "user_project";
|
|
6246
6237
|
}
|
|
6247
6238
|
/**
|
|
6248
6239
|
* Check which boundary a path belongs to
|
|
6249
6240
|
*/
|
|
6250
|
-
checkBoundaries(
|
|
6251
|
-
const normalized = resolvePath(
|
|
6241
|
+
checkBoundaries(path6) {
|
|
6242
|
+
const normalized = resolvePath(path6);
|
|
6252
6243
|
if (this.validatePath(normalized, this.config.agentWorkspace)) {
|
|
6253
6244
|
return "agent_workspace";
|
|
6254
6245
|
}
|
|
@@ -6266,15 +6257,15 @@ var PathResolver = class {
|
|
|
6266
6257
|
/**
|
|
6267
6258
|
* Get relative path from project root
|
|
6268
6259
|
*/
|
|
6269
|
-
getRelativeToProject(
|
|
6270
|
-
const normalized = resolvePath(
|
|
6260
|
+
getRelativeToProject(path6) {
|
|
6261
|
+
const normalized = resolvePath(path6);
|
|
6271
6262
|
return normalizePath(getRelativePath(this.config.projectDir, normalized));
|
|
6272
6263
|
}
|
|
6273
6264
|
/**
|
|
6274
6265
|
* Get relative path from working directory
|
|
6275
6266
|
*/
|
|
6276
|
-
getRelativeToWorking(
|
|
6277
|
-
const normalized = resolvePath(
|
|
6267
|
+
getRelativeToWorking(path6) {
|
|
6268
|
+
const normalized = resolvePath(path6);
|
|
6278
6269
|
return normalizePath(getRelativePath(this.config.workingDir, normalized));
|
|
6279
6270
|
}
|
|
6280
6271
|
/**
|
|
@@ -6293,11 +6284,11 @@ var PathResolver = class {
|
|
|
6293
6284
|
* Validate path is within project boundaries
|
|
6294
6285
|
* @throws PathError if outside project
|
|
6295
6286
|
*/
|
|
6296
|
-
validateInProject(
|
|
6297
|
-
const boundary = this.checkBoundaries(
|
|
6287
|
+
validateInProject(path6) {
|
|
6288
|
+
const boundary = this.checkBoundaries(path6);
|
|
6298
6289
|
if (boundary === "outside_boundaries" || boundary === "system_restricted") {
|
|
6299
6290
|
throw new PathError("Path outside project directory", {
|
|
6300
|
-
path:
|
|
6291
|
+
path: path6,
|
|
6301
6292
|
projectDir: this.config.projectDir,
|
|
6302
6293
|
boundary
|
|
6303
6294
|
});
|
|
@@ -8164,18 +8155,18 @@ var ProviderSessionManager = class {
|
|
|
8164
8155
|
};
|
|
8165
8156
|
var providerSessionInstances = /* @__PURE__ */ new Map();
|
|
8166
8157
|
async function getProviderSession(workspacePath) {
|
|
8167
|
-
let
|
|
8158
|
+
let path6;
|
|
8168
8159
|
{
|
|
8169
8160
|
if (process.env.NODE_ENV === "test" || process.env.VITEST) {
|
|
8170
|
-
|
|
8161
|
+
path6 = process.cwd();
|
|
8171
8162
|
} else {
|
|
8172
|
-
|
|
8163
|
+
path6 = await detectProjectRoot();
|
|
8173
8164
|
}
|
|
8174
8165
|
}
|
|
8175
|
-
if (!providerSessionInstances.has(
|
|
8176
|
-
providerSessionInstances.set(
|
|
8166
|
+
if (!providerSessionInstances.has(path6)) {
|
|
8167
|
+
providerSessionInstances.set(path6, new ProviderSessionManager(path6));
|
|
8177
8168
|
}
|
|
8178
|
-
return providerSessionInstances.get(
|
|
8169
|
+
return providerSessionInstances.get(path6);
|
|
8179
8170
|
}
|
|
8180
8171
|
|
|
8181
8172
|
// src/core/router/router.ts
|
|
@@ -9944,6 +9935,9 @@ var MemoryManager = class _MemoryManager {
|
|
|
9944
9935
|
if (!Number.isInteger(offsetValue) || offsetValue < 0) {
|
|
9945
9936
|
throw new Error(`Invalid offset value: ${options.offset}. Must be a non-negative integer.`);
|
|
9946
9937
|
}
|
|
9938
|
+
if (!limitClause) {
|
|
9939
|
+
limitClause = "LIMIT -1";
|
|
9940
|
+
}
|
|
9947
9941
|
offsetClause = `OFFSET ${offsetValue}`;
|
|
9948
9942
|
}
|
|
9949
9943
|
const sql = `
|
|
@@ -10297,6 +10291,13 @@ var MemoryManager = class _MemoryManager {
|
|
|
10297
10291
|
await this.initialize();
|
|
10298
10292
|
logger.info("Database restored successfully (atomic operation)", { srcPath: normalizePath(srcPath) });
|
|
10299
10293
|
} catch (error) {
|
|
10294
|
+
try {
|
|
10295
|
+
DatabaseFactory.close(this.db);
|
|
10296
|
+
} finally {
|
|
10297
|
+
this.initialized = false;
|
|
10298
|
+
this.entryCount = 0;
|
|
10299
|
+
this.statements = {};
|
|
10300
|
+
}
|
|
10300
10301
|
throw new MemoryError(
|
|
10301
10302
|
`Failed to restore database: ${error.message}`,
|
|
10302
10303
|
"DATABASE_ERROR",
|
|
@@ -10846,6 +10847,10 @@ var SessionManager = class _SessionManager {
|
|
|
10846
10847
|
MAX_TASKS_PER_SESSION = 1e3;
|
|
10847
10848
|
/** UUID v4 validation regex (static for performance) */
|
|
10848
10849
|
static UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
10850
|
+
/** Tracks whether manager has been destroyed to prevent late saves */
|
|
10851
|
+
destroyed = false;
|
|
10852
|
+
/** Last persistence error (reported during flush) */
|
|
10853
|
+
lastSaveError;
|
|
10849
10854
|
/**
|
|
10850
10855
|
* Validate session ID format (must be valid UUID v4)
|
|
10851
10856
|
*
|
|
@@ -11440,6 +11445,7 @@ var SessionManager = class _SessionManager {
|
|
|
11440
11445
|
* ```
|
|
11441
11446
|
*/
|
|
11442
11447
|
async destroy() {
|
|
11448
|
+
this.destroyed = true;
|
|
11443
11449
|
if (this.saveTimeout) {
|
|
11444
11450
|
clearTimeout(this.saveTimeout);
|
|
11445
11451
|
this.saveTimeout = void 0;
|
|
@@ -11450,9 +11456,12 @@ var SessionManager = class _SessionManager {
|
|
|
11450
11456
|
logger.error("Error flushing save during destroy", {
|
|
11451
11457
|
error: error.message
|
|
11452
11458
|
});
|
|
11459
|
+
this.lastSaveError = void 0;
|
|
11453
11460
|
}
|
|
11461
|
+
const sessionCount = this.activeSessions.size;
|
|
11462
|
+
this.activeSessions.clear();
|
|
11454
11463
|
logger.debug("SessionManager destroyed", {
|
|
11455
|
-
sessions:
|
|
11464
|
+
sessions: sessionCount
|
|
11456
11465
|
});
|
|
11457
11466
|
}
|
|
11458
11467
|
/**
|
|
@@ -11477,11 +11486,21 @@ var SessionManager = class _SessionManager {
|
|
|
11477
11486
|
this.pendingSave = void 0;
|
|
11478
11487
|
});
|
|
11479
11488
|
await this.pendingSave;
|
|
11489
|
+
if (this.lastSaveError) {
|
|
11490
|
+
const err = this.lastSaveError;
|
|
11491
|
+
this.lastSaveError = void 0;
|
|
11492
|
+
throw err;
|
|
11493
|
+
}
|
|
11480
11494
|
return;
|
|
11481
11495
|
}
|
|
11482
11496
|
if (this.pendingSave) {
|
|
11483
11497
|
try {
|
|
11484
11498
|
await this.pendingSave;
|
|
11499
|
+
if (this.lastSaveError) {
|
|
11500
|
+
const err = this.lastSaveError;
|
|
11501
|
+
this.lastSaveError = void 0;
|
|
11502
|
+
throw err;
|
|
11503
|
+
}
|
|
11485
11504
|
} catch (err) {
|
|
11486
11505
|
throw err;
|
|
11487
11506
|
}
|
|
@@ -11646,7 +11665,7 @@ var SessionManager = class _SessionManager {
|
|
|
11646
11665
|
* @private
|
|
11647
11666
|
*/
|
|
11648
11667
|
saveToFile() {
|
|
11649
|
-
if (!this.persistencePath) {
|
|
11668
|
+
if (!this.persistencePath || this.destroyed) {
|
|
11650
11669
|
return;
|
|
11651
11670
|
}
|
|
11652
11671
|
if (this.saveTimeout) {
|
|
@@ -11659,18 +11678,18 @@ var SessionManager = class _SessionManager {
|
|
|
11659
11678
|
}
|
|
11660
11679
|
this.saveNeeded = false;
|
|
11661
11680
|
const executeNextSave = async () => {
|
|
11662
|
-
|
|
11681
|
+
try {
|
|
11682
|
+
await this.doSave();
|
|
11683
|
+
this.lastSaveError = void 0;
|
|
11684
|
+
} catch (err) {
|
|
11685
|
+
this.lastSaveError = err;
|
|
11686
|
+
}
|
|
11663
11687
|
if (this.saveNeeded) {
|
|
11664
11688
|
this.saveNeeded = false;
|
|
11665
11689
|
return executeNextSave();
|
|
11666
11690
|
}
|
|
11667
11691
|
};
|
|
11668
|
-
this.pendingSave = executeNextSave().
|
|
11669
|
-
logger.error("Debounced save failed", {
|
|
11670
|
-
error: err.message
|
|
11671
|
-
});
|
|
11672
|
-
throw err;
|
|
11673
|
-
}).finally(() => {
|
|
11692
|
+
this.pendingSave = executeNextSave().finally(() => {
|
|
11674
11693
|
this.pendingSave = void 0;
|
|
11675
11694
|
});
|
|
11676
11695
|
}, 100);
|
|
@@ -15081,9 +15100,9 @@ var DependencyGraphBuilder = class {
|
|
|
15081
15100
|
detectCycles(graph) {
|
|
15082
15101
|
const visiting = /* @__PURE__ */ new Set();
|
|
15083
15102
|
const visited = /* @__PURE__ */ new Set();
|
|
15084
|
-
const visit = (nodeName,
|
|
15103
|
+
const visit = (nodeName, path6) => {
|
|
15085
15104
|
if (visiting.has(nodeName)) {
|
|
15086
|
-
throw new Error(`Circular dependency detected: ${[...
|
|
15105
|
+
throw new Error(`Circular dependency detected: ${[...path6, nodeName].join(" \u2192 ")}`);
|
|
15087
15106
|
}
|
|
15088
15107
|
if (visited.has(nodeName)) {
|
|
15089
15108
|
return;
|
|
@@ -15098,7 +15117,7 @@ var DependencyGraphBuilder = class {
|
|
|
15098
15117
|
}
|
|
15099
15118
|
visiting.add(nodeName);
|
|
15100
15119
|
for (const dependency of node.dependencies) {
|
|
15101
|
-
visit(dependency, [...
|
|
15120
|
+
visit(dependency, [...path6, nodeName]);
|
|
15102
15121
|
}
|
|
15103
15122
|
visiting.delete(nodeName);
|
|
15104
15123
|
visited.add(nodeName);
|
|
@@ -16831,59 +16850,59 @@ var DANGEROUS_PATH_PATTERNS = [
|
|
|
16831
16850
|
// Common data drive (Windows, alt format)
|
|
16832
16851
|
];
|
|
16833
16852
|
var SUSPICIOUS_PATH_CHARS = /[<>:|"]/;
|
|
16834
|
-
function validatePathParameter(
|
|
16835
|
-
if (!
|
|
16853
|
+
function validatePathParameter(path6, paramName, projectRoot = process.cwd()) {
|
|
16854
|
+
if (!path6 || path6.trim() === "") {
|
|
16836
16855
|
throw new ValidationError(
|
|
16837
16856
|
`Invalid ${paramName}: path cannot be empty`,
|
|
16838
16857
|
-32602 /* InvalidParams */,
|
|
16839
|
-
{ path:
|
|
16858
|
+
{ path: path6, paramName }
|
|
16840
16859
|
);
|
|
16841
16860
|
}
|
|
16842
16861
|
for (const pattern of DANGEROUS_PATH_PATTERNS) {
|
|
16843
|
-
if (
|
|
16862
|
+
if (path6.includes(pattern)) {
|
|
16844
16863
|
throw new ValidationError(
|
|
16845
16864
|
`Invalid ${paramName}: path contains dangerous pattern "${pattern}"`,
|
|
16846
16865
|
-32602 /* InvalidParams */,
|
|
16847
|
-
{ path:
|
|
16866
|
+
{ path: path6, paramName, pattern }
|
|
16848
16867
|
);
|
|
16849
16868
|
}
|
|
16850
16869
|
}
|
|
16851
|
-
if (isAbsolute(
|
|
16870
|
+
if (isAbsolute(path6)) {
|
|
16852
16871
|
throw new ValidationError(
|
|
16853
16872
|
`Invalid ${paramName}: absolute paths are not allowed`,
|
|
16854
16873
|
-32602 /* InvalidParams */,
|
|
16855
|
-
{ path:
|
|
16874
|
+
{ path: path6, paramName }
|
|
16856
16875
|
);
|
|
16857
16876
|
}
|
|
16858
16877
|
try {
|
|
16859
|
-
const resolvedPath = resolve(projectRoot,
|
|
16878
|
+
const resolvedPath = resolve(projectRoot, path6);
|
|
16860
16879
|
const normalizedRoot = resolve(projectRoot);
|
|
16861
16880
|
if (!resolvedPath.startsWith(normalizedRoot + sep) && resolvedPath !== normalizedRoot) {
|
|
16862
16881
|
throw new ValidationError(
|
|
16863
16882
|
`Invalid ${paramName}: path escapes project boundary`,
|
|
16864
16883
|
-32602 /* InvalidParams */,
|
|
16865
|
-
{ path:
|
|
16884
|
+
{ path: path6, paramName, projectRoot, resolvedPath }
|
|
16866
16885
|
);
|
|
16867
16886
|
}
|
|
16868
16887
|
} catch (error) {
|
|
16869
16888
|
throw new ValidationError(
|
|
16870
16889
|
`Invalid ${paramName}: path resolution failed`,
|
|
16871
16890
|
-32602 /* InvalidParams */,
|
|
16872
|
-
{ path:
|
|
16891
|
+
{ path: path6, paramName, error: String(error) }
|
|
16873
16892
|
);
|
|
16874
16893
|
}
|
|
16875
|
-
if (
|
|
16894
|
+
if (path6.includes("\0")) {
|
|
16876
16895
|
throw new ValidationError(
|
|
16877
16896
|
`Invalid ${paramName}: path contains null byte`,
|
|
16878
16897
|
-32602 /* InvalidParams */,
|
|
16879
|
-
{ path:
|
|
16898
|
+
{ path: path6, paramName }
|
|
16880
16899
|
);
|
|
16881
16900
|
}
|
|
16882
|
-
if (SUSPICIOUS_PATH_CHARS.test(
|
|
16901
|
+
if (SUSPICIOUS_PATH_CHARS.test(path6)) {
|
|
16883
16902
|
throw new ValidationError(
|
|
16884
16903
|
`Invalid ${paramName}: path contains invalid characters`,
|
|
16885
16904
|
-32602 /* InvalidParams */,
|
|
16886
|
-
{ path:
|
|
16905
|
+
{ path: path6, paramName }
|
|
16887
16906
|
);
|
|
16888
16907
|
}
|
|
16889
16908
|
}
|
|
@@ -17579,8 +17598,8 @@ function createMemoryExportHandler(deps) {
|
|
|
17579
17598
|
return async (input) => {
|
|
17580
17599
|
logger.info("[MCP] memory_export called", { input });
|
|
17581
17600
|
try {
|
|
17582
|
-
const { path:
|
|
17583
|
-
const absolutePath = resolveExportPath(deps.pathResolver,
|
|
17601
|
+
const { path: path6 } = input;
|
|
17602
|
+
const absolutePath = resolveExportPath(deps.pathResolver, path6);
|
|
17584
17603
|
const exported = await deps.memoryManager.exportToJSON(absolutePath);
|
|
17585
17604
|
const result = {
|
|
17586
17605
|
success: true,
|
|
@@ -17616,8 +17635,8 @@ function createMemoryImportHandler(deps) {
|
|
|
17616
17635
|
return async (input) => {
|
|
17617
17636
|
logger.info("[MCP] memory_import called", { input });
|
|
17618
17637
|
try {
|
|
17619
|
-
const { path:
|
|
17620
|
-
const absolutePath = resolveImportPath(deps.pathResolver,
|
|
17638
|
+
const { path: path6 } = input;
|
|
17639
|
+
const absolutePath = resolveImportPath(deps.pathResolver, path6);
|
|
17621
17640
|
const imported = await deps.memoryManager.importFromJSON(absolutePath);
|
|
17622
17641
|
const result = {
|
|
17623
17642
|
success: true,
|
|
@@ -18192,7 +18211,18 @@ var McpClient = class extends EventEmitter {
|
|
|
18192
18211
|
timeout: timeoutHandle
|
|
18193
18212
|
});
|
|
18194
18213
|
const message = JSON.stringify(request) + "\n";
|
|
18195
|
-
|
|
18214
|
+
try {
|
|
18215
|
+
this.process.stdin.write(message);
|
|
18216
|
+
} catch (error) {
|
|
18217
|
+
const pending = this.pendingRequests.get(id);
|
|
18218
|
+
if (pending) {
|
|
18219
|
+
clearTimeout(pending.timeout);
|
|
18220
|
+
this.pendingRequests.delete(id);
|
|
18221
|
+
}
|
|
18222
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
18223
|
+
reject(err);
|
|
18224
|
+
return;
|
|
18225
|
+
}
|
|
18196
18226
|
logger.debug("[MCP Client] Sent request", {
|
|
18197
18227
|
id,
|
|
18198
18228
|
method,
|