dsh-vision-fallback 0.5.0 → 0.6.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/lib/index.js +7 -4
- package/package.json +1 -1
- package/test/vision-fallback.test.mjs +46 -0
package/lib/index.js
CHANGED
|
@@ -449,13 +449,16 @@ class ReplacementCoordinator {
|
|
|
449
449
|
replacements = new Map();
|
|
450
450
|
this.pending.set(session, replacements);
|
|
451
451
|
}
|
|
452
|
+
const activeMessageIds = new Set(originalMessages.map((message) => message.id));
|
|
453
|
+
for (const messageId of replacements.keys()) {
|
|
454
|
+
if (!activeMessageIds.has(messageId)) replacements.delete(messageId);
|
|
455
|
+
}
|
|
452
456
|
for (let index = 0; index < originalMessages.length; index += 1) {
|
|
453
457
|
const original = originalMessages[index];
|
|
454
458
|
const rewritten = rewrittenMessages[index];
|
|
455
459
|
if (original === rewritten || !contentHasImage(original.content ?? [])) continue;
|
|
456
460
|
replacements.set(original.id, rewritten);
|
|
457
461
|
}
|
|
458
|
-
if (replacements.size > 128) replacements.clear();
|
|
459
462
|
}
|
|
460
463
|
|
|
461
464
|
onSessionEvent(session, event) {
|
|
@@ -512,9 +515,9 @@ function apply(ctx, config) {
|
|
|
512
515
|
ctx.on("agent/pre-step", async ({ agent, signal }, next) => {
|
|
513
516
|
const decision = await next();
|
|
514
517
|
if (decision.kind === "reject" || signal.aborted) return decision;
|
|
515
|
-
const
|
|
516
|
-
const rewritten = await controller.preprocess(
|
|
517
|
-
replacements.stage(agent.session,
|
|
518
|
+
const modelMessages = [...agent.session.deriveMessages(), ...decision.messages];
|
|
519
|
+
const rewritten = await controller.preprocess(modelMessages, modelMessages, signal);
|
|
520
|
+
replacements.stage(agent.session, modelMessages, rewritten);
|
|
518
521
|
return decision;
|
|
519
522
|
});
|
|
520
523
|
|
package/package.json
CHANGED
|
@@ -198,6 +198,52 @@ test("surface replacement 事件不会再次触发替换", async () => {
|
|
|
198
198
|
assert.deepEqual(appends[0].options.surfaceOp, { op: "replace", start: 12, end: 12 });
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
+
test("历史工具结果中的图片只以文字形式进入模型视图", async () => {
|
|
202
|
+
const originalFetch = globalThis.fetch;
|
|
203
|
+
globalThis.fetch = async () => ({
|
|
204
|
+
ok: true,
|
|
205
|
+
json: async () => ({ choices: [{ message: { content: "这是主题插件的界面截图" } }] })
|
|
206
|
+
});
|
|
207
|
+
const historicalToolResult = userMessage("tool-result-1", [{
|
|
208
|
+
type: "tool-result",
|
|
209
|
+
toolCallId: "read-image-1",
|
|
210
|
+
content: [
|
|
211
|
+
{ type: "text", text: "图片读取成功" },
|
|
212
|
+
{ type: "image", attachment }
|
|
213
|
+
],
|
|
214
|
+
isError: false
|
|
215
|
+
}]);
|
|
216
|
+
const current = userMessage("u2", [{ type: "text", text: "这是什么插件?" }]);
|
|
217
|
+
const surface = [historicalToolResult];
|
|
218
|
+
const session = {
|
|
219
|
+
deriveMessages: () => surface,
|
|
220
|
+
append() {
|
|
221
|
+
throw new Error("历史消息投影不应改写界面事件");
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
const controller = new VisionFallbackController(createServiceContext(), () => config);
|
|
225
|
+
const coordinator = new ReplacementCoordinator({ error() {} });
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const modelMessages = [...session.deriveMessages(), current];
|
|
229
|
+
const rewritten = await controller.preprocess(modelMessages, modelMessages);
|
|
230
|
+
coordinator.stage(session, modelMessages, rewritten);
|
|
231
|
+
|
|
232
|
+
const projected = session.deriveMessages();
|
|
233
|
+
assert.equal(projected.length, 1);
|
|
234
|
+
assert.equal(projected[0].id, historicalToolResult.id);
|
|
235
|
+
assert.equal(projected[0].content[0].type, "tool-result");
|
|
236
|
+
assert.equal(projected[0].content[0].content[1].type, "text");
|
|
237
|
+
assert.match(projected[0].content[0].content[1].text, /这是主题插件的界面截图/);
|
|
238
|
+
assert.equal(JSON.stringify(projected).includes('"type":"image"'), false);
|
|
239
|
+
assert.equal(surface[0], historicalToolResult);
|
|
240
|
+
assert.equal(surface[0].content[0].content[1].type, "image");
|
|
241
|
+
} finally {
|
|
242
|
+
coordinator.dispose();
|
|
243
|
+
globalThis.fetch = originalFetch;
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
201
247
|
test("图片能力覆盖可随开关变化并能恢复", async () => {
|
|
202
248
|
let current = config;
|
|
203
249
|
const original = async (provider, model) => ({
|