deepcode-ai 1.1.2 → 1.1.3
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/dist/index.js +270 -137
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1657,6 +1657,8 @@ import { Command as Command2 } from "commander";
|
|
|
1657
1657
|
|
|
1658
1658
|
// ../../packages/core/dist/index.js
|
|
1659
1659
|
import { Effect } from "effect";
|
|
1660
|
+
import { lstat, readdir } from "fs/promises";
|
|
1661
|
+
import path2 from "path";
|
|
1660
1662
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
1661
1663
|
|
|
1662
1664
|
// ../../packages/shared/dist/index.js
|
|
@@ -2227,20 +2229,20 @@ var SessionTelemetrySchema = z.object({
|
|
|
2227
2229
|
|
|
2228
2230
|
// ../../packages/core/dist/index.js
|
|
2229
2231
|
import { z as z2 } from "zod";
|
|
2230
|
-
import { spawn } from "child_process";
|
|
2232
|
+
import { execFile, spawn } from "child_process";
|
|
2233
|
+
import { spawn as spawn2 } from "child_process";
|
|
2231
2234
|
import { createInterface } from "readline";
|
|
2232
2235
|
import { Effect as Effect3 } from "effect";
|
|
2233
2236
|
import { z as z22 } from "zod";
|
|
2234
2237
|
import { Effect as Effect2 } from "effect";
|
|
2235
2238
|
import { createHash } from "crypto";
|
|
2236
2239
|
import { mkdir as mkdir2, readFile, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
2237
|
-
import
|
|
2240
|
+
import path22 from "path";
|
|
2238
2241
|
import { mkdir as mkdir22, readFile as readFile2 } from "fs/promises";
|
|
2239
2242
|
import os from "os";
|
|
2240
|
-
import
|
|
2243
|
+
import path3 from "path";
|
|
2241
2244
|
import { EventEmitter } from "events";
|
|
2242
2245
|
import { z as z3 } from "zod";
|
|
2243
|
-
import { execFile, spawn as spawn2 } from "child_process";
|
|
2244
2246
|
import { spawn as spawn3 } from "child_process";
|
|
2245
2247
|
import { URL as URL2 } from "url";
|
|
2246
2248
|
import { URLSearchParams } from "url";
|
|
@@ -2248,27 +2250,27 @@ import { execFile as execFile2 } from "child_process";
|
|
|
2248
2250
|
import { z as z4 } from "zod";
|
|
2249
2251
|
import { spawn as spawn4 } from "child_process";
|
|
2250
2252
|
import { existsSync } from "fs";
|
|
2251
|
-
import path3 from "path";
|
|
2252
|
-
import { mkdir as mkdir3, appendFile } from "fs/promises";
|
|
2253
2253
|
import path4 from "path";
|
|
2254
|
+
import { mkdir as mkdir3, appendFile } from "fs/promises";
|
|
2255
|
+
import path5 from "path";
|
|
2254
2256
|
import os2 from "os";
|
|
2255
2257
|
import { access, realpath } from "fs/promises";
|
|
2256
|
-
import path5 from "path";
|
|
2257
|
-
import os3 from "os";
|
|
2258
2258
|
import path6 from "path";
|
|
2259
|
-
import
|
|
2259
|
+
import os3 from "os";
|
|
2260
2260
|
import path7 from "path";
|
|
2261
|
+
import { mkdir as mkdir4, readFile as readFile3, readdir as readdir2 } from "fs/promises";
|
|
2262
|
+
import path8 from "path";
|
|
2261
2263
|
import { readFile as readFile5 } from "fs/promises";
|
|
2262
|
-
import
|
|
2264
|
+
import path10 from "path";
|
|
2263
2265
|
import { Effect as Effect4 } from "effect";
|
|
2264
2266
|
import { z as z5 } from "zod";
|
|
2265
|
-
import { mkdir as mkdir6, readFile as readFile6, readdir as
|
|
2266
|
-
import
|
|
2267
|
+
import { lstat as lstat2, mkdir as mkdir6, readFile as readFile6, readdir as readdir4, stat, writeFile as writeFile22 } from "fs/promises";
|
|
2268
|
+
import path11 from "path";
|
|
2267
2269
|
import { Effect as Effect5 } from "effect";
|
|
2268
2270
|
import { z as z6 } from "zod";
|
|
2269
2271
|
import { Effect as Effect6 } from "effect";
|
|
2270
2272
|
import { z as z7 } from "zod";
|
|
2271
|
-
import
|
|
2273
|
+
import path12 from "path";
|
|
2272
2274
|
import { Effect as Effect7 } from "effect";
|
|
2273
2275
|
import { z as z8 } from "zod";
|
|
2274
2276
|
import { Effect as Effect8 } from "effect";
|
|
@@ -2298,8 +2300,8 @@ var PermissionDeniedError = class extends DeepCodeError {
|
|
|
2298
2300
|
}
|
|
2299
2301
|
};
|
|
2300
2302
|
var PathNotAllowedError = class extends DeepCodeError {
|
|
2301
|
-
constructor(
|
|
2302
|
-
super(`Path is not allowed: ${
|
|
2303
|
+
constructor(path13, reason) {
|
|
2304
|
+
super(`Path is not allowed: ${path13}. ${reason}`, "PATH_NOT_ALLOWED");
|
|
2303
2305
|
this.name = "PathNotAllowedError";
|
|
2304
2306
|
}
|
|
2305
2307
|
};
|
|
@@ -2525,8 +2527,15 @@ var PlannedTaskSchema = z2.object({
|
|
|
2525
2527
|
dependencies: z2.array(z2.string()).default([])
|
|
2526
2528
|
});
|
|
2527
2529
|
var PlannedTaskArraySchema = z2.array(PlannedTaskSchema).min(1, "At least one task is required.");
|
|
2530
|
+
var READ_ONLY_DISCOVERY_VERB_PATTERN = /\b(?:list|show|find|search|inspect|check|track|listar|mostre|mostrar|busque|buscar|procure|procurar|inspecione|verifique|rastrear|rastreie)\b/i;
|
|
2531
|
+
var READ_ONLY_DISCOVERY_NOUN_PATTERN = /\b(?:project|projects|repo|repos|repository|repositories|directory|directories|folder|folders|workspace|projeto|projetos|repositorio|repositorios|diretorio|diretorios|pasta|pastas)\b/i;
|
|
2532
|
+
var READ_ONLY_MUTATION_PATTERN = /\b(?:git\s+init|git\s+add|git\s+commit|git\s+push|git\s+tag|git\s+stash|initialize\s+(?:a\s+)?git\s+repository|initialise\s+(?:a\s+)?git\s+repository|create\s+(?:a\s+)?\.?gitignore|stage\s+all\s+files|commit\s+all\s+files)\b/i;
|
|
2533
|
+
function isReadOnlyDiscoveryObjective(objective) {
|
|
2534
|
+
return READ_ONLY_DISCOVERY_VERB_PATTERN.test(objective) && READ_ONLY_DISCOVERY_NOUN_PATTERN.test(objective);
|
|
2535
|
+
}
|
|
2528
2536
|
var TaskPlanner = class {
|
|
2529
2537
|
async plan(objective, complete) {
|
|
2538
|
+
const readOnlyDiscoveryObjective = isReadOnlyDiscoveryObjective(objective);
|
|
2530
2539
|
const raw = await complete(`Create an execution plan for this coding task.
|
|
2531
2540
|
Return only JSON in this shape:
|
|
2532
2541
|
[
|
|
@@ -2539,6 +2548,9 @@ Requirements:
|
|
|
2539
2548
|
- Type must be one of: research, code, test, verify
|
|
2540
2549
|
- Dependencies must reference existing task IDs
|
|
2541
2550
|
- Tasks should be ordered logically
|
|
2551
|
+
${readOnlyDiscoveryObjective ? `- This is a read-only discovery request; prefer the fewest inspection steps needed
|
|
2552
|
+
- Do not propose initializing git repositories, creating .gitignore, staging files, committing, or pushing
|
|
2553
|
+
- Do not propose filesystem mutations for this request` : ""}
|
|
2542
2554
|
|
|
2543
2555
|
Task:
|
|
2544
2556
|
${objective}`);
|
|
@@ -2555,6 +2567,9 @@ Task:
|
|
|
2555
2567
|
throw new Error(`Task "${task.id}" has unknown dependency: "${dep}"`);
|
|
2556
2568
|
}
|
|
2557
2569
|
}
|
|
2570
|
+
if (readOnlyDiscoveryObjective && READ_ONLY_MUTATION_PATTERN.test(task.description)) {
|
|
2571
|
+
throw new Error(`Unsafe mutating task in read-only plan: "${task.description}"`);
|
|
2572
|
+
}
|
|
2558
2573
|
}
|
|
2559
2574
|
return {
|
|
2560
2575
|
objective,
|
|
@@ -3008,9 +3023,70 @@ function firstObjectField(payload, keys) {
|
|
|
3008
3023
|
function collapseFallbackWhitespace(input) {
|
|
3009
3024
|
return input.replace(/\n{3,}/g, "\n\n").trim();
|
|
3010
3025
|
}
|
|
3026
|
+
function execFileAsync(command, args, options) {
|
|
3027
|
+
return new Promise((resolve3, reject) => {
|
|
3028
|
+
execFile(
|
|
3029
|
+
command,
|
|
3030
|
+
args,
|
|
3031
|
+
{
|
|
3032
|
+
cwd: options.cwd,
|
|
3033
|
+
timeout: options.timeoutMs,
|
|
3034
|
+
signal: options.signal,
|
|
3035
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
3036
|
+
env: { ...process.env, FORCE_COLOR: "1" }
|
|
3037
|
+
},
|
|
3038
|
+
(error, stdout, stderr) => {
|
|
3039
|
+
if (error) {
|
|
3040
|
+
const err = error;
|
|
3041
|
+
if (typeof err.code === "number") {
|
|
3042
|
+
resolve3({ stdout, stderr, exitCode: err.code });
|
|
3043
|
+
return;
|
|
3044
|
+
}
|
|
3045
|
+
reject(error);
|
|
3046
|
+
return;
|
|
3047
|
+
}
|
|
3048
|
+
resolve3({ stdout, stderr, exitCode: 0 });
|
|
3049
|
+
}
|
|
3050
|
+
);
|
|
3051
|
+
});
|
|
3052
|
+
}
|
|
3053
|
+
function runShell(command, options) {
|
|
3054
|
+
return new Promise((resolve3, reject) => {
|
|
3055
|
+
const child = spawn(command, {
|
|
3056
|
+
cwd: options.cwd,
|
|
3057
|
+
shell: true,
|
|
3058
|
+
env: { ...process.env, FORCE_COLOR: "1" },
|
|
3059
|
+
signal: options.signal
|
|
3060
|
+
});
|
|
3061
|
+
let stdout = "";
|
|
3062
|
+
let stderr = "";
|
|
3063
|
+
let timedOut = false;
|
|
3064
|
+
const timer = setTimeout(() => {
|
|
3065
|
+
timedOut = true;
|
|
3066
|
+
child.kill("SIGTERM");
|
|
3067
|
+
setTimeout(() => child.kill("SIGKILL"), 1500).unref();
|
|
3068
|
+
}, options.timeoutMs);
|
|
3069
|
+
child.stdout?.on("data", (chunk) => {
|
|
3070
|
+
stdout += String(chunk);
|
|
3071
|
+
});
|
|
3072
|
+
child.stderr?.on("data", (chunk) => {
|
|
3073
|
+
stderr += String(chunk);
|
|
3074
|
+
});
|
|
3075
|
+
child.on("error", (error) => {
|
|
3076
|
+
clearTimeout(timer);
|
|
3077
|
+
reject(error);
|
|
3078
|
+
});
|
|
3079
|
+
child.on("close", (exitCode) => {
|
|
3080
|
+
clearTimeout(timer);
|
|
3081
|
+
resolve3({ stdout, stderr, exitCode, timedOut });
|
|
3082
|
+
});
|
|
3083
|
+
});
|
|
3084
|
+
}
|
|
3011
3085
|
var DIRECT_SHELL_COMMAND_PATTERN = /^(?:ls|dir|pwd|date|tree|find|rg|grep|cat|stat|wc)\b/i;
|
|
3012
3086
|
var DIRECT_UTILITY_PATH_PATTERN = /(?:^|\s)(?:~\/|\.{1,2}\/|\/)[^\s]*/;
|
|
3013
3087
|
var DIRECT_UTILITY_VERB_PATTERN = /\b(?:list|lista|liste|listar|mostre|mostrar|show|display|open|abrir|abra|read|leia|print|imprima|exiba)\b/i;
|
|
3088
|
+
var PROJECT_DISCOVERY_VERB_PATTERN = /\b(?:list|lista|liste|listar|show|mostre|mostrar|find|busque|buscar|procure|procurar|track|rastreie|rastrear|scan|escanear|discover|descubra)\b/i;
|
|
3089
|
+
var PROJECT_DISCOVERY_NOUN_PATTERN = /\b(?:project|projects|repo|repos|repository|repositories|repositorio|repositorios|projeto|projetos)\b/i;
|
|
3014
3090
|
var DATE_TIME_QUESTION_PATTERN = /\b(?:que dia e hoje|que dia é hoje|data de hoje|dia de hoje|what day is it|what day is today|today'?s date|current date|que horas sao|que horas são|hora atual|current time|what time is it)\b/i;
|
|
3015
3091
|
var SIMPLE_SHELL_COMMAND_PATTERN = /^(?:mkdir|touch|rmdir|cp|mv|chmod|chown|echo|ln|git\s+(?:init|clone|add|commit|push|pull|checkout|branch|stash|tag))\b/i;
|
|
3016
3092
|
var SIMPLE_ACTION_VERB_RE = /^(?:cria|crie|criar|apaga|apague|apagar|deleta|delete|deletar|remove|mova|move|renomeia|renomeie|renomear|create|rename|mkdir|make)\b/;
|
|
@@ -3127,6 +3203,11 @@ function parseUtilityRequest(input) {
|
|
|
3127
3203
|
if (normalizedInput === "date" || DATE_TIME_QUESTION_PATTERN.test(normalizedInput)) {
|
|
3128
3204
|
return { kind: "date" };
|
|
3129
3205
|
}
|
|
3206
|
+
if (PROJECT_DISCOVERY_NOUN_PATTERN.test(normalizedInput) && (PROJECT_DISCOVERY_VERB_PATTERN.test(normalizedInput) || /\bgit\b/i.test(normalizedInput))) {
|
|
3207
|
+
const explicitPathMatch = trimmed.match(/((?:~\/|\.{1,2}\/|\/)[^\s]+)/);
|
|
3208
|
+
const rawPath = explicitPathMatch?.[1]?.trim() || ".";
|
|
3209
|
+
return { kind: "list_projects", path: rawPath, rawPath };
|
|
3210
|
+
}
|
|
3130
3211
|
const shellListMatch = trimmed.match(/^(?:ls|dir)\s*(.+)?$/i);
|
|
3131
3212
|
if (shellListMatch) {
|
|
3132
3213
|
const rawPath = shellListMatch[1]?.trim() || ".";
|
|
@@ -3198,7 +3279,9 @@ function utilityDateResponse() {
|
|
|
3198
3279
|
}
|
|
3199
3280
|
function formatUtilityResult(request, result) {
|
|
3200
3281
|
if (!result.trim()) {
|
|
3201
|
-
|
|
3282
|
+
if (request.kind === "list_dir") return "Diret\xF3rio vazio.";
|
|
3283
|
+
if (request.kind === "list_projects") return "Nenhum projeto encontrado. Quer versionar alguma pasta?";
|
|
3284
|
+
return "Sem sa\xEDda.";
|
|
3202
3285
|
}
|
|
3203
3286
|
if (!result.startsWith("Error running ")) {
|
|
3204
3287
|
return result;
|
|
@@ -3254,6 +3337,9 @@ function isDirectUtilityRequest(input, policy) {
|
|
|
3254
3337
|
if (DIRECT_UTILITY_PATH_PATTERN.test(input) && DIRECT_UTILITY_VERB_PATTERN.test(normalizedInput)) {
|
|
3255
3338
|
return true;
|
|
3256
3339
|
}
|
|
3340
|
+
if (PROJECT_DISCOVERY_NOUN_PATTERN.test(normalizedInput) && (PROJECT_DISCOVERY_VERB_PATTERN.test(normalizedInput) || /\bgit\b/i.test(normalizedInput))) {
|
|
3341
|
+
return true;
|
|
3342
|
+
}
|
|
3257
3343
|
return DIRECT_UTILITY_VERB_PATTERN.test(normalizedInput) && (normalizedInput.includes(" directory") || normalizedInput.includes(" folder") || normalizedInput.includes(" pasta") || normalizedInput.includes(" diretorio") || normalizedInput.includes(" documents") || normalizedInput.includes(" documentos") || containsConfiguredTerm(normalizedInput, policy.fileExtensions));
|
|
3258
3344
|
}
|
|
3259
3345
|
function containsConfiguredTerm(normalizedInput, terms) {
|
|
@@ -3310,6 +3396,22 @@ function resolveExecutionTarget(config, session, mode, explicitProvider) {
|
|
|
3310
3396
|
}
|
|
3311
3397
|
return fallback;
|
|
3312
3398
|
}
|
|
3399
|
+
var PROJECT_MARKER = ".git";
|
|
3400
|
+
var PROJECT_DISCOVERY_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
3401
|
+
".git",
|
|
3402
|
+
".hg",
|
|
3403
|
+
".svn",
|
|
3404
|
+
"node_modules",
|
|
3405
|
+
"dist",
|
|
3406
|
+
"build",
|
|
3407
|
+
"coverage",
|
|
3408
|
+
".next",
|
|
3409
|
+
".turbo",
|
|
3410
|
+
".cache",
|
|
3411
|
+
"target",
|
|
3412
|
+
"__pycache__",
|
|
3413
|
+
"vendor"
|
|
3414
|
+
]);
|
|
3313
3415
|
var Agent = class {
|
|
3314
3416
|
constructor(providerManager, tools, sessions, config, cache, permissions, pathSecurity, eventBus) {
|
|
3315
3417
|
this.providerManager = providerManager;
|
|
@@ -4013,6 +4115,26 @@ ${assistantText}` : assistantText;
|
|
|
4013
4115
|
});
|
|
4014
4116
|
return output2;
|
|
4015
4117
|
}
|
|
4118
|
+
if (request.kind === "list_projects") {
|
|
4119
|
+
try {
|
|
4120
|
+
const output2 = await this.discoverProjects(session, request.path ?? ".");
|
|
4121
|
+
this.sessions.addMessage(session.id, {
|
|
4122
|
+
role: "assistant",
|
|
4123
|
+
source: "assistant",
|
|
4124
|
+
content: formatUtilityResult(request, output2)
|
|
4125
|
+
});
|
|
4126
|
+
return formatUtilityResult(request, output2);
|
|
4127
|
+
} catch (error) {
|
|
4128
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4129
|
+
const output2 = `Nao consegui localizar projetos em ${request.rawPath ?? request.path ?? "."}: ${message}`;
|
|
4130
|
+
this.sessions.addMessage(session.id, {
|
|
4131
|
+
role: "assistant",
|
|
4132
|
+
source: "assistant",
|
|
4133
|
+
content: output2
|
|
4134
|
+
});
|
|
4135
|
+
return output2;
|
|
4136
|
+
}
|
|
4137
|
+
}
|
|
4016
4138
|
const call = {
|
|
4017
4139
|
id: createId("toolcall"),
|
|
4018
4140
|
name: "list_dir",
|
|
@@ -4039,6 +4161,71 @@ ${assistantText}` : assistantText;
|
|
|
4039
4161
|
});
|
|
4040
4162
|
return output;
|
|
4041
4163
|
}
|
|
4164
|
+
async discoverProjects(session, inputPath) {
|
|
4165
|
+
if (!await this.isGitAvailable(session.worktree)) {
|
|
4166
|
+
return "Git nao esta instalado. Quer que eu instale?";
|
|
4167
|
+
}
|
|
4168
|
+
const rootPath = await this.pathSecurity.normalize(inputPath, { enforceAccess: false });
|
|
4169
|
+
await this.permissions.ensure({ operation: "list_projects", kind: "read", path: rootPath });
|
|
4170
|
+
const results = [];
|
|
4171
|
+
await this.walkForProjects(rootPath, 3, results, /* @__PURE__ */ new Set());
|
|
4172
|
+
if (results.length === 0) {
|
|
4173
|
+
return "";
|
|
4174
|
+
}
|
|
4175
|
+
const formatted = results.sort((left, right) => left.path.localeCompare(right.path)).map((match) => {
|
|
4176
|
+
const relative2 = path2.relative(rootPath, match.path) || ".";
|
|
4177
|
+
return `${relative2} [${match.markers.join(", ")}]`;
|
|
4178
|
+
});
|
|
4179
|
+
return formatted.join("\n");
|
|
4180
|
+
}
|
|
4181
|
+
async walkForProjects(directory, depthRemaining, results, seen) {
|
|
4182
|
+
if (seen.has(directory) || results.length >= 200) {
|
|
4183
|
+
return;
|
|
4184
|
+
}
|
|
4185
|
+
seen.add(directory);
|
|
4186
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
4187
|
+
const markerSet = new Set(
|
|
4188
|
+
entries.filter((entry) => entry.name === PROJECT_MARKER).map((entry) => entry.name)
|
|
4189
|
+
);
|
|
4190
|
+
if (markerSet.size > 0) {
|
|
4191
|
+
results.push({
|
|
4192
|
+
path: directory,
|
|
4193
|
+
markers: Array.from(markerSet).sort()
|
|
4194
|
+
});
|
|
4195
|
+
}
|
|
4196
|
+
if (depthRemaining <= 0) {
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4199
|
+
for (const entry of entries) {
|
|
4200
|
+
if (!entry.isDirectory()) {
|
|
4201
|
+
continue;
|
|
4202
|
+
}
|
|
4203
|
+
if (PROJECT_DISCOVERY_SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) {
|
|
4204
|
+
continue;
|
|
4205
|
+
}
|
|
4206
|
+
const fullPath = path2.join(directory, entry.name);
|
|
4207
|
+
try {
|
|
4208
|
+
const info = await lstat(fullPath);
|
|
4209
|
+
if (info.isSymbolicLink()) {
|
|
4210
|
+
continue;
|
|
4211
|
+
}
|
|
4212
|
+
await this.walkForProjects(fullPath, depthRemaining - 1, results, seen);
|
|
4213
|
+
} catch {
|
|
4214
|
+
continue;
|
|
4215
|
+
}
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
async isGitAvailable(cwd) {
|
|
4219
|
+
try {
|
|
4220
|
+
const result = await execFileAsync("git", ["--version"], {
|
|
4221
|
+
cwd,
|
|
4222
|
+
timeoutMs: 5e3
|
|
4223
|
+
});
|
|
4224
|
+
return result.exitCode === 0;
|
|
4225
|
+
} catch {
|
|
4226
|
+
return false;
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4042
4229
|
resolveTurnStrategy(input, mode) {
|
|
4043
4230
|
return resolveTurnStrategy(input, mode, this.config.buildTurnPolicy);
|
|
4044
4231
|
}
|
|
@@ -4080,7 +4267,7 @@ var McpClient = class {
|
|
|
4080
4267
|
ready;
|
|
4081
4268
|
nextId = 1;
|
|
4082
4269
|
pending = /* @__PURE__ */ new Map();
|
|
4083
|
-
constructor(command, args, env, spawnProcess =
|
|
4270
|
+
constructor(command, args, env, spawnProcess = spawn2) {
|
|
4084
4271
|
this.process = spawnProcess(command, args, {
|
|
4085
4272
|
stdio: ["pipe", "pipe", "pipe"],
|
|
4086
4273
|
env: { ...process.env, ...env }
|
|
@@ -4325,7 +4512,7 @@ var ToolCache = class {
|
|
|
4325
4512
|
async set(namespace, keyParts, value) {
|
|
4326
4513
|
if (!this.config.cache.enabled) return;
|
|
4327
4514
|
const key = cacheKey(namespace, keyParts);
|
|
4328
|
-
const dir =
|
|
4515
|
+
const dir = path22.join(this.worktree, ".deepcode", "cache");
|
|
4329
4516
|
await mkdir2(dir, { recursive: true });
|
|
4330
4517
|
const now = Date.now();
|
|
4331
4518
|
const entry = {
|
|
@@ -4338,10 +4525,10 @@ var ToolCache = class {
|
|
|
4338
4525
|
`, "utf8");
|
|
4339
4526
|
}
|
|
4340
4527
|
async clear() {
|
|
4341
|
-
await rm2(
|
|
4528
|
+
await rm2(path22.join(this.worktree, ".deepcode", "cache"), { recursive: true, force: true });
|
|
4342
4529
|
}
|
|
4343
4530
|
filePath(key) {
|
|
4344
|
-
return
|
|
4531
|
+
return path22.join(this.worktree, ".deepcode", "cache", `${key}.json`);
|
|
4345
4532
|
}
|
|
4346
4533
|
};
|
|
4347
4534
|
function cacheKey(namespace, keyParts) {
|
|
@@ -4349,12 +4536,12 @@ function cacheKey(namespace, keyParts) {
|
|
|
4349
4536
|
}
|
|
4350
4537
|
var ConfigLoader = class {
|
|
4351
4538
|
resolveConfigPath(options) {
|
|
4352
|
-
return options.configPath ?
|
|
4539
|
+
return options.configPath ? path3.resolve(options.configPath) : path3.join(options.cwd, ".deepcode", "config.json");
|
|
4353
4540
|
}
|
|
4354
4541
|
async load(options) {
|
|
4355
4542
|
const configPath = this.resolveConfigPath(options);
|
|
4356
4543
|
const rawFile = await this.readOptionalJson(configPath);
|
|
4357
|
-
const cwd =
|
|
4544
|
+
const cwd = path3.dirname(configPath) === path3.join(path3.resolve(options.cwd), ".deepcode") ? path3.resolve(options.cwd) : path3.dirname(configPath);
|
|
4358
4545
|
const openrouterApiKeyFile = parseOptionalString(process.env.OPENROUTER_API_KEY_FILE) ?? rawFile.providers?.openrouter?.apiKeyFile;
|
|
4359
4546
|
const anthropicApiKeyFile = parseOptionalString(process.env.ANTHROPIC_API_KEY_FILE) ?? rawFile.providers?.anthropic?.apiKeyFile;
|
|
4360
4547
|
const openaiApiKeyFile = parseOptionalString(process.env.OPENAI_API_KEY_FILE) ?? rawFile.providers?.openai?.apiKeyFile;
|
|
@@ -4436,14 +4623,14 @@ var ConfigLoader = class {
|
|
|
4436
4623
|
if (!parsed.success) {
|
|
4437
4624
|
throw new ConfigError(`Invalid DeepCode config: ${parsed.error.message}`, parsed.error);
|
|
4438
4625
|
}
|
|
4439
|
-
await mkdir22(
|
|
4626
|
+
await mkdir22(path3.dirname(configPath), { recursive: true });
|
|
4440
4627
|
await writeFileAtomic(configPath, `${JSON.stringify(parsed.data, null, 2)}
|
|
4441
4628
|
`);
|
|
4442
4629
|
return configPath;
|
|
4443
4630
|
}
|
|
4444
4631
|
async init(cwd) {
|
|
4445
|
-
const dir =
|
|
4446
|
-
const configPath =
|
|
4632
|
+
const dir = path3.join(cwd, ".deepcode");
|
|
4633
|
+
const configPath = path3.join(dir, "config.json");
|
|
4447
4634
|
await mkdir22(dir, { recursive: true });
|
|
4448
4635
|
const config = DeepCodeConfigSchema.parse({});
|
|
4449
4636
|
await writeFileAtomic(configPath, `${JSON.stringify(config, null, 2)}
|
|
@@ -4495,7 +4682,7 @@ function normalizeLabel(value) {
|
|
|
4495
4682
|
function resolveUserPath(filePath, cwd) {
|
|
4496
4683
|
if (!filePath) return void 0;
|
|
4497
4684
|
const expanded = filePath === "~" ? os.homedir() : filePath.replace(/^~(?=\/|\\)/, os.homedir());
|
|
4498
|
-
return
|
|
4685
|
+
return path3.isAbsolute(expanded) ? expanded : path3.resolve(cwd, expanded);
|
|
4499
4686
|
}
|
|
4500
4687
|
function parseOptionalBoolean(value) {
|
|
4501
4688
|
if (value === void 0) return void 0;
|
|
@@ -4548,65 +4735,6 @@ var EventBus = class {
|
|
|
4548
4735
|
}
|
|
4549
4736
|
}
|
|
4550
4737
|
};
|
|
4551
|
-
function execFileAsync(command, args, options) {
|
|
4552
|
-
return new Promise((resolve3, reject) => {
|
|
4553
|
-
execFile(
|
|
4554
|
-
command,
|
|
4555
|
-
args,
|
|
4556
|
-
{
|
|
4557
|
-
cwd: options.cwd,
|
|
4558
|
-
timeout: options.timeoutMs,
|
|
4559
|
-
signal: options.signal,
|
|
4560
|
-
maxBuffer: 20 * 1024 * 1024,
|
|
4561
|
-
env: { ...process.env, FORCE_COLOR: "1" }
|
|
4562
|
-
},
|
|
4563
|
-
(error, stdout, stderr) => {
|
|
4564
|
-
if (error) {
|
|
4565
|
-
const err = error;
|
|
4566
|
-
if (typeof err.code === "number") {
|
|
4567
|
-
resolve3({ stdout, stderr, exitCode: err.code });
|
|
4568
|
-
return;
|
|
4569
|
-
}
|
|
4570
|
-
reject(error);
|
|
4571
|
-
return;
|
|
4572
|
-
}
|
|
4573
|
-
resolve3({ stdout, stderr, exitCode: 0 });
|
|
4574
|
-
}
|
|
4575
|
-
);
|
|
4576
|
-
});
|
|
4577
|
-
}
|
|
4578
|
-
function runShell(command, options) {
|
|
4579
|
-
return new Promise((resolve3, reject) => {
|
|
4580
|
-
const child = spawn2(command, {
|
|
4581
|
-
cwd: options.cwd,
|
|
4582
|
-
shell: true,
|
|
4583
|
-
env: { ...process.env, FORCE_COLOR: "1" },
|
|
4584
|
-
signal: options.signal
|
|
4585
|
-
});
|
|
4586
|
-
let stdout = "";
|
|
4587
|
-
let stderr = "";
|
|
4588
|
-
let timedOut = false;
|
|
4589
|
-
const timer = setTimeout(() => {
|
|
4590
|
-
timedOut = true;
|
|
4591
|
-
child.kill("SIGTERM");
|
|
4592
|
-
setTimeout(() => child.kill("SIGKILL"), 1500).unref();
|
|
4593
|
-
}, options.timeoutMs);
|
|
4594
|
-
child.stdout?.on("data", (chunk) => {
|
|
4595
|
-
stdout += String(chunk);
|
|
4596
|
-
});
|
|
4597
|
-
child.stderr?.on("data", (chunk) => {
|
|
4598
|
-
stderr += String(chunk);
|
|
4599
|
-
});
|
|
4600
|
-
child.on("error", (error) => {
|
|
4601
|
-
clearTimeout(timer);
|
|
4602
|
-
reject(error);
|
|
4603
|
-
});
|
|
4604
|
-
child.on("close", (exitCode) => {
|
|
4605
|
-
clearTimeout(timer);
|
|
4606
|
-
resolve3({ stdout, stderr, exitCode, timedOut });
|
|
4607
|
-
});
|
|
4608
|
-
});
|
|
4609
|
-
}
|
|
4610
4738
|
var GitHubAuthenticatedUserSchema = z3.object({
|
|
4611
4739
|
login: z3.string(),
|
|
4612
4740
|
id: z3.number(),
|
|
@@ -4730,13 +4858,13 @@ var GitHubClient = class {
|
|
|
4730
4858
|
}
|
|
4731
4859
|
return parseGitHubRemote(result.stdout.trim());
|
|
4732
4860
|
}
|
|
4733
|
-
async request(
|
|
4861
|
+
async request(path13, init = {}) {
|
|
4734
4862
|
if (!this.options.token) {
|
|
4735
4863
|
throw new Error(
|
|
4736
4864
|
"GitHub token is required. Set GITHUB_TOKEN or .deepcode/config.json github.token."
|
|
4737
4865
|
);
|
|
4738
4866
|
}
|
|
4739
|
-
const response = await fetch(`${this.apiBase}${
|
|
4867
|
+
const response = await fetch(`${this.apiBase}${path13}`, {
|
|
4740
4868
|
...init,
|
|
4741
4869
|
headers: {
|
|
4742
4870
|
accept: "application/vnd.github+json",
|
|
@@ -4752,13 +4880,13 @@ var GitHubClient = class {
|
|
|
4752
4880
|
if (response.status === 204) return void 0;
|
|
4753
4881
|
return await response.json();
|
|
4754
4882
|
}
|
|
4755
|
-
async requestText(
|
|
4883
|
+
async requestText(path13, init = {}) {
|
|
4756
4884
|
if (!this.options.token) {
|
|
4757
4885
|
throw new Error(
|
|
4758
4886
|
"GitHub token is required. Set GITHUB_TOKEN or .deepcode/config.json github.token."
|
|
4759
4887
|
);
|
|
4760
4888
|
}
|
|
4761
|
-
const response = await fetch(`${this.apiBase}${
|
|
4889
|
+
const response = await fetch(`${this.apiBase}${path13}`, {
|
|
4762
4890
|
...init,
|
|
4763
4891
|
headers: {
|
|
4764
4892
|
accept: "application/vnd.github+json",
|
|
@@ -5099,7 +5227,7 @@ var LspClient = class {
|
|
|
5099
5227
|
await this.request("initialize", {
|
|
5100
5228
|
processId: process.pid,
|
|
5101
5229
|
rootUri: toFileUri(this.rootPath),
|
|
5102
|
-
workspaceFolders: [{ uri: toFileUri(this.rootPath), name:
|
|
5230
|
+
workspaceFolders: [{ uri: toFileUri(this.rootPath), name: path4.basename(this.rootPath) }],
|
|
5103
5231
|
capabilities: {
|
|
5104
5232
|
workspace: {
|
|
5105
5233
|
symbol: {
|
|
@@ -5201,7 +5329,7 @@ var LspClient = class {
|
|
|
5201
5329
|
}
|
|
5202
5330
|
};
|
|
5203
5331
|
function pickLanguageServer(servers, rootPath, queryPath) {
|
|
5204
|
-
const extension =
|
|
5332
|
+
const extension = path4.extname(queryPath);
|
|
5205
5333
|
const byExtension = servers.find((server) => server.fileExtensions.includes(extension));
|
|
5206
5334
|
if (byExtension) return byExtension;
|
|
5207
5335
|
const projectFiles = [
|
|
@@ -5211,14 +5339,14 @@ function pickLanguageServer(servers, rootPath, queryPath) {
|
|
|
5211
5339
|
["Cargo.toml", "rust"],
|
|
5212
5340
|
["go.mod", "go"]
|
|
5213
5341
|
];
|
|
5214
|
-
const detected = projectFiles.find(([file]) => pathExists(
|
|
5342
|
+
const detected = projectFiles.find(([file]) => pathExists(path4.join(rootPath, file)))?.[1];
|
|
5215
5343
|
return detected ? servers.find((server) => server.languages.includes(detected)) : servers[0];
|
|
5216
5344
|
}
|
|
5217
5345
|
function pathExists(filePath) {
|
|
5218
5346
|
return existsSync(filePath);
|
|
5219
5347
|
}
|
|
5220
5348
|
function toFileUri(filePath) {
|
|
5221
|
-
return `file://${
|
|
5349
|
+
return `file://${path4.resolve(filePath).replaceAll(path4.sep, "/")}`;
|
|
5222
5350
|
}
|
|
5223
5351
|
function fromFileUri(uri) {
|
|
5224
5352
|
return decodeURIComponent(uri.replace(/^file:\/\//, ""));
|
|
@@ -5226,12 +5354,12 @@ function fromFileUri(uri) {
|
|
|
5226
5354
|
var SECRET_KEY_PATTERN = /(api[_-]?key|token|authorization|secret|password|passwd|credential|private[_-]?key)/i;
|
|
5227
5355
|
var MIN_SECRET_VALUE_LENGTH = 4;
|
|
5228
5356
|
function redactSecrets(value, options = {}) {
|
|
5229
|
-
const
|
|
5357
|
+
const path13 = options.path ?? [];
|
|
5230
5358
|
const secretPlaceholder = options.secretPlaceholder ?? "[redacted]";
|
|
5231
5359
|
const emptySecretPlaceholder = options.emptySecretPlaceholder ?? "[empty]";
|
|
5232
5360
|
const secretValues = options.secretValues ?? collectSecretValues();
|
|
5233
5361
|
if (typeof value === "string") {
|
|
5234
|
-
if (isSecretPath(
|
|
5362
|
+
if (isSecretPath(path13)) {
|
|
5235
5363
|
return value.length > 0 ? secretPlaceholder : emptySecretPlaceholder;
|
|
5236
5364
|
}
|
|
5237
5365
|
return redactText(value, secretValues, secretPlaceholder);
|
|
@@ -5240,7 +5368,7 @@ function redactSecrets(value, options = {}) {
|
|
|
5240
5368
|
return value.map(
|
|
5241
5369
|
(item, index) => redactSecrets(item, {
|
|
5242
5370
|
...options,
|
|
5243
|
-
path: [...
|
|
5371
|
+
path: [...path13, String(index)],
|
|
5244
5372
|
secretValues
|
|
5245
5373
|
})
|
|
5246
5374
|
);
|
|
@@ -5251,7 +5379,7 @@ function redactSecrets(value, options = {}) {
|
|
|
5251
5379
|
key,
|
|
5252
5380
|
redactSecrets(item, {
|
|
5253
5381
|
...options,
|
|
5254
|
-
path: [...
|
|
5382
|
+
path: [...path13, key],
|
|
5255
5383
|
secretValues
|
|
5256
5384
|
})
|
|
5257
5385
|
])
|
|
@@ -5289,8 +5417,8 @@ function collectSecretValues(config) {
|
|
|
5289
5417
|
}
|
|
5290
5418
|
return [...values].sort((left, right) => right.length - left.length);
|
|
5291
5419
|
}
|
|
5292
|
-
function isSecretPath(
|
|
5293
|
-
const key =
|
|
5420
|
+
function isSecretPath(path13) {
|
|
5421
|
+
const key = path13[path13.length - 1] ?? "";
|
|
5294
5422
|
if (/(api[_-]?key|token|secret|credential).*file/i.test(key)) return false;
|
|
5295
5423
|
return SECRET_KEY_PATTERN.test(key);
|
|
5296
5424
|
}
|
|
@@ -6148,10 +6276,10 @@ var AuditLogger = class {
|
|
|
6148
6276
|
}
|
|
6149
6277
|
worktree;
|
|
6150
6278
|
async log(entry) {
|
|
6151
|
-
const dir =
|
|
6279
|
+
const dir = path5.join(this.worktree, ".deepcode");
|
|
6152
6280
|
await mkdir3(dir, { recursive: true });
|
|
6153
6281
|
const payload = redactSecrets({ ...entry, createdAt: entry.createdAt ?? nowIso() });
|
|
6154
|
-
await appendFile(
|
|
6282
|
+
await appendFile(path5.join(dir, "audit.log"), `${JSON.stringify(payload)}
|
|
6155
6283
|
`, "utf8");
|
|
6156
6284
|
}
|
|
6157
6285
|
};
|
|
@@ -6193,7 +6321,7 @@ var PathSecurity = class {
|
|
|
6193
6321
|
return resolved;
|
|
6194
6322
|
}
|
|
6195
6323
|
classify(targetPath) {
|
|
6196
|
-
const candidate =
|
|
6324
|
+
const candidate = path6.normalize(targetPath);
|
|
6197
6325
|
const blacklisted = this.rules.blacklist.some((rule) => globToRegex(rule).test(candidate));
|
|
6198
6326
|
if (blacklisted) {
|
|
6199
6327
|
return "blacklisted";
|
|
@@ -6206,8 +6334,8 @@ var PathSecurity = class {
|
|
|
6206
6334
|
}
|
|
6207
6335
|
async resolvePath(inputPath) {
|
|
6208
6336
|
const expanded = this.expandUserPath(inputPath);
|
|
6209
|
-
const absolute =
|
|
6210
|
-
const normalized2 =
|
|
6337
|
+
const absolute = path6.isAbsolute(expanded) ? expanded : path6.resolve(this.worktree, expanded);
|
|
6338
|
+
const normalized2 = path6.normalize(absolute);
|
|
6211
6339
|
const resolved = await this.resolveExistingParent(normalized2);
|
|
6212
6340
|
return resolved;
|
|
6213
6341
|
}
|
|
@@ -6219,7 +6347,7 @@ var PathSecurity = class {
|
|
|
6219
6347
|
const duplicatedHomePrefix = normalizedHome ? `~/${normalizedHome}` : "";
|
|
6220
6348
|
if (duplicatedHomePrefix && (normalizedInput === duplicatedHomePrefix || normalizedInput.startsWith(`${duplicatedHomePrefix}/`))) {
|
|
6221
6349
|
const absoluteSuffix = normalizedInput.slice(2);
|
|
6222
|
-
return
|
|
6350
|
+
return path6.sep === "\\" ? absoluteSuffix.replace(/\//g, "\\") : `/${absoluteSuffix}`;
|
|
6223
6351
|
}
|
|
6224
6352
|
return inputPath.replace(/^~(?=\/|\\)/, this.home);
|
|
6225
6353
|
}
|
|
@@ -6228,16 +6356,16 @@ var PathSecurity = class {
|
|
|
6228
6356
|
}
|
|
6229
6357
|
async resolveExistingParent(targetPath) {
|
|
6230
6358
|
let cursor = targetPath;
|
|
6231
|
-
while (cursor !==
|
|
6359
|
+
while (cursor !== path6.dirname(cursor)) {
|
|
6232
6360
|
try {
|
|
6233
6361
|
await access(cursor);
|
|
6234
6362
|
const real = await realpath(cursor);
|
|
6235
6363
|
if (targetPath === cursor) {
|
|
6236
6364
|
return real;
|
|
6237
6365
|
}
|
|
6238
|
-
return
|
|
6366
|
+
return path6.join(real, path6.relative(cursor, targetPath));
|
|
6239
6367
|
} catch {
|
|
6240
|
-
cursor =
|
|
6368
|
+
cursor = path6.dirname(cursor);
|
|
6241
6369
|
}
|
|
6242
6370
|
}
|
|
6243
6371
|
return targetPath;
|
|
@@ -6535,16 +6663,16 @@ function whitelistExampleForPath(targetPath) {
|
|
|
6535
6663
|
return "${WORKTREE}/**";
|
|
6536
6664
|
}
|
|
6537
6665
|
const home = process.env.HOME ?? os3.homedir();
|
|
6538
|
-
const normalizedTarget =
|
|
6539
|
-
const normalizedHome =
|
|
6666
|
+
const normalizedTarget = path7.resolve(targetPath);
|
|
6667
|
+
const normalizedHome = path7.resolve(home);
|
|
6540
6668
|
if (normalizedTarget === normalizedHome) {
|
|
6541
6669
|
return "${HOME}/**";
|
|
6542
6670
|
}
|
|
6543
|
-
if (normalizedTarget.startsWith(`${normalizedHome}${
|
|
6544
|
-
const relative2 =
|
|
6671
|
+
if (normalizedTarget.startsWith(`${normalizedHome}${path7.sep}`)) {
|
|
6672
|
+
const relative2 = path7.relative(normalizedHome, normalizedTarget).replaceAll(path7.sep, "/");
|
|
6545
6673
|
return relative2 ? `\${HOME}/${relative2}/**` : "${HOME}/**";
|
|
6546
6674
|
}
|
|
6547
|
-
const normalizedForConfig = normalizedTarget.replaceAll(
|
|
6675
|
+
const normalizedForConfig = normalizedTarget.replaceAll(path7.sep, "/");
|
|
6548
6676
|
if (normalizedForConfig === "/") {
|
|
6549
6677
|
return "/**";
|
|
6550
6678
|
}
|
|
@@ -6604,20 +6732,20 @@ var SessionManager = class {
|
|
|
6604
6732
|
}
|
|
6605
6733
|
async persist(sessionId) {
|
|
6606
6734
|
const session = this.get(sessionId);
|
|
6607
|
-
const dir =
|
|
6735
|
+
const dir = path8.join(this.worktree, ".deepcode", "sessions");
|
|
6608
6736
|
await mkdir4(dir, { recursive: true });
|
|
6609
|
-
const filePath =
|
|
6737
|
+
const filePath = path8.join(dir, `${session.id}.json`);
|
|
6610
6738
|
await writeFileAtomic(filePath, `${JSON.stringify(session, null, 2)}
|
|
6611
6739
|
`);
|
|
6612
6740
|
return filePath;
|
|
6613
6741
|
}
|
|
6614
6742
|
async loadAll() {
|
|
6615
|
-
const dir =
|
|
6743
|
+
const dir = path8.join(this.worktree, ".deepcode", "sessions");
|
|
6616
6744
|
try {
|
|
6617
|
-
const entries = await
|
|
6745
|
+
const entries = await readdir2(dir);
|
|
6618
6746
|
const loaded = [];
|
|
6619
6747
|
for (const entry of entries.filter((value) => value.endsWith(".json"))) {
|
|
6620
|
-
const filePath =
|
|
6748
|
+
const filePath = path8.join(dir, entry);
|
|
6621
6749
|
try {
|
|
6622
6750
|
const parsed = JSON.parse(await readFile3(filePath, "utf8"));
|
|
6623
6751
|
const result = SessionSchema.safeParse(parsed);
|
|
@@ -6665,7 +6793,7 @@ var analyzeCodeTool = defineTool({
|
|
|
6665
6793
|
const declarations = content.split(/\r?\n/).map((line, index) => ({ line: index + 1, text: line.trim() })).filter(({ text }) => /^(export\s+)?(class|interface|type|function|const|let|var|def|func)\s+/.test(text));
|
|
6666
6794
|
const result = {
|
|
6667
6795
|
file: filePath,
|
|
6668
|
-
extension:
|
|
6796
|
+
extension: path10.extname(filePath),
|
|
6669
6797
|
lines: content.split(/\r?\n/).length,
|
|
6670
6798
|
declarations
|
|
6671
6799
|
};
|
|
@@ -6734,7 +6862,7 @@ var readFileTool = defineTool({
|
|
|
6734
6862
|
if (cached.hit && cached.value !== void 0) {
|
|
6735
6863
|
context.logActivity({
|
|
6736
6864
|
type: "cache_hit",
|
|
6737
|
-
message: `Cache hit read_file ${
|
|
6865
|
+
message: `Cache hit read_file ${path11.relative(context.worktree, filePath)}`,
|
|
6738
6866
|
metadata: { path: filePath }
|
|
6739
6867
|
});
|
|
6740
6868
|
return cached.value;
|
|
@@ -6745,7 +6873,7 @@ var readFileTool = defineTool({
|
|
|
6745
6873
|
const end = args.limit ? Math.min(lines.length, start + args.limit) : lines.length;
|
|
6746
6874
|
context.logActivity({
|
|
6747
6875
|
type: "file_read",
|
|
6748
|
-
message: `Read ${
|
|
6876
|
+
message: `Read ${path11.relative(context.worktree, filePath)}`,
|
|
6749
6877
|
metadata: { path: filePath, lines: end - start }
|
|
6750
6878
|
});
|
|
6751
6879
|
const output = lines.slice(start, end).map((line, index) => `${String(start + index + 1).padStart(5, " ")} | ${line}`).join("\n");
|
|
@@ -6767,11 +6895,11 @@ var writeFileTool = defineTool({
|
|
|
6767
6895
|
const filePath = await context.pathSecurity.normalize(args.path, { enforceAccess: false });
|
|
6768
6896
|
await context.permissions.ensure({ operation: "write_file", kind: "write", path: filePath });
|
|
6769
6897
|
await context.snapshotForUndo?.(filePath);
|
|
6770
|
-
await mkdir6(
|
|
6898
|
+
await mkdir6(path11.dirname(filePath), { recursive: true });
|
|
6771
6899
|
await writeFile22(filePath, args.content, "utf8");
|
|
6772
6900
|
context.logActivity({
|
|
6773
6901
|
type: "file_written",
|
|
6774
|
-
message: `Wrote ${
|
|
6902
|
+
message: `Wrote ${path11.relative(context.worktree, filePath)}`,
|
|
6775
6903
|
metadata: { path: filePath, bytes: Buffer.byteLength(args.content) }
|
|
6776
6904
|
});
|
|
6777
6905
|
return `File written: ${filePath}`;
|
|
@@ -6804,7 +6932,7 @@ var editFileTool = defineTool({
|
|
|
6804
6932
|
await writeFile22(filePath, next, "utf8");
|
|
6805
6933
|
context.logActivity({
|
|
6806
6934
|
type: "file_edited",
|
|
6807
|
-
message: `Edited ${
|
|
6935
|
+
message: `Edited ${path11.relative(context.worktree, filePath)}`,
|
|
6808
6936
|
metadata: { path: filePath, removedBytes: args.oldString.length, addedBytes: args.newString.length }
|
|
6809
6937
|
});
|
|
6810
6938
|
return `File edited: ${filePath}`;
|
|
@@ -6822,18 +6950,23 @@ var listDirTool = defineTool({
|
|
|
6822
6950
|
try: async () => {
|
|
6823
6951
|
const dirPath = await context.pathSecurity.normalize(args.path, { enforceAccess: false });
|
|
6824
6952
|
await context.permissions.ensure({ operation: "list_dir", kind: "read", path: dirPath });
|
|
6825
|
-
const entries = await
|
|
6953
|
+
const entries = await readdir4(dirPath, { withFileTypes: true });
|
|
6826
6954
|
const rows = await Promise.all(
|
|
6827
6955
|
entries.filter((entry) => entry.name !== "node_modules" && entry.name !== ".git").map(async (entry) => {
|
|
6828
|
-
const fullPath =
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6956
|
+
const fullPath = path11.join(dirPath, entry.name);
|
|
6957
|
+
try {
|
|
6958
|
+
const info = await lstat2(fullPath);
|
|
6959
|
+
const type = entry.isSymbolicLink() ? "link" : entry.isDirectory() ? "dir " : "file";
|
|
6960
|
+
return `${type} ${String(info.size).padStart(9, " ")} ${entry.name}`;
|
|
6961
|
+
} catch (error) {
|
|
6962
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6963
|
+
return `unknown ${"?".padStart(9, " ")} ${entry.name} (${message})`;
|
|
6964
|
+
}
|
|
6832
6965
|
})
|
|
6833
6966
|
);
|
|
6834
6967
|
context.logActivity({
|
|
6835
6968
|
type: "directory_listed",
|
|
6836
|
-
message: `Listed ${
|
|
6969
|
+
message: `Listed ${path11.relative(context.worktree, dirPath) || "."}`,
|
|
6837
6970
|
metadata: { path: dirPath, entries: rows.length }
|
|
6838
6971
|
});
|
|
6839
6972
|
return rows.join("\n");
|
|
@@ -6952,7 +7085,7 @@ var searchTextTool = defineTool({
|
|
|
6952
7085
|
if (cached.hit && cached.value !== void 0) {
|
|
6953
7086
|
context.logActivity({
|
|
6954
7087
|
type: "cache_hit",
|
|
6955
|
-
message: `Cache hit search_text ${
|
|
7088
|
+
message: `Cache hit search_text ${path12.relative(context.worktree, searchPath) || "."}`,
|
|
6956
7089
|
metadata: { pattern: args.pattern }
|
|
6957
7090
|
});
|
|
6958
7091
|
return cached.value;
|
|
@@ -6977,7 +7110,7 @@ var searchTextTool = defineTool({
|
|
|
6977
7110
|
}));
|
|
6978
7111
|
context.logActivity({
|
|
6979
7112
|
type: "text_search",
|
|
6980
|
-
message: `Searched ${
|
|
7113
|
+
message: `Searched ${path12.relative(context.worktree, searchPath) || "."}`,
|
|
6981
7114
|
metadata: { pattern: args.pattern, matches: matches.length }
|
|
6982
7115
|
});
|
|
6983
7116
|
const output = JSON.stringify(matches, null, 2);
|
|
@@ -7017,7 +7150,7 @@ var searchFilesTool = defineTool({
|
|
|
7017
7150
|
throw new Error(result.stderr || `ripgrep exited with ${result.exitCode}`);
|
|
7018
7151
|
}
|
|
7019
7152
|
const needle = args.query.toLowerCase();
|
|
7020
|
-
const files = result.stdout.split(/\r?\n/).filter(Boolean).filter((file) =>
|
|
7153
|
+
const files = result.stdout.split(/\r?\n/).filter(Boolean).filter((file) => path12.basename(file).toLowerCase().includes(needle)).slice(0, 200);
|
|
7021
7154
|
context.logActivity({
|
|
7022
7155
|
type: "file_search",
|
|
7023
7156
|
message: `Found ${files.length} file(s)`,
|
|
@@ -7339,7 +7472,7 @@ function createDefaultToolRegistry() {
|
|
|
7339
7472
|
}
|
|
7340
7473
|
|
|
7341
7474
|
// ../../packages/cli/dist/index.js
|
|
7342
|
-
import
|
|
7475
|
+
import path9 from "path";
|
|
7343
7476
|
import { writeSync } from "fs";
|
|
7344
7477
|
import { mkdtemp, rm as rm3 } from "fs/promises";
|
|
7345
7478
|
import { tmpdir } from "os";
|
|
@@ -8315,7 +8448,7 @@ var AsyncFzf = class {
|
|
|
8315
8448
|
// ../../packages/cli/dist/index.js
|
|
8316
8449
|
import { execFile as execFile3 } from "child_process";
|
|
8317
8450
|
import * as nodeFs from "fs";
|
|
8318
|
-
import { access as access2, lstat, open, readFile as readFile4, stat as stat2 } from "fs/promises";
|
|
8451
|
+
import { access as access2, lstat as lstat3, open, readFile as readFile4, stat as stat2 } from "fs/promises";
|
|
8319
8452
|
import * as path42 from "path";
|
|
8320
8453
|
import { promisify } from "util";
|
|
8321
8454
|
import { useState as useState2, useRef, useCallback, useMemo } from "react";
|
|
@@ -9342,7 +9475,7 @@ import { jsx as jsx45, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
|
9342
9475
|
import { jsx as jsx46, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
9343
9476
|
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
9344
9477
|
async function createRuntime(options) {
|
|
9345
|
-
const worktree =
|
|
9478
|
+
const worktree = path9.resolve(options.cwd);
|
|
9346
9479
|
const config = await new ConfigLoader().load({ cwd: worktree, configPath: options.configPath });
|
|
9347
9480
|
const events = new EventBus();
|
|
9348
9481
|
const pathSecurity = new PathSecurity(worktree, config.paths);
|
|
@@ -10599,7 +10732,7 @@ async function isInTransientGitState(gitRoot) {
|
|
|
10599
10732
|
async function countUntrackedLines(absolutePath) {
|
|
10600
10733
|
let fileStat;
|
|
10601
10734
|
try {
|
|
10602
|
-
fileStat = await
|
|
10735
|
+
fileStat = await lstat3(absolutePath);
|
|
10603
10736
|
} catch {
|
|
10604
10737
|
return { added: 0, isBinary: true, truncated: false };
|
|
10605
10738
|
}
|