@oh-my-pi/pi-coding-agent 16.2.2 → 16.2.4

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 (164) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/cli.js +3682 -3615
  3. package/dist/types/advisor/__tests__/config.test.d.ts +1 -0
  4. package/dist/types/advisor/advise-tool.d.ts +8 -4
  5. package/dist/types/advisor/config.d.ts +88 -0
  6. package/dist/types/advisor/index.d.ts +1 -0
  7. package/dist/types/advisor/transcript-recorder.d.ts +13 -2
  8. package/dist/types/advisor/watchdog.d.ts +20 -0
  9. package/dist/types/cli/update-cli.d.ts +15 -0
  10. package/dist/types/collab/guest.d.ts +29 -0
  11. package/dist/types/collab/replication-shrink.d.ts +39 -0
  12. package/dist/types/config/provider-globals.d.ts +7 -0
  13. package/dist/types/config/settings-schema.d.ts +81 -0
  14. package/dist/types/debug/log-viewer.d.ts +1 -0
  15. package/dist/types/debug/raw-sse.d.ts +1 -0
  16. package/dist/types/edit/hashline/diff.d.ts +0 -11
  17. package/dist/types/extensibility/tool-event-input.d.ts +7 -0
  18. package/dist/types/extensibility/utils.d.ts +12 -0
  19. package/dist/types/mcp/transports/index.d.ts +1 -0
  20. package/dist/types/mcp/transports/sse.d.ts +20 -0
  21. package/dist/types/memories/index.d.ts +20 -1
  22. package/dist/types/modes/components/advisor-config.d.ts +59 -0
  23. package/dist/types/modes/components/index.d.ts +1 -0
  24. package/dist/types/modes/components/model-selector.d.ts +9 -1
  25. package/dist/types/modes/components/settings-selector.d.ts +1 -0
  26. package/dist/types/modes/components/status-line/component.d.ts +35 -1
  27. package/dist/types/modes/components/status-line/types.d.ts +13 -1
  28. package/dist/types/modes/controllers/command-controller.d.ts +3 -3
  29. package/dist/types/modes/controllers/selector-controller.d.ts +1 -0
  30. package/dist/types/modes/interactive-mode.d.ts +11 -4
  31. package/dist/types/modes/skill-command.d.ts +32 -0
  32. package/dist/types/modes/types.d.ts +9 -3
  33. package/dist/types/session/agent-session.d.ts +58 -10
  34. package/dist/types/session/indexed-session-storage.d.ts +7 -1
  35. package/dist/types/session/messages.d.ts +26 -0
  36. package/dist/types/session/messages.test.d.ts +1 -0
  37. package/dist/types/session/session-entries.d.ts +31 -3
  38. package/dist/types/session/session-history-format.d.ts +6 -0
  39. package/dist/types/session/session-loader.d.ts +9 -1
  40. package/dist/types/session/session-manager.d.ts +8 -7
  41. package/dist/types/session/session-storage.d.ts +11 -0
  42. package/dist/types/session/session-title-slot.d.ts +19 -0
  43. package/dist/types/ssh/connection-manager.d.ts +47 -0
  44. package/dist/types/ssh/utils.d.ts +16 -0
  45. package/dist/types/task/executor.d.ts +3 -16
  46. package/dist/types/task/render.d.ts +0 -5
  47. package/dist/types/task/renderer.d.ts +13 -0
  48. package/dist/types/task/types.d.ts +16 -0
  49. package/dist/types/task/yield-assembly.d.ts +28 -0
  50. package/dist/types/tiny/text.d.ts +8 -0
  51. package/dist/types/tools/render-utils.d.ts +2 -0
  52. package/dist/types/tools/review.d.ts +6 -4
  53. package/dist/types/tools/ssh.d.ts +1 -1
  54. package/dist/types/tools/todo.d.ts +6 -0
  55. package/dist/types/tools/yield.d.ts +8 -3
  56. package/dist/types/utils/thinking-display.d.ts +4 -0
  57. package/package.json +12 -12
  58. package/src/advisor/__tests__/advisor.test.ts +242 -10
  59. package/src/advisor/__tests__/config.test.ts +173 -0
  60. package/src/advisor/advise-tool.ts +11 -6
  61. package/src/advisor/config.ts +256 -0
  62. package/src/advisor/index.ts +1 -0
  63. package/src/advisor/runtime.ts +12 -2
  64. package/src/advisor/transcript-recorder.ts +25 -2
  65. package/src/advisor/watchdog.ts +57 -31
  66. package/src/autolearn/controller.ts +13 -22
  67. package/src/autoresearch/index.ts +7 -2
  68. package/src/cli/gc-cli.ts +17 -10
  69. package/src/cli/update-cli.ts +254 -0
  70. package/src/collab/guest.ts +43 -7
  71. package/src/collab/host.ts +13 -8
  72. package/src/collab/replication-shrink.ts +111 -0
  73. package/src/config/model-registry.ts +80 -18
  74. package/src/config/provider-globals.ts +25 -0
  75. package/src/config/settings-schema.ts +77 -0
  76. package/src/debug/index.ts +32 -7
  77. package/src/debug/log-viewer.ts +111 -53
  78. package/src/debug/raw-sse.ts +68 -48
  79. package/src/discovery/codex.ts +13 -5
  80. package/src/edit/hashline/diff.ts +57 -4
  81. package/src/eval/__tests__/julia-prelude.test.ts +2 -2
  82. package/src/eval/js/shared/local-module-loader.ts +23 -1
  83. package/src/export/html/template.js +13 -7
  84. package/src/extensibility/extensions/loader.ts +5 -3
  85. package/src/extensibility/extensions/wrapper.ts +9 -3
  86. package/src/extensibility/hooks/loader.ts +3 -3
  87. package/src/extensibility/hooks/tool-wrapper.ts +13 -4
  88. package/src/extensibility/plugins/manager.ts +2 -1
  89. package/src/extensibility/tool-event-input.ts +23 -0
  90. package/src/extensibility/utils.ts +74 -0
  91. package/src/internal-urls/docs-index.generated.txt +1 -1
  92. package/src/mcp/client.ts +3 -1
  93. package/src/mcp/manager.ts +12 -5
  94. package/src/mcp/transports/index.ts +1 -0
  95. package/src/mcp/transports/sse.ts +377 -0
  96. package/src/memories/index.ts +130 -15
  97. package/src/memory-backend/local-backend.ts +5 -3
  98. package/src/modes/components/advisor-config.ts +555 -0
  99. package/src/modes/components/advisor-message.ts +9 -2
  100. package/src/modes/components/agent-hub.ts +9 -4
  101. package/src/modes/components/index.ts +2 -0
  102. package/src/modes/components/model-selector.ts +79 -48
  103. package/src/modes/components/settings-selector.ts +1 -0
  104. package/src/modes/components/status-line/component.ts +150 -5
  105. package/src/modes/components/status-line/segments.ts +46 -21
  106. package/src/modes/components/status-line/types.ts +13 -1
  107. package/src/modes/components/tool-execution.ts +47 -6
  108. package/src/modes/controllers/command-controller.ts +27 -36
  109. package/src/modes/controllers/event-controller.ts +113 -1
  110. package/src/modes/controllers/extension-ui-controller.ts +1 -1
  111. package/src/modes/controllers/input-controller.ts +61 -61
  112. package/src/modes/controllers/selector-controller.ts +100 -9
  113. package/src/modes/interactive-mode.ts +74 -25
  114. package/src/modes/skill-command.ts +116 -0
  115. package/src/modes/types.ts +9 -3
  116. package/src/modes/utils/ui-helpers.ts +41 -23
  117. package/src/prompts/agents/reviewer.md +11 -10
  118. package/src/prompts/goals/goal-todo-context.md +12 -0
  119. package/src/prompts/review-custom-request.md +1 -2
  120. package/src/prompts/review-request.md +1 -2
  121. package/src/prompts/system/interrupted-thinking.md +7 -0
  122. package/src/prompts/system/recap-user.md +9 -0
  123. package/src/prompts/system/subagent-system-prompt.md +8 -5
  124. package/src/prompts/system/subagent-yield-reminder.md +6 -5
  125. package/src/prompts/system/system-prompt.md +0 -1
  126. package/src/prompts/tools/irc.md +2 -2
  127. package/src/prompts/tools/read.md +2 -2
  128. package/src/sdk.ts +28 -24
  129. package/src/session/agent-session.ts +899 -429
  130. package/src/session/indexed-session-storage.ts +86 -13
  131. package/src/session/messages.test.ts +125 -0
  132. package/src/session/messages.ts +172 -9
  133. package/src/session/redis-session-storage.ts +49 -2
  134. package/src/session/session-entries.ts +39 -2
  135. package/src/session/session-history-format.ts +29 -2
  136. package/src/session/session-listing.ts +54 -24
  137. package/src/session/session-loader.ts +66 -3
  138. package/src/session/session-manager.ts +115 -22
  139. package/src/session/session-persistence.ts +95 -1
  140. package/src/session/session-storage.ts +36 -0
  141. package/src/session/session-title-slot.ts +141 -0
  142. package/src/session/sql-session-storage.ts +71 -11
  143. package/src/slash-commands/builtin-registry.ts +23 -24
  144. package/src/ssh/__tests__/connection-manager-args.test.ts +123 -1
  145. package/src/ssh/__tests__/file-transfer-posix-guard.test.ts +55 -18
  146. package/src/ssh/connection-manager.ts +139 -12
  147. package/src/ssh/file-transfer.ts +23 -18
  148. package/src/ssh/ssh-executor.ts +2 -13
  149. package/src/ssh/utils.ts +19 -0
  150. package/src/task/executor.ts +21 -23
  151. package/src/task/render.ts +162 -20
  152. package/src/task/renderer.ts +14 -0
  153. package/src/task/types.ts +17 -0
  154. package/src/task/yield-assembly.ts +207 -0
  155. package/src/tiny/text.ts +23 -0
  156. package/src/tools/ask.ts +55 -4
  157. package/src/tools/render-utils.ts +2 -0
  158. package/src/tools/renderers.ts +8 -2
  159. package/src/tools/review.ts +17 -7
  160. package/src/tools/ssh.ts +8 -4
  161. package/src/tools/todo.ts +17 -1
  162. package/src/tools/yield.ts +140 -31
  163. package/src/utils/thinking-display.ts +15 -0
  164. package/src/prompts/system/autolearn-nudge.md +0 -5
