pi-agent-flow 1.0.4 → 1.0.6

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.
@@ -2,7 +2,7 @@
2
2
  name: architect
3
3
  description: Plan structure, break down requirements, design solutions
4
4
  tools: read, bash, find, grep, ls
5
- maxDepth: 2
5
+ maxDepth: 0
6
6
  ---
7
7
 
8
8
  During this architect flow — your mission is to design. Be conservative: prefer existing patterns and proven conventions over novelty. The conversation history above provides background context; treat it as reference only and do not let it distract from your objective.
package/agents/code.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: code
3
3
  description: Implement features, fix bugs, write tests, deploy, and ship
4
4
  tools: read, write, edit, bash, find, grep, ls
5
- maxDepth: 2
5
+ maxDepth: 0
6
6
  ---
7
7
 
8
8
  During this code flow — your mission is to build and ship. Be a craftsman: verify first, then ship. The conversation history above provides background context; treat it as reference only and do not let it distract from your objective.
package/agents/review.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: review
3
3
  description: Audit security, quality, correctness
4
4
  tools: read, bash, find, grep, ls
5
- maxDepth: 2
5
+ maxDepth: 0
6
6
  ---
7
7
 
8
8
  During this review flow — your mission is to audit. Be adversarial: look for what others miss, but stay honest. The conversation history above provides background context; treat it as reference only and do not let it distract from your objective.
package/flow.ts CHANGED
@@ -49,7 +49,7 @@ function mergeStreamingUsage(
49
49
  ...actual,
50
50
  ...(estimatedOutputTokens > 0 ? { output: Math.max(actual.output, estimatedOutputTokens) } : {}),
51
51
  ...(ctxEstimate > 0 ? { contextTokens: Math.max(actual.contextTokens, ctxEstimate) } : {}),
52
- ...(smoothedTps > 0 ? { smoothedTps } : {}),
52
+ ...(smoothedTps > 0 ? { smoothedTps: Math.max(actual.smoothedTps ?? 0, smoothedTps) } : {}),
53
53
  };
54
54
  }
55
55
 
