@frockbot/kernel-do 0.3.38 → 0.3.40
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frockbot/kernel-do",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.40",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@frockbot/kernel-composition": "0.3.
|
|
16
|
-
"@frockbot/kernel-contracts": "0.3.
|
|
15
|
+
"@frockbot/kernel-composition": "0.3.40",
|
|
16
|
+
"@frockbot/kernel-contracts": "0.3.40",
|
|
17
17
|
"cordis": "4.0.0-rc.8"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
package/src/authority.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// detail here; everything above them is Package policy behind narrow hooks.
|
|
6
6
|
import {
|
|
7
7
|
decodeSessionEvent,
|
|
8
|
+
validateToolOccurrenceJournal,
|
|
8
9
|
type NormalizedModelRequest,
|
|
9
10
|
type SessionEvent,
|
|
10
11
|
} from "@frockbot/kernel-contracts";
|
|
@@ -1982,7 +1983,14 @@ export class BotDurableAuthority<Snapshot> {
|
|
|
1982
1983
|
): Promise<BotTurnCompletion | undefined> {
|
|
1983
1984
|
const provider = latestModelRequestProviderV1(events);
|
|
1984
1985
|
const reconciles = this.hooks.providerReconciles ?? (() => true);
|
|
1985
|
-
|
|
1986
|
+
// A model's retrieval policy says nothing about an unresolved tool effect.
|
|
1987
|
+
// Preserve its intent for the tool reconciliation path (ADR 0028).
|
|
1988
|
+
const unresolvedTool =
|
|
1989
|
+
events.some((event) => event.type === "tool/call") &&
|
|
1990
|
+
[...validateToolOccurrenceJournal(events).values()].some(
|
|
1991
|
+
(entry) => entry.intent && !entry.result,
|
|
1992
|
+
);
|
|
1993
|
+
if (unresolvedTool || provider === undefined || reconciles(provider)) {
|
|
1986
1994
|
await this.requireRunReconciliation(runId, previous, events, reason);
|
|
1987
1995
|
return undefined;
|
|
1988
1996
|
}
|
|
@@ -77,7 +77,11 @@ function command(runId: string, text: string): OwnedBotTurnCommand {
|
|
|
77
77
|
function createAuthority(
|
|
78
78
|
storage: MemoryStorage,
|
|
79
79
|
provider: string,
|
|
80
|
-
options: {
|
|
80
|
+
options: {
|
|
81
|
+
providerReconciles?: boolean;
|
|
82
|
+
refuseWith?: string;
|
|
83
|
+
toolEffect?: boolean;
|
|
84
|
+
} = {},
|
|
81
85
|
): BotDurableAuthority<undefined> {
|
|
82
86
|
const hooks: BotDurableAuthorityHooks<undefined> = {
|
|
83
87
|
resolveAdmissionSnapshot: () => Promise.resolve(undefined),
|
|
@@ -164,6 +168,30 @@ function createAuthority(
|
|
|
164
168
|
appended,
|
|
165
169
|
);
|
|
166
170
|
}
|
|
171
|
+
if (options.toolEffect) {
|
|
172
|
+
await persist(
|
|
173
|
+
{
|
|
174
|
+
type: "assistant/message",
|
|
175
|
+
turn: 1,
|
|
176
|
+
step: 1,
|
|
177
|
+
requestId: "request-1",
|
|
178
|
+
text: "",
|
|
179
|
+
toolCalls: [{ id: "call-one", name: "external_action", input: {} }],
|
|
180
|
+
} as never,
|
|
181
|
+
{
|
|
182
|
+
type: "tool/call",
|
|
183
|
+
turn: 1,
|
|
184
|
+
step: 1,
|
|
185
|
+
occurrenceId: "tool:1:1:0",
|
|
186
|
+
name: "external_action",
|
|
187
|
+
input: {},
|
|
188
|
+
} as never,
|
|
189
|
+
);
|
|
190
|
+
throw new BotTurnReconciliationRequiredError(
|
|
191
|
+
"Tool effect outcome is unknown",
|
|
192
|
+
appended,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
167
195
|
const reason = `Model response outcome is uncertain: ${MODEL_FIRST_BYTE_DEADLINE_REASON_V1}`;
|
|
168
196
|
await persist({
|
|
169
197
|
type: "model/reconciliation-required",
|
|
@@ -263,3 +291,26 @@ describe("a model request that ran out of time", () => {
|
|
|
263
291
|
expect(storage.values.get("active-run")).toBeUndefined();
|
|
264
292
|
});
|
|
265
293
|
});
|
|
294
|
+
|
|
295
|
+
test("a non-retrieving model never terminalizes an unresolved tool effect", async () => {
|
|
296
|
+
const storage = new MemoryStorage();
|
|
297
|
+
const authority = createAuthority(storage, "flock-ai", { toolEffect: true });
|
|
298
|
+
await expect(
|
|
299
|
+
authority.run(command("run-tool", "perform an action")),
|
|
300
|
+
).rejects.toThrow();
|
|
301
|
+
const run = await storedRun(authority, "run-tool");
|
|
302
|
+
expect(run.status).toBe("reconciliation-required");
|
|
303
|
+
expect(
|
|
304
|
+
run.events.some(
|
|
305
|
+
(event) => event.type === "tool/result" || event.type === "turn/end",
|
|
306
|
+
),
|
|
307
|
+
).toBe(false);
|
|
308
|
+
expect(storage.values.get("active-run")).toBe("run-tool");
|
|
309
|
+
const reconstructed = createAuthority(storage, "flock-ai", {
|
|
310
|
+
toolEffect: true,
|
|
311
|
+
});
|
|
312
|
+
await reconstructed.recoverActiveRun();
|
|
313
|
+
expect((await storedRun(reconstructed, "run-tool")).status).toBe(
|
|
314
|
+
"reconciliation-required",
|
|
315
|
+
);
|
|
316
|
+
});
|