@oh-my-pi/pi-coding-agent 15.7.2 → 15.7.5

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 (188) hide show
  1. package/CHANGELOG.md +114 -6
  2. package/dist/types/cli/args.d.ts +1 -1
  3. package/dist/types/cli/extension-flags.d.ts +36 -0
  4. package/dist/types/config/config-file.d.ts +4 -0
  5. package/dist/types/config/file-lock.d.ts +23 -0
  6. package/dist/types/config/keybindings.d.ts +2 -1
  7. package/dist/types/config/model-registry.d.ts +6 -0
  8. package/dist/types/config/settings-schema.d.ts +69 -65
  9. package/dist/types/edit/hashline/diff.d.ts +3 -3
  10. package/dist/types/eval/__tests__/agent-bridge.test.d.ts +1 -0
  11. package/dist/types/eval/__tests__/budget-bridge.test.d.ts +1 -0
  12. package/dist/types/eval/__tests__/idle-timeout.test.d.ts +1 -0
  13. package/dist/types/eval/agent-bridge.d.ts +25 -0
  14. package/dist/types/eval/backend.d.ts +17 -2
  15. package/dist/types/eval/budget-bridge.d.ts +29 -0
  16. package/dist/types/eval/idle-timeout.d.ts +28 -0
  17. package/dist/types/eval/js/executor.d.ts +8 -0
  18. package/dist/types/eval/js/tool-bridge.d.ts +2 -1
  19. package/dist/types/eval/py/executor.d.ts +13 -0
  20. package/dist/types/exec/bash-executor.d.ts +1 -0
  21. package/dist/types/extensibility/custom-tools/types.d.ts +2 -2
  22. package/dist/types/extensibility/extensions/runner.d.ts +7 -0
  23. package/dist/types/extensibility/plugins/git-url.d.ts +11 -1
  24. package/dist/types/extensibility/plugins/manager.d.ts +12 -1
  25. package/dist/types/extensibility/shared-events.d.ts +2 -2
  26. package/dist/types/internal-urls/local-protocol.d.ts +19 -9
  27. package/dist/types/internal-urls/types.d.ts +14 -0
  28. package/dist/types/lsp/client.d.ts +3 -0
  29. package/dist/types/mcp/manager.d.ts +14 -5
  30. package/dist/types/memory-backend/index.d.ts +1 -1
  31. package/dist/types/memory-backend/resolve.d.ts +1 -1
  32. package/dist/types/memory-backend/types.d.ts +3 -3
  33. package/dist/types/mnemopi/backend.d.ts +4 -0
  34. package/dist/types/mnemopi/config.d.ts +29 -0
  35. package/dist/types/mnemopi/state.d.ts +72 -0
  36. package/dist/types/modes/components/custom-editor.d.ts +2 -2
  37. package/dist/types/modes/components/omfg-panel.d.ts +19 -0
  38. package/dist/types/modes/controllers/command-controller.d.ts +6 -0
  39. package/dist/types/modes/controllers/input-controller.d.ts +1 -3
  40. package/dist/types/modes/controllers/omfg-controller.d.ts +10 -0
  41. package/dist/types/modes/controllers/omfg-rule.d.ts +26 -0
  42. package/dist/types/modes/gradient-highlight.d.ts +5 -1
  43. package/dist/types/modes/interactive-mode.d.ts +7 -3
  44. package/dist/types/modes/magic-keywords.d.ts +14 -0
  45. package/dist/types/modes/markdown-prose.d.ts +27 -0
  46. package/dist/types/modes/orchestrate.d.ts +7 -2
  47. package/dist/types/modes/shared.d.ts +1 -1
  48. package/dist/types/modes/turn-budget.d.ts +18 -0
  49. package/dist/types/modes/types.d.ts +7 -3
  50. package/dist/types/modes/ultrathink.d.ts +7 -2
  51. package/dist/types/modes/workflow.d.ts +15 -0
  52. package/dist/types/sdk.d.ts +13 -3
  53. package/dist/types/session/agent-session.d.ts +36 -17
  54. package/dist/types/session/session-manager.d.ts +18 -0
  55. package/dist/types/session/session-storage.d.ts +6 -0
  56. package/dist/types/session/shake-types.d.ts +24 -0
  57. package/dist/types/task/executor.d.ts +2 -2
  58. package/dist/types/task/repair-args.d.ts +52 -0
  59. package/dist/types/tiny/models.d.ts +1 -1
  60. package/dist/types/tiny/title-client.d.ts +28 -2
  61. package/dist/types/tiny/title-protocol.d.ts +8 -5
  62. package/dist/types/tools/find.d.ts +1 -1
  63. package/dist/types/tools/index.d.ts +19 -3
  64. package/dist/types/tools/memory-edit.d.ts +1 -1
  65. package/dist/types/tools/path-utils.d.ts +7 -0
  66. package/dist/types/tui/output-block.d.ts +7 -7
  67. package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
  68. package/package.json +10 -10
  69. package/scripts/build-binary.ts +0 -1
  70. package/src/autoresearch/tools/run-experiment.ts +45 -113
  71. package/src/cli/args.ts +39 -16
  72. package/src/cli/extension-flags.ts +48 -0
  73. package/src/cli/plugin-cli.ts +11 -2
  74. package/src/cli.ts +59 -0
  75. package/src/config/config-file.ts +98 -13
  76. package/src/config/file-lock.ts +60 -17
  77. package/src/config/keybindings.ts +78 -27
  78. package/src/config/model-registry.ts +7 -1
  79. package/src/config/settings-schema.ts +73 -67
  80. package/src/config/settings.ts +22 -0
  81. package/src/edit/hashline/diff.ts +81 -24
  82. package/src/edit/renderer.ts +16 -12
  83. package/src/eval/__tests__/agent-bridge.test.ts +433 -0
  84. package/src/eval/__tests__/budget-bridge.test.ts +69 -0
  85. package/src/eval/__tests__/idle-timeout.test.ts +66 -0
  86. package/src/eval/__tests__/shared-executors.test.ts +21 -0
  87. package/src/eval/agent-bridge.ts +295 -0
  88. package/src/eval/backend.ts +17 -2
  89. package/src/eval/budget-bridge.ts +48 -0
  90. package/src/eval/idle-timeout.ts +80 -0
  91. package/src/eval/js/executor.ts +35 -7
  92. package/src/eval/js/index.ts +2 -1
  93. package/src/eval/js/shared/prelude.txt +85 -1
  94. package/src/eval/js/tool-bridge.ts +9 -0
  95. package/src/eval/py/executor.ts +41 -14
  96. package/src/eval/py/index.ts +2 -1
  97. package/src/eval/py/prelude.py +132 -1
  98. package/src/exec/bash-executor.ts +2 -3
  99. package/src/extensibility/custom-tools/types.ts +2 -2
  100. package/src/extensibility/extensions/runner.ts +12 -2
  101. package/src/extensibility/plugins/git-url.ts +90 -4
  102. package/src/extensibility/plugins/manager.ts +103 -7
  103. package/src/extensibility/shared-events.ts +2 -2
  104. package/src/internal-urls/docs-index.generated.ts +88 -88
  105. package/src/internal-urls/local-protocol.ts +23 -11
  106. package/src/internal-urls/types.ts +15 -0
  107. package/src/lsp/client.ts +28 -5
  108. package/src/main.ts +44 -55
  109. package/src/mcp/manager.ts +87 -4
  110. package/src/memory-backend/index.ts +1 -1
  111. package/src/memory-backend/resolve.ts +3 -3
  112. package/src/memory-backend/types.ts +3 -3
  113. package/src/{mnemosyne → mnemopi}/backend.ts +70 -70
  114. package/src/{mnemosyne → mnemopi}/config.ts +36 -36
  115. package/src/{mnemosyne → mnemopi}/state.ts +67 -67
  116. package/src/modes/components/agent-dashboard.ts +6 -6
  117. package/src/modes/components/custom-editor.ts +4 -11
  118. package/src/modes/components/extensions/state-manager.ts +3 -4
  119. package/src/modes/components/footer.ts +8 -9
  120. package/src/modes/components/hook-selector.ts +86 -20
  121. package/src/modes/components/oauth-selector.ts +93 -21
  122. package/src/modes/components/omfg-panel.ts +141 -0
  123. package/src/modes/components/settings-defs.ts +2 -2
  124. package/src/modes/components/tips.txt +2 -1
  125. package/src/modes/components/tool-execution.ts +38 -19
  126. package/src/modes/components/tree-selector.ts +4 -3
  127. package/src/modes/components/user-message-selector.ts +94 -19
  128. package/src/modes/components/user-message.ts +8 -1
  129. package/src/modes/controllers/command-controller.ts +25 -0
  130. package/src/modes/controllers/event-controller.ts +68 -3
  131. package/src/modes/controllers/input-controller.ts +14 -11
  132. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  133. package/src/modes/controllers/omfg-controller.ts +283 -0
  134. package/src/modes/controllers/omfg-rule.ts +647 -0
  135. package/src/modes/controllers/selector-controller.ts +1 -0
  136. package/src/modes/gradient-highlight.ts +23 -6
  137. package/src/modes/interactive-mode.ts +41 -7
  138. package/src/modes/magic-keywords.ts +20 -0
  139. package/src/modes/markdown-prose.ts +247 -0
  140. package/src/modes/orchestrate.ts +17 -11
  141. package/src/modes/shared.ts +3 -11
  142. package/src/modes/turn-budget.ts +31 -0
  143. package/src/modes/types.ts +7 -1
  144. package/src/modes/ultrathink.ts +16 -10
  145. package/src/modes/utils/hotkeys-markdown.ts +1 -1
  146. package/src/modes/workflow.ts +42 -0
  147. package/src/prompts/system/omfg-user.md +51 -0
  148. package/src/prompts/system/project-prompt.md +3 -2
  149. package/src/prompts/system/subagent-system-prompt.md +12 -8
  150. package/src/prompts/system/system-prompt.md +9 -6
  151. package/src/prompts/system/workflow-notice.md +70 -0
  152. package/src/prompts/tools/eval.md +13 -1
  153. package/src/prompts/tools/memory-edit.md +1 -1
  154. package/src/sdk.ts +63 -33
  155. package/src/session/agent-session.ts +290 -55
  156. package/src/session/session-manager.ts +32 -0
  157. package/src/session/session-storage.ts +68 -8
  158. package/src/session/shake-types.ts +43 -0
  159. package/src/slash-commands/builtin-registry.ts +39 -16
  160. package/src/task/executor.ts +17 -7
  161. package/src/task/index.ts +9 -8
  162. package/src/task/repair-args.ts +117 -0
  163. package/src/tiny/models.ts +2 -2
  164. package/src/tiny/title-client.ts +133 -43
  165. package/src/tiny/title-protocol.ts +10 -5
  166. package/src/tiny/worker.ts +3 -46
  167. package/src/tools/ast-edit.ts +3 -0
  168. package/src/tools/ast-grep.ts +3 -0
  169. package/src/tools/eval.ts +202 -26
  170. package/src/tools/find.ts +20 -6
  171. package/src/tools/gh.ts +1 -0
  172. package/src/tools/grouped-file-output.ts +9 -2
  173. package/src/tools/index.ts +17 -5
  174. package/src/tools/memory-edit.ts +4 -4
  175. package/src/tools/memory-recall.ts +5 -5
  176. package/src/tools/memory-reflect.ts +5 -5
  177. package/src/tools/memory-retain.ts +4 -4
  178. package/src/tools/path-utils.ts +13 -2
  179. package/src/tools/read.ts +1 -0
  180. package/src/tools/render-utils.ts +2 -1
  181. package/src/tools/search.ts +491 -76
  182. package/src/tui/output-block.ts +37 -75
  183. package/src/utils/git.ts +9 -3
  184. package/dist/types/mnemosyne/backend.d.ts +0 -4
  185. package/dist/types/mnemosyne/config.d.ts +0 -29
  186. package/dist/types/mnemosyne/state.d.ts +0 -72
  187. /package/dist/types/{mnemosyne → mnemopi}/index.d.ts +0 -0
  188. /package/src/{mnemosyne → mnemopi}/index.ts +0 -0
