pi-advisor-flow 0.10.1-dev.1 → 0.11.1-dev.1
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 +6 -1
- package/dist/index.js +43 -11
- package/package.json +2 -1
- package/src/model-stream.ts +63 -16
- package/src/tools/register-lifecycle.ts +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,12 +4,17 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0/).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## 0.11.0 - 2026-10-03
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
11
|
- Native Pi Codemode composition for `ask_advisor`: scripts receive structured advice, IDs, normalized usage, and existing skip metadata, while interactive responses remain unchanged. Documented deterministic-check composition and explicit draft disclosure limits.
|
|
12
12
|
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Advisor invocation guidelines no longer replace the whole system prompt, so prompt sections from other extensions, such as the list of MCP servers, still reach the model.
|
|
16
|
+
- Braces Vulnerability patched (CVE-2026-93687)
|
|
17
|
+
|
|
13
18
|
## 0.10.0 - 2026-10-02
|
|
14
19
|
|
|
15
20
|
### Added
|
package/dist/index.js
CHANGED
|
@@ -1854,6 +1854,14 @@ var resolveConfiguredModel = async (ctx, ref, label) => {
|
|
|
1854
1854
|
if (!model) {
|
|
1855
1855
|
throw new Error(`${label} model not found: ${ref}`);
|
|
1856
1856
|
}
|
|
1857
|
+
const { streamSimple } = ctx.modelRegistry;
|
|
1858
|
+
if (streamSimple) {
|
|
1859
|
+
return {
|
|
1860
|
+
model,
|
|
1861
|
+
ref,
|
|
1862
|
+
streamSimple: streamSimple.bind(ctx.modelRegistry)
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1857
1865
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
1858
1866
|
if (!auth.ok) {
|
|
1859
1867
|
throw new Error(auth.error);
|
|
@@ -1949,9 +1957,28 @@ var createCoalescedUpdate = (publish, intervalMs = ADVISOR_STREAM_UPDATE_INTERVA
|
|
|
1949
1957
|
}
|
|
1950
1958
|
};
|
|
1951
1959
|
};
|
|
1952
|
-
var
|
|
1953
|
-
|
|
1954
|
-
|
|
1960
|
+
var SIMPLE_REASONING_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
1961
|
+
var toSimpleReasoning = (effort) => {
|
|
1962
|
+
if (effort === undefined || effort === "off") {
|
|
1963
|
+
return;
|
|
1964
|
+
}
|
|
1965
|
+
const level = SIMPLE_REASONING_LEVELS.find((candidate) => candidate === effort);
|
|
1966
|
+
if (!level) {
|
|
1967
|
+
throw new Error(`Unsupported Advisor reasoning level: ${effort}`);
|
|
1968
|
+
}
|
|
1969
|
+
return level;
|
|
1970
|
+
};
|
|
1971
|
+
var createTextEventStream = (resolved, options, streamModel) => {
|
|
1972
|
+
const context = {
|
|
1973
|
+
messages: options.messages,
|
|
1974
|
+
systemPrompt: options.systemPrompt
|
|
1975
|
+
};
|
|
1976
|
+
if (!streamModel && resolved.streamSimple) {
|
|
1977
|
+
return resolved.streamSimple(resolved.model, context, {
|
|
1978
|
+
reasoning: toSimpleReasoning(options.reasoning),
|
|
1979
|
+
signal: options.signal
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1955
1982
|
const streamOptions = {
|
|
1956
1983
|
apiKey: resolved.apiKey,
|
|
1957
1984
|
env: resolved.env,
|
|
@@ -1962,7 +1989,12 @@ var collectTextStream = async (resolved, options, streamModel = stream) => {
|
|
|
1962
1989
|
if (options.reasoning !== undefined) {
|
|
1963
1990
|
streamOptions.reasoningEffort = options.reasoning;
|
|
1964
1991
|
}
|
|
1965
|
-
|
|
1992
|
+
return (streamModel ?? stream)(resolved.model, context, streamOptions);
|
|
1993
|
+
};
|
|
1994
|
+
var collectTextStream = async (resolved, options, streamModel) => {
|
|
1995
|
+
let thinking = "";
|
|
1996
|
+
let text = "";
|
|
1997
|
+
const eventStream = createTextEventStream(resolved, options, streamModel);
|
|
1966
1998
|
for await (const event of eventStream) {
|
|
1967
1999
|
if (event.type === "thinking_delta") {
|
|
1968
2000
|
thinking += event.delta;
|
|
@@ -9025,7 +9057,9 @@ var registerToolLifecycle = ({
|
|
|
9025
9057
|
ctx.ui.setStatus("advisor-usage", undefined);
|
|
9026
9058
|
}
|
|
9027
9059
|
});
|
|
9028
|
-
pi.on("before_agent_start", (
|
|
9060
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
9061
|
+
const { sections } = event.systemPromptOptions;
|
|
9062
|
+
delete sections.advisor_invocation_settings;
|
|
9029
9063
|
if (!pi.getActiveTools().includes("ask_advisor")) {
|
|
9030
9064
|
return;
|
|
9031
9065
|
}
|
|
@@ -9039,13 +9073,11 @@ var registerToolLifecycle = ({
|
|
|
9039
9073
|
guidelines.push(`Advisor calls remaining this session: ${budget}.
|
|
9040
9074
|
Reserve calls for material decisions, repeated failures, or final review.`);
|
|
9041
9075
|
}
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
Advisor invocation settings:
|
|
9076
|
+
if (guidelines.length > 0) {
|
|
9077
|
+
sections.advisor_invocation_settings = `Advisor invocation settings:
|
|
9046
9078
|
${guidelines.map((rule) => `- ${rule}`).join(`
|
|
9047
|
-
`)}
|
|
9048
|
-
}
|
|
9079
|
+
`)}`;
|
|
9080
|
+
}
|
|
9049
9081
|
});
|
|
9050
9082
|
pi.on("input", () => {
|
|
9051
9083
|
session.clearFollowUps();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-advisor-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1-dev.1",
|
|
4
4
|
"description": "Advanced Executor/Advisor flow for Pi, fully configurable and extendable.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"advisor",
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
},
|
|
94
94
|
"overrides": {
|
|
95
95
|
"brace-expansion": "5.0.12",
|
|
96
|
+
"braces": "github:micromatch/braces#d0d575e55e74a4e0218e5248fafb79efc3e54ebb",
|
|
96
97
|
"is-unicode-supported": "npm:@socketregistry/is-unicode-supported@1.0.5",
|
|
97
98
|
"safe-buffer": "npm:@socketregistry/safe-buffer@1.0.9",
|
|
98
99
|
"undici": "8.11.2"
|
package/src/model-stream.ts
CHANGED
|
@@ -2,19 +2,27 @@ import { stream } from "@earendil-works/pi-ai/compat";
|
|
|
2
2
|
import type {
|
|
3
3
|
Api,
|
|
4
4
|
AssistantMessage,
|
|
5
|
+
AssistantMessageEventStream,
|
|
6
|
+
Context,
|
|
5
7
|
Message,
|
|
6
8
|
Model,
|
|
9
|
+
SimpleStreamOptions,
|
|
7
10
|
} from "@earendil-works/pi-ai/compat";
|
|
8
11
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
9
12
|
|
|
10
13
|
import { splitRef } from "./config/state.ts";
|
|
11
14
|
|
|
12
15
|
export interface ResolvedConfiguredModel {
|
|
13
|
-
apiKey
|
|
16
|
+
apiKey?: string;
|
|
14
17
|
env?: Record<string, string>;
|
|
15
18
|
headers?: Record<string, string | null>;
|
|
16
19
|
model: Model<Api>;
|
|
17
20
|
ref: string;
|
|
21
|
+
streamSimple?: (
|
|
22
|
+
model: Model<Api>,
|
|
23
|
+
context: Context,
|
|
24
|
+
options?: SimpleStreamOptions
|
|
25
|
+
) => AssistantMessageEventStream;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
export const resolveConfiguredModel = async (
|
|
@@ -31,6 +39,14 @@ export const resolveConfiguredModel = async (
|
|
|
31
39
|
if (!model) {
|
|
32
40
|
throw new Error(`${label} model not found: ${ref}`);
|
|
33
41
|
}
|
|
42
|
+
const { streamSimple } = ctx.modelRegistry;
|
|
43
|
+
if (streamSimple) {
|
|
44
|
+
return {
|
|
45
|
+
model,
|
|
46
|
+
ref,
|
|
47
|
+
streamSimple: streamSimple.bind(ctx.modelRegistry),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
34
50
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
35
51
|
if (!auth.ok) {
|
|
36
52
|
throw new Error(auth.error);
|
|
@@ -179,30 +195,61 @@ export const createCoalescedUpdate = <T>(
|
|
|
179
195
|
};
|
|
180
196
|
};
|
|
181
197
|
|
|
182
|
-
|
|
198
|
+
const SIMPLE_REASONING_LEVELS: readonly NonNullable<
|
|
199
|
+
SimpleStreamOptions["reasoning"]
|
|
200
|
+
>[] = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
201
|
+
|
|
202
|
+
const toSimpleReasoning = (
|
|
203
|
+
effort: string | undefined
|
|
204
|
+
): SimpleStreamOptions["reasoning"] => {
|
|
205
|
+
if (effort === undefined || effort === "off") {
|
|
206
|
+
return undefined;
|
|
207
|
+
}
|
|
208
|
+
const level = SIMPLE_REASONING_LEVELS.find(
|
|
209
|
+
(candidate) => candidate === effort
|
|
210
|
+
);
|
|
211
|
+
if (!level) {
|
|
212
|
+
throw new Error(`Unsupported Advisor reasoning level: ${effort}`);
|
|
213
|
+
}
|
|
214
|
+
return level;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const createTextEventStream = (
|
|
183
218
|
resolved: ResolvedConfiguredModel,
|
|
184
219
|
options: CollectTextStreamOptions,
|
|
185
|
-
streamModel
|
|
186
|
-
):
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
220
|
+
streamModel?: typeof stream
|
|
221
|
+
): AssistantMessageEventStream => {
|
|
222
|
+
const context: Context = {
|
|
223
|
+
messages: options.messages,
|
|
224
|
+
systemPrompt: options.systemPrompt,
|
|
225
|
+
};
|
|
226
|
+
if (!streamModel && resolved.streamSimple) {
|
|
227
|
+
return resolved.streamSimple(resolved.model, context, {
|
|
228
|
+
reasoning: toSimpleReasoning(options.reasoning),
|
|
229
|
+
signal: options.signal,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const streamOptions: NonNullable<Parameters<typeof stream>[2]> = {
|
|
190
233
|
apiKey: resolved.apiKey,
|
|
191
234
|
env: resolved.env,
|
|
192
235
|
headers: resolved.headers,
|
|
193
|
-
|
|
194
|
-
reasoning: options.reasoning as never,
|
|
236
|
+
reasoning: options.reasoning,
|
|
195
237
|
signal: options.signal,
|
|
196
238
|
};
|
|
197
239
|
if (options.reasoning !== undefined) {
|
|
198
|
-
|
|
199
|
-
streamOptions.reasoningEffort = options.reasoning as never;
|
|
240
|
+
streamOptions.reasoningEffort = options.reasoning;
|
|
200
241
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
242
|
+
return (streamModel ?? stream)(resolved.model, context, streamOptions);
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export const collectTextStream = async (
|
|
246
|
+
resolved: ResolvedConfiguredModel,
|
|
247
|
+
options: CollectTextStreamOptions,
|
|
248
|
+
streamModel?: typeof stream
|
|
249
|
+
): Promise<CollectedTextStream> => {
|
|
250
|
+
let thinking = "";
|
|
251
|
+
let text = "";
|
|
252
|
+
const eventStream = createTextEventStream(resolved, options, streamModel);
|
|
206
253
|
|
|
207
254
|
for await (const event of eventStream) {
|
|
208
255
|
if (event.type === "thinking_delta") {
|
|
@@ -71,7 +71,9 @@ export const registerToolLifecycle = ({
|
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
pi.on("before_agent_start", (
|
|
74
|
+
pi.on("before_agent_start", (event, ctx) => {
|
|
75
|
+
const { sections } = event.systemPromptOptions;
|
|
76
|
+
delete sections.advisor_invocation_settings;
|
|
75
77
|
if (!pi.getActiveTools().includes("ask_advisor")) {
|
|
76
78
|
return;
|
|
77
79
|
}
|
|
@@ -88,11 +90,9 @@ export const registerToolLifecycle = ({
|
|
|
88
90
|
`Advisor calls remaining this session: ${budget}.\nReserve calls for material decisions, repeated failures, or final review.`
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
: undefined;
|
|
93
|
+
if (guidelines.length > 0) {
|
|
94
|
+
sections.advisor_invocation_settings = `Advisor invocation settings:\n${guidelines.map((rule) => `- ${rule}`).join("\n")}`;
|
|
95
|
+
}
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
pi.on("input", () => {
|