@markus-global/cli 0.6.4 → 0.6.5
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.d.ts.map +1 -1
- package/dist/commands/start.js +21 -10
- package/dist/commands/start.js.map +1 -1
- package/dist/markus.mjs +920 -304
- package/dist/web-ui/assets/index-DcnwpDqb.css +1 -0
- package/dist/web-ui/assets/index-tONQYLWM.js +351 -0
- package/dist/web-ui/index.html +2 -2
- package/dist/web-ui/logo.png +0 -0
- package/package.json +1 -1
- package/templates/roles/secretary/HEARTBEAT.md +1 -1
- package/templates/roles/secretary/ROLE.md +80 -4
- package/templates/skills/agent-building/SKILL.md +1 -1
- package/templates/skills/chrome-devtools/SKILL.md +56 -0
- package/templates/skills/image-generation/SKILL.md +183 -0
- package/templates/skills/image-generation/server.mjs +1269 -0
- package/templates/skills/image-generation/skill.json +26 -0
- package/templates/skills/markus-admin-cli/SKILL.md +1 -1
- package/templates/skills/self-evolution/SKILL.md +4 -4
- package/templates/skills/skill-building/SKILL.md +1 -1
- package/templates/skills/team-building/SKILL.md +1 -1
- package/templates/teams/content-team/ANNOUNCEMENT.md +28 -24
- package/templates/teams/content-team/NORMS.md +50 -48
- package/templates/teams/content-team/team.json +46 -16
- package/templates/teams/research-lab/ANNOUNCEMENT.md +24 -19
- package/templates/teams/research-lab/NORMS.md +77 -88
- package/templates/teams/research-lab/team.json +40 -14
- package/dist/web-ui/assets/index-5QUyR8je.js +0 -351
- package/dist/web-ui/assets/index-B9eoccwC.css +0 -1
package/dist/markus.mjs
CHANGED
|
@@ -6381,20 +6381,80 @@ var init_context_engine = __esm({
|
|
|
6381
6381
|
this.llmSummarizer = summarizer;
|
|
6382
6382
|
}
|
|
6383
6383
|
async buildSystemPrompt(opts) {
|
|
6384
|
-
const
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6384
|
+
const isDream = opts.scenario === "memory_consolidation";
|
|
6385
|
+
const stable = [];
|
|
6386
|
+
stable.push(opts.role.systemPrompt);
|
|
6387
|
+
if (opts.role.defaultPolicies.length > 0) {
|
|
6388
|
+
stable.push("\n## Policies");
|
|
6389
|
+
for (const policy of opts.role.defaultPolicies) {
|
|
6390
|
+
stable.push(`### ${policy.name}`);
|
|
6391
|
+
for (const rule of policy.rules) {
|
|
6392
|
+
stable.push(`- ${rule}`);
|
|
6393
|
+
}
|
|
6394
|
+
}
|
|
6388
6395
|
}
|
|
6389
|
-
|
|
6396
|
+
if (!isDream) {
|
|
6397
|
+
stable.push("\n## Tool Usage Rules");
|
|
6398
|
+
stable.push("**File editing discipline**: You MUST use `file_write` and `file_edit` for all file creation and modification. NEVER use `shell_execute` with `cat`, `echo`, `printf`, `tee`, pipes (`|`), output redirection (`>`, `>>`), heredocs (`<<`), or `sed`/`awk` to write or modify files \u2014 these bypass file access controls. `shell_execute` is for running commands (build, test, git, etc.), not for writing files.");
|
|
6399
|
+
stable.push("**Large file writing**: NEVER write a document >200 lines in a single `file_write` call. Write section by section: `file_write` the first section, then `file_edit` to append each subsequent section.");
|
|
6400
|
+
stable.push("**Error handling**: If a tool call fails, analyze the error and try a different approach \u2014 do NOT repeat the same failing action.");
|
|
6401
|
+
stable.push("**Subagent delegation**: For heavy subtasks needing many tool calls or lots of file reading, delegate to `spawn_subagent` to keep your context lean. Use `spawn_subagents` to run independent subtasks in parallel.");
|
|
6402
|
+
stable.push("**Built-in tools over CLI**: ALWAYS prefer built-in tools (`task_create`, `task_assign`, `team_hire_agent`, `builder_install`, `agent_send_message`, `memory_save`, etc.) over running `markus` CLI commands via `shell_execute`. The CLI is for human operators \u2014 agents must use their native tool interface. Only fall back to CLI if no built-in tool exists for the operation.");
|
|
6403
|
+
stable.push('**No auto-install/deploy**: NEVER automatically install or deploy agents, teams, or skills via `builder_install`, `team_hire_agent`, or `hub_install` unless explicitly requested by a human team member (e.g., "install", "deploy", "hire", "start"). Creating an artifact (writing files to `builder-artifacts/`) is separate from deploying it into the live organization.');
|
|
6404
|
+
stable.push("");
|
|
6405
|
+
stable.push("\n## Task & Requirement Workflow");
|
|
6406
|
+
stable.push("");
|
|
6407
|
+
stable.push("**Requirements** (governance gate):");
|
|
6408
|
+
stable.push("- `requirement_propose` \u2192 pending human approval \u2192 approved \u2192 link tasks via `requirement_id`");
|
|
6409
|
+
stable.push("- Every task MUST reference an approved `requirement_id`. Use `requirement_propose` first if no requirement exists.");
|
|
6410
|
+
stable.push("");
|
|
6411
|
+
stable.push("**Task lifecycle** \u2014 Create \u2192 Execute \u2192 Review \u2192 Complete:");
|
|
6412
|
+
stable.push('- **Create**: `task_create` (REQUIRED: `assigned_agent_id`, `reviewer_id`; optional `reviewer_type`: "agent"|"human"). Check `task_list` first to avoid duplicates.');
|
|
6413
|
+
stable.push("- **Execute**: Decompose with `subtask_create` \u2192 work through subtasks \u2192 `task_submit_review` with summary + deliverables (MANDATORY). System auto-fills `task_id` and `reviewer`.");
|
|
6414
|
+
stable.push('- **Review**: Reviewer approves with `task_update(status:"completed")` or rejects with `task_update(status:"in_progress", note:"what needs to change")` (auto-restarts execution). Workers MUST NOT set status=completed on their own tasks.');
|
|
6415
|
+
stable.push('- **Blockers**: Use `task_update(status:"blocked", note:"reason")` when unable to proceed.');
|
|
6416
|
+
stable.push("");
|
|
6417
|
+
stable.push("**Dependencies & DAG decomposition**:");
|
|
6418
|
+
stable.push("- **CRITICAL**: Use `blocked_by` to express ALL dependency relationships. If task B needs output from task A, B **MUST** include A's ID in `blocked_by`. Without this, tasks run in parallel and downstream tasks lack upstream deliverables.");
|
|
6419
|
+
stable.push("- For complex goals, create a DAG of tasks. Assign each to the best team member (`team_list`). Independent tasks run in parallel; dependent tasks wait for predecessors.");
|
|
6420
|
+
stable.push("- If consolidated output is needed, create a final synthesis task assigned to a manager, `blocked_by` ALL prerequisites.");
|
|
6421
|
+
stable.push("");
|
|
6422
|
+
stable.push("**Work discovery**: `list_projects` \u2192 `requirement_list` \u2192 `task_list`. Use `memory_save`/`memory_search` for personal notes; `deliverable_create`/`deliverable_search` for shared outputs.");
|
|
6423
|
+
stable.push("");
|
|
6424
|
+
stable.push("**Automatic status notifications** (do NOT duplicate manually):");
|
|
6425
|
+
stable.push("- When task status changes, the system **automatically** handles all side effects: execution start/cancel, reviewer notification, dependency unblocking.");
|
|
6426
|
+
stable.push("- Task status notifications are placed in assignees' mailboxes as **informational context only**.");
|
|
6427
|
+
stable.push("- Do NOT send A2A messages to notify about task status changes \u2014 only send A2A when you have substantive coordination needs beyond the status change itself.");
|
|
6428
|
+
stable.push("");
|
|
6429
|
+
stable.push("**Communicating with humans**:");
|
|
6430
|
+
stable.push("- `notify_user` \u2014 proactive message to a human team member: status updates, progress reports, findings, alerts. Appears in chat timeline AND notification bell. The human can reply. Write comprehensive body with full context. **This is the ONLY way to reach humans from non-chat contexts** (heartbeat, autonomous tasks, etc.).");
|
|
6431
|
+
stable.push("- `request_user_approval` \u2014 when you need a human decision, approval, or input. BLOCKS until the user responds. Supports custom options and freeform text. Do NOT use for routine updates.");
|
|
6432
|
+
stable.push("- `recall_activity` \u2014 query your own past execution logs by task or activity type. Use when you need to review what you did previously (e.g., to answer a follow-up question).");
|
|
6433
|
+
stable.push("");
|
|
6434
|
+
stable.push("**Communicating with other agents**:");
|
|
6435
|
+
stable.push("- `agent_send_message` \u2014 send a direct message to a peer agent. **By default this is asynchronous (fire-and-forget)**: the message enters their mailbox and you continue working without waiting. Set `wait_for_reply: true` only when you need the answer before you can proceed (rare \u2014 prefer async).");
|
|
6436
|
+
stable.push("- A2A messaging is inherently **non-blocking**. You send a message, the recipient processes it on their own schedule, and may reply later via their own `agent_send_message`. Do NOT spin-wait or poll for responses.");
|
|
6437
|
+
stable.push("- For substantial work requests, create a `task_create` assigned to the target agent instead of asking via message.");
|
|
6438
|
+
stable.push("- Do NOT use A2A messages for routine task status notifications \u2014 the system handles those automatically.");
|
|
6439
|
+
}
|
|
6440
|
+
const scenario = opts.scenario ?? "chat";
|
|
6441
|
+
stable.push(this.buildScenarioSection(scenario, { a2aWaitForReply: opts.a2aWaitForReply }));
|
|
6442
|
+
const semiStable = [];
|
|
6443
|
+
semiStable.push(this.buildIdentitySection({
|
|
6444
|
+
agentId: opts.agentId,
|
|
6445
|
+
agentName: opts.agentName,
|
|
6446
|
+
role: opts.role,
|
|
6447
|
+
identity: opts.identity,
|
|
6448
|
+
availableSkills: opts.availableSkills
|
|
6449
|
+
}));
|
|
6390
6450
|
const orgCtx = this.buildOrgContextSection(opts.orgContext, opts.contextMdPath);
|
|
6391
6451
|
if (orgCtx)
|
|
6392
|
-
|
|
6452
|
+
semiStable.push(orgCtx);
|
|
6393
6453
|
if (opts.teamAnnouncements?.trim()) {
|
|
6394
|
-
|
|
6454
|
+
semiStable.push("\n## Team Announcements\n" + opts.teamAnnouncements.trim());
|
|
6395
6455
|
}
|
|
6396
6456
|
if (opts.teamNorms?.trim()) {
|
|
6397
|
-
|
|
6457
|
+
semiStable.push("\n## Team Working Norms\n" + opts.teamNorms.trim());
|
|
6398
6458
|
}
|
|
6399
6459
|
if (opts.teamDataDir) {
|
|
6400
6460
|
const lines = ["\n## Team Data Directory", `Path: \`${opts.teamDataDir}\``, "Files:", "- `ANNOUNCEMENT.md` \u2014 team announcements", "- `NORMS.md` \u2014 team working norms"];
|
|
@@ -6403,50 +6463,32 @@ var init_context_engine = __esm({
|
|
|
6403
6463
|
} else {
|
|
6404
6464
|
lines.push("\nRead and follow the announcements and norms above. If you need changes, ask the team manager.");
|
|
6405
6465
|
}
|
|
6406
|
-
|
|
6407
|
-
}
|
|
6408
|
-
if (opts.projectContext) {
|
|
6409
|
-
const { project, repositories, governanceRules, teamRole } = opts.projectContext;
|
|
6410
|
-
parts.push("\n## Current Project");
|
|
6411
|
-
parts.push(`- Project: **${project.name}** (${project.status})`);
|
|
6412
|
-
if (project.description)
|
|
6413
|
-
parts.push(`- ${project.description.slice(0, SYSTEM_PROJECT_DESC_CHARS)}`);
|
|
6414
|
-
if (repositories?.length) {
|
|
6415
|
-
for (const repo of repositories) {
|
|
6416
|
-
parts.push(`- Repository: \`${repo.localPath}\` (${repo.role}, default branch: \`${repo.defaultBranch}\`)`);
|
|
6417
|
-
}
|
|
6418
|
-
}
|
|
6419
|
-
parts.push("");
|
|
6420
|
-
parts.push("Some git operations (switching to existing branches, pushing to protected branches, merge, rebase) require human approval \u2014 the system will pause and ask the reviewer. If denied, you will receive a reason; read it and adjust your approach.");
|
|
6421
|
-
if (teamRole)
|
|
6422
|
-
parts.push(`- Your role: ${teamRole}`);
|
|
6423
|
-
if (governanceRules)
|
|
6424
|
-
parts.push(`- Governance: ${governanceRules}`);
|
|
6466
|
+
semiStable.push(lines.join("\n"));
|
|
6425
6467
|
}
|
|
6426
6468
|
if (opts.agentWorkspace) {
|
|
6427
|
-
|
|
6428
|
-
|
|
6469
|
+
semiStable.push("\n## Your Workspace");
|
|
6470
|
+
semiStable.push(`- Working directory: \`${opts.agentWorkspace.primaryWorkspace}\``);
|
|
6429
6471
|
if (opts.agentWorkspace.sharedWorkspace) {
|
|
6430
|
-
|
|
6472
|
+
semiStable.push(`- Shared workspace: \`${opts.agentWorkspace.sharedWorkspace}\` (all agents can read/write here)`);
|
|
6431
6473
|
}
|
|
6432
6474
|
const artifactsDir = opts.agentWorkspace.builderArtifactsDir ?? "~/.markus/builder-artifacts";
|
|
6433
6475
|
if (opts.agentWorkspace.builderArtifactsDir) {
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6476
|
+
semiStable.push(`- Builder artifacts directory: \`${artifactsDir}/\``);
|
|
6477
|
+
semiStable.push(" When creating agents, teams, or skills, place them in the correct subdirectory:");
|
|
6478
|
+
semiStable.push(` - Agents \u2192 \`${artifactsDir}/agents/{agent-name}/\``);
|
|
6479
|
+
semiStable.push(` - Teams \u2192 \`${artifactsDir}/teams/{team-name}/\``);
|
|
6480
|
+
semiStable.push(` - Skills \u2192 \`${artifactsDir}/skills/{skill-name}/\``);
|
|
6481
|
+
semiStable.push(" The Builder page and install system ONLY recognize these paths.");
|
|
6440
6482
|
}
|
|
6441
6483
|
if (opts.agentDataDir) {
|
|
6442
|
-
|
|
6484
|
+
semiStable.push(`- Agent data directory: \`${opts.agentDataDir}\` (your ROLE.md, MEMORY.md, and personal files)`);
|
|
6443
6485
|
}
|
|
6444
|
-
|
|
6445
|
-
|
|
6486
|
+
semiStable.push("- IMPORTANT: Always use **absolute paths** in file operations. Relative paths are error-prone.");
|
|
6487
|
+
semiStable.push("- You can directly read files in the shared workspace using `file_read` \u2014 no need to request them from other agents.");
|
|
6446
6488
|
} else if (opts.agentDataDir) {
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6489
|
+
semiStable.push("\n## Your Workspace");
|
|
6490
|
+
semiStable.push(`- Agent data directory: \`${opts.agentDataDir}\` (your ROLE.md, MEMORY.md, and personal files)`);
|
|
6491
|
+
semiStable.push("- IMPORTANT: Always use **absolute paths** in file operations. Relative paths are error-prone.");
|
|
6450
6492
|
}
|
|
6451
6493
|
if (opts.agentWorkspace?.sharedWorkspace) {
|
|
6452
6494
|
const userMdPath = `${opts.agentWorkspace.sharedWorkspace}/USER.md`;
|
|
@@ -6454,91 +6496,78 @@ var init_context_engine = __esm({
|
|
|
6454
6496
|
if (existsSync8(userMdPath)) {
|
|
6455
6497
|
const userProfile = readFileSync6(userMdPath, "utf-8").trim();
|
|
6456
6498
|
if (userProfile) {
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6499
|
+
semiStable.push("\n## About the Owner");
|
|
6500
|
+
semiStable.push(userProfile.slice(0, SYSTEM_USER_PROFILE_CHARS));
|
|
6501
|
+
semiStable.push("\n_This profile is maintained by the Secretary. If you notice new preferences or patterns from the owner, mention them to the Secretary via `agent_send_message`._");
|
|
6460
6502
|
}
|
|
6461
6503
|
}
|
|
6462
6504
|
} catch {
|
|
6463
6505
|
}
|
|
6464
6506
|
}
|
|
6465
6507
|
if (opts.trustLevel) {
|
|
6466
|
-
|
|
6467
|
-
|
|
6508
|
+
semiStable.push("\n## Your Trust Level");
|
|
6509
|
+
semiStable.push(`- Level: **${opts.trustLevel.level}** (score: ${opts.trustLevel.score})`);
|
|
6468
6510
|
if (opts.trustLevel.level === "probation") {
|
|
6469
|
-
|
|
6511
|
+
semiStable.push("- You are on probation. All your task creations require human approval. Focus on quality to build trust.");
|
|
6470
6512
|
} else if (opts.trustLevel.level === "standard") {
|
|
6471
|
-
|
|
6513
|
+
semiStable.push("- You are a standard-level agent. Routine tasks may auto-approve; significant tasks need manager approval.");
|
|
6472
6514
|
} else if (opts.trustLevel.level === "trusted") {
|
|
6473
|
-
|
|
6515
|
+
semiStable.push("- You are a trusted agent. You have a proven track record and higher autonomy.");
|
|
6474
6516
|
} else if (opts.trustLevel.level === "senior") {
|
|
6475
|
-
|
|
6517
|
+
semiStable.push("- You are a senior agent. You have the highest autonomy. Routine tasks auto-approve.");
|
|
6476
6518
|
}
|
|
6477
6519
|
}
|
|
6520
|
+
if (opts.environment) {
|
|
6521
|
+
semiStable.push(this.buildEnvironmentSection(opts.environment));
|
|
6522
|
+
}
|
|
6523
|
+
const longTermMem = opts.memory.getLongTermMemory();
|
|
6524
|
+
if (longTermMem) {
|
|
6525
|
+
semiStable.push("\n## Your Knowledge");
|
|
6526
|
+
semiStable.push(longTermMem.slice(0, SYSTEM_KNOWLEDGE_CHARS));
|
|
6527
|
+
}
|
|
6528
|
+
const dynamic = [];
|
|
6529
|
+
if (opts.projectContext) {
|
|
6530
|
+
const { project, repositories, governanceRules, teamRole } = opts.projectContext;
|
|
6531
|
+
dynamic.push("\n## Current Project");
|
|
6532
|
+
dynamic.push(`- Project: **${project.name}** (${project.status})`);
|
|
6533
|
+
if (project.description)
|
|
6534
|
+
dynamic.push(`- ${project.description.slice(0, SYSTEM_PROJECT_DESC_CHARS)}`);
|
|
6535
|
+
if (repositories?.length) {
|
|
6536
|
+
for (const repo of repositories) {
|
|
6537
|
+
dynamic.push(`- Repository: \`${repo.localPath}\` (${repo.role}, default branch: \`${repo.defaultBranch}\`)`);
|
|
6538
|
+
}
|
|
6539
|
+
}
|
|
6540
|
+
dynamic.push("");
|
|
6541
|
+
dynamic.push("Some git operations (switching to existing branches, pushing to protected branches, merge, rebase) require human approval \u2014 the system will pause and ask the reviewer. If denied, you will receive a reason; read it and adjust your approach.");
|
|
6542
|
+
if (teamRole)
|
|
6543
|
+
dynamic.push(`- Your role: ${teamRole}`);
|
|
6544
|
+
if (governanceRules)
|
|
6545
|
+
dynamic.push(`- Governance: ${governanceRules}`);
|
|
6546
|
+
}
|
|
6478
6547
|
if (opts.announcements?.length) {
|
|
6479
|
-
|
|
6548
|
+
dynamic.push("\n## System Announcements");
|
|
6480
6549
|
for (const a of opts.announcements) {
|
|
6481
6550
|
const prefix = a.priority === "urgent" ? "[URGENT] " : a.priority === "high" ? "[HIGH] " : "[INFO] ";
|
|
6482
|
-
|
|
6551
|
+
dynamic.push(`- ${prefix}${a.title}: ${a.content}`);
|
|
6483
6552
|
}
|
|
6484
6553
|
}
|
|
6485
6554
|
if (opts.recentFeedback?.length) {
|
|
6486
|
-
|
|
6555
|
+
dynamic.push("\n## Human Feedback (recent)");
|
|
6487
6556
|
for (const fb of opts.recentFeedback) {
|
|
6488
6557
|
const urgency = fb.priority === "critical" ? "[CRITICAL] " : fb.priority === "important" ? "[IMPORTANT] " : "";
|
|
6489
6558
|
const anchor = fb.anchor ? ` (re: ${fb.anchor.section}${fb.anchor.itemId ? "/" + fb.anchor.itemId : ""})` : "";
|
|
6490
|
-
|
|
6559
|
+
dynamic.push(`- ${urgency}**${fb.authorName}**${anchor}: ${fb.content}`);
|
|
6491
6560
|
}
|
|
6492
6561
|
}
|
|
6493
6562
|
if (opts.projectDeliverables?.length) {
|
|
6494
|
-
|
|
6563
|
+
dynamic.push("\n## Project Deliverables (key entries)");
|
|
6495
6564
|
for (const k of opts.projectDeliverables) {
|
|
6496
|
-
|
|
6565
|
+
dynamic.push(`- **[${k.category}]** ${k.title}: ${k.content.slice(0, SYSTEM_DELIVERABLE_PREVIEW_CHARS)}`);
|
|
6497
6566
|
}
|
|
6498
6567
|
}
|
|
6499
|
-
if (opts.role.defaultPolicies.length > 0) {
|
|
6500
|
-
parts.push("\n## Policies");
|
|
6501
|
-
for (const policy of opts.role.defaultPolicies) {
|
|
6502
|
-
parts.push(`### ${policy.name}`);
|
|
6503
|
-
for (const rule of policy.rules) {
|
|
6504
|
-
parts.push(`- ${rule}`);
|
|
6505
|
-
}
|
|
6506
|
-
}
|
|
6507
|
-
}
|
|
6508
|
-
const longTermMem = opts.memory.getLongTermMemory();
|
|
6509
|
-
if (longTermMem) {
|
|
6510
|
-
parts.push("\n## Your Knowledge");
|
|
6511
|
-
parts.push(longTermMem.slice(0, SYSTEM_KNOWLEDGE_CHARS));
|
|
6512
|
-
}
|
|
6513
|
-
const alreadyShownIds = /* @__PURE__ */ new Set();
|
|
6514
|
-
const isDream = opts.scenario === "memory_consolidation";
|
|
6515
6568
|
if (!isDream && (opts.deliverableContext || opts.knowledgeContext)) {
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
}
|
|
6519
|
-
const cpp = opts.cognitiveContext;
|
|
6520
|
-
if (cpp && !cpp.isEmpty) {
|
|
6521
|
-
if (cpp.cognitiveContext) {
|
|
6522
|
-
parts.push("\n## Cognitive Context");
|
|
6523
|
-
parts.push(cpp.cognitiveContext);
|
|
6524
|
-
}
|
|
6525
|
-
if (cpp.retrievedContext) {
|
|
6526
|
-
parts.push("\n## Retrieved Context");
|
|
6527
|
-
parts.push(cpp.retrievedContext);
|
|
6528
|
-
}
|
|
6529
|
-
if (cpp.reflection) {
|
|
6530
|
-
parts.push("\n## Reflection");
|
|
6531
|
-
parts.push(cpp.reflection);
|
|
6532
|
-
}
|
|
6533
|
-
} else if (!isDream) {
|
|
6534
|
-
const relevantMemories = await this.retrieveRelevantMemories(opts.memory, opts.currentQuery, opts.agentId, alreadyShownIds);
|
|
6535
|
-
if (relevantMemories.length > 0) {
|
|
6536
|
-
parts.push("\n## Relevant Memories");
|
|
6537
|
-
for (const mem of relevantMemories) {
|
|
6538
|
-
const ts = mem.timestamp ? new Date(mem.timestamp).toLocaleDateString() : "";
|
|
6539
|
-
parts.push(`- [${ts}] ${mem.content}`);
|
|
6540
|
-
}
|
|
6541
|
-
}
|
|
6569
|
+
dynamic.push("\n## Shared Deliverables");
|
|
6570
|
+
dynamic.push((opts.deliverableContext ?? opts.knowledgeContext ?? "").slice(0, SYSTEM_DELIVERABLES_CHARS));
|
|
6542
6571
|
}
|
|
6543
6572
|
if (!isDream) {
|
|
6544
6573
|
if (opts.assignedTasks && opts.assignedTasks.length > 0) {
|
|
@@ -6551,111 +6580,102 @@ var init_context_engine = __esm({
|
|
|
6551
6580
|
const myDone = myTasks.filter((t) => CLOSED_STATUSES.has(t.status));
|
|
6552
6581
|
const MY_TASK_LIMIT = SYSTEM_MY_TASKS_MAX;
|
|
6553
6582
|
const TEAM_TASK_LIMIT = SYSTEM_TEAM_TASKS_MAX;
|
|
6554
|
-
|
|
6555
|
-
|
|
6583
|
+
dynamic.push("\n## Task Board");
|
|
6584
|
+
dynamic.push("### My Tasks (assigned to you):");
|
|
6556
6585
|
if (myActive.length > 0) {
|
|
6557
6586
|
const shown = myActive.slice(0, MY_TASK_LIMIT);
|
|
6558
6587
|
for (const t of shown) {
|
|
6559
|
-
|
|
6588
|
+
dynamic.push(`- [${t.status.toUpperCase()}] **${t.title}** (ID: \`${t.id}\`, priority: ${t.priority})`);
|
|
6560
6589
|
if (t.description)
|
|
6561
|
-
|
|
6590
|
+
dynamic.push(` ${t.description.slice(0, SYSTEM_TASK_DESC_CHARS)}`);
|
|
6562
6591
|
}
|
|
6563
6592
|
if (myActive.length > MY_TASK_LIMIT) {
|
|
6564
|
-
|
|
6593
|
+
dynamic.push(`_(${myActive.length - MY_TASK_LIMIT} more active tasks not shown \u2014 use \`task_list\` for full list)_`);
|
|
6565
6594
|
}
|
|
6566
6595
|
} else {
|
|
6567
|
-
|
|
6596
|
+
dynamic.push("No active tasks assigned to you.");
|
|
6568
6597
|
}
|
|
6569
6598
|
if (myDone.length > 0) {
|
|
6570
|
-
|
|
6599
|
+
dynamic.push(`_(${myDone.length} completed/closed tasks)_`);
|
|
6571
6600
|
}
|
|
6572
6601
|
if (otherTasks.length > 0) {
|
|
6573
6602
|
const otherActive = otherTasks.filter((t) => !CLOSED_STATUSES.has(t.status)).sort(byPriority);
|
|
6574
6603
|
const otherDone = otherTasks.filter((t) => CLOSED_STATUSES.has(t.status));
|
|
6575
6604
|
if (otherActive.length > 0) {
|
|
6576
|
-
|
|
6605
|
+
dynamic.push("### Team Tasks (assigned to others):");
|
|
6577
6606
|
const shown = otherActive.slice(0, TEAM_TASK_LIMIT);
|
|
6578
6607
|
for (const t of shown) {
|
|
6579
6608
|
const owner = t.assignedAgentName ?? t.assignedAgentId ?? "unassigned";
|
|
6580
|
-
|
|
6609
|
+
dynamic.push(`- [${t.status.toUpperCase()}] **${t.title}** (ID: \`${t.id}\`, assignee: ${owner}, priority: ${t.priority})`);
|
|
6581
6610
|
}
|
|
6582
6611
|
if (otherActive.length > TEAM_TASK_LIMIT) {
|
|
6583
|
-
|
|
6612
|
+
dynamic.push(`_(${otherActive.length - TEAM_TASK_LIMIT} more team tasks not shown)_`);
|
|
6584
6613
|
}
|
|
6585
6614
|
}
|
|
6586
6615
|
if (otherDone.length > 0) {
|
|
6587
|
-
|
|
6616
|
+
dynamic.push(`_(${otherDone.length} other completed/closed tasks)_`);
|
|
6588
6617
|
}
|
|
6589
6618
|
}
|
|
6590
6619
|
} else {
|
|
6591
|
-
|
|
6592
|
-
|
|
6620
|
+
dynamic.push("\n## Task Board");
|
|
6621
|
+
dynamic.push("No tasks on the board.");
|
|
6593
6622
|
}
|
|
6594
|
-
parts.push("");
|
|
6595
|
-
parts.push("### Task & Requirement Workflow");
|
|
6596
|
-
parts.push("");
|
|
6597
|
-
parts.push("**Requirements** (governance gate):");
|
|
6598
|
-
parts.push("- `requirement_propose` \u2192 pending human approval \u2192 approved \u2192 link tasks via `requirement_id`");
|
|
6599
|
-
parts.push("- Every task MUST reference an approved `requirement_id`. Use `requirement_propose` first if no requirement exists.");
|
|
6600
|
-
parts.push("");
|
|
6601
|
-
parts.push("**Task lifecycle** \u2014 Create \u2192 Execute \u2192 Review \u2192 Complete:");
|
|
6602
|
-
parts.push('- **Create**: `task_create` (REQUIRED: `assigned_agent_id`, `reviewer_id`; optional `reviewer_type`: "agent"|"human"). Check `task_list` first to avoid duplicates.');
|
|
6603
|
-
parts.push("- **Execute**: Decompose with `subtask_create` \u2192 work through subtasks \u2192 `task_submit_review` with summary + deliverables (MANDATORY). System auto-fills `task_id` and `reviewer`.");
|
|
6604
|
-
parts.push('- **Review**: Reviewer approves with `task_update(status:"completed")` or rejects with `task_update(status:"in_progress", note:"what needs to change")` (auto-restarts execution). Workers MUST NOT set status=completed on their own tasks.');
|
|
6605
|
-
parts.push('- **Blockers**: Use `task_update(status:"blocked", note:"reason")` when unable to proceed.');
|
|
6606
|
-
parts.push("");
|
|
6607
|
-
parts.push("**Dependencies & DAG decomposition**:");
|
|
6608
|
-
parts.push("- **CRITICAL**: Use `blocked_by` to express ALL dependency relationships. If task B needs output from task A, B **MUST** include A's ID in `blocked_by`. Without this, tasks run in parallel and downstream tasks lack upstream deliverables.");
|
|
6609
|
-
parts.push("- For complex goals, create a DAG of tasks. Assign each to the best team member (`team_list`). Independent tasks run in parallel; dependent tasks wait for predecessors.");
|
|
6610
|
-
parts.push("- If consolidated output is needed, create a final synthesis task assigned to a manager, `blocked_by` ALL prerequisites.");
|
|
6611
|
-
parts.push("");
|
|
6612
|
-
parts.push("**Work discovery**: `list_projects` \u2192 `requirement_list` \u2192 `task_list`. Use `memory_save`/`memory_search` for personal notes; `deliverable_create`/`deliverable_search` for shared outputs.");
|
|
6613
|
-
parts.push("");
|
|
6614
|
-
parts.push("**Automatic status notifications** (do NOT duplicate manually):");
|
|
6615
|
-
parts.push("- When task status changes, the system **automatically** handles all side effects: execution start/cancel, reviewer notification, dependency unblocking.");
|
|
6616
|
-
parts.push("- Task status notifications are placed in assignees' mailboxes as **informational context only**.");
|
|
6617
|
-
parts.push("- Do NOT send A2A messages to notify about task status changes \u2014 only send A2A when you have substantive coordination needs beyond the status change itself.");
|
|
6618
|
-
parts.push("");
|
|
6619
|
-
parts.push("**Communicating with humans**:");
|
|
6620
|
-
parts.push("- `notify_user` \u2014 proactive message to a human team member: status updates, progress reports, findings, alerts. Appears in chat timeline AND notification bell. The human can reply. Write comprehensive body with full context. **This is the ONLY way to reach humans from non-chat contexts** (heartbeat, autonomous tasks, etc.).");
|
|
6621
|
-
parts.push("- `request_user_approval` \u2014 when you need a human decision, approval, or input. BLOCKS until the user responds. Supports custom options and freeform text. Do NOT use for routine updates.");
|
|
6622
|
-
parts.push("- `recall_activity` \u2014 query your own past execution logs by task or activity type. Use when you need to review what you did previously (e.g., to answer a follow-up question).");
|
|
6623
|
-
parts.push("");
|
|
6624
|
-
parts.push("**Communicating with other agents**:");
|
|
6625
|
-
parts.push("- `agent_send_message` \u2014 send a direct message to a peer agent. **By default this is asynchronous (fire-and-forget)**: the message enters their mailbox and you continue working without waiting. Set `wait_for_reply: true` only when you need the answer before you can proceed (rare \u2014 prefer async).");
|
|
6626
|
-
parts.push("- A2A messaging is inherently **non-blocking**. You send a message, the recipient processes it on their own schedule, and may reply later via their own `agent_send_message`. Do NOT spin-wait or poll for responses.");
|
|
6627
|
-
parts.push("- For substantial work requests, create a `task_create` assigned to the target agent instead of asking via message.");
|
|
6628
|
-
parts.push("- Do NOT use A2A messages for routine task status notifications \u2014 the system handles those automatically.");
|
|
6629
6623
|
}
|
|
6630
|
-
if (opts.
|
|
6631
|
-
|
|
6624
|
+
if (opts.dynamicContext) {
|
|
6625
|
+
dynamic.push(opts.dynamicContext);
|
|
6626
|
+
}
|
|
6627
|
+
const alreadyShownIds = /* @__PURE__ */ new Set();
|
|
6628
|
+
const cpp = opts.cognitiveContext;
|
|
6629
|
+
if (cpp && !cpp.isEmpty) {
|
|
6630
|
+
if (cpp.cognitiveContext) {
|
|
6631
|
+
dynamic.push("\n## Cognitive Context");
|
|
6632
|
+
dynamic.push(cpp.cognitiveContext);
|
|
6633
|
+
}
|
|
6634
|
+
if (cpp.retrievedContext) {
|
|
6635
|
+
dynamic.push("\n## Retrieved Context");
|
|
6636
|
+
dynamic.push(cpp.retrievedContext);
|
|
6637
|
+
}
|
|
6638
|
+
if (cpp.reflection) {
|
|
6639
|
+
dynamic.push("\n## Reflection");
|
|
6640
|
+
dynamic.push(cpp.reflection);
|
|
6641
|
+
}
|
|
6642
|
+
} else if (!isDream) {
|
|
6643
|
+
const relevantMemories = await this.retrieveRelevantMemories(opts.memory, opts.currentQuery, opts.agentId, alreadyShownIds);
|
|
6644
|
+
if (relevantMemories.length > 0) {
|
|
6645
|
+
dynamic.push("\n## Relevant Memories");
|
|
6646
|
+
for (const mem of relevantMemories) {
|
|
6647
|
+
const ts = mem.timestamp ? new Date(mem.timestamp).toLocaleDateString() : "";
|
|
6648
|
+
dynamic.push(`- [${ts}] ${mem.content}`);
|
|
6649
|
+
}
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
if (!isDream && opts.mailboxContext) {
|
|
6653
|
+
dynamic.push(this.buildMailboxSection(opts.mailboxContext));
|
|
6632
6654
|
}
|
|
6633
6655
|
if (!isDream && opts.senderIdentity) {
|
|
6634
|
-
|
|
6656
|
+
dynamic.push(`
|
|
6635
6657
|
## Current Conversation`);
|
|
6636
|
-
|
|
6658
|
+
dynamic.push(`You are now talking to **${opts.senderIdentity.name}** (${opts.senderIdentity.role}).`);
|
|
6659
|
+
if (opts.senderIdentity.isFirstConversation) {
|
|
6660
|
+
dynamic.push("**This is their first conversation** \u2014 they have never used Markus before. Follow your onboarding protocol if you have one.");
|
|
6661
|
+
}
|
|
6637
6662
|
if (opts.senderIdentity.role === "owner") {
|
|
6638
|
-
|
|
6663
|
+
dynamic.push("This person is the organization owner. Their instructions have the highest priority. Be proactive in reporting and responsive to their needs.");
|
|
6639
6664
|
} else if (opts.senderIdentity.role === "admin") {
|
|
6640
|
-
|
|
6665
|
+
dynamic.push("This person is an administrator. Cooperate actively and share progress proactively.");
|
|
6641
6666
|
} else if (opts.senderIdentity.role === "guest") {
|
|
6642
|
-
|
|
6667
|
+
dynamic.push("This person is an external guest. Be polite but cautious \u2014 do not expose internal sensitive information.");
|
|
6643
6668
|
}
|
|
6644
6669
|
}
|
|
6645
6670
|
if (!isDream) {
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
}
|
|
6654
|
-
if (!isDream && opts.mailboxContext) {
|
|
6655
|
-
parts.push(this.buildMailboxSection(opts.mailboxContext));
|
|
6671
|
+
dynamic.push("\n## Tool Usage Rules");
|
|
6672
|
+
dynamic.push("**File editing discipline**: You MUST use `file_write` and `file_edit` for all file creation and modification. NEVER use `shell_execute` with `cat`, `echo`, `printf`, `tee`, pipes (`|`), output redirection (`>`, `>>`), heredocs (`<<`), or `sed`/`awk` to write or modify files \u2014 these bypass file access controls. `shell_execute` is for running commands (build, test, git, etc.), not for writing files.");
|
|
6673
|
+
dynamic.push("**Large file writing**: NEVER write a document >200 lines in a single `file_write` call. Write section by section: `file_write` the first section, then `file_edit` to append each subsequent section.");
|
|
6674
|
+
dynamic.push("**Error handling**: If a tool call fails, analyze the error and try a different approach \u2014 do NOT repeat the same failing action.");
|
|
6675
|
+
dynamic.push("**Subagent delegation**: For heavy subtasks needing many tool calls or lots of file reading, delegate to `spawn_subagent` to keep your context lean. Use `spawn_subagents` to run independent subtasks in parallel.");
|
|
6676
|
+
dynamic.push("**Built-in tools over CLI**: ALWAYS prefer built-in tools (`task_create`, `task_assign`, `package_install`, `agent_send_message`, `memory_save`, etc.) over running `markus` CLI commands via `shell_execute`. The CLI is for human operators \u2014 agents must use their native tool interface. Only fall back to CLI if no built-in tool exists for the operation.");
|
|
6677
|
+
dynamic.push('**No auto-install/deploy**: NEVER automatically install or deploy agents, teams, or skills via `package_install` or `hub_install` unless explicitly requested by a human team member (e.g., "install", "deploy", "hire", "start"). Creating an artifact (writing files to `builder-artifacts/`) is separate from deploying it into the live organization.');
|
|
6656
6678
|
}
|
|
6657
|
-
const scenario = opts.scenario ?? "chat";
|
|
6658
|
-
parts.push(this.buildScenarioSection(scenario, { a2aWaitForReply: opts.a2aWaitForReply }));
|
|
6659
6679
|
const now2 = /* @__PURE__ */ new Date();
|
|
6660
6680
|
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
6661
6681
|
const offset = now2.getTimezoneOffset();
|
|
@@ -6664,10 +6684,23 @@ var init_context_engine = __esm({
|
|
|
6664
6684
|
const absM = String(Math.abs(offset) % 60).padStart(2, "0");
|
|
6665
6685
|
const pad = (n) => String(n).padStart(2, "0");
|
|
6666
6686
|
const localStr = `${now2.getFullYear()}-${pad(now2.getMonth() + 1)}-${pad(now2.getDate())} ${pad(now2.getHours())}:${pad(now2.getMinutes())}:${pad(now2.getSeconds())}`;
|
|
6667
|
-
|
|
6687
|
+
dynamic.push(`
|
|
6668
6688
|
---
|
|
6669
6689
|
Current date and time: ${localStr} (${tz}, UTC${sign}${absH}:${absM})`);
|
|
6670
|
-
|
|
6690
|
+
const stableText = stable.join("\n");
|
|
6691
|
+
const semiStableText = semiStable.join("\n");
|
|
6692
|
+
const dynamicText = dynamic.join("\n");
|
|
6693
|
+
const segments = [];
|
|
6694
|
+
if (stableText)
|
|
6695
|
+
segments.push({ content: stableText, cacheBreakpoint: true });
|
|
6696
|
+
if (semiStableText)
|
|
6697
|
+
segments.push({ content: semiStableText, cacheBreakpoint: true });
|
|
6698
|
+
if (dynamicText)
|
|
6699
|
+
segments.push({ content: dynamicText });
|
|
6700
|
+
return {
|
|
6701
|
+
text: segments.map((s) => s.content).join("\n"),
|
|
6702
|
+
segments
|
|
6703
|
+
};
|
|
6671
6704
|
}
|
|
6672
6705
|
buildMailboxSection(ctx) {
|
|
6673
6706
|
const lines = ["\n## Your Attention State"];
|
|
@@ -6801,11 +6834,17 @@ ${ctx.mergedContent.slice(0, SYSTEM_MAILBOX_MERGED_CHARS)}`);
|
|
|
6801
6834
|
lines.push('- Give a generic acknowledgment like "Got it, will look into it" without substantive content');
|
|
6802
6835
|
lines.push("- Ignore prior comments that provide important context for the current discussion");
|
|
6803
6836
|
lines.push("");
|
|
6804
|
-
lines.push("**
|
|
6805
|
-
lines.push(
|
|
6806
|
-
lines.push("
|
|
6807
|
-
lines.push(
|
|
6808
|
-
lines.push("
|
|
6837
|
+
lines.push("**MANDATORY outcome \u2014 you MUST end with exactly one of these:**");
|
|
6838
|
+
lines.push("1. Call `task_comment` or `requirement_comment` tool to post your reply, OR");
|
|
6839
|
+
lines.push("2. Output `[NO_REPLY_NEEDED]` in your text to explicitly signal that no response is warranted.");
|
|
6840
|
+
lines.push("");
|
|
6841
|
+
lines.push("If you finish without doing either of the above, the system will automatically retry your turn \u2014 your text output alone is NEVER sufficient.");
|
|
6842
|
+
lines.push("");
|
|
6843
|
+
lines.push("**When to use `[NO_REPLY_NEEDED]` \u2014 do NOT reply when:**");
|
|
6844
|
+
lines.push('- The comment is just an acknowledgment ("Got it", "Will do", "Thanks", "Agreed")');
|
|
6845
|
+
lines.push("- Both parties have reached agreement or the discussion is resolved");
|
|
6846
|
+
lines.push('- Your reply would only be "Sounds good", "Agreed", or similar zero-information response');
|
|
6847
|
+
lines.push("- The comment does not ask a question, request action, or contain information you need to correct");
|
|
6809
6848
|
lines.push("- **Principle**: only comment when your reply adds **new information** or requests a **decision**. Avoid comment ping-pong.");
|
|
6810
6849
|
break;
|
|
6811
6850
|
case "review":
|
|
@@ -6919,8 +6958,7 @@ ${ctx.mergedContent.slice(0, SYSTEM_MAILBOX_MERGED_CHARS)}`);
|
|
|
6919
6958
|
lines.push("6. **Hiring & Team Building** \u2014 Two phases: CREATE then INSTALL (only when user requests).");
|
|
6920
6959
|
lines.push(" a) *Creating* (design the artifact): activate `agent-building` or `team-building` skill \u2192 write artifact files. Or `hub_search` to browse community packages.");
|
|
6921
6960
|
lines.push(" b) *Installing* (deploy into org \u2014 ONLY when user explicitly asks to install/deploy/hire):");
|
|
6922
|
-
lines.push(" -
|
|
6923
|
-
lines.push(" - Install artifact: `builder_install` (for custom-built or Hub-downloaded packages)");
|
|
6961
|
+
lines.push(" - `package_list` \u2192 `package_install` (type: agent/team/skill)");
|
|
6924
6962
|
lines.push(" - Hub one-step: `hub_install` (download + install)");
|
|
6925
6963
|
lines.push(" c) After install: onboard via `agent_send_message` (project context) \u2192 `task_create` (initial work)");
|
|
6926
6964
|
lines.push(" **IMPORTANT**: NEVER auto-install. Creating an artifact does NOT mean deploying it. Wait for explicit user request.");
|
|
@@ -7051,7 +7089,8 @@ ${ctx.mergedContent.slice(0, SYSTEM_MAILBOX_MERGED_CHARS)}`);
|
|
|
7051
7089
|
totalUsed,
|
|
7052
7090
|
available,
|
|
7053
7091
|
usagePercent: Math.round(usagePercent * 10) / 10
|
|
7054
|
-
}
|
|
7092
|
+
},
|
|
7093
|
+
systemCacheSegments: opts.systemCacheSegments
|
|
7055
7094
|
};
|
|
7056
7095
|
}
|
|
7057
7096
|
/**
|
|
@@ -8215,7 +8254,7 @@ var init_tool_selector = __esm({
|
|
|
8215
8254
|
"\u5206\u914D",
|
|
8216
8255
|
"\u8DEF\u7531"
|
|
8217
8256
|
],
|
|
8218
|
-
toolNames: ["team_list", "team_status", "delegate_message", "
|
|
8257
|
+
toolNames: ["team_list", "team_status", "delegate_message", "package_list", "package_install"]
|
|
8219
8258
|
},
|
|
8220
8259
|
{
|
|
8221
8260
|
name: "deliverables",
|
|
@@ -8245,6 +8284,21 @@ var init_tool_selector = __esm({
|
|
|
8245
8284
|
"\u7ECF\u9A8C"
|
|
8246
8285
|
],
|
|
8247
8286
|
toolNames: ["deliverable_create", "deliverable_search", "deliverable_list", "deliverable_update"]
|
|
8287
|
+
},
|
|
8288
|
+
{
|
|
8289
|
+
name: "builder",
|
|
8290
|
+
keywords: [
|
|
8291
|
+
"builder",
|
|
8292
|
+
"artifact",
|
|
8293
|
+
"deploy",
|
|
8294
|
+
"skill",
|
|
8295
|
+
"package",
|
|
8296
|
+
"hub",
|
|
8297
|
+
"\u90E8\u7F72",
|
|
8298
|
+
"\u5DE5\u4EF6",
|
|
8299
|
+
"\u6280\u80FD\u5305"
|
|
8300
|
+
],
|
|
8301
|
+
toolNames: ["builder_install", "builder_list"]
|
|
8248
8302
|
}
|
|
8249
8303
|
];
|
|
8250
8304
|
BASE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
@@ -41282,6 +41336,45 @@ async function searchBrave(query2, maxResults) {
|
|
|
41282
41336
|
date: r.page_age
|
|
41283
41337
|
}));
|
|
41284
41338
|
}
|
|
41339
|
+
async function searchBing(query2, maxResults) {
|
|
41340
|
+
const encoded = encodeURIComponent(query2);
|
|
41341
|
+
let res;
|
|
41342
|
+
try {
|
|
41343
|
+
res = await proxyFetch(`https://www.bing.com/search?q=${encoded}`, {
|
|
41344
|
+
headers: { "User-Agent": BING_UA }
|
|
41345
|
+
});
|
|
41346
|
+
} catch (err) {
|
|
41347
|
+
throw new Error(`Network error: ${err instanceof Error ? err.message : String(err)}`);
|
|
41348
|
+
}
|
|
41349
|
+
if (!res.ok)
|
|
41350
|
+
throw new Error(`HTTP ${res.status} ${res.statusText}`);
|
|
41351
|
+
const html = await res.text();
|
|
41352
|
+
const results = parseBingHtml(html, maxResults);
|
|
41353
|
+
if (results.length === 0)
|
|
41354
|
+
throw new Error("Parsed 0 results from Bing");
|
|
41355
|
+
return results;
|
|
41356
|
+
}
|
|
41357
|
+
function parseBingHtml(html, max) {
|
|
41358
|
+
const results = [];
|
|
41359
|
+
const algoRegex = /<li[^>]*class="b_algo"[^>]*>([\s\S]*?)<\/li>/g;
|
|
41360
|
+
let match;
|
|
41361
|
+
while ((match = algoRegex.exec(html)) !== null) {
|
|
41362
|
+
if (results.length >= max)
|
|
41363
|
+
break;
|
|
41364
|
+
const item = match[1];
|
|
41365
|
+
const linkMatch = item.match(/<a[^>]+href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/i);
|
|
41366
|
+
if (!linkMatch)
|
|
41367
|
+
continue;
|
|
41368
|
+
const url = linkMatch[1];
|
|
41369
|
+
const title = stripHtml(linkMatch[2]);
|
|
41370
|
+
if (!url || !title)
|
|
41371
|
+
continue;
|
|
41372
|
+
const snippetMatch = item.match(/<p[^>]*>([\s\S]*?)<\/p>/i);
|
|
41373
|
+
const snippet = snippetMatch ? stripHtml(snippetMatch[1]) : "";
|
|
41374
|
+
results.push({ title, url, snippet });
|
|
41375
|
+
}
|
|
41376
|
+
return results;
|
|
41377
|
+
}
|
|
41285
41378
|
async function searchDuckDuckGo(query2, maxResults) {
|
|
41286
41379
|
const encoded = encodeURIComponent(query2);
|
|
41287
41380
|
let lastError;
|
|
@@ -41370,7 +41463,7 @@ function parseDDGHtml(html, maxResults) {
|
|
|
41370
41463
|
function stripHtml(html) {
|
|
41371
41464
|
return html.replace(/<[^>]*>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/'/g, "'").replace(/ /g, " ").replace(/\s+/g, " ").trim();
|
|
41372
41465
|
}
|
|
41373
|
-
var SEARCH_TIMEOUT_MS, _dispatcher, WebSearchTool, DDG_UA, DDG_ENDPOINTS;
|
|
41466
|
+
var SEARCH_TIMEOUT_MS, _dispatcher, WebSearchTool, BING_UA, DDG_UA, DDG_ENDPOINTS;
|
|
41374
41467
|
var init_web_search = __esm({
|
|
41375
41468
|
"../core/dist/tools/web-search.js"() {
|
|
41376
41469
|
"use strict";
|
|
@@ -41399,6 +41492,7 @@ var init_web_search = __esm({
|
|
|
41399
41492
|
const backends = [
|
|
41400
41493
|
{ name: "Serper", fn: searchSerper },
|
|
41401
41494
|
{ name: "Brave", fn: searchBrave },
|
|
41495
|
+
{ name: "Bing", fn: searchBing },
|
|
41402
41496
|
{ name: "DuckDuckGo", fn: searchDuckDuckGo }
|
|
41403
41497
|
];
|
|
41404
41498
|
const errors = [];
|
|
@@ -41430,6 +41524,7 @@ var init_web_search = __esm({
|
|
|
41430
41524
|
});
|
|
41431
41525
|
}
|
|
41432
41526
|
};
|
|
41527
|
+
BING_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
|
|
41433
41528
|
DDG_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
|
|
41434
41529
|
DDG_ENDPOINTS = [
|
|
41435
41530
|
"https://lite.duckduckgo.com/lite/",
|
|
@@ -45502,6 +45597,7 @@ ${notification.stdoutTail}`);
|
|
|
45502
45597
|
senderId,
|
|
45503
45598
|
senderName: senderInfo?.name,
|
|
45504
45599
|
senderRole: senderInfo?.role,
|
|
45600
|
+
isFirstConversation: senderInfo?.isFirstConversation,
|
|
45505
45601
|
responsePromise: { resolve: resolve20, reject }
|
|
45506
45602
|
}
|
|
45507
45603
|
});
|
|
@@ -45531,6 +45627,7 @@ ${notification.stdoutTail}`);
|
|
|
45531
45627
|
senderId,
|
|
45532
45628
|
senderName: senderInfo?.name,
|
|
45533
45629
|
senderRole: senderInfo?.role,
|
|
45630
|
+
isFirstConversation: senderInfo?.isFirstConversation,
|
|
45534
45631
|
responsePromise: { resolve: resolve20, reject }
|
|
45535
45632
|
}
|
|
45536
45633
|
});
|
|
@@ -45677,7 +45774,7 @@ ${notification.stdoutTail}`);
|
|
|
45677
45774
|
this.currentInteractingUserId = item.metadata.senderId;
|
|
45678
45775
|
}
|
|
45679
45776
|
const extra = item.payload.extra ?? {};
|
|
45680
|
-
const senderInfo = item.metadata?.senderName ? { name: item.metadata.senderName, role: item.metadata.senderRole ?? "user" } : void 0;
|
|
45777
|
+
const senderInfo = item.metadata?.senderName ? { name: item.metadata.senderName, role: item.metadata.senderRole ?? "user", isFirstConversation: item.metadata.isFirstConversation } : void 0;
|
|
45681
45778
|
const resolveResponse = (reply) => {
|
|
45682
45779
|
if (typeof item.metadata?.responsePromise?.resolve === "function") {
|
|
45683
45780
|
item.metadata.responsePromise.resolve(stripCompletionMarker(reply));
|
|
@@ -46412,6 +46509,9 @@ ${conversationText}`
|
|
|
46412
46509
|
setIdentityContext(ctx) {
|
|
46413
46510
|
this.identityContext = ctx;
|
|
46414
46511
|
}
|
|
46512
|
+
getTeamName() {
|
|
46513
|
+
return this.identityContext?.team?.name;
|
|
46514
|
+
}
|
|
46415
46515
|
addDynamicContextProvider(provider, key2) {
|
|
46416
46516
|
const providerKey = key2 ?? `provider_${this.dynamicContextProviders.size}`;
|
|
46417
46517
|
this.dynamicContextProviders.set(providerKey, provider);
|
|
@@ -46944,7 +47044,7 @@ ${block}
|
|
|
46944
47044
|
await counter.ensureReady();
|
|
46945
47045
|
}
|
|
46946
47046
|
const cognitiveContext = await this.prepareCognitiveContext(scenario, effectiveMessage, senderId);
|
|
46947
|
-
const systemPrompt = await this.contextEngine.buildSystemPrompt({
|
|
47047
|
+
const { text: systemPrompt, segments: systemCacheSegments } = await this.contextEngine.buildSystemPrompt({
|
|
46948
47048
|
agentId: this.id,
|
|
46949
47049
|
agentName: this.config.name,
|
|
46950
47050
|
role: this.role,
|
|
@@ -46987,7 +47087,8 @@ ${block}
|
|
|
46987
47087
|
agentId: this.id,
|
|
46988
47088
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
46989
47089
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
46990
|
-
toolDefinitions: llmTools
|
|
47090
|
+
toolDefinitions: llmTools,
|
|
47091
|
+
systemCacheSegments
|
|
46991
47092
|
});
|
|
46992
47093
|
const messages = prepared.messages;
|
|
46993
47094
|
log17.debug("Context usage for chat", { usagePercent: prepared.usage.usagePercent, totalUsed: prepared.usage.totalUsed });
|
|
@@ -47000,7 +47101,8 @@ ${block}
|
|
|
47000
47101
|
messages,
|
|
47001
47102
|
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
47002
47103
|
metadata: this.getLLMMetadata(sessionId),
|
|
47003
|
-
compaction: useCompaction
|
|
47104
|
+
compaction: useCompaction,
|
|
47105
|
+
systemCacheSegments
|
|
47004
47106
|
}, this.getEffectiveProvider()), "Chat LLM call");
|
|
47005
47107
|
const tokensThisCall = response.usage.inputTokens + response.usage.outputTokens;
|
|
47006
47108
|
this.updateTokensUsed(tokensThisCall);
|
|
@@ -47014,6 +47116,7 @@ ${block}
|
|
|
47014
47116
|
});
|
|
47015
47117
|
let toolIterations = 0;
|
|
47016
47118
|
const effectiveMaxIter = options?.maxToolIterations ?? this._maxToolIterations;
|
|
47119
|
+
const commentToolUsed = /* @__PURE__ */ new Set();
|
|
47017
47120
|
while (response.finishReason === "tool_use" && response.toolCalls?.length || response.finishReason === "max_tokens") {
|
|
47018
47121
|
if (++toolIterations > effectiveMaxIter) {
|
|
47019
47122
|
log17.warn("Tool loop hit max iterations", {
|
|
@@ -47111,6 +47214,9 @@ ${block}
|
|
|
47111
47214
|
for (let i = 0; i < response.toolCalls.length; i++) {
|
|
47112
47215
|
const tc = response.toolCalls[i];
|
|
47113
47216
|
this.loopDetector.record(tc.name, tc.arguments ?? {}, toolResults[i]?.content ?? "");
|
|
47217
|
+
if (tc.name === "task_comment" || tc.name === "requirement_comment") {
|
|
47218
|
+
commentToolUsed.add(tc.name);
|
|
47219
|
+
}
|
|
47114
47220
|
}
|
|
47115
47221
|
const loopCheck = this.loopDetector.check();
|
|
47116
47222
|
if (loopCheck.detected) {
|
|
@@ -47160,7 +47266,8 @@ ${chatYield.item.payload.content}`;
|
|
|
47160
47266
|
agentId: this.id,
|
|
47161
47267
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47162
47268
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47163
|
-
toolDefinitions: llmTools
|
|
47269
|
+
toolDefinitions: llmTools,
|
|
47270
|
+
systemCacheSegments
|
|
47164
47271
|
});
|
|
47165
47272
|
const updatedMessages = prepared2.messages;
|
|
47166
47273
|
const llmStart2 = Date.now();
|
|
@@ -47168,7 +47275,8 @@ ${chatYield.item.payload.content}`;
|
|
|
47168
47275
|
messages: updatedMessages,
|
|
47169
47276
|
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
47170
47277
|
metadata: this.getLLMMetadata(sessionId),
|
|
47171
|
-
compaction: useCompaction
|
|
47278
|
+
compaction: useCompaction,
|
|
47279
|
+
systemCacheSegments
|
|
47172
47280
|
}, this.getEffectiveProvider()), "Chat LLM continuation");
|
|
47173
47281
|
const tokens2 = response.usage.inputTokens + response.usage.outputTokens;
|
|
47174
47282
|
this.updateTokensUsed(tokens2);
|
|
@@ -47181,6 +47289,93 @@ ${chatYield.item.payload.content}`;
|
|
|
47181
47289
|
success: true
|
|
47182
47290
|
});
|
|
47183
47291
|
}
|
|
47292
|
+
const hasNoReplyMarker = /\[NO_REPLY_NEEDED\]/i.test(response.content ?? "");
|
|
47293
|
+
if (scenario === "comment_response" && commentToolUsed.size === 0 && !hasNoReplyMarker && toolIterations < effectiveMaxIter) {
|
|
47294
|
+
this.memory.appendMessage(sessionId, {
|
|
47295
|
+
role: "assistant",
|
|
47296
|
+
content: response.content,
|
|
47297
|
+
toolCalls: response.toolCalls,
|
|
47298
|
+
reasoningContent: response.reasoningContent
|
|
47299
|
+
});
|
|
47300
|
+
this.memory.appendMessage(sessionId, {
|
|
47301
|
+
role: "user",
|
|
47302
|
+
content: "[SYSTEM] You are about to end your turn WITHOUT posting a reply and WITHOUT marking [NO_REPLY_NEEDED]. In this scenario your text output is NOT visible to anyone. You MUST either: (1) call `task_comment` or `requirement_comment` tool to post your reply in the comment thread, OR (2) output exactly [NO_REPLY_NEEDED] if you have determined that no response is warranted. Do it now."
|
|
47303
|
+
});
|
|
47304
|
+
const reminderMessages = this.memory.getRecentMessages(sessionId, maxHistory);
|
|
47305
|
+
const preparedReminder = await this.contextEngine.prepareMessages({
|
|
47306
|
+
systemPrompt,
|
|
47307
|
+
sessionMessages: reminderMessages,
|
|
47308
|
+
memory: this.memory,
|
|
47309
|
+
sessionId,
|
|
47310
|
+
agentId: this.id,
|
|
47311
|
+
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47312
|
+
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47313
|
+
toolDefinitions: llmTools,
|
|
47314
|
+
systemCacheSegments
|
|
47315
|
+
});
|
|
47316
|
+
response = await this.withNetworkRetry(() => this.llmRouter.chat({
|
|
47317
|
+
messages: preparedReminder.messages,
|
|
47318
|
+
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
47319
|
+
metadata: this.getLLMMetadata(sessionId),
|
|
47320
|
+
compaction: useCompaction,
|
|
47321
|
+
systemCacheSegments
|
|
47322
|
+
}, this.getEffectiveProvider()), "Chat LLM comment-reminder");
|
|
47323
|
+
if (response.finishReason === "tool_use" && response.toolCalls?.length) {
|
|
47324
|
+
const currentActId = this.state.currentActivity?.id;
|
|
47325
|
+
this.memory.appendMessage(sessionId, {
|
|
47326
|
+
role: "assistant",
|
|
47327
|
+
content: response.content,
|
|
47328
|
+
toolCalls: response.toolCalls,
|
|
47329
|
+
reasoningContent: response.reasoningContent
|
|
47330
|
+
});
|
|
47331
|
+
const toolResults = await Promise.all(response.toolCalls.map(async (tc) => {
|
|
47332
|
+
const toolStart = Date.now();
|
|
47333
|
+
if (currentActId) {
|
|
47334
|
+
this.emitActivityLog(currentActId, "tool_start", tc.name, { arguments: tc.arguments });
|
|
47335
|
+
}
|
|
47336
|
+
try {
|
|
47337
|
+
let result = await this.executeTool(tc, void 0, sessionId);
|
|
47338
|
+
result = this.offloadLargeResult(tc.name, result);
|
|
47339
|
+
if (currentActId) {
|
|
47340
|
+
this.emitActivityLog(currentActId, "tool_end", tc.name, {
|
|
47341
|
+
durationMs: Date.now() - toolStart,
|
|
47342
|
+
success: !isErrorResult2(result),
|
|
47343
|
+
arguments: tc.arguments,
|
|
47344
|
+
result
|
|
47345
|
+
});
|
|
47346
|
+
}
|
|
47347
|
+
return { toolCallId: tc.id, content: result, error: false };
|
|
47348
|
+
} catch (toolErr) {
|
|
47349
|
+
if (currentActId) {
|
|
47350
|
+
this.emitActivityLog(currentActId, "error", `Tool ${tc.name} failed: ${String(toolErr)}`);
|
|
47351
|
+
}
|
|
47352
|
+
return { toolCallId: tc.id, content: `Error: ${String(toolErr)}`, error: true };
|
|
47353
|
+
}
|
|
47354
|
+
}));
|
|
47355
|
+
for (const tr of toolResults) {
|
|
47356
|
+
this.memory.appendMessage(sessionId, { role: "tool", content: tr.content, toolCallId: tr.toolCallId });
|
|
47357
|
+
}
|
|
47358
|
+
const finalMessages = this.memory.getRecentMessages(sessionId, maxHistory);
|
|
47359
|
+
const preparedFinal = await this.contextEngine.prepareMessages({
|
|
47360
|
+
systemPrompt,
|
|
47361
|
+
sessionMessages: finalMessages,
|
|
47362
|
+
memory: this.memory,
|
|
47363
|
+
sessionId,
|
|
47364
|
+
agentId: this.id,
|
|
47365
|
+
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47366
|
+
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47367
|
+
toolDefinitions: llmTools,
|
|
47368
|
+
systemCacheSegments
|
|
47369
|
+
});
|
|
47370
|
+
response = await this.withNetworkRetry(() => this.llmRouter.chat({
|
|
47371
|
+
messages: preparedFinal.messages,
|
|
47372
|
+
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
47373
|
+
metadata: this.getLLMMetadata(sessionId),
|
|
47374
|
+
compaction: useCompaction,
|
|
47375
|
+
systemCacheSegments
|
|
47376
|
+
}, this.getEffectiveProvider()), "Chat LLM comment-reminder-final");
|
|
47377
|
+
}
|
|
47378
|
+
}
|
|
47184
47379
|
const rawReply = sanitizeLLMReply(response.content);
|
|
47185
47380
|
const displayReply = stripCompletionMarker(rawReply);
|
|
47186
47381
|
const outputCheck = await this.guardrails.checkOutput(displayReply, { agentId: this.id });
|
|
@@ -47266,7 +47461,7 @@ ${chatYield.item.payload.content}`;
|
|
|
47266
47461
|
const userContent = await this.buildUserContent(userMessage, images, fileNames);
|
|
47267
47462
|
this.memory.appendMessage(this.currentSessionId, { role: "user", content: userContent });
|
|
47268
47463
|
const cognitiveContext = await this.prepareCognitiveContext("chat", effectiveMessage, senderId);
|
|
47269
|
-
const systemPrompt = await this.contextEngine.buildSystemPrompt({
|
|
47464
|
+
const { text: systemPrompt, segments: systemCacheSegments } = await this.contextEngine.buildSystemPrompt({
|
|
47270
47465
|
agentId: this.id,
|
|
47271
47466
|
agentName: this.config.name,
|
|
47272
47467
|
role: this.role,
|
|
@@ -47302,7 +47497,8 @@ ${chatYield.item.payload.content}`;
|
|
|
47302
47497
|
agentId: this.id,
|
|
47303
47498
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47304
47499
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47305
|
-
toolDefinitions: llmTools
|
|
47500
|
+
toolDefinitions: llmTools,
|
|
47501
|
+
systemCacheSegments
|
|
47306
47502
|
});
|
|
47307
47503
|
const messages = preparedStream.messages;
|
|
47308
47504
|
log17.debug("Context usage for stream", { usagePercent: preparedStream.usage.usagePercent });
|
|
@@ -47338,7 +47534,7 @@ ${chatYield.item.payload.content}`;
|
|
|
47338
47534
|
try {
|
|
47339
47535
|
this.checkDailyTokenBudget();
|
|
47340
47536
|
const llmStart = Date.now();
|
|
47341
|
-
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(this.currentSessionId), compaction: useCompaction }, wrappedOnEvent, this.getEffectiveProvider(), abortController.signal), "Stream LLM call", abortController.signal);
|
|
47537
|
+
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(this.currentSessionId), compaction: useCompaction, systemCacheSegments }, wrappedOnEvent, this.getEffectiveProvider(), abortController.signal), "Stream LLM call", abortController.signal);
|
|
47342
47538
|
streamMarkerDelta.flush();
|
|
47343
47539
|
const tokensThisCall = response.usage.inputTokens + response.usage.outputTokens;
|
|
47344
47540
|
this.updateTokensUsed(tokensThisCall);
|
|
@@ -47496,7 +47692,8 @@ ${streamYield.item.payload.content}`;
|
|
|
47496
47692
|
agentId: this.id,
|
|
47497
47693
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47498
47694
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47499
|
-
toolDefinitions: llmTools
|
|
47695
|
+
toolDefinitions: llmTools,
|
|
47696
|
+
systemCacheSegments
|
|
47500
47697
|
});
|
|
47501
47698
|
const updatedMessages = preparedCont.messages;
|
|
47502
47699
|
if (cancelToken?.cancelled) {
|
|
@@ -47515,7 +47712,7 @@ ${streamYield.item.payload.content}`;
|
|
|
47515
47712
|
return lastResponseContent || "";
|
|
47516
47713
|
}
|
|
47517
47714
|
const llmStart2 = Date.now();
|
|
47518
|
-
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages: updatedMessages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(this.currentSessionId), compaction: useCompaction }, wrappedOnEvent, this.getEffectiveProvider(), abortController.signal), "Stream LLM continuation", abortController.signal);
|
|
47715
|
+
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages: updatedMessages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(this.currentSessionId), compaction: useCompaction, systemCacheSegments }, wrappedOnEvent, this.getEffectiveProvider(), abortController.signal), "Stream LLM continuation", abortController.signal);
|
|
47519
47716
|
streamMarkerDelta.flush();
|
|
47520
47717
|
const tokens2 = response.usage.inputTokens + response.usage.outputTokens;
|
|
47521
47718
|
this.updateTokensUsed(tokens2);
|
|
@@ -47753,7 +47950,7 @@ ${streamYield.item.payload.content}`;
|
|
|
47753
47950
|
this.memory.appendMessage(sessionId, { role: "user", content: taskPrompt });
|
|
47754
47951
|
}
|
|
47755
47952
|
const cognitiveContext = await this.prepareCognitiveContext("task_execution", taskPrompt);
|
|
47756
|
-
const systemPrompt = await this.contextEngine.buildSystemPrompt({
|
|
47953
|
+
const { text: systemPrompt, segments: systemCacheSegments } = await this.contextEngine.buildSystemPrompt({
|
|
47757
47954
|
agentId: this.id,
|
|
47758
47955
|
agentName: this.config.name,
|
|
47759
47956
|
role: this.role,
|
|
@@ -47820,12 +48017,13 @@ ${streamYield.item.payload.content}`;
|
|
|
47820
48017
|
agentId: this.id,
|
|
47821
48018
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
47822
48019
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
47823
|
-
toolDefinitions: llmTools
|
|
48020
|
+
toolDefinitions: llmTools,
|
|
48021
|
+
systemCacheSegments
|
|
47824
48022
|
});
|
|
47825
48023
|
const messages = preparedTask.messages;
|
|
47826
48024
|
log17.debug("Context usage for task execution", { taskId: taskId2, usagePercent: preparedTask.usage.usagePercent, totalUsed: preparedTask.usage.totalUsed });
|
|
47827
48025
|
let taskLlmStart = Date.now();
|
|
47828
|
-
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction }, handleStreamEvent, this.getEffectiveProvider(), abortController.signal), "Task execution LLM call", abortController.signal);
|
|
48026
|
+
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction, systemCacheSegments }, handleStreamEvent, this.getEffectiveProvider(), abortController.signal), "Task execution LLM call", abortController.signal);
|
|
47829
48027
|
let taskLlmTokens = response.usage.inputTokens + response.usage.outputTokens;
|
|
47830
48028
|
this.updateTokensUsed(taskLlmTokens);
|
|
47831
48029
|
this.calibrateTokenCounter(response.usage.inputTokens);
|
|
@@ -48007,14 +48205,16 @@ ${yieldResult.item.payload.content}`
|
|
|
48007
48205
|
agentId: this.id,
|
|
48008
48206
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
48009
48207
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
48010
|
-
toolDefinitions: llmTools
|
|
48208
|
+
toolDefinitions: llmTools,
|
|
48209
|
+
systemCacheSegments
|
|
48011
48210
|
});
|
|
48012
48211
|
taskLlmStart = Date.now();
|
|
48013
48212
|
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({
|
|
48014
48213
|
messages: preparedTaskCont.messages,
|
|
48015
48214
|
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
48016
48215
|
metadata: this.getLLMMetadata(sessionId),
|
|
48017
|
-
compaction: useCompaction
|
|
48216
|
+
compaction: useCompaction,
|
|
48217
|
+
systemCacheSegments
|
|
48018
48218
|
}, handleStreamEvent, this.getEffectiveProvider(), abortController.signal), "Task execution LLM continuation", abortController.signal);
|
|
48019
48219
|
taskLlmTokens = response.usage.inputTokens + response.usage.outputTokens;
|
|
48020
48220
|
this.updateTokensUsed(taskLlmTokens);
|
|
@@ -48056,14 +48256,16 @@ ${yieldResult.item.payload.content}`
|
|
|
48056
48256
|
agentId: this.id,
|
|
48057
48257
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
48058
48258
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
48059
|
-
toolDefinitions: llmTools
|
|
48259
|
+
toolDefinitions: llmTools,
|
|
48260
|
+
systemCacheSegments
|
|
48060
48261
|
});
|
|
48061
48262
|
taskLlmStart = Date.now();
|
|
48062
48263
|
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({
|
|
48063
48264
|
messages: preparedFinal.messages,
|
|
48064
48265
|
tools: llmTools.length > 0 ? llmTools : void 0,
|
|
48065
48266
|
metadata: this.getLLMMetadata(sessionId),
|
|
48066
|
-
compaction: useCompaction
|
|
48267
|
+
compaction: useCompaction,
|
|
48268
|
+
systemCacheSegments
|
|
48067
48269
|
}, handleStreamEvent, this.getEffectiveProvider(), abortController.signal), "Task execution final submit reminder", abortController.signal);
|
|
48068
48270
|
taskLlmTokens = response.usage.inputTokens + response.usage.outputTokens;
|
|
48069
48271
|
this.updateTokensUsed(taskLlmTokens);
|
|
@@ -48187,7 +48389,7 @@ ${yieldResult.item.payload.content}`
|
|
|
48187
48389
|
this.memory.getOrCreateSession(this.id, sessionId);
|
|
48188
48390
|
this.memory.appendMessage(sessionId, { role: "user", content: userMessage });
|
|
48189
48391
|
const cognitiveContext = await this.prepareCognitiveContext("chat", userMessage);
|
|
48190
|
-
const systemPrompt = await this.contextEngine.buildSystemPrompt({
|
|
48392
|
+
const { text: systemPrompt, segments: systemCacheSegments } = await this.contextEngine.buildSystemPrompt({
|
|
48191
48393
|
agentId: this.id,
|
|
48192
48394
|
agentName: this.config.name,
|
|
48193
48395
|
role: this.role,
|
|
@@ -48248,11 +48450,12 @@ ${yieldResult.item.payload.content}`
|
|
|
48248
48450
|
agentId: this.id,
|
|
48249
48451
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
48250
48452
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
48251
|
-
toolDefinitions: llmTools
|
|
48453
|
+
toolDefinitions: llmTools,
|
|
48454
|
+
systemCacheSegments
|
|
48252
48455
|
});
|
|
48253
48456
|
const messages = prepared.messages;
|
|
48254
48457
|
let risLlmStart = Date.now();
|
|
48255
|
-
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction }, handleStreamEvent, this.getEffectiveProvider()), "RespondInSession LLM call");
|
|
48458
|
+
let response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction, systemCacheSegments }, handleStreamEvent, this.getEffectiveProvider()), "RespondInSession LLM call");
|
|
48256
48459
|
let risTokens = response.usage.inputTokens + response.usage.outputTokens;
|
|
48257
48460
|
this.updateTokensUsed(risTokens);
|
|
48258
48461
|
this.calibrateTokenCounter(response.usage.inputTokens);
|
|
@@ -48310,10 +48513,11 @@ ${yieldResult.item.payload.content}`
|
|
|
48310
48513
|
agentId: this.id,
|
|
48311
48514
|
modelContextWindow: this.llmRouter.getModelContextWindow(this.getEffectiveProvider()),
|
|
48312
48515
|
modelMaxOutput: this.llmRouter.getModelMaxOutput(this.getEffectiveProvider()),
|
|
48313
|
-
toolDefinitions: llmTools
|
|
48516
|
+
toolDefinitions: llmTools,
|
|
48517
|
+
systemCacheSegments
|
|
48314
48518
|
});
|
|
48315
48519
|
risLlmStart = Date.now();
|
|
48316
|
-
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages: preparedCont.messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction }, handleStreamEvent, this.getEffectiveProvider()), "RespondInSession LLM continuation");
|
|
48520
|
+
response = await this.withNetworkRetry(() => this.llmRouter.chatStream({ messages: preparedCont.messages, tools: llmTools.length > 0 ? llmTools : void 0, metadata: this.getLLMMetadata(sessionId), compaction: useCompaction, systemCacheSegments }, handleStreamEvent, this.getEffectiveProvider()), "RespondInSession LLM continuation");
|
|
48317
48521
|
risTokens = response.usage.inputTokens + response.usage.outputTokens;
|
|
48318
48522
|
this.updateTokensUsed(risTokens);
|
|
48319
48523
|
this.calibrateTokenCounter(response.usage.inputTokens);
|
|
@@ -48973,8 +49177,8 @@ ${todayLog.slice(0, HEARTBEAT_DAILY_LOG_CHARS)}
|
|
|
48973
49177
|
"- Common sections: `procedures`, `conventions`, `preferences`, `domain-knowledge`.",
|
|
48974
49178
|
"",
|
|
48975
49179
|
"**Shareable skills** (for team-wide practices):",
|
|
48976
|
-
'- Check existing skills first: `discover_tools({ mode: "list_skills" })` and `
|
|
48977
|
-
"- To update an existing skill: edit files in `~/.markus/builder-artifacts/skills/{name}/`, bump version, re-install with `
|
|
49180
|
+
'- Check existing skills first: `discover_tools({ mode: "list_skills" })` and `package_list`.',
|
|
49181
|
+
"- To update an existing skill: edit files in `~/.markus/builder-artifacts/skills/{name}/`, bump version, re-install with `package_install`.",
|
|
48978
49182
|
"",
|
|
48979
49183
|
"**Direct self-evolution** (simplest and most impactful):",
|
|
48980
49184
|
"- **Update ROLE.md** \u2014 When you discover a behavioral rule, working style, or guiding principle that should always apply, append it to your ROLE.md via `file_edit`. ROLE.md is loaded into every conversation, so changes take effect immediately. Read first, then append. No need to accumulate 3 insights \u2014 even a single validated lesson can warrant a role update if it is fundamental.",
|
|
@@ -48986,7 +49190,7 @@ ${todayLog.slice(0, HEARTBEAT_DAILY_LOG_CHARS)}
|
|
|
48986
49190
|
'| Single insight / gotcha | `memory_save` with tags: `["insight"]` |',
|
|
48987
49191
|
'| Tool tip or preference | `memory_save` with tags: `["insight", "tool:<name>"]` |',
|
|
48988
49192
|
'| Multi-step repeatable workflow | `memory_update_longterm({ section: "procedures", mode: "patch" })` |',
|
|
48989
|
-
"| Practice worth sharing with the team | Create skill via **skill-building**, then install with `
|
|
49193
|
+
"| Practice worth sharing with the team | Create skill via **skill-building**, then install with `package_install` |",
|
|
48990
49194
|
"| Behavioral rule or guiding principle | Update ROLE.md (`file_read` \u2192 `file_edit` to append) |",
|
|
48991
49195
|
"| New recurring check for your patrol | Update HEARTBEAT.md (`file_read` \u2192 `file_edit`) |",
|
|
48992
49196
|
"",
|
|
@@ -49092,10 +49296,12 @@ ${todayLog.slice(0, HEARTBEAT_DAILY_LOG_CHARS)}
|
|
|
49092
49296
|
"discover_tools",
|
|
49093
49297
|
"notify_user",
|
|
49094
49298
|
"request_user_approval",
|
|
49095
|
-
"recall_activity"
|
|
49299
|
+
"recall_activity",
|
|
49300
|
+
"builder_install",
|
|
49301
|
+
"builder_list"
|
|
49096
49302
|
];
|
|
49097
49303
|
if (isManager) {
|
|
49098
|
-
baseTools.push("task_board_health", "task_cleanup_duplicates", "task_assign", "team_status", "deliverable_create", "deliverable_search", "
|
|
49304
|
+
baseTools.push("task_board_health", "task_cleanup_duplicates", "task_assign", "team_status", "deliverable_create", "deliverable_search", "package_install", "package_list");
|
|
49099
49305
|
}
|
|
49100
49306
|
const HEARTBEAT_ALLOWED_TOOLS = new Set(baseTools);
|
|
49101
49307
|
const HEARTBEAT_MAX_RETRIES = 3;
|
|
@@ -50245,6 +50451,73 @@ var init_browser_session = __esm({
|
|
|
50245
50451
|
});
|
|
50246
50452
|
|
|
50247
50453
|
// ../core/dist/tools/manager.js
|
|
50454
|
+
function createBuilderTools(ctx) {
|
|
50455
|
+
return [
|
|
50456
|
+
...ctx.listArtifacts ? [
|
|
50457
|
+
{
|
|
50458
|
+
name: "builder_list",
|
|
50459
|
+
description: "List builder artifacts (custom-created or Hub-downloaded agent/team/skill packages). These can be installed with builder_install.",
|
|
50460
|
+
inputSchema: {
|
|
50461
|
+
type: "object",
|
|
50462
|
+
properties: {
|
|
50463
|
+
type: {
|
|
50464
|
+
type: "string",
|
|
50465
|
+
enum: ["agent", "team", "skill"],
|
|
50466
|
+
description: "Filter by artifact type (optional)"
|
|
50467
|
+
}
|
|
50468
|
+
}
|
|
50469
|
+
},
|
|
50470
|
+
async execute(args) {
|
|
50471
|
+
try {
|
|
50472
|
+
const artifacts = ctx.listArtifacts(args["type"]);
|
|
50473
|
+
return JSON.stringify({ artifacts, count: artifacts.length });
|
|
50474
|
+
} catch (error) {
|
|
50475
|
+
return JSON.stringify({ status: "error", error: String(error) });
|
|
50476
|
+
}
|
|
50477
|
+
}
|
|
50478
|
+
}
|
|
50479
|
+
] : [],
|
|
50480
|
+
...ctx.installArtifact ? [
|
|
50481
|
+
{
|
|
50482
|
+
name: "builder_install",
|
|
50483
|
+
description: "Install a builder artifact \u2014 deploys an agent, team, or skill package into the live organization. For agents/teams: after installation, onboard with project context and assign initial tasks.",
|
|
50484
|
+
inputSchema: {
|
|
50485
|
+
type: "object",
|
|
50486
|
+
properties: {
|
|
50487
|
+
type: {
|
|
50488
|
+
type: "string",
|
|
50489
|
+
enum: ["agent", "team", "skill"],
|
|
50490
|
+
description: "Artifact type"
|
|
50491
|
+
},
|
|
50492
|
+
name: { type: "string", description: "Artifact name (from builder_list)" }
|
|
50493
|
+
},
|
|
50494
|
+
required: ["type", "name"]
|
|
50495
|
+
},
|
|
50496
|
+
async execute(args) {
|
|
50497
|
+
try {
|
|
50498
|
+
const type = args["type"]?.trim();
|
|
50499
|
+
const name = args["name"]?.trim();
|
|
50500
|
+
if (!type || !["agent", "team", "skill"].includes(type))
|
|
50501
|
+
return JSON.stringify({ status: "error", error: "type is required and must be one of: agent, team, skill" });
|
|
50502
|
+
if (!name)
|
|
50503
|
+
return JSON.stringify({ status: "error", error: "name is required \u2014 provide the artifact name from builder_list" });
|
|
50504
|
+
const result = await ctx.installArtifact(type, name);
|
|
50505
|
+
const isAgentOrTeam = result.type === "agent" || result.type === "team";
|
|
50506
|
+
return JSON.stringify({
|
|
50507
|
+
status: "success",
|
|
50508
|
+
...result,
|
|
50509
|
+
...isAgentOrTeam ? {
|
|
50510
|
+
next_steps: "Installed successfully. Next: onboard new agent(s) with project context via agent_send_message, then assign initial tasks via task_create."
|
|
50511
|
+
} : {}
|
|
50512
|
+
});
|
|
50513
|
+
} catch (error) {
|
|
50514
|
+
return JSON.stringify({ status: "error", error: String(error) });
|
|
50515
|
+
}
|
|
50516
|
+
}
|
|
50517
|
+
}
|
|
50518
|
+
] : []
|
|
50519
|
+
];
|
|
50520
|
+
}
|
|
50248
50521
|
function createManagerTools(ctx) {
|
|
50249
50522
|
return [
|
|
50250
50523
|
{
|
|
@@ -50363,79 +50636,34 @@ function createManagerTools(ctx) {
|
|
|
50363
50636
|
}
|
|
50364
50637
|
}
|
|
50365
50638
|
] : [],
|
|
50366
|
-
...ctx.listTemplates ? [
|
|
50367
|
-
{
|
|
50368
|
-
name: "team_list_templates",
|
|
50369
|
-
description: "List available agent templates that can be hired. Each template has a role, description, and category.",
|
|
50370
|
-
inputSchema: {
|
|
50371
|
-
type: "object",
|
|
50372
|
-
properties: {}
|
|
50373
|
-
},
|
|
50374
|
-
async execute() {
|
|
50375
|
-
try {
|
|
50376
|
-
const templates = ctx.listTemplates();
|
|
50377
|
-
return JSON.stringify({ templates, count: templates.length });
|
|
50378
|
-
} catch (error) {
|
|
50379
|
-
return JSON.stringify({ status: "error", error: String(error) });
|
|
50380
|
-
}
|
|
50381
|
-
}
|
|
50382
|
-
}
|
|
50383
|
-
] : [],
|
|
50384
|
-
...ctx.hireFromTemplate ? [
|
|
50385
|
-
{
|
|
50386
|
-
name: "team_hire_agent",
|
|
50387
|
-
description: "Hire a new agent from a template and add them to your team. After hiring, onboard the agent: send a welcome message with project context via agent_send_message, then assign initial tasks via task_create.",
|
|
50388
|
-
inputSchema: {
|
|
50389
|
-
type: "object",
|
|
50390
|
-
properties: {
|
|
50391
|
-
template_id: { type: "string", description: "Template ID (from team_list_templates)" },
|
|
50392
|
-
name: { type: "string", description: "Display name for the new agent" },
|
|
50393
|
-
skills: {
|
|
50394
|
-
type: "array",
|
|
50395
|
-
items: { type: "string" },
|
|
50396
|
-
description: "Optional skill IDs to assign"
|
|
50397
|
-
}
|
|
50398
|
-
},
|
|
50399
|
-
required: ["template_id", "name"]
|
|
50400
|
-
},
|
|
50401
|
-
async execute(args) {
|
|
50402
|
-
try {
|
|
50403
|
-
const templateId = args["template_id"]?.trim();
|
|
50404
|
-
const name = args["name"]?.trim();
|
|
50405
|
-
if (!templateId)
|
|
50406
|
-
return JSON.stringify({ status: "error", error: "template_id is required" });
|
|
50407
|
-
if (!name)
|
|
50408
|
-
return JSON.stringify({ status: "error", error: "name is required \u2014 please provide a display name for the new agent" });
|
|
50409
|
-
const result = await ctx.hireFromTemplate(templateId, name, args["skills"]);
|
|
50410
|
-
return JSON.stringify({
|
|
50411
|
-
status: "success",
|
|
50412
|
-
agent: result,
|
|
50413
|
-
next_steps: "Agent created and started. Next: onboard them with project context via agent_send_message, then assign initial tasks via task_create."
|
|
50414
|
-
});
|
|
50415
|
-
} catch (error) {
|
|
50416
|
-
return JSON.stringify({ status: "error", error: String(error) });
|
|
50417
|
-
}
|
|
50418
|
-
}
|
|
50419
|
-
}
|
|
50420
|
-
] : [],
|
|
50421
50639
|
...ctx.listArtifacts ? [
|
|
50422
50640
|
{
|
|
50423
|
-
name: "
|
|
50424
|
-
description:
|
|
50641
|
+
name: "package_list",
|
|
50642
|
+
description: 'List all available packages. type "agent": built-in roles (developer, content-writer, etc.) and custom agent packages. type "team": team templates (content-team, research-lab, etc.). type "skill": skill packages. Omit type to list all. Install with package_install. To find more online, use hub_search.',
|
|
50425
50643
|
inputSchema: {
|
|
50426
50644
|
type: "object",
|
|
50427
50645
|
properties: {
|
|
50428
50646
|
type: {
|
|
50429
50647
|
type: "string",
|
|
50430
50648
|
enum: ["agent", "team", "skill"],
|
|
50431
|
-
description: "Filter by
|
|
50649
|
+
description: "Filter by type (optional). Omit to list all."
|
|
50432
50650
|
}
|
|
50433
50651
|
}
|
|
50434
50652
|
},
|
|
50435
50653
|
async execute(args) {
|
|
50436
50654
|
try {
|
|
50437
|
-
const
|
|
50438
|
-
|
|
50655
|
+
const type = args["type"];
|
|
50656
|
+
const artifacts = ctx.listArtifacts(type);
|
|
50657
|
+
const roles = (!type || type === "agent") && ctx.listTemplates ? ctx.listTemplates() : [];
|
|
50658
|
+
const roleItems = roles.map((r) => ({
|
|
50659
|
+
type: "agent",
|
|
50660
|
+
source: "role",
|
|
50661
|
+
name: r.id ?? r.name,
|
|
50662
|
+
description: r.description ?? r.name,
|
|
50663
|
+
...r
|
|
50664
|
+
}));
|
|
50665
|
+
const items = [...roleItems, ...artifacts];
|
|
50666
|
+
return JSON.stringify({ items, count: items.length });
|
|
50439
50667
|
} catch (error) {
|
|
50440
50668
|
return JSON.stringify({ status: "error", error: String(error) });
|
|
50441
50669
|
}
|
|
@@ -50507,17 +50735,23 @@ function createManagerTools(ctx) {
|
|
|
50507
50735
|
] : [],
|
|
50508
50736
|
...ctx.installArtifact ? [
|
|
50509
50737
|
{
|
|
50510
|
-
name: "
|
|
50511
|
-
description:
|
|
50738
|
+
name: "package_install",
|
|
50739
|
+
description: 'Install a package into the live organization. type "agent": hire/install an agent (from a built-in role or a custom package). type "team": deploy a full team with all members, norms, and starter tasks. type "skill": install a skill package. Use package_list to see what is available.',
|
|
50512
50740
|
inputSchema: {
|
|
50513
50741
|
type: "object",
|
|
50514
50742
|
properties: {
|
|
50515
50743
|
type: {
|
|
50516
50744
|
type: "string",
|
|
50517
50745
|
enum: ["agent", "team", "skill"],
|
|
50518
|
-
description: "
|
|
50746
|
+
description: "Package type"
|
|
50519
50747
|
},
|
|
50520
|
-
name: { type: "string", description: "
|
|
50748
|
+
name: { type: "string", description: "Package name (from package_list)" },
|
|
50749
|
+
agent_name: { type: "string", description: 'Display name for the new agent (required when installing from a built-in role, e.g. "developer")' },
|
|
50750
|
+
skills: {
|
|
50751
|
+
type: "array",
|
|
50752
|
+
items: { type: "string" },
|
|
50753
|
+
description: "Optional skill IDs to assign to the new agent"
|
|
50754
|
+
}
|
|
50521
50755
|
},
|
|
50522
50756
|
required: ["type", "name"]
|
|
50523
50757
|
},
|
|
@@ -50528,13 +50762,36 @@ function createManagerTools(ctx) {
|
|
|
50528
50762
|
if (!type || !["agent", "team", "skill"].includes(type))
|
|
50529
50763
|
return JSON.stringify({ status: "error", error: "type is required and must be one of: agent, team, skill" });
|
|
50530
50764
|
if (!name)
|
|
50531
|
-
return JSON.stringify({ status: "error", error: "name is required \u2014
|
|
50765
|
+
return JSON.stringify({ status: "error", error: "name is required \u2014 use package_list to see available packages" });
|
|
50766
|
+
if (type === "agent") {
|
|
50767
|
+
try {
|
|
50768
|
+
const result2 = await ctx.installArtifact(type, name);
|
|
50769
|
+
return JSON.stringify({
|
|
50770
|
+
status: "success",
|
|
50771
|
+
...result2,
|
|
50772
|
+
next_steps: "Installed successfully. Next: onboard new agent with project context via agent_send_message, then assign tasks via task_create."
|
|
50773
|
+
});
|
|
50774
|
+
} catch {
|
|
50775
|
+
if (ctx.hireFromTemplate) {
|
|
50776
|
+
const agentName = args["agent_name"]?.trim();
|
|
50777
|
+
if (!agentName)
|
|
50778
|
+
return JSON.stringify({ status: "error", error: "agent_name is required when installing from a built-in role \u2014 provide a display name for the new agent" });
|
|
50779
|
+
const result2 = await ctx.hireFromTemplate(name, agentName, args["skills"]);
|
|
50780
|
+
return JSON.stringify({
|
|
50781
|
+
status: "success",
|
|
50782
|
+
type: "agent",
|
|
50783
|
+
agent: result2,
|
|
50784
|
+
next_steps: "Agent hired and started. Next: onboard with project context via agent_send_message, then assign tasks via task_create."
|
|
50785
|
+
});
|
|
50786
|
+
}
|
|
50787
|
+
throw new Error(`Agent package not found: ${name}. Use package_list to see available packages.`);
|
|
50788
|
+
}
|
|
50789
|
+
}
|
|
50532
50790
|
const result = await ctx.installArtifact(type, name);
|
|
50533
|
-
const isAgentOrTeam = result.type === "agent" || result.type === "team";
|
|
50534
50791
|
return JSON.stringify({
|
|
50535
50792
|
status: "success",
|
|
50536
50793
|
...result,
|
|
50537
|
-
...
|
|
50794
|
+
...type === "team" ? {
|
|
50538
50795
|
next_steps: "Installed successfully. Next: onboard new agent(s) with project context via agent_send_message, then assign initial tasks via task_create."
|
|
50539
50796
|
} : {}
|
|
50540
50797
|
});
|
|
@@ -50679,14 +50936,40 @@ function createA2ATools(ctx) {
|
|
|
50679
50936
|
},
|
|
50680
50937
|
{
|
|
50681
50938
|
name: "agent_list_colleagues",
|
|
50682
|
-
description: "List all other agents in your organization
|
|
50939
|
+
description: "List all other agents in your organization grouped by team. Shows team structure, roles, skills, and current status.",
|
|
50683
50940
|
inputSchema: {
|
|
50684
50941
|
type: "object",
|
|
50685
50942
|
properties: {}
|
|
50686
50943
|
},
|
|
50687
50944
|
async execute() {
|
|
50688
50945
|
const colleagues = ctx.listColleagues().filter((a) => a.id !== ctx.selfId);
|
|
50689
|
-
|
|
50946
|
+
const byTeam = /* @__PURE__ */ new Map();
|
|
50947
|
+
for (const c of colleagues) {
|
|
50948
|
+
const key2 = c.teamId ?? "__ungrouped__";
|
|
50949
|
+
if (!byTeam.has(key2))
|
|
50950
|
+
byTeam.set(key2, []);
|
|
50951
|
+
byTeam.get(key2).push(c);
|
|
50952
|
+
}
|
|
50953
|
+
const lines = [];
|
|
50954
|
+
lines.push(`Organization colleagues: ${colleagues.length} agents
|
|
50955
|
+
`);
|
|
50956
|
+
for (const [teamId, members] of byTeam) {
|
|
50957
|
+
const manager = members.find((m) => m.agentRole === "manager");
|
|
50958
|
+
const teamLabel = members[0]?.teamName ?? teamId;
|
|
50959
|
+
if (teamId === "__ungrouped__") {
|
|
50960
|
+
lines.push(`\u2500\u2500 Ungrouped \u2500\u2500`);
|
|
50961
|
+
} else {
|
|
50962
|
+
lines.push(`\u2500\u2500 Team: ${teamLabel}${manager ? ` (manager: ${manager.name})` : ""} \u2500\u2500`);
|
|
50963
|
+
}
|
|
50964
|
+
const sorted = [...members].sort((a, b) => a.agentRole === "manager" ? -1 : b.agentRole === "manager" ? 1 : 0);
|
|
50965
|
+
for (const m of sorted) {
|
|
50966
|
+
const badge = m.agentRole === "manager" ? " [Manager]" : "";
|
|
50967
|
+
const skills = m.skills?.length ? ` | skills: ${m.skills.join(", ")}` : "";
|
|
50968
|
+
lines.push(` \u2022 ${m.name} (${m.id})${badge} \u2014 ${m.role} | ${m.status}${skills}`);
|
|
50969
|
+
}
|
|
50970
|
+
lines.push("");
|
|
50971
|
+
}
|
|
50972
|
+
return lines.join("\n");
|
|
50690
50973
|
}
|
|
50691
50974
|
},
|
|
50692
50975
|
...ctx.sendGroupMessage ? [{
|
|
@@ -54479,6 +54762,14 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
54479
54762
|
agent.registerTool(tool);
|
|
54480
54763
|
}
|
|
54481
54764
|
}
|
|
54765
|
+
if (this.builderService) {
|
|
54766
|
+
const builderTools = createBuilderTools({
|
|
54767
|
+
installArtifact: (type, name) => this.builderService.installArtifact(type, name),
|
|
54768
|
+
listArtifacts: (type) => this.builderService.listArtifacts(type)
|
|
54769
|
+
});
|
|
54770
|
+
for (const tool of builderTools)
|
|
54771
|
+
agent.registerTool(tool);
|
|
54772
|
+
}
|
|
54482
54773
|
const mcpConfigs = request.mcpServers ?? this.globalMcpServers;
|
|
54483
54774
|
if (mcpConfigs) {
|
|
54484
54775
|
for (const [serverName, serverConfig] of Object.entries(mcpConfigs)) {
|
|
@@ -55040,6 +55331,14 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
55040
55331
|
agent.registerTool(tool);
|
|
55041
55332
|
}
|
|
55042
55333
|
}
|
|
55334
|
+
if (this.builderService) {
|
|
55335
|
+
const builderTools = createBuilderTools({
|
|
55336
|
+
installArtifact: (type, name) => this.builderService.installArtifact(type, name),
|
|
55337
|
+
listArtifacts: (type) => this.builderService.listArtifacts(type)
|
|
55338
|
+
});
|
|
55339
|
+
for (const tool of builderTools)
|
|
55340
|
+
agent.registerTool(tool);
|
|
55341
|
+
}
|
|
55043
55342
|
if (this.agentAuditCallback) {
|
|
55044
55343
|
const cb = this.agentAuditCallback;
|
|
55045
55344
|
agent.setAuditCallback((event) => cb(id, event));
|
|
@@ -55266,6 +55565,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
55266
55565
|
skills: a.config.skills,
|
|
55267
55566
|
activeTaskCount: state.activeTaskCount ?? 0,
|
|
55268
55567
|
teamId: a.config.teamId,
|
|
55568
|
+
teamName: a.getTeamName(),
|
|
55269
55569
|
lastError: state.lastError,
|
|
55270
55570
|
lastErrorAt: state.lastErrorAt,
|
|
55271
55571
|
currentTaskId: state.currentTaskId,
|
|
@@ -55687,8 +55987,9 @@ var init_anthropic = __esm({
|
|
|
55687
55987
|
max_tokens: request.maxTokens ?? this.maxTokens,
|
|
55688
55988
|
messages
|
|
55689
55989
|
};
|
|
55690
|
-
if (systemMsg)
|
|
55691
|
-
body["system"] = getTextContent(systemMsg.content);
|
|
55990
|
+
if (systemMsg) {
|
|
55991
|
+
body["system"] = this.buildSystemContent(getTextContent(systemMsg.content), request.systemCacheSegments);
|
|
55992
|
+
}
|
|
55692
55993
|
if (request.temperature !== void 0)
|
|
55693
55994
|
body["temperature"] = request.temperature;
|
|
55694
55995
|
if (request.stopSequences?.length)
|
|
@@ -55728,8 +56029,9 @@ var init_anthropic = __esm({
|
|
|
55728
56029
|
messages,
|
|
55729
56030
|
stream: true
|
|
55730
56031
|
};
|
|
55731
|
-
if (systemMsg)
|
|
55732
|
-
body["system"] = getTextContent(systemMsg.content);
|
|
56032
|
+
if (systemMsg) {
|
|
56033
|
+
body["system"] = this.buildSystemContent(getTextContent(systemMsg.content), request.systemCacheSegments);
|
|
56034
|
+
}
|
|
55733
56035
|
if (request.temperature !== void 0)
|
|
55734
56036
|
body["temperature"] = request.temperature;
|
|
55735
56037
|
if (request.stopSequences?.length)
|
|
@@ -55914,6 +56216,21 @@ var init_anthropic = __esm({
|
|
|
55914
56216
|
isCompactionSupported() {
|
|
55915
56217
|
return this.model.startsWith("claude-opus-4") || this.model.startsWith("claude-sonnet-4");
|
|
55916
56218
|
}
|
|
56219
|
+
/**
|
|
56220
|
+
* Build the `system` field for the Anthropic API. When structured cache
|
|
56221
|
+
* segments are provided, returns an array of content blocks with
|
|
56222
|
+
* `cache_control` breakpoints so the API can cache stable prefixes.
|
|
56223
|
+
* Falls back to a plain string when no segments are available.
|
|
56224
|
+
*/
|
|
56225
|
+
buildSystemContent(plainText, segments) {
|
|
56226
|
+
if (!segments || segments.length <= 1)
|
|
56227
|
+
return plainText;
|
|
56228
|
+
return segments.filter((s) => s.content.length > 0).map((s) => ({
|
|
56229
|
+
type: "text",
|
|
56230
|
+
text: s.content,
|
|
56231
|
+
...s.cacheBreakpoint ? { cache_control: { type: "ephemeral" } } : {}
|
|
56232
|
+
}));
|
|
56233
|
+
}
|
|
55917
56234
|
convertResponse(data) {
|
|
55918
56235
|
let content = "";
|
|
55919
56236
|
let compactionContent;
|
|
@@ -57239,6 +57556,13 @@ var init_oauth_manager = __esm({
|
|
|
57239
57556
|
});
|
|
57240
57557
|
|
|
57241
57558
|
// ../core/dist/llm/router.js
|
|
57559
|
+
function maskApiKey(key2) {
|
|
57560
|
+
if (!key2)
|
|
57561
|
+
return void 0;
|
|
57562
|
+
if (key2.length <= 8)
|
|
57563
|
+
return "****";
|
|
57564
|
+
return key2.slice(0, 4) + "..." + key2.slice(-4);
|
|
57565
|
+
}
|
|
57242
57566
|
function buildTiers(providerNames, defaultProvider) {
|
|
57243
57567
|
const tiers = [];
|
|
57244
57568
|
if (providerNames.includes(defaultProvider)) {
|
|
@@ -57917,6 +58241,8 @@ var init_router = __esm({
|
|
|
57917
58241
|
const builtinModels = BUILTIN_MODEL_CATALOG.filter((m) => m.provider === name);
|
|
57918
58242
|
const customCatalogModels = this.customModelCatalog.get(name) ?? [];
|
|
57919
58243
|
const mergedModels = [...builtinModels, ...customCatalogModels.filter((cm) => !builtinModels.some((bm) => bm.id === cm.id))];
|
|
58244
|
+
const rawKey = p.apiKey ?? "";
|
|
58245
|
+
const keySource = oauthProfile?.authType === "oauth" ? "oauth" : rawKey ? "config" : void 0;
|
|
57920
58246
|
providers[name] = {
|
|
57921
58247
|
name,
|
|
57922
58248
|
displayName: PROVIDER_DISPLAY_NAMES[name] ?? name,
|
|
@@ -57924,6 +58250,8 @@ var init_router = __esm({
|
|
|
57924
58250
|
baseUrl: p.baseUrl,
|
|
57925
58251
|
configured: true,
|
|
57926
58252
|
enabled: this.isProviderEnabled(name),
|
|
58253
|
+
apiKeyPreview: maskApiKey(rawKey),
|
|
58254
|
+
apiKeySource: keySource,
|
|
57927
58255
|
contextWindow: customModels?.contextWindow ?? modelDef?.contextWindow,
|
|
57928
58256
|
maxOutputTokens: customModels?.maxOutputTokens ?? modelDef?.maxOutputTokens,
|
|
57929
58257
|
cost: customModels?.cost ?? modelDef?.cost,
|
|
@@ -59999,11 +60327,13 @@ function loadTeamTemplateFromDir(dirPath) {
|
|
|
59999
60327
|
name: m.name,
|
|
60000
60328
|
count: m.count,
|
|
60001
60329
|
role: m.role,
|
|
60330
|
+
description: m.description,
|
|
60002
60331
|
skills: m.skills ?? []
|
|
60003
60332
|
})),
|
|
60004
60333
|
tags: manifest.tags ?? [],
|
|
60005
60334
|
category: manifest.category,
|
|
60006
60335
|
icon: manifest.icon,
|
|
60336
|
+
starterTasks: manifest.starterTasks,
|
|
60007
60337
|
announcements: existsSync21(annPath) ? readFileSync16(annPath, "utf-8") : void 0,
|
|
60008
60338
|
norms: existsSync21(normsPath) ? readFileSync16(normsPath, "utf-8") : void 0,
|
|
60009
60339
|
i18n: manifest.i18n
|
|
@@ -60226,6 +60556,34 @@ var init_org_service = __esm({
|
|
|
60226
60556
|
listHumanUsers(orgId2) {
|
|
60227
60557
|
return [...this.humans.values()].filter((h) => h.orgId === orgId2);
|
|
60228
60558
|
}
|
|
60559
|
+
/**
|
|
60560
|
+
* Update (or insert) a user's in-memory identity without touching the DB.
|
|
60561
|
+
* Safe to call from auth endpoints that already persisted DB changes.
|
|
60562
|
+
* Never throws — logs warnings on failure.
|
|
60563
|
+
*/
|
|
60564
|
+
syncHumanIdentity(userId2, orgId2, name, role, email) {
|
|
60565
|
+
try {
|
|
60566
|
+
const existing = this.humans.get(userId2);
|
|
60567
|
+
if (existing) {
|
|
60568
|
+
existing.name = name;
|
|
60569
|
+
if (email !== void 0)
|
|
60570
|
+
existing.email = email;
|
|
60571
|
+
existing.role = role;
|
|
60572
|
+
} else {
|
|
60573
|
+
this.humans.set(userId2, {
|
|
60574
|
+
id: userId2,
|
|
60575
|
+
name,
|
|
60576
|
+
email,
|
|
60577
|
+
role,
|
|
60578
|
+
orgId: orgId2,
|
|
60579
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
60580
|
+
});
|
|
60581
|
+
}
|
|
60582
|
+
this.refreshIdentityContextsForOrg(orgId2);
|
|
60583
|
+
} catch (err) {
|
|
60584
|
+
log49.warn("syncHumanIdentity failed (non-fatal)", { userId: userId2, error: String(err) });
|
|
60585
|
+
}
|
|
60586
|
+
}
|
|
60229
60587
|
updateHumanUser(userId2, updates) {
|
|
60230
60588
|
const user = this.humans.get(userId2);
|
|
60231
60589
|
if (!user)
|
|
@@ -61303,10 +61661,12 @@ var init_task_service = __esm({
|
|
|
61303
61661
|
}
|
|
61304
61662
|
}
|
|
61305
61663
|
if (!isReviewerDuringReview) {
|
|
61306
|
-
|
|
61664
|
+
const terminalStatuses = /* @__PURE__ */ new Set(["completed", "accepted", "archived"]);
|
|
61665
|
+
const handledByInjection = task?.status === "in_progress" || task?.status && terminalStatuses.has(task.status);
|
|
61666
|
+
if (task?.assignedAgentId && !handledByInjection) {
|
|
61307
61667
|
enqueueFor(task.assignedAgentId, "task_comment", `New comment from ${authorName} on your assigned task`);
|
|
61308
61668
|
}
|
|
61309
|
-
if (task?.createdBy &&
|
|
61669
|
+
if (task?.createdBy && !handledByInjection) {
|
|
61310
61670
|
enqueueFor(task.createdBy, "task_comment", `New comment from ${authorName} on a task you created`);
|
|
61311
61671
|
}
|
|
61312
61672
|
}
|
|
@@ -62540,7 +62900,7 @@ ${c.content}`;
|
|
|
62540
62900
|
type: "custom",
|
|
62541
62901
|
title: task.title,
|
|
62542
62902
|
description: `Agent "${creatorName}" wants to create task "${task.title}" (priority: ${task.priority}).`,
|
|
62543
|
-
details: { taskId: task.id, priority: task.priority, subType: "task" }
|
|
62903
|
+
details: { taskId: task.id, taskTitle: task.title, priority: task.priority, subType: "task" }
|
|
62544
62904
|
}).then((result) => {
|
|
62545
62905
|
const current = this.tasks.get(task.id);
|
|
62546
62906
|
if (!current || current.status !== "pending")
|
|
@@ -62779,6 +63139,12 @@ ${c.content}`;
|
|
|
62779
63139
|
if (from === "review" && to !== "review") {
|
|
62780
63140
|
this.activeReviews.delete(taskId2);
|
|
62781
63141
|
}
|
|
63142
|
+
if (TERMINAL_STATUSES.has(to) && this.hitlService) {
|
|
63143
|
+
const cancelled = this.hitlService.cancelApprovalsByDetail("taskId", taskId2, "system", `Task ${to}`);
|
|
63144
|
+
if (cancelled > 0) {
|
|
63145
|
+
log50.info(`Cancelled ${cancelled} pending approval(s) for task ${taskId2} (status \u2192 ${to})`);
|
|
63146
|
+
}
|
|
63147
|
+
}
|
|
62782
63148
|
}
|
|
62783
63149
|
// ─── Stage 2: DB persistence ─────────────────────────────────────────────────
|
|
62784
63150
|
persistStatusChange(id, status, updatedBy) {
|
|
@@ -62834,6 +63200,7 @@ ${deliverablesSummary}` : ""
|
|
|
62834
63200
|
type: "custom",
|
|
62835
63201
|
title: `Review: ${task.title}`,
|
|
62836
63202
|
description,
|
|
63203
|
+
details: { taskId: task.id, taskTitle: task.title, subType: "task_review" },
|
|
62837
63204
|
targetUserId: task.reviewerId,
|
|
62838
63205
|
options: [
|
|
62839
63206
|
{ id: "approve", label: "Approve" },
|
|
@@ -63862,7 +64229,7 @@ Action: ${guidance}` : ""
|
|
|
63862
64229
|
"",
|
|
63863
64230
|
'Save each lesson using `memory_save` with tags `["lesson", ...]`.',
|
|
63864
64231
|
'If it is a repeatable multi-step procedure, promote to SOP via `memory_update_longterm({ section: "sops", mode: "patch" })`.',
|
|
63865
|
-
"If the best practice would benefit other agents on the team, create a shareable skill via **skill-building** and install it with `
|
|
64232
|
+
"If the best practice would benefit other agents on the team, create a shareable skill via **skill-building** and install it with `package_install`.",
|
|
63866
64233
|
"",
|
|
63867
64234
|
"**Direct self-evolution** \u2014 consider the simplest, most impactful options:",
|
|
63868
64235
|
"- If this lesson reveals a behavioral rule that should always guide your work, append it to your ROLE.md via `file_edit`.",
|
|
@@ -63882,7 +64249,7 @@ Action: ${guidance}` : ""
|
|
|
63882
64249
|
"",
|
|
63883
64250
|
'If you identify a meaningful insight, save it using `memory_save` with tags `["lesson", "best-practice", ...]`.',
|
|
63884
64251
|
'If it is a multi-step workflow, promote to SOP via `memory_update_longterm({ section: "sops", mode: "patch" })`.',
|
|
63885
|
-
"If worth sharing with the team, create a skill via **skill-building** and install with `
|
|
64252
|
+
"If worth sharing with the team, create a skill via **skill-building** and install with `package_install`.",
|
|
63886
64253
|
"",
|
|
63887
64254
|
"**Direct self-evolution** \u2014 consider the simplest, most impactful options:",
|
|
63888
64255
|
"- If this success reveals a guiding principle or working style worth keeping, append it to your ROLE.md via `file_edit`.",
|
|
@@ -64135,7 +64502,7 @@ ${reason}`
|
|
|
64135
64502
|
updated.runAt = void 0;
|
|
64136
64503
|
}
|
|
64137
64504
|
if (fields.maxRuns !== void 0)
|
|
64138
|
-
updated.maxRuns = fields.maxRuns;
|
|
64505
|
+
updated.maxRuns = fields.maxRuns > 0 ? fields.maxRuns : void 0;
|
|
64139
64506
|
if (fields.timezone !== void 0)
|
|
64140
64507
|
updated.timezone = fields.timezone;
|
|
64141
64508
|
updated.nextRunAt = computeNextRunFromConfig(updated);
|
|
@@ -64505,8 +64872,10 @@ ${task.description}`;
|
|
|
64505
64872
|
content,
|
|
64506
64873
|
"",
|
|
64507
64874
|
`(This task "${task.title}" is already ${task.status}. You have full context from your execution above.`,
|
|
64508
|
-
"
|
|
64509
|
-
"
|
|
64875
|
+
"Your text response will be posted as a reply in the task comment thread automatically.",
|
|
64876
|
+
"Do NOT use the `task_comment` tool \u2014 your text output IS the reply visible to the commenter.",
|
|
64877
|
+
"If the feedback contains something worth remembering, save it to memory.",
|
|
64878
|
+
"You have all your tools available for taking action if appropriate.)"
|
|
64510
64879
|
].join("\n");
|
|
64511
64880
|
try {
|
|
64512
64881
|
log50.info("Triggering post-task agent reply", { taskId: taskId2, taskSessionId, agentId: agentId2, authorName });
|
|
@@ -64618,11 +64987,19 @@ var init_builder_service = __esm({
|
|
|
64618
64987
|
orgService;
|
|
64619
64988
|
skillRegistry;
|
|
64620
64989
|
wsBroadcast;
|
|
64990
|
+
taskService;
|
|
64991
|
+
builtinTeamTemplatesDir;
|
|
64621
64992
|
constructor(orgService, skillRegistry, wsBroadcast) {
|
|
64622
64993
|
this.orgService = orgService;
|
|
64623
64994
|
this.skillRegistry = skillRegistry;
|
|
64624
64995
|
this.wsBroadcast = wsBroadcast;
|
|
64625
64996
|
}
|
|
64997
|
+
setTaskService(taskService) {
|
|
64998
|
+
this.taskService = taskService;
|
|
64999
|
+
}
|
|
65000
|
+
setBuiltinTeamTemplatesDir(dir) {
|
|
65001
|
+
this.builtinTeamTemplatesDir = dir;
|
|
65002
|
+
}
|
|
64626
65003
|
get baseDir() {
|
|
64627
65004
|
return join20(homedir12(), ".markus", "builder-artifacts");
|
|
64628
65005
|
}
|
|
@@ -64655,14 +65032,42 @@ var init_builder_service = __esm({
|
|
|
64655
65032
|
});
|
|
64656
65033
|
}
|
|
64657
65034
|
}
|
|
65035
|
+
if ((!type || type === "team") && this.builtinTeamTemplatesDir && existsSync24(this.builtinTeamTemplatesDir)) {
|
|
65036
|
+
const artifactNames = new Set(artifacts.filter((a) => a.type === "team").map((a) => a.name));
|
|
65037
|
+
for (const entry of readdirSync8(this.builtinTeamTemplatesDir, { withFileTypes: true })) {
|
|
65038
|
+
if (!entry.isDirectory() || artifactNames.has(entry.name))
|
|
65039
|
+
continue;
|
|
65040
|
+
const tplDir = join20(this.builtinTeamTemplatesDir, entry.name);
|
|
65041
|
+
const manifest = readManifest(tplDir, "team", FS_HELPER);
|
|
65042
|
+
if (!manifest)
|
|
65043
|
+
continue;
|
|
65044
|
+
artifacts.push({
|
|
65045
|
+
type: "team",
|
|
65046
|
+
name: entry.name,
|
|
65047
|
+
description: manifest.description ?? void 0,
|
|
65048
|
+
meta: { ...manifest, source: "builtin" },
|
|
65049
|
+
path: tplDir,
|
|
65050
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
65051
|
+
});
|
|
65052
|
+
}
|
|
65053
|
+
}
|
|
64658
65054
|
artifacts.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
64659
65055
|
return artifacts;
|
|
64660
65056
|
}
|
|
64661
65057
|
async installArtifact(type, name) {
|
|
64662
65058
|
const typeDir = type === "agent" ? "agents" : type === "team" ? "teams" : "skills";
|
|
64663
|
-
|
|
65059
|
+
let artDir = join20(this.baseDir, typeDir, name);
|
|
64664
65060
|
if (!existsSync24(artDir)) {
|
|
64665
|
-
|
|
65061
|
+
if (type === "team" && this.builtinTeamTemplatesDir) {
|
|
65062
|
+
const builtinDir = join20(this.builtinTeamTemplatesDir, name);
|
|
65063
|
+
if (existsSync24(builtinDir)) {
|
|
65064
|
+
artDir = builtinDir;
|
|
65065
|
+
} else {
|
|
65066
|
+
throw new Error(`Team template not found: ${name}. Use package_list to see available packages.`);
|
|
65067
|
+
}
|
|
65068
|
+
} else {
|
|
65069
|
+
throw new Error(`Artifact not found: ${type}/${name}`);
|
|
65070
|
+
}
|
|
64666
65071
|
}
|
|
64667
65072
|
const installType = type;
|
|
64668
65073
|
const manifest = readManifest(artDir, installType, FS_HELPER);
|
|
@@ -64778,9 +65183,35 @@ var init_builder_service = __esm({
|
|
|
64778
65183
|
createdAgents.push({ id: agent.id, name: agent.config.name, role: agent.role.name });
|
|
64779
65184
|
}
|
|
64780
65185
|
}
|
|
65186
|
+
const starterTasks = manifest.starterTasks ?? manifest.team?.starterTasks ?? [];
|
|
65187
|
+
const createdTaskIds = [];
|
|
65188
|
+
if (starterTasks.length > 0 && this.taskService) {
|
|
65189
|
+
const managerId = createdAgents.find((a) => a.role === "manager" || members.find((m) => m.name === a.name)?.role === "manager")?.id ?? createdAgents[0]?.id;
|
|
65190
|
+
if (managerId) {
|
|
65191
|
+
for (const st of starterTasks) {
|
|
65192
|
+
try {
|
|
65193
|
+
const task = this.taskService.createTask({
|
|
65194
|
+
orgId: "default",
|
|
65195
|
+
title: st.title,
|
|
65196
|
+
description: st.description,
|
|
65197
|
+
priority: st.priority ?? "medium",
|
|
65198
|
+
assignedAgentId: managerId,
|
|
65199
|
+
reviewerId: managerId,
|
|
65200
|
+
reviewerType: "human",
|
|
65201
|
+
creatorRole: "human",
|
|
65202
|
+
taskType: "standard"
|
|
65203
|
+
});
|
|
65204
|
+
createdTaskIds.push(task.id);
|
|
65205
|
+
log51.info("installTeam: created starterTask", { taskId: task.id, title: st.title });
|
|
65206
|
+
} catch (err) {
|
|
65207
|
+
log51.warn("installTeam: failed to create starterTask", { title: st.title, error: String(err) });
|
|
65208
|
+
}
|
|
65209
|
+
}
|
|
65210
|
+
}
|
|
65211
|
+
}
|
|
64781
65212
|
return {
|
|
64782
65213
|
type: "team",
|
|
64783
|
-
installed: { team: { id: team.id, name: teamName }, agents: createdAgents }
|
|
65214
|
+
installed: { team: { id: team.id, name: teamName }, agents: createdAgents, starterTaskIds: createdTaskIds }
|
|
64784
65215
|
};
|
|
64785
65216
|
}
|
|
64786
65217
|
/**
|
|
@@ -65379,7 +65810,12 @@ var init_sse_handler = __esm({
|
|
|
65379
65810
|
replyLength: persistReply.length
|
|
65380
65811
|
});
|
|
65381
65812
|
if (this.options.wsBroadcaster) {
|
|
65382
|
-
this.options.wsBroadcaster.
|
|
65813
|
+
if (this.options.wsBroadcaster.broadcastProactiveMessage && this.sessionId) {
|
|
65814
|
+
const agentName = this.options.agent.config?.name ?? this.options.agentId;
|
|
65815
|
+
this.options.wsBroadcaster.broadcastProactiveMessage(this.options.agentId, agentName, this.sessionId, `ws_fallback_${Date.now()}`, persistReply, { isMainSession: true }, this.options.senderId);
|
|
65816
|
+
} else {
|
|
65817
|
+
this.options.wsBroadcaster.broadcastChat(this.options.agentId, persistReply, "agent");
|
|
65818
|
+
}
|
|
65383
65819
|
}
|
|
65384
65820
|
} else {
|
|
65385
65821
|
this.sseBuffer.send({
|
|
@@ -66194,6 +66630,7 @@ ${cleanText}`,
|
|
|
66194
66630
|
setSkillRegistry(registry) {
|
|
66195
66631
|
this.skillRegistry = registry;
|
|
66196
66632
|
this.builderService = new BuilderService(this.orgService, registry, (msg) => this.ws?.broadcast(msg));
|
|
66633
|
+
this.builderService.setTaskService(this.taskService);
|
|
66197
66634
|
}
|
|
66198
66635
|
getBuilderService() {
|
|
66199
66636
|
return this.builderService;
|
|
@@ -66866,6 +67303,24 @@ ${cleanText}`,
|
|
|
66866
67303
|
log56.warn("Failed to persist assistant message", { error: String(err) });
|
|
66867
67304
|
}
|
|
66868
67305
|
}
|
|
67306
|
+
triggerSecretaryWelcome(userId2, userName, userRole) {
|
|
67307
|
+
try {
|
|
67308
|
+
const mgr = this.orgService.getAgentManager();
|
|
67309
|
+
const agentList = mgr.listAgents();
|
|
67310
|
+
const secretaryInfo = agentList.find((a) => a.agentRole === "secretary" || a.role?.toLowerCase() === "secretary");
|
|
67311
|
+
if (!secretaryInfo)
|
|
67312
|
+
return;
|
|
67313
|
+
const secretary = mgr.getAgent(secretaryInfo.id);
|
|
67314
|
+
const welcomeMsg = `[SYSTEM] A new team member just joined: "${userName}" (role: ${userRole}, id: ${userId2}). They have completed their account setup. As their Secretary, proactively guide them through the system capabilities. Send them a welcome message using notify_user (target the new user by their id: ${userId2}) explaining what they can do in Markus \u2014 projects, tasks, deliverables, team collaboration, and how to work with AI agents. Help them get started with their first steps.`;
|
|
67315
|
+
secretary.sendMessage(welcomeMsg, userId2, {
|
|
67316
|
+
name: userName,
|
|
67317
|
+
role: userRole,
|
|
67318
|
+
isFirstConversation: true
|
|
67319
|
+
}, { sourceType: "human_chat", scenario: "chat" });
|
|
67320
|
+
} catch (err) {
|
|
67321
|
+
log56.warn("Failed to trigger secretary welcome for new user", { userId: userId2, error: String(err) });
|
|
67322
|
+
}
|
|
67323
|
+
}
|
|
66869
67324
|
start() {
|
|
66870
67325
|
this.server = createServer2((req, res) => this.handleRequest(req, res));
|
|
66871
67326
|
this.ws.attach(this.server);
|
|
@@ -66928,6 +67383,68 @@ ${cleanText}`,
|
|
|
66928
67383
|
await this.readBody(req);
|
|
66929
67384
|
}
|
|
66930
67385
|
}
|
|
67386
|
+
if (path === "/api/auth/status" && req.method === "GET") {
|
|
67387
|
+
if (!this.storage || !this.authEnabled) {
|
|
67388
|
+
this.json(res, 200, { initialized: true });
|
|
67389
|
+
return;
|
|
67390
|
+
}
|
|
67391
|
+
const allUsers = await this.storage.userRepo.listByOrg("default");
|
|
67392
|
+
const hasRealUsers = allUsers.some((u) => u.passwordHash && u.email !== "admin@markus.local");
|
|
67393
|
+
this.json(res, 200, { initialized: hasRealUsers });
|
|
67394
|
+
return;
|
|
67395
|
+
}
|
|
67396
|
+
if (path === "/api/auth/init" && req.method === "POST") {
|
|
67397
|
+
if (!this.storage) {
|
|
67398
|
+
this.json(res, 503, { error: "Storage not available" });
|
|
67399
|
+
return;
|
|
67400
|
+
}
|
|
67401
|
+
const allUsers = await this.storage.userRepo.listByOrg("default");
|
|
67402
|
+
const hasRealUsers = allUsers.some((u) => u.passwordHash && u.email !== "admin@markus.local");
|
|
67403
|
+
if (hasRealUsers) {
|
|
67404
|
+
this.json(res, 403, { error: "System already initialized" });
|
|
67405
|
+
return;
|
|
67406
|
+
}
|
|
67407
|
+
const body = await this.readBody(req);
|
|
67408
|
+
const name = (body["name"] ?? "").trim();
|
|
67409
|
+
const email = (body["email"] ?? "").trim().toLowerCase();
|
|
67410
|
+
const password = body["password"] ?? "";
|
|
67411
|
+
if (!name || !email || !password) {
|
|
67412
|
+
this.json(res, 400, { error: "name, email and password are required" });
|
|
67413
|
+
return;
|
|
67414
|
+
}
|
|
67415
|
+
if (password.length < 6) {
|
|
67416
|
+
this.json(res, 400, { error: "Password must be at least 6 characters" });
|
|
67417
|
+
return;
|
|
67418
|
+
}
|
|
67419
|
+
const hash = await hashPassword(password);
|
|
67420
|
+
const placeholder = allUsers.find((u) => u.role === "owner" && u.email === "admin@markus.local");
|
|
67421
|
+
let userId2;
|
|
67422
|
+
if (placeholder) {
|
|
67423
|
+
userId2 = placeholder.id;
|
|
67424
|
+
this.storage.userRepo.updateProfile(userId2, { name, email });
|
|
67425
|
+
await this.storage.userRepo.updatePassword(userId2, hash);
|
|
67426
|
+
} else {
|
|
67427
|
+
userId2 = userId();
|
|
67428
|
+
await this.storage.userRepo.upsert({
|
|
67429
|
+
id: userId2,
|
|
67430
|
+
orgId: "default",
|
|
67431
|
+
name,
|
|
67432
|
+
email,
|
|
67433
|
+
role: "owner",
|
|
67434
|
+
passwordHash: hash
|
|
67435
|
+
});
|
|
67436
|
+
}
|
|
67437
|
+
this.orgService.syncHumanIdentity(userId2, "default", name, "owner", email);
|
|
67438
|
+
await this.storage.userRepo.updateLastLogin(userId2);
|
|
67439
|
+
const exp = Math.floor(Date.now() / 1e3) + 7 * 24 * 3600;
|
|
67440
|
+
const token = await signToken({ userId: userId2, orgId: "default", role: "owner", exp }, this.jwtSecret);
|
|
67441
|
+
res.setHeader("Set-Cookie", `markus_token=${token}; HttpOnly; SameSite=Strict; Path=/; Max-Age=${7 * 24 * 3600}`);
|
|
67442
|
+
this.json(res, 200, {
|
|
67443
|
+
user: { id: userId2, name, email, role: "owner", orgId: "default" },
|
|
67444
|
+
needsOnboarding: true
|
|
67445
|
+
});
|
|
67446
|
+
return;
|
|
67447
|
+
}
|
|
66931
67448
|
if (path === "/api/auth/login" && req.method === "POST") {
|
|
66932
67449
|
const body = await this.readBody(req);
|
|
66933
67450
|
const email = (body["email"] ?? "").trim().toLowerCase();
|
|
@@ -66936,7 +67453,18 @@ ${cleanText}`,
|
|
|
66936
67453
|
this.json(res, 200, { user: { id: "anonymous", name: "Admin", role: "owner" } });
|
|
66937
67454
|
return;
|
|
66938
67455
|
}
|
|
66939
|
-
|
|
67456
|
+
let userRow = this.storage ? await this.storage.userRepo.findByEmail(email) : null;
|
|
67457
|
+
if (!userRow && this.storage) {
|
|
67458
|
+
const allUsers = await this.storage.userRepo.listByOrg("default");
|
|
67459
|
+
const unclaimedOwner = allUsers.find((u) => u.role === "owner" && !u.lastLoginAt && u.email === "admin@markus.local");
|
|
67460
|
+
if (unclaimedOwner && unclaimedOwner.passwordHash) {
|
|
67461
|
+
const ownerPasswordValid = await verifyPassword(password, unclaimedOwner.passwordHash);
|
|
67462
|
+
if (ownerPasswordValid) {
|
|
67463
|
+
this.storage.userRepo.updateProfile(unclaimedOwner.id, { email });
|
|
67464
|
+
userRow = { ...unclaimedOwner, email };
|
|
67465
|
+
}
|
|
67466
|
+
}
|
|
67467
|
+
}
|
|
66940
67468
|
if (!userRow || !userRow.passwordHash) {
|
|
66941
67469
|
this.json(res, 401, { error: "Invalid email or password" });
|
|
66942
67470
|
return;
|
|
@@ -66946,6 +67474,7 @@ ${cleanText}`,
|
|
|
66946
67474
|
this.json(res, 401, { error: "Invalid email or password" });
|
|
66947
67475
|
return;
|
|
66948
67476
|
}
|
|
67477
|
+
const isFirstLogin = !userRow.lastLoginAt;
|
|
66949
67478
|
await this.storage.userRepo.updateLastLogin(userRow.id);
|
|
66950
67479
|
const exp = Math.floor(Date.now() / 1e3) + 7 * 24 * 3600;
|
|
66951
67480
|
const token = await signToken({ userId: userRow.id, orgId: userRow.orgId, role: userRow.role, exp }, this.jwtSecret);
|
|
@@ -66958,7 +67487,8 @@ ${cleanText}`,
|
|
|
66958
67487
|
role: userRow.role,
|
|
66959
67488
|
orgId: userRow.orgId,
|
|
66960
67489
|
avatarUrl: userRow.avatarUrl ?? void 0
|
|
66961
|
-
}
|
|
67490
|
+
},
|
|
67491
|
+
needsOnboarding: isFirstLogin
|
|
66962
67492
|
});
|
|
66963
67493
|
return;
|
|
66964
67494
|
}
|
|
@@ -67250,6 +67780,18 @@ ${cleanText}`,
|
|
|
67250
67780
|
}
|
|
67251
67781
|
return;
|
|
67252
67782
|
}
|
|
67783
|
+
if (path === "/api/sessions/has-any" && req.method === "GET") {
|
|
67784
|
+
const authUser = await this.requireAuth(req, res);
|
|
67785
|
+
if (!authUser)
|
|
67786
|
+
return;
|
|
67787
|
+
if (!this.storage) {
|
|
67788
|
+
this.json(res, 200, { hasAny: false });
|
|
67789
|
+
return;
|
|
67790
|
+
}
|
|
67791
|
+
const hasAny = this.storage.chatSessionRepo.hasAnySessions(authUser.userId);
|
|
67792
|
+
this.json(res, 200, { hasAny });
|
|
67793
|
+
return;
|
|
67794
|
+
}
|
|
67253
67795
|
if (path.match(/^\/api\/agents\/[^/]+\/sessions$/) && req.method === "GET") {
|
|
67254
67796
|
const authUser = await this.getAuthUser(req);
|
|
67255
67797
|
const agentId2 = path.split("/")[3];
|
|
@@ -67664,7 +68206,9 @@ ${cleanText}`,
|
|
|
67664
68206
|
const fileNames = body["fileNames"]?.filter(Boolean);
|
|
67665
68207
|
const isRetry = body["isRetry"];
|
|
67666
68208
|
const isResume = body["isResume"];
|
|
67667
|
-
const
|
|
68209
|
+
const baseSenderInfo = this.orgService.resolveHumanIdentity(senderId);
|
|
68210
|
+
const isFirstConversation = this.storage ? !this.storage.chatSessionRepo.hasAnySessions(senderId) : false;
|
|
68211
|
+
const senderInfo = baseSenderInfo ? { ...baseSenderInfo, isFirstConversation } : void 0;
|
|
67668
68212
|
const agent = this.orgService.getAgentManager().getAgent(agentId2);
|
|
67669
68213
|
this.ws.broadcastAgentUpdate(agentId2, "working");
|
|
67670
68214
|
if (!sessionId) {
|
|
@@ -67777,9 +68321,15 @@ ${cleanText}`,
|
|
|
67777
68321
|
return;
|
|
67778
68322
|
}
|
|
67779
68323
|
if (path === "/api/group-chats" && req.method === "GET") {
|
|
68324
|
+
const authUser = await this.requireAuth(req, res);
|
|
68325
|
+
if (!authUser)
|
|
68326
|
+
return;
|
|
67780
68327
|
const orgId2 = url.searchParams.get("orgId") ?? "default";
|
|
68328
|
+
const userId2 = authUser.userId;
|
|
68329
|
+
const isAdmin = authUser.role === "owner" || authUser.role === "admin";
|
|
67781
68330
|
const teams = this.orgService.listTeamsWithMembers(orgId2);
|
|
67782
|
-
const
|
|
68331
|
+
const filteredTeams = isAdmin ? teams : teams.filter((t) => t.members.some((m) => m.id === userId2));
|
|
68332
|
+
const teamChats = filteredTeams.map((t) => ({
|
|
67783
68333
|
id: `group:${t.id}`,
|
|
67784
68334
|
name: t.name,
|
|
67785
68335
|
type: "team",
|
|
@@ -67787,7 +68337,7 @@ ${cleanText}`,
|
|
|
67787
68337
|
memberCount: t.members.length,
|
|
67788
68338
|
channelKey: `group:${t.id}`
|
|
67789
68339
|
}));
|
|
67790
|
-
const customChats = this.storage?.groupChatRepo ? this.storage.groupChatRepo.list(orgId2).map((c) => ({
|
|
68340
|
+
const customChats = this.storage?.groupChatRepo ? (isAdmin ? this.storage.groupChatRepo.list(orgId2) : this.storage.groupChatRepo.listByMember(orgId2, userId2)).map((c) => ({
|
|
67791
68341
|
id: c.id,
|
|
67792
68342
|
name: c.name,
|
|
67793
68343
|
type: "custom",
|
|
@@ -74836,6 +75386,14 @@ var init_hitl_service = __esm({
|
|
|
74836
75386
|
setTimeout(() => {
|
|
74837
75387
|
if (this.pendingResolvers.has(approval.id)) {
|
|
74838
75388
|
this.pendingResolvers.delete(approval.id);
|
|
75389
|
+
const a = this.approvals.get(approval.id);
|
|
75390
|
+
if (a && a.status === "pending") {
|
|
75391
|
+
a.status = "expired";
|
|
75392
|
+
a.respondedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
75393
|
+
a.responseComment = "Approval timed out";
|
|
75394
|
+
this.persistApproval(a);
|
|
75395
|
+
this.markApprovalNotificationsRead(a.id);
|
|
75396
|
+
}
|
|
74839
75397
|
resolve20({ approved: false, comment: "Approval timed out" });
|
|
74840
75398
|
}
|
|
74841
75399
|
}, opts.expiresInMs);
|
|
@@ -74863,6 +75421,35 @@ var init_hitl_service = __esm({
|
|
|
74863
75421
|
}
|
|
74864
75422
|
return approval;
|
|
74865
75423
|
}
|
|
75424
|
+
cancelApproval(id, cancelledBy, comment) {
|
|
75425
|
+
const approval = this.approvals.get(id);
|
|
75426
|
+
if (!approval || approval.status !== "pending")
|
|
75427
|
+
return void 0;
|
|
75428
|
+
approval.status = "cancelled";
|
|
75429
|
+
approval.respondedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
75430
|
+
approval.respondedBy = cancelledBy;
|
|
75431
|
+
if (comment)
|
|
75432
|
+
approval.responseComment = comment;
|
|
75433
|
+
this.persistApproval(approval);
|
|
75434
|
+
log57.info(`Approval ${id} cancelled by ${cancelledBy}`, { comment });
|
|
75435
|
+
this.markApprovalNotificationsRead(id);
|
|
75436
|
+
const resolve20 = this.pendingResolvers.get(id);
|
|
75437
|
+
if (resolve20) {
|
|
75438
|
+
this.pendingResolvers.delete(id);
|
|
75439
|
+
resolve20({ approved: false, comment: comment ?? "Approval cancelled" });
|
|
75440
|
+
}
|
|
75441
|
+
return approval;
|
|
75442
|
+
}
|
|
75443
|
+
cancelApprovalsByDetail(key2, value, cancelledBy, comment) {
|
|
75444
|
+
let count = 0;
|
|
75445
|
+
for (const approval of this.approvals.values()) {
|
|
75446
|
+
if (approval.status === "pending" && approval.details[key2] === value) {
|
|
75447
|
+
this.cancelApproval(approval.id, cancelledBy, comment);
|
|
75448
|
+
count++;
|
|
75449
|
+
}
|
|
75450
|
+
}
|
|
75451
|
+
return count;
|
|
75452
|
+
}
|
|
74866
75453
|
persistApproval(approval) {
|
|
74867
75454
|
if (!this.approvalRepo)
|
|
74868
75455
|
return;
|
|
@@ -76017,6 +76604,9 @@ var init_requirement_service = __esm({
|
|
|
76017
76604
|
const req = this.requirements.get(id);
|
|
76018
76605
|
if (!req)
|
|
76019
76606
|
throw new Error(`Requirement ${id} not found`);
|
|
76607
|
+
if (this.hitlService) {
|
|
76608
|
+
this.hitlService.cancelApprovalsByDetail("requirementId", id, cancelledBy ?? "system", "Requirement cancelled");
|
|
76609
|
+
}
|
|
76020
76610
|
const oldStatus = req.status;
|
|
76021
76611
|
req.status = "cancelled";
|
|
76022
76612
|
req.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -76110,6 +76700,9 @@ var init_requirement_service = __esm({
|
|
|
76110
76700
|
}
|
|
76111
76701
|
}
|
|
76112
76702
|
deleteRequirement(id) {
|
|
76703
|
+
if (this.hitlService) {
|
|
76704
|
+
this.hitlService.cancelApprovalsByDetail("requirementId", id, "system", "Requirement deleted");
|
|
76705
|
+
}
|
|
76113
76706
|
this.requirements.delete(id);
|
|
76114
76707
|
if (this.requirementRepo) {
|
|
76115
76708
|
this.requirementRepo.delete(id).catch((e) => log61.error("Failed to delete requirement from storage", { id, error: String(e) }));
|
|
@@ -77451,7 +78044,7 @@ var init_scheduled_task_runner = __esm({
|
|
|
77451
78044
|
if (!task.scheduleConfig)
|
|
77452
78045
|
continue;
|
|
77453
78046
|
const config = task.scheduleConfig;
|
|
77454
|
-
if (config.maxRuns
|
|
78047
|
+
if (config.maxRuns && config.maxRuns > 0 && (config.currentRuns ?? 0) >= config.maxRuns) {
|
|
77455
78048
|
continue;
|
|
77456
78049
|
}
|
|
77457
78050
|
const nextRun = config.nextRunAt ? new Date(config.nextRunAt).getTime() : 0;
|
|
@@ -78960,6 +79553,10 @@ CREATE INDEX IF NOT EXISTS idx_st_entity ON status_transitions(entity_type, enti
|
|
|
78960
79553
|
}
|
|
78961
79554
|
return this.db.prepare("SELECT * FROM chat_sessions WHERE agent_id = ? ORDER BY is_main DESC, last_message_at DESC LIMIT ?").all(agentId2, limit).map((r) => this._mapSession(r));
|
|
78962
79555
|
}
|
|
79556
|
+
hasAnySessions(userId2) {
|
|
79557
|
+
const r = this.db.prepare("SELECT 1 FROM chat_sessions WHERE user_id = ? LIMIT 1").get(userId2);
|
|
79558
|
+
return r !== null && r !== void 0;
|
|
79559
|
+
}
|
|
78963
79560
|
getSession(sessionId) {
|
|
78964
79561
|
const r = this.db.prepare("SELECT * FROM chat_sessions WHERE id = ?").get(sessionId);
|
|
78965
79562
|
return r ? this._mapSession(r) : null;
|
|
@@ -80430,6 +81027,17 @@ CREATE INDEX IF NOT EXISTS idx_st_entity ON status_transitions(entity_type, enti
|
|
|
80430
81027
|
memberCount: r["member_count"]
|
|
80431
81028
|
}));
|
|
80432
81029
|
}
|
|
81030
|
+
listByMember(orgId2, memberId) {
|
|
81031
|
+
const rows = this.db.prepare(`SELECT g.*, (SELECT COUNT(*) FROM group_chat_members WHERE group_chat_id = g.id) AS member_count
|
|
81032
|
+
FROM group_chats g
|
|
81033
|
+
INNER JOIN group_chat_members m ON m.group_chat_id = g.id
|
|
81034
|
+
WHERE g.org_id = ? AND m.member_id = ?
|
|
81035
|
+
ORDER BY g.created_at DESC`).all(orgId2, memberId);
|
|
81036
|
+
return rows.map((r) => ({
|
|
81037
|
+
...this.mapRow(r),
|
|
81038
|
+
memberCount: r["member_count"]
|
|
81039
|
+
}));
|
|
81040
|
+
}
|
|
80433
81041
|
getById(id) {
|
|
80434
81042
|
const r = this.db.prepare("SELECT * FROM group_chats WHERE id = ?").get(id);
|
|
80435
81043
|
if (!r)
|
|
@@ -82324,10 +82932,10 @@ function registerStartCommand(program2) {
|
|
|
82324
82932
|
const configPath = globalOpts.config ?? getDefaultConfigPath();
|
|
82325
82933
|
if (opts.setup || !existsSync33(configPath)) {
|
|
82326
82934
|
if (!existsSync33(configPath)) {
|
|
82327
|
-
console.log(" No configuration found \u2014
|
|
82935
|
+
console.log(" No configuration found \u2014 auto-configuring from environment...\n");
|
|
82328
82936
|
}
|
|
82329
82937
|
const { quickInit: quickInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
82330
|
-
await quickInit2();
|
|
82938
|
+
await quickInit2({ nonInteractive: true });
|
|
82331
82939
|
}
|
|
82332
82940
|
const config = loadConfig(globalOpts.config);
|
|
82333
82941
|
await startServer(config, { port: globalOpts.port, config: globalOpts.config });
|
|
@@ -82570,7 +83178,8 @@ async function startServer(config, values) {
|
|
|
82570
83178
|
startupLog("INFO", " 2. \u4EA4\u4E92\u5F0F\u914D\u7F6E \u2192 \u6B63\u5728\u542F\u52A8\u5411\u5BFC...");
|
|
82571
83179
|
startupBlank();
|
|
82572
83180
|
const { quickInit: quickInit2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
82573
|
-
|
|
83181
|
+
startupLog("INFO", "\u81EA\u52A8\u4ECE\u73AF\u5883\u53D8\u91CF/\u5DF2\u77E5\u914D\u7F6E\u5BFC\u5165 LLM \u8BBE\u7F6E...");
|
|
83182
|
+
await quickInit2({ nonInteractive: true });
|
|
82574
83183
|
const { loadConfig: reloadConfig } = await Promise.resolve().then(() => (init_dist(), dist_exports));
|
|
82575
83184
|
const updatedConfig = reloadConfig(values["config"]);
|
|
82576
83185
|
for (const [name, cfg] of Object.entries(updatedConfig.llm?.providers ?? {})) {
|
|
@@ -82733,6 +83342,10 @@ async function startServer(config, values) {
|
|
|
82733
83342
|
orgService.registerBuilderContextProviders(skillRegistry);
|
|
82734
83343
|
const builderService = apiServer.getBuilderService();
|
|
82735
83344
|
if (builderService) {
|
|
83345
|
+
const builtinTeamsDir = resolveTemplatesDir("teams");
|
|
83346
|
+
if (builtinTeamsDir && existsSync33(builtinTeamsDir)) {
|
|
83347
|
+
builderService.setBuiltinTeamTemplatesDir(builtinTeamsDir);
|
|
83348
|
+
}
|
|
82736
83349
|
agentManager.setBuilderService(builderService);
|
|
82737
83350
|
}
|
|
82738
83351
|
const hubClient = apiServer.getHubClient();
|
|
@@ -82764,6 +83377,7 @@ async function startServer(config, values) {
|
|
|
82764
83377
|
return { installed: result.installed, name: result.name, method: result.method };
|
|
82765
83378
|
});
|
|
82766
83379
|
agentManager.setUserApprovalRequester(async (opts) => {
|
|
83380
|
+
const taskTitle = opts.relatedTaskId ? taskService.getTask(opts.relatedTaskId)?.title : void 0;
|
|
82767
83381
|
return hitlService.requestApprovalAndWait({
|
|
82768
83382
|
agentId: opts.agentId,
|
|
82769
83383
|
agentName: opts.agentName,
|
|
@@ -82773,7 +83387,7 @@ async function startServer(config, values) {
|
|
|
82773
83387
|
targetUserId: ownerUserId,
|
|
82774
83388
|
options: opts.options,
|
|
82775
83389
|
allowFreeform: opts.allowFreeform,
|
|
82776
|
-
details: { priority: opts.priority, taskId: opts.relatedTaskId }
|
|
83390
|
+
details: { priority: opts.priority, taskId: opts.relatedTaskId, taskTitle }
|
|
82777
83391
|
});
|
|
82778
83392
|
});
|
|
82779
83393
|
agentManager.setUserNotifier((opts) => {
|
|
@@ -82849,7 +83463,8 @@ async function startServer(config, values) {
|
|
|
82849
83463
|
agentManager.getEventBus().on("agent:notify-user", async (evt) => {
|
|
82850
83464
|
const { agentId: agentId2, title, body, priority, taskId: taskId2, requirementId: requirementId2, targetUserId } = evt;
|
|
82851
83465
|
try {
|
|
82852
|
-
const
|
|
83466
|
+
const sessionUserId = targetUserId || defaultSessionUserId;
|
|
83467
|
+
const mainSession = storage.chatSessionRepo.getOrCreateMainSession(agentId2, sessionUserId);
|
|
82853
83468
|
const agent = agentManager.getAgent(agentId2);
|
|
82854
83469
|
const formattedMsg = `**${title}**
|
|
82855
83470
|
|
|
@@ -82865,7 +83480,7 @@ ${body}`;
|
|
|
82865
83480
|
storage.chatSessionRepo.updateLastMessage(mainSession.id);
|
|
82866
83481
|
ws.broadcastProactiveMessage(agentId2, agent.config.name, mainSession.id, msg.id, formattedMsg, {
|
|
82867
83482
|
isMainSession: true
|
|
82868
|
-
},
|
|
83483
|
+
}, sessionUserId);
|
|
82869
83484
|
const hasTask = !!taskId2;
|
|
82870
83485
|
hitlService.notify({
|
|
82871
83486
|
targetUserId: targetUserId ?? "all",
|
|
@@ -83029,13 +83644,14 @@ ${reason}`;
|
|
|
83029
83644
|
const reasonMatch = request.reason.match(/requires approval:\s*(.+?)\.?\s*Command:/);
|
|
83030
83645
|
title = reasonMatch ? `Git: ${reasonMatch[1]}` : "Shell: command approval";
|
|
83031
83646
|
}
|
|
83647
|
+
const taskTitle = request.taskId ? taskService.getTask(request.taskId)?.title : void 0;
|
|
83032
83648
|
const result = await hitlService.requestApprovalAndWait({
|
|
83033
83649
|
agentId: agentId2,
|
|
83034
83650
|
agentName,
|
|
83035
83651
|
type: "action",
|
|
83036
83652
|
title,
|
|
83037
83653
|
description: request.reason,
|
|
83038
|
-
details: { ...request.toolArgs, toolName: request.toolName, agentId: agentId2, taskId: request.taskId },
|
|
83654
|
+
details: { ...request.toolArgs, toolName: request.toolName, agentId: agentId2, taskId: request.taskId, taskTitle },
|
|
83039
83655
|
targetUserId: ownerUserId
|
|
83040
83656
|
});
|
|
83041
83657
|
auditService.record({
|