@oh-my-pi/pi-coding-agent 16.0.1 → 16.0.3

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 (102) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +0 -1
  3. package/dist/cli.js +316 -371
  4. package/dist/types/advisor/advise-tool.d.ts +30 -1
  5. package/dist/types/commands/install.d.ts +1 -1
  6. package/dist/types/config/model-resolver.d.ts +22 -0
  7. package/dist/types/config/settings-schema.d.ts +0 -10
  8. package/dist/types/eval/js/shared/runtime.d.ts +1 -0
  9. package/dist/types/eval/js/worker-core.d.ts +1 -0
  10. package/dist/types/exec/non-interactive-env.d.ts +2 -0
  11. package/dist/types/extensibility/extensions/loader.d.ts +2 -2
  12. package/dist/types/goals/runtime.d.ts +0 -1
  13. package/dist/types/mcp/tool-bridge.d.ts +3 -0
  14. package/dist/types/modes/components/custom-editor.d.ts +14 -4
  15. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  16. package/dist/types/modes/interactive-mode.d.ts +1 -1
  17. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +3 -2
  18. package/dist/types/modes/theme/mermaid-cache.d.ts +18 -1
  19. package/dist/types/modes/types.d.ts +1 -1
  20. package/dist/types/registry/agent-lifecycle.d.ts +16 -1
  21. package/dist/types/sdk.d.ts +8 -0
  22. package/dist/types/session/agent-session.d.ts +20 -8
  23. package/dist/types/session/messages.d.ts +3 -0
  24. package/dist/types/session/session-dump-format.d.ts +8 -2
  25. package/dist/types/session/session-entries.d.ts +4 -0
  26. package/dist/types/session/session-history-format.d.ts +2 -0
  27. package/dist/types/session/session-manager.d.ts +22 -0
  28. package/dist/types/stt/downloader.d.ts +5 -5
  29. package/dist/types/task/executor.d.ts +6 -0
  30. package/dist/types/task/persisted-revive.d.ts +36 -0
  31. package/dist/types/tiny/models.d.ts +8 -0
  32. package/dist/types/tools/builtin-names.d.ts +1 -1
  33. package/dist/types/tools/index.d.ts +0 -1
  34. package/dist/types/utils/markit.d.ts +8 -0
  35. package/package.json +12 -12
  36. package/src/advisor/__tests__/advisor.test.ts +156 -12
  37. package/src/advisor/advise-tool.ts +48 -6
  38. package/src/advisor/runtime.ts +10 -3
  39. package/src/auto-thinking/classifier.ts +12 -3
  40. package/src/cli/args.ts +1 -0
  41. package/src/cli.ts +2 -2
  42. package/src/commands/install.ts +3 -3
  43. package/src/config/model-resolver.ts +63 -12
  44. package/src/config/settings-schema.ts +0 -11
  45. package/src/discovery/github.ts +89 -1
  46. package/src/eval/agent-bridge.ts +2 -0
  47. package/src/eval/js/context-manager.ts +2 -1
  48. package/src/eval/js/shared/runtime.ts +189 -15
  49. package/src/eval/js/worker-core.ts +19 -0
  50. package/src/exec/bash-executor.ts +2 -2
  51. package/src/exec/non-interactive-env.ts +71 -0
  52. package/src/export/html/index.ts +1 -1
  53. package/src/export/html/tool-views.generated.js +34 -35
  54. package/src/extensibility/extensions/loader.ts +21 -9
  55. package/src/extensibility/extensions/runner.ts +17 -1
  56. package/src/extensibility/plugins/loader.ts +154 -21
  57. package/src/extensibility/plugins/manager.ts +40 -33
  58. package/src/goals/runtime.ts +1 -23
  59. package/src/internal-urls/docs-index.generated.ts +9 -11
  60. package/src/main.ts +20 -0
  61. package/src/mcp/render.ts +11 -1
  62. package/src/mcp/tool-bridge.ts +3 -0
  63. package/src/modes/components/custom-editor.test.ts +63 -18
  64. package/src/modes/components/custom-editor.ts +63 -15
  65. package/src/modes/controllers/command-controller.ts +2 -2
  66. package/src/modes/controllers/input-controller.ts +15 -9
  67. package/src/modes/controllers/selector-controller.ts +13 -8
  68. package/src/modes/controllers/tan-command-controller.ts +1 -0
  69. package/src/modes/interactive-mode.ts +4 -2
  70. package/src/modes/setup-wizard/wizard-overlay.ts +26 -4
  71. package/src/modes/theme/mermaid-cache.ts +74 -11
  72. package/src/modes/theme/theme.ts +14 -1
  73. package/src/modes/types.ts +1 -1
  74. package/src/prompts/system/system-prompt.md +2 -1
  75. package/src/registry/agent-lifecycle.ts +60 -8
  76. package/src/sdk.ts +20 -26
  77. package/src/session/agent-session.ts +381 -110
  78. package/src/session/artifacts.ts +19 -1
  79. package/src/session/messages.ts +1 -1
  80. package/src/session/session-dump-format.ts +167 -23
  81. package/src/session/session-entries.ts +4 -0
  82. package/src/session/session-history-format.ts +37 -3
  83. package/src/session/session-manager.ts +94 -4
  84. package/src/slash-commands/builtin-registry.ts +4 -7
  85. package/src/stt/asr-client.ts +6 -0
  86. package/src/stt/downloader.ts +13 -6
  87. package/src/stt/stt-controller.ts +52 -11
  88. package/src/system-prompt.ts +7 -1
  89. package/src/task/executor.ts +118 -6
  90. package/src/task/index.ts +2 -2
  91. package/src/task/persisted-revive.ts +128 -0
  92. package/src/tiny/models.ts +10 -0
  93. package/src/tiny/worker.ts +4 -3
  94. package/src/tools/builtin-names.ts +0 -1
  95. package/src/tools/index.ts +0 -4
  96. package/src/tools/output-meta.ts +17 -3
  97. package/src/utils/lang-from-path.ts +5 -0
  98. package/src/utils/markit.ts +24 -1
  99. package/src/utils/title-generator.ts +4 -4
  100. package/dist/types/tools/render-mermaid.d.ts +0 -38
  101. package/src/prompts/tools/render-mermaid.md +0 -9
  102. package/src/tools/render-mermaid.ts +0 -69
