zeitlich 0.2.13 → 0.2.14

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 (135) hide show
  1. package/README.md +49 -38
  2. package/dist/adapters/sandbox/daytona/index.cjs +205 -0
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -0
  4. package/dist/adapters/sandbox/daytona/index.d.cts +86 -0
  5. package/dist/adapters/sandbox/daytona/index.d.ts +86 -0
  6. package/dist/adapters/sandbox/daytona/index.js +202 -0
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -0
  8. package/dist/adapters/sandbox/inmemory/index.cjs +174 -0
  9. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -0
  10. package/dist/adapters/sandbox/inmemory/index.d.cts +28 -0
  11. package/dist/adapters/sandbox/inmemory/index.d.ts +28 -0
  12. package/dist/adapters/sandbox/inmemory/index.js +172 -0
  13. package/dist/adapters/sandbox/inmemory/index.js.map +1 -0
  14. package/dist/adapters/sandbox/virtual/index.cjs +405 -0
  15. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -0
  16. package/dist/adapters/sandbox/virtual/index.d.cts +85 -0
  17. package/dist/adapters/sandbox/virtual/index.d.ts +85 -0
  18. package/dist/adapters/sandbox/virtual/index.js +400 -0
  19. package/dist/adapters/sandbox/virtual/index.js.map +1 -0
  20. package/dist/adapters/thread/google-genai/index.cjs +284 -0
  21. package/dist/adapters/thread/google-genai/index.cjs.map +1 -0
  22. package/dist/adapters/thread/google-genai/index.d.cts +145 -0
  23. package/dist/adapters/thread/google-genai/index.d.ts +145 -0
  24. package/dist/adapters/thread/google-genai/index.js +278 -0
  25. package/dist/adapters/thread/google-genai/index.js.map +1 -0
  26. package/dist/adapters/{langchain → thread/langchain}/index.cjs +7 -9
  27. package/dist/adapters/thread/langchain/index.cjs.map +1 -0
  28. package/dist/adapters/{langchain → thread/langchain}/index.d.cts +17 -21
  29. package/dist/adapters/{langchain → thread/langchain}/index.d.ts +17 -21
  30. package/dist/adapters/{langchain → thread/langchain}/index.js +7 -9
  31. package/dist/adapters/thread/langchain/index.js.map +1 -0
  32. package/dist/index.cjs +816 -545
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +235 -74
  35. package/dist/index.d.ts +235 -74
  36. package/dist/index.js +804 -540
  37. package/dist/index.js.map +1 -1
  38. package/dist/types-B4C9txdq.d.ts +389 -0
  39. package/dist/{thread-manager-qc0g5Rvd.d.cts → types-B9ljZewB.d.cts} +1 -6
  40. package/dist/{thread-manager-qc0g5Rvd.d.ts → types-B9ljZewB.d.ts} +1 -6
  41. package/dist/types-BMXzv7TN.d.cts +476 -0
  42. package/dist/types-BMXzv7TN.d.ts +476 -0
  43. package/dist/types-BVP87m_W.d.cts +121 -0
  44. package/dist/types-CDubRtad.d.cts +115 -0
  45. package/dist/types-CDubRtad.d.ts +115 -0
  46. package/dist/types-CwwgQ_9H.d.ts +121 -0
  47. package/dist/types-GpMU4b0w.d.cts +389 -0
  48. package/dist/workflow.cjs +444 -318
  49. package/dist/workflow.cjs.map +1 -1
  50. package/dist/workflow.d.cts +271 -222
  51. package/dist/workflow.d.ts +271 -222
  52. package/dist/workflow.js +440 -316
  53. package/dist/workflow.js.map +1 -1
  54. package/package.json +59 -6
  55. package/src/adapters/sandbox/daytona/filesystem.ts +136 -0
  56. package/src/adapters/sandbox/daytona/index.ts +149 -0
  57. package/src/adapters/sandbox/daytona/types.ts +34 -0
  58. package/src/adapters/sandbox/inmemory/index.ts +213 -0
  59. package/src/adapters/sandbox/virtual/filesystem.ts +345 -0
  60. package/src/adapters/sandbox/virtual/index.ts +88 -0
  61. package/src/adapters/sandbox/virtual/mutations.ts +38 -0
  62. package/src/adapters/sandbox/virtual/provider.ts +101 -0
  63. package/src/adapters/sandbox/virtual/tree.ts +82 -0
  64. package/src/adapters/sandbox/virtual/types.ts +127 -0
  65. package/src/adapters/sandbox/virtual/virtual-sandbox.test.ts +523 -0
  66. package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +91 -0
  67. package/src/adapters/thread/google-genai/activities.ts +121 -0
  68. package/src/adapters/thread/google-genai/index.ts +41 -0
  69. package/src/adapters/thread/google-genai/model-invoker.ts +154 -0
  70. package/src/adapters/thread/google-genai/thread-manager.ts +169 -0
  71. package/src/adapters/{langchain → thread/langchain}/activities.ts +11 -15
  72. package/src/adapters/{langchain → thread/langchain}/index.ts +1 -1
  73. package/src/adapters/{langchain → thread/langchain}/model-invoker.ts +15 -18
  74. package/src/adapters/{langchain → thread/langchain}/thread-manager.ts +1 -1
  75. package/src/index.ts +32 -24
  76. package/src/lib/activity.ts +87 -0
  77. package/src/lib/hooks/index.ts +11 -0
  78. package/src/lib/hooks/types.ts +98 -0
  79. package/src/lib/model/helpers.ts +6 -0
  80. package/src/lib/model/index.ts +13 -0
  81. package/src/lib/{model-invoker.ts → model/types.ts} +18 -1
  82. package/src/lib/sandbox/index.ts +19 -0
  83. package/src/lib/sandbox/manager.ts +76 -0
  84. package/src/lib/sandbox/sandbox.test.ts +158 -0
  85. package/src/lib/{fs.ts → sandbox/tree.ts} +6 -6
  86. package/src/lib/sandbox/types.ts +164 -0
  87. package/src/lib/session/index.ts +11 -0
  88. package/src/lib/{session.ts → session/session.ts} +76 -48
  89. package/src/lib/session/types.ts +93 -0
  90. package/src/lib/skills/fs-provider.ts +16 -15
  91. package/src/lib/skills/handler.ts +31 -0
  92. package/src/lib/skills/index.ts +5 -1
  93. package/src/lib/skills/register.ts +20 -0
  94. package/src/lib/skills/tool.ts +47 -0
  95. package/src/lib/state/index.ts +9 -0
  96. package/src/lib/{state-manager.ts → state/manager.ts} +10 -147
  97. package/src/lib/state/types.ts +134 -0
  98. package/src/lib/subagent/define.ts +71 -0
  99. package/src/lib/subagent/handler.ts +99 -0
  100. package/src/lib/subagent/index.ts +13 -0
  101. package/src/lib/subagent/register.ts +53 -0
  102. package/src/lib/subagent/tool.ts +80 -0
  103. package/src/lib/subagent/types.ts +92 -0
  104. package/src/lib/thread/index.ts +7 -0
  105. package/src/lib/{thread-manager.ts → thread/manager.ts} +1 -33
  106. package/src/lib/thread/types.ts +33 -0
  107. package/src/lib/tool-router/auto-append.ts +55 -0
  108. package/src/lib/tool-router/index.ts +41 -0
  109. package/src/lib/tool-router/router.ts +462 -0
  110. package/src/lib/tool-router/types.ts +478 -0
  111. package/src/lib/tool-router/with-sandbox.ts +70 -0
  112. package/src/lib/types.ts +5 -382
  113. package/src/tools/bash/bash.test.ts +53 -55
  114. package/src/tools/bash/handler.ts +23 -51
  115. package/src/tools/edit/handler.ts +67 -81
  116. package/src/tools/glob/handler.ts +60 -17
  117. package/src/tools/read-file/handler.ts +67 -0
  118. package/src/tools/read-skill/handler.ts +1 -31
  119. package/src/tools/read-skill/tool.ts +5 -47
  120. package/src/tools/subagent/handler.ts +1 -100
  121. package/src/tools/subagent/tool.ts +5 -93
  122. package/src/tools/task-create/handler.ts +1 -1
  123. package/src/tools/task-get/handler.ts +1 -1
  124. package/src/tools/task-list/handler.ts +1 -1
  125. package/src/tools/task-update/handler.ts +1 -1
  126. package/src/tools/write-file/handler.ts +47 -0
  127. package/src/workflow.ts +88 -47
  128. package/tsup.config.ts +8 -1
  129. package/dist/adapters/langchain/index.cjs.map +0 -1
  130. package/dist/adapters/langchain/index.js.map +0 -1
  131. package/dist/model-invoker-y_zlyMqu.d.cts +0 -892
  132. package/dist/model-invoker-y_zlyMqu.d.ts +0 -892
  133. package/src/lib/tool-router.ts +0 -977
  134. package/src/lib/workflow-helpers.ts +0 -50
  135. /package/src/lib/{thread-id.ts → thread/id.ts} +0 -0
