@nklisch/pi-enhanced 0.1.7 → 0.1.9

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-arm64-msvc.node +0 -0
  3. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
  4. package/node_modules/@nklisch/pi-model-modes/README.md +13 -4
  5. package/node_modules/@nklisch/pi-model-modes/package.json +1 -1
  6. package/node_modules/@nklisch/pi-model-modes/presets.json +7 -0
  7. package/node_modules/@nklisch/pi-model-modes/prompts/base/straight.md +9 -0
  8. package/node_modules/@nklisch/pi-model-modes/prompts/base.json +6 -1
  9. package/node_modules/@nklisch/pi-model-modes/prompts/styles/straight.md +9 -0
  10. package/node_modules/@nklisch/pi-model-modes/src/footer.ts +3 -2
  11. package/node_modules/@nklisch/pi-plugins/README.md +4 -4
  12. package/node_modules/@nklisch/pi-plugins/dist/application/plugin-lifecycle-service.js +19 -2
  13. package/node_modules/@nklisch/pi-plugins/dist/application/plugin-lifecycle-service.js.map +1 -1
  14. package/node_modules/@nklisch/pi-plugins/dist/application/ports/lifecycle-transition-store.d.ts +12 -0
  15. package/node_modules/@nklisch/pi-plugins/dist/application/ports/lifecycle-transition-store.js.map +1 -1
  16. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/recovery/create-node-recovery-adapters.js +2 -1
  17. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/recovery/create-node-recovery-adapters.js.map +1 -1
  18. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/recovery/sqlite-transition-journal.d.ts +4 -0
  19. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/recovery/sqlite-transition-journal.js +28 -1
  20. package/node_modules/@nklisch/pi-plugins/dist/infrastructure/recovery/sqlite-transition-journal.js.map +1 -1
  21. package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-package.js +1 -1
  22. package/node_modules/@nklisch/pi-plugins/dist/runtime/mcp/pi-mcp-adapter-runtime.js +1 -1
  23. package/node_modules/@nklisch/pi-plugins/dist/runtime/subagents/pi-subagents-package.js +1 -1
  24. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/CHANGELOG.md +11 -0
  25. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/dist/public.d.ts +3 -1
  26. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/FORK-MAINTENANCE.md +1 -1
  27. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +2 -1
  28. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +4 -4
  29. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/client-server-opportunities.md +4 -4
  30. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/comparison-with-upstream.md +1 -1
  31. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/package.json +1 -1
  32. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/index.ts +8 -8
  33. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/create-subagent-session.ts +1 -0
  34. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/parent-snapshot.ts +3 -0
  35. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-manager.ts +16 -1
  36. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent-session.ts +12 -1
  37. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/lifecycle/subagent.ts +18 -1
  38. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/composite-subagent-observer.ts +8 -0
  39. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/notification.ts +3 -0
  40. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/observation/renderer.ts +2 -2
  41. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/runtime.ts +1 -0
  42. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/service/service-adapter.ts +11 -3
  43. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/session-config.ts +7 -3
  44. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/session/thinking-level.ts +42 -0
  45. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/agent-tool.ts +3 -3
  46. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/background-spawner.ts +7 -2
  47. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/foreground-runner.ts +7 -5
  48. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-report.ts +4 -1
  49. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/get-result-tool.ts +1 -0
  50. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/helpers.ts +1 -1
  51. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/result-renderer.ts +7 -4
  52. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/spawn-config.ts +15 -2
  53. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/tools/steer-tool.ts +3 -3
  54. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/types.ts +6 -2
  55. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/agent-widget.ts +117 -62
  56. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/display.ts +8 -1
  57. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigation.ts +7 -3
  58. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/session-navigator.ts +2 -2
  59. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/src/ui/widget-renderer.ts +6 -4
  60. package/node_modules/@nklisch/pi-plugins/package.json +3 -3
  61. package/package.json +2 -2
