zeitlich 0.2.2 → 0.2.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.
Files changed (45) hide show
  1. package/README.md +34 -31
  2. package/dist/index.cjs +305 -361
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +24 -43
  5. package/dist/index.d.ts +24 -43
  6. package/dist/index.js +277 -336
  7. package/dist/index.js.map +1 -1
  8. package/dist/{workflow-BQf5EfNN.d.cts → workflow-D-2vp4Pq.d.cts} +265 -241
  9. package/dist/{workflow-BQf5EfNN.d.ts → workflow-D-2vp4Pq.d.ts} +265 -241
  10. package/dist/workflow.cjs +206 -253
  11. package/dist/workflow.cjs.map +1 -1
  12. package/dist/workflow.d.cts +2 -3
  13. package/dist/workflow.d.ts +2 -3
  14. package/dist/workflow.js +182 -231
  15. package/dist/workflow.js.map +1 -1
  16. package/package.json +3 -2
  17. package/src/activities.ts +1 -14
  18. package/src/index.ts +14 -11
  19. package/src/lib/session.ts +56 -99
  20. package/src/lib/thread-manager.ts +45 -37
  21. package/src/lib/tool-router.ts +143 -103
  22. package/src/lib/types.ts +32 -25
  23. package/src/tools/ask-user-question/handler.ts +5 -5
  24. package/src/tools/ask-user-question/tool.ts +3 -2
  25. package/src/tools/bash/bash.test.ts +12 -12
  26. package/src/tools/bash/handler.ts +5 -5
  27. package/src/tools/bash/tool.ts +3 -2
  28. package/src/tools/edit/handler.ts +78 -123
  29. package/src/tools/edit/tool.ts +3 -2
  30. package/src/tools/glob/handler.ts +17 -48
  31. package/src/tools/glob/tool.ts +3 -2
  32. package/src/tools/grep/tool.ts +3 -2
  33. package/src/tools/{read → read-file}/tool.ts +3 -2
  34. package/src/tools/task/handler.ts +2 -2
  35. package/src/tools/task/tool.ts +2 -9
  36. package/src/tools/task-create/handler.ts +5 -11
  37. package/src/tools/task-create/tool.ts +3 -2
  38. package/src/tools/task-get/handler.ts +5 -10
  39. package/src/tools/task-get/tool.ts +3 -2
  40. package/src/tools/task-list/handler.ts +5 -10
  41. package/src/tools/task-list/tool.ts +3 -2
  42. package/src/tools/task-update/handler.ts +5 -12
  43. package/src/tools/task-update/tool.ts +3 -2
  44. package/src/tools/{write → write-file}/tool.ts +5 -6
  45. package/src/workflow.ts +23 -19
@@ -1,7 +1,7 @@
1
1
  import { dirname } from "path";
2
2
  import { fileURLToPath } from "url";
3
3
  import { describe, expect, it } from "vitest";
4
- import { handleBashTool } from "./handler";
4
+ import { createBashHandler } from "./handler";
5
5
  import { OverlayFs } from "just-bash";
