@wrongstack/core 0.89.1 → 0.104.0
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/{agent-bridge-B8F2ORwg.d.ts → agent-bridge-mOxbpFcg.d.ts} +1 -1
- package/dist/{agent-subagent-runner-CQaLFNnA.d.ts → agent-subagent-runner-DukQLUcS.d.ts} +433 -433
- package/dist/{events-DzyLtja6.d.ts → brain-Dfv4Y82E.d.ts} +179 -92
- package/dist/{compactor-CJq7LQev.d.ts → compactor-DXLxLcmU.d.ts} +2 -2
- package/dist/{config-_DZ7dN-T.d.ts → config-BSU-6vah.d.ts} +45 -38
- package/dist/{context-ToHAp4-U.d.ts → context-CNRYfhUv.d.ts} +1 -1
- package/dist/coordination/index.d.ts +16 -17
- package/dist/coordination/index.js +128 -37
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +34 -35
- package/dist/defaults/index.js +752 -218
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-CgIc30qi.d.ts → director-state-BfeCUbmk.d.ts} +1 -1
- package/dist/execution/index.d.ts +65 -370
- package/dist/execution/index.js +446 -53
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +9 -10
- package/dist/extension/index.js +8 -6
- package/dist/extension/index.js.map +1 -1
- package/dist/goal-preamble-CI8lxeY1.d.ts +378 -0
- package/dist/{goal-store-DvWLNu52.d.ts → goal-store-ht0VmR1A.d.ts} +63 -21
- package/dist/{index-Ca_lOmKl.d.ts → index-BWRN6wOb.d.ts} +13 -15
- package/dist/{index-Dx-CnrDN.d.ts → index-DIKEcfgC.d.ts} +9 -10
- package/dist/index.d.ts +188 -176
- package/dist/index.js +1508 -407
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -9
- package/dist/infrastructure/index.js +4 -2
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +14 -16
- package/dist/kernel/index.js.map +1 -1
- package/dist/{logger-B72yyPc6.d.ts → logger-B63L5bTg.d.ts} +1 -1
- package/dist/{logger-C_27pj9i.d.ts → logger-B9J5puGM.d.ts} +1 -1
- package/dist/{mcp-servers-Dck3T85_.d.ts → mcp-servers-CXCsANdY.d.ts} +3 -3
- package/dist/{mode-CHo2XtHs.d.ts → mode-ARA3HrkY.d.ts} +1 -1
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +8 -6
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-Be3osGt5.d.ts → models-registry-B6_KfS65.d.ts} +1 -1
- package/dist/{models-registry-Boz639EI.d.ts → models-registry-DU64QxQa.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-Da9nd8Ic.d.ts → multi-agent-coordinator-51LvnXkD.d.ts} +2 -2
- package/dist/{null-fleet-bus-CHJOXv3t.d.ts → null-fleet-bus-D09hMzFQ.d.ts} +32 -31
- package/dist/observability/index.d.ts +3 -3
- package/dist/{observability-CoSNZdhX.d.ts → observability-D-HZN_mF.d.ts} +1 -1
- package/dist/{parallel-eternal-engine-DyMCj2Pw.d.ts → parallel-eternal-engine-CUtmM_0V.d.ts} +54 -35
- package/dist/{path-resolver-TjBlRKyH.d.ts → path-resolver-DDJiMAtX.d.ts} +3 -3
- package/dist/{permission-14CChMmO.d.ts → permission-BDv7z0mk.d.ts} +7 -2
- package/dist/{permission-policy-gW5htOo1.d.ts → permission-policy-dF74EpDp.d.ts} +2 -2
- package/dist/{system-prompt-C0rLCeyn.d.ts → pipeline-BqiA_UMr.d.ts} +73 -73
- package/dist/{plan-templates-D9UhwoGh.d.ts → plan-templates-BdDxl9cI.d.ts} +79 -11
- package/dist/{provider-runner-BEPWwkxH.d.ts → provider-runner-BUunikwY.d.ts} +5 -5
- package/dist/{retry-policy-DSu6O6rD.d.ts → retry-policy-BcmuT_V0.d.ts} +2 -2
- package/dist/sdd/index.d.ts +17 -33
- package/dist/sdd/index.js +145 -36
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-scrubber-yGBFQYju.d.ts → secret-vault-DrOhc2i5.d.ts} +7 -7
- package/dist/security/index.d.ts +4 -5
- package/dist/security/index.js +4 -2
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-11-fm95U.d.ts → selector-C7wcdqMA.d.ts} +1 -1
- package/dist/{session-event-bridge-D0u-x576.d.ts → session-event-bridge-BpJ5trO9.d.ts} +2 -2
- package/dist/{session-reader-BQU-toaN.d.ts → session-reader-DDz1Ek4V.d.ts} +2 -2
- package/dist/{skill-BJeF2DwY.d.ts → skill-Bj6Ezqb8.d.ts} +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.js +3 -9
- package/dist/skills/index.js.map +1 -1
- package/dist/spec-TBi3Jr6T.d.ts +78 -0
- package/dist/storage/index.d.ts +145 -13
- package/dist/storage/index.js +990 -172
- package/dist/storage/index.js.map +1 -1
- package/dist/task-format-vGOIftmK.d.ts +23 -0
- package/dist/task-graph-u1q9Jkyk.d.ts +84 -0
- package/dist/types/index.d.ts +27 -28
- package/dist/types/index.js +19 -31
- package/dist/types/index.js.map +1 -1
- package/dist/utils/expect-defined.d.ts +7 -0
- package/dist/utils/expect-defined.js +11 -0
- package/dist/utils/expect-defined.js.map +1 -0
- package/dist/utils/index.d.ts +8 -20
- package/dist/utils/index.js +120 -41
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-BQMvEllz.d.ts → wstack-paths-_lqjzErq.d.ts} +1 -1
- package/package.json +5 -1
- package/skills/tech-stack/SKILL.md +177 -0
- package/dist/memory-CEXuo7sz.d.ts +0 -16
- package/dist/secret-scrubber-3MHDDAtm.d.ts +0 -6
- package/dist/task-graph-CikNdRTG.d.ts +0 -161
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import * as path6 from 'path';
|
|
|
6
6
|
import { join, extname, relative, isAbsolute, resolve, sep } from 'path';
|
|
7
7
|
import * as fs2 from 'fs';
|
|
8
8
|
import * as os7 from 'os';
|
|
9
|
+
import { hostname } from 'os';
|
|
9
10
|
import { execFile, spawn } from 'child_process';
|
|
10
11
|
import { promisify } from 'util';
|
|
11
12
|
import { EventEmitter } from 'events';
|
|
@@ -15,12 +16,6 @@ import { pipeline } from 'stream/promises';
|
|
|
15
16
|
|
|
16
17
|
var __defProp = Object.defineProperty;
|
|
17
18
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
18
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
19
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
20
|
-
}) : x)(function(x) {
|
|
21
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
22
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
23
|
-
});
|
|
24
19
|
var __esm = (fn, res) => function __init() {
|
|
25
20
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
26
21
|
};
|
|
@@ -1713,13 +1708,25 @@ function round4(n) {
|
|
|
1713
1708
|
return Math.round(n * 1e4) / 1e4;
|
|
1714
1709
|
}
|
|
1715
1710
|
|
|
1716
|
-
// src/
|
|
1717
|
-
|
|
1711
|
+
// src/types/memory.ts
|
|
1712
|
+
var MEMORY_TYPE_LABELS = {
|
|
1713
|
+
fact: "Fact",
|
|
1714
|
+
decision: "Decision",
|
|
1715
|
+
convention: "Convention",
|
|
1716
|
+
preference: "Preference",
|
|
1717
|
+
reference: "Reference",
|
|
1718
|
+
anti_pattern: "Anti-pattern"
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
// src/utils/expect-defined.ts
|
|
1722
|
+
function expectDefined(value, label) {
|
|
1718
1723
|
if (value === null || value === void 0) {
|
|
1719
|
-
throw new Error("Expected value to be defined");
|
|
1724
|
+
throw new Error(label ? `Expected ${label} to be defined` : "Expected value to be defined");
|
|
1720
1725
|
}
|
|
1721
1726
|
return value;
|
|
1722
1727
|
}
|
|
1728
|
+
|
|
1729
|
+
// src/utils/token-estimate.ts
|
|
1723
1730
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
1724
1731
|
var _cal = {
|
|
1725
1732
|
ratio: 1,
|
|
@@ -1853,12 +1860,6 @@ function resetCalibration() {
|
|
|
1853
1860
|
}
|
|
1854
1861
|
|
|
1855
1862
|
// src/utils/message-invariants.ts
|
|
1856
|
-
function expectDefined2(value) {
|
|
1857
|
-
if (value === null || value === void 0) {
|
|
1858
|
-
throw new Error("Expected value to be defined");
|
|
1859
|
-
}
|
|
1860
|
-
return value;
|
|
1861
|
-
}
|
|
1862
1863
|
function repairToolUseAdjacency(messages) {
|
|
1863
1864
|
const removedToolUses = [];
|
|
1864
1865
|
const removedToolResults = [];
|
|
@@ -1866,7 +1867,7 @@ function repairToolUseAdjacency(messages) {
|
|
|
1866
1867
|
let changed = false;
|
|
1867
1868
|
const out = [];
|
|
1868
1869
|
for (let i = 0; i < messages.length; i++) {
|
|
1869
|
-
const original =
|
|
1870
|
+
const original = expectDefined(messages[i]);
|
|
1870
1871
|
let msg = original;
|
|
1871
1872
|
if (hasToolUse(msg)) {
|
|
1872
1873
|
const nextIds = toolResultIds(messages[i + 1]);
|
|
@@ -3024,12 +3025,6 @@ Remember: your job is to make the user a better developer, not just to complete
|
|
|
3024
3025
|
];
|
|
3025
3026
|
|
|
3026
3027
|
// src/types/context-window.ts
|
|
3027
|
-
function expectDefined3(value) {
|
|
3028
|
-
if (value === null || value === void 0) {
|
|
3029
|
-
throw new Error("Expected value to be defined");
|
|
3030
|
-
}
|
|
3031
|
-
return value;
|
|
3032
|
-
}
|
|
3033
3028
|
var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
|
|
3034
3029
|
var CONTEXT_WINDOW_MODES = Object.freeze([
|
|
3035
3030
|
{
|
|
@@ -3086,7 +3081,7 @@ function isContextWindowModeId(id) {
|
|
|
3086
3081
|
}
|
|
3087
3082
|
function resolveContextWindowPolicy(config = {}, overrideMode) {
|
|
3088
3083
|
const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
|
|
3089
|
-
const mode = getContextWindowMode(requested) ??
|
|
3084
|
+
const mode = getContextWindowMode(requested) ?? expectDefined(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));
|
|
3090
3085
|
if (mode.id !== DEFAULT_CONTEXT_WINDOW_MODE_ID) {
|
|
3091
3086
|
return mode;
|
|
3092
3087
|
}
|
|
@@ -3566,12 +3561,6 @@ function sizeSignals(toolName, content) {
|
|
|
3566
3561
|
}
|
|
3567
3562
|
|
|
3568
3563
|
// src/execution/tool-executor.ts
|
|
3569
|
-
function expectDefined4(value) {
|
|
3570
|
-
if (value === null || value === void 0) {
|
|
3571
|
-
throw new Error("Expected value to be defined");
|
|
3572
|
-
}
|
|
3573
|
-
return value;
|
|
3574
|
-
}
|
|
3575
3564
|
var ToolExecutor = class {
|
|
3576
3565
|
constructor(registry, opts) {
|
|
3577
3566
|
this.registry = registry;
|
|
@@ -3978,7 +3967,7 @@ function hasMalformedArguments(input) {
|
|
|
3978
3967
|
function extractMalformedRaw(input) {
|
|
3979
3968
|
if (!hasMalformedArguments(input)) return void 0;
|
|
3980
3969
|
const obj = input;
|
|
3981
|
-
const value = obj[
|
|
3970
|
+
const value = obj[expectDefined(Object.keys(obj)[0])];
|
|
3982
3971
|
if (value === void 0 || value === null) return void 0;
|
|
3983
3972
|
if (typeof value === "string") return value;
|
|
3984
3973
|
try {
|
|
@@ -4025,12 +4014,6 @@ function compileUserRegex(pattern, flags) {
|
|
|
4025
4014
|
}
|
|
4026
4015
|
|
|
4027
4016
|
// src/storage/session-reader.ts
|
|
4028
|
-
function expectDefined5(value) {
|
|
4029
|
-
if (value === null || value === void 0) {
|
|
4030
|
-
throw new Error("Expected value to be defined");
|
|
4031
|
-
}
|
|
4032
|
-
return value;
|
|
4033
|
-
}
|
|
4034
4017
|
var DefaultSessionReader = class {
|
|
4035
4018
|
store;
|
|
4036
4019
|
constructor(opts) {
|
|
@@ -4092,7 +4075,7 @@ var DefaultSessionReader = class {
|
|
|
4092
4075
|
continue;
|
|
4093
4076
|
}
|
|
4094
4077
|
for (let i = 0; i < data.events.length; i++) {
|
|
4095
|
-
const ev =
|
|
4078
|
+
const ev = expectDefined(data.events[i]);
|
|
4096
4079
|
if (allowedTypes && !allowedTypes.has(ev.type)) continue;
|
|
4097
4080
|
const text = eventText(ev);
|
|
4098
4081
|
if (text === null) continue;
|
|
@@ -4459,13 +4442,116 @@ function formatTodosList(todos) {
|
|
|
4459
4442
|
return lines.join("\n");
|
|
4460
4443
|
}
|
|
4461
4444
|
|
|
4462
|
-
// src/utils/
|
|
4463
|
-
function
|
|
4464
|
-
|
|
4465
|
-
|
|
4445
|
+
// src/utils/task-format.ts
|
|
4446
|
+
function computeTaskItemProgress(tasks) {
|
|
4447
|
+
let completed = 0;
|
|
4448
|
+
let pending = 0;
|
|
4449
|
+
let inProgress = 0;
|
|
4450
|
+
let blocked = 0;
|
|
4451
|
+
let failed = 0;
|
|
4452
|
+
let review = 0;
|
|
4453
|
+
let estimatedHours = 0;
|
|
4454
|
+
let actualHours = 0;
|
|
4455
|
+
for (const t2 of tasks) {
|
|
4456
|
+
switch (t2.status) {
|
|
4457
|
+
case "completed":
|
|
4458
|
+
completed++;
|
|
4459
|
+
break;
|
|
4460
|
+
case "pending":
|
|
4461
|
+
pending++;
|
|
4462
|
+
break;
|
|
4463
|
+
case "in_progress":
|
|
4464
|
+
inProgress++;
|
|
4465
|
+
break;
|
|
4466
|
+
case "blocked":
|
|
4467
|
+
blocked++;
|
|
4468
|
+
break;
|
|
4469
|
+
case "failed":
|
|
4470
|
+
failed++;
|
|
4471
|
+
break;
|
|
4472
|
+
case "review":
|
|
4473
|
+
review++;
|
|
4474
|
+
break;
|
|
4475
|
+
}
|
|
4476
|
+
estimatedHours += t2.estimateHours ?? 0;
|
|
4466
4477
|
}
|
|
4467
|
-
return
|
|
4478
|
+
return {
|
|
4479
|
+
total: tasks.length,
|
|
4480
|
+
pending,
|
|
4481
|
+
inProgress,
|
|
4482
|
+
blocked,
|
|
4483
|
+
failed,
|
|
4484
|
+
review,
|
|
4485
|
+
completed,
|
|
4486
|
+
percentComplete: tasks.length > 0 ? Math.round(completed / tasks.length * 100) : 0,
|
|
4487
|
+
estimatedHours,
|
|
4488
|
+
actualHours
|
|
4489
|
+
};
|
|
4490
|
+
}
|
|
4491
|
+
var STATUS_ICON = {
|
|
4492
|
+
pending: "\u25CB",
|
|
4493
|
+
in_progress: "\u25D0",
|
|
4494
|
+
blocked: "\u2298",
|
|
4495
|
+
failed: "\u2717",
|
|
4496
|
+
review: "\u25D1",
|
|
4497
|
+
completed: "\u25CF"
|
|
4498
|
+
};
|
|
4499
|
+
var PRIORITY_ICON = {
|
|
4500
|
+
critical: "\u{1F534}",
|
|
4501
|
+
high: "\u{1F7E0}",
|
|
4502
|
+
medium: "\u{1F7E1}",
|
|
4503
|
+
low: "\u{1F7E2}"
|
|
4504
|
+
};
|
|
4505
|
+
var TYPE_ICON = {
|
|
4506
|
+
feature: "\u26A1",
|
|
4507
|
+
bugfix: "\u{1F41B}",
|
|
4508
|
+
refactor: "\u267B\uFE0F",
|
|
4509
|
+
docs: "\u{1F4DD}",
|
|
4510
|
+
test: "\u{1F9EA}",
|
|
4511
|
+
chore: "\u{1F527}"
|
|
4512
|
+
};
|
|
4513
|
+
function formatTaskProgress(tasks) {
|
|
4514
|
+
const p = computeTaskItemProgress(tasks);
|
|
4515
|
+
if (p.total === 0) return "No tasks.";
|
|
4516
|
+
const barWidth = 24;
|
|
4517
|
+
const filled = Math.round(p.percentComplete / 100 * barWidth);
|
|
4518
|
+
const empty = barWidth - filled;
|
|
4519
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
4520
|
+
return [
|
|
4521
|
+
`${color.bold("Tasks")} [${bar}] ${p.percentComplete}%`,
|
|
4522
|
+
` ${color.green("\u25CF")} ${p.completed} done \u2502 ${color.yellow("\u25D0")} ${p.inProgress} active \u2502 ${color.dim("\u25CB")} ${p.pending} pending \u2502 \u2298 ${p.blocked} blocked \u2502 \u2717 ${p.failed} failed`,
|
|
4523
|
+
p.estimatedHours > 0 ? ` ${color.dim(`est. ${p.estimatedHours}h`)}` : ""
|
|
4524
|
+
].filter(Boolean).join("\n");
|
|
4525
|
+
}
|
|
4526
|
+
function formatTaskList(tasks) {
|
|
4527
|
+
if (tasks.length === 0) return "No tasks.";
|
|
4528
|
+
const order = ["in_progress", "blocked", "review", "pending", "failed", "completed"];
|
|
4529
|
+
const groups = /* @__PURE__ */ new Map();
|
|
4530
|
+
for (const t2 of tasks) {
|
|
4531
|
+
const list = groups.get(t2.status) ?? [];
|
|
4532
|
+
list.push(t2);
|
|
4533
|
+
groups.set(t2.status, list);
|
|
4534
|
+
}
|
|
4535
|
+
const lines = [];
|
|
4536
|
+
lines.push(color.dim(`Tasks (${tasks.length} total):`));
|
|
4537
|
+
for (const status of order) {
|
|
4538
|
+
const group = groups.get(status);
|
|
4539
|
+
if (!group || group.length === 0) continue;
|
|
4540
|
+
const icon = STATUS_ICON[status];
|
|
4541
|
+
lines.push(` ${icon} ${status.toUpperCase()} (${group.length})`);
|
|
4542
|
+
for (const t2 of group) {
|
|
4543
|
+
const prio = PRIORITY_ICON[t2.priority];
|
|
4544
|
+
const type = TYPE_ICON[t2.type];
|
|
4545
|
+
const deps = t2.dependsOn && t2.dependsOn.length > 0 ? ` ${color.dim("\u2190")} ${color.dim(t2.dependsOn.map((d) => d.slice(0, 8)).join(", "))}` : "";
|
|
4546
|
+
const who = t2.assignee ? ` ${color.dim(`@${t2.assignee}`)}` : "";
|
|
4547
|
+
const hrs = t2.estimateHours ? ` ${color.dim(`${t2.estimateHours}h`)}` : "";
|
|
4548
|
+
lines.push(` ${type} ${prio} ${t2.title}${deps}${who}${hrs}`);
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
return lines.join("\n");
|
|
4468
4552
|
}
|
|
4553
|
+
|
|
4554
|
+
// src/utils/glob-match.ts
|
|
4469
4555
|
function escapeRegex(s) {
|
|
4470
4556
|
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
4471
4557
|
}
|
|
@@ -4477,7 +4563,7 @@ function getCachedGlob(pattern) {
|
|
|
4477
4563
|
if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {
|
|
4478
4564
|
const keys = [...COMPILED_GLOB_CACHE.keys()];
|
|
4479
4565
|
for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {
|
|
4480
|
-
COMPILED_GLOB_CACHE.delete(
|
|
4566
|
+
COMPILED_GLOB_CACHE.delete(expectDefined(keys[i]));
|
|
4481
4567
|
}
|
|
4482
4568
|
}
|
|
4483
4569
|
const re = compileGlob(pattern);
|
|
@@ -4837,20 +4923,6 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
4837
4923
|
function sleep(ms) {
|
|
4838
4924
|
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
4839
4925
|
}
|
|
4840
|
-
|
|
4841
|
-
// src/utils/expect-defined.ts
|
|
4842
|
-
function expectDefined7(value) {
|
|
4843
|
-
if (value === null || value === void 0) {
|
|
4844
|
-
throw new Error("Expected value to be defined");
|
|
4845
|
-
}
|
|
4846
|
-
return value;
|
|
4847
|
-
}
|
|
4848
|
-
function expectDefined8(value) {
|
|
4849
|
-
if (value === null || value === void 0) {
|
|
4850
|
-
throw new Error("Expected value to be defined");
|
|
4851
|
-
}
|
|
4852
|
-
return value;
|
|
4853
|
-
}
|
|
4854
4926
|
var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
4855
4927
|
var IS_WINDOWS = process.platform === "win32";
|
|
4856
4928
|
var SEP = IS_WINDOWS ? "\\" : "/";
|
|
@@ -4864,7 +4936,7 @@ function globToRegex(pat) {
|
|
|
4864
4936
|
let i = 0;
|
|
4865
4937
|
let re = "^";
|
|
4866
4938
|
while (i < pat.length) {
|
|
4867
|
-
const c =
|
|
4939
|
+
const c = expectDefined(pat[i]);
|
|
4868
4940
|
if (c === "*") {
|
|
4869
4941
|
if (pat[i + 1] === "*") {
|
|
4870
4942
|
re += ".*";
|
|
@@ -4903,7 +4975,7 @@ function globToRegex(pat) {
|
|
|
4903
4975
|
}
|
|
4904
4976
|
function baseDir(pat) {
|
|
4905
4977
|
let i = pat.length - 1;
|
|
4906
|
-
while (i >= 0 && !GLOB_CHARS.has(
|
|
4978
|
+
while (i >= 0 && !GLOB_CHARS.has(expectDefined(pat[i])) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
4907
4979
|
const cut = i >= 0 ? pat.lastIndexOf(SEP, i) : pat.lastIndexOf("/", i);
|
|
4908
4980
|
return cut < 0 ? "." : pat.slice(0, cut);
|
|
4909
4981
|
}
|
|
@@ -4968,12 +5040,6 @@ async function expandGlob(pattern) {
|
|
|
4968
5040
|
}
|
|
4969
5041
|
|
|
4970
5042
|
// src/utils/json-repair.ts
|
|
4971
|
-
function expectDefined9(value) {
|
|
4972
|
-
if (value === null || value === void 0) {
|
|
4973
|
-
throw new Error("Expected value to be defined");
|
|
4974
|
-
}
|
|
4975
|
-
return value;
|
|
4976
|
-
}
|
|
4977
5043
|
function completePartialObject(s) {
|
|
4978
5044
|
if (!s.trim().startsWith("{")) return s;
|
|
4979
5045
|
if (tryParse(s).ok) return s;
|
|
@@ -4985,7 +5051,7 @@ function completePartialObject(s) {
|
|
|
4985
5051
|
let contentEnd = 0;
|
|
4986
5052
|
let stringBraceDepth = 0;
|
|
4987
5053
|
for (let i = 0; i < s.length; i++) {
|
|
4988
|
-
const ch =
|
|
5054
|
+
const ch = expectDefined(s[i]);
|
|
4989
5055
|
if (inString) {
|
|
4990
5056
|
contentEnd = i + 1;
|
|
4991
5057
|
if (escaped) {
|
|
@@ -5081,12 +5147,6 @@ function mergeCustomModelDefs(providerCustomModels, configModels) {
|
|
|
5081
5147
|
|
|
5082
5148
|
// src/storage/session-store.ts
|
|
5083
5149
|
init_atomic_write();
|
|
5084
|
-
function expectDefined10(value) {
|
|
5085
|
-
if (value === null || value === void 0) {
|
|
5086
|
-
throw new Error("Expected value to be defined");
|
|
5087
|
-
}
|
|
5088
|
-
return value;
|
|
5089
|
-
}
|
|
5090
5150
|
function sanitizeModel(model) {
|
|
5091
5151
|
return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
5092
5152
|
}
|
|
@@ -5797,7 +5857,7 @@ var FileSessionWriter = class {
|
|
|
5797
5857
|
let targetCheckpointLine = -1;
|
|
5798
5858
|
let afterTarget = false;
|
|
5799
5859
|
for (let i = 0; i < lines.length; i++) {
|
|
5800
|
-
const line =
|
|
5860
|
+
const line = expectDefined(lines[i]);
|
|
5801
5861
|
if (!line.trim()) continue;
|
|
5802
5862
|
let event;
|
|
5803
5863
|
try {
|
|
@@ -6092,12 +6152,224 @@ function mergeAdjacentText(blocks) {
|
|
|
6092
6152
|
}
|
|
6093
6153
|
return out;
|
|
6094
6154
|
}
|
|
6155
|
+
init_atomic_write();
|
|
6156
|
+
var TYPE_PRIORITY_RE = /^\[(\w+)\|(\w+)\]\s+/;
|
|
6157
|
+
var TAG_RE = /#([\w-]+)/g;
|
|
6158
|
+
function formatMetadata(entry) {
|
|
6159
|
+
const parts = [];
|
|
6160
|
+
if (entry.type && entry.priority) {
|
|
6161
|
+
parts.push(`[${entry.type}|${entry.priority}]`);
|
|
6162
|
+
} else if (entry.type) {
|
|
6163
|
+
parts.push(`[${entry.type}]`);
|
|
6164
|
+
} else if (entry.priority) {
|
|
6165
|
+
parts.push(`[${entry.priority}]`);
|
|
6166
|
+
}
|
|
6167
|
+
if (entry.tags && entry.tags.length > 0) {
|
|
6168
|
+
parts.push(entry.tags.map((t2) => `#${t2}`).join(" "));
|
|
6169
|
+
}
|
|
6170
|
+
return parts.length > 0 ? ` ${parts.join(" ")}` : "";
|
|
6171
|
+
}
|
|
6172
|
+
function lineToEntry(line, scope) {
|
|
6173
|
+
const trimmed = line.trim();
|
|
6174
|
+
if (!trimmed.startsWith("- [")) return null;
|
|
6175
|
+
const tsMatch = trimmed.match(/^-\s*\[([^\]]+)\]/);
|
|
6176
|
+
if (!tsMatch) return null;
|
|
6177
|
+
const ts = tsMatch[1] ?? "";
|
|
6178
|
+
let rest = trimmed.slice(tsMatch[0].length).trim();
|
|
6179
|
+
let type;
|
|
6180
|
+
let priority;
|
|
6181
|
+
const tpMatch = rest.match(TYPE_PRIORITY_RE);
|
|
6182
|
+
if (tpMatch) {
|
|
6183
|
+
const a = tpMatch[1] ?? "";
|
|
6184
|
+
const b = tpMatch[2] ?? "";
|
|
6185
|
+
if (isMemoryType(a)) {
|
|
6186
|
+
type = a;
|
|
6187
|
+
priority = isPriority(b) ? b : void 0;
|
|
6188
|
+
} else if (isPriority(a)) {
|
|
6189
|
+
priority = a;
|
|
6190
|
+
}
|
|
6191
|
+
rest = rest.slice(tpMatch[0].length).trim();
|
|
6192
|
+
}
|
|
6193
|
+
const idMatch = rest.match(/^mem_\d+_\w+\s+/);
|
|
6194
|
+
let text;
|
|
6195
|
+
if (idMatch) {
|
|
6196
|
+
text = rest.slice(idMatch[0].length).trim();
|
|
6197
|
+
} else {
|
|
6198
|
+
text = rest.trim();
|
|
6199
|
+
}
|
|
6200
|
+
const tags = [];
|
|
6201
|
+
let tagMatch;
|
|
6202
|
+
TAG_RE.lastIndex = 0;
|
|
6203
|
+
while ((tagMatch = TAG_RE.exec(text)) !== null) {
|
|
6204
|
+
tags.push(tagMatch[1] ?? "");
|
|
6205
|
+
}
|
|
6206
|
+
const cleanText = text.replace(TAG_RE, "").replace(/\s{2,}/g, " ").trim();
|
|
6207
|
+
if (!cleanText) return null;
|
|
6208
|
+
return {
|
|
6209
|
+
scope,
|
|
6210
|
+
text: cleanText,
|
|
6211
|
+
ts,
|
|
6212
|
+
type,
|
|
6213
|
+
priority,
|
|
6214
|
+
tags: tags.length > 0 ? tags : void 0
|
|
6215
|
+
};
|
|
6216
|
+
}
|
|
6217
|
+
function isMemoryType(s) {
|
|
6218
|
+
return s in MEMORY_TYPE_LABELS;
|
|
6219
|
+
}
|
|
6220
|
+
function isPriority(s) {
|
|
6221
|
+
return s === "critical" || s === "high" || s === "medium" || s === "low";
|
|
6222
|
+
}
|
|
6223
|
+
var FileMemoryBackend = class {
|
|
6224
|
+
kind = "file";
|
|
6225
|
+
files;
|
|
6226
|
+
constructor(opts) {
|
|
6227
|
+
this.files = {
|
|
6228
|
+
"project-agents": opts.paths.inProjectAgentsFile,
|
|
6229
|
+
"project-memory": opts.paths.projectMemory,
|
|
6230
|
+
"user-memory": opts.paths.globalMemory
|
|
6231
|
+
};
|
|
6232
|
+
}
|
|
6233
|
+
resolveFile(filePath, scope) {
|
|
6234
|
+
return filePath || this.files[scope];
|
|
6235
|
+
}
|
|
6236
|
+
async remember(scope, entry, filePath) {
|
|
6237
|
+
const file = this.resolveFile(filePath, scope);
|
|
6238
|
+
await ensureDir(path6.dirname(file));
|
|
6239
|
+
let existing = "";
|
|
6240
|
+
try {
|
|
6241
|
+
existing = await fsp3.readFile(file, "utf8");
|
|
6242
|
+
} catch {
|
|
6243
|
+
}
|
|
6244
|
+
const id = `mem_${Date.now()}_${randomUUID().slice(0, 8)}`;
|
|
6245
|
+
const meta = formatMetadata(entry);
|
|
6246
|
+
const line = `
|
|
6247
|
+
- [${entry.ts}] ${id}${meta} ${entry.text.replace(/\n/g, " ")}
|
|
6248
|
+
`;
|
|
6249
|
+
const next = existing.trim() ? existing.replace(/\n+$/, "") + line : `# WrongStack Memory
|
|
6250
|
+
${line}`;
|
|
6251
|
+
await atomicWrite(file, next);
|
|
6252
|
+
}
|
|
6253
|
+
async forget(scope, query, filePath) {
|
|
6254
|
+
const file = this.resolveFile(filePath, scope);
|
|
6255
|
+
let existing;
|
|
6256
|
+
try {
|
|
6257
|
+
existing = await fsp3.readFile(file, "utf8");
|
|
6258
|
+
} catch {
|
|
6259
|
+
return 0;
|
|
6260
|
+
}
|
|
6261
|
+
const needle = query.toLowerCase();
|
|
6262
|
+
const idMatcher = /mem_\d+_\w+/;
|
|
6263
|
+
let removed = 0;
|
|
6264
|
+
const lines = existing.split("\n").filter((line) => {
|
|
6265
|
+
const trimmed = line.trim();
|
|
6266
|
+
if (!trimmed.startsWith("- ")) return true;
|
|
6267
|
+
if (idMatcher.test(query)) {
|
|
6268
|
+
const entryIdMatch = /mem_\d+_\w+/.exec(trimmed);
|
|
6269
|
+
if (entryIdMatch && entryIdMatch[0] === query) {
|
|
6270
|
+
removed++;
|
|
6271
|
+
return false;
|
|
6272
|
+
}
|
|
6273
|
+
}
|
|
6274
|
+
if (trimmed.toLowerCase().includes(needle)) {
|
|
6275
|
+
removed++;
|
|
6276
|
+
return false;
|
|
6277
|
+
}
|
|
6278
|
+
return true;
|
|
6279
|
+
});
|
|
6280
|
+
if (removed > 0) {
|
|
6281
|
+
if (lines.length === 0 || lines.length === 1 && !lines[0]?.trim()) {
|
|
6282
|
+
await atomicWrite(file, "");
|
|
6283
|
+
} else {
|
|
6284
|
+
await atomicWrite(file, lines.join("\n"));
|
|
6285
|
+
}
|
|
6286
|
+
}
|
|
6287
|
+
return removed;
|
|
6288
|
+
}
|
|
6289
|
+
async readAll(scope, filePath) {
|
|
6290
|
+
const file = this.resolveFile(filePath, scope);
|
|
6291
|
+
try {
|
|
6292
|
+
return await fsp3.readFile(file, "utf8");
|
|
6293
|
+
} catch {
|
|
6294
|
+
return "";
|
|
6295
|
+
}
|
|
6296
|
+
}
|
|
6297
|
+
async list(scope, filePath, limit) {
|
|
6298
|
+
const raw = await this.readAll(scope, filePath);
|
|
6299
|
+
if (!raw.trim()) return [];
|
|
6300
|
+
const entries = parseEntries(raw, scope);
|
|
6301
|
+
return limit ? entries.slice(0, limit) : entries;
|
|
6302
|
+
}
|
|
6303
|
+
async search(scope, query, filePath, limit) {
|
|
6304
|
+
const entries = await this.list(scope, filePath);
|
|
6305
|
+
const needle = query.toLowerCase().split(/\s+/);
|
|
6306
|
+
const scored = entries.map((e) => {
|
|
6307
|
+
const words = e.text.toLowerCase().split(/\s+/);
|
|
6308
|
+
let score = 0;
|
|
6309
|
+
for (const n of needle) {
|
|
6310
|
+
if (words.some((w) => w.includes(n))) score += 1;
|
|
6311
|
+
if (e.tags?.some((t2) => t2.toLowerCase().includes(n))) score += 2;
|
|
6312
|
+
}
|
|
6313
|
+
return { entry: e, score };
|
|
6314
|
+
});
|
|
6315
|
+
scored.sort((a, b) => b.score - a.score);
|
|
6316
|
+
const matched = scored.filter((s) => s.score > 0).map((s) => s.entry);
|
|
6317
|
+
return limit ? matched.slice(0, limit) : matched;
|
|
6318
|
+
}
|
|
6319
|
+
async clear(scope, filePath) {
|
|
6320
|
+
const file = this.resolveFile(filePath, scope);
|
|
6321
|
+
await atomicWrite(file, "");
|
|
6322
|
+
}
|
|
6323
|
+
async consolidate(scope, filePath) {
|
|
6324
|
+
const file = this.resolveFile(filePath, scope);
|
|
6325
|
+
let existing;
|
|
6326
|
+
try {
|
|
6327
|
+
existing = await fsp3.readFile(file, "utf8");
|
|
6328
|
+
} catch {
|
|
6329
|
+
return 0;
|
|
6330
|
+
}
|
|
6331
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6332
|
+
let removed = 0;
|
|
6333
|
+
const lines = existing.split("\n").filter((line) => {
|
|
6334
|
+
const trimmed = line.trim();
|
|
6335
|
+
if (!trimmed.startsWith("- ")) return true;
|
|
6336
|
+
const norm = trimmed.replace(/\[[^\]]+\]/g, "").replace(/\bmem_\d+_\w+\s*/, "").replace(/#[\w-]+/g, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
6337
|
+
if (seen.has(norm)) {
|
|
6338
|
+
removed++;
|
|
6339
|
+
return false;
|
|
6340
|
+
}
|
|
6341
|
+
seen.add(norm);
|
|
6342
|
+
return true;
|
|
6343
|
+
});
|
|
6344
|
+
const next = lines.join("\n");
|
|
6345
|
+
const backup = `${file}.bak.${Date.now()}`;
|
|
6346
|
+
try {
|
|
6347
|
+
await fsp3.copyFile(file, backup);
|
|
6348
|
+
} catch {
|
|
6349
|
+
}
|
|
6350
|
+
try {
|
|
6351
|
+
await atomicWrite(file, next);
|
|
6352
|
+
} catch {
|
|
6353
|
+
return 0;
|
|
6354
|
+
}
|
|
6355
|
+
return removed;
|
|
6356
|
+
}
|
|
6357
|
+
};
|
|
6358
|
+
function parseEntries(raw, scope = "project-memory") {
|
|
6359
|
+
const entries = [];
|
|
6360
|
+
for (const line of raw.split("\n")) {
|
|
6361
|
+
const entry = lineToEntry(line, scope);
|
|
6362
|
+
if (entry) entries.push(entry);
|
|
6363
|
+
}
|
|
6364
|
+
return entries.reverse();
|
|
6365
|
+
}
|
|
6095
6366
|
|
|
6096
6367
|
// src/storage/memory-store.ts
|
|
6097
|
-
init_atomic_write();
|
|
6098
6368
|
var MAX_BYTES_TOTAL = 32e3;
|
|
6099
6369
|
var DefaultMemoryStore = class {
|
|
6100
6370
|
files;
|
|
6371
|
+
events;
|
|
6372
|
+
backend;
|
|
6101
6373
|
/**
|
|
6102
6374
|
* Per-scope serialization queue. `remember` / `forget` / `consolidate` /
|
|
6103
6375
|
* `clear` are read-modify-write against a single file; without a lock,
|
|
@@ -6114,12 +6386,29 @@ var DefaultMemoryStore = class {
|
|
|
6114
6386
|
writeChain = /* @__PURE__ */ new Map();
|
|
6115
6387
|
/** Last write error per scope — surfaced as warnings on the next readAll(). */
|
|
6116
6388
|
writeErrors = /* @__PURE__ */ new Map();
|
|
6389
|
+
/**
|
|
6390
|
+
* When the global root is a temporary directory (opencode, CI sandboxes),
|
|
6391
|
+
* memory files are also mirrored to the project tree so they survive
|
|
6392
|
+
* session cleanup. The primary path stays in the temp root for isolation;
|
|
6393
|
+
* this backup ensures memory is never lost.
|
|
6394
|
+
*/
|
|
6395
|
+
persistBackup;
|
|
6396
|
+
backupDir;
|
|
6117
6397
|
constructor(opts) {
|
|
6118
6398
|
this.files = {
|
|
6119
6399
|
"project-agents": opts.paths.inProjectAgentsFile,
|
|
6120
6400
|
"project-memory": opts.paths.projectMemory,
|
|
6121
6401
|
"user-memory": opts.paths.globalMemory
|
|
6122
6402
|
};
|
|
6403
|
+
this.events = opts.events;
|
|
6404
|
+
this.backend = opts.backend ?? new FileMemoryBackend({ paths: opts.paths });
|
|
6405
|
+
const root = opts.paths.globalRoot.toLowerCase();
|
|
6406
|
+
this.persistBackup = /[/\\](tmp|temp|cache)[/\\]/.test(root);
|
|
6407
|
+
this.backupDir = this.persistBackup ? opts.paths.inProjectAgentsFile.replace(/AGENTS\.md$/, "memory-persist") : "";
|
|
6408
|
+
}
|
|
6409
|
+
/** Expose the backend for plugin introspection and advanced queries. */
|
|
6410
|
+
getBackend() {
|
|
6411
|
+
return this.backend;
|
|
6123
6412
|
}
|
|
6124
6413
|
async runSerialized(scope, work) {
|
|
6125
6414
|
const prior = this.writeChain.get(scope) ?? Promise.resolve();
|
|
@@ -6146,7 +6435,7 @@ var DefaultMemoryStore = class {
|
|
|
6146
6435
|
if (writeErr2) {
|
|
6147
6436
|
parts.push(`> \u26A0\uFE0F Memory write error (${labelOf(scope)}): ${writeErr2.message}`);
|
|
6148
6437
|
}
|
|
6149
|
-
const body = await this.
|
|
6438
|
+
const body = await this.backend.readAll(scope, this.files[scope]);
|
|
6150
6439
|
if (body.trim()) parts.push(`## ${labelOf(scope)}
|
|
6151
6440
|
|
|
6152
6441
|
${body.trim()}`);
|
|
@@ -6154,117 +6443,214 @@ ${body.trim()}`);
|
|
|
6154
6443
|
return parts.join("\n\n");
|
|
6155
6444
|
}
|
|
6156
6445
|
async read(scope) {
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6446
|
+
return this.backend.readAll(scope, this.files[scope]);
|
|
6447
|
+
}
|
|
6448
|
+
/**
|
|
6449
|
+
* List entries from a scope, newest first. Delegates to the backend
|
|
6450
|
+
* so graph/semantic backends can return enriched or filtered results.
|
|
6451
|
+
*/
|
|
6452
|
+
async list(scope = "project-memory", limit) {
|
|
6453
|
+
return this.backend.list(scope, this.files[scope], limit);
|
|
6454
|
+
}
|
|
6455
|
+
/**
|
|
6456
|
+
* Find memories related to the given text via graph traversal.
|
|
6457
|
+
* Falls back to content search when no graph backend is available.
|
|
6458
|
+
*/
|
|
6459
|
+
async findRelated(text, scope = "project-memory", limit = 5) {
|
|
6460
|
+
if (this.backend.findRelated) {
|
|
6461
|
+
return this.backend.findRelated(scope, this.files[scope], text, limit);
|
|
6161
6462
|
}
|
|
6463
|
+
return this.search(text, scope, limit);
|
|
6162
6464
|
}
|
|
6163
|
-
async
|
|
6465
|
+
async search(query, scope = "project-memory", limit) {
|
|
6466
|
+
return this.backend.search(scope, query, this.files[scope], limit);
|
|
6467
|
+
}
|
|
6468
|
+
async remember(text, scope = "project-memory", metadata) {
|
|
6469
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
6164
6470
|
return this.runSerialized(scope, async () => {
|
|
6165
|
-
const
|
|
6166
|
-
await
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
`;
|
|
6177
|
-
const next = existing.trim() ? existing.replace(/\n+$/, "") + entry : `# WrongStack Memory
|
|
6178
|
-
${entry}`;
|
|
6179
|
-
await atomicWrite(file, next);
|
|
6180
|
-
const buf = Buffer.byteLength(next, "utf8");
|
|
6181
|
-
if (buf > MAX_BYTES_TOTAL) {
|
|
6182
|
-
await this.consolidateUnsafe(scope);
|
|
6471
|
+
const entry = { scope, text, ts, ...metadata };
|
|
6472
|
+
await this.backend.remember(scope, entry, this.files[scope]);
|
|
6473
|
+
const raw = await this.backend.readAll(scope, this.files[scope]);
|
|
6474
|
+
if (Buffer.byteLength(raw, "utf8") > MAX_BYTES_TOTAL) {
|
|
6475
|
+
const removed = await this.backend.consolidate(scope, this.files[scope]);
|
|
6476
|
+
if (removed > 0) {
|
|
6477
|
+
this.events?.emit("memory.consolidated", {
|
|
6478
|
+
scope,
|
|
6479
|
+
removed
|
|
6480
|
+
});
|
|
6481
|
+
}
|
|
6183
6482
|
}
|
|
6483
|
+
await this.mirrorBackup(scope);
|
|
6484
|
+
this.events?.emit("memory.remembered", {
|
|
6485
|
+
scope,
|
|
6486
|
+
text,
|
|
6487
|
+
ts,
|
|
6488
|
+
type: entry.type,
|
|
6489
|
+
tags: entry.tags,
|
|
6490
|
+
priority: entry.priority
|
|
6491
|
+
});
|
|
6184
6492
|
});
|
|
6185
6493
|
}
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
const
|
|
6198
|
-
const
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
const
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
if (
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
|
|
6211
|
-
|
|
6494
|
+
/**
|
|
6495
|
+
* Score and rank memories by relevance to the current context.
|
|
6496
|
+
* Returns entries with score >= MIN_RELEVANCE_SCORE, sorted highest first.
|
|
6497
|
+
*/
|
|
6498
|
+
async scoreRelevant(ctx, scope = "project-memory", limit = 8) {
|
|
6499
|
+
const all = await this.list(scope);
|
|
6500
|
+
if (all.length === 0) return [];
|
|
6501
|
+
const taskWords = ctx.currentTask.toLowerCase().split(/\s+/).filter((w) => w.length > 2);
|
|
6502
|
+
const skillWords = (ctx.activeSkills ?? []).flatMap((s) => s.split("-"));
|
|
6503
|
+
const toolWords = (ctx.toolNames ?? []).flatMap((t2) => t2.toLowerCase().split("_"));
|
|
6504
|
+
const now = Date.now();
|
|
6505
|
+
const scored = [];
|
|
6506
|
+
for (const entry of all) {
|
|
6507
|
+
let score = 0;
|
|
6508
|
+
const reasons = [];
|
|
6509
|
+
const textLower = entry.text.toLowerCase();
|
|
6510
|
+
const tagsLower = (entry.tags ?? []).map((t2) => t2.toLowerCase());
|
|
6511
|
+
let taskHits = 0;
|
|
6512
|
+
for (const w of taskWords) {
|
|
6513
|
+
if (textLower.includes(w)) {
|
|
6514
|
+
taskHits++;
|
|
6515
|
+
score += 2;
|
|
6516
|
+
}
|
|
6517
|
+
if (tagsLower.some((t2) => t2.includes(w))) {
|
|
6518
|
+
taskHits++;
|
|
6519
|
+
score += 3;
|
|
6212
6520
|
}
|
|
6213
6521
|
}
|
|
6214
|
-
if (
|
|
6215
|
-
|
|
6216
|
-
|
|
6522
|
+
if (taskHits > 0) reasons.push(`task match (${taskHits})`);
|
|
6523
|
+
let skillHits = 0;
|
|
6524
|
+
for (const w of skillWords) {
|
|
6525
|
+
if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t2) => t2.includes(w)))) {
|
|
6526
|
+
skillHits++;
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6529
|
+
score += skillHits;
|
|
6530
|
+
if (skillHits > 0) reasons.push(`skill match (${skillHits})`);
|
|
6531
|
+
for (const w of toolWords) {
|
|
6532
|
+
if (w.length > 2 && (textLower.includes(w) || tagsLower.some((t2) => t2.includes(w)))) {
|
|
6533
|
+
score += 1;
|
|
6534
|
+
reasons.push(`tool mention: ${w}`);
|
|
6535
|
+
}
|
|
6536
|
+
}
|
|
6537
|
+
switch (entry.priority) {
|
|
6538
|
+
case "critical":
|
|
6539
|
+
score += 5;
|
|
6540
|
+
reasons.push("critical");
|
|
6541
|
+
break;
|
|
6542
|
+
case "high":
|
|
6543
|
+
score += 3;
|
|
6544
|
+
reasons.push("high priority");
|
|
6545
|
+
break;
|
|
6546
|
+
case "medium":
|
|
6547
|
+
score += 1;
|
|
6548
|
+
break;
|
|
6549
|
+
case "low":
|
|
6550
|
+
score -= 2;
|
|
6551
|
+
reasons.push("low priority");
|
|
6552
|
+
break;
|
|
6553
|
+
}
|
|
6554
|
+
switch (entry.type) {
|
|
6555
|
+
case "decision":
|
|
6556
|
+
score += 2;
|
|
6557
|
+
reasons.push("decision");
|
|
6558
|
+
break;
|
|
6559
|
+
case "convention":
|
|
6560
|
+
score += 2;
|
|
6561
|
+
reasons.push("convention");
|
|
6562
|
+
break;
|
|
6563
|
+
case "anti_pattern":
|
|
6564
|
+
score += 3;
|
|
6565
|
+
reasons.push("anti-pattern");
|
|
6566
|
+
break;
|
|
6567
|
+
case "preference":
|
|
6568
|
+
score += 1;
|
|
6569
|
+
reasons.push("preference");
|
|
6570
|
+
break;
|
|
6571
|
+
}
|
|
6572
|
+
const ageDays = (now - new Date(entry.ts).getTime()) / (1e3 * 60 * 60 * 24);
|
|
6573
|
+
if (ageDays < 1) score += 1;
|
|
6574
|
+
else if (ageDays > 30) score -= 1;
|
|
6575
|
+
if (entry.confidence !== void 0 && entry.confidence < 0.5) {
|
|
6576
|
+
score -= 2;
|
|
6577
|
+
reasons.push("low confidence");
|
|
6578
|
+
}
|
|
6579
|
+
if (entry.lastAccessed) {
|
|
6580
|
+
const hoursSinceAccess = (now - new Date(entry.lastAccessed).getTime()) / (1e3 * 60 * 60);
|
|
6581
|
+
if (hoursSinceAccess < 1) score -= 1;
|
|
6582
|
+
}
|
|
6583
|
+
if (score > 0) {
|
|
6584
|
+
scored.push({
|
|
6585
|
+
...entry,
|
|
6586
|
+
score,
|
|
6587
|
+
matchReason: reasons.join(", ") || "keyword match"
|
|
6588
|
+
});
|
|
6217
6589
|
}
|
|
6218
|
-
return true;
|
|
6219
|
-
});
|
|
6220
|
-
if (removed > 0) {
|
|
6221
|
-
await atomicWrite(file, lines.join("\n"));
|
|
6222
6590
|
}
|
|
6223
|
-
|
|
6591
|
+
scored.sort((a, b) => b.score - a.score);
|
|
6592
|
+
const threshold = 2;
|
|
6593
|
+
const relevant = scored.filter(
|
|
6594
|
+
(s) => s.score >= threshold || s.priority === "critical" || s.priority === "high"
|
|
6595
|
+
);
|
|
6596
|
+
return relevant.slice(0, Math.min(limit, 15));
|
|
6224
6597
|
}
|
|
6225
|
-
async
|
|
6226
|
-
return this.runSerialized(scope, async () =>
|
|
6598
|
+
async forget(query, scope = "project-memory") {
|
|
6599
|
+
return this.runSerialized(scope, async () => {
|
|
6600
|
+
const removed = await this.backend.forget(scope, query, this.files[scope]);
|
|
6601
|
+
if (removed > 0) {
|
|
6602
|
+
this.events?.emit("memory.forgotten", {
|
|
6603
|
+
scope,
|
|
6604
|
+
query,
|
|
6605
|
+
removed
|
|
6606
|
+
});
|
|
6607
|
+
await this.mirrorBackup(scope);
|
|
6608
|
+
}
|
|
6609
|
+
return removed;
|
|
6610
|
+
});
|
|
6227
6611
|
}
|
|
6228
|
-
async
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
const trimmed = line.trim();
|
|
6239
|
-
if (!trimmed.startsWith("- ")) return true;
|
|
6240
|
-
const norm = trimmed.replace(/\[[^\]]+\]/, "").replace(/\bmem_\d+_\w+\s*/, "").trim().toLowerCase();
|
|
6241
|
-
if (seen.has(norm)) return false;
|
|
6242
|
-
seen.add(norm);
|
|
6243
|
-
return true;
|
|
6612
|
+
async consolidate(scope) {
|
|
6613
|
+
return this.runSerialized(scope, async () => {
|
|
6614
|
+
const removed = await this.backend.consolidate(scope, this.files[scope]);
|
|
6615
|
+
if (removed > 0) {
|
|
6616
|
+
this.events?.emit("memory.consolidated", {
|
|
6617
|
+
scope,
|
|
6618
|
+
removed
|
|
6619
|
+
});
|
|
6620
|
+
await this.mirrorBackup(scope);
|
|
6621
|
+
}
|
|
6244
6622
|
});
|
|
6245
|
-
const next = lines.join("\n");
|
|
6246
|
-
const backup = `${file}.bak.${Date.now()}`;
|
|
6247
|
-
try {
|
|
6248
|
-
await fsp3.copyFile(file, backup);
|
|
6249
|
-
} catch {
|
|
6250
|
-
}
|
|
6251
|
-
try {
|
|
6252
|
-
await atomicWrite(file, next);
|
|
6253
|
-
} catch {
|
|
6254
|
-
return;
|
|
6255
|
-
}
|
|
6256
6623
|
}
|
|
6257
6624
|
async clear(scope) {
|
|
6258
6625
|
if (scope) {
|
|
6259
|
-
await this.runSerialized(scope, async () =>
|
|
6626
|
+
await this.runSerialized(scope, async () => {
|
|
6627
|
+
await this.backend.clear(scope, this.files[scope]);
|
|
6628
|
+
this.events?.emit("memory.cleared", { scope });
|
|
6629
|
+
await this.mirrorBackup(scope);
|
|
6630
|
+
});
|
|
6260
6631
|
return;
|
|
6261
6632
|
}
|
|
6262
6633
|
await Promise.all(
|
|
6263
6634
|
["project-agents", "project-memory", "user-memory"].map(
|
|
6264
|
-
(s) => this.runSerialized(s, async () =>
|
|
6635
|
+
(s) => this.runSerialized(s, async () => {
|
|
6636
|
+
await this.backend.clear(s, this.files[s]);
|
|
6637
|
+
this.events?.emit("memory.cleared", { scope: s });
|
|
6638
|
+
await this.mirrorBackup(s);
|
|
6639
|
+
})
|
|
6265
6640
|
)
|
|
6266
6641
|
);
|
|
6267
6642
|
}
|
|
6643
|
+
/** Mirror current memory content to the persistent backup directory. */
|
|
6644
|
+
async mirrorBackup(scope) {
|
|
6645
|
+
if (!this.persistBackup || scope === "project-agents") return;
|
|
6646
|
+
try {
|
|
6647
|
+
const content = await this.backend.readAll(scope, this.files[scope]);
|
|
6648
|
+
const { writeFile: writeFile11, mkdir: mkdir17 } = await import('fs/promises');
|
|
6649
|
+
await mkdir17(this.backupDir, { recursive: true });
|
|
6650
|
+
await writeFile11(`${this.backupDir}/${scope}.md`, content, "utf8");
|
|
6651
|
+
} catch {
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6268
6654
|
};
|
|
6269
6655
|
function labelOf(scope) {
|
|
6270
6656
|
switch (scope) {
|
|
@@ -7085,7 +7471,10 @@ function attachTodosCheckpoint(state, filePath, sessionId) {
|
|
|
7085
7471
|
let pending = null;
|
|
7086
7472
|
let writeChain = Promise.resolve();
|
|
7087
7473
|
const enqueueWrite = (todos) => {
|
|
7088
|
-
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos))
|
|
7474
|
+
writeChain = writeChain.then(() => saveTodosCheckpoint(filePath, sessionId, todos)).catch((err) => {
|
|
7475
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7476
|
+
console.error(`[TodosCheckpoint] save failed for session ${sessionId}: ${msg}`);
|
|
7477
|
+
});
|
|
7089
7478
|
return writeChain;
|
|
7090
7479
|
};
|
|
7091
7480
|
const flush = () => {
|
|
@@ -7389,7 +7778,7 @@ async function acquireDirectorStateLock(lockPath, processId = process.pid) {
|
|
|
7389
7778
|
}
|
|
7390
7779
|
const lock = {
|
|
7391
7780
|
pid: processId,
|
|
7392
|
-
hostname:
|
|
7781
|
+
hostname: hostname(),
|
|
7393
7782
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7394
7783
|
};
|
|
7395
7784
|
await atomicWrite(lockPath, JSON.stringify(lock), { mode: 384 });
|
|
@@ -8611,12 +9000,6 @@ var IntelligentCompactor = class {
|
|
|
8611
9000
|
};
|
|
8612
9001
|
|
|
8613
9002
|
// src/models/llm-selector.ts
|
|
8614
|
-
function expectDefined11(value) {
|
|
8615
|
-
if (value === null || value === void 0) {
|
|
8616
|
-
throw new Error("Expected value to be defined");
|
|
8617
|
-
}
|
|
8618
|
-
return value;
|
|
8619
|
-
}
|
|
8620
9003
|
var DEFAULT_SYSTEM_PROMPT = `You are a context pruning assistant. Given a conversation history and a token budget, decide which message ranges are worth keeping verbatim and which should be collapsed into summaries.
|
|
8621
9004
|
|
|
8622
9005
|
Output a JSON object with this structure:
|
|
@@ -8657,7 +9040,7 @@ function formatMessages(messages, maxChars = 8e3) {
|
|
|
8657
9040
|
const lines = [];
|
|
8658
9041
|
let used = 0;
|
|
8659
9042
|
for (let i = 0; i < messages.length; i++) {
|
|
8660
|
-
const m =
|
|
9043
|
+
const m = expectDefined(messages[i]);
|
|
8661
9044
|
const role = m.role.padEnd(10, " ");
|
|
8662
9045
|
let text;
|
|
8663
9046
|
if (typeof m.content === "string") {
|
|
@@ -8722,7 +9105,7 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
8722
9105
|
let tokenCount = 0;
|
|
8723
9106
|
let startIdx = 0;
|
|
8724
9107
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8725
|
-
const m =
|
|
9108
|
+
const m = expectDefined(messages[i]);
|
|
8726
9109
|
const cost = typeof m.content === "string" ? Math.ceil(m.content.length / 4) : m.content.reduce(
|
|
8727
9110
|
(acc, b) => acc + (b.type === "text" ? Math.ceil(b.text.length / 4) : Math.ceil(JSON.stringify(b).length / 4)),
|
|
8728
9111
|
0
|
|
@@ -9405,6 +9788,14 @@ function emptyGoal(goal) {
|
|
|
9405
9788
|
journal: []
|
|
9406
9789
|
};
|
|
9407
9790
|
}
|
|
9791
|
+
function setProgress(goal, progress, note) {
|
|
9792
|
+
const clamped = Math.min(100, Math.max(0, progress));
|
|
9793
|
+
return {
|
|
9794
|
+
...goal,
|
|
9795
|
+
progress: clamped,
|
|
9796
|
+
progressNote: note ?? clamped + "% complete"
|
|
9797
|
+
};
|
|
9798
|
+
}
|
|
9408
9799
|
function appendJournal(goal, entry) {
|
|
9409
9800
|
const iteration = goal.iterations + 1;
|
|
9410
9801
|
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -9433,34 +9824,110 @@ function summarizeUsage(goal) {
|
|
|
9433
9824
|
}
|
|
9434
9825
|
return { totalCostUsd, totalInputTokens, totalOutputTokens, iterationsWithUsage };
|
|
9435
9826
|
}
|
|
9827
|
+
var DOLLAR = "$";
|
|
9436
9828
|
function formatGoal(goal, journalLimit = 10) {
|
|
9437
9829
|
const lines = [];
|
|
9438
|
-
|
|
9439
|
-
lines.push(
|
|
9440
|
-
|
|
9441
|
-
|
|
9830
|
+
const displayGoal = goal.refinedGoal || goal.goal;
|
|
9831
|
+
lines.push(color.bold("Goal") + ": " + displayGoal);
|
|
9832
|
+
if (goal.refinedGoal && goal.refinedGoal !== goal.goal) {
|
|
9833
|
+
const snippet = goal.goal.length > 60 ? goal.goal.slice(0, 60) + "\u2026" : goal.goal;
|
|
9834
|
+
lines.push(color.dim(' (original: "' + snippet + '")'));
|
|
9835
|
+
}
|
|
9836
|
+
if (typeof goal.progress === "number") {
|
|
9837
|
+
const pct = Math.min(100, Math.max(0, Math.round(goal.progress)));
|
|
9838
|
+
const filled = Math.round(pct / 5);
|
|
9839
|
+
const empty = 20 - filled;
|
|
9840
|
+
const bar = color.green("\u2588".repeat(filled)) + color.dim("\u2591".repeat(empty));
|
|
9841
|
+
lines.push("Progress: " + bar + " " + color.bold(pct + "%"));
|
|
9842
|
+
if (goal.progressNote) {
|
|
9843
|
+
lines.push(" " + color.dim(goal.progressNote));
|
|
9844
|
+
}
|
|
9845
|
+
if (goal.progressTrend) {
|
|
9846
|
+
const trendIcon = goal.progressTrend === "accelerating" ? "\u{1F680}" : goal.progressTrend === "stalling" ? "\u26A0\uFE0F" : "\u27A1\uFE0F";
|
|
9847
|
+
lines.push(" Trend: " + trendIcon + " " + goal.progressTrend);
|
|
9848
|
+
}
|
|
9849
|
+
}
|
|
9850
|
+
if (goal.deliverables && goal.deliverables.length > 0) {
|
|
9851
|
+
lines.push("");
|
|
9852
|
+
lines.push(color.bold("Deliverables:"));
|
|
9853
|
+
for (const d of goal.deliverables) {
|
|
9854
|
+
const done = /^\[[x✓]\]|✅|\(done\)/i.test(d);
|
|
9855
|
+
const marker = done ? color.green("\u2713") : color.dim("\u25CB");
|
|
9856
|
+
lines.push(" " + marker + " " + d);
|
|
9857
|
+
}
|
|
9858
|
+
}
|
|
9859
|
+
lines.push("");
|
|
9860
|
+
lines.push("Set: " + goal.setAt);
|
|
9861
|
+
lines.push("Last activity: " + goal.lastActivityAt);
|
|
9862
|
+
lines.push("Iterations: " + goal.iterations);
|
|
9442
9863
|
const stateLabel = goal.goalState ?? "active";
|
|
9443
|
-
lines.push(
|
|
9444
|
-
lines.push(
|
|
9864
|
+
lines.push("State: " + stateLabel + (goal.iterations > 0 ? " (iteration #" + goal.iterations + ")" : ""));
|
|
9865
|
+
lines.push("Engine: " + goal.engineState);
|
|
9445
9866
|
const usage = summarizeUsage(goal);
|
|
9446
9867
|
if (usage.iterationsWithUsage > 0) {
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
);
|
|
9868
|
+
const spent = "Spent: " + DOLLAR + usage.totalCostUsd.toFixed(4) + " (in " + usage.totalInputTokens + " / out " + usage.totalOutputTokens + " tokens across " + usage.iterationsWithUsage + " iterations)";
|
|
9869
|
+
lines.push(spent);
|
|
9450
9870
|
}
|
|
9451
9871
|
if (goal.journal.length > 0) {
|
|
9452
9872
|
lines.push("");
|
|
9453
|
-
lines.push(
|
|
9873
|
+
lines.push("Recent journal (last " + Math.min(journalLimit, goal.journal.length) + "):");
|
|
9454
9874
|
const tail = goal.journal.slice(-journalLimit);
|
|
9455
9875
|
for (const e of tail) {
|
|
9456
9876
|
const mark = e.status === "success" ? "\u2713" : e.status === "failure" ? "\u2717" : e.status === "aborted" ? "\u2298" : "\xB7";
|
|
9457
|
-
const note = e.note ?
|
|
9458
|
-
const cost = typeof e.costUsd === "number" ?
|
|
9459
|
-
lines.push(
|
|
9877
|
+
const note = e.note ? " \u2014 " + e.note : "";
|
|
9878
|
+
const cost = typeof e.costUsd === "number" ? " (" + DOLLAR + e.costUsd.toFixed(4) + ")" : "";
|
|
9879
|
+
lines.push(" #" + e.iteration + " " + mark + " [" + e.source + "] " + e.task + cost + note);
|
|
9460
9880
|
}
|
|
9461
9881
|
}
|
|
9462
9882
|
return lines.join("\n");
|
|
9463
9883
|
}
|
|
9884
|
+
function parseProgressFromText(text) {
|
|
9885
|
+
const re = /\[progress:\s*(\d{1,3})%\]\s*(?:[—\-]\s*(.+))?/i;
|
|
9886
|
+
const m = text.match(re);
|
|
9887
|
+
if (!m) return null;
|
|
9888
|
+
const progress = Math.min(100, Math.max(0, Number.parseInt(m[1], 10)));
|
|
9889
|
+
const note = m[2]?.trim() || void 0;
|
|
9890
|
+
return { progress, note };
|
|
9891
|
+
}
|
|
9892
|
+
function recordProgress(goal, progress, note) {
|
|
9893
|
+
const clamped = Math.min(100, Math.max(0, progress));
|
|
9894
|
+
const history = [...goal.progressHistory ?? [], { at: (/* @__PURE__ */ new Date()).toISOString(), progress: clamped, note }];
|
|
9895
|
+
const trimmed = history.length > 200 ? history.slice(-200) : history;
|
|
9896
|
+
return {
|
|
9897
|
+
...goal,
|
|
9898
|
+
progress: clamped,
|
|
9899
|
+
progressNote: note ?? `${clamped}% complete`,
|
|
9900
|
+
progressHistory: trimmed,
|
|
9901
|
+
progressTrend: computeTrend(trimmed)
|
|
9902
|
+
};
|
|
9903
|
+
}
|
|
9904
|
+
var MAX_PROGRESS_HISTORY = 200;
|
|
9905
|
+
function computeTrend(history) {
|
|
9906
|
+
if (history.length < 3) return void 0;
|
|
9907
|
+
const recent = history.slice(-5);
|
|
9908
|
+
const deltas = [];
|
|
9909
|
+
for (let i = 1; i < recent.length; i++) {
|
|
9910
|
+
deltas.push(recent[i].progress - recent[i - 1].progress);
|
|
9911
|
+
}
|
|
9912
|
+
if (deltas.length < 2) return void 0;
|
|
9913
|
+
const avgDelta = deltas.reduce((a, b) => a + b, 0) / deltas.length;
|
|
9914
|
+
if (avgDelta > 2) return "accelerating";
|
|
9915
|
+
if (avgDelta < -1) return "stalling";
|
|
9916
|
+
return "steady";
|
|
9917
|
+
}
|
|
9918
|
+
|
|
9919
|
+
// src/execution/autonomy-brain.ts
|
|
9920
|
+
function formatDecisionSummary(decision, request) {
|
|
9921
|
+
const question = request.question.length > 80 ? request.question.slice(0, 77) + "\u2026" : request.question;
|
|
9922
|
+
if (decision.type === "deny") {
|
|
9923
|
+
return `\u{1F9E0} Brain: DENIED \u2014 "${question}" \u2192 ${decision.reason}`;
|
|
9924
|
+
}
|
|
9925
|
+
if (decision.type === "answer") {
|
|
9926
|
+
const action = decision.optionId ? `chose [${decision.optionId}]` : decision.text.length > 60 ? decision.text.slice(0, 57) + "\u2026" : decision.text;
|
|
9927
|
+
return `\u{1F9E0} Brain: DECIDED \u2014 "${question}" \u2192 ${action}`;
|
|
9928
|
+
}
|
|
9929
|
+
return `\u{1F9E0} Brain: ASKED HUMAN \u2014 "${question}"`;
|
|
9930
|
+
}
|
|
9464
9931
|
|
|
9465
9932
|
// src/execution/eternal-autonomy.ts
|
|
9466
9933
|
var execFileP = promisify(execFile);
|
|
@@ -9531,7 +9998,7 @@ var EternalAutonomyEngine = class {
|
|
|
9531
9998
|
this.consecutiveFailures = 0;
|
|
9532
9999
|
}
|
|
9533
10000
|
if (this.stopRequested) break;
|
|
9534
|
-
await sleep(this.opts.cycleGapMs ??
|
|
10001
|
+
await sleep(this.opts.cycleGapMs ?? 0);
|
|
9535
10002
|
}
|
|
9536
10003
|
} finally {
|
|
9537
10004
|
this.state = "stopped";
|
|
@@ -9701,6 +10168,18 @@ var EternalAutonomyEngine = class {
|
|
|
9701
10168
|
this.stopRequested = true;
|
|
9702
10169
|
return true;
|
|
9703
10170
|
}
|
|
10171
|
+
const parsed = parseProgressFromText(finalText);
|
|
10172
|
+
if (parsed) {
|
|
10173
|
+
await this.updateProgress(parsed.progress, parsed.note);
|
|
10174
|
+
if (parsed.progress >= 100) {
|
|
10175
|
+
await this.markGoalCompleted(
|
|
10176
|
+
{ source: action.source, task: action.task, directive: action.directive },
|
|
10177
|
+
`progress reached 100%: ${parsed.note ?? "goal complete"}`
|
|
10178
|
+
);
|
|
10179
|
+
this.stopRequested = true;
|
|
10180
|
+
return true;
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
9704
10183
|
this.iterationsSinceCompact++;
|
|
9705
10184
|
await this.maybeCompact().catch((err) => {
|
|
9706
10185
|
this.opts.onError?.(
|
|
@@ -9787,11 +10266,16 @@ var EternalAutonomyEngine = class {
|
|
|
9787
10266
|
this.consecutiveBrainstormDone++;
|
|
9788
10267
|
const threshold = this.opts.brainstormDoneStopThreshold ?? 3;
|
|
9789
10268
|
if (this.consecutiveBrainstormDone >= threshold) {
|
|
9790
|
-
await this.
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
10269
|
+
const shouldStop = await this.consultBrainForDone(goal);
|
|
10270
|
+
if (shouldStop) {
|
|
10271
|
+
await this.markGoalCompleted(
|
|
10272
|
+
{ source: "brainstorm", task: "no further work", directive: "" },
|
|
10273
|
+
`brainstorm returned DONE ${this.consecutiveBrainstormDone}x in a row${this.opts.brain ? ", brain confirmed" : ""}`
|
|
10274
|
+
);
|
|
10275
|
+
this.stopRequested = true;
|
|
10276
|
+
} else {
|
|
10277
|
+
this.consecutiveBrainstormDone = 0;
|
|
10278
|
+
}
|
|
9795
10279
|
}
|
|
9796
10280
|
return null;
|
|
9797
10281
|
}
|
|
@@ -10010,8 +10494,8 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
10010
10494
|
await saveGoal(this.goalPath, abandoned);
|
|
10011
10495
|
}
|
|
10012
10496
|
try {
|
|
10013
|
-
const { unlink:
|
|
10014
|
-
await
|
|
10497
|
+
const { unlink: unlink14 } = await import('fs/promises');
|
|
10498
|
+
await unlink14(this.goalPath);
|
|
10015
10499
|
} catch {
|
|
10016
10500
|
}
|
|
10017
10501
|
this.opts.onEternalStop?.();
|
|
@@ -10025,6 +10509,69 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
10025
10509
|
async appendFailure(task, note) {
|
|
10026
10510
|
await this.appendIterationEntry({ source: "manual", task, status: "failure", note });
|
|
10027
10511
|
}
|
|
10512
|
+
/**
|
|
10513
|
+
* Consult the brain on whether the goal is truly complete.
|
|
10514
|
+
* Without a brain, always returns true (use heuristic: DONE threshold met = done).
|
|
10515
|
+
*/
|
|
10516
|
+
async consultBrainForDone(goal) {
|
|
10517
|
+
if (!this.opts.brain) return true;
|
|
10518
|
+
const deliverablesStatus = goal.deliverables?.length ? `
|
|
10519
|
+
Deliverables: ${goal.deliverables.length} total, progress ${goal.progress ?? "unknown"}%` : "";
|
|
10520
|
+
const recentJournal = goal.journal.slice(-5).map(
|
|
10521
|
+
(e) => ` #${e.iteration} [${e.status}] ${e.task}`
|
|
10522
|
+
).join("\n");
|
|
10523
|
+
try {
|
|
10524
|
+
const decision = await this.opts.brain.decide({
|
|
10525
|
+
id: `goal-done-${goal.iterations}`,
|
|
10526
|
+
source: "system",
|
|
10527
|
+
question: `Brainstorm returned DONE ${this.consecutiveBrainstormDone}x. Is the goal truly complete?`,
|
|
10528
|
+
context: [
|
|
10529
|
+
`Goal: ${goal.goal}`,
|
|
10530
|
+
`Iterations: ${goal.iterations}`,
|
|
10531
|
+
`Progress: ${goal.progress ?? "unknown"}%`,
|
|
10532
|
+
deliverablesStatus,
|
|
10533
|
+
recentJournal ? `
|
|
10534
|
+
Recent work:
|
|
10535
|
+
${recentJournal}` : ""
|
|
10536
|
+
].join("\n"),
|
|
10537
|
+
risk: "high",
|
|
10538
|
+
fallback: "continue"
|
|
10539
|
+
});
|
|
10540
|
+
const summary = formatDecisionSummary(decision, {
|
|
10541
|
+
id: `goal-done-${goal.iterations}`,
|
|
10542
|
+
source: "system",
|
|
10543
|
+
question: "Is the goal complete?",
|
|
10544
|
+
risk: "high",
|
|
10545
|
+
fallback: "continue"
|
|
10546
|
+
});
|
|
10547
|
+
const rationale = "rationale" in decision ? decision.rationale : void 0;
|
|
10548
|
+
await this.appendIterationEntry({
|
|
10549
|
+
source: "brainstorm",
|
|
10550
|
+
task: summary,
|
|
10551
|
+
status: "success",
|
|
10552
|
+
note: rationale
|
|
10553
|
+
});
|
|
10554
|
+
if (decision.type === "deny") {
|
|
10555
|
+
return false;
|
|
10556
|
+
}
|
|
10557
|
+
if (decision.type === "answer") {
|
|
10558
|
+
const text = decision.text.toLowerCase();
|
|
10559
|
+
return text.includes("complete") || text.includes("done") || text.includes("yes");
|
|
10560
|
+
}
|
|
10561
|
+
return true;
|
|
10562
|
+
} catch {
|
|
10563
|
+
return true;
|
|
10564
|
+
}
|
|
10565
|
+
}
|
|
10566
|
+
/**
|
|
10567
|
+
* Persist a progress update from the agent's [PROGRESS: N%] output.
|
|
10568
|
+
*/
|
|
10569
|
+
async updateProgress(progress, note) {
|
|
10570
|
+
const current = await loadGoal(this.goalPath);
|
|
10571
|
+
if (!current) return;
|
|
10572
|
+
const updated = recordProgress(current, progress, note);
|
|
10573
|
+
await saveGoal(this.goalPath, updated);
|
|
10574
|
+
}
|
|
10028
10575
|
async persistEngineState(state) {
|
|
10029
10576
|
const current = await loadGoal(this.goalPath);
|
|
10030
10577
|
if (!current) return;
|
|
@@ -10390,15 +10937,7 @@ function makeAgentSubagentRunner(opts) {
|
|
|
10390
10937
|
let budgetError = null;
|
|
10391
10938
|
const onBudgetError = (err) => {
|
|
10392
10939
|
if (err instanceof BudgetThresholdSignal) {
|
|
10393
|
-
|
|
10394
|
-
if (decision === "stop") {
|
|
10395
|
-
budgetError = new BudgetExceededError(err.kind, err.limit, err.used);
|
|
10396
|
-
aborter.abort();
|
|
10397
|
-
}
|
|
10398
|
-
}).catch(() => {
|
|
10399
|
-
budgetError = new BudgetExceededError(err.kind, err.limit, err.used);
|
|
10400
|
-
aborter.abort();
|
|
10401
|
-
});
|
|
10940
|
+
budgetError = err;
|
|
10402
10941
|
return;
|
|
10403
10942
|
}
|
|
10404
10943
|
aborter.abort();
|
|
@@ -10506,15 +11045,23 @@ function makeAgentSubagentRunner(opts) {
|
|
|
10506
11045
|
}
|
|
10507
11046
|
if (budgetError) {
|
|
10508
11047
|
if ("decision" in budgetError) {
|
|
10509
|
-
|
|
10510
|
-
|
|
11048
|
+
try {
|
|
11049
|
+
const decision = await budgetError.decision;
|
|
11050
|
+
if (decision === "stop") {
|
|
11051
|
+
budgetError = new BudgetExceededError(
|
|
11052
|
+
budgetError.kind,
|
|
11053
|
+
budgetError.limit,
|
|
11054
|
+
budgetError.used
|
|
11055
|
+
);
|
|
11056
|
+
} else {
|
|
11057
|
+
budgetError = null;
|
|
11058
|
+
}
|
|
11059
|
+
} catch {
|
|
10511
11060
|
budgetError = new BudgetExceededError(
|
|
10512
11061
|
budgetError.kind,
|
|
10513
11062
|
budgetError.limit,
|
|
10514
11063
|
budgetError.used
|
|
10515
11064
|
);
|
|
10516
|
-
} else {
|
|
10517
|
-
budgetError = null;
|
|
10518
11065
|
}
|
|
10519
11066
|
}
|
|
10520
11067
|
if (budgetError) throw budgetError;
|
|
@@ -12665,17 +13212,120 @@ Working rules:
|
|
|
12665
13212
|
phase: "meta",
|
|
12666
13213
|
summary: "Token/cloud cost optimization: finds spend waste, recommends model routing and trimming with $ estimates.",
|
|
12667
13214
|
keywords: [
|
|
12668
|
-
"cost",
|
|
12669
|
-
"token cost",
|
|
12670
|
-
"optimize cost",
|
|
12671
|
-
"spend",
|
|
12672
|
-
"cheaper",
|
|
12673
|
-
"model routing",
|
|
12674
|
-
"budget",
|
|
12675
|
-
"expensive",
|
|
12676
|
-
"reduce tokens",
|
|
12677
|
-
"pricing",
|
|
12678
|
-
"cloud cost"
|
|
13215
|
+
"cost",
|
|
13216
|
+
"token cost",
|
|
13217
|
+
"optimize cost",
|
|
13218
|
+
"spend",
|
|
13219
|
+
"cheaper",
|
|
13220
|
+
"model routing",
|
|
13221
|
+
"budget",
|
|
13222
|
+
"expensive",
|
|
13223
|
+
"reduce tokens",
|
|
13224
|
+
"pricing",
|
|
13225
|
+
"cloud cost"
|
|
13226
|
+
]
|
|
13227
|
+
}
|
|
13228
|
+
},
|
|
13229
|
+
{
|
|
13230
|
+
config: {
|
|
13231
|
+
id: "tech-stack",
|
|
13232
|
+
name: "Tech Stack Validator",
|
|
13233
|
+
role: "tech-stack",
|
|
13234
|
+
tools: ["search", "fetch", "read", "grep", "glob", "outdated", "audit", "json"],
|
|
13235
|
+
prompt: `You are the Tech Stack Validator \u2014 a single-shot validation agent that fires
|
|
13236
|
+
before any package, library, or framework choice is committed.
|
|
13237
|
+
|
|
13238
|
+
Your ONLY job: verify that a technology choice is current, real, and not obsolete.
|
|
13239
|
+
You are the "this isn't code, this is 10-year-old technology" agent. Intervene
|
|
13240
|
+
hard when the LLM hallucinates a version number or suggests dead tech.
|
|
13241
|
+
|
|
13242
|
+
## Critical rules
|
|
13243
|
+
|
|
13244
|
+
1. **Verify existence.** Search npm registry (fetch https://registry.npmjs.org/<pkg>/latest)
|
|
13245
|
+
or web search. A package that doesn't exist = hallucination.
|
|
13246
|
+
|
|
13247
|
+
2. **Check latest version.** Never trust any version number from the model. Always
|
|
13248
|
+
fetch the actual latest stable version from npm or the project's release page.
|
|
13249
|
+
|
|
13250
|
+
3. **Reject dead packages.** No release in >2 years + unresolved critical issues =
|
|
13251
|
+
dead. Suggest a maintained replacement.
|
|
13252
|
+
|
|
13253
|
+
4. **Reject prehistoric tech.** Any package/pattern superseded \u22655 years ago is
|
|
13254
|
+
REJECTED. Key blocklist:
|
|
13255
|
+
- axios / node-fetch / got / request \u2192 native fetch (Node 18+)
|
|
13256
|
+
- moment \u2192 date-fns / luxon / Temporal
|
|
13257
|
+
- jQuery (new projects) \u2192 vanilla DOM / React
|
|
13258
|
+
- Gulp / Grunt \u2192 tsup / esbuild / vite
|
|
13259
|
+
- CoffeeScript / Flow \u2192 TypeScript
|
|
13260
|
+
- Bluebird \u2192 native Promises
|
|
13261
|
+
- crypto-js \u2192 node:crypto / Web Crypto
|
|
13262
|
+
- Bower \u2192 npm/pnpm
|
|
13263
|
+
- underscore \u2192 lodash or native ES2020+
|
|
13264
|
+
|
|
13265
|
+
5. **The intervention phrase.** When rejecting on age grounds, you MUST output
|
|
13266
|
+
exactly: "This isn't code, this is X-year-old technology." where X =
|
|
13267
|
+
current year \u2212 the year the technology was made obsolete. Follow with
|
|
13268
|
+
what replaced it and a one-step migration path.
|
|
13269
|
+
|
|
13270
|
+
6. **Prefer built-in over third-party.** Check Node 22+ native APIs first:
|
|
13271
|
+
node:test, node:sqlite, fetch, WebSocket, Web Crypto \u2014 all built-in.
|
|
13272
|
+
|
|
13273
|
+
## Workflow (single-shot \u2014 do NOT loop)
|
|
13274
|
+
|
|
13275
|
+
1. Receive the proposed package + version
|
|
13276
|
+
2. Search npm registry or web for the latest version
|
|
13277
|
+
3. Check age, maintenance status, deprecation
|
|
13278
|
+
4. Output verdict: APPROVED (with exact version) or REJECTED (with replacement)
|
|
13279
|
+
|
|
13280
|
+
## Output format
|
|
13281
|
+
|
|
13282
|
+
### Tech Stack Validation \u2014 <package>
|
|
13283
|
+
|
|
13284
|
+
**Status**: APPROVED | REJECTED
|
|
13285
|
+
|
|
13286
|
+
**Package**: <name>@<version>
|
|
13287
|
+
**Source**: <URL you checked \u2014 npm registry, GitHub, web search>
|
|
13288
|
+
**Age**: <first release> \u2014 <last release date>
|
|
13289
|
+
**Verdict**: 1\u20132 sentence explanation.
|
|
13290
|
+
|
|
13291
|
+
When REJECTED on age:
|
|
13292
|
+
**"This isn't code, this is X-year-old technology."**
|
|
13293
|
+
**Replaced by**: <modern alternative>
|
|
13294
|
+
**Migration**: <one concrete step>
|
|
13295
|
+
|
|
13296
|
+
When APPROVED:
|
|
13297
|
+
**Install**: pnpm add <name>@^<major>.<minor>.0`
|
|
13298
|
+
},
|
|
13299
|
+
budget: {
|
|
13300
|
+
timeoutMs: 6e4,
|
|
13301
|
+
maxIterations: 5,
|
|
13302
|
+
maxToolCalls: 20,
|
|
13303
|
+
maxTokens: 4e4,
|
|
13304
|
+
maxCostUsd: 0.1
|
|
13305
|
+
},
|
|
13306
|
+
capability: {
|
|
13307
|
+
phase: "meta",
|
|
13308
|
+
summary: "Single-shot tech stack validator: checks npm for latest versions, rejects dead/obsolete packages, enforces modern alternatives.",
|
|
13309
|
+
keywords: [
|
|
13310
|
+
"tech stack",
|
|
13311
|
+
"version",
|
|
13312
|
+
"package",
|
|
13313
|
+
"library",
|
|
13314
|
+
"framework",
|
|
13315
|
+
"dependency",
|
|
13316
|
+
"install",
|
|
13317
|
+
"upgrade",
|
|
13318
|
+
"latest",
|
|
13319
|
+
"npm",
|
|
13320
|
+
"pnpm add",
|
|
13321
|
+
"outdated",
|
|
13322
|
+
"obsolete",
|
|
13323
|
+
"deprecated",
|
|
13324
|
+
"what version",
|
|
13325
|
+
"which package",
|
|
13326
|
+
"check version",
|
|
13327
|
+
"verify version",
|
|
13328
|
+
"is this current"
|
|
12679
13329
|
]
|
|
12680
13330
|
}
|
|
12681
13331
|
}
|
|
@@ -14010,12 +14660,6 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
14010
14660
|
};
|
|
14011
14661
|
|
|
14012
14662
|
// src/execution/parallel-eternal-engine.ts
|
|
14013
|
-
function expectDefined12(value) {
|
|
14014
|
-
if (value === null || value === void 0) {
|
|
14015
|
-
throw new Error("Expected value to be defined");
|
|
14016
|
-
}
|
|
14017
|
-
return value;
|
|
14018
|
-
}
|
|
14019
14663
|
var GOAL_COMPLETE_MARKER2 = /^\s*\[goal[_\s-]?complete\]\s*$/im;
|
|
14020
14664
|
var ParallelEternalEngine = class {
|
|
14021
14665
|
constructor(opts) {
|
|
@@ -14171,7 +14815,7 @@ var ParallelEternalEngine = class {
|
|
|
14171
14815
|
// Fan-out
|
|
14172
14816
|
// -------------------------------------------------------------------------
|
|
14173
14817
|
async fanOut(goal, tasks) {
|
|
14174
|
-
const coordinator =
|
|
14818
|
+
const coordinator = expectDefined(this.coordinator);
|
|
14175
14819
|
const slotCount = Math.min(this.slots, tasks.length);
|
|
14176
14820
|
const routes = this.dispatchEnabled ? await Promise.all(
|
|
14177
14821
|
tasks.slice(0, slotCount).map(
|
|
@@ -14203,7 +14847,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
14203
14847
|
const routeInfo = [];
|
|
14204
14848
|
const spawnPromises = [];
|
|
14205
14849
|
for (let i = 0; i < slotCount; i++) {
|
|
14206
|
-
const task =
|
|
14850
|
+
const task = expectDefined(tasks[i]);
|
|
14207
14851
|
const route = routes[i] ?? null;
|
|
14208
14852
|
const subagentId = `parallel-${this.iterations}-${i}`;
|
|
14209
14853
|
const taskId = randomUUID();
|
|
@@ -14476,7 +15120,17 @@ ${journalTail.join("\n")}` : "Recent journal: (none \u2014 this is the first ite
|
|
|
14476
15120
|
}
|
|
14477
15121
|
|
|
14478
15122
|
// src/execution/goal-preamble.ts
|
|
14479
|
-
function buildGoalPreamble(goal) {
|
|
15123
|
+
function buildGoalPreamble(goal, deliverables) {
|
|
15124
|
+
const deliverableBlock = deliverables && deliverables.length > 0 ? [
|
|
15125
|
+
"",
|
|
15126
|
+
"CONCRETE DELIVERABLES (check these off as you go):",
|
|
15127
|
+
...deliverables.map((d, i) => ` ${i + 1}. ${d}`),
|
|
15128
|
+
"",
|
|
15129
|
+
"After EACH iteration, estimate your completion percentage (0\u2013100)",
|
|
15130
|
+
"against this deliverable list. Output it as:",
|
|
15131
|
+
" [PROGRESS: N%] \u2014 <1-sentence status>",
|
|
15132
|
+
"The eternal engine reads this to update the progress bar."
|
|
15133
|
+
].join("\n") : "";
|
|
14480
15134
|
return [
|
|
14481
15135
|
"[GOAL \u2014 LOCKED IN. You will work on this until it is verifiably done.",
|
|
14482
15136
|
"The user granted you full autonomy. Read these constraints once, then act.",
|
|
@@ -14485,6 +15139,7 @@ function buildGoalPreamble(goal) {
|
|
|
14485
15139
|
"---",
|
|
14486
15140
|
goal,
|
|
14487
15141
|
"---",
|
|
15142
|
+
deliverableBlock,
|
|
14488
15143
|
"",
|
|
14489
15144
|
"AUTHORITY YOU HAVE:",
|
|
14490
15145
|
"- Spawn as many subagents as the work needs (delegate / spawn_subagent).",
|
|
@@ -14506,6 +15161,7 @@ function buildGoalPreamble(goal) {
|
|
|
14506
15161
|
"- You can tell the user HOW to verify it themselves in 10 seconds.",
|
|
14507
15162
|
'- You have NOT hedged. None of: "looks like it should work", "I',
|
|
14508
15163
|
' believe this fixes it", "the changes appear correct".',
|
|
15164
|
+
`- Progress bar shows 100%. All deliverables checked off.`,
|
|
14509
15165
|
"",
|
|
14510
15166
|
"WHAT IS NOT DONE \u2014 never report any of these as completion:",
|
|
14511
15167
|
"- An error message you didn't recover from.",
|
|
@@ -14520,6 +15176,13 @@ function buildGoalPreamble(goal) {
|
|
|
14520
15176
|
" respond to with a fresh attempt (different role, different model,",
|
|
14521
15177
|
" tighter prompt).",
|
|
14522
15178
|
"",
|
|
15179
|
+
"PROGRESS REPORTING \u2014 MANDATORY every iteration:",
|
|
15180
|
+
"- End every response with exactly: [PROGRESS: N%] \u2014 <status note>",
|
|
15181
|
+
" where N is your honest estimate (0-100) of how much of the goal",
|
|
15182
|
+
" is done. The engine tracks this and shows a live progress bar.",
|
|
15183
|
+
"- Example: [PROGRESS: 45%] \u2014 Auth module refactored, 3/5 tests pass,",
|
|
15184
|
+
" remaining: test coverage + docs update.",
|
|
15185
|
+
"",
|
|
14523
15186
|
"PERSISTENCE PROTOCOL:",
|
|
14524
15187
|
"- If blocked, try at least 3 different angles before reporting the",
|
|
14525
15188
|
" problem to the user. Different tool inputs, different subagent",
|
|
@@ -14562,6 +15225,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14562
15225
|
settled = false;
|
|
14563
15226
|
timeoutMs;
|
|
14564
15227
|
cancelled = false;
|
|
15228
|
+
_raceResolved = false;
|
|
14565
15229
|
alerts = [];
|
|
14566
15230
|
snapshotWarnings = [];
|
|
14567
15231
|
/** Tracks tool call counts per subagent for progress-based timeout decisions. */
|
|
@@ -14658,7 +15322,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14658
15322
|
* Safe to call multiple times (idempotent after first call).
|
|
14659
15323
|
*/
|
|
14660
15324
|
cancel(reason = "Director cancelled collab session") {
|
|
14661
|
-
if (this.
|
|
15325
|
+
if (this.cancelled) return;
|
|
14662
15326
|
this.cancelled = true;
|
|
14663
15327
|
if (this._timeoutTimer) {
|
|
14664
15328
|
clearTimeout(this._timeoutTimer);
|
|
@@ -14696,6 +15360,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14696
15360
|
this.subagentIds.set("critic", criticId);
|
|
14697
15361
|
const timeout = new Promise((_, reject) => {
|
|
14698
15362
|
this._timeoutTimer = setTimeout(() => {
|
|
15363
|
+
if (this._raceResolved) return;
|
|
14699
15364
|
this.cancel("Session-level timeout reached");
|
|
14700
15365
|
reject(new Error(`CollabSession timed out after ${this.timeoutMs}ms`));
|
|
14701
15366
|
}, this.timeoutMs);
|
|
@@ -14711,6 +15376,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14711
15376
|
timeout
|
|
14712
15377
|
]);
|
|
14713
15378
|
} catch (err) {
|
|
15379
|
+
this._raceResolved = true;
|
|
14714
15380
|
if (this._timeoutTimer) {
|
|
14715
15381
|
clearTimeout(this._timeoutTimer);
|
|
14716
15382
|
this._timeoutTimer = void 0;
|
|
@@ -14725,6 +15391,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14725
15391
|
}
|
|
14726
15392
|
this.snapshotWarnings = await this.checkSnapshotFreshness();
|
|
14727
15393
|
const report = this.assembleReport();
|
|
15394
|
+
this._raceResolved = true;
|
|
14728
15395
|
this.cleanup();
|
|
14729
15396
|
this.emit("session.done", report);
|
|
14730
15397
|
return report;
|
|
@@ -18307,7 +18974,7 @@ var TaskTracker = class {
|
|
|
18307
18974
|
const blockers = this.getBlockers(taskId);
|
|
18308
18975
|
return blockers.every((id) => {
|
|
18309
18976
|
const node = this.graph?.nodes.get(id);
|
|
18310
|
-
return node?.status === "completed";
|
|
18977
|
+
return node?.status === "completed" || node?.status === "failed";
|
|
18311
18978
|
});
|
|
18312
18979
|
}
|
|
18313
18980
|
getProgress() {
|
|
@@ -18339,7 +19006,7 @@ var TaskTracker = class {
|
|
|
18339
19006
|
const remainingBlockers = this.getBlockers(depId);
|
|
18340
19007
|
const allUnblocked = remainingBlockers.every((id) => {
|
|
18341
19008
|
const blocker = this.graph?.nodes.get(id);
|
|
18342
|
-
return blocker?.status === "completed";
|
|
19009
|
+
return blocker?.status === "completed" || blocker?.status === "failed";
|
|
18343
19010
|
});
|
|
18344
19011
|
if (allUnblocked) {
|
|
18345
19012
|
dep.status = "pending";
|
|
@@ -18353,7 +19020,7 @@ var TaskTracker = class {
|
|
|
18353
19020
|
const blockers = this.getBlockers(taskId);
|
|
18354
19021
|
const someBlocked = blockers.some((id) => {
|
|
18355
19022
|
const blocker = this.graph?.nodes.get(id);
|
|
18356
|
-
return blocker?.status !== "completed";
|
|
19023
|
+
return blocker?.status !== "completed" && blocker?.status !== "failed";
|
|
18357
19024
|
});
|
|
18358
19025
|
if (someBlocked) {
|
|
18359
19026
|
const node = this.graph.nodes.get(taskId);
|
|
@@ -18790,12 +19457,6 @@ var TaskGraphStore = class {
|
|
|
18790
19457
|
};
|
|
18791
19458
|
|
|
18792
19459
|
// src/sdd/spec-builder.ts
|
|
18793
|
-
function expectDefined13(value) {
|
|
18794
|
-
if (value === null || value === void 0) {
|
|
18795
|
-
throw new Error("Expected value to be defined");
|
|
18796
|
-
}
|
|
18797
|
-
return value;
|
|
18798
|
-
}
|
|
18799
19460
|
function buildQuestioningPrompt(session, min, max) {
|
|
18800
19461
|
const answered = session.answers.length;
|
|
18801
19462
|
const remaining = Math.max(0, min - answered);
|
|
@@ -18841,7 +19502,7 @@ function buildQuestioningPrompt(session, min, max) {
|
|
|
18841
19502
|
if (answered > 0) {
|
|
18842
19503
|
lines.push("", "**Conversation so far:**");
|
|
18843
19504
|
for (let i = 0; i < answered; i++) {
|
|
18844
|
-
const a =
|
|
19505
|
+
const a = expectDefined(session.answers[i]);
|
|
18845
19506
|
lines.push(``, `Q${i + 1}: ${a.question}`, `A${i + 1}: ${a.answer}`);
|
|
18846
19507
|
}
|
|
18847
19508
|
}
|
|
@@ -18999,10 +19660,10 @@ var AISpecBuilder = class {
|
|
|
18999
19660
|
async saveSession() {
|
|
19000
19661
|
if (!this.sessionPath) return;
|
|
19001
19662
|
try {
|
|
19002
|
-
const
|
|
19663
|
+
const fsp21 = await import('fs/promises');
|
|
19003
19664
|
const path37 = await import('path');
|
|
19004
19665
|
const { atomicWrite: atomicWrite2 } = await Promise.resolve().then(() => (init_atomic_write(), atomic_write_exports));
|
|
19005
|
-
await
|
|
19666
|
+
await fsp21.mkdir(path37.dirname(this.sessionPath), { recursive: true });
|
|
19006
19667
|
await atomicWrite2(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
19007
19668
|
} catch {
|
|
19008
19669
|
}
|
|
@@ -19011,8 +19672,8 @@ var AISpecBuilder = class {
|
|
|
19011
19672
|
async loadSession() {
|
|
19012
19673
|
if (!this.sessionPath) return false;
|
|
19013
19674
|
try {
|
|
19014
|
-
const
|
|
19015
|
-
const raw = await
|
|
19675
|
+
const fsp21 = await import('fs/promises');
|
|
19676
|
+
const raw = await fsp21.readFile(this.sessionPath, "utf8");
|
|
19016
19677
|
const loaded = JSON.parse(raw);
|
|
19017
19678
|
if (loaded?.id && loaded?.phase && loaded?.title) {
|
|
19018
19679
|
this.session = loaded;
|
|
@@ -19026,8 +19687,8 @@ var AISpecBuilder = class {
|
|
|
19026
19687
|
async deleteSession() {
|
|
19027
19688
|
if (!this.sessionPath) return;
|
|
19028
19689
|
try {
|
|
19029
|
-
const
|
|
19030
|
-
await
|
|
19690
|
+
const fsp21 = await import('fs/promises');
|
|
19691
|
+
await fsp21.unlink(this.sessionPath);
|
|
19031
19692
|
} catch {
|
|
19032
19693
|
}
|
|
19033
19694
|
}
|
|
@@ -19428,7 +20089,7 @@ function templateToMarkdown(template, title) {
|
|
|
19428
20089
|
}
|
|
19429
20090
|
|
|
19430
20091
|
// src/sdd/task-visualizer.ts
|
|
19431
|
-
var
|
|
20092
|
+
var STATUS_ICON2 = {
|
|
19432
20093
|
pending: "\u25CB",
|
|
19433
20094
|
in_progress: "\u25D0",
|
|
19434
20095
|
blocked: "\u2298",
|
|
@@ -19436,13 +20097,13 @@ var STATUS_ICON = {
|
|
|
19436
20097
|
review: "\u25D1",
|
|
19437
20098
|
completed: "\u25CF"
|
|
19438
20099
|
};
|
|
19439
|
-
var
|
|
20100
|
+
var PRIORITY_ICON2 = {
|
|
19440
20101
|
critical: "\u{1F534}",
|
|
19441
20102
|
high: "\u{1F7E0}",
|
|
19442
20103
|
medium: "\u{1F7E1}",
|
|
19443
20104
|
low: "\u{1F7E2}"
|
|
19444
20105
|
};
|
|
19445
|
-
var
|
|
20106
|
+
var TYPE_ICON2 = {
|
|
19446
20107
|
feature: "\u26A1",
|
|
19447
20108
|
bugfix: "\u{1F41B}",
|
|
19448
20109
|
refactor: "\u267B\uFE0F",
|
|
@@ -19491,9 +20152,9 @@ function renderNode(graph, nodeId, lines, rendered, childrenMap, compact, prefix
|
|
|
19491
20152
|
rendered.add(nodeId);
|
|
19492
20153
|
const node = graph.nodes.get(nodeId);
|
|
19493
20154
|
if (!node) return;
|
|
19494
|
-
const icon =
|
|
19495
|
-
const prioIcon =
|
|
19496
|
-
const typeIcon =
|
|
20155
|
+
const icon = STATUS_ICON2[node.status];
|
|
20156
|
+
const prioIcon = PRIORITY_ICON2[node.priority];
|
|
20157
|
+
const typeIcon = TYPE_ICON2[node.type];
|
|
19497
20158
|
const title = compact ? truncate2(node.title, 40) : node.title;
|
|
19498
20159
|
const blockedBy = childrenMap.get(nodeId) ?? [];
|
|
19499
20160
|
const depsStr = blockedBy.length > 0 ? ` \u2190 [${blockedBy.map((d) => graph.nodes.get(d)?.title?.slice(0, 12) ?? "?").join(", ")}]` : "";
|
|
@@ -19535,11 +20196,11 @@ function renderTaskList(graph) {
|
|
|
19535
20196
|
}
|
|
19536
20197
|
for (const [status, group] of Object.entries(groups)) {
|
|
19537
20198
|
if (group.length === 0) continue;
|
|
19538
|
-
const icon =
|
|
20199
|
+
const icon = STATUS_ICON2[status];
|
|
19539
20200
|
lines.push(`${icon} ${status.toUpperCase()} (${group.length})`);
|
|
19540
20201
|
for (const node of group) {
|
|
19541
|
-
const prio =
|
|
19542
|
-
const type =
|
|
20202
|
+
const prio = PRIORITY_ICON2[node.priority];
|
|
20203
|
+
const type = TYPE_ICON2[node.type];
|
|
19543
20204
|
lines.push(` ${type} ${prio} ${node.title}`);
|
|
19544
20205
|
}
|
|
19545
20206
|
lines.push("");
|
|
@@ -19583,12 +20244,6 @@ function truncate2(str, maxLen) {
|
|
|
19583
20244
|
}
|
|
19584
20245
|
|
|
19585
20246
|
// src/sdd/critical-path.ts
|
|
19586
|
-
function expectDefined14(value) {
|
|
19587
|
-
if (value === null || value === void 0) {
|
|
19588
|
-
throw new Error("Expected value to be defined");
|
|
19589
|
-
}
|
|
19590
|
-
return value;
|
|
19591
|
-
}
|
|
19592
20247
|
function analyzeCriticalPath(graph) {
|
|
19593
20248
|
const nodes = Array.from(graph.nodes.values());
|
|
19594
20249
|
const topoOrder = topologicalSort(graph);
|
|
@@ -19664,7 +20319,7 @@ function getTransitiveBlocked(_graph, taskId, blocksMap) {
|
|
|
19664
20319
|
const visited = /* @__PURE__ */ new Set();
|
|
19665
20320
|
const queue = [taskId];
|
|
19666
20321
|
while (queue.length > 0) {
|
|
19667
|
-
const current =
|
|
20322
|
+
const current = expectDefined(queue.shift());
|
|
19668
20323
|
const blocked = blocksMap.get(current);
|
|
19669
20324
|
if (!blocked) continue;
|
|
19670
20325
|
for (const id of blocked) {
|
|
@@ -19710,7 +20365,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
19710
20365
|
if (!changed) break;
|
|
19711
20366
|
}
|
|
19712
20367
|
let maxDist = 0;
|
|
19713
|
-
let maxId =
|
|
20368
|
+
let maxId = expectDefined(allIds[0]);
|
|
19714
20369
|
for (const id of allIds) {
|
|
19715
20370
|
const d = dist.get(id) ?? 0;
|
|
19716
20371
|
if (d > maxDist) {
|
|
@@ -20179,25 +20834,22 @@ var SddTaskDecomposer = class {
|
|
|
20179
20834
|
return nodes.some((n) => n.status === "blocked");
|
|
20180
20835
|
}
|
|
20181
20836
|
};
|
|
20182
|
-
function expectDefined15(value) {
|
|
20183
|
-
if (value === null || value === void 0) {
|
|
20184
|
-
throw new Error("Expected value to be defined");
|
|
20185
|
-
}
|
|
20186
|
-
return value;
|
|
20187
|
-
}
|
|
20188
20837
|
var SddParallelRun = class {
|
|
20189
20838
|
constructor(opts) {
|
|
20190
20839
|
this.opts = opts;
|
|
20191
20840
|
this.slots = Math.min(16, Math.max(1, opts.parallelSlots ?? 4));
|
|
20192
20841
|
this.timeoutMs = opts.taskTimeoutMs ?? 3e5;
|
|
20842
|
+
this.maxRetries = Math.max(0, opts.maxRetries ?? 2);
|
|
20193
20843
|
this.decomposer = new SddTaskDecomposer(opts.tracker, opts.graph, { parallelSlots: this.slots });
|
|
20194
20844
|
}
|
|
20195
20845
|
opts;
|
|
20196
20846
|
slots;
|
|
20197
20847
|
timeoutMs;
|
|
20848
|
+
maxRetries;
|
|
20198
20849
|
decomposer;
|
|
20199
20850
|
coordinator = null;
|
|
20200
20851
|
stopRequested = false;
|
|
20852
|
+
retryMap = /* @__PURE__ */ new Map();
|
|
20201
20853
|
// -------------------------------------------------------------------
|
|
20202
20854
|
// Public API
|
|
20203
20855
|
// -------------------------------------------------------------------
|
|
@@ -20209,6 +20861,7 @@ var SddParallelRun = class {
|
|
|
20209
20861
|
/** Execute all waves until completion or deadlock. Returns final summary. */
|
|
20210
20862
|
async run() {
|
|
20211
20863
|
this.stopRequested = false;
|
|
20864
|
+
this.retryMap.clear();
|
|
20212
20865
|
const startTime = Date.now();
|
|
20213
20866
|
let totalCompleted = 0;
|
|
20214
20867
|
let totalFailed = 0;
|
|
@@ -20333,13 +20986,24 @@ var SddParallelRun = class {
|
|
|
20333
20986
|
const successCount = results.filter((r) => r.status === "success").length;
|
|
20334
20987
|
const failCount = results.length - successCount;
|
|
20335
20988
|
for (let i = 0; i < results.length; i++) {
|
|
20336
|
-
const result =
|
|
20337
|
-
const taskId =
|
|
20989
|
+
const result = expectDefined(results[i]);
|
|
20990
|
+
const taskId = expectDefined(taskIds[i]);
|
|
20338
20991
|
if (result.status === "success") {
|
|
20339
20992
|
this.opts.tracker.updateNodeStatus(taskId, "completed");
|
|
20993
|
+
this.retryMap.delete(taskId);
|
|
20340
20994
|
} else {
|
|
20341
20995
|
const errMsg = result.error?.kind ? `${result.error.kind}: ${result.error.message}` : result.error?.message ?? "unknown error";
|
|
20342
|
-
this.
|
|
20996
|
+
const currentRetries = this.retryMap.get(taskId) ?? 0;
|
|
20997
|
+
if (currentRetries < this.maxRetries) {
|
|
20998
|
+
this.retryMap.set(taskId, currentRetries + 1);
|
|
20999
|
+
this.opts.tracker.updateNodeStatus(
|
|
21000
|
+
taskId,
|
|
21001
|
+
"pending",
|
|
21002
|
+
`Retry ${currentRetries + 1}/${this.maxRetries}: ${errMsg}`
|
|
21003
|
+
);
|
|
21004
|
+
} else {
|
|
21005
|
+
this.opts.tracker.updateNodeStatus(taskId, "failed", errMsg);
|
|
21006
|
+
}
|
|
20343
21007
|
}
|
|
20344
21008
|
}
|
|
20345
21009
|
return {
|
|
@@ -20354,6 +21018,7 @@ var SddParallelRun = class {
|
|
|
20354
21018
|
}
|
|
20355
21019
|
buildProgress() {
|
|
20356
21020
|
const gp = this.opts.tracker.getProgress();
|
|
21021
|
+
const isDeadlocked = !this.decomposer.isDone() && this.decomposer.nextBatch().deadlocked;
|
|
20357
21022
|
return {
|
|
20358
21023
|
wave: this.decomposer.getWaveCount(),
|
|
20359
21024
|
total: gp.total,
|
|
@@ -20363,7 +21028,7 @@ var SddParallelRun = class {
|
|
|
20363
21028
|
blocked: gp.blocked,
|
|
20364
21029
|
pending: gp.pending,
|
|
20365
21030
|
percent: gp.percentComplete,
|
|
20366
|
-
deadlocked:
|
|
21031
|
+
deadlocked: isDeadlocked
|
|
20367
21032
|
};
|
|
20368
21033
|
}
|
|
20369
21034
|
};
|
|
@@ -21441,12 +22106,6 @@ var allServers = () => ({
|
|
|
21441
22106
|
"zai-vision": { ...zaiVisionServer(), enabled: false },
|
|
21442
22107
|
"minimax-vision": { ...miniMaxVisionServer(), enabled: false }
|
|
21443
22108
|
});
|
|
21444
|
-
function expectDefined16(value) {
|
|
21445
|
-
if (value === null || value === void 0) {
|
|
21446
|
-
throw new Error("Expected value to be defined");
|
|
21447
|
-
}
|
|
21448
|
-
return value;
|
|
21449
|
-
}
|
|
21450
22109
|
function parseSkillRef(input) {
|
|
21451
22110
|
const trimmed = input.trim().replace(/^https?:\/\/github\.com\//, "").replace(/\.git$/, "");
|
|
21452
22111
|
const atIdx = trimmed.indexOf("@");
|
|
@@ -21463,7 +22122,7 @@ function parseSkillRef(input) {
|
|
|
21463
22122
|
if (parts.length < 2) {
|
|
21464
22123
|
throw new Error(`Invalid skill reference "${input}". Expected format: user/repo or user/repo@ref`);
|
|
21465
22124
|
}
|
|
21466
|
-
return { owner:
|
|
22125
|
+
return { owner: expectDefined(parts[0]), repo: expectDefined(parts[1]), ref };
|
|
21467
22126
|
}
|
|
21468
22127
|
var MAX_TARBALL_SIZE = 50 * 1024 * 1024;
|
|
21469
22128
|
async function downloadGitHubTarball(parsed) {
|
|
@@ -21632,12 +22291,6 @@ var SkillManifestStore = class {
|
|
|
21632
22291
|
};
|
|
21633
22292
|
|
|
21634
22293
|
// src/skills/skill-installer.ts
|
|
21635
|
-
function expectDefined17(value) {
|
|
21636
|
-
if (value === null || value === void 0) {
|
|
21637
|
-
throw new Error("Expected value to be defined");
|
|
21638
|
-
}
|
|
21639
|
-
return value;
|
|
21640
|
-
}
|
|
21641
22294
|
var MAX_SKILL_FILE_SIZE = 100 * 1024;
|
|
21642
22295
|
var SkillInstaller = class {
|
|
21643
22296
|
opts;
|
|
@@ -21762,7 +22415,7 @@ var SkillInstaller = class {
|
|
|
21762
22415
|
bySource.get(key)?.push(entry);
|
|
21763
22416
|
}
|
|
21764
22417
|
for (const [, entries] of bySource) {
|
|
21765
|
-
const first =
|
|
22418
|
+
const first = expectDefined(entries[0]);
|
|
21766
22419
|
const scope = first.scope;
|
|
21767
22420
|
const isGlobal = scope === "user";
|
|
21768
22421
|
try {
|
|
@@ -21929,15 +22582,387 @@ async function collectFiles(dir, baseDir2) {
|
|
|
21929
22582
|
}
|
|
21930
22583
|
return results;
|
|
21931
22584
|
}
|
|
22585
|
+
var GraphMemoryBackend = class {
|
|
22586
|
+
kind = "graph";
|
|
22587
|
+
file;
|
|
22588
|
+
graphFile;
|
|
22589
|
+
// In-memory graph state — lazily loaded, saved on mutation.
|
|
22590
|
+
nodes = /* @__PURE__ */ new Map();
|
|
22591
|
+
edges = [];
|
|
22592
|
+
loadedScope = null;
|
|
22593
|
+
loaded = false;
|
|
22594
|
+
constructor(opts) {
|
|
22595
|
+
this.file = new FileMemoryBackend({ paths: opts.paths });
|
|
22596
|
+
this.graphFile = opts.graphPath ?? `${opts.paths.projectDir}/memory-graph.json`;
|
|
22597
|
+
}
|
|
22598
|
+
// ── Backend interface ──────────────────────────────────────────────
|
|
22599
|
+
async remember(scope, entry, filePath) {
|
|
22600
|
+
await this.file.remember(scope, entry, filePath);
|
|
22601
|
+
await this.loadGraph(scope);
|
|
22602
|
+
const nodeId = this.nodeId(entry);
|
|
22603
|
+
const existing = this.nodes.get(nodeId);
|
|
22604
|
+
if (existing) {
|
|
22605
|
+
existing.count++;
|
|
22606
|
+
existing.entry = entry;
|
|
22607
|
+
existing.type = entry.type;
|
|
22608
|
+
existing.tags = entry.tags;
|
|
22609
|
+
existing.priority = entry.priority;
|
|
22610
|
+
} else {
|
|
22611
|
+
this.nodes.set(nodeId, {
|
|
22612
|
+
id: nodeId,
|
|
22613
|
+
entry,
|
|
22614
|
+
firstSeen: entry.ts,
|
|
22615
|
+
count: 1,
|
|
22616
|
+
type: entry.type,
|
|
22617
|
+
tags: entry.tags,
|
|
22618
|
+
priority: entry.priority
|
|
22619
|
+
});
|
|
22620
|
+
for (const [, other] of this.nodes) {
|
|
22621
|
+
if (other.id === nodeId) continue;
|
|
22622
|
+
const sim = wordOverlap(entry.text, other.entry.text);
|
|
22623
|
+
const tagSim = sharedTags(entry.tags ?? [], other.tags ?? []);
|
|
22624
|
+
const weight = Math.max(sim, tagSim * 0.5);
|
|
22625
|
+
if (weight > 0.15) {
|
|
22626
|
+
this.edges.push({
|
|
22627
|
+
from: nodeId,
|
|
22628
|
+
to: other.id,
|
|
22629
|
+
relation: sim >= tagSim ? "similar" : "same_turn",
|
|
22630
|
+
weight,
|
|
22631
|
+
ts: entry.ts
|
|
22632
|
+
});
|
|
22633
|
+
}
|
|
22634
|
+
}
|
|
22635
|
+
}
|
|
22636
|
+
await this.saveGraph(scope);
|
|
22637
|
+
}
|
|
22638
|
+
async forget(scope, query, filePath) {
|
|
22639
|
+
const removed = await this.file.forget(scope, query, filePath);
|
|
22640
|
+
if (removed > 0) {
|
|
22641
|
+
await this.loadGraph(scope);
|
|
22642
|
+
const n = query.toLowerCase();
|
|
22643
|
+
const toRemove = [];
|
|
22644
|
+
for (const [id, node] of this.nodes) {
|
|
22645
|
+
if (node.entry.text.toLowerCase().includes(n)) {
|
|
22646
|
+
toRemove.push(id);
|
|
22647
|
+
}
|
|
22648
|
+
}
|
|
22649
|
+
for (const id of toRemove) this.nodes.delete(id);
|
|
22650
|
+
this.edges = this.edges.filter((e) => !toRemove.includes(e.from) && !toRemove.includes(e.to));
|
|
22651
|
+
await this.saveGraph(scope);
|
|
22652
|
+
}
|
|
22653
|
+
return removed;
|
|
22654
|
+
}
|
|
22655
|
+
async readAll(scope, filePath) {
|
|
22656
|
+
return this.file.readAll(scope, filePath);
|
|
22657
|
+
}
|
|
22658
|
+
async list(scope, filePath, limit) {
|
|
22659
|
+
await this.loadGraph(scope);
|
|
22660
|
+
const fileEntries = await this.file.list(scope, filePath);
|
|
22661
|
+
const nodeMap = new Map(this.nodes.entries());
|
|
22662
|
+
const enriched = fileEntries.map((fe) => {
|
|
22663
|
+
const nodeId = this.nodeId(fe);
|
|
22664
|
+
const node = nodeMap.get(nodeId);
|
|
22665
|
+
if (node) {
|
|
22666
|
+
return {
|
|
22667
|
+
...fe,
|
|
22668
|
+
type: node.type ?? fe.type,
|
|
22669
|
+
tags: node.tags ?? fe.tags,
|
|
22670
|
+
priority: node.priority ?? fe.priority
|
|
22671
|
+
};
|
|
22672
|
+
}
|
|
22673
|
+
return fe;
|
|
22674
|
+
});
|
|
22675
|
+
const fileIds = new Set(fileEntries.map((e) => this.nodeId(e)));
|
|
22676
|
+
for (const [id, node] of this.nodes) {
|
|
22677
|
+
if (!fileIds.has(id)) {
|
|
22678
|
+
enriched.push(node.entry);
|
|
22679
|
+
}
|
|
22680
|
+
}
|
|
22681
|
+
enriched.sort((a, b) => b.ts.localeCompare(a.ts));
|
|
22682
|
+
return limit ? enriched.slice(0, limit) : enriched;
|
|
22683
|
+
}
|
|
22684
|
+
async search(scope, query, filePath, limit) {
|
|
22685
|
+
await this.loadGraph(scope);
|
|
22686
|
+
const needle = query.toLowerCase().split(/\s+/);
|
|
22687
|
+
const all = await this.list(scope, filePath);
|
|
22688
|
+
const scored = all.map((entry) => {
|
|
22689
|
+
const words = entry.text.toLowerCase().split(/\s+/);
|
|
22690
|
+
let score = 0;
|
|
22691
|
+
for (const n of needle) {
|
|
22692
|
+
if (words.some((w) => w.includes(n))) score += 1;
|
|
22693
|
+
if (entry.tags?.some((t2) => t2.toLowerCase().includes(n))) score += 2;
|
|
22694
|
+
}
|
|
22695
|
+
const node = this.nodes.get(this.nodeId(entry));
|
|
22696
|
+
if (node) {
|
|
22697
|
+
if (node.priority === "critical") score += 3;
|
|
22698
|
+
else if (node.priority === "high") score += 2;
|
|
22699
|
+
score += node.count * 0.5;
|
|
22700
|
+
}
|
|
22701
|
+
return { entry, score };
|
|
22702
|
+
});
|
|
22703
|
+
scored.sort((a, b) => b.score - a.score);
|
|
22704
|
+
const matched = scored.filter((s) => s.score > 0).map((s) => s.entry);
|
|
22705
|
+
return limit ? matched.slice(0, limit) : matched;
|
|
22706
|
+
}
|
|
22707
|
+
async clear(scope, filePath) {
|
|
22708
|
+
await this.file.clear(scope, filePath);
|
|
22709
|
+
this.nodes.clear();
|
|
22710
|
+
this.edges = [];
|
|
22711
|
+
this.loadedScope = scope;
|
|
22712
|
+
this.loaded = true;
|
|
22713
|
+
try {
|
|
22714
|
+
await fsp3.unlink(this.graphFile);
|
|
22715
|
+
} catch {
|
|
22716
|
+
}
|
|
22717
|
+
}
|
|
22718
|
+
async consolidate(scope, filePath) {
|
|
22719
|
+
return this.file.consolidate(scope, filePath);
|
|
22720
|
+
}
|
|
22721
|
+
// ── Graph-specific queries ─────────────────────────────────────────
|
|
22722
|
+
/**
|
|
22723
|
+
* Find memories related to the given entry, ordered by edge weight.
|
|
22724
|
+
*/
|
|
22725
|
+
async findRelated(scope, _filePath, entryText, limit = 5) {
|
|
22726
|
+
await this.loadGraph(scope);
|
|
22727
|
+
const targetId = this.nodeId({ scope, text: entryText, ts: "" });
|
|
22728
|
+
const related = this.edges.filter((e) => e.from === targetId || e.to === targetId).sort((a, b) => b.weight - a.weight).slice(0, limit);
|
|
22729
|
+
const result = [];
|
|
22730
|
+
for (const edge of related) {
|
|
22731
|
+
const otherId = edge.from === targetId ? edge.to : edge.from;
|
|
22732
|
+
const node = this.nodes.get(otherId);
|
|
22733
|
+
if (node) result.push(node.entry);
|
|
22734
|
+
}
|
|
22735
|
+
return result;
|
|
22736
|
+
}
|
|
22737
|
+
/**
|
|
22738
|
+
* Get all edges for visualization or traversal.
|
|
22739
|
+
*/
|
|
22740
|
+
getGraph() {
|
|
22741
|
+
return {
|
|
22742
|
+
nodes: [...this.nodes.values()],
|
|
22743
|
+
edges: [...this.edges]
|
|
22744
|
+
};
|
|
22745
|
+
}
|
|
22746
|
+
// ── Persistence ────────────────────────────────────────────────────
|
|
22747
|
+
nodeId(entry) {
|
|
22748
|
+
const norm = entry.text.toLowerCase().trim().replace(/\s+/g, " ");
|
|
22749
|
+
return `${entry.scope ?? "mem"}::${simpleHash(norm)}`;
|
|
22750
|
+
}
|
|
22751
|
+
async loadGraph(scope) {
|
|
22752
|
+
if (this.loaded && this.loadedScope === scope) return;
|
|
22753
|
+
try {
|
|
22754
|
+
const raw = await fsp3.readFile(this.graphFile, "utf8");
|
|
22755
|
+
const data = JSON.parse(raw);
|
|
22756
|
+
this.nodes = new Map(data.nodes);
|
|
22757
|
+
this.edges = data.edges;
|
|
22758
|
+
} catch {
|
|
22759
|
+
this.nodes = /* @__PURE__ */ new Map();
|
|
22760
|
+
this.edges = [];
|
|
22761
|
+
}
|
|
22762
|
+
this.loadedScope = scope;
|
|
22763
|
+
this.loaded = true;
|
|
22764
|
+
}
|
|
22765
|
+
async saveGraph(scope) {
|
|
22766
|
+
this.loadedScope = scope;
|
|
22767
|
+
this.loaded = true;
|
|
22768
|
+
try {
|
|
22769
|
+
const data = {
|
|
22770
|
+
nodes: [...this.nodes.entries()],
|
|
22771
|
+
edges: this.edges
|
|
22772
|
+
};
|
|
22773
|
+
await fsp3.mkdir(
|
|
22774
|
+
this.graphFile.substring(0, this.graphFile.lastIndexOf("/")),
|
|
22775
|
+
{ recursive: true }
|
|
22776
|
+
);
|
|
22777
|
+
const tmp = `${this.graphFile}.tmp`;
|
|
22778
|
+
await fsp3.writeFile(tmp, JSON.stringify(data));
|
|
22779
|
+
await fsp3.rename(tmp, this.graphFile);
|
|
22780
|
+
} catch {
|
|
22781
|
+
}
|
|
22782
|
+
}
|
|
22783
|
+
};
|
|
22784
|
+
function wordOverlap(a, b) {
|
|
22785
|
+
const wordsA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
22786
|
+
const wordsB = new Set(b.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
22787
|
+
if (wordsA.size === 0 || wordsB.size === 0) return 0;
|
|
22788
|
+
let intersection = 0;
|
|
22789
|
+
for (const w of wordsA) {
|
|
22790
|
+
if (wordsB.has(w)) intersection++;
|
|
22791
|
+
}
|
|
22792
|
+
return intersection / Math.max(wordsA.size, wordsB.size);
|
|
22793
|
+
}
|
|
22794
|
+
function sharedTags(a, b) {
|
|
22795
|
+
if (a.length === 0 || b.length === 0) return 0;
|
|
22796
|
+
const setB = new Set(b);
|
|
22797
|
+
let shared = 0;
|
|
22798
|
+
for (const t2 of a) if (setB.has(t2)) shared++;
|
|
22799
|
+
return shared / Math.max(a.length, b.length);
|
|
22800
|
+
}
|
|
22801
|
+
function simpleHash(s) {
|
|
22802
|
+
let h = 0;
|
|
22803
|
+
for (let i = 0; i < s.length; i++) {
|
|
22804
|
+
h = (h << 5) - h + s.charCodeAt(i) | 0;
|
|
22805
|
+
}
|
|
22806
|
+
return Math.abs(h).toString(36);
|
|
22807
|
+
}
|
|
22808
|
+
|
|
22809
|
+
// src/storage/memory-consolidator.ts
|
|
22810
|
+
function buildConsolidationPrompt(finalText, iterations, existingEntries) {
|
|
22811
|
+
const existingBlock = existingEntries.length > 0 ? `
|
|
22812
|
+
|
|
22813
|
+
Existing memory entries:
|
|
22814
|
+
${existingEntries.map((e) => `- [${e.ts.slice(0, 10)}] ${e.text}`).join("\n")}` : "";
|
|
22815
|
+
return `You are a memory consolidator. Review the following session summary and decide what key facts, conventions, decisions, or learnings should be persisted to long-term memory.
|
|
22816
|
+
|
|
22817
|
+
Session summary (${iterations} iterations):
|
|
22818
|
+
${finalText.slice(0, 3e3)}${existingBlock}
|
|
22819
|
+
|
|
22820
|
+
Return a JSON object with an "operations" array. Each operation must have an "action" field:
|
|
22821
|
+
- "add": create a new memory entry. Include "text", and optionally "type", "tags", "priority".
|
|
22822
|
+
- "edit": replace an existing entry. Include "query" (to match) and "text" (replacement).
|
|
22823
|
+
- "delete": remove an entry. Include "query" (to match).
|
|
22824
|
+
|
|
22825
|
+
Memory types:
|
|
22826
|
+
- "fact": Objective truth about the project (e.g. "uses pnpm workspaces")
|
|
22827
|
+
- "decision": A choice that was made (e.g. "decided to use biome over eslint")
|
|
22828
|
+
- "convention": A recurring pattern or standard (e.g. "commit messages use conventional format")
|
|
22829
|
+
- "preference": User or team preference (e.g. "prefers short variable names")
|
|
22830
|
+
- "reference": Pointer to a file or location (e.g. "auth logic in packages/core/src/auth/")
|
|
22831
|
+
- "anti_pattern": Something to avoid (e.g. "never use any in TypeScript")
|
|
22832
|
+
|
|
22833
|
+
Priority levels:
|
|
22834
|
+
- "critical": Must always be known (e.g. security constraints)
|
|
22835
|
+
- "high": Important for most tasks
|
|
22836
|
+
- "medium": Useful context
|
|
22837
|
+
- "low": Nice to know
|
|
22838
|
+
|
|
22839
|
+
Rules:
|
|
22840
|
+
- Only persist facts likely useful across multiple future sessions.
|
|
22841
|
+
- Do NOT persist task progress, temporary state, or one-off observations.
|
|
22842
|
+
- Prefer "add" over "edit" unless the existing entry is clearly outdated.
|
|
22843
|
+
- Assign a type and priority to every "add" operation.
|
|
22844
|
+
- Use 1-3 hashtag tags for each entry (e.g. #typescript #build).
|
|
22845
|
+
- Be concise \u2014 each memory entry should be one clear sentence.
|
|
22846
|
+
|
|
22847
|
+
Return ONLY valid JSON, no markdown, no explanation:
|
|
22848
|
+
{
|
|
22849
|
+
"operations": [
|
|
22850
|
+
{
|
|
22851
|
+
"action": "add",
|
|
22852
|
+
"text": "Project uses pnpm workspaces with TypeScript strict mode",
|
|
22853
|
+
"type": "convention",
|
|
22854
|
+
"priority": "high",
|
|
22855
|
+
"tags": ["pnpm", "typescript", "build"]
|
|
22856
|
+
},
|
|
22857
|
+
{
|
|
22858
|
+
"action": "edit",
|
|
22859
|
+
"query": "pnpm",
|
|
22860
|
+
"text": "Project uses pnpm v9+ with ESM-only modules",
|
|
22861
|
+
"type": "fact",
|
|
22862
|
+
"priority": "medium"
|
|
22863
|
+
},
|
|
22864
|
+
{ "action": "delete", "query": "outdated convention" }
|
|
22865
|
+
]
|
|
22866
|
+
}`;
|
|
22867
|
+
}
|
|
22868
|
+
var SessionMemoryConsolidator = class {
|
|
22869
|
+
name = "session-memory-consolidator";
|
|
22870
|
+
owner = "core";
|
|
22871
|
+
memoryStore;
|
|
22872
|
+
provider;
|
|
22873
|
+
model;
|
|
22874
|
+
minIterations;
|
|
22875
|
+
maxExistingEntries;
|
|
22876
|
+
constructor(opts) {
|
|
22877
|
+
this.memoryStore = opts.memoryStore;
|
|
22878
|
+
this.provider = opts.provider;
|
|
22879
|
+
this.model = opts.model;
|
|
22880
|
+
this.minIterations = opts.minIterations ?? 2;
|
|
22881
|
+
this.maxExistingEntries = opts.maxExistingEntries ?? 15;
|
|
22882
|
+
}
|
|
22883
|
+
afterRun = async (ctx, result) => {
|
|
22884
|
+
if (result.status !== "done") return;
|
|
22885
|
+
if (!result.finalText || result.finalText.trim().length < 20) return;
|
|
22886
|
+
if (result.iterations < this.minIterations) return;
|
|
22887
|
+
const provider = this.provider ?? ctx.provider;
|
|
22888
|
+
if (!provider || !provider.complete) return;
|
|
22889
|
+
try {
|
|
22890
|
+
const existingEntries = await this.memoryStore.list("project-memory", this.maxExistingEntries);
|
|
22891
|
+
const prompt = buildConsolidationPrompt(
|
|
22892
|
+
result.finalText,
|
|
22893
|
+
result.iterations,
|
|
22894
|
+
existingEntries
|
|
22895
|
+
);
|
|
22896
|
+
const signal = AbortSignal.timeout(15e3);
|
|
22897
|
+
const response = await provider.complete(
|
|
22898
|
+
{
|
|
22899
|
+
model: this.model ?? ctx.model,
|
|
22900
|
+
system: [{ type: "text", text: prompt }],
|
|
22901
|
+
messages: [
|
|
22902
|
+
{ role: "user", content: "Review the session and return memory operations as JSON." }
|
|
22903
|
+
],
|
|
22904
|
+
maxTokens: 500
|
|
22905
|
+
},
|
|
22906
|
+
{ signal }
|
|
22907
|
+
);
|
|
22908
|
+
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("").trim();
|
|
22909
|
+
if (!text) return;
|
|
22910
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
22911
|
+
if (!jsonMatch) return;
|
|
22912
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
22913
|
+
if (!Array.isArray(parsed.operations) || parsed.operations.length === 0) return;
|
|
22914
|
+
let added = 0;
|
|
22915
|
+
let edited = 0;
|
|
22916
|
+
let deleted = 0;
|
|
22917
|
+
for (const op of parsed.operations) {
|
|
22918
|
+
switch (op.action) {
|
|
22919
|
+
case "add": {
|
|
22920
|
+
if (op.text && op.text.trim()) {
|
|
22921
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
22922
|
+
type: op.type,
|
|
22923
|
+
tags: op.tags,
|
|
22924
|
+
priority: op.priority
|
|
22925
|
+
});
|
|
22926
|
+
added++;
|
|
22927
|
+
}
|
|
22928
|
+
break;
|
|
22929
|
+
}
|
|
22930
|
+
case "edit": {
|
|
22931
|
+
if (op.query && op.text && op.text.trim()) {
|
|
22932
|
+
await this.memoryStore.forget(op.query);
|
|
22933
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
22934
|
+
type: op.type,
|
|
22935
|
+
tags: op.tags,
|
|
22936
|
+
priority: op.priority
|
|
22937
|
+
});
|
|
22938
|
+
edited++;
|
|
22939
|
+
}
|
|
22940
|
+
break;
|
|
22941
|
+
}
|
|
22942
|
+
case "delete": {
|
|
22943
|
+
if (op.query) {
|
|
22944
|
+
const n = await this.memoryStore.forget(op.query);
|
|
22945
|
+
deleted += n;
|
|
22946
|
+
}
|
|
22947
|
+
break;
|
|
22948
|
+
}
|
|
22949
|
+
}
|
|
22950
|
+
}
|
|
22951
|
+
if (added > 0 || edited > 0 || deleted > 0) {
|
|
22952
|
+
const parts = [];
|
|
22953
|
+
if (added) parts.push(`${added} added`);
|
|
22954
|
+
if (edited) parts.push(`${edited} edited`);
|
|
22955
|
+
if (deleted) parts.push(`${deleted} deleted`);
|
|
22956
|
+
process.stderr.write(`[memory] Session consolidation: ${parts.join(", ")}
|
|
22957
|
+
`);
|
|
22958
|
+
}
|
|
22959
|
+
} catch {
|
|
22960
|
+
}
|
|
22961
|
+
};
|
|
22962
|
+
};
|
|
21932
22963
|
|
|
21933
22964
|
// src/storage/annotations-store.ts
|
|
21934
22965
|
init_atomic_write();
|
|
21935
|
-
function expectDefined18(value) {
|
|
21936
|
-
if (value === null || value === void 0) {
|
|
21937
|
-
throw new Error("Expected value to be defined");
|
|
21938
|
-
}
|
|
21939
|
-
return value;
|
|
21940
|
-
}
|
|
21941
22966
|
var FILE_VERSION = 1;
|
|
21942
22967
|
var MAX_TEXT_LENGTH = 2e3;
|
|
21943
22968
|
var MAX_ANNOTATIONS = 1e3;
|
|
@@ -22030,7 +23055,7 @@ var AnnotationsStore = class {
|
|
|
22030
23055
|
return;
|
|
22031
23056
|
}
|
|
22032
23057
|
const next = {
|
|
22033
|
-
...
|
|
23058
|
+
...expectDefined(all[idx]),
|
|
22034
23059
|
resolved: true,
|
|
22035
23060
|
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22036
23061
|
resolvedBy: input.resolvedBy
|
|
@@ -22268,12 +23293,6 @@ var ReplayLogStore = class {
|
|
|
22268
23293
|
return next;
|
|
22269
23294
|
}
|
|
22270
23295
|
};
|
|
22271
|
-
function expectDefined19(value) {
|
|
22272
|
-
if (value === null || value === void 0) {
|
|
22273
|
-
throw new Error("Expected value to be defined");
|
|
22274
|
-
}
|
|
22275
|
-
return value;
|
|
22276
|
-
}
|
|
22277
23296
|
var SessionRecovery = class {
|
|
22278
23297
|
constructor(dir) {
|
|
22279
23298
|
this.dir = dir;
|
|
@@ -22314,7 +23333,7 @@ var SessionRecovery = class {
|
|
|
22314
23333
|
const lines = raw.split("\n").filter((l) => l.trim());
|
|
22315
23334
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
22316
23335
|
try {
|
|
22317
|
-
const ev = JSON.parse(
|
|
23336
|
+
const ev = JSON.parse(expectDefined(lines[i]));
|
|
22318
23337
|
if (ev.type === "in_flight_start") {
|
|
22319
23338
|
return {
|
|
22320
23339
|
sessionId,
|
|
@@ -22367,12 +23386,12 @@ var SessionRecovery = class {
|
|
|
22367
23386
|
let lastCheckpointIdx = -1;
|
|
22368
23387
|
for (let i = 0; i < events.length; i++) {
|
|
22369
23388
|
if (events[i]?.type === "checkpoint") {
|
|
22370
|
-
lastCheckpoint =
|
|
23389
|
+
lastCheckpoint = expectDefined(events[i]);
|
|
22371
23390
|
lastCheckpointIdx = i;
|
|
22372
23391
|
}
|
|
22373
23392
|
}
|
|
22374
23393
|
const pendingEvents = lastCheckpointIdx >= 0 ? events.slice(lastCheckpointIdx + 1) : events;
|
|
22375
|
-
const lastEv =
|
|
23394
|
+
const lastEv = expectDefined(events[events.length - 1]);
|
|
22376
23395
|
const inFlightStart = lastEv.type === "in_flight_start" ? lastEv : null;
|
|
22377
23396
|
const context = inFlightStart && inFlightStart.type === "in_flight_start" ? inFlightStart.context : null;
|
|
22378
23397
|
return {
|
|
@@ -22418,12 +23437,6 @@ var SessionRecovery = class {
|
|
|
22418
23437
|
|
|
22419
23438
|
// src/storage/tool-audit-log.ts
|
|
22420
23439
|
init_atomic_write();
|
|
22421
|
-
function expectDefined20(value) {
|
|
22422
|
-
if (value === null || value === void 0) {
|
|
22423
|
-
throw new Error("Expected value to be defined");
|
|
22424
|
-
}
|
|
22425
|
-
return value;
|
|
22426
|
-
}
|
|
22427
23440
|
var GENESIS_PREV = "0".repeat(64);
|
|
22428
23441
|
var DEFAULT_FSYNC_EVERY = 100;
|
|
22429
23442
|
var ToolAuditLog = class {
|
|
@@ -22504,7 +23517,7 @@ var ToolAuditLog = class {
|
|
|
22504
23517
|
}
|
|
22505
23518
|
let prevHash = GENESIS_PREV;
|
|
22506
23519
|
for (let i = 0; i < entries.length; i++) {
|
|
22507
|
-
const e =
|
|
23520
|
+
const e = expectDefined(entries[i]);
|
|
22508
23521
|
if (e.prevHash !== prevHash) {
|
|
22509
23522
|
return {
|
|
22510
23523
|
ok: false,
|
|
@@ -22624,12 +23637,6 @@ function sortKeys2(value) {
|
|
|
22624
23637
|
|
|
22625
23638
|
// src/storage/session-rewinder.ts
|
|
22626
23639
|
init_atomic_write();
|
|
22627
|
-
function expectDefined21(value) {
|
|
22628
|
-
if (value === null || value === void 0) {
|
|
22629
|
-
throw new Error("Expected value to be defined");
|
|
22630
|
-
}
|
|
22631
|
-
return value;
|
|
22632
|
-
}
|
|
22633
23640
|
var DefaultSessionRewinder = class {
|
|
22634
23641
|
constructor(sessionsDir, projectRoot) {
|
|
22635
23642
|
this.sessionsDir = sessionsDir;
|
|
@@ -22668,7 +23675,7 @@ var DefaultSessionRewinder = class {
|
|
|
22668
23675
|
const events = parseEvents(raw);
|
|
22669
23676
|
let targetIdx = -1;
|
|
22670
23677
|
for (let i = 0; i < events.length; i++) {
|
|
22671
|
-
const event =
|
|
23678
|
+
const event = expectDefined(events[i]);
|
|
22672
23679
|
if (event.type === "checkpoint") {
|
|
22673
23680
|
const checkpointEvent = event;
|
|
22674
23681
|
if (checkpointEvent.promptIndex === checkpointIndex) {
|
|
@@ -22682,7 +23689,7 @@ var DefaultSessionRewinder = class {
|
|
|
22682
23689
|
}
|
|
22683
23690
|
const snapshotsToRevert = [];
|
|
22684
23691
|
for (let i = targetIdx + 1; i < events.length; i++) {
|
|
22685
|
-
const event =
|
|
23692
|
+
const event = expectDefined(events[i]);
|
|
22686
23693
|
if (event.type === "checkpoint") {
|
|
22687
23694
|
break;
|
|
22688
23695
|
}
|
|
@@ -22792,6 +23799,43 @@ async function revertSnapshots(snapshots, projectRoot) {
|
|
|
22792
23799
|
return { revertedFiles, errors };
|
|
22793
23800
|
}
|
|
22794
23801
|
|
|
23802
|
+
// src/storage/task-store.ts
|
|
23803
|
+
init_atomic_write();
|
|
23804
|
+
function emptyTaskFile(sessionId) {
|
|
23805
|
+
return {
|
|
23806
|
+
version: 1,
|
|
23807
|
+
sessionId,
|
|
23808
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23809
|
+
tasks: []
|
|
23810
|
+
};
|
|
23811
|
+
}
|
|
23812
|
+
async function loadTasks(filePath) {
|
|
23813
|
+
let raw;
|
|
23814
|
+
try {
|
|
23815
|
+
raw = await fsp3.readFile(filePath, "utf8");
|
|
23816
|
+
} catch {
|
|
23817
|
+
return null;
|
|
23818
|
+
}
|
|
23819
|
+
try {
|
|
23820
|
+
const parsed = JSON.parse(raw);
|
|
23821
|
+
if (parsed?.version !== 1 || !Array.isArray(parsed.tasks)) return null;
|
|
23822
|
+
return parsed;
|
|
23823
|
+
} catch {
|
|
23824
|
+
return null;
|
|
23825
|
+
}
|
|
23826
|
+
}
|
|
23827
|
+
async function saveTasks(filePath, tasks) {
|
|
23828
|
+
try {
|
|
23829
|
+
tasks.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
23830
|
+
await atomicWrite(filePath, JSON.stringify(tasks, null, 2), { mode: 384 });
|
|
23831
|
+
} catch (err) {
|
|
23832
|
+
console.warn(
|
|
23833
|
+
"[task-store] save failed:",
|
|
23834
|
+
err instanceof Error ? err.message : String(err)
|
|
23835
|
+
);
|
|
23836
|
+
}
|
|
23837
|
+
}
|
|
23838
|
+
|
|
22795
23839
|
// src/storage/prompt-store.ts
|
|
22796
23840
|
init_atomic_write();
|
|
22797
23841
|
var DefaultPromptStore = class {
|
|
@@ -22864,12 +23908,6 @@ var DefaultPromptStore = class {
|
|
|
22864
23908
|
};
|
|
22865
23909
|
}
|
|
22866
23910
|
};
|
|
22867
|
-
function expectDefined22(value) {
|
|
22868
|
-
if (value === null || value === void 0) {
|
|
22869
|
-
throw new Error("Expected value to be defined");
|
|
22870
|
-
}
|
|
22871
|
-
return value;
|
|
22872
|
-
}
|
|
22873
23911
|
var ALL_SYNC_CATEGORIES = ["settings", "skills", "prompts", "memory", "history"];
|
|
22874
23912
|
var CloudSync = class {
|
|
22875
23913
|
constructor(paths, getConfig, setConfig) {
|
|
@@ -22912,8 +23950,8 @@ var CloudSync = class {
|
|
|
22912
23950
|
const cfg = this.getConfig();
|
|
22913
23951
|
if (!cfg?.enabled) return { ok: false, action: "push", categories: [], message: "Not enabled." };
|
|
22914
23952
|
const parts = cfg.repo.split("/");
|
|
22915
|
-
const owner =
|
|
22916
|
-
const repoName =
|
|
23953
|
+
const owner = expectDefined(parts[0]);
|
|
23954
|
+
const repoName = expectDefined(parts[1]);
|
|
22917
23955
|
const branch = "main";
|
|
22918
23956
|
const baseTreeSha = this.state?.sha;
|
|
22919
23957
|
const { treeEntries, rev } = await this.buildLocalTree(cfg.categories);
|
|
@@ -22965,8 +24003,8 @@ var CloudSync = class {
|
|
|
22965
24003
|
const cfg = this.getConfig();
|
|
22966
24004
|
if (!cfg?.enabled) return { ok: false, action: "pull", categories: [], message: "Not enabled." };
|
|
22967
24005
|
const pullParts = cfg.repo.split("/");
|
|
22968
|
-
const owner =
|
|
22969
|
-
const repoName =
|
|
24006
|
+
const owner = expectDefined(pullParts[0]);
|
|
24007
|
+
const repoName = expectDefined(pullParts[1]);
|
|
22970
24008
|
const branchData = await this.getRef(token, owner, repoName, "main");
|
|
22971
24009
|
const currentSha = branchData.object.sha;
|
|
22972
24010
|
const commitData = await this.getCommit(token, owner, repoName, currentSha);
|
|
@@ -24064,8 +25102,8 @@ var ReportGenerator = class {
|
|
|
24064
25102
|
try {
|
|
24065
25103
|
await stat(this.options.outputDir);
|
|
24066
25104
|
} catch {
|
|
24067
|
-
const { mkdir:
|
|
24068
|
-
await
|
|
25105
|
+
const { mkdir: mkdir17 } = await import('fs/promises');
|
|
25106
|
+
await mkdir17(this.options.outputDir, { recursive: true });
|
|
24069
25107
|
}
|
|
24070
25108
|
}
|
|
24071
25109
|
generateMarkdown(result) {
|
|
@@ -24312,12 +25350,6 @@ var defaultGitignoreUpdater = new GitignoreUpdater();
|
|
|
24312
25350
|
|
|
24313
25351
|
// src/security-scanner/orchestrator.ts
|
|
24314
25352
|
init_atomic_write();
|
|
24315
|
-
function expectDefined23(value) {
|
|
24316
|
-
if (value === null || value === void 0) {
|
|
24317
|
-
throw new Error("Expected value to be defined");
|
|
24318
|
-
}
|
|
24319
|
-
return value;
|
|
24320
|
-
}
|
|
24321
25353
|
var SecurityScannerOrchestrator = class {
|
|
24322
25354
|
constructor(retryPolicy, errorHandler) {
|
|
24323
25355
|
this.retryPolicy = retryPolicy;
|
|
@@ -24367,7 +25399,7 @@ var SecurityScannerOrchestrator = class {
|
|
|
24367
25399
|
if (detectionResult.detectedStacks.length === 0) {
|
|
24368
25400
|
throw new Error(`No supported tech stack detected in ${projectRoot}`);
|
|
24369
25401
|
}
|
|
24370
|
-
const techStack =
|
|
25402
|
+
const techStack = expectDefined(detectionResult.detectedStacks[0]);
|
|
24371
25403
|
const generatedSkill = await this.generateSkillLLM(provider, model, projectRoot, techStack);
|
|
24372
25404
|
const scanResult = await this.scanWithLLM(provider, model, projectRoot, generatedSkill, techStack, options);
|
|
24373
25405
|
const synthesizedReport = await this.synthesizeReportLLM(provider, model, projectRoot, techStack, scanResult);
|
|
@@ -24448,7 +25480,7 @@ Return ONLY the JSON object, no markdown, no explanation.`;
|
|
|
24448
25480
|
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
24449
25481
|
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
24450
25482
|
if (jsonMatch) {
|
|
24451
|
-
const sanitized = sanitizeJsonString(
|
|
25483
|
+
const sanitized = sanitizeJsonString(expectDefined(jsonMatch[0])) || expectDefined(jsonMatch[0]);
|
|
24452
25484
|
const skillData = JSON.parse(sanitized);
|
|
24453
25485
|
return {
|
|
24454
25486
|
name: skillData.name || `security-scanner-${techStack.stack}`,
|
|
@@ -24568,7 +25600,7 @@ Return ONLY the JSON array. If no issues found, return [].`;
|
|
|
24568
25600
|
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
24569
25601
|
const jsonMatch = text.match(/\[[\s\S]*\]/);
|
|
24570
25602
|
if (jsonMatch) {
|
|
24571
|
-
const sanitized = sanitizeJsonString(
|
|
25603
|
+
const sanitized = sanitizeJsonString(expectDefined(jsonMatch[0])) || expectDefined(jsonMatch[0]);
|
|
24572
25604
|
const parsed = JSON.parse(sanitized);
|
|
24573
25605
|
return parsed.map((item, idx) => ({
|
|
24574
25606
|
id: `llm-finding-${idx}-${Date.now()}`,
|
|
@@ -24808,7 +25840,7 @@ ${dirs.join(", ")}`);
|
|
|
24808
25840
|
if (detectionResult.detectedStacks.length === 0) {
|
|
24809
25841
|
throw new Error(`No supported tech stack detected in ${projectRoot}`);
|
|
24810
25842
|
}
|
|
24811
|
-
const techStack =
|
|
25843
|
+
const techStack = expectDefined(detectionResult.detectedStacks[0]);
|
|
24812
25844
|
return {
|
|
24813
25845
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24814
25846
|
projectRoot,
|
|
@@ -24997,16 +26029,16 @@ Use \`/security report <number>\` to view a specific report.` };
|
|
|
24997
26029
|
}
|
|
24998
26030
|
const index = Number.parseInt(reportId, 10) - 1;
|
|
24999
26031
|
if (!Number.isNaN(index) && reports[index]) {
|
|
25000
|
-
const { readFile:
|
|
25001
|
-
const content = await
|
|
26032
|
+
const { readFile: readFile40 } = await import('fs/promises');
|
|
26033
|
+
const content = await readFile40(join(reportsDir, reports[index]), "utf-8");
|
|
25002
26034
|
return { message: `# Security Report
|
|
25003
26035
|
|
|
25004
26036
|
${content}` };
|
|
25005
26037
|
}
|
|
25006
26038
|
const match = reports.find((r) => r.includes(reportId));
|
|
25007
26039
|
if (match) {
|
|
25008
|
-
const { readFile:
|
|
25009
|
-
const content = await
|
|
26040
|
+
const { readFile: readFile40 } = await import('fs/promises');
|
|
26041
|
+
const content = await readFile40(join(reportsDir, match), "utf-8");
|
|
25010
26042
|
return { message: `# Security Report
|
|
25011
26043
|
|
|
25012
26044
|
${content}` };
|
|
@@ -25416,12 +26448,6 @@ var FleetManager = class {
|
|
|
25416
26448
|
this.usage.dispose();
|
|
25417
26449
|
}
|
|
25418
26450
|
};
|
|
25419
|
-
function expectDefined24(value) {
|
|
25420
|
-
if (value === null || value === void 0) {
|
|
25421
|
-
throw new Error("Expected value to be defined");
|
|
25422
|
-
}
|
|
25423
|
-
return value;
|
|
25424
|
-
}
|
|
25425
26451
|
function createMcpControlTool(opts) {
|
|
25426
26452
|
const { getConfig, configPath, registry } = opts;
|
|
25427
26453
|
const inputSchema = {
|
|
@@ -25573,7 +26599,7 @@ async function runDisable(name, deps) {
|
|
|
25573
26599
|
const mcpServers = {
|
|
25574
26600
|
...full.mcpServers ?? {}
|
|
25575
26601
|
};
|
|
25576
|
-
const existing =
|
|
26602
|
+
const existing = expectDefined(mcpServers[name]);
|
|
25577
26603
|
mcpServers[name] = { ...existing, enabled: false };
|
|
25578
26604
|
full.mcpServers = mcpServers;
|
|
25579
26605
|
await writeConfig(deps.configPath, full);
|
|
@@ -25644,12 +26670,6 @@ function badge(state) {
|
|
|
25644
26670
|
}
|
|
25645
26671
|
|
|
25646
26672
|
// src/extension/registry.ts
|
|
25647
|
-
function expectDefined25(value) {
|
|
25648
|
-
if (value === null || value === void 0) {
|
|
25649
|
-
throw new Error("Expected value to be defined");
|
|
25650
|
-
}
|
|
25651
|
-
return value;
|
|
25652
|
-
}
|
|
25653
26673
|
var ExtensionRegistry = class {
|
|
25654
26674
|
extensions = [];
|
|
25655
26675
|
promptContributors = [];
|
|
@@ -25815,7 +26835,7 @@ var ExtensionRegistry = class {
|
|
|
25815
26835
|
* default runner, each subsequent wrapper wraps the previous.
|
|
25816
26836
|
*/
|
|
25817
26837
|
wrapProviderRunner(inner) {
|
|
25818
|
-
const wrappers = this.extensions.filter((e) => e.wrapProviderRunner).map((e) => ({ name: e.name, wrap:
|
|
26838
|
+
const wrappers = this.extensions.filter((e) => e.wrapProviderRunner).map((e) => ({ name: e.name, wrap: expectDefined(e.wrapProviderRunner) }));
|
|
25819
26839
|
if (wrappers.length === 0) return inner;
|
|
25820
26840
|
let composed = inner;
|
|
25821
26841
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
@@ -26832,6 +27852,7 @@ async function bootConfig(options = {}) {
|
|
|
26832
27852
|
await fsp3.mkdir(wpaths.projectDir, { recursive: true });
|
|
26833
27853
|
await fsp3.mkdir(wpaths.projectSessions, { recursive: true });
|
|
26834
27854
|
await writeProjectMeta(wpaths, projectRoot);
|
|
27855
|
+
await ensureGitignore(projectRoot);
|
|
26835
27856
|
cleanupStaleProjects(wpaths).catch(() => {
|
|
26836
27857
|
});
|
|
26837
27858
|
const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
|
|
@@ -26907,6 +27928,22 @@ async function writeProjectMeta(paths, projectRoot) {
|
|
|
26907
27928
|
} catch {
|
|
26908
27929
|
}
|
|
26909
27930
|
}
|
|
27931
|
+
var GITIGNORE_ENTRY = ".wrongstack/\n";
|
|
27932
|
+
async function ensureGitignore(projectRoot) {
|
|
27933
|
+
const gitignorePath = path6.join(projectRoot, ".gitignore");
|
|
27934
|
+
try {
|
|
27935
|
+
let content = "";
|
|
27936
|
+
try {
|
|
27937
|
+
content = await fsp3.readFile(gitignorePath, "utf8");
|
|
27938
|
+
} catch {
|
|
27939
|
+
}
|
|
27940
|
+
if (!content.includes(".wrongstack")) {
|
|
27941
|
+
const updated = content ? content.endsWith("\n") ? content + GITIGNORE_ENTRY : content + "\n" + GITIGNORE_ENTRY : GITIGNORE_ENTRY;
|
|
27942
|
+
await fsp3.writeFile(gitignorePath, updated, "utf8");
|
|
27943
|
+
}
|
|
27944
|
+
} catch {
|
|
27945
|
+
}
|
|
27946
|
+
}
|
|
26910
27947
|
async function cleanupStaleProjects(wpaths) {
|
|
26911
27948
|
const projectsRoot = path6.dirname(wpaths.projectDir);
|
|
26912
27949
|
let entries;
|
|
@@ -27344,7 +28381,10 @@ var DefaultSystemPromptBuilder = class {
|
|
|
27344
28381
|
skillCache;
|
|
27345
28382
|
/** Cached full skill bodies (after frontmatter), built once per session. */
|
|
27346
28383
|
skillBodyCache;
|
|
28384
|
+
/** Tools from last build — used for memory relevance scoring. */
|
|
28385
|
+
_lastBuildTools;
|
|
27347
28386
|
async build(ctx) {
|
|
28387
|
+
this._lastBuildTools = ctx.tools;
|
|
27348
28388
|
if (this.opts.skillLoader && !this.skillCache) {
|
|
27349
28389
|
try {
|
|
27350
28390
|
const entries = await this.opts.skillLoader.listEntries();
|
|
@@ -27648,10 +28688,31 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
27648
28688
|
const parts = [];
|
|
27649
28689
|
if (this.opts.memoryStore) {
|
|
27650
28690
|
try {
|
|
27651
|
-
|
|
27652
|
-
|
|
28691
|
+
if (this.opts.memoryStore.scoreRelevant) {
|
|
28692
|
+
const toolNames = this._lastBuildTools?.map((t2) => t2.name) ?? [];
|
|
28693
|
+
const scored = await this.opts.memoryStore.scoreRelevant(
|
|
28694
|
+
{
|
|
28695
|
+
currentTask: "",
|
|
28696
|
+
toolNames
|
|
28697
|
+
},
|
|
28698
|
+
"project-memory",
|
|
28699
|
+
8
|
|
28700
|
+
);
|
|
28701
|
+
if (scored.length > 0) {
|
|
28702
|
+
const lines = ["# Relevant Memory"];
|
|
28703
|
+
for (const e of scored) {
|
|
28704
|
+
const badge2 = e.type ? `[\`${e.type.replace("_", "-")}\`] ` : "";
|
|
28705
|
+
const priorityMark = e.priority === "critical" ? "\u26A1" : e.priority === "high" ? "\u25B2" : "";
|
|
28706
|
+
lines.push(`- ${priorityMark}${badge2}${e.text}${e.tags ? ` \`#${e.tags.join(" #")}\`` : ""}`);
|
|
28707
|
+
}
|
|
28708
|
+
parts.push(lines.join("\n"));
|
|
28709
|
+
}
|
|
28710
|
+
} else {
|
|
28711
|
+
const mem = await this.opts.memoryStore.readAll();
|
|
28712
|
+
if (mem.trim()) parts.push(`# Project Memory
|
|
27653
28713
|
|
|
27654
28714
|
${mem}`);
|
|
28715
|
+
}
|
|
27655
28716
|
} catch {
|
|
27656
28717
|
}
|
|
27657
28718
|
}
|
|
@@ -28103,8 +29164,13 @@ var SlashCommandRegistry = class {
|
|
|
28103
29164
|
if (!entry) {
|
|
28104
29165
|
return { message: `Unknown command "/${name}". Type /help for a list.` };
|
|
28105
29166
|
}
|
|
28106
|
-
|
|
28107
|
-
|
|
29167
|
+
try {
|
|
29168
|
+
const res = await entry.cmd.run(args, ctx);
|
|
29169
|
+
return res ?? {};
|
|
29170
|
+
} catch (err) {
|
|
29171
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
29172
|
+
return { message: `Command "/${name}" failed: ${msg}` };
|
|
29173
|
+
}
|
|
28108
29174
|
}
|
|
28109
29175
|
};
|
|
28110
29176
|
|
|
@@ -28538,20 +29604,28 @@ function wrapApiForCapabilityCheck(plugin, api, log, enforce = false) {
|
|
|
28538
29604
|
}
|
|
28539
29605
|
|
|
28540
29606
|
// src/execution/prompt-enhancer.ts
|
|
28541
|
-
var ENHANCER_SYSTEM_PROMPT = `You are a request refiner embedded in a coding agent. Your ONLY job is to rewrite the user's message into
|
|
29607
|
+
var ENHANCER_SYSTEM_PROMPT = `You are a request refiner embedded in a coding agent. Your ONLY job is to rewrite the user's message into clearer, unambiguous instructions that the coding agent can act on confidently.
|
|
28542
29608
|
|
|
28543
29609
|
Rules:
|
|
28544
29610
|
- Preserve the user's intent and scope EXACTLY. Do not add new requirements, features, constraints, or steps the user did not ask for. Do not remove anything they did ask for.
|
|
28545
29611
|
- Do NOT answer, solve, or perform the request. Only restate it more clearly.
|
|
28546
29612
|
- Keep all concrete details verbatim: file paths, identifiers, code, error text, numbers, names, URLs.
|
|
28547
29613
|
- Resolve obvious ambiguity by making the implied subject explicit, not by inventing specifics. If something is genuinely unspecified, leave it general rather than guessing.
|
|
28548
|
-
- Be concise: one tight instruction (a few sentences at most). No preamble, no explanation, no quotes, no markdown headers.
|
|
29614
|
+
- Be concise: one tight instruction per version (a few sentences at most). No preamble, no explanation, no quotes, no markdown headers.
|
|
28549
29615
|
- If the message is already clear and complete, return it essentially unchanged.
|
|
28550
|
-
|
|
29616
|
+
|
|
29617
|
+
You MUST output TWO versions of the refined request, separated by a line containing only "---".
|
|
29618
|
+
- First version: refined in the SAME LANGUAGE the user wrote in (if Turkish \u2192 Turkish, if Spanish \u2192 Spanish, etc.).
|
|
29619
|
+
- Second version: refined in ENGLISH (translate the intent into clear English while preserving all concrete details).
|
|
29620
|
+
|
|
29621
|
+
Output format:
|
|
29622
|
+
<refined in user's language>
|
|
29623
|
+
---
|
|
29624
|
+
<refined in English>
|
|
28551
29625
|
|
|
28552
29626
|
When earlier conversation turns are provided, they are CONTEXT ONLY. Use them to resolve references in the user's latest message \u2014 "it", "that", "the same", "the other one", "this file", "again" \u2014 so the refined instruction is self-contained. Refine ONLY the user's latest message; do not answer it, do not act on or restate earlier turns, and do not summarize the conversation.
|
|
28553
29627
|
|
|
28554
|
-
Output ONLY the
|
|
29628
|
+
Output ONLY the two versions separated by "---" \u2014 nothing else.`;
|
|
28555
29629
|
var AFFIRMATION_RE = /^(y|n|yes|no|yep|nope|ok|okay|sure|go|go ahead|continue|proceed|stop|cancel|done|next|skip|retry|again|please do|do it)\b[.! ]*$/i;
|
|
28556
29630
|
function shouldEnhance(text) {
|
|
28557
29631
|
const t2 = text.trim();
|
|
@@ -28598,12 +29672,23 @@ async function enhanceUserPrompt(opts) {
|
|
|
28598
29672
|
const signal = opts.signal ? AbortSignal.any([opts.signal, timer.signal]) : timer.signal;
|
|
28599
29673
|
try {
|
|
28600
29674
|
const res = await provider.complete(req, { signal });
|
|
28601
|
-
const
|
|
28602
|
-
if (!
|
|
29675
|
+
const raw = res.content.filter(isTextBlock).map((b) => b.text).join("\n").trim();
|
|
29676
|
+
if (!raw) {
|
|
28603
29677
|
opts.onError?.("model returned no text");
|
|
28604
29678
|
return null;
|
|
28605
29679
|
}
|
|
28606
|
-
|
|
29680
|
+
const sepIdx = raw.indexOf("\n---\n");
|
|
29681
|
+
if (sepIdx === -1) {
|
|
29682
|
+
opts.onError?.("model did not produce two versions");
|
|
29683
|
+
return { refined: raw, english: raw };
|
|
29684
|
+
}
|
|
29685
|
+
const refined = raw.slice(0, sepIdx).trim();
|
|
29686
|
+
const english = raw.slice(sepIdx + 5).trim();
|
|
29687
|
+
if (!refined || !english) {
|
|
29688
|
+
opts.onError?.("one or both versions empty");
|
|
29689
|
+
return null;
|
|
29690
|
+
}
|
|
29691
|
+
return { refined, english };
|
|
28607
29692
|
} catch (err) {
|
|
28608
29693
|
if (opts.signal?.aborted) return null;
|
|
28609
29694
|
if (timer.signal.aborted) {
|
|
@@ -28706,8 +29791,8 @@ var PhaseGraphBuilder = class _PhaseGraphBuilder {
|
|
|
28706
29791
|
return graph;
|
|
28707
29792
|
}
|
|
28708
29793
|
/**
|
|
28709
|
-
*
|
|
28710
|
-
*
|
|
29794
|
+
* Create phases from an existing TaskGraph.
|
|
29795
|
+
* Groups tasks into phases by priority and type.
|
|
28711
29796
|
*/
|
|
28712
29797
|
static fromTaskGraph(taskGraph, options) {
|
|
28713
29798
|
const tasksPerPhase = options.tasksPerPhase ?? 5;
|
|
@@ -28779,14 +29864,14 @@ var PhaseOrchestrator = class {
|
|
|
28779
29864
|
maxVerifyAttempts: opts.maxVerifyAttempts ?? 2,
|
|
28780
29865
|
autonomous: opts.autonomous ?? true,
|
|
28781
29866
|
phaseDelayMs: opts.phaseDelayMs ?? 0,
|
|
28782
|
-
stopOnFailure: opts.stopOnFailure ??
|
|
29867
|
+
stopOnFailure: opts.stopOnFailure ?? false,
|
|
28783
29868
|
events: this.events
|
|
28784
29869
|
};
|
|
28785
29870
|
}
|
|
28786
29871
|
// ─── Lifecycle ────────────────────────────────────────────────────────────
|
|
28787
29872
|
/**
|
|
28788
|
-
*
|
|
28789
|
-
*
|
|
29873
|
+
* Start the full phase flow.
|
|
29874
|
+
* In autonomous mode, starts root phases and automatically starts the next phase when they finish.
|
|
28790
29875
|
*/
|
|
28791
29876
|
async start() {
|
|
28792
29877
|
this.stopped = false;
|
|
@@ -28813,17 +29898,17 @@ var PhaseOrchestrator = class {
|
|
|
28813
29898
|
this.tickInterval = setInterval(() => this.tick(), 1e3);
|
|
28814
29899
|
}
|
|
28815
29900
|
}
|
|
28816
|
-
/**
|
|
29901
|
+
/** Wait for all pending phase merges, dependency-ordered and globally serialized. */
|
|
28817
29902
|
async drainMerges() {
|
|
28818
29903
|
await Promise.allSettled([...this.phaseMergePromise.values()]);
|
|
28819
29904
|
await this.mergeQueue.catch(() => {
|
|
28820
29905
|
});
|
|
28821
29906
|
}
|
|
28822
|
-
/**
|
|
29907
|
+
/** Pause: active phases continue, but no new phase starts. */
|
|
28823
29908
|
pause() {
|
|
28824
29909
|
this.paused = true;
|
|
28825
29910
|
}
|
|
28826
|
-
/**
|
|
29911
|
+
/** Resume: new phases may start again. */
|
|
28827
29912
|
resume() {
|
|
28828
29913
|
this.paused = false;
|
|
28829
29914
|
this.tick().catch((err) => {
|
|
@@ -28833,7 +29918,7 @@ var PhaseOrchestrator = class {
|
|
|
28833
29918
|
);
|
|
28834
29919
|
});
|
|
28835
29920
|
}
|
|
28836
|
-
/**
|
|
29921
|
+
/** Stop completely, including active phases. */
|
|
28837
29922
|
stop() {
|
|
28838
29923
|
this.stopped = true;
|
|
28839
29924
|
if (this.tickInterval) {
|
|
@@ -29031,7 +30116,10 @@ var PhaseOrchestrator = class {
|
|
|
29031
30116
|
const depPromises = phase.dependsOn.map((d) => this.phaseMergePromise.get(d)).filter((p) => Boolean(p));
|
|
29032
30117
|
const merged = (async () => {
|
|
29033
30118
|
await Promise.allSettled(depPromises);
|
|
29034
|
-
this.mergeQueue = this.mergeQueue.then(() => this.mergeOne(phase, handle))
|
|
30119
|
+
this.mergeQueue = this.mergeQueue.then(() => this.mergeOne(phase, handle)).catch((err) => {
|
|
30120
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
30121
|
+
console.error(`[PhaseOrchestrator] mergeOne failed for phase ${phase.id}: ${msg}`);
|
|
30122
|
+
});
|
|
29035
30123
|
await this.mergeQueue;
|
|
29036
30124
|
})();
|
|
29037
30125
|
this.phaseMergePromise.set(phase.id, merged);
|
|
@@ -29223,7 +30311,7 @@ var PhaseOrchestrator = class {
|
|
|
29223
30311
|
if (phase.status !== "pending") continue;
|
|
29224
30312
|
const depsDone = phase.dependsOn.every((depId) => {
|
|
29225
30313
|
const dep = this.graph.phases.get(depId);
|
|
29226
|
-
return dep?.status === "completed" || dep?.status === "skipped";
|
|
30314
|
+
return dep?.status === "completed" || dep?.status === "skipped" || dep?.status === "failed";
|
|
29227
30315
|
});
|
|
29228
30316
|
if (depsDone || phase.parallelizable) {
|
|
29229
30317
|
ready.push(phase);
|
|
@@ -29434,7 +30522,9 @@ var AutoPhaseRunner = class {
|
|
|
29434
30522
|
if (failedPhase) {
|
|
29435
30523
|
this.opts.onFail?.(this.graph, failedPhase, new Error(p.error));
|
|
29436
30524
|
}
|
|
29437
|
-
this.
|
|
30525
|
+
if (this.opts.stopOnFailure) {
|
|
30526
|
+
this.cleanup();
|
|
30527
|
+
}
|
|
29438
30528
|
}
|
|
29439
30529
|
};
|
|
29440
30530
|
/** Stores the unsubscribe function returned by EventBus.on() */
|
|
@@ -29488,10 +30578,32 @@ var AutoPhaseRunner = class {
|
|
|
29488
30578
|
}, 2e3);
|
|
29489
30579
|
}
|
|
29490
30580
|
this.maxRunTimer = setTimeout(
|
|
29491
|
-
() =>
|
|
29492
|
-
|
|
30581
|
+
() => {
|
|
30582
|
+
this.opts.onProgress?.({
|
|
30583
|
+
totalPhases: 0,
|
|
30584
|
+
pending: 0,
|
|
30585
|
+
ready: 0,
|
|
30586
|
+
running: 0,
|
|
30587
|
+
paused: 0,
|
|
30588
|
+
completed: 0,
|
|
30589
|
+
failed: 0,
|
|
30590
|
+
skipped: 0,
|
|
30591
|
+
percentComplete: 0,
|
|
30592
|
+
totalTasks: 0,
|
|
30593
|
+
completedTasks: 0,
|
|
30594
|
+
failedTasks: 0,
|
|
30595
|
+
estimatedHours: 0,
|
|
30596
|
+
actualHours: 0
|
|
30597
|
+
});
|
|
30598
|
+
this.stop();
|
|
30599
|
+
},
|
|
30600
|
+
this.opts.maxRunDurationMs ?? 7 * 24 * 60 * 6e4
|
|
29493
30601
|
);
|
|
29494
|
-
this.
|
|
30602
|
+
if (this.opts.maxRunDurationMs !== void 0 && this.opts.maxRunDurationMs <= 0) {
|
|
30603
|
+
clearTimeout(this.maxRunTimer);
|
|
30604
|
+
this.maxRunTimer = null;
|
|
30605
|
+
}
|
|
30606
|
+
this.maxRunTimer?.unref?.();
|
|
29495
30607
|
if (this.opts.events) {
|
|
29496
30608
|
const events = this.opts.events;
|
|
29497
30609
|
const onUntyped = events.on;
|
|
@@ -29583,14 +30695,14 @@ var AutoPhasePlanner = class {
|
|
|
29583
30695
|
this.opts = opts;
|
|
29584
30696
|
}
|
|
29585
30697
|
opts;
|
|
29586
|
-
/**
|
|
30698
|
+
/** Convert the goal into a phase-and-todo plan. */
|
|
29587
30699
|
async plan() {
|
|
29588
30700
|
const prompt = this.buildPrompt();
|
|
29589
30701
|
const raw = await this.opts.runOnce(prompt);
|
|
29590
30702
|
const phases = this.parse(raw);
|
|
29591
30703
|
return { phases, raw, parseFailed: phases.length === 0 };
|
|
29592
30704
|
}
|
|
29593
|
-
/**
|
|
30705
|
+
/** Instruction prompt for the plan the model should produce. */
|
|
29594
30706
|
buildPrompt() {
|
|
29595
30707
|
const minP = this.opts.minPhases ?? 3;
|
|
29596
30708
|
const maxP = this.opts.maxPhases ?? 8;
|
|
@@ -29638,7 +30750,7 @@ ${ctx}
|
|
|
29638
30750
|
"```"
|
|
29639
30751
|
].filter((l) => l !== "").join("\n");
|
|
29640
30752
|
}
|
|
29641
|
-
/**
|
|
30753
|
+
/** Extract JSON from raw output, validate it, and convert it to PhaseTemplate[]. */
|
|
29642
30754
|
parse(raw) {
|
|
29643
30755
|
const json = extractJSONArray(raw);
|
|
29644
30756
|
if (!json) return [];
|
|
@@ -30378,7 +31490,8 @@ ${check.stderr}`);
|
|
|
30378
31490
|
const child = spawn(this.gitBin, args, {
|
|
30379
31491
|
cwd,
|
|
30380
31492
|
env: buildChildEnv(),
|
|
30381
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
31493
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
31494
|
+
signal: AbortSignal.timeout(3e4)
|
|
30382
31495
|
});
|
|
30383
31496
|
child.stdout?.on("data", (c) => {
|
|
30384
31497
|
stdout += c.toString();
|
|
@@ -30746,12 +31859,6 @@ var ReplayProviderRunner = class {
|
|
|
30746
31859
|
};
|
|
30747
31860
|
|
|
30748
31861
|
// src/plugins/prompts-plugin.ts
|
|
30749
|
-
function expectDefined26(value) {
|
|
30750
|
-
if (value === null || value === void 0) {
|
|
30751
|
-
throw new Error("Expected value to be defined");
|
|
30752
|
-
}
|
|
30753
|
-
return value;
|
|
30754
|
-
}
|
|
30755
31862
|
function createPromptsPlugin(opts) {
|
|
30756
31863
|
let store = null;
|
|
30757
31864
|
return {
|
|
@@ -30805,7 +31912,7 @@ ${lines.join("\n")}
|
|
|
30805
31912
|
if (!restJoined) return { message: "Usage: /prompts view <title>" };
|
|
30806
31913
|
const matches = await store.find(restJoined);
|
|
30807
31914
|
if (matches.length === 0) return { message: `No prompt matching "${restJoined}".` };
|
|
30808
|
-
const entry = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ??
|
|
31915
|
+
const entry = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? expectDefined(matches[0]);
|
|
30809
31916
|
const tags = entry.tags.length > 0 ? ` [${entry.tags.join(", ")}]` : "";
|
|
30810
31917
|
return {
|
|
30811
31918
|
message: `# ${entry.title}${tags}
|
|
@@ -30828,7 +31935,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
30828
31935
|
if (!restJoined) return { message: "Usage: /prompts delete <title>" };
|
|
30829
31936
|
const matches = await store.find(restJoined);
|
|
30830
31937
|
if (matches.length === 0) return { message: `No prompt matching "${restJoined}".` };
|
|
30831
|
-
const exact = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ??
|
|
31938
|
+
const exact = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? expectDefined(matches[0]);
|
|
30832
31939
|
const deleted = await store.delete(exact.id);
|
|
30833
31940
|
return { message: deleted ? `Deleted "${exact.title}".` : "Delete failed." };
|
|
30834
31941
|
}
|
|
@@ -30838,7 +31945,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
30838
31945
|
if (!parsed.title) return { message: 'Usage: /prompts edit "title" "new content"' };
|
|
30839
31946
|
const matches = await store.find(parsed.title);
|
|
30840
31947
|
if (matches.length === 0) return { message: `No prompt matching "${parsed.title}".` };
|
|
30841
|
-
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ??
|
|
31948
|
+
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ?? expectDefined(matches[0]);
|
|
30842
31949
|
exact.content = parsed.content;
|
|
30843
31950
|
exact.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30844
31951
|
await store.save(exact);
|
|
@@ -30850,7 +31957,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
30850
31957
|
if (!parsed.title) return { message: 'Usage: /prompts extend "title" <instructions>' };
|
|
30851
31958
|
const matches = await store.find(parsed.title);
|
|
30852
31959
|
if (matches.length === 0) return { message: `No prompt matching "${parsed.title}".` };
|
|
30853
|
-
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ??
|
|
31960
|
+
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ?? expectDefined(matches[0]);
|
|
30854
31961
|
const prov = ctx.provider;
|
|
30855
31962
|
if (!prov?.complete) return { message: "LLM not available. Configure a provider first." };
|
|
30856
31963
|
const enhanced = await prov.complete(ctx.model, [
|
|
@@ -30885,9 +31992,9 @@ function parseTitleContent(args) {
|
|
|
30885
31992
|
const trimmed = args.trim();
|
|
30886
31993
|
if (!trimmed) return { title: "", content: "" };
|
|
30887
31994
|
const doubleMatch = /^"([^"]+)"\s+"([^"]+)"$/.exec(trimmed) || /^'([^']+)'\s+'([^']+)'$/.exec(trimmed);
|
|
30888
|
-
if (doubleMatch) return { title:
|
|
31995
|
+
if (doubleMatch) return { title: expectDefined(doubleMatch[1]), content: expectDefined(doubleMatch[2]) };
|
|
30889
31996
|
const singleMatch = /^'([^']+)'\s+(.+)$/.exec(trimmed);
|
|
30890
|
-
if (singleMatch) return { title:
|
|
31997
|
+
if (singleMatch) return { title: expectDefined(singleMatch[1]), content: expectDefined(singleMatch[2]) };
|
|
30891
31998
|
const firstSpace = trimmed.indexOf(" ");
|
|
30892
31999
|
if (firstSpace === -1) return { title: trimmed, content: "" };
|
|
30893
32000
|
return { title: trimmed.slice(0, firstSpace), content: trimmed.slice(firstSpace + 1) };
|
|
@@ -30898,12 +32005,6 @@ function dim2(s) {
|
|
|
30898
32005
|
|
|
30899
32006
|
// src/plugins/sync-plugin.ts
|
|
30900
32007
|
init_atomic_write();
|
|
30901
|
-
function expectDefined27(value) {
|
|
30902
|
-
if (value === null || value === void 0) {
|
|
30903
|
-
throw new Error("Expected value to be defined");
|
|
30904
|
-
}
|
|
30905
|
-
return value;
|
|
30906
|
-
}
|
|
30907
32008
|
function createSyncPlugin(opts) {
|
|
30908
32009
|
let cloud = null;
|
|
30909
32010
|
let configStore;
|
|
@@ -30977,7 +32078,7 @@ function buildSyncCommand(cloud, configStore, vault, syncConfigPath) {
|
|
|
30977
32078
|
if (!repo || !repo.includes("/")) {
|
|
30978
32079
|
return { message: 'Invalid repo format. Expected "owner/repo".' };
|
|
30979
32080
|
}
|
|
30980
|
-
const storedToken = vault ? vault.encrypt(
|
|
32081
|
+
const storedToken = vault ? vault.encrypt(expectDefined(token)) : expectDefined(token);
|
|
30981
32082
|
const syncConfig = {
|
|
30982
32083
|
enabled: true,
|
|
30983
32084
|
repo,
|
|
@@ -31118,7 +32219,7 @@ function createGitPlugin() {
|
|
|
31118
32219
|
async function runGit(args, cwd) {
|
|
31119
32220
|
try {
|
|
31120
32221
|
return await new Promise((resolve13, reject) => {
|
|
31121
|
-
const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
32222
|
+
const child = spawn("git", args, { cwd, stdio: ["ignore", "pipe", "pipe"], signal: AbortSignal.timeout(3e4) });
|
|
31122
32223
|
let stdout = "";
|
|
31123
32224
|
let stderr = "";
|
|
31124
32225
|
child.stdout?.on("data", (d) => {
|
|
@@ -31843,6 +32944,6 @@ ${formatPlan(updated)}`
|
|
|
31843
32944
|
};
|
|
31844
32945
|
}
|
|
31845
32946
|
|
|
31846
|
-
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob,
|
|
32947
|
+
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousRunner, BUG_HUNTER_AGENT, BrainDecisionQueue, BudgetExceededError, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, CheckpointManager, CloudSync, CollaborationBus, ConfigError, ConfigMigrationError, Container, Context, ConversationState, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GraphMemoryBackend, HookRegistry, HookRunner, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, LAYER_1_IDENTITY, LLMSelector, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MEMORY_TYPE_LABELS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, SubagentBudget, TOKENS, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolError, ToolExecutor, ToolRegistry, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyRosterBudget, asBlocks, asText, assertSafePath, atomicWrite, attachAutoExtend, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildGoalPreamble, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildRecoveryStrategies, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createMcpControlTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createSyncPlugin, createToolOutputSerializer, decryptConfigSecrets, defaultGitignoreUpdater, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, deriveTodosFromPlanItem, detectNewlineStyle, dispatchAgent, downloadGitHubTarball, emptyGoal, emptyPlan, emptyTaskFile, encryptConfigSecrets, enhanceUserPrompt, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expectDefined, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getPlanTemplate, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hashRequest, hookMatcherMatches, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isPluginError, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, makeAgentSubagentRunner, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeRollUpTool, makeSpawnTool, makeTerminateTool, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, normalizeToLf, normalizedEqual, onResize, parseContinueDirective, parseEntries, parseProgressFromText, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, recordProgress, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setProgress, setRawMode, shouldEnhance, slackServer, sleep, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, withFileLock, wrapAsState, writeErr, writeOut, zaiVisionServer };
|
|
31847
32948
|
//# sourceMappingURL=index.js.map
|
|
31848
32949
|
//# sourceMappingURL=index.js.map
|