@@ -0,0 +1,42 @@
1
+ import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai/compat";
2
+ import type { Model } from "@earendil-works/pi-ai";
3
+ import type { ThinkingLevel } from "#src/types";
4
+
5
+ /** Pi's default when no session setting is available. */
6
+ export const DEFAULT_THINKING_LEVEL: ThinkingLevel = "medium";
7
+
8
+ /**
9
+ * Resolve the level Pi will use for a model before its AgentSession exists.
10
+ *
11
+ * The session factory passes this resolved value to Pi, while the Subagent
12
+ * record replaces it with AgentSession.thinkingLevel after construction. That
13
+ * two-step flow keeps queued/launch status useful without allowing a local
14
+ * approximation to outrank the SDK's authoritative value.
15
+ */
16
+ export function resolveEffectiveThinkingLevel(
17
+ model: unknown,
18
+ requested?: ThinkingLevel,
19
+ inherited?: ThinkingLevel,
20
+ ): ThinkingLevel {
21
+ const level = requested ?? inherited ?? DEFAULT_THINKING_LEVEL;
22
+ // With no model yet, preserve the level Pi would receive rather than forcing
23
+ // `off`: createAgentSession may still resolve a configured default model.
24
+ // The created child session remains authoritative and supplies the clamp.
25
+ if (model == null) return level;
26
+ if (!isThinkingModel(model)) return "off";
27
+
28
+ const supported = getSupportedThinkingLevels(model);
29
+ return supported.includes(level)
30
+ ? level
31
+ : clampThinkingLevel(model, level);
32
+ }
33
+
34
+ function isThinkingModel(value: unknown): value is Model<any> {
35
+ if (typeof value !== "object" || value === null) return false;
36
+ const candidate = value as { provider?: unknown; id?: unknown; reasoning?: unknown };
37
+ return typeof candidate.provider === "string"
38
+ && candidate.provider.length > 0
39
+ && typeof candidate.id === "string"
40
+ && candidate.id.length > 0
41
+ && typeof candidate.reasoning === "boolean";
42
+ }
@@ -13,7 +13,7 @@ import { buildAgentGuidelines, buildDetails, buildTypeListText, textResult } fro
13
13
  import { renderAgentResult } from "#src/tools/result-renderer";
14
14
  import { type ModelInfo, resolveSpawnConfig } from "#src/tools/spawn-config";
15
15
  import type { ParentSessionInfo, Subagent } from "#src/types";
16
- import { type AgentDetails, formatDuration, getDisplayName } from "#src/ui/display";
16
+ import { type AgentDetails, formatDuration, formatModelThinking, getDisplayName } from "#src/ui/display";
17
17
 
18
18
  // ---- Deps interfaces ----
19
19
 
