heyio 1.1.6 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/copilot/agents.js +15 -4
- package/dist/copilot/ceremonies.js +155 -0
- package/dist/copilot/system-message.js +7 -1
- package/dist/copilot/tools.js +15 -1
- package/package.json +1 -1
package/dist/copilot/agents.js
CHANGED
|
@@ -28,11 +28,22 @@ export async function delegateTask(squadId, task, instanceId) {
|
|
|
28
28
|
.join("\n");
|
|
29
29
|
const systemMessage = `# Squad Team Lead: ${lead.character_name}
|
|
30
30
|
|
|
31
|
-
You are ${lead.character_name}, the team lead for this squad. Your role is
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
You are ${lead.character_name}, the team lead for this squad. Your role is STRICTLY coordination — you do NOT write code, tests, or implementation of any kind.
|
|
32
|
+
|
|
33
|
+
## Your Responsibilities:
|
|
34
|
+
1. Break down tasks into smaller pieces and delegate to specialists
|
|
35
|
+
2. Route work to the appropriate specialist based on their role
|
|
34
36
|
3. Coordinate reviews and approvals
|
|
35
37
|
4. Ensure quality gates are met
|
|
38
|
+
5. Report progress and blockers
|
|
39
|
+
|
|
40
|
+
## PROHIBITED — You must NEVER:
|
|
41
|
+
- Write, edit, or generate code directly
|
|
42
|
+
- Create or modify files in the repository
|
|
43
|
+
- Run build/test commands to fix code (only to verify status)
|
|
44
|
+
- Implement any part of a task yourself
|
|
45
|
+
|
|
46
|
+
If no suitable specialist exists for a sub-task, report that back — do NOT attempt it yourself.
|
|
36
47
|
|
|
37
48
|
## Your Team:
|
|
38
49
|
${agentRoster}
|
|
@@ -40,7 +51,7 @@ ${agentRoster}
|
|
|
40
51
|
## Workflow Rules:
|
|
41
52
|
- Peer review: QA + Test + Lead have veto power
|
|
42
53
|
- Use \`--comment\` with "LGTM" for approvals (not \`--approve\`)
|
|
43
|
-
- Always
|
|
54
|
+
- Always use the gh CLI for GitHub interactions
|
|
44
55
|
- Merge criteria: all veto-capable members have posted approving comments + CI passes + no conflicts
|
|
45
56
|
|
|
46
57
|
${lead.persona ? `## Personality:\n${lead.persona}` : ""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { approveAll } from "@github/copilot-sdk";
|
|
2
|
+
import { getClient } from "./client.js";
|
|
3
|
+
import { getLeadForSquad, getAgentsForSquad } from "../store/squads.js";
|
|
4
|
+
import { selectModel } from "./model-router.js";
|
|
5
|
+
import { postFeedItem } from "../store/feed.js";
|
|
6
|
+
function buildFacilitatorPrompt(lead, agents, task) {
|
|
7
|
+
const roster = agents
|
|
8
|
+
.filter((a) => !a.is_lead)
|
|
9
|
+
.map((a) => `- ${a.character_name} (${a.role_title})${a.is_qa ? " [QA]" : ""}${a.is_test ? " [TEST]" : ""}`)
|
|
10
|
+
.join("\n");
|
|
11
|
+
return `# Planning Meeting Facilitator: ${lead.character_name}
|
|
12
|
+
|
|
13
|
+
You are facilitating a planning meeting for your squad. Your job is to gather input from specialists, then synthesize a clear action plan.
|
|
14
|
+
|
|
15
|
+
## The Task
|
|
16
|
+
${task}
|
|
17
|
+
|
|
18
|
+
## Your Team (Specialists)
|
|
19
|
+
${roster}
|
|
20
|
+
|
|
21
|
+
## Instructions
|
|
22
|
+
For each specialist who is relevant to this task, think about what their domain expertise would contribute. Then synthesize ALL perspectives into a structured plan.
|
|
23
|
+
|
|
24
|
+
Consider each relevant specialist's likely concerns:
|
|
25
|
+
${agents
|
|
26
|
+
.filter((a) => !a.is_lead)
|
|
27
|
+
.map((a) => `- ${a.character_name} (${a.role_title}): What risks, technical suggestions, or constraints would they raise?`)
|
|
28
|
+
.join("\n")}
|
|
29
|
+
|
|
30
|
+
## Output Format
|
|
31
|
+
Produce a plan in this exact format:
|
|
32
|
+
|
|
33
|
+
### Task Summary
|
|
34
|
+
(One sentence summary of what we're building)
|
|
35
|
+
|
|
36
|
+
### Plan
|
|
37
|
+
(Numbered list of work items with agent assignments)
|
|
38
|
+
|
|
39
|
+
### Risks & Concerns
|
|
40
|
+
(Bullet list of risks identified, with mitigation strategies)
|
|
41
|
+
|
|
42
|
+
### Dependencies
|
|
43
|
+
(What must happen in order, what can be parallel)
|
|
44
|
+
|
|
45
|
+
### Assignments
|
|
46
|
+
(Clear mapping: Agent → what they own)
|
|
47
|
+
|
|
48
|
+
## Rules
|
|
49
|
+
- You are ONLY planning — do NOT execute any work
|
|
50
|
+
- Assign work to specialists based on their role titles
|
|
51
|
+
- Identify what can be done in parallel vs what has dependencies
|
|
52
|
+
- Flag if any expertise is missing from the team
|
|
53
|
+
${lead.persona ? `\n## Your Style:\n${lead.persona}` : ""}
|
|
54
|
+
`;
|
|
55
|
+
}
|
|
56
|
+
function buildSpecialistPrompt(agent, task) {
|
|
57
|
+
return `# Planning Input: ${agent.character_name}
|
|
58
|
+
|
|
59
|
+
You are ${agent.character_name}, a ${agent.role_title}. Your team is planning a new task and needs your expert input.
|
|
60
|
+
|
|
61
|
+
## The Task
|
|
62
|
+
${task}
|
|
63
|
+
|
|
64
|
+
## Your Role
|
|
65
|
+
Provide input ONLY from your area of expertise (${agent.role_title}). Be specific and actionable.
|
|
66
|
+
|
|
67
|
+
## Respond With
|
|
68
|
+
1. **Concerns/Risks**: What could go wrong in your domain?
|
|
69
|
+
2. **Technical Suggestions**: How would you approach your part?
|
|
70
|
+
3. **Dependencies**: What do you need from other team members before you can start?
|
|
71
|
+
4. **Estimated Complexity**: Simple / Moderate / Complex for your portion
|
|
72
|
+
5. **Questions**: Anything unclear that affects your work?
|
|
73
|
+
|
|
74
|
+
Keep your response focused and concise — this is a planning meeting, not implementation.
|
|
75
|
+
${agent.persona ? `\n## Your Style:\n${agent.persona}` : ""}
|
|
76
|
+
`;
|
|
77
|
+
}
|
|
78
|
+
export async function planningMeeting(squadId, task) {
|
|
79
|
+
const lead = getLeadForSquad(squadId);
|
|
80
|
+
if (!lead) {
|
|
81
|
+
throw new Error("Squad has no team lead. Add a lead agent first.");
|
|
82
|
+
}
|
|
83
|
+
const agents = getAgentsForSquad(squadId);
|
|
84
|
+
const relevantAgents = agents.filter((a) => !a.is_lead);
|
|
85
|
+
if (relevantAgents.length === 0) {
|
|
86
|
+
throw new Error("Squad has no specialists to consult. Add agents first.");
|
|
87
|
+
}
|
|
88
|
+
const client = await getClient();
|
|
89
|
+
// Phase 1: Gather specialist input in parallel
|
|
90
|
+
const specialistInputs = await Promise.allSettled(relevantAgents.map(async (agent) => {
|
|
91
|
+
const model = await selectModel("low");
|
|
92
|
+
const session = await client.createSession({
|
|
93
|
+
model,
|
|
94
|
+
streaming: true,
|
|
95
|
+
workingDirectory: process.cwd(),
|
|
96
|
+
systemMessage: { content: buildSpecialistPrompt(agent, task) },
|
|
97
|
+
onPermissionRequest: approveAll,
|
|
98
|
+
});
|
|
99
|
+
try {
|
|
100
|
+
const response = await session.sendAndWait({ prompt: "Please provide your planning input for this task." }, 60_000);
|
|
101
|
+
return {
|
|
102
|
+
agent: agent.character_name,
|
|
103
|
+
role: agent.role_title,
|
|
104
|
+
input: response?.data?.content ?? "(no response)",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await session.disconnect();
|
|
109
|
+
}
|
|
110
|
+
}));
|
|
111
|
+
// Collect successful inputs
|
|
112
|
+
const inputs = specialistInputs
|
|
113
|
+
.filter((r) => r.status === "fulfilled")
|
|
114
|
+
.map((r) => r.value);
|
|
115
|
+
const inputsSummary = inputs
|
|
116
|
+
.map((i) => `### ${i.agent} (${i.role})\n${i.input}`)
|
|
117
|
+
.join("\n\n");
|
|
118
|
+
// Phase 2: Lead synthesizes the plan
|
|
119
|
+
const facilitatorModel = await selectModel("medium");
|
|
120
|
+
const facilitatorSession = await client.createSession({
|
|
121
|
+
model: facilitatorModel,
|
|
122
|
+
streaming: true,
|
|
123
|
+
workingDirectory: process.cwd(),
|
|
124
|
+
systemMessage: { content: buildFacilitatorPrompt(lead, agents, task) },
|
|
125
|
+
onPermissionRequest: approveAll,
|
|
126
|
+
});
|
|
127
|
+
let plan;
|
|
128
|
+
try {
|
|
129
|
+
const prompt = `Here is the input gathered from your team:\n\n${inputsSummary}\n\nNow synthesize this into a clear, structured action plan.`;
|
|
130
|
+
const response = await facilitatorSession.sendAndWait({ prompt }, 120_000);
|
|
131
|
+
plan = response?.data?.content ?? "Planning meeting completed but no plan was produced.";
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
await facilitatorSession.disconnect();
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
plan,
|
|
138
|
+
participants: [lead.character_name, ...inputs.map((i) => i.agent)],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
export async function squadMeeting(squadId, task, executeAfter) {
|
|
142
|
+
const result = await planningMeeting(squadId, task);
|
|
143
|
+
const summary = `## Planning Meeting Complete\n\n**Participants:** ${result.participants.join(", ")}\n\n${result.plan}`;
|
|
144
|
+
if (!executeAfter) {
|
|
145
|
+
// Post to feed and wait for user to trigger execution
|
|
146
|
+
postFeedItem(`squad-${squadId}`, "Planning meeting complete — awaiting approval", summary);
|
|
147
|
+
return summary;
|
|
148
|
+
}
|
|
149
|
+
// Execute: delegate with the plan as additional context
|
|
150
|
+
const { delegateTask } = await import("./agents.js");
|
|
151
|
+
const enrichedTask = `${task}\n\n---\n## Approved Plan (from team meeting)\n${result.plan}`;
|
|
152
|
+
const execResult = await delegateTask(squadId, enrichedTask);
|
|
153
|
+
return `Meeting held, then executed.\n\n${summary}\n\n---\n## Execution Result\n${execResult}`;
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=ceremonies.js.map
|
|
@@ -26,13 +26,19 @@ You are IO, a personal AI assistant daemon. You run 24/7 on the user's machine,
|
|
|
26
26
|
- Never delegate unless explicitly asked — creating an issue ≠ request to start work
|
|
27
27
|
- When creating squads, research the universe dynamically — never use hardcoded character lists
|
|
28
28
|
- **Always use the gh CLI** for all GitHub interactions (repos, issues, PRs, releases, actions, etc.). Only fall back to the GitHub API or other methods if gh is unavailable or cannot accomplish the task.
|
|
29
|
+
- For complex tasks involving multiple specialists, use squad_meeting to have the team plan together before executing. Use squad_delegate for straightforward single-domain tasks.
|
|
30
|
+
- If the user says "plan this" or "have the team meet" → use squad_meeting with execute_after=false
|
|
31
|
+
- If the user says "do this" for a complex task → use squad_meeting with execute_after=true
|
|
32
|
+
- If the user says "just do it" or it's a simple task → use squad_delegate directly
|
|
29
33
|
|
|
30
34
|
## Squad Coverage Requirements
|
|
31
35
|
Every squad MUST have:
|
|
32
|
-
1. A dedicated team lead (PM/Senior Engineer, coordination-only)
|
|
36
|
+
1. A dedicated team lead (PM/Senior Engineer, coordination-only — **never writes code**)
|
|
33
37
|
2. At least one QA reviewer
|
|
34
38
|
3. At least one agent with a test/quality role title
|
|
35
39
|
|
|
40
|
+
Team leads are strictly managers/delegators/reviewers. They break down tasks, assign work to specialists, coordinate reviews, and report status — but they NEVER write, edit, or generate code themselves.
|
|
41
|
+
|
|
36
42
|
## GitHub Self-Review Limitation
|
|
37
43
|
All squad agents share the repo owner's gh identity. GitHub blocks self-approval. Veto reviewers use --comment with "LGTM" instead of --approve. Merge criteria: all veto-capable members have posted approving comments + CI passes + no conflicts.
|
|
38
44
|
${selfEditBlock}
|
package/dist/copilot/tools.js
CHANGED
|
@@ -134,7 +134,7 @@ export function createTools() {
|
|
|
134
134
|
},
|
|
135
135
|
}),
|
|
136
136
|
defineTool("squad_delegate", {
|
|
137
|
-
description: "Delegate a task to a squad's team lead. The lead will break it down and route to specialists.",
|
|
137
|
+
description: "Delegate a task to a squad's team lead. The lead will break it down and route to specialists. Use this for direct execution without a planning meeting.",
|
|
138
138
|
parameters: z.object({
|
|
139
139
|
squad_id: z.string().describe("Squad ID"),
|
|
140
140
|
task: z.string().describe("Detailed task description"),
|
|
@@ -146,6 +146,20 @@ export function createTools() {
|
|
|
146
146
|
return result;
|
|
147
147
|
},
|
|
148
148
|
}),
|
|
149
|
+
defineTool("squad_meeting", {
|
|
150
|
+
description: "Trigger a planning meeting for a squad. All relevant specialists provide input before work begins. Use this for complex multi-agent tasks where team input improves the plan. Set execute_after=true to start work immediately after planning, or false to post the plan to the feed for user review.",
|
|
151
|
+
parameters: z.object({
|
|
152
|
+
squad_id: z.string().describe("Squad ID"),
|
|
153
|
+
task: z.string().describe("Detailed task description for the team to plan"),
|
|
154
|
+
execute_after: z
|
|
155
|
+
.boolean()
|
|
156
|
+
.describe("If true, execute the plan immediately after the meeting. If false, post plan to feed and wait for user approval."),
|
|
157
|
+
}),
|
|
158
|
+
handler: async ({ squad_id, task, execute_after }) => {
|
|
159
|
+
const { squadMeeting } = await import("./ceremonies.js");
|
|
160
|
+
return await squadMeeting(squad_id, task, execute_after);
|
|
161
|
+
},
|
|
162
|
+
}),
|
|
149
163
|
defineTool("squad_task_status", {
|
|
150
164
|
description: "Check the status of tasks for a squad",
|
|
151
165
|
parameters: z.object({
|