feat: complete evidence restructuring worktree
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
import { createAssistantMessageEventStream, streamSimpleOpenAICompletions } from "@earendil-works/pi-ai";
|
||||
|
||||
function convertThinkingBlocks(message) {
|
||||
return {
|
||||
...message,
|
||||
content: (message.content ?? []).map((block) => {
|
||||
if (block?.type !== "thinking") return block;
|
||||
return { type: "text", text: block.thinking ?? "" };
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function convertEvent(event) {
|
||||
if (event.type === "thinking_start") {
|
||||
return { type: "text_start", contentIndex: event.contentIndex, partial: convertThinkingBlocks(event.partial) };
|
||||
}
|
||||
if (event.type === "thinking_delta") {
|
||||
return { type: "text_delta", contentIndex: event.contentIndex, delta: event.delta, partial: convertThinkingBlocks(event.partial) };
|
||||
}
|
||||
if (event.type === "thinking_end") {
|
||||
return { type: "text_end", contentIndex: event.contentIndex, content: event.content, partial: convertThinkingBlocks(event.partial) };
|
||||
}
|
||||
if (event.type === "done") {
|
||||
return { ...event, message: convertThinkingBlocks(event.message) };
|
||||
}
|
||||
if (event.type === "error") {
|
||||
return { ...event, error: convertThinkingBlocks(event.error) };
|
||||
}
|
||||
if (event.partial) {
|
||||
return { ...event, partial: convertThinkingBlocks(event.partial) };
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
function streamAritmolab(model, context, options) {
|
||||
const source = streamSimpleOpenAICompletions(model, context, options);
|
||||
const stream = createAssistantMessageEventStream();
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
for await (const event of source) {
|
||||
stream.push(convertEvent(event));
|
||||
}
|
||||
} catch (error) {
|
||||
const message = {
|
||||
role: "assistant",
|
||||
content: [],
|
||||
api: model.api,
|
||||
provider: model.provider,
|
||||
model: model.id,
|
||||
usage: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
totalTokens: 0,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
||||
},
|
||||
stopReason: options?.signal?.aborted ? "aborted" : "error",
|
||||
errorMessage: error instanceof Error ? error.message : String(error),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
stream.push({ type: "error", reason: message.stopReason, error: message });
|
||||
stream.end();
|
||||
}
|
||||
})();
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
export default function (pi) {
|
||||
pi.registerProvider("aritmolab", {
|
||||
name: "AritmoLab",
|
||||
baseUrl: "https://ml-aritmolab.policlinicosandonato.it/v1",
|
||||
apiKey: "aritmolab",
|
||||
api: "openai-completions",
|
||||
streamSimple: streamAritmolab,
|
||||
models: [
|
||||
{
|
||||
id: "qwen3.6-35b-a3b",
|
||||
name: "AritmoLab Qwen3.6 35B A3B",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 131072,
|
||||
maxTokens: 16384,
|
||||
compat: {
|
||||
supportsDeveloperRole: false,
|
||||
supportsReasoningEffort: false,
|
||||
supportsStore: false,
|
||||
maxTokensField: "max_tokens",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert");
|
||||
const crypto = require("node:crypto");
|
||||
const cp = require("node:child_process");
|
||||
const fs = require("node:fs");
|
||||
const { createRequire } = require("node:module");
|
||||
@@ -125,17 +124,26 @@ function stripDescriptions(value, insideProperties = false) {
|
||||
return value;
|
||||
}
|
||||
|
||||
test("the injected skill stays byte-identical during extraction", () => {
|
||||
test("before_agent_start injects the canonical skill byte-for-byte", async () => {
|
||||
const harnessRoot = path.resolve(__dirname, "..", "..", "..", "..");
|
||||
const digest = (relativePath) => crypto
|
||||
.createHash("sha256")
|
||||
.update(fs.readFileSync(path.join(harnessRoot, relativePath)))
|
||||
.digest("hex");
|
||||
|
||||
assert.equal(
|
||||
digest(path.join(".pi", "skills", "tht-sessione", "SKILL.md")),
|
||||
"626a794071c095a4f20fffabb3bab901f05c101590adbdc58e45adfae56f3219",
|
||||
const canonicalSkill = fs.readFileSync(
|
||||
path.join(harnessRoot, ".pi", "skills", "tht-sessione", "SKILL.md"),
|
||||
"utf8",
|
||||
);
|
||||
const { pi } = createFakePi();
|
||||
installGate(pi);
|
||||
|
||||
await pi.emit("input", { source: "rpc", text: '/nuova-domanda "x"' });
|
||||
const injected = await pi.emit("before_agent_start", { systemPrompt: "BASE" });
|
||||
const systemPrompt = injected?.systemPrompt ?? "";
|
||||
const opening = "<tht-sessione-skill>\n";
|
||||
const closing = "\n</tht-sessione-skill>";
|
||||
const start = systemPrompt.indexOf(opening);
|
||||
const end = systemPrompt.indexOf(closing, start + opening.length);
|
||||
|
||||
assert.notEqual(start, -1);
|
||||
assert.notEqual(end, -1);
|
||||
assert.equal(systemPrompt.slice(start + opening.length, end), canonicalSkill);
|
||||
});
|
||||
|
||||
test("F1 persists a concrete clarification directly from the select widget", async () => {
|
||||
|
||||
Reference in New Issue
Block a user