@@ -1,111 +1,97 @@
1
1
  import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { SandboxContext } from "../../lib/tool-router/with-sandbox";
2
3
  import type { FileEditArgs } from "./tool";
3
- import type { IFileSystem } from "just-bash";
4
4
 
5
- /**
6
- * Result of an edit operation
7
- */
8
5
  interface EditResult {
9
6
  path: string;
10
7
  success: boolean;
11
8
  replacements: number;
12
9
  }
13
10
 
14
- /**
15
- * Escape special regex characters in a string
16
- */
17
11
  function escapeRegExp(str: string): string {
18
12
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
19
13
  }
20
14
 
21
15
  /**
22
- * Creates an edit handler that edits files within the scoped file tree.
16
+ * Edit tool handler performs string replacements in sandbox files.
23
17
  *
24
- * @param fs - File system implementation for I/O operations
25
- * @returns An ActivityToolHandler for edit tool calls
18
+ * Wrap with {@link withSandbox} at activity registration time to inject the
19
+ * sandbox automatically.
26
20
  */
27
- export function createEditHandler(
28
- fs: IFileSystem
29
- ): ActivityToolHandler<FileEditArgs, EditResult> {
30
- return async (args) => {
31
- const { file_path, old_string, new_string, replace_all = false } = args;
21
+ export const editHandler: ActivityToolHandler<
22
+ FileEditArgs,
23
+ EditResult,
24
+ SandboxContext
25
+ > = async (args, { sandbox }) => {
26
+ const { fs } = sandbox;
27
+ const { file_path, old_string, new_string, replace_all = false } = args;
28
+
29
+ if (old_string === new_string) {
30
+ return {
31
+ toolResponse: `Error: old_string and new_string must be different.`,
32
+ data: { path: file_path, success: false, replacements: 0 },
33
+ };
34
+ }
32
35
 
33
- // Validate old_string !== new_string
34
- if (old_string === new_string) {
36
+ try {
37
+ const exists = await fs.exists(file_path);
38
+ if (!exists) {
35
39
  return {
36
- toolResponse: `Error: old_string and new_string must be different.`,
40
+ toolResponse: `Error: File "${file_path}" does not exist.`,
37
41
  data: { path: file_path, success: false, replacements: 0 },
38
42
  };
39
43
  }
40
44
 
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);
45
+ const content = await fs.readFile(file_path);
53
46
 
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
- }
47
+ if (!content.includes(old_string)) {
48
+ return {
49
+ toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
50
+ data: { path: file_path, success: false, replacements: 0 },
51
+ };
52
+ }
61
53
 
62
- // Count occurrences
63
- const escapedOldString = escapeRegExp(old_string);
64
- const globalRegex = new RegExp(escapedOldString, "g");
65
- const occurrences = (content.match(globalRegex) || []).length;
54
+ const escapedOldString = escapeRegExp(old_string);
55
+ const globalRegex = new RegExp(escapedOldString, "g");
56
+ const occurrences = (content.match(globalRegex) || []).length;
66
57
 
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
- }
58
+ if (!replace_all && occurrences > 1) {
59
+ return {
60
+ toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
61
+ data: { path: file_path, success: false, replacements: 0 },
62
+ };
63
+ }
74
64
 
75
- // Perform replacement
76
- let newContent: string;
77
- let replacements: number;
65
+ let newContent: string;
66
+ let replacements: number;
78
67
 
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
- }
68
+ if (replace_all) {
69
+ newContent = content.split(old_string).join(new_string);
70
+ replacements = occurrences;
71
+ } else {
72
+ const index = content.indexOf(old_string);
73
+ newContent =
74
+ content.slice(0, index) +
75
+ new_string +
76
+ content.slice(index + old_string.length);
77
+ replacements = 1;
78
+ }
91
79
 
92
- // Write the modified content
93
- await fs.writeFile(file_path, newContent);
80
+ await fs.writeFile(file_path, newContent);
94
81
 
95
- const summary = replace_all
96
- ? `Replaced ${replacements} occurrence(s)`
97
- : `Replaced 1 occurrence`;
82
+ const summary = replace_all
83
+ ? `Replaced ${replacements} occurrence(s)`
84
+ : `Replaced 1 occurrence`;
98
85
 
99
- return {
100
- toolResponse: `${summary} in ${file_path}`,
101
- data: { path: file_path, success: true, replacements },
102
- };
103
- } catch (error) {
104
- const message = error instanceof Error ? error.message : "Unknown error";
105
- return {
106
- toolResponse: `Error editing file "${file_path}": ${message}`,
107
- data: { path: file_path, success: false, replacements: 0 },
108
- };
109
- }
110
- };
111
- }
86
+ return {
87
+ toolResponse: `${summary} in ${file_path}`,
88
+ data: { path: file_path, success: true, replacements },
89
+ };
90
+ } catch (error) {
91
+ const message = error instanceof Error ? error.message : "Unknown error";
92
+ return {
93
+ toolResponse: `Error editing file "${file_path}": ${message}`,
94
+ data: { path: file_path, success: false, replacements: 0 },
95
+ };
96
+ }
97
+ };
@@ -1,31 +1,74 @@
1
1
  import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { SandboxContext } from "../../lib/tool-router/with-sandbox";
