@compyle/unagent 1.0.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 +547 -0
  3. package/dist/agents/agent-as-tool.d.ts +4 -0
  4. package/dist/agents/agent-as-tool.d.ts.map +1 -0
  5. package/dist/agents/agent-as-tool.js +105 -0
  6. package/dist/agents/agent-as-tool.js.map +1 -0
  7. package/dist/agents/define-agent.d.ts +101 -0
  8. package/dist/agents/define-agent.d.ts.map +1 -0
  9. package/dist/agents/define-agent.js +866 -0
  10. package/dist/agents/define-agent.js.map +1 -0
  11. package/dist/agents/index.d.ts +3 -0
  12. package/dist/agents/index.d.ts.map +1 -0
  13. package/dist/agents/index.js +3 -0
  14. package/dist/agents/index.js.map +1 -0
  15. package/dist/bridge/node-bridge.d.ts +2 -0
  16. package/dist/bridge/node-bridge.d.ts.map +1 -0
  17. package/dist/bridge/node-bridge.js +772 -0
  18. package/dist/bridge/node-bridge.js.map +1 -0
  19. package/dist/client/base-client.d.ts +86 -0
  20. package/dist/client/base-client.d.ts.map +1 -0
  21. package/dist/client/base-client.js +254 -0
  22. package/dist/client/base-client.js.map +1 -0
  23. package/dist/client/claude.d.ts +66 -0
  24. package/dist/client/claude.d.ts.map +1 -0
  25. package/dist/client/claude.js +846 -0
  26. package/dist/client/claude.js.map +1 -0
  27. package/dist/client/codex/codex-client.d.ts +78 -0
  28. package/dist/client/codex/codex-client.d.ts.map +1 -0
  29. package/dist/client/codex/codex-client.js +906 -0
  30. package/dist/client/codex/codex-client.js.map +1 -0
  31. package/dist/client/codex/codex-home.d.ts +6 -0
  32. package/dist/client/codex/codex-home.d.ts.map +1 -0
  33. package/dist/client/codex/codex-home.js +26 -0
  34. package/dist/client/codex/codex-home.js.map +1 -0
  35. package/dist/client/codex/config/config-loader.d.ts +8 -0
  36. package/dist/client/codex/config/config-loader.d.ts.map +1 -0
  37. package/dist/client/codex/config/config-loader.js +137 -0
  38. package/dist/client/codex/config/config-loader.js.map +1 -0
  39. package/dist/client/codex/config/config-types.d.ts +43 -0
  40. package/dist/client/codex/config/config-types.d.ts.map +1 -0
  41. package/dist/client/codex/config/config-types.js +2 -0
  42. package/dist/client/codex/config/config-types.js.map +1 -0
  43. package/dist/client/codex/config/config-writer.d.ts +24 -0
  44. package/dist/client/codex/config/config-writer.d.ts.map +1 -0
  45. package/dist/client/codex/config/config-writer.js +353 -0
  46. package/dist/client/codex/config/config-writer.js.map +1 -0
  47. package/dist/client/codex/config/index.d.ts +7 -0
  48. package/dist/client/codex/config/index.d.ts.map +1 -0
  49. package/dist/client/codex/config/index.js +6 -0
  50. package/dist/client/codex/config/index.js.map +1 -0
  51. package/dist/client/codex/config/mcp-config-generator.d.ts +7 -0
  52. package/dist/client/codex/config/mcp-config-generator.d.ts.map +1 -0
  53. package/dist/client/codex/config/mcp-config-generator.js +140 -0
  54. package/dist/client/codex/config/mcp-config-generator.js.map +1 -0
  55. package/dist/client/codex/config/tools-config-writer.d.ts +2 -0
  56. package/dist/client/codex/config/tools-config-writer.d.ts.map +1 -0
  57. package/dist/client/codex/config/tools-config-writer.js +21 -0
  58. package/dist/client/codex/config/tools-config-writer.js.map +1 -0
  59. package/dist/client/codex/index.d.ts +4 -0
  60. package/dist/client/codex/index.d.ts.map +1 -0
  61. package/dist/client/codex/index.js +3 -0
  62. package/dist/client/codex/index.js.map +1 -0
  63. package/dist/client/config-utils.d.ts +4 -0
  64. package/dist/client/config-utils.d.ts.map +1 -0
  65. package/dist/client/config-utils.js +32 -0
  66. package/dist/client/config-utils.js.map +1 -0
  67. package/dist/client/extra-headers.d.ts +12 -0
  68. package/dist/client/extra-headers.d.ts.map +1 -0
  69. package/dist/client/extra-headers.js +102 -0
  70. package/dist/client/extra-headers.js.map +1 -0
  71. package/dist/client/field-mappings.d.ts +3 -0
  72. package/dist/client/field-mappings.d.ts.map +1 -0
  73. package/dist/client/field-mappings.js +40 -0
  74. package/dist/client/field-mappings.js.map +1 -0
  75. package/dist/client/transformers/content-utils.d.ts +34 -0
  76. package/dist/client/transformers/content-utils.d.ts.map +1 -0
  77. package/dist/client/transformers/content-utils.js +237 -0
  78. package/dist/client/transformers/content-utils.js.map +1 -0
  79. package/dist/events/event-bus.d.ts +19 -0
  80. package/dist/events/event-bus.d.ts.map +1 -0
  81. package/dist/events/event-bus.js +134 -0
  82. package/dist/events/event-bus.js.map +1 -0
  83. package/dist/events/event-types.d.ts +53 -0
  84. package/dist/events/event-types.d.ts.map +1 -0
  85. package/dist/events/event-types.js +6 -0
  86. package/dist/events/event-types.js.map +1 -0
  87. package/dist/events/index.d.ts +4 -0
  88. package/dist/events/index.d.ts.map +1 -0
  89. package/dist/events/index.js +4 -0
  90. package/dist/events/index.js.map +1 -0
  91. package/dist/index.d.ts +12 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +11 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/messages/index.d.ts +3 -0
  96. package/dist/messages/index.d.ts.map +1 -0
  97. package/dist/messages/index.js +3 -0
  98. package/dist/messages/index.js.map +1 -0
  99. package/dist/messages/message-types.d.ts +60 -0
  100. package/dist/messages/message-types.d.ts.map +1 -0
  101. package/dist/messages/message-types.js +6 -0
  102. package/dist/messages/message-types.js.map +1 -0
  103. package/dist/messages/message-utils.d.ts +51 -0
  104. package/dist/messages/message-utils.d.ts.map +1 -0
  105. package/dist/messages/message-utils.js +343 -0
  106. package/dist/messages/message-utils.js.map +1 -0
  107. package/dist/tools/define-tool.d.ts +6 -0
  108. package/dist/tools/define-tool.d.ts.map +1 -0
  109. package/dist/tools/define-tool.js +83 -0
  110. package/dist/tools/define-tool.js.map +1 -0
  111. package/dist/tools/index.d.ts +6 -0
  112. package/dist/tools/index.d.ts.map +1 -0
  113. package/dist/tools/index.js +6 -0
  114. package/dist/tools/index.js.map +1 -0
  115. package/dist/tools/mcp-stdio-proxy.d.ts +2 -0
  116. package/dist/tools/mcp-stdio-proxy.d.ts.map +1 -0
  117. package/dist/tools/mcp-stdio-proxy.js +31 -0
  118. package/dist/tools/mcp-stdio-proxy.js.map +1 -0
  119. package/dist/tools/tool-call-context.d.ts +8 -0
  120. package/dist/tools/tool-call-context.d.ts.map +1 -0
  121. package/dist/tools/tool-call-context.js +44 -0
  122. package/dist/tools/tool-call-context.js.map +1 -0
  123. package/dist/tools/tool-registry.d.ts +14 -0
  124. package/dist/tools/tool-registry.d.ts.map +1 -0
  125. package/dist/tools/tool-registry.js +47 -0
  126. package/dist/tools/tool-registry.js.map +1 -0
  127. package/dist/tools/tool-result-converter.d.ts +3 -0
  128. package/dist/tools/tool-result-converter.d.ts.map +1 -0
  129. package/dist/tools/tool-result-converter.js +38 -0
  130. package/dist/tools/tool-result-converter.js.map +1 -0
  131. package/dist/tools/tool-service-manager.d.ts +12 -0
  132. package/dist/tools/tool-service-manager.d.ts.map +1 -0
  133. package/dist/tools/tool-service-manager.js +118 -0
  134. package/dist/tools/tool-service-manager.js.map +1 -0
  135. package/dist/tools/tool-stdio-mcp-service.d.ts +29 -0
  136. package/dist/tools/tool-stdio-mcp-service.d.ts.map +1 -0
  137. package/dist/tools/tool-stdio-mcp-service.js +185 -0
  138. package/dist/tools/tool-stdio-mcp-service.js.map +1 -0
  139. package/dist/tools/tool-types.d.ts +29 -0
  140. package/dist/tools/tool-types.d.ts.map +1 -0
  141. package/dist/tools/tool-types.js +2 -0
  142. package/dist/tools/tool-types.js.map +1 -0
  143. package/package.json +58 -0
