@wrongstack/core 0.270.0 → 0.272.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-bridge-PcHQl_UQ.d.ts → agent-bridge-jVSZiygR.d.ts} +1 -1
- package/dist/{agent-subagent-runner-SHJW7t8q.d.ts → agent-subagent-runner-DOLIwBRo.d.ts} +7 -7
- package/dist/{brain-BYcK__Ym.d.ts → brain-CdbbJWi3.d.ts} +71 -1
- package/dist/{compactor-C2RKEBtC.d.ts → compactor-72ug-ZRB.d.ts} +1 -1
- package/dist/{config-C_ae2k86.d.ts → config-D2DGoGSQ.d.ts} +29 -2
- package/dist/{context-Dp87Bcaq.d.ts → context-Dw55zZ_Q.d.ts} +110 -1
- package/dist/coordination/index.d.ts +121 -17
- package/dist/coordination/index.js +738 -74
- package/dist/coordination/index.js.map +1 -1
- package/dist/defaults/index.d.ts +25 -25
- package/dist/defaults/index.js +599 -86
- package/dist/defaults/index.js.map +1 -1
- package/dist/execution/index.d.ts +23 -18
- package/dist/execution/index.js +136 -41
- package/dist/execution/index.js.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +36 -6
- package/dist/execution/prompt-enhancer.js +35 -9
- package/dist/execution/prompt-enhancer.js.map +1 -1
- package/dist/extension/index.d.ts +6 -6
- package/dist/{global-mailbox-Bvrz1P3f.d.ts → global-mailbox-CQj_C9Dp.d.ts} +139 -3
- package/dist/{goal-preamble-CA_4yiGQ.d.ts → goal-preamble-ZXDjjR1y.d.ts} +9 -9
- package/dist/{goal-store-DhuJoUNG.d.ts → goal-store-CcJBd-g1.d.ts} +1 -1
- package/dist/hq/index.d.ts +93 -6
- package/dist/hq/index.js +616 -46
- package/dist/hq/index.js.map +1 -1
- package/dist/{index-whDfTANu.d.ts → index-2Lhk5v0o.d.ts} +2 -2
- package/dist/{index-CZQ6Pwbs.d.ts → index-BL7BAx0p.d.ts} +8 -8
- package/dist/{index-W4VJCzHa.d.ts → index-Qo4kTzgw.d.ts} +5 -5
- package/dist/index.d.ts +96 -56
- package/dist/index.js +1938 -349
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/index.d.ts +6 -6
- package/dist/infrastructure/index.js +5 -3
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/kernel/index.d.ts +9 -9
- package/dist/kernel/index.js.map +1 -1
- package/dist/{mcp-servers-DJdZiRcv.d.ts → mcp-servers-DS-YUXvF.d.ts} +3 -3
- package/dist/models/index.d.ts +5 -5
- package/dist/models/index.js +28 -5
- package/dist/models/index.js.map +1 -1
- package/dist/{models-registry-C3a-2-Yd.d.ts → models-registry-DP6pGHet.d.ts} +1 -1
- package/dist/{multi-agent-coordinator-CJSpTe5O.d.ts → multi-agent-coordinator-BvbdNQ14.d.ts} +1 -1
- package/dist/{null-fleet-bus-QVshIsDx.d.ts → null-fleet-bus-BxTfXBKo.d.ts} +6 -6
- package/dist/observability/index.d.ts +2 -2
- package/dist/{parallel-eternal-engine-D9y5Pkcc.d.ts → parallel-eternal-engine-Cf-GTegR.d.ts} +9 -9
- package/dist/{path-resolver-CnQ8SIfh.d.ts → path-resolver-DztfnFcv.d.ts} +3 -3
- package/dist/{permission-CvYQNUqZ.d.ts → permission-CC7XFYWG.d.ts} +1 -1
- package/dist/{permission-policy-D5Ss8j4B.d.ts → permission-policy-cYR4RJmw.d.ts} +2 -2
- package/dist/{pipeline-l_zzFRh3.d.ts → pipeline-sNIkhXeB.d.ts} +2 -2
- package/dist/{plan-templates-NtPgyeJA.d.ts → plan-templates-DYiKFmEb.d.ts} +11 -5
- package/dist/{provider-model-resolve-d5poT5y0.d.ts → provider-model-resolve-dYAbTs_i.d.ts} +3 -3
- package/dist/{provider-runner-gkctlQV_.d.ts → provider-runner-Dw8x0F7u.d.ts} +3 -3
- package/dist/{retry-policy-CtFhfwa8.d.ts → retry-policy-BV7nzeAd.d.ts} +1 -1
- package/dist/sdd/index.d.ts +8 -8
- package/dist/sdd/index.js +2 -0
- package/dist/sdd/index.js.map +1 -1
- package/dist/{secret-vault-BLsVmTIK.d.ts → secret-vault-eMBKfheR.d.ts} +9 -1
- package/dist/security/index.d.ts +5 -5
- package/dist/security/index.js +137 -10
- package/dist/security/index.js.map +1 -1
- package/dist/{selector-CXl2_y9W.d.ts → selector-C4ORTOid.d.ts} +1 -1
- package/dist/{session-event-bridge-Ccud20CC.d.ts → session-event-bridge-CeNpUL9w.d.ts} +1 -1
- package/dist/{session-reader-ZeXQmsmE.d.ts → session-reader-BepLSnGL.d.ts} +1 -1
- package/dist/storage/index.d.ts +45 -13
- package/dist/storage/index.js +374 -113
- package/dist/storage/index.js.map +1 -1
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +9 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/index.js +202 -41
- package/dist/types/index.js.map +1 -1
- package/dist/utils/index.d.ts +17 -4
- package/dist/utils/index.js +48 -9
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as crypto2 from 'crypto';
|
|
2
|
-
import { randomBytes, randomUUID, createHash, createCipheriv, createDecipheriv } from 'crypto';
|
|
2
|
+
import { randomBytes, randomUUID, createHash, createCipheriv, createDecipheriv, scryptSync } from 'crypto';
|
|
3
3
|
import * as fsp3 from 'fs/promises';
|
|
4
4
|
import { readFile, readdir, stat, mkdir } from 'fs/promises';
|
|
5
5
|
import * as path3 from 'path';
|
|
@@ -9,6 +9,8 @@ import * as net from 'net';
|
|
|
9
9
|
import * as os6 from 'os';
|
|
10
10
|
import { hostname } from 'os';
|
|
11
11
|
import * as fs3 from 'fs';
|
|
12
|
+
import { createReadStream } from 'fs';
|
|
13
|
+
import { createInterface } from 'readline';
|
|
12
14
|
import { execFile, spawn } from 'child_process';
|
|
13
15
|
import { promisify } from 'util';
|
|
14
16
|
import { EventEmitter } from 'events';
|
|
@@ -59,8 +61,8 @@ async function atomicWrite(targetPath, content, opts = {}) {
|
|
|
59
61
|
}
|
|
60
62
|
let mode;
|
|
61
63
|
try {
|
|
62
|
-
const
|
|
63
|
-
mode =
|
|
64
|
+
const stat16 = await fsp3.stat(targetPath);
|
|
65
|
+
mode = stat16.mode & 511;
|
|
64
66
|
} catch {
|
|
65
67
|
mode = opts.mode;
|
|
66
68
|
}
|
|
@@ -100,8 +102,8 @@ async function withFileLock(targetPath, fn, opts = {}) {
|
|
|
100
102
|
}
|
|
101
103
|
if (code !== "EEXIST") throw err;
|
|
102
104
|
try {
|
|
103
|
-
const
|
|
104
|
-
if (Date.now() -
|
|
105
|
+
const stat16 = await fsp3.stat(lockPath);
|
|
106
|
+
if (Date.now() - stat16.mtimeMs > staleMs) {
|
|
105
107
|
await fsp3.unlink(lockPath);
|
|
106
108
|
continue;
|
|
107
109
|
}
|
|
@@ -430,11 +432,11 @@ var init_session_registry = __esm({
|
|
|
430
432
|
*/
|
|
431
433
|
async breakStaleLock(lockPath) {
|
|
432
434
|
try {
|
|
433
|
-
const [
|
|
435
|
+
const [stat16, content] = await Promise.all([
|
|
434
436
|
fsp3.stat(lockPath),
|
|
435
437
|
fsp3.readFile(lockPath, "utf8").catch(() => "")
|
|
436
438
|
]);
|
|
437
|
-
const ageMs = Date.now() -
|
|
439
|
+
const ageMs = Date.now() - stat16.mtimeMs;
|
|
438
440
|
const ownerPid = Number.parseInt(content.trim(), 10);
|
|
439
441
|
const ownerDead = Number.isInteger(ownerPid) && ownerPid > 0 && ownerPid !== process.pid && !pidAlive(ownerPid);
|
|
440
442
|
if (ownerDead || ageMs > STALE_LOCK_MS) {
|
|
@@ -477,9 +479,9 @@ var init_session_registry = __esm({
|
|
|
477
479
|
for (const name of await fsp3.readdir(dir)) {
|
|
478
480
|
const isTemp = (name.startsWith(`${base}.`) || name.startsWith(`.${base}.`)) && name.endsWith(".tmp");
|
|
479
481
|
if (!isTemp) continue;
|
|
480
|
-
const
|
|
481
|
-
if (!
|
|
482
|
-
if (now -
|
|
482
|
+
const stat16 = await fsp3.stat(path3.join(dir, name)).catch(() => null);
|
|
483
|
+
if (!stat16) continue;
|
|
484
|
+
if (now - stat16.mtimeMs > STALE_TMP_MS) stale.push({ name, mtimeMs: stat16.mtimeMs });
|
|
483
485
|
}
|
|
484
486
|
stale.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
485
487
|
await Promise.all(
|
|
@@ -562,6 +564,25 @@ function looksSecret(name) {
|
|
|
562
564
|
}
|
|
563
565
|
return false;
|
|
564
566
|
}
|
|
567
|
+
function valueHasEmbeddedCredential(value) {
|
|
568
|
+
return /\b[a-z][a-z0-9+.-]*:\/\/[^/\s:@]*:[^/\s@]+@/i.test(value);
|
|
569
|
+
}
|
|
570
|
+
var NODE_OPTIONS_INJECTION_FLAG = /^(?:--require|-r|--import|--loader|--experimental-loader)$/;
|
|
571
|
+
var NODE_OPTIONS_INJECTION_FLAG_EQ = /^(?:--require|-r|--import|--loader|--experimental-loader)=/;
|
|
572
|
+
function sanitizeNodeOptions(value) {
|
|
573
|
+
const tokens = value.split(/\s+/).filter(Boolean);
|
|
574
|
+
const kept = [];
|
|
575
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
576
|
+
const tok = tokens[i];
|
|
577
|
+
if (NODE_OPTIONS_INJECTION_FLAG_EQ.test(tok)) continue;
|
|
578
|
+
if (NODE_OPTIONS_INJECTION_FLAG.test(tok)) {
|
|
579
|
+
i++;
|
|
580
|
+
continue;
|
|
581
|
+
}
|
|
582
|
+
kept.push(tok);
|
|
583
|
+
}
|
|
584
|
+
return kept.join(" ");
|
|
585
|
+
}
|
|
565
586
|
function buildChildEnv(optsOrSessionId) {
|
|
566
587
|
const opts = typeof optsOrSessionId === "string" ? { sessionId: optsOrSessionId } : optsOrSessionId ?? {};
|
|
567
588
|
const hasOwn = Object.hasOwn(process.env, "WRONGSTACK_CHILD_ENV_PASSTHROUGH");
|
|
@@ -582,11 +603,17 @@ function buildChildEnv(optsOrSessionId) {
|
|
|
582
603
|
continue;
|
|
583
604
|
}
|
|
584
605
|
const upper = k.toUpperCase();
|
|
606
|
+
if (valueHasEmbeddedCredential(v)) continue;
|
|
585
607
|
if (ALLOWED_KEYS.has(upper)) {
|
|
586
608
|
out[k] = v;
|
|
587
609
|
continue;
|
|
588
610
|
}
|
|
589
611
|
if (looksSecret(upper)) continue;
|
|
612
|
+
if (upper === "NODE_OPTIONS") {
|
|
613
|
+
const sanitized = sanitizeNodeOptions(v);
|
|
614
|
+
if (sanitized) out[k] = sanitized;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
590
617
|
if (upper.startsWith("NODE_") || upper.startsWith("NPM_") || upper.startsWith("PNPM_") || upper.startsWith("YARN_") || upper.startsWith("GIT_") || upper.startsWith("CI") || upper.startsWith("XDG_") || // Our own non-secret knobs (WRONGSTACK_HOME, WRONGSTACK_SESSION_ID, …).
|
|
591
618
|
// Secrets never live in WRONGSTACK_* env vars (they're in the encrypted
|
|
592
619
|
// vault). Forwarding keeps child wstack processes — e.g. ones spawned
|
|
@@ -676,7 +703,7 @@ function envFlag(value) {
|
|
|
676
703
|
return !/^(0|false|no|off)$/i.test(value.trim());
|
|
677
704
|
}
|
|
678
705
|
var COLOR = isColorTty();
|
|
679
|
-
var wrap = (
|
|
706
|
+
var wrap = (open10, close) => (s) => COLOR ? `\x1B[${open10}m${s}\x1B[${close}m` : s;
|
|
680
707
|
var color = {
|
|
681
708
|
reset: wrap("0", "0"),
|
|
682
709
|
bold: wrap("1", "22"),
|
|
@@ -727,9 +754,9 @@ async function updateJsonObjectFile(filePath, mutator) {
|
|
|
727
754
|
await writeJsonObjectFile(filePath, next);
|
|
728
755
|
return next;
|
|
729
756
|
}
|
|
730
|
-
function getJsonPath(root,
|
|
757
|
+
function getJsonPath(root, path50) {
|
|
731
758
|
let current = root;
|
|
732
|
-
for (const segment of
|
|
759
|
+
for (const segment of path50) {
|
|
733
760
|
if (typeof segment === "number") {
|
|
734
761
|
if (!Array.isArray(current)) return void 0;
|
|
735
762
|
current = current[segment];
|
|
@@ -740,13 +767,13 @@ function getJsonPath(root, path48) {
|
|
|
740
767
|
}
|
|
741
768
|
return current;
|
|
742
769
|
}
|
|
743
|
-
function setJsonPath(root,
|
|
744
|
-
if (
|
|
770
|
+
function setJsonPath(root, path50, value) {
|
|
771
|
+
if (path50.length === 0) {
|
|
745
772
|
if (!isJsonObject(value)) throw new Error("Root config value must be an object");
|
|
746
773
|
return value;
|
|
747
774
|
}
|
|
748
|
-
const parent = ensureJsonParent(root,
|
|
749
|
-
const leaf = lastPathSegment(
|
|
775
|
+
const parent = ensureJsonParent(root, path50);
|
|
776
|
+
const leaf = lastPathSegment(path50);
|
|
750
777
|
if (typeof leaf === "number") {
|
|
751
778
|
if (!Array.isArray(parent)) throw new Error(`Cannot set numeric segment ${leaf} on non-array parent`);
|
|
752
779
|
parent[leaf] = value;
|
|
@@ -756,10 +783,10 @@ function setJsonPath(root, path48, value) {
|
|
|
756
783
|
}
|
|
757
784
|
return root;
|
|
758
785
|
}
|
|
759
|
-
function removeJsonPath(root,
|
|
760
|
-
if (
|
|
761
|
-
const parent = getJsonPath(root,
|
|
762
|
-
const leaf = lastPathSegment(
|
|
786
|
+
function removeJsonPath(root, path50) {
|
|
787
|
+
if (path50.length === 0) return false;
|
|
788
|
+
const parent = getJsonPath(root, path50.slice(0, -1));
|
|
789
|
+
const leaf = lastPathSegment(path50);
|
|
763
790
|
if (typeof leaf === "number") {
|
|
764
791
|
if (!Array.isArray(parent) || leaf < 0 || leaf >= parent.length) return false;
|
|
765
792
|
parent.splice(leaf, 1);
|
|
@@ -769,27 +796,27 @@ function removeJsonPath(root, path48) {
|
|
|
769
796
|
delete parent[leaf];
|
|
770
797
|
return true;
|
|
771
798
|
}
|
|
772
|
-
async function setJsonPathInFile(filePath,
|
|
773
|
-
return updateJsonObjectFile(filePath, (config) => setJsonPath(config,
|
|
799
|
+
async function setJsonPathInFile(filePath, path50, value) {
|
|
800
|
+
return updateJsonObjectFile(filePath, (config) => setJsonPath(config, path50, value));
|
|
774
801
|
}
|
|
775
|
-
async function removeJsonPathInFile(filePath,
|
|
802
|
+
async function removeJsonPathInFile(filePath, path50) {
|
|
776
803
|
return updateJsonObjectFile(filePath, (config) => {
|
|
777
|
-
removeJsonPath(config,
|
|
804
|
+
removeJsonPath(config, path50);
|
|
778
805
|
});
|
|
779
806
|
}
|
|
780
807
|
function isJsonObject(value) {
|
|
781
808
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
782
809
|
}
|
|
783
|
-
function lastPathSegment(
|
|
784
|
-
const segment =
|
|
810
|
+
function lastPathSegment(path50) {
|
|
811
|
+
const segment = path50[path50.length - 1];
|
|
785
812
|
if (segment === void 0) throw new Error("Invalid empty JSON path");
|
|
786
813
|
return segment;
|
|
787
814
|
}
|
|
788
|
-
function ensureJsonParent(root,
|
|
815
|
+
function ensureJsonParent(root, path50) {
|
|
789
816
|
let current = root;
|
|
790
|
-
for (let i = 0; i <
|
|
791
|
-
const segment =
|
|
792
|
-
const nextSegment =
|
|
817
|
+
for (let i = 0; i < path50.length - 1; i += 1) {
|
|
818
|
+
const segment = path50[i];
|
|
819
|
+
const nextSegment = path50[i + 1];
|
|
793
820
|
if (segment === void 0) throw new Error("Invalid empty JSON path segment");
|
|
794
821
|
const nextContainer = typeof nextSegment === "number" ? [] : {};
|
|
795
822
|
if (typeof segment === "number") {
|
|
@@ -808,6 +835,9 @@ var MAX_TOOL_CALLS = 80;
|
|
|
808
835
|
var MAX_FACTS = 40;
|
|
809
836
|
var MAX_ERRORS = 20;
|
|
810
837
|
var MAX_DIGEST_CHARS = 4e3;
|
|
838
|
+
var RECENT_TOOL_CALL_SCAN_LIMIT = 20;
|
|
839
|
+
var EXTRACT_CONTENT_CAP_CHARS = 1e4;
|
|
840
|
+
var EXTRACT_ERROR_TAIL_LINES = 200;
|
|
811
841
|
var WRITE_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "replace", "patch"]);
|
|
812
842
|
var READ_TOOLS = /* @__PURE__ */ new Set(["read", "grep", "glob", "ls", "tree"]);
|
|
813
843
|
function createContextEvidenceState() {
|
|
@@ -833,8 +863,9 @@ function recordUserIntentEvidence(ctx, text) {
|
|
|
833
863
|
}
|
|
834
864
|
function recordToolOutputEvidence(ctx, input) {
|
|
835
865
|
const state = ensureEvidence(ctx);
|
|
836
|
-
const
|
|
837
|
-
const
|
|
866
|
+
const scanContent = input.content.length > EXTRACT_CONTENT_CAP_CHARS ? input.content.slice(0, EXTRACT_CONTENT_CAP_CHARS) : input.content;
|
|
867
|
+
const files = extractFiles(ctx, input.toolName, input.input, scanContent);
|
|
868
|
+
const symbols = extractSymbols(scanContent, input.input);
|
|
838
869
|
const commands = extractCommands(input.toolName, input.input);
|
|
839
870
|
const errors = extractErrors(input.content);
|
|
840
871
|
const summary = summarizeToolOutput(input.toolName, input.input, input.content, {
|
|
@@ -877,7 +908,8 @@ function markAssistantReferencedEvidence(ctx, text) {
|
|
|
877
908
|
const state = ensureEvidence(ctx);
|
|
878
909
|
const haystack = text.toLowerCase();
|
|
879
910
|
if (!haystack.trim()) return;
|
|
880
|
-
|
|
911
|
+
const recent = state.toolCalls.length > RECENT_TOOL_CALL_SCAN_LIMIT ? state.toolCalls.slice(-RECENT_TOOL_CALL_SCAN_LIMIT) : state.toolCalls;
|
|
912
|
+
for (const tool of recent) {
|
|
881
913
|
if (!metadataReferencedByText(tool, haystack)) continue;
|
|
882
914
|
tool.status = "referenced";
|
|
883
915
|
tool.referenceCount++;
|
|
@@ -1032,7 +1064,8 @@ function extractCommands(toolName, input) {
|
|
|
1032
1064
|
return [command.slice(0, 220)];
|
|
1033
1065
|
}
|
|
1034
1066
|
function extractErrors(content) {
|
|
1035
|
-
const
|
|
1067
|
+
const allLines = content.split(/\r?\n/);
|
|
1068
|
+
const lines = allLines.length > EXTRACT_ERROR_TAIL_LINES ? allLines.slice(-EXTRACT_ERROR_TAIL_LINES) : allLines;
|
|
1036
1069
|
const errors = [];
|
|
1037
1070
|
for (const line of lines) {
|
|
1038
1071
|
if (!/\b(error|exception|failed|failure|fatal|panic|timeout|denied|enoent|eacces|eperm|typeerror|syntaxerror)\b/i.test(line)) continue;
|
|
@@ -1441,8 +1474,8 @@ async function expandGlob(pattern) {
|
|
|
1441
1474
|
for (const e of entries) {
|
|
1442
1475
|
const full = `${dir}${SEP}${e}`;
|
|
1443
1476
|
try {
|
|
1444
|
-
const
|
|
1445
|
-
if (
|
|
1477
|
+
const stat16 = await fsp3.stat(full);
|
|
1478
|
+
if (stat16.isDirectory()) await walk3(full, rest);
|
|
1446
1479
|
} catch {
|
|
1447
1480
|
}
|
|
1448
1481
|
}
|
|
@@ -1459,8 +1492,8 @@ async function expandGlob(pattern) {
|
|
|
1459
1492
|
if (entries.includes(seg)) {
|
|
1460
1493
|
const full = `${dir}${SEP}${seg}`;
|
|
1461
1494
|
try {
|
|
1462
|
-
const
|
|
1463
|
-
if (
|
|
1495
|
+
const stat16 = await fsp3.stat(full);
|
|
1496
|
+
if (stat16.isDirectory()) await walk3(full, rest);
|
|
1464
1497
|
} catch {
|
|
1465
1498
|
}
|
|
1466
1499
|
}
|
|
@@ -1476,6 +1509,7 @@ function escapeRegex(s) {
|
|
|
1476
1509
|
}
|
|
1477
1510
|
var COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
|
|
1478
1511
|
var CACHE_MAX_SIZE = 2e3;
|
|
1512
|
+
var NEVER_MATCH = /[^\s\S]/;
|
|
1479
1513
|
function getCachedGlob(pattern) {
|
|
1480
1514
|
const cached = COMPILED_GLOB_CACHE.get(pattern);
|
|
1481
1515
|
if (cached) return cached;
|
|
@@ -1485,7 +1519,12 @@ function getCachedGlob(pattern) {
|
|
|
1485
1519
|
COMPILED_GLOB_CACHE.delete(expectDefined(keys[i]));
|
|
1486
1520
|
}
|
|
1487
1521
|
}
|
|
1488
|
-
|
|
1522
|
+
let re;
|
|
1523
|
+
try {
|
|
1524
|
+
re = compileGlob(pattern);
|
|
1525
|
+
} catch {
|
|
1526
|
+
re = NEVER_MATCH;
|
|
1527
|
+
}
|
|
1489
1528
|
COMPILED_GLOB_CACHE.set(pattern, re);
|
|
1490
1529
|
return re;
|
|
1491
1530
|
}
|
|
@@ -1733,11 +1772,11 @@ function validateAgainstSchema(value, schema) {
|
|
|
1733
1772
|
walk(value, schema, "", errors);
|
|
1734
1773
|
return { ok: errors.length === 0, errors };
|
|
1735
1774
|
}
|
|
1736
|
-
function walk(value, schema,
|
|
1775
|
+
function walk(value, schema, path50, errors) {
|
|
1737
1776
|
if (schema.enum !== void 0) {
|
|
1738
1777
|
if (!schema.enum.some((e) => deepEqual(e, value))) {
|
|
1739
1778
|
errors.push({
|
|
1740
|
-
path:
|
|
1779
|
+
path: path50 || "<root>",
|
|
1741
1780
|
message: `expected one of ${JSON.stringify(schema.enum)}, got ${JSON.stringify(value)}`
|
|
1742
1781
|
});
|
|
1743
1782
|
return;
|
|
@@ -1746,7 +1785,7 @@ function walk(value, schema, path48, errors) {
|
|
|
1746
1785
|
if (typeof schema.type === "string") {
|
|
1747
1786
|
if (!checkType(value, schema.type)) {
|
|
1748
1787
|
errors.push({
|
|
1749
|
-
path:
|
|
1788
|
+
path: path50 || "<root>",
|
|
1750
1789
|
message: `expected ${schema.type}, got ${describeType(value)}`
|
|
1751
1790
|
});
|
|
1752
1791
|
return;
|
|
@@ -1756,20 +1795,20 @@ function walk(value, schema, path48, errors) {
|
|
|
1756
1795
|
const obj = value;
|
|
1757
1796
|
for (const req of schema.required ?? []) {
|
|
1758
1797
|
if (!(req in obj)) {
|
|
1759
|
-
errors.push({ path: joinPath(
|
|
1798
|
+
errors.push({ path: joinPath(path50, req), message: "required property missing" });
|
|
1760
1799
|
}
|
|
1761
1800
|
}
|
|
1762
1801
|
if (schema.properties) {
|
|
1763
1802
|
for (const [key, subSchema] of Object.entries(schema.properties)) {
|
|
1764
1803
|
if (key in obj) {
|
|
1765
|
-
walk(obj[key], subSchema, joinPath(
|
|
1804
|
+
walk(obj[key], subSchema, joinPath(path50, key), errors);
|
|
1766
1805
|
}
|
|
1767
1806
|
}
|
|
1768
1807
|
}
|
|
1769
1808
|
}
|
|
1770
1809
|
if (schema.type === "array" && Array.isArray(value) && schema.items) {
|
|
1771
1810
|
for (let i = 0; i < value.length; i++) {
|
|
1772
|
-
walk(value[i], schema.items, `${
|
|
1811
|
+
walk(value[i], schema.items, `${path50}[${i}]`, errors);
|
|
1773
1812
|
}
|
|
1774
1813
|
}
|
|
1775
1814
|
}
|
|
@@ -2431,18 +2470,20 @@ var MODEL_FAMILY_RATIO = {
|
|
|
2431
2470
|
deepseek: 3.5
|
|
2432
2471
|
};
|
|
2433
2472
|
var ESTIMATE_CACHE = /* @__PURE__ */ new Map();
|
|
2473
|
+
var _estimateCacheOrder = [];
|
|
2434
2474
|
var ESTIMATE_CACHE_MAX_SIZE = 5e4;
|
|
2435
2475
|
function getCachedEstimate(key, compute) {
|
|
2436
2476
|
const existing = ESTIMATE_CACHE.get(key);
|
|
2437
2477
|
if (existing !== void 0) return existing;
|
|
2438
2478
|
if (ESTIMATE_CACHE.size >= ESTIMATE_CACHE_MAX_SIZE) {
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
ESTIMATE_CACHE.delete(
|
|
2479
|
+
while (ESTIMATE_CACHE.size > Math.floor(ESTIMATE_CACHE_MAX_SIZE / 2)) {
|
|
2480
|
+
const oldest = _estimateCacheOrder.shift();
|
|
2481
|
+
if (oldest !== void 0) ESTIMATE_CACHE.delete(oldest);
|
|
2442
2482
|
}
|
|
2443
2483
|
}
|
|
2444
2484
|
const estimate = compute(key);
|
|
2445
2485
|
ESTIMATE_CACHE.set(key, estimate);
|
|
2486
|
+
_estimateCacheOrder.push(key);
|
|
2446
2487
|
return estimate;
|
|
2447
2488
|
}
|
|
2448
2489
|
function estimateToolInputTokens(input) {
|
|
@@ -4463,11 +4504,88 @@ var ALGO = "aes-256-gcm";
|
|
|
4463
4504
|
var KEY_FILE_MODE = 384;
|
|
4464
4505
|
var KEY_FILE_MAGIC = Buffer.from("WSKV", "ascii");
|
|
4465
4506
|
var VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES;
|
|
4507
|
+
var KEK_MAGIC = Buffer.from("WSKW", "ascii");
|
|
4508
|
+
var KEK_SALT_BYTES = 16;
|
|
4509
|
+
var WRAPPED_KEY_FILE_SIZE = KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES;
|
|
4510
|
+
var SCRYPT_N = 1 << 15;
|
|
4511
|
+
var SCRYPT_R = 8;
|
|
4512
|
+
var SCRYPT_P = 1;
|
|
4513
|
+
var SCRYPT_MAXMEM = 64 * 1024 * 1024;
|
|
4514
|
+
function getVaultPassphrase() {
|
|
4515
|
+
const v = process.env["WRONGSTACK_VAULT_PASSPHRASE"];
|
|
4516
|
+
return v && v.length > 0 ? v : void 0;
|
|
4517
|
+
}
|
|
4518
|
+
function isWrappedKeyFile(buf) {
|
|
4519
|
+
return buf.length === WRAPPED_KEY_FILE_SIZE && buf.subarray(0, KEK_MAGIC.length).equals(KEK_MAGIC);
|
|
4520
|
+
}
|
|
4521
|
+
function deriveKEK(passphrase, salt) {
|
|
4522
|
+
return scryptSync(passphrase, salt, KEY_BYTES, {
|
|
4523
|
+
N: SCRYPT_N,
|
|
4524
|
+
r: SCRYPT_R,
|
|
4525
|
+
p: SCRYPT_P,
|
|
4526
|
+
maxmem: SCRYPT_MAXMEM
|
|
4527
|
+
});
|
|
4528
|
+
}
|
|
4529
|
+
function wrapDataKey(dataKey, keyVersion, passphrase) {
|
|
4530
|
+
const salt = randomBytes(KEK_SALT_BYTES);
|
|
4531
|
+
const iv = randomBytes(IV_BYTES);
|
|
4532
|
+
const kek = deriveKEK(passphrase, salt);
|
|
4533
|
+
const cipher = createCipheriv(ALGO, kek, iv);
|
|
4534
|
+
const ct = Buffer.concat([cipher.update(dataKey), cipher.final()]);
|
|
4535
|
+
const tag = cipher.getAuthTag();
|
|
4536
|
+
const out = Buffer.alloc(WRAPPED_KEY_FILE_SIZE);
|
|
4537
|
+
let off = 0;
|
|
4538
|
+
KEK_MAGIC.copy(out, off);
|
|
4539
|
+
off += KEK_MAGIC.length;
|
|
4540
|
+
out[off] = keyVersion & 255;
|
|
4541
|
+
off += 1;
|
|
4542
|
+
salt.copy(out, off);
|
|
4543
|
+
off += KEK_SALT_BYTES;
|
|
4544
|
+
iv.copy(out, off);
|
|
4545
|
+
off += IV_BYTES;
|
|
4546
|
+
tag.copy(out, off);
|
|
4547
|
+
off += TAG_BYTES;
|
|
4548
|
+
ct.copy(out, off);
|
|
4549
|
+
return out;
|
|
4550
|
+
}
|
|
4551
|
+
function unwrapDataKey(buf, keyFile) {
|
|
4552
|
+
const passphrase = getVaultPassphrase();
|
|
4553
|
+
if (!passphrase) {
|
|
4554
|
+
throw new ConfigError({
|
|
4555
|
+
message: `SecretVault: key file ${keyFile} is passphrase-protected \u2014 set the WRONGSTACK_VAULT_PASSPHRASE environment variable to unlock it.`,
|
|
4556
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
4557
|
+
context: { keyFile }
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4560
|
+
let off = KEK_MAGIC.length;
|
|
4561
|
+
const version = buf[off];
|
|
4562
|
+
off += 1;
|
|
4563
|
+
const salt = buf.subarray(off, off + KEK_SALT_BYTES);
|
|
4564
|
+
off += KEK_SALT_BYTES;
|
|
4565
|
+
const iv = buf.subarray(off, off + IV_BYTES);
|
|
4566
|
+
off += IV_BYTES;
|
|
4567
|
+
const tag = buf.subarray(off, off + TAG_BYTES);
|
|
4568
|
+
off += TAG_BYTES;
|
|
4569
|
+
const ct = buf.subarray(off, off + KEY_BYTES);
|
|
4570
|
+
const kek = deriveKEK(passphrase, salt);
|
|
4571
|
+
const decipher = createDecipheriv(ALGO, kek, iv);
|
|
4572
|
+
decipher.setAuthTag(tag);
|
|
4573
|
+
try {
|
|
4574
|
+
const key = Buffer.concat([decipher.update(ct), decipher.final()]);
|
|
4575
|
+
return { key: Buffer.from(key), version };
|
|
4576
|
+
} catch {
|
|
4577
|
+
throw new ConfigError({
|
|
4578
|
+
message: `SecretVault: failed to unlock key file ${keyFile} \u2014 wrong WRONGSTACK_VAULT_PASSPHRASE (key unwrap authentication failed).`,
|
|
4579
|
+
code: ERROR_CODES.CONFIG_INVALID,
|
|
4580
|
+
context: { keyFile }
|
|
4581
|
+
});
|
|
4582
|
+
}
|
|
4583
|
+
}
|
|
4466
4584
|
function checkKeyFilePermissions(keyFile) {
|
|
4467
4585
|
if (process.platform === "win32") return;
|
|
4468
4586
|
try {
|
|
4469
|
-
const
|
|
4470
|
-
const actualMode =
|
|
4587
|
+
const stat16 = fs3.statSync(keyFile);
|
|
4588
|
+
const actualMode = stat16.mode & 511;
|
|
4471
4589
|
if (actualMode !== KEY_FILE_MODE) {
|
|
4472
4590
|
console.warn(JSON.stringify({
|
|
4473
4591
|
level: "warn",
|
|
@@ -4555,25 +4673,56 @@ var DefaultSecretVault = class {
|
|
|
4555
4673
|
const oldVersion = this._keyVersion;
|
|
4556
4674
|
const newKey = randomBytes(KEY_BYTES);
|
|
4557
4675
|
const newVersion = oldVersion + 1;
|
|
4558
|
-
const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
|
|
4559
|
-
KEY_FILE_MAGIC.copy(keyFileBuf, 0);
|
|
4560
|
-
keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
|
|
4561
|
-
newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
|
|
4562
4676
|
fs3.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
4563
|
-
|
|
4677
|
+
const passphrase = getVaultPassphrase();
|
|
4678
|
+
if (passphrase) {
|
|
4679
|
+
fs3.writeFileSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase), { mode: 384 });
|
|
4680
|
+
} else {
|
|
4681
|
+
const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
|
|
4682
|
+
KEY_FILE_MAGIC.copy(keyFileBuf, 0);
|
|
4683
|
+
keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
|
|
4684
|
+
newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
|
|
4685
|
+
fs3.writeFileSync(this.keyFile, keyFileBuf, { mode: 384 });
|
|
4686
|
+
}
|
|
4564
4687
|
checkKeyFilePermissions(this.keyFile);
|
|
4565
4688
|
this.key = newKey;
|
|
4566
4689
|
this._keyVersion = newVersion;
|
|
4567
4690
|
return { oldVersion, newVersion };
|
|
4568
4691
|
}
|
|
4692
|
+
/**
|
|
4693
|
+
* If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored
|
|
4694
|
+
* unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)
|
|
4695
|
+
* form. The data key is preserved, so all existing ciphertext keeps
|
|
4696
|
+
* decrypting. Best-effort: a write failure leaves the working unwrapped file
|
|
4697
|
+
* in place and is not fatal to load.
|
|
4698
|
+
*/
|
|
4699
|
+
migrateToWrappedIfPassphrase() {
|
|
4700
|
+
const passphrase = getVaultPassphrase();
|
|
4701
|
+
if (!passphrase || !this.key) return;
|
|
4702
|
+
try {
|
|
4703
|
+
fs3.writeFileSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase), {
|
|
4704
|
+
mode: 384
|
|
4705
|
+
});
|
|
4706
|
+
checkKeyFilePermissions(this.keyFile);
|
|
4707
|
+
} catch {
|
|
4708
|
+
}
|
|
4709
|
+
}
|
|
4569
4710
|
loadOrCreateKey() {
|
|
4570
4711
|
if (this.key) return this.key;
|
|
4571
4712
|
try {
|
|
4572
4713
|
const buf = fs3.readFileSync(this.keyFile);
|
|
4714
|
+
if (isWrappedKeyFile(buf)) {
|
|
4715
|
+
const { key: key2, version } = unwrapDataKey(buf, this.keyFile);
|
|
4716
|
+
this.key = key2;
|
|
4717
|
+
this._keyVersion = version;
|
|
4718
|
+
checkKeyFilePermissions(this.keyFile);
|
|
4719
|
+
return this.key;
|
|
4720
|
+
}
|
|
4573
4721
|
if (buf.length === KEY_BYTES) {
|
|
4574
4722
|
this.key = buf;
|
|
4575
4723
|
this._keyVersion = 1;
|
|
4576
4724
|
checkKeyFilePermissions(this.keyFile);
|
|
4725
|
+
this.migrateToWrappedIfPassphrase();
|
|
4577
4726
|
return this.key;
|
|
4578
4727
|
}
|
|
4579
4728
|
if (buf.length === VERSIONED_KEY_FILE_SIZE) {
|
|
@@ -4597,6 +4746,7 @@ var DefaultSecretVault = class {
|
|
|
4597
4746
|
this.key = Buffer.from(key2);
|
|
4598
4747
|
this._keyVersion = version;
|
|
4599
4748
|
checkKeyFilePermissions(this.keyFile);
|
|
4749
|
+
this.migrateToWrappedIfPassphrase();
|
|
4600
4750
|
return this.key;
|
|
4601
4751
|
}
|
|
4602
4752
|
throw new ConfigError({
|
|
@@ -4609,11 +4759,20 @@ var DefaultSecretVault = class {
|
|
|
4609
4759
|
}
|
|
4610
4760
|
fs3.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
|
|
4611
4761
|
const key = randomBytes(KEY_BYTES);
|
|
4762
|
+
const passphrase = getVaultPassphrase();
|
|
4763
|
+
const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;
|
|
4612
4764
|
try {
|
|
4613
|
-
fs3.writeFileSync(this.keyFile,
|
|
4765
|
+
fs3.writeFileSync(this.keyFile, initialBytes, { mode: 384, flag: "wx" });
|
|
4614
4766
|
} catch (err) {
|
|
4615
4767
|
if (err.code !== "EEXIST") throw err;
|
|
4616
4768
|
const buf = fs3.readFileSync(this.keyFile);
|
|
4769
|
+
if (isWrappedKeyFile(buf)) {
|
|
4770
|
+
const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);
|
|
4771
|
+
this.key = winnerKey;
|
|
4772
|
+
this._keyVersion = version;
|
|
4773
|
+
checkKeyFilePermissions(this.keyFile);
|
|
4774
|
+
return this.key;
|
|
4775
|
+
}
|
|
4617
4776
|
if (buf.length === KEY_BYTES) {
|
|
4618
4777
|
this.key = buf;
|
|
4619
4778
|
this._keyVersion = 1;
|
|
@@ -5217,17 +5376,9 @@ function findPreserveStart(messages, preserveK) {
|
|
|
5217
5376
|
const prev = messages[preserveStart - 1];
|
|
5218
5377
|
if (!first || !prev || first.role !== "user" || prev.role !== "assistant") break;
|
|
5219
5378
|
if (typeof first.content === "string" || typeof prev.content === "string") break;
|
|
5220
|
-
const
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
if (block.type === "tool_result") resultIds.add(block.tool_use_id);
|
|
5224
|
-
}
|
|
5225
|
-
if (resultIds.size === 0) break;
|
|
5226
|
-
const hasMatchingUse = prev.content.some((block) => {
|
|
5227
|
-
pairRepairInnerIterations++;
|
|
5228
|
-
return block.type === "tool_use" && resultIds.has(block.id);
|
|
5229
|
-
});
|
|
5230
|
-
if (!hasMatchingUse) break;
|
|
5379
|
+
const pairCheck = hasMatchingToolPair(first.content, prev.content);
|
|
5380
|
+
pairRepairInnerIterations += pairCheck.iterations;
|
|
5381
|
+
if (!pairCheck.matched) break;
|
|
5231
5382
|
preserveStart--;
|
|
5232
5383
|
}
|
|
5233
5384
|
if (compactionDebugEnabled()) {
|
|
@@ -5246,9 +5397,34 @@ function findPreserveStart(messages, preserveK) {
|
|
|
5246
5397
|
}
|
|
5247
5398
|
return preserveStart;
|
|
5248
5399
|
}
|
|
5400
|
+
function hasMatchingToolPair(resultContent, useContent) {
|
|
5401
|
+
let iterations = 0;
|
|
5402
|
+
let firstResultId;
|
|
5403
|
+
let resultIds;
|
|
5404
|
+
for (const block of resultContent) {
|
|
5405
|
+
iterations++;
|
|
5406
|
+
if (block.type !== "tool_result") continue;
|
|
5407
|
+
if (firstResultId === void 0) {
|
|
5408
|
+
firstResultId = block.tool_use_id;
|
|
5409
|
+
} else {
|
|
5410
|
+
resultIds ??= /* @__PURE__ */ new Set([firstResultId]);
|
|
5411
|
+
resultIds.add(block.tool_use_id);
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
5414
|
+
if (firstResultId === void 0) return { matched: false, iterations };
|
|
5415
|
+
for (const block of useContent) {
|
|
5416
|
+
iterations++;
|
|
5417
|
+
if (block.type !== "tool_use") continue;
|
|
5418
|
+
if (resultIds ? resultIds.has(block.id) : block.id === firstResultId) {
|
|
5419
|
+
return { matched: true, iterations };
|
|
5420
|
+
}
|
|
5421
|
+
}
|
|
5422
|
+
return { matched: false, iterations };
|
|
5423
|
+
}
|
|
5249
5424
|
function eliseOldToolResults(messages, opts) {
|
|
5250
5425
|
const preserveStart = findPreserveStart(messages, opts.preserveK);
|
|
5251
5426
|
let hasOversized = false;
|
|
5427
|
+
let firstOversizedIndex = -1;
|
|
5252
5428
|
let fastPathIterations = 0;
|
|
5253
5429
|
let fastPathInnerIterations = 0;
|
|
5254
5430
|
for (let i = 0; i < preserveStart && !hasOversized; i++) {
|
|
@@ -5260,6 +5436,7 @@ function eliseOldToolResults(messages, opts) {
|
|
|
5260
5436
|
const oversized = b.type === "tool_result" && estimateToolResultTokens(b.content) >= opts.eliseThreshold || b.type === "tool_use" && estimateToolInputTokens(b.input) >= opts.eliseThreshold;
|
|
5261
5437
|
if (oversized) {
|
|
5262
5438
|
hasOversized = true;
|
|
5439
|
+
firstOversizedIndex = i;
|
|
5263
5440
|
break;
|
|
5264
5441
|
}
|
|
5265
5442
|
}
|
|
@@ -5282,26 +5459,29 @@ function eliseOldToolResults(messages, opts) {
|
|
|
5282
5459
|
let changed = false;
|
|
5283
5460
|
let fullPassIterations = 0;
|
|
5284
5461
|
let fullPassInnerIterations = 0;
|
|
5285
|
-
|
|
5286
|
-
for (let i =
|
|
5462
|
+
let next;
|
|
5463
|
+
for (let i = firstOversizedIndex; i < preserveStart; i++) {
|
|
5287
5464
|
fullPassIterations++;
|
|
5288
5465
|
const msg = messages[i];
|
|
5289
|
-
if (
|
|
5290
|
-
next[i] = msg;
|
|
5291
|
-
continue;
|
|
5292
|
-
}
|
|
5466
|
+
if (!msg || !Array.isArray(msg.content)) continue;
|
|
5293
5467
|
const original = msg.content;
|
|
5294
|
-
|
|
5468
|
+
let newContent;
|
|
5469
|
+
for (let idx = 0; idx < original.length; idx++) {
|
|
5470
|
+
fullPassInnerIterations++;
|
|
5471
|
+
const b = original[idx];
|
|
5472
|
+
if (!b) continue;
|
|
5295
5473
|
if (b.type === "tool_use") {
|
|
5296
5474
|
const tokens2 = estimateToolInputTokens(b.input);
|
|
5297
|
-
if (tokens2 < opts.eliseThreshold)
|
|
5475
|
+
if (tokens2 < opts.eliseThreshold) continue;
|
|
5298
5476
|
const elidedInput = summarizeToolUseInputElision(b, tokens2);
|
|
5299
5477
|
saved += Math.max(0, tokens2 - estimateToolInputTokens(elidedInput));
|
|
5300
|
-
|
|
5478
|
+
newContent ??= original.slice();
|
|
5479
|
+
newContent[idx] = { ...b, input: elidedInput };
|
|
5480
|
+
continue;
|
|
5301
5481
|
}
|
|
5302
|
-
if (b.type !== "tool_result")
|
|
5482
|
+
if (b.type !== "tool_result") continue;
|
|
5303
5483
|
const tokens = estimateToolResultTokens(b.content);
|
|
5304
|
-
if (tokens < opts.eliseThreshold)
|
|
5484
|
+
if (tokens < opts.eliseThreshold) continue;
|
|
5305
5485
|
saved += tokens;
|
|
5306
5486
|
const elided = {
|
|
5307
5487
|
type: "tool_result",
|
|
@@ -5309,15 +5489,14 @@ function eliseOldToolResults(messages, opts) {
|
|
|
5309
5489
|
content: summarizeToolResultElision(b, tokens),
|
|
5310
5490
|
is_error: b.is_error
|
|
5311
5491
|
};
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
|
-
|
|
5492
|
+
newContent ??= original.slice();
|
|
5493
|
+
newContent[idx] = elided;
|
|
5494
|
+
}
|
|
5495
|
+
if (newContent) {
|
|
5496
|
+
next ??= messages.slice();
|
|
5317
5497
|
next[i] = { ...msg, content: newContent };
|
|
5318
5498
|
changed = true;
|
|
5319
5499
|
}
|
|
5320
|
-
fullPassInnerIterations += original.length;
|
|
5321
5500
|
if (compactionDebugEnabled()) {
|
|
5322
5501
|
const ratio = fullPassInnerIterations / fullPassIterations;
|
|
5323
5502
|
if (ratio > 10) {
|
|
@@ -5344,7 +5523,7 @@ function eliseOldToolResults(messages, opts) {
|
|
|
5344
5523
|
tokensSaved: saved,
|
|
5345
5524
|
changed
|
|
5346
5525
|
});
|
|
5347
|
-
return { messages: changed ? next : messages, saved, changed };
|
|
5526
|
+
return { messages: changed && next ? next : messages, saved, changed };
|
|
5348
5527
|
}
|
|
5349
5528
|
function summarizeToolUseInputElision(block, tokens) {
|
|
5350
5529
|
const fields = {};
|
|
@@ -6096,6 +6275,7 @@ var DefaultSecretScrubber = class {
|
|
|
6096
6275
|
// src/models/models-registry.ts
|
|
6097
6276
|
init_atomic_write();
|
|
6098
6277
|
var DEFAULT_URL = "https://models.dev/api.json";
|
|
6278
|
+
var ENV_URL_KEY = "WRONGSTACK_MODELS_DEV_URL";
|
|
6099
6279
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
6100
6280
|
var DEFAULT_REFRESH_TIMEOUT_MS = 15e3;
|
|
6101
6281
|
var FAMILY_BY_NPM = {
|
|
@@ -6141,7 +6321,7 @@ var DefaultModelsRegistry = class {
|
|
|
6141
6321
|
overlayCacheFile;
|
|
6142
6322
|
constructor(opts) {
|
|
6143
6323
|
this.cacheFile = opts.cacheFile;
|
|
6144
|
-
this.url = opts.url ?? DEFAULT_URL;
|
|
6324
|
+
this.url = opts.url ?? process.env[ENV_URL_KEY] ?? DEFAULT_URL;
|
|
6145
6325
|
this.ttlMs = (opts.ttlSeconds ?? DEFAULT_TTL_SECONDS) * 1e3;
|
|
6146
6326
|
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
6147
6327
|
this.seed = opts.seed;
|
|
@@ -6186,6 +6366,10 @@ var DefaultModelsRegistry = class {
|
|
|
6186
6366
|
const cached = await this.readCacheAt(this.cacheFile);
|
|
6187
6367
|
if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {
|
|
6188
6368
|
this.fetchedAt = new Date(cached.fetchedAt);
|
|
6369
|
+
const ageSeconds = Math.floor((Date.now() - this.fetchedAt.getTime()) / 1e3);
|
|
6370
|
+
console.warn(
|
|
6371
|
+
`ModelsRegistry: models.dev unavailable (${toErrorMessage(err)}); using stale cache from ${formatAge(ageSeconds)} ago. Run \`wstack models refresh\` to retry.`
|
|
6372
|
+
);
|
|
6189
6373
|
return cached.payload;
|
|
6190
6374
|
}
|
|
6191
6375
|
if (overlayAvailable) {
|
|
@@ -6271,7 +6455,13 @@ var DefaultModelsRegistry = class {
|
|
|
6271
6455
|
return json;
|
|
6272
6456
|
} catch {
|
|
6273
6457
|
const cached = await this.readCacheAt(this.overlayCacheFile);
|
|
6274
|
-
if (cached && this.isWithinMaxStaleAge(cached.fetchedAt))
|
|
6458
|
+
if (cached && this.isWithinMaxStaleAge(cached.fetchedAt)) {
|
|
6459
|
+
const ageSeconds = Math.floor((Date.now() - new Date(cached.fetchedAt).getTime()) / 1e3);
|
|
6460
|
+
console.warn(
|
|
6461
|
+
`ModelsRegistry: overlay unavailable; using stale overlay from ${formatAge(ageSeconds)} ago.`
|
|
6462
|
+
);
|
|
6463
|
+
return cached.payload;
|
|
6464
|
+
}
|
|
6275
6465
|
return void 0;
|
|
6276
6466
|
}
|
|
6277
6467
|
}
|
|
@@ -6368,6 +6558,16 @@ var DefaultModelsRegistry = class {
|
|
|
6368
6558
|
return path3.resolve(this.cacheFile);
|
|
6369
6559
|
}
|
|
6370
6560
|
};
|
|
6561
|
+
function formatAge(seconds) {
|
|
6562
|
+
if (seconds < 60) return "<1m";
|
|
6563
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
|
|
6564
|
+
if (seconds < 86400) {
|
|
6565
|
+
const h = Math.floor(seconds / 3600);
|
|
6566
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
6567
|
+
return m > 0 ? `${h}h ${m}m` : `${h}h`;
|
|
6568
|
+
}
|
|
6569
|
+
return `${Math.floor(seconds / 86400)}d`;
|
|
6570
|
+
}
|
|
6371
6571
|
function hasEntries(payload) {
|
|
6372
6572
|
return payload !== void 0 && Object.keys(payload).length > 0;
|
|
6373
6573
|
}
|
|
@@ -8176,6 +8376,8 @@ function generateSessionId(startedAt, model) {
|
|
|
8176
8376
|
const modelPart = model ? `_${sanitizeModel(model)}` : "";
|
|
8177
8377
|
return `${date}/${time}Z${modelPart}_${suffix}`;
|
|
8178
8378
|
}
|
|
8379
|
+
|
|
8380
|
+
// src/storage/session-store.ts
|
|
8179
8381
|
var DefaultSessionStore = class _DefaultSessionStore {
|
|
8180
8382
|
dir;
|
|
8181
8383
|
events;
|
|
@@ -8193,6 +8395,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8193
8395
|
_loadCache = /* @__PURE__ */ new Map();
|
|
8194
8396
|
_indexCache = null;
|
|
8195
8397
|
static LOAD_CACHE_MAX_ENTRIES = 50;
|
|
8398
|
+
static LIST_SCAN_CONCURRENCY = 32;
|
|
8196
8399
|
constructor(opts) {
|
|
8197
8400
|
this.dir = opts.dir;
|
|
8198
8401
|
this.events = opts.events;
|
|
@@ -8354,9 +8557,9 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8354
8557
|
let cacheHit = false;
|
|
8355
8558
|
try {
|
|
8356
8559
|
const s = await fsp3.stat(file);
|
|
8357
|
-
const
|
|
8560
|
+
const stat16 = { mtimeMs: s.mtimeMs, size: s.size };
|
|
8358
8561
|
const cached = this._loadCache.get(id);
|
|
8359
|
-
if (cached && cached.mtimeMs ===
|
|
8562
|
+
if (cached && cached.mtimeMs === stat16.mtimeMs && cached.size === stat16.size) {
|
|
8360
8563
|
cacheHit = true;
|
|
8361
8564
|
this._loadCache.delete(id);
|
|
8362
8565
|
this._loadCache.set(id, cached);
|
|
@@ -8384,7 +8587,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8384
8587
|
this._loadCache.delete(oldest);
|
|
8385
8588
|
}
|
|
8386
8589
|
}
|
|
8387
|
-
this._loadCache.set(id, { mtimeMs:
|
|
8590
|
+
this._loadCache.set(id, { mtimeMs: stat16.mtimeMs, size: stat16.size, data });
|
|
8388
8591
|
return data;
|
|
8389
8592
|
} catch (err) {
|
|
8390
8593
|
outcome = "failure";
|
|
@@ -8415,15 +8618,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8415
8618
|
});
|
|
8416
8619
|
return indexed.slice(0, limit);
|
|
8417
8620
|
}
|
|
8418
|
-
|
|
8419
|
-
const sessions = await Promise.all(ids.map((id) => this.summaryFor(id).catch(() => null)));
|
|
8420
|
-
const out = sessions.filter((s) => s !== null);
|
|
8421
|
-
out.sort((a, b) => {
|
|
8422
|
-
if (a.startedAt < b.startedAt) return 1;
|
|
8423
|
-
if (a.startedAt > b.startedAt) return -1;
|
|
8424
|
-
return a.id.localeCompare(b.id);
|
|
8425
|
-
});
|
|
8426
|
-
return out.slice(0, limit);
|
|
8621
|
+
return await this.listFromDirectoryScan(limit);
|
|
8427
8622
|
} catch {
|
|
8428
8623
|
return [];
|
|
8429
8624
|
}
|
|
@@ -8494,15 +8689,15 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8494
8689
|
* Returns empty array when the index doesn't exist or is corrupt.
|
|
8495
8690
|
*/
|
|
8496
8691
|
async readIndex() {
|
|
8497
|
-
let
|
|
8692
|
+
let stat16;
|
|
8498
8693
|
try {
|
|
8499
8694
|
const s = await fsp3.stat(this.indexFile);
|
|
8500
|
-
|
|
8695
|
+
stat16 = { mtimeMs: s.mtimeMs, size: s.size };
|
|
8501
8696
|
} catch {
|
|
8502
8697
|
this._indexCache = null;
|
|
8503
8698
|
return [];
|
|
8504
8699
|
}
|
|
8505
|
-
if (this._indexCache !== null && this._indexCache.mtimeMs ===
|
|
8700
|
+
if (this._indexCache !== null && this._indexCache.mtimeMs === stat16.mtimeMs && this._indexCache.size === stat16.size) {
|
|
8506
8701
|
return [...this._indexCache.summaries];
|
|
8507
8702
|
}
|
|
8508
8703
|
let raw;
|
|
@@ -8530,7 +8725,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8530
8725
|
}
|
|
8531
8726
|
}
|
|
8532
8727
|
const summaries = Array.from(seen.values());
|
|
8533
|
-
this._indexCache = { ...
|
|
8728
|
+
this._indexCache = { ...stat16, summaries };
|
|
8534
8729
|
return [...summaries];
|
|
8535
8730
|
}
|
|
8536
8731
|
/**
|
|
@@ -8548,46 +8743,105 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8548
8743
|
this._indexCache = null;
|
|
8549
8744
|
return valid.length;
|
|
8550
8745
|
}
|
|
8746
|
+
async listFromDirectoryScan(limit) {
|
|
8747
|
+
const refs = await this.collectSessionFiles(this.dir);
|
|
8748
|
+
const candidates = await mapWithConcurrency(
|
|
8749
|
+
refs,
|
|
8750
|
+
_DefaultSessionStore.LIST_SCAN_CONCURRENCY,
|
|
8751
|
+
async (ref) => {
|
|
8752
|
+
const manifest = await this.readSummaryManifest(ref.id);
|
|
8753
|
+
if (manifest) return { summary: manifest, needsBackfill: false };
|
|
8754
|
+
const summary = await this.summaryHeaderFor(ref);
|
|
8755
|
+
return summary ? { summary, needsBackfill: true } : null;
|
|
8756
|
+
}
|
|
8757
|
+
);
|
|
8758
|
+
const out = candidates.filter((s) => s !== null);
|
|
8759
|
+
out.sort((a, b) => compareSessionSummaries(a.summary, b.summary));
|
|
8760
|
+
const selected = out.slice(0, limit);
|
|
8761
|
+
const summaries = await mapWithConcurrency(
|
|
8762
|
+
selected,
|
|
8763
|
+
Math.min(_DefaultSessionStore.LIST_SCAN_CONCURRENCY, Math.max(1, limit)),
|
|
8764
|
+
async (candidate) => {
|
|
8765
|
+
if (!candidate.needsBackfill) return candidate.summary;
|
|
8766
|
+
return await this.summaryFor(candidate.summary.id).catch(() => candidate.summary);
|
|
8767
|
+
}
|
|
8768
|
+
);
|
|
8769
|
+
return summaries.filter((s) => s !== null);
|
|
8770
|
+
}
|
|
8771
|
+
async collectSessionFiles(dir, prefix = "", depth = 0) {
|
|
8772
|
+
let entries;
|
|
8773
|
+
try {
|
|
8774
|
+
entries = await fsp3.readdir(dir, { withFileTypes: true });
|
|
8775
|
+
} catch {
|
|
8776
|
+
return [];
|
|
8777
|
+
}
|
|
8778
|
+
const dirEntries = [];
|
|
8779
|
+
const files = [];
|
|
8780
|
+
for (const entry of entries) {
|
|
8781
|
+
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
8782
|
+
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
8783
|
+
continue;
|
|
8784
|
+
if (entry.isDirectory()) {
|
|
8785
|
+
dirEntries.push(entry);
|
|
8786
|
+
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
8787
|
+
if (entry.name === "_index.jsonl") continue;
|
|
8788
|
+
const base = entry.name.replace(/\.jsonl$/, "");
|
|
8789
|
+
const id = prefix ? `${prefix}/${base}` : base;
|
|
8790
|
+
files.push({ id, filePath: path3.join(dir, entry.name) });
|
|
8791
|
+
}
|
|
8792
|
+
}
|
|
8793
|
+
const childFileArrays = await Promise.all(
|
|
8794
|
+
dirEntries.map((entry) => {
|
|
8795
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
8796
|
+
return this.collectSessionFiles(path3.join(dir, entry.name), childPrefix, depth + 1);
|
|
8797
|
+
})
|
|
8798
|
+
);
|
|
8799
|
+
return [...childFileArrays.flat(), ...files];
|
|
8800
|
+
}
|
|
8551
8801
|
/** Recursively collect session IDs from date-shard subdirectories.
|
|
8552
8802
|
* IDs include the date-prefix path (e.g. "2026-06-06/17-46-57Z_…").
|
|
8553
8803
|
* Skips `.jsonl`/`.summary.json` root files, dot-files, and
|
|
8554
8804
|
* sub-directories that belong to fleet/subagent sessions. */
|
|
8555
8805
|
async collectSessionIds(dir, prefix = "", depth = 0) {
|
|
8556
|
-
const ids = [];
|
|
8557
8806
|
let entries;
|
|
8558
8807
|
try {
|
|
8559
8808
|
entries = await fsp3.readdir(dir, { withFileTypes: true });
|
|
8560
8809
|
} catch {
|
|
8561
|
-
return
|
|
8810
|
+
return [];
|
|
8562
8811
|
}
|
|
8812
|
+
const dirEntries = [];
|
|
8813
|
+
const fileIds = [];
|
|
8563
8814
|
for (const entry of entries) {
|
|
8564
8815
|
if (entry.name.startsWith(".") && entry.name !== ".wrongstack") continue;
|
|
8565
8816
|
if (entry.name === "shared" || entry.name === "subagents" || entry.name === "attachments")
|
|
8566
8817
|
continue;
|
|
8567
8818
|
if (entry.isDirectory()) {
|
|
8568
|
-
|
|
8569
|
-
ids.push(...await this.collectSessionIds(path3.join(dir, entry.name), childPrefix, depth + 1));
|
|
8819
|
+
dirEntries.push(entry);
|
|
8570
8820
|
} else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
|
|
8571
8821
|
if (entry.name === "_index.jsonl") continue;
|
|
8572
8822
|
const base = entry.name.replace(/\.jsonl$/, "");
|
|
8573
|
-
|
|
8823
|
+
fileIds.push(prefix ? `${prefix}/${base}` : base);
|
|
8574
8824
|
}
|
|
8575
8825
|
}
|
|
8576
|
-
|
|
8826
|
+
const childIdArrays = await Promise.all(
|
|
8827
|
+
dirEntries.map((entry) => {
|
|
8828
|
+
const childPrefix = depth === 0 ? entry.name : `${prefix}/${entry.name}`;
|
|
8829
|
+
return this.collectSessionIds(path3.join(dir, entry.name), childPrefix, depth + 1);
|
|
8830
|
+
})
|
|
8831
|
+
);
|
|
8832
|
+
return [...childIdArrays.flat(), ...fileIds];
|
|
8577
8833
|
}
|
|
8578
8834
|
async summaryFor(id) {
|
|
8579
8835
|
const manifest = this.sessionPath(id, ".summary.json");
|
|
8580
8836
|
const t0 = Date.now();
|
|
8581
8837
|
let outcome = "success";
|
|
8582
8838
|
let errorMsg;
|
|
8839
|
+
const fromManifest = await this.readSummaryManifest(id, t0);
|
|
8840
|
+
if (fromManifest) return fromManifest;
|
|
8583
8841
|
try {
|
|
8584
|
-
const raw = await fsp3.readFile(manifest, "utf8");
|
|
8585
|
-
this.emitRead(id, manifest, "summary", "success", Date.now() - t0);
|
|
8586
|
-
return JSON.parse(raw);
|
|
8587
|
-
} catch {
|
|
8588
8842
|
const full = this.sessionPath(id, ".jsonl");
|
|
8589
|
-
const
|
|
8590
|
-
const summary = await this.summarize(id,
|
|
8843
|
+
const stat16 = await fsp3.stat(full);
|
|
8844
|
+
const summary = await this.summarize(id, stat16.mtime.toISOString());
|
|
8591
8845
|
await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
|
|
8592
8846
|
const msg = toErrorMessage(err);
|
|
8593
8847
|
this.emitError(id, manifest, "summary_fallback", msg, true);
|
|
@@ -8603,6 +8857,78 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8603
8857
|
errorMsg = "summary fallback \u2014 manifest rebuilt";
|
|
8604
8858
|
this.emitRead(id, manifest, "summary", outcome, Date.now() - t0, errorMsg);
|
|
8605
8859
|
return summary;
|
|
8860
|
+
} catch (err) {
|
|
8861
|
+
outcome = "failure";
|
|
8862
|
+
errorMsg = toErrorMessage(err);
|
|
8863
|
+
this.emitRead(id, manifest, "summary", outcome, Date.now() - t0, errorMsg);
|
|
8864
|
+
return {
|
|
8865
|
+
id,
|
|
8866
|
+
title: "(damaged)",
|
|
8867
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8868
|
+
model: "unknown",
|
|
8869
|
+
provider: "unknown",
|
|
8870
|
+
tokenTotal: 0
|
|
8871
|
+
};
|
|
8872
|
+
}
|
|
8873
|
+
}
|
|
8874
|
+
async readSummaryManifest(id, startTime = Date.now()) {
|
|
8875
|
+
const manifest = this.sessionPath(id, ".summary.json");
|
|
8876
|
+
try {
|
|
8877
|
+
const raw = await fsp3.readFile(manifest, "utf8");
|
|
8878
|
+
this.emitRead(id, manifest, "summary", "success", Date.now() - startTime);
|
|
8879
|
+
return JSON.parse(raw);
|
|
8880
|
+
} catch {
|
|
8881
|
+
return null;
|
|
8882
|
+
}
|
|
8883
|
+
}
|
|
8884
|
+
async summaryHeaderFor(ref) {
|
|
8885
|
+
let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
8886
|
+
try {
|
|
8887
|
+
const stat16 = await fsp3.stat(ref.filePath);
|
|
8888
|
+
if (!stat16.isFile()) {
|
|
8889
|
+
return {
|
|
8890
|
+
id: ref.id,
|
|
8891
|
+
title: "(damaged)",
|
|
8892
|
+
startedAt: stat16.mtime.toISOString(),
|
|
8893
|
+
model: "unknown",
|
|
8894
|
+
provider: "unknown",
|
|
8895
|
+
tokenTotal: 0
|
|
8896
|
+
};
|
|
8897
|
+
}
|
|
8898
|
+
mtime = stat16.mtime.toISOString();
|
|
8899
|
+
} catch {
|
|
8900
|
+
return null;
|
|
8901
|
+
}
|
|
8902
|
+
try {
|
|
8903
|
+
for await (const event of this.iterSessionEvents(ref.filePath)) {
|
|
8904
|
+
if (event.type === "session_start") {
|
|
8905
|
+
return {
|
|
8906
|
+
id: ref.id,
|
|
8907
|
+
title: "(empty session)",
|
|
8908
|
+
startedAt: event.ts,
|
|
8909
|
+
model: event.model ?? "unknown",
|
|
8910
|
+
provider: event.provider ?? "unknown",
|
|
8911
|
+
tokenTotal: 0
|
|
8912
|
+
};
|
|
8913
|
+
}
|
|
8914
|
+
}
|
|
8915
|
+
return {
|
|
8916
|
+
id: ref.id,
|
|
8917
|
+
title: "(empty session)",
|
|
8918
|
+
startedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
|
|
8919
|
+
model: "unknown",
|
|
8920
|
+
provider: "unknown",
|
|
8921
|
+
tokenTotal: 0
|
|
8922
|
+
};
|
|
8923
|
+
} catch {
|
|
8924
|
+
return {
|
|
8925
|
+
id: ref.id,
|
|
8926
|
+
title: "(damaged)",
|
|
8927
|
+
startedAt: mtime,
|
|
8928
|
+
model: "unknown",
|
|
8929
|
+
provider: "unknown",
|
|
8930
|
+
tokenTotal: 0
|
|
8931
|
+
};
|
|
8606
8932
|
}
|
|
8607
8933
|
}
|
|
8608
8934
|
/**
|
|
@@ -8669,8 +8995,8 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8669
8995
|
const pruneFile = async (dir, name, prefix) => {
|
|
8670
8996
|
const jsonlPath = path3.join(dir, name);
|
|
8671
8997
|
try {
|
|
8672
|
-
const
|
|
8673
|
-
if (
|
|
8998
|
+
const stat16 = await fsp3.stat(jsonlPath);
|
|
8999
|
+
if (stat16.mtimeMs >= cutoff) return;
|
|
8674
9000
|
} catch {
|
|
8675
9001
|
return;
|
|
8676
9002
|
}
|
|
@@ -8727,39 +9053,62 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8727
9053
|
}
|
|
8728
9054
|
async summarize(id, mtime) {
|
|
8729
9055
|
try {
|
|
8730
|
-
const
|
|
8731
|
-
|
|
8732
|
-
|
|
9056
|
+
const file = this.sessionPath(id, ".jsonl");
|
|
9057
|
+
let title = "(empty session)";
|
|
9058
|
+
let startedAt = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
9059
|
+
let endedAt;
|
|
9060
|
+
let model = "unknown";
|
|
9061
|
+
let provider = "unknown";
|
|
9062
|
+
let tokenIn = 0;
|
|
9063
|
+
let tokenOut = 0;
|
|
8733
9064
|
let iterationCount = 0;
|
|
8734
9065
|
let toolCallCount = 0;
|
|
8735
9066
|
let toolErrorCount = 0;
|
|
8736
9067
|
let fileChangeCount = 0;
|
|
8737
9068
|
const toolBreakdown = {};
|
|
8738
9069
|
let outcome;
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
9070
|
+
let lastEventType;
|
|
9071
|
+
let hasError = false;
|
|
9072
|
+
let sawStart = false;
|
|
9073
|
+
for await (const e of this.iterSessionEvents(file)) {
|
|
9074
|
+
lastEventType = e.type;
|
|
9075
|
+
if (e.type === "session_start") {
|
|
9076
|
+
if (!sawStart) {
|
|
9077
|
+
sawStart = true;
|
|
9078
|
+
startedAt = e.ts;
|
|
9079
|
+
model = e.model ?? "unknown";
|
|
9080
|
+
provider = e.provider ?? "unknown";
|
|
9081
|
+
}
|
|
9082
|
+
} else if (e.type === "session_end") {
|
|
9083
|
+
endedAt = e.ts;
|
|
9084
|
+
} else if (e.type === "user_input") {
|
|
9085
|
+
if (title === "(empty session)") title = userInputTitle(e.content);
|
|
9086
|
+
} else if (e.type === "llm_response") {
|
|
9087
|
+
tokenIn += e.usage.input ?? 0;
|
|
9088
|
+
tokenOut += e.usage.output ?? 0;
|
|
9089
|
+
} else if (e.type === "in_flight_start") iterationCount++;
|
|
8742
9090
|
else if (e.type === "tool_call_start") {
|
|
8743
9091
|
toolCallCount++;
|
|
8744
9092
|
toolBreakdown[e.name] = (toolBreakdown[e.name] ?? 0) + 1;
|
|
8745
9093
|
} else if (e.type === "tool_result" && e.isError) toolErrorCount++;
|
|
8746
9094
|
else if (e.type === "file_snapshot") fileChangeCount += e.files.length;
|
|
9095
|
+
else if (e.type === "error" || e.type === "provider_error") hasError = true;
|
|
8747
9096
|
}
|
|
8748
|
-
if (
|
|
9097
|
+
if (lastEventType === "session_end") {
|
|
8749
9098
|
outcome = "completed";
|
|
8750
|
-
} else if (
|
|
9099
|
+
} else if (lastEventType === "in_flight_start") {
|
|
8751
9100
|
outcome = "aborted";
|
|
8752
|
-
} else if (
|
|
9101
|
+
} else if (hasError) {
|
|
8753
9102
|
outcome = "error";
|
|
8754
9103
|
}
|
|
8755
9104
|
return {
|
|
8756
9105
|
id,
|
|
8757
9106
|
title,
|
|
8758
|
-
startedAt
|
|
8759
|
-
endedAt
|
|
8760
|
-
model
|
|
8761
|
-
provider
|
|
8762
|
-
tokenTotal:
|
|
9107
|
+
startedAt,
|
|
9108
|
+
endedAt,
|
|
9109
|
+
model,
|
|
9110
|
+
provider,
|
|
9111
|
+
tokenTotal: tokenIn + tokenOut,
|
|
8763
9112
|
iterationCount: iterationCount > 0 ? iterationCount : void 0,
|
|
8764
9113
|
toolCallCount: toolCallCount > 0 ? toolCallCount : void 0,
|
|
8765
9114
|
toolErrorCount: toolErrorCount > 0 ? toolErrorCount : void 0,
|
|
@@ -8778,6 +9127,25 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
8778
9127
|
};
|
|
8779
9128
|
}
|
|
8780
9129
|
}
|
|
9130
|
+
async *iterSessionEvents(file) {
|
|
9131
|
+
const stream = createReadStream(file, { encoding: "utf8" });
|
|
9132
|
+
const lines = createInterface({ input: stream, crlfDelay: Infinity });
|
|
9133
|
+
try {
|
|
9134
|
+
for await (const line of lines) {
|
|
9135
|
+
if (!line.trim()) continue;
|
|
9136
|
+
try {
|
|
9137
|
+
const parsed = JSON.parse(line);
|
|
9138
|
+
if (parsed !== null && typeof parsed === "object" && typeof parsed.type === "string" && typeof parsed.ts === "string") {
|
|
9139
|
+
yield parsed;
|
|
9140
|
+
}
|
|
9141
|
+
} catch {
|
|
9142
|
+
}
|
|
9143
|
+
}
|
|
9144
|
+
} finally {
|
|
9145
|
+
lines.close();
|
|
9146
|
+
stream.destroy();
|
|
9147
|
+
}
|
|
9148
|
+
}
|
|
8781
9149
|
metaFromEvents(id, events) {
|
|
8782
9150
|
const start = events.find((e) => e.type === "session_start");
|
|
8783
9151
|
const end = events.findLast((e) => e.type === "session_end");
|
|
@@ -9441,6 +9809,27 @@ function userInputTitle(content) {
|
|
|
9441
9809
|
const text = typeof content === "string" ? content : content.filter((b) => b.type === "text").map((b) => b.text).join(" ");
|
|
9442
9810
|
return (text || "(non-text input)").slice(0, 60);
|
|
9443
9811
|
}
|
|
9812
|
+
function compareSessionSummaries(a, b) {
|
|
9813
|
+
if (a.startedAt < b.startedAt) return 1;
|
|
9814
|
+
if (a.startedAt > b.startedAt) return -1;
|
|
9815
|
+
return a.id.localeCompare(b.id);
|
|
9816
|
+
}
|
|
9817
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
9818
|
+
if (items.length === 0) return [];
|
|
9819
|
+
const out = new Array(items.length);
|
|
9820
|
+
let next = 0;
|
|
9821
|
+
const workerCount = Math.min(Math.max(1, concurrency), items.length);
|
|
9822
|
+
const workers = Array.from({ length: workerCount }, async () => {
|
|
9823
|
+
for (; ; ) {
|
|
9824
|
+
const idx = next++;
|
|
9825
|
+
if (idx >= items.length) return;
|
|
9826
|
+
const item = items[idx];
|
|
9827
|
+
if (item !== void 0) out[idx] = await fn(item);
|
|
9828
|
+
}
|
|
9829
|
+
});
|
|
9830
|
+
await Promise.all(workers);
|
|
9831
|
+
return out;
|
|
9832
|
+
}
|
|
9444
9833
|
|
|
9445
9834
|
// src/storage/queue-store.ts
|
|
9446
9835
|
init_atomic_write();
|
|
@@ -10470,8 +10859,8 @@ ${body.trim()}`);
|
|
|
10470
10859
|
if (!this.persistBackup || scope === "project-agents") return;
|
|
10471
10860
|
try {
|
|
10472
10861
|
const content = await this.backend.readAll(scope, this.files[scope]);
|
|
10473
|
-
const { writeFile: writeFile14, mkdir:
|
|
10474
|
-
await
|
|
10862
|
+
const { writeFile: writeFile14, mkdir: mkdir24 } = await import('fs/promises');
|
|
10863
|
+
await mkdir24(this.backupDir, { recursive: true });
|
|
10475
10864
|
await writeFile14(`${this.backupDir}/${scope}.md`, content, "utf8");
|
|
10476
10865
|
} catch {
|
|
10477
10866
|
}
|
|
@@ -10657,6 +11046,42 @@ var defaultIndexing = {
|
|
|
10657
11046
|
watchExternal: true,
|
|
10658
11047
|
debounceMs: 400
|
|
10659
11048
|
};
|
|
11049
|
+
var IN_PROJECT_FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
11050
|
+
"provider",
|
|
11051
|
+
"apiKey",
|
|
11052
|
+
"baseUrl",
|
|
11053
|
+
"providers",
|
|
11054
|
+
"mcpServers",
|
|
11055
|
+
"hooks",
|
|
11056
|
+
"plugins",
|
|
11057
|
+
"sync",
|
|
11058
|
+
"yolo",
|
|
11059
|
+
"extensions"
|
|
11060
|
+
]);
|
|
11061
|
+
function stripUnsafeInProjectFields(inProject, sourcePath, warn = (msg) => console.warn(msg)) {
|
|
11062
|
+
const stripped = [];
|
|
11063
|
+
const out = {};
|
|
11064
|
+
for (const [k, v] of Object.entries(inProject)) {
|
|
11065
|
+
if (IN_PROJECT_FORBIDDEN_KEYS.has(k)) {
|
|
11066
|
+
stripped.push(k);
|
|
11067
|
+
continue;
|
|
11068
|
+
}
|
|
11069
|
+
out[k] = v;
|
|
11070
|
+
}
|
|
11071
|
+
if (stripped.length > 0) {
|
|
11072
|
+
warn(
|
|
11073
|
+
JSON.stringify({
|
|
11074
|
+
level: "warn",
|
|
11075
|
+
event: "config.in_project_unsafe_fields_ignored",
|
|
11076
|
+
path: sourcePath,
|
|
11077
|
+
ignoredKeys: stripped,
|
|
11078
|
+
message: `Ignored ${stripped.length} unsafe field(s) from the repo-committed config "${sourcePath}": ${stripped.join(", ")}. These can only be set in your personal ~/.wrongstack/config.json, not in a project-committed file.`,
|
|
11079
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
11080
|
+
})
|
|
11081
|
+
);
|
|
11082
|
+
}
|
|
11083
|
+
return out;
|
|
11084
|
+
}
|
|
10660
11085
|
function deepMerge2(base, patch) {
|
|
10661
11086
|
const opts = { arrayMode: "concat-primitives" };
|
|
10662
11087
|
if (envBoolOptional(process.env.WRONGSTACK_DEBUG_CONFIG)) {
|
|
@@ -10692,7 +11117,7 @@ var DefaultConfigLoader = class {
|
|
|
10692
11117
|
]);
|
|
10693
11118
|
cfg = deepMerge2(cfg, global);
|
|
10694
11119
|
cfg = deepMerge2(cfg, local);
|
|
10695
|
-
cfg = deepMerge2(cfg, inProject);
|
|
11120
|
+
cfg = deepMerge2(cfg, stripUnsafeInProjectFields(inProject, this.paths.inProjectConfig));
|
|
10696
11121
|
for (const [key, fn] of Object.entries(ENV_MAP)) {
|
|
10697
11122
|
const v = process.env[key];
|
|
10698
11123
|
if (v) fn(cfg, v);
|
|
@@ -12085,6 +12510,9 @@ function isClearlyDestructiveBashCommand(command, projectRoot) {
|
|
|
12085
12510
|
}
|
|
12086
12511
|
|
|
12087
12512
|
// src/security/permission-policy.ts
|
|
12513
|
+
function matchesTrust(patterns, subject) {
|
|
12514
|
+
return patterns.includes(subject) || matchAny(patterns, subject);
|
|
12515
|
+
}
|
|
12088
12516
|
var DefaultPermissionPolicy = class {
|
|
12089
12517
|
policy = {};
|
|
12090
12518
|
loaded = false;
|
|
@@ -12221,7 +12649,7 @@ var DefaultPermissionPolicy = class {
|
|
|
12221
12649
|
this._evalCache.set(cacheKey, decision);
|
|
12222
12650
|
return decision;
|
|
12223
12651
|
}
|
|
12224
|
-
if (entry?.deny && subject &&
|
|
12652
|
+
if (entry?.deny && subject && matchesTrust(entry.deny, subject)) {
|
|
12225
12653
|
const decision = { permission: "deny", source: "deny", reason: "matched deny pattern" };
|
|
12226
12654
|
this._evalCache.set(cacheKey, decision);
|
|
12227
12655
|
return decision;
|
|
@@ -12231,7 +12659,7 @@ var DefaultPermissionPolicy = class {
|
|
|
12231
12659
|
this._evalCache.set(cacheKey, decision);
|
|
12232
12660
|
return decision;
|
|
12233
12661
|
}
|
|
12234
|
-
if (entry?.allow && subject &&
|
|
12662
|
+
if (entry?.allow && subject && matchesTrust(entry.allow, subject)) {
|
|
12235
12663
|
const decision = { permission: "auto", source: "trust", reason: "matched allow pattern" };
|
|
12236
12664
|
this._evalCache.set(cacheKey, decision);
|
|
12237
12665
|
return decision;
|
|
@@ -12767,6 +13195,16 @@ function handleMessageStop(state, ev) {
|
|
|
12767
13195
|
async function streamProviderToResponse(provider, req, signal, ctx, events, logger) {
|
|
12768
13196
|
const state = createStreamingState(req.model);
|
|
12769
13197
|
logger.debug("Stream started", { providerId: provider.id, model: req.model });
|
|
13198
|
+
const TEXT_BATCH_SIZE = 4;
|
|
13199
|
+
let pendingText = "";
|
|
13200
|
+
let pendingCount = 0;
|
|
13201
|
+
const flushText = () => {
|
|
13202
|
+
if (pendingCount > 0) {
|
|
13203
|
+
events.emit("provider.text_delta", { ctx, text: pendingText });
|
|
13204
|
+
pendingText = "";
|
|
13205
|
+
pendingCount = 0;
|
|
13206
|
+
}
|
|
13207
|
+
};
|
|
12770
13208
|
const iter = provider.stream(req, { signal })[Symbol.asyncIterator]();
|
|
12771
13209
|
try {
|
|
12772
13210
|
for (; ; ) {
|
|
@@ -12786,9 +13224,12 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12786
13224
|
break;
|
|
12787
13225
|
case "text_delta":
|
|
12788
13226
|
handleTextDelta(state, ev.text);
|
|
12789
|
-
|
|
13227
|
+
pendingText += ev.text;
|
|
13228
|
+
pendingCount++;
|
|
13229
|
+
if (pendingCount >= TEXT_BATCH_SIZE) flushText();
|
|
12790
13230
|
break;
|
|
12791
13231
|
case "tool_use_start": {
|
|
13232
|
+
flushText();
|
|
12792
13233
|
const idVal = ev.id;
|
|
12793
13234
|
const nameVal = ev.name;
|
|
12794
13235
|
handleToolUseStart(state, { id: idVal, name: nameVal });
|
|
@@ -12800,6 +13241,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12800
13241
|
handleToolUseInputDelta(state, ev);
|
|
12801
13242
|
break;
|
|
12802
13243
|
case "tool_use_stop": {
|
|
13244
|
+
flushText();
|
|
12803
13245
|
const stoppedName = state.tools.get(ev.id)?.name ?? "unknown";
|
|
12804
13246
|
handleToolUseStop(state, ev);
|
|
12805
13247
|
events.emit("provider.tool_use_stop", { ctx, id: ev.id, name: stoppedName });
|
|
@@ -12809,6 +13251,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12809
13251
|
handleThinkingStart(state, ev);
|
|
12810
13252
|
break;
|
|
12811
13253
|
case "thinking_delta":
|
|
13254
|
+
flushText();
|
|
12812
13255
|
handleThinkingDelta(state, ev.text);
|
|
12813
13256
|
events.emit("provider.thinking_delta", { ctx, text: ev.text });
|
|
12814
13257
|
break;
|
|
@@ -12840,6 +13283,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12840
13283
|
eventType: String(evAny.type),
|
|
12841
13284
|
errorMessage: errMsg
|
|
12842
13285
|
});
|
|
13286
|
+
flushText();
|
|
12843
13287
|
events.emit("provider.stream_error", {
|
|
12844
13288
|
ctx,
|
|
12845
13289
|
eventType: String(evAny.type),
|
|
@@ -12850,6 +13294,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12850
13294
|
} catch (err) {
|
|
12851
13295
|
if (signal.aborted) {
|
|
12852
13296
|
state.stopReason = "end_turn";
|
|
13297
|
+
flushText();
|
|
12853
13298
|
logger.debug("Stream aborted \u2014 returning partial state", {
|
|
12854
13299
|
providerId: provider.id,
|
|
12855
13300
|
model: req.model,
|
|
@@ -12878,6 +13323,7 @@ async function streamProviderToResponse(provider, req, signal, ctx, events, logg
|
|
|
12878
13323
|
} catch {
|
|
12879
13324
|
}
|
|
12880
13325
|
}
|
|
13326
|
+
flushText();
|
|
12881
13327
|
logger.debug("Stream completed", {
|
|
12882
13328
|
providerId: provider.id,
|
|
12883
13329
|
model: req.model,
|
|
@@ -14734,7 +15180,14 @@ var EternalAutonomyEngine = class {
|
|
|
14734
15180
|
try {
|
|
14735
15181
|
const reloaded = await loadGoal(this.goalPath, this.opts.events);
|
|
14736
15182
|
iterationIndex = reloaded?.iterations ?? 0;
|
|
14737
|
-
} catch {
|
|
15183
|
+
} catch (err) {
|
|
15184
|
+
console.error(JSON.stringify({
|
|
15185
|
+
level: "warn",
|
|
15186
|
+
event: "autonomy.goal_reload_failed",
|
|
15187
|
+
message: toErrorMessage(err),
|
|
15188
|
+
context: { goalPath: this.goalPath },
|
|
15189
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
15190
|
+
}));
|
|
14738
15191
|
}
|
|
14739
15192
|
this.opts.onIteration?.({
|
|
14740
15193
|
at: (this.opts.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -14969,7 +15422,14 @@ ${lastFew}` : "No prior iterations yet.",
|
|
|
14969
15422
|
} finally {
|
|
14970
15423
|
clearTimeout(timer);
|
|
14971
15424
|
}
|
|
14972
|
-
} catch {
|
|
15425
|
+
} catch (err) {
|
|
15426
|
+
console.error(JSON.stringify({
|
|
15427
|
+
level: "warn",
|
|
15428
|
+
event: "autonomy.brainstorm_failed",
|
|
15429
|
+
message: toErrorMessage(err),
|
|
15430
|
+
context: { goal: goal.goal.slice(0, 100) },
|
|
15431
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
15432
|
+
}));
|
|
14973
15433
|
return null;
|
|
14974
15434
|
}
|
|
14975
15435
|
}
|
|
@@ -18849,6 +19309,68 @@ Working rules:
|
|
|
18849
19309
|
- When in doubt, flag as medium rather than ignoring potential issues`
|
|
18850
19310
|
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
18851
19311
|
};
|
|
19312
|
+
var SHADOW_AGENT = {
|
|
19313
|
+
id: "shadow-agent",
|
|
19314
|
+
name: "Shadow",
|
|
19315
|
+
role: "shadow-agent",
|
|
19316
|
+
prompt: `You are the Shadow Agent \u2014 a silent background monitor for the WrongStack fleet.
|
|
19317
|
+
|
|
19318
|
+
Your job is to observe, detect anomalies, and be ready to intervene \u2014 but only when commanded.
|
|
19319
|
+
|
|
19320
|
+
## Core Responsibilities
|
|
19321
|
+
|
|
19322
|
+
1. **Fleet Monitoring** (every 30s)
|
|
19323
|
+
- Call \`fleet_status\` + \`fleet_health\` on each heartbeat
|
|
19324
|
+
- Track what each agent is doing (task descriptions)
|
|
19325
|
+
- Detect stuck agents (>5min no events), idle agents, crashed agents
|
|
19326
|
+
|
|
19327
|
+
2. **FleetBus Subscription**
|
|
19328
|
+
- Subscribe to \`subagent.*\` events to track lifecycle
|
|
19329
|
+
- Subscribe to \`tool.executed\` to monitor activity
|
|
19330
|
+
- Track agent joins (subagent.started) and leaves (subagent.stopped)
|
|
19331
|
+
|
|
19332
|
+
3. **Mailbox Surveillance**
|
|
19333
|
+
- Monitor for \`control\` type messages starting with "hoop"
|
|
19334
|
+
- Detect orphan assigns (assign without result within 5min)
|
|
19335
|
+
- Cross-session awareness via shared project mailbox
|
|
19336
|
+
|
|
19337
|
+
4. **Spike Detection**
|
|
19338
|
+
- Track task duration per agent
|
|
19339
|
+
- Flag agents that spawn and die within <5 seconds
|
|
19340
|
+
- Log spike events with reason (completed/error/killed/timeout)
|
|
19341
|
+
|
|
19342
|
+
5. **Intervention Commands**
|
|
19343
|
+
Parse these from mailbox control messages:
|
|
19344
|
+
- \`hoop <agentId>\` \u2014 terminate specific agent
|
|
19345
|
+
- \`hoop all\` \u2014 terminate all running agents
|
|
19346
|
+
- \`shadow status\` \u2014 report current fleet snapshot
|
|
19347
|
+
- \`shadow mute\` \u2014 pause heartbeat monitoring
|
|
19348
|
+
- \`shadow resume\` \u2014 resume heartbeat monitoring
|
|
19349
|
+
- \`shadow interval <ms>\` \u2014 change heartbeat interval
|
|
19350
|
+
- \`shadow model <model-id>\` \u2014 change analysis model
|
|
19351
|
+
|
|
19352
|
+
## Operating Rules
|
|
19353
|
+
|
|
19354
|
+
- **Silent by default**: Use DEBUG level logging unless anomaly detected
|
|
19355
|
+
- **Deterministic**: Same state always produces same actions \u2014 no randomness
|
|
19356
|
+
- **Report on anomaly**: When anomaly detected, use \`mail_send\` to broadcast warning
|
|
19357
|
+
- **Never auto-intervene**: Always report unless explicitly commanded
|
|
19358
|
+
- **Minimal footprint**: Small state, efficient snapshots
|
|
19359
|
+
|
|
19360
|
+
## Startup Sequence
|
|
19361
|
+
|
|
19362
|
+
1. Send broadcast: \`shadow:started { intervalMs, model, startTime }\`
|
|
19363
|
+
2. Subscribe to FleetBus for all relevant events
|
|
19364
|
+
3. Schedule heartbeat cron job at configured interval
|
|
19365
|
+
4. Wait for commands or anomalies
|
|
19366
|
+
|
|
19367
|
+
## Shutdown Sequence
|
|
19368
|
+
|
|
19369
|
+
1. Cancel all cron jobs (\`cron_cancel\`)
|
|
19370
|
+
2. Send broadcast: \`shadow:stopped { reason, finalState }\`
|
|
19371
|
+
3. Clean up FleetBus subscriptions`
|
|
19372
|
+
// Budgets are set by the orchestrator per task — see fleet.ts header.
|
|
19373
|
+
};
|
|
18852
19374
|
var CRITIC_AGENT = {
|
|
18853
19375
|
id: "critic",
|
|
18854
19376
|
name: "Critic",
|
|
@@ -18889,6 +19411,7 @@ var FLEET_ROSTER = {
|
|
|
18889
19411
|
"refactor-planner": REFACTOR_PLANNER_AGENT,
|
|
18890
19412
|
"security-scanner": SECURITY_SCANNER_AGENT,
|
|
18891
19413
|
"critic": CRITIC_AGENT,
|
|
19414
|
+
"shadow-agent": SHADOW_AGENT,
|
|
18892
19415
|
...Object.fromEntries(
|
|
18893
19416
|
ALL_AGENT_DEFINITIONS.map((d) => [d.config.role, d.config])
|
|
18894
19417
|
)
|
|
@@ -18900,6 +19423,8 @@ var FLEET_ROSTER_BUDGETS = {
|
|
|
18900
19423
|
"refactor-planner": { timeoutMs: 7.5 * 60 * 60 * 1e3, maxIterations: 6e3, maxToolCalls: 18e3 },
|
|
18901
19424
|
"security-scanner": { timeoutMs: 10 * 60 * 60 * 1e3, maxIterations: 8e3, maxToolCalls: 2e4 },
|
|
18902
19425
|
"critic": { timeoutMs: 5 * 60 * 60 * 1e3, maxIterations: 4e3, maxToolCalls: 12e3 },
|
|
19426
|
+
"shadow-agent": { timeoutMs: 24 * 60 * 60 * 1e3, maxIterations: 1e4, maxToolCalls: 5e3 },
|
|
19427
|
+
// Long-running background monitor
|
|
18903
19428
|
...Object.fromEntries(
|
|
18904
19429
|
ALL_AGENT_DEFINITIONS.map((d) => [d.config.role, d.budget])
|
|
18905
19430
|
)
|
|
@@ -20107,7 +20632,14 @@ ${personaLine}Task: ${task}
|
|
|
20107
20632
|
subagentIds.push(subagentId);
|
|
20108
20633
|
taskIds.push(taskId);
|
|
20109
20634
|
await coordinator.assign(spec);
|
|
20110
|
-
} catch {
|
|
20635
|
+
} catch (err) {
|
|
20636
|
+
console.error(JSON.stringify({
|
|
20637
|
+
level: "warn",
|
|
20638
|
+
event: "parallel_engine.spawn_failed",
|
|
20639
|
+
message: toErrorMessage(err),
|
|
20640
|
+
context: { slot: i, task, subagentId },
|
|
20641
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20642
|
+
}));
|
|
20111
20643
|
}
|
|
20112
20644
|
})()
|
|
20113
20645
|
);
|
|
@@ -20132,7 +20664,14 @@ ${personaLine}Task: ${task}
|
|
|
20132
20664
|
} finally {
|
|
20133
20665
|
clearTimeout(timer);
|
|
20134
20666
|
}
|
|
20135
|
-
} catch {
|
|
20667
|
+
} catch (err) {
|
|
20668
|
+
console.error(JSON.stringify({
|
|
20669
|
+
level: "warn",
|
|
20670
|
+
event: "parallel_engine.brainstorm_results_failed",
|
|
20671
|
+
message: toErrorMessage(err),
|
|
20672
|
+
context: { slotCount, taskIds },
|
|
20673
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20674
|
+
}));
|
|
20136
20675
|
results = coordinator.results().slice(-taskIds.length);
|
|
20137
20676
|
}
|
|
20138
20677
|
await Promise.allSettled(subagentIds.map((id) => coordinator.remove(id)));
|
|
@@ -20166,7 +20705,14 @@ ${personaLine}Task: ${task}
|
|
|
20166
20705
|
if (file) tasks.push(`[git] inspect and fix: ${file}`);
|
|
20167
20706
|
}
|
|
20168
20707
|
}
|
|
20169
|
-
} catch {
|
|
20708
|
+
} catch (err) {
|
|
20709
|
+
console.error(JSON.stringify({
|
|
20710
|
+
level: "warn",
|
|
20711
|
+
event: "parallel_engine.git_status_failed",
|
|
20712
|
+
message: toErrorMessage(err),
|
|
20713
|
+
context: { projectRoot: this.opts.projectRoot },
|
|
20714
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
20715
|
+
}));
|
|
20170
20716
|
}
|
|
20171
20717
|
}
|
|
20172
20718
|
if (tasks.length < this.slots) {
|
|
@@ -20520,7 +21066,7 @@ var CollabSession = class extends EventEmitter {
|
|
|
20520
21066
|
}
|
|
20521
21067
|
for (const filePath of allFiles) {
|
|
20522
21068
|
try {
|
|
20523
|
-
const [content,
|
|
21069
|
+
const [content, stat16] = await Promise.all([
|
|
20524
21070
|
fsp3.readFile(filePath, "utf8"),
|
|
20525
21071
|
fsp3.stat(filePath)
|
|
20526
21072
|
]);
|
|
@@ -20530,8 +21076,8 @@ var CollabSession = class extends EventEmitter {
|
|
|
20530
21076
|
path: filePath,
|
|
20531
21077
|
content,
|
|
20532
21078
|
language,
|
|
20533
|
-
snapshotMtimeMs:
|
|
20534
|
-
snapshotSizeBytes:
|
|
21079
|
+
snapshotMtimeMs: stat16.mtimeMs,
|
|
21080
|
+
snapshotSizeBytes: stat16.size
|
|
20535
21081
|
});
|
|
20536
21082
|
} catch {
|
|
20537
21083
|
this.snapshot.files.push({ path: filePath, content: "", language: void 0 });
|
|
@@ -20944,9 +21490,9 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
|
|
|
20944
21490
|
for (const file of this.snapshot.files) {
|
|
20945
21491
|
if (file.snapshotMtimeMs === void 0 && file.snapshotSizeBytes === void 0) continue;
|
|
20946
21492
|
try {
|
|
20947
|
-
const
|
|
20948
|
-
const mtimeChanged = file.snapshotMtimeMs !== void 0 &&
|
|
20949
|
-
const sizeChanged = file.snapshotSizeBytes !== void 0 &&
|
|
21493
|
+
const stat16 = await fsp3.stat(file.path);
|
|
21494
|
+
const mtimeChanged = file.snapshotMtimeMs !== void 0 && stat16.mtimeMs > file.snapshotMtimeMs + 1;
|
|
21495
|
+
const sizeChanged = file.snapshotSizeBytes !== void 0 && stat16.size !== file.snapshotSizeBytes;
|
|
20950
21496
|
if (mtimeChanged || sizeChanged) {
|
|
20951
21497
|
warnings.push(`${file.path} changed after the collab snapshot was captured.`);
|
|
20952
21498
|
}
|
|
@@ -23707,8 +24253,8 @@ async function loadProjectModes(modesDir) {
|
|
|
23707
24253
|
for (const entry of entries) {
|
|
23708
24254
|
if (!entry.endsWith(".md") && !entry.endsWith(".txt")) continue;
|
|
23709
24255
|
const filePath = path3.join(modesDir, entry);
|
|
23710
|
-
const
|
|
23711
|
-
if (!
|
|
24256
|
+
const stat16 = await fsp3.stat(filePath);
|
|
24257
|
+
if (!stat16.isFile()) continue;
|
|
23712
24258
|
const content = await fsp3.readFile(filePath, "utf8");
|
|
23713
24259
|
const id = path3.basename(entry, path3.extname(entry));
|
|
23714
24260
|
modes.push({
|
|
@@ -25045,10 +25591,10 @@ var AISpecBuilder = class {
|
|
|
25045
25591
|
async saveSession() {
|
|
25046
25592
|
if (!this.sessionPath) return;
|
|
25047
25593
|
try {
|
|
25048
|
-
const
|
|
25049
|
-
const
|
|
25594
|
+
const fsp26 = await import('fs/promises');
|
|
25595
|
+
const path50 = await import('path');
|
|
25050
25596
|
const { atomicWrite: atomicWrite2 } = await Promise.resolve().then(() => (init_atomic_write(), atomic_write_exports));
|
|
25051
|
-
await
|
|
25597
|
+
await fsp26.mkdir(path50.dirname(this.sessionPath), { recursive: true });
|
|
25052
25598
|
await atomicWrite2(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
25053
25599
|
} catch {
|
|
25054
25600
|
}
|
|
@@ -25057,8 +25603,8 @@ var AISpecBuilder = class {
|
|
|
25057
25603
|
async loadSession() {
|
|
25058
25604
|
if (!this.sessionPath) return false;
|
|
25059
25605
|
try {
|
|
25060
|
-
const
|
|
25061
|
-
const raw = await
|
|
25606
|
+
const fsp26 = await import('fs/promises');
|
|
25607
|
+
const raw = await fsp26.readFile(this.sessionPath, "utf8");
|
|
25062
25608
|
const loaded = JSON.parse(raw);
|
|
25063
25609
|
if (loaded?.id && loaded?.phase && loaded?.title) {
|
|
25064
25610
|
this.session = loaded;
|
|
@@ -25072,8 +25618,8 @@ var AISpecBuilder = class {
|
|
|
25072
25618
|
async deleteSession() {
|
|
25073
25619
|
if (!this.sessionPath) return;
|
|
25074
25620
|
try {
|
|
25075
|
-
const
|
|
25076
|
-
await
|
|
25621
|
+
const fsp26 = await import('fs/promises');
|
|
25622
|
+
await fsp26.unlink(this.sessionPath);
|
|
25077
25623
|
} catch {
|
|
25078
25624
|
}
|
|
25079
25625
|
}
|
|
@@ -25775,15 +26321,15 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
|
|
|
25775
26321
|
maxId = id;
|
|
25776
26322
|
}
|
|
25777
26323
|
}
|
|
25778
|
-
const
|
|
26324
|
+
const path50 = [];
|
|
25779
26325
|
let current = maxId;
|
|
25780
26326
|
const visited = /* @__PURE__ */ new Set();
|
|
25781
26327
|
while (current && !visited.has(current)) {
|
|
25782
26328
|
visited.add(current);
|
|
25783
|
-
|
|
26329
|
+
path50.unshift(current);
|
|
25784
26330
|
current = prev.get(current) ?? null;
|
|
25785
26331
|
}
|
|
25786
|
-
return
|
|
26332
|
+
return path50;
|
|
25787
26333
|
}
|
|
25788
26334
|
function computeParallelGroups(graph, blockedByMap) {
|
|
25789
26335
|
const groups = [];
|
|
@@ -26791,7 +27337,7 @@ async function startMetricsServer(opts) {
|
|
|
26791
27337
|
const tls = opts.tls;
|
|
26792
27338
|
const useHttps = !!(tls?.cert && tls?.key);
|
|
26793
27339
|
const host = opts.host ?? "127.0.0.1";
|
|
26794
|
-
const
|
|
27340
|
+
const path50 = opts.path ?? "/metrics";
|
|
26795
27341
|
const healthPath = opts.healthPath ?? "/healthz";
|
|
26796
27342
|
const healthRegistry = opts.healthRegistry;
|
|
26797
27343
|
const listener = (req, res) => {
|
|
@@ -26801,7 +27347,7 @@ async function startMetricsServer(opts) {
|
|
|
26801
27347
|
return;
|
|
26802
27348
|
}
|
|
26803
27349
|
const url = req.url.split("?")[0];
|
|
26804
|
-
if (url ===
|
|
27350
|
+
if (url === path50) {
|
|
26805
27351
|
let body;
|
|
26806
27352
|
try {
|
|
26807
27353
|
body = renderPrometheus(opts.sink.snapshot());
|
|
@@ -26865,7 +27411,7 @@ async function startMetricsServer(opts) {
|
|
|
26865
27411
|
const protocol = useHttps ? "https" : "http";
|
|
26866
27412
|
return {
|
|
26867
27413
|
port: boundPort,
|
|
26868
|
-
url: `${protocol}://${host}:${boundPort}${
|
|
27414
|
+
url: `${protocol}://${host}:${boundPort}${path50}`,
|
|
26869
27415
|
close: () => new Promise((resolve18, reject) => {
|
|
26870
27416
|
server.close((err) => err ? reject(err) : resolve18());
|
|
26871
27417
|
})
|
|
@@ -27804,13 +28350,13 @@ var SkillInstaller = class {
|
|
|
27804
28350
|
context: { reason: "path_traversal", skillName: skill.name }
|
|
27805
28351
|
});
|
|
27806
28352
|
}
|
|
27807
|
-
const
|
|
27808
|
-
if (
|
|
28353
|
+
const stat16 = await fsp3.stat(srcPath);
|
|
28354
|
+
if (stat16.size > MAX_SKILL_FILE_SIZE) {
|
|
27809
28355
|
throw new FsError({
|
|
27810
|
-
message: `Skill file "${file}" is too large (${(
|
|
28356
|
+
message: `Skill file "${file}" is too large (${(stat16.size / 1024).toFixed(1)}KB). Max: ${MAX_SKILL_FILE_SIZE / 1024}KB`,
|
|
27811
28357
|
code: ERROR_CODES.FS_WRITE_FAILED,
|
|
27812
28358
|
path: srcPath,
|
|
27813
|
-
context: { skillName: skill.name, fileSize:
|
|
28359
|
+
context: { skillName: skill.name, fileSize: stat16.size, maxSize: MAX_SKILL_FILE_SIZE }
|
|
27814
28360
|
});
|
|
27815
28361
|
}
|
|
27816
28362
|
await fsp3.mkdir(path3.dirname(destPath), { recursive: true });
|
|
@@ -28068,6 +28614,12 @@ var GraphMemoryBackend = class {
|
|
|
28068
28614
|
edges = [];
|
|
28069
28615
|
loadedScope = null;
|
|
28070
28616
|
loaded = false;
|
|
28617
|
+
/**
|
|
28618
|
+
* Promise that resolves when the current in-flight _saveGraph completes.
|
|
28619
|
+
* Tests call flush() to await this before deleting the backend or its temp dir.
|
|
28620
|
+
* Each save operation chains onto the previous one so concurrent saves are serialised.
|
|
28621
|
+
*/
|
|
28622
|
+
_saveDone = Promise.resolve();
|
|
28071
28623
|
constructor(opts) {
|
|
28072
28624
|
this.file = new FileMemoryBackend({ paths: opts.paths });
|
|
28073
28625
|
this.graphFile = opts.graphPath ?? `${opts.paths.projectDir}/memory-graph.json`;
|
|
@@ -28094,7 +28646,8 @@ var GraphMemoryBackend = class {
|
|
|
28094
28646
|
tags: entry.tags,
|
|
28095
28647
|
priority: entry.priority
|
|
28096
28648
|
});
|
|
28097
|
-
|
|
28649
|
+
const recentNodes = [...this.nodes.values()].slice(-100);
|
|
28650
|
+
for (const other of recentNodes) {
|
|
28098
28651
|
if (other.id === nodeId) continue;
|
|
28099
28652
|
const sim = wordOverlap(entry.text, other.entry.text);
|
|
28100
28653
|
const tagSim = sharedTags(entry.tags ?? [], other.tags ?? []);
|
|
@@ -28110,7 +28663,8 @@ var GraphMemoryBackend = class {
|
|
|
28110
28663
|
}
|
|
28111
28664
|
}
|
|
28112
28665
|
}
|
|
28113
|
-
|
|
28666
|
+
this._saveDone = this._saveGraph(scope);
|
|
28667
|
+
await this._saveDone;
|
|
28114
28668
|
}
|
|
28115
28669
|
async forget(scope, query, filePath) {
|
|
28116
28670
|
const removed = await this.file.forget(scope, query, filePath);
|
|
@@ -28125,7 +28679,8 @@ var GraphMemoryBackend = class {
|
|
|
28125
28679
|
}
|
|
28126
28680
|
for (const id of toRemove) this.nodes.delete(id);
|
|
28127
28681
|
this.edges = this.edges.filter((e) => !toRemove.includes(e.from) && !toRemove.includes(e.to));
|
|
28128
|
-
|
|
28682
|
+
this._saveDone = this._saveGraph(scope);
|
|
28683
|
+
await this._saveDone;
|
|
28129
28684
|
}
|
|
28130
28685
|
return removed;
|
|
28131
28686
|
}
|
|
@@ -28237,7 +28792,8 @@ var GraphMemoryBackend = class {
|
|
|
28237
28792
|
this.loadedScope = scope;
|
|
28238
28793
|
this.loaded = true;
|
|
28239
28794
|
}
|
|
28240
|
-
|
|
28795
|
+
/** Fire-and-forget graph persistence. Named _saveGraph to signal it must not be awaited. */
|
|
28796
|
+
async _saveGraph(scope) {
|
|
28241
28797
|
this.loadedScope = scope;
|
|
28242
28798
|
this.loaded = true;
|
|
28243
28799
|
try {
|
|
@@ -28245,16 +28801,21 @@ var GraphMemoryBackend = class {
|
|
|
28245
28801
|
nodes: [...this.nodes.entries()],
|
|
28246
28802
|
edges: this.edges
|
|
28247
28803
|
};
|
|
28248
|
-
|
|
28249
|
-
|
|
28250
|
-
{ recursive: true }
|
|
28251
|
-
);
|
|
28804
|
+
const dir = this.graphFile.substring(0, this.graphFile.lastIndexOf("/"));
|
|
28805
|
+
await fsp3.mkdir(dir, { recursive: true });
|
|
28252
28806
|
const tmp = `${this.graphFile}.tmp`;
|
|
28253
28807
|
await fsp3.writeFile(tmp, JSON.stringify(data));
|
|
28254
28808
|
await fsp3.rename(tmp, this.graphFile);
|
|
28255
28809
|
} catch {
|
|
28256
28810
|
}
|
|
28257
28811
|
}
|
|
28812
|
+
/**
|
|
28813
|
+
* Wait for all in-flight _saveGraph operations to complete.
|
|
28814
|
+
* Call this before deleting the backend or its temp directory.
|
|
28815
|
+
*/
|
|
28816
|
+
async flush() {
|
|
28817
|
+
await this._saveDone;
|
|
28818
|
+
}
|
|
28258
28819
|
};
|
|
28259
28820
|
function wordOverlap(a, b) {
|
|
28260
28821
|
const wordsA = new Set(a.toLowerCase().split(/\s+/).filter((w) => w.length > 2));
|
|
@@ -28355,84 +28916,89 @@ var SessionMemoryConsolidator = class {
|
|
|
28355
28916
|
this.minIterations = opts.minIterations ?? 2;
|
|
28356
28917
|
this.maxExistingEntries = opts.maxExistingEntries ?? 15;
|
|
28357
28918
|
}
|
|
28358
|
-
afterRun =
|
|
28919
|
+
afterRun = (ctx, result) => {
|
|
28359
28920
|
if (result.status !== "done") return;
|
|
28360
28921
|
if (!result.finalText || result.finalText.trim().length < 20) return;
|
|
28361
28922
|
if (result.iterations < this.minIterations) return;
|
|
28362
28923
|
const provider = this.provider ?? ctx.provider;
|
|
28363
28924
|
if (!provider?.complete) return;
|
|
28364
|
-
|
|
28365
|
-
|
|
28366
|
-
|
|
28367
|
-
|
|
28368
|
-
|
|
28369
|
-
existingEntries
|
|
28370
|
-
|
|
28371
|
-
|
|
28372
|
-
|
|
28373
|
-
|
|
28374
|
-
|
|
28375
|
-
|
|
28376
|
-
|
|
28377
|
-
|
|
28378
|
-
|
|
28379
|
-
|
|
28380
|
-
|
|
28381
|
-
|
|
28382
|
-
|
|
28383
|
-
|
|
28384
|
-
|
|
28385
|
-
|
|
28386
|
-
|
|
28387
|
-
|
|
28388
|
-
|
|
28389
|
-
|
|
28390
|
-
|
|
28391
|
-
|
|
28392
|
-
|
|
28393
|
-
|
|
28394
|
-
|
|
28395
|
-
|
|
28396
|
-
|
|
28397
|
-
|
|
28398
|
-
|
|
28399
|
-
|
|
28400
|
-
|
|
28401
|
-
|
|
28925
|
+
const _finalText = result.finalText;
|
|
28926
|
+
const _iterations = result.iterations;
|
|
28927
|
+
const _model = this.model ?? ctx.model;
|
|
28928
|
+
void (async () => {
|
|
28929
|
+
try {
|
|
28930
|
+
const existingEntries = await this.memoryStore.list("project-memory", this.maxExistingEntries);
|
|
28931
|
+
const prompt = buildConsolidationPrompt(
|
|
28932
|
+
_finalText,
|
|
28933
|
+
_iterations,
|
|
28934
|
+
existingEntries
|
|
28935
|
+
);
|
|
28936
|
+
const signal = AbortSignal.timeout(15e3);
|
|
28937
|
+
const response = await provider.complete(
|
|
28938
|
+
{
|
|
28939
|
+
model: _model,
|
|
28940
|
+
system: [{ type: "text", text: prompt }],
|
|
28941
|
+
messages: [
|
|
28942
|
+
{ role: "user", content: "Review the session and return memory operations as JSON." }
|
|
28943
|
+
],
|
|
28944
|
+
maxTokens: 500
|
|
28945
|
+
},
|
|
28946
|
+
{ signal }
|
|
28947
|
+
);
|
|
28948
|
+
const text = response.content.filter((b) => b.type === "text").map((b) => b.text).join("").trim();
|
|
28949
|
+
if (!text) return;
|
|
28950
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
28951
|
+
if (!jsonMatch) return;
|
|
28952
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
28953
|
+
if (!Array.isArray(parsed.operations) || parsed.operations.length === 0) return;
|
|
28954
|
+
let added = 0;
|
|
28955
|
+
let edited = 0;
|
|
28956
|
+
let deleted = 0;
|
|
28957
|
+
for (const op of parsed.operations) {
|
|
28958
|
+
switch (op.action) {
|
|
28959
|
+
case "add": {
|
|
28960
|
+
if (op.text?.trim()) {
|
|
28961
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
28962
|
+
type: op.type,
|
|
28963
|
+
tags: op.tags,
|
|
28964
|
+
priority: op.priority
|
|
28965
|
+
});
|
|
28966
|
+
added++;
|
|
28967
|
+
}
|
|
28968
|
+
break;
|
|
28402
28969
|
}
|
|
28403
|
-
|
|
28404
|
-
|
|
28405
|
-
|
|
28406
|
-
|
|
28407
|
-
|
|
28408
|
-
|
|
28409
|
-
|
|
28410
|
-
|
|
28411
|
-
|
|
28412
|
-
}
|
|
28413
|
-
|
|
28970
|
+
case "edit": {
|
|
28971
|
+
if (op.query && op.text?.trim()) {
|
|
28972
|
+
await this.memoryStore.forget(op.query);
|
|
28973
|
+
await this.memoryStore.remember(op.text.trim(), void 0, {
|
|
28974
|
+
type: op.type,
|
|
28975
|
+
tags: op.tags,
|
|
28976
|
+
priority: op.priority
|
|
28977
|
+
});
|
|
28978
|
+
edited++;
|
|
28979
|
+
}
|
|
28980
|
+
break;
|
|
28414
28981
|
}
|
|
28415
|
-
|
|
28416
|
-
|
|
28417
|
-
|
|
28418
|
-
|
|
28419
|
-
|
|
28420
|
-
|
|
28982
|
+
case "delete": {
|
|
28983
|
+
if (op.query) {
|
|
28984
|
+
const n = await this.memoryStore.forget(op.query);
|
|
28985
|
+
deleted += n;
|
|
28986
|
+
}
|
|
28987
|
+
break;
|
|
28421
28988
|
}
|
|
28422
|
-
break;
|
|
28423
28989
|
}
|
|
28424
28990
|
}
|
|
28425
|
-
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28429
|
-
|
|
28430
|
-
|
|
28431
|
-
process.stderr.write(`[memory] Session consolidation: ${parts.join(", ")}
|
|
28991
|
+
if (added > 0 || edited > 0 || deleted > 0) {
|
|
28992
|
+
const parts = [];
|
|
28993
|
+
if (added) parts.push(`${added} added`);
|
|
28994
|
+
if (edited) parts.push(`${edited} edited`);
|
|
28995
|
+
if (deleted) parts.push(`${deleted} deleted`);
|
|
28996
|
+
process.stderr.write(`[memory] Session consolidation: ${parts.join(", ")}
|
|
28432
28997
|
`);
|
|
28998
|
+
}
|
|
28999
|
+
} catch {
|
|
28433
29000
|
}
|
|
28434
|
-
}
|
|
28435
|
-
}
|
|
29001
|
+
})();
|
|
28436
29002
|
};
|
|
28437
29003
|
};
|
|
28438
29004
|
function sessionScopedPath(dir, sessionId, suffix) {
|
|
@@ -29059,15 +29625,15 @@ var SessionRecovery = class {
|
|
|
29059
29625
|
async detectStale(sessionId) {
|
|
29060
29626
|
const fp = this.filePath(sessionId);
|
|
29061
29627
|
const TAIL_SIZE = 8192;
|
|
29062
|
-
let
|
|
29628
|
+
let stat16;
|
|
29063
29629
|
try {
|
|
29064
|
-
|
|
29630
|
+
stat16 = await fsp3.stat(fp);
|
|
29065
29631
|
} catch (err) {
|
|
29066
29632
|
if (err.code === "ENOENT") return null;
|
|
29067
29633
|
return null;
|
|
29068
29634
|
}
|
|
29069
|
-
if (
|
|
29070
|
-
const position = Math.max(0,
|
|
29635
|
+
if (stat16.size === 0) return null;
|
|
29636
|
+
const position = Math.max(0, stat16.size - TAIL_SIZE);
|
|
29071
29637
|
const buf = Buffer.alloc(TAIL_SIZE);
|
|
29072
29638
|
let fh;
|
|
29073
29639
|
try {
|
|
@@ -29545,6 +30111,9 @@ var AgentStatusTracker = class {
|
|
|
29545
30111
|
leaderName;
|
|
29546
30112
|
// Live agent map: agentId → AgentEntry
|
|
29547
30113
|
agents = /* @__PURE__ */ new Map();
|
|
30114
|
+
// Last full agent list flushed (leader + subagents). Lets external consumers
|
|
30115
|
+
// read the current state synchronously without re-deriving it.
|
|
30116
|
+
lastAgents = [];
|
|
29548
30117
|
// Leader tracking
|
|
29549
30118
|
leaderStatus = "idle";
|
|
29550
30119
|
leaderCurrentTool;
|
|
@@ -29566,6 +30135,10 @@ var AgentStatusTracker = class {
|
|
|
29566
30135
|
this.leaderName = opts.leaderName ?? "leader";
|
|
29567
30136
|
this.onUpdate = opts.onUpdate;
|
|
29568
30137
|
}
|
|
30138
|
+
/** Current full agent list (leader + subagents) as of the last flush. */
|
|
30139
|
+
getAgents() {
|
|
30140
|
+
return this.lastAgents.length > 0 ? [...this.lastAgents] : [];
|
|
30141
|
+
}
|
|
29569
30142
|
start() {
|
|
29570
30143
|
this.unsubscribers.push(
|
|
29571
30144
|
this.events.onPattern("agent.run.started", () => {
|
|
@@ -29807,6 +30380,11 @@ var AgentStatusTracker = class {
|
|
|
29807
30380
|
lastActivityAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
29808
30381
|
};
|
|
29809
30382
|
const allAgents = [leaderEntry, ...this.agents.values()];
|
|
30383
|
+
this.lastAgents = allAgents;
|
|
30384
|
+
try {
|
|
30385
|
+
this.events.emit("session.agents_updated", { agents: allAgents });
|
|
30386
|
+
} catch {
|
|
30387
|
+
}
|
|
29810
30388
|
this.registry.updateAgents(allAgents).then(() => {
|
|
29811
30389
|
try {
|
|
29812
30390
|
this.onUpdate?.();
|
|
@@ -30466,8 +31044,8 @@ var CloudSync = class {
|
|
|
30466
31044
|
const localPath = this.categoryToPath(cat);
|
|
30467
31045
|
if (!localPath) continue;
|
|
30468
31046
|
try {
|
|
30469
|
-
const
|
|
30470
|
-
if (
|
|
31047
|
+
const stat16 = await fsp3.stat(localPath);
|
|
31048
|
+
if (stat16.isDirectory()) {
|
|
30471
31049
|
const files = await this.walkDir(localPath, localPath);
|
|
30472
31050
|
for (const file of files) {
|
|
30473
31051
|
const content = await fsp3.readFile(file, "utf8");
|
|
@@ -30492,8 +31070,8 @@ var CloudSync = class {
|
|
|
30492
31070
|
const localPath = this.categoryToPath(cat);
|
|
30493
31071
|
if (!localPath) continue;
|
|
30494
31072
|
try {
|
|
30495
|
-
const
|
|
30496
|
-
if (
|
|
31073
|
+
const stat16 = await fsp3.stat(localPath);
|
|
31074
|
+
if (stat16.isDirectory()) {
|
|
30497
31075
|
const files = await this.walkDir(localPath, localPath);
|
|
30498
31076
|
for (const file of files) {
|
|
30499
31077
|
const content = await fsp3.readFile(file);
|
|
@@ -30684,7 +31262,13 @@ function parseHqFrame(raw) {
|
|
|
30684
31262
|
}
|
|
30685
31263
|
}
|
|
30686
31264
|
}
|
|
30687
|
-
var KNOWN_HQ_EVENT_PAYLOAD_TYPES = /* @__PURE__ */ new Set([
|
|
31265
|
+
var KNOWN_HQ_EVENT_PAYLOAD_TYPES = /* @__PURE__ */ new Set([
|
|
31266
|
+
"mailbox.snapshot",
|
|
31267
|
+
"mailbox.event",
|
|
31268
|
+
"session.snapshot",
|
|
31269
|
+
"session.transcript",
|
|
31270
|
+
"session.ended"
|
|
31271
|
+
]);
|
|
30688
31272
|
function isHqMailboxMessageSummary(x) {
|
|
30689
31273
|
if (typeof x !== "object" || x === null) return false;
|
|
30690
31274
|
const v = x;
|
|
@@ -30731,6 +31315,52 @@ function isHqMailboxEventPayload(x) {
|
|
|
30731
31315
|
if (v.agent !== void 0 && !isHqMailboxAgentSummary(v.agent)) return false;
|
|
30732
31316
|
return true;
|
|
30733
31317
|
}
|
|
31318
|
+
var HQ_SESSION_AGENT_STATUSES = /* @__PURE__ */ new Set([
|
|
31319
|
+
"idle",
|
|
31320
|
+
"running",
|
|
31321
|
+
"streaming",
|
|
31322
|
+
"waiting_user",
|
|
31323
|
+
"error"
|
|
31324
|
+
]);
|
|
31325
|
+
function isHqSessionAgentSummary(x) {
|
|
31326
|
+
if (typeof x !== "object" || x === null) return false;
|
|
31327
|
+
const v = x;
|
|
31328
|
+
return typeof v.id === "string" && typeof v.name === "string" && typeof v.status === "string" && HQ_SESSION_AGENT_STATUSES.has(v.status) && typeof v.iterations === "number" && typeof v.toolCalls === "number" && typeof v.lastActivityAt === "string";
|
|
31329
|
+
}
|
|
31330
|
+
var HQ_SESSION_STATUSES = /* @__PURE__ */ new Set(["active", "idle", "closing", "stale"]);
|
|
31331
|
+
function isHqSessionSnapshotPayload(x) {
|
|
31332
|
+
if (typeof x !== "object" || x === null) return false;
|
|
31333
|
+
const v = x;
|
|
31334
|
+
if (typeof v.sessionId !== "string" || typeof v.clientKind !== "string" || typeof v.machineId !== "string" || typeof v.projectId !== "string" || typeof v.projectName !== "string" || typeof v.projectRoot !== "string" || typeof v.status !== "string" || !HQ_SESSION_STATUSES.has(v.status) || typeof v.startedAt !== "string" || typeof v.lastActivityAt !== "string" || typeof v.agentCount !== "number" || !Array.isArray(v.agents)) {
|
|
31335
|
+
return false;
|
|
31336
|
+
}
|
|
31337
|
+
for (const agent of v.agents) {
|
|
31338
|
+
if (!isHqSessionAgentSummary(agent)) return false;
|
|
31339
|
+
}
|
|
31340
|
+
return true;
|
|
31341
|
+
}
|
|
31342
|
+
var HQ_TRANSCRIPT_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "error"]);
|
|
31343
|
+
function isHqTranscriptEntry(x) {
|
|
31344
|
+
if (typeof x !== "object" || x === null) return false;
|
|
31345
|
+
const v = x;
|
|
31346
|
+
return typeof v.ts === "string" && typeof v.role === "string" && HQ_TRANSCRIPT_ROLES.has(v.role) && typeof v.text === "string";
|
|
31347
|
+
}
|
|
31348
|
+
function isHqTranscriptAppendPayload(x) {
|
|
31349
|
+
if (typeof x !== "object" || x === null) return false;
|
|
31350
|
+
const v = x;
|
|
31351
|
+
if (typeof v.sessionId !== "string" || typeof v.fromSeq !== "number" || !Array.isArray(v.entries)) {
|
|
31352
|
+
return false;
|
|
31353
|
+
}
|
|
31354
|
+
for (const entry of v.entries) {
|
|
31355
|
+
if (!isHqTranscriptEntry(entry)) return false;
|
|
31356
|
+
}
|
|
31357
|
+
return true;
|
|
31358
|
+
}
|
|
31359
|
+
function isHqSessionEndedPayload(x) {
|
|
31360
|
+
if (typeof x !== "object" || x === null) return false;
|
|
31361
|
+
const v = x;
|
|
31362
|
+
return typeof v.sessionId === "string" && typeof v.endedAt === "string";
|
|
31363
|
+
}
|
|
30734
31364
|
function parseHqEventPayload(eventType, payload) {
|
|
30735
31365
|
if (!KNOWN_HQ_EVENT_PAYLOAD_TYPES.has(eventType)) {
|
|
30736
31366
|
return { ok: true, payload };
|
|
@@ -30740,6 +31370,12 @@ function parseHqEventPayload(eventType, payload) {
|
|
|
30740
31370
|
return isHqMailboxSnapshotPayload(payload) ? { ok: true, payload } : { ok: false, reason: "malformed-payload" };
|
|
30741
31371
|
case "mailbox.event":
|
|
30742
31372
|
return isHqMailboxEventPayload(payload) ? { ok: true, payload } : { ok: false, reason: "malformed-payload" };
|
|
31373
|
+
case "session.snapshot":
|
|
31374
|
+
return isHqSessionSnapshotPayload(payload) ? { ok: true, payload } : { ok: false, reason: "malformed-payload" };
|
|
31375
|
+
case "session.transcript":
|
|
31376
|
+
return isHqTranscriptAppendPayload(payload) ? { ok: true, payload } : { ok: false, reason: "malformed-payload" };
|
|
31377
|
+
case "session.ended":
|
|
31378
|
+
return isHqSessionEndedPayload(payload) ? { ok: true, payload } : { ok: false, reason: "malformed-payload" };
|
|
30743
31379
|
default: {
|
|
30744
31380
|
const _exhaustive = eventType;
|
|
30745
31381
|
return _exhaustive;
|
|
@@ -31210,6 +31846,41 @@ var HqPublisher = class {
|
|
|
31210
31846
|
...input.timestamp !== void 0 ? { timestamp: input.timestamp } : {}
|
|
31211
31847
|
});
|
|
31212
31848
|
}
|
|
31849
|
+
/** The client identity this publisher announced (clientId, kind, machineId, …). */
|
|
31850
|
+
get identity() {
|
|
31851
|
+
return this.options.client;
|
|
31852
|
+
}
|
|
31853
|
+
/** The project identity this publisher is bound to. */
|
|
31854
|
+
get project() {
|
|
31855
|
+
return this.options.project;
|
|
31856
|
+
}
|
|
31857
|
+
/** Publish a live session/terminal snapshot (state + agents). */
|
|
31858
|
+
publishSessionSnapshot(payload, opts) {
|
|
31859
|
+
return this.publishEvent({
|
|
31860
|
+
type: "session.snapshot",
|
|
31861
|
+
payload,
|
|
31862
|
+
sessionId: payload.sessionId,
|
|
31863
|
+
...opts?.timestamp !== void 0 ? { timestamp: opts.timestamp } : {}
|
|
31864
|
+
});
|
|
31865
|
+
}
|
|
31866
|
+
/** Publish an incremental batch of transcript turns for a session. */
|
|
31867
|
+
publishTranscriptAppend(payload, opts) {
|
|
31868
|
+
return this.publishEvent({
|
|
31869
|
+
type: "session.transcript",
|
|
31870
|
+
payload,
|
|
31871
|
+
sessionId: payload.sessionId,
|
|
31872
|
+
...opts?.timestamp !== void 0 ? { timestamp: opts.timestamp } : {}
|
|
31873
|
+
});
|
|
31874
|
+
}
|
|
31875
|
+
/** Mark a session/terminal as ended. */
|
|
31876
|
+
publishSessionEnded(payload, opts) {
|
|
31877
|
+
return this.publishEvent({
|
|
31878
|
+
type: "session.ended",
|
|
31879
|
+
payload,
|
|
31880
|
+
sessionId: payload.sessionId,
|
|
31881
|
+
...opts?.timestamp !== void 0 ? { timestamp: opts.timestamp } : {}
|
|
31882
|
+
});
|
|
31883
|
+
}
|
|
31213
31884
|
pollCommands() {
|
|
31214
31885
|
this.sendFrame({
|
|
31215
31886
|
type: "client.command_poll",
|
|
@@ -31777,30 +32448,69 @@ var GlobalMailbox = class {
|
|
|
31777
32448
|
async _readMessages() {
|
|
31778
32449
|
try {
|
|
31779
32450
|
const raw = await fsp3.readFile(this.messagePath, "utf8");
|
|
31780
|
-
|
|
31781
|
-
const messages = [];
|
|
31782
|
-
for (const line of lines) {
|
|
31783
|
-
try {
|
|
31784
|
-
const parsed = JSON.parse(line);
|
|
31785
|
-
if (!parsed["readBy"]) {
|
|
31786
|
-
const readBy = {};
|
|
31787
|
-
if (parsed["read"] && parsed["readAt"]) {
|
|
31788
|
-
readBy[parsed["to"]] = parsed["readAt"];
|
|
31789
|
-
}
|
|
31790
|
-
parsed["readBy"] = readBy;
|
|
31791
|
-
delete parsed["read"];
|
|
31792
|
-
delete parsed["readAt"];
|
|
31793
|
-
}
|
|
31794
|
-
messages.push(parsed);
|
|
31795
|
-
} catch {
|
|
31796
|
-
}
|
|
31797
|
-
}
|
|
31798
|
-
return messages;
|
|
32451
|
+
return this._parseLines(raw);
|
|
31799
32452
|
} catch (err) {
|
|
31800
32453
|
if (err.code === "ENOENT") return [];
|
|
31801
32454
|
throw err;
|
|
31802
32455
|
}
|
|
31803
32456
|
}
|
|
32457
|
+
/**
|
|
32458
|
+
* Read only newly-appended bytes from the file and append them to the
|
|
32459
|
+
* in-memory cache. This avoids re-reading and re-parsing the entire file
|
|
32460
|
+
* when another process appended messages since our last read.
|
|
32461
|
+
*
|
|
32462
|
+
* Only safe when the file grew in size (messages are append-only). When
|
|
32463
|
+
* the file was rewritten (ack/purge changed existing content), callers
|
|
32464
|
+
* must fall back to {@link _readMessages}.
|
|
32465
|
+
*
|
|
32466
|
+
* @returns The (now up-to-date) message cache.
|
|
32467
|
+
*/
|
|
32468
|
+
async _readNewMessagesOnly(fd, oldSize, newSize) {
|
|
32469
|
+
const tailLen = newSize - oldSize;
|
|
32470
|
+
const buf = Buffer.alloc(tailLen);
|
|
32471
|
+
await fd.read(buf, 0, tailLen, oldSize);
|
|
32472
|
+
const tail = buf.toString("utf8");
|
|
32473
|
+
for (const line of tail.split(LINE_SEPARATOR)) {
|
|
32474
|
+
if (!line.trim()) continue;
|
|
32475
|
+
try {
|
|
32476
|
+
const parsed = JSON.parse(line);
|
|
32477
|
+
if (!parsed["readBy"]) {
|
|
32478
|
+
const readBy = {};
|
|
32479
|
+
if (parsed["read"] && parsed["readAt"]) {
|
|
32480
|
+
readBy[parsed["to"]] = parsed["readAt"];
|
|
32481
|
+
}
|
|
32482
|
+
parsed["readBy"] = readBy;
|
|
32483
|
+
delete parsed["read"];
|
|
32484
|
+
delete parsed["readAt"];
|
|
32485
|
+
}
|
|
32486
|
+
this._messageCache.push(parsed);
|
|
32487
|
+
} catch {
|
|
32488
|
+
}
|
|
32489
|
+
}
|
|
32490
|
+
return this._messageCache;
|
|
32491
|
+
}
|
|
32492
|
+
/** Parse a JSONL string into MailboxMessage[], including migration. */
|
|
32493
|
+
_parseLines(raw) {
|
|
32494
|
+
const lines = raw.split(LINE_SEPARATOR).filter((l) => l.trim().length > 0);
|
|
32495
|
+
const messages = [];
|
|
32496
|
+
for (const line of lines) {
|
|
32497
|
+
try {
|
|
32498
|
+
const parsed = JSON.parse(line);
|
|
32499
|
+
if (!parsed["readBy"]) {
|
|
32500
|
+
const readBy = {};
|
|
32501
|
+
if (parsed["read"] && parsed["readAt"]) {
|
|
32502
|
+
readBy[parsed["to"]] = parsed["readAt"];
|
|
32503
|
+
}
|
|
32504
|
+
parsed["readBy"] = readBy;
|
|
32505
|
+
delete parsed["read"];
|
|
32506
|
+
delete parsed["readAt"];
|
|
32507
|
+
}
|
|
32508
|
+
messages.push(parsed);
|
|
32509
|
+
} catch {
|
|
32510
|
+
}
|
|
32511
|
+
}
|
|
32512
|
+
return messages;
|
|
32513
|
+
}
|
|
31804
32514
|
/**
|
|
31805
32515
|
* Read messages, then adopt the result as the in-memory cache. Use this
|
|
31806
32516
|
* from writers that just took the file lock — the read reflects the
|
|
@@ -31820,6 +32530,10 @@ var GlobalMailbox = class {
|
|
|
31820
32530
|
* stat matches the cached mtime+size we return the cached array — no
|
|
31821
32531
|
* file read and no JSON.parse — collapsing the per-iteration query
|
|
31822
32532
|
* cost on the mailbox-loop hot path.
|
|
32533
|
+
*
|
|
32534
|
+
* When the file only grew (new messages appended by another process),
|
|
32535
|
+
* we read and parse just the tail bytes instead of the entire file.
|
|
32536
|
+
* This avoids re-parsing the full 10K-message history on every check.
|
|
31823
32537
|
*/
|
|
31824
32538
|
async _readMessagesCached() {
|
|
31825
32539
|
try {
|
|
@@ -31827,6 +32541,17 @@ var GlobalMailbox = class {
|
|
|
31827
32541
|
if (this._messageCache !== null && this._messageCacheMtime === st.mtimeMs && this._messageCacheSize === st.size) {
|
|
31828
32542
|
return this._messageCache;
|
|
31829
32543
|
}
|
|
32544
|
+
if (this._messageCache !== null && this._messageCacheSize >= 0 && st.size > this._messageCacheSize) {
|
|
32545
|
+
const fd = await fsp3.open(this.messagePath, "r");
|
|
32546
|
+
try {
|
|
32547
|
+
const updated = await this._readNewMessagesOnly(fd, this._messageCacheSize, st.size);
|
|
32548
|
+
this._messageCacheMtime = st.mtimeMs;
|
|
32549
|
+
this._messageCacheSize = st.size;
|
|
32550
|
+
return updated;
|
|
32551
|
+
} finally {
|
|
32552
|
+
await fd.close();
|
|
32553
|
+
}
|
|
32554
|
+
}
|
|
31830
32555
|
const all = await this._readMessages();
|
|
31831
32556
|
this._setMessageCache(all, st.mtimeMs, st.size);
|
|
31832
32557
|
return all;
|
|
@@ -32191,7 +32916,7 @@ function resolveHqConfig(options = {}) {
|
|
|
32191
32916
|
};
|
|
32192
32917
|
}
|
|
32193
32918
|
function stableMachineId() {
|
|
32194
|
-
return createHash("sha256").update(
|
|
32919
|
+
return createHash("sha256").update(hostname()).digest("hex").slice(0, 12);
|
|
32195
32920
|
}
|
|
32196
32921
|
function deriveProjectId(projectRoot) {
|
|
32197
32922
|
return createHash("sha256").update(projectRoot).digest("hex").slice(0, 12);
|
|
@@ -32233,6 +32958,377 @@ function createHqPublisherFromEnv(options) {
|
|
|
32233
32958
|
function createGlobalMailbox(options) {
|
|
32234
32959
|
return new GlobalMailbox(options.projectDir, options.events, options.hqPublisher);
|
|
32235
32960
|
}
|
|
32961
|
+
|
|
32962
|
+
// src/hq/agent-bridge.ts
|
|
32963
|
+
function startAgentMonitorEventBridge(opts) {
|
|
32964
|
+
const { events, clientId, projectId, publish } = opts;
|
|
32965
|
+
const seq = { current: 0 };
|
|
32966
|
+
function nextSeq() {
|
|
32967
|
+
seq.current += 1;
|
|
32968
|
+
return seq.current;
|
|
32969
|
+
}
|
|
32970
|
+
function buildEnvelope(type, payload) {
|
|
32971
|
+
return createHqEventEnvelope({
|
|
32972
|
+
id: `${Date.now().toString(36)}-${nextSeq()}`,
|
|
32973
|
+
type,
|
|
32974
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32975
|
+
clientId,
|
|
32976
|
+
projectId,
|
|
32977
|
+
seq: nextSeq(),
|
|
32978
|
+
payload
|
|
32979
|
+
});
|
|
32980
|
+
}
|
|
32981
|
+
const offMessage = events.on("agent.timeline.message", (payload) => {
|
|
32982
|
+
if (!publish) return;
|
|
32983
|
+
const msgPayload = {
|
|
32984
|
+
subagentId: payload.subagentId,
|
|
32985
|
+
agentName: payload.agentName,
|
|
32986
|
+
content: payload.content,
|
|
32987
|
+
kind: payload.kind,
|
|
32988
|
+
iteration: payload.iteration,
|
|
32989
|
+
ts: payload.ts
|
|
32990
|
+
};
|
|
32991
|
+
if (payload.toolName !== void 0) msgPayload.toolName = payload.toolName;
|
|
32992
|
+
if (payload.costUsd !== void 0) msgPayload.costUsd = payload.costUsd;
|
|
32993
|
+
publish(buildEnvelope("agent.message", msgPayload));
|
|
32994
|
+
});
|
|
32995
|
+
const offStatus = events.on("agent.status_changed", (payload) => {
|
|
32996
|
+
if (!publish) return;
|
|
32997
|
+
const statusPayload = {
|
|
32998
|
+
subagentId: payload.subagentId,
|
|
32999
|
+
agentName: payload.agentName,
|
|
33000
|
+
status: payload.status,
|
|
33001
|
+
ts: payload.ts
|
|
33002
|
+
};
|
|
33003
|
+
if (payload.summary !== void 0) statusPayload.summary = payload.summary;
|
|
33004
|
+
if (payload.task !== void 0) statusPayload.task = payload.task;
|
|
33005
|
+
publish(buildEnvelope("agent.status", statusPayload));
|
|
33006
|
+
});
|
|
33007
|
+
return () => {
|
|
33008
|
+
offMessage();
|
|
33009
|
+
offStatus();
|
|
33010
|
+
};
|
|
33011
|
+
}
|
|
33012
|
+
|
|
33013
|
+
// src/hq/transcript-mapper.ts
|
|
33014
|
+
function blocksToText(content) {
|
|
33015
|
+
if (typeof content === "string") return content;
|
|
33016
|
+
if (Array.isArray(content)) {
|
|
33017
|
+
return content.filter(
|
|
33018
|
+
(b) => !!b && typeof b === "object" && b.type === "text" && typeof b.text === "string"
|
|
33019
|
+
).map((b) => b.text).join("\n");
|
|
33020
|
+
}
|
|
33021
|
+
return "";
|
|
33022
|
+
}
|
|
33023
|
+
function asString(v) {
|
|
33024
|
+
if (typeof v === "string") return v;
|
|
33025
|
+
try {
|
|
33026
|
+
return JSON.stringify(v, null, 2);
|
|
33027
|
+
} catch {
|
|
33028
|
+
return String(v);
|
|
33029
|
+
}
|
|
33030
|
+
}
|
|
33031
|
+
function argsEntry(ts, name, input, id) {
|
|
33032
|
+
return {
|
|
33033
|
+
ts,
|
|
33034
|
+
role: "tool",
|
|
33035
|
+
tool: String(name ?? "tool"),
|
|
33036
|
+
toolInput: input !== void 0 && input !== null ? asString(input) : "{}",
|
|
33037
|
+
text: "",
|
|
33038
|
+
...typeof id === "string" ? { toolUseId: id } : {}
|
|
33039
|
+
};
|
|
33040
|
+
}
|
|
33041
|
+
function mapSessionEventToEntries(ev) {
|
|
33042
|
+
const ts = typeof ev["ts"] === "string" ? ev["ts"] : "";
|
|
33043
|
+
const make = (role, text, extra) => ({
|
|
33044
|
+
ts,
|
|
33045
|
+
role,
|
|
33046
|
+
text,
|
|
33047
|
+
...extra
|
|
33048
|
+
});
|
|
33049
|
+
switch (ev["type"]) {
|
|
33050
|
+
case "user_input": {
|
|
33051
|
+
const t2 = blocksToText(ev["content"]);
|
|
33052
|
+
return t2.trim() ? [make("user", t2)] : [];
|
|
33053
|
+
}
|
|
33054
|
+
case "llm_response": {
|
|
33055
|
+
const out = [];
|
|
33056
|
+
const t2 = blocksToText(ev["content"]);
|
|
33057
|
+
if (t2.trim()) out.push(make("assistant", t2));
|
|
33058
|
+
const content = ev["content"];
|
|
33059
|
+
if (Array.isArray(content)) {
|
|
33060
|
+
for (const b of content) {
|
|
33061
|
+
if (b && typeof b === "object" && b.type === "tool_use") {
|
|
33062
|
+
const block = b;
|
|
33063
|
+
out.push(argsEntry(ts, block.name, block.input, block.id));
|
|
33064
|
+
}
|
|
33065
|
+
}
|
|
33066
|
+
}
|
|
33067
|
+
return out;
|
|
33068
|
+
}
|
|
33069
|
+
case "tool_use":
|
|
33070
|
+
return [argsEntry(ts, ev["name"], ev["input"], ev["id"])];
|
|
33071
|
+
case "tool_call_start":
|
|
33072
|
+
return [argsEntry(ts, ev["name"], ev["input"] ?? ev["args"], ev["id"])];
|
|
33073
|
+
case "tool_result": {
|
|
33074
|
+
const isError = ev["isError"] === true;
|
|
33075
|
+
const content = ev["content"] ?? ev["output"];
|
|
33076
|
+
const outStr = content !== void 0 && content !== null ? asString(content) : "";
|
|
33077
|
+
return [
|
|
33078
|
+
make(isError ? "error" : "tool", outStr, {
|
|
33079
|
+
tool: "\u21B3 result",
|
|
33080
|
+
...isError ? { isError: true } : {},
|
|
33081
|
+
...typeof ev["id"] === "string" ? { toolUseId: ev["id"] } : {}
|
|
33082
|
+
})
|
|
33083
|
+
];
|
|
33084
|
+
}
|
|
33085
|
+
case "tool_call_end": {
|
|
33086
|
+
const isError = ev["isError"] === true;
|
|
33087
|
+
const content = ev["output"] ?? ev["content"];
|
|
33088
|
+
const outStr = content !== void 0 && content !== null ? asString(content) : "";
|
|
33089
|
+
if (!outStr.trim() && !isError && typeof ev["durationMs"] !== "number") return [];
|
|
33090
|
+
return [
|
|
33091
|
+
make(isError ? "error" : "tool", outStr, {
|
|
33092
|
+
tool: typeof ev["name"] === "string" ? String(ev["name"]) : "\u21B3 result",
|
|
33093
|
+
...typeof ev["durationMs"] === "number" ? { durationMs: ev["durationMs"] } : {},
|
|
33094
|
+
...isError ? { isError: true } : {},
|
|
33095
|
+
...typeof ev["id"] === "string" ? { toolUseId: ev["id"] } : {}
|
|
33096
|
+
})
|
|
33097
|
+
];
|
|
33098
|
+
}
|
|
33099
|
+
case "error":
|
|
33100
|
+
case "provider_error":
|
|
33101
|
+
return [make("error", String(ev["message"] ?? "error"))];
|
|
33102
|
+
case "agent_spawned":
|
|
33103
|
+
return [make("system", `spawned ${String(ev["role"] ?? "agent")}`)];
|
|
33104
|
+
case "task_completed":
|
|
33105
|
+
return [make("system", `task done: ${String(ev["title"] ?? "")}`)];
|
|
33106
|
+
case "task_failed":
|
|
33107
|
+
return [make("system", `task failed: ${String(ev["title"] ?? "")}`)];
|
|
33108
|
+
default:
|
|
33109
|
+
return [];
|
|
33110
|
+
}
|
|
33111
|
+
}
|
|
33112
|
+
function isResultEntry(e) {
|
|
33113
|
+
return (e.role === "tool" || e.role === "error") && e.toolUseId !== void 0 && e.toolInput === void 0;
|
|
33114
|
+
}
|
|
33115
|
+
function mergeToolResults(flat) {
|
|
33116
|
+
const out = [];
|
|
33117
|
+
const argsById = /* @__PURE__ */ new Map();
|
|
33118
|
+
for (const src of flat) {
|
|
33119
|
+
const e = { ...src };
|
|
33120
|
+
if (isResultEntry(e) && e.toolUseId !== void 0) {
|
|
33121
|
+
const tgt = argsById.get(e.toolUseId);
|
|
33122
|
+
if (tgt) {
|
|
33123
|
+
tgt.text = e.text || "";
|
|
33124
|
+
if (e.durationMs !== void 0) tgt.durationMs = e.durationMs;
|
|
33125
|
+
if (e.isError) {
|
|
33126
|
+
tgt.role = "error";
|
|
33127
|
+
tgt.isError = true;
|
|
33128
|
+
}
|
|
33129
|
+
continue;
|
|
33130
|
+
}
|
|
33131
|
+
}
|
|
33132
|
+
out.push(e);
|
|
33133
|
+
if (e.role === "tool" && e.toolUseId !== void 0 && e.toolInput !== void 0) {
|
|
33134
|
+
argsById.set(e.toolUseId, e);
|
|
33135
|
+
}
|
|
33136
|
+
}
|
|
33137
|
+
return out;
|
|
33138
|
+
}
|
|
33139
|
+
function buildTranscriptFromEvents(events) {
|
|
33140
|
+
const flat = [];
|
|
33141
|
+
for (const ev of events) {
|
|
33142
|
+
for (const e of mapSessionEventToEntries(ev)) flat.push(e);
|
|
33143
|
+
}
|
|
33144
|
+
return mergeToolResults(flat);
|
|
33145
|
+
}
|
|
33146
|
+
|
|
33147
|
+
// src/hq/session-bridge.ts
|
|
33148
|
+
var VALID_AGENT_STATUS = /* @__PURE__ */ new Set([
|
|
33149
|
+
"idle",
|
|
33150
|
+
"running",
|
|
33151
|
+
"streaming",
|
|
33152
|
+
"waiting_user",
|
|
33153
|
+
"error"
|
|
33154
|
+
]);
|
|
33155
|
+
function toAgentSummary(a) {
|
|
33156
|
+
const status = VALID_AGENT_STATUS.has(a.status) ? a.status : "idle";
|
|
33157
|
+
return {
|
|
33158
|
+
id: a.id,
|
|
33159
|
+
name: a.name,
|
|
33160
|
+
status,
|
|
33161
|
+
iterations: a.iterations,
|
|
33162
|
+
toolCalls: a.toolCalls,
|
|
33163
|
+
lastActivityAt: a.lastActivityAt,
|
|
33164
|
+
...a.currentTool !== void 0 ? { currentTool: a.currentTool } : {},
|
|
33165
|
+
...a.costUsd !== void 0 ? { costUsd: a.costUsd } : {},
|
|
33166
|
+
...a.tokensIn !== void 0 ? { tokensIn: a.tokensIn } : {},
|
|
33167
|
+
...a.tokensOut !== void 0 ? { tokensOut: a.tokensOut } : {},
|
|
33168
|
+
...a.ctxPct !== void 0 ? { ctxPct: a.ctxPct } : {},
|
|
33169
|
+
...a.model !== void 0 ? { model: a.model } : {},
|
|
33170
|
+
...a.partialText !== void 0 ? { partialText: a.partialText } : {}
|
|
33171
|
+
};
|
|
33172
|
+
}
|
|
33173
|
+
function deriveSessionStatus(agents) {
|
|
33174
|
+
return agents.some(
|
|
33175
|
+
(a) => a.status === "running" || a.status === "streaming" || a.status === "waiting_user"
|
|
33176
|
+
) ? "active" : "idle";
|
|
33177
|
+
}
|
|
33178
|
+
function startSessionTelemetryBridge(opts) {
|
|
33179
|
+
const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
33180
|
+
const publisher = opts.publisher;
|
|
33181
|
+
const identity = publisher.identity;
|
|
33182
|
+
const project = publisher.project;
|
|
33183
|
+
const startedAt = opts.startedAt ?? now();
|
|
33184
|
+
const wpaths = resolveWstackPaths({
|
|
33185
|
+
projectRoot: opts.projectRoot,
|
|
33186
|
+
...opts.globalRoot !== void 0 ? { globalRoot: opts.globalRoot } : {}
|
|
33187
|
+
});
|
|
33188
|
+
const sessionFile = path3.join(wpaths.projectSessions, `${opts.sessionId}.jsonl`);
|
|
33189
|
+
let agents = [];
|
|
33190
|
+
let lastActivityAt = startedAt;
|
|
33191
|
+
let lastSnapshotHash = "";
|
|
33192
|
+
let disposed = false;
|
|
33193
|
+
function buildSnapshot() {
|
|
33194
|
+
return {
|
|
33195
|
+
sessionId: opts.sessionId,
|
|
33196
|
+
clientKind: identity.kind,
|
|
33197
|
+
machineId: identity.machineId,
|
|
33198
|
+
projectId: project.projectId,
|
|
33199
|
+
projectName: opts.projectName ?? project.projectName,
|
|
33200
|
+
projectRoot: opts.projectRoot,
|
|
33201
|
+
status: deriveSessionStatus(agents),
|
|
33202
|
+
startedAt,
|
|
33203
|
+
lastActivityAt,
|
|
33204
|
+
agentCount: agents.length,
|
|
33205
|
+
agents,
|
|
33206
|
+
...identity.hostname !== void 0 ? { hostname: identity.hostname } : {},
|
|
33207
|
+
...identity.pid !== void 0 ? { pid: identity.pid } : {},
|
|
33208
|
+
...opts.gitBranch !== void 0 ? { gitBranch: opts.gitBranch } : {}
|
|
33209
|
+
};
|
|
33210
|
+
}
|
|
33211
|
+
function publishSnapshot(force = false) {
|
|
33212
|
+
if (disposed) return;
|
|
33213
|
+
const snap = buildSnapshot();
|
|
33214
|
+
const hash = JSON.stringify({ ...snap, lastActivityAt: "" });
|
|
33215
|
+
if (!force && hash === lastSnapshotHash) return;
|
|
33216
|
+
lastSnapshotHash = hash;
|
|
33217
|
+
try {
|
|
33218
|
+
publisher.publishSessionSnapshot(snap);
|
|
33219
|
+
} catch {
|
|
33220
|
+
}
|
|
33221
|
+
}
|
|
33222
|
+
const offAgents = opts.events?.on("session.agents_updated", (payload) => {
|
|
33223
|
+
agents = payload.agents.map(toAgentSummary);
|
|
33224
|
+
lastActivityAt = now();
|
|
33225
|
+
publishSnapshot();
|
|
33226
|
+
});
|
|
33227
|
+
publishSnapshot(true);
|
|
33228
|
+
let offset = 0;
|
|
33229
|
+
let partial = "";
|
|
33230
|
+
let seqEmitted = 0;
|
|
33231
|
+
let tailing = false;
|
|
33232
|
+
let watcher = null;
|
|
33233
|
+
let watchPending = false;
|
|
33234
|
+
function setupWatcher() {
|
|
33235
|
+
if (disposed || watcher) return;
|
|
33236
|
+
try {
|
|
33237
|
+
const nextWatcher = fs3.watch(sessionFile, () => {
|
|
33238
|
+
if (watchPending || disposed) return;
|
|
33239
|
+
watchPending = true;
|
|
33240
|
+
setTimeout(() => {
|
|
33241
|
+
watchPending = false;
|
|
33242
|
+
void tail();
|
|
33243
|
+
}, 25);
|
|
33244
|
+
});
|
|
33245
|
+
nextWatcher.on("error", () => {
|
|
33246
|
+
try {
|
|
33247
|
+
nextWatcher.close();
|
|
33248
|
+
} catch {
|
|
33249
|
+
}
|
|
33250
|
+
if (watcher === nextWatcher) watcher = null;
|
|
33251
|
+
});
|
|
33252
|
+
watcher = nextWatcher;
|
|
33253
|
+
} catch {
|
|
33254
|
+
watcher = null;
|
|
33255
|
+
}
|
|
33256
|
+
}
|
|
33257
|
+
async function tail() {
|
|
33258
|
+
if (disposed || tailing) return;
|
|
33259
|
+
tailing = true;
|
|
33260
|
+
try {
|
|
33261
|
+
const stat16 = await fsp3.stat(sessionFile).catch(() => null);
|
|
33262
|
+
if (disposed) return;
|
|
33263
|
+
if (!stat16) return;
|
|
33264
|
+
setupWatcher();
|
|
33265
|
+
if (stat16.size <= offset) return;
|
|
33266
|
+
const fd = await fsp3.open(sessionFile, "r");
|
|
33267
|
+
try {
|
|
33268
|
+
if (disposed) return;
|
|
33269
|
+
const len = stat16.size - offset;
|
|
33270
|
+
const buf = Buffer.allocUnsafe(len);
|
|
33271
|
+
await fd.read(buf, 0, len, offset);
|
|
33272
|
+
offset = stat16.size;
|
|
33273
|
+
partial += buf.toString("utf8");
|
|
33274
|
+
const lines = partial.split("\n");
|
|
33275
|
+
partial = lines.pop() ?? "";
|
|
33276
|
+
const entries = [];
|
|
33277
|
+
for (const line of lines) {
|
|
33278
|
+
const trimmed = line.trim();
|
|
33279
|
+
if (!trimmed) continue;
|
|
33280
|
+
let obj;
|
|
33281
|
+
try {
|
|
33282
|
+
obj = JSON.parse(trimmed);
|
|
33283
|
+
} catch {
|
|
33284
|
+
continue;
|
|
33285
|
+
}
|
|
33286
|
+
for (const entry of mapSessionEventToEntries(obj)) entries.push(entry);
|
|
33287
|
+
}
|
|
33288
|
+
if (entries.length > 0) {
|
|
33289
|
+
try {
|
|
33290
|
+
publisher.publishTranscriptAppend({
|
|
33291
|
+
sessionId: opts.sessionId,
|
|
33292
|
+
fromSeq: seqEmitted,
|
|
33293
|
+
entries
|
|
33294
|
+
});
|
|
33295
|
+
} catch {
|
|
33296
|
+
}
|
|
33297
|
+
seqEmitted += entries.length;
|
|
33298
|
+
lastActivityAt = now();
|
|
33299
|
+
}
|
|
33300
|
+
} finally {
|
|
33301
|
+
await fd.close();
|
|
33302
|
+
}
|
|
33303
|
+
} catch {
|
|
33304
|
+
} finally {
|
|
33305
|
+
tailing = false;
|
|
33306
|
+
}
|
|
33307
|
+
}
|
|
33308
|
+
const snapshotTimer = setInterval(() => publishSnapshot(true), opts.snapshotIntervalMs ?? 2500);
|
|
33309
|
+
const tailTimer = setInterval(() => void tail(), opts.transcriptIntervalMs ?? 500);
|
|
33310
|
+
snapshotTimer.unref?.();
|
|
33311
|
+
tailTimer.unref?.();
|
|
33312
|
+
void tail();
|
|
33313
|
+
return () => {
|
|
33314
|
+
if (disposed) return;
|
|
33315
|
+
disposed = true;
|
|
33316
|
+
offAgents?.();
|
|
33317
|
+
if (watcher) {
|
|
33318
|
+
try {
|
|
33319
|
+
watcher.close();
|
|
33320
|
+
} catch {
|
|
33321
|
+
}
|
|
33322
|
+
watcher = null;
|
|
33323
|
+
}
|
|
33324
|
+
clearInterval(snapshotTimer);
|
|
33325
|
+
clearInterval(tailTimer);
|
|
33326
|
+
try {
|
|
33327
|
+
publisher.publishSessionEnded({ sessionId: opts.sessionId, endedAt: now() });
|
|
33328
|
+
} catch {
|
|
33329
|
+
}
|
|
33330
|
+
};
|
|
33331
|
+
}
|
|
32236
33332
|
var MATCHERS = {
|
|
32237
33333
|
pnpmWorkspace: (files) => files.includes("pnpm-workspace.yaml"),
|
|
32238
33334
|
gradlew: (_files, dirs) => dirs.includes("gradlew"),
|
|
@@ -33110,8 +34206,8 @@ var ReportGenerator = class {
|
|
|
33110
34206
|
try {
|
|
33111
34207
|
await stat(this.options.outputDir);
|
|
33112
34208
|
} catch {
|
|
33113
|
-
const { mkdir:
|
|
33114
|
-
await
|
|
34209
|
+
const { mkdir: mkdir24 } = await import('fs/promises');
|
|
34210
|
+
await mkdir24(this.options.outputDir, { recursive: true });
|
|
33115
34211
|
}
|
|
33116
34212
|
}
|
|
33117
34213
|
generateMarkdown(result) {
|
|
@@ -34639,6 +35735,10 @@ var DefaultMailbox = class {
|
|
|
34639
35735
|
_messageCache = null;
|
|
34640
35736
|
_messageCacheMtime = -1;
|
|
34641
35737
|
_messageCacheSize = -1;
|
|
35738
|
+
/** Primary index: recipient → Set of messages (points into _messageCache). */
|
|
35739
|
+
_byTo = /* @__PURE__ */ new Map();
|
|
35740
|
+
/** Secondary index: sender → Set of messages (points into _messageCache). */
|
|
35741
|
+
_byFrom = /* @__PURE__ */ new Map();
|
|
34642
35742
|
constructor(sessionDir) {
|
|
34643
35743
|
this.filePath = path3.join(sessionDir, MAILBOX_FILE2);
|
|
34644
35744
|
}
|
|
@@ -34674,12 +35774,30 @@ var DefaultMailbox = class {
|
|
|
34674
35774
|
}
|
|
34675
35775
|
// ── Query ─────────────────────────────────────────────────────────────
|
|
34676
35776
|
async query(q) {
|
|
34677
|
-
const
|
|
35777
|
+
const needFullScan = q.unreadBy !== void 0 || q.since !== void 0;
|
|
35778
|
+
let candidates;
|
|
35779
|
+
if (needFullScan) {
|
|
35780
|
+
candidates = await this._readAllCached();
|
|
35781
|
+
} else {
|
|
35782
|
+
await this._readAllCached();
|
|
35783
|
+
if (q.to !== void 0) {
|
|
35784
|
+
const direct = this._byTo.get(q.to);
|
|
35785
|
+
const broadcast = this._byTo.get("*");
|
|
35786
|
+
const combined = /* @__PURE__ */ new Map();
|
|
35787
|
+
if (direct) for (const m of direct) combined.set(m.id, m);
|
|
35788
|
+
if (broadcast) for (const m of broadcast) combined.set(m.id, m);
|
|
35789
|
+
candidates = Array.from(combined.values());
|
|
35790
|
+
} else if (q.from !== void 0) {
|
|
35791
|
+
candidates = Array.from(this._byFrom.get(q.from) ?? []);
|
|
35792
|
+
} else {
|
|
35793
|
+
candidates = await this._readAllCached();
|
|
35794
|
+
}
|
|
35795
|
+
}
|
|
34678
35796
|
const limit = q.limit ?? 50;
|
|
34679
35797
|
const order = q.minPriority !== void 0 ? { low: 0, normal: 1, high: 2 } : null;
|
|
34680
35798
|
const minPriorityRank = order && q.minPriority !== void 0 ? order[q.minPriority] : 0;
|
|
34681
35799
|
const filtered = [];
|
|
34682
|
-
for (const msg of
|
|
35800
|
+
for (const msg of candidates) {
|
|
34683
35801
|
if (q.to !== void 0 && msg.to !== q.to && msg.to !== "*") continue;
|
|
34684
35802
|
if (q.from !== void 0 && msg.from !== q.from) continue;
|
|
34685
35803
|
if (q.unreadBy !== void 0 && q.unreadBy in msg.readBy) continue;
|
|
@@ -34780,6 +35898,8 @@ var DefaultMailbox = class {
|
|
|
34780
35898
|
this._messageCache = null;
|
|
34781
35899
|
this._messageCacheMtime = -1;
|
|
34782
35900
|
this._messageCacheSize = -1;
|
|
35901
|
+
this._byTo.clear();
|
|
35902
|
+
this._byFrom.clear();
|
|
34783
35903
|
}
|
|
34784
35904
|
async clearAll() {
|
|
34785
35905
|
await withFileLock(this.filePath, async () => {
|
|
@@ -34838,36 +35958,81 @@ var DefaultMailbox = class {
|
|
|
34838
35958
|
async _readAll() {
|
|
34839
35959
|
try {
|
|
34840
35960
|
const raw = await fsp3.readFile(this.filePath, "utf8");
|
|
34841
|
-
|
|
34842
|
-
const messages = [];
|
|
34843
|
-
for (const line of lines) {
|
|
34844
|
-
try {
|
|
34845
|
-
const parsed = JSON.parse(line);
|
|
34846
|
-
if (!parsed["readBy"]) {
|
|
34847
|
-
const readBy = {};
|
|
34848
|
-
if (parsed["read"] && parsed["readAt"]) {
|
|
34849
|
-
readBy[parsed["to"] ?? "unknown"] = parsed["readAt"];
|
|
34850
|
-
}
|
|
34851
|
-
parsed["readBy"] = readBy;
|
|
34852
|
-
delete parsed["read"];
|
|
34853
|
-
delete parsed["readAt"];
|
|
34854
|
-
}
|
|
34855
|
-
messages.push(parsed);
|
|
34856
|
-
} catch {
|
|
34857
|
-
}
|
|
34858
|
-
}
|
|
34859
|
-
return messages;
|
|
35961
|
+
return this._parseLines(raw);
|
|
34860
35962
|
} catch (err) {
|
|
34861
35963
|
if (err.code === "ENOENT") return [];
|
|
34862
35964
|
throw err;
|
|
34863
35965
|
}
|
|
34864
35966
|
}
|
|
35967
|
+
/**
|
|
35968
|
+
* Read only newly-appended bytes from the file and append them to the
|
|
35969
|
+
* in-memory cache, avoiding a full re-read when the file only grew.
|
|
35970
|
+
*/
|
|
35971
|
+
async _readNewMessagesOnly(fd, oldSize, newSize) {
|
|
35972
|
+
const tailLen = newSize - oldSize;
|
|
35973
|
+
const buf = Buffer.alloc(tailLen);
|
|
35974
|
+
await fd.read(buf, 0, tailLen, oldSize);
|
|
35975
|
+
const tail = buf.toString("utf8");
|
|
35976
|
+
for (const line of tail.split(LINE_SEPARATOR2)) {
|
|
35977
|
+
if (!line.trim()) continue;
|
|
35978
|
+
try {
|
|
35979
|
+
const parsed = JSON.parse(line);
|
|
35980
|
+
if (!parsed["readBy"]) {
|
|
35981
|
+
const readBy = {};
|
|
35982
|
+
if (parsed["read"] && parsed["readAt"]) {
|
|
35983
|
+
readBy[parsed["to"] ?? "unknown"] = parsed["readAt"];
|
|
35984
|
+
}
|
|
35985
|
+
parsed["readBy"] = readBy;
|
|
35986
|
+
delete parsed["read"];
|
|
35987
|
+
delete parsed["readAt"];
|
|
35988
|
+
}
|
|
35989
|
+
const msg = parsed;
|
|
35990
|
+
this._messageCache.push(msg);
|
|
35991
|
+
this._indexMsg(msg);
|
|
35992
|
+
} catch {
|
|
35993
|
+
}
|
|
35994
|
+
}
|
|
35995
|
+
return this._messageCache;
|
|
35996
|
+
}
|
|
35997
|
+
/** Parse a JSONL string into MailboxMessage[], including migration. */
|
|
35998
|
+
_parseLines(raw) {
|
|
35999
|
+
const lines = raw.split(LINE_SEPARATOR2).filter((l) => l.trim().length > 0);
|
|
36000
|
+
const messages = [];
|
|
36001
|
+
for (const line of lines) {
|
|
36002
|
+
try {
|
|
36003
|
+
const parsed = JSON.parse(line);
|
|
36004
|
+
if (!parsed["readBy"]) {
|
|
36005
|
+
const readBy = {};
|
|
36006
|
+
if (parsed["read"] && parsed["readAt"]) {
|
|
36007
|
+
readBy[parsed["to"] ?? "unknown"] = parsed["readAt"];
|
|
36008
|
+
}
|
|
36009
|
+
parsed["readBy"] = readBy;
|
|
36010
|
+
delete parsed["read"];
|
|
36011
|
+
delete parsed["readAt"];
|
|
36012
|
+
}
|
|
36013
|
+
messages.push(parsed);
|
|
36014
|
+
} catch {
|
|
36015
|
+
}
|
|
36016
|
+
}
|
|
36017
|
+
return messages;
|
|
36018
|
+
}
|
|
34865
36019
|
async _readAllCached() {
|
|
34866
36020
|
try {
|
|
34867
36021
|
const st = await fsp3.stat(this.filePath);
|
|
34868
36022
|
if (this._messageCache !== null && this._messageCacheMtime === st.mtimeMs && this._messageCacheSize === st.size) {
|
|
34869
36023
|
return this._messageCache;
|
|
34870
36024
|
}
|
|
36025
|
+
if (this._messageCache !== null && this._messageCacheSize >= 0 && st.size > this._messageCacheSize) {
|
|
36026
|
+
const fd = await fsp3.open(this.filePath, "r");
|
|
36027
|
+
try {
|
|
36028
|
+
const updated = await this._readNewMessagesOnly(fd, this._messageCacheSize, st.size);
|
|
36029
|
+
this._messageCacheMtime = st.mtimeMs;
|
|
36030
|
+
this._messageCacheSize = st.size;
|
|
36031
|
+
return updated;
|
|
36032
|
+
} finally {
|
|
36033
|
+
await fd.close();
|
|
36034
|
+
}
|
|
36035
|
+
}
|
|
34871
36036
|
const all = await this._readAll();
|
|
34872
36037
|
this._setMessageCache(all, st.mtimeMs, st.size);
|
|
34873
36038
|
return all;
|
|
@@ -34884,9 +36049,12 @@ var DefaultMailbox = class {
|
|
|
34884
36049
|
this._messageCache = null;
|
|
34885
36050
|
this._messageCacheMtime = -1;
|
|
34886
36051
|
this._messageCacheSize = -1;
|
|
36052
|
+
this._byTo.clear();
|
|
36053
|
+
this._byFrom.clear();
|
|
34887
36054
|
return;
|
|
34888
36055
|
}
|
|
34889
36056
|
this._messageCache = messages;
|
|
36057
|
+
this._buildIndexes(messages);
|
|
34890
36058
|
if (mtime !== void 0 && size !== void 0) {
|
|
34891
36059
|
this._messageCacheMtime = mtime;
|
|
34892
36060
|
this._messageCacheSize = size;
|
|
@@ -34904,9 +36072,35 @@ var DefaultMailbox = class {
|
|
|
34904
36072
|
this._messageCache = null;
|
|
34905
36073
|
this._messageCacheMtime = -1;
|
|
34906
36074
|
this._messageCacheSize = -1;
|
|
36075
|
+
this._byTo.clear();
|
|
36076
|
+
this._byFrom.clear();
|
|
34907
36077
|
return;
|
|
34908
36078
|
}
|
|
34909
36079
|
this._messageCache.push(msg);
|
|
36080
|
+
this._indexMsg(msg);
|
|
36081
|
+
}
|
|
36082
|
+
/** Rebuild both indexes from a full message list. */
|
|
36083
|
+
_buildIndexes(messages) {
|
|
36084
|
+
this._byTo.clear();
|
|
36085
|
+
this._byFrom.clear();
|
|
36086
|
+
for (const msg of messages) {
|
|
36087
|
+
this._indexMsg(msg);
|
|
36088
|
+
}
|
|
36089
|
+
}
|
|
36090
|
+
/** Add a single message to both indexes. */
|
|
36091
|
+
_indexMsg(msg) {
|
|
36092
|
+
const toSet = this._byTo.get(msg.to);
|
|
36093
|
+
if (toSet) {
|
|
36094
|
+
toSet.add(msg);
|
|
36095
|
+
} else {
|
|
36096
|
+
this._byTo.set(msg.to, /* @__PURE__ */ new Set([msg]));
|
|
36097
|
+
}
|
|
36098
|
+
const fromSet = this._byFrom.get(msg.from);
|
|
36099
|
+
if (fromSet) {
|
|
36100
|
+
fromSet.add(msg);
|
|
36101
|
+
} else {
|
|
36102
|
+
this._byFrom.set(msg.from, /* @__PURE__ */ new Set([msg]));
|
|
36103
|
+
}
|
|
34910
36104
|
}
|
|
34911
36105
|
};
|
|
34912
36106
|
var BrainMonitor = class {
|
|
@@ -38337,6 +39531,262 @@ ${input.detail}`
|
|
|
38337
39531
|
this.onCoordinatorEvent?.(event);
|
|
38338
39532
|
}
|
|
38339
39533
|
};
|
|
39534
|
+
var AgentMonitorService = class {
|
|
39535
|
+
_fleetBus;
|
|
39536
|
+
_events;
|
|
39537
|
+
_transcriptsDir;
|
|
39538
|
+
_maxEntries;
|
|
39539
|
+
_streamEnabled;
|
|
39540
|
+
_onEntry;
|
|
39541
|
+
/** Per-subagent virtual sessions. */
|
|
39542
|
+
_sessions = /* @__PURE__ */ new Map();
|
|
39543
|
+
/** Disposers for FleetBus subscriptions, keyed by subagentId. */
|
|
39544
|
+
_subscriptions = /* @__PURE__ */ new Map();
|
|
39545
|
+
/** Generic fleet-wide subscription disposer. */
|
|
39546
|
+
_fleetDisposer;
|
|
39547
|
+
/** Track whether service is running. */
|
|
39548
|
+
_started = false;
|
|
39549
|
+
constructor(opts) {
|
|
39550
|
+
this._fleetBus = opts.fleetBus;
|
|
39551
|
+
this._events = opts.events;
|
|
39552
|
+
this._transcriptsDir = opts.transcriptsDir;
|
|
39553
|
+
this._maxEntries = opts.maxEntriesPerAgent ?? 500;
|
|
39554
|
+
this._streamEnabled = opts.streamEnabled ?? false;
|
|
39555
|
+
this._onEntry = opts.onEntry;
|
|
39556
|
+
}
|
|
39557
|
+
// ── Public API ────────────────────────────────────────────────────
|
|
39558
|
+
/** Set the FleetBus to listen on. Must be called before `start()`. */
|
|
39559
|
+
setFleetBus(bus) {
|
|
39560
|
+
this._fleetBus = bus;
|
|
39561
|
+
}
|
|
39562
|
+
get streamEnabled() {
|
|
39563
|
+
return this._streamEnabled;
|
|
39564
|
+
}
|
|
39565
|
+
/** Enable/disable streaming agent conversations to the main chat timeline. */
|
|
39566
|
+
setStreamEnabled(enabled) {
|
|
39567
|
+
this._streamEnabled = enabled;
|
|
39568
|
+
}
|
|
39569
|
+
/** Get a snapshot of all known agent sessions. */
|
|
39570
|
+
getAllSessions() {
|
|
39571
|
+
return Array.from(this._sessions.values());
|
|
39572
|
+
}
|
|
39573
|
+
/** Get a specific agent's virtual session, or undefined. */
|
|
39574
|
+
getSession(subagentId) {
|
|
39575
|
+
return this._sessions.get(subagentId);
|
|
39576
|
+
}
|
|
39577
|
+
/** Get transcript entries for a specific agent, newest first. */
|
|
39578
|
+
getTranscript(subagentId, limit = 50) {
|
|
39579
|
+
const session = this._sessions.get(subagentId);
|
|
39580
|
+
if (!session) return [];
|
|
39581
|
+
return session.transcript.slice(-limit).reverse();
|
|
39582
|
+
}
|
|
39583
|
+
/** Set a callback for each new timeline entry (HQ bridge). */
|
|
39584
|
+
setOnEntry(handler) {
|
|
39585
|
+
this._onEntry = handler;
|
|
39586
|
+
}
|
|
39587
|
+
// ── Lifecycle ──────────────────────────────────────────────────────
|
|
39588
|
+
/** Start listening to FleetBus events. */
|
|
39589
|
+
start() {
|
|
39590
|
+
if (this._started) return;
|
|
39591
|
+
if (!this._fleetBus) {
|
|
39592
|
+
this._started = true;
|
|
39593
|
+
return;
|
|
39594
|
+
}
|
|
39595
|
+
this._started = true;
|
|
39596
|
+
this._fleetDisposer = this._fleetBus.onAny((event) => {
|
|
39597
|
+
this._routeEvent(event.subagentId, event.type, event.payload);
|
|
39598
|
+
});
|
|
39599
|
+
}
|
|
39600
|
+
/** Stop listening and clean up all subscriptions. */
|
|
39601
|
+
stop() {
|
|
39602
|
+
if (!this._started) return;
|
|
39603
|
+
this._started = false;
|
|
39604
|
+
if (this._fleetDisposer) {
|
|
39605
|
+
this._fleetDisposer();
|
|
39606
|
+
this._fleetDisposer = void 0;
|
|
39607
|
+
}
|
|
39608
|
+
for (const disposer of this._subscriptions.values()) {
|
|
39609
|
+
disposer();
|
|
39610
|
+
}
|
|
39611
|
+
this._subscriptions.clear();
|
|
39612
|
+
}
|
|
39613
|
+
/** Ensure a subagent is being tracked. Called when a subagent spawns. */
|
|
39614
|
+
trackSubagent(subagentId, agentName, task) {
|
|
39615
|
+
if (this._sessions.has(subagentId)) return;
|
|
39616
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
39617
|
+
const session = {
|
|
39618
|
+
subagentId,
|
|
39619
|
+
agentName,
|
|
39620
|
+
createdAt: now,
|
|
39621
|
+
status: "spawned",
|
|
39622
|
+
task,
|
|
39623
|
+
transcript: []
|
|
39624
|
+
};
|
|
39625
|
+
this._sessions.set(subagentId, session);
|
|
39626
|
+
this._addEntry(subagentId, {
|
|
39627
|
+
id: this._uid(),
|
|
39628
|
+
subagentId,
|
|
39629
|
+
agentName,
|
|
39630
|
+
ts: now,
|
|
39631
|
+
kind: "system",
|
|
39632
|
+
content: task ? `\u{1F3AF} Spawned: ${task}` : "\u{1F916} Agent spawned",
|
|
39633
|
+
iteration: 0
|
|
39634
|
+
});
|
|
39635
|
+
this._events.emit("agent.status_changed", {
|
|
39636
|
+
subagentId,
|
|
39637
|
+
agentName,
|
|
39638
|
+
status: "spawned",
|
|
39639
|
+
ts: now,
|
|
39640
|
+
summary: task,
|
|
39641
|
+
task
|
|
39642
|
+
});
|
|
39643
|
+
}
|
|
39644
|
+
/** Mark a subagent as completed/failed/etc. Called on subagent finish. */
|
|
39645
|
+
completeSubagent(subagentId, status, summary) {
|
|
39646
|
+
const session = this._sessions.get(subagentId);
|
|
39647
|
+
if (!session) return;
|
|
39648
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
39649
|
+
session.status = status;
|
|
39650
|
+
this._addEntry(subagentId, {
|
|
39651
|
+
id: this._uid(),
|
|
39652
|
+
subagentId,
|
|
39653
|
+
agentName: session.agentName,
|
|
39654
|
+
ts: now,
|
|
39655
|
+
kind: "status",
|
|
39656
|
+
content: summary ?? `Agent ${status}`,
|
|
39657
|
+
iteration: 999
|
|
39658
|
+
});
|
|
39659
|
+
this._events.emit("agent.status_changed", {
|
|
39660
|
+
subagentId,
|
|
39661
|
+
agentName: session.agentName,
|
|
39662
|
+
status,
|
|
39663
|
+
ts: now,
|
|
39664
|
+
summary,
|
|
39665
|
+
task: session.task
|
|
39666
|
+
});
|
|
39667
|
+
}
|
|
39668
|
+
// ── Internal ───────────────────────────────────────────────────────
|
|
39669
|
+
_routeEvent(subagentId, type, payload) {
|
|
39670
|
+
const session = this._sessions.get(subagentId);
|
|
39671
|
+
if (!session) return;
|
|
39672
|
+
switch (type) {
|
|
39673
|
+
case "provider.text_delta": {
|
|
39674
|
+
const text = payload.text;
|
|
39675
|
+
if (!text || text.length === 0) return;
|
|
39676
|
+
const iteration = payload.iteration ?? 0;
|
|
39677
|
+
this._addEntry(subagentId, {
|
|
39678
|
+
id: this._uid(),
|
|
39679
|
+
subagentId,
|
|
39680
|
+
agentName: session.agentName,
|
|
39681
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39682
|
+
kind: "text",
|
|
39683
|
+
content: text,
|
|
39684
|
+
iteration
|
|
39685
|
+
});
|
|
39686
|
+
break;
|
|
39687
|
+
}
|
|
39688
|
+
case "provider.thinking_delta": {
|
|
39689
|
+
const text = payload.text;
|
|
39690
|
+
if (!text || text.length === 0) return;
|
|
39691
|
+
const iteration = payload.iteration ?? 0;
|
|
39692
|
+
this._addEntry(subagentId, {
|
|
39693
|
+
id: this._uid(),
|
|
39694
|
+
subagentId,
|
|
39695
|
+
agentName: session.agentName,
|
|
39696
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39697
|
+
kind: "text",
|
|
39698
|
+
content: `\u{1F9E0} ${text}`,
|
|
39699
|
+
iteration
|
|
39700
|
+
});
|
|
39701
|
+
break;
|
|
39702
|
+
}
|
|
39703
|
+
case "tool.started": {
|
|
39704
|
+
const name = payload.name;
|
|
39705
|
+
if (!name) return;
|
|
39706
|
+
this._addEntry(subagentId, {
|
|
39707
|
+
id: this._uid(),
|
|
39708
|
+
subagentId,
|
|
39709
|
+
agentName: session.agentName,
|
|
39710
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39711
|
+
kind: "tool_use",
|
|
39712
|
+
content: `\u{1F527} ${name}()`,
|
|
39713
|
+
iteration: payload.iteration ?? 0,
|
|
39714
|
+
toolName: name
|
|
39715
|
+
});
|
|
39716
|
+
break;
|
|
39717
|
+
}
|
|
39718
|
+
case "tool.executed": {
|
|
39719
|
+
const name = payload.name;
|
|
39720
|
+
const ok = payload.ok;
|
|
39721
|
+
const durationMs = payload.durationMs;
|
|
39722
|
+
if (!name) return;
|
|
39723
|
+
const statusIcon2 = ok ? "\u2705" : "\u274C";
|
|
39724
|
+
const duration = durationMs !== void 0 ? ` (${durationMs}ms)` : "";
|
|
39725
|
+
this._addEntry(subagentId, {
|
|
39726
|
+
id: this._uid(),
|
|
39727
|
+
subagentId,
|
|
39728
|
+
agentName: session.agentName,
|
|
39729
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39730
|
+
kind: "tool_result",
|
|
39731
|
+
content: `${statusIcon2} ${name}${duration}`,
|
|
39732
|
+
iteration: payload.iteration ?? 0,
|
|
39733
|
+
toolName: name,
|
|
39734
|
+
toolOk: ok
|
|
39735
|
+
});
|
|
39736
|
+
break;
|
|
39737
|
+
}
|
|
39738
|
+
case "iteration.completed": {
|
|
39739
|
+
const index = payload.index ?? 0;
|
|
39740
|
+
if (index > 0 && index % 5 === 0) {
|
|
39741
|
+
this._addEntry(subagentId, {
|
|
39742
|
+
id: this._uid(),
|
|
39743
|
+
subagentId,
|
|
39744
|
+
agentName: session.agentName,
|
|
39745
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39746
|
+
kind: "status",
|
|
39747
|
+
content: `\u{1F504} Iteration ${index}`,
|
|
39748
|
+
iteration: index
|
|
39749
|
+
});
|
|
39750
|
+
}
|
|
39751
|
+
break;
|
|
39752
|
+
}
|
|
39753
|
+
}
|
|
39754
|
+
}
|
|
39755
|
+
_addEntry(subagentId, entry) {
|
|
39756
|
+
const session = this._sessions.get(subagentId);
|
|
39757
|
+
if (!session) return;
|
|
39758
|
+
session.transcript.push(entry);
|
|
39759
|
+
if (session.transcript.length > this._maxEntries) {
|
|
39760
|
+
session.transcript.splice(0, session.transcript.length - this._maxEntries);
|
|
39761
|
+
}
|
|
39762
|
+
this._appendToFile(subagentId, entry).catch(() => {
|
|
39763
|
+
});
|
|
39764
|
+
this._events.emit("agent.timeline.message", {
|
|
39765
|
+
subagentId: entry.subagentId,
|
|
39766
|
+
agentName: entry.agentName,
|
|
39767
|
+
content: entry.content,
|
|
39768
|
+
kind: entry.kind === "tool_result" ? "tool_use" : entry.kind === "system" ? "status" : entry.kind,
|
|
39769
|
+
iteration: entry.iteration,
|
|
39770
|
+
ts: entry.ts,
|
|
39771
|
+
toolName: entry.toolName,
|
|
39772
|
+
costUsd: entry.costUsd
|
|
39773
|
+
});
|
|
39774
|
+
this._onEntry?.(entry);
|
|
39775
|
+
}
|
|
39776
|
+
async _appendToFile(subagentId, entry) {
|
|
39777
|
+
const dir = path3.join(this._transcriptsDir, subagentId);
|
|
39778
|
+
await fsp3.mkdir(dir, { recursive: true });
|
|
39779
|
+
const filePath = path3.join(dir, "transcript.jsonl");
|
|
39780
|
+
const line = JSON.stringify(entry) + "\n";
|
|
39781
|
+
await fsp3.appendFile(filePath, line, { encoding: "utf8" });
|
|
39782
|
+
}
|
|
39783
|
+
_uid() {
|
|
39784
|
+
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
|
|
39785
|
+
}
|
|
39786
|
+
};
|
|
39787
|
+
function createAgentMonitorService(opts) {
|
|
39788
|
+
return new AgentMonitorService(opts);
|
|
39789
|
+
}
|
|
38340
39790
|
|
|
38341
39791
|
// src/tools/mcp-control.ts
|
|
38342
39792
|
function createMcpControlTool(opts) {
|
|
@@ -38364,11 +39814,18 @@ function createMcpControlTool(opts) {
|
|
|
38364
39814
|
};
|
|
38365
39815
|
return {
|
|
38366
39816
|
name: "mcp_control",
|
|
38367
|
-
description: "Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers. Use activate/deactivate to ephemerally toggle tool registration without disconnecting \u2014 ideal for token-saving mode where MCP tools are lazy-loaded on demand.",
|
|
39817
|
+
description: "Manage MCP server lifecycle: list available servers, search by name or capability, enable or disable servers at runtime, restart running servers. Use activate/deactivate to ephemerally toggle tool registration without disconnecting \u2014 ideal for token-saving mode where MCP tools are lazy-loaded on demand. NOTE: `enable`/`restart` start a server process, which for the built-in stdio presets runs `npx -y <package>` \u2014 i.e. it fetches and executes an npm package from the network. Treat it as code execution.",
|
|
38368
39818
|
category: "mcp",
|
|
38369
39819
|
permission: "auto",
|
|
38370
39820
|
mutating: true,
|
|
38371
|
-
|
|
39821
|
+
// `enable`/`restart` spawn a server process that, for the stdio presets,
|
|
39822
|
+
// fetches and runs an npm package (`npx -y <pkg>`) — effectively remote
|
|
39823
|
+
// code execution. Marking the tool destructive means the YOLO
|
|
39824
|
+
// `confirmDestructive` safety net still prompts before it runs (plain
|
|
39825
|
+
// non-YOLO already confirms via the CONFIG_MUTATE dangerous-capability
|
|
39826
|
+
// net in the executor). Read-only actions (list/search) ride the same
|
|
39827
|
+
// tool but are cheap to confirm/trust once.
|
|
39828
|
+
riskTier: "destructive",
|
|
38372
39829
|
capabilities: [ToolCapabilities.CONFIG_MUTATE],
|
|
38373
39830
|
inputSchema,
|
|
38374
39831
|
async execute(raw) {
|
|
@@ -39489,25 +40946,29 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
39489
40946
|
const checkMailbox = attachMailboxChecker(a);
|
|
39490
40947
|
async function compactContextIfNeeded() {
|
|
39491
40948
|
const msgCount = a.ctx.messages.length;
|
|
39492
|
-
|
|
40949
|
+
const maxContext = currentMaxContext();
|
|
40950
|
+
if (_lastCompactionMsgCount === msgCount && _lastCompactionWasNoop && _lastCompactionMaxContext === maxContext && maxContext > 0) {
|
|
39493
40951
|
return;
|
|
39494
40952
|
}
|
|
39495
40953
|
await a.pipelines.contextWindow.run(a.ctx);
|
|
39496
40954
|
_lastCompactionMsgCount = msgCount;
|
|
40955
|
+
_lastCompactionMaxContext = maxContext;
|
|
39497
40956
|
const stashed = a.ctx.lastRequestTokens;
|
|
39498
40957
|
const tokens = typeof stashed === "number" && stashed > 0 ? stashed : 0;
|
|
39499
|
-
const load =
|
|
40958
|
+
const load = maxContext > 0 ? tokens / maxContext : 0;
|
|
39500
40959
|
_lastCompactionWasNoop = tokens > 0 && load < 0.5;
|
|
39501
40960
|
}
|
|
39502
40961
|
const calibrationKey = (model = a.ctx.model) => `${a.ctx.provider?.id ?? "unknown"}/${model}`;
|
|
39503
40962
|
function emitContextPct() {
|
|
39504
40963
|
const msgCount = a.ctx.messages.length;
|
|
39505
40964
|
const toolCount = (a.ctx.tools ?? []).length;
|
|
39506
|
-
|
|
40965
|
+
const maxContext = currentMaxContext();
|
|
40966
|
+
if (msgCount === _lastEmittedMsgCount && toolCount === _lastEmittedToolCount && maxContext === _lastEmittedMaxContext && maxContext > 0) {
|
|
39507
40967
|
return;
|
|
39508
40968
|
}
|
|
39509
40969
|
_lastEmittedMsgCount = msgCount;
|
|
39510
40970
|
_lastEmittedToolCount = toolCount;
|
|
40971
|
+
_lastEmittedMaxContext = maxContext;
|
|
39511
40972
|
if (msgCount !== _lastPreFlightMsgCount) {
|
|
39512
40973
|
a.ctx.lastRequestTokens = estimateRequestTokens(
|
|
39513
40974
|
a.ctx.messages,
|
|
@@ -39517,11 +40978,6 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
39517
40978
|
_lastPreFlightMsgCount = msgCount;
|
|
39518
40979
|
a.ctx.meta["lastRequestTokensAt"] = { msgCount, toolCount };
|
|
39519
40980
|
}
|
|
39520
|
-
if (!_maxContext) {
|
|
39521
|
-
const metaLimit = a.ctx.meta?.["effectiveMaxContext"];
|
|
39522
|
-
const providerMax = a.ctx.provider.capabilities.maxContext;
|
|
39523
|
-
_maxContext = typeof metaLimit === "number" && metaLimit > 0 ? metaLimit : typeof providerMax === "number" && providerMax > 0 ? providerMax : 2e5;
|
|
39524
|
-
}
|
|
39525
40981
|
let total;
|
|
39526
40982
|
const stashed = a.ctx.lastRequestTokens;
|
|
39527
40983
|
if (typeof stashed === "number" && stashed > 0) {
|
|
@@ -39536,13 +40992,19 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
39536
40992
|
);
|
|
39537
40993
|
total = est.total;
|
|
39538
40994
|
}
|
|
39539
|
-
a.events.emit("ctx.pct", { load: total /
|
|
40995
|
+
a.events.emit("ctx.pct", { load: total / maxContext, tokens: total, maxContext });
|
|
40996
|
+
}
|
|
40997
|
+
function currentMaxContext() {
|
|
40998
|
+
const metaLimit = a.ctx.meta?.["effectiveMaxContext"];
|
|
40999
|
+
const providerMax = a.ctx.provider.capabilities.maxContext;
|
|
41000
|
+
return typeof metaLimit === "number" && metaLimit > 0 ? metaLimit : typeof providerMax === "number" && providerMax > 0 ? providerMax : 2e5;
|
|
39540
41001
|
}
|
|
39541
|
-
let _maxContext = 0;
|
|
39542
41002
|
let _lastEmittedMsgCount = -1;
|
|
39543
41003
|
let _lastEmittedToolCount = -1;
|
|
41004
|
+
let _lastEmittedMaxContext = -1;
|
|
39544
41005
|
let _lastPreFlightMsgCount = -1;
|
|
39545
41006
|
let _lastCompactionMsgCount = -1;
|
|
41007
|
+
let _lastCompactionMaxContext = -1;
|
|
39546
41008
|
let _lastCompactionWasNoop = false;
|
|
39547
41009
|
function foldBlockIntoConversation(block) {
|
|
39548
41010
|
const messages = a.ctx.messages;
|
|
@@ -39612,7 +41074,8 @@ function createAgentLoopHandler(a, handlers) {
|
|
|
39612
41074
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39613
41075
|
content: inputPayload.content
|
|
39614
41076
|
});
|
|
39615
|
-
|
|
41077
|
+
void a.ctx.session.flush().catch(() => {
|
|
41078
|
+
});
|
|
39616
41079
|
const promptIndex = a.ctx.messages.filter((m) => m.role === "user").length - 1;
|
|
39617
41080
|
const preview = inputPayload.text.slice(0, 80) + (inputPayload.text.length > 80 ? "\u2026" : "");
|
|
39618
41081
|
await a.ctx.session.writeCheckpoint(promptIndex, preview);
|
|
@@ -40365,14 +41828,20 @@ var HookRunner = class {
|
|
|
40365
41828
|
};
|
|
40366
41829
|
|
|
40367
41830
|
// src/execution/model-runtime.ts
|
|
40368
|
-
function resolveModelRuntime(settings, reasoning) {
|
|
41831
|
+
function resolveModelRuntime(settings, reasoning, capabilities) {
|
|
40369
41832
|
const warnings = [];
|
|
40370
41833
|
if (!settings) {
|
|
40371
|
-
return { reasoning: void 0, cache: void 0, warnings };
|
|
41834
|
+
return { reasoning: void 0, cache: void 0, parameters: void 0, warnings };
|
|
40372
41835
|
}
|
|
40373
41836
|
const reasoningField = resolveReasoningForRequest(settings, reasoning, warnings);
|
|
40374
41837
|
const cacheField = resolveCacheForRequest(settings);
|
|
40375
|
-
|
|
41838
|
+
const paramsField = resolveParametersForRequest(settings.parameters, capabilities);
|
|
41839
|
+
return {
|
|
41840
|
+
reasoning: reasoningField,
|
|
41841
|
+
cache: cacheField,
|
|
41842
|
+
parameters: paramsField,
|
|
41843
|
+
warnings
|
|
41844
|
+
};
|
|
40376
41845
|
}
|
|
40377
41846
|
function resolveReasoningForRequest(settings, rc, warnings) {
|
|
40378
41847
|
const cfg = settings.reasoning;
|
|
@@ -40430,11 +41899,38 @@ function resolveCacheForRequest(settings, _warnings) {
|
|
|
40430
41899
|
const out = { ttl };
|
|
40431
41900
|
return out;
|
|
40432
41901
|
}
|
|
41902
|
+
function resolveParametersForRequest(params, caps, _warnings) {
|
|
41903
|
+
if (!params) return void 0;
|
|
41904
|
+
const out = {};
|
|
41905
|
+
if (params.topK !== void 0 && caps?.topK !== false) {
|
|
41906
|
+
out.topK = params.topK;
|
|
41907
|
+
}
|
|
41908
|
+
if (params.frequencyPenalty !== void 0 && caps?.frequencyPenalty !== false) {
|
|
41909
|
+
out.frequencyPenalty = params.frequencyPenalty;
|
|
41910
|
+
}
|
|
41911
|
+
if (params.presencePenalty !== void 0 && caps?.presencePenalty !== false) {
|
|
41912
|
+
out.presencePenalty = params.presencePenalty;
|
|
41913
|
+
}
|
|
41914
|
+
if (params.seed !== void 0 && caps?.seed !== false) {
|
|
41915
|
+
out.seed = params.seed;
|
|
41916
|
+
}
|
|
41917
|
+
if (params.user !== void 0) {
|
|
41918
|
+
out.user = params.user;
|
|
41919
|
+
}
|
|
41920
|
+
if (params.logprobs !== void 0 && caps?.logprobs !== false) {
|
|
41921
|
+
out.logprobs = params.logprobs;
|
|
41922
|
+
if (params.topLogprobs !== void 0) {
|
|
41923
|
+
out.topLogprobs = params.topLogprobs;
|
|
41924
|
+
}
|
|
41925
|
+
}
|
|
41926
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
41927
|
+
}
|
|
40433
41928
|
function applyModelRuntime(req, opts) {
|
|
40434
41929
|
const settings = opts.getSettings();
|
|
40435
41930
|
if (!settings) return req;
|
|
40436
41931
|
const rc = opts.getReasoningConfig();
|
|
40437
|
-
const
|
|
41932
|
+
const caps = opts.getCapabilities?.();
|
|
41933
|
+
const resolved = resolveModelRuntime(settings, rc, caps);
|
|
40438
41934
|
for (const w of resolved.warnings) opts.onWarning?.(w);
|
|
40439
41935
|
const next = { ...req };
|
|
40440
41936
|
if (resolved.reasoning !== void 0) {
|
|
@@ -40443,6 +41939,9 @@ function applyModelRuntime(req, opts) {
|
|
|
40443
41939
|
if (resolved.cache !== void 0) {
|
|
40444
41940
|
next.cache = resolved.cache;
|
|
40445
41941
|
}
|
|
41942
|
+
if (resolved.parameters !== void 0) {
|
|
41943
|
+
Object.assign(next, resolved.parameters);
|
|
41944
|
+
}
|
|
40446
41945
|
return next;
|
|
40447
41946
|
}
|
|
40448
41947
|
async function bootConfig(options = {}) {
|
|
@@ -40765,8 +42264,8 @@ var InputBuilder = class {
|
|
|
40765
42264
|
async registerFile(input) {
|
|
40766
42265
|
const ref = await this.store.add({ ...input, kind: "file" });
|
|
40767
42266
|
this.refs.push(ref);
|
|
40768
|
-
const
|
|
40769
|
-
return `[file:${
|
|
42267
|
+
const path50 = ref.meta.filename ?? ref.meta.label ?? String(ref.seq);
|
|
42268
|
+
return `[file:${path50}]`;
|
|
40770
42269
|
}
|
|
40771
42270
|
/**
|
|
40772
42271
|
* Whether `appendPaste(text)` would collapse the text to a placeholder
|
|
@@ -40915,9 +42414,9 @@ var DefaultSystemPromptBuilder = class {
|
|
|
40915
42414
|
skillBodyCache;
|
|
40916
42415
|
/** Tools from last build — used for memory relevance scoring. */
|
|
40917
42416
|
_lastBuildTools;
|
|
40918
|
-
/** Cached rendered online agents string, keyed by
|
|
42417
|
+
/** Cached rendered online agents string, keyed by content fingerprint. */
|
|
40919
42418
|
_lastOnlineAgents;
|
|
40920
|
-
/** Cached full buildToolUsage output — keyed by tools array +
|
|
42419
|
+
/** Cached full buildToolUsage output — keyed by tools array ref + agents fingerprint. */
|
|
40921
42420
|
_toolsUsageCache;
|
|
40922
42421
|
/**
|
|
40923
42422
|
* Normalizes `tokenSavingMode` to a boolean for backward-compatible boolean checks.
|
|
@@ -41053,13 +42552,13 @@ var DefaultSystemPromptBuilder = class {
|
|
|
41053
42552
|
if (!planPath) return "";
|
|
41054
42553
|
let raw;
|
|
41055
42554
|
try {
|
|
41056
|
-
const
|
|
41057
|
-
if (this._planCache && this._planCache.path === planPath && this._planCache.mtimeMs ===
|
|
42555
|
+
const stat16 = await fsp3.stat(planPath);
|
|
42556
|
+
if (this._planCache && this._planCache.path === planPath && this._planCache.mtimeMs === stat16.mtimeMs) {
|
|
41058
42557
|
return this._planCache.text;
|
|
41059
42558
|
}
|
|
41060
42559
|
raw = await fsp3.readFile(planPath, "utf8");
|
|
41061
42560
|
const text = this._formatPlan(raw);
|
|
41062
|
-
this._planCache = { path: planPath, mtimeMs:
|
|
42561
|
+
this._planCache = { path: planPath, mtimeMs: stat16.mtimeMs, text };
|
|
41063
42562
|
return text;
|
|
41064
42563
|
} catch {
|
|
41065
42564
|
this._planCache = void 0;
|
|
@@ -41074,8 +42573,8 @@ var DefaultSystemPromptBuilder = class {
|
|
|
41074
42573
|
return "";
|
|
41075
42574
|
}
|
|
41076
42575
|
if (!Array.isArray(parsed.items) || parsed.items.length === 0) return "";
|
|
41077
|
-
const
|
|
41078
|
-
if (
|
|
42576
|
+
const open10 = parsed.items.filter((i) => i?.status !== "done");
|
|
42577
|
+
if (open10.length === 0) return "";
|
|
41079
42578
|
const lines = ["## Active plan"];
|
|
41080
42579
|
if (parsed.title) lines.push(`*${parsed.title}*`, "");
|
|
41081
42580
|
parsed.items.forEach((it, idx) => {
|
|
@@ -41090,7 +42589,8 @@ var DefaultSystemPromptBuilder = class {
|
|
|
41090
42589
|
}
|
|
41091
42590
|
buildToolUsage(tools, ctx) {
|
|
41092
42591
|
if (tools.length === 0) return "## Tool usage\n\nNo tools registered.";
|
|
41093
|
-
|
|
42592
|
+
const agentsHash = this.agentsFingerprint(ctx.onlineAgents);
|
|
42593
|
+
if (this._toolsUsageCache?.toolsRef === tools && this._toolsUsageCache?.agentsHash === agentsHash) {
|
|
41094
42594
|
return this._toolsUsageCache.text;
|
|
41095
42595
|
}
|
|
41096
42596
|
const byCat = /* @__PURE__ */ new Map();
|
|
@@ -41377,7 +42877,7 @@ the server connection \u2014 only tool visibility changes.`);
|
|
|
41377
42877
|
|
|
41378
42878
|
Use \`context_manager\` to manage context. Call \`{"action":"check"}\` to see token budget.`);
|
|
41379
42879
|
} else {
|
|
41380
|
-
const maxCtx = this.
|
|
42880
|
+
const maxCtx = this.modelCapabilities()?.maxContextTokens ?? 128e3;
|
|
41381
42881
|
const threshold = maxCtx <= 32e3 ? "50" : "70";
|
|
41382
42882
|
lines.push(`
|
|
41383
42883
|
## Context management
|
|
@@ -41395,15 +42895,38 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
41395
42895
|
}
|
|
41396
42896
|
}
|
|
41397
42897
|
const text = lines.join("\n");
|
|
41398
|
-
this._toolsUsageCache = { toolsRef: tools,
|
|
42898
|
+
this._toolsUsageCache = { toolsRef: tools, agentsHash, text };
|
|
41399
42899
|
return text;
|
|
41400
42900
|
}
|
|
41401
42901
|
/**
|
|
41402
|
-
*
|
|
42902
|
+
* Cheap content fingerprint of the online agents array. The mailbox
|
|
42903
|
+
* rebuilds the array as a fresh object on every status check, so caching
|
|
42904
|
+
* by reference always misses — this lets the renderOnlineAgents and
|
|
42905
|
+
* buildToolUsage caches detect membership changes instead.
|
|
42906
|
+
*
|
|
42907
|
+
* O(n) over agent names with no per-element string concatenation. Uses
|
|
42908
|
+
* FNV-1a over character codes so two different agent sets collide only
|
|
42909
|
+
* if they produce the identical sequence of name characters — astronomically
|
|
42910
|
+
* unlikely. A collision would produce a stale agent list in the prompt,
|
|
42911
|
+
* a cosmetic issue, not a correctness bug.
|
|
42912
|
+
*/
|
|
42913
|
+
agentsFingerprint(agents) {
|
|
42914
|
+
if (!agents || agents.length === 0) return "0";
|
|
42915
|
+
let h = 2166136261;
|
|
42916
|
+
for (const a of agents) {
|
|
42917
|
+
for (let i = 0; i < a.name.length; i++) {
|
|
42918
|
+
h ^= a.name.charCodeAt(i);
|
|
42919
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
42920
|
+
}
|
|
42921
|
+
}
|
|
42922
|
+
return `${agents.length}:${h.toString(36)}`;
|
|
42923
|
+
}
|
|
42924
|
+
/**
|
|
42925
|
+
* Render the online agents list, cached by content fingerprint. The agents
|
|
41403
42926
|
* list changes at join/leave pace (seconds to minutes), not every prompt
|
|
41404
|
-
* build turn (hundreds of ms).
|
|
41405
|
-
* the
|
|
41406
|
-
*
|
|
42927
|
+
* build turn (hundreds of ms). The fingerprint detects membership changes
|
|
42928
|
+
* without holding the array reference — the mailbox rebuilds the array as
|
|
42929
|
+
* a fresh object on every status check, so reference equality always misses.
|
|
41407
42930
|
*
|
|
41408
42931
|
* Tier behaviour:
|
|
41409
42932
|
* - 'off' / 'medium' / 'aggressive' → full list with names, sessions, sources
|
|
@@ -41411,13 +42934,14 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
41411
42934
|
*/
|
|
41412
42935
|
renderOnlineAgents(agents) {
|
|
41413
42936
|
if (!agents || agents.length === 0) return "";
|
|
41414
|
-
|
|
42937
|
+
const hash = this.agentsFingerprint(agents);
|
|
42938
|
+
if (this._lastOnlineAgents?.hash === hash) {
|
|
41415
42939
|
return this._lastOnlineAgents.text;
|
|
41416
42940
|
}
|
|
41417
42941
|
const totalCount = agents.length;
|
|
41418
42942
|
if (this.tier === "minimal" || this.tier === "light") {
|
|
41419
42943
|
const text2 = ` (${totalCount} agent${totalCount !== 1 ? "s" : ""} online)`;
|
|
41420
|
-
this._lastOnlineAgents = {
|
|
42944
|
+
this._lastOnlineAgents = { hash, text: text2 };
|
|
41421
42945
|
return text2;
|
|
41422
42946
|
}
|
|
41423
42947
|
const agentList = agents.map(
|
|
@@ -41427,11 +42951,21 @@ summarize it, and let the tool result hold only the summary.`);
|
|
|
41427
42951
|
|
|
41428
42952
|
**Currently online (${totalCount} agent${totalCount !== 1 ? "s" : ""}):**
|
|
41429
42953
|
${agentList}`;
|
|
41430
|
-
this._lastOnlineAgents = {
|
|
42954
|
+
this._lastOnlineAgents = { hash, text };
|
|
41431
42955
|
return text;
|
|
41432
42956
|
}
|
|
41433
42957
|
async buildEnvironment(ctx) {
|
|
41434
|
-
const
|
|
42958
|
+
const modelCapabilities = this.modelCapabilities();
|
|
42959
|
+
const cacheKey = [
|
|
42960
|
+
ctx.projectRoot,
|
|
42961
|
+
ctx.provider ?? "",
|
|
42962
|
+
ctx.model ?? "",
|
|
42963
|
+
modelCapabilities?.maxContextTokens ?? 0,
|
|
42964
|
+
modelCapabilities?.supportsTools ? 1 : 0,
|
|
42965
|
+
modelCapabilities?.supportsVision ? 1 : 0,
|
|
42966
|
+
modelCapabilities?.supportsReasoning ? 1 : 0
|
|
42967
|
+
].join("\0");
|
|
42968
|
+
const cached = this.envCacheByRoot.get(cacheKey);
|
|
41435
42969
|
if (cached) return cached;
|
|
41436
42970
|
const today = this.opts.todayIso ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
41437
42971
|
const platform2 = `${os6.platform()} ${os6.release()}`;
|
|
@@ -41463,15 +42997,15 @@ ${agentList}`;
|
|
|
41463
42997
|
`- Running on: ${ctx.provider ?? "<unknown provider>"}/${ctx.model ?? "<unknown model>"}`
|
|
41464
42998
|
);
|
|
41465
42999
|
}
|
|
41466
|
-
if (
|
|
43000
|
+
if (modelCapabilities) {
|
|
41467
43001
|
lines.push(
|
|
41468
|
-
`- Context window: ${
|
|
43002
|
+
`- Context window: ${modelCapabilities.maxContextTokens.toLocaleString()} tokens max`
|
|
41469
43003
|
);
|
|
41470
43004
|
}
|
|
41471
43005
|
}
|
|
41472
|
-
if (tier !== "aggressive" &&
|
|
43006
|
+
if (tier !== "aggressive" && modelCapabilities) {
|
|
41473
43007
|
lines.push(
|
|
41474
|
-
`- Context window: ${
|
|
43008
|
+
`- Context window: ${modelCapabilities.maxContextTokens.toLocaleString()} tokens max`
|
|
41475
43009
|
);
|
|
41476
43010
|
}
|
|
41477
43011
|
if (tier !== "aggressive" && (ctx.provider || ctx.model)) {
|
|
@@ -41493,9 +43027,13 @@ ${agentList}`;
|
|
|
41493
43027
|
);
|
|
41494
43028
|
}
|
|
41495
43029
|
const text = lines.join("\n");
|
|
41496
|
-
this.envCacheByRoot.set(
|
|
43030
|
+
this.envCacheByRoot.set(cacheKey, text);
|
|
41497
43031
|
return text;
|
|
41498
43032
|
}
|
|
43033
|
+
modelCapabilities() {
|
|
43034
|
+
const caps = this.opts.modelCapabilities;
|
|
43035
|
+
return typeof caps === "function" ? caps() : caps;
|
|
43036
|
+
}
|
|
41499
43037
|
async buildMemoryAndSkills() {
|
|
41500
43038
|
const parts = [];
|
|
41501
43039
|
const memoryCount = this.tier === "minimal" ? 3 : this.tier === "light" ? 5 : 8;
|
|
@@ -41621,8 +43159,8 @@ ${clean.trim()}`);
|
|
|
41621
43159
|
}
|
|
41622
43160
|
async dirExists(p) {
|
|
41623
43161
|
try {
|
|
41624
|
-
const
|
|
41625
|
-
return
|
|
43162
|
+
const stat16 = await fsp3.stat(p);
|
|
43163
|
+
return stat16.isDirectory();
|
|
41626
43164
|
} catch {
|
|
41627
43165
|
return false;
|
|
41628
43166
|
}
|
|
@@ -42554,18 +44092,21 @@ Rules:
|
|
|
42554
44092
|
- Be concise: one tight instruction per version (a few sentences at most). No preamble, no explanation, no quotes, no markdown headers.
|
|
42555
44093
|
- If the message is already clear and complete, return it essentially unchanged.
|
|
42556
44094
|
|
|
42557
|
-
|
|
42558
|
-
|
|
42559
|
-
-
|
|
44095
|
+
Detect the language of the user's LATEST message and output accordingly:
|
|
44096
|
+
|
|
44097
|
+
- If that message is ALREADY in English: output exactly ONE refined version, in English. Nothing else \u2014 no "---" line, no second copy.
|
|
44098
|
+
- If that message is in ANY OTHER language (Turkish, Spanish, \u2026): output TWO versions separated by a line containing only "---":
|
|
44099
|
+
- First version: refined in the SAME LANGUAGE the user wrote in.
|
|
44100
|
+
- Second version: refined in ENGLISH (translate the intent into clear English while preserving all concrete details).
|
|
42560
44101
|
|
|
42561
|
-
Output format:
|
|
44102
|
+
Output format for non-English input:
|
|
42562
44103
|
<refined in user's language>
|
|
42563
44104
|
---
|
|
42564
44105
|
<refined in English>
|
|
42565
44106
|
|
|
42566
|
-
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.
|
|
44107
|
+
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. The conversation language does NOT decide the output language \u2014 only the language of the latest message does.
|
|
42567
44108
|
|
|
42568
|
-
Output ONLY the
|
|
44109
|
+
Output ONLY the refined request(s) in the format above \u2014 nothing else.`;
|
|
42569
44110
|
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;
|
|
42570
44111
|
function shouldEnhance(text) {
|
|
42571
44112
|
const t2 = text.trim();
|
|
@@ -42578,6 +44119,24 @@ function shouldEnhance(text) {
|
|
|
42578
44119
|
if (words.length < 3) return false;
|
|
42579
44120
|
return true;
|
|
42580
44121
|
}
|
|
44122
|
+
var EFFORT_PREFERENCE = [
|
|
44123
|
+
"low",
|
|
44124
|
+
"minimal",
|
|
44125
|
+
"medium",
|
|
44126
|
+
"high",
|
|
44127
|
+
"xhigh",
|
|
44128
|
+
"max",
|
|
44129
|
+
"none"
|
|
44130
|
+
];
|
|
44131
|
+
function gatedEnhancerReasoning(rc) {
|
|
44132
|
+
if (!rc) return void 0;
|
|
44133
|
+
if (rc.effortSupported && rc.effortLevels.length > 0) {
|
|
44134
|
+
const lowest = EFFORT_PREFERENCE.find((e) => rc.effortLevels.includes(e)) ?? rc.effortLevels[0];
|
|
44135
|
+
if (lowest) return { effort: lowest };
|
|
44136
|
+
}
|
|
44137
|
+
if (rc.disableSupported) return { enabled: false };
|
|
44138
|
+
return void 0;
|
|
44139
|
+
}
|
|
42581
44140
|
function normalizedEqual(a, b) {
|
|
42582
44141
|
const norm = (s) => s.trim().replace(/\s+/g, " ").toLowerCase();
|
|
42583
44142
|
return norm(a) === norm(b);
|
|
@@ -42601,11 +44160,17 @@ async function enhanceUserPrompt(opts) {
|
|
|
42601
44160
|
model,
|
|
42602
44161
|
system: [{ type: "text", text: ENHANCER_SYSTEM_PROMPT }],
|
|
42603
44162
|
messages: [{ role: "user", content: buildRefinerInput(text, opts.history) }],
|
|
42604
|
-
maxTokens
|
|
44163
|
+
maxTokens,
|
|
42605
44164
|
// NOTE: deliberately NO `temperature`. The main agent loop never sets it,
|
|
42606
44165
|
// and reasoning models (DeepSeek reasoner, o1/o3, …) return HTTP 400 when
|
|
42607
44166
|
// `temperature` is present — which would make every refine call fail and
|
|
42608
44167
|
// silently fall back to the original (no panel shown).
|
|
44168
|
+
//
|
|
44169
|
+
// A reasoning hint is forwarded ONLY when the caller supplies one (it must
|
|
44170
|
+
// already be gated to the model's advertised support — see
|
|
44171
|
+
// `gatedEnhancerReasoning`). Absent it, no reasoning field is sent, which
|
|
44172
|
+
// is identical to the original behavior.
|
|
44173
|
+
...opts.reasoning ? { reasoning: opts.reasoning } : {}
|
|
42609
44174
|
};
|
|
42610
44175
|
const timer = new AbortController();
|
|
42611
44176
|
const to = setTimeout(() => timer.abort(new Error("enhancer timeout")), timeoutMs);
|
|
@@ -42619,7 +44184,6 @@ async function enhanceUserPrompt(opts) {
|
|
|
42619
44184
|
}
|
|
42620
44185
|
const sepIdx = raw.indexOf("\n---\n");
|
|
42621
44186
|
if (sepIdx === -1) {
|
|
42622
|
-
opts.onError?.("model did not produce two versions");
|
|
42623
44187
|
return { refined: raw, english: raw };
|
|
42624
44188
|
}
|
|
42625
44189
|
const refined = raw.slice(0, sepIdx).trim();
|
|
@@ -44573,6 +46137,24 @@ var CollaborationBus = class {
|
|
|
44573
46137
|
// "skip the bash call, just give it the answer I typed". The
|
|
44574
46138
|
// injection is matched by tool_use_id, consumed once, and discarded.
|
|
44575
46139
|
injectionQueue = /* @__PURE__ */ new Map();
|
|
46140
|
+
onConsumed;
|
|
46141
|
+
/**
|
|
46142
|
+
* Register a listener fired when `collabInjectMiddleware` actually splices a
|
|
46143
|
+
* queued injection into a tool call (Phase 4 feedback loop). The webui's
|
|
46144
|
+
* CollaborationWebSocketHandler uses it to broadcast a
|
|
46145
|
+
* `collab.injection.granted` with phase `'consumed'` so observers learn the
|
|
46146
|
+
* injection was applied (and to which real tool). Last registration wins.
|
|
46147
|
+
*/
|
|
46148
|
+
onInjectionConsumed(fn) {
|
|
46149
|
+
this.onConsumed = fn;
|
|
46150
|
+
}
|
|
46151
|
+
/**
|
|
46152
|
+
* Invoked by `collabInjectMiddleware` immediately after it replaces a tool
|
|
46153
|
+
* call's result with a queued injection. No-op when no listener is set.
|
|
46154
|
+
*/
|
|
46155
|
+
notifyInjectionConsumed(info) {
|
|
46156
|
+
this.onConsumed?.(info);
|
|
46157
|
+
}
|
|
44576
46158
|
/**
|
|
44577
46159
|
* Queue a manual tool result. The next time the agent's toolCall
|
|
44578
46160
|
* pipeline sees a matching `toolUse.id`, the
|
|
@@ -44967,8 +46549,8 @@ function extractManifestPath(msg) {
|
|
|
44967
46549
|
}
|
|
44968
46550
|
return void 0;
|
|
44969
46551
|
}
|
|
44970
|
-
function isManifestFile(
|
|
44971
|
-
const name = pathBasename(
|
|
46552
|
+
function isManifestFile(path50) {
|
|
46553
|
+
const name = pathBasename(path50).toLowerCase();
|
|
44972
46554
|
const manifests = [
|
|
44973
46555
|
"package.json",
|
|
44974
46556
|
"package-lock.json",
|
|
@@ -45068,6 +46650,13 @@ function collabInjectMiddleware(bus, opts = {}) {
|
|
|
45068
46650
|
content: typeof injected.content === "string" ? injected.content : JSON.stringify(injected.content),
|
|
45069
46651
|
is_error: injected.isError
|
|
45070
46652
|
};
|
|
46653
|
+
bus.notifyInjectionConsumed({
|
|
46654
|
+
toolUseId: payload.toolUse.id,
|
|
46655
|
+
toolName: payload.toolUse.name,
|
|
46656
|
+
authorId: injected.authorId,
|
|
46657
|
+
reason: injected.reason,
|
|
46658
|
+
isError: injected.isError
|
|
46659
|
+
});
|
|
45071
46660
|
};
|
|
45072
46661
|
}
|
|
45073
46662
|
|
|
@@ -46471,6 +48060,6 @@ function createChimeraPlugin() {
|
|
|
46471
48060
|
};
|
|
46472
48061
|
}
|
|
46473
48062
|
|
|
46474
|
-
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, TOOLS as AGENT_TOOL_PRESETS, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousBrain, AutonomousCoordinator, AutonomousRunner, BUG_HUNTER_AGENT, BUILD_AGENTS, BrainDecisionQueue, BrainMonitor, BudgetExceededError, BudgetThresholdSignal, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, ChangeManager, CheckpointManager, CloudSync, CollabSession, CollaborationBus, ConfigError, ConfigMigrationError, ConsensusProtocol, Container, Context, ConversationState, DANGEROUS_FOR_SUBAGENTS, DECISION_TIMEOUT_MS, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_HQ_REDACTION_POLICY, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_QUALITY_CHECKS, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEFAULT_TUI_THINKING_WORD, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorAlertLevel, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetNotifier, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HEAVY_BUDGET, HQ_AUTH_FILE_VERSION, HQ_PROTOCOL_VERSION, HookRegistry, HookRunner, HqPublisher, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, KNOWLEDGE_AGENTS, KnowledgeGraph, LAYER_1_IDENTITY, LIGHT_BUDGET, LLMSelector, LargeAnswerStore, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MAX_TUI_THINKING_WORD_LENGTH, MEDIUM_BUDGET, MEMORY_TYPE_LABELS, META_AGENTS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PLANNING_AGENTS, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, REVIEW_AGENTS, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TIMEOUT_PREEMPT_FRACTION, TOKENS, TaskAuctioneer, TaskDAG, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolCapabilities, ToolError, ToolErrorCategory, ToolExecutor, ToolRegistry, VERIFY_AGENTS, WIDE_SUBAGENT_CAPABILITIES, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyModelRuntime, applyRosterBudget, asBlocks, asText, assertNever, assertNotPrivateHost, assertSafePath, assessCommitSafety, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildContextEvidenceDigest, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compactSchemaDescriptions, compactToolDefinitionForWire, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextEvidenceState, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createGlobalMailbox, createHqEventEnvelope, createHqPublisherFromEnv, createMailboxChecker, createMailboxEventPayload, createMailboxHooks, createMailboxSnapshotPayload, createMailboxSnapshotPayloadFromMailbox, createMcpControlTool, createMcpUseTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultHqDataDir, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, definePlugin, deriveTodosFromPlanItem, describeCatalogModel, detectEcosystem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyHqAuthFile, emptyPlan, emptyTaskFile, encryptConfigSecrets, encryptedPrefixForVersion, enhanceUserPrompt, ensureDir, ensureHqFirstRunAuthFile, escapeGlobSubject, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expandIPv6, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, getAgentDefinition, getCalibrationState, getContextWindowMode, getDangerousCapabilities, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getJsonPath, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasCapability, hasDangerousCapabilityForSubagents, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, hqAuthFilePath, hqRuntimeFilePath, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isJsonObject, isPathSubjectKey, isPluginError, isPrimitiveArray, isPrivateIPv4, isPrivateIPv6, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, jsonObjectFileExists, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskResultTool, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, makeWorkCompleteTool, mapMailboxAgentToHqSummary, mapMailboxMessageToHqSummary, markAssistantReferencedEvidence, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, migratePlaintextSecrets, miniMaxVisionServer, mintHqBrowserToken, mintHqToken, mutateHqAuthFile, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizePathSubject, normalizeRecipient, normalizeToLf, normalizeTokenSavingTier, normalizeTuiThinkingWord, normalizedEqual, onResize, parseContinueDirective, parseEncryptedVersion, parseEntries, parseHqEventPayload, parseHqFrame, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, playwrightServer, projectHash, projectSlug, readHqAuthFile, readHqRuntimeFileSync, readJsonObjectFile, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, recordToolOutputEvidence, recordUserIntentEvidence, redactHqEvent, redactHqValue, removeJsonPath, removeJsonPathInFile, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, repeatedReadPressure, resetCalibration, resolveAuditLevel, resolveCacheForRequest, resolveChimeraConfig, resolveContextWindowPolicy, resolveHqConfig, resolveHqConfigFromEnv, resolveHqDataDir, resolveMailboxIdentity, resolveModelMatrix, resolveModelRuntime, resolveProjectDir, resolveProviderModelList, resolveReasoningForRequest, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, rotateConfigKeys, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, scrubAndTruncateHqPreview, securitySlashCommand, sentinelServer, setBtwNote, setJsonPath, setJsonPathInFile, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, sshManagerServer, stableStringify, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startTechStackConsumer, stripAnsi, subjectForToolInput, summarizeHqToolArgs, summarizeUsage, templateToMarkdown, toErrorMessage, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updateJsonObjectFile, updatePackageOutdatedStatus, validateAgainstSchema, watchHqAuthFile, wireMetricsToEvents, withDisabledToolFiltering, withFileLock, wrapAsState, writeErr, writeHqAuthFile, writeHqRuntimeFile, writeJsonObjectFile, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
48063
|
+
export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, TOOLS as AGENT_TOOL_PRESETS, AISpecBuilder, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, ALL_SYNC_CATEGORIES, AUDIT_LOG_AGENT, Agent, AgentError, AgentMonitorService, AgentStatusTracker, AnnotationsStore, AutoApprovePermissionPolicy, AutoCompactionMiddleware, AutoExecutor, AutoPhasePlanner, AutoPhaseRunner, AutonomousBrain, AutonomousCoordinator, AutonomousRunner, BUG_HUNTER_AGENT, BUILD_AGENTS, BrainDecisionQueue, BrainMonitor, BudgetExceededError, BudgetThresholdSignal, CHIMERA_REVIEW_PROMPT, CONTEXT_WINDOW_MODES, CORE_RECONSTRUCT_EVENTS, ChangeManager, CheckpointManager, CloudSync, CollabSession, CollaborationBus, ConfigError, ConfigMigrationError, ConsensusProtocol, Container, Context, ConversationState, DANGEROUS_FOR_SUBAGENTS, DECISION_TIMEOUT_MS, DEFAULT_AUTONOMY_CONFIG, DEFAULT_CIRCUIT_BREAKER_CONFIG, DEFAULT_CONFIG_MIGRATIONS, DEFAULT_CONTEXT_CONFIG, DEFAULT_CONTEXT_WINDOW_MODE_ID, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_HQ_REDACTION_POLICY, DEFAULT_MAX_ITERATIONS, DEFAULT_MODES, DEFAULT_QUALITY_CHECKS, DEFAULT_RECOVERY_STRATEGIES, DEFAULT_SESSION_LOGGING_CONFIG, DEFAULT_SESSION_PRUNE_DAYS, DEFAULT_SPEC_TEMPLATE, DEFAULT_SUBAGENT_BASELINE, DEFAULT_TOOLS_CONFIG, DEFAULT_TUI_THINKING_WORD, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, DefaultAttachmentStore, DefaultBrainArbiter, DefaultConfigLoader, DefaultConfigStore, DefaultErrorHandler, DefaultHealthRegistry, DefaultLogger, DefaultMailbox, DefaultMemoryStore, DefaultModeStore, DefaultModelsRegistry, DefaultMultiAgentCoordinator, DefaultPathResolver, DefaultPermissionPolicy, DefaultPluginAPI, DefaultPromptStore, DefaultProviderRunner, DefaultRetryPolicy, DefaultSecretScrubber, DefaultSecretVault, DefaultSessionReader, DefaultSessionRewinder, DefaultSessionStore, DefaultSkillLoader, DefaultSystemPromptBuilder, DefaultTaskStore, DefaultTokenCounter, Director, DirectorAlertLevel, DirectorStateCheckpoint, DoneConditionChecker, ENHANCER_SYSTEM_PROMPT, ERROR_CODES, EternalAutonomyEngine, EventBus, ExtensionRegistry, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FORBIDDEN_PROTO_KEYS, FileMemoryBackend, FleetBus, FleetCostCapError, FleetManager, FleetNotifier, FleetSpawnBudgetError, FleetUsageAggregator, FsError, GitignoreUpdater, GlobalMailbox, GraphMemoryBackend, HEAVY_BUDGET, HQ_AUTH_FILE_VERSION, HQ_PROTOCOL_VERSION, HookRegistry, HookRunner, HqPublisher, HumanEscalatingBrainArbiter, HybridCompactor, InMemoryAgentBridge, InMemoryBridgeTransport, InMemoryMetricsSink, InputBuilder, IntelligentCompactor, KERNEL_API_VERSION, KNOWLEDGE_AGENTS, KnowledgeGraph, LAYER_1_IDENTITY, LIGHT_BUDGET, LLMSelector, LargeAnswerStore, MATRIX_PHASE_KEYS, MAX_JOURNAL_ENTRIES, MAX_PROGRESS_HISTORY, MAX_TUI_THINKING_WORD_LENGTH, MEDIUM_BUDGET, MEMORY_TYPE_LABELS, META_AGENTS, NULL_FLEET_BUS, NoopMetricsSink, NoopTracer, OTelTracer, ObservableBrainArbiter, PLANNING_AGENTS, PROMETHEUS_CONTENT_TYPE, ParallelEternalEngine, PhaseGraphBuilder, PhaseOrchestrator, PhaseStore, Pipeline, PluginError, ProviderError, ProviderRegistry, QueueStore, REFACTOR_PLANNER_AGENT, REVIEW_AGENTS, RecoveryLock, ReplayLogStore, ReplayProviderRunner, ReportGenerator, RunController, SECURITY_SCANNER_AGENT, SPEC_TEMPLATES, STANDARD_AUDIT_EVENTS, ScopedEventBus, SddError, SddParallelRun, SddTaskDecomposer, SecurityScanner, SecurityScannerOrchestrator, SelectiveCompactor, SessionAnalyzer, SessionError, SessionMemoryConsolidator, SessionRecovery, SessionRegistry, SkillGenerator, SkillInstaller, SkillManifestStore, SlashCommandRegistry, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, StreamHangError, SubagentBudget, TIMEOUT_PREEMPT_FRACTION, TOKENS, TaskAuctioneer, TaskDAG, TaskFlow, TaskGenerator, TaskGraphStore, TaskTracker, TechStackDetector, ToolAuditLog, ToolCapabilities, ToolError, ToolErrorCategory, ToolExecutor, ToolRegistry, VERIFY_AGENTS, WIDE_SUBAGENT_CAPABILITIES, WorktreeManager, WrongStackError, addPlanItem, allServers, analyzeCriticalPath, appendJournal, applyModelRuntime, applyRosterBudget, asBlocks, asText, assertNever, assertNotPrivateHost, assertSafePath, assessCommitSafety, atomicWrite, attachAutoExtend, attachDepWatcherBridge, attachMailboxChecker, attachPlanCheckpoint, attachTodosCheckpoint, awsServer, blockServer, bootConfig, braveSearchServer, buildBtwBlock, buildChildEnv, buildContextEvidenceDigest, buildGoalPreamble, buildLosslessDigest, buildMailboxBlock, buildOtlpMetricsRequest, buildOtlpTracesRequest, buildQueuedMessagesBlock, buildRecoveryStrategies, buildSmartDigest, buildTranscriptFromEvents, classifyFamily, clearPlan, collabInjectMiddleware, collabPauseMiddleware, color, compactLog, compactSchemaDescriptions, compactToolDefinitionForWire, compileGlob, compileUserRegex, completePartialObject, composeDirectorPrompt, composeSubagentPrompt, computeMessageTokens, computeTaskItemProgress, computeTaskProgress, consumeBtwNotes, consumeQueuedMessagesUpdate, context7Server, contextManagerTool, createAgentMonitorService, createAutoExecutor, createAutoPhaseFromTaskGraph, createAutonomyBrain, createChimeraPlugin, createContextEvidenceState, createContextManagerTool, createDefaultPipelines, createDelegateTool, createGitPlugin, createGlobalMailbox, createHqEventEnvelope, createHqPublisherFromEnv, createMailboxChecker, createMailboxEventPayload, createMailboxHooks, createMailboxSnapshotPayload, createMailboxSnapshotPayloadFromMailbox, createMcpControlTool, createMcpUseTool, createMessage, createObservabilityPlugin, createPlanPlugin, createPromptsPlugin, createSecurityPlugin, createSecuritySlashCommand, createSessionEventBridge, createSkillsPlugin, createStrategyCompactor, createSyncPlugin, createTieredBrainArbiter, createToolOutputSerializer, decryptConfigSecrets, deepMerge, defaultGitignoreUpdater, defaultHqDataDir, defaultOrchestrator, defaultReportGenerator, defaultSecurityScanner, defaultSkillGenerator, defaultTechStackDetector, definePlugin, deriveTodosFromPlanItem, describeCatalogModel, detectEcosystem, detectNewlineStyle, detectEcosystem as detectPackageEcosystem, dispatchAgent, downloadGitHubTarball, eliseOldToolResults, emptyGoal, emptyHqAuthFile, emptyPlan, emptyTaskFile, encryptConfigSecrets, encryptedPrefixForVersion, enhanceUserPrompt, ensureDir, ensureHqFirstRunAuthFile, escapeGlobSubject, estimateMessageTokens, estimateMessages, estimateRequestTokens, estimateRequestTokensCalibrated, estimateTextTokens, estimateToolDefTokens, estimateToolInputTokens, estimateToolResultTokens, everArtServer, expandGlob, expandIPv6, expectDefined, extractRunEnv, extractText, filesystemServer, findCriticalPath, findPreserveStart, flagsToConfigPatch, formatContextWindowModeList, formatDecisionSummary, formatGoal, formatHumanPrompt, formatPlan, formatPlanTemplates, formatTaskList, formatTaskProgress, formatTodosList, gatedEnhancerReasoning, generateSessionId, getAgentDefinition, getCalibrationState, getContextWindowMode, getDangerousCapabilities, getFileHistory, getFilesByAgent, getFullLog, getFullPackageLog, getJsonPath, getLastAuthor, getManifestPackages, getPackageAuthor, getPackagesByAgent, getPlanTemplate, getSessionRegistry, getTemplate, getTermSize, githubServer, goalFilePath, googleMapsServer, hasCapability, hasDangerousCapabilityForSubagents, hasSessionRegistry, hasTextContent, hashRequest, hookMatcherMatches, hqAuthFilePath, hqRuntimeFilePath, injectPendingMailboxMessages, isAgentError, isConfigError, isContextWindowModeId, isFsError, isImageBlock, isInteractive, isJsonObject, isPathSubjectKey, isPluginError, isPrimitiveArray, isPrivateIPv4, isPrivateIPv6, isSddError, isSecretField, isSessionError, isStdinTTY, isStdoutTTY, isTextBlock, isThinkingBlock, isToolError, isToolResultBlock, isToolUseBlock, isValidMatrixKey, isWrongStackError, jsonObjectFileExists, listContextWindowModes, listPlanTemplates, listTemplates, loadDirectorState, loadGoal, loadPlan, loadPlugins, loadProjectModes, loadTasks, loadTodosCheckpoint, loadUserModes, mailboxSessionTag, makeAgentSubagentRunner, makeAskResultTool, makeAskTool, makeAssignTool, makeAutonomyPromptContributor, makeAwaitTasksTool, makeCollabDebugTool, makeContinueToNextIterationTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetHealthTool, makeFleetSessionTool, makeFleetStatusTool, makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateTool, makeWorkCompleteTool, mapMailboxAgentToHqSummary, mapMailboxMessageToHqSummary, mapSessionEventToEntries, markAssistantReferencedEvidence, matchAny, matchGlob, matrixKeyKind, mergeCustomModelDefs, mergeModelsPayload, mergeToolResults, migratePlaintextSecrets, miniMaxVisionServer, mintHqBrowserToken, mintHqToken, mutateHqAuthFile, mutatePlan, mutateTasks, noOpLogger, noOpVault, normalizePathSubject, normalizeRecipient, normalizeToLf, normalizeTokenSavingTier, normalizeTuiThinkingWord, normalizedEqual, onResize, parseContinueDirective, parseEncryptedVersion, parseEntries, parseHqEventPayload, parseHqFrame, parseProgressFromText, parseSkillRef, peekQueuedMessages, pendingBtwCount, phaseForRole, playwrightServer, projectHash, projectSlug, readHqAuthFile, readHqRuntimeFileSync, readJsonObjectFile, recentTextTurns, recordActualUsage, recordFileAction, recordPackageAction, recordProgress, recordToolOutputEvidence, recordUserIntentEvidence, redactHqEvent, redactHqValue, removeJsonPath, removeJsonPathInFile, removePlanItem, renderProgress, renderPrometheus, renderSpecAnalysis, renderTaskGraph, renderTaskList, repairToolUseAdjacency, repeatedReadPressure, resetCalibration, resolveAuditLevel, resolveCacheForRequest, resolveChimeraConfig, resolveContextWindowPolicy, resolveHqConfig, resolveHqConfigFromEnv, resolveHqDataDir, resolveMailboxIdentity, resolveModelMatrix, resolveModelRuntime, resolveProjectDir, resolveProviderModelList, resolveReasoningForRequest, resolveSessionLoggingConfig, resolveWstackPaths, rewriteConfigEncrypted, rosterSummaryFromConfigs, rotateConfigKeys, runConfigMigrations, runProviderWithRetry, runShellHook, safeParse, safeStringify, sanitizeJsonString, sanitizeModel, sanitizeNodeOptions, saveGoal, savePlan, saveTasks, saveTodosCheckpoint, scoreAgents, scoreMessage, scrubAndTruncateHqPreview, securitySlashCommand, sentinelServer, setBtwNote, setJsonPath, setJsonPathInFile, setOutputLineGuard, setPlanItemStatus, setProgress, setQueuedMessagesSnapshot, setRawMode, shouldEnhance, slackServer, sleep, sshManagerServer, stableStringify, startAgentMonitorEventBridge, startMetricsServer, startOtlpMetricsExporter, startOtlpTraceExporter, startPackageOutdatedWatcher, startSessionTelemetryBridge, startTechStackConsumer, stripAnsi, subjectForToolInput, summarizeHqToolArgs, summarizeUsage, templateToMarkdown, toErrorMessage, toStyle, toWrongStackError, topologicalSort, truncate, unifiedDiff, unloadPlugins, updateJsonObjectFile, updatePackageOutdatedStatus, validateAgainstSchema, watchHqAuthFile, wireMetricsToEvents, withDisabledToolFiltering, withFileLock, wrapAsState, writeErr, writeHqAuthFile, writeHqRuntimeFile, writeJsonObjectFile, writeOut, wstackGlobalRoot, zaiVisionServer };
|
|
46475
48064
|
//# sourceMappingURL=index.js.map
|
|
46476
48065
|
//# sourceMappingURL=index.js.map
|