@kendoo.agentdesk/agentdesk 0.9.5 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -13
- package/bin/agentdesk.mjs +2 -7
- package/cli/agents.mjs +53 -78
- package/cli/daemon.mjs +1 -2
- package/cli/init.mjs +78 -13
- package/cli/orchestrator.mjs +2 -271
- package/cli/prompt.mjs +7 -3
- package/cli/stream-parser.mjs +1 -1
- package/cli/team.mjs +38 -25
- package/cli/tracker-check.mjs +211 -0
- package/package.json +1 -1
- package/prompts/team.md +135 -278
- package/cli/agent-prompts.mjs +0 -166
- package/cli/agent-runner.mjs +0 -148
package/cli/agent-prompts.mjs
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
// Per-agent prompt generator for sub-agent architecture
|
|
2
|
-
|
|
3
|
-
import { generateContext } from "./detect.mjs";
|
|
4
|
-
|
|
5
|
-
const PHASE_INSTRUCTIONS = {
|
|
6
|
-
intake: {
|
|
7
|
-
Jane: `You are leading the intake for this task. Your job:
|
|
8
|
-
1. Understand the task requirements from the description and/or tracker.
|
|
9
|
-
2. Check for existing branches: \`git branch -a | grep <task-id>\`
|
|
10
|
-
3. Check for existing PRs: \`gh pr list --search <task-id> --json number,title,state\`
|
|
11
|
-
4. Explore the codebase briefly to understand what we're working with.
|
|
12
|
-
5. Summarize: what needs to be done, what already exists, and what the starting point is.
|
|
13
|
-
6. Recommend which phase to start from (BRAINSTORM for new work, EXECUTION if branch exists).
|
|
14
|
-
|
|
15
|
-
IMPORTANT: At the end of your intake summary, you MUST provide a short title for this session on its own line in this exact format:
|
|
16
|
-
SESSION_TITLE: <4-8 word title>
|
|
17
|
-
Example: SESSION_TITLE: Fix checkout total calculation
|
|
18
|
-
This title will be displayed in the dashboard navbar, so keep it short and descriptive.`,
|
|
19
|
-
},
|
|
20
|
-
|
|
21
|
-
brainstorm: {
|
|
22
|
-
_default: (agent) => `Share your perspective on this task from your role as ${agent.role}.
|
|
23
|
-
Focus on: ${agent.brainstorm?.focus || "your area of expertise"}.
|
|
24
|
-
Use [${agent.brainstorm?.tag || "SAY"}] tag.
|
|
25
|
-
Be specific. If you disagree with anything in the conversation so far, use [ARGUE] and explain why.
|
|
26
|
-
If you agree, still add value — don't just say "I agree."`,
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
planning: {
|
|
30
|
-
_default: (agent) => `Present your plan for this task from your role as ${agent.role}.
|
|
31
|
-
Your expected output: ${agent.planning || "Your role-specific plan."}
|
|
32
|
-
Be concrete — name files, approaches, specific concerns.`,
|
|
33
|
-
},
|
|
34
|
-
|
|
35
|
-
"planning-review": {
|
|
36
|
-
_default: () => `Review all the plans presented by the team.
|
|
37
|
-
If you see problems, conflicts, or missing considerations, use [ARGUE] and explain.
|
|
38
|
-
If everything looks good, acknowledge with [AGREE] and note why.`,
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
execution: {
|
|
42
|
-
_default: (agent) => {
|
|
43
|
-
if (!agent.execution) return "This task has no execution step for your role. Skip this phase.";
|
|
44
|
-
return `Complete your execution tasks:
|
|
45
|
-
${agent.execution.tasks.map((t, i) => `${i + 1}. ${t}`).join("\n")}
|
|
46
|
-
|
|
47
|
-
Work carefully. Use tools as needed. Narrate what you're doing.`;
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
"execution-review": {
|
|
52
|
-
_default: (agent) => `Review the changes made so far.
|
|
53
|
-
From your perspective as ${agent.role}:
|
|
54
|
-
${agent.groundRules || "Review for issues in your area of expertise."}
|
|
55
|
-
If you find issues, describe them specifically with file paths and line numbers.
|
|
56
|
-
If everything looks good, confirm with [AGREE].`,
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
review: {
|
|
60
|
-
_default: (agent) => `The session is wrapping up. Provide your final notes:
|
|
61
|
-
- Any remaining concerns?
|
|
62
|
-
- Anything the team should watch out for?
|
|
63
|
-
- Overall assessment from your perspective as ${agent.role}.
|
|
64
|
-
Keep it brief.`,
|
|
65
|
-
Jane: `The session is wrapping up. Provide the final summary:
|
|
66
|
-
1. What was accomplished
|
|
67
|
-
2. Any remaining concerns from the team
|
|
68
|
-
3. What the next steps should be
|
|
69
|
-
Keep it concise.`,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export function buildAgentPrompt(agent, { phase, task, project, conversation, inboxUrl, sessionUrl }) {
|
|
74
|
-
const parts = [];
|
|
75
|
-
|
|
76
|
-
// Identity
|
|
77
|
-
parts.push(`You are ${agent.name}, ${agent.role} on a software development team.`);
|
|
78
|
-
parts.push("");
|
|
79
|
-
|
|
80
|
-
// Role
|
|
81
|
-
parts.push("## Your Role");
|
|
82
|
-
parts.push(agent.description);
|
|
83
|
-
if (agent.groundRules) parts.push(`\nGround rules: ${agent.groundRules}`);
|
|
84
|
-
if (agent.codePrinciple) parts.push(`\nCode principle: ${agent.codePrinciple}`);
|
|
85
|
-
parts.push("");
|
|
86
|
-
|
|
87
|
-
// Communication
|
|
88
|
-
parts.push("## Communication");
|
|
89
|
-
parts.push(`Prefix your output with your badge: ${agent.badge}`);
|
|
90
|
-
parts.push("Use these tags in your messages:");
|
|
91
|
-
parts.push("- [SAY] — Normal statements, announcements, questions");
|
|
92
|
-
parts.push("- [THINK] — Internal reasoning, analysis");
|
|
93
|
-
parts.push("- [ACT] — When using tools or taking actions");
|
|
94
|
-
parts.push("- [ARGUE] — When you disagree or see problems");
|
|
95
|
-
parts.push("- [AGREE] — When you agree (but still add value)");
|
|
96
|
-
parts.push("");
|
|
97
|
-
|
|
98
|
-
// Task
|
|
99
|
-
parts.push("## Task");
|
|
100
|
-
parts.push(`Task ID: ${task.id}`);
|
|
101
|
-
if (task.link) parts.push(`Task link: ${task.link}`);
|
|
102
|
-
if (task.description) parts.push(`\nDescription: ${task.description}`);
|
|
103
|
-
parts.push("");
|
|
104
|
-
|
|
105
|
-
// Project context
|
|
106
|
-
if (project) {
|
|
107
|
-
const context = generateContext(project);
|
|
108
|
-
parts.push("## Project Context");
|
|
109
|
-
parts.push(context);
|
|
110
|
-
parts.push("");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Conversation so far
|
|
114
|
-
if (conversation && conversation.length > 0) {
|
|
115
|
-
parts.push("## Conversation So Far");
|
|
116
|
-
for (const msg of conversation) {
|
|
117
|
-
if (msg.type === "phase") {
|
|
118
|
-
parts.push(`\n--- ${msg.phase} ---\n`);
|
|
119
|
-
} else if (msg.agent && msg.message) {
|
|
120
|
-
parts.push(`${msg.agent} [${msg.tag || "SAY"}]: ${msg.message}`);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
parts.push("");
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Phase instructions
|
|
127
|
-
parts.push(`## Current Phase: ${phase.toUpperCase()}`);
|
|
128
|
-
const phaseConfig = PHASE_INSTRUCTIONS[phase] || {};
|
|
129
|
-
const agentInstr = phaseConfig[agent.name] || (phaseConfig._default ? phaseConfig._default(agent) : "Contribute from your area of expertise.");
|
|
130
|
-
parts.push(agentInstr);
|
|
131
|
-
parts.push("");
|
|
132
|
-
|
|
133
|
-
// Inbox (Jane only)
|
|
134
|
-
if (agent.name === "Jane" && inboxUrl) {
|
|
135
|
-
parts.push("## User Messages");
|
|
136
|
-
parts.push(`Before starting, check for user messages: \`curl -s ${inboxUrl}\``);
|
|
137
|
-
parts.push("If the response is not empty ([]), read the messages and incorporate the user's input.");
|
|
138
|
-
parts.push("");
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Session URL
|
|
142
|
-
if (sessionUrl) {
|
|
143
|
-
parts.push(`Session: ${sessionUrl}`);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// Time
|
|
147
|
-
const now = new Date();
|
|
148
|
-
parts.push(`\nCurrent date/time: ${now.toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" })} ${now.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" })}`);
|
|
149
|
-
|
|
150
|
-
return parts.join("\n");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Get tool list for an agent
|
|
154
|
-
const AGENT_TOOLS = {
|
|
155
|
-
Jane: ["Bash", "Read"],
|
|
156
|
-
Dennis: ["Bash", "Read", "Edit", "Write", "Glob", "Grep"],
|
|
157
|
-
Sam: ["Read", "Glob", "Grep"],
|
|
158
|
-
Bart: ["Bash", "Read", "Glob", "Grep"],
|
|
159
|
-
Vera: ["Bash", "Read", "Edit", "Write", "Glob", "Grep"],
|
|
160
|
-
Luna: ["Read", "Glob"],
|
|
161
|
-
Mark: ["Read", "Glob"],
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
export function getAgentTools(agentName) {
|
|
165
|
-
return AGENT_TOOLS[agentName] || ["Bash", "Read", "Edit", "Write", "Glob", "Grep"];
|
|
166
|
-
}
|
package/cli/agent-runner.mjs
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
// Spawns a single Claude process for one agent and parses its output
|
|
2
|
-
|
|
3
|
-
import { spawn } from "child_process";
|
|
4
|
-
import { createInterface } from "readline";
|
|
5
|
-
|
|
6
|
-
export async function runAgent(agentName, {
|
|
7
|
-
prompt,
|
|
8
|
-
allowedTools = ["Bash", "Read", "Edit", "Write", "Glob", "Grep"],
|
|
9
|
-
cwd,
|
|
10
|
-
env,
|
|
11
|
-
onMessage,
|
|
12
|
-
onToolUse,
|
|
13
|
-
onToolResult,
|
|
14
|
-
}) {
|
|
15
|
-
const messages = [];
|
|
16
|
-
const toolUses = [];
|
|
17
|
-
let rawOutput = "";
|
|
18
|
-
let inputTokens = 0;
|
|
19
|
-
let outputTokens = 0;
|
|
20
|
-
let steps = 0;
|
|
21
|
-
let hadArgue = false;
|
|
22
|
-
|
|
23
|
-
const child = spawn(
|
|
24
|
-
"claude",
|
|
25
|
-
[
|
|
26
|
-
"-p", prompt,
|
|
27
|
-
"--allowedTools", allowedTools.join(","),
|
|
28
|
-
"--verbose",
|
|
29
|
-
"--output-format", "stream-json",
|
|
30
|
-
],
|
|
31
|
-
{
|
|
32
|
-
stdio: ["pipe", "pipe", "inherit"],
|
|
33
|
-
shell: false,
|
|
34
|
-
env: env || process.env,
|
|
35
|
-
cwd,
|
|
36
|
-
}
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
child.stdin.end();
|
|
40
|
-
|
|
41
|
-
const rl = createInterface({ input: child.stdout });
|
|
42
|
-
|
|
43
|
-
for await (const line of rl) {
|
|
44
|
-
try {
|
|
45
|
-
const event = JSON.parse(line);
|
|
46
|
-
|
|
47
|
-
// Track tokens
|
|
48
|
-
if (event.usage) {
|
|
49
|
-
if (event.usage.input_tokens) inputTokens = Math.max(inputTokens, event.usage.input_tokens);
|
|
50
|
-
if (event.usage.output_tokens) outputTokens += (event.usage.output_tokens_delta || 0);
|
|
51
|
-
}
|
|
52
|
-
if (event.message?.usage) {
|
|
53
|
-
if (event.message.usage.input_tokens) inputTokens = Math.max(inputTokens, event.message.usage.input_tokens);
|
|
54
|
-
if (event.message.usage.output_tokens) outputTokens = Math.max(outputTokens, event.message.usage.output_tokens);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Text output
|
|
58
|
-
if (event.type === "assistant" && event.message?.content) {
|
|
59
|
-
for (const block of event.message.content) {
|
|
60
|
-
if (block.type === "text" && block.text.trim()) {
|
|
61
|
-
const text = block.text.trim();
|
|
62
|
-
rawOutput += text + "\n";
|
|
63
|
-
|
|
64
|
-
// Detect tags
|
|
65
|
-
let tag = "SAY";
|
|
66
|
-
if (/\[ARGUE\]/i.test(text)) { tag = "ARGUE"; hadArgue = true; }
|
|
67
|
-
else if (/\[AGREE\]/i.test(text)) tag = "AGREE";
|
|
68
|
-
else if (/\[THINK\]/i.test(text)) tag = "THINK";
|
|
69
|
-
else if (/\[ACT\]/i.test(text)) tag = "ACT";
|
|
70
|
-
|
|
71
|
-
const cleanMsg = text.replace(/\[(SAY|ACT|THINK|AGREE|ARGUE)\]\s*/gi, "").replace(/\*+/g, "");
|
|
72
|
-
const msg = { agent: agentName, tag, message: cleanMsg };
|
|
73
|
-
messages.push(msg);
|
|
74
|
-
onMessage?.(msg);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Tool use
|
|
80
|
-
if (event.type === "tool_use") {
|
|
81
|
-
const name = event.name || event.tool_name;
|
|
82
|
-
steps++;
|
|
83
|
-
|
|
84
|
-
let description = "Running command...";
|
|
85
|
-
if (name === "Bash") {
|
|
86
|
-
const cmd = event.input?.command || "";
|
|
87
|
-
if (cmd.includes("curl") && cmd.includes("linear")) description = "Calling Linear API...";
|
|
88
|
-
else if (cmd.includes("curl")) description = "Making API request...";
|
|
89
|
-
else {
|
|
90
|
-
const shortCmd = cmd.length > 80 ? cmd.slice(0, 80) + "..." : cmd;
|
|
91
|
-
description = `$ ${shortCmd}`;
|
|
92
|
-
}
|
|
93
|
-
} else if (name === "Read") {
|
|
94
|
-
const shortPath = (event.input?.file_path || "").split("/").slice(-3).join("/");
|
|
95
|
-
description = `Reading ${shortPath}`;
|
|
96
|
-
} else if (name === "Edit" || name === "Write") {
|
|
97
|
-
const shortPath = (event.input?.file_path || "").split("/").slice(-3).join("/");
|
|
98
|
-
description = `${name === "Edit" ? "Editing" : "Writing"} ${shortPath}`;
|
|
99
|
-
} else if (name === "Glob" || name === "Grep") {
|
|
100
|
-
description = `Searching ${event.input?.pattern || ""}`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const use = { agent: agentName, tool: name, description };
|
|
104
|
-
toolUses.push(use);
|
|
105
|
-
onToolUse?.(use);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Tool result
|
|
109
|
-
if (event.type === "tool_result") {
|
|
110
|
-
const output = event.content || event.output;
|
|
111
|
-
let text = "";
|
|
112
|
-
if (typeof output === "string") text = output.trim();
|
|
113
|
-
else if (Array.isArray(output)) {
|
|
114
|
-
text = output.filter(b => b.type === "text").map(b => b.text.trim()).join("\n");
|
|
115
|
-
}
|
|
116
|
-
const hasError = text && (text.toLowerCase().includes("error") || text.toLowerCase().includes("failed"));
|
|
117
|
-
const summary = text?.length > 300 ? `Done (${text.length} chars)` : text || "Done";
|
|
118
|
-
onToolResult?.({ success: !hasError, summary });
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Final result
|
|
122
|
-
if (event.type === "result") {
|
|
123
|
-
if (event.usage) {
|
|
124
|
-
if (event.usage.input_tokens) inputTokens = Math.max(inputTokens, event.usage.input_tokens);
|
|
125
|
-
if (event.usage.output_tokens) outputTokens = Math.max(outputTokens, event.usage.output_tokens);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
} catch {
|
|
129
|
-
// skip non-JSON
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const exitCode = await new Promise(resolve => {
|
|
134
|
-
child.on("close", (code) => resolve(code || 0));
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
agent: agentName,
|
|
139
|
-
messages,
|
|
140
|
-
toolUses,
|
|
141
|
-
rawOutput,
|
|
142
|
-
inputTokens,
|
|
143
|
-
outputTokens,
|
|
144
|
-
steps,
|
|
145
|
-
hadArgue,
|
|
146
|
-
exitCode,
|
|
147
|
-
};
|
|
148
|
-
}
|