@uncaged/workflow-agent-builtin 0.5.0-alpha.5

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 (92) hide show
  1. package/README.md +141 -0
  2. package/dist/agent.d.ts +3 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +89 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +5 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/detail.d.ts +13 -0
  11. package/dist/detail.d.ts.map +1 -0
  12. package/dist/detail.js +32 -0
  13. package/dist/detail.js.map +1 -0
  14. package/dist/index.d.ts +11 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +8 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/llm/index.d.ts +3 -0
  19. package/dist/llm/index.d.ts.map +1 -0
  20. package/dist/llm/index.js +2 -0
  21. package/dist/llm/index.js.map +1 -0
  22. package/dist/llm/llm.d.ts +5 -0
  23. package/dist/llm/llm.d.ts.map +1 -0
  24. package/dist/llm/llm.js +119 -0
  25. package/dist/llm/llm.js.map +1 -0
  26. package/dist/llm/types.d.ts +33 -0
  27. package/dist/llm/types.d.ts.map +1 -0
  28. package/dist/llm/types.js +2 -0
  29. package/dist/llm/types.js.map +1 -0
  30. package/dist/loop.d.ts +38 -0
  31. package/dist/loop.d.ts.map +1 -0
  32. package/dist/loop.js +156 -0
  33. package/dist/loop.js.map +1 -0
  34. package/dist/prompt.d.ts +11 -0
  35. package/dist/prompt.d.ts.map +1 -0
  36. package/dist/prompt.js +93 -0
  37. package/dist/prompt.js.map +1 -0
  38. package/dist/schemas.d.ts +4 -0
  39. package/dist/schemas.d.ts.map +1 -0
  40. package/dist/schemas.js +42 -0
  41. package/dist/schemas.js.map +1 -0
  42. package/dist/session.d.ts +10 -0
  43. package/dist/session.d.ts.map +1 -0
  44. package/dist/session.js +45 -0
  45. package/dist/session.js.map +1 -0
  46. package/dist/tools/index.d.ts +8 -0
  47. package/dist/tools/index.d.ts.map +1 -0
  48. package/dist/tools/index.js +33 -0
  49. package/dist/tools/index.js.map +1 -0
  50. package/dist/tools/path.d.ts +3 -0
  51. package/dist/tools/path.d.ts.map +1 -0
  52. package/dist/tools/path.js +6 -0
  53. package/dist/tools/path.js.map +1 -0
  54. package/dist/tools/read-file.d.ts +3 -0
  55. package/dist/tools/read-file.d.ts.map +1 -0
  56. package/dist/tools/read-file.js +39 -0
  57. package/dist/tools/read-file.js.map +1 -0
  58. package/dist/tools/run-command.d.ts +3 -0
  59. package/dist/tools/run-command.d.ts.map +1 -0
  60. package/dist/tools/run-command.js +81 -0
  61. package/dist/tools/run-command.js.map +1 -0
  62. package/dist/tools/types.d.ts +12 -0
  63. package/dist/tools/types.d.ts.map +1 -0
  64. package/dist/tools/types.js +2 -0
  65. package/dist/tools/types.js.map +1 -0
  66. package/dist/tools/write-file.d.ts +3 -0
  67. package/dist/tools/write-file.d.ts.map +1 -0
  68. package/dist/tools/write-file.js +35 -0
  69. package/dist/tools/write-file.js.map +1 -0
  70. package/dist/types.d.ts +42 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +2 -0
  73. package/dist/types.js.map +1 -0
  74. package/package.json +45 -0
  75. package/src/agent.ts +158 -0
  76. package/src/cli.ts +6 -0
  77. package/src/detail.ts +49 -0
  78. package/src/index.ts +16 -0
  79. package/src/llm/index.ts +7 -0
  80. package/src/llm/llm.ts +139 -0
  81. package/src/llm/types.ts +29 -0
  82. package/src/loop.ts +303 -0
  83. package/src/prompt.ts +115 -0
  84. package/src/schemas.ts +45 -0
  85. package/src/session.ts +59 -0
  86. package/src/tools/index.ts +44 -0
  87. package/src/tools/path.ts +6 -0
  88. package/src/tools/read-file.ts +41 -0
  89. package/src/tools/run-command.ts +95 -0
  90. package/src/tools/types.ts +13 -0
  91. package/src/tools/write-file.ts +36 -0
  92. package/src/types.ts +49 -0
