@xalia/agent 0.6.9 → 0.6.11

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 (199) hide show
  1. package/README.md +11 -0
  2. package/dist/agent/src/agent/agent.js +77 -18
  3. package/dist/agent/src/agent/agentUtils.js +3 -2
  4. package/dist/agent/src/agent/documentSummarizer.js +126 -0
  5. package/dist/agent/src/agent/dummyLLM.js +25 -22
  6. package/dist/agent/src/agent/imageGenLLM.js +22 -19
  7. package/dist/agent/src/agent/llm.js +1 -1
  8. package/dist/agent/src/agent/openAILLM.js +15 -12
  9. package/dist/agent/src/agent/openAILLMStreaming.js +68 -37
  10. package/dist/agent/src/agent/repeatLLM.js +16 -7
  11. package/dist/agent/src/agent/tokenCounter.js +390 -0
  12. package/dist/agent/src/agent/tokenCounter.test.js +206 -0
  13. package/dist/agent/src/agent/toolSettings.js +17 -0
  14. package/dist/agent/src/agent/tools/calculatorTool.js +45 -0
  15. package/dist/agent/src/agent/tools/contentExtractors/pdfToText.js +55 -0
  16. package/dist/agent/src/agent/tools/datetimeTool.js +38 -0
  17. package/dist/agent/src/agent/tools/fileManager/fileManagerTool.js +156 -0
  18. package/dist/agent/src/agent/tools/fileManager/index.js +31 -0
  19. package/dist/agent/src/agent/tools/fileManager/memoryFileManager.js +102 -0
  20. package/dist/agent/src/{chat/data → agent/tools/fileManager}/mimeTypes.js +3 -1
  21. package/dist/agent/src/agent/tools/fileManager/prompt.js +33 -0
  22. package/dist/agent/src/{chat/data/dbSessionFileModels.js → agent/tools/fileManager/types.js} +7 -0
  23. package/dist/agent/src/agent/tools/index.js +64 -0
  24. package/dist/agent/src/agent/tools/openUrlTool.js +57 -0
  25. package/dist/agent/src/agent/tools/renderTool.js +89 -0
  26. package/dist/agent/src/agent/tools/utils.js +61 -0
  27. package/dist/agent/src/{chat/utils/search.js → agent/tools/webSearch.js} +1 -2
  28. package/dist/agent/src/agent/tools/webSearchTool.js +40 -0
  29. package/dist/agent/src/chat/client/chatClient.js +28 -0
  30. package/dist/agent/src/chat/client/index.js +4 -1
  31. package/dist/agent/src/chat/client/sessionClient.js +28 -2
  32. package/dist/agent/src/chat/constants.js +8 -0
  33. package/dist/agent/src/chat/data/dbSessionFiles.js +11 -6
  34. package/dist/agent/src/chat/protocol/messages.js +5 -0
  35. package/dist/agent/src/chat/server/chatContextManager.js +45 -25
  36. package/dist/agent/src/chat/server/conversation.js +3 -0
  37. package/dist/agent/src/chat/server/imageGeneratorTools.js +20 -8
  38. package/dist/agent/src/chat/server/openAIRouterLLM.js +0 -3
  39. package/dist/agent/src/chat/server/openSession.js +218 -55
  40. package/dist/agent/src/chat/server/promptRefiner.js +86 -0
  41. package/dist/agent/src/chat/server/server.js +5 -1
  42. package/dist/agent/src/chat/server/sessionFileManager.js +22 -221
  43. package/dist/agent/src/chat/server/sessionRegistry.js +87 -0
  44. package/dist/agent/src/chat/server/titleGenerator.js +112 -0
  45. package/dist/agent/src/chat/server/titleGenerator.test.js +113 -0
  46. package/dist/agent/src/chat/server/tools.js +63 -287
  47. package/dist/agent/src/chat/utils/approvalManager.js +6 -3
  48. package/dist/agent/src/chat/utils/multiAsyncQueue.js +3 -0
  49. package/dist/agent/src/test/agent.test.js +16 -17
  50. package/dist/agent/src/test/chatContextManager.test.js +15 -3
  51. package/dist/agent/src/test/dbMcpServerConfigs.test.js +4 -4
  52. package/dist/agent/src/test/dbSessionFiles.test.js +17 -17
  53. package/dist/agent/src/test/testTools.js +6 -1
  54. package/dist/agent/src/test/tools.test.js +27 -9
  55. package/dist/agent/src/tool/agentChat.js +5 -2
  56. package/dist/agent/src/tool/chatMain.js +34 -7
  57. package/dist/agent/src/tool/commandPrompt.js +2 -2
  58. package/dist/agent/src/tool/files.js +7 -8
  59. package/package.json +8 -2
  60. package/.env.development +0 -1
  61. package/.prettierrc.json +0 -11
  62. package/dist/agent/src/agent/tools.js +0 -44
  63. package/eslint.config.mjs +0 -38
  64. package/scripts/chat_server +0 -8
  65. package/scripts/git_message +0 -31
  66. package/scripts/git_wip +0 -21
  67. package/scripts/pr_message +0 -18
  68. package/scripts/pr_review +0 -16
  69. package/scripts/setup_chat +0 -90
  70. package/scripts/shutdown_chat_server +0 -42
  71. package/scripts/start_chat_server +0 -24
  72. package/scripts/sudomcp_import +0 -23
  73. package/scripts/test_chat +0 -308
  74. package/src/agent/agent.ts +0 -624
  75. package/src/agent/agentUtils.ts +0 -285
  76. package/src/agent/compressingContextManager.ts +0 -129
  77. package/src/agent/context.ts +0 -265
  78. package/src/agent/contextWithWorkspace.ts +0 -162
  79. package/src/agent/dummyLLM.ts +0 -126
  80. package/src/agent/iAgentEventHandler.ts +0 -64
  81. package/src/agent/imageGenLLM.ts +0 -97
  82. package/src/agent/imageGenerator.ts +0 -45
  83. package/src/agent/iplatform.ts +0 -18
  84. package/src/agent/llm.ts +0 -74
  85. package/src/agent/mcpServerManager.ts +0 -541
  86. package/src/agent/nullAgentEventHandler.ts +0 -26
  87. package/src/agent/nullPlatform.ts +0 -13
  88. package/src/agent/openAI.ts +0 -123
  89. package/src/agent/openAILLM.ts +0 -95
  90. package/src/agent/openAILLMStreaming.ts +0 -609
  91. package/src/agent/promptProvider.ts +0 -87
  92. package/src/agent/repeatLLM.ts +0 -50
  93. package/src/agent/sudoMcpServerManager.ts +0 -361
  94. package/src/agent/tokenAuth.ts +0 -50
  95. package/src/agent/tools.ts +0 -57
  96. package/src/chat/client/chatClient.ts +0 -922
  97. package/src/chat/client/connection.test.ts +0 -241
  98. package/src/chat/client/connection.ts +0 -286
  99. package/src/chat/client/constants.ts +0 -1
  100. package/src/chat/client/index.ts +0 -18
  101. package/src/chat/client/interfaces.ts +0 -34
  102. package/src/chat/client/sessionClient.ts +0 -537
  103. package/src/chat/client/sessionFiles.ts +0 -142
  104. package/src/chat/client/teamManager.ts +0 -29
  105. package/src/chat/data/apiKeyManager.ts +0 -76
  106. package/src/chat/data/dataModels.ts +0 -101
  107. package/src/chat/data/database.ts +0 -997
  108. package/src/chat/data/dbMcpServerConfigs.ts +0 -59
  109. package/src/chat/data/dbSessionFileModels.ts +0 -113
  110. package/src/chat/data/dbSessionFiles.ts +0 -99
  111. package/src/chat/data/dbSessionMessages.ts +0 -102
  112. package/src/chat/data/mimeTypes.ts +0 -58
  113. package/src/chat/protocol/connectionMessages.ts +0 -49
  114. package/src/chat/protocol/constants.ts +0 -55
  115. package/src/chat/protocol/errors.ts +0 -16
  116. package/src/chat/protocol/messages.ts +0 -846
  117. package/src/chat/server/README.md +0 -127
  118. package/src/chat/server/chatContextManager.ts +0 -639
  119. package/src/chat/server/connectionManager.test.ts +0 -246
  120. package/src/chat/server/connectionManager.ts +0 -506
  121. package/src/chat/server/conversation.ts +0 -316
  122. package/src/chat/server/errorUtils.ts +0 -28
  123. package/src/chat/server/imageGeneratorTools.ts +0 -160
  124. package/src/chat/server/openAIRouterLLM.ts +0 -171
  125. package/src/chat/server/openSession.ts +0 -1689
  126. package/src/chat/server/openSessionMessageSender.ts +0 -4
  127. package/src/chat/server/server.ts +0 -175
  128. package/src/chat/server/sessionFileManager.ts +0 -422
  129. package/src/chat/server/sessionRegistry.test.ts +0 -137
  130. package/src/chat/server/sessionRegistry.ts +0 -1425
  131. package/src/chat/server/test-utils/mockFactories.ts +0 -422
  132. package/src/chat/server/tools.ts +0 -397
  133. package/src/chat/utils/agentSessionMap.ts +0 -76
  134. package/src/chat/utils/approvalManager.ts +0 -183
  135. package/src/chat/utils/asyncLock.ts +0 -43
  136. package/src/chat/utils/asyncQueue.ts +0 -62
  137. package/src/chat/utils/htmlToText.ts +0 -61
  138. package/src/chat/utils/multiAsyncQueue.ts +0 -62
  139. package/src/chat/utils/responseAwaiter.ts +0 -181
  140. package/src/chat/utils/search.ts +0 -139
  141. package/src/chat/utils/userResolver.ts +0 -48
  142. package/src/chat/utils/websocket.ts +0 -16
  143. package/src/index.ts +0 -0
  144. package/src/test/agent.test.ts +0 -590
  145. package/src/test/approvalManager.test.ts +0 -141
  146. package/src/test/chatContextManager.test.ts +0 -527
  147. package/src/test/clientServerConnection.test.ts +0 -205
  148. package/src/test/compressingContextManager.test.ts +0 -77
  149. package/src/test/context.test.ts +0 -150
  150. package/src/test/contextTestTools.ts +0 -95
  151. package/src/test/conversation.test.ts +0 -109
  152. package/src/test/db.test.ts +0 -363
  153. package/src/test/dbMcpServerConfigs.test.ts +0 -112
  154. package/src/test/dbSessionFiles.test.ts +0 -258
  155. package/src/test/dbSessionMessages.test.ts +0 -85
  156. package/src/test/dbTestTools.ts +0 -157
  157. package/src/test/imageLoad.test.ts +0 -15
  158. package/src/test/mcpServerManager.test.ts +0 -114
  159. package/src/test/multiAsyncQueue.test.ts +0 -183
  160. package/src/test/openaiStreaming.test.ts +0 -177
  161. package/src/test/prompt.test.ts +0 -27
  162. package/src/test/promptProvider.test.ts +0 -33
  163. package/src/test/responseAwaiter.test.ts +0 -103
  164. package/src/test/sudoMcpServerManager.test.ts +0 -63
  165. package/src/test/testTools.ts +0 -171
  166. package/src/test/tools.test.ts +0 -39
  167. package/src/tool/agentChat.ts +0 -194
  168. package/src/tool/agentMain.ts +0 -180
  169. package/src/tool/chatMain.ts +0 -594
  170. package/src/tool/commandPrompt.ts +0 -264
  171. package/src/tool/files.ts +0 -84
  172. package/src/tool/main.ts +0 -25
  173. package/src/tool/nodePlatform.ts +0 -73
  174. package/src/tool/options.ts +0 -144
  175. package/src/tool/prompt.ts +0 -101
  176. package/test_data/background_test_profile.json +0 -6
  177. package/test_data/background_test_script.json +0 -11
  178. package/test_data/dummyllm_script_crash.json +0 -32
  179. package/test_data/dummyllm_script_image_gen.json +0 -19
  180. package/test_data/dummyllm_script_image_gen_fe.json +0 -29
  181. package/test_data/dummyllm_script_invoke_image_gen_tool.json +0 -37
  182. package/test_data/dummyllm_script_render_tool.json +0 -29
  183. package/test_data/dummyllm_script_simplecalc.json +0 -28
  184. package/test_data/dummyllm_script_test_auto_approve.json +0 -81
  185. package/test_data/dummyllm_script_test_simplecalc_addition.json +0 -29
  186. package/test_data/frog.png +0 -0
  187. package/test_data/frog.png.b64 +0 -1
  188. package/test_data/git_message_profile.json +0 -4
  189. package/test_data/git_wip_system.txt +0 -5
  190. package/test_data/image_gen_test_profile.json +0 -5
  191. package/test_data/pr_message_profile.json +0 -4
  192. package/test_data/pr_review_profile.json +0 -4
  193. package/test_data/prompt_simplecalc.txt +0 -1
  194. package/test_data/simplecalc_profile.json +0 -4
  195. package/test_data/sudomcp_import_profile.json +0 -4
  196. package/test_data/test_script_profile.json +0 -8
  197. package/tsconfig.json +0 -13
  198. package/vitest.config.ts +0 -39
  199. /package/dist/agent/src/{chat/utils → agent/tools/contentExtractors}/htmlToText.js +0 -0
