chore: upgrade pi dependencies to 0.84.1
This commit is contained in:
@@ -19,6 +19,7 @@ test("selectExtractionModel uses first configured model with auth", async () =>
|
||||
const result = await selectExtractionModel(
|
||||
{
|
||||
model: model("fallback", "c"),
|
||||
scopedModels: [],
|
||||
modelRegistry: {
|
||||
find(provider: string, _id: string) {
|
||||
if (provider === "missing") {
|
||||
@@ -44,11 +45,55 @@ test("selectExtractionModel uses first configured model with auth", async () =>
|
||||
|
||||
assert.deepEqual(result, {
|
||||
model: second,
|
||||
auth: { ok: true, apiKey: "key" },
|
||||
usedFallback: false,
|
||||
});
|
||||
});
|
||||
|
||||
test("selectExtractionModel respects the current session model scope", async () => {
|
||||
const configured = model("configured", "a");
|
||||
const fallback = model("fallback", "b");
|
||||
const result = await selectExtractionModel(
|
||||
{
|
||||
model: fallback,
|
||||
scopedModels: [{ model: fallback }],
|
||||
modelRegistry: {
|
||||
find() {
|
||||
return configured;
|
||||
},
|
||||
getApiKeyAndHeaders() {
|
||||
return Promise.resolve({ ok: true, apiKey: "key" });
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
[{ provider: "configured", id: "a" }]
|
||||
);
|
||||
|
||||
assert.deepEqual(result, {
|
||||
model: fallback,
|
||||
usedFallback: true,
|
||||
});
|
||||
});
|
||||
|
||||
test("selectExtractionModel rejects a fallback outside the current session scope", async () => {
|
||||
const fallback = model("fallback", "a");
|
||||
const result = await selectExtractionModel(
|
||||
{
|
||||
model: fallback,
|
||||
scopedModels: [{ model: model("allowed", "b") }],
|
||||
modelRegistry: {
|
||||
find() {
|
||||
return;
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
[]
|
||||
);
|
||||
|
||||
assert.deepEqual(result, {
|
||||
error: "No available extraction model in the current session model scope.",
|
||||
});
|
||||
});
|
||||
|
||||
test("extraction business rules flag option spam", () => {
|
||||
const issues = collectExtractionBusinessIssues({
|
||||
questions: [
|
||||
@@ -111,6 +156,7 @@ test("selectExtractionModel validates fallback model auth", async () => {
|
||||
const result = await selectExtractionModel(
|
||||
{
|
||||
model: fallback,
|
||||
scopedModels: [],
|
||||
modelRegistry: {
|
||||
find() {
|
||||
return;
|
||||
|
||||
@@ -85,6 +85,7 @@ test("branch payload lookup ignores invalid stored payloads", () => {
|
||||
const result = findLatestPayloadInCurrentBranch(
|
||||
ctx([
|
||||
custom({ version: 1, source: "tool", params: { questions: [] } }),
|
||||
custom({ version: 1, source: "tool", params: {} }),
|
||||
custom({ version: 1, source: "answer-extraction", params }),
|
||||
]),
|
||||
"tool"
|
||||
|
||||
+37
-36
@@ -1,9 +1,8 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { validateToolArguments } from "@earendil-works/pi-ai/base";
|
||||
import { Value } from "typebox/value";
|
||||
import { registerAskTool } from "../src/ask-tool.ts";
|
||||
import { AskOptionSchema } from "../src/schema.ts";
|
||||
import { AskOptionSchema, AskParamsSchema } from "../src/schema.ts";
|
||||
import type { AskParams } from "../src/types.ts";
|
||||
|
||||
const NON_INTERACTIVE_MESSAGE_RE =
|
||||
@@ -17,7 +16,6 @@ const PREVIEW_RULE_RE =
|
||||
/questions\[0\]\.options\[0\]\.preview: Question 1, option 1: preview questions require preview text for every option; add preview text or use type "single" instead/;
|
||||
const MISSING_OPTION_VALUE_RE =
|
||||
/questions\[0\]\.options\[0\]\.value: Question 1, option 1: value is required/;
|
||||
const MISSING_OPTION_LABEL_RE = /label/;
|
||||
const EMPTY_QUESTIONS_RE = /questions: At least one question is required/;
|
||||
const INVALID_TYPE_RE =
|
||||
/questions\[0\]\.type: Question 1: invalid type "grid"; expected "single", "multi", or "preview"/;
|
||||
@@ -96,6 +94,22 @@ test("ask option schema and tool guidance support grounded recommendations", ()
|
||||
);
|
||||
});
|
||||
|
||||
test("ask params schema constrains question types", () => {
|
||||
assert.equal(
|
||||
Value.Check(AskParamsSchema, {
|
||||
questions: [
|
||||
{
|
||||
id: "layout",
|
||||
prompt: "Choose a layout",
|
||||
type: "grid",
|
||||
options: [{ value: "compact", label: "Compact" }],
|
||||
},
|
||||
],
|
||||
}),
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
test("ask tool stores valid payloads as soon as they are called", async () => {
|
||||
const { entries, tool } = registerMockTool();
|
||||
const params = sampleParams();
|
||||
@@ -357,29 +371,25 @@ test("ask tool reports preview validation with structured issues", async () => {
|
||||
|
||||
test("ask tool accepts blank optional presentation fields", async () => {
|
||||
const { tool } = registerMockTool();
|
||||
const params = validateToolArguments(tool as never, {
|
||||
type: "toolCall",
|
||||
id: "call-blank-optionals",
|
||||
name: "ask_user",
|
||||
arguments: {
|
||||
title: " ",
|
||||
questions: [
|
||||
{
|
||||
id: "scope",
|
||||
label: " ",
|
||||
prompt: "Pick scope",
|
||||
options: [
|
||||
{
|
||||
value: "small",
|
||||
label: "Small",
|
||||
description: " ",
|
||||
preview: "\t",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}) as AskParams;
|
||||
const params: AskParams = {
|
||||
title: " ",
|
||||
questions: [
|
||||
{
|
||||
id: "scope",
|
||||
label: " ",
|
||||
prompt: "Pick scope",
|
||||
options: [
|
||||
{
|
||||
value: "small",
|
||||
label: "Small",
|
||||
description: " ",
|
||||
preview: "\t",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
assert.equal(Value.Check(AskParamsSchema, params), true);
|
||||
const result = await tool.execute(
|
||||
"call-blank-optionals",
|
||||
params,
|
||||
@@ -446,16 +456,7 @@ test("public schema requires semantic identifiers and labels", () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
assert.throws(
|
||||
() =>
|
||||
validateToolArguments(tool as never, {
|
||||
type: "toolCall",
|
||||
id: "call-missing-label",
|
||||
name: "ask_user",
|
||||
arguments: missingLabel,
|
||||
}),
|
||||
MISSING_OPTION_LABEL_RE
|
||||
);
|
||||
assert.equal(Value.Check(AskParamsSchema, missingLabel), false);
|
||||
});
|
||||
|
||||
test("ask tool transcript renderers summarize call and cancelled result", () => {
|
||||
|
||||
@@ -82,7 +82,7 @@ function toolResult(toolCallId: string) {
|
||||
|
||||
function storedPayload(
|
||||
sourceEntryId: string,
|
||||
storedParams: AskParams = params,
|
||||
storedParams: unknown = params,
|
||||
version = 1
|
||||
) {
|
||||
return {
|
||||
@@ -185,12 +185,22 @@ test("pending ask scan validates recorded arguments as payload fallback", () =>
|
||||
),
|
||||
{ params, toolCallId: "call-2" }
|
||||
);
|
||||
assert.deepEqual(
|
||||
findPendingAskToolCall(
|
||||
scannerContext([askToolCall("call-3"), storedPayload("call-3", {})])
|
||||
),
|
||||
{ params, toolCallId: "call-3" }
|
||||
);
|
||||
assert.equal(
|
||||
findPendingAskToolCall(
|
||||
scannerContext([askToolCall("call-3", { questions: [] })])
|
||||
scannerContext([askToolCall("call-4", { questions: [] })])
|
||||
),
|
||||
undefined
|
||||
);
|
||||
assert.equal(
|
||||
findPendingAskToolCall(scannerContext([askToolCall("call-5", {})])),
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
test("pending ask scan skips a newer invalid call for an older valid call", () => {
|
||||
|
||||
@@ -343,7 +343,14 @@ test("question-note-only results still render note content", () => {
|
||||
},
|
||||
};
|
||||
|
||||
assert.equal(renderResultText(result), " note: Prefer incremental changes");
|
||||
assert.equal(
|
||||
renderResultText(result),
|
||||
"? Scope: (no answer)\n note: Prefer incremental changes"
|
||||
);
|
||||
assert.equal(
|
||||
summarizeResult(result),
|
||||
"Scope: (no answer)\nScope note: Prefer incremental changes"
|
||||
);
|
||||
});
|
||||
|
||||
test("elaborate results include unselected notes in summary and render output", () => {
|
||||
|
||||
Reference in New Issue
Block a user