@anionex/dsh-vision-toolkit 0.1.7 → 0.1.9
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/README.i18n.yaml +2 -2
- package/README.md +34 -17
- package/README.zh.md +32 -7
- package/assets/community-group-qr.png +0 -0
- package/assets/vision-model-test.png +0 -0
- package/docs/requirements-traceability/README.i18n.yaml +2 -2
- package/docs/requirements-traceability/README.md +2 -2
- package/docs/requirements-traceability/README.zh.md +2 -2
- package/lib/client.js +361 -28
- package/lib/client.js.map +1 -1
- package/lib/config.js +14 -0
- package/lib/config.js.map +1 -1
- package/lib/image-input-variants.js +615 -0
- package/lib/image-input-variants.js.map +1 -0
- package/lib/index.js +8 -1
- package/lib/index.js.map +1 -1
- package/lib/paste-images.js +6 -0
- package/lib/paste-images.js.map +1 -1
- package/lib/runtime.js +37 -3
- package/lib/runtime.js.map +1 -1
- package/lib/types/client/index.d.ts +16 -5
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/paste-images.d.ts +69 -0
- package/lib/types/client/paste-images.d.ts.map +1 -1
- package/lib/types/config.d.ts +26 -0
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/image-input-variants.d.ts +153 -0
- package/lib/types/image-input-variants.d.ts.map +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/paste-images.d.ts +35 -0
- package/lib/types/paste-images.d.ts.map +1 -1
- package/lib/types/runtime.d.ts +5 -2
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/web-request.d.ts +7 -0
- package/lib/types/web-request.d.ts.map +1 -1
- package/lib/types/web.d.ts +17 -2
- package/lib/types/web.d.ts.map +1 -1
- package/lib/web-request.js +11 -2
- package/lib/web-request.js.map +1 -1
- package/lib/web.js +88 -5
- package/lib/web.js.map +1 -1
- package/package.json +2 -1
- package/src/client/index.tsx +53 -14
- package/src/client/paste-images.tsx +331 -15
- package/src/config.ts +40 -0
- package/src/image-input-variants.ts +688 -0
- package/src/index.ts +18 -1
- package/src/paste-images.ts +39 -0
- package/src/runtime.ts +42 -3
- package/src/web-request.ts +12 -2
- package/src/web.ts +90 -4
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image-input variants: sibling model-selector entries for every model the
|
|
3
|
+
* host positively declares text-only. A variant declares image input, so
|
|
4
|
+
* pasted images keep the native attachment flow — composer thumbnail and the
|
|
5
|
+
* durable session image — while the variant's stream rewrites every image
|
|
6
|
+
* block into a Vision Toolkit description before delegating to the original
|
|
7
|
+
* route. The durable log is untouched; only the wire carries text.
|
|
8
|
+
* @module dsh-vision-toolkit/image-input-variants
|
|
9
|
+
*/
|
|
10
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
11
|
+
import { tmpdir } from 'node:os';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { LlmAdapter, contentHasImage } from '@deepseek-ai/dsh-llm';
|
|
14
|
+
/** Provider-id prefix for the variant routes this plugin registers. */
|
|
15
|
+
export const VARIANT_PROVIDER_PREFIX = 'vision-toolkit-';
|
|
16
|
+
/** Display suffix shared by variant provider names and variant model names. */
|
|
17
|
+
export const VARIANT_SUFFIX = ' (Vision Toolkit)';
|
|
18
|
+
/** Promise-cache bound for image descriptions, so a long-lived Web profile cannot hoard evidence text. */
|
|
19
|
+
const EVIDENCE_CACHE_LIMIT = 64;
|
|
20
|
+
/**
|
|
21
|
+
* Media types the Vision Toolkit glance pipeline accepts, by declared media
|
|
22
|
+
* type. Narrower than the paste-to-workspace route (which stores any image
|
|
23
|
+
* type): a paste of an unsupported type on a variant session degrades loudly
|
|
24
|
+
* on the wire instead of being described.
|
|
25
|
+
*/
|
|
26
|
+
const MEDIA_EXTENSIONS = {
|
|
27
|
+
'image/png': '.png',
|
|
28
|
+
'image/jpeg': '.jpg',
|
|
29
|
+
'image/webp': '.webp',
|
|
30
|
+
'image/gif': '.gif',
|
|
31
|
+
};
|
|
32
|
+
/** Model-facing prefix on converted image blocks. */
|
|
33
|
+
const DESCRIBED_PREFIX = '[Image described by the Vision Toolkit]\n';
|
|
34
|
+
/** Model-facing prefix on degraded conversions; the model must never guess at image content. */
|
|
35
|
+
const DEGRADED_PREFIX = '[The Vision Toolkit could not describe this image: ';
|
|
36
|
+
/** The variant provider route minted for one upstream route. */
|
|
37
|
+
export function variantProviderId(upstream) {
|
|
38
|
+
return `${VARIANT_PROVIDER_PREFIX}${upstream}`;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether one model earns an image-input variant: the host must positively
|
|
42
|
+
* declare it text-only. A model with unknown modalities is left alone — its
|
|
43
|
+
* native channel is the safe default, and the variant would degrade it.
|
|
44
|
+
* @param info - model metadata from the host catalog.
|
|
45
|
+
* @returns true when the model is confirmed text-only.
|
|
46
|
+
*/
|
|
47
|
+
export function shouldWrapModel(info) {
|
|
48
|
+
return Array.isArray(info.inputModalities) && !info.inputModalities.includes('image');
|
|
49
|
+
}
|
|
50
|
+
/** Whether a content block list carries an image at any depth (tool-result nesting included). */
|
|
51
|
+
export { contentHasImage } from '@deepseek-ai/dsh-llm';
|
|
52
|
+
function messageOf(error) {
|
|
53
|
+
return error instanceof Error ? error.message : String(error);
|
|
54
|
+
}
|
|
55
|
+
/** Bounded promise cache for one attachment's description; failed reads are not retained. */
|
|
56
|
+
export class EvidenceCache {
|
|
57
|
+
limit;
|
|
58
|
+
entries = new Map();
|
|
59
|
+
constructor(limit) {
|
|
60
|
+
this.limit = limit;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Read one key's entry or compute it. Concurrent readers join the in-flight
|
|
64
|
+
* computation; a settled failure is evicted so a fixed configuration gets a
|
|
65
|
+
* fresh chance.
|
|
66
|
+
* @param key - the attachment identity (content-addressed).
|
|
67
|
+
* @param load - computes the description; must resolve `{ ok, block }` and never reject.
|
|
68
|
+
* @returns the cached or computed block.
|
|
69
|
+
*/
|
|
70
|
+
read(key, load) {
|
|
71
|
+
const existing = this.entries.get(key);
|
|
72
|
+
if (existing !== undefined) {
|
|
73
|
+
// Refresh recency: Map iteration order is insertion order.
|
|
74
|
+
this.entries.delete(key);
|
|
75
|
+
this.entries.set(key, existing);
|
|
76
|
+
return existing;
|
|
77
|
+
}
|
|
78
|
+
const pending = load().then((result) => {
|
|
79
|
+
// Only evict our own entry: this promise may have been LRU-evicted and
|
|
80
|
+
// the key re-populated by a newer read meanwhile.
|
|
81
|
+
if (!result.ok && this.entries.get(key) === pending) {
|
|
82
|
+
this.entries.delete(key);
|
|
83
|
+
}
|
|
84
|
+
return result.block;
|
|
85
|
+
}, (error) => {
|
|
86
|
+
if (this.entries.get(key) === pending) {
|
|
87
|
+
this.entries.delete(key);
|
|
88
|
+
}
|
|
89
|
+
throw error;
|
|
90
|
+
});
|
|
91
|
+
this.entries.set(key, pending);
|
|
92
|
+
while (this.entries.size > this.limit) {
|
|
93
|
+
const oldest = this.entries.keys().next().value;
|
|
94
|
+
if (oldest === undefined)
|
|
95
|
+
break;
|
|
96
|
+
this.entries.delete(oldest);
|
|
97
|
+
}
|
|
98
|
+
return pending;
|
|
99
|
+
}
|
|
100
|
+
/** Drop every cached description (runtime reconfiguration invalidates provider-specific reads). */
|
|
101
|
+
clear() {
|
|
102
|
+
this.entries.clear();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Wait on a shared promise without inheriting its lifetime: the caller's
|
|
107
|
+
* abort rejects this wait immediately, while the underlying read keeps
|
|
108
|
+
* running and lands in the cache for the retry.
|
|
109
|
+
* @param promise - the shared computation.
|
|
110
|
+
* @param signal - the caller's cancellation, or undefined to wait unconditionally.
|
|
111
|
+
* @returns the computed value, unless the caller aborted first.
|
|
112
|
+
*/
|
|
113
|
+
export function abortableWait(promise, signal) {
|
|
114
|
+
if (signal === undefined)
|
|
115
|
+
return promise;
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
if (signal.aborted) {
|
|
118
|
+
reject(signal.reason ?? new Error('aborted'));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const onAbort = () => { reject(signal.reason ?? new Error('aborted')); };
|
|
122
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
123
|
+
promise.then((value) => {
|
|
124
|
+
signal.removeEventListener('abort', onAbort);
|
|
125
|
+
resolve(value);
|
|
126
|
+
}, (error) => {
|
|
127
|
+
signal.removeEventListener('abort', onAbort);
|
|
128
|
+
reject(error);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
async function convertBlocks(blocks, convert) {
|
|
133
|
+
const out = [];
|
|
134
|
+
for (const block of blocks) {
|
|
135
|
+
if (block.type === 'image') {
|
|
136
|
+
out.push(await convert(block));
|
|
137
|
+
}
|
|
138
|
+
else if (block.type === 'tool-result' && contentHasImage(block.content)) {
|
|
139
|
+
out.push({ ...block, content: await convertBlocks(block.content, convert) });
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
out.push(block);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Read one image block into a Vision Toolkit description text block. Never
|
|
149
|
+
* throws: failures degrade to an explanatory block with `ok: false`, so the
|
|
150
|
+
* caller can decide what a failure means (the cache refuses to memoize it).
|
|
151
|
+
* @param ctx - plugin context; reads the optional `attachments` service.
|
|
152
|
+
* @param runtime - the currently serving Vision Toolkit runtime, if ready.
|
|
153
|
+
* @param block - the image block to describe.
|
|
154
|
+
* @returns the outcome and its model-facing replacement block.
|
|
155
|
+
*/
|
|
156
|
+
async function readImageBlock(ctx, runtime, block) {
|
|
157
|
+
const attachments = ctx.get('attachments');
|
|
158
|
+
const current = runtime();
|
|
159
|
+
if (attachments === undefined || current === undefined) {
|
|
160
|
+
return { ok: false, block: { type: 'text', text: `${DEGRADED_PREFIX}the Vision Toolkit runtime is not ready.]` } };
|
|
161
|
+
}
|
|
162
|
+
const extension = MEDIA_EXTENSIONS[block.attachment.mediaType];
|
|
163
|
+
if (extension === undefined) {
|
|
164
|
+
return { ok: false, block: { type: 'text', text: `${DEGRADED_PREFIX}unsupported image media type ${block.attachment.mediaType}.]` } };
|
|
165
|
+
}
|
|
166
|
+
let directory;
|
|
167
|
+
try {
|
|
168
|
+
// The glance pipeline validates paths against the workspace it is given,
|
|
169
|
+
// so the temp copy lives in a dedicated directory passed as that workspace.
|
|
170
|
+
const stored = await attachments.readImage(block.attachment);
|
|
171
|
+
directory = await mkdtemp(join(tmpdir(), 'dsh-vision-toolkit-'));
|
|
172
|
+
const file = join(directory, `image${extension}`);
|
|
173
|
+
await writeFile(file, Buffer.from(stored.data), { mode: 0o600 });
|
|
174
|
+
// A fresh signal on purpose: the cached run must not die with its first
|
|
175
|
+
// caller (their abort used to cancel every concurrent joiner); the runtime
|
|
176
|
+
// deadline still bounds it.
|
|
177
|
+
const result = await current.glance({ images: [file] }, { signal: new AbortController().signal, workspace: directory });
|
|
178
|
+
const answer = result.answer.trim();
|
|
179
|
+
if (answer.length === 0)
|
|
180
|
+
throw new Error('the Vision Toolkit returned an empty description');
|
|
181
|
+
return { ok: true, block: { type: 'text', text: `${DESCRIBED_PREFIX}${answer}` } };
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
block: { type: 'text', text: `${DEGRADED_PREFIX}${messageOf(error).slice(0, 300)}.]` },
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
if (directory !== undefined) {
|
|
191
|
+
await rm(directory, { recursive: true, force: true }).catch(() => { });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Rewrite image blocks in one message list into description text blocks.
|
|
197
|
+
* The original messages are returned untouched when nothing carries an image;
|
|
198
|
+
* converted messages are new objects, so the durable request stays immutable.
|
|
199
|
+
* @param ctx - plugin context for the attachments service.
|
|
200
|
+
* @param runtime - the currently serving runtime (lazily read per conversion).
|
|
201
|
+
* @param cache - shared per-adapter description cache.
|
|
202
|
+
* @param messages - the assembled request messages.
|
|
203
|
+
* @param signal - the caller's cancellation for this conversion pass.
|
|
204
|
+
* @returns the rewritten message list.
|
|
205
|
+
*/
|
|
206
|
+
export async function convertImagesToEvidence(ctx, runtime, cache, messages, signal) {
|
|
207
|
+
const out = [];
|
|
208
|
+
for (const message of messages) {
|
|
209
|
+
if (!contentHasImage(message.content)) {
|
|
210
|
+
out.push(message);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const content = await convertBlocks(message.content, (block) => abortableWait(cache.read(String(block.attachment.attachmentId), () => readImageBlock(ctx, runtime, block)), signal));
|
|
214
|
+
out.push({ ...message, content });
|
|
215
|
+
}
|
|
216
|
+
return out;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The adapter behind one variant route: model metadata declares image input,
|
|
220
|
+
* and every stream rewrites image blocks before delegating to the upstream
|
|
221
|
+
* route through the host service (so the upstream route's own middleware,
|
|
222
|
+
* retry policy, and replay handling still apply).
|
|
223
|
+
*/
|
|
224
|
+
export class ImageInputVariantAdapter extends LlmAdapter {
|
|
225
|
+
ctx;
|
|
226
|
+
llm;
|
|
227
|
+
upstream;
|
|
228
|
+
upstreamName;
|
|
229
|
+
runtime;
|
|
230
|
+
cache;
|
|
231
|
+
lastRuntime;
|
|
232
|
+
constructor(ctx, llm, upstream, upstreamName, runtime, cache) {
|
|
233
|
+
super();
|
|
234
|
+
this.ctx = ctx;
|
|
235
|
+
this.llm = llm;
|
|
236
|
+
this.upstream = upstream;
|
|
237
|
+
this.upstreamName = upstreamName;
|
|
238
|
+
this.runtime = runtime;
|
|
239
|
+
this.cache = cache;
|
|
240
|
+
}
|
|
241
|
+
providerInfo(provider) {
|
|
242
|
+
return { id: provider, name: `${this.upstreamName}${VARIANT_SUFFIX}` };
|
|
243
|
+
}
|
|
244
|
+
async listModels(provider) {
|
|
245
|
+
const models = await this.llm.listModels(this.upstream);
|
|
246
|
+
return models.filter(shouldWrapModel).map((model) => ({
|
|
247
|
+
provider,
|
|
248
|
+
id: model.id,
|
|
249
|
+
name: `${model.name}${VARIANT_SUFFIX}`,
|
|
250
|
+
inputModalities: ['text', 'image'],
|
|
251
|
+
...(model.description === undefined ? {} : { description: model.description }),
|
|
252
|
+
}));
|
|
253
|
+
}
|
|
254
|
+
async resolveModel(provider, model, signal) {
|
|
255
|
+
const info = await this.llm.resolveModelInfo(this.upstream, model, signal);
|
|
256
|
+
if (!shouldWrapModel(info)) {
|
|
257
|
+
throw new Error(`model "${model}" is not a text-only model and needs no image-input variant`);
|
|
258
|
+
}
|
|
259
|
+
return {
|
|
260
|
+
provider,
|
|
261
|
+
id: model,
|
|
262
|
+
name: `${info.name}${VARIANT_SUFFIX}`,
|
|
263
|
+
inputModalities: ['text', 'image'],
|
|
264
|
+
...(info.description === undefined ? {} : { description: info.description }),
|
|
265
|
+
// Capability and call-default metadata rides through unchanged: the
|
|
266
|
+
// variant is a wire-only facade, so context capacity, output caps, and
|
|
267
|
+
// reasoning efforts must behave exactly like the upstream route.
|
|
268
|
+
...(info.context === undefined ? {} : { context: info.context }),
|
|
269
|
+
...(info.defaultMaxTokens === undefined ? {} : { defaultMaxTokens: info.defaultMaxTokens }),
|
|
270
|
+
...(info.reasoning === undefined ? {} : { reasoning: info.reasoning }),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
async *stream(options) {
|
|
274
|
+
// A reconfigured runtime is a NEW instance; descriptions read through the
|
|
275
|
+
// previous provider must not be replayed for the new one.
|
|
276
|
+
const current = this.runtime();
|
|
277
|
+
if (current !== this.lastRuntime) {
|
|
278
|
+
this.cache.clear();
|
|
279
|
+
this.lastRuntime = current;
|
|
280
|
+
}
|
|
281
|
+
const messages = await convertImagesToEvidence(this.ctx, this.runtime, this.cache, options.messages, options.signal);
|
|
282
|
+
// Delegate through the host service under the upstream route: the variant
|
|
283
|
+
// is a wire-only facade, and the upstream route owns retry and replay.
|
|
284
|
+
yield* this.llm.stream({ ...options, provider: this.upstream, messages });
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Whether the plugin should take a paste over for one live Session: true only
|
|
289
|
+
* when the current model is positively declared text-only. The model-selector
|
|
290
|
+
* label is the authoritative source when supplied — the Session's persisted
|
|
291
|
+
* route header only updates on a request, so a model switch would otherwise be
|
|
292
|
+
* invisible until the next turn — with a fallback to that header. Unknown
|
|
293
|
+
* routes answer false: the native attachment flow is the safe default, and a
|
|
294
|
+
* text-only model merely keeps its ordinary image-admission error.
|
|
295
|
+
* @param ctx - plugin context with `sessions` and `llm`.
|
|
296
|
+
* @param sessionId - the live Session id the paste belongs to.
|
|
297
|
+
* @param modelLabel - the model-selector label the client currently shows, if any.
|
|
298
|
+
* @returns true when pastes should become workspace paths instead of attachments.
|
|
299
|
+
*/
|
|
300
|
+
export async function sessionPasteTakeover(ctx, sessionId, modelLabel) {
|
|
301
|
+
if (modelLabel !== undefined && modelLabel.trim() !== '') {
|
|
302
|
+
const byLabel = await labelTakeoverVerdict(ctx, modelLabel);
|
|
303
|
+
if (byLabel !== undefined)
|
|
304
|
+
return byLabel;
|
|
305
|
+
}
|
|
306
|
+
return sessionHeaderTakeover(ctx, sessionId);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Resolve the takeover verdict from the Session's last requested route header.
|
|
310
|
+
* @param ctx - plugin context with `sessions` and `llm`.
|
|
311
|
+
* @param sessionId - the live Session id.
|
|
312
|
+
* @returns true when the persisted route is positively text-only.
|
|
313
|
+
*/
|
|
314
|
+
export async function sessionHeaderTakeover(ctx, sessionId) {
|
|
315
|
+
const session = ctx.sessions.get(sessionId);
|
|
316
|
+
if (session === undefined)
|
|
317
|
+
return false;
|
|
318
|
+
const routed = session.requestHeader()?.config;
|
|
319
|
+
if (routed === undefined)
|
|
320
|
+
return false;
|
|
321
|
+
const llm = ctx.get('llm');
|
|
322
|
+
if (llm === undefined)
|
|
323
|
+
return false;
|
|
324
|
+
let info;
|
|
325
|
+
try {
|
|
326
|
+
info = await llm.resolveModelInfo(routed.provider, routed.model);
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
return shouldWrapModel(info);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Resolve the takeover verdict from a model-selector label alone. Every model
|
|
335
|
+
* whose name or id appears in the label votes: any image-capable (or unknown-
|
|
336
|
+
* capability) match vetoes the takeover, and at least one positively text-only
|
|
337
|
+
* match confirms it. A route whose catalog cannot be read also vetoes — the
|
|
338
|
+
* unreadable route is exactly where an image-capable twin could hide, so a
|
|
339
|
+
* label match on a half-read catalog must not confirm a takeover. The label
|
|
340
|
+
* carries no provider id, so no picking is attempted: the answer is decisive
|
|
341
|
+
* only when the whole catalog was walkable and every match agrees.
|
|
342
|
+
* @param ctx - plugin context with the `llm` service.
|
|
343
|
+
* @param label - the selector label the browser shows.
|
|
344
|
+
* @returns true (take over), false (native), or undefined when nothing matched.
|
|
345
|
+
*/
|
|
346
|
+
export async function labelTakeoverVerdict(ctx, label) {
|
|
347
|
+
const llm = ctx.get('llm');
|
|
348
|
+
if (llm === undefined)
|
|
349
|
+
return undefined;
|
|
350
|
+
const lowered = label.toLowerCase();
|
|
351
|
+
let matchedTextOnly = false;
|
|
352
|
+
for (const provider of llm.listProviders()) {
|
|
353
|
+
let models;
|
|
354
|
+
try {
|
|
355
|
+
models = await llm.listModels(provider.id);
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
// An unreadable route cannot vote — and it is exactly where an
|
|
359
|
+
// image-capable twin could hide (a variant route probes its upstream).
|
|
360
|
+
// A label match on a half-read catalog must not confirm a takeover, so
|
|
361
|
+
// the verdict is vetoed for THIS label; the session header fallback is
|
|
362
|
+
// deliberately not used here because it may still describe a previous
|
|
363
|
+
// model after a switch. Loud, so a broken provider is diagnosable.
|
|
364
|
+
ctx.logger.warn('dsh-vision-toolkit: paste verdict could not read route "%s"; native paste wins for this label. %s', provider.id, messageOf(error).slice(0, 300));
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
for (const model of models) {
|
|
368
|
+
for (const candidate of [model.name, model.id]) {
|
|
369
|
+
if (typeof candidate !== 'string' || candidate.length === 0)
|
|
370
|
+
continue;
|
|
371
|
+
if (!lowered.includes(candidate.toLowerCase()))
|
|
372
|
+
continue;
|
|
373
|
+
if (!shouldWrapModel(model)) {
|
|
374
|
+
// An image-capable or unconfirmed model in the label keeps its
|
|
375
|
+
// native paste; the variant routes declare image input and are
|
|
376
|
+
// covered by this veto.
|
|
377
|
+
return false;
|
|
378
|
+
}
|
|
379
|
+
// Positive confirmation has a floor: one- and two-character names
|
|
380
|
+
// match label prose far too easily to identify the selected model.
|
|
381
|
+
if (candidate.length >= 3)
|
|
382
|
+
matchedTextOnly = true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return matchedTextOnly ? true : undefined;
|
|
387
|
+
}
|
|
388
|
+
/** Label-verdict cache bound, so a long-lived Web profile cannot hoard catalog walks. */
|
|
389
|
+
const LABEL_VERDICT_TTL_MS = 15_000;
|
|
390
|
+
const LABEL_VERDICT_CAP = 32;
|
|
391
|
+
/**
|
|
392
|
+
* Resolve the paste verdict for one exact model route. Image-capable (or
|
|
393
|
+
* unresolvable) routes keep the native flow; a text-only route whose
|
|
394
|
+
* image-input variant is registered gets an auto-switch instruction; a
|
|
395
|
+
* text-only route without a usable variant falls back to the path takeover.
|
|
396
|
+
* @param ctx - plugin context with the `llm` service.
|
|
397
|
+
* @param getConfig - resolves the current plugin configuration.
|
|
398
|
+
* @param selection - the exact provider/model the browser currently selects.
|
|
399
|
+
* @returns the verdict for that route.
|
|
400
|
+
*/
|
|
401
|
+
async function routePasteVerdict(ctx, getConfig, selection) {
|
|
402
|
+
const llm = ctx.get('llm');
|
|
403
|
+
if (llm === undefined)
|
|
404
|
+
return { takeOver: false };
|
|
405
|
+
let info;
|
|
406
|
+
try {
|
|
407
|
+
info = await llm.resolveModelInfo(selection.provider, selection.model);
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
// An unresolvable route keeps the native flow; the host's own admission
|
|
411
|
+
// error is the honest answer for a model that cannot take images.
|
|
412
|
+
return { takeOver: false };
|
|
413
|
+
}
|
|
414
|
+
if (!shouldWrapModel(info))
|
|
415
|
+
return { takeOver: false };
|
|
416
|
+
const variants = getConfig().imageInputVariants;
|
|
417
|
+
// Auto-switch is an opt-in refinement of the takeover: off means the
|
|
418
|
+
// text-only route keeps its ordinary path takeover.
|
|
419
|
+
if (!variants.enabled || !variants.autoSwitch)
|
|
420
|
+
return { takeOver: true };
|
|
421
|
+
const variantProvider = variantProviderId(selection.provider);
|
|
422
|
+
try {
|
|
423
|
+
if (!llm.listProviders().some(provider => provider.id === variantProvider))
|
|
424
|
+
return { takeOver: true };
|
|
425
|
+
const models = await llm.listModels(variantProvider);
|
|
426
|
+
const twin = models.find(model => model.id === selection.model);
|
|
427
|
+
// The variant only wraps text-only models, so membership confirms both
|
|
428
|
+
// the route and the wrap; anything else keeps the path takeover.
|
|
429
|
+
if (twin === undefined)
|
|
430
|
+
return { takeOver: true };
|
|
431
|
+
return {
|
|
432
|
+
takeOver: false,
|
|
433
|
+
autoSwitch: {
|
|
434
|
+
provider: variantProvider,
|
|
435
|
+
model: selection.model,
|
|
436
|
+
label: twin.name,
|
|
437
|
+
...(selection.reasoningEffort === undefined ? {} : { reasoningEffort: selection.reasoningEffort }),
|
|
438
|
+
},
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
return { takeOver: true };
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Paste-policy resolver with a short cache. The exact route is the live fact
|
|
447
|
+
* (the browser re-reads it per paste), and the host catalog only changes on
|
|
448
|
+
* topology events, so a brief cache is safe; every `llm/adapters-updated`
|
|
449
|
+
* notification empties it — including the sweep that registers a variant
|
|
450
|
+
* after the first sweep, so a stale "no variant" verdict cannot outlive the
|
|
451
|
+
* route it described.
|
|
452
|
+
* @param ctx - plugin context with the `llm` service.
|
|
453
|
+
* @param getConfig - resolves the current plugin configuration per verdict.
|
|
454
|
+
* @returns the cached verdict resolver for the Web paste-policy route.
|
|
455
|
+
*/
|
|
456
|
+
export function createPasteTakeoverResolver(ctx, getConfig) {
|
|
457
|
+
const routes = new Map();
|
|
458
|
+
const labels = new Map();
|
|
459
|
+
const trim = (map) => {
|
|
460
|
+
while (map.size > LABEL_VERDICT_CAP) {
|
|
461
|
+
const oldest = map.keys().next().value;
|
|
462
|
+
if (oldest === undefined)
|
|
463
|
+
break;
|
|
464
|
+
map.delete(oldest);
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
if (typeof ctx.on === 'function') {
|
|
468
|
+
ctx.on('llm/adapters-updated', () => {
|
|
469
|
+
routes.clear();
|
|
470
|
+
labels.clear();
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
return async (sessionId, selection, modelLabel) => {
|
|
474
|
+
if (selection !== undefined && selection.provider.trim() !== '' && selection.model.trim() !== '') {
|
|
475
|
+
const key = `route:${selection.provider}|${selection.model}`;
|
|
476
|
+
const cached = routes.get(key);
|
|
477
|
+
if (cached !== undefined && Date.now() - cached.at <= LABEL_VERDICT_TTL_MS)
|
|
478
|
+
return cached.verdict;
|
|
479
|
+
const verdict = await routePasteVerdict(ctx, getConfig, selection);
|
|
480
|
+
routes.set(key, { verdict, at: Date.now() });
|
|
481
|
+
trim(routes);
|
|
482
|
+
return verdict;
|
|
483
|
+
}
|
|
484
|
+
if (modelLabel !== undefined && modelLabel.trim() !== '') {
|
|
485
|
+
const key = `label:${modelLabel}`;
|
|
486
|
+
const cached = labels.get(key);
|
|
487
|
+
if (cached !== undefined && Date.now() - cached.at <= LABEL_VERDICT_TTL_MS) {
|
|
488
|
+
return { takeOver: cached.takeOver ?? (await sessionHeaderTakeover(ctx, sessionId)) };
|
|
489
|
+
}
|
|
490
|
+
const verdict = await labelTakeoverVerdict(ctx, modelLabel);
|
|
491
|
+
// A decisive answer AND a miss are both cached: a label that matches
|
|
492
|
+
// nothing would otherwise pay a full catalog walk on every paste.
|
|
493
|
+
labels.set(key, { takeOver: verdict, at: Date.now() });
|
|
494
|
+
trim(labels);
|
|
495
|
+
return { takeOver: verdict ?? (await sessionHeaderTakeover(ctx, sessionId)) };
|
|
496
|
+
}
|
|
497
|
+
return { takeOver: await sessionHeaderTakeover(ctx, sessionId) };
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Register and maintain one variant route per eligible upstream route. Routes
|
|
502
|
+
* that later vanish are released; routes that gain eligible models later are
|
|
503
|
+
* picked up by the next sweep (host topology notifications included).
|
|
504
|
+
* @param ctx - plugin context with the `llm` service.
|
|
505
|
+
* @param getConfig - resolves the current plugin configuration per sweep.
|
|
506
|
+
* @param getRuntime - the currently serving Vision Toolkit runtime, if ready.
|
|
507
|
+
* @returns the disposer and a manual re-sweep trigger (settings changes).
|
|
508
|
+
*/
|
|
509
|
+
export function installImageInputVariants(ctx, getConfig, getRuntime) {
|
|
510
|
+
const registrations = new Map();
|
|
511
|
+
let disposed = false;
|
|
512
|
+
// Serialize sweeps: a registration itself announces llm/adapters-updated,
|
|
513
|
+
// and two interleaved sweeps must never probe the same route concurrently.
|
|
514
|
+
let sweeping = Promise.resolve();
|
|
515
|
+
// Coalesce bursts: a sweep triggered while one is pending is one extra pass,
|
|
516
|
+
// not one per notification (a single registration emits a notification).
|
|
517
|
+
let sweepQueued = false;
|
|
518
|
+
const releaseAll = () => {
|
|
519
|
+
for (const dispose of [...registrations.values()])
|
|
520
|
+
dispose();
|
|
521
|
+
registrations.clear();
|
|
522
|
+
};
|
|
523
|
+
const sweep = () => {
|
|
524
|
+
if (sweepQueued)
|
|
525
|
+
return;
|
|
526
|
+
sweepQueued = true;
|
|
527
|
+
queueMicrotask(() => {
|
|
528
|
+
sweepQueued = false;
|
|
529
|
+
sweeping = sweeping.then(sweepOnce, sweepOnce);
|
|
530
|
+
});
|
|
531
|
+
};
|
|
532
|
+
const sweepOnce = async () => {
|
|
533
|
+
if (disposed)
|
|
534
|
+
return;
|
|
535
|
+
try {
|
|
536
|
+
const variants = getConfig().imageInputVariants;
|
|
537
|
+
if (!variants.enabled) {
|
|
538
|
+
releaseAll();
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
const llm = ctx.get('llm');
|
|
542
|
+
if (llm === undefined)
|
|
543
|
+
return;
|
|
544
|
+
const restrict = new Set(variants.providers);
|
|
545
|
+
let providers;
|
|
546
|
+
try {
|
|
547
|
+
providers = llm.listProviders();
|
|
548
|
+
}
|
|
549
|
+
catch {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
for (const provider of providers) {
|
|
553
|
+
const upstream = provider.id;
|
|
554
|
+
if (restrict.size > 0 && !restrict.has(upstream))
|
|
555
|
+
continue;
|
|
556
|
+
// Our own variant routes declare image input and are never wrapped;
|
|
557
|
+
// probing them would just re-probe their upstream route.
|
|
558
|
+
if (upstream.startsWith(VARIANT_PROVIDER_PREFIX))
|
|
559
|
+
continue;
|
|
560
|
+
let models;
|
|
561
|
+
try {
|
|
562
|
+
models = await llm.listModels(upstream);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
const eligible = models.some(shouldWrapModel);
|
|
568
|
+
const registered = registrations.has(upstream);
|
|
569
|
+
if (!eligible && registered) {
|
|
570
|
+
// The route lost its eligible models: release the stale variant.
|
|
571
|
+
const dispose = registrations.get(upstream);
|
|
572
|
+
dispose?.();
|
|
573
|
+
registrations.delete(upstream);
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (!eligible || registered)
|
|
577
|
+
continue;
|
|
578
|
+
if (disposed)
|
|
579
|
+
return;
|
|
580
|
+
try {
|
|
581
|
+
const dispose = llm.registerAdapter([variantProviderId(upstream)], new ImageInputVariantAdapter(ctx, llm, upstream, provider.name, getRuntime, new EvidenceCache(EVIDENCE_CACHE_LIMIT)));
|
|
582
|
+
registrations.set(upstream, dispose);
|
|
583
|
+
}
|
|
584
|
+
catch (error) {
|
|
585
|
+
ctx.logger.warn('dsh-vision-toolkit: image-input variant registration skipped for "%s": %s', upstream, messageOf(error));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const live = new Set(providers.map(provider => provider.id));
|
|
589
|
+
for (const [upstream, dispose] of [...registrations]) {
|
|
590
|
+
// A wrapper is released when its upstream route vanished OR the
|
|
591
|
+
// current configuration no longer allows that route (restrict
|
|
592
|
+
// narrowing must not leave stale variants behind).
|
|
593
|
+
if (!live.has(upstream) || (restrict.size > 0 && !restrict.has(upstream))) {
|
|
594
|
+
dispose();
|
|
595
|
+
registrations.delete(upstream);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
catch (error) {
|
|
600
|
+
ctx.logger.warn('dsh-vision-toolkit: image-input variant sweep failed: %s', messageOf(error));
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
if (typeof ctx.on === 'function') {
|
|
604
|
+
ctx.on('llm/adapters-updated', () => { sweep(); });
|
|
605
|
+
}
|
|
606
|
+
sweep();
|
|
607
|
+
return {
|
|
608
|
+
dispose: () => {
|
|
609
|
+
disposed = true;
|
|
610
|
+
releaseAll();
|
|
611
|
+
},
|
|
612
|
+
reconcile: () => { sweep(); },
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
//# sourceMappingURL=image-input-variants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-input-variants.js","sourceRoot":"","sources":["../src/image-input-variants.ts"],"names":[],"mappings":"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"}
|