neatlogs 1.1.21 → 1.1.22

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.
@@ -40,7 +40,7 @@ module.exports = __toCommonJS(opencode_plugin_exports);
40
40
  var import_protobufjs = __toESM(require("protobufjs"));
41
41
 
42
42
  // src/version.ts
43
- var __version__ = "1.1.21";
43
+ var __version__ = "1.1.22";
44
44
 
45
45
  // src/opencode-trace-shipper.ts
46
46
  var PACKAGE_NAME = "neatlogs.opencode";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/opencode-plugin.ts","../src/opencode-trace-shipper.ts","../src/version.ts","../src/constants.ts"],"sourcesContent":["/**\n * Neatlogs opencode plugin.\n *\n * opencode loads plugins from its config (`opencode.json` → `\"plugin\": [...]`)\n * or from local `.opencode/plugin/*.ts` files. A plugin is an async factory that\n * receives an app context and returns lifecycle hooks. This plugin instruments\n * opencode automatically — no per-call wiring — turning each opencode TURN into\n * its own neatlogs trace (mirrors @neatlogs/claude-code):\n *\n * WORKFLOW opencode.turn (one TRACE per user turn; parents that turn's spans)\n * ↳ LLM assistant turn (per completed assistant message)\n * ↳ TOOL tool execution (tool.execute.before → tool.execute.after)\n *\n * A turn opens on `chat.message` and closes on `session.idle` (which fires after\n * the turn's full tool-loop settles) — NOT on each `message.completed`, so a\n * multi-round tool-using turn stays one trace. Every span carries\n * `neatlogs.conversation.id` = the opencode session ID and a per-turn trace id;\n * all of a session's turn-traces are grouped in the UI via `neatlogs.session.id`.\n *\n * Export model (mirrors @raindrop-ai/opencode-plugin and neatlogs-claude-code):\n * opencode loads the plugin in-process but `opencode run` is short-lived. Rather\n * than the OpenTelemetry BatchSpanProcessor (whose async, scheduled-delay export\n * + `beforeExit` shutdown races the teardown and drops spans), this plugin builds\n * spans directly and ships them via AWAITED `fetch(POST /v1/traces)` — and it\n * flushes after every completed assistant turn (incremental persistence) plus a\n * final flush on `session.idle`. A `neatlogs.trace.complete` marker is sent so\n * the backend enqueues the trace for finalization (simplification → UI).\n *\n * Setup — either:\n * • npm package, in opencode.json: `{ \"plugin\": [\"neatlogs/opencode\"] }`, OR\n * • local file `.opencode/plugin/neatlogs.ts`:\n * export { NeatlogsOpencodePlugin as default } from 'neatlogs/opencode';\n *\n * Env:\n * NEATLOGS_API_KEY required to export\n * NEATLOGS_ENDPOINT backend base URL (default https://ingest.neatlogs.com)\n */\n\nimport {\n TraceShipper,\n type OtlpSpan,\n type OtlpKeyValue,\n SpanStatusCode,\n generateTraceId,\n generateSpanId,\n nowNanoString,\n msToNanoString,\n attrStr,\n attrInt,\n attrDouble,\n} from './opencode-trace-shipper.js';\nimport { DEFAULT_INGEST_ENDPOINT } from './constants.js';\n\n/** A span being built incrementally — ended (and shipped) later. */\ninterface OpenSpan {\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n startNano: string;\n attributes: OtlpKeyValue[];\n}\n\ninterface SessionState {\n /** Per-TURN trace id — minted when the turn's root opens, so each turn is its\n * own trace. Undefined between turns. */\n traceId?: Uint8Array;\n /** The current turn's WORKFLOW root span (created on chat.message, ended on idle). */\n rootSpan?: OpenSpan;\n /** Open TOOL spans keyed by callID → start time. */\n toolStarts: Map<string, { spanId: Uint8Array; startNano: string; tool: string; args: any }>;\n /** Accumulated assistant text per messageID (from text parts). */\n outputParts: Map<string, string>;\n /** Tool calls per assistant messageID (so a tool-only turn still has output). */\n toolCalls: Map<string, Array<{ name: string; input: any; callID: string }>>;\n /** assistant messageIDs already emitted (completion can fire repeatedly). */\n processed: Set<string>;\n /** Current user prompt (this turn's input). */\n currentInput: string;\n /** Captured system prompt. */\n systemPrompt?: string;\n /** Latest assistant text — the AGENT root's output on close. */\n lastAssistantText: string;\n}\n\nexport const NeatlogsOpencodePlugin = async (_ctx: any): Promise<Record<string, any>> => {\n const apiKey = (process.env.NEATLOGS_API_KEY ?? '').trim();\n const endpoint = (process.env.NEATLOGS_ENDPOINT ?? DEFAULT_INGEST_ENDPOINT).trim();\n const workflowName = 'opencode';\n const debug = String(process.env.NEATLOGS_DEBUG || '').toLowerCase() === 'true';\n\n const shipper = new TraceShipper({ apiKey, endpoint, workflowName, debug });\n const sessions = new Map<string, SessionState>();\n\n function stateFor(sessionID: string): SessionState {\n let s = sessions.get(sessionID);\n if (!s) {\n s = {\n toolStarts: new Map(),\n outputParts: new Map(),\n toolCalls: new Map(),\n processed: new Set(),\n currentInput: '',\n lastAssistantText: '',\n };\n sessions.set(sessionID, s);\n }\n return s;\n }\n\n /** Start the per-turn WORKFLOW root span, minting a fresh trace id for this\n * turn (idempotent within a turn). `neatlogs.session.id` groups the session's\n * turn-traces in the UI. */\n function startRoot(st: SessionState, sessionID: string): void {\n if (st.rootSpan) return;\n st.traceId = generateTraceId();\n st.rootSpan = {\n spanId: generateSpanId(),\n name: 'opencode.turn',\n startNano: nowNanoString(),\n attributes: [\n { key: 'neatlogs.span.kind', value: { stringValue: 'WORKFLOW' } },\n { key: 'neatlogs.agent.framework', value: { stringValue: 'opencode' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n { key: 'neatlogs.session.id', value: { stringValue: sessionID } },\n ],\n };\n }\n\n /** End + enqueue the WORKFLOW turn root, send the completion marker, and flush.\n * Clears the turn's trace id + accumulators so the next turn is a fresh trace. */\n async function closeAndFlush(st: SessionState, sessionID: string): Promise<void> {\n if (st.rootSpan && st.traceId) {\n const attrs = st.rootSpan.attributes.slice();\n setIO(attrs, 'WORKFLOW', st.currentInput || undefined, st.lastAssistantText || undefined);\n shipper.enqueue({\n traceId: st.traceId,\n spanId: st.rootSpan.spanId,\n name: st.rootSpan.name,\n kind: 1,\n startTimeUnixNano: st.rootSpan.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n // Completion marker — the backend only finalizes (simplifies → UI) a trace\n // once it sees a `neatlogs.trace.complete` span. Parented to the root.\n const m = nowNanoString();\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan.spanId,\n name: 'neatlogs.trace.complete',\n kind: 1,\n startTimeUnixNano: m,\n endTimeUnixNano: m,\n attributes: [\n { key: 'neatlogs.trace.complete', value: { boolValue: true } },\n { key: 'neatlogs.internal', value: { boolValue: true } },\n { key: 'neatlogs.span.kind', value: { stringValue: 'Neatlogs.INTERNAL' } },\n ],\n });\n }\n // Reset per-turn state so the next chat.message opens a brand-new trace.\n st.rootSpan = undefined;\n st.traceId = undefined;\n st.currentInput = '';\n st.lastAssistantText = '';\n st.processed.clear();\n st.outputParts.clear();\n st.toolCalls.clear();\n await shipper.flush();\n void sessionID;\n }\n\n return {\n /**\n * Awaited by opencode on scope teardown (registered via an internal\n * `addFinalizer`), unlike the fire-and-forget `event` hook. On a short-lived\n * `opencode run`, `session.idle`'s `await shipper.flush()` is a dangling\n * promise the process kills before the POST resolves — so we close any turn\n * still open and `settle()` all in-flight flushes here, before exit.\n */\n dispose: async () => {\n try {\n for (const [sessionID, st] of sessions) {\n if (st.rootSpan) await closeAndFlush(st, sessionID);\n }\n await shipper.settle();\n } catch {\n /* never break opencode over tracing */\n }\n },\n\n /** Fired when the user submits a prompt — open the turn's AGENT root. */\n 'chat.message': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? output?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const parts = output?.parts ?? [];\n const text = Array.isArray(parts)\n ? parts\n .filter((p: any) => p?.type === 'text' && typeof p.text === 'string')\n .map((p: any) => p.text)\n .join('\\n')\n : '';\n if (text) st.currentInput = text;\n startRoot(st, sessionID);\n } catch {\n /* ignore */\n }\n },\n\n /** Capture the system prompt. */\n 'experimental.chat.system.transform': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? '');\n const parts = output?.system ?? output?.parts ?? output;\n const joined = Array.isArray(parts) ? parts.map((p: any) => (typeof p === 'string' ? p : p?.text ?? '')).join('\\n') : String(parts ?? '');\n if (sessionID && joined) stateFor(sessionID).systemPrompt = joined;\n } catch {\n /* ignore */\n }\n },\n\n /** Global event bus — message parts, assistant completions, session idle. */\n event: async ({ event }: { event: any }) => {\n try {\n await handleEvent(shipper, sessions, stateFor, startRoot, closeAndFlush, event);\n } catch {\n // never break opencode over tracing\n }\n },\n\n /** Tool start — record start time + args (span built atomically in `after`). */\n 'tool.execute.before': async (input: any, output: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n startRoot(st, sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n st.toolStarts.set(callID, {\n spanId: generateSpanId(),\n startNano: nowNanoString(),\n tool: String(input?.tool ?? 'tool'),\n args: output?.args,\n });\n } catch {\n /* ignore */\n }\n },\n\n /** Tool end — enqueue the completed TOOL span (parented to the turn root). */\n 'tool.execute.after': async (input: any, result: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n const start = st.toolStarts.get(callID);\n if (!start) return;\n st.toolStarts.delete(callID);\n if (!st.traceId) return;\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'TOOL' } },\n { key: 'neatlogs.tool.name', value: { stringValue: start.tool } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n if (start.args !== undefined) {\n // The shipper bypasses the SDK attribute-processor, so emit the\n // already-namespaced keys the backend consumer reads directly\n // (neatlogs.tool.input / .output and the generic neatlogs.input.value),\n // not the raw input.value/output.value the processor would map.\n setIO(attrs, 'TOOL', safeStringify(start.args), undefined);\n push(attrs, attrStr('neatlogs.tool.input', safeStringify(start.args)));\n }\n if (result?.title) push(attrs, attrStr('neatlogs.tool.title', String(result.title)));\n const out = result?.output ?? result?.result;\n if (out !== undefined) {\n const o = typeof out === 'string' ? out : safeStringify(out);\n setIO(attrs, 'TOOL', undefined, o);\n push(attrs, attrStr('neatlogs.tool.output', o));\n }\n if (result?.metadata !== undefined) {\n push(attrs, attrStr('neatlogs.tool.metadata', safeStringify(result.metadata)));\n }\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: start.spanId,\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.tool.${start.tool}`,\n kind: 1,\n startTimeUnixNano: start.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n } catch {\n /* ignore */\n }\n },\n };\n};\n\n// Convenience aliases so users can import under any common name.\nexport const neatlogsOpencodePlugin = NeatlogsOpencodePlugin;\nexport default NeatlogsOpencodePlugin;\n\n// ---------------------------------------------------------------------------\n// Event handling\n// ---------------------------------------------------------------------------\n\nfunction handleEvent(\n shipper: TraceShipper,\n sessions: Map<string, SessionState>,\n stateFor: (sessionID: string) => SessionState,\n startRoot: (st: SessionState, sessionID: string) => void,\n closeAndFlush: (st: SessionState, sessionID: string) => Promise<void>,\n event: any,\n): Promise<unknown> | undefined {\n const type = event?.type;\n const props = event?.properties ?? {};\n\n // Accumulate text + tool-call parts on an assistant message.\n if (type === 'message.part.updated' || type === 'message.part.completed') {\n const part = props.part ?? props;\n const messageID = part?.messageID ?? part?.message_id;\n const sessionID = part?.sessionID ?? props.sessionID;\n if (!messageID || !sessionID) return undefined;\n const st = stateFor(String(sessionID));\n if (part?.type === 'text' && typeof part?.text === 'string') {\n st.outputParts.set(String(messageID), part.text);\n } else if (part?.type === 'tool' && part?.tool) {\n const list = st.toolCalls.get(String(messageID)) ?? [];\n const callID = String(part.callID ?? part.tool);\n const input = part?.state?.input ?? {};\n const existing = list.find((t) => t.callID === callID);\n if (existing) existing.input = input;\n else list.push({ name: String(part.tool), input, callID });\n st.toolCalls.set(String(messageID), list);\n }\n return undefined;\n }\n\n // Assistant message completed → emit the LLM span, then flush this turn.\n if (type === 'message.updated' || type === 'message.completed') {\n const info = props.info ?? props.message ?? props;\n const sessionID = info?.sessionID ?? info?.session_id;\n if (!sessionID) return undefined;\n if (info?.role !== 'assistant') return undefined;\n const completed = info?.time?.completed ?? info?.completed;\n const id = String(info?.id ?? '');\n if (!completed || !id) return undefined;\n const st = stateFor(String(sessionID));\n if (st.processed.has(id)) return undefined;\n st.processed.add(id);\n startRoot(st, String(sessionID));\n emitLlmSpan(shipper, st, info, String(sessionID));\n // Incremental persistence: ship this turn's spans now (don't wait for idle).\n return shipper.flush().catch(() => undefined);\n }\n\n // Session finished → end root, send completion marker, final flush.\n if (type === 'session.idle' || type === 'session.deleted') {\n const sessionID = props.sessionID ?? props.info?.id;\n if (!sessionID) return undefined;\n const st = sessions.get(String(sessionID));\n if (!st) return undefined;\n st.toolStarts.clear();\n const p = closeAndFlush(st, String(sessionID));\n if (type === 'session.deleted') sessions.delete(String(sessionID));\n return p;\n }\n\n return undefined;\n}\n\nfunction emitLlmSpan(shipper: TraceShipper, st: SessionState, info: any, sessionID: string): void {\n if (!st.traceId) return;\n const model = info?.modelID ?? info?.model ?? '';\n const provider = info?.providerID ?? info?.provider ?? '';\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'LLM' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n push(attrs, attrStr('neatlogs.llm.model_name', model ? String(model) : undefined));\n push(attrs, attrStr('neatlogs.llm.provider', provider ? String(provider) : undefined));\n\n let inIdx = 0;\n if (st.systemPrompt) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'system'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.systemPrompt));\n inIdx++;\n }\n if (st.currentInput) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'user'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.currentInput));\n setIO(attrs, 'LLM', st.currentInput, undefined);\n }\n\n const outText = st.outputParts.get(String(info?.id)) || messageText(info) || '';\n const toolCalls = st.toolCalls.get(String(info?.id)) ?? [];\n\n if (outText) {\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', outText));\n setIO(attrs, 'LLM', undefined, outText);\n st.lastAssistantText = outText;\n }\n // Tool-deciding turns often carry no text — render the tool call(s) as output.\n if (toolCalls.length) {\n toolCalls.forEach((tc, j) => {\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.name`, tc.name));\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.input ?? {})));\n });\n if (!outText) {\n const rendered = toolCalls.map((tc) => `→ ${tc.name}(${safeStringify(tc.input ?? {})})`).join('\\n');\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', rendered));\n setIO(attrs, 'LLM', undefined, rendered);\n }\n }\n\n // Tokens: opencode message tokens { input, output, reasoning, cache:{read,write} }\n const tokens = info?.tokens;\n if (tokens) {\n push(attrs, attrInt('neatlogs.llm.token_count.prompt', tokens.input));\n push(attrs, attrInt('neatlogs.llm.token_count.completion', tokens.output));\n if (tokens.input != null && tokens.output != null) {\n push(attrs, attrInt('neatlogs.llm.token_count.total', tokens.input + tokens.output));\n }\n push(attrs, attrInt('neatlogs.llm.token_count.reasoning', tokens.reasoning));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_read', tokens.cache?.read));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_write', tokens.cache?.write));\n }\n push(attrs, attrDouble('neatlogs.llm.cost_usd', info?.cost));\n push(attrs, attrStr('neatlogs.llm.finish_reason', info?.finish ? String(info.finish) : undefined));\n\n // Use opencode's real start time when available (else now).\n const createdMs = info?.time?.created;\n const startNano = typeof createdMs === 'number' ? msToNanoString(Math.floor(createdMs)) : nowNanoString();\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.llm.${model || 'model'}`,\n kind: 1,\n startTimeUnixNano: startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n\n // Reset accumulated parts for the next turn.\n if (info?.id) {\n st.outputParts.delete(String(info.id));\n st.toolCalls.delete(String(info.id));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction push(arr: OtlpKeyValue[], kv: OtlpKeyValue | undefined): void {\n if (kv) arr.push(kv);\n}\n\n/**\n * Set generic input/output on a span using the ALREADY-NAMESPACED keys the\n * backend consumer reads. The OTel-SDK wrappers rely on the attribute-processor\n * to map raw `input.value` → `neatlogs.{kind}.input`; this plugin ships spans\n * directly (no processor), so it must emit the namespaced keys itself:\n * neatlogs.input.value / neatlogs.output.value (generic)\n * neatlogs.{kind}.input / neatlogs.{kind}.output (kind-specific)\n * We also keep the raw input.value/output.value for any consumer that maps it.\n */\nfunction setIO(arr: OtlpKeyValue[], kind: string, input?: string, output?: string): void {\n const k = kind.toLowerCase();\n if (input !== undefined) {\n push(arr, attrStr('input.value', input));\n push(arr, attrStr('neatlogs.input.value', input));\n push(arr, attrStr(`neatlogs.${k}.input`, input));\n }\n if (output !== undefined) {\n push(arr, attrStr('output.value', output));\n push(arr, attrStr('neatlogs.output.value', output));\n push(arr, attrStr(`neatlogs.${k}.output`, output));\n }\n}\n\n/** Flatten an opencode message's parts/content to readable text. */\nfunction messageText(info: any): string {\n if (!info) return '';\n if (typeof info.text === 'string') return info.text;\n const parts = info.parts ?? info.content;\n if (typeof parts === 'string') return parts;\n if (!Array.isArray(parts)) return '';\n const out: string[] = [];\n for (const p of parts) {\n if (typeof p === 'string') out.push(p);\n else if (p && typeof p === 'object' && typeof p.text === 'string') out.push(p.text);\n }\n return out.join('');\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n","/**\n * Direct OTLP trace shipper for the opencode plugin.\n *\n * opencode loads the plugin in-process but `opencode run` is short-lived — it\n * tears down the moment a session goes idle. The OpenTelemetry BatchSpanProcessor\n * (async, scheduled-delay export + a `beforeExit` shutdown) races that teardown,\n * dropping spans or leaving aborted half-sent requests. This shipper mirrors the\n * proven `neatlogs-claude-code` design instead: spans are queued, then `flush()`\n * does a single AWAITED `fetch(POST /v1/traces)` round-trip that completes before\n * the host process can exit. No batch processor, no exit-time race.\n *\n * Self-contained (inlined OTLP protobuf schema) so it adds no runtime file I/O.\n */\n\nimport protobuf from 'protobufjs';\nimport { __version__ } from './version.js';\n\nconst PACKAGE_NAME = 'neatlogs.opencode';\n\nexport interface OtlpKeyValue {\n key: string;\n value: {\n stringValue?: string;\n intValue?: string;\n doubleValue?: number;\n boolValue?: boolean;\n };\n}\n\nexport interface OtlpSpan {\n traceId: Uint8Array;\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n /** OTLP SpanKind enum (0=unspecified, 1=internal, …). Neatlogs kind rides in attributes. */\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: OtlpKeyValue[];\n status?: { code: number; message?: string };\n}\n\n// Inlined OTLP proto definition — avoids .proto file I/O at runtime.\nconst OTLP_PROTO_JSON: protobuf.INamespace = {\n nested: {\n opentelemetry: {\n nested: {\n proto: {\n nested: {\n common: {\n nested: {\n v1: {\n nested: {\n AnyValue: {\n oneofs: {\n value: {\n oneof: [\n 'stringValue',\n 'boolValue',\n 'intValue',\n 'doubleValue',\n 'arrayValue',\n 'kvlistValue',\n 'bytesValue',\n ],\n },\n },\n fields: {\n stringValue: { type: 'string', id: 1 },\n boolValue: { type: 'bool', id: 2 },\n intValue: { type: 'int64', id: 3 },\n doubleValue: { type: 'double', id: 4 },\n arrayValue: { type: 'ArrayValue', id: 5 },\n kvlistValue: { type: 'KeyValueList', id: 6 },\n bytesValue: { type: 'bytes', id: 7 },\n },\n },\n ArrayValue: { fields: { values: { rule: 'repeated', type: 'AnyValue', id: 1 } } },\n KeyValueList: { fields: { values: { rule: 'repeated', type: 'KeyValue', id: 1 } } },\n KeyValue: {\n fields: { key: { type: 'string', id: 1 }, value: { type: 'AnyValue', id: 2 } },\n },\n InstrumentationScope: {\n fields: { name: { type: 'string', id: 1 }, version: { type: 'string', id: 2 } },\n },\n },\n },\n },\n },\n resource: {\n nested: {\n v1: {\n nested: {\n Resource: {\n fields: {\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n trace: {\n nested: {\n v1: {\n nested: {\n ResourceSpans: {\n fields: {\n resource: { type: 'opentelemetry.proto.resource.v1.Resource', id: 1 },\n scopeSpans: { rule: 'repeated', type: 'ScopeSpans', id: 2 },\n },\n },\n ScopeSpans: {\n fields: {\n scope: { type: 'opentelemetry.proto.common.v1.InstrumentationScope', id: 1 },\n spans: { rule: 'repeated', type: 'Span', id: 2 },\n },\n },\n Span: {\n fields: {\n traceId: { type: 'bytes', id: 1 },\n spanId: { type: 'bytes', id: 2 },\n traceState: { type: 'string', id: 3 },\n parentSpanId: { type: 'bytes', id: 4 },\n name: { type: 'string', id: 5 },\n kind: { type: 'SpanKind', id: 6 },\n startTimeUnixNano: { type: 'fixed64', id: 7 },\n endTimeUnixNano: { type: 'fixed64', id: 8 },\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 9,\n },\n droppedAttributesCount: { type: 'uint32', id: 10 },\n status: { type: 'Status', id: 15 },\n },\n },\n Status: {\n fields: { message: { type: 'string', id: 2 }, code: { type: 'StatusCode', id: 3 } },\n },\n StatusCode: {\n values: { STATUS_CODE_UNSET: 0, STATUS_CODE_OK: 1, STATUS_CODE_ERROR: 2 },\n },\n SpanKind: {\n values: {\n SPAN_KIND_UNSPECIFIED: 0,\n SPAN_KIND_INTERNAL: 1,\n SPAN_KIND_SERVER: 2,\n SPAN_KIND_CLIENT: 3,\n SPAN_KIND_PRODUCER: 4,\n SPAN_KIND_CONSUMER: 5,\n },\n },\n },\n },\n },\n },\n collector: {\n nested: {\n trace: {\n nested: {\n v1: {\n nested: {\n ExportTraceServiceRequest: {\n fields: {\n resourceSpans: {\n rule: 'repeated',\n type: 'opentelemetry.proto.trace.v1.ResourceSpans',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nconst protoRoot = protobuf.Root.fromJSON(OTLP_PROTO_JSON);\nconst ExportTraceServiceRequest = protoRoot.lookupType(\n 'opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest',\n);\n\nexport const SpanStatusCode = { UNSET: 0, OK: 1, ERROR: 2 } as const;\n\n// ---------------------------------------------------------------------------\n// ID + time + attribute helpers\n// ---------------------------------------------------------------------------\n\nfunction randomBytes(length: number): Uint8Array {\n const out = new Uint8Array(length);\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(out);\n return out;\n }\n for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);\n return out;\n}\n\nexport function generateTraceId(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function generateSpanId(): Uint8Array {\n return randomBytes(8);\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport function nowNanoString(): string {\n return (BigInt(Date.now()) * 1_000_000n).toString();\n}\n\nexport function msToNanoString(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString();\n}\n\nexport function attrStr(key: string, value: string | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null) return undefined;\n return { key, value: { stringValue: String(value) } };\n}\n\nexport function attrInt(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { intValue: String(Math.trunc(value)) } };\n}\n\nexport function attrDouble(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { doubleValue: value } };\n}\n\nexport interface TraceShipperOptions {\n apiKey: string;\n endpoint: string;\n debug?: boolean;\n maxRetries?: number;\n workflowName?: string;\n}\n\nexport class TraceShipper {\n private apiKey: string;\n private endpoint: string;\n private debug: boolean;\n private maxRetries: number;\n workflowName: string;\n private queue: OtlpSpan[] = [];\n private prefix = '[neatlogs/opencode]';\n /** In-flight flush round-trips — awaited by `settle()` on dispose so a\n * short-lived host (`opencode run`) can force pending exports to complete. */\n private inflight = new Set<Promise<void>>();\n\n constructor(opts: TraceShipperOptions) {\n this.apiKey = opts.apiKey;\n this.endpoint = opts.endpoint.endsWith('/') ? opts.endpoint.slice(0, -1) : opts.endpoint;\n this.debug = !!opts.debug;\n this.maxRetries = opts.maxRetries ?? 3;\n this.workflowName = opts.workflowName || '';\n }\n\n enqueue(span: OtlpSpan): void {\n this.queue.push(span);\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n /**\n * Ship all queued spans in a single awaited POST. Resolves only once the HTTP\n * response is received (or all retries are exhausted) — so a short-lived host\n * can safely exit immediately after awaiting this.\n *\n * The returned promise is also tracked in `inflight` so `settle()` can await\n * it even when the caller (an un-awaited opencode `event` hook) drops it.\n */\n flush(): Promise<void> {\n const p = this._flush().finally(() => this.inflight.delete(p));\n this.inflight.add(p);\n return p;\n }\n\n /**\n * Await every flush started so far (including ones whose promise the caller\n * discarded). Called from the plugin's `dispose` hook, which opencode DOES\n * await on scope teardown — unlike the fire-and-forget `event` hook.\n */\n async settle(): Promise<void> {\n while (this.inflight.size > 0) {\n await Promise.allSettled(Array.from(this.inflight));\n }\n }\n\n private async _flush(): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.apiKey) {\n this.queue = [];\n return;\n }\n\n const spans = this.queue.splice(0);\n const payload = this.buildProtobuf(spans);\n const url = `${this.endpoint}/v1/traces`;\n\n if (this.debug) console.log(`${this.prefix} Shipping ${spans.length} spans to ${url}`);\n\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n try {\n const resp = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'x-api-key': this.apiKey,\n },\n body: payload as any,\n });\n\n if (resp.ok) {\n if (this.debug) console.log(`${this.prefix} Shipped ${spans.length} spans`);\n return;\n }\n if (resp.status === 401) {\n console.warn(`${this.prefix} Invalid API key (401) — dropping ${spans.length} spans`);\n return;\n }\n if (resp.status < 500 && resp.status !== 429) {\n if (this.debug) console.warn(`${this.prefix} HTTP ${resp.status} — dropping spans`);\n return;\n }\n // 429 / 5xx → retry\n } catch (err) {\n if (this.debug) {\n console.warn(\n `${this.prefix} Attempt ${attempt}/${this.maxRetries}: ${(err as Error).message}`,\n );\n }\n }\n if (attempt < this.maxRetries) {\n await new Promise((r) => setTimeout(r, 500 * 2 ** (attempt - 1)));\n }\n }\n console.warn(`${this.prefix} Failed to ship ${spans.length} spans after ${this.maxRetries} attempts`);\n }\n\n private buildProtobuf(spans: OtlpSpan[]): Uint8Array {\n const protoSpans = spans.map((span) => ({\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || undefined,\n name: span.name,\n kind: span.kind,\n startTimeUnixNano: nanoToLong(span.startTimeUnixNano),\n endTimeUnixNano: nanoToLong(span.endTimeUnixNano),\n attributes: span.attributes.map((a) => ({\n key: a.key,\n value:\n a.value.intValue !== undefined\n ? { intValue: nanoToLong(a.value.intValue) }\n : a.value,\n })),\n status: span.status ? { code: span.status.code, message: span.status.message } : undefined,\n }));\n\n const resourceAttributes: Array<{ key: string; value: { stringValue: string } }> = [\n { key: 'service.name', value: { stringValue: 'neatlogs.opencode' } },\n { key: 'service.version', value: { stringValue: __version__ } },\n ];\n if (this.workflowName) {\n resourceAttributes.push({\n key: 'neatlogs.workflow_name',\n value: { stringValue: this.workflowName },\n });\n }\n\n const message = {\n resourceSpans: [\n {\n resource: { attributes: resourceAttributes },\n scopeSpans: [\n {\n scope: { name: PACKAGE_NAME, version: __version__ },\n spans: protoSpans,\n },\n ],\n },\n ],\n };\n\n const errMsg = ExportTraceServiceRequest.verify(message);\n if (errMsg && this.debug) console.warn(`${this.prefix} Proto verify: ${errMsg}`);\n\n return ExportTraceServiceRequest.encode(ExportTraceServiceRequest.fromObject(message)).finish();\n }\n}\n\n/** protobufjs encodes fixed64/int64 from a {low,high,unsigned} Long-like. */\nfunction nanoToLong(nanoStr: string): { low: number; high: number; unsigned: boolean } {\n const big = BigInt(nanoStr);\n const low = Number(big & 0xffffffffn);\n const high = Number((big >> 32n) & 0xffffffffn);\n return { low, high, unsigned: true };\n}\n","/**\n * SDK version. Kept in sync with package.json by the `version:sync` script\n * (runs automatically on `prebuild`). Do not edit by hand — bump package.json.\n */\nexport const __version__ = '1.1.21';\n","/** Stable SDK-wide defaults shared by every NeatLogs entry point. */\nexport const DEFAULT_INGEST_ENDPOINT = 'https://ingest.neatlogs.com' as const;\nexport const DEFAULT_MAX_QUEUE_ITEMS = 2048;\nexport const DEFAULT_MAX_SEMANTIC_STREAM_EVENTS = 128;\nexport const DEFAULT_MAX_STREAM_CAPTURE_BYTES = 1024 * 1024;\nexport const DEFAULT_MAX_STREAM_CAPTURE_ITEMS = 1024;\n\n/** UTF-8 byte length without allocating a second buffer for hostile stream chunks. */\nexport function utf8ByteLength(\n value: string,\n limit = Number.MAX_SAFE_INTEGER,\n): number {\n let bytes = 0;\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff && i + 1 < value.length) {\n const next = value.charCodeAt(i + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n i += 1;\n } else bytes += 3;\n } else bytes += 3;\n if (bytes > limit) return limit + 1;\n }\n return bytes;\n}\n\nexport function exportQueueCapacity(batchSize: number): number {\n return Math.max(DEFAULT_MAX_QUEUE_ITEMS, batchSize * 4);\n}\n"],"mappings":"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","names":["protobuf"]}
1
+ {"version":3,"sources":["../src/opencode-plugin.ts","../src/opencode-trace-shipper.ts","../src/version.ts","../src/constants.ts"],"sourcesContent":["/**\n * Neatlogs opencode plugin.\n *\n * opencode loads plugins from its config (`opencode.json` → `\"plugin\": [...]`)\n * or from local `.opencode/plugin/*.ts` files. A plugin is an async factory that\n * receives an app context and returns lifecycle hooks. This plugin instruments\n * opencode automatically — no per-call wiring — turning each opencode TURN into\n * its own neatlogs trace (mirrors @neatlogs/claude-code):\n *\n * WORKFLOW opencode.turn (one TRACE per user turn; parents that turn's spans)\n * ↳ LLM assistant turn (per completed assistant message)\n * ↳ TOOL tool execution (tool.execute.before → tool.execute.after)\n *\n * A turn opens on `chat.message` and closes on `session.idle` (which fires after\n * the turn's full tool-loop settles) — NOT on each `message.completed`, so a\n * multi-round tool-using turn stays one trace. Every span carries\n * `neatlogs.conversation.id` = the opencode session ID and a per-turn trace id;\n * all of a session's turn-traces are grouped in the UI via `neatlogs.session.id`.\n *\n * Export model (mirrors @raindrop-ai/opencode-plugin and neatlogs-claude-code):\n * opencode loads the plugin in-process but `opencode run` is short-lived. Rather\n * than the OpenTelemetry BatchSpanProcessor (whose async, scheduled-delay export\n * + `beforeExit` shutdown races the teardown and drops spans), this plugin builds\n * spans directly and ships them via AWAITED `fetch(POST /v1/traces)` — and it\n * flushes after every completed assistant turn (incremental persistence) plus a\n * final flush on `session.idle`. A `neatlogs.trace.complete` marker is sent so\n * the backend enqueues the trace for finalization (simplification → UI).\n *\n * Setup — either:\n * • npm package, in opencode.json: `{ \"plugin\": [\"neatlogs/opencode\"] }`, OR\n * • local file `.opencode/plugin/neatlogs.ts`:\n * export { NeatlogsOpencodePlugin as default } from 'neatlogs/opencode';\n *\n * Env:\n * NEATLOGS_API_KEY required to export\n * NEATLOGS_ENDPOINT backend base URL (default https://ingest.neatlogs.com)\n */\n\nimport {\n TraceShipper,\n type OtlpSpan,\n type OtlpKeyValue,\n SpanStatusCode,\n generateTraceId,\n generateSpanId,\n nowNanoString,\n msToNanoString,\n attrStr,\n attrInt,\n attrDouble,\n} from './opencode-trace-shipper.js';\nimport { DEFAULT_INGEST_ENDPOINT } from './constants.js';\n\n/** A span being built incrementally — ended (and shipped) later. */\ninterface OpenSpan {\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n startNano: string;\n attributes: OtlpKeyValue[];\n}\n\ninterface SessionState {\n /** Per-TURN trace id — minted when the turn's root opens, so each turn is its\n * own trace. Undefined between turns. */\n traceId?: Uint8Array;\n /** The current turn's WORKFLOW root span (created on chat.message, ended on idle). */\n rootSpan?: OpenSpan;\n /** Open TOOL spans keyed by callID → start time. */\n toolStarts: Map<string, { spanId: Uint8Array; startNano: string; tool: string; args: any }>;\n /** Accumulated assistant text per messageID (from text parts). */\n outputParts: Map<string, string>;\n /** Tool calls per assistant messageID (so a tool-only turn still has output). */\n toolCalls: Map<string, Array<{ name: string; input: any; callID: string }>>;\n /** assistant messageIDs already emitted (completion can fire repeatedly). */\n processed: Set<string>;\n /** Current user prompt (this turn's input). */\n currentInput: string;\n /** Captured system prompt. */\n systemPrompt?: string;\n /** Latest assistant text — the AGENT root's output on close. */\n lastAssistantText: string;\n}\n\nexport const NeatlogsOpencodePlugin = async (_ctx: any): Promise<Record<string, any>> => {\n const apiKey = (process.env.NEATLOGS_API_KEY ?? '').trim();\n const endpoint = (process.env.NEATLOGS_ENDPOINT ?? DEFAULT_INGEST_ENDPOINT).trim();\n const workflowName = 'opencode';\n const debug = String(process.env.NEATLOGS_DEBUG || '').toLowerCase() === 'true';\n\n const shipper = new TraceShipper({ apiKey, endpoint, workflowName, debug });\n const sessions = new Map<string, SessionState>();\n\n function stateFor(sessionID: string): SessionState {\n let s = sessions.get(sessionID);\n if (!s) {\n s = {\n toolStarts: new Map(),\n outputParts: new Map(),\n toolCalls: new Map(),\n processed: new Set(),\n currentInput: '',\n lastAssistantText: '',\n };\n sessions.set(sessionID, s);\n }\n return s;\n }\n\n /** Start the per-turn WORKFLOW root span, minting a fresh trace id for this\n * turn (idempotent within a turn). `neatlogs.session.id` groups the session's\n * turn-traces in the UI. */\n function startRoot(st: SessionState, sessionID: string): void {\n if (st.rootSpan) return;\n st.traceId = generateTraceId();\n st.rootSpan = {\n spanId: generateSpanId(),\n name: 'opencode.turn',\n startNano: nowNanoString(),\n attributes: [\n { key: 'neatlogs.span.kind', value: { stringValue: 'WORKFLOW' } },\n { key: 'neatlogs.agent.framework', value: { stringValue: 'opencode' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n { key: 'neatlogs.session.id', value: { stringValue: sessionID } },\n ],\n };\n }\n\n /** End + enqueue the WORKFLOW turn root, send the completion marker, and flush.\n * Clears the turn's trace id + accumulators so the next turn is a fresh trace. */\n async function closeAndFlush(st: SessionState, sessionID: string): Promise<void> {\n if (st.rootSpan && st.traceId) {\n const attrs = st.rootSpan.attributes.slice();\n setIO(attrs, 'WORKFLOW', st.currentInput || undefined, st.lastAssistantText || undefined);\n shipper.enqueue({\n traceId: st.traceId,\n spanId: st.rootSpan.spanId,\n name: st.rootSpan.name,\n kind: 1,\n startTimeUnixNano: st.rootSpan.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n // Completion marker — the backend only finalizes (simplifies → UI) a trace\n // once it sees a `neatlogs.trace.complete` span. Parented to the root.\n const m = nowNanoString();\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan.spanId,\n name: 'neatlogs.trace.complete',\n kind: 1,\n startTimeUnixNano: m,\n endTimeUnixNano: m,\n attributes: [\n { key: 'neatlogs.trace.complete', value: { boolValue: true } },\n { key: 'neatlogs.internal', value: { boolValue: true } },\n { key: 'neatlogs.span.kind', value: { stringValue: 'Neatlogs.INTERNAL' } },\n ],\n });\n }\n // Reset per-turn state so the next chat.message opens a brand-new trace.\n st.rootSpan = undefined;\n st.traceId = undefined;\n st.currentInput = '';\n st.lastAssistantText = '';\n st.processed.clear();\n st.outputParts.clear();\n st.toolCalls.clear();\n await shipper.flush();\n void sessionID;\n }\n\n return {\n /**\n * Awaited by opencode on scope teardown (registered via an internal\n * `addFinalizer`), unlike the fire-and-forget `event` hook. On a short-lived\n * `opencode run`, `session.idle`'s `await shipper.flush()` is a dangling\n * promise the process kills before the POST resolves — so we close any turn\n * still open and `settle()` all in-flight flushes here, before exit.\n */\n dispose: async () => {\n try {\n for (const [sessionID, st] of sessions) {\n if (st.rootSpan) await closeAndFlush(st, sessionID);\n }\n await shipper.settle();\n } catch {\n /* never break opencode over tracing */\n }\n },\n\n /** Fired when the user submits a prompt — open the turn's AGENT root. */\n 'chat.message': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? output?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const parts = output?.parts ?? [];\n const text = Array.isArray(parts)\n ? parts\n .filter((p: any) => p?.type === 'text' && typeof p.text === 'string')\n .map((p: any) => p.text)\n .join('\\n')\n : '';\n if (text) st.currentInput = text;\n startRoot(st, sessionID);\n } catch {\n /* ignore */\n }\n },\n\n /** Capture the system prompt. */\n 'experimental.chat.system.transform': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? '');\n const parts = output?.system ?? output?.parts ?? output;\n const joined = Array.isArray(parts) ? parts.map((p: any) => (typeof p === 'string' ? p : p?.text ?? '')).join('\\n') : String(parts ?? '');\n if (sessionID && joined) stateFor(sessionID).systemPrompt = joined;\n } catch {\n /* ignore */\n }\n },\n\n /** Global event bus — message parts, assistant completions, session idle. */\n event: async ({ event }: { event: any }) => {\n try {\n await handleEvent(shipper, sessions, stateFor, startRoot, closeAndFlush, event);\n } catch {\n // never break opencode over tracing\n }\n },\n\n /** Tool start — record start time + args (span built atomically in `after`). */\n 'tool.execute.before': async (input: any, output: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n startRoot(st, sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n st.toolStarts.set(callID, {\n spanId: generateSpanId(),\n startNano: nowNanoString(),\n tool: String(input?.tool ?? 'tool'),\n args: output?.args,\n });\n } catch {\n /* ignore */\n }\n },\n\n /** Tool end — enqueue the completed TOOL span (parented to the turn root). */\n 'tool.execute.after': async (input: any, result: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n const start = st.toolStarts.get(callID);\n if (!start) return;\n st.toolStarts.delete(callID);\n if (!st.traceId) return;\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'TOOL' } },\n { key: 'neatlogs.tool.name', value: { stringValue: start.tool } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n if (start.args !== undefined) {\n // The shipper bypasses the SDK attribute-processor, so emit the\n // already-namespaced keys the backend consumer reads directly\n // (neatlogs.tool.input / .output and the generic neatlogs.input.value),\n // not the raw input.value/output.value the processor would map.\n setIO(attrs, 'TOOL', safeStringify(start.args), undefined);\n push(attrs, attrStr('neatlogs.tool.input', safeStringify(start.args)));\n }\n if (result?.title) push(attrs, attrStr('neatlogs.tool.title', String(result.title)));\n const out = result?.output ?? result?.result;\n if (out !== undefined) {\n const o = typeof out === 'string' ? out : safeStringify(out);\n setIO(attrs, 'TOOL', undefined, o);\n push(attrs, attrStr('neatlogs.tool.output', o));\n }\n if (result?.metadata !== undefined) {\n push(attrs, attrStr('neatlogs.tool.metadata', safeStringify(result.metadata)));\n }\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: start.spanId,\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.tool.${start.tool}`,\n kind: 1,\n startTimeUnixNano: start.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n } catch {\n /* ignore */\n }\n },\n };\n};\n\n// Convenience aliases so users can import under any common name.\nexport const neatlogsOpencodePlugin = NeatlogsOpencodePlugin;\nexport default NeatlogsOpencodePlugin;\n\n// ---------------------------------------------------------------------------\n// Event handling\n// ---------------------------------------------------------------------------\n\nfunction handleEvent(\n shipper: TraceShipper,\n sessions: Map<string, SessionState>,\n stateFor: (sessionID: string) => SessionState,\n startRoot: (st: SessionState, sessionID: string) => void,\n closeAndFlush: (st: SessionState, sessionID: string) => Promise<void>,\n event: any,\n): Promise<unknown> | undefined {\n const type = event?.type;\n const props = event?.properties ?? {};\n\n // Accumulate text + tool-call parts on an assistant message.\n if (type === 'message.part.updated' || type === 'message.part.completed') {\n const part = props.part ?? props;\n const messageID = part?.messageID ?? part?.message_id;\n const sessionID = part?.sessionID ?? props.sessionID;\n if (!messageID || !sessionID) return undefined;\n const st = stateFor(String(sessionID));\n if (part?.type === 'text' && typeof part?.text === 'string') {\n st.outputParts.set(String(messageID), part.text);\n } else if (part?.type === 'tool' && part?.tool) {\n const list = st.toolCalls.get(String(messageID)) ?? [];\n const callID = String(part.callID ?? part.tool);\n const input = part?.state?.input ?? {};\n const existing = list.find((t) => t.callID === callID);\n if (existing) existing.input = input;\n else list.push({ name: String(part.tool), input, callID });\n st.toolCalls.set(String(messageID), list);\n }\n return undefined;\n }\n\n // Assistant message completed → emit the LLM span, then flush this turn.\n if (type === 'message.updated' || type === 'message.completed') {\n const info = props.info ?? props.message ?? props;\n const sessionID = info?.sessionID ?? info?.session_id;\n if (!sessionID) return undefined;\n if (info?.role !== 'assistant') return undefined;\n const completed = info?.time?.completed ?? info?.completed;\n const id = String(info?.id ?? '');\n if (!completed || !id) return undefined;\n const st = stateFor(String(sessionID));\n if (st.processed.has(id)) return undefined;\n st.processed.add(id);\n startRoot(st, String(sessionID));\n emitLlmSpan(shipper, st, info, String(sessionID));\n // Incremental persistence: ship this turn's spans now (don't wait for idle).\n return shipper.flush().catch(() => undefined);\n }\n\n // Session finished → end root, send completion marker, final flush.\n if (type === 'session.idle' || type === 'session.deleted') {\n const sessionID = props.sessionID ?? props.info?.id;\n if (!sessionID) return undefined;\n const st = sessions.get(String(sessionID));\n if (!st) return undefined;\n st.toolStarts.clear();\n const p = closeAndFlush(st, String(sessionID));\n if (type === 'session.deleted') sessions.delete(String(sessionID));\n return p;\n }\n\n return undefined;\n}\n\nfunction emitLlmSpan(shipper: TraceShipper, st: SessionState, info: any, sessionID: string): void {\n if (!st.traceId) return;\n const model = info?.modelID ?? info?.model ?? '';\n const provider = info?.providerID ?? info?.provider ?? '';\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'LLM' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n push(attrs, attrStr('neatlogs.llm.model_name', model ? String(model) : undefined));\n push(attrs, attrStr('neatlogs.llm.provider', provider ? String(provider) : undefined));\n\n let inIdx = 0;\n if (st.systemPrompt) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'system'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.systemPrompt));\n inIdx++;\n }\n if (st.currentInput) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'user'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.currentInput));\n setIO(attrs, 'LLM', st.currentInput, undefined);\n }\n\n const outText = st.outputParts.get(String(info?.id)) || messageText(info) || '';\n const toolCalls = st.toolCalls.get(String(info?.id)) ?? [];\n\n if (outText) {\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', outText));\n setIO(attrs, 'LLM', undefined, outText);\n st.lastAssistantText = outText;\n }\n // Tool-deciding turns often carry no text — render the tool call(s) as output.\n if (toolCalls.length) {\n toolCalls.forEach((tc, j) => {\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.name`, tc.name));\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.input ?? {})));\n });\n if (!outText) {\n const rendered = toolCalls.map((tc) => `→ ${tc.name}(${safeStringify(tc.input ?? {})})`).join('\\n');\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', rendered));\n setIO(attrs, 'LLM', undefined, rendered);\n }\n }\n\n // Tokens: opencode message tokens { input, output, reasoning, cache:{read,write} }\n const tokens = info?.tokens;\n if (tokens) {\n push(attrs, attrInt('neatlogs.llm.token_count.prompt', tokens.input));\n push(attrs, attrInt('neatlogs.llm.token_count.completion', tokens.output));\n if (tokens.input != null && tokens.output != null) {\n push(attrs, attrInt('neatlogs.llm.token_count.total', tokens.input + tokens.output));\n }\n push(attrs, attrInt('neatlogs.llm.token_count.reasoning', tokens.reasoning));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_read', tokens.cache?.read));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_write', tokens.cache?.write));\n }\n push(attrs, attrDouble('neatlogs.llm.cost_usd', info?.cost));\n push(attrs, attrStr('neatlogs.llm.finish_reason', info?.finish ? String(info.finish) : undefined));\n\n // Use opencode's real start time when available (else now).\n const createdMs = info?.time?.created;\n const startNano = typeof createdMs === 'number' ? msToNanoString(Math.floor(createdMs)) : nowNanoString();\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.llm.${model || 'model'}`,\n kind: 1,\n startTimeUnixNano: startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n\n // Reset accumulated parts for the next turn.\n if (info?.id) {\n st.outputParts.delete(String(info.id));\n st.toolCalls.delete(String(info.id));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction push(arr: OtlpKeyValue[], kv: OtlpKeyValue | undefined): void {\n if (kv) arr.push(kv);\n}\n\n/**\n * Set generic input/output on a span using the ALREADY-NAMESPACED keys the\n * backend consumer reads. The OTel-SDK wrappers rely on the attribute-processor\n * to map raw `input.value` → `neatlogs.{kind}.input`; this plugin ships spans\n * directly (no processor), so it must emit the namespaced keys itself:\n * neatlogs.input.value / neatlogs.output.value (generic)\n * neatlogs.{kind}.input / neatlogs.{kind}.output (kind-specific)\n * We also keep the raw input.value/output.value for any consumer that maps it.\n */\nfunction setIO(arr: OtlpKeyValue[], kind: string, input?: string, output?: string): void {\n const k = kind.toLowerCase();\n if (input !== undefined) {\n push(arr, attrStr('input.value', input));\n push(arr, attrStr('neatlogs.input.value', input));\n push(arr, attrStr(`neatlogs.${k}.input`, input));\n }\n if (output !== undefined) {\n push(arr, attrStr('output.value', output));\n push(arr, attrStr('neatlogs.output.value', output));\n push(arr, attrStr(`neatlogs.${k}.output`, output));\n }\n}\n\n/** Flatten an opencode message's parts/content to readable text. */\nfunction messageText(info: any): string {\n if (!info) return '';\n if (typeof info.text === 'string') return info.text;\n const parts = info.parts ?? info.content;\n if (typeof parts === 'string') return parts;\n if (!Array.isArray(parts)) return '';\n const out: string[] = [];\n for (const p of parts) {\n if (typeof p === 'string') out.push(p);\n else if (p && typeof p === 'object' && typeof p.text === 'string') out.push(p.text);\n }\n return out.join('');\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n","/**\n * Direct OTLP trace shipper for the opencode plugin.\n *\n * opencode loads the plugin in-process but `opencode run` is short-lived — it\n * tears down the moment a session goes idle. The OpenTelemetry BatchSpanProcessor\n * (async, scheduled-delay export + a `beforeExit` shutdown) races that teardown,\n * dropping spans or leaving aborted half-sent requests. This shipper mirrors the\n * proven `neatlogs-claude-code` design instead: spans are queued, then `flush()`\n * does a single AWAITED `fetch(POST /v1/traces)` round-trip that completes before\n * the host process can exit. No batch processor, no exit-time race.\n *\n * Self-contained (inlined OTLP protobuf schema) so it adds no runtime file I/O.\n */\n\nimport protobuf from 'protobufjs';\nimport { __version__ } from './version.js';\n\nconst PACKAGE_NAME = 'neatlogs.opencode';\n\nexport interface OtlpKeyValue {\n key: string;\n value: {\n stringValue?: string;\n intValue?: string;\n doubleValue?: number;\n boolValue?: boolean;\n };\n}\n\nexport interface OtlpSpan {\n traceId: Uint8Array;\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n /** OTLP SpanKind enum (0=unspecified, 1=internal, …). Neatlogs kind rides in attributes. */\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: OtlpKeyValue[];\n status?: { code: number; message?: string };\n}\n\n// Inlined OTLP proto definition — avoids .proto file I/O at runtime.\nconst OTLP_PROTO_JSON: protobuf.INamespace = {\n nested: {\n opentelemetry: {\n nested: {\n proto: {\n nested: {\n common: {\n nested: {\n v1: {\n nested: {\n AnyValue: {\n oneofs: {\n value: {\n oneof: [\n 'stringValue',\n 'boolValue',\n 'intValue',\n 'doubleValue',\n 'arrayValue',\n 'kvlistValue',\n 'bytesValue',\n ],\n },\n },\n fields: {\n stringValue: { type: 'string', id: 1 },\n boolValue: { type: 'bool', id: 2 },\n intValue: { type: 'int64', id: 3 },\n doubleValue: { type: 'double', id: 4 },\n arrayValue: { type: 'ArrayValue', id: 5 },\n kvlistValue: { type: 'KeyValueList', id: 6 },\n bytesValue: { type: 'bytes', id: 7 },\n },\n },\n ArrayValue: { fields: { values: { rule: 'repeated', type: 'AnyValue', id: 1 } } },\n KeyValueList: { fields: { values: { rule: 'repeated', type: 'KeyValue', id: 1 } } },\n KeyValue: {\n fields: { key: { type: 'string', id: 1 }, value: { type: 'AnyValue', id: 2 } },\n },\n InstrumentationScope: {\n fields: { name: { type: 'string', id: 1 }, version: { type: 'string', id: 2 } },\n },\n },\n },\n },\n },\n resource: {\n nested: {\n v1: {\n nested: {\n Resource: {\n fields: {\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n trace: {\n nested: {\n v1: {\n nested: {\n ResourceSpans: {\n fields: {\n resource: { type: 'opentelemetry.proto.resource.v1.Resource', id: 1 },\n scopeSpans: { rule: 'repeated', type: 'ScopeSpans', id: 2 },\n },\n },\n ScopeSpans: {\n fields: {\n scope: { type: 'opentelemetry.proto.common.v1.InstrumentationScope', id: 1 },\n spans: { rule: 'repeated', type: 'Span', id: 2 },\n },\n },\n Span: {\n fields: {\n traceId: { type: 'bytes', id: 1 },\n spanId: { type: 'bytes', id: 2 },\n traceState: { type: 'string', id: 3 },\n parentSpanId: { type: 'bytes', id: 4 },\n name: { type: 'string', id: 5 },\n kind: { type: 'SpanKind', id: 6 },\n startTimeUnixNano: { type: 'fixed64', id: 7 },\n endTimeUnixNano: { type: 'fixed64', id: 8 },\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 9,\n },\n droppedAttributesCount: { type: 'uint32', id: 10 },\n status: { type: 'Status', id: 15 },\n },\n },\n Status: {\n fields: { message: { type: 'string', id: 2 }, code: { type: 'StatusCode', id: 3 } },\n },\n StatusCode: {\n values: { STATUS_CODE_UNSET: 0, STATUS_CODE_OK: 1, STATUS_CODE_ERROR: 2 },\n },\n SpanKind: {\n values: {\n SPAN_KIND_UNSPECIFIED: 0,\n SPAN_KIND_INTERNAL: 1,\n SPAN_KIND_SERVER: 2,\n SPAN_KIND_CLIENT: 3,\n SPAN_KIND_PRODUCER: 4,\n SPAN_KIND_CONSUMER: 5,\n },\n },\n },\n },\n },\n },\n collector: {\n nested: {\n trace: {\n nested: {\n v1: {\n nested: {\n ExportTraceServiceRequest: {\n fields: {\n resourceSpans: {\n rule: 'repeated',\n type: 'opentelemetry.proto.trace.v1.ResourceSpans',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nconst protoRoot = protobuf.Root.fromJSON(OTLP_PROTO_JSON);\nconst ExportTraceServiceRequest = protoRoot.lookupType(\n 'opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest',\n);\n\nexport const SpanStatusCode = { UNSET: 0, OK: 1, ERROR: 2 } as const;\n\n// ---------------------------------------------------------------------------\n// ID + time + attribute helpers\n// ---------------------------------------------------------------------------\n\nfunction randomBytes(length: number): Uint8Array {\n const out = new Uint8Array(length);\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(out);\n return out;\n }\n for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);\n return out;\n}\n\nexport function generateTraceId(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function generateSpanId(): Uint8Array {\n return randomBytes(8);\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport function nowNanoString(): string {\n return (BigInt(Date.now()) * 1_000_000n).toString();\n}\n\nexport function msToNanoString(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString();\n}\n\nexport function attrStr(key: string, value: string | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null) return undefined;\n return { key, value: { stringValue: String(value) } };\n}\n\nexport function attrInt(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { intValue: String(Math.trunc(value)) } };\n}\n\nexport function attrDouble(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { doubleValue: value } };\n}\n\nexport interface TraceShipperOptions {\n apiKey: string;\n endpoint: string;\n debug?: boolean;\n maxRetries?: number;\n workflowName?: string;\n}\n\nexport class TraceShipper {\n private apiKey: string;\n private endpoint: string;\n private debug: boolean;\n private maxRetries: number;\n workflowName: string;\n private queue: OtlpSpan[] = [];\n private prefix = '[neatlogs/opencode]';\n /** In-flight flush round-trips — awaited by `settle()` on dispose so a\n * short-lived host (`opencode run`) can force pending exports to complete. */\n private inflight = new Set<Promise<void>>();\n\n constructor(opts: TraceShipperOptions) {\n this.apiKey = opts.apiKey;\n this.endpoint = opts.endpoint.endsWith('/') ? opts.endpoint.slice(0, -1) : opts.endpoint;\n this.debug = !!opts.debug;\n this.maxRetries = opts.maxRetries ?? 3;\n this.workflowName = opts.workflowName || '';\n }\n\n enqueue(span: OtlpSpan): void {\n this.queue.push(span);\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n /**\n * Ship all queued spans in a single awaited POST. Resolves only once the HTTP\n * response is received (or all retries are exhausted) — so a short-lived host\n * can safely exit immediately after awaiting this.\n *\n * The returned promise is also tracked in `inflight` so `settle()` can await\n * it even when the caller (an un-awaited opencode `event` hook) drops it.\n */\n flush(): Promise<void> {\n const p = this._flush().finally(() => this.inflight.delete(p));\n this.inflight.add(p);\n return p;\n }\n\n /**\n * Await every flush started so far (including ones whose promise the caller\n * discarded). Called from the plugin's `dispose` hook, which opencode DOES\n * await on scope teardown — unlike the fire-and-forget `event` hook.\n */\n async settle(): Promise<void> {\n while (this.inflight.size > 0) {\n await Promise.allSettled(Array.from(this.inflight));\n }\n }\n\n private async _flush(): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.apiKey) {\n this.queue = [];\n return;\n }\n\n const spans = this.queue.splice(0);\n const payload = this.buildProtobuf(spans);\n const url = `${this.endpoint}/v1/traces`;\n\n if (this.debug) console.log(`${this.prefix} Shipping ${spans.length} spans to ${url}`);\n\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n try {\n const resp = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'x-api-key': this.apiKey,\n },\n body: payload as any,\n });\n\n if (resp.ok) {\n if (this.debug) console.log(`${this.prefix} Shipped ${spans.length} spans`);\n return;\n }\n if (resp.status === 401) {\n console.warn(`${this.prefix} Invalid API key (401) — dropping ${spans.length} spans`);\n return;\n }\n if (resp.status < 500 && resp.status !== 429) {\n if (this.debug) console.warn(`${this.prefix} HTTP ${resp.status} — dropping spans`);\n return;\n }\n // 429 / 5xx → retry\n } catch (err) {\n if (this.debug) {\n console.warn(\n `${this.prefix} Attempt ${attempt}/${this.maxRetries}: ${(err as Error).message}`,\n );\n }\n }\n if (attempt < this.maxRetries) {\n await new Promise((r) => setTimeout(r, 500 * 2 ** (attempt - 1)));\n }\n }\n console.warn(`${this.prefix} Failed to ship ${spans.length} spans after ${this.maxRetries} attempts`);\n }\n\n private buildProtobuf(spans: OtlpSpan[]): Uint8Array {\n const protoSpans = spans.map((span) => ({\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || undefined,\n name: span.name,\n kind: span.kind,\n startTimeUnixNano: nanoToLong(span.startTimeUnixNano),\n endTimeUnixNano: nanoToLong(span.endTimeUnixNano),\n attributes: span.attributes.map((a) => ({\n key: a.key,\n value:\n a.value.intValue !== undefined\n ? { intValue: nanoToLong(a.value.intValue) }\n : a.value,\n })),\n status: span.status ? { code: span.status.code, message: span.status.message } : undefined,\n }));\n\n const resourceAttributes: Array<{ key: string; value: { stringValue: string } }> = [\n { key: 'service.name', value: { stringValue: 'neatlogs.opencode' } },\n { key: 'service.version', value: { stringValue: __version__ } },\n ];\n if (this.workflowName) {\n resourceAttributes.push({\n key: 'neatlogs.workflow_name',\n value: { stringValue: this.workflowName },\n });\n }\n\n const message = {\n resourceSpans: [\n {\n resource: { attributes: resourceAttributes },\n scopeSpans: [\n {\n scope: { name: PACKAGE_NAME, version: __version__ },\n spans: protoSpans,\n },\n ],\n },\n ],\n };\n\n const errMsg = ExportTraceServiceRequest.verify(message);\n if (errMsg && this.debug) console.warn(`${this.prefix} Proto verify: ${errMsg}`);\n\n return ExportTraceServiceRequest.encode(ExportTraceServiceRequest.fromObject(message)).finish();\n }\n}\n\n/** protobufjs encodes fixed64/int64 from a {low,high,unsigned} Long-like. */\nfunction nanoToLong(nanoStr: string): { low: number; high: number; unsigned: boolean } {\n const big = BigInt(nanoStr);\n const low = Number(big & 0xffffffffn);\n const high = Number((big >> 32n) & 0xffffffffn);\n return { low, high, unsigned: true };\n}\n","/**\n * SDK version. Kept in sync with package.json by the `version:sync` script\n * (runs automatically on `prebuild`). Do not edit by hand — bump package.json.\n */\nexport const __version__ = '1.1.22';\n","/** Stable SDK-wide defaults shared by every NeatLogs entry point. */\nexport const DEFAULT_INGEST_ENDPOINT = 'https://ingest.neatlogs.com' as const;\nexport const DEFAULT_MAX_QUEUE_ITEMS = 2048;\nexport const DEFAULT_MAX_SEMANTIC_STREAM_EVENTS = 128;\nexport const DEFAULT_MAX_STREAM_CAPTURE_BYTES = 1024 * 1024;\nexport const DEFAULT_MAX_STREAM_CAPTURE_ITEMS = 1024;\n\n/** UTF-8 byte length without allocating a second buffer for hostile stream chunks. */\nexport function utf8ByteLength(\n value: string,\n limit = Number.MAX_SAFE_INTEGER,\n): number {\n let bytes = 0;\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff && i + 1 < value.length) {\n const next = value.charCodeAt(i + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n i += 1;\n } else bytes += 3;\n } else bytes += 3;\n if (bytes > limit) return limit + 1;\n }\n return bytes;\n}\n\nexport function exportQueueCapacity(batchSize: number): number {\n return Math.max(DEFAULT_MAX_QUEUE_ITEMS, batchSize * 4);\n}\n"],"mappings":"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","names":["protobuf"]}
@@ -2,7 +2,7 @@
2
2
  import protobuf from "protobufjs";
3
3
 
4
4
  // src/version.ts
5
- var __version__ = "1.1.21";
5
+ var __version__ = "1.1.22";
6
6
 
7
7
  // src/opencode-trace-shipper.ts
8
8
  var PACKAGE_NAME = "neatlogs.opencode";
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/opencode-trace-shipper.ts","../src/version.ts","../src/constants.ts","../src/opencode-plugin.ts"],"sourcesContent":["/**\n * Direct OTLP trace shipper for the opencode plugin.\n *\n * opencode loads the plugin in-process but `opencode run` is short-lived — it\n * tears down the moment a session goes idle. The OpenTelemetry BatchSpanProcessor\n * (async, scheduled-delay export + a `beforeExit` shutdown) races that teardown,\n * dropping spans or leaving aborted half-sent requests. This shipper mirrors the\n * proven `neatlogs-claude-code` design instead: spans are queued, then `flush()`\n * does a single AWAITED `fetch(POST /v1/traces)` round-trip that completes before\n * the host process can exit. No batch processor, no exit-time race.\n *\n * Self-contained (inlined OTLP protobuf schema) so it adds no runtime file I/O.\n */\n\nimport protobuf from 'protobufjs';\nimport { __version__ } from './version.js';\n\nconst PACKAGE_NAME = 'neatlogs.opencode';\n\nexport interface OtlpKeyValue {\n key: string;\n value: {\n stringValue?: string;\n intValue?: string;\n doubleValue?: number;\n boolValue?: boolean;\n };\n}\n\nexport interface OtlpSpan {\n traceId: Uint8Array;\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n /** OTLP SpanKind enum (0=unspecified, 1=internal, …). Neatlogs kind rides in attributes. */\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: OtlpKeyValue[];\n status?: { code: number; message?: string };\n}\n\n// Inlined OTLP proto definition — avoids .proto file I/O at runtime.\nconst OTLP_PROTO_JSON: protobuf.INamespace = {\n nested: {\n opentelemetry: {\n nested: {\n proto: {\n nested: {\n common: {\n nested: {\n v1: {\n nested: {\n AnyValue: {\n oneofs: {\n value: {\n oneof: [\n 'stringValue',\n 'boolValue',\n 'intValue',\n 'doubleValue',\n 'arrayValue',\n 'kvlistValue',\n 'bytesValue',\n ],\n },\n },\n fields: {\n stringValue: { type: 'string', id: 1 },\n boolValue: { type: 'bool', id: 2 },\n intValue: { type: 'int64', id: 3 },\n doubleValue: { type: 'double', id: 4 },\n arrayValue: { type: 'ArrayValue', id: 5 },\n kvlistValue: { type: 'KeyValueList', id: 6 },\n bytesValue: { type: 'bytes', id: 7 },\n },\n },\n ArrayValue: { fields: { values: { rule: 'repeated', type: 'AnyValue', id: 1 } } },\n KeyValueList: { fields: { values: { rule: 'repeated', type: 'KeyValue', id: 1 } } },\n KeyValue: {\n fields: { key: { type: 'string', id: 1 }, value: { type: 'AnyValue', id: 2 } },\n },\n InstrumentationScope: {\n fields: { name: { type: 'string', id: 1 }, version: { type: 'string', id: 2 } },\n },\n },\n },\n },\n },\n resource: {\n nested: {\n v1: {\n nested: {\n Resource: {\n fields: {\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n trace: {\n nested: {\n v1: {\n nested: {\n ResourceSpans: {\n fields: {\n resource: { type: 'opentelemetry.proto.resource.v1.Resource', id: 1 },\n scopeSpans: { rule: 'repeated', type: 'ScopeSpans', id: 2 },\n },\n },\n ScopeSpans: {\n fields: {\n scope: { type: 'opentelemetry.proto.common.v1.InstrumentationScope', id: 1 },\n spans: { rule: 'repeated', type: 'Span', id: 2 },\n },\n },\n Span: {\n fields: {\n traceId: { type: 'bytes', id: 1 },\n spanId: { type: 'bytes', id: 2 },\n traceState: { type: 'string', id: 3 },\n parentSpanId: { type: 'bytes', id: 4 },\n name: { type: 'string', id: 5 },\n kind: { type: 'SpanKind', id: 6 },\n startTimeUnixNano: { type: 'fixed64', id: 7 },\n endTimeUnixNano: { type: 'fixed64', id: 8 },\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 9,\n },\n droppedAttributesCount: { type: 'uint32', id: 10 },\n status: { type: 'Status', id: 15 },\n },\n },\n Status: {\n fields: { message: { type: 'string', id: 2 }, code: { type: 'StatusCode', id: 3 } },\n },\n StatusCode: {\n values: { STATUS_CODE_UNSET: 0, STATUS_CODE_OK: 1, STATUS_CODE_ERROR: 2 },\n },\n SpanKind: {\n values: {\n SPAN_KIND_UNSPECIFIED: 0,\n SPAN_KIND_INTERNAL: 1,\n SPAN_KIND_SERVER: 2,\n SPAN_KIND_CLIENT: 3,\n SPAN_KIND_PRODUCER: 4,\n SPAN_KIND_CONSUMER: 5,\n },\n },\n },\n },\n },\n },\n collector: {\n nested: {\n trace: {\n nested: {\n v1: {\n nested: {\n ExportTraceServiceRequest: {\n fields: {\n resourceSpans: {\n rule: 'repeated',\n type: 'opentelemetry.proto.trace.v1.ResourceSpans',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nconst protoRoot = protobuf.Root.fromJSON(OTLP_PROTO_JSON);\nconst ExportTraceServiceRequest = protoRoot.lookupType(\n 'opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest',\n);\n\nexport const SpanStatusCode = { UNSET: 0, OK: 1, ERROR: 2 } as const;\n\n// ---------------------------------------------------------------------------\n// ID + time + attribute helpers\n// ---------------------------------------------------------------------------\n\nfunction randomBytes(length: number): Uint8Array {\n const out = new Uint8Array(length);\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(out);\n return out;\n }\n for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);\n return out;\n}\n\nexport function generateTraceId(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function generateSpanId(): Uint8Array {\n return randomBytes(8);\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport function nowNanoString(): string {\n return (BigInt(Date.now()) * 1_000_000n).toString();\n}\n\nexport function msToNanoString(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString();\n}\n\nexport function attrStr(key: string, value: string | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null) return undefined;\n return { key, value: { stringValue: String(value) } };\n}\n\nexport function attrInt(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { intValue: String(Math.trunc(value)) } };\n}\n\nexport function attrDouble(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { doubleValue: value } };\n}\n\nexport interface TraceShipperOptions {\n apiKey: string;\n endpoint: string;\n debug?: boolean;\n maxRetries?: number;\n workflowName?: string;\n}\n\nexport class TraceShipper {\n private apiKey: string;\n private endpoint: string;\n private debug: boolean;\n private maxRetries: number;\n workflowName: string;\n private queue: OtlpSpan[] = [];\n private prefix = '[neatlogs/opencode]';\n /** In-flight flush round-trips — awaited by `settle()` on dispose so a\n * short-lived host (`opencode run`) can force pending exports to complete. */\n private inflight = new Set<Promise<void>>();\n\n constructor(opts: TraceShipperOptions) {\n this.apiKey = opts.apiKey;\n this.endpoint = opts.endpoint.endsWith('/') ? opts.endpoint.slice(0, -1) : opts.endpoint;\n this.debug = !!opts.debug;\n this.maxRetries = opts.maxRetries ?? 3;\n this.workflowName = opts.workflowName || '';\n }\n\n enqueue(span: OtlpSpan): void {\n this.queue.push(span);\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n /**\n * Ship all queued spans in a single awaited POST. Resolves only once the HTTP\n * response is received (or all retries are exhausted) — so a short-lived host\n * can safely exit immediately after awaiting this.\n *\n * The returned promise is also tracked in `inflight` so `settle()` can await\n * it even when the caller (an un-awaited opencode `event` hook) drops it.\n */\n flush(): Promise<void> {\n const p = this._flush().finally(() => this.inflight.delete(p));\n this.inflight.add(p);\n return p;\n }\n\n /**\n * Await every flush started so far (including ones whose promise the caller\n * discarded). Called from the plugin's `dispose` hook, which opencode DOES\n * await on scope teardown — unlike the fire-and-forget `event` hook.\n */\n async settle(): Promise<void> {\n while (this.inflight.size > 0) {\n await Promise.allSettled(Array.from(this.inflight));\n }\n }\n\n private async _flush(): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.apiKey) {\n this.queue = [];\n return;\n }\n\n const spans = this.queue.splice(0);\n const payload = this.buildProtobuf(spans);\n const url = `${this.endpoint}/v1/traces`;\n\n if (this.debug) console.log(`${this.prefix} Shipping ${spans.length} spans to ${url}`);\n\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n try {\n const resp = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'x-api-key': this.apiKey,\n },\n body: payload as any,\n });\n\n if (resp.ok) {\n if (this.debug) console.log(`${this.prefix} Shipped ${spans.length} spans`);\n return;\n }\n if (resp.status === 401) {\n console.warn(`${this.prefix} Invalid API key (401) — dropping ${spans.length} spans`);\n return;\n }\n if (resp.status < 500 && resp.status !== 429) {\n if (this.debug) console.warn(`${this.prefix} HTTP ${resp.status} — dropping spans`);\n return;\n }\n // 429 / 5xx → retry\n } catch (err) {\n if (this.debug) {\n console.warn(\n `${this.prefix} Attempt ${attempt}/${this.maxRetries}: ${(err as Error).message}`,\n );\n }\n }\n if (attempt < this.maxRetries) {\n await new Promise((r) => setTimeout(r, 500 * 2 ** (attempt - 1)));\n }\n }\n console.warn(`${this.prefix} Failed to ship ${spans.length} spans after ${this.maxRetries} attempts`);\n }\n\n private buildProtobuf(spans: OtlpSpan[]): Uint8Array {\n const protoSpans = spans.map((span) => ({\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || undefined,\n name: span.name,\n kind: span.kind,\n startTimeUnixNano: nanoToLong(span.startTimeUnixNano),\n endTimeUnixNano: nanoToLong(span.endTimeUnixNano),\n attributes: span.attributes.map((a) => ({\n key: a.key,\n value:\n a.value.intValue !== undefined\n ? { intValue: nanoToLong(a.value.intValue) }\n : a.value,\n })),\n status: span.status ? { code: span.status.code, message: span.status.message } : undefined,\n }));\n\n const resourceAttributes: Array<{ key: string; value: { stringValue: string } }> = [\n { key: 'service.name', value: { stringValue: 'neatlogs.opencode' } },\n { key: 'service.version', value: { stringValue: __version__ } },\n ];\n if (this.workflowName) {\n resourceAttributes.push({\n key: 'neatlogs.workflow_name',\n value: { stringValue: this.workflowName },\n });\n }\n\n const message = {\n resourceSpans: [\n {\n resource: { attributes: resourceAttributes },\n scopeSpans: [\n {\n scope: { name: PACKAGE_NAME, version: __version__ },\n spans: protoSpans,\n },\n ],\n },\n ],\n };\n\n const errMsg = ExportTraceServiceRequest.verify(message);\n if (errMsg && this.debug) console.warn(`${this.prefix} Proto verify: ${errMsg}`);\n\n return ExportTraceServiceRequest.encode(ExportTraceServiceRequest.fromObject(message)).finish();\n }\n}\n\n/** protobufjs encodes fixed64/int64 from a {low,high,unsigned} Long-like. */\nfunction nanoToLong(nanoStr: string): { low: number; high: number; unsigned: boolean } {\n const big = BigInt(nanoStr);\n const low = Number(big & 0xffffffffn);\n const high = Number((big >> 32n) & 0xffffffffn);\n return { low, high, unsigned: true };\n}\n","/**\n * SDK version. Kept in sync with package.json by the `version:sync` script\n * (runs automatically on `prebuild`). Do not edit by hand — bump package.json.\n */\nexport const __version__ = '1.1.21';\n","/** Stable SDK-wide defaults shared by every NeatLogs entry point. */\nexport const DEFAULT_INGEST_ENDPOINT = 'https://ingest.neatlogs.com' as const;\nexport const DEFAULT_MAX_QUEUE_ITEMS = 2048;\nexport const DEFAULT_MAX_SEMANTIC_STREAM_EVENTS = 128;\nexport const DEFAULT_MAX_STREAM_CAPTURE_BYTES = 1024 * 1024;\nexport const DEFAULT_MAX_STREAM_CAPTURE_ITEMS = 1024;\n\n/** UTF-8 byte length without allocating a second buffer for hostile stream chunks. */\nexport function utf8ByteLength(\n value: string,\n limit = Number.MAX_SAFE_INTEGER,\n): number {\n let bytes = 0;\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff && i + 1 < value.length) {\n const next = value.charCodeAt(i + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n i += 1;\n } else bytes += 3;\n } else bytes += 3;\n if (bytes > limit) return limit + 1;\n }\n return bytes;\n}\n\nexport function exportQueueCapacity(batchSize: number): number {\n return Math.max(DEFAULT_MAX_QUEUE_ITEMS, batchSize * 4);\n}\n","/**\n * Neatlogs opencode plugin.\n *\n * opencode loads plugins from its config (`opencode.json` → `\"plugin\": [...]`)\n * or from local `.opencode/plugin/*.ts` files. A plugin is an async factory that\n * receives an app context and returns lifecycle hooks. This plugin instruments\n * opencode automatically — no per-call wiring — turning each opencode TURN into\n * its own neatlogs trace (mirrors @neatlogs/claude-code):\n *\n * WORKFLOW opencode.turn (one TRACE per user turn; parents that turn's spans)\n * ↳ LLM assistant turn (per completed assistant message)\n * ↳ TOOL tool execution (tool.execute.before → tool.execute.after)\n *\n * A turn opens on `chat.message` and closes on `session.idle` (which fires after\n * the turn's full tool-loop settles) — NOT on each `message.completed`, so a\n * multi-round tool-using turn stays one trace. Every span carries\n * `neatlogs.conversation.id` = the opencode session ID and a per-turn trace id;\n * all of a session's turn-traces are grouped in the UI via `neatlogs.session.id`.\n *\n * Export model (mirrors @raindrop-ai/opencode-plugin and neatlogs-claude-code):\n * opencode loads the plugin in-process but `opencode run` is short-lived. Rather\n * than the OpenTelemetry BatchSpanProcessor (whose async, scheduled-delay export\n * + `beforeExit` shutdown races the teardown and drops spans), this plugin builds\n * spans directly and ships them via AWAITED `fetch(POST /v1/traces)` — and it\n * flushes after every completed assistant turn (incremental persistence) plus a\n * final flush on `session.idle`. A `neatlogs.trace.complete` marker is sent so\n * the backend enqueues the trace for finalization (simplification → UI).\n *\n * Setup — either:\n * • npm package, in opencode.json: `{ \"plugin\": [\"neatlogs/opencode\"] }`, OR\n * • local file `.opencode/plugin/neatlogs.ts`:\n * export { NeatlogsOpencodePlugin as default } from 'neatlogs/opencode';\n *\n * Env:\n * NEATLOGS_API_KEY required to export\n * NEATLOGS_ENDPOINT backend base URL (default https://ingest.neatlogs.com)\n */\n\nimport {\n TraceShipper,\n type OtlpSpan,\n type OtlpKeyValue,\n SpanStatusCode,\n generateTraceId,\n generateSpanId,\n nowNanoString,\n msToNanoString,\n attrStr,\n attrInt,\n attrDouble,\n} from './opencode-trace-shipper.js';\nimport { DEFAULT_INGEST_ENDPOINT } from './constants.js';\n\n/** A span being built incrementally — ended (and shipped) later. */\ninterface OpenSpan {\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n startNano: string;\n attributes: OtlpKeyValue[];\n}\n\ninterface SessionState {\n /** Per-TURN trace id — minted when the turn's root opens, so each turn is its\n * own trace. Undefined between turns. */\n traceId?: Uint8Array;\n /** The current turn's WORKFLOW root span (created on chat.message, ended on idle). */\n rootSpan?: OpenSpan;\n /** Open TOOL spans keyed by callID → start time. */\n toolStarts: Map<string, { spanId: Uint8Array; startNano: string; tool: string; args: any }>;\n /** Accumulated assistant text per messageID (from text parts). */\n outputParts: Map<string, string>;\n /** Tool calls per assistant messageID (so a tool-only turn still has output). */\n toolCalls: Map<string, Array<{ name: string; input: any; callID: string }>>;\n /** assistant messageIDs already emitted (completion can fire repeatedly). */\n processed: Set<string>;\n /** Current user prompt (this turn's input). */\n currentInput: string;\n /** Captured system prompt. */\n systemPrompt?: string;\n /** Latest assistant text — the AGENT root's output on close. */\n lastAssistantText: string;\n}\n\nexport const NeatlogsOpencodePlugin = async (_ctx: any): Promise<Record<string, any>> => {\n const apiKey = (process.env.NEATLOGS_API_KEY ?? '').trim();\n const endpoint = (process.env.NEATLOGS_ENDPOINT ?? DEFAULT_INGEST_ENDPOINT).trim();\n const workflowName = 'opencode';\n const debug = String(process.env.NEATLOGS_DEBUG || '').toLowerCase() === 'true';\n\n const shipper = new TraceShipper({ apiKey, endpoint, workflowName, debug });\n const sessions = new Map<string, SessionState>();\n\n function stateFor(sessionID: string): SessionState {\n let s = sessions.get(sessionID);\n if (!s) {\n s = {\n toolStarts: new Map(),\n outputParts: new Map(),\n toolCalls: new Map(),\n processed: new Set(),\n currentInput: '',\n lastAssistantText: '',\n };\n sessions.set(sessionID, s);\n }\n return s;\n }\n\n /** Start the per-turn WORKFLOW root span, minting a fresh trace id for this\n * turn (idempotent within a turn). `neatlogs.session.id` groups the session's\n * turn-traces in the UI. */\n function startRoot(st: SessionState, sessionID: string): void {\n if (st.rootSpan) return;\n st.traceId = generateTraceId();\n st.rootSpan = {\n spanId: generateSpanId(),\n name: 'opencode.turn',\n startNano: nowNanoString(),\n attributes: [\n { key: 'neatlogs.span.kind', value: { stringValue: 'WORKFLOW' } },\n { key: 'neatlogs.agent.framework', value: { stringValue: 'opencode' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n { key: 'neatlogs.session.id', value: { stringValue: sessionID } },\n ],\n };\n }\n\n /** End + enqueue the WORKFLOW turn root, send the completion marker, and flush.\n * Clears the turn's trace id + accumulators so the next turn is a fresh trace. */\n async function closeAndFlush(st: SessionState, sessionID: string): Promise<void> {\n if (st.rootSpan && st.traceId) {\n const attrs = st.rootSpan.attributes.slice();\n setIO(attrs, 'WORKFLOW', st.currentInput || undefined, st.lastAssistantText || undefined);\n shipper.enqueue({\n traceId: st.traceId,\n spanId: st.rootSpan.spanId,\n name: st.rootSpan.name,\n kind: 1,\n startTimeUnixNano: st.rootSpan.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n // Completion marker — the backend only finalizes (simplifies → UI) a trace\n // once it sees a `neatlogs.trace.complete` span. Parented to the root.\n const m = nowNanoString();\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan.spanId,\n name: 'neatlogs.trace.complete',\n kind: 1,\n startTimeUnixNano: m,\n endTimeUnixNano: m,\n attributes: [\n { key: 'neatlogs.trace.complete', value: { boolValue: true } },\n { key: 'neatlogs.internal', value: { boolValue: true } },\n { key: 'neatlogs.span.kind', value: { stringValue: 'Neatlogs.INTERNAL' } },\n ],\n });\n }\n // Reset per-turn state so the next chat.message opens a brand-new trace.\n st.rootSpan = undefined;\n st.traceId = undefined;\n st.currentInput = '';\n st.lastAssistantText = '';\n st.processed.clear();\n st.outputParts.clear();\n st.toolCalls.clear();\n await shipper.flush();\n void sessionID;\n }\n\n return {\n /**\n * Awaited by opencode on scope teardown (registered via an internal\n * `addFinalizer`), unlike the fire-and-forget `event` hook. On a short-lived\n * `opencode run`, `session.idle`'s `await shipper.flush()` is a dangling\n * promise the process kills before the POST resolves — so we close any turn\n * still open and `settle()` all in-flight flushes here, before exit.\n */\n dispose: async () => {\n try {\n for (const [sessionID, st] of sessions) {\n if (st.rootSpan) await closeAndFlush(st, sessionID);\n }\n await shipper.settle();\n } catch {\n /* never break opencode over tracing */\n }\n },\n\n /** Fired when the user submits a prompt — open the turn's AGENT root. */\n 'chat.message': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? output?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const parts = output?.parts ?? [];\n const text = Array.isArray(parts)\n ? parts\n .filter((p: any) => p?.type === 'text' && typeof p.text === 'string')\n .map((p: any) => p.text)\n .join('\\n')\n : '';\n if (text) st.currentInput = text;\n startRoot(st, sessionID);\n } catch {\n /* ignore */\n }\n },\n\n /** Capture the system prompt. */\n 'experimental.chat.system.transform': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? '');\n const parts = output?.system ?? output?.parts ?? output;\n const joined = Array.isArray(parts) ? parts.map((p: any) => (typeof p === 'string' ? p : p?.text ?? '')).join('\\n') : String(parts ?? '');\n if (sessionID && joined) stateFor(sessionID).systemPrompt = joined;\n } catch {\n /* ignore */\n }\n },\n\n /** Global event bus — message parts, assistant completions, session idle. */\n event: async ({ event }: { event: any }) => {\n try {\n await handleEvent(shipper, sessions, stateFor, startRoot, closeAndFlush, event);\n } catch {\n // never break opencode over tracing\n }\n },\n\n /** Tool start — record start time + args (span built atomically in `after`). */\n 'tool.execute.before': async (input: any, output: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n startRoot(st, sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n st.toolStarts.set(callID, {\n spanId: generateSpanId(),\n startNano: nowNanoString(),\n tool: String(input?.tool ?? 'tool'),\n args: output?.args,\n });\n } catch {\n /* ignore */\n }\n },\n\n /** Tool end — enqueue the completed TOOL span (parented to the turn root). */\n 'tool.execute.after': async (input: any, result: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n const start = st.toolStarts.get(callID);\n if (!start) return;\n st.toolStarts.delete(callID);\n if (!st.traceId) return;\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'TOOL' } },\n { key: 'neatlogs.tool.name', value: { stringValue: start.tool } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n if (start.args !== undefined) {\n // The shipper bypasses the SDK attribute-processor, so emit the\n // already-namespaced keys the backend consumer reads directly\n // (neatlogs.tool.input / .output and the generic neatlogs.input.value),\n // not the raw input.value/output.value the processor would map.\n setIO(attrs, 'TOOL', safeStringify(start.args), undefined);\n push(attrs, attrStr('neatlogs.tool.input', safeStringify(start.args)));\n }\n if (result?.title) push(attrs, attrStr('neatlogs.tool.title', String(result.title)));\n const out = result?.output ?? result?.result;\n if (out !== undefined) {\n const o = typeof out === 'string' ? out : safeStringify(out);\n setIO(attrs, 'TOOL', undefined, o);\n push(attrs, attrStr('neatlogs.tool.output', o));\n }\n if (result?.metadata !== undefined) {\n push(attrs, attrStr('neatlogs.tool.metadata', safeStringify(result.metadata)));\n }\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: start.spanId,\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.tool.${start.tool}`,\n kind: 1,\n startTimeUnixNano: start.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n } catch {\n /* ignore */\n }\n },\n };\n};\n\n// Convenience aliases so users can import under any common name.\nexport const neatlogsOpencodePlugin = NeatlogsOpencodePlugin;\nexport default NeatlogsOpencodePlugin;\n\n// ---------------------------------------------------------------------------\n// Event handling\n// ---------------------------------------------------------------------------\n\nfunction handleEvent(\n shipper: TraceShipper,\n sessions: Map<string, SessionState>,\n stateFor: (sessionID: string) => SessionState,\n startRoot: (st: SessionState, sessionID: string) => void,\n closeAndFlush: (st: SessionState, sessionID: string) => Promise<void>,\n event: any,\n): Promise<unknown> | undefined {\n const type = event?.type;\n const props = event?.properties ?? {};\n\n // Accumulate text + tool-call parts on an assistant message.\n if (type === 'message.part.updated' || type === 'message.part.completed') {\n const part = props.part ?? props;\n const messageID = part?.messageID ?? part?.message_id;\n const sessionID = part?.sessionID ?? props.sessionID;\n if (!messageID || !sessionID) return undefined;\n const st = stateFor(String(sessionID));\n if (part?.type === 'text' && typeof part?.text === 'string') {\n st.outputParts.set(String(messageID), part.text);\n } else if (part?.type === 'tool' && part?.tool) {\n const list = st.toolCalls.get(String(messageID)) ?? [];\n const callID = String(part.callID ?? part.tool);\n const input = part?.state?.input ?? {};\n const existing = list.find((t) => t.callID === callID);\n if (existing) existing.input = input;\n else list.push({ name: String(part.tool), input, callID });\n st.toolCalls.set(String(messageID), list);\n }\n return undefined;\n }\n\n // Assistant message completed → emit the LLM span, then flush this turn.\n if (type === 'message.updated' || type === 'message.completed') {\n const info = props.info ?? props.message ?? props;\n const sessionID = info?.sessionID ?? info?.session_id;\n if (!sessionID) return undefined;\n if (info?.role !== 'assistant') return undefined;\n const completed = info?.time?.completed ?? info?.completed;\n const id = String(info?.id ?? '');\n if (!completed || !id) return undefined;\n const st = stateFor(String(sessionID));\n if (st.processed.has(id)) return undefined;\n st.processed.add(id);\n startRoot(st, String(sessionID));\n emitLlmSpan(shipper, st, info, String(sessionID));\n // Incremental persistence: ship this turn's spans now (don't wait for idle).\n return shipper.flush().catch(() => undefined);\n }\n\n // Session finished → end root, send completion marker, final flush.\n if (type === 'session.idle' || type === 'session.deleted') {\n const sessionID = props.sessionID ?? props.info?.id;\n if (!sessionID) return undefined;\n const st = sessions.get(String(sessionID));\n if (!st) return undefined;\n st.toolStarts.clear();\n const p = closeAndFlush(st, String(sessionID));\n if (type === 'session.deleted') sessions.delete(String(sessionID));\n return p;\n }\n\n return undefined;\n}\n\nfunction emitLlmSpan(shipper: TraceShipper, st: SessionState, info: any, sessionID: string): void {\n if (!st.traceId) return;\n const model = info?.modelID ?? info?.model ?? '';\n const provider = info?.providerID ?? info?.provider ?? '';\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'LLM' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n push(attrs, attrStr('neatlogs.llm.model_name', model ? String(model) : undefined));\n push(attrs, attrStr('neatlogs.llm.provider', provider ? String(provider) : undefined));\n\n let inIdx = 0;\n if (st.systemPrompt) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'system'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.systemPrompt));\n inIdx++;\n }\n if (st.currentInput) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'user'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.currentInput));\n setIO(attrs, 'LLM', st.currentInput, undefined);\n }\n\n const outText = st.outputParts.get(String(info?.id)) || messageText(info) || '';\n const toolCalls = st.toolCalls.get(String(info?.id)) ?? [];\n\n if (outText) {\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', outText));\n setIO(attrs, 'LLM', undefined, outText);\n st.lastAssistantText = outText;\n }\n // Tool-deciding turns often carry no text — render the tool call(s) as output.\n if (toolCalls.length) {\n toolCalls.forEach((tc, j) => {\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.name`, tc.name));\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.input ?? {})));\n });\n if (!outText) {\n const rendered = toolCalls.map((tc) => `→ ${tc.name}(${safeStringify(tc.input ?? {})})`).join('\\n');\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', rendered));\n setIO(attrs, 'LLM', undefined, rendered);\n }\n }\n\n // Tokens: opencode message tokens { input, output, reasoning, cache:{read,write} }\n const tokens = info?.tokens;\n if (tokens) {\n push(attrs, attrInt('neatlogs.llm.token_count.prompt', tokens.input));\n push(attrs, attrInt('neatlogs.llm.token_count.completion', tokens.output));\n if (tokens.input != null && tokens.output != null) {\n push(attrs, attrInt('neatlogs.llm.token_count.total', tokens.input + tokens.output));\n }\n push(attrs, attrInt('neatlogs.llm.token_count.reasoning', tokens.reasoning));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_read', tokens.cache?.read));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_write', tokens.cache?.write));\n }\n push(attrs, attrDouble('neatlogs.llm.cost_usd', info?.cost));\n push(attrs, attrStr('neatlogs.llm.finish_reason', info?.finish ? String(info.finish) : undefined));\n\n // Use opencode's real start time when available (else now).\n const createdMs = info?.time?.created;\n const startNano = typeof createdMs === 'number' ? msToNanoString(Math.floor(createdMs)) : nowNanoString();\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.llm.${model || 'model'}`,\n kind: 1,\n startTimeUnixNano: startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n\n // Reset accumulated parts for the next turn.\n if (info?.id) {\n st.outputParts.delete(String(info.id));\n st.toolCalls.delete(String(info.id));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction push(arr: OtlpKeyValue[], kv: OtlpKeyValue | undefined): void {\n if (kv) arr.push(kv);\n}\n\n/**\n * Set generic input/output on a span using the ALREADY-NAMESPACED keys the\n * backend consumer reads. The OTel-SDK wrappers rely on the attribute-processor\n * to map raw `input.value` → `neatlogs.{kind}.input`; this plugin ships spans\n * directly (no processor), so it must emit the namespaced keys itself:\n * neatlogs.input.value / neatlogs.output.value (generic)\n * neatlogs.{kind}.input / neatlogs.{kind}.output (kind-specific)\n * We also keep the raw input.value/output.value for any consumer that maps it.\n */\nfunction setIO(arr: OtlpKeyValue[], kind: string, input?: string, output?: string): void {\n const k = kind.toLowerCase();\n if (input !== undefined) {\n push(arr, attrStr('input.value', input));\n push(arr, attrStr('neatlogs.input.value', input));\n push(arr, attrStr(`neatlogs.${k}.input`, input));\n }\n if (output !== undefined) {\n push(arr, attrStr('output.value', output));\n push(arr, attrStr('neatlogs.output.value', output));\n push(arr, attrStr(`neatlogs.${k}.output`, output));\n }\n}\n\n/** Flatten an opencode message's parts/content to readable text. */\nfunction messageText(info: any): string {\n if (!info) return '';\n if (typeof info.text === 'string') return info.text;\n const parts = info.parts ?? info.content;\n if (typeof parts === 'string') return parts;\n if (!Array.isArray(parts)) return '';\n const out: string[] = [];\n for (const p of parts) {\n if (typeof p === 'string') out.push(p);\n else if (p && typeof p === 'object' && typeof p.text === 'string') out.push(p.text);\n }\n return out.join('');\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n"],"mappings":";AAcA,OAAO,cAAc;;;ACVd,IAAM,cAAc;;;ADa3B,IAAM,eAAe;AA0BrB,IAAM,kBAAuC;AAAA,EAC3C,QAAQ;AAAA,IACN,eAAe;AAAA,MACb,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,QAAQ;AAAA,YACN,QAAQ;AAAA,cACN,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,OAAO;AAAA,0BACL,OAAO;AAAA,4BACL;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,0BACF;AAAA,wBACF;AAAA,sBACF;AAAA,sBACA,QAAQ;AAAA,wBACN,aAAa,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACrC,WAAW,EAAE,MAAM,QAAQ,IAAI,EAAE;AAAA,wBACjC,UAAU,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBACjC,aAAa,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACrC,YAAY,EAAE,MAAM,cAAc,IAAI,EAAE;AAAA,wBACxC,aAAa,EAAE,MAAM,gBAAgB,IAAI,EAAE;AAAA,wBAC3C,YAAY,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,sBACrC;AAAA,oBACF;AAAA,oBACA,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,MAAM,YAAY,IAAI,EAAE,EAAE,EAAE;AAAA,oBAChF,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,MAAM,YAAY,IAAI,EAAE,EAAE,EAAE;AAAA,oBAClF,UAAU;AAAA,sBACR,QAAQ,EAAE,KAAK,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,OAAO,EAAE,MAAM,YAAY,IAAI,EAAE,EAAE;AAAA,oBAC/E;AAAA,oBACA,sBAAsB;AAAA,sBACpB,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,SAAS,EAAE,MAAM,UAAU,IAAI,EAAE,EAAE;AAAA,oBAChF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,UAAU;AAAA,cACR,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,YAAY;AAAA,0BACV,MAAM;AAAA,0BACN,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN;AAAA,sBACF;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,eAAe;AAAA,sBACb,QAAQ;AAAA,wBACN,UAAU,EAAE,MAAM,4CAA4C,IAAI,EAAE;AAAA,wBACpE,YAAY,EAAE,MAAM,YAAY,MAAM,cAAc,IAAI,EAAE;AAAA,sBAC5D;AAAA,oBACF;AAAA,oBACA,YAAY;AAAA,sBACV,QAAQ;AAAA,wBACN,OAAO,EAAE,MAAM,sDAAsD,IAAI,EAAE;AAAA,wBAC3E,OAAO,EAAE,MAAM,YAAY,MAAM,QAAQ,IAAI,EAAE;AAAA,sBACjD;AAAA,oBACF;AAAA,oBACA,MAAM;AAAA,sBACJ,QAAQ;AAAA,wBACN,SAAS,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBAChC,QAAQ,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBAC/B,YAAY,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACpC,cAAc,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBACrC,MAAM,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBAC9B,MAAM,EAAE,MAAM,YAAY,IAAI,EAAE;AAAA,wBAChC,mBAAmB,EAAE,MAAM,WAAW,IAAI,EAAE;AAAA,wBAC5C,iBAAiB,EAAE,MAAM,WAAW,IAAI,EAAE;AAAA,wBAC1C,YAAY;AAAA,0BACV,MAAM;AAAA,0BACN,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN;AAAA,wBACA,wBAAwB,EAAE,MAAM,UAAU,IAAI,GAAG;AAAA,wBACjD,QAAQ,EAAE,MAAM,UAAU,IAAI,GAAG;AAAA,sBACnC;AAAA,oBACF;AAAA,oBACA,QAAQ;AAAA,sBACN,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,MAAM,EAAE,MAAM,cAAc,IAAI,EAAE,EAAE;AAAA,oBACpF;AAAA,oBACA,YAAY;AAAA,sBACV,QAAQ,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,mBAAmB,EAAE;AAAA,oBAC1E;AAAA,oBACA,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,uBAAuB;AAAA,wBACvB,oBAAoB;AAAA,wBACpB,kBAAkB;AAAA,wBAClB,kBAAkB;AAAA,wBAClB,oBAAoB;AAAA,wBACpB,oBAAoB;AAAA,sBACtB;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,WAAW;AAAA,cACT,QAAQ;AAAA,gBACN,OAAO;AAAA,kBACL,QAAQ;AAAA,oBACN,IAAI;AAAA,sBACF,QAAQ;AAAA,wBACN,2BAA2B;AAAA,0BACzB,QAAQ;AAAA,4BACN,eAAe;AAAA,8BACb,MAAM;AAAA,8BACN,MAAM;AAAA,8BACN,IAAI;AAAA,4BACN;AAAA,0BACF;AAAA,wBACF;AAAA,sBACF;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,YAAY,SAAS,KAAK,SAAS,eAAe;AACxD,IAAM,4BAA4B,UAAU;AAAA,EAC1C;AACF;AAEO,IAAM,iBAAiB,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,EAAE;AAM1D,SAAS,YAAY,QAA4B;AAC/C,QAAM,MAAM,IAAI,WAAW,MAAM;AACjC,QAAM,SAAS,WAAW;AAC1B,MAAI,UAAU,OAAO,OAAO,oBAAoB,YAAY;AAC1D,WAAO,gBAAgB,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC5E,SAAO;AACT;AAEO,SAAS,kBAA8B;AAC5C,SAAO,YAAY,EAAE;AACvB;AAEO,SAAS,iBAA6B;AAC3C,SAAO,YAAY,CAAC;AACtB;AAQO,SAAS,gBAAwB;AACtC,UAAQ,OAAO,KAAK,IAAI,CAAC,IAAI,UAAY,SAAS;AACpD;AAEO,SAAS,eAAe,IAAoB;AACjD,UAAQ,OAAO,KAAK,MAAM,EAAE,CAAC,IAAI,UAAY,SAAS;AACxD;AAEO,SAAS,QAAQ,KAAa,OAAqD;AACxF,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,SAAO,EAAE,KAAK,OAAO,EAAE,aAAa,OAAO,KAAK,EAAE,EAAE;AACtD;AAEO,SAAS,QAAQ,KAAa,OAAqD;AACxF,MAAI,UAAU,UAAa,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AAC7E,SAAO,EAAE,KAAK,OAAO,EAAE,UAAU,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,EAAE;AAC/D;AAEO,SAAS,WAAW,KAAa,OAAqD;AAC3F,MAAI,UAAU,UAAa,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AAC7E,SAAO,EAAE,KAAK,OAAO,EAAE,aAAa,MAAM,EAAE;AAC9C;AAUO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACR;AAAA,EACQ,QAAoB,CAAC;AAAA,EACrB,SAAS;AAAA;AAAA;AAAA,EAGT,WAAW,oBAAI,IAAmB;AAAA,EAE1C,YAAY,MAA2B;AACrC,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAChF,SAAK,QAAQ,CAAC,CAAC,KAAK;AACpB,SAAK,aAAa,KAAK,cAAc;AACrC,SAAK,eAAe,KAAK,gBAAgB;AAAA,EAC3C;AAAA,EAEA,QAAQ,MAAsB;AAC5B,SAAK,MAAM,KAAK,IAAI;AAAA,EACtB;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAuB;AACrB,UAAM,IAAI,KAAK,OAAO,EAAE,QAAQ,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC;AAC7D,SAAK,SAAS,IAAI,CAAC;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAwB;AAC5B,WAAO,KAAK,SAAS,OAAO,GAAG;AAC7B,YAAM,QAAQ,WAAW,MAAM,KAAK,KAAK,QAAQ,CAAC;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAc,SAAwB;AACpC,QAAI,KAAK,MAAM,WAAW,EAAG;AAC7B,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,QAAQ,CAAC;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,MAAM,OAAO,CAAC;AACjC,UAAM,UAAU,KAAK,cAAc,KAAK;AACxC,UAAM,MAAM,GAAG,KAAK,QAAQ;AAE5B,QAAI,KAAK,MAAO,SAAQ,IAAI,GAAG,KAAK,MAAM,aAAa,MAAM,MAAM,aAAa,GAAG,EAAE;AAErF,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW;AAC3D,UAAI;AACF,cAAM,OAAO,MAAM,MAAM,KAAK;AAAA,UAC5B,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,aAAa,KAAK;AAAA,UACpB;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AAED,YAAI,KAAK,IAAI;AACX,cAAI,KAAK,MAAO,SAAQ,IAAI,GAAG,KAAK,MAAM,YAAY,MAAM,MAAM,QAAQ;AAC1E;AAAA,QACF;AACA,YAAI,KAAK,WAAW,KAAK;AACvB,kBAAQ,KAAK,GAAG,KAAK,MAAM,0CAAqC,MAAM,MAAM,QAAQ;AACpF;AAAA,QACF;AACA,YAAI,KAAK,SAAS,OAAO,KAAK,WAAW,KAAK;AAC5C,cAAI,KAAK,MAAO,SAAQ,KAAK,GAAG,KAAK,MAAM,SAAS,KAAK,MAAM,wBAAmB;AAClF;AAAA,QACF;AAAA,MAEF,SAAS,KAAK;AACZ,YAAI,KAAK,OAAO;AACd,kBAAQ;AAAA,YACN,GAAG,KAAK,MAAM,YAAY,OAAO,IAAI,KAAK,UAAU,KAAM,IAAc,OAAO;AAAA,UACjF;AAAA,QACF;AAAA,MACF;AACA,UAAI,UAAU,KAAK,YAAY;AAC7B,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC;AAAA,MAClE;AAAA,IACF;AACA,YAAQ,KAAK,GAAG,KAAK,MAAM,mBAAmB,MAAM,MAAM,gBAAgB,KAAK,UAAU,WAAW;AAAA,EACtG;AAAA,EAEQ,cAAc,OAA+B;AACnD,UAAM,aAAa,MAAM,IAAI,CAAC,UAAU;AAAA,MACtC,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK,gBAAgB;AAAA,MACnC,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,mBAAmB,WAAW,KAAK,iBAAiB;AAAA,MACpD,iBAAiB,WAAW,KAAK,eAAe;AAAA,MAChD,YAAY,KAAK,WAAW,IAAI,CAAC,OAAO;AAAA,QACtC,KAAK,EAAE;AAAA,QACP,OACE,EAAE,MAAM,aAAa,SACjB,EAAE,UAAU,WAAW,EAAE,MAAM,QAAQ,EAAE,IACzC,EAAE;AAAA,MACV,EAAE;AAAA,MACF,QAAQ,KAAK,SAAS,EAAE,MAAM,KAAK,OAAO,MAAM,SAAS,KAAK,OAAO,QAAQ,IAAI;AAAA,IACnF,EAAE;AAEF,UAAM,qBAA6E;AAAA,MACjF,EAAE,KAAK,gBAAgB,OAAO,EAAE,aAAa,oBAAoB,EAAE;AAAA,MACnE,EAAE,KAAK,mBAAmB,OAAO,EAAE,aAAa,YAAY,EAAE;AAAA,IAChE;AACA,QAAI,KAAK,cAAc;AACrB,yBAAmB,KAAK;AAAA,QACtB,KAAK;AAAA,QACL,OAAO,EAAE,aAAa,KAAK,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH;AAEA,UAAM,UAAU;AAAA,MACd,eAAe;AAAA,QACb;AAAA,UACE,UAAU,EAAE,YAAY,mBAAmB;AAAA,UAC3C,YAAY;AAAA,YACV;AAAA,cACE,OAAO,EAAE,MAAM,cAAc,SAAS,YAAY;AAAA,cAClD,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,0BAA0B,OAAO,OAAO;AACvD,QAAI,UAAU,KAAK,MAAO,SAAQ,KAAK,GAAG,KAAK,MAAM,kBAAkB,MAAM,EAAE;AAE/E,WAAO,0BAA0B,OAAO,0BAA0B,WAAW,OAAO,CAAC,EAAE,OAAO;AAAA,EAChG;AACF;AAGA,SAAS,WAAW,SAAmE;AACrF,QAAM,MAAM,OAAO,OAAO;AAC1B,QAAM,MAAM,OAAO,MAAM,WAAW;AACpC,QAAM,OAAO,OAAQ,OAAO,MAAO,WAAW;AAC9C,SAAO,EAAE,KAAK,MAAM,UAAU,KAAK;AACrC;;;AEhaO,IAAM,0BAA0B;AAGhC,IAAM,mCAAmC,OAAO;;;ACgFhD,IAAM,yBAAyB,OAAO,SAA4C;AACvF,QAAM,UAAU,QAAQ,IAAI,oBAAoB,IAAI,KAAK;AACzD,QAAM,YAAY,QAAQ,IAAI,qBAAqB,yBAAyB,KAAK;AACjF,QAAM,eAAe;AACrB,QAAM,QAAQ,OAAO,QAAQ,IAAI,kBAAkB,EAAE,EAAE,YAAY,MAAM;AAEzE,QAAM,UAAU,IAAI,aAAa,EAAE,QAAQ,UAAU,cAAc,MAAM,CAAC;AAC1E,QAAM,WAAW,oBAAI,IAA0B;AAE/C,WAAS,SAAS,WAAiC;AACjD,QAAI,IAAI,SAAS,IAAI,SAAS;AAC9B,QAAI,CAAC,GAAG;AACN,UAAI;AAAA,QACF,YAAY,oBAAI,IAAI;AAAA,QACpB,aAAa,oBAAI,IAAI;AAAA,QACrB,WAAW,oBAAI,IAAI;AAAA,QACnB,WAAW,oBAAI,IAAI;AAAA,QACnB,cAAc;AAAA,QACd,mBAAmB;AAAA,MACrB;AACA,eAAS,IAAI,WAAW,CAAC;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAKA,WAAS,UAAU,IAAkB,WAAyB;AAC5D,QAAI,GAAG,SAAU;AACjB,OAAG,UAAU,gBAAgB;AAC7B,OAAG,WAAW;AAAA,MACZ,QAAQ,eAAe;AAAA,MACvB,MAAM;AAAA,MACN,WAAW,cAAc;AAAA,MACzB,YAAY;AAAA,QACV,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,WAAW,EAAE;AAAA,QAChE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,WAAW,EAAE;AAAA,QACtE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,QACrE,EAAE,KAAK,uBAAuB,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAIA,iBAAe,cAAc,IAAkB,WAAkC;AAC/E,QAAI,GAAG,YAAY,GAAG,SAAS;AAC7B,YAAM,QAAQ,GAAG,SAAS,WAAW,MAAM;AAC3C,YAAM,OAAO,YAAY,GAAG,gBAAgB,QAAW,GAAG,qBAAqB,MAAS;AACxF,cAAQ,QAAQ;AAAA,QACd,SAAS,GAAG;AAAA,QACZ,QAAQ,GAAG,SAAS;AAAA,QACpB,MAAM,GAAG,SAAS;AAAA,QAClB,MAAM;AAAA,QACN,mBAAmB,GAAG,SAAS;AAAA,QAC/B,iBAAiB,cAAc;AAAA,QAC/B,YAAY;AAAA,QACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,MACpC,CAAC;AAGD,YAAM,IAAI,cAAc;AACxB,cAAQ,QAAQ;AAAA,QACd,SAAS,GAAG;AAAA,QACZ,QAAQ,eAAe;AAAA,QACvB,cAAc,GAAG,SAAS;AAAA,QAC1B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,YAAY;AAAA,UACV,EAAE,KAAK,2BAA2B,OAAO,EAAE,WAAW,KAAK,EAAE;AAAA,UAC7D,EAAE,KAAK,qBAAqB,OAAO,EAAE,WAAW,KAAK,EAAE;AAAA,UACvD,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,oBAAoB,EAAE;AAAA,QAC3E;AAAA,MACF,CAAC;AAAA,IACH;AAEA,OAAG,WAAW;AACd,OAAG,UAAU;AACb,OAAG,eAAe;AAClB,OAAG,oBAAoB;AACvB,OAAG,UAAU,MAAM;AACnB,OAAG,YAAY,MAAM;AACrB,OAAG,UAAU,MAAM;AACnB,UAAM,QAAQ,MAAM;AACpB,SAAK;AAAA,EACP;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQL,SAAS,YAAY;AACnB,UAAI;AACF,mBAAW,CAAC,WAAW,EAAE,KAAK,UAAU;AACtC,cAAI,GAAG,SAAU,OAAM,cAAc,IAAI,SAAS;AAAA,QACpD;AACA,cAAM,QAAQ,OAAO;AAAA,MACvB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,gBAAgB,OAAO,QAAa,WAAgB;AAClD,UAAI;AACF,cAAM,YAAY,OAAO,QAAQ,aAAa,QAAQ,aAAa,EAAE;AACrE,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,cAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,cAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MACG,OAAO,CAAC,MAAW,GAAG,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EACnE,IAAI,CAAC,MAAW,EAAE,IAAI,EACtB,KAAK,IAAI,IACZ;AACJ,YAAI,KAAM,IAAG,eAAe;AAC5B,kBAAU,IAAI,SAAS;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,sCAAsC,OAAO,QAAa,WAAgB;AACxE,UAAI;AACF,cAAM,YAAY,OAAO,QAAQ,aAAa,EAAE;AAChD,cAAM,QAAQ,QAAQ,UAAU,QAAQ,SAAS;AACjD,cAAM,SAAS,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,CAAC,MAAY,OAAO,MAAM,WAAW,IAAI,GAAG,QAAQ,EAAG,EAAE,KAAK,IAAI,IAAI,OAAO,SAAS,EAAE;AACxI,YAAI,aAAa,OAAQ,UAAS,SAAS,EAAE,eAAe;AAAA,MAC9D,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,OAAO,OAAO,EAAE,MAAM,MAAsB;AAC1C,UAAI;AACF,cAAM,YAAY,SAAS,UAAU,UAAU,WAAW,eAAe,KAAK;AAAA,MAChF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,uBAAuB,OAAO,OAAY,WAAgB;AACxD,UAAI;AACF,cAAM,YAAY,OAAO,OAAO,aAAa,EAAE;AAC/C,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,kBAAU,IAAI,SAAS;AACvB,cAAM,SAAS,OAAO,OAAO,UAAU,OAAO,QAAQ,EAAE;AACxD,WAAG,WAAW,IAAI,QAAQ;AAAA,UACxB,QAAQ,eAAe;AAAA,UACvB,WAAW,cAAc;AAAA,UACzB,MAAM,OAAO,OAAO,QAAQ,MAAM;AAAA,UAClC,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,sBAAsB,OAAO,OAAY,WAAgB;AACvD,UAAI;AACF,cAAM,YAAY,OAAO,OAAO,aAAa,EAAE;AAC/C,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,cAAM,SAAS,OAAO,OAAO,UAAU,OAAO,QAAQ,EAAE;AACxD,cAAM,QAAQ,GAAG,WAAW,IAAI,MAAM;AACtC,YAAI,CAAC,MAAO;AACZ,WAAG,WAAW,OAAO,MAAM;AAC3B,YAAI,CAAC,GAAG,QAAS;AAEjB,cAAM,QAAwB;AAAA,UAC5B,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,OAAO,EAAE;AAAA,UAC5D,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,MAAM,KAAK,EAAE;AAAA,UAChE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,QACvE;AACA,YAAI,MAAM,SAAS,QAAW;AAK5B,gBAAM,OAAO,QAAQ,cAAc,MAAM,IAAI,GAAG,MAAS;AACzD,eAAK,OAAO,QAAQ,uBAAuB,cAAc,MAAM,IAAI,CAAC,CAAC;AAAA,QACvE;AACA,YAAI,QAAQ,MAAO,MAAK,OAAO,QAAQ,uBAAuB,OAAO,OAAO,KAAK,CAAC,CAAC;AACnF,cAAM,MAAM,QAAQ,UAAU,QAAQ;AACtC,YAAI,QAAQ,QAAW;AACrB,gBAAM,IAAI,OAAO,QAAQ,WAAW,MAAM,cAAc,GAAG;AAC3D,gBAAM,OAAO,QAAQ,QAAW,CAAC;AACjC,eAAK,OAAO,QAAQ,wBAAwB,CAAC,CAAC;AAAA,QAChD;AACA,YAAI,QAAQ,aAAa,QAAW;AAClC,eAAK,OAAO,QAAQ,0BAA0B,cAAc,OAAO,QAAQ,CAAC,CAAC;AAAA,QAC/E;AAEA,gBAAQ,QAAQ;AAAA,UACd,SAAS,GAAG;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,cAAc,GAAG,UAAU;AAAA,UAC3B,MAAM,iBAAiB,MAAM,IAAI;AAAA,UACjC,MAAM;AAAA,UACN,mBAAmB,MAAM;AAAA,UACzB,iBAAiB,cAAc;AAAA,UAC/B,YAAY;AAAA,UACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,QACpC,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,yBAAyB;AACtC,IAAO,0BAAQ;AAMf,SAAS,YACP,SACA,UACA,UACA,WACA,eACA,OAC8B;AAC9B,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,OAAO,cAAc,CAAC;AAGpC,MAAI,SAAS,0BAA0B,SAAS,0BAA0B;AACxE,UAAM,OAAO,MAAM,QAAQ;AAC3B,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,QAAI,CAAC,aAAa,CAAC,UAAW,QAAO;AACrC,UAAM,KAAK,SAAS,OAAO,SAAS,CAAC;AACrC,QAAI,MAAM,SAAS,UAAU,OAAO,MAAM,SAAS,UAAU;AAC3D,SAAG,YAAY,IAAI,OAAO,SAAS,GAAG,KAAK,IAAI;AAAA,IACjD,WAAW,MAAM,SAAS,UAAU,MAAM,MAAM;AAC9C,YAAM,OAAO,GAAG,UAAU,IAAI,OAAO,SAAS,CAAC,KAAK,CAAC;AACrD,YAAM,SAAS,OAAO,KAAK,UAAU,KAAK,IAAI;AAC9C,YAAM,QAAQ,MAAM,OAAO,SAAS,CAAC;AACrC,YAAM,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AACrD,UAAI,SAAU,UAAS,QAAQ;AAAA,UAC1B,MAAK,KAAK,EAAE,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,OAAO,CAAC;AACzD,SAAG,UAAU,IAAI,OAAO,SAAS,GAAG,IAAI;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,qBAAqB,SAAS,qBAAqB;AAC9D,UAAM,OAAO,MAAM,QAAQ,MAAM,WAAW;AAC5C,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,QAAI,CAAC,UAAW,QAAO;AACvB,QAAI,MAAM,SAAS,YAAa,QAAO;AACvC,UAAM,YAAY,MAAM,MAAM,aAAa,MAAM;AACjD,UAAM,KAAK,OAAO,MAAM,MAAM,EAAE;AAChC,QAAI,CAAC,aAAa,CAAC,GAAI,QAAO;AAC9B,UAAM,KAAK,SAAS,OAAO,SAAS,CAAC;AACrC,QAAI,GAAG,UAAU,IAAI,EAAE,EAAG,QAAO;AACjC,OAAG,UAAU,IAAI,EAAE;AACnB,cAAU,IAAI,OAAO,SAAS,CAAC;AAC/B,gBAAY,SAAS,IAAI,MAAM,OAAO,SAAS,CAAC;AAEhD,WAAO,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC9C;AAGA,MAAI,SAAS,kBAAkB,SAAS,mBAAmB;AACzD,UAAM,YAAY,MAAM,aAAa,MAAM,MAAM;AACjD,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,KAAK,SAAS,IAAI,OAAO,SAAS,CAAC;AACzC,QAAI,CAAC,GAAI,QAAO;AAChB,OAAG,WAAW,MAAM;AACpB,UAAM,IAAI,cAAc,IAAI,OAAO,SAAS,CAAC;AAC7C,QAAI,SAAS,kBAAmB,UAAS,OAAO,OAAO,SAAS,CAAC;AACjE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,YAAY,SAAuB,IAAkB,MAAW,WAAyB;AAChG,MAAI,CAAC,GAAG,QAAS;AACjB,QAAM,QAAQ,MAAM,WAAW,MAAM,SAAS;AAC9C,QAAM,WAAW,MAAM,cAAc,MAAM,YAAY;AAEvD,QAAM,QAAwB;AAAA,IAC5B,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,MAAM,EAAE;AAAA,IAC3D,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,EACvE;AACA,OAAK,OAAO,QAAQ,2BAA2B,QAAQ,OAAO,KAAK,IAAI,MAAS,CAAC;AACjF,OAAK,OAAO,QAAQ,yBAAyB,WAAW,OAAO,QAAQ,IAAI,MAAS,CAAC;AAErF,MAAI,QAAQ;AACZ,MAAI,GAAG,cAAc;AACnB,SAAK,OAAO,QAAQ,+BAA+B,KAAK,SAAS,QAAQ,CAAC;AAC1E,SAAK,OAAO,QAAQ,+BAA+B,KAAK,YAAY,GAAG,YAAY,CAAC;AACpF;AAAA,EACF;AACA,MAAI,GAAG,cAAc;AACnB,SAAK,OAAO,QAAQ,+BAA+B,KAAK,SAAS,MAAM,CAAC;AACxE,SAAK,OAAO,QAAQ,+BAA+B,KAAK,YAAY,GAAG,YAAY,CAAC;AACpF,UAAM,OAAO,OAAO,GAAG,cAAc,MAAS;AAAA,EAChD;AAEA,QAAM,UAAU,GAAG,YAAY,IAAI,OAAO,MAAM,EAAE,CAAC,KAAK,YAAY,IAAI,KAAK;AAC7E,QAAM,YAAY,GAAG,UAAU,IAAI,OAAO,MAAM,EAAE,CAAC,KAAK,CAAC;AAEzD,MAAI,SAAS;AACX,SAAK,OAAO,QAAQ,uCAAuC,WAAW,CAAC;AACvE,SAAK,OAAO,QAAQ,0CAA0C,OAAO,CAAC;AACtE,UAAM,OAAO,OAAO,QAAW,OAAO;AACtC,OAAG,oBAAoB;AAAA,EACzB;AAEA,MAAI,UAAU,QAAQ;AACpB,cAAU,QAAQ,CAAC,IAAI,MAAM;AAC3B,WAAK,OAAO,QAAQ,2BAA2B,CAAC,SAAS,GAAG,IAAI,CAAC;AACjE,WAAK,OAAO,QAAQ,2BAA2B,CAAC,cAAc,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAAA,IAC9F,CAAC;AACD,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,UAAU,IAAI,CAAC,OAAO,UAAK,GAAG,IAAI,IAAI,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,IAAI;AAClG,WAAK,OAAO,QAAQ,uCAAuC,WAAW,CAAC;AACvE,WAAK,OAAO,QAAQ,0CAA0C,QAAQ,CAAC;AACvE,YAAM,OAAO,OAAO,QAAW,QAAQ;AAAA,IACzC;AAAA,EACF;AAGA,QAAM,SAAS,MAAM;AACrB,MAAI,QAAQ;AACV,SAAK,OAAO,QAAQ,mCAAmC,OAAO,KAAK,CAAC;AACpE,SAAK,OAAO,QAAQ,uCAAuC,OAAO,MAAM,CAAC;AACzE,QAAI,OAAO,SAAS,QAAQ,OAAO,UAAU,MAAM;AACjD,WAAK,OAAO,QAAQ,kCAAkC,OAAO,QAAQ,OAAO,MAAM,CAAC;AAAA,IACrF;AACA,SAAK,OAAO,QAAQ,sCAAsC,OAAO,SAAS,CAAC;AAC3E,SAAK,OAAO,QAAQ,uCAAuC,OAAO,OAAO,IAAI,CAAC;AAC9E,SAAK,OAAO,QAAQ,wCAAwC,OAAO,OAAO,KAAK,CAAC;AAAA,EAClF;AACA,OAAK,OAAO,WAAW,yBAAyB,MAAM,IAAI,CAAC;AAC3D,OAAK,OAAO,QAAQ,8BAA8B,MAAM,SAAS,OAAO,KAAK,MAAM,IAAI,MAAS,CAAC;AAGjG,QAAM,YAAY,MAAM,MAAM;AAC9B,QAAM,YAAY,OAAO,cAAc,WAAW,eAAe,KAAK,MAAM,SAAS,CAAC,IAAI,cAAc;AAExG,UAAQ,QAAQ;AAAA,IACd,SAAS,GAAG;AAAA,IACZ,QAAQ,eAAe;AAAA,IACvB,cAAc,GAAG,UAAU;AAAA,IAC3B,MAAM,gBAAgB,SAAS,OAAO;AAAA,IACtC,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,iBAAiB,cAAc;AAAA,IAC/B,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,EACpC,CAAC;AAGD,MAAI,MAAM,IAAI;AACZ,OAAG,YAAY,OAAO,OAAO,KAAK,EAAE,CAAC;AACrC,OAAG,UAAU,OAAO,OAAO,KAAK,EAAE,CAAC;AAAA,EACrC;AACF;AAMA,SAAS,KAAK,KAAqB,IAAoC;AACrE,MAAI,GAAI,KAAI,KAAK,EAAE;AACrB;AAWA,SAAS,MAAM,KAAqB,MAAc,OAAgB,QAAuB;AACvF,QAAM,IAAI,KAAK,YAAY;AAC3B,MAAI,UAAU,QAAW;AACvB,SAAK,KAAK,QAAQ,eAAe,KAAK,CAAC;AACvC,SAAK,KAAK,QAAQ,wBAAwB,KAAK,CAAC;AAChD,SAAK,KAAK,QAAQ,YAAY,CAAC,UAAU,KAAK,CAAC;AAAA,EACjD;AACA,MAAI,WAAW,QAAW;AACxB,SAAK,KAAK,QAAQ,gBAAgB,MAAM,CAAC;AACzC,SAAK,KAAK,QAAQ,yBAAyB,MAAM,CAAC;AAClD,SAAK,KAAK,QAAQ,YAAY,CAAC,WAAW,MAAM,CAAC;AAAA,EACnD;AACF;AAGA,SAAS,YAAY,MAAmB;AACtC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,OAAO,KAAK,SAAS,SAAU,QAAO,KAAK;AAC/C,QAAM,QAAQ,KAAK,SAAS,KAAK;AACjC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,MAAgB,CAAC;AACvB,aAAW,KAAK,OAAO;AACrB,QAAI,OAAO,MAAM,SAAU,KAAI,KAAK,CAAC;AAAA,aAC5B,KAAK,OAAO,MAAM,YAAY,OAAO,EAAE,SAAS,SAAU,KAAI,KAAK,EAAE,IAAI;AAAA,EACpF;AACA,SAAO,IAAI,KAAK,EAAE;AACpB;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,KAAK;AAAA,EAClC,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/opencode-trace-shipper.ts","../src/version.ts","../src/constants.ts","../src/opencode-plugin.ts"],"sourcesContent":["/**\n * Direct OTLP trace shipper for the opencode plugin.\n *\n * opencode loads the plugin in-process but `opencode run` is short-lived — it\n * tears down the moment a session goes idle. The OpenTelemetry BatchSpanProcessor\n * (async, scheduled-delay export + a `beforeExit` shutdown) races that teardown,\n * dropping spans or leaving aborted half-sent requests. This shipper mirrors the\n * proven `neatlogs-claude-code` design instead: spans are queued, then `flush()`\n * does a single AWAITED `fetch(POST /v1/traces)` round-trip that completes before\n * the host process can exit. No batch processor, no exit-time race.\n *\n * Self-contained (inlined OTLP protobuf schema) so it adds no runtime file I/O.\n */\n\nimport protobuf from 'protobufjs';\nimport { __version__ } from './version.js';\n\nconst PACKAGE_NAME = 'neatlogs.opencode';\n\nexport interface OtlpKeyValue {\n key: string;\n value: {\n stringValue?: string;\n intValue?: string;\n doubleValue?: number;\n boolValue?: boolean;\n };\n}\n\nexport interface OtlpSpan {\n traceId: Uint8Array;\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n /** OTLP SpanKind enum (0=unspecified, 1=internal, …). Neatlogs kind rides in attributes. */\n kind: number;\n startTimeUnixNano: string;\n endTimeUnixNano: string;\n attributes: OtlpKeyValue[];\n status?: { code: number; message?: string };\n}\n\n// Inlined OTLP proto definition — avoids .proto file I/O at runtime.\nconst OTLP_PROTO_JSON: protobuf.INamespace = {\n nested: {\n opentelemetry: {\n nested: {\n proto: {\n nested: {\n common: {\n nested: {\n v1: {\n nested: {\n AnyValue: {\n oneofs: {\n value: {\n oneof: [\n 'stringValue',\n 'boolValue',\n 'intValue',\n 'doubleValue',\n 'arrayValue',\n 'kvlistValue',\n 'bytesValue',\n ],\n },\n },\n fields: {\n stringValue: { type: 'string', id: 1 },\n boolValue: { type: 'bool', id: 2 },\n intValue: { type: 'int64', id: 3 },\n doubleValue: { type: 'double', id: 4 },\n arrayValue: { type: 'ArrayValue', id: 5 },\n kvlistValue: { type: 'KeyValueList', id: 6 },\n bytesValue: { type: 'bytes', id: 7 },\n },\n },\n ArrayValue: { fields: { values: { rule: 'repeated', type: 'AnyValue', id: 1 } } },\n KeyValueList: { fields: { values: { rule: 'repeated', type: 'KeyValue', id: 1 } } },\n KeyValue: {\n fields: { key: { type: 'string', id: 1 }, value: { type: 'AnyValue', id: 2 } },\n },\n InstrumentationScope: {\n fields: { name: { type: 'string', id: 1 }, version: { type: 'string', id: 2 } },\n },\n },\n },\n },\n },\n resource: {\n nested: {\n v1: {\n nested: {\n Resource: {\n fields: {\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n trace: {\n nested: {\n v1: {\n nested: {\n ResourceSpans: {\n fields: {\n resource: { type: 'opentelemetry.proto.resource.v1.Resource', id: 1 },\n scopeSpans: { rule: 'repeated', type: 'ScopeSpans', id: 2 },\n },\n },\n ScopeSpans: {\n fields: {\n scope: { type: 'opentelemetry.proto.common.v1.InstrumentationScope', id: 1 },\n spans: { rule: 'repeated', type: 'Span', id: 2 },\n },\n },\n Span: {\n fields: {\n traceId: { type: 'bytes', id: 1 },\n spanId: { type: 'bytes', id: 2 },\n traceState: { type: 'string', id: 3 },\n parentSpanId: { type: 'bytes', id: 4 },\n name: { type: 'string', id: 5 },\n kind: { type: 'SpanKind', id: 6 },\n startTimeUnixNano: { type: 'fixed64', id: 7 },\n endTimeUnixNano: { type: 'fixed64', id: 8 },\n attributes: {\n rule: 'repeated',\n type: 'opentelemetry.proto.common.v1.KeyValue',\n id: 9,\n },\n droppedAttributesCount: { type: 'uint32', id: 10 },\n status: { type: 'Status', id: 15 },\n },\n },\n Status: {\n fields: { message: { type: 'string', id: 2 }, code: { type: 'StatusCode', id: 3 } },\n },\n StatusCode: {\n values: { STATUS_CODE_UNSET: 0, STATUS_CODE_OK: 1, STATUS_CODE_ERROR: 2 },\n },\n SpanKind: {\n values: {\n SPAN_KIND_UNSPECIFIED: 0,\n SPAN_KIND_INTERNAL: 1,\n SPAN_KIND_SERVER: 2,\n SPAN_KIND_CLIENT: 3,\n SPAN_KIND_PRODUCER: 4,\n SPAN_KIND_CONSUMER: 5,\n },\n },\n },\n },\n },\n },\n collector: {\n nested: {\n trace: {\n nested: {\n v1: {\n nested: {\n ExportTraceServiceRequest: {\n fields: {\n resourceSpans: {\n rule: 'repeated',\n type: 'opentelemetry.proto.trace.v1.ResourceSpans',\n id: 1,\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n },\n};\n\nconst protoRoot = protobuf.Root.fromJSON(OTLP_PROTO_JSON);\nconst ExportTraceServiceRequest = protoRoot.lookupType(\n 'opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest',\n);\n\nexport const SpanStatusCode = { UNSET: 0, OK: 1, ERROR: 2 } as const;\n\n// ---------------------------------------------------------------------------\n// ID + time + attribute helpers\n// ---------------------------------------------------------------------------\n\nfunction randomBytes(length: number): Uint8Array {\n const out = new Uint8Array(length);\n const crypto = globalThis.crypto;\n if (crypto && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(out);\n return out;\n }\n for (let i = 0; i < out.length; i++) out[i] = Math.floor(Math.random() * 256);\n return out;\n}\n\nexport function generateTraceId(): Uint8Array {\n return randomBytes(16);\n}\n\nexport function generateSpanId(): Uint8Array {\n return randomBytes(8);\n}\n\nexport function bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport function nowNanoString(): string {\n return (BigInt(Date.now()) * 1_000_000n).toString();\n}\n\nexport function msToNanoString(ms: number): string {\n return (BigInt(Math.floor(ms)) * 1_000_000n).toString();\n}\n\nexport function attrStr(key: string, value: string | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null) return undefined;\n return { key, value: { stringValue: String(value) } };\n}\n\nexport function attrInt(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { intValue: String(Math.trunc(value)) } };\n}\n\nexport function attrDouble(key: string, value: number | undefined): OtlpKeyValue | undefined {\n if (value === undefined || value === null || !Number.isFinite(value)) return undefined;\n return { key, value: { doubleValue: value } };\n}\n\nexport interface TraceShipperOptions {\n apiKey: string;\n endpoint: string;\n debug?: boolean;\n maxRetries?: number;\n workflowName?: string;\n}\n\nexport class TraceShipper {\n private apiKey: string;\n private endpoint: string;\n private debug: boolean;\n private maxRetries: number;\n workflowName: string;\n private queue: OtlpSpan[] = [];\n private prefix = '[neatlogs/opencode]';\n /** In-flight flush round-trips — awaited by `settle()` on dispose so a\n * short-lived host (`opencode run`) can force pending exports to complete. */\n private inflight = new Set<Promise<void>>();\n\n constructor(opts: TraceShipperOptions) {\n this.apiKey = opts.apiKey;\n this.endpoint = opts.endpoint.endsWith('/') ? opts.endpoint.slice(0, -1) : opts.endpoint;\n this.debug = !!opts.debug;\n this.maxRetries = opts.maxRetries ?? 3;\n this.workflowName = opts.workflowName || '';\n }\n\n enqueue(span: OtlpSpan): void {\n this.queue.push(span);\n }\n\n get pending(): number {\n return this.queue.length;\n }\n\n /**\n * Ship all queued spans in a single awaited POST. Resolves only once the HTTP\n * response is received (or all retries are exhausted) — so a short-lived host\n * can safely exit immediately after awaiting this.\n *\n * The returned promise is also tracked in `inflight` so `settle()` can await\n * it even when the caller (an un-awaited opencode `event` hook) drops it.\n */\n flush(): Promise<void> {\n const p = this._flush().finally(() => this.inflight.delete(p));\n this.inflight.add(p);\n return p;\n }\n\n /**\n * Await every flush started so far (including ones whose promise the caller\n * discarded). Called from the plugin's `dispose` hook, which opencode DOES\n * await on scope teardown — unlike the fire-and-forget `event` hook.\n */\n async settle(): Promise<void> {\n while (this.inflight.size > 0) {\n await Promise.allSettled(Array.from(this.inflight));\n }\n }\n\n private async _flush(): Promise<void> {\n if (this.queue.length === 0) return;\n if (!this.apiKey) {\n this.queue = [];\n return;\n }\n\n const spans = this.queue.splice(0);\n const payload = this.buildProtobuf(spans);\n const url = `${this.endpoint}/v1/traces`;\n\n if (this.debug) console.log(`${this.prefix} Shipping ${spans.length} spans to ${url}`);\n\n for (let attempt = 1; attempt <= this.maxRetries; attempt++) {\n try {\n const resp = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-protobuf',\n 'x-api-key': this.apiKey,\n },\n body: payload as any,\n });\n\n if (resp.ok) {\n if (this.debug) console.log(`${this.prefix} Shipped ${spans.length} spans`);\n return;\n }\n if (resp.status === 401) {\n console.warn(`${this.prefix} Invalid API key (401) — dropping ${spans.length} spans`);\n return;\n }\n if (resp.status < 500 && resp.status !== 429) {\n if (this.debug) console.warn(`${this.prefix} HTTP ${resp.status} — dropping spans`);\n return;\n }\n // 429 / 5xx → retry\n } catch (err) {\n if (this.debug) {\n console.warn(\n `${this.prefix} Attempt ${attempt}/${this.maxRetries}: ${(err as Error).message}`,\n );\n }\n }\n if (attempt < this.maxRetries) {\n await new Promise((r) => setTimeout(r, 500 * 2 ** (attempt - 1)));\n }\n }\n console.warn(`${this.prefix} Failed to ship ${spans.length} spans after ${this.maxRetries} attempts`);\n }\n\n private buildProtobuf(spans: OtlpSpan[]): Uint8Array {\n const protoSpans = spans.map((span) => ({\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || undefined,\n name: span.name,\n kind: span.kind,\n startTimeUnixNano: nanoToLong(span.startTimeUnixNano),\n endTimeUnixNano: nanoToLong(span.endTimeUnixNano),\n attributes: span.attributes.map((a) => ({\n key: a.key,\n value:\n a.value.intValue !== undefined\n ? { intValue: nanoToLong(a.value.intValue) }\n : a.value,\n })),\n status: span.status ? { code: span.status.code, message: span.status.message } : undefined,\n }));\n\n const resourceAttributes: Array<{ key: string; value: { stringValue: string } }> = [\n { key: 'service.name', value: { stringValue: 'neatlogs.opencode' } },\n { key: 'service.version', value: { stringValue: __version__ } },\n ];\n if (this.workflowName) {\n resourceAttributes.push({\n key: 'neatlogs.workflow_name',\n value: { stringValue: this.workflowName },\n });\n }\n\n const message = {\n resourceSpans: [\n {\n resource: { attributes: resourceAttributes },\n scopeSpans: [\n {\n scope: { name: PACKAGE_NAME, version: __version__ },\n spans: protoSpans,\n },\n ],\n },\n ],\n };\n\n const errMsg = ExportTraceServiceRequest.verify(message);\n if (errMsg && this.debug) console.warn(`${this.prefix} Proto verify: ${errMsg}`);\n\n return ExportTraceServiceRequest.encode(ExportTraceServiceRequest.fromObject(message)).finish();\n }\n}\n\n/** protobufjs encodes fixed64/int64 from a {low,high,unsigned} Long-like. */\nfunction nanoToLong(nanoStr: string): { low: number; high: number; unsigned: boolean } {\n const big = BigInt(nanoStr);\n const low = Number(big & 0xffffffffn);\n const high = Number((big >> 32n) & 0xffffffffn);\n return { low, high, unsigned: true };\n}\n","/**\n * SDK version. Kept in sync with package.json by the `version:sync` script\n * (runs automatically on `prebuild`). Do not edit by hand — bump package.json.\n */\nexport const __version__ = '1.1.22';\n","/** Stable SDK-wide defaults shared by every NeatLogs entry point. */\nexport const DEFAULT_INGEST_ENDPOINT = 'https://ingest.neatlogs.com' as const;\nexport const DEFAULT_MAX_QUEUE_ITEMS = 2048;\nexport const DEFAULT_MAX_SEMANTIC_STREAM_EVENTS = 128;\nexport const DEFAULT_MAX_STREAM_CAPTURE_BYTES = 1024 * 1024;\nexport const DEFAULT_MAX_STREAM_CAPTURE_ITEMS = 1024;\n\n/** UTF-8 byte length without allocating a second buffer for hostile stream chunks. */\nexport function utf8ByteLength(\n value: string,\n limit = Number.MAX_SAFE_INTEGER,\n): number {\n let bytes = 0;\n for (let i = 0; i < value.length; i++) {\n const code = value.charCodeAt(i);\n if (code < 0x80) bytes += 1;\n else if (code < 0x800) bytes += 2;\n else if (code >= 0xd800 && code <= 0xdbff && i + 1 < value.length) {\n const next = value.charCodeAt(i + 1);\n if (next >= 0xdc00 && next <= 0xdfff) {\n bytes += 4;\n i += 1;\n } else bytes += 3;\n } else bytes += 3;\n if (bytes > limit) return limit + 1;\n }\n return bytes;\n}\n\nexport function exportQueueCapacity(batchSize: number): number {\n return Math.max(DEFAULT_MAX_QUEUE_ITEMS, batchSize * 4);\n}\n","/**\n * Neatlogs opencode plugin.\n *\n * opencode loads plugins from its config (`opencode.json` → `\"plugin\": [...]`)\n * or from local `.opencode/plugin/*.ts` files. A plugin is an async factory that\n * receives an app context and returns lifecycle hooks. This plugin instruments\n * opencode automatically — no per-call wiring — turning each opencode TURN into\n * its own neatlogs trace (mirrors @neatlogs/claude-code):\n *\n * WORKFLOW opencode.turn (one TRACE per user turn; parents that turn's spans)\n * ↳ LLM assistant turn (per completed assistant message)\n * ↳ TOOL tool execution (tool.execute.before → tool.execute.after)\n *\n * A turn opens on `chat.message` and closes on `session.idle` (which fires after\n * the turn's full tool-loop settles) — NOT on each `message.completed`, so a\n * multi-round tool-using turn stays one trace. Every span carries\n * `neatlogs.conversation.id` = the opencode session ID and a per-turn trace id;\n * all of a session's turn-traces are grouped in the UI via `neatlogs.session.id`.\n *\n * Export model (mirrors @raindrop-ai/opencode-plugin and neatlogs-claude-code):\n * opencode loads the plugin in-process but `opencode run` is short-lived. Rather\n * than the OpenTelemetry BatchSpanProcessor (whose async, scheduled-delay export\n * + `beforeExit` shutdown races the teardown and drops spans), this plugin builds\n * spans directly and ships them via AWAITED `fetch(POST /v1/traces)` — and it\n * flushes after every completed assistant turn (incremental persistence) plus a\n * final flush on `session.idle`. A `neatlogs.trace.complete` marker is sent so\n * the backend enqueues the trace for finalization (simplification → UI).\n *\n * Setup — either:\n * • npm package, in opencode.json: `{ \"plugin\": [\"neatlogs/opencode\"] }`, OR\n * • local file `.opencode/plugin/neatlogs.ts`:\n * export { NeatlogsOpencodePlugin as default } from 'neatlogs/opencode';\n *\n * Env:\n * NEATLOGS_API_KEY required to export\n * NEATLOGS_ENDPOINT backend base URL (default https://ingest.neatlogs.com)\n */\n\nimport {\n TraceShipper,\n type OtlpSpan,\n type OtlpKeyValue,\n SpanStatusCode,\n generateTraceId,\n generateSpanId,\n nowNanoString,\n msToNanoString,\n attrStr,\n attrInt,\n attrDouble,\n} from './opencode-trace-shipper.js';\nimport { DEFAULT_INGEST_ENDPOINT } from './constants.js';\n\n/** A span being built incrementally — ended (and shipped) later. */\ninterface OpenSpan {\n spanId: Uint8Array;\n parentSpanId?: Uint8Array;\n name: string;\n startNano: string;\n attributes: OtlpKeyValue[];\n}\n\ninterface SessionState {\n /** Per-TURN trace id — minted when the turn's root opens, so each turn is its\n * own trace. Undefined between turns. */\n traceId?: Uint8Array;\n /** The current turn's WORKFLOW root span (created on chat.message, ended on idle). */\n rootSpan?: OpenSpan;\n /** Open TOOL spans keyed by callID → start time. */\n toolStarts: Map<string, { spanId: Uint8Array; startNano: string; tool: string; args: any }>;\n /** Accumulated assistant text per messageID (from text parts). */\n outputParts: Map<string, string>;\n /** Tool calls per assistant messageID (so a tool-only turn still has output). */\n toolCalls: Map<string, Array<{ name: string; input: any; callID: string }>>;\n /** assistant messageIDs already emitted (completion can fire repeatedly). */\n processed: Set<string>;\n /** Current user prompt (this turn's input). */\n currentInput: string;\n /** Captured system prompt. */\n systemPrompt?: string;\n /** Latest assistant text — the AGENT root's output on close. */\n lastAssistantText: string;\n}\n\nexport const NeatlogsOpencodePlugin = async (_ctx: any): Promise<Record<string, any>> => {\n const apiKey = (process.env.NEATLOGS_API_KEY ?? '').trim();\n const endpoint = (process.env.NEATLOGS_ENDPOINT ?? DEFAULT_INGEST_ENDPOINT).trim();\n const workflowName = 'opencode';\n const debug = String(process.env.NEATLOGS_DEBUG || '').toLowerCase() === 'true';\n\n const shipper = new TraceShipper({ apiKey, endpoint, workflowName, debug });\n const sessions = new Map<string, SessionState>();\n\n function stateFor(sessionID: string): SessionState {\n let s = sessions.get(sessionID);\n if (!s) {\n s = {\n toolStarts: new Map(),\n outputParts: new Map(),\n toolCalls: new Map(),\n processed: new Set(),\n currentInput: '',\n lastAssistantText: '',\n };\n sessions.set(sessionID, s);\n }\n return s;\n }\n\n /** Start the per-turn WORKFLOW root span, minting a fresh trace id for this\n * turn (idempotent within a turn). `neatlogs.session.id` groups the session's\n * turn-traces in the UI. */\n function startRoot(st: SessionState, sessionID: string): void {\n if (st.rootSpan) return;\n st.traceId = generateTraceId();\n st.rootSpan = {\n spanId: generateSpanId(),\n name: 'opencode.turn',\n startNano: nowNanoString(),\n attributes: [\n { key: 'neatlogs.span.kind', value: { stringValue: 'WORKFLOW' } },\n { key: 'neatlogs.agent.framework', value: { stringValue: 'opencode' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n { key: 'neatlogs.session.id', value: { stringValue: sessionID } },\n ],\n };\n }\n\n /** End + enqueue the WORKFLOW turn root, send the completion marker, and flush.\n * Clears the turn's trace id + accumulators so the next turn is a fresh trace. */\n async function closeAndFlush(st: SessionState, sessionID: string): Promise<void> {\n if (st.rootSpan && st.traceId) {\n const attrs = st.rootSpan.attributes.slice();\n setIO(attrs, 'WORKFLOW', st.currentInput || undefined, st.lastAssistantText || undefined);\n shipper.enqueue({\n traceId: st.traceId,\n spanId: st.rootSpan.spanId,\n name: st.rootSpan.name,\n kind: 1,\n startTimeUnixNano: st.rootSpan.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n // Completion marker — the backend only finalizes (simplifies → UI) a trace\n // once it sees a `neatlogs.trace.complete` span. Parented to the root.\n const m = nowNanoString();\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan.spanId,\n name: 'neatlogs.trace.complete',\n kind: 1,\n startTimeUnixNano: m,\n endTimeUnixNano: m,\n attributes: [\n { key: 'neatlogs.trace.complete', value: { boolValue: true } },\n { key: 'neatlogs.internal', value: { boolValue: true } },\n { key: 'neatlogs.span.kind', value: { stringValue: 'Neatlogs.INTERNAL' } },\n ],\n });\n }\n // Reset per-turn state so the next chat.message opens a brand-new trace.\n st.rootSpan = undefined;\n st.traceId = undefined;\n st.currentInput = '';\n st.lastAssistantText = '';\n st.processed.clear();\n st.outputParts.clear();\n st.toolCalls.clear();\n await shipper.flush();\n void sessionID;\n }\n\n return {\n /**\n * Awaited by opencode on scope teardown (registered via an internal\n * `addFinalizer`), unlike the fire-and-forget `event` hook. On a short-lived\n * `opencode run`, `session.idle`'s `await shipper.flush()` is a dangling\n * promise the process kills before the POST resolves — so we close any turn\n * still open and `settle()` all in-flight flushes here, before exit.\n */\n dispose: async () => {\n try {\n for (const [sessionID, st] of sessions) {\n if (st.rootSpan) await closeAndFlush(st, sessionID);\n }\n await shipper.settle();\n } catch {\n /* never break opencode over tracing */\n }\n },\n\n /** Fired when the user submits a prompt — open the turn's AGENT root. */\n 'chat.message': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? output?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const parts = output?.parts ?? [];\n const text = Array.isArray(parts)\n ? parts\n .filter((p: any) => p?.type === 'text' && typeof p.text === 'string')\n .map((p: any) => p.text)\n .join('\\n')\n : '';\n if (text) st.currentInput = text;\n startRoot(st, sessionID);\n } catch {\n /* ignore */\n }\n },\n\n /** Capture the system prompt. */\n 'experimental.chat.system.transform': async (_input: any, output: any) => {\n try {\n const sessionID = String(_input?.sessionID ?? '');\n const parts = output?.system ?? output?.parts ?? output;\n const joined = Array.isArray(parts) ? parts.map((p: any) => (typeof p === 'string' ? p : p?.text ?? '')).join('\\n') : String(parts ?? '');\n if (sessionID && joined) stateFor(sessionID).systemPrompt = joined;\n } catch {\n /* ignore */\n }\n },\n\n /** Global event bus — message parts, assistant completions, session idle. */\n event: async ({ event }: { event: any }) => {\n try {\n await handleEvent(shipper, sessions, stateFor, startRoot, closeAndFlush, event);\n } catch {\n // never break opencode over tracing\n }\n },\n\n /** Tool start — record start time + args (span built atomically in `after`). */\n 'tool.execute.before': async (input: any, output: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n startRoot(st, sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n st.toolStarts.set(callID, {\n spanId: generateSpanId(),\n startNano: nowNanoString(),\n tool: String(input?.tool ?? 'tool'),\n args: output?.args,\n });\n } catch {\n /* ignore */\n }\n },\n\n /** Tool end — enqueue the completed TOOL span (parented to the turn root). */\n 'tool.execute.after': async (input: any, result: any) => {\n try {\n const sessionID = String(input?.sessionID ?? '');\n if (!sessionID) return;\n const st = stateFor(sessionID);\n const callID = String(input?.callID ?? input?.tool ?? '');\n const start = st.toolStarts.get(callID);\n if (!start) return;\n st.toolStarts.delete(callID);\n if (!st.traceId) return;\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'TOOL' } },\n { key: 'neatlogs.tool.name', value: { stringValue: start.tool } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n if (start.args !== undefined) {\n // The shipper bypasses the SDK attribute-processor, so emit the\n // already-namespaced keys the backend consumer reads directly\n // (neatlogs.tool.input / .output and the generic neatlogs.input.value),\n // not the raw input.value/output.value the processor would map.\n setIO(attrs, 'TOOL', safeStringify(start.args), undefined);\n push(attrs, attrStr('neatlogs.tool.input', safeStringify(start.args)));\n }\n if (result?.title) push(attrs, attrStr('neatlogs.tool.title', String(result.title)));\n const out = result?.output ?? result?.result;\n if (out !== undefined) {\n const o = typeof out === 'string' ? out : safeStringify(out);\n setIO(attrs, 'TOOL', undefined, o);\n push(attrs, attrStr('neatlogs.tool.output', o));\n }\n if (result?.metadata !== undefined) {\n push(attrs, attrStr('neatlogs.tool.metadata', safeStringify(result.metadata)));\n }\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: start.spanId,\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.tool.${start.tool}`,\n kind: 1,\n startTimeUnixNano: start.startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n } catch {\n /* ignore */\n }\n },\n };\n};\n\n// Convenience aliases so users can import under any common name.\nexport const neatlogsOpencodePlugin = NeatlogsOpencodePlugin;\nexport default NeatlogsOpencodePlugin;\n\n// ---------------------------------------------------------------------------\n// Event handling\n// ---------------------------------------------------------------------------\n\nfunction handleEvent(\n shipper: TraceShipper,\n sessions: Map<string, SessionState>,\n stateFor: (sessionID: string) => SessionState,\n startRoot: (st: SessionState, sessionID: string) => void,\n closeAndFlush: (st: SessionState, sessionID: string) => Promise<void>,\n event: any,\n): Promise<unknown> | undefined {\n const type = event?.type;\n const props = event?.properties ?? {};\n\n // Accumulate text + tool-call parts on an assistant message.\n if (type === 'message.part.updated' || type === 'message.part.completed') {\n const part = props.part ?? props;\n const messageID = part?.messageID ?? part?.message_id;\n const sessionID = part?.sessionID ?? props.sessionID;\n if (!messageID || !sessionID) return undefined;\n const st = stateFor(String(sessionID));\n if (part?.type === 'text' && typeof part?.text === 'string') {\n st.outputParts.set(String(messageID), part.text);\n } else if (part?.type === 'tool' && part?.tool) {\n const list = st.toolCalls.get(String(messageID)) ?? [];\n const callID = String(part.callID ?? part.tool);\n const input = part?.state?.input ?? {};\n const existing = list.find((t) => t.callID === callID);\n if (existing) existing.input = input;\n else list.push({ name: String(part.tool), input, callID });\n st.toolCalls.set(String(messageID), list);\n }\n return undefined;\n }\n\n // Assistant message completed → emit the LLM span, then flush this turn.\n if (type === 'message.updated' || type === 'message.completed') {\n const info = props.info ?? props.message ?? props;\n const sessionID = info?.sessionID ?? info?.session_id;\n if (!sessionID) return undefined;\n if (info?.role !== 'assistant') return undefined;\n const completed = info?.time?.completed ?? info?.completed;\n const id = String(info?.id ?? '');\n if (!completed || !id) return undefined;\n const st = stateFor(String(sessionID));\n if (st.processed.has(id)) return undefined;\n st.processed.add(id);\n startRoot(st, String(sessionID));\n emitLlmSpan(shipper, st, info, String(sessionID));\n // Incremental persistence: ship this turn's spans now (don't wait for idle).\n return shipper.flush().catch(() => undefined);\n }\n\n // Session finished → end root, send completion marker, final flush.\n if (type === 'session.idle' || type === 'session.deleted') {\n const sessionID = props.sessionID ?? props.info?.id;\n if (!sessionID) return undefined;\n const st = sessions.get(String(sessionID));\n if (!st) return undefined;\n st.toolStarts.clear();\n const p = closeAndFlush(st, String(sessionID));\n if (type === 'session.deleted') sessions.delete(String(sessionID));\n return p;\n }\n\n return undefined;\n}\n\nfunction emitLlmSpan(shipper: TraceShipper, st: SessionState, info: any, sessionID: string): void {\n if (!st.traceId) return;\n const model = info?.modelID ?? info?.model ?? '';\n const provider = info?.providerID ?? info?.provider ?? '';\n\n const attrs: OtlpKeyValue[] = [\n { key: 'neatlogs.span.kind', value: { stringValue: 'LLM' } },\n { key: 'neatlogs.conversation.id', value: { stringValue: sessionID } },\n ];\n push(attrs, attrStr('neatlogs.llm.model_name', model ? String(model) : undefined));\n push(attrs, attrStr('neatlogs.llm.provider', provider ? String(provider) : undefined));\n\n let inIdx = 0;\n if (st.systemPrompt) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'system'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.systemPrompt));\n inIdx++;\n }\n if (st.currentInput) {\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.role`, 'user'));\n push(attrs, attrStr(`neatlogs.llm.input_messages.${inIdx}.content`, st.currentInput));\n setIO(attrs, 'LLM', st.currentInput, undefined);\n }\n\n const outText = st.outputParts.get(String(info?.id)) || messageText(info) || '';\n const toolCalls = st.toolCalls.get(String(info?.id)) ?? [];\n\n if (outText) {\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', outText));\n setIO(attrs, 'LLM', undefined, outText);\n st.lastAssistantText = outText;\n }\n // Tool-deciding turns often carry no text — render the tool call(s) as output.\n if (toolCalls.length) {\n toolCalls.forEach((tc, j) => {\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.name`, tc.name));\n push(attrs, attrStr(`neatlogs.llm.tool_calls.${j}.arguments`, safeStringify(tc.input ?? {})));\n });\n if (!outText) {\n const rendered = toolCalls.map((tc) => `→ ${tc.name}(${safeStringify(tc.input ?? {})})`).join('\\n');\n push(attrs, attrStr('neatlogs.llm.output_messages.0.role', 'assistant'));\n push(attrs, attrStr('neatlogs.llm.output_messages.0.content', rendered));\n setIO(attrs, 'LLM', undefined, rendered);\n }\n }\n\n // Tokens: opencode message tokens { input, output, reasoning, cache:{read,write} }\n const tokens = info?.tokens;\n if (tokens) {\n push(attrs, attrInt('neatlogs.llm.token_count.prompt', tokens.input));\n push(attrs, attrInt('neatlogs.llm.token_count.completion', tokens.output));\n if (tokens.input != null && tokens.output != null) {\n push(attrs, attrInt('neatlogs.llm.token_count.total', tokens.input + tokens.output));\n }\n push(attrs, attrInt('neatlogs.llm.token_count.reasoning', tokens.reasoning));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_read', tokens.cache?.read));\n push(attrs, attrInt('neatlogs.llm.token_count.cache_write', tokens.cache?.write));\n }\n push(attrs, attrDouble('neatlogs.llm.cost_usd', info?.cost));\n push(attrs, attrStr('neatlogs.llm.finish_reason', info?.finish ? String(info.finish) : undefined));\n\n // Use opencode's real start time when available (else now).\n const createdMs = info?.time?.created;\n const startNano = typeof createdMs === 'number' ? msToNanoString(Math.floor(createdMs)) : nowNanoString();\n\n shipper.enqueue({\n traceId: st.traceId,\n spanId: generateSpanId(),\n parentSpanId: st.rootSpan?.spanId,\n name: `opencode.llm.${model || 'model'}`,\n kind: 1,\n startTimeUnixNano: startNano,\n endTimeUnixNano: nowNanoString(),\n attributes: attrs,\n status: { code: SpanStatusCode.OK },\n });\n\n // Reset accumulated parts for the next turn.\n if (info?.id) {\n st.outputParts.delete(String(info.id));\n st.toolCalls.delete(String(info.id));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction push(arr: OtlpKeyValue[], kv: OtlpKeyValue | undefined): void {\n if (kv) arr.push(kv);\n}\n\n/**\n * Set generic input/output on a span using the ALREADY-NAMESPACED keys the\n * backend consumer reads. The OTel-SDK wrappers rely on the attribute-processor\n * to map raw `input.value` → `neatlogs.{kind}.input`; this plugin ships spans\n * directly (no processor), so it must emit the namespaced keys itself:\n * neatlogs.input.value / neatlogs.output.value (generic)\n * neatlogs.{kind}.input / neatlogs.{kind}.output (kind-specific)\n * We also keep the raw input.value/output.value for any consumer that maps it.\n */\nfunction setIO(arr: OtlpKeyValue[], kind: string, input?: string, output?: string): void {\n const k = kind.toLowerCase();\n if (input !== undefined) {\n push(arr, attrStr('input.value', input));\n push(arr, attrStr('neatlogs.input.value', input));\n push(arr, attrStr(`neatlogs.${k}.input`, input));\n }\n if (output !== undefined) {\n push(arr, attrStr('output.value', output));\n push(arr, attrStr('neatlogs.output.value', output));\n push(arr, attrStr(`neatlogs.${k}.output`, output));\n }\n}\n\n/** Flatten an opencode message's parts/content to readable text. */\nfunction messageText(info: any): string {\n if (!info) return '';\n if (typeof info.text === 'string') return info.text;\n const parts = info.parts ?? info.content;\n if (typeof parts === 'string') return parts;\n if (!Array.isArray(parts)) return '';\n const out: string[] = [];\n for (const p of parts) {\n if (typeof p === 'string') out.push(p);\n else if (p && typeof p === 'object' && typeof p.text === 'string') out.push(p.text);\n }\n return out.join('');\n}\n\nfunction safeStringify(value: unknown): string {\n if (typeof value === 'string') return value;\n try {\n return JSON.stringify(value) ?? '';\n } catch {\n return String(value);\n }\n}\n"],"mappings":";AAcA,OAAO,cAAc;;;ACVd,IAAM,cAAc;;;ADa3B,IAAM,eAAe;AA0BrB,IAAM,kBAAuC;AAAA,EAC3C,QAAQ;AAAA,IACN,eAAe;AAAA,MACb,QAAQ;AAAA,QACN,OAAO;AAAA,UACL,QAAQ;AAAA,YACN,QAAQ;AAAA,cACN,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,OAAO;AAAA,0BACL,OAAO;AAAA,4BACL;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,4BACA;AAAA,0BACF;AAAA,wBACF;AAAA,sBACF;AAAA,sBACA,QAAQ;AAAA,wBACN,aAAa,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACrC,WAAW,EAAE,MAAM,QAAQ,IAAI,EAAE;AAAA,wBACjC,UAAU,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBACjC,aAAa,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACrC,YAAY,EAAE,MAAM,cAAc,IAAI,EAAE;AAAA,wBACxC,aAAa,EAAE,MAAM,gBAAgB,IAAI,EAAE;AAAA,wBAC3C,YAAY,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,sBACrC;AAAA,oBACF;AAAA,oBACA,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,MAAM,YAAY,IAAI,EAAE,EAAE,EAAE;AAAA,oBAChF,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,MAAM,YAAY,IAAI,EAAE,EAAE,EAAE;AAAA,oBAClF,UAAU;AAAA,sBACR,QAAQ,EAAE,KAAK,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,OAAO,EAAE,MAAM,YAAY,IAAI,EAAE,EAAE;AAAA,oBAC/E;AAAA,oBACA,sBAAsB;AAAA,sBACpB,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,SAAS,EAAE,MAAM,UAAU,IAAI,EAAE,EAAE;AAAA,oBAChF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,UAAU;AAAA,cACR,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,YAAY;AAAA,0BACV,MAAM;AAAA,0BACN,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN;AAAA,sBACF;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,QAAQ;AAAA,gBACN,IAAI;AAAA,kBACF,QAAQ;AAAA,oBACN,eAAe;AAAA,sBACb,QAAQ;AAAA,wBACN,UAAU,EAAE,MAAM,4CAA4C,IAAI,EAAE;AAAA,wBACpE,YAAY,EAAE,MAAM,YAAY,MAAM,cAAc,IAAI,EAAE;AAAA,sBAC5D;AAAA,oBACF;AAAA,oBACA,YAAY;AAAA,sBACV,QAAQ;AAAA,wBACN,OAAO,EAAE,MAAM,sDAAsD,IAAI,EAAE;AAAA,wBAC3E,OAAO,EAAE,MAAM,YAAY,MAAM,QAAQ,IAAI,EAAE;AAAA,sBACjD;AAAA,oBACF;AAAA,oBACA,MAAM;AAAA,sBACJ,QAAQ;AAAA,wBACN,SAAS,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBAChC,QAAQ,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBAC/B,YAAY,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBACpC,cAAc,EAAE,MAAM,SAAS,IAAI,EAAE;AAAA,wBACrC,MAAM,EAAE,MAAM,UAAU,IAAI,EAAE;AAAA,wBAC9B,MAAM,EAAE,MAAM,YAAY,IAAI,EAAE;AAAA,wBAChC,mBAAmB,EAAE,MAAM,WAAW,IAAI,EAAE;AAAA,wBAC5C,iBAAiB,EAAE,MAAM,WAAW,IAAI,EAAE;AAAA,wBAC1C,YAAY;AAAA,0BACV,MAAM;AAAA,0BACN,MAAM;AAAA,0BACN,IAAI;AAAA,wBACN;AAAA,wBACA,wBAAwB,EAAE,MAAM,UAAU,IAAI,GAAG;AAAA,wBACjD,QAAQ,EAAE,MAAM,UAAU,IAAI,GAAG;AAAA,sBACnC;AAAA,oBACF;AAAA,oBACA,QAAQ;AAAA,sBACN,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,IAAI,EAAE,GAAG,MAAM,EAAE,MAAM,cAAc,IAAI,EAAE,EAAE;AAAA,oBACpF;AAAA,oBACA,YAAY;AAAA,sBACV,QAAQ,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,mBAAmB,EAAE;AAAA,oBAC1E;AAAA,oBACA,UAAU;AAAA,sBACR,QAAQ;AAAA,wBACN,uBAAuB;AAAA,wBACvB,oBAAoB;AAAA,wBACpB,kBAAkB;AAAA,wBAClB,kBAAkB;AAAA,wBAClB,oBAAoB;AAAA,wBACpB,oBAAoB;AAAA,sBACtB;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,WAAW;AAAA,cACT,QAAQ;AAAA,gBACN,OAAO;AAAA,kBACL,QAAQ;AAAA,oBACN,IAAI;AAAA,sBACF,QAAQ;AAAA,wBACN,2BAA2B;AAAA,0BACzB,QAAQ;AAAA,4BACN,eAAe;AAAA,8BACb,MAAM;AAAA,8BACN,MAAM;AAAA,8BACN,IAAI;AAAA,4BACN;AAAA,0BACF;AAAA,wBACF;AAAA,sBACF;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,YAAY,SAAS,KAAK,SAAS,eAAe;AACxD,IAAM,4BAA4B,UAAU;AAAA,EAC1C;AACF;AAEO,IAAM,iBAAiB,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,EAAE;AAM1D,SAAS,YAAY,QAA4B;AAC/C,QAAM,MAAM,IAAI,WAAW,MAAM;AACjC,QAAM,SAAS,WAAW;AAC1B,MAAI,UAAU,OAAO,OAAO,oBAAoB,YAAY;AAC1D,WAAO,gBAAgB,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC5E,SAAO;AACT;AAEO,SAAS,kBAA8B;AAC5C,SAAO,YAAY,EAAE;AACvB;AAEO,SAAS,iBAA6B;AAC3C,SAAO,YAAY,CAAC;AACtB;AAQO,SAAS,gBAAwB;AACtC,UAAQ,OAAO,KAAK,IAAI,CAAC,IAAI,UAAY,SAAS;AACpD;AAEO,SAAS,eAAe,IAAoB;AACjD,UAAQ,OAAO,KAAK,MAAM,EAAE,CAAC,IAAI,UAAY,SAAS;AACxD;AAEO,SAAS,QAAQ,KAAa,OAAqD;AACxF,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,SAAO,EAAE,KAAK,OAAO,EAAE,aAAa,OAAO,KAAK,EAAE,EAAE;AACtD;AAEO,SAAS,QAAQ,KAAa,OAAqD;AACxF,MAAI,UAAU,UAAa,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AAC7E,SAAO,EAAE,KAAK,OAAO,EAAE,UAAU,OAAO,KAAK,MAAM,KAAK,CAAC,EAAE,EAAE;AAC/D;AAEO,SAAS,WAAW,KAAa,OAAqD;AAC3F,MAAI,UAAU,UAAa,UAAU,QAAQ,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AAC7E,SAAO,EAAE,KAAK,OAAO,EAAE,aAAa,MAAM,EAAE;AAC9C;AAUO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACR;AAAA,EACQ,QAAoB,CAAC;AAAA,EACrB,SAAS;AAAA;AAAA;AAAA,EAGT,WAAW,oBAAI,IAAmB;AAAA,EAE1C,YAAY,MAA2B;AACrC,SAAK,SAAS,KAAK;AACnB,SAAK,WAAW,KAAK,SAAS,SAAS,GAAG,IAAI,KAAK,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AAChF,SAAK,QAAQ,CAAC,CAAC,KAAK;AACpB,SAAK,aAAa,KAAK,cAAc;AACrC,SAAK,eAAe,KAAK,gBAAgB;AAAA,EAC3C;AAAA,EAEA,QAAQ,MAAsB;AAC5B,SAAK,MAAM,KAAK,IAAI;AAAA,EACtB;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAAuB;AACrB,UAAM,IAAI,KAAK,OAAO,EAAE,QAAQ,MAAM,KAAK,SAAS,OAAO,CAAC,CAAC;AAC7D,SAAK,SAAS,IAAI,CAAC;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAwB;AAC5B,WAAO,KAAK,SAAS,OAAO,GAAG;AAC7B,YAAM,QAAQ,WAAW,MAAM,KAAK,KAAK,QAAQ,CAAC;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAc,SAAwB;AACpC,QAAI,KAAK,MAAM,WAAW,EAAG;AAC7B,QAAI,CAAC,KAAK,QAAQ;AAChB,WAAK,QAAQ,CAAC;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,MAAM,OAAO,CAAC;AACjC,UAAM,UAAU,KAAK,cAAc,KAAK;AACxC,UAAM,MAAM,GAAG,KAAK,QAAQ;AAE5B,QAAI,KAAK,MAAO,SAAQ,IAAI,GAAG,KAAK,MAAM,aAAa,MAAM,MAAM,aAAa,GAAG,EAAE;AAErF,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW;AAC3D,UAAI;AACF,cAAM,OAAO,MAAM,MAAM,KAAK;AAAA,UAC5B,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,aAAa,KAAK;AAAA,UACpB;AAAA,UACA,MAAM;AAAA,QACR,CAAC;AAED,YAAI,KAAK,IAAI;AACX,cAAI,KAAK,MAAO,SAAQ,IAAI,GAAG,KAAK,MAAM,YAAY,MAAM,MAAM,QAAQ;AAC1E;AAAA,QACF;AACA,YAAI,KAAK,WAAW,KAAK;AACvB,kBAAQ,KAAK,GAAG,KAAK,MAAM,0CAAqC,MAAM,MAAM,QAAQ;AACpF;AAAA,QACF;AACA,YAAI,KAAK,SAAS,OAAO,KAAK,WAAW,KAAK;AAC5C,cAAI,KAAK,MAAO,SAAQ,KAAK,GAAG,KAAK,MAAM,SAAS,KAAK,MAAM,wBAAmB;AAClF;AAAA,QACF;AAAA,MAEF,SAAS,KAAK;AACZ,YAAI,KAAK,OAAO;AACd,kBAAQ;AAAA,YACN,GAAG,KAAK,MAAM,YAAY,OAAO,IAAI,KAAK,UAAU,KAAM,IAAc,OAAO;AAAA,UACjF;AAAA,QACF;AAAA,MACF;AACA,UAAI,UAAU,KAAK,YAAY;AAC7B,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC;AAAA,MAClE;AAAA,IACF;AACA,YAAQ,KAAK,GAAG,KAAK,MAAM,mBAAmB,MAAM,MAAM,gBAAgB,KAAK,UAAU,WAAW;AAAA,EACtG;AAAA,EAEQ,cAAc,OAA+B;AACnD,UAAM,aAAa,MAAM,IAAI,CAAC,UAAU;AAAA,MACtC,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,cAAc,KAAK,gBAAgB;AAAA,MACnC,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,mBAAmB,WAAW,KAAK,iBAAiB;AAAA,MACpD,iBAAiB,WAAW,KAAK,eAAe;AAAA,MAChD,YAAY,KAAK,WAAW,IAAI,CAAC,OAAO;AAAA,QACtC,KAAK,EAAE;AAAA,QACP,OACE,EAAE,MAAM,aAAa,SACjB,EAAE,UAAU,WAAW,EAAE,MAAM,QAAQ,EAAE,IACzC,EAAE;AAAA,MACV,EAAE;AAAA,MACF,QAAQ,KAAK,SAAS,EAAE,MAAM,KAAK,OAAO,MAAM,SAAS,KAAK,OAAO,QAAQ,IAAI;AAAA,IACnF,EAAE;AAEF,UAAM,qBAA6E;AAAA,MACjF,EAAE,KAAK,gBAAgB,OAAO,EAAE,aAAa,oBAAoB,EAAE;AAAA,MACnE,EAAE,KAAK,mBAAmB,OAAO,EAAE,aAAa,YAAY,EAAE;AAAA,IAChE;AACA,QAAI,KAAK,cAAc;AACrB,yBAAmB,KAAK;AAAA,QACtB,KAAK;AAAA,QACL,OAAO,EAAE,aAAa,KAAK,aAAa;AAAA,MAC1C,CAAC;AAAA,IACH;AAEA,UAAM,UAAU;AAAA,MACd,eAAe;AAAA,QACb;AAAA,UACE,UAAU,EAAE,YAAY,mBAAmB;AAAA,UAC3C,YAAY;AAAA,YACV;AAAA,cACE,OAAO,EAAE,MAAM,cAAc,SAAS,YAAY;AAAA,cAClD,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,0BAA0B,OAAO,OAAO;AACvD,QAAI,UAAU,KAAK,MAAO,SAAQ,KAAK,GAAG,KAAK,MAAM,kBAAkB,MAAM,EAAE;AAE/E,WAAO,0BAA0B,OAAO,0BAA0B,WAAW,OAAO,CAAC,EAAE,OAAO;AAAA,EAChG;AACF;AAGA,SAAS,WAAW,SAAmE;AACrF,QAAM,MAAM,OAAO,OAAO;AAC1B,QAAM,MAAM,OAAO,MAAM,WAAW;AACpC,QAAM,OAAO,OAAQ,OAAO,MAAO,WAAW;AAC9C,SAAO,EAAE,KAAK,MAAM,UAAU,KAAK;AACrC;;;AEhaO,IAAM,0BAA0B;AAGhC,IAAM,mCAAmC,OAAO;;;ACgFhD,IAAM,yBAAyB,OAAO,SAA4C;AACvF,QAAM,UAAU,QAAQ,IAAI,oBAAoB,IAAI,KAAK;AACzD,QAAM,YAAY,QAAQ,IAAI,qBAAqB,yBAAyB,KAAK;AACjF,QAAM,eAAe;AACrB,QAAM,QAAQ,OAAO,QAAQ,IAAI,kBAAkB,EAAE,EAAE,YAAY,MAAM;AAEzE,QAAM,UAAU,IAAI,aAAa,EAAE,QAAQ,UAAU,cAAc,MAAM,CAAC;AAC1E,QAAM,WAAW,oBAAI,IAA0B;AAE/C,WAAS,SAAS,WAAiC;AACjD,QAAI,IAAI,SAAS,IAAI,SAAS;AAC9B,QAAI,CAAC,GAAG;AACN,UAAI;AAAA,QACF,YAAY,oBAAI,IAAI;AAAA,QACpB,aAAa,oBAAI,IAAI;AAAA,QACrB,WAAW,oBAAI,IAAI;AAAA,QACnB,WAAW,oBAAI,IAAI;AAAA,QACnB,cAAc;AAAA,QACd,mBAAmB;AAAA,MACrB;AACA,eAAS,IAAI,WAAW,CAAC;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAKA,WAAS,UAAU,IAAkB,WAAyB;AAC5D,QAAI,GAAG,SAAU;AACjB,OAAG,UAAU,gBAAgB;AAC7B,OAAG,WAAW;AAAA,MACZ,QAAQ,eAAe;AAAA,MACvB,MAAM;AAAA,MACN,WAAW,cAAc;AAAA,MACzB,YAAY;AAAA,QACV,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,WAAW,EAAE;AAAA,QAChE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,WAAW,EAAE;AAAA,QACtE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,QACrE,EAAE,KAAK,uBAAuB,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAIA,iBAAe,cAAc,IAAkB,WAAkC;AAC/E,QAAI,GAAG,YAAY,GAAG,SAAS;AAC7B,YAAM,QAAQ,GAAG,SAAS,WAAW,MAAM;AAC3C,YAAM,OAAO,YAAY,GAAG,gBAAgB,QAAW,GAAG,qBAAqB,MAAS;AACxF,cAAQ,QAAQ;AAAA,QACd,SAAS,GAAG;AAAA,QACZ,QAAQ,GAAG,SAAS;AAAA,QACpB,MAAM,GAAG,SAAS;AAAA,QAClB,MAAM;AAAA,QACN,mBAAmB,GAAG,SAAS;AAAA,QAC/B,iBAAiB,cAAc;AAAA,QAC/B,YAAY;AAAA,QACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,MACpC,CAAC;AAGD,YAAM,IAAI,cAAc;AACxB,cAAQ,QAAQ;AAAA,QACd,SAAS,GAAG;AAAA,QACZ,QAAQ,eAAe;AAAA,QACvB,cAAc,GAAG,SAAS;AAAA,QAC1B,MAAM;AAAA,QACN,MAAM;AAAA,QACN,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,QACjB,YAAY;AAAA,UACV,EAAE,KAAK,2BAA2B,OAAO,EAAE,WAAW,KAAK,EAAE;AAAA,UAC7D,EAAE,KAAK,qBAAqB,OAAO,EAAE,WAAW,KAAK,EAAE;AAAA,UACvD,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,oBAAoB,EAAE;AAAA,QAC3E;AAAA,MACF,CAAC;AAAA,IACH;AAEA,OAAG,WAAW;AACd,OAAG,UAAU;AACb,OAAG,eAAe;AAClB,OAAG,oBAAoB;AACvB,OAAG,UAAU,MAAM;AACnB,OAAG,YAAY,MAAM;AACrB,OAAG,UAAU,MAAM;AACnB,UAAM,QAAQ,MAAM;AACpB,SAAK;AAAA,EACP;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQL,SAAS,YAAY;AACnB,UAAI;AACF,mBAAW,CAAC,WAAW,EAAE,KAAK,UAAU;AACtC,cAAI,GAAG,SAAU,OAAM,cAAc,IAAI,SAAS;AAAA,QACpD;AACA,cAAM,QAAQ,OAAO;AAAA,MACvB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,gBAAgB,OAAO,QAAa,WAAgB;AAClD,UAAI;AACF,cAAM,YAAY,OAAO,QAAQ,aAAa,QAAQ,aAAa,EAAE;AACrE,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,cAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,cAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MACG,OAAO,CAAC,MAAW,GAAG,SAAS,UAAU,OAAO,EAAE,SAAS,QAAQ,EACnE,IAAI,CAAC,MAAW,EAAE,IAAI,EACtB,KAAK,IAAI,IACZ;AACJ,YAAI,KAAM,IAAG,eAAe;AAC5B,kBAAU,IAAI,SAAS;AAAA,MACzB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,sCAAsC,OAAO,QAAa,WAAgB;AACxE,UAAI;AACF,cAAM,YAAY,OAAO,QAAQ,aAAa,EAAE;AAChD,cAAM,QAAQ,QAAQ,UAAU,QAAQ,SAAS;AACjD,cAAM,SAAS,MAAM,QAAQ,KAAK,IAAI,MAAM,IAAI,CAAC,MAAY,OAAO,MAAM,WAAW,IAAI,GAAG,QAAQ,EAAG,EAAE,KAAK,IAAI,IAAI,OAAO,SAAS,EAAE;AACxI,YAAI,aAAa,OAAQ,UAAS,SAAS,EAAE,eAAe;AAAA,MAC9D,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,OAAO,OAAO,EAAE,MAAM,MAAsB;AAC1C,UAAI;AACF,cAAM,YAAY,SAAS,UAAU,UAAU,WAAW,eAAe,KAAK;AAAA,MAChF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,uBAAuB,OAAO,OAAY,WAAgB;AACxD,UAAI;AACF,cAAM,YAAY,OAAO,OAAO,aAAa,EAAE;AAC/C,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,kBAAU,IAAI,SAAS;AACvB,cAAM,SAAS,OAAO,OAAO,UAAU,OAAO,QAAQ,EAAE;AACxD,WAAG,WAAW,IAAI,QAAQ;AAAA,UACxB,QAAQ,eAAe;AAAA,UACvB,WAAW,cAAc;AAAA,UACzB,MAAM,OAAO,OAAO,QAAQ,MAAM;AAAA,UAClC,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAAA;AAAA,IAGA,sBAAsB,OAAO,OAAY,WAAgB;AACvD,UAAI;AACF,cAAM,YAAY,OAAO,OAAO,aAAa,EAAE;AAC/C,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,SAAS,SAAS;AAC7B,cAAM,SAAS,OAAO,OAAO,UAAU,OAAO,QAAQ,EAAE;AACxD,cAAM,QAAQ,GAAG,WAAW,IAAI,MAAM;AACtC,YAAI,CAAC,MAAO;AACZ,WAAG,WAAW,OAAO,MAAM;AAC3B,YAAI,CAAC,GAAG,QAAS;AAEjB,cAAM,QAAwB;AAAA,UAC5B,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,OAAO,EAAE;AAAA,UAC5D,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,MAAM,KAAK,EAAE;AAAA,UAChE,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,QACvE;AACA,YAAI,MAAM,SAAS,QAAW;AAK5B,gBAAM,OAAO,QAAQ,cAAc,MAAM,IAAI,GAAG,MAAS;AACzD,eAAK,OAAO,QAAQ,uBAAuB,cAAc,MAAM,IAAI,CAAC,CAAC;AAAA,QACvE;AACA,YAAI,QAAQ,MAAO,MAAK,OAAO,QAAQ,uBAAuB,OAAO,OAAO,KAAK,CAAC,CAAC;AACnF,cAAM,MAAM,QAAQ,UAAU,QAAQ;AACtC,YAAI,QAAQ,QAAW;AACrB,gBAAM,IAAI,OAAO,QAAQ,WAAW,MAAM,cAAc,GAAG;AAC3D,gBAAM,OAAO,QAAQ,QAAW,CAAC;AACjC,eAAK,OAAO,QAAQ,wBAAwB,CAAC,CAAC;AAAA,QAChD;AACA,YAAI,QAAQ,aAAa,QAAW;AAClC,eAAK,OAAO,QAAQ,0BAA0B,cAAc,OAAO,QAAQ,CAAC,CAAC;AAAA,QAC/E;AAEA,gBAAQ,QAAQ;AAAA,UACd,SAAS,GAAG;AAAA,UACZ,QAAQ,MAAM;AAAA,UACd,cAAc,GAAG,UAAU;AAAA,UAC3B,MAAM,iBAAiB,MAAM,IAAI;AAAA,UACjC,MAAM;AAAA,UACN,mBAAmB,MAAM;AAAA,UACzB,iBAAiB,cAAc;AAAA,UAC/B,YAAY;AAAA,UACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,QACpC,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,yBAAyB;AACtC,IAAO,0BAAQ;AAMf,SAAS,YACP,SACA,UACA,UACA,WACA,eACA,OAC8B;AAC9B,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,OAAO,cAAc,CAAC;AAGpC,MAAI,SAAS,0BAA0B,SAAS,0BAA0B;AACxE,UAAM,OAAO,MAAM,QAAQ;AAC3B,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,QAAI,CAAC,aAAa,CAAC,UAAW,QAAO;AACrC,UAAM,KAAK,SAAS,OAAO,SAAS,CAAC;AACrC,QAAI,MAAM,SAAS,UAAU,OAAO,MAAM,SAAS,UAAU;AAC3D,SAAG,YAAY,IAAI,OAAO,SAAS,GAAG,KAAK,IAAI;AAAA,IACjD,WAAW,MAAM,SAAS,UAAU,MAAM,MAAM;AAC9C,YAAM,OAAO,GAAG,UAAU,IAAI,OAAO,SAAS,CAAC,KAAK,CAAC;AACrD,YAAM,SAAS,OAAO,KAAK,UAAU,KAAK,IAAI;AAC9C,YAAM,QAAQ,MAAM,OAAO,SAAS,CAAC;AACrC,YAAM,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AACrD,UAAI,SAAU,UAAS,QAAQ;AAAA,UAC1B,MAAK,KAAK,EAAE,MAAM,OAAO,KAAK,IAAI,GAAG,OAAO,OAAO,CAAC;AACzD,SAAG,UAAU,IAAI,OAAO,SAAS,GAAG,IAAI;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,qBAAqB,SAAS,qBAAqB;AAC9D,UAAM,OAAO,MAAM,QAAQ,MAAM,WAAW;AAC5C,UAAM,YAAY,MAAM,aAAa,MAAM;AAC3C,QAAI,CAAC,UAAW,QAAO;AACvB,QAAI,MAAM,SAAS,YAAa,QAAO;AACvC,UAAM,YAAY,MAAM,MAAM,aAAa,MAAM;AACjD,UAAM,KAAK,OAAO,MAAM,MAAM,EAAE;AAChC,QAAI,CAAC,aAAa,CAAC,GAAI,QAAO;AAC9B,UAAM,KAAK,SAAS,OAAO,SAAS,CAAC;AACrC,QAAI,GAAG,UAAU,IAAI,EAAE,EAAG,QAAO;AACjC,OAAG,UAAU,IAAI,EAAE;AACnB,cAAU,IAAI,OAAO,SAAS,CAAC;AAC/B,gBAAY,SAAS,IAAI,MAAM,OAAO,SAAS,CAAC;AAEhD,WAAO,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC9C;AAGA,MAAI,SAAS,kBAAkB,SAAS,mBAAmB;AACzD,UAAM,YAAY,MAAM,aAAa,MAAM,MAAM;AACjD,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,KAAK,SAAS,IAAI,OAAO,SAAS,CAAC;AACzC,QAAI,CAAC,GAAI,QAAO;AAChB,OAAG,WAAW,MAAM;AACpB,UAAM,IAAI,cAAc,IAAI,OAAO,SAAS,CAAC;AAC7C,QAAI,SAAS,kBAAmB,UAAS,OAAO,OAAO,SAAS,CAAC;AACjE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,YAAY,SAAuB,IAAkB,MAAW,WAAyB;AAChG,MAAI,CAAC,GAAG,QAAS;AACjB,QAAM,QAAQ,MAAM,WAAW,MAAM,SAAS;AAC9C,QAAM,WAAW,MAAM,cAAc,MAAM,YAAY;AAEvD,QAAM,QAAwB;AAAA,IAC5B,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,MAAM,EAAE;AAAA,IAC3D,EAAE,KAAK,4BAA4B,OAAO,EAAE,aAAa,UAAU,EAAE;AAAA,EACvE;AACA,OAAK,OAAO,QAAQ,2BAA2B,QAAQ,OAAO,KAAK,IAAI,MAAS,CAAC;AACjF,OAAK,OAAO,QAAQ,yBAAyB,WAAW,OAAO,QAAQ,IAAI,MAAS,CAAC;AAErF,MAAI,QAAQ;AACZ,MAAI,GAAG,cAAc;AACnB,SAAK,OAAO,QAAQ,+BAA+B,KAAK,SAAS,QAAQ,CAAC;AAC1E,SAAK,OAAO,QAAQ,+BAA+B,KAAK,YAAY,GAAG,YAAY,CAAC;AACpF;AAAA,EACF;AACA,MAAI,GAAG,cAAc;AACnB,SAAK,OAAO,QAAQ,+BAA+B,KAAK,SAAS,MAAM,CAAC;AACxE,SAAK,OAAO,QAAQ,+BAA+B,KAAK,YAAY,GAAG,YAAY,CAAC;AACpF,UAAM,OAAO,OAAO,GAAG,cAAc,MAAS;AAAA,EAChD;AAEA,QAAM,UAAU,GAAG,YAAY,IAAI,OAAO,MAAM,EAAE,CAAC,KAAK,YAAY,IAAI,KAAK;AAC7E,QAAM,YAAY,GAAG,UAAU,IAAI,OAAO,MAAM,EAAE,CAAC,KAAK,CAAC;AAEzD,MAAI,SAAS;AACX,SAAK,OAAO,QAAQ,uCAAuC,WAAW,CAAC;AACvE,SAAK,OAAO,QAAQ,0CAA0C,OAAO,CAAC;AACtE,UAAM,OAAO,OAAO,QAAW,OAAO;AACtC,OAAG,oBAAoB;AAAA,EACzB;AAEA,MAAI,UAAU,QAAQ;AACpB,cAAU,QAAQ,CAAC,IAAI,MAAM;AAC3B,WAAK,OAAO,QAAQ,2BAA2B,CAAC,SAAS,GAAG,IAAI,CAAC;AACjE,WAAK,OAAO,QAAQ,2BAA2B,CAAC,cAAc,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAAA,IAC9F,CAAC;AACD,QAAI,CAAC,SAAS;AACZ,YAAM,WAAW,UAAU,IAAI,CAAC,OAAO,UAAK,GAAG,IAAI,IAAI,cAAc,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,IAAI;AAClG,WAAK,OAAO,QAAQ,uCAAuC,WAAW,CAAC;AACvE,WAAK,OAAO,QAAQ,0CAA0C,QAAQ,CAAC;AACvE,YAAM,OAAO,OAAO,QAAW,QAAQ;AAAA,IACzC;AAAA,EACF;AAGA,QAAM,SAAS,MAAM;AACrB,MAAI,QAAQ;AACV,SAAK,OAAO,QAAQ,mCAAmC,OAAO,KAAK,CAAC;AACpE,SAAK,OAAO,QAAQ,uCAAuC,OAAO,MAAM,CAAC;AACzE,QAAI,OAAO,SAAS,QAAQ,OAAO,UAAU,MAAM;AACjD,WAAK,OAAO,QAAQ,kCAAkC,OAAO,QAAQ,OAAO,MAAM,CAAC;AAAA,IACrF;AACA,SAAK,OAAO,QAAQ,sCAAsC,OAAO,SAAS,CAAC;AAC3E,SAAK,OAAO,QAAQ,uCAAuC,OAAO,OAAO,IAAI,CAAC;AAC9E,SAAK,OAAO,QAAQ,wCAAwC,OAAO,OAAO,KAAK,CAAC;AAAA,EAClF;AACA,OAAK,OAAO,WAAW,yBAAyB,MAAM,IAAI,CAAC;AAC3D,OAAK,OAAO,QAAQ,8BAA8B,MAAM,SAAS,OAAO,KAAK,MAAM,IAAI,MAAS,CAAC;AAGjG,QAAM,YAAY,MAAM,MAAM;AAC9B,QAAM,YAAY,OAAO,cAAc,WAAW,eAAe,KAAK,MAAM,SAAS,CAAC,IAAI,cAAc;AAExG,UAAQ,QAAQ;AAAA,IACd,SAAS,GAAG;AAAA,IACZ,QAAQ,eAAe;AAAA,IACvB,cAAc,GAAG,UAAU;AAAA,IAC3B,MAAM,gBAAgB,SAAS,OAAO;AAAA,IACtC,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,iBAAiB,cAAc;AAAA,IAC/B,YAAY;AAAA,IACZ,QAAQ,EAAE,MAAM,eAAe,GAAG;AAAA,EACpC,CAAC;AAGD,MAAI,MAAM,IAAI;AACZ,OAAG,YAAY,OAAO,OAAO,KAAK,EAAE,CAAC;AACrC,OAAG,UAAU,OAAO,OAAO,KAAK,EAAE,CAAC;AAAA,EACrC;AACF;AAMA,SAAS,KAAK,KAAqB,IAAoC;AACrE,MAAI,GAAI,KAAI,KAAK,EAAE;AACrB;AAWA,SAAS,MAAM,KAAqB,MAAc,OAAgB,QAAuB;AACvF,QAAM,IAAI,KAAK,YAAY;AAC3B,MAAI,UAAU,QAAW;AACvB,SAAK,KAAK,QAAQ,eAAe,KAAK,CAAC;AACvC,SAAK,KAAK,QAAQ,wBAAwB,KAAK,CAAC;AAChD,SAAK,KAAK,QAAQ,YAAY,CAAC,UAAU,KAAK,CAAC;AAAA,EACjD;AACA,MAAI,WAAW,QAAW;AACxB,SAAK,KAAK,QAAQ,gBAAgB,MAAM,CAAC;AACzC,SAAK,KAAK,QAAQ,yBAAyB,MAAM,CAAC;AAClD,SAAK,KAAK,QAAQ,YAAY,CAAC,WAAW,MAAM,CAAC;AAAA,EACnD;AACF;AAGA,SAAS,YAAY,MAAmB;AACtC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,OAAO,KAAK,SAAS,SAAU,QAAO,KAAK;AAC/C,QAAM,QAAQ,KAAK,SAAS,KAAK;AACjC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,QAAM,MAAgB,CAAC;AACvB,aAAW,KAAK,OAAO;AACrB,QAAI,OAAO,MAAM,SAAU,KAAI,KAAK,CAAC;AAAA,aAC5B,KAAK,OAAO,MAAM,YAAY,OAAO,EAAE,SAAS,SAAU,KAAI,KAAK,EAAE,IAAI;AAAA,EACpF;AACA,SAAO,IAAI,KAAK,EAAE;AACpB;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK,KAAK;AAAA,EAClC,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;","names":[]}