@frockbot/kernel-agent-loop 0.3.1 → 0.3.3

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-agent-loop",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -12,13 +12,13 @@
12
12
  "typecheck": "tsc --noEmit -p tsconfig.json"
13
13
  },
14
14
  "dependencies": {
15
- "@frockbot/kernel-contracts": "0.3.1",
15
+ "@frockbot/kernel-contracts": "0.3.3",
16
16
  "cordis": "4.0.0-rc.8"
17
17
  },
18
18
  "devDependencies": {
19
- "@frockbot/plugin-models": "0.3.1",
20
- "@frockbot/plugin-prompt": "0.3.1",
21
- "@frockbot/plugin-tools": "0.3.1",
19
+ "@frockbot/plugin-models": "0.3.3",
20
+ "@frockbot/plugin-prompt": "0.3.3",
21
+ "@frockbot/plugin-tools": "0.3.3",
22
22
  "@types/bun": "1.4.0",
23
23
  "@types/node": "26.2.0",
24
24
  "typescript": "^7.0.2"
package/src/agent.ts CHANGED
@@ -70,7 +70,7 @@ export interface Agent extends LoopAgentRuntimeV1 {
70
70
  readonly status: AgentStatus;
71
71
  send(input: string | AgentSendV1): string;
72
72
  resume(): void;
73
- cancel(reason?: "user" | "shutdown"): void;
73
+ cancel(reason?: "user" | "shutdown", detail?: string): void;
74
74
  whenIdle(): Promise<void>;
75
75
  }
76
76
 
package/src/index.test.ts CHANGED
@@ -512,6 +512,8 @@ describe("AgentLoop", () => {
512
512
  if (request?.type !== "model/request") throw new Error("request missing");
513
513
  expect(request.request.tools.map((schema) => schema.name)).toEqual([
514
514
  "work",
515
+ "get_dynamic_tools",
516
+ "call_dynamic_tool",
515
517
  ]);
516
518
  });
517
519
 
@@ -556,6 +558,8 @@ describe("AgentLoop", () => {
556
558
  if (request?.type !== "model/request") throw new Error("request missing");
557
559
  expect(request.request.tools.map((schema) => schema.name)).toEqual([
558
560
  "send_to_user",
561
+ "get_dynamic_tools",
562
+ "call_dynamic_tool",
559
563
  ]);
560
564
  expect(
561
565
  handle.agent.session.events.some(
@@ -1664,7 +1668,11 @@ describe("AgentLoop", () => {
1664
1668
  provider: "scripted",
1665
1669
  model: "test-model",
1666
1670
  system: "You are the FrockBot test agent.",
1667
- tools: [{ name: "echo" }],
1671
+ tools: expect.arrayContaining([
1672
+ expect.objectContaining({ name: "echo" }),
1673
+ expect.objectContaining({ name: "get_dynamic_tools" }),
1674
+ expect.objectContaining({ name: "call_dynamic_tool" }),
1675
+ ]),
1668
1676
  },
1669
1677
  });
1670
1678
  expect(events.at(-1)).toMatchObject({
package/src/index.ts CHANGED
@@ -149,6 +149,13 @@ class LoopAgent implements Agent {
149
149
  #inbox: AgentInput[] = [];
150
150
  #activity: Promise<void> = Promise.resolve();
151
151
  #controller: AbortController | undefined;
152
+ /**
153
+ * Why the current cancellation happened, as an opaque bounded string the
154
+ * caller supplied. The loop never reads it: it records it on the `turn/end`
155
+ * it writes, so the durable log says what interrupted the Turn rather than
156
+ * only that something did.
157
+ */
158
+ #cancelDetail: string | undefined;
152
159
  #disposeRequested = false;
153
160
  #resumeRequested = false;
154
161
 
@@ -216,8 +223,9 @@ class LoopAgent implements Agent {
216
223
  this.#wake();
217
224
  }
218
225
 
219
- cancel(reason: "user" | "shutdown" = "user"): void {
226
+ cancel(reason: "user" | "shutdown" = "user", detail?: string): void {
220
227
  if (this.#status === "disposed") return;
228
+ this.#cancelDetail = turnEndReason(detail);
221
229
  this.#ctx.emit("agent/cancel-requested", this, reason);
222
230
  const queued = this.#inbox.splice(0);
223
231
  if (queued.length > 0) {
@@ -587,6 +595,7 @@ class LoopAgent implements Agent {
587
595
  signal.aborted
588
596
  ) {
589
597
  turnOutcome = "cancelled";
598
+ turnReason = this.#cancelDetail;
590
599
  } else {
591
600
  turnOutcome = "model-error";
592
601
  turnReason = turnEndReason(modelFailureMessage(error));
@@ -746,6 +755,7 @@ class LoopAgent implements Agent {
746
755
  signal.aborted
747
756
  ) {
748
757
  turnOutcome = "cancelled";
758
+ turnReason = this.#cancelDetail;
749
759
  } else {
750
760
  turnOutcome = "model-error";
751
761
  turnReason = turnEndReason(modelFailureMessage(error));