wave-agent-sdk 1.0.4 → 1.0.6
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.
- package/dist/agent.d.ts +23 -1
- package/dist/agent.js +34 -4
- package/dist/managers/aiManager.d.ts +36 -0
- package/dist/managers/aiManager.js +240 -8
- package/dist/managers/messageManager.d.ts +1 -3
- package/dist/managers/messageManager.js +19 -9
- package/dist/managers/slashCommandManager.js +28 -0
- package/dist/managers/subagentManager.d.ts +0 -2
- package/dist/services/session.js +2 -9
- package/dist/telemetry/instrumentation.d.ts +1 -1
- package/dist/telemetry/instrumentation.js +57 -28
- package/dist/tools/bashTool.js +16 -6
- package/dist/tools/grepTool.js +11 -3
- package/dist/types/index.d.ts +3 -0
- package/dist/types/messaging.d.ts +2 -0
- package/dist/utils/containerSetup.js +0 -3
- package/dist/utils/messageOperations.d.ts +10 -1
- package/dist/utils/messageOperations.js +19 -1
- package/dist/utils/notificationXml.js +5 -0
- package/dist/utils/ripgrep.d.ts +4 -4
- package/dist/utils/ripgrep.js +4 -27
- package/package.json +20 -8
- package/bin/rg +0 -79
- package/dist/managers/forkedAgentManager.d.ts +0 -50
- package/dist/managers/forkedAgentManager.js +0 -130
- package/scripts/install_ripgrep.js +0 -111
- package/scripts/postinstall.js +0 -38
- package/src/agent.ts +0 -1271
- package/src/constants/subagents.ts +0 -4
- package/src/constants/toolLimits.ts +0 -15
- package/src/constants/tools.ts +0 -24
- package/src/core/plugin.ts +0 -237
- package/src/core/session.ts +0 -9
- package/src/index.ts +0 -38
- package/src/managers/MemoryRuleManager.ts +0 -198
- package/src/managers/aiManager.ts +0 -2429
- package/src/managers/backgroundTaskManager.ts +0 -480
- package/src/managers/bangManager.ts +0 -119
- package/src/managers/cronManager.ts +0 -401
- package/src/managers/foregroundTaskManager.ts +0 -30
- package/src/managers/forkedAgentManager.ts +0 -216
- package/src/managers/hookManager.ts +0 -1089
- package/src/managers/liveConfigManager.ts +0 -445
- package/src/managers/lspManager.ts +0 -470
- package/src/managers/mcpManager.ts +0 -1010
- package/src/managers/messageManager.ts +0 -1180
- package/src/managers/messageQueue.ts +0 -157
- package/src/managers/permissionManager.ts +0 -1140
- package/src/managers/planManager.ts +0 -112
- package/src/managers/pluginManager.ts +0 -330
- package/src/managers/pluginScopeManager.ts +0 -124
- package/src/managers/reversionManager.ts +0 -178
- package/src/managers/skillManager.ts +0 -578
- package/src/managers/slashCommandManager.ts +0 -564
- package/src/managers/subagentManager.ts +0 -915
- package/src/managers/toolManager.ts +0 -489
- package/src/managers/workflowManager.ts +0 -493
- package/src/prompts/autoMemory.ts +0 -33
- package/src/prompts/autoMemoryExtraction.ts +0 -146
- package/src/prompts/index.ts +0 -506
- package/src/prompts/planModeReminders.ts +0 -126
- package/src/services/GitService.ts +0 -131
- package/src/services/MarketplaceService.ts +0 -1052
- package/src/services/MemoryRuleService.ts +0 -71
- package/src/services/aiService.ts +0 -919
- package/src/services/authService.ts +0 -565
- package/src/services/autoMemoryService.ts +0 -280
- package/src/services/configurationService.ts +0 -1520
- package/src/services/fileWatcher.ts +0 -319
- package/src/services/hook.ts +0 -348
- package/src/services/initializationService.ts +0 -357
- package/src/services/interactionService.ts +0 -229
- package/src/services/jsonlHandler.ts +0 -295
- package/src/services/memory.ts +0 -234
- package/src/services/pluginLoader.ts +0 -252
- package/src/services/remoteSettingsService.ts +0 -366
- package/src/services/reversionService.ts +0 -122
- package/src/services/session.ts +0 -922
- package/src/services/taskManager.ts +0 -321
- package/src/telemetry/events.ts +0 -65
- package/src/telemetry/instrumentation.ts +0 -499
- package/src/telemetry/sessionTracing.ts +0 -348
- package/src/tools/agentTool.ts +0 -322
- package/src/tools/askUserQuestion.ts +0 -160
- package/src/tools/bashTool.ts +0 -621
- package/src/tools/buildTool.ts +0 -61
- package/src/tools/cronCreateTool.ts +0 -161
- package/src/tools/cronDeleteTool.ts +0 -51
- package/src/tools/cronListTool.ts +0 -47
- package/src/tools/editTool.ts +0 -313
- package/src/tools/enterPlanMode.ts +0 -124
- package/src/tools/enterWorktreeTool.ts +0 -190
- package/src/tools/exitPlanMode.ts +0 -139
- package/src/tools/exitWorktreeTool.ts +0 -236
- package/src/tools/globTool.ts +0 -167
- package/src/tools/grepTool.ts +0 -399
- package/src/tools/lspTool.ts +0 -883
- package/src/tools/readTool.ts +0 -426
- package/src/tools/skillTool.ts +0 -248
- package/src/tools/taskManagementTools.ts +0 -574
- package/src/tools/taskStopTool.ts +0 -78
- package/src/tools/types.ts +0 -137
- package/src/tools/webFetchTool.ts +0 -373
- package/src/tools/workflowTool.ts +0 -205
- package/src/tools/writeTool.ts +0 -267
- package/src/types/agent.ts +0 -128
- package/src/types/auth.ts +0 -19
- package/src/types/commands.ts +0 -30
- package/src/types/config.ts +0 -43
- package/src/types/configuration.ts +0 -168
- package/src/types/core.ts +0 -105
- package/src/types/cron.ts +0 -13
- package/src/types/environment.ts +0 -106
- package/src/types/fileSearch.ts +0 -4
- package/src/types/history.ts +0 -7
- package/src/types/hooks.ts +0 -256
- package/src/types/index.ts +0 -41
- package/src/types/lsp.ts +0 -98
- package/src/types/marketplace.ts +0 -71
- package/src/types/mcp.ts +0 -43
- package/src/types/memoryRule.ts +0 -31
- package/src/types/messaging.ts +0 -114
- package/src/types/permissions.ts +0 -80
- package/src/types/plugins.ts +0 -39
- package/src/types/processes.ts +0 -99
- package/src/types/reversion.ts +0 -29
- package/src/types/session.ts +0 -12
- package/src/types/skills.ts +0 -108
- package/src/types/tasks.ts +0 -13
- package/src/types/telemetry.ts +0 -98
- package/src/types/tools.ts +0 -44
- package/src/types/workflow.ts +0 -6
- package/src/utils/abortUtils.ts +0 -118
- package/src/utils/atomicWrite.ts +0 -61
- package/src/utils/bashParser.ts +0 -899
- package/src/utils/cacheControlUtils.ts +0 -426
- package/src/utils/commandArgumentParser.ts +0 -161
- package/src/utils/commandPathResolver.ts +0 -88
- package/src/utils/configPaths.ts +0 -220
- package/src/utils/configValidator.ts +0 -100
- package/src/utils/constants.ts +0 -39
- package/src/utils/container.ts +0 -92
- package/src/utils/containerSetup.ts +0 -371
- package/src/utils/convertMessagesForAPI.ts +0 -326
- package/src/utils/cronTasks.ts +0 -128
- package/src/utils/cronTasksLock.ts +0 -182
- package/src/utils/cronToHuman.ts +0 -99
- package/src/utils/customCommands.ts +0 -95
- package/src/utils/editUtils.ts +0 -20
- package/src/utils/fileFormat.ts +0 -40
- package/src/utils/fileSearch.ts +0 -151
- package/src/utils/fileUtils.ts +0 -223
- package/src/utils/gitUtils.ts +0 -315
- package/src/utils/globalLogger.ts +0 -128
- package/src/utils/groupMessagesByApiRound.ts +0 -121
- package/src/utils/hookMatcher.ts +0 -176
- package/src/utils/markdownParser.ts +0 -317
- package/src/utils/mcpUtils.ts +0 -138
- package/src/utils/messageOperations.ts +0 -641
- package/src/utils/modelCapabilities.ts +0 -30
- package/src/utils/nameGenerator.ts +0 -99
- package/src/utils/notificationXml.ts +0 -57
- package/src/utils/openaiClient.ts +0 -251
- package/src/utils/parseCronExpression.ts +0 -78
- package/src/utils/path.ts +0 -72
- package/src/utils/pathEncoder.ts +0 -400
- package/src/utils/pathSafety.ts +0 -40
- package/src/utils/promptHistory.ts +0 -168
- package/src/utils/ripgrep.ts +0 -35
- package/src/utils/shellResolver.ts +0 -190
- package/src/utils/skillParser.ts +0 -246
- package/src/utils/stringUtils.ts +0 -156
- package/src/utils/subagentParser.ts +0 -279
- package/src/utils/taskReminder.ts +0 -96
- package/src/utils/tokenCalculation.ts +0 -43
- package/src/utils/tokenEstimate.ts +0 -34
- package/src/utils/toolResultStorage.ts +0 -117
- package/src/utils/worktreeSession.ts +0 -26
- package/src/utils/worktreeUtils.ts +0 -786
- package/src/workflow/budgetTracker.ts +0 -34
- package/src/workflow/concurrencyLimiter.ts +0 -47
- package/src/workflow/journal.ts +0 -95
- package/src/workflow/progressReporter.ts +0 -141
- package/src/workflow/runState.ts +0 -65
- package/src/workflow/scriptRuntime.ts +0 -274
- package/src/workflow/structuredOutput.ts +0 -123
- package/src/workflow/types.ts +0 -101
- package/src/workflow/workflowApis.ts +0 -410
- package/vendor/ripgrep/linux-aarch64/rg +0 -0
- package/vendor/ripgrep/linux-x86_64/rg +0 -0
- package/vendor/ripgrep/macos-aarch64/rg +0 -0
- package/vendor/ripgrep/macos-x86_64/rg +0 -0
- package/vendor/ripgrep/windows-aarch64/rg.exe +0 -0
- package/vendor/ripgrep/windows-x86_64/rg.exe +0 -0
|
@@ -1,499 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenTelemetry Instrumentation Module
|
|
3
|
-
*
|
|
4
|
-
* Handles SDK initialization, provider setup, exporter configuration,
|
|
5
|
-
* and graceful shutdown for Wave's OpenTelemetry integration.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
TelemetryConfig,
|
|
10
|
-
ExporterTarget,
|
|
11
|
-
OTLPProtocol,
|
|
12
|
-
} from "../types/telemetry.js";
|
|
13
|
-
import { logger } from "../utils/globalLogger.js";
|
|
14
|
-
import * as fs from "node:fs";
|
|
15
|
-
|
|
16
|
-
import type { SpanExporter, ReadableSpan } from "@opentelemetry/sdk-trace-node";
|
|
17
|
-
import type {
|
|
18
|
-
LogRecordExporter,
|
|
19
|
-
ReadableLogRecord,
|
|
20
|
-
} from "@opentelemetry/sdk-logs";
|
|
21
|
-
import {
|
|
22
|
-
AuthService,
|
|
23
|
-
getOrCreateAnonymousId,
|
|
24
|
-
} from "../services/authService.js";
|
|
25
|
-
|
|
26
|
-
// Lazy-loaded OTEL modules — only imported when telemetry is initialized
|
|
27
|
-
let sdkNode: typeof import("@opentelemetry/sdk-node") | undefined;
|
|
28
|
-
let api: typeof import("@opentelemetry/api") | undefined;
|
|
29
|
-
let sdkLogs: typeof import("@opentelemetry/sdk-logs") | undefined;
|
|
30
|
-
let exporterTraceOtlpHttp:
|
|
31
|
-
| typeof import("@opentelemetry/exporter-trace-otlp-http")
|
|
32
|
-
| undefined;
|
|
33
|
-
let exporterLogsOtlpHttp:
|
|
34
|
-
| typeof import("@opentelemetry/exporter-logs-otlp-http")
|
|
35
|
-
| undefined;
|
|
36
|
-
|
|
37
|
-
/** Internal SDK instance */
|
|
38
|
-
let otelSdk: import("@opentelemetry/sdk-node").NodeSDK | undefined;
|
|
39
|
-
|
|
40
|
-
/** Whether telemetry has been initialized */
|
|
41
|
-
let initialized = false;
|
|
42
|
-
|
|
43
|
-
/** Current resolved config */
|
|
44
|
-
let currentConfig: TelemetryConfig | undefined;
|
|
45
|
-
|
|
46
|
-
/** Default telemetry file path */
|
|
47
|
-
const DEFAULT_TELEMETRY_FILE = "~/.wave/telemetry.jsonl";
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Resolve the telemetry file path, expanding ~ to home directory.
|
|
51
|
-
*/
|
|
52
|
-
function resolveTelemetryFilePath(): string {
|
|
53
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
54
|
-
return DEFAULT_TELEMETRY_FILE.replace("~", homeDir);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Load OTEL SDK modules via dynamic import (lazy loading to avoid startup penalty).
|
|
59
|
-
*/
|
|
60
|
-
async function loadOTELModules(): Promise<void> {
|
|
61
|
-
if (api) return; // Already loaded
|
|
62
|
-
|
|
63
|
-
[sdkNode, api, sdkLogs, exporterTraceOtlpHttp, exporterLogsOtlpHttp] =
|
|
64
|
-
await Promise.all([
|
|
65
|
-
import("@opentelemetry/sdk-node"),
|
|
66
|
-
import("@opentelemetry/api"),
|
|
67
|
-
import("@opentelemetry/sdk-logs"),
|
|
68
|
-
import("@opentelemetry/exporter-trace-otlp-http"),
|
|
69
|
-
import("@opentelemetry/exporter-logs-otlp-http"),
|
|
70
|
-
]);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Resolve the exporter target from environment variable or config.
|
|
75
|
-
* Environment variable takes precedence over settings.json config.
|
|
76
|
-
*/
|
|
77
|
-
function resolveExporter(
|
|
78
|
-
signal: "traces" | "logs",
|
|
79
|
-
config?: Partial<TelemetryConfig>,
|
|
80
|
-
): ExporterTarget | undefined {
|
|
81
|
-
const envVar = `OTEL_${signal.toUpperCase()}_EXPORTER`;
|
|
82
|
-
const envValue = process.env[envVar];
|
|
83
|
-
if (envValue === "jsonl" || envValue === "otlp") {
|
|
84
|
-
return envValue;
|
|
85
|
-
}
|
|
86
|
-
if (envValue && envValue !== "none") {
|
|
87
|
-
logger?.warn(`Unknown OTEL exporter: ${envValue}, ignoring`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const configKey = `${signal}Exporter` as keyof TelemetryConfig;
|
|
91
|
-
return config?.[configKey] as ExporterTarget | undefined;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Resolve the OTLP endpoint from environment variable or config.
|
|
96
|
-
*/
|
|
97
|
-
function resolveEndpoint(
|
|
98
|
-
config?: Partial<TelemetryConfig>,
|
|
99
|
-
): string | undefined {
|
|
100
|
-
return process.env.OTEL_EXPORTER_OTLP_ENDPOINT || config?.endpoint;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Resolve the OTLP protocol from environment variable or config.
|
|
105
|
-
*/
|
|
106
|
-
function resolveProtocol(
|
|
107
|
-
config?: Partial<TelemetryConfig>,
|
|
108
|
-
): OTLPProtocol | undefined {
|
|
109
|
-
const envProtocol = process.env.OTEL_EXPORTER_OTLP_PROTOCOL as
|
|
110
|
-
| OTLPProtocol
|
|
111
|
-
| undefined;
|
|
112
|
-
if (envProtocol) return envProtocol;
|
|
113
|
-
return config?.protocol;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Resolve OTLP headers from environment variable or config.
|
|
118
|
-
* Env var format: "key1=value1,key2=value2"
|
|
119
|
-
*/
|
|
120
|
-
function resolveHeaders(
|
|
121
|
-
config?: Partial<TelemetryConfig>,
|
|
122
|
-
): Record<string, string> | undefined {
|
|
123
|
-
const envHeaders = process.env.OTEL_EXPORTER_OTLP_HEADERS;
|
|
124
|
-
if (envHeaders) {
|
|
125
|
-
const headers: Record<string, string> = {};
|
|
126
|
-
for (const pair of envHeaders.split(",")) {
|
|
127
|
-
const [key, ...valueParts] = pair.split("=");
|
|
128
|
-
if (key && valueParts.length > 0) {
|
|
129
|
-
headers[key.trim()] = valueParts.join("=").trim();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
133
|
-
}
|
|
134
|
-
return config?.headers;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Resolve PII gate flags from environment variables.
|
|
139
|
-
*/
|
|
140
|
-
function resolveLogUserPrompts(config?: Partial<TelemetryConfig>): boolean {
|
|
141
|
-
const envValue = process.env.OTEL_LOG_USER_PROMPTS;
|
|
142
|
-
if (envValue === "1" || envValue === "true") return true;
|
|
143
|
-
if (envValue === "0" || envValue === "false") return false;
|
|
144
|
-
return config?.logUserPrompts ?? false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function resolveLogToolContent(config?: Partial<TelemetryConfig>): boolean {
|
|
148
|
-
const envValue = process.env.OTEL_LOG_TOOL_CONTENT;
|
|
149
|
-
if (envValue === "1" || envValue === "true") return true;
|
|
150
|
-
if (envValue === "0" || envValue === "false") return false;
|
|
151
|
-
return config?.logToolContent ?? false;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Resolve span TTL from environment variable or config.
|
|
156
|
-
*/
|
|
157
|
-
function resolveSpanTtlMs(config?: Partial<TelemetryConfig>): number {
|
|
158
|
-
const envValue = process.env.OTEL_SPAN_TTL_MS;
|
|
159
|
-
if (envValue) {
|
|
160
|
-
const parsed = parseInt(envValue, 10);
|
|
161
|
-
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
162
|
-
}
|
|
163
|
-
return config?.spanTtlMs ?? 1_800_000; // 30 minutes default
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Resolve shutdown timeout from environment variable or config.
|
|
168
|
-
*/
|
|
169
|
-
function resolveShutdownTimeoutMs(config?: Partial<TelemetryConfig>): number {
|
|
170
|
-
const envValue = process.env.OTEL_SHUTDOWN_TIMEOUT_MS;
|
|
171
|
-
if (envValue) {
|
|
172
|
-
const parsed = parseInt(envValue, 10);
|
|
173
|
-
if (!isNaN(parsed) && parsed > 0) return parsed;
|
|
174
|
-
}
|
|
175
|
-
return config?.shutdownTimeoutMs ?? 2_000; // 2 seconds default
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Resolve the full TelemetryConfig from env vars + settings.json.
|
|
180
|
-
* Env vars take precedence over settings.json.
|
|
181
|
-
*/
|
|
182
|
-
export function resolveTelemetryConfig(
|
|
183
|
-
settingsConfig?: Partial<TelemetryConfig>,
|
|
184
|
-
): TelemetryConfig {
|
|
185
|
-
const tracesExporter = resolveExporter("traces", settingsConfig);
|
|
186
|
-
const logsExporter = resolveExporter("logs", settingsConfig);
|
|
187
|
-
|
|
188
|
-
return {
|
|
189
|
-
enabled:
|
|
190
|
-
process.env.OTEL_ENABLED === "false"
|
|
191
|
-
? false
|
|
192
|
-
: (settingsConfig?.enabled ?? !!(tracesExporter || logsExporter)),
|
|
193
|
-
tracesExporter,
|
|
194
|
-
logsExporter,
|
|
195
|
-
endpoint: resolveEndpoint(settingsConfig),
|
|
196
|
-
protocol: resolveProtocol(settingsConfig),
|
|
197
|
-
headers: resolveHeaders(settingsConfig),
|
|
198
|
-
logUserPrompts: resolveLogUserPrompts(settingsConfig),
|
|
199
|
-
logToolContent: resolveLogToolContent(settingsConfig),
|
|
200
|
-
shutdownTimeoutMs: resolveShutdownTimeoutMs(settingsConfig),
|
|
201
|
-
spanTtlMs: resolveSpanTtlMs(settingsConfig),
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Create an OTLP trace exporter configured with endpoint, protocol, and headers.
|
|
207
|
-
*/
|
|
208
|
-
function createOTLPTraceExporter(config: TelemetryConfig) {
|
|
209
|
-
const exporterConfig: {
|
|
210
|
-
url?: string;
|
|
211
|
-
headers?: Record<string, string>;
|
|
212
|
-
} = {};
|
|
213
|
-
|
|
214
|
-
if (config.endpoint) {
|
|
215
|
-
exporterConfig.url = `${config.endpoint}/v1/traces`;
|
|
216
|
-
}
|
|
217
|
-
if (config.headers) {
|
|
218
|
-
exporterConfig.headers = config.headers;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return new exporterTraceOtlpHttp!.OTLPTraceExporter(exporterConfig);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Create an OTLP log exporter.
|
|
226
|
-
*/
|
|
227
|
-
function createOTLPLogExporter(config: TelemetryConfig) {
|
|
228
|
-
const exporterConfig: {
|
|
229
|
-
url?: string;
|
|
230
|
-
headers?: Record<string, string>;
|
|
231
|
-
} = {};
|
|
232
|
-
|
|
233
|
-
if (config.endpoint) {
|
|
234
|
-
exporterConfig.url = `${config.endpoint}/v1/logs`;
|
|
235
|
-
}
|
|
236
|
-
if (config.headers) {
|
|
237
|
-
exporterConfig.headers = config.headers;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return new exporterLogsOtlpHttp!.OTLPLogExporter(exporterConfig);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* JSONL Span Exporter — writes span data as JSON lines to a file.
|
|
245
|
-
*/
|
|
246
|
-
class JsonlSpanExporter implements SpanExporter {
|
|
247
|
-
private filePath: string;
|
|
248
|
-
|
|
249
|
-
constructor(filePath?: string) {
|
|
250
|
-
this.filePath = filePath || resolveTelemetryFilePath();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export(
|
|
254
|
-
spans: ReadableSpan[],
|
|
255
|
-
resultCallback: (result: { code: number }) => void,
|
|
256
|
-
): void {
|
|
257
|
-
try {
|
|
258
|
-
const lines = spans.map((span) => {
|
|
259
|
-
const record: Record<string, unknown> = {
|
|
260
|
-
type: "span",
|
|
261
|
-
span_name: span.name,
|
|
262
|
-
trace_id: span.spanContext().traceId,
|
|
263
|
-
span_id: span.spanContext().spanId,
|
|
264
|
-
parent_span_id: span.parentSpanContext?.spanId,
|
|
265
|
-
start_time: span.startTime,
|
|
266
|
-
end_time: span.endTime,
|
|
267
|
-
status: span.status.code,
|
|
268
|
-
attributes: span.attributes,
|
|
269
|
-
};
|
|
270
|
-
return JSON.stringify(record);
|
|
271
|
-
});
|
|
272
|
-
fs.appendFileSync(this.filePath, lines.join("\n") + "\n", "utf8");
|
|
273
|
-
resultCallback({ code: 0 });
|
|
274
|
-
} catch (error) {
|
|
275
|
-
logger?.warn("JSONL span export failed:", error);
|
|
276
|
-
resultCallback({ code: 1 });
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
shutdown(): Promise<void> {
|
|
281
|
-
return Promise.resolve();
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
forceFlush(): Promise<void> {
|
|
285
|
-
return Promise.resolve();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* JSONL Log Exporter — writes log records as JSON lines to a file.
|
|
291
|
-
*/
|
|
292
|
-
class JsonlLogExporter implements LogRecordExporter {
|
|
293
|
-
private filePath: string;
|
|
294
|
-
|
|
295
|
-
constructor(filePath?: string) {
|
|
296
|
-
this.filePath = filePath || resolveTelemetryFilePath();
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export(
|
|
300
|
-
logs: ReadableLogRecord[],
|
|
301
|
-
resultCallback: (result: { code: number }) => void,
|
|
302
|
-
): void {
|
|
303
|
-
try {
|
|
304
|
-
const lines = logs.map((log) => {
|
|
305
|
-
const record: Record<string, unknown> = {
|
|
306
|
-
type: "log",
|
|
307
|
-
event_name: (log.attributes as Record<string, unknown>)?.[
|
|
308
|
-
"event.name"
|
|
309
|
-
],
|
|
310
|
-
severity: log.severityNumber,
|
|
311
|
-
body: log.body,
|
|
312
|
-
timestamp: log.hrTime,
|
|
313
|
-
attributes: log.attributes,
|
|
314
|
-
};
|
|
315
|
-
return JSON.stringify(record);
|
|
316
|
-
});
|
|
317
|
-
fs.appendFileSync(this.filePath, lines.join("\n") + "\n", "utf8");
|
|
318
|
-
resultCallback({ code: 0 });
|
|
319
|
-
} catch (error) {
|
|
320
|
-
logger?.warn("JSONL log export failed:", error);
|
|
321
|
-
resultCallback({ code: 1 });
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
shutdown(): Promise<void> {
|
|
326
|
-
return Promise.resolve();
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
forceFlush(): Promise<void> {
|
|
330
|
-
return Promise.resolve();
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Initialize OpenTelemetry SDK with providers and exporters.
|
|
336
|
-
* Idempotent — safe to call multiple times.
|
|
337
|
-
*
|
|
338
|
-
* @param config - Optional TelemetryConfig. If not provided, resolved from env vars.
|
|
339
|
-
*/
|
|
340
|
-
export async function initializeTelemetry(
|
|
341
|
-
config?: Partial<TelemetryConfig>,
|
|
342
|
-
): Promise<void> {
|
|
343
|
-
if (initialized) {
|
|
344
|
-
logger?.debug("Telemetry already initialized, skipping");
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
await loadOTELModules();
|
|
350
|
-
} catch (error) {
|
|
351
|
-
logger?.warn(
|
|
352
|
-
"Failed to load OpenTelemetry modules. Telemetry will be disabled:",
|
|
353
|
-
error,
|
|
354
|
-
);
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
try {
|
|
359
|
-
currentConfig = resolveTelemetryConfig(config);
|
|
360
|
-
|
|
361
|
-
if (!currentConfig.enabled) {
|
|
362
|
-
logger?.debug("Telemetry not enabled (no exporters configured)");
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
const { tracesExporter, logsExporter } = currentConfig;
|
|
367
|
-
|
|
368
|
-
// Build resource attributes using new API (sdk-node 0.217+)
|
|
369
|
-
const { resources } = sdkNode!;
|
|
370
|
-
const resource = resources.defaultResource().merge(
|
|
371
|
-
resources.resourceFromAttributes({
|
|
372
|
-
"service.name": "wave",
|
|
373
|
-
"service.version": process.env.npm_package_version || "unknown",
|
|
374
|
-
"os.type": process.platform,
|
|
375
|
-
"host.arch": process.arch,
|
|
376
|
-
}),
|
|
377
|
-
);
|
|
378
|
-
|
|
379
|
-
// Configure trace provider
|
|
380
|
-
const nodeSdkOptions: Record<string, unknown> = { resource };
|
|
381
|
-
|
|
382
|
-
if (tracesExporter === "otlp" && currentConfig.endpoint) {
|
|
383
|
-
nodeSdkOptions.traceExporter = createOTLPTraceExporter(currentConfig);
|
|
384
|
-
} else if (tracesExporter === "jsonl") {
|
|
385
|
-
nodeSdkOptions.traceExporter = new JsonlSpanExporter();
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
// Configure logs provider
|
|
389
|
-
if (logsExporter === "otlp" && currentConfig.endpoint) {
|
|
390
|
-
nodeSdkOptions.logRecordProcessor = new sdkLogs!.BatchLogRecordProcessor(
|
|
391
|
-
createOTLPLogExporter(currentConfig),
|
|
392
|
-
);
|
|
393
|
-
} else if (logsExporter === "jsonl") {
|
|
394
|
-
nodeSdkOptions.logRecordProcessor = new sdkLogs!.BatchLogRecordProcessor(
|
|
395
|
-
new JsonlLogExporter(),
|
|
396
|
-
);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Only initialize SDK if at least one exporter is configured
|
|
400
|
-
if (nodeSdkOptions.traceExporter || nodeSdkOptions.logRecordProcessor) {
|
|
401
|
-
otelSdk = new sdkNode!.NodeSDK(nodeSdkOptions);
|
|
402
|
-
await otelSdk.start();
|
|
403
|
-
initialized = true;
|
|
404
|
-
|
|
405
|
-
logger?.info("OpenTelemetry initialized", {
|
|
406
|
-
tracesExporter,
|
|
407
|
-
logsExporter,
|
|
408
|
-
endpoint: currentConfig.endpoint,
|
|
409
|
-
});
|
|
410
|
-
} else {
|
|
411
|
-
logger?.debug("No telemetry exporters configured, skipping init");
|
|
412
|
-
}
|
|
413
|
-
} catch (error) {
|
|
414
|
-
logger?.warn(
|
|
415
|
-
"OpenTelemetry initialization failed, continuing without telemetry:",
|
|
416
|
-
error,
|
|
417
|
-
);
|
|
418
|
-
// Graceful degradation — do not crash
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Shut down OpenTelemetry, flushing all pending data.
|
|
424
|
-
* Respects shutdownTimeoutMs config.
|
|
425
|
-
*/
|
|
426
|
-
export async function shutdownTelemetry(): Promise<void> {
|
|
427
|
-
if (!otelSdk || !initialized) {
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
try {
|
|
432
|
-
const timeout = currentConfig?.shutdownTimeoutMs ?? 2_000;
|
|
433
|
-
const timeoutPromise = new Promise<void>((_, reject) => {
|
|
434
|
-
setTimeout(
|
|
435
|
-
() => reject(new Error("Telemetry shutdown timed out")),
|
|
436
|
-
timeout,
|
|
437
|
-
);
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
await Promise.race([otelSdk.shutdown(), timeoutPromise]);
|
|
441
|
-
logger?.debug("OpenTelemetry shut down successfully");
|
|
442
|
-
} catch (error) {
|
|
443
|
-
logger?.warn("OpenTelemetry shutdown failed:", error);
|
|
444
|
-
} finally {
|
|
445
|
-
otelSdk = undefined;
|
|
446
|
-
initialized = false;
|
|
447
|
-
currentConfig = undefined;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* Get the OTEL API module (for creating tracers, meters, etc.).
|
|
453
|
-
* Returns undefined if telemetry is not initialized.
|
|
454
|
-
*/
|
|
455
|
-
export function getOTELApi(): typeof import("@opentelemetry/api") | undefined {
|
|
456
|
-
return api;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Get the current resolved config.
|
|
461
|
-
*/
|
|
462
|
-
export function getCurrentConfig(): TelemetryConfig | undefined {
|
|
463
|
-
return currentConfig;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Check if telemetry is initialized.
|
|
468
|
-
*/
|
|
469
|
-
export function isInitialized(): boolean {
|
|
470
|
-
return initialized;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// Export JSONL exporters for testing
|
|
474
|
-
export { JsonlSpanExporter, JsonlLogExporter };
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Get telemetry attributes for the current session.
|
|
478
|
-
*
|
|
479
|
-
* Priority:
|
|
480
|
-
* 1. SSO authenticated → server-provided user.id + user.email
|
|
481
|
-
* 2. Not authenticated → persistent anonymous ID from ~/.wave/config.json
|
|
482
|
-
*/
|
|
483
|
-
export function getTelemetryAttributes(): Record<string, string> {
|
|
484
|
-
try {
|
|
485
|
-
const user = AuthService.getInstance().getAuthUser();
|
|
486
|
-
if (user) {
|
|
487
|
-
const attrs: Record<string, string> = { "user.id": user.id };
|
|
488
|
-
if (user.email) {
|
|
489
|
-
attrs["user.email"] = user.email;
|
|
490
|
-
}
|
|
491
|
-
return attrs;
|
|
492
|
-
}
|
|
493
|
-
} catch {
|
|
494
|
-
// AuthService not available or not authenticated
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// Fallback to anonymous ID
|
|
498
|
-
return { "user.id": getOrCreateAnonymousId() };
|
|
499
|
-
}
|