pi-subagents-lite 1.2.0 → 1.3.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/README.md CHANGED
@@ -18,13 +18,13 @@ Every tool the LLM sees costs tokens — in the system prompt, and in every turn
18
18
  | `promptGuidelines` with rules | _(none)_ |
19
19
  | Parameters with `.description()` | Bare `Type.String()` |
20
20
 
21
- Tool names like `Agent` and `StopAgent`, and parameter names like `prompt`, `description`, `run_in_background` are self-documenting. The LLM infers usage from the schema — no verbose descriptions needed. Tool results reinforce correct usage with clear success/error messages.
21
+ Tool names like `Agent`, `StopAgent`, and `AgentStatus`, and parameter names like `prompt`, `description`, `run_in_background` are self-documenting. The LLM infers usage from the schema — no verbose descriptions needed. Tool results reinforce correct usage with clear success/error messages.
22
22
 
23
- **Result:** foreground and background agents, custom agent types, per-model concurrency, cost tracking, steering, model overrides — all with minimal token overhead.
23
+ **Result:** foreground and background agents, custom agent types, per-model concurrency, cost tracking, steering, model overrides, agent status — all with minimal token overhead.
24
24
 
25
25
  ## Features
26
26
 
27
- - **Two tools** — `Agent` (spawn) and `StopAgent` (stop)
27
+ - **Three tools** — `Agent` (spawn), `StopAgent` (stop), and `AgentStatus` (list agents)
28
28
  - **Manual spawn** — spawn agents from the `/agents` menu without asking the LLM. Full control over model, thinking, turns, and background mode.
29
29
  - **Foreground & background** — block or fire-and-forget with auto-delivered results
30
30
  - **Custom agent types** — define via `.md` files with YAML frontmatter (tools, model, thinking, turn limits)
@@ -98,7 +98,7 @@ Stop a running agent at any time via /agents command
98
98
  | Parameter | Required | Description |
99
99
  |---|---|---|
100
100
  | `prompt` | ✅ | The task for the sub-agent |
