pi-multimodal-proxy 1.12.1 → 1.13.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,11 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [1.13.0] - 2026-08-09
8
+
9
+ ### Fixed
10
+ - Migrated to `ModelRegistry.complete`.
11
+
7
12
  ## [1.12.1] - 2026-08-07
8
13
 
9
14
  ### Fixed
package/README.md CHANGED
@@ -314,3 +314,4 @@ For the full security audit see [`SECURITY-REVIEW.md`](./SECURITY-REVIEW.md).
314
314
  ## License
315
315
 
316
316
  MIT
317
+
@@ -49,13 +49,43 @@ import { access, copyFile, mkdir, mkdtemp, readFile, readdir, rm } from "node:fs
49
49
  import os from "node:os";
50
50
  import { isAbsolute, join } from "node:path";
51
51
  import { promisify } from "node:util";
52
- import { type ImageContent as PiAiImage, complete } from "@earendil-works/pi-ai";
52
+ import { type ImageContent as PiAiImage, type Api, type Model, type Context, type ProviderStreamOptions, type AssistantMessage } from "@earendil-works/pi-ai";
53
+
54
+ type LegacyComplete = <TApi extends Api>(model: Model<TApi>, context: Context, options?: ProviderStreamOptions) => Promise<AssistantMessage>;
55
+
56
+ // move `complete` to @earendil-works/pi-ai/compat
57
+ let legacyCompletePromise: Promise<LegacyComplete> | undefined;
58
+ function loadLegacyComplete(): Promise<LegacyComplete> {
59
+ if (!legacyCompletePromise) {
60
+ const compatSpecifier: string = "@earendil-works/pi-ai/compat";
61
+ legacyCompletePromise = import("@earendil-works/pi-ai").then((mod: any) =>
62
+ typeof mod.complete === "function"
63
+ ? mod.complete
64
+ : import(compatSpecifier).then((compat: any) => compat.complete),
65
+ );
66
+ }
67
+ return legacyCompletePromise;
68
+ }
69
+
70
+ /** Compatibility wrapper: uses new ModelRegistry.complete when available, otherwise falls back to legacyComplete. */
71
+ function hasComplete(mr: ModelRegistry): mr is ModelRegistry & { complete: LegacyComplete } {
72
+ return typeof (mr as any).complete === "function";
73
+ }
74
+
75
+ async function completeCompat<TApi extends Api>(ctx: ExtensionContext, model: Model<TApi>, request: Context, options?: ProviderStreamOptions) {
76
+ if (hasComplete(ctx.modelRegistry)) {
77
+ return ctx.modelRegistry.complete(model, request, options);
78
+ }
79
+ const legacyComplete = await loadLegacyComplete();
80
+ return legacyComplete(model, request, options);
81
+ }
82
+
53
83
  import type {
54
84
  BeforeAgentStartEvent,
55
85
  BeforeAgentStartEventResult,
56
86
  ContextEvent,
57
87
  ExtensionAPI,
58
- ExtensionContext,
88
+ ExtensionContext, ModelRegistry,
59
89
  SessionCompactEvent,
60
90
  SessionEntry,
61
91
  SessionStartEvent,
@@ -617,7 +647,9 @@ async function analyzeImages(
617
647
  config: VisionConfig,
618
648
  ctx: ExtensionContext,
619
649
  ): Promise<AnalysisResult[] | null> {
650
+
620
651
  const visionModel = ctx.modelRegistry.find(config.provider, config.modelId);
652
+
621
653
  if (!visionModel) {
622
654
  ctx.ui.notify(
623
655
  `[multimodal-proxy] Model "${modelLabel(config)}" not found. Use /multimodal-proxy pick to choose one.`,
@@ -667,7 +699,7 @@ async function analyzeImages(
667
699
  storeImageData(imageData, hash, piAiImage.data, piAiImage.mimeType);
668
700
 
669
701
  try {
670
- const response = await complete(
702
+ const response = await completeCompat(ctx,
671
703
  visionModel,
672
704
  {
673
705
  systemPrompt: config.systemPrompt,
@@ -790,7 +822,7 @@ async function analyzeVideo(
790
822
  : "";
791
823
 
792
824
  try {
793
- const response = await complete(
825
+ const response = await completeCompat(ctx,
794
826
  videoModel,
795
827
  {
796
828
  systemPrompt: config.videoSystemPrompt,
@@ -1463,7 +1495,7 @@ async function handleAnalyzeImage(
1463
1495
 
1464
1496
  try {
1465
1497
  const startTime = Date.now();
1466
- const response = await complete(
1498
+ const response = await completeCompat(ctx,
1467
1499
  visionModel,
1468
1500
  {
1469
1501
  systemPrompt,
@@ -2029,7 +2061,7 @@ export default function (pi: ExtensionAPI) {
2029
2061
  ...jointImages,
2030
2062
  ];
2031
2063
 
2032
- const jointResponse = await complete(
2064
+ const jointResponse = await completeCompat(ctx,
2033
2065
  jointVisionModel,
2034
2066
  {
2035
2067
  systemPrompt: jointSystemPrompt,
@@ -3120,7 +3152,7 @@ Use "*" or "all" to grant consent for all providers globally.`,
3120
3152
 
3121
3153
  try {
3122
3154
  const startTime = Date.now();
3123
- const response = await complete(
3155
+ const response = await completeCompat(ctx,
3124
3156
  descVisionModel,
3125
3157
  {
3126
3158
  systemPrompt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-multimodal-proxy",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "description": "Automatic image, video and audio description for any model in Pi. Routes media to a multimodal model and injects descriptions into context.",
5
5
  "keywords": [
6
6
  "pi-package"