@lelemondev/sdk 0.6.2 → 0.7.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.
- package/dist/express.js.map +1 -1
- package/dist/express.mjs.map +1 -1
- package/dist/hono.js.map +1 -1
- package/dist/hono.mjs.map +1 -1
- package/dist/index.d.mts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +213 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +213 -3
- package/dist/index.mjs.map +1 -1
- package/dist/integrations.js.map +1 -1
- package/dist/integrations.mjs.map +1 -1
- package/dist/lambda.js.map +1 -1
- package/dist/lambda.mjs.map +1 -1
- package/dist/next.js.map +1 -1
- package/dist/next.mjs.map +1 -1
- package/package.json +1 -1
package/dist/express.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/integrations/express.ts"],"names":[],"mappings":";;;;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACrBO,SAAS,gBAAA,GAAsC;AACpD,EAAA,OAAO,CAAC,IAAA,EAAM,GAAA,EAAK,IAAA,KAAS;AAE1B,IAAA,GAAA,CAAI,EAAA,CAAG,UAAU,MAAM;AACrB,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAEpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AACF","file":"express.js","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Express Integration\n *\n * Middleware that automatically flushes traces when response finishes.\n *\n * @example\n * import express from 'express';\n * import { createMiddleware } from '@lelemondev/sdk/express';\n *\n * const app = express();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring express as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Minimal Express request type (avoids requiring express as dependency)\n */\nexport interface ExpressRequest {\n [key: string]: unknown;\n}\n\n/**\n * Minimal Express response type (avoids requiring express as dependency)\n */\nexport interface ExpressResponse {\n on(event: 'finish' | 'close' | 'error', listener: () => void): this;\n [key: string]: unknown;\n}\n\n/**\n * Express next function type\n */\nexport type ExpressNextFunction = (error?: unknown) => void;\n\n/**\n * Express middleware function type\n *\n * @param req - Express request object\n * @param res - Express response object\n * @param next - Next function to pass control\n */\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction\n) => void;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Express middleware for automatic trace flushing\n *\n * Flushes traces when the response finishes (after res.send/res.json).\n * This is fire-and-forget and doesn't block the response.\n *\n * @returns Express middleware function\n *\n * @example\n * // Global middleware\n * app.use(createMiddleware());\n *\n * @example\n * // Per-route middleware\n * app.post('/chat', createMiddleware(), async (req, res) => {\n * res.json({ ok: true });\n * });\n */\nexport function createMiddleware(): ExpressMiddleware {\n return (_req, res, next) => {\n // Flush when response is finished (after headers + body sent)\n res.on('finish', () => {\n flush().catch(() => {\n // Silently ignore flush errors - fire and forget\n });\n });\n\n next();\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts","../src/integrations/express.ts"],"names":[],"mappings":";;;;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACrBO,SAAS,gBAAA,GAAsC;AACpD,EAAA,OAAO,CAAC,IAAA,EAAM,GAAA,EAAK,IAAA,KAAS;AAE1B,IAAA,GAAA,CAAI,EAAA,CAAG,UAAU,MAAM;AACrB,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAEpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AACF","file":"express.js","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://www.lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Express Integration\n *\n * Middleware that automatically flushes traces when response finishes.\n *\n * @example\n * import express from 'express';\n * import { createMiddleware } from '@lelemondev/sdk/express';\n *\n * const app = express();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring express as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Minimal Express request type (avoids requiring express as dependency)\n */\nexport interface ExpressRequest {\n [key: string]: unknown;\n}\n\n/**\n * Minimal Express response type (avoids requiring express as dependency)\n */\nexport interface ExpressResponse {\n on(event: 'finish' | 'close' | 'error', listener: () => void): this;\n [key: string]: unknown;\n}\n\n/**\n * Express next function type\n */\nexport type ExpressNextFunction = (error?: unknown) => void;\n\n/**\n * Express middleware function type\n *\n * @param req - Express request object\n * @param res - Express response object\n * @param next - Next function to pass control\n */\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction\n) => void;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Express middleware for automatic trace flushing\n *\n * Flushes traces when the response finishes (after res.send/res.json).\n * This is fire-and-forget and doesn't block the response.\n *\n * @returns Express middleware function\n *\n * @example\n * // Global middleware\n * app.use(createMiddleware());\n *\n * @example\n * // Per-route middleware\n * app.post('/chat', createMiddleware(), async (req, res) => {\n * res.json({ ok: true });\n * });\n */\nexport function createMiddleware(): ExpressMiddleware {\n return (_req, res, next) => {\n // Flush when response is finished (after headers + body sent)\n res.on('finish', () => {\n flush().catch(() => {\n // Silently ignore flush errors - fire and forget\n });\n });\n\n next();\n };\n}\n"]}
|
package/dist/express.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/integrations/express.ts"],"names":[],"mappings":";;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACrBO,SAAS,gBAAA,GAAsC;AACpD,EAAA,OAAO,CAAC,IAAA,EAAM,GAAA,EAAK,IAAA,KAAS;AAE1B,IAAA,GAAA,CAAI,EAAA,CAAG,UAAU,MAAM;AACrB,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAEpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AACF","file":"express.mjs","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Express Integration\n *\n * Middleware that automatically flushes traces when response finishes.\n *\n * @example\n * import express from 'express';\n * import { createMiddleware } from '@lelemondev/sdk/express';\n *\n * const app = express();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring express as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Minimal Express request type (avoids requiring express as dependency)\n */\nexport interface ExpressRequest {\n [key: string]: unknown;\n}\n\n/**\n * Minimal Express response type (avoids requiring express as dependency)\n */\nexport interface ExpressResponse {\n on(event: 'finish' | 'close' | 'error', listener: () => void): this;\n [key: string]: unknown;\n}\n\n/**\n * Express next function type\n */\nexport type ExpressNextFunction = (error?: unknown) => void;\n\n/**\n * Express middleware function type\n *\n * @param req - Express request object\n * @param res - Express response object\n * @param next - Next function to pass control\n */\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction\n) => void;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Express middleware for automatic trace flushing\n *\n * Flushes traces when the response finishes (after res.send/res.json).\n * This is fire-and-forget and doesn't block the response.\n *\n * @returns Express middleware function\n *\n * @example\n * // Global middleware\n * app.use(createMiddleware());\n *\n * @example\n * // Per-route middleware\n * app.post('/chat', createMiddleware(), async (req, res) => {\n * res.json({ ok: true });\n * });\n */\nexport function createMiddleware(): ExpressMiddleware {\n return (_req, res, next) => {\n // Flush when response is finished (after headers + body sent)\n res.on('finish', () => {\n flush().catch(() => {\n // Silently ignore flush errors - fire and forget\n });\n });\n\n next();\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts","../src/integrations/express.ts"],"names":[],"mappings":";;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACrBO,SAAS,gBAAA,GAAsC;AACpD,EAAA,OAAO,CAAC,IAAA,EAAM,GAAA,EAAK,IAAA,KAAS;AAE1B,IAAA,GAAA,CAAI,EAAA,CAAG,UAAU,MAAM;AACrB,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAEpB,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,IAAA,EAAK;AAAA,EACP,CAAA;AACF","file":"express.mjs","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://www.lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Express Integration\n *\n * Middleware that automatically flushes traces when response finishes.\n *\n * @example\n * import express from 'express';\n * import { createMiddleware } from '@lelemondev/sdk/express';\n *\n * const app = express();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring express as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Minimal Express request type (avoids requiring express as dependency)\n */\nexport interface ExpressRequest {\n [key: string]: unknown;\n}\n\n/**\n * Minimal Express response type (avoids requiring express as dependency)\n */\nexport interface ExpressResponse {\n on(event: 'finish' | 'close' | 'error', listener: () => void): this;\n [key: string]: unknown;\n}\n\n/**\n * Express next function type\n */\nexport type ExpressNextFunction = (error?: unknown) => void;\n\n/**\n * Express middleware function type\n *\n * @param req - Express request object\n * @param res - Express response object\n * @param next - Next function to pass control\n */\nexport type ExpressMiddleware = (\n req: ExpressRequest,\n res: ExpressResponse,\n next: ExpressNextFunction\n) => void;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Express middleware for automatic trace flushing\n *\n * Flushes traces when the response finishes (after res.send/res.json).\n * This is fire-and-forget and doesn't block the response.\n *\n * @returns Express middleware function\n *\n * @example\n * // Global middleware\n * app.use(createMiddleware());\n *\n * @example\n * // Per-route middleware\n * app.post('/chat', createMiddleware(), async (req, res) => {\n * res.json({ ok: true });\n * });\n */\nexport function createMiddleware(): ExpressMiddleware {\n return (_req, res, next) => {\n // Flush when response is finished (after headers + body sent)\n res.on('finish', () => {\n flush().catch(() => {\n // Silently ignore flush errors - fire and forget\n });\n });\n\n next();\n };\n}\n"]}
|
package/dist/hono.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/integrations/hono.ts"],"names":[],"mappings":";;;;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACZO,SAAS,gBAAA,GAAmC;AACjD,EAAA,OAAO,OAAO,GAAG,IAAA,KAAS;AACxB,IAAA,MAAM,IAAA,EAAK;AAGX,IAAA,IAAI,CAAA,CAAE,cAAc,SAAA,EAAW;AAC7B,MAAA,CAAA,CAAE,YAAA,CAAa,SAAA,CAAU,KAAA,EAAO,CAAA;AAAA,IAClC,CAAA,MAAO;AAEL,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxB;AAAA,EACF,CAAA;AACF","file":"hono.js","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Hono Integration\n *\n * Middleware for Hono framework (Cloudflare Workers, Deno, Bun, Node.js).\n * Uses executionCtx.waitUntil() when available for non-blocking flush.\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring hono as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execution context for edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport interface ExecutionContext {\n waitUntil(promise: Promise<unknown>): void;\n passThroughOnException(): void;\n}\n\n/**\n * Minimal Hono context type (avoids requiring hono as dependency)\n */\nexport interface HonoContext {\n req: {\n raw: Request;\n [key: string]: unknown;\n };\n res: Response | undefined;\n executionCtx?: ExecutionContext;\n [key: string]: unknown;\n}\n\n/**\n * Hono next function type\n */\nexport type HonoNextFunction = () => Promise<void>;\n\n/**\n * Hono middleware function type\n *\n * @param c - Hono context object\n * @param next - Next function to continue middleware chain\n */\nexport type HonoMiddleware = (c: HonoContext, next: HonoNextFunction) => Promise<void>;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Hono middleware for automatic trace flushing\n *\n * On Cloudflare Workers/Deno Deploy: uses executionCtx.waitUntil() for non-blocking flush\n * On Node.js/Bun: flushes after response (fire-and-forget)\n *\n * @returns Hono middleware function\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n *\n * // Global middleware\n * app.use(createMiddleware());\n *\n * app.post('/chat', async (c) => {\n * const openai = observe(new OpenAI());\n * const result = await openai.chat.completions.create({...});\n * return c.json(result);\n * });\n *\n * export default app;\n */\nexport function createMiddleware(): HonoMiddleware {\n return async (c, next) => {\n await next();\n\n // Use waitUntil if available (Cloudflare Workers, Deno Deploy)\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(flush());\n } else {\n // Fire-and-forget for Node.js/Bun\n flush().catch(() => {});\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts","../src/integrations/hono.ts"],"names":[],"mappings":";;;;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACZO,SAAS,gBAAA,GAAmC;AACjD,EAAA,OAAO,OAAO,GAAG,IAAA,KAAS;AACxB,IAAA,MAAM,IAAA,EAAK;AAGX,IAAA,IAAI,CAAA,CAAE,cAAc,SAAA,EAAW;AAC7B,MAAA,CAAA,CAAE,YAAA,CAAa,SAAA,CAAU,KAAA,EAAO,CAAA;AAAA,IAClC,CAAA,MAAO;AAEL,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxB;AAAA,EACF,CAAA;AACF","file":"hono.js","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://www.lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Hono Integration\n *\n * Middleware for Hono framework (Cloudflare Workers, Deno, Bun, Node.js).\n * Uses executionCtx.waitUntil() when available for non-blocking flush.\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring hono as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execution context for edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport interface ExecutionContext {\n waitUntil(promise: Promise<unknown>): void;\n passThroughOnException(): void;\n}\n\n/**\n * Minimal Hono context type (avoids requiring hono as dependency)\n */\nexport interface HonoContext {\n req: {\n raw: Request;\n [key: string]: unknown;\n };\n res: Response | undefined;\n executionCtx?: ExecutionContext;\n [key: string]: unknown;\n}\n\n/**\n * Hono next function type\n */\nexport type HonoNextFunction = () => Promise<void>;\n\n/**\n * Hono middleware function type\n *\n * @param c - Hono context object\n * @param next - Next function to continue middleware chain\n */\nexport type HonoMiddleware = (c: HonoContext, next: HonoNextFunction) => Promise<void>;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Hono middleware for automatic trace flushing\n *\n * On Cloudflare Workers/Deno Deploy: uses executionCtx.waitUntil() for non-blocking flush\n * On Node.js/Bun: flushes after response (fire-and-forget)\n *\n * @returns Hono middleware function\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n *\n * // Global middleware\n * app.use(createMiddleware());\n *\n * app.post('/chat', async (c) => {\n * const openai = observe(new OpenAI());\n * const result = await openai.chat.completions.create({...});\n * return c.json(result);\n * });\n *\n * export default app;\n */\nexport function createMiddleware(): HonoMiddleware {\n return async (c, next) => {\n await next();\n\n // Use waitUntil if available (Cloudflare Workers, Deno Deploy)\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(flush());\n } else {\n // Fire-and-forget for Node.js/Bun\n flush().catch(() => {});\n }\n };\n}\n"]}
|
package/dist/hono.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/config.ts","../src/integrations/hono.ts"],"names":[],"mappings":";;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACZO,SAAS,gBAAA,GAAmC;AACjD,EAAA,OAAO,OAAO,GAAG,IAAA,KAAS;AACxB,IAAA,MAAM,IAAA,EAAK;AAGX,IAAA,IAAI,CAAA,CAAE,cAAc,SAAA,EAAW;AAC7B,MAAA,CAAA,CAAE,YAAA,CAAa,SAAA,CAAU,KAAA,EAAO,CAAA;AAAA,IAClC,CAAA,MAAO;AAEL,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxB;AAAA,EACF,CAAA;AACF","file":"hono.mjs","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Hono Integration\n *\n * Middleware for Hono framework (Cloudflare Workers, Deno, Bun, Node.js).\n * Uses executionCtx.waitUntil() when available for non-blocking flush.\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring hono as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execution context for edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport interface ExecutionContext {\n waitUntil(promise: Promise<unknown>): void;\n passThroughOnException(): void;\n}\n\n/**\n * Minimal Hono context type (avoids requiring hono as dependency)\n */\nexport interface HonoContext {\n req: {\n raw: Request;\n [key: string]: unknown;\n };\n res: Response | undefined;\n executionCtx?: ExecutionContext;\n [key: string]: unknown;\n}\n\n/**\n * Hono next function type\n */\nexport type HonoNextFunction = () => Promise<void>;\n\n/**\n * Hono middleware function type\n *\n * @param c - Hono context object\n * @param next - Next function to continue middleware chain\n */\nexport type HonoMiddleware = (c: HonoContext, next: HonoNextFunction) => Promise<void>;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Hono middleware for automatic trace flushing\n *\n * On Cloudflare Workers/Deno Deploy: uses executionCtx.waitUntil() for non-blocking flush\n * On Node.js/Bun: flushes after response (fire-and-forget)\n *\n * @returns Hono middleware function\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n *\n * // Global middleware\n * app.use(createMiddleware());\n *\n * app.post('/chat', async (c) => {\n * const openai = observe(new OpenAI());\n * const result = await openai.chat.completions.create({...});\n * return c.json(result);\n * });\n *\n * export default app;\n */\nexport function createMiddleware(): HonoMiddleware {\n return async (c, next) => {\n await next();\n\n // Use waitUntil if available (Cloudflare Workers, Deno Deploy)\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(flush());\n } else {\n // Fire-and-forget for Node.js/Bun\n flush().catch(() => {});\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/config.ts","../src/integrations/hono.ts"],"names":[],"mappings":";;AA2FA,eAAsB,KAAA,GAAuB;AAI7C;;;ACZO,SAAS,gBAAA,GAAmC;AACjD,EAAA,OAAO,OAAO,GAAG,IAAA,KAAS;AACxB,IAAA,MAAM,IAAA,EAAK;AAGX,IAAA,IAAI,CAAA,CAAE,cAAc,SAAA,EAAW;AAC7B,MAAA,CAAA,CAAE,YAAA,CAAa,SAAA,CAAU,KAAA,EAAO,CAAA;AAAA,IAClC,CAAA,MAAO;AAEL,MAAA,KAAA,EAAM,CAAE,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACxB;AAAA,EACF,CAAA;AACF","file":"hono.mjs","sourcesContent":["/**\n * Global Configuration\n *\n * Manages SDK configuration and transport instance.\n */\n\nimport type { LelemonConfig } from './types';\nimport { Transport } from './transport';\nimport { setDebug, info, warn, debug } from './logger';\n\n// ─────────────────────────────────────────────────────────────\n// Global State\n// ─────────────────────────────────────────────────────────────\n\nlet globalConfig: LelemonConfig = {};\nlet globalTransport: Transport | null = null;\nlet initialized = false;\n\n// ─────────────────────────────────────────────────────────────\n// Configuration\n// ─────────────────────────────────────────────────────────────\n\nconst DEFAULT_ENDPOINT = 'https://www.lelemon.dev';\n\n/**\n * Initialize the SDK\n * Call once at app startup\n */\nexport function init(config: LelemonConfig = {}): void {\n globalConfig = config;\n\n // Configure debug mode\n if (config.debug) {\n setDebug(true);\n }\n\n info('Initializing SDK', {\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? false,\n });\n\n globalTransport = createTransport(config);\n initialized = true;\n\n // Log status after transport is created\n if (globalTransport.isEnabled()) {\n info('SDK initialized - tracing enabled');\n } else {\n debug('SDK initialized - tracing disabled (no API key or explicitly disabled)');\n }\n}\n\n/**\n * Get current config\n */\nexport function getConfig(): LelemonConfig {\n return globalConfig;\n}\n\n/**\n * Check if SDK is initialized\n */\nexport function isInitialized(): boolean {\n return initialized;\n}\n\n/**\n * Check if SDK is enabled\n */\nexport function isEnabled(): boolean {\n return getTransport().isEnabled();\n}\n\n// ─────────────────────────────────────────────────────────────\n// Transport\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Get or create transport instance\n */\nexport function getTransport(): Transport {\n if (!globalTransport) {\n globalTransport = createTransport(globalConfig);\n }\n return globalTransport;\n}\n\n/**\n * Flush all pending traces\n */\nexport async function flush(): Promise<void> {\n if (globalTransport) {\n await globalTransport.flush();\n }\n}\n\n/**\n * Create transport instance\n */\nfunction createTransport(config: LelemonConfig): Transport {\n const apiKey = config.apiKey ?? getEnvVar('LELEMON_API_KEY');\n\n if (!apiKey && !config.disabled) {\n warn('No API key provided. Set apiKey in init() or LELEMON_API_KEY env var. Tracing disabled.');\n }\n\n return new Transport({\n apiKey: apiKey ?? '',\n endpoint: config.endpoint ?? DEFAULT_ENDPOINT,\n debug: config.debug ?? false,\n disabled: config.disabled ?? !apiKey,\n batchSize: config.batchSize,\n flushIntervalMs: config.flushIntervalMs,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n}\n\n/**\n * Get environment variable (works in Node and edge)\n */\nfunction getEnvVar(name: string): string | undefined {\n if (typeof process !== 'undefined' && process.env) {\n return process.env[name];\n }\n return undefined;\n}\n","/**\n * Hono Integration\n *\n * Middleware for Hono framework (Cloudflare Workers, Deno, Bun, Node.js).\n * Uses executionCtx.waitUntil() when available for non-blocking flush.\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n * app.use(createMiddleware());\n */\n\nimport { flush } from '../core/config';\n\n// ─────────────────────────────────────────────────────────────\n// Types (minimal to avoid requiring hono as dependency)\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Execution context for edge runtimes (Cloudflare Workers, Deno Deploy)\n */\nexport interface ExecutionContext {\n waitUntil(promise: Promise<unknown>): void;\n passThroughOnException(): void;\n}\n\n/**\n * Minimal Hono context type (avoids requiring hono as dependency)\n */\nexport interface HonoContext {\n req: {\n raw: Request;\n [key: string]: unknown;\n };\n res: Response | undefined;\n executionCtx?: ExecutionContext;\n [key: string]: unknown;\n}\n\n/**\n * Hono next function type\n */\nexport type HonoNextFunction = () => Promise<void>;\n\n/**\n * Hono middleware function type\n *\n * @param c - Hono context object\n * @param next - Next function to continue middleware chain\n */\nexport type HonoMiddleware = (c: HonoContext, next: HonoNextFunction) => Promise<void>;\n\n// ─────────────────────────────────────────────────────────────\n// Middleware\n// ─────────────────────────────────────────────────────────────\n\n/**\n * Create Hono middleware for automatic trace flushing\n *\n * On Cloudflare Workers/Deno Deploy: uses executionCtx.waitUntil() for non-blocking flush\n * On Node.js/Bun: flushes after response (fire-and-forget)\n *\n * @returns Hono middleware function\n *\n * @example\n * import { Hono } from 'hono';\n * import { createMiddleware } from '@lelemondev/sdk/hono';\n *\n * const app = new Hono();\n *\n * // Global middleware\n * app.use(createMiddleware());\n *\n * app.post('/chat', async (c) => {\n * const openai = observe(new OpenAI());\n * const result = await openai.chat.completions.create({...});\n * return c.json(result);\n * });\n *\n * export default app;\n */\nexport function createMiddleware(): HonoMiddleware {\n return async (c, next) => {\n await next();\n\n // Use waitUntil if available (Cloudflare Workers, Deno Deploy)\n if (c.executionCtx?.waitUntil) {\n c.executionCtx.waitUntil(flush());\n } else {\n // Fire-and-forget for Node.js/Bun\n flush().catch(() => {});\n }\n };\n}\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -28,6 +28,27 @@ interface ObserveOptions {
|
|
|
28
28
|
/** Tags for filtering */
|
|
29
29
|
tags?: string[];
|
|
30
30
|
}
|
|
31
|
+
type SpanType = 'llm' | 'tool' | 'retrieval' | 'custom';
|
|
32
|
+
interface CaptureSpanOptions {
|
|
33
|
+
/** Span type */
|
|
34
|
+
type: SpanType;
|
|
35
|
+
/** Span name (tool name, retrieval source, custom name) */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Input data */
|
|
38
|
+
input: unknown;
|
|
39
|
+
/** Output data */
|
|
40
|
+
output: unknown;
|
|
41
|
+
/** Duration in milliseconds */
|
|
42
|
+
durationMs: number;
|
|
43
|
+
/** Status */
|
|
44
|
+
status?: 'success' | 'error';
|
|
45
|
+
/** Error message if status is 'error' */
|
|
46
|
+
errorMessage?: string;
|
|
47
|
+
/** Tool call ID (for linking tool results) */
|
|
48
|
+
toolCallId?: string;
|
|
49
|
+
/** Custom metadata */
|
|
50
|
+
metadata?: Record<string, unknown>;
|
|
51
|
+
}
|
|
31
52
|
|
|
32
53
|
/**
|
|
33
54
|
* Global Configuration
|
|
@@ -85,4 +106,37 @@ declare function observe<T>(client: T, options?: ObserveOptions): T;
|
|
|
85
106
|
*/
|
|
86
107
|
declare function createObserve(defaultOptions: ObserveOptions): <T>(client: T, options?: ObserveOptions) => T;
|
|
87
108
|
|
|
88
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Capture Module
|
|
111
|
+
*
|
|
112
|
+
* Handles trace capture and batching.
|
|
113
|
+
* Called by providers to record LLM calls.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Manually capture a span (tool call, retrieval, custom)
|
|
118
|
+
* Use this when auto-detection doesn't cover your use case
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // Capture a tool call
|
|
122
|
+
* captureSpan({
|
|
123
|
+
* type: 'tool',
|
|
124
|
+
* name: 'get_weather',
|
|
125
|
+
* input: { location: 'San Francisco' },
|
|
126
|
+
* output: { temperature: 72, conditions: 'sunny' },
|
|
127
|
+
* durationMs: 150,
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Capture a retrieval/RAG operation
|
|
132
|
+
* captureSpan({
|
|
133
|
+
* type: 'retrieval',
|
|
134
|
+
* name: 'vector_search',
|
|
135
|
+
* input: { query: 'user question', k: 5 },
|
|
136
|
+
* output: { documents: [...] },
|
|
137
|
+
* durationMs: 50,
|
|
138
|
+
* });
|
|
139
|
+
*/
|
|
140
|
+
declare function captureSpan(options: CaptureSpanOptions): void;
|
|
141
|
+
|
|
142
|
+
export { type CaptureSpanOptions, type LelemonConfig, type ObserveOptions, type ProviderName, type SpanType, captureSpan, createObserve, flush, init, isEnabled, observe };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,27 @@ interface ObserveOptions {
|
|
|
28
28
|
/** Tags for filtering */
|
|
29
29
|
tags?: string[];
|
|
30
30
|
}
|
|
31
|
+
type SpanType = 'llm' | 'tool' | 'retrieval' | 'custom';
|
|
32
|
+
interface CaptureSpanOptions {
|
|
33
|
+
/** Span type */
|
|
34
|
+
type: SpanType;
|
|
35
|
+
/** Span name (tool name, retrieval source, custom name) */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Input data */
|
|
38
|
+
input: unknown;
|
|
39
|
+
/** Output data */
|
|
40
|
+
output: unknown;
|
|
41
|
+
/** Duration in milliseconds */
|
|
42
|
+
durationMs: number;
|
|
43
|
+
/** Status */
|
|
44
|
+
status?: 'success' | 'error';
|
|
45
|
+
/** Error message if status is 'error' */
|
|
46
|
+
errorMessage?: string;
|
|
47
|
+
/** Tool call ID (for linking tool results) */
|
|
48
|
+
toolCallId?: string;
|
|
49
|
+
/** Custom metadata */
|
|
50
|
+
metadata?: Record<string, unknown>;
|
|
51
|
+
}
|
|
31
52
|
|
|
32
53
|
/**
|
|
33
54
|
* Global Configuration
|
|
@@ -85,4 +106,37 @@ declare function observe<T>(client: T, options?: ObserveOptions): T;
|
|
|
85
106
|
*/
|
|
86
107
|
declare function createObserve(defaultOptions: ObserveOptions): <T>(client: T, options?: ObserveOptions) => T;
|
|
87
108
|
|
|
88
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Capture Module
|
|
111
|
+
*
|
|
112
|
+
* Handles trace capture and batching.
|
|
113
|
+
* Called by providers to record LLM calls.
|
|
114
|
+
*/
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Manually capture a span (tool call, retrieval, custom)
|
|
118
|
+
* Use this when auto-detection doesn't cover your use case
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // Capture a tool call
|
|
122
|
+
* captureSpan({
|
|
123
|
+
* type: 'tool',
|
|
124
|
+
* name: 'get_weather',
|
|
125
|
+
* input: { location: 'San Francisco' },
|
|
126
|
+
* output: { temperature: 72, conditions: 'sunny' },
|
|
127
|
+
* durationMs: 150,
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Capture a retrieval/RAG operation
|
|
132
|
+
* captureSpan({
|
|
133
|
+
* type: 'retrieval',
|
|
134
|
+
* name: 'vector_search',
|
|
135
|
+
* input: { query: 'user question', k: 5 },
|
|
136
|
+
* output: { documents: [...] },
|
|
137
|
+
* durationMs: 50,
|
|
138
|
+
* });
|
|
139
|
+
*/
|
|
140
|
+
declare function captureSpan(options: CaptureSpanOptions): void;
|
|
141
|
+
|
|
142
|
+
export { type CaptureSpanOptions, type LelemonConfig, type ObserveOptions, type ProviderName, type SpanType, captureSpan, createObserve, flush, init, isEnabled, observe };
|
package/dist/index.js
CHANGED
|
@@ -205,7 +205,7 @@ var Transport = class {
|
|
|
205
205
|
// src/core/config.ts
|
|
206
206
|
var globalConfig = {};
|
|
207
207
|
var globalTransport = null;
|
|
208
|
-
var DEFAULT_ENDPOINT = "https://lelemon.dev";
|
|
208
|
+
var DEFAULT_ENDPOINT = "https://www.lelemon.dev";
|
|
209
209
|
function init(config = {}) {
|
|
210
210
|
globalConfig = config;
|
|
211
211
|
if (config.debug) {
|
|
@@ -359,6 +359,74 @@ function captureError(params) {
|
|
|
359
359
|
traceCaptureError(params.provider, err instanceof Error ? err : new Error(String(err)));
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
|
+
function captureSpan(options) {
|
|
363
|
+
try {
|
|
364
|
+
const transport = getTransport();
|
|
365
|
+
if (!transport.isEnabled()) {
|
|
366
|
+
debug("Transport disabled, skipping span capture");
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const context = getGlobalContext();
|
|
370
|
+
const request = {
|
|
371
|
+
spanType: options.type,
|
|
372
|
+
name: options.name,
|
|
373
|
+
provider: "unknown",
|
|
374
|
+
// Manual spans don't have a provider
|
|
375
|
+
model: options.name,
|
|
376
|
+
// Use name as model for compatibility
|
|
377
|
+
input: sanitizeInput(options.input),
|
|
378
|
+
output: sanitizeOutput(options.output),
|
|
379
|
+
inputTokens: 0,
|
|
380
|
+
outputTokens: 0,
|
|
381
|
+
durationMs: options.durationMs,
|
|
382
|
+
status: options.status || "success",
|
|
383
|
+
errorMessage: options.errorMessage,
|
|
384
|
+
streaming: false,
|
|
385
|
+
sessionId: context.sessionId,
|
|
386
|
+
userId: context.userId,
|
|
387
|
+
toolCallId: options.toolCallId,
|
|
388
|
+
metadata: { ...context.metadata, ...options.metadata },
|
|
389
|
+
tags: context.tags
|
|
390
|
+
};
|
|
391
|
+
debug(`Span captured: ${options.type}/${options.name}`, { durationMs: options.durationMs });
|
|
392
|
+
transport.enqueue(request);
|
|
393
|
+
} catch (err) {
|
|
394
|
+
traceCaptureError("unknown", err instanceof Error ? err : new Error(String(err)));
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function captureToolSpans(toolCalls, provider) {
|
|
398
|
+
for (const tool of toolCalls) {
|
|
399
|
+
try {
|
|
400
|
+
const transport = getTransport();
|
|
401
|
+
if (!transport.isEnabled()) continue;
|
|
402
|
+
const context = getGlobalContext();
|
|
403
|
+
const request = {
|
|
404
|
+
spanType: "tool",
|
|
405
|
+
name: tool.name,
|
|
406
|
+
provider,
|
|
407
|
+
model: tool.name,
|
|
408
|
+
input: sanitizeInput(tool.input),
|
|
409
|
+
output: null,
|
|
410
|
+
// Tool result will come later
|
|
411
|
+
inputTokens: 0,
|
|
412
|
+
outputTokens: 0,
|
|
413
|
+
durationMs: 0,
|
|
414
|
+
// Duration unknown at this point
|
|
415
|
+
status: "success",
|
|
416
|
+
streaming: false,
|
|
417
|
+
sessionId: context.sessionId,
|
|
418
|
+
userId: context.userId,
|
|
419
|
+
toolCallId: tool.id,
|
|
420
|
+
metadata: { ...context.metadata, toolUseDetected: true },
|
|
421
|
+
tags: context.tags
|
|
422
|
+
};
|
|
423
|
+
debug(`Tool span captured: ${tool.name}`, { toolCallId: tool.id });
|
|
424
|
+
transport.enqueue(request);
|
|
425
|
+
} catch (err) {
|
|
426
|
+
traceCaptureError(provider, err instanceof Error ? err : new Error(String(err)));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
362
430
|
var MAX_STRING_LENGTH = 1e5;
|
|
363
431
|
var SENSITIVE_KEYS = ["api_key", "apikey", "password", "secret", "token", "authorization"];
|
|
364
432
|
function sanitizeInput(input) {
|
|
@@ -770,7 +838,8 @@ function wrapMessagesCreate(originalFn) {
|
|
|
770
838
|
return wrapStream2(response, request, startTime);
|
|
771
839
|
}
|
|
772
840
|
const durationMs = Date.now() - startTime;
|
|
773
|
-
const
|
|
841
|
+
const messageResponse = response;
|
|
842
|
+
const extracted = extractMessageResponse(messageResponse);
|
|
774
843
|
captureTrace({
|
|
775
844
|
provider: PROVIDER_NAME2,
|
|
776
845
|
model: request.model || extracted.model || "unknown",
|
|
@@ -782,6 +851,10 @@ function wrapMessagesCreate(originalFn) {
|
|
|
782
851
|
status: "success",
|
|
783
852
|
streaming: false
|
|
784
853
|
});
|
|
854
|
+
const toolCalls = extractToolCalls(messageResponse);
|
|
855
|
+
if (toolCalls.length > 0) {
|
|
856
|
+
captureToolSpans(toolCalls, PROVIDER_NAME2);
|
|
857
|
+
}
|
|
785
858
|
return response;
|
|
786
859
|
} catch (error) {
|
|
787
860
|
const durationMs = Date.now() - startTime;
|
|
@@ -834,6 +907,8 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
834
907
|
let outputTokens = 0;
|
|
835
908
|
let model = request.model || "unknown";
|
|
836
909
|
let captured = false;
|
|
910
|
+
const toolCalls = [];
|
|
911
|
+
let currentToolIndex = null;
|
|
837
912
|
const wrappedIterator = async function* () {
|
|
838
913
|
try {
|
|
839
914
|
for await (const event of originalStream) {
|
|
@@ -846,6 +921,34 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
846
921
|
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
847
922
|
chunks.push(event.delta.text);
|
|
848
923
|
}
|
|
924
|
+
if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
|
|
925
|
+
const block = event.content_block;
|
|
926
|
+
if (block.id && block.name) {
|
|
927
|
+
currentToolIndex = event.index ?? toolCalls.length;
|
|
928
|
+
toolCalls.push({
|
|
929
|
+
id: block.id,
|
|
930
|
+
name: block.name,
|
|
931
|
+
input: block.input ?? {},
|
|
932
|
+
inputJson: ""
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (event.type === "content_block_delta" && event.delta?.partial_json && currentToolIndex !== null) {
|
|
937
|
+
const tool = toolCalls.find((_, i) => i === currentToolIndex);
|
|
938
|
+
if (tool) {
|
|
939
|
+
tool.inputJson += event.delta.partial_json;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (event.type === "content_block_stop" && currentToolIndex !== null) {
|
|
943
|
+
const tool = toolCalls[currentToolIndex];
|
|
944
|
+
if (tool && tool.inputJson) {
|
|
945
|
+
try {
|
|
946
|
+
tool.input = JSON.parse(tool.inputJson);
|
|
947
|
+
} catch {
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
currentToolIndex = null;
|
|
951
|
+
}
|
|
849
952
|
if (event.type === "message_delta" && event.usage) {
|
|
850
953
|
outputTokens = event.usage.output_tokens || 0;
|
|
851
954
|
}
|
|
@@ -880,6 +983,12 @@ function wrapAnthropicStream(stream, request, startTime) {
|
|
|
880
983
|
status: "success",
|
|
881
984
|
streaming: true
|
|
882
985
|
});
|
|
986
|
+
if (toolCalls.length > 0) {
|
|
987
|
+
captureToolSpans(
|
|
988
|
+
toolCalls.map((t) => ({ id: t.id, name: t.name, input: t.input })),
|
|
989
|
+
PROVIDER_NAME2
|
|
990
|
+
);
|
|
991
|
+
}
|
|
883
992
|
}
|
|
884
993
|
}
|
|
885
994
|
};
|
|
@@ -898,6 +1007,8 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
898
1007
|
let outputTokens = 0;
|
|
899
1008
|
let model = request.model || "unknown";
|
|
900
1009
|
let error = null;
|
|
1010
|
+
const toolCalls = [];
|
|
1011
|
+
let currentToolIndex = null;
|
|
901
1012
|
try {
|
|
902
1013
|
for await (const event of stream) {
|
|
903
1014
|
if (event.type === "message_start" && event.message) {
|
|
@@ -909,6 +1020,34 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
909
1020
|
if (event.type === "content_block_delta" && event.delta?.text) {
|
|
910
1021
|
chunks.push(event.delta.text);
|
|
911
1022
|
}
|
|
1023
|
+
if (event.type === "content_block_start" && event.content_block?.type === "tool_use") {
|
|
1024
|
+
const block = event.content_block;
|
|
1025
|
+
if (block.id && block.name) {
|
|
1026
|
+
currentToolIndex = event.index ?? toolCalls.length;
|
|
1027
|
+
toolCalls.push({
|
|
1028
|
+
id: block.id,
|
|
1029
|
+
name: block.name,
|
|
1030
|
+
input: block.input ?? {},
|
|
1031
|
+
inputJson: ""
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (event.type === "content_block_delta" && event.delta?.partial_json && currentToolIndex !== null) {
|
|
1036
|
+
const tool = toolCalls.find((_, i) => i === currentToolIndex);
|
|
1037
|
+
if (tool) {
|
|
1038
|
+
tool.inputJson += event.delta.partial_json;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (event.type === "content_block_stop" && currentToolIndex !== null) {
|
|
1042
|
+
const tool = toolCalls[currentToolIndex];
|
|
1043
|
+
if (tool && tool.inputJson) {
|
|
1044
|
+
try {
|
|
1045
|
+
tool.input = JSON.parse(tool.inputJson);
|
|
1046
|
+
} catch {
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
currentToolIndex = null;
|
|
1050
|
+
}
|
|
912
1051
|
if (event.type === "message_delta" && event.usage) {
|
|
913
1052
|
outputTokens = event.usage.output_tokens || 0;
|
|
914
1053
|
}
|
|
@@ -940,6 +1079,12 @@ async function* wrapStream2(stream, request, startTime) {
|
|
|
940
1079
|
status: "success",
|
|
941
1080
|
streaming: true
|
|
942
1081
|
});
|
|
1082
|
+
if (toolCalls.length > 0) {
|
|
1083
|
+
captureToolSpans(
|
|
1084
|
+
toolCalls.map((t) => ({ id: t.id, name: t.name, input: t.input })),
|
|
1085
|
+
PROVIDER_NAME2
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
943
1088
|
}
|
|
944
1089
|
}
|
|
945
1090
|
}
|
|
@@ -971,6 +1116,22 @@ function extractTokens2(response) {
|
|
|
971
1116
|
return null;
|
|
972
1117
|
}
|
|
973
1118
|
}
|
|
1119
|
+
function extractToolCalls(response) {
|
|
1120
|
+
try {
|
|
1121
|
+
if (!response.content || !Array.isArray(response.content)) {
|
|
1122
|
+
return [];
|
|
1123
|
+
}
|
|
1124
|
+
return response.content.filter(
|
|
1125
|
+
(block) => block.type === "tool_use" && !!block.id && !!block.name
|
|
1126
|
+
).map((block) => ({
|
|
1127
|
+
id: block.id,
|
|
1128
|
+
name: block.name,
|
|
1129
|
+
input: block.input ?? {}
|
|
1130
|
+
}));
|
|
1131
|
+
} catch {
|
|
1132
|
+
return [];
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
974
1135
|
|
|
975
1136
|
// src/providers/bedrock.ts
|
|
976
1137
|
var PROVIDER_NAME3 = "bedrock";
|
|
@@ -1037,6 +1198,10 @@ async function handleConverse(send, command) {
|
|
|
1037
1198
|
latencyMs: response.metrics?.latencyMs
|
|
1038
1199
|
}
|
|
1039
1200
|
});
|
|
1201
|
+
const toolCalls = extractToolCalls2(response);
|
|
1202
|
+
if (toolCalls.length > 0) {
|
|
1203
|
+
captureToolSpans(toolCalls, PROVIDER_NAME3);
|
|
1204
|
+
}
|
|
1040
1205
|
return response;
|
|
1041
1206
|
} catch (error) {
|
|
1042
1207
|
captureError({
|
|
@@ -1079,11 +1244,26 @@ async function* wrapConverseStream(stream, input, startTime) {
|
|
|
1079
1244
|
let inputTokens = 0;
|
|
1080
1245
|
let outputTokens = 0;
|
|
1081
1246
|
let error = null;
|
|
1247
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
1082
1248
|
try {
|
|
1083
1249
|
for await (const event of stream) {
|
|
1084
1250
|
if (event.contentBlockDelta?.delta?.text) {
|
|
1085
1251
|
chunks.push(event.contentBlockDelta.delta.text);
|
|
1086
1252
|
}
|
|
1253
|
+
if (event.contentBlockStart?.start?.toolUse) {
|
|
1254
|
+
const tool = event.contentBlockStart.start.toolUse;
|
|
1255
|
+
toolCalls.set(event.contentBlockStart.contentBlockIndex, {
|
|
1256
|
+
id: tool.toolUseId,
|
|
1257
|
+
name: tool.name,
|
|
1258
|
+
inputJson: ""
|
|
1259
|
+
});
|
|
1260
|
+
}
|
|
1261
|
+
if (event.contentBlockDelta?.delta?.toolUse?.input) {
|
|
1262
|
+
const tool = toolCalls.get(event.contentBlockDelta.contentBlockIndex);
|
|
1263
|
+
if (tool) {
|
|
1264
|
+
tool.inputJson += event.contentBlockDelta.delta.toolUse.input;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1087
1267
|
if (event.metadata?.usage) {
|
|
1088
1268
|
inputTokens = event.metadata.usage.inputTokens || 0;
|
|
1089
1269
|
outputTokens = event.metadata.usage.outputTokens || 0;
|
|
@@ -1116,6 +1296,19 @@ async function* wrapConverseStream(stream, input, startTime) {
|
|
|
1116
1296
|
status: "success",
|
|
1117
1297
|
streaming: true
|
|
1118
1298
|
});
|
|
1299
|
+
if (toolCalls.size > 0) {
|
|
1300
|
+
const tools = Array.from(toolCalls.values()).map((t) => {
|
|
1301
|
+
let parsedInput = {};
|
|
1302
|
+
try {
|
|
1303
|
+
if (t.inputJson) {
|
|
1304
|
+
parsedInput = JSON.parse(t.inputJson);
|
|
1305
|
+
}
|
|
1306
|
+
} catch {
|
|
1307
|
+
}
|
|
1308
|
+
return { id: t.id, name: t.name, input: parsedInput };
|
|
1309
|
+
});
|
|
1310
|
+
captureToolSpans(tools, PROVIDER_NAME3);
|
|
1311
|
+
}
|
|
1119
1312
|
}
|
|
1120
1313
|
}
|
|
1121
1314
|
}
|
|
@@ -1240,6 +1433,23 @@ function extractConverseOutput(response) {
|
|
|
1240
1433
|
hasToolUse
|
|
1241
1434
|
};
|
|
1242
1435
|
}
|
|
1436
|
+
function extractToolCalls2(response) {
|
|
1437
|
+
try {
|
|
1438
|
+
const content = response.output?.message?.content;
|
|
1439
|
+
if (!content || !Array.isArray(content)) {
|
|
1440
|
+
return [];
|
|
1441
|
+
}
|
|
1442
|
+
return content.filter(
|
|
1443
|
+
(block) => !!block.toolUse && !!block.toolUse.toolUseId && !!block.toolUse.name
|
|
1444
|
+
).map((block) => ({
|
|
1445
|
+
id: block.toolUse.toolUseId,
|
|
1446
|
+
name: block.toolUse.name,
|
|
1447
|
+
input: block.toolUse.input ?? {}
|
|
1448
|
+
}));
|
|
1449
|
+
} catch {
|
|
1450
|
+
return [];
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1243
1453
|
function parseInvokeModelBody(body) {
|
|
1244
1454
|
try {
|
|
1245
1455
|
const text = new TextDecoder().decode(body);
|
|
@@ -1909,6 +2119,7 @@ function createObserve(defaultOptions) {
|
|
|
1909
2119
|
};
|
|
1910
2120
|
}
|
|
1911
2121
|
|
|
2122
|
+
exports.captureSpan = captureSpan;
|
|
1912
2123
|
exports.createObserve = createObserve;
|
|
1913
2124
|
exports.flush = flush;
|
|
1914
2125
|
exports.init = init;
|