zeitlich 0.2.22 → 0.2.23
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/README.md +242 -59
- package/dist/adapters/sandbox/daytona/index.cjs +4 -1
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
- package/dist/adapters/sandbox/daytona/index.js +4 -1
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +1 -0
- package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/daytona/workflow.js +1 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +16 -2
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +3 -2
- package/dist/adapters/sandbox/inmemory/index.d.ts +3 -2
- package/dist/adapters/sandbox/inmemory/index.js +16 -2
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +1 -0
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.js +1 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
- package/dist/adapters/sandbox/virtual/index.cjs +33 -9
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +6 -5
- package/dist/adapters/sandbox/virtual/index.d.ts +6 -5
- package/dist/adapters/sandbox/virtual/index.js +33 -9
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.cjs +1 -0
- package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.d.cts +3 -3
- package/dist/adapters/sandbox/virtual/workflow.d.ts +3 -3
- package/dist/adapters/sandbox/virtual/workflow.js +1 -0
- package/dist/adapters/sandbox/virtual/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +3 -3
- package/dist/adapters/thread/google-genai/index.d.ts +3 -3
- package/dist/adapters/thread/google-genai/workflow.d.cts +3 -3
- package/dist/adapters/thread/google-genai/workflow.d.ts +3 -3
- package/dist/adapters/thread/langchain/index.d.cts +3 -3
- package/dist/adapters/thread/langchain/index.d.ts +3 -3
- package/dist/adapters/thread/langchain/workflow.d.cts +3 -3
- package/dist/adapters/thread/langchain/workflow.d.ts +3 -3
- package/dist/index.cjs +247 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.js +245 -55
- package/dist/index.js.map +1 -1
- package/dist/{queries-Bw6WEPMw.d.cts → queries-DModcWRy.d.cts} +1 -1
- package/dist/{queries-C27raDaB.d.ts → queries-byD0jr1Y.d.ts} +1 -1
- package/dist/{types-ClsHhtwL.d.cts → types-B50pBPEV.d.ts} +159 -35
- package/dist/{types-YbL7JpEA.d.cts → types-Bll19FZJ.d.cts} +7 -0
- package/dist/{types-YbL7JpEA.d.ts → types-Bll19FZJ.d.ts} +7 -0
- package/dist/{types-BJ8itUAl.d.cts → types-BuXdFhaZ.d.cts} +6 -6
- package/dist/{types-HBosetv3.d.cts → types-ChAMwU3q.d.cts} +2 -0
- package/dist/{types-HBosetv3.d.ts → types-ChAMwU3q.d.ts} +2 -0
- package/dist/{types-C5bkx6kQ.d.ts → types-DQW8l7pY.d.cts} +159 -35
- package/dist/{types-ENYCKFBk.d.ts → types-GZ76HZSj.d.ts} +6 -6
- package/dist/workflow.cjs +241 -57
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +49 -32
- package/dist/workflow.d.ts +49 -32
- package/dist/workflow.js +239 -55
- package/dist/workflow.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
- package/src/adapters/sandbox/daytona/index.ts +4 -0
- package/src/adapters/sandbox/daytona/proxy.ts +4 -3
- package/src/adapters/sandbox/e2b/index.ts +5 -0
- package/src/adapters/sandbox/inmemory/index.ts +24 -4
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -2
- package/src/adapters/sandbox/virtual/filesystem.ts +41 -17
- package/src/adapters/sandbox/virtual/provider.ts +4 -0
- package/src/adapters/sandbox/virtual/proxy.ts +1 -0
- package/src/adapters/sandbox/virtual/types.ts +9 -4
- package/src/lib/lifecycle.ts +57 -0
- package/src/lib/sandbox/manager.ts +13 -1
- package/src/lib/sandbox/types.ts +13 -4
- package/src/lib/session/index.ts +1 -0
- package/src/lib/session/session-edge-cases.integration.test.ts +447 -33
- package/src/lib/session/session.integration.test.ts +52 -32
- package/src/lib/session/session.ts +107 -33
- package/src/lib/session/types.ts +55 -16
- package/src/lib/subagent/define.ts +5 -4
- package/src/lib/subagent/handler.ts +139 -14
- package/src/lib/subagent/index.ts +3 -0
- package/src/lib/subagent/register.ts +10 -3
- package/src/lib/subagent/signals.ts +8 -0
- package/src/lib/subagent/subagent.integration.test.ts +853 -150
- package/src/lib/subagent/tool.ts +2 -2
- package/src/lib/subagent/types.ts +77 -19
- package/src/lib/subagent/workflow.ts +83 -12
- package/src/lib/tool-router/router.integration.test.ts +137 -4
- package/src/lib/tool-router/router.ts +13 -3
- package/src/lib/tool-router/types.ts +7 -0
- package/src/lib/workflow.test.ts +89 -21
- package/src/lib/workflow.ts +33 -18
- package/src/workflow.ts +6 -1
|
@@ -34,7 +34,11 @@ vi.mock("@temporalio/workflow", () => {
|
|
|
34
34
|
condition: async (fn: () => boolean) => fn(),
|
|
35
35
|
defineUpdate: (name: string) => ({ __type: "update", name }),
|
|
36
36
|
defineQuery: (name: string) => ({ __type: "query", name }),
|
|
37
|
+
defineSignal: (name: string) => ({ __type: "signal", name }),
|
|
37
38
|
setHandler: (_def: unknown, _handler: unknown) => {},
|
|
39
|
+
startChild: async () => ({ result: () => Promise.resolve(null) }),
|
|
40
|
+
workflowInfo: () => ({ taskQueue: "default-queue" }),
|
|
41
|
+
getExternalWorkflowHandle: () => ({ signal: async () => {} }),
|
|
38
42
|
uuid4: () =>
|
|
39
43
|
`00000000-0000-0000-0000-${String(++idCounter).padStart(12, "0")}`,
|
|
40
44
|
ApplicationFailure: MockApplicationFailure,
|
|
@@ -151,7 +155,7 @@ describe("createSession edge cases", () => {
|
|
|
151
155
|
|
|
152
156
|
const session = await createSession({
|
|
153
157
|
agentName: "TestAgent",
|
|
154
|
-
threadId: "thread-1",
|
|
158
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
155
159
|
runAgent: createScriptedRunAgent([
|
|
156
160
|
{
|
|
157
161
|
message: "Need user input",
|
|
@@ -187,7 +191,7 @@ describe("createSession edge cases", () => {
|
|
|
187
191
|
|
|
188
192
|
const session = await createSession({
|
|
189
193
|
agentName: "TestAgent",
|
|
190
|
-
threadId: "thread-1",
|
|
194
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
191
195
|
runAgent: createScriptedRunAgent([
|
|
192
196
|
{
|
|
193
197
|
message: "bad calls",
|
|
@@ -233,7 +237,7 @@ describe("createSession edge cases", () => {
|
|
|
233
237
|
|
|
234
238
|
const session = await createSession({
|
|
235
239
|
agentName: "TestAgent",
|
|
236
|
-
threadId: "thread-1",
|
|
240
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
237
241
|
runAgent: createScriptedRunAgent([
|
|
238
242
|
{
|
|
239
243
|
message: "no id",
|
|
@@ -264,7 +268,7 @@ describe("createSession edge cases", () => {
|
|
|
264
268
|
|
|
265
269
|
const session = await createSession({
|
|
266
270
|
agentName: "TestAgent",
|
|
267
|
-
threadId: "thread-1",
|
|
271
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
268
272
|
runAgent: createScriptedRunAgent([
|
|
269
273
|
{
|
|
270
274
|
message: "I tried calling a tool",
|
|
@@ -302,7 +306,7 @@ describe("createSession edge cases", () => {
|
|
|
302
306
|
|
|
303
307
|
const session = await createSession({
|
|
304
308
|
agentName: "TestAgent",
|
|
305
|
-
threadId: "thread-1",
|
|
309
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
306
310
|
runAgent: createScriptedRunAgent([
|
|
307
311
|
{
|
|
308
312
|
message: "calling fail",
|
|
@@ -332,7 +336,7 @@ describe("createSession edge cases", () => {
|
|
|
332
336
|
|
|
333
337
|
// --- Tool handler throws without recovery ---
|
|
334
338
|
|
|
335
|
-
it("session
|
|
339
|
+
it("session completes when tool handler throws with no failure hook (error suppressed)", async () => {
|
|
336
340
|
const { ops } = createMockThreadOps();
|
|
337
341
|
let endReason: string | undefined;
|
|
338
342
|
|
|
@@ -347,7 +351,7 @@ describe("createSession edge cases", () => {
|
|
|
347
351
|
|
|
348
352
|
const session = await createSession({
|
|
349
353
|
agentName: "TestAgent",
|
|
350
|
-
threadId: "thread-1",
|
|
354
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
351
355
|
runAgent: createScriptedRunAgent([
|
|
352
356
|
{
|
|
353
357
|
message: "calling fail",
|
|
@@ -368,10 +372,10 @@ describe("createSession edge cases", () => {
|
|
|
368
372
|
initialState: { systemPrompt: "test" },
|
|
369
373
|
});
|
|
370
374
|
|
|
371
|
-
await
|
|
372
|
-
|
|
373
|
-
);
|
|
374
|
-
expect(endReason).toBe("
|
|
375
|
+
const result = await session.runSession({ stateManager });
|
|
376
|
+
expect(result.exitReason).toBe("completed");
|
|
377
|
+
expect(result.finalMessage).toBe("done");
|
|
378
|
+
expect(endReason).toBe("completed");
|
|
375
379
|
});
|
|
376
380
|
|
|
377
381
|
// --- Metadata passed through to hooks ---
|
|
@@ -383,7 +387,7 @@ describe("createSession edge cases", () => {
|
|
|
383
387
|
|
|
384
388
|
const session = await createSession({
|
|
385
389
|
agentName: "TestAgent",
|
|
386
|
-
threadId: "thread-1",
|
|
390
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
387
391
|
metadata: { env: "test", version: 42 },
|
|
388
392
|
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
389
393
|
threadOps: ops,
|
|
@@ -425,15 +429,16 @@ describe("createSession edge cases", () => {
|
|
|
425
429
|
createdAt: new Date().toISOString(),
|
|
426
430
|
}),
|
|
427
431
|
forkSandbox: async () => "forked-sandbox-id",
|
|
432
|
+
pauseSandbox: async () => {},
|
|
428
433
|
};
|
|
429
434
|
|
|
430
435
|
const session = await createSession({
|
|
431
436
|
agentName: "TestAgent",
|
|
432
|
-
threadId: "thread-1",
|
|
437
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
433
438
|
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
434
439
|
threadOps: ops,
|
|
435
440
|
buildContextMessage: () => "go",
|
|
436
|
-
|
|
441
|
+
sandboxOps,
|
|
437
442
|
});
|
|
438
443
|
|
|
439
444
|
const stateManager = createAgentStateManager({
|
|
@@ -466,17 +471,18 @@ describe("createSession edge cases", () => {
|
|
|
466
471
|
createdAt: new Date().toISOString(),
|
|
467
472
|
}),
|
|
468
473
|
forkSandbox: async () => "forked-sandbox-id",
|
|
474
|
+
pauseSandbox: async () => {},
|
|
469
475
|
};
|
|
470
476
|
|
|
471
477
|
const session = await createSession({
|
|
472
478
|
agentName: "TestAgent",
|
|
473
|
-
threadId: "thread-1",
|
|
479
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
474
480
|
runAgent: async () => {
|
|
475
481
|
throw new Error("LLM crash");
|
|
476
482
|
},
|
|
477
483
|
threadOps: ops,
|
|
478
484
|
buildContextMessage: () => "go",
|
|
479
|
-
|
|
485
|
+
sandboxOps,
|
|
480
486
|
});
|
|
481
487
|
|
|
482
488
|
const stateManager = createAgentStateManager({
|
|
@@ -498,7 +504,7 @@ describe("createSession edge cases", () => {
|
|
|
498
504
|
|
|
499
505
|
const session = await createSession({
|
|
500
506
|
agentName: "TestAgent",
|
|
501
|
-
threadId: "thread-1",
|
|
507
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
502
508
|
runAgent: createScriptedRunAgent([]),
|
|
503
509
|
threadOps: ops,
|
|
504
510
|
buildContextMessage: () => "hi",
|
|
@@ -531,7 +537,7 @@ describe("createSession edge cases", () => {
|
|
|
531
537
|
|
|
532
538
|
const session = await createSession({
|
|
533
539
|
agentName: "TestAgent",
|
|
534
|
-
threadId: "thread-1",
|
|
540
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
535
541
|
runAgent: createScriptedRunAgent([
|
|
536
542
|
{
|
|
537
543
|
message: "t1",
|
|
@@ -562,15 +568,14 @@ describe("createSession edge cases", () => {
|
|
|
562
568
|
expect(result.usage.totalOutputTokens).toBe(50);
|
|
563
569
|
});
|
|
564
570
|
|
|
565
|
-
// ---
|
|
571
|
+
// --- Thread fork: new threadId from source ---
|
|
566
572
|
|
|
567
|
-
it("
|
|
573
|
+
it("fork thread mode generates new threadId and forks when source is provided", async () => {
|
|
568
574
|
const { ops, log } = createMockThreadOps();
|
|
569
575
|
|
|
570
576
|
const session = await createSession({
|
|
571
577
|
agentName: "TestAgent",
|
|
572
|
-
threadId: "original-thread",
|
|
573
|
-
continueThread: true,
|
|
578
|
+
thread: { mode: "fork", threadId: "original-thread" },
|
|
574
579
|
runAgent: createScriptedRunAgent([
|
|
575
580
|
{ message: "continued", toolCalls: [] },
|
|
576
581
|
]),
|
|
@@ -601,7 +606,7 @@ describe("createSession edge cases", () => {
|
|
|
601
606
|
|
|
602
607
|
const session = await createSession({
|
|
603
608
|
agentName: "TestAgent",
|
|
604
|
-
threadId: "thread-1",
|
|
609
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
605
610
|
maxTurns: 1,
|
|
606
611
|
runAgent: createScriptedRunAgent([
|
|
607
612
|
{
|
|
@@ -646,7 +651,7 @@ describe("createSession edge cases", () => {
|
|
|
646
651
|
|
|
647
652
|
const session = await createSession({
|
|
648
653
|
agentName: "TestAgent",
|
|
649
|
-
threadId: "thread-1",
|
|
654
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
650
655
|
processToolsInParallel: false,
|
|
651
656
|
runAgent: createScriptedRunAgent([
|
|
652
657
|
{
|
|
@@ -679,7 +684,7 @@ describe("createSession edge cases", () => {
|
|
|
679
684
|
|
|
680
685
|
const session = await createSession({
|
|
681
686
|
agentName: "TestAgent",
|
|
682
|
-
threadId: "thread-1",
|
|
687
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
683
688
|
runAgent: createScriptedRunAgent([
|
|
684
689
|
{
|
|
685
690
|
message: "mixed",
|
|
@@ -735,7 +740,7 @@ describe("createSession edge cases", () => {
|
|
|
735
740
|
|
|
736
741
|
const session = await createSession({
|
|
737
742
|
agentName: "TestAgent",
|
|
738
|
-
threadId: "thread-1",
|
|
743
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
739
744
|
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
740
745
|
threadOps: ops,
|
|
741
746
|
buildContextMessage: () => [
|
|
@@ -769,7 +774,7 @@ describe("createSession edge cases", () => {
|
|
|
769
774
|
|
|
770
775
|
const session = await createSession({
|
|
771
776
|
agentName: "TestAgent",
|
|
772
|
-
threadId: "thread-1",
|
|
777
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
773
778
|
runAgent: createScriptedRunAgent([
|
|
774
779
|
{
|
|
775
780
|
message: "t1",
|
|
@@ -818,7 +823,7 @@ describe("createSession edge cases", () => {
|
|
|
818
823
|
|
|
819
824
|
const session = await createSession({
|
|
820
825
|
agentName: "TestAgent",
|
|
821
|
-
threadId: "thread-1",
|
|
826
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
822
827
|
runAgent: createScriptedRunAgent([
|
|
823
828
|
{
|
|
824
829
|
message: "self",
|
|
@@ -852,7 +857,7 @@ describe("createSession edge cases", () => {
|
|
|
852
857
|
|
|
853
858
|
const session = await createSession({
|
|
854
859
|
agentName: "TestAgent",
|
|
855
|
-
threadId: "thread-1",
|
|
860
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
856
861
|
runAgent: createScriptedRunAgent([
|
|
857
862
|
{
|
|
858
863
|
message: "calling",
|
|
@@ -908,15 +913,16 @@ describe("createSession edge cases", () => {
|
|
|
908
913
|
destroySandbox: async () => {},
|
|
909
914
|
snapshotSandbox: snapshotSpy,
|
|
910
915
|
forkSandbox: async () => "forked-sandbox-id",
|
|
916
|
+
pauseSandbox: async () => {},
|
|
911
917
|
};
|
|
912
918
|
|
|
913
919
|
const session = await createSession({
|
|
914
920
|
agentName: "TestAgent",
|
|
915
|
-
threadId: "thread-1",
|
|
921
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
916
922
|
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
917
923
|
threadOps: ops,
|
|
918
924
|
buildContextMessage: () => "go",
|
|
919
|
-
|
|
925
|
+
sandboxOps,
|
|
920
926
|
});
|
|
921
927
|
|
|
922
928
|
const stateManager = createAgentStateManager({
|
|
@@ -935,7 +941,7 @@ describe("createSession edge cases", () => {
|
|
|
935
941
|
|
|
936
942
|
const session = await createSession({
|
|
937
943
|
agentName: "TestAgent",
|
|
938
|
-
threadId: "thread-1",
|
|
944
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
939
945
|
runAgent: createScriptedRunAgent([
|
|
940
946
|
{
|
|
941
947
|
message: "t1",
|
|
@@ -970,7 +976,7 @@ describe("createSession edge cases", () => {
|
|
|
970
976
|
|
|
971
977
|
const session = await createSession({
|
|
972
978
|
agentName: "TestAgent",
|
|
973
|
-
threadId: "thread-1",
|
|
979
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
974
980
|
maxTurns: 0,
|
|
975
981
|
runAgent: createScriptedRunAgent([]),
|
|
976
982
|
threadOps: ops,
|
|
@@ -988,4 +994,412 @@ describe("createSession edge cases", () => {
|
|
|
988
994
|
expect(result.usage.turns).toBe(0);
|
|
989
995
|
expect(result.finalMessage).toBeNull();
|
|
990
996
|
});
|
|
997
|
+
|
|
998
|
+
// --- sandboxId returned from runSession ---
|
|
999
|
+
|
|
1000
|
+
it("returns sandboxId from runSession when sandbox is created", async () => {
|
|
1001
|
+
const { ops } = createMockThreadOps();
|
|
1002
|
+
|
|
1003
|
+
const sandboxOps: SandboxOps = {
|
|
1004
|
+
createSandbox: async () => ({ sandboxId: "sb-created" }),
|
|
1005
|
+
destroySandbox: async () => {},
|
|
1006
|
+
pauseSandbox: async () => {},
|
|
1007
|
+
snapshotSandbox: async () => ({
|
|
1008
|
+
sandboxId: "sb-1",
|
|
1009
|
+
providerId: "test",
|
|
1010
|
+
data: null,
|
|
1011
|
+
createdAt: new Date().toISOString(),
|
|
1012
|
+
}),
|
|
1013
|
+
forkSandbox: async () => "forked-sb",
|
|
1014
|
+
};
|
|
1015
|
+
|
|
1016
|
+
const session = await createSession({
|
|
1017
|
+
agentName: "TestAgent",
|
|
1018
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1019
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1020
|
+
threadOps: ops,
|
|
1021
|
+
buildContextMessage: () => "go",
|
|
1022
|
+
sandboxOps,
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
const stateManager = createAgentStateManager({
|
|
1026
|
+
initialState: { systemPrompt: "test" },
|
|
1027
|
+
});
|
|
1028
|
+
|
|
1029
|
+
const result = await session.runSession({ stateManager });
|
|
1030
|
+
expect((result as { sandboxId?: string }).sandboxId).toBe("sb-created");
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
it("returns inherited sandboxId from runSession", async () => {
|
|
1034
|
+
const { ops } = createMockThreadOps();
|
|
1035
|
+
|
|
1036
|
+
const sandboxOps: SandboxOps = {
|
|
1037
|
+
createSandbox: async () => ({ sandboxId: "sb" }),
|
|
1038
|
+
destroySandbox: async () => {},
|
|
1039
|
+
pauseSandbox: async () => {},
|
|
1040
|
+
snapshotSandbox: async () => ({
|
|
1041
|
+
sandboxId: "sb",
|
|
1042
|
+
providerId: "test",
|
|
1043
|
+
data: null,
|
|
1044
|
+
createdAt: new Date().toISOString(),
|
|
1045
|
+
}),
|
|
1046
|
+
forkSandbox: async () => "forked-sb",
|
|
1047
|
+
};
|
|
1048
|
+
|
|
1049
|
+
const session = await createSession({
|
|
1050
|
+
agentName: "TestAgent",
|
|
1051
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1052
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1053
|
+
threadOps: ops,
|
|
1054
|
+
buildContextMessage: () => "go",
|
|
1055
|
+
sandbox: { mode: "inherit", sandboxId: "inherited-sb" },
|
|
1056
|
+
sandboxOps,
|
|
1057
|
+
});
|
|
1058
|
+
|
|
1059
|
+
const stateManager = createAgentStateManager({
|
|
1060
|
+
initialState: { systemPrompt: "test" },
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
const result = await session.runSession({ stateManager });
|
|
1064
|
+
expect((result as { sandboxId?: string }).sandboxId).toBe("inherited-sb");
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
// --- Inherited sandbox is not destroyed ---
|
|
1068
|
+
|
|
1069
|
+
it("does not destroy inherited sandbox even when sandboxOps is provided", async () => {
|
|
1070
|
+
const { ops } = createMockThreadOps();
|
|
1071
|
+
const sandboxLog: string[] = [];
|
|
1072
|
+
|
|
1073
|
+
const sandboxOps: SandboxOps = {
|
|
1074
|
+
createSandbox: async () => {
|
|
1075
|
+
sandboxLog.push("create");
|
|
1076
|
+
return { sandboxId: "new-sb" };
|
|
1077
|
+
},
|
|
1078
|
+
destroySandbox: async (id: string) => {
|
|
1079
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1080
|
+
},
|
|
1081
|
+
pauseSandbox: async (id: string) => {
|
|
1082
|
+
sandboxLog.push(`pause:${id}`);
|
|
1083
|
+
},
|
|
1084
|
+
snapshotSandbox: async () => ({
|
|
1085
|
+
sandboxId: "sb-1",
|
|
1086
|
+
providerId: "test",
|
|
1087
|
+
data: null,
|
|
1088
|
+
createdAt: new Date().toISOString(),
|
|
1089
|
+
}),
|
|
1090
|
+
forkSandbox: async () => "forked-sb",
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
const session = await createSession({
|
|
1094
|
+
agentName: "TestAgent",
|
|
1095
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1096
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1097
|
+
threadOps: ops,
|
|
1098
|
+
buildContextMessage: () => "go",
|
|
1099
|
+
sandboxOps,
|
|
1100
|
+
sandbox: { mode: "inherit", sandboxId: "inherited-sb" },
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
const stateManager = createAgentStateManager({
|
|
1104
|
+
initialState: { systemPrompt: "test" },
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1107
|
+
await session.runSession({ stateManager });
|
|
1108
|
+
|
|
1109
|
+
expect(sandboxLog).toHaveLength(0);
|
|
1110
|
+
});
|
|
1111
|
+
|
|
1112
|
+
// --- Sandbox fork ---
|
|
1113
|
+
|
|
1114
|
+
it("forks sandbox when sandbox init mode is fork", async () => {
|
|
1115
|
+
const { ops } = createMockThreadOps();
|
|
1116
|
+
const sandboxLog: string[] = [];
|
|
1117
|
+
|
|
1118
|
+
const sandboxOps: SandboxOps = {
|
|
1119
|
+
createSandbox: async () => {
|
|
1120
|
+
sandboxLog.push("create");
|
|
1121
|
+
return { sandboxId: "new-sb" };
|
|
1122
|
+
},
|
|
1123
|
+
destroySandbox: async (id: string) => {
|
|
1124
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1125
|
+
},
|
|
1126
|
+
pauseSandbox: async () => {},
|
|
1127
|
+
snapshotSandbox: async () => ({
|
|
1128
|
+
sandboxId: "sb-1",
|
|
1129
|
+
providerId: "test",
|
|
1130
|
+
data: null,
|
|
1131
|
+
createdAt: new Date().toISOString(),
|
|
1132
|
+
}),
|
|
1133
|
+
forkSandbox: async (id: string) => {
|
|
1134
|
+
sandboxLog.push(`fork:${id}`);
|
|
1135
|
+
return `forked-from-${id}`;
|
|
1136
|
+
},
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
const session = await createSession({
|
|
1140
|
+
agentName: "TestAgent",
|
|
1141
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1142
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1143
|
+
threadOps: ops,
|
|
1144
|
+
buildContextMessage: () => "go",
|
|
1145
|
+
sandboxOps,
|
|
1146
|
+
sandbox: { mode: "fork", sandboxId: "paused-sb-1" },
|
|
1147
|
+
});
|
|
1148
|
+
|
|
1149
|
+
const stateManager = createAgentStateManager({
|
|
1150
|
+
initialState: { systemPrompt: "test" },
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
const result = await session.runSession({ stateManager });
|
|
1154
|
+
|
|
1155
|
+
expect(sandboxLog).toContain("fork:paused-sb-1");
|
|
1156
|
+
expect(sandboxLog).not.toContain("create");
|
|
1157
|
+
expect((result as { sandboxId?: string }).sandboxId).toBe("forked-from-paused-sb-1");
|
|
1158
|
+
expect(sandboxLog).toContain("destroy:forked-from-paused-sb-1");
|
|
1159
|
+
});
|
|
1160
|
+
|
|
1161
|
+
// --- Forked sandbox is destroyed on exit ---
|
|
1162
|
+
|
|
1163
|
+
it("destroys forked sandbox on exit (not inherited)", async () => {
|
|
1164
|
+
const { ops } = createMockThreadOps();
|
|
1165
|
+
const sandboxLog: string[] = [];
|
|
1166
|
+
|
|
1167
|
+
const sandboxOps: SandboxOps = {
|
|
1168
|
+
createSandbox: async () => ({ sandboxId: "new-sb" }),
|
|
1169
|
+
destroySandbox: async (id: string) => {
|
|
1170
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1171
|
+
},
|
|
1172
|
+
pauseSandbox: async () => {},
|
|
1173
|
+
snapshotSandbox: async () => ({
|
|
1174
|
+
sandboxId: "sb-1",
|
|
1175
|
+
providerId: "test",
|
|
1176
|
+
data: null,
|
|
1177
|
+
createdAt: new Date().toISOString(),
|
|
1178
|
+
}),
|
|
1179
|
+
forkSandbox: async () => "forked-sb",
|
|
1180
|
+
};
|
|
1181
|
+
|
|
1182
|
+
const session = await createSession({
|
|
1183
|
+
agentName: "TestAgent",
|
|
1184
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1185
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1186
|
+
threadOps: ops,
|
|
1187
|
+
buildContextMessage: () => "go",
|
|
1188
|
+
sandboxOps,
|
|
1189
|
+
sandbox: { mode: "fork", sandboxId: "old-sb" },
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
const stateManager = createAgentStateManager({
|
|
1193
|
+
initialState: { systemPrompt: "test" },
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1196
|
+
await session.runSession({ stateManager });
|
|
1197
|
+
|
|
1198
|
+
expect(sandboxLog).toContain("destroy:forked-sb");
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
// --- sandboxShutdown: "pause" ---
|
|
1202
|
+
|
|
1203
|
+
it("pauses sandbox on exit when sandboxShutdown is pause", async () => {
|
|
1204
|
+
const { ops } = createMockThreadOps();
|
|
1205
|
+
const sandboxLog: string[] = [];
|
|
1206
|
+
|
|
1207
|
+
const sandboxOps: SandboxOps = {
|
|
1208
|
+
createSandbox: async () => ({ sandboxId: "sb-pause-test" }),
|
|
1209
|
+
destroySandbox: async (id: string) => {
|
|
1210
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1211
|
+
},
|
|
1212
|
+
pauseSandbox: async (id: string) => {
|
|
1213
|
+
sandboxLog.push(`pause:${id}`);
|
|
1214
|
+
},
|
|
1215
|
+
snapshotSandbox: async () => ({
|
|
1216
|
+
sandboxId: "sb-1",
|
|
1217
|
+
providerId: "test",
|
|
1218
|
+
data: null,
|
|
1219
|
+
createdAt: new Date().toISOString(),
|
|
1220
|
+
}),
|
|
1221
|
+
forkSandbox: async () => "forked-sb",
|
|
1222
|
+
};
|
|
1223
|
+
|
|
1224
|
+
const session = await createSession({
|
|
1225
|
+
agentName: "TestAgent",
|
|
1226
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1227
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1228
|
+
threadOps: ops,
|
|
1229
|
+
buildContextMessage: () => "go",
|
|
1230
|
+
sandboxOps,
|
|
1231
|
+
sandboxShutdown: "pause",
|
|
1232
|
+
});
|
|
1233
|
+
|
|
1234
|
+
const stateManager = createAgentStateManager({
|
|
1235
|
+
initialState: { systemPrompt: "test" },
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
await session.runSession({ stateManager });
|
|
1239
|
+
|
|
1240
|
+
expect(sandboxLog).toContain("pause:sb-pause-test");
|
|
1241
|
+
expect(sandboxLog).not.toContain("destroy:sb-pause-test");
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
// --- sandboxShutdown: "pause-until-parent-close" ---
|
|
1245
|
+
|
|
1246
|
+
it("pauses sandbox on exit when sandboxShutdown is pause-until-parent-close", async () => {
|
|
1247
|
+
const { ops } = createMockThreadOps();
|
|
1248
|
+
const sandboxLog: string[] = [];
|
|
1249
|
+
|
|
1250
|
+
const sandboxOps: SandboxOps = {
|
|
1251
|
+
createSandbox: async () => ({ sandboxId: "sb-parent-close" }),
|
|
1252
|
+
destroySandbox: async (id: string) => {
|
|
1253
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1254
|
+
},
|
|
1255
|
+
pauseSandbox: async (id: string) => {
|
|
1256
|
+
sandboxLog.push(`pause:${id}`);
|
|
1257
|
+
},
|
|
1258
|
+
snapshotSandbox: async () => ({
|
|
1259
|
+
sandboxId: "sb-1",
|
|
1260
|
+
providerId: "test",
|
|
1261
|
+
data: null,
|
|
1262
|
+
createdAt: new Date().toISOString(),
|
|
1263
|
+
}),
|
|
1264
|
+
forkSandbox: async () => "forked-sb",
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1267
|
+
const session = await createSession({
|
|
1268
|
+
agentName: "TestAgent",
|
|
1269
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1270
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1271
|
+
threadOps: ops,
|
|
1272
|
+
buildContextMessage: () => "go",
|
|
1273
|
+
sandboxOps,
|
|
1274
|
+
sandboxShutdown: "pause-until-parent-close",
|
|
1275
|
+
});
|
|
1276
|
+
|
|
1277
|
+
const stateManager = createAgentStateManager({
|
|
1278
|
+
initialState: { systemPrompt: "test" },
|
|
1279
|
+
});
|
|
1280
|
+
|
|
1281
|
+
await session.runSession({ stateManager });
|
|
1282
|
+
|
|
1283
|
+
expect(sandboxLog).toContain("pause:sb-parent-close");
|
|
1284
|
+
expect(sandboxLog).not.toContain("destroy:sb-parent-close");
|
|
1285
|
+
});
|
|
1286
|
+
|
|
1287
|
+
// --- Throws when sandbox fork/continue provided without sandboxOps ---
|
|
1288
|
+
|
|
1289
|
+
it("throws when sandbox fork mode is set without sandboxOps", async () => {
|
|
1290
|
+
const { ops } = createMockThreadOps();
|
|
1291
|
+
|
|
1292
|
+
const session = await createSession({
|
|
1293
|
+
agentName: "TestAgent",
|
|
1294
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1295
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1296
|
+
threadOps: ops,
|
|
1297
|
+
buildContextMessage: () => "go",
|
|
1298
|
+
sandbox: { mode: "fork", sandboxId: "prev-sb" },
|
|
1299
|
+
});
|
|
1300
|
+
|
|
1301
|
+
const stateManager = createAgentStateManager({
|
|
1302
|
+
initialState: { systemPrompt: "test" },
|
|
1303
|
+
});
|
|
1304
|
+
|
|
1305
|
+
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
1306
|
+
"No sandboxOps provided — cannot fork sandbox"
|
|
1307
|
+
);
|
|
1308
|
+
});
|
|
1309
|
+
|
|
1310
|
+
// --- No sandboxId returned when no sandbox ---
|
|
1311
|
+
|
|
1312
|
+
it("does not return sandboxId when no sandbox is configured", async () => {
|
|
1313
|
+
const { ops } = createMockThreadOps();
|
|
1314
|
+
|
|
1315
|
+
const session = await createSession({
|
|
1316
|
+
agentName: "TestAgent",
|
|
1317
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1318
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
1319
|
+
threadOps: ops,
|
|
1320
|
+
buildContextMessage: () => "go",
|
|
1321
|
+
});
|
|
1322
|
+
|
|
1323
|
+
const stateManager = createAgentStateManager({
|
|
1324
|
+
initialState: { systemPrompt: "test" },
|
|
1325
|
+
});
|
|
1326
|
+
|
|
1327
|
+
const result = await session.runSession({ stateManager });
|
|
1328
|
+
expect((result as { sandboxId?: string }).sandboxId).toBeUndefined();
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
// --- Thread: defaults to new thread when no thread field provided ---
|
|
1332
|
+
|
|
1333
|
+
it("defaults to new thread without fork when no thread field is provided", async () => {
|
|
1334
|
+
const { ops, log } = createMockThreadOps();
|
|
1335
|
+
|
|
1336
|
+
const session = await createSession({
|
|
1337
|
+
agentName: "TestAgent",
|
|
1338
|
+
runAgent: createScriptedRunAgent([
|
|
1339
|
+
{ message: "done", toolCalls: [] },
|
|
1340
|
+
]),
|
|
1341
|
+
threadOps: ops,
|
|
1342
|
+
buildContextMessage: () => "go",
|
|
1343
|
+
});
|
|
1344
|
+
|
|
1345
|
+
const stateManager = createAgentStateManager({
|
|
1346
|
+
initialState: { systemPrompt: "test" },
|
|
1347
|
+
});
|
|
1348
|
+
|
|
1349
|
+
const result = await session.runSession({ stateManager });
|
|
1350
|
+
expect(result.exitReason).toBe("completed");
|
|
1351
|
+
|
|
1352
|
+
const forkOps = log.filter((l) => l.op === "forkThread");
|
|
1353
|
+
expect(forkOps).toHaveLength(0);
|
|
1354
|
+
|
|
1355
|
+
const systemOps = log.filter((l) => l.op === "appendSystemMessage");
|
|
1356
|
+
expect(systemOps).toHaveLength(1);
|
|
1357
|
+
});
|
|
1358
|
+
|
|
1359
|
+
// --- Sandbox pause on error ---
|
|
1360
|
+
|
|
1361
|
+
it("pauses sandbox even when session fails if sandboxShutdown is pause", async () => {
|
|
1362
|
+
const { ops } = createMockThreadOps();
|
|
1363
|
+
const sandboxLog: string[] = [];
|
|
1364
|
+
|
|
1365
|
+
const sandboxOps: SandboxOps = {
|
|
1366
|
+
createSandbox: async () => ({ sandboxId: "sb-err" }),
|
|
1367
|
+
destroySandbox: async (id: string) => {
|
|
1368
|
+
sandboxLog.push(`destroy:${id}`);
|
|
1369
|
+
},
|
|
1370
|
+
pauseSandbox: async (id: string) => {
|
|
1371
|
+
sandboxLog.push(`pause:${id}`);
|
|
1372
|
+
},
|
|
1373
|
+
snapshotSandbox: async () => ({
|
|
1374
|
+
sandboxId: "sb-1",
|
|
1375
|
+
providerId: "test",
|
|
1376
|
+
data: null,
|
|
1377
|
+
createdAt: new Date().toISOString(),
|
|
1378
|
+
}),
|
|
1379
|
+
forkSandbox: async () => "forked-sb",
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
const session = await createSession({
|
|
1383
|
+
agentName: "TestAgent",
|
|
1384
|
+
thread: { mode: "new", threadId: "thread-1" },
|
|
1385
|
+
runAgent: async () => {
|
|
1386
|
+
throw new Error("crash");
|
|
1387
|
+
},
|
|
1388
|
+
threadOps: ops,
|
|
1389
|
+
buildContextMessage: () => "go",
|
|
1390
|
+
sandboxOps,
|
|
1391
|
+
sandboxShutdown: "pause",
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
const stateManager = createAgentStateManager({
|
|
1395
|
+
initialState: { systemPrompt: "test" },
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
1399
|
+
"crash"
|
|
1400
|
+
);
|
|
1401
|
+
|
|
1402
|
+
expect(sandboxLog).toContain("pause:sb-err");
|
|
1403
|
+
expect(sandboxLog).not.toContain("destroy:sb-err");
|
|
1404
|
+
});
|
|
991
1405
|
});
|