pi-advisor-flow 0.11.0 → 0.11.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 CHANGED
@@ -4,6 +4,13 @@ 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
+ ## 0.11.1 - 2026-10-04
8
+
9
+ ### Changed
10
+
11
+ - Updated CI and local validation to Bun 1.4.2.
12
+ - Updated the Pi development toolchain to the 1.0.2 packages (`pi-ai`, `pi-coding-agent`, `pi-tui`); the supported peer range stays `^1.0.0`.
13
+
7
14
  ## 0.11.0 - 2026-10-03
8
15
 
9
16
  ### 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 collectTextStream = async (resolved, options, streamModel = stream) => {
1953
- let thinking = "";
1954
- let text = "";
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
- const eventStream = streamModel(resolved.model, { messages: options.messages, systemPrompt: options.systemPrompt }, streamOptions);
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-advisor-flow",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Advanced Executor/Advisor flow for Pi, fully configurable and extendable.",
5
5
  "keywords": [
6
6
  "advisor",
@@ -51,9 +51,9 @@
51
51
  "format:check": "oxfmt --check"
52
52
  },
53
53
  "devDependencies": {
54
- "@earendil-works/pi-ai": "1.0.0",
55
- "@earendil-works/pi-coding-agent": "1.0.0",
56
- "@earendil-works/pi-tui": "1.0.0",
54
+ "@earendil-works/pi-ai": "1.0.2",
55
+ "@earendil-works/pi-coding-agent": "1.0.2",
56
+ "@earendil-works/pi-tui": "1.0.2",
57
57
  "@oxlint/plugins": "1.86.0",
58
58
  "@types/node": "^26.6.4",
59
59
  "@typesafe-ai/sdk": "^0.6.0",
@@ -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: string;
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
- export const collectTextStream = async (
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: typeof stream = stream
186
- ): Promise<CollectedTextStream> => {
187
- let thinking = "";
188
- let text = "";
189
- const streamOptions: Parameters<typeof streamModel>[2] = {
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
- // SAFETY: stream() models the provider-facing reasoning field as never; options.reasoning is the Pi-facing effort string.
194
- reasoning: options.reasoning as never,
236
+ reasoning: options.reasoning,
195
237
  signal: options.signal,
196
238
  };
197
239
  if (options.reasoning !== undefined) {
198
- // SAFETY: reasoningEffort takes the same effort string; kept absent when reasoning is unset.
199
- streamOptions.reasoningEffort = options.reasoning as never;
240
+ streamOptions.reasoningEffort = options.reasoning;
200
241
  }
201
- const eventStream = streamModel(
202
- resolved.model,
203
- { messages: options.messages, systemPrompt: options.systemPrompt },
204
- streamOptions
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") {