6
6
 
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -10,7 +10,7 @@ describe("bash with default options", () => {
10
10
  const fs = new OverlayFs({ root: __dirname, mountPoint: "/home/user" });
11
11
 
12
12
  it("executes echo and captures stdout", async () => {
13
- const { data } = await handleBashTool({fs})(
13
+ const { data } = await createBashHandler({fs})(
14
14
  { command: "echo 'hello world'" },
15
15
  {}
16
16
  );
@@ -20,17 +20,17 @@ describe("bash with default options", () => {
20
20
  });
21
21
 
22
22
  it("returns exit code 0 for successful commands", async () => {
23
- const { data } = await handleBashTool({fs})({ command: "true" }, {});
23
+ const { data } = await createBashHandler({fs})({ command: "true" }, {});
24
24
  expect(data?.exitCode).toBe(0);
25
25
  });
26
26
 
27
27
  it("returns non-zero exit code for failed commands", async () => {
28
- const { data } = await handleBashTool({fs})({ command: "false" }, {});
28
+ const { data } = await createBashHandler({fs})({ command: "false" }, {});
29
29
  expect(data?.exitCode).toBe(1);
30
30
  });
31
31
 
32
32
  it("captures stderr output", async () => {
33
- const { data } = await handleBashTool({fs})(
33
+ const { data } = await createBashHandler({fs})(
34
34
  { command: "echo 'error message' >&2" },
35
35
  {}
36
36
  );
@@ -39,7 +39,7 @@ describe("bash with default options", () => {
39
39
  });
40
40
 
41
41
  it("supports piping between commands", async () => {
42
- const { data } = await handleBashTool({fs})(
42
+ const { data } = await createBashHandler({fs})(
43
43
  { command: "echo 'hello world' | tr 'a-z' 'A-Z'" },
44
44
  {}
45
45
  );
@@ -47,7 +47,7 @@ describe("bash with default options", () => {
47
47
  });
48
48
 
49
49
  it("supports command chaining with &&", async () => {
50
- const { data } = await handleBashTool({fs})(
50
+ const { data } = await createBashHandler({fs})(
51
51
  { command: "echo 'first' && echo 'second'" },
52
52
  {}
53
53
  );
@@ -56,7 +56,7 @@ describe("bash with default options", () => {
56
56
  });
57
57
 
58
58
  it("handles multi-line output", async () => {
59
- const { data } = await handleBashTool({fs})(
59
+ const { data } = await createBashHandler({fs})(
60
60
  { command: "printf 'line1\\nline2\\nline3'" },
61
61
  {}
62
62
  );
@@ -67,7 +67,7 @@ describe("bash with default options", () => {
67
67
  });
68
68
 
69
69
  it("handles commands with arguments and flags", async () => {
70
- const { data } = await handleBashTool({fs})(
70
+ const { data } = await createBashHandler({fs})(
71
71
  { command: "echo -n 'no newline'" },
72
72
  {}
73
73
  );
@@ -75,7 +75,7 @@ describe("bash with default options", () => {
75
75
  });
76
76
 
77
77
  it("supports command substitution", async () => {
78
- const { data } = await handleBashTool({fs})(
78
+ const { data } = await createBashHandler({fs})(
79
79
  { command: "echo \"count: $(echo 'a b c' | wc -w | tr -d ' ')\"" },
80
80
  {}
81
81
  );
@@ -83,7 +83,7 @@ describe("bash with default options", () => {
83
83
  });
84
84
 
85
85
  it("returns toolResponse string with formatted output", async () => {
86
- const { toolResponse } = await handleBashTool({fs})(
86
+ const { toolResponse } = await createBashHandler({fs})(
87
87
  { command: "echo 'test'" },
88
88
  {}
89
89
  );
@@ -96,7 +96,7 @@ describe("bash with default options", () => {
96
96
  describe("bash with overlay filesystem", () => {
97
97
  it("sees files in the current directory", async () => {
98
98
  const fs = new OverlayFs({ root: __dirname, mountPoint: "/home/user" });
99
- const { data } = await handleBashTool({fs})({ command: "ls" }, {});
99
+ const { data } = await createBashHandler({fs})({ command: "ls" }, {});
100
100
  expect(data?.stdout).toContain("bash.test.ts");
101
101
  expect(data?.stdout).toContain("handler.ts");
102
102
  expect(data?.stdout).toContain("tool.ts");
@@ -1,5 +1,5 @@
1
- import type { ActivityToolHandler } from "../../workflow";
2
- import type { bashToolSchemaType } from "./tool";
1
+ import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { BashArgs } from "./tool";
3
3
  import { Bash, type BashOptions } from "just-bash";
4
4
 
5
5
  type BashExecOut = {
@@ -11,10 +11,10 @@ type BashExecOut = {
11
11
  /** BashOptions with `fs` required */
12
12
  type BashToolOptions = Required<Pick<BashOptions, "fs">> & Omit<BashOptions, "fs">;
13
13
 
14
- export const handleBashTool: (
14
+ export const createBashHandler: (
15
15
  bashOptions: BashToolOptions,
16
- ) => ActivityToolHandler<bashToolSchemaType, BashExecOut | null> =
17
- (bashOptions: BashToolOptions) => async (args: bashToolSchemaType, _context) => {
16
+ ) => ActivityToolHandler<BashArgs, BashExecOut | null> =
17
+ (bashOptions: BashToolOptions) => async (args: BashArgs, _context) => {
18
18
  const { command } = args;
19
19
 
20
20
  const mergedOptions: BashOptions = {
@@ -1,4 +1,5 @@
1
1
  import z from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const createBashToolDescription = ({
4
5
  fileTree,
@@ -31,6 +32,6 @@ Use this tool to:
31
32
  ),
32
33
  }),
33
34
  strict: true,
34
- };
35
+ } satisfies ToolDefinition;
35
36
 
36
- export type bashToolSchemaType = z.infer<typeof bashTool.schema>;
37
+ export type BashArgs = z.infer<typeof bashTool.schema>;
@@ -1,38 +1,16 @@
1
- import type { EditToolSchemaType } from "./tool";
1
+ import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { FileEditArgs } from "./tool";
2
3
  import type { IFileSystem } from "just-bash";
3
4
 
4
5
  /**
5
6
  * Result of an edit operation
6
7
  */
7
- export interface EditResult {
8
+ interface EditResult {
8
9
  path: string;
9
10
  success: boolean;
10
11
  replacements: number;
11
12
  }
12
13
 
13
- /**
14
- * Edit handler response
15
- */
16
- export interface EditHandlerResponse {
17
- toolResponse: string;
18
- data: EditResult;
19
- }
20
-
21
- /**
22
- * Options for edit handler
23
- */
24
- export interface EditHandlerOptions {
25
- /**
26
- * Set of file paths that have been read in this session.
27
- * Required for enforcing read-before-write policy.
28
- */
29
- readFiles: Set<string>;
30
- /**
31
- * If true, skip the read-before-write check (not recommended)
32
- */
33
- skipReadCheck?: boolean;
34
- }
35
-
36
14
  /**
37
15
  * Escape special regex characters in a string
38
16
  */
@@ -41,116 +19,93 @@ function escapeRegExp(str: string): string {
41
19
  }
42
20
 
43
21
  /**
44
- * Edit handler that edits files within the scoped file tree.
22
+ * Creates an edit handler that edits files within the scoped file tree.
45
23
  *
46
- * @param args - Tool arguments (file_path, old_string, new_string, replace_all)
47
- * @param options - Additional options (readFiles, skipReadCheck)
24
+ * @param fs - File system implementation for I/O operations
25
+ * @returns An ActivityToolHandler for edit tool calls
48
26
  */
49
- export async function editHandler(
50
- args: EditToolSchemaType,
27
+ export function createEditHandler(
51
28
  fs: IFileSystem
52
- ): Promise<EditHandlerResponse> {
53
- const { file_path, old_string, new_string, replace_all = false } = args;
54
-
55
- // Validate old_string !== new_string
56
- if (old_string === new_string) {
57
- return {
58
- toolResponse: `Error: old_string and new_string must be different.`,
59
- data: {
60
- path: file_path,
61
- success: false,
62
- replacements: 0,
63
- },
64
- };
65
- }
29
+ ): ActivityToolHandler<FileEditArgs, EditResult> {
30
+ return async (args) => {
31
+ const { file_path, old_string, new_string, replace_all = false } = args;
66
32
 
67
- try {
68
- // Check if file exists
69
- const exists = await fs.exists(file_path);
70
- if (!exists) {
33
+ // Validate old_string !== new_string
34
+ if (old_string === new_string) {
71
35
  return {
72
- toolResponse: `Error: File "${file_path}" does not exist.`,
73
- data: {
74
- path: file_path,
75
- success: false,
76
- replacements: 0,
77
- },
36
+ toolResponse: `Error: old_string and new_string must be different.`,
37
+ data: { path: file_path, success: false, replacements: 0 },
78
38
  };
79
39
  }
80
40
 
81
- // Read current content
82
- const content = await fs.readFile(file_path);
41
+ try {
42
+ // Check if file exists
43
+ const exists = await fs.exists(file_path);
44
+ if (!exists) {
45
+ return {
46
+ toolResponse: `Error: File "${file_path}" does not exist.`,
47
+ data: { path: file_path, success: false, replacements: 0 },
48
+ };
49
+ }
50
+
51
+ // Read current content
52
+ const content = await fs.readFile(file_path);
53
+
54
+ // Check if old_string exists in the file
55
+ if (!content.includes(old_string)) {
56
+ return {
57
+ toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
58
+ data: { path: file_path, success: false, replacements: 0 },
59
+ };
60
+ }
61
+
62
+ // Count occurrences
63
+ const escapedOldString = escapeRegExp(old_string);
64
+ const globalRegex = new RegExp(escapedOldString, "g");
65
+ const occurrences = (content.match(globalRegex) || []).length;
66
+
67
+ // Check uniqueness if not replace_all
68
+ if (!replace_all && occurrences > 1) {
69
+ return {
70
+ toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
71
+ data: { path: file_path, success: false, replacements: 0 },
72
+ };
73
+ }
74
+
75
+ // Perform replacement
76
+ let newContent: string;
77
+ let replacements: number;
78
+
79
+ if (replace_all) {
80
+ newContent = content.split(old_string).join(new_string);
81
+ replacements = occurrences;
82
+ } else {
83
+ // Replace only the first occurrence
84
+ const index = content.indexOf(old_string);
85
+ newContent =
86
+ content.slice(0, index) +
87
+ new_string +
88
+ content.slice(index + old_string.length);
89
+ replacements = 1;
90
+ }
91
+
92
+ // Write the modified content
93
+ await fs.writeFile(file_path, newContent);
94
+
95
+ const summary = replace_all
96
+ ? `Replaced ${replacements} occurrence(s)`
97
+ : `Replaced 1 occurrence`;
83
98
 
84
- // Check if old_string exists in the file
85
- if (!content.includes(old_string)) {
86
99
  return {
87
- toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
88
- data: {
89
- path: file_path,
90
- success: false,
91
- replacements: 0,
92
- },
100
+ toolResponse: `${summary} in ${file_path}`,
101
+ data: { path: file_path, success: true, replacements },
93
102
  };
94
- }
95
-
96
- // Count occurrences
97
- const escapedOldString = escapeRegExp(old_string);
98
- const globalRegex = new RegExp(escapedOldString, "g");
99
- const occurrences = (content.match(globalRegex) || []).length;
100
-
101
- // Check uniqueness if not replace_all
102
- if (!replace_all && occurrences > 1) {
103
+ } catch (error) {
104
+ const message = error instanceof Error ? error.message : "Unknown error";
103
105
  return {
104
- toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
105
- data: {
106
- path: file_path,
107
- success: false,
108
- replacements: 0,
109
- },
106
+ toolResponse: `Error editing file "${file_path}": ${message}`,
107
+ data: { path: file_path, success: false, replacements: 0 },
110
108
  };
111
109
  }
112
-
113
- // Perform replacement
114
- let newContent: string;
115
- let replacements: number;
116
-
117
- if (replace_all) {
118
- newContent = content.split(old_string).join(new_string);
119
- replacements = occurrences;
120
- } else {
121
- // Replace only the first occurrence
122
- const index = content.indexOf(old_string);
123
- newContent =
124
- content.slice(0, index) +
125
- new_string +
126
- content.slice(index + old_string.length);
127
- replacements = 1;
128
- }
129
-
130
- // Write the modified content
131
- await fs.writeFile(file_path, newContent);
132
-
133
- const summary = replace_all
134
- ? `Replaced ${replacements} occurrence(s)`
135
- : `Replaced 1 occurrence`;
136
-
137
- return {
138
- toolResponse: `${summary} in ${file_path}`,
139
- data: {
140
- path: file_path,
141
- success: true,
142
- replacements,
143
- },
144
- };
145
- } catch (error) {
146
- const message = error instanceof Error ? error.message : "Unknown error";
147
- return {
148
- toolResponse: `Error editing file "${file_path}": ${message}`,
149
- data: {
150
- path: file_path,
151
- success: false,
152
- replacements: 0,
153
- },
154
- };
155
- }
110
+ };
156
111
  }
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const editTool = {
4
5
  name: "FileEdit" as const,
@@ -34,6 +35,6 @@ IMPORTANT:
34
35
  ),
35
36
  }),
36
37
  strict: true,
37
- };
38
+ } satisfies ToolDefinition;
38
39
 
39
- export type EditToolSchemaType = z.infer<typeof editTool.schema>;
40
+ export type FileEditArgs = z.infer<typeof editTool.schema>;
@@ -1,62 +1,31 @@
1
+ import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { GlobArgs } from "./tool";
1
3
  import type { IFileSystem } from "just-bash";
2
4
  import { Bash } from "just-bash";
3
- import type { GlobToolSchemaType } from "./tool";
4
5
 
5
6
  /**
6
7
  * Result of a glob operation
7
8
  */
8
- export interface GlobResult {
9
+ interface GlobResult {
9
10
  files: string[];
10
11
  }
11
12
 
12
13
  /**
13
- * Glob handler response
14
- */
15
- export interface GlobHandlerResponse {
16
- toolResponse: string;
17
- data: GlobResult;
18
- }
19
-
20
- /**
21
- * Glob handler that searches within the scoped file tree.
14
+ * Creates a glob handler that searches within the scoped file tree.
22
15
  *
23
- * @param args - Tool arguments (pattern, root)
24
- * @param provider - FileSystemProvider for I/O operations
16
+ * @param fs - File system implementation for I/O operations
17
+ * @returns An ActivityToolHandler for glob tool calls
25
18
  */
26
- export async function globHandler(
27
- _args: GlobToolSchemaType,
19
+ export function createGlobHandler(
28
20
  fs: IFileSystem
29
- ): Promise<GlobHandlerResponse> {
30
- // const { pattern, root } = args;
31
- const _bash = new Bash({ fs });
32
-
33
- return Promise.resolve({
34
- toolResponse: "Hello, world!",
35
- data: { files: [] },
36
- });
37
-
38
- // try {
39
- // const matches = await bash.exec(`glob ${root} -name "${pattern}"`);
40
-
41
- // if (matches.length === 0) {
42
- // return {
43
- // content: `No files found matching pattern: ${pattern}`,
44
- // result: { files: [] },
45
- // };
46
- // }
47
-
48
- // const paths = matches.map((node) => node.path);
49
- // const fileList = paths.map((p) => ` ${p}`).join("\n");
50
-
51
- // return {
52
- // content: `Found ${matches.length} file(s) matching "${pattern}":\n${fileList}`,
53
- // result: { files: matches },
54
- // };
55
- // } catch (error) {
56
- // const message = error instanceof Error ? error.message : "Unknown error";
57
- // return {
58
- // content: `Error searching for files: ${message}`,
59
- // result: { files: [] },
60
- // };
61
- // }
21
+ ): ActivityToolHandler<GlobArgs, GlobResult> {
22
+ return async (_args) => {
23
+ // const { pattern, root } = args;
24
+ const _bash = new Bash({ fs });
25
+
26
+ return {
27
+ toolResponse: "Hello, world!",
28
+ data: { files: [] },
29
+ };
30
+ };
62
31
  }
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const globTool = {
4
5
  name: "Glob" as const,
@@ -22,6 +23,6 @@ Examples:
22
23
  .describe("Optional root directory to search from"),
23
24
  }),
24
25
  strict: true,
25
- };
26
+ } satisfies ToolDefinition;
26
27
 
27
- export type GlobToolSchemaType = z.infer<typeof globTool.schema>;
28
+ export type GlobArgs = z.infer<typeof globTool.schema>;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const grepTool = {
4
5
  name: "Grep" as const,
@@ -40,6 +41,6 @@ Examples:
40
41
  .describe("Number of context lines to show around matches"),
41
42
  }),
42
43
  strict: true,
43
- };
44
+ } satisfies ToolDefinition;
44
45
 
45
- export type GrepToolSchemaType = z.infer<typeof grepTool.schema>;
46
+ export type GrepArgs = z.infer<typeof grepTool.schema>;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const readTool = {
4
5
  name: "FileRead" as const,
@@ -28,6 +29,6 @@ The tool returns the file content in an appropriate format:
28
29
  .describe("Maximum number of lines to read (for text files)"),
29
30
  }),
30
31
  strict: true,
31
- };
32
+ } satisfies ToolDefinition;
32
33
 
33
- export type ReadToolSchemaType = z.infer<typeof readTool.schema>;
34
+ export type FileReadArgs = z.infer<typeof readTool.schema>;
@@ -1,7 +1,7 @@
1
1
  import { executeChild, workflowInfo, uuid4 } from "@temporalio/workflow";
2
2
  import type { ToolHandlerResponse } from "../../lib/tool-router";
3
3
  import type { SubagentConfig, SubagentInput } from "../../lib/types";
4
- import type { GenericTaskToolSchemaType } from "./tool";
4
+ import type { TaskArgs } from "./tool";
5
5
 
6
6
  /**
7
7
  * Result from a task handler execution
@@ -34,7 +34,7 @@ export function createTaskHandler(subagents: SubagentConfig[]) {
34
34
  workflowInfo();
35
35
 
36
36
  return async (
37
- args: GenericTaskToolSchemaType
37
+ args: TaskArgs
38
38
  ): Promise<ToolHandlerResponse<TaskHandlerResult>> => {
39
39
  const config = subagents.find((s) => s.name === args.subagent);
40
40
 
@@ -80,16 +80,9 @@ export function createTaskTool<T extends SubagentConfig[]>(
80
80
  }
81
81
 
82
82
  /**
83
- * Infer the schema type for a task tool created with specific subagents
83
+ * Task tool args type (when subagent names are not known at compile time)
84
84
  */
85
- export type TaskToolSchemaType<T extends SubagentConfig[]> = z.infer<
86
- ReturnType<typeof createTaskTool<T>>["schema"]
87
- >;
88
-
89
- /**
90
- * Generic task tool schema type (when subagent names are not known at compile time)
91
- */
92
- export type GenericTaskToolSchemaType = {
85
+ export type TaskArgs = {
93
86
  subagent: string;
94
87
  description: string;
95
88
  prompt: string;
@@ -2,29 +2,23 @@ import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
4
  } from "../../lib/state-manager";
5
- import type { ToolHandlerResponse } from "../../lib/tool-router";
5
+ import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
- import type { TaskCreateToolSchemaType } from "./tool";
7
+ import type { TaskCreateArgs } from "./tool";
8
8
  import { uuid4 } from "@temporalio/workflow";
9
9
 
10
10
  /**
11
11
  * Creates a TaskCreate handler that adds tasks to the workflow state.
12
12
  *
13
13
  * @param stateManager - State manager containing tasks state
14
- * @param idGenerator - Function to generate unique task IDs (e.g., uuid4 from Temporal)
15
- * @returns A tool handler function
16
- *
17
- * @example
18
- * const handler = createTaskCreateHandler(stateManager, uuid4);
14
+ * @returns A ToolHandler for TaskCreate tool calls
19
15
  */
20
16
  export function createTaskCreateHandler<
21
17
  TCustom extends JsonSerializable<TCustom>,
22
18
  >(
23
19
  stateManager: AgentStateManager<TCustom>
24
- ): (args: TaskCreateToolSchemaType) => ToolHandlerResponse<WorkflowTask> {
25
- return (
26
- args: TaskCreateToolSchemaType
27
- ): ToolHandlerResponse<WorkflowTask> => {
20
+ ): ToolHandler<TaskCreateArgs, WorkflowTask> {
21
+ return (args) => {
28
22
  const task: WorkflowTask = {
29
23
  id: uuid4(),
30
24
  subject: args.subject,
@@ -1,4 +1,5 @@
1
1
  import z from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const taskCreateTool = {
4
5
  name: "TaskCreate" as const,
@@ -61,6 +62,6 @@ export const taskCreateTool = {
61
62
  .record(z.string(), z.string())
62
63
  .describe("Arbitrary key-value pairs for tracking"),
63
64
  }),
64
- };
65
+ } satisfies ToolDefinition;
65
66
 
66
- export type TaskCreateToolSchemaType = z.infer<typeof taskCreateTool.schema>;
67
+ export type TaskCreateArgs = z.infer<typeof taskCreateTool.schema>;
@@ -2,25 +2,20 @@ import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
4
  } from "../../lib/state-manager";
5
- import type { ToolHandlerResponse } from "../../lib/tool-router";
5
+ import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
- import type { TaskGetToolSchemaType } from "./tool";
7
+ import type { TaskGetArgs } from "./tool";
8
8
 
9
9
  /**
10
10
  * Creates a TaskGet handler that retrieves a task by ID.
11
11
  *
12
12
  * @param stateManager - State manager containing tasks state
13
- * @returns A tool handler function
14
- *
15
- * @example
16
- * const handler = createTaskGetHandler(stateManager);
13
+ * @returns A ToolHandler for TaskGet tool calls
17
14
  */
18
15
  export function createTaskGetHandler<TCustom extends JsonSerializable<TCustom>>(
19
16
  stateManager: AgentStateManager<TCustom>
20
- ): (args: TaskGetToolSchemaType) => ToolHandlerResponse<WorkflowTask | null> {
21
- return (
22
- args: TaskGetToolSchemaType
23
- ): ToolHandlerResponse<WorkflowTask | null> => {
17
+ ): ToolHandler<TaskGetArgs, WorkflowTask | null> {
18
+ return (args) => {
24
19
  const task = stateManager.getTask(args.taskId) ?? null;
25
20
 
26
21
  if (!task) {
@@ -1,4 +1,5 @@
1
1
  import z from "zod";
2
+ import type { ToolDefinition } from "../../lib/tool-router";
2
3
 
3
4
  export const taskGetTool = {
4
5
  name: "TaskGet" as const,
@@ -6,6 +7,6 @@ export const taskGetTool = {
6
7
  schema: z.object({
7
8
  taskId: z.string().describe("The ID of the task to get"),
8
9
  }),
9
- };
10
+ } satisfies ToolDefinition;
10
11
 
11
- export type TaskGetToolSchemaType = z.infer<typeof taskGetTool.schema>;
12
+ export type TaskGetArgs = z.infer<typeof taskGetTool.schema>;