wave-agent-sdk 1.0.5 → 1.0.7

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 (202) hide show
  1. package/dist/agent.d.ts +34 -1
  2. package/dist/agent.js +49 -4
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +1 -1
  5. package/dist/managers/aiManager.d.ts +36 -0
  6. package/dist/managers/aiManager.js +240 -11
  7. package/dist/managers/messageManager.d.ts +2 -4
  8. package/dist/managers/messageManager.js +14 -7
  9. package/dist/managers/slashCommandManager.js +28 -0
  10. package/dist/managers/subagentManager.d.ts +0 -2
  11. package/dist/services/aiService.d.ts +2 -3
  12. package/dist/services/aiService.js +4 -18
  13. package/dist/services/configurationService.d.ts +7 -0
  14. package/dist/services/configurationService.js +10 -0
  15. package/dist/telemetry/instrumentation.d.ts +1 -1
  16. package/dist/telemetry/instrumentation.js +57 -28
  17. package/dist/tools/bashTool.js +16 -6
  18. package/dist/tools/grepTool.js +11 -3
  19. package/dist/types/core.d.ts +1 -34
  20. package/dist/types/index.d.ts +4 -0
  21. package/dist/types/messaging.d.ts +2 -0
  22. package/dist/utils/cacheControlUtils.d.ts +5 -27
  23. package/dist/utils/cacheControlUtils.js +12 -73
  24. package/dist/utils/containerSetup.js +0 -3
  25. package/dist/utils/messageOperations.d.ts +2 -1
  26. package/dist/utils/messageOperations.js +2 -1
  27. package/dist/utils/notificationXml.js +5 -0
  28. package/dist/utils/ripgrep.d.ts +4 -4
  29. package/dist/utils/ripgrep.js +4 -27
  30. package/package.json +20 -8
  31. package/bin/rg +0 -79
  32. package/dist/managers/forkedAgentManager.d.ts +0 -50
  33. package/dist/managers/forkedAgentManager.js +0 -130
  34. package/scripts/install_ripgrep.js +0 -111
  35. package/scripts/postinstall.js +0 -38
  36. package/src/agent.ts +0 -1271
  37. package/src/constants/subagents.ts +0 -4
  38. package/src/constants/toolLimits.ts +0 -15
  39. package/src/constants/tools.ts +0 -24
  40. package/src/core/plugin.ts +0 -237
  41. package/src/core/session.ts +0 -9
  42. package/src/index.ts +0 -38
  43. package/src/managers/MemoryRuleManager.ts +0 -198
  44. package/src/managers/aiManager.ts +0 -2429
  45. package/src/managers/backgroundTaskManager.ts +0 -480
  46. package/src/managers/bangManager.ts +0 -119
  47. package/src/managers/cronManager.ts +0 -401
  48. package/src/managers/foregroundTaskManager.ts +0 -30
  49. package/src/managers/forkedAgentManager.ts +0 -216
  50. package/src/managers/hookManager.ts +0 -1089
  51. package/src/managers/liveConfigManager.ts +0 -445
  52. package/src/managers/lspManager.ts +0 -470
  53. package/src/managers/mcpManager.ts +0 -1010
  54. package/src/managers/messageManager.ts +0 -1184
  55. package/src/managers/messageQueue.ts +0 -157
  56. package/src/managers/permissionManager.ts +0 -1140
  57. package/src/managers/planManager.ts +0 -112
  58. package/src/managers/pluginManager.ts +0 -330
  59. package/src/managers/pluginScopeManager.ts +0 -124
  60. package/src/managers/reversionManager.ts +0 -178
  61. package/src/managers/skillManager.ts +0 -578
  62. package/src/managers/slashCommandManager.ts +0 -564
  63. package/src/managers/subagentManager.ts +0 -915
  64. package/src/managers/toolManager.ts +0 -489
  65. package/src/managers/workflowManager.ts +0 -493
  66. package/src/prompts/autoMemory.ts +0 -33
  67. package/src/prompts/autoMemoryExtraction.ts +0 -146
  68. package/src/prompts/index.ts +0 -506
  69. package/src/prompts/planModeReminders.ts +0 -126
  70. package/src/services/GitService.ts +0 -131
  71. package/src/services/MarketplaceService.ts +0 -1052
  72. package/src/services/MemoryRuleService.ts +0 -71
  73. package/src/services/aiService.ts +0 -919
  74. package/src/services/authService.ts +0 -565
  75. package/src/services/autoMemoryService.ts +0 -280
  76. package/src/services/configurationService.ts +0 -1520
  77. package/src/services/fileWatcher.ts +0 -319
  78. package/src/services/hook.ts +0 -348
  79. package/src/services/initializationService.ts +0 -357
  80. package/src/services/interactionService.ts +0 -229
  81. package/src/services/jsonlHandler.ts +0 -295
  82. package/src/services/memory.ts +0 -234
  83. package/src/services/pluginLoader.ts +0 -252
  84. package/src/services/remoteSettingsService.ts +0 -366
  85. package/src/services/reversionService.ts +0 -122
  86. package/src/services/session.ts +0 -917
  87. package/src/services/taskManager.ts +0 -321
  88. package/src/telemetry/events.ts +0 -65
  89. package/src/telemetry/instrumentation.ts +0 -499
  90. package/src/telemetry/sessionTracing.ts +0 -348
  91. package/src/tools/agentTool.ts +0 -322
  92. package/src/tools/askUserQuestion.ts +0 -160
  93. package/src/tools/bashTool.ts +0 -621
  94. package/src/tools/buildTool.ts +0 -61
  95. package/src/tools/cronCreateTool.ts +0 -161
  96. package/src/tools/cronDeleteTool.ts +0 -51
  97. package/src/tools/cronListTool.ts +0 -47
  98. package/src/tools/editTool.ts +0 -313
  99. package/src/tools/enterPlanMode.ts +0 -124
  100. package/src/tools/enterWorktreeTool.ts +0 -190
  101. package/src/tools/exitPlanMode.ts +0 -139
  102. package/src/tools/exitWorktreeTool.ts +0 -236
  103. package/src/tools/globTool.ts +0 -167
  104. package/src/tools/grepTool.ts +0 -399
  105. package/src/tools/lspTool.ts +0 -883
  106. package/src/tools/readTool.ts +0 -426
  107. package/src/tools/skillTool.ts +0 -248
  108. package/src/tools/taskManagementTools.ts +0 -574
  109. package/src/tools/taskStopTool.ts +0 -78
  110. package/src/tools/types.ts +0 -137
  111. package/src/tools/webFetchTool.ts +0 -373
  112. package/src/tools/workflowTool.ts +0 -205
  113. package/src/tools/writeTool.ts +0 -267
  114. package/src/types/agent.ts +0 -128
  115. package/src/types/auth.ts +0 -19
  116. package/src/types/commands.ts +0 -30
  117. package/src/types/config.ts +0 -43
  118. package/src/types/configuration.ts +0 -168
  119. package/src/types/core.ts +0 -105
  120. package/src/types/cron.ts +0 -13
  121. package/src/types/environment.ts +0 -106
  122. package/src/types/fileSearch.ts +0 -4
  123. package/src/types/history.ts +0 -7
  124. package/src/types/hooks.ts +0 -256
  125. package/src/types/index.ts +0 -41
  126. package/src/types/lsp.ts +0 -98
  127. package/src/types/marketplace.ts +0 -71
  128. package/src/types/mcp.ts +0 -43
  129. package/src/types/memoryRule.ts +0 -31
  130. package/src/types/messaging.ts +0 -114
  131. package/src/types/permissions.ts +0 -80
  132. package/src/types/plugins.ts +0 -39
  133. package/src/types/processes.ts +0 -99
  134. package/src/types/reversion.ts +0 -29
  135. package/src/types/session.ts +0 -12
  136. package/src/types/skills.ts +0 -108
  137. package/src/types/tasks.ts +0 -13
  138. package/src/types/telemetry.ts +0 -98
  139. package/src/types/tools.ts +0 -44
  140. package/src/types/workflow.ts +0 -6
  141. package/src/utils/abortUtils.ts +0 -118
  142. package/src/utils/atomicWrite.ts +0 -61
  143. package/src/utils/bashParser.ts +0 -899
  144. package/src/utils/cacheControlUtils.ts +0 -426
  145. package/src/utils/commandArgumentParser.ts +0 -161
  146. package/src/utils/commandPathResolver.ts +0 -88
  147. package/src/utils/configPaths.ts +0 -220
  148. package/src/utils/configValidator.ts +0 -100
  149. package/src/utils/constants.ts +0 -39
  150. package/src/utils/container.ts +0 -92
  151. package/src/utils/containerSetup.ts +0 -371
  152. package/src/utils/convertMessagesForAPI.ts +0 -326
  153. package/src/utils/cronTasks.ts +0 -128
  154. package/src/utils/cronTasksLock.ts +0 -182
  155. package/src/utils/cronToHuman.ts +0 -99
  156. package/src/utils/customCommands.ts +0 -95
  157. package/src/utils/editUtils.ts +0 -20
  158. package/src/utils/fileFormat.ts +0 -40
  159. package/src/utils/fileSearch.ts +0 -151
  160. package/src/utils/fileUtils.ts +0 -223
  161. package/src/utils/gitUtils.ts +0 -315
  162. package/src/utils/globalLogger.ts +0 -128
  163. package/src/utils/groupMessagesByApiRound.ts +0 -121
  164. package/src/utils/hookMatcher.ts +0 -176
  165. package/src/utils/markdownParser.ts +0 -317
  166. package/src/utils/mcpUtils.ts +0 -138
  167. package/src/utils/messageOperations.ts +0 -659
  168. package/src/utils/modelCapabilities.ts +0 -30
  169. package/src/utils/nameGenerator.ts +0 -99
  170. package/src/utils/notificationXml.ts +0 -57
  171. package/src/utils/openaiClient.ts +0 -251
  172. package/src/utils/parseCronExpression.ts +0 -78
  173. package/src/utils/path.ts +0 -72
  174. package/src/utils/pathEncoder.ts +0 -400
  175. package/src/utils/pathSafety.ts +0 -40
  176. package/src/utils/promptHistory.ts +0 -168
  177. package/src/utils/ripgrep.ts +0 -35
  178. package/src/utils/shellResolver.ts +0 -190
  179. package/src/utils/skillParser.ts +0 -246
  180. package/src/utils/stringUtils.ts +0 -156
  181. package/src/utils/subagentParser.ts +0 -279
  182. package/src/utils/taskReminder.ts +0 -96
  183. package/src/utils/tokenCalculation.ts +0 -43
  184. package/src/utils/tokenEstimate.ts +0 -34
  185. package/src/utils/toolResultStorage.ts +0 -117
  186. package/src/utils/worktreeSession.ts +0 -26
  187. package/src/utils/worktreeUtils.ts +0 -786
  188. package/src/workflow/budgetTracker.ts +0 -34
  189. package/src/workflow/concurrencyLimiter.ts +0 -47
  190. package/src/workflow/journal.ts +0 -95
  191. package/src/workflow/progressReporter.ts +0 -141
  192. package/src/workflow/runState.ts +0 -65
  193. package/src/workflow/scriptRuntime.ts +0 -274
  194. package/src/workflow/structuredOutput.ts +0 -123
  195. package/src/workflow/types.ts +0 -101
  196. package/src/workflow/workflowApis.ts +0 -410
  197. package/vendor/ripgrep/linux-aarch64/rg +0 -0
  198. package/vendor/ripgrep/linux-x86_64/rg +0 -0
  199. package/vendor/ripgrep/macos-aarch64/rg +0 -0
  200. package/vendor/ripgrep/macos-x86_64/rg +0 -0
  201. package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
  202. package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