101
- | `description` | | Brief description for the LLM caller |
101
+ | `description` | | Brief description for the LLM caller (optional — if omitted, derived from prompt) |
102
102
  | `agent` | | Type name — `general-purpose`, `Explore`, or any custom type you define (see [Custom Agent Types](#custom-agent-types)). The available values are **auto-populated** from `.md` files in your agent directories — drop a file, it appears in the enum. Set `hidden: true` in frontmatter to hide a type from this list (still callable by name). |
103
103
  | `run_in_background` | | Fire-and-forget; result delivered automatically when done |
104
104
  | `worktree_path` | | Absolute path to a git worktree. Agent runs in that worktree's context, discovers agents from its `.pi/agents/` directory, and displays a worktree label in the widget and menus. Path is validated against the parent repo's git common dir. |
@@ -389,6 +389,16 @@ Agent IDs can be discovered from:
389
389
  - The `StopAgent` error message, which lists all running agent IDs
390
390
  - The `/agents` menu's **Running agents** section
391
391
 
392
+ ## AgentStatus Tool
393
+
394
+ List all agents with their type, short ID, and status. Returns a formatted list of all agents (running, queued, completed, stopped, error) and a nudge message reminding the LLM not to poll.
395
+
396
+ **Usage:** The LLM calls `AgentStatus` to check on agents, but the extension nudges it to wait for automatic notifications instead of polling. This prevents wasteful repeated calls while still allowing the LLM to discover agents when needed.
397
+
398
+ **Output format:** `type·short_id·status, type·short_id·status, ...`
399
+
400
+ Example: `general-purpose·a1b2c3·running, Explore·d4e5f6·completed`
401
+
392
402
  ## Output Logs
393
403
 
394
404
  `/tmp/pi-agent-outputs/<agentId>.log` — append-only, human-readable, `tail -f` friendly. Every line is prefixed with an ISO 8601 timestamp:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-subagents-lite",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Lightweight sub-agents for pi — spawn specialized agents with isolated sessions, tools, and models.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -0,0 +1,50 @@
1
+ /**
2
+ * agent-status.ts — AgentStatus tool implementation.
3
+ *
4
+ * A lightweight informational tool that lists all agents (running, queued,
5
+ * completed, stopped, error) from the manager and returns a clear message
6
+ * about not polling for status.
7
+ */
8
+
9
+ import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
10
+ import type { AgentRecord } from "./types.js";
11
+ import { SHORT_ID_LENGTH } from "./types.js";
12
+ import { getManager } from "./state.js";
13
+
14
+ /**
15
+ * Format a single agent record as "type·short_id·status".
16
+ */
17
+ function formatAgent(record: AgentRecord): string {
18
+ const shortId = record.id.slice(0, SHORT_ID_LENGTH);
19
+ return `${record.display.type}·${shortId}·${record.lifecycle.status}`;
20
+ }
21
+
22
+ /**
23
+ * Execute the AgentStatus tool.
24
+ *
25
+ * Returns a formatted list of all agents with their type, short ID, and status,
26
+ * followed by a nudge message telling the model not to poll.
27
+ */
28
+ export async function executeAgentStatusTool(
29
+ _toolCallId: string,
30
+ _params: Record<string, unknown>,
31
+ _signal: AbortSignal | undefined,
32
+ _onUpdate: ((update: any) => void) | undefined,
33
+ _ctx: ExtensionContext,
34
+ ): Promise<any> {
35
+ const manager = getManager();
36
+ const agents = manager.listAgents();
37
+
38
+ const nudge = "Don't poll — you'll receive notifications when agents complete.";
39
+
40
+ if (agents.length === 0) {
41
+ return {
42
+ content: [{ type: "text", text: `No agents running or completed.\n\n${nudge}` }],
43
+ };
44
+ }
45
+
46
+ const formatted = agents.map(formatAgent).join(", ");
47
+ return {
48
+ content: [{ type: "text", text: `${formatted}\n\n${nudge}` }],
49
+ };
50
+ }
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ import { AgentWidget, type UICtx } from "./ui/agent-widget.js";
38
38
  import { showAgentsMainMenu } from "./menus.js";
39
39
  import { loadConfig } from "./config-io.js";
40
40
  import { executeAgentTool, executeStopAgentTool, toolCallListener, backgroundAgentIds, scheduleNudge } from "./tool-execution.js";
41
+ import { executeAgentStatusTool } from "./agent-status.js";
41
42
  import { renderAgentToolCall, renderAgentToolResult, renderSubagentResult } from "./renderer.js";
42
43
  import {
43
44
  __config,
@@ -168,7 +169,7 @@ function registerAgentTool(pi: ExtensionAPI): void {
168
169
  label: "Agent",
169
170
  parameters: Type.Object({
170
171
  prompt: Type.String(),
171
- description: Type.String(),
172
+ description: Type.Optional(Type.String()),
172
173
  agent: agentParam,
173
174
  run_in_background: Type.Optional(Type.Boolean()),
174
175
  worktree_path: Type.Optional(Type.String()),
@@ -211,6 +212,15 @@ export default function (pi: ExtensionAPI) {
211
212
  execute: executeStopAgentTool,
212
213
  });
213
214
 
215
+ // AgentStatus tool — stealth schema, list all agents and their statuses
216
+ // @ts-expect-error — description removed to save prompt tokens
217
+ pi.registerTool({
218
+ name: "AgentStatus",
219
+ label: "AgentStatus",
220
+ parameters: Type.Object({}),
221
+ execute: executeAgentStatusTool,
222
+ });
223
+
214
224
  // Message renderer — subagent-result (background agent completion)
215
225
  pi.registerMessageRenderer("subagent-result", (message, options, theme) =>
216
226
  renderSubagentResult(
@@ -253,7 +253,7 @@ export async function executeAgentTool(
253
253
  }
254
254
 
255
255
  const prompt = params.prompt as string;
256
- const description = params.description as string;
256
+ const description = (params.description as string | undefined) || prompt.split("\n")[0].slice(0, 80) || prompt.slice(0, 80);
257
257
  const runInBackground = params.run_in_background as boolean | undefined;
258
258
  const maxTurns = params.max_turns as number | undefined ?? getAgentConfig(resolvedType)?.maxTurns;
259
259