@@ -0,0 +1,95 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolvePath } from "./path.js";
3
+ import type { BuiltinTool } from "./types.js";
4
+
5
+ const COMMAND_TIMEOUT_MS = 60_000;
6
+ const MAX_OUTPUT_CHARS = 32_000;
7
+
8
+ function isRecord(value: unknown): value is Record<string, unknown> {
9
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10
+ }
11
+
12
+ function truncate(text: string, maxChars: number): string {
13
+ if (text.length <= maxChars) {
14
+ return text;
15
+ }
16
+ return `${text.slice(0, maxChars)}\n...(truncated)`;
17
+ }
18
+
19
+ function runShell(
20
+ command: string,
21
+ cwd: string,
22
+ ): Promise<{ stdout: string; stderr: string; code: number }> {
23
+ return new Promise((resolve, reject) => {
24
+ const child = spawn(command, {
25
+ cwd,
26
+ env: process.env,
27
+ shell: true,
28
+ stdio: ["ignore", "pipe", "pipe"],
29
+ });
30
+
31
+ let stdout = "";
32
+ let stderr = "";
33
+ child.stdout?.on("data", (chunk: Buffer) => {
34
+ stdout += chunk.toString();
35
+ });
36
+ child.stderr?.on("data", (chunk: Buffer) => {
37
+ stderr += chunk.toString();
38
+ });
39
+
40
+ const timer = setTimeout(() => {
41
+ child.kill("SIGTERM");
42
+ }, COMMAND_TIMEOUT_MS);
43
+
44
+ child.on("error", (cause) => {
45
+ clearTimeout(timer);
46
+ const message = cause instanceof Error ? cause.message : String(cause);
47
+ reject(new Error(message));
48
+ });
49
+
50
+ child.on("close", (code) => {
51
+ clearTimeout(timer);
52
+ resolve({ stdout, stderr, code: code ?? 1 });
53
+ });
54
+ });
55
+ }
56
+
57
+ export const runCommandTool: BuiltinTool = {
58
+ name: "run_command",
59
+ description: "Run a shell command. Output is truncated to 32KB.",
60
+ parameters: {
61
+ type: "object",
62
+ required: ["command"],
63
+ properties: {
64
+ command: { type: "string", description: "Shell command to execute." },
65
+ cwd: {
66
+ type: "string",
67
+ description: "Optional working directory relative to workspace root.",
68
+ },
69
+ },
70
+ additionalProperties: false,
71
+ },
72
+ execute: async (args, ctx) => {
73
+ if (!isRecord(args) || typeof args.command !== "string") {
74
+ return "Error: command must be a string";
75
+ }
76
+ let workDir = ctx.cwd;
77
+ if (args.cwd !== undefined && args.cwd !== null) {
78
+ if (typeof args.cwd !== "string") {
79
+ return "Error: cwd must be a string";
80
+ }
81
+ workDir = resolvePath(ctx.cwd, args.cwd);
82
+ }
83
+ try {
84
+ const { stdout, stderr, code } = await runShell(args.command, workDir);
85
+ const out = truncate(
86
+ `exit_code: ${code}\n--- stdout ---\n${stdout}\n--- stderr ---\n${stderr}`,
87
+ MAX_OUTPUT_CHARS,
88
+ );
89
+ return out;
90
+ } catch (cause) {
91
+ const message = cause instanceof Error ? cause.message : String(cause);
92
+ return `Error: ${message}`;
93
+ }
94
+ },
95
+ };
@@ -0,0 +1,13 @@
1
+ import type { JSONSchema } from "@uncaged/json-cas";
2
+
3
+ export type ToolContext = {
4
+ cwd: string;
5
+ storageRoot: string;
6
+ };
7
+
8
+ export type BuiltinTool = {
9
+ name: string;
10
+ description: string;
11
+ parameters: JSONSchema;
12
+ execute: (args: unknown, ctx: ToolContext) => Promise<string>;
13
+ };
@@ -0,0 +1,36 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { resolvePath } from "./path.js";
4
+ import type { BuiltinTool } from "./types.js";
5
+
6
+ function isRecord(value: unknown): value is Record<string, unknown> {
7
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8
+ }
9
+
10
+ export const writeFileTool: BuiltinTool = {
11
+ name: "write_file",
12
+ description: "Write UTF-8 text to a file in the workspace (creates parent directories).",
13
+ parameters: {
14
+ type: "object",
15
+ required: ["path", "content"],
16
+ properties: {
17
+ path: { type: "string", description: "Relative or absolute path within the workspace." },
18
+ content: { type: "string", description: "File contents to write." },
19
+ },
20
+ additionalProperties: false,
21
+ },
22
+ execute: async (args, ctx) => {
23
+ if (!isRecord(args) || typeof args.path !== "string" || typeof args.content !== "string") {
24
+ return "Error: path and content must be strings";
25
+ }
26
+ const resolved = resolvePath(ctx.cwd, args.path);
27
+ try {
28
+ await mkdir(dirname(resolved), { recursive: true });
29
+ await writeFile(resolved, args.content, "utf8");
30
+ return `Wrote ${args.content.length} bytes to ${args.path}`;
31
+ } catch (cause) {
32
+ const message = cause instanceof Error ? cause.message : String(cause);
33
+ return `Error: ${message}`;
34
+ }
35
+ },
36
+ };
package/src/types.ts ADDED
@@ -0,0 +1,49 @@
1
+ import type { ChatMessage } from "./llm/index.js";
2
+
3
+ export type BuiltinToolCallRecord = {
4
+ id: string;
5
+ name: string;
6
+ args: string;
7
+ };
8
+
9
+ export type BuiltinToolResultRecord = {
10
+ toolCallId: string;
11
+ name: string;
12
+ content: string;
13
+ };
14
+
15
+ export type BuiltinLoopTurn = {
16
+ assistantContent: string | null;
17
+ toolCalls: BuiltinToolCallRecord[] | null;
18
+ toolResults: BuiltinToolResultRecord[] | null;
19
+ };
20
+
21
+ export type BuiltinSessionState = {
22
+ sessionId: string;
23
+ model: string;
24
+ startedAtMs: number;
25
+ messages: ChatMessage[];
26
+ turns: BuiltinLoopTurn[];
27
+ };
28
+
29
+ export type BuiltinTurnRole = "assistant" | "tool";
30
+
31
+ export type BuiltinToolCall = {
32
+ name: string;
33
+ args: string;
34
+ };
35
+
36
+ export type BuiltinTurnPayload = {
37
+ role: BuiltinTurnRole;
38
+ content: string;
39
+ toolCalls: BuiltinToolCall[] | null;
40
+ reasoning: string | null;
41
+ };
42
+
43
+ export type BuiltinDetailPayload = {
44
+ sessionId: string;
45
+ model: string;
46
+ duration: number;
47
+ turnCount: number;
48
+ turns: string[];
49
+ };