@dougbots/pi-agents 0.2.0 → 0.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 +9 -3
- package/extensions/agents/index.ts +23 -5
- package/extensions/agents/model-selection.ts +17 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,8 +76,14 @@ session and restored by `/resume`.
|
|
|
76
76
|
|
|
77
77
|
`PI_AGENT_PROFILE=<name>` is an explicit launch-time override; `PROFILE=<name>`
|
|
78
78
|
is accepted as a convenience alias. Both take precedence over a saved session
|
|
79
|
-
selection. Explicit `--model` still
|
|
80
|
-
model.
|
|
79
|
+
selection. Explicit `--model` and `--thinking` still take precedence over an
|
|
80
|
+
agent-profile's model and thinking level.
|
|
81
|
+
|
|
82
|
+
While a session has a profile active, the extension reflects it into
|
|
83
|
+
`process.env.PI_AGENT_PROFILE` (cleared on `/agent-profile none`). Child
|
|
84
|
+
processes inherit it, so tooling like `agent-model.sh <role> pi` resolves the
|
|
85
|
+
same model the session runs, and fresh dispatches from the session stay on the
|
|
86
|
+
active profile.
|
|
81
87
|
|
|
82
88
|
## Commands
|
|
83
89
|
|
|
@@ -114,7 +120,7 @@ avenor_spawn(
|
|
|
114
120
|
)
|
|
115
121
|
```
|
|
116
122
|
|
|
117
|
-
Explicit `--model`
|
|
123
|
+
Explicit `--model` and `--thinking` selections take precedence over the profile defaults. Avenor forwards a roster entry's `model` and `thinking` to the pi subprocess as `--model` and `--thinking`, so no agent config changes are needed for a one-off override, and a roster entry that names an agent keeps its own thinking level.
|
|
118
124
|
|
|
119
125
|
Requires [avenor](https://github.com/sdougbrown/avenor) with the pi backend (v0.3.3+). Model resolution falls back to `~/.pi/agent/agents.json` when the agent is not found in opencode config.
|
|
120
126
|
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type AgentProfilesConfig,
|
|
10
10
|
type ThinkingLevel,
|
|
11
11
|
} from "./agent-profile.ts";
|
|
12
|
-
import { findCliModelOverride, parseModelSpecifier } from "./model-selection.ts";
|
|
12
|
+
import { findCliModelOverride, findCliThinkingOverride, parseModelSpecifier } from "./model-selection.ts";
|
|
13
13
|
|
|
14
14
|
/* ------------------------------------------------------------------ */
|
|
15
15
|
/* Types */
|
|
@@ -137,10 +137,12 @@ function checkBashPermission(
|
|
|
137
137
|
export default async function (pi: ExtensionAPI) {
|
|
138
138
|
const agents = loadAgentsConfig();
|
|
139
139
|
const { profiles: agentProfiles, errors: agentProfileConfigErrors } = loadAgentProfilesConfig();
|
|
140
|
-
// Built-in flags are not exposed through pi.getFlag(). Avenor forwards
|
|
141
|
-
// model
|
|
142
|
-
// the caller's
|
|
140
|
+
// Built-in flags are not exposed through pi.getFlag(). Avenor forwards a
|
|
141
|
+
// roster entry's model and thinking level to pi as --model and --thinking,
|
|
142
|
+
// so argv is the extension-level signal that the caller's choice should take
|
|
143
|
+
// precedence over the profile default.
|
|
143
144
|
const cliModelOverride = findCliModelOverride(process.argv.slice(2));
|
|
145
|
+
const cliThinkingOverride = findCliThinkingOverride(process.argv.slice(2));
|
|
144
146
|
let activeAgent: { name: string; profile: AgentProfile } | null = null;
|
|
145
147
|
let activeAgentProfileName: string | undefined;
|
|
146
148
|
|
|
@@ -161,6 +163,20 @@ export default async function (pi: ExtensionAPI) {
|
|
|
161
163
|
);
|
|
162
164
|
}
|
|
163
165
|
|
|
166
|
+
/**
|
|
167
|
+
* Surface the session's active agent-profile to child processes.
|
|
168
|
+
*
|
|
169
|
+
* agent-model.sh resolves a role's effective model by reading
|
|
170
|
+
* $PI_AGENT_PROFILE; absent a launch-time override, the interactive
|
|
171
|
+
* /agent-profile selection is otherwise invisible to anything pi spawns.
|
|
172
|
+
* Mirroring it into the env lets the resolver agree with the session and,
|
|
173
|
+
* since children inherit it, keeps fresh dispatches on the same profile.
|
|
174
|
+
*/
|
|
175
|
+
function syncProfileEnv(name: string | undefined) {
|
|
176
|
+
if (name) process.env.PI_AGENT_PROFILE = name;
|
|
177
|
+
else delete process.env.PI_AGENT_PROFILE;
|
|
178
|
+
}
|
|
179
|
+
|
|
164
180
|
/** Apply a named agent-profile, optionally saving the choice in this session. */
|
|
165
181
|
async function selectAgentProfile(
|
|
166
182
|
name: string | undefined,
|
|
@@ -175,6 +191,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
175
191
|
const previousName = activeAgentProfileName;
|
|
176
192
|
activeAgentProfileName = name;
|
|
177
193
|
setAgentProfileStatus(ctx);
|
|
194
|
+
syncProfileEnv(name);
|
|
178
195
|
|
|
179
196
|
// The active role must receive a new effective model/thinking level now;
|
|
180
197
|
// future roles resolve the overlay when /agent is invoked. Do not persist
|
|
@@ -182,6 +199,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
182
199
|
if (activeAgent && !(await applyAgent(activeAgent.name, ctx))) {
|
|
183
200
|
activeAgentProfileName = previousName;
|
|
184
201
|
setAgentProfileStatus(ctx);
|
|
202
|
+
syncProfileEnv(previousName);
|
|
185
203
|
return false;
|
|
186
204
|
}
|
|
187
205
|
|
|
@@ -215,7 +233,7 @@ export default async function (pi: ExtensionAPI) {
|
|
|
215
233
|
await pi.setModel(model);
|
|
216
234
|
}
|
|
217
235
|
|
|
218
|
-
if (profile.thinkingLevel) pi.setThinkingLevel(profile.thinkingLevel);
|
|
236
|
+
if (profile.thinkingLevel && !cliThinkingOverride) pi.setThinkingLevel(profile.thinkingLevel);
|
|
219
237
|
|
|
220
238
|
// Tool restrictions — best-effort against currently registered tools.
|
|
221
239
|
// tool_call handler enforces restrictions regardless of registration timing.
|
|
@@ -4,19 +4,30 @@ export interface ModelSpecifier {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Return the
|
|
7
|
+
* Return the value pi received for a built-in flag, if any.
|
|
8
8
|
*
|
|
9
|
-
* Pi consumes
|
|
10
|
-
* pi.getFlag(). Inspecting argv lets agent profiles respect
|
|
11
|
-
* precedence, including
|
|
9
|
+
* Pi consumes its built-in flags itself, so extension flags cannot expose
|
|
10
|
+
* these values via pi.getFlag(). Inspecting argv lets agent profiles respect
|
|
11
|
+
* normal CLI precedence, including the model and thinking level Avenor
|
|
12
|
+
* forwards from a roster entry.
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
function findCliFlagValue(argv: readonly string[], flag: string): string | undefined {
|
|
14
15
|
for (let index = 0; index < argv.length - 1; index += 1) {
|
|
15
|
-
if (argv[index] ===
|
|
16
|
+
if (argv[index] === flag) return argv[index + 1];
|
|
16
17
|
}
|
|
17
18
|
return undefined;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
/** Return the model explicitly supplied to pi, if any. */
|
|
22
|
+
export function findCliModelOverride(argv: readonly string[]): string | undefined {
|
|
23
|
+
return findCliFlagValue(argv, "--model");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Return the thinking level explicitly supplied to pi, if any. */
|
|
27
|
+
export function findCliThinkingOverride(argv: readonly string[]): string | undefined {
|
|
28
|
+
return findCliFlagValue(argv, "--thinking");
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
/** Split provider/model-id at the first slash so model IDs may contain slashes. */
|
|
21
32
|
export function parseModelSpecifier(specifier: string): ModelSpecifier | undefined {
|
|
22
33
|
const separator = specifier.indexOf("/");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dougbots/pi-agents",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Agent profiles for pi — preconfigured model, system prompt, tool restrictions, and permission gates",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --experimental-strip-types --test tests/*.test.mts"
|