@narumitw/pi-langfuse 0.50.6 → 0.51.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,202 @@
1
+ export { MAX_CAPTURE_BYTES, sanitizeTraceValue } from "./sanitizer.js";
2
+ export declare const TRACE_SCHEMA_VERSION = "2";
3
+ export interface ObservationAttributes {
4
+ input?: unknown;
5
+ output?: unknown;
6
+ metadata?: Record<string, unknown>;
7
+ level?: "DEBUG" | "DEFAULT" | "WARNING" | "ERROR";
8
+ statusMessage?: string;
9
+ completionStartTime?: Date;
10
+ model?: string;
11
+ modelParameters?: Record<string, string | number>;
12
+ usageDetails?: Record<string, number>;
13
+ costDetails?: Record<string, number>;
14
+ version?: string;
15
+ name?: string;
16
+ sessionId?: string;
17
+ userId?: string;
18
+ tags?: string[];
19
+ }
20
+ export interface Observation {
21
+ readonly traceId?: string;
22
+ update(attributes: ObservationAttributes): Observation;
23
+ updateTrace?(attributes: ObservationAttributes): Observation;
24
+ end(endTime?: number): Observation;
25
+ }
26
+ export type ObservationType = "agent" | "generation" | "span" | "tool";
27
+ export interface TraceBackend {
28
+ start(name: string, attributes: ObservationAttributes, options: {
29
+ asType: ObservationType;
30
+ parent?: Observation;
31
+ startTime?: Date;
32
+ }): Observation;
33
+ forceFlush(): Promise<void>;
34
+ shutdown(): Promise<void>;
35
+ }
36
+ export interface TraceRecorderOptions {
37
+ sessionId: string;
38
+ userId?: string;
39
+ cwd: string;
40
+ mode: string;
41
+ captureContent: boolean;
42
+ traceName?: string;
43
+ tags?: readonly string[];
44
+ metadata?: Readonly<Record<string, unknown>>;
45
+ onTraceId?: (traceId: string) => void;
46
+ }
47
+ interface ModelDescriptor {
48
+ provider?: string;
49
+ id?: string;
50
+ api?: string;
51
+ }
52
+ export interface GitMetadata {
53
+ branch?: string;
54
+ commit?: string;
55
+ detached: boolean;
56
+ }
57
+ export interface ContextSnapshot {
58
+ leafId?: string | null;
59
+ contextUsage?: {
60
+ tokens: number | null;
61
+ contextWindow: number;
62
+ percent: number | null;
63
+ };
64
+ }
65
+ interface BeginAgentInput {
66
+ prompt: unknown;
67
+ images?: unknown;
68
+ model?: ModelDescriptor;
69
+ git?: GitMetadata;
70
+ snapshot?: ContextSnapshot;
71
+ requestId?: string;
72
+ }
73
+ interface AttemptInput {
74
+ reason?: string;
75
+ }
76
+ interface GenerationInput {
77
+ startedAt?: number;
78
+ payload?: unknown;
79
+ payloadStage?: "before_provider_request";
80
+ model?: ModelDescriptor;
81
+ thinkingLevel?: string;
82
+ }
83
+ interface AssistantMessage {
84
+ role: string;
85
+ content?: unknown;
86
+ provider?: string;
87
+ api?: string;
88
+ model?: string;
89
+ responseModel?: string;
90
+ responseId?: string;
91
+ usage?: {
92
+ input?: number;
93
+ output?: number;
94
+ cacheRead?: number;
95
+ cacheWrite?: number;
96
+ cacheWrite1h?: number;
97
+ reasoning?: number;
98
+ totalTokens?: number;
99
+ cost?: {
100
+ input?: number;
101
+ output?: number;
102
+ cacheRead?: number;
103
+ cacheWrite?: number;
104
+ total?: number;
105
+ };
106
+ };
107
+ stopReason?: string;
108
+ errorMessage?: string;
109
+ }
110
+ interface ToolResult {
111
+ content?: unknown;
112
+ details?: unknown;
113
+ isError?: boolean;
114
+ }
115
+ interface TurnResult {
116
+ message: {
117
+ role: string;
118
+ stopReason?: string;
119
+ errorMessage?: string;
120
+ };
121
+ toolResultCount: number;
122
+ }
123
+ interface CompactionStart {
124
+ reason: string;
125
+ willRetry: boolean;
126
+ tokensBefore?: number;
127
+ messagesToSummarize: number;
128
+ turnPrefixMessages: number;
129
+ branchEntries: number;
130
+ isSplitTurn: boolean;
131
+ }
132
+ interface CompactionFinish {
133
+ reason: string;
134
+ willRetry: boolean;
135
+ fromExtension: boolean;
136
+ tokensBefore?: number;
137
+ details?: unknown;
138
+ usage?: {
139
+ input?: number;
140
+ output?: number;
141
+ cacheRead?: number;
142
+ cacheWrite?: number;
143
+ totalTokens?: number;
144
+ cost?: {
145
+ input?: number;
146
+ output?: number;
147
+ cacheRead?: number;
148
+ cacheWrite?: number;
149
+ total?: number;
150
+ };
151
+ };
152
+ }
153
+ export declare class TraceRecorder {
154
+ private readonly backend;
155
+ private readonly context;
156
+ private root;
157
+ private attempt;
158
+ private attemptIndex;
159
+ private turn;
160
+ private turnIndex;
161
+ private generation;
162
+ private readonly tools;
163
+ private readonly duplicateToolIds;
164
+ private compaction;
165
+ private lastOutput;
166
+ private lastAssistant;
167
+ private lastAttemptOutcome;
168
+ private unresolvedToolErrors;
169
+ private startSnapshot;
170
+ private counters;
171
+ constructor(backend: TraceBackend, context: TraceRecorderOptions);
172
+ private startObservation;
173
+ hasActiveTrace(): boolean;
174
+ hasActiveAttempt(): boolean;
175
+ beginAgent(input: BeginAgentInput): void;
176
+ beginAttempt(input?: AttemptInput): void;
177
+ finishAttempt(message?: AssistantMessage): void;
178
+ beginTurn(turnIndex: number): void;
179
+ finishTurn(turnIndex: number, result: TurnResult): void;
180
+ beginGeneration(input?: GenerationInput): void;
181
+ recordProviderResponse(status: number, headers?: Record<string, string>): void;
182
+ markGenerationFirstOutput(timestamp?: number): void;
183
+ markGenerationEnd(endTime?: number): void;
184
+ finishAssistant(message: AssistantMessage): void;
185
+ beginTool(toolCallId: string, toolName: string, args?: unknown, startedAt?: number): void;
186
+ recordToolInput(toolCallId: string, input: unknown): void;
187
+ recordToolProgress(toolCallId: string, timestamp?: number): void;
188
+ finishTool(toolCallId: string, result: ToolResult): void;
189
+ beginCompaction(input: CompactionStart): void;
190
+ finishCompaction(input: CompactionFinish): void;
191
+ settle(snapshot?: ContextSnapshot): void;
192
+ interrupt(statusMessage: string, snapshot?: ContextSnapshot): void;
193
+ dispose(statusMessage?: string, snapshot?: ContextSnapshot): void;
194
+ private closeActiveTrace;
195
+ private closeAttempt;
196
+ private startToolObservation;
197
+ private closeTurn;
198
+ private closeTools;
199
+ private closeGeneration;
200
+ private closeCompaction;
201
+ private capture;
202
+ }
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "@narumitw/pi-langfuse",
3
- "version": "0.50.6",
3
+ "version": "0.51.1",
4
4
  "description": "Pi extension that traces LLM generations and tool activity to Langfuse.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