@@ -1,171 +0,0 @@
1
- import {
2
- AssistantMessageParam,
3
- MessageParam,
4
- MessageToolCall,
5
- ToolMessageParam,
6
- ContentPartImage,
7
- ToolDescriptor,
8
- Completion,
9
- } from "../agent/llm";
10
- import { IAgentEventHandler } from "../agent/iAgentEventHandler";
11
- import { IPlatform } from "../agent/iplatform";
12
- import { DummyLLM, DummyLLMScriptEntry } from "../agent/dummyLLM";
13
- import { ILLM } from "../agent/llm";
14
-
15
- export const DUMMY_PLATFORM: IPlatform = {
16
- openUrl: () => {
17
- throw Error("unimpl");
18
- },
19
- load: () => {
20
- throw Error("unimpl");
21
- },
22
- renderHTML: () => {
23
- throw Error("unimpl");
24
- },
25
- };
26
-
27
- /**
28
- * IAgentEventHandler which records all calls, for testing.
29
- */
30
- export class TestAgentEventHandler implements IAgentEventHandler {
31
- private all: MessageParam[] = [];
32
- private completions: AssistantMessageParam[] = [];
33
- private images: ContentPartImage[] = [];
34
- private agentMessages: string[] = [""];
35
- private reasoning: string[] = [""];
36
- private toolCalls: MessageToolCall[] = [];
37
- private agentToolCalls: MessageToolCall[] = [];
38
- private toolCallResults: ToolMessageParam[] = [];
39
-
40
- onCompletion(result: AssistantMessageParam) {
41
- this.completions.push(result);
42
- this.all.push(result);
43
- }
44
-
45
- onImage(image: ContentPartImage) {
46
- this.images.push(image);
47
- }
48
-
49
- onToolCallResult(result: ToolMessageParam): void {
50
- this.toolCallResults.push(result);
51
- this.all.push(result);
52
- }
53
-
54
- onAgentMessage(chunk: string, isEnd: boolean): Promise<void> {
55
- this.agentMessages[this.agentMessages.length - 1] += chunk;
56
- if (isEnd) {
57
- this.agentMessages.push("");
58
- this.reasoning.push("");
59
- }
60
- return new Promise<void>((r) => {
61
- r();
62
- });
63
- }
64
-
65
- onReasoning(reasoning: string): Promise<void> {
66
- this.reasoning[this.reasoning.length - 1] += reasoning;
67
- return new Promise<void>((r) => {
68
- r();
69
- });
70
- }
71
-
72
- onToolCall(
73
- toolCall: MessageToolCall,
74
- isAgentTool: boolean
75
- ): Promise<boolean> {
76
- return new Promise<boolean>((r) => {
77
- this.toolCalls.push(toolCall);
78
- if (isAgentTool) {
79
- this.agentToolCalls.push(toolCall);
80
- }
81
- r(true);
82
- });
83
- }
84
-
85
- getAll(): MessageParam[] {
86
- return this.all;
87
- }
88
-
89
- getCompletions(): AssistantMessageParam[] {
90
- return this.completions;
91
- }
92
-
93
- getAgentMessages(): string[] {
94
- return this.agentMessages.slice(0, this.agentMessages.length - 1);
95
- }
96
-
97
- getToolCalls(): MessageToolCall[] {
98
- return this.toolCalls;
99
- }
100
-
101
- getAgentToolCalls(): MessageToolCall[] {
102
- return this.agentToolCalls;
103
- }
104
-
105
- getToolCallResults(): ToolMessageParam[] {
106
- return this.toolCallResults;
107
- }
108
-
109
- getReasoning(): string[] {
110
- return this.reasoning;
111
- }
112
- }
113
-
114
- export type TestLLMRequest = {
115
- messages: MessageParam[];
116
- tools?: ToolDescriptor[];
117
- };
118
-
119
- /**
120
- * Extension of Dummy which records requests. Doesn't inherit due to the
121
- * static initializers.
122
- */
123
- export class TestDummyLLM extends DummyLLM {
124
- private readonly requests: TestLLMRequest[];
125
-
126
- constructor(script: DummyLLMScriptEntry[]) {
127
- super(script);
128
- this.requests = [];
129
- }
130
-
131
- override getConversationResponse(
132
- messages: MessageParam[],
133
- tools?: ToolDescriptor[],
134
- onMessage?: (msg: string, end: boolean) => Promise<void>,
135
- onReasoning?: (reasoning: string) => Promise<void>
136
- ): Promise<Completion> {
137
- this.requests.push({ messages, tools });
138
- return super.getConversationResponse(
139
- messages,
140
- tools,
141
- onMessage,
142
- onReasoning
143
- );
144
- }
145
-
146
- getRequests(): TestLLMRequest[] {
147
- return this.requests;
148
- }
149
- }
150
-
151
- /**
152
- * An LLM which always errors out.
153
- */
154
- export class TestErrorLLM implements ILLM {
155
- getModel(): string {
156
- return "error";
157
- }
158
- getUrl(): string {
159
- return "error://";
160
- }
161
- setModel(_model: string): void {
162
- throw new Error("cannot set model");
163
- }
164
- getConversationResponse(
165
- _messages: MessageParam[],
166
- _tools?: ToolDescriptor[],
167
- _onMessage?: (msg: string, end: boolean) => Promise<void>
168
- ): Promise<Completion> {
169
- throw new Error("LLM test error");
170
- }
171
- }
@@ -1,39 +0,0 @@
1
- import { expect } from "vitest";
2
- import {
3
- calculatorEval,
4
- isoWithTimezone,
5
- makeParseArgsFn,
6
- openURL,
7
- } from "../chat/server/tools";
8
-
9
- describe("Tools", () => {
10
- it("time_now should contain timezone", function () {
11
- let time = isoWithTimezone("UTC");
12
- console.log(time);
13
- expect(time).includes("UTC");
14
-
15
- time = isoWithTimezone("Asia/Tokyo");
16
- console.log(time);
17
- expect(time).includes("GMT+9");
18
- expect(time).includes("Asia/Tokyo");
19
- });
20
-
21
- it("arithmetic should eval expressions", function () {
22
- expect(calculatorEval("(3*4)-2")).eql("10");
23
- });
24
-
25
- it("openUrl grabs text from url without error", async function () {
26
- const text = await openURL("https://www.google.com/");
27
- console.log(text);
28
- expect(text).not.contains("rror");
29
- });
30
-
31
- it("makeParseArgsFn behaves correctly", () => {
32
- const parseNameValue = makeParseArgsFn(["name", "value"] as const);
33
- expect(parseNameValue({ name: "adsf", value: "qwer" })).eql({
34
- name: "adsf",
35
- value: "qwer",
36
- });
37
- expect(() => parseNameValue({ name: "adsf" })).throws();
38
- });
39
- });
@@ -1,194 +0,0 @@
1
- import yocto from "yocto-spinner";
2
- import { Spinner } from "yocto-spinner";
3
- import chalk from "chalk";
4
-
5
- import { configuration, utils } from "@xalia/xmcp/tool";
6
- import { getLogger } from "@xalia/xmcp/sdk";
7
-
8
- import { AgentProfile } from "../agent/agent";
9
- import { createAgentWithSkills } from "../agent/agentUtils";
10
- import { IAgentEventHandler } from "../agent/iAgentEventHandler";
11
-
12
- import { loadImageAsDataUrlOrUndefined } from "./files";
13
- import { NODE_PLATFORM } from "./nodePlatform";
14
- import { CommandPrompt } from "./commandPrompt";
15
- import { IPrompt, Prompt } from "./prompt";
16
- import { ContextManager } from "../agent/context";
17
- import {
18
- ContentPartImage,
19
- MessageParam,
20
- MessageToolCall,
21
- ToolMessageParam,
22
- } from "../agent/llm";
23
-
24
- const logger = getLogger();
25
-
26
- export const DEFAULT_AGENT_LLM_MODEL =
27
- process.env["DEFAULT_LLM_MODEL"] || "anthropic/claude-sonnet-4.5";
28
-
29
- async function write(msg: string): Promise<void> {
30
- return new Promise((resolve, err) => {
31
- process.stdout.write(msg, (e) => {
32
- if (e) {
33
- err(e);
34
- } else {
35
- resolve();
36
- }
37
- });
38
- });
39
- }
40
-
41
- export async function runChat(
42
- llmUrl: string,
43
- agentProfile: AgentProfile,
44
- conversation: MessageParam[] | undefined,
45
- prompt: string | undefined,
46
- image: string | undefined,
47
- llmApiKey: string | undefined,
48
- sudomcpConfig: configuration.Configuration,
49
- approveToolsUpTo: number,
50
- stream: boolean
51
- ) {
52
- // In chat mode, just print the messages. Ask for tool confirmation
53
- // unless approveTools is set.
54
-
55
- const spinner: Spinner = yocto();
56
- let first = true;
57
- let reasoningFirst = true;
58
-
59
- const onAgentMessage = async (msg: string, msgEnd: boolean) => {
60
- if (first) {
61
- first = false;
62
-
63
- if (!reasoningFirst) {
64
- await write(`${chalk.grey("]")}\n`);
65
- }
66
-
67
- await write("AGENT: ");
68
- spinner.stop().clear();
69
- }
70
-
71
- if (msg) {
72
- await write(msg);
73
- }
74
-
75
- if (msgEnd) {
76
- await write("\n");
77
- first = true;
78
- reasoningFirst = true;
79
- }
80
- };
81
-
82
- const onReasoning = async (reasoning: string) => {
83
- logger.debug(`[AgentChat.onReasoning]: ${reasoning}`);
84
- if (reasoningFirst) {
85
- spinner.stop().clear();
86
- await write(chalk.grey("[REASONING: "));
87
- reasoningFirst = false;
88
- }
89
- await write(chalk.grey(reasoning));
90
- };
91
-
92
- const repl: IPrompt = new Prompt();
93
- const cmdPrompt = new CommandPrompt(repl);
94
-
95
- let remainingApprovedToolCalls = approveToolsUpTo;
96
- const onToolCall = async (toolCall: MessageToolCall) => {
97
- if (remainingApprovedToolCalls !== 0) {
98
- --remainingApprovedToolCalls;
99
- return true;
100
- }
101
-
102
- spinner.stop().clear();
103
- const result = await cmdPrompt.promptToolCall(toolCall);
104
- spinner.start();
105
- return result;
106
- };
107
-
108
- const onToolCallResult = (result: ToolMessageParam) => {
109
- // CLI doesn't need to display tool results - they're handled internally
110
- logger.debug(`Tool call result: ${JSON.stringify(result)}`);
111
- };
112
-
113
- const onImage = (image: ContentPartImage) => {
114
- const dataUrl = image.image_url.url;
115
- void NODE_PLATFORM.renderHTML(`<img src="${dataUrl}" />`);
116
- };
117
-
118
- // Create event handler for CLI agent
119
- const eventHandler: IAgentEventHandler = {
120
- onCompletion: () => {},
121
- onImage,
122
- onAgentMessage,
123
- onReasoning,
124
- onToolCall,
125
- onToolCallResult,
126
- };
127
-
128
- // Create agent
129
-
130
- const [agent, sudoMcpServerManager] = await createAgentWithSkills(
131
- llmUrl,
132
- agentProfile.model || DEFAULT_AGENT_LLM_MODEL,
133
- eventHandler,
134
- NODE_PLATFORM,
135
- new ContextManager(agentProfile.system_prompt, conversation || []),
136
- llmApiKey,
137
- sudomcpConfig,
138
- agentProfile.mcp_settings,
139
- utils.FRONTEND_PROD_AUTHORIZED_URL,
140
- stream
141
- );
142
-
143
- // Opening banner
144
- console.log(chalk.green("SudoMCP Agent CLI"));
145
- console.log(
146
- `(Type ${chalk.yellow("/h")} for help, ${chalk.yellow("/q")} to quit.)`
147
- );
148
-
149
- // Display first prompt if supplied
150
- if (prompt) {
151
- console.log(`USER: ${prompt}`);
152
- }
153
-
154
- // Conversation loop
155
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
156
- while (true) {
157
- if (!prompt) {
158
- const [msg, img] = await cmdPrompt.getNextPrompt(
159
- agent,
160
- sudoMcpServerManager
161
- );
162
- if (!msg && !img) {
163
- break;
164
- }
165
- prompt = msg;
166
- image = img;
167
- }
168
-
169
- image = loadImageAsDataUrlOrUndefined(image);
170
-
171
- // Pass the prompt and image to the Agent
172
- try {
173
- spinner.start();
174
- await agent.userMessageEx(prompt, image);
175
- } catch (e) {
176
- console.log(`ERROR: ${String(e)}`);
177
- console.log(` STACK: ${(e as Error).stack ?? "undefined"}`);
178
- }
179
- prompt = undefined;
180
- image = undefined;
181
- }
182
-
183
- // Shutdown the agent
184
-
185
- await cmdPrompt.shutdown();
186
- await agent.shutdown();
187
-
188
- logger.debug("shutdown done");
189
- }
190
-
191
- /**
192
- * Read lines from the prompt, parsing any commands, and return once there is
193
- * a prompt and/or image for the llm. Both undefined means exit.
194
- */
@@ -1,180 +0,0 @@
1
- import * as fs from "fs";
2
- import * as dotenv from "dotenv";
3
- import { command, option, flag, optional, string } from "cmd-ts";
4
- import { strict as assert } from "assert";
5
-
6
- import { configuration, utils } from "@xalia/xmcp/tool";
7
- import { getLogger } from "@xalia/xmcp/sdk";
8
-
9
- import { AgentProfile } from "../agent/agent";
10
- import { runOneShot } from "../agent/agentUtils";
11
-
12
- import {
13
- llmUrl,
14
- llmApiKey,
15
- promptFile,
16
- oneShot,
17
- approveTools,
18
- approveToolsUpTo,
19
- imageFile,
20
- } from "./options";
21
- import {
22
- loadFileOrUndefined,
23
- loadFileOrStdin,
24
- loadImageAsDataUrlOrUndefined,
25
- } from "./files";
26
- import { DEFAULT_AGENT_LLM_MODEL, runChat } from "./agentChat";
27
- import { NODE_PLATFORM } from "./nodePlatform";
28
- import { MessageParam } from "../agent/llm";
29
-
30
- dotenv.config();
31
-
32
- const logger = getLogger();
33
-
34
- export const agentMain = command({
35
- name: "main",
36
- args: {
37
- promptFile,
38
- imageFile,
39
- llmUrl,
40
- llmApiKey,
41
- oneShot,
42
- approveTools,
43
- approveToolsUpTo,
44
- sudomcpConfigFile: option({
45
- type: optional(string),
46
- long: "sudomcp-config-file",
47
- description:
48
- "SudoMCP config file (content or file, default: ~/config/..)",
49
- env: "SUDOMCP_CONFIG",
50
- }),
51
- conversationFile: option({
52
- type: optional(string),
53
- long: "conversation",
54
- description: "Restore conversation (content or file) (see /wc)",
55
- env: "CONVERSATION",
56
- }),
57
- conversationOutputFile: option({
58
- type: optional(string),
59
- long: "conversation-output",
60
- description: "Save final conversation to file (--one-shot mode)",
61
- env: "CONVERSATION_OUTPUT",
62
- }),
63
- agentProfileFile: option({
64
- type: optional(string),
65
- long: "agent-profile",
66
- description: "Agent profile (content or filename)",
67
- env: "AGENT_PROFILE",
68
- }),
69
- noStreaming: flag({
70
- long: "no-stream",
71
- description: "Disable streaming (chat mode only)",
72
- }),
73
- },
74
- handler: async ({
75
- promptFile,
76
- imageFile,
77
- llmUrl,
78
- llmApiKey,
79
- oneShot,
80
- approveTools,
81
- approveToolsUpTo,
82
- sudomcpConfigFile,
83
- conversationFile,
84
- conversationOutputFile,
85
- agentProfileFile,
86
- noStreaming,
87
- }): Promise<void> => {
88
- approveToolsUpTo = (() => {
89
- if (typeof approveToolsUpTo === "undefined") {
90
- // For the non-interactive case, `--approve-tools` is ignored.
91
- if (oneShot) {
92
- return -1;
93
- }
94
- return approveTools ? -1 : 0;
95
- }
96
- return approveToolsUpTo;
97
- })();
98
- assert(typeof approveToolsUpTo === "number");
99
-
100
- // Load the AgentProfile or use a default
101
-
102
- const agentProfile: AgentProfile = (() => {
103
- let agentProfile = utils.loadContentOrFileOrUndefined(
104
- agentProfileFile,
105
- AgentProfile
106
- );
107
- if (!agentProfile) {
108
- agentProfile = new AgentProfile(
109
- undefined,
110
- "You are a helpful agent",
111
- {}
112
- );
113
- }
114
-
115
- return agentProfile;
116
- })();
117
- logger.debug(`agent config: ${JSON.stringify(agentProfile)}`);
118
-
119
- // Read sudomcp config file. This will be used for SudoMcpServerManager,
120
- // and also to fall back to the sudomcp api key if an explicit llmApiKey
121
- // was not given.
122
-
123
- const sudomcpConfig = configuration.loadEnsureConfig(sudomcpConfigFile);
124
- if (!llmApiKey) {
125
- llmApiKey = sudomcpConfig.api_key;
126
- logger.debug(`using xmcp api key: ${llmApiKey}`);
127
- }
128
-
129
- // Restore conversation from value or file.
130
-
131
- const startingConversation: MessageParam[] | undefined =
132
- utils.loadContentOrFileOrUndefined(conversationFile);
133
- logger.debug(
134
- `startingConversation: ${JSON.stringify(startingConversation)}`
135
- );
136
-
137
- // Run in one-shot mode or chat-mode
138
-
139
- if (oneShot) {
140
- if (!promptFile) {
141
- throw new Error("one-shot mode requires a prompt");
142
- }
143
- const prompt = await loadFileOrStdin(promptFile);
144
-
145
- const { response, conversation } = await runOneShot(
146
- llmUrl,
147
- agentProfile,
148
- DEFAULT_AGENT_LLM_MODEL,
149
- startingConversation,
150
- NODE_PLATFORM,
151
- prompt,
152
- loadImageAsDataUrlOrUndefined(imageFile),
153
- llmApiKey,
154
- sudomcpConfig,
155
- approveToolsUpTo
156
- );
157
- console.log(response);
158
-
159
- if (conversationOutputFile) {
160
- logger.debug(`writing conversation to ${conversationOutputFile}:`);
161
- logger.debug(` conversation: ${JSON.stringify(conversation)}`);
162
-
163
- fs.writeFileSync(conversationOutputFile, JSON.stringify(conversation));
164
- }
165
- } else {
166
- const prompt = loadFileOrUndefined(promptFile);
167
- return runChat(
168
- llmUrl,
169
- agentProfile,
170
- startingConversation,
171
- prompt,
172
- imageFile,
173
- llmApiKey,
174
- sudomcpConfig,
175
- approveToolsUpTo,
176
- !noStreaming
177
- );
178
- }
179
- },
180
- });