pi-optchat 0.6.1 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/src/agents.ts +21 -7
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ Ask in plain words, for example: "Spawn an agent to investigate this repository
|
|
|
69
69
|
|
|
70
70
|
- Children get the profile's memory view (frozen at launch), its instructions, read-only `zoom`/`date`, and normal coding tools plus your installed extensions.
|
|
71
71
|
- Each child reports back on its own when it finishes. The parent stays alive to receive reports; it never polls.
|
|
72
|
-
- The parent can send a running child guidance with `tell
|
|
72
|
+
- The parent can send a running child guidance with `tell`, and the child can message its parent mid-run with `tell_parent` (a question, an early finding). It reaches the parent like a report, marked "still running": between tool calls if the parent is busy, or waking it if it's waiting.
|
|
73
73
|
- Delegation goes up to three levels below the main agent (child, grandchild, great-grandchild).
|
|
74
74
|
- At most 8 agents can be active per profile, including parents waiting on descendants. Going over a limit returns an error; there is no queue.
|
|
75
75
|
- Stopping an agent stops its whole subtree. A failed parent stops its descendants.
|
|
@@ -140,7 +140,7 @@ Each profile is locked to one Pi process. If you open the same profile in a seco
|
|
|
140
140
|
|
|
141
141
|
- Your first message starts a subagent in the second window's working directory. Later messages continue the same conversation.
|
|
142
142
|
- The subagent runs inside the original process, which stays the only writer of memory. It appears in the original window's inspector and uses one of the 8 agent slots. While it is open, the original window can't switch profile or import.
|
|
143
|
-
- The main agent is told when the conversation starts. Use `/tell-main <message>` to message it yourself; the subagent
|
|
143
|
+
- The main agent is told when the conversation starts. Use `/tell-main <message>` to message it yourself; the subagent can use `tell_parent`, and the main agent replies with `tell`. Routine turns don't wake the main agent.
|
|
144
144
|
- Run `/complete` when done. The window closes, remaining work stops, and the compactor writes a handoff for the main agent: decisions, changes, evidence, failures, unfinished work, and links to the transcripts.
|
|
145
145
|
- Closing or force-quitting the window also produces a handoff, marked **interrupted**.
|
|
146
146
|
- If the original window is closed cleanly, handoffs are delivered on next start. If it is killed, reopening the profile recovers unfinished handoffs (work is not restarted).
|
package/package.json
CHANGED
package/src/agents.ts
CHANGED
|
@@ -115,7 +115,8 @@ export class Children {
|
|
|
115
115
|
if (cancelled()) throw new Error('Parent or profile is stopping.');
|
|
116
116
|
const id = randomUUID().slice(0, 8), directory = task.cwd ?? cwd;
|
|
117
117
|
const delegation = depth < 3 ? 'You may delegate parts of your assigned task with spawn when useful. Child reports arrive automatically after your current run ends; the harness keeps you alive to receive them. Never poll, sleep, or wait in a tool for children. Finish your current work and return; you will be prompted with their results. The profile allows 8 active agents total.' : 'You are at the maximum delegation depth. Complete your task with your own tools.';
|
|
118
|
-
const instructions = [this.instructions(), delegation, connected ? 'You are speaking directly with the user in a connected window. Continue this conversation across requests. Use
|
|
118
|
+
const instructions = [this.instructions(), delegation, connected ? 'You are speaking directly with the user in a connected window. Continue this conversation across requests. Use tell_parent for questions or findings the main agent needs now. A handoff will be generated when the user completes or disconnects the window.'
|
|
119
|
+
: 'Use tell_parent only when your parent needs something now (a blocking question, an important early finding, or when asked to). Your final answer is delivered automatically; do not repeat it with tell_parent.'].filter(Boolean).join('\n\n');
|
|
119
120
|
// The user's settings list their installed packages; a copy in memory keeps the child from writing them back.
|
|
120
121
|
const settingsManager = SettingsManager.inMemory({ ...SettingsManager.create(directory, getAgentDir()).getSettings(), compaction: { enabled: false }, cacheWarming: 'off' });
|
|
121
122
|
const loader = new DefaultResourceLoader({ cwd: directory, agentDir: getAgentDir(), settingsManager,
|
|
@@ -135,12 +136,7 @@ export class Children {
|
|
|
135
136
|
await loader.reload();
|
|
136
137
|
const { session } = await (this.options.createSession ?? createAgentSession)({ cwd: directory, resourceLoader: loader, settingsManager,
|
|
137
138
|
model, thinkingLevel: selected.thinking, sessionManager: SessionManager.create(directory, join(this.profileDirectory, 'runs')),
|
|
138
|
-
customTools: [...memoryTools(() => this.memory), ...(depth < 3 ? this.delegationTools(id, directory) : []),
|
|
139
|
-
name: 'tell_main', label: 'Message main agent', description: 'Send the main agent a question or important finding. Its reply can arrive as guidance; continue useful work instead of polling.',
|
|
140
|
-
parameters: Type.Object({ message: Type.String() }), execute: async (_id: string, args: { message: string }) => {
|
|
141
|
-
await this.report(`[${id}] Connected agent message: ${args.message}`); return result('Message sent to the main agent.');
|
|
142
|
-
},
|
|
143
|
-
}] : [])],
|
|
139
|
+
customTools: [...memoryTools(() => this.memory), ...(depth < 3 ? this.delegationTools(id, directory) : []), this.parentTool(id, parentId, connected)],
|
|
144
140
|
excludeTools: depth < 3 ? [] : ['spawn', 'tell'],
|
|
145
141
|
});
|
|
146
142
|
await session.bindExtensions({});
|
|
@@ -185,6 +181,24 @@ export class Children {
|
|
|
185
181
|
},
|
|
186
182
|
}];
|
|
187
183
|
}
|
|
184
|
+
/** Lets a child message its parent mid-run, the way tell lets the parent guide it. */
|
|
185
|
+
private parentTool(id: string, parentId: string | undefined, connected: boolean) {
|
|
186
|
+
return { name: 'tell_parent', label: parentId ? 'Message parent agent' : 'Message main agent',
|
|
187
|
+
description: `Send ${parentId ? 'your parent agent' : 'the main agent'} a question or important finding while you keep working. Its reply can arrive as guidance; continue useful work instead of polling. Your final answer is delivered automatically.`,
|
|
188
|
+
parameters: Type.Object({ message: Type.String() }), execute: async (_id: string, args: { message: string }) => {
|
|
189
|
+
const message = args.message.trim();
|
|
190
|
+
if (!message) throw new Error('Message is empty.');
|
|
191
|
+
const text = `[${id}] ${connected ? 'Connected agent message' : 'Message from subagent (still running)'}: ${message}`;
|
|
192
|
+
if (!parentId) { await this.report(text); return result('Message sent to the main agent.'); }
|
|
193
|
+
const parent = this.running.get(parentId);
|
|
194
|
+
if (!parent || !['running', 'waiting'].includes(parent.info.state)) throw new Error('Your parent is no longer running.');
|
|
195
|
+
if (parent.info.state === 'waiting') { parent.pendingReports.push(text); parent.wake?.(); }
|
|
196
|
+
else await parent.session.steer(text);
|
|
197
|
+
this.changed();
|
|
198
|
+
return result(`Message sent to parent ${parentId}.`);
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
}
|
|
188
202
|
private directChildren(id: string) { return [...this.running.values()].filter(c => c.info.parentId === id); }
|
|
189
203
|
private async execute(live: LiveRun, view: string) {
|
|
190
204
|
const { session, info } = live;
|