pi-agent-flow 1.1.0 → 1.2.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.
@@ -10,8 +10,8 @@ import * as fs from "node:fs";
10
10
  import * as os from "node:os";
11
11
  import * as path from "node:path";
12
12
  import type { AgentToolResult } from "@mariozechner/pi-agent-core";
13
- import { type FlowConfig, getFlowTier } from "./agents.js";
14
- import { parseFlowCliArgs } from "./runner-cli.js";
13
+ import { type FlowConfig } from "./agents.js";
14
+ import { parseFlowCliArgs } from "./cli-args.js";
15
15
  import { processFlowJsonLine, drainStreamingText, drainStreamingEstimate, drainCtxEstimate, updateSmoothedTps, drainSmoothedTps } from "./runner-events.js";
16
16
  import {
17
17
  type SingleResult,
@@ -52,8 +52,8 @@ function mergeStreamingUsage(
52
52
  ...actual,
53
53
  ...(estimatedOutputTokens > 0 ? { output: Math.max(actual.output, estimatedOutputTokens) } : {}),
54
54
  ...(ctxEstimate > 0 ? { contextTokens: Math.max(actual.contextTokens, ctxEstimate) } : {}),
55
- // Preserve the peak smoothedTPS seen during the stream rather than the live EMA value.
56
- ...(smoothedTps > 0 ? { smoothedTps: Math.max(actual.smoothedTps || 0, smoothedTps) } : {}),
55
+ // Show the live EMA value so the dashboard can rise and fall smoothly.
56
+ ...(smoothedTps > 0 ? { smoothedTps } : {}),
57
57
  };
58
58
  }
59
59
 
@@ -117,7 +117,7 @@ export function getOptimizedTools(
117
117
  );
118
118
  if (!hasLegacyTools) return flowTools;
119
119
  const filtered = flowTools.filter(
120
- (t) => t !== "read" && t !== "write" && t !== "edit" && t !== "batch",
120
+ (t) => t !== "read" && t !== "write" && t !== "edit" && t !== "batch" && t !== "batch_read",
121
121
  );
122
122
  return filtered.includes("batch")
123
123
  ? filtered
@@ -128,7 +128,7 @@ function buildFlowArgs(
128
128
  flow: FlowConfig,
129
129
  intent: string,
130
130
  forkSessionPath: string | null,
131
- tieredModels?: { lite?: string; flash?: string; full?: string },
131
+ model?: string,
132
132
  parentDepth: number = 0,
133
133
  maxDepth: number = 0,
134
134
  toolOptimize: boolean = false,
@@ -145,10 +145,21 @@ function buildFlowArgs(
145
145
  args.push("--session", forkSessionPath);
146
146
  }
147
147
 
148
- const tier = getFlowTier(flow.name);
149
- const tierModel = tieredModels?.[tier] ?? inheritedCliArgs.tieredModels?.[tier];
150
- const model = flow.model ?? tierModel ?? inheritedCliArgs.fallbackModel;
151
- if (model) args.push("--model", model);
148
+ if (inheritedCliArgs.flowModelConfig) {
149
+ args.push("--flow-model-config", inheritedCliArgs.flowModelConfig);
150
+ }
151
+ if (inheritedCliArgs.tieredModels?.lite) {
152
+ args.push("--flow-lite-model", inheritedCliArgs.tieredModels.lite);
153
+ }
154
+ if (inheritedCliArgs.tieredModels?.flash) {
155
+ args.push("--flow-flash-model", inheritedCliArgs.tieredModels.flash);
156
+ }
157
+ if (inheritedCliArgs.tieredModels?.full) {
158
+ args.push("--flow-full-model", inheritedCliArgs.tieredModels.full);
159
+ }
160
+
161
+ const resolvedModel = model ?? flow.model ?? inheritedCliArgs.fallbackModel;
162
+ if (resolvedModel) args.push("--model", resolvedModel);
152
163
 
153
164
  const thinking = flow.thinking ?? inheritedCliArgs.fallbackThinking;
154
165
  if (thinking) args.push("--thinking", thinking);
@@ -245,8 +256,8 @@ export interface RunFlowOptions {
245
256
  preventCycles: boolean;
246
257
  /** Whether to transform tool lists to use batch. */
247
258
  toolOptimize?: boolean;
248
- /** Tiered model overrides (lite/flash/full). */
249
- tieredModels?: { lite?: string; flash?: string; full?: string };
259
+ /** Explicit model to use for this flow execution. */
260
+ model?: string;
250
261
  /** Abort signal for cancellation. */
251
262
  signal?: AbortSignal;
252
263
  /** Streaming update callback. */
@@ -276,6 +287,7 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
276
287
  maxDepth,
277
288
  preventCycles,
278
289
  toolOptimize = false,
290
+ model,
279
291
  signal,
280
292
  onUpdate,
281
293
  makeDetails,
@@ -297,7 +309,7 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
297
309
  };
298
310
  }