@@ -0,0 +1,846 @@
1
+ import { query } from "@anthropic-ai/claude-agent-sdk";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import * as path from "path";
5
+ import { BaseClient, } from "./base-client.js";
6
+ import { ClientType, } from "../events/index.js";
7
+ import { createAssistantMessage, createToolCallResultMessage, createUserMessage, normalizeMessage, } from "../messages/index.js";
8
+ import { toContentArray, getTextValue, getImageUrl, stringifyContent, buildToolResultFromBlock, buildToolUseFromRecord, ToolCallTracker, } from "./transformers/content-utils.js";
9
+ import { convertSnakeCaseToCamelCase } from "./config-utils.js";
10
+ import { CLAUDE_FIELD_MAPPINGS } from "./field-mappings.js";
11
+ import { extractCustomTools, isRegisteredTool } from "../tools/define-tool.js";
12
+ import { getAgentToolServiceCommand, resolveToolServiceOwner } from "../tools/tool-service-manager.js";
13
+ export class ClaudeClient extends BaseClient {
14
+ agentConfig;
15
+ toolCallTracker = new ToolCallTracker();
16
+ stderrBuffer = "";
17
+ stderrBufferLimit = 16000;
18
+ activeQuery;
19
+ constructor(config) {
20
+ super(ClientType.CLAUDE, config);
21
+ this.agentConfig = convertSnakeCaseToCamelCase(config, CLAUDE_FIELD_MAPPINGS);
22
+ }
23
+ async run(params) {
24
+ const events = [];
25
+ this.toolCallTracker.reset();
26
+ this.resetStderrBuffer();
27
+ let finalData = null;
28
+ let errorOccurred = false;
29
+ let sessionStarted = false;
30
+ const { controller, cleanup } = this.createAbortController(params.signal);
31
+ try {
32
+ const queryOptions = await this.buildQueryOptions({ abortController: controller });
33
+ const queryRunner = query({
34
+ prompt: params.query,
35
+ options: queryOptions,
36
+ });
37
+ this.activeQuery = queryRunner;
38
+ for await (const message of queryRunner) {
39
+ if (!sessionStarted && this.isInitMessage(message)) {
40
+ const initSessionId = this.getInitSessionId(message);
41
+ if (initSessionId) {
42
+ await this.emitSessionStart(params, events, initSessionId);
43
+ await this.emitUserItemEvents(params.query, events);
44
+ sessionStarted = true;
45
+ }
46
+ }
47
+ const convertedEvents = this.convertMessageToEvents(message);
48
+ events.push(...convertedEvents);
49
+ for (const event of convertedEvents) {
50
+ await this.emit(event);
51
+ }
52
+ if (message.type === "text" && message.content) {
53
+ finalData = message;
54
+ }
55
+ if (message.type === "assistant" && message.message) {
56
+ finalData = message.message;
57
+ }
58
+ if (message.type === "message" && message.role === "assistant") {
59
+ finalData = message;
60
+ }
61
+ }
62
+ if (this.isAbortRequested()) {
63
+ await this.emitSessionEnd(events, "aborted");
64
+ return {
65
+ success: false,
66
+ error: new Error("Aborted"),
67
+ events,
68
+ };
69
+ }
70
+ await this.emitSessionEnd(events);
71
+ return {
72
+ success: !errorOccurred,
73
+ data: finalData,
74
+ events,
75
+ };
76
+ }
77
+ catch (error) {
78
+ if (this.isAbortRequested()) {
79
+ await this.emitSessionEnd(events, "aborted");
80
+ return {
81
+ success: false,
82
+ error: error,
83
+ events,
84
+ };
85
+ }
86
+ await this.emitErrorEvent("run", error, events, this.getStderrContext());
87
+ await this.emitSessionEnd(events, "error");
88
+ return {
89
+ success: false,
90
+ error: error,
91
+ events,
92
+ };
93
+ }
94
+ finally {
95
+ this.activeQuery = undefined;
96
+ cleanup();
97
+ }
98
+ }
99
+ async runStream(params) {
100
+ this.toolCallTracker.reset();
101
+ this.resetStderrBuffer();
102
+ const { controller, cleanup } = this.createAbortController(params.signal);
103
+ try {
104
+ const queryOptions = await this.buildQueryOptions({ abortController: controller });
105
+ const eventStream = this.createEventStream(params, queryOptions);
106
+ return {
107
+ events: this.wrapEventStream(eventStream, () => {
108
+ this.activeQuery = undefined;
109
+ cleanup();
110
+ }),
111
+ };
112
+ }
113
+ catch (error) {
114
+ const aborted = this.isAbortRequested();
115
+ cleanup();
116
+ if (aborted) {
117
+ const sessionEndEvent = await this.emitSessionEnd(undefined, "aborted");
118
+ return {
119
+ events: (async function* () {
120
+ yield sessionEndEvent;
121
+ })(),
122
+ };
123
+ }
124
+ const errorEvent = await this.emitErrorEvent("runStream", error, undefined, this.getStderrContext());
125
+ const sessionEndEvent = await this.emitSessionEnd(undefined, "error");
126
+ return {
127
+ events: (async function* () {
128
+ yield errorEvent;
129
+ yield sessionEndEvent;
130
+ })(),
131
+ };
132
+ }
133
+ }
134
+ async resume(params) {
135
+ this.toolCallTracker.reset();
136
+ this.resetStderrBuffer();
137
+ const { controller, cleanup } = this.createAbortController();
138
+ try {
139
+ const queryOptions = await this.buildQueryOptions({ abortController: controller });
140
+ const eventStream = this.createEventStream({ query: params.query || "[resuming session]", sessionId: params.sessionId }, queryOptions, params.sessionId);
141
+ return {
142
+ events: this.wrapEventStream(eventStream, () => {
143
+ this.activeQuery = undefined;
144
+ cleanup();
145
+ }),
146
+ };
147
+ }
148
+ catch (error) {
149
+ const aborted = this.isAbortRequested();
150
+ cleanup();
151
+ if (aborted) {
152
+ const sessionEndEvent = await this.emitSessionEnd(undefined, "aborted");
153
+ return {
154
+ events: (async function* () {
155
+ yield sessionEndEvent;
156
+ })(),
157
+ };
158
+ }
159
+ const errorEvent = await this.emitErrorEvent("resume", error, undefined, {
160
+ ...this.getStderrContext(),
161
+ sessionId: params.sessionId,
162
+ });
163
+ const sessionEndEvent = await this.emitSessionEnd(undefined, "error");
164
+ return {
165
+ events: (async function* () {
166
+ yield errorEvent;
167
+ yield sessionEndEvent;
168
+ })(),
169
+ };
170
+ }
171
+ }
172
+ async buildQueryOptions(overrides) {
173
+ const options = {};
174
+ let toolRegistryServer = null;
175
+ const toolServerName = "custom-tools";
176
+ const permissionMode = resolveString(this.agentConfig.permissionMode);
177
+ if (permissionMode) {
178
+ options.permissionMode = permissionMode === "auto" ? "default" : permissionMode;
179
+ }
180
+ const systemPrompt = resolveString(this.agentConfig.systemPrompt);
181
+ if (systemPrompt !== undefined) {
182
+ options.systemPrompt = systemPrompt;
183
+ }
184
+ if (this.agentConfig.model) {
185
+ options.model = this.agentConfig.model;
186
+ }
187
+ if (this.agentConfig.agents) {
188
+ const normalizedAgents = {};
189
+ for (const [name, agent] of Object.entries(this.agentConfig.agents)) {
190
+ const { customTools, toolNames } = splitAgentTools(agent.tools);
191
+ const extraCustomTools = Array.isArray(agent.customTools) ? agent.customTools : [];
192
+ const agentCustomTools = [...customTools, ...extraCustomTools];
193
+ const allowedTools = normalizeToolNameList(agent.allowedTools);
194
+ const disallowedTools = normalizeToolNameList(agent.disallowedTools);
195
+ const agentToolNames = mergeToolNames([
196
+ ...toolNames,
197
+ ...allowedTools,
198
+ ...agentCustomTools.map((tool) => tool.name),
199
+ ]);
200
+ const prompt = agent.prompt || agent.systemPrompt;
201
+ const agentOwner = getToolServiceOwner(agent);
202
+ const toolServerConfig = agentOwner && agentCustomTools.length > 0
203
+ ? await buildToolServerConfig(agentOwner, agentCustomTools, toolServerName)
204
+ : null;
205
+ const agentMcpServers = mergeAgentMcpServers(normalizeAgentMcpServers(agent.mcpServers), toolServerConfig);
206
+ normalizedAgents[name] = {
207
+ description: agent.description ?? "",
208
+ prompt: prompt || "",
209
+ ...(agentToolNames.length > 0 ? { tools: agentToolNames } : {}),
210
+ ...(disallowedTools.length > 0 ? { disallowedTools } : {}),
211
+ ...(agent.model ? { model: agent.model } : {}),
212
+ ...(agentMcpServers ? { mcpServers: agentMcpServers } : {}),
213
+ };
214
+ }
215
+ options.agents = normalizedAgents;
216
+ }
217
+ const customTools = extractCustomTools(this.agentConfig.tools);
218
+ if (customTools.length > 0) {
219
+ const toolServiceOwner = getToolServiceOwner(this.agentConfig);
220
+ if (toolServiceOwner) {
221
+ toolRegistryServer = await buildToolServerConfig(toolServiceOwner, customTools, toolServerName);
222
+ }
223
+ }
224
+ const allowedTools = normalizeToolNameList(this.agentConfig.allowedTools);
225
+ if (allowedTools.length > 0) {
226
+ options.allowedTools = allowedTools;
227
+ }
228
+ const disallowedTools = normalizeToolNameList(this.agentConfig.disallowedTools);
229
+ if (disallowedTools.length > 0) {
230
+ options.disallowedTools = disallowedTools;
231
+ }
232
+ const mcpServers = this.agentConfig.mcpServers;
233
+ if (mcpServers) {
234
+ options.mcpServers = {
235
+ ...(toolRegistryServer || {}),
236
+ ...mcpServers,
237
+ };
238
+ }
239
+ else if (toolRegistryServer) {
240
+ options.mcpServers = toolRegistryServer;
241
+ }
242
+ if (this.agentConfig.hooks) {
243
+ options.hooks = this.agentConfig.hooks;
244
+ }
245
+ if (this.agentConfig.resume) {
246
+ options.resume = this.agentConfig.resume;
247
+ }
248
+ const envOverrides = {};
249
+ let hasEnvOverrides = false;
250
+ if (this.agentConfig.apiKey) {
251
+ envOverrides.ANTHROPIC_API_KEY = this.agentConfig.apiKey;
252
+ hasEnvOverrides = true;
253
+ }
254
+ if (this.agentConfig.baseURL) {
255
+ envOverrides.ANTHROPIC_BASE_URL = this.agentConfig.baseURL;
256
+ hasEnvOverrides = true;
257
+ }
258
+ if (this.agentConfig.authToken) {
259
+ envOverrides.ANTHROPIC_AUTH_TOKEN = this.agentConfig.authToken;
260
+ hasEnvOverrides = true;
261
+ }
262
+ if (this.agentConfig.env && Object.keys(this.agentConfig.env).length > 0) {
263
+ Object.assign(envOverrides, this.agentConfig.env);
264
+ hasEnvOverrides = true;
265
+ }
266
+ if (hasEnvOverrides) {
267
+ options.env = {
268
+ ...process.env,
269
+ ...envOverrides,
270
+ };
271
+ }
272
+ options.stderr = (chunk) => {
273
+ this.captureStderr(chunk);
274
+ };
275
+ const settingSources = normalizeToolNameList(this.agentConfig.settingSources);
276
+ if (settingSources.length > 0) {
277
+ options.settingSources = [...settingSources];
278
+ }
279
+ else if (this.agentConfig.useProjectConfig) {
280
+ options.settingSources = ["project"];
281
+ }
282
+ const skillDir = resolveString(this.agentConfig.skillDir);
283
+ if (skillDir) {
284
+ ensureClaudeSkillPlugin(skillDir);
285
+ options.plugins = [{ type: "local", path: skillDir }];
286
+ }
287
+ const addDirs = normalizeToolNameList(this.agentConfig.addDirs);
288
+ if (addDirs.length > 0) {
289
+ options.additionalDirectories = [...addDirs];
290
+ }
291
+ const cwd = this.agentConfig.cwd ?? this.agentConfig.workingDirectory;
292
+ if (cwd) {
293
+ options.cwd = cwd;
294
+ }
295
+ if (overrides?.abortController) {
296
+ options.abortController = overrides.abortController;
297
+ }
298
+ return options;
299
+ }
300
+ abort() {
301
+ super.abort();
302
+ if (this.activeQuery) {
303
+ this.activeQuery.close();
304
+ }
305
+ }
306
+ getSessionDir() {
307
+ const envClaudConfigDir = this.agentConfig.env?.CLAUDE_CONFIG_DIR;
308
+ const baseDir = envClaudConfigDir || path.join(os.homedir(), ".claude");
309
+ return path.join(baseDir, "projects");
310
+ }
311
+ async *createEventStream(params, queryOptions, resumeSessionId) {
312
+ let endReason;
313
+ let sessionStarted = false;
314
+ try {
315
+ const finalOptions = resumeSessionId
316
+ ? { ...queryOptions, resume: resumeSessionId }
317
+ : queryOptions;
318
+ const queryRunner = query({
319
+ prompt: params.query,
320
+ options: finalOptions,
321
+ });
322
+ this.activeQuery = queryRunner;
323
+ for await (const message of queryRunner) {
324
+ if (!sessionStarted && this.isInitMessage(message)) {
325
+ const initSessionId = this.getInitSessionId(message) ?? resumeSessionId;
326
+ if (initSessionId) {
327
+ const sessionStartEvent = await this.emitSessionStart(params, undefined, initSessionId);
328
+ yield sessionStartEvent;
329
+ const userEvents = await this.emitUserItemEvents(params.query);
330
+ for (const event of userEvents) {
331
+ yield event;
332
+ }
333
+ sessionStarted = true;
334
+ }
335
+ }
336
+ const events = this.convertMessageToEvents(message);
337
+ for (const event of events) {
338
+ await this.emit(event);
339
+ yield event;
340
+ }
341
+ }
342
+ }
343
+ catch (error) {
344
+ if (this.isAbortRequested()) {
345
+ endReason = "aborted";
346
+ }
347
+ else {
348
+ const errorEvent = {
349
+ type: "error",
350
+ ...this.createBaseEvent(),
351
+ error: error,
352
+ context: { stage: "streamIteration", ...this.getStderrContext() },
353
+ };
354
+ await this.emit(errorEvent);
355
+ yield errorEvent;
356
+ endReason = "error";
357
+ }
358
+ }
359
+ if (!sessionStarted && resumeSessionId) {
360
+ const sessionStartEvent = await this.emitSessionStart(params, undefined, resumeSessionId);
361
+ yield sessionStartEvent;
362
+ const userEvents = await this.emitUserItemEvents(params.query);
363
+ for (const event of userEvents) {
364
+ yield event;
365
+ }
366
+ }
367
+ if (!endReason && this.isAbortRequested()) {
368
+ endReason = "aborted";
369
+ }
370
+ const sessionEndEvent = await this.emitSessionEnd(undefined, endReason);
371
+ yield sessionEndEvent;
372
+ }
373
+ isInitMessage(message) {
374
+ return Boolean(message &&
375
+ typeof message === "object" &&
376
+ message.type === "system" &&
377
+ message.subtype === "init");
378
+ }
379
+ getInitSessionId(message) {
380
+ const raw = message.session_id;
381
+ return typeof raw === "string" && raw.trim() ? raw : undefined;
382
+ }
383
+ convertMessageToEvents(message) {
384
+ const events = [];
385
+ const convertedMessage = this.convertToMessage(message);
386
+ if (convertedMessage) {
387
+ const normalized = convertedMessage;
388
+ const startMessage = { ...normalized, content: [] };
389
+ const itemStartEvent = {
390
+ type: "item.start",
391
+ ...this.createBaseEvent(),
392
+ message: startMessage,
393
+ };
394
+ const itemChunkEvent = {
395
+ type: "item.chunk",
396
+ ...this.createBaseEvent(),
397
+ message: normalized,
398
+ };
399
+ const itemEndEvent = {
400
+ type: "item.end",
401
+ ...this.createBaseEvent(),
402
+ message: normalized,
403
+ };
404
+ events.push(itemStartEvent, itemChunkEvent, itemEndEvent);
405
+ }
406
+ switch (message.type) {
407
+ case "system":
408
+ if (message.subtype === "init") {
409
+ if (message.session_id) {
410
+ }
411
+ }
412
+ break;
413
+ case "error":
414
+ const errorEvent = {
415
+ type: "error",
416
+ ...this.createBaseEvent(),
417
+ error: new Error(message.error?.message || String(message.error)),
418
+ context: {
419
+ stage: "agentExecution",
420
+ details: message.error,
421
+ },
422
+ };
423
+ events.push(errorEvent);
424
+ break;
425
+ default:
426
+ break;
427
+ }
428
+ return events;
429
+ }
430
+ buildAssistantMessageFromContent(content, model) {
431
+ const blocks = toContentArray(content);
432
+ const textParts = [];
433
+ const toolCalls = [];
434
+ const thinkingParts = [];
435
+ let thinkingSignature;
436
+ for (const block of blocks) {
437
+ if (typeof block === "string") {
438
+ textParts.push(block);
439
+ continue;
440
+ }
441
+ if (!block || typeof block !== "object") {
442
+ continue;
443
+ }
444
+ const record = block;
445
+ const blockType = typeof record.type === "string" ? record.type : undefined;
446
+ if (blockType === "text") {
447
+ const text = getTextValue(record);
448
+ if (text !== null) {
449
+ textParts.push(text);
450
+ }
451
+ continue;
452
+ }
453
+ if (blockType === "tool_use") {
454
+ const { id, name } = this.toolCallTracker.registerToolUse(record);
455
+ const toolUse = buildToolUseFromRecord(record, id);
456
+ toolUse.id = id;
457
+ toolUse.name = name;
458
+ toolCalls.push(toolUse);
459
+ continue;
460
+ }
461
+ if (blockType === "thinking") {
462
+ const text = getTextValue(record);
463
+ if (text !== null) {
464
+ thinkingParts.push(text);
465
+ }
466
+ if (!thinkingSignature && typeof record.signature === "string") {
467
+ thinkingSignature = record.signature;
468
+ }
469
+ }
470
+ }
471
+ if (textParts.length === 0 && toolCalls.length === 0 && thinkingParts.length === 0) {
472
+ return null;
473
+ }
474
+ return createAssistantMessage({
475
+ text: textParts.length > 0 ? textParts.join("\n") : undefined,
476
+ toolCalls: toolCalls.length > 0 ? toolCalls : undefined,
477
+ thinking: thinkingParts.length > 0
478
+ ? { content: thinkingParts.join("\n"), signature: thinkingSignature }
479
+ : undefined,
480
+ model,
481
+ });
482
+ }
483
+ buildUserOrToolResultMessageFromContent(content) {
484
+ const blocks = toContentArray(content);
485
+ const toolResults = [];
486
+ const textParts = [];
487
+ const images = [];
488
+ for (const block of blocks) {
489
+ if (typeof block === "string") {
490
+ textParts.push(block);
491
+ continue;
492
+ }
493
+ if (!block || typeof block !== "object") {
494
+ continue;
495
+ }
496
+ const record = block;
497
+ const blockType = typeof record.type === "string" ? record.type : undefined;
498
+ if (blockType === "tool_result") {
499
+ const toolResult = buildToolResultFromBlock(record);
500
+ if (toolResult) {
501
+ const { id: toolUseId } = this.toolCallTracker.resolveToolResult(record);
502
+ toolResults.push({
503
+ toolUseId,
504
+ content: toolResult.content,
505
+ isError: toolResult.isError,
506
+ });
507
+ }
508
+ continue;
509
+ }
510
+ if (blockType === "text") {
511
+ const text = getTextValue(record);
512
+ if (text !== null) {
513
+ textParts.push(text);
514
+ }
515
+ continue;
516
+ }
517
+ if (blockType === "image") {
518
+ const url = getImageUrl(record);
519
+ if (url) {
520
+ images.push(url);
521
+ }
522
+ }
523
+ }
524
+ if (toolResults.length > 0) {
525
+ return createToolCallResultMessage(toolResults.map((result) => ({
526
+ tool_use_id: result.toolUseId,
527
+ content: result.content,
528
+ isError: result.isError,
529
+ })));
530
+ }
531
+ if (textParts.length === 0 && images.length === 0) {
532
+ return null;
533
+ }
534
+ if (images.length === 0) {
535
+ return createUserMessage(textParts.join("\n"));
536
+ }
537
+ return createUserMessage({ text: textParts.join("\n"), images });
538
+ }
539
+ resetStderrBuffer() {
540
+ this.stderrBuffer = "";
541
+ }
542
+ captureStderr(chunk) {
543
+ if (!chunk) {
544
+ return;
545
+ }
546
+ this.stderrBuffer += chunk;
547
+ if (this.stderrBuffer.length > this.stderrBufferLimit) {
548
+ this.stderrBuffer = this.stderrBuffer.slice(-this.stderrBufferLimit);
549
+ }
550
+ }
551
+ getStderrContext() {
552
+ const stderr = this.stderrBuffer.trim();
553
+ if (!stderr) {
554
+ return {};
555
+ }
556
+ return { stderr };
557
+ }
558
+ getModel(messageModel) {
559
+ return messageModel
560
+ ?? this.agentConfig.model
561
+ ?? "claude-sonnet-4-5-20250929";
562
+ }
563
+ convertToMessage(message) {
564
+ let msg = null;
565
+ switch (message.type) {
566
+ case "system":
567
+ case "usage":
568
+ case "result":
569
+ case "error":
570
+ break;
571
+ case "assistant": {
572
+ const content = message.message?.content ?? message.content;
573
+ msg = this.buildAssistantMessageFromContent(content, this.getModel(message.model));
574
+ break;
575
+ }
576
+ case "user": {
577
+ const content = message.message?.content ?? message.content;
578
+ msg = this.buildUserOrToolResultMessageFromContent(content);
579
+ break;
580
+ }
581
+ case "message": {
582
+ const role = message.role ?? message.message?.role;
583
+ const content = message.content ?? message.message?.content;
584
+ if (role === "assistant") {
585
+ msg = this.buildAssistantMessageFromContent(content, this.getModel(message.model));
586
+ }
587
+ else if (role === "user") {
588
+ msg = this.buildUserOrToolResultMessageFromContent(content);
589
+ }
590
+ break;
591
+ }
592
+ case "text":
593
+ if (message.content) {
594
+ msg = createAssistantMessage({ text: String(message.content), model: this.getModel(message.model) });
595
+ }
596
+ break;
597
+ case "thinking":
598
+ if (message.content) {
599
+ msg = createAssistantMessage({
600
+ thinking: {
601
+ content: String(message.content),
602
+ signature: message.signature,
603
+ },
604
+ model: this.getModel(message.model),
605
+ });
606
+ }
607
+ break;
608
+ case "tool_use":
609
+ const toolUseRecord = message;
610
+ const { id: toolUseId, name: toolUseName } = this.toolCallTracker.registerToolUse(toolUseRecord);
611
+ const toolUse = buildToolUseFromRecord(toolUseRecord, toolUseId);
612
+ toolUse.id = toolUseId;
613
+ toolUse.name = toolUseName;
614
+ msg = createAssistantMessage({ toolCalls: [toolUse], model: this.getModel(message.model) });
615
+ break;
616
+ case "tool_result":
617
+ const toolResultRecord = message;
618
+ const { id: toolResultId } = this.toolCallTracker.resolveToolResult(toolResultRecord);
619
+ let resultContent = "";
620
+ if (typeof message.content === "string" && message.content.length > 0) {
621
+ resultContent = message.content;
622
+ }
623
+ else if (message.content !== undefined && message.content !== null) {
624
+ resultContent = stringifyContent(message.content);
625
+ }
626
+ if (!resultContent && message.result !== undefined && message.result !== null) {
627
+ resultContent = stringifyContent(message.result);
628
+ }
629
+ msg = createToolCallResultMessage([
630
+ {
631
+ tool_use_id: toolResultId,
632
+ content: resultContent,
633
+ isError: message.is_error || false,
634
+ },
635
+ ]);
636
+ break;
637
+ default:
638
+ if (message.content !== undefined && message.content !== null) {
639
+ msg = createAssistantMessage({
640
+ text: stringifyContent(message.content),
641
+ model: this.getModel(message.model),
642
+ });
643
+ }
644
+ else {
645
+ msg = createAssistantMessage({
646
+ text: stringifyContent(message),
647
+ model: this.getModel(message.model),
648
+ });
649
+ }
650
+ break;
651
+ }
652
+ const parentToolUseId = this.getParentToolUseId(message);
653
+ if (msg && parentToolUseId) {
654
+ msg = { ...msg, parent_tool_use_id: parentToolUseId };
655
+ }
656
+ return msg ? normalizeMessage(this.applyParentToolUseId(msg)) : null;
657
+ }
658
+ getParentToolUseId(message) {
659
+ const topLevel = typeof message.parent_tool_use_id === "string"
660
+ ? message.parent_tool_use_id
661
+ : typeof message.parentToolUseId === "string"
662
+ ? message.parentToolUseId
663
+ : undefined;
664
+ if (topLevel) {
665
+ return topLevel;
666
+ }
667
+ const nested = message.message;
668
+ if (!nested || typeof nested !== "object") {
669
+ return undefined;
670
+ }
671
+ const nestedRecord = nested;
672
+ const nestedDirect = typeof nestedRecord.parent_tool_use_id === "string"
673
+ ? nestedRecord.parent_tool_use_id
674
+ : typeof nestedRecord.parentToolUseId === "string"
675
+ ? nestedRecord.parentToolUseId
676
+ : undefined;
677
+ if (nestedDirect) {
678
+ return nestedDirect;
679
+ }
680
+ const meta = nestedRecord.metadata;
681
+ if (meta && typeof meta === "object") {
682
+ const metaRecord = meta;
683
+ const metaValue = typeof metaRecord.parent_tool_use_id === "string"
684
+ ? metaRecord.parent_tool_use_id
685
+ : typeof metaRecord.parentToolUseId === "string"
686
+ ? metaRecord.parentToolUseId
687
+ : undefined;
688
+ if (metaValue) {
689
+ return metaValue;
690
+ }
691
+ }
692
+ const messageMeta = message.metadata;
693
+ if (messageMeta) {
694
+ const metaValue = typeof messageMeta.parent_tool_use_id === "string"
695
+ ? messageMeta.parent_tool_use_id
696
+ : typeof messageMeta.parentToolUseId === "string"
697
+ ? messageMeta.parentToolUseId
698
+ : undefined;
699
+ if (metaValue) {
700
+ return metaValue;
701
+ }
702
+ }
703
+ return undefined;
704
+ }
705
+ getAgentConfig() {
706
+ return { ...this.agentConfig };
707
+ }
708
+ updateAgentConfig(config) {
709
+ this.agentConfig = { ...this.agentConfig, ...config };
710
+ }
711
+ setAllowedTools(tools) {
712
+ this.agentConfig.allowedTools = tools;
713
+ }
714
+ setPermissionMode(mode) {
715
+ this.agentConfig.permissionMode = mode;
716
+ }
717
+ addMcpServer(name, config) {
718
+ if (!this.agentConfig.mcpServers) {
719
+ this.agentConfig.mcpServers = {};
720
+ }
721
+ this.agentConfig.mcpServers[name] = config;
722
+ }
723
+ addAgent(name, config) {
724
+ if (!this.agentConfig.agents) {
725
+ this.agentConfig.agents = {};
726
+ }
727
+ this.agentConfig.agents[name] = config;
728
+ }
729
+ }
730
+ function splitAgentTools(tools) {
731
+ const customTools = [];
732
+ const toolNames = [];
733
+ const addTool = (tool) => {
734
+ if (isRegisteredTool(tool)) {
735
+ customTools.push(tool);
736
+ toolNames.push(tool.name);
737
+ return;
738
+ }
739
+ if (typeof tool === "string" && tool.length > 0) {
740
+ toolNames.push(tool);
741
+ return;
742
+ }
743
+ throw new Error("Agent tools must be RegisteredTool instances or tool name strings");
744
+ };
745
+ if (tools === undefined || tools === null) {
746
+ return { customTools, toolNames };
747
+ }
748
+ if (Array.isArray(tools)) {
749
+ for (const tool of tools) {
750
+ addTool(tool);
751
+ }
752
+ return { customTools, toolNames };
753
+ }
754
+ addTool(tools);
755
+ return { customTools, toolNames };
756
+ }
757
+ function normalizeToolNameList(value) {
758
+ if (!value) {
759
+ return [];
760
+ }
761
+ if (Array.isArray(value)) {
762
+ return value.filter((item) => typeof item === "string" && item.length > 0);
763
+ }
764
+ if (typeof value === "string" && value.length > 0) {
765
+ return [value];
766
+ }
767
+ return [];
768
+ }
769
+ function mergeToolNames(toolNames) {
770
+ return Array.from(new Set(toolNames));
771
+ }
772
+ function normalizeAgentMcpServers(value) {
773
+ if (!value) {
774
+ return undefined;
775
+ }
776
+ if (Array.isArray(value)) {
777
+ return value;
778
+ }
779
+ return [value];
780
+ }
781
+ function mergeAgentMcpServers(existing, toolServerConfig) {
782
+ if (!toolServerConfig) {
783
+ return existing;
784
+ }
785
+ if (existing && existing.length > 0) {
786
+ return [toolServerConfig, ...existing];
787
+ }
788
+ return [toolServerConfig];
789
+ }
790
+ async function buildToolServerConfig(owner, tools, serverName) {
791
+ if (tools.length === 0) {
792
+ return null;
793
+ }
794
+ const command = await getAgentToolServiceCommand(owner, tools, {
795
+ name: serverName,
796
+ version: "1.0.0",
797
+ });
798
+ return {
799
+ [serverName]: {
800
+ type: "stdio",
801
+ command: command.command,
802
+ args: command.args,
803
+ ...(command.env ? { env: command.env } : {}),
804
+ },
805
+ };
806
+ }
807
+ function getToolServiceOwner(value) {
808
+ const owner = resolveToolServiceOwner(value);
809
+ if (owner) {
810
+ return owner;
811
+ }
812
+ return isRecord(value) ? value : null;
813
+ }
814
+ function isRecord(value) {
815
+ return typeof value === "object" && value !== null && !Array.isArray(value);
816
+ }
817
+ function resolveString(value) {
818
+ return typeof value === "string" && value.length > 0 ? value : undefined;
819
+ }
820
+ function ensureClaudeSkillPlugin(skillDir) {
821
+ const pluginContent = {
822
+ name: "load-custom-skill-plugin",
823
+ description: "plugin to load custom skills",
824
+ version: "1.0.0",
825
+ skills: "./",
826
+ };
827
+ fs.mkdirSync(path.join(skillDir, ".claude-plugin"), { recursive: true });
828
+ const pluginPath = path.join(skillDir, ".claude-plugin", "plugin.json");
829
+ const serialized = `${JSON.stringify(pluginContent, null, 2)}\n`;
830
+ let shouldWrite = true;
831
+ if (fs.existsSync(pluginPath)) {
832
+ try {
833
+ const existing = fs.readFileSync(pluginPath, "utf-8");
834
+ if (existing === serialized) {
835
+ shouldWrite = false;
836
+ }
837
+ }
838
+ catch {
839
+ shouldWrite = true;
840
+ }
841
+ }
842
+ if (shouldWrite) {
843
+ fs.writeFileSync(pluginPath, serialized, "utf-8");
844
+ }
845
+ }
846
+ //# sourceMappingURL=claude.js.map