zeitlich 0.2.15 → 0.2.17

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.
Files changed (78) hide show
  1. package/README.md +125 -64
  2. package/dist/adapters/sandbox/daytona/index.cjs +52 -23
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  4. package/dist/adapters/sandbox/daytona/index.d.cts +10 -2
  5. package/dist/adapters/sandbox/daytona/index.d.ts +10 -2
  6. package/dist/adapters/sandbox/daytona/index.js +52 -23
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  8. package/dist/adapters/sandbox/inmemory/index.cjs +21 -16
  9. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  10. package/dist/adapters/sandbox/inmemory/index.d.cts +1 -1
  11. package/dist/adapters/sandbox/inmemory/index.d.ts +1 -1
  12. package/dist/adapters/sandbox/inmemory/index.js +21 -16
  13. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  14. package/dist/adapters/sandbox/virtual/index.cjs +83 -38
  15. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
  16. package/dist/adapters/sandbox/virtual/index.d.cts +6 -6
  17. package/dist/adapters/sandbox/virtual/index.d.ts +6 -6
  18. package/dist/adapters/sandbox/virtual/index.js +80 -38
  19. package/dist/adapters/sandbox/virtual/index.js.map +1 -1
  20. package/dist/adapters/thread/google-genai/index.d.cts +2 -2
  21. package/dist/adapters/thread/google-genai/index.d.ts +2 -2
  22. package/dist/adapters/thread/langchain/index.cjs +2 -2
  23. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  24. package/dist/adapters/thread/langchain/index.d.cts +2 -2
  25. package/dist/adapters/thread/langchain/index.d.ts +2 -2
  26. package/dist/adapters/thread/langchain/index.js +2 -2
  27. package/dist/adapters/thread/langchain/index.js.map +1 -1
  28. package/dist/index.cjs +102 -10
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +6 -6
  31. package/dist/index.d.ts +6 -6
  32. package/dist/index.js +98 -11
  33. package/dist/index.js.map +1 -1
  34. package/dist/{types-CwwgQ_9H.d.ts → queries-BlC1I3DK.d.ts} +48 -3
  35. package/dist/{types-BVP87m_W.d.cts → queries-DlJ3jE48.d.cts} +48 -3
  36. package/dist/{types-CDubRtad.d.cts → types-BMRzfELQ.d.cts} +2 -0
  37. package/dist/{types-CDubRtad.d.ts → types-BMRzfELQ.d.ts} +2 -0
  38. package/dist/{types-Dje1TdH6.d.cts → types-Bh-BbfCp.d.cts} +31 -12
  39. package/dist/{types-BWvIYK28.d.ts → types-NkiAxU4t.d.ts} +31 -12
  40. package/dist/workflow.cjs +102 -10
  41. package/dist/workflow.cjs.map +1 -1
  42. package/dist/workflow.d.cts +114 -40
  43. package/dist/workflow.d.ts +114 -40
  44. package/dist/workflow.js +98 -11
  45. package/dist/workflow.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/adapters/sandbox/daytona/filesystem.ts +43 -19
  48. package/src/adapters/sandbox/daytona/index.ts +16 -3
  49. package/src/adapters/sandbox/daytona/types.ts +4 -0
  50. package/src/adapters/sandbox/inmemory/index.ts +22 -16
  51. package/src/adapters/sandbox/virtual/filesystem.ts +29 -31
  52. package/src/adapters/sandbox/virtual/index.ts +7 -3
  53. package/src/adapters/sandbox/virtual/provider.ts +5 -2
  54. package/src/adapters/sandbox/virtual/queries.ts +97 -0
  55. package/src/adapters/sandbox/virtual/types.ts +3 -0
  56. package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +4 -3
  57. package/src/adapters/thread/langchain/activities.ts +7 -5
  58. package/src/lib/sandbox/tree.integration.test.ts +153 -0
  59. package/src/lib/sandbox/types.ts +2 -0
  60. package/src/lib/session/session-edge-cases.integration.test.ts +962 -0
  61. package/src/lib/session/session.integration.test.ts +853 -0
  62. package/src/lib/session/session.ts +5 -4
  63. package/src/lib/skills/skills.integration.test.ts +308 -0
  64. package/src/lib/state/manager.integration.test.ts +342 -0
  65. package/src/lib/subagent/define.ts +34 -47
  66. package/src/lib/subagent/handler.ts +9 -6
  67. package/src/lib/subagent/index.ts +4 -1
  68. package/src/lib/subagent/subagent.integration.test.ts +573 -0
  69. package/src/lib/subagent/types.ts +40 -10
  70. package/src/lib/subagent/workflow.ts +114 -0
  71. package/src/lib/thread/id.test.ts +50 -0
  72. package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +344 -0
  73. package/src/lib/tool-router/router-edge-cases.integration.test.ts +623 -0
  74. package/src/lib/tool-router/router.integration.test.ts +699 -0
  75. package/src/lib/types.test.ts +29 -0
  76. package/src/lib/workflow.test.ts +131 -0
  77. package/src/lib/workflow.ts +45 -0
  78. package/src/workflow.ts +12 -2
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { isTerminalStatus } from "./types";
3
+ import type { AgentStatus } from "./types";
4
+
5
+ describe("isTerminalStatus", () => {
6
+ it("returns true for COMPLETED", () => {
7
+ expect(isTerminalStatus("COMPLETED")).toBe(true);
8
+ });
9
+
10
+ it("returns true for FAILED", () => {
11
+ expect(isTerminalStatus("FAILED")).toBe(true);
12
+ });
13
+
14
+ it("returns true for CANCELLED", () => {
15
+ expect(isTerminalStatus("CANCELLED")).toBe(true);
16
+ });
17
+
18
+ it("returns false for RUNNING", () => {
19
+ expect(isTerminalStatus("RUNNING")).toBe(false);
20
+ });
21
+
22
+ it("returns false for WAITING_FOR_INPUT", () => {
23
+ expect(isTerminalStatus("WAITING_FOR_INPUT")).toBe(false);
24
+ });
25
+
26
+ it("returns false for unknown status", () => {
27
+ expect(isTerminalStatus("UNKNOWN" as AgentStatus)).toBe(false);
28
+ });
29
+ });
@@ -0,0 +1,131 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ defineWorkflow,
4
+ type WorkflowInput,
5
+ type WorkflowSessionInput,
6
+ } from "./workflow";
7
+
8
+ describe("defineWorkflow", () => {
9
+ it("maps previousThreadId to threadId + continueThread", async () => {
10
+ let capturedSession: WorkflowSessionInput | undefined;
11
+
12
+ const workflow = defineWorkflow(async (_input, sessionInput) => {
13
+ capturedSession = sessionInput;
14
+ return { ok: true };
15
+ });
16
+
17
+ await workflow({}, { previousThreadId: "prev-42" });
18
+
19
+ expect(capturedSession).toEqual({
20
+ threadId: "prev-42",
21
+ continueThread: true,
22
+ });
23
+ });
24
+
25
+ it("maps sandboxId", async () => {
26
+ let capturedSession: WorkflowSessionInput | undefined;
27
+
28
+ const workflow = defineWorkflow(async (_input, sessionInput) => {
29
+ capturedSession = sessionInput;
30
+ return { ok: true };
31
+ });
32
+
33
+ await workflow({}, { sandboxId: "sb-123" });
34
+
35
+ expect(capturedSession).toEqual({ sandboxId: "sb-123" });
36
+ });
37
+
38
+ it("maps both previousThreadId and sandboxId together", async () => {
39
+ let capturedSession: WorkflowSessionInput | undefined;
40
+
41
+ const workflow = defineWorkflow(async (_input, sessionInput) => {
42
+ capturedSession = sessionInput;
43
+ return { ok: true };
44
+ });
45
+
46
+ await workflow({}, { previousThreadId: "prev-1", sandboxId: "sb-1" });
47
+
48
+ expect(capturedSession).toEqual({
49
+ threadId: "prev-1",
50
+ continueThread: true,
51
+ sandboxId: "sb-1",
52
+ });
53
+ });
54
+
55
+ it("returns empty sessionInput when no previousThreadId or sandboxId", async () => {
56
+ let capturedSession: WorkflowSessionInput | undefined;
57
+
58
+ const workflow = defineWorkflow(async (_input, sessionInput) => {
59
+ capturedSession = sessionInput;
60
+ return { ok: true };
61
+ });
62
+
63
+ await workflow({});
64
+
65
+ expect(capturedSession).toEqual({});
66
+ });
67
+
68
+ it("passes full input as first argument", async () => {
69
+ let capturedInput: unknown;
70
+
71
+ const workflow = defineWorkflow<{
72
+ prompt: string;
73
+ metadata: { key: string };
74
+ previousThreadId?: string;
75
+ sandboxId?: string;
76
+ }, { ok: boolean }>(async (input, _sessionInput) => {
77
+ capturedInput = input;
78
+ return { ok: true };
79
+ });
80
+
81
+ await workflow({
82
+ prompt: "research",
83
+ metadata: { key: "val" },
84
+ });
85
+
86
+ expect(capturedInput).toEqual({
87
+ prompt: "research",
88
+ metadata: { key: "val" },
89
+ });
90
+ });
91
+
92
+ it("passes workflowInput as second argument only", async () => {
93
+ let capturedInput: unknown;
94
+ let capturedSession: WorkflowSessionInput | undefined;
95
+
96
+ const workflow = defineWorkflow<{ prompt: string }, { ok: boolean }>(
97
+ async (input, sessionInput) => {
98
+ capturedInput = input;
99
+ capturedSession = sessionInput;
100
+ return { ok: true };
101
+ },
102
+ );
103
+
104
+ const workflowInput: WorkflowInput = {
105
+ previousThreadId: "prev",
106
+ sandboxId: "sb",
107
+ };
108
+ await workflow({ prompt: "go" }, workflowInput);
109
+
110
+ expect(capturedInput).toEqual({ prompt: "go" });
111
+ expect(capturedSession).toEqual({
112
+ threadId: "prev",
113
+ continueThread: true,
114
+ sandboxId: "sb",
115
+ });
116
+ });
117
+
118
+ it("returns the handler response unchanged", async () => {
119
+ const workflow = defineWorkflow(async () => ({
120
+ finalMessage: "result text",
121
+ threadId: "thread-123",
122
+ }));
123
+
124
+ const result = await workflow({});
125
+
126
+ expect(result).toEqual({
127
+ finalMessage: "result text",
128
+ threadId: "thread-123",
129
+ });
130
+ });
131
+ });
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Session config fields derived from a main workflow input, ready to spread
3
+ * into `createSession`.
4
+ */
5
+ export interface WorkflowSessionInput {
6
+ /** Thread ID to continue (set from `input.previousThreadId`) */
7
+ threadId?: string;
8
+ /** Whether to continue an existing thread (true when `previousThreadId` is present) */
9
+ continueThread?: boolean;
10
+ /** Optional sandbox ID forwarded to the session */
11
+ sandboxId?: string;
12
+ }
13
+
14
+ /** Raw workflow input fields that map into `WorkflowSessionInput`. */
15
+ export interface WorkflowInput {
16
+ /** When set, continue this thread instead of starting fresh */
17
+ previousThreadId?: string;
18
+ /** Optional sandbox ID to reuse */
19
+ sandboxId?: string;
20
+ }
21
+
22
+ /**
23
+ * Wraps a main workflow function, translating workflow input fields into
24
+ * session-compatible fields that can be spread directly into `createSession`.
25
+ *
26
+ * The wrapper:
27
+ * - Accepts a generic typed `input` as first argument
28
+ * - Accepts optional `workflowInput` ({ previousThreadId, sandboxId }) as second argument
29
+ * - Derives `threadId` + `continueThread` from `workflowInput.previousThreadId`
30
+ * - Derives `sandboxId` from `workflowInput.sandboxId`
31
+ */
32
+ export function defineWorkflow<TInput, TResult>(
33
+ fn: (input: TInput, sessionInput: WorkflowSessionInput) => Promise<TResult>,
34
+ ): (input: TInput, workflowInput?: WorkflowInput) => Promise<TResult> {
35
+ return async (input, workflowInput = {}) => {
36
+ const sessionInput: WorkflowSessionInput = {
37
+ ...(workflowInput.previousThreadId && {
38
+ threadId: workflowInput.previousThreadId,
39
+ continueThread: true,
40
+ }),
41
+ ...(workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }),
42
+ };
43
+ return fn(input, sessionInput);
44
+ };
45
+ }
package/src/workflow.ts CHANGED
@@ -25,6 +25,8 @@ export {
25
25
  proxySandboxOps,
26
26
  } from "./lib/session";