299
311
 
300
- const resolvedModel = flow.model ?? inheritedCliArgs.fallbackModel;
312
+ const resolvedModel = model ?? flow.model ?? inheritedCliArgs.fallbackModel;
301
313
  const result: SingleResult = {
302
314
  type: normalizedFlowName,
303
315
  agentSource: flow.source,
@@ -310,21 +322,30 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
310
322
  model: resolvedModel,
311
323
  };
312
324
 
325
+ let liveStreamingText = "";
326
+ let liveEstimatedOutputTokens = 0;
327
+ let lastActualOutputTokens = result.usage.output;
313
328
  const emitUpdate = () => {
314
- const streaming = drainStreamingText(result);
329
+ const streamingDelta = drainStreamingText(result);
330
+ if (streamingDelta) liveStreamingText += streamingDelta;
315
331
  const estimatedTokens = drainStreamingEstimate(result);
332
+ if (result.usage.output !== lastActualOutputTokens) {
333
+ lastActualOutputTokens = result.usage.output;
334
+ liveEstimatedOutputTokens = result.usage.output;
335
+ }
336
+ liveEstimatedOutputTokens += estimatedTokens;
316
337
  const ctxEst = drainCtxEstimate(result);
317
338
  updateSmoothedTps(result, estimatedTokens);
318
339
  const smoothedTps = drainSmoothedTps(result);
319
- const mergedUsage = mergeStreamingUsage(result.usage, estimatedTokens, ctxEst, smoothedTps);
340
+ const mergedUsage = mergeStreamingUsage(result.usage, liveEstimatedOutputTokens, ctxEst, smoothedTps);
320
341
  onUpdate?.({
321
342
  content: [
322
343
  {
323
344
  type: "text",
324
- text: streaming || getFlowOutput(result.messages) || "(running...)",
345
+ text: liveStreamingText || getFlowOutput(result.messages) || "(running...)",
325
346
  },
326
347
  ],
327
- details: makeDetails([{ ...result, usage: mergedUsage }]),
348
+ details: makeDetails([{ ...result, usage: mergedUsage, streamingText: liveStreamingText || undefined }]),
328
349
  });
329
350
  };
330
351
 
@@ -342,7 +363,7 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
342
363
  flow,
343
364
  intent,
344
365
  forkSessionTmpPath,
345
- opts.tieredModels,
366
+ model,
346
367
  parentDepth,
347
368
  maxDepth,
348
369
  toolOptimize,
@@ -104,19 +104,19 @@ registerHook({
104
104
  },
105
105
  });
106
106
 
107
- /** Suggest explore flow after a successful audit flow. */
107
+ /** Suggest scout flow after a successful audit flow. */
108
108
  registerHook({
109
- name: "pi-agent-flow/audit-to-explore",
109
+ name: "pi-agent-flow/audit-to-scout",
110
110
  trigger: { flowTypes: ["audit"], onlyOnSuccess: true },
111
111
  action: (ctx) => {
112
- const exploreWasRequested = ctx.params.some(
113
- (p) => p.type.toLowerCase() === "explore",
112
+ const scoutWasRequested = ctx.params.some(
113
+ (p) => p.type.toLowerCase() === "scout",
114
114
  );
115
- if (exploreWasRequested) return null;
115
+ if (scoutWasRequested) return null;
116
116
 
117
117
  return {
118
118
  content:
119
- "Audit complete. Consider running an [explore] flow to review the audit findings.",
119
+ "Audit complete. Consider running a [scout] flow to trace the audit findings across the codebase.",
120
120
  priority: 15,
121
121
  };
122
122
  },