@@ -23,7 +23,12 @@ export interface AdvisorNote {
23
23
  export interface AdvisorMessageDetails {
24
24
  notes: AdvisorNote[];
25
25
  }
26
- /** Render one advisor card body from a batch of notes (prefix + one bullet per note). */
26
+ /**
27
+ * Render a batch of advisor notes as the agent-facing message body: one
28
+ * `<advisory>` element per note, severity as an attribute. Shared by the
29
+ * non-interrupting YieldQueue dispatcher and the interrupting steer path so both
30
+ * build byte-identical content.
31
+ */
27
32
  export declare function formatAdvisorBatchContent(notes: readonly AdvisorNote[]): string;
28
33
  /**
29
34
  * Whether advice at this severity should interrupt the running agent (delivered
@@ -32,6 +37,30 @@ export declare function formatAdvisorBatchContent(notes: readonly AdvisorNote[])
32
37
  * and `blocker` interrupt; a plain `nit` queues.
33
38
  */
34
39
  export declare function isInterruptingSeverity(severity: AdvisorSeverity | undefined): boolean;
40
+ /** How an advisor note is routed to the primary. */
41
+ export type AdvisorDeliveryChannel = "aside" | "steer" | "preserve";
42
+ /**
43
+ * Decide how one advisor note reaches the primary agent.
44
+ *
45
+ * - A non-interrupting `nit` always rides the non-interrupting aside queue.
46
+ * - An interrupting `concern`/`blocker` is normally steered into the agent: into
47
+ * the live turn while one is streaming, or (when idle) a triggered turn so the
48
+ * advice is acted on immediately.
49
+ * - After a deliberate user interrupt (`autoResumeSuppressed`) the advisor must
50
+ * not auto-resume the stopped run. While the agent is idle — or still tearing
51
+ * the interrupted turn down (`aborting`) — the note is preserved as a visible
52
+ * card instead of restarting the run. But once a turn is actively streaming
53
+ * again (a resume the user already drove), steering the note in does NOT
54
+ * auto-resume anything, so it is delivered live. Parking it during an active
55
+ * run instead strands it (it never reaches the running agent) and the withheld
56
+ * notes dump as one burst at the next user prompt — the bug this guards.
57
+ */
58
+ export declare function resolveAdvisorDeliveryChannel(opts: {
59
+ severity: AdvisorSeverity | undefined;
60
+ autoResumeSuppressed: boolean;
61
+ streaming: boolean;
62
+ aborting: boolean;
63
+ }): AdvisorDeliveryChannel;
35
64
  /**
36
65
  * Side-effect-free investigation tools handed to the advisor agent so it can
37
66
  * inspect the workspace before weighing in. Names match the primary session's
@@ -22,7 +22,7 @@ import { Command } from "@oh-my-pi/pi-utils/cli";
22
22
  * Heuristic used to decide whether `omp install <target>` should `link` a
23
23
  * local directory or `install` a remote spec. Exported for tests.
24
24
  */
25
- export declare function looksLikeLocalPath(target: string): boolean;
25
+ export declare function looksLikeLocalPath(target: string, cwd?: string): boolean;
26
26
  export default class Install extends Command {
27
27
  static description: string;
28
28
  static args: {
@@ -19,6 +19,14 @@ import type { Api, Effort, Model } from "@oh-my-pi/pi-ai";
19
19
  import { type ModelRegistry } from "./model-registry";
20
20
  import { type ModelRole } from "./model-roles";
21
21
  import type { Settings } from "./settings";
22
+ /**
23
+ * Pick the first provider-default model in availability order.
24
+ *
25
+ * If multiple providers expose that same default id, rank only that shared-id
26
+ * group by canonical provider priority so native/OAuth transports beat mirrors
27
+ * without changing unrelated provider fallback precedence.
28
+ */
29
+ export declare function pickDefaultAvailableModel(availableModels: Model<Api>[]): Model<Api> | undefined;
22
30
  export interface ScopedModel {
23
31
  model: Model<Api>;
24
32
  thinkingLevel?: ThinkingLevel;
@@ -37,7 +45,21 @@ export declare function parseModelString(modelStr: string): {
37
45
  * Format a model as "provider/modelId" string.
38
46
  */
39
47
  export declare function formatModelString(model: Model<Api>): string;
48
+ export declare function formatModelStringWithRouting(model: Model<Api>): string;
40
49
  export declare function formatModelSelectorValue(selector: string, thinkingLevel: ThinkingLevel | undefined): string;
50
+ /**
51
+ * Split a trailing `@<upstream>` provider-routing selector off a model pattern.
52
+ *
53
+ * `openrouter/z-ai/glm-4.7@cerebras` -> base `openrouter/z-ai/glm-4.7`, upstream
54
+ * `cerebras`. A `:thinking` suffix after the slug is kept on the base
55
+ * (`...@cerebras:high` -> base `...:high`). Returns undefined when there is no
56
+ * `@` or the suffix is not a bare provider slug, so model ids that legitimately
57
+ * contain `@` (`claude-opus-4-8@default`, `workers-ai/@cf/...`) are never split.
58
+ */
59
+ export declare function splitUpstreamRouting(pattern: string): {
60
+ base: string;
61
+ upstream: string;
62
+ } | undefined;
41
63
  export declare function resolveProviderModelReference(provider: string, modelId: string, availableModels: readonly Model<Api>[]): Model<Api> | undefined;
42
64
  export interface ModelMatchPreferences {
43
65
  /** Most-recently-used model keys (provider/modelId) to prefer when ambiguous. */
@@ -3241,16 +3241,6 @@ export declare const SETTINGS_SCHEMA: {
3241
3241
  readonly description: "Enable the ast_edit tool for structural AST rewrites";
3242
3242
  };
3243
3243
  };
3244
- readonly "renderMermaid.enabled": {
3245
- readonly type: "boolean";
3246
- readonly default: false;
3247
- readonly ui: {
3248
- readonly tab: "tools";
3249
- readonly group: "Available Tools";
3250
- readonly label: "Render Mermaid";
3251
- readonly description: "Enable the render_mermaid tool for Mermaid-to-ASCII rendering";
3252
- };
3253
- };
3254
3244
  readonly "debug.enabled": {
3255
3245
  readonly type: "boolean";
3256
3246
  readonly default: true;
@@ -55,4 +55,5 @@ export declare class JsRuntime {
55
55
  cwd?: string;
56
56
  }): Promise<unknown>;
57
57
  displayValue(value: unknown, hooks?: RuntimeHooks | undefined): void;
58
+ dispose(): void;
58
59
  }
@@ -2,4 +2,5 @@ import type { Transport } from "./worker-protocol";
2
2
  export declare class WorkerCore {
3
3
  #private;
4
4
  constructor(transport: Transport);
5
+ dispose(): void;
5
6
  }
@@ -1 +1,3 @@
1
1
  export declare const NON_INTERACTIVE_ENV: Readonly<Record<string, string>>;
2
+ /** Builds the per-command environment for non-interactive child processes. */
3
+ export declare function buildNonInteractiveEnv(overrides?: Record<string, string>, baseEnv?: Record<string, string | undefined>, platform?: NodeJS.Platform): Record<string, string>;
@@ -40,8 +40,8 @@ export declare function loadExtensions(paths: string[], cwd: string, eventBus?:
40
40
  /**
41
41
  * Discover absolute paths of extensions to load, without importing or
42
42
  * binding factories. Hot path on session startup — the scan walks native
43
- * `.omp`/`.pi` extension capabilities, the installed-plugin tree, and any
44
- * configured paths.
43
+ * `.omp`/`.pi` extension capabilities, JS/TS hook factories, the
44
+ * installed-plugin tree, and any configured paths.
45
45
  *
46
46
  * Subagents reuse the parent's collected paths via the SDK's
47
47
  * `preloadedExtensionPaths` option, then call {@link loadExtensions} themselves
@@ -28,7 +28,6 @@ export interface GoalRuntimeSnapshot {
28
28
  }
29
29
  export type GoalPromptKind = "active" | "continuation" | "budget-limit";
30
30
  export declare function remainingTokens(goal: Goal | null | undefined): number | null;
31
- export declare function escapeXmlText(input: string): string;
32
31
  export declare function renderTrustedObjective(objective: string): string;
33
32
  export declare function goalTokenDelta(current: GoalTokenUsage, baseline: GoalTokenUsage): number;
34
33
  export declare function renderGoalPrompt(kind: GoalPromptKind, goal: Goal): string;
@@ -8,6 +8,7 @@ import type { TSchema } from "@oh-my-pi/pi-ai";
8
8
  import type { SourceMeta } from "../capability/types";
9
9
  import type { CustomTool, CustomToolContext, CustomToolResult, RenderResultOptions } from "../extensibility/custom-tools/types";
10
10
  import type { Theme } from "../modes/theme/theme";
11
+ import type { OutputMeta } from "../tools/output-meta";
11
12
  import type { MCPContent, MCPServerConnection, MCPToolDefinition } from "./types";
12
13
  /** Reconnect callback: tears down stale connection, returns new one or null. */
13
14
  export type MCPReconnect = () => Promise<MCPServerConnection | null>;
@@ -26,6 +27,8 @@ export interface MCPToolDetails {
26
27
  provider?: string;
27
28
  /** Provider display name (e.g., "Claude Code", "MCP Config") */
28
29
  providerName?: string;
30
+ /** Structured output metadata (set by the spill wrapper when output is truncated to an artifact). */
31
+ meta?: OutputMeta;
29
32
  }
30
33
  export declare function createMCPToolName(serverName: string, toolName: string): string;
31
34
  /**
@@ -1,10 +1,20 @@
1
1
  import { Editor, type KeyId } from "@oh-my-pi/pi-tui";
2
2
  import type { AppKeybinding } from "../../config/keybindings";
3
3
  type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.display.reset" | "app.thinking.cycle" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.clipboard.pasteImage" | "app.clipboard.pasteTextRaw" | "app.clipboard.copyPrompt">;
4
- /** Plain spaces from one auto-repeat run that trigger the space-hold push-to-talk STT gesture.
5
- * Holding the space bar makes the terminal emit a burst of spaces; once more than this many land
6
- * in the editor we treat it as "space held", track them back out, and start recording. */
7
- export declare const SPACE_HOLD_THRESHOLD = 5;
4
+ /** Max gap (ms) between two spaces for the later one to count as OS key auto-repeat rather than a
5
+ * deliberate press. OS auto-repeat is fast; a deliberate tap (even a fast one) is slower. */
6
+ export declare const SPACE_REPEAT_MAX_GAP_MS = 120;
7
+ /** Two consecutive inter-space gaps are "mechanical" (machine-driven auto-repeat) when both are
8
+ * within {@link SPACE_REPEAT_MAX_GAP_MS} and differ by no more than this — an absolute jitter floor
9
+ * or, for slower repeat rates, {@link SPACE_REPEAT_JITTER_RATIO} of the smaller gap. OS key-repeat
10
+ * is metronomic; a human smashing the bar is fast but irregular, so its deltas never stay this
11
+ * steady. */
12
+ export declare const SPACE_REPEAT_JITTER_MS = 18;
13
+ export declare const SPACE_REPEAT_JITTER_RATIO = 0.35;
14
+ /** Consecutive mechanical (fast + steady) deltas that confirm the space bar is held and start
15
+ * recording. Needs a sustained metronomic cadence, so jittery smashing and deliberate taps never
16
+ * reach it. */
17
+ export declare const SPACE_HOLD_MECHANICAL_RUN = 2;
8
18
  /** Idle gap (ms) after the last repeated space that counts as the space bar being released, ending
9
19
  * the push-to-talk recording. Must comfortably exceed the OS key-repeat interval. */
10
20
  export declare const SPACE_HOLD_RELEASE_MS = 250;
@@ -10,7 +10,7 @@ export declare class CommandController {
10
10
  constructor(ctx: InteractiveModeContext);
11
11
  openInBrowser(urlOrPath: string): void;
12
12
  handleExportCommand(text: string): Promise<void>;
13
- handleDumpCommand(isRaw?: boolean): void;
13
+ handleDumpCommand(): void;
14
14
  handleAdvisorDumpCommand(isRaw?: boolean): void;
15
15
  handleDebugTranscriptCommand(): Promise<void>;
16
16
  handleShareCommand(): Promise<void>;
@@ -268,7 +268,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
268
268
  findLastAssistantMessage(): AssistantMessage | undefined;
269
269
  extractAssistantText(message: AssistantMessage): string;
270
270
  handleExportCommand(text: string): Promise<void>;
271
- handleDumpCommand(isRaw?: boolean): void;
271
+ handleDumpCommand(): void;
272
272
  handleAdvisorDumpCommand(isRaw?: boolean): void;
273
273
  handleDebugTranscriptCommand(): Promise<void>;
274
274
  handleShareCommand(): Promise<void>;
@@ -1,7 +1,7 @@
1
- import { type Component } from "@oh-my-pi/pi-tui";
1
+ import { type Component, type OverlayFocusOwner } from "@oh-my-pi/pi-tui";
2
2
  import type { InteractiveModeContext } from "../types";
3
3
  import type { SetupScene } from "./scenes/types";
4
- export declare class SetupWizardComponent implements Component {
4
+ export declare class SetupWizardComponent implements Component, OverlayFocusOwner {
5
5
  #private;
6
6
  readonly ctx: InteractiveModeContext;
7
7
  readonly scenes: readonly SetupScene[];
@@ -9,6 +9,7 @@ export declare class SetupWizardComponent implements Component {
9
9
  run(): Promise<void>;
10
10
  dispose(): void;
11
11
  invalidate(): void;
12
+ ownsOverlayFocusTarget(component: Component): boolean;
12
13
  handleInput(data: string): void;
13
14
  render(width: number): readonly string[];
14
15
  }
@@ -1,8 +1,25 @@
1
+ import { type MermaidAsciiRenderOptions } from "@oh-my-pi/pi-utils";
2
+ /**
3
+ * Options controlling how fenced Mermaid source is resolved to terminal ASCII.
4
+ * Extends the raw render options (theme, color mode, spacing, `useAscii`) with a
5
+ * viewport-fitting hint.
6
+ */
7
+ export interface MermaidResolveOptions extends MermaidAsciiRenderOptions {
8
+ /**
9
+ * Maximum display width (terminal columns) the diagram should occupy. A
10
+ * layout that overflows this width is re-rendered in the perpendicular
11
+ * orientation — a wide horizontal chain collapses to a tall vertical column
12
+ * (which the terminal can scroll), and a wide vertical fan-out collapses to a
13
+ * tall horizontal column. Omit to keep the source's own layout regardless of
14
+ * width.
15
+ */
16
+ maxWidth?: number;
17
+ }
1
18
  /**
2
19
  * Resolve mermaid ASCII from fenced block source text.
3
20
  * Returns null when rendering fails, while memoizing failures to avoid repeated work.
4
21
  */
5
- export declare function resolveMermaidAscii(source: string): string | null;
22
+ export declare function resolveMermaidAscii(source: string, options?: MermaidResolveOptions): string | null;
6
23
  /**
7
24
  * Clear the mermaid cache.
8
25
  */
@@ -262,7 +262,7 @@ export interface InteractiveModeContext {
262
262
  handleHotkeysCommand(): void;
263
263
  handleToolsCommand(): void;
264
264
  handleContextCommand(): void;
265
- handleDumpCommand(isRaw?: boolean): void;
265
+ handleDumpCommand(): void;
266
266
  handleAdvisorDumpCommand(isRaw?: boolean): void;
267
267
  handleDebugTranscriptCommand(): Promise<void>;
268
268
  handleClearCommand(): Promise<void>;
@@ -10,8 +10,16 @@
10
10
  * `parked` ↔ `idle`.
11
11
  */
12
12
  import type { AgentSession } from "../session/agent-session";
13
- import { AgentRegistry } from "./agent-registry";
13
+ import { type AgentRef, AgentRegistry } from "./agent-registry";
14
14
  export type AgentReviver = () => Promise<AgentSession>;
15
+ /**
16
+ * Builds a reviver for a `parked` ref restored from disk (Agent Hub scan,
17
+ * collab mirror, resumed process) that carries a sessionFile but no in-memory
18
+ * adoption. Returns undefined when the ref cannot be faithfully rebuilt (no
19
+ * persisted session contract, or its workspace is gone). Injected from the
20
+ * top-level session so this manager stays free of sdk/SessionManager imports.
21
+ */
22
+ export type PersistedSubagentReviverFactory = (ref: AgentRef) => Promise<AgentReviver | undefined>;
15
23
  export interface AdoptOptions {
16
24
  /** TTL before an idle agent is parked. <= 0 disables parking. */
17
25
  idleTtlMs: number;
@@ -24,6 +32,13 @@ export declare class AgentLifecycleManager {
24
32
  /** Reset the global manager. Test-only. */
25
33
  static resetGlobalForTests(): void;
26
34
  constructor(registry?: AgentRegistry);
35
+ /**
36
+ * Install the factory used to cold-revive `parked` refs restored from disk
37
+ * (Agent Hub scan, collab mirror, resumed process) — they carry a sessionFile
38
+ * but no adoption. Set by the top-level session, which owns the ambient deps
39
+ * (auth, models, MCP, artifacts) the factory needs at revive time.
40
+ */
41
+ setPersistedSubagentReviverFactory(factory: PersistedSubagentReviverFactory, idleTtlMs: number): void;
27
42
  /**
28
43
  * Take ownership of a finished subagent. Caller has already set registry
29
44
  * status to "idle". Arms the TTL timer (idleTtlMs <= 0 adopts without one).
@@ -144,6 +144,14 @@ export interface CreateAgentSessionOptions {
144
144
  agentRegistry?: AgentRegistry;
145
145
  /** Parent task ID prefix for nested artifact naming (e.g., "Extensions") */
146
146
  parentTaskPrefix?: string;
147
+ /**
148
+ * Registry id of the spawning agent, recorded as this subagent's parent in
149
+ * the agent registry. Distinct from `parentTaskPrefix`, which is this agent's
150
+ * own artifact/output-id prefix (the executor passes the child's own id
151
+ * there, so it must never double as the parent link). Undefined for the
152
+ * top-level "Main" session, which has no parent.
153
+ */
154
+ parentAgentId?: string;
147
155
  /** Inherited eval executor session id for subagents sharing parent eval state. */
148
156
  parentEvalSessionId?: string;
149
157
  /** Session manager. Default: session stored under the configured agentDir sessions root */
@@ -669,12 +669,23 @@ export declare class AgentSession {
669
669
  sendUserMessage(content: string | (TextContent | ImageContent)[], options?: {
670
670
  deliverAs?: "steer" | "followUp";
671
671
  }): Promise<void>;
672
- /** Clear queued messages and return them (text plus any attached images). */
673
- clearQueue(): {
672
+ /** Clear queued messages and return the user-restorable ones (text plus any attached images).
673
+ * Only user-authored messages (plain user turns, `attribution:"user"` custom like `/skill`) are
674
+ * returned for editor restore. Other queued messages stay in the agent-core queues so a continuing
675
+ * stream still delivers them — EXCEPT on `forInterrupt` (Esc+abort), where only advisor cards are
676
+ * kept (abort()'s #extractQueuedAdvisorCards preserves them as visible advice) and every other
677
+ * non-user steer (hidden goal/plan/budget, IRC/extension asides) is dropped, so abort()'s
678
+ * #drainStrandedQueuedMessages can't auto-resume the run the user just interrupted (the drain only
679
+ * fires while agent.hasQueuedMessages()). Plain Alt+Up dequeue preserves those non-user steers. */
680
+ clearQueue(options?: {
681
+ forInterrupt?: boolean;
682
+ }): {
674
683
  steering: RestoredQueuedMessage[];
675
684
  followUp: RestoredQueuedMessage[];
676
685
  };
677
- /** Number of pending displayable messages (includes steering, follow-up, and next-turn messages) */
686
+ /** Number of pending displayable messages (includes steering, follow-up, and next-turn messages).
687
+ * Reflects actual queued work (advisor cards included) — feeds hasPendingMessages()/RPC and the
688
+ * empty-submit abort gate. The user-restorable subset is surfaced by getQueuedMessages()/clearQueue(). */
678
689
  get queuedMessageCount(): number;
679
690
  getQueuedMessages(): {
680
691
  steering: readonly string[];
@@ -683,6 +694,7 @@ export declare class AgentSession {
683
694
  /**
684
695
  * Pop the last queued message (steering first, then follow-up).
685
696
  * Used by dequeue keybinding to restore messages to editor one at a time.
697
+ * Steps over agent-authored queued messages (advisor cards, hidden/internal steers).
686
698
  */
687
699
  popLastQueuedMessage(): RestoredQueuedMessage | undefined;
688
700
  get skillsSettings(): SkillsSettings | undefined;
@@ -1128,12 +1140,12 @@ export declare class AgentSession {
1128
1140
  */
1129
1141
  getLastVisibleHandoffText(): string | undefined;
1130
1142
  /**
1131
- * Format the entire session as plain text for clipboard export.
1132
- * Includes user messages, assistant text, thinking blocks, tool calls, and tool results.
1143
+ * Format the entire session as plain text for clipboard export: system
1144
+ * prompt, model/thinking config, tool inventory, and the full transcript
1145
+ * rendered with markdown role headings (`## User`, `## Assistant`,
1146
+ * `### Tool Call`/`### Tool Result`).
1133
1147
  */
1134
- formatSessionAsText(options?: {
1135
- compact?: boolean;
1136
- }): string;
1148
+ formatSessionAsText(): string;
1137
1149
  /**
1138
1150
  * Enable or disable the advisor for this session. The setting is overridden for the session,
1139
1151
  * and the runtime is started or stopped to match.
@@ -55,6 +55,9 @@ export declare function isSilentAbort(errorMessage: string | undefined): boolean
55
55
  export declare const USER_INTERRUPT_LABEL = "Interrupted by user";
56
56
  export declare function isUserInterruptAbort(errorMessage: string | undefined): boolean;
57
57
  export declare function shouldRenderAbortReason(errorMessage: string | undefined): boolean;
58
+ /** Sentinel `errorMessage` the agent stamps on any abort that carried no custom
59
+ * reason (bare `abort()`). Renderers treat it as "no specific reason given". */
60
+ export declare const GENERIC_ABORT_SENTINEL = "Request was aborted";
58
61
  /** Resolve the operator-facing label for an aborted assistant turn. A custom
59
62
  * abort reason threaded onto `errorMessage` is returned verbatim; aborts with
60
63
  * no threaded reason fall back to the retry-aware generic label. Call
@@ -1,5 +1,10 @@
1
1
  /**
2
- * Plain-text / markdown session formatting (same shape as /dump clipboard export).
2
+ * Plain-text / markdown session formatting for `/dump` and `/advisor dump raw`.
3
+ *
4
+ * Renders a prelude (system prompt, model/thinking config, tool inventory)
5
+ * followed by the message history as per-message markdown headings: `## User`,
6
+ * `## Assistant` (with `<thinking>` blocks and `### Tool Call: <name>` + YAML
7
+ * args), `### Tool Result: <name>`, and the execution/summary sections.
3
8
  */
4
9
  import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
5
10
  import type { Model, ToolExample } from "@oh-my-pi/pi-ai";
@@ -18,6 +23,7 @@ export interface FormatSessionDumpTextOptions {
18
23
  tools?: readonly SessionDumpToolInfo[];
19
24
  }
20
25
  /**
21
- * Format messages and session metadata as markdown/plain text (same as AgentSession.formatSessionAsText / /dump).
26
+ * Format messages and session metadata as markdown/plain text (same as
27
+ * AgentSession.formatSessionAsText / /dump).
22
28
  */
23
29
  export declare function formatSessionDumpText(options: FormatSessionDumpTextOptions): string;
@@ -108,6 +108,10 @@ export interface SessionInitEntry extends SessionEntryBase {
108
108
  tools: string[];
109
109
  /** Output schema if structured output was requested */
110
110
  outputSchema?: unknown;
111
+ /** Spawn allowlist the subagent ran with ("" = none, "*" = any, else CSV); absent on pre-spawns files. */
112
+ spawns?: string;
113
+ /** The agent's `readSummarize` setting (`false` = read summarization disabled); absent uses the session default. */
114
+ readSummarize?: boolean;
111
115
  }
112
116
  /** Mode change entry - tracks agent mode transitions (e.g. plan mode). */
113
117
  export interface ModeChangeEntry extends SessionEntryBase {
@@ -5,6 +5,8 @@ export interface HistoryFormatOptions {
5
5
  includeThinking?: boolean;
6
6
  /** Render tool intent comment before tool call lines. */
7
7
  includeToolIntent?: boolean;
8
+ /** Render watched-session roles as inline `**agent**:` / `**user**:` labels (collapsing consecutive same-role messages) instead of `## ` headings, so a primary transcript embedded inside an advisor turn stays visually distinct. */
9
+ watchedRoles?: boolean;
8
10
  }
9
11
  /**
10
12
  * Format a session's message array as a concise markdown transcript.
@@ -152,6 +152,8 @@ export declare class SessionManager {
152
152
  task: string;
153
153
  tools: string[];
154
154
  outputSchema?: unknown;
155
+ spawns?: string;
156
+ readSummarize?: boolean;
155
157
  }): string;
156
158
  appendCompaction<T = unknown>(summary: string, shortSummary: string | undefined, firstKeptEntryId: string, tokensBefore: number, details?: T, fromExtension?: boolean, preserveData?: Record<string, unknown>): string;
157
159
  appendCustomEntry(customType: string, data?: unknown): string;
@@ -254,7 +256,27 @@ export declare class SessionManager {
254
256
  */
255
257
  static open(filePath: string, sessionDir?: string, storage?: SessionStorage, options?: {
256
258
  initialCwd?: string;
259
+ suppressBreadcrumb?: boolean;
257
260
  }): Promise<SessionManager>;
261
+ /**
262
+ * Lock-free peek for cold subagent revival: returns the recorded working
263
+ * directory (session header) and the latest `session_init` contract (system
264
+ * prompt / tools / output schema) WITHOUT taking the single-writer lock that
265
+ * {@link open} acquires — the caller re-opens for the actual revive. Returns
266
+ * null when the file can't be read; `init` is null for files written before
267
+ * `session_init` was recorded (no faithful contract to rebuild from).
268
+ */
269
+ static peekSessionInit(filePath: string, storage?: SessionStorage): Promise<{
270
+ cwd: string;
271
+ init: {
272
+ systemPrompt: string;
273
+ task: string;
274
+ tools: string[];
275
+ outputSchema?: unknown;
276
+ spawns?: string;
277
+ readSummarize?: boolean;
278
+ } | null;
279
+ } | null>;
258
280
  /** Continue the most recent session, or create a new one if none exists. */
259
281
  static continueRecent(cwd: string, sessionDir?: string, storage?: SessionStorage): Promise<SessionManager>;
260
282
  /** Create an in-memory session (no file persistence). */
@@ -27,12 +27,12 @@ export interface SttDownloadProgress {
27
27
  label: string;
28
28
  }
29
29
  /**
30
- * Whether the selected model is already present in the local cache. For
30
+ * Whether the selected model is fully present in the local cache. For
31
31
  * transformers.js Whisper tiers a complete download leaves `config.json` plus
32
- * the `onnx/` weight files (a bare `config.json` from an interrupted fetch reads
33
- * as not-cached); for sherpa-onnx tiers every model file (encoder/decoder/joiner
34
- * + tokens) must be present (`.part` sidecars from an interrupted fetch are
35
- * ignored).
32
+ * matching `encoder*.onnx` and `decoder*.onnx` shards under `onnx/` (a partial
33
+ * fetch with only one shard, or a bare `config.json`, reads as not-cached); for
34
+ * sherpa-onnx tiers every model file (encoder/decoder/joiner + tokens) must be
35
+ * present (`.part` sidecars from an interrupted fetch are ignored).
36
36
  */
37
37
  export declare function isSttModelCached(key: string): Promise<boolean>;
38
38
  /**
@@ -132,6 +132,12 @@ export interface ExecutorOptions {
132
132
  parentTelemetry?: AgentTelemetryConfig;
133
133
  /** Skills to autoload via sendCustomMessage before the first prompt */
134
134
  autoloadSkills?: Skill[];
135
+ /**
136
+ * Registry id of the spawning agent, recorded as this subagent's parent.
137
+ * Forwarded verbatim to the SDK; the executor never derives it (the spawner
138
+ * passes its own `getAgentId()`).
139
+ */
140
+ parentAgentId?: string;
135
141
  }
136
142
  export interface YieldItem {
137
143
  data?: unknown;
@@ -0,0 +1,36 @@
1
+ import type { ModelRegistry } from "../config/model-registry";
2
+ import type { Settings } from "../config/settings";
3
+ import type { PersistedSubagentReviverFactory } from "../registry/agent-lifecycle";
4
+ import type { AgentSession } from "../session/agent-session";
5
+ import type { AuthStorage } from "../session/auth-storage";
6
+ /**
7
+ * Ambient context the reviver needs at revive time. The top-level session is
8
+ * kept LIVE (cwd / artifact manager read on demand) so a later `/new` or cwd
9
+ * move is followed rather than snapshotted; auth/models/settings are
10
+ * process-stable and captured by reference.
11
+ */
12
+ export interface PersistedSubagentReviveContext {
13
+ session: AgentSession;
14
+ authStorage: AuthStorage;
15
+ modelRegistry: ModelRegistry;
16
+ settings: Settings;
17
+ /** LSP policy of the top-level session; revived subagents inherit it rather than defaulting on. */
18
+ enableLsp: boolean;
19
+ }
20
+ /**
21
+ * Build the factory the {@link AgentLifecycleManager} uses to cold-revive a
22
+ * `parked` subagent ref restored from disk (Agent Hub scan, collab mirror, or a
23
+ * resumed process). Such a ref carries a sessionFile but no in-memory adoption —
24
+ * the executor's live reviver closure died with the process/turn that spawned
25
+ * it — so `ensureLive` (IRC sends, hub focus) would otherwise refuse it.
26
+ *
27
+ * This rebuilds the subagent the same way `--resume` rebuilds a session: reopen
28
+ * the JSONL and replay it through {@link createAgentSession}. The catch is that
29
+ * resume restores only conversation/model from the file — the runtime contract
30
+ * (tools / system prompt / output schema / kind) is built from options, so a
31
+ * bare reopen would resurrect a wrong (top-level) session. We source that
32
+ * contract from the persisted `session_init` entry instead, and mirror the
33
+ * executor's subagent wiring (MCP proxy tools, depth-derived gating,
34
+ * yield-required, active-tool clamp, registry status sync).
35
+ */
36
+ export declare function createPersistedSubagentReviverFactory(ctx: PersistedSubagentReviveContext): PersistedSubagentReviverFactory;
@@ -9,6 +9,8 @@ export interface TinyTitleLocalModelSpec {
9
9
  label: string;
10
10
  description: string;
11
11
  contextNote: string;
12
+ /** Model family emits hidden reasoning unless the chat template disables it. */
13
+ reasoning?: boolean;
12
14
  }
13
15
  export declare const TINY_TITLE_LOCAL_MODELS: readonly [{
14
16
  readonly key: "lfm2-350m";
@@ -24,6 +26,7 @@ export declare const TINY_TITLE_LOCAL_MODELS: readonly [{
24
26
  readonly label: "Qwen3 0.6B";
25
27
  readonly description: "Most robust local option; slower first load, about 500 MB cached.";
26
28
  readonly contextNote: "Use when title quality matters more than local startup cost.";
29
+ readonly reasoning: true;
27
30
  }, {
28
31
  readonly key: "gemma-270m";
29
32
  readonly repo: "onnx-community/gemma-3-270m-it-ONNX";
@@ -77,6 +80,7 @@ export declare const TINY_MEMORY_LOCAL_MODELS: readonly [{
77
80
  readonly label: "Qwen3 1.7B";
78
81
  readonly description: "Recommended; most disciplined extraction (ignores chit-chat), good consolidation, about 1.1 GB cached.";
79
82
  readonly contextNote: "Best single-model pick for memory from the local experiment.";
83
+ readonly reasoning: true;
80
84
  }, {
81
85
  readonly key: "gemma-3-1b";
82
86
  readonly repo: "onnx-community/gemma-3-1b-it-ONNX";
@@ -113,6 +117,8 @@ export declare const TINY_MEMORY_MODEL_OPTIONS: ({
113
117
  })[];
114
118
  export declare function isTinyMemoryLocalModelKey(value: string): value is TinyMemoryLocalModelKey;
115
119
  export declare function getTinyMemoryModelSpec(key: TinyMemoryLocalModelKey): (typeof TINY_MEMORY_LOCAL_MODELS)[number];
120
+ /** Return whether a memory local model may emit reasoning tokens before answers. */
121
+ export declare function isTinyMemoryReasoningModelKey(key: TinyMemoryLocalModelKey): boolean;
116
122
  /** Any local model key (title or memory), used by the shared inference worker. */
117
123
  export type TinyLocalModelKey = TinyTitleLocalModelKey | TinyMemoryLocalModelKey;
118
124
  /** Resolve a local model spec by key across both the title and memory registries. */
@@ -133,6 +139,7 @@ export declare const TINY_LOCAL_MODELS: readonly [{
133
139
  readonly label: "Qwen3 0.6B";
134
140
  readonly description: "Most robust local option; slower first load, about 500 MB cached.";
135
141
  readonly contextNote: "Use when title quality matters more than local startup cost.";
142
+ readonly reasoning: true;
136
143
  }, {
137
144
  readonly key: "gemma-270m";
138
145
  readonly repo: "onnx-community/gemma-3-270m-it-ONNX";
@@ -161,6 +168,7 @@ export declare const TINY_LOCAL_MODELS: readonly [{
161
168
  readonly label: "Qwen3 1.7B";
162
169
  readonly description: "Recommended; most disciplined extraction (ignores chit-chat), good consolidation, about 1.1 GB cached.";
163
170
  readonly contextNote: "Best single-model pick for memory from the local experiment.";
171
+ readonly reasoning: true;
164
172
  }, {
165
173
  readonly key: "gemma-3-1b";
166
174
  readonly repo: "onnx-community/gemma-3-1b-it-ONNX";
@@ -1,2 +1,2 @@
1
- export declare const BUILTIN_TOOL_NAMES: readonly ["read", "bash", "edit", "ast_grep", "ast_edit", "render_mermaid", "ask", "debug", "eval", "ssh", "github", "find", "search", "lsp", "inspect_image", "browser", "checkpoint", "rewind", "task", "job", "irc", "todo", "web_search", "search_tool_bm25", "write", "memory_edit", "retain", "recall", "reflect", "learn", "manage_skill"];
1
+ export declare const BUILTIN_TOOL_NAMES: readonly ["read", "bash", "edit", "ast_grep", "ast_edit", "ask", "debug", "eval", "ssh", "github", "find", "search", "lsp", "inspect_image", "browser", "checkpoint", "rewind", "task", "job", "irc", "todo", "web_search", "search_tool_bm25", "write", "memory_edit", "retain", "recall", "reflect", "learn", "manage_skill"];
2
2
  export type BuiltinToolName = (typeof BUILTIN_TOOL_NAMES)[number];
@@ -54,7 +54,6 @@ export * from "./memory-recall";
54
54
  export * from "./memory-reflect";
55
55
  export * from "./memory-retain";
56
56
  export * from "./read";
57
- export * from "./render-mermaid";
58
57
  export * from "./report-tool-issue";
59
58
  export * from "./resolve";
60
59
  export * from "./review";
@@ -3,5 +3,13 @@ export interface MarkitConversionResult {
3
3
  ok: boolean;
4
4
  error?: string;
5
5
  }
6
+ interface MuPdfWasmModuleConfig {
7
+ print?: (...values: unknown[]) => void;
8
+ printErr?: (...values: unknown[]) => void;
9
+ }
10
+ declare global {
11
+ var $libmupdf_wasm_Module: MuPdfWasmModuleConfig | undefined;
12
+ }
6
13
  export declare function convertFileWithMarkit(filePath: string, signal?: AbortSignal): Promise<MarkitConversionResult>;
7
14
  export declare function convertBufferWithMarkit(buffer: Uint8Array, extension: string, signal?: AbortSignal): Promise<MarkitConversionResult>;
15
+ export {};