@wrongstack/core 0.73.1 → 0.82.6
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-C0Ze7Ldm.d.ts → agent-bridge-C9P_HPez.d.ts} +2 -2
- package/dist/{agent-subagent-runner-BmITbs1Q.d.ts → agent-subagent-runner-2Aq0jOSj.d.ts} +107 -102
- package/dist/{compactor-D_ExJajC.d.ts → compactor-CJq7LQev.d.ts} +3 -3
- package/dist/{config-Dy0CK_o6.d.ts → config-_DZ7dN-T.d.ts} +77 -75
- package/dist/{context-y87Jc5ei.d.ts → context-ToHAp4-U.d.ts} +119 -90
- package/dist/coordination/index.d.ts +16 -16
- package/dist/coordination/index.js +382 -43
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +31 -31
- package/dist/defaults/index.js +524 -110
- package/dist/defaults/index.js.map +1 -1
- package/dist/{director-state-BmYi3DGA.d.ts → director-state-CgIc30qi.d.ts} +19 -19
- package/dist/{events-BBAlxBuw.d.ts → events-DnRqXaZ3.d.ts} +77 -39
- package/dist/execution/index.d.ts +53 -53
- package/dist/execution/index.js +67 -23
- package/dist/execution/index.js.map +1 -1
- package/dist/extension/index.d.ts +9 -9
- package/dist/extension/index.js +8 -1
- package/dist/extension/index.js.map +1 -1
- package/dist/{goal-store-C7jcumEh.d.ts → goal-store-DvWLNu52.d.ts} +4 -4
- package/dist/{index-yQbZ2NQx.d.ts → index-BNOLadHw.d.ts} +28 -28
- package/dist/{index-BN6i2Nfg.d.ts → index-N0_c4bHQ.d.ts} +45 -45
- package/dist/index.d.ts +233 -160
- package/dist/index.js +825 -160
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +9 -9
- package/dist/infrastructure/index.js +29 -7
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +14 -14
- package/dist/kernel/index.js +7 -0
- package/dist/kernel/index.js.map +1 -1
- package/dist/logger-B72yyPc6.d.ts +12 -0
- package/dist/{logger-bOzkF5LL.d.ts → logger-C_27pj9i.d.ts} +12 -4
- package/dist/{mcp-servers-T0O6UN_w.d.ts → mcp-servers-Dck3T85_.d.ts} +20 -20
- package/dist/{mode-BO4SEUIv.d.ts → mode-CHo2XtHs.d.ts} +4 -4
- package/dist/models/index.d.ts +10 -10
- package/dist/models/index.js +8 -2
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-BcYJDKLm.d.ts → models-registry-Be3osGt5.d.ts} +28 -28
- package/dist/{models-registry-Cuq1C8V9.d.ts → models-registry-Boz639EI.d.ts} +12 -12
- package/dist/{multi-agent-coordinator-BSBbZt0e.d.ts → multi-agent-coordinator-DllpCVkF.d.ts} +12 -12
- package/dist/{null-fleet-bus-BCIRT_nV.d.ts → null-fleet-bus-BY0AN-sr.d.ts} +129 -120
- package/dist/observability/index.d.ts +41 -41
- package/dist/observability/index.js.map +1 -1
- package/dist/{observability-BhnVLBLS.d.ts → observability-CoSNZdhX.d.ts} +4 -4
- package/dist/{parallel-eternal-engine-CjAYGaCw.d.ts → parallel-eternal-engine-D402RASp.d.ts} +49 -49
- package/dist/{path-resolver-BnqXa9Ze.d.ts → path-resolver-UPFTsDyD.d.ts} +6 -6
- package/dist/{permission-V5BLOrY6.d.ts → permission-14CChMmO.d.ts} +10 -8
- package/dist/{permission-policy-CBVx-d-8.d.ts → permission-policy-gW5htOo1.d.ts} +7 -7
- package/dist/{plan-templates-DBgrTGPu.d.ts → plan-templates-DRvPgkfZ.d.ts} +70 -32
- package/dist/{provider-runner-n3KkHT_w.d.ts → provider-runner-COAJM8tC.d.ts} +6 -6
- package/dist/{retry-policy-CG3qvH_e.d.ts → retry-policy-DSu6O6rD.d.ts} +4 -4
- package/dist/sdd/index.d.ts +47 -47
- package/dist/sdd/index.js +47 -22
- package/dist/sdd/index.js.map +1 -1
- package/dist/security/index.d.ts +6 -6
- package/dist/security/index.js +7 -1
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-RvBR_YRW.d.ts → selector-11-fm95U.d.ts} +2 -2
- package/dist/{session-event-bridge-CDHxcmQU.d.ts → session-event-bridge-D0u-x576.d.ts} +7 -7
- package/dist/{session-reader-BIpwM60D.d.ts → session-reader-BQU-toaN.d.ts} +23 -23
- package/dist/{skill-CxuWrsKK.d.ts → skill-BJeF2DwY.d.ts} +1 -1
- package/dist/skills/index.d.ts +9 -9
- package/dist/skills/index.js +15 -3
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/index.d.ts +15 -15
- package/dist/storage/index.js +398 -80
- package/dist/storage/index.js.map +1 -1
- package/dist/{system-prompt-CA11g6Jo.d.ts → system-prompt-C0rLCeyn.d.ts} +16 -11
- package/dist/{task-graph-D1YQbpxF.d.ts → task-graph-CikNdRTG.d.ts} +22 -22
- package/dist/types/index.d.ts +25 -25
- package/dist/types/index.js +61 -12
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +46 -45
- package/dist/utils/index.js +64 -13
- package/dist/utils/index.js.map +1 -1
- package/dist/{wstack-paths-eMXnY1_X.d.ts → wstack-paths-BQMvEllz.d.ts} +10 -3
- package/package.json +1 -1
- package/dist/logger-DDd5C--Z.d.ts +0 -12
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { readFile, readdir, stat, mkdir } from 'fs/promises';
|
|
|
5
5
|
import * as path6 from 'path';
|
|
6
6
|
import { join, extname, relative, isAbsolute, resolve, sep } from 'path';
|
|
7
7
|
import * as fs2 from 'fs';
|
|
8
|
-
import * as
|
|
8
|
+
import * as os7 from 'os';
|
|
9
9
|
import { execFile, spawn } from 'child_process';
|
|
10
10
|
import { promisify } from 'util';
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
@@ -419,6 +419,13 @@ var Container = class {
|
|
|
419
419
|
has(token) {
|
|
420
420
|
return this.entries.has(token);
|
|
421
421
|
}
|
|
422
|
+
/**
|
|
423
|
+
* Resolve a token if it is bound, otherwise return undefined.
|
|
424
|
+
* Unlike resolve(), this does not throw if the token is unbound.
|
|
425
|
+
*/
|
|
426
|
+
safeResolve(token) {
|
|
427
|
+
return this.has(token) ? this.resolve(token) : void 0;
|
|
428
|
+
}
|
|
422
429
|
ownerOf(token) {
|
|
423
430
|
return this.entries.get(token)?.owner;
|
|
424
431
|
}
|
|
@@ -1338,9 +1345,20 @@ function setRawMode(input, mode) {
|
|
|
1338
1345
|
input.setRawMode(mode);
|
|
1339
1346
|
return true;
|
|
1340
1347
|
}
|
|
1348
|
+
var activeOutputGuard = null;
|
|
1349
|
+
function setOutputLineGuard(guard) {
|
|
1350
|
+
activeOutputGuard = guard;
|
|
1351
|
+
}
|
|
1341
1352
|
function writeTo(s, stream) {
|
|
1342
1353
|
if (!stream || typeof stream.write !== "function") return false;
|
|
1354
|
+
const guard = activeOutputGuard;
|
|
1355
|
+
if (!guard) {
|
|
1356
|
+
stream.write(s);
|
|
1357
|
+
return true;
|
|
1358
|
+
}
|
|
1359
|
+
guard.suspend();
|
|
1343
1360
|
stream.write(s);
|
|
1361
|
+
guard.resume();
|
|
1344
1362
|
return true;
|
|
1345
1363
|
}
|
|
1346
1364
|
function writeOut(s, stream = process.stdout) {
|
|
@@ -1404,11 +1422,13 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
1404
1422
|
file;
|
|
1405
1423
|
bindings;
|
|
1406
1424
|
pretty;
|
|
1425
|
+
stderr;
|
|
1407
1426
|
constructor(opts = {}) {
|
|
1408
1427
|
this.level = opts.level ?? process.env.WRONGSTACK_LOG_LEVEL ?? "info";
|
|
1409
1428
|
this.file = opts.file;
|
|
1410
1429
|
this.bindings = opts.bindings ?? {};
|
|
1411
1430
|
this.pretty = opts.pretty ?? true;
|
|
1431
|
+
this.stderr = opts.stderr !== false;
|
|
1412
1432
|
if (this.file) {
|
|
1413
1433
|
try {
|
|
1414
1434
|
fs2.mkdirSync(path6.dirname(this.file), { recursive: true });
|
|
@@ -1436,6 +1456,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
1436
1456
|
level: this.level,
|
|
1437
1457
|
file: this.file,
|
|
1438
1458
|
pretty: this.pretty,
|
|
1459
|
+
stderr: this.stderr,
|
|
1439
1460
|
bindings: { ...this.bindings, ...bindings }
|
|
1440
1461
|
});
|
|
1441
1462
|
}
|
|
@@ -1455,6 +1476,7 @@ var DefaultLogger = class _DefaultLogger {
|
|
|
1455
1476
|
} catch {
|
|
1456
1477
|
}
|
|
1457
1478
|
}
|
|
1479
|
+
if (!this.stderr) return;
|
|
1458
1480
|
if (r <= LEVEL_RANK.warn || this.level === "debug" || this.level === "trace") {
|
|
1459
1481
|
const head = `${color.dim(ts)} ${COLORS[level](level.toUpperCase().padEnd(5))} ${msg}`;
|
|
1460
1482
|
if (ctx !== void 0) {
|
|
@@ -1511,7 +1533,7 @@ var DefaultTokenCounter = class {
|
|
|
1511
1533
|
} else if (this.registry && this.providerId && model) {
|
|
1512
1534
|
if (this.priceCache.size >= PRICE_CACHE_MAX_SIZE) {
|
|
1513
1535
|
const keys = [...this.priceCache.keys()];
|
|
1514
|
-
this.priceCache.delete(keys[0]);
|
|
1536
|
+
this.priceCache.delete(keys[0] ?? "");
|
|
1515
1537
|
}
|
|
1516
1538
|
void this.registry.getModel(this.providerId, model).then((m) => {
|
|
1517
1539
|
if (m) {
|
|
@@ -1536,7 +1558,7 @@ var DefaultTokenCounter = class {
|
|
|
1536
1558
|
const price = priceFromModel(resolved);
|
|
1537
1559
|
if (this.priceCache.size >= PRICE_CACHE_MAX_SIZE) {
|
|
1538
1560
|
const keys = [...this.priceCache.keys()];
|
|
1539
|
-
this.priceCache.delete(keys[0]);
|
|
1561
|
+
this.priceCache.delete(keys[0] ?? "");
|
|
1540
1562
|
}
|
|
1541
1563
|
this.priceCache.set(resolved.modelId, price);
|
|
1542
1564
|
this.applyPrice(usage, price);
|
|
@@ -1604,6 +1626,12 @@ function round4(n) {
|
|
|
1604
1626
|
}
|
|
1605
1627
|
|
|
1606
1628
|
// src/utils/token-estimate.ts
|
|
1629
|
+
function expectDefined(value) {
|
|
1630
|
+
if (value === null || value === void 0) {
|
|
1631
|
+
throw new Error("Expected value to be defined");
|
|
1632
|
+
}
|
|
1633
|
+
return value;
|
|
1634
|
+
}
|
|
1607
1635
|
var RoughTokenEstimate = (text, charsPerToken = 3.5) => Math.max(1, Math.ceil(text.length / charsPerToken));
|
|
1608
1636
|
var _cal = {
|
|
1609
1637
|
ratio: 1,
|
|
@@ -1624,7 +1652,7 @@ function getCachedEstimate(key, compute) {
|
|
|
1624
1652
|
if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
|
|
1625
1653
|
const keys = [...ESTIMATE_CACHE.keys()];
|
|
1626
1654
|
for (let i = 0; i < Math.floor(ESTIMATE_CACHE_MAX_SIZE / 4); i++) {
|
|
1627
|
-
ESTIMATE_CACHE.delete(keys[i]);
|
|
1655
|
+
ESTIMATE_CACHE.delete(expectDefined(keys[i]));
|
|
1628
1656
|
}
|
|
1629
1657
|
}
|
|
1630
1658
|
const estimate = compute();
|
|
@@ -1737,6 +1765,12 @@ function resetCalibration() {
|
|
|
1737
1765
|
}
|
|
1738
1766
|
|
|
1739
1767
|
// src/utils/message-invariants.ts
|
|
1768
|
+
function expectDefined2(value) {
|
|
1769
|
+
if (value === null || value === void 0) {
|
|
1770
|
+
throw new Error("Expected value to be defined");
|
|
1771
|
+
}
|
|
1772
|
+
return value;
|
|
1773
|
+
}
|
|
1740
1774
|
function repairToolUseAdjacency(messages) {
|
|
1741
1775
|
const removedToolUses = [];
|
|
1742
1776
|
const removedToolResults = [];
|
|
@@ -1744,7 +1778,7 @@ function repairToolUseAdjacency(messages) {
|
|
|
1744
1778
|
let changed = false;
|
|
1745
1779
|
const out = [];
|
|
1746
1780
|
for (let i = 0; i < messages.length; i++) {
|
|
1747
|
-
const original = messages[i];
|
|
1781
|
+
const original = expectDefined2(messages[i]);
|
|
1748
1782
|
let msg = original;
|
|
1749
1783
|
if (hasToolUse(msg)) {
|
|
1750
1784
|
const nextIds = toolResultIds(messages[i + 1]);
|
|
@@ -2000,7 +2034,11 @@ var PROJECT_MARKERS = [
|
|
|
2000
2034
|
"go.mod",
|
|
2001
2035
|
"Cargo.toml",
|
|
2002
2036
|
"pyproject.toml",
|
|
2003
|
-
|
|
2037
|
+
// Use AGENTS.md, not the bare .wrongstack directory. A bare .wrongstack/
|
|
2038
|
+
// directory can be the global config directory (~/.wrongstack), which is
|
|
2039
|
+
// NOT a project marker. Only .wrongstack/AGENTS.md signals a real
|
|
2040
|
+
// WrongStack project.
|
|
2041
|
+
".wrongstack/AGENTS.md"
|
|
2004
2042
|
];
|
|
2005
2043
|
var DefaultPathResolver = class {
|
|
2006
2044
|
projectRoot;
|
|
@@ -2012,7 +2050,12 @@ var DefaultPathResolver = class {
|
|
|
2012
2050
|
detectProjectRoot(start) {
|
|
2013
2051
|
let dir = path6.resolve(start);
|
|
2014
2052
|
const root = path6.parse(dir).root;
|
|
2053
|
+
const home = path6.resolve(os7.homedir());
|
|
2054
|
+
const startPath = path6.resolve(start);
|
|
2015
2055
|
while (dir !== root) {
|
|
2056
|
+
if (dir === home && dir !== startPath) {
|
|
2057
|
+
break;
|
|
2058
|
+
}
|
|
2016
2059
|
for (const marker of PROJECT_MARKERS) {
|
|
2017
2060
|
try {
|
|
2018
2061
|
fs2.accessSync(path6.join(dir, marker));
|
|
@@ -2024,7 +2067,7 @@ var DefaultPathResolver = class {
|
|
|
2024
2067
|
if (parent === dir) break;
|
|
2025
2068
|
dir = parent;
|
|
2026
2069
|
}
|
|
2027
|
-
return
|
|
2070
|
+
return startPath;
|
|
2028
2071
|
}
|
|
2029
2072
|
resolve(input) {
|
|
2030
2073
|
const abs = path6.isAbsolute(input) ? input : path6.resolve(this.cwd, input);
|
|
@@ -2893,6 +2936,12 @@ Remember: your job is to make the user a better developer, not just to complete
|
|
|
2893
2936
|
];
|
|
2894
2937
|
|
|
2895
2938
|
// src/types/context-window.ts
|
|
2939
|
+
function expectDefined3(value) {
|
|
2940
|
+
if (value === null || value === void 0) {
|
|
2941
|
+
throw new Error("Expected value to be defined");
|
|
2942
|
+
}
|
|
2943
|
+
return value;
|
|
2944
|
+
}
|
|
2896
2945
|
var DEFAULT_CONTEXT_WINDOW_MODE_ID = "balanced";
|
|
2897
2946
|
var CONTEXT_WINDOW_MODES = Object.freeze([
|
|
2898
2947
|
{
|
|
@@ -2949,7 +2998,7 @@ function isContextWindowModeId(id) {
|
|
|
2949
2998
|
}
|
|
2950
2999
|
function resolveContextWindowPolicy(config = {}, overrideMode) {
|
|
2951
3000
|
const requested = overrideMode ?? config.mode ?? DEFAULT_CONTEXT_WINDOW_MODE_ID;
|
|
2952
|
-
const mode = getContextWindowMode(requested) ?? getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID);
|
|
3001
|
+
const mode = getContextWindowMode(requested) ?? expectDefined3(getContextWindowMode(DEFAULT_CONTEXT_WINDOW_MODE_ID));
|
|
2953
3002
|
if (mode.id !== DEFAULT_CONTEXT_WINDOW_MODE_ID) {
|
|
2954
3003
|
return mode;
|
|
2955
3004
|
}
|
|
@@ -3000,7 +3049,7 @@ var InMemoryBridgeTransport = class {
|
|
|
3000
3049
|
}
|
|
3001
3050
|
subscribe(agentId, handler) {
|
|
3002
3051
|
if (!this.subs.has(agentId)) this.subs.set(agentId, /* @__PURE__ */ new Set());
|
|
3003
|
-
this.subs.get(agentId)
|
|
3052
|
+
this.subs.get(agentId)?.add(handler);
|
|
3004
3053
|
return () => this.subs.get(agentId)?.delete(handler);
|
|
3005
3054
|
}
|
|
3006
3055
|
close(agentId) {
|
|
@@ -3429,6 +3478,12 @@ function sizeSignals(toolName, content) {
|
|
|
3429
3478
|
}
|
|
3430
3479
|
|
|
3431
3480
|
// src/execution/tool-executor.ts
|
|
3481
|
+
function expectDefined4(value) {
|
|
3482
|
+
if (value === null || value === void 0) {
|
|
3483
|
+
throw new Error("Expected value to be defined");
|
|
3484
|
+
}
|
|
3485
|
+
return value;
|
|
3486
|
+
}
|
|
3432
3487
|
var ToolExecutor = class {
|
|
3433
3488
|
constructor(registry, opts) {
|
|
3434
3489
|
this.registry = registry;
|
|
@@ -3717,6 +3772,9 @@ ${post.additionalContext}` };
|
|
|
3717
3772
|
async runStreamedTool(tool, input, ctx, signal, toolUseId) {
|
|
3718
3773
|
let finalOutput;
|
|
3719
3774
|
let sawFinal = false;
|
|
3775
|
+
if (!tool.executeStream) {
|
|
3776
|
+
throw new Error(`Tool "${tool.name}" does not support streaming execution`);
|
|
3777
|
+
}
|
|
3720
3778
|
const stream = tool.executeStream(input, ctx, { signal });
|
|
3721
3779
|
for await (const ev of stream) {
|
|
3722
3780
|
if (ev.type === "final") {
|
|
@@ -3821,7 +3879,7 @@ function hasMalformedArguments(input) {
|
|
|
3821
3879
|
function extractMalformedRaw(input) {
|
|
3822
3880
|
if (!hasMalformedArguments(input)) return void 0;
|
|
3823
3881
|
const obj = input;
|
|
3824
|
-
const value = obj[Object.keys(obj)[0]];
|
|
3882
|
+
const value = obj[expectDefined4(Object.keys(obj)[0])];
|
|
3825
3883
|
if (value === void 0 || value === null) return void 0;
|
|
3826
3884
|
if (typeof value === "string") return value;
|
|
3827
3885
|
try {
|
|
@@ -3868,6 +3926,12 @@ function compileUserRegex(pattern, flags) {
|
|
|
3868
3926
|
}
|
|
3869
3927
|
|
|
3870
3928
|
// src/storage/session-reader.ts
|
|
3929
|
+
function expectDefined5(value) {
|
|
3930
|
+
if (value === null || value === void 0) {
|
|
3931
|
+
throw new Error("Expected value to be defined");
|
|
3932
|
+
}
|
|
3933
|
+
return value;
|
|
3934
|
+
}
|
|
3871
3935
|
var DefaultSessionReader = class {
|
|
3872
3936
|
store;
|
|
3873
3937
|
constructor(opts) {
|
|
@@ -3929,7 +3993,7 @@ var DefaultSessionReader = class {
|
|
|
3929
3993
|
continue;
|
|
3930
3994
|
}
|
|
3931
3995
|
for (let i = 0; i < data.events.length; i++) {
|
|
3932
|
-
const ev = data.events[i];
|
|
3996
|
+
const ev = expectDefined5(data.events[i]);
|
|
3933
3997
|
if (allowedTypes && !allowedTypes.has(ev.type)) continue;
|
|
3934
3998
|
const text = eventText(ev);
|
|
3935
3999
|
if (text === null) continue;
|
|
@@ -4197,7 +4261,7 @@ function escapeControlCharsInStrings(s) {
|
|
|
4197
4261
|
let inString = false;
|
|
4198
4262
|
let out = "";
|
|
4199
4263
|
for (let i = 0; i < s.length; i++) {
|
|
4200
|
-
const c = s
|
|
4264
|
+
const c = s.charAt(i);
|
|
4201
4265
|
if (c === '"' && (i === 0 || s[i - 1] !== "\\")) {
|
|
4202
4266
|
inString = !inString;
|
|
4203
4267
|
out += c;
|
|
@@ -4235,12 +4299,12 @@ function stripSingleLineComments(s) {
|
|
|
4235
4299
|
const chars = [];
|
|
4236
4300
|
let i = 0;
|
|
4237
4301
|
while (i < s.length) {
|
|
4238
|
-
const c = s
|
|
4239
|
-
if (c === '"' && (i === 0 || s
|
|
4302
|
+
const c = s.charAt(i);
|
|
4303
|
+
if (c === '"' && (i === 0 || s.charAt(i - 1) !== "\\")) {
|
|
4240
4304
|
inString = !inString;
|
|
4241
4305
|
chars.push(c);
|
|
4242
|
-
} else if (c === "/" && s
|
|
4243
|
-
while (i < s.length && s
|
|
4306
|
+
} else if (c === "/" && s.charAt(i + 1) === "/" && !inString) {
|
|
4307
|
+
while (i < s.length && s.charAt(i) !== "\n") i++;
|
|
4244
4308
|
} else {
|
|
4245
4309
|
chars.push(c);
|
|
4246
4310
|
}
|
|
@@ -4297,6 +4361,12 @@ function formatTodosList(todos) {
|
|
|
4297
4361
|
}
|
|
4298
4362
|
|
|
4299
4363
|
// src/utils/glob-match.ts
|
|
4364
|
+
function expectDefined6(value) {
|
|
4365
|
+
if (value === null || value === void 0) {
|
|
4366
|
+
throw new Error("Expected value to be defined");
|
|
4367
|
+
}
|
|
4368
|
+
return value;
|
|
4369
|
+
}
|
|
4300
4370
|
function escapeRegex(s) {
|
|
4301
4371
|
return s.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
4302
4372
|
}
|
|
@@ -4308,7 +4378,7 @@ function getCachedGlob(pattern) {
|
|
|
4308
4378
|
if (COMPILED_GLOB_CACHE.size >= CACHE_MAX_SIZE) {
|
|
4309
4379
|
const keys = [...COMPILED_GLOB_CACHE.keys()];
|
|
4310
4380
|
for (let i = 0; i < Math.floor(CACHE_MAX_SIZE / 4); i++) {
|
|
4311
|
-
COMPILED_GLOB_CACHE.delete(keys[i]);
|
|
4381
|
+
COMPILED_GLOB_CACHE.delete(expectDefined6(keys[i]));
|
|
4312
4382
|
}
|
|
4313
4383
|
}
|
|
4314
4384
|
const re = compileGlob(pattern);
|
|
@@ -4526,11 +4596,20 @@ function unifiedDiff(oldText, newText, opts = {}) {
|
|
|
4526
4596
|
function projectHash(absRoot) {
|
|
4527
4597
|
return createHash("sha256").update(path6.resolve(absRoot)).digest("hex").slice(0, 12);
|
|
4528
4598
|
}
|
|
4599
|
+
function projectSlug(absRoot) {
|
|
4600
|
+
const base = slugify(path6.basename(absRoot));
|
|
4601
|
+
const hash = createHash("sha256").update(path6.resolve(absRoot)).digest("hex").slice(0, 6);
|
|
4602
|
+
return `${base}-${hash}`;
|
|
4603
|
+
}
|
|
4604
|
+
function slugify(name) {
|
|
4605
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "project";
|
|
4606
|
+
}
|
|
4529
4607
|
function resolveWstackPaths(opts) {
|
|
4530
|
-
const home = opts.userHome ??
|
|
4608
|
+
const home = opts.userHome ?? os7.homedir();
|
|
4531
4609
|
const globalRoot = opts.globalRoot ?? path6.join(home, ".wrongstack");
|
|
4532
4610
|
const hash = projectHash(opts.projectRoot);
|
|
4533
|
-
const
|
|
4611
|
+
const slug = projectSlug(opts.projectRoot);
|
|
4612
|
+
const projectDir = path6.join(globalRoot, "projects", slug);
|
|
4534
4613
|
return {
|
|
4535
4614
|
globalRoot,
|
|
4536
4615
|
configDir: globalRoot,
|
|
@@ -4555,6 +4634,7 @@ function resolveWstackPaths(opts) {
|
|
|
4555
4634
|
inProjectSkills: path6.join(opts.projectRoot, ".wrongstack", "skills"),
|
|
4556
4635
|
inProjectWorktrees: path6.join(opts.projectRoot, ".wrongstack", "worktrees"),
|
|
4557
4636
|
projectHash: hash,
|
|
4637
|
+
projectSlug: slug,
|
|
4558
4638
|
projectGoal: path6.join(projectDir, "goal.json"),
|
|
4559
4639
|
projectSpecs: path6.join(projectDir, "specs"),
|
|
4560
4640
|
projectTaskGraphs: path6.join(projectDir, "task-graphs"),
|
|
@@ -4653,6 +4733,12 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
4653
4733
|
if (opts.sessionId) out["WRONGSTACK_SESSION_ID"] = opts.sessionId;
|
|
4654
4734
|
return out;
|
|
4655
4735
|
}
|
|
4736
|
+
function expectDefined7(value) {
|
|
4737
|
+
if (value === null || value === void 0) {
|
|
4738
|
+
throw new Error("Expected value to be defined");
|
|
4739
|
+
}
|
|
4740
|
+
return value;
|
|
4741
|
+
}
|
|
4656
4742
|
var GLOB_CHARS = /* @__PURE__ */ new Set(["*", "?", "["]);
|
|
4657
4743
|
var IS_WINDOWS = process.platform === "win32";
|
|
4658
4744
|
var SEP = IS_WINDOWS ? "\\" : "/";
|
|
@@ -4666,7 +4752,7 @@ function globToRegex(pat) {
|
|
|
4666
4752
|
let i = 0;
|
|
4667
4753
|
let re = "^";
|
|
4668
4754
|
while (i < pat.length) {
|
|
4669
|
-
const c = pat[i];
|
|
4755
|
+
const c = expectDefined7(pat[i]);
|
|
4670
4756
|
if (c === "*") {
|
|
4671
4757
|
if (pat[i + 1] === "*") {
|
|
4672
4758
|
re += ".*";
|
|
@@ -4705,7 +4791,7 @@ function globToRegex(pat) {
|
|
|
4705
4791
|
}
|
|
4706
4792
|
function baseDir(pat) {
|
|
4707
4793
|
let i = pat.length - 1;
|
|
4708
|
-
while (i >= 0 && !GLOB_CHARS.has(pat[i]) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
4794
|
+
while (i >= 0 && !GLOB_CHARS.has(expectDefined7(pat[i])) && pat[i] !== SEP && pat[i] !== "/") i--;
|
|
4709
4795
|
const cut = i >= 0 ? pat.lastIndexOf(SEP, i) : pat.lastIndexOf("/", i);
|
|
4710
4796
|
return cut < 0 ? "." : pat.slice(0, cut);
|
|
4711
4797
|
}
|
|
@@ -4770,6 +4856,12 @@ async function expandGlob(pattern) {
|
|
|
4770
4856
|
}
|
|
4771
4857
|
|
|
4772
4858
|
// src/utils/json-repair.ts
|
|
4859
|
+
function expectDefined8(value) {
|
|
4860
|
+
if (value === null || value === void 0) {
|
|
4861
|
+
throw new Error("Expected value to be defined");
|
|
4862
|
+
}
|
|
4863
|
+
return value;
|
|
4864
|
+
}
|
|
4773
4865
|
function completePartialObject(s) {
|
|
4774
4866
|
if (!s.trim().startsWith("{")) return s;
|
|
4775
4867
|
if (tryParse(s).ok) return s;
|
|
@@ -4781,7 +4873,7 @@ function completePartialObject(s) {
|
|
|
4781
4873
|
let contentEnd = 0;
|
|
4782
4874
|
let stringBraceDepth = 0;
|
|
4783
4875
|
for (let i = 0; i < s.length; i++) {
|
|
4784
|
-
const ch = s[i];
|
|
4876
|
+
const ch = expectDefined8(s[i]);
|
|
4785
4877
|
if (inString) {
|
|
4786
4878
|
contentEnd = i + 1;
|
|
4787
4879
|
if (escaped) {
|
|
@@ -4877,7 +4969,23 @@ function mergeCustomModelDefs(providerCustomModels, configModels) {
|
|
|
4877
4969
|
|
|
4878
4970
|
// src/storage/session-store.ts
|
|
4879
4971
|
init_atomic_write();
|
|
4880
|
-
|
|
4972
|
+
function expectDefined9(value) {
|
|
4973
|
+
if (value === null || value === void 0) {
|
|
4974
|
+
throw new Error("Expected value to be defined");
|
|
4975
|
+
}
|
|
4976
|
+
return value;
|
|
4977
|
+
}
|
|
4978
|
+
function sanitizeModel(model) {
|
|
4979
|
+
return model.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
4980
|
+
}
|
|
4981
|
+
function generateSessionId(startedAt, model) {
|
|
4982
|
+
const date = startedAt.slice(0, 10);
|
|
4983
|
+
const time = startedAt.slice(11, 19).replace(/:/g, "-");
|
|
4984
|
+
const suffix = randomBytes(2).toString("hex");
|
|
4985
|
+
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
4986
|
+
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
4987
|
+
}
|
|
4988
|
+
var DefaultSessionStore = class _DefaultSessionStore {
|
|
4881
4989
|
dir;
|
|
4882
4990
|
events;
|
|
4883
4991
|
secretScrubber;
|
|
@@ -4886,19 +4994,29 @@ var DefaultSessionStore = class {
|
|
|
4886
4994
|
this.events = opts.events;
|
|
4887
4995
|
this.secretScrubber = opts.secretScrubber;
|
|
4888
4996
|
}
|
|
4997
|
+
/** Absolute path to the session index file. */
|
|
4998
|
+
get indexFile() {
|
|
4999
|
+
return path6.join(this.dir, "_index.jsonl");
|
|
5000
|
+
}
|
|
4889
5001
|
/** Join session ID to its absolute path within the store directory. */
|
|
4890
5002
|
sessionPath(id, ext) {
|
|
4891
5003
|
return path6.join(this.dir, `${id}${ext}`);
|
|
4892
5004
|
}
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
5005
|
+
/**
|
|
5006
|
+
* Ensure the directory implied by the session ID exists. When the ID
|
|
5007
|
+
* contains a date prefix like `2026-06-06/...`, this creates the date
|
|
5008
|
+
* subdirectory so sessions group naturally by day.
|
|
5009
|
+
*/
|
|
5010
|
+
async ensureShardDir(id) {
|
|
5011
|
+
const dirPath = path6.dirname(path6.join(this.dir, id));
|
|
5012
|
+
await ensureDir(dirPath);
|
|
5013
|
+
return dirPath;
|
|
4896
5014
|
}
|
|
4897
5015
|
async create(meta) {
|
|
4898
5016
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4899
|
-
const id = meta.id
|
|
5017
|
+
const id = meta.id && meta.id.length > 0 ? meta.id : generateSessionId(startedAt, meta.model ?? meta.provider);
|
|
4900
5018
|
const shardDir = await this.ensureShardDir(id);
|
|
4901
|
-
const file = path6.join(shardDir, `${id}.jsonl`);
|
|
5019
|
+
const file = path6.join(shardDir, `${path6.basename(id)}.jsonl`);
|
|
4902
5020
|
let handle;
|
|
4903
5021
|
try {
|
|
4904
5022
|
handle = await fsp3.open(file, "a", 384);
|
|
@@ -4912,7 +5030,8 @@ var DefaultSessionStore = class {
|
|
|
4912
5030
|
return new FileSessionWriter(id, handle, startedAt, meta, this.events, {
|
|
4913
5031
|
dir: shardDir,
|
|
4914
5032
|
filePath: file,
|
|
4915
|
-
secretScrubber: this.secretScrubber
|
|
5033
|
+
secretScrubber: this.secretScrubber,
|
|
5034
|
+
onClose: (s) => this.appendToIndex(s)
|
|
4916
5035
|
});
|
|
4917
5036
|
} catch (err) {
|
|
4918
5037
|
await handle.close().catch(() => {
|
|
@@ -4943,7 +5062,7 @@ var DefaultSessionStore = class {
|
|
|
4943
5062
|
provider: data.metadata.provider
|
|
4944
5063
|
},
|
|
4945
5064
|
this.events,
|
|
4946
|
-
{ resumed: true, dir: this.dir, filePath: file, secretScrubber: this.secretScrubber }
|
|
5065
|
+
{ resumed: true, dir: this.dir, filePath: file, secretScrubber: this.secretScrubber, onClose: (s) => this.appendToIndex(s) }
|
|
4947
5066
|
);
|
|
4948
5067
|
return { writer, data };
|
|
4949
5068
|
} catch (err) {
|
|
@@ -4973,6 +5092,15 @@ var DefaultSessionStore = class {
|
|
|
4973
5092
|
async list(limit = 20) {
|
|
4974
5093
|
try {
|
|
4975
5094
|
await ensureDir(this.dir);
|
|
5095
|
+
const indexed = await this.readIndex();
|
|
5096
|
+
if (indexed.length > 0) {
|
|
5097
|
+
indexed.sort((a, b) => {
|
|
5098
|
+
if (a.startedAt < b.startedAt) return 1;
|
|
5099
|
+
if (a.startedAt > b.startedAt) return -1;
|
|
5100
|
+
return a.id.localeCompare(b.id);
|
|
5101
|
+
});
|
|
5102
|
+
return indexed.slice(0, limit);
|
|
5103
|
+
}
|
|
4976
5104
|
const ids = await this.collectSessionIds(this.dir);
|
|
4977
5105
|
const sessions = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
4978
5106
|
const out = sessions.filter((s) => s !== null);
|
|
@@ -4986,16 +5114,121 @@ var DefaultSessionStore = class {
|
|
|
4986
5114
|
return [];
|
|
4987
5115
|
}
|
|
4988
5116
|
}
|
|
4989
|
-
|
|
4990
|
-
|
|
5117
|
+
// ── Session index (_index.jsonl) ─────────────────────────────────────────
|
|
5118
|
+
//
|
|
5119
|
+
// One JSON line per closed session, appended atomically on close().
|
|
5120
|
+
// When a session is deleted, a tombstone {action:"delete",id:"..."} is
|
|
5121
|
+
// appended. On read, tombstones filter out matching session entries.
|
|
5122
|
+
// This keeps listing O(lines-in-index) instead of O(files-on-disk).
|
|
5123
|
+
//
|
|
5124
|
+
// The index auto-compacts every N appends to prevent unbounded growth
|
|
5125
|
+
// from tombstones and duplicate entries (resume cycles).
|
|
5126
|
+
indexAppendCount = 0;
|
|
5127
|
+
static COMPACT_EVERY = 30;
|
|
5128
|
+
/** Append a session summary to the index. */
|
|
5129
|
+
async appendToIndex(summary) {
|
|
5130
|
+
try {
|
|
5131
|
+
await ensureDir(this.dir);
|
|
5132
|
+
const line = JSON.stringify(summary) + "\n";
|
|
5133
|
+
await fsp3.appendFile(this.indexFile, line, "utf8");
|
|
5134
|
+
this.indexAppendCount++;
|
|
5135
|
+
if (this.indexAppendCount >= _DefaultSessionStore.COMPACT_EVERY) {
|
|
5136
|
+
await this.compactIndex();
|
|
5137
|
+
this.indexAppendCount = 0;
|
|
5138
|
+
}
|
|
5139
|
+
} catch {
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
/** Append a tombstone entry for a deleted session. */
|
|
5143
|
+
async writeTombstone(id) {
|
|
5144
|
+
try {
|
|
5145
|
+
await ensureDir(this.dir);
|
|
5146
|
+
const line = JSON.stringify({ action: "delete", id }) + "\n";
|
|
5147
|
+
await fsp3.appendFile(this.indexFile, line, "utf8");
|
|
5148
|
+
this.indexAppendCount++;
|
|
5149
|
+
} catch {
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
/**
|
|
5153
|
+
* Compact the index: read all entries, drop tombstones, deduplicate
|
|
5154
|
+
* (keep latest per session), and rewrite. Atomic via temp+rename.
|
|
5155
|
+
*/
|
|
5156
|
+
async compactIndex() {
|
|
5157
|
+
const entries = await this.readIndex();
|
|
5158
|
+
if (entries.length === 0) return;
|
|
5159
|
+
const tmp = `${this.indexFile}.compact.tmp`;
|
|
5160
|
+
const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
5161
|
+
await fsp3.writeFile(tmp, lines, "utf8");
|
|
5162
|
+
await fsp3.rename(tmp, this.indexFile);
|
|
5163
|
+
}
|
|
5164
|
+
/**
|
|
5165
|
+
* Read the index file and return deduplicated session summaries.
|
|
5166
|
+
* Entries with a matching tombstone are filtered out.
|
|
5167
|
+
* Returns empty array when the index doesn't exist or is corrupt.
|
|
5168
|
+
*/
|
|
5169
|
+
async readIndex() {
|
|
5170
|
+
let raw;
|
|
5171
|
+
try {
|
|
5172
|
+
raw = await fsp3.readFile(this.indexFile, "utf8");
|
|
5173
|
+
} catch {
|
|
5174
|
+
return [];
|
|
5175
|
+
}
|
|
5176
|
+
const deleted = /* @__PURE__ */ new Set();
|
|
5177
|
+
const seen = /* @__PURE__ */ new Map();
|
|
5178
|
+
for (const line of raw.split("\n")) {
|
|
5179
|
+
if (!line.trim()) continue;
|
|
5180
|
+
try {
|
|
5181
|
+
const entry = JSON.parse(line);
|
|
5182
|
+
if (entry.action === "delete" && entry.id) {
|
|
5183
|
+
deleted.add(entry.id);
|
|
5184
|
+
seen.delete(entry.id);
|
|
5185
|
+
continue;
|
|
5186
|
+
}
|
|
5187
|
+
if (entry.id && !deleted.has(entry.id)) {
|
|
5188
|
+
seen.set(entry.id, entry);
|
|
5189
|
+
}
|
|
5190
|
+
} catch {
|
|
5191
|
+
}
|
|
5192
|
+
}
|
|
5193
|
+
return Array.from(seen.values());
|
|
5194
|
+
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Rebuild the index from disk by scanning all sessions and writing a
|
|
5197
|
+
* fresh _index.jsonl. Useful after manual cleanup or index corruption.
|
|
5198
|
+
*/
|
|
5199
|
+
async rebuildIndex() {
|
|
5200
|
+
const ids = await this.collectSessionIds(this.dir);
|
|
5201
|
+
const summaries = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
5202
|
+
const valid = summaries.filter((s) => s !== null);
|
|
5203
|
+
const tmp = `${this.indexFile}.tmp`;
|
|
5204
|
+
const lines = valid.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
5205
|
+
await fsp3.writeFile(tmp, lines, "utf8");
|
|
5206
|
+
await fsp3.rename(tmp, this.indexFile);
|
|
5207
|
+
return valid.length;
|
|
5208
|
+
}
|
|
5209
|
+
/** Recursively collect session IDs from date-shard subdirectories.
|
|
5210
|
+
* IDs include the date-prefix path (e.g. "2026-06-06/17-46-57Z_…").
|
|
5211
|
+
* Skips `.jsonl`/`.summary.json` root files, dot-files, and
|
|
5212
|
+
* sub-directories that belong to fleet/subagent sessions. */
|
|
5213
|
+
async collectSessionIds(dir, prefix = "", depth = 0) {
|
|
4991
5214
|
const ids = [];
|
|
4992
|
-
|
|
5215
|
+
let entries;
|
|
5216
|
+
try {
|
|
5217
|
+
entries = await fsp3.readdir(dir, { withFileTypes: true });
|
|
5218
|
+
} catch {
|
|
5219
|
+
return ids;
|
|
5220
|
+
}
|
|
4993
5221
|
for (const entry of entries) {
|
|
4994
|
-
|
|
5222
|
+
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
5223
|
+
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
5224
|
+
continue;
|
|
4995
5225
|
if (entry.isDirectory()) {
|
|
4996
|
-
|
|
5226
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
5227
|
+
ids.push(...await this.collectSessionIds(path6.join(dir, entry.name), childPrefix, depth + 1));
|
|
4997
5228
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
4998
|
-
|
|
5229
|
+
if (entry.name === "_index.jsonl") continue;
|
|
5230
|
+
const base = entry.name.replace(/\.jsonl$/, "");
|
|
5231
|
+
ids.push(prefix ? `${prefix}/${base}` : base);
|
|
4999
5232
|
}
|
|
5000
5233
|
}
|
|
5001
5234
|
return ids;
|
|
@@ -5018,9 +5251,70 @@ var DefaultSessionStore = class {
|
|
|
5018
5251
|
return summary;
|
|
5019
5252
|
}
|
|
5020
5253
|
}
|
|
5021
|
-
|
|
5022
|
-
|
|
5254
|
+
/**
|
|
5255
|
+
* Delete a session and all associated files: JSONL, summary, plan/todos
|
|
5256
|
+
* sidecars, and the session directory (fleet.json, shared/, subagents/).
|
|
5257
|
+
*/
|
|
5258
|
+
async deleteSession(id) {
|
|
5259
|
+
await fsp3.unlink(this.sessionPath(id, ".jsonl")).catch(() => void 0);
|
|
5023
5260
|
await fsp3.unlink(this.sessionPath(id, ".summary.json")).catch(() => void 0);
|
|
5261
|
+
const shardDir = path6.dirname(path6.join(this.dir, id));
|
|
5262
|
+
const base = path6.basename(id);
|
|
5263
|
+
for (const ext of [".plan.json", ".todos.json"]) {
|
|
5264
|
+
await fsp3.unlink(path6.join(shardDir, `${base}${ext}`)).catch(() => void 0);
|
|
5265
|
+
}
|
|
5266
|
+
const sessDir = path6.join(shardDir, base);
|
|
5267
|
+
await fsp3.rm(sessDir, { recursive: true, force: true }).catch(() => void 0);
|
|
5268
|
+
await this.writeTombstone(id);
|
|
5269
|
+
}
|
|
5270
|
+
async delete(id) {
|
|
5271
|
+
await this.deleteSession(id);
|
|
5272
|
+
}
|
|
5273
|
+
async prune(maxAgeDays = 30) {
|
|
5274
|
+
const cutoff = Date.now() - maxAgeDays * 864e5;
|
|
5275
|
+
let deleted = 0;
|
|
5276
|
+
let activeSessionId = null;
|
|
5277
|
+
try {
|
|
5278
|
+
const raw = await fsp3.readFile(path6.join(this.dir, "active.json"), "utf8");
|
|
5279
|
+
const active = JSON.parse(raw);
|
|
5280
|
+
activeSessionId = active.sessionId ?? null;
|
|
5281
|
+
} catch {
|
|
5282
|
+
}
|
|
5283
|
+
const entries = await fsp3.readdir(this.dir, { withFileTypes: true }).catch(() => []);
|
|
5284
|
+
for (const entry of entries) {
|
|
5285
|
+
if (!entry.isDirectory()) continue;
|
|
5286
|
+
const dateDir = path6.join(this.dir, entry.name);
|
|
5287
|
+
const files = await fsp3.readdir(dateDir, { withFileTypes: true }).catch(() => []);
|
|
5288
|
+
for (const file of files) {
|
|
5289
|
+
if (!file.isFile() || !file.name.endsWith(".jsonl")) continue;
|
|
5290
|
+
const jsonlPath = path6.join(dateDir, file.name);
|
|
5291
|
+
try {
|
|
5292
|
+
const stat10 = await fsp3.stat(jsonlPath);
|
|
5293
|
+
if (stat10.mtimeMs >= cutoff) continue;
|
|
5294
|
+
} catch {
|
|
5295
|
+
continue;
|
|
5296
|
+
}
|
|
5297
|
+
const id = `${entry.name}/${file.name.replace(/\.jsonl$/, "")}`;
|
|
5298
|
+
if (activeSessionId && id === activeSessionId) continue;
|
|
5299
|
+
await this.deleteSession(id);
|
|
5300
|
+
deleted++;
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
if (deleted > 0) {
|
|
5304
|
+
await this.compactIndex().catch(() => void 0);
|
|
5305
|
+
}
|
|
5306
|
+
for (const entry of entries) {
|
|
5307
|
+
if (!entry.isDirectory()) continue;
|
|
5308
|
+
const dateDir = path6.join(this.dir, entry.name);
|
|
5309
|
+
try {
|
|
5310
|
+
const remaining = await fsp3.readdir(dateDir);
|
|
5311
|
+
if (remaining.length === 0) {
|
|
5312
|
+
await fsp3.rmdir(dateDir).catch(() => void 0);
|
|
5313
|
+
}
|
|
5314
|
+
} catch {
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
5317
|
+
return deleted;
|
|
5024
5318
|
}
|
|
5025
5319
|
async clearHistory(id) {
|
|
5026
5320
|
await this.ensureShardDir(id);
|
|
@@ -5042,13 +5336,42 @@ var DefaultSessionStore = class {
|
|
|
5042
5336
|
const data = await this.load(id);
|
|
5043
5337
|
const firstUser = data.events.find((e) => e.type === "user_input");
|
|
5044
5338
|
const title = firstUser && firstUser.type === "user_input" ? userInputTitle(firstUser.content) : "(empty session)";
|
|
5339
|
+
let iterationCount = 0;
|
|
5340
|
+
let toolCallCount = 0;
|
|
5341
|
+
let toolErrorCount = 0;
|
|
5342
|
+
let fileChangeCount = 0;
|
|
5343
|
+
const toolBreakdown = {};
|
|
5344
|
+
let outcome = void 0;
|
|
5345
|
+
const lastEvent = data.events[data.events.length - 1];
|
|
5346
|
+
for (const e of data.events) {
|
|
5347
|
+
if (e.type === "in_flight_start") iterationCount++;
|
|
5348
|
+
else if (e.type === "tool_call_start") {
|
|
5349
|
+
toolCallCount++;
|
|
5350
|
+
toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;
|
|
5351
|
+
} else if (e.type === "tool_result" && e.isError) toolErrorCount++;
|
|
5352
|
+
else if (e.type === "file_snapshot") fileChangeCount += e.files.length;
|
|
5353
|
+
}
|
|
5354
|
+
if (lastEvent?.type === "session_end") {
|
|
5355
|
+
outcome = "completed";
|
|
5356
|
+
} else if (lastEvent?.type === "in_flight_start") {
|
|
5357
|
+
outcome = "aborted";
|
|
5358
|
+
} else if (data.events.some((e) => e.type === "error")) {
|
|
5359
|
+
outcome = "error";
|
|
5360
|
+
}
|
|
5045
5361
|
return {
|
|
5046
5362
|
id,
|
|
5047
5363
|
title,
|
|
5048
5364
|
startedAt: data.metadata.startedAt,
|
|
5365
|
+
endedAt: data.metadata.endedAt,
|
|
5049
5366
|
model: data.metadata.model ?? "unknown",
|
|
5050
5367
|
provider: data.metadata.provider ?? "unknown",
|
|
5051
|
-
tokenTotal: data.usage.input + data.usage.output
|
|
5368
|
+
tokenTotal: data.usage.input + data.usage.output,
|
|
5369
|
+
iterationCount: iterationCount > 0 ? iterationCount : void 0,
|
|
5370
|
+
toolCallCount: toolCallCount > 0 ? toolCallCount : void 0,
|
|
5371
|
+
toolErrorCount: toolErrorCount > 0 ? toolErrorCount : void 0,
|
|
5372
|
+
fileChangeCount: fileChangeCount > 0 ? fileChangeCount : void 0,
|
|
5373
|
+
toolBreakdown: Object.keys(toolBreakdown).length > 0 ? toolBreakdown : {},
|
|
5374
|
+
outcome
|
|
5052
5375
|
};
|
|
5053
5376
|
} catch {
|
|
5054
5377
|
return {
|
|
@@ -5147,9 +5470,10 @@ var FileSessionWriter = class {
|
|
|
5147
5470
|
this.meta = meta;
|
|
5148
5471
|
this.events = events;
|
|
5149
5472
|
this.resumed = opts.resumed ?? false;
|
|
5150
|
-
this.manifestFile = opts.dir ? path6.join(opts.dir, `${id}.summary.json`) : "";
|
|
5473
|
+
this.manifestFile = opts.dir ? path6.join(opts.dir, `${path6.basename(id)}.summary.json`) : "";
|
|
5151
5474
|
this.filePath = opts.filePath ?? "";
|
|
5152
5475
|
this.secretScrubber = opts.secretScrubber;
|
|
5476
|
+
this.onCloseCb = opts.onClose;
|
|
5153
5477
|
this.summary = {
|
|
5154
5478
|
id,
|
|
5155
5479
|
title: "(empty session)",
|
|
@@ -5179,6 +5503,15 @@ var FileSessionWriter = class {
|
|
|
5179
5503
|
appendFailCount = 0;
|
|
5180
5504
|
lastAppendWarnAt = 0;
|
|
5181
5505
|
secretScrubber;
|
|
5506
|
+
onCloseCb;
|
|
5507
|
+
// ── Enriched summary tracking ──────────────────────────────────────────
|
|
5508
|
+
iterationCount = 0;
|
|
5509
|
+
toolCallCount = 0;
|
|
5510
|
+
toolErrorCount = 0;
|
|
5511
|
+
toolBreakdown = {};
|
|
5512
|
+
fileChangeCount = 0;
|
|
5513
|
+
compactionCount = 0;
|
|
5514
|
+
outcome = void 0;
|
|
5182
5515
|
/**
|
|
5183
5516
|
* Scrub secrets out of conversation-turn events before they are observed
|
|
5184
5517
|
* for the summary, written to the JSONL log, or surfaced on resume. Only
|
|
@@ -5256,8 +5589,22 @@ var FileSessionWriter = class {
|
|
|
5256
5589
|
observeForSummary(event) {
|
|
5257
5590
|
if (event.type === "tool_use") {
|
|
5258
5591
|
this.openToolUses.add(event.id);
|
|
5592
|
+
} else if (event.type === "tool_call_start") {
|
|
5593
|
+
this.toolCallCount++;
|
|
5594
|
+
this.toolBreakdown[event.name] = (this.toolBreakdown[event.name] ?? 0) + 1;
|
|
5259
5595
|
} else if (event.type === "tool_result") {
|
|
5260
5596
|
this.openToolUses.delete(event.id);
|
|
5597
|
+
if (event.isError) {
|
|
5598
|
+
this.toolErrorCount++;
|
|
5599
|
+
this.outcome = "error";
|
|
5600
|
+
}
|
|
5601
|
+
} else if (event.type === "file_snapshot") {
|
|
5602
|
+
this.fileChangeCount += event.files.length;
|
|
5603
|
+
} else if (event.type === "compaction") {
|
|
5604
|
+
this.compactionCount++;
|
|
5605
|
+
}
|
|
5606
|
+
if (event.type === "error" || event.type === "provider_error") {
|
|
5607
|
+
this.outcome = "error";
|
|
5261
5608
|
}
|
|
5262
5609
|
if (event.type === "user_input" && this.summary.title === "(empty session)") {
|
|
5263
5610
|
this.summary = { ...this.summary, title: userInputTitle(event.content) };
|
|
@@ -5268,18 +5615,35 @@ var FileSessionWriter = class {
|
|
|
5268
5615
|
} else if (event.type === "session_end") {
|
|
5269
5616
|
const total = event.usage.input + event.usage.output;
|
|
5270
5617
|
if (total > 0) this.summary = { ...this.summary, tokenTotal: total };
|
|
5618
|
+
} else if (event.type === "in_flight_start") {
|
|
5619
|
+
this.iterationCount++;
|
|
5271
5620
|
}
|
|
5272
5621
|
}
|
|
5273
5622
|
async close() {
|
|
5274
5623
|
if (this.closing) return;
|
|
5275
5624
|
this.closing = true;
|
|
5276
5625
|
this.closed = true;
|
|
5626
|
+
this.summary = {
|
|
5627
|
+
...this.summary,
|
|
5628
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5629
|
+
iterationCount: this.iterationCount,
|
|
5630
|
+
toolCallCount: this.toolCallCount,
|
|
5631
|
+
toolErrorCount: this.toolErrorCount,
|
|
5632
|
+
fileChangeCount: this.fileChangeCount,
|
|
5633
|
+
compactionCount: this.compactionCount > 0 ? this.compactionCount : void 0,
|
|
5634
|
+
toolBreakdown: { ...this.toolBreakdown },
|
|
5635
|
+
outcome: this.outcome ?? "completed"
|
|
5636
|
+
};
|
|
5277
5637
|
if (this.manifestFile) {
|
|
5278
5638
|
try {
|
|
5279
5639
|
await atomicWrite(this.manifestFile, JSON.stringify(this.summary), { mode: 384 });
|
|
5280
5640
|
} catch {
|
|
5281
5641
|
}
|
|
5282
5642
|
}
|
|
5643
|
+
try {
|
|
5644
|
+
await this.onCloseCb?.(this.summary);
|
|
5645
|
+
} catch {
|
|
5646
|
+
}
|
|
5283
5647
|
try {
|
|
5284
5648
|
await this.handle.close();
|
|
5285
5649
|
} catch {
|
|
@@ -5321,7 +5685,7 @@ var FileSessionWriter = class {
|
|
|
5321
5685
|
let targetCheckpointLine = -1;
|
|
5322
5686
|
let afterTarget = false;
|
|
5323
5687
|
for (let i = 0; i < lines.length; i++) {
|
|
5324
|
-
const line = lines[i];
|
|
5688
|
+
const line = expectDefined9(lines[i]);
|
|
5325
5689
|
if (!line.trim()) continue;
|
|
5326
5690
|
let event;
|
|
5327
5691
|
try {
|
|
@@ -6244,7 +6608,7 @@ var RecoveryLock = class {
|
|
|
6244
6608
|
constructor(opts) {
|
|
6245
6609
|
this.file = path6.join(opts.dir, LOCK_FILE);
|
|
6246
6610
|
this.pid = opts.pid ?? process.pid;
|
|
6247
|
-
this.hostname = opts.hostname ??
|
|
6611
|
+
this.hostname = opts.hostname ?? os7.hostname();
|
|
6248
6612
|
this.maxAgeMs = opts.maxAgeMs ?? DEFAULT_MAX_AGE_MS;
|
|
6249
6613
|
this.sessionStore = opts.sessionStore;
|
|
6250
6614
|
this.probe = opts.isPidAlive ?? defaultIsPidAlive;
|
|
@@ -6458,8 +6822,11 @@ var SessionAnalyzer = class {
|
|
|
6458
6822
|
}
|
|
6459
6823
|
calcDuration(events) {
|
|
6460
6824
|
if (events.length < 2) return 0;
|
|
6461
|
-
const
|
|
6462
|
-
const
|
|
6825
|
+
const firstEvent = events[0];
|
|
6826
|
+
const lastEvent = events[events.length - 1];
|
|
6827
|
+
if (!firstEvent || !lastEvent) return 0;
|
|
6828
|
+
const first = new Date(firstEvent.ts).getTime();
|
|
6829
|
+
const last = new Date(lastEvent.ts).getTime();
|
|
6463
6830
|
return last - first;
|
|
6464
6831
|
}
|
|
6465
6832
|
};
|
|
@@ -6572,7 +6939,7 @@ async function loadTodosCheckpoint(filePath) {
|
|
|
6572
6939
|
const parsed = JSON.parse(raw);
|
|
6573
6940
|
if (parsed?.version !== 1 || !Array.isArray(parsed.todos)) return null;
|
|
6574
6941
|
return parsed.todos.filter(
|
|
6575
|
-
(t2) => !!t2 && typeof t2.id === "string" && typeof t2.content === "string" && typeof t2.status === "string"
|
|
6942
|
+
(t2) => !!t2 && typeof t2.id === "string" && typeof t2.content === "string" && typeof t2.status === "string" && (t2.activeForm === void 0 || typeof t2.activeForm === "string")
|
|
6576
6943
|
);
|
|
6577
6944
|
} catch {
|
|
6578
6945
|
return null;
|
|
@@ -7568,7 +7935,7 @@ function parseDescription(raw) {
|
|
|
7568
7935
|
const scope = [];
|
|
7569
7936
|
const coversMatch = /(?:covers|for|including)\s+([^.]+)/i.exec(desc);
|
|
7570
7937
|
if (coversMatch) {
|
|
7571
|
-
const items = coversMatch[1].replace(/[·•]/g, ",").split(",").map((s) => s.trim()).filter(Boolean);
|
|
7938
|
+
const items = coversMatch[1] ?? "".replace(/[·•]/g, ",").split(",").map((s) => s.trim()).filter(Boolean);
|
|
7572
7939
|
scope.push(...items);
|
|
7573
7940
|
}
|
|
7574
7941
|
return { trigger, scope };
|
|
@@ -8023,7 +8390,7 @@ var IntelligentCompactor = class {
|
|
|
8023
8390
|
maxTokens: 1024
|
|
8024
8391
|
};
|
|
8025
8392
|
const ac = ctx.signal ? void 0 : new AbortController();
|
|
8026
|
-
const signal = ctx.signal ?? ac
|
|
8393
|
+
const signal = ctx.signal ?? ac?.signal;
|
|
8027
8394
|
const res = await this.provider.complete(req, { signal });
|
|
8028
8395
|
const textBlocks = res.content.filter(isTextBlock);
|
|
8029
8396
|
return textBlocks.map((b) => b.text).join("\n").trim() || "(empty summary)";
|
|
@@ -8126,6 +8493,12 @@ var IntelligentCompactor = class {
|
|
|
8126
8493
|
};
|
|
8127
8494
|
|
|
8128
8495
|
// src/models/llm-selector.ts
|
|
8496
|
+
function expectDefined10(value) {
|
|
8497
|
+
if (value === null || value === void 0) {
|
|
8498
|
+
throw new Error("Expected value to be defined");
|
|
8499
|
+
}
|
|
8500
|
+
return value;
|
|
8501
|
+
}
|
|
8129
8502
|
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.
|
|
8130
8503
|
|
|
8131
8504
|
Output a JSON object with this structure:
|
|
@@ -8166,7 +8539,7 @@ function formatMessages(messages, maxChars = 8e3) {
|
|
|
8166
8539
|
const lines = [];
|
|
8167
8540
|
let used = 0;
|
|
8168
8541
|
for (let i = 0; i < messages.length; i++) {
|
|
8169
|
-
const m = messages[i];
|
|
8542
|
+
const m = expectDefined10(messages[i]);
|
|
8170
8543
|
const role = m.role.padEnd(10, " ");
|
|
8171
8544
|
let text;
|
|
8172
8545
|
if (typeof m.content === "string") {
|
|
@@ -8231,7 +8604,7 @@ IMPORTANT: Total conversation (${totalTokens} tokens) exceeds budget (${effectiv
|
|
|
8231
8604
|
let tokenCount = 0;
|
|
8232
8605
|
let startIdx = 0;
|
|
8233
8606
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8234
|
-
const m = messages[i];
|
|
8607
|
+
const m = expectDefined10(messages[i]);
|
|
8235
8608
|
const cost = typeof m.content === "string" ? Math.ceil(m.content.length / 4) : m.content.reduce(
|
|
8236
8609
|
(acc, b) => acc + (b.type === "text" ? Math.ceil(b.text.length / 4) : Math.ceil(JSON.stringify(b).length / 4)),
|
|
8237
8610
|
0
|
|
@@ -8442,6 +8815,7 @@ Summarize the following message range:`;
|
|
|
8442
8815
|
let boundary = preserveIdx;
|
|
8443
8816
|
for (let i = preserveIdx; i < messages.length && i < preserveIdx + 6; i++) {
|
|
8444
8817
|
const m = messages[i];
|
|
8818
|
+
if (!m) continue;
|
|
8445
8819
|
if (m.role === "user" && this.hasTextContent(m)) {
|
|
8446
8820
|
boundary = i;
|
|
8447
8821
|
break;
|
|
@@ -8868,7 +9242,7 @@ init_atomic_write();
|
|
|
8868
9242
|
var MAX_JOURNAL_ENTRIES = 500;
|
|
8869
9243
|
function goalFilePath(projectRoot) {
|
|
8870
9244
|
const hash = createHash("sha256").update(path6.resolve(projectRoot)).digest("hex").slice(0, 12);
|
|
8871
|
-
return path6.join(
|
|
9245
|
+
return path6.join(os7.homedir(), ".wrongstack", "projects", hash, "goal.json");
|
|
8872
9246
|
}
|
|
8873
9247
|
async function loadGoal(filePath) {
|
|
8874
9248
|
let raw;
|
|
@@ -9706,16 +10080,16 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
9706
10080
|
}
|
|
9707
10081
|
if (exceeded.length === 0) return [];
|
|
9708
10082
|
if (!this._onThreshold) {
|
|
9709
|
-
const first2 = exceeded[0];
|
|
10083
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
9710
10084
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
9711
10085
|
}
|
|
9712
10086
|
if (this._mode === "sync") {
|
|
9713
|
-
const first2 = exceeded[0];
|
|
10087
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
9714
10088
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
9715
10089
|
}
|
|
9716
10090
|
const bus = this._events;
|
|
9717
10091
|
if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
|
|
9718
|
-
const first2 = exceeded[0];
|
|
10092
|
+
const first2 = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
9719
10093
|
throw new BudgetExceededError(first2.kind, first2.limit, first2.used);
|
|
9720
10094
|
}
|
|
9721
10095
|
for (const entry of exceeded) {
|
|
@@ -9723,8 +10097,9 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
9723
10097
|
const decision2 = this._negotiateExtension(entry.kind, exceeded);
|
|
9724
10098
|
this._pendingNegotiations.set(entry.kind, decision2);
|
|
9725
10099
|
}
|
|
9726
|
-
const first = exceeded[0];
|
|
10100
|
+
const first = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
9727
10101
|
const decision = this._pendingNegotiations.get(first.kind);
|
|
10102
|
+
if (!decision) throw new Error(`No pending negotiation for ${first.kind}`);
|
|
9728
10103
|
throw new BudgetThresholdSignal(first.kind, first.limit, first.used, decision);
|
|
9729
10104
|
}
|
|
9730
10105
|
/**
|
|
@@ -9746,8 +10121,11 @@ var SubagentBudget = class _SubagentBudget {
|
|
|
9746
10121
|
* a fresh signal.
|
|
9747
10122
|
*/
|
|
9748
10123
|
async _negotiateExtension(kind, exceeded) {
|
|
10124
|
+
if (!this._onThreshold) {
|
|
10125
|
+
return "stop";
|
|
10126
|
+
}
|
|
9749
10127
|
try {
|
|
9750
|
-
const first = exceeded[0];
|
|
10128
|
+
const first = exceeded[0] ?? { kind: "iterations", limit: 0, used: 0 };
|
|
9751
10129
|
const result = this._onThreshold({
|
|
9752
10130
|
kind: first.kind,
|
|
9753
10131
|
used: first.used,
|
|
@@ -12230,6 +12608,11 @@ function getAgentDefinition(role) {
|
|
|
12230
12608
|
|
|
12231
12609
|
// src/coordination/dispatcher.ts
|
|
12232
12610
|
var DEFAULT_DISPATCH_ROLE = "executor";
|
|
12611
|
+
var FALLBACK_DEFINITION = {
|
|
12612
|
+
config: { role: "unknown", name: "Unknown Agent" },
|
|
12613
|
+
budget: {},
|
|
12614
|
+
capability: { phase: "meta", summary: "", keywords: [] }
|
|
12615
|
+
};
|
|
12233
12616
|
function normalize2(text) {
|
|
12234
12617
|
return ` ${text.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim()} `;
|
|
12235
12618
|
}
|
|
@@ -12257,7 +12640,7 @@ function scoreAgents(task, catalog = AGENT_CATALOG) {
|
|
|
12257
12640
|
}
|
|
12258
12641
|
function heuristicConfidence(candidates) {
|
|
12259
12642
|
if (candidates.length === 0) return 0;
|
|
12260
|
-
const top = candidates[0]
|
|
12643
|
+
const top = candidates[0]?.score ?? 0;
|
|
12261
12644
|
const second = candidates[1]?.score ?? 0;
|
|
12262
12645
|
const strength = Math.min(1, top / 3);
|
|
12263
12646
|
const margin = (top - second + 1) / (top + 1);
|
|
@@ -12273,7 +12656,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
12273
12656
|
if (top && confidence >= threshold) {
|
|
12274
12657
|
return {
|
|
12275
12658
|
role: top.role,
|
|
12276
|
-
definition: catalog[top.role],
|
|
12659
|
+
definition: catalog[top.role] ?? FALLBACK_DEFINITION,
|
|
12277
12660
|
confidence,
|
|
12278
12661
|
method: "heuristic",
|
|
12279
12662
|
reason: `Matched keywords: ${top.matched.slice(0, 4).join(", ")}`,
|
|
@@ -12281,7 +12664,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
12281
12664
|
};
|
|
12282
12665
|
}
|
|
12283
12666
|
if (opts.classifier) {
|
|
12284
|
-
const pool = (candidates.length > 0 ? candidates.slice(0, maxCandidates).map((c) => catalog[c.role]) : ALL_AGENT_DEFINITIONS).map((d) => ({
|
|
12667
|
+
const pool = (candidates.length > 0 ? candidates.slice(0, maxCandidates).map((c) => catalog[c.role] ?? FALLBACK_DEFINITION) : ALL_AGENT_DEFINITIONS).map((d) => ({
|
|
12285
12668
|
role: d.config.role,
|
|
12286
12669
|
name: d.config.name,
|
|
12287
12670
|
summary: d.capability.summary
|
|
@@ -12291,7 +12674,7 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
12291
12674
|
if (choice && catalog[choice.role]) {
|
|
12292
12675
|
return {
|
|
12293
12676
|
role: choice.role,
|
|
12294
|
-
definition: catalog[choice.role],
|
|
12677
|
+
definition: catalog[choice.role] ?? FALLBACK_DEFINITION,
|
|
12295
12678
|
confidence: 1,
|
|
12296
12679
|
method: "llm",
|
|
12297
12680
|
reason: choice.reason ?? "Selected by LLM classifier",
|
|
@@ -12304,17 +12687,17 @@ async function dispatchAgent(task, opts = {}) {
|
|
|
12304
12687
|
if (top) {
|
|
12305
12688
|
return {
|
|
12306
12689
|
role: top.role,
|
|
12307
|
-
definition: catalog[top.role],
|
|
12690
|
+
definition: catalog[top.role] ?? FALLBACK_DEFINITION,
|
|
12308
12691
|
confidence,
|
|
12309
12692
|
method: "heuristic",
|
|
12310
12693
|
reason: `Weak match (${top.matched.slice(0, 3).join(", ") || "low signal"})`,
|
|
12311
12694
|
alternatives: candidates.slice(1, maxCandidates)
|
|
12312
12695
|
};
|
|
12313
12696
|
}
|
|
12314
|
-
const fallbackRole = catalog[DEFAULT_DISPATCH_ROLE] ? DEFAULT_DISPATCH_ROLE : Object.keys(catalog)[0];
|
|
12697
|
+
const fallbackRole = catalog[DEFAULT_DISPATCH_ROLE] ? DEFAULT_DISPATCH_ROLE : Object.keys(catalog)[0] ?? DEFAULT_DISPATCH_ROLE;
|
|
12315
12698
|
return {
|
|
12316
12699
|
role: fallbackRole,
|
|
12317
|
-
definition: catalog[fallbackRole],
|
|
12700
|
+
definition: catalog[fallbackRole] ?? FALLBACK_DEFINITION,
|
|
12318
12701
|
confidence: 0,
|
|
12319
12702
|
method: "fallback",
|
|
12320
12703
|
reason: "No keyword signal; defaulting to the generalist Executor",
|
|
@@ -13127,6 +13510,7 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
13127
13510
|
takeNextDispatchableTask() {
|
|
13128
13511
|
for (let i = 0; i < this.pendingTasks.length; i++) {
|
|
13129
13512
|
const task = this.pendingTasks[i];
|
|
13513
|
+
if (!task) continue;
|
|
13130
13514
|
const subagentId = task.subagentId ? this.isIdleSubagent(task.subagentId) ? task.subagentId : null : this.findIdleSubagent();
|
|
13131
13515
|
if (!subagentId) continue;
|
|
13132
13516
|
this.pendingTasks.splice(i, 1);
|
|
@@ -13318,14 +13702,14 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
13318
13702
|
const idleExceeded = idleLimit !== void 0 && budget.idleMs() >= idleLimit;
|
|
13319
13703
|
if (idleExceeded && !wallExceeded) {
|
|
13320
13704
|
this.subagents.get(ctx.subagentId)?.abortController.abort();
|
|
13321
|
-
reject(new BudgetExceededError("timeout", idleLimit, budget.idleMs()));
|
|
13705
|
+
reject(new BudgetExceededError("timeout", idleLimit ?? 0, budget.idleMs()));
|
|
13322
13706
|
return;
|
|
13323
13707
|
}
|
|
13324
13708
|
if (!wallExceeded) {
|
|
13325
13709
|
scheduleNext();
|
|
13326
13710
|
return;
|
|
13327
13711
|
}
|
|
13328
|
-
const limit = wallLimit;
|
|
13712
|
+
const limit = wallLimit ?? 0;
|
|
13329
13713
|
if (!budget.onThreshold) {
|
|
13330
13714
|
this.subagents.get(ctx.subagentId)?.abortController.abort();
|
|
13331
13715
|
reject(new BudgetExceededError("timeout", limit, elapsed));
|
|
@@ -13484,6 +13868,12 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
13484
13868
|
};
|
|
13485
13869
|
|
|
13486
13870
|
// src/execution/parallel-eternal-engine.ts
|
|
13871
|
+
function expectDefined11(value) {
|
|
13872
|
+
if (value === null || value === void 0) {
|
|
13873
|
+
throw new Error("Expected value to be defined");
|
|
13874
|
+
}
|
|
13875
|
+
return value;
|
|
13876
|
+
}
|
|
13487
13877
|
function sleep2(ms) {
|
|
13488
13878
|
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
13489
13879
|
}
|
|
@@ -13642,7 +14032,7 @@ var ParallelEternalEngine = class {
|
|
|
13642
14032
|
// Fan-out
|
|
13643
14033
|
// -------------------------------------------------------------------------
|
|
13644
14034
|
async fanOut(goal, tasks) {
|
|
13645
|
-
const coordinator = this.coordinator;
|
|
14035
|
+
const coordinator = expectDefined11(this.coordinator);
|
|
13646
14036
|
const slotCount = Math.min(this.slots, tasks.length);
|
|
13647
14037
|
const routes = this.dispatchEnabled ? await Promise.all(
|
|
13648
14038
|
tasks.slice(0, slotCount).map(
|
|
@@ -13674,7 +14064,7 @@ ${recentJournal}` : "No prior iterations.",
|
|
|
13674
14064
|
const routeInfo = [];
|
|
13675
14065
|
const spawnPromises = [];
|
|
13676
14066
|
for (let i = 0; i < slotCount; i++) {
|
|
13677
|
-
const task = tasks[i];
|
|
14067
|
+
const task = expectDefined11(tasks[i]);
|
|
13678
14068
|
const route = routes[i] ?? null;
|
|
13679
14069
|
const subagentId = `parallel-${this.iterations}-${i}`;
|
|
13680
14070
|
const taskId = randomUUID();
|
|
@@ -14177,7 +14567,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14177
14567
|
this.emit("session.error", error);
|
|
14178
14568
|
throw error;
|
|
14179
14569
|
}
|
|
14180
|
-
for (const result of results
|
|
14570
|
+
for (const result of results?.flat() ?? []) {
|
|
14181
14571
|
await this.parseAndEmit(result);
|
|
14182
14572
|
}
|
|
14183
14573
|
const report = this.assembleReport();
|
|
@@ -14238,7 +14628,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
14238
14628
|
}
|
|
14239
14629
|
budgetForRole(role) {
|
|
14240
14630
|
if (this.options.budgetOverrides?.[role]) {
|
|
14241
|
-
return this.options.budgetOverrides[role];
|
|
14631
|
+
return this.options.budgetOverrides[role] ?? { maxIterations: 0, maxToolCalls: 0, timeoutMs: 0 };
|
|
14242
14632
|
}
|
|
14243
14633
|
const defaults = {
|
|
14244
14634
|
"bug-hunter": { maxIterations: 2e3, maxToolCalls: 5e3, timeoutMs: 10 * 60 * 1e3 },
|
|
@@ -14691,7 +15081,7 @@ function makeSpawnTool(director, roster) {
|
|
|
14691
15081
|
});
|
|
14692
15082
|
const dispatchRole = dispatchResult.role;
|
|
14693
15083
|
if (roster?.[dispatchRole]) {
|
|
14694
|
-
cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole]);
|
|
15084
|
+
cfg = instantiateRosterConfig(dispatchRole, roster[dispatchRole] ?? {});
|
|
14695
15085
|
} else {
|
|
14696
15086
|
const def = dispatchResult.definition;
|
|
14697
15087
|
cfg = {
|
|
@@ -16628,6 +17018,7 @@ function createDelegateTool(opts) {
|
|
|
16628
17018
|
if (typeof i.task !== "string" || !i.task.trim()) {
|
|
16629
17019
|
return { ok: false, error: "`task` is required." };
|
|
16630
17020
|
}
|
|
17021
|
+
const target = i.role ?? i.name ?? "subagent";
|
|
16631
17022
|
try {
|
|
16632
17023
|
let director = await opts.host.ensureDirector();
|
|
16633
17024
|
if (!director) {
|
|
@@ -16688,6 +17079,7 @@ function createDelegateTool(opts) {
|
|
|
16688
17079
|
if (!cfg.timeoutMs) {
|
|
16689
17080
|
cfg.timeoutMs = Math.max(3e4, timeoutMs - SUBAGENT_TIMEOUT_BUFFER_MS);
|
|
16690
17081
|
}
|
|
17082
|
+
opts.events?.emit("delegate.started", { target, task: i.task });
|
|
16691
17083
|
const subagentId = await director.spawn(cfg);
|
|
16692
17084
|
const taskId = await director.assign({
|
|
16693
17085
|
id: `${randomUUID()}`,
|
|
@@ -16722,6 +17114,17 @@ function createDelegateTool(opts) {
|
|
|
16722
17114
|
});
|
|
16723
17115
|
if ("__timeout" in result) {
|
|
16724
17116
|
const partial2 = await readSubagentPartial(opts, subagentId);
|
|
17117
|
+
opts.events?.emit("delegate.completed", {
|
|
17118
|
+
target,
|
|
17119
|
+
task: i.task,
|
|
17120
|
+
ok: false,
|
|
17121
|
+
status: "host_timeout",
|
|
17122
|
+
summary: `[${target}] timed out \u2014 no result within ${Math.round(timeoutMs / 1e3)}s`,
|
|
17123
|
+
durationMs: timeoutMs,
|
|
17124
|
+
iterations: partial2?.events ?? 0,
|
|
17125
|
+
toolCalls: partial2?.toolUsesObserved ?? 0,
|
|
17126
|
+
subagentId
|
|
17127
|
+
});
|
|
16725
17128
|
return {
|
|
16726
17129
|
ok: false,
|
|
16727
17130
|
stopReason: "host_timeout",
|
|
@@ -16738,6 +17141,24 @@ function createDelegateTool(opts) {
|
|
|
16738
17141
|
const retryable = result.error?.retryable;
|
|
16739
17142
|
const backoffMs = result.error?.backoffMs;
|
|
16740
17143
|
const summary = buildDelegateSummary(i.role, result);
|
|
17144
|
+
let costUsd;
|
|
17145
|
+
try {
|
|
17146
|
+
costUsd = dir.snapshot().perSubagent[result.subagentId]?.cost;
|
|
17147
|
+
} catch {
|
|
17148
|
+
costUsd = void 0;
|
|
17149
|
+
}
|
|
17150
|
+
opts.events?.emit("delegate.completed", {
|
|
17151
|
+
target,
|
|
17152
|
+
task: i.task,
|
|
17153
|
+
ok: result.status === "success",
|
|
17154
|
+
status: result.status,
|
|
17155
|
+
summary,
|
|
17156
|
+
durationMs: result.durationMs,
|
|
17157
|
+
iterations: result.iterations,
|
|
17158
|
+
toolCalls: result.toolCalls,
|
|
17159
|
+
costUsd,
|
|
17160
|
+
subagentId: result.subagentId
|
|
17161
|
+
});
|
|
16741
17162
|
return {
|
|
16742
17163
|
ok: result.status === "success",
|
|
16743
17164
|
status: result.status,
|
|
@@ -16759,10 +17180,21 @@ function createDelegateTool(opts) {
|
|
|
16759
17180
|
summary
|
|
16760
17181
|
};
|
|
16761
17182
|
} catch (err) {
|
|
17183
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17184
|
+
opts.events?.emit("delegate.completed", {
|
|
17185
|
+
target,
|
|
17186
|
+
task: i.task,
|
|
17187
|
+
ok: false,
|
|
17188
|
+
status: "error",
|
|
17189
|
+
summary: `[${target}] failed \u2014 ${message}`,
|
|
17190
|
+
durationMs: 0,
|
|
17191
|
+
iterations: 0,
|
|
17192
|
+
toolCalls: 0
|
|
17193
|
+
});
|
|
16762
17194
|
return {
|
|
16763
17195
|
ok: false,
|
|
16764
17196
|
stopReason: "error",
|
|
16765
|
-
error:
|
|
17197
|
+
error: message
|
|
16766
17198
|
};
|
|
16767
17199
|
}
|
|
16768
17200
|
}
|
|
@@ -16958,7 +17390,10 @@ function attachAutoExtend(events, policy = {}) {
|
|
|
16958
17390
|
if (kind === "timeout" || kind === "idle_timeout") {
|
|
16959
17391
|
if (progress > lastTimeoutProgress) {
|
|
16960
17392
|
lastTimeoutProgress = progress;
|
|
16961
|
-
const next2 = Math.min(
|
|
17393
|
+
const next2 = Math.min(
|
|
17394
|
+
Math.ceil(limit * (1 + factor)),
|
|
17395
|
+
ceiling.timeoutMs ?? DEFAULT_CEILING.timeoutMs
|
|
17396
|
+
);
|
|
16962
17397
|
extend({ timeoutMs: next2 });
|
|
16963
17398
|
} else {
|
|
16964
17399
|
deny();
|
|
@@ -16972,7 +17407,7 @@ function attachAutoExtend(events, policy = {}) {
|
|
|
16972
17407
|
}
|
|
16973
17408
|
extendCounts.set(kind, count + 1);
|
|
16974
17409
|
const field = FIELD_BY_KIND[kind];
|
|
16975
|
-
const cap = ceiling[field];
|
|
17410
|
+
const cap = ceiling[field] ?? DEFAULT_CEILING[field];
|
|
16976
17411
|
const next = Math.min(Math.ceil(limit * (1 + factor)), cap);
|
|
16977
17412
|
extend({ [field]: next });
|
|
16978
17413
|
})
|
|
@@ -17617,7 +18052,7 @@ var TaskTracker = class {
|
|
|
17617
18052
|
if (filter.type?.length && !filter.type.includes(n.type)) return false;
|
|
17618
18053
|
if (filter.assignee?.length && n.assignee && !filter.assignee.includes(n.assignee))
|
|
17619
18054
|
return false;
|
|
17620
|
-
if (filter.tags?.length && n.tags && !n.tags.some((t2) => filter.tags
|
|
18055
|
+
if (filter.tags?.length && n.tags && !n.tags.some((t2) => filter.tags?.includes(t2)))
|
|
17621
18056
|
return false;
|
|
17622
18057
|
if (filter.specRequirementId && n.specRequirementId !== filter.specRequirementId)
|
|
17623
18058
|
return false;
|
|
@@ -18131,6 +18566,12 @@ var TaskGraphStore = class {
|
|
|
18131
18566
|
};
|
|
18132
18567
|
|
|
18133
18568
|
// src/sdd/spec-builder.ts
|
|
18569
|
+
function expectDefined12(value) {
|
|
18570
|
+
if (value === null || value === void 0) {
|
|
18571
|
+
throw new Error("Expected value to be defined");
|
|
18572
|
+
}
|
|
18573
|
+
return value;
|
|
18574
|
+
}
|
|
18134
18575
|
function buildQuestioningPrompt(session, min, max) {
|
|
18135
18576
|
const answered = session.answers.length;
|
|
18136
18577
|
const remaining = Math.max(0, min - answered);
|
|
@@ -18176,7 +18617,7 @@ function buildQuestioningPrompt(session, min, max) {
|
|
|
18176
18617
|
if (answered > 0) {
|
|
18177
18618
|
lines.push("", "**Conversation so far:**");
|
|
18178
18619
|
for (let i = 0; i < answered; i++) {
|
|
18179
|
-
const a = session.answers[i];
|
|
18620
|
+
const a = expectDefined12(session.answers[i]);
|
|
18180
18621
|
lines.push(``, `Q${i + 1}: ${a.question}`, `A${i + 1}: ${a.answer}`);
|
|
18181
18622
|
}
|
|
18182
18623
|
}
|
|
@@ -18918,6 +19359,12 @@ function truncate2(str, maxLen) {
|
|
|
18918
19359
|
}
|
|
18919
19360
|
|
|
18920
19361
|
// src/sdd/critical-path.ts
|
|
19362
|
+
function expectDefined13(value) {
|
|
19363
|
+
if (value === null || value === void 0) {
|
|
19364
|
+
throw new Error("Expected value to be defined");
|
|
19365
|
+
}
|
|
19366
|
+
return value;
|
|
19367
|
+
}
|
|
18921
19368
|
function analyzeCriticalPath(graph) {
|
|
18922
19369
|
const nodes = Array.from(graph.nodes.values());
|
|
18923
19370
|
const topoOrder = topologicalSort(graph);
|
|
@@ -18926,9 +19373,9 @@ function analyzeCriticalPath(graph) {
|
|
|
18926
19373
|
for (const edge of graph.edges) {
|
|
18927
19374
|
if (edge.type === "depends_on") {
|
|
18928
19375
|
if (!blockedByMap.has(edge.from)) blockedByMap.set(edge.from, /* @__PURE__ */ new Set());
|
|
18929
|
-
blockedByMap.get(edge.from)
|
|
19376
|
+
blockedByMap.get(edge.from)?.add(edge.to);
|
|
18930
19377
|
if (!blocksMap.has(edge.to)) blocksMap.set(edge.to, /* @__PURE__ */ new Set());
|
|
18931
|
-
blocksMap.get(edge.to)
|
|
19378
|
+
blocksMap.get(edge.to)?.add(edge.from);
|
|
18932
19379
|
}
|
|
18933
19380
|
}
|
|
18934
19381
|
const readyTasks = [];
|
|
@@ -18993,7 +19440,7 @@ function getTransitiveBlocked(_graph, taskId, blocksMap) {
|
|
|
18993
19440
|
const visited = /* @__PURE__ */ new Set();
|
|
18994
19441
|
const queue = [taskId];
|
|
18995
19442
|
while (queue.length > 0) {
|
|
18996
|
-
const current = queue.shift();
|
|
19443
|
+
const current = expectDefined13(queue.shift());
|
|
18997
19444
|
const blocked = blocksMap.get(current);
|
|
18998
19445
|
if (!blocked) continue;
|
|
18999
19446
|
for (const id of blocked) {
|
|
@@ -19018,7 +19465,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
19018
19465
|
for (const [taskId, blockers] of blockedByMap) {
|
|
19019
19466
|
for (const blockerId of blockers) {
|
|
19020
19467
|
if (!blocksMap.has(blockerId)) blocksMap.set(blockerId, /* @__PURE__ */ new Set());
|
|
19021
|
-
blocksMap.get(blockerId)
|
|
19468
|
+
blocksMap.get(blockerId)?.add(taskId);
|
|
19022
19469
|
}
|
|
19023
19470
|
}
|
|
19024
19471
|
const n = allIds.length;
|
|
@@ -19039,7 +19486,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
19039
19486
|
if (!changed) break;
|
|
19040
19487
|
}
|
|
19041
19488
|
let maxDist = 0;
|
|
19042
|
-
let maxId = allIds[0];
|
|
19489
|
+
let maxId = expectDefined13(allIds[0]);
|
|
19043
19490
|
for (const id of allIds) {
|
|
19044
19491
|
const d = dist.get(id) ?? 0;
|
|
19045
19492
|
if (d > maxDist) {
|
|
@@ -19508,6 +19955,12 @@ var SddTaskDecomposer = class {
|
|
|
19508
19955
|
return nodes.some((n) => n.status === "blocked");
|
|
19509
19956
|
}
|
|
19510
19957
|
};
|
|
19958
|
+
function expectDefined14(value) {
|
|
19959
|
+
if (value === null || value === void 0) {
|
|
19960
|
+
throw new Error("Expected value to be defined");
|
|
19961
|
+
}
|
|
19962
|
+
return value;
|
|
19963
|
+
}
|
|
19511
19964
|
var SddParallelRun = class {
|
|
19512
19965
|
constructor(opts) {
|
|
19513
19966
|
this.opts = opts;
|
|
@@ -19608,8 +20061,10 @@ var SddParallelRun = class {
|
|
|
19608
20061
|
"\u2022 Do not ask before routine in-project tool use; if a permission gate appears, wait for that flow.",
|
|
19609
20062
|
"\u2022 Keep output concise \u2014 summarize changes, do not transcribe files."
|
|
19610
20063
|
].join("\n");
|
|
20064
|
+
if (!this.coordinator) throw new Error("SDD parallel runner requires a coordinator");
|
|
20065
|
+
const coordinator = this.coordinator;
|
|
19611
20066
|
const spawns = subagentIds.map(
|
|
19612
|
-
(subagentId) =>
|
|
20067
|
+
(subagentId) => coordinator.spawn({
|
|
19613
20068
|
id: subagentId,
|
|
19614
20069
|
name: subagentId,
|
|
19615
20070
|
role: "executor",
|
|
@@ -19617,12 +20072,12 @@ var SddParallelRun = class {
|
|
|
19617
20072
|
})
|
|
19618
20073
|
);
|
|
19619
20074
|
const spawnResults = await Promise.all(spawns);
|
|
19620
|
-
if (!spawnResults.every((r) => r.subagentId)) {
|
|
20075
|
+
if (!spawnResults.every((r) => Boolean(r.subagentId))) {
|
|
19621
20076
|
throw new Error("One or more subagent spawns failed");
|
|
19622
20077
|
}
|
|
19623
20078
|
const assignPromises = tasks.map((task, i) => {
|
|
19624
20079
|
const spec = {
|
|
19625
|
-
id: taskIds[i],
|
|
20080
|
+
id: taskIds[i] ?? task.id,
|
|
19626
20081
|
description: [
|
|
19627
20082
|
directivePreamble,
|
|
19628
20083
|
"",
|
|
@@ -19631,15 +20086,15 @@ var SddParallelRun = class {
|
|
|
19631
20086
|
"",
|
|
19632
20087
|
task.description
|
|
19633
20088
|
].join("\n"),
|
|
19634
|
-
subagentId: subagentIds[i],
|
|
20089
|
+
subagentId: subagentIds[i] ?? spawnResults[i]?.subagentId ?? task.id,
|
|
19635
20090
|
timeoutMs: this.timeoutMs
|
|
19636
20091
|
};
|
|
19637
|
-
return this.coordinator
|
|
20092
|
+
return this.coordinator?.assign(spec);
|
|
19638
20093
|
});
|
|
19639
20094
|
await Promise.all(assignPromises);
|
|
19640
20095
|
let results;
|
|
19641
20096
|
try {
|
|
19642
|
-
results = await
|
|
20097
|
+
results = await coordinator.awaitTasks(taskIds);
|
|
19643
20098
|
} catch (err) {
|
|
19644
20099
|
results = taskIds.map((id) => ({
|
|
19645
20100
|
subagentId: "",
|
|
@@ -19654,8 +20109,8 @@ var SddParallelRun = class {
|
|
|
19654
20109
|
const successCount = results.filter((r) => r.status === "success").length;
|
|
19655
20110
|
const failCount = results.length - successCount;
|
|
19656
20111
|
for (let i = 0; i < results.length; i++) {
|
|
19657
|
-
const result = results[i];
|
|
19658
|
-
const taskId = taskIds[i];
|
|
20112
|
+
const result = expectDefined14(results[i]);
|
|
20113
|
+
const taskId = expectDefined14(taskIds[i]);
|
|
19659
20114
|
if (result.status === "success") {
|
|
19660
20115
|
this.opts.tracker.updateNodeStatus(taskId, "completed");
|
|
19661
20116
|
} else {
|
|
@@ -20762,6 +21217,12 @@ var allServers = () => ({
|
|
|
20762
21217
|
"zai-vision": { ...zaiVisionServer(), enabled: false },
|
|
20763
21218
|
"minimax-vision": { ...miniMaxVisionServer(), enabled: false }
|
|
20764
21219
|
});
|
|
21220
|
+
function expectDefined15(value) {
|
|
21221
|
+
if (value === null || value === void 0) {
|
|
21222
|
+
throw new Error("Expected value to be defined");
|
|
21223
|
+
}
|
|
21224
|
+
return value;
|
|
21225
|
+
}
|
|
20765
21226
|
function parseSkillRef(input) {
|
|
20766
21227
|
const trimmed = input.trim().replace(/^https?:\/\/github\.com\//, "").replace(/\.git$/, "");
|
|
20767
21228
|
const atIdx = trimmed.indexOf("@");
|
|
@@ -20778,7 +21239,7 @@ function parseSkillRef(input) {
|
|
|
20778
21239
|
if (parts.length < 2) {
|
|
20779
21240
|
throw new Error(`Invalid skill reference "${input}". Expected format: user/repo or user/repo@ref`);
|
|
20780
21241
|
}
|
|
20781
|
-
return { owner: parts[0], repo: parts[1], ref };
|
|
21242
|
+
return { owner: expectDefined15(parts[0]), repo: expectDefined15(parts[1]), ref };
|
|
20782
21243
|
}
|
|
20783
21244
|
var MAX_TARBALL_SIZE = 50 * 1024 * 1024;
|
|
20784
21245
|
async function downloadGitHubTarball(parsed) {
|
|
@@ -20810,7 +21271,7 @@ async function downloadGitHubTarball(parsed) {
|
|
|
20810
21271
|
`Tarball too large (${(Number.parseInt(contentLength, 10) / 1024 / 1024).toFixed(1)}MB). Max: ${MAX_TARBALL_SIZE / 1024 / 1024}MB`
|
|
20811
21272
|
);
|
|
20812
21273
|
}
|
|
20813
|
-
const tempDir = await fsp3.mkdtemp(path6.join(
|
|
21274
|
+
const tempDir = await fsp3.mkdtemp(path6.join(os7.tmpdir(), "wskill-"));
|
|
20814
21275
|
try {
|
|
20815
21276
|
if (!response.body) {
|
|
20816
21277
|
throw new Error("Empty response body from GitHub API");
|
|
@@ -20947,6 +21408,12 @@ var SkillManifestStore = class {
|
|
|
20947
21408
|
};
|
|
20948
21409
|
|
|
20949
21410
|
// src/skills/skill-installer.ts
|
|
21411
|
+
function expectDefined16(value) {
|
|
21412
|
+
if (value === null || value === void 0) {
|
|
21413
|
+
throw new Error("Expected value to be defined");
|
|
21414
|
+
}
|
|
21415
|
+
return value;
|
|
21416
|
+
}
|
|
20950
21417
|
var MAX_SKILL_FILE_SIZE = 100 * 1024;
|
|
20951
21418
|
var SkillInstaller = class {
|
|
20952
21419
|
opts;
|
|
@@ -21068,10 +21535,10 @@ var SkillInstaller = class {
|
|
|
21068
21535
|
for (const entry of targets) {
|
|
21069
21536
|
const key = `${entry.source}@${entry.ref}`;
|
|
21070
21537
|
if (!bySource.has(key)) bySource.set(key, []);
|
|
21071
|
-
bySource.get(key)
|
|
21538
|
+
bySource.get(key)?.push(entry);
|
|
21072
21539
|
}
|
|
21073
21540
|
for (const [, entries] of bySource) {
|
|
21074
|
-
const first = entries[0];
|
|
21541
|
+
const first = expectDefined16(entries[0]);
|
|
21075
21542
|
const scope = first.scope;
|
|
21076
21543
|
const isGlobal = scope === "user";
|
|
21077
21544
|
try {
|
|
@@ -21241,6 +21708,12 @@ async function collectFiles(dir, baseDir2) {
|
|
|
21241
21708
|
|
|
21242
21709
|
// src/storage/annotations-store.ts
|
|
21243
21710
|
init_atomic_write();
|
|
21711
|
+
function expectDefined17(value) {
|
|
21712
|
+
if (value === null || value === void 0) {
|
|
21713
|
+
throw new Error("Expected value to be defined");
|
|
21714
|
+
}
|
|
21715
|
+
return value;
|
|
21716
|
+
}
|
|
21244
21717
|
var FILE_VERSION = 1;
|
|
21245
21718
|
var MAX_TEXT_LENGTH = 2e3;
|
|
21246
21719
|
var MAX_ANNOTATIONS = 1e3;
|
|
@@ -21332,7 +21805,7 @@ var AnnotationsStore = class {
|
|
|
21332
21805
|
return;
|
|
21333
21806
|
}
|
|
21334
21807
|
const next = {
|
|
21335
|
-
...all[idx],
|
|
21808
|
+
...expectDefined17(all[idx]),
|
|
21336
21809
|
resolved: true,
|
|
21337
21810
|
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21338
21811
|
resolvedBy: input.resolvedBy
|
|
@@ -21568,6 +22041,12 @@ var ReplayLogStore = class {
|
|
|
21568
22041
|
return next;
|
|
21569
22042
|
}
|
|
21570
22043
|
};
|
|
22044
|
+
function expectDefined18(value) {
|
|
22045
|
+
if (value === null || value === void 0) {
|
|
22046
|
+
throw new Error("Expected value to be defined");
|
|
22047
|
+
}
|
|
22048
|
+
return value;
|
|
22049
|
+
}
|
|
21571
22050
|
var SessionRecovery = class {
|
|
21572
22051
|
constructor(dir) {
|
|
21573
22052
|
this.dir = dir;
|
|
@@ -21608,7 +22087,7 @@ var SessionRecovery = class {
|
|
|
21608
22087
|
const lines = raw.split("\n").filter((l) => l.trim());
|
|
21609
22088
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
21610
22089
|
try {
|
|
21611
|
-
const ev = JSON.parse(lines[i]);
|
|
22090
|
+
const ev = JSON.parse(expectDefined18(lines[i]));
|
|
21612
22091
|
if (ev.type === "in_flight_start") {
|
|
21613
22092
|
return {
|
|
21614
22093
|
sessionId,
|
|
@@ -21660,13 +22139,13 @@ var SessionRecovery = class {
|
|
|
21660
22139
|
let lastCheckpoint = null;
|
|
21661
22140
|
let lastCheckpointIdx = -1;
|
|
21662
22141
|
for (let i = 0; i < events.length; i++) {
|
|
21663
|
-
if (events[i]
|
|
21664
|
-
lastCheckpoint = events[i];
|
|
22142
|
+
if (events[i]?.type === "checkpoint") {
|
|
22143
|
+
lastCheckpoint = expectDefined18(events[i]);
|
|
21665
22144
|
lastCheckpointIdx = i;
|
|
21666
22145
|
}
|
|
21667
22146
|
}
|
|
21668
22147
|
const pendingEvents = lastCheckpointIdx >= 0 ? events.slice(lastCheckpointIdx + 1) : events;
|
|
21669
|
-
const lastEv = events[events.length - 1];
|
|
22148
|
+
const lastEv = expectDefined18(events[events.length - 1]);
|
|
21670
22149
|
const inFlightStart = lastEv.type === "in_flight_start" ? lastEv : null;
|
|
21671
22150
|
const context = inFlightStart && inFlightStart.type === "in_flight_start" ? inFlightStart.context : null;
|
|
21672
22151
|
return {
|
|
@@ -21709,6 +22188,12 @@ var SessionRecovery = class {
|
|
|
21709
22188
|
return path6.join(this.dir, `${sessionId}.jsonl`);
|
|
21710
22189
|
}
|
|
21711
22190
|
};
|
|
22191
|
+
function expectDefined19(value) {
|
|
22192
|
+
if (value === null || value === void 0) {
|
|
22193
|
+
throw new Error("Expected value to be defined");
|
|
22194
|
+
}
|
|
22195
|
+
return value;
|
|
22196
|
+
}
|
|
21712
22197
|
var GENESIS_PREV = "0".repeat(64);
|
|
21713
22198
|
var DEFAULT_FSYNC_EVERY = 100;
|
|
21714
22199
|
var ToolAuditLog = class {
|
|
@@ -21775,7 +22260,7 @@ var ToolAuditLog = class {
|
|
|
21775
22260
|
async verify(sessionId) {
|
|
21776
22261
|
const entries = await this.readAll(sessionId);
|
|
21777
22262
|
if (entries.length === 0) return { ok: true, entries: 0 };
|
|
21778
|
-
if (entries[0]
|
|
22263
|
+
if (entries[0]?.prevHash !== GENESIS_PREV) {
|
|
21779
22264
|
return {
|
|
21780
22265
|
ok: false,
|
|
21781
22266
|
brokenAt: 0,
|
|
@@ -21784,7 +22269,7 @@ var ToolAuditLog = class {
|
|
|
21784
22269
|
}
|
|
21785
22270
|
let prevHash = GENESIS_PREV;
|
|
21786
22271
|
for (let i = 0; i < entries.length; i++) {
|
|
21787
|
-
const e = entries[i];
|
|
22272
|
+
const e = expectDefined19(entries[i]);
|
|
21788
22273
|
if (e.prevHash !== prevHash) {
|
|
21789
22274
|
return {
|
|
21790
22275
|
ok: false,
|
|
@@ -21903,6 +22388,12 @@ function sortKeys2(value) {
|
|
|
21903
22388
|
|
|
21904
22389
|
// src/storage/session-rewinder.ts
|
|
21905
22390
|
init_atomic_write();
|
|
22391
|
+
function expectDefined20(value) {
|
|
22392
|
+
if (value === null || value === void 0) {
|
|
22393
|
+
throw new Error("Expected value to be defined");
|
|
22394
|
+
}
|
|
22395
|
+
return value;
|
|
22396
|
+
}
|
|
21906
22397
|
var DefaultSessionRewinder = class {
|
|
21907
22398
|
constructor(sessionsDir, projectRoot) {
|
|
21908
22399
|
this.sessionsDir = sessionsDir;
|
|
@@ -21941,7 +22432,7 @@ var DefaultSessionRewinder = class {
|
|
|
21941
22432
|
const events = parseEvents(raw);
|
|
21942
22433
|
let targetIdx = -1;
|
|
21943
22434
|
for (let i = 0; i < events.length; i++) {
|
|
21944
|
-
const event = events[i];
|
|
22435
|
+
const event = expectDefined20(events[i]);
|
|
21945
22436
|
if (event.type === "checkpoint") {
|
|
21946
22437
|
const checkpointEvent = event;
|
|
21947
22438
|
if (checkpointEvent.promptIndex === checkpointIndex) {
|
|
@@ -21955,7 +22446,7 @@ var DefaultSessionRewinder = class {
|
|
|
21955
22446
|
}
|
|
21956
22447
|
const snapshotsToRevert = [];
|
|
21957
22448
|
for (let i = targetIdx + 1; i < events.length; i++) {
|
|
21958
|
-
const event = events[i];
|
|
22449
|
+
const event = expectDefined20(events[i]);
|
|
21959
22450
|
if (event.type === "checkpoint") {
|
|
21960
22451
|
break;
|
|
21961
22452
|
}
|
|
@@ -22137,6 +22628,12 @@ var DefaultPromptStore = class {
|
|
|
22137
22628
|
};
|
|
22138
22629
|
}
|
|
22139
22630
|
};
|
|
22631
|
+
function expectDefined21(value) {
|
|
22632
|
+
if (value === null || value === void 0) {
|
|
22633
|
+
throw new Error("Expected value to be defined");
|
|
22634
|
+
}
|
|
22635
|
+
return value;
|
|
22636
|
+
}
|
|
22140
22637
|
var ALL_SYNC_CATEGORIES = ["settings", "skills", "prompts", "memory", "history"];
|
|
22141
22638
|
var CloudSync = class {
|
|
22142
22639
|
constructor(paths, getConfig, setConfig) {
|
|
@@ -22179,8 +22676,8 @@ var CloudSync = class {
|
|
|
22179
22676
|
const cfg = this.getConfig();
|
|
22180
22677
|
if (!cfg?.enabled) return { ok: false, action: "push", categories: [], message: "Not enabled." };
|
|
22181
22678
|
const parts = cfg.repo.split("/");
|
|
22182
|
-
const owner = parts[0];
|
|
22183
|
-
const repoName = parts[1];
|
|
22679
|
+
const owner = expectDefined21(parts[0]);
|
|
22680
|
+
const repoName = expectDefined21(parts[1]);
|
|
22184
22681
|
const branch = "main";
|
|
22185
22682
|
const baseTreeSha = this.state?.sha;
|
|
22186
22683
|
const { treeEntries, rev } = await this.buildLocalTree(cfg.categories);
|
|
@@ -22232,8 +22729,8 @@ var CloudSync = class {
|
|
|
22232
22729
|
const cfg = this.getConfig();
|
|
22233
22730
|
if (!cfg?.enabled) return { ok: false, action: "pull", categories: [], message: "Not enabled." };
|
|
22234
22731
|
const pullParts = cfg.repo.split("/");
|
|
22235
|
-
const owner = pullParts[0];
|
|
22236
|
-
const repoName = pullParts[1];
|
|
22732
|
+
const owner = expectDefined21(pullParts[0]);
|
|
22733
|
+
const repoName = expectDefined21(pullParts[1]);
|
|
22237
22734
|
const branchData = await this.getRef(token, owner, repoName, "main");
|
|
22238
22735
|
const currentSha = branchData.object.sha;
|
|
22239
22736
|
const commitData = await this.getCommit(token, owner, repoName, currentSha);
|
|
@@ -22288,7 +22785,7 @@ var CloudSync = class {
|
|
|
22288
22785
|
// ── GitHub API helpers ──────────────────────────────────────────────
|
|
22289
22786
|
async githubFetch(token, owner, repo, method, pathSegment, body) {
|
|
22290
22787
|
const url = `https://api.github.com/repos/${owner}/${repo}${pathSegment}`;
|
|
22291
|
-
const
|
|
22788
|
+
const init = {
|
|
22292
22789
|
signal: AbortSignal.timeout(15e3),
|
|
22293
22790
|
method,
|
|
22294
22791
|
headers: {
|
|
@@ -22296,9 +22793,10 @@ var CloudSync = class {
|
|
|
22296
22793
|
Accept: "application/vnd.github+json",
|
|
22297
22794
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
22298
22795
|
"Content-Type": "application/json"
|
|
22299
|
-
}
|
|
22300
|
-
|
|
22301
|
-
|
|
22796
|
+
}
|
|
22797
|
+
};
|
|
22798
|
+
if (body !== void 0) init.body = JSON.stringify(body);
|
|
22799
|
+
const res = await fetch(url, init);
|
|
22302
22800
|
if (!res.ok) {
|
|
22303
22801
|
const errText = await res.text();
|
|
22304
22802
|
throw new Error(`GitHub API ${method} ${pathSegment} failed (${res.status}): ${errText}`);
|
|
@@ -23433,7 +23931,7 @@ var ReportGenerator = class {
|
|
|
23433
23931
|
if (groups[finding.category] === void 0) {
|
|
23434
23932
|
groups[finding.category] = [];
|
|
23435
23933
|
}
|
|
23436
|
-
groups[finding.category]
|
|
23934
|
+
groups[finding.category]?.push(finding);
|
|
23437
23935
|
}
|
|
23438
23936
|
return groups;
|
|
23439
23937
|
}
|
|
@@ -23578,6 +24076,12 @@ var defaultGitignoreUpdater = new GitignoreUpdater();
|
|
|
23578
24076
|
|
|
23579
24077
|
// src/security-scanner/orchestrator.ts
|
|
23580
24078
|
init_atomic_write();
|
|
24079
|
+
function expectDefined22(value) {
|
|
24080
|
+
if (value === null || value === void 0) {
|
|
24081
|
+
throw new Error("Expected value to be defined");
|
|
24082
|
+
}
|
|
24083
|
+
return value;
|
|
24084
|
+
}
|
|
23581
24085
|
var SecurityScannerOrchestrator = class {
|
|
23582
24086
|
constructor(retryPolicy, errorHandler) {
|
|
23583
24087
|
this.retryPolicy = retryPolicy;
|
|
@@ -23627,7 +24131,7 @@ var SecurityScannerOrchestrator = class {
|
|
|
23627
24131
|
if (detectionResult.detectedStacks.length === 0) {
|
|
23628
24132
|
throw new Error(`No supported tech stack detected in ${projectRoot}`);
|
|
23629
24133
|
}
|
|
23630
|
-
const techStack = detectionResult.detectedStacks[0];
|
|
24134
|
+
const techStack = expectDefined22(detectionResult.detectedStacks[0]);
|
|
23631
24135
|
const generatedSkill = await this.generateSkillLLM(provider, model, projectRoot, techStack);
|
|
23632
24136
|
const scanResult = await this.scanWithLLM(provider, model, projectRoot, generatedSkill, techStack, options);
|
|
23633
24137
|
const synthesizedReport = await this.synthesizeReportLLM(provider, model, projectRoot, techStack, scanResult);
|
|
@@ -23708,7 +24212,7 @@ Return ONLY the JSON object, no markdown, no explanation.`;
|
|
|
23708
24212
|
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
23709
24213
|
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
23710
24214
|
if (jsonMatch) {
|
|
23711
|
-
const sanitized = sanitizeJsonString(jsonMatch[0]) || jsonMatch[0];
|
|
24215
|
+
const sanitized = sanitizeJsonString(expectDefined22(jsonMatch[0])) || expectDefined22(jsonMatch[0]);
|
|
23712
24216
|
const skillData = JSON.parse(sanitized);
|
|
23713
24217
|
return {
|
|
23714
24218
|
name: skillData.name || `security-scanner-${techStack.stack}`,
|
|
@@ -23828,7 +24332,7 @@ Return ONLY the JSON array. If no issues found, return [].`;
|
|
|
23828
24332
|
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("");
|
|
23829
24333
|
const jsonMatch = text.match(/\[[\s\S]*\]/);
|
|
23830
24334
|
if (jsonMatch) {
|
|
23831
|
-
const sanitized = sanitizeJsonString(jsonMatch[0]) || jsonMatch[0];
|
|
24335
|
+
const sanitized = sanitizeJsonString(expectDefined22(jsonMatch[0])) || expectDefined22(jsonMatch[0]);
|
|
23832
24336
|
const parsed = JSON.parse(sanitized);
|
|
23833
24337
|
return parsed.map((item, idx) => ({
|
|
23834
24338
|
id: `llm-finding-${idx}-${Date.now()}`,
|
|
@@ -24068,7 +24572,7 @@ ${dirs.join(", ")}`);
|
|
|
24068
24572
|
if (detectionResult.detectedStacks.length === 0) {
|
|
24069
24573
|
throw new Error(`No supported tech stack detected in ${projectRoot}`);
|
|
24070
24574
|
}
|
|
24071
|
-
const techStack = detectionResult.detectedStacks[0];
|
|
24575
|
+
const techStack = expectDefined22(detectionResult.detectedStacks[0]);
|
|
24072
24576
|
return {
|
|
24073
24577
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24074
24578
|
projectRoot,
|
|
@@ -24257,16 +24761,16 @@ Use \`/security report <number>\` to view a specific report.` };
|
|
|
24257
24761
|
}
|
|
24258
24762
|
const index = Number.parseInt(reportId, 10) - 1;
|
|
24259
24763
|
if (!Number.isNaN(index) && reports[index]) {
|
|
24260
|
-
const { readFile:
|
|
24261
|
-
const content = await
|
|
24764
|
+
const { readFile: readFile38 } = await import('fs/promises');
|
|
24765
|
+
const content = await readFile38(join(reportsDir, reports[index]), "utf-8");
|
|
24262
24766
|
return { message: `# Security Report
|
|
24263
24767
|
|
|
24264
24768
|
${content}` };
|
|
24265
24769
|
}
|
|
24266
24770
|
const match = reports.find((r) => r.includes(reportId));
|
|
24267
24771
|
if (match) {
|
|
24268
|
-
const { readFile:
|
|
24269
|
-
const content = await
|
|
24772
|
+
const { readFile: readFile38 } = await import('fs/promises');
|
|
24773
|
+
const content = await readFile38(join(reportsDir, match), "utf-8");
|
|
24270
24774
|
return { message: `# Security Report
|
|
24271
24775
|
|
|
24272
24776
|
${content}` };
|
|
@@ -24676,6 +25180,12 @@ var FleetManager = class {
|
|
|
24676
25180
|
this.usage.dispose();
|
|
24677
25181
|
}
|
|
24678
25182
|
};
|
|
25183
|
+
function expectDefined23(value) {
|
|
25184
|
+
if (value === null || value === void 0) {
|
|
25185
|
+
throw new Error("Expected value to be defined");
|
|
25186
|
+
}
|
|
25187
|
+
return value;
|
|
25188
|
+
}
|
|
24679
25189
|
function createMcpControlTool(opts) {
|
|
24680
25190
|
const { getConfig, configPath, registry } = opts;
|
|
24681
25191
|
const inputSchema = {
|
|
@@ -24721,11 +25231,11 @@ async function mcpControlDispatch(input, deps) {
|
|
|
24721
25231
|
case "search":
|
|
24722
25232
|
return renderSearch(query ?? "", deps);
|
|
24723
25233
|
case "enable":
|
|
24724
|
-
return runEnable(server, deps);
|
|
25234
|
+
return server ? runEnable(server, deps) : "`server` is required for enable.";
|
|
24725
25235
|
case "disable":
|
|
24726
|
-
return runDisable(server, deps);
|
|
25236
|
+
return server ? runDisable(server, deps) : "`server` is required for disable.";
|
|
24727
25237
|
case "restart":
|
|
24728
|
-
return runRestart(server, deps);
|
|
25238
|
+
return server ? runRestart(server, deps) : "`server` is required for restart.";
|
|
24729
25239
|
default:
|
|
24730
25240
|
return `Unknown action "${action}". Use one of: list, search, enable, disable, restart.`;
|
|
24731
25241
|
}
|
|
@@ -24827,7 +25337,7 @@ async function runDisable(name, deps) {
|
|
|
24827
25337
|
const mcpServers = {
|
|
24828
25338
|
...full.mcpServers ?? {}
|
|
24829
25339
|
};
|
|
24830
|
-
const existing = mcpServers[name];
|
|
25340
|
+
const existing = expectDefined23(mcpServers[name]);
|
|
24831
25341
|
mcpServers[name] = { ...existing, enabled: false };
|
|
24832
25342
|
full.mcpServers = mcpServers;
|
|
24833
25343
|
await writeConfig(deps.configPath, full);
|
|
@@ -24898,6 +25408,12 @@ function badge(state) {
|
|
|
24898
25408
|
}
|
|
24899
25409
|
|
|
24900
25410
|
// src/extension/registry.ts
|
|
25411
|
+
function expectDefined24(value) {
|
|
25412
|
+
if (value === null || value === void 0) {
|
|
25413
|
+
throw new Error("Expected value to be defined");
|
|
25414
|
+
}
|
|
25415
|
+
return value;
|
|
25416
|
+
}
|
|
24901
25417
|
var ExtensionRegistry = class {
|
|
24902
25418
|
extensions = [];
|
|
24903
25419
|
promptContributors = [];
|
|
@@ -25063,11 +25579,12 @@ var ExtensionRegistry = class {
|
|
|
25063
25579
|
* default runner, each subsequent wrapper wraps the previous.
|
|
25064
25580
|
*/
|
|
25065
25581
|
wrapProviderRunner(inner) {
|
|
25066
|
-
const wrappers = this.extensions.filter((e) => e.wrapProviderRunner).map((e) => ({ name: e.name, wrap: e.wrapProviderRunner }));
|
|
25582
|
+
const wrappers = this.extensions.filter((e) => e.wrapProviderRunner).map((e) => ({ name: e.name, wrap: expectDefined24(e.wrapProviderRunner) }));
|
|
25067
25583
|
if (wrappers.length === 0) return inner;
|
|
25068
25584
|
let composed = inner;
|
|
25069
25585
|
for (let i = wrappers.length - 1; i >= 0; i--) {
|
|
25070
25586
|
const wrapper = wrappers[i];
|
|
25587
|
+
if (!wrapper) continue;
|
|
25071
25588
|
const next = composed;
|
|
25072
25589
|
composed = async (ctx, req) => {
|
|
25073
25590
|
try {
|
|
@@ -25166,7 +25683,7 @@ function createAgentToolHandler(a) {
|
|
|
25166
25683
|
const useById = new Map(selectedToolUses.map((u) => [u.id, u]));
|
|
25167
25684
|
const resultsForMessage = [];
|
|
25168
25685
|
for (const { result, tool, durationMs } of outputs) {
|
|
25169
|
-
if (result.type === "tool_confirm_pending") {
|
|
25686
|
+
if (result.type === "tool_confirm_pending" && tool) {
|
|
25170
25687
|
const decision = await waitForConfirm({
|
|
25171
25688
|
tool,
|
|
25172
25689
|
input: result.input,
|
|
@@ -25228,6 +25745,7 @@ function createAgentToolHandler(a) {
|
|
|
25228
25745
|
resultsForMessage.push(reRunResult.result);
|
|
25229
25746
|
continue;
|
|
25230
25747
|
}
|
|
25748
|
+
if (result.type !== "tool_result") continue;
|
|
25231
25749
|
resultsForMessage.push(result);
|
|
25232
25750
|
const use = useById.get(result.tool_use_id);
|
|
25233
25751
|
if (!use) continue;
|
|
@@ -25743,13 +26261,12 @@ var Agent = class {
|
|
|
25743
26261
|
return this.container.resolve(TOKENS.PermissionPolicy);
|
|
25744
26262
|
}
|
|
25745
26263
|
get renderer() {
|
|
25746
|
-
return this.container.
|
|
26264
|
+
return this.container.safeResolve(TOKENS.Renderer);
|
|
25747
26265
|
}
|
|
25748
26266
|
disableInteractiveConfirmation() {
|
|
25749
26267
|
this.toolExecutor.clearConfirmAwaiter();
|
|
25750
|
-
|
|
25751
|
-
|
|
25752
|
-
policy.setPromptDelegate(void 0);
|
|
26268
|
+
if (typeof this.permission.setPromptDelegate === "function") {
|
|
26269
|
+
this.permission.setPromptDelegate(void 0);
|
|
25753
26270
|
}
|
|
25754
26271
|
}
|
|
25755
26272
|
register(tool) {
|
|
@@ -25779,6 +26296,7 @@ var Agent = class {
|
|
|
25779
26296
|
const signal = controller.signal;
|
|
25780
26297
|
this.ctx.signal = signal;
|
|
25781
26298
|
controller.onAbort(() => this.ctx.drainAbortHooks());
|
|
26299
|
+
this.ctx.tools = this.tools.list();
|
|
25782
26300
|
const span = this.tracer?.startSpan("agent.run", {
|
|
25783
26301
|
"agent.model": opts.model ?? this.ctx.model,
|
|
25784
26302
|
"agent.executionStrategy": opts.executionStrategy ?? this.executionStrategy
|
|
@@ -25795,7 +26313,8 @@ var Agent = class {
|
|
|
25795
26313
|
return result;
|
|
25796
26314
|
} catch (err) {
|
|
25797
26315
|
const wse = err instanceof AgentError ? err : toWrongStackError(err);
|
|
25798
|
-
|
|
26316
|
+
const safeError = err instanceof Error ? new Error(err.message) : new Error(String(err));
|
|
26317
|
+
this.events.emit("error", { err: safeError, phase: "agent", _original: err instanceof Error ? err : void 0 });
|
|
25799
26318
|
if (err instanceof Error) span?.recordError(err);
|
|
25800
26319
|
span?.setAttribute("agent.status", "failed");
|
|
25801
26320
|
const result = {
|
|
@@ -26071,12 +26590,14 @@ async function bootConfig(options = {}) {
|
|
|
26071
26590
|
const cwd = typeof flags["cwd"] === "string" ? path6.resolve(flags["cwd"]) : process.cwd();
|
|
26072
26591
|
const pathResolver = new DefaultPathResolver(cwd);
|
|
26073
26592
|
const projectRoot = pathResolver.projectRoot;
|
|
26074
|
-
const userHome =
|
|
26593
|
+
const userHome = os7.homedir();
|
|
26075
26594
|
const wpaths = resolveWstackPaths({ projectRoot, userHome });
|
|
26076
26595
|
await fsp3.mkdir(wpaths.globalRoot, { recursive: true });
|
|
26077
26596
|
await fsp3.mkdir(wpaths.projectDir, { recursive: true });
|
|
26078
26597
|
await fsp3.mkdir(wpaths.projectSessions, { recursive: true });
|
|
26079
26598
|
await writeProjectMeta(wpaths, projectRoot);
|
|
26599
|
+
cleanupStaleProjects(wpaths).catch(() => {
|
|
26600
|
+
});
|
|
26080
26601
|
const vault = new DefaultSecretVault({ keyFile: wpaths.secretsKey });
|
|
26081
26602
|
for (const file of [wpaths.globalConfig, wpaths.projectLocalConfig]) {
|
|
26082
26603
|
try {
|
|
@@ -26142,6 +26663,7 @@ async function writeProjectMeta(paths, projectRoot) {
|
|
|
26142
26663
|
await fsp3.mkdir(paths.projectDir, { recursive: true });
|
|
26143
26664
|
const meta = {
|
|
26144
26665
|
hash: paths.projectHash,
|
|
26666
|
+
slug: paths.projectSlug,
|
|
26145
26667
|
root: projectRoot,
|
|
26146
26668
|
lastSeen: (/* @__PURE__ */ new Date()).toISOString()
|
|
26147
26669
|
};
|
|
@@ -26149,6 +26671,31 @@ async function writeProjectMeta(paths, projectRoot) {
|
|
|
26149
26671
|
} catch {
|
|
26150
26672
|
}
|
|
26151
26673
|
}
|
|
26674
|
+
async function cleanupStaleProjects(wpaths) {
|
|
26675
|
+
const projectsRoot = path6.dirname(wpaths.projectDir);
|
|
26676
|
+
let entries;
|
|
26677
|
+
try {
|
|
26678
|
+
entries = await fsp3.readdir(projectsRoot, { withFileTypes: true });
|
|
26679
|
+
} catch {
|
|
26680
|
+
return;
|
|
26681
|
+
}
|
|
26682
|
+
for (const entry of entries) {
|
|
26683
|
+
if (!entry.isDirectory()) continue;
|
|
26684
|
+
const metaPath = path6.join(projectsRoot, entry.name, "meta.json");
|
|
26685
|
+
try {
|
|
26686
|
+
const raw = await fsp3.readFile(metaPath, "utf8");
|
|
26687
|
+
const meta = JSON.parse(raw);
|
|
26688
|
+
if (typeof meta.root === "string") {
|
|
26689
|
+
try {
|
|
26690
|
+
await fsp3.access(meta.root);
|
|
26691
|
+
} catch {
|
|
26692
|
+
await fsp3.rm(path6.join(projectsRoot, entry.name), { recursive: true, force: true });
|
|
26693
|
+
}
|
|
26694
|
+
}
|
|
26695
|
+
} catch {
|
|
26696
|
+
}
|
|
26697
|
+
}
|
|
26698
|
+
}
|
|
26152
26699
|
|
|
26153
26700
|
// src/core/conversation-state.ts
|
|
26154
26701
|
var ConversationState = class {
|
|
@@ -26187,9 +26734,11 @@ var ConversationState = class {
|
|
|
26187
26734
|
this.emit({ kind: "messages_replaced", messages: [...messages] });
|
|
26188
26735
|
}
|
|
26189
26736
|
replaceTodos(todos) {
|
|
26737
|
+
const allDone = todos.length > 0 && todos.every((t2) => t2.status === "completed");
|
|
26738
|
+
const effective = allDone ? [] : todos;
|
|
26190
26739
|
this.ctx.todos.length = 0;
|
|
26191
|
-
this.ctx.todos.splice(0, 0, ...
|
|
26192
|
-
this.emit({ kind: "todos_replaced", todos: [...
|
|
26740
|
+
this.ctx.todos.splice(0, 0, ...effective);
|
|
26741
|
+
this.emit({ kind: "todos_replaced", todos: [...effective] });
|
|
26193
26742
|
}
|
|
26194
26743
|
setMeta(key, value) {
|
|
26195
26744
|
this.ctx.meta[key] = value;
|
|
@@ -26813,7 +27362,7 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
26813
27362
|
const cached = this.envCacheByRoot.get(ctx.projectRoot);
|
|
26814
27363
|
if (cached) return cached;
|
|
26815
27364
|
const today = this.opts.todayIso ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
26816
|
-
const platform2 = `${
|
|
27365
|
+
const platform2 = `${os7.platform()} ${os7.release()}`;
|
|
26817
27366
|
const shell = process.env.SHELL ?? process.env.ComSpec ?? "unknown";
|
|
26818
27367
|
const node = process.version;
|
|
26819
27368
|
const isGit = await this.dirExists(path6.join(ctx.projectRoot, ".git"));
|
|
@@ -27752,6 +28301,104 @@ function wrapApiForCapabilityCheck(plugin, api, log, enforce = false) {
|
|
|
27752
28301
|
});
|
|
27753
28302
|
}
|
|
27754
28303
|
|
|
28304
|
+
// src/execution/prompt-enhancer.ts
|
|
28305
|
+
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 a single, clearer, unambiguous instruction that the coding agent can act on confidently.
|
|
28306
|
+
|
|
28307
|
+
Rules:
|
|
28308
|
+
- 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.
|
|
28309
|
+
- Do NOT answer, solve, or perform the request. Only restate it more clearly.
|
|
28310
|
+
- Keep all concrete details verbatim: file paths, identifiers, code, error text, numbers, names, URLs.
|
|
28311
|
+
- Resolve obvious ambiguity by making the implied subject explicit, not by inventing specifics. If something is genuinely unspecified, leave it general rather than guessing.
|
|
28312
|
+
- Be concise: one tight instruction (a few sentences at most). No preamble, no explanation, no quotes, no markdown headers.
|
|
28313
|
+
- If the message is already clear and complete, return it essentially unchanged.
|
|
28314
|
+
- Preserve the user's language (if they wrote in Turkish, refine in Turkish).
|
|
28315
|
+
|
|
28316
|
+
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.
|
|
28317
|
+
|
|
28318
|
+
Output ONLY the refined request text \u2014 nothing else.`;
|
|
28319
|
+
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;
|
|
28320
|
+
function shouldEnhance(text) {
|
|
28321
|
+
const t2 = text.trim();
|
|
28322
|
+
if (!t2) return false;
|
|
28323
|
+
if (t2.startsWith("/")) return false;
|
|
28324
|
+
if (t2.length < 12) return false;
|
|
28325
|
+
if (AFFIRMATION_RE.test(t2)) return false;
|
|
28326
|
+
if (/^[\d\s.,]+$/.test(t2)) return false;
|
|
28327
|
+
const words = t2.split(/\s+/).filter(Boolean);
|
|
28328
|
+
if (words.length < 3) return false;
|
|
28329
|
+
return true;
|
|
28330
|
+
}
|
|
28331
|
+
function normalizedEqual(a, b) {
|
|
28332
|
+
const norm = (s) => s.trim().replace(/\s+/g, " ").toLowerCase();
|
|
28333
|
+
return norm(a) === norm(b);
|
|
28334
|
+
}
|
|
28335
|
+
function buildRefinerInput(text, history) {
|
|
28336
|
+
if (!history || history.length === 0) return text;
|
|
28337
|
+
const lines = history.map((t2) => `${t2.role === "user" ? "User" : "Assistant"}: ${t2.text}`);
|
|
28338
|
+
return [
|
|
28339
|
+
"Recent conversation (context only \u2014 do not act on it):",
|
|
28340
|
+
...lines,
|
|
28341
|
+
"",
|
|
28342
|
+
"Latest message to refine:",
|
|
28343
|
+
text
|
|
28344
|
+
].join("\n");
|
|
28345
|
+
}
|
|
28346
|
+
async function enhanceUserPrompt(opts) {
|
|
28347
|
+
const { provider, model, text } = opts;
|
|
28348
|
+
const timeoutMs = opts.timeoutMs ?? 9e4;
|
|
28349
|
+
const maxTokens = opts.maxTokens ?? 2048;
|
|
28350
|
+
const req = {
|
|
28351
|
+
model,
|
|
28352
|
+
system: [{ type: "text", text: ENHANCER_SYSTEM_PROMPT }],
|
|
28353
|
+
messages: [{ role: "user", content: buildRefinerInput(text, opts.history) }],
|
|
28354
|
+
maxTokens
|
|
28355
|
+
// NOTE: deliberately NO `temperature`. The main agent loop never sets it,
|
|
28356
|
+
// and reasoning models (DeepSeek reasoner, o1/o3, …) return HTTP 400 when
|
|
28357
|
+
// `temperature` is present — which would make every refine call fail and
|
|
28358
|
+
// silently fall back to the original (no panel shown).
|
|
28359
|
+
};
|
|
28360
|
+
const timer = new AbortController();
|
|
28361
|
+
const to = setTimeout(() => timer.abort(new Error("enhancer timeout")), timeoutMs);
|
|
28362
|
+
const signal = opts.signal ? AbortSignal.any([opts.signal, timer.signal]) : timer.signal;
|
|
28363
|
+
try {
|
|
28364
|
+
const res = await provider.complete(req, { signal });
|
|
28365
|
+
const refined = res.content.filter(isTextBlock).map((b) => b.text).join("\n").trim();
|
|
28366
|
+
if (!refined) {
|
|
28367
|
+
opts.onError?.("model returned no text");
|
|
28368
|
+
return null;
|
|
28369
|
+
}
|
|
28370
|
+
return refined;
|
|
28371
|
+
} catch (err) {
|
|
28372
|
+
if (opts.signal?.aborted) return null;
|
|
28373
|
+
if (timer.signal.aborted) {
|
|
28374
|
+
opts.onError?.(`timed out after ${Math.round(timeoutMs / 1e3)}s`);
|
|
28375
|
+
return null;
|
|
28376
|
+
}
|
|
28377
|
+
opts.onError?.(err instanceof Error ? err.message : String(err));
|
|
28378
|
+
return null;
|
|
28379
|
+
} finally {
|
|
28380
|
+
clearTimeout(to);
|
|
28381
|
+
}
|
|
28382
|
+
}
|
|
28383
|
+
function messageText(content) {
|
|
28384
|
+
if (typeof content === "string") return content;
|
|
28385
|
+
return content.filter(isTextBlock).map((b) => b.text).join("\n").trim();
|
|
28386
|
+
}
|
|
28387
|
+
function recentTextTurns(messages, maxTurns = 6, maxChars = 1500) {
|
|
28388
|
+
const turns = [];
|
|
28389
|
+
for (let i = messages.length - 1; i >= 0 && turns.length < maxTurns; i--) {
|
|
28390
|
+
const m = messages[i];
|
|
28391
|
+
if (!m || m.role !== "user" && m.role !== "assistant") continue;
|
|
28392
|
+
const text = messageText(m.content);
|
|
28393
|
+
if (!text) continue;
|
|
28394
|
+
turns.unshift({
|
|
28395
|
+
role: m.role,
|
|
28396
|
+
text: text.length > maxChars ? `${text.slice(0, maxChars - 1)}\u2026` : text
|
|
28397
|
+
});
|
|
28398
|
+
}
|
|
28399
|
+
return turns;
|
|
28400
|
+
}
|
|
28401
|
+
|
|
27755
28402
|
// src/autophase/phase-graph-builder.ts
|
|
27756
28403
|
var PhaseGraphBuilder = class _PhaseGraphBuilder {
|
|
27757
28404
|
constructor(opts) {
|
|
@@ -27763,7 +28410,7 @@ var PhaseGraphBuilder = class _PhaseGraphBuilder {
|
|
|
27763
28410
|
const phases = /* @__PURE__ */ new Map();
|
|
27764
28411
|
const phaseIds = [];
|
|
27765
28412
|
for (let i = 0; i < this.opts.phases.length; i++) {
|
|
27766
|
-
const tmpl = this.opts.phases[i];
|
|
28413
|
+
const tmpl = this.opts.phases[i] ?? { name: "", description: "", taskTemplates: [], parallelizable: false, priority: "medium", estimateHours: 0 };
|
|
27767
28414
|
const phaseId = crypto.randomUUID();
|
|
27768
28415
|
phaseIds.push(phaseId);
|
|
27769
28416
|
const store = this.opts.externalTaskStore ?? new DefaultTaskStore();
|
|
@@ -27788,8 +28435,8 @@ var PhaseGraphBuilder = class _PhaseGraphBuilder {
|
|
|
27788
28435
|
description: tmpl.description,
|
|
27789
28436
|
status: "pending",
|
|
27790
28437
|
taskGraph,
|
|
27791
|
-
dependsOn: i > 0 ? [phaseIds[i - 1]] : [],
|
|
27792
|
-
nextPhases: i < this.opts.phases.length - 1 ? [phaseIds[i + 1]] : [],
|
|
28438
|
+
dependsOn: i > 0 ? [phaseIds[i - 1] ?? ""] : [],
|
|
28439
|
+
nextPhases: i < this.opts.phases.length - 1 ? [phaseIds[i + 1] ?? ""] : [],
|
|
27793
28440
|
parallelizable: tmpl.parallelizable,
|
|
27794
28441
|
priority: tmpl.priority,
|
|
27795
28442
|
estimateHours: tmpl.estimateHours,
|
|
@@ -27802,15 +28449,16 @@ var PhaseGraphBuilder = class _PhaseGraphBuilder {
|
|
|
27802
28449
|
const phaseArray = Array.from(phases.values());
|
|
27803
28450
|
for (let i = 0; i < phaseArray.length; i++) {
|
|
27804
28451
|
const phase = phaseArray[i];
|
|
27805
|
-
phase
|
|
27806
|
-
phase.
|
|
28452
|
+
if (!phase) continue;
|
|
28453
|
+
phase.nextPhases = i < phaseArray.length - 1 ? [phaseArray[i + 1]?.id ?? ""] : [];
|
|
28454
|
+
phase.dependsOn = i > 0 ? [phaseArray[i - 1]?.id ?? ""] : [];
|
|
27807
28455
|
}
|
|
27808
28456
|
const graph = {
|
|
27809
28457
|
id: graphId,
|
|
27810
28458
|
title: this.opts.title,
|
|
27811
28459
|
description: this.opts.description ?? "",
|
|
27812
28460
|
phases,
|
|
27813
|
-
rootPhaseIds: phaseIds.length > 0 ? [phaseIds[0]] : [],
|
|
28461
|
+
rootPhaseIds: phaseIds.length > 0 ? [phaseIds[0] ?? ""] : [],
|
|
27814
28462
|
activePhaseIds: [],
|
|
27815
28463
|
completedPhaseIds: [],
|
|
27816
28464
|
failedPhaseIds: [],
|
|
@@ -27992,7 +28640,7 @@ var PhaseOrchestrator = class {
|
|
|
27992
28640
|
return;
|
|
27993
28641
|
}
|
|
27994
28642
|
if (this.opts.stopOnFailure && this.graph.failedPhaseIds.length > 0) {
|
|
27995
|
-
const failedPhase = this.graph.phases.get(this.graph.failedPhaseIds[0]);
|
|
28643
|
+
const failedPhase = this.graph.phases.get(this.graph.failedPhaseIds[0] ?? "");
|
|
27996
28644
|
if (failedPhase) {
|
|
27997
28645
|
this.onGraphFailed(failedPhase);
|
|
27998
28646
|
}
|
|
@@ -28168,9 +28816,14 @@ var PhaseOrchestrator = class {
|
|
|
28168
28816
|
name: phase.name,
|
|
28169
28817
|
files: info.conflictFiles
|
|
28170
28818
|
});
|
|
28171
|
-
|
|
28819
|
+
const resolved = await this.ctx.resolveConflict?.(phase, info);
|
|
28820
|
+
return resolved ?? false;
|
|
28172
28821
|
} : void 0;
|
|
28173
|
-
const
|
|
28822
|
+
const mergeOpts = {
|
|
28823
|
+
squash: true
|
|
28824
|
+
};
|
|
28825
|
+
if (resolve13 !== void 0) mergeOpts.resolve = resolve13;
|
|
28826
|
+
const result = await this.worktrees.merge(handle, mergeOpts);
|
|
28174
28827
|
if (result.resolved) {
|
|
28175
28828
|
this.emit("phase.conflictResolved", { phaseId: phase.id, name: phase.name });
|
|
28176
28829
|
}
|
|
@@ -28564,9 +29217,6 @@ var AutoPhaseRunner = class {
|
|
|
28564
29217
|
this.graph = await builder.build();
|
|
28565
29218
|
const ctx = {
|
|
28566
29219
|
executeTask: this.opts.executeTask,
|
|
28567
|
-
verifyPhase: this.opts.verifyPhase,
|
|
28568
|
-
repairPhase: this.opts.repairPhase,
|
|
28569
|
-
resolveConflict: this.opts.resolveConflict,
|
|
28570
29220
|
brain: this.opts.brain,
|
|
28571
29221
|
onPhaseComplete: (phase) => {
|
|
28572
29222
|
this.opts.onPhaseComplete?.(phase);
|
|
@@ -28578,6 +29228,9 @@ var AutoPhaseRunner = class {
|
|
|
28578
29228
|
this.opts.onTick?.(tickCtx);
|
|
28579
29229
|
}
|
|
28580
29230
|
};
|
|
29231
|
+
if (this.opts.verifyPhase !== void 0) ctx.verifyPhase = this.opts.verifyPhase;
|
|
29232
|
+
if (this.opts.repairPhase !== void 0) ctx.repairPhase = this.opts.repairPhase;
|
|
29233
|
+
if (this.opts.resolveConflict !== void 0) ctx.resolveConflict = this.opts.resolveConflict;
|
|
28581
29234
|
this.orchestrator = new PhaseOrchestrator({
|
|
28582
29235
|
graph: this.graph,
|
|
28583
29236
|
ctx,
|
|
@@ -28593,8 +29246,8 @@ var AutoPhaseRunner = class {
|
|
|
28593
29246
|
});
|
|
28594
29247
|
if (this.opts.onProgress) {
|
|
28595
29248
|
this.progressInterval = setInterval(() => {
|
|
28596
|
-
const progress = this.orchestrator
|
|
28597
|
-
this.opts.onProgress(progress);
|
|
29249
|
+
const progress = this.orchestrator?.getProgress();
|
|
29250
|
+
if (progress) this.opts.onProgress?.(progress);
|
|
28598
29251
|
}, 2e3);
|
|
28599
29252
|
}
|
|
28600
29253
|
if (this.opts.events) {
|
|
@@ -28814,7 +29467,7 @@ function firstBalancedArray(text) {
|
|
|
28814
29467
|
let inString = false;
|
|
28815
29468
|
let escaped = false;
|
|
28816
29469
|
for (let i = start; i < text.length; i++) {
|
|
28817
|
-
const ch = text[i];
|
|
29470
|
+
const ch = text[i] ?? "";
|
|
28818
29471
|
if (inString) {
|
|
28819
29472
|
if (escaped) {
|
|
28820
29473
|
escaped = false;
|
|
@@ -29324,7 +29977,7 @@ ${merged.stderr}`);
|
|
|
29324
29977
|
async tryResolveConflict(handle, conflictFiles, opts) {
|
|
29325
29978
|
let resolved = false;
|
|
29326
29979
|
try {
|
|
29327
|
-
resolved = await opts.resolve({ conflictFiles, cwd: this.projectRoot });
|
|
29980
|
+
resolved = opts.resolve ? await opts.resolve({ conflictFiles, cwd: this.projectRoot }) : false;
|
|
29328
29981
|
} catch {
|
|
29329
29982
|
resolved = false;
|
|
29330
29983
|
}
|
|
@@ -29847,6 +30500,12 @@ var ReplayProviderRunner = class {
|
|
|
29847
30500
|
};
|
|
29848
30501
|
|
|
29849
30502
|
// src/plugins/prompts-plugin.ts
|
|
30503
|
+
function expectDefined25(value) {
|
|
30504
|
+
if (value === null || value === void 0) {
|
|
30505
|
+
throw new Error("Expected value to be defined");
|
|
30506
|
+
}
|
|
30507
|
+
return value;
|
|
30508
|
+
}
|
|
29850
30509
|
function createPromptsPlugin(opts) {
|
|
29851
30510
|
let store = null;
|
|
29852
30511
|
return {
|
|
@@ -29900,7 +30559,7 @@ ${lines.join("\n")}
|
|
|
29900
30559
|
if (!restJoined) return { message: "Usage: /prompts view <title>" };
|
|
29901
30560
|
const matches = await store.find(restJoined);
|
|
29902
30561
|
if (matches.length === 0) return { message: `No prompt matching "${restJoined}".` };
|
|
29903
|
-
const entry = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? matches[0];
|
|
30562
|
+
const entry = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? expectDefined25(matches[0]);
|
|
29904
30563
|
const tags = entry.tags.length > 0 ? ` [${entry.tags.join(", ")}]` : "";
|
|
29905
30564
|
return {
|
|
29906
30565
|
message: `# ${entry.title}${tags}
|
|
@@ -29923,7 +30582,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
29923
30582
|
if (!restJoined) return { message: "Usage: /prompts delete <title>" };
|
|
29924
30583
|
const matches = await store.find(restJoined);
|
|
29925
30584
|
if (matches.length === 0) return { message: `No prompt matching "${restJoined}".` };
|
|
29926
|
-
const exact = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? matches[0];
|
|
30585
|
+
const exact = matches.find((m) => m.title.toLowerCase() === restJoined.toLowerCase()) ?? expectDefined25(matches[0]);
|
|
29927
30586
|
const deleted = await store.delete(exact.id);
|
|
29928
30587
|
return { message: deleted ? `Deleted "${exact.title}".` : "Delete failed." };
|
|
29929
30588
|
}
|
|
@@ -29933,7 +30592,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
29933
30592
|
if (!parsed.title) return { message: 'Usage: /prompts edit "title" "new content"' };
|
|
29934
30593
|
const matches = await store.find(parsed.title);
|
|
29935
30594
|
if (matches.length === 0) return { message: `No prompt matching "${parsed.title}".` };
|
|
29936
|
-
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title
|
|
30595
|
+
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ?? expectDefined25(matches[0]);
|
|
29937
30596
|
exact.content = parsed.content;
|
|
29938
30597
|
exact.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
29939
30598
|
await store.save(exact);
|
|
@@ -29945,7 +30604,7 @@ ${dim2(`id: ${entry.id} | created: ${entry.createdAt}`)}`
|
|
|
29945
30604
|
if (!parsed.title) return { message: 'Usage: /prompts extend "title" <instructions>' };
|
|
29946
30605
|
const matches = await store.find(parsed.title);
|
|
29947
30606
|
if (matches.length === 0) return { message: `No prompt matching "${parsed.title}".` };
|
|
29948
|
-
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title
|
|
30607
|
+
const exact = matches.find((m) => m.title.toLowerCase() === parsed.title?.toLowerCase()) ?? expectDefined25(matches[0]);
|
|
29949
30608
|
const prov = ctx.provider;
|
|
29950
30609
|
if (!prov?.complete) return { message: "LLM not available. Configure a provider first." };
|
|
29951
30610
|
const enhanced = await prov.complete(ctx.model, [
|
|
@@ -29980,9 +30639,9 @@ function parseTitleContent(args) {
|
|
|
29980
30639
|
const trimmed = args.trim();
|
|
29981
30640
|
if (!trimmed) return { title: "", content: "" };
|
|
29982
30641
|
const doubleMatch = /^"([^"]+)"\s+"([^"]+)"$/.exec(trimmed) || /^'([^']+)'\s+'([^']+)'$/.exec(trimmed);
|
|
29983
|
-
if (doubleMatch) return { title: doubleMatch[1], content: doubleMatch[2] };
|
|
30642
|
+
if (doubleMatch) return { title: expectDefined25(doubleMatch[1]), content: expectDefined25(doubleMatch[2]) };
|
|
29984
30643
|
const singleMatch = /^'([^']+)'\s+(.+)$/.exec(trimmed);
|
|
29985
|
-
if (singleMatch) return { title: singleMatch[1], content: singleMatch[2] };
|
|
30644
|
+
if (singleMatch) return { title: expectDefined25(singleMatch[1]), content: expectDefined25(singleMatch[2]) };
|
|
29986
30645
|
const firstSpace = trimmed.indexOf(" ");
|
|
29987
30646
|
if (firstSpace === -1) return { title: trimmed, content: "" };
|
|
29988
30647
|
return { title: trimmed.slice(0, firstSpace), content: trimmed.slice(firstSpace + 1) };
|
|
@@ -29993,6 +30652,12 @@ function dim2(s) {
|
|
|
29993
30652
|
|
|
29994
30653
|
// src/plugins/sync-plugin.ts
|
|
29995
30654
|
init_atomic_write();
|
|
30655
|
+
function expectDefined26(value) {
|
|
30656
|
+
if (value === null || value === void 0) {
|
|
30657
|
+
throw new Error("Expected value to be defined");
|
|
30658
|
+
}
|
|
30659
|
+
return value;
|
|
30660
|
+
}
|
|
29996
30661
|
function createSyncPlugin(opts) {
|
|
29997
30662
|
let cloud = null;
|
|
29998
30663
|
let configStore;
|
|
@@ -30018,11 +30683,11 @@ function createSyncPlugin(opts) {
|
|
|
30018
30683
|
cloud = new CloudSync(
|
|
30019
30684
|
paths,
|
|
30020
30685
|
() => {
|
|
30021
|
-
const cfg = configStore
|
|
30686
|
+
const cfg = configStore?.get();
|
|
30022
30687
|
return cfg.sync;
|
|
30023
30688
|
},
|
|
30024
30689
|
async (cfg) => {
|
|
30025
|
-
configStore
|
|
30690
|
+
configStore?.update({ sync: cfg });
|
|
30026
30691
|
}
|
|
30027
30692
|
);
|
|
30028
30693
|
void cloud.loadState();
|
|
@@ -30066,7 +30731,7 @@ function buildSyncCommand(cloud, configStore, vault, syncConfigPath) {
|
|
|
30066
30731
|
if (!repo || !repo.includes("/")) {
|
|
30067
30732
|
return { message: 'Invalid repo format. Expected "owner/repo".' };
|
|
30068
30733
|
}
|
|
30069
|
-
const storedToken = vault ? vault.encrypt(token) : token;
|
|
30734
|
+
const storedToken = vault ? vault.encrypt(expectDefined26(token)) : expectDefined26(token);
|
|
30070
30735
|
const syncConfig = {
|
|
30071
30736
|
enabled: true,
|
|
30072
30737
|
repo,
|
|
@@ -30306,7 +30971,7 @@ async function generateCommitMessageHeuristics(cwd) {
|
|
|
30306
30971
|
const commitType = detectCommitType(statsResult.stdout);
|
|
30307
30972
|
let scope = "";
|
|
30308
30973
|
if (files.length > 0) {
|
|
30309
|
-
const primary = files[0]
|
|
30974
|
+
const primary = files[0]?.split("/")[0];
|
|
30310
30975
|
if (primary && primary !== "packages" && primary !== "apps" && primary !== "node_modules") {
|
|
30311
30976
|
scope = `(${primary})`;
|
|
30312
30977
|
}
|
|
@@ -30552,7 +31217,7 @@ function createSkillsPlugin(opts) {
|
|
|
30552
31217
|
};
|
|
30553
31218
|
}
|
|
30554
31219
|
function makeInstaller(skillLoader, projectRoot) {
|
|
30555
|
-
const globalRoot = path6.join(
|
|
31220
|
+
const globalRoot = path6.join(os7.homedir(), ".wrongstack");
|
|
30556
31221
|
return new SkillInstaller({
|
|
30557
31222
|
manifestPath: path6.join(globalRoot, "installed-skills.json"),
|
|
30558
31223
|
projectSkillsDir: path6.join(projectRoot, ".wrongstack", "skills"),
|
|
@@ -30903,6 +31568,6 @@ ${formatPlan(updated)}`
|
|
|
30903
31568
|
};
|
|
30904
31569
|
}
|
|
30905
31570
|
|
|
30906
|
-
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_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, 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, ensureDir, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, 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, 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, onResize, parseContinueDirective, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, recordActualUsage, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setPlanItemStatus, setRawMode, slackServer, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState, writeErr, writeOut, zaiVisionServer };
|
|
31571
|
+
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_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, extractRunEnv, filesystemServer, findCriticalPath, flagsToConfigPatch, formatContextWindowModeList, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, 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, 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, parseSkillRef, pendingBtwCount, phaseForRole, projectHash, projectSlug, recentTextTurns, recordActualUsage, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, resetCalibration, resolveAuditLevel, resolveContextWindowPolicy, resolveModelMatrix, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTodosCheckpoint, scoreAgents, securitySlashCommand, sentinelServer, setBtwNote, setOutputLineGuard, setPlanItemStatus, setRawMode, shouldEnhance, slackServer, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, stripAnsi, summarizeUsage, templateToMarkdown, toStyle, toWrongStackError, topologicalSort, unifiedDiff, unloadPlugins, validateAgainstSchema, wireMetricsToEvents, wrapAsState, writeErr, writeOut, zaiVisionServer };
|
|
30907
31572
|
//# sourceMappingURL=index.js.map
|
|
30908
31573
|
//# sourceMappingURL=index.js.map
|