fix: restore model activity reasoning stream
This commit is contained in:
@@ -3,6 +3,7 @@ import type { RpcClient } from "../rpc/rpc-client.js";
|
||||
export type ClientEvent =
|
||||
| { type: "ui_request"; ui_request: any }
|
||||
| { type: "text_delta"; text: string }
|
||||
| { type: "activity_delta"; text: string }
|
||||
| { type: "info"; [k: string]: any }
|
||||
| { type: "system_event"; [k: string]: any };
|
||||
|
||||
@@ -27,6 +28,8 @@ export class SessionBridge {
|
||||
this.fan({ type: "info", level: m.notifyType ?? "info", text: m.message ?? "" });
|
||||
} else if (m.type === "message_update" && m.assistantMessageEvent?.type === "text_delta") {
|
||||
this.fan({ type: "text_delta", text: m.assistantMessageEvent.delta ?? "" });
|
||||
} else if (m.type === "message_update" && m.assistantMessageEvent?.type === "thinking_delta") {
|
||||
this.fan({ type: "activity_delta", text: m.assistantMessageEvent.delta ?? "" });
|
||||
} else if (m.type === "text_delta") {
|
||||
this.fan({ type: "text_delta", text: m.text ?? "" });
|
||||
// tool_execution_* events are intentionally NOT forwarded: they clutter
|
||||
|
||||
@@ -69,8 +69,7 @@ export function sessionRoutes(
|
||||
const options = {
|
||||
provider: s.provider,
|
||||
model: s.model,
|
||||
// Keep the saved preference in the manifest; F1 starts tool-first.
|
||||
thinking: "off",
|
||||
thinking: s.thinking,
|
||||
author: getUser(req).id,
|
||||
question: b.question,
|
||||
};
|
||||
@@ -117,9 +116,7 @@ export function sessionRoutes(
|
||||
const options = {
|
||||
provider: saved?.provider,
|
||||
model: saved?.model,
|
||||
// Phase 1 must reach a widget instead of exposing a long reasoning trace.
|
||||
// The session keeps its saved preference for later turns.
|
||||
thinking: "off",
|
||||
thinking: saved?.thinking ?? settings.thinking,
|
||||
author: getUser(req).id,
|
||||
mode: "resume" as const,
|
||||
};
|
||||
|
||||
@@ -47,6 +47,65 @@ test("POST /sessions usa i settings (workspace/provider/model/thinking) e crea+a
|
||||
unlinkSync(modelKey);
|
||||
});
|
||||
|
||||
test("POST /sessions configura Pi con il thinking globale selezionato", async () => {
|
||||
let configured: any;
|
||||
const bridge = { onClientEvent: () => {}, emitClientEvent: () => {} };
|
||||
const runtime = { bridge } as any;
|
||||
const mgr = {
|
||||
createFor: () => runtime,
|
||||
configure: async (_rt: any, options: any) => { configured = options; },
|
||||
start: () => {},
|
||||
teardown: () => {},
|
||||
} as any;
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
mgr,
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: true }),
|
||||
searchPack: async () => {},
|
||||
sessionNew: async () => ({ id: "s-thinking" }),
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd", provider: "zai", model: "glm-5.2", thinking: "high" }) as any,
|
||||
});
|
||||
|
||||
await app.inject({ method: "POST", url: "/sessions", payload: { question: "q" } });
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
|
||||
expect(configured.thinking).toBe("high");
|
||||
});
|
||||
|
||||
test("POST /sessions/:id/resume configura Pi con il thinking persistito", async () => {
|
||||
let configured: any;
|
||||
const bridge = { onClientEvent: () => {}, emitClientEvent: () => {} };
|
||||
const runtime = { bridge } as any;
|
||||
const mgr = {
|
||||
get: () => undefined,
|
||||
createFor: () => runtime,
|
||||
configure: async (_rt: any, options: any) => { configured = options; },
|
||||
start: () => {},
|
||||
teardown: () => {},
|
||||
} as any;
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
mgr,
|
||||
thtRunner: {
|
||||
ollamaEnsure: async () => ({ ok: true }),
|
||||
sessionShow: async () => ({
|
||||
status: "open",
|
||||
archived: false,
|
||||
provider: "zai",
|
||||
model: "glm-5.2",
|
||||
thinking: "medium",
|
||||
}),
|
||||
reopenSession: async () => {},
|
||||
} as any,
|
||||
getSettings: () => ({ workspace: "psd", thinking: "low" }) as any,
|
||||
});
|
||||
|
||||
await app.inject({ method: "POST", url: "/sessions/s-thinking/resume" });
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
|
||||
expect(configured.thinking).toBe("medium");
|
||||
});
|
||||
|
||||
test("POST /sessions/:id/response inoltra al bridge (no error)", async () => {
|
||||
const app = buildApp(loadConfig({ THT_HARNESS_DIR: "../harness" }), {
|
||||
thtRunner: {
|
||||
|
||||
@@ -28,6 +28,20 @@ test("real Pi message_update (assistantMessageEvent text_delta) becomes a text_d
|
||||
expect(seen).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("real Pi thinking_delta becomes a dedicated activity_delta to the FE", () => {
|
||||
const { rpc, fire } = fakeRpc();
|
||||
const b = new SessionBridge(rpc);
|
||||
const seen: any[] = [];
|
||||
b.onClientEvent((e) => seen.push(e));
|
||||
|
||||
fire({
|
||||
type: "message_update",
|
||||
assistantMessageEvent: { type: "thinking_delta", contentIndex: 0, delta: "Valuto le ambiguità" },
|
||||
});
|
||||
|
||||
expect(seen).toEqual([{ type: "activity_delta", text: "Valuto le ambiguità" }]);
|
||||
});
|
||||
|
||||
test("extension_ui_request nativo (method:input, title=json) diventa ui_request col descriptor ed è il pendente", () => {
|
||||
const { rpc, fire } = fakeRpc();
|
||||
const b = new SessionBridge(rpc);
|
||||
|
||||
Reference in New Issue
Block a user