kagent-ts 0.1.0

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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +395 -0
  3. package/dist/compression/interface.d.ts +26 -0
  4. package/dist/compression/interface.d.ts.map +1 -0
  5. package/dist/compression/interface.js +3 -0
  6. package/dist/compression/interface.js.map +1 -0
  7. package/dist/compression/sliding-window.d.ts +21 -0
  8. package/dist/compression/sliding-window.d.ts.map +1 -0
  9. package/dist/compression/sliding-window.js +55 -0
  10. package/dist/compression/sliding-window.js.map +1 -0
  11. package/dist/compression/types.d.ts +12 -0
  12. package/dist/compression/types.d.ts.map +1 -0
  13. package/dist/compression/types.js +3 -0
  14. package/dist/compression/types.js.map +1 -0
  15. package/dist/context/context-manager.d.ts +76 -0
  16. package/dist/context/context-manager.d.ts.map +1 -0
  17. package/dist/context/context-manager.js +132 -0
  18. package/dist/context/context-manager.js.map +1 -0
  19. package/dist/context/types.d.ts +35 -0
  20. package/dist/context/types.d.ts.map +1 -0
  21. package/dist/context/types.js +3 -0
  22. package/dist/context/types.js.map +1 -0
  23. package/dist/core/agent.d.ts +288 -0
  24. package/dist/core/agent.d.ts.map +1 -0
  25. package/dist/core/agent.js +398 -0
  26. package/dist/core/agent.js.map +1 -0
  27. package/dist/core/hooks.d.ts +34 -0
  28. package/dist/core/hooks.d.ts.map +1 -0
  29. package/dist/core/hooks.js +3 -0
  30. package/dist/core/hooks.js.map +1 -0
  31. package/dist/core/plan-solve-agent.d.ts +114 -0
  32. package/dist/core/plan-solve-agent.d.ts.map +1 -0
  33. package/dist/core/plan-solve-agent.js +450 -0
  34. package/dist/core/plan-solve-agent.js.map +1 -0
  35. package/dist/core/react-agent.d.ts +52 -0
  36. package/dist/core/react-agent.d.ts.map +1 -0
  37. package/dist/core/react-agent.js +266 -0
  38. package/dist/core/react-agent.js.map +1 -0
  39. package/dist/core/response-schema.d.ts +91 -0
  40. package/dist/core/response-schema.d.ts.map +1 -0
  41. package/dist/core/response-schema.js +292 -0
  42. package/dist/core/response-schema.js.map +1 -0
  43. package/dist/core/types.d.ts +6 -0
  44. package/dist/core/types.d.ts.map +1 -0
  45. package/dist/core/types.js +3 -0
  46. package/dist/core/types.js.map +1 -0
  47. package/dist/index.d.ts +39 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +67 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/llm/interface.d.ts +87 -0
  52. package/dist/llm/interface.d.ts.map +1 -0
  53. package/dist/llm/interface.js +3 -0
  54. package/dist/llm/interface.js.map +1 -0
  55. package/dist/llm/openai-provider.d.ts +92 -0
  56. package/dist/llm/openai-provider.d.ts.map +1 -0
  57. package/dist/llm/openai-provider.js +262 -0
  58. package/dist/llm/openai-provider.js.map +1 -0
  59. package/dist/messages/message.d.ts +50 -0
  60. package/dist/messages/message.d.ts.map +1 -0
  61. package/dist/messages/message.js +87 -0
  62. package/dist/messages/message.js.map +1 -0
  63. package/dist/messages/types.d.ts +31 -0
  64. package/dist/messages/types.d.ts.map +1 -0
  65. package/dist/messages/types.js +14 -0
  66. package/dist/messages/types.js.map +1 -0
  67. package/dist/preferences/preference-manager.d.ts +88 -0
  68. package/dist/preferences/preference-manager.d.ts.map +1 -0
  69. package/dist/preferences/preference-manager.js +196 -0
  70. package/dist/preferences/preference-manager.js.map +1 -0
  71. package/dist/preferences/types.d.ts +27 -0
  72. package/dist/preferences/types.d.ts.map +1 -0
  73. package/dist/preferences/types.js +3 -0
  74. package/dist/preferences/types.js.map +1 -0
  75. package/dist/session/session-manager.d.ts +56 -0
  76. package/dist/session/session-manager.d.ts.map +1 -0
  77. package/dist/session/session-manager.js +156 -0
  78. package/dist/session/session-manager.js.map +1 -0
  79. package/dist/session/session-types.d.ts +51 -0
  80. package/dist/session/session-types.d.ts.map +1 -0
  81. package/dist/session/session-types.js +3 -0
  82. package/dist/session/session-types.js.map +1 -0
  83. package/dist/skills/file-skill-loader.d.ts +88 -0
  84. package/dist/skills/file-skill-loader.d.ts.map +1 -0
  85. package/dist/skills/file-skill-loader.js +365 -0
  86. package/dist/skills/file-skill-loader.js.map +1 -0
  87. package/dist/skills/index.d.ts +4 -0
  88. package/dist/skills/index.d.ts.map +1 -0
  89. package/dist/skills/index.js +10 -0
  90. package/dist/skills/index.js.map +1 -0
  91. package/dist/skills/skill-manager.d.ts +133 -0
  92. package/dist/skills/skill-manager.d.ts.map +1 -0
  93. package/dist/skills/skill-manager.js +310 -0
  94. package/dist/skills/skill-manager.js.map +1 -0
  95. package/dist/skills/types.d.ts +42 -0
  96. package/dist/skills/types.d.ts.map +1 -0
  97. package/dist/skills/types.js +3 -0
  98. package/dist/skills/types.js.map +1 -0
  99. package/dist/tools/builtin/edit-file.d.ts +12 -0
  100. package/dist/tools/builtin/edit-file.d.ts.map +1 -0
  101. package/dist/tools/builtin/edit-file.js +123 -0
  102. package/dist/tools/builtin/edit-file.js.map +1 -0
  103. package/dist/tools/builtin/glob-search.d.ts +11 -0
  104. package/dist/tools/builtin/glob-search.d.ts.map +1 -0
  105. package/dist/tools/builtin/glob-search.js +264 -0
  106. package/dist/tools/builtin/glob-search.js.map +1 -0
  107. package/dist/tools/builtin/grep-search.d.ts +14 -0
  108. package/dist/tools/builtin/grep-search.d.ts.map +1 -0
  109. package/dist/tools/builtin/grep-search.js +264 -0
  110. package/dist/tools/builtin/grep-search.js.map +1 -0
  111. package/dist/tools/builtin/index.d.ts +21 -0
  112. package/dist/tools/builtin/index.d.ts.map +1 -0
  113. package/dist/tools/builtin/index.js +53 -0
  114. package/dist/tools/builtin/index.js.map +1 -0
  115. package/dist/tools/builtin/read-file.d.ts +11 -0
  116. package/dist/tools/builtin/read-file.d.ts.map +1 -0
  117. package/dist/tools/builtin/read-file.js +122 -0
  118. package/dist/tools/builtin/read-file.js.map +1 -0
  119. package/dist/tools/builtin/write-file.d.ts +10 -0
  120. package/dist/tools/builtin/write-file.d.ts.map +1 -0
  121. package/dist/tools/builtin/write-file.js +89 -0
  122. package/dist/tools/builtin/write-file.js.map +1 -0
  123. package/dist/tools/circuit-breaker.d.ts +77 -0
  124. package/dist/tools/circuit-breaker.d.ts.map +1 -0
  125. package/dist/tools/circuit-breaker.js +102 -0
  126. package/dist/tools/circuit-breaker.js.map +1 -0
  127. package/dist/tools/error-tracker.d.ts +116 -0
  128. package/dist/tools/error-tracker.d.ts.map +1 -0
  129. package/dist/tools/error-tracker.js +484 -0
  130. package/dist/tools/error-tracker.js.map +1 -0
  131. package/dist/tools/tool-registry.d.ts +87 -0
  132. package/dist/tools/tool-registry.d.ts.map +1 -0
  133. package/dist/tools/tool-registry.js +188 -0
  134. package/dist/tools/tool-registry.js.map +1 -0
  135. package/dist/tools/types.d.ts +95 -0
  136. package/dist/tools/types.d.ts.map +1 -0
  137. package/dist/tools/types.js +14 -0
  138. package/dist/tools/types.js.map +1 -0
  139. package/dist/utils/token-counter.d.ts +31 -0
  140. package/dist/utils/token-counter.d.ts.map +1 -0
  141. package/dist/utils/token-counter.js +105 -0
  142. package/dist/utils/token-counter.js.map +1 -0
  143. package/package.json +56 -0
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReActAgent = void 0;
4
+ const agent_1 = require("./agent");
5
+ const message_1 = require("../messages/message");
6
+ const response_schema_1 = require("./response-schema");
7
+ const openai_provider_1 = require("../llm/openai-provider");
8
+ const response_schema_2 = require("./response-schema");
9
+ /**
10
+ * Default system prompt for ReAct-style reasoning with structured JSON output.
11
+ *
12
+ * The LLM is instructed to respond with JSON so the agent can reliably
13
+ * parse thoughts and final answers — no free-text format ambiguity.
14
+ */
15
+ const DEFAULT_REACT_SYSTEM_PROMPT = `You are a helpful AI assistant powered by a ReAct (Reasoning + Acting) loop.
16
+ You have access to a set of tools you can use to answer the user's question.
17
+
18
+ Follow this process:
19
+ 1. Think step by step about what the user needs.
20
+ 2. Decide whether to use a tool or give the final answer.
21
+ 3. If using a tool, call it with the correct parameters.
22
+ 4. Observe the result and decide the next step.
23
+ 5. Repeat until you have the complete answer.
24
+
25
+ If no tools are needed, respond with the final answer directly.
26
+ Always think step by step before acting.
27
+
28
+ === Tool Error Recovery ===
29
+ When a tool returns an error:
30
+ 1. READ the error message carefully — understand WHY it failed.
31
+ 2. ANALYZE whether the parameters were correct. Common issues:
32
+ - Wrong file path (check spelling, use absolute paths)
33
+ - Missing or incorrect arguments
34
+ - The tool may need different input formats
35
+ 3. RETRY with corrected parameters if you can fix the issue.
36
+ 4. If the same tool fails repeatedly, try a COMPLETELY DIFFERENT approach.
37
+ 5. If a tool is disabled after too many failures, DO NOT try to use it again.
38
+ Find another way to accomplish the task.${response_schema_1.STRUCTURED_OUTPUT_INSTRUCTIONS}`;
39
+ /**
40
+ * ReAct Agent implementing a structured Thought → Action → Observation → Final Answer loop.
41
+ *
42
+ * The agent uses structured JSON output from the LLM:
43
+ * - Intermediate steps: {"thought": "..."}
44
+ * - Final answer: {"thought": "...", "answer": "..."}
45
+ * - Tool calls via native function calling (OpenAI tool_calls)
46
+ *
47
+ * Session persistence:
48
+ * When `enableCheckpointing` is set, the agent auto-saves checkpoints after
49
+ * each LLM+tools cycle. On network error, an `interrupted` checkpoint is
50
+ * saved so the user can resume later via `agent.resume(sessionId, input)`.
51
+ */
52
+ class ReActAgent extends agent_1.Agent {
53
+ maxIterations;
54
+ enableSkillAutoDetect;
55
+ constructor(config) {
56
+ // Set default ReAct system prompt if none provided
57
+ const mergedConfig = {
58
+ ...config,
59
+ systemPrompt: config.systemPrompt ?? DEFAULT_REACT_SYSTEM_PROMPT,
60
+ };
61
+ super(mergedConfig);
62
+ this.maxIterations = config.maxIterations ?? 10;
63
+ this.enableSkillAutoDetect = config.enableSkillAutoDetect ?? true;
64
+ // If skills are registered, rebuild the system prompt so the
65
+ // available-skills hint is included in the initial prompt.
66
+ if (this.skillManager.activeCount > 0) {
67
+ this.rebuildSystemPrompt();
68
+ }
69
+ }
70
+ async run(input) {
71
+ // ── Progressive disclosure ─────────────────────────────────────────
72
+ if (this.enableSkillAutoDetect && this.skillManager.activeCount >= 0) {
73
+ const activated = this.skillManager.detectAndActivate(input);
74
+ if (activated.length > 0) {
75
+ this.rebuildSystemPrompt();
76
+ console.log(`[Skills] Auto-activated: ${activated.join(", ")}`);
77
+ }
78
+ }
79
+ // ── Create user message ──────────────────────────────────────────
80
+ const userMessage = message_1.Message.user(input);
81
+ this.contextManager.addMessage(userMessage.toDict());
82
+ // Save initial checkpoint (captures user input before any LLM call)
83
+ if (this.checkpointingEnabled) {
84
+ this.saveCheckpoint("active");
85
+ }
86
+ // Track consecutive unproductive iterations (no tool calls, no answer)
87
+ let consecutiveEmptyIterations = 0;
88
+ const EMPTY_ITERATION_LIMIT = 5;
89
+ // ── ReAct loop ────────────────────────────────────────────────────
90
+ for (let iteration = 0; iteration < this.maxIterations; iteration++) {
91
+ // Check if user cancelled (SIGINT)
92
+ if (this.isCancelled) {
93
+ this.sessionManager?.deleteSession(this.sessionManager.getSessionId());
94
+ return "Execution cancelled by user. Session discarded.";
95
+ }
96
+ // Check and compress if needed
97
+ this.checkAndCompress();
98
+ // Prepare messages for the LLM
99
+ const contextMessages = this.contextManager.getContextMessages();
100
+ // Call the LLM with all registered tools — with network error handling
101
+ this.hooks.onLLMStart?.();
102
+ let response;
103
+ try {
104
+ response = await this.llm.chat(contextMessages, this.toolRegistry.getTools());
105
+ }
106
+ catch (err) {
107
+ if (err instanceof openai_provider_1.LLMNetworkError) {
108
+ this.hooks.onLLMError?.(err);
109
+ return this.handleNetworkError(err, iteration + 1);
110
+ }
111
+ throw err; // Unknown error — propagate
112
+ }
113
+ this.hooks.onLLMEnd?.(response);
114
+ // Parse the response content as structured JSON
115
+ const parsed = (0, response_schema_1.parseReActResponse)(response.content);
116
+ const rawContent = response.content;
117
+ // Create assistant message from the response
118
+ const assistantMessage = message_1.Message.assistant(rawContent, response.tool_calls);
119
+ // Store in context
120
+ this.contextManager.addMessage(assistantMessage.toDict());
121
+ // Check if LLM wants to call tools
122
+ if (response.tool_calls && response.tool_calls.length > 0) {
123
+ consecutiveEmptyIterations = 0;
124
+ // Log the reasoning thought and capture as error analysis
125
+ if (parsed.thought) {
126
+ console.log(`[Thought] ${parsed.thought}`);
127
+ this.hooks.onThought?.(parsed.thought);
128
+ this.captureAnalysisFromThought(parsed.thought);
129
+ }
130
+ for (const toolCall of response.tool_calls) {
131
+ let args;
132
+ try {
133
+ args = JSON.parse(toolCall.function.arguments);
134
+ }
135
+ catch {
136
+ args = {};
137
+ }
138
+ this.hooks.onToolStart?.(toolCall.function.name, args);
139
+ // Execute via ToolRegistry — includes circuit breaker protection
140
+ let result;
141
+ try {
142
+ result = await this.toolRegistry.execute(toolCall.function.name, args);
143
+ }
144
+ catch (err) {
145
+ const message = err instanceof Error ? err.message : String(err);
146
+ result = `Error executing tool "${toolCall.function.name}": ${message}`;
147
+ }
148
+ // Determine success vs error and fire appropriate hook
149
+ if (result.startsWith("Error")) {
150
+ this.hooks.onToolError?.(toolCall.function.name, result);
151
+ }
152
+ else {
153
+ this.hooks.onToolEnd?.(toolCall.function.name, result);
154
+ }
155
+ // Track this result for error analysis if it indicates a failure
156
+ this.trackToolErrorForAnalysis(toolCall.function.name, result);
157
+ // Create tool result message
158
+ const toolMessage = message_1.Message.tool(result, toolCall.id, toolCall.function.name);
159
+ this.contextManager.addMessage(toolMessage.toDict());
160
+ }
161
+ // Save checkpoint after complete tool execution round
162
+ if (this.checkpointingEnabled) {
163
+ this.saveCheckpoint("active");
164
+ }
165
+ // Continue the loop for the next Thought
166
+ continue;
167
+ }
168
+ // No tool calls — extract the final answer from the JSON
169
+ if ("answer" in parsed && parsed.answer) {
170
+ this.hooks.onFinish?.(parsed.answer);
171
+ // Save final checkpoint as completed
172
+ if (this.checkpointingEnabled) {
173
+ this.saveCheckpoint("completed");
174
+ }
175
+ return parsed.answer;
176
+ }
177
+ // JSON has "thought" but no "answer" — continue the loop
178
+ // (the agent is still reasoning)
179
+ if (parsed.thought) {
180
+ consecutiveEmptyIterations++;
181
+ console.log(`[Thought] ${parsed.thought}`);
182
+ this.hooks.onThought?.(parsed.thought);
183
+ this.captureAnalysisFromThought(parsed.thought);
184
+ // If stuck in unproductive thought-only loop, inject format reminder
185
+ if (consecutiveEmptyIterations >= 3) {
186
+ console.log(`[ReAct] ${consecutiveEmptyIterations} consecutive thought-only iterations — ` +
187
+ `injecting format reminder.`);
188
+ const reminderMsg = message_1.Message.assistant(response_schema_2.STRUCTURED_OUTPUT_REMINDER);
189
+ this.contextManager.addMessage(reminderMsg.toDict());
190
+ }
191
+ // If exceeded limit, bail out
192
+ if (consecutiveEmptyIterations >= EMPTY_ITERATION_LIMIT) {
193
+ const stuckMsg = "I apologize, but I'm having difficulty making progress on your request. " +
194
+ "Please try rephrasing or breaking it down into smaller, more specific steps.";
195
+ const stuckAssistantMessage = message_1.Message.assistant(stuckMsg);
196
+ this.contextManager.addMessage(stuckAssistantMessage.toDict());
197
+ this.hooks.onFinish?.(stuckMsg);
198
+ return stuckMsg;
199
+ }
200
+ // Save checkpoint after a thought-only iteration
201
+ if (this.checkpointingEnabled) {
202
+ this.saveCheckpoint("active");
203
+ }
204
+ continue;
205
+ }
206
+ // Empty response (no thought, no answer, no tool calls)
207
+ consecutiveEmptyIterations++;
208
+ if (consecutiveEmptyIterations >= EMPTY_ITERATION_LIMIT) {
209
+ const stuckMsg = "I apologize, but I'm having difficulty making progress on your request. " +
210
+ "Please try rephrasing or breaking it down into smaller, more specific steps.";
211
+ const stuckAssistantMessage = message_1.Message.assistant(stuckMsg);
212
+ this.contextManager.addMessage(stuckAssistantMessage.toDict());
213
+ this.hooks.onFinish?.(stuckMsg);
214
+ return stuckMsg;
215
+ }
216
+ }
217
+ // ── Max iterations reached without final answer ───────────────────
218
+ const timeoutMsg = `I apologize, but I was unable to complete the task within ${this.maxIterations} iterations. ` +
219
+ `Please try breaking your request into smaller steps.`;
220
+ const timeoutAssistantMessage = message_1.Message.assistant(timeoutMsg);
221
+ this.contextManager.addMessage(timeoutAssistantMessage.toDict());
222
+ this.hooks.onFinish?.(timeoutMsg);
223
+ return timeoutMsg;
224
+ }
225
+ // ─── Resume ──────────────────────────────────────────────────────────
226
+ /**
227
+ * Resume a previously interrupted session.
228
+ *
229
+ * Loads the saved session state (messages, system prompt) so the agent
230
+ * can continue from where it left off. The `input` is treated as a new
231
+ * user message appended to the restored conversation.
232
+ *
233
+ * @param sessionId The session ID to resume.
234
+ * @param input New user input to continue the conversation.
235
+ * @returns The agent's final response.
236
+ */
237
+ async resume(sessionId, input) {
238
+ this.loadAndRestoreSession(sessionId);
239
+ return this.run(input);
240
+ }
241
+ // ─── Private Helpers ─────────────────────────────────────────────────
242
+ /**
243
+ * Handle an LLMNetworkError: save an interrupted checkpoint if
244
+ * checkpointing is enabled, and return a user-facing message with
245
+ * resume instructions.
246
+ */
247
+ handleNetworkError(err, iteration) {
248
+ if (this.checkpointingEnabled) {
249
+ this.saveCheckpoint("interrupted");
250
+ }
251
+ const sid = this.sessionManager?.getSessionId() ?? "unknown";
252
+ console.error(`\n[Network Error] ${err.cause}: ${err.message}`);
253
+ if (this.checkpointingEnabled && this.sessionManager) {
254
+ return (`[Network Error] ${err.message}\n\n` +
255
+ `Your session "${sid}" has been saved (iteration ${iteration}).\n` +
256
+ `After your network is restored, resume with:\n` +
257
+ ` agent.resume("${sid}", "continue with my previous request")\n\n` +
258
+ `Or start a new session by calling agent.run() again with a fresh input.`);
259
+ }
260
+ // Checkpointing not enabled — just report the error
261
+ return (`[Network Error] ${err.message}\n\n` +
262
+ `Please check your network connection and try again.`);
263
+ }
264
+ }
265
+ exports.ReActAgent = ReActAgent;
266
+ //# sourceMappingURL=react-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-agent.js","sourceRoot":"","sources":["../../src/core/react-agent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Structured JSON response schema for LLM outputs.
3
+ *
4
+ * Instead of parsing free-text ReAct format (Thought/Action/Action Input),
5
+ * the LLM is instructed to respond with a JSON object that the agent
6
+ * can reliably parse. This eliminates ambiguity in the agent loop.
7
+ */
8
+ /**
9
+ * Intermediate reasoning step (no final answer yet).
10
+ */
11
+ export interface ReActReasoning {
12
+ /** Step-by-step reasoning about what to do next. */
13
+ thought: string;
14
+ }
15
+ /**
16
+ * Final answer from the agent.
17
+ */
18
+ export interface ReActFinalAnswer {
19
+ /** Final reasoning before answering. */
20
+ thought: string;
21
+ /** The complete answer for the user. */
22
+ answer: string;
23
+ }
24
+ /**
25
+ * Union of all possible ReAct response shapes.
26
+ */
27
+ export type ReActResponse = ReActReasoning | ReActFinalAnswer;
28
+ /**
29
+ * Parse a raw LLM content string into a structured ReActResponse.
30
+ *
31
+ * Handles:
32
+ * - Raw JSON: {"thought": "...", "answer": "..."}
33
+ * - Code blocks: ```json\n{"thought": "..."}\n```
34
+ * - Extra text: Let me think... {"thought": "..."}
35
+ *
36
+ * Falls back to wrapping the raw text as a thought when JSON parsing fails.
37
+ */
38
+ export declare function parseReActResponse(raw: string): ReActResponse;
39
+ /**
40
+ * Instructions injected into the system prompt to teach the LLM
41
+ * the JSON response format.
42
+ */
43
+ export declare const STRUCTURED_OUTPUT_INSTRUCTIONS = "\n=== Response Format ===\nYou MUST respond with a valid JSON object in the \"content\" field of your message.\nDo NOT wrap the JSON in markdown code blocks.\n\nWhen you have the FINAL ANSWER for the user:\n{\"thought\": \"...step-by-step reasoning...\", \"answer\": \"...complete answer for the user...\"}\n\nWhen you are REASONING (intermediate step, before or after using tools):\n{\"thought\": \"...step-by-step reasoning...\"}\n\nRules:\n- \"thought\" is REQUIRED in every response \u2014 it contains your step-by-step reasoning.\n- \"answer\" is ONLY included in your final response, when you have the complete answer.\n- The JSON must be valid and parseable \u2014 no trailing commas, no comments.\n- If you need to use a tool, put your reasoning in \"thought\" as JSON, and send the tool call via the function calling mechanism.";
44
+ /**
45
+ * Compact one-line reminder appended to each assistant message
46
+ * to reinforce the JSON format.
47
+ */
48
+ export declare const STRUCTURED_OUTPUT_REMINDER = "\n\nRemember: Respond with a JSON object: {\"thought\": \"...\", \"answer\": \"...\"} (answer only for final response).";
49
+ /**
50
+ * Response from the Plan-and-Solve agent.
51
+ *
52
+ * Different phases produce different shapes:
53
+ * - Planning: { thought, plan: string[] }
54
+ * - Executing: { thought } (may also include tool_calls)
55
+ * - Revising: { thought, revised_plan: string[] }
56
+ * - Final: { thought, answer }
57
+ */
58
+ export interface PlanSolveResponse {
59
+ /** Step-by-step reasoning (required in every response). */
60
+ thought: string;
61
+ /** Initial plan — numbered steps covering the full task. */
62
+ plan?: string[];
63
+ /** Replacement plan — overrides remaining steps. */
64
+ revised_plan?: string[];
65
+ /** Final answer for the user. */
66
+ answer?: string;
67
+ /**
68
+ * 1-based index of the step the LLM is currently working on.
69
+ * Used for plan progress tracking and display.
70
+ * Steps before this are marked as completed.
71
+ */
72
+ currentStep?: number;
73
+ }
74
+ /**
75
+ * Parse a raw LLM content string into a PlanSolveResponse.
76
+ *
77
+ * Reuses the same multi-strategy JSON extraction as parseReActResponse
78
+ * but handles the Plan-and-Solve shapes (plan/revised_plan arrays).
79
+ */
80
+ export declare function parsePlanSolveResponse(raw: string): PlanSolveResponse;
81
+ /**
82
+ * System prompt instructions for the Plan-and-Solve paradigm.
83
+ *
84
+ * The LLM is instructed to separate planning from execution:
85
+ * 1. Phase 1 — PLAN: Analyze and create a detailed numbered plan.
86
+ * 2. Phase 2 — RESOLVE: Work through each step, using tools.
87
+ * Revise remaining steps if new information emerges.
88
+ * 3. Final: When all steps are complete, provide the full answer.
89
+ */
90
+ export declare const PLAN_SOLVE_INSTRUCTIONS = "\n=== Plan-and-Resolve Paradigm ===\nYou follow a structured two-phase approach to solve tasks:\n\nPhase 1 \u2014 PLAN: Analyze the user's request and create a detailed, step-by-step plan covering all the work needed. Each step must be concrete and actionable.\n\nPhase 2 \u2014 RESOLVE: Execute each step of the plan. Use tools as needed.\n- After each step, you may REVISE remaining steps if the plan needs updating.\n- A revision replaces all remaining steps \u2014 do NOT re-list already completed steps.\n\n=== Response Format ===\nYou MUST respond with a valid JSON object in the \"content\" field.\n\nCreating the INITIAL PLAN:\n{\"thought\": \"...analysis...\", \"plan\": [\"Step 1: description\", \"Step 2: description\", \"...\"]}\n\nExecuting steps (use \"currentStep\" to indicate your progress):\n{\"thought\": \"...reasoning...\", \"currentStep\": 2}\n\nREVISING the plan (replaces REMAINING steps only):\n{\"thought\": \"...reasoning about why the plan needs to change...\", \"revised_plan\": [\"Updated Step A: ...\", \"Updated Step B: ...\", \"...\"]}\n\nFinal answer:\n{\"thought\": \"...summary...\", \"answer\": \"...complete answer for the user...\"}\n\nRules:\n- \"thought\" is REQUIRED in every response.\n- \"plan\" is ONLY for the initial plan creation (first response after user input).\n- \"revised_plan\" replaces REMAINING steps \u2014 do NOT re-list already done steps.\n- \"currentStep\" is the 1-based index of the step you are about to execute next.\n- \"answer\" is ONLY for the final response, when ALL steps are complete.\n- The JSON must be valid and parseable \u2014 no trailing commas, no comments.\n\n=== When to Replan \u2014 output \"revised_plan\" when: ===\n1. REPEATED TOOL FAILURES: A tool fails 2+ consecutive times on the same step.\n \u2192 The current approach isn't working \u2014 try a completely different method.\n\n2. CONTRADICTED ASSUMPTIONS: A tool result reveals information that disproves\n a key assumption your plan was based on.\n \u2192 Adjust remaining steps to account for the new reality.\n\n3. EXECUTION DRIFT: The actual state of things differs from what the plan\n expected at this point.\n \u2192 Realign the remaining steps with what has actually happened.\n\n4. STUCK ON A STEP: You cannot make progress on the current step after\n multiple attempts with different approaches.\n \u2192 Skip or reorder steps \u2014 try a different angle to reach the goal.\n\nIMPORTANT: Replanning is a normal part of problem-solving. If in doubt,\noutput a \"revised_plan\" rather than retrying the same failing approach.";
91
+ //# sourceMappingURL=response-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-schema.d.ts","sourceRoot":"","sources":["../../src/core/response-schema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,gBAAgB,CAAC;AAI9D;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAwB7D;AAmID;;;GAGG;AACH,eAAO,MAAM,8BAA8B,y0BAesF,CAAC;AAElI;;;GAGG;AACH,eAAO,MAAM,0BAA0B,4HACoF,CAAC;AAI5H;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAwCrE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,oiFAkDoC,CAAC"}
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ /**
3
+ * Structured JSON response schema for LLM outputs.
4
+ *
5
+ * Instead of parsing free-text ReAct format (Thought/Action/Action Input),
6
+ * the LLM is instructed to respond with a JSON object that the agent
7
+ * can reliably parse. This eliminates ambiguity in the agent loop.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PLAN_SOLVE_INSTRUCTIONS = exports.STRUCTURED_OUTPUT_REMINDER = exports.STRUCTURED_OUTPUT_INSTRUCTIONS = void 0;
11
+ exports.parseReActResponse = parseReActResponse;
12
+ exports.parsePlanSolveResponse = parsePlanSolveResponse;
13
+ // ─── Response Parser ────────────────────────────────────────────────────
14
+ /**
15
+ * Parse a raw LLM content string into a structured ReActResponse.
16
+ *
17
+ * Handles:
18
+ * - Raw JSON: {"thought": "...", "answer": "..."}
19
+ * - Code blocks: ```json\n{"thought": "..."}\n```
20
+ * - Extra text: Let me think... {"thought": "..."}
21
+ *
22
+ * Falls back to wrapping the raw text as a thought when JSON parsing fails.
23
+ */
24
+ function parseReActResponse(raw) {
25
+ const json = extractJSON(raw);
26
+ if (json) {
27
+ try {
28
+ const parsed = JSON.parse(json);
29
+ // Must be an object with at least "thought"
30
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
31
+ const thought = String(parsed.thought ?? "");
32
+ if ("answer" in parsed && parsed.answer !== undefined && parsed.answer !== null) {
33
+ return { thought, answer: String(parsed.answer) };
34
+ }
35
+ return { thought };
36
+ }
37
+ }
38
+ catch {
39
+ // JSON parse failed — fall through to fallback
40
+ }
41
+ }
42
+ // Fallback: treat the entire raw string as the thought
43
+ return { thought: raw };
44
+ }
45
+ /**
46
+ * Try to extract a JSON object from a string that may contain
47
+ * markdown, extra text, malformed newlines, or other noise.
48
+ *
49
+ * Strategy in order:
50
+ * 1. Direct parse of the trimmed text.
51
+ * 2. Extract from ```json ... ``` markdown block.
52
+ * 3. Find balanced { ... } via depth counting, then try to parse.
53
+ * 4. Clean up common issues (unescaped newlines) and retry steps 1-3.
54
+ *
55
+ * Returns the JSON string if found, or null.
56
+ */
57
+ function extractJSON(text) {
58
+ if (!text)
59
+ return null;
60
+ // Try with progressively more aggressive cleanup
61
+ const variants = [
62
+ text.trim(),
63
+ cleanupJSON(text.trim()),
64
+ text.trim().replace(/\n/g, " ").replace(/\r/g, ""),
65
+ ];
66
+ // De-duplicate variants
67
+ const seen = new Set();
68
+ const uniqueVariants = variants.filter((v) => {
69
+ if (seen.has(v))
70
+ return false;
71
+ seen.add(v);
72
+ return true;
73
+ });
74
+ for (const variant of uniqueVariants) {
75
+ const result = tryExtractJSON(variant);
76
+ if (result)
77
+ return result;
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Try all extraction strategies on a single variant of the text.
83
+ */
84
+ function tryExtractJSON(text) {
85
+ // 1. Try the entire string as JSON
86
+ if (isValidJSON(text))
87
+ return text;
88
+ // 2. Try extracting from markdown code blocks: ```json ... ```
89
+ const blockMatch = text.match(/```(?:json)?\s*(\{[\s\S]*?\})\s*```/);
90
+ if (blockMatch && isValidJSON(blockMatch[1]))
91
+ return blockMatch[1];
92
+ // 3. Try finding the first { ... } with balanced braces
93
+ const braceStart = text.indexOf("{");
94
+ if (braceStart >= 0) {
95
+ const fromBrace = text.slice(braceStart);
96
+ const result = extractBalancedBraces(fromBrace);
97
+ if (result)
98
+ return result;
99
+ }
100
+ return null;
101
+ }
102
+ /**
103
+ * Find balanced { ... } and validate as JSON.
104
+ * Handles strings with escaped quotes to avoid false brace matching.
105
+ */
106
+ function extractBalancedBraces(text) {
107
+ let depth = 0;
108
+ let inString = false;
109
+ let escapeNext = false;
110
+ for (let i = 0; i < text.length; i++) {
111
+ const ch = text[i];
112
+ if (inString) {
113
+ if (escapeNext) {
114
+ escapeNext = false;
115
+ }
116
+ else if (ch === "\\") {
117
+ escapeNext = true;
118
+ }
119
+ else if (ch === '"') {
120
+ inString = false;
121
+ }
122
+ }
123
+ else {
124
+ if (ch === '"') {
125
+ inString = true;
126
+ escapeNext = false;
127
+ }
128
+ else if (ch === "{") {
129
+ depth++;
130
+ }
131
+ else if (ch === "}") {
132
+ depth--;
133
+ if (depth === 0) {
134
+ const candidate = text.slice(0, i + 1);
135
+ if (isValidJSON(candidate))
136
+ return candidate;
137
+ break;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ return null;
143
+ }
144
+ /**
145
+ * Clean up common JSON formatting issues from LLM output.
146
+ */
147
+ function cleanupJSON(text) {
148
+ let result = text;
149
+ // Replace actual newlines inside JSON strings with \n escape
150
+ // (only between "..." regions)
151
+ result = result.replace(/\r\n/g, "\n").replace(/\r/g, "");
152
+ return result;
153
+ }
154
+ /**
155
+ * Quick check if a string is valid JSON.
156
+ */
157
+ function isValidJSON(text) {
158
+ try {
159
+ JSON.parse(text);
160
+ return true;
161
+ }
162
+ catch {
163
+ return false;
164
+ }
165
+ }
166
+ // ─── System Prompt Templates ────────────────────────────────────────────
167
+ /**
168
+ * Instructions injected into the system prompt to teach the LLM
169
+ * the JSON response format.
170
+ */
171
+ exports.STRUCTURED_OUTPUT_INSTRUCTIONS = `
172
+ === Response Format ===
173
+ You MUST respond with a valid JSON object in the "content" field of your message.
174
+ Do NOT wrap the JSON in markdown code blocks.
175
+
176
+ When you have the FINAL ANSWER for the user:
177
+ {"thought": "...step-by-step reasoning...", "answer": "...complete answer for the user..."}
178
+
179
+ When you are REASONING (intermediate step, before or after using tools):
180
+ {"thought": "...step-by-step reasoning..."}
181
+
182
+ Rules:
183
+ - "thought" is REQUIRED in every response — it contains your step-by-step reasoning.
184
+ - "answer" is ONLY included in your final response, when you have the complete answer.
185
+ - The JSON must be valid and parseable — no trailing commas, no comments.
186
+ - If you need to use a tool, put your reasoning in "thought" as JSON, and send the tool call via the function calling mechanism.`;
187
+ /**
188
+ * Compact one-line reminder appended to each assistant message
189
+ * to reinforce the JSON format.
190
+ */
191
+ exports.STRUCTURED_OUTPUT_REMINDER = "\n\nRemember: Respond with a JSON object: {\"thought\": \"...\", \"answer\": \"...\"} (answer only for final response).";
192
+ /**
193
+ * Parse a raw LLM content string into a PlanSolveResponse.
194
+ *
195
+ * Reuses the same multi-strategy JSON extraction as parseReActResponse
196
+ * but handles the Plan-and-Solve shapes (plan/revised_plan arrays).
197
+ */
198
+ function parsePlanSolveResponse(raw) {
199
+ const json = extractJSON(raw);
200
+ if (json) {
201
+ try {
202
+ const parsed = JSON.parse(json);
203
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
204
+ const thought = String(parsed.thought ?? "");
205
+ const result = { thought };
206
+ // plan — array of strings
207
+ if (parsed.plan && Array.isArray(parsed.plan)) {
208
+ result.plan = parsed.plan.map(String);
209
+ }
210
+ // revised_plan — array of strings
211
+ if (parsed.revised_plan && Array.isArray(parsed.revised_plan)) {
212
+ result.revised_plan = parsed.revised_plan.map(String);
213
+ }
214
+ // answer — final response
215
+ if (parsed.answer !== undefined && parsed.answer !== null) {
216
+ result.answer = String(parsed.answer);
217
+ }
218
+ // currentStep — step progress indicator (1-based)
219
+ if (typeof parsed.currentStep === "number" && parsed.currentStep >= 1) {
220
+ result.currentStep = Math.floor(parsed.currentStep);
221
+ }
222
+ return result;
223
+ }
224
+ }
225
+ catch {
226
+ // JSON parse failed — fall through to fallback
227
+ }
228
+ }
229
+ // Fallback: treat the entire raw string as thought
230
+ return { thought: raw };
231
+ }
232
+ /**
233
+ * System prompt instructions for the Plan-and-Solve paradigm.
234
+ *
235
+ * The LLM is instructed to separate planning from execution:
236
+ * 1. Phase 1 — PLAN: Analyze and create a detailed numbered plan.
237
+ * 2. Phase 2 — RESOLVE: Work through each step, using tools.
238
+ * Revise remaining steps if new information emerges.
239
+ * 3. Final: When all steps are complete, provide the full answer.
240
+ */
241
+ exports.PLAN_SOLVE_INSTRUCTIONS = `
242
+ === Plan-and-Resolve Paradigm ===
243
+ You follow a structured two-phase approach to solve tasks:
244
+
245
+ Phase 1 — PLAN: Analyze the user's request and create a detailed, step-by-step plan covering all the work needed. Each step must be concrete and actionable.
246
+
247
+ Phase 2 — RESOLVE: Execute each step of the plan. Use tools as needed.
248
+ - After each step, you may REVISE remaining steps if the plan needs updating.
249
+ - A revision replaces all remaining steps — do NOT re-list already completed steps.
250
+
251
+ === Response Format ===
252
+ You MUST respond with a valid JSON object in the "content" field.
253
+
254
+ Creating the INITIAL PLAN:
255
+ {"thought": "...analysis...", "plan": ["Step 1: description", "Step 2: description", "..."]}
256
+
257
+ Executing steps (use "currentStep" to indicate your progress):
258
+ {"thought": "...reasoning...", "currentStep": 2}
259
+
260
+ REVISING the plan (replaces REMAINING steps only):
261
+ {"thought": "...reasoning about why the plan needs to change...", "revised_plan": ["Updated Step A: ...", "Updated Step B: ...", "..."]}
262
+
263
+ Final answer:
264
+ {"thought": "...summary...", "answer": "...complete answer for the user..."}
265
+
266
+ Rules:
267
+ - "thought" is REQUIRED in every response.
268
+ - "plan" is ONLY for the initial plan creation (first response after user input).
269
+ - "revised_plan" replaces REMAINING steps — do NOT re-list already done steps.
270
+ - "currentStep" is the 1-based index of the step you are about to execute next.
271
+ - "answer" is ONLY for the final response, when ALL steps are complete.
272
+ - The JSON must be valid and parseable — no trailing commas, no comments.
273
+
274
+ === When to Replan — output "revised_plan" when: ===
275
+ 1. REPEATED TOOL FAILURES: A tool fails 2+ consecutive times on the same step.
276
+ → The current approach isn't working — try a completely different method.
277
+
278
+ 2. CONTRADICTED ASSUMPTIONS: A tool result reveals information that disproves
279
+ a key assumption your plan was based on.
280
+ → Adjust remaining steps to account for the new reality.
281
+
282
+ 3. EXECUTION DRIFT: The actual state of things differs from what the plan
283
+ expected at this point.
284
+ → Realign the remaining steps with what has actually happened.
285
+
286
+ 4. STUCK ON A STEP: You cannot make progress on the current step after
287
+ multiple attempts with different approaches.
288
+ → Skip or reorder steps — try a different angle to reach the goal.
289
+
290
+ IMPORTANT: Replanning is a normal part of problem-solving. If in doubt,
291
+ output a "revised_plan" rather than retrying the same failing approach.`;
292
+ //# sourceMappingURL=response-schema.js.map