@@ -0,0 +1 @@
1
+ export {};
@@ -8,11 +8,15 @@ export type AdvisorSeverity = "nit" | "concern" | "blocker";
8
8
  export interface AdviseDetails {
9
9
  note: string;
10
10
  severity?: AdvisorSeverity;
11
+ /** Which configured advisor produced this note (omitted for the default advisor). */
12
+ advisor?: string;
11
13
  }
12
14
  /** One queued advice note. */
13
15
  export interface AdvisorNote {
14
16
  note: string;
15
17
  severity?: AdvisorSeverity;
18
+ /** Which configured advisor produced this note (omitted for the default advisor). */
19
+ advisor?: string;
16
20
  }
17
21
  /** Details payload on the batched `advisor` custom message rendered in the transcript. */
18
22
  export interface AdvisorMessageDetails {
@@ -78,11 +82,11 @@ export declare function resolveAdvisorDeliveryChannel(opts: {
78
82
  */
79
83
  export declare function deriveAdvisorTelemetry(primaryTelemetry: AgentTelemetryConfig | undefined, identity: AgentIdentity): AgentTelemetryConfig | undefined;
80
84
  /**
81
- * Side-effect-free investigation tools handed to the advisor agent so it can
82
- * inspect the workspace before weighing in. Names match the primary session's
83
- * tool instances, which the advisor reuses.
85
+ * The tools an advisor receives by default when its config omits `tools` — the
86
+ * read-only investigative set. The full available pool is every built tool the
87
+ * session has (the advisor is a full agent); a config's `tools` selects from it.
84
88
  */
85
- export declare const ADVISOR_READONLY_TOOL_NAMES: ReadonlySet<string>;
89
+ export declare const ADVISOR_DEFAULT_TOOL_NAMES: ReadonlySet<string>;
86
90
  export declare class AdviseTool implements AgentTool<typeof adviseSchema, AdviseDetails> {
87
91
  #private;
88
92
  private readonly onAdvice;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * One advisor declared in a `WATCHDOG.yml` file. `model` is a model selector
3
+ * with an optional `:level` thinking suffix (e.g. `x-ai/grok-code-fast:high`),
4
+ * resolved exactly like any other model override; `tools` is a subset of the
5
+ * read-only investigative tool names (default: all). `instructions` is the
6
+ * advisor's specialization, appended to the shared baseline.
7
+ */
8
+ export interface AdvisorConfig {
9
+ name: string;
10
+ model?: string;
11
+ tools?: string[];
12
+ instructions?: string;
13
+ }
14
+ /**
15
+ * The result of walking the `WATCHDOG.yml`/`WATCHDOG.yaml` search path: the
16
+ * deduped advisor roster plus the concatenated top-level `instructions` baseline
17
+ * that is prepended (alongside `WATCHDOG.md`) to every advisor.
18
+ */
19
+ export interface DiscoveredAdvisors {
20
+ advisors: AdvisorConfig[];
21
+ sharedInstructions: string | undefined;
22
+ }
23
+ /**
24
+ * Normalize an advisor name into a filesystem-/id-safe slug used for its
25
+ * transcript filename and session id: lowercase, non-alphanumerics collapsed to
26
+ * `-`, leading/trailing `-` trimmed. Falls back to `"advisor"` when nothing
27
+ * survives; callers dedupe collisions.
28
+ */
29
+ export declare function slugifyAdvisorName(name: string): string;
30
+ /**
31
+ * Discover advisor configs from `WATCHDOG.yml`/`WATCHDOG.yaml` files on the same
32
+ * user + project search path as `WATCHDOG.md`. Advisors are keyed by slug; a
33
+ * more-specific file (project leaf > project ancestor > user) replaces an earlier
34
+ * entry with the same slug. Top-level `instructions` across all files concatenate
35
+ * into the shared baseline. A malformed file is logged and skipped — never
36
+ * thrown — so a bad project config can't kill the session.
37
+ */
38
+ export declare function discoverAdvisorConfigs(cwd: string, agentDir?: string): Promise<DiscoveredAdvisors>;
39
+ /** Which level a `WATCHDOG.yml` lives at: the project root or the user agent dir. */
40
+ export type AdvisorConfigScope = "project" | "user";
41
+ /**
42
+ * The editable contents of a single `WATCHDOG.yml` file: the shared top-level
43
+ * `instructions` plus the advisor roster. Unlike {@link DiscoveredAdvisors}, this
44
+ * is one file's raw view (no cross-level merge, no `@import` expansion) so the
45
+ * config editor round-trips exactly what the user wrote.
46
+ */
47
+ export interface WatchdogConfigDoc {
48
+ instructions?: string;
49
+ advisors: AdvisorConfig[];
50
+ }
51
+ /**
52
+ * Resolve the `WATCHDOG.yml` path for a scope: `project` → `<projectDir>/WATCHDOG.yml`
53
+ * (discovered by the project-level walk), `user` → `<agentDir>/WATCHDOG.yml` (the
54
+ * user-level candidate).
55
+ */
56
+ export declare function advisorConfigFilePath(scope: AdvisorConfigScope, dirs: {
57
+ projectDir: string;
58
+ agentDir: string;
59
+ }): string;
60
+ /**
61
+ * Resolve which `WATCHDOG.{yml,yaml}` to edit for a scope: prefer the canonical
62
+ * `.yml`, but when only a `.yaml` exists for that scope, edit it in place so an
63
+ * existing `.yaml` user isn't shown a blank editor and left with two files at the
64
+ * same precedence. Falls back to `.yml` when neither exists.
65
+ */
66
+ export declare function resolveAdvisorConfigEditPath(scope: AdvisorConfigScope, dirs: {
67
+ projectDir: string;
68
+ agentDir: string;
69
+ }): Promise<string>;
70
+ /**
71
+ * Load one `WATCHDOG.yml` file for editing — raw, un-merged, un-expanded. Missing,
72
+ * unparseable, or schema-invalid files yield an empty doc (never throws) so the
73
+ * editor opens cleanly on a fresh or broken file.
74
+ */
75
+ export declare function loadWatchdogConfigFile(filePath: string): Promise<WatchdogConfigDoc>;
76
+ /**
77
+ * Serialize an editable doc back to block-style `WATCHDOG.yml` text via Bun's
78
+ * `YAML.stringify` (the same API the repo uses for other hand-editable config),
79
+ * omitting empty fields. Round-trips through {@link loadWatchdogConfigFile}.
80
+ * Returns `""` for an empty doc.
81
+ */
82
+ export declare function serializeWatchdogConfig(doc: WatchdogConfigDoc): string;
83
+ /**
84
+ * Write an editable doc to `WATCHDOG.yml`. An empty doc removes the file so
85
+ * discovery falls back to the legacy single-advisor path rather than leaving an
86
+ * empty config behind.
87
+ */
88
+ export declare function saveWatchdogConfigFile(filePath: string, doc: WatchdogConfigDoc): Promise<void>;
@@ -1,4 +1,5 @@
1
1
  export * from "./advise-tool";
2
+ export * from "./config";
2
3
  export * from "./emission-guard";
3
4
  export * from "./runtime";
4
5
  export * from "./transcript-recorder";
@@ -6,6 +6,14 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
6
6
  */
7
7
  export declare const ADVISOR_TRANSCRIPT_STEM = "__advisor";
8
8
  export declare const ADVISOR_TRANSCRIPT_FILENAME = "__advisor.jsonl";
9
+ /**
10
+ * Transcript filename for an advisor: `__advisor.jsonl` for the legacy/default
11
+ * advisor (empty slug), `__advisor.<slug>.jsonl` for a named advisor. The `.`
12
+ * separator keeps named files out of the output manager's `-<n>` bump namespace.
13
+ */
14
+ export declare function advisorTranscriptFilename(slug: string): string;
15
+ /** Whether a filename is any advisor transcript (`__advisor.jsonl` or `__advisor.<slug>.jsonl`). */
16
+ export declare function isAdvisorTranscriptName(name: string): boolean;
9
17
  /**
10
18
  * Append-only persister for an advisor agent's transcript.
11
19
  *
@@ -32,11 +40,14 @@ export declare class AdvisorTranscriptRecorder {
32
40
  private readonly resolveSessionFile;
33
41
  private readonly resolveCwd;
34
42
  /**
43
+ * @param filename Transcript filename within the session dir. Defaults to
44
+ * `__advisor.jsonl`; named advisors pass `__advisor.<slug>.jsonl` via
45
+ * {@link advisorTranscriptFilename}.
35
46
  * @param after Optional barrier the queue starts behind — used on the advisor
36
47
  * on→off→on toggle so a fresh recorder's first `open` waits for the prior
37
- * recorder's `close` and the two never hold the same `__advisor.jsonl` at once.
48
+ * recorder's `close` and the two never hold the same file at once.
38
49
  */
39
- constructor(resolveSessionFile: () => string | undefined, resolveCwd: () => string, after?: Promise<unknown>);
50
+ constructor(resolveSessionFile: () => string | undefined, resolveCwd: () => string, filename?: string, after?: Promise<unknown>);
40
51
  /**
41
52
  * Persist one finalized advisor message. Assistant turns carry the usage the
42
53
  * stats parser reads; tool results round out the Hub transcript; user deltas
@@ -11,6 +11,26 @@ export declare function formatAdvisorContextPrompt(contextFiles: ReadonlyArray<{
11
11
  path: string;
12
12
  content: string;
13
13
  }>): string | undefined;
14
+ /**
15
+ * A readable config candidate discovered on the watchdog/advisor search path,
16
+ * with raw (un-expanded) content and its position metadata.
17
+ */
18
+ export interface ConfigCandidate {
19
+ path: string;
20
+ content: string;
21
+ level: "user" | "project";
22
+ depth: number;
23
+ }
24
+ /**
25
+ * Walk the watchdog/advisor config search path — the user agent dir plus every
26
+ * directory from `cwd` up to the repo root (or home), probing both `<F>` and
27
+ * `.omp/<F>` for each given filename — and return the readable candidates with
28
+ * their raw content, sorted user-first then project ancestor→leaf (depth
29
+ * descending, so the leaf directory is most specific/last). Shared by
30
+ * {@link discoverWatchdogFiles} and `discoverAdvisorConfigs`. Content is returned
31
+ * verbatim (no `@import` expansion); callers expand what they need.
32
+ */
33
+ export declare function collectConfigCandidates(cwd: string, agentDir: string | undefined, filenames: string[]): Promise<ConfigCandidate[]>;
14
34
  /**
15
35
  * Discover and load WATCHDOG.md files walking up from cwd, project .omp folder, and user agent dir.
16
36
  * Returns formatted watchdog file blocks ready to be appended to the advisor system prompt.
@@ -27,6 +27,21 @@ interface UpdateMethodResolutionOptions {
27
27
  miseDataDir?: string;
28
28
  }
29
29
  export declare function resolveUpdateMethodForTest(ompPath: string, bunBinDir: string | undefined, options?: UpdateMethodResolutionOptions): UpdateMethod;
30
+ interface BunInstallCachePruneResult {
31
+ scannedPackages: number;
32
+ removedEntries: number;
33
+ }
34
+ /**
35
+ * Prune Bun's package cache so each package keeps only its newest cached version.
36
+ *
37
+ * Bun stores package cache entries as both a package marker directory
38
+ * (`react/19.2.6@@@1`) and a materialized package directory
39
+ * (`react@19.2.6@@@1`). Global `omp` updates can leave one full copy per
40
+ * release. The marker and materialized entries are removed together so the
41
+ * cache stays internally consistent.
42
+ */
43
+ export declare function pruneBunInstallCache(cacheDir: string, packageNames?: Set<string>): Promise<BunInstallCachePruneResult>;
44
+ export declare function resolveBunGlobalNodeModulesDirFromLocations(globalBinDir: string | undefined, cacheDir: string | undefined): string | undefined;
30
45
  /**
31
46
  * Best-effort removal of binary-update backups left by earlier runs.
32
47
  *
@@ -5,6 +5,35 @@ import { AgentRegistry } from "../registry/agent-registry";
5
5
  import { type CollabSessionState } from "./protocol";
6
6
  /** Commands a guest may run locally; everything else is host-only. */
7
7
  export declare const COLLAB_GUEST_ALLOWED_COMMANDS: Record<string, true>;
8
+ /** Minimal context surface the idle-state reconciler mutates. */
9
+ export interface GuestIdleReconcilerCtx {
10
+ statusLine: {
11
+ markActivityEnd: () => void;
12
+ };
13
+ loadingAnimation: {
14
+ stop: () => void;
15
+ } | undefined;
16
+ }
17
+ /**
18
+ * Close the guest UI state held open by an earlier `agent_start` whose
19
+ * matching `agent_end` never reached us — most often because a reconnect
20
+ * dropped the event mid-stream. Triggered from {@link CollabGuestLink}'s
21
+ * `state` reconciler when the host reports `isStreaming === false`:
22
+ * folds the in-flight active-time window into the per-session meter (so
23
+ * `time_spent` stops ticking) and stops the `Working…` loader if one is
24
+ * still animating. No-op when the host is still streaming.
25
+ *
26
+ * Exported for direct unit testing; mutates the loader field on `ctx` so
27
+ * the same loader is not stopped twice on subsequent reconciliations.
28
+ */
29
+ export declare function reconcileGuestIdleHostState(ctx: GuestIdleReconcilerCtx, isStreaming: boolean): void;
30
+ /** Reconcile a welcome/resync snapshot's host activity state into the guest meter. */
31
+ export interface GuestSnapshotActivityReconcilerCtx extends GuestIdleReconcilerCtx {
32
+ statusLine: GuestIdleReconcilerCtx["statusLine"] & {
33
+ markActivityStart: () => void;
34
+ };
35
+ }
36
+ export declare function reconcileGuestSnapshotHostState(ctx: GuestSnapshotActivityReconcilerCtx, isStreaming: boolean): void;
8
37
  export declare class CollabGuestLink {
9
38
  #private;
10
39
  state: CollabSessionState | null;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Hard-cap helper for host→guest collab frames.
3
+ *
4
+ * The host wraps every {@link CollabFrame} in an AES-GCM envelope and ships it
5
+ * through the relay's WebSocket. WebSocket servers enforce a per-frame
6
+ * `maxPayloadLength` (Bun's default is 16 MB; many proxies cap lower). A
7
+ * single oversized payload — typically a `read`/`bash`/`search` tool result
8
+ * captured as one multi-megabyte string, or a tool result whose `content`
9
+ * array holds thousands of small blocks — would otherwise ship as its own
10
+ * oversized frame and trip that limit, killing the host's WebSocket with
11
+ * `1006 Received too big message`. `CollabSocket` treats 1006 as transient
12
+ * and reconnects, the next guest hello triggers the same oversized send, and
13
+ * the loop never breaks (issue #3739).
14
+ *
15
+ * This helper bounds any JSON-serializable payload below
16
+ * {@link MAX_REPLICATED_PAYLOAD_BYTES}. Already-small payloads pass through
17
+ * untouched; oversized ones are returned as a deep-cloned shadow where long
18
+ * strings are head-truncated AND long arrays are head-clipped, with
19
+ * `[…N chars elided for collab session]` / `[…N items elided for collab
20
+ * session]` markers. Both axes are needed: string truncation alone leaves
21
+ * the cap unenforced for a payload built of many short strings, where no
22
+ * field exceeds the per-string floor.
23
+ */
24
+ /**
25
+ * Per-payload ceiling for host→guest frames. Bun's default WebSocket
26
+ * `maxPayloadLength` is 16 MB; we leave a generous margin so the AES-GCM
27
+ * envelope (+ IV + tag), the 4-byte peer header, and the outer wire wrapper
28
+ * fit comfortably under that on every reasonable relay.
29
+ */
30
+ export declare const MAX_REPLICATED_PAYLOAD_BYTES: number;
31
+ /**
32
+ * Return `value` unchanged when its JSON serialization already fits
33
+ * {@link MAX_REPLICATED_PAYLOAD_BYTES}; otherwise return a deep-cloned
34
+ * shadow shrunk along both string and array axes until the payload fits.
35
+ * The function is generic over `T` because the wire shape is preserved:
36
+ * only string leaves and array tails change; discriminator fields, ids, and
37
+ * other small metadata pass through untouched.
38
+ */
39
+ export declare function shrinkForReplication<T>(value: T): T;
@@ -0,0 +1,7 @@
1
+ interface ProviderGlobalSettings {
2
+ get(path: "providers.webSearchExclude"): unknown;
3
+ get(path: "providers.webSearch"): unknown;
4
+ get(path: "providers.image"): unknown;
5
+ }
6
+ export declare function applyProviderGlobalsFromSettings(settings: ProviderGlobalSettings): void;
7
+ export {};
@@ -443,6 +443,16 @@ export declare const SETTINGS_SCHEMA: {
443
443
  readonly description: "Use the terminal's default background for the status line instead of the theme's `statusLineBg`. Powerline end caps are dropped because they need a contrasting fill to bridge into the surrounding terminal.";
444
444
  };
445
445
  };
446
+ readonly "statusLine.compactThinkingLevel": {
447
+ readonly type: "boolean";
448
+ readonly default: false;
449
+ readonly ui: {
450
+ readonly tab: "appearance";
451
+ readonly group: "Status Line";
452
+ readonly label: "Compact Thinking Level";
453
+ readonly description: "Show the thinking level as a single icon on the model name instead of a separate ` · <level>` suffix.";
454
+ };
455
+ };
446
456
  readonly "tools.artifactSpillThreshold": {
447
457
  readonly type: "number";
448
458
  readonly default: 50;
@@ -1667,6 +1677,42 @@ export declare const SETTINGS_SCHEMA: {
1667
1677
  readonly description: "Notify when the ask tool is waiting for input";
1668
1678
  };
1669
1679
  };
1680
+ readonly "recap.enabled": {
1681
+ readonly type: "boolean";
1682
+ readonly default: true;
1683
+ readonly ui: {
1684
+ readonly tab: "interaction";
1685
+ readonly group: "Notifications";
1686
+ readonly label: "Idle Recap";
1687
+ readonly description: "Generate a brief LLM recap of where things stand after the terminal has been idle";
1688
+ };
1689
+ };
1690
+ readonly "recap.idleSeconds": {
1691
+ readonly type: "number";
1692
+ readonly default: 240;
1693
+ readonly ui: {
1694
+ readonly tab: "interaction";
1695
+ readonly group: "Notifications";
1696
+ readonly label: "Idle Recap Delay";
1697
+ readonly description: "Seconds to wait while idle before showing the recap";
1698
+ readonly options: readonly [{
1699
+ readonly value: "60";
1700
+ readonly label: "1 minute";
1701
+ }, {
1702
+ readonly value: "120";
1703
+ readonly label: "2 minutes";
1704
+ }, {
1705
+ readonly value: "240";
1706
+ readonly label: "4 minutes";
1707
+ }, {
1708
+ readonly value: "300";
1709
+ readonly label: "5 minutes";
1710
+ }, {
1711
+ readonly value: "600";
1712
+ readonly label: "10 minutes";
1713
+ }];
1714
+ };
1715
+ };
1670
1716
  readonly "collab.relayUrl": {
1671
1717
  readonly type: "string";
1672
1718
  readonly default: "wss://my.omp.sh";
@@ -1955,6 +2001,16 @@ export declare const SETTINGS_SCHEMA: {
1955
2001
  readonly description: "Use remote compaction endpoints when available instead of local summarization";
1956
2002
  };
1957
2003
  };
2004
+ readonly "compaction.remoteStreamingV2Enabled": {
2005
+ readonly type: "boolean";
2006
+ readonly default: true;
2007
+ readonly ui: {
2008
+ readonly tab: "context";
2009
+ readonly group: "Compaction";
2010
+ readonly label: "Remote Compaction V2";
2011
+ readonly description: "Use Responses streaming compaction for compatible remote compaction models";
2012
+ };
2013
+ };
1958
2014
  readonly "compaction.reserveTokens": {
1959
2015
  readonly type: "number";
1960
2016
  readonly default: 16384;
@@ -1971,6 +2027,10 @@ export declare const SETTINGS_SCHEMA: {
1971
2027
  readonly type: "string";
1972
2028
  readonly default: undefined;
1973
2029
  };
2030
+ readonly "compaction.v2RetainedMessageBudget": {
2031
+ readonly type: "number";
2032
+ readonly default: 64000;
2033
+ };
1974
2034
  readonly "compaction.idleEnabled": {
1975
2035
  readonly type: "boolean";
1976
2036
  readonly default: false;
@@ -3907,6 +3967,16 @@ export declare const SETTINGS_SCHEMA: {
3907
3967
  readonly description: "Run modes where active goals may auto-continue between turns";
3908
3968
  };
3909
3969
  };
3970
+ readonly "title.refreshOnReplan": {
3971
+ readonly type: "boolean";
3972
+ readonly default: true;
3973
+ readonly ui: {
3974
+ readonly tab: "tasks";
3975
+ readonly group: "Modes";
3976
+ readonly label: "Refresh Title on Replan";
3977
+ readonly description: "Refresh generated session titles after todo init replans unless the title was set by the user";
3978
+ };
3979
+ };
3910
3980
  readonly "task.isolation.mode": {
3911
3981
  readonly type: "enum";
3912
3982
  readonly values: readonly ["none", "auto", "apfs", "btrfs", "zfs", "reflink", "overlayfs", "projfs", "block-clone", "rcopy"];
@@ -5272,12 +5342,21 @@ export interface CompactionSettings {
5272
5342
  autoContinue: boolean;
5273
5343
  remoteEnabled: boolean;
5274
5344
  remoteEndpoint: string | undefined;
5345
+ remoteStreamingV2Enabled: boolean;
5346
+ v2RetainedMessageBudget: number;
5275
5347
  idleEnabled: boolean;
5276
5348
  idleThresholdTokens: number;
5277
5349
  idleTimeoutSeconds: number;
5278
5350
  supersedeReads: boolean;
5279
5351
  dropUseless: boolean;
5280
5352
  }
5353
+ export interface RecapSettings {
5354
+ enabled: boolean;
5355
+ idleSeconds: number;
5356
+ }
5357
+ export interface TitleSettings {
5358
+ refreshOnReplan: boolean;
5359
+ }
5281
5360
  export interface ContextPromotionSettings {
5282
5361
  enabled: boolean;
5283
5362
  }
@@ -5408,6 +5487,8 @@ export interface GcSettings {
5408
5487
  /** Map group prefix -> typed settings interface */
5409
5488
  export interface GroupTypeMap {
5410
5489
  compaction: CompactionSettings;
5490
+ recap: RecapSettings;
5491
+ title: TitleSettings;
5411
5492
  contextPromotion: ContextPromotionSettings;
5412
5493
  retry: RetrySettings;
5413
5494
  memories: MemoriesSettings;
@@ -35,6 +35,7 @@ export declare class DebugLogViewerModel {
35
35
  setFilterQuery(query: string): void;
36
36
  toggleProcessFilter(): void;
37
37
  moveCursor(delta: number, extendSelection: boolean): void;
38
+ moveCursorToRow(rowIndex: number, extendSelection: boolean): boolean;
38
39
  getSelectedLogIndices(): number[];
39
40
  getSelectedCount(): number;
40
41
  isSelected(logIndex: number): boolean;
@@ -12,6 +12,7 @@ export interface RawSseViewerOptions {
12
12
  export declare class RawSseViewerComponent implements Component {
13
13
  #private;
14
14
  constructor(options: RawSseViewerOptions);
15
+ dispose(): void;
15
16
  handleInput(keyData: string): void;
16
17
  invalidate(): void;
17
18
  render(width: number): readonly string[];
@@ -1,14 +1,3 @@
1
- /**
2
- * Read-only hashline diff preview helpers used by the streaming edit
3
- * renderer. Reads the target file, parses + applies the section's edits in
4
- * memory (no FS write, no LSP writethrough), then hands the before/after
5
- * pair to {@link generateDiffString} so the renderer can show the diff
6
- * while the tool call is still streaming.
7
- *
8
- * Uses the same snapshot-tag semantics as the apply path: a live content-hash
9
- * match is accepted even when the tag was minted by a source that did not keep
10
- * history, and stale tags recover through the session snapshot store when possible.
11
- */
12
1
  import { type PatchSection, type SnapshotStore } from "@oh-my-pi/hashline";
13
2
  export interface HashlineDiffOptions {
14
3
  /**
@@ -1,2 +1,9 @@
1
+ interface ToolEventInputResolver {
2
+ name: string;
3
+ resolveEventInput?: (input: string) => string;
4
+ }
5
+ /** Resolves mode-specific textual tool input before extension/hook event normalization. */
6
+ export declare function resolveToolEventInput(tool: ToolEventInputResolver, input: Record<string, unknown>): Record<string, unknown>;
1
7
  /** Adds derived compatibility fields to tool event input without changing tool execution parameters. */
2
8
  export declare function normalizeToolEventInput(toolName: string, input: Record<string, unknown>): Record<string, unknown>;
9
+ export {};
@@ -10,3 +10,15 @@ export declare function resolvePath(filePath: string, cwd: string): string;
10
10
  * Create a no-op UI context for headless modes.
11
11
  */
12
12
  export declare function createNoOpUIContext(): HookUIContext;
13
+ /**
14
+ * Raised by {@link withExitGuard} when a guarded callback synchronously
15
+ * attempts to terminate the host process. Callers catch this like any other
16
+ * load-time failure so the extension/hook is skipped with a logged error
17
+ * instead of taking the CLI down with it.
18
+ */
19
+ export declare class ExtensionExitError extends Error {
20
+ readonly alias: string;
21
+ readonly code: number | string | undefined;
22
+ constructor(code: number | string | undefined, alias?: string);
23
+ }
24
+ export declare function withExitGuard<T>(fn: () => Promise<T>): Promise<T>;
@@ -2,4 +2,5 @@
2
2
  * MCP transport exports.
3
3
  */
4
4
  export * from "./http";
5
+ export * from "./sse";
5
6
  export * from "./stdio";
@@ -0,0 +1,20 @@
1
+ import type { MCPRequestOptions, MCPSseServerConfig, MCPTransport } from "../../mcp/types";
2
+ /** Legacy MCP HTTP+SSE transport from protocol revision 2024-11-05. */
3
+ export declare class LegacySseTransport implements MCPTransport {
4
+ #private;
5
+ onClose?: () => void;
6
+ onError?: (error: Error) => void;
7
+ onNotification?: (method: string, params: unknown) => void;
8
+ onRequest?: (method: string, params: unknown) => Promise<unknown>;
9
+ /** Called on 401/403 to attempt token refresh. Returns updated headers or null. */
10
+ onAuthError?: () => Promise<Record<string, string> | null>;
11
+ constructor(config: MCPSseServerConfig);
12
+ get connected(): boolean;
13
+ get url(): string;
14
+ connect(): Promise<void>;
15
+ request<T = unknown>(method: string, params?: Record<string, unknown>, options?: MCPRequestOptions): Promise<T>;
16
+ notify(method: string, params?: Record<string, unknown>): Promise<void>;
17
+ close(): Promise<void>;
18
+ }
19
+ /** Create and connect a legacy HTTP+SSE transport. */
20
+ export declare function createSseTransport(config: MCPSseServerConfig): Promise<LegacySseTransport>;
@@ -14,10 +14,28 @@ export declare function startMemoryStartupTask(options: {
14
14
  agentDir: string;
15
15
  taskDepth: number;
16
16
  }): void;
17
+ interface MemoryInstructionSession {
18
+ sessionManager: Pick<AgentSession["sessionManager"], "getSessionFile">;
19
+ }
20
+ /**
21
+ * Drop the per-session memory instruction snapshot after explicit memory state
22
+ * changes that must affect the active conversation immediately, such as
23
+ * `/memory clear`.
24
+ */
25
+ export declare function clearMemoryToolDeveloperInstructionsCache(session: MemoryInstructionSession | undefined): void;
26
+ /**
27
+ * Refresh the active session's consolidated-memory snapshot after startup maintenance.
28
+ *
29
+ * Startup may finish after the first prompt build and write `memory_summary.md`;
30
+ * the active session should see that summary. It must not reread `learned.md`,
31
+ * because a `learn` call racing with startup belongs to the next session's
32
+ * memory prompt, not the active prompt-cache prefix.
33
+ */
34
+ export declare function refreshMemoryToolDeveloperInstructionsCacheAfterStartup(session: MemoryInstructionSession, agentDir: string, settings: Settings): Promise<void>;
17
35
  /**
18
36
  * Build memory usage instructions for prompt injection.
19
37
  */
20
- export declare function buildMemoryToolDeveloperInstructions(agentDir: string, settings: Settings): Promise<string | undefined>;
38
+ export declare function buildMemoryToolDeveloperInstructions(agentDir: string, settings: Settings, session?: MemoryInstructionSession): Promise<string | undefined>;
21
39
  /**
22
40
  * Clear all persisted memory state and generated artifacts.
23
41
  */
@@ -33,3 +51,4 @@ export declare function getMemoryRoot(agentDir: string, cwd: string): string;
33
51
  * tool when `memory.backend` is `local`.
34
52
  */
35
53
  export declare function saveLearnedLesson(agentDir: string, cwd: string, input: MemoryBackendSaveInput): Promise<MemoryBackendSaveResult>;
54
+ export {};
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Fullscreen `/advisor configure` overlay: a mouse- and keyboard-driven editor
3
+ * for the `WATCHDOG.yml` advisor roster at project or user level.
4
+ *
5
+ * It paints the entire alternate screen from row 0 (so SGR mouse rows index
6
+ * directly into the rendered frame) using the shared {@link ./overlay-box} chrome.
7
+ * The list screen is a two-pane split (the `/extensions` idiom): a clickable
8
+ * advisor/action sidebar on the left, and a scrollable preview of the highlighted
9
+ * advisor's model / tools / instructions on the right, filling the free space.
10
+ *
11
+ * Each screen is backed by a proven primitive — {@link SelectList} (list / detail
12
+ * / tools / thinking), {@link Input} (name), {@link ModelSelectorComponent} (the
13
+ * same rich `/model` picker, in direct-select mode), and {@link HookEditorComponent}
14
+ * (multiline instructions; Ctrl+G opens `$EDITOR`). The overlay edits an in-memory
15
+ * {@link WatchdogConfigDoc} and only touches disk + the live advisors via the host
16
+ * `save` callback.
17
+ */
18
+ import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
19
+ import type { Model } from "@oh-my-pi/pi-ai";
20
+ import { type Component, type TUI } from "@oh-my-pi/pi-tui";
21
+ import { type AdvisorConfigScope, type WatchdogConfigDoc } from "../../advisor";
22
+ import type { ModelRegistry } from "../../config/model-registry";
23
+ import type { Settings } from "../../config/settings";
24
+ /** Host callbacks: all disk + live-runtime effects flow through these. */
25
+ export interface AdvisorConfigCallbacks {
26
+ /** Load a scope's `WATCHDOG.yml` into an editable doc (empty when absent). */
27
+ loadDoc: (scope: AdvisorConfigScope) => Promise<WatchdogConfigDoc>;
28
+ /** Persist the doc to the scope's file and rebuild the live advisors. */
29
+ save: (scope: AdvisorConfigScope, doc: WatchdogConfigDoc) => Promise<void>;
30
+ /** Tear down the overlay and restore the editor. */
31
+ close: () => void;
32
+ requestRender: () => void;
33
+ /** Surface a transient status/warning line to the user. */
34
+ notify: (message: string) => void;
35
+ }
36
+ export interface AdvisorConfigDeps {
37
+ modelRegistry: ModelRegistry;
38
+ settings: Settings;
39
+ scopedModels: ReadonlyArray<{
40
+ model: Model;
41
+ thinkingLevel?: ThinkingLevel;
42
+ }>;
43
+ availableToolNames: string[];
44
+ /** Formatted advisor-role model shown on the seeded default row (e.g. "anthropic/claude-..."). */
45
+ defaultModelLabel?: string;
46
+ }
47
+ /**
48
+ * Fullscreen advisor-configuration overlay. Implements {@link Component} directly
49
+ * (rather than extending Container) so it owns the whole frame and the mouse
50
+ * geometry needed to make every row clickable.
51
+ */
52
+ export declare class AdvisorConfigOverlayComponent implements Component {
53
+ #private;
54
+ constructor(tui: TUI, deps: AdvisorConfigDeps, scope: AdvisorConfigScope, doc: WatchdogConfigDoc, callbacks: AdvisorConfigCallbacks);
55
+ render(width: number): readonly string[];
56
+ handleInput(data: string): void;
57
+ /** Forward enhanced-paste transports into a multiline instructions editor. */
58
+ pasteText(text: string): void;
59
+ }
@@ -1,3 +1,4 @@
1
+ export * from "./advisor-config";
1
2
  export * from "./assistant-message";
2
3
  export * from "./bash-execution";
3
4
  export * from "./bordered-loader";
@@ -1,5 +1,5 @@
1
1
  import type { Model } from "@oh-my-pi/pi-ai";
2
- import { Container, Input, type TUI } from "@oh-my-pi/pi-tui";
2
+ import { Container, Input, type SgrMouseEvent, type TUI } from "@oh-my-pi/pi-tui";
3
3
  import type { ModelRegistry } from "../../config/model-registry";
4
4
  import type { Settings } from "../../config/settings";
5
5
  import { type ConfiguredThinkingLevel } from "../../thinking";
@@ -19,9 +19,17 @@ export declare class ModelSelectorComponent extends Container {
19
19
  #private;
20
20
  constructor(tui: TUI, _currentModel: Model | undefined, settings: Settings, modelRegistry: ModelRegistry, scopedModels: ReadonlyArray<ScopedModelItem>, onSelect: RoleSelectCallback, onCancel: () => void, options?: {
21
21
  temporaryOnly?: boolean;
22
+ directSelect?: boolean;
23
+ pickerHint?: string;
22
24
  initialSearchInput?: string;
23
25
  currentContextTokens?: number;
24
26
  });
27
+ /**
28
+ * Concatenate children like Container.render, recording where the model list
29
+ * lands so routed mouse events can be hit-tested against it.
30
+ */
31
+ render(width: number): readonly string[];
32
+ routeMouse(event: SgrMouseEvent, line: number, _col: number): void;
25
33
  handleInput(keyData: string): void;
26
34
  getSearchInput(): Input;
27
35
  }