@oh-my-pi/pi-agent-core 15.10.7 → 15.10.9

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/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [15.10.8] - 2026-06-09
6
+ ### Added
7
+
8
+ - Added optional `fetch` overrides to `SummaryOptions` and `compact`/`generateSummary` so remote compaction can use custom HTTP clients
9
+ - Added optional `fetch` option to `ProxyStreamOptions` to control the HTTP request used by `streamProxy`
10
+ - Added optional `fetch` overrides to `requestOpenAiRemoteCompaction` and `requestRemoteCompaction` for injectable HTTP transport
11
+ - Added the upstream provider that served a request (`AssistantMessage.upstreamProvider`, e.g. OpenRouter's routed provider) as a `pi.gen_ai.response.upstream_provider` chat-span telemetry attribute, alongside the existing response id and time-to-first-chunk.
12
+
5
13
  ## [15.10.5] - 2026-06-08
6
14
  ### Removed
7
15
 
@@ -4,7 +4,7 @@
4
4
  * Pure functions for compaction logic. The session manager handles I/O,
5
5
  * and after compaction the session is reloaded.
6
6
  */
7
- import { type MessageAttribution, type Model, type Usage } from "@oh-my-pi/pi-ai";
7
+ import { type FetchImpl, type MessageAttribution, type Model, type Usage } from "@oh-my-pi/pi-ai";
8
8
  import { type AgentTelemetry } from "../telemetry";
9
9
  import { ThinkingLevel } from "../thinking";
10
10
  import type { AgentMessage, AgentTool } from "../types";
@@ -125,6 +125,8 @@ export interface SummaryOptions {
125
125
  * `resolveCompactionEffort` for the conversion contract.
126
126
  */
127
127
  thinkingLevel?: ThinkingLevel;
128
+ /** Optional fetch implementation threaded into remote compaction calls. */
129
+ fetch?: FetchImpl;
128
130
  }
129
131
  export declare function generateSummary(currentMessages: AgentMessage[], model: Model, reserveTokens: number, apiKey: string, signal?: AbortSignal, customInstructions?: string, previousSummary?: string, options?: SummaryOptions): Promise<string>;
130
132
  export interface HandoffOptions {
@@ -11,7 +11,7 @@
11
11
  * summarization endpoints that accept `{ systemPrompt, prompt }` and reply
12
12
  * with `{ summary, shortSummary? }`.
13
13
  */
14
- import type { Message, Model } from "@oh-my-pi/pi-ai/types";
14
+ import type { FetchImpl, Message, Model } from "@oh-my-pi/pi-ai/types";
15
15
  export declare const OPENAI_REMOTE_COMPACTION_PRESERVE_KEY = "openaiRemoteCompaction";
16
16
  export type OpenAiRemoteCompactionItem = {
17
17
  type: "compaction" | "compaction_summary";
@@ -54,5 +54,9 @@ export declare function withOpenAiRemoteCompactionPreserveData(preserveData: Rec
54
54
  * encrypted reasoning we want to preserve.
55
55
  */
56
56
  export declare function buildOpenAiNativeHistory(messages: Message[], model: Model, previousReplacementHistory?: Array<Record<string, unknown>>): Array<Record<string, unknown>>;
57
- export declare function requestOpenAiRemoteCompaction(model: Model, apiKey: string, compactInput: Array<Record<string, unknown>>, instructions: string, signal?: AbortSignal): Promise<OpenAiRemoteCompactionResponse>;
58
- export declare function requestRemoteCompaction(endpoint: string, request: RemoteCompactionRequest, signal?: AbortSignal): Promise<RemoteCompactionResponse>;
57
+ export declare function requestOpenAiRemoteCompaction(model: Model, apiKey: string, compactInput: Array<Record<string, unknown>>, instructions: string, signal?: AbortSignal, opts?: {
58
+ fetch?: FetchImpl;
59
+ }): Promise<OpenAiRemoteCompactionResponse>;
60
+ export declare function requestRemoteCompaction(endpoint: string, request: RemoteCompactionRequest, signal?: AbortSignal, opts?: {
61
+ fetch?: FetchImpl;
62
+ }): Promise<RemoteCompactionResponse>;
@@ -2,7 +2,7 @@
2
2
  * Proxy stream function for apps that route LLM calls through a server.
3
3
  * The server manages auth and proxies requests to LLM providers.
4
4
  */
5
- import { type AssistantMessage, type AssistantMessageEvent, type Context, EventStream, type Model, type SimpleStreamOptions, type StopReason } from "@oh-my-pi/pi-ai";
5
+ import { type AssistantMessage, type AssistantMessageEvent, type Context, EventStream, type FetchImpl, type Model, type SimpleStreamOptions, type StopReason } from "@oh-my-pi/pi-ai";
6
6
  export declare class ProxyMessageEventStream extends EventStream<AssistantMessageEvent, AssistantMessage> {
7
7
  constructor();
8
8
  }
@@ -60,6 +60,8 @@ export interface ProxyStreamOptions extends SimpleStreamOptions {
60
60
  authToken: string;
61
61
  /** Proxy server URL (e.g., "https://genai.example.com") */
62
62
  proxyUrl: string;
63
+ /** Optional fetch implementation; defaults to global fetch. */
64
+ fetch?: FetchImpl;
63
65
  }
64
66
  /**
65
67
  * Stream function that proxies through a server instead of calling LLM providers directly.
@@ -87,6 +87,7 @@ export declare const enum PiGenAIAttr {
87
87
  RequestMessages = "pi.gen_ai.request.messages",
88
88
  ResponseText = "pi.gen_ai.response.text",
89
89
  ResponseToolCalls = "pi.gen_ai.response.tool_calls",
90
+ ResponseUpstreamProvider = "pi.gen_ai.response.upstream_provider",
90
91
  UsageTotalTokens = "pi.gen_ai.usage.total_tokens",
91
92
  UsageServerSideTools = "pi.gen_ai.usage.server_tool_requests",
92
93
  CostEstimatedUsd = "pi.gen_ai.cost.estimated_usd",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-agent-core",
4
- "version": "15.10.7",
4
+ "version": "15.10.9",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -35,9 +35,9 @@
35
35
  "fmt": "biome format --write ."
36
36
  },
37
37
  "dependencies": {
38
- "@oh-my-pi/pi-ai": "15.10.7",
39
- "@oh-my-pi/pi-natives": "15.10.7",
40
- "@oh-my-pi/pi-utils": "15.10.7",
38
+ "@oh-my-pi/pi-ai": "15.10.9",
39
+ "@oh-my-pi/pi-natives": "15.10.9",
40
+ "@oh-my-pi/pi-utils": "15.10.9",
41
41
  "@opentelemetry/api": "^1.9.1"
42
42
  },
43
43
  "devDependencies": {
@@ -9,6 +9,7 @@ import {
9
9
  type AssistantMessage,
10
10
  clampThinkingLevelForModel,
11
11
  Effort,
12
+ type FetchImpl,
12
13
  type Message,
13
14
  type MessageAttribution,
14
15
  type Model,
@@ -595,6 +596,8 @@ export interface SummaryOptions {
595
596
  * `resolveCompactionEffort` for the conversion contract.
596
597
  */
597
598
  thinkingLevel?: ThinkingLevel;
599
+ /** Optional fetch implementation threaded into remote compaction calls. */
600
+ fetch?: FetchImpl;
598
601
  }
599
602
 
600
603
  export async function generateSummary(
@@ -647,6 +650,7 @@ export async function generateSummary(
647
650
  prompt: promptText,
648
651
  },
649
652
  signal,
653
+ { fetch: options.fetch },
650
654
  );
651
655
  return remote.summary;
652
656
  }
@@ -992,6 +996,7 @@ export async function compact(
992
996
  // silently falls back to Effort.High — the same defect e07b47ee4 fixed
993
997
  // at the call sites, leaked back in here. See resolveCompactionEffort.
994
998
  thinkingLevel: options?.thinkingLevel,
999
+ fetch: options?.fetch,
995
1000
  };
996
1001
 
997
1002
  let preserveData = withOpenAiRemoteCompactionPreserveData(previousPreserveData, undefined);
@@ -1015,6 +1020,7 @@ export async function compact(
1015
1020
  remoteHistory,
1016
1021
  summaryOptions.remoteInstructions ?? SUMMARIZATION_SYSTEM_PROMPT,
1017
1022
  signal,
1023
+ { fetch: summaryOptions.fetch },
1018
1024
  );
1019
1025
  preserveData = withOpenAiRemoteCompactionPreserveData(previousPreserveData, remote);
1020
1026
  } catch (err) {
@@ -20,7 +20,7 @@ import {
20
20
  } from "@oh-my-pi/pi-ai/providers/openai-codex/constants";
21
21
  import { parseTextSignature } from "@oh-my-pi/pi-ai/providers/openai-responses-shared";
22
22
  import { transformMessages } from "@oh-my-pi/pi-ai/providers/transform-messages";
23
- import type { AssistantMessage, Message, Model } from "@oh-my-pi/pi-ai/types";
23
+ import type { AssistantMessage, FetchImpl, Message, Model } from "@oh-my-pi/pi-ai/types";
24
24
  import {
25
25
  getOpenAIResponsesHistoryItems,
26
26
  getOpenAIResponsesHistoryPayload,
@@ -428,6 +428,7 @@ export async function requestOpenAiRemoteCompaction(
428
428
  compactInput: Array<Record<string, unknown>>,
429
429
  instructions: string,
430
430
  signal?: AbortSignal,
431
+ opts?: { fetch?: FetchImpl },
431
432
  ): Promise<OpenAiRemoteCompactionResponse> {
432
433
  const endpoint = resolveOpenAiCompactEndpoint(model);
433
434
  const request: OpenAiRemoteCompactionRequest = {
@@ -451,7 +452,7 @@ export async function requestOpenAiRemoteCompaction(
451
452
  headers[OPENAI_HEADERS.ORIGINATOR] = OPENAI_HEADER_VALUES.ORIGINATOR_CODEX;
452
453
  }
453
454
 
454
- const response = await fetch(endpoint, {
455
+ const response = await (opts?.fetch ?? fetch)(endpoint, {
455
456
  method: "POST",
456
457
  headers,
457
458
  body: JSON.stringify(request),
@@ -501,8 +502,9 @@ export async function requestRemoteCompaction(
501
502
  endpoint: string,
502
503
  request: RemoteCompactionRequest,
503
504
  signal?: AbortSignal,
505
+ opts?: { fetch?: FetchImpl },
504
506
  ): Promise<RemoteCompactionResponse> {
505
- const response = await fetch(endpoint, {
507
+ const response = await (opts?.fetch ?? fetch)(endpoint, {
506
508
  method: "POST",
507
509
  headers: { "content-type": "application/json" },
508
510
  body: JSON.stringify(request),
package/src/proxy.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  type AssistantMessageEvent,
8
8
  type Context,
9
9
  EventStream,
10
+ type FetchImpl,
10
11
  type Model,
11
12
  type SimpleStreamOptions,
12
13
  type StopReason,
@@ -61,6 +62,8 @@ export interface ProxyStreamOptions extends SimpleStreamOptions {
61
62
  authToken: string;
62
63
  /** Proxy server URL (e.g., "https://genai.example.com") */
63
64
  proxyUrl: string;
65
+ /** Optional fetch implementation; defaults to global fetch. */
66
+ fetch?: FetchImpl;
64
67
  }
65
68
 
66
69
  /**
@@ -117,7 +120,7 @@ export function streamProxy(model: Model, context: Context, options: ProxyStream
117
120
  }
118
121
 
119
122
  try {
120
- response = await fetch(`${options.proxyUrl}/api/stream`, {
123
+ response = await (options.fetch ?? fetch)(`${options.proxyUrl}/api/stream`, {
121
124
  method: "POST",
122
125
  headers: {
123
126
  Authorization: `Bearer ${options.authToken}`,
package/src/telemetry.ts CHANGED
@@ -133,6 +133,7 @@ export const enum PiGenAIAttr {
133
133
  RequestMessages = "pi.gen_ai.request.messages",
134
134
  ResponseText = "pi.gen_ai.response.text",
135
135
  ResponseToolCalls = "pi.gen_ai.response.tool_calls",
136
+ ResponseUpstreamProvider = "pi.gen_ai.response.upstream_provider",
136
137
  UsageTotalTokens = "pi.gen_ai.usage.total_tokens",
137
138
  UsageServerSideTools = "pi.gen_ai.usage.server_tool_requests",
138
139
  CostEstimatedUsd = "pi.gen_ai.cost.estimated_usd",
@@ -1189,6 +1190,9 @@ export function failChatSpan(
1189
1190
  function applyChatResponseAttributes(span: Span, message: AssistantMessage): void {
1190
1191
  span.setAttribute(GenAIAttr.ResponseModel, message.model);
1191
1192
  if (message.responseId) span.setAttribute(GenAIAttr.ResponseId, message.responseId);
1193
+ if (message.upstreamProvider) {
1194
+ span.setAttribute(PiGenAIAttr.ResponseUpstreamProvider, message.upstreamProvider);
1195
+ }
1192
1196
  if (message.ttft != null) span.setAttribute(GenAIAttr.ResponseTimeToFirstChunk, message.ttft / 1000);
1193
1197
  const finishReason = mapStopReason(message.stopReason);
1194
1198
  if (finishReason) span.setAttribute(GenAIAttr.ResponseFinishReasons, [finishReason]);