27
27
  export type { ZeitlichSession, ThreadOps, SessionConfig } from "./lib/session";
28
+ export { defineWorkflow } from "./lib/workflow";
29
+ export type { WorkflowInput, WorkflowSessionInput } from "./lib/workflow";
28
30
 
29
31
  // Thread utilities
30
32
  export { getShortId } from "./lib/thread";
@@ -45,7 +47,7 @@ export {
45
47
  hasNoOtherToolCalls,
46
48
  defineTool,
47
49
  } from "./lib/tool-router";
48
- export { defineSubagent } from "./lib/subagent";
50
+ export { defineSubagent, defineSubagentWorkflow } from "./lib/subagent";
49
51
  export type {
50
52
  // Tool definition types
51
53
  ToolDefinition,
@@ -130,10 +132,12 @@ export type {
130
132
  // Subagent types
131
133
  export type {
132
134
  SubagentConfig,
135
+ SubagentDefinition,
133
136
  SubagentHooks,
134
- SubagentInput,
135
137
  SubagentHandlerResponse,
136
138
  SubagentWorkflow,
139
+ SubagentWorkflowInput,
140
+ SubagentSessionInput,
137
141
  } from "./lib/subagent/types";
138
142
  // Sandbox types (workflow-safe — no activity-side code)
139
143
  export type {
@@ -159,6 +163,12 @@ export {
159
163
  // pulling activity-side code like VirtualSandboxFileSystem / Provider).
160
164
  export { applyVirtualTreeMutations } from "./adapters/sandbox/virtual/mutations";
161
165
  export { formatVirtualFileTree } from "./adapters/sandbox/virtual/tree";
166
+ export {
167
+ hasFileWithMimeType,
168
+ filesWithMimeType,
169
+ hasDirectory,
170
+ } from "./adapters/sandbox/virtual/queries";
171
+
162
172
  export type {
163
173
  FileEntry,
164
174
  FileEntryMetadata,