@xynogen/pix-subagent 0.1.1 → 0.1.3
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 +1 -1
- package/package.json +1 -1
- package/src/index.ts +2 -3
- package/src/tools.ts +5 -7
- package/src/ui/widget.ts +16 -24
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Pi extension — planner-driven sub-agents with 3 tools, live widget (model alwa
|
|
|
8
8
|
pi install npm:@xynogen/pix-subagent
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
> Also included in [`@xynogen/pix-core`](https://
|
|
11
|
+
> Also included in [`@xynogen/pix-core`](https://www.npmjs.com/package/@xynogen/pix-core):
|
|
12
12
|
>
|
|
13
13
|
> ```bash
|
|
14
14
|
> pi install npm:@xynogen/pix-core
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -86,7 +86,6 @@ export default function registerPixSubagent(pi: ExtensionAPI): void {
|
|
|
86
86
|
// onComplete — fire subagent-notification nudge for each finished bg agent
|
|
87
87
|
(record) => {
|
|
88
88
|
agentActivity.delete(record.id);
|
|
89
|
-
widget.markFinished(record.id);
|
|
90
89
|
|
|
91
90
|
if (record.resultConsumed) {
|
|
92
91
|
widget.update();
|
|
@@ -191,9 +190,9 @@ export default function registerPixSubagent(pi: ExtensionAPI): void {
|
|
|
191
190
|
}
|
|
192
191
|
});
|
|
193
192
|
|
|
194
|
-
pi.on("
|
|
195
|
-
widget.setUICtx(ctx.ui as Parameters<typeof widget.setUICtx>[0]);
|
|
193
|
+
pi.on("turn_start", (_event, ctx) => {
|
|
196
194
|
widget.onTurnStart();
|
|
195
|
+
widget.setUICtx(ctx.ui as Parameters<typeof widget.setUICtx>[0]);
|
|
197
196
|
widget.ensureTimer();
|
|
198
197
|
});
|
|
199
198
|
|
package/src/tools.ts
CHANGED
|
@@ -180,10 +180,10 @@ If the target is already known, use a direct tool — \`read\` for a known path,
|
|
|
180
180
|
|
|
181
181
|
## Usage notes
|
|
182
182
|
- Always include a short (3-5 word) description summarizing what the agent will do (shown in UI).
|
|
183
|
-
- When you launch multiple agents for independent work, send them in a single message with multiple tool uses,
|
|
183
|
+
- When you launch multiple agents for independent work, send them in a single message with multiple tool uses, so they run concurrently.
|
|
184
184
|
- When the agent is done, it returns a single message. The result is not visible to the user — to show the user, send a text message with a concise summary.
|
|
185
185
|
- Trust but verify: an agent's summary describes what it intended to do, not what it did. When an agent writes or edits code, check the actual changes before reporting work as done.
|
|
186
|
-
- Use run_in_background
|
|
186
|
+
- Use run_in_background: true only when you explicitly do not need to see the output inline (e.g. fire-and-forget background tasks). Default is foreground — the agent streams inline and you see its work as it runs.
|
|
187
187
|
- Use resume with an agent ID to continue a previous agent's work.
|
|
188
188
|
- Use agent_steer to send mid-run messages to a running background agent.
|
|
189
189
|
- Use model to specify a model from the available models list above (provider/id or fuzzy e.g. "haiku").
|
|
@@ -296,12 +296,10 @@ export function createAgentTool(
|
|
|
296
296
|
|
|
297
297
|
const stats = buildStats(details, theme);
|
|
298
298
|
|
|
299
|
-
// Streaming / running
|
|
299
|
+
// Streaming / running — live state shown by the ● Agents widget, so the
|
|
300
|
+
// inline transcript stays empty to avoid stacking one card per agent.
|
|
300
301
|
if (isPartial || details.status === "running") {
|
|
301
|
-
|
|
302
|
-
let line = theme.fg("accent", frame) + (stats ? ` ${stats}` : "");
|
|
303
|
-
line += `\n${theme.fg("dim", ` ⎿ ${details.activity ?? "thinking…"}`)}`;
|
|
304
|
-
return new Text(line, 0, 0);
|
|
302
|
+
return new Text("", 0, 0);
|
|
305
303
|
}
|
|
306
304
|
|
|
307
305
|
// Background launched
|
package/src/ui/widget.ts
CHANGED
|
@@ -133,8 +133,8 @@ export class AgentWidget {
|
|
|
133
133
|
private uiCtx: UICtx | undefined;
|
|
134
134
|
private widgetFrame = 0;
|
|
135
135
|
private widgetInterval: ReturnType<typeof setInterval> | undefined;
|
|
136
|
-
private
|
|
137
|
-
private static readonly
|
|
136
|
+
private static readonly FINISHED_LINGER_MS = 5_000;
|
|
137
|
+
private static readonly ERROR_LINGER_MS = 15_000;
|
|
138
138
|
private widgetRegistered = false;
|
|
139
139
|
private tui: unknown = undefined;
|
|
140
140
|
private lastStatusText: string | undefined;
|
|
@@ -154,9 +154,6 @@ export class AgentWidget {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
onTurnStart() {
|
|
157
|
-
for (const [id, age] of this.finishedTurnAge) {
|
|
158
|
-
this.finishedTurnAge.set(id, age + 1);
|
|
159
|
-
}
|
|
160
157
|
this.update();
|
|
161
158
|
}
|
|
162
159
|
|
|
@@ -166,18 +163,14 @@ export class AgentWidget {
|
|
|
166
163
|
}
|
|
167
164
|
}
|
|
168
165
|
|
|
169
|
-
private shouldShowFinished(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
markFinished(agentId: string) {
|
|
178
|
-
if (!this.finishedTurnAge.has(agentId)) {
|
|
179
|
-
this.finishedTurnAge.set(agentId, 0);
|
|
180
|
-
}
|
|
166
|
+
private shouldShowFinished(status: string, completedAt: number): boolean {
|
|
167
|
+
// Linger a few seconds after finish, then drop. The ✓ … Done line in the
|
|
168
|
+
// transcript is the permanent record; errors stay longer so failures are
|
|
169
|
+
// noticed. The 80ms widget timer re-evaluates this continuously.
|
|
170
|
+
const linger = ERROR_STATUSES.has(status)
|
|
171
|
+
? AgentWidget.ERROR_LINGER_MS
|
|
172
|
+
: AgentWidget.FINISHED_LINGER_MS;
|
|
173
|
+
return Date.now() - completedAt < linger;
|
|
181
174
|
}
|
|
182
175
|
|
|
183
176
|
private renderFinishedLine(
|
|
@@ -246,8 +239,8 @@ export class AgentWidget {
|
|
|
246
239
|
(a) =>
|
|
247
240
|
a.status !== "running" &&
|
|
248
241
|
a.status !== "queued" &&
|
|
249
|
-
a.completedAt &&
|
|
250
|
-
this.shouldShowFinished(a.
|
|
242
|
+
a.completedAt != null &&
|
|
243
|
+
this.shouldShowFinished(a.status, a.completedAt),
|
|
251
244
|
);
|
|
252
245
|
|
|
253
246
|
if (running.length === 0 && queued.length === 0 && finished.length === 0)
|
|
@@ -403,7 +396,10 @@ export class AgentWidget {
|
|
|
403
396
|
for (const a of allAgents) {
|
|
404
397
|
if (a.status === "running") runningCount++;
|
|
405
398
|
else if (a.status === "queued") queuedCount++;
|
|
406
|
-
else if (
|
|
399
|
+
else if (
|
|
400
|
+
a.completedAt != null &&
|
|
401
|
+
this.shouldShowFinished(a.status, a.completedAt)
|
|
402
|
+
)
|
|
407
403
|
hasFinished = true;
|
|
408
404
|
}
|
|
409
405
|
const hasActive = runningCount > 0 || queuedCount > 0;
|
|
@@ -422,10 +418,6 @@ export class AgentWidget {
|
|
|
422
418
|
clearInterval(this.widgetInterval);
|
|
423
419
|
this.widgetInterval = undefined;
|
|
424
420
|
}
|
|
425
|
-
for (const [id] of this.finishedTurnAge) {
|
|
426
|
-
if (!allAgents.some((a) => a.id === id))
|
|
427
|
-
this.finishedTurnAge.delete(id);
|
|
428
|
-
}
|
|
429
421
|
return;
|
|
430
422
|
}
|
|
431
423
|
|