pi-langfuse 1.5.19 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils.ts CHANGED
@@ -334,6 +334,55 @@ export function getProviderPayload(event: Record<string, unknown>): unknown {
334
334
  return event.request ?? event.payload ?? event.body ?? event.providerPayload ?? event.messages ?? event;
335
335
  }
336
336
 
337
+ export type ToolUpdateTransport =
338
+ | "anthropic-native"
339
+ | "openai-additional-tools"
340
+ | "openai-tool-search"
341
+ | "mid-conversation-system"
342
+ | "collapsed-leading-system";
343
+
344
+ /** Classify the provider payload observed by this hook rather than guessing from the model name alone. */
345
+ export function inferToolUpdateTransport(payload: unknown, hasPriorSystemState: boolean): ToolUpdateTransport | undefined {
346
+ let sawToolChangeBlock = false;
347
+ let sawAdditionalTools = false;
348
+ let sawToolSearch = false;
349
+ let sawTopLevelTools = false;
350
+ let sawMidConversationSystem = false;
351
+ let visited = 0;
352
+
353
+ const walk = (value: unknown, key?: string) => {
354
+ if (++visited > 2_000 || value === null || value === undefined) return;
355
+ if (key === "additional_tools") sawAdditionalTools = true;
356
+ if (key === "tools") sawTopLevelTools = true;
357
+ if (key === "tool_search" || key === "tool_search_output") sawToolSearch = true;
358
+ if (typeof value !== "object") return;
359
+ if (Array.isArray(value)) {
360
+ let sawNonSystem = false;
361
+ for (const item of value) {
362
+ if (item && typeof item === "object" && !Array.isArray(item)) {
363
+ const role = (item as Record<string, unknown>).role;
364
+ if (role === "system" && sawNonSystem) sawMidConversationSystem = true;
365
+ if (role && role !== "system") sawNonSystem = true;
366
+ }
367
+ walk(item);
368
+ }
369
+ return;
370
+ }
371
+ const record = value as Record<string, unknown>;
372
+ const type = record.type;
373
+ if (type === "tool_addition" || type === "tool_removal") sawToolChangeBlock = true;
374
+ for (const [childKey, child] of Object.entries(record)) walk(child, childKey);
375
+ };
376
+
377
+ walk(payload);
378
+ if (sawToolChangeBlock) return "anthropic-native";
379
+ if (sawAdditionalTools) return "openai-additional-tools";
380
+ if (sawToolSearch) return "openai-tool-search";
381
+ if (sawMidConversationSystem) return "mid-conversation-system";
382
+ if (hasPriorSystemState && sawTopLevelTools) return "collapsed-leading-system";
383
+ return undefined;
384
+ }
385
+
337
386
  export function extractModelParameters(payload: unknown): Record<string, string | number> | undefined {
338
387
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
339
388
  return undefined;
@@ -487,6 +536,32 @@ export function extractUsage(
487
536
  };
488
537
  }
489
538
 
539
+ export function extractCacheMetrics(messageOrEvent: Record<string, unknown>): {
540
+ cacheReadTokens: number;
541
+ cacheWriteTokens: number;
542
+ uncachedInputTokens: number;
543
+ cacheHitRatio?: number;
544
+ } | undefined {
545
+ const usage = (messageOrEvent.usage ??
546
+ (messageOrEvent.message && typeof messageOrEvent.message === "object"
547
+ ? (messageOrEvent.message as Record<string, unknown>).usage
548
+ : undefined)) as Record<string, unknown> | undefined;
549
+ if (!usage || typeof usage !== "object") return undefined;
550
+
551
+ const uncachedInputTokens = Number(
552
+ usage.input ?? usage.inputTokens ?? usage.prompt_tokens ?? usage.promptTokens ?? 0,
553
+ );
554
+ const cacheReadTokens = Number(usage.cacheRead ?? usage.cache_read ?? usage.cachedTokens ?? 0);
555
+ const cacheWriteTokens = Number(usage.cacheWrite ?? usage.cache_write ?? 0);
556
+ const denominator = uncachedInputTokens + cacheReadTokens;
557
+ return {
558
+ cacheReadTokens,
559
+ cacheWriteTokens,
560
+ uncachedInputTokens,
561
+ ...(denominator > 0 ? { cacheHitRatio: cacheReadTokens / denominator } : {}),
562
+ };
563
+ }
564
+
490
565
  export function extractCostDetails(messageOrEvent: Record<string, unknown>): Record<string, number> | undefined {
491
566
  const usage = (messageOrEvent.usage ??
492
567
  (messageOrEvent.message && typeof messageOrEvent.message === "object"
@@ -1,49 +0,0 @@
1
- declare module "@opentelemetry/sdk-trace-base" {
2
- export class BasicTracerProvider {
3
- constructor(options?: { resource?: unknown; spanProcessors?: unknown[] });
4
- forceFlush?(): Promise<void>;
5
- shutdown?(): Promise<void>;
6
- }
7
- }
8
-
9
- declare module "@langfuse/otel" {
10
- export class LangfuseSpanProcessor {
11
- constructor(options: {
12
- publicKey: string;
13
- secretKey: string;
14
- baseUrl: string;
15
- });
16
- forceFlush?(): Promise<void>;
17
- shutdown?(): Promise<void>;
18
- }
19
- }
20
-
21
- declare module "@langfuse/tracing" {
22
- export function setLangfuseTracerProvider(provider: unknown): void;
23
-
24
- export function startObservation(
25
- name: string,
26
- body?: Record<string, unknown>,
27
- options?: { asType?: string },
28
- ): unknown;
29
-
30
- export function propagateAttributes<T>(
31
- params: {
32
- sessionId?: string;
33
- traceName?: string;
34
- metadata?: Record<string, string>;
35
- tags?: string[];
36
- },
37
- fn: () => T,
38
- ): T;
39
- }
40
-
41
- declare module "@langfuse/client" {
42
- export class LangfuseClient {
43
- constructor(options: {
44
- publicKey: string;
45
- secretKey: string;
46
- baseUrl: string;
47
- });
48
- }
49
- }
@@ -1,29 +0,0 @@
1
- declare module "node:fs" {
2
- export function mkdirSync(path: string, options?: { recursive?: boolean }): void;
3
- export function readFileSync(path: string, encoding: string): string;
4
- export function existsSync(path: string): boolean;
5
- export function writeFileSync(path: string, data: string, encoding: string): void;
6
- }
7
-
8
- declare module "node:crypto" {
9
- export function randomUUID(): string;
10
- }
11
-
12
- declare module "node:os" {
13
- export function homedir(): string;
14
- }
15
-
16
- declare module "node:path" {
17
- export function resolve(...paths: string[]): string;
18
- export function dirname(path: string): string;
19
- export function basename(path: string, suffix?: string): string;
20
- }
21
-
22
- declare module "node:url" {
23
- export function fileURLToPath(url: string | URL): string;
24
- }
25
-
26
- declare const process: {
27
- cwd(): string;
28
- env: Record<string, string | undefined>;
29
- };
@@ -1,16 +0,0 @@
1
- declare module "@earendil-works/pi-coding-agent" {
2
- export interface ExtensionContext {
3
- sessionManager?: {
4
- getSessionId?: () => unknown;
5
- getSessionFile?: () => unknown;
6
- };
7
- }
8
-
9
- export interface ExtensionAPI {
10
- on(event: string, handler: (event: any, ctx: any) => unknown): void;
11
- registerCommand(
12
- name: string,
13
- options: { description?: string; handler: (args: string, ctx: any) => unknown },
14
- ): void;
15
- }
16
- }