gossipcat 0.1.0 → 0.1.2
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/README.md +294 -121
- package/dist-mcp/data/archetypes.json +226 -0
- package/dist-mcp/mcp-server.js +879 -741
- package/package.json +2 -2
package/dist-mcp/mcp-server.js
CHANGED
|
@@ -69,6 +69,46 @@ var init_mcp_context = __esm({
|
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
|
|
72
|
+
// apps/cli/src/version.ts
|
|
73
|
+
var version_exports = {};
|
|
74
|
+
__export(version_exports, {
|
|
75
|
+
getGossipcatVersion: () => getGossipcatVersion
|
|
76
|
+
});
|
|
77
|
+
function getGossipcatVersion() {
|
|
78
|
+
if (cached2 !== null) return cached2;
|
|
79
|
+
cached2 = resolveVersion();
|
|
80
|
+
return cached2;
|
|
81
|
+
}
|
|
82
|
+
function resolveVersion() {
|
|
83
|
+
let dir = __dirname;
|
|
84
|
+
const root = (0, import_path.resolve)("/");
|
|
85
|
+
for (let i = 0; i < 20 && dir !== root; i++) {
|
|
86
|
+
const candidate = (0, import_path.resolve)(dir, "package.json");
|
|
87
|
+
if ((0, import_fs.existsSync)(candidate)) {
|
|
88
|
+
try {
|
|
89
|
+
const pkg = JSON.parse((0, import_fs.readFileSync)(candidate, "utf-8"));
|
|
90
|
+
if (pkg && pkg.name === "gossipcat" && typeof pkg.version === "string") {
|
|
91
|
+
return pkg.version;
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const parent = (0, import_path.dirname)(dir);
|
|
97
|
+
if (parent === dir) break;
|
|
98
|
+
dir = parent;
|
|
99
|
+
}
|
|
100
|
+
return "unknown";
|
|
101
|
+
}
|
|
102
|
+
var import_fs, import_path, cached2;
|
|
103
|
+
var init_version = __esm({
|
|
104
|
+
"apps/cli/src/version.ts"() {
|
|
105
|
+
"use strict";
|
|
106
|
+
import_fs = require("fs");
|
|
107
|
+
import_path = require("path");
|
|
108
|
+
cached2 = null;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
72
112
|
// packages/orchestrator/src/llm-client.ts
|
|
73
113
|
async function fetchWithRetry503(url2, init, providerName) {
|
|
74
114
|
const res = await fetch(url2, init);
|
|
@@ -108,13 +148,13 @@ function createProvider(provider, model, apiKey, projectRoot, baseUrl) {
|
|
|
108
148
|
throw new Error(`Unknown provider: ${provider}`);
|
|
109
149
|
}
|
|
110
150
|
}
|
|
111
|
-
var import_crypto,
|
|
151
|
+
var import_crypto, import_fs2, import_path2, QuotaExhaustedException, QuotaTracker, AnthropicProvider, OpenAIProvider, GeminiProvider, OllamaProvider, NullProvider;
|
|
112
152
|
var init_llm_client = __esm({
|
|
113
153
|
"packages/orchestrator/src/llm-client.ts"() {
|
|
114
154
|
"use strict";
|
|
115
155
|
import_crypto = require("crypto");
|
|
116
|
-
|
|
117
|
-
|
|
156
|
+
import_fs2 = require("fs");
|
|
157
|
+
import_path2 = require("path");
|
|
118
158
|
QuotaExhaustedException = class extends Error {
|
|
119
159
|
provider;
|
|
120
160
|
retryAfterMs;
|
|
@@ -128,7 +168,7 @@ var init_llm_client = __esm({
|
|
|
128
168
|
QuotaTracker = class {
|
|
129
169
|
constructor(provider, projectRoot) {
|
|
130
170
|
this.provider = provider;
|
|
131
|
-
this.statePath = projectRoot ? (0,
|
|
171
|
+
this.statePath = projectRoot ? (0, import_path2.join)(projectRoot, ".gossip", "quota-state.json") : null;
|
|
132
172
|
this.load();
|
|
133
173
|
}
|
|
134
174
|
consecutive429s = 0;
|
|
@@ -136,9 +176,9 @@ var init_llm_client = __esm({
|
|
|
136
176
|
reason = "quota";
|
|
137
177
|
statePath;
|
|
138
178
|
load() {
|
|
139
|
-
if (!this.statePath || !(0,
|
|
179
|
+
if (!this.statePath || !(0, import_fs2.existsSync)(this.statePath)) return;
|
|
140
180
|
try {
|
|
141
|
-
const state = JSON.parse((0,
|
|
181
|
+
const state = JSON.parse((0, import_fs2.readFileSync)(this.statePath, "utf-8"));
|
|
142
182
|
if (state[this.provider]) {
|
|
143
183
|
this.exhaustedUntil = state[this.provider].exhaustedUntil;
|
|
144
184
|
this.consecutive429s = state[this.provider].consecutive429s;
|
|
@@ -150,15 +190,15 @@ var init_llm_client = __esm({
|
|
|
150
190
|
persist() {
|
|
151
191
|
if (!this.statePath) return;
|
|
152
192
|
try {
|
|
153
|
-
const dir = (0,
|
|
154
|
-
if (!(0,
|
|
193
|
+
const dir = (0, import_path2.join)(this.statePath, "..");
|
|
194
|
+
if (!(0, import_fs2.existsSync)(dir)) (0, import_fs2.mkdirSync)(dir, { recursive: true });
|
|
155
195
|
let existing = {};
|
|
156
196
|
try {
|
|
157
|
-
existing = JSON.parse((0,
|
|
197
|
+
existing = JSON.parse((0, import_fs2.readFileSync)(this.statePath, "utf-8"));
|
|
158
198
|
} catch {
|
|
159
199
|
}
|
|
160
200
|
existing[this.provider] = { exhaustedUntil: this.exhaustedUntil, consecutive429s: this.consecutive429s, reason: this.reason };
|
|
161
|
-
(0,
|
|
201
|
+
(0, import_fs2.writeFileSync)(this.statePath, JSON.stringify(existing, null, 2));
|
|
162
202
|
} catch {
|
|
163
203
|
}
|
|
164
204
|
}
|
|
@@ -3078,7 +3118,7 @@ var init_gossip_agent = __esm({
|
|
|
3078
3118
|
}
|
|
3079
3119
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
3080
3120
|
connect() {
|
|
3081
|
-
return new Promise((
|
|
3121
|
+
return new Promise((resolve18, reject) => {
|
|
3082
3122
|
const ws = new import_ws.default(this.config.relayUrl);
|
|
3083
3123
|
const timeout = setTimeout(() => {
|
|
3084
3124
|
ws.removeAllListeners();
|
|
@@ -3111,7 +3151,7 @@ var init_gossip_agent = __esm({
|
|
|
3111
3151
|
ws.on("error", (err) => this.emit("error", err));
|
|
3112
3152
|
this.startKeepAlive();
|
|
3113
3153
|
this.emit("connect", msg.sessionId);
|
|
3114
|
-
|
|
3154
|
+
resolve18();
|
|
3115
3155
|
} else if (msg.type === "error") {
|
|
3116
3156
|
clearTimeout(timeout);
|
|
3117
3157
|
ws.removeAllListeners();
|
|
@@ -3137,7 +3177,7 @@ var init_gossip_agent = __esm({
|
|
|
3137
3177
|
this.reconnectTimer = null;
|
|
3138
3178
|
}
|
|
3139
3179
|
if (!this.ws) return;
|
|
3140
|
-
return new Promise((
|
|
3180
|
+
return new Promise((resolve18) => {
|
|
3141
3181
|
this.intentionalDisconnect = true;
|
|
3142
3182
|
this._connected = false;
|
|
3143
3183
|
const ws = this.ws;
|
|
@@ -3148,7 +3188,7 @@ var init_gossip_agent = __esm({
|
|
|
3148
3188
|
settled = true;
|
|
3149
3189
|
this.intentionalDisconnect = false;
|
|
3150
3190
|
this.emit("disconnect", code);
|
|
3151
|
-
|
|
3191
|
+
resolve18();
|
|
3152
3192
|
};
|
|
3153
3193
|
const timer = setTimeout(() => done(1e3), 2e3);
|
|
3154
3194
|
ws.once("close", (code) => {
|
|
@@ -3187,8 +3227,8 @@ var init_gossip_agent = __esm({
|
|
|
3187
3227
|
throw new Error("Not connected to relay");
|
|
3188
3228
|
}
|
|
3189
3229
|
const encoded = Buffer.from(this.codec.encode(envelope));
|
|
3190
|
-
return new Promise((
|
|
3191
|
-
this.ws.send(encoded, (err) => err ? reject(err) :
|
|
3230
|
+
return new Promise((resolve18, reject) => {
|
|
3231
|
+
this.ws.send(encoded, (err) => err ? reject(err) : resolve18());
|
|
3192
3232
|
});
|
|
3193
3233
|
}
|
|
3194
3234
|
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
@@ -3632,7 +3672,7 @@ ${context}` : ""}
|
|
|
3632
3672
|
this.toolCallBudget.set(name, used + 1);
|
|
3633
3673
|
}
|
|
3634
3674
|
const requestId = (0, import_crypto4.randomUUID)();
|
|
3635
|
-
const resultPromise = new Promise((
|
|
3675
|
+
const resultPromise = new Promise((resolve18, reject) => {
|
|
3636
3676
|
const timer = setTimeout(() => {
|
|
3637
3677
|
if (this.pendingToolCalls.has(requestId)) {
|
|
3638
3678
|
this.pendingToolCalls.delete(requestId);
|
|
@@ -3643,7 +3683,7 @@ ${context}` : ""}
|
|
|
3643
3683
|
this.pendingToolCalls.set(requestId, {
|
|
3644
3684
|
resolve: (r) => {
|
|
3645
3685
|
clearTimeout(timer);
|
|
3646
|
-
|
|
3686
|
+
resolve18(r);
|
|
3647
3687
|
},
|
|
3648
3688
|
reject: (e) => {
|
|
3649
3689
|
clearTimeout(timer);
|
|
@@ -3708,12 +3748,12 @@ ${context}` : ""}
|
|
|
3708
3748
|
});
|
|
3709
3749
|
|
|
3710
3750
|
// packages/tools/src/file-tools.ts
|
|
3711
|
-
var import_promises,
|
|
3751
|
+
var import_promises, import_path3, FileTools;
|
|
3712
3752
|
var init_file_tools = __esm({
|
|
3713
3753
|
"packages/tools/src/file-tools.ts"() {
|
|
3714
3754
|
"use strict";
|
|
3715
3755
|
import_promises = require("fs/promises");
|
|
3716
|
-
|
|
3756
|
+
import_path3 = require("path");
|
|
3717
3757
|
FileTools = class {
|
|
3718
3758
|
constructor(sandbox) {
|
|
3719
3759
|
this.sandbox = sandbox;
|
|
@@ -3738,7 +3778,7 @@ var init_file_tools = __esm({
|
|
|
3738
3778
|
}
|
|
3739
3779
|
async fileWrite(args) {
|
|
3740
3780
|
const absPath = this.sandbox.validatePath(args.path);
|
|
3741
|
-
const dir = (0,
|
|
3781
|
+
const dir = (0, import_path3.resolve)(absPath, "..");
|
|
3742
3782
|
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
3743
3783
|
await (0, import_promises.writeFile)(absPath, args.content, "utf-8");
|
|
3744
3784
|
return `Written ${args.content.length} bytes to ${args.path}`;
|
|
@@ -3783,7 +3823,7 @@ var init_file_tools = __esm({
|
|
|
3783
3823
|
}
|
|
3784
3824
|
for (const entry of entries) {
|
|
3785
3825
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
3786
|
-
const fullPath = (0,
|
|
3826
|
+
const fullPath = (0, import_path3.join)(dir, entry);
|
|
3787
3827
|
let info;
|
|
3788
3828
|
try {
|
|
3789
3829
|
info = await (0, import_promises.stat)(fullPath);
|
|
@@ -3795,7 +3835,7 @@ var init_file_tools = __esm({
|
|
|
3795
3835
|
} else {
|
|
3796
3836
|
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
3797
3837
|
const regex = new RegExp(regexStr);
|
|
3798
|
-
const relPath = (0,
|
|
3838
|
+
const relPath = (0, import_path3.relative)(this.sandbox.projectRoot, fullPath);
|
|
3799
3839
|
if (regex.test(entry) || regex.test(relPath)) {
|
|
3800
3840
|
results.push(relPath);
|
|
3801
3841
|
}
|
|
@@ -3812,7 +3852,7 @@ var init_file_tools = __esm({
|
|
|
3812
3852
|
}
|
|
3813
3853
|
for (const entry of entries) {
|
|
3814
3854
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
3815
|
-
const fullPath = (0,
|
|
3855
|
+
const fullPath = (0, import_path3.join)(dir, entry);
|
|
3816
3856
|
let info;
|
|
3817
3857
|
try {
|
|
3818
3858
|
info = await (0, import_promises.stat)(fullPath);
|
|
@@ -3825,7 +3865,7 @@ var init_file_tools = __esm({
|
|
|
3825
3865
|
try {
|
|
3826
3866
|
const content = await (0, import_promises.readFile)(fullPath, "utf-8");
|
|
3827
3867
|
const lines = content.split("\n");
|
|
3828
|
-
const relPath = (0,
|
|
3868
|
+
const relPath = (0, import_path3.relative)(this.sandbox.projectRoot, fullPath);
|
|
3829
3869
|
lines.forEach((line, idx) => {
|
|
3830
3870
|
if (regex.test(line)) {
|
|
3831
3871
|
results.push(`${relPath}:${idx + 1}: ${line}`);
|
|
@@ -3849,7 +3889,7 @@ var init_file_tools = __esm({
|
|
|
3849
3889
|
const entry = filtered[i];
|
|
3850
3890
|
const isLast = i === filtered.length - 1;
|
|
3851
3891
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
3852
|
-
const fullPath = (0,
|
|
3892
|
+
const fullPath = (0, import_path3.join)(dir, entry);
|
|
3853
3893
|
let info;
|
|
3854
3894
|
try {
|
|
3855
3895
|
info = await (0, import_promises.stat)(fullPath);
|
|
@@ -4054,20 +4094,20 @@ var init_git_tools = __esm({
|
|
|
4054
4094
|
});
|
|
4055
4095
|
|
|
4056
4096
|
// packages/tools/src/skill-tools.ts
|
|
4057
|
-
var
|
|
4097
|
+
var import_fs3, import_path4, SkillTools;
|
|
4058
4098
|
var init_skill_tools = __esm({
|
|
4059
4099
|
"packages/tools/src/skill-tools.ts"() {
|
|
4060
4100
|
"use strict";
|
|
4061
|
-
|
|
4062
|
-
|
|
4101
|
+
import_fs3 = require("fs");
|
|
4102
|
+
import_path4 = require("path");
|
|
4063
4103
|
SkillTools = class {
|
|
4064
4104
|
gapLogPath;
|
|
4065
4105
|
constructor(projectRoot) {
|
|
4066
|
-
const gossipDir2 = (0,
|
|
4067
|
-
if (!(0,
|
|
4068
|
-
(0,
|
|
4106
|
+
const gossipDir2 = (0, import_path4.join)(projectRoot, ".gossip");
|
|
4107
|
+
if (!(0, import_fs3.existsSync)(gossipDir2)) {
|
|
4108
|
+
(0, import_fs3.mkdirSync)(gossipDir2, { recursive: true });
|
|
4069
4109
|
}
|
|
4070
|
-
this.gapLogPath = (0,
|
|
4110
|
+
this.gapLogPath = (0, import_path4.join)(gossipDir2, "skill-gaps.jsonl");
|
|
4071
4111
|
}
|
|
4072
4112
|
async suggestSkill(args, callerId) {
|
|
4073
4113
|
const entry = {
|
|
@@ -4078,16 +4118,16 @@ var init_skill_tools = __esm({
|
|
|
4078
4118
|
task_context: args.task_context,
|
|
4079
4119
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
4080
4120
|
};
|
|
4081
|
-
(0,
|
|
4121
|
+
(0, import_fs3.appendFileSync)(this.gapLogPath, JSON.stringify(entry) + "\n");
|
|
4082
4122
|
this.truncateIfNeeded();
|
|
4083
4123
|
return `Suggestion noted: '${args.skill_name}'. Continue with your current skills.`;
|
|
4084
4124
|
}
|
|
4085
4125
|
truncateIfNeeded() {
|
|
4086
4126
|
try {
|
|
4087
|
-
const content = (0,
|
|
4127
|
+
const content = (0, import_fs3.readFileSync)(this.gapLogPath, "utf-8");
|
|
4088
4128
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
4089
4129
|
if (lines.length > 5e3) {
|
|
4090
|
-
(0,
|
|
4130
|
+
(0, import_fs3.writeFileSync)(this.gapLogPath, lines.slice(-1e3).join("\n") + "\n");
|
|
4091
4131
|
}
|
|
4092
4132
|
} catch {
|
|
4093
4133
|
}
|
|
@@ -4097,16 +4137,16 @@ var init_skill_tools = __esm({
|
|
|
4097
4137
|
});
|
|
4098
4138
|
|
|
4099
4139
|
// packages/tools/src/sandbox.ts
|
|
4100
|
-
var
|
|
4140
|
+
var import_path5, import_fs4, Sandbox;
|
|
4101
4141
|
var init_sandbox = __esm({
|
|
4102
4142
|
"packages/tools/src/sandbox.ts"() {
|
|
4103
4143
|
"use strict";
|
|
4104
|
-
|
|
4105
|
-
|
|
4144
|
+
import_path5 = require("path");
|
|
4145
|
+
import_fs4 = require("fs");
|
|
4106
4146
|
Sandbox = class {
|
|
4107
4147
|
root;
|
|
4108
4148
|
constructor(projectRoot) {
|
|
4109
|
-
this.root = (0,
|
|
4149
|
+
this.root = (0, import_fs4.realpathSync)((0, import_path5.resolve)(projectRoot));
|
|
4110
4150
|
}
|
|
4111
4151
|
get projectRoot() {
|
|
4112
4152
|
return this.root;
|
|
@@ -4118,14 +4158,14 @@ var init_sandbox = __esm({
|
|
|
4118
4158
|
* Resolves symlinks to prevent symlink escape attacks.
|
|
4119
4159
|
*/
|
|
4120
4160
|
validatePath(filePath) {
|
|
4121
|
-
const resolved = (0,
|
|
4161
|
+
const resolved = (0, import_path5.resolve)(this.root, filePath);
|
|
4122
4162
|
let checkPath = resolved;
|
|
4123
|
-
while (!(0,
|
|
4124
|
-
const parent = (0,
|
|
4163
|
+
while (!(0, import_fs4.existsSync)(checkPath)) {
|
|
4164
|
+
const parent = (0, import_path5.dirname)(checkPath);
|
|
4125
4165
|
if (parent === checkPath) break;
|
|
4126
4166
|
checkPath = parent;
|
|
4127
4167
|
}
|
|
4128
|
-
const real = (0,
|
|
4168
|
+
const real = (0, import_fs4.existsSync)(checkPath) ? (0, import_fs4.realpathSync)(checkPath) : checkPath;
|
|
4129
4169
|
const remainder = resolved.slice(checkPath.length);
|
|
4130
4170
|
const fullReal = real + remainder;
|
|
4131
4171
|
if (!fullReal.startsWith(this.root + "/") && fullReal !== this.root) {
|
|
@@ -8343,16 +8383,16 @@ var init_tool_schemas = __esm({
|
|
|
8343
8383
|
// packages/tools/src/tool-server.ts
|
|
8344
8384
|
function canonicalizeForBoundary(p) {
|
|
8345
8385
|
let out = p;
|
|
8346
|
-
if ((0,
|
|
8386
|
+
if ((0, import_fs5.existsSync)(out)) {
|
|
8347
8387
|
try {
|
|
8348
|
-
out = (0,
|
|
8388
|
+
out = (0, import_fs5.realpathSync)(out);
|
|
8349
8389
|
} catch {
|
|
8350
8390
|
}
|
|
8351
8391
|
} else {
|
|
8352
|
-
const parent = (0,
|
|
8353
|
-
if (parent !== out && (0,
|
|
8392
|
+
const parent = (0, import_path6.dirname)(out);
|
|
8393
|
+
if (parent !== out && (0, import_fs5.existsSync)(parent)) {
|
|
8354
8394
|
try {
|
|
8355
|
-
out = (0,
|
|
8395
|
+
out = (0, import_path6.join)((0, import_fs5.realpathSync)(parent), (0, import_path6.basename)(out));
|
|
8356
8396
|
} catch {
|
|
8357
8397
|
}
|
|
8358
8398
|
}
|
|
@@ -8385,7 +8425,7 @@ function truncateAtLine(text, maxLength) {
|
|
|
8385
8425
|
const cut = text.lastIndexOf("\n", maxLength);
|
|
8386
8426
|
return text.slice(0, cut !== -1 ? cut : maxLength);
|
|
8387
8427
|
}
|
|
8388
|
-
var import_msgpack4, import_crypto5,
|
|
8428
|
+
var import_msgpack4, import_crypto5, import_path6, import_fs5, CASE_INSENSITIVE_FS, ToolServer;
|
|
8389
8429
|
var init_tool_server = __esm({
|
|
8390
8430
|
"packages/tools/src/tool-server.ts"() {
|
|
8391
8431
|
"use strict";
|
|
@@ -8399,8 +8439,8 @@ var init_tool_server = __esm({
|
|
|
8399
8439
|
init_skill_tools();
|
|
8400
8440
|
init_sandbox();
|
|
8401
8441
|
init_tool_schemas();
|
|
8402
|
-
|
|
8403
|
-
|
|
8442
|
+
import_path6 = require("path");
|
|
8443
|
+
import_fs5 = require("fs");
|
|
8404
8444
|
CASE_INSENSITIVE_FS = process.platform === "darwin" || process.platform === "win32";
|
|
8405
8445
|
ToolServer = class _ToolServer {
|
|
8406
8446
|
agent;
|
|
@@ -8455,12 +8495,12 @@ var init_tool_server = __esm({
|
|
|
8455
8495
|
return this.agent.agentId;
|
|
8456
8496
|
}
|
|
8457
8497
|
assignScope(agentId, scope) {
|
|
8458
|
-
const abs = (0,
|
|
8498
|
+
const abs = (0, import_path6.resolve)(this.sandbox.projectRoot, scope);
|
|
8459
8499
|
this.agentScopes.set(agentId, canonicalizeForBoundary(abs));
|
|
8460
8500
|
this.writeAgents.add(agentId);
|
|
8461
8501
|
}
|
|
8462
8502
|
assignRoot(agentId, root) {
|
|
8463
|
-
const abs = (0,
|
|
8503
|
+
const abs = (0, import_path6.resolve)(root);
|
|
8464
8504
|
this.agentRoots.set(agentId, canonicalizeForBoundary(abs));
|
|
8465
8505
|
this.writeAgents.add(agentId);
|
|
8466
8506
|
}
|
|
@@ -8520,13 +8560,13 @@ var init_tool_server = __esm({
|
|
|
8520
8560
|
if (toolName === "file_write") {
|
|
8521
8561
|
const filePath = args.path;
|
|
8522
8562
|
if (scope) {
|
|
8523
|
-
const canonical = canonicalizeForBoundary((0,
|
|
8563
|
+
const canonical = canonicalizeForBoundary((0, import_path6.resolve)(this.sandbox.projectRoot, filePath));
|
|
8524
8564
|
if (!canonical.startsWith(scope)) {
|
|
8525
8565
|
throw new Error(`Write blocked: "${filePath}" is outside scope "${scope}"`);
|
|
8526
8566
|
}
|
|
8527
8567
|
}
|
|
8528
8568
|
if (root) {
|
|
8529
|
-
const canonical = canonicalizeForBoundary((0,
|
|
8569
|
+
const canonical = canonicalizeForBoundary((0, import_path6.resolve)(root, filePath));
|
|
8530
8570
|
if (!canonical.startsWith(root)) {
|
|
8531
8571
|
throw new Error(`Write blocked: "${filePath}" is outside worktree root "${root}"`);
|
|
8532
8572
|
}
|
|
@@ -8561,13 +8601,13 @@ var init_tool_server = __esm({
|
|
|
8561
8601
|
if (toolName === "file_delete") {
|
|
8562
8602
|
const filePath = args.path;
|
|
8563
8603
|
if (scope) {
|
|
8564
|
-
const canonical = canonicalizeForBoundary((0,
|
|
8604
|
+
const canonical = canonicalizeForBoundary((0, import_path6.resolve)(this.sandbox.projectRoot, filePath));
|
|
8565
8605
|
if (!canonical.startsWith(scope)) {
|
|
8566
8606
|
throw new Error(`Delete blocked: "${filePath}" is outside scope "${scope}"`);
|
|
8567
8607
|
}
|
|
8568
8608
|
}
|
|
8569
8609
|
if (root) {
|
|
8570
|
-
const canonical = canonicalizeForBoundary((0,
|
|
8610
|
+
const canonical = canonicalizeForBoundary((0, import_path6.resolve)(root, filePath));
|
|
8571
8611
|
if (!canonical.startsWith(root)) {
|
|
8572
8612
|
throw new Error(`Delete blocked: "${filePath}" is outside worktree root "${root}"`);
|
|
8573
8613
|
}
|
|
@@ -8603,7 +8643,7 @@ var init_tool_server = __esm({
|
|
|
8603
8643
|
case "file_read": {
|
|
8604
8644
|
const readScope = callerId ? this.agentScopes.get(callerId) : void 0;
|
|
8605
8645
|
if (readScope) {
|
|
8606
|
-
const canonical = canonicalizeForBoundary((0,
|
|
8646
|
+
const canonical = canonicalizeForBoundary((0, import_path6.resolve)(this.sandbox.projectRoot, args.path));
|
|
8607
8647
|
if (!canonical.startsWith(readScope)) {
|
|
8608
8648
|
throw new Error(`Read blocked: "${args.path}" is outside scope "${readScope}"`);
|
|
8609
8649
|
}
|
|
@@ -8797,7 +8837,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
8797
8837
|
}
|
|
8798
8838
|
async requestPeerReview(callerId, diff, testResult) {
|
|
8799
8839
|
const requestId = (0, import_crypto5.randomUUID)();
|
|
8800
|
-
const reviewPromise = new Promise((
|
|
8840
|
+
const reviewPromise = new Promise((resolve18, reject) => {
|
|
8801
8841
|
const timer = setTimeout(() => {
|
|
8802
8842
|
this.pendingReviews.delete(requestId);
|
|
8803
8843
|
reject(new Error("Review timed out"));
|
|
@@ -8806,7 +8846,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
8806
8846
|
this.pendingReviews.set(requestId, {
|
|
8807
8847
|
resolve: (r) => {
|
|
8808
8848
|
clearTimeout(timer);
|
|
8809
|
-
|
|
8849
|
+
resolve18(r);
|
|
8810
8850
|
},
|
|
8811
8851
|
reject: (e) => {
|
|
8812
8852
|
clearTimeout(timer);
|
|
@@ -8832,7 +8872,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
8832
8872
|
}
|
|
8833
8873
|
async handleRunTests(args, callerId) {
|
|
8834
8874
|
const { fileGlob } = args;
|
|
8835
|
-
const resolvedGlob = (0,
|
|
8875
|
+
const resolvedGlob = (0, import_path6.resolve)(this.sandbox.projectRoot, fileGlob.replace(/\*/g, "_"));
|
|
8836
8876
|
if (!resolvedGlob.startsWith(this.sandbox.projectRoot)) {
|
|
8837
8877
|
throw new Error("run_tests: fileGlob must not contain path traversal");
|
|
8838
8878
|
}
|
|
@@ -8840,7 +8880,7 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
8840
8880
|
throw new Error("run_tests: fileGlob must not contain flags. Pass only file paths/globs.");
|
|
8841
8881
|
}
|
|
8842
8882
|
const scope = callerId ? this.agentScopes.get(callerId) : void 0;
|
|
8843
|
-
const cwd = scope ? this.sandbox.validatePath((0,
|
|
8883
|
+
const cwd = scope ? this.sandbox.validatePath((0, import_path6.resolve)(this.sandbox.projectRoot, scope)) : this.sandbox.projectRoot;
|
|
8844
8884
|
let output;
|
|
8845
8885
|
let success2;
|
|
8846
8886
|
try {
|
|
@@ -8860,11 +8900,11 @@ ${truncateAtLine(fullDiff, 3e3)}`;
|
|
|
8860
8900
|
}
|
|
8861
8901
|
async handleRunTypecheck(callerId) {
|
|
8862
8902
|
const scope = callerId ? this.agentScopes.get(callerId) : void 0;
|
|
8863
|
-
const cwd = scope ? this.sandbox.validatePath((0,
|
|
8903
|
+
const cwd = scope ? this.sandbox.validatePath((0, import_path6.resolve)(this.sandbox.projectRoot, scope)) : this.sandbox.projectRoot;
|
|
8864
8904
|
let output;
|
|
8865
8905
|
let success2;
|
|
8866
8906
|
try {
|
|
8867
|
-
const tsconfigPath = (0,
|
|
8907
|
+
const tsconfigPath = (0, import_path6.resolve)(this.sandbox.projectRoot, "tsconfig.json");
|
|
8868
8908
|
output = await this.shellTools.shellExec({
|
|
8869
8909
|
command: "npx",
|
|
8870
8910
|
args: ["tsc", "--noEmit", "--project", tsconfigPath],
|
|
@@ -9247,16 +9287,16 @@ function resolveSkill(agentId, skill, projectRoot) {
|
|
|
9247
9287
|
if (!normalized) return null;
|
|
9248
9288
|
const filename = `${normalized}.md`;
|
|
9249
9289
|
const bases = [
|
|
9250
|
-
(0,
|
|
9251
|
-
(0,
|
|
9252
|
-
(0,
|
|
9290
|
+
(0, import_path7.resolve)(projectRoot, ".gossip", "agents", agentId, "skills"),
|
|
9291
|
+
(0, import_path7.resolve)(projectRoot, ".gossip", "skills"),
|
|
9292
|
+
(0, import_path7.resolve)(__dirname, "default-skills")
|
|
9253
9293
|
];
|
|
9254
9294
|
for (const base of bases) {
|
|
9255
|
-
const candidate = (0,
|
|
9256
|
-
if (!candidate.startsWith(base +
|
|
9257
|
-
if ((0,
|
|
9295
|
+
const candidate = (0, import_path7.resolve)(base, filename);
|
|
9296
|
+
if (!candidate.startsWith(base + import_path7.sep)) continue;
|
|
9297
|
+
if ((0, import_fs6.existsSync)(candidate)) {
|
|
9258
9298
|
try {
|
|
9259
|
-
return (0,
|
|
9299
|
+
return (0, import_fs6.readFileSync)(candidate, "utf-8");
|
|
9260
9300
|
} catch (err) {
|
|
9261
9301
|
process.stderr.write(
|
|
9262
9302
|
`[skill-loader] Failed to read skill file ${candidate}: ${err?.message ?? err}
|
|
@@ -9271,12 +9311,12 @@ function resolveSkill(agentId, skill, projectRoot) {
|
|
|
9271
9311
|
function resolveSkillExists(agentId, skill, projectRoot) {
|
|
9272
9312
|
return resolveSkill(agentId, skill, projectRoot) !== null;
|
|
9273
9313
|
}
|
|
9274
|
-
var
|
|
9314
|
+
var import_fs6, import_path7, SAFE_AGENT_ID, MAX_CONTEXTUAL_SKILLS, MIN_KEYWORD_HITS, DEFAULT_KEYWORDS, patternCache, MAX_PATTERN_CACHE, MAX_KEYWORD_LENGTH;
|
|
9275
9315
|
var init_skill_loader = __esm({
|
|
9276
9316
|
"packages/orchestrator/src/skill-loader.ts"() {
|
|
9277
9317
|
"use strict";
|
|
9278
|
-
|
|
9279
|
-
|
|
9318
|
+
import_fs6 = require("fs");
|
|
9319
|
+
import_path7 = require("path");
|
|
9280
9320
|
init_skill_parser();
|
|
9281
9321
|
init_skill_name();
|
|
9282
9322
|
SAFE_AGENT_ID = /^[a-z0-9][a-z0-9_-]{0,62}$/;
|
|
@@ -9475,29 +9515,29 @@ Attributes can appear in any order. Do NOT include confirmations.`;
|
|
|
9475
9515
|
});
|
|
9476
9516
|
|
|
9477
9517
|
// packages/orchestrator/src/agent-memory.ts
|
|
9478
|
-
var
|
|
9518
|
+
var import_fs7, import_path8, AgentMemoryReader;
|
|
9479
9519
|
var init_agent_memory = __esm({
|
|
9480
9520
|
"packages/orchestrator/src/agent-memory.ts"() {
|
|
9481
9521
|
"use strict";
|
|
9482
|
-
|
|
9483
|
-
|
|
9522
|
+
import_fs7 = require("fs");
|
|
9523
|
+
import_path8 = require("path");
|
|
9484
9524
|
AgentMemoryReader = class {
|
|
9485
9525
|
constructor(projectRoot) {
|
|
9486
9526
|
this.projectRoot = projectRoot;
|
|
9487
9527
|
}
|
|
9488
9528
|
loadMemory(agentId, taskText) {
|
|
9489
|
-
const memDir = (0,
|
|
9490
|
-
const indexPath = (0,
|
|
9491
|
-
if (!(0,
|
|
9529
|
+
const memDir = (0, import_path8.join)(this.projectRoot, ".gossip", "agents", agentId, "memory");
|
|
9530
|
+
const indexPath = (0, import_path8.join)(memDir, "MEMORY.md");
|
|
9531
|
+
if (!(0, import_fs7.existsSync)(indexPath)) return null;
|
|
9492
9532
|
const parts = [];
|
|
9493
|
-
const indexContent = (0,
|
|
9533
|
+
const indexContent = (0, import_fs7.readFileSync)(indexPath, "utf-8");
|
|
9494
9534
|
const indexLines = indexContent.split("\n");
|
|
9495
9535
|
parts.push(indexLines.length > 200 ? indexLines.slice(0, 200).join("\n") + "\n[Truncated]" : indexContent);
|
|
9496
|
-
const knowledgeDir = (0,
|
|
9497
|
-
if ((0,
|
|
9536
|
+
const knowledgeDir = (0, import_path8.join)(memDir, "knowledge");
|
|
9537
|
+
if ((0, import_fs7.existsSync)(knowledgeDir)) {
|
|
9498
9538
|
const files = this.selectKnowledgeFiles(knowledgeDir, taskText);
|
|
9499
9539
|
for (const file2 of files) {
|
|
9500
|
-
let content = (0,
|
|
9540
|
+
let content = (0, import_fs7.readFileSync)(file2.path, "utf-8");
|
|
9501
9541
|
content = content.replace(/<\/?(?:agent-memory|system|instructions)>/gi, "");
|
|
9502
9542
|
parts.push(`<agent-memory>
|
|
9503
9543
|
${content}
|
|
@@ -9507,11 +9547,11 @@ ${content}
|
|
|
9507
9547
|
}
|
|
9508
9548
|
}
|
|
9509
9549
|
}
|
|
9510
|
-
const projectKnowledgeDir = (0,
|
|
9511
|
-
if ((0,
|
|
9550
|
+
const projectKnowledgeDir = (0, import_path8.join)(this.projectRoot, ".gossip", "agents", "_project", "memory", "knowledge");
|
|
9551
|
+
if ((0, import_fs7.existsSync)(projectKnowledgeDir)) {
|
|
9512
9552
|
const projectFiles = this.selectKnowledgeFiles(projectKnowledgeDir, taskText, 3);
|
|
9513
9553
|
for (const file2 of projectFiles) {
|
|
9514
|
-
let content = (0,
|
|
9554
|
+
let content = (0, import_fs7.readFileSync)(file2.path, "utf-8");
|
|
9515
9555
|
content = content.replace(/<\/?(?:agent-memory|system|instructions)>/gi, "");
|
|
9516
9556
|
parts.push(`<project-context>
|
|
9517
9557
|
${content}
|
|
@@ -9521,19 +9561,19 @@ ${content}
|
|
|
9521
9561
|
}
|
|
9522
9562
|
}
|
|
9523
9563
|
}
|
|
9524
|
-
const calPath = (0,
|
|
9525
|
-
if ((0,
|
|
9526
|
-
parts.push((0,
|
|
9564
|
+
const calPath = (0, import_path8.join)(memDir, "calibration", "accuracy.md");
|
|
9565
|
+
if ((0, import_fs7.existsSync)(calPath)) {
|
|
9566
|
+
parts.push((0, import_fs7.readFileSync)(calPath, "utf-8"));
|
|
9527
9567
|
}
|
|
9528
9568
|
return parts.join("\n\n");
|
|
9529
9569
|
}
|
|
9530
9570
|
selectKnowledgeFiles(knowledgeDir, taskText, maxFiles = 5) {
|
|
9531
|
-
const files = (0,
|
|
9571
|
+
const files = (0, import_fs7.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
|
|
9532
9572
|
const scored = [];
|
|
9533
9573
|
const lower = taskText.toLowerCase();
|
|
9534
9574
|
for (const file2 of files) {
|
|
9535
|
-
const filePath = (0,
|
|
9536
|
-
const content = (0,
|
|
9575
|
+
const filePath = (0, import_path8.join)(knowledgeDir, file2);
|
|
9576
|
+
const content = (0, import_fs7.readFileSync)(filePath, "utf-8");
|
|
9537
9577
|
const frontmatter = this.parseFrontmatter(content);
|
|
9538
9578
|
if (frontmatter) {
|
|
9539
9579
|
const warmth = this.calculateWarmth(frontmatter.importance, frontmatter.lastAccessed);
|
|
@@ -9547,7 +9587,7 @@ ${content}
|
|
|
9547
9587
|
} else {
|
|
9548
9588
|
const relevance = this.calculateRelevance(content.slice(0, 500), lower);
|
|
9549
9589
|
try {
|
|
9550
|
-
const mtime = (0,
|
|
9590
|
+
const mtime = (0, import_fs7.statSync)(filePath).mtimeMs;
|
|
9551
9591
|
const ageDays = (Date.now() - mtime) / 864e5;
|
|
9552
9592
|
const ageFactor = 1 / (1 + ageDays / 30);
|
|
9553
9593
|
scored.push({ path: filePath, score: Math.max(relevance * ageFactor, 0.05) });
|
|
@@ -9602,7 +9642,7 @@ ${content}
|
|
|
9602
9642
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9603
9643
|
const fmEnd = content.indexOf("\n---", 4);
|
|
9604
9644
|
if (fmEnd < 0) {
|
|
9605
|
-
(0,
|
|
9645
|
+
(0, import_fs7.writeFileSync)(filePath, content);
|
|
9606
9646
|
return;
|
|
9607
9647
|
}
|
|
9608
9648
|
let frontmatter = content.slice(0, fmEnd);
|
|
@@ -9613,19 +9653,19 @@ ${content}
|
|
|
9613
9653
|
const newCount = parseInt(countMatch[1]) + 1;
|
|
9614
9654
|
frontmatter = frontmatter.replace(/accessCount:\s*\d+/, `accessCount: ${newCount}`);
|
|
9615
9655
|
}
|
|
9616
|
-
(0,
|
|
9656
|
+
(0, import_fs7.writeFileSync)(filePath, frontmatter + body);
|
|
9617
9657
|
}
|
|
9618
9658
|
};
|
|
9619
9659
|
}
|
|
9620
9660
|
});
|
|
9621
9661
|
|
|
9622
9662
|
// packages/orchestrator/src/memory-compactor.ts
|
|
9623
|
-
var
|
|
9663
|
+
var import_fs8, import_path9, MAX_ARCHIVE_LINES, MemoryCompactor;
|
|
9624
9664
|
var init_memory_compactor = __esm({
|
|
9625
9665
|
"packages/orchestrator/src/memory-compactor.ts"() {
|
|
9626
9666
|
"use strict";
|
|
9627
|
-
|
|
9628
|
-
|
|
9667
|
+
import_fs8 = require("fs");
|
|
9668
|
+
import_path9 = require("path");
|
|
9629
9669
|
MAX_ARCHIVE_LINES = 5e3;
|
|
9630
9670
|
MemoryCompactor = class {
|
|
9631
9671
|
constructor(projectRoot) {
|
|
@@ -9637,32 +9677,32 @@ var init_memory_compactor = __esm({
|
|
|
9637
9677
|
return (importance ?? 0.5) * (1 / (1 + days / 30));
|
|
9638
9678
|
}
|
|
9639
9679
|
compactIfNeeded(agentId, maxEntries = 20) {
|
|
9640
|
-
const memDir = (0,
|
|
9641
|
-
const tasksPath = (0,
|
|
9642
|
-
const lockPath = (0,
|
|
9643
|
-
if (!(0,
|
|
9644
|
-
if ((0,
|
|
9680
|
+
const memDir = (0, import_path9.join)(this.projectRoot, ".gossip", "agents", agentId, "memory");
|
|
9681
|
+
const tasksPath = (0, import_path9.join)(memDir, "tasks.jsonl");
|
|
9682
|
+
const lockPath = (0, import_path9.join)(memDir, "tasks.jsonl.lock");
|
|
9683
|
+
if (!(0, import_fs8.existsSync)(tasksPath)) return { archived: 0 };
|
|
9684
|
+
if ((0, import_fs8.existsSync)(lockPath)) {
|
|
9645
9685
|
try {
|
|
9646
|
-
const lockTs = parseInt((0,
|
|
9686
|
+
const lockTs = parseInt((0, import_fs8.readFileSync)(lockPath, "utf-8"), 10);
|
|
9647
9687
|
if (!Number.isNaN(lockTs) && Date.now() - lockTs < 6e4) return { archived: 0 };
|
|
9648
|
-
(0,
|
|
9688
|
+
(0, import_fs8.unlinkSync)(lockPath);
|
|
9649
9689
|
} catch {
|
|
9650
9690
|
try {
|
|
9651
|
-
(0,
|
|
9691
|
+
(0, import_fs8.unlinkSync)(lockPath);
|
|
9652
9692
|
} catch {
|
|
9653
9693
|
return { archived: 0 };
|
|
9654
9694
|
}
|
|
9655
9695
|
}
|
|
9656
9696
|
}
|
|
9657
9697
|
try {
|
|
9658
|
-
const fd = (0,
|
|
9659
|
-
(0,
|
|
9660
|
-
(0,
|
|
9698
|
+
const fd = (0, import_fs8.openSync)(lockPath, import_fs8.constants.O_WRONLY | import_fs8.constants.O_CREAT | import_fs8.constants.O_EXCL);
|
|
9699
|
+
(0, import_fs8.writeFileSync)(fd, `${Date.now()}`);
|
|
9700
|
+
(0, import_fs8.closeSync)(fd);
|
|
9661
9701
|
} catch {
|
|
9662
9702
|
return { archived: 0 };
|
|
9663
9703
|
}
|
|
9664
9704
|
try {
|
|
9665
|
-
const lines = (0,
|
|
9705
|
+
const lines = (0, import_fs8.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
9666
9706
|
if (lines.length <= maxEntries) return { archived: 0 };
|
|
9667
9707
|
const entries = [];
|
|
9668
9708
|
let dropped = 0;
|
|
@@ -9679,7 +9719,7 @@ var init_memory_compactor = __esm({
|
|
|
9679
9719
|
const toArchive = entries.slice(0, entries.length - maxEntries);
|
|
9680
9720
|
const toKeep = entries.slice(entries.length - maxEntries);
|
|
9681
9721
|
toKeep.sort((a, b) => a.idx - b.idx);
|
|
9682
|
-
const archivePath = (0,
|
|
9722
|
+
const archivePath = (0, import_path9.join)(memDir, "archive.jsonl");
|
|
9683
9723
|
for (const item of toArchive) {
|
|
9684
9724
|
const archived = {
|
|
9685
9725
|
archivedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9687,22 +9727,22 @@ var init_memory_compactor = __esm({
|
|
|
9687
9727
|
warmth: item.warmth,
|
|
9688
9728
|
entry: item.entry
|
|
9689
9729
|
};
|
|
9690
|
-
(0,
|
|
9730
|
+
(0, import_fs8.appendFileSync)(archivePath, JSON.stringify(archived) + "\n");
|
|
9691
9731
|
}
|
|
9692
9732
|
try {
|
|
9693
|
-
if ((0,
|
|
9694
|
-
const archiveLines = (0,
|
|
9733
|
+
if ((0, import_fs8.existsSync)(archivePath)) {
|
|
9734
|
+
const archiveLines = (0, import_fs8.readFileSync)(archivePath, "utf-8").trim().split("\n");
|
|
9695
9735
|
if (archiveLines.length > MAX_ARCHIVE_LINES) {
|
|
9696
|
-
(0,
|
|
9736
|
+
(0, import_fs8.writeFileSync)(archivePath, archiveLines.slice(-MAX_ARCHIVE_LINES).join("\n") + "\n");
|
|
9697
9737
|
}
|
|
9698
9738
|
}
|
|
9699
9739
|
} catch {
|
|
9700
9740
|
}
|
|
9701
|
-
(0,
|
|
9741
|
+
(0, import_fs8.writeFileSync)(tasksPath, toKeep.map((e) => e.line).join("\n") + "\n");
|
|
9702
9742
|
return { archived: toArchive.length, dropped: dropped || void 0, message: `Compacted ${toArchive.length} memories for ${agentId}${dropped ? ` (${dropped} malformed lines dropped)` : ""}` };
|
|
9703
9743
|
} finally {
|
|
9704
9744
|
try {
|
|
9705
|
-
(0,
|
|
9745
|
+
(0, import_fs8.unlinkSync)(lockPath);
|
|
9706
9746
|
} catch {
|
|
9707
9747
|
}
|
|
9708
9748
|
}
|
|
@@ -9721,11 +9761,11 @@ function sanitizeName(name) {
|
|
|
9721
9761
|
function discoverProjectStructure(projectRoot) {
|
|
9722
9762
|
try {
|
|
9723
9763
|
const parts = [];
|
|
9724
|
-
const entries = (0,
|
|
9764
|
+
const entries = (0, import_fs9.readdirSync)(projectRoot, { withFileTypes: true });
|
|
9725
9765
|
for (const entry of entries) {
|
|
9726
9766
|
if (!entry.isDirectory() || isSkipped(entry.name)) continue;
|
|
9727
9767
|
try {
|
|
9728
|
-
const allChildren = (0,
|
|
9768
|
+
const allChildren = (0, import_fs9.readdirSync)((0, import_path10.join)(projectRoot, entry.name)).filter((f) => !f.startsWith("."));
|
|
9729
9769
|
if (allChildren.length === 0) continue;
|
|
9730
9770
|
const shown = allChildren.slice(0, MAX_CHILDREN).map(sanitizeName);
|
|
9731
9771
|
const suffix = allChildren.length > MAX_CHILDREN ? `, ...${allChildren.length - MAX_CHILDREN} more` : "";
|
|
@@ -9738,12 +9778,12 @@ function discoverProjectStructure(projectRoot) {
|
|
|
9738
9778
|
return [];
|
|
9739
9779
|
}
|
|
9740
9780
|
}
|
|
9741
|
-
var
|
|
9781
|
+
var import_fs9, import_path10, SKIP, MAX_CHILDREN;
|
|
9742
9782
|
var init_project_structure = __esm({
|
|
9743
9783
|
"packages/orchestrator/src/project-structure.ts"() {
|
|
9744
9784
|
"use strict";
|
|
9745
|
-
|
|
9746
|
-
|
|
9785
|
+
import_fs9 = require("fs");
|
|
9786
|
+
import_path10 = require("path");
|
|
9747
9787
|
SKIP = /* @__PURE__ */ new Set([
|
|
9748
9788
|
"node_modules",
|
|
9749
9789
|
"build",
|
|
@@ -9784,12 +9824,12 @@ function truncateStartAndEnd(text, maxLen) {
|
|
|
9784
9824
|
|
|
9785
9825
|
${text.slice(-tail)}`;
|
|
9786
9826
|
}
|
|
9787
|
-
var
|
|
9827
|
+
var import_fs10, import_path11, MemoryWriter;
|
|
9788
9828
|
var init_memory_writer = __esm({
|
|
9789
9829
|
"packages/orchestrator/src/memory-writer.ts"() {
|
|
9790
9830
|
"use strict";
|
|
9791
|
-
|
|
9792
|
-
|
|
9831
|
+
import_fs10 = require("fs");
|
|
9832
|
+
import_path11 = require("path");
|
|
9793
9833
|
init_memory_compactor();
|
|
9794
9834
|
init_project_structure();
|
|
9795
9835
|
MemoryWriter = class {
|
|
@@ -9802,12 +9842,12 @@ var init_memory_writer = __esm({
|
|
|
9802
9842
|
this.summaryLlm = llm;
|
|
9803
9843
|
}
|
|
9804
9844
|
getMemDir(agentId) {
|
|
9805
|
-
return (0,
|
|
9845
|
+
return (0, import_path11.join)(this.projectRoot, ".gossip", "agents", agentId, "memory");
|
|
9806
9846
|
}
|
|
9807
9847
|
ensureDirs(agentId) {
|
|
9808
9848
|
const memDir = this.getMemDir(agentId);
|
|
9809
|
-
(0,
|
|
9810
|
-
(0,
|
|
9849
|
+
(0, import_fs10.mkdirSync)((0, import_path11.join)(memDir, "knowledge"), { recursive: true });
|
|
9850
|
+
(0, import_fs10.mkdirSync)((0, import_path11.join)(memDir, "calibration"), { recursive: true });
|
|
9811
9851
|
return memDir;
|
|
9812
9852
|
}
|
|
9813
9853
|
async writeTaskEntry(agentId, data) {
|
|
@@ -9825,7 +9865,7 @@ var init_memory_writer = __esm({
|
|
|
9825
9865
|
importance: this.deriveImportance(data.scores),
|
|
9826
9866
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
9827
9867
|
};
|
|
9828
|
-
(0,
|
|
9868
|
+
(0, import_fs10.appendFileSync)((0, import_path11.join)(memDir, "tasks.jsonl"), JSON.stringify(entry) + "\n");
|
|
9829
9869
|
}
|
|
9830
9870
|
/**
|
|
9831
9871
|
* Extract key facts from a task result and write as a knowledge entry.
|
|
@@ -9834,7 +9874,7 @@ var init_memory_writer = __esm({
|
|
|
9834
9874
|
*/
|
|
9835
9875
|
async writeKnowledgeFromResult(agentId, data) {
|
|
9836
9876
|
const memDir = this.ensureDirs(agentId);
|
|
9837
|
-
const knowledgeDir = (0,
|
|
9877
|
+
const knowledgeDir = (0, import_path11.join)(memDir, "knowledge");
|
|
9838
9878
|
const safeResult = data.result.length > 5e4 ? data.result.slice(0, 5e4) : data.result;
|
|
9839
9879
|
let cognitiveSummary = null;
|
|
9840
9880
|
if (this.summaryLlm) {
|
|
@@ -9884,7 +9924,7 @@ ${cleanSummary}` : cleanSummary;
|
|
|
9884
9924
|
...data.agentAccuracy !== void 0 && data.agentAccuracy < 0.4 ? ["> \u26A0 This agent has low accuracy (" + (data.agentAccuracy * 100).toFixed(0) + "%). Treat factual claims as unverified.\n"] : [],
|
|
9885
9925
|
body
|
|
9886
9926
|
].join("\n");
|
|
9887
|
-
(0,
|
|
9927
|
+
(0, import_fs10.writeFileSync)((0, import_path11.join)(knowledgeDir, filename), content);
|
|
9888
9928
|
}
|
|
9889
9929
|
/**
|
|
9890
9930
|
* Generate a cognitive summary — what the agent learned, not just what it saw.
|
|
@@ -9925,7 +9965,7 @@ ${truncateStartAndEnd(result, 4e3)}`
|
|
|
9925
9965
|
/** Session summary data shared across public methods */
|
|
9926
9966
|
sessionSummaryData(data) {
|
|
9927
9967
|
const memDir = this.ensureDirs("_project");
|
|
9928
|
-
const knowledgeDir = (0,
|
|
9968
|
+
const knowledgeDir = (0, import_path11.join)(memDir, "knowledge");
|
|
9929
9969
|
const now = /* @__PURE__ */ new Date();
|
|
9930
9970
|
const timestamp = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
9931
9971
|
const today = now.toISOString().split("T")[0];
|
|
@@ -9948,9 +9988,9 @@ ${discovered.join("\n")}
|
|
|
9948
9988
|
let existingMemoriesContext = "";
|
|
9949
9989
|
const existingFiles = [];
|
|
9950
9990
|
try {
|
|
9951
|
-
const files = (0,
|
|
9991
|
+
const files = (0, import_fs10.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md") && !f.endsWith("-session.md"));
|
|
9952
9992
|
for (const f of files) {
|
|
9953
|
-
const content = (0,
|
|
9993
|
+
const content = (0, import_fs10.readFileSync)((0, import_path11.join)(knowledgeDir, f), "utf-8");
|
|
9954
9994
|
const descMatch = content.match(/description:\s*(.+)/);
|
|
9955
9995
|
const desc = descMatch ? descMatch[1].trim() : "(no description)";
|
|
9956
9996
|
existingFiles.push(f);
|
|
@@ -10060,10 +10100,18 @@ ${rawInput.slice(0, SESSION_SUMMARY_MAX_CHARS)}`;
|
|
|
10060
10100
|
summaryBody = raw;
|
|
10061
10101
|
} else {
|
|
10062
10102
|
rawLlmResponse = raw;
|
|
10063
|
-
const hasSummaryLine = /^SUMMARY:\s*.+/m.test(raw);
|
|
10064
10103
|
const hasSectionHeader = /^##\s+\w/m.test(raw);
|
|
10065
|
-
if (!
|
|
10104
|
+
if (!hasSectionHeader) {
|
|
10066
10105
|
process.stderr.write("[gossipcat] Session summary missing required structure, using raw fallback\n");
|
|
10106
|
+
try {
|
|
10107
|
+
const debugPath = (0, import_path11.join)(memDir, "last-malformed-summary.txt");
|
|
10108
|
+
(0, import_fs10.writeFileSync)(debugPath, `# Malformed session summary @ ${timestamp}
|
|
10109
|
+
# No ## header found in LLM output.
|
|
10110
|
+
|
|
10111
|
+
---
|
|
10112
|
+
${raw}`);
|
|
10113
|
+
} catch {
|
|
10114
|
+
}
|
|
10067
10115
|
summaryBody = `> \u26A0\uFE0F LLM summary malformed \u2014 raw data below.
|
|
10068
10116
|
|
|
10069
10117
|
${rawInput.slice(0, SESSION_SUMMARY_MAX_CHARS)}`;
|
|
@@ -10105,15 +10153,15 @@ ${rawInput.slice(0, SESSION_SUMMARY_MAX_CHARS)}`;
|
|
|
10105
10153
|
if (staleFiles.length > 0) {
|
|
10106
10154
|
for (const sf of staleFiles) {
|
|
10107
10155
|
try {
|
|
10108
|
-
const filePath = (0,
|
|
10109
|
-
let fileContent = (0,
|
|
10156
|
+
const filePath = (0, import_path11.join)(knowledgeDir, sf);
|
|
10157
|
+
let fileContent = (0, import_fs10.readFileSync)(filePath, "utf-8");
|
|
10110
10158
|
fileContent = fileContent.replace(/importance:\s*[\d.]+/, "importance: 0.1");
|
|
10111
10159
|
if (!/status:/.test(fileContent)) {
|
|
10112
10160
|
fileContent = fileContent.replace(/\n---/, "\nstatus: shipped\n---");
|
|
10113
10161
|
} else {
|
|
10114
10162
|
fileContent = fileContent.replace(/status:\s*.+/, "status: shipped");
|
|
10115
10163
|
}
|
|
10116
|
-
(0,
|
|
10164
|
+
(0, import_fs10.writeFileSync)(filePath, fileContent);
|
|
10117
10165
|
process.stderr.write(`[gossipcat] \u{1F5DC}\uFE0F Marked stale: ${sf}
|
|
10118
10166
|
`);
|
|
10119
10167
|
} catch {
|
|
@@ -10134,8 +10182,8 @@ ${rawInput.slice(0, SESSION_SUMMARY_MAX_CHARS)}`;
|
|
|
10134
10182
|
"",
|
|
10135
10183
|
summaryBody
|
|
10136
10184
|
].filter((l) => l !== "").join("\n");
|
|
10137
|
-
(0,
|
|
10138
|
-
const nextSessionPath = (0,
|
|
10185
|
+
(0, import_fs10.writeFileSync)((0, import_path11.join)(knowledgeDir, filename), content);
|
|
10186
|
+
const nextSessionPath = (0, import_path11.join)(this.projectRoot, ".gossip", "next-session.md");
|
|
10139
10187
|
const openMatch = summaryBody.match(/##\s+Open[^\n]*\n([\s\S]*?)(?=\n##|\s*$)/i);
|
|
10140
10188
|
const NEXT_SESSION_MAX_CHARS = 1500;
|
|
10141
10189
|
const nextSessionContent = openMatch ? `# Next Session
|
|
@@ -10145,11 +10193,11 @@ ${openMatch[0].trim()}
|
|
|
10145
10193
|
|
|
10146
10194
|
${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
10147
10195
|
`;
|
|
10148
|
-
(0,
|
|
10149
|
-
const migrationTasksPath = (0,
|
|
10150
|
-
if ((0,
|
|
10196
|
+
(0, import_fs10.writeFileSync)(nextSessionPath, nextSessionContent);
|
|
10197
|
+
const migrationTasksPath = (0, import_path11.join)(memDir, "tasks.jsonl");
|
|
10198
|
+
if ((0, import_fs10.existsSync)(migrationTasksPath)) {
|
|
10151
10199
|
try {
|
|
10152
|
-
const mLines = (0,
|
|
10200
|
+
const mLines = (0, import_fs10.readFileSync)(migrationTasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
10153
10201
|
let migrated = false;
|
|
10154
10202
|
const fixed = mLines.map((line) => {
|
|
10155
10203
|
try {
|
|
@@ -10163,7 +10211,7 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10163
10211
|
return line;
|
|
10164
10212
|
}
|
|
10165
10213
|
});
|
|
10166
|
-
if (migrated) (0,
|
|
10214
|
+
if (migrated) (0, import_fs10.writeFileSync)(migrationTasksPath, fixed.join("\n") + "\n");
|
|
10167
10215
|
} catch {
|
|
10168
10216
|
}
|
|
10169
10217
|
}
|
|
@@ -10188,10 +10236,10 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10188
10236
|
/** Shared warmth-aware pruning — evicts lowest-warmth files, respects pinned */
|
|
10189
10237
|
pruneKnowledgeDir(knowledgeDir, maxFiles) {
|
|
10190
10238
|
try {
|
|
10191
|
-
const existing = (0,
|
|
10239
|
+
const existing = (0, import_fs10.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md") && !f.endsWith("-session.md")).sort();
|
|
10192
10240
|
if (existing.length >= maxFiles) {
|
|
10193
10241
|
const scored = existing.map((f) => {
|
|
10194
|
-
const content = (0,
|
|
10242
|
+
const content = (0, import_fs10.readFileSync)((0, import_path11.join)(knowledgeDir, f), "utf-8");
|
|
10195
10243
|
const importance = parseFloat(content.match(/importance:\s*([\d.]+)/)?.[1] ?? "0.5");
|
|
10196
10244
|
const isPinned = /pinned:\s*true/i.test(content);
|
|
10197
10245
|
const ts = f.slice(0, 19).replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/, "$1T$2:$3:$4");
|
|
@@ -10210,10 +10258,10 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10210
10258
|
);
|
|
10211
10259
|
}
|
|
10212
10260
|
for (const item of toEvict) {
|
|
10213
|
-
(0,
|
|
10261
|
+
(0, import_fs10.unlinkSync)((0, import_path11.join)(knowledgeDir, item.file));
|
|
10214
10262
|
}
|
|
10215
10263
|
}
|
|
10216
|
-
const sessionFiles = (0,
|
|
10264
|
+
const sessionFiles = (0, import_fs10.readdirSync)(knowledgeDir).filter((f) => f.endsWith("-session.md")).sort();
|
|
10217
10265
|
const MAX_SESSION_FILES = 5;
|
|
10218
10266
|
const SESSION_TTL_DAYS = 14;
|
|
10219
10267
|
for (const sf of sessionFiles) {
|
|
@@ -10221,10 +10269,10 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10221
10269
|
const ts = sf.slice(0, 19).replace(/^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})/, "$1T$2:$3:$4");
|
|
10222
10270
|
const days = (Date.now() - new Date(ts).getTime()) / 864e5;
|
|
10223
10271
|
if (days > SESSION_TTL_DAYS) {
|
|
10224
|
-
const sfPath = (0,
|
|
10225
|
-
const sfContent = (0,
|
|
10272
|
+
const sfPath = (0, import_path11.join)(knowledgeDir, sf);
|
|
10273
|
+
const sfContent = (0, import_fs10.readFileSync)(sfPath, "utf-8");
|
|
10226
10274
|
if (!/importance:\s*0\.1/.test(sfContent)) {
|
|
10227
|
-
(0,
|
|
10275
|
+
(0, import_fs10.writeFileSync)(sfPath, sfContent.replace(/importance:\s*[\d.]+/, "importance: 0.1"));
|
|
10228
10276
|
}
|
|
10229
10277
|
}
|
|
10230
10278
|
} catch {
|
|
@@ -10235,7 +10283,7 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10235
10283
|
const bodies = [];
|
|
10236
10284
|
for (const sf of toCompact) {
|
|
10237
10285
|
try {
|
|
10238
|
-
const sfContent = (0,
|
|
10286
|
+
const sfContent = (0, import_fs10.readFileSync)((0, import_path11.join)(knowledgeDir, sf), "utf-8");
|
|
10239
10287
|
const body = sfContent.split("---").slice(2).join("---").trim();
|
|
10240
10288
|
if (body) bodies.push(body.slice(0, 800));
|
|
10241
10289
|
} catch {
|
|
@@ -10255,10 +10303,10 @@ ${truncateAtWord(summaryBody, NEXT_SESSION_MAX_CHARS)}
|
|
|
10255
10303
|
"",
|
|
10256
10304
|
...bodies
|
|
10257
10305
|
].join("\n").slice(0, 3e3);
|
|
10258
|
-
(0,
|
|
10306
|
+
(0, import_fs10.writeFileSync)((0, import_path11.join)(knowledgeDir, digestName), digestContent);
|
|
10259
10307
|
for (const sf of toCompact) {
|
|
10260
10308
|
try {
|
|
10261
|
-
(0,
|
|
10309
|
+
(0, import_fs10.unlinkSync)((0, import_path11.join)(knowledgeDir, sf));
|
|
10262
10310
|
} catch {
|
|
10263
10311
|
}
|
|
10264
10312
|
}
|
|
@@ -10441,7 +10489,7 @@ ${result}`;
|
|
|
10441
10489
|
writeConsensusKnowledge(agentId, findings) {
|
|
10442
10490
|
if (findings.length === 0) return;
|
|
10443
10491
|
const memDir = this.ensureDirs(agentId);
|
|
10444
|
-
const knowledgeDir = (0,
|
|
10492
|
+
const knowledgeDir = (0, import_path11.join)(memDir, "knowledge");
|
|
10445
10493
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
10446
10494
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
10447
10495
|
const filename = `${timestamp}-consensus.md`;
|
|
@@ -10471,7 +10519,7 @@ ${result}`;
|
|
|
10471
10519
|
})
|
|
10472
10520
|
].join("\n");
|
|
10473
10521
|
this.pruneKnowledgeDir(knowledgeDir, 25);
|
|
10474
|
-
(0,
|
|
10522
|
+
(0, import_fs10.writeFileSync)((0, import_path11.join)(knowledgeDir, filename), content);
|
|
10475
10523
|
}
|
|
10476
10524
|
/**
|
|
10477
10525
|
* Update task memory importance based on consensus signals.
|
|
@@ -10494,14 +10542,14 @@ ${result}`;
|
|
|
10494
10542
|
taskAdj.set(s.taskId, (taskAdj.get(s.taskId) ?? 0) + weight);
|
|
10495
10543
|
}
|
|
10496
10544
|
for (const [agentId, taskAdjustments] of adjustments) {
|
|
10497
|
-
const memDir = (0,
|
|
10498
|
-
const tasksPath = (0,
|
|
10499
|
-
const lockPath = (0,
|
|
10500
|
-
if (!(0,
|
|
10501
|
-
if ((0,
|
|
10545
|
+
const memDir = (0, import_path11.join)(this.projectRoot, ".gossip", "agents", agentId, "memory");
|
|
10546
|
+
const tasksPath = (0, import_path11.join)(memDir, "tasks.jsonl");
|
|
10547
|
+
const lockPath = (0, import_path11.join)(memDir, "tasks.jsonl.lock");
|
|
10548
|
+
if (!(0, import_fs10.existsSync)(tasksPath)) continue;
|
|
10549
|
+
if ((0, import_fs10.existsSync)(lockPath)) continue;
|
|
10502
10550
|
try {
|
|
10503
|
-
(0,
|
|
10504
|
-
const lines = (0,
|
|
10551
|
+
(0, import_fs10.writeFileSync)(lockPath, `${Date.now()}`);
|
|
10552
|
+
const lines = (0, import_fs10.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
10505
10553
|
let modified = false;
|
|
10506
10554
|
const updated = lines.map((line) => {
|
|
10507
10555
|
try {
|
|
@@ -10518,12 +10566,12 @@ ${result}`;
|
|
|
10518
10566
|
}
|
|
10519
10567
|
});
|
|
10520
10568
|
if (modified) {
|
|
10521
|
-
(0,
|
|
10569
|
+
(0, import_fs10.writeFileSync)(tasksPath, updated.join("\n") + "\n");
|
|
10522
10570
|
}
|
|
10523
10571
|
} catch {
|
|
10524
10572
|
} finally {
|
|
10525
10573
|
try {
|
|
10526
|
-
(0,
|
|
10574
|
+
(0, import_fs10.unlinkSync)(lockPath);
|
|
10527
10575
|
} catch {
|
|
10528
10576
|
}
|
|
10529
10577
|
}
|
|
@@ -10533,13 +10581,13 @@ ${result}`;
|
|
|
10533
10581
|
const memDir = this.getMemDir(agentId);
|
|
10534
10582
|
const parts = [`# Agent Memory \u2014 ${agentId}
|
|
10535
10583
|
`];
|
|
10536
|
-
const knowledgeDir = (0,
|
|
10537
|
-
if ((0,
|
|
10538
|
-
const files = (0,
|
|
10584
|
+
const knowledgeDir = (0, import_path11.join)(memDir, "knowledge");
|
|
10585
|
+
if ((0, import_fs10.existsSync)(knowledgeDir)) {
|
|
10586
|
+
const files = (0, import_fs10.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md")).sort().reverse();
|
|
10539
10587
|
if (files.length > 0) {
|
|
10540
10588
|
parts.push("## Knowledge (most recent first)");
|
|
10541
10589
|
for (const file2 of files) {
|
|
10542
|
-
const content = (0,
|
|
10590
|
+
const content = (0, import_fs10.readFileSync)((0, import_path11.join)(knowledgeDir, file2), "utf-8");
|
|
10543
10591
|
const descMatch = content.match(/description:\s*(.+)/);
|
|
10544
10592
|
const desc = descMatch ? descMatch[1].trim() : file2.replace(".md", "");
|
|
10545
10593
|
parts.push(`- [${file2.replace(".md", "")}](knowledge/${file2}) \u2014 ${desc}`);
|
|
@@ -10547,17 +10595,17 @@ ${result}`;
|
|
|
10547
10595
|
parts.push("");
|
|
10548
10596
|
}
|
|
10549
10597
|
}
|
|
10550
|
-
const calPath = (0,
|
|
10551
|
-
if ((0,
|
|
10552
|
-
const content = (0,
|
|
10598
|
+
const calPath = (0, import_path11.join)(memDir, "calibration", "accuracy.md");
|
|
10599
|
+
if ((0, import_fs10.existsSync)(calPath)) {
|
|
10600
|
+
const content = (0, import_fs10.readFileSync)(calPath, "utf-8");
|
|
10553
10601
|
const descMatch = content.match(/description:\s*(.+)/);
|
|
10554
10602
|
parts.push("## Calibration");
|
|
10555
10603
|
parts.push(`- [accuracy](calibration/accuracy.md) \u2014 ${descMatch ? descMatch[1].trim() : "accuracy data"}`);
|
|
10556
10604
|
parts.push("");
|
|
10557
10605
|
}
|
|
10558
|
-
const tasksPath = (0,
|
|
10559
|
-
if ((0,
|
|
10560
|
-
const lines = (0,
|
|
10606
|
+
const tasksPath = (0, import_path11.join)(memDir, "tasks.jsonl");
|
|
10607
|
+
if ((0, import_fs10.existsSync)(tasksPath)) {
|
|
10608
|
+
const lines = (0, import_fs10.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
10561
10609
|
const recent = lines.slice(-5).reverse();
|
|
10562
10610
|
if (recent.length > 0) {
|
|
10563
10611
|
parts.push("## Recent Tasks");
|
|
@@ -10574,12 +10622,12 @@ ${result}`;
|
|
|
10574
10622
|
}
|
|
10575
10623
|
}
|
|
10576
10624
|
try {
|
|
10577
|
-
const knowledgeDir2 = (0,
|
|
10578
|
-
if ((0,
|
|
10579
|
-
const knowledgeFiles = (0,
|
|
10625
|
+
const knowledgeDir2 = (0, import_path11.join)(memDir, "knowledge");
|
|
10626
|
+
if ((0, import_fs10.existsSync)(knowledgeDir2)) {
|
|
10627
|
+
const knowledgeFiles = (0, import_fs10.readdirSync)(knowledgeDir2).filter((f) => f.endsWith(".md")).sort().reverse().slice(0, 5);
|
|
10580
10628
|
const patterns = [];
|
|
10581
10629
|
for (const kf of knowledgeFiles) {
|
|
10582
|
-
const kContent = (0,
|
|
10630
|
+
const kContent = (0, import_fs10.readFileSync)((0, import_path11.join)(knowledgeDir2, kf), "utf-8");
|
|
10583
10631
|
const decisionsMatch = kContent.match(/Decisions: (.+)/);
|
|
10584
10632
|
if (decisionsMatch) patterns.push(decisionsMatch[1].trim());
|
|
10585
10633
|
const failuresMatch = kContent.match(/Failures: (.+)/);
|
|
@@ -10591,19 +10639,19 @@ ${result}`;
|
|
|
10591
10639
|
}
|
|
10592
10640
|
} catch {
|
|
10593
10641
|
}
|
|
10594
|
-
(0,
|
|
10642
|
+
(0, import_fs10.writeFileSync)((0, import_path11.join)(memDir, "MEMORY.md"), parts.join("\n"));
|
|
10595
10643
|
}
|
|
10596
10644
|
};
|
|
10597
10645
|
}
|
|
10598
10646
|
});
|
|
10599
10647
|
|
|
10600
10648
|
// packages/orchestrator/src/task-graph.ts
|
|
10601
|
-
var
|
|
10649
|
+
var import_fs11, import_path12, MAX_SCAN_LINES, TaskGraph;
|
|
10602
10650
|
var init_task_graph = __esm({
|
|
10603
10651
|
"packages/orchestrator/src/task-graph.ts"() {
|
|
10604
10652
|
"use strict";
|
|
10605
|
-
|
|
10606
|
-
|
|
10653
|
+
import_fs11 = require("fs");
|
|
10654
|
+
import_path12 = require("path");
|
|
10607
10655
|
MAX_SCAN_LINES = 1e3;
|
|
10608
10656
|
TaskGraph = class {
|
|
10609
10657
|
graphPath;
|
|
@@ -10613,14 +10661,14 @@ var init_task_graph = __esm({
|
|
|
10613
10661
|
// taskId → last event line number
|
|
10614
10662
|
eventCount = 0;
|
|
10615
10663
|
constructor(projectRoot) {
|
|
10616
|
-
const gossipDir2 = (0,
|
|
10617
|
-
(0,
|
|
10618
|
-
this.graphPath = (0,
|
|
10619
|
-
this.syncMetaPath = (0,
|
|
10620
|
-
this.indexPath = (0,
|
|
10664
|
+
const gossipDir2 = (0, import_path12.join)(projectRoot, ".gossip");
|
|
10665
|
+
(0, import_fs11.mkdirSync)(gossipDir2, { recursive: true });
|
|
10666
|
+
this.graphPath = (0, import_path12.join)(gossipDir2, "task-graph.jsonl");
|
|
10667
|
+
this.syncMetaPath = (0, import_path12.join)(gossipDir2, "task-graph-sync.json");
|
|
10668
|
+
this.indexPath = (0, import_path12.join)(gossipDir2, "task-graph-index.json");
|
|
10621
10669
|
this.loadIndex();
|
|
10622
|
-
if ((0,
|
|
10623
|
-
const buf = (0,
|
|
10670
|
+
if ((0, import_fs11.existsSync)(this.graphPath)) {
|
|
10671
|
+
const buf = (0, import_fs11.readFileSync)(this.graphPath);
|
|
10624
10672
|
let count = 0;
|
|
10625
10673
|
for (let i = 0; i < buf.length; i++) {
|
|
10626
10674
|
if (buf[i] === 10) count++;
|
|
@@ -10629,9 +10677,9 @@ var init_task_graph = __esm({
|
|
|
10629
10677
|
}
|
|
10630
10678
|
}
|
|
10631
10679
|
loadIndex() {
|
|
10632
|
-
if ((0,
|
|
10680
|
+
if ((0, import_fs11.existsSync)(this.indexPath)) {
|
|
10633
10681
|
try {
|
|
10634
|
-
const data = JSON.parse((0,
|
|
10682
|
+
const data = JSON.parse((0, import_fs11.readFileSync)(this.indexPath, "utf-8"));
|
|
10635
10683
|
this.index = new Map(Object.entries(data).map(([k, v]) => [k, Number(v)]));
|
|
10636
10684
|
} catch {
|
|
10637
10685
|
}
|
|
@@ -10639,10 +10687,10 @@ var init_task_graph = __esm({
|
|
|
10639
10687
|
}
|
|
10640
10688
|
/** Save index to disk (call explicitly, not on every append) */
|
|
10641
10689
|
flushIndex() {
|
|
10642
|
-
(0,
|
|
10690
|
+
(0, import_fs11.writeFileSync)(this.indexPath, JSON.stringify(Object.fromEntries(this.index)));
|
|
10643
10691
|
}
|
|
10644
10692
|
appendEvent(event) {
|
|
10645
|
-
(0,
|
|
10693
|
+
(0, import_fs11.appendFileSync)(this.graphPath, JSON.stringify(event) + "\n");
|
|
10646
10694
|
if ("taskId" in event) {
|
|
10647
10695
|
this.index.set(event.taskId, this.eventCount);
|
|
10648
10696
|
}
|
|
@@ -10724,8 +10772,8 @@ var init_task_graph = __esm({
|
|
|
10724
10772
|
}
|
|
10725
10773
|
// ── Read methods ─────────────────────────────────────────────────────
|
|
10726
10774
|
readEvents() {
|
|
10727
|
-
if (!(0,
|
|
10728
|
-
const content = (0,
|
|
10775
|
+
if (!(0, import_fs11.existsSync)(this.graphPath)) return [];
|
|
10776
|
+
const content = (0, import_fs11.readFileSync)(this.graphPath, "utf-8");
|
|
10729
10777
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
10730
10778
|
const tail = lines.slice(-MAX_SCAN_LINES);
|
|
10731
10779
|
return tail.map((line) => {
|
|
@@ -10807,14 +10855,14 @@ var init_task_graph = __esm({
|
|
|
10807
10855
|
return this.eventCount;
|
|
10808
10856
|
}
|
|
10809
10857
|
getSyncMeta() {
|
|
10810
|
-
if (!(0,
|
|
10858
|
+
if (!(0, import_fs11.existsSync)(this.syncMetaPath)) {
|
|
10811
10859
|
return { lastSync: "", lastSyncEventCount: 0 };
|
|
10812
10860
|
}
|
|
10813
|
-
return JSON.parse((0,
|
|
10861
|
+
return JSON.parse((0, import_fs11.readFileSync)(this.syncMetaPath, "utf-8"));
|
|
10814
10862
|
}
|
|
10815
10863
|
updateSyncMeta(meta3) {
|
|
10816
10864
|
const current = this.getSyncMeta();
|
|
10817
|
-
(0,
|
|
10865
|
+
(0, import_fs11.writeFileSync)(this.syncMetaPath, JSON.stringify({ ...current, ...meta3 }, null, 2));
|
|
10818
10866
|
}
|
|
10819
10867
|
getUnsynced(lastSyncTimestamp) {
|
|
10820
10868
|
if (!lastSyncTimestamp) return this.readEvents();
|
|
@@ -10825,12 +10873,12 @@ var init_task_graph = __esm({
|
|
|
10825
10873
|
});
|
|
10826
10874
|
|
|
10827
10875
|
// packages/orchestrator/src/skill-catalog.ts
|
|
10828
|
-
var
|
|
10876
|
+
var import_fs12, import_path13, SkillCatalog;
|
|
10829
10877
|
var init_skill_catalog = __esm({
|
|
10830
10878
|
"packages/orchestrator/src/skill-catalog.ts"() {
|
|
10831
10879
|
"use strict";
|
|
10832
|
-
|
|
10833
|
-
|
|
10880
|
+
import_fs12 = require("fs");
|
|
10881
|
+
import_path13 = require("path");
|
|
10834
10882
|
init_skill_name();
|
|
10835
10883
|
init_skill_parser();
|
|
10836
10884
|
SkillCatalog = class {
|
|
@@ -10839,11 +10887,11 @@ var init_skill_catalog = __esm({
|
|
|
10839
10887
|
projectSkillsDir;
|
|
10840
10888
|
projectFileMtimes = /* @__PURE__ */ new Map();
|
|
10841
10889
|
constructor(projectRoot, catalogPath) {
|
|
10842
|
-
const defaultPath = catalogPath || (0,
|
|
10843
|
-
this.defaultSkillsDir = (0,
|
|
10844
|
-
this.projectSkillsDir = projectRoot ? (0,
|
|
10890
|
+
const defaultPath = catalogPath || (0, import_path13.resolve)(__dirname, "default-skills", "catalog.json");
|
|
10891
|
+
this.defaultSkillsDir = (0, import_path13.resolve)(__dirname, "default-skills");
|
|
10892
|
+
this.projectSkillsDir = projectRoot ? (0, import_path13.join)(projectRoot, ".gossip", "skills") : null;
|
|
10845
10893
|
try {
|
|
10846
|
-
const raw = (0,
|
|
10894
|
+
const raw = (0, import_fs12.readFileSync)(defaultPath, "utf-8");
|
|
10847
10895
|
const data = JSON.parse(raw);
|
|
10848
10896
|
this.entries = data.skills.map((s) => ({
|
|
10849
10897
|
...s,
|
|
@@ -10884,7 +10932,7 @@ var init_skill_catalog = __esm({
|
|
|
10884
10932
|
}
|
|
10885
10933
|
validate() {
|
|
10886
10934
|
const issues = [];
|
|
10887
|
-
const mdFiles = (0,
|
|
10935
|
+
const mdFiles = (0, import_fs12.readdirSync)(this.defaultSkillsDir).filter((f) => f.endsWith(".md")).map((f) => normalizeSkillName(f.replace(".md", "")));
|
|
10888
10936
|
for (const file2 of mdFiles) {
|
|
10889
10937
|
if (!this.entries.find((e) => e.name === file2)) {
|
|
10890
10938
|
issues.push(`Skill file '${file2}' has no catalog entry`);
|
|
@@ -10893,15 +10941,15 @@ var init_skill_catalog = __esm({
|
|
|
10893
10941
|
return issues;
|
|
10894
10942
|
}
|
|
10895
10943
|
loadProjectSkills() {
|
|
10896
|
-
if (!this.projectSkillsDir || !(0,
|
|
10897
|
-
const files = (0,
|
|
10944
|
+
if (!this.projectSkillsDir || !(0, import_fs12.existsSync)(this.projectSkillsDir)) return;
|
|
10945
|
+
const files = (0, import_fs12.readdirSync)(this.projectSkillsDir).filter((f) => f.endsWith(".md"));
|
|
10898
10946
|
const newMtimes = /* @__PURE__ */ new Map();
|
|
10899
10947
|
for (const file2 of files) {
|
|
10900
|
-
const filePath = (0,
|
|
10948
|
+
const filePath = (0, import_path13.join)(this.projectSkillsDir, file2);
|
|
10901
10949
|
try {
|
|
10902
|
-
const mtime = (0,
|
|
10950
|
+
const mtime = (0, import_fs12.statSync)(filePath).mtimeMs;
|
|
10903
10951
|
newMtimes.set(file2, mtime);
|
|
10904
|
-
const content = (0,
|
|
10952
|
+
const content = (0, import_fs12.readFileSync)(filePath, "utf-8");
|
|
10905
10953
|
const fm = parseSkillFrontmatter(content);
|
|
10906
10954
|
if (!fm) continue;
|
|
10907
10955
|
const entry = {
|
|
@@ -10923,14 +10971,14 @@ var init_skill_catalog = __esm({
|
|
|
10923
10971
|
this.projectFileMtimes = newMtimes;
|
|
10924
10972
|
}
|
|
10925
10973
|
reloadIfChanged() {
|
|
10926
|
-
if (!this.projectSkillsDir || !(0,
|
|
10927
|
-
const files = (0,
|
|
10974
|
+
if (!this.projectSkillsDir || !(0, import_fs12.existsSync)(this.projectSkillsDir)) return;
|
|
10975
|
+
const files = (0, import_fs12.readdirSync)(this.projectSkillsDir).filter((f) => f.endsWith(".md"));
|
|
10928
10976
|
let changed = files.length !== this.projectFileMtimes.size;
|
|
10929
10977
|
if (!changed) {
|
|
10930
10978
|
for (const file2 of files) {
|
|
10931
|
-
const filePath = (0,
|
|
10979
|
+
const filePath = (0, import_path13.join)(this.projectSkillsDir, file2);
|
|
10932
10980
|
try {
|
|
10933
|
-
const mtime = (0,
|
|
10981
|
+
const mtime = (0, import_fs12.statSync)(filePath).mtimeMs;
|
|
10934
10982
|
if (mtime !== this.projectFileMtimes.get(file2)) {
|
|
10935
10983
|
changed = true;
|
|
10936
10984
|
break;
|
|
@@ -10951,12 +10999,12 @@ var init_skill_catalog = __esm({
|
|
|
10951
10999
|
});
|
|
10952
11000
|
|
|
10953
11001
|
// packages/orchestrator/src/skill-gap-tracker.ts
|
|
10954
|
-
var
|
|
11002
|
+
var import_fs13, import_path14, MAX_LOG_LINES, TRUNCATE_TO, SkillGapTracker;
|
|
10955
11003
|
var init_skill_gap_tracker = __esm({
|
|
10956
11004
|
"packages/orchestrator/src/skill-gap-tracker.ts"() {
|
|
10957
11005
|
"use strict";
|
|
10958
|
-
|
|
10959
|
-
|
|
11006
|
+
import_fs13 = require("fs");
|
|
11007
|
+
import_path14 = require("path");
|
|
10960
11008
|
init_skill_name();
|
|
10961
11009
|
MAX_LOG_LINES = 5e3;
|
|
10962
11010
|
TRUNCATE_TO = 1e3;
|
|
@@ -10965,8 +11013,8 @@ var init_skill_gap_tracker = __esm({
|
|
|
10965
11013
|
resolutionsPath;
|
|
10966
11014
|
resolutionsCache = null;
|
|
10967
11015
|
constructor(projectRoot) {
|
|
10968
|
-
this.gapLogPath = (0,
|
|
10969
|
-
this.resolutionsPath = (0,
|
|
11016
|
+
this.gapLogPath = (0, import_path14.join)(projectRoot, ".gossip", "skill-gaps.jsonl");
|
|
11017
|
+
this.resolutionsPath = (0, import_path14.join)(projectRoot, ".gossip", "skill-resolutions.json");
|
|
10970
11018
|
this.migrateResolutions();
|
|
10971
11019
|
}
|
|
10972
11020
|
checkThresholds() {
|
|
@@ -10994,9 +11042,9 @@ var init_skill_gap_tracker = __esm({
|
|
|
10994
11042
|
const normalized = normalizeSkillName(skillName);
|
|
10995
11043
|
const resolutions = this.loadResolutions();
|
|
10996
11044
|
resolutions[normalized] = (/* @__PURE__ */ new Date()).toISOString();
|
|
10997
|
-
const dir = (0,
|
|
10998
|
-
if (!(0,
|
|
10999
|
-
(0,
|
|
11045
|
+
const dir = (0, import_path14.join)(this.resolutionsPath, "..");
|
|
11046
|
+
if (!(0, import_fs13.existsSync)(dir)) (0, import_fs13.mkdirSync)(dir, { recursive: true });
|
|
11047
|
+
(0, import_fs13.writeFileSync)(this.resolutionsPath, JSON.stringify(resolutions, null, 2));
|
|
11000
11048
|
this.resolutionsCache = resolutions;
|
|
11001
11049
|
}
|
|
11002
11050
|
getSuggestionsSince(agentId, sinceMs) {
|
|
@@ -11005,9 +11053,9 @@ var init_skill_gap_tracker = __esm({
|
|
|
11005
11053
|
);
|
|
11006
11054
|
}
|
|
11007
11055
|
appendSuggestion(suggestion) {
|
|
11008
|
-
const dir = (0,
|
|
11009
|
-
if (!(0,
|
|
11010
|
-
(0,
|
|
11056
|
+
const dir = (0, import_path14.join)(this.gapLogPath, "..");
|
|
11057
|
+
if (!(0, import_fs13.existsSync)(dir)) (0, import_fs13.mkdirSync)(dir, { recursive: true });
|
|
11058
|
+
(0, import_fs13.appendFileSync)(this.gapLogPath, JSON.stringify(suggestion) + "\n");
|
|
11011
11059
|
this.truncateIfNeeded();
|
|
11012
11060
|
}
|
|
11013
11061
|
getPendingSkills() {
|
|
@@ -11035,9 +11083,9 @@ var init_skill_gap_tracker = __esm({
|
|
|
11035
11083
|
);
|
|
11036
11084
|
}
|
|
11037
11085
|
readSuggestions() {
|
|
11038
|
-
if (!(0,
|
|
11086
|
+
if (!(0, import_fs13.existsSync)(this.gapLogPath)) return [];
|
|
11039
11087
|
try {
|
|
11040
|
-
const lines = (0,
|
|
11088
|
+
const lines = (0, import_fs13.readFileSync)(this.gapLogPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
11041
11089
|
return lines.map((line) => {
|
|
11042
11090
|
try {
|
|
11043
11091
|
return JSON.parse(line);
|
|
@@ -11051,12 +11099,12 @@ var init_skill_gap_tracker = __esm({
|
|
|
11051
11099
|
}
|
|
11052
11100
|
loadResolutions() {
|
|
11053
11101
|
if (this.resolutionsCache) return this.resolutionsCache;
|
|
11054
|
-
if (!(0,
|
|
11102
|
+
if (!(0, import_fs13.existsSync)(this.resolutionsPath)) {
|
|
11055
11103
|
this.resolutionsCache = {};
|
|
11056
11104
|
return this.resolutionsCache;
|
|
11057
11105
|
}
|
|
11058
11106
|
try {
|
|
11059
|
-
this.resolutionsCache = JSON.parse((0,
|
|
11107
|
+
this.resolutionsCache = JSON.parse((0, import_fs13.readFileSync)(this.resolutionsPath, "utf-8"));
|
|
11060
11108
|
return this.resolutionsCache;
|
|
11061
11109
|
} catch {
|
|
11062
11110
|
this.resolutionsCache = {};
|
|
@@ -11064,10 +11112,10 @@ var init_skill_gap_tracker = __esm({
|
|
|
11064
11112
|
}
|
|
11065
11113
|
}
|
|
11066
11114
|
migrateResolutions() {
|
|
11067
|
-
if ((0,
|
|
11068
|
-
if (!(0,
|
|
11115
|
+
if ((0, import_fs13.existsSync)(this.resolutionsPath)) return;
|
|
11116
|
+
if (!(0, import_fs13.existsSync)(this.gapLogPath)) return;
|
|
11069
11117
|
try {
|
|
11070
|
-
const lines = (0,
|
|
11118
|
+
const lines = (0, import_fs13.readFileSync)(this.gapLogPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
11071
11119
|
const resolutions = {};
|
|
11072
11120
|
for (const line of lines) {
|
|
11073
11121
|
try {
|
|
@@ -11079,21 +11127,21 @@ var init_skill_gap_tracker = __esm({
|
|
|
11079
11127
|
}
|
|
11080
11128
|
}
|
|
11081
11129
|
if (Object.keys(resolutions).length > 0) {
|
|
11082
|
-
const dir = (0,
|
|
11083
|
-
if (!(0,
|
|
11084
|
-
(0,
|
|
11130
|
+
const dir = (0, import_path14.join)(this.resolutionsPath, "..");
|
|
11131
|
+
if (!(0, import_fs13.existsSync)(dir)) (0, import_fs13.mkdirSync)(dir, { recursive: true });
|
|
11132
|
+
(0, import_fs13.writeFileSync)(this.resolutionsPath, JSON.stringify(resolutions, null, 2));
|
|
11085
11133
|
this.resolutionsCache = resolutions;
|
|
11086
11134
|
}
|
|
11087
11135
|
} catch {
|
|
11088
11136
|
}
|
|
11089
11137
|
}
|
|
11090
11138
|
truncateIfNeeded() {
|
|
11091
|
-
if (!(0,
|
|
11139
|
+
if (!(0, import_fs13.existsSync)(this.gapLogPath)) return;
|
|
11092
11140
|
try {
|
|
11093
|
-
const content = (0,
|
|
11141
|
+
const content = (0, import_fs13.readFileSync)(this.gapLogPath, "utf-8");
|
|
11094
11142
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
11095
11143
|
if (lines.length > MAX_LOG_LINES) {
|
|
11096
|
-
(0,
|
|
11144
|
+
(0, import_fs13.writeFileSync)(this.gapLogPath, lines.slice(-TRUNCATE_TO).join("\n") + "\n");
|
|
11097
11145
|
}
|
|
11098
11146
|
} catch {
|
|
11099
11147
|
}
|
|
@@ -11103,12 +11151,12 @@ var init_skill_gap_tracker = __esm({
|
|
|
11103
11151
|
});
|
|
11104
11152
|
|
|
11105
11153
|
// packages/orchestrator/src/scope-tracker.ts
|
|
11106
|
-
var
|
|
11154
|
+
var import_path15, import_fs14, ScopeTracker;
|
|
11107
11155
|
var init_scope_tracker = __esm({
|
|
11108
11156
|
"packages/orchestrator/src/scope-tracker.ts"() {
|
|
11109
11157
|
"use strict";
|
|
11110
|
-
|
|
11111
|
-
|
|
11158
|
+
import_path15 = require("path");
|
|
11159
|
+
import_fs14 = require("fs");
|
|
11112
11160
|
ScopeTracker = class {
|
|
11113
11161
|
// taskId → scope (for release)
|
|
11114
11162
|
constructor(projectRoot) {
|
|
@@ -11119,15 +11167,15 @@ var init_scope_tracker = __esm({
|
|
|
11119
11167
|
taskToScope = /* @__PURE__ */ new Map();
|
|
11120
11168
|
normalize(scope) {
|
|
11121
11169
|
if (!scope || !scope.trim()) throw new Error("Scope must not be empty");
|
|
11122
|
-
const realRoot = (0,
|
|
11123
|
-
const abs = (0,
|
|
11170
|
+
const realRoot = (0, import_fs14.realpathSync)(this.projectRoot);
|
|
11171
|
+
const abs = (0, import_path15.resolve)(realRoot, scope);
|
|
11124
11172
|
let real;
|
|
11125
11173
|
try {
|
|
11126
|
-
real = (0,
|
|
11174
|
+
real = (0, import_fs14.realpathSync)(abs);
|
|
11127
11175
|
} catch {
|
|
11128
11176
|
real = abs;
|
|
11129
11177
|
}
|
|
11130
|
-
const rel = (0,
|
|
11178
|
+
const rel = (0, import_path15.relative)(realRoot, real);
|
|
11131
11179
|
if (rel.startsWith("..")) throw new Error(`Scope "${scope}" resolves outside project root`);
|
|
11132
11180
|
if (rel === "") throw new Error(`Scope "${scope}" resolves to project root \u2014 too broad`);
|
|
11133
11181
|
return rel.endsWith("/") ? rel : rel + "/";
|
|
@@ -11165,14 +11213,14 @@ var init_scope_tracker = __esm({
|
|
|
11165
11213
|
});
|
|
11166
11214
|
|
|
11167
11215
|
// packages/orchestrator/src/worktree-manager.ts
|
|
11168
|
-
var import_child_process3, import_util8, import_promises2,
|
|
11216
|
+
var import_child_process3, import_util8, import_promises2, import_path16, import_os, execFileAsync3, WorktreeManager;
|
|
11169
11217
|
var init_worktree_manager = __esm({
|
|
11170
11218
|
"packages/orchestrator/src/worktree-manager.ts"() {
|
|
11171
11219
|
"use strict";
|
|
11172
11220
|
import_child_process3 = require("child_process");
|
|
11173
11221
|
import_util8 = require("util");
|
|
11174
11222
|
import_promises2 = require("fs/promises");
|
|
11175
|
-
|
|
11223
|
+
import_path16 = require("path");
|
|
11176
11224
|
import_os = require("os");
|
|
11177
11225
|
execFileAsync3 = (0, import_util8.promisify)(import_child_process3.execFile);
|
|
11178
11226
|
WorktreeManager = class {
|
|
@@ -11181,7 +11229,7 @@ var init_worktree_manager = __esm({
|
|
|
11181
11229
|
}
|
|
11182
11230
|
async create(taskId) {
|
|
11183
11231
|
const branch = `gossip-${taskId}`;
|
|
11184
|
-
const wtPath = await (0, import_promises2.mkdtemp)((0,
|
|
11232
|
+
const wtPath = await (0, import_promises2.mkdtemp)((0, import_path16.join)((0, import_os.tmpdir)(), "gossip-wt-"));
|
|
11185
11233
|
await execFileAsync3("git", ["branch", branch, "HEAD"], { cwd: this.projectRoot });
|
|
11186
11234
|
try {
|
|
11187
11235
|
await execFileAsync3("git", ["worktree", "add", wtPath, branch], { cwd: this.projectRoot });
|
|
@@ -11256,12 +11304,12 @@ function getSeverityMultiplier(severity) {
|
|
|
11256
11304
|
function clamp(v, min, max) {
|
|
11257
11305
|
return Math.max(min, Math.min(max, v));
|
|
11258
11306
|
}
|
|
11259
|
-
var
|
|
11307
|
+
var import_fs15, import_path17, CIRCUIT_BREAKER_THRESHOLD, NEGATIVE_SIGNALS, SIGNAL_EXPIRY_DAYS, KNOWN_SIGNALS, SEVERITY_MULTIPLIER, PerformanceReader;
|
|
11260
11308
|
var init_performance_reader = __esm({
|
|
11261
11309
|
"packages/orchestrator/src/performance-reader.ts"() {
|
|
11262
11310
|
"use strict";
|
|
11263
|
-
|
|
11264
|
-
|
|
11311
|
+
import_fs15 = require("fs");
|
|
11312
|
+
import_path17 = require("path");
|
|
11265
11313
|
CIRCUIT_BREAKER_THRESHOLD = 3;
|
|
11266
11314
|
NEGATIVE_SIGNALS = /* @__PURE__ */ new Set(["hallucination_caught", "disagreement", "unique_unconfirmed"]);
|
|
11267
11315
|
SIGNAL_EXPIRY_DAYS = 30;
|
|
@@ -11290,13 +11338,13 @@ var init_performance_reader = __esm({
|
|
|
11290
11338
|
cachedScores = null;
|
|
11291
11339
|
cachedMtimeMs = 0;
|
|
11292
11340
|
constructor(projectRoot) {
|
|
11293
|
-
this.filePath = (0,
|
|
11341
|
+
this.filePath = (0, import_path17.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
11294
11342
|
}
|
|
11295
11343
|
/** Read all signals and compute per-agent scores (cached by file mtime) */
|
|
11296
11344
|
getScores() {
|
|
11297
11345
|
let mtimeMs = 0;
|
|
11298
11346
|
try {
|
|
11299
|
-
mtimeMs = (0,
|
|
11347
|
+
mtimeMs = (0, import_fs15.statSync)(this.filePath).mtimeMs;
|
|
11300
11348
|
} catch {
|
|
11301
11349
|
}
|
|
11302
11350
|
if (this.cachedScores && mtimeMs === this.cachedMtimeMs) {
|
|
@@ -11372,9 +11420,9 @@ var init_performance_reader = __esm({
|
|
|
11372
11420
|
* Don't unify these — see getCountersSince doc and consensus 9369ebfc-a3654b51 f1.
|
|
11373
11421
|
*/
|
|
11374
11422
|
readSignalsRaw() {
|
|
11375
|
-
if (!(0,
|
|
11423
|
+
if (!(0, import_fs15.existsSync)(this.filePath)) return [];
|
|
11376
11424
|
try {
|
|
11377
|
-
const lines = (0,
|
|
11425
|
+
const lines = (0, import_fs15.readFileSync)(this.filePath, "utf-8").trim().split("\n").filter(Boolean);
|
|
11378
11426
|
const all = lines.map((line) => {
|
|
11379
11427
|
try {
|
|
11380
11428
|
return JSON.parse(line);
|
|
@@ -11407,10 +11455,10 @@ var init_performance_reader = __esm({
|
|
|
11407
11455
|
}
|
|
11408
11456
|
}
|
|
11409
11457
|
readSignals() {
|
|
11410
|
-
if (!(0,
|
|
11458
|
+
if (!(0, import_fs15.existsSync)(this.filePath)) return [];
|
|
11411
11459
|
try {
|
|
11412
11460
|
const expiryMs = Date.now() - SIGNAL_EXPIRY_DAYS * 864e5;
|
|
11413
|
-
const lines = (0,
|
|
11461
|
+
const lines = (0, import_fs15.readFileSync)(this.filePath, "utf-8").trim().split("\n").filter(Boolean);
|
|
11414
11462
|
const all = lines.map((line) => {
|
|
11415
11463
|
try {
|
|
11416
11464
|
return JSON.parse(line);
|
|
@@ -11675,11 +11723,11 @@ var init_performance_reader = __esm({
|
|
|
11675
11723
|
return result;
|
|
11676
11724
|
}
|
|
11677
11725
|
getImplScore(agentId) {
|
|
11678
|
-
if (!(0,
|
|
11726
|
+
if (!(0, import_fs15.existsSync)(this.filePath)) return null;
|
|
11679
11727
|
try {
|
|
11680
11728
|
const now = Date.now();
|
|
11681
11729
|
const expiryMs = now - SIGNAL_EXPIRY_DAYS * 864e5;
|
|
11682
|
-
const lines = (0,
|
|
11730
|
+
const lines = (0, import_fs15.readFileSync)(this.filePath, "utf-8").trim().split("\n").filter(Boolean);
|
|
11683
11731
|
let pass = 0, fail = 0, approved = 0, rejected = 0, lastImplSignalMs = 0;
|
|
11684
11732
|
for (const line of lines) {
|
|
11685
11733
|
try {
|
|
@@ -11718,12 +11766,12 @@ var init_performance_reader = __esm({
|
|
|
11718
11766
|
});
|
|
11719
11767
|
|
|
11720
11768
|
// packages/orchestrator/src/skill-counters.ts
|
|
11721
|
-
var
|
|
11769
|
+
var import_fs16, import_path18, STALE_THRESHOLD, PROMOTION_RATE, PROMOTION_MIN_WINDOW, SkillCounterTracker;
|
|
11722
11770
|
var init_skill_counters = __esm({
|
|
11723
11771
|
"packages/orchestrator/src/skill-counters.ts"() {
|
|
11724
11772
|
"use strict";
|
|
11725
|
-
|
|
11726
|
-
|
|
11773
|
+
import_fs16 = require("fs");
|
|
11774
|
+
import_path18 = require("path");
|
|
11727
11775
|
STALE_THRESHOLD = 30;
|
|
11728
11776
|
PROMOTION_RATE = 0.8;
|
|
11729
11777
|
PROMOTION_MIN_WINDOW = 20;
|
|
@@ -11732,7 +11780,7 @@ var init_skill_counters = __esm({
|
|
|
11732
11780
|
filePath;
|
|
11733
11781
|
dirty = false;
|
|
11734
11782
|
constructor(projectRoot) {
|
|
11735
|
-
this.filePath = (0,
|
|
11783
|
+
this.filePath = (0, import_path18.join)(projectRoot, ".gossip", "skill-counters.json");
|
|
11736
11784
|
this.load();
|
|
11737
11785
|
}
|
|
11738
11786
|
/**
|
|
@@ -11807,15 +11855,15 @@ var init_skill_counters = __esm({
|
|
|
11807
11855
|
/** Flush counters to disk. Call during gossip_collect. */
|
|
11808
11856
|
flush() {
|
|
11809
11857
|
if (!this.dirty) return;
|
|
11810
|
-
const dir = (0,
|
|
11811
|
-
if (!(0,
|
|
11812
|
-
(0,
|
|
11858
|
+
const dir = (0, import_path18.dirname)(this.filePath);
|
|
11859
|
+
if (!(0, import_fs16.existsSync)(dir)) (0, import_fs16.mkdirSync)(dir, { recursive: true });
|
|
11860
|
+
(0, import_fs16.writeFileSync)(this.filePath, JSON.stringify(this.data, null, 2) + "\n");
|
|
11813
11861
|
this.dirty = false;
|
|
11814
11862
|
}
|
|
11815
11863
|
load() {
|
|
11816
11864
|
try {
|
|
11817
|
-
if ((0,
|
|
11818
|
-
const raw = JSON.parse((0,
|
|
11865
|
+
if ((0, import_fs16.existsSync)(this.filePath)) {
|
|
11866
|
+
const raw = JSON.parse((0, import_fs16.readFileSync)(this.filePath, "utf-8"));
|
|
11819
11867
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return;
|
|
11820
11868
|
for (const [agentId, skills] of Object.entries(raw)) {
|
|
11821
11869
|
if (!skills || typeof skills !== "object") {
|
|
@@ -11842,14 +11890,14 @@ function shortConsensusId() {
|
|
|
11842
11890
|
const hex3 = (0, import_crypto6.randomUUID)().replace(/-/g, "");
|
|
11843
11891
|
return hex3.slice(0, 8) + "-" + hex3.slice(8, 16);
|
|
11844
11892
|
}
|
|
11845
|
-
var import_promises3,
|
|
11893
|
+
var import_promises3, import_fs17, import_crypto6, import_path19, SUMMARY_HEADER, FALLBACK_MAX_LENGTH, MAX_SUMMARY_LENGTH, MAX_CROSS_REVIEW_ENTRIES, VALID_ACTIONS, ANCHOR_PATTERN, ConsensusEngine;
|
|
11846
11894
|
var init_consensus_engine = __esm({
|
|
11847
11895
|
"packages/orchestrator/src/consensus-engine.ts"() {
|
|
11848
11896
|
"use strict";
|
|
11849
11897
|
import_promises3 = require("fs/promises");
|
|
11850
|
-
|
|
11898
|
+
import_fs17 = require("fs");
|
|
11851
11899
|
import_crypto6 = require("crypto");
|
|
11852
|
-
|
|
11900
|
+
import_path19 = require("path");
|
|
11853
11901
|
SUMMARY_HEADER = "## Consensus Summary";
|
|
11854
11902
|
FALLBACK_MAX_LENGTH = 2e3;
|
|
11855
11903
|
MAX_SUMMARY_LENGTH = 5e3;
|
|
@@ -11885,7 +11933,7 @@ var init_consensus_engine = __esm({
|
|
|
11885
11933
|
for (const r of results) {
|
|
11886
11934
|
const wt = r.worktreeInfo?.path;
|
|
11887
11935
|
if (wt && typeof wt === "string") {
|
|
11888
|
-
next.add((0,
|
|
11936
|
+
next.add((0, import_path19.resolve)(wt));
|
|
11889
11937
|
}
|
|
11890
11938
|
}
|
|
11891
11939
|
let changed = next.size !== this.currentWorktreeRoots.size;
|
|
@@ -12713,9 +12761,9 @@ ${safeSnippet}
|
|
|
12713
12761
|
*/
|
|
12714
12762
|
/** Guard: resolved path must stay inside one of the valid roots */
|
|
12715
12763
|
isInsideAnyRoot(candidate, roots) {
|
|
12716
|
-
const normalized = (0,
|
|
12764
|
+
const normalized = (0, import_path19.resolve)(candidate);
|
|
12717
12765
|
return roots.some((root) => {
|
|
12718
|
-
const normalizedRoot = (0,
|
|
12766
|
+
const normalizedRoot = (0, import_path19.resolve)(root);
|
|
12719
12767
|
return normalized === normalizedRoot || normalized.startsWith(normalizedRoot + "/");
|
|
12720
12768
|
});
|
|
12721
12769
|
}
|
|
@@ -12725,7 +12773,7 @@ ${safeSnippet}
|
|
|
12725
12773
|
const fileName = fileRef.split("/").pop();
|
|
12726
12774
|
for (const root of roots) {
|
|
12727
12775
|
try {
|
|
12728
|
-
const candidate = (0,
|
|
12776
|
+
const candidate = (0, import_path19.join)(root, fileRef);
|
|
12729
12777
|
if (this.isInsideAnyRoot(candidate, roots)) {
|
|
12730
12778
|
await (0, import_promises3.stat)(candidate);
|
|
12731
12779
|
return candidate;
|
|
@@ -12734,7 +12782,7 @@ ${safeSnippet}
|
|
|
12734
12782
|
}
|
|
12735
12783
|
if (fileName !== fileRef) {
|
|
12736
12784
|
try {
|
|
12737
|
-
const candidate = (0,
|
|
12785
|
+
const candidate = (0, import_path19.join)(root, fileName);
|
|
12738
12786
|
if (this.isInsideAnyRoot(candidate, roots)) {
|
|
12739
12787
|
await (0, import_promises3.stat)(candidate);
|
|
12740
12788
|
return candidate;
|
|
@@ -12744,7 +12792,7 @@ ${safeSnippet}
|
|
|
12744
12792
|
}
|
|
12745
12793
|
const searchDirs = ["packages", "src", "apps", "tests", "test", "tools", "scripts", "lib"];
|
|
12746
12794
|
for (const dir of searchDirs) {
|
|
12747
|
-
const found = await this.findFile((0,
|
|
12795
|
+
const found = await this.findFile((0, import_path19.join)(root, dir), fileName, roots);
|
|
12748
12796
|
if (found) return found;
|
|
12749
12797
|
}
|
|
12750
12798
|
}
|
|
@@ -12754,7 +12802,7 @@ ${safeSnippet}
|
|
|
12754
12802
|
try {
|
|
12755
12803
|
const entries = await (0, import_promises3.readdir)(dir, { withFileTypes: true });
|
|
12756
12804
|
for (const entry of entries) {
|
|
12757
|
-
const fullPath = (0,
|
|
12805
|
+
const fullPath = (0, import_path19.join)(dir, entry.name);
|
|
12758
12806
|
if (entry.isFile() && entry.name === fileName) {
|
|
12759
12807
|
if (!this.isInsideAnyRoot(fullPath, validRoots)) return null;
|
|
12760
12808
|
return fullPath;
|
|
@@ -12780,7 +12828,7 @@ ${safeSnippet}
|
|
|
12780
12828
|
const sourceExts = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
12781
12829
|
for (const root of roots) {
|
|
12782
12830
|
for (const dir of searchDirs) {
|
|
12783
|
-
const result = await this.grepDir((0,
|
|
12831
|
+
const result = await this.grepDir((0, import_path19.join)(root, dir), identifier, sourceExts, CONTEXT_LINES);
|
|
12784
12832
|
if (result) return result;
|
|
12785
12833
|
}
|
|
12786
12834
|
}
|
|
@@ -12791,7 +12839,7 @@ ${safeSnippet}
|
|
|
12791
12839
|
try {
|
|
12792
12840
|
const entries = await (0, import_promises3.readdir)(dir, { withFileTypes: true });
|
|
12793
12841
|
for (const entry of entries) {
|
|
12794
|
-
const fullPath = (0,
|
|
12842
|
+
const fullPath = (0, import_path19.join)(dir, entry.name);
|
|
12795
12843
|
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== ".git" && entry.name !== "dist") {
|
|
12796
12844
|
const found = await this.grepDir(fullPath, identifier, exts, contextLines);
|
|
12797
12845
|
if (found) return found;
|
|
@@ -13285,11 +13333,11 @@ ${safeSnippet}
|
|
|
13285
13333
|
dumpFailedCrossReview(reviewerAgentId, text) {
|
|
13286
13334
|
if (!this.config.projectRoot) return;
|
|
13287
13335
|
try {
|
|
13288
|
-
const dir = (0,
|
|
13289
|
-
(0,
|
|
13336
|
+
const dir = (0, import_path19.join)(this.config.projectRoot, ".gossip", "cross-review-failures");
|
|
13337
|
+
(0, import_fs17.mkdirSync)(dir, { recursive: true });
|
|
13290
13338
|
const safeId2 = reviewerAgentId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
13291
13339
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
13292
|
-
(0,
|
|
13340
|
+
(0, import_fs17.writeFileSync)((0, import_path19.join)(dir, `${safeId2}-${ts}.txt`), text);
|
|
13293
13341
|
} catch {
|
|
13294
13342
|
}
|
|
13295
13343
|
}
|
|
@@ -13362,12 +13410,12 @@ function validateSignal(signal) {
|
|
|
13362
13410
|
throw new Error(`Signal validation failed: unknown type "${signal.type}"`);
|
|
13363
13411
|
}
|
|
13364
13412
|
}
|
|
13365
|
-
var
|
|
13413
|
+
var import_fs18, import_path20, VALID_CONSENSUS_SIGNALS, VALID_IMPL_SIGNALS, VALID_META_SIGNALS, PerformanceWriter;
|
|
13366
13414
|
var init_performance_writer = __esm({
|
|
13367
13415
|
"packages/orchestrator/src/performance-writer.ts"() {
|
|
13368
13416
|
"use strict";
|
|
13369
|
-
|
|
13370
|
-
|
|
13417
|
+
import_fs18 = require("fs");
|
|
13418
|
+
import_path20 = require("path");
|
|
13371
13419
|
VALID_CONSENSUS_SIGNALS = /* @__PURE__ */ new Set([
|
|
13372
13420
|
"agreement",
|
|
13373
13421
|
"disagreement",
|
|
@@ -13393,19 +13441,19 @@ var init_performance_writer = __esm({
|
|
|
13393
13441
|
PerformanceWriter = class {
|
|
13394
13442
|
filePath;
|
|
13395
13443
|
constructor(projectRoot) {
|
|
13396
|
-
const dir = (0,
|
|
13397
|
-
if (!(0,
|
|
13398
|
-
this.filePath = (0,
|
|
13444
|
+
const dir = (0, import_path20.join)(projectRoot, ".gossip");
|
|
13445
|
+
if (!(0, import_fs18.existsSync)(dir)) (0, import_fs18.mkdirSync)(dir, { recursive: true });
|
|
13446
|
+
this.filePath = (0, import_path20.join)(dir, "agent-performance.jsonl");
|
|
13399
13447
|
}
|
|
13400
13448
|
appendSignal(signal) {
|
|
13401
13449
|
validateSignal(signal);
|
|
13402
|
-
(0,
|
|
13450
|
+
(0, import_fs18.appendFileSync)(this.filePath, JSON.stringify(signal) + "\n");
|
|
13403
13451
|
}
|
|
13404
13452
|
appendSignals(signals) {
|
|
13405
13453
|
if (signals.length === 0) return;
|
|
13406
13454
|
for (const s of signals) validateSignal(s);
|
|
13407
13455
|
const data = signals.map((s) => JSON.stringify(s)).join("\n") + "\n";
|
|
13408
|
-
(0,
|
|
13456
|
+
(0, import_fs18.appendFileSync)(this.filePath, data);
|
|
13409
13457
|
}
|
|
13410
13458
|
};
|
|
13411
13459
|
}
|
|
@@ -13604,12 +13652,12 @@ ${topFindings}`;
|
|
|
13604
13652
|
});
|
|
13605
13653
|
|
|
13606
13654
|
// packages/orchestrator/src/session-context.ts
|
|
13607
|
-
var
|
|
13655
|
+
var import_fs19, import_path21, log3, SessionContext;
|
|
13608
13656
|
var init_session_context = __esm({
|
|
13609
13657
|
"packages/orchestrator/src/session-context.ts"() {
|
|
13610
13658
|
"use strict";
|
|
13611
|
-
|
|
13612
|
-
|
|
13659
|
+
import_fs19 = require("fs");
|
|
13660
|
+
import_path21 = require("path");
|
|
13613
13661
|
log3 = (msg) => process.stderr.write(`[gossipcat] ${msg}
|
|
13614
13662
|
`);
|
|
13615
13663
|
SessionContext = class _SessionContext {
|
|
@@ -13623,7 +13671,7 @@ var init_session_context = __esm({
|
|
|
13623
13671
|
this.projectRoot = config2.projectRoot;
|
|
13624
13672
|
this.llm = config2.llm;
|
|
13625
13673
|
try {
|
|
13626
|
-
const gossipPath = (0,
|
|
13674
|
+
const gossipPath = (0, import_path21.join)(config2.projectRoot, ".gossip", "agents", "_project", "memory", "session-gossip.jsonl");
|
|
13627
13675
|
const { existsSync: ex, readFileSync: rf } = require("fs");
|
|
13628
13676
|
if (ex(gossipPath)) {
|
|
13629
13677
|
const lines = rf(gossipPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
@@ -13675,9 +13723,9 @@ var init_session_context = __esm({
|
|
|
13675
13723
|
this.sessionGossip.shift();
|
|
13676
13724
|
}
|
|
13677
13725
|
try {
|
|
13678
|
-
const gossipPath = (0,
|
|
13679
|
-
(0,
|
|
13680
|
-
(0,
|
|
13726
|
+
const gossipPath = (0, import_path21.join)(this.projectRoot, ".gossip", "agents", "_project", "memory", "session-gossip.jsonl");
|
|
13727
|
+
(0, import_fs19.mkdirSync)((0, import_path21.dirname)(gossipPath), { recursive: true });
|
|
13728
|
+
(0, import_fs19.appendFileSync)(gossipPath, JSON.stringify({ agentId, taskSummary: summary, timestamp: Date.now() }) + "\n");
|
|
13681
13729
|
this.rotateJsonlFile(gossipPath, 100, 50);
|
|
13682
13730
|
} catch {
|
|
13683
13731
|
}
|
|
@@ -13698,10 +13746,10 @@ ${result.slice(0, 2e3)}` }
|
|
|
13698
13746
|
/** Rotate a JSONL file: if over maxEntries lines, keep only the last keepEntries. */
|
|
13699
13747
|
rotateJsonlFile(filePath, maxEntries, keepEntries) {
|
|
13700
13748
|
try {
|
|
13701
|
-
const content = (0,
|
|
13749
|
+
const content = (0, import_fs19.readFileSync)(filePath, "utf-8");
|
|
13702
13750
|
const lines = content.trim().split("\n").filter((l) => l.length > 0);
|
|
13703
13751
|
if (lines.length > maxEntries) {
|
|
13704
|
-
(0,
|
|
13752
|
+
(0, import_fs19.writeFileSync)(filePath, lines.slice(-keepEntries).join("\n") + "\n");
|
|
13705
13753
|
}
|
|
13706
13754
|
} catch {
|
|
13707
13755
|
}
|
|
@@ -13720,13 +13768,13 @@ function shouldSkipConsensus(task, agents, costMode, agreementHistory) {
|
|
|
13720
13768
|
const firstWord = task.trim().split(/\s+/)[0] || "";
|
|
13721
13769
|
return OBSERVATION_VERBS.test(firstWord);
|
|
13722
13770
|
}
|
|
13723
|
-
var import_crypto8,
|
|
13771
|
+
var import_crypto8, import_fs20, import_path22, log4, DispatchPipeline, SECURITY_KEYWORDS, OBSERVATION_VERBS;
|
|
13724
13772
|
var init_dispatch_pipeline = __esm({
|
|
13725
13773
|
"packages/orchestrator/src/dispatch-pipeline.ts"() {
|
|
13726
13774
|
"use strict";
|
|
13727
13775
|
import_crypto8 = require("crypto");
|
|
13728
|
-
|
|
13729
|
-
|
|
13776
|
+
import_fs20 = require("fs");
|
|
13777
|
+
import_path22 = require("path");
|
|
13730
13778
|
init_types2();
|
|
13731
13779
|
init_skill_loader();
|
|
13732
13780
|
init_prompt_assembler();
|
|
@@ -13815,8 +13863,8 @@ var init_dispatch_pipeline = __esm({
|
|
|
13815
13863
|
this.sessionContext = new SessionContext({ llm: config2.llm ?? null, projectRoot: config2.projectRoot });
|
|
13816
13864
|
this.worktreeManager.pruneOrphans().catch((err) => log4(`Orphan cleanup failed: ${err.message}`));
|
|
13817
13865
|
try {
|
|
13818
|
-
const projectMemDir = (0,
|
|
13819
|
-
(0,
|
|
13866
|
+
const projectMemDir = (0, import_path22.join)(config2.projectRoot, ".gossip", "agents", "_project", "memory");
|
|
13867
|
+
(0, import_fs20.mkdirSync)(projectMemDir, { recursive: true });
|
|
13820
13868
|
} catch {
|
|
13821
13869
|
}
|
|
13822
13870
|
}
|
|
@@ -13887,11 +13935,11 @@ var init_dispatch_pipeline = __esm({
|
|
|
13887
13935
|
const specRefs = extractSpecReferences(task);
|
|
13888
13936
|
if (specRefs.length > 0) {
|
|
13889
13937
|
try {
|
|
13890
|
-
const specPath = (0,
|
|
13891
|
-
const realSpecPath = (0,
|
|
13892
|
-
const realRoot = (0,
|
|
13938
|
+
const specPath = (0, import_path22.resolve)(this.projectRoot, specRefs[0]);
|
|
13939
|
+
const realSpecPath = (0, import_fs20.realpathSync)(specPath);
|
|
13940
|
+
const realRoot = (0, import_fs20.realpathSync)(this.projectRoot);
|
|
13893
13941
|
if (realSpecPath.startsWith(realRoot + "/")) {
|
|
13894
|
-
const specContent = (0,
|
|
13942
|
+
const specContent = (0, import_fs20.readFileSync)(realSpecPath, "utf-8");
|
|
13895
13943
|
const implFiles = extractSpecReferences(task, specContent);
|
|
13896
13944
|
const enrichment = buildSpecReviewEnrichment(implFiles);
|
|
13897
13945
|
if (enrichment) specReviewContext = enrichment;
|
|
@@ -13899,7 +13947,7 @@ var init_dispatch_pipeline = __esm({
|
|
|
13899
13947
|
} catch {
|
|
13900
13948
|
}
|
|
13901
13949
|
}
|
|
13902
|
-
const memoryDir = (0,
|
|
13950
|
+
const memoryDir = (0, import_path22.join)(this.projectRoot, ".gossip", "agents", agentId, "memory", "knowledge");
|
|
13903
13951
|
const promptContent = assemblePrompt({
|
|
13904
13952
|
memory: memory || void 0,
|
|
13905
13953
|
memoryDir,
|
|
@@ -13959,7 +14007,7 @@ var init_dispatch_pipeline = __esm({
|
|
|
13959
14007
|
const elapsedMs = (entry.completedAt ?? Date.now()) - entry.startedAt;
|
|
13960
14008
|
process.stderr.write(`[gossipcat] \u2705 relay \u2190 ${entry.agentId} [${entry.id}] OK (${(elapsedMs / 1e3).toFixed(1)}s, ${(event.payload.result || "").length} chars)
|
|
13961
14009
|
`);
|
|
13962
|
-
(0,
|
|
14010
|
+
(0, import_fs20.appendFileSync)((0, import_path22.join)(this.projectRoot, ".gossip", "task-graph.jsonl"), JSON.stringify({
|
|
13963
14011
|
type: "task.completed",
|
|
13964
14012
|
taskId: entry.id,
|
|
13965
14013
|
agentId: entry.agentId,
|
|
@@ -13983,7 +14031,7 @@ var init_dispatch_pipeline = __esm({
|
|
|
13983
14031
|
const elapsedMs = (entry.completedAt ?? Date.now()) - entry.startedAt;
|
|
13984
14032
|
process.stderr.write(`[gossipcat] \u274C relay \u2190 ${entry.agentId} [${entry.id}] FAILED (${(elapsedMs / 1e3).toFixed(1)}s) \u2014 ${event.payload.error}
|
|
13985
14033
|
`);
|
|
13986
|
-
(0,
|
|
14034
|
+
(0, import_fs20.appendFileSync)((0, import_path22.join)(this.projectRoot, ".gossip", "task-graph.jsonl"), JSON.stringify({
|
|
13987
14035
|
type: "task.failed",
|
|
13988
14036
|
taskId: entry.id,
|
|
13989
14037
|
agentId: entry.agentId,
|
|
@@ -14910,13 +14958,13 @@ function parseYamlLikeToolCall(content) {
|
|
|
14910
14958
|
const args = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
|
|
14911
14959
|
return { tool, args };
|
|
14912
14960
|
}
|
|
14913
|
-
var
|
|
14961
|
+
var import_fs21, import_path23, log5, AGENT_ID_RE, TAG_PATTERN, BLOCK_RE, BLOCK_IN_FENCE_RE, ToolRouter, ToolExecutor;
|
|
14914
14962
|
var init_tool_router = __esm({
|
|
14915
14963
|
"packages/orchestrator/src/tool-router.ts"() {
|
|
14916
14964
|
"use strict";
|
|
14917
14965
|
init_tool_definitions();
|
|
14918
|
-
|
|
14919
|
-
|
|
14966
|
+
import_fs21 = require("fs");
|
|
14967
|
+
import_path23 = require("path");
|
|
14920
14968
|
log5 = (msg) => process.stderr.write(`[tool-router] ${msg}
|
|
14921
14969
|
`);
|
|
14922
14970
|
AGENT_ID_RE = /^[a-zA-Z0-9_-]+$/;
|
|
@@ -15322,12 +15370,12 @@ ${agentOutputs}` }
|
|
|
15322
15370
|
const fsp = await import("fs/promises");
|
|
15323
15371
|
const updatedIds = [];
|
|
15324
15372
|
for (const id of pending.agentIds) {
|
|
15325
|
-
const agentDir = (0,
|
|
15326
|
-
const filePath = (0,
|
|
15327
|
-
if (!(0,
|
|
15373
|
+
const agentDir = (0, import_path23.join)(this.projectRoot, ".gossip", "agents", id);
|
|
15374
|
+
const filePath = (0, import_path23.join)(agentDir, "instructions.md");
|
|
15375
|
+
if (!(0, import_fs21.existsSync)(agentDir)) {
|
|
15328
15376
|
await fsp.mkdir(agentDir, { recursive: true });
|
|
15329
15377
|
}
|
|
15330
|
-
if ((0,
|
|
15378
|
+
if ((0, import_fs21.existsSync)(filePath)) {
|
|
15331
15379
|
await fsp.appendFile(filePath, `
|
|
15332
15380
|
|
|
15333
15381
|
${pending.instruction}`, "utf-8");
|
|
@@ -15441,9 +15489,9 @@ ${collectResult.consensus.summary}`;
|
|
|
15441
15489
|
async handlePlan(args) {
|
|
15442
15490
|
let task = String(args.task);
|
|
15443
15491
|
try {
|
|
15444
|
-
const specPath = (0,
|
|
15445
|
-
if ((0,
|
|
15446
|
-
const spec = (0,
|
|
15492
|
+
const specPath = (0, import_path23.join)(this.projectRoot, ".gossip", "spec.md");
|
|
15493
|
+
if ((0, import_fs21.existsSync)(specPath)) {
|
|
15494
|
+
const spec = (0, import_fs21.readFileSync)(specPath, "utf-8");
|
|
15447
15495
|
task = `${task}
|
|
15448
15496
|
|
|
15449
15497
|
[Project Spec]
|
|
@@ -15501,11 +15549,11 @@ ${taskLines.join("\n")}`,
|
|
|
15501
15549
|
if (!this.llm) {
|
|
15502
15550
|
return { text: "Tool error: LLM not available for spec generation" };
|
|
15503
15551
|
}
|
|
15504
|
-
const specPath = (0,
|
|
15552
|
+
const specPath = (0, import_path23.join)(this.projectRoot, ".gossip", "spec.md");
|
|
15505
15553
|
let existingSpec = "";
|
|
15506
15554
|
try {
|
|
15507
|
-
if ((0,
|
|
15508
|
-
existingSpec = (0,
|
|
15555
|
+
if ((0, import_fs21.existsSync)(specPath)) {
|
|
15556
|
+
existingSpec = (0, import_fs21.readFileSync)(specPath, "utf-8");
|
|
15509
15557
|
}
|
|
15510
15558
|
} catch {
|
|
15511
15559
|
}
|
|
@@ -15541,7 +15589,7 @@ Keep it SHORT \u2014 under 30 lines. This is a working document, not a design do
|
|
|
15541
15589
|
const specContent = response.text || "";
|
|
15542
15590
|
try {
|
|
15543
15591
|
const { mkdirSync: mkdirSync21, writeFileSync: writeFS } = require("fs");
|
|
15544
|
-
mkdirSync21((0,
|
|
15592
|
+
mkdirSync21((0, import_path23.join)(this.projectRoot, ".gossip"), { recursive: true });
|
|
15545
15593
|
writeFS(specPath, specContent, "utf-8");
|
|
15546
15594
|
} catch (err) {
|
|
15547
15595
|
return { text: `Spec generated but failed to save: ${err.message}
|
|
@@ -15579,11 +15627,11 @@ ${lines.join("\n")}` };
|
|
|
15579
15627
|
if (!this.registry.get(agentId)) {
|
|
15580
15628
|
return { text: `Tool error: agent "${agentId}" not found in registry` };
|
|
15581
15629
|
}
|
|
15582
|
-
const tasksPath = (0,
|
|
15583
|
-
if (!(0,
|
|
15630
|
+
const tasksPath = (0, import_path23.join)(this.projectRoot, ".gossip", "agents", agentId, "memory", "tasks.jsonl");
|
|
15631
|
+
if (!(0, import_fs21.existsSync)(tasksPath)) {
|
|
15584
15632
|
return { text: `Agent "${agentId}" \u2014 no task history found.` };
|
|
15585
15633
|
}
|
|
15586
|
-
const rawLines = (0,
|
|
15634
|
+
const rawLines = (0, import_fs21.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
15587
15635
|
const last5 = rawLines.slice(-5).map((line) => {
|
|
15588
15636
|
try {
|
|
15589
15637
|
return JSON.parse(line);
|
|
@@ -15600,11 +15648,11 @@ Last ${last5.length} tasks:
|
|
|
15600
15648
|
${formatted.join("\n")}` };
|
|
15601
15649
|
}
|
|
15602
15650
|
handleAgentPerformance() {
|
|
15603
|
-
const perfPath = (0,
|
|
15604
|
-
if (!(0,
|
|
15651
|
+
const perfPath = (0, import_path23.join)(this.projectRoot, ".gossip", "agent-performance.jsonl");
|
|
15652
|
+
if (!(0, import_fs21.existsSync)(perfPath)) {
|
|
15605
15653
|
return { text: "No performance data found." };
|
|
15606
15654
|
}
|
|
15607
|
-
const rawLines = (0,
|
|
15655
|
+
const rawLines = (0, import_fs21.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
15608
15656
|
const last20 = rawLines.slice(-20).map((line) => {
|
|
15609
15657
|
try {
|
|
15610
15658
|
return JSON.parse(line);
|
|
@@ -15655,11 +15703,11 @@ Instruction: "${instruction}"`,
|
|
|
15655
15703
|
if (!this.registry.get(agentId)) {
|
|
15656
15704
|
return { text: `Tool error: agent "${agentId}" not found in registry` };
|
|
15657
15705
|
}
|
|
15658
|
-
const tasksPath = (0,
|
|
15659
|
-
if (!(0,
|
|
15706
|
+
const tasksPath = (0, import_path23.join)(this.projectRoot, ".gossip", "agents", agentId, "memory", "tasks.jsonl");
|
|
15707
|
+
if (!(0, import_fs21.existsSync)(tasksPath)) {
|
|
15660
15708
|
return { text: `No task history for agent "${agentId}".` };
|
|
15661
15709
|
}
|
|
15662
|
-
const rawLines = (0,
|
|
15710
|
+
const rawLines = (0, import_fs21.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
15663
15711
|
const entries = rawLines.slice(-limit).map((line) => {
|
|
15664
15712
|
try {
|
|
15665
15713
|
return JSON.parse(line);
|
|
@@ -15719,17 +15767,34 @@ ${formatted.join("\n")}` };
|
|
|
15719
15767
|
});
|
|
15720
15768
|
|
|
15721
15769
|
// packages/orchestrator/src/archetype-catalog.ts
|
|
15722
|
-
|
|
15770
|
+
function findArchetypeCatalog() {
|
|
15771
|
+
const candidates = [
|
|
15772
|
+
(0, import_path24.resolve)(__dirname, "data", "archetypes.json"),
|
|
15773
|
+
// bundled prod: dist-mcp/data/archetypes.json
|
|
15774
|
+
(0, import_path24.resolve)(__dirname, "..", "..", "..", "data", "archetypes.json"),
|
|
15775
|
+
// dev ts-node: packages/orchestrator/src → repo/data
|
|
15776
|
+
(0, import_path24.resolve)(process.cwd(), "data", "archetypes.json")
|
|
15777
|
+
// last-resort dev fallback
|
|
15778
|
+
];
|
|
15779
|
+
for (const p of candidates) {
|
|
15780
|
+
if ((0, import_fs22.existsSync)(p)) return p;
|
|
15781
|
+
}
|
|
15782
|
+
return null;
|
|
15783
|
+
}
|
|
15784
|
+
var import_fs22, import_path24, ArchetypeCatalog;
|
|
15723
15785
|
var init_archetype_catalog = __esm({
|
|
15724
15786
|
"packages/orchestrator/src/archetype-catalog.ts"() {
|
|
15725
15787
|
"use strict";
|
|
15726
|
-
|
|
15727
|
-
|
|
15728
|
-
DEFAULT_PATH = (0, import_path23.resolve)(__dirname, "..", "..", "..", "data", "archetypes.json");
|
|
15788
|
+
import_fs22 = require("fs");
|
|
15789
|
+
import_path24 = require("path");
|
|
15729
15790
|
ArchetypeCatalog = class {
|
|
15730
15791
|
archetypes;
|
|
15731
15792
|
constructor(catalogPath) {
|
|
15732
|
-
const
|
|
15793
|
+
const path2 = catalogPath ?? findArchetypeCatalog();
|
|
15794
|
+
if (!path2) {
|
|
15795
|
+
throw new Error("archetypes.json not found \u2014 tried bundled dist-mcp/data/, dev ts-node path, and cwd/data/. Reinstall gossipcat.");
|
|
15796
|
+
}
|
|
15797
|
+
const raw = (0, import_fs22.readFileSync)(path2, "utf-8");
|
|
15733
15798
|
this.archetypes = JSON.parse(raw);
|
|
15734
15799
|
}
|
|
15735
15800
|
/** Return all archetype IDs */
|
|
@@ -15779,13 +15844,13 @@ var init_archetype_catalog = __esm({
|
|
|
15779
15844
|
});
|
|
15780
15845
|
|
|
15781
15846
|
// packages/orchestrator/src/project-initializer.ts
|
|
15782
|
-
var
|
|
15847
|
+
var import_fs23, import_path25, SIGNAL_DIRS, SIGNAL_FILES, LANG_FILES, ProjectInitializer;
|
|
15783
15848
|
var init_project_initializer = __esm({
|
|
15784
15849
|
"packages/orchestrator/src/project-initializer.ts"() {
|
|
15785
15850
|
"use strict";
|
|
15786
15851
|
init_archetype_catalog();
|
|
15787
|
-
|
|
15788
|
-
|
|
15852
|
+
import_fs23 = require("fs");
|
|
15853
|
+
import_path25 = require("path");
|
|
15789
15854
|
SIGNAL_DIRS = [
|
|
15790
15855
|
"src",
|
|
15791
15856
|
"pages",
|
|
@@ -15817,16 +15882,16 @@ var init_project_initializer = __esm({
|
|
|
15817
15882
|
this.config = config2;
|
|
15818
15883
|
}
|
|
15819
15884
|
scanDirectory(root) {
|
|
15820
|
-
const absRoot = (0,
|
|
15885
|
+
const absRoot = (0, import_path25.resolve)(root);
|
|
15821
15886
|
const signals = { dependencies: [], directories: [], files: [] };
|
|
15822
15887
|
for (const [file2, lang] of Object.entries(LANG_FILES)) {
|
|
15823
|
-
if (this.safeExists(absRoot, (0,
|
|
15888
|
+
if (this.safeExists(absRoot, (0, import_path25.join)(absRoot, file2))) signals.language = lang;
|
|
15824
15889
|
}
|
|
15825
|
-
const pkgPath = (0,
|
|
15890
|
+
const pkgPath = (0, import_path25.join)(absRoot, "package.json");
|
|
15826
15891
|
if (this.safeExists(absRoot, pkgPath)) {
|
|
15827
15892
|
signals.files.push("package.json");
|
|
15828
15893
|
try {
|
|
15829
|
-
const pkg = JSON.parse((0,
|
|
15894
|
+
const pkg = JSON.parse((0, import_fs23.readFileSync)(pkgPath, "utf-8"));
|
|
15830
15895
|
signals.dependencies = [
|
|
15831
15896
|
...Object.keys(pkg.dependencies || {}),
|
|
15832
15897
|
...Object.keys(pkg.devDependencies || {})
|
|
@@ -15836,18 +15901,18 @@ var init_project_initializer = __esm({
|
|
|
15836
15901
|
if (!signals.language) signals.language = "JavaScript";
|
|
15837
15902
|
}
|
|
15838
15903
|
for (const dir of SIGNAL_DIRS) {
|
|
15839
|
-
const p = (0,
|
|
15904
|
+
const p = (0, import_path25.join)(absRoot, dir);
|
|
15840
15905
|
if (this.safeExists(absRoot, p) && this.isDir(p)) signals.directories.push(`${dir}/`);
|
|
15841
15906
|
}
|
|
15842
|
-
const wfPath = (0,
|
|
15907
|
+
const wfPath = (0, import_path25.join)(absRoot, ".github", "workflows");
|
|
15843
15908
|
if (this.safeExists(absRoot, wfPath) && this.isDir(wfPath)) {
|
|
15844
15909
|
signals.directories.push(".github/workflows/");
|
|
15845
15910
|
}
|
|
15846
15911
|
for (const file2 of SIGNAL_FILES) {
|
|
15847
|
-
if (this.safeExists(absRoot, (0,
|
|
15912
|
+
if (this.safeExists(absRoot, (0, import_path25.join)(absRoot, file2))) signals.files.push(file2);
|
|
15848
15913
|
}
|
|
15849
15914
|
for (const file2 of Object.keys(LANG_FILES)) {
|
|
15850
|
-
if (this.safeExists(absRoot, (0,
|
|
15915
|
+
if (this.safeExists(absRoot, (0, import_path25.join)(absRoot, file2))) signals.files.push(file2);
|
|
15851
15916
|
}
|
|
15852
15917
|
return signals;
|
|
15853
15918
|
}
|
|
@@ -15865,7 +15930,8 @@ var init_project_initializer = __esm({
|
|
|
15865
15930
|
for (const p of ["google", "anthropic", "openai"]) {
|
|
15866
15931
|
if (await this.config.keyProvider(p)) providers.push(p);
|
|
15867
15932
|
}
|
|
15868
|
-
|
|
15933
|
+
const hostIsClaudeCode = process.env.CLAUDECODE === "1" || !!process.env.CLAUDE_CODE_ENTRYPOINT;
|
|
15934
|
+
if (!providers.length && !hostIsClaudeCode) {
|
|
15869
15935
|
return { text: "No API keys available. Run gossipcat setup to configure providers." };
|
|
15870
15936
|
}
|
|
15871
15937
|
const catalog = new ArchetypeCatalog(this.config.catalogPath);
|
|
@@ -15877,11 +15943,14 @@ var init_project_initializer = __esm({
|
|
|
15877
15943
|
anthropic: { best: "claude-opus-4-6", fast: "claude-sonnet-4-6", cheapest: "claude-haiku-4-5" },
|
|
15878
15944
|
openai: { best: "gpt-4o", fast: "gpt-4o", cheapest: "gpt-4o-mini" }
|
|
15879
15945
|
};
|
|
15880
|
-
const availableModels =
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
|
|
15946
|
+
const availableModels = [
|
|
15947
|
+
...hostIsClaudeCode ? ["none: none (native Claude Code orchestration \u2014 no API key needed, preferred for main_agent on this host)"] : [],
|
|
15948
|
+
...providers.map((p) => {
|
|
15949
|
+
const tiers = MODEL_TIERS[p];
|
|
15950
|
+
if (!tiers) return `${p}: (use any available model)`;
|
|
15951
|
+
return `${p}: ${tiers.best} (best), ${tiers.fast} (fast), ${tiers.cheapest} (cheapest)`;
|
|
15952
|
+
})
|
|
15953
|
+
].join("\n");
|
|
15885
15954
|
const brainstormCtx = signals.brainstormContext;
|
|
15886
15955
|
const systemPrompt = `You are configuring an agent team for a software project.
|
|
15887
15956
|
|
|
@@ -15928,7 +15997,7 @@ You may add additional skills from the table above based on project needs. Do NO
|
|
|
15928
15997
|
- Pick the best archetype and customize roles for this specific project
|
|
15929
15998
|
- Use ONLY the exact model names listed above
|
|
15930
15999
|
- Choose models based on project complexity: simple \u2192 "fast" for all, complex \u2192 "best" for critical roles
|
|
15931
|
-
- For the main_agent (orchestrator), use the "best" model from the primary provider
|
|
16000
|
+
- For the main_agent (orchestrator): ${hostIsClaudeCode ? 'PREFER { "provider": "none", "model": "none" } \u2014 native Claude Code orchestration needs no API key and is the zero-config default on this host. Only pick a keyed provider if the user explicitly asks for one.' : 'use the "best" model from the primary provider'}
|
|
15932
16001
|
- Do NOT include agent IDs \u2014 the system generates them automatically
|
|
15933
16002
|
- **Scale team size to project complexity.** Simple (single-page app, script, simple game) \u2192 1-2 agents. Medium \u2192 2-3. Complex multi-module \u2192 4-5. NEVER duplicate roles.
|
|
15934
16003
|
- Max 5 agents, prefer fewer. Every agent costs money.
|
|
@@ -15979,13 +16048,13 @@ ${agentList}`,
|
|
|
15979
16048
|
}
|
|
15980
16049
|
async writeConfig(projectRoot) {
|
|
15981
16050
|
if (!this.pendingProposal) throw new Error("No pending proposal to write");
|
|
15982
|
-
const gossipDir2 = (0,
|
|
15983
|
-
if (!(0,
|
|
16051
|
+
const gossipDir2 = (0, import_path25.join)(projectRoot, ".gossip");
|
|
16052
|
+
if (!(0, import_fs23.existsSync)(gossipDir2)) (0, import_fs23.mkdirSync)(gossipDir2, { recursive: true });
|
|
15984
16053
|
const agents = {};
|
|
15985
16054
|
for (const a of this.pendingProposal.agents || []) {
|
|
15986
16055
|
agents[a.id] = { provider: a.provider, model: a.model, preset: a.preset, skills: a.skills || [] };
|
|
15987
|
-
const agentDir = (0,
|
|
15988
|
-
if (!(0,
|
|
16056
|
+
const agentDir = (0, import_path25.join)(gossipDir2, "agents", a.id);
|
|
16057
|
+
if (!(0, import_fs23.existsSync)(agentDir)) (0, import_fs23.mkdirSync)(agentDir, { recursive: true });
|
|
15989
16058
|
}
|
|
15990
16059
|
const config2 = {
|
|
15991
16060
|
main_agent: this.pendingProposal.main_agent,
|
|
@@ -15996,20 +16065,20 @@ ${agentList}`,
|
|
|
15996
16065
|
},
|
|
15997
16066
|
agents
|
|
15998
16067
|
};
|
|
15999
|
-
(0,
|
|
16068
|
+
(0, import_fs23.writeFileSync)((0, import_path25.join)(gossipDir2, "config.json"), JSON.stringify(config2, null, 2));
|
|
16000
16069
|
}
|
|
16001
16070
|
safeExists(root, target) {
|
|
16002
|
-
const resolved = (0,
|
|
16071
|
+
const resolved = (0, import_path25.resolve)(target);
|
|
16003
16072
|
if (!resolved.startsWith(root)) return false;
|
|
16004
16073
|
try {
|
|
16005
|
-
return !(0,
|
|
16074
|
+
return !(0, import_fs23.lstatSync)(resolved).isSymbolicLink();
|
|
16006
16075
|
} catch {
|
|
16007
16076
|
return false;
|
|
16008
16077
|
}
|
|
16009
16078
|
}
|
|
16010
16079
|
isDir(target) {
|
|
16011
16080
|
try {
|
|
16012
|
-
return (0,
|
|
16081
|
+
return (0, import_fs23.lstatSync)(target).isDirectory();
|
|
16013
16082
|
} catch {
|
|
16014
16083
|
return false;
|
|
16015
16084
|
}
|
|
@@ -16019,12 +16088,12 @@ ${agentList}`,
|
|
|
16019
16088
|
});
|
|
16020
16089
|
|
|
16021
16090
|
// packages/orchestrator/src/team-manager.ts
|
|
16022
|
-
var
|
|
16091
|
+
var import_fs24, import_path26, TeamManager;
|
|
16023
16092
|
var init_team_manager = __esm({
|
|
16024
16093
|
"packages/orchestrator/src/team-manager.ts"() {
|
|
16025
16094
|
"use strict";
|
|
16026
|
-
|
|
16027
|
-
|
|
16095
|
+
import_fs24 = require("fs");
|
|
16096
|
+
import_path26 = require("path");
|
|
16028
16097
|
TeamManager = class {
|
|
16029
16098
|
registry;
|
|
16030
16099
|
pipeline;
|
|
@@ -16080,8 +16149,8 @@ var init_team_manager = __esm({
|
|
|
16080
16149
|
applyAdd(config2) {
|
|
16081
16150
|
this.registry.register(config2);
|
|
16082
16151
|
this.writeConfig();
|
|
16083
|
-
const dir = (0,
|
|
16084
|
-
if (!(0,
|
|
16152
|
+
const dir = (0, import_path26.join)(this.projectRoot, ".gossip", "agents", config2.id);
|
|
16153
|
+
if (!(0, import_fs24.existsSync)(dir)) (0, import_fs24.mkdirSync)(dir, { recursive: true });
|
|
16085
16154
|
this.pendingAction = null;
|
|
16086
16155
|
}
|
|
16087
16156
|
applyRemove(agentId) {
|
|
@@ -16115,11 +16184,11 @@ var init_team_manager = __esm({
|
|
|
16115
16184
|
};
|
|
16116
16185
|
}
|
|
16117
16186
|
writeConfig() {
|
|
16118
|
-
const configPath = (0,
|
|
16187
|
+
const configPath = (0, import_path26.join)(this.projectRoot, ".gossip", "config.json");
|
|
16119
16188
|
let existing = {};
|
|
16120
|
-
if ((0,
|
|
16189
|
+
if ((0, import_fs24.existsSync)(configPath)) {
|
|
16121
16190
|
try {
|
|
16122
|
-
existing = JSON.parse((0,
|
|
16191
|
+
existing = JSON.parse((0, import_fs24.readFileSync)(configPath, "utf-8"));
|
|
16123
16192
|
} catch {
|
|
16124
16193
|
}
|
|
16125
16194
|
}
|
|
@@ -16131,9 +16200,9 @@ var init_team_manager = __esm({
|
|
|
16131
16200
|
...a.preset ? { preset: a.preset } : {},
|
|
16132
16201
|
skills: a.skills
|
|
16133
16202
|
}));
|
|
16134
|
-
const dir = (0,
|
|
16135
|
-
if (!(0,
|
|
16136
|
-
(0,
|
|
16203
|
+
const dir = (0, import_path26.join)(this.projectRoot, ".gossip");
|
|
16204
|
+
if (!(0, import_fs24.existsSync)(dir)) (0, import_fs24.mkdirSync)(dir, { recursive: true });
|
|
16205
|
+
(0, import_fs24.writeFileSync)(configPath, JSON.stringify(existing, null, 2) + "\n");
|
|
16137
16206
|
}
|
|
16138
16207
|
};
|
|
16139
16208
|
}
|
|
@@ -16355,7 +16424,7 @@ message: Your question?
|
|
|
16355
16424
|
}
|
|
16356
16425
|
/** Start all worker agents (connect to relay) */
|
|
16357
16426
|
async start() {
|
|
16358
|
-
const { existsSync:
|
|
16427
|
+
const { existsSync: existsSync43, readFileSync: readFileSync40 } = await import("fs");
|
|
16359
16428
|
const { join: join48 } = await import("path");
|
|
16360
16429
|
for (const config2 of this.registry.getAll()) {
|
|
16361
16430
|
if (config2.native) continue;
|
|
@@ -16366,7 +16435,7 @@ message: Your question?
|
|
|
16366
16435
|
}
|
|
16367
16436
|
const llm = createProvider(config2.provider, config2.model, apiKey);
|
|
16368
16437
|
const instructionsPath = join48(this.projectRoot, ".gossip", "agents", config2.id, "instructions.md");
|
|
16369
|
-
const instructions =
|
|
16438
|
+
const instructions = existsSync43(instructionsPath) ? readFileSync40(instructionsPath, "utf-8") : void 0;
|
|
16370
16439
|
const enableWebSearch = config2.preset === "researcher" || config2.skills.includes("research");
|
|
16371
16440
|
const worker = new WorkerAgent(config2.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
|
|
16372
16441
|
await worker.start();
|
|
@@ -16548,7 +16617,7 @@ message: Your question?
|
|
|
16548
16617
|
this.registry.register(config2);
|
|
16549
16618
|
}
|
|
16550
16619
|
async syncWorkers(keyProvider) {
|
|
16551
|
-
const { existsSync:
|
|
16620
|
+
const { existsSync: existsSync43, readFileSync: readFileSync40 } = await import("fs");
|
|
16552
16621
|
const { join: join48 } = await import("path");
|
|
16553
16622
|
let added = 0;
|
|
16554
16623
|
for (const ac of this.registry.getAll()) {
|
|
@@ -16557,7 +16626,7 @@ message: Your question?
|
|
|
16557
16626
|
const key = await keyProvider(ac.provider);
|
|
16558
16627
|
const llm = createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
|
|
16559
16628
|
const instructionsPath = join48(this.projectRoot, ".gossip", "agents", ac.id, "instructions.md");
|
|
16560
|
-
const instructions =
|
|
16629
|
+
const instructions = existsSync43(instructionsPath) ? readFileSync40(instructionsPath, "utf-8") : void 0;
|
|
16561
16630
|
const enableWebSearch = ac.preset === "researcher" || ac.skills.includes("research");
|
|
16562
16631
|
const worker = new WorkerAgent(ac.id, llm, this.relayUrl, ALL_TOOLS, instructions, enableWebSearch, this.relayApiKey);
|
|
16563
16632
|
await worker.start();
|
|
@@ -17078,12 +17147,12 @@ var init_consensus_types = __esm({
|
|
|
17078
17147
|
});
|
|
17079
17148
|
|
|
17080
17149
|
// packages/orchestrator/src/skill-index.ts
|
|
17081
|
-
var
|
|
17150
|
+
var import_fs25, import_path27, DANGEROUS_KEYS, SkillIndex;
|
|
17082
17151
|
var init_skill_index = __esm({
|
|
17083
17152
|
"packages/orchestrator/src/skill-index.ts"() {
|
|
17084
17153
|
"use strict";
|
|
17085
|
-
|
|
17086
|
-
|
|
17154
|
+
import_fs25 = require("fs");
|
|
17155
|
+
import_path27 = require("path");
|
|
17087
17156
|
init_skill_name();
|
|
17088
17157
|
DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype", "_project"]);
|
|
17089
17158
|
SkillIndex = class {
|
|
@@ -17092,7 +17161,7 @@ var init_skill_index = __esm({
|
|
|
17092
17161
|
dirty = false;
|
|
17093
17162
|
_exists = false;
|
|
17094
17163
|
constructor(projectRoot) {
|
|
17095
|
-
this.filePath = (0,
|
|
17164
|
+
this.filePath = (0, import_path27.join)(projectRoot, ".gossip", "skill-index.json");
|
|
17096
17165
|
this.load();
|
|
17097
17166
|
}
|
|
17098
17167
|
/** Bind a skill to an agent (creates or updates the slot) */
|
|
@@ -17284,7 +17353,7 @@ var init_skill_index = __esm({
|
|
|
17284
17353
|
}
|
|
17285
17354
|
load() {
|
|
17286
17355
|
try {
|
|
17287
|
-
const raw = (0,
|
|
17356
|
+
const raw = (0, import_fs25.readFileSync)(this.filePath, "utf-8");
|
|
17288
17357
|
const parsed = JSON.parse(raw);
|
|
17289
17358
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
17290
17359
|
for (const key of Object.keys(parsed)) {
|
|
@@ -17306,9 +17375,9 @@ var init_skill_index = __esm({
|
|
|
17306
17375
|
}
|
|
17307
17376
|
save() {
|
|
17308
17377
|
if (!this.dirty) return;
|
|
17309
|
-
const dir = (0,
|
|
17310
|
-
(0,
|
|
17311
|
-
(0,
|
|
17378
|
+
const dir = (0, import_path27.dirname)(this.filePath);
|
|
17379
|
+
(0, import_fs25.mkdirSync)(dir, { recursive: true });
|
|
17380
|
+
(0, import_fs25.writeFileSync)(this.filePath, JSON.stringify(this.data, null, 2) + "\n");
|
|
17312
17381
|
this._exists = true;
|
|
17313
17382
|
this.dirty = false;
|
|
17314
17383
|
}
|
|
@@ -17323,12 +17392,12 @@ function safeId(value) {
|
|
|
17323
17392
|
}
|
|
17324
17393
|
return encodeURIComponent(value);
|
|
17325
17394
|
}
|
|
17326
|
-
var
|
|
17395
|
+
var import_fs26, import_path28, TaskGraphSync;
|
|
17327
17396
|
var init_task_graph_sync = __esm({
|
|
17328
17397
|
"packages/orchestrator/src/task-graph-sync.ts"() {
|
|
17329
17398
|
"use strict";
|
|
17330
|
-
|
|
17331
|
-
|
|
17399
|
+
import_fs26 = require("fs");
|
|
17400
|
+
import_path28 = require("path");
|
|
17332
17401
|
TaskGraphSync = class {
|
|
17333
17402
|
constructor(graph, supabaseUrl, supabaseKey, userId, projectId, projectRoot, displayName, migration) {
|
|
17334
17403
|
this.graph = graph;
|
|
@@ -17338,7 +17407,7 @@ var init_task_graph_sync = __esm({
|
|
|
17338
17407
|
this.projectId = projectId;
|
|
17339
17408
|
this.displayName = displayName;
|
|
17340
17409
|
this.migration = migration;
|
|
17341
|
-
this.gossipDir = (0,
|
|
17410
|
+
this.gossipDir = (0, import_path28.join)(projectRoot, ".gossip");
|
|
17342
17411
|
}
|
|
17343
17412
|
gossipDir;
|
|
17344
17413
|
migrationDone = false;
|
|
@@ -17461,9 +17530,9 @@ var init_task_graph_sync = __esm({
|
|
|
17461
17530
|
});
|
|
17462
17531
|
}
|
|
17463
17532
|
async syncAgentScores() {
|
|
17464
|
-
const perfPath = (0,
|
|
17465
|
-
if (!(0,
|
|
17466
|
-
const content = (0,
|
|
17533
|
+
const perfPath = (0, import_path28.join)(this.gossipDir, "agent-performance.jsonl");
|
|
17534
|
+
if (!(0, import_fs26.existsSync)(perfPath)) return 0;
|
|
17535
|
+
const content = (0, import_fs26.readFileSync)(perfPath, "utf-8");
|
|
17467
17536
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
17468
17537
|
const meta3 = this.graph.getSyncMeta();
|
|
17469
17538
|
let synced = 0;
|
|
@@ -17610,61 +17679,61 @@ Return JSON: { "<agentId>": "<summary>", ... }`
|
|
|
17610
17679
|
// packages/orchestrator/src/rules-loader.ts
|
|
17611
17680
|
function findBundledRules() {
|
|
17612
17681
|
const candidates = [
|
|
17613
|
-
(0,
|
|
17614
|
-
(0,
|
|
17615
|
-
(0,
|
|
17682
|
+
(0, import_path29.resolve)(__dirname, "default-rules", "gossipcat-rules.md"),
|
|
17683
|
+
(0, import_path29.resolve)(__dirname, "..", "default-rules", "gossipcat-rules.md"),
|
|
17684
|
+
(0, import_path29.resolve)(process.cwd(), "packages", "orchestrator", "src", "default-rules", "gossipcat-rules.md")
|
|
17616
17685
|
];
|
|
17617
17686
|
for (const p of candidates) {
|
|
17618
|
-
if ((0,
|
|
17687
|
+
if ((0, import_fs27.existsSync)(p)) return p;
|
|
17619
17688
|
}
|
|
17620
17689
|
return null;
|
|
17621
17690
|
}
|
|
17622
17691
|
function ensureRulesFile(projectRoot) {
|
|
17623
|
-
const target = (0,
|
|
17624
|
-
if ((0,
|
|
17692
|
+
const target = (0, import_path29.join)(projectRoot, ".gossip", "rules.md");
|
|
17693
|
+
if ((0, import_fs27.existsSync)(target)) return { created: false, path: target };
|
|
17625
17694
|
const bundled = findBundledRules();
|
|
17626
17695
|
if (!bundled) return { created: false, path: null };
|
|
17627
17696
|
try {
|
|
17628
|
-
(0,
|
|
17629
|
-
(0,
|
|
17697
|
+
(0, import_fs27.mkdirSync)((0, import_path29.dirname)(target), { recursive: true });
|
|
17698
|
+
(0, import_fs27.copyFileSync)(bundled, target);
|
|
17630
17699
|
return { created: true, path: target };
|
|
17631
17700
|
} catch {
|
|
17632
17701
|
return { created: false, path: null };
|
|
17633
17702
|
}
|
|
17634
17703
|
}
|
|
17635
17704
|
function readRulesContent(projectRoot) {
|
|
17636
|
-
const local = (0,
|
|
17637
|
-
if ((0,
|
|
17705
|
+
const local = (0, import_path29.join)(projectRoot, ".gossip", "rules.md");
|
|
17706
|
+
if ((0, import_fs27.existsSync)(local)) {
|
|
17638
17707
|
try {
|
|
17639
|
-
return (0,
|
|
17708
|
+
return (0, import_fs27.readFileSync)(local, "utf-8");
|
|
17640
17709
|
} catch {
|
|
17641
17710
|
}
|
|
17642
17711
|
}
|
|
17643
17712
|
const bundled = findBundledRules();
|
|
17644
17713
|
if (bundled) {
|
|
17645
17714
|
try {
|
|
17646
|
-
return (0,
|
|
17715
|
+
return (0, import_fs27.readFileSync)(bundled, "utf-8");
|
|
17647
17716
|
} catch {
|
|
17648
17717
|
}
|
|
17649
17718
|
}
|
|
17650
17719
|
return null;
|
|
17651
17720
|
}
|
|
17652
|
-
var
|
|
17721
|
+
var import_fs27, import_path29;
|
|
17653
17722
|
var init_rules_loader = __esm({
|
|
17654
17723
|
"packages/orchestrator/src/rules-loader.ts"() {
|
|
17655
17724
|
"use strict";
|
|
17656
|
-
|
|
17657
|
-
|
|
17725
|
+
import_fs27 = require("fs");
|
|
17726
|
+
import_path29 = require("path");
|
|
17658
17727
|
}
|
|
17659
17728
|
});
|
|
17660
17729
|
|
|
17661
17730
|
// packages/orchestrator/src/bootstrap.ts
|
|
17662
|
-
var
|
|
17731
|
+
var import_fs28, import_path30, log6, BootstrapGenerator;
|
|
17663
17732
|
var init_bootstrap = __esm({
|
|
17664
17733
|
"packages/orchestrator/src/bootstrap.ts"() {
|
|
17665
17734
|
"use strict";
|
|
17666
|
-
|
|
17667
|
-
|
|
17735
|
+
import_fs28 = require("fs");
|
|
17736
|
+
import_path30 = require("path");
|
|
17668
17737
|
init_rules_loader();
|
|
17669
17738
|
log6 = (msg) => process.stderr.write(`[gossipcat] ${msg}
|
|
17670
17739
|
`);
|
|
@@ -17687,23 +17756,23 @@ var init_bootstrap = __esm({
|
|
|
17687
17756
|
};
|
|
17688
17757
|
}
|
|
17689
17758
|
migrateConfig() {
|
|
17690
|
-
const oldPath = (0,
|
|
17691
|
-
const newPath = (0,
|
|
17692
|
-
if (!(0,
|
|
17693
|
-
(0,
|
|
17694
|
-
(0,
|
|
17759
|
+
const oldPath = (0, import_path30.resolve)(this.projectRoot, "gossip.agents.json");
|
|
17760
|
+
const newPath = (0, import_path30.resolve)(this.projectRoot, ".gossip", "config.json");
|
|
17761
|
+
if (!(0, import_fs28.existsSync)(newPath) && (0, import_fs28.existsSync)(oldPath)) {
|
|
17762
|
+
(0, import_fs28.mkdirSync)((0, import_path30.resolve)(this.projectRoot, ".gossip"), { recursive: true });
|
|
17763
|
+
(0, import_fs28.copyFileSync)(oldPath, newPath);
|
|
17695
17764
|
log6("Migrated config to .gossip/config.json \u2014 gossip.agents.json is now ignored.");
|
|
17696
17765
|
}
|
|
17697
17766
|
}
|
|
17698
17767
|
loadConfig() {
|
|
17699
17768
|
const paths = [
|
|
17700
|
-
(0,
|
|
17701
|
-
(0,
|
|
17769
|
+
(0, import_path30.resolve)(this.projectRoot, ".gossip", "config.json"),
|
|
17770
|
+
(0, import_path30.resolve)(this.projectRoot, "gossip.agents.json")
|
|
17702
17771
|
];
|
|
17703
17772
|
for (const p of paths) {
|
|
17704
|
-
if ((0,
|
|
17773
|
+
if ((0, import_fs28.existsSync)(p)) {
|
|
17705
17774
|
try {
|
|
17706
|
-
return JSON.parse((0,
|
|
17775
|
+
return JSON.parse((0, import_fs28.readFileSync)(p, "utf-8"));
|
|
17707
17776
|
} catch {
|
|
17708
17777
|
log6("Config parse error, falling back to setup mode");
|
|
17709
17778
|
return null;
|
|
@@ -17724,9 +17793,9 @@ var init_bootstrap = __esm({
|
|
|
17724
17793
|
skills: ac.skills || [],
|
|
17725
17794
|
taskCount: 0
|
|
17726
17795
|
};
|
|
17727
|
-
const tasksPath = (0,
|
|
17728
|
-
if ((0,
|
|
17729
|
-
const lines = (0,
|
|
17796
|
+
const tasksPath = (0, import_path30.join)(this.projectRoot, ".gossip", "agents", id, "memory", "tasks.jsonl");
|
|
17797
|
+
if ((0, import_fs28.existsSync)(tasksPath)) {
|
|
17798
|
+
const lines = (0, import_fs28.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
17730
17799
|
let count = 0;
|
|
17731
17800
|
let lastTs = "";
|
|
17732
17801
|
for (const line of lines) {
|
|
@@ -17740,9 +17809,9 @@ var init_bootstrap = __esm({
|
|
|
17740
17809
|
summary.taskCount = count;
|
|
17741
17810
|
if (lastTs) summary.lastActive = lastTs.split("T")[0];
|
|
17742
17811
|
}
|
|
17743
|
-
const memPath = (0,
|
|
17744
|
-
if ((0,
|
|
17745
|
-
const content = (0,
|
|
17812
|
+
const memPath = (0, import_path30.join)(this.projectRoot, ".gossip", "agents", id, "memory", "MEMORY.md");
|
|
17813
|
+
if ((0, import_fs28.existsSync)(memPath)) {
|
|
17814
|
+
const content = (0, import_fs28.readFileSync)(memPath, "utf-8").slice(0, 500);
|
|
17746
17815
|
const knowledgeLines = content.match(/- \[([^\]]+)\]/g);
|
|
17747
17816
|
if (knowledgeLines?.length) {
|
|
17748
17817
|
summary.topics = knowledgeLines.map((l) => l.replace(/- \[([^\]]+)\].*/, "$1")).join(", ");
|
|
@@ -17975,13 +18044,13 @@ Skills are auto-injected from agent config. Project-wide skills in .gossip/skill
|
|
|
17975
18044
|
* Returns the body content of the top knowledge files, capped at 2500 chars.
|
|
17976
18045
|
*/
|
|
17977
18046
|
readProjectMemory() {
|
|
17978
|
-
const knowledgeDir = (0,
|
|
17979
|
-
if (!(0,
|
|
17980
|
-
const files = (0,
|
|
18047
|
+
const knowledgeDir = (0, import_path30.join)(this.projectRoot, ".gossip", "agents", "_project", "memory", "knowledge");
|
|
18048
|
+
if (!(0, import_fs28.existsSync)(knowledgeDir)) return null;
|
|
18049
|
+
const files = (0, import_fs28.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md") && !f.endsWith("-session.md"));
|
|
17981
18050
|
if (files.length === 0) return null;
|
|
17982
18051
|
const scored = files.map((f) => {
|
|
17983
18052
|
try {
|
|
17984
|
-
const content = (0,
|
|
18053
|
+
const content = (0, import_fs28.readFileSync)((0, import_path30.join)(knowledgeDir, f), "utf-8");
|
|
17985
18054
|
const importance = parseFloat(content.match(/importance:\s*([\d.]+)/)?.[1] ?? "0.5");
|
|
17986
18055
|
const isPinned = /pinned:\s*true/i.test(content);
|
|
17987
18056
|
const tsPart = f.slice(0, 19);
|
|
@@ -18006,9 +18075,9 @@ Skills are auto-injected from agent config. Project-wide skills in .gossip/skill
|
|
|
18006
18075
|
* Annotates TODO/remaining lines where the referenced tool actually exists.
|
|
18007
18076
|
*/
|
|
18008
18077
|
verifyToolClaims(content) {
|
|
18009
|
-
const mcpPath = (0,
|
|
18010
|
-
if (!(0,
|
|
18011
|
-
const rawSource = (0,
|
|
18078
|
+
const mcpPath = (0, import_path30.join)(this.projectRoot, "apps", "cli", "src", "mcp-server-sdk.ts");
|
|
18079
|
+
if (!(0, import_fs28.existsSync)(mcpPath)) return content;
|
|
18080
|
+
const rawSource = (0, import_fs28.readFileSync)(mcpPath, "utf-8");
|
|
18012
18081
|
const source = rawSource.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, "");
|
|
18013
18082
|
const keywordRe = /TODO|remaining|deferred|needed|pending/i;
|
|
18014
18083
|
const toolRe = /gossip_\w+/;
|
|
@@ -18026,10 +18095,10 @@ Skills are auto-injected from agent config. Project-wide skills in .gossip/skill
|
|
|
18026
18095
|
}
|
|
18027
18096
|
/** Read .gossip/next-session.md if it exists — user/orchestrator notes for the next session */
|
|
18028
18097
|
readNextSessionNotes() {
|
|
18029
|
-
const notesPath = (0,
|
|
18030
|
-
if (!(0,
|
|
18098
|
+
const notesPath = (0, import_path30.join)(this.projectRoot, ".gossip", "next-session.md");
|
|
18099
|
+
if (!(0, import_fs28.existsSync)(notesPath)) return null;
|
|
18031
18100
|
try {
|
|
18032
|
-
const content = (0,
|
|
18101
|
+
const content = (0, import_fs28.readFileSync)(notesPath, "utf-8").trim();
|
|
18033
18102
|
if (content.length === 0) return null;
|
|
18034
18103
|
return this.verifyToolClaims(content.slice(0, 3e3));
|
|
18035
18104
|
} catch {
|
|
@@ -18243,13 +18312,13 @@ var init_check_effectiveness = __esm({
|
|
|
18243
18312
|
});
|
|
18244
18313
|
|
|
18245
18314
|
// packages/orchestrator/src/skill-engine.ts
|
|
18246
|
-
var
|
|
18315
|
+
var import_fs29, import_crypto9, import_path31, SAFE_NAME, KNOWN_CATEGORIES, CATEGORY_KEYWORDS, REQUIRED_SECTIONS, BUNDLED_TEMPLATE, SkillEngine;
|
|
18247
18316
|
var init_skill_engine = __esm({
|
|
18248
18317
|
"packages/orchestrator/src/skill-engine.ts"() {
|
|
18249
18318
|
"use strict";
|
|
18250
|
-
|
|
18319
|
+
import_fs29 = require("fs");
|
|
18251
18320
|
import_crypto9 = require("crypto");
|
|
18252
|
-
|
|
18321
|
+
import_path31 = require("path");
|
|
18253
18322
|
init_skill_name();
|
|
18254
18323
|
init_check_effectiveness();
|
|
18255
18324
|
SAFE_NAME = /^[a-z0-9][a-z0-9_-]{0,62}$/;
|
|
@@ -18350,9 +18419,9 @@ NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST.
|
|
|
18350
18419
|
}
|
|
18351
18420
|
}
|
|
18352
18421
|
let projectContext = "";
|
|
18353
|
-
const bootstrapPath = (0,
|
|
18354
|
-
if ((0,
|
|
18355
|
-
projectContext = (0,
|
|
18422
|
+
const bootstrapPath = (0, import_path31.join)(this.projectRoot, ".gossip", "bootstrap.md");
|
|
18423
|
+
if ((0, import_fs29.existsSync)(bootstrapPath)) {
|
|
18424
|
+
projectContext = (0, import_fs29.readFileSync)(bootstrapPath, "utf-8").slice(0, 1500);
|
|
18356
18425
|
}
|
|
18357
18426
|
if (this.techStackCache === void 0) {
|
|
18358
18427
|
this.techStackCache = await this.detectTechStack();
|
|
@@ -18434,10 +18503,10 @@ Requirements:
|
|
|
18434
18503
|
const bound_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
18435
18504
|
cleaned = this.injectSnapshotFields(cleaned, { baseline_accuracy_correct, baseline_accuracy_hallucinated, bound_at });
|
|
18436
18505
|
const skillName = normalizeSkillName(category);
|
|
18437
|
-
const skillDir = (0,
|
|
18438
|
-
(0,
|
|
18439
|
-
const skillPath = (0,
|
|
18440
|
-
(0,
|
|
18506
|
+
const skillDir = (0, import_path31.join)(this.projectRoot, ".gossip", "agents", agentId, "skills");
|
|
18507
|
+
(0, import_fs29.mkdirSync)(skillDir, { recursive: true });
|
|
18508
|
+
const skillPath = (0, import_path31.join)(skillDir, `${skillName}.md`);
|
|
18509
|
+
(0, import_fs29.writeFileSync)(skillPath, cleaned);
|
|
18441
18510
|
return { path: skillPath, content: cleaned };
|
|
18442
18511
|
}
|
|
18443
18512
|
/**
|
|
@@ -18481,24 +18550,24 @@ ${fm}
|
|
|
18481
18550
|
}
|
|
18482
18551
|
}
|
|
18483
18552
|
loadTemplate() {
|
|
18484
|
-
const userDir = (0,
|
|
18485
|
-
if ((0,
|
|
18486
|
-
const files = (0,
|
|
18553
|
+
const userDir = (0, import_path31.join)(this.projectRoot, ".gossip", "skill-templates");
|
|
18554
|
+
if ((0, import_fs29.existsSync)(userDir)) {
|
|
18555
|
+
const files = (0, import_fs29.readdirSync)(userDir).filter((f) => f.endsWith(".md"));
|
|
18487
18556
|
if (files.length > 0) {
|
|
18488
|
-
return (0,
|
|
18557
|
+
return (0, import_fs29.readFileSync)((0, import_path31.join)(userDir, files[0]), "utf-8");
|
|
18489
18558
|
}
|
|
18490
18559
|
}
|
|
18491
18560
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
18492
|
-
const cacheBase = (0,
|
|
18493
|
-
if ((0,
|
|
18561
|
+
const cacheBase = (0, import_path31.join)(home, ".claude", "plugins", "cache", "claude-plugins-official", "superpowers");
|
|
18562
|
+
if ((0, import_fs29.existsSync)(cacheBase)) {
|
|
18494
18563
|
try {
|
|
18495
|
-
const versions = (0,
|
|
18564
|
+
const versions = (0, import_fs29.readdirSync)(cacheBase).sort().reverse();
|
|
18496
18565
|
for (const ver of versions) {
|
|
18497
|
-
const skillPath = (0,
|
|
18498
|
-
if ((0,
|
|
18499
|
-
const realPath = (0,
|
|
18500
|
-
if (realPath.startsWith((0,
|
|
18501
|
-
return (0,
|
|
18566
|
+
const skillPath = (0, import_path31.join)(cacheBase, ver, "skills", "systematic-debugging", "SKILL.md");
|
|
18567
|
+
if ((0, import_fs29.existsSync)(skillPath)) {
|
|
18568
|
+
const realPath = (0, import_fs29.realpathSync)(skillPath);
|
|
18569
|
+
if (realPath.startsWith((0, import_path31.resolve)(cacheBase))) {
|
|
18570
|
+
return (0, import_fs29.readFileSync)(realPath, "utf-8");
|
|
18502
18571
|
}
|
|
18503
18572
|
}
|
|
18504
18573
|
}
|
|
@@ -18514,20 +18583,20 @@ ${fm}
|
|
|
18514
18583
|
*/
|
|
18515
18584
|
async detectTechStack() {
|
|
18516
18585
|
const inputs = [];
|
|
18517
|
-
const pkgPaths = [(0,
|
|
18586
|
+
const pkgPaths = [(0, import_path31.join)(this.projectRoot, "package.json")];
|
|
18518
18587
|
try {
|
|
18519
|
-
const packagesDir = (0,
|
|
18520
|
-
if ((0,
|
|
18521
|
-
for (const dir of (0,
|
|
18522
|
-
const p = (0,
|
|
18523
|
-
if ((0,
|
|
18588
|
+
const packagesDir = (0, import_path31.join)(this.projectRoot, "packages");
|
|
18589
|
+
if ((0, import_fs29.existsSync)(packagesDir)) {
|
|
18590
|
+
for (const dir of (0, import_fs29.readdirSync)(packagesDir)) {
|
|
18591
|
+
const p = (0, import_path31.join)(packagesDir, dir, "package.json");
|
|
18592
|
+
if ((0, import_fs29.existsSync)(p)) pkgPaths.push(p);
|
|
18524
18593
|
}
|
|
18525
18594
|
}
|
|
18526
18595
|
} catch {
|
|
18527
18596
|
}
|
|
18528
18597
|
for (const p of pkgPaths.slice(0, 5)) {
|
|
18529
18598
|
try {
|
|
18530
|
-
const pkg = JSON.parse((0,
|
|
18599
|
+
const pkg = JSON.parse((0, import_fs29.readFileSync)(p, "utf-8"));
|
|
18531
18600
|
const deps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
|
|
18532
18601
|
if (deps.length > 0) {
|
|
18533
18602
|
inputs.push(`${p.replace(this.projectRoot + "/", "")}: ${deps.join(", ")}`);
|
|
@@ -18536,7 +18605,7 @@ ${fm}
|
|
|
18536
18605
|
}
|
|
18537
18606
|
}
|
|
18538
18607
|
try {
|
|
18539
|
-
const srcDirs = ["src", "packages", "apps", "lib"].filter((d) => (0,
|
|
18608
|
+
const srcDirs = ["src", "packages", "apps", "lib"].filter((d) => (0, import_fs29.existsSync)((0, import_path31.join)(this.projectRoot, d)));
|
|
18540
18609
|
inputs.push(`Source dirs: ${srcDirs.join(", ") || "root"}`);
|
|
18541
18610
|
} catch {
|
|
18542
18611
|
}
|
|
@@ -18563,10 +18632,10 @@ ${inputs.join("\n")}
|
|
|
18563
18632
|
}
|
|
18564
18633
|
}
|
|
18565
18634
|
loadCategoryFindings(category) {
|
|
18566
|
-
const filePath = (0,
|
|
18567
|
-
if (!(0,
|
|
18635
|
+
const filePath = (0, import_path31.join)(this.projectRoot, ".gossip", "agent-performance.jsonl");
|
|
18636
|
+
if (!(0, import_fs29.existsSync)(filePath)) return [];
|
|
18568
18637
|
try {
|
|
18569
|
-
return (0,
|
|
18638
|
+
return (0, import_fs29.readFileSync)(filePath, "utf-8").trim().split("\n").filter(Boolean).map((line) => {
|
|
18570
18639
|
try {
|
|
18571
18640
|
return JSON.parse(line);
|
|
18572
18641
|
} catch {
|
|
@@ -18596,10 +18665,10 @@ ${inputs.join("\n")}
|
|
|
18596
18665
|
return { status: "pending", shouldUpdate: false };
|
|
18597
18666
|
}
|
|
18598
18667
|
const skillPath = this.resolveSkillPath(agentId, category);
|
|
18599
|
-
if (!(0,
|
|
18668
|
+
if (!(0, import_fs29.existsSync)(skillPath)) {
|
|
18600
18669
|
return { status: "pending", shouldUpdate: false };
|
|
18601
18670
|
}
|
|
18602
|
-
const raw = (0,
|
|
18671
|
+
const raw = (0, import_fs29.readFileSync)(skillPath, "utf-8");
|
|
18603
18672
|
const { frontmatter: rawFrontmatter, body } = this.parseSkillFile(raw);
|
|
18604
18673
|
const nowMs = Date.now();
|
|
18605
18674
|
const { frontmatter, mutated } = this.migrateIfNeeded(
|
|
@@ -18677,7 +18746,7 @@ ${inputs.join("\n")}
|
|
|
18677
18746
|
*/
|
|
18678
18747
|
resolveSkillPath(agentId, category) {
|
|
18679
18748
|
const skillName = normalizeSkillName(category);
|
|
18680
|
-
return (0,
|
|
18749
|
+
return (0, import_path31.join)(this.projectRoot, ".gossip", "agents", agentId, "skills", `${skillName}.md`);
|
|
18681
18750
|
}
|
|
18682
18751
|
/**
|
|
18683
18752
|
* Splits a skill file into its frontmatter key-value map and the body text
|
|
@@ -18765,11 +18834,11 @@ ${fmLines.join("\n")}
|
|
|
18765
18834
|
---${body}`;
|
|
18766
18835
|
const tmpPath = `${skillPath}.tmp.${process.pid}.${(0, import_crypto9.randomBytes)(4).toString("hex")}`;
|
|
18767
18836
|
try {
|
|
18768
|
-
(0,
|
|
18769
|
-
(0,
|
|
18837
|
+
(0, import_fs29.writeFileSync)(tmpPath, content, "utf-8");
|
|
18838
|
+
(0, import_fs29.renameSync)(tmpPath, skillPath);
|
|
18770
18839
|
} catch (err) {
|
|
18771
18840
|
try {
|
|
18772
|
-
(0,
|
|
18841
|
+
(0, import_fs29.unlinkSync)(tmpPath);
|
|
18773
18842
|
} catch {
|
|
18774
18843
|
}
|
|
18775
18844
|
throw err;
|
|
@@ -18780,12 +18849,12 @@ ${fmLines.join("\n")}
|
|
|
18780
18849
|
});
|
|
18781
18850
|
|
|
18782
18851
|
// packages/orchestrator/src/memory-searcher.ts
|
|
18783
|
-
var
|
|
18852
|
+
var import_fs30, import_path32, MAX_QUERY_LENGTH, MAX_KEYWORDS, MAX_TASK_FILE_BYTES, MemorySearcher;
|
|
18784
18853
|
var init_memory_searcher = __esm({
|
|
18785
18854
|
"packages/orchestrator/src/memory-searcher.ts"() {
|
|
18786
18855
|
"use strict";
|
|
18787
|
-
|
|
18788
|
-
|
|
18856
|
+
import_fs30 = require("fs");
|
|
18857
|
+
import_path32 = require("path");
|
|
18789
18858
|
MAX_QUERY_LENGTH = 500;
|
|
18790
18859
|
MAX_KEYWORDS = 20;
|
|
18791
18860
|
MAX_TASK_FILE_BYTES = 2 * 1024 * 1024;
|
|
@@ -18800,19 +18869,19 @@ var init_memory_searcher = __esm({
|
|
|
18800
18869
|
const limit = Math.min(maxResults, 10);
|
|
18801
18870
|
const keywords = this.extractKeywords(safeQuery);
|
|
18802
18871
|
if (keywords.length === 0) return [];
|
|
18803
|
-
const memDir = (0,
|
|
18804
|
-
if (!(0,
|
|
18872
|
+
const memDir = (0, import_path32.join)(this.projectRoot, ".gossip", "agents", agentId, "memory");
|
|
18873
|
+
if (!(0, import_fs30.existsSync)(memDir)) return [];
|
|
18805
18874
|
const results = [];
|
|
18806
|
-
const knowledgeDir = (0,
|
|
18807
|
-
if ((0,
|
|
18808
|
-
const files = (0,
|
|
18875
|
+
const knowledgeDir = (0, import_path32.join)(memDir, "knowledge");
|
|
18876
|
+
if ((0, import_fs30.existsSync)(knowledgeDir)) {
|
|
18877
|
+
const files = (0, import_fs30.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
|
|
18809
18878
|
for (const file2 of files) {
|
|
18810
|
-
const filePath = (0,
|
|
18879
|
+
const filePath = (0, import_path32.join)(knowledgeDir, file2);
|
|
18811
18880
|
try {
|
|
18812
|
-
const content = (0,
|
|
18881
|
+
const content = (0, import_fs30.readFileSync)(filePath, "utf-8");
|
|
18813
18882
|
const frontmatter = this.parseFrontmatter(content);
|
|
18814
18883
|
const body = content.replace(/^---[\s\S]*?---\n*/, "");
|
|
18815
|
-
const name = frontmatter?.name || (0,
|
|
18884
|
+
const name = frontmatter?.name || (0, import_path32.basename)(file2, ".md");
|
|
18816
18885
|
const description = frontmatter?.description || "";
|
|
18817
18886
|
const importance = frontmatter?.importance ?? 0.5;
|
|
18818
18887
|
const score = this.scoreContent(keywords, name, description, body, importance);
|
|
@@ -18829,12 +18898,12 @@ var init_memory_searcher = __esm({
|
|
|
18829
18898
|
}
|
|
18830
18899
|
}
|
|
18831
18900
|
}
|
|
18832
|
-
const tasksPath = (0,
|
|
18833
|
-
if ((0,
|
|
18901
|
+
const tasksPath = (0, import_path32.join)(memDir, "tasks.jsonl");
|
|
18902
|
+
if ((0, import_fs30.existsSync)(tasksPath)) {
|
|
18834
18903
|
try {
|
|
18835
|
-
const stat3 = (0,
|
|
18904
|
+
const stat3 = (0, import_fs30.statSync)(tasksPath);
|
|
18836
18905
|
if (stat3.size > MAX_TASK_FILE_BYTES) return results.sort((a, b) => b.score - a.score).slice(0, limit);
|
|
18837
|
-
const lines = (0,
|
|
18906
|
+
const lines = (0, import_fs30.readFileSync)(tasksPath, "utf-8").split("\n").filter((l) => l.trim());
|
|
18838
18907
|
for (const line of lines) {
|
|
18839
18908
|
try {
|
|
18840
18909
|
const entry = JSON.parse(line);
|
|
@@ -19120,9 +19189,9 @@ function prependScopeNote(prompt) {
|
|
|
19120
19189
|
}
|
|
19121
19190
|
function readSandboxMode(projectRoot) {
|
|
19122
19191
|
try {
|
|
19123
|
-
const p = (0,
|
|
19124
|
-
if (!(0,
|
|
19125
|
-
const raw = JSON.parse((0,
|
|
19192
|
+
const p = (0, import_path33.join)(projectRoot, ".gossip", "config.json");
|
|
19193
|
+
if (!(0, import_fs31.existsSync)(p)) return "warn";
|
|
19194
|
+
const raw = JSON.parse((0, import_fs31.readFileSync)(p, "utf-8"));
|
|
19126
19195
|
const mode = raw?.sandboxEnforcement;
|
|
19127
19196
|
if (mode === "off" || mode === "warn" || mode === "block") return mode;
|
|
19128
19197
|
return "warn";
|
|
@@ -19132,17 +19201,17 @@ function readSandboxMode(projectRoot) {
|
|
|
19132
19201
|
}
|
|
19133
19202
|
function recordDispatchMetadata(projectRoot, meta3) {
|
|
19134
19203
|
try {
|
|
19135
|
-
const dir = (0,
|
|
19136
|
-
(0,
|
|
19137
|
-
(0,
|
|
19204
|
+
const dir = (0, import_path33.join)(projectRoot, ".gossip");
|
|
19205
|
+
(0, import_fs31.mkdirSync)(dir, { recursive: true });
|
|
19206
|
+
(0, import_fs31.appendFileSync)((0, import_path33.join)(dir, METADATA_FILE), JSON.stringify(meta3) + "\n");
|
|
19138
19207
|
} catch {
|
|
19139
19208
|
}
|
|
19140
19209
|
}
|
|
19141
19210
|
function lookupDispatchMetadata(projectRoot, taskId) {
|
|
19142
19211
|
try {
|
|
19143
|
-
const p = (0,
|
|
19144
|
-
if (!(0,
|
|
19145
|
-
const raw = (0,
|
|
19212
|
+
const p = (0, import_path33.join)(projectRoot, ".gossip", METADATA_FILE);
|
|
19213
|
+
if (!(0, import_fs31.existsSync)(p)) return null;
|
|
19214
|
+
const raw = (0, import_fs31.readFileSync)(p, "utf-8");
|
|
19146
19215
|
const lines = raw.split("\n").filter(Boolean);
|
|
19147
19216
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
19148
19217
|
try {
|
|
@@ -19174,21 +19243,21 @@ function parseGitStatus(porcelain) {
|
|
|
19174
19243
|
function normalizeScope(scope, projectRoot) {
|
|
19175
19244
|
let s = scope.trim();
|
|
19176
19245
|
if (!s) return "";
|
|
19177
|
-
if ((0,
|
|
19178
|
-
s = (0,
|
|
19246
|
+
if ((0, import_path33.isAbsolute)(s)) {
|
|
19247
|
+
s = (0, import_path33.relative)(projectRoot, s);
|
|
19179
19248
|
} else if (s.startsWith("./")) {
|
|
19180
19249
|
s = s.slice(2);
|
|
19181
19250
|
}
|
|
19182
|
-
s = (0,
|
|
19251
|
+
s = (0, import_path33.normalize)(s).replace(/\/+$/, "");
|
|
19183
19252
|
if (s === "." || s === "") return "";
|
|
19184
19253
|
return s;
|
|
19185
19254
|
}
|
|
19186
19255
|
function isInsideScope(filePath, scope) {
|
|
19187
19256
|
if (!scope) return true;
|
|
19188
|
-
const f = (0,
|
|
19257
|
+
const f = (0, import_path33.normalize)(filePath).replace(/^\.\//, "");
|
|
19189
19258
|
const s = scope.replace(/^\.\//, "").replace(/\/+$/, "");
|
|
19190
19259
|
if (f === s) return true;
|
|
19191
|
-
return f.startsWith(s + "/") || f.startsWith(s +
|
|
19260
|
+
return f.startsWith(s + "/") || f.startsWith(s + import_path33.sep);
|
|
19192
19261
|
}
|
|
19193
19262
|
function detectBoundaryEscapes(meta3, modifiedFiles, projectRoot) {
|
|
19194
19263
|
const mode = meta3.writeMode;
|
|
@@ -19250,8 +19319,8 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
19250
19319
|
} catch {
|
|
19251
19320
|
}
|
|
19252
19321
|
try {
|
|
19253
|
-
const dir = (0,
|
|
19254
|
-
(0,
|
|
19322
|
+
const dir = (0, import_path33.join)(projectRoot, ".gossip");
|
|
19323
|
+
(0, import_fs31.mkdirSync)(dir, { recursive: true });
|
|
19255
19324
|
const line = {
|
|
19256
19325
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19257
19326
|
taskId: meta3.taskId,
|
|
@@ -19262,17 +19331,17 @@ function recordBoundaryEscape(projectRoot, meta3, violations, mode) {
|
|
|
19262
19331
|
action: mode
|
|
19263
19332
|
// "warn" or "block"
|
|
19264
19333
|
};
|
|
19265
|
-
(0,
|
|
19334
|
+
(0, import_fs31.appendFileSync)((0, import_path33.join)(dir, BOUNDARY_ESCAPE_FILE), JSON.stringify(line) + "\n");
|
|
19266
19335
|
} catch {
|
|
19267
19336
|
}
|
|
19268
19337
|
}
|
|
19269
|
-
var import_child_process4,
|
|
19338
|
+
var import_child_process4, import_fs31, import_path33, METADATA_FILE, BOUNDARY_ESCAPE_FILE, SYSTEM_PREFIXES, SCOPE_NOTE, __test__;
|
|
19270
19339
|
var init_sandbox2 = __esm({
|
|
19271
19340
|
"apps/cli/src/sandbox.ts"() {
|
|
19272
19341
|
"use strict";
|
|
19273
19342
|
import_child_process4 = require("child_process");
|
|
19274
|
-
|
|
19275
|
-
|
|
19343
|
+
import_fs31 = require("fs");
|
|
19344
|
+
import_path33 = require("path");
|
|
19276
19345
|
METADATA_FILE = "dispatch-metadata.jsonl";
|
|
19277
19346
|
BOUNDARY_ESCAPE_FILE = "boundary-escapes.jsonl";
|
|
19278
19347
|
SYSTEM_PREFIXES = [
|
|
@@ -19405,6 +19474,10 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
19405
19474
|
round.pendingNativeAgents.delete(agent_id);
|
|
19406
19475
|
process.stderr.write(`[gossipcat] \u{1F4E8} Cross-review received from ${agent_id}. Remaining: ${round.pendingNativeAgents.size}
|
|
19407
19476
|
`);
|
|
19477
|
+
let parsedCount = 0;
|
|
19478
|
+
let acceptedCount = 0;
|
|
19479
|
+
const rejectedPeerIds = /* @__PURE__ */ new Set();
|
|
19480
|
+
let parseError = null;
|
|
19408
19481
|
try {
|
|
19409
19482
|
const { ConsensusEngine: ConsensusEngine2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
19410
19483
|
const parseLlm = ctx.mainAgent.getLlm();
|
|
@@ -19414,14 +19487,51 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
19414
19487
|
projectRoot: process.cwd()
|
|
19415
19488
|
});
|
|
19416
19489
|
const entries = engine.parseCrossReviewResponse(agent_id, result, 50);
|
|
19490
|
+
parsedCount = entries.length;
|
|
19417
19491
|
const validPeerIds = new Set(round.allResults.map((r) => r.agentId));
|
|
19418
|
-
const filtered = entries.filter((e) =>
|
|
19492
|
+
const filtered = entries.filter((e) => {
|
|
19493
|
+
const selfReview = e.peerAgentId === agent_id;
|
|
19494
|
+
const unknownPeer = !validPeerIds.has(e.peerAgentId);
|
|
19495
|
+
if (selfReview || unknownPeer) {
|
|
19496
|
+
if (e.peerAgentId) rejectedPeerIds.add(e.peerAgentId);
|
|
19497
|
+
return false;
|
|
19498
|
+
}
|
|
19499
|
+
return true;
|
|
19500
|
+
});
|
|
19501
|
+
acceptedCount = filtered.length;
|
|
19419
19502
|
round.nativeCrossReviewEntries.push(...filtered);
|
|
19503
|
+
if (parsedCount > 0 && acceptedCount === 0) {
|
|
19504
|
+
process.stderr.write(
|
|
19505
|
+
`[gossipcat] \u26A0\uFE0F Cross-review from ${agent_id}: all ${parsedCount} entries rejected. Bad peer IDs: [${[...rejectedPeerIds].join(", ")}]. Valid round members: [${[...validPeerIds].join(", ")}]. Expected findingId format "<peerAgentId>:f<N>".
|
|
19506
|
+
`
|
|
19507
|
+
);
|
|
19508
|
+
} else if (parsedCount > acceptedCount) {
|
|
19509
|
+
process.stderr.write(
|
|
19510
|
+
`[gossipcat] \u26A0\uFE0F Cross-review from ${agent_id}: ${parsedCount - acceptedCount}/${parsedCount} entries rejected (bad peer IDs: [${[...rejectedPeerIds].join(", ")}]).
|
|
19511
|
+
`
|
|
19512
|
+
);
|
|
19513
|
+
}
|
|
19420
19514
|
} catch (err) {
|
|
19421
|
-
|
|
19515
|
+
parseError = err.message;
|
|
19516
|
+
process.stderr.write(`[gossipcat] Failed to parse cross-review from ${agent_id}: ${parseError}
|
|
19422
19517
|
`);
|
|
19423
19518
|
}
|
|
19424
19519
|
persistPendingConsensus();
|
|
19520
|
+
const validPeerList = [...new Set(round.allResults.map((r) => r.agentId))].join(", ");
|
|
19521
|
+
let diagnostic = "";
|
|
19522
|
+
if (parseError) {
|
|
19523
|
+
diagnostic = `
|
|
19524
|
+
\u26A0\uFE0F Parse error: ${parseError}`;
|
|
19525
|
+
} else if (parsedCount > 0 && acceptedCount === 0) {
|
|
19526
|
+
diagnostic = `
|
|
19527
|
+
\u26A0\uFE0F All ${parsedCount} entries were REJECTED. Bad peer IDs: [${[...rejectedPeerIds].join(", ")}]. Valid round members: [${validPeerList}]. Expected findingId format "<peerAgentId>:f<N>" using exact agent IDs from the round.`;
|
|
19528
|
+
} else if (parsedCount > acceptedCount) {
|
|
19529
|
+
diagnostic = `
|
|
19530
|
+
\u26A0\uFE0F ${parsedCount - acceptedCount}/${parsedCount} entries rejected (bad peer IDs: [${[...rejectedPeerIds].join(", ")}]). Valid round members: [${validPeerList}].`;
|
|
19531
|
+
} else if (parsedCount > 0) {
|
|
19532
|
+
diagnostic = `
|
|
19533
|
+
\u2705 ${acceptedCount}/${parsedCount} entries accepted.`;
|
|
19534
|
+
}
|
|
19425
19535
|
if (round.pendingNativeAgents.size > 0) {
|
|
19426
19536
|
const EXTENSION_MS = 6e5;
|
|
19427
19537
|
const MAX_TOTAL_MS = 36e5;
|
|
@@ -19430,7 +19540,7 @@ async function handleRelayCrossReview(consensus_id, agent_id, result) {
|
|
|
19430
19540
|
return {
|
|
19431
19541
|
content: [{
|
|
19432
19542
|
type: "text",
|
|
19433
|
-
text: `Cross-review from ${agent_id} received. Waiting for ${round.pendingNativeAgents.size} more agent(s): ${[...round.pendingNativeAgents].join(", ")}`
|
|
19543
|
+
text: `Cross-review from ${agent_id} received. Waiting for ${round.pendingNativeAgents.size} more agent(s): ${[...round.pendingNativeAgents].join(", ")}${diagnostic}`
|
|
19434
19544
|
}]
|
|
19435
19545
|
};
|
|
19436
19546
|
}
|
|
@@ -19545,10 +19655,10 @@ function persistPendingConsensus() {
|
|
|
19545
19655
|
}
|
|
19546
19656
|
function restorePendingConsensus(projectRoot) {
|
|
19547
19657
|
try {
|
|
19548
|
-
const { existsSync:
|
|
19658
|
+
const { existsSync: existsSync43, readFileSync: readFileSync40, unlinkSync: unlinkSync4 } = require("fs");
|
|
19549
19659
|
const { join: join48 } = require("path");
|
|
19550
19660
|
const filePath = join48(projectRoot, ".gossip", CONSENSUS_FILE);
|
|
19551
|
-
if (!
|
|
19661
|
+
if (!existsSync43(filePath)) return;
|
|
19552
19662
|
const raw = JSON.parse(readFileSync40(filePath, "utf-8"));
|
|
19553
19663
|
const now = Date.now();
|
|
19554
19664
|
for (const [id, data] of Object.entries(raw)) {
|
|
@@ -19592,15 +19702,15 @@ __export(check_effectiveness_runner_exports, {
|
|
|
19592
19702
|
runCheckEffectivenessForAllSkills: () => runCheckEffectivenessForAllSkills
|
|
19593
19703
|
});
|
|
19594
19704
|
async function runCheckEffectivenessForAllSkills(opts) {
|
|
19595
|
-
const baseDir = (0,
|
|
19596
|
-
if (!(0,
|
|
19597
|
-
const agentDirs = (0,
|
|
19705
|
+
const baseDir = (0, import_path35.join)(opts.projectRoot, ".gossip", "agents");
|
|
19706
|
+
if (!(0, import_fs33.existsSync)(baseDir)) return;
|
|
19707
|
+
const agentDirs = (0, import_fs33.readdirSync)(baseDir);
|
|
19598
19708
|
for (const agentId of agentDirs) {
|
|
19599
|
-
const skillsDir = (0,
|
|
19600
|
-
if (!(0,
|
|
19709
|
+
const skillsDir = (0, import_path35.join)(baseDir, agentId, "skills");
|
|
19710
|
+
if (!(0, import_fs33.existsSync)(skillsDir)) continue;
|
|
19601
19711
|
const role = opts.registryGet(agentId)?.role;
|
|
19602
19712
|
if (role === "implementer") continue;
|
|
19603
|
-
const files = (0,
|
|
19713
|
+
const files = (0, import_fs33.readdirSync)(skillsDir).filter((f) => f.endsWith(".md"));
|
|
19604
19714
|
for (const file2 of files) {
|
|
19605
19715
|
const category = file2.replace(/\.md$/, "");
|
|
19606
19716
|
try {
|
|
@@ -19621,12 +19731,12 @@ async function runCheckEffectivenessForAllSkills(opts) {
|
|
|
19621
19731
|
}
|
|
19622
19732
|
}
|
|
19623
19733
|
}
|
|
19624
|
-
var
|
|
19734
|
+
var import_fs33, import_path35;
|
|
19625
19735
|
var init_check_effectiveness_runner = __esm({
|
|
19626
19736
|
"apps/cli/src/handlers/check-effectiveness-runner.ts"() {
|
|
19627
19737
|
"use strict";
|
|
19628
|
-
|
|
19629
|
-
|
|
19738
|
+
import_fs33 = require("fs");
|
|
19739
|
+
import_path35 = require("path");
|
|
19630
19740
|
}
|
|
19631
19741
|
});
|
|
19632
19742
|
|
|
@@ -20309,12 +20419,12 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
20309
20419
|
const hourlyActivity = new Array(12).fill(0);
|
|
20310
20420
|
const now = Date.now();
|
|
20311
20421
|
const hourMs = 60 * 60 * 1e3;
|
|
20312
|
-
const graphPath = (0,
|
|
20313
|
-
if ((0,
|
|
20422
|
+
const graphPath = (0, import_path36.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
20423
|
+
if ((0, import_fs34.existsSync)(graphPath)) {
|
|
20314
20424
|
try {
|
|
20315
20425
|
const created = /* @__PURE__ */ new Map();
|
|
20316
20426
|
const finished = /* @__PURE__ */ new Set();
|
|
20317
|
-
const lines = (0,
|
|
20427
|
+
const lines = (0, import_fs34.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20318
20428
|
for (const line of lines) {
|
|
20319
20429
|
try {
|
|
20320
20430
|
const ev = JSON.parse(line);
|
|
@@ -20365,10 +20475,10 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
20365
20475
|
let lastConsensusTimestamp = "";
|
|
20366
20476
|
let actionableFindings = 0;
|
|
20367
20477
|
const consensusTaskIds = /* @__PURE__ */ new Set();
|
|
20368
|
-
const perfPath = (0,
|
|
20369
|
-
if ((0,
|
|
20478
|
+
const perfPath = (0, import_path36.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
20479
|
+
if ((0, import_fs34.existsSync)(perfPath)) {
|
|
20370
20480
|
try {
|
|
20371
|
-
const lines = (0,
|
|
20481
|
+
const lines = (0, import_fs34.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20372
20482
|
for (const line of lines) {
|
|
20373
20483
|
try {
|
|
20374
20484
|
const entry = JSON.parse(line);
|
|
@@ -20401,23 +20511,23 @@ async function overviewHandler(projectRoot, ctx2) {
|
|
|
20401
20511
|
const avgDurationMs = durationCount > 0 ? Math.round(totalDuration / durationCount) : 0;
|
|
20402
20512
|
return { agentsOnline, relayCount, relayConnected, nativeCount, consensusRuns, totalFindings, confirmedFindings, totalSignals, tasksCompleted, tasksFailed, avgDurationMs, lastConsensusTimestamp, actionableFindings, hourlyActivity };
|
|
20403
20513
|
}
|
|
20404
|
-
var
|
|
20514
|
+
var import_fs34, import_path36;
|
|
20405
20515
|
var init_api_overview = __esm({
|
|
20406
20516
|
"packages/relay/src/dashboard/api-overview.ts"() {
|
|
20407
20517
|
"use strict";
|
|
20408
|
-
|
|
20409
|
-
|
|
20518
|
+
import_fs34 = require("fs");
|
|
20519
|
+
import_path36 = require("path");
|
|
20410
20520
|
}
|
|
20411
20521
|
});
|
|
20412
20522
|
|
|
20413
20523
|
// packages/relay/src/dashboard/api-agents.ts
|
|
20414
20524
|
function readTaskGraphByAgent(projectRoot) {
|
|
20415
|
-
const taskGraphPath = (0,
|
|
20525
|
+
const taskGraphPath = (0, import_path37.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
20416
20526
|
const result = /* @__PURE__ */ new Map();
|
|
20417
|
-
if (!(0,
|
|
20527
|
+
if (!(0, import_fs35.existsSync)(taskGraphPath)) return result;
|
|
20418
20528
|
let lines;
|
|
20419
20529
|
try {
|
|
20420
|
-
lines = (0,
|
|
20530
|
+
lines = (0, import_fs35.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20421
20531
|
} catch {
|
|
20422
20532
|
return result;
|
|
20423
20533
|
}
|
|
@@ -20514,14 +20624,14 @@ async function agentsHandler(projectRoot, configs, onlineAgents = []) {
|
|
|
20514
20624
|
};
|
|
20515
20625
|
});
|
|
20516
20626
|
}
|
|
20517
|
-
var
|
|
20627
|
+
var import_fs35, import_path37, DEFAULT_SCORE;
|
|
20518
20628
|
var init_api_agents = __esm({
|
|
20519
20629
|
"packages/relay/src/dashboard/api-agents.ts"() {
|
|
20520
20630
|
"use strict";
|
|
20521
20631
|
init_performance_reader();
|
|
20522
20632
|
init_skill_index();
|
|
20523
|
-
|
|
20524
|
-
|
|
20633
|
+
import_fs35 = require("fs");
|
|
20634
|
+
import_path37 = require("path");
|
|
20525
20635
|
DEFAULT_SCORE = {
|
|
20526
20636
|
agentId: "",
|
|
20527
20637
|
accuracy: 0.5,
|
|
@@ -20545,7 +20655,7 @@ var init_api_agents = __esm({
|
|
|
20545
20655
|
|
|
20546
20656
|
// packages/relay/src/dashboard/api-skills.ts
|
|
20547
20657
|
function isCorrupt(projectRoot, index) {
|
|
20548
|
-
return (0,
|
|
20658
|
+
return (0, import_fs36.existsSync)((0, import_path38.join)(projectRoot, ".gossip", "skill-index.json")) && !index.exists();
|
|
20549
20659
|
}
|
|
20550
20660
|
async function skillsGetHandler(projectRoot) {
|
|
20551
20661
|
try {
|
|
@@ -20574,13 +20684,13 @@ async function skillsBindHandler(projectRoot, body) {
|
|
|
20574
20684
|
return { success: false, error: err instanceof Error ? err.message : "Unknown error" };
|
|
20575
20685
|
}
|
|
20576
20686
|
}
|
|
20577
|
-
var
|
|
20687
|
+
var import_fs36, import_path38, AGENT_ID_RE2;
|
|
20578
20688
|
var init_api_skills = __esm({
|
|
20579
20689
|
"packages/relay/src/dashboard/api-skills.ts"() {
|
|
20580
20690
|
"use strict";
|
|
20581
20691
|
init_skill_index();
|
|
20582
|
-
|
|
20583
|
-
|
|
20692
|
+
import_fs36 = require("fs");
|
|
20693
|
+
import_path38 = require("path");
|
|
20584
20694
|
AGENT_ID_RE2 = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
20585
20695
|
}
|
|
20586
20696
|
});
|
|
@@ -20588,25 +20698,25 @@ var init_api_skills = __esm({
|
|
|
20588
20698
|
// packages/relay/src/dashboard/api-memory.ts
|
|
20589
20699
|
async function memoryHandler(projectRoot, agentId) {
|
|
20590
20700
|
if (!agentId || !AGENT_ID_RE3.test(agentId) || DANGEROUS_IDS.has(agentId)) throw new Error("Invalid agent ID");
|
|
20591
|
-
const memDir = (0,
|
|
20701
|
+
const memDir = (0, import_path39.join)(projectRoot, ".gossip", "agents", agentId, "memory");
|
|
20592
20702
|
let index = "";
|
|
20593
|
-
const indexPath = (0,
|
|
20594
|
-
if ((0,
|
|
20703
|
+
const indexPath = (0, import_path39.join)(memDir, "MEMORY.md");
|
|
20704
|
+
if ((0, import_fs37.existsSync)(indexPath)) {
|
|
20595
20705
|
try {
|
|
20596
|
-
index = (0,
|
|
20706
|
+
index = (0, import_fs37.readFileSync)(indexPath, "utf-8");
|
|
20597
20707
|
} catch {
|
|
20598
20708
|
}
|
|
20599
20709
|
}
|
|
20600
20710
|
const knowledge = [];
|
|
20601
|
-
const knowledgeDir = (0,
|
|
20711
|
+
const knowledgeDir = (0, import_path39.join)(memDir, "knowledge");
|
|
20602
20712
|
const knowledgeDirs = [knowledgeDir, memDir];
|
|
20603
20713
|
for (const dir of knowledgeDirs) {
|
|
20604
|
-
if (!(0,
|
|
20714
|
+
if (!(0, import_fs37.existsSync)(dir)) continue;
|
|
20605
20715
|
try {
|
|
20606
|
-
const files = (0,
|
|
20716
|
+
const files = (0, import_fs37.readdirSync)(dir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md");
|
|
20607
20717
|
for (const filename of files) {
|
|
20608
20718
|
try {
|
|
20609
|
-
const raw = (0,
|
|
20719
|
+
const raw = (0, import_fs37.readFileSync)((0, import_path39.join)(dir, filename), "utf-8");
|
|
20610
20720
|
const { frontmatter, content } = parseFrontmatter(raw);
|
|
20611
20721
|
knowledge.push({ filename, frontmatter, content });
|
|
20612
20722
|
} catch {
|
|
@@ -20616,10 +20726,10 @@ async function memoryHandler(projectRoot, agentId) {
|
|
|
20616
20726
|
}
|
|
20617
20727
|
}
|
|
20618
20728
|
const tasks = [];
|
|
20619
|
-
const tasksPath = (0,
|
|
20620
|
-
if ((0,
|
|
20729
|
+
const tasksPath = (0, import_path39.join)(memDir, "tasks.jsonl");
|
|
20730
|
+
if ((0, import_fs37.existsSync)(tasksPath)) {
|
|
20621
20731
|
try {
|
|
20622
|
-
const lines = (0,
|
|
20732
|
+
const lines = (0, import_fs37.readFileSync)(tasksPath, "utf-8").trim().split("\n").filter(Boolean).slice(-200);
|
|
20623
20733
|
for (const line of lines) {
|
|
20624
20734
|
try {
|
|
20625
20735
|
tasks.push(JSON.parse(line));
|
|
@@ -20647,12 +20757,12 @@ function parseFrontmatter(raw) {
|
|
|
20647
20757
|
}
|
|
20648
20758
|
return { frontmatter: fm, content: raw.slice(end + 3).trim() };
|
|
20649
20759
|
}
|
|
20650
|
-
var
|
|
20760
|
+
var import_fs37, import_path39, AGENT_ID_RE3, DANGEROUS_IDS;
|
|
20651
20761
|
var init_api_memory = __esm({
|
|
20652
20762
|
"packages/relay/src/dashboard/api-memory.ts"() {
|
|
20653
20763
|
"use strict";
|
|
20654
|
-
|
|
20655
|
-
|
|
20764
|
+
import_fs37 = require("fs");
|
|
20765
|
+
import_path39 = require("path");
|
|
20656
20766
|
AGENT_ID_RE3 = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
20657
20767
|
DANGEROUS_IDS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
20658
20768
|
}
|
|
@@ -20664,11 +20774,11 @@ async function consensusHandler(projectRoot, query) {
|
|
|
20664
20774
|
const rawPageSize = parseInt(query?.get("pageSize") ?? "", 10);
|
|
20665
20775
|
const page = isNaN(rawPage) || rawPage < 1 ? 1 : rawPage;
|
|
20666
20776
|
const pageSize = isNaN(rawPageSize) || rawPageSize < 1 ? DEFAULT_PAGE_SIZE : Math.min(rawPageSize, MAX_PAGE_SIZE);
|
|
20667
|
-
const perfPath = (0,
|
|
20668
|
-
if (!(0,
|
|
20777
|
+
const perfPath = (0, import_path40.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
20778
|
+
if (!(0, import_fs38.existsSync)(perfPath)) return { runs: [], totalRuns: 0, totalSignals: 0, page, pageSize };
|
|
20669
20779
|
const signals = [];
|
|
20670
20780
|
try {
|
|
20671
|
-
const lines = (0,
|
|
20781
|
+
const lines = (0, import_fs38.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20672
20782
|
for (const line of lines) {
|
|
20673
20783
|
try {
|
|
20674
20784
|
const parsed = JSON.parse(line);
|
|
@@ -20739,12 +20849,12 @@ async function consensusHandler(projectRoot, query) {
|
|
|
20739
20849
|
const paginatedRuns = runs.slice(offset, offset + pageSize);
|
|
20740
20850
|
return { runs: paginatedRuns, totalRuns, totalSignals: signals.length, page, pageSize };
|
|
20741
20851
|
}
|
|
20742
|
-
var
|
|
20852
|
+
var import_fs38, import_path40, RESOLUTION_SIGNALS, DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE;
|
|
20743
20853
|
var init_api_consensus = __esm({
|
|
20744
20854
|
"packages/relay/src/dashboard/api-consensus.ts"() {
|
|
20745
20855
|
"use strict";
|
|
20746
|
-
|
|
20747
|
-
|
|
20856
|
+
import_fs38 = require("fs");
|
|
20857
|
+
import_path40 = require("path");
|
|
20748
20858
|
RESOLUTION_SIGNALS = /* @__PURE__ */ new Set(["agreement", "unique_confirmed", "consensus_verified"]);
|
|
20749
20859
|
DEFAULT_PAGE_SIZE = 10;
|
|
20750
20860
|
MAX_PAGE_SIZE = 50;
|
|
@@ -20756,11 +20866,11 @@ async function signalsHandler(projectRoot, query) {
|
|
|
20756
20866
|
const agentFilter = query?.get("agent") ?? null;
|
|
20757
20867
|
const limit = Math.min(Math.max(parseInt(query?.get("limit") ?? "", 10) || DEFAULT_LIMIT, 1), MAX_LIMIT);
|
|
20758
20868
|
const offset = Math.max(parseInt(query?.get("offset") ?? "", 10) || 0, 0);
|
|
20759
|
-
const perfPath = (0,
|
|
20760
|
-
if (!(0,
|
|
20869
|
+
const perfPath = (0, import_path41.join)(projectRoot, ".gossip", "agent-performance.jsonl");
|
|
20870
|
+
if (!(0, import_fs39.existsSync)(perfPath)) return { items: [], total: 0, offset, limit };
|
|
20761
20871
|
const all = [];
|
|
20762
20872
|
try {
|
|
20763
|
-
const lines = (0,
|
|
20873
|
+
const lines = (0, import_fs39.readFileSync)(perfPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20764
20874
|
for (const line of lines) {
|
|
20765
20875
|
try {
|
|
20766
20876
|
const entry = JSON.parse(line);
|
|
@@ -20776,12 +20886,12 @@ async function signalsHandler(projectRoot, query) {
|
|
|
20776
20886
|
all.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
20777
20887
|
return { items: all.slice(offset, offset + limit), total: all.length, offset, limit };
|
|
20778
20888
|
}
|
|
20779
|
-
var
|
|
20889
|
+
var import_fs39, import_path41, MAX_LIMIT, DEFAULT_LIMIT;
|
|
20780
20890
|
var init_api_signals = __esm({
|
|
20781
20891
|
"packages/relay/src/dashboard/api-signals.ts"() {
|
|
20782
20892
|
"use strict";
|
|
20783
|
-
|
|
20784
|
-
|
|
20893
|
+
import_fs39 = require("fs");
|
|
20894
|
+
import_path41 = require("path");
|
|
20785
20895
|
MAX_LIMIT = 200;
|
|
20786
20896
|
DEFAULT_LIMIT = 50;
|
|
20787
20897
|
}
|
|
@@ -20789,29 +20899,29 @@ var init_api_signals = __esm({
|
|
|
20789
20899
|
|
|
20790
20900
|
// packages/relay/src/dashboard/api-learnings.ts
|
|
20791
20901
|
async function learningsHandler(projectRoot) {
|
|
20792
|
-
const agentsDir = (0,
|
|
20793
|
-
if (!(0,
|
|
20902
|
+
const agentsDir = (0, import_path42.join)(projectRoot, ".gossip", "agents");
|
|
20903
|
+
if (!(0, import_fs40.existsSync)(agentsDir)) return { learnings: [] };
|
|
20794
20904
|
const all = [];
|
|
20795
20905
|
let agentIds;
|
|
20796
20906
|
try {
|
|
20797
|
-
agentIds = (0,
|
|
20907
|
+
agentIds = (0, import_fs40.readdirSync)(agentsDir).filter((f) => !f.startsWith("."));
|
|
20798
20908
|
} catch {
|
|
20799
20909
|
return { learnings: [] };
|
|
20800
20910
|
}
|
|
20801
20911
|
for (const agentId of agentIds) {
|
|
20802
|
-
const knowledgeDir = (0,
|
|
20803
|
-
if (!(0,
|
|
20912
|
+
const knowledgeDir = (0, import_path42.join)(agentsDir, agentId, "memory", "knowledge");
|
|
20913
|
+
if (!(0, import_fs40.existsSync)(knowledgeDir)) continue;
|
|
20804
20914
|
let files;
|
|
20805
20915
|
try {
|
|
20806
|
-
files = (0,
|
|
20916
|
+
files = (0, import_fs40.readdirSync)(knowledgeDir).filter((f) => f.endsWith(".md"));
|
|
20807
20917
|
} catch {
|
|
20808
20918
|
continue;
|
|
20809
20919
|
}
|
|
20810
20920
|
for (const filename of files) {
|
|
20811
|
-
const filepath = (0,
|
|
20921
|
+
const filepath = (0, import_path42.join)(knowledgeDir, filename);
|
|
20812
20922
|
try {
|
|
20813
|
-
const stat3 = (0,
|
|
20814
|
-
const raw = (0,
|
|
20923
|
+
const stat3 = (0, import_fs40.statSync)(filepath);
|
|
20924
|
+
const raw = (0, import_fs40.readFileSync)(filepath, "utf-8");
|
|
20815
20925
|
const fm = parseFrontmatter2(raw);
|
|
20816
20926
|
all.push({
|
|
20817
20927
|
agentId,
|
|
@@ -20838,12 +20948,12 @@ function parseFrontmatter2(raw) {
|
|
|
20838
20948
|
}
|
|
20839
20949
|
return fm;
|
|
20840
20950
|
}
|
|
20841
|
-
var
|
|
20951
|
+
var import_fs40, import_path42, MAX_LEARNINGS;
|
|
20842
20952
|
var init_api_learnings = __esm({
|
|
20843
20953
|
"packages/relay/src/dashboard/api-learnings.ts"() {
|
|
20844
20954
|
"use strict";
|
|
20845
|
-
|
|
20846
|
-
|
|
20955
|
+
import_fs40 = require("fs");
|
|
20956
|
+
import_path42 = require("path");
|
|
20847
20957
|
MAX_LEARNINGS = 10;
|
|
20848
20958
|
}
|
|
20849
20959
|
});
|
|
@@ -20854,12 +20964,12 @@ async function tasksHandler(projectRoot, query) {
|
|
|
20854
20964
|
const rawOffset = parseInt(query?.get("offset") ?? "0", 10);
|
|
20855
20965
|
const limit = isNaN(rawLimit) || rawLimit < 1 ? 50 : Math.min(rawLimit, 200);
|
|
20856
20966
|
const offset = isNaN(rawOffset) || rawOffset < 0 ? 0 : rawOffset;
|
|
20857
|
-
const graphPath = (0,
|
|
20858
|
-
if (!(0,
|
|
20967
|
+
const graphPath = (0, import_path43.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
20968
|
+
if (!(0, import_fs41.existsSync)(graphPath)) return { items: [], total: 0, offset, limit };
|
|
20859
20969
|
const created = /* @__PURE__ */ new Map();
|
|
20860
20970
|
const completed = /* @__PURE__ */ new Map();
|
|
20861
20971
|
try {
|
|
20862
|
-
const lines = (0,
|
|
20972
|
+
const lines = (0, import_fs41.readFileSync)(graphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20863
20973
|
for (const line of lines) {
|
|
20864
20974
|
try {
|
|
20865
20975
|
const entry = JSON.parse(line);
|
|
@@ -20914,23 +21024,23 @@ async function tasksHandler(projectRoot, query) {
|
|
|
20914
21024
|
tasks.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
20915
21025
|
return { items: tasks.slice(offset, offset + limit), total: tasks.length, offset, limit };
|
|
20916
21026
|
}
|
|
20917
|
-
var
|
|
21027
|
+
var import_fs41, import_path43;
|
|
20918
21028
|
var init_api_tasks = __esm({
|
|
20919
21029
|
"packages/relay/src/dashboard/api-tasks.ts"() {
|
|
20920
21030
|
"use strict";
|
|
20921
|
-
|
|
20922
|
-
|
|
21031
|
+
import_fs41 = require("fs");
|
|
21032
|
+
import_path43 = require("path");
|
|
20923
21033
|
}
|
|
20924
21034
|
});
|
|
20925
21035
|
|
|
20926
21036
|
// packages/relay/src/dashboard/api-active-tasks.ts
|
|
20927
21037
|
async function activeTasksHandler(projectRoot) {
|
|
20928
|
-
const taskGraphPath = (0,
|
|
20929
|
-
if (!(0,
|
|
21038
|
+
const taskGraphPath = (0, import_path44.join)(projectRoot, ".gossip", "task-graph.jsonl");
|
|
21039
|
+
if (!(0, import_fs42.existsSync)(taskGraphPath)) return { tasks: [] };
|
|
20930
21040
|
const created = /* @__PURE__ */ new Map();
|
|
20931
21041
|
const finished = /* @__PURE__ */ new Set();
|
|
20932
21042
|
try {
|
|
20933
|
-
const lines = (0,
|
|
21043
|
+
const lines = (0, import_fs42.readFileSync)(taskGraphPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
20934
21044
|
for (const line of lines) {
|
|
20935
21045
|
try {
|
|
20936
21046
|
const ev = JSON.parse(line);
|
|
@@ -20957,12 +21067,12 @@ async function activeTasksHandler(projectRoot) {
|
|
|
20957
21067
|
active.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
20958
21068
|
return { tasks: active.slice(0, 10) };
|
|
20959
21069
|
}
|
|
20960
|
-
var
|
|
21070
|
+
var import_fs42, import_path44;
|
|
20961
21071
|
var init_api_active_tasks = __esm({
|
|
20962
21072
|
"packages/relay/src/dashboard/api-active-tasks.ts"() {
|
|
20963
21073
|
"use strict";
|
|
20964
|
-
|
|
20965
|
-
|
|
21074
|
+
import_fs42 = require("fs");
|
|
21075
|
+
import_path44 = require("path");
|
|
20966
21076
|
}
|
|
20967
21077
|
});
|
|
20968
21078
|
|
|
@@ -20975,25 +21085,25 @@ function categorize(text) {
|
|
|
20975
21085
|
return "other";
|
|
20976
21086
|
}
|
|
20977
21087
|
function logsHandler(projectRoot, query) {
|
|
20978
|
-
const logPath = (0,
|
|
20979
|
-
if (!(0,
|
|
21088
|
+
const logPath = (0, import_path45.join)(projectRoot, ".gossip", "mcp.log");
|
|
21089
|
+
if (!(0, import_fs43.existsSync)(logPath)) {
|
|
20980
21090
|
return { entries: [], totalLines: 0, fileSize: 0 };
|
|
20981
21091
|
}
|
|
20982
21092
|
const filter = query?.get("filter") || void 0;
|
|
20983
21093
|
const tail = parseInt(query?.get("tail") || "200", 10);
|
|
20984
21094
|
const clampedTail = Math.min(Math.max(tail, 10), 2e3);
|
|
20985
|
-
const fileSize = (0,
|
|
21095
|
+
const fileSize = (0, import_fs43.statSync)(logPath).size;
|
|
20986
21096
|
const MAX_READ = 512 * 1024;
|
|
20987
21097
|
const readFrom = Math.max(0, fileSize - MAX_READ);
|
|
20988
21098
|
const readLen = fileSize - readFrom;
|
|
20989
|
-
const fd = (0,
|
|
21099
|
+
const fd = (0, import_fs43.openSync)(logPath, "r");
|
|
20990
21100
|
let buf = Buffer.alloc(0);
|
|
20991
21101
|
try {
|
|
20992
21102
|
buf = Buffer.allocUnsafe(readLen);
|
|
20993
|
-
const bytesRead = (0,
|
|
21103
|
+
const bytesRead = (0, import_fs43.readSync)(fd, buf, 0, readLen, readFrom);
|
|
20994
21104
|
buf = buf.subarray(0, bytesRead);
|
|
20995
21105
|
} finally {
|
|
20996
|
-
(0,
|
|
21106
|
+
(0, import_fs43.closeSync)(fd);
|
|
20997
21107
|
}
|
|
20998
21108
|
let raw = buf.toString("utf-8");
|
|
20999
21109
|
let lineOffset = 0;
|
|
@@ -21001,13 +21111,13 @@ function logsHandler(projectRoot, query) {
|
|
|
21001
21111
|
const nl = raw.indexOf("\n");
|
|
21002
21112
|
raw = nl >= 0 ? raw.slice(nl + 1) : raw;
|
|
21003
21113
|
const SCAN_CHUNK = 64 * 1024;
|
|
21004
|
-
const scanFd = (0,
|
|
21114
|
+
const scanFd = (0, import_fs43.openSync)(logPath, "r");
|
|
21005
21115
|
try {
|
|
21006
21116
|
let pos = 0;
|
|
21007
21117
|
const chunk = Buffer.allocUnsafe(SCAN_CHUNK);
|
|
21008
21118
|
while (pos < readFrom) {
|
|
21009
21119
|
const len = Math.min(SCAN_CHUNK, readFrom - pos);
|
|
21010
|
-
const n = (0,
|
|
21120
|
+
const n = (0, import_fs43.readSync)(scanFd, chunk, 0, len, pos);
|
|
21011
21121
|
if (n === 0) break;
|
|
21012
21122
|
for (let j = 0; j < n; j++) {
|
|
21013
21123
|
if (chunk[j] === 10) lineOffset++;
|
|
@@ -21015,7 +21125,7 @@ function logsHandler(projectRoot, query) {
|
|
|
21015
21125
|
pos += n;
|
|
21016
21126
|
}
|
|
21017
21127
|
} finally {
|
|
21018
|
-
(0,
|
|
21128
|
+
(0, import_fs43.closeSync)(scanFd);
|
|
21019
21129
|
}
|
|
21020
21130
|
}
|
|
21021
21131
|
const allLines = raw.split("\n").filter(Boolean);
|
|
@@ -21033,12 +21143,12 @@ function logsHandler(projectRoot, query) {
|
|
|
21033
21143
|
entries = entries.slice(-clampedTail);
|
|
21034
21144
|
return { entries, totalLines, fileSize, filter };
|
|
21035
21145
|
}
|
|
21036
|
-
var
|
|
21146
|
+
var import_fs43, import_path45, CATEGORY_PATTERNS2;
|
|
21037
21147
|
var init_api_logs = __esm({
|
|
21038
21148
|
"packages/relay/src/dashboard/api-logs.ts"() {
|
|
21039
21149
|
"use strict";
|
|
21040
|
-
|
|
21041
|
-
|
|
21150
|
+
import_fs43 = require("fs");
|
|
21151
|
+
import_path45 = require("path");
|
|
21042
21152
|
CATEGORY_PATTERNS2 = [
|
|
21043
21153
|
[/^\[worker:/, "worker"],
|
|
21044
21154
|
[/^\[Gemini\]/, "gemini"],
|
|
@@ -21066,8 +21176,22 @@ var init_api_logs = __esm({
|
|
|
21066
21176
|
});
|
|
21067
21177
|
|
|
21068
21178
|
// packages/relay/src/dashboard/routes.ts
|
|
21179
|
+
function resolveDashboardRoot(projectRoot) {
|
|
21180
|
+
const candidates = [
|
|
21181
|
+
(0, import_path46.resolve)(__dirname, "..", "dist-dashboard"),
|
|
21182
|
+
// bundled: dist-mcp/mcp-server.js → ../dist-dashboard
|
|
21183
|
+
(0, import_path46.resolve)(__dirname, "..", "..", "..", "..", "dist-dashboard"),
|
|
21184
|
+
// tsc dev: packages/relay/dist/dashboard → repo-root
|
|
21185
|
+
(0, import_path46.join)(projectRoot, "dist-dashboard")
|
|
21186
|
+
// legacy dev fallback (git-clone running from repo root)
|
|
21187
|
+
];
|
|
21188
|
+
for (const p of candidates) {
|
|
21189
|
+
if ((0, import_fs44.existsSync)(p)) return p;
|
|
21190
|
+
}
|
|
21191
|
+
return null;
|
|
21192
|
+
}
|
|
21069
21193
|
function readBody(req) {
|
|
21070
|
-
return new Promise((
|
|
21194
|
+
return new Promise((resolve18, reject) => {
|
|
21071
21195
|
const chunks = [];
|
|
21072
21196
|
let size = 0;
|
|
21073
21197
|
let tooLarge = false;
|
|
@@ -21082,14 +21206,14 @@ function readBody(req) {
|
|
|
21082
21206
|
chunks.push(chunk);
|
|
21083
21207
|
});
|
|
21084
21208
|
req.on("end", () => {
|
|
21085
|
-
if (!tooLarge)
|
|
21209
|
+
if (!tooLarge) resolve18(Buffer.concat(chunks).toString("utf-8"));
|
|
21086
21210
|
});
|
|
21087
21211
|
req.on("error", (err) => {
|
|
21088
21212
|
if (!tooLarge) reject(err);
|
|
21089
21213
|
});
|
|
21090
21214
|
});
|
|
21091
21215
|
}
|
|
21092
|
-
var
|
|
21216
|
+
var import_fs44, import_path46, AUTH_MAX_ATTEMPTS, AUTH_LOCKOUT_MS, DashboardRouter, MAX_BODY_SIZE;
|
|
21093
21217
|
var init_routes = __esm({
|
|
21094
21218
|
"packages/relay/src/dashboard/routes.ts"() {
|
|
21095
21219
|
"use strict";
|
|
@@ -21103,8 +21227,8 @@ var init_routes = __esm({
|
|
|
21103
21227
|
init_api_tasks();
|
|
21104
21228
|
init_api_active_tasks();
|
|
21105
21229
|
init_api_logs();
|
|
21106
|
-
|
|
21107
|
-
|
|
21230
|
+
import_fs44 = require("fs");
|
|
21231
|
+
import_path46 = require("path");
|
|
21108
21232
|
AUTH_MAX_ATTEMPTS = 10;
|
|
21109
21233
|
AUTH_LOCKOUT_MS = 6e4;
|
|
21110
21234
|
DashboardRouter = class {
|
|
@@ -21112,8 +21236,10 @@ var init_routes = __esm({
|
|
|
21112
21236
|
this.auth = auth;
|
|
21113
21237
|
this.projectRoot = projectRoot;
|
|
21114
21238
|
this.ctx = ctx2;
|
|
21239
|
+
this.dashboardRoot = resolveDashboardRoot(projectRoot);
|
|
21115
21240
|
}
|
|
21116
21241
|
authAttempts = /* @__PURE__ */ new Map();
|
|
21242
|
+
dashboardRoot;
|
|
21117
21243
|
/** Update live context (call when agents connect/disconnect) */
|
|
21118
21244
|
updateContext(ctx2) {
|
|
21119
21245
|
if (ctx2.agentConfigs !== void 0) this.ctx.agentConfigs = ctx2.agentConfigs;
|
|
@@ -21279,18 +21405,24 @@ var init_routes = __esm({
|
|
|
21279
21405
|
return true;
|
|
21280
21406
|
}
|
|
21281
21407
|
serveDashboard(res) {
|
|
21282
|
-
|
|
21283
|
-
|
|
21408
|
+
if (!this.dashboardRoot) {
|
|
21409
|
+
res.writeHead(503, { "Content-Type": "text/plain" });
|
|
21410
|
+
res.end("Dashboard assets not found. Reinstall gossipcat or rebuild from source.");
|
|
21411
|
+
return true;
|
|
21412
|
+
}
|
|
21413
|
+
const htmlPath = (0, import_path46.join)(this.dashboardRoot, "index.html");
|
|
21414
|
+
if (!(0, import_fs44.existsSync)(htmlPath)) {
|
|
21284
21415
|
res.writeHead(503, { "Content-Type": "text/plain" });
|
|
21285
|
-
res.end(
|
|
21416
|
+
res.end(`Dashboard index.html missing at ${this.dashboardRoot}. Reinstall gossipcat.`);
|
|
21286
21417
|
return true;
|
|
21287
21418
|
}
|
|
21288
|
-
const html = (0,
|
|
21419
|
+
const html = (0, import_fs44.readFileSync)(htmlPath, "utf-8");
|
|
21289
21420
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
21290
21421
|
res.end(html);
|
|
21291
21422
|
return true;
|
|
21292
21423
|
}
|
|
21293
21424
|
serveStaticFile(res, url2) {
|
|
21425
|
+
if (!this.dashboardRoot) return false;
|
|
21294
21426
|
const relativePath = url2.replace(/^\/dashboard\//, "");
|
|
21295
21427
|
if (relativePath.includes("..")) {
|
|
21296
21428
|
res.writeHead(404);
|
|
@@ -21310,16 +21442,16 @@ var init_routes = __esm({
|
|
|
21310
21442
|
const ext = "." + (relativePath.split(".").pop() || "");
|
|
21311
21443
|
const mime = MIME[ext];
|
|
21312
21444
|
if (!mime) return false;
|
|
21313
|
-
const filePath = (0,
|
|
21445
|
+
const filePath = (0, import_path46.join)(this.dashboardRoot, relativePath);
|
|
21314
21446
|
try {
|
|
21315
|
-
const realFile = (0,
|
|
21316
|
-
const realBase = (0,
|
|
21447
|
+
const realFile = (0, import_fs44.realpathSync)(filePath);
|
|
21448
|
+
const realBase = (0, import_fs44.realpathSync)(this.dashboardRoot);
|
|
21317
21449
|
if (!realFile.startsWith(realBase + "/")) {
|
|
21318
21450
|
res.writeHead(404);
|
|
21319
21451
|
res.end();
|
|
21320
21452
|
return true;
|
|
21321
21453
|
}
|
|
21322
|
-
const data = (0,
|
|
21454
|
+
const data = (0, import_fs44.readFileSync)(realFile);
|
|
21323
21455
|
res.writeHead(200, { "Content-Type": mime, "Cache-Control": "public, max-age=86400" });
|
|
21324
21456
|
res.end(data);
|
|
21325
21457
|
return true;
|
|
@@ -21334,15 +21466,15 @@ var init_routes = __esm({
|
|
|
21334
21466
|
return match ? match[1] : null;
|
|
21335
21467
|
}
|
|
21336
21468
|
getConsensusReports(page = 1, pageSize = 5) {
|
|
21337
|
-
const { readdirSync: readdirSync13, readFileSync: readFileSync40, existsSync:
|
|
21338
|
-
const reportsDir = (0,
|
|
21339
|
-
if (!
|
|
21469
|
+
const { readdirSync: readdirSync13, readFileSync: readFileSync40, existsSync: existsSync43 } = require("fs");
|
|
21470
|
+
const reportsDir = (0, import_path46.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
21471
|
+
if (!existsSync43(reportsDir)) return { reports: [], totalReports: 0, page, pageSize };
|
|
21340
21472
|
try {
|
|
21341
21473
|
const { statSync: statSync9 } = require("fs");
|
|
21342
21474
|
const allFiles = readdirSync13(reportsDir).filter((f) => f.endsWith(".json")).sort((a, b) => {
|
|
21343
21475
|
try {
|
|
21344
|
-
const aTime = statSync9((0,
|
|
21345
|
-
const bTime = statSync9((0,
|
|
21476
|
+
const aTime = statSync9((0, import_path46.join)(reportsDir, a)).mtimeMs;
|
|
21477
|
+
const bTime = statSync9((0, import_path46.join)(reportsDir, b)).mtimeMs;
|
|
21346
21478
|
return bTime - aTime;
|
|
21347
21479
|
} catch {
|
|
21348
21480
|
return 0;
|
|
@@ -21353,11 +21485,11 @@ var init_routes = __esm({
|
|
|
21353
21485
|
const clampedPage = Math.max(page, 1);
|
|
21354
21486
|
const start = (clampedPage - 1) * clampedPageSize;
|
|
21355
21487
|
const files = allFiles.slice(start, start + clampedPageSize);
|
|
21356
|
-
const realReportsDir = (0,
|
|
21488
|
+
const realReportsDir = (0, import_fs44.realpathSync)(reportsDir);
|
|
21357
21489
|
const reports = files.map((f) => {
|
|
21358
21490
|
try {
|
|
21359
|
-
const filePath = (0,
|
|
21360
|
-
const realFile = (0,
|
|
21491
|
+
const filePath = (0, import_path46.join)(reportsDir, f);
|
|
21492
|
+
const realFile = (0, import_fs44.realpathSync)(filePath);
|
|
21361
21493
|
if (!realFile.startsWith(realReportsDir + "/")) return null;
|
|
21362
21494
|
return JSON.parse(readFileSync40(realFile, "utf-8"));
|
|
21363
21495
|
} catch {
|
|
@@ -21370,27 +21502,27 @@ var init_routes = __esm({
|
|
|
21370
21502
|
}
|
|
21371
21503
|
}
|
|
21372
21504
|
archiveFindings() {
|
|
21373
|
-
const { readdirSync: readdirSync13, readFileSync: readFileSync40, renameSync: renameSync2, writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync:
|
|
21374
|
-
const reportsDir = (0,
|
|
21375
|
-
const archiveDir = (0,
|
|
21505
|
+
const { readdirSync: readdirSync13, readFileSync: readFileSync40, renameSync: renameSync2, writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync: existsSync43 } = require("fs");
|
|
21506
|
+
const reportsDir = (0, import_path46.join)(this.projectRoot, ".gossip", "consensus-reports");
|
|
21507
|
+
const archiveDir = (0, import_path46.join)(this.projectRoot, ".gossip", "consensus-reports-archive");
|
|
21376
21508
|
let archived = 0;
|
|
21377
|
-
if (
|
|
21509
|
+
if (existsSync43(reportsDir)) {
|
|
21378
21510
|
const files = readdirSync13(reportsDir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
21379
21511
|
if (files.length > 5) {
|
|
21380
21512
|
mkdirSync21(archiveDir, { recursive: true });
|
|
21381
21513
|
const toArchive = files.slice(5);
|
|
21382
21514
|
for (const f of toArchive) {
|
|
21383
21515
|
try {
|
|
21384
|
-
renameSync2((0,
|
|
21516
|
+
renameSync2((0, import_path46.join)(reportsDir, f), (0, import_path46.join)(archiveDir, f));
|
|
21385
21517
|
archived++;
|
|
21386
21518
|
} catch {
|
|
21387
21519
|
}
|
|
21388
21520
|
}
|
|
21389
21521
|
}
|
|
21390
21522
|
}
|
|
21391
|
-
const findingsPath = (0,
|
|
21523
|
+
const findingsPath = (0, import_path46.join)(this.projectRoot, ".gossip", "implementation-findings.jsonl");
|
|
21392
21524
|
let findingsCleared = 0;
|
|
21393
|
-
if (
|
|
21525
|
+
if (existsSync43(findingsPath)) {
|
|
21394
21526
|
try {
|
|
21395
21527
|
const lines = readFileSync40(findingsPath, "utf-8").trim().split("\n").filter(Boolean);
|
|
21396
21528
|
const kept = lines.filter((line) => {
|
|
@@ -21409,7 +21541,7 @@ var init_routes = __esm({
|
|
|
21409
21541
|
} catch {
|
|
21410
21542
|
}
|
|
21411
21543
|
}
|
|
21412
|
-
const remaining =
|
|
21544
|
+
const remaining = existsSync43(reportsDir) ? readdirSync13(reportsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
21413
21545
|
return { archived, remaining, findingsCleared };
|
|
21414
21546
|
}
|
|
21415
21547
|
json(res, status, data) {
|
|
@@ -21422,14 +21554,14 @@ var init_routes = __esm({
|
|
|
21422
21554
|
});
|
|
21423
21555
|
|
|
21424
21556
|
// packages/relay/src/dashboard/ws.ts
|
|
21425
|
-
var import_ws3,
|
|
21557
|
+
var import_ws3, import_fs45, import_fs46, import_path47, DashboardWs;
|
|
21426
21558
|
var init_ws = __esm({
|
|
21427
21559
|
"packages/relay/src/dashboard/ws.ts"() {
|
|
21428
21560
|
"use strict";
|
|
21429
21561
|
import_ws3 = require("ws");
|
|
21430
|
-
import_fs44 = require("fs");
|
|
21431
21562
|
import_fs45 = require("fs");
|
|
21432
|
-
|
|
21563
|
+
import_fs46 = require("fs");
|
|
21564
|
+
import_path47 = require("path");
|
|
21433
21565
|
DashboardWs = class {
|
|
21434
21566
|
clients = /* @__PURE__ */ new Set();
|
|
21435
21567
|
logWatcher = null;
|
|
@@ -21454,15 +21586,15 @@ var init_ws = __esm({
|
|
|
21454
21586
|
/** Start watching mcp.log for new lines and broadcasting them to connected clients. */
|
|
21455
21587
|
startLogWatcher(projectRoot) {
|
|
21456
21588
|
this.stopLogWatcher();
|
|
21457
|
-
this.logPath = (0,
|
|
21458
|
-
if (!(0,
|
|
21589
|
+
this.logPath = (0, import_path47.join)(projectRoot, ".gossip", "mcp.log");
|
|
21590
|
+
if (!(0, import_fs45.existsSync)(this.logPath)) return;
|
|
21459
21591
|
try {
|
|
21460
|
-
this.logOffset = (0,
|
|
21592
|
+
this.logOffset = (0, import_fs45.statSync)(this.logPath).size;
|
|
21461
21593
|
} catch {
|
|
21462
21594
|
this.logOffset = 0;
|
|
21463
21595
|
}
|
|
21464
21596
|
try {
|
|
21465
|
-
this.logWatcher = (0,
|
|
21597
|
+
this.logWatcher = (0, import_fs46.watch)(this.logPath, () => {
|
|
21466
21598
|
if (this.clients.size === 0) return;
|
|
21467
21599
|
this.readNewLines();
|
|
21468
21600
|
});
|
|
@@ -21479,7 +21611,7 @@ var init_ws = __esm({
|
|
|
21479
21611
|
if (this.logReading) return;
|
|
21480
21612
|
this.logReading = true;
|
|
21481
21613
|
try {
|
|
21482
|
-
const currentSize = (0,
|
|
21614
|
+
const currentSize = (0, import_fs45.statSync)(this.logPath).size;
|
|
21483
21615
|
if (currentSize < this.logOffset) {
|
|
21484
21616
|
this.logOffset = 0;
|
|
21485
21617
|
this.logCarry = "";
|
|
@@ -21492,7 +21624,7 @@ var init_ws = __esm({
|
|
|
21492
21624
|
const readFrom = capped ? (this.logCarry = "", this.logCapped = true, currentSize - 65536) : (this.logCapped = false, this.logOffset);
|
|
21493
21625
|
let stream;
|
|
21494
21626
|
try {
|
|
21495
|
-
stream = (0,
|
|
21627
|
+
stream = (0, import_fs45.createReadStream)(this.logPath, { start: readFrom, end: currentSize - 1 });
|
|
21496
21628
|
} catch {
|
|
21497
21629
|
this.logReading = false;
|
|
21498
21630
|
return;
|
|
@@ -21586,7 +21718,7 @@ var init_server = __esm({
|
|
|
21586
21718
|
return `ws://localhost:${this._port}`;
|
|
21587
21719
|
}
|
|
21588
21720
|
async start() {
|
|
21589
|
-
return new Promise((
|
|
21721
|
+
return new Promise((resolve18) => {
|
|
21590
21722
|
this.httpServer = (0, import_http.createServer)(this.handleHttp.bind(this));
|
|
21591
21723
|
if (this.config.dashboard) {
|
|
21592
21724
|
this.dashboardAuth = new DashboardAuth();
|
|
@@ -21631,7 +21763,7 @@ var init_server = __esm({
|
|
|
21631
21763
|
this.httpServer.listen(this.config.port, this.config.host ?? "127.0.0.1", () => {
|
|
21632
21764
|
const addr = this.httpServer.address();
|
|
21633
21765
|
this._port = addr.port;
|
|
21634
|
-
|
|
21766
|
+
resolve18();
|
|
21635
21767
|
});
|
|
21636
21768
|
});
|
|
21637
21769
|
}
|
|
@@ -21650,9 +21782,9 @@ var init_server = __esm({
|
|
|
21650
21782
|
for (const client of this.wss.clients) {
|
|
21651
21783
|
client.close(1001, "Server shutting down");
|
|
21652
21784
|
}
|
|
21653
|
-
return new Promise((
|
|
21785
|
+
return new Promise((resolve18) => {
|
|
21654
21786
|
this.wss.close(() => {
|
|
21655
|
-
this.httpServer.close(() =>
|
|
21787
|
+
this.httpServer.close(() => resolve18());
|
|
21656
21788
|
});
|
|
21657
21789
|
});
|
|
21658
21790
|
}
|
|
@@ -21848,18 +21980,18 @@ __export(config_exports, {
|
|
|
21848
21980
|
function findConfigPath(projectRoot) {
|
|
21849
21981
|
const root = projectRoot || process.cwd();
|
|
21850
21982
|
const candidates = [
|
|
21851
|
-
(0,
|
|
21852
|
-
(0,
|
|
21853
|
-
(0,
|
|
21854
|
-
(0,
|
|
21983
|
+
(0, import_path48.resolve)(root, ".gossip", "config.json"),
|
|
21984
|
+
(0, import_path48.resolve)(root, "gossip.agents.json"),
|
|
21985
|
+
(0, import_path48.resolve)(root, "gossip.agents.yaml"),
|
|
21986
|
+
(0, import_path48.resolve)(root, "gossip.agents.yml")
|
|
21855
21987
|
];
|
|
21856
21988
|
for (const p of candidates) {
|
|
21857
|
-
if ((0,
|
|
21989
|
+
if ((0, import_fs47.existsSync)(p)) return p;
|
|
21858
21990
|
}
|
|
21859
21991
|
return null;
|
|
21860
21992
|
}
|
|
21861
21993
|
function loadConfig(configPath) {
|
|
21862
|
-
const raw = (0,
|
|
21994
|
+
const raw = (0, import_fs47.readFileSync)(configPath, "utf-8");
|
|
21863
21995
|
let parsed;
|
|
21864
21996
|
try {
|
|
21865
21997
|
parsed = JSON.parse(raw);
|
|
@@ -21938,19 +22070,19 @@ function configToAgentConfigs(config2) {
|
|
|
21938
22070
|
}
|
|
21939
22071
|
function loadClaudeSubagents(projectRoot, existingIds) {
|
|
21940
22072
|
const root = projectRoot || process.cwd();
|
|
21941
|
-
const agentsDir = (0,
|
|
21942
|
-
if (!(0,
|
|
22073
|
+
const agentsDir = (0, import_path48.join)(root, ".claude", "agents");
|
|
22074
|
+
if (!(0, import_fs47.existsSync)(agentsDir)) return [];
|
|
21943
22075
|
let files;
|
|
21944
22076
|
try {
|
|
21945
|
-
files = (0,
|
|
22077
|
+
files = (0, import_fs47.readdirSync)(agentsDir).filter((f) => f.endsWith(".md"));
|
|
21946
22078
|
} catch {
|
|
21947
22079
|
return [];
|
|
21948
22080
|
}
|
|
21949
22081
|
const agents = [];
|
|
21950
22082
|
for (const file2 of files) {
|
|
21951
|
-
const filePath = (0,
|
|
22083
|
+
const filePath = (0, import_path48.join)(agentsDir, file2);
|
|
21952
22084
|
try {
|
|
21953
|
-
const content = (0,
|
|
22085
|
+
const content = (0, import_fs47.readFileSync)(filePath, "utf-8");
|
|
21954
22086
|
const frontmatter = content.match(/^---\n([\s\S]*?)\n---/);
|
|
21955
22087
|
if (!frontmatter) continue;
|
|
21956
22088
|
const fm = frontmatter[1];
|
|
@@ -22005,12 +22137,12 @@ function inferSkills(description, name) {
|
|
|
22005
22137
|
if (skills.length === 0) skills.push("general");
|
|
22006
22138
|
return skills;
|
|
22007
22139
|
}
|
|
22008
|
-
var
|
|
22140
|
+
var import_fs47, import_path48, VALID_PROVIDERS, CLAUDE_MODEL_MAP;
|
|
22009
22141
|
var init_config = __esm({
|
|
22010
22142
|
"apps/cli/src/config.ts"() {
|
|
22011
22143
|
"use strict";
|
|
22012
|
-
|
|
22013
|
-
|
|
22144
|
+
import_fs47 = require("fs");
|
|
22145
|
+
import_path48 = require("path");
|
|
22014
22146
|
VALID_PROVIDERS = ["anthropic", "openai", "openclaw", "google", "local", "native"];
|
|
22015
22147
|
CLAUDE_MODEL_MAP = {
|
|
22016
22148
|
opus: { provider: "anthropic", model: "claude-opus-4-6" },
|
|
@@ -22025,14 +22157,14 @@ var keychain_exports = {};
|
|
|
22025
22157
|
__export(keychain_exports, {
|
|
22026
22158
|
Keychain: () => Keychain
|
|
22027
22159
|
});
|
|
22028
|
-
var import_child_process5, import_os2,
|
|
22160
|
+
var import_child_process5, import_os2, import_fs48, import_path49, import_crypto15, SERVICE_NAME, VALID_PROVIDERS2, ENCRYPTED_FILE, ALGO, Keychain;
|
|
22029
22161
|
var init_keychain = __esm({
|
|
22030
22162
|
"apps/cli/src/keychain.ts"() {
|
|
22031
22163
|
"use strict";
|
|
22032
22164
|
import_child_process5 = require("child_process");
|
|
22033
22165
|
import_os2 = require("os");
|
|
22034
|
-
|
|
22035
|
-
|
|
22166
|
+
import_fs48 = require("fs");
|
|
22167
|
+
import_path49 = require("path");
|
|
22036
22168
|
import_crypto15 = require("crypto");
|
|
22037
22169
|
SERVICE_NAME = "gossip-mesh";
|
|
22038
22170
|
VALID_PROVIDERS2 = /^[a-zA-Z0-9_-]{1,32}$/;
|
|
@@ -22074,10 +22206,10 @@ var init_keychain = __esm({
|
|
|
22074
22206
|
return (0, import_crypto15.pbkdf2Sync)(seed, salt, 6e5, 32, "sha256");
|
|
22075
22207
|
}
|
|
22076
22208
|
loadEncryptedFile() {
|
|
22077
|
-
const filePath = (0,
|
|
22078
|
-
if (!(0,
|
|
22209
|
+
const filePath = (0, import_path49.join)(process.cwd(), ENCRYPTED_FILE);
|
|
22210
|
+
if (!(0, import_fs48.existsSync)(filePath)) return;
|
|
22079
22211
|
try {
|
|
22080
|
-
const raw = (0,
|
|
22212
|
+
const raw = (0, import_fs48.readFileSync)(filePath);
|
|
22081
22213
|
if (raw.length < 61) return;
|
|
22082
22214
|
const salt = raw.subarray(0, 32);
|
|
22083
22215
|
const iv = raw.subarray(32, 44);
|
|
@@ -22095,9 +22227,9 @@ var init_keychain = __esm({
|
|
|
22095
22227
|
}
|
|
22096
22228
|
}
|
|
22097
22229
|
saveEncryptedFile() {
|
|
22098
|
-
const filePath = (0,
|
|
22099
|
-
const dir = (0,
|
|
22100
|
-
if (!(0,
|
|
22230
|
+
const filePath = (0, import_path49.join)(process.cwd(), ENCRYPTED_FILE);
|
|
22231
|
+
const dir = (0, import_path49.join)(process.cwd(), ".gossip");
|
|
22232
|
+
if (!(0, import_fs48.existsSync)(dir)) (0, import_fs48.mkdirSync)(dir, { recursive: true });
|
|
22101
22233
|
const data = JSON.stringify(Object.fromEntries(this.inMemoryStore));
|
|
22102
22234
|
const salt = (0, import_crypto15.randomBytes)(32);
|
|
22103
22235
|
const iv = (0, import_crypto15.randomBytes)(12);
|
|
@@ -22105,7 +22237,7 @@ var init_keychain = __esm({
|
|
|
22105
22237
|
const cipher = (0, import_crypto15.createCipheriv)(ALGO, key, iv);
|
|
22106
22238
|
const encrypted = Buffer.concat([cipher.update(data, "utf8"), cipher.final()]);
|
|
22107
22239
|
const tag = cipher.getAuthTag();
|
|
22108
|
-
(0,
|
|
22240
|
+
(0, import_fs48.writeFileSync)(filePath, Buffer.concat([salt, iv, tag, encrypted]), { mode: 384 });
|
|
22109
22241
|
}
|
|
22110
22242
|
isKeychainAvailable() {
|
|
22111
22243
|
if ((0, import_os2.platform)() === "darwin") {
|
|
@@ -22205,17 +22337,17 @@ __export(identity_exports, {
|
|
|
22205
22337
|
normalizeGitUrl: () => normalizeGitUrl
|
|
22206
22338
|
});
|
|
22207
22339
|
function getOrCreateSalt(projectRoot) {
|
|
22208
|
-
const saltPath = (0,
|
|
22340
|
+
const saltPath = (0, import_path50.join)(projectRoot, ".gossip", "local-salt");
|
|
22209
22341
|
try {
|
|
22210
|
-
return (0,
|
|
22342
|
+
return (0, import_fs49.readFileSync)(saltPath, "utf-8").trim();
|
|
22211
22343
|
} catch {
|
|
22212
22344
|
const salt = (0, import_crypto16.randomBytes)(16).toString("hex");
|
|
22213
|
-
(0,
|
|
22345
|
+
(0, import_fs49.mkdirSync)((0, import_path50.join)(projectRoot, ".gossip"), { recursive: true });
|
|
22214
22346
|
try {
|
|
22215
|
-
(0,
|
|
22347
|
+
(0, import_fs49.writeFileSync)(saltPath, salt, { flag: "wx" });
|
|
22216
22348
|
return salt;
|
|
22217
22349
|
} catch {
|
|
22218
|
-
return (0,
|
|
22350
|
+
return (0, import_fs49.readFileSync)(saltPath, "utf-8").trim();
|
|
22219
22351
|
}
|
|
22220
22352
|
}
|
|
22221
22353
|
}
|
|
@@ -22265,12 +22397,12 @@ function getProjectId(projectRoot) {
|
|
|
22265
22397
|
}
|
|
22266
22398
|
return (0, import_crypto16.createHash)("sha256").update(projectRoot).digest("hex").slice(0, 16);
|
|
22267
22399
|
}
|
|
22268
|
-
var
|
|
22400
|
+
var import_fs49, import_path50, import_crypto16, import_child_process6;
|
|
22269
22401
|
var init_identity = __esm({
|
|
22270
22402
|
"apps/cli/src/identity.ts"() {
|
|
22271
22403
|
"use strict";
|
|
22272
|
-
|
|
22273
|
-
|
|
22404
|
+
import_fs49 = require("fs");
|
|
22405
|
+
import_path50 = require("path");
|
|
22274
22406
|
import_crypto16 = require("crypto");
|
|
22275
22407
|
import_child_process6 = require("child_process");
|
|
22276
22408
|
}
|
|
@@ -22282,14 +22414,8 @@ __export(gossip_update_exports, {
|
|
|
22282
22414
|
handleGossipUpdate: () => handleGossipUpdate
|
|
22283
22415
|
});
|
|
22284
22416
|
function getCurrentVersion() {
|
|
22285
|
-
|
|
22286
|
-
|
|
22287
|
-
if ((0, import_fs49.existsSync)(pkgPath)) {
|
|
22288
|
-
return JSON.parse((0, import_fs49.readFileSync)(pkgPath, "utf-8")).version ?? "0.0.0";
|
|
22289
|
-
}
|
|
22290
|
-
} catch {
|
|
22291
|
-
}
|
|
22292
|
-
return "0.0.0";
|
|
22417
|
+
const v = getGossipcatVersion();
|
|
22418
|
+
return v === "unknown" ? "0.0.0" : v;
|
|
22293
22419
|
}
|
|
22294
22420
|
async function getLatestVersion() {
|
|
22295
22421
|
const res = await fetch("https://registry.npmjs.org/gossipcat/latest");
|
|
@@ -22298,9 +22424,9 @@ async function getLatestVersion() {
|
|
|
22298
22424
|
return data.version;
|
|
22299
22425
|
}
|
|
22300
22426
|
function detectInstallMethod() {
|
|
22301
|
-
const packageRoot = (0,
|
|
22427
|
+
const packageRoot = (0, import_path51.resolve)(__dirname, "..", "..", "..", "..");
|
|
22302
22428
|
if (process.env.npm_config_global === "true") return "global";
|
|
22303
|
-
if ((0,
|
|
22429
|
+
if ((0, import_fs50.existsSync)((0, import_path51.join)(packageRoot, ".git"))) return "git-clone";
|
|
22304
22430
|
return "local";
|
|
22305
22431
|
}
|
|
22306
22432
|
function updateCommand(method, version2) {
|
|
@@ -22351,7 +22477,7 @@ Check your internet connection or visit https://www.npmjs.com/package/gossipcat
|
|
|
22351
22477
|
try {
|
|
22352
22478
|
(0, import_child_process7.execSync)(command, {
|
|
22353
22479
|
stdio: "inherit",
|
|
22354
|
-
cwd: method === "git-clone" ? (0,
|
|
22480
|
+
cwd: method === "git-clone" ? (0, import_path51.resolve)(__dirname, "..", "..", "..", "..") : process.cwd()
|
|
22355
22481
|
});
|
|
22356
22482
|
} catch (err) {
|
|
22357
22483
|
return {
|
|
@@ -22373,13 +22499,14 @@ Run /mcp reconnect in Claude Code to load the new version.`
|
|
|
22373
22499
|
}]
|
|
22374
22500
|
};
|
|
22375
22501
|
}
|
|
22376
|
-
var import_child_process7,
|
|
22502
|
+
var import_child_process7, import_fs50, import_path51;
|
|
22377
22503
|
var init_gossip_update = __esm({
|
|
22378
22504
|
"apps/cli/src/handlers/gossip-update.ts"() {
|
|
22379
22505
|
"use strict";
|
|
22380
22506
|
import_child_process7 = require("child_process");
|
|
22381
|
-
|
|
22382
|
-
|
|
22507
|
+
import_fs50 = require("fs");
|
|
22508
|
+
import_path51 = require("path");
|
|
22509
|
+
init_version();
|
|
22383
22510
|
}
|
|
22384
22511
|
});
|
|
22385
22512
|
|
|
@@ -22542,8 +22669,8 @@ var init_verify_memory = __esm({
|
|
|
22542
22669
|
});
|
|
22543
22670
|
|
|
22544
22671
|
// apps/cli/src/mcp-server-sdk.ts
|
|
22545
|
-
var
|
|
22546
|
-
var
|
|
22672
|
+
var import_fs51 = require("fs");
|
|
22673
|
+
var import_path52 = require("path");
|
|
22547
22674
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
22548
22675
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
22549
22676
|
var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
@@ -36320,6 +36447,7 @@ config(en_default());
|
|
|
36320
36447
|
var import_crypto17 = require("crypto");
|
|
36321
36448
|
var import_http2 = require("http");
|
|
36322
36449
|
init_mcp_context();
|
|
36450
|
+
init_version();
|
|
36323
36451
|
|
|
36324
36452
|
// apps/cli/src/handlers/native-tasks.ts
|
|
36325
36453
|
var import_crypto10 = require("crypto");
|
|
@@ -36724,8 +36852,8 @@ ${utilityBlocks.join("\n\n")}`;
|
|
|
36724
36852
|
|
|
36725
36853
|
// apps/cli/src/handlers/dispatch.ts
|
|
36726
36854
|
var import_crypto11 = require("crypto");
|
|
36727
|
-
var
|
|
36728
|
-
var
|
|
36855
|
+
var import_fs32 = require("fs");
|
|
36856
|
+
var import_path34 = require("path");
|
|
36729
36857
|
init_src4();
|
|
36730
36858
|
init_src3();
|
|
36731
36859
|
init_mcp_context();
|
|
@@ -36842,7 +36970,7 @@ var AGENT_PROVIDER_MAP = {
|
|
|
36842
36970
|
};
|
|
36843
36971
|
function readQuotaState() {
|
|
36844
36972
|
try {
|
|
36845
|
-
const raw = (0,
|
|
36973
|
+
const raw = (0, import_fs32.readFileSync)((0, import_path34.join)(process.cwd(), ".gossip", "quota-state.json"), "utf8");
|
|
36846
36974
|
return JSON.parse(raw);
|
|
36847
36975
|
} catch {
|
|
36848
36976
|
return {};
|
|
@@ -37188,8 +37316,8 @@ async function handleDispatchConsensus(taskDefs, _utility_task_id) {
|
|
|
37188
37316
|
});
|
|
37189
37317
|
const lenses = await Promise.race([
|
|
37190
37318
|
lensPromise,
|
|
37191
|
-
new Promise((
|
|
37192
|
-
timerId = setTimeout(() =>
|
|
37319
|
+
new Promise((resolve18) => {
|
|
37320
|
+
timerId = setTimeout(() => resolve18(null), LENS_TIMEOUT_MS);
|
|
37193
37321
|
})
|
|
37194
37322
|
]);
|
|
37195
37323
|
if (timerId) clearTimeout(timerId);
|
|
@@ -37405,7 +37533,7 @@ Relay may be down. Check gossip_status() for connection state.` }] };
|
|
|
37405
37533
|
process.stderr.write(`[gossipcat] \u23F3 Consensus: ${doneCount}/${pendingNativeIds.length} agents complete (${agentStatus})
|
|
37406
37534
|
`);
|
|
37407
37535
|
}
|
|
37408
|
-
await new Promise((
|
|
37536
|
+
await new Promise((resolve18) => setTimeout(resolve18, POLL_INTERVAL));
|
|
37409
37537
|
}
|
|
37410
37538
|
const arrived = pendingNativeIds.filter((id) => ctx.nativeResultMap.has(id)).length;
|
|
37411
37539
|
const timedOutCount = pendingNativeIds.filter((id) => {
|
|
@@ -37902,12 +38030,12 @@ ${gaps.map((g) => ` - ${g.agentId} needs "${g.category}" (score: ${g.score.toFi
|
|
|
37902
38030
|
|
|
37903
38031
|
// apps/cli/src/mcp-server-sdk.ts
|
|
37904
38032
|
init_relay_cross_review();
|
|
37905
|
-
var gossipDir = (0,
|
|
38033
|
+
var gossipDir = (0, import_path52.join)(process.cwd(), ".gossip");
|
|
37906
38034
|
try {
|
|
37907
|
-
(0,
|
|
38035
|
+
(0, import_fs51.mkdirSync)(gossipDir, { recursive: true });
|
|
37908
38036
|
} catch {
|
|
37909
38037
|
}
|
|
37910
|
-
var logStream = (0,
|
|
38038
|
+
var logStream = (0, import_fs51.createWriteStream)((0, import_path52.join)(gossipDir, "mcp.log"), { flags: "a" });
|
|
37911
38039
|
process.stderr.write = ((chunk, ...args) => {
|
|
37912
38040
|
return logStream.write(chunk, ...args);
|
|
37913
38041
|
});
|
|
@@ -38074,10 +38202,10 @@ var _pendingSessionData = /* @__PURE__ */ new Map();
|
|
|
38074
38202
|
var _pendingVerifyData = /* @__PURE__ */ new Map();
|
|
38075
38203
|
var _modules = null;
|
|
38076
38204
|
function lookupFindingSeverity(findingId, projectRoot) {
|
|
38077
|
-
const { existsSync:
|
|
38205
|
+
const { existsSync: existsSync43, readdirSync: readdirSync13, readFileSync: readFileSync40 } = require("fs");
|
|
38078
38206
|
const { join: join48 } = require("path");
|
|
38079
38207
|
const reportsDir = join48(projectRoot, ".gossip", "consensus-reports");
|
|
38080
|
-
if (!
|
|
38208
|
+
if (!existsSync43(reportsDir)) return null;
|
|
38081
38209
|
try {
|
|
38082
38210
|
const files = readdirSync13(reportsDir).filter((f) => f.endsWith(".json"));
|
|
38083
38211
|
for (const file2 of files) {
|
|
@@ -38144,12 +38272,21 @@ async function refreshBootstrap() {
|
|
|
38144
38272
|
async function doBoot() {
|
|
38145
38273
|
const m = await getModules();
|
|
38146
38274
|
const configPath = m.findConfigPath();
|
|
38147
|
-
|
|
38148
|
-
|
|
38275
|
+
let config2;
|
|
38276
|
+
if (configPath) {
|
|
38277
|
+
config2 = m.loadConfig(configPath);
|
|
38278
|
+
} else {
|
|
38279
|
+
process.stderr.write("[gossipcat] \u26A0\uFE0F No gossip.agents.json found \u2014 booting in degraded mode (dashboard + relay only). Run gossip_setup inside Claude Code to create your agent team.\n");
|
|
38280
|
+
config2 = {
|
|
38281
|
+
main_agent: { provider: "none", model: "none" },
|
|
38282
|
+
utility_model: { provider: "none", model: "none" },
|
|
38283
|
+
agents: {}
|
|
38284
|
+
};
|
|
38285
|
+
}
|
|
38149
38286
|
const agentConfigs = m.configToAgentConfigs(config2);
|
|
38150
38287
|
ctx.keychain = new m.Keychain();
|
|
38151
38288
|
const { existsSync: pidExists, readFileSync: readPid, writeFileSync: writePid, unlinkSync: delPid } = require("fs");
|
|
38152
|
-
const pidFile = (0,
|
|
38289
|
+
const pidFile = (0, import_path52.join)(process.cwd(), ".gossip", "relay.pid");
|
|
38153
38290
|
if (pidExists(pidFile)) {
|
|
38154
38291
|
const oldPid = parseInt(readPid(pidFile, "utf-8").trim(), 10);
|
|
38155
38292
|
if (!isNaN(oldPid) && oldPid !== process.pid) {
|
|
@@ -38162,8 +38299,10 @@ async function doBoot() {
|
|
|
38162
38299
|
}
|
|
38163
38300
|
}
|
|
38164
38301
|
const relayApiKey = (0, import_crypto17.randomBytes)(32).toString("hex");
|
|
38302
|
+
const envPort = process.env.GOSSIPCAT_PORT ? parseInt(process.env.GOSSIPCAT_PORT, 10) : NaN;
|
|
38303
|
+
const relayPort = Number.isFinite(envPort) && envPort >= 0 && envPort <= 65535 ? envPort : 0;
|
|
38165
38304
|
ctx.relay = new m.RelayServer({
|
|
38166
|
-
port:
|
|
38305
|
+
port: relayPort,
|
|
38167
38306
|
apiKey: relayApiKey,
|
|
38168
38307
|
dashboard: {
|
|
38169
38308
|
projectRoot: process.cwd(),
|
|
@@ -38237,10 +38376,10 @@ async function doBoot() {
|
|
|
38237
38376
|
}
|
|
38238
38377
|
const key = await ctx.keychain.getKey(ac.provider);
|
|
38239
38378
|
const llm = m.createProvider(ac.provider, ac.model, key ?? void 0, void 0, ac.base_url);
|
|
38240
|
-
const { existsSync:
|
|
38379
|
+
const { existsSync: existsSync43, readFileSync: readFileSync40 } = require("fs");
|
|
38241
38380
|
const { join: join48 } = require("path");
|
|
38242
38381
|
const instructionsPath = join48(process.cwd(), ".gossip", "agents", ac.id, "instructions.md");
|
|
38243
|
-
const baseInstructions =
|
|
38382
|
+
const baseInstructions = existsSync43(instructionsPath) ? readFileSync40(instructionsPath, "utf-8") : "";
|
|
38244
38383
|
const identity = identityRegistry.get(ac.id);
|
|
38245
38384
|
const identityBlock = identity ? m.formatIdentityBlock(identity) + "\n" : "";
|
|
38246
38385
|
const instructions = (identityBlock + baseInstructions).trim() || void 0;
|
|
@@ -38298,8 +38437,13 @@ async function doBoot() {
|
|
|
38298
38437
|
if (!mainKey) {
|
|
38299
38438
|
mainProvider = "none";
|
|
38300
38439
|
config2.main_agent.provider = "none";
|
|
38301
|
-
|
|
38440
|
+
if (env.host === "claude-code") {
|
|
38441
|
+
process.stderr.write(`[gossipcat] \u2705 Native Claude Code orchestration enabled (no API LLM needed \u2014 host classifies via natural language)
|
|
38442
|
+
`);
|
|
38443
|
+
} else {
|
|
38444
|
+
process.stderr.write(`[gossipcat] \u274C No API keys available \u2014 orchestrator LLM disabled, features degrade to profile-based
|
|
38302
38445
|
`);
|
|
38446
|
+
}
|
|
38303
38447
|
}
|
|
38304
38448
|
}
|
|
38305
38449
|
ctx.mainProvider = mainProvider;
|
|
@@ -38572,7 +38716,7 @@ ctx.getModules = getModules;
|
|
|
38572
38716
|
var server = new import_mcp.McpServer(
|
|
38573
38717
|
{
|
|
38574
38718
|
name: "gossipcat",
|
|
38575
|
-
version:
|
|
38719
|
+
version: getGossipcatVersion()
|
|
38576
38720
|
},
|
|
38577
38721
|
{
|
|
38578
38722
|
instructions: "gossipcat \u2014 multi-agent orchestration. ALWAYS call gossip_status() first when starting work in this project. The gossip_status response loads the orchestrator role, dispatch rules, consensus workflow, native agent relay rule, sandbox enforcement, and other operating rules from .gossip/rules.md. These rules are not in this instruction text \u2014 they live in the gossip_status output to keep the instruction surface small and to allow per-project customization."
|
|
@@ -38806,7 +38950,7 @@ server.tool(
|
|
|
38806
38950
|
}
|
|
38807
38951
|
try {
|
|
38808
38952
|
const { readFileSync: readFileSync40 } = await import("fs");
|
|
38809
|
-
const quotaPath = (0,
|
|
38953
|
+
const quotaPath = (0, import_path52.join)(process.cwd(), ".gossip", "quota-state.json");
|
|
38810
38954
|
const quotaRaw = readFileSync40(quotaPath, "utf8");
|
|
38811
38955
|
const quotaState = JSON.parse(quotaRaw);
|
|
38812
38956
|
for (const [provider, state] of Object.entries(quotaState)) {
|
|
@@ -38822,15 +38966,15 @@ server.tool(
|
|
|
38822
38966
|
}
|
|
38823
38967
|
try {
|
|
38824
38968
|
const { readFileSync: readFileSync40, readdirSync: readdirSync13, statSync: statSync9 } = await import("fs");
|
|
38825
|
-
const reportsDir = (0,
|
|
38826
|
-
const perfPath = (0,
|
|
38969
|
+
const reportsDir = (0, import_path52.join)(process.cwd(), ".gossip", "consensus-reports");
|
|
38970
|
+
const perfPath = (0, import_path52.join)(process.cwd(), ".gossip", "agent-performance.jsonl");
|
|
38827
38971
|
const WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
38828
38972
|
const now = Date.now();
|
|
38829
38973
|
const recentReports = [];
|
|
38830
38974
|
try {
|
|
38831
38975
|
for (const fname of readdirSync13(reportsDir)) {
|
|
38832
38976
|
if (!fname.endsWith(".json")) continue;
|
|
38833
|
-
const fpath = (0,
|
|
38977
|
+
const fpath = (0, import_path52.join)(reportsDir, fname);
|
|
38834
38978
|
const st = statSync9(fpath);
|
|
38835
38979
|
if (now - st.mtimeMs > WINDOW_MS) continue;
|
|
38836
38980
|
recentReports.push({ id: fname.replace(/\.json$/, ""), mtimeMs: st.mtimeMs });
|
|
@@ -39079,7 +39223,7 @@ server.tool(
|
|
|
39079
39223
|
}
|
|
39080
39224
|
return { content: [{ type: "text", text: results.join("\n") }] };
|
|
39081
39225
|
}
|
|
39082
|
-
const { writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync:
|
|
39226
|
+
const { writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync: existsSync43 } = require("fs");
|
|
39083
39227
|
const { join: join48 } = require("path");
|
|
39084
39228
|
const root = process.cwd();
|
|
39085
39229
|
const CLAUDE_MODEL_MAP2 = {
|
|
@@ -39148,7 +39292,7 @@ server.tool(
|
|
|
39148
39292
|
continue;
|
|
39149
39293
|
}
|
|
39150
39294
|
const nativeFile = join48(root, ".claude", "agents", `${agent.id}.md`);
|
|
39151
|
-
const wasNative = existingAgents[agent.id]?.native ||
|
|
39295
|
+
const wasNative = existingAgents[agent.id]?.native || existsSync43(nativeFile);
|
|
39152
39296
|
if (wasNative) {
|
|
39153
39297
|
errors.push(`${agent.id}: cannot re-register native agent as custom \u2014 .claude/agents/${agent.id}.md exists. Remove the file first or keep it as native.`);
|
|
39154
39298
|
continue;
|
|
@@ -39991,7 +40135,7 @@ ${preview}` }]
|
|
|
39991
40135
|
const { SkillGapTracker: SkillGapTracker2, parseSkillFrontmatter: parseSkillFrontmatter2, normalizeSkillName: normalizeSkillName2 } = await Promise.resolve().then(() => (init_src4(), src_exports3));
|
|
39992
40136
|
const tracker = new SkillGapTracker2(process.cwd());
|
|
39993
40137
|
if (skills && skills.length > 0) {
|
|
39994
|
-
const { writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync:
|
|
40138
|
+
const { writeFileSync: writeFileSync17, mkdirSync: mkdirSync21, existsSync: existsSync43, readFileSync: readFileSync40 } = require("fs");
|
|
39995
40139
|
const { join: join48 } = require("path");
|
|
39996
40140
|
const dir = join48(process.cwd(), ".gossip", "skills");
|
|
39997
40141
|
mkdirSync21(dir, { recursive: true });
|
|
@@ -39999,7 +40143,7 @@ ${preview}` }]
|
|
|
39999
40143
|
for (const sk of skills) {
|
|
40000
40144
|
const name = normalizeSkillName2(sk.name);
|
|
40001
40145
|
const filePath = join48(dir, `${name}.md`);
|
|
40002
|
-
if (
|
|
40146
|
+
if (existsSync43(filePath)) {
|
|
40003
40147
|
const existing = readFileSync40(filePath, "utf-8");
|
|
40004
40148
|
const fm = parseSkillFrontmatter2(existing);
|
|
40005
40149
|
if (fm) {
|
|
@@ -40685,14 +40829,8 @@ ${match.url}` }] };
|
|
|
40685
40829
|
}
|
|
40686
40830
|
return { content: [{ type: "text", text: `Dedup check failed (${err.message ?? "unknown error"}). Not filing to avoid duplicates. Run \`gh auth status\` and retry.` }] };
|
|
40687
40831
|
}
|
|
40688
|
-
|
|
40689
|
-
|
|
40690
|
-
const { readFileSync: readFileSync40 } = await import("fs");
|
|
40691
|
-
const { join: join48 } = await import("path");
|
|
40692
|
-
const pkgRaw = readFileSync40(join48(process.cwd(), "package.json"), "utf-8");
|
|
40693
|
-
version2 = JSON.parse(pkgRaw).version ?? "unknown";
|
|
40694
|
-
} catch {
|
|
40695
|
-
}
|
|
40832
|
+
const { getGossipcatVersion: getGossipcatVersion2 } = await Promise.resolve().then(() => (init_version(), version_exports));
|
|
40833
|
+
const version2 = getGossipcatVersion2();
|
|
40696
40834
|
let gitHead = "unknown";
|
|
40697
40835
|
try {
|
|
40698
40836
|
const result = await execFile4("git", ["rev-parse", "--short", "HEAD"]);
|
|
@@ -40774,10 +40912,10 @@ function startHttpMcpTransport() {
|
|
|
40774
40912
|
}
|
|
40775
40913
|
let body;
|
|
40776
40914
|
if (req.method === "POST") {
|
|
40777
|
-
const raw = await new Promise((
|
|
40915
|
+
const raw = await new Promise((resolve18, reject) => {
|
|
40778
40916
|
const chunks = [];
|
|
40779
40917
|
req.on("data", (c) => chunks.push(c));
|
|
40780
|
-
req.on("end", () =>
|
|
40918
|
+
req.on("end", () => resolve18(Buffer.concat(chunks).toString("utf-8")));
|
|
40781
40919
|
req.on("error", reject);
|
|
40782
40920
|
});
|
|
40783
40921
|
try {
|