@markus-global/cli 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/start.js +3 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/markus.mjs +914 -814
- package/dist/web-ui/assets/index-CvTg0RPT.css +1 -0
- package/dist/web-ui/assets/index-DJ4hiBa1.js +61 -0
- package/dist/web-ui/index.html +2 -2
- package/package.json +1 -1
- package/templates/roles/agent-father/ROLE.md +15 -1
- package/templates/roles/developer/ROLE.md +61 -16
- package/templates/roles/devops/ROLE.md +26 -4
- package/templates/roles/project-manager/ROLE.md +59 -0
- package/templates/roles/qa-engineer/ROLE.md +36 -8
- package/templates/roles/research-assistant/ROLE.md +29 -2
- package/templates/roles/reviewer/ROLE.md +14 -7
- package/templates/roles/team-factory/ROLE.md +18 -1
- package/templates/skills/agent-building/SKILL.md +4 -2
- package/templates/skills/team-building/SKILL.md +25 -5
- package/templates/teams/content-team/ANNOUNCEMENT.md +20 -6
- package/templates/teams/content-team/NORMS.md +42 -14
- package/templates/teams/content-team/team.json +31 -6
- package/templates/teams/dev-squad/ANNOUNCEMENT.md +17 -6
- package/templates/teams/dev-squad/NORMS.md +60 -20
- package/templates/teams/dev-squad/team.json +38 -7
- package/templates/teams/engineering-pod/ANNOUNCEMENT.md +26 -0
- package/templates/teams/engineering-pod/NORMS.md +78 -0
- package/templates/teams/engineering-pod/team.json +50 -0
- package/templates/teams/research-lab/ANNOUNCEMENT.md +25 -0
- package/templates/teams/research-lab/NORMS.md +88 -0
- package/templates/teams/research-lab/team.json +43 -0
- package/templates/teams/startup-team/ANNOUNCEMENT.md +20 -7
- package/templates/teams/startup-team/NORMS.md +57 -19
- package/templates/teams/startup-team/team.json +24 -8
- package/dist/web-ui/assets/index-Bcc58A3R.css +0 -1
- package/dist/web-ui/assets/index-CM4C4YC8.js +0 -61
package/dist/markus.mjs
CHANGED
|
@@ -6248,7 +6248,7 @@ var init_context_engine = __esm({
|
|
|
6248
6248
|
}
|
|
6249
6249
|
}
|
|
6250
6250
|
parts.push("\n## Working Strategy");
|
|
6251
|
-
parts.push("For multi-step tasks: (1) Plan first \u2014 outline approach, use `todo.md` for long tasks. (2) Update progress after each step. (3) Restate objectives before each action. (4) On errors, analyze before retrying \u2014 try a different approach. (5) Offload large tool output to files.");
|
|
6251
|
+
parts.push("For multi-step tasks: (1) Plan first \u2014 outline approach, use `todo.md` for long tasks. (2) Update progress after each step. (3) Restate objectives before each action. (4) On errors, analyze before retrying \u2014 try a different approach. (5) Offload large tool output to files. (6) For heavy subtasks that need many tool calls or lots of file reading, delegate to `spawn_subagent` to keep your own context lean. Use `spawn_subagents` to run independent subtasks in parallel.");
|
|
6252
6252
|
const scenario = opts.scenario ?? "chat";
|
|
6253
6253
|
parts.push(this.buildScenarioSection(scenario));
|
|
6254
6254
|
const now2 = /* @__PURE__ */ new Date();
|
|
@@ -6313,6 +6313,28 @@ Current date and time: ${localStr} (${tz}, UTC${sign}${absH}:${absM})`);
|
|
|
6313
6313
|
lines.push("4. **Handle blockers**: If you cannot proceed, set status to `blocked` with a clear explanation.");
|
|
6314
6314
|
lines.push("5. **Submit for review**: When ALL subtasks are complete, call `task_submit_review` with summary + deliverables (MANDATORY \u2014 the task does NOT complete without this).");
|
|
6315
6315
|
lines.push("");
|
|
6316
|
+
lines.push("**Delegating subtasks to subagents (`spawn_subagent` / `spawn_subagents`):**");
|
|
6317
|
+
lines.push("");
|
|
6318
|
+
lines.push("Subagents are lightweight child loops with independent context windows. They inherit your tools but do NOT pollute your conversation history. Use them strategically:");
|
|
6319
|
+
lines.push("");
|
|
6320
|
+
lines.push("*DELEGATE to a subagent when the subtask is:*");
|
|
6321
|
+
lines.push("- **Deep exploration / analysis**: reading and cross-referencing many files (>5), codebase-wide searches, architecture analysis \u2014 a subagent keeps your own context clean");
|
|
6322
|
+
lines.push("- **Independent code modifications**: editing files in separate modules that don't depend on each other \u2014 perfect for `spawn_subagents` (parallel)");
|
|
6323
|
+
lines.push("- **Research & information gathering**: web searches, reading long documents, comparing alternatives \u2014 heavy context that you don't need to retain");
|
|
6324
|
+
lines.push("- **Test generation**: writing tests for already-implemented code \u2014 self-contained work with clear inputs/outputs");
|
|
6325
|
+
lines.push("- **Documentation / content generation**: producing docs, READMEs, changelogs from existing code \u2014 doesn't need your live reasoning context");
|
|
6326
|
+
lines.push("- **Repetitive multi-file refactoring**: renaming, format migrations, pattern replacements across many files \u2014 especially in parallel");
|
|
6327
|
+
lines.push("");
|
|
6328
|
+
lines.push("*Do NOT delegate when:*");
|
|
6329
|
+
lines.push("- The subtask is quick (\u22643 tool calls) \u2014 overhead of spawning a subagent is not worth it");
|
|
6330
|
+
lines.push("- The next subtask depends on detailed intermediate reasoning from this one \u2014 keep it in your own context");
|
|
6331
|
+
lines.push("- The subtask requires back-and-forth decisions that depend on your overall plan");
|
|
6332
|
+
lines.push("");
|
|
6333
|
+
lines.push("*Parallel execution pattern (`spawn_subagents`):*");
|
|
6334
|
+
lines.push("When you have N independent subtasks, use `spawn_subagents` with an array of tasks to run them all concurrently. Example: implementing separate API endpoints, writing tests for different modules, analyzing different components.");
|
|
6335
|
+
lines.push("");
|
|
6336
|
+
lines.push("*Workflow:* `subtask_create` (track) \u2192 `spawn_subagent`/`spawn_subagents` (execute) \u2192 verify result \u2192 `subtask_complete` (mark done).");
|
|
6337
|
+
lines.push("");
|
|
6316
6338
|
lines.push("**Quality standards:**");
|
|
6317
6339
|
lines.push("- Use all available tools to produce thorough, high-quality output");
|
|
6318
6340
|
lines.push("- If a tool call fails, analyze the error and try a different approach \u2014 do NOT repeat the same failing action");
|
|
@@ -6356,9 +6378,18 @@ Current date and time: ${localStr} (${tz}, UTC${sign}${absH}:${absM})`);
|
|
|
6356
6378
|
const lines = ["\n## Your Identity"];
|
|
6357
6379
|
if (opts.identity) {
|
|
6358
6380
|
const self = opts.identity.self;
|
|
6381
|
+
const teamName = opts.identity.team?.name;
|
|
6359
6382
|
lines.push(`- Name: ${self.name}`);
|
|
6360
6383
|
lines.push(`- Role: ${opts.role.name} (${opts.role.description})`);
|
|
6361
|
-
|
|
6384
|
+
if (self.agentRole === "manager" && teamName) {
|
|
6385
|
+
lines.push(`- Position: Team Manager of **${teamName}**`);
|
|
6386
|
+
} else if (self.agentRole === "manager") {
|
|
6387
|
+
lines.push(`- Position: Team Manager`);
|
|
6388
|
+
} else if (teamName) {
|
|
6389
|
+
lines.push(`- Position: Member of **${teamName}**`);
|
|
6390
|
+
} else {
|
|
6391
|
+
lines.push(`- Position: Team Member`);
|
|
6392
|
+
}
|
|
6362
6393
|
if (self.skills.length > 0) {
|
|
6363
6394
|
lines.push(`- Active Skills: ${self.skills.join(", ")}`);
|
|
6364
6395
|
}
|
|
@@ -6378,19 +6409,25 @@ Current date and time: ${localStr} (${tz}, UTC${sign}${absH}:${absM})`);
|
|
|
6378
6409
|
if (opts.identity.manager && opts.identity.self.agentRole !== "manager") {
|
|
6379
6410
|
lines.push(`
|
|
6380
6411
|
### Your Manager`);
|
|
6381
|
-
lines.push(`- ${opts.identity.manager.name} (
|
|
6412
|
+
lines.push(`- ${opts.identity.manager.name} (Team Manager) \u2014 report progress and escalate issues to them`);
|
|
6382
6413
|
}
|
|
6383
6414
|
if (opts.identity.colleagues.length > 0) {
|
|
6384
|
-
lines.push(`
|
|
6385
|
-
### Your
|
|
6415
|
+
lines.push(teamName ? `
|
|
6416
|
+
### Your Team \u2014 ${teamName}` : "\n### Your Team");
|
|
6386
6417
|
for (const c of opts.identity.colleagues) {
|
|
6387
6418
|
const statusTag = c.status ? ` [${c.status}]` : "";
|
|
6388
|
-
lines.push(`- ${c.name} (${c.role}
|
|
6419
|
+
lines.push(`- ${c.name} (${c.role})${statusTag}${c.skills?.length ? ` \u2014 skills: ${c.skills.join(", ")}` : ""}`);
|
|
6420
|
+
}
|
|
6421
|
+
}
|
|
6422
|
+
if (opts.identity.otherTeams && opts.identity.otherTeams.length > 0) {
|
|
6423
|
+
lines.push("\n### Other Teams (for cross-team coordination)");
|
|
6424
|
+
for (const t of opts.identity.otherTeams) {
|
|
6425
|
+
lines.push(`- **${t.name}**: ${t.members.map((m) => `${m.name} (${m.role})`).join(", ")}`);
|
|
6389
6426
|
}
|
|
6390
6427
|
}
|
|
6391
6428
|
if (opts.identity.humans.length > 0) {
|
|
6392
6429
|
lines.push(`
|
|
6393
|
-
### Human
|
|
6430
|
+
### Human Users`);
|
|
6394
6431
|
for (const h of opts.identity.humans) {
|
|
6395
6432
|
const tag = h.role === "owner" ? " \u2605 Owner" : h.role === "admin" ? " Admin" : "";
|
|
6396
6433
|
lines.push(`- ${h.name}${tag}`);
|
|
@@ -6399,11 +6436,11 @@ Current date and time: ${localStr} (${tz}, UTC${sign}${absH}:${absM})`);
|
|
|
6399
6436
|
if (opts.identity.self.agentRole === "manager") {
|
|
6400
6437
|
lines.push(`
|
|
6401
6438
|
### Manager Responsibilities`);
|
|
6402
|
-
lines.push(
|
|
6403
|
-
lines.push("1. **Routing** \u2014
|
|
6404
|
-
lines.push("2. **Coordination** \u2014 Assign tasks to
|
|
6405
|
-
lines.push("3. **Reporting** \u2014
|
|
6406
|
-
lines.push("4. **
|
|
6439
|
+
lines.push(`You manage${teamName ? ` the **${teamName}** team` : " your team"}. Your scope is your own team members listed above.`);
|
|
6440
|
+
lines.push("1. **Routing** \u2014 Determine which team member should handle incoming requests");
|
|
6441
|
+
lines.push("2. **Coordination** \u2014 Assign tasks to team members based on their skills and availability");
|
|
6442
|
+
lines.push("3. **Reporting** \u2014 Report your team's progress to human stakeholders");
|
|
6443
|
+
lines.push("4. **Cross-team** \u2014 Coordinate with other team managers via `agent_send_message` when work crosses team boundaries");
|
|
6407
6444
|
lines.push("5. **Escalation** \u2014 Escalate issues that require human decision to the Owner");
|
|
6408
6445
|
}
|
|
6409
6446
|
} else {
|
|
@@ -7366,7 +7403,9 @@ var init_tool_selector = __esm({
|
|
|
7366
7403
|
"memory_save",
|
|
7367
7404
|
"memory_search",
|
|
7368
7405
|
"deliverable_search",
|
|
7369
|
-
"deliverable_create"
|
|
7406
|
+
"deliverable_create",
|
|
7407
|
+
"spawn_subagent",
|
|
7408
|
+
"spawn_subagents"
|
|
7370
7409
|
]);
|
|
7371
7410
|
ToolSelector = class {
|
|
7372
7411
|
groups;
|
|
@@ -40979,10 +41018,53 @@ var init_patch = __esm({
|
|
|
40979
41018
|
// ../core/dist/tools/process-manager.js
|
|
40980
41019
|
import { spawn as spawn2 } from "node:child_process";
|
|
40981
41020
|
import { resolve as resolve8 } from "node:path";
|
|
41021
|
+
function onBackgroundCompletion(cb) {
|
|
41022
|
+
completionListeners.push(cb);
|
|
41023
|
+
return () => {
|
|
41024
|
+
const idx = completionListeners.indexOf(cb);
|
|
41025
|
+
if (idx >= 0)
|
|
41026
|
+
completionListeners.splice(idx, 1);
|
|
41027
|
+
};
|
|
41028
|
+
}
|
|
41029
|
+
function drainCompletedNotifications() {
|
|
41030
|
+
const results = [];
|
|
41031
|
+
for (const s of sessions.values()) {
|
|
41032
|
+
if (s.exitCode !== null && !s.notified) {
|
|
41033
|
+
s.notified = true;
|
|
41034
|
+
results.push({
|
|
41035
|
+
sessionId: s.id,
|
|
41036
|
+
command: s.command.slice(0, 200),
|
|
41037
|
+
exitCode: s.exitCode,
|
|
41038
|
+
durationMs: Date.now() - s.startedAt,
|
|
41039
|
+
stderrTail: s.stderr.slice(-10).join("\n"),
|
|
41040
|
+
stdoutTail: s.stdout.slice(-10).join("\n")
|
|
41041
|
+
});
|
|
41042
|
+
}
|
|
41043
|
+
}
|
|
41044
|
+
return results;
|
|
41045
|
+
}
|
|
41046
|
+
function notifyCompletion(session) {
|
|
41047
|
+
if (completionListeners.length === 0)
|
|
41048
|
+
return;
|
|
41049
|
+
const notification = {
|
|
41050
|
+
sessionId: session.id,
|
|
41051
|
+
command: session.command.slice(0, 200),
|
|
41052
|
+
exitCode: session.exitCode ?? -1,
|
|
41053
|
+
durationMs: Date.now() - session.startedAt,
|
|
41054
|
+
stderrTail: session.stderr.slice(-10).join("\n"),
|
|
41055
|
+
stdoutTail: session.stdout.slice(-10).join("\n")
|
|
41056
|
+
};
|
|
41057
|
+
for (const cb of completionListeners) {
|
|
41058
|
+
try {
|
|
41059
|
+
cb(notification);
|
|
41060
|
+
} catch {
|
|
41061
|
+
}
|
|
41062
|
+
}
|
|
41063
|
+
}
|
|
40982
41064
|
function createBackgroundExecTool(workspacePath) {
|
|
40983
41065
|
return {
|
|
40984
41066
|
name: "background_exec",
|
|
40985
|
-
description: 'Run a shell command in the background. Returns immediately with a session ID. Use the "process" tool to poll for results, view logs, or kill the process. Ideal for long-running commands like dev servers, test suites, or builds.',
|
|
41067
|
+
description: 'Run a shell command in the background. Returns immediately with a session ID. Use the "process" tool to poll for results, view logs, or kill the process. Ideal for long-running commands like dev servers, test suites, or builds. You will be automatically notified when the process completes.',
|
|
40986
41068
|
inputSchema: {
|
|
40987
41069
|
type: "object",
|
|
40988
41070
|
properties: {
|
|
@@ -41014,7 +41096,8 @@ function createBackgroundExecTool(workspacePath) {
|
|
|
41014
41096
|
exitCode: null,
|
|
41015
41097
|
stdout: [],
|
|
41016
41098
|
stderr: [],
|
|
41017
|
-
process: child
|
|
41099
|
+
process: child,
|
|
41100
|
+
notified: false
|
|
41018
41101
|
};
|
|
41019
41102
|
child.stdout?.on("data", (chunk) => {
|
|
41020
41103
|
const lines = chunk.toString().split("\n");
|
|
@@ -41032,16 +41115,20 @@ function createBackgroundExecTool(workspacePath) {
|
|
|
41032
41115
|
});
|
|
41033
41116
|
child.on("close", (code) => {
|
|
41034
41117
|
session.exitCode = code ?? -1;
|
|
41118
|
+
notifyCompletion(session);
|
|
41035
41119
|
});
|
|
41036
41120
|
child.on("exit", (code) => {
|
|
41037
|
-
if (session.exitCode === null)
|
|
41121
|
+
if (session.exitCode === null) {
|
|
41038
41122
|
session.exitCode = code ?? -1;
|
|
41123
|
+
notifyCompletion(session);
|
|
41124
|
+
}
|
|
41039
41125
|
});
|
|
41040
41126
|
if (timeoutSec > 0) {
|
|
41041
41127
|
setTimeout(() => {
|
|
41042
41128
|
if (session.exitCode === null) {
|
|
41043
41129
|
child.kill("SIGTERM");
|
|
41044
41130
|
session.exitCode = -1;
|
|
41131
|
+
notifyCompletion(session);
|
|
41045
41132
|
}
|
|
41046
41133
|
}, timeoutSec * 1e3);
|
|
41047
41134
|
}
|
|
@@ -41147,12 +41234,13 @@ function createProcessTool() {
|
|
|
41147
41234
|
}
|
|
41148
41235
|
};
|
|
41149
41236
|
}
|
|
41150
|
-
var sessions, sessionCounter;
|
|
41237
|
+
var sessions, sessionCounter, completionListeners;
|
|
41151
41238
|
var init_process_manager = __esm({
|
|
41152
41239
|
"../core/dist/tools/process-manager.js"() {
|
|
41153
41240
|
"use strict";
|
|
41154
41241
|
sessions = /* @__PURE__ */ new Map();
|
|
41155
41242
|
sessionCounter = 0;
|
|
41243
|
+
completionListeners = [];
|
|
41156
41244
|
}
|
|
41157
41245
|
});
|
|
41158
41246
|
|
|
@@ -41193,6 +41281,254 @@ var init_builtin = __esm({
|
|
|
41193
41281
|
}
|
|
41194
41282
|
});
|
|
41195
41283
|
|
|
41284
|
+
// ../core/dist/tools/subagent.js
|
|
41285
|
+
function buildToolMap(parentTools, allowedTools) {
|
|
41286
|
+
const toolMap = /* @__PURE__ */ new Map();
|
|
41287
|
+
if (allowedTools && allowedTools.length > 0) {
|
|
41288
|
+
for (const name of allowedTools) {
|
|
41289
|
+
const handler4 = parentTools.get(name);
|
|
41290
|
+
if (handler4 && !BLOCKED_TOOLS.has(name)) {
|
|
41291
|
+
toolMap.set(name, handler4);
|
|
41292
|
+
}
|
|
41293
|
+
}
|
|
41294
|
+
} else {
|
|
41295
|
+
for (const [name, handler4] of parentTools) {
|
|
41296
|
+
if (!BLOCKED_TOOLS.has(name)) {
|
|
41297
|
+
toolMap.set(name, handler4);
|
|
41298
|
+
}
|
|
41299
|
+
}
|
|
41300
|
+
}
|
|
41301
|
+
return toolMap;
|
|
41302
|
+
}
|
|
41303
|
+
async function runSubagentLoop(ctx, task, opts) {
|
|
41304
|
+
const hardCap = ctx.maxToolIterations ?? DEFAULT_MAX_SUBAGENT_ITERATIONS;
|
|
41305
|
+
const maxIter = Math.min(opts?.maxIterations ?? hardCap, hardCap);
|
|
41306
|
+
const parentTools = ctx.getTools();
|
|
41307
|
+
const provider = ctx.getProvider();
|
|
41308
|
+
const contextWindow = ctx.llmRouter.getModelContextWindow(provider);
|
|
41309
|
+
const toolMap = buildToolMap(parentTools, opts?.allowedTools);
|
|
41310
|
+
const llmTools = [...toolMap.values()].map((t) => ({
|
|
41311
|
+
name: t.name,
|
|
41312
|
+
description: t.description,
|
|
41313
|
+
inputSchema: t.inputSchema
|
|
41314
|
+
}));
|
|
41315
|
+
const systemContent = opts?.systemPrompt ?? "You are a focused subagent spawned to handle a specific subtask. Complete the task thoroughly and return a clear, concise result. Do not ask follow-up questions \u2014 work with what you have.";
|
|
41316
|
+
let messages2 = [
|
|
41317
|
+
{ role: "system", content: systemContent },
|
|
41318
|
+
{ role: "user", content: task }
|
|
41319
|
+
];
|
|
41320
|
+
log12.info("Subagent started", {
|
|
41321
|
+
parentAgent: ctx.agentId,
|
|
41322
|
+
taskLength: task.length,
|
|
41323
|
+
toolCount: toolMap.size,
|
|
41324
|
+
maxIterations: maxIter
|
|
41325
|
+
});
|
|
41326
|
+
let response = await ctx.llmRouter.chat({
|
|
41327
|
+
messages: messages2,
|
|
41328
|
+
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
41329
|
+
metadata: { agentId: ctx.agentId, sessionId: `subagent_${Date.now()}` }
|
|
41330
|
+
}, provider);
|
|
41331
|
+
let iterations = 0;
|
|
41332
|
+
while (response.finishReason === "tool_use" && response.toolCalls?.length || response.finishReason === "max_tokens") {
|
|
41333
|
+
if (++iterations > maxIter) {
|
|
41334
|
+
log12.warn("Subagent hit max iterations", { parentAgent: ctx.agentId, iterations });
|
|
41335
|
+
break;
|
|
41336
|
+
}
|
|
41337
|
+
if (response.finishReason === "max_tokens" && !response.toolCalls?.length) {
|
|
41338
|
+
messages2.push({ role: "assistant", content: response.content });
|
|
41339
|
+
messages2.push({
|
|
41340
|
+
role: "user",
|
|
41341
|
+
content: "[Continue from where you left off. Do not repeat what you already said.]"
|
|
41342
|
+
});
|
|
41343
|
+
} else {
|
|
41344
|
+
messages2.push({
|
|
41345
|
+
role: "assistant",
|
|
41346
|
+
content: response.content,
|
|
41347
|
+
toolCalls: response.toolCalls
|
|
41348
|
+
});
|
|
41349
|
+
for (const tc of response.toolCalls) {
|
|
41350
|
+
const handler4 = toolMap.get(tc.name);
|
|
41351
|
+
let result;
|
|
41352
|
+
if (!handler4) {
|
|
41353
|
+
result = JSON.stringify({ error: `Unknown tool: ${tc.name}` });
|
|
41354
|
+
} else {
|
|
41355
|
+
try {
|
|
41356
|
+
result = await handler4.execute(tc.arguments);
|
|
41357
|
+
result = ctx.offloadLargeResult(tc.name, result);
|
|
41358
|
+
} catch (err) {
|
|
41359
|
+
result = `Error: ${String(err)}`;
|
|
41360
|
+
}
|
|
41361
|
+
}
|
|
41362
|
+
messages2.push({ role: "tool", content: result, toolCallId: tc.id });
|
|
41363
|
+
}
|
|
41364
|
+
}
|
|
41365
|
+
messages2 = ctx.contextEngine.shrinkEphemeralMessages(messages2, contextWindow);
|
|
41366
|
+
response = await ctx.llmRouter.chat({
|
|
41367
|
+
messages: messages2,
|
|
41368
|
+
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
41369
|
+
metadata: { agentId: ctx.agentId, sessionId: `subagent_${Date.now()}` }
|
|
41370
|
+
}, provider);
|
|
41371
|
+
}
|
|
41372
|
+
log12.info("Subagent completed", {
|
|
41373
|
+
parentAgent: ctx.agentId,
|
|
41374
|
+
iterations,
|
|
41375
|
+
resultLength: response.content.length
|
|
41376
|
+
});
|
|
41377
|
+
return response.content;
|
|
41378
|
+
}
|
|
41379
|
+
function createSubagentTool(ctx) {
|
|
41380
|
+
return {
|
|
41381
|
+
name: "spawn_subagent",
|
|
41382
|
+
description: "Spawn a lightweight subagent with a clean, independent context to handle a focused subtask. The subagent inherits your tools but gets its own message history \u2014 it will not pollute your conversation. Use this to break down complex tasks: deep code analysis, research, file refactoring, test generation, etc. The subagent runs to completion and returns its final result to you. For running multiple subagents in parallel, use spawn_subagents instead.",
|
|
41383
|
+
inputSchema: {
|
|
41384
|
+
type: "object",
|
|
41385
|
+
properties: {
|
|
41386
|
+
task: {
|
|
41387
|
+
type: "string",
|
|
41388
|
+
description: "The focused task prompt for the subagent. Be specific about what you want it to do and what result to return."
|
|
41389
|
+
},
|
|
41390
|
+
system_prompt: {
|
|
41391
|
+
type: "string",
|
|
41392
|
+
description: "Optional custom system prompt for the subagent. Defaults to a focused task-execution prompt."
|
|
41393
|
+
},
|
|
41394
|
+
allowed_tools: {
|
|
41395
|
+
type: "array",
|
|
41396
|
+
items: { type: "string" },
|
|
41397
|
+
description: "Optional subset of tool names the subagent can use. If omitted, it inherits all parent tools."
|
|
41398
|
+
},
|
|
41399
|
+
max_iterations: {
|
|
41400
|
+
type: "number",
|
|
41401
|
+
description: "Max tool iterations. Lower this for quick tasks."
|
|
41402
|
+
}
|
|
41403
|
+
},
|
|
41404
|
+
required: ["task"]
|
|
41405
|
+
},
|
|
41406
|
+
async execute(args) {
|
|
41407
|
+
const task = args["task"];
|
|
41408
|
+
if (!task) {
|
|
41409
|
+
return JSON.stringify({ status: "error", error: "task is required" });
|
|
41410
|
+
}
|
|
41411
|
+
try {
|
|
41412
|
+
const result = await runSubagentLoop(ctx, task, {
|
|
41413
|
+
systemPrompt: args["system_prompt"],
|
|
41414
|
+
allowedTools: args["allowed_tools"],
|
|
41415
|
+
maxIterations: args["max_iterations"]
|
|
41416
|
+
});
|
|
41417
|
+
return JSON.stringify({ status: "completed", result });
|
|
41418
|
+
} catch (err) {
|
|
41419
|
+
log12.error("Subagent execution failed", { error: String(err) });
|
|
41420
|
+
return JSON.stringify({ status: "error", error: `Subagent failed: ${String(err)}` });
|
|
41421
|
+
}
|
|
41422
|
+
}
|
|
41423
|
+
};
|
|
41424
|
+
}
|
|
41425
|
+
function createParallelSubagentTool(ctx) {
|
|
41426
|
+
return {
|
|
41427
|
+
name: "spawn_subagents",
|
|
41428
|
+
description: "Spawn multiple subagents in PARALLEL, each with an independent context. All subagents run concurrently and their results are collected and returned together. Use this when you have multiple independent subtasks that can be worked on simultaneously: analyzing different files, researching different topics, implementing separate modules, etc. Each subagent gets its own clean message history and inherits your tools. IMPORTANT: Only use for truly independent tasks \u2014 subagents cannot communicate with each other.",
|
|
41429
|
+
inputSchema: {
|
|
41430
|
+
type: "object",
|
|
41431
|
+
properties: {
|
|
41432
|
+
tasks: {
|
|
41433
|
+
type: "array",
|
|
41434
|
+
items: {
|
|
41435
|
+
type: "object",
|
|
41436
|
+
properties: {
|
|
41437
|
+
id: {
|
|
41438
|
+
type: "string",
|
|
41439
|
+
description: 'A short identifier for this subtask (used to label results). E.g. "auth-review", "api-tests".'
|
|
41440
|
+
},
|
|
41441
|
+
task: {
|
|
41442
|
+
type: "string",
|
|
41443
|
+
description: "The focused task prompt for this subagent."
|
|
41444
|
+
},
|
|
41445
|
+
allowed_tools: {
|
|
41446
|
+
type: "array",
|
|
41447
|
+
items: { type: "string" },
|
|
41448
|
+
description: "Optional subset of tools this subagent can use."
|
|
41449
|
+
},
|
|
41450
|
+
max_iterations: {
|
|
41451
|
+
type: "number",
|
|
41452
|
+
description: "Optional max iterations for this subagent."
|
|
41453
|
+
}
|
|
41454
|
+
},
|
|
41455
|
+
required: ["id", "task"]
|
|
41456
|
+
},
|
|
41457
|
+
description: "Array of subtasks to execute in parallel. Each gets an independent subagent."
|
|
41458
|
+
},
|
|
41459
|
+
system_prompt: {
|
|
41460
|
+
type: "string",
|
|
41461
|
+
description: "Optional shared system prompt for all subagents."
|
|
41462
|
+
}
|
|
41463
|
+
},
|
|
41464
|
+
required: ["tasks"]
|
|
41465
|
+
},
|
|
41466
|
+
async execute(args) {
|
|
41467
|
+
const tasks2 = args["tasks"];
|
|
41468
|
+
if (!tasks2 || !Array.isArray(tasks2) || tasks2.length === 0) {
|
|
41469
|
+
return JSON.stringify({ status: "error", error: "tasks array is required and must not be empty" });
|
|
41470
|
+
}
|
|
41471
|
+
const MAX_PARALLEL = 10;
|
|
41472
|
+
if (tasks2.length > MAX_PARALLEL) {
|
|
41473
|
+
return JSON.stringify({
|
|
41474
|
+
status: "error",
|
|
41475
|
+
error: `Too many parallel subagents (${tasks2.length}). Maximum is ${MAX_PARALLEL}.`
|
|
41476
|
+
});
|
|
41477
|
+
}
|
|
41478
|
+
const sharedSystemPrompt = args["system_prompt"];
|
|
41479
|
+
log12.info("Spawning parallel subagents", {
|
|
41480
|
+
parentAgent: ctx.agentId,
|
|
41481
|
+
count: tasks2.length,
|
|
41482
|
+
taskIds: tasks2.map((t) => t.id)
|
|
41483
|
+
});
|
|
41484
|
+
const startTime = Date.now();
|
|
41485
|
+
const results = await Promise.allSettled(tasks2.map(async (t) => {
|
|
41486
|
+
const result = await runSubagentLoop(ctx, t.task, {
|
|
41487
|
+
systemPrompt: sharedSystemPrompt,
|
|
41488
|
+
allowedTools: t.allowed_tools,
|
|
41489
|
+
maxIterations: t.max_iterations
|
|
41490
|
+
});
|
|
41491
|
+
return { id: t.id, result };
|
|
41492
|
+
}));
|
|
41493
|
+
const output = results.map((r, i) => {
|
|
41494
|
+
if (r.status === "fulfilled") {
|
|
41495
|
+
return { id: r.value.id, status: "completed", result: r.value.result };
|
|
41496
|
+
}
|
|
41497
|
+
return { id: tasks2[i].id, status: "error", error: String(r.reason) };
|
|
41498
|
+
});
|
|
41499
|
+
const completed = output.filter((o) => o.status === "completed").length;
|
|
41500
|
+
const failed = output.filter((o) => o.status === "error").length;
|
|
41501
|
+
log12.info("Parallel subagents finished", {
|
|
41502
|
+
parentAgent: ctx.agentId,
|
|
41503
|
+
completed,
|
|
41504
|
+
failed,
|
|
41505
|
+
totalDurationMs: Date.now() - startTime
|
|
41506
|
+
});
|
|
41507
|
+
return JSON.stringify({
|
|
41508
|
+
status: "completed",
|
|
41509
|
+
summary: `${completed}/${tasks2.length} subagents completed successfully${failed > 0 ? `, ${failed} failed` : ""}`,
|
|
41510
|
+
durationMs: Date.now() - startTime,
|
|
41511
|
+
results: output
|
|
41512
|
+
});
|
|
41513
|
+
}
|
|
41514
|
+
};
|
|
41515
|
+
}
|
|
41516
|
+
var log12, DEFAULT_MAX_SUBAGENT_ITERATIONS, BLOCKED_TOOLS;
|
|
41517
|
+
var init_subagent = __esm({
|
|
41518
|
+
"../core/dist/tools/subagent.js"() {
|
|
41519
|
+
"use strict";
|
|
41520
|
+
init_dist();
|
|
41521
|
+
log12 = createLogger("subagent");
|
|
41522
|
+
DEFAULT_MAX_SUBAGENT_ITERATIONS = 200;
|
|
41523
|
+
BLOCKED_TOOLS = /* @__PURE__ */ new Set([
|
|
41524
|
+
"spawn_subagent",
|
|
41525
|
+
"spawn_subagents",
|
|
41526
|
+
"send_user_message",
|
|
41527
|
+
"discover_tools"
|
|
41528
|
+
]);
|
|
41529
|
+
}
|
|
41530
|
+
});
|
|
41531
|
+
|
|
41196
41532
|
// ../core/dist/concurrent/task-queue.js
|
|
41197
41533
|
var TaskPriority, TaskStatus, TaskType, TaskQueue;
|
|
41198
41534
|
var init_task_queue = __esm({
|
|
@@ -41907,12 +42243,12 @@ function hashString(str) {
|
|
|
41907
42243
|
function noDetection() {
|
|
41908
42244
|
return { detected: false, severity: "none", pattern: "", message: "" };
|
|
41909
42245
|
}
|
|
41910
|
-
var
|
|
42246
|
+
var log13, DEFAULT_CONFIG3, ToolLoopDetector;
|
|
41911
42247
|
var init_tool_loop_detector = __esm({
|
|
41912
42248
|
"../core/dist/tool-loop-detector.js"() {
|
|
41913
42249
|
"use strict";
|
|
41914
42250
|
init_dist();
|
|
41915
|
-
|
|
42251
|
+
log13 = createLogger("tool-loop-detector");
|
|
41916
42252
|
DEFAULT_CONFIG3 = {
|
|
41917
42253
|
enabled: true,
|
|
41918
42254
|
historySize: 30,
|
|
@@ -41982,12 +42318,12 @@ var init_tool_loop_detector = __esm({
|
|
|
41982
42318
|
}
|
|
41983
42319
|
if (streak >= this.config.criticalThreshold) {
|
|
41984
42320
|
const msg = `Critical: "${last.name}" called ${streak} times with identical arguments`;
|
|
41985
|
-
|
|
42321
|
+
log13.warn(msg);
|
|
41986
42322
|
return { detected: true, severity: "critical", pattern: "genericRepeat", message: msg };
|
|
41987
42323
|
}
|
|
41988
42324
|
if (streak >= this.config.warningThreshold) {
|
|
41989
42325
|
const msg = `Warning: "${last.name}" called ${streak} times with identical arguments`;
|
|
41990
|
-
|
|
42326
|
+
log13.warn(msg);
|
|
41991
42327
|
return { detected: true, severity: "warning", pattern: "genericRepeat", message: msg };
|
|
41992
42328
|
}
|
|
41993
42329
|
return noDetection();
|
|
@@ -42015,12 +42351,12 @@ var init_tool_loop_detector = __esm({
|
|
|
42015
42351
|
}
|
|
42016
42352
|
if (cycles >= Math.ceil(this.config.criticalThreshold / 2)) {
|
|
42017
42353
|
const msg = `Critical: ping-pong pattern detected \u2014 "${recent[recent.length - 2].name}" \u2194 "${recent[recent.length - 1].name}" for ${cycles} cycles`;
|
|
42018
|
-
|
|
42354
|
+
log13.warn(msg);
|
|
42019
42355
|
return { detected: true, severity: "critical", pattern: "pingPong", message: msg };
|
|
42020
42356
|
}
|
|
42021
42357
|
if (cycles >= Math.ceil(this.config.warningThreshold / 2)) {
|
|
42022
42358
|
const msg = `Warning: ping-pong pattern \u2014 "${recent[recent.length - 2].name}" \u2194 "${recent[recent.length - 1].name}" for ${cycles} cycles`;
|
|
42023
|
-
|
|
42359
|
+
log13.warn(msg);
|
|
42024
42360
|
return { detected: true, severity: "warning", pattern: "pingPong", message: msg };
|
|
42025
42361
|
}
|
|
42026
42362
|
return noDetection();
|
|
@@ -42044,12 +42380,12 @@ var init_tool_loop_detector = __esm({
|
|
|
42044
42380
|
}
|
|
42045
42381
|
if (sameResultStreak >= this.config.criticalThreshold) {
|
|
42046
42382
|
const msg = `Critical: "${recent[recent.length - 1].name}" returned identical results ${sameResultStreak} times \u2014 no progress`;
|
|
42047
|
-
|
|
42383
|
+
log13.warn(msg);
|
|
42048
42384
|
return { detected: true, severity: "critical", pattern: "noProgress", message: msg };
|
|
42049
42385
|
}
|
|
42050
42386
|
if (sameResultStreak >= this.config.warningThreshold) {
|
|
42051
42387
|
const msg = `Warning: "${recent[recent.length - 1].name}" returned identical results ${sameResultStreak} times`;
|
|
42052
|
-
|
|
42388
|
+
log13.warn(msg);
|
|
42053
42389
|
return { detected: true, severity: "warning", pattern: "noProgress", message: msg };
|
|
42054
42390
|
}
|
|
42055
42391
|
return noDetection();
|
|
@@ -42076,7 +42412,7 @@ function isErrorResult(result) {
|
|
|
42076
42412
|
return false;
|
|
42077
42413
|
}
|
|
42078
42414
|
}
|
|
42079
|
-
var taskAsyncContext,
|
|
42415
|
+
var taskAsyncContext, log14, Agent;
|
|
42080
42416
|
var init_agent2 = __esm({
|
|
42081
42417
|
"../core/dist/agent.js"() {
|
|
42082
42418
|
"use strict";
|
|
@@ -42093,11 +42429,13 @@ var init_agent2 = __esm({
|
|
|
42093
42429
|
init_environment_profile();
|
|
42094
42430
|
init_tool_selector();
|
|
42095
42431
|
init_builtin();
|
|
42432
|
+
init_subagent();
|
|
42433
|
+
init_process_manager();
|
|
42096
42434
|
init_concurrent();
|
|
42097
42435
|
init_task_queue();
|
|
42098
42436
|
init_tool_loop_detector();
|
|
42099
42437
|
taskAsyncContext = new AsyncLocalStorage();
|
|
42100
|
-
|
|
42438
|
+
log14 = createLogger("agent");
|
|
42101
42439
|
Agent = class _Agent {
|
|
42102
42440
|
id;
|
|
42103
42441
|
config;
|
|
@@ -42172,6 +42510,9 @@ var init_agent2 = __esm({
|
|
|
42172
42510
|
static NETWORK_RETRY_BASE_MS = 2e3;
|
|
42173
42511
|
static MEMORY_CONSOLIDATION_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
42174
42512
|
// 4 hours
|
|
42513
|
+
static DEFAULT_MAX_TOOL_ITERATIONS = 200;
|
|
42514
|
+
_maxToolIterations;
|
|
42515
|
+
_bgCompletionUnsub;
|
|
42175
42516
|
constructor(options) {
|
|
42176
42517
|
this.id = options.config.id || agentId();
|
|
42177
42518
|
this.config = { ...options.config, id: this.id };
|
|
@@ -42189,6 +42530,7 @@ var init_agent2 = __esm({
|
|
|
42189
42530
|
this.dataDir = options.dataDir;
|
|
42190
42531
|
this.pathPolicy = options.pathPolicy;
|
|
42191
42532
|
this.skillRegistry = options.skillRegistry;
|
|
42533
|
+
this._maxToolIterations = options.maxToolIterations ?? _Agent.DEFAULT_MAX_TOOL_ITERATIONS;
|
|
42192
42534
|
this.eventBus = new EventBus();
|
|
42193
42535
|
this.memory = options.memory ?? new MemoryStore(options.dataDir);
|
|
42194
42536
|
this.contextEngine = new ContextEngine();
|
|
@@ -42207,6 +42549,37 @@ var init_agent2 = __esm({
|
|
|
42207
42549
|
this.tools.set(tool.name, tool);
|
|
42208
42550
|
}
|
|
42209
42551
|
}
|
|
42552
|
+
const subagentCtx = {
|
|
42553
|
+
llmRouter: this.llmRouter,
|
|
42554
|
+
contextEngine: this.contextEngine,
|
|
42555
|
+
getTools: () => taskAsyncContext.getStore()?.tools ?? this.tools,
|
|
42556
|
+
getProvider: () => this.getEffectiveProvider(),
|
|
42557
|
+
agentId: this.id,
|
|
42558
|
+
offloadLargeResult: (toolName, result) => this.offloadLargeResult(toolName, result),
|
|
42559
|
+
maxToolIterations: this._maxToolIterations
|
|
42560
|
+
};
|
|
42561
|
+
this.tools.set("spawn_subagent", createSubagentTool(subagentCtx));
|
|
42562
|
+
this.tools.set("spawn_subagents", createParallelSubagentTool(subagentCtx));
|
|
42563
|
+
this._bgCompletionUnsub = onBackgroundCompletion((notification) => {
|
|
42564
|
+
const sessionId = this.currentSessionId;
|
|
42565
|
+
if (!sessionId)
|
|
42566
|
+
return;
|
|
42567
|
+
const status = notification.exitCode === 0 ? "succeeded" : `failed (exit ${notification.exitCode})`;
|
|
42568
|
+
const parts = [
|
|
42569
|
+
`[BACKGROUND PROCESS COMPLETED] Session ${notification.sessionId} ${status}.`,
|
|
42570
|
+
`Command: ${notification.command}`,
|
|
42571
|
+
`Duration: ${Math.round(notification.durationMs / 1e3)}s`
|
|
42572
|
+
];
|
|
42573
|
+
if (notification.exitCode !== 0 && notification.stderrTail) {
|
|
42574
|
+
parts.push(`Stderr (last lines):
|
|
42575
|
+
${notification.stderrTail}`);
|
|
42576
|
+
}
|
|
42577
|
+
if (notification.exitCode === 0 && notification.stdoutTail) {
|
|
42578
|
+
parts.push(`Output (last lines):
|
|
42579
|
+
${notification.stdoutTail}`);
|
|
42580
|
+
}
|
|
42581
|
+
this.injectUserMessage(sessionId, parts.join("\n"));
|
|
42582
|
+
});
|
|
42210
42583
|
this.taskExecutor = new TaskExecutor({
|
|
42211
42584
|
agentId: this.id,
|
|
42212
42585
|
maxConcurrentTasks: _Agent.MAX_CONCURRENT_TASKS,
|
|
@@ -42214,7 +42587,7 @@ var init_agent2 = __esm({
|
|
|
42214
42587
|
});
|
|
42215
42588
|
this.stateManager = new AgentStateManager(this.id, this.taskExecutor);
|
|
42216
42589
|
this.eventBus.on("heartbeat:trigger", (ctx) => {
|
|
42217
|
-
this.handleHeartbeat(ctx).catch((e) =>
|
|
42590
|
+
this.handleHeartbeat(ctx).catch((e) => log14.error("Heartbeat handler failed", { error: String(e) }));
|
|
42218
42591
|
});
|
|
42219
42592
|
const roleFilePath = join6(this.dataDir, "role", "ROLE.md");
|
|
42220
42593
|
this.toolHooks.register({
|
|
@@ -42223,13 +42596,13 @@ var init_agent2 = __esm({
|
|
|
42223
42596
|
if ((ctx.toolName === "file_edit" || ctx.toolName === "file_write") && ctx.success) {
|
|
42224
42597
|
const targetPath = ctx.arguments["path"] ?? ctx.arguments["filePath"] ?? "";
|
|
42225
42598
|
if (targetPath === roleFilePath || targetPath.endsWith("/role/ROLE.md")) {
|
|
42226
|
-
|
|
42599
|
+
log14.info("Agent modified its own ROLE.md \u2014 reloading role definition");
|
|
42227
42600
|
this.reloadRole();
|
|
42228
42601
|
}
|
|
42229
42602
|
}
|
|
42230
42603
|
}
|
|
42231
42604
|
});
|
|
42232
|
-
|
|
42605
|
+
log14.info(`Agent created: ${this.id}`, { name: this.config.name, role: this.role.name });
|
|
42233
42606
|
}
|
|
42234
42607
|
/**
|
|
42235
42608
|
* Resolve the LLM provider name for this agent.
|
|
@@ -42273,22 +42646,23 @@ var init_agent2 = __esm({
|
|
|
42273
42646
|
try {
|
|
42274
42647
|
this.environmentProfile = await detectEnvironment();
|
|
42275
42648
|
} catch (e) {
|
|
42276
|
-
|
|
42649
|
+
log14.warn("Environment detection failed", { error: String(e) });
|
|
42277
42650
|
}
|
|
42278
42651
|
const latestSession = this.memory.getLatestSession(this.id);
|
|
42279
42652
|
if (latestSession && latestSession.messages.length > 0) {
|
|
42280
42653
|
this.currentSessionId = latestSession.id;
|
|
42281
|
-
|
|
42654
|
+
log14.info(`Resumed session ${latestSession.id} with ${latestSession.messages.length} messages`);
|
|
42282
42655
|
}
|
|
42283
42656
|
this.heartbeat.start();
|
|
42284
42657
|
this.memoryConsolidationTimer = setInterval(() => {
|
|
42285
|
-
this.consolidateMemory().catch((e) =>
|
|
42658
|
+
this.consolidateMemory().catch((e) => log14.warn("Memory consolidation failed", { error: String(e) }));
|
|
42286
42659
|
}, _Agent.MEMORY_CONSOLIDATION_INTERVAL_MS);
|
|
42287
42660
|
this.eventBus.emit("agent:started", { agentId: this.id });
|
|
42288
|
-
|
|
42661
|
+
log14.info(`Agent started: ${this.config.name}`);
|
|
42289
42662
|
}
|
|
42290
42663
|
async stop() {
|
|
42291
42664
|
this.heartbeat.stop();
|
|
42665
|
+
this._bgCompletionUnsub?.();
|
|
42292
42666
|
if (this.memoryConsolidationTimer) {
|
|
42293
42667
|
clearInterval(this.memoryConsolidationTimer);
|
|
42294
42668
|
this.memoryConsolidationTimer = void 0;
|
|
@@ -42296,7 +42670,7 @@ var init_agent2 = __esm({
|
|
|
42296
42670
|
this.metricsCollector.flush();
|
|
42297
42671
|
this.setStatus("offline");
|
|
42298
42672
|
this.eventBus.emit("agent:stopped", { agentId: this.id });
|
|
42299
|
-
|
|
42673
|
+
log14.info(`Agent stopped: ${this.config.name}`);
|
|
42300
42674
|
}
|
|
42301
42675
|
/**
|
|
42302
42676
|
* Reload the agent's role from its ROLE.md file on disk.
|
|
@@ -42314,9 +42688,9 @@ var init_agent2 = __esm({
|
|
|
42314
42688
|
name,
|
|
42315
42689
|
systemPrompt: content
|
|
42316
42690
|
};
|
|
42317
|
-
|
|
42691
|
+
log14.info(`Role reloaded from disk for agent ${this.config.name}`);
|
|
42318
42692
|
} catch (err) {
|
|
42319
|
-
|
|
42693
|
+
log14.warn(`Failed to reload role for agent ${this.config.name}`, { error: String(err) });
|
|
42320
42694
|
}
|
|
42321
42695
|
}
|
|
42322
42696
|
/**
|
|
@@ -42326,7 +42700,7 @@ var init_agent2 = __esm({
|
|
|
42326
42700
|
startNewSession() {
|
|
42327
42701
|
const session = this.memory.createSession(this.id);
|
|
42328
42702
|
this.currentSessionId = session.id;
|
|
42329
|
-
|
|
42703
|
+
log14.info(`New session started for agent ${this.config.name}: ${session.id}`);
|
|
42330
42704
|
}
|
|
42331
42705
|
/**
|
|
42332
42706
|
* Bind the current in-memory session to a DB session ID (ses_*).
|
|
@@ -42336,7 +42710,7 @@ var init_agent2 = __esm({
|
|
|
42336
42710
|
bindDbSession(dbSessionId) {
|
|
42337
42711
|
if (this.currentSessionId) {
|
|
42338
42712
|
this.dbSessionMap.set(dbSessionId, this.currentSessionId);
|
|
42339
|
-
|
|
42713
|
+
log14.debug(`Bound DB session ${dbSessionId} \u2192 memory session ${this.currentSessionId}`);
|
|
42340
42714
|
}
|
|
42341
42715
|
}
|
|
42342
42716
|
/**
|
|
@@ -42350,7 +42724,7 @@ var init_agent2 = __esm({
|
|
|
42350
42724
|
const session2 = this.memory.getSession(existingMemorySessionId);
|
|
42351
42725
|
if (session2) {
|
|
42352
42726
|
this.currentSessionId = existingMemorySessionId;
|
|
42353
|
-
|
|
42727
|
+
log14.debug(`Switched to existing memory session ${existingMemorySessionId} for DB session ${dbSessionId}`);
|
|
42354
42728
|
return;
|
|
42355
42729
|
}
|
|
42356
42730
|
this.dbSessionMap.delete(dbSessionId);
|
|
@@ -42366,7 +42740,7 @@ var init_agent2 = __esm({
|
|
|
42366
42740
|
}
|
|
42367
42741
|
}
|
|
42368
42742
|
this.currentSessionId = session.id;
|
|
42369
|
-
|
|
42743
|
+
log14.info(`Restored session context for DB session ${dbSessionId} \u2192 memory session ${session.id} (${dbMessages.length} messages)`);
|
|
42370
42744
|
}
|
|
42371
42745
|
pause(reason) {
|
|
42372
42746
|
if (this.state.status === "offline")
|
|
@@ -42374,7 +42748,7 @@ var init_agent2 = __esm({
|
|
|
42374
42748
|
this.pauseReason = reason;
|
|
42375
42749
|
this.setStatus("paused");
|
|
42376
42750
|
this.eventBus.emit("agent:paused", { agentId: this.id, reason });
|
|
42377
|
-
|
|
42751
|
+
log14.info(`Agent paused: ${this.config.name}`, { reason });
|
|
42378
42752
|
}
|
|
42379
42753
|
resume() {
|
|
42380
42754
|
if (this.state.status !== "paused")
|
|
@@ -42382,7 +42756,7 @@ var init_agent2 = __esm({
|
|
|
42382
42756
|
this.pauseReason = void 0;
|
|
42383
42757
|
this.setStatus(this.activeTasks.size > 0 ? "working" : "idle");
|
|
42384
42758
|
this.eventBus.emit("agent:resumed", { agentId: this.id });
|
|
42385
|
-
|
|
42759
|
+
log14.info(`Agent resumed: ${this.config.name}`);
|
|
42386
42760
|
}
|
|
42387
42761
|
getPauseReason() {
|
|
42388
42762
|
return this.pauseReason;
|
|
@@ -42397,7 +42771,7 @@ var init_agent2 = __esm({
|
|
|
42397
42771
|
session = this.memory.getOrCreateSession(this.id, sessionId);
|
|
42398
42772
|
}
|
|
42399
42773
|
this.memory.appendMessage(sessionId, { role: "user", content });
|
|
42400
|
-
|
|
42774
|
+
log14.debug("Injected user message into session", { sessionId, contentLength: content.length });
|
|
42401
42775
|
}
|
|
42402
42776
|
/**
|
|
42403
42777
|
* 执行聊天任务(高优先级)
|
|
@@ -42515,7 +42889,7 @@ var init_agent2 = __esm({
|
|
|
42515
42889
|
cancelActiveStream() {
|
|
42516
42890
|
if (this.activeStreamToken) {
|
|
42517
42891
|
this.activeStreamToken.cancelled = true;
|
|
42518
|
-
|
|
42892
|
+
log14.info("Active stream cancelled", { agentId: this.id });
|
|
42519
42893
|
}
|
|
42520
42894
|
}
|
|
42521
42895
|
/** Get a cancel token for the current stream */
|
|
@@ -42681,7 +43055,7 @@ ${conversationText}`
|
|
|
42681
43055
|
const profile = this.config.profile;
|
|
42682
43056
|
if (profile?.maxTokensPerDay !== void 0 && profile.maxTokensPerDay !== null && this.state.tokensUsedToday >= profile.maxTokensPerDay) {
|
|
42683
43057
|
this.setStatus("paused");
|
|
42684
|
-
|
|
43058
|
+
log14.warn("Agent paused: daily token budget exceeded", {
|
|
42685
43059
|
agentId: this.id,
|
|
42686
43060
|
tokensUsedToday: this.state.tokensUsedToday,
|
|
42687
43061
|
maxTokensPerDay: profile.maxTokensPerDay
|
|
@@ -42716,9 +43090,15 @@ ${conversationText}`
|
|
|
42716
43090
|
this.notifyStateChange();
|
|
42717
43091
|
if (wasPausedByBudget) {
|
|
42718
43092
|
this.setStatus("idle");
|
|
42719
|
-
|
|
43093
|
+
log14.info("Agent resumed after daily token reset", { agentId: this.id });
|
|
42720
43094
|
}
|
|
42721
43095
|
}
|
|
43096
|
+
get maxToolIterations() {
|
|
43097
|
+
return this._maxToolIterations;
|
|
43098
|
+
}
|
|
43099
|
+
set maxToolIterations(value) {
|
|
43100
|
+
this._maxToolIterations = Math.max(1, Math.min(value, 1e4));
|
|
43101
|
+
}
|
|
42722
43102
|
setOrgContext(ctx) {
|
|
42723
43103
|
this.orgContext = ctx;
|
|
42724
43104
|
}
|
|
@@ -42980,7 +43360,7 @@ No recent activity recorded.`,
|
|
|
42980
43360
|
${report}`);
|
|
42981
43361
|
return report;
|
|
42982
43362
|
} catch (error) {
|
|
42983
|
-
|
|
43363
|
+
log14.error("Failed to generate daily report", { error: String(error) });
|
|
42984
43364
|
return `Unable to generate report: ${String(error)}`;
|
|
42985
43365
|
}
|
|
42986
43366
|
}
|
|
@@ -43102,7 +43482,7 @@ ${report}`);
|
|
|
43102
43482
|
toolDefinitions: llmTools
|
|
43103
43483
|
});
|
|
43104
43484
|
messages2 = prepared.messages;
|
|
43105
|
-
|
|
43485
|
+
log14.debug("Context usage for chat", { usagePercent: prepared.usage.usagePercent, totalUsed: prepared.usage.totalUsed });
|
|
43106
43486
|
}
|
|
43107
43487
|
const useCompaction = this.llmRouter.isCompactionSupported(this.getEffectiveProvider());
|
|
43108
43488
|
try {
|
|
@@ -43124,11 +43504,10 @@ ${report}`);
|
|
|
43124
43504
|
durationMs: Date.now() - llmStart,
|
|
43125
43505
|
success: true
|
|
43126
43506
|
});
|
|
43127
|
-
const MAX_TOOL_ITERATIONS = 200;
|
|
43128
43507
|
let toolIterations = 0;
|
|
43129
43508
|
while (response.finishReason === "tool_use" && response.toolCalls?.length || response.finishReason === "max_tokens") {
|
|
43130
|
-
if (++toolIterations >
|
|
43131
|
-
|
|
43509
|
+
if (++toolIterations > this._maxToolIterations) {
|
|
43510
|
+
log14.warn("Tool loop hit max iterations", {
|
|
43132
43511
|
agentId: this.id,
|
|
43133
43512
|
iterations: toolIterations
|
|
43134
43513
|
});
|
|
@@ -43239,7 +43618,7 @@ ${report}`);
|
|
|
43239
43618
|
const loopCheck = this.loopDetector.check();
|
|
43240
43619
|
if (loopCheck.detected) {
|
|
43241
43620
|
if (loopCheck.severity === "critical") {
|
|
43242
|
-
|
|
43621
|
+
log14.warn("Loop detector: critical pattern \u2014 breaking", {
|
|
43243
43622
|
agentId: this.id,
|
|
43244
43623
|
pattern: loopCheck.pattern
|
|
43245
43624
|
});
|
|
@@ -43335,7 +43714,7 @@ ${report}`);
|
|
|
43335
43714
|
success: false,
|
|
43336
43715
|
detail: String(error)
|
|
43337
43716
|
});
|
|
43338
|
-
|
|
43717
|
+
log14.error("Failed to handle message", { error: String(error) });
|
|
43339
43718
|
throw error;
|
|
43340
43719
|
}
|
|
43341
43720
|
}
|
|
@@ -43401,7 +43780,7 @@ ${report}`);
|
|
|
43401
43780
|
toolDefinitions: llmTools
|
|
43402
43781
|
});
|
|
43403
43782
|
const messages2 = preparedStream.messages;
|
|
43404
|
-
|
|
43783
|
+
log14.debug("Context usage for stream", { usagePercent: preparedStream.usage.usagePercent });
|
|
43405
43784
|
const useCompaction = this.llmRouter.isCompactionSupported(this.getEffectiveProvider());
|
|
43406
43785
|
const abortController = new AbortController();
|
|
43407
43786
|
let cancelPollTimer;
|
|
@@ -43431,14 +43810,14 @@ ${report}`);
|
|
|
43431
43810
|
let streamToolIterations = 0;
|
|
43432
43811
|
while (response.finishReason === "tool_use" && response.toolCalls?.length || response.finishReason === "max_tokens") {
|
|
43433
43812
|
if (++streamToolIterations > MAX_STREAM_TOOL_ITERATIONS) {
|
|
43434
|
-
|
|
43813
|
+
log14.warn("Stream tool loop hit max iterations", {
|
|
43435
43814
|
agentId: this.id,
|
|
43436
43815
|
iterations: streamToolIterations
|
|
43437
43816
|
});
|
|
43438
43817
|
break;
|
|
43439
43818
|
}
|
|
43440
43819
|
if (cancelToken?.cancelled) {
|
|
43441
|
-
|
|
43820
|
+
log14.info("Stream cancelled by user during tool loop", { agentId: this.id });
|
|
43442
43821
|
if (lastResponseContent && this.currentSessionId) {
|
|
43443
43822
|
this.memory.appendMessage(this.currentSessionId, {
|
|
43444
43823
|
role: "assistant",
|
|
@@ -43512,7 +43891,7 @@ ${report}`);
|
|
|
43512
43891
|
}
|
|
43513
43892
|
const loopCheck = this.loopDetector.check();
|
|
43514
43893
|
if (loopCheck.detected && loopCheck.severity === "critical") {
|
|
43515
|
-
|
|
43894
|
+
log14.warn("Stream loop detector: critical pattern \u2014 injecting warning", {
|
|
43516
43895
|
agentId: this.id,
|
|
43517
43896
|
pattern: loopCheck.pattern
|
|
43518
43897
|
});
|
|
@@ -43533,7 +43912,7 @@ ${report}`);
|
|
|
43533
43912
|
});
|
|
43534
43913
|
const updatedMessages = preparedCont.messages;
|
|
43535
43914
|
if (cancelToken?.cancelled) {
|
|
43536
|
-
|
|
43915
|
+
log14.info("Stream cancelled before LLM re-call", { agentId: this.id });
|
|
43537
43916
|
if (lastResponseContent && this.currentSessionId) {
|
|
43538
43917
|
this.memory.appendMessage(this.currentSessionId, {
|
|
43539
43918
|
role: "assistant",
|
|
@@ -43617,7 +43996,7 @@ ${report}`);
|
|
|
43617
43996
|
success: false,
|
|
43618
43997
|
detail: String(error)
|
|
43619
43998
|
});
|
|
43620
|
-
|
|
43999
|
+
log14.error("Failed to handle stream message", { error: String(error) });
|
|
43621
44000
|
throw error;
|
|
43622
44001
|
} finally {
|
|
43623
44002
|
if (cancelPollTimer)
|
|
@@ -43686,6 +44065,30 @@ ${report}`);
|
|
|
43686
44065
|
onLog({ seq: -1, type: "text_delta", content: text2, persist: false });
|
|
43687
44066
|
};
|
|
43688
44067
|
emit("status", "started", { agentId: this.id, agentName: this.config.name });
|
|
44068
|
+
let createdWorktreePath;
|
|
44069
|
+
if (taskWorkspace && taskWorkspace.branch) {
|
|
44070
|
+
const repoRoot = taskWorkspace.worktreePath;
|
|
44071
|
+
const isolatedPath = join6(repoRoot, ".worktrees", `task-${taskId2}`);
|
|
44072
|
+
try {
|
|
44073
|
+
const { exec: execCb3 } = await import("node:child_process");
|
|
44074
|
+
const { promisify: promisify4 } = await import("node:util");
|
|
44075
|
+
const execAsync3 = promisify4(execCb3);
|
|
44076
|
+
await execAsync3(`git worktree add "${isolatedPath}" -b "${taskWorkspace.branch}" "${taskWorkspace.baseBranch}"`, { cwd: repoRoot });
|
|
44077
|
+
taskWorkspace = { ...taskWorkspace, worktreePath: isolatedPath };
|
|
44078
|
+
createdWorktreePath = isolatedPath;
|
|
44079
|
+
emit("status", `worktree created: ${isolatedPath}`, { branch: taskWorkspace.branch });
|
|
44080
|
+
log14.info("Git worktree created for task", { taskId: taskId2, path: isolatedPath, branch: taskWorkspace.branch });
|
|
44081
|
+
} catch (wtErr) {
|
|
44082
|
+
const msg = String(wtErr.message ?? wtErr);
|
|
44083
|
+
if (msg.includes("already exists")) {
|
|
44084
|
+
taskWorkspace = { ...taskWorkspace, worktreePath: isolatedPath };
|
|
44085
|
+
createdWorktreePath = isolatedPath;
|
|
44086
|
+
log14.warn("Worktree already exists, reusing", { taskId: taskId2, path: isolatedPath });
|
|
44087
|
+
} else {
|
|
44088
|
+
log14.warn("Failed to create worktree, falling back to repo root", { taskId: taskId2, error: msg });
|
|
44089
|
+
}
|
|
44090
|
+
}
|
|
44091
|
+
}
|
|
43689
44092
|
if (taskWorkspace) {
|
|
43690
44093
|
const worktreePolicy = {
|
|
43691
44094
|
primaryWorkspace: taskWorkspace.worktreePath,
|
|
@@ -43710,7 +44113,7 @@ ${report}`);
|
|
|
43710
44113
|
if (ctx) {
|
|
43711
44114
|
ctx.tools = taskLocalTools;
|
|
43712
44115
|
}
|
|
43713
|
-
|
|
44116
|
+
log14.info("Tools rebound to worktree workspace (task-local)", {
|
|
43714
44117
|
taskId: taskId2,
|
|
43715
44118
|
agentId: this.id,
|
|
43716
44119
|
worktreePath: taskWorkspace.worktreePath
|
|
@@ -43837,7 +44240,7 @@ ${report}`);
|
|
|
43837
44240
|
toolDefinitions: llmTools
|
|
43838
44241
|
});
|
|
43839
44242
|
const messages2 = preparedTask.messages;
|
|
43840
|
-
|
|
44243
|
+
log14.debug("Context usage for task execution", { taskId: taskId2, usagePercent: preparedTask.usage.usagePercent, totalUsed: preparedTask.usage.totalUsed });
|
|
43841
44244
|
let taskLlmStart = Date.now();
|
|
43842
44245
|
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages: messages2, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction }, (event) => {
|
|
43843
44246
|
if (event.type === "text_delta" && event.text) {
|
|
@@ -43854,7 +44257,7 @@ ${report}`);
|
|
|
43854
44257
|
if (cancelToken?.cancelled) {
|
|
43855
44258
|
flushText();
|
|
43856
44259
|
emit("status", "cancelled", { reason: "Task execution was stopped externally" });
|
|
43857
|
-
|
|
44260
|
+
log14.info("Task execution cancelled externally", { taskId: taskId2, agentId: this.id });
|
|
43858
44261
|
return;
|
|
43859
44262
|
}
|
|
43860
44263
|
flushText();
|
|
@@ -43906,7 +44309,7 @@ ${report}`);
|
|
|
43906
44309
|
}
|
|
43907
44310
|
if (cancelToken?.cancelled) {
|
|
43908
44311
|
emit("status", "cancelled", { reason: "Task execution was stopped externally" });
|
|
43909
|
-
|
|
44312
|
+
log14.info("Task execution cancelled externally after tools", { taskId: taskId2, agentId: this.id });
|
|
43910
44313
|
return;
|
|
43911
44314
|
}
|
|
43912
44315
|
if (taskToolIterations > 0 && taskToolIterations % 10 === 0) {
|
|
@@ -43921,7 +44324,7 @@ ${report}`);
|
|
|
43921
44324
|
"- Use `task_note` to record progress before submitting."
|
|
43922
44325
|
].join("\n")
|
|
43923
44326
|
});
|
|
43924
|
-
|
|
44327
|
+
log14.debug("Injected task completion reminder", { taskId: taskId2, iteration: taskToolIterations });
|
|
43925
44328
|
}
|
|
43926
44329
|
const preparedTaskCont = await this.contextEngine.prepareMessages({
|
|
43927
44330
|
systemPrompt,
|
|
@@ -43953,7 +44356,7 @@ ${report}`);
|
|
|
43953
44356
|
if (cancelToken?.cancelled) {
|
|
43954
44357
|
flushText();
|
|
43955
44358
|
emit("status", "cancelled", { reason: "Task execution was stopped externally" });
|
|
43956
|
-
|
|
44359
|
+
log14.info("Task execution cancelled externally after completion", { taskId: taskId2, agentId: this.id });
|
|
43957
44360
|
return;
|
|
43958
44361
|
}
|
|
43959
44362
|
flushText();
|
|
@@ -43962,12 +44365,12 @@ ${report}`);
|
|
|
43962
44365
|
emit("status", "execution_finished", {});
|
|
43963
44366
|
this.metricsCollector.recordTaskCompletion(taskId2, "completed", Date.now() - taskStartMs);
|
|
43964
44367
|
this.eventBus.emit("task:completed", { taskId: taskId2, agentId: this.id });
|
|
43965
|
-
|
|
44368
|
+
log14.info("Task execution finished", { taskId: taskId2, agentId: this.id });
|
|
43966
44369
|
} catch (error) {
|
|
43967
44370
|
if (cancelToken?.cancelled) {
|
|
43968
44371
|
flushText();
|
|
43969
44372
|
emit("status", "cancelled", { reason: "Task execution was stopped externally" });
|
|
43970
|
-
|
|
44373
|
+
log14.info("Task execution cancelled (caught abort)", { taskId: taskId2, agentId: this.id });
|
|
43971
44374
|
return;
|
|
43972
44375
|
}
|
|
43973
44376
|
if (textBuffer.trim()) {
|
|
@@ -43985,7 +44388,7 @@ ${report}`);
|
|
|
43985
44388
|
success: false,
|
|
43986
44389
|
detail: String(error)
|
|
43987
44390
|
});
|
|
43988
|
-
|
|
44391
|
+
log14.error("Task execution failed", { taskId: taskId2, agentId: this.id, error: String(error) });
|
|
43989
44392
|
this.eventBus.emit("task:failed", { taskId: taskId2, agentId: this.id, error: String(error) });
|
|
43990
44393
|
taskFailed = String(error);
|
|
43991
44394
|
throw error;
|
|
@@ -44214,7 +44617,7 @@ ${report}`);
|
|
|
44214
44617
|
for (const tool of updatedTools) {
|
|
44215
44618
|
this.tools.set(tool.name, tool);
|
|
44216
44619
|
}
|
|
44217
|
-
|
|
44620
|
+
log14.info("Granted read-only access", { agentId: this.id, path });
|
|
44218
44621
|
}
|
|
44219
44622
|
/**
|
|
44220
44623
|
* Remove a previously granted read-only path and rebuild tools.
|
|
@@ -44235,7 +44638,7 @@ ${report}`);
|
|
|
44235
44638
|
for (const tool of updatedTools) {
|
|
44236
44639
|
this.tools.set(tool.name, tool);
|
|
44237
44640
|
}
|
|
44238
|
-
|
|
44641
|
+
log14.info("Revoked read-only access", { agentId: this.id, path });
|
|
44239
44642
|
}
|
|
44240
44643
|
getState() {
|
|
44241
44644
|
const state = { ...this.state };
|
|
@@ -44354,7 +44757,7 @@ ${report}`);
|
|
|
44354
44757
|
}
|
|
44355
44758
|
try {
|
|
44356
44759
|
const result2 = await this.skillInstaller(args);
|
|
44357
|
-
|
|
44760
|
+
log14.info("Skill installed via discover_tools", { agentId: this.id, skill: skillName, method: result2.method });
|
|
44358
44761
|
return JSON.stringify({
|
|
44359
44762
|
status: "ok",
|
|
44360
44763
|
installed: result2.name,
|
|
@@ -44392,7 +44795,7 @@ ${report}`);
|
|
|
44392
44795
|
this.activateTools(toolNames);
|
|
44393
44796
|
mcpToolCount = mcpTools.length;
|
|
44394
44797
|
} catch (err) {
|
|
44395
|
-
|
|
44798
|
+
log14.warn("Failed to activate skill MCP servers via discover_tools", {
|
|
44396
44799
|
agentId: this.id,
|
|
44397
44800
|
skill: name,
|
|
44398
44801
|
error: String(err)
|
|
@@ -44407,7 +44810,7 @@ ${report}`);
|
|
|
44407
44810
|
if (!skill.manifest.instructions && mcpToolCount === 0)
|
|
44408
44811
|
parts.push("skill found but has no instructions or MCP tools");
|
|
44409
44812
|
activated.push(parts.length > 1 ? `${parts[0]} (${parts.slice(1).join(", ")})` : parts[0]);
|
|
44410
|
-
|
|
44813
|
+
log14.info("Skill activated via discover_tools", {
|
|
44411
44814
|
agentId: this.id,
|
|
44412
44815
|
skill: name,
|
|
44413
44816
|
mcpToolCount,
|
|
@@ -44443,7 +44846,7 @@ ${report}`);
|
|
|
44443
44846
|
}
|
|
44444
44847
|
try {
|
|
44445
44848
|
const result = await this.userMessageSender(message);
|
|
44446
|
-
|
|
44849
|
+
log14.info("Proactive message sent to user", { agentId: this.id, sessionId: result.sessionId });
|
|
44447
44850
|
return JSON.stringify({ status: "ok", sessionId: result.sessionId, messageId: result.messageId });
|
|
44448
44851
|
} catch (err) {
|
|
44449
44852
|
return JSON.stringify({ status: "error", message: `Failed to send message: ${String(err)}` });
|
|
@@ -44467,7 +44870,7 @@ ${report}`);
|
|
|
44467
44870
|
const needsApproval = this.config.profile?.requireApprovalFor?.some((pattern) => toolCall.name === pattern || toolCall.name.startsWith(pattern.replace("*", "")));
|
|
44468
44871
|
if (needsApproval) {
|
|
44469
44872
|
if (this.approvalCallback) {
|
|
44470
|
-
|
|
44873
|
+
log14.info(`Tool ${toolCall.name} requires approval, requesting...`, { agentId: this.id });
|
|
44471
44874
|
const approved = await this.approvalCallback({
|
|
44472
44875
|
agentId: this.id,
|
|
44473
44876
|
agentName: this.config.name,
|
|
@@ -44476,15 +44879,15 @@ ${report}`);
|
|
|
44476
44879
|
reason: `Agent wants to execute '${toolCall.name}'`
|
|
44477
44880
|
});
|
|
44478
44881
|
if (!approved) {
|
|
44479
|
-
|
|
44882
|
+
log14.info(`Tool ${toolCall.name} execution denied by human`, { agentId: this.id });
|
|
44480
44883
|
return JSON.stringify({
|
|
44481
44884
|
status: "denied",
|
|
44482
44885
|
error: `Execution of '${toolCall.name}' was denied by human reviewer`
|
|
44483
44886
|
});
|
|
44484
44887
|
}
|
|
44485
|
-
|
|
44888
|
+
log14.info(`Tool ${toolCall.name} approved by human`, { agentId: this.id });
|
|
44486
44889
|
} else {
|
|
44487
|
-
|
|
44890
|
+
log14.warn(`Tool ${toolCall.name} requires approval but no approval callback set`, {
|
|
44488
44891
|
agentId: this.id
|
|
44489
44892
|
});
|
|
44490
44893
|
}
|
|
@@ -44525,10 +44928,10 @@ ${report}`);
|
|
|
44525
44928
|
try {
|
|
44526
44929
|
if (attempt > 0) {
|
|
44527
44930
|
const delay = _Agent.TOOL_RETRY_BASE_MS * Math.pow(2, attempt - 1);
|
|
44528
|
-
|
|
44931
|
+
log14.info(`Retrying tool ${toolCall.name} (attempt ${attempt + 1})`, { delay });
|
|
44529
44932
|
await new Promise((r) => setTimeout(r, delay));
|
|
44530
44933
|
}
|
|
44531
|
-
|
|
44934
|
+
log14.debug(`Executing tool: ${toolCall.name}`, { args: effectiveArgs, attempt });
|
|
44532
44935
|
const span = startSpan("agent.tool", { tool: toolCall.name, attempt });
|
|
44533
44936
|
try {
|
|
44534
44937
|
const result = await handler4.execute(effectiveArgs, onOutput);
|
|
@@ -44551,7 +44954,7 @@ ${report}`);
|
|
|
44551
44954
|
}
|
|
44552
44955
|
} catch (error) {
|
|
44553
44956
|
lastError = error;
|
|
44554
|
-
|
|
44957
|
+
log14.error(`Tool execution failed: ${toolCall.name} (attempt ${attempt + 1})`, {
|
|
44555
44958
|
error: String(error)
|
|
44556
44959
|
});
|
|
44557
44960
|
}
|
|
@@ -44563,7 +44966,7 @@ ${report}`);
|
|
|
44563
44966
|
handleFailure(reason) {
|
|
44564
44967
|
this.consecutiveFailures++;
|
|
44565
44968
|
if (this.consecutiveFailures >= _Agent.MAX_CONSECUTIVE_FAILURES) {
|
|
44566
|
-
|
|
44969
|
+
log14.warn("Consecutive failure threshold reached, escalating to human", {
|
|
44567
44970
|
agentId: this.id,
|
|
44568
44971
|
failures: this.consecutiveFailures
|
|
44569
44972
|
});
|
|
@@ -44588,7 +44991,7 @@ ${report}`);
|
|
|
44588
44991
|
throw error;
|
|
44589
44992
|
}
|
|
44590
44993
|
const delay = _Agent.NETWORK_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
44591
|
-
|
|
44994
|
+
log14.warn(`${label} failed with network error, retrying (${attempt + 1}/${_Agent.NETWORK_RETRY_MAX})`, {
|
|
44592
44995
|
agentId: this.id,
|
|
44593
44996
|
error: String(error).slice(0, 200),
|
|
44594
44997
|
delay
|
|
@@ -44612,7 +45015,7 @@ ${report}`);
|
|
|
44612
45015
|
}
|
|
44613
45016
|
}
|
|
44614
45017
|
async handleHeartbeat(ctx) {
|
|
44615
|
-
|
|
45018
|
+
log14.info("Processing heartbeat check-in");
|
|
44616
45019
|
const activityId = this.startActivity("heartbeat", "Heartbeat check-in", {});
|
|
44617
45020
|
let lastHeartbeatSummary = "";
|
|
44618
45021
|
try {
|
|
@@ -44664,10 +45067,12 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44664
45067
|
'- **type**: "file"',
|
|
44665
45068
|
"- **Content must be concise, clear, and accurate**:",
|
|
44666
45069
|
" 1. **My work today**: What you personally accomplished (tasks reviewed, approved/rejected, decisions made)",
|
|
44667
|
-
" 2. **
|
|
44668
|
-
" 3. **
|
|
44669
|
-
" 4. **
|
|
45070
|
+
" 2. **My team progress**: What each member of YOUR team accomplished today (use `team_status` to check). Focus on your own team only.",
|
|
45071
|
+
" 3. **Cross-team interactions**: Any coordination with other teams (if applicable)",
|
|
45072
|
+
" 4. **Blockers & risks**: Anything stalled or at risk within your team",
|
|
45073
|
+
" 5. **Plan for tomorrow**: Top priorities for the next day",
|
|
44670
45074
|
"- Keep it under 500 words. No filler. Every sentence must carry information.",
|
|
45075
|
+
"- IMPORTANT: Only report on YOUR team. Do NOT report on agents from other teams.",
|
|
44671
45076
|
"- If no meaningful activity happened today, say so honestly \u2014 do not fabricate work.",
|
|
44672
45077
|
"- The system will automatically mark the report as created after this heartbeat.",
|
|
44673
45078
|
""
|
|
@@ -44687,26 +45092,67 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44687
45092
|
"Quality bar: Only record insights that are **specific**, **actionable**, and **non-obvious**.",
|
|
44688
45093
|
"Skip if nothing meaningful happened since last heartbeat."
|
|
44689
45094
|
].join("\n");
|
|
45095
|
+
const bgCompletions = drainCompletedNotifications();
|
|
45096
|
+
let bgCompletionSection = "";
|
|
45097
|
+
if (bgCompletions.length > 0) {
|
|
45098
|
+
const lines = bgCompletions.map((n) => {
|
|
45099
|
+
const status = n.exitCode === 0 ? "OK" : `FAILED (exit ${n.exitCode})`;
|
|
45100
|
+
return `- [${status}] \`${n.command}\` (${Math.round(n.durationMs / 1e3)}s)${n.exitCode !== 0 && n.stderrTail ? `
|
|
45101
|
+
stderr: ${n.stderrTail.slice(0, 200)}` : ""}`;
|
|
45102
|
+
});
|
|
45103
|
+
bgCompletionSection = [
|
|
45104
|
+
"",
|
|
45105
|
+
"## Background Processes Completed",
|
|
45106
|
+
`${bgCompletions.length} background process(es) finished since last check:`,
|
|
45107
|
+
...lines,
|
|
45108
|
+
"Review any failures and take action if needed."
|
|
45109
|
+
].join("\n");
|
|
45110
|
+
}
|
|
44690
45111
|
const prompt = [
|
|
44691
45112
|
"[HEARTBEAT CHECK-IN]",
|
|
44692
45113
|
"",
|
|
44693
45114
|
"## Your Checklist",
|
|
44694
45115
|
checklist,
|
|
44695
45116
|
lastHeartbeatSummary,
|
|
45117
|
+
bgCompletionSection,
|
|
44696
45118
|
failedTaskRecoverySection,
|
|
44697
45119
|
dailyReportSection,
|
|
44698
45120
|
selfEvolutionSection,
|
|
44699
45121
|
"",
|
|
44700
|
-
"##
|
|
45122
|
+
"## Core Principle: Patrol, Don't Build",
|
|
45123
|
+
"Heartbeat is a patrol \u2014 observe, triage, and take lightweight actions. Heavy work belongs in tasks.",
|
|
45124
|
+
"",
|
|
45125
|
+
"## What You CAN Do (lightweight actions)",
|
|
45126
|
+
"- **Check status**: `task_list`, `task_get`, `team_status` \u2014 see what's going on",
|
|
45127
|
+
"- **Send messages**: `agent_send_message`, `send_user_message` \u2014 notify people of issues or updates",
|
|
45128
|
+
"- **Create tasks**: `task_create` \u2014 if you spot something that needs doing, create a task for it (assign to yourself or others)",
|
|
45129
|
+
'- **Trigger existing tasks**: `task_update(status: "in_progress")` \u2014 restart failed tasks or unblock stuck ones',
|
|
45130
|
+
'- **Retry failed tasks**: If tasks assigned to you are in `failed` status, retry via `task_update(status: "in_progress")` with a note',
|
|
45131
|
+
"- **Quick reviews**: If tasks are in `review` where you are the reviewer, review them now (may need more tool calls)",
|
|
45132
|
+
"- **Save insights**: `memory_save` \u2014 record observations, lessons, and patterns",
|
|
45133
|
+
"- **Propose requirements**: `requirement_propose` \u2014 suggest work based on what you observe",
|
|
45134
|
+
"",
|
|
45135
|
+
"## What You Must NOT Do",
|
|
45136
|
+
"- **No complex multi-step implementation** \u2014 don't write code, refactor modules, or do deep analysis in heartbeat",
|
|
45137
|
+
"- If you identify something complex that needs doing:",
|
|
45138
|
+
" 1. Notify the user via `send_user_message` explaining what you found and why it matters",
|
|
45139
|
+
" 2. Create a task via `task_create` with clear description and acceptance criteria",
|
|
45140
|
+
" 3. The user will approve and the task system handles execution",
|
|
45141
|
+
"",
|
|
45142
|
+
"## Conditional Actions",
|
|
45143
|
+
"- If background processes failed \u2192 check the error, notify the responsible developer or user",
|
|
45144
|
+
"- If tasks are blocked for too long \u2192 investigate blockers, send a message to the assignee or PM",
|
|
45145
|
+
"- If a dependency task completed \u2192 check if downstream tasks can be unblocked",
|
|
45146
|
+
"- If you notice a recurring pattern \u2192 save it as a lesson via `memory_save`",
|
|
45147
|
+
"",
|
|
45148
|
+
"## Finishing Up",
|
|
44701
45149
|
"- Compare against your last heartbeat summary above. Skip unchanged items.",
|
|
44702
|
-
"-
|
|
44703
|
-
"-
|
|
44704
|
-
'- **Exception \u2014 failed tasks**: If you find tasks assigned to you in `failed` status, retry them via `task_update(status: "in_progress")` with a note.',
|
|
44705
|
-
"- **Exception \u2014 daily report**: If the Daily Report Required section is present above, you MUST produce the report. This may require additional tool calls.",
|
|
44706
|
-
"- At the end, call `memory_save` with key `heartbeat:summary` \u2014 one line per finding.",
|
|
45150
|
+
"- If the Daily Report Required section is present above, you MUST produce the report.",
|
|
45151
|
+
"- Call `memory_save` with key `heartbeat:summary` \u2014 one line per finding.",
|
|
44707
45152
|
"- If nothing needs attention and no daily report is due, respond with exactly: HEARTBEAT_OK"
|
|
44708
45153
|
].join("\n");
|
|
44709
45154
|
const baseTools = [
|
|
45155
|
+
"task_create",
|
|
44710
45156
|
"task_list",
|
|
44711
45157
|
"task_update",
|
|
44712
45158
|
"task_get",
|
|
@@ -44759,7 +45205,7 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44759
45205
|
lastError = error;
|
|
44760
45206
|
if (attempt < HEARTBEAT_MAX_RETRIES) {
|
|
44761
45207
|
const delay = HEARTBEAT_RETRY_BASE_MS * Math.pow(2, attempt);
|
|
44762
|
-
|
|
45208
|
+
log14.warn(`Heartbeat attempt ${attempt + 1}/${HEARTBEAT_MAX_RETRIES + 1} failed, retrying in ${delay}ms`, {
|
|
44763
45209
|
agentId: this.id,
|
|
44764
45210
|
error: String(error).slice(0, 200)
|
|
44765
45211
|
});
|
|
@@ -44770,7 +45216,7 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44770
45216
|
this.emitActivityLog(activityId, "error", String(lastError));
|
|
44771
45217
|
this.endActivity(activityId);
|
|
44772
45218
|
this.metricsCollector.recordHeartbeat(false);
|
|
44773
|
-
|
|
45219
|
+
log14.error("Heartbeat failed after all retries", {
|
|
44774
45220
|
agentId: this.id,
|
|
44775
45221
|
attempts: HEARTBEAT_MAX_RETRIES + 1,
|
|
44776
45222
|
error: String(lastError)
|
|
@@ -44809,9 +45255,9 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44809
45255
|
maxHistory: 25,
|
|
44810
45256
|
scenario: "heartbeat"
|
|
44811
45257
|
});
|
|
44812
|
-
|
|
45258
|
+
log14.info("Memory flush completed before compaction", { agentId: this.id, sessionId });
|
|
44813
45259
|
} catch (error) {
|
|
44814
|
-
|
|
45260
|
+
log14.warn("Memory flush failed, proceeding with compaction anyway", { error: String(error) });
|
|
44815
45261
|
}
|
|
44816
45262
|
}
|
|
44817
45263
|
/**
|
|
@@ -44829,7 +45275,7 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44829
45275
|
await this.memoryFlush(this.currentSessionId);
|
|
44830
45276
|
const { flushedCount } = this.memory.compactSession(this.currentSessionId, 15);
|
|
44831
45277
|
if (flushedCount > 0) {
|
|
44832
|
-
|
|
45278
|
+
log14.info("Memory consolidation: compacted main session", {
|
|
44833
45279
|
agentId: this.id,
|
|
44834
45280
|
flushedCount,
|
|
44835
45281
|
remaining: session.messages.length
|
|
@@ -44843,9 +45289,9 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44843
45289
|
await this.dreamConsolidateMemory(entries2);
|
|
44844
45290
|
this.pruneMemoryMd();
|
|
44845
45291
|
}
|
|
44846
|
-
|
|
45292
|
+
log14.debug("Memory consolidation completed", { agentId: this.id });
|
|
44847
45293
|
} catch (error) {
|
|
44848
|
-
|
|
45294
|
+
log14.warn("Memory consolidation failed", { agentId: this.id, error: String(error) });
|
|
44849
45295
|
}
|
|
44850
45296
|
}
|
|
44851
45297
|
/**
|
|
@@ -44861,7 +45307,7 @@ ${todayLog.slice(0, 3e3)}
|
|
|
44861
45307
|
return `[${i}] id=${e.id} type=${e.type} date=${e.timestamp?.slice(0, 10) ?? "?"}${tags}
|
|
44862
45308
|
${e.content.slice(0, 200)}`;
|
|
44863
45309
|
}).join("\n\n");
|
|
44864
|
-
|
|
45310
|
+
log14.info("Dream cycle starting", {
|
|
44865
45311
|
agentId: this.id,
|
|
44866
45312
|
totalEntries: entries2.length,
|
|
44867
45313
|
batchSize: batch.length,
|
|
@@ -44900,11 +45346,11 @@ ${e.content.slice(0, 200)}`;
|
|
|
44900
45346
|
});
|
|
44901
45347
|
const jsonMatch = response.match(/\{[\s\S]*\}/);
|
|
44902
45348
|
if (!jsonMatch) {
|
|
44903
|
-
|
|
45349
|
+
log14.debug("Dream cycle: no valid JSON in response, skipping");
|
|
44904
45350
|
return;
|
|
44905
45351
|
}
|
|
44906
45352
|
const plan = JSON.parse(jsonMatch[0]);
|
|
44907
|
-
|
|
45353
|
+
log14.info("Dream cycle plan", {
|
|
44908
45354
|
agentId: this.id,
|
|
44909
45355
|
toRemove: plan.remove?.length ?? 0,
|
|
44910
45356
|
toMerge: plan.merge?.length ?? 0,
|
|
@@ -44946,7 +45392,7 @@ ${e.content.slice(0, 200)}`;
|
|
|
44946
45392
|
}
|
|
44947
45393
|
}
|
|
44948
45394
|
if (removedCount > 0 || mergedCount > 0) {
|
|
44949
|
-
|
|
45395
|
+
log14.info("Dream cycle completed", {
|
|
44950
45396
|
agentId: this.id,
|
|
44951
45397
|
entriesBefore: entries2.length,
|
|
44952
45398
|
removed: removedCount,
|
|
@@ -44954,10 +45400,10 @@ ${e.content.slice(0, 200)}`;
|
|
|
44954
45400
|
entriesAfter: this.memory.getEntries().length
|
|
44955
45401
|
});
|
|
44956
45402
|
} else {
|
|
44957
|
-
|
|
45403
|
+
log14.debug("Dream cycle: no changes needed", { agentId: this.id });
|
|
44958
45404
|
}
|
|
44959
45405
|
} catch (error) {
|
|
44960
|
-
|
|
45406
|
+
log14.warn("Dream cycle failed", { agentId: this.id, error: String(error) });
|
|
44961
45407
|
}
|
|
44962
45408
|
}
|
|
44963
45409
|
/**
|
|
@@ -45000,7 +45446,7 @@ ${e.content.slice(0, 200)}`;
|
|
|
45000
45446
|
if (pruned !== content.trim()) {
|
|
45001
45447
|
const memoryMdPath = join6(this.dataDir, "MEMORY.md");
|
|
45002
45448
|
writeFileSync7(memoryMdPath, pruned + "\n");
|
|
45003
|
-
|
|
45449
|
+
log14.info("Pruned MEMORY.md: removed daily-report sections and LLM artifacts", { agentId: this.id });
|
|
45004
45450
|
}
|
|
45005
45451
|
}
|
|
45006
45452
|
};
|
|
@@ -45158,12 +45604,12 @@ ${sharedContent}` : roleContent;
|
|
|
45158
45604
|
|
|
45159
45605
|
// ../core/dist/tools/mcp-client.js
|
|
45160
45606
|
import { spawn as spawn3 } from "node:child_process";
|
|
45161
|
-
var
|
|
45607
|
+
var log15, MCPClientManager;
|
|
45162
45608
|
var init_mcp_client = __esm({
|
|
45163
45609
|
"../core/dist/tools/mcp-client.js"() {
|
|
45164
45610
|
"use strict";
|
|
45165
45611
|
init_dist();
|
|
45166
|
-
|
|
45612
|
+
log15 = createLogger("mcp-client");
|
|
45167
45613
|
MCPClientManager = class _MCPClientManager {
|
|
45168
45614
|
servers = /* @__PURE__ */ new Map();
|
|
45169
45615
|
requestId = 0;
|
|
@@ -45179,31 +45625,31 @@ var init_mcp_client = __esm({
|
|
|
45179
45625
|
async connectByKey(key2, displayName, config) {
|
|
45180
45626
|
const existing = this.servers.get(key2);
|
|
45181
45627
|
if (existing) {
|
|
45182
|
-
|
|
45628
|
+
log15.info(`MCP server ${displayName} already connected, reusing (${existing.tools.length} tools)`);
|
|
45183
45629
|
return existing.tools;
|
|
45184
45630
|
}
|
|
45185
|
-
|
|
45631
|
+
log15.info(`Connecting to MCP server: ${displayName}`, { command: config.command, key: key2 });
|
|
45186
45632
|
const proc = spawn3(config.command, config.args ?? [], {
|
|
45187
45633
|
stdio: ["pipe", "pipe", "pipe"],
|
|
45188
45634
|
env: { ...process.env, ...config.env }
|
|
45189
45635
|
});
|
|
45190
45636
|
proc.on("error", (err) => {
|
|
45191
|
-
|
|
45637
|
+
log15.error(`MCP server ${displayName} error`, { error: String(err) });
|
|
45192
45638
|
});
|
|
45193
45639
|
const stderrChunks = [];
|
|
45194
45640
|
proc.stderr?.on("data", (data) => {
|
|
45195
45641
|
const text2 = data.toString();
|
|
45196
45642
|
stderrChunks.push(text2);
|
|
45197
45643
|
if (stderrChunks.length <= 5) {
|
|
45198
|
-
|
|
45644
|
+
log15.warn(`MCP server ${displayName} stderr`, { text: text2.trimEnd() });
|
|
45199
45645
|
}
|
|
45200
45646
|
});
|
|
45201
45647
|
proc.on("exit", (code) => {
|
|
45202
45648
|
const stderr = stderrChunks.join("").trim();
|
|
45203
45649
|
if (stderr) {
|
|
45204
|
-
|
|
45650
|
+
log15.error(`MCP server ${displayName} exited with stderr`, { code, stderr: stderr.slice(0, 500) });
|
|
45205
45651
|
} else {
|
|
45206
|
-
|
|
45652
|
+
log15.info(`MCP server ${displayName} exited`, { code });
|
|
45207
45653
|
}
|
|
45208
45654
|
this.servers.delete(key2);
|
|
45209
45655
|
this.stdoutBuffers.delete(proc);
|
|
@@ -45227,7 +45673,7 @@ var init_mcp_client = __esm({
|
|
|
45227
45673
|
const toolsResult = await this.sendRequest(proc, "tools/list", {});
|
|
45228
45674
|
const tools = toolsResult?.tools ?? [];
|
|
45229
45675
|
this.servers.set(key2, { process: proc, tools });
|
|
45230
|
-
|
|
45676
|
+
log15.info(`MCP server ${displayName} connected with ${tools.length} tools`);
|
|
45231
45677
|
return tools;
|
|
45232
45678
|
} catch (err) {
|
|
45233
45679
|
proc.kill();
|
|
@@ -45302,7 +45748,7 @@ var init_mcp_client = __esm({
|
|
|
45302
45748
|
server.process.kill();
|
|
45303
45749
|
this.servers.delete(name);
|
|
45304
45750
|
this.stdoutBuffers.delete(server.process);
|
|
45305
|
-
|
|
45751
|
+
log15.info(`MCP server disconnected: ${name}`);
|
|
45306
45752
|
}
|
|
45307
45753
|
}
|
|
45308
45754
|
async disconnectServerScoped(name, scopeId) {
|
|
@@ -45379,12 +45825,12 @@ var init_mcp_client = __esm({
|
|
|
45379
45825
|
});
|
|
45380
45826
|
|
|
45381
45827
|
// ../core/dist/tools/browser-session.js
|
|
45382
|
-
var
|
|
45828
|
+
var log16, TARGET_ID_PARAM_NAMES, BrowserSessionManager;
|
|
45383
45829
|
var init_browser_session = __esm({
|
|
45384
45830
|
"../core/dist/tools/browser-session.js"() {
|
|
45385
45831
|
"use strict";
|
|
45386
45832
|
init_dist();
|
|
45387
|
-
|
|
45833
|
+
log16 = createLogger("browser-session");
|
|
45388
45834
|
TARGET_ID_PARAM_NAMES = ["targetId", "id", "pageId", "target"];
|
|
45389
45835
|
BrowserSessionManager = class {
|
|
45390
45836
|
/** agentId → set of owned target/page IDs */
|
|
@@ -45468,7 +45914,7 @@ var init_browser_session = __esm({
|
|
|
45468
45914
|
const owned = this.getOwned(agentId2);
|
|
45469
45915
|
for (const id of ids) {
|
|
45470
45916
|
owned.add(id);
|
|
45471
|
-
|
|
45917
|
+
log16.debug(`Page ${id} assigned to agent ${agentId2}`);
|
|
45472
45918
|
}
|
|
45473
45919
|
return result;
|
|
45474
45920
|
}
|
|
@@ -45491,7 +45937,7 @@ var init_browser_session = __esm({
|
|
|
45491
45937
|
return owned.has(id);
|
|
45492
45938
|
});
|
|
45493
45939
|
if (parsed.length !== filtered.length) {
|
|
45494
|
-
|
|
45940
|
+
log16.debug(`list_pages: agent ${agentId2} sees ${filtered.length}/${parsed.length} pages (strict ownership filter)`);
|
|
45495
45941
|
}
|
|
45496
45942
|
return JSON.stringify(filtered);
|
|
45497
45943
|
}
|
|
@@ -45509,7 +45955,7 @@ var init_browser_session = __esm({
|
|
|
45509
45955
|
const targetId = this.extractTargetIdFromArgs(args);
|
|
45510
45956
|
if (targetId && !this.isOwnedByMe(agentId2, targetId)) {
|
|
45511
45957
|
const msg = `Cannot select page ${targetId}: you can only select pages you created with new_page. Use new_page to open your own tab.`;
|
|
45512
|
-
|
|
45958
|
+
log16.warn(msg, { agentId: agentId2, targetId });
|
|
45513
45959
|
return JSON.stringify({ error: msg });
|
|
45514
45960
|
}
|
|
45515
45961
|
return handler4.execute(args);
|
|
@@ -45524,7 +45970,7 @@ var init_browser_session = __esm({
|
|
|
45524
45970
|
const targetId = this.extractTargetIdFromArgs(args);
|
|
45525
45971
|
if (targetId && !this.isOwnedByMe(agentId2, targetId)) {
|
|
45526
45972
|
const msg = `Cannot close page ${targetId}: you can only close pages you created with new_page. Do not close tabs you did not open.`;
|
|
45527
|
-
|
|
45973
|
+
log16.warn(msg, { agentId: agentId2, targetId });
|
|
45528
45974
|
return JSON.stringify({ error: msg });
|
|
45529
45975
|
}
|
|
45530
45976
|
const result = await handler4.execute(args);
|
|
@@ -45547,13 +45993,13 @@ var init_browser_session = __esm({
|
|
|
45547
45993
|
const owned = this.getOwned(agentId2);
|
|
45548
45994
|
if (owned.size === 0) {
|
|
45549
45995
|
const msg = "You have no owned pages. Call new_page first to create your own tab before navigating.";
|
|
45550
|
-
|
|
45996
|
+
log16.warn(`Agent ${agentId2} called navigate_page with no owned pages`, { agentId: agentId2, url: args.url });
|
|
45551
45997
|
return JSON.stringify({ error: msg });
|
|
45552
45998
|
}
|
|
45553
45999
|
const targetId = this.extractTargetIdFromArgs(args);
|
|
45554
46000
|
if (targetId && !owned.has(targetId)) {
|
|
45555
46001
|
const msg = `Cannot navigate page ${targetId}: it is not a page you own. Use new_page to create your own tab.`;
|
|
45556
|
-
|
|
46002
|
+
log16.warn(msg, { agentId: agentId2, targetId });
|
|
45557
46003
|
return JSON.stringify({ error: msg });
|
|
45558
46004
|
}
|
|
45559
46005
|
return handler4.execute(args);
|
|
@@ -45577,13 +46023,13 @@ var init_browser_session = __esm({
|
|
|
45577
46023
|
const owned = this.getOwned(agentId2);
|
|
45578
46024
|
if (owned.size === 0) {
|
|
45579
46025
|
const msg = `Cannot use ${toolName} before creating a tab. Call new_page first to create your own tab.`;
|
|
45580
|
-
|
|
46026
|
+
log16.warn(`Agent ${agentId2} called ${toolName} with no owned pages`, { agentId: agentId2 });
|
|
45581
46027
|
return JSON.stringify({ error: msg });
|
|
45582
46028
|
}
|
|
45583
46029
|
const targetId = this.extractTargetIdFromArgs(args);
|
|
45584
46030
|
if (targetId && !owned.has(targetId)) {
|
|
45585
46031
|
const msg = `Cannot use ${toolName} on page ${targetId}: it is not a page you own. Only interact with pages you created via new_page.`;
|
|
45586
|
-
|
|
46032
|
+
log16.warn(msg, { agentId: agentId2, targetId, toolName });
|
|
45587
46033
|
return JSON.stringify({ error: msg });
|
|
45588
46034
|
}
|
|
45589
46035
|
return handler4.execute(args);
|
|
@@ -45597,7 +46043,7 @@ var init_browser_session = __esm({
|
|
|
45597
46043
|
cleanupAgent(agentId2) {
|
|
45598
46044
|
const owned = this.ownedPages.get(agentId2);
|
|
45599
46045
|
if (owned?.size) {
|
|
45600
|
-
|
|
46046
|
+
log16.info(`Cleaning up ${owned.size} browser page(s) for agent ${agentId2}`);
|
|
45601
46047
|
}
|
|
45602
46048
|
this.ownedPages.delete(agentId2);
|
|
45603
46049
|
}
|
|
@@ -45647,7 +46093,7 @@ function createManagerTools(ctx) {
|
|
|
45647
46093
|
const targetId = args["agent_id"];
|
|
45648
46094
|
const message = args["message"];
|
|
45649
46095
|
ctx.delegateMessage(targetId, message, "manager").catch((err) => {
|
|
45650
|
-
|
|
46096
|
+
log17.warn(`Delegated task to ${targetId} failed in background`, { error: String(err) });
|
|
45651
46097
|
});
|
|
45652
46098
|
return JSON.stringify({ status: "dispatched", message: "Task dispatched. The agent will work on it independently." });
|
|
45653
46099
|
}
|
|
@@ -45726,12 +46172,12 @@ function createManagerTools(ctx) {
|
|
|
45726
46172
|
] : []
|
|
45727
46173
|
];
|
|
45728
46174
|
}
|
|
45729
|
-
var
|
|
46175
|
+
var log17;
|
|
45730
46176
|
var init_manager = __esm({
|
|
45731
46177
|
"../core/dist/tools/manager.js"() {
|
|
45732
46178
|
"use strict";
|
|
45733
46179
|
init_dist();
|
|
45734
|
-
|
|
46180
|
+
log17 = createLogger("manager-tools");
|
|
45735
46181
|
}
|
|
45736
46182
|
});
|
|
45737
46183
|
|
|
@@ -45771,19 +46217,19 @@ function createA2ATools(ctx) {
|
|
|
45771
46217
|
return JSON.stringify({ status: "error", error: "Cannot send a message to yourself" });
|
|
45772
46218
|
}
|
|
45773
46219
|
if (waitForReply) {
|
|
45774
|
-
|
|
46220
|
+
log18.info(`A2A request (sync): ${ctx.selfName} \u2192 ${targetId}`, { messageLen: message.length });
|
|
45775
46221
|
try {
|
|
45776
46222
|
const reply = await ctx.sendMessage(targetId, message, ctx.selfId, ctx.selfName);
|
|
45777
|
-
|
|
46223
|
+
log18.info(`A2A reply received: ${targetId} \u2192 ${ctx.selfName}`, { replyLen: reply.length });
|
|
45778
46224
|
return JSON.stringify({ status: "replied", from: targetId, reply });
|
|
45779
46225
|
} catch (err) {
|
|
45780
|
-
|
|
46226
|
+
log18.warn(`A2A sync message to ${targetId} failed`, { error: String(err) });
|
|
45781
46227
|
return JSON.stringify({ status: "error", error: `Failed to get reply: ${String(err)}` });
|
|
45782
46228
|
}
|
|
45783
46229
|
}
|
|
45784
|
-
|
|
46230
|
+
log18.info(`A2A notify (async): ${ctx.selfName} \u2192 ${targetId}`, { messageLen: message.length });
|
|
45785
46231
|
ctx.sendMessage(targetId, message, ctx.selfId, ctx.selfName).catch((err) => {
|
|
45786
|
-
|
|
46232
|
+
log18.warn(`A2A async message to ${targetId} failed in background`, { error: String(err) });
|
|
45787
46233
|
});
|
|
45788
46234
|
return JSON.stringify({ status: "dispatched", message: "Notification sent. The agent will process it independently." });
|
|
45789
46235
|
}
|
|
@@ -45859,12 +46305,12 @@ function createA2ATools(ctx) {
|
|
|
45859
46305
|
}] : []
|
|
45860
46306
|
];
|
|
45861
46307
|
}
|
|
45862
|
-
var
|
|
46308
|
+
var log18;
|
|
45863
46309
|
var init_a2a = __esm({
|
|
45864
46310
|
"../core/dist/tools/a2a.js"() {
|
|
45865
46311
|
"use strict";
|
|
45866
46312
|
init_dist();
|
|
45867
|
-
|
|
46313
|
+
log18 = createLogger("a2a-tools");
|
|
45868
46314
|
}
|
|
45869
46315
|
});
|
|
45870
46316
|
|
|
@@ -45891,7 +46337,7 @@ function createStructuredA2ATools(ctx) {
|
|
|
45891
46337
|
}
|
|
45892
46338
|
};
|
|
45893
46339
|
const message = JSON.stringify(structuredMessage);
|
|
45894
|
-
|
|
46340
|
+
log19.info(`Structured A2A message dispatched: ${ctx.selfName} \u2192 ${targetId}`, {
|
|
45895
46341
|
messageType,
|
|
45896
46342
|
payloadSize: JSON.stringify(payload).length
|
|
45897
46343
|
});
|
|
@@ -45899,7 +46345,7 @@ function createStructuredA2ATools(ctx) {
|
|
|
45899
46345
|
try {
|
|
45900
46346
|
await ctx.sendMessage(targetId, message, ctx.selfId, ctx.selfName);
|
|
45901
46347
|
} catch (err) {
|
|
45902
|
-
|
|
46348
|
+
log19.warn(`Structured A2A message to ${targetId} failed in background`, {
|
|
45903
46349
|
error: String(err),
|
|
45904
46350
|
messageType
|
|
45905
46351
|
});
|
|
@@ -45993,12 +46439,12 @@ function createStructuredA2ATools(ctx) {
|
|
|
45993
46439
|
}
|
|
45994
46440
|
];
|
|
45995
46441
|
}
|
|
45996
|
-
var
|
|
46442
|
+
var log19, A2A_SEND_INTERVAL_MS, sendQueue;
|
|
45997
46443
|
var init_a2a_structured = __esm({
|
|
45998
46444
|
"../core/dist/tools/a2a-structured.js"() {
|
|
45999
46445
|
"use strict";
|
|
46000
46446
|
init_dist();
|
|
46001
|
-
|
|
46447
|
+
log19 = createLogger("a2a-structured-tools");
|
|
46002
46448
|
A2A_SEND_INTERVAL_MS = 3e4;
|
|
46003
46449
|
sendQueue = Promise.resolve();
|
|
46004
46450
|
}
|
|
@@ -46118,7 +46564,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46118
46564
|
taskType,
|
|
46119
46565
|
scheduleConfig
|
|
46120
46566
|
});
|
|
46121
|
-
|
|
46567
|
+
log20.info(`Task created by agent ${ctx.agentId}`, { taskId: task.id, title: task.title, assignedAgentId });
|
|
46122
46568
|
if (task.status === "pending_approval") {
|
|
46123
46569
|
return JSON.stringify({
|
|
46124
46570
|
status: "pending_approval",
|
|
@@ -46132,7 +46578,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46132
46578
|
message: `Task created: "${task.title}" (ID: ${task.id})`
|
|
46133
46579
|
});
|
|
46134
46580
|
} catch (error) {
|
|
46135
|
-
|
|
46581
|
+
log20.error("task_create failed", { error: String(error) });
|
|
46136
46582
|
return JSON.stringify({ status: "error", error: String(error) });
|
|
46137
46583
|
}
|
|
46138
46584
|
}
|
|
@@ -46302,7 +46748,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46302
46748
|
await ctx.addTaskNote(task2.id, note, ctx.agentName).catch(() => {
|
|
46303
46749
|
});
|
|
46304
46750
|
}
|
|
46305
|
-
|
|
46751
|
+
log20.info(`Pending task cancelled by creator ${ctx.agentId}`, { taskId: task2.id });
|
|
46306
46752
|
return JSON.stringify({
|
|
46307
46753
|
status: "success",
|
|
46308
46754
|
task: task2,
|
|
@@ -46315,7 +46761,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46315
46761
|
});
|
|
46316
46762
|
}
|
|
46317
46763
|
if (existing?.assignedAgentId === ctx.agentId && existing?.status === "in_progress") {
|
|
46318
|
-
|
|
46764
|
+
log20.warn(`Agent ${ctx.agentId} attempted to set own running task to "${newStatus}"`, { taskId: taskId2 });
|
|
46319
46765
|
return JSON.stringify({
|
|
46320
46766
|
status: "denied",
|
|
46321
46767
|
error: `Setting your own running task to "${newStatus}" will immediately abort all ongoing work. If you truly need to stop, confirm by adding a note explaining why. Otherwise, continue working on the task.`
|
|
@@ -46335,7 +46781,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46335
46781
|
await ctx.addTaskNote(task.id, note, ctx.agentName).catch(() => {
|
|
46336
46782
|
});
|
|
46337
46783
|
}
|
|
46338
|
-
|
|
46784
|
+
log20.info(`Task updated by agent ${ctx.agentId}`, {
|
|
46339
46785
|
taskId: task.id,
|
|
46340
46786
|
status: task.status
|
|
46341
46787
|
});
|
|
@@ -46352,7 +46798,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46352
46798
|
await ctx.addTaskNote(taskId2, note, ctx.agentName);
|
|
46353
46799
|
}
|
|
46354
46800
|
const task = ctx.getTask ? await ctx.getTask(taskId2) : null;
|
|
46355
|
-
|
|
46801
|
+
log20.info(`Task updated by agent ${ctx.agentId}`, { taskId: taskId2, hasNote: !!note, hasDescription: description !== void 0, hasBlockedBy: blockedBy !== void 0 });
|
|
46356
46802
|
return JSON.stringify({
|
|
46357
46803
|
status: "success",
|
|
46358
46804
|
task,
|
|
@@ -46646,7 +47092,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46646
47092
|
projectId: args["project_id"],
|
|
46647
47093
|
tags: args["tags"]
|
|
46648
47094
|
});
|
|
46649
|
-
|
|
47095
|
+
log20.info(`Requirement proposed by agent ${ctx.agentId}`, {
|
|
46650
47096
|
requirementId: req.id,
|
|
46651
47097
|
title: req.title
|
|
46652
47098
|
});
|
|
@@ -46656,7 +47102,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46656
47102
|
message: `Requirement proposed: "${req.title}" (ID: ${req.id}). It will be reviewed by a human user. Do NOT create tasks for this until it is approved.`
|
|
46657
47103
|
});
|
|
46658
47104
|
} catch (error) {
|
|
46659
|
-
|
|
47105
|
+
log20.error("requirement_propose failed", { error: String(error) });
|
|
46660
47106
|
return JSON.stringify({ status: "error", error: String(error) });
|
|
46661
47107
|
}
|
|
46662
47108
|
}
|
|
@@ -46749,7 +47195,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46749
47195
|
async execute(args) {
|
|
46750
47196
|
try {
|
|
46751
47197
|
const req = await ctx.updateRequirementStatus(args["requirement_id"], args["status"], args["reason"]);
|
|
46752
|
-
|
|
47198
|
+
log20.info(`Requirement status updated by agent ${ctx.agentId}`, {
|
|
46753
47199
|
requirementId: req.id,
|
|
46754
47200
|
newStatus: req.status,
|
|
46755
47201
|
reason: args["reason"]
|
|
@@ -46760,7 +47206,7 @@ function createAgentTaskTools(ctx) {
|
|
|
46760
47206
|
message: `Requirement "${req.title}" (ID: ${req.id}) status changed to ${req.status}.`
|
|
46761
47207
|
});
|
|
46762
47208
|
} catch (error) {
|
|
46763
|
-
|
|
47209
|
+
log20.error("requirement_update_status failed", { error: String(error) });
|
|
46764
47210
|
return JSON.stringify({ status: "error", error: String(error) });
|
|
46765
47211
|
}
|
|
46766
47212
|
}
|
|
@@ -46768,12 +47214,12 @@ function createAgentTaskTools(ctx) {
|
|
|
46768
47214
|
] : []
|
|
46769
47215
|
];
|
|
46770
47216
|
}
|
|
46771
|
-
var
|
|
47217
|
+
var log20;
|
|
46772
47218
|
var init_task_tools = __esm({
|
|
46773
47219
|
"../core/dist/tools/task-tools.js"() {
|
|
46774
47220
|
"use strict";
|
|
46775
47221
|
init_dist();
|
|
46776
|
-
|
|
47222
|
+
log20 = createLogger("task-tools");
|
|
46777
47223
|
}
|
|
46778
47224
|
});
|
|
46779
47225
|
|
|
@@ -47100,10 +47546,10 @@ function createMemoryTools(ctx) {
|
|
|
47100
47546
|
ctx.memory.addEntry(entry);
|
|
47101
47547
|
if (ctx.semanticSearch?.isEnabled()) {
|
|
47102
47548
|
ctx.semanticSearch.indexMemory(entry, ctx.agentId).catch((err) => {
|
|
47103
|
-
|
|
47549
|
+
log21.warn("Failed to index memory for semantic search", { error: String(err) });
|
|
47104
47550
|
});
|
|
47105
47551
|
}
|
|
47106
|
-
|
|
47552
|
+
log21.info("Agent saved memory", { agentId: ctx.agentId, type, contentLen: content.length });
|
|
47107
47553
|
return JSON.stringify({ status: "saved", id: entry.id, type });
|
|
47108
47554
|
}
|
|
47109
47555
|
},
|
|
@@ -47142,7 +47588,7 @@ function createMemoryTools(ctx) {
|
|
|
47142
47588
|
let entries2 = semResults.map((r) => r.entry);
|
|
47143
47589
|
if (type)
|
|
47144
47590
|
entries2 = entries2.filter((e) => e.type === type);
|
|
47145
|
-
|
|
47591
|
+
log21.debug("Semantic memory search", { agentId: ctx.agentId, query: query2, results: entries2.length });
|
|
47146
47592
|
return JSON.stringify({
|
|
47147
47593
|
results: entries2.map((e) => ({
|
|
47148
47594
|
id: e.id,
|
|
@@ -47154,14 +47600,14 @@ function createMemoryTools(ctx) {
|
|
|
47154
47600
|
count: entries2.length
|
|
47155
47601
|
});
|
|
47156
47602
|
} catch (err) {
|
|
47157
|
-
|
|
47603
|
+
log21.warn("Semantic search failed, falling back to substring", { error: String(err) });
|
|
47158
47604
|
}
|
|
47159
47605
|
}
|
|
47160
47606
|
let results = ctx.memory.search(query2);
|
|
47161
47607
|
if (type)
|
|
47162
47608
|
results = results.filter((e) => e.type === type);
|
|
47163
47609
|
results = results.slice(0, limit);
|
|
47164
|
-
|
|
47610
|
+
log21.debug("Memory search (substring)", { agentId: ctx.agentId, query: query2, results: results.length });
|
|
47165
47611
|
return JSON.stringify({
|
|
47166
47612
|
results: results.map((e) => ({
|
|
47167
47613
|
id: e.id,
|
|
@@ -47227,18 +47673,18 @@ function createMemoryTools(ctx) {
|
|
|
47227
47673
|
const section = args["section"];
|
|
47228
47674
|
const content = args["content"];
|
|
47229
47675
|
ctx.memory.addLongTermMemory(section, content);
|
|
47230
|
-
|
|
47676
|
+
log21.info("Agent updated long-term memory", { agentId: ctx.agentId, section, contentLen: content.length });
|
|
47231
47677
|
return JSON.stringify({ status: "updated", section });
|
|
47232
47678
|
}
|
|
47233
47679
|
}
|
|
47234
47680
|
];
|
|
47235
47681
|
}
|
|
47236
|
-
var
|
|
47682
|
+
var log21;
|
|
47237
47683
|
var init_memory = __esm({
|
|
47238
47684
|
"../core/dist/tools/memory.js"() {
|
|
47239
47685
|
"use strict";
|
|
47240
47686
|
init_dist();
|
|
47241
|
-
|
|
47687
|
+
log21 = createLogger("memory-tools");
|
|
47242
47688
|
}
|
|
47243
47689
|
});
|
|
47244
47690
|
|
|
@@ -47257,12 +47703,12 @@ function cosineSimilarity(a, b) {
|
|
|
47257
47703
|
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
47258
47704
|
return denom === 0 ? 0 : dot / denom;
|
|
47259
47705
|
}
|
|
47260
|
-
var
|
|
47706
|
+
var log22, OpenAIEmbeddingProvider, PgVectorStore, LocalVectorStore, SemanticMemorySearch;
|
|
47261
47707
|
var init_semantic_search = __esm({
|
|
47262
47708
|
"../core/dist/memory/semantic-search.js"() {
|
|
47263
47709
|
"use strict";
|
|
47264
47710
|
init_dist();
|
|
47265
|
-
|
|
47711
|
+
log22 = createLogger("semantic-search");
|
|
47266
47712
|
OpenAIEmbeddingProvider = class {
|
|
47267
47713
|
dimensions;
|
|
47268
47714
|
apiKey;
|
|
@@ -47316,7 +47762,7 @@ var init_semantic_search = __esm({
|
|
|
47316
47762
|
params: [id, metadata.agentId, metadata.content, metadata.type, vectorStr]
|
|
47317
47763
|
});
|
|
47318
47764
|
} catch (err) {
|
|
47319
|
-
|
|
47765
|
+
log22.warn("Vector upsert failed, pgvector may not be available", { error: String(err) });
|
|
47320
47766
|
}
|
|
47321
47767
|
}
|
|
47322
47768
|
async search(queryEmbedding, opts) {
|
|
@@ -47340,7 +47786,7 @@ var init_semantic_search = __esm({
|
|
|
47340
47786
|
type: r["type"]
|
|
47341
47787
|
}));
|
|
47342
47788
|
} catch (err) {
|
|
47343
|
-
|
|
47789
|
+
log22.warn("Vector search failed", { error: String(err) });
|
|
47344
47790
|
return [];
|
|
47345
47791
|
}
|
|
47346
47792
|
}
|
|
@@ -47372,10 +47818,10 @@ var init_semantic_search = __esm({
|
|
|
47372
47818
|
params: []
|
|
47373
47819
|
});
|
|
47374
47820
|
this.pgvectorAvailable = true;
|
|
47375
|
-
|
|
47821
|
+
log22.info("pgvector memory_embeddings table ready");
|
|
47376
47822
|
return true;
|
|
47377
47823
|
} catch (err) {
|
|
47378
|
-
|
|
47824
|
+
log22.warn("pgvector setup failed, semantic search will use fallback", { error: String(err) });
|
|
47379
47825
|
this.pgvectorAvailable = false;
|
|
47380
47826
|
return false;
|
|
47381
47827
|
}
|
|
@@ -47424,10 +47870,10 @@ var init_semantic_search = __esm({
|
|
|
47424
47870
|
if (existsSync14(this.storePath)) {
|
|
47425
47871
|
const data = JSON.parse(readFileSync11(this.storePath, "utf-8"));
|
|
47426
47872
|
this.vectors = new Map(data);
|
|
47427
|
-
|
|
47873
|
+
log22.info("Local vector store loaded", { entries: this.vectors.size });
|
|
47428
47874
|
}
|
|
47429
47875
|
} catch (err) {
|
|
47430
|
-
|
|
47876
|
+
log22.warn("Failed to load local vector store", { error: String(err) });
|
|
47431
47877
|
}
|
|
47432
47878
|
}
|
|
47433
47879
|
scheduleSave() {
|
|
@@ -47442,7 +47888,7 @@ var init_semantic_search = __esm({
|
|
|
47442
47888
|
writeFileSync8(this.storePath, JSON.stringify(Array.from(this.vectors.entries())));
|
|
47443
47889
|
this.dirty = false;
|
|
47444
47890
|
} catch (err) {
|
|
47445
|
-
|
|
47891
|
+
log22.warn("Failed to save local vector store", { error: String(err) });
|
|
47446
47892
|
}
|
|
47447
47893
|
}, 2e3);
|
|
47448
47894
|
}
|
|
@@ -47477,7 +47923,7 @@ var init_semantic_search = __esm({
|
|
|
47477
47923
|
type: entry.type
|
|
47478
47924
|
});
|
|
47479
47925
|
} catch (err) {
|
|
47480
|
-
|
|
47926
|
+
log22.warn("Failed to index memory entry", { id: entry.id, error: String(err) });
|
|
47481
47927
|
}
|
|
47482
47928
|
}
|
|
47483
47929
|
async search(query2, opts) {
|
|
@@ -47500,7 +47946,7 @@ var init_semantic_search = __esm({
|
|
|
47500
47946
|
similarity: r.similarity
|
|
47501
47947
|
}));
|
|
47502
47948
|
} catch (err) {
|
|
47503
|
-
|
|
47949
|
+
log22.warn("Semantic search failed, returning empty results", { error: String(err) });
|
|
47504
47950
|
return [];
|
|
47505
47951
|
}
|
|
47506
47952
|
}
|
|
@@ -47514,12 +47960,12 @@ var init_semantic_search = __esm({
|
|
|
47514
47960
|
});
|
|
47515
47961
|
|
|
47516
47962
|
// ../a2a/dist/bus.js
|
|
47517
|
-
var
|
|
47963
|
+
var log23, MAX_RETRIES, RETRY_BASE_MS, A2ABus;
|
|
47518
47964
|
var init_bus = __esm({
|
|
47519
47965
|
"../a2a/dist/bus.js"() {
|
|
47520
47966
|
"use strict";
|
|
47521
47967
|
init_dist();
|
|
47522
|
-
|
|
47968
|
+
log23 = createLogger("a2a-bus");
|
|
47523
47969
|
MAX_RETRIES = 3;
|
|
47524
47970
|
RETRY_BASE_MS = 1e3;
|
|
47525
47971
|
A2ABus = class {
|
|
@@ -47527,11 +47973,11 @@ var init_bus = __esm({
|
|
|
47527
47973
|
agentEndpoints = /* @__PURE__ */ new Map();
|
|
47528
47974
|
registerAgent(agentId2, handler4) {
|
|
47529
47975
|
this.agentEndpoints.set(agentId2, handler4);
|
|
47530
|
-
|
|
47976
|
+
log23.info(`Agent registered on A2A bus: ${agentId2}`);
|
|
47531
47977
|
}
|
|
47532
47978
|
unregisterAgent(agentId2) {
|
|
47533
47979
|
this.agentEndpoints.delete(agentId2);
|
|
47534
|
-
|
|
47980
|
+
log23.info(`Agent unregistered from A2A bus: ${agentId2}`);
|
|
47535
47981
|
}
|
|
47536
47982
|
on(type, handler4) {
|
|
47537
47983
|
const existing = this.handlers.get(type) ?? [];
|
|
@@ -47548,7 +47994,7 @@ var init_bus = __esm({
|
|
|
47548
47994
|
lastError = error;
|
|
47549
47995
|
if (attempt < MAX_RETRIES - 1) {
|
|
47550
47996
|
const delay = RETRY_BASE_MS * Math.pow(2, attempt);
|
|
47551
|
-
|
|
47997
|
+
log23.warn(`${label} failed, retrying (${attempt + 1}/${MAX_RETRIES})`, {
|
|
47552
47998
|
error: String(error).slice(0, 200),
|
|
47553
47999
|
delay
|
|
47554
48000
|
});
|
|
@@ -47556,10 +48002,10 @@ var init_bus = __esm({
|
|
|
47556
48002
|
}
|
|
47557
48003
|
}
|
|
47558
48004
|
}
|
|
47559
|
-
|
|
48005
|
+
log23.error(`${label} failed after ${MAX_RETRIES} retries`, { error: String(lastError) });
|
|
47560
48006
|
}
|
|
47561
48007
|
async send(envelope) {
|
|
47562
|
-
|
|
48008
|
+
log23.debug(`A2A message: ${envelope.type} from=${envelope.from} to=${envelope.to}`, {
|
|
47563
48009
|
id: envelope.id,
|
|
47564
48010
|
correlationId: envelope.correlationId
|
|
47565
48011
|
});
|
|
@@ -47567,7 +48013,7 @@ var init_bus = __esm({
|
|
|
47567
48013
|
if (agentHandler) {
|
|
47568
48014
|
await this.deliverWithRetry(agentHandler, envelope, `A2A delivery to ${envelope.to}`);
|
|
47569
48015
|
} else {
|
|
47570
|
-
|
|
48016
|
+
log23.warn(`A2A target agent not found: ${envelope.to}`);
|
|
47571
48017
|
}
|
|
47572
48018
|
const typeHandlers = this.handlers.get(envelope.type) ?? [];
|
|
47573
48019
|
for (const handler4 of typeHandlers) {
|
|
@@ -47596,12 +48042,12 @@ var init_bus = __esm({
|
|
|
47596
48042
|
});
|
|
47597
48043
|
|
|
47598
48044
|
// ../a2a/dist/delegation.js
|
|
47599
|
-
var
|
|
48045
|
+
var log24, DelegationManager;
|
|
47600
48046
|
var init_delegation = __esm({
|
|
47601
48047
|
"../a2a/dist/delegation.js"() {
|
|
47602
48048
|
"use strict";
|
|
47603
48049
|
init_dist();
|
|
47604
|
-
|
|
48050
|
+
log24 = createLogger("a2a-delegation");
|
|
47605
48051
|
DelegationManager = class {
|
|
47606
48052
|
bus;
|
|
47607
48053
|
agentCards = /* @__PURE__ */ new Map();
|
|
@@ -47661,7 +48107,7 @@ var init_delegation = __esm({
|
|
|
47661
48107
|
payload: delegation
|
|
47662
48108
|
};
|
|
47663
48109
|
await this.bus.send(envelope);
|
|
47664
|
-
|
|
48110
|
+
log24.info(`Task delegated from ${fromAgentId} to ${targetId}`, {
|
|
47665
48111
|
taskId: delegation.taskId,
|
|
47666
48112
|
title: delegation.title
|
|
47667
48113
|
});
|
|
@@ -47700,7 +48146,7 @@ var init_delegation = __esm({
|
|
|
47700
48146
|
}
|
|
47701
48147
|
async handleDelegation(envelope) {
|
|
47702
48148
|
const delegation = envelope.payload;
|
|
47703
|
-
|
|
48149
|
+
log24.info(`Received task delegation: ${delegation.title}`, {
|
|
47704
48150
|
from: envelope.from,
|
|
47705
48151
|
to: envelope.to,
|
|
47706
48152
|
taskId: delegation.taskId
|
|
@@ -47711,14 +48157,14 @@ var init_delegation = __esm({
|
|
|
47711
48157
|
}
|
|
47712
48158
|
async handleUpdate(envelope) {
|
|
47713
48159
|
const update2 = envelope.payload;
|
|
47714
|
-
|
|
48160
|
+
log24.info(`Task update: ${update2.taskId} -> ${update2.status}`, {
|
|
47715
48161
|
from: envelope.from,
|
|
47716
48162
|
progress: update2.progress
|
|
47717
48163
|
});
|
|
47718
48164
|
}
|
|
47719
48165
|
async handleComplete(envelope) {
|
|
47720
48166
|
const update2 = envelope.payload;
|
|
47721
|
-
|
|
48167
|
+
log24.info(`Task completed: ${update2.taskId}`, {
|
|
47722
48168
|
from: envelope.from,
|
|
47723
48169
|
to: envelope.to
|
|
47724
48170
|
});
|
|
@@ -47728,22 +48174,22 @@ var init_delegation = __esm({
|
|
|
47728
48174
|
});
|
|
47729
48175
|
|
|
47730
48176
|
// ../a2a/dist/collaboration.js
|
|
47731
|
-
var
|
|
48177
|
+
var log25;
|
|
47732
48178
|
var init_collaboration = __esm({
|
|
47733
48179
|
"../a2a/dist/collaboration.js"() {
|
|
47734
48180
|
"use strict";
|
|
47735
48181
|
init_dist();
|
|
47736
|
-
|
|
48182
|
+
log25 = createLogger("a2a-collaboration");
|
|
47737
48183
|
}
|
|
47738
48184
|
});
|
|
47739
48185
|
|
|
47740
48186
|
// ../a2a/dist/structured.js
|
|
47741
|
-
var
|
|
48187
|
+
var log26;
|
|
47742
48188
|
var init_structured = __esm({
|
|
47743
48189
|
"../a2a/dist/structured.js"() {
|
|
47744
48190
|
"use strict";
|
|
47745
48191
|
init_dist();
|
|
47746
|
-
|
|
48192
|
+
log26 = createLogger("a2a-structured");
|
|
47747
48193
|
}
|
|
47748
48194
|
});
|
|
47749
48195
|
|
|
@@ -47771,7 +48217,7 @@ function resolveCurrentTaskId(agentObj, ts, agentId2) {
|
|
|
47771
48217
|
const currentTask = ts.getTask(currentId);
|
|
47772
48218
|
if (currentTask?.status === "in_progress")
|
|
47773
48219
|
return currentId;
|
|
47774
|
-
|
|
48220
|
+
log27.warn("Agent currentTaskId is no longer in_progress, searching activeTasks for a valid candidate", {
|
|
47775
48221
|
agentId: agentId2,
|
|
47776
48222
|
currentTaskId: currentId,
|
|
47777
48223
|
actualStatus: currentTask?.status
|
|
@@ -47785,13 +48231,13 @@ function resolveCurrentTaskId(agentObj, ts, agentId2) {
|
|
|
47785
48231
|
for (const t of activeTasks) {
|
|
47786
48232
|
const task = ts.getTask(t.taskId);
|
|
47787
48233
|
if (task && ["completed", "failed", "cancelled", "archived"].includes(task.status)) {
|
|
47788
|
-
|
|
48234
|
+
log27.warn("Removing stale task from agent activeTasks", { agentId: agentId2, taskId: t.taskId, status: task.status });
|
|
47789
48235
|
agentObj?.removeActiveTask(t.taskId);
|
|
47790
48236
|
}
|
|
47791
48237
|
}
|
|
47792
48238
|
throw new Error(`No in_progress task found for agent ${agentId2} \u2014 cannot submit for review. Active task IDs: [${activeTasks.map((t) => t.taskId).join(", ")}]`);
|
|
47793
48239
|
}
|
|
47794
|
-
var
|
|
48240
|
+
var log27, AgentManager;
|
|
47795
48241
|
var init_agent_manager = __esm({
|
|
47796
48242
|
"../core/dist/agent-manager.js"() {
|
|
47797
48243
|
"use strict";
|
|
@@ -47811,7 +48257,7 @@ var init_agent_manager = __esm({
|
|
|
47811
48257
|
init_semantic_search();
|
|
47812
48258
|
init_security();
|
|
47813
48259
|
init_dist3();
|
|
47814
|
-
|
|
48260
|
+
log27 = createLogger("agent-manager");
|
|
47815
48261
|
AgentManager = class _AgentManager {
|
|
47816
48262
|
agents = /* @__PURE__ */ new Map();
|
|
47817
48263
|
eventBus;
|
|
@@ -47840,6 +48286,7 @@ var init_agent_manager = __esm({
|
|
|
47840
48286
|
activityCallbacks;
|
|
47841
48287
|
a2aBus;
|
|
47842
48288
|
delegationManager;
|
|
48289
|
+
_maxToolIterations = 200;
|
|
47843
48290
|
templateRegistry;
|
|
47844
48291
|
groupChatHandlers;
|
|
47845
48292
|
buildKnowledgeCallbacks(agentId2, orgId2) {
|
|
@@ -47954,11 +48401,11 @@ var init_agent_manager = __esm({
|
|
|
47954
48401
|
this.semanticSearch = new SemanticMemorySearch(embeddingProvider, vectorStore);
|
|
47955
48402
|
this.semanticSearch.initialize().then((ok) => {
|
|
47956
48403
|
if (ok)
|
|
47957
|
-
|
|
48404
|
+
log27.info("Semantic memory search initialized (LocalVectorStore)");
|
|
47958
48405
|
else
|
|
47959
|
-
|
|
48406
|
+
log27.warn("Semantic memory search initialization failed");
|
|
47960
48407
|
}).catch((err) => {
|
|
47961
|
-
|
|
48408
|
+
log27.warn("Semantic memory search init error", { error: String(err) });
|
|
47962
48409
|
});
|
|
47963
48410
|
}
|
|
47964
48411
|
this.a2aBus = new A2ABus();
|
|
@@ -47966,7 +48413,7 @@ var init_agent_manager = __esm({
|
|
|
47966
48413
|
this.delegationManager.onDelegationReceived(async (envelope, delegation) => {
|
|
47967
48414
|
const targetAgent = this.agents.get(envelope.to);
|
|
47968
48415
|
if (!targetAgent) {
|
|
47969
|
-
|
|
48416
|
+
log27.warn("Delegation target agent not found", { to: envelope.to });
|
|
47970
48417
|
return;
|
|
47971
48418
|
}
|
|
47972
48419
|
if (this.taskService) {
|
|
@@ -47980,7 +48427,7 @@ var init_agent_manager = __esm({
|
|
|
47980
48427
|
createdBy: envelope.from,
|
|
47981
48428
|
creatorRole: "manager"
|
|
47982
48429
|
});
|
|
47983
|
-
|
|
48430
|
+
log27.info("Delegation created real task", {
|
|
47984
48431
|
taskId: task.id,
|
|
47985
48432
|
delegatedTo: envelope.to,
|
|
47986
48433
|
from: envelope.from,
|
|
@@ -47996,6 +48443,12 @@ Priority: ${delegation.priority}`, envelope.from, { name: envelope.from, role: "
|
|
|
47996
48443
|
this.templateRegistry = options.templateRegistry;
|
|
47997
48444
|
mkdirSync9(this.dataDir, { recursive: true });
|
|
47998
48445
|
}
|
|
48446
|
+
get maxToolIterations() {
|
|
48447
|
+
return this._maxToolIterations;
|
|
48448
|
+
}
|
|
48449
|
+
set maxToolIterations(value) {
|
|
48450
|
+
this._maxToolIterations = Math.max(1, Math.min(value, 1e4));
|
|
48451
|
+
}
|
|
47999
48452
|
setTaskService(taskService) {
|
|
48000
48453
|
this.taskService = taskService;
|
|
48001
48454
|
}
|
|
@@ -48117,7 +48570,8 @@ Priority: ${delegation.priority}`, envelope.from, { name: envelope.from, role: "
|
|
|
48117
48570
|
tools,
|
|
48118
48571
|
orgContext: request.orgContext,
|
|
48119
48572
|
pathPolicy,
|
|
48120
|
-
skillRegistry: this.skillRegistry
|
|
48573
|
+
skillRegistry: this.skillRegistry,
|
|
48574
|
+
maxToolIterations: this._maxToolIterations
|
|
48121
48575
|
};
|
|
48122
48576
|
const agent = new Agent(agentOpts);
|
|
48123
48577
|
if (this.skillRegistry) {
|
|
@@ -48126,14 +48580,14 @@ Priority: ${delegation.priority}`, envelope.from, { name: envelope.from, role: "
|
|
|
48126
48580
|
agent.injectSkillInstructions(skillName, instructions);
|
|
48127
48581
|
}
|
|
48128
48582
|
if (builtinInstructions.size > 0) {
|
|
48129
|
-
|
|
48583
|
+
log27.info(`Always-on builtin skills injected for agent ${id}`, { skills: [...builtinInstructions.keys()] });
|
|
48130
48584
|
}
|
|
48131
48585
|
agent.setAvailableSkillCatalog(this.skillRegistry.getBuiltinSkillCatalog());
|
|
48132
48586
|
}
|
|
48133
48587
|
if (this.skillRegistry && config.skills.length > 0) {
|
|
48134
48588
|
const missingSkills = config.skills.filter((s) => !this.skillRegistry.get(s));
|
|
48135
48589
|
if (missingSkills.length > 0) {
|
|
48136
|
-
|
|
48590
|
+
log27.warn(`Agent ${config.name} (${id}) references skills not found in registry`, {
|
|
48137
48591
|
missing: missingSkills,
|
|
48138
48592
|
available: this.skillRegistry.list().map((s) => s.name)
|
|
48139
48593
|
});
|
|
@@ -48165,12 +48619,12 @@ Priority: ${delegation.priority}`, envelope.from, { name: envelope.from, role: "
|
|
|
48165
48619
|
toolNames.push(tool.name);
|
|
48166
48620
|
}
|
|
48167
48621
|
agent.activateTools(toolNames);
|
|
48168
|
-
|
|
48622
|
+
log27.info(`Skill ${skillName} MCP server ${serverName} connected for agent ${id}`, {
|
|
48169
48623
|
toolCount: mcpTools.length,
|
|
48170
48624
|
isolated
|
|
48171
48625
|
});
|
|
48172
48626
|
} catch (error) {
|
|
48173
|
-
|
|
48627
|
+
log27.warn(`Failed to connect skill ${skillName} MCP server ${serverName} for agent ${id}`, {
|
|
48174
48628
|
error: String(error)
|
|
48175
48629
|
});
|
|
48176
48630
|
}
|
|
@@ -48401,7 +48855,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48401
48855
|
return [];
|
|
48402
48856
|
}
|
|
48403
48857
|
});
|
|
48404
|
-
|
|
48858
|
+
log27.info(`Task tools injected for agent ${id}`);
|
|
48405
48859
|
}
|
|
48406
48860
|
if (this.projectService) {
|
|
48407
48861
|
for (const tool of createProjectTools({
|
|
@@ -48415,8 +48869,10 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48415
48869
|
}
|
|
48416
48870
|
}
|
|
48417
48871
|
if (request.agentRole === "manager") {
|
|
48872
|
+
const myTeamId = config.teamId;
|
|
48873
|
+
const filterByTeam = (list2) => myTeamId ? list2.filter((a) => a.teamId === myTeamId) : list2;
|
|
48418
48874
|
const managerTools = createManagerTools({
|
|
48419
|
-
listAgents: () => this.listAgents().map((a) => {
|
|
48875
|
+
listAgents: () => filterByTeam(this.listAgents()).map((a) => {
|
|
48420
48876
|
try {
|
|
48421
48877
|
const ag = this.getAgent(a.id);
|
|
48422
48878
|
return { ...a, skills: ag.config.skills };
|
|
@@ -48429,7 +48885,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48429
48885
|
const reply = await target.handleMessage(message, id, { name: config.name, role: "manager" });
|
|
48430
48886
|
return stripInternalBlocks(reply);
|
|
48431
48887
|
},
|
|
48432
|
-
getTeamStatus: () => this.listAgents().map((a) => {
|
|
48888
|
+
getTeamStatus: () => filterByTeam(this.listAgents()).map((a) => {
|
|
48433
48889
|
try {
|
|
48434
48890
|
const ag = this.getAgent(a.id);
|
|
48435
48891
|
const state = ag.getState();
|
|
@@ -48459,11 +48915,11 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48459
48915
|
for (const tool of mcpTools) {
|
|
48460
48916
|
agent.registerTool(tool);
|
|
48461
48917
|
}
|
|
48462
|
-
|
|
48918
|
+
log27.info(`MCP server ${serverName} tools registered for agent ${id}`, {
|
|
48463
48919
|
toolCount: mcpTools.length
|
|
48464
48920
|
});
|
|
48465
48921
|
} catch (error) {
|
|
48466
|
-
|
|
48922
|
+
log27.warn(`Failed to connect MCP server ${serverName} for agent ${id}`, {
|
|
48467
48923
|
error: String(error)
|
|
48468
48924
|
});
|
|
48469
48925
|
}
|
|
@@ -48499,7 +48955,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48499
48955
|
status: "idle"
|
|
48500
48956
|
});
|
|
48501
48957
|
this.eventBus.emit("agent:created", { agentId: id, name: request.name });
|
|
48502
|
-
|
|
48958
|
+
log27.info(`Agent created: ${request.name} (${id})`);
|
|
48503
48959
|
return agent;
|
|
48504
48960
|
}
|
|
48505
48961
|
/**
|
|
@@ -48604,7 +49060,8 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48604
49060
|
tools,
|
|
48605
49061
|
pathPolicy,
|
|
48606
49062
|
restoredState: { tokensUsedToday: row.tokensUsedToday ?? 0 },
|
|
48607
|
-
skillRegistry: this.skillRegistry
|
|
49063
|
+
skillRegistry: this.skillRegistry,
|
|
49064
|
+
maxToolIterations: this._maxToolIterations
|
|
48608
49065
|
});
|
|
48609
49066
|
if (this.skillRegistry) {
|
|
48610
49067
|
const builtinInstructions = this.skillRegistry.getBuiltinInstructions();
|
|
@@ -48616,7 +49073,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48616
49073
|
if (this.skillRegistry && config.skills.length > 0) {
|
|
48617
49074
|
const missingSkills = config.skills.filter((s) => !this.skillRegistry.get(s));
|
|
48618
49075
|
if (missingSkills.length > 0) {
|
|
48619
|
-
|
|
49076
|
+
log27.warn(`Restored agent ${config.name} (${id}) references skills not found in registry`, {
|
|
48620
49077
|
missing: missingSkills,
|
|
48621
49078
|
available: this.skillRegistry.list().map((s) => s.name)
|
|
48622
49079
|
});
|
|
@@ -48648,12 +49105,12 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48648
49105
|
toolNames.push(tool.name);
|
|
48649
49106
|
}
|
|
48650
49107
|
agent.activateTools(toolNames);
|
|
48651
|
-
|
|
49108
|
+
log27.info(`Skill ${skillName} MCP server ${serverName} restored for agent ${id}`, {
|
|
48652
49109
|
toolCount: mcpTools.length,
|
|
48653
49110
|
isolated
|
|
48654
49111
|
});
|
|
48655
49112
|
} catch (error) {
|
|
48656
|
-
|
|
49113
|
+
log27.warn(`Failed to restore skill ${skillName} MCP server ${serverName} for agent ${id}`, {
|
|
48657
49114
|
error: String(error)
|
|
48658
49115
|
});
|
|
48659
49116
|
}
|
|
@@ -48866,8 +49323,10 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48866
49323
|
}
|
|
48867
49324
|
}
|
|
48868
49325
|
if (config.agentRole === "manager") {
|
|
49326
|
+
const restoredTeamId = config.teamId;
|
|
49327
|
+
const filterByTeamRestored = (list2) => restoredTeamId ? list2.filter((a) => a.teamId === restoredTeamId) : list2;
|
|
48869
49328
|
const managerTools = createManagerTools({
|
|
48870
|
-
listAgents: () => this.listAgents().map((a) => {
|
|
49329
|
+
listAgents: () => filterByTeamRestored(this.listAgents()).map((a) => {
|
|
48871
49330
|
try {
|
|
48872
49331
|
const ag = this.getAgent(a.id);
|
|
48873
49332
|
return { ...a, skills: ag.config.skills };
|
|
@@ -48880,7 +49339,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48880
49339
|
const reply = await target.handleMessage(message, id, { name: config.name, role: "manager" });
|
|
48881
49340
|
return stripInternalBlocks(reply);
|
|
48882
49341
|
},
|
|
48883
|
-
getTeamStatus: () => this.listAgents().map((a) => {
|
|
49342
|
+
getTeamStatus: () => filterByTeamRestored(this.listAgents()).map((a) => {
|
|
48884
49343
|
try {
|
|
48885
49344
|
const ag = this.getAgent(a.id);
|
|
48886
49345
|
const state = ag.getState();
|
|
@@ -48930,7 +49389,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48930
49389
|
status: "idle"
|
|
48931
49390
|
});
|
|
48932
49391
|
this.eventBus.emit("agent:created", { agentId: id, name: row.name });
|
|
48933
|
-
|
|
49392
|
+
log27.info(`Agent restored: ${row.name} (${id})`, {
|
|
48934
49393
|
profile: config.profile ? "yes" : "no",
|
|
48935
49394
|
tokensUsedToday: row.tokensUsedToday ?? 0,
|
|
48936
49395
|
activeTaskIds: Array.isArray(row.activeTaskIds) ? row.activeTaskIds.length : 0
|
|
@@ -48951,21 +49410,21 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48951
49410
|
try {
|
|
48952
49411
|
const task = this.taskService.getTask(taskId2);
|
|
48953
49412
|
if (!task) {
|
|
48954
|
-
|
|
49413
|
+
log27.warn("Task not found during rehydration, skipping", { agentId: agentId2, taskId: taskId2 });
|
|
48955
49414
|
continue;
|
|
48956
49415
|
}
|
|
48957
49416
|
if (task.status === "completed" || task.status === "cancelled" || task.status === "failed") {
|
|
48958
|
-
|
|
49417
|
+
log27.debug("Task already terminal, skipping rehydration", {
|
|
48959
49418
|
agentId: agentId2,
|
|
48960
49419
|
taskId: taskId2,
|
|
48961
49420
|
status: task.status
|
|
48962
49421
|
});
|
|
48963
49422
|
continue;
|
|
48964
49423
|
}
|
|
48965
|
-
|
|
49424
|
+
log27.info("Re-queuing interrupted task", { agentId: agentId2, taskId: taskId2, title: task.title });
|
|
48966
49425
|
this.taskService.assignTask(taskId2, agentId2);
|
|
48967
49426
|
} catch (error) {
|
|
48968
|
-
|
|
49427
|
+
log27.warn("Failed to rehydrate task", { agentId: agentId2, taskId: taskId2, error: String(error) });
|
|
48969
49428
|
}
|
|
48970
49429
|
}
|
|
48971
49430
|
}
|
|
@@ -48996,13 +49455,13 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
48996
49455
|
if (existsSync15(agentDir)) {
|
|
48997
49456
|
try {
|
|
48998
49457
|
rmSync(agentDir, { recursive: true, force: true });
|
|
48999
|
-
|
|
49458
|
+
log27.info(`Agent data directory purged: ${agentDir}`);
|
|
49000
49459
|
} catch (err) {
|
|
49001
|
-
|
|
49460
|
+
log27.warn("Failed to purge agent data directory", { agentId: agentId2, error: String(err) });
|
|
49002
49461
|
}
|
|
49003
49462
|
}
|
|
49004
49463
|
}
|
|
49005
|
-
|
|
49464
|
+
log27.info(`Agent removed: ${agentId2}`, { purgeFiles: !!opts?.purgeFiles });
|
|
49006
49465
|
}
|
|
49007
49466
|
/** Remove orphaned agent directories that have no matching DB record */
|
|
49008
49467
|
purgeOrphanedAgentDirs(knownAgentIds) {
|
|
@@ -49024,7 +49483,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49024
49483
|
}
|
|
49025
49484
|
}
|
|
49026
49485
|
if (removed.length > 0)
|
|
49027
|
-
|
|
49486
|
+
log27.info(`Purged ${removed.length} orphaned agent directories`);
|
|
49028
49487
|
return { removed, failed };
|
|
49029
49488
|
}
|
|
49030
49489
|
getAgent(agentId2) {
|
|
@@ -49045,7 +49504,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49045
49504
|
return;
|
|
49046
49505
|
const reviewer = this.getAgent(reviewerAgentId);
|
|
49047
49506
|
reviewer.grantReadOnlyAccess(worktreePath);
|
|
49048
|
-
|
|
49507
|
+
log27.info("Granted reviewer access to worktree", { reviewerAgentId, worktreePath });
|
|
49049
49508
|
}
|
|
49050
49509
|
/**
|
|
49051
49510
|
* Revoke a reviewer agent's read-only access to a task's worktree.
|
|
@@ -49056,7 +49515,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49056
49515
|
return;
|
|
49057
49516
|
const reviewer = this.getAgent(reviewerAgentId);
|
|
49058
49517
|
reviewer.revokeReadOnlyAccess(worktreePath);
|
|
49059
|
-
|
|
49518
|
+
log27.info("Revoked reviewer access to worktree", { reviewerAgentId, worktreePath });
|
|
49060
49519
|
}
|
|
49061
49520
|
setAuditCallback(cb) {
|
|
49062
49521
|
this.agentAuditCallback = cb;
|
|
@@ -49219,7 +49678,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49219
49678
|
}
|
|
49220
49679
|
this.globalPaused = true;
|
|
49221
49680
|
this.eventBus.emit("system:pause-all", { reason });
|
|
49222
|
-
|
|
49681
|
+
log27.info("All agents paused", { reason });
|
|
49223
49682
|
}
|
|
49224
49683
|
async resumeAllAgents() {
|
|
49225
49684
|
for (const [, agent] of this.agents) {
|
|
@@ -49230,7 +49689,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49230
49689
|
this.globalPaused = false;
|
|
49231
49690
|
this.emergencyMode = false;
|
|
49232
49691
|
this.eventBus.emit("system:resume-all", {});
|
|
49233
|
-
|
|
49692
|
+
log27.info("All agents resumed");
|
|
49234
49693
|
}
|
|
49235
49694
|
async emergencyStop() {
|
|
49236
49695
|
for (const [, agent] of this.agents) {
|
|
@@ -49240,7 +49699,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49240
49699
|
this.emergencyMode = true;
|
|
49241
49700
|
this.globalPaused = true;
|
|
49242
49701
|
this.eventBus.emit("system:emergency-stop", {});
|
|
49243
|
-
|
|
49702
|
+
log27.warn("EMERGENCY STOP \u2014 all agents stopped");
|
|
49244
49703
|
}
|
|
49245
49704
|
isGlobalPaused() {
|
|
49246
49705
|
return this.globalPaused;
|
|
@@ -49251,7 +49710,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49251
49710
|
clearEmergencyMode() {
|
|
49252
49711
|
this.emergencyMode = false;
|
|
49253
49712
|
this.globalPaused = false;
|
|
49254
|
-
|
|
49713
|
+
log27.info("Emergency mode cleared");
|
|
49255
49714
|
}
|
|
49256
49715
|
async shutdown() {
|
|
49257
49716
|
for (const [, agent] of this.agents) {
|
|
@@ -49260,7 +49719,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49260
49719
|
} catch {
|
|
49261
49720
|
}
|
|
49262
49721
|
}
|
|
49263
|
-
|
|
49722
|
+
log27.info("AgentManager shutdown complete \u2014 all metrics flushed");
|
|
49264
49723
|
}
|
|
49265
49724
|
// ─── Role Template Versioning & Sync ──────────────────────────────────────
|
|
49266
49725
|
static ROLE_FILES = ["ROLE.md", "HEARTBEAT.md", "POLICIES.md", "CONTEXT.md"];
|
|
@@ -49351,7 +49810,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49351
49810
|
}
|
|
49352
49811
|
}
|
|
49353
49812
|
agent.reloadRole();
|
|
49354
|
-
|
|
49813
|
+
log27.info("Synced agent role from template", { agentId: agentId2, roleId, synced });
|
|
49355
49814
|
return { agentId: agentId2, success: true, synced };
|
|
49356
49815
|
}
|
|
49357
49816
|
checkAllRoleUpdates() {
|
|
@@ -49381,7 +49840,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49381
49840
|
}
|
|
49382
49841
|
}
|
|
49383
49842
|
this.eventBus.emit("system:announcement", announcement);
|
|
49384
|
-
|
|
49843
|
+
log27.info("Announcement broadcast", { id: announcement.id, title: announcement.title });
|
|
49385
49844
|
}
|
|
49386
49845
|
getActiveAnnouncements() {
|
|
49387
49846
|
const now2 = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -49395,13 +49854,20 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49395
49854
|
}
|
|
49396
49855
|
/**
|
|
49397
49856
|
* Rebuild and inject identity context for all agents in an organization.
|
|
49398
|
-
*
|
|
49857
|
+
* Colleagues are scoped to the agent's own team; other teams are listed for cross-team awareness.
|
|
49399
49858
|
*/
|
|
49400
|
-
refreshIdentityContexts(orgId2, orgName, humans) {
|
|
49859
|
+
refreshIdentityContexts(orgId2, orgName, humans, teams2) {
|
|
49401
49860
|
const orgAgents = [...this.agents.values()].filter((a) => a.config.orgId === orgId2);
|
|
49402
|
-
const
|
|
49861
|
+
const agentTeamMap = /* @__PURE__ */ new Map();
|
|
49862
|
+
for (const t of teams2 ?? []) {
|
|
49863
|
+
for (const aid of t.memberAgentIds)
|
|
49864
|
+
agentTeamMap.set(aid, t.id);
|
|
49865
|
+
}
|
|
49403
49866
|
for (const agent of orgAgents) {
|
|
49404
|
-
const
|
|
49867
|
+
const myTeamId = agent.config.teamId ?? agentTeamMap.get(agent.id);
|
|
49868
|
+
const myTeam = teams2?.find((t) => t.id === myTeamId);
|
|
49869
|
+
const sameTeamAgents = myTeamId ? orgAgents.filter((a) => a.id !== agent.id && (a.config.teamId === myTeamId || agentTeamMap.get(a.id) === myTeamId)) : orgAgents.filter((a) => a.id !== agent.id);
|
|
49870
|
+
const colleagues = sameTeamAgents.map((a) => ({
|
|
49405
49871
|
id: a.id,
|
|
49406
49872
|
name: a.config.name,
|
|
49407
49873
|
role: a.role.name,
|
|
@@ -49409,6 +49875,19 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49409
49875
|
skills: a.config.skills,
|
|
49410
49876
|
status: a.getState().status
|
|
49411
49877
|
}));
|
|
49878
|
+
const teamManager = sameTeamAgents.find((a) => a.config.agentRole === "manager");
|
|
49879
|
+
const otherTeams = (teams2 ?? []).filter((t) => t.id !== myTeamId).map((t) => ({
|
|
49880
|
+
id: t.id,
|
|
49881
|
+
name: t.name,
|
|
49882
|
+
members: t.memberAgentIds.map((aid) => {
|
|
49883
|
+
try {
|
|
49884
|
+
const a = this.getAgent(aid);
|
|
49885
|
+
return { id: a.id, name: a.config.name, role: a.role.name };
|
|
49886
|
+
} catch {
|
|
49887
|
+
return null;
|
|
49888
|
+
}
|
|
49889
|
+
}).filter((m) => m !== null)
|
|
49890
|
+
})).filter((t) => t.members.length > 0);
|
|
49412
49891
|
const identity = {
|
|
49413
49892
|
self: {
|
|
49414
49893
|
id: agent.id,
|
|
@@ -49418,13 +49897,15 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
49418
49897
|
skills: agent.config.skills
|
|
49419
49898
|
},
|
|
49420
49899
|
organization: { id: orgId2, name: orgName },
|
|
49900
|
+
team: myTeam ? { id: myTeam.id, name: myTeam.name, description: myTeam.description } : void 0,
|
|
49421
49901
|
colleagues,
|
|
49902
|
+
otherTeams: otherTeams.length > 0 ? otherTeams : void 0,
|
|
49422
49903
|
humans: humans.map((h) => ({ id: h.id, name: h.name, role: h.role })),
|
|
49423
|
-
manager:
|
|
49904
|
+
manager: teamManager && teamManager.id !== agent.id ? { id: teamManager.id, name: teamManager.config.name } : void 0
|
|
49424
49905
|
};
|
|
49425
49906
|
agent.setIdentityContext(identity);
|
|
49426
49907
|
}
|
|
49427
|
-
|
|
49908
|
+
log27.info(`Refreshed identity contexts for ${orgAgents.length} agents in org ${orgId2}`);
|
|
49428
49909
|
}
|
|
49429
49910
|
};
|
|
49430
49911
|
}
|
|
@@ -50484,12 +50965,12 @@ var init_ollama = __esm({
|
|
|
50484
50965
|
import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, mkdirSync as mkdirSync10, existsSync as existsSync16, unlinkSync as unlinkSync2 } from "node:fs";
|
|
50485
50966
|
import { join as join10 } from "node:path";
|
|
50486
50967
|
import { homedir as homedir5 } from "node:os";
|
|
50487
|
-
var
|
|
50968
|
+
var log28, AuthProfileStore;
|
|
50488
50969
|
var init_auth_profiles = __esm({
|
|
50489
50970
|
"../core/dist/llm/auth-profiles.js"() {
|
|
50490
50971
|
"use strict";
|
|
50491
50972
|
init_dist();
|
|
50492
|
-
|
|
50973
|
+
log28 = createLogger("auth-profiles");
|
|
50493
50974
|
AuthProfileStore = class {
|
|
50494
50975
|
filePath;
|
|
50495
50976
|
lockPath;
|
|
@@ -50507,7 +50988,7 @@ var init_auth_profiles = __esm({
|
|
|
50507
50988
|
const raw = readFileSync13(this.filePath, "utf-8");
|
|
50508
50989
|
return JSON.parse(raw);
|
|
50509
50990
|
} catch (err) {
|
|
50510
|
-
|
|
50991
|
+
log28.warn("Failed to read auth-profiles.json, starting fresh", { error: String(err) });
|
|
50511
50992
|
return { version: 1, profiles: [] };
|
|
50512
50993
|
}
|
|
50513
50994
|
}
|
|
@@ -50543,7 +51024,7 @@ var init_auth_profiles = __esm({
|
|
|
50543
51024
|
}
|
|
50544
51025
|
} catch {
|
|
50545
51026
|
}
|
|
50546
|
-
|
|
51027
|
+
log28.debug("Auth profile lock contention, proceeding without lock");
|
|
50547
51028
|
return () => {
|
|
50548
51029
|
};
|
|
50549
51030
|
}
|
|
@@ -50571,7 +51052,7 @@ var init_auth_profiles = __esm({
|
|
|
50571
51052
|
data.profiles.push({ ...profile, createdAt: Date.now(), updatedAt: Date.now() });
|
|
50572
51053
|
}
|
|
50573
51054
|
this.write(data);
|
|
50574
|
-
|
|
51055
|
+
log28.info(`Upserted auth profile: ${profile.id} (${profile.provider}/${profile.authType})`);
|
|
50575
51056
|
} finally {
|
|
50576
51057
|
release2();
|
|
50577
51058
|
}
|
|
@@ -50582,13 +51063,13 @@ var init_auth_profiles = __esm({
|
|
|
50582
51063
|
const data = this.read();
|
|
50583
51064
|
const profile = data.profiles.find((p) => p.id === profileId);
|
|
50584
51065
|
if (!profile) {
|
|
50585
|
-
|
|
51066
|
+
log28.warn(`Profile not found for token update: ${profileId}`);
|
|
50586
51067
|
return;
|
|
50587
51068
|
}
|
|
50588
51069
|
profile.oauth = tokens;
|
|
50589
51070
|
profile.updatedAt = Date.now();
|
|
50590
51071
|
this.write(data);
|
|
50591
|
-
|
|
51072
|
+
log28.debug(`Updated OAuth tokens for profile: ${profileId}`);
|
|
50592
51073
|
} finally {
|
|
50593
51074
|
release2();
|
|
50594
51075
|
}
|
|
@@ -50601,7 +51082,7 @@ var init_auth_profiles = __esm({
|
|
|
50601
51082
|
data.profiles = data.profiles.filter((p) => p.id !== id);
|
|
50602
51083
|
if (data.profiles.length < before2) {
|
|
50603
51084
|
this.write(data);
|
|
50604
|
-
|
|
51085
|
+
log28.info(`Deleted auth profile: ${id}`);
|
|
50605
51086
|
return true;
|
|
50606
51087
|
}
|
|
50607
51088
|
return false;
|
|
@@ -50702,12 +51183,12 @@ function callbackHtml(title, message, success2) {
|
|
|
50702
51183
|
<p>${message}</p>
|
|
50703
51184
|
</div></body></html>`;
|
|
50704
51185
|
}
|
|
50705
|
-
var
|
|
51186
|
+
var log29, KNOWN_OAUTH_PROVIDERS, OAuthManager;
|
|
50706
51187
|
var init_oauth_manager = __esm({
|
|
50707
51188
|
"../core/dist/llm/oauth-manager.js"() {
|
|
50708
51189
|
"use strict";
|
|
50709
51190
|
init_dist();
|
|
50710
|
-
|
|
51191
|
+
log29 = createLogger("oauth-manager");
|
|
50711
51192
|
KNOWN_OAUTH_PROVIDERS = {
|
|
50712
51193
|
"openai-codex": {
|
|
50713
51194
|
authorizeUrl: "https://auth.openai.com/oauth/authorize",
|
|
@@ -50726,7 +51207,7 @@ var init_oauth_manager = __esm({
|
|
|
50726
51207
|
}
|
|
50727
51208
|
registerProvider(name, config) {
|
|
50728
51209
|
this.customProviders.set(name, config);
|
|
50729
|
-
|
|
51210
|
+
log29.info(`Registered custom OAuth provider: ${name}`);
|
|
50730
51211
|
}
|
|
50731
51212
|
getProviderConfig(provider) {
|
|
50732
51213
|
return this.customProviders.get(provider) ?? KNOWN_OAUTH_PROVIDERS[provider];
|
|
@@ -50805,10 +51286,10 @@ var init_oauth_manager = __esm({
|
|
|
50805
51286
|
});
|
|
50806
51287
|
pending.server = server;
|
|
50807
51288
|
server.listen(port, "localhost", () => {
|
|
50808
|
-
|
|
51289
|
+
log29.info(`OAuth callback server listening on localhost:${port} for ${provider}`);
|
|
50809
51290
|
});
|
|
50810
51291
|
server.on("error", (err) => {
|
|
50811
|
-
|
|
51292
|
+
log29.error(`Failed to start OAuth callback server on port ${port}`, { error: String(err) });
|
|
50812
51293
|
this.cleanupPending(state);
|
|
50813
51294
|
reject(new Error(`Cannot start callback server: ${err.message}. Port ${port} may be in use.`));
|
|
50814
51295
|
});
|
|
@@ -50873,7 +51354,7 @@ var init_oauth_manager = __esm({
|
|
|
50873
51354
|
expiresAt: Date.now() + (data.expires_in ?? 3600) * 1e3,
|
|
50874
51355
|
accountId: extractAccountId(data.access_token)
|
|
50875
51356
|
};
|
|
50876
|
-
|
|
51357
|
+
log29.info(`OAuth token exchange successful for ${provider}`, { accountId: tokens.accountId });
|
|
50877
51358
|
return tokens;
|
|
50878
51359
|
}
|
|
50879
51360
|
/**
|
|
@@ -50910,7 +51391,7 @@ var init_oauth_manager = __esm({
|
|
|
50910
51391
|
accountId: profile.oauth.accountId ?? extractAccountId(data.access_token)
|
|
50911
51392
|
};
|
|
50912
51393
|
this.profileStore.updateOAuthTokens(profileId, newTokens);
|
|
50913
|
-
|
|
51394
|
+
log29.info(`Refreshed OAuth token for profile ${profileId}`);
|
|
50914
51395
|
return newTokens.accessToken;
|
|
50915
51396
|
}
|
|
50916
51397
|
/**
|
|
@@ -50931,7 +51412,7 @@ var init_oauth_manager = __esm({
|
|
|
50931
51412
|
return profile.oauth.accessToken;
|
|
50932
51413
|
}
|
|
50933
51414
|
if (profile.oauth.refreshToken) {
|
|
50934
|
-
|
|
51415
|
+
log29.debug(`Token expiring soon for ${profileId}, refreshing...`);
|
|
50935
51416
|
return this.refreshToken(profileId);
|
|
50936
51417
|
}
|
|
50937
51418
|
if (profile.oauth.expiresAt > Date.now()) {
|
|
@@ -50976,7 +51457,7 @@ var init_oauth_manager = __esm({
|
|
|
50976
51457
|
clearTimeout(pending.timeoutHandle);
|
|
50977
51458
|
if (pending.server) {
|
|
50978
51459
|
pending.server.close(() => {
|
|
50979
|
-
|
|
51460
|
+
log29.debug(`Closed OAuth callback server for state ${state.slice(0, 8)}...`);
|
|
50980
51461
|
});
|
|
50981
51462
|
}
|
|
50982
51463
|
this.pendingLogins.delete(state);
|
|
@@ -51009,7 +51490,7 @@ function buildTiers(providerNames, defaultProvider) {
|
|
|
51009
51490
|
}
|
|
51010
51491
|
return tiers;
|
|
51011
51492
|
}
|
|
51012
|
-
var
|
|
51493
|
+
var log30, ALL_COMPLEXITY, LLMRouter, PROVIDER_DISPLAY_NAMES, BUILTIN_MODEL_CATALOG;
|
|
51013
51494
|
var init_router = __esm({
|
|
51014
51495
|
"../core/dist/llm/router.js"() {
|
|
51015
51496
|
"use strict";
|
|
@@ -51021,7 +51502,7 @@ var init_router = __esm({
|
|
|
51021
51502
|
init_ollama();
|
|
51022
51503
|
init_auth_profiles();
|
|
51023
51504
|
init_oauth_manager();
|
|
51024
|
-
|
|
51505
|
+
log30 = createLogger("llm-router");
|
|
51025
51506
|
ALL_COMPLEXITY = ["simple", "moderate", "complex"];
|
|
51026
51507
|
LLMRouter = class _LLMRouter {
|
|
51027
51508
|
providers = /* @__PURE__ */ new Map();
|
|
@@ -51078,7 +51559,7 @@ var init_router = __esm({
|
|
|
51078
51559
|
};
|
|
51079
51560
|
const provider = new OpenAIProvider({ ...providerConfig, provider: name }, async () => oauthMgr.getValidToken(profileId));
|
|
51080
51561
|
this.registerProvider(name, provider);
|
|
51081
|
-
|
|
51562
|
+
log30.info(`Registered OAuth-backed provider: ${name}`, { profileId, model: providerConfig.model });
|
|
51082
51563
|
}
|
|
51083
51564
|
get defaultProviderName() {
|
|
51084
51565
|
return this.defaultProvider;
|
|
@@ -51110,13 +51591,13 @@ var init_router = __esm({
|
|
|
51110
51591
|
if (fatal && !h.degraded) {
|
|
51111
51592
|
h.degraded = true;
|
|
51112
51593
|
h.resetMs = this.CIRCUIT_RESET_FATAL_MS;
|
|
51113
|
-
|
|
51594
|
+
log30.warn(`Provider ${name} immediately degraded (non-retryable error) \u2014 skipping for ${this.CIRCUIT_RESET_FATAL_MS / 6e4} min`);
|
|
51114
51595
|
return;
|
|
51115
51596
|
}
|
|
51116
51597
|
if (h.consecutiveFailures >= this.CIRCUIT_OPEN_AFTER && !h.degraded) {
|
|
51117
51598
|
h.degraded = true;
|
|
51118
51599
|
h.resetMs = this.CIRCUIT_RESET_MS;
|
|
51119
|
-
|
|
51600
|
+
log30.warn(`Provider ${name} marked as degraded after ${h.consecutiveFailures} failures \u2014 skipping for ${this.CIRCUIT_RESET_MS / 6e4} min`);
|
|
51120
51601
|
}
|
|
51121
51602
|
}
|
|
51122
51603
|
isAvailable(name) {
|
|
@@ -51127,7 +51608,7 @@ var init_router = __esm({
|
|
|
51127
51608
|
return true;
|
|
51128
51609
|
const resetMs = h.resetMs ?? this.CIRCUIT_RESET_MS;
|
|
51129
51610
|
if (Date.now() - h.lastFailureAt > resetMs) {
|
|
51130
|
-
|
|
51611
|
+
log30.info(`Provider ${name} circuit reset \u2014 will retry`);
|
|
51131
51612
|
h.degraded = false;
|
|
51132
51613
|
h.consecutiveFailures = 0;
|
|
51133
51614
|
return true;
|
|
@@ -51136,7 +51617,7 @@ var init_router = __esm({
|
|
|
51136
51617
|
}
|
|
51137
51618
|
registerProvider(name, provider) {
|
|
51138
51619
|
this.providers.set(name, provider);
|
|
51139
|
-
|
|
51620
|
+
log30.info(`Registered LLM provider: ${name}`, { model: provider.model });
|
|
51140
51621
|
}
|
|
51141
51622
|
enableAutoSelect(tiers) {
|
|
51142
51623
|
this.autoSelect = true;
|
|
@@ -51170,15 +51651,15 @@ var init_router = __esm({
|
|
|
51170
51651
|
const complexity = _LLMRouter.assessComplexity(request);
|
|
51171
51652
|
const match = this.providerTiers.find((t) => t.complexity.includes(complexity) && this.providers.has(t.name) && this.isAvailable(t.name));
|
|
51172
51653
|
if (match) {
|
|
51173
|
-
|
|
51654
|
+
log30.debug(`Auto-selected provider: ${match.name}`, { complexity });
|
|
51174
51655
|
return match.name;
|
|
51175
51656
|
}
|
|
51176
51657
|
const healthy = [...this.providers.keys()].find((n) => this.isAvailable(n));
|
|
51177
51658
|
if (healthy) {
|
|
51178
|
-
|
|
51659
|
+
log30.warn(`All tiered providers degraded for complexity=${complexity}, falling back to: ${healthy}`);
|
|
51179
51660
|
return healthy;
|
|
51180
51661
|
}
|
|
51181
|
-
|
|
51662
|
+
log30.warn("All providers degraded \u2014 using default as last resort");
|
|
51182
51663
|
return this.defaultProvider;
|
|
51183
51664
|
}
|
|
51184
51665
|
getFallbacks(primary) {
|
|
@@ -51228,7 +51709,7 @@ var init_router = __esm({
|
|
|
51228
51709
|
timeoutMs: cfg?.timeoutMs
|
|
51229
51710
|
});
|
|
51230
51711
|
} catch (err) {
|
|
51231
|
-
|
|
51712
|
+
log30.warn(`Failed to auto-register OAuth provider ${providerName}`, { error: String(err) });
|
|
51232
51713
|
}
|
|
51233
51714
|
}
|
|
51234
51715
|
}
|
|
@@ -51241,7 +51722,7 @@ var init_router = __esm({
|
|
|
51241
51722
|
...providerNames.filter((n) => n !== effectiveDefault)
|
|
51242
51723
|
].filter((n) => providerNames.includes(n));
|
|
51243
51724
|
router.setFallbackOrder(fallbackOrder);
|
|
51244
|
-
|
|
51725
|
+
log30.info("Auto-select enabled with fallback", { providers: providerNames, defaultProvider: effectiveDefault, fallbackOrder });
|
|
51245
51726
|
}
|
|
51246
51727
|
return router;
|
|
51247
51728
|
}
|
|
@@ -51261,7 +51742,7 @@ var init_router = __esm({
|
|
|
51261
51742
|
throw new Error(`LLM provider not found: ${primary}. Available: ${[...this.providers.keys()].join(", ")}`);
|
|
51262
51743
|
}
|
|
51263
51744
|
request = this.resolveMaxTokens(request, primary);
|
|
51264
|
-
|
|
51745
|
+
log30.debug(`Sending request to ${primary}`, { model: provider.model, messageCount: request.messages.length });
|
|
51265
51746
|
const span = startSpan("llm.chat", { provider: primary, model: provider.model });
|
|
51266
51747
|
const startTime = Date.now();
|
|
51267
51748
|
let lastError = null;
|
|
@@ -51269,27 +51750,27 @@ var init_router = __esm({
|
|
|
51269
51750
|
const response = await provider.chat(request);
|
|
51270
51751
|
this.recordSuccess(primary);
|
|
51271
51752
|
span.end({ inputTokens: response.usage.inputTokens, outputTokens: response.usage.outputTokens, finishReason: response.finishReason });
|
|
51272
|
-
|
|
51753
|
+
log30.debug(`Response from ${primary}`, { tokens: response.usage, finishReason: response.finishReason });
|
|
51273
51754
|
this.emitLog(primary, provider.model, request, response, Date.now() - startTime);
|
|
51274
51755
|
return response;
|
|
51275
51756
|
} catch (error) {
|
|
51276
51757
|
lastError = error;
|
|
51277
51758
|
this.recordFailure(primary, error);
|
|
51278
|
-
|
|
51759
|
+
log30.error(`LLM request failed for ${primary}`, { error: String(error) });
|
|
51279
51760
|
for (const fallbackName of this.getFallbacks(primary)) {
|
|
51280
51761
|
const fb = this.providers.get(fallbackName);
|
|
51281
|
-
|
|
51762
|
+
log30.info(`Falling back to ${fallbackName}`, { model: fb.model });
|
|
51282
51763
|
try {
|
|
51283
51764
|
const response = await fb.chat(request);
|
|
51284
51765
|
this.recordSuccess(fallbackName);
|
|
51285
51766
|
span.end({ inputTokens: response.usage.inputTokens, outputTokens: response.usage.outputTokens, finishReason: response.finishReason });
|
|
51286
|
-
|
|
51767
|
+
log30.info(`Fallback to ${fallbackName} succeeded`);
|
|
51287
51768
|
this.emitLog(fallbackName, fb.model, request, response, Date.now() - startTime);
|
|
51288
51769
|
return response;
|
|
51289
51770
|
} catch (fbError) {
|
|
51290
51771
|
lastError = fbError;
|
|
51291
51772
|
this.recordFailure(fallbackName, fbError);
|
|
51292
|
-
|
|
51773
|
+
log30.error(`Fallback ${fallbackName} also failed`, { error: String(fbError) });
|
|
51293
51774
|
}
|
|
51294
51775
|
}
|
|
51295
51776
|
span.setError(lastError instanceof Error ? lastError : String(lastError));
|
|
@@ -51307,7 +51788,7 @@ var init_router = __esm({
|
|
|
51307
51788
|
const span = startSpan("llm.chatStream", { provider: primary, model: provider.model });
|
|
51308
51789
|
const startTime = Date.now();
|
|
51309
51790
|
if (!provider.chatStream) {
|
|
51310
|
-
|
|
51791
|
+
log30.debug(`Provider ${primary} does not support streaming, falling back to non-stream`);
|
|
51311
51792
|
const response = await provider.chat(request);
|
|
51312
51793
|
if (response.content)
|
|
51313
51794
|
onEvent({ type: "text_delta", text: response.content });
|
|
@@ -51331,10 +51812,10 @@ var init_router = __esm({
|
|
|
51331
51812
|
span.end();
|
|
51332
51813
|
throw lastError;
|
|
51333
51814
|
}
|
|
51334
|
-
|
|
51815
|
+
log30.error(`LLM stream request failed for ${primary}`, { error: String(error) });
|
|
51335
51816
|
for (const fallbackName of this.getFallbacks(primary)) {
|
|
51336
51817
|
const fb = this.providers.get(fallbackName);
|
|
51337
|
-
|
|
51818
|
+
log30.info(`Stream fallback to ${fallbackName}`);
|
|
51338
51819
|
try {
|
|
51339
51820
|
let response;
|
|
51340
51821
|
if (fb.chatStream) {
|
|
@@ -51348,14 +51829,14 @@ var init_router = __esm({
|
|
|
51348
51829
|
this.recordSuccess(fallbackName);
|
|
51349
51830
|
span.end({ inputTokens: response.usage.inputTokens, outputTokens: response.usage.outputTokens, finishReason: response.finishReason });
|
|
51350
51831
|
this.emitLog(fallbackName, fb.model, request, response, Date.now() - startTime);
|
|
51351
|
-
|
|
51832
|
+
log30.info(`Stream fallback to ${fallbackName} succeeded`);
|
|
51352
51833
|
return response;
|
|
51353
51834
|
} catch (fbError) {
|
|
51354
51835
|
lastError = fbError;
|
|
51355
51836
|
this.recordFailure(fallbackName, fbError);
|
|
51356
51837
|
if (signal?.aborted)
|
|
51357
51838
|
break;
|
|
51358
|
-
|
|
51839
|
+
log30.error(`Stream fallback ${fallbackName} failed`, { error: String(fbError) });
|
|
51359
51840
|
}
|
|
51360
51841
|
}
|
|
51361
51842
|
span.setError(lastError instanceof Error ? lastError : String(lastError));
|
|
@@ -51382,7 +51863,7 @@ var init_router = __esm({
|
|
|
51382
51863
|
throw new Error(`Cannot set default to unknown provider: ${name}. Available: ${[...this.providers.keys()].join(", ")}`);
|
|
51383
51864
|
}
|
|
51384
51865
|
this.defaultProvider = name;
|
|
51385
|
-
|
|
51866
|
+
log30.info(`Default LLM provider updated to: ${name}`);
|
|
51386
51867
|
const providerNames = this.listProviders();
|
|
51387
51868
|
if (this.autoSelect && providerNames.length > 1) {
|
|
51388
51869
|
this.providerTiers = buildTiers(providerNames, name);
|
|
@@ -51449,7 +51930,7 @@ var init_router = __esm({
|
|
|
51449
51930
|
...this.customModelConfigs.get(providerName) ?? {},
|
|
51450
51931
|
...config
|
|
51451
51932
|
});
|
|
51452
|
-
|
|
51933
|
+
log30.info(`Updated model config for ${providerName}`, config);
|
|
51453
51934
|
}
|
|
51454
51935
|
setProviderEnabled(providerName, enabled) {
|
|
51455
51936
|
if (enabled) {
|
|
@@ -51457,7 +51938,7 @@ var init_router = __esm({
|
|
|
51457
51938
|
} else {
|
|
51458
51939
|
this.disabledProviders.add(providerName);
|
|
51459
51940
|
}
|
|
51460
|
-
|
|
51941
|
+
log30.info(`Provider ${providerName} ${enabled ? "enabled" : "disabled"}`);
|
|
51461
51942
|
}
|
|
51462
51943
|
isProviderEnabled(providerName) {
|
|
51463
51944
|
return !this.disabledProviders.has(providerName);
|
|
@@ -51581,12 +52062,12 @@ var init_router = __esm({
|
|
|
51581
52062
|
import { mkdirSync as mkdirSync11, appendFileSync as appendFileSync2 } from "node:fs";
|
|
51582
52063
|
import { join as join11 } from "node:path";
|
|
51583
52064
|
import { homedir as homedir6 } from "node:os";
|
|
51584
|
-
var
|
|
52065
|
+
var log31, LLMLogger;
|
|
51585
52066
|
var init_llm_logger = __esm({
|
|
51586
52067
|
"../core/dist/llm/llm-logger.js"() {
|
|
51587
52068
|
"use strict";
|
|
51588
52069
|
init_dist();
|
|
51589
|
-
|
|
52070
|
+
log31 = createLogger("llm-logger");
|
|
51590
52071
|
LLMLogger = class {
|
|
51591
52072
|
logDir;
|
|
51592
52073
|
enabled;
|
|
@@ -51597,7 +52078,7 @@ var init_llm_logger = __esm({
|
|
|
51597
52078
|
try {
|
|
51598
52079
|
mkdirSync11(this.logDir, { recursive: true });
|
|
51599
52080
|
} catch {
|
|
51600
|
-
|
|
52081
|
+
log31.warn("Failed to create LLM log directory", { dir: this.logDir });
|
|
51601
52082
|
this.enabled = false;
|
|
51602
52083
|
}
|
|
51603
52084
|
}
|
|
@@ -51611,7 +52092,7 @@ var init_llm_logger = __esm({
|
|
|
51611
52092
|
const line2 = JSON.stringify(entry) + "\n";
|
|
51612
52093
|
appendFileSync2(filePath, line2, "utf-8");
|
|
51613
52094
|
} catch (err) {
|
|
51614
|
-
|
|
52095
|
+
log31.warn("Failed to write LLM log entry", { error: String(err) });
|
|
51615
52096
|
}
|
|
51616
52097
|
}
|
|
51617
52098
|
};
|
|
@@ -51637,12 +52118,12 @@ var init_enhanced_role_loader = __esm({
|
|
|
51637
52118
|
|
|
51638
52119
|
// ../core/dist/external-gateway.js
|
|
51639
52120
|
import { createHmac, randomBytes as randomBytes3, timingSafeEqual } from "node:crypto";
|
|
51640
|
-
var
|
|
52121
|
+
var log32, ExternalAgentGateway, GatewayError;
|
|
51641
52122
|
var init_external_gateway = __esm({
|
|
51642
52123
|
"../core/dist/external-gateway.js"() {
|
|
51643
52124
|
"use strict";
|
|
51644
52125
|
init_dist();
|
|
51645
|
-
|
|
52126
|
+
log32 = createLogger("external-gateway");
|
|
51646
52127
|
ExternalAgentGateway = class {
|
|
51647
52128
|
config;
|
|
51648
52129
|
registrations = /* @__PURE__ */ new Map();
|
|
@@ -51688,14 +52169,14 @@ var init_external_gateway = __esm({
|
|
|
51688
52169
|
if (this.store) {
|
|
51689
52170
|
await this.store.saveRegistration(reg);
|
|
51690
52171
|
}
|
|
51691
|
-
|
|
52172
|
+
log32.info("Recreated Markus agent for external registration", { externalAgentId: reg.externalAgentId, markusAgentId: created.id });
|
|
51692
52173
|
} catch (err) {
|
|
51693
|
-
|
|
52174
|
+
log32.error("Failed to recreate Markus agent for external registration", { externalAgentId: reg.externalAgentId, error: String(err) });
|
|
51694
52175
|
}
|
|
51695
52176
|
}
|
|
51696
52177
|
}
|
|
51697
52178
|
if (rows.length > 0) {
|
|
51698
|
-
|
|
52179
|
+
log32.info("Loaded external agent registrations from store", { count: rows.length });
|
|
51699
52180
|
}
|
|
51700
52181
|
return rows.length;
|
|
51701
52182
|
}
|
|
@@ -51718,7 +52199,7 @@ var init_external_gateway = __esm({
|
|
|
51718
52199
|
const created = await this.agentCreator({ name: agentName, orgId: orgId2, capabilities });
|
|
51719
52200
|
markusAgentId = created.id;
|
|
51720
52201
|
} catch (err) {
|
|
51721
|
-
|
|
52202
|
+
log32.error("Failed to create Markus agent for external registration", { externalAgentId, error: String(err) });
|
|
51722
52203
|
throw new GatewayError(`Failed to create internal agent: ${String(err)}`, 500);
|
|
51723
52204
|
}
|
|
51724
52205
|
}
|
|
@@ -51735,9 +52216,9 @@ var init_external_gateway = __esm({
|
|
|
51735
52216
|
this.registrations.set(key2, registration);
|
|
51736
52217
|
this.orgAgentCounts.set(orgId2, orgCount + 1);
|
|
51737
52218
|
if (this.store) {
|
|
51738
|
-
await this.store.saveRegistration(registration).catch((err) =>
|
|
52219
|
+
await this.store.saveRegistration(registration).catch((err) => log32.error("Failed to persist registration", { externalAgentId, error: String(err) }));
|
|
51739
52220
|
}
|
|
51740
|
-
|
|
52221
|
+
log32.info("External agent registered", { externalAgentId, orgId: orgId2, markusAgentId });
|
|
51741
52222
|
return registration;
|
|
51742
52223
|
}
|
|
51743
52224
|
authenticate(request) {
|
|
@@ -51767,7 +52248,7 @@ var init_external_gateway = __esm({
|
|
|
51767
52248
|
expiresAt: Date.now() + this.config.tokenExpiryMs
|
|
51768
52249
|
};
|
|
51769
52250
|
const token = this.signToken(tokenPayload);
|
|
51770
|
-
|
|
52251
|
+
log32.info("External agent authenticated", { externalAgentId, orgId: orgId2, markusAgentId: registration.markusAgentId });
|
|
51771
52252
|
return {
|
|
51772
52253
|
token,
|
|
51773
52254
|
externalAgentId,
|
|
@@ -51832,7 +52313,7 @@ var init_external_gateway = __esm({
|
|
|
51832
52313
|
const response = await this.messageRouter(token.markusAgentId, `[${message.type.toUpperCase()}] ${message.content}`, token.externalAgentId);
|
|
51833
52314
|
return { success: true, messageId, response };
|
|
51834
52315
|
} catch (err) {
|
|
51835
|
-
|
|
52316
|
+
log32.error("Message routing failed", { messageId, error: String(err) });
|
|
51836
52317
|
return { success: false, messageId, error: String(err) };
|
|
51837
52318
|
}
|
|
51838
52319
|
}
|
|
@@ -51858,7 +52339,7 @@ var init_external_gateway = __esm({
|
|
|
51858
52339
|
this.store.updateRegistration(externalAgentId, orgId2, { connected: false }).catch(() => {
|
|
51859
52340
|
});
|
|
51860
52341
|
}
|
|
51861
|
-
|
|
52342
|
+
log32.info("External agent disconnected", { externalAgentId, orgId: orgId2 });
|
|
51862
52343
|
}
|
|
51863
52344
|
}
|
|
51864
52345
|
async unregister(externalAgentId, orgId2) {
|
|
@@ -51870,9 +52351,9 @@ var init_external_gateway = __esm({
|
|
|
51870
52351
|
const count = this.orgAgentCounts.get(orgId2) ?? 1;
|
|
51871
52352
|
this.orgAgentCounts.set(orgId2, Math.max(0, count - 1));
|
|
51872
52353
|
if (this.store) {
|
|
51873
|
-
await this.store.deleteRegistration(externalAgentId, orgId2).catch((err) =>
|
|
52354
|
+
await this.store.deleteRegistration(externalAgentId, orgId2).catch((err) => log32.error("Failed to delete registration from store", { externalAgentId, error: String(err) }));
|
|
51874
52355
|
}
|
|
51875
|
-
|
|
52356
|
+
log32.info("External agent unregistered", { externalAgentId, orgId: orgId2 });
|
|
51876
52357
|
return reg;
|
|
51877
52358
|
}
|
|
51878
52359
|
listRegistrations(orgId2) {
|
|
@@ -52176,12 +52657,12 @@ var init_markus_handbook = __esm({
|
|
|
52176
52657
|
});
|
|
52177
52658
|
|
|
52178
52659
|
// ../core/dist/gateway/sync-handler.js
|
|
52179
|
-
var
|
|
52660
|
+
var log33, GatewaySyncHandler;
|
|
52180
52661
|
var init_sync_handler = __esm({
|
|
52181
52662
|
"../core/dist/gateway/sync-handler.js"() {
|
|
52182
52663
|
"use strict";
|
|
52183
52664
|
init_dist();
|
|
52184
|
-
|
|
52665
|
+
log33 = createLogger("gateway-sync");
|
|
52185
52666
|
GatewaySyncHandler = class {
|
|
52186
52667
|
tasks;
|
|
52187
52668
|
messages;
|
|
@@ -52212,9 +52693,9 @@ var init_sync_handler = __esm({
|
|
|
52212
52693
|
for (const ct of req.completedTasks) {
|
|
52213
52694
|
try {
|
|
52214
52695
|
this.tasks.updateTaskStatus(ct.taskId, "completed", `ext:${markusAgentId}`);
|
|
52215
|
-
|
|
52696
|
+
log33.info("External agent completed task", { markusAgentId, taskId: ct.taskId });
|
|
52216
52697
|
} catch (e) {
|
|
52217
|
-
|
|
52698
|
+
log33.warn("Failed to complete task from sync", { taskId: ct.taskId, error: String(e) });
|
|
52218
52699
|
}
|
|
52219
52700
|
}
|
|
52220
52701
|
}
|
|
@@ -52222,9 +52703,9 @@ var init_sync_handler = __esm({
|
|
|
52222
52703
|
for (const ft of req.failedTasks) {
|
|
52223
52704
|
try {
|
|
52224
52705
|
this.tasks.updateTaskStatus(ft.taskId, "failed", `ext:${markusAgentId}`);
|
|
52225
|
-
|
|
52706
|
+
log33.info("External agent failed task", { markusAgentId, taskId: ft.taskId, error: ft.error });
|
|
52226
52707
|
} catch (e) {
|
|
52227
|
-
|
|
52708
|
+
log33.warn("Failed to update task failure from sync", { taskId: ft.taskId, error: String(e) });
|
|
52228
52709
|
}
|
|
52229
52710
|
}
|
|
52230
52711
|
}
|
|
@@ -52241,7 +52722,7 @@ var init_sync_handler = __esm({
|
|
|
52241
52722
|
try {
|
|
52242
52723
|
this.messages.deliver(markusAgentId, msg.to, msg.content);
|
|
52243
52724
|
} catch (e) {
|
|
52244
|
-
|
|
52725
|
+
log33.warn("Failed to deliver message from sync", { to: msg.to, error: String(e) });
|
|
52245
52726
|
}
|
|
52246
52727
|
}
|
|
52247
52728
|
}
|
|
@@ -52297,26 +52778,26 @@ var init_gateway = __esm({
|
|
|
52297
52778
|
// ../core/dist/review-service.js
|
|
52298
52779
|
import { exec as execCb } from "node:child_process";
|
|
52299
52780
|
import { promisify as promisify2 } from "node:util";
|
|
52300
|
-
var execAsync,
|
|
52781
|
+
var execAsync, log34;
|
|
52301
52782
|
var init_review_service = __esm({
|
|
52302
52783
|
"../core/dist/review-service.js"() {
|
|
52303
52784
|
"use strict";
|
|
52304
52785
|
init_dist();
|
|
52305
52786
|
execAsync = promisify2(execCb);
|
|
52306
|
-
|
|
52787
|
+
log34 = createLogger("review-service");
|
|
52307
52788
|
}
|
|
52308
52789
|
});
|
|
52309
52790
|
|
|
52310
52791
|
// ../core/dist/workspace-manager.js
|
|
52311
52792
|
import { exec as execCb2 } from "node:child_process";
|
|
52312
52793
|
import { promisify as promisify3 } from "node:util";
|
|
52313
|
-
var execAsync2,
|
|
52794
|
+
var execAsync2, log35;
|
|
52314
52795
|
var init_workspace_manager = __esm({
|
|
52315
52796
|
"../core/dist/workspace-manager.js"() {
|
|
52316
52797
|
"use strict";
|
|
52317
52798
|
init_dist();
|
|
52318
52799
|
execAsync2 = promisify3(execCb2);
|
|
52319
|
-
|
|
52800
|
+
log35 = createLogger("workspace-manager");
|
|
52320
52801
|
}
|
|
52321
52802
|
});
|
|
52322
52803
|
|
|
@@ -52339,26 +52820,27 @@ var init_tools = __esm({
|
|
|
52339
52820
|
init_a2a_structured();
|
|
52340
52821
|
init_task_tools();
|
|
52341
52822
|
init_memory();
|
|
52823
|
+
init_subagent();
|
|
52342
52824
|
}
|
|
52343
52825
|
});
|
|
52344
52826
|
|
|
52345
52827
|
// ../core/dist/tool-profiles.js
|
|
52346
|
-
var
|
|
52828
|
+
var log36;
|
|
52347
52829
|
var init_tool_profiles = __esm({
|
|
52348
52830
|
"../core/dist/tool-profiles.js"() {
|
|
52349
52831
|
"use strict";
|
|
52350
52832
|
init_dist();
|
|
52351
|
-
|
|
52833
|
+
log36 = createLogger("tool-profiles");
|
|
52352
52834
|
}
|
|
52353
52835
|
});
|
|
52354
52836
|
|
|
52355
52837
|
// ../core/dist/skills/registry.js
|
|
52356
|
-
var
|
|
52838
|
+
var log37, InMemorySkillRegistry;
|
|
52357
52839
|
var init_registry = __esm({
|
|
52358
52840
|
"../core/dist/skills/registry.js"() {
|
|
52359
52841
|
"use strict";
|
|
52360
52842
|
init_dist();
|
|
52361
|
-
|
|
52843
|
+
log37 = createLogger("skill-registry");
|
|
52362
52844
|
InMemorySkillRegistry = class _InMemorySkillRegistry {
|
|
52363
52845
|
skills = /* @__PURE__ */ new Map();
|
|
52364
52846
|
aliases = /* @__PURE__ */ new Map();
|
|
@@ -52368,18 +52850,18 @@ var init_registry = __esm({
|
|
|
52368
52850
|
register(skill) {
|
|
52369
52851
|
const name = skill.manifest.name;
|
|
52370
52852
|
if (this.skills.has(name)) {
|
|
52371
|
-
|
|
52853
|
+
log37.warn(`Skill ${name} already registered, overwriting`);
|
|
52372
52854
|
}
|
|
52373
52855
|
this.skills.set(name, skill);
|
|
52374
52856
|
this.aliases.set(_InMemorySkillRegistry.normalize(name), name);
|
|
52375
|
-
|
|
52857
|
+
log37.info(`Skill registered: ${name} v${skill.manifest.version}`, {
|
|
52376
52858
|
hasInstructions: !!skill.manifest.instructions
|
|
52377
52859
|
});
|
|
52378
52860
|
}
|
|
52379
52861
|
unregister(skillName) {
|
|
52380
52862
|
this.skills.delete(skillName);
|
|
52381
52863
|
this.aliases.delete(_InMemorySkillRegistry.normalize(skillName));
|
|
52382
|
-
|
|
52864
|
+
log37.info(`Skill unregistered: ${skillName}`);
|
|
52383
52865
|
}
|
|
52384
52866
|
get(skillName) {
|
|
52385
52867
|
return this.skills.get(skillName) ?? this.skills.get(this.aliases.get(_InMemorySkillRegistry.normalize(skillName)) ?? "");
|
|
@@ -52451,12 +52933,12 @@ function readSkillInstructions(skillDir) {
|
|
|
52451
52933
|
return void 0;
|
|
52452
52934
|
}
|
|
52453
52935
|
}
|
|
52454
|
-
var
|
|
52936
|
+
var log38;
|
|
52455
52937
|
var init_loader = __esm({
|
|
52456
52938
|
"../core/dist/skills/loader.js"() {
|
|
52457
52939
|
"use strict";
|
|
52458
52940
|
init_dist();
|
|
52459
|
-
|
|
52941
|
+
log38 = createLogger("skill-loader");
|
|
52460
52942
|
}
|
|
52461
52943
|
});
|
|
52462
52944
|
|
|
@@ -52540,7 +53022,7 @@ function discoverSkillsInDir(dir) {
|
|
|
52540
53022
|
results.push({ manifest, path: skillDir, source: dir });
|
|
52541
53023
|
}
|
|
52542
53024
|
} catch (err) {
|
|
52543
|
-
|
|
53025
|
+
log39.warn(`Invalid SKILL.md in ${skillDir}: ${err}`);
|
|
52544
53026
|
}
|
|
52545
53027
|
continue;
|
|
52546
53028
|
}
|
|
@@ -52556,14 +53038,14 @@ async function createDefaultSkillRegistry(options) {
|
|
|
52556
53038
|
const found = discoverSkillsInDir(dir);
|
|
52557
53039
|
for (const { manifest, path: skillPath } of found) {
|
|
52558
53040
|
if (registry.get(manifest.name)) {
|
|
52559
|
-
|
|
53041
|
+
log39.debug(`Skill ${manifest.name} already registered, skipping ${skillPath}`);
|
|
52560
53042
|
continue;
|
|
52561
53043
|
}
|
|
52562
53044
|
manifest.sourcePath = skillPath;
|
|
52563
53045
|
if (isBuiltin)
|
|
52564
53046
|
manifest.builtIn = true;
|
|
52565
53047
|
registry.register({ manifest });
|
|
52566
|
-
|
|
53048
|
+
log39.info(`Loaded skill: ${manifest.name} from ${skillPath}`, {
|
|
52567
53049
|
hasInstructions: !!manifest.instructions,
|
|
52568
53050
|
builtIn: isBuiltin
|
|
52569
53051
|
});
|
|
@@ -52571,7 +53053,7 @@ async function createDefaultSkillRegistry(options) {
|
|
|
52571
53053
|
}
|
|
52572
53054
|
return registry;
|
|
52573
53055
|
}
|
|
52574
|
-
var
|
|
53056
|
+
var log39, WELL_KNOWN_SKILL_DIRS;
|
|
52575
53057
|
var init_skills = __esm({
|
|
52576
53058
|
"../core/dist/skills/index.js"() {
|
|
52577
53059
|
"use strict";
|
|
@@ -52579,7 +53061,7 @@ var init_skills = __esm({
|
|
|
52579
53061
|
init_dist();
|
|
52580
53062
|
init_registry();
|
|
52581
53063
|
init_loader();
|
|
52582
|
-
|
|
53064
|
+
log39 = createLogger("skill-registry");
|
|
52583
53065
|
WELL_KNOWN_SKILL_DIRS = [
|
|
52584
53066
|
join13(homedir7(), ".markus", "skills"),
|
|
52585
53067
|
join13(homedir7(), ".claude", "skills"),
|
|
@@ -52797,12 +53279,12 @@ function createDefaultTemplateRegistry() {
|
|
|
52797
53279
|
}
|
|
52798
53280
|
return registry;
|
|
52799
53281
|
}
|
|
52800
|
-
var
|
|
53282
|
+
var log40, TemplateRegistry;
|
|
52801
53283
|
var init_registry2 = __esm({
|
|
52802
53284
|
"../core/dist/templates/registry.js"() {
|
|
52803
53285
|
"use strict";
|
|
52804
53286
|
init_dist();
|
|
52805
|
-
|
|
53287
|
+
log40 = createLogger("template-registry");
|
|
52806
53288
|
TemplateRegistry = class {
|
|
52807
53289
|
templates = /* @__PURE__ */ new Map();
|
|
52808
53290
|
persistence;
|
|
@@ -52825,16 +53307,16 @@ var init_registry2 = __esm({
|
|
|
52825
53307
|
loaded++;
|
|
52826
53308
|
}
|
|
52827
53309
|
}
|
|
52828
|
-
|
|
53310
|
+
log40.info(`Synced ${loaded} templates from database`, { total: this.templates.size });
|
|
52829
53311
|
return loaded;
|
|
52830
53312
|
} catch (err) {
|
|
52831
|
-
|
|
53313
|
+
log40.warn("Failed to sync templates from database", { error: String(err) });
|
|
52832
53314
|
return 0;
|
|
52833
53315
|
}
|
|
52834
53316
|
}
|
|
52835
53317
|
register(template) {
|
|
52836
53318
|
this.templates.set(template.id, template);
|
|
52837
|
-
|
|
53319
|
+
log40.info(`Template registered: ${template.name} (${template.id})`, {
|
|
52838
53320
|
source: template.source,
|
|
52839
53321
|
category: template.category
|
|
52840
53322
|
});
|
|
@@ -52896,12 +53378,12 @@ var init_templates = __esm({
|
|
|
52896
53378
|
});
|
|
52897
53379
|
|
|
52898
53380
|
// ../core/dist/workflow/engine.js
|
|
52899
|
-
var
|
|
53381
|
+
var log41, WorkflowEngine;
|
|
52900
53382
|
var init_engine = __esm({
|
|
52901
53383
|
"../core/dist/workflow/engine.js"() {
|
|
52902
53384
|
"use strict";
|
|
52903
53385
|
init_dist();
|
|
52904
|
-
|
|
53386
|
+
log41 = createLogger("workflow-engine");
|
|
52905
53387
|
WorkflowEngine = class {
|
|
52906
53388
|
executor;
|
|
52907
53389
|
executions = /* @__PURE__ */ new Map();
|
|
@@ -52922,7 +53404,7 @@ var init_engine = __esm({
|
|
|
52922
53404
|
try {
|
|
52923
53405
|
handler4(event);
|
|
52924
53406
|
} catch (err) {
|
|
52925
|
-
|
|
53407
|
+
log41.warn("Event handler error", { error: String(err) });
|
|
52926
53408
|
}
|
|
52927
53409
|
}
|
|
52928
53410
|
}
|
|
@@ -53017,7 +53499,7 @@ var init_engine = __esm({
|
|
|
53017
53499
|
};
|
|
53018
53500
|
this.executions.set(executionId, execution);
|
|
53019
53501
|
this.emit({ type: "workflow_started", executionId, timestamp: /* @__PURE__ */ new Date() });
|
|
53020
|
-
|
|
53502
|
+
log41.info("Workflow started", { executionId, workflowId: def.id, stepCount: def.steps.length });
|
|
53021
53503
|
try {
|
|
53022
53504
|
await this.executeGraph(def, execution);
|
|
53023
53505
|
if (execution.status === "cancelled")
|
|
@@ -53030,13 +53512,13 @@ var init_engine = __esm({
|
|
|
53030
53512
|
execution.status = "completed";
|
|
53031
53513
|
execution.completedAt = /* @__PURE__ */ new Date();
|
|
53032
53514
|
this.emit({ type: "workflow_completed", executionId, timestamp: /* @__PURE__ */ new Date(), data: execution.outputs });
|
|
53033
|
-
|
|
53515
|
+
log41.info("Workflow completed", { executionId, elapsed: Date.now() - execution.startedAt.getTime() });
|
|
53034
53516
|
} catch (err) {
|
|
53035
53517
|
execution.status = "failed";
|
|
53036
53518
|
execution.error = String(err);
|
|
53037
53519
|
execution.completedAt = /* @__PURE__ */ new Date();
|
|
53038
53520
|
this.emit({ type: "workflow_failed", executionId, timestamp: /* @__PURE__ */ new Date(), data: { error: String(err) } });
|
|
53039
|
-
|
|
53521
|
+
log41.error("Workflow failed", { executionId, error: String(err) });
|
|
53040
53522
|
}
|
|
53041
53523
|
return execution;
|
|
53042
53524
|
}
|
|
@@ -53076,7 +53558,7 @@ var init_engine = __esm({
|
|
|
53076
53558
|
const promises = readySteps.map((stepId) => {
|
|
53077
53559
|
const stepDef = stepDefs.get(stepId);
|
|
53078
53560
|
return this.executeStep(stepDef, execution).catch((err) => {
|
|
53079
|
-
|
|
53561
|
+
log41.error("Step execution error", { stepId, error: String(err) });
|
|
53080
53562
|
});
|
|
53081
53563
|
});
|
|
53082
53564
|
await Promise.all(promises);
|
|
@@ -53167,7 +53649,7 @@ var init_engine = __esm({
|
|
|
53167
53649
|
timestamp: /* @__PURE__ */ new Date(),
|
|
53168
53650
|
data: { attempt: stepExec.retryCount, maxRetries }
|
|
53169
53651
|
});
|
|
53170
|
-
|
|
53652
|
+
log41.warn("Step retrying", { stepId: stepDef.id, attempt: stepExec.retryCount });
|
|
53171
53653
|
} else {
|
|
53172
53654
|
stepExec.status = "failed";
|
|
53173
53655
|
stepExec.error = String(err);
|
|
@@ -53355,7 +53837,7 @@ var init_engine = __esm({
|
|
|
53355
53837
|
const fn = new Function("steps", "inputs", `return !!(${expr})`);
|
|
53356
53838
|
return fn(steps, execution.inputs);
|
|
53357
53839
|
} catch {
|
|
53358
|
-
|
|
53840
|
+
log41.warn("Expression evaluation failed", { expr });
|
|
53359
53841
|
return false;
|
|
53360
53842
|
}
|
|
53361
53843
|
}
|
|
@@ -53420,7 +53902,7 @@ function loadTeamTemplateFromDir(dirPath) {
|
|
|
53420
53902
|
norms: existsSync19(normsPath) ? readFileSync16(normsPath, "utf-8") : void 0
|
|
53421
53903
|
};
|
|
53422
53904
|
} catch (err) {
|
|
53423
|
-
|
|
53905
|
+
log42.warn(`Failed to load team template from ${dirPath}`, { error: String(err) });
|
|
53424
53906
|
return null;
|
|
53425
53907
|
}
|
|
53426
53908
|
}
|
|
@@ -53443,7 +53925,7 @@ function createDefaultTeamTemplates() {
|
|
|
53443
53925
|
templatesDir = resolve11(process.cwd(), "templates", "teams");
|
|
53444
53926
|
}
|
|
53445
53927
|
if (!existsSync19(templatesDir)) {
|
|
53446
|
-
|
|
53928
|
+
log42.warn(`Team templates directory not found: ${templatesDir}`);
|
|
53447
53929
|
return registry;
|
|
53448
53930
|
}
|
|
53449
53931
|
const entries2 = readdirSync7(templatesDir, { withFileTypes: true });
|
|
@@ -53455,22 +53937,21 @@ function createDefaultTeamTemplates() {
|
|
|
53455
53937
|
registry.register(tpl);
|
|
53456
53938
|
}
|
|
53457
53939
|
}
|
|
53458
|
-
|
|
53940
|
+
log42.info(`Loaded ${registry.list().length} team templates from ${templatesDir}`);
|
|
53459
53941
|
return registry;
|
|
53460
53942
|
}
|
|
53461
|
-
var
|
|
53943
|
+
var log42, TeamTemplateRegistry;
|
|
53462
53944
|
var init_team_template = __esm({
|
|
53463
53945
|
"../core/dist/workflow/team-template.js"() {
|
|
53464
53946
|
"use strict";
|
|
53465
53947
|
init_dist();
|
|
53466
|
-
|
|
53948
|
+
log42 = createLogger("team-template");
|
|
53467
53949
|
TeamTemplateRegistry = class {
|
|
53468
53950
|
templates = /* @__PURE__ */ new Map();
|
|
53469
53951
|
register(template) {
|
|
53470
53952
|
this.templates.set(template.id, template);
|
|
53471
|
-
|
|
53472
|
-
members: template.members.length
|
|
53473
|
-
hasWorkflow: !!template.workflow
|
|
53953
|
+
log42.info(`Team template registered: ${template.name}`, {
|
|
53954
|
+
members: template.members.length
|
|
53474
53955
|
});
|
|
53475
53956
|
}
|
|
53476
53957
|
unregister(id) {
|
|
@@ -53508,13 +53989,13 @@ var init_types = __esm({
|
|
|
53508
53989
|
});
|
|
53509
53990
|
|
|
53510
53991
|
// ../core/dist/federation/federation-manager.js
|
|
53511
|
-
var
|
|
53992
|
+
var log43;
|
|
53512
53993
|
var init_federation_manager = __esm({
|
|
53513
53994
|
"../core/dist/federation/federation-manager.js"() {
|
|
53514
53995
|
"use strict";
|
|
53515
53996
|
init_dist();
|
|
53516
53997
|
init_types();
|
|
53517
|
-
|
|
53998
|
+
log43 = createLogger("federation");
|
|
53518
53999
|
}
|
|
53519
54000
|
});
|
|
53520
54001
|
|
|
@@ -53528,266 +54009,12 @@ var init_federation = __esm({
|
|
|
53528
54009
|
});
|
|
53529
54010
|
|
|
53530
54011
|
// ../core/dist/agent-snapshot.js
|
|
53531
|
-
var
|
|
54012
|
+
var log44;
|
|
53532
54013
|
var init_agent_snapshot = __esm({
|
|
53533
54014
|
"../core/dist/agent-snapshot.js"() {
|
|
53534
54015
|
"use strict";
|
|
53535
54016
|
init_dist();
|
|
53536
|
-
|
|
53537
|
-
}
|
|
53538
|
-
});
|
|
53539
|
-
|
|
53540
|
-
// ../core/dist/prompt-studio.js
|
|
53541
|
-
var log44, PromptStudio;
|
|
53542
|
-
var init_prompt_studio = __esm({
|
|
53543
|
-
"../core/dist/prompt-studio.js"() {
|
|
53544
|
-
"use strict";
|
|
53545
|
-
init_dist();
|
|
53546
|
-
log44 = createLogger("prompt-studio");
|
|
53547
|
-
PromptStudio = class {
|
|
53548
|
-
executor;
|
|
53549
|
-
prompts = /* @__PURE__ */ new Map();
|
|
53550
|
-
abTests = /* @__PURE__ */ new Map();
|
|
53551
|
-
evaluations = [];
|
|
53552
|
-
constructor(executor) {
|
|
53553
|
-
this.executor = executor;
|
|
53554
|
-
}
|
|
53555
|
-
setExecutor(executor) {
|
|
53556
|
-
this.executor = executor;
|
|
53557
|
-
}
|
|
53558
|
-
// ── Prompt Management ──────────────────────────────────────────────────
|
|
53559
|
-
createPrompt(opts) {
|
|
53560
|
-
const id = generateId("prompt");
|
|
53561
|
-
const version2 = {
|
|
53562
|
-
id: generateId("pv"),
|
|
53563
|
-
promptId: id,
|
|
53564
|
-
version: 1,
|
|
53565
|
-
content: opts.content,
|
|
53566
|
-
variables: this.extractVariables(opts.content),
|
|
53567
|
-
author: opts.author,
|
|
53568
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
53569
|
-
};
|
|
53570
|
-
const prompt = {
|
|
53571
|
-
id,
|
|
53572
|
-
name: opts.name,
|
|
53573
|
-
description: opts.description,
|
|
53574
|
-
category: opts.category,
|
|
53575
|
-
currentVersion: 1,
|
|
53576
|
-
versions: [version2],
|
|
53577
|
-
tags: opts.tags ?? [],
|
|
53578
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
53579
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
53580
|
-
};
|
|
53581
|
-
this.prompts.set(id, prompt);
|
|
53582
|
-
log44.info("Prompt created", { promptId: id, name: opts.name });
|
|
53583
|
-
return prompt;
|
|
53584
|
-
}
|
|
53585
|
-
updatePrompt(promptId, content, author, changelog) {
|
|
53586
|
-
const prompt = this.prompts.get(promptId);
|
|
53587
|
-
if (!prompt)
|
|
53588
|
-
throw new Error(`Prompt ${promptId} not found`);
|
|
53589
|
-
const newVersionNum = prompt.currentVersion + 1;
|
|
53590
|
-
const version2 = {
|
|
53591
|
-
id: generateId("pv"),
|
|
53592
|
-
promptId,
|
|
53593
|
-
version: newVersionNum,
|
|
53594
|
-
content,
|
|
53595
|
-
variables: this.extractVariables(content),
|
|
53596
|
-
author,
|
|
53597
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
53598
|
-
changelog
|
|
53599
|
-
};
|
|
53600
|
-
prompt.versions.push(version2);
|
|
53601
|
-
prompt.currentVersion = newVersionNum;
|
|
53602
|
-
prompt.updatedAt = /* @__PURE__ */ new Date();
|
|
53603
|
-
log44.info("Prompt updated", { promptId, version: newVersionNum });
|
|
53604
|
-
return version2;
|
|
53605
|
-
}
|
|
53606
|
-
getPrompt(promptId) {
|
|
53607
|
-
return this.prompts.get(promptId);
|
|
53608
|
-
}
|
|
53609
|
-
getVersion(promptId, version2) {
|
|
53610
|
-
const prompt = this.prompts.get(promptId);
|
|
53611
|
-
return prompt?.versions.find((v) => v.version === version2);
|
|
53612
|
-
}
|
|
53613
|
-
listPrompts(category) {
|
|
53614
|
-
const all = [...this.prompts.values()];
|
|
53615
|
-
if (!category)
|
|
53616
|
-
return all;
|
|
53617
|
-
return all.filter((p) => p.category === category);
|
|
53618
|
-
}
|
|
53619
|
-
searchPrompts(query2) {
|
|
53620
|
-
const lower = query2.toLowerCase();
|
|
53621
|
-
return [...this.prompts.values()].filter((p) => p.name.toLowerCase().includes(lower) || p.description.toLowerCase().includes(lower) || p.tags.some((t) => t.toLowerCase().includes(lower)));
|
|
53622
|
-
}
|
|
53623
|
-
deletePrompt(promptId) {
|
|
53624
|
-
return this.prompts.delete(promptId);
|
|
53625
|
-
}
|
|
53626
|
-
renderPrompt(promptId, variables, version2) {
|
|
53627
|
-
const prompt = this.prompts.get(promptId);
|
|
53628
|
-
if (!prompt)
|
|
53629
|
-
throw new Error(`Prompt ${promptId} not found`);
|
|
53630
|
-
const v = version2 ? prompt.versions.find((pv) => pv.version === version2) : prompt.versions.find((pv) => pv.version === prompt.currentVersion);
|
|
53631
|
-
if (!v)
|
|
53632
|
-
throw new Error(`Version ${version2 ?? prompt.currentVersion} not found`);
|
|
53633
|
-
return this.interpolatePrompt(v.content, variables);
|
|
53634
|
-
}
|
|
53635
|
-
// ── A/B Testing ────────────────────────────────────────────────────────
|
|
53636
|
-
createABTest(opts) {
|
|
53637
|
-
const prompt = this.prompts.get(opts.promptId);
|
|
53638
|
-
if (!prompt)
|
|
53639
|
-
throw new Error(`Prompt ${opts.promptId} not found`);
|
|
53640
|
-
const findVersion2 = (v) => prompt.versions.find((pv) => pv.version === v);
|
|
53641
|
-
if (!findVersion2(opts.variantA))
|
|
53642
|
-
throw new Error(`Variant A (v${opts.variantA}) not found`);
|
|
53643
|
-
if (!findVersion2(opts.variantB))
|
|
53644
|
-
throw new Error(`Variant B (v${opts.variantB}) not found`);
|
|
53645
|
-
const test = {
|
|
53646
|
-
id: generateId("ab-test"),
|
|
53647
|
-
name: opts.name,
|
|
53648
|
-
promptId: opts.promptId,
|
|
53649
|
-
variantA: opts.variantA,
|
|
53650
|
-
variantB: opts.variantB,
|
|
53651
|
-
splitRatio: opts.splitRatio ?? 0.5,
|
|
53652
|
-
status: "draft",
|
|
53653
|
-
metrics: {
|
|
53654
|
-
variantATrials: 0,
|
|
53655
|
-
variantBTrials: 0,
|
|
53656
|
-
variantAScores: [],
|
|
53657
|
-
variantBScores: []
|
|
53658
|
-
},
|
|
53659
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
53660
|
-
};
|
|
53661
|
-
this.abTests.set(test.id, test);
|
|
53662
|
-
log44.info("A/B test created", { testId: test.id, promptId: opts.promptId });
|
|
53663
|
-
return test;
|
|
53664
|
-
}
|
|
53665
|
-
startABTest(testId) {
|
|
53666
|
-
const test = this.abTests.get(testId);
|
|
53667
|
-
if (!test || test.status !== "draft")
|
|
53668
|
-
return false;
|
|
53669
|
-
test.status = "running";
|
|
53670
|
-
return true;
|
|
53671
|
-
}
|
|
53672
|
-
/** Pick which variant to use based on the split ratio */
|
|
53673
|
-
pickVariant(testId) {
|
|
53674
|
-
const test = this.abTests.get(testId);
|
|
53675
|
-
if (!test || test.status !== "running") {
|
|
53676
|
-
throw new Error(`A/B test ${testId} is not running`);
|
|
53677
|
-
}
|
|
53678
|
-
const isA = Math.random() < test.splitRatio;
|
|
53679
|
-
return isA ? { version: test.variantA, variant: "A" } : { version: test.variantB, variant: "B" };
|
|
53680
|
-
}
|
|
53681
|
-
recordABResult(testId, variant, score) {
|
|
53682
|
-
const test = this.abTests.get(testId);
|
|
53683
|
-
if (!test || test.status !== "running")
|
|
53684
|
-
return;
|
|
53685
|
-
if (variant === "A") {
|
|
53686
|
-
test.metrics.variantATrials++;
|
|
53687
|
-
test.metrics.variantAScores.push(score);
|
|
53688
|
-
} else {
|
|
53689
|
-
test.metrics.variantBTrials++;
|
|
53690
|
-
test.metrics.variantBScores.push(score);
|
|
53691
|
-
}
|
|
53692
|
-
}
|
|
53693
|
-
completeABTest(testId) {
|
|
53694
|
-
const test = this.abTests.get(testId);
|
|
53695
|
-
if (!test || test.status !== "running")
|
|
53696
|
-
return void 0;
|
|
53697
|
-
test.status = "completed";
|
|
53698
|
-
test.completedAt = /* @__PURE__ */ new Date();
|
|
53699
|
-
log44.info("A/B test completed", {
|
|
53700
|
-
testId,
|
|
53701
|
-
variantAAvg: this.average(test.metrics.variantAScores),
|
|
53702
|
-
variantBAvg: this.average(test.metrics.variantBScores)
|
|
53703
|
-
});
|
|
53704
|
-
return test;
|
|
53705
|
-
}
|
|
53706
|
-
getABTestResults(testId) {
|
|
53707
|
-
const test = this.abTests.get(testId);
|
|
53708
|
-
if (!test)
|
|
53709
|
-
return void 0;
|
|
53710
|
-
const avgA = this.average(test.metrics.variantAScores);
|
|
53711
|
-
const avgB = this.average(test.metrics.variantBScores);
|
|
53712
|
-
const diff = Math.abs(avgA - avgB);
|
|
53713
|
-
const totalTrials = test.metrics.variantATrials + test.metrics.variantBTrials;
|
|
53714
|
-
const confidence = totalTrials > 0 ? Math.min(1, totalTrials / 100 * (diff / Math.max(avgA, avgB, 0.01))) : 0;
|
|
53715
|
-
let winner = "tie";
|
|
53716
|
-
if (diff > 0.05)
|
|
53717
|
-
winner = avgA > avgB ? "A" : "B";
|
|
53718
|
-
return { test, variantAAvg: avgA, variantBAvg: avgB, winner, confidence };
|
|
53719
|
-
}
|
|
53720
|
-
listABTests(promptId) {
|
|
53721
|
-
const all = [...this.abTests.values()];
|
|
53722
|
-
if (!promptId)
|
|
53723
|
-
return all;
|
|
53724
|
-
return all.filter((t) => t.promptId === promptId);
|
|
53725
|
-
}
|
|
53726
|
-
// ── Evaluation ─────────────────────────────────────────────────────────
|
|
53727
|
-
async evaluate(promptId, version2, testInput, variables = {}, evaluator) {
|
|
53728
|
-
if (!this.executor)
|
|
53729
|
-
throw new Error("No prompt executor configured");
|
|
53730
|
-
const rendered = this.renderPrompt(promptId, variables, version2);
|
|
53731
|
-
const fullPrompt = `${rendered}
|
|
53732
|
-
|
|
53733
|
-
Input: ${testInput}`;
|
|
53734
|
-
const { output, latencyMs, tokenCount } = await this.executor.execute(fullPrompt, variables);
|
|
53735
|
-
const result = {
|
|
53736
|
-
id: generateId("eval"),
|
|
53737
|
-
promptId,
|
|
53738
|
-
version: version2,
|
|
53739
|
-
testInput,
|
|
53740
|
-
output,
|
|
53741
|
-
score: 0,
|
|
53742
|
-
latencyMs,
|
|
53743
|
-
tokenCount,
|
|
53744
|
-
evaluatedAt: /* @__PURE__ */ new Date(),
|
|
53745
|
-
evaluator
|
|
53746
|
-
};
|
|
53747
|
-
this.evaluations.push(result);
|
|
53748
|
-
return result;
|
|
53749
|
-
}
|
|
53750
|
-
scoreEvaluation(evaluationId, score, notes) {
|
|
53751
|
-
const ev = this.evaluations.find((e) => e.id === evaluationId);
|
|
53752
|
-
if (!ev)
|
|
53753
|
-
return false;
|
|
53754
|
-
ev.score = Math.max(0, Math.min(10, score));
|
|
53755
|
-
if (notes)
|
|
53756
|
-
ev.notes = notes;
|
|
53757
|
-
return true;
|
|
53758
|
-
}
|
|
53759
|
-
getEvaluations(promptId, version2) {
|
|
53760
|
-
return this.evaluations.filter((e) => e.promptId === promptId && (version2 === void 0 || e.version === version2));
|
|
53761
|
-
}
|
|
53762
|
-
getEvaluationSummary(promptId, version2) {
|
|
53763
|
-
const evals = this.getEvaluations(promptId, version2);
|
|
53764
|
-
if (evals.length === 0)
|
|
53765
|
-
return { avgScore: 0, avgLatencyMs: 0, avgTokenCount: 0, count: 0 };
|
|
53766
|
-
return {
|
|
53767
|
-
avgScore: this.average(evals.map((e) => e.score)),
|
|
53768
|
-
avgLatencyMs: this.average(evals.map((e) => e.latencyMs)),
|
|
53769
|
-
avgTokenCount: this.average(evals.map((e) => e.tokenCount)),
|
|
53770
|
-
count: evals.length
|
|
53771
|
-
};
|
|
53772
|
-
}
|
|
53773
|
-
// ── Helpers ────────────────────────────────────────────────────────────
|
|
53774
|
-
extractVariables(content) {
|
|
53775
|
-
const matches2 = content.match(/\{\{(\w+)\}\}/g);
|
|
53776
|
-
if (!matches2)
|
|
53777
|
-
return [];
|
|
53778
|
-
return [...new Set(matches2.map((m) => m.slice(2, -2)))];
|
|
53779
|
-
}
|
|
53780
|
-
interpolatePrompt(content, variables) {
|
|
53781
|
-
return content.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
|
|
53782
|
-
return variables[name] ?? `{{${name}}}`;
|
|
53783
|
-
});
|
|
53784
|
-
}
|
|
53785
|
-
average(arr) {
|
|
53786
|
-
if (arr.length === 0)
|
|
53787
|
-
return 0;
|
|
53788
|
-
return Math.round(arr.reduce((s, v) => s + v, 0) / arr.length * 100) / 100;
|
|
53789
|
-
}
|
|
53790
|
-
};
|
|
54017
|
+
log44 = createLogger("agent-snapshot");
|
|
53791
54018
|
}
|
|
53792
54019
|
});
|
|
53793
54020
|
|
|
@@ -53835,7 +54062,6 @@ var init_dist4 = __esm({
|
|
|
53835
54062
|
init_workflow();
|
|
53836
54063
|
init_federation();
|
|
53837
54064
|
init_agent_snapshot();
|
|
53838
|
-
init_prompt_studio();
|
|
53839
54065
|
}
|
|
53840
54066
|
});
|
|
53841
54067
|
|
|
@@ -54422,7 +54648,13 @@ var init_org_service = __esm({
|
|
|
54422
54648
|
if (!org)
|
|
54423
54649
|
return;
|
|
54424
54650
|
const humans = this.listHumanUsers(targetOrgId);
|
|
54425
|
-
this.
|
|
54651
|
+
const teams2 = this.listTeams(targetOrgId).map((t) => ({
|
|
54652
|
+
id: t.id,
|
|
54653
|
+
name: t.name,
|
|
54654
|
+
description: t.description,
|
|
54655
|
+
memberAgentIds: t.memberAgentIds
|
|
54656
|
+
}));
|
|
54657
|
+
this.agentManager.refreshIdentityContexts(targetOrgId, org.name, humans, teams2);
|
|
54426
54658
|
}
|
|
54427
54659
|
listAvailableRoles() {
|
|
54428
54660
|
return this.roleLoader.listAvailableRoles();
|
|
@@ -54712,7 +54944,29 @@ var init_org_service = __esm({
|
|
|
54712
54944
|
for (const r of roleNames) {
|
|
54713
54945
|
parts.push(`- \`${r}\``);
|
|
54714
54946
|
}
|
|
54947
|
+
const templateDirs = this.roleLoader.getTemplateDirs();
|
|
54948
|
+
if (templateDirs.length > 0) {
|
|
54949
|
+
parts.push("");
|
|
54950
|
+
parts.push("**Tip**: You can read existing role templates for reference when writing custom ROLE.md files.");
|
|
54951
|
+
parts.push(`Use \`file_read\` to inspect any template, e.g.: \`file_read("${templateDirs[0]}/developer/ROLE.md")\``);
|
|
54952
|
+
parts.push("This is especially useful for understanding the level of detail and workflow guidance expected in a good ROLE.md.");
|
|
54953
|
+
}
|
|
54715
54954
|
}
|
|
54955
|
+
parts.push("");
|
|
54956
|
+
parts.push("## Platform Capabilities (reference when writing ROLE.md)");
|
|
54957
|
+
parts.push("");
|
|
54958
|
+
parts.push("When writing custom ROLE.md for agents, reference these platform capabilities where relevant:");
|
|
54959
|
+
parts.push("");
|
|
54960
|
+
parts.push("- **`spawn_subagent`** \u2014 Spawn lightweight in-process subagents for focused subtasks (deep analysis, research, boilerplate generation) without polluting the parent agent's context");
|
|
54961
|
+
parts.push("- **`background_exec`** \u2014 Run long-running commands (builds, test suites, deployments) in background with automatic completion notifications");
|
|
54962
|
+
parts.push("- **`shell_execute`** \u2014 Execute any shell command, including `git` (merge, diff, branch) and `gh` CLI (PRs, issues, releases) for Git/GitHub operations");
|
|
54963
|
+
parts.push("- **Worktree isolation** \u2014 Each task gets an isolated git worktree (`task/<id>` branch). Developers work in isolation; the reviewer merges after approval.");
|
|
54964
|
+
parts.push("- **`web_search` / `web_fetch`** \u2014 Search the web and fetch page content for research, documentation lookup, and real-time information");
|
|
54965
|
+
parts.push("- **Task dependencies** \u2014 Use `blockedBy` to express dependencies between tasks. Blocked tasks auto-start when dependencies complete.");
|
|
54966
|
+
parts.push("- **Deliverables** \u2014 Use `deliverable_create` to register outputs (files, conventions, architecture decisions) as trackable artifacts");
|
|
54967
|
+
parts.push("- **Memory** \u2014 Use `memory_save` / `memory_search` for persistent knowledge across sessions");
|
|
54968
|
+
parts.push("");
|
|
54969
|
+
parts.push("Include workflow guidance in ROLE.md that tells the agent *when* and *how* to use these capabilities for their specific role.");
|
|
54716
54970
|
return parts.join("\n");
|
|
54717
54971
|
}
|
|
54718
54972
|
};
|
|
@@ -56587,10 +56841,25 @@ ${c.content}`;
|
|
|
56587
56841
|
parts.push(`> ${note}`);
|
|
56588
56842
|
}
|
|
56589
56843
|
}
|
|
56844
|
+
if (task.projectId && this.projectService) {
|
|
56845
|
+
const project = this.projectService.getProject(task.projectId);
|
|
56846
|
+
const repo = project?.repositories?.find((r) => r.role === "primary" && r.localPath) ?? project?.repositories?.find((r) => r.localPath);
|
|
56847
|
+
if (repo?.localPath) {
|
|
56848
|
+
const branchName = `task/${task.id}`;
|
|
56849
|
+
const worktreePath = `${repo.localPath}/.worktrees/task-${task.id}`;
|
|
56850
|
+
parts.push("");
|
|
56851
|
+
parts.push("**Git Context:**");
|
|
56852
|
+
parts.push(`- Repository: \`${repo.localPath}\``);
|
|
56853
|
+
parts.push(`- Task branch: \`${branchName}\``);
|
|
56854
|
+
parts.push(`- Base branch: \`${repo.defaultBranch}\``);
|
|
56855
|
+
parts.push(`- Worktree: \`${worktreePath}\``);
|
|
56856
|
+
parts.push(`- To see changes: \`cd ${repo.localPath} && git diff ${repo.defaultBranch}...${branchName}\``);
|
|
56857
|
+
}
|
|
56858
|
+
}
|
|
56590
56859
|
parts.push("");
|
|
56591
56860
|
parts.push(`Please review immediately. Use \`task_get\` with task_id "${task.id}" to inspect deliverable files, then either:`);
|
|
56592
|
-
parts.push(`-
|
|
56593
|
-
parts.push(`-
|
|
56861
|
+
parts.push(`- **Approve**: Review the code, merge the branch (via \`git merge\` or \`gh pr create\` + \`gh pr merge\`), then \`task_update\` with status "completed"`);
|
|
56862
|
+
parts.push(`- **Reject**: If the code has issues or merge conflicts, add a \`task_note\` explaining what needs to change, then \`task_update\` with status "in_progress" to send it back`);
|
|
56594
56863
|
parts.push("");
|
|
56595
56864
|
parts.push(`CRITICAL: You MUST ONLY review this specific task (ID: ${task.id}). Do NOT change the status of any other task.`);
|
|
56596
56865
|
const reviewMessage = parts.join("\n");
|
|
@@ -58444,7 +58713,6 @@ var init_api_server = __esm({
|
|
|
58444
58713
|
templateRegistry;
|
|
58445
58714
|
workflowEngine;
|
|
58446
58715
|
teamTemplateRegistry;
|
|
58447
|
-
promptStudio;
|
|
58448
58716
|
customGroupChats = [];
|
|
58449
58717
|
constructor(orgService, taskService, port = 8056) {
|
|
58450
58718
|
this.orgService = orgService;
|
|
@@ -58453,7 +58721,6 @@ var init_api_server = __esm({
|
|
|
58453
58721
|
this.ws = new WSBroadcaster();
|
|
58454
58722
|
this.teamTemplateRegistry = createDefaultTeamTemplates();
|
|
58455
58723
|
this.templateRegistry = createDefaultTemplateRegistry();
|
|
58456
|
-
this.promptStudio = new PromptStudio();
|
|
58457
58724
|
const am = this.orgService.getAgentManager();
|
|
58458
58725
|
if (this.templateRegistry && !am.getTemplateRegistry()) {
|
|
58459
58726
|
am.setTemplateRegistry(this.templateRegistry);
|
|
@@ -62691,6 +62958,37 @@ var init_api_server = __esm({
|
|
|
62691
62958
|
}
|
|
62692
62959
|
return;
|
|
62693
62960
|
}
|
|
62961
|
+
if (path === "/api/settings/agent" && req.method === "GET") {
|
|
62962
|
+
const am = this.orgService.getAgentManager();
|
|
62963
|
+
this.json(res, 200, { maxToolIterations: am.maxToolIterations });
|
|
62964
|
+
return;
|
|
62965
|
+
}
|
|
62966
|
+
if (path === "/api/settings/agent" && req.method === "POST") {
|
|
62967
|
+
const auth = await this.requireAuth(req, res);
|
|
62968
|
+
if (!auth)
|
|
62969
|
+
return;
|
|
62970
|
+
const body = await this.readBody(req);
|
|
62971
|
+
const am = this.orgService.getAgentManager();
|
|
62972
|
+
let changed = false;
|
|
62973
|
+
if (typeof body["maxToolIterations"] === "number") {
|
|
62974
|
+
am.maxToolIterations = body["maxToolIterations"];
|
|
62975
|
+
changed = true;
|
|
62976
|
+
}
|
|
62977
|
+
if (changed) {
|
|
62978
|
+
try {
|
|
62979
|
+
saveConfig({ agent: { maxToolIterations: am.maxToolIterations } }, this.markusConfigPath);
|
|
62980
|
+
} catch (e) {
|
|
62981
|
+
log51.warn("Failed to persist agent settings to config file", { error: String(e) });
|
|
62982
|
+
}
|
|
62983
|
+
for (const info of am.listAgents()) {
|
|
62984
|
+
const agent = am.getAgent(info.id);
|
|
62985
|
+
if (agent)
|
|
62986
|
+
agent.maxToolIterations = am.maxToolIterations;
|
|
62987
|
+
}
|
|
62988
|
+
}
|
|
62989
|
+
this.json(res, 200, { maxToolIterations: am.maxToolIterations });
|
|
62990
|
+
return;
|
|
62991
|
+
}
|
|
62694
62992
|
if (path === "/api/settings/llm/models" && req.method === "GET") {
|
|
62695
62993
|
if (!this.llmRouter) {
|
|
62696
62994
|
this.json(res, 200, { models: [] });
|
|
@@ -63258,207 +63556,6 @@ var init_api_server = __esm({
|
|
|
63258
63556
|
this.json(res, 200, { deleted: true });
|
|
63259
63557
|
return;
|
|
63260
63558
|
}
|
|
63261
|
-
if (path === "/api/prompts" && req.method === "GET") {
|
|
63262
|
-
const category = url.searchParams.get("category") ?? void 0;
|
|
63263
|
-
const q = url.searchParams.get("q");
|
|
63264
|
-
const prompts = q ? this.promptStudio.searchPrompts(q) : this.promptStudio.listPrompts(category);
|
|
63265
|
-
this.json(res, 200, { prompts });
|
|
63266
|
-
return;
|
|
63267
|
-
}
|
|
63268
|
-
if (path === "/api/prompts" && req.method === "POST") {
|
|
63269
|
-
const auth = await this.requireAuth(req, res);
|
|
63270
|
-
if (!auth)
|
|
63271
|
-
return;
|
|
63272
|
-
const body = await this.readBody(req);
|
|
63273
|
-
const { name, description, category, content, tags } = body;
|
|
63274
|
-
if (!name || !content) {
|
|
63275
|
-
this.json(res, 400, { error: "name and content are required" });
|
|
63276
|
-
return;
|
|
63277
|
-
}
|
|
63278
|
-
const prompt = this.promptStudio.createPrompt({
|
|
63279
|
-
name,
|
|
63280
|
-
description: description ?? "",
|
|
63281
|
-
category: category ?? "general",
|
|
63282
|
-
content,
|
|
63283
|
-
author: auth.userId ?? "user",
|
|
63284
|
-
tags
|
|
63285
|
-
});
|
|
63286
|
-
this.json(res, 201, { prompt });
|
|
63287
|
-
return;
|
|
63288
|
-
}
|
|
63289
|
-
if (path.match(/^\/api\/prompts\/[^/]+$/) && req.method === "GET") {
|
|
63290
|
-
const promptId = path.split("/")[3];
|
|
63291
|
-
const prompt = this.promptStudio.getPrompt(promptId);
|
|
63292
|
-
if (!prompt) {
|
|
63293
|
-
this.json(res, 404, { error: "Prompt not found" });
|
|
63294
|
-
return;
|
|
63295
|
-
}
|
|
63296
|
-
this.json(res, 200, { prompt });
|
|
63297
|
-
return;
|
|
63298
|
-
}
|
|
63299
|
-
if (path.match(/^\/api\/prompts\/[^/]+$/) && req.method === "DELETE") {
|
|
63300
|
-
const promptId = path.split("/")[3];
|
|
63301
|
-
this.promptStudio.deletePrompt(promptId);
|
|
63302
|
-
this.json(res, 200, { deleted: true });
|
|
63303
|
-
return;
|
|
63304
|
-
}
|
|
63305
|
-
if (path.match(/^\/api\/prompts\/[^/]+\/versions$/) && req.method === "POST") {
|
|
63306
|
-
const auth = await this.requireAuth(req, res);
|
|
63307
|
-
if (!auth)
|
|
63308
|
-
return;
|
|
63309
|
-
const promptId = path.split("/")[3];
|
|
63310
|
-
const body = await this.readBody(req);
|
|
63311
|
-
const { content, changelog } = body;
|
|
63312
|
-
if (!content) {
|
|
63313
|
-
this.json(res, 400, { error: "content is required" });
|
|
63314
|
-
return;
|
|
63315
|
-
}
|
|
63316
|
-
try {
|
|
63317
|
-
const version2 = this.promptStudio.updatePrompt(promptId, content, auth.userId ?? "user", changelog);
|
|
63318
|
-
this.json(res, 201, { version: version2 });
|
|
63319
|
-
} catch (err) {
|
|
63320
|
-
this.json(res, 404, { error: String(err) });
|
|
63321
|
-
}
|
|
63322
|
-
return;
|
|
63323
|
-
}
|
|
63324
|
-
if (path.match(/^\/api\/prompts\/[^/]+\/render$/) && req.method === "POST") {
|
|
63325
|
-
const promptId = path.split("/")[3];
|
|
63326
|
-
const body = await this.readBody(req);
|
|
63327
|
-
const { variables, version: version2 } = body;
|
|
63328
|
-
try {
|
|
63329
|
-
const rendered = this.promptStudio.renderPrompt(promptId, variables ?? {}, version2);
|
|
63330
|
-
this.json(res, 200, { rendered });
|
|
63331
|
-
} catch (err) {
|
|
63332
|
-
this.json(res, 400, { error: String(err) });
|
|
63333
|
-
}
|
|
63334
|
-
return;
|
|
63335
|
-
}
|
|
63336
|
-
if (path === "/api/prompts/ab-tests" && req.method === "GET") {
|
|
63337
|
-
const promptId = url.searchParams.get("promptId") ?? void 0;
|
|
63338
|
-
const tests = this.promptStudio.listABTests(promptId);
|
|
63339
|
-
this.json(res, 200, { tests });
|
|
63340
|
-
return;
|
|
63341
|
-
}
|
|
63342
|
-
if (path === "/api/prompts/ab-tests" && req.method === "POST") {
|
|
63343
|
-
const auth = await this.requireAuth(req, res);
|
|
63344
|
-
if (!auth)
|
|
63345
|
-
return;
|
|
63346
|
-
const body = await this.readBody(req);
|
|
63347
|
-
const { name, promptId, variantA, variantB, splitRatio } = body;
|
|
63348
|
-
try {
|
|
63349
|
-
const test = this.promptStudio.createABTest({
|
|
63350
|
-
name,
|
|
63351
|
-
promptId,
|
|
63352
|
-
variantA,
|
|
63353
|
-
variantB,
|
|
63354
|
-
splitRatio
|
|
63355
|
-
});
|
|
63356
|
-
this.json(res, 201, { test });
|
|
63357
|
-
} catch (err) {
|
|
63358
|
-
this.json(res, 400, { error: String(err) });
|
|
63359
|
-
}
|
|
63360
|
-
return;
|
|
63361
|
-
}
|
|
63362
|
-
if (path.match(/^\/api\/prompts\/ab-tests\/[^/]+\/start$/) && req.method === "POST") {
|
|
63363
|
-
const testId = path.split("/")[4];
|
|
63364
|
-
const started = this.promptStudio.startABTest(testId);
|
|
63365
|
-
this.json(res, 200, { started });
|
|
63366
|
-
return;
|
|
63367
|
-
}
|
|
63368
|
-
if (path.match(/^\/api\/prompts\/ab-tests\/[^/]+\/complete$/) && req.method === "POST") {
|
|
63369
|
-
const testId = path.split("/")[4];
|
|
63370
|
-
const result = this.promptStudio.completeABTest(testId);
|
|
63371
|
-
if (!result) {
|
|
63372
|
-
this.json(res, 404, { error: "Test not found or not running" });
|
|
63373
|
-
return;
|
|
63374
|
-
}
|
|
63375
|
-
this.json(res, 200, { test: result });
|
|
63376
|
-
return;
|
|
63377
|
-
}
|
|
63378
|
-
if (path.match(/^\/api\/prompts\/ab-tests\/[^/]+\/record$/) && req.method === "POST") {
|
|
63379
|
-
const testId = path.split("/")[4];
|
|
63380
|
-
const body = await this.readBody(req);
|
|
63381
|
-
const { variant, score } = body;
|
|
63382
|
-
this.promptStudio.recordABResult(testId, variant, score);
|
|
63383
|
-
this.json(res, 200, { ok: true });
|
|
63384
|
-
return;
|
|
63385
|
-
}
|
|
63386
|
-
if (path.match(/^\/api\/prompts\/ab-tests\/[^/]+\/results$/) && req.method === "GET") {
|
|
63387
|
-
const testId = path.split("/")[4];
|
|
63388
|
-
const results = this.promptStudio.getABTestResults(testId);
|
|
63389
|
-
if (!results) {
|
|
63390
|
-
this.json(res, 404, { error: "Test not found" });
|
|
63391
|
-
return;
|
|
63392
|
-
}
|
|
63393
|
-
this.json(res, 200, results);
|
|
63394
|
-
return;
|
|
63395
|
-
}
|
|
63396
|
-
if (path.match(/^\/api\/prompts\/[^/]+\/evaluations$/) && req.method === "GET") {
|
|
63397
|
-
const promptId = path.split("/")[3];
|
|
63398
|
-
const version2 = url.searchParams.get("version") ? parseInt(url.searchParams.get("version"), 10) : void 0;
|
|
63399
|
-
const evaluations = this.promptStudio.getEvaluations(promptId, version2);
|
|
63400
|
-
this.json(res, 200, { evaluations });
|
|
63401
|
-
return;
|
|
63402
|
-
}
|
|
63403
|
-
if (path.match(/^\/api\/prompts\/[^/]+\/evaluate$/) && req.method === "POST") {
|
|
63404
|
-
const auth = await this.requireAuth(req, res);
|
|
63405
|
-
if (!auth)
|
|
63406
|
-
return;
|
|
63407
|
-
const promptId = path.split("/")[3];
|
|
63408
|
-
const body = await this.readBody(req);
|
|
63409
|
-
const { version: version2, testInput, variables } = body;
|
|
63410
|
-
if (!testInput || version2 === void 0) {
|
|
63411
|
-
this.json(res, 400, { error: "version and testInput are required" });
|
|
63412
|
-
return;
|
|
63413
|
-
}
|
|
63414
|
-
if (this.llmRouter && !this.promptStudio["executor"]) {
|
|
63415
|
-
this.promptStudio.setExecutor({
|
|
63416
|
-
execute: async (prompt) => {
|
|
63417
|
-
const startMs = Date.now();
|
|
63418
|
-
const response = await this.llmRouter.chat({
|
|
63419
|
-
messages: [
|
|
63420
|
-
{
|
|
63421
|
-
role: "system",
|
|
63422
|
-
content: "You are a helpful assistant. Respond to the prompt accurately and concisely."
|
|
63423
|
-
},
|
|
63424
|
-
{ role: "user", content: prompt }
|
|
63425
|
-
]
|
|
63426
|
-
});
|
|
63427
|
-
return {
|
|
63428
|
-
output: response.content,
|
|
63429
|
-
latencyMs: Date.now() - startMs,
|
|
63430
|
-
tokenCount: (response.usage?.inputTokens ?? 0) + (response.usage?.outputTokens ?? 0)
|
|
63431
|
-
};
|
|
63432
|
-
}
|
|
63433
|
-
});
|
|
63434
|
-
}
|
|
63435
|
-
try {
|
|
63436
|
-
const result = await this.promptStudio.evaluate(promptId, version2, testInput, variables ?? {}, auth.userId ?? "user");
|
|
63437
|
-
this.json(res, 200, { evaluation: result });
|
|
63438
|
-
} catch (err) {
|
|
63439
|
-
this.json(res, 400, { error: String(err) });
|
|
63440
|
-
}
|
|
63441
|
-
return;
|
|
63442
|
-
}
|
|
63443
|
-
if (path.match(/^\/api\/prompts\/evaluations\/[^/]+\/score$/) && req.method === "POST") {
|
|
63444
|
-
const evaluationId = path.split("/")[4];
|
|
63445
|
-
const body = await this.readBody(req);
|
|
63446
|
-
const { score, notes } = body;
|
|
63447
|
-
const updated = this.promptStudio.scoreEvaluation(evaluationId, score, notes);
|
|
63448
|
-
this.json(res, 200, { updated });
|
|
63449
|
-
return;
|
|
63450
|
-
}
|
|
63451
|
-
if (path.match(/^\/api\/prompts\/[^/]+\/evaluation-summary$/) && req.method === "GET") {
|
|
63452
|
-
const promptId = path.split("/")[3];
|
|
63453
|
-
const version2 = url.searchParams.get("version") ? parseInt(url.searchParams.get("version"), 10) : void 0;
|
|
63454
|
-
if (version2 === void 0) {
|
|
63455
|
-
this.json(res, 400, { error: "version query param is required" });
|
|
63456
|
-
return;
|
|
63457
|
-
}
|
|
63458
|
-
const summary = this.promptStudio.getEvaluationSummary(promptId, version2);
|
|
63459
|
-
this.json(res, 200, { summary });
|
|
63460
|
-
return;
|
|
63461
|
-
}
|
|
63462
63559
|
if (path === "/api/system/open-path" && req.method === "POST") {
|
|
63463
63560
|
try {
|
|
63464
63561
|
const body = await this.readBody(req);
|
|
@@ -79362,6 +79459,9 @@ async function createServices(config) {
|
|
|
79362
79459
|
taskService,
|
|
79363
79460
|
mcpServers: config.mcpServers
|
|
79364
79461
|
});
|
|
79462
|
+
if (config.agent?.maxToolIterations) {
|
|
79463
|
+
agentManager.maxToolIterations = config.agent.maxToolIterations;
|
|
79464
|
+
}
|
|
79365
79465
|
taskService.setAgentManager(agentManager);
|
|
79366
79466
|
const orgService = new OrganizationService(agentManager, roleLoader, storage ?? void 0);
|
|
79367
79467
|
taskService.setOrgService(orgService);
|