@@ -1,321 +0,0 @@
1
- import { promises as fs } from "fs";
2
- import { join } from "path";
3
- import { homedir } from "os";
4
- import { EventEmitter } from "events";
5
- import { Task } from "../types/tasks.js";
6
- import { logger } from "../utils/globalLogger.js";
7
- import { Container } from "../utils/container.js";
8
- import type { MessageManager } from "../managers/messageManager.js";
9
- import type { ConfigurationService } from "./configurationService.js";
10
-
11
- function byIdAsc(a: Task, b: Task) {
12
- const aNum = parseInt(a.id, 10);
13
- const bNum = parseInt(b.id, 10);
14
- if (!isNaN(aNum) && !isNaN(bNum)) return aNum - bNum;
15
- return a.id.localeCompare(b.id);
16
- }
17
-
18
- export class TaskManager extends EventEmitter {
19
- private readonly baseDir: string;
20
- private taskListId: string;
21
-
22
- constructor(
23
- private container: Container,
24
- taskListId: string,
25
- ) {
26
- super();
27
- this.taskListId = taskListId;
28
- this.baseDir = join(homedir(), ".wave", "tasks");
29
- }
30
-
31
- public getTaskListId(): string {
32
- return this.taskListId;
33
- }
34
-
35
- public setTaskListId(taskListId: string): void {
36
- this.taskListId = taskListId;
37
- }
38
-
39
- /**
40
- * Syncs the task list ID with the current session's root session ID.
41
- * This is typically called when the session is cleared or compacted.
42
- */
43
- public async syncWithSession(): Promise<void> {
44
- const messageManager = this.container.get<MessageManager>("MessageManager");
45
- if (!messageManager) return;
46
-
47
- const rootSessionId = messageManager.getRootSessionId();
48
- // Read the per-session snapshot (not process.env) so multiple sessions in
49
- // one `wave --stdio` process don't cross-pollute this flag.
50
- const envSnap =
51
- this.container
52
- .get<ConfigurationService>("ConfigurationService")
53
- ?.getEnvSnapshot() ?? {};
54
- const pinnedTaskListId =
55
- envSnap.WAVE_TASK_LIST_ID ?? process.env.WAVE_TASK_LIST_ID;
56
- if (this.taskListId !== rootSessionId && !pinnedTaskListId) {
57
- this.setTaskListId(rootSessionId);
58
- await this.refreshTasks();
59
- }
60
- }
61
-
62
- private getSessionDir(): string {
63
- return join(this.baseDir, this.taskListId);
64
- }
65
-
66
- public getTaskPath(taskId: string): string {
67
- return join(this.getSessionDir(), `${taskId}.json`);
68
- }
69
-
70
- private getLockPath(): string {
71
- return join(this.getSessionDir(), `.lock`);
72
- }
73
-
74
- async ensureSessionDir(): Promise<void> {
75
- await fs.mkdir(this.getSessionDir(), { recursive: true });
76
- }
77
-
78
- private async withLock<T>(operation: () => Promise<T>): Promise<T> {
79
- const lockPath = this.getLockPath();
80
- let lockHandle;
81
- const maxRetries = 100;
82
- const retryDelay = process.env.NODE_ENV === "test" ? 1 : 100;
83
- const staleThreshold = 10000;
84
-
85
- await this.ensureSessionDir();
86
-
87
- for (let i = 0; i < maxRetries; i++) {
88
- try {
89
- lockHandle = await fs.open(lockPath, "wx");
90
- break;
91
- } catch (error) {
92
- const code = (error as NodeJS.ErrnoException).code;
93
-
94
- // Only EEXIST (lock held) and EPERM (Windows pending-delete window)
95
- // are transient lock-contention errors. EACCES/ENOENT are real failures
96
- // and must not be retried as lock competition.
97
- if (code !== "EEXIST" && code !== "EPERM") {
98
- throw error;
99
- }
100
-
101
- if (i === maxRetries - 1) {
102
- throw new Error(
103
- `Could not acquire lock for task list ${this.taskListId} after ${maxRetries} retries`,
104
- );
105
- }
106
-
107
- // Stale recovery: if the lock holder crashed without releasing, the
108
- // lock file remains forever. Check mtime — if older than the threshold,
109
- // remove it. Aligns with proper-lockfile's default 10s stale detection.
110
- // The lock file is empty (no PID content), so mtime is the only signal.
111
- if (
112
- code === "EEXIST" &&
113
- (await this.isLockStale(lockPath, staleThreshold))
114
- ) {
115
- logger.warn(
116
- `TaskManager: removing stale lock for task list ${this.taskListId}`,
117
- );
118
- try {
119
- await fs.unlink(lockPath);
120
- } catch {
121
- // Another waiter may have already removed it — retry anyway
122
- }
123
- continue;
124
- }
125
-
126
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
127
- }
128
- }
129
-
130
- try {
131
- return await operation();
132
- } finally {
133
- if (lockHandle) {
134
- await lockHandle.close();
135
- }
136
- try {
137
- await fs.unlink(lockPath);
138
- } catch (error) {
139
- logger.error(
140
- `Failed to release lock for task list ${this.taskListId}:`,
141
- error,
142
- );
143
- }
144
- }
145
- }
146
-
147
- private async isLockStale(
148
- lockPath: string,
149
- threshold: number,
150
- ): Promise<boolean> {
151
- try {
152
- const stats = await fs.stat(lockPath);
153
- return Date.now() - stats.mtimeMs > threshold;
154
- } catch {
155
- // Lock was removed between our EEXIST and stat — not stale, just retry
156
- return false;
157
- }
158
- }
159
-
160
- private validateTask(task: Task): void {
161
- if (!task.id || typeof task.id !== "string")
162
- throw new Error("Invalid task ID");
163
- if (!task.subject || typeof task.subject !== "string")
164
- throw new Error("Invalid task subject");
165
- if (!task.description || typeof task.description !== "string")
166
- throw new Error("Invalid task description");
167
- if (
168
- !task.status ||
169
- !["pending", "in_progress", "completed", "deleted"].includes(task.status)
170
- ) {
171
- throw new Error(`Invalid task status: ${task.status}`);
172
- }
173
- }
174
-
175
- async createTask(task: Omit<Task, "id">): Promise<string> {
176
- return await this.withLock(async () => {
177
- const taskId = await this.getNextTaskId();
178
- const fullTask: Task = { ...task, id: taskId };
179
- this.validateTask(fullTask);
180
- const taskPath = this.getTaskPath(taskId);
181
- const content = JSON.stringify(fullTask, null, 2);
182
- await fs.writeFile(taskPath, content, "utf8");
183
- this.emit("tasksChange", this.taskListId);
184
- logger.debug(`Task ${taskId} created in task list ${this.taskListId}`);
185
- return taskId;
186
- });
187
- }
188
-
189
- async getTask(taskId: string): Promise<Task | null> {
190
- const taskPath = this.getTaskPath(taskId);
191
- try {
192
- const content = await fs.readFile(taskPath, "utf8");
193
- try {
194
- return JSON.parse(content.trim()) as Task;
195
- } catch (parseError) {
196
- logger.error(`Failed to parse task file ${taskPath}:`, parseError);
197
- logger.error(`Corrupted content: ${content}`);
198
- throw parseError;
199
- }
200
- } catch (error) {
201
- if ((error as NodeJS.ErrnoException).code === "ENOENT") {
202
- return null;
203
- }
204
- throw error;
205
- }
206
- }
207
-
208
- async updateTask(task: Task): Promise<void> {
209
- this.validateTask(task);
210
- await this.withLock(async () => {
211
- const taskPath = this.getTaskPath(task.id);
212
- const content = JSON.stringify(task, null, 2);
213
- await fs.writeFile(taskPath, content, "utf8");
214
- this.emit("tasksChange", this.taskListId);
215
- logger.debug(`Task ${task.id} updated in task list ${this.taskListId}`);
216
- });
217
- }
218
-
219
- async deleteTask(taskId: string): Promise<void> {
220
- await this.withLock(async () => {
221
- const taskPath = this.getTaskPath(taskId);
222
- try {
223
- await fs.unlink(taskPath);
224
- this.emit("tasksChange", this.taskListId);
225
- logger.debug(
226
- `Task ${taskId} deleted from task list ${this.taskListId}`,
227
- );
228
- } catch (error) {
229
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
230
- throw error;
231
- }
232
- }
233
- });
234
- }
235
-
236
- async cleanupOldTaskLists(days: number = 30): Promise<void> {
237
- const threshold = Date.now() - days * 24 * 60 * 60 * 1000;
238
- try {
239
- const dirs = await fs.readdir(this.baseDir);
240
- for (const dir of dirs) {
241
- if (dir === this.taskListId) continue;
242
-
243
- const dirPath = join(this.baseDir, dir);
244
- const stats = await fs.stat(dirPath);
245
- if (!stats.isDirectory()) continue;
246
-
247
- // Check mtime of the directory and its contents
248
- let latestMtime = stats.mtimeMs;
249
- const files = await fs.readdir(dirPath);
250
- for (const file of files) {
251
- const filePath = join(dirPath, file);
252
- const fileStats = await fs.stat(filePath);
253
- if (fileStats.mtimeMs > latestMtime) {
254
- latestMtime = fileStats.mtimeMs;
255
- }
256
- }
257
-
258
- if (latestMtime < threshold) {
259
- logger.info(`Cleaning up old task list directory: ${dirPath}`);
260
- await fs.rm(dirPath, { recursive: true, force: true });
261
- }
262
- }
263
- } catch (error) {
264
- if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
265
- logger.error("Failed to cleanup old task lists:", error);
266
- }
267
- }
268
- }
269
-
270
- async listTasks(): Promise<Task[]> {
271
- const sessionDir = this.getSessionDir();
272
- try {
273
- const files = await fs.readdir(sessionDir);
274
- const taskFiles = files.filter((f) => f.endsWith(".json"));
275
-
276
- const tasks = await Promise.all(
277
- taskFiles.map(async (file) => {
278
- const taskPath = join(sessionDir, file);
279
- try {
280
- const content = await fs.readFile(taskPath, "utf8");
281
- return JSON.parse(content.trim()) as Task;
282
- } catch (error) {
283
- logger.error(
284
- `Failed to read or parse task file ${taskPath}:`,
285
- error,
286
- );
287
- return null;
288
- }
289
- }),
290
- );
291
-
292
- return tasks.filter((t): t is Task => t !== null).sort(byIdAsc);
293
- } catch (error) {
294
- if ((error as NodeJS.ErrnoException).code === "ENOENT") {
295
- return [];
296
- }
297
- throw error;
298
- }
299
- }
300
-
301
- async getNextTaskId(): Promise<string> {
302
- const tasks = await this.listTasks();
303
- if (tasks.length === 0) {
304
- return "1";
305
- }
306
- const ids = tasks.map((t) => parseInt(t.id, 10)).filter((id) => !isNaN(id));
307
-
308
- if (ids.length === 0) {
309
- return (tasks.length + 1).toString();
310
- }
311
-
312
- return (Math.max(...ids) + 1).toString();
313
- }
314
-
315
- /**
316
- * Refreshes the task list by re-reading tasks from disk and emitting a change event.
317
- */
318
- public async refreshTasks(): Promise<void> {
319
- this.emit("tasksChange", this.taskListId);
320
- }
321
- }
@@ -1,65 +0,0 @@
1
- /**
2
- * OpenTelemetry Event Logging
3
- *
4
- * Provides the `logOTelEvent` API for structured session lifecycle events
5
- * with PII gates.
6
- */
7
-
8
- import type { OTelEventName } from "../types/telemetry.js";
9
- import {
10
- isInitialized,
11
- getCurrentConfig,
12
- getTelemetryAttributes,
13
- } from "./instrumentation.js";
14
-
15
- interface OTelLogger {
16
- emit: (logRecord: {
17
- body?: unknown;
18
- attributes?: Record<string, unknown>;
19
- }) => void;
20
- }
21
-
22
- let cachedLogger: OTelLogger | undefined;
23
-
24
- async function getOTelLogger(): Promise<OTelLogger | undefined> {
25
- if (cachedLogger) return cachedLogger;
26
- try {
27
- const { logs } = await import("@opentelemetry/api-logs");
28
- cachedLogger = logs.getLogger("wave") as OTelLogger;
29
- return cachedLogger;
30
- } catch {
31
- return undefined;
32
- }
33
- }
34
-
35
- /**
36
- * Logs a structured event via the OTEL logs API. Respects PII gates.
37
- */
38
- export async function logOTelEvent(
39
- eventName: OTelEventName,
40
- metadata: Record<string, string | undefined>,
41
- ): Promise<void> {
42
- if (!isInitialized()) return;
43
-
44
- const log = await getOTelLogger();
45
- if (!log) return;
46
-
47
- // PII gate: strip prompt text if logUserPrompts is false
48
- const attributes: Record<string, string> = {};
49
- const config = getCurrentConfig();
50
-
51
- for (const [key, value] of Object.entries(metadata)) {
52
- if (value === undefined) continue;
53
- if (key === "prompt" && !config?.logUserPrompts) continue;
54
- attributes[key] = value;
55
- }
56
-
57
- log.emit({
58
- body: eventName,
59
- attributes: {
60
- "event.name": eventName,
61
- ...getTelemetryAttributes(),
62
- ...attributes,
63
- },
64
- });
65
- }