@@ -1,4 +1,4 @@
1
- import type { InternalResource, InternalUrl, ProtocolHandler, UrlCompletion } from "./types";
1
+ import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
2
2
  export interface LocalProtocolOptions {
3
3
  getArtifactsDir?: () => string | null;
4
4
  getSessionId?: () => string | null;
@@ -28,13 +28,23 @@ export declare class LocalProtocolHandler implements ProtocolHandler {
28
28
  * Returns the active local-protocol options.
29
29
  *
30
30
  * Resolution order:
31
- * 1. Explicit override installed via {@link setOverride} (used by subagents
32
- * that share their parent's root and by SDK consumers with a custom
33
- * artifacts/session id mapping).
34
- * 2. The main session in `AgentRegistry.global()`. Its `SessionManager`
35
- * supplies both `getArtifactsDir` and `getSessionId`.
31
+ * 1. **Caller-supplied** `context.localProtocolOptions` (the actual session
32
+ * that initiated the `read`/`find`/`search`/`router.resolve` call). This
33
+ * is what keeps `local://` reads pinned to the calling session in
34
+ * multi-session hosts (cmux/ACP, embedded SDK consumers) where every
35
+ * session registers as `kind: "main"` and "first one wins" would route
36
+ * to the wrong artifacts directory.
37
+ * 2. Explicit process-global override installed via {@link setOverride}
38
+ * (used by SDK consumers with a custom artifacts/session-id mapping and
39
+ * by code paths that do not have a calling session, e.g. TUI hyperlink
40
+ * resolution).
41
+ * 3. The first `main`-kind session in `AgentRegistry.global()`. Its
42
+ * `SessionManager` supplies both `getArtifactsDir` and `getSessionId`.
43
+ * Last-resort fallback — every caller that has a session reference
44
+ * SHOULD thread it through `context` so this branch is never taken in
45
+ * multi-session setups.
36
46
  */
37
- static resolveOptions(): LocalProtocolOptions | undefined;
38
- resolve(url: InternalUrl): Promise<InternalResource>;
39
- complete(): Promise<UrlCompletion[]>;
47
+ static resolveOptions(context?: ResolveContext): LocalProtocolOptions | undefined;
48
+ resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource>;
49
+ complete(_query?: string, context?: ResolveContext): Promise<UrlCompletion[]>;
40
50
  }
@@ -4,6 +4,7 @@
4
4
  * Internal URLs (agent://, artifact://, memory://, skill://, rule://, mcp://, omp://, local://) are resolved by tools like read,
5
5
  * providing access to agent outputs and server resources without exposing filesystem paths.
6
6
  */
7
+ import type { LocalProtocolOptions } from "./local-protocol";
7
8
  /**
8
9
  * Raw resource payload returned by protocol handlers. The `immutable` flag is
9
10
  * applied by the router from {@link ProtocolHandler.immutable}, so handlers do
@@ -73,6 +74,17 @@ export interface ResolveContext {
73
74
  settings?: unknown;
74
75
  /** Caller's abort signal. */
75
76
  signal?: AbortSignal;
77
+ /**
78
+ * Calling session's `local://` root mapping. When present, the local-protocol
79
+ * handler resolves the URL against THIS session's artifacts dir instead of
80
+ * picking the first `main`-kind session from the global `AgentRegistry`.
81
+ *
82
+ * Required for correctness in multi-session hosts (cmux/ACP, embedded SDK
83
+ * consumers) where multiple sessions are registered as `main` and the
84
+ * "first one wins" lookup picks the wrong artifacts directory — see
85
+ * [#1608](https://github.com/can1357/oh-my-pi/issues/1608).
86
+ */
87
+ localProtocolOptions?: LocalProtocolOptions;
76
88
  }
77
89
  /**
78
90
  * Caller context for write operations dispatched to host-owned URI handlers.
@@ -84,6 +96,8 @@ export interface WriteContext {
84
96
  cwd?: string;
85
97
  /** Caller's abort signal. */
86
98
  signal?: AbortSignal;
99
+ /** Calling session's `local://` root mapping — see {@link ResolveContext.localProtocolOptions}. */
100
+ localProtocolOptions?: LocalProtocolOptions;
87
101
  }
