@koda-sl/baker-bridge 0.143.0 → 0.145.0-dev.5f3658e72
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.
|
@@ -2121,6 +2121,61 @@ describe("BridgeJobExecutor", () => {
|
|
|
2121
2121
|
await inactiveExecutor.execute({ threadId: "thread_inactive_close", turnId: "turn_inactive_close", prompt: "Stop", history: history([]) }, inactiveControls);
|
|
2122
2122
|
expect(inactiveCloseCalls).toEqual(["close"]);
|
|
2123
2123
|
});
|
|
2124
|
+
// BAKER-1025 (AskUserQuestion), BAKER-502 (the report held behind it), BAKER-2215
|
|
2125
|
+
// (request_tag_input), and the ExitPlanMode and request_connection sightings: each held
|
|
2126
|
+
// the turn ~900 s before the same deny, although the card stays up and a later answer
|
|
2127
|
+
// resumes the chat as a new turn anyway.
|
|
2128
|
+
it.each([
|
|
2129
|
+
{ toolName: "AskUserQuestion", input: { questions: [{ question: "Which budget?" }] }, planMode: false },
|
|
2130
|
+
{ toolName: "ExitPlanMode", input: { plan: "Draft flow" }, planMode: true },
|
|
2131
|
+
{
|
|
2132
|
+
toolName: "mcp__baker_ui__request_tag_input",
|
|
2133
|
+
input: { changes: [{ mode: "create", tagType: "clarity" }] },
|
|
2134
|
+
planMode: false,
|
|
2135
|
+
},
|
|
2136
|
+
{
|
|
2137
|
+
toolName: CONNECTION_INPUT_TOOL_NAME,
|
|
2138
|
+
input: { connections: [{ platform: "hubspot", reason: "Send leads to HubSpot" }] },
|
|
2139
|
+
planMode: false,
|
|
2140
|
+
},
|
|
2141
|
+
])("releases the turn within a minute when $toolName goes unanswered", async ({ toolName, input, planMode }) => {
|
|
2142
|
+
vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "setInterval", "clearInterval"] });
|
|
2143
|
+
try {
|
|
2144
|
+
let guardResult;
|
|
2145
|
+
let reachedTool = () => undefined;
|
|
2146
|
+
const toolReached = new Promise((resolve) => {
|
|
2147
|
+
reachedTool = resolve;
|
|
2148
|
+
});
|
|
2149
|
+
const executor = new BridgeJobExecutor({
|
|
2150
|
+
sdk: {
|
|
2151
|
+
query: (queryInput) => ({
|
|
2152
|
+
async *[Symbol.asyncIterator]() {
|
|
2153
|
+
reachedTool();
|
|
2154
|
+
guardResult = await queryInput.options.canUseTool?.(toolName, input, {
|
|
2155
|
+
toolUseID: "tool_unanswered",
|
|
2156
|
+
requestId: "req_unanswered",
|
|
2157
|
+
signal: queryInput.options.abortController?.signal ?? new AbortController().signal,
|
|
2158
|
+
});
|
|
2159
|
+
yield resultMessage(0, "session_unanswered");
|
|
2160
|
+
},
|
|
2161
|
+
}),
|
|
2162
|
+
},
|
|
2163
|
+
model: "claude-test",
|
|
2164
|
+
sessionStore: { load: async () => undefined, save: async () => undefined, clear: async () => undefined },
|
|
2165
|
+
relay: recordingRelay(),
|
|
2166
|
+
});
|
|
2167
|
+
const controls = activeControls();
|
|
2168
|
+
const outcome = executor.execute({ threadId: "thread_unanswered", turnId: "turn_unanswered", prompt: "Ask first", planMode }, controls);
|
|
2169
|
+
await toolReached;
|
|
2170
|
+
await vi.advanceTimersByTimeAsync(59_000);
|
|
2171
|
+
expect(guardResult).toMatchObject({ behavior: "deny", message: expect.stringContaining("has not answered") });
|
|
2172
|
+
await vi.runOnlyPendingTimersAsync();
|
|
2173
|
+
await outcome;
|
|
2174
|
+
}
|
|
2175
|
+
finally {
|
|
2176
|
+
vi.useRealTimers();
|
|
2177
|
+
}
|
|
2178
|
+
});
|
|
2124
2179
|
it("denies an unanswered AskUserQuestion gracefully instead of erroring the turn", async () => {
|
|
2125
2180
|
const relay = recordingRelay();
|
|
2126
2181
|
let inputResolvedCalls = 0;
|
|
@@ -2157,6 +2212,9 @@ describe("BridgeJobExecutor", () => {
|
|
|
2157
2212
|
// cleanly so the user can answer with a normal message later.
|
|
2158
2213
|
expect(guardResult).toMatchObject({ behavior: "deny" });
|
|
2159
2214
|
expect(guardResult.message).toContain("has not answered");
|
|
2215
|
+
// BAKER-245: the card stays on screen, so a closing note that restated it made the
|
|
2216
|
+
// marketer read the same question three times (prose, card, prose).
|
|
2217
|
+
expect(guardResult.message).toMatch(/do not repeat the question/i);
|
|
2160
2218
|
expect(outcome).toMatchObject({ kind: "completed", costUsd: 0, model: "claude-test" });
|
|
2161
2219
|
expect(controls.pendingQuestions.size).toBe(0);
|
|
2162
2220
|
// The backend's pending question must SURVIVE the live wait ending: the
|