@agimon-ai/log-sink-mcp 0.24.4 → 0.25.1

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/README.md CHANGED
@@ -7,8 +7,9 @@ AI-powered log analysis MCP server with HTTP ingestion and SQLite storage.
7
7
  `log-sink-mcp` provides a complete log analysis solution for AI assistants like Claude. It combines:
8
8
 
9
9
  - **HTTP Server**: REST endpoint for log ingestion from any application
10
- - **MCP Server**: 4 application-focused tools for searching/filtering, tracing, and inspecting logs
10
+ - **MCP Server**: 5 application-focused tools for searching/filtering, tracing, and inspecting logs
11
11
  - **CLI Analysis Commands**: Local shell commands for deeper error and agent-issue analysis
12
+ - **Pi Extension**: Ships a Pi extension that exports the agent's own session telemetry into the sink
12
13
  - **SQLite Database**: Fast local storage with FTS5 full-text search plus cached local embeddings
13
14
  - **Real-time Analysis**: Query logs, trace distributed requests, analyze error patterns
14
15
 
@@ -17,7 +18,8 @@ Perfect for debugging, monitoring, and understanding application behavior throug
17
18
  ## Features
18
19
 
19
20
  - ✅ **HTTP Log Ingestion**: POST logs from any application via REST API
20
- - ✅ **4 MCP Tools**: Search/filter, trace, and inspect stats/services
21
+ - ✅ **5 MCP Tools**: Search/filter, trace, agent-issue analysis, and inspect stats/services
22
+ - ✅ **Agent Telemetry**: Pi extension records prompts, turns, tool calls, token usage, and cost
21
23
  - ✅ **Hybrid Search**: FTS5-powered search plus optional local semantic retrieval across messages and errors
22
24
  - ✅ **Distributed Tracing**: Timeline view for trace IDs and span relationships
23
25
  - ✅ **Error Analysis**: Pattern detection and error categorization
@@ -43,7 +45,7 @@ Perfect for debugging, monitoring, and understanding application behavior throug
43
45
 
44
46
  ┌──────────────┐ MCP Protocol ┌─────────────────┐
45
47
  │ Claude / │ <─────────────────────> │ MCP Server │
46
- │ AI Agent │ 4 App Log Tools │ (stdio) │
48
+ │ AI Agent │ 5 App Log Tools │ (stdio) │
47
49
  └──────────────┘ └────────┬────────┘
48
50
 
49
51
 
@@ -319,10 +321,13 @@ Search and filter log entries. Without `query`/`searchQuery`, it behaves as a st
319
321
  - `traceId?`: string - Filter by trace ID
320
322
  - `spanId?`: string - Filter by span ID
321
323
  - `errorType?`: string - Filter by error type
322
- - `sessionId?`: string - Filter by agent session ID
323
- - `workflowRunId?`: string - Filter by workflow run ID
324
- - `workflowName?`: string - Filter by workflow name
325
- - `jobName?`: string - Filter by workflow job name
324
+ - `sessionId?` / `parentSessionId?`: string - Filter by agent session ID or its parent
325
+ - `agentName?`: string - Filter by agent name
326
+ - `workflowRunId?` / `workflowRunKey?` / `workflowId?`: string - Filter by workflow run ID, stable run key, or workflow file ID
327
+ - `workflowName?` / `workflowWorkspace?`: string - Filter by workflow name or workspace
328
+ - `jobName?` / `jobId?`: string - Filter by workflow job name or job execution ID
329
+ - `stepName?` / `phase?`: string - Filter by workflow step name or phase
330
+ - `signalType?`: string - `log` or `span`
326
331
  - `startTime?`: string - ISO 8601 start time filter
327
332
  - `endTime?`: string - ISO 8601 end time filter
328
333
  - `limit?`: number - Maximum results (default: 100)
@@ -336,7 +341,30 @@ Find error logs from user-service that mention "database timeout"
336
341
 
337
342
  ---
338
343
 
339
- ### 2. `get_trace_timeline`
344
+ ### 2. `analyze_agent_issues`
345
+
346
+ Detect and aggregate agent-run problems for reviewing agent performance and improving the harness: failed tool calls, API errors, refusals, retries exhausted, rejected tools, and error logs. Unlike error-severity analysis, this understands agent event semantics, so it also catches warning-level returned tool errors and info-level tool results carrying `success=false`.
347
+
348
+ **Parameters:**
349
+ - `sessionId?` / `parentSessionId?`: string - Scope to one agent launch
350
+ - `agentName?`: string - Scope to one agent identity
351
+ - `service?`: string or string[] - Scope by agent/service name (for example `claude-code`, `codex`)
352
+ - `workflowRunId?` / `workflowRunKey?` / `workflowName?` / `workflowWorkspace?`: string - Scope by workflow
353
+ - `jobName?` / `jobId?` / `stepName?` / `phase?`: string - Scope within a run
354
+ - `startTime?` / `endTime?`: string - ISO 8601 analysis window
355
+ - `limit?`: number - Maximum issue samples returned (default: 100)
356
+ - `scanLimit?`: number - Maximum matching records scanned (default: 50000); the response reports when this truncates the window
357
+
358
+ **Example:**
359
+ ```
360
+ Why did the last agent session keep failing its edits?
361
+ ```
362
+
363
+ **Returns:** Counts by category, tool, and error type, plus sample issues carrying the tool, input, and error context needed to diagnose them.
364
+
365
+ ---
366
+
367
+ ### 3. `get_trace_timeline`
340
368
 
341
369
  Get chronological timeline for a distributed trace.
342
370
 
@@ -352,22 +380,25 @@ Show me the trace timeline for trace ID a1b2c3d4e5f6789012345678901234ab
352
380
 
353
381
  ---
354
382
 
355
- ### 3. `get_log_stats`
383
+ ### 4. `get_log_stats`
356
384
 
357
- Get statistics grouped by log level.
385
+ Get aggregate statistics, grouped along whichever dimension you ask for.
358
386
 
359
- **Parameters:** None
387
+ **Parameters:**
388
+ - `groupBy?`: string - `both` (default), `level`, `service`, `agent`, `workflow`, `job`, or `signal`
389
+ - `signalType?`: string - `log` (default), `span`, or `all`
390
+ - `startTime?` / `endTime?`: string - ISO 8601 window
360
391
 
361
392
  **Example:**
362
393
  ```
363
394
  Show me log statistics
364
395
  ```
365
396
 
366
- **Returns:** Count per log level (debug, info, warn, error), total count.
397
+ **Returns:** Counts per group, plus a total.
367
398
 
368
399
  ---
369
400
 
370
- ### 4. `get_services`
401
+ ### 5. `get_services`
371
402
 
372
403
  List all unique services that have logged.
373
404
 
@@ -380,6 +411,44 @@ What services are logging to the database?
380
411
 
381
412
  **Returns:** Array of service names with log counts.
382
413
 