88
102
  /**
89
103
  * Handler for a specific internal URL scheme (e.g., agent://, memory://, skill://, mcp://).
@@ -39,6 +39,9 @@ export declare function notifySaved(client: LspClient, filePath: string, signal?
39
39
  * Increments version, sends didChange and didSave notifications.
40
40
  */
41
41
  export declare function refreshFile(client: LspClient, filePath: string, signal?: AbortSignal): Promise<void>;
42
+ /**
43
+ * Shutdown a specific client by key.
44
+ */
42
45
  export declare function shutdownClient(key: string): Promise<void>;
43
46
  /**
44
47
  * Send an LSP request and wait for response.
@@ -130,12 +130,21 @@ export declare class MCPManager {
130
130
  disconnectAll(): Promise<void>;
131
131
  /**
132
132
  * Reconnect to a server after a connection failure.
133
+ *
133
134
  * Tears down the stale connection, re-resolves auth, establishes a new
134
- * connection, reloads tools, and notifies consumers.
135
- * Concurrent calls for the same server share one reconnection attempt.
136
- * Returns the new connection, or null if reconnection failed.
137
- */
138
- reconnectServer(name: string): Promise<MCPServerConnection | null>;
135
+ * connection, reloads tools, and notifies consumers. Concurrent calls for
136
+ * the same server share one reconnection attempt. Returns the new
137
+ * connection, or `null` if reconnection failed or the per-server crash
138
+ * burst limit (see {@link RECONNECT_BURST_LIMIT}) is exceeded.
139
+ *
140
+ * @param options.manual - When `true`, resets the crash-burst window so a
141
+ * user-driven retry (e.g. `/mcp reconnect`) is never blocked by an
142
+ * earlier storm. Defaults to `false`; the transport `onClose` callback
143
+ * and the per-tool-call retry path in `tool-bridge` MUST NOT set it.
144
+ */
145
+ reconnectServer(name: string, options?: {
146
+ manual?: boolean;
147
+ }): Promise<MCPServerConnection | null>;
139
148
  /**
140
149
  * Refresh tools from a specific server.
141
150
  */