7
15
  "private": false,
8
16
  "keywords": [
9
17
  "pi-package",
@@ -35,8 +43,8 @@
35
43
  "@earendil-works/pi-coding-agent": "*"
36
44
  },
37
45
  "devDependencies": {
38
- "@earendil-works/pi-coding-agent": "0.85.1",
39
- "@types/node": "26.4.1",
46
+ "@earendil-works/pi-coding-agent": "0.86.0",
47
+ "@types/node": "26.6.2",
40
48
  "typescript": "7.0.2",
41
49
  "esbuild": "0.28.2"
42
50
  },
package/src/git.ts ADDED
@@ -0,0 +1,60 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import type { GitMetadata } from "./tracing.js";
3
+
4
+ const GIT_LOOKUP_TIMEOUT_MS = 1_000;
5
+ const MAX_GIT_BRANCH_LENGTH = 256;
6
+
7
+ type GitExecutor = ExtensionAPI["exec"];
8
+
9
+ export async function resolveGitMetadata(exec: GitExecutor, cwd: string): Promise<GitMetadata | undefined> {
10
+ const [branchResult, commit] = await Promise.all([resolveGitBranch(exec, cwd), resolveGitCommit(exec, cwd)]);
11
+ if (!branchResult.resolved) return undefined;
12
+ if (branchResult.branch) {
13
+ return {
14
+ branch: branchResult.branch,
15
+ ...(commit ? { commit } : {}),
16
+ detached: false,
17
+ };
18
+ }
19
+ return commit ? { commit, detached: true } : undefined;
20
+ }
21
+
22
+ async function resolveGitBranch(exec: GitExecutor, cwd: string): Promise<{ resolved: boolean; branch?: string }> {
23
+ try {
24
+ const result = await exec("git", ["symbolic-ref", "--quiet", "--short", "HEAD"], {
25
+ cwd,
26
+ timeout: GIT_LOOKUP_TIMEOUT_MS,
27
+ });
28
+ if (result.killed) return { resolved: false };
29
+ if (result.code === 1) return { resolved: true };
30
+ if (result.code !== 0) return { resolved: false };
31
+ const branch = normalizeGitBranch(result.stdout);
32
+ return branch ? { resolved: true, branch } : { resolved: false };
33
+ } catch {
34
+ return { resolved: false };
35
+ }
36
+ }
37
+
38
+ async function resolveGitCommit(exec: GitExecutor, cwd: string): Promise<string | undefined> {
39
+ try {
40
+ const result = await exec("git", ["rev-parse", "--verify", "--short=12", "HEAD"], {
41
+ cwd,
42
+ timeout: GIT_LOOKUP_TIMEOUT_MS,
43
+ });
44
+ if (result.code !== 0 || result.killed) return undefined;
45
+ const commit = result.stdout.trim();
46
+ return /^[0-9a-f]{4,64}$/iu.test(commit) ? commit.toLowerCase() : undefined;
47
+ } catch {
48
+ return undefined;
49
+ }
50
+ }
51
+
52
+ function normalizeGitBranch(value: string): string | undefined {
53
+ const branch = value.trim();
54
+ if (!branch || branch.length > MAX_GIT_BRANCH_LENGTH) return undefined;
55
+ for (const character of branch) {
56
+ const code = character.codePointAt(0) ?? 0;
57
+ if (code <= 31 || code === 127) return undefined;
58
+ }
59
+ return branch;
60
+ }
package/src/index.ts CHANGED
@@ -1 +1,10 @@
1
1
  export { default } from "./langfuse.js";
2
+ export {
3
+ type CreateLangfuseRuntimeOptions,
4
+ createLangfuseRuntime,
5
+ createPiLangfuseSession,
6
+ type LangfuseRuntime,
7
+ type LangfuseRuntimeConfig,
8
+ type PiLangfuseSession,
9
+ type PiLangfuseSessionOptions,
10
+ } from "./public-api.js";