414
+ ## Pi extension
415
+
416
+ The package ships a [Pi](https://github.com/earendil-works/pi) extension, declared in the `pi.extensions` field of `package.json` and loaded when the package is installed as a Pi package. It registers no commands and no tools. It subscribes to Pi's session events and exports them as OTLP logs under the service name `pi`, so the agent's own behaviour lands in the same database as your application's.
417
+
418
+ | Pi event | Record | Level |
419
+ |---|---|---|
420
+ | `session_start` | `pi.session.started` | info |
421
+ | `before_agent_start` | `pi.user_prompt` | info |
422
+ | `agent_start` | `pi.agent.started` | info |
423
+ | `turn_start` | `pi.turn.started` | debug |
424
+ | `turn_end` | `pi.turn.finished` | info |
425
+ | `tool_execution_start` | `pi.tool_call` | debug |
426
+ | `tool_execution_end` | `pi.tool_result` | info |
427
+ | `after_provider_response` | `pi.api_response`, or `pi.api_error` on status 400 and above | debug / error |
428
+ | `model_select` | `pi.model.selected` | info |
429
+ | `agent_end` | `pi.agent.finished` | info |
430
+ | `agent_settled` | `pi.agent.settled` | debug |
431
+ | `session_shutdown` | `pi.session.finished` | info |
432
+
433
+ Every record carries the session ID, cwd, mode, thinking level, and selected model. `pi.turn.finished` adds the standard `gen_ai.usage.*` attributes: input, output, cache read, cache write, reasoning, total tokens, and cost. `pi.tool_result` adds the tool name and its duration in milliseconds.
434
+
435
+ Two things are deliberate about what it does not do:
436
+
437
+ - **Prompts and tool payloads are omitted by default.** Set `AGENT_OTEL_REDACT=0` to include `user.prompt`, `tool.input`, and `tool.result`.
438
+ - **Telemetry is dropped rather than written to disk when no sink is reachable.** Endpoint discovery health-checks a running server; if there is none, the file backend is shut down instead of quietly filling a log directory. Set `LOG_SINK_PI_FILE_FALLBACK=1` to keep it.
439
+
440
+ Failures in the extension itself warn to the console and never propagate: telemetry that breaks the agent it is measuring is worse than no telemetry.
441
+
442
+ Once a session has run, query it like any other service:
443
+
444
+ ```bash
445
+ # What went wrong in this agent session
446
+ log-sink-mcp logs agent-issues --session-id <session-id>
447
+
448
+ # Token spend and per-tool consumption for the session
449
+ log-sink-mcp logs metrics --service pi --group-by agent
450
+ ```
451
+
383
452
  ## Integration Examples
384
453
 
385
454
  ### Pino Logger
@@ -548,7 +617,7 @@ bun run src/cli.ts mcp-serve --type sse --port 3002
548
617
 
549
618
  #### `logs` command
550
619
 
551
- Run log analysis capabilities directly from the shell. The deeper `analyze-errors` and `agent-issues` commands are CLI-only so the MCP server stays focused on application log inspection.
620
+ Run log analysis capabilities directly from the shell. Most subcommands mirror an MCP tool; `analyze-errors` and `clear` are CLI-only.
552
621
 
553
622
  ```bash
554
623
  bun run src/cli.ts logs <subcommand> [options]
@@ -560,6 +629,7 @@ Subcommands:
560
629
  - `search --mode hybrid`: Default hybrid search across FTS5 and semantic embeddings
561
630
  - `trace`: Equivalent to `get_trace_timeline`
562
631
  - `analyze-errors`: CLI-only grouped error analysis
632
+ - `agent-issues`: Equivalent to `analyze_agent_issues`
563
633
  - `stats`: Equivalent to `get_log_stats`
564
634
  - `metrics`: Workflow, token, failure, and per-tool consumption metrics
565
635
  - `services`: Equivalent to `get_services`
@@ -603,7 +673,22 @@ bun run src/cli.ts logs services
603
673
 
604
674
  ### Environment Variables
605
675
 
606
- None required. All configuration via CLI flags.
676
+ None are required: the server and its CLI are configured entirely through flags. These apply to the telemetry side, meaning the Pi extension and any process using `@agimon-ai/log-sink-mcp/telemetry/node`.
677
+
678
+ | Variable | Effect |
679
+ |---|---|
680
+ | `LOG_SINK_ENDPOINT` | Send to this log-sink instead of discovering a running one |
681
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Standard OTLP endpoint; the signal-specific `_LOGS_` and `_TRACES_` forms take precedence, and any of them override discovery |
682
+ | `OTEL_EXPORTER_OTLP_HEADERS` | Extra export headers; `_LOGS_` and `_TRACES_` variants apply per signal |
683
+ | `OTEL_EXPORTER_OTLP_TIMEOUT` | Export timeout in milliseconds; `_LOGS_` and `_TRACES_` variants apply per signal |
684
+ | `OTEL_SDK_DISABLED` | Disable telemetry entirely |
685
+ | `AGENT_TELEMETRY_DISABLED=1` | Disable the Pi extension only |
686
+ | `AGENT_OTEL_TRACES` | `1`, `true`, or `yes` to export spans as well as logs |
687
+ | `AGENT_OTEL_REDACT=0` | Include prompts, tool inputs, and tool results |
688
+ | `LOG_SINK_PI_FILE_FALLBACK=1` | Let the Pi extension write to files when no sink is reachable |
689
+ | `LOG_SINK_FILE_MAX_BYTES`, `LOG_SINK_FILE_MAX_FILES` | Rotation limits for the file backend |
690
+
691
+ Telemetry is tagged for later filtering from the environment it runs in. `AGENT_SESSION_ID` and `PARENT_AGENT_SESSION_ID` scope records to an agent launch, and `WORKFLOW_RUN_ID`, `WORKFLOW_RUN_KEY`, `WORKFLOW_ID`, `WORKFLOW_NAME`, `WORKFLOW_WORKSPACE`, `WORKFLOW_JOB_ID`, `WORKFLOW_JOB_NAME`, `WORKFLOW_STEP_NAME`, `WORKFLOW_PHASE`, and `WORKFLOW_RUNNER` scope them to a workflow run. Each becomes an ingest header and then a queryable field, which is what makes `--workflow-run-id` and `--session-id` work across the CLI and MCP tools.
607
692
 
608
693
  ## Development
609
694
 
@@ -628,8 +713,15 @@ log-sink-mcp/
628
713
  │ ├── cli.ts # CLI entry point
629
714
  │ ├── commands/ # CLI commands
630
715
  │ │ ├── http-serve.ts # HTTP server command
631
- │ │ └── mcp-serve.ts # MCP server command
716
+ │ │ ├── mcp-serve.ts # MCP server command
717
+ │ │ ├── logs.ts # Log analysis subcommands
718
+ │ │ └── claude-hook.ts # Claude Code hook context command
632
719
  │ ├── container/ # InversifyJS DI container
720
+ │ ├── extensions/ # Pi extension
721
+ │ │ ├── pi.ts # Extension entry point
722
+ │ │ └── piTelemetry.ts # Pi session event to OTLP mapping
723
+ │ ├── telemetry/
724
+ │ │ └── node.ts # Node OTLP setup, endpoint discovery, file fallback
633
725
  │ ├── models/ # Drizzle schemas
634
726
  │ │ └── schema.ts # Log table schema
635
727
  │ ├── server/
@@ -645,6 +737,7 @@ log-sink-mcp/
645
737
  │ │ ├── QueryLogsTool.ts # Compatibility wrapper for filter-only queries
646
738
  │ │ ├── GetTraceTimelineTool.ts
647
739
  │ │ ├── AnalyzeErrorsTool.ts
740
+ │ │ ├── AnalyzeAgentIssuesTool.ts
648
741
  │ │ ├── GetLogStatsTool.ts
649
742
  │ │ ├── GetServicesTool.ts
650
743
  │ │ └── ClearLogsTool.ts
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const e=require(`./node-9pwprHry.cjs`),t=require(`./stdio-Gb0mj6eo.cjs`);let n=require(`zod`),r=require(`node:fs`),i=require(`node:fs/promises`);i=e.u(i,1);let a=require(`node:path`),o=require(`node:url`),s=require(`@agimon-ai/foundation-port-registry`),c=require(`@agimon-ai/foundation-process-registry`),l=require(`commander`),u=require(`@hono/node-server`),d=require(`node:crypto`),f=require(`hono`),p=require(`hono/cors`),m=require(`hono-rate-limiter`),h=require(`hono/html`),g=require(`hono/jsx/jsx-runtime`);function _(e){return e.option(`--config <path>`,`Path to .logsink.yaml`).option(`--global`,`Use the global log-sink instance`).option(`--instance <scope>`,`Force log-sink instance: local or global`)}function v(e){let t=e.instance?.trim();if(e.global&&t&&t.toLowerCase()!==`global`)throw Error(`Use either --global or --instance local, not both`);return e.global?`global`:t}function y(t,n=e.s){t.config&&(process.env.LOG_SINK_CONFIG=t.config);let r=v(t);return r&&(process.env.LOG_SINK_INSTANCE=r),e.c({configPath:t.config,packageName:n})}const b=[`error`,`fatal`];function x(e){let t=e.trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}}function S(e){if(e==null)return`unknown`;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function C(e){return e.hook_event_name===`PostToolUseFailure`?`Current tool failure:\n- Tool: ${e.tool_name??`unknown tool`}\n- Error: ${S(e.error)}`:null}function w(e,t,n){let r=new Map;for(let t of e){let e=`${t.service}::${t.level}::${t.error_type??``}::${t.error_message??t.message}`,i=new Date(Number(t.created_at)).toISOString();r.has(e)||r.set(e,{key:e,count:0,service:t.service,level:t.level,errorType:t.error_type,errorMessage:t.error_message,message:t.message,firstSeen:i,lastSeen:i,traceIds:new Set,examples:[]});let a=r.get(e);a.count+=1,a.lastSeen=i,t.trace_id&&a.traceIds.add(t.trace_id),a.examples.length<n&&a.examples.push({id:t.id,timestamp:i,traceId:t.trace_id})}return Array.from(r.values()).sort((e,t)=>t.count-e.count||t.lastSeen.localeCompare(e.lastSeen)).slice(0,t)}function ee(e,t,n,r){let i=w(e,n,r),a=[];a.push(`Recent log errors (${e.length} new):`),t.tool_name&&a.push(`- Triggered after tool: ${t.tool_name}`);for(let[e,t]of i.entries()){a.push(`${e+1}. ${t.service} [${t.level}] x${t.count} ${t.errorType?`(${t.errorType}) `:``}${t.errorMessage??t.message}`),a.push(` First seen: ${t.firstSeen}`),a.push(` Last seen: ${t.lastSeen}`),t.traceIds.size>0&&a.push(` Trace IDs: ${Array.from(t.traceIds).slice(0,3).join(`, `)}`);for(let e of t.examples)a.push(` Example: ${e.timestamp} id=${e.id}${e.traceId?` trace=${e.traceId}`:``}`)}if(t.hook_event_name===`PostToolUseFailure`){let e=C(t);e&&a.push(``,e)}return a.join(`
2
+ const e=require(`./node-9pwprHry.cjs`),t=require(`./stdio-QFR4qcFs.cjs`);let n=require(`zod`),r=require(`node:fs`),i=require(`node:fs/promises`);i=e.u(i,1);let a=require(`node:path`),o=require(`node:url`),s=require(`@agimon-ai/foundation-port-registry`),c=require(`@agimon-ai/foundation-process-registry`),l=require(`commander`),u=require(`@hono/node-server`),d=require(`node:crypto`),f=require(`hono`),p=require(`hono/cors`),m=require(`hono-rate-limiter`),h=require(`hono/html`),g=require(`hono/jsx/jsx-runtime`);function _(e){return e.option(`--config <path>`,`Path to .logsink.yaml`).option(`--global`,`Use the global log-sink instance`).option(`--instance <scope>`,`Force log-sink instance: local or global`)}function v(e){let t=e.instance?.trim();if(e.global&&t&&t.toLowerCase()!==`global`)throw Error(`Use either --global or --instance local, not both`);return e.global?`global`:t}function y(t,n=e.s){t.config&&(process.env.LOG_SINK_CONFIG=t.config);let r=v(t);return r&&(process.env.LOG_SINK_INSTANCE=r),e.c({configPath:t.config,packageName:n})}const b=[`error`,`fatal`];function x(e){let t=e.trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}}function S(e){if(e==null)return`unknown`;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function C(e){return e.hook_event_name===`PostToolUseFailure`?`Current tool failure:\n- Tool: ${e.tool_name??`unknown tool`}\n- Error: ${S(e.error)}`:null}function w(e,t,n){let r=new Map;for(let t of e){let e=`${t.service}::${t.level}::${t.error_type??``}::${t.error_message??t.message}`,i=new Date(Number(t.created_at)).toISOString();r.has(e)||r.set(e,{key:e,count:0,service:t.service,level:t.level,errorType:t.error_type,errorMessage:t.error_message,message:t.message,firstSeen:i,lastSeen:i,traceIds:new Set,examples:[]});let a=r.get(e);a.count+=1,a.lastSeen=i,t.trace_id&&a.traceIds.add(t.trace_id),a.examples.length<n&&a.examples.push({id:t.id,timestamp:i,traceId:t.trace_id})}return Array.from(r.values()).sort((e,t)=>t.count-e.count||t.lastSeen.localeCompare(e.lastSeen)).slice(0,t)}function ee(e,t,n,r){let i=w(e,n,r),a=[];a.push(`Recent log errors (${e.length} new):`),t.tool_name&&a.push(`- Triggered after tool: ${t.tool_name}`);for(let[e,t]of i.entries()){a.push(`${e+1}. ${t.service} [${t.level}] x${t.count} ${t.errorType?`(${t.errorType}) `:``}${t.errorMessage??t.message}`),a.push(` First seen: ${t.firstSeen}`),a.push(` Last seen: ${t.lastSeen}`),t.traceIds.size>0&&a.push(` Trace IDs: ${Array.from(t.traceIds).slice(0,3).join(`, `)}`);for(let e of t.examples)a.push(` Example: ${e.timestamp} id=${e.id}${e.traceId?` trace=${e.traceId}`:``}`)}if(t.hook_event_name===`PostToolUseFailure`){let e=C(t);e&&a.push(``,e)}return a.join(`
3
3
  `)}function te(t){if(t.session_id?.trim())return(0,s.normalizeRepositoryPath)(e.l(t.cwd?.trim()||process.cwd()))}async function ne(t,n){let i=v(n);if(n.dbPath){let e=i===`global`?`global`:`local`;return(0,r.existsSync)(n.dbPath)?{dbPath:n.dbPath,scope:e}:void 0}let a={...process.env};n.config&&(a.LOG_SINK_CONFIG=n.config),i&&(a.LOG_SINK_INSTANCE=i);let o=e.c({configPath:n.config,cwd:t.cwd??process.cwd(),env:a,packageName:e.s}),c=new s.PortRegistryService(a.PORT_REGISTRY_PATH??s.DEFAULT_REGISTRY_PATH);try{let e=await c.getPort({repositoryPath:o.repositoryPath,serviceName:`log-sink-mcp-http`,serviceType:`tool`,environment:a.NODE_ENV||`development`}),t=e.record?.metadata?.dbPath;if(e.success&&typeof t==`string`&&t&&(0,r.existsSync)(t))return{dbPath:t,scope:o.scope}}catch{}return(0,r.existsSync)(o.dbPath)?{dbPath:o.dbPath,scope:o.scope}:void 0}async function re(e,t,n,r,i,a){let o=e.getSqliteClient(),s=Date.now()-n*60*1e3,c=``;if(t){let e=o.prepare(`
4
4
  SELECT id, created_at
5
5
  FROM logs
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"./stdio-DaqaONHT.mjs";import{d as p,f as m,p as h,u as g}from"./node-Bv2snZci.mjs";import{z as _}from"zod";import{existsSync as v,readFileSync as y}from"node:fs";import*as b from"node:fs/promises";import{dirname as x,join as ee}from"node:path";import{fileURLToPath as te}from"node:url";import{DEFAULT_PORT_RANGE as S,DEFAULT_REGISTRY_PATH as ne,PortRegistryService as re,normalizeRepositoryPath as ie}from"@agimon-ai/foundation-port-registry";import{createProcessLease as C,resolveSiblingRegistryPath as w}from"@agimon-ai/foundation-process-registry";import{Command as T,InvalidArgumentError as E}from"commander";import{serve as ae}from"@hono/node-server";import{createHash as oe}from"node:crypto";import{Hono as D}from"hono";import{cors as se}from"hono/cors";import{rateLimiter as ce}from"hono-rate-limiter";import{raw as le}from"hono/html";import{jsx as O,jsxs as k}from"hono/jsx/jsx-runtime";function A(e){return e.option(`--config <path>`,`Path to .logsink.yaml`).option(`--global`,`Use the global log-sink instance`).option(`--instance <scope>`,`Force log-sink instance: local or global`)}function j(e){let t=e.instance?.trim();if(e.global&&t&&t.toLowerCase()!==`global`)throw Error(`Use either --global or --instance local, not both`);return e.global?`global`:t}function M(e,t=p){e.config&&(process.env.LOG_SINK_CONFIG=e.config);let n=j(e);return n&&(process.env.LOG_SINK_INSTANCE=n),m({configPath:e.config,packageName:t})}const ue=[`error`,`fatal`];function de(e){let t=e.trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}}function fe(e){if(e==null)return`unknown`;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function pe(e){return e.hook_event_name===`PostToolUseFailure`?`Current tool failure:\n- Tool: ${e.tool_name??`unknown tool`}\n- Error: ${fe(e.error)}`:null}function me(e,t,n){let r=new Map;for(let t of e){let e=`${t.service}::${t.level}::${t.error_type??``}::${t.error_message??t.message}`,i=new Date(Number(t.created_at)).toISOString();r.has(e)||r.set(e,{key:e,count:0,service:t.service,level:t.level,errorType:t.error_type,errorMessage:t.error_message,message:t.message,firstSeen:i,lastSeen:i,traceIds:new Set,examples:[]});let a=r.get(e);a.count+=1,a.lastSeen=i,t.trace_id&&a.traceIds.add(t.trace_id),a.examples.length<n&&a.examples.push({id:t.id,timestamp:i,traceId:t.trace_id})}return Array.from(r.values()).sort((e,t)=>t.count-e.count||t.lastSeen.localeCompare(e.lastSeen)).slice(0,t)}function he(e,t,n,r){let i=me(e,n,r),a=[];a.push(`Recent log errors (${e.length} new):`),t.tool_name&&a.push(`- Triggered after tool: ${t.tool_name}`);for(let[e,t]of i.entries()){a.push(`${e+1}. ${t.service} [${t.level}] x${t.count} ${t.errorType?`(${t.errorType}) `:``}${t.errorMessage??t.message}`),a.push(` First seen: ${t.firstSeen}`),a.push(` Last seen: ${t.lastSeen}`),t.traceIds.size>0&&a.push(` Trace IDs: ${Array.from(t.traceIds).slice(0,3).join(`, `)}`);for(let e of t.examples)a.push(` Example: ${e.timestamp} id=${e.id}${e.traceId?` trace=${e.traceId}`:``}`)}if(t.hook_event_name===`PostToolUseFailure`){let e=pe(t);e&&a.push(``,e)}return a.join(`
2
+ import{a as e,c as t,d as n,f as r,i,l as a,n as o,o as s,p as c,r as l,s as u,t as d,u as f}from"./stdio-kDI4sBvK.mjs";import{d as p,f as m,p as h,u as g}from"./node-Bv2snZci.mjs";import{z as _}from"zod";import{existsSync as v,readFileSync as y}from"node:fs";import*as b from"node:fs/promises";import{dirname as x,join as ee}from"node:path";import{fileURLToPath as te}from"node:url";import{DEFAULT_PORT_RANGE as S,DEFAULT_REGISTRY_PATH as ne,PortRegistryService as re,normalizeRepositoryPath as ie}from"@agimon-ai/foundation-port-registry";import{createProcessLease as C,resolveSiblingRegistryPath as w}from"@agimon-ai/foundation-process-registry";import{Command as T,InvalidArgumentError as E}from"commander";import{serve as ae}from"@hono/node-server";import{createHash as oe}from"node:crypto";import{Hono as D}from"hono";import{cors as se}from"hono/cors";import{rateLimiter as ce}from"hono-rate-limiter";import{raw as le}from"hono/html";import{jsx as O,jsxs as k}from"hono/jsx/jsx-runtime";function A(e){return e.option(`--config <path>`,`Path to .logsink.yaml`).option(`--global`,`Use the global log-sink instance`).option(`--instance <scope>`,`Force log-sink instance: local or global`)}function j(e){let t=e.instance?.trim();if(e.global&&t&&t.toLowerCase()!==`global`)throw Error(`Use either --global or --instance local, not both`);return e.global?`global`:t}function M(e,t=p){e.config&&(process.env.LOG_SINK_CONFIG=e.config);let n=j(e);return n&&(process.env.LOG_SINK_INSTANCE=n),m({configPath:e.config,packageName:t})}const ue=[`error`,`fatal`];function de(e){let t=e.trim();if(!t)return null;try{return JSON.parse(t)}catch{return null}}function fe(e){if(e==null)return`unknown`;if(typeof e==`string`)return e;try{return JSON.stringify(e,null,2)}catch{return String(e)}}function pe(e){return e.hook_event_name===`PostToolUseFailure`?`Current tool failure:\n- Tool: ${e.tool_name??`unknown tool`}\n- Error: ${fe(e.error)}`:null}function me(e,t,n){let r=new Map;for(let t of e){let e=`${t.service}::${t.level}::${t.error_type??``}::${t.error_message??t.message}`,i=new Date(Number(t.created_at)).toISOString();r.has(e)||r.set(e,{key:e,count:0,service:t.service,level:t.level,errorType:t.error_type,errorMessage:t.error_message,message:t.message,firstSeen:i,lastSeen:i,traceIds:new Set,examples:[]});let a=r.get(e);a.count+=1,a.lastSeen=i,t.trace_id&&a.traceIds.add(t.trace_id),a.examples.length<n&&a.examples.push({id:t.id,timestamp:i,traceId:t.trace_id})}return Array.from(r.values()).sort((e,t)=>t.count-e.count||t.lastSeen.localeCompare(e.lastSeen)).slice(0,t)}function he(e,t,n,r){let i=me(e,n,r),a=[];a.push(`Recent log errors (${e.length} new):`),t.tool_name&&a.push(`- Triggered after tool: ${t.tool_name}`);for(let[e,t]of i.entries()){a.push(`${e+1}. ${t.service} [${t.level}] x${t.count} ${t.errorType?`(${t.errorType}) `:``}${t.errorMessage??t.message}`),a.push(` First seen: ${t.firstSeen}`),a.push(` Last seen: ${t.lastSeen}`),t.traceIds.size>0&&a.push(` Trace IDs: ${Array.from(t.traceIds).slice(0,3).join(`, `)}`);for(let e of t.examples)a.push(` Example: ${e.timestamp} id=${e.id}${e.traceId?` trace=${e.traceId}`:``}`)}if(t.hook_event_name===`PostToolUseFailure`){let e=pe(t);e&&a.push(``,e)}return a.join(`
3
3
  `)}function ge(e){if(e.session_id?.trim())return ie(h(e.cwd?.trim()||process.cwd()))}async function _e(e,t){let n=j(t);if(t.dbPath){let e=n===`global`?`global`:`local`;return v(t.dbPath)?{dbPath:t.dbPath,scope:e}:void 0}let r={...process.env};t.config&&(r.LOG_SINK_CONFIG=t.config),n&&(r.LOG_SINK_INSTANCE=n);let i=m({configPath:t.config,cwd:e.cwd??process.cwd(),env:r,packageName:p}),a=new re(r.PORT_REGISTRY_PATH??ne);try{let e=await a.getPort({repositoryPath:i.repositoryPath,serviceName:`log-sink-mcp-http`,serviceType:`tool`,environment:r.NODE_ENV||`development`}),t=e.record?.metadata?.dbPath;if(e.success&&typeof t==`string`&&t&&v(t))return{dbPath:t,scope:i.scope}}catch{}return v(i.dbPath)?{dbPath:i.dbPath,scope:i.scope}:void 0}async function ve(e,t,n,r,i,a){let o=e.getSqliteClient(),s=Date.now()-n*60*1e3,c=``;if(t){let e=o.prepare(`
4
4
  SELECT id, created_at
5
5
  FROM logs
@@ -1,2 +1,2 @@
1
- var e=require(`../piTelemetry-P-o6KRQk.cjs`).t();module.exports=e;
1
+ var e=require(`../piTelemetry-BYKSOd4F.cjs`).t();module.exports=e;
2
2
  //# sourceMappingURL=pi.cjs.map
@@ -1,2 +1,2 @@
1
- import{t as e}from"../piTelemetry-BPQgGDpj.mjs";var t=e();export{t as default};
1
+ import{t as e}from"../piTelemetry-Dlhhs5sx.mjs";var t=e();export{t as default};
2
2
  //# sourceMappingURL=pi.mjs.map
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./node-9pwprHry.cjs`),t=require(`./stdio-Gb0mj6eo.cjs`),n=require(`./piTelemetry-P-o6KRQk.cjs`);let r=require(`@opentelemetry/api`),i=require(`@opentelemetry/api-logs`);exports.SpanKind=r.SpanKind,exports.SpanStatusCode=r.SpanStatusCode,exports.StdioTransportHandler=t.t,exports.createNodeTelemetry=e.t,exports.createPiTelemetryExtension=n.t,exports.createServer=t.n,exports.getLogSinkOtelEndpoint=e.n,exports.log=i.logs,exports.resolveLogSinkOtelEndpoint=e.a,exports.resolveLogSinkPort=e.o,exports.resolveNodeTelemetryEndpoints=e.r,exports.trace=r.trace;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./node-9pwprHry.cjs`),t=require(`./stdio-QFR4qcFs.cjs`),n=require(`./piTelemetry-BYKSOd4F.cjs`);let r=require(`@opentelemetry/api`),i=require(`@opentelemetry/api-logs`);exports.SpanKind=r.SpanKind,exports.SpanStatusCode=r.SpanStatusCode,exports.StdioTransportHandler=t.t,exports.createNodeTelemetry=e.t,exports.createPiTelemetryExtension=n.t,exports.createServer=t.n,exports.getLogSinkOtelEndpoint=e.n,exports.log=i.logs,exports.resolveLogSinkOtelEndpoint=e.a,exports.resolveLogSinkPort=e.o,exports.resolveNodeTelemetryEndpoints=e.r,exports.trace=r.trace;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./stdio-DaqaONHT.mjs";import{a as n,c as r,i,l as a,n as o,o as s,r as c,t as l,u}from"./node-Bv2snZci.mjs";import{t as d}from"./piTelemetry-BPQgGDpj.mjs";export{l as SpanKind,o as SpanStatusCode,t as StdioTransportHandler,c as createNodeTelemetry,d as createPiTelemetryExtension,e as createServer,i as getLogSinkOtelEndpoint,n as log,a as resolveLogSinkOtelEndpoint,u as resolveLogSinkPort,s as resolveNodeTelemetryEndpoints,r as trace};
1
+ import{n as e,t}from"./stdio-kDI4sBvK.mjs";import{a as n,c as r,i,l as a,n as o,o as s,r as c,t as l,u}from"./node-Bv2snZci.mjs";import{t as d}from"./piTelemetry-Dlhhs5sx.mjs";export{l as SpanKind,o as SpanStatusCode,t as StdioTransportHandler,c as createNodeTelemetry,d as createPiTelemetryExtension,e as createServer,i as getLogSinkOtelEndpoint,n as log,a as resolveLogSinkOtelEndpoint,u as resolveLogSinkPort,s as resolveNodeTelemetryEndpoints,r as trace};
@@ -0,0 +1,2 @@
1
+ const e=require(`./node-9pwprHry.cjs`);function t(e){return e===`1`||e?.toLowerCase()===`true`||e?.toLowerCase()===`yes`}function n(e){try{return JSON.stringify(e)}catch{return`[unserializable]`}}function r(e,t){console.warn(`[log-sink-mcp pi telemetry] ${e} failed: ${t instanceof Error?t.message:String(t)}`)}function i(e){let t={"pi.cwd":e.cwd,"pi.mode":e.mode,"pi.session.id":e.sessionManager.getSessionId()};e.thinkingLevel&&(t[`pi.thinking_level`]=e.thinkingLevel);let n=e.sessionManager.getSessionFile();return n&&(t[`pi.session.file`]=n),e.model&&(t[`gen_ai.provider.name`]=e.model.provider,t[`gen_ai.request.model`]=e.model.id),t}function a(e){if(e.role!==`assistant`)return;let t={"gen_ai.response.model":e.responseModel??e.model,"gen_ai.response.finish_reasons":e.stopReason,"gen_ai.usage.input_tokens":e.usage.input,"gen_ai.usage.output_tokens":e.usage.output,"gen_ai.usage.cache_read_tokens":e.usage.cacheRead,"gen_ai.usage.cache_write_tokens":e.usage.cacheWrite,"gen_ai.usage.total_tokens":e.usage.totalTokens,"gen_ai.usage.cost":e.usage.cost.total};return e.usage.reasoning!==void 0&&(t[`gen_ai.usage.reasoning_tokens`]=e.usage.reasoning),t}function o(e){let t={"x-agent":`pi`},n=e.AGENT_SESSION_ID??e.PI_SESSION_ID;return n&&(t[`x-agent-session-id`]=n),e.AGENT_PARENT_SESSION_ID&&(t[`x-agent-parent-session-id`]=e.AGENT_PARENT_SESSION_ID),t}function s(s={}){return function(c){let l=s.env??process.env,u=s.telemetryFactory??e.t,d=l.AGENT_OTEL_REDACT===`0`,f=new Map,p,m,h=e=>l.AGENT_TELEMETRY_DISABLED===`1`?Promise.resolve(void 0):(m??=u({serviceName:`pi`,packageName:`@agimon-ai/log-sink-mcp`,cwd:e.cwd,env:l,discoverEndpoint:!0,enableLogs:!0,enableTraces:t(l.AGENT_OTEL_TRACES),headers:o(l)}).then(async e=>{let n=s.allowFileFallback||t(l.LOG_SINK_PI_FILE_FALLBACK);if(e.backend!==`file`||n)return e;await e.shutdown().catch(e=>r(`File fallback shutdown`,e))}).catch(e=>{r(`Initialization`,e)}),m);c.on(`session_start`,async(e,t)=>{(await h(t))?.logger.info(`pi.session.started`,{attributes:{...i(t),"pi.session.reason":e.reason}})}),c.on(`before_agent_start`,async(e,t)=>{(await h(t))?.logger.info(`pi.user_prompt`,{attributes:{...i(t),"pi.user_message.length":e.prompt.length,"pi.user_message.image_count":e.images?.length??0,...d?{"user.prompt":e.prompt}:{}}})}),c.on(`agent_start`,async(e,t)=>{p=Date.now(),(await h(t))?.logger.info(`pi.agent.started`,{attributes:i(t)})}),c.on(`turn_start`,async(e,t)=>{(await h(t))?.logger.debug(`pi.turn.started`,{attributes:{...i(t),"pi.turn.index":e.turnIndex}})}),c.on(`turn_end`,async(e,t)=>{let n=await h(t),r=a(e.message);if(n?.logger.info(`pi.turn.finished`,{attributes:{...i(t),"pi.turn.index":e.turnIndex,"pi.tool_result.count":e.toolResults.length,...r}}),r)for(let a of e.toolResults)n?.logger.debug(`pi.tool_token_sample`,{attributes:{...i(t),...r,"tool.name":a.toolName,token_attribution:`toolCallTurn`}})}),c.on(`tool_execution_start`,async(e,t)=>{f.set(e.toolCallId,Date.now()),(await h(t))?.logger.debug(`pi.tool_call`,{attributes:{...i(t),"tool.name":e.toolName,"tool.call.id":e.toolCallId,...d?{"tool.input":n(e.args)}:{}}})}),c.on(`tool_execution_end`,async(e,t)=>{let r=f.get(e.toolCallId);f.delete(e.toolCallId),(await h(t))?.logger.info(`pi.tool_result`,{attributes:{...i(t),success:!e.isError,tool_name:e.toolName,"tool.name":e.toolName,"tool.call.id":e.toolCallId,"tool.result.error":e.isError,...r===void 0?{}:{"tool.duration_ms":Date.now()-r},...d?{"tool.result":n(e.result)}:{}}})}),c.on(`after_provider_response`,async(e,t)=>{let n=await h(t),r={attributes:{...i(t),status_code:e.status,"http.response.status_code":e.status}};e.status>=400?n?.logger.error(`pi.api_error`,r):n?.logger.debug(`pi.api_response`,r)}),c.on(`model_select`,async(e,t)=>{(await h(t))?.logger.info(`pi.model.selected`,{attributes:{...i(t),"pi.model.source":e.source,"gen_ai.provider.name":e.model.provider,"gen_ai.request.model":e.model.id}})}),c.on(`agent_end`,async(e,t)=>{let n=await h(t);n?.logger.info(`pi.agent.finished`,{attributes:{...i(t),"pi.message.count":e.messages.length,...p===void 0?{}:{"pi.agent.duration_ms":Date.now()-p}}}),p=void 0,await n?.flush().catch(e=>r(`Flush`,e))}),c.on(`agent_settled`,async(e,t)=>{(await h(t))?.logger.debug(`pi.agent.settled`,{attributes:i(t)})}),c.on(`session_shutdown`,async(e,t)=>{let n=await h(t);n?.logger.info(`pi.session.finished`,{attributes:{...i(t),"pi.session.reason":e.reason}}),await n?.shutdown().catch(e=>r(`Shutdown`,e))})}}Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return s}});
2
+ //# sourceMappingURL=piTelemetry-BYKSOd4F.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piTelemetry-BYKSOd4F.cjs","names":["createNodeTelemetry"],"sources":["../src/extensions/piTelemetry.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext, TurnEndEvent } from '@earendil-works/pi-coding-agent';\nimport { createNodeTelemetry, type NodeTelemetryHandle, type NodeTelemetryOptions } from '../telemetry/node.js';\n\nconst SERVICE_NAME = 'pi';\nconst PACKAGE_NAME = '@agimon-ai/log-sink-mcp';\n\ntype TelemetryFactory = (options: NodeTelemetryOptions) => Promise<NodeTelemetryHandle>;\n\nexport interface PiTelemetryExtensionOptions {\n allowFileFallback?: boolean;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: TelemetryFactory;\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes';\n}\n\nfunction serialize(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n\nfunction reportFailure(operation: string, error: unknown): void {\n console.warn(\n `[log-sink-mcp pi telemetry] ${operation} failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n}\n\nfunction contextAttributes(ctx: ExtensionContext): Record<string, string | number | boolean> {\n const attributes: Record<string, string | number | boolean> = {\n 'pi.cwd': ctx.cwd,\n 'pi.mode': ctx.mode,\n 'pi.session.id': ctx.sessionManager.getSessionId(),\n };\n\n if (ctx.thinkingLevel) attributes['pi.thinking_level'] = ctx.thinkingLevel;\n const sessionFile = ctx.sessionManager.getSessionFile();\n if (sessionFile) attributes['pi.session.file'] = sessionFile;\n if (ctx.model) {\n attributes['gen_ai.provider.name'] = ctx.model.provider;\n attributes['gen_ai.request.model'] = ctx.model.id;\n }\n\n return attributes;\n}\n\n/**\n * Token accounting for one turn.\n *\n * Returns nothing when the turn carries no usage, which is what lets a caller\n * skip emitting a record the metrics aggregator would only discard.\n */\nfunction usageAttributes(message: TurnEndEvent['message']): Record<string, string | number> | undefined {\n if (message.role !== 'assistant') return undefined;\n\n const attributes: Record<string, string | number> = {\n 'gen_ai.response.model': message.responseModel ?? message.model,\n 'gen_ai.response.finish_reasons': message.stopReason,\n 'gen_ai.usage.input_tokens': message.usage.input,\n 'gen_ai.usage.output_tokens': message.usage.output,\n 'gen_ai.usage.cache_read_tokens': message.usage.cacheRead,\n 'gen_ai.usage.cache_write_tokens': message.usage.cacheWrite,\n 'gen_ai.usage.total_tokens': message.usage.totalTokens,\n 'gen_ai.usage.cost': message.usage.cost.total,\n };\n if (message.usage.reasoning !== undefined) attributes['gen_ai.usage.reasoning_tokens'] = message.usage.reasoning;\n\n return attributes;\n}\n\nfunction telemetryHeaders(env: NodeJS.ProcessEnv): Record<string, string> {\n const headers: Record<string, string> = { 'x-agent': SERVICE_NAME };\n const sessionId = env.AGENT_SESSION_ID ?? env.PI_SESSION_ID;\n if (sessionId) headers['x-agent-session-id'] = sessionId;\n if (env.AGENT_PARENT_SESSION_ID) headers['x-agent-parent-session-id'] = env.AGENT_PARENT_SESSION_ID;\n return headers;\n}\n\nexport function createPiTelemetryExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerPiTelemetry(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const telemetryFactory = options.telemetryFactory ?? createNodeTelemetry;\n const includeSensitiveDetails = env.AGENT_OTEL_REDACT === '0';\n const toolStartedAt = new Map<string, number>();\n let agentStartedAt: number | undefined;\n let telemetryPromise: Promise<NodeTelemetryHandle | undefined> | undefined;\n\n const getTelemetry = (ctx: ExtensionContext): Promise<NodeTelemetryHandle | undefined> => {\n if (env.AGENT_TELEMETRY_DISABLED === '1') return Promise.resolve(undefined);\n\n telemetryPromise ??= telemetryFactory({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: ctx.cwd,\n env,\n discoverEndpoint: true,\n enableLogs: true,\n enableTraces: isEnabled(env.AGENT_OTEL_TRACES),\n headers: telemetryHeaders(env),\n })\n .then(async (telemetry) => {\n const allowFileFallback = options.allowFileFallback || isEnabled(env.LOG_SINK_PI_FILE_FALLBACK);\n if (telemetry.backend !== 'file' || allowFileFallback) return telemetry;\n\n await telemetry.shutdown().catch((error: unknown) => reportFailure('File fallback shutdown', error));\n return undefined;\n })\n .catch((error: unknown) => {\n reportFailure('Initialization', error);\n return undefined;\n });\n return telemetryPromise;\n };\n\n pi.on('session_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.session.started', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n },\n });\n });\n\n pi.on('before_agent_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.user_prompt', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.user_message.length': event.prompt.length,\n 'pi.user_message.image_count': event.images?.length ?? 0,\n ...(includeSensitiveDetails ? { 'user.prompt': event.prompt } : {}),\n },\n });\n });\n\n pi.on('agent_start', async (_event, ctx) => {\n agentStartedAt = Date.now();\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.agent.started', {\n attributes: contextAttributes(ctx),\n });\n });\n\n pi.on('turn_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.turn.started', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n },\n });\n });\n\n pi.on('turn_end', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n const usage = usageAttributes(event.message);\n telemetry?.logger.info('pi.turn.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n 'pi.tool_result.count': event.toolResults.length,\n ...usage,\n },\n });\n\n // One sample per tool call, carrying the usage of the turn that issued\n // it, so the percentiles answer \"how large is the context when this tool\n // runs\". A turn calling several tools emits a sample each: the metric is\n // a distribution per tool, not a sum, so the repetition is the point.\n if (!usage) return;\n for (const result of event.toolResults) {\n telemetry?.logger.debug('pi.tool_token_sample', {\n attributes: {\n ...contextAttributes(ctx),\n ...usage,\n 'tool.name': result.toolName,\n token_attribution: 'toolCallTurn',\n },\n });\n }\n });\n\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.tool_call', {\n attributes: {\n ...contextAttributes(ctx),\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n ...(includeSensitiveDetails ? { 'tool.input': serialize(event.args) } : {}),\n },\n });\n });\n\n pi.on('tool_execution_end', async (event, ctx) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.tool_result', {\n attributes: {\n ...contextAttributes(ctx),\n success: !event.isError,\n tool_name: event.toolName,\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { 'tool.duration_ms': Date.now() - startedAt }),\n ...(includeSensitiveDetails ? { 'tool.result': serialize(event.result) } : {}),\n },\n });\n });\n\n pi.on('after_provider_response', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n const options = {\n attributes: {\n ...contextAttributes(ctx),\n status_code: event.status,\n 'http.response.status_code': event.status,\n },\n };\n if (event.status >= 400) telemetry?.logger.error('pi.api_error', options);\n else telemetry?.logger.debug('pi.api_response', options);\n });\n\n pi.on('model_select', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.model.selected', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.model.source': event.source,\n 'gen_ai.provider.name': event.model.provider,\n 'gen_ai.request.model': event.model.id,\n },\n });\n });\n\n pi.on('agent_end', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.agent.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.message.count': event.messages.length,\n ...(agentStartedAt === undefined ? {} : { 'pi.agent.duration_ms': Date.now() - agentStartedAt }),\n },\n });\n agentStartedAt = undefined;\n await telemetry?.flush().catch((error: unknown) => reportFailure('Flush', error));\n });\n\n pi.on('agent_settled', async (_event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.agent.settled', {\n attributes: contextAttributes(ctx),\n });\n });\n\n pi.on('session_shutdown', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.session.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n },\n });\n await telemetry?.shutdown().catch((error: unknown) => reportFailure('Shutdown', error));\n });\n };\n}\n"],"mappings":"uCAcA,SAAS,EAAU,EAAoC,CACrD,OAAO,IAAU,KAAO,GAAO,aAAa,GAAK,QAAU,GAAO,aAAa,GAAK,MAGtF,SAAS,EAAU,EAAwB,CACzC,GAAI,CACF,OAAO,KAAK,UAAU,EAAM,MACtB,CACN,MAAO,oBAIX,SAAS,EAAc,EAAmB,EAAsB,CAC9D,QAAQ,KACN,+BAA+B,EAAU,WAAW,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,GAC3G,CAGH,SAAS,EAAkB,EAAkE,CAC3F,IAAM,EAAwD,CAC5D,SAAU,EAAI,IACd,UAAW,EAAI,KACf,gBAAiB,EAAI,eAAe,cAAc,CACnD,CAEG,EAAI,gBAAe,EAAW,qBAAuB,EAAI,eAC7D,IAAM,EAAc,EAAI,eAAe,gBAAgB,CAOvD,OANI,IAAa,EAAW,mBAAqB,GAC7C,EAAI,QACN,EAAW,wBAA0B,EAAI,MAAM,SAC/C,EAAW,wBAA0B,EAAI,MAAM,IAG1C,EAST,SAAS,EAAgB,EAA+E,CACtG,GAAI,EAAQ,OAAS,YAAa,OAElC,IAAM,EAA8C,CAClD,wBAAyB,EAAQ,eAAiB,EAAQ,MAC1D,iCAAkC,EAAQ,WAC1C,4BAA6B,EAAQ,MAAM,MAC3C,6BAA8B,EAAQ,MAAM,OAC5C,iCAAkC,EAAQ,MAAM,UAChD,kCAAmC,EAAQ,MAAM,WACjD,4BAA6B,EAAQ,MAAM,YAC3C,oBAAqB,EAAQ,MAAM,KAAK,MACzC,CAGD,OAFI,EAAQ,MAAM,YAAc,IAAA,KAAW,EAAW,iCAAmC,EAAQ,MAAM,WAEhG,EAGT,SAAS,EAAiB,EAAgD,CACxE,IAAM,EAAkC,CAAE,UAAW,KAAc,CAC7D,EAAY,EAAI,kBAAoB,EAAI,cAG9C,OAFI,IAAW,EAAQ,sBAAwB,GAC3C,EAAI,0BAAyB,EAAQ,6BAA+B,EAAI,yBACrE,EAGT,SAAgB,EAA2B,EAAuC,EAAE,CAAE,CACpF,OAAO,SAA6B,EAAwB,CAC1D,IAAM,EAAM,EAAQ,KAAO,QAAQ,IAC7B,EAAmB,EAAQ,kBAAoBA,EAAAA,EAC/C,EAA0B,EAAI,oBAAsB,IACpD,EAAgB,IAAI,IACtB,EACA,EAEE,EAAgB,GAChB,EAAI,2BAA6B,IAAY,QAAQ,QAAQ,IAAA,GAAU,EAE3E,IAAqB,EAAiB,CACpC,YAAa,KACb,YAAa,0BACb,IAAK,EAAI,IACT,MACA,iBAAkB,GAClB,WAAY,GACZ,aAAc,EAAU,EAAI,kBAAkB,CAC9C,QAAS,EAAiB,EAAI,CAC/B,CAAC,CACC,KAAK,KAAO,IAAc,CACzB,IAAM,EAAoB,EAAQ,mBAAqB,EAAU,EAAI,0BAA0B,CAC/F,GAAI,EAAU,UAAY,QAAU,EAAmB,OAAO,EAE9D,MAAM,EAAU,UAAU,CAAC,MAAO,GAAmB,EAAc,yBAA0B,EAAM,CAAC,EAEpG,CACD,MAAO,GAAmB,CACzB,EAAc,iBAAkB,EAAM,EAEtC,CACG,GAGT,EAAG,GAAG,gBAAiB,MAAO,EAAO,IAAQ,EAE3C,MADwB,EAAa,EAAI,GAC9B,OAAO,KAAK,qBAAsB,CAC3C,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,oBAAqB,EAAM,OAC5B,CACF,CAAC,EACF,CAEF,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAQ,EAEhD,MADwB,EAAa,EAAI,GAC9B,OAAO,KAAK,iBAAkB,CACvC,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,yBAA0B,EAAM,OAAO,OACvC,8BAA+B,EAAM,QAAQ,QAAU,EACvD,GAAI,EAA0B,CAAE,cAAe,EAAM,OAAQ,CAAG,EAAE,CACnE,CACF,CAAC,EACF,CAEF,EAAG,GAAG,cAAe,MAAO,EAAQ,IAAQ,CAC1C,EAAiB,KAAK,KAAK,EAE3B,MADwB,EAAa,EAAI,GAC9B,OAAO,KAAK,mBAAoB,CACzC,WAAY,EAAkB,EAAI,CACnC,CAAC,EACF,CAEF,EAAG,GAAG,aAAc,MAAO,EAAO,IAAQ,EAExC,MADwB,EAAa,EAAI,GAC9B,OAAO,MAAM,kBAAmB,CACzC,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,gBAAiB,EAAM,UACxB,CACF,CAAC,EACF,CAEF,EAAG,GAAG,WAAY,MAAO,EAAO,IAAQ,CACtC,IAAM,EAAY,MAAM,EAAa,EAAI,CACnC,EAAQ,EAAgB,EAAM,QAAQ,CAC5C,MAAW,OAAO,KAAK,mBAAoB,CACzC,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,gBAAiB,EAAM,UACvB,uBAAwB,EAAM,YAAY,OAC1C,GAAG,EACJ,CACF,CAAC,CAMG,EACL,IAAK,IAAM,KAAU,EAAM,YACzB,GAAW,OAAO,MAAM,uBAAwB,CAC9C,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,GAAG,EACH,YAAa,EAAO,SACpB,kBAAmB,eACpB,CACF,CAAC,EAEJ,CAEF,EAAG,GAAG,uBAAwB,MAAO,EAAO,IAAQ,CAClD,EAAc,IAAI,EAAM,WAAY,KAAK,KAAK,CAAC,EAE/C,MADwB,EAAa,EAAI,GAC9B,OAAO,MAAM,eAAgB,CACtC,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,YAAa,EAAM,SACnB,eAAgB,EAAM,WACtB,GAAI,EAA0B,CAAE,aAAc,EAAU,EAAM,KAAK,CAAE,CAAG,EAAE,CAC3E,CACF,CAAC,EACF,CAEF,EAAG,GAAG,qBAAsB,MAAO,EAAO,IAAQ,CAChD,IAAM,EAAY,EAAc,IAAI,EAAM,WAAW,CACrD,EAAc,OAAO,EAAM,WAAW,EAEtC,MADwB,EAAa,EAAI,GAC9B,OAAO,KAAK,iBAAkB,CACvC,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,QAAS,CAAC,EAAM,QAChB,UAAW,EAAM,SACjB,YAAa,EAAM,SACnB,eAAgB,EAAM,WACtB,oBAAqB,EAAM,QAC3B,GAAI,IAAc,IAAA,GAAY,EAAE,CAAG,CAAE,mBAAoB,KAAK,KAAK,CAAG,EAAW,CACjF,GAAI,EAA0B,CAAE,cAAe,EAAU,EAAM,OAAO,CAAE,CAAG,EAAE,CAC9E,CACF,CAAC,EACF,CAEF,EAAG,GAAG,0BAA2B,MAAO,EAAO,IAAQ,CACrD,IAAM,EAAY,MAAM,EAAa,EAAI,CACnC,EAAU,CACd,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,YAAa,EAAM,OACnB,4BAA6B,EAAM,OACpC,CACF,CACG,EAAM,QAAU,IAAK,GAAW,OAAO,MAAM,eAAgB,EAAQ,CACpE,GAAW,OAAO,MAAM,kBAAmB,EAAQ,EACxD,CAEF,EAAG,GAAG,eAAgB,MAAO,EAAO,IAAQ,EAE1C,MADwB,EAAa,EAAI,GAC9B,OAAO,KAAK,oBAAqB,CAC1C,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,kBAAmB,EAAM,OACzB,uBAAwB,EAAM,MAAM,SACpC,uBAAwB,EAAM,MAAM,GACrC,CACF,CAAC,EACF,CAEF,EAAG,GAAG,YAAa,MAAO,EAAO,IAAQ,CACvC,IAAM,EAAY,MAAM,EAAa,EAAI,CACzC,GAAW,OAAO,KAAK,oBAAqB,CAC1C,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,mBAAoB,EAAM,SAAS,OACnC,GAAI,IAAmB,IAAA,GAAY,EAAE,CAAG,CAAE,uBAAwB,KAAK,KAAK,CAAG,EAAgB,CAChG,CACF,CAAC,CACF,EAAiB,IAAA,GACjB,MAAM,GAAW,OAAO,CAAC,MAAO,GAAmB,EAAc,QAAS,EAAM,CAAC,EACjF,CAEF,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,EAE5C,MADwB,EAAa,EAAI,GAC9B,OAAO,MAAM,mBAAoB,CAC1C,WAAY,EAAkB,EAAI,CACnC,CAAC,EACF,CAEF,EAAG,GAAG,mBAAoB,MAAO,EAAO,IAAQ,CAC9C,IAAM,EAAY,MAAM,EAAa,EAAI,CACzC,GAAW,OAAO,KAAK,sBAAuB,CAC5C,WAAY,CACV,GAAG,EAAkB,EAAI,CACzB,oBAAqB,EAAM,OAC5B,CACF,CAAC,CACF,MAAM,GAAW,UAAU,CAAC,MAAO,GAAmB,EAAc,WAAY,EAAM,CAAC,EACvF"}
@@ -0,0 +1,2 @@
1
+ import{r as e}from"./node-Bv2snZci.mjs";function t(e){return e===`1`||e?.toLowerCase()===`true`||e?.toLowerCase()===`yes`}function n(e){try{return JSON.stringify(e)}catch{return`[unserializable]`}}function r(e,t){console.warn(`[log-sink-mcp pi telemetry] ${e} failed: ${t instanceof Error?t.message:String(t)}`)}function i(e){let t={"pi.cwd":e.cwd,"pi.mode":e.mode,"pi.session.id":e.sessionManager.getSessionId()};e.thinkingLevel&&(t[`pi.thinking_level`]=e.thinkingLevel);let n=e.sessionManager.getSessionFile();return n&&(t[`pi.session.file`]=n),e.model&&(t[`gen_ai.provider.name`]=e.model.provider,t[`gen_ai.request.model`]=e.model.id),t}function a(e){if(e.role!==`assistant`)return;let t={"gen_ai.response.model":e.responseModel??e.model,"gen_ai.response.finish_reasons":e.stopReason,"gen_ai.usage.input_tokens":e.usage.input,"gen_ai.usage.output_tokens":e.usage.output,"gen_ai.usage.cache_read_tokens":e.usage.cacheRead,"gen_ai.usage.cache_write_tokens":e.usage.cacheWrite,"gen_ai.usage.total_tokens":e.usage.totalTokens,"gen_ai.usage.cost":e.usage.cost.total};return e.usage.reasoning!==void 0&&(t[`gen_ai.usage.reasoning_tokens`]=e.usage.reasoning),t}function o(e){let t={"x-agent":`pi`},n=e.AGENT_SESSION_ID??e.PI_SESSION_ID;return n&&(t[`x-agent-session-id`]=n),e.AGENT_PARENT_SESSION_ID&&(t[`x-agent-parent-session-id`]=e.AGENT_PARENT_SESSION_ID),t}function s(s={}){return function(c){let l=s.env??process.env,u=s.telemetryFactory??e,d=l.AGENT_OTEL_REDACT===`0`,f=new Map,p,m,h=e=>l.AGENT_TELEMETRY_DISABLED===`1`?Promise.resolve(void 0):(m??=u({serviceName:`pi`,packageName:`@agimon-ai/log-sink-mcp`,cwd:e.cwd,env:l,discoverEndpoint:!0,enableLogs:!0,enableTraces:t(l.AGENT_OTEL_TRACES),headers:o(l)}).then(async e=>{let n=s.allowFileFallback||t(l.LOG_SINK_PI_FILE_FALLBACK);if(e.backend!==`file`||n)return e;await e.shutdown().catch(e=>r(`File fallback shutdown`,e))}).catch(e=>{r(`Initialization`,e)}),m);c.on(`session_start`,async(e,t)=>{(await h(t))?.logger.info(`pi.session.started`,{attributes:{...i(t),"pi.session.reason":e.reason}})}),c.on(`before_agent_start`,async(e,t)=>{(await h(t))?.logger.info(`pi.user_prompt`,{attributes:{...i(t),"pi.user_message.length":e.prompt.length,"pi.user_message.image_count":e.images?.length??0,...d?{"user.prompt":e.prompt}:{}}})}),c.on(`agent_start`,async(e,t)=>{p=Date.now(),(await h(t))?.logger.info(`pi.agent.started`,{attributes:i(t)})}),c.on(`turn_start`,async(e,t)=>{(await h(t))?.logger.debug(`pi.turn.started`,{attributes:{...i(t),"pi.turn.index":e.turnIndex}})}),c.on(`turn_end`,async(e,t)=>{let n=await h(t),r=a(e.message);if(n?.logger.info(`pi.turn.finished`,{attributes:{...i(t),"pi.turn.index":e.turnIndex,"pi.tool_result.count":e.toolResults.length,...r}}),r)for(let a of e.toolResults)n?.logger.debug(`pi.tool_token_sample`,{attributes:{...i(t),...r,"tool.name":a.toolName,token_attribution:`toolCallTurn`}})}),c.on(`tool_execution_start`,async(e,t)=>{f.set(e.toolCallId,Date.now()),(await h(t))?.logger.debug(`pi.tool_call`,{attributes:{...i(t),"tool.name":e.toolName,"tool.call.id":e.toolCallId,...d?{"tool.input":n(e.args)}:{}}})}),c.on(`tool_execution_end`,async(e,t)=>{let r=f.get(e.toolCallId);f.delete(e.toolCallId),(await h(t))?.logger.info(`pi.tool_result`,{attributes:{...i(t),success:!e.isError,tool_name:e.toolName,"tool.name":e.toolName,"tool.call.id":e.toolCallId,"tool.result.error":e.isError,...r===void 0?{}:{"tool.duration_ms":Date.now()-r},...d?{"tool.result":n(e.result)}:{}}})}),c.on(`after_provider_response`,async(e,t)=>{let n=await h(t),r={attributes:{...i(t),status_code:e.status,"http.response.status_code":e.status}};e.status>=400?n?.logger.error(`pi.api_error`,r):n?.logger.debug(`pi.api_response`,r)}),c.on(`model_select`,async(e,t)=>{(await h(t))?.logger.info(`pi.model.selected`,{attributes:{...i(t),"pi.model.source":e.source,"gen_ai.provider.name":e.model.provider,"gen_ai.request.model":e.model.id}})}),c.on(`agent_end`,async(e,t)=>{let n=await h(t);n?.logger.info(`pi.agent.finished`,{attributes:{...i(t),"pi.message.count":e.messages.length,...p===void 0?{}:{"pi.agent.duration_ms":Date.now()-p}}}),p=void 0,await n?.flush().catch(e=>r(`Flush`,e))}),c.on(`agent_settled`,async(e,t)=>{(await h(t))?.logger.debug(`pi.agent.settled`,{attributes:i(t)})}),c.on(`session_shutdown`,async(e,t)=>{let n=await h(t);n?.logger.info(`pi.session.finished`,{attributes:{...i(t),"pi.session.reason":e.reason}}),await n?.shutdown().catch(e=>r(`Shutdown`,e))})}}export{s as t};
2
+ //# sourceMappingURL=piTelemetry-Dlhhs5sx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piTelemetry-Dlhhs5sx.mjs","names":[],"sources":["../src/extensions/piTelemetry.ts"],"sourcesContent":["import type { ExtensionAPI, ExtensionContext, TurnEndEvent } from '@earendil-works/pi-coding-agent';\nimport { createNodeTelemetry, type NodeTelemetryHandle, type NodeTelemetryOptions } from '../telemetry/node.js';\n\nconst SERVICE_NAME = 'pi';\nconst PACKAGE_NAME = '@agimon-ai/log-sink-mcp';\n\ntype TelemetryFactory = (options: NodeTelemetryOptions) => Promise<NodeTelemetryHandle>;\n\nexport interface PiTelemetryExtensionOptions {\n allowFileFallback?: boolean;\n env?: NodeJS.ProcessEnv;\n telemetryFactory?: TelemetryFactory;\n}\n\nfunction isEnabled(value: string | undefined): boolean {\n return value === '1' || value?.toLowerCase() === 'true' || value?.toLowerCase() === 'yes';\n}\n\nfunction serialize(value: unknown): string {\n try {\n return JSON.stringify(value);\n } catch {\n return '[unserializable]';\n }\n}\n\nfunction reportFailure(operation: string, error: unknown): void {\n console.warn(\n `[log-sink-mcp pi telemetry] ${operation} failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n}\n\nfunction contextAttributes(ctx: ExtensionContext): Record<string, string | number | boolean> {\n const attributes: Record<string, string | number | boolean> = {\n 'pi.cwd': ctx.cwd,\n 'pi.mode': ctx.mode,\n 'pi.session.id': ctx.sessionManager.getSessionId(),\n };\n\n if (ctx.thinkingLevel) attributes['pi.thinking_level'] = ctx.thinkingLevel;\n const sessionFile = ctx.sessionManager.getSessionFile();\n if (sessionFile) attributes['pi.session.file'] = sessionFile;\n if (ctx.model) {\n attributes['gen_ai.provider.name'] = ctx.model.provider;\n attributes['gen_ai.request.model'] = ctx.model.id;\n }\n\n return attributes;\n}\n\n/**\n * Token accounting for one turn.\n *\n * Returns nothing when the turn carries no usage, which is what lets a caller\n * skip emitting a record the metrics aggregator would only discard.\n */\nfunction usageAttributes(message: TurnEndEvent['message']): Record<string, string | number> | undefined {\n if (message.role !== 'assistant') return undefined;\n\n const attributes: Record<string, string | number> = {\n 'gen_ai.response.model': message.responseModel ?? message.model,\n 'gen_ai.response.finish_reasons': message.stopReason,\n 'gen_ai.usage.input_tokens': message.usage.input,\n 'gen_ai.usage.output_tokens': message.usage.output,\n 'gen_ai.usage.cache_read_tokens': message.usage.cacheRead,\n 'gen_ai.usage.cache_write_tokens': message.usage.cacheWrite,\n 'gen_ai.usage.total_tokens': message.usage.totalTokens,\n 'gen_ai.usage.cost': message.usage.cost.total,\n };\n if (message.usage.reasoning !== undefined) attributes['gen_ai.usage.reasoning_tokens'] = message.usage.reasoning;\n\n return attributes;\n}\n\nfunction telemetryHeaders(env: NodeJS.ProcessEnv): Record<string, string> {\n const headers: Record<string, string> = { 'x-agent': SERVICE_NAME };\n const sessionId = env.AGENT_SESSION_ID ?? env.PI_SESSION_ID;\n if (sessionId) headers['x-agent-session-id'] = sessionId;\n if (env.AGENT_PARENT_SESSION_ID) headers['x-agent-parent-session-id'] = env.AGENT_PARENT_SESSION_ID;\n return headers;\n}\n\nexport function createPiTelemetryExtension(options: PiTelemetryExtensionOptions = {}) {\n return function registerPiTelemetry(pi: ExtensionAPI): void {\n const env = options.env ?? process.env;\n const telemetryFactory = options.telemetryFactory ?? createNodeTelemetry;\n const includeSensitiveDetails = env.AGENT_OTEL_REDACT === '0';\n const toolStartedAt = new Map<string, number>();\n let agentStartedAt: number | undefined;\n let telemetryPromise: Promise<NodeTelemetryHandle | undefined> | undefined;\n\n const getTelemetry = (ctx: ExtensionContext): Promise<NodeTelemetryHandle | undefined> => {\n if (env.AGENT_TELEMETRY_DISABLED === '1') return Promise.resolve(undefined);\n\n telemetryPromise ??= telemetryFactory({\n serviceName: SERVICE_NAME,\n packageName: PACKAGE_NAME,\n cwd: ctx.cwd,\n env,\n discoverEndpoint: true,\n enableLogs: true,\n enableTraces: isEnabled(env.AGENT_OTEL_TRACES),\n headers: telemetryHeaders(env),\n })\n .then(async (telemetry) => {\n const allowFileFallback = options.allowFileFallback || isEnabled(env.LOG_SINK_PI_FILE_FALLBACK);\n if (telemetry.backend !== 'file' || allowFileFallback) return telemetry;\n\n await telemetry.shutdown().catch((error: unknown) => reportFailure('File fallback shutdown', error));\n return undefined;\n })\n .catch((error: unknown) => {\n reportFailure('Initialization', error);\n return undefined;\n });\n return telemetryPromise;\n };\n\n pi.on('session_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.session.started', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n },\n });\n });\n\n pi.on('before_agent_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.user_prompt', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.user_message.length': event.prompt.length,\n 'pi.user_message.image_count': event.images?.length ?? 0,\n ...(includeSensitiveDetails ? { 'user.prompt': event.prompt } : {}),\n },\n });\n });\n\n pi.on('agent_start', async (_event, ctx) => {\n agentStartedAt = Date.now();\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.agent.started', {\n attributes: contextAttributes(ctx),\n });\n });\n\n pi.on('turn_start', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.turn.started', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n },\n });\n });\n\n pi.on('turn_end', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n const usage = usageAttributes(event.message);\n telemetry?.logger.info('pi.turn.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.turn.index': event.turnIndex,\n 'pi.tool_result.count': event.toolResults.length,\n ...usage,\n },\n });\n\n // One sample per tool call, carrying the usage of the turn that issued\n // it, so the percentiles answer \"how large is the context when this tool\n // runs\". A turn calling several tools emits a sample each: the metric is\n // a distribution per tool, not a sum, so the repetition is the point.\n if (!usage) return;\n for (const result of event.toolResults) {\n telemetry?.logger.debug('pi.tool_token_sample', {\n attributes: {\n ...contextAttributes(ctx),\n ...usage,\n 'tool.name': result.toolName,\n token_attribution: 'toolCallTurn',\n },\n });\n }\n });\n\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.tool_call', {\n attributes: {\n ...contextAttributes(ctx),\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n ...(includeSensitiveDetails ? { 'tool.input': serialize(event.args) } : {}),\n },\n });\n });\n\n pi.on('tool_execution_end', async (event, ctx) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.tool_result', {\n attributes: {\n ...contextAttributes(ctx),\n success: !event.isError,\n tool_name: event.toolName,\n 'tool.name': event.toolName,\n 'tool.call.id': event.toolCallId,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { 'tool.duration_ms': Date.now() - startedAt }),\n ...(includeSensitiveDetails ? { 'tool.result': serialize(event.result) } : {}),\n },\n });\n });\n\n pi.on('after_provider_response', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n const options = {\n attributes: {\n ...contextAttributes(ctx),\n status_code: event.status,\n 'http.response.status_code': event.status,\n },\n };\n if (event.status >= 400) telemetry?.logger.error('pi.api_error', options);\n else telemetry?.logger.debug('pi.api_response', options);\n });\n\n pi.on('model_select', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.model.selected', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.model.source': event.source,\n 'gen_ai.provider.name': event.model.provider,\n 'gen_ai.request.model': event.model.id,\n },\n });\n });\n\n pi.on('agent_end', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.agent.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.message.count': event.messages.length,\n ...(agentStartedAt === undefined ? {} : { 'pi.agent.duration_ms': Date.now() - agentStartedAt }),\n },\n });\n agentStartedAt = undefined;\n await telemetry?.flush().catch((error: unknown) => reportFailure('Flush', error));\n });\n\n pi.on('agent_settled', async (_event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.debug('pi.agent.settled', {\n attributes: contextAttributes(ctx),\n });\n });\n\n pi.on('session_shutdown', async (event, ctx) => {\n const telemetry = await getTelemetry(ctx);\n telemetry?.logger.info('pi.session.finished', {\n attributes: {\n ...contextAttributes(ctx),\n 'pi.session.reason': event.reason,\n },\n });\n await telemetry?.shutdown().catch((error: unknown) => reportFailure('Shutdown', error));\n });\n };\n}\n"],"mappings":"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"}
@@ -70,7 +70,7 @@ const e=require(`./node-9pwprHry.cjs`);let t=require(`@agimon-ai/foundation-vali
70
70
  ORDER BY timestamp ${o}
71
71
  LIMIT ?
72
72
  OFFSET ?
73
- `).all(...c,r,i)).map(e=>this.mapRow(e)),total:Number(l[0]?.count??0)}}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}};M=w([(0,a.injectable)(),C(0,(0,a.inject)(y.LogStorageService)),S(`design:paramtypes`,[Object])],M);const ne=[`gen_ai.usage.input_tokens`,`gen_ai.usage.prompt_tokens`,`llm.usage.input_tokens`,`input_tokens`,`prompt_tokens`,`usage.input_tokens`,`usage.prompt_tokens`,`response.usage.input_tokens`,`response.usage.prompt_tokens`,`usageMetadata.promptTokenCount`,`promptTokenCount`],re=[`gen_ai.usage.output_tokens`,`gen_ai.usage.completion_tokens`,`llm.usage.output_tokens`,`output_tokens`,`completion_tokens`,`usage.output_tokens`,`usage.completion_tokens`,`response.usage.output_tokens`,`response.usage.completion_tokens`,`usageMetadata.candidatesTokenCount`,`candidatesTokenCount`],ie=[`gen_ai.usage.total_tokens`,`llm.usage.total_tokens`,`total_tokens`,`usage.total_tokens`,`response.usage.total_tokens`,`usageMetadata.totalTokenCount`,`totalTokenCount`],ae=[`gen_ai.usage.cache_read.input_tokens`,`gen_ai.usage.cache_creation.input_tokens`,`input_tokens_details.cached_tokens`,`usage.input_tokens_details.cached_tokens`,`response.usage.input_tokens_details.cached_tokens`,`usage.metadata.cached_tokens`,`metadata.cached_tokens`,`cached_tokens`],oe=[`gen_ai.usage.reasoning.output_tokens`,`output_tokens_details.reasoning_tokens`,`usage.output_tokens_details.reasoning_tokens`,`response.usage.output_tokens_details.reasoning_tokens`,`usage.metadata.reasoning_tokens`,`metadata.reasoning_tokens`,`reasoning_tokens`],se=[`model_proxy.model`,`gen_ai.response.model`,`gen_ai.request.model`,`llm.response.model`,`llm.request.model`,`response.model`,`model`,`modelVersion`,`requestedModel`],ce=[`model_proxy.provider`,`gen_ai.system`,`llm.provider`,`provider`,`provider_name`,`model_provider`];function N(e){if(typeof e!=`string`)return e;let t=e.trim();if(!t||t[0]!==`{`&&t[0]!==`[`)return e;try{return JSON.parse(t)}catch{return e}}function le(e,t){let n=N(e);if(!n||typeof n!=`object`||Array.isArray(n))return;let r=n[t];if(r!==void 0)return N(r);let i=n;for(let e of t.split(`.`))if(i=N(i),!i||typeof i!=`object`||Array.isArray(i)||(i=i[e],i===void 0))return;return N(i)}function ue(e,t){for(let n of t){let t=le(e,n);if(t!=null&&t!==``)return t}}function de(e){if(typeof e==`number`&&Number.isFinite(e))return Math.max(0,e);if(typeof e==`bigint`)return Number(e);if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return Math.max(0,t)}return null}function P(e,t){return de(ue(e,t))}function fe(e,t){let n=ue(e,t);return typeof n==`string`&&n.trim().length>0?n.trim():typeof n==`number`||typeof n==`boolean`?String(n):null}function pe(e){let t=P(e,ne),n=P(e,re),r=P(e,ie),i=P(e,ae),a=P(e,oe),o=t??0,s=n??0;return{inputTokens:o,outputTokens:s,totalTokens:r??o+s,cachedInputTokens:i??0,reasoningOutputTokens:a??0,hasUsage:t!==null||n!==null||r!==null||i!==null||a!==null}}function me(e){return{model:fe(e,se),provider:fe(e,ce)}}function he(e){let t=e.toLowerCase();return t.includes(`gen_ai.usage`)||t.includes(`llm.usage`)||/(^|[._-])(input|output|prompt|completion|total|cached|reasoning|candidates?)_?tokens?($|[._-])/.test(t)||/(^|[._-])(prompt|candidates|total)tokencount($|[._-])/.test(t)}function ge(e){return de(e)!==null}function _e(e){return e}function ve(e){if(!e)return{};try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function ye(e){let t=pe(e);return{inputTokens:t.inputTokens,outputTokens:t.outputTokens,totalTokens:t.totalTokens,cachedInputTokens:t.cachedInputTokens,reasoningOutputTokens:t.reasoningOutputTokens,usageEventCount:+!!t.hasUsage,hasUsage:t.hasUsage}}function F(){return{inputTokens:0,outputTokens:0,totalTokens:0,cachedInputTokens:0,reasoningOutputTokens:0,usageEventCount:0}}function be(e,t){e.inputTokens+=t.inputTokens,e.outputTokens+=t.outputTokens,e.totalTokens+=t.totalTokens,e.cachedInputTokens+=t.cachedInputTokens,e.reasoningOutputTokens+=t.reasoningOutputTokens,e.usageEventCount+=t.usageEventCount}function I(e,t){t&&(e[t]=(e[t]??0)+1)}function L(e){return e?(Array.isArray(e)?e:[e]).flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(e=>e.length>0):[]}function xe(e,t){return t.length===0||e!==null&&t.includes(e)}function Se(e){return Math.round(e*100)/100}function R(e,t){if(e.length===0)return 0;let n=[...e].sort((e,t)=>e-t);return n[Math.min(n.length-1,Math.max(0,Math.ceil(n.length*t)-1))]??0}function Ce(e){let t=e.map(e=>e.inputTokens),n=e.map(e=>e.outputTokens),r=e.map(e=>e.totalTokens),i=e=>e.reduce((e,t)=>e+t,0),a=e=>e.length===0?0:Se(i(e)/e.length);return{samples:e.length,avgInputTokens:a(t),p50InputTokens:R(t,.5),p90InputTokens:R(t,.9),avgOutputTokens:a(n),p50OutputTokens:R(n,.5),p90OutputTokens:R(n,.9),avgTotalTokens:a(r),p50TotalTokens:R(r,.5),p90TotalTokens:R(r,.9)}}function we(e,t){return t===0?100:Se(e/t*100)}function Te(e){return e.endsWith(`.tool_token_sample`)}function z(e,...t){for(let n of t){let t=e[n];if(typeof t==`string`&&t.trim().length>0)return t.trim();if(typeof t==`number`||typeof t==`boolean`)return String(t)}return null}function Ee(e){let t=e.metadata,n=e.raw.message??``,r=z(t,`error_type`)??e.raw.error_type,i=t.success,a=t[`tool.result.error`],o=i===!1||i===`false`||a===!0||a===`true`,s=z(t,`decision`),c=z(t,`browse_tool.error.category`);return c===`caller_validation`||c===`caller_execution`?`caller_error`:c===`spec_failure`?`expected_failure`:c===`page_state`?`page_state`:c===`infrastructure_failure`?`infrastructure_failure`:n.includes(`api_error`)?`api_error`:n.includes(`api_retries_exhausted`)?`api_retries_exhausted`:n.includes(`api_refusal`)?`api_refusal`:(n.includes(`tool_result`)||n.includes(`tool error`))&&o?`tool_failure`:n.includes(`tool_decision`)&&s===`reject`?`tool_rejected`:e.raw.level===`error`||e.raw.level===`fatal`||r?`log_error`:null}function De(e,t){return e.message!==`Selected LLM provider`&&e.message!==`LLM provider attempt failed`?null:z(t,`tool`)}function Oe(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,` `)}function ke(e,t){let n=t===`job`?`workflow.job.finished`:`workflow.run.finished`;if(e.raw.message!==n)return!1;let r=t===`job`?`workflow.job.outcome`:`workflow.outcome`;return z(e.metadata,r)===`failed`}let B=class{constructor(e){this.storage=e}async getMetrics(e={},t={}){await this.storage.ensureInitialized();let n=this.storage.getSqliteClient(),r=L(e.model),i=L(e.provider),{whereSql:a,params:o}=this.buildWhereClause(e),s=_e(n.prepare(`
73
+ `).all(...c,r,i)).map(e=>this.mapRow(e)),total:Number(l[0]?.count??0)}}catch(e){throw Error(`Failed to query logs: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}};M=w([(0,a.injectable)(),C(0,(0,a.inject)(y.LogStorageService)),S(`design:paramtypes`,[Object])],M);const ne=[`gen_ai.usage.input_tokens`,`gen_ai.usage.prompt_tokens`,`llm.usage.input_tokens`,`input_tokens`,`prompt_tokens`,`usage.input_tokens`,`usage.prompt_tokens`,`response.usage.input_tokens`,`response.usage.prompt_tokens`,`usageMetadata.promptTokenCount`,`promptTokenCount`],re=[`gen_ai.usage.output_tokens`,`gen_ai.usage.completion_tokens`,`llm.usage.output_tokens`,`output_tokens`,`completion_tokens`,`usage.output_tokens`,`usage.completion_tokens`,`response.usage.output_tokens`,`response.usage.completion_tokens`,`usageMetadata.candidatesTokenCount`,`candidatesTokenCount`],ie=[`gen_ai.usage.total_tokens`,`llm.usage.total_tokens`,`total_tokens`,`usage.total_tokens`,`response.usage.total_tokens`,`usageMetadata.totalTokenCount`,`totalTokenCount`],ae=[`gen_ai.usage.cache_read.input_tokens`,`gen_ai.usage.cache_read_tokens`,`gen_ai.usage.cache_creation.input_tokens`,`gen_ai.usage.cache_write_tokens`,`input_tokens_details.cached_tokens`,`usage.input_tokens_details.cached_tokens`,`response.usage.input_tokens_details.cached_tokens`,`usage.metadata.cached_tokens`,`metadata.cached_tokens`,`cached_tokens`],oe=[`gen_ai.usage.reasoning.output_tokens`,`gen_ai.usage.reasoning_tokens`,`output_tokens_details.reasoning_tokens`,`usage.output_tokens_details.reasoning_tokens`,`response.usage.output_tokens_details.reasoning_tokens`,`usage.metadata.reasoning_tokens`,`metadata.reasoning_tokens`,`reasoning_tokens`],se=[`model_proxy.model`,`gen_ai.response.model`,`gen_ai.request.model`,`llm.response.model`,`llm.request.model`,`response.model`,`model`,`modelVersion`,`requestedModel`],ce=[`model_proxy.provider`,`gen_ai.system`,`llm.provider`,`provider`,`provider_name`,`model_provider`];function N(e){if(typeof e!=`string`)return e;let t=e.trim();if(!t||t[0]!==`{`&&t[0]!==`[`)return e;try{return JSON.parse(t)}catch{return e}}function le(e,t){let n=N(e);if(!n||typeof n!=`object`||Array.isArray(n))return;let r=n[t];if(r!==void 0)return N(r);let i=n;for(let e of t.split(`.`))if(i=N(i),!i||typeof i!=`object`||Array.isArray(i)||(i=i[e],i===void 0))return;return N(i)}function ue(e,t){for(let n of t){let t=le(e,n);if(t!=null&&t!==``)return t}}function de(e){if(typeof e==`number`&&Number.isFinite(e))return Math.max(0,e);if(typeof e==`bigint`)return Number(e);if(typeof e==`string`){let t=Number(e);if(Number.isFinite(t))return Math.max(0,t)}return null}function P(e,t){return de(ue(e,t))}function fe(e,t){let n=ue(e,t);return typeof n==`string`&&n.trim().length>0?n.trim():typeof n==`number`||typeof n==`boolean`?String(n):null}function pe(e){let t=P(e,ne),n=P(e,re),r=P(e,ie),i=P(e,ae),a=P(e,oe),o=t??0,s=n??0;return{inputTokens:o,outputTokens:s,totalTokens:r??o+s,cachedInputTokens:i??0,reasoningOutputTokens:a??0,hasUsage:t!==null||n!==null||r!==null||i!==null||a!==null}}function me(e){return{model:fe(e,se),provider:fe(e,ce)}}function he(e){let t=e.toLowerCase();return t.includes(`gen_ai.usage`)||t.includes(`llm.usage`)||/(^|[._-])(input|output|prompt|completion|total|cached|reasoning|candidates?)_?tokens?($|[._-])/.test(t)||/(^|[._-])(prompt|candidates|total)tokencount($|[._-])/.test(t)}function ge(e){return de(e)!==null}function _e(e){return e}function ve(e){if(!e)return{};try{let t=JSON.parse(e);return t&&typeof t==`object`&&!Array.isArray(t)?t:{}}catch{return{}}}function ye(e){let t=pe(e);return{inputTokens:t.inputTokens,outputTokens:t.outputTokens,totalTokens:t.totalTokens,cachedInputTokens:t.cachedInputTokens,reasoningOutputTokens:t.reasoningOutputTokens,usageEventCount:+!!t.hasUsage,hasUsage:t.hasUsage}}function F(){return{inputTokens:0,outputTokens:0,totalTokens:0,cachedInputTokens:0,reasoningOutputTokens:0,usageEventCount:0}}function be(e,t){e.inputTokens+=t.inputTokens,e.outputTokens+=t.outputTokens,e.totalTokens+=t.totalTokens,e.cachedInputTokens+=t.cachedInputTokens,e.reasoningOutputTokens+=t.reasoningOutputTokens,e.usageEventCount+=t.usageEventCount}function I(e,t){t&&(e[t]=(e[t]??0)+1)}function L(e){return e?(Array.isArray(e)?e:[e]).flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(e=>e.length>0):[]}function xe(e,t){return t.length===0||e!==null&&t.includes(e)}function Se(e){return Math.round(e*100)/100}function R(e,t){if(e.length===0)return 0;let n=[...e].sort((e,t)=>e-t);return n[Math.min(n.length-1,Math.max(0,Math.ceil(n.length*t)-1))]??0}function Ce(e){let t=e.map(e=>e.inputTokens),n=e.map(e=>e.outputTokens),r=e.map(e=>e.totalTokens),i=e=>e.reduce((e,t)=>e+t,0),a=e=>e.length===0?0:Se(i(e)/e.length);return{samples:e.length,avgInputTokens:a(t),p50InputTokens:R(t,.5),p90InputTokens:R(t,.9),avgOutputTokens:a(n),p50OutputTokens:R(n,.5),p90OutputTokens:R(n,.9),avgTotalTokens:a(r),p50TotalTokens:R(r,.5),p90TotalTokens:R(r,.9)}}function we(e,t){return t===0?100:Se(e/t*100)}function Te(e){return e.endsWith(`.tool_token_sample`)}function z(e,...t){for(let n of t){let t=e[n];if(typeof t==`string`&&t.trim().length>0)return t.trim();if(typeof t==`number`||typeof t==`boolean`)return String(t)}return null}function Ee(e){let t=e.metadata,n=e.raw.message??``,r=z(t,`error_type`)??e.raw.error_type,i=t.success,a=t[`tool.result.error`],o=i===!1||i===`false`||a===!0||a===`true`,s=z(t,`decision`),c=z(t,`browse_tool.error.category`);return c===`caller_validation`||c===`caller_execution`?`caller_error`:c===`spec_failure`?`expected_failure`:c===`page_state`?`page_state`:c===`infrastructure_failure`?`infrastructure_failure`:n.includes(`api_error`)?`api_error`:n.includes(`api_retries_exhausted`)?`api_retries_exhausted`:n.includes(`api_refusal`)?`api_refusal`:(n.includes(`tool_result`)||n.includes(`tool error`))&&o?`tool_failure`:n.includes(`tool_decision`)&&s===`reject`?`tool_rejected`:e.raw.level===`error`||e.raw.level===`fatal`||r?`log_error`:null}function De(e,t){return e.message!==`Selected LLM provider`&&e.message!==`LLM provider attempt failed`?null:z(t,`tool`)}function Oe(e){return e.trim().toLowerCase().replace(/[^a-z0-9]+/g,` `)}function ke(e,t){let n=t===`job`?`workflow.job.finished`:`workflow.run.finished`;if(e.raw.message!==n)return!1;let r=t===`job`?`workflow.job.outcome`:`workflow.outcome`;return z(e.metadata,r)===`failed`}let B=class{constructor(e){this.storage=e}async getMetrics(e={},t={}){await this.storage.ensureInitialized();let n=this.storage.getSqliteClient(),r=L(e.model),i=L(e.provider),{whereSql:a,params:o}=this.buildWhereClause(e),s=_e(n.prepare(`
74
74
  SELECT
75
75
  id, timestamp, level, message, service, metadata, error_type, error_message,
76
76
  session_id, workflow_run_id, workflow_name, job_name, job_id, agent_name,
@@ -318,4 +318,4 @@ const e=require(`./node-9pwprHry.cjs`);let t=require(`@agimon-ai/foundation-vali
318
318
  LIMIT ?
319
319
  OFFSET ?
320
320
  `,d=r.prepare(l).get(...s);return{results:Re(r.prepare(u).all(a,...s,n,c)).map(e=>this.mapRow(e)),total:Number(d.total??0)}}catch(r){let i=await this.searchService.searchLogsPaginated(e,t,n);return console.warn(`Semantic search unavailable, falling back to FTS: ${r instanceof Error?r.message:String(r)}`),{results:i.results.map(e=>this.mapFallbackRow(e)),total:i.total}}}};K=w([(0,a.injectable)(),C(0,(0,a.inject)(y.LogStorageService)),C(1,(0,a.inject)(y.LogSearchService)),C(2,(0,a.inject)(y.EmbeddingService)),S(`design:paramtypes`,[Object,Object,Object])],K);const ze=new a.ContainerModule(e=>{e.bind(y.LogStorageService).to(W).inSingletonScope(),e.bind(y.EmbeddingService).to(E).inSingletonScope(),e.bind(y.LogQueryService).to(M).inSingletonScope(),e.bind(y.LogMetricsService).to(B).inSingletonScope(),e.bind(y.LogSearchService).to(U).inSingletonScope(),e.bind(y.SemanticSearchService).to(K).inSingletonScope(),e.bind(y.LogRetentionService).to(V).inSingletonScope(),e.bind(y.HttpServerHealthCheck).to(D).inSingletonScope(),e.bind(y.HttpServerManager).to(k).inSingletonScope()});function Be(){let e=new a.Container;e.load(ze);let t=e.get(y.LogStorageService);if(x()){let n=e.get(y.EmbeddingService);t.setEmbeddingWriter(e=>n.indexLogs(e))}return e}const q=i.z.object({sessionId:i.z.string().optional().describe(`Agent session id to scope the analysis to one agent launch`),workflowRunId:i.z.string().optional().describe(`Workflow run id to scope to all jobs of one workflow run`),workflowName:i.z.string().optional().describe(`Workflow name to scope to all runs of a workflow type`),jobName:i.z.string().optional().describe(`Workflow job name to scope to a single job`),jobId:i.z.string().optional().describe(`Workflow job execution id to scope by`),agentName:i.z.string().optional().describe(`Agent identity to scope by`),workflowRunKey:i.z.string().optional().describe(`Workflow run key to scope by`),workflowWorkspace:i.z.string().optional().describe(`Workflow workspace to scope by`),stepName:i.z.string().optional().describe(`Workflow step name to scope by`),phase:i.z.string().optional().describe(`Workflow phase to scope by`),service:i.z.union([i.z.string(),i.z.array(i.z.string())]).optional().describe(`Agent/service name(s) to scope by (e.g. claude-code, codex)`),startTime:i.z.string().optional().describe(`Start time for the analysis window (ISO 8601 format)`),endTime:i.z.string().optional().describe(`End time for the analysis window (ISO 8601 format)`),limit:i.z.number().min(1).max(1e3).optional().default(100).describe(`Maximum number of issue samples to return`),scanLimit:i.z.number().min(1).max(1e5).optional().default(5e4).describe(`Maximum matching log records to scan; the response reports when this truncates the window`)});var Ve=class e{static TOOL_NAME=`analyze_agent_issues`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getInputSchema(){return q}getDefinition(){return{name:e.TOOL_NAME,description:`Detect and aggregate agent-run problems (failed tool calls, API errors, refusals, retries exhausted, rejected tools, error logs) for reviewing agent performance and improving the repo harness. Filter by session id, workflow run id, workflow name, job name, or agent/service. Returns counts by category/tool/error-type plus sample issues with the tool, input, and error context needed to diagnose them.`,inputSchema:i.z.toJSONSchema(q,{reused:`inline`})}}async execute(e){try{let t=q.parse(e),n=await this.queryService.analyzeAgentIssues({sessionId:t.sessionId,workflowRunId:t.workflowRunId,workflowName:t.workflowName,jobName:t.jobName,jobId:t.jobId,agentName:t.agentName,workflowRunKey:t.workflowRunKey,workflowWorkspace:t.workflowWorkspace,stepName:t.stepName,phase:t.phase,service:t.service,startTime:t.startTime?new Date(t.startTime):void 0,endTime:t.endTime?new Date(t.endTime):void 0},{sampleLimit:t.limit,scanLimit:t.scanLimit});return{content:[{type:`text`,text:JSON.stringify({...n,issues:n.issues.map(e=>({...e,timestamp:e.timestamp.toISOString()}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error analyzing agent issues: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}};const J=i.z.object({startTime:i.z.string().optional().describe(`Start time for statistics (ISO 8601 format)`),endTime:i.z.string().optional().describe(`End time for statistics (ISO 8601 format)`),groupBy:i.z.enum([`level`,`service`,`both`,`agent`,`workflow`,`job`,`signal`]).optional().default(`both`).describe(`Dimension used to group statistics.`),signalType:i.z.enum([`log`,`span`,`all`]).optional().default(`log`).describe(`Count log records by default, span records, or 'all' signals.`)});var Y=class e{static TOOL_NAME=`get_log_stats`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getInputSchema(){return J}getDefinition(){return{name:e.TOOL_NAME,description:`Get aggregate log statistics including counts by level, service, or both. Useful for dashboards and monitoring.`,inputSchema:i.z.toJSONSchema(J,{reused:`inline`})}}async execute(e){try{let t=J.parse(e),n;(t.startTime||t.endTime)&&(n={start:t.startTime?new Date(t.startTime):new Date(0),end:t.endTime?new Date(t.endTime):new Date});let r=await this.queryService.getStatistics(n,t.groupBy,t.signalType);return{content:[{type:`text`,text:JSON.stringify({timeRange:n,groupBy:t.groupBy,signalType:t.signalType,totalEntries:r.reduce((e,t)=>e+t.count,0),statistics:r.map(e=>({service:e.service,level:e.level,count:e.count,value:t.groupBy===`level`?e.level:e.service}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting log stats: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}};const He=i.z.object({});var Ue=class e{static TOOL_NAME=`get_services`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getInputSchema(){return He}getDefinition(){return{name:e.TOOL_NAME,description:`List all active services that have sent logs. Returns service names sorted alphabetically.`,inputSchema:i.z.toJSONSchema(He,{reused:`inline`})}}async execute(e){try{let e=await this.queryService.getActiveServices();return{content:[{type:`text`,text:JSON.stringify({count:e.length,services:e.sort()},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting services: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}};const X=i.z.object({traceId:i.z.string().describe(`OTEL trace ID (32 hex characters)`)});var We=class e{static TOOL_NAME=`get_trace_timeline`;queryService;constructor(e){this.queryService=e.get(y.LogQueryService)}getInputSchema(){return X}getDefinition(){return{name:e.TOOL_NAME,description:`Reconstruct the chronological timeline of a distributed trace. Returns all spans in order with timing, service hops, and log messages.`,inputSchema:i.z.toJSONSchema(X,{reused:`inline`})}}async execute(e){try{let t=X.parse(e),n=await this.queryService.getTraceTimeline(t.traceId);return{content:[{type:`text`,text:JSON.stringify({traceId:t.traceId,count:n.length,timeline:n.map(e=>({timestamp:e.timestamp.toISOString(),service:e.service,spanId:e.spanId,parentSpanId:e.parentSpanId,level:e.level,message:e.message,duration:e.duration}))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error getting trace timeline: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}};let Ge=function(e){return e.TRACE=`trace`,e.DEBUG=`debug`,e.INFO=`info`,e.WARN=`warn`,e.ERROR=`error`,e.FATAL=`fatal`,e}({});const Ke=i.z.enum([`trace`,`debug`,`info`,`warn`,`error`,`fatal`]),qe=i.z.enum([`fts`,`semantic`,`hybrid`]),Z=i.z.object({searchQuery:i.z.string().optional().describe(`Text to search for. Common punctuation such as hyphens is escaped safely; quoted phrases, prefix matching with *, and boolean operators AND/OR/NOT are supported.`),query:i.z.string().optional().describe(`Alias for searchQuery. Use this for full-text search while also applying structured filters.`),mode:qe.optional().default(`hybrid`).describe(`Search strategy to use`),service:i.z.union([i.z.string(),i.z.array(i.z.string())]).optional().describe(`Service name(s) to filter by`),level:i.z.union([Ke,i.z.array(Ke)]).optional().describe(`Log level(s) to filter by`),traceId:i.z.string().optional().describe(`Trace ID to filter by (OTEL format: 32 hex characters)`),spanId:i.z.string().optional().describe(`Span ID to filter by`),errorType:i.z.string().optional().describe(`Error type to filter by`),sessionId:i.z.string().optional().describe(`Agent session id to filter by`),workflowRunId:i.z.string().optional().describe(`Workflow run id to filter by`),workflowName:i.z.string().optional().describe(`Workflow name to filter by`),jobName:i.z.string().optional().describe(`Workflow job name to filter by`),jobId:i.z.string().optional().describe(`Workflow job execution id to filter by`),agentName:i.z.string().optional().describe(`Agent name to filter by`),parentSessionId:i.z.string().optional().describe(`Parent agent session id to filter by`),workflowRunKey:i.z.string().optional().describe(`Stable workflow run key to filter by`),workflowId:i.z.string().optional().describe(`Workflow file id to filter by`),workflowWorkspace:i.z.string().optional().describe(`Workflow workspace to filter by`),stepName:i.z.string().optional().describe(`Workflow step name to filter by`),phase:i.z.string().optional().describe(`Workflow phase to filter by`),signalType:i.z.enum([`log`,`span`]).optional().describe(`Telemetry signal type to filter by`),startTime:i.z.string().optional().describe(`Start time for log range (ISO 8601 format)`),endTime:i.z.string().optional().describe(`End time for log range (ISO 8601 format)`),limit:i.z.number().min(1).max(1e3).optional().default(100).describe(`Maximum number of search results to return`)});var Je=class e{static TOOL_NAME=`search_logs`;queryService;searchService;semanticSearchService;constructor(e){this.queryService=e.get(y.LogQueryService),this.searchService=e.get(y.LogSearchService),this.semanticSearchService=e.get(y.SemanticSearchService)}getInputSchema(){return Z}getDefinition(){return{name:e.TOOL_NAME,description:`Search and query log entries. Supports structured filters such as level, service, trace/session/workflow fields, time range, and optional full-text query using FTS5, local semantic embeddings, or both.`,inputSchema:i.z.toJSONSchema(Z,{reused:`inline`})}}async execute(e){try{let t=Z.parse(e),n=this.buildFilters(t),r=this.getSearchQuery(t),i=t.mode??`hybrid`,a=r?await this.searchByText(r,n,i,t.limit):await this.queryByFilters(n,t.limit);return{content:[{type:`text`,text:JSON.stringify({mode:r?i:`filter`,count:a.length,query:r,filters:Object.keys(n).length>0?this.serializeFilters(n):void 0,results:a.map(e=>this.serializeResult(e,!!r))},null,2)}]}}catch(e){return{content:[{type:`text`,text:`Error searching logs: ${e instanceof Error?e.message:`Unknown error`}`}],isError:!0}}}buildFilters(e){let t={};return e.service&&(t.service=e.service),e.level&&(t.level=e.level),e.traceId&&(t.traceId=e.traceId),e.spanId&&(t.spanId=e.spanId),e.errorType&&(t.errorType=e.errorType),e.sessionId&&(t.sessionId=e.sessionId),e.workflowRunId&&(t.workflowRunId=e.workflowRunId),e.workflowName&&(t.workflowName=e.workflowName),e.jobName&&(t.jobName=e.jobName),e.jobId&&(t.jobId=e.jobId),e.agentName&&(t.agentName=e.agentName),e.parentSessionId&&(t.parentSessionId=e.parentSessionId),e.workflowRunKey&&(t.workflowRunKey=e.workflowRunKey),e.workflowId&&(t.workflowId=e.workflowId),e.workflowWorkspace&&(t.workflowWorkspace=e.workflowWorkspace),e.stepName&&(t.stepName=e.stepName),e.phase&&(t.phase=e.phase),e.signalType&&(t.signalType=e.signalType),e.startTime&&(t.startTime=this.parseDate(e.startTime,`startTime`)),e.endTime&&(t.endTime=this.parseDate(e.endTime,`endTime`)),t}getSearchQuery(e){return(e.searchQuery??e.query)?.trim()||void 0}parseDate(e,t){let n=new Date(e);if(Number.isNaN(n.getTime()))throw Error(`Invalid ${t}: expected ISO 8601 timestamp`);return n}async queryByFilters(e,t){let n=Object.keys(e).length>0,r=!!(e.sessionId||e.workflowRunId||e.workflowName||e.jobName||e.traceId||e.spanId||e.startTime||e.endTime||e.service&&!e.level);return(await this.queryService.queryLogs({...e,level:n?e.level:[`info`,`warn`,`error`,`fatal`],order:r?`asc`:`desc`,limit:t})).logs}async searchByText(e,t,n,r){return n===`semantic`?this.semanticSearchService.searchLogs(e,t,r):n===`fts`?this.searchService.searchLogs(e,t,r):this.searchHybrid(e,t,r)}serializeFilters(e){return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,t instanceof Date?t.toISOString():t]))}serializeResult(e,t){let n=typeof e.score==`number`?e.score:typeof e.rank==`number`?this.getFallbackScore(e.rank):void 0;return{...t?{score:n,rank:e.rank,distance:e.distance,sources:e.sources}:{},id:e.id,timestamp:e.timestamp.toISOString(),level:e.level,message:e.message,service:e.service,traceId:e.traceId,spanId:e.spanId,parentSpanId:e.parentSpanId,hostname:e.hostname,pid:e.pid,metadata:e.metadata,errorType:e.errorType,errorMessage:e.errorMessage,errorStack:e.errorStack,sessionId:e.sessionId,workflowRunId:e.workflowRunId,workflowName:e.workflowName,jobName:e.jobName,jobId:e.jobId,agentName:e.agentName,parentSessionId:e.parentSessionId,workflowRunKey:e.workflowRunKey,workflowId:e.workflowId,workflowWorkspace:e.workflowWorkspace,stepName:e.stepName,phase:e.phase,signalType:e.signalType,durationMs:e.durationMs}}getFallbackScore(e){return 1/(1+Math.max(0,Math.abs(e)))}async searchHybrid(e,t,n){let r=Math.max(n*2,50),i=this.searchService.searchLogs(e,t,r),a=await this.semanticSearchService.isAvailable(),o=await i;if(!a)return o;let s=await this.semanticSearchService.searchLogs(e,t,r),c=new Map;return o.forEach((e,t)=>{c.set(e.id,{result:e,score:.65*(1/(1+t)),rank:e.rank,sources:new Set([`fts`])})}),s.forEach((e,t)=>{let n=c.get(e.id),r=.35*(1/(1+t));n?(n.score+=r,n.sources.add(`semantic`),n.distance=e.distance,n.result={...n.result,...e}):c.set(e.id,{result:e,score:r,distance:e.distance,sources:new Set([`semantic`])})}),Array.from(c.values()).sort((e,t)=>t.score-e.score).slice(0,n).map(e=>({...e.result,score:e.score,sources:Array.from(e.sources),rank:e.rank,distance:e.distance}))}};const Q=`@agimon-ai/log-sink-mcp`;let Ye;function Xe(){return Ye??=e.t({serviceName:Q,workspaceRoot:process.cwd(),discoverEndpoint:!1}),Ye}async function $(e,t,n){let r=await Xe();return r.runInSpan(e,{attributes:t},async()=>{try{return await n()}catch(n){throw r.logger.error(`${e} failed`,{attributes:t,exception:n}),n}})}function Ze(e){let a=new n.Server({name:`log-sink-mcp`,version:`0.1.0`},{capabilities:{tools:{}}}),o=e??Be(),s=[new Je(o),new Ve(o),new We(o),new Y(o),new Ue(o)],c=new Map(s.map(e=>[e.getDefinition().name,e]));return a.setRequestHandler(r.ListToolsRequestSchema,async()=>$(`mcp.server.list_tools`,{"mcp.service":Q},async()=>({tools:s.map(e=>e.getDefinition())}))),a.setRequestHandler(r.CallToolRequestSchema,async e=>{let{name:n,arguments:r}=e.params;return $(`mcp.server.call_tool`,{"mcp.service":Q,"mcp.tool.name":n},async()=>{let e=c.get(n);if(!e)return{content:[{type:`text`,text:`Unknown tool: ${n}`}],isError:!0};let a=(0,t.coerceArgs)(r??{},e.getInputSchema());try{return await e.execute(a)}catch(r){return r instanceof i.z.ZodError?{content:[{type:`text`,text:(0,t.formatZodError)(r,{schemaName:n,schema:e.getInputSchema()})}],isError:!0}:{content:[{type:`text`,text:`Error executing tool ${n}: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}})}),a}var Qe=class{server;transport=null;constructor(e){this.server=e}async start(){this.transport=new v.StdioServerTransport,await this.server.connect(this.transport)}async stop(){this.transport&&=(await this.transport.close(),null)}};Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return We}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return Ve}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return he}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return ge}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return Ge}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return Be}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return Ze}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return Ue}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return Je}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return Qe}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return W}});
321
- //# sourceMappingURL=stdio-Gb0mj6eo.cjs.map
321
+ //# sourceMappingURL=stdio-QFR4qcFs.cjs.map