@@ -1,4 +1,4 @@
1
- export * from "../mnemosyne";
1
+ export * from "../mnemopi";
2
2
  export * from "./local-backend";
3
3
  export * from "./off-backend";
4
4
  export * from "./resolve";
@@ -6,7 +6,7 @@ import type { MemoryBackend } from "./types";
6
6
  * Selection rules (single source of truth — every memory consumer routes
7
7
  * through this):
8
8
  * - `memory.backend === "hindsight"` → Hindsight remote memory
9
- * - `memory.backend === "mnemosyne"` → local Mnemosyne SQLite memory
9
+ * - `memory.backend === "mnemopi"` → local Mnemopi SQLite memory
10
10
  * - `memory.backend === "local"` → local rollout summary pipeline
11
11
  * - everything else → no-op
12
12
  *
@@ -9,9 +9,9 @@ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
9
9
  import type { ModelRegistry } from "../config/model-registry";
10
10
  import type { Settings } from "../config/settings";
11
11
  import type { HindsightSessionState } from "../hindsight/state";
12
- import type { MnemosyneSessionState } from "../mnemosyne/state";
12
+ import type { MnemopiSessionState } from "../mnemopi/state";
13
13
  import type { AgentSession } from "../session/agent-session";
14
- export type MemoryBackendId = "off" | "local" | "hindsight" | "mnemosyne";
14
+ export type MemoryBackendId = "off" | "local" | "hindsight" | "mnemopi";
15
15
  export interface MemoryBackendStartOptions {
16
16
  session: AgentSession;
17
17
  settings: Settings;
@@ -19,7 +19,7 @@ export interface MemoryBackendStartOptions {
19
19
  agentDir: string;
20
20
  taskDepth: number;
21
21
  parentHindsightSessionState?: HindsightSessionState;
22
- parentMnemosyneSessionState?: MnemosyneSessionState;
22
+ parentMnemopiSessionState?: MnemopiSessionState;
23
23
  }
24
24
  export interface MemoryBackend {
25
25
  readonly id: MemoryBackendId;
@@ -0,0 +1,4 @@
1
+ import type { MemoryBackend } from "../memory-backend/types";
2
+ import type { AgentSession } from "../session/agent-session";
3
+ export declare const mnemopiBackend: MemoryBackend;
4
+ export declare function getMnemopiDbDirForTests(session: AgentSession): string | undefined;
@@ -0,0 +1,29 @@
1
+ import type { MnemopiOptions } from "@oh-my-pi/pi-mnemopi";
2
+ import type { Settings } from "../config/settings";
3
+ export type MnemopiLlmMode = "none" | "smol" | "remote";
4
+ export type MnemopiScoping = "global" | "per-project" | "per-project-tagged";
5
+ export type MnemopiProviderOptions = Pick<MnemopiOptions, "noEmbeddings" | "embeddingModel" | "embeddingApiUrl" | "embeddingApiKey" | "llm">;
6
+ export interface MnemopiBackendConfig {
7
+ dbPath: string;
8
+ baseBank?: string;
9
+ bank: string;
10
+ globalBank?: string;
11
+ retainBank?: string;
12
+ recallBanks?: readonly string[];
13
+ scoping?: MnemopiScoping;
14
+ autoRecall: boolean;
15
+ autoRetain: boolean;
16
+ retainEveryNTurns: number;
17
+ recallLimit: number;
18
+ recallContextTurns: number;
19
+ recallMaxQueryChars: number;
20
+ injectionTokenLimit: number;
21
+ debug: boolean;
22
+ providerOptions: MnemopiProviderOptions;
23
+ llmMode: MnemopiLlmMode;
24
+ llmBaseUrl?: string;
25
+ llmApiKey?: string;
26
+ llmModel?: string;
27
+ }
28
+ export declare function loadMnemopiConfig(settings: Settings, agentDir: string): MnemopiBackendConfig;
29
+ export declare function truncateApproxTokens(text: string, tokenLimit: number): string;
@@ -0,0 +1,72 @@
1
+ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
2
+ import { Mnemopi, type RecallResult } from "@oh-my-pi/pi-mnemopi";
3
+ import type { AgentSession } from "../session/agent-session";
4
+ import type { MnemopiBackendConfig } from "./config";
5
+ interface MnemopiScopedMemory {
6
+ bank: string;
7
+ memory: Mnemopi;
8
+ }
9
+ type MnemopiRememberInput = Parameters<Mnemopi["remember"]>[0];
10
+ type MnemopiRememberOptions = Parameters<Mnemopi["remember"]>[1];
11
+ export type MnemopiMemoryEditOperation = "update" | "forget" | "invalidate";
12
+ export interface MnemopiMemoryEditOptions {
13
+ content?: string;
14
+ importance?: number;
15
+ replacementId?: string;
16
+ }
17
+ export interface MnemopiMemoryEditResult {
18
+ status: "updated" | "deleted" | "invalidated" | "not_found";
19
+ bank?: string;
20
+ store?: "working" | "episodic";
21
+ }
22
+ export declare function getMnemopiSessionState(session: AgentSession | undefined): MnemopiSessionState | undefined;
23
+ export declare function setMnemopiSessionState(session: AgentSession, state: MnemopiSessionState | undefined): MnemopiSessionState | undefined;
24
+ export interface MnemopiSessionStateOptions {
25
+ sessionId: string;
26
+ config: MnemopiBackendConfig;
27
+ session: AgentSession;
28
+ aliasOf?: MnemopiSessionState;
29
+ lastRetainedTurn?: number;
30
+ hasRecalledForFirstTurn?: boolean;
31
+ }
32
+ export declare class MnemopiSessionState {
33
+ sessionId: string;
34
+ readonly config: MnemopiBackendConfig;
35
+ readonly session: AgentSession;
36
+ readonly memory: Mnemopi;
37
+ readonly globalMemory?: Mnemopi;
38
+ readonly aliasOf?: MnemopiSessionState;
39
+ private readonly scoped;
40
+ lastRetainedTurn: number;
41
+ hasRecalledForFirstTurn: boolean;
42
+ lastRecallSnippet?: string;
43
+ unsubscribe?: () => void;
44
+ constructor(options: MnemopiSessionStateOptions);
45
+ setSessionId(sessionId: string): void;
46
+ resetConversationTracking(): void;
47
+ getScopedRecallTargets(): readonly MnemopiScopedMemory[];
48
+ getScopedRetainTarget(): MnemopiScopedMemory;
49
+ editScopedMemory(op: MnemopiMemoryEditOperation, id: string, options?: MnemopiMemoryEditOptions): MnemopiMemoryEditResult;
50
+ formatScopedRecallWithIds(results: readonly RecallResult[]): string;
51
+ collectScopedRecallResults(query: string): RecallResult[];
52
+ recallResultsScoped(query: string): RecallResult[];
53
+ formatScopedRecallContext(results: readonly RecallResult[], format?: "bullet" | "json"): string | undefined;
54
+ formatContextScoped(results: readonly RecallResult[], format?: "bullet" | "json"): string;
55
+ rememberInScope(memory: MnemopiRememberInput, options?: MnemopiRememberOptions): string | undefined;
56
+ rememberScoped(memory: MnemopiRememberInput, options?: MnemopiRememberOptions): string | undefined;
57
+ recallForContext(query: string): Promise<string | undefined>;
58
+ beforeAgentStartPrompt(promptText: string): Promise<string | undefined>;
59
+ recallForCompaction(messages: AgentMessage[]): Promise<string | undefined>;
60
+ maybeRetainOnAgentEnd(_messages: AgentMessage[]): Promise<void>;
61
+ forceRetainCurrentSession(): Promise<void>;
62
+ retainMessages(messages: Array<{
63
+ role: string;
64
+ content: string;
65
+ }>, sourceId: string): Promise<void>;
66
+ attachSessionListeners(): void;
67
+ maybeRecallOnAgentStart(): Promise<void>;
68
+ dispose(): void;
69
+ }
70
+ export declare function getMnemopiScopedDbPaths(config: MnemopiBackendConfig): readonly string[];
71
+ export declare function getMnemopiScopedBanks(config: MnemopiBackendConfig): readonly string[];
72
+ export {};
@@ -6,7 +6,8 @@ type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.cl
6
6
  */
7
7
  export declare class CustomEditor extends Editor {
8
8
  #private;
9
- /** Gradient-highlight the "ultrathink" / "orchestrate" keywords as the user types them. */
9
+ /** Gradient-highlight the "ultrathink" / "orchestrate" / "workflow" keywords as the user types
10
+ * them, skipping any occurrence inside code spans, fenced blocks, or XML sections. */
10
11
  decorateText: (text: string) => string;
11
12
  onEscape?: () => void;
12
13
  shouldBypassAutocompleteOnEscape?: () => boolean;
@@ -21,7 +22,6 @@ export declare class CustomEditor extends Editor {
21
22
  onExternalEditor?: () => void;
22
23
  onHistorySearch?: () => void;
23
24
  onSuspend?: () => void;
24
- onShowHotkeys?: () => void;
25
25
  onSelectModelTemporary?: () => void;
26
26
  /** Called when the configured copy-prompt shortcut is pressed. */
27
27
  onCopyPrompt?: () => void;
@@ -0,0 +1,19 @@
1
+ import { Container, type TUI } from "@oh-my-pi/pi-tui";
2
+ export type OmfgPanelState = "generating" | "validating" | "confirming" | "saving" | "saved" | "rejected" | "aborted" | "error";
3
+ interface OmfgPanelComponentOptions {
4
+ complaint: string;
5
+ tui: TUI;
6
+ }
7
+ export declare class OmfgPanelComponent extends Container {
8
+ #private;
9
+ constructor(options: OmfgPanelComponentOptions);
10
+ appendDraft(delta: string): void;
11
+ setRule(text: string): void;
12
+ setStatus(state: OmfgPanelState, status: string): void;
13
+ markSaved(path: string): void;
14
+ markRejected(): void;
15
+ markAborted(): void;
16
+ markError(message: string): void;
17
+ close(): void;
18
+ }
19
+ export {};
@@ -3,6 +3,7 @@ import { type ProviderDetails, type UsageReport } from "@oh-my-pi/pi-ai";
3
3
  import type { CompactOptions } from "../../extensibility/extensions/types";
4
4
  import { theme } from "../../modes/theme/theme";
5
5
  import type { InteractiveModeContext } from "../../modes/types";
6
+ import { type ShakeMode } from "../../session/shake-types";
6
7
  export declare class CommandController {
7
8
  #private;
8
9
  private readonly ctx;
@@ -29,6 +30,11 @@ export declare class CommandController {
29
30
  handleBashCommand(command: string, excludeFromContext?: boolean): Promise<void>;
30
31
  handlePythonCommand(code: string, excludeFromContext?: boolean): Promise<void>;
31
32
  handleCompactCommand(customInstructions?: string): Promise<CompactionOutcome>;
33
+ /**
34
+ * TUI handler for `/shake`. `elide` drops heavy structural content and
35
+ * `images` strips image blocks. Rebuilds the chat and reports counts.
36
+ */
37
+ handleShakeCommand(mode: ShakeMode): Promise<void>;
32
38
  handleSkillCommand(skillPath: string, args: string): Promise<void>;
33
39
  executeCompaction(customInstructionsOrOptions?: string | CompactOptions, isAuto?: boolean): Promise<CompactionOutcome>;
34
40
  handleHandoffCommand(customInstructions?: string): Promise<void>;
@@ -24,9 +24,7 @@ export declare class InputController {
24
24
  /** Copy current prompt text to system clipboard. */
25
25
  handleCopyPrompt(): void;
26
26
  cycleThinkingLevel(): void;
27
- cycleRoleModel(options?: {
28
- temporary?: boolean;
29
- }): Promise<void>;
27
+ cycleRoleModel(direction?: "forward" | "backward"): Promise<void>;
30
28
  toggleToolOutputExpansion(): void;
31
29
  setToolsExpanded(expanded: boolean): void;
32
30
  toggleThinkingBlockVisibility(): void;
@@ -0,0 +1,10 @@
1
+ import type { InteractiveModeContext } from "../types";
2
+ export declare class OmfgController {
3
+ #private;
4
+ private readonly ctx;
5
+ constructor(ctx: InteractiveModeContext);
6
+ hasActiveRequest(): boolean;
7
+ handleEscape(): boolean;
8
+ dispose(): void;
9
+ start(complaint: string): Promise<void>;
10
+ }
@@ -0,0 +1,26 @@
1
+ import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
2
+ import type { Rule } from "../../capability/rule";
3
+ export interface ParsedGeneratedRule {
4
+ rule: Rule;
5
+ fileContent: string;
6
+ }
7
+ export type GeneratedRuleParseResult = ParsedGeneratedRule | {
8
+ error: string;
9
+ };
10
+ export interface RuleHistoryValidation {
11
+ matched: boolean;
12
+ feedback?: string;
13
+ }
14
+ export interface ParsedRuleHistoryValidation {
15
+ candidate: ParsedGeneratedRule;
16
+ validation: RuleHistoryValidation;
17
+ repairedCondition: boolean;
18
+ }
19
+ export type OmfgRuleSourceLevel = "project" | "user";
20
+ export declare function extractGeneratedRuleJson(text: string): string | null;
21
+ export declare function sanitizeRuleName(rawName: string): string;
22
+ export declare function buildOmfgRuleForPath(ruleName: string, fileContent: string, filePath: string, level: OmfgRuleSourceLevel): Rule;
23
+ export declare function parseGeneratedRule(text: string): GeneratedRuleParseResult;
24
+ export declare function validateRuleAgainstAssistantHistory(rule: Rule, messages: readonly AgentMessage[]): RuleHistoryValidation;
25
+ export declare function validateParsedRuleAgainstAssistantHistory(candidate: ParsedGeneratedRule, messages: readonly AgentMessage[]): ParsedRuleHistoryValidation;
26
+ export declare function ruleMatchesAssistantHistory(rule: Rule, messages: readonly AgentMessage[]): boolean;
@@ -1,3 +1,7 @@
1
+ /** A gradient keyword highlighter. `resetTo` is the SGR foreground sequence
2
+ * re-emitted after each painted keyword so surrounding text keeps its color;
3
+ * it defaults to a plain foreground reset (editor / default-colored text). */
4
+ export type KeywordHighlighter = (text: string, resetTo?: string) => string;
1
5
  /** Declarative spec for {@link createGradientHighlighter}. */
2
6
  export interface GradientHighlightSpec {
3
7
  /** Cheap, stateless presence probe used to skip the boundary regex on most lines. Must be non-global. */
@@ -20,4 +24,4 @@ export interface GradientHighlightSpec {
20
24
  * untouched when `probe` does not match. The palette is compiled lazily and
21
25
  * memoized per active color mode.
22
26
  */
23
- export declare function createGradientHighlighter(spec: GradientHighlightSpec): (text: string) => string;
27
+ export declare function createGradientHighlighter(spec: GradientHighlightSpec): KeywordHighlighter;
@@ -11,6 +11,7 @@ import { type PlanApprovalDetails } from "../plan-mode/approved-plan";
11
11
  import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
12
12
  import { HistoryStorage } from "../session/history-storage";
13
13
  import type { SessionContext, SessionManager } from "../session/session-manager";
14
+ import type { ShakeMode } from "../session/shake-types";
14
15
  import type { LspStartupServerInfo } from "../tools";
15
16
  import type { EventBus } from "../utils/event-bus";
16
17
  import type { AssistantMessageComponent } from "./components/assistant-message";
@@ -53,6 +54,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
53
54
  statusContainer: Container;
54
55
  todoContainer: Container;
55
56
  btwContainer: Container;
57
+ omfgContainer: Container;
56
58
  editor: CustomEditor;
57
59
  editorContainer: Container;
58
60
  hookWidgetContainerAbove: Container;
@@ -207,6 +209,7 @@ export declare class InteractiveMode implements InteractiveModeContext {
207
209
  handleSSHCommand(text: string): Promise<void>;
208
210
  handleCompactCommand(customInstructions?: string): Promise<CompactionOutcome>;
209
211
  handleHandoffCommand(customInstructions?: string): Promise<void>;
212
+ handleShakeCommand(mode: ShakeMode): Promise<void>;
210
213
  executeCompaction(customInstructionsOrOptions?: string | CompactOptions, isAuto?: boolean): Promise<CompactionOutcome>;
211
214
  openInBrowser(urlOrPath: string): void;
212
215
  showSettingsSelector(): void;
@@ -233,10 +236,11 @@ export declare class InteractiveMode implements InteractiveModeContext {
233
236
  handleBtwCommand(question: string): Promise<void>;
234
237
  hasActiveBtw(): boolean;
235
238
  handleBtwEscape(): boolean;
239
+ handleOmfgCommand(complaint: string): Promise<void>;
240
+ hasActiveOmfg(): boolean;
241
+ handleOmfgEscape(): boolean;
236
242
  cycleThinkingLevel(): void;
237
- cycleRoleModel(options?: {
238
- temporary?: boolean;
239
- }): Promise<void>;
243
+ cycleRoleModel(direction?: "forward" | "backward"): Promise<void>;
240
244
  toggleToolOutputExpansion(): void;
241
245
  setToolsExpanded(expanded: boolean): void;
242
246
  toggleThinkingBlockVisibility(): void;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Gradient-highlight every magic keyword ("ultrathink", "orchestrate",
3
+ * "workflow") that appears as standalone prose, skipping any occurrence inside a
4
+ * code block, inline code span, or XML/HTML section. Each highlighter paints its
5
+ * own keyword with its own gradient, so chaining is order-independent — the
6
+ * earlier passes only inject zero-width SGR escapes (no backticks or angle
7
+ * brackets), which never confuse the later passes' markdown masking.
8
+ *
9
+ * `resetTo` is the SGR foreground sequence restored after each painted keyword;
10
+ * pass the surrounding text color when decorating already-colored content (e.g.
11
+ * a themed message bubble) so the gradient does not bleed into the rest of the
12
+ * line. Defaults to a plain foreground reset for default-colored editor text.
13
+ */
14
+ export declare function highlightMagicKeywords(text: string, resetTo?: string): string;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Markdown structure awareness for the magic-keyword affordances
3
+ * ("ultrathink"/"orchestrate"/"workflow").
4
+ *
5
+ * Keyword detection and editor/transcript highlighting must fire only on prose
6
+ * the user is actually addressing to the model — never on a word that happens to
7
+ * live inside a fenced code block, an inline code span, or an HTML/XML section.
8
+ * {@link maskNonProse} returns a length-preserving copy of the text where every
9
+ * such region is blanked to spaces, so a word-bounded match run against the mask
10
+ * never lands inside code/markup while its indices still address the original
11
+ * text for painting.
12
+ */
13
+ /**
14
+ * Return a copy of `text` with identical length (indices map 1:1) where every
15
+ * character inside a non-prose region is replaced by a space. Non-prose regions
16
+ * are markdown fenced code blocks, inline code spans, and HTML/XML tags together
17
+ * with the content they enclose. Newlines are preserved. Text with no construct
18
+ * that could open such a region is returned unchanged.
19
+ */
20
+ export declare function maskNonProse(text: string): string;
21
+ /**
22
+ * Whether `text` contains a standalone keyword match (per the non-global,
23
+ * word-bounded `word` regex) that lives in prose rather than inside a code
24
+ * block, inline code span, or HTML/XML section. `word` MUST be non-global so
25
+ * `.test` stays stateless.
26
+ */
27
+ export declare function keywordInProse(text: string, word: RegExp): boolean;
@@ -1,10 +1,15 @@
1
+ import { type KeywordHighlighter } from "./gradient-highlight";
1
2
  /** Hidden system notice appended after a user message that mentions "orchestrate". */
2
3
  export declare const ORCHESTRATE_NOTICE: string;
3
- /** Whether `text` contains the standalone keyword "orchestrate" (any case). */
4
+ /**
5
+ * Whether `text` contains the standalone keyword "orchestrate" (lowercase,
6
+ * whitespace-delimited) in prose — never inside a code block, inline code span,
7
+ * or XML/HTML section.
8
+ */
4
9
  export declare function containsOrchestrate(text: string): boolean;
5
10
  /**
6
11
  * Highlight every standalone "orchestrate" in `text` for editor display with a
7
12
  * cool teal→violet gradient (hue 150..280), visually distinct from ultrathink's
8
13
  * full-spectrum rainbow.
9
14
  */
10
- export declare const highlightOrchestrate: (text: string) => string;
15
+ export declare const highlightOrchestrate: KeywordHighlighter;
@@ -1,5 +1,5 @@
1
1
  import type { TabBarTheme } from "@oh-my-pi/pi-tui";
2
- /** Sanitize text for display in a single-line status. Strips ANSI escape sequences, C0/C1 control characters, collapses whitespace, trims. */
2
+ /** Sanitize text for display in a single-line status. Strips ANSI/VT escape sequences, maps remaining C0/C1 control characters to spaces, collapses whitespace, trims. */
3
3
  export declare function sanitizeStatusText(text: string): string;
4
4
  /** Shared tab bar theme used by model-selector and settings-selector. */
5
5
  export declare function getTabBarTheme(): TabBarTheme;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * "+Nk" turn token-budget directive.
3
+ *
4
+ * A standalone `+<number>[k|m]` token in the user's message sets a per-turn
5
+ * output-token budget surfaced by the `eval` `budget` helper. By default it is
6
+ * ADVISORY — the model self-limits via `budget.remaining()`. Append `!`
7
+ * (`+500k!`) to make it a HARD ceiling: eval `agent()` refuses to spawn once the
8
+ * turn's spend reaches it. Matching is anchored to token boundaries so it does
9
+ * not fire on prices or version strings embedded in prose.
10
+ */
11
+ export interface TurnBudget {
12
+ /** Output-token ceiling for the turn. */
13
+ total: number;
14
+ /** Whether the ceiling is enforced (eval `agent()` throws past it) vs advisory. */
15
+ hard: boolean;
16
+ }
17
+ /** Parse a `+Nk`/`+N`/`+Nm`(`!`) turn-budget directive from `text`, or null when absent. */
18
+ export declare function parseTurnBudget(text: string): TurnBudget | null;
@@ -11,6 +11,7 @@ import type { PlanApprovalDetails } from "../plan-mode/approved-plan";
11
11
  import type { AgentSession, AgentSessionEvent } from "../session/agent-session";
12
12
  import type { HistoryStorage } from "../session/history-storage";
13
13
  import type { SessionContext, SessionManager } from "../session/session-manager";
14
+ import type { ShakeMode } from "../session/shake-types";
14
15
  import type { LspStartupServerInfo } from "../tools";
15
16
  import type { AssistantMessageComponent } from "./components/assistant-message";
16
17
  import type { BashExecutionComponent } from "./components/bash-execution";
@@ -57,6 +58,7 @@ export interface InteractiveModeContext {
57
58
  statusContainer: Container;
58
59
  todoContainer: Container;
59
60
  btwContainer: Container;
61
+ omfgContainer: Container;
60
62
  editor: CustomEditor;
61
63
  editorContainer: Container;
62
64
  hookWidgetContainerAbove: Container;
@@ -207,6 +209,7 @@ export interface InteractiveModeContext {
207
209
  handleSSHCommand(text: string): Promise<void>;
208
210
  handleCompactCommand(customInstructions?: string): Promise<CompactionOutcome>;
209
211
  handleHandoffCommand(customInstructions?: string): Promise<void>;
212
+ handleShakeCommand(mode: ShakeMode): Promise<void>;
210
213
  handleMoveCommand(targetPath: string): Promise<void>;
211
214
  handleRenameCommand(title: string): Promise<void>;
212
215
  handleMemoryCommand(text: string): Promise<void>;
@@ -241,10 +244,11 @@ export interface InteractiveModeContext {
241
244
  handleBtwCommand(question: string): Promise<void>;
242
245
  hasActiveBtw(): boolean;
243
246
  handleBtwEscape(): boolean;
247
+ handleOmfgCommand(complaint: string): Promise<void>;
248
+ hasActiveOmfg(): boolean;
249
+ handleOmfgEscape(): boolean;
244
250
  cycleThinkingLevel(): void;
245
- cycleRoleModel(options?: {
246
- temporary?: boolean;
247
- }): Promise<void>;
251
+ cycleRoleModel(direction?: "forward" | "backward"): Promise<void>;
248
252
  toggleToolOutputExpansion(): void;
249
253
  setToolsExpanded(expanded: boolean): void;
250
254
  toggleThinkingBlockVisibility(): void;
@@ -1,10 +1,15 @@
1
+ import { type KeywordHighlighter } from "./gradient-highlight";
1
2
  /** Hidden system notice appended after a user message that mentions "ultrathink". */
2
3
  export declare const ULTRATHINK_NOTICE: string;
3
- /** Whether `text` contains the standalone keyword "ultrathink" (any case). */
4
+ /**
5
+ * Whether `text` contains the standalone keyword "ultrathink" (lowercase,
6
+ * whitespace-delimited) in prose — never inside a code block, inline code span,
7
+ * or XML/HTML section.
8
+ */
4
9
  export declare function containsUltrathink(text: string): boolean;
5
10
  /**
6
11
  * Rainbow-highlight every standalone "ultrathink" in `text` for editor display.
7
12
  * Sweeps red→violet (hue 0..330), stopping short of the wrap back to red so the
8
13
  * gradient resolves smoothly regardless of casing or match length.
9
14
  */
10
- export declare const highlightUltrathink: (text: string) => string;
15
+ export declare const highlightUltrathink: KeywordHighlighter;
@@ -0,0 +1,15 @@
1
+ import { type KeywordHighlighter } from "./gradient-highlight";
2
+ /** Hidden system notice appended after a user message that mentions "workflow". */
3
+ export declare const WORKFLOW_NOTICE: string;
4
+ /**
5
+ * Whether `text` contains the standalone keyword "workflow"/"workflows"
6
+ * (lowercase, whitespace-delimited) in prose — never inside a code block, inline
7
+ * code span, or XML/HTML section.
8
+ */
9
+ export declare function containsWorkflow(text: string): boolean;
10
+ /**
11
+ * Highlight every standalone "workflow"/"workflows" in `text` for editor display
12
+ * with a warm amber→green gradient (hue 30..150), visually distinct from
13
+ * ultrathink's rainbow and orchestrate's teal→violet.
14
+ */
15
+ export declare const highlightWorkflow: KeywordHighlighter;
@@ -13,7 +13,7 @@ import { type FileSlashCommand } from "./extensibility/slash-commands";
13
13
  import type { HindsightSessionState } from "./hindsight/state";
14
14
  import { type LocalProtocolOptions } from "./internal-urls";
15
15
  import { MCPManager, type MCPToolsLoadResult } from "./mcp";
16
- import { type MnemosyneSessionState } from "./mnemosyne/state";
16
+ import { type MnemopiSessionState } from "./mnemopi/state";
17
17
  import { AgentRegistry } from "./registry/agent-registry";
18
18
  import { AgentSession } from "./session/agent-session";
19
19
  import { AuthStorage } from "./session/auth-storage";
@@ -99,8 +99,8 @@ export interface CreateAgentSessionOptions {
99
99
  taskDepth?: number;
100
100
  /** Parent Hindsight state to alias for subagent memory tools. */
101
101
  parentHindsightSessionState?: HindsightSessionState;
102
- /** Parent Mnemosyne state to alias for subagent memory tools. */
103
- parentMnemosyneSessionState?: MnemosyneSessionState;
102
+ /** Parent Mnemopi state to alias for subagent memory tools. */
103
+ parentMnemopiSessionState?: MnemopiSessionState;
104
104
  /** Pre-allocated agent identity for IRC routing. Default: "0-Main" for top-level, parentTaskPrefix-derived for sub. */
105
105
  agentId?: string;
106
106
  /** Display name for the agent in IRC. Default: "main" or "sub". */
@@ -176,6 +176,16 @@ export declare function discoverAuthStorage(agentDir?: string): Promise<AuthStor
176
176
  * Discover extensions from cwd.
177
177
  */
178
178
  export declare function discoverExtensions(cwd?: string): Promise<LoadExtensionsResult>;
179
+ /**
180
+ * Load the discovered/configured extensions for a session — everything {@link
181
+ * createAgentSession} would load except the inline factory extensions it appends
182
+ * itself. Extracted so the CLI can resolve extension-registered flags (and thus
183
+ * classify `@file` arguments extension-aware) *before* a session — and its
184
+ * terminal breadcrumb — is created, then hand the result back through
185
+ * {@link CreateAgentSessionOptions.preloadedExtensions} so the work is not
186
+ * repeated. Keep this the single source of the discovery branch logic.
187
+ */
188
+ export declare function loadSessionExtensions(options: Pick<CreateAgentSessionOptions, "disableExtensionDiscovery" | "additionalExtensionPaths">, cwd: string, settings: Settings, eventBus: EventBus): Promise<LoadExtensionsResult>;
179
189
  /**
180
190
  * Discover skills from cwd and agentDir.
181
191
  */