@dougbots/avenor-pi 0.8.3 → 0.10.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 +35 -5
- package/dist/index.d.ts +101 -2
- package/dist/index.js +780 -45
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -86,8 +86,9 @@ packages/pi/
|
|
|
86
86
|
├── package.json
|
|
87
87
|
├── tsdown.config.ts
|
|
88
88
|
├── src/
|
|
89
|
-
│ ├── index.ts # main extension
|
|
90
|
-
│ ├──
|
|
89
|
+
│ ├── index.ts # main extension, tool registration, commands, and hooks
|
|
90
|
+
│ ├── render.ts # host-only tool-call and result presentation
|
|
91
|
+
│ ├── types.ts # shared types and status emoji mapping
|
|
91
92
|
│ └── watch.ts # EventFeedOverlay TUI component
|
|
92
93
|
└── dist/
|
|
93
94
|
└── index.js # built output (loaded by pi)
|
|
@@ -111,7 +112,7 @@ Available tools for LLM sub-agent management:
|
|
|
111
112
|
|
|
112
113
|
| Tool | Description |
|
|
113
114
|
|---|---|
|
|
114
|
-
| `avenor_spawn` | Dispatch an agent run (blocking or fire-and-forget). Uses the `pi` backend by default; accepts `agent`, `model`, `prompt`, and `
|
|
115
|
+
| `avenor_spawn` | Dispatch an agent run (blocking or fire-and-forget). Uses the `pi` backend by default in direct mode; accepts optional `agent`, `model`, `prompt`, `dir`, `roster_file`, and `roster_entry`. |
|
|
115
116
|
| `avenor_status` | Get status of a run or all runs; use `view="lifecycle"` for compact progress and permission checks |
|
|
116
117
|
| `avenor_result` | Wait for a run and return its complete final output without transcript details |
|
|
117
118
|
| `avenor_inspect` | Review a bounded transcript, tool activity, permissions, and final output |
|
|
@@ -120,20 +121,49 @@ Available tools for LLM sub-agent management:
|
|
|
120
121
|
| `avenor_events` | Read events from a run |
|
|
121
122
|
| `avenor_shutdown` | Shut down the avenor supervisor |
|
|
122
123
|
|
|
124
|
+
### Direct and roster spawns
|
|
125
|
+
|
|
126
|
+
Direct mode permits `agent`, `model`, and `backend` to be omitted independently, including a backend-only request; omitted values use runtime defaults. Pi supplies `backend: "pi"` for direct tool calls when no backend is given. Roster mode uses both `roster_file` and `roster_entry`, and leaves backend selection to the roster entry instead of applying Pi's direct default:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{
|
|
130
|
+
"prompt": "Review the repository",
|
|
131
|
+
"roster_file": "/repo/roster.json",
|
|
132
|
+
"roster_entry": "reviewer"
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Each roster entry must contain `backend` and at least one of `agent` or `model`. Do not combine roster mode with direct `agent`, `model`, or `backend` overrides. Roster entries currently do not support `system` or `thinking`; `thinking` remains a run-level option and is validated against the effective backend. A resumed session must stay on its original backend. Use an absolute `roster_file` path when the Pi process and target project have different working directories.
|
|
137
|
+
|
|
123
138
|
### Pi-specific features
|
|
124
139
|
|
|
125
140
|
Beyond the tools, the extension integrates with Pi's TUI and event system:
|
|
126
141
|
|
|
127
142
|
- **Status widget** — persistent widget showing all active runs with status, phase, and permission state
|
|
128
|
-
- **Footer status** — active runs shown in the Pi footer bar
|
|
143
|
+
- **Footer status** — active runs and polling error counts shown in the Pi footer bar
|
|
144
|
+
- **Polling diagnostics** — bounded polling errors are emitted on `avenor:poll:error` for companion extensions
|
|
129
145
|
- **Live progress** — blocking `avenor_spawn` calls stream progress updates via `onUpdate`
|
|
130
146
|
- **Context enrichment** — active sub-agents are automatically surfaced in the system prompt via `before_agent_start`
|
|
131
|
-
- **Custom rendering** — tool calls and results
|
|
147
|
+
- **Custom rendering** — The Pi extension renders all Avenor tool calls and results as themed, bounded summaries. Results have collapsed and expanded views.
|
|
132
148
|
- **Commands** — interactive commands for run management:
|
|
133
149
|
- `/avenor-status` — show status of all runs
|
|
150
|
+
- `/avenor-errors` — show and clear recent polling errors
|
|
134
151
|
- `/avenor-watch <run_id>` — open a live event feed overlay
|
|
135
152
|
- `/avenor-cancel <run_id>` — cancel a running sub-agent
|
|
136
153
|
|
|
154
|
+
### Tool-result channels
|
|
155
|
+
|
|
156
|
+
Pi returns JSON model content in `content[0].text` and structured `details` for
|
|
157
|
+
all tools except `avenor_spawn`. The renderer creates themed, bounded summaries
|
|
158
|
+
for display. It does not modify the underlying model content or the `details`
|
|
159
|
+
object.
|
|
160
|
+
|
|
161
|
+
Pi's rendered summaries sanitize and bound the output, events, and snapshot rows
|
|
162
|
+
they display. Use `avenor_result`, `avenor_inspect`, or `avenor_events` for the
|
|
163
|
+
corresponding data.
|
|
164
|
+
|
|
165
|
+
MCP clients render their own results.
|
|
166
|
+
|
|
137
167
|
### Agent profiles
|
|
138
168
|
|
|
139
169
|
The `avenor_spawn` tool accepts an optional `agent` parameter that maps to a named profile in pi's `agents.json`:
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { InspectResult, StatusResult, Supervisor, answerPermissionTool, dial, eventsTool, followUpTool, inspectTool, observeRun, resultTool, shutdownTool, spawnTool, statusTool } from "@dougbots/avenor-core";
|
|
2
|
-
import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { EventBus, ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
5
|
interface RunStatusEntry {
|
|
6
6
|
runId: string;
|
|
7
|
+
/** Supervisor socket provided at spawn time for namespace scoping. */
|
|
8
|
+
supervisorId?: string;
|
|
9
|
+
/** Runtime ID scoped to the explicit or singleton supervisor. */
|
|
10
|
+
runtimeId?: string;
|
|
7
11
|
label: string;
|
|
8
12
|
status: string;
|
|
9
13
|
phase?: string;
|
|
@@ -19,6 +23,92 @@ interface RunStatusEntry {
|
|
|
19
23
|
nestedCount?: number;
|
|
20
24
|
}
|
|
21
25
|
//#endregion
|
|
26
|
+
//#region src/events.d.ts
|
|
27
|
+
/** Emitted when the official extension completes a polling cycle. */
|
|
28
|
+
declare const CHANNEL_POLL_COMPLETED: "avenor:poll:completed";
|
|
29
|
+
/** Emitted when the extension observes a terminal run result. */
|
|
30
|
+
declare const CHANNEL_RUN_TERMINAL: "avenor:run:terminal";
|
|
31
|
+
/** Emitted when a best-effort polling operation fails. */
|
|
32
|
+
declare const CHANNEL_POLL_ERROR: "avenor:poll:error";
|
|
33
|
+
type PollErrorSource = 'singleton-list' | 'run-status' | 'spawn-status';
|
|
34
|
+
interface PollErrorPayload {
|
|
35
|
+
/** Polling operation that failed. */
|
|
36
|
+
readonly source: PollErrorSource;
|
|
37
|
+
/** Run associated with the failure, when the operation was run-specific. */
|
|
38
|
+
readonly runId?: string;
|
|
39
|
+
/** Human-readable operation description. */
|
|
40
|
+
readonly message: string;
|
|
41
|
+
/** Bounded, sanitized error text suitable for debug consumers. */
|
|
42
|
+
readonly error: string;
|
|
43
|
+
/** Number of polling errors observed by this extension instance. */
|
|
44
|
+
readonly count: number;
|
|
45
|
+
/** Wall-clock timestamp in epoch milliseconds. */
|
|
46
|
+
readonly timestamp: number;
|
|
47
|
+
}
|
|
48
|
+
interface PollErrorPayloadInput {
|
|
49
|
+
readonly source: PollErrorSource;
|
|
50
|
+
readonly runId?: string;
|
|
51
|
+
readonly message: string;
|
|
52
|
+
readonly error: unknown;
|
|
53
|
+
readonly count: number;
|
|
54
|
+
readonly timestamp: number;
|
|
55
|
+
}
|
|
56
|
+
type AvenorRunStatus = Readonly<Omit<RunStatusEntry, 'supervisorId' | 'pid' | 'permissionDescription'> & {
|
|
57
|
+
supervisorKey: string;
|
|
58
|
+
}>;
|
|
59
|
+
interface PollCompletedPayload {
|
|
60
|
+
/** Status for each direct run tracked by the official extension. */
|
|
61
|
+
readonly entries: readonly AvenorRunStatus[];
|
|
62
|
+
/** Wall-clock timestamp in epoch milliseconds. */
|
|
63
|
+
readonly timestamp: number;
|
|
64
|
+
/** Monotonic counter for this official-extension instance. */
|
|
65
|
+
readonly generation: number;
|
|
66
|
+
}
|
|
67
|
+
interface RunTerminalPayload {
|
|
68
|
+
readonly runId: string;
|
|
69
|
+
/** Stable opaque scope for the explicit or singleton supervisor. */
|
|
70
|
+
readonly supervisorKey: string;
|
|
71
|
+
readonly runtimeId?: string;
|
|
72
|
+
readonly label: string;
|
|
73
|
+
readonly agent: string;
|
|
74
|
+
readonly status: string;
|
|
75
|
+
/** Number of active descendants when the run was removed, if available. */
|
|
76
|
+
readonly nestedCount?: number;
|
|
77
|
+
readonly backend?: string;
|
|
78
|
+
}
|
|
79
|
+
interface RunTerminalPayloadInput {
|
|
80
|
+
readonly runId: string;
|
|
81
|
+
/** Local supervisor socket, converted to an opaque supervisorKey. */
|
|
82
|
+
readonly supervisorId?: string;
|
|
83
|
+
readonly runtimeId?: string;
|
|
84
|
+
readonly label: string;
|
|
85
|
+
readonly agent: string;
|
|
86
|
+
readonly status: string;
|
|
87
|
+
readonly nestedCount?: number;
|
|
88
|
+
readonly backend?: string;
|
|
89
|
+
}
|
|
90
|
+
interface AvenorEventMap {
|
|
91
|
+
[CHANNEL_POLL_COMPLETED]: PollCompletedPayload;
|
|
92
|
+
[CHANNEL_RUN_TERMINAL]: RunTerminalPayload;
|
|
93
|
+
[CHANNEL_POLL_ERROR]: PollErrorPayload;
|
|
94
|
+
}
|
|
95
|
+
type AvenorEventChannel = keyof AvenorEventMap;
|
|
96
|
+
type AvenorEventBus = Pick<EventBus, 'emit' | 'on'>;
|
|
97
|
+
/** Emit an Avenor event with a type-checked payload. */
|
|
98
|
+
declare function emitAvenorEvent<K extends AvenorEventChannel>(bus: Pick<EventBus, 'emit'>, event: K, data: AvenorEventMap[K]): void;
|
|
99
|
+
/** Subscribe to an Avenor event and return Pi's unsubscribe function. */
|
|
100
|
+
declare function onAvenorEvent<K extends AvenorEventChannel>(bus: Pick<EventBus, 'on'>, event: K, handler: (data: AvenorEventMap[K]) => void): () => void;
|
|
101
|
+
/**
|
|
102
|
+
* Copy and freeze the selected fields exposed to companion consumers.
|
|
103
|
+
* Keep this allowlist explicit so future private RunStatusEntry fields are not
|
|
104
|
+
* included in the event accidentally.
|
|
105
|
+
*/
|
|
106
|
+
declare function createPollCompletedPayload(entries: readonly RunStatusEntry[], timestamp: number, generation: number): PollCompletedPayload;
|
|
107
|
+
/** Copy and freeze a terminal payload before publishing it. */
|
|
108
|
+
declare function createRunTerminalPayload(payload: RunTerminalPayloadInput): RunTerminalPayload;
|
|
109
|
+
/** Copy, bound, sanitize, and freeze a polling error before publishing it. */
|
|
110
|
+
declare function createPollErrorPayload(payload: PollErrorPayloadInput): PollErrorPayload;
|
|
111
|
+
//#endregion
|
|
22
112
|
//#region src/index.d.ts
|
|
23
113
|
interface ExtensionDeps {
|
|
24
114
|
spawnTool: typeof spawnTool;
|
|
@@ -34,6 +124,15 @@ interface ExtensionDeps {
|
|
|
34
124
|
Supervisor: typeof Supervisor;
|
|
35
125
|
}
|
|
36
126
|
declare function statusSupervisorId(requestedSupervisorId: string | undefined, spawnedSupervisorId: string): string | undefined;
|
|
127
|
+
type SpawnHostParams = {
|
|
128
|
+
agent?: string;
|
|
129
|
+
model?: string;
|
|
130
|
+
backend?: string;
|
|
131
|
+
roster_file?: string;
|
|
132
|
+
roster_entry?: string;
|
|
133
|
+
};
|
|
134
|
+
/** Project shared spawn identity into Pi tool metadata without resolving rosters here. */
|
|
135
|
+
declare function spawnIdentityMetadata(params: SpawnHostParams, status?: Pick<StatusResult, 'roster_file' | 'roster_entry' | 'agent' | 'model' | 'backend' | 'effective_agent' | 'effective_model' | 'effective_backend'>): Record<string, unknown>;
|
|
37
136
|
declare function buildCompletionText(run: {
|
|
38
137
|
runId: string;
|
|
39
138
|
label: string;
|
|
@@ -45,4 +144,4 @@ declare function buildInspectPayload(result: InspectResult): Record<string, unkn
|
|
|
45
144
|
declare function createExtension(deps?: ExtensionDeps): (pi: ExtensionAPI) => Promise<void>;
|
|
46
145
|
declare const _default: (pi: ExtensionAPI) => Promise<void>;
|
|
47
146
|
//#endregion
|
|
48
|
-
export { ExtensionDeps, buildCompletionText, buildInspectPayload, compactWhitespace, createExtension, _default as default, isTerminalStatus, renderStatusLines, statusSupervisorId };
|
|
147
|
+
export { type AvenorEventBus, type AvenorEventChannel, type AvenorEventMap, type AvenorRunStatus, CHANNEL_POLL_COMPLETED, CHANNEL_POLL_ERROR, CHANNEL_RUN_TERMINAL, ExtensionDeps, type PollCompletedPayload, type PollErrorPayload, type PollErrorPayloadInput, type PollErrorSource, type RunTerminalPayload, type RunTerminalPayloadInput, buildCompletionText, buildInspectPayload, compactWhitespace, createExtension, createPollCompletedPayload, createPollErrorPayload, createRunTerminalPayload, _default as default, emitAvenorEvent, isTerminalStatus, onAvenorEvent, renderStatusLines, spawnIdentityMetadata, statusSupervisorId };
|