@trydecember/cli 0.4.3 → 0.4.4
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/december.js +1469 -254
- package/package.json +1 -1
package/dist/december.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "@trydecember/cli",
|
|
68
|
-
version: "0.4.
|
|
68
|
+
version: "0.4.4",
|
|
69
69
|
description: "a coding agent for terminal and cloud.",
|
|
70
70
|
homepage: "https://trydecember.com",
|
|
71
71
|
repository: {
|
|
@@ -11072,10 +11072,13 @@ async function providerFetch(url, init) {
|
|
|
11072
11072
|
if (!res.ok) {
|
|
11073
11073
|
const text = await res.text();
|
|
11074
11074
|
const normalized = normalizeErrorResponse(text);
|
|
11075
|
+
const headers = new Headers(res.headers);
|
|
11076
|
+
headers.delete("retry-after");
|
|
11077
|
+
headers.delete("retry-after-ms");
|
|
11075
11078
|
return new Response(normalized, {
|
|
11076
11079
|
status: res.status,
|
|
11077
11080
|
statusText: res.statusText,
|
|
11078
|
-
headers
|
|
11081
|
+
headers
|
|
11079
11082
|
});
|
|
11080
11083
|
}
|
|
11081
11084
|
return res;
|
|
@@ -11085,7 +11088,8 @@ function openaiProvider(baseURL, apiKey, defaultHeaders, customClient) {
|
|
|
11085
11088
|
baseURL,
|
|
11086
11089
|
apiKey: apiKey || process.env.OPENAI_API_KEY || "dummy-key",
|
|
11087
11090
|
defaultHeaders,
|
|
11088
|
-
fetch: providerFetch
|
|
11091
|
+
fetch: providerFetch,
|
|
11092
|
+
maxRetries: 0
|
|
11089
11093
|
});
|
|
11090
11094
|
return createProvider({
|
|
11091
11095
|
id: "openai",
|
|
@@ -11184,6 +11188,11 @@ function openaiProvider(baseURL, apiKey, defaultHeaders, customClient) {
|
|
|
11184
11188
|
}
|
|
11185
11189
|
const activeToolCalls = new Map;
|
|
11186
11190
|
for await (const chunk of stream) {
|
|
11191
|
+
if (chunk.error) {
|
|
11192
|
+
const errObj = chunk.error;
|
|
11193
|
+
const msg = typeof errObj === "string" ? errObj : errObj.message || JSON.stringify(errObj);
|
|
11194
|
+
throw new Error(msg);
|
|
11195
|
+
}
|
|
11187
11196
|
if (chunk.usage) {
|
|
11188
11197
|
const cachedTokens = chunk.usage.prompt_tokens_details?.cached_tokens;
|
|
11189
11198
|
yield {
|
|
@@ -66472,15 +66481,23 @@ function anthropicProvider(baseURL, apiKey, customClientOrDefaultHeaders, custom
|
|
|
66472
66481
|
antMessages.push({ role: "assistant", content });
|
|
66473
66482
|
}
|
|
66474
66483
|
} else {
|
|
66475
|
-
antMessages.
|
|
66476
|
-
|
|
66477
|
-
content
|
|
66478
|
-
|
|
66479
|
-
|
|
66480
|
-
|
|
66481
|
-
|
|
66482
|
-
|
|
66483
|
-
|
|
66484
|
+
const prev = antMessages[antMessages.length - 1];
|
|
66485
|
+
if (prev && prev.role === "user" && Array.isArray(prev.content)) {
|
|
66486
|
+
prev.content.push({
|
|
66487
|
+
type: "text",
|
|
66488
|
+
text: msg.content
|
|
66489
|
+
});
|
|
66490
|
+
} else {
|
|
66491
|
+
antMessages.push({
|
|
66492
|
+
role: "user",
|
|
66493
|
+
content: [
|
|
66494
|
+
{
|
|
66495
|
+
type: "text",
|
|
66496
|
+
text: msg.content
|
|
66497
|
+
}
|
|
66498
|
+
]
|
|
66499
|
+
});
|
|
66500
|
+
}
|
|
66484
66501
|
}
|
|
66485
66502
|
}
|
|
66486
66503
|
if (antMessages.length >= 4) {
|
|
@@ -109444,6 +109461,14 @@ var LIVE_MODEL_CACHE_TTL_MS, liveModelCache, diskCacheLoaded = false, getCurated
|
|
|
109444
109461
|
case "aurikoai":
|
|
109445
109462
|
case "auriko-ai":
|
|
109446
109463
|
return [
|
|
109464
|
+
{
|
|
109465
|
+
label: "DeepSeek V4 Flash",
|
|
109466
|
+
value: "deepseek-v4-flash"
|
|
109467
|
+
},
|
|
109468
|
+
{
|
|
109469
|
+
label: "Gemini 2.5 Flash",
|
|
109470
|
+
value: "gemini-2.5-flash"
|
|
109471
|
+
},
|
|
109447
109472
|
{
|
|
109448
109473
|
label: "Claude Sonnet 4.6",
|
|
109449
109474
|
value: "claude-sonnet-4-6"
|
|
@@ -109456,18 +109481,10 @@ var LIVE_MODEL_CACHE_TTL_MS, liveModelCache, diskCacheLoaded = false, getCurated
|
|
|
109456
109481
|
label: "Claude Opus 4.7",
|
|
109457
109482
|
value: "claude-opus-4-7"
|
|
109458
109483
|
},
|
|
109459
|
-
{
|
|
109460
|
-
label: "DeepSeek V4 Flash",
|
|
109461
|
-
value: "deepseek-v4-flash"
|
|
109462
|
-
},
|
|
109463
109484
|
{
|
|
109464
109485
|
label: "DeepSeek V4 Pro",
|
|
109465
109486
|
value: "deepseek-v4-pro"
|
|
109466
109487
|
},
|
|
109467
|
-
{
|
|
109468
|
-
label: "Gemini 2.5 Flash",
|
|
109469
|
-
value: "gemini-2.5-flash"
|
|
109470
|
-
},
|
|
109471
109488
|
{
|
|
109472
109489
|
label: "Gemini 2.5 Pro",
|
|
109473
109490
|
value: "gemini-2.5-pro"
|
|
@@ -111284,9 +111301,15 @@ var LIVE_MODEL_CACHE_TTL_MS, liveModelCache, diskCacheLoaded = false, getCurated
|
|
|
111284
111301
|
if (normalized === "anyapi") {
|
|
111285
111302
|
return "anthropic/claude-sonnet-4-6";
|
|
111286
111303
|
}
|
|
111304
|
+
if (normalized === "auriko" || normalized === "aurikoai" || normalized === "auriko-ai") {
|
|
111305
|
+
return "deepseek-v4-flash";
|
|
111306
|
+
}
|
|
111287
111307
|
if (normalized === "bailing") {
|
|
111288
111308
|
return "Ling-1T";
|
|
111289
111309
|
}
|
|
111310
|
+
if (normalized === "baseten" || normalized === "basetenco" || normalized === "baseten-co") {
|
|
111311
|
+
return "deepseek-ai/DeepSeek-V4.1-Flash";
|
|
111312
|
+
}
|
|
111290
111313
|
if (normalized === "berget") {
|
|
111291
111314
|
return "mistralai/Mistral-Small-3.2-24B-Instruct-2506";
|
|
111292
111315
|
}
|
|
@@ -119421,6 +119444,190 @@ var init_browser = __esm(() => {
|
|
|
119421
119444
|
};
|
|
119422
119445
|
});
|
|
119423
119446
|
|
|
119447
|
+
// ../../packages/tools/src/code_intelligence.ts
|
|
119448
|
+
function formatDiagnostics(diags, path) {
|
|
119449
|
+
const target = path ? ` for ${path}` : "";
|
|
119450
|
+
if (!diags) {
|
|
119451
|
+
return `No diagnostic errors found${target}.`;
|
|
119452
|
+
}
|
|
119453
|
+
if (typeof diags === "string") {
|
|
119454
|
+
const trimmed = diags.trim();
|
|
119455
|
+
if (!trimmed) {
|
|
119456
|
+
return `No diagnostic errors found${target}.`;
|
|
119457
|
+
}
|
|
119458
|
+
return `Diagnostic errors found${target}:
|
|
119459
|
+
${trimmed}`;
|
|
119460
|
+
}
|
|
119461
|
+
if (Array.isArray(diags)) {
|
|
119462
|
+
if (diags.length === 0) {
|
|
119463
|
+
return `No diagnostic errors found${target}.`;
|
|
119464
|
+
}
|
|
119465
|
+
const formatted = diags.map((d) => {
|
|
119466
|
+
const loc = d.line ? `:${d.line}${d.column ? `:${d.column}` : ""}` : "";
|
|
119467
|
+
return `${d.filePath}${loc} - [${d.severity ?? "error"}] ${d.message}${d.source ? ` (${d.source})` : ""}`;
|
|
119468
|
+
}).join(`
|
|
119469
|
+
`);
|
|
119470
|
+
return `Diagnostic errors found${target}:
|
|
119471
|
+
${formatted}`;
|
|
119472
|
+
}
|
|
119473
|
+
return `No diagnostic errors found${target}.`;
|
|
119474
|
+
}
|
|
119475
|
+
var codeIntelligenceSchema, CodeIntelligenceTool;
|
|
119476
|
+
var init_code_intelligence = __esm(() => {
|
|
119477
|
+
init_esm2();
|
|
119478
|
+
codeIntelligenceSchema = Type2.Object({
|
|
119479
|
+
action: Type2.Union([
|
|
119480
|
+
Type2.Literal("diagnostics"),
|
|
119481
|
+
Type2.Literal("definition"),
|
|
119482
|
+
Type2.Literal("references"),
|
|
119483
|
+
Type2.Literal("outline")
|
|
119484
|
+
], {
|
|
119485
|
+
description: 'The code intelligence action to perform: "diagnostics", "definition", "references", or "outline".'
|
|
119486
|
+
}),
|
|
119487
|
+
path: Type2.Optional(Type2.String({
|
|
119488
|
+
description: 'Relative or absolute file path or directory to query. Required for "definition", "references", and "outline".'
|
|
119489
|
+
})),
|
|
119490
|
+
line: Type2.Optional(Type2.Integer({
|
|
119491
|
+
description: "1-indexed line number of the symbol for definition or references lookup."
|
|
119492
|
+
})),
|
|
119493
|
+
column: Type2.Optional(Type2.Integer({
|
|
119494
|
+
description: "1-indexed column number of the symbol for definition or references lookup."
|
|
119495
|
+
})),
|
|
119496
|
+
symbol: Type2.Optional(Type2.String({
|
|
119497
|
+
description: "Optional symbol name to search for in the file if line and column are not specified."
|
|
119498
|
+
}))
|
|
119499
|
+
});
|
|
119500
|
+
CodeIntelligenceTool = {
|
|
119501
|
+
name: "code_intelligence",
|
|
119502
|
+
description: "Query on-demand code intelligence, symbol definitions, call site references, document outline, and compiler diagnostics across the workspace or for a specific file.",
|
|
119503
|
+
inputSchema: codeIntelligenceSchema,
|
|
119504
|
+
execute: async ({ action, path, line, column, symbol }, context) => {
|
|
119505
|
+
if (action !== "diagnostics" && action !== "definition" && action !== "references" && action !== "outline") {
|
|
119506
|
+
return `Unsupported action: "${action}". Supported actions: "diagnostics", "definition", "references", "outline".`;
|
|
119507
|
+
}
|
|
119508
|
+
if (action === "diagnostics") {
|
|
119509
|
+
const diagFn = context.operations.diagnostics?.getDiagnostics || context.operations.lsp?.getDiagnostics;
|
|
119510
|
+
if (!diagFn) {
|
|
119511
|
+
return "Error: Diagnostics operations are not supported in the current environment.";
|
|
119512
|
+
}
|
|
119513
|
+
try {
|
|
119514
|
+
const diags = await diagFn(path ?? "");
|
|
119515
|
+
return formatDiagnostics(diags, path);
|
|
119516
|
+
} catch (err) {
|
|
119517
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119518
|
+
return `Error retrieving diagnostics: ${message}`;
|
|
119519
|
+
}
|
|
119520
|
+
}
|
|
119521
|
+
if (action === "outline") {
|
|
119522
|
+
if (!path) {
|
|
119523
|
+
return 'Error: "path" parameter is required for "outline" action.';
|
|
119524
|
+
}
|
|
119525
|
+
if (!context.operations.lsp?.getOutline) {
|
|
119526
|
+
return "Error: LSP operations are not supported in the current environment.";
|
|
119527
|
+
}
|
|
119528
|
+
try {
|
|
119529
|
+
const symbols = await context.operations.lsp.getOutline(path);
|
|
119530
|
+
if (!symbols || symbols.length === 0) {
|
|
119531
|
+
return `No document symbols found for ${path}.`;
|
|
119532
|
+
}
|
|
119533
|
+
const lines = symbols.map((s) => `- [${s.kind}] ${s.name} (${path}:${s.line}:${s.column})${s.containerName ? ` (in ${s.containerName})` : ""}`);
|
|
119534
|
+
return `Document outline for ${path}:
|
|
119535
|
+
${lines.join(`
|
|
119536
|
+
`)}`;
|
|
119537
|
+
} catch (err) {
|
|
119538
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119539
|
+
return `Error retrieving outline: ${message}`;
|
|
119540
|
+
}
|
|
119541
|
+
}
|
|
119542
|
+
if (!path) {
|
|
119543
|
+
return `Error: "path" parameter is required for "${action}" action.`;
|
|
119544
|
+
}
|
|
119545
|
+
let targetLine = line;
|
|
119546
|
+
let targetColumn = column;
|
|
119547
|
+
if ((targetLine === undefined || targetColumn === undefined) && symbol) {
|
|
119548
|
+
try {
|
|
119549
|
+
const content = await context.operations.fs.readFile(path);
|
|
119550
|
+
const fileLines = content.split(`
|
|
119551
|
+
`);
|
|
119552
|
+
let fallbackLine;
|
|
119553
|
+
let fallbackCol;
|
|
119554
|
+
for (let i = 0;i < fileLines.length; i++) {
|
|
119555
|
+
const lineStr = fileLines[i];
|
|
119556
|
+
const idx = lineStr.indexOf(symbol);
|
|
119557
|
+
if (idx !== -1) {
|
|
119558
|
+
if (/^\s*import\b/.test(lineStr)) {
|
|
119559
|
+
if (fallbackLine === undefined) {
|
|
119560
|
+
fallbackLine = i + 1;
|
|
119561
|
+
fallbackCol = idx + 1;
|
|
119562
|
+
}
|
|
119563
|
+
} else {
|
|
119564
|
+
targetLine = i + 1;
|
|
119565
|
+
targetColumn = idx + 1;
|
|
119566
|
+
break;
|
|
119567
|
+
}
|
|
119568
|
+
}
|
|
119569
|
+
}
|
|
119570
|
+
if (targetLine === undefined) {
|
|
119571
|
+
targetLine = fallbackLine;
|
|
119572
|
+
targetColumn = fallbackCol;
|
|
119573
|
+
}
|
|
119574
|
+
if (targetLine === undefined || targetColumn === undefined) {
|
|
119575
|
+
return `Symbol "${symbol}" not found in ${path}.`;
|
|
119576
|
+
}
|
|
119577
|
+
} catch (err) {
|
|
119578
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119579
|
+
return `Error reading file ${path}: ${message}`;
|
|
119580
|
+
}
|
|
119581
|
+
}
|
|
119582
|
+
if (targetLine === undefined || targetColumn === undefined) {
|
|
119583
|
+
return `Error: "line" and "column" (or "symbol") are required for "${action}" action.`;
|
|
119584
|
+
}
|
|
119585
|
+
if (action === "definition") {
|
|
119586
|
+
if (!context.operations.lsp?.getDefinition) {
|
|
119587
|
+
return "Error: LSP operations are not supported in the current environment.";
|
|
119588
|
+
}
|
|
119589
|
+
try {
|
|
119590
|
+
const raw = await context.operations.lsp.getDefinition(path, targetLine, targetColumn);
|
|
119591
|
+
const locs = Array.isArray(raw) ? raw : raw ? [raw] : [];
|
|
119592
|
+
if (locs.length === 0) {
|
|
119593
|
+
return `No definition found for symbol at ${path}:${targetLine}:${targetColumn}.`;
|
|
119594
|
+
}
|
|
119595
|
+
if (locs.length === 1) {
|
|
119596
|
+
const loc = locs[0];
|
|
119597
|
+
return `Definition found at ${loc.filePath}:${loc.line}:${loc.column}`;
|
|
119598
|
+
}
|
|
119599
|
+
const list = locs.map((l) => `- ${l.filePath}:${l.line}:${l.column}`).join(`
|
|
119600
|
+
`);
|
|
119601
|
+
return `Definition(s) found:
|
|
119602
|
+
${list}`;
|
|
119603
|
+
} catch (err) {
|
|
119604
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119605
|
+
return `Error retrieving definition: ${message}`;
|
|
119606
|
+
}
|
|
119607
|
+
}
|
|
119608
|
+
if (action === "references") {
|
|
119609
|
+
if (!context.operations.lsp?.getReferences) {
|
|
119610
|
+
return "Error: LSP operations are not supported in the current environment.";
|
|
119611
|
+
}
|
|
119612
|
+
try {
|
|
119613
|
+
const refs = await context.operations.lsp.getReferences(path, targetLine, targetColumn);
|
|
119614
|
+
if (!refs || refs.length === 0) {
|
|
119615
|
+
return `No references found for symbol at ${path}:${targetLine}:${targetColumn}.`;
|
|
119616
|
+
}
|
|
119617
|
+
const list = refs.map((r) => `- ${r.filePath}:${r.line}:${r.column}`).join(`
|
|
119618
|
+
`);
|
|
119619
|
+
return `Found ${refs.length} reference(s) for symbol at ${path}:${targetLine}:${targetColumn}:
|
|
119620
|
+
${list}`;
|
|
119621
|
+
} catch (err) {
|
|
119622
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
119623
|
+
return `Error retrieving references: ${message}`;
|
|
119624
|
+
}
|
|
119625
|
+
}
|
|
119626
|
+
return `Unsupported action: "${action}".`;
|
|
119627
|
+
}
|
|
119628
|
+
};
|
|
119629
|
+
});
|
|
119630
|
+
|
|
119424
119631
|
// ../../packages/tools/src/deferred-registry.ts
|
|
119425
119632
|
class DeferredToolRegistry {
|
|
119426
119633
|
tools = new Map;
|
|
@@ -121274,6 +121481,264 @@ var init_ls = __esm(() => {
|
|
|
121274
121481
|
};
|
|
121275
121482
|
});
|
|
121276
121483
|
|
|
121484
|
+
// ../../packages/tools/src/manage_memory.ts
|
|
121485
|
+
import path20 from "node:path";
|
|
121486
|
+
function resolveWriteTarget(cwd, target, category) {
|
|
121487
|
+
const isRules = target === "rules" || target === "RULES.md" || !target && category === "rules";
|
|
121488
|
+
if (isRules) {
|
|
121489
|
+
if (target === "RULES.md") {
|
|
121490
|
+
return { relativePath: "RULES.md", isRules: true };
|
|
121491
|
+
}
|
|
121492
|
+
return { relativePath: "RULES.md", isRules: true };
|
|
121493
|
+
}
|
|
121494
|
+
if (target === "MEMORY.md") {
|
|
121495
|
+
return { relativePath: "MEMORY.md", isRules: false };
|
|
121496
|
+
}
|
|
121497
|
+
return { relativePath: path20.join(".december", "memory.md"), isRules: false };
|
|
121498
|
+
}
|
|
121499
|
+
function resolveReadCandidates(target) {
|
|
121500
|
+
if (target === "rules" || target === "RULES.md") {
|
|
121501
|
+
return ["RULES.md", path20.join(".december", "rules.md"), path20.join(".december", "RULES.md")];
|
|
121502
|
+
}
|
|
121503
|
+
if (target === "memory" || target === "MEMORY.md") {
|
|
121504
|
+
return [
|
|
121505
|
+
path20.join(".december", "memory.md"),
|
|
121506
|
+
"MEMORY.md",
|
|
121507
|
+
path20.join(".december", "MEMORY.md")
|
|
121508
|
+
];
|
|
121509
|
+
}
|
|
121510
|
+
return [
|
|
121511
|
+
path20.join(".december", "memory.md"),
|
|
121512
|
+
"MEMORY.md",
|
|
121513
|
+
"RULES.md",
|
|
121514
|
+
path20.join(".december", "rules.md")
|
|
121515
|
+
];
|
|
121516
|
+
}
|
|
121517
|
+
function normalizeEntry(text) {
|
|
121518
|
+
return text.replace(/^[-*•]\s+/, "").trim();
|
|
121519
|
+
}
|
|
121520
|
+
var manageMemorySchema, ManageMemoryTool;
|
|
121521
|
+
var init_manage_memory = __esm(() => {
|
|
121522
|
+
init_esm2();
|
|
121523
|
+
manageMemorySchema = Type2.Object({
|
|
121524
|
+
action: Type2.Union([Type2.Literal("record"), Type2.Literal("read"), Type2.Literal("forget")], {
|
|
121525
|
+
description: 'The action to perform: "record" to store an entry, "read" to inspect entries, or "forget" to prune an entry.'
|
|
121526
|
+
}),
|
|
121527
|
+
entry: Type2.Optional(Type2.String({
|
|
121528
|
+
description: "The memory or rule entry text to record or forget."
|
|
121529
|
+
})),
|
|
121530
|
+
category: Type2.Optional(Type2.Union([
|
|
121531
|
+
Type2.Literal("build_and_test"),
|
|
121532
|
+
Type2.Literal("conventions"),
|
|
121533
|
+
Type2.Literal("architecture"),
|
|
121534
|
+
Type2.Literal("quirks"),
|
|
121535
|
+
Type2.Literal("rules"),
|
|
121536
|
+
Type2.Literal("general")
|
|
121537
|
+
], {
|
|
121538
|
+
description: "Category header: build_and_test, conventions, architecture, quirks, rules, or general."
|
|
121539
|
+
})),
|
|
121540
|
+
target: Type2.Optional(Type2.Union([
|
|
121541
|
+
Type2.Literal("memory"),
|
|
121542
|
+
Type2.Literal("rules"),
|
|
121543
|
+
Type2.Literal("MEMORY.md"),
|
|
121544
|
+
Type2.Literal("RULES.md")
|
|
121545
|
+
], {
|
|
121546
|
+
description: 'Target file: "memory" (.december/memory.md or MEMORY.md) or "rules" (RULES.md or .december/rules.md). Defaults to memory for general/memory entries, or rules if category is "rules".'
|
|
121547
|
+
})),
|
|
121548
|
+
query: Type2.Optional(Type2.String({
|
|
121549
|
+
description: "Optional query keyword to filter entries when reading."
|
|
121550
|
+
}))
|
|
121551
|
+
});
|
|
121552
|
+
ManageMemoryTool = {
|
|
121553
|
+
name: "manage_memory",
|
|
121554
|
+
description: "Use this tool to record, read, or forget persistent notes, conventions, build/test commands, quirks, and rules across sessions in workspace memory (.december/memory.md, MEMORY.md, RULES.md).",
|
|
121555
|
+
inputSchema: manageMemorySchema,
|
|
121556
|
+
execute: async ({ action, entry, category, target, query }, context) => {
|
|
121557
|
+
const cwd = context.operations.env.cwd();
|
|
121558
|
+
switch (action) {
|
|
121559
|
+
case "record": {
|
|
121560
|
+
if (!entry || !entry.trim()) {
|
|
121561
|
+
return 'Error: "entry" parameter is required for action "record".';
|
|
121562
|
+
}
|
|
121563
|
+
const cleanEntry = normalizeEntry(entry);
|
|
121564
|
+
if (!cleanEntry) {
|
|
121565
|
+
return 'Error: "entry" parameter cannot be empty.';
|
|
121566
|
+
}
|
|
121567
|
+
const { relativePath, isRules } = resolveWriteTarget(cwd, target, category);
|
|
121568
|
+
const fullPath = path20.isAbsolute(relativePath) ? relativePath : path20.join(cwd, relativePath);
|
|
121569
|
+
const cat = category || (isRules ? "rules" : "conventions");
|
|
121570
|
+
let existingContent = "";
|
|
121571
|
+
try {
|
|
121572
|
+
existingContent = await context.operations.fs.readFile(fullPath);
|
|
121573
|
+
} catch {}
|
|
121574
|
+
const lines = existingContent.split(`
|
|
121575
|
+
`);
|
|
121576
|
+
for (const line of lines) {
|
|
121577
|
+
const lineContent = normalizeEntry(line);
|
|
121578
|
+
if (lineContent && lineContent.toLowerCase() === cleanEntry.toLowerCase()) {
|
|
121579
|
+
return `Entry already exists in ${relativePath} under "${cat}". Skipped duplicate.`;
|
|
121580
|
+
}
|
|
121581
|
+
}
|
|
121582
|
+
const headerRegex = new RegExp(`^##\\s+${cat}\\b`, "im");
|
|
121583
|
+
const headerMatch = existingContent.match(headerRegex);
|
|
121584
|
+
let updatedContent = "";
|
|
121585
|
+
if (headerMatch && headerMatch.index !== undefined) {
|
|
121586
|
+
const headerIndex = headerMatch.index;
|
|
121587
|
+
const rest = existingContent.slice(headerIndex);
|
|
121588
|
+
const nextHeaderMatch = rest.slice(headerMatch[0].length).match(/\n##\s+/i);
|
|
121589
|
+
if (nextHeaderMatch && nextHeaderMatch.index !== undefined) {
|
|
121590
|
+
const insertPos = headerIndex + headerMatch[0].length + nextHeaderMatch.index;
|
|
121591
|
+
updatedContent = `${existingContent.slice(0, insertPos)}
|
|
121592
|
+
- ${cleanEntry}${existingContent.slice(insertPos)}`;
|
|
121593
|
+
} else {
|
|
121594
|
+
updatedContent = `${existingContent.trimEnd()}
|
|
121595
|
+
- ${cleanEntry}
|
|
121596
|
+
`;
|
|
121597
|
+
}
|
|
121598
|
+
} else {
|
|
121599
|
+
const prefix = existingContent.trim() ? `${existingContent.trimEnd()}
|
|
121600
|
+
|
|
121601
|
+
` : "";
|
|
121602
|
+
updatedContent = `${prefix}## ${cat}
|
|
121603
|
+
- ${cleanEntry}
|
|
121604
|
+
`;
|
|
121605
|
+
}
|
|
121606
|
+
try {
|
|
121607
|
+
await context.operations.fs.writeFile(fullPath, updatedContent);
|
|
121608
|
+
return `Recorded entry under "${cat}" in ${relativePath}.`;
|
|
121609
|
+
} catch (err) {
|
|
121610
|
+
return `Failed to write memory file: ${err.message}`;
|
|
121611
|
+
}
|
|
121612
|
+
}
|
|
121613
|
+
case "read": {
|
|
121614
|
+
const candidates = resolveReadCandidates(target);
|
|
121615
|
+
const contents = [];
|
|
121616
|
+
for (const candidate of candidates) {
|
|
121617
|
+
const fullPath = path20.isAbsolute(candidate) ? candidate : path20.join(cwd, candidate);
|
|
121618
|
+
try {
|
|
121619
|
+
const text = await context.operations.fs.readFile(fullPath);
|
|
121620
|
+
if (text && text.trim()) {
|
|
121621
|
+
contents.push({ file: candidate, text: text.trim() });
|
|
121622
|
+
}
|
|
121623
|
+
} catch {}
|
|
121624
|
+
}
|
|
121625
|
+
if (contents.length === 0) {
|
|
121626
|
+
return "No memory or rules entries found.";
|
|
121627
|
+
}
|
|
121628
|
+
if (category) {
|
|
121629
|
+
const matchedSections = [];
|
|
121630
|
+
const catLower = category.toLowerCase();
|
|
121631
|
+
for (const item of contents) {
|
|
121632
|
+
const lines = item.text.split(`
|
|
121633
|
+
`);
|
|
121634
|
+
let inCategory = false;
|
|
121635
|
+
const sectionLines = [];
|
|
121636
|
+
for (const line of lines) {
|
|
121637
|
+
if (line.startsWith("## ")) {
|
|
121638
|
+
const headerName = line.slice(3).trim().toLowerCase();
|
|
121639
|
+
if (headerName === catLower) {
|
|
121640
|
+
inCategory = true;
|
|
121641
|
+
sectionLines.push(line);
|
|
121642
|
+
} else {
|
|
121643
|
+
inCategory = false;
|
|
121644
|
+
}
|
|
121645
|
+
} else if (inCategory) {
|
|
121646
|
+
sectionLines.push(line);
|
|
121647
|
+
}
|
|
121648
|
+
}
|
|
121649
|
+
if (sectionLines.length > 0) {
|
|
121650
|
+
matchedSections.push(`### Source: ${item.file}
|
|
121651
|
+
${sectionLines.join(`
|
|
121652
|
+
`).trim()}`);
|
|
121653
|
+
}
|
|
121654
|
+
}
|
|
121655
|
+
if (matchedSections.length === 0) {
|
|
121656
|
+
return `No entries found under category "${category}".`;
|
|
121657
|
+
}
|
|
121658
|
+
return matchedSections.join(`
|
|
121659
|
+
|
|
121660
|
+
`);
|
|
121661
|
+
}
|
|
121662
|
+
if (query) {
|
|
121663
|
+
const queryLower = query.toLowerCase();
|
|
121664
|
+
const matchedLines = [];
|
|
121665
|
+
for (const item of contents) {
|
|
121666
|
+
const lines = item.text.split(`
|
|
121667
|
+
`);
|
|
121668
|
+
let currentHeader = "";
|
|
121669
|
+
const fileMatches = [];
|
|
121670
|
+
for (const line of lines) {
|
|
121671
|
+
if (line.startsWith("## ")) {
|
|
121672
|
+
currentHeader = line;
|
|
121673
|
+
} else if (line.toLowerCase().includes(queryLower)) {
|
|
121674
|
+
if (currentHeader && !fileMatches.includes(currentHeader)) {
|
|
121675
|
+
fileMatches.push(currentHeader);
|
|
121676
|
+
}
|
|
121677
|
+
fileMatches.push(line);
|
|
121678
|
+
}
|
|
121679
|
+
}
|
|
121680
|
+
if (fileMatches.length > 0) {
|
|
121681
|
+
matchedLines.push(`### Source: ${item.file}
|
|
121682
|
+
${fileMatches.join(`
|
|
121683
|
+
`)}`);
|
|
121684
|
+
}
|
|
121685
|
+
}
|
|
121686
|
+
if (matchedLines.length === 0) {
|
|
121687
|
+
return `No memory entries found matching "${query}".`;
|
|
121688
|
+
}
|
|
121689
|
+
return matchedLines.join(`
|
|
121690
|
+
|
|
121691
|
+
`);
|
|
121692
|
+
}
|
|
121693
|
+
return contents.map((c) => `### Source: ${c.file}
|
|
121694
|
+
${c.text}`).join(`
|
|
121695
|
+
|
|
121696
|
+
`);
|
|
121697
|
+
}
|
|
121698
|
+
case "forget": {
|
|
121699
|
+
if (!entry || !entry.trim()) {
|
|
121700
|
+
return 'Error: "entry" parameter is required for action "forget".';
|
|
121701
|
+
}
|
|
121702
|
+
const targetClean = normalizeEntry(entry).toLowerCase();
|
|
121703
|
+
const candidates = resolveReadCandidates(target);
|
|
121704
|
+
let removed = false;
|
|
121705
|
+
for (const candidate of candidates) {
|
|
121706
|
+
const fullPath = path20.isAbsolute(candidate) ? candidate : path20.join(cwd, candidate);
|
|
121707
|
+
try {
|
|
121708
|
+
const text = await context.operations.fs.readFile(fullPath);
|
|
121709
|
+
const lines = text.split(`
|
|
121710
|
+
`);
|
|
121711
|
+
const newLines = [];
|
|
121712
|
+
let fileModified = false;
|
|
121713
|
+
for (const line of lines) {
|
|
121714
|
+
const lineClean = normalizeEntry(line).toLowerCase();
|
|
121715
|
+
if (lineClean && (lineClean === targetClean || lineClean.includes(targetClean))) {
|
|
121716
|
+
fileModified = true;
|
|
121717
|
+
removed = true;
|
|
121718
|
+
continue;
|
|
121719
|
+
}
|
|
121720
|
+
newLines.push(line);
|
|
121721
|
+
}
|
|
121722
|
+
if (fileModified) {
|
|
121723
|
+
await context.operations.fs.writeFile(fullPath, newLines.join(`
|
|
121724
|
+
`).trimEnd() + `
|
|
121725
|
+
`);
|
|
121726
|
+
}
|
|
121727
|
+
} catch {}
|
|
121728
|
+
}
|
|
121729
|
+
if (removed) {
|
|
121730
|
+
return "Removed entry from memory.";
|
|
121731
|
+
}
|
|
121732
|
+
return "Entry not found in memory.";
|
|
121733
|
+
}
|
|
121734
|
+
default: {
|
|
121735
|
+
return "Invalid action. Supported actions: record, read, forget.";
|
|
121736
|
+
}
|
|
121737
|
+
}
|
|
121738
|
+
}
|
|
121739
|
+
};
|
|
121740
|
+
});
|
|
121741
|
+
|
|
121277
121742
|
// ../../packages/tools/src/manage_task.ts
|
|
121278
121743
|
var manageTaskSchema, ManageTaskTool;
|
|
121279
121744
|
var init_manage_task = __esm(() => {
|
|
@@ -162242,7 +162707,7 @@ ${formatted}`;
|
|
|
162242
162707
|
|
|
162243
162708
|
// ../../packages/tools/src/bash-operations.ts
|
|
162244
162709
|
import { spawn as spawn2 } from "node:child_process";
|
|
162245
|
-
import
|
|
162710
|
+
import path21 from "node:path";
|
|
162246
162711
|
function trackDetachedChildPid(pid) {
|
|
162247
162712
|
trackedDetachedChildPids.add(pid);
|
|
162248
162713
|
}
|
|
@@ -162252,7 +162717,7 @@ function untrackDetachedChildPid(pid) {
|
|
|
162252
162717
|
function killProcessGroup(pid) {
|
|
162253
162718
|
if (process.platform === "win32") {
|
|
162254
162719
|
try {
|
|
162255
|
-
const child = spawn2(
|
|
162720
|
+
const child = spawn2(path21.join(process.env.SystemRoot ?? "C:\\Windows", "System32", "taskkill.exe"), ["/F", "/T", "/PID", String(pid)], {
|
|
162256
162721
|
stdio: "ignore",
|
|
162257
162722
|
detached: true,
|
|
162258
162723
|
windowsHide: true
|
|
@@ -162370,12 +162835,14 @@ var init_src4 = __esm(() => {
|
|
|
162370
162835
|
init_ask_question();
|
|
162371
162836
|
init_bash();
|
|
162372
162837
|
init_browser();
|
|
162838
|
+
init_code_intelligence();
|
|
162373
162839
|
init_deferred_registry();
|
|
162374
162840
|
init_edit();
|
|
162375
162841
|
init_edit_diff();
|
|
162376
162842
|
init_find();
|
|
162377
162843
|
init_grep();
|
|
162378
162844
|
init_ls();
|
|
162845
|
+
init_manage_memory();
|
|
162379
162846
|
init_manage_task();
|
|
162380
162847
|
init_read();
|
|
162381
162848
|
init_search_tools();
|
|
@@ -162393,11 +162860,13 @@ var init_src4 = __esm(() => {
|
|
|
162393
162860
|
init_grep();
|
|
162394
162861
|
init_ask_question();
|
|
162395
162862
|
init_manage_task();
|
|
162863
|
+
init_manage_memory();
|
|
162396
162864
|
init_browser();
|
|
162397
162865
|
init_web_search();
|
|
162398
162866
|
init_diff_preview();
|
|
162399
162867
|
init_deferred_registry();
|
|
162400
162868
|
init_search_tools();
|
|
162869
|
+
init_code_intelligence();
|
|
162401
162870
|
CORE_TOOLS = [
|
|
162402
162871
|
BashTool,
|
|
162403
162872
|
ReadFileTool,
|
|
@@ -162408,7 +162877,9 @@ var init_src4 = __esm(() => {
|
|
|
162408
162877
|
FindFilesTool,
|
|
162409
162878
|
GrepSearchTool,
|
|
162410
162879
|
AskQuestionTool,
|
|
162411
|
-
SearchToolsTool
|
|
162880
|
+
SearchToolsTool,
|
|
162881
|
+
CodeIntelligenceTool,
|
|
162882
|
+
ManageMemoryTool
|
|
162412
162883
|
];
|
|
162413
162884
|
DEFERRED_TOOLS = [ManageTaskTool, BrowserTool, WebSearchTool];
|
|
162414
162885
|
defaultDeferredRegistry.register(BrowserTool, {
|
|
@@ -162423,6 +162894,10 @@ var init_src4 = __esm(() => {
|
|
|
162423
162894
|
category: "task",
|
|
162424
162895
|
keywords: ["task", "background", "kill", "status", "process", "pid", "manage_task"]
|
|
162425
162896
|
});
|
|
162897
|
+
defaultDeferredRegistry.register(ManageMemoryTool, {
|
|
162898
|
+
category: "memory",
|
|
162899
|
+
keywords: ["memory", "rules", "conventions", "quirks", "manage_memory", "remember", "forget"]
|
|
162900
|
+
});
|
|
162426
162901
|
});
|
|
162427
162902
|
|
|
162428
162903
|
// ../../node_modules/.bun/uuid@14.0.1/node_modules/uuid/dist-node/rng.js
|
|
@@ -162627,6 +163102,64 @@ function estimateTokens(messages) {
|
|
|
162627
163102
|
return acc + Math.ceil((text.length + toolInput.length) / 4);
|
|
162628
163103
|
}, 0);
|
|
162629
163104
|
}
|
|
163105
|
+
function isSafeCompactionBoundary(messages, splitIndex, startIndex = 0) {
|
|
163106
|
+
if (splitIndex <= startIndex || splitIndex >= messages.length) {
|
|
163107
|
+
return false;
|
|
163108
|
+
}
|
|
163109
|
+
if (messages[splitIndex]?.role === "tool") {
|
|
163110
|
+
return false;
|
|
163111
|
+
}
|
|
163112
|
+
const preCallIds = new Set;
|
|
163113
|
+
for (let i = startIndex;i < splitIndex; i++) {
|
|
163114
|
+
const msg = messages[i];
|
|
163115
|
+
if (msg?.toolCalls) {
|
|
163116
|
+
for (const tc of msg.toolCalls) {
|
|
163117
|
+
if (tc.id)
|
|
163118
|
+
preCallIds.add(tc.id);
|
|
163119
|
+
}
|
|
163120
|
+
}
|
|
163121
|
+
}
|
|
163122
|
+
for (let i = splitIndex;i < messages.length; i++) {
|
|
163123
|
+
const msg = messages[i];
|
|
163124
|
+
if (msg?.role === "tool" && msg.toolCallId && preCallIds.has(msg.toolCallId)) {
|
|
163125
|
+
return false;
|
|
163126
|
+
}
|
|
163127
|
+
}
|
|
163128
|
+
const postCallIds = new Set;
|
|
163129
|
+
for (let i = splitIndex;i < messages.length; i++) {
|
|
163130
|
+
const msg = messages[i];
|
|
163131
|
+
if (msg?.toolCalls) {
|
|
163132
|
+
for (const tc of msg.toolCalls) {
|
|
163133
|
+
if (tc.id)
|
|
163134
|
+
postCallIds.add(tc.id);
|
|
163135
|
+
}
|
|
163136
|
+
}
|
|
163137
|
+
}
|
|
163138
|
+
for (let i = startIndex;i < splitIndex; i++) {
|
|
163139
|
+
const msg = messages[i];
|
|
163140
|
+
if (msg?.role === "tool" && msg.toolCallId && postCallIds.has(msg.toolCallId)) {
|
|
163141
|
+
return false;
|
|
163142
|
+
}
|
|
163143
|
+
}
|
|
163144
|
+
return true;
|
|
163145
|
+
}
|
|
163146
|
+
function findSafeCompactionBoundary(messages, targetIndex, startIndex = 1) {
|
|
163147
|
+
if (isSafeCompactionBoundary(messages, targetIndex, startIndex)) {
|
|
163148
|
+
return targetIndex;
|
|
163149
|
+
}
|
|
163150
|
+
const maxDelta = messages.length;
|
|
163151
|
+
for (let delta = 1;delta < maxDelta; delta++) {
|
|
163152
|
+
const left = targetIndex - delta;
|
|
163153
|
+
if (left > startIndex && isSafeCompactionBoundary(messages, left, startIndex)) {
|
|
163154
|
+
return left;
|
|
163155
|
+
}
|
|
163156
|
+
const right = targetIndex + delta;
|
|
163157
|
+
if (right < messages.length && isSafeCompactionBoundary(messages, right, startIndex)) {
|
|
163158
|
+
return right;
|
|
163159
|
+
}
|
|
163160
|
+
}
|
|
163161
|
+
return targetIndex;
|
|
163162
|
+
}
|
|
162630
163163
|
async function compactContextIfNeeded(messages, llm, maxTokens, modelOptions, signal) {
|
|
162631
163164
|
let limit = maxTokens;
|
|
162632
163165
|
if (!limit) {
|
|
@@ -162645,10 +163178,17 @@ async function compactContextIfNeeded(messages, llm, maxTokens, modelOptions, si
|
|
|
162645
163178
|
if (messages.length <= PROTECTED_TAIL + 1) {
|
|
162646
163179
|
return messages;
|
|
162647
163180
|
}
|
|
162648
|
-
const
|
|
162649
|
-
const
|
|
162650
|
-
const
|
|
162651
|
-
const
|
|
163181
|
+
const hasSystemPrompt = messages[0]?.role === "system";
|
|
163182
|
+
const systemPrompt = hasSystemPrompt ? messages[0] : undefined;
|
|
163183
|
+
const historyStartIndex = hasSystemPrompt ? 1 : 0;
|
|
163184
|
+
const targetIndex = messages.length - PROTECTED_TAIL;
|
|
163185
|
+
const safeSplitIndex = findSafeCompactionBoundary(messages, targetIndex, historyStartIndex);
|
|
163186
|
+
if (safeSplitIndex <= historyStartIndex || safeSplitIndex >= messages.length) {
|
|
163187
|
+
return messages;
|
|
163188
|
+
}
|
|
163189
|
+
const middleHistory = messages.slice(historyStartIndex, safeSplitIndex);
|
|
163190
|
+
const recentHistory = messages.slice(safeSplitIndex);
|
|
163191
|
+
const hasPreviousSummary = middleHistory.length > 0 && (middleHistory[0].role === "system" || middleHistory[0].role === "user") && middleHistory[0].content.includes("[COMPACTED HISTORY SUMMARY]");
|
|
162652
163192
|
let previousSummaryText = "";
|
|
162653
163193
|
let messagesToSummarize = middleHistory;
|
|
162654
163194
|
if (hasPreviousSummary) {
|
|
@@ -162656,6 +163196,9 @@ async function compactContextIfNeeded(messages, llm, maxTokens, modelOptions, si
|
|
|
162656
163196
|
`, "");
|
|
162657
163197
|
messagesToSummarize = middleHistory.slice(1);
|
|
162658
163198
|
}
|
|
163199
|
+
if (messagesToSummarize.length === 0) {
|
|
163200
|
+
return messages;
|
|
163201
|
+
}
|
|
162659
163202
|
const fileManifests = extractFileManifests(messagesToSummarize, previousSummaryText);
|
|
162660
163203
|
const historyText = messagesToSummarize.map((m) => {
|
|
162661
163204
|
let txt = `[${m.role.toUpperCase()}]: ${m.content}`;
|
|
@@ -162793,7 +163336,7 @@ ${fileManifests.modifiedFiles.join(`
|
|
|
162793
163336
|
content: `[COMPACTED HISTORY SUMMARY]
|
|
162794
163337
|
${finalSummary}`
|
|
162795
163338
|
};
|
|
162796
|
-
return [systemPrompt, summaryMessage, ...recentHistory];
|
|
163339
|
+
return systemPrompt ? [systemPrompt, summaryMessage, ...recentHistory] : [summaryMessage, ...recentHistory];
|
|
162797
163340
|
}
|
|
162798
163341
|
var DEFAULT_MAX_TOKENS = 32000, PRUNE_PROTECT_TOKENS = 40000, PRUNE_MINIMUM_SAVINGS = 15000, PRUNE_PROTECT_STEPS = 3, PRUNE_PROTECTED_TOOLS;
|
|
162799
163342
|
var init_compaction = __esm(() => {
|
|
@@ -162802,10 +163345,144 @@ var init_compaction = __esm(() => {
|
|
|
162802
163345
|
});
|
|
162803
163346
|
|
|
162804
163347
|
// ../../packages/agent/src/conversation-manager.ts
|
|
163348
|
+
import fs19 from "node:fs";
|
|
163349
|
+
import path22 from "node:path";
|
|
163350
|
+
|
|
162805
163351
|
class ConversationManager {
|
|
162806
163352
|
_messages = [];
|
|
162807
|
-
|
|
163353
|
+
workspaceRoot;
|
|
163354
|
+
constructor(initialMessagesOrOptions, options) {
|
|
163355
|
+
let initialMessages = [];
|
|
163356
|
+
let opts;
|
|
163357
|
+
if (Array.isArray(initialMessagesOrOptions)) {
|
|
163358
|
+
initialMessages = initialMessagesOrOptions;
|
|
163359
|
+
opts = options;
|
|
163360
|
+
} else if (initialMessagesOrOptions && typeof initialMessagesOrOptions === "object") {
|
|
163361
|
+
opts = initialMessagesOrOptions;
|
|
163362
|
+
}
|
|
162808
163363
|
this._messages = initialMessages;
|
|
163364
|
+
if (opts?.workspaceRoot) {
|
|
163365
|
+
this.workspaceRoot = opts.workspaceRoot;
|
|
163366
|
+
this.initSession({
|
|
163367
|
+
workspaceRoot: opts.workspaceRoot,
|
|
163368
|
+
systemPrompt: opts.systemPrompt
|
|
163369
|
+
});
|
|
163370
|
+
}
|
|
163371
|
+
}
|
|
163372
|
+
initSession(optionsOrWorkspaceRoot, systemPromptArg) {
|
|
163373
|
+
let workspaceRoot;
|
|
163374
|
+
let systemPrompt;
|
|
163375
|
+
if (typeof optionsOrWorkspaceRoot === "string") {
|
|
163376
|
+
workspaceRoot = optionsOrWorkspaceRoot;
|
|
163377
|
+
systemPrompt = systemPromptArg;
|
|
163378
|
+
} else if (optionsOrWorkspaceRoot && typeof optionsOrWorkspaceRoot === "object") {
|
|
163379
|
+
workspaceRoot = optionsOrWorkspaceRoot.workspaceRoot;
|
|
163380
|
+
systemPrompt = optionsOrWorkspaceRoot.systemPrompt;
|
|
163381
|
+
} else {
|
|
163382
|
+
workspaceRoot = this.workspaceRoot;
|
|
163383
|
+
systemPrompt = systemPromptArg;
|
|
163384
|
+
}
|
|
163385
|
+
if (workspaceRoot) {
|
|
163386
|
+
this.workspaceRoot = workspaceRoot;
|
|
163387
|
+
}
|
|
163388
|
+
const existingSystemIndex = this._messages.findIndex((m) => m.role === "system");
|
|
163389
|
+
let prompt = systemPrompt;
|
|
163390
|
+
if (prompt === undefined) {
|
|
163391
|
+
if (existingSystemIndex !== -1) {
|
|
163392
|
+
prompt = this._messages[existingSystemIndex].content;
|
|
163393
|
+
} else {
|
|
163394
|
+
prompt = "";
|
|
163395
|
+
}
|
|
163396
|
+
}
|
|
163397
|
+
const memoryContent = this.readWorkspaceMemory(workspaceRoot);
|
|
163398
|
+
let finalPrompt = prompt;
|
|
163399
|
+
if (memoryContent) {
|
|
163400
|
+
finalPrompt = this.injectMemoryBlock(prompt, memoryContent);
|
|
163401
|
+
}
|
|
163402
|
+
if (existingSystemIndex !== -1) {
|
|
163403
|
+
this._messages[existingSystemIndex].content = finalPrompt;
|
|
163404
|
+
} else if (finalPrompt) {
|
|
163405
|
+
this._messages.unshift({
|
|
163406
|
+
role: "system",
|
|
163407
|
+
content: finalPrompt,
|
|
163408
|
+
id: v4_default2(),
|
|
163409
|
+
timestamp: Date.now()
|
|
163410
|
+
});
|
|
163411
|
+
}
|
|
163412
|
+
return finalPrompt;
|
|
163413
|
+
}
|
|
163414
|
+
readWorkspaceMemory(workspaceRoot) {
|
|
163415
|
+
if (!workspaceRoot)
|
|
163416
|
+
return "";
|
|
163417
|
+
const memoryCandidates = [
|
|
163418
|
+
path22.join(workspaceRoot, ".december", "memory.md"),
|
|
163419
|
+
path22.join(workspaceRoot, "MEMORY.md"),
|
|
163420
|
+
path22.join(workspaceRoot, ".december", "MEMORY.md"),
|
|
163421
|
+
path22.join(workspaceRoot, "memory.md")
|
|
163422
|
+
];
|
|
163423
|
+
const rulesCandidates = [
|
|
163424
|
+
path22.join(workspaceRoot, "RULES.md"),
|
|
163425
|
+
path22.join(workspaceRoot, ".december", "rules.md"),
|
|
163426
|
+
path22.join(workspaceRoot, ".december", "RULES.md"),
|
|
163427
|
+
path22.join(workspaceRoot, "rules.md")
|
|
163428
|
+
];
|
|
163429
|
+
let memoryText = "";
|
|
163430
|
+
for (const candidate of memoryCandidates) {
|
|
163431
|
+
try {
|
|
163432
|
+
if (fs19.existsSync(candidate) && fs19.statSync(candidate).isFile()) {
|
|
163433
|
+
const content = fs19.readFileSync(candidate, "utf8").trim();
|
|
163434
|
+
if (content) {
|
|
163435
|
+
memoryText = content;
|
|
163436
|
+
break;
|
|
163437
|
+
}
|
|
163438
|
+
}
|
|
163439
|
+
} catch {}
|
|
163440
|
+
}
|
|
163441
|
+
let rulesText = "";
|
|
163442
|
+
for (const candidate of rulesCandidates) {
|
|
163443
|
+
try {
|
|
163444
|
+
if (fs19.existsSync(candidate) && fs19.statSync(candidate).isFile()) {
|
|
163445
|
+
const content = fs19.readFileSync(candidate, "utf8").trim();
|
|
163446
|
+
if (content) {
|
|
163447
|
+
rulesText = content;
|
|
163448
|
+
break;
|
|
163449
|
+
}
|
|
163450
|
+
}
|
|
163451
|
+
} catch {}
|
|
163452
|
+
}
|
|
163453
|
+
const parts = [];
|
|
163454
|
+
if (memoryText)
|
|
163455
|
+
parts.push(memoryText);
|
|
163456
|
+
if (rulesText && rulesText !== memoryText)
|
|
163457
|
+
parts.push(rulesText);
|
|
163458
|
+
return parts.join(`
|
|
163459
|
+
|
|
163460
|
+
`).trim();
|
|
163461
|
+
}
|
|
163462
|
+
injectMemoryBlock(prompt, memoryContent) {
|
|
163463
|
+
if (!memoryContent.trim())
|
|
163464
|
+
return prompt;
|
|
163465
|
+
if (prompt.includes("<project_memory>"))
|
|
163466
|
+
return prompt;
|
|
163467
|
+
const block = `<project_memory>
|
|
163468
|
+
${memoryContent.trim()}
|
|
163469
|
+
</project_memory>`;
|
|
163470
|
+
if (!prompt)
|
|
163471
|
+
return block;
|
|
163472
|
+
if (prompt.includes(`
|
|
163473
|
+
|
|
163474
|
+
Current date:`)) {
|
|
163475
|
+
return prompt.replace(`
|
|
163476
|
+
|
|
163477
|
+
Current date:`, `
|
|
163478
|
+
|
|
163479
|
+
${block}
|
|
163480
|
+
|
|
163481
|
+
Current date:`);
|
|
163482
|
+
}
|
|
163483
|
+
return `${prompt}
|
|
163484
|
+
|
|
163485
|
+
${block}`;
|
|
162809
163486
|
}
|
|
162810
163487
|
get messages() {
|
|
162811
163488
|
return this._messages;
|
|
@@ -163560,10 +164237,10 @@ class LangfuseMedia {
|
|
|
163560
164237
|
this._contentType = contentType;
|
|
163561
164238
|
this._source = "bytes";
|
|
163562
164239
|
} else if (filePath && contentType) {
|
|
163563
|
-
if (!
|
|
164240
|
+
if (!fs20) {
|
|
163564
164241
|
throw new Error("File system support is not available in this environment");
|
|
163565
164242
|
}
|
|
163566
|
-
if (!
|
|
164243
|
+
if (!fs20.existsSync(filePath)) {
|
|
163567
164244
|
throw new Error(`File at path ${filePath} does not exist`);
|
|
163568
164245
|
}
|
|
163569
164246
|
this._contentBytes = this.readFile(filePath);
|
|
@@ -163575,10 +164252,10 @@ class LangfuseMedia {
|
|
|
163575
164252
|
}
|
|
163576
164253
|
readFile(filePath) {
|
|
163577
164254
|
try {
|
|
163578
|
-
if (!
|
|
164255
|
+
if (!fs20) {
|
|
163579
164256
|
throw new Error("File system support is not available in this environment");
|
|
163580
164257
|
}
|
|
163581
|
-
return
|
|
164258
|
+
return fs20.readFileSync(filePath);
|
|
163582
164259
|
} catch (error) {
|
|
163583
164260
|
console.error(`Error reading file at path ${filePath}`, error);
|
|
163584
164261
|
return;
|
|
@@ -164700,7 +165377,7 @@ var DEFAULT_PROMPT_CACHE_TTL_SECONDS = 60, LangfusePersistedProperty, ChatMessag
|
|
|
164700
165377
|
}
|
|
164701
165378
|
});
|
|
164702
165379
|
return queryParams.toString();
|
|
164703
|
-
}, utils, common_release_envs,
|
|
165380
|
+
}, utils, common_release_envs, fs20 = null, cryptoModule = null, dynamicImport = (module) => {
|
|
164704
165381
|
return import(module);
|
|
164705
165382
|
}, MAX_EVENT_SIZE_BYTES, MAX_BATCH_SIZE_BYTES, ENVIRONMENT_PATTERN, WHITELISTED_LANGFUSE_INTERNAL_ENVIRONMENTS, LangfuseFetchHttpError, LangfuseFetchNetworkError, SUPPORT_URL = "https://langfuse.com/support", API_DOCS_URL = "https://api.reference.langfuse.com", RBAC_DOCS_URL = "https://langfuse.com/docs/rbac", INSTALLATION_DOCS_URL = "https://langfuse.com/docs/sdk/typescript/guide", RATE_LIMITS_URL = "https://langfuse.com/faq/all/api-limits", NPM_PACKAGE_URL = "https://www.npmjs.com/package/langfuse", updatePromptResponse, defaultServerErrorPrompt, defaultErrorResponse, errorResponseByCode, LangfuseCore, LangfuseTraceClient, LangfuseObservationClient, LangfuseSpanClient, LangfuseGenerationClient, LangfuseEventClient;
|
|
164706
165383
|
var init_lib = __esm(() => {
|
|
@@ -164879,12 +165556,12 @@ var init_lib = __esm(() => {
|
|
|
164879
165556
|
];
|
|
164880
165557
|
if (typeof globalThis.Deno !== "undefined") {
|
|
164881
165558
|
Promise.all([dynamicImport("node:fs"), dynamicImport("node:crypto")]).then(([importedFs, importedCrypto]) => {
|
|
164882
|
-
|
|
165559
|
+
fs20 = importedFs;
|
|
164883
165560
|
cryptoModule = importedCrypto;
|
|
164884
165561
|
}).catch();
|
|
164885
165562
|
} else if (typeof process !== "undefined" && process.versions?.node) {
|
|
164886
165563
|
Promise.all([dynamicImport("fs"), dynamicImport("crypto")]).then(([importedFs, importedCrypto]) => {
|
|
164887
|
-
|
|
165564
|
+
fs20 = importedFs;
|
|
164888
165565
|
cryptoModule = importedCrypto;
|
|
164889
165566
|
}).catch();
|
|
164890
165567
|
} else if (typeof crypto !== "undefined") {
|
|
@@ -166387,29 +167064,73 @@ var init_tracer_factory = __esm(() => {
|
|
|
166387
167064
|
});
|
|
166388
167065
|
|
|
166389
167066
|
// ../../packages/agent/src/utils/evaporation.ts
|
|
166390
|
-
function
|
|
167067
|
+
function isErrorToolOutput(content) {
|
|
167068
|
+
const lower = content.toLowerCase();
|
|
167069
|
+
return content.includes("[Tool Error]") || lower.includes("error:") || lower.includes("command failed") || lower.includes("exit code 1") || lower.includes("exit code 2") || lower.includes("failed:") || lower.includes("traceback (most recent call last)") || lower.includes("exception:") || lower.includes("fatal:") || lower.includes("panic:") || lower.includes("syntaxerror");
|
|
167070
|
+
}
|
|
167071
|
+
function truncateLargeToolOutput(rawContent, maxBytes = 6 * 1024, headLines = 20, tailLines = 20) {
|
|
167072
|
+
const byteLength = Buffer.byteLength(rawContent, "utf8");
|
|
167073
|
+
if (byteLength <= maxBytes) {
|
|
167074
|
+
return rawContent;
|
|
167075
|
+
}
|
|
167076
|
+
if (isErrorToolOutput(rawContent)) {
|
|
167077
|
+
return rawContent;
|
|
167078
|
+
}
|
|
167079
|
+
const lines = rawContent.split(`
|
|
167080
|
+
`);
|
|
167081
|
+
if (lines.length <= headLines + tailLines) {
|
|
167082
|
+
return rawContent;
|
|
167083
|
+
}
|
|
167084
|
+
const head = lines.slice(0, headLines).join(`
|
|
167085
|
+
`);
|
|
167086
|
+
const tail = lines.slice(lines.length - tailLines).join(`
|
|
167087
|
+
`);
|
|
167088
|
+
const omittedLines = lines.length - headLines - tailLines;
|
|
167089
|
+
const omittedBytes = byteLength - Buffer.byteLength(head, "utf8") - Buffer.byteLength(tail, "utf8");
|
|
167090
|
+
const omittedKb = (omittedBytes / 1024).toFixed(1);
|
|
167091
|
+
const banner = `
|
|
167092
|
+
|
|
167093
|
+
[... ${omittedLines} lines truncated (${omittedKb} KB) ...]
|
|
167094
|
+
|
|
167095
|
+
`;
|
|
167096
|
+
return head + banner + tail;
|
|
167097
|
+
}
|
|
167098
|
+
function evaporateStaleToolOutputs(messages, preserveRecentTurnsOrOptions = 3, preserveRecentStepsArg) {
|
|
166391
167099
|
if (!messages || messages.length === 0)
|
|
166392
167100
|
return [];
|
|
167101
|
+
let preserveRecentTurns = 3;
|
|
167102
|
+
let preserveRecentSteps = 2;
|
|
167103
|
+
let maxOutputSize = 6 * 1024;
|
|
167104
|
+
let headLines = 20;
|
|
167105
|
+
let tailLines = 20;
|
|
167106
|
+
if (typeof preserveRecentTurnsOrOptions === "number") {
|
|
167107
|
+
preserveRecentTurns = preserveRecentTurnsOrOptions;
|
|
167108
|
+
if (preserveRecentStepsArg !== undefined) {
|
|
167109
|
+
preserveRecentSteps = preserveRecentStepsArg;
|
|
167110
|
+
}
|
|
167111
|
+
} else if (typeof preserveRecentTurnsOrOptions === "object") {
|
|
167112
|
+
preserveRecentTurns = preserveRecentTurnsOrOptions.preserveRecentTurns ?? 3;
|
|
167113
|
+
preserveRecentSteps = preserveRecentTurnsOrOptions.preserveRecentSteps ?? 2;
|
|
167114
|
+
maxOutputSize = preserveRecentTurnsOrOptions.maxOutputSize ?? 6 * 1024;
|
|
167115
|
+
headLines = preserveRecentTurnsOrOptions.headLines ?? 20;
|
|
167116
|
+
tailLines = preserveRecentTurnsOrOptions.tailLines ?? 20;
|
|
167117
|
+
}
|
|
166393
167118
|
let userTurnsSeen = 0;
|
|
166394
|
-
let
|
|
167119
|
+
let agentStepsSeen = 0;
|
|
167120
|
+
const isStale = new Array(messages.length).fill(false);
|
|
166395
167121
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
166396
167122
|
const msg = messages[i];
|
|
167123
|
+
if (!msg)
|
|
167124
|
+
continue;
|
|
166397
167125
|
if (msg.role === "user" && !msg.isUI) {
|
|
166398
167126
|
userTurnsSeen++;
|
|
166399
|
-
if (userTurnsSeen >= preserveRecentTurns) {
|
|
166400
|
-
cutoffIndex = i;
|
|
166401
|
-
break;
|
|
166402
|
-
}
|
|
166403
167127
|
}
|
|
166404
|
-
|
|
166405
|
-
|
|
166406
|
-
|
|
166407
|
-
|
|
166408
|
-
|
|
166409
|
-
|
|
166410
|
-
toolCalls: m.toolCalls,
|
|
166411
|
-
toolCallId: m.toolCallId
|
|
166412
|
-
}));
|
|
167128
|
+
if (msg.role === "assistant" && (msg.toolCalls?.length || 0) > 0) {
|
|
167129
|
+
agentStepsSeen++;
|
|
167130
|
+
}
|
|
167131
|
+
if (userTurnsSeen >= preserveRecentTurns || agentStepsSeen >= preserveRecentSteps) {
|
|
167132
|
+
isStale[i] = true;
|
|
167133
|
+
}
|
|
166413
167134
|
}
|
|
166414
167135
|
return messages.map((msg, idx) => {
|
|
166415
167136
|
const baseMsg = {
|
|
@@ -166419,27 +167140,37 @@ function evaporateStaleToolOutputs(messages, preserveRecentTurns = 3) {
|
|
|
166419
167140
|
toolCalls: msg.toolCalls,
|
|
166420
167141
|
toolCallId: msg.toolCallId
|
|
166421
167142
|
};
|
|
166422
|
-
if (
|
|
167143
|
+
if (msg.role !== "tool") {
|
|
166423
167144
|
return baseMsg;
|
|
166424
167145
|
}
|
|
166425
|
-
|
|
166426
|
-
|
|
166427
|
-
|
|
166428
|
-
|
|
166429
|
-
|
|
166430
|
-
|
|
166431
|
-
|
|
166432
|
-
|
|
167146
|
+
const rawContent = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
|
|
167147
|
+
if (rawContent.length < 200) {
|
|
167148
|
+
return baseMsg;
|
|
167149
|
+
}
|
|
167150
|
+
if (isErrorToolOutput(rawContent)) {
|
|
167151
|
+
return baseMsg;
|
|
167152
|
+
}
|
|
167153
|
+
if (rawContent.startsWith("[Tool Output Evaporated:") || rawContent.startsWith("[tool output microcompacted:") || rawContent.startsWith("[Old tool result content cleared]")) {
|
|
167154
|
+
return baseMsg;
|
|
167155
|
+
}
|
|
167156
|
+
if (isStale[idx]) {
|
|
166433
167157
|
const lines = rawContent.split(`
|
|
166434
167158
|
`);
|
|
166435
167159
|
const lineCount = lines.length;
|
|
166436
167160
|
const byteSize = (Buffer.byteLength(rawContent, "utf8") / 1024).toFixed(1);
|
|
166437
|
-
const tombstone = `[Tool Output Evaporated: ${lineCount} lines (${byteSize} KB). Content previously processed by assistant.]`;
|
|
167161
|
+
const tombstone = `[Tool Output Evaporated: ${lineCount} lines (${byteSize} KB). exit code 0. Content previously processed by assistant.]`;
|
|
166438
167162
|
return {
|
|
166439
167163
|
...baseMsg,
|
|
166440
167164
|
content: tombstone
|
|
166441
167165
|
};
|
|
166442
167166
|
}
|
|
167167
|
+
const truncated = truncateLargeToolOutput(rawContent, maxOutputSize, headLines, tailLines);
|
|
167168
|
+
if (truncated !== rawContent) {
|
|
167169
|
+
return {
|
|
167170
|
+
...baseMsg,
|
|
167171
|
+
content: truncated
|
|
167172
|
+
};
|
|
167173
|
+
}
|
|
166443
167174
|
return baseMsg;
|
|
166444
167175
|
});
|
|
166445
167176
|
}
|
|
@@ -166504,8 +167235,14 @@ class Agent2 {
|
|
|
166504
167235
|
this.convertToLlm = config.convertToLlm || this.defaultConvertToLlm;
|
|
166505
167236
|
this.steeringQueue = new PendingMessageQueue(config.steeringMode || "all");
|
|
166506
167237
|
this.followUpQueue = new PendingMessageQueue(config.followUpMode || "all");
|
|
166507
|
-
this.conversation = new ConversationManager;
|
|
166508
167238
|
this.workspaceDir = config.workspaceDir;
|
|
167239
|
+
this.conversation = new ConversationManager([], {
|
|
167240
|
+
workspaceRoot: config.workspaceDir
|
|
167241
|
+
});
|
|
167242
|
+
this.systemPrompt = this.conversation.initSession({
|
|
167243
|
+
workspaceRoot: config.workspaceDir,
|
|
167244
|
+
systemPrompt: this.systemPrompt
|
|
167245
|
+
});
|
|
166509
167246
|
this.logsDir = config.logsDir;
|
|
166510
167247
|
this.disableLogging = config.disableLogging || false;
|
|
166511
167248
|
this.deferredRegistry = config.deferredRegistry || new DeferredToolRegistry;
|
|
@@ -166523,10 +167260,12 @@ class Agent2 {
|
|
|
166523
167260
|
this.deferredRegistry.register(tool);
|
|
166524
167261
|
}
|
|
166525
167262
|
}
|
|
166526
|
-
this.conversation.
|
|
166527
|
-
|
|
166528
|
-
|
|
166529
|
-
|
|
167263
|
+
if (this.conversation.messages.length === 0) {
|
|
167264
|
+
this.conversation.addMessage({
|
|
167265
|
+
role: "system",
|
|
167266
|
+
content: this.systemPrompt
|
|
167267
|
+
});
|
|
167268
|
+
}
|
|
166530
167269
|
}
|
|
166531
167270
|
get messages() {
|
|
166532
167271
|
return this.conversation.messages;
|
|
@@ -166536,16 +167275,26 @@ class Agent2 {
|
|
|
166536
167275
|
}
|
|
166537
167276
|
defaultConvertToLlm(messages) {
|
|
166538
167277
|
const filtered = messages.filter((m) => !m.isUI);
|
|
166539
|
-
const evaporated = evaporateStaleToolOutputs(filtered,
|
|
167278
|
+
const evaporated = evaporateStaleToolOutputs(filtered, {
|
|
167279
|
+
preserveRecentTurns: 3,
|
|
167280
|
+
preserveRecentSteps: 2,
|
|
167281
|
+
maxOutputSize: 6 * 1024
|
|
167282
|
+
});
|
|
166540
167283
|
const merged = [];
|
|
166541
|
-
for (
|
|
167284
|
+
for (let i = 0;i < evaporated.length; i++) {
|
|
167285
|
+
const msg = evaporated[i];
|
|
167286
|
+
let role = msg.role;
|
|
167287
|
+
const content = msg.content;
|
|
167288
|
+
if (role === "system" && i > 0 && content.includes("[COMPACTED HISTORY SUMMARY]")) {
|
|
167289
|
+
role = "user";
|
|
167290
|
+
}
|
|
166542
167291
|
const prev = merged[merged.length - 1];
|
|
166543
|
-
if (prev && prev.role === "user" &&
|
|
167292
|
+
if (prev && prev.role === "user" && role === "user" && !prev.toolCalls && !msg.toolCalls) {
|
|
166544
167293
|
prev.content = `${prev.content}
|
|
166545
167294
|
|
|
166546
|
-
${
|
|
167295
|
+
${content}`;
|
|
166547
167296
|
} else {
|
|
166548
|
-
merged.push({ ...msg });
|
|
167297
|
+
merged.push({ ...msg, role, content });
|
|
166549
167298
|
}
|
|
166550
167299
|
}
|
|
166551
167300
|
return merged;
|
|
@@ -166859,9 +167608,9 @@ var init_p_retry = __esm(() => {
|
|
|
166859
167608
|
});
|
|
166860
167609
|
|
|
166861
167610
|
// ../../packages/agent/src/utils/request-logger.ts
|
|
166862
|
-
import
|
|
167611
|
+
import fs21 from "node:fs";
|
|
166863
167612
|
import os11 from "node:os";
|
|
166864
|
-
import
|
|
167613
|
+
import path23 from "node:path";
|
|
166865
167614
|
function createRequestLogEntry(params) {
|
|
166866
167615
|
const {
|
|
166867
167616
|
turn,
|
|
@@ -166914,11 +167663,11 @@ function getGlobalConfigDir() {
|
|
|
166914
167663
|
const home = process.env.HOME || os11.homedir();
|
|
166915
167664
|
const isTestEnv = !!process.env.VITEST;
|
|
166916
167665
|
if (isTestEnv && home === os11.homedir()) {
|
|
166917
|
-
return
|
|
167666
|
+
return path23.join(os11.tmpdir(), "december-test-config", ".december");
|
|
166918
167667
|
}
|
|
166919
|
-
const canonicalDir =
|
|
166920
|
-
const legacyDir =
|
|
166921
|
-
if (
|
|
167668
|
+
const canonicalDir = path23.join(home, ".december");
|
|
167669
|
+
const legacyDir = path23.join(home, ".config", "december");
|
|
167670
|
+
if (fs21.existsSync(canonicalDir) || !fs21.existsSync(legacyDir)) {
|
|
166922
167671
|
return canonicalDir;
|
|
166923
167672
|
}
|
|
166924
167673
|
return legacyDir;
|
|
@@ -166928,7 +167677,7 @@ function getLogsDir(customDir) {
|
|
|
166928
167677
|
return customDir;
|
|
166929
167678
|
if (process.env.DECEMBER_LOGS_DIR)
|
|
166930
167679
|
return process.env.DECEMBER_LOGS_DIR;
|
|
166931
|
-
return
|
|
167680
|
+
return path23.join(getGlobalConfigDir(), "logs");
|
|
166932
167681
|
}
|
|
166933
167682
|
function getSessionLogPath(sessionIdOrLogsDir, logsDirOrSessionId) {
|
|
166934
167683
|
if (!sessionIdOrLogsDir && !logsDirOrSessionId)
|
|
@@ -166936,7 +167685,7 @@ function getSessionLogPath(sessionIdOrLogsDir, logsDirOrSessionId) {
|
|
|
166936
167685
|
let sessionId;
|
|
166937
167686
|
let customDir;
|
|
166938
167687
|
if (logsDirOrSessionId) {
|
|
166939
|
-
if (sessionIdOrLogsDir.startsWith("session-") || !sessionIdOrLogsDir.includes(
|
|
167688
|
+
if (sessionIdOrLogsDir.startsWith("session-") || !sessionIdOrLogsDir.includes(path23.sep) && logsDirOrSessionId.includes(path23.sep)) {
|
|
166940
167689
|
sessionId = sessionIdOrLogsDir;
|
|
166941
167690
|
customDir = logsDirOrSessionId;
|
|
166942
167691
|
} else {
|
|
@@ -166947,7 +167696,7 @@ function getSessionLogPath(sessionIdOrLogsDir, logsDirOrSessionId) {
|
|
|
166947
167696
|
sessionId = sessionIdOrLogsDir;
|
|
166948
167697
|
}
|
|
166949
167698
|
const cleanSessionId = sessionId.startsWith("session-") ? sessionId : `session-${sessionId}`;
|
|
166950
|
-
return
|
|
167699
|
+
return path23.join(getLogsDir(customDir), `${cleanSessionId}.jsonl`);
|
|
166951
167700
|
}
|
|
166952
167701
|
async function appendTurnLog(arg1, arg2, arg3) {
|
|
166953
167702
|
try {
|
|
@@ -166970,11 +167719,11 @@ async function appendTurnLog(arg1, arg2, arg3) {
|
|
|
166970
167719
|
const logFile = getSessionLogPath(sessionId, logsDir);
|
|
166971
167720
|
if (!logFile)
|
|
166972
167721
|
return;
|
|
166973
|
-
const dir =
|
|
166974
|
-
await
|
|
167722
|
+
const dir = path23.dirname(logFile);
|
|
167723
|
+
await fs21.promises.mkdir(dir, { recursive: true });
|
|
166975
167724
|
const line = JSON.stringify(entry) + `
|
|
166976
167725
|
`;
|
|
166977
|
-
await
|
|
167726
|
+
await fs21.promises.appendFile(logFile, line, "utf8");
|
|
166978
167727
|
} catch {}
|
|
166979
167728
|
}
|
|
166980
167729
|
var init_request_logger = __esm(() => {
|
|
@@ -167753,17 +168502,17 @@ var init_agent_loop = __esm(() => {
|
|
|
167753
168502
|
]);
|
|
167754
168503
|
});
|
|
167755
168504
|
// ../../packages/agent/src/skills/skill-subagent.ts
|
|
167756
|
-
import
|
|
168505
|
+
import fs22 from "node:fs";
|
|
167757
168506
|
async function executeSkillInSubagent(options) {
|
|
167758
168507
|
const { skill, args = [], task, parentAgent, signal, onEvent } = options;
|
|
167759
168508
|
let rawBody = skill.content || "";
|
|
167760
|
-
if (!rawBody && skill.entryFilePath &&
|
|
168509
|
+
if (!rawBody && skill.entryFilePath && fs22.existsSync(skill.entryFilePath)) {
|
|
167761
168510
|
try {
|
|
167762
168511
|
const parsed = parseSkillFile(skill.entryFilePath);
|
|
167763
168512
|
rawBody = parsed.body;
|
|
167764
168513
|
} catch {
|
|
167765
168514
|
try {
|
|
167766
|
-
rawBody =
|
|
168515
|
+
rawBody = fs22.readFileSync(skill.entryFilePath, "utf8");
|
|
167767
168516
|
} catch (err) {
|
|
167768
168517
|
return {
|
|
167769
168518
|
success: false,
|
|
@@ -167911,9 +168660,9 @@ var init_run_skill_tool = __esm(() => {
|
|
|
167911
168660
|
});
|
|
167912
168661
|
|
|
167913
168662
|
// ../../packages/agent/src/harness/agent-harness.ts
|
|
167914
|
-
import
|
|
168663
|
+
import fs23 from "node:fs";
|
|
167915
168664
|
import os12 from "node:os";
|
|
167916
|
-
import
|
|
168665
|
+
import path24 from "node:path";
|
|
167917
168666
|
function isReasoningModel(model, thinkingLevel) {
|
|
167918
168667
|
if (thinkingLevel === "off") {
|
|
167919
168668
|
return false;
|
|
@@ -167975,22 +168724,22 @@ function discoverProjectRules(startDir, rootBoundary) {
|
|
|
167975
168724
|
"AGENTS.override.md",
|
|
167976
168725
|
"AGENTS.md",
|
|
167977
168726
|
"CLAUDE.md",
|
|
167978
|
-
|
|
167979
|
-
|
|
168727
|
+
path24.join(".december", "rules.md"),
|
|
168728
|
+
path24.join(".december", "AGENTS.md")
|
|
167980
168729
|
];
|
|
167981
168730
|
const seen = new Set;
|
|
167982
|
-
let current =
|
|
167983
|
-
const boundary = rootBoundary ?
|
|
168731
|
+
let current = path24.resolve(startDir);
|
|
168732
|
+
const boundary = rootBoundary ? path24.resolve(rootBoundary) : path24.parse(current).root;
|
|
167984
168733
|
const collectedFiles = [];
|
|
167985
168734
|
while (true) {
|
|
167986
168735
|
for (const name of candidateNames) {
|
|
167987
|
-
const candidatePath =
|
|
167988
|
-
if (
|
|
168736
|
+
const candidatePath = path24.join(current, name);
|
|
168737
|
+
if (fs23.existsSync(candidatePath)) {
|
|
167989
168738
|
try {
|
|
167990
|
-
if (
|
|
168739
|
+
if (fs23.statSync(candidatePath).isFile()) {
|
|
167991
168740
|
if (!seen.has(candidatePath)) {
|
|
167992
168741
|
seen.add(candidatePath);
|
|
167993
|
-
const content =
|
|
168742
|
+
const content = fs23.readFileSync(candidatePath, "utf8").trim();
|
|
167994
168743
|
if (content) {
|
|
167995
168744
|
collectedFiles.unshift({ path: candidatePath, content });
|
|
167996
168745
|
}
|
|
@@ -168001,7 +168750,7 @@ function discoverProjectRules(startDir, rootBoundary) {
|
|
|
168001
168750
|
}
|
|
168002
168751
|
if (current === boundary)
|
|
168003
168752
|
break;
|
|
168004
|
-
const parent =
|
|
168753
|
+
const parent = path24.dirname(current);
|
|
168005
168754
|
if (parent === current)
|
|
168006
168755
|
break;
|
|
168007
168756
|
current = parent;
|
|
@@ -168009,17 +168758,17 @@ function discoverProjectRules(startDir, rootBoundary) {
|
|
|
168009
168758
|
const home = process.env.HOME || process.env.USERPROFILE || os12.homedir();
|
|
168010
168759
|
const globalCandidateDirs = [
|
|
168011
168760
|
process.env.DECEMBER_CONFIG_DIR,
|
|
168012
|
-
|
|
168013
|
-
|
|
168761
|
+
path24.join(home, ".december"),
|
|
168762
|
+
path24.join(home, ".config", "december")
|
|
168014
168763
|
].filter((dir) => !!dir);
|
|
168015
168764
|
for (const globalDir of globalCandidateDirs) {
|
|
168016
168765
|
for (const candidate of ["rules.md", "AGENTS.md"]) {
|
|
168017
|
-
const globalPath =
|
|
168018
|
-
if (
|
|
168766
|
+
const globalPath = path24.join(globalDir, candidate);
|
|
168767
|
+
if (fs23.existsSync(globalPath) && !seen.has(globalPath)) {
|
|
168019
168768
|
try {
|
|
168020
|
-
if (
|
|
168769
|
+
if (fs23.statSync(globalPath).isFile()) {
|
|
168021
168770
|
seen.add(globalPath);
|
|
168022
|
-
const content =
|
|
168771
|
+
const content = fs23.readFileSync(globalPath, "utf8").trim();
|
|
168023
168772
|
if (content) {
|
|
168024
168773
|
collectedFiles.unshift({ path: globalPath, content });
|
|
168025
168774
|
}
|
|
@@ -168275,6 +169024,12 @@ var init_agent_harness = __esm(() => {
|
|
|
168275
169024
|
guidelines: [
|
|
168276
169025
|
"Use 'run_skill' to delegate complex procedural workflows or specialized domain tasks to an isolated subagent, keeping the main conversation context clean."
|
|
168277
169026
|
]
|
|
169027
|
+
},
|
|
169028
|
+
manage_memory: {
|
|
169029
|
+
snippet: "Record, read, or prune persistent workspace rules and memories",
|
|
169030
|
+
guidelines: [
|
|
169031
|
+
"Use 'manage_memory' to record learned conventions, build/test commands, architecture notes, and quirks into persistent workspace memory."
|
|
169032
|
+
]
|
|
168278
169033
|
}
|
|
168279
169034
|
};
|
|
168280
169035
|
});
|
|
@@ -168289,10 +169044,383 @@ var init_telemetry = __esm(() => {
|
|
|
168289
169044
|
init_tracer_factory();
|
|
168290
169045
|
});
|
|
168291
169046
|
|
|
169047
|
+
// ../../packages/agent/src/lsp-client.ts
|
|
169048
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
169049
|
+
import fs24 from "node:fs";
|
|
169050
|
+
import path25 from "node:path";
|
|
169051
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
169052
|
+
|
|
169053
|
+
class LspClient {
|
|
169054
|
+
workspaceRoot;
|
|
169055
|
+
binaryPath;
|
|
169056
|
+
requestTimeoutMs;
|
|
169057
|
+
child = null;
|
|
169058
|
+
nextId = 1;
|
|
169059
|
+
pendingRequests = new Map;
|
|
169060
|
+
buffer = Buffer.alloc(0);
|
|
169061
|
+
diagnosticsByUri = new Map;
|
|
169062
|
+
openedDocuments = new Set;
|
|
169063
|
+
initPromise = null;
|
|
169064
|
+
isShutdown = false;
|
|
169065
|
+
constructor(options) {
|
|
169066
|
+
this.workspaceRoot = path25.resolve(options.workspaceRoot);
|
|
169067
|
+
this.binaryPath = options.binaryPath;
|
|
169068
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 15000;
|
|
169069
|
+
}
|
|
169070
|
+
async start() {
|
|
169071
|
+
if (this.initPromise) {
|
|
169072
|
+
return this.initPromise;
|
|
169073
|
+
}
|
|
169074
|
+
this.initPromise = this.initInternal();
|
|
169075
|
+
return this.initPromise;
|
|
169076
|
+
}
|
|
169077
|
+
findBinary() {
|
|
169078
|
+
if (this.binaryPath && fs24.existsSync(this.binaryPath)) {
|
|
169079
|
+
return this.binaryPath;
|
|
169080
|
+
}
|
|
169081
|
+
const candidatePaths = [
|
|
169082
|
+
path25.resolve(this.workspaceRoot, "node_modules/.bin/typescript-language-server"),
|
|
169083
|
+
path25.resolve(process.cwd(), "node_modules/.bin/typescript-language-server"),
|
|
169084
|
+
path25.resolve(process.cwd(), "node_modules/typescript-language-server/lib/cli.mjs")
|
|
169085
|
+
];
|
|
169086
|
+
for (const candidate of candidatePaths) {
|
|
169087
|
+
if (fs24.existsSync(candidate)) {
|
|
169088
|
+
return candidate;
|
|
169089
|
+
}
|
|
169090
|
+
}
|
|
169091
|
+
return "typescript-language-server";
|
|
169092
|
+
}
|
|
169093
|
+
async initInternal() {
|
|
169094
|
+
const bin = this.findBinary();
|
|
169095
|
+
this.child = spawn3(bin, ["--stdio"], {
|
|
169096
|
+
cwd: this.workspaceRoot,
|
|
169097
|
+
env: { ...process.env },
|
|
169098
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
169099
|
+
});
|
|
169100
|
+
this.child.stdout?.on("data", (chunk) => {
|
|
169101
|
+
this.handleStdout(chunk);
|
|
169102
|
+
});
|
|
169103
|
+
this.child.stderr?.on("data", (_chunk) => {});
|
|
169104
|
+
this.child.on("error", (err) => {
|
|
169105
|
+
this.rejectAllPending(new Error(`LSP process error: ${err.message}`));
|
|
169106
|
+
});
|
|
169107
|
+
this.child.on("exit", (code) => {
|
|
169108
|
+
this.rejectAllPending(new Error(`LSP process exited with code ${code}`));
|
|
169109
|
+
this.child = null;
|
|
169110
|
+
this.initPromise = null;
|
|
169111
|
+
});
|
|
169112
|
+
const rootUri = pathToFileURL(this.workspaceRoot).toString();
|
|
169113
|
+
await this.sendRequest("initialize", {
|
|
169114
|
+
processId: process.pid,
|
|
169115
|
+
rootUri,
|
|
169116
|
+
rootPath: this.workspaceRoot,
|
|
169117
|
+
capabilities: {
|
|
169118
|
+
textDocument: {
|
|
169119
|
+
definition: { dynamicRegistration: false, linkSupport: true },
|
|
169120
|
+
references: { dynamicRegistration: false },
|
|
169121
|
+
documentSymbol: {
|
|
169122
|
+
dynamicRegistration: false,
|
|
169123
|
+
hierarchicalDocumentSymbolSupport: true
|
|
169124
|
+
},
|
|
169125
|
+
synchronization: {
|
|
169126
|
+
dynamicRegistration: false,
|
|
169127
|
+
willSave: false,
|
|
169128
|
+
didSave: true
|
|
169129
|
+
}
|
|
169130
|
+
}
|
|
169131
|
+
}
|
|
169132
|
+
});
|
|
169133
|
+
this.sendNotification("initialized", {});
|
|
169134
|
+
}
|
|
169135
|
+
handleStdout(chunk) {
|
|
169136
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
169137
|
+
while (true) {
|
|
169138
|
+
const headerEnd = this.buffer.indexOf(`\r
|
|
169139
|
+
\r
|
|
169140
|
+
`);
|
|
169141
|
+
if (headerEnd === -1)
|
|
169142
|
+
break;
|
|
169143
|
+
const headerStr = this.buffer.subarray(0, headerEnd).toString("utf8");
|
|
169144
|
+
const match = headerStr.match(/Content-Length:\s*(\d+)/i);
|
|
169145
|
+
if (!match) {
|
|
169146
|
+
this.buffer = this.buffer.subarray(headerEnd + 4);
|
|
169147
|
+
continue;
|
|
169148
|
+
}
|
|
169149
|
+
const contentLength = parseInt(match[1], 10);
|
|
169150
|
+
const totalMsgLength = headerEnd + 4 + contentLength;
|
|
169151
|
+
if (this.buffer.length < totalMsgLength)
|
|
169152
|
+
break;
|
|
169153
|
+
const body = this.buffer.subarray(headerEnd + 4, totalMsgLength).toString("utf8");
|
|
169154
|
+
this.buffer = this.buffer.subarray(totalMsgLength);
|
|
169155
|
+
try {
|
|
169156
|
+
const msg = JSON.parse(body);
|
|
169157
|
+
if (msg.id !== undefined && this.pendingRequests.has(msg.id)) {
|
|
169158
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
169159
|
+
clearTimeout(pending.timeout);
|
|
169160
|
+
this.pendingRequests.delete(msg.id);
|
|
169161
|
+
if (msg.error) {
|
|
169162
|
+
pending.reject(new Error(msg.error.message || "LSP error"));
|
|
169163
|
+
} else {
|
|
169164
|
+
pending.resolve(msg.result);
|
|
169165
|
+
}
|
|
169166
|
+
} else if (msg.method === "textDocument/publishDiagnostics") {
|
|
169167
|
+
this.handlePublishDiagnostics(msg.params);
|
|
169168
|
+
}
|
|
169169
|
+
} catch {}
|
|
169170
|
+
}
|
|
169171
|
+
}
|
|
169172
|
+
handlePublishDiagnostics(params) {
|
|
169173
|
+
if (!params || !params.uri || !Array.isArray(params.diagnostics))
|
|
169174
|
+
return;
|
|
169175
|
+
const uri = params.uri;
|
|
169176
|
+
const filePath = fileURLToPath(uri);
|
|
169177
|
+
const items = params.diagnostics.map((d) => {
|
|
169178
|
+
const sevNum = d.severity ?? 1;
|
|
169179
|
+
const severity = sevNum === 1 ? "error" : sevNum === 2 ? "warning" : "info";
|
|
169180
|
+
return {
|
|
169181
|
+
filePath,
|
|
169182
|
+
line: (d.range?.start?.line ?? 0) + 1,
|
|
169183
|
+
column: (d.range?.start?.character ?? 0) + 1,
|
|
169184
|
+
message: d.message || "",
|
|
169185
|
+
severity,
|
|
169186
|
+
source: d.source || "typescript"
|
|
169187
|
+
};
|
|
169188
|
+
});
|
|
169189
|
+
this.diagnosticsByUri.set(uri, items);
|
|
169190
|
+
}
|
|
169191
|
+
sendRequest(method, params) {
|
|
169192
|
+
if (!this.child || !this.child.stdin || this.isShutdown) {
|
|
169193
|
+
return Promise.reject(new Error("LSP client is not running"));
|
|
169194
|
+
}
|
|
169195
|
+
const id = this.nextId++;
|
|
169196
|
+
return new Promise((resolve, reject) => {
|
|
169197
|
+
const timeout = setTimeout(() => {
|
|
169198
|
+
this.pendingRequests.delete(id);
|
|
169199
|
+
reject(new Error(`LSP request "${method}" timed out after ${this.requestTimeoutMs}ms`));
|
|
169200
|
+
}, this.requestTimeoutMs);
|
|
169201
|
+
this.pendingRequests.set(id, { resolve, reject, timeout });
|
|
169202
|
+
const payload = JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
|
169203
|
+
const header = `Content-Length: ${Buffer.byteLength(payload, "utf8")}\r
|
|
169204
|
+
\r
|
|
169205
|
+
`;
|
|
169206
|
+
this.child?.stdin?.write(header + payload);
|
|
169207
|
+
});
|
|
169208
|
+
}
|
|
169209
|
+
sendNotification(method, params) {
|
|
169210
|
+
if (!this.child || !this.child.stdin || this.isShutdown)
|
|
169211
|
+
return;
|
|
169212
|
+
const payload = JSON.stringify({ jsonrpc: "2.0", method, params });
|
|
169213
|
+
const header = `Content-Length: ${Buffer.byteLength(payload, "utf8")}\r
|
|
169214
|
+
\r
|
|
169215
|
+
`;
|
|
169216
|
+
this.child.stdin.write(header + payload);
|
|
169217
|
+
}
|
|
169218
|
+
async openDocument(filePath, content) {
|
|
169219
|
+
const absPath = path25.isAbsolute(filePath) ? filePath : path25.resolve(this.workspaceRoot, filePath);
|
|
169220
|
+
const uri = pathToFileURL(absPath).toString();
|
|
169221
|
+
if (this.openedDocuments.has(uri)) {
|
|
169222
|
+
return uri;
|
|
169223
|
+
}
|
|
169224
|
+
let fileContent = content;
|
|
169225
|
+
if (fileContent === undefined) {
|
|
169226
|
+
try {
|
|
169227
|
+
fileContent = fs24.readFileSync(absPath, "utf8");
|
|
169228
|
+
} catch {
|
|
169229
|
+
fileContent = "";
|
|
169230
|
+
}
|
|
169231
|
+
}
|
|
169232
|
+
this.sendNotification("textDocument/didOpen", {
|
|
169233
|
+
textDocument: {
|
|
169234
|
+
uri,
|
|
169235
|
+
languageId: "typescript",
|
|
169236
|
+
version: 1,
|
|
169237
|
+
text: fileContent
|
|
169238
|
+
}
|
|
169239
|
+
});
|
|
169240
|
+
this.openedDocuments.add(uri);
|
|
169241
|
+
return uri;
|
|
169242
|
+
}
|
|
169243
|
+
async getDefinition(filePath, line, column) {
|
|
169244
|
+
const queryRawDefinition = async (targetFile, targetLine, targetCol) => {
|
|
169245
|
+
await this.start();
|
|
169246
|
+
const uri = await this.openDocument(targetFile);
|
|
169247
|
+
const raw = await this.sendRequest("textDocument/definition", {
|
|
169248
|
+
textDocument: { uri },
|
|
169249
|
+
position: {
|
|
169250
|
+
line: Math.max(0, targetLine - 1),
|
|
169251
|
+
character: Math.max(0, targetCol - 1)
|
|
169252
|
+
}
|
|
169253
|
+
});
|
|
169254
|
+
if (!raw)
|
|
169255
|
+
return [];
|
|
169256
|
+
const array = Array.isArray(raw) ? raw : [raw];
|
|
169257
|
+
const locations = [];
|
|
169258
|
+
for (const loc of array) {
|
|
169259
|
+
const targetUri = loc.targetUri || loc.uri;
|
|
169260
|
+
if (!targetUri)
|
|
169261
|
+
continue;
|
|
169262
|
+
const targetRange = loc.targetSelectionRange || loc.targetRange || loc.range;
|
|
169263
|
+
const targetFilePath = fileURLToPath(targetUri);
|
|
169264
|
+
locations.push({
|
|
169265
|
+
filePath: targetFilePath,
|
|
169266
|
+
line: (targetRange?.start?.line ?? 0) + 1,
|
|
169267
|
+
column: (targetRange?.start?.character ?? 0) + 1
|
|
169268
|
+
});
|
|
169269
|
+
}
|
|
169270
|
+
return locations;
|
|
169271
|
+
};
|
|
169272
|
+
const initial = await queryRawDefinition(filePath, line, column);
|
|
169273
|
+
const resolved = [];
|
|
169274
|
+
for (const loc of initial) {
|
|
169275
|
+
try {
|
|
169276
|
+
const content = fs24.readFileSync(loc.filePath, "utf8");
|
|
169277
|
+
const lines = content.split(`
|
|
169278
|
+
`);
|
|
169279
|
+
const lineContent = lines[loc.line - 1] || "";
|
|
169280
|
+
if (/^\s*import\b/.test(lineContent)) {
|
|
169281
|
+
const secondHop = await queryRawDefinition(loc.filePath, loc.line, loc.column);
|
|
169282
|
+
if (secondHop.length > 0 && !(secondHop.length === 1 && secondHop[0].filePath === loc.filePath && secondHop[0].line === loc.line)) {
|
|
169283
|
+
resolved.push(...secondHop);
|
|
169284
|
+
continue;
|
|
169285
|
+
}
|
|
169286
|
+
}
|
|
169287
|
+
} catch {}
|
|
169288
|
+
resolved.push(loc);
|
|
169289
|
+
}
|
|
169290
|
+
return resolved;
|
|
169291
|
+
}
|
|
169292
|
+
async getReferences(filePath, line, column) {
|
|
169293
|
+
await this.start();
|
|
169294
|
+
const uri = await this.openDocument(filePath);
|
|
169295
|
+
const raw = await this.sendRequest("textDocument/references", {
|
|
169296
|
+
textDocument: { uri },
|
|
169297
|
+
position: {
|
|
169298
|
+
line: Math.max(0, line - 1),
|
|
169299
|
+
character: Math.max(0, column - 1)
|
|
169300
|
+
},
|
|
169301
|
+
context: { includeDeclaration: true }
|
|
169302
|
+
});
|
|
169303
|
+
if (!raw || !Array.isArray(raw))
|
|
169304
|
+
return [];
|
|
169305
|
+
const locations = [];
|
|
169306
|
+
for (const loc of raw) {
|
|
169307
|
+
if (!loc.uri)
|
|
169308
|
+
continue;
|
|
169309
|
+
const targetFilePath = fileURLToPath(loc.uri);
|
|
169310
|
+
locations.push({
|
|
169311
|
+
filePath: targetFilePath,
|
|
169312
|
+
line: (loc.range?.start?.line ?? 0) + 1,
|
|
169313
|
+
column: (loc.range?.start?.character ?? 0) + 1
|
|
169314
|
+
});
|
|
169315
|
+
}
|
|
169316
|
+
return locations;
|
|
169317
|
+
}
|
|
169318
|
+
async getOutline(filePath) {
|
|
169319
|
+
await this.start();
|
|
169320
|
+
const uri = await this.openDocument(filePath);
|
|
169321
|
+
const raw = await this.sendRequest("textDocument/documentSymbol", {
|
|
169322
|
+
textDocument: { uri }
|
|
169323
|
+
});
|
|
169324
|
+
if (!raw || !Array.isArray(raw))
|
|
169325
|
+
return [];
|
|
169326
|
+
const items = [];
|
|
169327
|
+
const extractSymbols = (symbols, containerName) => {
|
|
169328
|
+
for (const sym of symbols) {
|
|
169329
|
+
const kindStr = SYMBOL_KINDS[sym.kind] || "symbol";
|
|
169330
|
+
const range = sym.range || sym.location?.range;
|
|
169331
|
+
const line = (range?.start?.line ?? 0) + 1;
|
|
169332
|
+
const column = (range?.start?.character ?? 0) + 1;
|
|
169333
|
+
items.push({
|
|
169334
|
+
name: sym.name || "anonymous",
|
|
169335
|
+
kind: kindStr,
|
|
169336
|
+
line,
|
|
169337
|
+
column,
|
|
169338
|
+
containerName: sym.containerName || containerName
|
|
169339
|
+
});
|
|
169340
|
+
if (Array.isArray(sym.children) && sym.children.length > 0) {
|
|
169341
|
+
extractSymbols(sym.children, sym.name);
|
|
169342
|
+
}
|
|
169343
|
+
}
|
|
169344
|
+
};
|
|
169345
|
+
extractSymbols(raw);
|
|
169346
|
+
return items;
|
|
169347
|
+
}
|
|
169348
|
+
getDiagnostics(filePath) {
|
|
169349
|
+
if (filePath) {
|
|
169350
|
+
const absPath = path25.isAbsolute(filePath) ? filePath : path25.resolve(this.workspaceRoot, filePath);
|
|
169351
|
+
const uri = pathToFileURL(absPath).toString();
|
|
169352
|
+
return this.diagnosticsByUri.get(uri) || [];
|
|
169353
|
+
}
|
|
169354
|
+
const all = [];
|
|
169355
|
+
for (const items of this.diagnosticsByUri.values()) {
|
|
169356
|
+
all.push(...items);
|
|
169357
|
+
}
|
|
169358
|
+
return all;
|
|
169359
|
+
}
|
|
169360
|
+
async shutdown() {
|
|
169361
|
+
if (this.isShutdown)
|
|
169362
|
+
return;
|
|
169363
|
+
this.isShutdown = true;
|
|
169364
|
+
if (this.child) {
|
|
169365
|
+
try {
|
|
169366
|
+
await Promise.race([
|
|
169367
|
+
this.sendRequest("shutdown", {}),
|
|
169368
|
+
new Promise((r) => setTimeout(r, 500))
|
|
169369
|
+
]);
|
|
169370
|
+
this.sendNotification("exit", {});
|
|
169371
|
+
} catch {}
|
|
169372
|
+
try {
|
|
169373
|
+
this.child.kill("SIGTERM");
|
|
169374
|
+
} catch {}
|
|
169375
|
+
this.child = null;
|
|
169376
|
+
}
|
|
169377
|
+
this.rejectAllPending(new Error("LSP client shutdown"));
|
|
169378
|
+
}
|
|
169379
|
+
rejectAllPending(err) {
|
|
169380
|
+
for (const [id, pending] of this.pendingRequests.entries()) {
|
|
169381
|
+
clearTimeout(pending.timeout);
|
|
169382
|
+
pending.reject(err);
|
|
169383
|
+
this.pendingRequests.delete(id);
|
|
169384
|
+
}
|
|
169385
|
+
}
|
|
169386
|
+
}
|
|
169387
|
+
var SYMBOL_KINDS;
|
|
169388
|
+
var init_lsp_client = __esm(() => {
|
|
169389
|
+
SYMBOL_KINDS = {
|
|
169390
|
+
1: "file",
|
|
169391
|
+
2: "module",
|
|
169392
|
+
3: "namespace",
|
|
169393
|
+
4: "package",
|
|
169394
|
+
5: "class",
|
|
169395
|
+
6: "method",
|
|
169396
|
+
7: "property",
|
|
169397
|
+
8: "field",
|
|
169398
|
+
9: "constructor",
|
|
169399
|
+
10: "enum",
|
|
169400
|
+
11: "interface",
|
|
169401
|
+
12: "function",
|
|
169402
|
+
13: "variable",
|
|
169403
|
+
14: "constant",
|
|
169404
|
+
15: "string",
|
|
169405
|
+
16: "number",
|
|
169406
|
+
17: "boolean",
|
|
169407
|
+
18: "array",
|
|
169408
|
+
19: "object",
|
|
169409
|
+
20: "key",
|
|
169410
|
+
21: "null",
|
|
169411
|
+
22: "enumMember",
|
|
169412
|
+
23: "struct",
|
|
169413
|
+
24: "event",
|
|
169414
|
+
25: "operator",
|
|
169415
|
+
26: "typeParameter"
|
|
169416
|
+
};
|
|
169417
|
+
});
|
|
169418
|
+
|
|
168292
169419
|
// ../../packages/agent/src/index.ts
|
|
168293
169420
|
var exports_src3 = {};
|
|
168294
169421
|
__export(exports_src3, {
|
|
168295
169422
|
AgentHarness: () => AgentHarness,
|
|
169423
|
+
LspClient: () => LspClient,
|
|
168296
169424
|
runAgentLoop: () => runAgentLoop
|
|
168297
169425
|
});
|
|
168298
169426
|
var init_src5 = __esm(() => {
|
|
@@ -168305,6 +169433,7 @@ var init_src5 = __esm(() => {
|
|
|
168305
169433
|
init_telemetry();
|
|
168306
169434
|
init_skill_subagent();
|
|
168307
169435
|
init_run_skill_tool();
|
|
169436
|
+
init_lsp_client();
|
|
168308
169437
|
});
|
|
168309
169438
|
|
|
168310
169439
|
// src/headless-runner.ts
|
|
@@ -168582,8 +169711,8 @@ var exports_file_session_repository = {};
|
|
|
168582
169711
|
__export(exports_file_session_repository, {
|
|
168583
169712
|
FileSessionRepository: () => FileSessionRepository
|
|
168584
169713
|
});
|
|
168585
|
-
import
|
|
168586
|
-
import
|
|
169714
|
+
import fs25 from "node:fs/promises";
|
|
169715
|
+
import path26 from "node:path";
|
|
168587
169716
|
|
|
168588
169717
|
class FileSessionRepository {
|
|
168589
169718
|
sessionDir;
|
|
@@ -168593,22 +169722,22 @@ class FileSessionRepository {
|
|
|
168593
169722
|
if (sessionDir) {
|
|
168594
169723
|
this.sessionDir = sessionDir;
|
|
168595
169724
|
} else {
|
|
168596
|
-
this.sessionDir =
|
|
168597
|
-
const legacyDir =
|
|
169725
|
+
this.sessionDir = path26.join(getConfigDir(), "sessions");
|
|
169726
|
+
const legacyDir = path26.join(getLegacyConfigDir(), "sessions");
|
|
168598
169727
|
if (legacyDir !== this.sessionDir) {
|
|
168599
169728
|
this.legacySessionDir = legacyDir;
|
|
168600
169729
|
}
|
|
168601
169730
|
}
|
|
168602
169731
|
}
|
|
168603
169732
|
async saveContext(sessionId, messages) {
|
|
168604
|
-
await
|
|
168605
|
-
const historyPath =
|
|
169733
|
+
await fs25.mkdir(this.sessionDir, { recursive: true });
|
|
169734
|
+
const historyPath = path26.join(this.sessionDir, `${sessionId}.jsonl`);
|
|
168606
169735
|
let existing = this.sessionCache[sessionId];
|
|
168607
169736
|
if (!existing) {
|
|
168608
169737
|
existing = {};
|
|
168609
169738
|
this.sessionCache[sessionId] = existing;
|
|
168610
169739
|
try {
|
|
168611
|
-
const data = await
|
|
169740
|
+
const data = await fs25.readFile(historyPath, "utf-8");
|
|
168612
169741
|
const lines = data.split(`
|
|
168613
169742
|
`).filter((l) => l.trim().length > 0);
|
|
168614
169743
|
for (const l of lines) {
|
|
@@ -168632,19 +169761,19 @@ class FileSessionRepository {
|
|
|
168632
169761
|
}
|
|
168633
169762
|
}
|
|
168634
169763
|
if (appendContent) {
|
|
168635
|
-
await
|
|
169764
|
+
await fs25.appendFile(historyPath, appendContent, "utf-8");
|
|
168636
169765
|
}
|
|
168637
169766
|
}
|
|
168638
169767
|
async loadContext(sessionId) {
|
|
168639
|
-
let historyPath =
|
|
169768
|
+
let historyPath = path26.join(this.sessionDir, `${sessionId}.jsonl`);
|
|
168640
169769
|
try {
|
|
168641
169770
|
let data;
|
|
168642
169771
|
try {
|
|
168643
|
-
data = await
|
|
169772
|
+
data = await fs25.readFile(historyPath, "utf-8");
|
|
168644
169773
|
} catch (err) {
|
|
168645
169774
|
if (this.legacySessionDir) {
|
|
168646
|
-
const legacyPath =
|
|
168647
|
-
data = await
|
|
169775
|
+
const legacyPath = path26.join(this.legacySessionDir, `${sessionId}.jsonl`);
|
|
169776
|
+
data = await fs25.readFile(legacyPath, "utf-8");
|
|
168648
169777
|
historyPath = legacyPath;
|
|
168649
169778
|
} else {
|
|
168650
169779
|
throw err;
|
|
@@ -168685,7 +169814,7 @@ class FileSessionRepository {
|
|
|
168685
169814
|
if (msgs.length < lines.length) {
|
|
168686
169815
|
const compacted = msgs.map((m) => JSON.stringify(m)).join(`
|
|
168687
169816
|
`);
|
|
168688
|
-
await
|
|
169817
|
+
await fs25.writeFile(historyPath, compacted, "utf-8").catch(() => {});
|
|
168689
169818
|
}
|
|
168690
169819
|
const cacheObj = {};
|
|
168691
169820
|
for (const msg of msgs) {
|
|
@@ -168699,12 +169828,12 @@ class FileSessionRepository {
|
|
|
168699
169828
|
}
|
|
168700
169829
|
async listSessions() {
|
|
168701
169830
|
try {
|
|
168702
|
-
await
|
|
169831
|
+
await fs25.mkdir(this.sessionDir, { recursive: true });
|
|
168703
169832
|
const sessions = [];
|
|
168704
169833
|
const seenIds = new Set;
|
|
168705
169834
|
const processDirectory = async (dirPath) => {
|
|
168706
169835
|
try {
|
|
168707
|
-
const dirFiles = await
|
|
169836
|
+
const dirFiles = await fs25.readdir(dirPath);
|
|
168708
169837
|
for (const file of dirFiles) {
|
|
168709
169838
|
if (!file.endsWith(".jsonl"))
|
|
168710
169839
|
continue;
|
|
@@ -168712,10 +169841,10 @@ class FileSessionRepository {
|
|
|
168712
169841
|
if (seenIds.has(id))
|
|
168713
169842
|
continue;
|
|
168714
169843
|
seenIds.add(id);
|
|
168715
|
-
const filePath =
|
|
169844
|
+
const filePath = path26.join(dirPath, file);
|
|
168716
169845
|
try {
|
|
168717
|
-
const stat = await
|
|
168718
|
-
const data = await
|
|
169846
|
+
const stat = await fs25.stat(filePath);
|
|
169847
|
+
const data = await fs25.readFile(filePath, "utf-8");
|
|
168719
169848
|
const lines = data.split(`
|
|
168720
169849
|
`).filter((l) => l.trim().length > 0);
|
|
168721
169850
|
let preview = "";
|
|
@@ -168749,20 +169878,20 @@ class FileSessionRepository {
|
|
|
168749
169878
|
}
|
|
168750
169879
|
}
|
|
168751
169880
|
async deleteSession(sessionId) {
|
|
168752
|
-
const historyPath =
|
|
169881
|
+
const historyPath = path26.join(this.sessionDir, `${sessionId}.jsonl`);
|
|
168753
169882
|
try {
|
|
168754
|
-
await
|
|
169883
|
+
await fs25.unlink(historyPath);
|
|
168755
169884
|
} catch (e) {}
|
|
168756
169885
|
if (this.legacySessionDir) {
|
|
168757
169886
|
try {
|
|
168758
|
-
await
|
|
169887
|
+
await fs25.unlink(path26.join(this.legacySessionDir, `${sessionId}.jsonl`));
|
|
168759
169888
|
} catch {}
|
|
168760
169889
|
}
|
|
168761
169890
|
}
|
|
168762
169891
|
async renameSession(oldSessionId, newSessionId) {
|
|
168763
|
-
const oldPath =
|
|
168764
|
-
const newPath =
|
|
168765
|
-
await
|
|
169892
|
+
const oldPath = path26.join(this.sessionDir, `${oldSessionId}.jsonl`);
|
|
169893
|
+
const newPath = path26.join(this.sessionDir, `${newSessionId}.jsonl`);
|
|
169894
|
+
await fs25.rename(oldPath, newPath);
|
|
168766
169895
|
}
|
|
168767
169896
|
}
|
|
168768
169897
|
var init_file_session_repository = __esm(() => {
|
|
@@ -174396,21 +175525,53 @@ __export(exports_local_operations, {
|
|
|
174396
175525
|
localOperations: () => localOperations,
|
|
174397
175526
|
setActiveScopeDir: () => setActiveScopeDir
|
|
174398
175527
|
});
|
|
174399
|
-
import { exec as exec4, spawn as
|
|
174400
|
-
import
|
|
174401
|
-
import
|
|
175528
|
+
import { exec as exec4, spawn as spawn4 } from "node:child_process";
|
|
175529
|
+
import nodeFs from "node:fs";
|
|
175530
|
+
import fs26 from "node:fs/promises";
|
|
175531
|
+
import path27 from "node:path";
|
|
174402
175532
|
import { promisify as promisify4 } from "node:util";
|
|
174403
175533
|
function setActiveScopeDir(dir) {
|
|
174404
175534
|
activeScopeDir = dir;
|
|
174405
175535
|
}
|
|
174406
175536
|
function getScopedCwd() {
|
|
174407
175537
|
if (activeScopeDir) {
|
|
174408
|
-
return
|
|
175538
|
+
return path27.resolve(process.cwd(), activeScopeDir);
|
|
174409
175539
|
}
|
|
174410
175540
|
return process.cwd();
|
|
174411
175541
|
}
|
|
174412
|
-
|
|
175542
|
+
function isTypeScriptProject(workspaceDir) {
|
|
175543
|
+
return nodeFs.existsSync(path27.join(workspaceDir, "tsconfig.json")) || nodeFs.existsSync(path27.join(workspaceDir, "package.json"));
|
|
175544
|
+
}
|
|
175545
|
+
async function getOrLaunchLspClient(customWorkspaceDir) {
|
|
175546
|
+
const workspaceDir = customWorkspaceDir || getScopedCwd();
|
|
175547
|
+
if (activeLspClient && activeLspWorkspace === workspaceDir) {
|
|
175548
|
+
return activeLspClient;
|
|
175549
|
+
}
|
|
175550
|
+
if (!isTypeScriptProject(workspaceDir)) {
|
|
175551
|
+
return null;
|
|
175552
|
+
}
|
|
175553
|
+
if (activeLspClient) {
|
|
175554
|
+
try {
|
|
175555
|
+
await activeLspClient.shutdown();
|
|
175556
|
+
} catch {}
|
|
175557
|
+
activeLspClient = null;
|
|
175558
|
+
activeLspWorkspace = null;
|
|
175559
|
+
}
|
|
175560
|
+
const client = new LspClient({ workspaceRoot: workspaceDir });
|
|
175561
|
+
activeLspClient = client;
|
|
175562
|
+
activeLspWorkspace = workspaceDir;
|
|
175563
|
+
try {
|
|
175564
|
+
await client.start();
|
|
175565
|
+
} catch {
|
|
175566
|
+
activeLspClient = null;
|
|
175567
|
+
activeLspWorkspace = null;
|
|
175568
|
+
return null;
|
|
175569
|
+
}
|
|
175570
|
+
return activeLspClient;
|
|
175571
|
+
}
|
|
175572
|
+
var import_fast_glob, execAsync2, localBashOps, activeScopeDir, SERVER_READY_REGEX, DEFAULT_BG_TIMEOUT_MS = 20000, DEFAULT_SERVER_READY_DELAY_MS = 2500, localOperations, activeLspClient = null, activeLspWorkspace = null;
|
|
174413
175573
|
var init_local_operations = __esm(() => {
|
|
175574
|
+
init_src5();
|
|
174414
175575
|
init_src();
|
|
174415
175576
|
init_src4();
|
|
174416
175577
|
init_task_manager();
|
|
@@ -174426,7 +175587,7 @@ var init_local_operations = __esm(() => {
|
|
|
174426
175587
|
const fallbackTimeoutMs = actualOptions.waitMsBeforeAsync ?? DEFAULT_BG_TIMEOUT_MS;
|
|
174427
175588
|
const serverDelayMs = actualOptions.serverReadyDelayMs ?? DEFAULT_SERVER_READY_DELAY_MS;
|
|
174428
175589
|
return new Promise((resolve, reject) => {
|
|
174429
|
-
const child =
|
|
175590
|
+
const child = spawn4(command, {
|
|
174430
175591
|
cwd: targetCwd,
|
|
174431
175592
|
detached: process.platform !== "win32",
|
|
174432
175593
|
env: actualOptions.env ?? process.env,
|
|
@@ -174556,19 +175717,19 @@ Failed to start process: ${err?.message || err}
|
|
|
174556
175717
|
fs: {
|
|
174557
175718
|
readFile: async (filepath) => {
|
|
174558
175719
|
const root = getScopedCwd();
|
|
174559
|
-
const absolutePath =
|
|
174560
|
-
return
|
|
175720
|
+
const absolutePath = path27.isAbsolute(filepath) ? filepath : path27.resolve(root, filepath);
|
|
175721
|
+
return fs26.readFile(absolutePath, "utf8");
|
|
174561
175722
|
},
|
|
174562
175723
|
writeFile: async (filepath, content) => {
|
|
174563
175724
|
const root = getScopedCwd();
|
|
174564
|
-
const absolutePath =
|
|
174565
|
-
await
|
|
174566
|
-
await
|
|
175725
|
+
const absolutePath = path27.isAbsolute(filepath) ? filepath : path27.resolve(root, filepath);
|
|
175726
|
+
await fs26.mkdir(path27.dirname(absolutePath), { recursive: true });
|
|
175727
|
+
await fs26.writeFile(absolutePath, content, "utf8");
|
|
174567
175728
|
},
|
|
174568
175729
|
readdir: async (dirPath) => {
|
|
174569
175730
|
const root = getScopedCwd();
|
|
174570
|
-
const absolutePath =
|
|
174571
|
-
const entries = await
|
|
175731
|
+
const absolutePath = path27.isAbsolute(dirPath) ? dirPath : path27.resolve(root, dirPath);
|
|
175732
|
+
const entries = await fs26.readdir(absolutePath, { withFileTypes: true });
|
|
174572
175733
|
const ignores = getWorkspaceIgnores(root);
|
|
174573
175734
|
return entries.filter((entry) => !isPathIgnored(entry.name, ignores)).map((entry) => {
|
|
174574
175735
|
const type = entry.isDirectory() ? "DIR " : "FILE";
|
|
@@ -174577,14 +175738,14 @@ Failed to start process: ${err?.message || err}
|
|
|
174577
175738
|
},
|
|
174578
175739
|
mkdir: async (dirPath, options) => {
|
|
174579
175740
|
const root = getScopedCwd();
|
|
174580
|
-
const absolutePath =
|
|
174581
|
-
await
|
|
175741
|
+
const absolutePath = path27.isAbsolute(dirPath) ? dirPath : path27.resolve(root, dirPath);
|
|
175742
|
+
await fs26.mkdir(absolutePath, options);
|
|
174582
175743
|
},
|
|
174583
175744
|
exists: async (filepath) => {
|
|
174584
175745
|
const root = getScopedCwd();
|
|
174585
|
-
const absolutePath =
|
|
175746
|
+
const absolutePath = path27.isAbsolute(filepath) ? filepath : path27.resolve(root, filepath);
|
|
174586
175747
|
try {
|
|
174587
|
-
await
|
|
175748
|
+
await fs26.access(absolutePath);
|
|
174588
175749
|
return true;
|
|
174589
175750
|
} catch {
|
|
174590
175751
|
return false;
|
|
@@ -174594,7 +175755,7 @@ Failed to start process: ${err?.message || err}
|
|
|
174594
175755
|
search: {
|
|
174595
175756
|
find: async (dirPath, query) => {
|
|
174596
175757
|
const root = getScopedCwd();
|
|
174597
|
-
const targetDir =
|
|
175758
|
+
const targetDir = path27.isAbsolute(dirPath) ? dirPath : path27.resolve(root, dirPath);
|
|
174598
175759
|
const ignores = getWorkspaceIgnores(root);
|
|
174599
175760
|
const files = await import_fast_glob.default([query], {
|
|
174600
175761
|
cwd: targetDir,
|
|
@@ -174606,7 +175767,7 @@ Failed to start process: ${err?.message || err}
|
|
|
174606
175767
|
},
|
|
174607
175768
|
grep: async (dirPath, query) => {
|
|
174608
175769
|
const root = getScopedCwd();
|
|
174609
|
-
const targetDir =
|
|
175770
|
+
const targetDir = path27.isAbsolute(dirPath) ? dirPath : path27.resolve(root, dirPath);
|
|
174610
175771
|
const ignores = getWorkspaceIgnores(root);
|
|
174611
175772
|
try {
|
|
174612
175773
|
const escapedQuery = query.replace(/"/g, "\\\"");
|
|
@@ -174620,7 +175781,7 @@ Failed to start process: ${err?.message || err}
|
|
|
174620
175781
|
if (!line.trim())
|
|
174621
175782
|
return false;
|
|
174622
175783
|
const rawPath = line.split(":")[0];
|
|
174623
|
-
const relPath =
|
|
175784
|
+
const relPath = path27.isAbsolute(rawPath) ? path27.relative(root, rawPath) : rawPath;
|
|
174624
175785
|
return !isPathIgnored(relPath, ignores);
|
|
174625
175786
|
});
|
|
174626
175787
|
return filtered.join(`
|
|
@@ -174662,8 +175823,56 @@ Failed to start process: ${err?.message || err}
|
|
|
174662
175823
|
return { text: "", error: error.message };
|
|
174663
175824
|
}
|
|
174664
175825
|
}
|
|
175826
|
+
},
|
|
175827
|
+
diagnostics: {
|
|
175828
|
+
getDiagnostics: async (filePath) => {
|
|
175829
|
+
const client = await getOrLaunchLspClient();
|
|
175830
|
+
if (!client)
|
|
175831
|
+
return [];
|
|
175832
|
+
return client.getDiagnostics(filePath);
|
|
175833
|
+
}
|
|
175834
|
+
},
|
|
175835
|
+
lsp: {
|
|
175836
|
+
getDefinition: async (filePath, line, column) => {
|
|
175837
|
+
const client = await getOrLaunchLspClient();
|
|
175838
|
+
if (!client)
|
|
175839
|
+
return [];
|
|
175840
|
+
return client.getDefinition(filePath, line, column);
|
|
175841
|
+
},
|
|
175842
|
+
getReferences: async (filePath, line, column) => {
|
|
175843
|
+
const client = await getOrLaunchLspClient();
|
|
175844
|
+
if (!client)
|
|
175845
|
+
return [];
|
|
175846
|
+
return client.getReferences(filePath, line, column);
|
|
175847
|
+
},
|
|
175848
|
+
getOutline: async (filePath) => {
|
|
175849
|
+
const client = await getOrLaunchLspClient();
|
|
175850
|
+
if (!client)
|
|
175851
|
+
return [];
|
|
175852
|
+
return client.getOutline(filePath);
|
|
175853
|
+
},
|
|
175854
|
+
getDiagnostics: async (filePath) => {
|
|
175855
|
+
const client = await getOrLaunchLspClient();
|
|
175856
|
+
if (!client)
|
|
175857
|
+
return [];
|
|
175858
|
+
return client.getDiagnostics(filePath);
|
|
175859
|
+
},
|
|
175860
|
+
shutdown: async () => {
|
|
175861
|
+
if (activeLspClient) {
|
|
175862
|
+
await activeLspClient.shutdown();
|
|
175863
|
+
activeLspClient = null;
|
|
175864
|
+
activeLspWorkspace = null;
|
|
175865
|
+
}
|
|
175866
|
+
}
|
|
174665
175867
|
}
|
|
174666
175868
|
};
|
|
175869
|
+
process.on("exit", () => {
|
|
175870
|
+
if (activeLspClient) {
|
|
175871
|
+
try {
|
|
175872
|
+
activeLspClient.shutdown();
|
|
175873
|
+
} catch {}
|
|
175874
|
+
}
|
|
175875
|
+
});
|
|
174667
175876
|
});
|
|
174668
175877
|
|
|
174669
175878
|
// src/utils/provider-factory.ts
|
|
@@ -179015,7 +180224,7 @@ var init_wrap_ansi = __esm(() => {
|
|
|
179015
180224
|
// ../../node_modules/.bun/terminal-size@4.0.1/node_modules/terminal-size/index.js
|
|
179016
180225
|
import process3 from "node:process";
|
|
179017
180226
|
import { execFileSync } from "node:child_process";
|
|
179018
|
-
import
|
|
180227
|
+
import fs27 from "node:fs";
|
|
179019
180228
|
import tty from "node:tty";
|
|
179020
180229
|
function terminalSize() {
|
|
179021
180230
|
const { env, stdout, stderr } = process3;
|
|
@@ -179063,7 +180272,7 @@ var defaultColumns = 80, defaultRows = 24, exec6 = (command, arguments_, { shell
|
|
|
179063
180272
|
return true;
|
|
179064
180273
|
}
|
|
179065
180274
|
try {
|
|
179066
|
-
const statContents =
|
|
180275
|
+
const statContents = fs27.readFileSync("/proc/self/stat", "utf8");
|
|
179067
180276
|
const closingParenthesisIndex = statContents.lastIndexOf(") ");
|
|
179068
180277
|
if (closingParenthesisIndex === -1) {
|
|
179069
180278
|
return false;
|
|
@@ -179083,8 +180292,8 @@ var defaultColumns = 80, defaultRows = 24, exec6 = (command, arguments_, { shell
|
|
|
179083
180292
|
}
|
|
179084
180293
|
}, devTty = () => {
|
|
179085
180294
|
try {
|
|
179086
|
-
const flags = process3.platform === "darwin" ?
|
|
179087
|
-
const { columns, rows } = tty.WriteStream(
|
|
180295
|
+
const flags = process3.platform === "darwin" ? fs27.constants.O_EVTONLY | fs27.constants.O_NONBLOCK : fs27.constants.O_NONBLOCK;
|
|
180296
|
+
const { columns, rows } = tty.WriteStream(fs27.openSync("/dev/tty", flags));
|
|
179088
180297
|
return { columns, rows };
|
|
179089
180298
|
} catch {}
|
|
179090
180299
|
}, tput = () => {
|
|
@@ -211286,7 +212495,7 @@ var init_Text = __esm(() => {
|
|
|
211286
212495
|
});
|
|
211287
212496
|
|
|
211288
212497
|
// ../../node_modules/.bun/ink@7.1.0+90ffd46201e3176f/node_modules/ink/build/components/ErrorOverview.js
|
|
211289
|
-
import * as
|
|
212498
|
+
import * as fs28 from "node:fs";
|
|
211290
212499
|
import { cwd } from "node:process";
|
|
211291
212500
|
function ErrorOverview({ error }) {
|
|
211292
212501
|
const stack = error.stack ? error.stack.split(`
|
|
@@ -211296,8 +212505,8 @@ function ErrorOverview({ error }) {
|
|
|
211296
212505
|
let excerpt;
|
|
211297
212506
|
let lineWidth = 0;
|
|
211298
212507
|
const stackLineCounts = new Map;
|
|
211299
|
-
if (filePath && origin?.line &&
|
|
211300
|
-
const sourceCode =
|
|
212508
|
+
if (filePath && origin?.line && fs28.existsSync(filePath)) {
|
|
212509
|
+
const sourceCode = fs28.readFileSync(filePath, "utf8");
|
|
211301
212510
|
excerpt = dist_default4(sourceCode, origin.line);
|
|
211302
212511
|
if (excerpt) {
|
|
211303
212512
|
for (const { line } of excerpt) {
|
|
@@ -212728,7 +213937,7 @@ var init_render_to_string = __esm(async () => {
|
|
|
212728
213937
|
});
|
|
212729
213938
|
|
|
212730
213939
|
// ../../node_modules/.bun/ink@7.1.0+90ffd46201e3176f/node_modules/ink/build/components/Static.js
|
|
212731
|
-
function
|
|
213940
|
+
function Static15(props) {
|
|
212732
213941
|
const { items, children: render, style: customStyle } = props;
|
|
212733
213942
|
const [index, setIndex] = import_react17.useState(0);
|
|
212734
213943
|
const itemsToRender = import_react17.useMemo(() => {
|
|
@@ -213971,9 +215180,9 @@ var init_paste_manager = __esm(() => {
|
|
|
213971
215180
|
});
|
|
213972
215181
|
|
|
213973
215182
|
// ../../packages/tui/src/utils/prompt-history.ts
|
|
213974
|
-
import
|
|
215183
|
+
import fs29 from "node:fs";
|
|
213975
215184
|
import os15 from "node:os";
|
|
213976
|
-
import
|
|
215185
|
+
import path28 from "node:path";
|
|
213977
215186
|
|
|
213978
215187
|
class PromptHistory {
|
|
213979
215188
|
historyPath;
|
|
@@ -213985,16 +215194,16 @@ class PromptHistory {
|
|
|
213985
215194
|
this.historyPath = customPath;
|
|
213986
215195
|
} else {
|
|
213987
215196
|
const home = process.env.HOME || process.env.USERPROFILE || os15.homedir();
|
|
213988
|
-
const canonicalPath =
|
|
213989
|
-
const legacyPath =
|
|
213990
|
-
this.historyPath =
|
|
215197
|
+
const canonicalPath = path28.join(home, ".december", "history");
|
|
215198
|
+
const legacyPath = path28.join(home, ".config", "december", "history");
|
|
215199
|
+
this.historyPath = fs29.existsSync(canonicalPath) || !fs29.existsSync(legacyPath) ? canonicalPath : legacyPath;
|
|
213991
215200
|
}
|
|
213992
215201
|
this.load();
|
|
213993
215202
|
}
|
|
213994
215203
|
load() {
|
|
213995
215204
|
try {
|
|
213996
|
-
if (
|
|
213997
|
-
const raw =
|
|
215205
|
+
if (fs29.existsSync(this.historyPath)) {
|
|
215206
|
+
const raw = fs29.readFileSync(this.historyPath, "utf8");
|
|
213998
215207
|
this.entries = raw.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
|
|
213999
215208
|
}
|
|
214000
215209
|
} catch {
|
|
@@ -214010,11 +215219,11 @@ class PromptHistory {
|
|
|
214010
215219
|
this.cursor = this.entries.length;
|
|
214011
215220
|
this.currentDraft = "";
|
|
214012
215221
|
try {
|
|
214013
|
-
const dir =
|
|
214014
|
-
if (!
|
|
214015
|
-
|
|
215222
|
+
const dir = path28.dirname(this.historyPath);
|
|
215223
|
+
if (!fs29.existsSync(dir)) {
|
|
215224
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
214016
215225
|
}
|
|
214017
|
-
|
|
215226
|
+
fs29.appendFileSync(this.historyPath, trimmed + `
|
|
214018
215227
|
`, "utf8");
|
|
214019
215228
|
} catch {}
|
|
214020
215229
|
}
|
|
@@ -214078,16 +215287,16 @@ var init_clipboard = () => {};
|
|
|
214078
215287
|
|
|
214079
215288
|
// ../../packages/tui/src/utils/handoff.ts
|
|
214080
215289
|
import { exec as exec7 } from "node:child_process";
|
|
214081
|
-
import
|
|
214082
|
-
import
|
|
215290
|
+
import fs30 from "node:fs";
|
|
215291
|
+
import path29 from "node:path";
|
|
214083
215292
|
import { promisify as promisify5 } from "node:util";
|
|
214084
215293
|
function getHandoffExcludes(baseDir = process.cwd()) {
|
|
214085
215294
|
const excludes = [...MANDATORY_HANDOFF_EXCLUDES];
|
|
214086
215295
|
const readIgnoreFile = (fileName) => {
|
|
214087
|
-
const filePath =
|
|
215296
|
+
const filePath = path29.join(baseDir, fileName);
|
|
214088
215297
|
try {
|
|
214089
|
-
if (
|
|
214090
|
-
const lines =
|
|
215298
|
+
if (fs30.existsSync(filePath)) {
|
|
215299
|
+
const lines = fs30.readFileSync(filePath, "utf8").split(`
|
|
214091
215300
|
`);
|
|
214092
215301
|
for (const line of lines) {
|
|
214093
215302
|
const trimmed = line.trim();
|
|
@@ -214156,9 +215365,9 @@ var init_handoff = __esm(() => {
|
|
|
214156
215365
|
});
|
|
214157
215366
|
|
|
214158
215367
|
// ../../packages/tui/src/components/command-menu/commands.tsx
|
|
214159
|
-
import
|
|
215368
|
+
import fs31 from "node:fs";
|
|
214160
215369
|
import os17 from "node:os";
|
|
214161
|
-
import
|
|
215370
|
+
import path30 from "node:path";
|
|
214162
215371
|
var COMMANDS;
|
|
214163
215372
|
var init_commands2 = __esm(() => {
|
|
214164
215373
|
init_clipboard();
|
|
@@ -214262,13 +215471,13 @@ var init_commands2 = __esm(() => {
|
|
|
214262
215471
|
const archivePath = ".december-handoff.tar.gz";
|
|
214263
215472
|
try {
|
|
214264
215473
|
const home = process.env.HOME || process.env.USERPROFILE || os17.homedir();
|
|
214265
|
-
const canonicalConfigPath =
|
|
214266
|
-
const legacyConfigPath =
|
|
214267
|
-
const configPath =
|
|
215474
|
+
const canonicalConfigPath = path30.join(home, ".december", "config.json");
|
|
215475
|
+
const legacyConfigPath = path30.join(home, ".config", "december", "config.json");
|
|
215476
|
+
const configPath = fs31.existsSync(canonicalConfigPath) || !fs31.existsSync(legacyConfigPath) ? canonicalConfigPath : legacyConfigPath;
|
|
214268
215477
|
let config = {};
|
|
214269
215478
|
try {
|
|
214270
|
-
if (
|
|
214271
|
-
config = JSON.parse(
|
|
215479
|
+
if (fs31.existsSync(configPath)) {
|
|
215480
|
+
config = JSON.parse(fs31.readFileSync(configPath, "utf8"));
|
|
214272
215481
|
}
|
|
214273
215482
|
} catch {}
|
|
214274
215483
|
if (!config.decemberToken) {
|
|
@@ -214303,7 +215512,7 @@ var init_commands2 = __esm(() => {
|
|
|
214303
215512
|
headers: { Authorization: `Bearer ${config.decemberToken}` }
|
|
214304
215513
|
});
|
|
214305
215514
|
if (!urlRes.ok) {
|
|
214306
|
-
await
|
|
215515
|
+
await fs31.promises.unlink(archivePath).catch(() => {});
|
|
214307
215516
|
if (urlRes.status === 401) {
|
|
214308
215517
|
ctx.toast.show({
|
|
214309
215518
|
variant: "error",
|
|
@@ -214324,7 +215533,7 @@ var init_commands2 = __esm(() => {
|
|
|
214324
215533
|
const urlJson = await urlRes.json();
|
|
214325
215534
|
const { uploadUrl, objectKey } = urlJson.data || urlJson;
|
|
214326
215535
|
ctx.toast.show({ variant: "info", message: "Uploading to MinIO..." });
|
|
214327
|
-
const fileData = await
|
|
215536
|
+
const fileData = await fs31.promises.readFile(archivePath);
|
|
214328
215537
|
const uploadRes = await fetch(uploadUrl, {
|
|
214329
215538
|
method: "PUT",
|
|
214330
215539
|
body: fileData
|
|
@@ -214348,11 +215557,11 @@ var init_commands2 = __esm(() => {
|
|
|
214348
215557
|
const errJson = await sessionRes.json().catch(() => ({}));
|
|
214349
215558
|
throw new Error(errJson.message || await sessionRes.text());
|
|
214350
215559
|
}
|
|
214351
|
-
await
|
|
215560
|
+
await fs31.promises.unlink(archivePath).catch(() => {});
|
|
214352
215561
|
ctx.toast.show({ variant: "success", message: "Handoff complete! Exiting in 3s." });
|
|
214353
215562
|
setTimeout(() => ctx.exit(), 3000);
|
|
214354
215563
|
} catch (e) {
|
|
214355
|
-
await
|
|
215564
|
+
await fs31.promises.unlink(archivePath).catch(() => {});
|
|
214356
215565
|
ctx.toast.show({ variant: "error", message: `Handoff failed: ${e.message}` });
|
|
214357
215566
|
}
|
|
214358
215567
|
}
|
|
@@ -216045,7 +217254,7 @@ var init_scroll_viewport = __esm(async () => {
|
|
|
216045
217254
|
});
|
|
216046
217255
|
|
|
216047
217256
|
// ../../packages/tui/src/utils/terminal-link.ts
|
|
216048
|
-
import
|
|
217257
|
+
import path31 from "node:path";
|
|
216049
217258
|
function terminalLink(text, uri) {
|
|
216050
217259
|
if (!uri)
|
|
216051
217260
|
return text;
|
|
@@ -216054,7 +217263,7 @@ function terminalLink(text, uri) {
|
|
|
216054
217263
|
function fileLink(displayPath, targetPath, line, col) {
|
|
216055
217264
|
if (!targetPath)
|
|
216056
217265
|
return displayPath;
|
|
216057
|
-
const absPath =
|
|
217266
|
+
const absPath = path31.isAbsolute(targetPath) ? targetPath : path31.resolve(process.cwd(), targetPath);
|
|
216058
217267
|
const lineFragment = line ? `#L${line}${col ? `:${col}` : ""}` : "";
|
|
216059
217268
|
const uri = `file://${absPath}${lineFragment}`;
|
|
216060
217269
|
return terminalLink(displayPath, uri);
|
|
@@ -216063,9 +217272,9 @@ function toRelativePath(filePath, cwd = process.cwd()) {
|
|
|
216063
217272
|
if (!filePath)
|
|
216064
217273
|
return "";
|
|
216065
217274
|
const trimmed = filePath.trim();
|
|
216066
|
-
if (!
|
|
217275
|
+
if (!path31.isAbsolute(trimmed))
|
|
216067
217276
|
return trimmed;
|
|
216068
|
-
const rel =
|
|
217277
|
+
const rel = path31.relative(cwd, trimmed);
|
|
216069
217278
|
if (!rel || rel.startsWith("..")) {
|
|
216070
217279
|
return trimmed;
|
|
216071
217280
|
}
|
|
@@ -262433,27 +263642,27 @@ ${r}`;
|
|
|
262433
263642
|
});
|
|
262434
263643
|
|
|
262435
263644
|
// ../../packages/tui/src/components/header.tsx
|
|
262436
|
-
import
|
|
263645
|
+
import fs32 from "node:fs";
|
|
262437
263646
|
import { homedir } from "node:os";
|
|
262438
|
-
import
|
|
263647
|
+
import path32 from "node:path";
|
|
262439
263648
|
function getGitBranch(workspaceRoot = process.cwd()) {
|
|
262440
263649
|
if (cachedBranch !== undefined) {
|
|
262441
263650
|
return cachedBranch;
|
|
262442
263651
|
}
|
|
262443
263652
|
try {
|
|
262444
|
-
const gitPath =
|
|
262445
|
-
if (
|
|
262446
|
-
const stat =
|
|
262447
|
-
let headPath =
|
|
263653
|
+
const gitPath = path32.resolve(workspaceRoot, ".git");
|
|
263654
|
+
if (fs32.existsSync(gitPath)) {
|
|
263655
|
+
const stat = fs32.statSync(gitPath);
|
|
263656
|
+
let headPath = path32.resolve(gitPath, "HEAD");
|
|
262448
263657
|
if (stat.isFile()) {
|
|
262449
|
-
const content =
|
|
263658
|
+
const content = fs32.readFileSync(gitPath, "utf-8").trim();
|
|
262450
263659
|
if (content.startsWith("gitdir:")) {
|
|
262451
263660
|
const gitDir = content.slice(7).trim();
|
|
262452
|
-
headPath =
|
|
263661
|
+
headPath = path32.resolve(workspaceRoot, gitDir, "HEAD");
|
|
262453
263662
|
}
|
|
262454
263663
|
}
|
|
262455
|
-
if (
|
|
262456
|
-
const headContent =
|
|
263664
|
+
if (fs32.existsSync(headPath)) {
|
|
263665
|
+
const headContent = fs32.readFileSync(headPath, "utf-8").trim();
|
|
262457
263666
|
if (headContent.startsWith("ref: refs/heads/")) {
|
|
262458
263667
|
cachedBranch = headContent.replace("ref: refs/heads/", "").trim();
|
|
262459
263668
|
return cachedBranch;
|
|
@@ -262727,7 +263936,7 @@ var init_message_list = __esm(async () => {
|
|
|
262727
263936
|
flexDirection: "column",
|
|
262728
263937
|
width: "100%",
|
|
262729
263938
|
children: [
|
|
262730
|
-
staticMessages.length > 0 && /* @__PURE__ */ jsx_runtime20.jsx(
|
|
263939
|
+
staticMessages.length > 0 && /* @__PURE__ */ jsx_runtime20.jsx(Static15, {
|
|
262731
263940
|
items: staticMessages,
|
|
262732
263941
|
style: { width: "100%" },
|
|
262733
263942
|
children: (msg, index) => renderSingleMessage(msg, index, staticMessages, cliVersion, latestVersion, userEmail, expandCommands, announcement)
|
|
@@ -267816,17 +269025,17 @@ var init_global_shortcuts = __esm(async () => {
|
|
|
267816
269025
|
|
|
267817
269026
|
// ../../packages/tui/src/utils/pager.ts
|
|
267818
269027
|
import * as cp3 from "node:child_process";
|
|
267819
|
-
import
|
|
269028
|
+
import fs33 from "node:fs";
|
|
267820
269029
|
import os18 from "node:os";
|
|
267821
|
-
import
|
|
269030
|
+
import path33 from "node:path";
|
|
267822
269031
|
function openPlanInPager(planText, title = "december-plan") {
|
|
267823
269032
|
if (Boolean(process.env.BUN_TEST) || Boolean(process.env.VITEST)) {
|
|
267824
269033
|
return Promise.resolve();
|
|
267825
269034
|
}
|
|
267826
269035
|
return new Promise((resolve) => {
|
|
267827
269036
|
try {
|
|
267828
|
-
const tmpFile =
|
|
267829
|
-
|
|
269037
|
+
const tmpFile = path33.join(os18.tmpdir(), `${title}-${Date.now()}.md`);
|
|
269038
|
+
fs33.writeFileSync(tmpFile, planText, "utf8");
|
|
267830
269039
|
const pager = process.env.PAGER || process.env.EDITOR || (os18.platform() === "win32" ? "notepad" : "less -R");
|
|
267831
269040
|
const child = cp3.spawn(pager, [tmpFile], {
|
|
267832
269041
|
stdio: "inherit",
|
|
@@ -267834,7 +269043,7 @@ function openPlanInPager(planText, title = "december-plan") {
|
|
|
267834
269043
|
});
|
|
267835
269044
|
child.on("exit", () => {
|
|
267836
269045
|
try {
|
|
267837
|
-
|
|
269046
|
+
fs33.unlinkSync(tmpFile);
|
|
267838
269047
|
} catch {}
|
|
267839
269048
|
resolve();
|
|
267840
269049
|
});
|
|
@@ -268404,8 +269613,8 @@ var init_store = __esm(() => {
|
|
|
268404
269613
|
|
|
268405
269614
|
// src/store/interceptors.ts
|
|
268406
269615
|
import { execSync as execSync2 } from "node:child_process";
|
|
268407
|
-
import
|
|
268408
|
-
import
|
|
269616
|
+
import fs34 from "node:fs/promises";
|
|
269617
|
+
import path34 from "node:path";
|
|
268409
269618
|
async function computeToolCallDiff(toolCall) {
|
|
268410
269619
|
if (toolCall.input?.diff) {
|
|
268411
269620
|
return toolCall.input.diff;
|
|
@@ -268414,11 +269623,11 @@ async function computeToolCallDiff(toolCall) {
|
|
|
268414
269623
|
if (!targetPath)
|
|
268415
269624
|
return;
|
|
268416
269625
|
const cwd = process.cwd();
|
|
268417
|
-
const resolved =
|
|
268418
|
-
const relative =
|
|
269626
|
+
const resolved = path34.resolve(cwd, targetPath);
|
|
269627
|
+
const relative = path34.relative(cwd, resolved);
|
|
268419
269628
|
let oldContent = "";
|
|
268420
269629
|
try {
|
|
268421
|
-
oldContent = await
|
|
269630
|
+
oldContent = await fs34.readFile(resolved, "utf-8");
|
|
268422
269631
|
} catch {}
|
|
268423
269632
|
if (toolCall.name === "write_to_file" || toolCall.name === "write") {
|
|
268424
269633
|
const newContent = toolCall.input?.CodeContent ?? toolCall.input?.content ?? "";
|
|
@@ -268482,9 +269691,9 @@ function setupAgentInterceptors(agent, storeState) {
|
|
|
268482
269691
|
];
|
|
268483
269692
|
if (fileTools.includes(toolCall.name)) {
|
|
268484
269693
|
const cwd = process.cwd();
|
|
268485
|
-
const resolved =
|
|
268486
|
-
const relative =
|
|
268487
|
-
const isOutside = relative.startsWith("..") ||
|
|
269694
|
+
const resolved = path34.resolve(cwd, targetPath);
|
|
269695
|
+
const relative = path34.relative(cwd, resolved);
|
|
269696
|
+
const isOutside = relative.startsWith("..") || path34.isAbsolute(relative);
|
|
268488
269697
|
if (!config.nonWorkspaceAccess && isOutside) {
|
|
268489
269698
|
return {
|
|
268490
269699
|
block: true,
|
|
@@ -268548,8 +269757,8 @@ function setupAgentInterceptors(agent, storeState) {
|
|
|
268548
269757
|
const targetPath = toolCall.input?.TargetFile || toolCall.input?.AbsolutePath || toolCall.input?.filePath || toolCall.input?.path;
|
|
268549
269758
|
if (targetPath) {
|
|
268550
269759
|
const cwd = process.cwd();
|
|
268551
|
-
const resolved =
|
|
268552
|
-
const relative =
|
|
269760
|
+
const resolved = path34.resolve(cwd, targetPath);
|
|
269761
|
+
const relative = path34.relative(cwd, resolved);
|
|
268553
269762
|
try {
|
|
268554
269763
|
execSync2(`git ls-files --error-unmatch "${relative}"`, {
|
|
268555
269764
|
cwd,
|
|
@@ -268576,7 +269785,7 @@ var init_interceptors = __esm(() => {
|
|
|
268576
269785
|
});
|
|
268577
269786
|
|
|
268578
269787
|
// src/utils/direct-shell.ts
|
|
268579
|
-
import { spawn as
|
|
269788
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
268580
269789
|
function startDirectCommand(command, options = {}) {
|
|
268581
269790
|
const { timeoutMs = 20000, serverReadyDelayMs = 2500, onData, onBackground } = options;
|
|
268582
269791
|
let output = "";
|
|
@@ -268586,7 +269795,7 @@ function startDirectCommand(command, options = {}) {
|
|
|
268586
269795
|
const isWindows = process.platform === "win32";
|
|
268587
269796
|
const shellCmd = isWindows ? "cmd.exe" : "/bin/bash";
|
|
268588
269797
|
const shellArgs = isWindows ? ["/d", "/s", "/c", command] : ["-c", command];
|
|
268589
|
-
const child =
|
|
269798
|
+
const child = spawn6(shellCmd, shellArgs, {
|
|
268590
269799
|
cwd: process.cwd(),
|
|
268591
269800
|
env: process.env,
|
|
268592
269801
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -268738,15 +269947,15 @@ var init_direct_shell = __esm(() => {
|
|
|
268738
269947
|
});
|
|
268739
269948
|
|
|
268740
269949
|
// src/utils/usage-tracker.ts
|
|
268741
|
-
import
|
|
268742
|
-
import
|
|
269950
|
+
import fs35 from "node:fs/promises";
|
|
269951
|
+
import path35 from "node:path";
|
|
268743
269952
|
function getUsageFilePath() {
|
|
268744
|
-
return
|
|
269953
|
+
return path35.join(getConfigDir(), "usage.json");
|
|
268745
269954
|
}
|
|
268746
269955
|
async function loadUsageLedger() {
|
|
268747
269956
|
const filePath = getUsageFilePath();
|
|
268748
269957
|
try {
|
|
268749
|
-
const raw = await
|
|
269958
|
+
const raw = await fs35.readFile(filePath, "utf-8");
|
|
268750
269959
|
const parsed = JSON.parse(raw);
|
|
268751
269960
|
if (parsed && typeof parsed === "object" && parsed.version === 1 && parsed.days) {
|
|
268752
269961
|
return parsed;
|
|
@@ -268759,8 +269968,8 @@ async function loadUsageLedger() {
|
|
|
268759
269968
|
}
|
|
268760
269969
|
async function saveUsageLedger(ledger) {
|
|
268761
269970
|
const configDir = getConfigDir();
|
|
268762
|
-
const filePath =
|
|
268763
|
-
const tmpPath =
|
|
269971
|
+
const filePath = path35.join(configDir, "usage.json");
|
|
269972
|
+
const tmpPath = path35.join(configDir, `usage.json.tmp.${Date.now()}`);
|
|
268764
269973
|
const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().slice(0, 10);
|
|
268765
269974
|
const prunedDays = {};
|
|
268766
269975
|
for (const [dateKey, dayRecord] of Object.entries(ledger.days)) {
|
|
@@ -268770,12 +269979,12 @@ async function saveUsageLedger(ledger) {
|
|
|
268770
269979
|
}
|
|
268771
269980
|
ledger.days = prunedDays;
|
|
268772
269981
|
try {
|
|
268773
|
-
await
|
|
268774
|
-
await
|
|
268775
|
-
await
|
|
269982
|
+
await fs35.mkdir(configDir, { recursive: true });
|
|
269983
|
+
await fs35.writeFile(tmpPath, JSON.stringify(ledger, null, 2), "utf-8");
|
|
269984
|
+
await fs35.rename(tmpPath, filePath);
|
|
268776
269985
|
} catch {
|
|
268777
269986
|
try {
|
|
268778
|
-
await
|
|
269987
|
+
await fs35.unlink(tmpPath);
|
|
268779
269988
|
} catch {}
|
|
268780
269989
|
}
|
|
268781
269990
|
}
|
|
@@ -268973,7 +270182,7 @@ var init_usage_rates2 = __esm(() => {
|
|
|
268973
270182
|
// src/utils/error-parser.ts
|
|
268974
270183
|
import util5 from "util";
|
|
268975
270184
|
function isCreditOrBalanceError(combined) {
|
|
268976
|
-
return combined.includes("insufficient balance") || combined.includes("insufficient credits") || combined.includes("insufficient_balance") || combined.includes("insufficient_credits") || combined.includes("insufficient_quota") || combined.includes("balance is insufficient") || combined.includes("balance insufficient") || combined.includes("balance exhausted") || combined.includes("out of credits") || combined.includes("credit balance is too low") || combined.includes("credits exhausted") || combined.includes("requires more credits") || combined.includes("can only afford") || combined.includes("payment required") || combined.includes("quota exceeded") || combined.includes("quota_exhausted") || combined.includes("402") || combined.includes("1008") || combined.includes("20009") || (combined.includes("credits") || combined.includes("balance")) && (combined.includes("insufficient") || combined.includes("exhausted") || combined.includes("empty") || combined.includes("zero") || combined.includes("low") || combined.includes("top up") || combined.includes("recharge") || combined.includes("afford") || combined.includes("add credits"));
|
|
270185
|
+
return combined.includes("insufficient balance") || combined.includes("insufficient credits") || combined.includes("insufficient_balance") || combined.includes("insufficient_credits") || combined.includes("insufficient_quota") || combined.includes("balance is insufficient") || combined.includes("balance insufficient") || combined.includes("balance exhausted") || combined.includes("out of credits") || combined.includes("credit balance is too low") || combined.includes("credits exhausted") || combined.includes("requires more credits") || combined.includes("can only afford") || combined.includes("payment required") || combined.includes("quota exceeded") || combined.includes("quota_exhausted") || combined.includes("budget_exhausted") || combined.includes("budget exhausted") || combined.includes("budget exceeded") || combined.includes("budget_exceeded") || combined.includes("402") || combined.includes("1008") || combined.includes("20009") || (combined.includes("credits") || combined.includes("balance")) && (combined.includes("insufficient") || combined.includes("exhausted") || combined.includes("empty") || combined.includes("zero") || combined.includes("low") || combined.includes("top up") || combined.includes("recharge") || combined.includes("afford") || combined.includes("add credits"));
|
|
268977
270186
|
}
|
|
268978
270187
|
function normalizeProviderAlias(provider) {
|
|
268979
270188
|
if (!provider)
|
|
@@ -269357,7 +270566,8 @@ function parseErrorMessage(err, context) {
|
|
|
269357
270566
|
}
|
|
269358
270567
|
const contextStr = `${context?.provider || ""} ${context?.model || ""}`.toLowerCase().trim();
|
|
269359
270568
|
const lowerStr = (errMsg + " " + (finalResult || "") + (contextStr ? " " + contextStr : "")).toLowerCase();
|
|
269360
|
-
const
|
|
270569
|
+
const isBudgetExhausted = lowerStr.includes("budget_exhausted") || lowerStr.includes("budget exhausted") || lowerStr.includes("budget_exceeded") || lowerStr.includes("budget exceeded");
|
|
270570
|
+
const isRateLimit = !isBudgetExhausted && (lowerStr.includes("429") || lowerStr.includes("quota") || lowerStr.includes("rate limit") || lowerStr.includes("rate_limit") || lowerStr.includes("resource_exhausted") || lowerStr.includes("generativelanguage.googleapis.com"));
|
|
269361
270571
|
if (isRateLimit && !finalResult.includes("Rate limit or quota exhausted")) {
|
|
269362
270572
|
const rateDetails = resolveRateLimitDetails(lowerStr, context);
|
|
269363
270573
|
return rateDetails.notice + finalResult;
|
|
@@ -269398,7 +270608,8 @@ function parseError(err, context) {
|
|
|
269398
270608
|
const contextStr = `${context?.provider || ""} ${context?.model || ""}`.toLowerCase().trim();
|
|
269399
270609
|
const fullMessage = parseErrorMessage(err, context);
|
|
269400
270610
|
const combined = `${fullMessage} ${explicitCause || ""} ${contextStr ? " " + contextStr : ""}`.toLowerCase();
|
|
269401
|
-
const
|
|
270611
|
+
const isBudgetExhausted = combined.includes("budget_exhausted") || combined.includes("budget exhausted") || combined.includes("budget_exceeded") || combined.includes("budget exceeded");
|
|
270612
|
+
const isRateLimit = !isBudgetExhausted && (combined.includes("429") || combined.includes("quota") || combined.includes("rate limit") || combined.includes("rate_limit") || combined.includes("resource_exhausted") || combined.includes("generativelanguage.googleapis.com"));
|
|
269402
270613
|
if (isRateLimit) {
|
|
269403
270614
|
const parts = fullMessage.split(`
|
|
269404
270615
|
`);
|
|
@@ -270040,7 +271251,7 @@ var init_error_parser = __esm(() => {
|
|
|
270040
271251
|
{
|
|
270041
271252
|
id: "auriko",
|
|
270042
271253
|
name: "Auriko",
|
|
270043
|
-
match: (str) => (str.includes("auriko.ai") || str.includes("api.auriko.ai") || str.includes("auriko")) && (isCreditOrBalanceError(str) || str.includes("credits") || str.includes("402")),
|
|
271254
|
+
match: (str) => (str.includes("auriko.ai") || str.includes("api.auriko.ai") || str.includes("auriko")) && (isCreditOrBalanceError(str) || str.includes("credits") || str.includes("budget") || str.includes("402")),
|
|
270044
271255
|
notice: `Insufficient credits in your Auriko account. Please check your account at https://www.auriko.ai/dashboard
|
|
270045
271256
|
`,
|
|
270046
271257
|
message: "Insufficient credits in your Auriko account.",
|
|
@@ -270210,14 +271421,14 @@ function extractJsonArray(rawText) {
|
|
|
270210
271421
|
}
|
|
270211
271422
|
|
|
270212
271423
|
// src/utils/project-context.ts
|
|
270213
|
-
import
|
|
270214
|
-
import
|
|
271424
|
+
import fs36 from "node:fs";
|
|
271425
|
+
import path36 from "node:path";
|
|
270215
271426
|
function getProjectContext(workspaceDir = process.cwd()) {
|
|
270216
271427
|
const parts = [];
|
|
270217
271428
|
try {
|
|
270218
|
-
const pkgPath =
|
|
270219
|
-
if (
|
|
270220
|
-
const pkg = JSON.parse(
|
|
271429
|
+
const pkgPath = path36.join(workspaceDir, "package.json");
|
|
271430
|
+
if (fs36.existsSync(pkgPath)) {
|
|
271431
|
+
const pkg = JSON.parse(fs36.readFileSync(pkgPath, "utf8"));
|
|
270221
271432
|
const deps = Object.keys(pkg.dependencies || {}).slice(0, 15).join(", ");
|
|
270222
271433
|
const devDeps = Object.keys(pkg.devDependencies || {}).slice(0, 10).join(", ");
|
|
270223
271434
|
parts.push(`Project: ${pkg.name || "Unnamed"}`);
|
|
@@ -270226,13 +271437,13 @@ function getProjectContext(workspaceDir = process.cwd()) {
|
|
|
270226
271437
|
if (devDeps)
|
|
270227
271438
|
parts.push(`DevDependencies: ${devDeps}`);
|
|
270228
271439
|
}
|
|
270229
|
-
const agentsPath =
|
|
270230
|
-
if (
|
|
270231
|
-
const content =
|
|
271440
|
+
const agentsPath = path36.join(workspaceDir, "AGENTS.md");
|
|
271441
|
+
if (fs36.existsSync(agentsPath)) {
|
|
271442
|
+
const content = fs36.readFileSync(agentsPath, "utf8");
|
|
270232
271443
|
parts.push(`Guidelines (from AGENTS.md):
|
|
270233
271444
|
${content.slice(0, 500)}`);
|
|
270234
271445
|
}
|
|
270235
|
-
const entries =
|
|
271446
|
+
const entries = fs36.readdirSync(workspaceDir, { withFileTypes: true }).filter((e) => !e.name.startsWith(".") && e.name !== "node_modules").map((e) => e.isDirectory() ? `${e.name}/` : e.name).slice(0, 20);
|
|
270236
271447
|
if (entries.length > 0) {
|
|
270237
271448
|
parts.push(`Workspace layout: ${entries.join(", ")}`);
|
|
270238
271449
|
}
|
|
@@ -270387,14 +271598,14 @@ async function fetchProviderBalance(provider, apiKey, timeoutMs = 2000) {
|
|
|
270387
271598
|
}
|
|
270388
271599
|
|
|
270389
271600
|
// src/utils/formatters.ts
|
|
270390
|
-
import
|
|
271601
|
+
import path37 from "node:path";
|
|
270391
271602
|
function toRelativePath2(filePath, cwd = process.cwd()) {
|
|
270392
271603
|
if (!filePath)
|
|
270393
271604
|
return "";
|
|
270394
271605
|
const trimmed = filePath.trim();
|
|
270395
|
-
if (!
|
|
271606
|
+
if (!path37.isAbsolute(trimmed))
|
|
270396
271607
|
return trimmed;
|
|
270397
|
-
const rel =
|
|
271608
|
+
const rel = path37.relative(cwd, trimmed);
|
|
270398
271609
|
if (!rel || rel.startsWith("..")) {
|
|
270399
271610
|
return trimmed;
|
|
270400
271611
|
}
|
|
@@ -271134,7 +272345,7 @@ ${formatSubscriptionCard(bundle, targetModel)}`
|
|
|
271134
272345
|
const probeAbortController = new AbortController;
|
|
271135
272346
|
const probeTimeout = setTimeout(() => {
|
|
271136
272347
|
probeAbortController.abort(new Error("Connection timed out while verifying API key."));
|
|
271137
|
-
},
|
|
272348
|
+
}, 8000);
|
|
271138
272349
|
try {
|
|
271139
272350
|
const stream = testProvider.stream([{ role: "user", content: "Hi" }], undefined, undefined, {
|
|
271140
272351
|
model: testModel,
|
|
@@ -271151,15 +272362,19 @@ ${formatSubscriptionCard(bundle, targetModel)}`
|
|
|
271151
272362
|
}
|
|
271152
272363
|
} catch (probeErr) {
|
|
271153
272364
|
lastProbeErr = probeErr;
|
|
271154
|
-
const errText =
|
|
272365
|
+
const errText = `${probeErr?.message || ""} ${probeErr?.code || ""} ${probeErr?.error?.code || ""} ${String(probeErr)}`.toLowerCase();
|
|
271155
272366
|
if (errText.includes("401") || errText.includes("unauthorized") || errText.includes("invalid api key") || errText.includes("incorrect api key")) {
|
|
271156
272367
|
throw probeErr;
|
|
271157
272368
|
}
|
|
271158
|
-
if (errText.includes("402") || errText.includes("credits") || errText.includes("payment") || errText.includes("afford") || errText.includes("insufficient_quota")) {
|
|
272369
|
+
if (errText.includes("402") || errText.includes("credits") || errText.includes("payment") || errText.includes("afford") || errText.includes("budget") || errText.includes("balance") || errText.includes("insufficient_quota")) {
|
|
271159
272370
|
if (!lowCreditErr) {
|
|
271160
272371
|
lowCreditErr = probeErr;
|
|
271161
272372
|
lowCreditModel = testModel;
|
|
271162
272373
|
}
|
|
272374
|
+
break;
|
|
272375
|
+
}
|
|
272376
|
+
if (errText.includes("timed out") || errText.includes("timeout") || probeErr?.name === "AbortError") {
|
|
272377
|
+
break;
|
|
271163
272378
|
}
|
|
271164
272379
|
}
|
|
271165
272380
|
}
|
|
@@ -271199,10 +272414,10 @@ ${formatSubscriptionCard(bundle, targetModel)}`
|
|
|
271199
272414
|
setApiKey("");
|
|
271200
272415
|
addToast(MESSAGES.AUTH.API_KEY_SAVED(selectedProvider), "success");
|
|
271201
272416
|
} catch (err) {
|
|
271202
|
-
const errStr =
|
|
272417
|
+
const errStr = `${err?.message || ""} ${err?.code || ""} ${err?.error?.code || ""} ${String(err)}`.toLowerCase();
|
|
271203
272418
|
const isTimeout = err?.name === "AbortError" || errStr.includes("aborted") || errStr.includes("timed out") || errStr.includes("timeout");
|
|
271204
|
-
const isLowCredit = errStr.includes("402") || errStr.includes("credits") || errStr.includes("payment") || errStr.includes("afford");
|
|
271205
|
-
if (errStr.includes("429") || errStr.includes("quota") || errStr.includes("rate limit") || errStr.includes("404") || errStr.includes("not found") || errStr.includes("503") || errStr.includes("无可用渠道") || errStr.includes("no available channel") || isLowCredit) {
|
|
272419
|
+
const isLowCredit = errStr.includes("402") || errStr.includes("credits") || errStr.includes("payment") || errStr.includes("afford") || errStr.includes("budget") || errStr.includes("balance") || errStr.includes("insufficient_quota");
|
|
272420
|
+
if (errStr.includes("429") || errStr.includes("quota") || errStr.includes("rate limit") || errStr.includes("404") || errStr.includes("not found") || errStr.includes("503") || errStr.includes("无可用渠道") || errStr.includes("no available channel") || errStr.includes("platform_keys_unavailable") || errStr.includes("byok_keys_required") || errStr.includes("tier_opt_in_required") || errStr.includes("no_provider_available") || isLowCredit) {
|
|
271206
272421
|
await Promise.resolve().then(() => init_models5());
|
|
271207
272422
|
const finalModel = testModel || getDefaultModelForProvider(selectedProvider);
|
|
271208
272423
|
const config = await loadConfig();
|
|
@@ -273793,7 +275008,7 @@ var init_use_agent_session = __esm(async () => {
|
|
|
273793
275008
|
|
|
273794
275009
|
// src/index.ts
|
|
273795
275010
|
init_package();
|
|
273796
|
-
import
|
|
275011
|
+
import path38 from "node:path";
|
|
273797
275012
|
|
|
273798
275013
|
// src/args.ts
|
|
273799
275014
|
import { parseArgs } from "node:util";
|
|
@@ -273931,12 +275146,12 @@ Options:
|
|
|
273931
275146
|
}
|
|
273932
275147
|
// src/constants/release-highlights.json
|
|
273933
275148
|
var release_highlights_default = {
|
|
273934
|
-
version: "0.4.
|
|
273935
|
-
title: "What's New in v0.4.
|
|
275149
|
+
version: "0.4.4",
|
|
275150
|
+
title: "What's New in v0.4.4",
|
|
273936
275151
|
bullets: [
|
|
273937
|
-
"
|
|
273938
|
-
"*(
|
|
273939
|
-
"*(
|
|
275152
|
+
"*(agent)* Passive workspace memory ingestion and manage_memory tool",
|
|
275153
|
+
"*(agent)* Lsp client integration for definition and reference navigation",
|
|
275154
|
+
"*(tools)* Prefer non-import lines when resolving symbol definition in code_intelligence"
|
|
273940
275155
|
],
|
|
273941
275156
|
url: "https://trydecember.com/docs/changelog"
|
|
273942
275157
|
};
|
|
@@ -274137,7 +275352,7 @@ To define project-specific instructions, create an AGENTS.md file in your projec
|
|
|
274137
275352
|
sessionRepository,
|
|
274138
275353
|
sessionId,
|
|
274139
275354
|
runtime: "cli",
|
|
274140
|
-
workspaceDir: parsedArgs.scope ?
|
|
275355
|
+
workspaceDir: parsedArgs.scope ? path38.resolve(process.cwd(), parsedArgs.scope) : process.cwd(),
|
|
274141
275356
|
thinkingLevel: config.thinkingLevel || "auto",
|
|
274142
275357
|
steeringMode: config.steeringMode || "all",
|
|
274143
275358
|
followUpMode: config.followUpMode || "all"
|
|
@@ -274241,7 +275456,7 @@ Executing Headless Task: "${parsedArgs.prompt}"
|
|
|
274241
275456
|
sessionRepository,
|
|
274242
275457
|
sessionId,
|
|
274243
275458
|
runtime: "cli",
|
|
274244
|
-
workspaceDir: parsedArgs.scope ?
|
|
275459
|
+
workspaceDir: parsedArgs.scope ? path38.resolve(process.cwd(), parsedArgs.scope) : process.cwd(),
|
|
274245
275460
|
thinkingLevel: config.thinkingLevel || "auto",
|
|
274246
275461
|
steeringMode: config.steeringMode || "all",
|
|
274247
275462
|
followUpMode: config.followUpMode || "all"
|