@czottmann/pi-automode 1.14.0 → 1.15.0

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.15.0] - 2026-08-28
8
+
9
+ ## Bug fixes
10
+
11
+ - **OMP 18 classifier compatibility** — Support OMP 18 model registries that lack `complete()` and `getProvider()`. Load the legacy completion API only for these registries. Keep current Pi on its runtime registry path so extension-registered providers remain available. Thanks, @NarryG! (#29)
12
+
7
13
  ## [1.14.0] - 2026-08-27
8
14
 
9
15
  ## Bug fixes
@@ -45,7 +51,8 @@ All notable changes to this project are documented in this file.
45
51
  - **Project config trust gate** — Ignore `.pi/automode.local.json` and `.pi/automode.json` until Pi trusts the project. Apply the trust gate during startup and config reloads. (#16)
46
52
  - **In-memory observability logs** — Write logs to an extension-owned directory (`~/.pi/agent/extensions/pi-automode/logs/`) instead of the launching project directory. Thanks, @HerbertGao! (#13)
47
53
 
48
- [Unreleased]: https://github.com/czottmann/pi-automode/compare/v1.14.0...HEAD
54
+ [Unreleased]: https://github.com/czottmann/pi-automode/compare/v1.15.0...HEAD
55
+ [1.15.0]: https://github.com/czottmann/pi-automode/compare/v1.14.0...v1.15.0
49
56
  [1.14.0]: https://github.com/czottmann/pi-automode/compare/v1.13.0...v1.14.0
50
57
  [1.13.0]: https://github.com/czottmann/pi-automode/compare/v1.12.0...v1.13.0
51
58
  [1.12.0]: https://github.com/czottmann/pi-automode/compare/v1.11.0...v1.12.0
package/README.md CHANGED
@@ -8,6 +8,10 @@ It is not a sandbox. Extensions run in the Pi process. A malicious extension can
8
8
 
9
9
  Pi-automode does not guard user `!` or `!!` shell commands. It guards only agent tool calls. Use it to reduce unsafe autonomous tool use. Do not use it as an OS security boundary.
10
10
 
11
+ ## Compatibility
12
+
13
+ Pi-automode supports Pi and Oh My Pi (OMP) 18. It automatically uses OMP's legacy completion API. The integration needs no OMP-specific configuration.
14
+
11
15
  ## Install
12
16
 
13
17
  From npm:
@@ -84,10 +84,9 @@ async function resolveClassifier(
84
84
  };
85
85
  }
86
86
 
87
- const rawComplete: ClassifierCompletionFn = (callModel, context, options) =>
88
- ctx.modelRegistry.complete(callModel, context, options);
89
- const simpleComplete: ClassifierCompletionFn = (callModel, context, options) =>
90
- completeSimpleWithRegistry(ctx, callModel, context, options);
87
+ const { rawComplete, simpleComplete } = createRegistryCompletionFns(
88
+ ctx.modelRegistry,
89
+ );
91
90
  const completionPlan = createClassifierCompletionPlan(
92
91
  model,
93
92
  config.classifierReasoningLevel,
@@ -125,6 +124,70 @@ export type ClassifierCompletionFn = (
125
124
  },
126
125
  ) => Promise<AssistantMessage>;
127
126
 
127
+ type RegistryCompletionApi = {
128
+ complete?: ClassifierCompletionFn;
129
+ getProvider?: (provider: string) => {
130
+ streamSimple: (
131
+ model: Model<any>,
132
+ context: { systemPrompt: string; messages: UserMessage[] },
133
+ options: Parameters<ClassifierCompletionFn>[2],
134
+ ) => { result: () => Promise<AssistantMessage> };
135
+ } | undefined;
136
+ };
137
+ type ClassifierCompletionFallbacks = {
138
+ rawComplete: ClassifierCompletionFn;
139
+ simpleComplete: ClassifierCompletionFn;
140
+ };
141
+
142
+ type ClassifierCompletionFallbackLoader =
143
+ () => Promise<ClassifierCompletionFallbacks>;
144
+
145
+ // Static import would initialize deprecated compat registries on current Pi;
146
+ // OMP rewrites this literal dynamic import to its native pi-ai module.
147
+ async function loadCompatCompletionFns(): Promise<ClassifierCompletionFallbacks> {
148
+ const { complete, completeSimple } = await import(
149
+ "@earendil-works/pi-ai/compat"
150
+ );
151
+ return {
152
+ rawComplete: complete as ClassifierCompletionFn,
153
+ simpleComplete: completeSimple as ClassifierCompletionFn,
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Prefer the current runtime registry so extension-registered providers remain
159
+ * visible. Older Pi-family runtimes (including OMP 18) expose neither
160
+ * `complete` nor `getProvider`; lazily load the compat API they already use.
161
+ */
162
+ export function createRegistryCompletionFns(
163
+ registry: RegistryCompletionApi,
164
+ fallbackLoader: ClassifierCompletionFallbackLoader =
165
+ loadCompatCompletionFns,
166
+ ): ClassifierCompletionFallbacks {
167
+ let fallbackPromise: Promise<ClassifierCompletionFallbacks> | undefined;
168
+ const rawComplete: ClassifierCompletionFn =
169
+ typeof registry.complete === "function"
170
+ ? (model, context, options) =>
171
+ registry.complete!.call(registry, model, context, options)
172
+ : async (model, context, options) =>
173
+ (await (fallbackPromise ??= fallbackLoader())).rawComplete(
174
+ model,
175
+ context,
176
+ options,
177
+ );
178
+ const simpleComplete: ClassifierCompletionFn =
179
+ typeof registry.getProvider === "function"
180
+ ? (model, context, options) =>
181
+ completeSimpleWithRegistry(registry, model, context, options)
182
+ : async (model, context, options) =>
183
+ (await (fallbackPromise ??= fallbackLoader())).simpleComplete(
184
+ model,
185
+ context,
186
+ options,
187
+ );
188
+ return { rawComplete, simpleComplete };
189
+ }
190
+
128
191
  export type RetryOptions = {
129
192
  maxAttempts?: number;
130
193
  maxTokens?: number;
@@ -206,17 +269,16 @@ async function completeClassifierAttempt(
206
269
 
207
270
  /**
208
271
  * Run normalized Pi AI completion through the provider in Pi's runtime registry.
209
- * This temporary bridge is only valid until Pi exposes
210
- * `ctx.modelRegistry.completeSimple(...)` natively. Replace this function with
211
- * that API when the project's minimum supported Pi version includes it.
272
+ * Callers use this only when the registry exposes `getProvider`; legacy
273
+ * registries take the compat completion path instead.
212
274
  */
213
275
  async function completeSimpleWithRegistry(
214
- ctx: ExtensionContext,
276
+ registry: RegistryCompletionApi,
215
277
  model: Model<any>,
216
278
  context: { systemPrompt: string; messages: UserMessage[] },
217
279
  options: Parameters<ClassifierCompletionFn>[2],
218
280
  ): Promise<AssistantMessage> {
219
- const provider = ctx.modelRegistry.getProvider(model.provider);
281
+ const provider = registry.getProvider?.(model.provider);
220
282
  if (!provider) throw new Error(`Unknown provider: ${model.provider}`);
221
283
  return provider.streamSimple(model, context, options).result();
222
284
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@czottmann/pi-automode",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "Claude Code-style auto mode guardrail for pi.",
5
5
  "repository": {
6
6
  "url": "https://github.com/czottmann/pi-automode"