2
3
  import type { GlobArgs } from "./tool";
3
- import type { IFileSystem } from "just-bash";
4
- import { Bash } from "just-bash";
4
+ import type { Sandbox } from "../../lib/sandbox/types";
5
5
 
6
- /**
7
- * Result of a glob operation
8
- */
9
6
  interface GlobResult {
10
7
  files: string[];
11
8
  }
12
9
 
13
10
  /**
14
- * Creates a glob handler that searches within the scoped file tree.
11
+ * Simple glob-style matcher (supports `*` and `**`).
12
+ */
13
+ function matchGlob(pattern: string, path: string): boolean {
14
+ const regex = pattern
15
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
16
+ .replace(/\*\*/g, "{{GLOBSTAR}}")
17
+ .replace(/\*/g, "[^/]*")
18
+ .replace(/\{\{GLOBSTAR\}\}/g, ".*");
19
+ return new RegExp(`^${regex}$`).test(path);
20
+ }
21
+
22
+ async function walk(
23
+ fs: Sandbox["fs"],
24
+ dir: string,
25
+ ): Promise<string[]> {
26
+ const results: string[] = [];
27
+ const entries = await fs.readdirWithFileTypes(dir);
28
+ for (const entry of entries) {
29
+ const full = dir === "/" ? `/${entry.name}` : `${dir}/${entry.name}`;
30
+ if (entry.isDirectory) {
31
+ results.push(...(await walk(fs, full)));
32
+ } else {
33
+ results.push(full);
34
+ }
35
+ }
36
+ return results;
37
+ }
38
+
39
+ /**
40
+ * Glob tool handler — searches files within a {@link Sandbox} filesystem.
15
41
  *
16
- * @param fs - File system implementation for I/O operations
17
- * @returns An ActivityToolHandler for glob tool calls
42
+ * Wrap with {@link withSandbox} at activity registration time to inject the
43
+ * sandbox automatically.
18
44
  */
