@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
package/dist/loop.js ADDED
@@ -0,0 +1,156 @@
1
+ import { createLogger } from "@uncaged/workflow-util";
2
+ import { chatCompletionWithTools, } from "./llm/index.js";
3
+ import { appendSessionTurn } from "./session.js";
4
+ import { builtinToolsToOpenAi, executeBuiltinTool, getBuiltinTools, } from "./tools/index.js";
5
+ const log = createLogger({ sink: { kind: "stderr" } });
6
+ export const BUILTIN_MAX_TURNS = 30;
7
+ export const BUILTIN_CONTINUE_MAX_TURNS = 5;
8
+ function mapToolCallsForPayload(calls) {
9
+ return calls.map((call) => ({
10
+ name: call.name,
11
+ args: call.arguments,
12
+ }));
13
+ }
14
+ async function appendTurn(storageRoot, sessionId, payload) {
15
+ await appendSessionTurn(storageRoot, sessionId, payload);
16
+ }
17
+ export async function executeTurnTools(calls, toolCtx, messages, storageRoot, sessionId) {
18
+ let turnCount = 0;
19
+ for (const call of calls) {
20
+ const result = await executeBuiltinTool(call.name, call.arguments, toolCtx);
21
+ messages.push({ role: "tool", tool_call_id: call.id, content: result });
22
+ await appendTurn(storageRoot, sessionId, {
23
+ role: "tool",
24
+ content: result,
25
+ toolCalls: null,
26
+ reasoning: null,
27
+ });
28
+ turnCount += 1;
29
+ }
30
+ return turnCount;
31
+ }
32
+ const MAX_NUDGES = 3;
33
+ const DEADLINE_WARNING_TURNS = 3;
34
+ export function shouldInjectDeadlineWarning(turn, maxTurns, alreadyWarned, noTools) {
35
+ const turnsRemaining = maxTurns - turn;
36
+ return (!noTools && !alreadyWarned && turnsRemaining > 0 && turnsRemaining <= DEADLINE_WARNING_TURNS);
37
+ }
38
+ export function shouldProcessToolCalls(toolCalls, noTools) {
39
+ return !noTools && toolCalls !== null && toolCalls.length > 0;
40
+ }
41
+ export function extractFinalText(messages) {
42
+ for (let i = messages.length - 1; i >= 0; i--) {
43
+ const msg = messages[i];
44
+ if (msg !== undefined &&
45
+ msg.role === "assistant" &&
46
+ msg.content !== null &&
47
+ msg.content.trim() !== "") {
48
+ return msg.content;
49
+ }
50
+ }
51
+ return "";
52
+ }
53
+ function injectDeadlineWarning(messages, turnsRemaining) {
54
+ log("4NRXW6KT", `${turnsRemaining} turns remaining, injecting deadline warning`);
55
+ messages.push({
56
+ role: "user",
57
+ content: `⚠️ You have ${turnsRemaining} turns remaining. ` +
58
+ "Wrap up your work and output the YAML frontmatter starting with `---`. " +
59
+ "If you cannot finish in time, output frontmatter with `status: failed` and describe what remains.",
60
+ });
61
+ }
62
+ async function handleTextOnlyTurn(text, messages, storageRoot, sessionId, noTools, turn, maxTurns, currentNudgeCount) {
63
+ await appendTurn(storageRoot, sessionId, {
64
+ role: "assistant",
65
+ content: text,
66
+ toolCalls: null,
67
+ reasoning: null,
68
+ });
69
+ const turnCount = 1;
70
+ let nudgeCount = currentNudgeCount;
71
+ let turnAdjustment = 0;
72
+ if (shouldNudge({ noTools, text, turn, maxTurns })) {
73
+ nudgeCount += 1;
74
+ log("7FXQM2KN", `text-only turn without frontmatter, nudge ${nudgeCount}/${MAX_NUDGES}`);
75
+ const nudge = "You stopped calling tools but your response does not start with the required `---` YAML frontmatter. " +
76
+ "Either continue using tools to complete your work, or output your final response starting with `---`.";
77
+ messages.push({ role: "user", content: nudge });
78
+ // Nudge doesn't consume turn budget (up to MAX_NUDGES)
79
+ if (nudgeCount <= MAX_NUDGES) {
80
+ turnAdjustment = -1;
81
+ }
82
+ return { shouldBreak: false, finalText: "", turnCount, nudgeCount, turnAdjustment };
83
+ }
84
+ return { shouldBreak: true, finalText: text, turnCount, nudgeCount, turnAdjustment };
85
+ }
86
+ async function handleToolCallTurn(content, toolCalls, messages, storageRoot, sessionId, toolCtx) {
87
+ await appendTurn(storageRoot, sessionId, {
88
+ role: "assistant",
89
+ content,
90
+ toolCalls: mapToolCallsForPayload(toolCalls),
91
+ reasoning: null,
92
+ });
93
+ let turnCount = 1;
94
+ // Execute tools
95
+ turnCount += await executeTurnTools(toolCalls, toolCtx, messages, storageRoot, sessionId);
96
+ return turnCount;
97
+ }
98
+ export function shouldNudge({ noTools, text, turn, maxTurns }) {
99
+ return !noTools && !text.trimStart().startsWith("---") && turn < maxTurns - 1;
100
+ }
101
+ async function processLoopIteration(options, messages, openAiTools, turn, nudgeCount) {
102
+ const response = await chatCompletionWithTools(options.provider, messages, openAiTools.length > 0 ? openAiTools : null);
103
+ // When noTools is set, ignore any tool_calls the LLM might still return
104
+ const effectiveToolCalls = options.noTools ? null : (response.toolCalls ?? null);
105
+ const assistantMessage = {
106
+ role: "assistant",
107
+ content: response.content,
108
+ tool_calls: effectiveToolCalls,
109
+ };
110
+ messages.push(assistantMessage);
111
+ if (!shouldProcessToolCalls(effectiveToolCalls, options.noTools)) {
112
+ const text = response.content ?? "";
113
+ const result = await handleTextOnlyTurn(text, messages, options.storageRoot, options.sessionId, options.noTools, turn, options.maxTurns, nudgeCount);
114
+ return result;
115
+ }
116
+ // At this point, effectiveToolCalls is guaranteed to be non-null and non-empty
117
+ const turnCount = await handleToolCallTurn(response.content ?? "", effectiveToolCalls, messages, options.storageRoot, options.sessionId, options.toolCtx);
118
+ return {
119
+ shouldBreak: false,
120
+ finalText: "",
121
+ turnCount,
122
+ nudgeCount,
123
+ turnAdjustment: 0,
124
+ };
125
+ }
126
+ /** Agent run loop: LLM ↔ tools until no tool_calls or maxTurns. */
127
+ export async function runBuiltinLoop(options) {
128
+ const messages = [...options.messages];
129
+ const openAiTools = options.noTools ? [] : builtinToolsToOpenAi(getBuiltinTools());
130
+ let finalText = "";
131
+ let turnCount = 0;
132
+ let nudgeCount = 0;
133
+ let deadlineWarned = false;
134
+ for (let turn = 0; turn < options.maxTurns; turn++) {
135
+ log("8K2M4N7P", `builtin loop turn ${turn + 1}/${options.maxTurns}`);
136
+ // Warn agent when approaching turn limit
137
+ if (shouldInjectDeadlineWarning(turn, options.maxTurns, deadlineWarned, options.noTools)) {
138
+ deadlineWarned = true;
139
+ const turnsRemaining = options.maxTurns - turn;
140
+ injectDeadlineWarning(messages, turnsRemaining);
141
+ }
142
+ const result = await processLoopIteration(options, messages, openAiTools, turn, nudgeCount);
143
+ turnCount += result.turnCount;
144
+ nudgeCount = result.nudgeCount;
145
+ turn += result.turnAdjustment;
146
+ if (result.shouldBreak) {
147
+ finalText = result.finalText;
148
+ break;
149
+ }
150
+ }
151
+ if (finalText === "") {
152
+ finalText = extractFinalText(messages);
153
+ }
154
+ return { finalText, messages, turnCount };
155
+ }
156
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,OAAO,EAEL,uBAAuB,GAGxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAG1B,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAmB5C,SAAS,sBAAsB,CAAC,KAAoB;IAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,IAAI,CAAC,SAAS;KACrB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,KAAK,UAAU,UAAU,CACvB,WAAmB,EACnB,SAAiB,EACjB,OAA2B;IAE3B,MAAM,iBAAiB,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA6D,EAC7D,OAAoB,EACpB,QAAuB,EACvB,WAAmB,EACnB,SAAiB;IAEjB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACxE,MAAM,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE;YACvC,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,MAAM;YACf,SAAS,EAAE,IAAI;YACf,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;QACH,SAAS,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AASD,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,MAAM,UAAU,2BAA2B,CACzC,IAAY,EACZ,QAAgB,EAChB,aAAsB,EACtB,OAAgB;IAEhB,MAAM,cAAc,GAAG,QAAQ,GAAG,IAAI,CAAC;IACvC,OAAO,CACL,CAAC,OAAO,IAAI,CAAC,aAAa,IAAI,cAAc,GAAG,CAAC,IAAI,cAAc,IAAI,sBAAsB,CAC7F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,SAA+B,EAAE,OAAgB;IACtF,OAAO,CAAC,OAAO,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,IACE,GAAG,KAAK,SAAS;YACjB,GAAG,CAAC,IAAI,KAAK,WAAW;YACxB,GAAG,CAAC,OAAO,KAAK,IAAI;YACpB,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EACzB,CAAC;YACD,OAAO,GAAG,CAAC,OAAO,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAuB,EAAE,cAAsB;IAC5E,GAAG,CAAC,UAAU,EAAE,GAAG,cAAc,8CAA8C,CAAC,CAAC;IACjF,QAAQ,CAAC,IAAI,CAAC;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO,EACL,eAAe,cAAc,oBAAoB;YACjD,yEAAyE;YACzE,mGAAmG;KACtG,CAAC,CAAC;AACL,CAAC;AAUD,KAAK,UAAU,kBAAkB,CAC/B,IAAY,EACZ,QAAuB,EACvB,WAAmB,EACnB,SAAiB,EACjB,OAAgB,EAChB,IAAY,EACZ,QAAgB,EAChB,iBAAyB;IAEzB,MAAM,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE;QACvC,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,CAAC,CAAC;IACpB,IAAI,UAAU,GAAG,iBAAiB,CAAC;IACnC,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,IAAI,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QACnD,UAAU,IAAI,CAAC,CAAC;QAChB,GAAG,CAAC,UAAU,EAAE,6CAA6C,UAAU,IAAI,UAAU,EAAE,CAAC,CAAC;QACzF,MAAM,KAAK,GACT,uGAAuG;YACvG,uGAAuG,CAAC;QAC1G,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,uDAAuD;QACvD,IAAI,UAAU,IAAI,UAAU,EAAE,CAAC;YAC7B,cAAc,GAAG,CAAC,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;IACtF,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AACvF,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,OAAe,EACf,SAAwB,EACxB,QAAuB,EACvB,WAAmB,EACnB,SAAiB,EACjB,OAAoB;IAEpB,MAAM,UAAU,CAAC,WAAW,EAAE,SAAS,EAAE;QACvC,IAAI,EAAE,WAAW;QACjB,OAAO;QACP,SAAS,EAAE,sBAAsB,CAAC,SAAS,CAAC;QAC5C,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;IACH,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,gBAAgB;IAChB,SAAS,IAAI,MAAM,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAE1F,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAsB;IAC/E,OAAO,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAC;AAChF,CAAC;AAUD,KAAK,UAAU,oBAAoB,CACjC,OAA8B,EAC9B,QAAuB,EACvB,WAAmC,EACnC,IAAY,EACZ,UAAkB;IAElB,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAC5C,OAAO,CAAC,QAAQ,EAChB,QAAQ,EACR,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAC5C,CAAC;IAEF,wEAAwE;IACxE,MAAM,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IAEjF,MAAM,gBAAgB,GAAgB;QACpC,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,UAAU,EAAE,kBAAkB;KAC/B,CAAC;IACF,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAEhC,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CACrC,IAAI,EACJ,QAAQ,EACR,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,OAAO,EACf,IAAI,EACJ,OAAO,CAAC,QAAQ,EAChB,UAAU,CACX,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+EAA+E;IAC/E,MAAM,SAAS,GAAG,MAAM,kBAAkB,CACxC,QAAQ,CAAC,OAAO,IAAI,EAAE,EACtB,kBAAmC,EACnC,QAAQ,EACR,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,SAAS,EACjB,OAAO,CAAC,OAAO,CAChB,CAAC;IAEF,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,EAAE;QACb,SAAS;QACT,UAAU;QACV,cAAc,EAAE,CAAC;KAClB,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAA8B;IAE9B,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,eAAe,EAAE,CAAC,CAAC;IACnF,IAAI,SAAS,GAAG,EAAE,CAAC;IACnB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QACnD,GAAG,CAAC,UAAU,EAAE,qBAAqB,IAAI,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;QAErE,yCAAyC;QACzC,IAAI,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACzF,cAAc,GAAG,IAAI,CAAC;YACtB,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;YAC/C,qBAAqB,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5F,SAAS,IAAI,MAAM,CAAC,SAAS,CAAC;QAC9B,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAC/B,IAAI,IAAI,MAAM,CAAC,cAAc,CAAC;QAE9B,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YAC7B,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;QACrB,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type AgentContext } from "@uncaged/workflow-util-agent";
2
+ import type { ChatMessage } from "./llm/index.js";
3
+ /**
4
+ * Reconstruct multi-turn chat messages from thread history for cache-friendly session resume.
5
+ *
6
+ * - system: role prompt + output format (stable prefix)
7
+ * - For each prior visit of this role: user (edgePrompt + inter-step summary) + assistant (output JSON)
8
+ * - Final user: current edgePrompt + summary since last visit of this role
9
+ */
10
+ export declare function buildBuiltinMessages(ctx: AgentContext): ChatMessage[];
11
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAmB,MAAM,8BAA8B,CAAC;AAElF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA2ClD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,EAAE,CA8DrE"}
package/dist/prompt.js ADDED
@@ -0,0 +1,93 @@
1
+ import { buildRolePrompt } from "@uncaged/workflow-util-agent";
2
+ function formatStep(step, stepNumber) {
3
+ return [
4
+ `### Step ${stepNumber}: ${step.role}`,
5
+ `Output: ${JSON.stringify(step.output)}`,
6
+ `Agent: ${step.agent}`,
7
+ ].join("\n");
8
+ }
9
+ function buildStepsSummary(steps, fromIndex, toIndex) {
10
+ if (fromIndex >= toIndex) {
11
+ return "";
12
+ }
13
+ const lines = ["## What Happened Since Your Last Turn"];
14
+ for (let i = fromIndex; i < toIndex; i++) {
15
+ const step = steps[i];
16
+ if (step === undefined) {
17
+ continue;
18
+ }
19
+ lines.push("");
20
+ lines.push(formatStep(step, i + 1));
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ function buildUserTurnContent(edgePrompt, summary) {
25
+ const parts = [];
26
+ if (edgePrompt !== "") {
27
+ parts.push(edgePrompt);
28
+ }
29
+ if (summary !== "") {
30
+ if (parts.length > 0) {
31
+ parts.push("");
32
+ }
33
+ parts.push(summary);
34
+ }
35
+ return parts.join("\n");
36
+ }
37
+ /**
38
+ * Reconstruct multi-turn chat messages from thread history for cache-friendly session resume.
39
+ *
40
+ * - system: role prompt + output format (stable prefix)
41
+ * - For each prior visit of this role: user (edgePrompt + inter-step summary) + assistant (output JSON)
42
+ * - Final user: current edgePrompt + summary since last visit of this role
43
+ */
44
+ export function buildBuiltinMessages(ctx) {
45
+ const roleDef = ctx.workflow.roles[ctx.role];
46
+ const rolePrompt = roleDef !== undefined ? buildRolePrompt(roleDef) : "";
47
+ const systemParts = [];
48
+ if (ctx.outputFormatInstruction !== "") {
49
+ systemParts.push(ctx.outputFormatInstruction, "");
50
+ }
51
+ systemParts.push(rolePrompt);
52
+ systemParts.push("", "## Workflow", "", `Your working directory is: ${process.cwd()}`, "", "You have tools available (read_file, write_file, run_command). " +
53
+ "Use them to complete your task — read files, run commands, make changes as needed. " +
54
+ "Your task is described in the user message below — do NOT use uwf or workflow CLI commands to discover your task. " +
55
+ "When you are done, output your final response with the YAML frontmatter block as specified above. " +
56
+ "Do NOT output the frontmatter until you have completed all necessary work. " +
57
+ "If you are running low on turns and cannot finish, output the frontmatter with `status: failed` and explain what remains in the body. " +
58
+ "CRITICAL: Your final output MUST start with the `---` fence on the very first line — " +
59
+ "no preamble text, no explanation before it. The parser requires `---` at position 0.");
60
+ const messages = [{ role: "system", content: systemParts.join("\n") }];
61
+ const roleVisitIndices = [];
62
+ for (let i = 0; i < ctx.steps.length; i++) {
63
+ const step = ctx.steps[i];
64
+ if (step !== undefined && step.role === ctx.role) {
65
+ roleVisitIndices.push(i);
66
+ }
67
+ }
68
+ let prevVisitIndex = -1;
69
+ for (const visitIndex of roleVisitIndices) {
70
+ const visitStep = ctx.steps[visitIndex];
71
+ if (visitStep === undefined) {
72
+ continue;
73
+ }
74
+ const summary = buildStepsSummary(ctx.steps, prevVisitIndex + 1, visitIndex);
75
+ messages.push({
76
+ role: "user",
77
+ content: buildUserTurnContent(visitStep.edgePrompt, summary),
78
+ });
79
+ messages.push({
80
+ role: "assistant",
81
+ content: JSON.stringify(visitStep.output),
82
+ tool_calls: null,
83
+ });
84
+ prevVisitIndex = visitIndex;
85
+ }
86
+ const finalSummary = buildStepsSummary(ctx.steps, prevVisitIndex + 1, ctx.steps.length);
87
+ messages.push({
88
+ role: "user",
89
+ content: buildUserTurnContent(ctx.edgePrompt, finalSummary),
90
+ });
91
+ return messages;
92
+ }
93
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { JSONSchema } from "@uncaged/json-cas";
2
+ export declare const BUILTIN_TURN_SCHEMA: JSONSchema;
3
+ export declare const BUILTIN_DETAIL_SCHEMA: JSONSchema;
4
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAYpD,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,UAenC,CAAC"}
@@ -0,0 +1,42 @@
1
+ const BUILTIN_TOOL_CALL_SCHEMA = {
2
+ type: "object",
3
+ required: ["name", "args"],
4
+ properties: {
5
+ name: { type: "string" },
6
+ args: { type: "string" },
7
+ },
8
+ additionalProperties: false,
9
+ };
10
+ export const BUILTIN_TURN_SCHEMA = {
11
+ title: "builtin-turn",
12
+ type: "object",
13
+ required: ["role", "content"],
14
+ properties: {
15
+ role: { type: "string", enum: ["assistant", "tool"] },
16
+ content: { type: "string" },
17
+ toolCalls: {
18
+ anyOf: [{ type: "array", items: BUILTIN_TOOL_CALL_SCHEMA }, { type: "null" }],
19
+ },
20
+ reasoning: {
21
+ anyOf: [{ type: "string" }, { type: "null" }],
22
+ },
23
+ },
24
+ additionalProperties: false,
25
+ };
26
+ export const BUILTIN_DETAIL_SCHEMA = {
27
+ title: "builtin-detail",
28
+ type: "object",
29
+ required: ["sessionId", "model", "duration", "turnCount", "turns"],
30
+ properties: {
31
+ sessionId: { type: "string" },
32
+ model: { type: "string" },
33
+ duration: { type: "integer" },
34
+ turnCount: { type: "integer" },
35
+ turns: {
36
+ type: "array",
37
+ items: { type: "string", format: "cas_ref" },
38
+ },
39
+ },
40
+ additionalProperties: false,
41
+ };
42
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAEA,MAAM,wBAAwB,GAAe;IAC3C,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACzB;IACD,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,KAAK,EAAE,cAAc;IACrB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;IAC7B,UAAU,EAAE;QACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE;QACrD,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC3B,SAAS,EAAE;YACT,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,wBAAwB,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SAC9E;QACD,SAAS,EAAE;YACT,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SAC9C;KACF;IACD,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,KAAK,EAAE,gBAAgB;IACvB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,CAAC;IAClE,UAAU,EAAE;QACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC7B,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC9B,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE;SAC7C;KACF;IACD,oBAAoB,EAAE,KAAK;CAC5B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { BuiltinTurnPayload } from "./types.js";
2
+ /** Ensure sessions directory exists. */
3
+ export declare function initSessionDir(storageRoot: string): Promise<void>;
4
+ /** Append a turn to the session jsonl file. */
5
+ export declare function appendSessionTurn(storageRoot: string, sessionId: string, turn: BuiltinTurnPayload): Promise<void>;
6
+ /** Read all turns from session jsonl. Returns empty array if file does not exist. */
7
+ export declare function readSessionTurns(storageRoot: string, sessionId: string): Promise<BuiltinTurnPayload[]>;
8
+ /** Remove session jsonl file (called after detail is persisted to step CAS). */
9
+ export declare function removeSession(storageRoot: string, sessionId: string): Promise<void>;
10
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAYrD,wCAAwC;AACxC,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvE;AAED,+CAA+C;AAC/C,wBAAsB,iBAAiB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,qFAAqF;AACrF,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAW/B;AAED,gFAAgF;AAChF,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzF"}
@@ -0,0 +1,45 @@
1
+ import { appendFile, mkdir, readFile, rm } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { createLogger } from "@uncaged/workflow-util";
4
+ const log = createLogger({ sink: { kind: "stderr" } });
5
+ function sessionsDir(storageRoot) {
6
+ return join(storageRoot, "sessions");
7
+ }
8
+ function sessionFile(storageRoot, sessionId) {
9
+ return join(sessionsDir(storageRoot), `${sessionId}.jsonl`);
10
+ }
11
+ /** Ensure sessions directory exists. */
12
+ export async function initSessionDir(storageRoot) {
13
+ await mkdir(sessionsDir(storageRoot), { recursive: true });
14
+ }
15
+ /** Append a turn to the session jsonl file. */
16
+ export async function appendSessionTurn(storageRoot, sessionId, turn) {
17
+ const line = `${JSON.stringify(turn)}\n`;
18
+ await appendFile(sessionFile(storageRoot, sessionId), line, "utf-8");
19
+ log("3XQVN8KR", `session ${sessionId} appended ${turn.role} turn`);
20
+ }
21
+ /** Read all turns from session jsonl. Returns empty array if file does not exist. */
22
+ export async function readSessionTurns(storageRoot, sessionId) {
23
+ try {
24
+ const content = await readFile(sessionFile(storageRoot, sessionId), "utf-8");
25
+ const lines = content
26
+ .trim()
27
+ .split("\n")
28
+ .filter((l) => l.length > 0);
29
+ return lines.map((l) => JSON.parse(l));
30
+ }
31
+ catch {
32
+ return [];
33
+ }
34
+ }
35
+ /** Remove session jsonl file (called after detail is persisted to step CAS). */
36
+ export async function removeSession(storageRoot, sessionId) {
37
+ try {
38
+ await rm(sessionFile(storageRoot, sessionId));
39
+ log("7FWDP2MJ", `session ${sessionId} removed`);
40
+ }
41
+ catch {
42
+ // already gone — fine
43
+ }
44
+ }
45
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAItD,MAAM,GAAG,GAAG,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEvD,SAAS,WAAW,CAAC,WAAmB;IACtC,OAAO,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,WAAW,CAAC,WAAmB,EAAE,SAAiB;IACzD,OAAO,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,GAAG,SAAS,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAED,wCAAwC;AACxC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,WAAmB;IACtD,MAAM,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED,+CAA+C;AAC/C,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,SAAiB,EACjB,IAAwB;IAExB,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;IACzC,MAAM,UAAU,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrE,GAAG,CAAC,UAAU,EAAE,WAAW,SAAS,aAAa,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,OAAO;aAClB,IAAI,EAAE;aACN,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/B,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAuB,CAAC,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,SAAiB;IACxE,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,UAAU,EAAE,WAAW,SAAS,UAAU,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { OpenAiToolDefinition } from "../llm/index.js";
2
+ import type { BuiltinTool, ToolContext } from "./types.js";
3
+ export { resolvePath } from "./path.js";
4
+ export type { BuiltinTool, ToolContext } from "./types.js";
5
+ export declare function getBuiltinTools(): readonly BuiltinTool[];
6
+ export declare function builtinToolsToOpenAi(tools: readonly BuiltinTool[]): OpenAiToolDefinition[];
7
+ export declare function executeBuiltinTool(name: string, argsJson: string, ctx: ToolContext): Promise<string>;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAI5D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI3D,wBAAgB,eAAe,IAAI,SAAS,WAAW,EAAE,CAExD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,oBAAoB,EAAE,CAS1F;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,WAAW,GACf,OAAO,CAAC,MAAM,CAAC,CAYjB"}
@@ -0,0 +1,33 @@
1
+ import { readFileTool } from "./read-file.js";
2
+ import { runCommandTool } from "./run-command.js";
3
+ import { writeFileTool } from "./write-file.js";
4
+ export { resolvePath } from "./path.js";
5
+ const BUILTIN_TOOLS = [readFileTool, writeFileTool, runCommandTool];
6
+ export function getBuiltinTools() {
7
+ return BUILTIN_TOOLS;
8
+ }
9
+ export function builtinToolsToOpenAi(tools) {
10
+ return tools.map((tool) => ({
11
+ type: "function",
12
+ function: {
13
+ name: tool.name,
14
+ description: tool.description,
15
+ parameters: tool.parameters,
16
+ },
17
+ }));
18
+ }
19
+ export async function executeBuiltinTool(name, argsJson, ctx) {
20
+ const tool = BUILTIN_TOOLS.find((t) => t.name === name);
21
+ if (tool === undefined) {
22
+ return `Error: unknown tool ${name}`;
23
+ }
24
+ let args;
25
+ try {
26
+ args = JSON.parse(argsJson);
27
+ }
28
+ catch {
29
+ return "Error: tool arguments must be valid JSON";
30
+ }
31
+ return tool.execute(args, ctx);
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,MAAM,aAAa,GAAkB,CAAC,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AAEnF,MAAM,UAAU,eAAe;IAC7B,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAA6B;IAChE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAqC;SACvD;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,QAAgB,EAChB,GAAgB;IAEhB,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACxD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,uBAAuB,IAAI,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,IAAa,CAAC;IAClB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAY,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,0CAA0C,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Resolve a path relative to the working directory. */
2
+ export declare function resolvePath(cwd: string, inputPath: string): string;
3
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/tools/path.ts"],"names":[],"mappings":"AAEA,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAElE"}
@@ -0,0 +1,6 @@
1
+ import { resolve } from "node:path";
2
+ /** Resolve a path relative to the working directory. */
3
+ export function resolvePath(cwd, inputPath) {
4
+ return resolve(cwd, inputPath);
5
+ }
6
+ //# sourceMappingURL=path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/tools/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,wDAAwD;AACxD,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,SAAiB;IACxD,OAAO,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { BuiltinTool } from "./types.js";
2
+ export declare const readFileTool: BuiltinTool;
3
+ //# sourceMappingURL=read-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.d.ts","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAQ9C,eAAO,MAAM,YAAY,EAAE,WA8B1B,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import { resolvePath } from "./path.js";
3
+ const MAX_READ_BYTES = 512 * 1024;
4
+ function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ export const readFileTool = {
8
+ name: "read_file",
9
+ description: "Read a UTF-8 text file from the workspace.",
10
+ parameters: {
11
+ type: "object",
12
+ required: ["path"],
13
+ properties: {
14
+ path: { type: "string", description: "Relative or absolute path within the workspace." },
15
+ },
16
+ additionalProperties: false,
17
+ },
18
+ execute: async (args, ctx) => {
19
+ if (!isRecord(args) || typeof args.path !== "string") {
20
+ return "Error: path must be a string";
21
+ }
22
+ const resolved = resolvePath(ctx.cwd, args.path);
23
+ try {
24
+ const info = await stat(resolved);
25
+ if (!info.isFile()) {
26
+ return "Error: not a file";
27
+ }
28
+ if (info.size > MAX_READ_BYTES) {
29
+ return `Error: file exceeds ${MAX_READ_BYTES} byte limit`;
30
+ }
31
+ return await readFile(resolved, "utf8");
32
+ }
33
+ catch (cause) {
34
+ const message = cause instanceof Error ? cause.message : String(cause);
35
+ return `Error: ${message}`;
36
+ }
37
+ },
38
+ };
39
+ //# sourceMappingURL=read-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC;AAElC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,4CAA4C;IACzD,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iDAAiD,EAAE;SACzF;QACD,oBAAoB,EAAE,KAAK;KAC5B;IACD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,8BAA8B,CAAC;QACxC,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,OAAO,mBAAmB,CAAC;YAC7B,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,GAAG,cAAc,EAAE,CAAC;gBAC/B,OAAO,uBAAuB,cAAc,aAAa,CAAC;YAC5D,CAAC;YACD,OAAO,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,UAAU,OAAO,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { BuiltinTool } from "./types.js";
2
+ export declare const runCommandTool: BuiltinTool;
3
+ //# sourceMappingURL=run-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-command.d.ts","sourceRoot":"","sources":["../../src/tools/run-command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAsD9C,eAAO,MAAM,cAAc,EAAE,WAsC5B,CAAC"}
@@ -0,0 +1,81 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolvePath } from "./path.js";
3
+ const COMMAND_TIMEOUT_MS = 60_000;
4
+ const MAX_OUTPUT_CHARS = 32_000;
5
+ function isRecord(value) {
6
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7
+ }
8
+ function truncate(text, maxChars) {
9
+ if (text.length <= maxChars) {
10
+ return text;
11
+ }
12
+ return `${text.slice(0, maxChars)}\n...(truncated)`;
13
+ }
14
+ function runShell(command, cwd) {
15
+ return new Promise((resolve, reject) => {
16
+ const child = spawn(command, {
17
+ cwd,
18
+ env: process.env,
19
+ shell: true,
20
+ stdio: ["ignore", "pipe", "pipe"],
21
+ });
22
+ let stdout = "";
23
+ let stderr = "";
24
+ child.stdout?.on("data", (chunk) => {
25
+ stdout += chunk.toString();
26
+ });
27
+ child.stderr?.on("data", (chunk) => {
28
+ stderr += chunk.toString();
29
+ });
30
+ const timer = setTimeout(() => {
31
+ child.kill("SIGTERM");
32
+ }, COMMAND_TIMEOUT_MS);
33
+ child.on("error", (cause) => {
34
+ clearTimeout(timer);
35
+ const message = cause instanceof Error ? cause.message : String(cause);
36
+ reject(new Error(message));
37
+ });
38
+ child.on("close", (code) => {
39
+ clearTimeout(timer);
40
+ resolve({ stdout, stderr, code: code ?? 1 });
41
+ });
42
+ });
43
+ }
44
+ export const runCommandTool = {
45
+ name: "run_command",
46
+ description: "Run a shell command. Output is truncated to 32KB.",
47
+ parameters: {
48
+ type: "object",
49
+ required: ["command"],
50
+ properties: {
51
+ command: { type: "string", description: "Shell command to execute." },
52
+ cwd: {
53
+ type: "string",
54
+ description: "Optional working directory relative to workspace root.",
55
+ },
56
+ },
57
+ additionalProperties: false,
58
+ },
59
+ execute: async (args, ctx) => {
60
+ if (!isRecord(args) || typeof args.command !== "string") {
61
+ return "Error: command must be a string";
62
+ }
63
+ let workDir = ctx.cwd;
64
+ if (args.cwd !== undefined && args.cwd !== null) {
65
+ if (typeof args.cwd !== "string") {
66
+ return "Error: cwd must be a string";
67
+ }
68
+ workDir = resolvePath(ctx.cwd, args.cwd);
69
+ }
70
+ try {
71
+ const { stdout, stderr, code } = await runShell(args.command, workDir);
72
+ const out = truncate(`exit_code: ${code}\n--- stdout ---\n${stdout}\n--- stderr ---\n${stderr}`, MAX_OUTPUT_CHARS);
73
+ return out;
74
+ }
75
+ catch (cause) {
76
+ const message = cause instanceof Error ? cause.message : String(cause);
77
+ return `Error: ${message}`;
78
+ }
79
+ },
80
+ };
81
+ //# sourceMappingURL=run-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-command.js","sourceRoot":"","sources":["../../src/tools/run-command.ts"],"names":[],"mappings":"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"}