@@ -113,9 +113,9 @@ export class AgentTool {
113
113
  : `Error: ${record.error}`
114
114
  : partial ?? "No output.";
115
115
  return textResult(
116
- `Model: ${record.modelLabel}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}\n\n${resultText}`,
116
+ `Model: ${formatModelThinking(record.modelLabel, record.effectiveThinkingLevel)}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}\n\n${resultText}`,
117
117
  buildDetails(
118
- { ...config.presentation.detailBase, modelName: record.modelLabel },
118
+ { ...config.presentation.detailBase, modelName: record.modelLabel, thinkingLevel: record.effectiveThinkingLevel },
119
119
  record,
120
120
  ),
121
121
  );
@@ -1,6 +1,7 @@
1
1
  import type { ParentSnapshot } from "#src/lifecycle/parent-snapshot";
2
2
  import type { AgentSpawnConfig } from "#src/lifecycle/subagent-manager";
3
3
  import { textResult } from "#src/tools/helpers";
4
+ import { formatModelThinking } from "#src/ui/display";
4
5
  import type { ResolvedSpawnConfig } from "#src/tools/spawn-config";
5
6
  import type { ParentSessionInfo, Subagent } from "#src/types";
6
7
 
@@ -36,7 +37,7 @@ export function spawnBackground(
36
37
  model: execution.model,
37
38
  maxTurns: execution.effectiveMaxTurns,
38
39
  inheritContext: execution.inheritContext,
39
- thinkingLevel: execution.thinking,
40
+ thinkingLevel: execution.effectiveThinkingLevel,
40
41
  isBackground: true,
41
42
  origin: "tool",
42
43
  invocation: execution.agentInvocation,
@@ -52,7 +53,10 @@ export function spawnBackground(
52
53
  `Agent ${isQueued ? "queued" : "started"} in background.\n` +
53
54
  `Agent ID: ${id}\n` +
54
55
  `Type: ${identity.displayName}\n` +
55
- `Model: ${presentation.modelName}\n` +
56
+ `Model: ${formatModelThinking(
57
+ record?.modelLabel ?? presentation.modelName,
58
+ record?.effectiveThinkingLevel ?? execution.effectiveThinkingLevel,
59
+ )}\n` +
56
60
  `Runtime: 0.0s\n` +
57
61
  `Description: ${execution.description}\n` +
58
62
  (identity.fellBack ? `Fallback: requested ${identity.rawType}; using ${identity.subagentType}\n` : "") +
@@ -66,6 +70,7 @@ export function spawnBackground(
66
70
  `Do not duplicate this agent's work.`,
67
71
  {
68
72
  ...presentation.detailBase,
73
+ thinkingLevel: record?.effectiveThinkingLevel ?? execution.effectiveThinkingLevel,
69
74
  toolUses: 0,
70
75
  tokens: "",
71
76
  durationMs: 0,
@@ -12,6 +12,7 @@ import type { ParentSessionInfo, Subagent } from "#src/types";
12
12
  import {
13
13
  type AgentDetails,
14
14
  describeActivity,
15
+ formatModelThinking,
15
16
  formatMs,
16
17
  SPINNER,
17
18
  } from "#src/ui/display";
@@ -73,11 +74,12 @@ export async function runForeground(
73
74
  });
74
75
  };
75
76
 
76
- // Animate spinner at ~80ms (smooth rotation through 10 braille frames)
77
+ // Each update traverses the parent TUI tree; avoid doing that at animation
78
+ // speed while the foreground tool already owns the progress surface.
77
79
  const spinnerInterval = setInterval(() => {
78
80
  spinnerFrame++;
79
81
  streamUpdate();
80
- }, 80);
82
+ }, 500);
81
83
 
82
84
  streamUpdate();
83
85
 
@@ -92,7 +94,7 @@ export async function runForeground(
92
94
  model: execution.model,
93
95
  maxTurns: execution.effectiveMaxTurns,
94
96
  inheritContext: execution.inheritContext,
95
- thinkingLevel: execution.thinking,
97
+ thinkingLevel: execution.effectiveThinkingLevel,
96
98
  origin: "tool",
97
99
  invocation: execution.agentInvocation,
98
100
  signal,
@@ -125,7 +127,7 @@ export async function runForeground(
125
127
  if (record.status === "error") {
126
128
  const partial = record.result?.trim();
127
129
  return textResult(
128
- `${fallbackNote}Model: ${record.modelLabel}\nRuntime: ${formatMs(details.durationMs)}\nAgent failed: ${record.error}` +
130
+ `${fallbackNote}Model: ${formatModelThinking(record.modelLabel, record.effectiveThinkingLevel)}\nRuntime: ${formatMs(details.durationMs)}\nAgent failed: ${record.error}` +
129
131
  (partial ? `\n\nPartial output before the failure:\n${partial}` : ""),
130
132
  details,
131
133
  );
@@ -135,7 +137,7 @@ export async function runForeground(
135
137
  const statsParts = [`${record.toolUses} tool uses`];
136
138
  if (tokenText) statsParts.push(tokenText);
137
139
  return textResult(
138
- `${fallbackNote}Model: ${record.modelLabel}\nRuntime: ${formatMs(durationMs)}\nAgent completed (${statsParts.join(", ")})${getStatusNote(record.status)}.\n\n` +
140
+ `${fallbackNote}Model: ${formatModelThinking(record.modelLabel, record.effectiveThinkingLevel)}\nRuntime: ${formatMs(durationMs)}\nAgent completed (${statsParts.join(", ")})${getStatusNote(record.status)}.\n\n` +
139
141
  (record.result?.trim() ?? "No output."),
140
142
  details,
141
143
  );
@@ -8,12 +8,15 @@
8
8
  */
9
9
 
10
10
  import type { SubagentStatus } from "#src/lifecycle/subagent";
11
+ import type { ThinkingLevel } from "#src/types";
12
+ import { formatModelThinking } from "#src/ui/display";
11
13
 
12
14
  /** The data a get_subagent_result report renders from — only what the formatter reads. */
13
15
  export interface AgentReport {
14
16
  id: string;
15
17
  displayName: string;
16
18
  modelLabel: string;
19
+ thinkingLevel: ThinkingLevel;
17
20
  status: SubagentStatus;
18
21
  toolUses: number;
19
22
  /** Pre-formatted lifetime token total; "" when zero. */
@@ -63,7 +66,7 @@ export function renderReportBody(report: AgentReport): string {
63
66
  export function formatAgentReport(report: AgentReport): string {
64
67
  let output =
65
68
  `Agent: ${report.id}\n` +
66
- `Type: ${report.displayName} | Model: ${report.modelLabel} | Status: ${report.status} | ${renderStatsParts(report).join(" | ")}\n` +
69
+ `Type: ${report.displayName} | Model: ${formatModelThinking(report.modelLabel, report.thinkingLevel)} | Status: ${report.status} | ${renderStatsParts(report).join(" | ")}\n` +
67
70
  `Description: ${report.description}\n\n`;
68
71
  output += renderReportBody(report);
69
72
  if (report.conversation) {
@@ -47,6 +47,7 @@ export class GetResultTool {
47
47
  id: record.id,
48
48
  displayName: getDisplayName(record.type, this.registry),
49
49
  modelLabel: record.modelLabel,
50
+ thinkingLevel: record.effectiveThinkingLevel,
50
51
  status: record.status,
51
52
  toolUses: record.toolUses,
52
53
  tokens: formatLifetimeTokens(record),
@@ -18,7 +18,7 @@ export function getStatusNote(status: string): string {
18
18
 
19
19
  /** Build AgentDetails from a base + record-specific fields. */
20
20
  export function buildDetails(
21
- base: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "tags">,
21
+ base: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "thinkingLevel" | "tags">,
22
22
  record: {
23
23
  toolUses: number;
24
24
  startedAt: number;
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import type { AgentDetails, Theme } from "#src/ui/display";
10
- import { formatMs, formatTurns, SPINNER } from "#src/ui/display";
10
+ import { formatModelThinking, formatMs, formatTurns, SPINNER } from "#src/ui/display";
11
11
 
12
12
  // ---- Dispatcher ----
13
13
 
@@ -42,7 +42,10 @@ export function renderRunning(details: AgentDetails, theme: Theme): string {
42
42
 
43
43
  /** Render background launch status. */
44
44
  export function renderBackground(details: AgentDetails, theme: Theme): string {
45
- const identity = [details.modelName, formatMs(details.durationMs)].filter(Boolean).join(" · ");
45
+ const identity = [
46
+ formatModelThinking(details.modelName ?? "unknown model", details.thinkingLevel),
47
+ formatMs(details.durationMs),
48
+ ].join(" · ");
46
49
  return theme.fg("dim", ` \u23BF Running in background (ID: ${details.agentId}) · ${identity}`);
47
50
  }
48
51
 
@@ -113,8 +116,8 @@ export function renderFailed(details: AgentDetails, theme: Theme): string {
113
116
  */
114
117
  export function renderStats(details: AgentDetails, theme: Theme): string {
115
118
  const parts: string[] = [];
116
- if (details.modelName) parts.push(details.modelName);
117
- if (details.tags) parts.push(...details.tags);
119
+ parts.push(formatModelThinking(details.modelName ?? "unknown model", details.thinkingLevel));
120
+ if (details.tags) parts.push(...details.tags.filter((tag) => !tag.startsWith("thinking: ")));
118
121
  if (details.turnCount != null && details.turnCount > 0) {
119
122
  parts.push(formatTurns(details.turnCount, details.maxTurns));
120
123
  }
@@ -14,6 +14,7 @@ import { normalizeMaxTurns } from "#src/lifecycle/turn-limits";
14
14
  import type { ModelRegistry } from "#src/session/model-resolver";
15
15
  import { formatModelLabel } from "#src/session/model-label";
16
16
  import { resolveInvocationModel } from "#src/session/model-resolver";
17
+ import { resolveEffectiveThinkingLevel } from "#src/session/thinking-level";
17
18
  import type { AgentInvocation, SubagentType, ThinkingLevel } from "#src/types";
18
19
  import {
19
20
  type AgentDetails,
@@ -25,6 +26,8 @@ import {
25
26
  /** Model info extracted from the parent session context. */
26
27
  export interface ModelInfo {
27
28
  parentModel: Model<any> | undefined;
29
+ /** Parent's current level for children that inherit thinking settings. */
30
+ parentThinkingLevel?: ThinkingLevel;
28
31
  modelRegistry: ModelRegistry | undefined;
29
32
  }
30
33
 
@@ -42,7 +45,10 @@ export interface SpawnExecution {
42
45
  description: string;
43
46
  model: Model<any> | undefined;
44
47
  effectiveMaxTurns: number | undefined;
48
+ /** Requested/configured level before model-capability clamping. */
45
49
  thinking: ThinkingLevel | undefined;
50
+ /** Exact level passed to the child session after model-capability clamping. */
51
+ effectiveThinkingLevel: ThinkingLevel;
46
52
  inheritContext: boolean;
47
53
  runInBackground: boolean;
48
54
  agentInvocation: AgentInvocation;
@@ -50,9 +56,9 @@ export interface SpawnExecution {
50
56
 
51
57
  /** Presentation: display/UI values derived from identity and execution. */
52
58
  export interface SpawnPresentation {
53
- modelName: string | undefined;
59
+ modelName: string;
54
60
  agentTags: string[];
55
- detailBase: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "tags">;
61
+ detailBase: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "thinkingLevel" | "tags">;
56
62
  }
57
63
 
58
64
  /** Fully resolved config for spawning an agent — composed of domain-aligned sub-interfaces. */
@@ -110,6 +116,11 @@ export function resolveSpawnConfig(
110
116
  const model = resolution.model;
111
117
 
112
118
  const thinking = resolvedConfig.thinking;
119
+ const effectiveThinkingLevel = resolveEffectiveThinkingLevel(
120
+ model,
121
+ thinking,
122
+ modelInfo.parentThinkingLevel,
123
+ );
113
124
  const inheritContext = resolvedConfig.inheritContext;
114
125
  const runInBackground = resolvedConfig.runInBackground;
115
126
 
@@ -137,6 +148,7 @@ export function resolveSpawnConfig(
137
148
  description: params.description as string,
138
149
  subagentType,
139
150
  modelName,
151
+ thinkingLevel: effectiveThinkingLevel,
140
152
  tags: agentTags.length > 0 ? agentTags : undefined,
141
153
  };
142
154
 
@@ -148,6 +160,7 @@ export function resolveSpawnConfig(
148
160
  model,
149
161
  effectiveMaxTurns,
150
162
  thinking,
163
+ effectiveThinkingLevel,
151
164
  inheritContext,
152
165
  runInBackground,
153
166
  agentInvocation,
@@ -2,7 +2,7 @@ import { defineTool } from "@earendil-works/pi-coding-agent";
2
2
  import { Type } from "@sinclair/typebox";
3
3
  import { formatLifetimeTokens, textResult } from "#src/tools/helpers";
4
4
  import type { SteerOutcome, Subagent } from "#src/types";
5
- import { formatDuration } from "#src/ui/display";
5
+ import { formatDuration, formatModelThinking } from "#src/ui/display";
6
6
 
7
7
  // ---- Deps interfaces ----
8
8
 
@@ -68,7 +68,7 @@ export class SteerTool {
68
68
  private renderDelivered(record: Subagent) {
69
69
  const tokens = formatLifetimeTokens(record);
70
70
  const contextPercent = record.getContextPercent();
71
- const stateParts: string[] = [record.modelLabel, formatDuration(record.startedAt, record.completedAt)];
71
+ const stateParts: string[] = [formatModelThinking(record.modelLabel, record.effectiveThinkingLevel), formatDuration(record.startedAt, record.completedAt)];
72
72
  if (tokens) stateParts.push(tokens);
73
73
  stateParts.push(`${record.toolUses} tool ${record.toolUses === 1 ? "use" : "uses"}`);
74
74
  if (contextPercent !== null)
@@ -84,7 +84,7 @@ export class SteerTool {
84
84
  }
85
85
 
86
86
  private renderRunIdentity(record: Subagent): string {
87
- return `Model: ${record.modelLabel}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}`;
87
+ return `Model: ${formatModelThinking(record.modelLabel, record.effectiveThinkingLevel)}\nRuntime: ${formatDuration(record.startedAt, record.completedAt)}`;
88
88
  }
89
89
 
90
90
  toToolDefinition() {
@@ -2,14 +2,16 @@
2
2
  * types.ts — Type definitions for the subagent system.
3
3
  */
4
4
 
5
- import type { ThinkingLevel } from "@earendil-works/pi-ai";
5
+ import type { ModelThinkingLevel } from "@earendil-works/pi-ai";
6
6
  import type { AgentSessionEvent, SessionContext as SdkSessionContext } from "@earendil-works/pi-coding-agent";
7
7
  import type { ModelRegistry } from "#src/session/model-resolver";
8
8
 
9
9
 
10
10
  export type { SteerOutcome } from "#src/lifecycle/subagent";
11
11
  export { Subagent } from "#src/lifecycle/subagent";
12
- export type { AgentSessionEvent, ThinkingLevel };
12
+ export type { AgentSessionEvent };
13
+ /** Pi's model-capability thinking levels, including the explicit `off` value. */
14
+ export type ThinkingLevel = ModelThinkingLevel;
13
15
 
14
16
  /**
15
17
  * One message in a child session's history, typed from Pi's `SessionContext`.
@@ -86,6 +88,8 @@ export interface AgentInvocation {
86
88
  export interface SessionContext {
87
89
  readonly cwd: string;
88
90
  readonly model: unknown;
91
+ /** Parent session's current effective thinking level for inherited children. */
92
+ readonly thinkingLevel?: ThinkingLevel;
89
93
  readonly modelRegistry: ModelRegistry | undefined;
90
94
  getSystemPrompt(): string;
91
95
  readonly sessionManager: {