@@ -104,6 +104,8 @@ function buildFlowArgs(
104
104
  intent: string,
105
105
  forkSessionPath: string | null,
106
106
  tieredModels?: { lite?: string; flash?: string; full?: string },
107
+ parentDepth: number = 0,
108
+ maxDepth: number = 0,
107
109
  ): string[] {
108
110
  const args: string[] = [
109
111
  "--mode",
@@ -138,17 +140,46 @@ function buildFlowArgs(
138
140
  // No --append-system-prompt: child inherits parent's system prompt for cache hits.
139
141
  // Flow instructions go in the intent message instead.
140
142
 
141
- const flowDirectives =
142
- `<flow-directive>\n` +
143
- `The conversation history above is background context — use it for reference, but your sole focus is the intent below, and try to execute EXACTLY as requested in the intent.\n` +
144
- `</flow-directive>`;
145
-
146
- const flowInstructions = flow.systemPrompt.trim()
147
- ? `\n\n<system-directive>\n${flow.systemPrompt.trim()}\n</system-directive>`
143
+ const currentDepth = Math.max(0, Math.floor(parentDepth)) + 1;
144
+ const effectiveMaxDepth = Math.max(0, Math.floor(maxDepth));
145
+ const canDelegate = currentDepth < effectiveMaxDepth;
146
+ const availableTools = flow.tools?.join(", ") ?? "all";
147
+
148
+ // Phase 1: Context seal — sharp boundary declaring history sealed
149
+ const contextSeal =
150
+ `<context-seal>\n` +
151
+ `The conversation above is sealed — it is your session history for situational awareness only.\n` +
152
+ `Your task begins NOW. Do not respond to or continue anything from the history.\n` +
153
+ `</context-seal>`;
154
+
155
+ // Phase 2: Activation — role, tools, depth, delegation rules (dynamically generated)
156
+ const delegationRule = canDelegate
157
+ ? `You may delegate to sub-flows (depth ${currentDepth}/${effectiveMaxDepth}).`
158
+ : `You may NOT delegate to sub-flows (depth limit reached).`;
159
+
160
+ const activation =
161
+ `\n\n<activation flow="${flow.name}" depth="${currentDepth}" tools="${availableTools}">\n` +
162
+ `You are a [${flow.name}] agent operating at depth ${currentDepth}.\n` +
163
+ `Available tools: ${availableTools}.\n` +
164
+ `${delegationRule}\n` +
165
+ `Do not attempt to use any tool outside the available set — it will fail.\n` +
166
+ `</activation>`;
167
+
168
+ // Phase 3: Directive — the flow's system prompt (renamed from <system-directive>)
169
+ const directive = flow.systemPrompt.trim()
170
+ ? `\n\n<directive>\n${flow.systemPrompt.trim()}\n</directive>`
148
171
  : "";
149
172
 
173
+ // Phase 4: Mission — the intent wrapped with execution contract
174
+ const mission =
175
+ `\n\n<mission>\n` +
176
+ `${intent}\n` +
177
+ `\nExecute this mission. Use only your available tools. If blocked, report why — do not guess.\n` +
178
+ `Follow the output format specified in your directive.\n` +
179
+ `</mission>`;
180
+
150
181
  // -p must immediately precede the prompt so the CLI parser binds it correctly
151
- args.push("-p", `${flowDirectives}${flowInstructions}\n\nIntent: ${intent}`);
182
+ args.push("-p", `${contextSeal}${activation}${directive}${mission}`);
152
183
  return args;
153
184
  }
154
185
 
@@ -269,6 +300,8 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
269
300
  intent,
270
301
  forkSessionTmpPath,
271
302
  opts.tieredModels,
303
+ parentDepth,
304
+ maxDepth,
272
305
  );
273
306
  let wasAborted = false;
274
307
 
@@ -403,6 +436,15 @@ export async function runFlow(opts: RunFlowOptions): Promise<SingleResult> {
403
436
  });
404
437
 
405
438
  result.exitCode = exitCode;
439
+
440
+ // Persist final smoothed TPS into the result's usage so it survives after streaming ends.
441
+ // During streaming, emitUpdate() only merges smoothedTps into a temporary display object;
442
+ // without this, result.usage.smoothedTps stays at 0 and the UI shows a dash.
443
+ const finalSmoothedTps = drainSmoothedTps(result);
444
+ if (finalSmoothedTps > 0) {
445
+ result.usage.smoothedTps = finalSmoothedTps;
446
+ }
447
+
406
448
  return normalizeFlowResult(result, wasAborted);
407
449
  } finally {
408
450
  cleanupFlowTempDir(forkSessionTmpDir);
package/index.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  // Limits
26
26
  // ---------------------------------------------------------------------------
27
27
 
28
- const DEFAULT_MAX_DELEGATION_DEPTH = 3;
28
+ const DEFAULT_MAX_DELEGATION_DEPTH = 0;
29
29
  const DEFAULT_PREVENT_CYCLE_DELEGATION = true;
30
30
  const FLOW_DEPTH_ENV = "PI_FLOW_DEPTH";
31
31
  const FLOW_MAX_DEPTH_ENV = "PI_FLOW_MAX_DEPTH";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-agent-flow",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Flow-state delegation extension for Pi coding agent.",
5
5
  "type": "module",
6
6
  "main": "index.ts",
package/runner-events.js CHANGED
@@ -52,7 +52,7 @@ export function drainStreamingText(result) {
52
52
  const CHARS_PER_TOKEN = 4;
53
53
 
54
54
  /** EMA smoothing factor for tokens-per-second (higher = more responsive). */
55
- const EMA_ALPHA = 0.3;
55
+ const EMA_ALPHA = 0.15;
56
56
 
57
57
  function getStreamingEstimate(result) {
58
58
  if (!Object.prototype.hasOwnProperty.call(result, "__streamingEstimate")) {