@dreki-gg/pi-subagent 0.8.3 → 0.8.4
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @dreki-gg/pi-subagent
|
|
2
2
|
|
|
3
|
+
## 0.8.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`376864c`](https://github.com/dreki-gg/pi-extensions/commit/376864c37cefa47530363b47055311269c1724a8) Thanks [@jalbarrang](https://github.com/jalbarrang)! - feat(subagent): show live tool-aware status in working message during /run-agent
|
|
8
|
+
|
|
9
|
+
Previously `/run-agent` only showed a transient notification, leaving users with no visibility into what the background agent was doing (especially after a fork-at session switch that visually looks like a reload). Now the working message updates in real-time as the agent works:
|
|
10
|
+
|
|
11
|
+
- `scout · starting...`
|
|
12
|
+
- `scout · reading …/src/utils.ts`
|
|
13
|
+
- `scout · $ bun test --filter...`
|
|
14
|
+
- `scout · editing …/config.json`
|
|
15
|
+
- `scout · thinking...`
|
|
16
|
+
|
|
17
|
+
Added `onToolExecutionStart` callback to `spawnPiAgent` and `runAgent` to surface `tool_execution_start` events from the JSON stream.
|
|
18
|
+
|
|
3
19
|
## 0.8.3
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ResolvedPaths } from '@earendil-works/pi-coding-agent';
|
|
2
2
|
import { discoverAgents, type AgentScope } from './agents.js';
|
|
3
3
|
import type { AgentResult } from './agent-runner-types.js';
|
|
4
|
-
import { emptyUsage, spawnPiAgent } from './spawn-utils.js';
|
|
4
|
+
import { emptyUsage, spawnPiAgent, type ToolExecutionStartEvent } from './spawn-utils.js';
|
|
5
5
|
|
|
6
6
|
export type OnPhaseUpdate = (phaseName: string, agentName: string, result: AgentResult) => void;
|
|
7
7
|
|
|
@@ -11,6 +11,7 @@ export interface RunAgentOptions {
|
|
|
11
11
|
model?: string;
|
|
12
12
|
thinking?: string;
|
|
13
13
|
onUpdate?: OnPhaseUpdate;
|
|
14
|
+
onToolExecutionStart?: (event: ToolExecutionStartEvent) => void;
|
|
14
15
|
phaseName?: string;
|
|
15
16
|
signal?: AbortSignal;
|
|
16
17
|
resolvedPaths?: ResolvedPaths;
|
|
@@ -76,6 +77,7 @@ export async function runAgent(
|
|
|
76
77
|
options.onUpdate(options.phaseName ?? 'unknown', agentName, { ...result });
|
|
77
78
|
}
|
|
78
79
|
},
|
|
80
|
+
onToolExecutionStart: options.onToolExecutionStart,
|
|
79
81
|
});
|
|
80
82
|
|
|
81
83
|
result.exitCode = spawnResult.exitCode;
|
|
@@ -43,12 +43,61 @@ import { extractRecentConversation } from './synthesis.js';
|
|
|
43
43
|
import type { AgentResult } from './agent-runner-types.js';
|
|
44
44
|
import { getFinalText } from './agent-result-utils.js';
|
|
45
45
|
import { buildHandoffFromResult, renderHandoffForPrompt } from './handoffs.js';
|
|
46
|
-
import { emptyUsage, spawnPiAgent } from './spawn-utils.js';
|
|
46
|
+
import { emptyUsage, spawnPiAgent, type ToolExecutionStartEvent } from './spawn-utils.js';
|
|
47
47
|
|
|
48
48
|
const MAX_PARALLEL_TASKS = 8;
|
|
49
49
|
const MAX_CONCURRENCY = 4;
|
|
50
50
|
const COLLAPSED_ITEM_COUNT = 10;
|
|
51
51
|
|
|
52
|
+
function describeToolExecution(event: ToolExecutionStartEvent): string {
|
|
53
|
+
const shortenPath = (p: string) => {
|
|
54
|
+
const home = os.homedir();
|
|
55
|
+
const shortened = p.startsWith(home) ? `~${p.slice(home.length)}` : p;
|
|
56
|
+
// Show only the last 2 path segments for brevity
|
|
57
|
+
const parts = shortened.split('/');
|
|
58
|
+
return parts.length > 3 ? `…/${parts.slice(-2).join('/')}` : shortened;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const args = event.args;
|
|
62
|
+
switch (event.toolName) {
|
|
63
|
+
case 'bash': {
|
|
64
|
+
const cmd = (args.command as string) || '';
|
|
65
|
+
const preview = cmd.length > 50 ? `${cmd.slice(0, 50)}…` : cmd;
|
|
66
|
+
return `$ ${preview}`;
|
|
67
|
+
}
|
|
68
|
+
case 'read': {
|
|
69
|
+
const p = ((args.file_path || args.path) as string) || '';
|
|
70
|
+
return `reading ${shortenPath(p)}`;
|
|
71
|
+
}
|
|
72
|
+
case 'write': {
|
|
73
|
+
const p = ((args.file_path || args.path) as string) || '';
|
|
74
|
+
return `writing ${shortenPath(p)}`;
|
|
75
|
+
}
|
|
76
|
+
case 'edit': {
|
|
77
|
+
const p = ((args.file_path || args.path) as string) || '';
|
|
78
|
+
return `editing ${shortenPath(p)}`;
|
|
79
|
+
}
|
|
80
|
+
case 'grep': {
|
|
81
|
+
const pattern = (args.pattern as string) || '';
|
|
82
|
+
return `grep /${pattern}/`;
|
|
83
|
+
}
|
|
84
|
+
case 'find': {
|
|
85
|
+
const pattern = (args.pattern as string) || '*';
|
|
86
|
+
return `find ${pattern}`;
|
|
87
|
+
}
|
|
88
|
+
case 'ls':
|
|
89
|
+
return `ls ${shortenPath((args.path as string) || '.')}`;
|
|
90
|
+
case 'web_search':
|
|
91
|
+
return `searching: ${(args.query as string)?.slice(0, 40) || '…'}`;
|
|
92
|
+
case 'web_visit':
|
|
93
|
+
return 'visiting page';
|
|
94
|
+
case 'subagent':
|
|
95
|
+
return `spawning ${(args.agent as string) || 'subagent'}`;
|
|
96
|
+
default:
|
|
97
|
+
return event.toolName;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
52
101
|
function formatTokens(count: number): string {
|
|
53
102
|
if (count < 1000) return count.toString();
|
|
54
103
|
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
|
|
@@ -1439,13 +1488,29 @@ export default function (pi: ExtensionAPI) {
|
|
|
1439
1488
|
`Running agent: ${agent.name} [${agent.source}${forked ? ', forked' : ', inline'}${selectedModel ? `, model=${selectedModel}` : ''}${selectedThinking ? `, thinking=${selectedThinking}` : ''}]`,
|
|
1440
1489
|
'info',
|
|
1441
1490
|
);
|
|
1491
|
+
let lastToolDescription = '';
|
|
1492
|
+
const updateWorkingStatus = (toolDesc?: string) => {
|
|
1493
|
+
if (toolDesc) lastToolDescription = toolDesc;
|
|
1494
|
+
const parts = [agent.name];
|
|
1495
|
+
if (lastToolDescription) parts.push(lastToolDescription);
|
|
1496
|
+
commandUi.setWorkingMessage(parts.join(' · '));
|
|
1497
|
+
};
|
|
1498
|
+
updateWorkingStatus('starting...');
|
|
1442
1499
|
|
|
1443
1500
|
const result = await runAgent(commandCwd, agent.name, task, {
|
|
1444
1501
|
agentScope,
|
|
1445
1502
|
resolvedPaths,
|
|
1446
1503
|
model,
|
|
1447
1504
|
thinking,
|
|
1505
|
+
onUpdate: () => {
|
|
1506
|
+
// When a turn completes and the agent is thinking about next steps
|
|
1507
|
+
updateWorkingStatus('thinking...');
|
|
1508
|
+
},
|
|
1509
|
+
onToolExecutionStart: (event) => {
|
|
1510
|
+
updateWorkingStatus(describeToolExecution(event));
|
|
1511
|
+
},
|
|
1448
1512
|
});
|
|
1513
|
+
commandUi.setWorkingMessage();
|
|
1449
1514
|
const failed = result.exitCode !== 0 || result.stopReason === 'error';
|
|
1450
1515
|
const output = getFinalText(result).trim();
|
|
1451
1516
|
|
|
@@ -57,6 +57,12 @@ function cleanupTempFiles(
|
|
|
57
57
|
if (tmpPromptDir) try { fs.rmdirSync(tmpPromptDir); } catch { /* ignore */ }
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
export interface ToolExecutionStartEvent {
|
|
61
|
+
toolCallId: string;
|
|
62
|
+
toolName: string;
|
|
63
|
+
args: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
export interface SpawnPiAgentOptions {
|
|
61
67
|
cwd: string;
|
|
62
68
|
agentName: string;
|
|
@@ -68,6 +74,7 @@ export interface SpawnPiAgentOptions {
|
|
|
68
74
|
signal?: AbortSignal;
|
|
69
75
|
onMessage?: (msg: Message) => void;
|
|
70
76
|
onToolResult?: (msg: Message) => void;
|
|
77
|
+
onToolExecutionStart?: (event: ToolExecutionStartEvent) => void;
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
export interface SpawnPiAgentResult {
|
|
@@ -158,6 +165,14 @@ export async function spawnPiAgent(options: SpawnPiAgentOptions): Promise<SpawnP
|
|
|
158
165
|
result.messages.push(event.message as Message);
|
|
159
166
|
options.onToolResult?.(event.message as Message);
|
|
160
167
|
}
|
|
168
|
+
|
|
169
|
+
if (event.type === 'tool_execution_start' && event.toolName) {
|
|
170
|
+
options.onToolExecutionStart?.({
|
|
171
|
+
toolCallId: event.toolCallId ?? '',
|
|
172
|
+
toolName: event.toolName,
|
|
173
|
+
args: event.args ?? {},
|
|
174
|
+
});
|
|
175
|
+
}
|
|
161
176
|
};
|
|
162
177
|
|
|
163
178
|
proc.stdout.on('data', (data: Buffer) => {
|
package/package.json
CHANGED