@narumitw/pi-langfuse 0.50.5 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.ts.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/config.ts", "../src/sanitizer.ts", "../src/tracing.ts", "../src/langfuse.ts"],
4
- "sourcesContent": ["import { randomUUID } from \"node:crypto\";\nimport { chmod, mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\n\nconst CONFIG_FILE_NAME = \"pi-langfuse.json\";\nexport const DEFAULT_BASE_URL = \"https://us.cloud.langfuse.com\";\n\nexport interface LangfuseConfig {\n\tpublicKey: string;\n\tsecretKey: string;\n\tbaseUrl: string;\n\tenvironment?: string;\n\trelease?: string;\n\tuserId?: string;\n\tcaptureContent: boolean;\n}\n\nexport type LangfuseConfigPatch = Partial<LangfuseConfig>;\n\nexport type LangfuseConfigResult =\n\t| { ok: true; config: LangfuseConfig; path: string; warnings: string[] }\n\t| { ok: false; path: string; warnings: string[]; reason: string };\n\nexport function langfuseConfigPath(): string {\n\treturn join(getAgentDir(), CONFIG_FILE_NAME);\n}\n\nconst configSaveQueues = new Map<string, Promise<void>>();\n\nexport async function waitForLangfuseConfigWrites(path = langfuseConfigPath()): Promise<void> {\n\tawait configSaveQueues.get(path);\n}\n\nexport function writeLangfuseConfig(\n\tpatch: LangfuseConfigPatch,\n\tpath = langfuseConfigPath(),\n): Promise<LangfuseConfig> {\n\tconst previous = configSaveQueues.get(path) ?? Promise.resolve();\n\tconst operation = previous.then(() => writeLangfuseConfigNow(patch, path));\n\tconst tail = operation.then(\n\t\t() => undefined,\n\t\t() => undefined,\n\t);\n\tconfigSaveQueues.set(path, tail);\n\tvoid tail.then(() => {\n\t\tif (configSaveQueues.get(path) === tail) configSaveQueues.delete(path);\n\t});\n\treturn operation;\n}\n\nasync function writeLangfuseConfigNow(\n\tpatch: LangfuseConfigPatch,\n\tpath: string,\n): Promise<LangfuseConfig> {\n\tconst currentDocument = await readLangfuseDocumentForUpdate(path);\n\tconst normalized = normalizeLangfuseConfig({ ...currentDocument, ...patch });\n\tif (!normalized.ok) throw new Error(normalized.reason);\n\tconst {\n\t\tpublicKey: _publicKey,\n\t\tsecretKey: _secretKey,\n\t\tbaseUrl: _baseUrl,\n\t\tenvironment: _environment,\n\t\trelease: _release,\n\t\tuserId: _userId,\n\t\tcaptureContent: _captureContent,\n\t\t...unknownFields\n\t} = currentDocument;\n\tconst nextDocument = { ...unknownFields, ...normalized.config };\n\n\tawait mkdir(dirname(path), { recursive: true, mode: 0o700 });\n\tconst tempPath = `${path}.${process.pid}.${randomUUID()}.tmp`;\n\ttry {\n\t\tawait writeFile(tempPath, `${JSON.stringify(nextDocument, null, 2)}\\n`, {\n\t\t\tencoding: \"utf8\",\n\t\t\tmode: 0o600,\n\t\t});\n\t\tawait chmod(tempPath, 0o600);\n\t\tawait rename(tempPath, path);\n\t\treturn normalized.config;\n\t} catch (error) {\n\t\tawait rm(tempPath, { force: true }).catch(() => undefined);\n\t\tthrow error;\n\t}\n}\n\nasync function readLangfuseDocumentForUpdate(path: string): Promise<Record<string, unknown>> {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(await readFile(path, \"utf8\")) as unknown;\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return {};\n\t\tthrow new Error(\n\t\t\t`Cannot update ${CONFIG_FILE_NAME} because the existing file is malformed or unreadable; repair it first.`,\n\t\t);\n\t}\n\tconst normalized = normalizeLangfuseConfig(parsed);\n\tif (!normalized.ok) {\n\t\tthrow new Error(\n\t\t\t`Cannot update ${CONFIG_FILE_NAME} because the existing file has invalid recognized fields; repair it first.`,\n\t\t);\n\t}\n\treturn { ...(parsed as Record<string, unknown>) };\n}\n\nexport async function loadLangfuseConfig(\n\tpath = langfuseConfigPath(),\n): Promise<LangfuseConfigResult> {\n\tawait configSaveQueues.get(path);\n\tconst warnings: string[] = [];\n\tconst permissionFailure = await ensurePrivatePermissions(path, warnings);\n\tif (permissionFailure) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tpath,\n\t\t\twarnings,\n\t\t\treason: `Refusing to load credentials: ${permissionFailure}`,\n\t\t};\n\t}\n\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(path, \"utf8\");\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\treturn { ok: false, path, warnings, reason: `Configuration file not found: ${path}` };\n\t\t}\n\t\treturn {\n\t\t\tok: false,\n\t\t\tpath,\n\t\t\twarnings,\n\t\t\treason: `Failed to read ${path}: ${formatError(error)}`,\n\t\t};\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text) as unknown;\n\t} catch {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tpath,\n\t\t\twarnings,\n\t\t\treason: `Failed to parse ${path} as JSON; repair the file before retrying.`,\n\t\t};\n\t}\n\n\tconst normalized = normalizeLangfuseConfig(parsed);\n\tif (!normalized.ok) return { ok: false, path, warnings, reason: normalized.reason };\n\treturn { ok: true, config: normalized.config, path, warnings };\n}\n\nexport function normalizeLangfuseConfig(\n\tvalue: unknown,\n): { ok: true; config: LangfuseConfig } | { ok: false; reason: string } {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\treturn { ok: false, reason: \"pi-langfuse.json must contain a JSON object.\" };\n\t}\n\tconst input = value as Record<string, unknown>;\n\tconst publicKey = normalizeString(input.publicKey);\n\tconst secretKey = normalizeString(input.secretKey);\n\tif (!publicKey) {\n\t\treturn { ok: false, reason: \"pi-langfuse.json requires a literal publicKey string.\" };\n\t}\n\tif (!secretKey) {\n\t\treturn { ok: false, reason: \"pi-langfuse.json requires a literal secretKey string.\" };\n\t}\n\tif (isInterpolation(publicKey)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason:\n\t\t\t\t\"pi-langfuse.json publicKey must be literal; environment and command interpolation are not supported.\",\n\t\t};\n\t}\n\tif (isInterpolation(secretKey)) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason:\n\t\t\t\t\"pi-langfuse.json secretKey must be literal; environment and command interpolation are not supported.\",\n\t\t};\n\t}\n\n\tconst rawBaseUrl =\n\t\tinput.baseUrl === undefined ? DEFAULT_BASE_URL : normalizeString(input.baseUrl);\n\tif (!rawBaseUrl) {\n\t\treturn { ok: false, reason: \"pi-langfuse.json baseUrl must be a non-empty string.\" };\n\t}\n\tconst baseUrl = normalizeBaseUrl(rawBaseUrl);\n\tif (!baseUrl) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason:\n\t\t\t\t\"pi-langfuse.json baseUrl must use HTTP or HTTPS without credentials, a query, or a fragment.\",\n\t\t};\n\t}\n\n\tif (input.captureContent !== undefined && typeof input.captureContent !== \"boolean\") {\n\t\treturn { ok: false, reason: \"pi-langfuse.json captureContent must be a boolean.\" };\n\t}\n\tconst environment = optionalString(input.environment, \"environment\");\n\tif (!environment.ok) return environment;\n\tif (\n\t\tenvironment.value &&\n\t\t(environment.value.length > 40 || !/^(?!langfuse)[a-z0-9_-]+$/u.test(environment.value))\n\t) {\n\t\treturn {\n\t\t\tok: false,\n\t\t\treason:\n\t\t\t\t\"pi-langfuse.json environment must be at most 40 lowercase letters, numbers, hyphens, or underscores and must not start with langfuse.\",\n\t\t};\n\t}\n\tconst release = optionalString(input.release, \"release\");\n\tif (!release.ok) return release;\n\tconst userId = optionalString(input.userId, \"userId\");\n\tif (!userId.ok) return userId;\n\tif (userId.value && userId.value.length > 200) {\n\t\treturn { ok: false, reason: \"pi-langfuse.json userId must be at most 200 characters.\" };\n\t}\n\n\treturn {\n\t\tok: true,\n\t\tconfig: {\n\t\t\tpublicKey,\n\t\t\tsecretKey,\n\t\t\tbaseUrl,\n\t\t\t...(environment.value ? { environment: environment.value } : {}),\n\t\t\t...(release.value ? { release: release.value } : {}),\n\t\t\t...(userId.value ? { userId: userId.value } : {}),\n\t\t\tcaptureContent: input.captureContent ?? true,\n\t\t},\n\t};\n}\n\nasync function ensurePrivatePermissions(\n\tpath: string,\n\twarnings: string[],\n): Promise<string | undefined> {\n\ttry {\n\t\tconst file = await stat(path);\n\t\tif ((file.mode & 0o777) !== 0o600) {\n\t\t\tawait chmod(path, 0o600);\n\t\t\tconst repaired = await stat(path);\n\t\t\tif ((repaired.mode & 0o777) !== 0o600) {\n\t\t\t\tthrow new Error(`permissions remained ${(repaired.mode & 0o777).toString(8)}`);\n\t\t\t}\n\t\t\twarnings.push(`Restricted ${path} permissions to 0600.`);\n\t\t}\n\t} catch (error) {\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") return undefined;\n\t\tconst failure = `Failed to enforce 0600 permissions for ${path}: ${formatError(error)}`;\n\t\twarnings.push(failure);\n\t\treturn failure;\n\t}\n\treturn undefined;\n}\n\nfunction normalizeBaseUrl(value: string): string | undefined {\n\ttry {\n\t\tconst url = new URL(value);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") return undefined;\n\t\tif (url.username || url.password || url.search || url.hash) return undefined;\n\t\treturn url.toString().replace(/\\/+$/, \"\");\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction optionalString(\n\tvalue: unknown,\n\tname: string,\n): { ok: true; value?: string } | { ok: false; reason: string } {\n\tif (value === undefined) return { ok: true };\n\tconst normalized = normalizeString(value);\n\treturn normalized\n\t\t? { ok: true, value: normalized }\n\t\t: { ok: false, reason: `pi-langfuse.json ${name} must be a non-empty string.` };\n}\n\nfunction normalizeString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction isInterpolation(value: string): boolean {\n\treturn value.startsWith(\"$\") || value.startsWith(\"!\");\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n\nfunction formatError(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n", "export const MAX_CAPTURE_BYTES = 64 * 1024;\nconst MAX_STRING_LENGTH = 50_000;\nconst MAX_COLLECTION_LENGTH = 200;\nconst MAX_DEPTH = 12;\nconst TRUNCATED = \"[truncated: content budget exceeded]\";\nconst BASE64_DATA_URI = /data:[^,\\s\"'`]*;base64,[^\\s\"'`]*/gi;\nconst BASE64_DATA_URI_OMITTED = \"[base64 data URI omitted]\";\nconst OPAQUE_SIGNATURE_KEYS = new Set([\"thinkingSignature\", \"textSignature\", \"thoughtSignature\"]);\n\nexport function sanitizeTraceValue(value: unknown): unknown {\n\tconst budget = { remaining: MAX_CAPTURE_BYTES };\n\tconst sanitized = sanitize(value, new WeakSet<object>(), 0, budget);\n\treturn serializedBytes(sanitized) <= MAX_CAPTURE_BYTES ? sanitized : TRUNCATED;\n}\n\nfunction sanitize(\n\tvalue: unknown,\n\tactive: WeakSet<object>,\n\tdepth: number,\n\tbudget: { remaining: number },\n): unknown {\n\tif (budget.remaining <= byteLength(TRUNCATED)) return TRUNCATED;\n\tif (value === null || typeof value === \"number\" || typeof value === \"boolean\") {\n\t\treturn consume(value, budget);\n\t}\n\tif (typeof value === \"string\") {\n\t\tconst bounded = truncateString(value, Math.min(MAX_STRING_LENGTH, budget.remaining));\n\t\tconst redacted = bounded.replace(BASE64_DATA_URI, BASE64_DATA_URI_OMITTED);\n\t\treturn consume(redacted, budget);\n\t}\n\tif (typeof value === \"bigint\") return consume(value.toString(), budget);\n\tif (typeof value === \"undefined\" || typeof value === \"function\" || typeof value === \"symbol\") {\n\t\treturn undefined;\n\t}\n\tif (value instanceof Date) {\n\t\treturn consume(Number.isNaN(value.getTime()) ? \"[invalid date]\" : value.toISOString(), budget);\n\t}\n\tif (value instanceof Error) {\n\t\treturn sanitize({ name: value.name, message: value.message }, active, depth, budget);\n\t}\n\tif (depth >= MAX_DEPTH) return consume(\"[maximum depth reached]\", budget);\n\tif (active.has(value)) return consume(\"[circular]\", budget);\n\tactive.add(value);\n\n\tlet result: unknown;\n\tif (Array.isArray(value)) {\n\t\tconst items: unknown[] = [];\n\t\tfor (const item of value.slice(0, MAX_COLLECTION_LENGTH)) {\n\t\t\tif (budget.remaining <= byteLength(TRUNCATED)) break;\n\t\t\titems.push(sanitize(item, active, depth + 1, budget));\n\t\t}\n\t\tif (items.length < value.length) items.push(`[${value.length - items.length} items omitted]`);\n\t\tresult = items;\n\t} else {\n\t\tconst record = value as Record<string, unknown>;\n\t\tconst output: Record<string, unknown> = {};\n\t\tconst objectType = readProperty(record, \"type\").value;\n\t\tconst redactData = objectType === \"image\" || objectType === \"base64\";\n\t\tlet visited = 0;\n\t\tlet processed = 0;\n\t\tlet omitted = false;\n\t\ttry {\n\t\t\tfor (const key in record) {\n\t\t\t\tif (visited >= MAX_COLLECTION_LENGTH || budget.remaining <= byteLength(TRUNCATED)) {\n\t\t\t\t\tomitted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tvisited += 1;\n\t\t\t\tif (!Object.hasOwn(record, key) || OPAQUE_SIGNATURE_KEYS.has(key)) continue;\n\t\t\t\tconst keyBudget = Math.min(MAX_STRING_LENGTH, Math.max(0, budget.remaining - 4));\n\t\t\t\tif (key.length > keyBudget) {\n\t\t\t\t\tomitted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tconst keyBytes = byteLength(key);\n\t\t\t\tif (keyBytes > keyBudget) {\n\t\t\t\t\tomitted = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbudget.remaining -= keyBytes + 4;\n\t\t\t\tconst property = readProperty(record, key);\n\t\t\t\tif (redactData && key === \"data\") {\n\t\t\t\t\toutput[key] = consume(\"[base64 omitted]\", budget);\n\t\t\t\t} else if (!property.ok) output[key] = consume(\"[unreadable property]\", budget);\n\t\t\t\telse output[key] = sanitize(property.value, active, depth + 1, budget);\n\t\t\t\tprocessed += 1;\n\t\t\t}\n\t\t} catch {\n\t\t\tif (processed === 0) {\n\t\t\t\tactive.delete(value);\n\t\t\t\treturn consume(\"[unreadable object]\", budget);\n\t\t\t}\n\t\t\tomitted = true;\n\t\t}\n\t\tif (omitted) output.$truncated = \"additional object entries omitted\";\n\t\tresult = output;\n\t}\n\tactive.delete(value);\n\treturn result;\n}\n\nfunction readProperty(\n\trecord: Record<string, unknown>,\n\tkey: string,\n): { ok: true; value: unknown } | { ok: false; value?: undefined } {\n\ttry {\n\t\treturn { ok: true, value: record[key] };\n\t} catch {\n\t\treturn { ok: false };\n\t}\n}\n\nfunction consume<T>(value: T, budget: { remaining: number }): T | string {\n\tconst size = serializedBytes(value);\n\tif (size > budget.remaining) {\n\t\tbudget.remaining -= byteLength(TRUNCATED);\n\t\treturn TRUNCATED;\n\t}\n\tbudget.remaining -= size;\n\treturn value;\n}\n\nfunction truncateString(value: string, maxBytes: number): string {\n\tconst boundedPrefix = value.slice(0, maxBytes);\n\tif (boundedPrefix.length === value.length && byteLength(boundedPrefix) <= maxBytes) {\n\t\treturn boundedPrefix;\n\t}\n\tconst suffix = \"\u2026 [truncated]\";\n\tconst target = Math.max(0, maxBytes - byteLength(suffix) - 2);\n\tlet bytes = 0;\n\tlet output = \"\";\n\tfor (const character of boundedPrefix) {\n\t\tconst size = byteLength(character);\n\t\tif (bytes + size > target) break;\n\t\toutput += character;\n\t\tbytes += size;\n\t}\n\treturn `${output}${suffix}`;\n}\n\nfunction serializedBytes(value: unknown): number {\n\treturn byteLength(JSON.stringify(value) ?? \"null\");\n}\n\nfunction byteLength(value: string): number {\n\treturn Buffer.byteLength(value, \"utf8\");\n}\n", "import { sanitizeTraceValue } from \"./sanitizer.js\";\n\nexport { MAX_CAPTURE_BYTES, sanitizeTraceValue } from \"./sanitizer.js\";\n\nexport const TRACE_SCHEMA_VERSION = \"2\";\nconst MAX_HEADER_VALUE_LENGTH = 1_024;\nconst CONTENT_DISABLED = \"[content capture disabled]\";\nconst ALLOWED_RESPONSE_HEADERS = new Set([\n\t\"anthropic-ratelimit-requests-limit\",\n\t\"anthropic-ratelimit-requests-remaining\",\n\t\"anthropic-ratelimit-requests-reset\",\n\t\"anthropic-ratelimit-tokens-limit\",\n\t\"anthropic-ratelimit-tokens-remaining\",\n\t\"anthropic-ratelimit-tokens-reset\",\n\t\"cf-ray\",\n\t\"openai-request-id\",\n\t\"request-id\",\n\t\"retry-after\",\n\t\"x-amzn-requestid\",\n\t\"x-request-id\",\n\t\"x-ratelimit-limit-requests\",\n\t\"x-ratelimit-limit-tokens\",\n\t\"x-ratelimit-remaining-requests\",\n\t\"x-ratelimit-remaining-tokens\",\n\t\"x-ratelimit-reset-requests\",\n\t\"x-ratelimit-reset-tokens\",\n]);\n\nexport interface ObservationAttributes {\n\tinput?: unknown;\n\toutput?: unknown;\n\tmetadata?: Record<string, unknown>;\n\tlevel?: \"DEBUG\" | \"DEFAULT\" | \"WARNING\" | \"ERROR\";\n\tstatusMessage?: string;\n\tcompletionStartTime?: Date;\n\tmodel?: string;\n\tmodelParameters?: Record<string, string | number>;\n\tusageDetails?: Record<string, number>;\n\tcostDetails?: Record<string, number>;\n\tversion?: string;\n\tname?: string;\n\tsessionId?: string;\n\tuserId?: string;\n\ttags?: string[];\n}\n\nexport interface Observation {\n\tupdate(attributes: ObservationAttributes): Observation;\n\tupdateTrace?(attributes: ObservationAttributes): Observation;\n\tend(endTime?: number): Observation;\n}\n\nexport type ObservationType = \"agent\" | \"generation\" | \"span\" | \"tool\";\n\nexport interface TraceBackend {\n\tstart(\n\t\tname: string,\n\t\tattributes: ObservationAttributes,\n\t\toptions: { asType: ObservationType; parent?: Observation },\n\t): Observation;\n\tforceFlush(): Promise<void>;\n\tshutdown(): Promise<void>;\n}\n\ninterface RecorderContext {\n\tsessionId: string;\n\tuserId?: string;\n\tcwd: string;\n\tmode: string;\n\tcaptureContent: boolean;\n}\n\ninterface ModelDescriptor {\n\tprovider?: string;\n\tid?: string;\n\tapi?: string;\n}\n\nexport interface GitMetadata {\n\tbranch?: string;\n\tcommit?: string;\n\tdetached: boolean;\n}\n\nexport interface ContextSnapshot {\n\tleafId?: string | null;\n\tcontextUsage?: {\n\t\ttokens: number | null;\n\t\tcontextWindow: number;\n\t\tpercent: number | null;\n\t};\n}\n\ninterface BeginAgentInput {\n\tprompt: unknown;\n\timages?: unknown;\n\tmodel?: ModelDescriptor;\n\tgit?: GitMetadata;\n\tsnapshot?: ContextSnapshot;\n}\n\ninterface AttemptInput {\n\treason?: string;\n}\n\ninterface GenerationInput {\n\tpayload?: unknown;\n\tpayloadStage?: \"before_provider_request\";\n\tmodel?: ModelDescriptor;\n\tthinkingLevel?: string;\n}\n\ninterface AssistantMessage {\n\trole: string;\n\tcontent?: unknown;\n\tprovider?: string;\n\tapi?: string;\n\tmodel?: string;\n\tresponseModel?: string;\n\tresponseId?: string;\n\tusage?: {\n\t\tinput?: number;\n\t\toutput?: number;\n\t\tcacheRead?: number;\n\t\tcacheWrite?: number;\n\t\tcacheWrite1h?: number;\n\t\treasoning?: number;\n\t\ttotalTokens?: number;\n\t\tcost?: {\n\t\t\tinput?: number;\n\t\t\toutput?: number;\n\t\t\tcacheRead?: number;\n\t\t\tcacheWrite?: number;\n\t\t\ttotal?: number;\n\t\t};\n\t};\n\tstopReason?: string;\n\terrorMessage?: string;\n}\n\ninterface ToolResult {\n\tcontent?: unknown;\n\tdetails?: unknown;\n\tisError?: boolean;\n}\n\ninterface TurnResult {\n\tmessage: { role: string; stopReason?: string; errorMessage?: string };\n\ttoolResultCount: number;\n}\n\ninterface CompactionStart {\n\treason: string;\n\twillRetry: boolean;\n\ttokensBefore?: number;\n\tmessagesToSummarize: number;\n\tturnPrefixMessages: number;\n\tbranchEntries: number;\n\tisSplitTurn: boolean;\n}\n\ninterface CompactionFinish {\n\treason: string;\n\twillRetry: boolean;\n\tfromExtension: boolean;\n\ttokensBefore?: number;\n\tdetails?: unknown;\n\tusage?: {\n\t\tinput?: number;\n\t\toutput?: number;\n\t\tcacheRead?: number;\n\t\tcacheWrite?: number;\n\t\ttotalTokens?: number;\n\t\tcost?: {\n\t\t\tinput?: number;\n\t\t\toutput?: number;\n\t\t\tcacheRead?: number;\n\t\t\tcacheWrite?: number;\n\t\t\ttotal?: number;\n\t\t};\n\t};\n}\n\ntype Outcome = \"success\" | \"error\" | \"aborted\" | \"length\" | \"interrupted\";\n\ninterface GenerationState {\n\tobservation: Observation;\n\tendTime?: number;\n\tcompletionStartTime?: number;\n\trequestMetadata: Record<string, unknown>;\n\tstatuses: number[];\n\theaders: Record<string, string>;\n}\n\ninterface ToolState {\n\tobservation: Observation;\n\tstartedAt: number;\n\tprogressUpdates: number;\n\tfirstProgressAt?: number;\n}\n\ninterface CompactionState {\n\tobservation: Observation;\n}\n\ninterface Counters {\n\tattempts: number;\n\tturns: number;\n\tgenerations: number;\n\ttools: number;\n\ttoolErrors: number;\n\tcompactions: number;\n\trecoveredErrors: number;\n\tfailedAttempts: number;\n}\n\nexport class TraceRecorder {\n\tprivate root: Observation | undefined;\n\tprivate attempt: Observation | undefined;\n\tprivate attemptIndex: number | undefined;\n\tprivate turn: Observation | undefined;\n\tprivate turnIndex: number | undefined;\n\tprivate generation: GenerationState | undefined;\n\tprivate readonly tools = new Map<string, ToolState>();\n\tprivate readonly duplicateToolIds = new Set<string>();\n\tprivate compaction: CompactionState | undefined;\n\tprivate lastOutput: unknown;\n\tprivate lastAssistant: AssistantMessage | undefined;\n\tprivate lastAttemptOutcome: Outcome | undefined;\n\tprivate unresolvedToolErrors = 0;\n\tprivate startSnapshot: ContextSnapshot | undefined;\n\tprivate counters: Counters = emptyCounters();\n\n\tconstructor(\n\t\tprivate readonly backend: TraceBackend,\n\t\tprivate readonly context: RecorderContext,\n\t) {}\n\n\tprivate startObservation(\n\t\tname: string,\n\t\tattributes: ObservationAttributes,\n\t\toptions: { asType: ObservationType; parent?: Observation },\n\t): Observation {\n\t\tconst { sessionId, userId } = this.context;\n\t\treturn this.backend.start(\n\t\t\tname,\n\t\t\t{ ...attributes, sessionId, ...(userId ? { userId } : {}) },\n\t\t\toptions,\n\t\t);\n\t}\n\n\thasActiveTrace(): boolean {\n\t\treturn this.root !== undefined;\n\t}\n\n\thasActiveAttempt(): boolean {\n\t\treturn this.attempt !== undefined;\n\t}\n\n\tbeginAgent(input: BeginAgentInput): void {\n\t\tif (this.root) this.closeActiveTrace(\"Interrupted by a new Pi run.\", undefined, \"interrupted\");\n\n\t\tthis.lastOutput = undefined;\n\t\tthis.lastAssistant = undefined;\n\t\tthis.lastAttemptOutcome = undefined;\n\t\tthis.unresolvedToolErrors = 0;\n\t\tthis.duplicateToolIds.clear();\n\t\tthis.startSnapshot = input.snapshot;\n\t\tthis.counters = emptyCounters();\n\t\tconst traceInput = this.capture({\n\t\t\tprompt: input.prompt,\n\t\t\t...(hasItems(input.images) ? { images: input.images } : {}),\n\t\t});\n\t\tconst metadata: Record<string, unknown> = {\n\t\t\t\"pi.cwd\": this.context.cwd,\n\t\t\t...(input.git?.branch ? { \"pi.git.branch\": input.git.branch } : {}),\n\t\t\t...(input.git?.commit ? { \"pi.git.commit\": input.git.commit } : {}),\n\t\t\t...(input.git ? { \"pi.git.detached\": input.git.detached } : {}),\n\t\t\t\"pi.mode\": this.context.mode,\n\t\t\t...(input.model?.id ? { \"pi.model\": input.model.id } : {}),\n\t\t\t...(input.model?.provider ? { \"pi.provider\": input.model.provider } : {}),\n\t\t\t\"pi.session.id\": this.context.sessionId,\n\t\t\t\"pi.trace.schema_version\": Number(TRACE_SCHEMA_VERSION),\n\t\t\t...snapshotMetadata(\"start\", input.snapshot),\n\t\t};\n\t\tconst attributes = { input: traceInput, metadata, version: TRACE_SCHEMA_VERSION };\n\t\tconst gitTag = input.git?.branch\n\t\t\t? `branch:${input.git.branch}`\n\t\t\t: input.git?.detached\n\t\t\t\t? \"git:detached\"\n\t\t\t\t: undefined;\n\n\t\tthis.root = this.startObservation(\"pi.agent\", attributes, { asType: \"agent\" });\n\t\tthis.root.updateTrace?.({\n\t\t\tname: \"pi.trace\",\n\t\t\tsessionId: this.context.sessionId,\n\t\t\t...(this.context.userId ? { userId: this.context.userId } : {}),\n\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t\tinput: traceInput,\n\t\t\tmetadata,\n\t\t\ttags: [\"pi\", ...(gitTag ? [gitTag] : [])],\n\t\t});\n\t}\n\n\tbeginAttempt(input: AttemptInput = {}): void {\n\t\tif (!this.root) return;\n\t\tif (this.attempt) {\n\t\t\tthis.closeAttempt(undefined, \"Interrupted by the next Pi attempt.\", \"interrupted\");\n\t\t}\n\t\tconst index = this.counters.attempts;\n\t\tthis.counters.attempts += 1;\n\t\tthis.lastAssistant = undefined;\n\t\tthis.unresolvedToolErrors = 0;\n\t\tthis.attemptIndex = index;\n\t\tthis.attempt = this.startObservation(\n\t\t\t\"pi.attempt\",\n\t\t\t{\n\t\t\t\tmetadata: {\n\t\t\t\t\t\"pi.attempt.index\": index,\n\t\t\t\t\t...(input.reason ? { \"pi.attempt.reason\": input.reason } : {}),\n\t\t\t\t},\n\t\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t\t},\n\t\t\t{ asType: \"span\", parent: this.root },\n\t\t);\n\t}\n\n\tfinishAttempt(message?: AssistantMessage): void {\n\t\tif (message?.role === \"assistant\") this.finishAssistant(message);\n\t\tif (!this.attempt) return;\n\t\tconst outcome = this.unresolvedToolErrors > 0 ? \"error\" : classifyOutcome(message);\n\t\tthis.closeAttempt(\n\t\t\tmessage,\n\t\t\tthis.unresolvedToolErrors > 0 ? \"Pi attempt ended after a tool failure.\" : undefined,\n\t\t\toutcome,\n\t\t);\n\t}\n\n\tbeginTurn(turnIndex: number): void {\n\t\tif (!this.root) return;\n\t\tif (this.turn) this.closeTurn(\"Interrupted by the next Pi turn.\", \"ERROR\");\n\t\tthis.counters.turns += 1;\n\t\tthis.turnIndex = turnIndex;\n\t\tthis.turn = this.startObservation(\n\t\t\t\"pi.turn\",\n\t\t\t{ metadata: { \"pi.turn.index\": turnIndex }, version: TRACE_SCHEMA_VERSION },\n\t\t\t{ asType: \"span\", parent: this.attempt ?? this.root },\n\t\t);\n\t}\n\n\tfinishTurn(turnIndex: number, result: TurnResult): void {\n\t\tif (!this.turn) return;\n\t\tthis.closeGeneration(\"Turn ended without a finalized assistant message.\");\n\t\tthis.closeTools(\"Tool span ended when the Pi turn finished.\");\n\n\t\tconst mismatched = this.turnIndex !== turnIndex;\n\t\tconst outcome = classifyOutcome(result.message);\n\t\tthis.turn.update({\n\t\t\tmetadata: {\n\t\t\t\t\"pi.turn.index\": this.turnIndex ?? turnIndex,\n\t\t\t\t\"pi.turn.tool_result_count\": result.toolResultCount,\n\t\t\t\t...(result.message.stopReason ? { \"pi.turn.stop_reason\": result.message.stopReason } : {}),\n\t\t\t},\n\t\t\t...(mismatched && outcome === \"success\"\n\t\t\t\t? {\n\t\t\t\t\t\tlevel: \"WARNING\" as const,\n\t\t\t\t\t\tstatusMessage: `Turn ${turnIndex} ended while turn ${this.turnIndex} was active.`,\n\t\t\t\t\t}\n\t\t\t\t: severityForOutcome(outcome, result.message.errorMessage)),\n\t\t});\n\t\tthis.turn.end();\n\t\tthis.turn = undefined;\n\t\tthis.turnIndex = undefined;\n\t}\n\n\tbeginGeneration(input: GenerationInput = {}): void {\n\t\tif (!this.root) return;\n\t\tthis.closeGeneration(\"Interrupted by the next provider request.\");\n\t\tif (this.unresolvedToolErrors > 0) {\n\t\t\tthis.counters.recoveredErrors += this.unresolvedToolErrors;\n\t\t\tthis.unresolvedToolErrors = 0;\n\t\t}\n\t\tthis.counters.generations += 1;\n\t\tconst requestMetadata: Record<string, unknown> = {\n\t\t\t...(input.payloadStage ? { \"pi.request.payload_stage\": input.payloadStage } : {}),\n\t\t\t...(input.model?.provider ? { \"pi.request.provider\": input.model.provider } : {}),\n\t\t\t...(input.model?.id ? { \"pi.request.model\": input.model.id } : {}),\n\t\t\t...(input.model?.api ? { \"pi.request.api\": input.model.api } : {}),\n\t\t\t...(input.thinkingLevel ? { \"pi.request.thinking_level\": input.thinkingLevel } : {}),\n\t\t};\n\t\tconst observation = this.startObservation(\n\t\t\t\"pi.llm\",\n\t\t\t{\n\t\t\t\t...(input.payload !== undefined ? { input: this.capture(input.payload) } : {}),\n\t\t\t\t...(input.model?.id ? { model: input.model.id } : {}),\n\t\t\t\t...(input.thinkingLevel\n\t\t\t\t\t? { modelParameters: { thinking_level: input.thinkingLevel } }\n\t\t\t\t\t: {}),\n\t\t\t\t...(Object.keys(requestMetadata).length > 0 ? { metadata: requestMetadata } : {}),\n\t\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t\t},\n\t\t\t{ asType: \"generation\", parent: this.turn ?? this.attempt ?? this.root },\n\t\t);\n\t\tthis.generation = {\n\t\t\tobservation,\n\t\t\trequestMetadata,\n\t\t\tstatuses: [],\n\t\t\theaders: {},\n\t\t};\n\t}\n\n\trecordProviderResponse(status: number, headers: Record<string, string> = {}): void {\n\t\tif (!this.generation) return;\n\t\tthis.generation.statuses.push(status);\n\t\tObject.assign(this.generation.headers, allowlistedResponseHeaders(headers));\n\t}\n\n\tmarkGenerationFirstOutput(timestamp = Date.now()): void {\n\t\tif (this.generation && this.generation.completionStartTime === undefined) {\n\t\t\tthis.generation.completionStartTime = timestamp;\n\t\t}\n\t}\n\n\tmarkGenerationEnd(endTime = Date.now()): void {\n\t\tif (this.generation && this.generation.endTime === undefined) {\n\t\t\tthis.generation.endTime = endTime;\n\t\t}\n\t}\n\n\tfinishAssistant(message: AssistantMessage): void {\n\t\tif (message.role !== \"assistant\") return;\n\t\tthis.lastAssistant = message;\n\t\tthis.lastOutput = this.capture(message.content);\n\t\tif (!this.generation) return;\n\n\t\tconst state = this.generation;\n\t\tconst usageDetails = numericRecord({\n\t\t\tinput: message.usage?.input,\n\t\t\toutput: message.usage?.output,\n\t\t\tcache_read_input_tokens: message.usage?.cacheRead,\n\t\t\tcache_creation_input_tokens: message.usage?.cacheWrite,\n\t\t\ttotal: message.usage?.totalTokens,\n\t\t});\n\t\tconst costDetails = positiveNumericRecord({\n\t\t\tinput: message.usage?.cost?.input,\n\t\t\toutput: message.usage?.cost?.output,\n\t\t\tcache_read: message.usage?.cost?.cacheRead,\n\t\t\tcache_write: message.usage?.cost?.cacheWrite,\n\t\t\ttotal: message.usage?.cost?.total,\n\t\t});\n\t\tconst outcome = classifyOutcome(message);\n\t\tconst responseModel = message.responseModel ?? message.model;\n\t\tconst httpMetadata = generationHttpMetadata(state);\n\t\tconst recoveredStatuses = state.statuses.filter((status) => status >= 400).length;\n\t\tif (outcome === \"success\" && recoveredStatuses > 0) {\n\t\t\tthis.counters.recoveredErrors += recoveredStatuses;\n\t\t}\n\t\tstate.observation.update({\n\t\t\toutput: this.lastOutput,\n\t\t\t...(state.completionStartTime !== undefined\n\t\t\t\t? { completionStartTime: new Date(state.completionStartTime) }\n\t\t\t\t: {}),\n\t\t\t...(responseModel ? { model: responseModel } : {}),\n\t\t\t...(Object.keys(usageDetails).length > 0 ? { usageDetails } : {}),\n\t\t\t...(Object.keys(costDetails).length > 0 ? { costDetails } : {}),\n\t\t\tmetadata: {\n\t\t\t\t...state.requestMetadata,\n\t\t\t\t...httpMetadata,\n\t\t\t\t...(message.provider\n\t\t\t\t\t? { \"pi.provider\": message.provider, \"pi.response.provider\": message.provider }\n\t\t\t\t\t: {}),\n\t\t\t\t...(message.api ? { \"pi.response.api\": message.api } : {}),\n\t\t\t\t...(responseModel ? { \"pi.response.model\": responseModel } : {}),\n\t\t\t\t...(message.responseId ? { \"pi.response.id\": message.responseId } : {}),\n\t\t\t\t...(message.responseModel && message.model && message.responseModel !== message.model\n\t\t\t\t\t? { \"pi.requested_model\": message.model }\n\t\t\t\t\t: {}),\n\t\t\t\t...(message.stopReason ? { \"pi.stop_reason\": message.stopReason } : {}),\n\t\t\t\t...(finiteNumber(message.usage?.reasoning)\n\t\t\t\t\t? { \"pi.usage.reasoning_tokens\": message.usage.reasoning }\n\t\t\t\t\t: {}),\n\t\t\t\t...(finiteNumber(message.usage?.cacheWrite1h)\n\t\t\t\t\t? { \"pi.usage.cache_write_1h_tokens\": message.usage.cacheWrite1h }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\t...severityForOutcome(outcome, message.errorMessage),\n\t\t});\n\t\tstate.observation.end(state.endTime);\n\t\tthis.generation = undefined;\n\t}\n\n\tbeginTool(toolCallId: string, toolName: string, args?: unknown, startedAt = Date.now()): void {\n\t\tif (!this.root) return;\n\t\tthis.counters.tools += 1;\n\t\tif (this.duplicateToolIds.has(toolCallId)) {\n\t\t\tthis.counters.toolErrors += 1;\n\t\t\tconst duplicate = this.startToolObservation(toolCallId, toolName, args);\n\t\t\tduplicate.update({\n\t\t\t\tlevel: \"ERROR\",\n\t\t\t\tstatusMessage: \"Duplicate tool call ID cannot be correlated safely.\",\n\t\t\t});\n\t\t\tduplicate.end();\n\t\t\treturn;\n\t\t}\n\n\t\tconst existing = this.tools.get(toolCallId);\n\t\tif (existing) {\n\t\t\texisting.observation.update({\n\t\t\t\tlevel: \"ERROR\",\n\t\t\t\tstatusMessage: \"Duplicate tool execution started.\",\n\t\t\t});\n\t\t\texisting.observation.end();\n\t\t\tthis.tools.delete(toolCallId);\n\t\t\tthis.counters.toolErrors += 2;\n\t\t\tconst duplicate = this.startToolObservation(toolCallId, toolName, args);\n\t\t\tduplicate.update({\n\t\t\t\tlevel: \"ERROR\",\n\t\t\t\tstatusMessage: \"Duplicate tool call ID cannot be correlated safely.\",\n\t\t\t});\n\t\t\tduplicate.end();\n\t\t\tthis.duplicateToolIds.add(toolCallId);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.tools.set(toolCallId, {\n\t\t\tobservation: this.startToolObservation(toolCallId, toolName, args),\n\t\t\tstartedAt,\n\t\t\tprogressUpdates: 0,\n\t\t});\n\t}\n\n\trecordToolInput(toolCallId: string, input: unknown): void {\n\t\tif (input === undefined || this.duplicateToolIds.has(toolCallId)) return;\n\t\tthis.tools.get(toolCallId)?.observation.update({ input: this.capture(input) });\n\t}\n\n\trecordToolProgress(toolCallId: string, timestamp = Date.now()): void {\n\t\tconst tool = this.tools.get(toolCallId);\n\t\tif (!tool) return;\n\t\ttool.progressUpdates += 1;\n\t\ttool.firstProgressAt ??= timestamp;\n\t}\n\n\tfinishTool(toolCallId: string, result: ToolResult): void {\n\t\tif (this.duplicateToolIds.has(toolCallId)) return;\n\t\tconst tool = this.tools.get(toolCallId);\n\t\tif (!tool) return;\n\t\tif (result.isError) {\n\t\t\tthis.counters.toolErrors += 1;\n\t\t\tthis.unresolvedToolErrors += 1;\n\t\t}\n\t\ttool.observation.update({\n\t\t\toutput: this.capture({ content: result.content, details: result.details }),\n\t\t\tmetadata: {\n\t\t\t\t\"pi.tool.progress_update_count\": tool.progressUpdates,\n\t\t\t\t...(tool.firstProgressAt !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t\"pi.tool.time_to_first_progress_ms\": Math.max(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\ttool.firstProgressAt - tool.startedAt,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\t...(result.isError\n\t\t\t\t? { level: \"ERROR\" as const, statusMessage: \"Pi tool execution failed.\" }\n\t\t\t\t: {}),\n\t\t});\n\t\ttool.observation.end();\n\t\tthis.tools.delete(toolCallId);\n\t}\n\n\tbeginCompaction(input: CompactionStart): void {\n\t\tif (!this.root) return;\n\t\tthis.closeCompaction(\"Interrupted by another Pi compaction.\");\n\t\tthis.counters.compactions += 1;\n\t\tthis.compaction = {\n\t\t\tobservation: this.startObservation(\n\t\t\t\t\"pi.compaction\",\n\t\t\t\t{\n\t\t\t\t\tmetadata: {\n\t\t\t\t\t\t\"pi.compaction.reason\": input.reason,\n\t\t\t\t\t\t\"pi.compaction.will_retry\": input.willRetry,\n\t\t\t\t\t\t...(finiteNumber(input.tokensBefore)\n\t\t\t\t\t\t\t? { \"pi.compaction.tokens_before\": input.tokensBefore }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\"pi.compaction.messages_to_summarize\": input.messagesToSummarize,\n\t\t\t\t\t\t\"pi.compaction.turn_prefix_messages\": input.turnPrefixMessages,\n\t\t\t\t\t\t\"pi.compaction.branch_entries\": input.branchEntries,\n\t\t\t\t\t\t\"pi.compaction.is_split_turn\": input.isSplitTurn,\n\t\t\t\t\t},\n\t\t\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t\t\t},\n\t\t\t\t{ asType: \"span\", parent: this.root },\n\t\t\t),\n\t\t};\n\t}\n\n\tfinishCompaction(input: CompactionFinish): void {\n\t\tif (!this.compaction) return;\n\t\tconst details = structuralCompactionDetails(input.details);\n\t\tconst usage = numericRecord({\n\t\t\tinput: input.usage?.input,\n\t\t\toutput: input.usage?.output,\n\t\t\tcache_read: input.usage?.cacheRead,\n\t\t\tcache_write: input.usage?.cacheWrite,\n\t\t\ttotal: input.usage?.totalTokens,\n\t\t});\n\t\tconst cost = positiveNumericRecord({\n\t\t\tinput: input.usage?.cost?.input,\n\t\t\toutput: input.usage?.cost?.output,\n\t\t\tcache_read: input.usage?.cost?.cacheRead,\n\t\t\tcache_write: input.usage?.cost?.cacheWrite,\n\t\t\ttotal: input.usage?.cost?.total,\n\t\t});\n\t\tthis.compaction.observation.update({\n\t\t\tmetadata: {\n\t\t\t\t\"pi.compaction.reason\": input.reason,\n\t\t\t\t\"pi.compaction.will_retry\": input.willRetry,\n\t\t\t\t\"pi.compaction.from_extension\": input.fromExtension,\n\t\t\t\t...(finiteNumber(input.tokensBefore)\n\t\t\t\t\t? { \"pi.compaction.tokens_before\": input.tokensBefore }\n\t\t\t\t\t: {}),\n\t\t\t\t...details,\n\t\t\t\t...prefixRecord(\"pi.compaction.usage\", usage),\n\t\t\t\t...prefixRecord(\"pi.compaction.cost\", cost),\n\t\t\t},\n\t\t});\n\t\tthis.compaction.observation.end();\n\t\tthis.compaction = undefined;\n\t}\n\n\tsettle(snapshot?: ContextSnapshot): void {\n\t\tthis.closeActiveTrace(undefined, snapshot);\n\t}\n\n\tinterrupt(statusMessage: string, snapshot?: ContextSnapshot): void {\n\t\tthis.closeActiveTrace(statusMessage, snapshot, \"interrupted\");\n\t}\n\n\tasync flush(): Promise<void> {\n\t\tawait this.backend.forceFlush();\n\t}\n\n\tasync shutdown(snapshot?: ContextSnapshot): Promise<void> {\n\t\tthis.closeActiveTrace(\"Pi shut down before the active trace settled.\", snapshot, \"interrupted\");\n\t\tawait this.backend.shutdown();\n\t}\n\n\tprivate closeActiveTrace(\n\t\tstatusMessage?: string,\n\t\tsnapshot?: ContextSnapshot,\n\t\tforcedOutcome?: Outcome,\n\t): void {\n\t\tthis.closeTurn(statusMessage ?? \"Pi turn ended when the agent run settled.\");\n\t\tthis.closeAttempt(undefined, statusMessage, forcedOutcome ?? \"interrupted\");\n\t\tthis.closeCompaction(statusMessage ?? \"Pi compaction ended when the agent run settled.\");\n\n\t\tif (!this.root) return;\n\t\tconst baseOutcome =\n\t\t\tforcedOutcome ?? this.lastAttemptOutcome ?? classifyOutcome(this.lastAssistant);\n\t\tconst recoveredErrorCount =\n\t\t\tthis.counters.recoveredErrors +\n\t\t\t(baseOutcome === \"success\" ? this.counters.failedAttempts : 0);\n\t\tconst traceOutcome =\n\t\t\tbaseOutcome === \"success\" && recoveredErrorCount > 0 ? \"recovered_success\" : baseOutcome;\n\t\tconst finalMetadata: Record<string, unknown> = {\n\t\t\t\"pi.trace.schema_version\": Number(TRACE_SCHEMA_VERSION),\n\t\t\t\"pi.trace.outcome\": traceOutcome,\n\t\t\t...(this.lastAssistant?.stopReason\n\t\t\t\t? { \"pi.trace.stop_reason\": this.lastAssistant.stopReason }\n\t\t\t\t: {}),\n\t\t\t\"pi.trace.attempt_count\": this.counters.attempts,\n\t\t\t\"pi.trace.turn_count\": this.counters.turns,\n\t\t\t\"pi.trace.generation_count\": this.counters.generations,\n\t\t\t\"pi.trace.tool_count\": this.counters.tools,\n\t\t\t\"pi.trace.tool_error_count\": this.counters.toolErrors,\n\t\t\t\"pi.trace.compaction_count\": this.counters.compactions,\n\t\t\t\"pi.trace.recovered_error_count\": recoveredErrorCount,\n\t\t\t...snapshotMetadata(\"start\", this.startSnapshot),\n\t\t\t...snapshotMetadata(\"end\", snapshot),\n\t\t};\n\t\tconst finalAttributes: ObservationAttributes = {\n\t\t\t...(this.lastOutput !== undefined ? { output: this.lastOutput } : {}),\n\t\t\tmetadata: finalMetadata,\n\t\t\t...severityForOutcome(baseOutcome, statusMessage ?? this.lastAssistant?.errorMessage),\n\t\t};\n\t\tthis.root.update(finalAttributes);\n\t\tthis.root.updateTrace?.({\n\t\t\t...(this.lastOutput !== undefined ? { output: this.lastOutput } : {}),\n\t\t\tmetadata: finalMetadata,\n\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t});\n\t\tthis.root.end();\n\t\tthis.root = undefined;\n\t\tthis.lastOutput = undefined;\n\t\tthis.lastAssistant = undefined;\n\t\tthis.lastAttemptOutcome = undefined;\n\t\tthis.unresolvedToolErrors = 0;\n\t\tthis.duplicateToolIds.clear();\n\t\tthis.startSnapshot = undefined;\n\t}\n\n\tprivate closeAttempt(\n\t\tmessage?: AssistantMessage,\n\t\tstatusMessage?: string,\n\t\tforcedOutcome?: Outcome,\n\t): void {\n\t\tif (!this.attempt) return;\n\t\tthis.closeTurn(statusMessage ?? \"Pi turn ended when the attempt finished.\");\n\t\tconst outcome = forcedOutcome ?? classifyOutcome(message);\n\t\tif (outcome === \"error\") this.counters.failedAttempts += 1;\n\t\tthis.lastAttemptOutcome = outcome;\n\t\tthis.attempt.update({\n\t\t\t...(message?.content !== undefined ? { output: this.capture(message.content) } : {}),\n\t\t\tmetadata: {\n\t\t\t\t\"pi.attempt.index\": this.attemptIndex ?? Math.max(0, this.counters.attempts - 1),\n\t\t\t\t\"pi.attempt.outcome\": outcome,\n\t\t\t\t...(message?.stopReason ? { \"pi.attempt.stop_reason\": message.stopReason } : {}),\n\t\t\t},\n\t\t\t...severityForOutcome(outcome, statusMessage ?? message?.errorMessage),\n\t\t});\n\t\tthis.attempt.end();\n\t\tthis.attempt = undefined;\n\t\tthis.attemptIndex = undefined;\n\t\tthis.unresolvedToolErrors = 0;\n\t}\n\n\tprivate startToolObservation(toolCallId: string, toolName: string, args?: unknown): Observation {\n\t\treturn this.startObservation(\n\t\t\t`pi.tool.${toolName}`,\n\t\t\t{\n\t\t\t\t...(args !== undefined ? { input: this.capture(args) } : {}),\n\t\t\t\tmetadata: { \"pi.tool.call_id\": toolCallId, \"pi.tool.name\": toolName },\n\t\t\t\tversion: TRACE_SCHEMA_VERSION,\n\t\t\t},\n\t\t\t{ asType: \"tool\", parent: this.turn ?? this.attempt ?? this.root },\n\t\t);\n\t}\n\n\tprivate closeTurn(statusMessage: string, generationLevel: \"ERROR\" | \"WARNING\" = \"WARNING\"): void {\n\t\tthis.closeGeneration(statusMessage, generationLevel);\n\t\tthis.closeTools(statusMessage);\n\t\tif (!this.turn) return;\n\t\tthis.turn.update({ level: \"WARNING\", statusMessage });\n\t\tthis.turn.end();\n\t\tthis.turn = undefined;\n\t\tthis.turnIndex = undefined;\n\t}\n\n\tprivate closeTools(statusMessage: string): void {\n\t\tfor (const tool of this.tools.values()) {\n\t\t\ttool.observation.update({\n\t\t\t\tlevel: \"WARNING\",\n\t\t\t\tstatusMessage,\n\t\t\t\tmetadata: {\n\t\t\t\t\t\"pi.tool.progress_update_count\": tool.progressUpdates,\n\t\t\t\t\t...(tool.firstProgressAt !== undefined\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\"pi.tool.time_to_first_progress_ms\": Math.max(\n\t\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\t\ttool.firstProgressAt - tool.startedAt,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {}),\n\t\t\t\t},\n\t\t\t});\n\t\t\ttool.observation.end();\n\t\t}\n\t\tthis.tools.clear();\n\t}\n\n\tprivate closeGeneration(statusMessage: string, level: \"ERROR\" | \"WARNING\" = \"ERROR\"): void {\n\t\tif (!this.generation) return;\n\t\tthis.generation.observation.update({\n\t\t\tlevel,\n\t\t\tstatusMessage,\n\t\t\tmetadata: {\n\t\t\t\t...this.generation.requestMetadata,\n\t\t\t\t...generationHttpMetadata(this.generation),\n\t\t\t},\n\t\t});\n\t\tthis.generation.observation.end(this.generation.endTime);\n\t\tthis.generation = undefined;\n\t}\n\n\tprivate closeCompaction(statusMessage: string): void {\n\t\tif (!this.compaction) return;\n\t\tthis.compaction.observation.update({ level: \"WARNING\", statusMessage });\n\t\tthis.compaction.observation.end();\n\t\tthis.compaction = undefined;\n\t}\n\n\tprivate capture(value: unknown): unknown {\n\t\treturn this.context.captureContent ? sanitizeTraceValue(value) : CONTENT_DISABLED;\n\t}\n}\n\nfunction generationHttpMetadata(state: GenerationState): Record<string, unknown> {\n\tconst finalStatus = state.statuses.at(-1);\n\treturn {\n\t\t...(state.statuses.length > 0\n\t\t\t? {\n\t\t\t\t\t\"http.response.status_codes\": [...state.statuses],\n\t\t\t\t\t\"http.response.status_code\": finalStatus,\n\t\t\t\t\t\"http.response.attempt_count\": state.statuses.length,\n\t\t\t\t\t\"http.response.retry_count\": Math.max(0, state.statuses.length - 1),\n\t\t\t\t}\n\t\t\t: {}),\n\t\t...(Object.keys(state.headers).length > 0\n\t\t\t? { \"http.response.headers\": { ...state.headers } }\n\t\t\t: {}),\n\t};\n}\n\nfunction allowlistedResponseHeaders(headers: Record<string, string>): Record<string, string> {\n\tconst output: Record<string, string> = {};\n\tfor (const [rawName, rawValue] of Object.entries(headers)) {\n\t\tconst name = rawName.toLowerCase();\n\t\tif (!ALLOWED_RESPONSE_HEADERS.has(name) || typeof rawValue !== \"string\") continue;\n\t\toutput[name] = truncateString(rawValue, MAX_HEADER_VALUE_LENGTH);\n\t}\n\treturn output;\n}\n\nfunction structuralCompactionDetails(details: unknown): Record<string, unknown> {\n\tif (!details || typeof details !== \"object\" || Array.isArray(details)) return {};\n\tconst record = details as Record<string, unknown>;\n\treturn {\n\t\t...(Array.isArray(record.readFiles)\n\t\t\t? { \"pi.compaction.read_file_count\": record.readFiles.length }\n\t\t\t: {}),\n\t\t...(Array.isArray(record.modifiedFiles)\n\t\t\t? { \"pi.compaction.modified_file_count\": record.modifiedFiles.length }\n\t\t\t: {}),\n\t};\n}\n\nfunction snapshotMetadata(prefix: string, snapshot?: ContextSnapshot): Record<string, unknown> {\n\tif (!snapshot) return {};\n\treturn {\n\t\t...(snapshot.leafId ? { [`pi.trace.${prefix}_leaf_id`]: snapshot.leafId } : {}),\n\t\t...(snapshot.contextUsage\n\t\t\t? {\n\t\t\t\t\t...(finiteNumber(snapshot.contextUsage.tokens)\n\t\t\t\t\t\t? { [`pi.trace.${prefix}_context_tokens`]: snapshot.contextUsage.tokens }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t[`pi.trace.${prefix}_context_window`]: snapshot.contextUsage.contextWindow,\n\t\t\t\t\t...(finiteNumber(snapshot.contextUsage.percent)\n\t\t\t\t\t\t? { [`pi.trace.${prefix}_context_percent`]: snapshot.contextUsage.percent }\n\t\t\t\t\t\t: {}),\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n}\n\nfunction classifyOutcome(message?: {\n\trole?: string;\n\tstopReason?: string;\n\terrorMessage?: string;\n}): Outcome {\n\tif (message?.role !== \"assistant\") return \"interrupted\";\n\tif (message.stopReason === \"error\" || message.errorMessage) return \"error\";\n\tif (message.stopReason === \"aborted\") return \"aborted\";\n\tif (message.stopReason === \"length\") return \"length\";\n\treturn \"success\";\n}\n\nfunction severityForOutcome(\n\toutcome: Outcome,\n\tstatusMessage?: string,\n): Pick<ObservationAttributes, \"level\" | \"statusMessage\"> {\n\tif (outcome === \"success\") return {};\n\tif (outcome === \"error\") {\n\t\treturn {\n\t\t\tlevel: \"ERROR\",\n\t\t\tstatusMessage: statusMessage ?? \"The Pi operation failed.\",\n\t\t};\n\t}\n\treturn {\n\t\tlevel: \"WARNING\",\n\t\tstatusMessage:\n\t\t\tstatusMessage ??\n\t\t\t(outcome === \"aborted\"\n\t\t\t\t? \"The Pi operation was aborted.\"\n\t\t\t\t: outcome === \"length\"\n\t\t\t\t\t? \"The model reached its output limit.\"\n\t\t\t\t\t: \"The Pi operation was interrupted.\"),\n\t};\n}\n\nfunction prefixRecord(prefix: string, values: Record<string, number>): Record<string, number> {\n\treturn Object.fromEntries(\n\t\tObject.entries(values).map(([key, value]) => [`${prefix}.${key}`, value]),\n\t);\n}\n\nfunction truncateString(value: string, maxBytes: number): string {\n\tconst boundedPrefix = value.slice(0, maxBytes);\n\tif (boundedPrefix.length === value.length && byteLength(boundedPrefix) <= maxBytes) {\n\t\treturn boundedPrefix;\n\t}\n\tconst suffix = \"\u2026 [truncated]\";\n\tconst target = Math.max(0, maxBytes - byteLength(suffix) - 2);\n\tlet bytes = 0;\n\tlet output = \"\";\n\tfor (const character of boundedPrefix) {\n\t\tconst size = byteLength(character);\n\t\tif (bytes + size > target) break;\n\t\toutput += character;\n\t\tbytes += size;\n\t}\n\treturn `${output}${suffix}`;\n}\n\nfunction byteLength(value: string): number {\n\treturn Buffer.byteLength(value, \"utf8\");\n}\n\nfunction numericRecord(values: Record<string, number | undefined>): Record<string, number> {\n\treturn Object.fromEntries(\n\t\tObject.entries(values).filter((entry): entry is [string, number] => finiteNumber(entry[1])),\n\t);\n}\n\nfunction positiveNumericRecord(values: Record<string, number | undefined>): Record<string, number> {\n\treturn Object.fromEntries(\n\t\tObject.entries(values).filter(\n\t\t\t(entry): entry is [string, number] => finiteNumber(entry[1]) && entry[1] > 0,\n\t\t),\n\t);\n}\n\nfunction finiteNumber(value: unknown): value is number {\n\treturn typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction hasItems(value: unknown): boolean {\n\treturn Array.isArray(value) ? value.length > 0 : value !== undefined;\n}\n\nfunction emptyCounters(): Counters {\n\treturn {\n\t\tattempts: 0,\n\t\tturns: 0,\n\t\tgenerations: 0,\n\t\ttools: 0,\n\t\ttoolErrors: 0,\n\t\tcompactions: 0,\n\t\trecoveredErrors: 0,\n\t\tfailedAttempts: 0,\n\t};\n}\n", "import type {\n\tExtensionAPI,\n\tExtensionCommandContext,\n\tExtensionContext,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n\tDEFAULT_BASE_URL,\n\ttype LangfuseConfig,\n\ttype LangfuseConfigPatch,\n\ttype LangfuseConfigResult,\n\tloadLangfuseConfig,\n\tnormalizeLangfuseConfig,\n\twriteLangfuseConfig,\n} from \"./config.js\";\nimport {\n\ttype ContextSnapshot,\n\ttype GitMetadata,\n\ttype TraceBackend,\n\tTraceRecorder,\n} from \"./tracing.js\";\n\ninterface ExtensionDependencies {\n\tloadConfig(path?: string): Promise<LangfuseConfigResult>;\n\twriteConfig(config: LangfuseConfigPatch, path?: string): Promise<unknown>;\n\tcreateBackend(config: LangfuseConfig): Promise<TraceBackend>;\n\tresolveGitMetadata(cwd: string): Promise<GitMetadata | undefined>;\n}\n\nconst FLUSH_ACTION = \"Flush completed traces for this session\";\nconst SET_UP_ACTION = \"Set up Langfuse for this Pi agent directory (restart required)\";\nconst UPDATE_ACTION = \"Update Langfuse for this Pi agent directory (restart required)\";\nconst HELP_ACTION = \"Show setup and privacy help\";\n\nexport function createLangfuseExtension(\n\tdependencies: Partial<ExtensionDependencies> = {},\n): (pi: ExtensionAPI) => void {\n\tconst loadConfig = dependencies.loadConfig ?? loadLangfuseConfig;\n\tconst writeConfig = dependencies.writeConfig ?? writeLangfuseConfig;\n\tconst createBackend =\n\t\tdependencies.createBackend ??\n\t\t(async (config) => {\n\t\t\tconst { createProductionBackend } = await import(\"./runtime.js\");\n\t\t\treturn createProductionBackend(config);\n\t\t});\n\n\treturn function langfuse(pi: ExtensionAPI) {\n\t\tconst resolveGit =\n\t\t\tdependencies.resolveGitMetadata ??\n\t\t\t((cwd: string) =>\n\t\t\t\tresolveGitMetadata((command, args, options) => pi.exec(command, args, options), cwd));\n\t\tlet recorder: TraceRecorder | undefined;\n\t\tlet activeConfig: LangfuseConfig | undefined;\n\t\tlet configPath: string | undefined;\n\t\tlet initializationError: string | undefined;\n\t\tlet hasStoredConfig = false;\n\t\tlet configurationNotice: string | undefined;\n\t\tlet sessionGeneration = 0;\n\t\tlet menuController = new AbortController();\n\t\tlet configWriteQueue = Promise.resolve();\n\t\tlet nextAttemptReason: string | undefined;\n\n\t\tasync function showLangfuseMenu(ctx: ExtensionCommandContext) {\n\t\t\tif (!ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\tformatNonInteractiveStatus(activeConfig, configPath, initializationError),\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst menuGeneration = sessionGeneration;\n\t\t\tconst menuSignal = menuController.signal;\n\t\t\tconst isCurrent = () => menuGeneration === sessionGeneration && !menuSignal.aborted;\n\t\t\tconst { defineMenu, runMenu } = await import(\"@narumitw/pi-tui-kit\");\n\t\t\tif (!isCurrent()) return;\n\t\t\ttype Screen = \"main\";\n\t\t\ttype Action = \"flush\" | \"configure\" | \"help\";\n\t\t\tconst menu = defineMenu<undefined, Screen, Action>({\n\t\t\t\tstart: \"main\",\n\t\t\t\tscreens: {\n\t\t\t\t\tmain: () => ({\n\t\t\t\t\t\tkind: \"actions\",\n\t\t\t\t\t\ttitle: \"Langfuse\",\n\t\t\t\t\t\tlines: formatMenuTitle(\n\t\t\t\t\t\t\tactiveConfig,\n\t\t\t\t\t\t\tconfigPath,\n\t\t\t\t\t\t\tinitializationError,\n\t\t\t\t\t\t\tconfigurationNotice,\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t\t\t.slice(1),\n\t\t\t\t\t\titems: [\n\t\t\t\t\t\t\t...(recorder ? [{ id: \"flush\", label: FLUSH_ACTION, action: \"flush\" as const }] : []),\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tid: \"configure\",\n\t\t\t\t\t\t\t\tlabel: hasStoredConfig ? UPDATE_ACTION : SET_UP_ACTION,\n\t\t\t\t\t\t\t\taction: \"configure\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ id: \"help\", label: HELP_ACTION, action: \"help\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t\thint: \"close\",\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t\tactions: {\n\t\t\t\t\tflush: async () => {\n\t\t\t\t\t\tconst menuRecorder = recorder;\n\t\t\t\t\t\tconst menuConfig = activeConfig;\n\t\t\t\t\t\tif (!menuRecorder) {\n\t\t\t\t\t\t\tctx.ui.notify(\"Langfuse tracing is not enabled for this session.\", \"warning\");\n\t\t\t\t\t\t\treturn { kind: \"close\" };\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait menuRecorder.flush();\n\t\t\t\t\t\t\tif (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\t\tctx.ui.notify(\"Langfuse traces flushed for this session.\", \"info\");\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tif (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\t\tctx.ui.notify(`Langfuse flush failed: ${formatError(error, menuConfig)}`, \"error\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { kind: \"close\" };\n\t\t\t\t\t},\n\t\t\t\t\tconfigure: async () => {\n\t\t\t\t\t\tconst loaded = await loadConfig(configPath);\n\t\t\t\t\t\tif (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\tconfigPath = loaded.path;\n\t\t\t\t\t\tconst next = await promptForConfig(\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\tloaded.ok ? loaded.config : undefined,\n\t\t\t\t\t\t\t() => menuGeneration === sessionGeneration,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (!next || menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst write = configWriteQueue.then(() => writeConfig(next, loaded.path));\n\t\t\t\t\t\t\tconfigWriteQueue = write.then(\n\t\t\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t\t\t\t() => undefined,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tawait write;\n\t\t\t\t\t\t\tif (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\t\thasStoredConfig = true;\n\t\t\t\t\t\t\tconfigurationNotice =\n\t\t\t\t\t\t\t\t\"Saved; restart each Pi process to use it in subsequent sessions.\";\n\t\t\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t\t\t`Saved Langfuse config to ${loaded.path} for this Pi agent directory. Restart each Pi process to apply it to subsequent sessions.`,\n\t\t\t\t\t\t\t\t\"info\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tif (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n\t\t\t\t\t\t\tctx.ui.notify(`Failed to save Langfuse config: ${formatError(error, next)}`, \"error\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn { kind: \"close\" };\n\t\t\t\t\t},\n\t\t\t\t\thelp: async () => {\n\t\t\t\t\t\tctx.ui.notify(formatHelp(configPath), \"info\");\n\t\t\t\t\t\treturn { kind: \"close\" };\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\t\t\tawait runMenu(ctx, menu, {\n\t\t\t\tgetState: () => undefined,\n\t\t\t\tsignal: menuSignal,\n\t\t\t\tisCurrent,\n\t\t\t});\n\t\t}\n\n\t\tpi.registerCommand(\"langfuse\", {\n\t\t\tdescription: \"Open interactive Langfuse tracing controls\",\n\t\t\thandler: async (_args, ctx) => showLangfuseMenu(ctx),\n\t\t});\n\n\t\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\t\tconst generation = ++sessionGeneration;\n\t\t\tmenuController.abort(new DOMException(\"Langfuse session replaced\", \"AbortError\"));\n\t\t\tmenuController = new AbortController();\n\t\t\trecorder = undefined;\n\t\t\tactiveConfig = undefined;\n\t\t\tconfigPath = undefined;\n\t\t\tinitializationError = undefined;\n\t\t\thasStoredConfig = false;\n\t\t\tconfigurationNotice = undefined;\n\t\t\tnextAttemptReason = undefined;\n\n\t\t\tawait configWriteQueue;\n\t\t\tif (generation !== sessionGeneration) return;\n\t\t\tconst result = await loadConfig();\n\t\t\tif (generation !== sessionGeneration) return;\n\t\t\tconfigPath = result.path;\n\t\t\tfor (const warning of result.warnings) ctx.ui.notify(warning, \"warning\");\n\t\t\tif (!result.ok) {\n\t\t\t\tinitializationError = formatConfigError(result);\n\t\t\t\tctx.ui.notify(initializationError, \"warning\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thasStoredConfig = true;\n\t\t\ttry {\n\t\t\t\tconst backend = await createBackend(result.config);\n\t\t\t\tif (generation !== sessionGeneration) {\n\t\t\t\t\tawait backend.shutdown().catch(() => undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tactiveConfig = result.config;\n\t\t\t\trecorder = new TraceRecorder(backend, {\n\t\t\t\t\tsessionId: ctx.sessionManager.getSessionId(),\n\t\t\t\t\t...(result.config.userId ? { userId: result.config.userId } : {}),\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tmode: ctx.mode,\n\t\t\t\t\tcaptureContent: result.config.captureContent,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tif (generation !== sessionGeneration) return;\n\t\t\t\tinitializationError = `Langfuse tracing could not start: ${formatError(error, result.config)}`;\n\t\t\t\tctx.ui.notify(initializationError, \"warning\");\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"before_agent_start\", async (event, ctx) => {\n\t\t\tnextAttemptReason = undefined;\n\t\t\tconst activeRecorder = recorder;\n\t\t\tif (!activeRecorder) return;\n\t\t\tconst git = await resolveGit(ctx.cwd).catch(() => undefined);\n\t\t\tif (recorder !== activeRecorder) return;\n\t\t\tactiveRecorder.beginAgent({\n\t\t\t\tprompt: event.prompt,\n\t\t\t\timages: event.images,\n\t\t\t\tmodel: ctx.model\n\t\t\t\t\t? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api }\n\t\t\t\t\t: undefined,\n\t\t\t\tgit,\n\t\t\t\tsnapshot: contextSnapshot(ctx),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"agent_start\", () => {\n\t\t\tif (!recorder) return;\n\t\t\trecorder.beginAttempt(nextAttemptReason ? { reason: nextAttemptReason } : undefined);\n\t\t\tnextAttemptReason = undefined;\n\t\t});\n\n\t\tpi.on(\"turn_start\", (event, ctx) => {\n\t\t\tif (!recorder) return;\n\t\t\tensureActiveRun(recorder, ctx);\n\t\t\trecorder.beginTurn(event.turnIndex);\n\t\t});\n\n\t\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\t\tif (!recorder) return;\n\t\t\tensureActiveRun(recorder, ctx);\n\t\t\trecorder.beginGeneration({\n\t\t\t\tpayload: event.payload,\n\t\t\t\tpayloadStage: \"before_provider_request\",\n\t\t\t\tmodel: ctx.model\n\t\t\t\t\t? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api }\n\t\t\t\t\t: undefined,\n\t\t\t\tthinkingLevel: pi.getThinkingLevel(),\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"after_provider_response\", (event) => {\n\t\t\trecorder?.recordProviderResponse(event.status, event.headers);\n\t\t});\n\n\t\tpi.on(\"message_update\", (event) => {\n\t\t\tif (isRealOutputDelta(event.assistantMessageEvent)) recorder?.markGenerationFirstOutput();\n\t\t});\n\n\t\tpi.on(\"message_end\", (event) => {\n\t\t\tif (event.message.role === \"assistant\") recorder?.markGenerationEnd();\n\t\t});\n\n\t\tpi.on(\"turn_end\", (event) => {\n\t\t\tif (event.message.role === \"assistant\") recorder?.finishAssistant(event.message);\n\t\t\trecorder?.finishTurn(event.turnIndex, {\n\t\t\t\tmessage: event.message,\n\t\t\t\ttoolResultCount: event.toolResults.length,\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"tool_execution_start\", (event) => {\n\t\t\trecorder?.beginTool(event.toolCallId, event.toolName, event.args);\n\t\t});\n\n\t\tpi.on(\"tool_execution_update\", (event) => {\n\t\t\trecorder?.recordToolProgress(event.toolCallId);\n\t\t});\n\n\t\tpi.on(\"tool_result\", (event) => {\n\t\t\trecorder?.recordToolInput(event.toolCallId, event.input);\n\t\t});\n\n\t\tpi.on(\"tool_execution_end\", (event) => {\n\t\t\trecorder?.finishTool(event.toolCallId, {\n\t\t\t\tcontent: event.result.content,\n\t\t\t\tdetails: event.result.details,\n\t\t\t\tisError: event.isError,\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"agent_end\", (event) => {\n\t\t\tconst message = findLastAssistant(event.messages);\n\t\t\trecorder?.finishAttempt(message);\n\t\t});\n\n\t\tpi.on(\"session_before_compact\", (event) => {\n\t\t\trecorder?.beginCompaction({\n\t\t\t\treason: event.reason,\n\t\t\t\twillRetry: event.willRetry,\n\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\tmessagesToSummarize: event.preparation.messagesToSummarize.length,\n\t\t\t\tturnPrefixMessages: event.preparation.turnPrefixMessages.length,\n\t\t\t\tbranchEntries: event.branchEntries.length,\n\t\t\t\tisSplitTurn: event.preparation.isSplitTurn,\n\t\t\t});\n\t\t});\n\n\t\tpi.on(\"session_compact\", (event) => {\n\t\t\tconst entry = event.compactionEntry as typeof event.compactionEntry & {\n\t\t\t\tusage?: Parameters<TraceRecorder[\"finishCompaction\"]>[0][\"usage\"];\n\t\t\t};\n\t\t\trecorder?.finishCompaction({\n\t\t\t\treason: event.reason,\n\t\t\t\twillRetry: event.willRetry,\n\t\t\t\tfromExtension: event.fromExtension,\n\t\t\t\ttokensBefore: entry.tokensBefore,\n\t\t\t\tdetails: entry.details,\n\t\t\t\tusage: entry.usage,\n\t\t\t});\n\t\t\tif (event.willRetry && recorder?.hasActiveTrace()) nextAttemptReason = \"post_compaction\";\n\t\t});\n\n\t\tpi.on(\"agent_settled\", (_event, ctx) => {\n\t\t\trecorder?.settle(contextSnapshot(ctx));\n\t\t\tnextAttemptReason = undefined;\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (event, ctx) => {\n\t\t\tconst generation = ++sessionGeneration;\n\t\t\tmenuController.abort(new DOMException(\"Langfuse session shut down\", \"AbortError\"));\n\t\t\tconst activeRecorder = recorder;\n\t\t\tconst shutdownConfig = activeConfig;\n\t\t\tconst pendingConfigWrite = configWriteQueue;\n\t\t\tconst shutdownSnapshot = activeRecorder ? contextSnapshot(ctx) : undefined;\n\t\t\trecorder = undefined;\n\t\t\tactiveConfig = undefined;\n\t\t\tawait pendingConfigWrite;\n\t\t\tif (!activeRecorder) return;\n\t\t\ttry {\n\t\t\t\tif (event.reason === \"quit\") await activeRecorder.shutdown(shutdownSnapshot);\n\t\t\t\telse {\n\t\t\t\t\tactiveRecorder.interrupt(\n\t\t\t\t\t\t`Pi session ended before settlement (${event.reason}).`,\n\t\t\t\t\t\tshutdownSnapshot,\n\t\t\t\t\t);\n\t\t\t\t\tawait activeRecorder.flush();\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (generation !== sessionGeneration) return;\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Langfuse shutdown export failed: ${formatError(error, shutdownConfig)}`,\n\t\t\t\t\t\"error\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t};\n}\n\nfunction ensureActiveRun(recorder: TraceRecorder, ctx: ExtensionContext): void {\n\tif (!recorder.hasActiveTrace()) {\n\t\trecorder.beginAgent({\n\t\t\tprompt: \"[automatic continuation]\",\n\t\t\tmodel: ctx.model\n\t\t\t\t? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api }\n\t\t\t\t: undefined,\n\t\t\tsnapshot: contextSnapshot(ctx),\n\t\t});\n\t}\n\tif (!recorder.hasActiveAttempt()) recorder.beginAttempt();\n}\n\nfunction contextSnapshot(ctx: ExtensionContext): ContextSnapshot {\n\treturn {\n\t\tleafId:\n\t\t\ttypeof ctx.sessionManager.getLeafId === \"function\"\n\t\t\t\t? ctx.sessionManager.getLeafId()\n\t\t\t\t: undefined,\n\t\tcontextUsage: ctx.getContextUsage(),\n\t};\n}\n\nfunction findLastAssistant<T extends { role?: string }>(messages: readonly T[]): T | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index -= 1) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"assistant\") return message;\n\t}\n\treturn undefined;\n}\n\nfunction isRealOutputDelta(event: { type: string; delta?: unknown }): boolean {\n\treturn (\n\t\t(event.type === \"text_delta\" ||\n\t\t\tevent.type === \"thinking_delta\" ||\n\t\t\tevent.type === \"toolcall_delta\") &&\n\t\ttypeof event.delta === \"string\" &&\n\t\tevent.delta.length > 0\n\t);\n}\n\nconst GIT_LOOKUP_TIMEOUT_MS = 1_000;\nconst MAX_GIT_BRANCH_LENGTH = 256;\n\ntype GitExecutor = ExtensionAPI[\"exec\"];\n\nexport async function resolveGitMetadata(\n\texec: GitExecutor,\n\tcwd: string,\n): Promise<GitMetadata | undefined> {\n\tconst [branchResult, commit] = await Promise.all([\n\t\tresolveGitBranch(exec, cwd),\n\t\tresolveGitCommit(exec, cwd),\n\t]);\n\tif (!branchResult.resolved) return undefined;\n\tif (branchResult.branch) {\n\t\treturn {\n\t\t\tbranch: branchResult.branch,\n\t\t\t...(commit ? { commit } : {}),\n\t\t\tdetached: false,\n\t\t};\n\t}\n\treturn commit ? { commit, detached: true } : undefined;\n}\n\nasync function resolveGitBranch(\n\texec: GitExecutor,\n\tcwd: string,\n): Promise<{ resolved: boolean; branch?: string }> {\n\ttry {\n\t\tconst result = await exec(\"git\", [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n\t\t\tcwd,\n\t\t\ttimeout: GIT_LOOKUP_TIMEOUT_MS,\n\t\t});\n\t\tif (result.killed) return { resolved: false };\n\t\tif (result.code === 1) return { resolved: true };\n\t\tif (result.code !== 0) return { resolved: false };\n\t\tconst branch = normalizeGitBranch(result.stdout);\n\t\treturn branch ? { resolved: true, branch } : { resolved: false };\n\t} catch {\n\t\treturn { resolved: false };\n\t}\n}\n\nasync function resolveGitCommit(exec: GitExecutor, cwd: string): Promise<string | undefined> {\n\ttry {\n\t\tconst result = await exec(\"git\", [\"rev-parse\", \"--verify\", \"--short=12\", \"HEAD\"], {\n\t\t\tcwd,\n\t\t\ttimeout: GIT_LOOKUP_TIMEOUT_MS,\n\t\t});\n\t\tif (result.code !== 0 || result.killed) return undefined;\n\t\tconst commit = result.stdout.trim();\n\t\treturn /^[0-9a-f]{4,64}$/iu.test(commit) ? commit.toLowerCase() : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction normalizeGitBranch(value: string): string | undefined {\n\tconst branch = value.trim();\n\tif (!branch || branch.length > MAX_GIT_BRANCH_LENGTH) return undefined;\n\tfor (const character of branch) {\n\t\tconst code = character.codePointAt(0) ?? 0;\n\t\tif (code <= 31 || code === 127) return undefined;\n\t}\n\treturn branch;\n}\n\nasync function promptForConfig(\n\tctx: ExtensionCommandContext,\n\tcurrent: LangfuseConfig | undefined,\n\tisCurrent: () => boolean,\n): Promise<LangfuseConfigPatch | undefined> {\n\tconst secretKey = await ctx.ui.input(\"Langfuse secret key (leave blank to keep existing):\");\n\tif (!isCurrent()) return undefined;\n\tif (secretKey === undefined) {\n\t\tctx.ui.notify(\"Cancelled\", \"info\");\n\t\treturn undefined;\n\t}\n\tconst publicKey = await ctx.ui.input(\"Langfuse public key (leave blank to keep existing):\");\n\tif (!isCurrent()) return undefined;\n\tif (publicKey === undefined) {\n\t\tctx.ui.notify(\"Cancelled\", \"info\");\n\t\treturn undefined;\n\t}\n\tconst baseUrl = await ctx.ui.input(\n\t\t`Langfuse base URL (leave blank for default ${DEFAULT_BASE_URL}):`,\n\t\tDEFAULT_BASE_URL,\n\t);\n\tif (!isCurrent()) return undefined;\n\tif (baseUrl === undefined) {\n\t\tctx.ui.notify(\"Cancelled\", \"info\");\n\t\treturn undefined;\n\t}\n\n\tconst patch: LangfuseConfigPatch = {\n\t\t...(publicKey.trim() ? { publicKey: publicKey.trim() } : {}),\n\t\t...(secretKey.trim() ? { secretKey: secretKey.trim() } : {}),\n\t\tbaseUrl: baseUrl.trim() || DEFAULT_BASE_URL,\n\t};\n\tconst normalized = normalizeLangfuseConfig({ ...current, ...patch });\n\tif (!normalized.ok) {\n\t\tctx.ui.notify(`Invalid Langfuse config: ${normalized.reason}`, \"error\");\n\t\treturn undefined;\n\t}\n\treturn patch;\n}\n\nfunction formatMenuTitle(\n\tactiveConfig: LangfuseConfig | undefined,\n\tconfigPath: string | undefined,\n\tinitializationError: string | undefined,\n\tconfigurationNotice: string | undefined,\n): string {\n\tconst lines = [\n\t\t\"Langfuse\",\n\t\t\"\",\n\t\t\"Current session:\",\n\t\t` Tracing: ${activeConfig ? \"enabled\" : \"disabled\"}`,\n\t];\n\tif (activeConfig) {\n\t\tlines.push(\n\t\t\t` Endpoint: ${activeConfig.baseUrl}`,\n\t\t\t` Content capture: ${activeConfig.captureContent ? \"enabled\" : \"disabled\"}`,\n\t\t);\n\t} else if (configurationNotice) {\n\t\tlines.push(\" State: tracing remains disabled until Pi restarts.\");\n\t} else if (initializationError) {\n\t\tlines.push(` Reason: ${initializationError}`);\n\t}\n\tlines.push(\n\t\t\"\",\n\t\t\"Agent-directory configuration:\",\n\t\t` Configuration: ${configPath ?? \"unknown\"}`,\n\t\t\" Scope: this Pi agent directory; restart each Pi process to apply changes.\",\n\t);\n\tif (configurationNotice) lines.push(` Pending: ${configurationNotice}`);\n\tlines.push(\"\", \"What do you want to do?\");\n\treturn lines.join(\"\\n\");\n}\n\nfunction formatNonInteractiveStatus(\n\tactiveConfig: LangfuseConfig | undefined,\n\tconfigPath: string | undefined,\n\tinitializationError: string | undefined,\n): string {\n\treturn [\n\t\t\"/langfuse requires interactive UI.\",\n\t\t`Current session tracing: ${activeConfig ? \"enabled\" : \"disabled\"}`,\n\t\t...(activeConfig\n\t\t\t? [\n\t\t\t\t\t`Endpoint: ${activeConfig.baseUrl}`,\n\t\t\t\t\t`Content capture: ${activeConfig.captureContent ? \"enabled\" : \"disabled\"}`,\n\t\t\t\t]\n\t\t\t: initializationError\n\t\t\t\t? [`Reason: ${initializationError}`]\n\t\t\t\t: []),\n\t\t`Configuration: ${configPath ?? \"unknown\"}`,\n\t\t\"Edit the private config manually, then restart each Pi process to apply it to subsequent sessions.\",\n\t].join(\"\\n\");\n}\n\nfunction formatHelp(configPath: string | undefined): string {\n\treturn [\n\t\t\"Langfuse setup and privacy:\",\n\t\t\"Run /langfuse in interactive Pi to manage tracing for the current session.\",\n\t\t`Configuration: ${configPath ?? \"pi-langfuse.json\"}`,\n\t\t\"The file belongs to this Pi agent directory; restart each Pi process after changing it.\",\n\t\t\"Trace content may contain prompts, responses, tool arguments, tool results, and source code.\",\n\t\t\"Git branch, commit, cwd, model, and usage remain in metadata when content capture is disabled.\",\n\t\t'Use \"captureContent\": false in the private config to export metadata only.',\n\t].join(\"\\n\");\n}\n\nfunction formatConfigError(result: Extract<LangfuseConfigResult, { ok: false }>): string {\n\tconst setupHint = result.reason.startsWith(\"Configuration file not found:\")\n\t\t? \" Run /langfuse and choose Set up Langfuse.\"\n\t\t: \"\";\n\treturn `Langfuse tracing is disabled: ${result.reason}${setupHint}`;\n}\n\nfunction formatError(error: unknown, config?: LangfuseConfigPatch): string {\n\tlet message = error instanceof Error ? error.message : String(error);\n\tconst secrets = [config?.publicKey, config?.secretKey]\n\t\t.filter((secret): secret is string => Boolean(secret))\n\t\t.sort((left, right) => right.length - left.length);\n\tfor (const secret of secrets) {\n\t\tmessage = message.split(secret).join(\"[LANGFUSE_KEY_REDACTED]\");\n\t}\n\treturn message;\n}\n\nexport default createLangfuseExtension();\n"],
5
- "mappings": "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",
6
- "names": ["truncateString", "byteLength", "formatError"]
3
+ "sources": ["../src/git.ts", "../src/sanitizer.ts", "../src/tracing.ts", "../src/pi-session.ts", "../src/langfuse.ts", "../src/public-api.ts"],
4
+ "sourcesContent": ["import type { ExtensionAPI } from \"@earendil-works/pi-coding-agent\";\nimport type { GitMetadata } from \"./tracing.js\";\n\nconst GIT_LOOKUP_TIMEOUT_MS = 1_000;\nconst MAX_GIT_BRANCH_LENGTH = 256;\n\ntype GitExecutor = ExtensionAPI[\"exec\"];\n\nexport async function resolveGitMetadata(exec: GitExecutor, cwd: string): Promise<GitMetadata | undefined> {\n const [branchResult, commit] = await Promise.all([resolveGitBranch(exec, cwd), resolveGitCommit(exec, cwd)]);\n if (!branchResult.resolved) return undefined;\n if (branchResult.branch) {\n return {\n branch: branchResult.branch,\n ...(commit ? { commit } : {}),\n detached: false,\n };\n }\n return commit ? { commit, detached: true } : undefined;\n}\n\nasync function resolveGitBranch(exec: GitExecutor, cwd: string): Promise<{ resolved: boolean; branch?: string }> {\n try {\n const result = await exec(\"git\", [\"symbolic-ref\", \"--quiet\", \"--short\", \"HEAD\"], {\n cwd,\n timeout: GIT_LOOKUP_TIMEOUT_MS,\n });\n if (result.killed) return { resolved: false };\n if (result.code === 1) return { resolved: true };\n if (result.code !== 0) return { resolved: false };\n const branch = normalizeGitBranch(result.stdout);\n return branch ? { resolved: true, branch } : { resolved: false };\n } catch {\n return { resolved: false };\n }\n}\n\nasync function resolveGitCommit(exec: GitExecutor, cwd: string): Promise<string | undefined> {\n try {\n const result = await exec(\"git\", [\"rev-parse\", \"--verify\", \"--short=12\", \"HEAD\"], {\n cwd,\n timeout: GIT_LOOKUP_TIMEOUT_MS,\n });\n if (result.code !== 0 || result.killed) return undefined;\n const commit = result.stdout.trim();\n return /^[0-9a-f]{4,64}$/iu.test(commit) ? commit.toLowerCase() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction normalizeGitBranch(value: string): string | undefined {\n const branch = value.trim();\n if (!branch || branch.length > MAX_GIT_BRANCH_LENGTH) return undefined;\n for (const character of branch) {\n const code = character.codePointAt(0) ?? 0;\n if (code <= 31 || code === 127) return undefined;\n }\n return branch;\n}\n", "export const MAX_CAPTURE_BYTES = 64 * 1024;\nconst MAX_STRING_LENGTH = 50_000;\nconst MAX_COLLECTION_LENGTH = 200;\nconst MAX_DEPTH = 12;\nconst TRUNCATED = \"[truncated: content budget exceeded]\";\nconst BASE64_DATA_URI = /data:[^,\\s\"'`]*;base64,[^\\s\"'`]*/gi;\nconst BASE64_DATA_URI_OMITTED = \"[base64 data URI omitted]\";\nconst OPAQUE_SIGNATURE_KEYS = new Set([\"thinkingSignature\", \"textSignature\", \"thoughtSignature\"]);\n\nexport function sanitizeTraceValue(value: unknown): unknown {\n const budget = { remaining: MAX_CAPTURE_BYTES };\n const sanitized = sanitize(value, new WeakSet<object>(), 0, budget);\n return serializedBytes(sanitized) <= MAX_CAPTURE_BYTES ? sanitized : TRUNCATED;\n}\n\nfunction sanitize(value: unknown, active: WeakSet<object>, depth: number, budget: { remaining: number }): unknown {\n if (budget.remaining <= byteLength(TRUNCATED)) return TRUNCATED;\n if (value === null || typeof value === \"number\" || typeof value === \"boolean\") {\n return consume(value, budget);\n }\n if (typeof value === \"string\") {\n return consume(sanitizeString(value, Math.min(MAX_STRING_LENGTH, budget.remaining)), budget);\n }\n if (typeof value === \"bigint\") return consume(value.toString(), budget);\n if (typeof value === \"undefined\" || typeof value === \"function\" || typeof value === \"symbol\") {\n return undefined;\n }\n if (value instanceof Date) {\n return consume(Number.isNaN(value.getTime()) ? \"[invalid date]\" : value.toISOString(), budget);\n }\n if (value instanceof Error) {\n return sanitize({ name: value.name, message: value.message }, active, depth, budget);\n }\n if (depth >= MAX_DEPTH) return consume(\"[maximum depth reached]\", budget);\n if (active.has(value)) return consume(\"[circular]\", budget);\n active.add(value);\n\n let result: unknown;\n if (Array.isArray(value)) {\n const items: unknown[] = [];\n for (const item of value.slice(0, MAX_COLLECTION_LENGTH)) {\n if (budget.remaining <= byteLength(TRUNCATED)) break;\n items.push(sanitize(item, active, depth + 1, budget));\n }\n if (items.length < value.length) items.push(`[${value.length - items.length} items omitted]`);\n result = items;\n } else {\n const record = value as Record<string, unknown>;\n const output: Record<string, unknown> = {};\n const objectType = readProperty(record, \"type\").value;\n const redactData = objectType === \"image\" || objectType === \"base64\";\n let visited = 0;\n let processed = 0;\n let omitted = false;\n try {\n for (const key in record) {\n if (visited >= MAX_COLLECTION_LENGTH || budget.remaining <= byteLength(TRUNCATED)) {\n omitted = true;\n break;\n }\n visited += 1;\n if (!Object.hasOwn(record, key) || OPAQUE_SIGNATURE_KEYS.has(key)) continue;\n const keyBudget = Math.min(MAX_STRING_LENGTH, Math.max(0, budget.remaining - 4));\n if (key.length > keyBudget) {\n omitted = true;\n break;\n }\n const keyBytes = byteLength(key);\n if (keyBytes > keyBudget) {\n omitted = true;\n break;\n }\n const sanitizedKey = sanitizeString(key, keyBudget);\n budget.remaining -= byteLength(sanitizedKey) + 4;\n const property = readProperty(record, key);\n if (redactData && key === \"data\") {\n output[sanitizedKey] = consume(\"[base64 omitted]\", budget);\n } else if (!property.ok) output[sanitizedKey] = consume(\"[unreadable property]\", budget);\n else output[sanitizedKey] = sanitize(property.value, active, depth + 1, budget);\n processed += 1;\n }\n } catch {\n if (processed === 0) {\n active.delete(value);\n return consume(\"[unreadable object]\", budget);\n }\n omitted = true;\n }\n if (omitted) output.$truncated = \"additional object entries omitted\";\n result = output;\n }\n active.delete(value);\n return result;\n}\n\nfunction readProperty(\n record: Record<string, unknown>,\n key: string,\n): { ok: true; value: unknown } | { ok: false; value?: undefined } {\n try {\n return { ok: true, value: record[key] };\n } catch {\n return { ok: false };\n }\n}\n\nfunction consume<T>(value: T, budget: { remaining: number }): T | string {\n const size = serializedBytes(value);\n if (size > budget.remaining) {\n budget.remaining -= byteLength(TRUNCATED);\n return TRUNCATED;\n }\n budget.remaining -= size;\n return value;\n}\n\nfunction sanitizeString(value: string, maxBytes: number): string {\n return truncateString(value, maxBytes).replace(BASE64_DATA_URI, BASE64_DATA_URI_OMITTED);\n}\n\nfunction truncateString(value: string, maxBytes: number): string {\n const boundedPrefix = value.slice(0, maxBytes);\n if (boundedPrefix.length === value.length && byteLength(boundedPrefix) <= maxBytes) {\n return boundedPrefix;\n }\n const suffix = \"\u2026 [truncated]\";\n const target = Math.max(0, maxBytes - byteLength(suffix) - 2);\n let bytes = 0;\n let output = \"\";\n for (const character of boundedPrefix) {\n const size = byteLength(character);\n if (bytes + size > target) break;\n output += character;\n bytes += size;\n }\n return `${output}${suffix}`;\n}\n\nfunction serializedBytes(value: unknown): number {\n return byteLength(JSON.stringify(value) ?? \"null\");\n}\n\nfunction byteLength(value: string): number {\n return Buffer.byteLength(value, \"utf8\");\n}\n", "import { sanitizeTraceValue } from \"./sanitizer.js\";\n\nexport { MAX_CAPTURE_BYTES, sanitizeTraceValue } from \"./sanitizer.js\";\n\nexport const TRACE_SCHEMA_VERSION = \"2\";\nconst MAX_HEADER_VALUE_LENGTH = 1_024;\nconst CONTENT_DISABLED = \"[content capture disabled]\";\nconst ALLOWED_RESPONSE_HEADERS = new Set([\n \"anthropic-ratelimit-requests-limit\",\n \"anthropic-ratelimit-requests-remaining\",\n \"anthropic-ratelimit-requests-reset\",\n \"anthropic-ratelimit-tokens-limit\",\n \"anthropic-ratelimit-tokens-remaining\",\n \"anthropic-ratelimit-tokens-reset\",\n \"cf-ray\",\n \"openai-request-id\",\n \"request-id\",\n \"retry-after\",\n \"x-amzn-requestid\",\n \"x-request-id\",\n \"x-ratelimit-limit-requests\",\n \"x-ratelimit-limit-tokens\",\n \"x-ratelimit-remaining-requests\",\n \"x-ratelimit-remaining-tokens\",\n \"x-ratelimit-reset-requests\",\n \"x-ratelimit-reset-tokens\",\n]);\n\nexport interface ObservationAttributes {\n input?: unknown;\n output?: unknown;\n metadata?: Record<string, unknown>;\n level?: \"DEBUG\" | \"DEFAULT\" | \"WARNING\" | \"ERROR\";\n statusMessage?: string;\n completionStartTime?: Date;\n model?: string;\n modelParameters?: Record<string, string | number>;\n usageDetails?: Record<string, number>;\n costDetails?: Record<string, number>;\n version?: string;\n name?: string;\n sessionId?: string;\n userId?: string;\n tags?: string[];\n}\n\nexport interface Observation {\n readonly traceId?: string;\n update(attributes: ObservationAttributes): Observation;\n updateTrace?(attributes: ObservationAttributes): Observation;\n end(endTime?: number): Observation;\n}\n\nexport type ObservationType = \"agent\" | \"generation\" | \"span\" | \"tool\";\n\nexport interface TraceBackend {\n start(\n name: string,\n attributes: ObservationAttributes,\n options: { asType: ObservationType; parent?: Observation; startTime?: Date },\n ): Observation;\n forceFlush(): Promise<void>;\n shutdown(): Promise<void>;\n}\n\nexport interface TraceRecorderOptions {\n sessionId: string;\n userId?: string;\n cwd: string;\n mode: string;\n captureContent: boolean;\n traceName?: string;\n tags?: readonly string[];\n metadata?: Readonly<Record<string, unknown>>;\n onTraceId?: (traceId: string) => void;\n}\n\ninterface ModelDescriptor {\n provider?: string;\n id?: string;\n api?: string;\n}\n\nexport interface GitMetadata {\n branch?: string;\n commit?: string;\n detached: boolean;\n}\n\nexport interface ContextSnapshot {\n leafId?: string | null;\n contextUsage?: {\n tokens: number | null;\n contextWindow: number;\n percent: number | null;\n };\n}\n\ninterface BeginAgentInput {\n prompt: unknown;\n images?: unknown;\n model?: ModelDescriptor;\n git?: GitMetadata;\n snapshot?: ContextSnapshot;\n requestId?: string;\n}\n\ninterface AttemptInput {\n reason?: string;\n}\n\ninterface GenerationInput {\n startedAt?: number;\n payload?: unknown;\n payloadStage?: \"before_provider_request\";\n model?: ModelDescriptor;\n thinkingLevel?: string;\n}\n\ninterface AssistantMessage {\n role: string;\n content?: unknown;\n provider?: string;\n api?: string;\n model?: string;\n responseModel?: string;\n responseId?: string;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n cacheWrite1h?: number;\n reasoning?: number;\n totalTokens?: number;\n cost?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n total?: number;\n };\n };\n stopReason?: string;\n errorMessage?: string;\n}\n\ninterface ToolResult {\n content?: unknown;\n details?: unknown;\n isError?: boolean;\n}\n\ninterface TurnResult {\n message: { role: string; stopReason?: string; errorMessage?: string };\n toolResultCount: number;\n}\n\ninterface CompactionStart {\n reason: string;\n willRetry: boolean;\n tokensBefore?: number;\n messagesToSummarize: number;\n turnPrefixMessages: number;\n branchEntries: number;\n isSplitTurn: boolean;\n}\n\ninterface CompactionFinish {\n reason: string;\n willRetry: boolean;\n fromExtension: boolean;\n tokensBefore?: number;\n details?: unknown;\n usage?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n totalTokens?: number;\n cost?: {\n input?: number;\n output?: number;\n cacheRead?: number;\n cacheWrite?: number;\n total?: number;\n };\n };\n}\n\ntype Outcome = \"success\" | \"error\" | \"aborted\" | \"length\" | \"interrupted\";\n\ninterface GenerationState {\n observation: Observation;\n endTime?: number;\n completionStartTime?: number;\n requestMetadata: Record<string, unknown>;\n statuses: number[];\n headers: Record<string, string>;\n}\n\ninterface ToolState {\n observation: Observation;\n startedAt: number;\n progressUpdates: number;\n firstProgressAt?: number;\n}\n\ninterface CompactionState {\n observation: Observation;\n}\n\ninterface Counters {\n attempts: number;\n turns: number;\n generations: number;\n tools: number;\n toolErrors: number;\n compactions: number;\n recoveredErrors: number;\n failedAttempts: number;\n}\n\nexport class TraceRecorder {\n private root: Observation | undefined;\n private attempt: Observation | undefined;\n private attemptIndex: number | undefined;\n private turn: Observation | undefined;\n private turnIndex: number | undefined;\n private generation: GenerationState | undefined;\n private readonly tools = new Map<string, ToolState>();\n private readonly duplicateToolIds = new Set<string>();\n private compaction: CompactionState | undefined;\n private lastOutput: unknown;\n private lastAssistant: AssistantMessage | undefined;\n private lastAttemptOutcome: Outcome | undefined;\n private unresolvedToolErrors = 0;\n private startSnapshot: ContextSnapshot | undefined;\n private counters: Counters = emptyCounters();\n\n constructor(\n private readonly backend: TraceBackend,\n private readonly context: TraceRecorderOptions,\n ) {}\n\n private startObservation(\n name: string,\n attributes: ObservationAttributes,\n options: { asType: ObservationType; parent?: Observation; startTime?: Date },\n ): Observation {\n const { sessionId, userId } = this.context;\n return this.backend.start(name, { ...attributes, sessionId, ...(userId ? { userId } : {}) }, options);\n }\n\n hasActiveTrace(): boolean {\n return this.root !== undefined;\n }\n\n hasActiveAttempt(): boolean {\n return this.attempt !== undefined;\n }\n\n beginAgent(input: BeginAgentInput): void {\n if (this.root) this.closeActiveTrace(\"Interrupted by a new Pi run.\", undefined, \"interrupted\");\n\n this.lastOutput = undefined;\n this.lastAssistant = undefined;\n this.lastAttemptOutcome = undefined;\n this.unresolvedToolErrors = 0;\n this.duplicateToolIds.clear();\n this.startSnapshot = input.snapshot;\n this.counters = emptyCounters();\n const traceInput = this.capture({\n prompt: input.prompt,\n ...(hasItems(input.images) ? { images: input.images } : {}),\n });\n const metadata: Record<string, unknown> = {\n ...customTraceMetadata(this.context.metadata),\n \"pi.cwd\": this.context.cwd,\n ...(input.git?.branch ? { \"pi.git.branch\": input.git.branch } : {}),\n ...(input.git?.commit ? { \"pi.git.commit\": input.git.commit } : {}),\n ...(input.git ? { \"pi.git.detached\": input.git.detached } : {}),\n \"pi.mode\": this.context.mode,\n ...(input.model?.id ? { \"pi.model\": input.model.id } : {}),\n ...(input.model?.provider ? { \"pi.provider\": input.model.provider } : {}),\n ...(input.requestId ? { \"pi.request.id\": input.requestId } : {}),\n \"pi.session.id\": this.context.sessionId,\n \"pi.trace.schema_version\": Number(TRACE_SCHEMA_VERSION),\n ...snapshotMetadata(\"start\", input.snapshot),\n };\n const attributes = { input: traceInput, metadata, version: TRACE_SCHEMA_VERSION };\n const gitTag = input.git?.branch ? `branch:${input.git.branch}` : input.git?.detached ? \"git:detached\" : undefined;\n\n this.root = this.startObservation(\"pi.agent\", attributes, { asType: \"agent\" });\n this.root.updateTrace?.({\n name: normalizeTraceName(this.context.traceName),\n sessionId: this.context.sessionId,\n ...(this.context.userId ? { userId: this.context.userId } : {}),\n version: TRACE_SCHEMA_VERSION,\n input: traceInput,\n metadata,\n tags: traceTags(this.context.tags, gitTag),\n });\n const traceId = this.root.traceId;\n if (traceId && this.context.onTraceId) {\n try {\n void Promise.resolve(this.context.onTraceId(traceId)).catch(() => undefined);\n } catch {\n // Host callbacks must not corrupt observation lifecycle state.\n }\n }\n }\n\n beginAttempt(input: AttemptInput = {}): void {\n if (!this.root) return;\n if (this.attempt) {\n this.closeAttempt(undefined, \"Interrupted by the next Pi attempt.\", \"interrupted\");\n }\n const index = this.counters.attempts;\n this.counters.attempts += 1;\n this.lastAssistant = undefined;\n this.unresolvedToolErrors = 0;\n this.attemptIndex = index;\n this.attempt = this.startObservation(\n \"pi.attempt\",\n {\n metadata: {\n \"pi.attempt.index\": index,\n ...(input.reason ? { \"pi.attempt.reason\": input.reason } : {}),\n },\n version: TRACE_SCHEMA_VERSION,\n },\n { asType: \"span\", parent: this.root },\n );\n }\n\n finishAttempt(message?: AssistantMessage): void {\n if (message?.role === \"assistant\") this.finishAssistant(message);\n if (!this.attempt) return;\n const outcome = this.unresolvedToolErrors > 0 ? \"error\" : classifyOutcome(message);\n this.closeAttempt(\n message,\n this.unresolvedToolErrors > 0 ? \"Pi attempt ended after a tool failure.\" : undefined,\n outcome,\n );\n }\n\n beginTurn(turnIndex: number): void {\n if (!this.root) return;\n if (this.turn) this.closeTurn(\"Interrupted by the next Pi turn.\", \"ERROR\");\n this.counters.turns += 1;\n this.turnIndex = turnIndex;\n this.turn = this.startObservation(\n \"pi.turn\",\n { metadata: { \"pi.turn.index\": turnIndex }, version: TRACE_SCHEMA_VERSION },\n { asType: \"span\", parent: this.attempt ?? this.root },\n );\n }\n\n finishTurn(turnIndex: number, result: TurnResult): void {\n if (!this.turn) return;\n this.closeGeneration(\"Turn ended without a finalized assistant message.\");\n this.closeTools(\"Tool span ended when the Pi turn finished.\");\n\n const mismatched = this.turnIndex !== turnIndex;\n const outcome = classifyOutcome(result.message);\n this.turn.update({\n metadata: {\n \"pi.turn.index\": this.turnIndex ?? turnIndex,\n \"pi.turn.tool_result_count\": result.toolResultCount,\n ...(result.message.stopReason ? { \"pi.turn.stop_reason\": result.message.stopReason } : {}),\n },\n ...(mismatched && outcome === \"success\"\n ? {\n level: \"WARNING\" as const,\n statusMessage: `Turn ${turnIndex} ended while turn ${this.turnIndex} was active.`,\n }\n : severityForOutcome(outcome, result.message.errorMessage)),\n });\n this.turn.end();\n this.turn = undefined;\n this.turnIndex = undefined;\n }\n\n beginGeneration(input: GenerationInput = {}): void {\n if (!this.root) return;\n this.closeGeneration(\"Interrupted by the next provider request.\");\n if (this.unresolvedToolErrors > 0) {\n this.counters.recoveredErrors += this.unresolvedToolErrors;\n this.unresolvedToolErrors = 0;\n }\n this.counters.generations += 1;\n const requestMetadata: Record<string, unknown> = {\n ...(input.payloadStage ? { \"pi.request.payload_stage\": input.payloadStage } : {}),\n ...(input.model?.provider ? { \"pi.request.provider\": input.model.provider } : {}),\n ...(input.model?.id ? { \"pi.request.model\": input.model.id } : {}),\n ...(input.model?.api ? { \"pi.request.api\": input.model.api } : {}),\n ...(input.thinkingLevel ? { \"pi.request.thinking_level\": input.thinkingLevel } : {}),\n };\n const observation = this.startObservation(\n \"pi.llm\",\n {\n ...(input.payload !== undefined ? { input: this.capture(input.payload) } : {}),\n ...(input.model?.id ? { model: input.model.id } : {}),\n ...(input.thinkingLevel ? { modelParameters: { thinking_level: input.thinkingLevel } } : {}),\n ...(Object.keys(requestMetadata).length > 0 ? { metadata: requestMetadata } : {}),\n version: TRACE_SCHEMA_VERSION,\n },\n {\n asType: \"generation\",\n parent: this.turn ?? this.attempt ?? this.root,\n ...(input.startedAt === undefined ? {} : { startTime: new Date(input.startedAt) }),\n },\n );\n this.generation = {\n observation,\n requestMetadata,\n statuses: [],\n headers: {},\n };\n }\n\n recordProviderResponse(status: number, headers: Record<string, string> = {}): void {\n if (!this.generation) return;\n this.generation.statuses.push(status);\n Object.assign(this.generation.headers, allowlistedResponseHeaders(headers));\n }\n\n markGenerationFirstOutput(timestamp = Date.now()): void {\n if (this.generation && this.generation.completionStartTime === undefined) {\n this.generation.completionStartTime = timestamp;\n }\n }\n\n markGenerationEnd(endTime = Date.now()): void {\n if (this.generation && this.generation.endTime === undefined) {\n this.generation.endTime = endTime;\n }\n }\n\n finishAssistant(message: AssistantMessage): void {\n if (message.role !== \"assistant\") return;\n this.lastAssistant = message;\n this.lastOutput = this.capture(message.content);\n if (!this.generation) return;\n\n const state = this.generation;\n const usageDetails = numericRecord({\n input: message.usage?.input,\n output: message.usage?.output,\n cache_read_input_tokens: message.usage?.cacheRead,\n cache_creation_input_tokens: message.usage?.cacheWrite,\n total: message.usage?.totalTokens,\n });\n const costDetails = positiveNumericRecord({\n input: message.usage?.cost?.input,\n output: message.usage?.cost?.output,\n cache_read: message.usage?.cost?.cacheRead,\n cache_write: message.usage?.cost?.cacheWrite,\n total: message.usage?.cost?.total,\n });\n const outcome = classifyOutcome(message);\n const responseModel = message.responseModel ?? message.model;\n const httpMetadata = generationHttpMetadata(state);\n const recoveredStatuses = state.statuses.filter((status) => status >= 400).length;\n if (outcome === \"success\" && recoveredStatuses > 0) {\n this.counters.recoveredErrors += recoveredStatuses;\n }\n state.observation.update({\n output: this.lastOutput,\n ...(state.completionStartTime !== undefined ? { completionStartTime: new Date(state.completionStartTime) } : {}),\n ...(responseModel ? { model: responseModel } : {}),\n ...(Object.keys(usageDetails).length > 0 ? { usageDetails } : {}),\n ...(Object.keys(costDetails).length > 0 ? { costDetails } : {}),\n metadata: {\n ...state.requestMetadata,\n ...httpMetadata,\n ...(message.provider ? { \"pi.provider\": message.provider, \"pi.response.provider\": message.provider } : {}),\n ...(message.api ? { \"pi.response.api\": message.api } : {}),\n ...(responseModel ? { \"pi.response.model\": responseModel } : {}),\n ...(message.responseId ? { \"pi.response.id\": message.responseId } : {}),\n ...(message.responseModel && message.model && message.responseModel !== message.model\n ? { \"pi.requested_model\": message.model }\n : {}),\n ...(message.stopReason ? { \"pi.stop_reason\": message.stopReason } : {}),\n ...(finiteNumber(message.usage?.reasoning) ? { \"pi.usage.reasoning_tokens\": message.usage.reasoning } : {}),\n ...(finiteNumber(message.usage?.cacheWrite1h)\n ? { \"pi.usage.cache_write_1h_tokens\": message.usage.cacheWrite1h }\n : {}),\n },\n ...severityForOutcome(outcome, message.errorMessage),\n });\n state.observation.end(state.endTime);\n this.generation = undefined;\n }\n\n beginTool(toolCallId: string, toolName: string, args?: unknown, startedAt = Date.now()): void {\n if (!this.root) return;\n this.counters.tools += 1;\n if (this.duplicateToolIds.has(toolCallId)) {\n this.counters.toolErrors += 1;\n const duplicate = this.startToolObservation(toolCallId, toolName, args);\n duplicate.update({\n level: \"ERROR\",\n statusMessage: \"Duplicate tool call ID cannot be correlated safely.\",\n });\n duplicate.end();\n return;\n }\n\n const existing = this.tools.get(toolCallId);\n if (existing) {\n existing.observation.update({\n level: \"ERROR\",\n statusMessage: \"Duplicate tool execution started.\",\n });\n existing.observation.end();\n this.tools.delete(toolCallId);\n this.counters.toolErrors += 2;\n const duplicate = this.startToolObservation(toolCallId, toolName, args);\n duplicate.update({\n level: \"ERROR\",\n statusMessage: \"Duplicate tool call ID cannot be correlated safely.\",\n });\n duplicate.end();\n this.duplicateToolIds.add(toolCallId);\n return;\n }\n\n this.tools.set(toolCallId, {\n observation: this.startToolObservation(toolCallId, toolName, args),\n startedAt,\n progressUpdates: 0,\n });\n }\n\n recordToolInput(toolCallId: string, input: unknown): void {\n if (input === undefined || this.duplicateToolIds.has(toolCallId)) return;\n this.tools.get(toolCallId)?.observation.update({ input: this.capture(input) });\n }\n\n recordToolProgress(toolCallId: string, timestamp = Date.now()): void {\n const tool = this.tools.get(toolCallId);\n if (!tool) return;\n tool.progressUpdates += 1;\n tool.firstProgressAt ??= timestamp;\n }\n\n finishTool(toolCallId: string, result: ToolResult): void {\n if (this.duplicateToolIds.has(toolCallId)) return;\n const tool = this.tools.get(toolCallId);\n if (!tool) return;\n if (result.isError) {\n this.counters.toolErrors += 1;\n this.unresolvedToolErrors += 1;\n }\n tool.observation.update({\n output: this.capture({ content: result.content, details: result.details }),\n metadata: {\n \"pi.tool.progress_update_count\": tool.progressUpdates,\n ...(tool.firstProgressAt !== undefined\n ? {\n \"pi.tool.time_to_first_progress_ms\": Math.max(0, tool.firstProgressAt - tool.startedAt),\n }\n : {}),\n },\n ...(result.isError ? { level: \"ERROR\" as const, statusMessage: \"Pi tool execution failed.\" } : {}),\n });\n tool.observation.end();\n this.tools.delete(toolCallId);\n }\n\n beginCompaction(input: CompactionStart): void {\n if (!this.root) return;\n this.closeCompaction(\"Interrupted by another Pi compaction.\");\n this.counters.compactions += 1;\n this.compaction = {\n observation: this.startObservation(\n \"pi.compaction\",\n {\n metadata: {\n \"pi.compaction.reason\": input.reason,\n \"pi.compaction.will_retry\": input.willRetry,\n ...(finiteNumber(input.tokensBefore) ? { \"pi.compaction.tokens_before\": input.tokensBefore } : {}),\n \"pi.compaction.messages_to_summarize\": input.messagesToSummarize,\n \"pi.compaction.turn_prefix_messages\": input.turnPrefixMessages,\n \"pi.compaction.branch_entries\": input.branchEntries,\n \"pi.compaction.is_split_turn\": input.isSplitTurn,\n },\n version: TRACE_SCHEMA_VERSION,\n },\n { asType: \"span\", parent: this.root },\n ),\n };\n }\n\n finishCompaction(input: CompactionFinish): void {\n if (!this.compaction) return;\n const details = structuralCompactionDetails(input.details);\n const usage = numericRecord({\n input: input.usage?.input,\n output: input.usage?.output,\n cache_read: input.usage?.cacheRead,\n cache_write: input.usage?.cacheWrite,\n total: input.usage?.totalTokens,\n });\n const cost = positiveNumericRecord({\n input: input.usage?.cost?.input,\n output: input.usage?.cost?.output,\n cache_read: input.usage?.cost?.cacheRead,\n cache_write: input.usage?.cost?.cacheWrite,\n total: input.usage?.cost?.total,\n });\n this.compaction.observation.update({\n metadata: {\n \"pi.compaction.reason\": input.reason,\n \"pi.compaction.will_retry\": input.willRetry,\n \"pi.compaction.from_extension\": input.fromExtension,\n ...(finiteNumber(input.tokensBefore) ? { \"pi.compaction.tokens_before\": input.tokensBefore } : {}),\n ...details,\n ...prefixRecord(\"pi.compaction.usage\", usage),\n ...prefixRecord(\"pi.compaction.cost\", cost),\n },\n });\n this.compaction.observation.end();\n this.compaction = undefined;\n }\n\n settle(snapshot?: ContextSnapshot): void {\n this.closeActiveTrace(undefined, snapshot);\n }\n\n interrupt(statusMessage: string, snapshot?: ContextSnapshot): void {\n this.closeActiveTrace(statusMessage, snapshot, \"interrupted\");\n }\n\n dispose(statusMessage = \"Pi session ended before the active trace settled.\", snapshot?: ContextSnapshot): void {\n this.closeActiveTrace(statusMessage, snapshot, \"interrupted\");\n }\n\n private closeActiveTrace(statusMessage?: string, snapshot?: ContextSnapshot, forcedOutcome?: Outcome): void {\n this.closeTurn(statusMessage ?? \"Pi turn ended when the agent run settled.\");\n this.closeAttempt(undefined, statusMessage, forcedOutcome ?? \"interrupted\");\n this.closeCompaction(statusMessage ?? \"Pi compaction ended when the agent run settled.\");\n\n if (!this.root) return;\n const baseOutcome = forcedOutcome ?? this.lastAttemptOutcome ?? classifyOutcome(this.lastAssistant);\n const recoveredErrorCount =\n this.counters.recoveredErrors + (baseOutcome === \"success\" ? this.counters.failedAttempts : 0);\n const traceOutcome = baseOutcome === \"success\" && recoveredErrorCount > 0 ? \"recovered_success\" : baseOutcome;\n const finalMetadata: Record<string, unknown> = {\n \"pi.trace.schema_version\": Number(TRACE_SCHEMA_VERSION),\n \"pi.trace.outcome\": traceOutcome,\n ...(this.lastAssistant?.stopReason ? { \"pi.trace.stop_reason\": this.lastAssistant.stopReason } : {}),\n \"pi.trace.attempt_count\": this.counters.attempts,\n \"pi.trace.turn_count\": this.counters.turns,\n \"pi.trace.generation_count\": this.counters.generations,\n \"pi.trace.tool_count\": this.counters.tools,\n \"pi.trace.tool_error_count\": this.counters.toolErrors,\n \"pi.trace.compaction_count\": this.counters.compactions,\n \"pi.trace.recovered_error_count\": recoveredErrorCount,\n ...snapshotMetadata(\"start\", this.startSnapshot),\n ...snapshotMetadata(\"end\", snapshot),\n };\n const finalAttributes: ObservationAttributes = {\n ...(this.lastOutput !== undefined ? { output: this.lastOutput } : {}),\n metadata: finalMetadata,\n ...severityForOutcome(baseOutcome, statusMessage ?? this.lastAssistant?.errorMessage),\n };\n this.root.update(finalAttributes);\n this.root.updateTrace?.({\n ...(this.lastOutput !== undefined ? { output: this.lastOutput } : {}),\n metadata: finalMetadata,\n version: TRACE_SCHEMA_VERSION,\n });\n this.root.end();\n this.root = undefined;\n this.lastOutput = undefined;\n this.lastAssistant = undefined;\n this.lastAttemptOutcome = undefined;\n this.unresolvedToolErrors = 0;\n this.duplicateToolIds.clear();\n this.startSnapshot = undefined;\n }\n\n private closeAttempt(message?: AssistantMessage, statusMessage?: string, forcedOutcome?: Outcome): void {\n if (!this.attempt) return;\n this.closeTurn(statusMessage ?? \"Pi turn ended when the attempt finished.\");\n const outcome = forcedOutcome ?? classifyOutcome(message);\n if (outcome === \"error\") this.counters.failedAttempts += 1;\n this.lastAttemptOutcome = outcome;\n this.attempt.update({\n ...(message?.content !== undefined ? { output: this.capture(message.content) } : {}),\n metadata: {\n \"pi.attempt.index\": this.attemptIndex ?? Math.max(0, this.counters.attempts - 1),\n \"pi.attempt.outcome\": outcome,\n ...(message?.stopReason ? { \"pi.attempt.stop_reason\": message.stopReason } : {}),\n },\n ...severityForOutcome(outcome, statusMessage ?? message?.errorMessage),\n });\n this.attempt.end();\n this.attempt = undefined;\n this.attemptIndex = undefined;\n this.unresolvedToolErrors = 0;\n }\n\n private startToolObservation(toolCallId: string, toolName: string, args?: unknown): Observation {\n return this.startObservation(\n `pi.tool.${toolName}`,\n {\n ...(args !== undefined ? { input: this.capture(args) } : {}),\n metadata: { \"pi.tool.call_id\": toolCallId, \"pi.tool.name\": toolName },\n version: TRACE_SCHEMA_VERSION,\n },\n { asType: \"tool\", parent: this.turn ?? this.attempt ?? this.root },\n );\n }\n\n private closeTurn(statusMessage: string, generationLevel: \"ERROR\" | \"WARNING\" = \"WARNING\"): void {\n this.closeGeneration(statusMessage, generationLevel);\n this.closeTools(statusMessage);\n if (!this.turn) return;\n this.turn.update({ level: \"WARNING\", statusMessage });\n this.turn.end();\n this.turn = undefined;\n this.turnIndex = undefined;\n }\n\n private closeTools(statusMessage: string): void {\n for (const tool of this.tools.values()) {\n tool.observation.update({\n level: \"WARNING\",\n statusMessage,\n metadata: {\n \"pi.tool.progress_update_count\": tool.progressUpdates,\n ...(tool.firstProgressAt !== undefined\n ? {\n \"pi.tool.time_to_first_progress_ms\": Math.max(0, tool.firstProgressAt - tool.startedAt),\n }\n : {}),\n },\n });\n tool.observation.end();\n }\n this.tools.clear();\n }\n\n private closeGeneration(statusMessage: string, level: \"ERROR\" | \"WARNING\" = \"ERROR\"): void {\n if (!this.generation) return;\n this.generation.observation.update({\n level,\n statusMessage,\n metadata: {\n ...this.generation.requestMetadata,\n ...generationHttpMetadata(this.generation),\n },\n });\n this.generation.observation.end(this.generation.endTime);\n this.generation = undefined;\n }\n\n private closeCompaction(statusMessage: string): void {\n if (!this.compaction) return;\n this.compaction.observation.update({ level: \"WARNING\", statusMessage });\n this.compaction.observation.end();\n this.compaction = undefined;\n }\n\n private capture(value: unknown): unknown {\n return this.context.captureContent ? sanitizeTraceValue(value) : CONTENT_DISABLED;\n }\n}\n\nfunction normalizeTraceName(value: string | undefined): string {\n return typeof value === \"string\" && value.trim() ? value.trim() : \"pi.trace\";\n}\n\nfunction traceTags(customTags: readonly string[] | undefined, gitTag: string | undefined): string[] {\n const tags = [\"pi\", ...(gitTag ? [gitTag] : []), ...(customTags ?? [])];\n return [...new Set(tags.map(sanitizeTraceTag).filter((tag): tag is string => tag !== undefined))];\n}\n\nfunction sanitizeTraceTag(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n const sanitized = sanitizeTraceValue(value.trim());\n return typeof sanitized === \"string\" && sanitized.trim() ? sanitized.trim() : undefined;\n}\n\nfunction customTraceMetadata(metadata: Readonly<Record<string, unknown>> | undefined): Record<string, unknown> {\n if (!metadata) return {};\n const sanitized = sanitizeTraceValue(metadata);\n if (!sanitized || typeof sanitized !== \"object\" || Array.isArray(sanitized)) return {};\n return Object.fromEntries(Object.entries(sanitized).filter(([key]) => !key.startsWith(\"pi.\")));\n}\n\nfunction generationHttpMetadata(state: GenerationState): Record<string, unknown> {\n const finalStatus = state.statuses.at(-1);\n return {\n ...(state.statuses.length > 0\n ? {\n \"http.response.status_codes\": [...state.statuses],\n \"http.response.status_code\": finalStatus,\n \"http.response.attempt_count\": state.statuses.length,\n \"http.response.retry_count\": Math.max(0, state.statuses.length - 1),\n }\n : {}),\n ...(Object.keys(state.headers).length > 0 ? { \"http.response.headers\": { ...state.headers } } : {}),\n };\n}\n\nfunction allowlistedResponseHeaders(headers: Record<string, string>): Record<string, string> {\n const output: Record<string, string> = {};\n for (const [rawName, rawValue] of Object.entries(headers)) {\n const name = rawName.toLowerCase();\n if (!ALLOWED_RESPONSE_HEADERS.has(name) || typeof rawValue !== \"string\") continue;\n output[name] = truncateString(rawValue, MAX_HEADER_VALUE_LENGTH);\n }\n return output;\n}\n\nfunction structuralCompactionDetails(details: unknown): Record<string, unknown> {\n if (!details || typeof details !== \"object\" || Array.isArray(details)) return {};\n const record = details as Record<string, unknown>;\n return {\n ...(Array.isArray(record.readFiles) ? { \"pi.compaction.read_file_count\": record.readFiles.length } : {}),\n ...(Array.isArray(record.modifiedFiles)\n ? { \"pi.compaction.modified_file_count\": record.modifiedFiles.length }\n : {}),\n };\n}\n\nfunction snapshotMetadata(prefix: string, snapshot?: ContextSnapshot): Record<string, unknown> {\n if (!snapshot) return {};\n return {\n ...(snapshot.leafId ? { [`pi.trace.${prefix}_leaf_id`]: snapshot.leafId } : {}),\n ...(snapshot.contextUsage\n ? {\n ...(finiteNumber(snapshot.contextUsage.tokens)\n ? { [`pi.trace.${prefix}_context_tokens`]: snapshot.contextUsage.tokens }\n : {}),\n [`pi.trace.${prefix}_context_window`]: snapshot.contextUsage.contextWindow,\n ...(finiteNumber(snapshot.contextUsage.percent)\n ? { [`pi.trace.${prefix}_context_percent`]: snapshot.contextUsage.percent }\n : {}),\n }\n : {}),\n };\n}\n\nfunction classifyOutcome(message?: { role?: string; stopReason?: string; errorMessage?: string }): Outcome {\n if (message?.role !== \"assistant\") return \"interrupted\";\n if (message.stopReason === \"error\" || message.errorMessage) return \"error\";\n if (message.stopReason === \"aborted\") return \"aborted\";\n if (message.stopReason === \"length\") return \"length\";\n return \"success\";\n}\n\nfunction severityForOutcome(\n outcome: Outcome,\n statusMessage?: string,\n): Pick<ObservationAttributes, \"level\" | \"statusMessage\"> {\n if (outcome === \"success\") return {};\n if (outcome === \"error\") {\n return {\n level: \"ERROR\",\n statusMessage: statusMessage ?? \"The Pi operation failed.\",\n };\n }\n return {\n level: \"WARNING\",\n statusMessage:\n statusMessage ??\n (outcome === \"aborted\"\n ? \"The Pi operation was aborted.\"\n : outcome === \"length\"\n ? \"The model reached its output limit.\"\n : \"The Pi operation was interrupted.\"),\n };\n}\n\nfunction prefixRecord(prefix: string, values: Record<string, number>): Record<string, number> {\n return Object.fromEntries(Object.entries(values).map(([key, value]) => [`${prefix}.${key}`, value]));\n}\n\nfunction truncateString(value: string, maxBytes: number): string {\n const boundedPrefix = value.slice(0, maxBytes);\n if (boundedPrefix.length === value.length && byteLength(boundedPrefix) <= maxBytes) {\n return boundedPrefix;\n }\n const suffix = \"\u2026 [truncated]\";\n const target = Math.max(0, maxBytes - byteLength(suffix) - 2);\n let bytes = 0;\n let output = \"\";\n for (const character of boundedPrefix) {\n const size = byteLength(character);\n if (bytes + size > target) break;\n output += character;\n bytes += size;\n }\n return `${output}${suffix}`;\n}\n\nfunction byteLength(value: string): number {\n return Buffer.byteLength(value, \"utf8\");\n}\n\nfunction numericRecord(values: Record<string, number | undefined>): Record<string, number> {\n return Object.fromEntries(\n Object.entries(values).filter((entry): entry is [string, number] => finiteNumber(entry[1])),\n );\n}\n\nfunction positiveNumericRecord(values: Record<string, number | undefined>): Record<string, number> {\n return Object.fromEntries(\n Object.entries(values).filter((entry): entry is [string, number] => finiteNumber(entry[1]) && entry[1] > 0),\n );\n}\n\nfunction finiteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction hasItems(value: unknown): boolean {\n return Array.isArray(value) ? value.length > 0 : value !== undefined;\n}\n\nfunction emptyCounters(): Counters {\n return {\n attempts: 0,\n turns: 0,\n generations: 0,\n tools: 0,\n toolErrors: 0,\n compactions: 0,\n recoveredErrors: 0,\n failedAttempts: 0,\n };\n}\n", "import type { ExtensionAPI, ExtensionContext, ExtensionFactory } from \"@earendil-works/pi-coding-agent\";\nimport { resolveGitMetadata } from \"./git.js\";\nimport { getLangfuseRuntimeInternal, type LangfuseRuntime } from \"./runtime-core.js\";\nimport {\n type ContextSnapshot,\n type GitMetadata,\n sanitizeTraceValue,\n TraceRecorder,\n type TraceRecorderOptions,\n} from \"./tracing.js\";\n\nexport interface PiLangfuseSessionOptions {\n traceName?: string;\n sessionId?: string;\n userId?: string;\n tags?: readonly string[];\n metadata?: Readonly<Record<string, unknown>>;\n captureContent?: boolean;\n onTraceId?: (traceId: string) => void;\n}\n\nexport interface PiLangfuseSession {\n readonly extension: ExtensionFactory;\n setRequestId(requestId?: string): void;\n dispose(): Promise<void>;\n}\n\ninterface ResolvedSession {\n runtime: LangfuseRuntime;\n options?: PiLangfuseSessionOptions;\n releaseIfStale?(reason: string): Promise<void>;\n}\n\ninterface PiLangfuseSessionControllerOptions {\n resolveSession(ctx: ExtensionContext, isCurrent: () => boolean): Promise<ResolvedSession | undefined>;\n resolveGitMetadata?(pi: ExtensionAPI, cwd: string): Promise<GitMetadata | undefined>;\n onSessionStart?(): void;\n onSessionShutdown?(): void;\n onSessionReady?(session: ResolvedSession): void;\n onSessionUnavailable?(): void;\n onInitializationError?(error: unknown, ctx: ExtensionContext): void;\n beforeSessionDispose?(): Promise<void>;\n onShutdownError?(error: unknown, ctx: ExtensionContext): void;\n flushOnReplacement?: boolean;\n shutdownRuntimeOnQuit?: boolean;\n}\n\ntype Registration = object;\n\ntype InitializationResult = { ok: true } | { ok: false; error: unknown };\n\ninterface PendingInitialization {\n current: boolean;\n reason?: string;\n completion: Promise<InitializationResult>;\n complete(result: InitializationResult): void;\n}\n\ninterface PendingProviderGeneration {\n startedAt: number;\n payload: unknown;\n model?: { provider: string; id: string; api: string };\n thinkingLevel?: string;\n responses: Array<{ status: number; headers: Record<string, string> }>;\n}\n\ninterface ActiveBinding {\n registration: Registration;\n recorder: TraceRecorder;\n runtime: LangfuseRuntime;\n releaseRuntime: () => void;\n}\n\nexport interface PiLangfuseSessionController extends PiLangfuseSession {\n readonly active: boolean;\n readonly runtime: LangfuseRuntime | undefined;\n flush(): Promise<void>;\n}\n\nexport function createPiLangfuseSession(\n runtime: LangfuseRuntime,\n options: PiLangfuseSessionOptions = {},\n): PiLangfuseSession {\n const sessionOptions = snapshotSessionOptions(options);\n return createPiLangfuseSessionController({\n resolveSession: async () => ({ runtime, options: sessionOptions }),\n });\n}\n\nexport function createPiLangfuseSessionController(\n options: PiLangfuseSessionControllerOptions,\n): PiLangfuseSessionController {\n let binding: ActiveBinding | undefined;\n let runtimeForShutdown: LangfuseRuntime | undefined;\n let ownerRegistration: Registration | undefined;\n let pendingInitialization: PendingInitialization | undefined;\n const outstandingInitializations = new Set<PendingInitialization>();\n let disposePromise: Promise<void> | undefined;\n let disposed = false;\n let sessionGeneration = 0;\n let requestId: string | undefined;\n let requestIdRevision = 0;\n let nextAttemptReason: string | undefined;\n let lastSnapshot: ContextSnapshot | undefined;\n let pendingProviderGeneration: PendingProviderGeneration | undefined;\n\n const controller: PiLangfuseSessionController = {\n extension(pi) {\n if (disposed) throw new Error(\"A disposed Pi Langfuse session controller cannot be bound.\");\n registerHooks(pi);\n },\n setRequestId(value) {\n requestId = normalizeOptionalString(value);\n requestIdRevision += 1;\n },\n dispose() {\n if (disposePromise) return disposePromise;\n disposed = true;\n const initializations = invalidateAllInitializations(\"disposed\");\n ownerRegistration = undefined;\n sessionGeneration += 1;\n closeBinding(binding, \"Pi Langfuse session controller was disposed.\", lastSnapshot);\n runtimeForShutdown = undefined;\n disposePromise = joinInitializations(initializations);\n return disposePromise;\n },\n get active() {\n return binding !== undefined;\n },\n get runtime() {\n return binding?.runtime;\n },\n async flush() {\n const runtime = binding?.runtime;\n if (!runtime) throw new Error(\"Langfuse tracing is not enabled for this session.\");\n await runtime.flush();\n },\n };\n\n function closeBinding(target: ActiveBinding | undefined, statusMessage: string, snapshot?: ContextSnapshot): void {\n if (!target) return;\n const wasCurrent = binding === target;\n if (wasCurrent) {\n binding = undefined;\n pendingProviderGeneration = undefined;\n }\n target.releaseRuntime();\n target.recorder.dispose(statusMessage, snapshot);\n if (wasCurrent) nextAttemptReason = undefined;\n }\n\n function invalidatePendingInitialization(reason: string): void {\n if (!pendingInitialization) return;\n pendingInitialization.current = false;\n pendingInitialization.reason = reason;\n pendingInitialization = undefined;\n }\n\n function invalidateAllInitializations(reason: string): PendingInitialization[] {\n const initializations = [...outstandingInitializations];\n for (const initialization of initializations) {\n initialization.current = false;\n initialization.reason = reason;\n }\n pendingInitialization = undefined;\n return initializations;\n }\n\n function createPendingInitialization(): PendingInitialization {\n let complete!: (result: InitializationResult) => void;\n const completion = new Promise<InitializationResult>((resolve) => {\n complete = resolve;\n });\n const initialization = { current: true, completion, complete };\n outstandingInitializations.add(initialization);\n return initialization;\n }\n\n async function joinInitializations(initializations: readonly PendingInitialization[]): Promise<void> {\n const results = await Promise.all(initializations.map(({ completion }) => completion));\n const errors = results.flatMap((result) => (result.ok ? [] : [result.error]));\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) throw new AggregateError(errors, \"Pi Langfuse session initialization cleanup failed.\");\n }\n\n async function initializeSession(\n registration: Registration,\n initialization: PendingInitialization,\n ctx: ExtensionContext,\n ): Promise<void> {\n const generation = ++sessionGeneration;\n closeBinding(binding, \"Pi session was replaced before shutdown completed.\", lastSnapshot);\n lastSnapshot = contextSnapshot(ctx);\n nextAttemptReason = undefined;\n options.onSessionStart?.();\n\n const isCurrent = () =>\n !disposed && initialization.current && ownerRegistration === registration && generation === sessionGeneration;\n let resolved: ResolvedSession | undefined;\n try {\n resolved = await options.resolveSession(ctx, isCurrent);\n } catch (error) {\n if (isCurrent()) options.onInitializationError?.(error, ctx);\n return;\n }\n if (!isCurrent()) {\n const reason = initialization.reason ?? \"replaced\";\n if (\n resolved &&\n options.shutdownRuntimeOnQuit &&\n reason !== \"quit\" &&\n reason !== \"disposed\" &&\n (!runtimeForShutdown || runtimeForShutdown.closed)\n ) {\n runtimeForShutdown = resolved.runtime;\n }\n await resolved?.releaseIfStale?.(reason);\n return;\n }\n if (!resolved) {\n options.onSessionUnavailable?.();\n return;\n }\n\n try {\n const internal = getLangfuseRuntimeInternal(resolved.runtime);\n const recorderOptions = createRecorderOptions(ctx, resolved.options);\n const recorder = new TraceRecorder(internal.backend, recorderOptions);\n const nextBinding = {} as ActiveBinding;\n const releaseRuntime = internal.registerSession((statusMessage) => {\n closeBinding(nextBinding, statusMessage, lastSnapshot);\n });\n Object.assign(nextBinding, { registration, recorder, runtime: resolved.runtime, releaseRuntime });\n if (!isCurrent()) {\n releaseRuntime();\n return;\n }\n binding = nextBinding;\n if (options.shutdownRuntimeOnQuit) runtimeForShutdown = resolved.runtime;\n options.onSessionReady?.(resolved);\n } catch (error) {\n if (isCurrent()) options.onInitializationError?.(error, ctx);\n }\n }\n\n function registerHooks(pi: ExtensionAPI): void {\n const registration: Registration = {};\n const activeRecorder = () => activeRecorderFor(registration);\n\n pi.on(\"session_start\", async (_event, ctx) => {\n if (disposed) return;\n pendingProviderGeneration = undefined;\n if (ownerRegistration && ownerRegistration !== registration) {\n options.onInitializationError?.(\n new Error(\"A Pi Langfuse session controller cannot manage multiple active Pi sessions.\"),\n ctx,\n );\n return;\n }\n\n invalidatePendingInitialization(\"replaced\");\n ownerRegistration = registration;\n const initialization = createPendingInitialization();\n pendingInitialization = initialization;\n let result: InitializationResult = { ok: true };\n try {\n await initializeSession(registration, initialization, ctx);\n } catch (error) {\n result = { ok: false, error };\n throw error;\n } finally {\n initialization.complete(result);\n outstandingInitializations.delete(initialization);\n if (pendingInitialization === initialization) pendingInitialization = undefined;\n }\n });\n\n pi.on(\"before_agent_start\", async (event, ctx) => {\n // Cache warming emits provider hooks without assistant lifecycle events. Unclaimed\n // metadata is discarded at the next real run rather than classified by timing.\n pendingProviderGeneration = undefined;\n const active = ownerRegistration === registration ? binding : undefined;\n if (!active || active.runtime.closed) return;\n nextAttemptReason = undefined;\n const git = await (options.resolveGitMetadata\n ? options.resolveGitMetadata(pi, ctx.cwd)\n : resolveGitMetadata((command, args, execOptions) => pi.exec(command, args, execOptions), ctx.cwd)\n ).catch(() => undefined);\n if (ownerRegistration !== registration || binding !== active || active.runtime.closed) return;\n lastSnapshot = contextSnapshot(ctx);\n startRootTrace((nextRequestId) => {\n active.recorder.beginAgent({\n prompt: event.prompt,\n images: event.images,\n model: ctx.model ? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api } : undefined,\n git,\n snapshot: lastSnapshot,\n ...(nextRequestId ? { requestId: nextRequestId } : {}),\n });\n });\n });\n\n pi.on(\"agent_start\", () => {\n const recorder = activeRecorder();\n if (!recorder) return;\n recorder.beginAttempt(nextAttemptReason ? { reason: nextAttemptReason } : undefined);\n nextAttemptReason = undefined;\n });\n\n pi.on(\"turn_start\", (event, ctx) => {\n const recorder = activeRecorder();\n if (!recorder) return;\n lastSnapshot = contextSnapshot(ctx);\n ensureActiveRun(recorder, ctx, startRootTrace);\n recorder.beginTurn(event.turnIndex);\n });\n\n pi.on(\"before_provider_request\", (event, ctx) => {\n if (!activeRecorder()) return;\n lastSnapshot = contextSnapshot(ctx);\n pendingProviderGeneration = {\n startedAt: Date.now(),\n payload: event.payload,\n model: ctx.model ? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api } : undefined,\n thinkingLevel: pi.getThinkingLevel(),\n responses: [],\n };\n });\n\n pi.on(\"after_provider_response\", (event) => {\n pendingProviderGeneration?.responses.push({ status: event.status, headers: event.headers });\n });\n\n pi.on(\"message_start\", (event, ctx) => {\n if (event.message.role === \"assistant\") claimPendingProviderGeneration(ctx, activeRecorder());\n });\n\n pi.on(\"message_update\", (event, ctx) => {\n if (!isRealOutputDelta(event.assistantMessageEvent)) return;\n const recorder = activeRecorder();\n claimPendingProviderGeneration(ctx, recorder);\n recorder?.markGenerationFirstOutput();\n });\n\n pi.on(\"message_end\", (event, ctx) => {\n if (event.message.role !== \"assistant\") return;\n const recorder = activeRecorder();\n claimPendingProviderGeneration(ctx, recorder);\n recorder?.markGenerationEnd();\n });\n\n pi.on(\"turn_end\", (event, ctx) => {\n const recorder = activeRecorder();\n if (!recorder) return;\n if (event.message.role === \"assistant\") claimPendingProviderGeneration(ctx, recorder);\n lastSnapshot = contextSnapshot(ctx);\n if (event.message.role === \"assistant\") recorder.finishAssistant(event.message);\n recorder.finishTurn(event.turnIndex, {\n message: event.message,\n toolResultCount: event.toolResults.length,\n });\n });\n\n pi.on(\"tool_execution_start\", (event) => {\n activeRecorder()?.beginTool(event.toolCallId, event.toolName, event.args);\n });\n\n pi.on(\"tool_execution_update\", (event) => {\n activeRecorder()?.recordToolProgress(event.toolCallId);\n });\n\n pi.on(\"tool_result\", (event) => {\n activeRecorder()?.recordToolInput(event.toolCallId, event.input);\n });\n\n pi.on(\"tool_execution_end\", (event) => {\n activeRecorder()?.finishTool(event.toolCallId, {\n content: event.result.content,\n details: event.result.details,\n isError: event.isError,\n });\n });\n\n pi.on(\"agent_end\", (event) => {\n const message = findLastAssistant(event.messages);\n activeRecorder()?.finishAttempt(message);\n });\n\n pi.on(\"session_before_compact\", (event) => {\n activeRecorder()?.beginCompaction({\n reason: event.reason,\n willRetry: event.willRetry,\n tokensBefore: event.preparation.tokensBefore,\n messagesToSummarize: event.preparation.messagesToSummarize.length,\n turnPrefixMessages: event.preparation.turnPrefixMessages.length,\n branchEntries: event.branchEntries.length,\n isSplitTurn: event.preparation.isSplitTurn,\n });\n });\n\n pi.on(\"session_compact\", (event) => {\n const recorder = activeRecorder();\n const entry = event.compactionEntry as typeof event.compactionEntry & {\n usage?: Parameters<TraceRecorder[\"finishCompaction\"]>[0][\"usage\"];\n };\n recorder?.finishCompaction({\n reason: event.reason,\n willRetry: event.willRetry,\n fromExtension: event.fromExtension,\n tokensBefore: entry.tokensBefore,\n details: entry.details,\n usage: entry.usage,\n });\n if (event.willRetry && recorder?.hasActiveTrace()) nextAttemptReason = \"post_compaction\";\n });\n\n pi.on(\"agent_settled\", (_event, ctx) => {\n const recorder = activeRecorder();\n if (!recorder) return;\n lastSnapshot = contextSnapshot(ctx);\n recorder.settle(lastSnapshot);\n pendingProviderGeneration = undefined;\n nextAttemptReason = undefined;\n });\n\n pi.on(\"session_shutdown\", async (event, ctx) => {\n if (ownerRegistration !== registration) return;\n const initializations = invalidateAllInitializations(event.reason);\n ownerRegistration = undefined;\n const generation = ++sessionGeneration;\n options.onSessionShutdown?.();\n const active = binding?.registration === registration ? binding : undefined;\n const runtime = active?.runtime ?? runtimeForShutdown;\n lastSnapshot = active ? contextSnapshot(ctx) : lastSnapshot;\n closeBinding(\n active,\n event.reason === \"quit\"\n ? \"Pi shut down before the active trace settled.\"\n : `Pi session ended before settlement (${event.reason}).`,\n lastSnapshot,\n );\n\n let beforeDisposeFailure: { error: unknown } | undefined;\n try {\n await options.beforeSessionDispose?.();\n } catch (error) {\n beforeDisposeFailure = { error };\n }\n\n try {\n await joinInitializations(initializations);\n if (disposed || generation !== sessionGeneration) return;\n if (beforeDisposeFailure) throw beforeDisposeFailure.error;\n if (runtime) {\n if (event.reason === \"quit\" && options.shutdownRuntimeOnQuit) await runtime.shutdown();\n else if (options.flushOnReplacement) await runtime.flush();\n }\n } catch (error) {\n if (!disposed && generation === sessionGeneration) options.onShutdownError?.(error, ctx);\n }\n });\n }\n\n function claimPendingProviderGeneration(ctx: ExtensionContext, recorder: TraceRecorder | undefined): void {\n const pending = pendingProviderGeneration;\n if (!pending || !recorder) return;\n pendingProviderGeneration = undefined;\n ensureActiveRun(recorder, ctx, startRootTrace);\n recorder.beginGeneration({\n startedAt: pending.startedAt,\n payload: pending.payload,\n payloadStage: \"before_provider_request\",\n model: pending.model,\n thinkingLevel: pending.thinkingLevel,\n });\n for (const response of pending.responses) recorder.recordProviderResponse(response.status, response.headers);\n }\n\n function startRootTrace(start: (nextRequestId: string | undefined) => void): void {\n const revision = requestIdRevision;\n const nextRequestId = requestId;\n start(nextRequestId);\n if (requestIdRevision === revision) requestId = undefined;\n }\n\n function activeRecorderFor(registration: Registration): TraceRecorder | undefined {\n return ownerRegistration === registration && binding?.registration === registration && !binding.runtime.closed\n ? binding.recorder\n : undefined;\n }\n\n return controller;\n}\n\nfunction createRecorderOptions(ctx: ExtensionContext, options: PiLangfuseSessionOptions = {}): TraceRecorderOptions {\n const userId = normalizeUserId(options.userId);\n return {\n sessionId: normalizeOptionalString(options.sessionId) ?? ctx.sessionManager.getSessionId(),\n ...(userId ? { userId } : {}),\n cwd: ctx.cwd,\n mode: ctx.mode,\n captureContent: options.captureContent ?? true,\n ...(normalizeOptionalString(options.traceName) ? { traceName: normalizeOptionalString(options.traceName) } : {}),\n ...(options.tags ? { tags: [...options.tags] } : {}),\n ...(options.metadata ? { metadata: { ...options.metadata } } : {}),\n ...(options.onTraceId ? { onTraceId: options.onTraceId } : {}),\n };\n}\n\nfunction snapshotSessionOptions(options: PiLangfuseSessionOptions): PiLangfuseSessionOptions {\n normalizeUserId(options.userId);\n return {\n ...options,\n ...(options.tags ? { tags: [...options.tags] } : {}),\n ...(options.metadata ? { metadata: { ...options.metadata } } : {}),\n };\n}\n\nfunction ensureActiveRun(\n recorder: TraceRecorder,\n ctx: ExtensionContext,\n startRootTrace: (start: (nextRequestId: string | undefined) => void) => void,\n): void {\n if (!recorder.hasActiveTrace()) {\n startRootTrace((nextRequestId) => {\n recorder.beginAgent({\n prompt: \"[automatic continuation]\",\n model: ctx.model ? { provider: ctx.model.provider, id: ctx.model.id, api: ctx.model.api } : undefined,\n snapshot: contextSnapshot(ctx),\n ...(nextRequestId ? { requestId: nextRequestId } : {}),\n });\n });\n }\n if (!recorder.hasActiveAttempt()) recorder.beginAttempt();\n}\n\nfunction contextSnapshot(ctx: ExtensionContext): ContextSnapshot {\n return {\n leafId: typeof ctx.sessionManager.getLeafId === \"function\" ? ctx.sessionManager.getLeafId() : undefined,\n contextUsage: ctx.getContextUsage(),\n };\n}\n\nfunction findLastAssistant<T extends { role?: string }>(messages: readonly T[]): T | undefined {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message?.role === \"assistant\") return message;\n }\n return undefined;\n}\n\nfunction isRealOutputDelta(event: { type: string; delta?: unknown }): boolean {\n return (\n (event.type === \"text_delta\" || event.type === \"thinking_delta\" || event.type === \"toolcall_delta\") &&\n typeof event.delta === \"string\" &&\n event.delta.length > 0\n );\n}\n\nfunction normalizeUserId(value: unknown): string | undefined {\n const userId = normalizeOptionalString(value);\n if (userId && userId.length > 200) throw new Error(\"Langfuse userId must be at most 200 characters.\");\n return userId;\n}\n\nfunction normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== \"string\" || !value.trim()) return undefined;\n const sanitized = sanitizeTraceValue(value.trim());\n return typeof sanitized === \"string\" && sanitized.trim() ? sanitized.trim() : undefined;\n}\n", "import type { ExtensionAPI, ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport {\n DEFAULT_BASE_URL,\n type LangfuseConfig,\n type LangfuseConfigPatch,\n type LangfuseConfigResult,\n loadLangfuseConfig,\n normalizeLangfuseConfig,\n writeLangfuseConfig,\n} from \"./config.js\";\nimport { createPiLangfuseSessionController, type PiLangfuseSessionController } from \"./pi-session.js\";\nimport { createLangfuseRuntimeFromBackend } from \"./runtime-core.js\";\nimport type { GitMetadata, TraceBackend } from \"./tracing.js\";\n\nexport { resolveGitMetadata } from \"./git.js\";\n\ninterface ExtensionDependencies {\n loadConfig(path?: string): Promise<LangfuseConfigResult>;\n writeConfig(config: LangfuseConfigPatch, path?: string): Promise<unknown>;\n createBackend(config: LangfuseConfig): Promise<TraceBackend>;\n resolveGitMetadata(cwd: string): Promise<GitMetadata | undefined>;\n}\n\nconst FLUSH_ACTION = \"Flush completed traces for this session\";\nconst SET_UP_ACTION = \"Set up Langfuse for this Pi agent directory (restart required)\";\nconst UPDATE_ACTION = \"Update Langfuse for this Pi agent directory (restart required)\";\nconst HELP_ACTION = \"Show setup and privacy help\";\n\nexport function createLangfuseExtension(dependencies: Partial<ExtensionDependencies> = {}): (pi: ExtensionAPI) => void {\n const loadConfig = dependencies.loadConfig ?? loadLangfuseConfig;\n const writeConfig = dependencies.writeConfig ?? writeLangfuseConfig;\n const resolveInjectedGitMetadata = dependencies.resolveGitMetadata;\n\n return function langfuse(pi: ExtensionAPI) {\n let activeConfig: LangfuseConfig | undefined;\n let loadingConfig: LangfuseConfig | undefined;\n let runtimeConfigForShutdown: LangfuseConfig | undefined;\n let shutdownConfig: LangfuseConfig | undefined;\n let configPath: string | undefined;\n let initializationError: string | undefined;\n let hasStoredConfig = false;\n let configurationNotice: string | undefined;\n let sessionGeneration = 0;\n let menuController = new AbortController();\n let configWriteQueue = Promise.resolve();\n\n const tracing: PiLangfuseSessionController = createPiLangfuseSessionController({\n onSessionStart() {\n sessionGeneration += 1;\n menuController.abort(new DOMException(\"Langfuse session replaced\", \"AbortError\"));\n menuController = new AbortController();\n activeConfig = undefined;\n loadingConfig = undefined;\n shutdownConfig = undefined;\n configPath = undefined;\n initializationError = undefined;\n hasStoredConfig = false;\n configurationNotice = undefined;\n },\n onSessionShutdown() {\n sessionGeneration += 1;\n menuController.abort(new DOMException(\"Langfuse session shut down\", \"AbortError\"));\n shutdownConfig = activeConfig ?? runtimeConfigForShutdown ?? loadingConfig;\n activeConfig = undefined;\n },\n async resolveSession(ctx, isCurrent) {\n await configWriteQueue;\n if (!isCurrent()) return undefined;\n const result = await loadConfig();\n if (!isCurrent()) return undefined;\n configPath = result.path;\n for (const warning of result.warnings) ctx.ui.notify(warning, \"warning\");\n if (!result.ok) {\n initializationError = formatConfigError(result);\n ctx.ui.notify(initializationError, \"warning\");\n return undefined;\n }\n\n hasStoredConfig = true;\n loadingConfig = result.config;\n const createBackend = dependencies.createBackend;\n const ownsRuntime = createBackend !== undefined;\n const runtime = createBackend\n ? createLangfuseRuntimeFromBackend(await createBackend(result.config))\n : await (await import(\"./runtime.js\")).createLangfuseRuntime({ config: result.config, env: false });\n if (isCurrent() || !runtimeConfigForShutdown) runtimeConfigForShutdown = result.config;\n if (isCurrent()) {\n activeConfig = result.config;\n loadingConfig = undefined;\n }\n return {\n runtime,\n releaseIfStale: async (reason) => {\n if (ownsRuntime || reason === \"quit\") await runtime.shutdown();\n },\n options: {\n ...(result.config.userId ? { userId: result.config.userId } : {}),\n captureContent: result.config.captureContent,\n },\n };\n },\n ...(resolveInjectedGitMetadata\n ? { resolveGitMetadata: (_pi: ExtensionAPI, cwd: string) => resolveInjectedGitMetadata(cwd) }\n : {}),\n onInitializationError(error, ctx) {\n const config = loadingConfig;\n loadingConfig = undefined;\n initializationError = `Langfuse tracing could not start: ${formatError(error, config)}`;\n ctx.ui.notify(initializationError, \"warning\");\n },\n beforeSessionDispose: async () => {\n await configWriteQueue;\n },\n onShutdownError(error, ctx) {\n ctx.ui.notify(`Langfuse shutdown export failed: ${formatError(error, shutdownConfig)}`, \"error\");\n },\n flushOnReplacement: true,\n shutdownRuntimeOnQuit: true,\n });\n\n async function showLangfuseMenu(ctx: ExtensionCommandContext) {\n if (!ctx.hasUI) {\n ctx.ui.notify(formatNonInteractiveStatus(activeConfig, configPath, initializationError), \"warning\");\n return;\n }\n const menuGeneration = sessionGeneration;\n const menuSignal = menuController.signal;\n const isCurrent = () => menuGeneration === sessionGeneration && !menuSignal.aborted;\n const { defineMenu, runMenu } = await import(\"@narumitw/pi-tui-kit\");\n if (!isCurrent()) return;\n type Screen = \"main\";\n type Action = \"flush\" | \"configure\" | \"help\";\n const menu = defineMenu<undefined, Screen, Action>({\n start: \"main\",\n screens: {\n main: () => ({\n kind: \"actions\",\n title: \"Langfuse\",\n lines: formatMenuTitle(activeConfig, configPath, initializationError, configurationNotice)\n .split(\"\\n\")\n .slice(1),\n items: [\n ...(tracing.active ? [{ id: \"flush\", label: FLUSH_ACTION, action: \"flush\" as const }] : []),\n {\n id: \"configure\",\n label: hasStoredConfig ? UPDATE_ACTION : SET_UP_ACTION,\n action: \"configure\",\n },\n { id: \"help\", label: HELP_ACTION, action: \"help\" },\n ],\n hint: \"close\",\n }),\n },\n actions: {\n flush: async () => {\n const menuConfig = activeConfig;\n if (!tracing.active) {\n ctx.ui.notify(\"Langfuse tracing is not enabled for this session.\", \"warning\");\n return { kind: \"close\" };\n }\n try {\n await tracing.flush();\n if (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n ctx.ui.notify(\"Langfuse traces flushed for this session.\", \"info\");\n } catch (error) {\n if (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n ctx.ui.notify(`Langfuse flush failed: ${formatError(error, menuConfig)}`, \"error\");\n }\n return { kind: \"close\" };\n },\n configure: async () => {\n const loaded = await loadConfig(configPath);\n if (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n configPath = loaded.path;\n const next = await promptForConfig(\n ctx,\n loaded.ok ? loaded.config : undefined,\n () => menuGeneration === sessionGeneration,\n );\n if (!next || menuGeneration !== sessionGeneration) return { kind: \"close\" };\n try {\n const write = configWriteQueue.then(() => writeConfig(next, loaded.path));\n configWriteQueue = write.then(\n () => undefined,\n () => undefined,\n );\n await write;\n if (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n hasStoredConfig = true;\n configurationNotice = \"Saved; restart each Pi process to use it in subsequent sessions.\";\n ctx.ui.notify(\n `Saved Langfuse config to ${loaded.path} for this Pi agent directory. Restart each Pi process to apply it to subsequent sessions.`,\n \"info\",\n );\n } catch (error) {\n if (menuGeneration !== sessionGeneration) return { kind: \"close\" };\n ctx.ui.notify(`Failed to save Langfuse config: ${formatError(error, next)}`, \"error\");\n }\n return { kind: \"close\" };\n },\n help: async () => {\n ctx.ui.notify(formatHelp(configPath), \"info\");\n return { kind: \"close\" };\n },\n },\n });\n await runMenu(ctx, menu, {\n getState: () => undefined,\n signal: menuSignal,\n isCurrent,\n });\n }\n\n pi.registerCommand(\"langfuse\", {\n description: \"Open interactive Langfuse tracing controls\",\n handler: async (_args, ctx) => showLangfuseMenu(ctx),\n });\n\n tracing.extension(pi);\n };\n}\n\nasync function promptForConfig(\n ctx: ExtensionCommandContext,\n current: LangfuseConfig | undefined,\n isCurrent: () => boolean,\n): Promise<LangfuseConfigPatch | undefined> {\n const secretKey = await ctx.ui.input(\"Langfuse secret key (leave blank to keep existing):\");\n if (!isCurrent()) return undefined;\n if (secretKey === undefined) {\n ctx.ui.notify(\"Cancelled\", \"info\");\n return undefined;\n }\n const publicKey = await ctx.ui.input(\"Langfuse public key (leave blank to keep existing):\");\n if (!isCurrent()) return undefined;\n if (publicKey === undefined) {\n ctx.ui.notify(\"Cancelled\", \"info\");\n return undefined;\n }\n const baseUrl = await ctx.ui.input(\n `Langfuse base URL (leave blank for default ${DEFAULT_BASE_URL}):`,\n DEFAULT_BASE_URL,\n );\n if (!isCurrent()) return undefined;\n if (baseUrl === undefined) {\n ctx.ui.notify(\"Cancelled\", \"info\");\n return undefined;\n }\n\n const patch: LangfuseConfigPatch = {\n ...(publicKey.trim() ? { publicKey: publicKey.trim() } : {}),\n ...(secretKey.trim() ? { secretKey: secretKey.trim() } : {}),\n baseUrl: baseUrl.trim() || DEFAULT_BASE_URL,\n };\n const normalized = normalizeLangfuseConfig({ ...current, ...patch });\n if (!normalized.ok) {\n ctx.ui.notify(`Invalid Langfuse config: ${normalized.reason}`, \"error\");\n return undefined;\n }\n return patch;\n}\n\nfunction formatMenuTitle(\n activeConfig: LangfuseConfig | undefined,\n configPath: string | undefined,\n initializationError: string | undefined,\n configurationNotice: string | undefined,\n): string {\n const lines = [\"Langfuse\", \"\", \"Current session:\", ` Tracing: ${activeConfig ? \"enabled\" : \"disabled\"}`];\n if (activeConfig) {\n lines.push(\n ` Endpoint: ${activeConfig.baseUrl}`,\n ` Content capture: ${activeConfig.captureContent ? \"enabled\" : \"disabled\"}`,\n );\n } else if (configurationNotice) {\n lines.push(\" State: tracing remains disabled until Pi restarts.\");\n } else if (initializationError) {\n lines.push(` Reason: ${initializationError}`);\n }\n lines.push(\n \"\",\n \"Agent-directory configuration:\",\n ` Configuration: ${configPath ?? \"unknown\"}`,\n \" Scope: this Pi agent directory; restart each Pi process to apply changes.\",\n );\n if (configurationNotice) lines.push(` Pending: ${configurationNotice}`);\n lines.push(\"\", \"What do you want to do?\");\n return lines.join(\"\\n\");\n}\n\nfunction formatNonInteractiveStatus(\n activeConfig: LangfuseConfig | undefined,\n configPath: string | undefined,\n initializationError: string | undefined,\n): string {\n return [\n \"/langfuse requires interactive UI.\",\n `Current session tracing: ${activeConfig ? \"enabled\" : \"disabled\"}`,\n ...(activeConfig\n ? [\n `Endpoint: ${activeConfig.baseUrl}`,\n `Content capture: ${activeConfig.captureContent ? \"enabled\" : \"disabled\"}`,\n ]\n : initializationError\n ? [`Reason: ${initializationError}`]\n : []),\n `Configuration: ${configPath ?? \"unknown\"}`,\n \"Edit the private config manually, then restart each Pi process to apply it to subsequent sessions.\",\n ].join(\"\\n\");\n}\n\nfunction formatHelp(configPath: string | undefined): string {\n return [\n \"Langfuse setup and privacy:\",\n \"Run /langfuse in interactive Pi to manage tracing for the current session.\",\n `Configuration: ${configPath ?? \"pi-langfuse.json\"}`,\n \"The file belongs to this Pi agent directory; restart each Pi process after changing it.\",\n \"Trace content may contain prompts, responses, tool arguments, tool results, and source code.\",\n \"Git branch, commit, cwd, model, and usage remain in metadata when content capture is disabled.\",\n 'Use \"captureContent\": false in the private config to export metadata only.',\n ].join(\"\\n\");\n}\n\nfunction formatConfigError(result: Extract<LangfuseConfigResult, { ok: false }>): string {\n const setupHint = result.reason.startsWith(\"Configuration file not found:\")\n ? \" Run /langfuse and choose Set up Langfuse.\"\n : \"\";\n return `Langfuse tracing is disabled: ${result.reason}${setupHint}`;\n}\n\nfunction formatError(error: unknown, config?: LangfuseConfigPatch): string {\n let message = error instanceof Error ? error.message : String(error);\n const secrets = [config?.publicKey, config?.secretKey]\n .filter((secret): secret is string => Boolean(secret))\n .sort((left, right) => right.length - left.length);\n for (const secret of secrets) {\n message = message.split(secret).join(\"[LANGFUSE_KEY_REDACTED]\");\n }\n return message;\n}\n\nexport default createLangfuseExtension();\n", "import type { CreateLangfuseRuntimeOptions, LangfuseRuntime } from \"./runtime-core.js\";\n\nexport {\n createPiLangfuseSession,\n type PiLangfuseSession,\n type PiLangfuseSessionOptions,\n} from \"./pi-session.js\";\nexport type {\n CreateLangfuseRuntimeOptions,\n LangfuseRuntime,\n LangfuseRuntimeConfig,\n} from \"./runtime-core.js\";\n\nexport async function createLangfuseRuntime(options: CreateLangfuseRuntimeOptions = {}): Promise<LangfuseRuntime> {\n const runtime = await import(\"./runtime.js\");\n return runtime.createLangfuseRuntime(options);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["truncateString", "byteLength"]
7
7
  }
@@ -0,0 +1,13 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import { type LangfuseConfig, type LangfuseConfigPatch, type LangfuseConfigResult } from "./config.js";
3
+ import type { GitMetadata, TraceBackend } from "./tracing.js";
4
+ export { resolveGitMetadata } from "./git.js";
5
+ interface ExtensionDependencies {
6
+ loadConfig(path?: string): Promise<LangfuseConfigResult>;
7
+ writeConfig(config: LangfuseConfigPatch, path?: string): Promise<unknown>;
8
+ createBackend(config: LangfuseConfig): Promise<TraceBackend>;
9
+ resolveGitMetadata(cwd: string): Promise<GitMetadata | undefined>;
10
+ }
11
+ export declare function createLangfuseExtension(dependencies?: Partial<ExtensionDependencies>): (pi: ExtensionAPI) => void;
12
+ declare const _default: (pi: ExtensionAPI) => void;
13
+ export default _default;
@@ -0,0 +1,43 @@
1
+ import type { ExtensionAPI, ExtensionContext, ExtensionFactory } from "@earendil-works/pi-coding-agent";
2
+ import { type LangfuseRuntime } from "./runtime-core.js";
3
+ import { type GitMetadata } from "./tracing.js";
4
+ export interface PiLangfuseSessionOptions {
5
+ traceName?: string;
6
+ sessionId?: string;
7
+ userId?: string;
8
+ tags?: readonly string[];
9
+ metadata?: Readonly<Record<string, unknown>>;
10
+ captureContent?: boolean;
11
+ onTraceId?: (traceId: string) => void;
12
+ }
13
+ export interface PiLangfuseSession {
14
+ readonly extension: ExtensionFactory;
15
+ setRequestId(requestId?: string): void;
16
+ dispose(): Promise<void>;
17
+ }
18
+ interface ResolvedSession {
19
+ runtime: LangfuseRuntime;
20
+ options?: PiLangfuseSessionOptions;
21
+ releaseIfStale?(reason: string): Promise<void>;
22
+ }
23
+ interface PiLangfuseSessionControllerOptions {
24
+ resolveSession(ctx: ExtensionContext, isCurrent: () => boolean): Promise<ResolvedSession | undefined>;
25
+ resolveGitMetadata?(pi: ExtensionAPI, cwd: string): Promise<GitMetadata | undefined>;
26
+ onSessionStart?(): void;
27
+ onSessionShutdown?(): void;
28
+ onSessionReady?(session: ResolvedSession): void;
29
+ onSessionUnavailable?(): void;
30
+ onInitializationError?(error: unknown, ctx: ExtensionContext): void;
31
+ beforeSessionDispose?(): Promise<void>;
32
+ onShutdownError?(error: unknown, ctx: ExtensionContext): void;
33
+ flushOnReplacement?: boolean;
34
+ shutdownRuntimeOnQuit?: boolean;
35
+ }
36
+ export interface PiLangfuseSessionController extends PiLangfuseSession {
37
+ readonly active: boolean;
38
+ readonly runtime: LangfuseRuntime | undefined;
39
+ flush(): Promise<void>;
40
+ }
41
+ export declare function createPiLangfuseSession(runtime: LangfuseRuntime, options?: PiLangfuseSessionOptions): PiLangfuseSession;
42
+ export declare function createPiLangfuseSessionController(options: PiLangfuseSessionControllerOptions): PiLangfuseSessionController;
43
+ export {};