19
- export function createGlobHandler(
20
- fs: IFileSystem
21
- ): ActivityToolHandler<GlobArgs, GlobResult> {
22
- return async (_args) => {
23
- // const { pattern, root } = args;
24
- const _bash = new Bash({ fs });
45
+ export const globHandler: ActivityToolHandler<
46
+ GlobArgs,
47
+ GlobResult,
48
+ SandboxContext
49
+ > = async (args, { sandbox }) => {
50
+ const { fs } = sandbox;
51
+ const { pattern, root = "/" } = args;
52
+
53
+ try {
54
+ const allFiles = await walk(fs, root);
55
+ const relativeTo = root.endsWith("/") ? root : `${root}/`;
56
+ const matched = allFiles
57
+ .map((f) => (f.startsWith(relativeTo) ? f.slice(relativeTo.length) : f))
58
+ .filter((f) => matchGlob(pattern, f));
25
59
 
26
60
  return {
27
- toolResponse: "Hello, world!",
61
+ toolResponse:
62
+ matched.length > 0
63
+ ? `Found ${matched.length} file(s):\n${matched.join("\n")}`
64
+ : `No files matched pattern "${pattern}"`,
65
+ data: { files: matched },
66
+ };
67
+ } catch (error) {
68
+ const message = error instanceof Error ? error.message : "Unknown error";
69
+ return {
70
+ toolResponse: `Error running glob: ${message}`,
28
71
  data: { files: [] },
29
72
  };
30
- };
31
- }
73
+ }
74
+ };
@@ -0,0 +1,67 @@
1
+ import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { SandboxContext } from "../../lib/tool-router/with-sandbox";
3
+ import type { FileReadArgs } from "./tool";
4
+
5
+ interface ReadFileResult {
6
+ path: string;
7
+ content: string;
8
+ totalLines?: number;
9
+ }
10
+
11
+ /**
12
+ * Read-file tool handler — reads files from a {@link Sandbox} filesystem.
13
+ *
14
+ * Wrap with {@link withSandbox} at activity registration time to inject the
15
+ * sandbox automatically.
16
+ */
17
+ export const readFileHandler: ActivityToolHandler<
18
+ FileReadArgs,
19
+ ReadFileResult | null,
20
+ SandboxContext
21
+ > = async (args, { sandbox }) => {
22
+ const { fs } = sandbox;
23
+ const { path, offset, limit } = args;
24
+
25
+ try {
26
+ const exists = await fs.exists(path);
27
+ if (!exists) {
28
+ return {
29
+ toolResponse: `Error: File "${path}" does not exist.`,
30
+ data: null,
31
+ };
32
+ }
33
+
34
+ const raw = await fs.readFile(path);
35
+ const lines = raw.split("\n");
36
+ const totalLines = lines.length;
37
+
38
+ if (offset !== undefined || limit !== undefined) {
39
+ const start = Math.max(0, (offset ?? 1) - 1);
40
+ const end = limit !== undefined ? start + limit : lines.length;
41
+ const slice = lines.slice(start, end);
42
+ const numbered = slice
43
+ .map((line, i) => `${String(start + i + 1).padStart(6)}|${line}`)
44
+ .join("\n");
45
+
46
+ return {
47
+ toolResponse: numbered,
48
+ data: { path, content: numbered, totalLines },
49
+ };
50
+ }
51
+
52
+ const numbered = lines
53
+ .map((line, i) => `${String(i + 1).padStart(6)}|${line}`)
54
+ .join("\n");
55
+
56
+ return {
57
+ toolResponse: numbered,
58
+ data: { path, content: numbered, totalLines },
59
+ };
60
+ } catch (error) {
61
+ const message = error instanceof Error ? error.message : "Unknown error";
62
+ return {
63
+ toolResponse: `Error reading file "${path}": ${message}`,
64
+ data: null,
65
+ };
66
+ }
67
+ };
@@ -1,31 +1 @@
1
- import type { Skill } from "../../lib/skills/types";
2
- import type { ToolHandlerResponse } from "../../lib/tool-router";
3
- import type { ReadSkillArgs } from "./tool";
4
-
5
- /**
6
- * Creates a ReadSkill handler that looks up skills from an in-memory array.
7
- * Runs directly in the workflow (like task tools) — no activity needed.
8
- */
9
- export function createReadSkillHandler(
10
- skills: Skill[]
11
- ): (args: ReadSkillArgs) => ToolHandlerResponse<null> {
12
- const skillMap = new Map(skills.map((s) => [s.name, s]));
13
-
14
- return (args: ReadSkillArgs): ToolHandlerResponse<null> => {
15
- const skill = skillMap.get(args.skill_name);
16
-
17
- if (!skill) {
18
- return {
19
- toolResponse: JSON.stringify({
20
- error: `Skill "${args.skill_name}" not found`,
21
- }),
22
- data: null,
23
- };
24
- }
25
-
26
- return {
27
- toolResponse: skill.instructions,
28
- data: null,
29
- };
30
- };
31
- }
1
+ export { createReadSkillHandler } from "../../lib/skills/handler";
@@ -1,47 +1,5 @@
1
- import z from "zod";
2
- import type { Skill } from "../../lib/skills/types";
3
-
4
- export const READ_SKILL_TOOL_NAME = "ReadSkill" as const;
5
-
6
- function buildReadSkillDescription(skills: Skill[]): string {
7
- const skillList = skills
8
- .map((s) => `- **${s.name}**: ${s.description}`)
9
- .join("\n");
10
-
11
- return `Load the full instructions for a skill. Read the skill before following its instructions.
12
-
13
- # Available skills:
14
- ${skillList}
15
- `;
16
- }
17
-
18
- /**
19
- * Creates a ReadSkill tool configured with the available skills.
20
- * The tool description embeds skill metadata so the agent discovers
21
- * skills purely through the tool definition.
22
- */
23
- export function createReadSkillTool(skills: Skill[]): {
24
- name: string;
25
- description: string;
26
- schema: z.ZodObject<{
27
- skill_name: z.ZodEnum<Record<string, string>>;
28
- }>;
29
- } {
30
- if (skills.length === 0) {
31
- throw new Error("createReadSkillTool requires at least one skill");
32
- }
33
-
34
- const names = skills.map((s) => s.name);
35
-
36
- return {
37
- name: READ_SKILL_TOOL_NAME,
38
- description: buildReadSkillDescription(skills),
39
- schema: z.object({
40
- skill_name: z.enum(names).describe("The name of the skill to load"),
41
- }),
42
- } as const;
43
- }
44
-
45
- export type ReadSkillArgs = {
46
- skill_name: string;
47
- };
1
+ export {
2
+ createReadSkillTool,
3
+ READ_SKILL_TOOL_NAME,
4
+ type ReadSkillArgs,
5
+ } from "../../lib/skills/tool";
@@ -1,100 +1 @@
1
- import { executeChild, workflowInfo } from "@temporalio/workflow";
2
- import { getShortId } from "../../lib/thread-id";
3
- import type { ToolHandlerResponse } from "../../lib/tool-router";
4
- import type { ToolMessageContent } from "../../lib/types";
5
- import type {
6
- InferSubagentResult,
7
- SubagentConfig,
8
- SubagentInput,
9
- } from "../../lib/types";
10
- import type { SubagentArgs } from "./tool";
11
- import type { z } from "zod";
12
-
13
- /**
14
- * Creates a Subagent tool handler that spawns child workflows for configured subagents.
15
- *
16
- * @param subagents - Array of subagent configurations
17
- * @returns A tool handler function that can be used with the tool router
18
- *
19
- * @example
20
- * const subagentHandler = subagentHandler([
21
- * {
22
- * name: "researcher",
23
- * description: "Researches topics",
24
- * workflow: "researcherWorkflow",
25
- * resultSchema: z.object({ findings: z.string() }),
26
- * },
27
- * ]);
28
- */
29
- export function createSubagentHandler<
30
- const T extends readonly SubagentConfig[],
31
- >(subagents: [...T]) {
32
- const { taskQueue: parentTaskQueue } = workflowInfo();
33
-
34
- return async (
35
- args: SubagentArgs
36
- ): Promise<ToolHandlerResponse<InferSubagentResult<T[number]> | null>> => {
37
- const config = subagents.find((s) => s.agentName === args.subagent);
38
-
39
- if (!config) {
40
- throw new Error(
41
- `Unknown subagent: ${args.subagent}. Available: ${subagents.map((s) => s.agentName).join(", ")}`
42
- );
43
- }
44
-
45
- const childWorkflowId = `${args.subagent}-${getShortId()}`;
46
-
47
- const input: SubagentInput = {
48
- prompt: args.prompt,
49
- ...(config.context && { context: config.context }),
50
- ...(args.threadId &&
51
- config.allowThreadContinuation && { threadId: args.threadId }),
52
- };
53
-
54
- const childOpts = {
55
- workflowId: childWorkflowId,
56
- args: [input] as const,
57
- taskQueue: config.taskQueue ?? parentTaskQueue,
58
- };
59
-
60
- const { toolResponse, data, usage, threadId: childThreadId } =
61
- typeof config.workflow === "string"
62
- ? await executeChild(config.workflow, childOpts)
63
- : await executeChild(config.workflow, childOpts);
64
-
65
- if (!toolResponse) {
66
- return {
67
- toolResponse: "Subagent workflow returned no response",
68
- data: null,
69
- ...(usage && { usage }),
70
- };
71
- }
72
-
73
- // Validate result if schema provided, otherwise pass through as-is
74
- const validated = (
75
- config.resultSchema ? config.resultSchema.safeParse(data) : null
76
- ) as z.ZodSafeParseResult<InferSubagentResult<T[number]>> | null;
77
-
78
- if (validated && !validated.success) {
79
- return {
80
- toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
81
- data: null,
82
- ...(usage && { usage }),
83
- };
84
- }
85
-
86
- let finalToolResponse: ToolMessageContent = toolResponse;
87
- if (config.allowThreadContinuation && childThreadId) {
88
- finalToolResponse =
89
- typeof toolResponse === "string"
90
- ? `${toolResponse}\n\n[Thread ID: ${childThreadId}]`
91
- : toolResponse;
92
- }
93
-
94
- return {
95
- toolResponse: finalToolResponse,
96
- data: validated ? validated.data : data,
97
- ...(usage && { usage }),
98
- };
99
- };
100
- }
1
+ export { createSubagentHandler } from "../../lib/subagent/handler";
@@ -1,93 +1,5 @@
1
- import z from "zod";
2
- import type { SubagentConfig } from "../../lib/types";
3
-
4
- export const SUBAGENT_TOOL_NAME = "Subagent" as const;
5
-
6
- /**
7
- * Builds the tool description with available subagent information
8
- */
9
- function buildSubagentDescription(subagents: SubagentConfig[]): string {
10
- const subagentList = subagents
11
- .map((s) => {
12
- const continuation = s.allowThreadContinuation
13
- ? "\n*(Supports thread continuation — pass a threadId to resume a previous conversation)*"
14
- : "";
15
- return `## ${s.agentName}\n${s.description}${continuation}`;
16
- })
17
- .join("\n\n");
18
-
19
- return `The ${SUBAGENT_TOOL_NAME} tool launches specialized agents (subagents) that autonomously handle complex work. Each agent type has specific capabilities and tools available to it.
20
-
21
- # Available subagents:
22
- ${subagentList}
23
- `;
24
- }
25
-
26
- /**
27
- * Creates a Subagent tool configured with the available subagents.
28
- *
29
- * @param subagents - Array of subagent configurations (must have at least one)
30
- * @returns A tool definition with dynamic schema based on available subagents
31
- *
32
- * @example
33
- * const subagentTool = createSubagentTool([
34
- * {
35
- * agentName: "researcher",
36
- * description: "Researches topics and gathers information",
37
- * workflow: "researcherWorkflow",
38
- * resultSchema: z.object({ findings: z.string() }),
39
- * },
40
- * ]);
41
- */
42
- export function createSubagentTool<T extends SubagentConfig[]>(
43
- subagents: T
44
- ): {
45
- readonly name: typeof SUBAGENT_TOOL_NAME;
46
- readonly description: string;
47
- readonly schema: z.ZodObject<z.ZodRawShape>;
48
- } {
49
- if (subagents.length === 0) {
50
- throw new Error("createTaskTool requires at least one subagent");
51
- }
52
-
53
- const names = subagents.map((s) => s.agentName);
54
- const hasThreadContinuation = subagents.some(
55
- (s) => s.allowThreadContinuation
56
- );
57
-
58
- const baseFields = {
59
- subagent: z.enum(names).describe("The type of subagent to launch"),
60
- description: z
61
- .string()
62
- .describe("A short (3-5 word) description of the task"),
63
- prompt: z.string().describe("The task for the agent to perform"),
64
- };
65
-
66
- const schema = hasThreadContinuation
67
- ? z.object({
68
- ...baseFields,
69
- threadId: z
70
- .string()
71
- .nullable()
72
- .describe(
73
- "Thread ID to continue an existing conversation, or null to start a new one"
74
- ),
75
- })
76
- : z.object(baseFields);
77
-
78
- return {
79
- name: SUBAGENT_TOOL_NAME,
80
- description: buildSubagentDescription(subagents),
81
- schema,
82
- } as const;
83
- }
84
-
85
- /**
86
- * Subagent tool args type (when subagent names are not known at compile time)
87
- */
88
- export type SubagentArgs = {
89
- subagent: string;
90
- description: string;
91
- prompt: string;
92
- threadId?: string;
93
- };
1
+ export {
2
+ createSubagentTool,
3
+ SUBAGENT_TOOL_NAME,
4
+ type SubagentArgs,
5
+ } from "../../lib/subagent/tool";
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
- } from "../../lib/state-manager";
4
+ } from "../../lib/state";
5
5
  import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
7
  import type { TaskCreateArgs } from "./tool";
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
- } from "../../lib/state-manager";
4
+ } from "../../lib/state";
5
5
  import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
7
  import type { TaskGetArgs } from "./tool";
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
- } from "../../lib/state-manager";
4
+ } from "../../lib/state";
5
5
  import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
7
  import type { TaskListArgs } from "./tool";
@@ -1,7 +1,7 @@
1
1
  import type {
2
2
  AgentStateManager,
3
3
  JsonSerializable,
4
- } from "../../lib/state-manager";
4
+ } from "../../lib/state";
5
5
  import type { ToolHandler } from "../../lib/tool-router";
6
6
  import type { WorkflowTask } from "../../lib/types";
7
7
  import type { TaskUpdateArgs } from "./tool";