@skydiveai/pi-server 0.1.0-beta.165 → 0.1.0-beta.1738

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.d.mts CHANGED
@@ -208,30 +208,7 @@ declare function createPrewarm({
208
208
  */
209
209
  declare const KNOWN_PI_PROVIDERS: readonly ["amazon-bedrock", "anthropic", "google", "google-vertex", "openai", "azure-openai-responses", "openai-codex", "deepseek", "github-copilot", "xai", "groq", "cerebras", "openrouter", "vercel-ai-gateway", "zai", "mistral", "minimax", "minimax-cn", "moonshotai", "moonshotai-cn", "huggingface", "fireworks", "opencode", "opencode-go", "kimi-coding", "cloudflare-workers-ai", "cloudflare-ai-gateway", "xiaomi", "xiaomi-token-plan-cn", "xiaomi-token-plan-ams", "xiaomi-token-plan-sgp"];
210
210
  declare const modelSpecSchema: z.ZodDiscriminatedUnion<"api", [z.ZodObject<{
211
- api: z.ZodLiteral<"openai-completions">;
212
- compat: z.ZodOptional<z.ZodObject<{
213
- supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
214
- requiresThinkingAsText: z.ZodOptional<z.ZodBoolean>;
215
- thinkingFormat: z.ZodOptional<z.ZodEnum<["openai", "openrouter", "deepseek", "zai", "qwen", "qwen-chat-template"]>>;
216
- supportsStrictMode: z.ZodOptional<z.ZodBoolean>;
217
- maxTokensField: z.ZodOptional<z.ZodEnum<["max_completion_tokens", "max_tokens"]>>;
218
- cacheControlFormat: z.ZodOptional<z.ZodLiteral<"anthropic">>;
219
- }, "strip", z.ZodTypeAny, {
220
- supportsReasoningEffort?: boolean | undefined;
221
- requiresThinkingAsText?: boolean | undefined;
222
- thinkingFormat?: "openai" | "deepseek" | "openrouter" | "zai" | "qwen" | "qwen-chat-template" | undefined;
223
- supportsStrictMode?: boolean | undefined;
224
- maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
225
- cacheControlFormat?: "anthropic" | undefined;
226
- }, {
227
- supportsReasoningEffort?: boolean | undefined;
228
- requiresThinkingAsText?: boolean | undefined;
229
- thinkingFormat?: "openai" | "deepseek" | "openrouter" | "zai" | "qwen" | "qwen-chat-template" | undefined;
230
- supportsStrictMode?: boolean | undefined;
231
- maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
232
- cacheControlFormat?: "anthropic" | undefined;
233
- }>>; /** Exact model id the serving endpoint expects. */
234
- id: z.ZodString; /** Display name shown in pi surfaces and session logs. */
211
+ /** Exact model id the serving endpoint expects. */id: z.ZodString; /** Display name shown in pi surfaces and session logs. */
235
212
  name: z.ZodString; /** pi-ai provider key — also the auth-storage key for `apiKey`. */
236
213
  provider: z.ZodEnum<["amazon-bedrock", "anthropic", "google", "google-vertex", "openai", "azure-openai-responses", "openai-codex", "deepseek", "github-copilot", "xai", "groq", "cerebras", "openrouter", "vercel-ai-gateway", "zai", "mistral", "minimax", "minimax-cn", "moonshotai", "moonshotai-cn", "huggingface", "fireworks", "opencode", "opencode-go", "kimi-coding", "cloudflare-workers-ai", "cloudflare-ai-gateway", "xiaomi", "xiaomi-token-plan-cn", "xiaomi-token-plan-ams", "xiaomi-token-plan-sgp"]>; /** Provider API root, e.g. "https://openrouter.ai/api/v1". */
237
214
  baseUrl: z.ZodString;
@@ -244,17 +221,17 @@ declare const modelSpecSchema: z.ZodDiscriminatedUnion<"api", [z.ZodObject<{
244
221
  high: z.ZodOptional<z.ZodNullable<z.ZodString>>;
245
222
  xhigh: z.ZodOptional<z.ZodNullable<z.ZodString>>;
246
223
  }, "strip", z.ZodTypeAny, {
247
- medium?: string | null | undefined;
248
224
  off?: string | null | undefined;
249
225
  minimal?: string | null | undefined;
250
226
  low?: string | null | undefined;
227
+ medium?: string | null | undefined;
251
228
  high?: string | null | undefined;
252
229
  xhigh?: string | null | undefined;
253
230
  }, {
254
- medium?: string | null | undefined;
255
231
  off?: string | null | undefined;
256
232
  minimal?: string | null | undefined;
257
233
  low?: string | null | undefined;
234
+ medium?: string | null | undefined;
258
235
  high?: string | null | undefined;
259
236
  xhigh?: string | null | undefined;
260
237
  }>>;
@@ -268,73 +245,85 @@ declare const modelSpecSchema: z.ZodDiscriminatedUnion<"api", [z.ZodObject<{
268
245
  * placeholder that layer recognizes — the value is opaque to this server.
269
246
  */
270
247
  apiKey: z.ZodOptional<z.ZodString>;
248
+ api: z.ZodLiteral<"openai-completions">;
249
+ compat: z.ZodOptional<z.ZodObject<{
250
+ supportsReasoningEffort: z.ZodOptional<z.ZodBoolean>;
251
+ requiresThinkingAsText: z.ZodOptional<z.ZodBoolean>;
252
+ thinkingFormat: z.ZodOptional<z.ZodEnum<["openai", "openrouter", "deepseek", "zai", "qwen", "qwen-chat-template"]>>;
253
+ supportsStrictMode: z.ZodOptional<z.ZodBoolean>;
254
+ maxTokensField: z.ZodOptional<z.ZodEnum<["max_completion_tokens", "max_tokens"]>>;
255
+ cacheControlFormat: z.ZodOptional<z.ZodLiteral<"anthropic">>;
256
+ }, "strip", z.ZodTypeAny, {
257
+ supportsReasoningEffort?: boolean | undefined;
258
+ requiresThinkingAsText?: boolean | undefined;
259
+ thinkingFormat?: "deepseek" | "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
260
+ supportsStrictMode?: boolean | undefined;
261
+ maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
262
+ cacheControlFormat?: "anthropic" | undefined;
263
+ }, {
264
+ supportsReasoningEffort?: boolean | undefined;
265
+ requiresThinkingAsText?: boolean | undefined;
266
+ thinkingFormat?: "deepseek" | "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
267
+ supportsStrictMode?: boolean | undefined;
268
+ maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
269
+ cacheControlFormat?: "anthropic" | undefined;
270
+ }>>;
271
271
  }, "strip", z.ZodTypeAny, {
272
- api: "openai-completions";
273
272
  id: string;
274
273
  name: string;
275
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
274
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
276
275
  baseUrl: string;
277
276
  reasoning: boolean;
278
- input: ["text" | "image", ...("text" | "image")[]];
277
+ thinkingLevelMap?: {
278
+ off?: string | null | undefined;
279
+ minimal?: string | null | undefined;
280
+ low?: string | null | undefined;
281
+ medium?: string | null | undefined;
282
+ high?: string | null | undefined;
283
+ xhigh?: string | null | undefined;
284
+ } | undefined;
285
+ input: ["image" | "text", ...("image" | "text")[]];
279
286
  contextWindow: number;
280
287
  maxTokens: number;
288
+ apiKey?: string | undefined;
289
+ api: "openai-completions";
281
290
  compat?: {
282
291
  supportsReasoningEffort?: boolean | undefined;
283
292
  requiresThinkingAsText?: boolean | undefined;
284
- thinkingFormat?: "openai" | "deepseek" | "openrouter" | "zai" | "qwen" | "qwen-chat-template" | undefined;
293
+ thinkingFormat?: "deepseek" | "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
285
294
  supportsStrictMode?: boolean | undefined;
286
295
  maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
287
296
  cacheControlFormat?: "anthropic" | undefined;
288
297
  } | undefined;
298
+ }, {
299
+ id: string;
300
+ name: string;
301
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
302
+ baseUrl: string;
303
+ reasoning: boolean;
289
304
  thinkingLevelMap?: {
290
- medium?: string | null | undefined;
291
305
  off?: string | null | undefined;
292
306
  minimal?: string | null | undefined;
293
307
  low?: string | null | undefined;
308
+ medium?: string | null | undefined;
294
309
  high?: string | null | undefined;
295
310
  xhigh?: string | null | undefined;
296
311
  } | undefined;
297
- apiKey?: string | undefined;
298
- }, {
299
- api: "openai-completions";
300
- id: string;
301
- name: string;
302
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
303
- baseUrl: string;
304
- reasoning: boolean;
305
- input: ["text" | "image", ...("text" | "image")[]];
312
+ input: ["image" | "text", ...("image" | "text")[]];
306
313
  contextWindow: number;
307
314
  maxTokens: number;
315
+ apiKey?: string | undefined;
316
+ api: "openai-completions";
308
317
  compat?: {
309
318
  supportsReasoningEffort?: boolean | undefined;
310
319
  requiresThinkingAsText?: boolean | undefined;
311
- thinkingFormat?: "openai" | "deepseek" | "openrouter" | "zai" | "qwen" | "qwen-chat-template" | undefined;
320
+ thinkingFormat?: "deepseek" | "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
312
321
  supportsStrictMode?: boolean | undefined;
313
322
  maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
314
323
  cacheControlFormat?: "anthropic" | undefined;
315
324
  } | undefined;
316
- thinkingLevelMap?: {
317
- medium?: string | null | undefined;
318
- off?: string | null | undefined;
319
- minimal?: string | null | undefined;
320
- low?: string | null | undefined;
321
- high?: string | null | undefined;
322
- xhigh?: string | null | undefined;
323
- } | undefined;
324
- apiKey?: string | undefined;
325
325
  }>, z.ZodObject<{
326
- api: z.ZodLiteral<"anthropic-messages">;
327
- compat: z.ZodOptional<z.ZodObject<{
328
- supportsEagerToolInputStreaming: z.ZodOptional<z.ZodBoolean>;
329
- supportsLongCacheRetention: z.ZodOptional<z.ZodBoolean>;
330
- }, "strip", z.ZodTypeAny, {
331
- supportsEagerToolInputStreaming?: boolean | undefined;
332
- supportsLongCacheRetention?: boolean | undefined;
333
- }, {
334
- supportsEagerToolInputStreaming?: boolean | undefined;
335
- supportsLongCacheRetention?: boolean | undefined;
336
- }>>; /** Exact model id the serving endpoint expects. */
337
- id: z.ZodString; /** Display name shown in pi surfaces and session logs. */
326
+ /** Exact model id the serving endpoint expects. */id: z.ZodString; /** Display name shown in pi surfaces and session logs. */
338
327
  name: z.ZodString; /** pi-ai provider key — also the auth-storage key for `apiKey`. */
339
328
  provider: z.ZodEnum<["amazon-bedrock", "anthropic", "google", "google-vertex", "openai", "azure-openai-responses", "openai-codex", "deepseek", "github-copilot", "xai", "groq", "cerebras", "openrouter", "vercel-ai-gateway", "zai", "mistral", "minimax", "minimax-cn", "moonshotai", "moonshotai-cn", "huggingface", "fireworks", "opencode", "opencode-go", "kimi-coding", "cloudflare-workers-ai", "cloudflare-ai-gateway", "xiaomi", "xiaomi-token-plan-cn", "xiaomi-token-plan-ams", "xiaomi-token-plan-sgp"]>; /** Provider API root, e.g. "https://openrouter.ai/api/v1". */
340
329
  baseUrl: z.ZodString;
@@ -347,17 +336,17 @@ declare const modelSpecSchema: z.ZodDiscriminatedUnion<"api", [z.ZodObject<{
347
336
  high: z.ZodOptional<z.ZodNullable<z.ZodString>>;
348
337
  xhigh: z.ZodOptional<z.ZodNullable<z.ZodString>>;
349
338
  }, "strip", z.ZodTypeAny, {
350
- medium?: string | null | undefined;
351
339
  off?: string | null | undefined;
352
340
  minimal?: string | null | undefined;
353
341
  low?: string | null | undefined;
342
+ medium?: string | null | undefined;
354
343
  high?: string | null | undefined;
355
344
  xhigh?: string | null | undefined;
356
345
  }, {
357
- medium?: string | null | undefined;
358
346
  off?: string | null | undefined;
359
347
  minimal?: string | null | undefined;
360
348
  low?: string | null | undefined;
349
+ medium?: string | null | undefined;
361
350
  high?: string | null | undefined;
362
351
  xhigh?: string | null | undefined;
363
352
  }>>;
@@ -371,52 +360,63 @@ declare const modelSpecSchema: z.ZodDiscriminatedUnion<"api", [z.ZodObject<{
371
360
  * placeholder that layer recognizes — the value is opaque to this server.
372
361
  */
373
362
  apiKey: z.ZodOptional<z.ZodString>;
363
+ api: z.ZodLiteral<"anthropic-messages">;
364
+ compat: z.ZodOptional<z.ZodObject<{
365
+ supportsEagerToolInputStreaming: z.ZodOptional<z.ZodBoolean>;
366
+ supportsLongCacheRetention: z.ZodOptional<z.ZodBoolean>;
367
+ }, "strip", z.ZodTypeAny, {
368
+ supportsEagerToolInputStreaming?: boolean | undefined;
369
+ supportsLongCacheRetention?: boolean | undefined;
370
+ }, {
371
+ supportsEagerToolInputStreaming?: boolean | undefined;
372
+ supportsLongCacheRetention?: boolean | undefined;
373
+ }>>;
374
374
  }, "strip", z.ZodTypeAny, {
375
- api: "anthropic-messages";
376
375
  id: string;
377
376
  name: string;
378
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
377
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
379
378
  baseUrl: string;
380
379
  reasoning: boolean;
381
- input: ["text" | "image", ...("text" | "image")[]];
382
- contextWindow: number;
383
- maxTokens: number;
384
- compat?: {
385
- supportsEagerToolInputStreaming?: boolean | undefined;
386
- supportsLongCacheRetention?: boolean | undefined;
387
- } | undefined;
388
380
  thinkingLevelMap?: {
389
- medium?: string | null | undefined;
390
381
  off?: string | null | undefined;
391
382
  minimal?: string | null | undefined;
392
383
  low?: string | null | undefined;
384
+ medium?: string | null | undefined;
393
385
  high?: string | null | undefined;
394
386
  xhigh?: string | null | undefined;
395
387
  } | undefined;
396
- apiKey?: string | undefined;
397
- }, {
398
- api: "anthropic-messages";
399
- id: string;
400
- name: string;
401
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
402
- baseUrl: string;
403
- reasoning: boolean;
404
- input: ["text" | "image", ...("text" | "image")[]];
388
+ input: ["image" | "text", ...("image" | "text")[]];
405
389
  contextWindow: number;
406
390
  maxTokens: number;
391
+ apiKey?: string | undefined;
392
+ api: "anthropic-messages";
407
393
  compat?: {
408
394
  supportsEagerToolInputStreaming?: boolean | undefined;
409
395
  supportsLongCacheRetention?: boolean | undefined;
410
396
  } | undefined;
397
+ }, {
398
+ id: string;
399
+ name: string;
400
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
401
+ baseUrl: string;
402
+ reasoning: boolean;
411
403
  thinkingLevelMap?: {
412
- medium?: string | null | undefined;
413
404
  off?: string | null | undefined;
414
405
  minimal?: string | null | undefined;
415
406
  low?: string | null | undefined;
407
+ medium?: string | null | undefined;
416
408
  high?: string | null | undefined;
417
409
  xhigh?: string | null | undefined;
418
410
  } | undefined;
411
+ input: ["image" | "text", ...("image" | "text")[]];
412
+ contextWindow: number;
413
+ maxTokens: number;
419
414
  apiKey?: string | undefined;
415
+ api: "anthropic-messages";
416
+ compat?: {
417
+ supportsEagerToolInputStreaming?: boolean | undefined;
418
+ supportsLongCacheRetention?: boolean | undefined;
419
+ } | undefined;
420
420
  }>]>;
421
421
  type ModelSpec = z.infer<typeof modelSpecSchema>;
422
422
  /**
@@ -426,16 +426,20 @@ type ModelSpec = z.infer<typeof modelSpecSchema>;
426
426
  */
427
427
  declare function parseModelSpec(input: unknown, log: Logger): ModelSpec | null;
428
428
  declare function buildModelFromSpec(spec: ModelSpec): {
429
- compat?: {
430
- supportsReasoningEffort?: boolean | undefined;
431
- requiresThinkingAsText?: boolean | undefined;
432
- thinkingFormat?: "openai" | "deepseek" | "openrouter" | "zai" | "qwen" | "qwen-chat-template" | undefined;
433
- supportsStrictMode?: boolean | undefined;
434
- maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
435
- cacheControlFormat?: "anthropic" | undefined;
429
+ id: string;
430
+ name: string;
431
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
432
+ baseUrl: string;
433
+ reasoning: boolean;
434
+ thinkingLevelMap?: {
435
+ off?: string | null | undefined;
436
+ minimal?: string | null | undefined;
437
+ low?: string | null | undefined;
438
+ medium?: string | null | undefined;
439
+ high?: string | null | undefined;
440
+ xhigh?: string | null | undefined;
436
441
  } | undefined;
437
- api: "openai-completions";
438
- input: ["text" | "image", ...("text" | "image")[]];
442
+ input: ["image" | "text", ...("image" | "text")[]];
439
443
  cost: {
440
444
  input: number;
441
445
  output: number;
@@ -444,26 +448,30 @@ declare function buildModelFromSpec(spec: ModelSpec): {
444
448
  };
445
449
  contextWindow: number;
446
450
  maxTokens: number;
451
+ api: "openai-completions";
452
+ compat?: {
453
+ supportsReasoningEffort?: boolean | undefined;
454
+ requiresThinkingAsText?: boolean | undefined;
455
+ thinkingFormat?: "deepseek" | "openai" | "openrouter" | "qwen" | "qwen-chat-template" | "zai" | undefined;
456
+ supportsStrictMode?: boolean | undefined;
457
+ maxTokensField?: "max_completion_tokens" | "max_tokens" | undefined;
458
+ cacheControlFormat?: "anthropic" | undefined;
459
+ } | undefined;
460
+ } | {
461
+ id: string;
462
+ name: string;
463
+ provider: "amazon-bedrock" | "anthropic" | "azure-openai-responses" | "cerebras" | "cloudflare-ai-gateway" | "cloudflare-workers-ai" | "deepseek" | "fireworks" | "github-copilot" | "google" | "google-vertex" | "groq" | "huggingface" | "kimi-coding" | "minimax" | "minimax-cn" | "mistral" | "moonshotai" | "moonshotai-cn" | "openai" | "openai-codex" | "opencode" | "opencode-go" | "openrouter" | "vercel-ai-gateway" | "xai" | "xiaomi" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-sgp" | "zai";
464
+ baseUrl: string;
465
+ reasoning: boolean;
447
466
  thinkingLevelMap?: {
448
- medium?: string | null | undefined;
449
467
  off?: string | null | undefined;
450
468
  minimal?: string | null | undefined;
451
469
  low?: string | null | undefined;
470
+ medium?: string | null | undefined;
452
471
  high?: string | null | undefined;
453
472
  xhigh?: string | null | undefined;
454
473
  } | undefined;
455
- id: string;
456
- name: string;
457
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
458
- baseUrl: string;
459
- reasoning: boolean;
460
- } | {
461
- compat?: {
462
- supportsEagerToolInputStreaming?: boolean | undefined;
463
- supportsLongCacheRetention?: boolean | undefined;
464
- } | undefined;
465
- api: "anthropic-messages";
466
- input: ["text" | "image", ...("text" | "image")[]];
474
+ input: ["image" | "text", ...("image" | "text")[]];
467
475
  cost: {
468
476
  input: number;
469
477
  output: number;
@@ -472,19 +480,11 @@ declare function buildModelFromSpec(spec: ModelSpec): {
472
480
  };
473
481
  contextWindow: number;
474
482
  maxTokens: number;
475
- thinkingLevelMap?: {
476
- medium?: string | null | undefined;
477
- off?: string | null | undefined;
478
- minimal?: string | null | undefined;
479
- low?: string | null | undefined;
480
- high?: string | null | undefined;
481
- xhigh?: string | null | undefined;
483
+ api: "anthropic-messages";
484
+ compat?: {
485
+ supportsEagerToolInputStreaming?: boolean | undefined;
486
+ supportsLongCacheRetention?: boolean | undefined;
482
487
  } | undefined;
483
- id: string;
484
- name: string;
485
- provider: "anthropic" | "amazon-bedrock" | "google" | "google-vertex" | "openai" | "azure-openai-responses" | "openai-codex" | "deepseek" | "github-copilot" | "xai" | "groq" | "cerebras" | "openrouter" | "vercel-ai-gateway" | "zai" | "mistral" | "minimax" | "minimax-cn" | "moonshotai" | "moonshotai-cn" | "huggingface" | "fireworks" | "opencode" | "opencode-go" | "kimi-coding" | "cloudflare-workers-ai" | "cloudflare-ai-gateway" | "xiaomi" | "xiaomi-token-plan-cn" | "xiaomi-token-plan-ams" | "xiaomi-token-plan-sgp";
486
- baseUrl: string;
487
- reasoning: boolean;
488
488
  };
489
489
  /**
490
490
  * Resolve the model a request should run on: a valid `x_model` wins,
@@ -542,4 +542,27 @@ declare function getCurrentTraceparent(): string | null;
542
542
  /** Extract the trace id (second segment) from a `traceparent` value. */
543
543
  declare function parseTraceId(traceparent: string | null): string | null;
544
544
  //#endregion
545
- export { type A2AOptions, type AnthropicMessagesOptions, type ChatCompletionsOptions, type CreateSessionArgs, DEFAULT_MODEL, DEFAULT_PROVIDER, DEFAULT_THINKING_LEVEL, KNOWN_PI_PROVIDERS, type Middleware, type ModelSpec, PI_AGENT_DIR, type PostPromptCallback, type ProtocolHandler, type ProtocolsOptions, type ResponsesOptions, type SessionFactory, type SessionSetupCallback, type TraceContext, VALID_THINKING_LEVELS, type WebHandler, buildAgentCard, buildModelFromSpec, chainMiddleware, composeHandlers, createAgentExecutor, createMapSessionRegistry, createPrewarm, createProtocolHandlers, createProtocols, deriveTraceContext, getCurrentTraceparent, logger, modelSpecSchema, mountAt, newTraceContext, parseModelSpec, parseTraceId, requestHeaders, requestLogger, requestUrl, resolveRequestModel, runInTraceContext, setCurrentTraceparent, webHandlerToMiddleware, withSpecApiKey };
545
+ //#region src/billing-blocked-provider-signal.d.ts
546
+ /**
547
+ * Duplicated from the billing gate's `BlockReason` (apps/anyone/billing
548
+ * gate/block-reason.ts): pi-server runs inside the sandbox and must not
549
+ * depend on platform packages. A reason the proxy sends that predates this
550
+ * build fails the enum and degrades to the untyped `billing_blocked`
551
+ * handling — never a crash. Exported so agent-lifecycle's chat.test.ts can
552
+ * pin this copy against its own (which billing's block-reason.test.ts in
553
+ * turn pins against the gate), keeping every copy drift-checked.
554
+ */
555
+ declare const BILLING_BLOCK_REASONS: readonly ["insufficient_balance", "payment_failed", "hard_spend_limit_reached"];
556
+ declare const payloadSchema: z.ZodObject<{
557
+ blockReason: z.ZodEnum<["insufficient_balance", "payment_failed", "hard_spend_limit_reached"]>;
558
+ message: z.ZodString;
559
+ }, "strict", z.ZodTypeAny, {
560
+ blockReason: "hard_spend_limit_reached" | "insufficient_balance" | "payment_failed";
561
+ message: string;
562
+ }, {
563
+ blockReason: "hard_spend_limit_reached" | "insufficient_balance" | "payment_failed";
564
+ message: string;
565
+ }>;
566
+ type BillingBlockedProviderSignal = z.infer<typeof payloadSchema>;
567
+ //#endregion
568
+ export { type A2AOptions, type AnthropicMessagesOptions, BILLING_BLOCK_REASONS, type BillingBlockedProviderSignal, type ChatCompletionsOptions, type CreateSessionArgs, DEFAULT_MODEL, DEFAULT_PROVIDER, DEFAULT_THINKING_LEVEL, KNOWN_PI_PROVIDERS, type Middleware, type ModelSpec, PI_AGENT_DIR, type PostPromptCallback, type ProtocolHandler, type ProtocolsOptions, type ResponsesOptions, type SessionFactory, type SessionSetupCallback, type TraceContext, VALID_THINKING_LEVELS, type WebHandler, buildAgentCard, buildModelFromSpec, chainMiddleware, composeHandlers, createAgentExecutor, createMapSessionRegistry, createPrewarm, createProtocolHandlers, createProtocols, deriveTraceContext, getCurrentTraceparent, logger, modelSpecSchema, mountAt, newTraceContext, parseModelSpec, parseTraceId, requestHeaders, requestLogger, requestUrl, resolveRequestModel, runInTraceContext, setCurrentTraceparent, webHandlerToMiddleware, withSpecApiKey };
package/dist/index.mjs CHANGED
@@ -373,6 +373,57 @@ async function runConversation({ session, prompt, images, log, postPrompt }) {
373
373
  });
374
374
  }
375
375
  /**
376
+ * Track the agent session's built-in model-call auto-retry so it leaves a
377
+ * trace.
378
+ *
379
+ * `AgentSession` already restarts a failed assistant turn in place (via
380
+ * `agent.continue()`, so no prompt is replayed and no tool re-executes) for the
381
+ * transient provider/transport failures pi classifies as retryable -- dropped
382
+ * streams, `terminated`, 5xx, overloaded, rate limits. It is on by default,
383
+ * with its own budget and backoff, and it emits `auto_retry_start` /
384
+ * `auto_retry_end` around each attempt.
385
+ *
386
+ * Nothing consumed those events, so a retry left no trace anywhere: a call that
387
+ * succeeded first try and one that burned the whole budget before failing
388
+ * produced the same terminal error, and the fleet-wide retry rate was
389
+ * unmeasurable. That gap is why a 2026-08-16 investigation into three runs lost
390
+ * to `provider_error: terminated` could not tell whether the budget had run out
391
+ * (ANY-7101).
392
+ *
393
+ * Exposed as a handler rather than its own `session.subscribe` call so each
394
+ * protocol feeds it from the single subscription it already owns -- one
395
+ * subscriber, explicit ordering.
396
+ *
397
+ * `attempts()` reports what has been spent so far, so a terminal error can
398
+ * carry the count to the worker, where it lands in a log group we can query
399
+ * fleet-wide (the sandbox's own logs are not).
400
+ */
401
+ function createAutoRetryObserver(log) {
402
+ let attempts = 0;
403
+ return {
404
+ observe(event) {
405
+ if (event.type === "auto_retry_start") {
406
+ attempts = typeof event.attempt === "number" ? event.attempt : attempts + 1;
407
+ log.warn({
408
+ event: "model_call_auto_retry",
409
+ attempt: event.attempt,
410
+ max_attempts: event.maxAttempts,
411
+ delay_ms: event.delayMs,
412
+ error_message: event.errorMessage
413
+ }, "retrying failed model call in place");
414
+ return;
415
+ }
416
+ if (event.type === "auto_retry_end") log.warn({
417
+ event: "model_call_auto_retry_end",
418
+ attempt: event.attempt,
419
+ success: event.success,
420
+ final_error: event.finalError
421
+ }, event.success ? "model call recovered after retry" : "model call retries exhausted");
422
+ },
423
+ attempts: () => attempts
424
+ };
425
+ }
426
+ /**
376
427
  * Hard-stop the in-flight turn for a session. Shared by every protocol's
377
428
  * `/:id/abort` route: a cancel signals the stop explicitly instead of relying
378
429
  * on a dropped connection. `session.abort()` interrupts the turn and resolves
@@ -877,6 +928,7 @@ function classifyCode(status, message, code) {
877
928
  if (status === 429 || code === "rate_limit_exceeded" || /rate[_ ]limit|too many requests|resource[_ ]exhausted/i.test(message)) return "rate_limited";
878
929
  if (status === 529 || code === "provider_overloaded" || /overloaded/i.test(message)) return "provider_overloaded";
879
930
  if (status === 503 || status === 504 || code === "provider_unavailable" || /no healthy upstream|upstream request timeout|stream timeout|service unavailable|unavailable|gateway/i.test(message)) return "provider_unavailable";
931
+ if (code === "content_filter" || /finish_reason:\s*content_filter|content[_ ]filter|content[_ ]management[_ ]policy/i.test(message)) return "content_filter";
880
932
  return "provider_error";
881
933
  }
882
934
  /**
@@ -891,7 +943,7 @@ function isModelProviderError(err) {
891
943
  if (numericStatus(e) !== null) return true;
892
944
  if (e.error && typeof e.error === "object") return true;
893
945
  const msg = messageText(err);
894
- return /prompt is too long|context[_ ]length[_ ]exceeded|exceeds maximum token limit|input token count|rate[_ ]limit|overloaded|no healthy upstream|upstream request timeout|insufficient credits|requires more credits|credit balance is too low|payment required|purchase more credits/i.test(msg);
946
+ return /prompt is too long|context[_ ]length[_ ]exceeded|exceeds maximum token limit|input token count|rate[_ ]limit|overloaded|no healthy upstream|upstream request timeout|insufficient credits|requires more credits|credit balance is too low|payment required|purchase more credits|finish_reason:\s*content_filter|content[_ ]filter|content[_ ]management[_ ]policy/i.test(msg);
895
947
  }
896
948
  /** Build the structured, forwardable error from a thrown model-provider error. */
897
949
  function toModelProviderError(err) {
@@ -1158,12 +1210,14 @@ function runStream$2({ session, sm, prompt, images, id, sessionId, modelName, lo
1158
1210
  textBlockOpen = false;
1159
1211
  };
1160
1212
  let capturedModelError = null;
1213
+ const autoRetry = createAutoRetryObserver(log);
1161
1214
  const emitProviderError = (providerError) => {
1162
1215
  log.warn({
1163
1216
  event: "model_provider_error",
1164
1217
  code: providerError.code,
1165
1218
  upstream_status: providerError.upstreamStatus,
1166
- provider: providerError.provider
1219
+ provider: providerError.provider,
1220
+ retry_attempts: autoRetry.attempts()
1167
1221
  }, "forwarding model-provider error to client");
1168
1222
  sseEvent(writer, "error", {
1169
1223
  type: "error",
@@ -1173,13 +1227,15 @@ function runStream$2({ session, sm, prompt, images, id, sessionId, modelName, lo
1173
1227
  x_model_provider_error: {
1174
1228
  code: providerError.code,
1175
1229
  provider: providerError.provider,
1176
- upstream_status: providerError.upstreamStatus
1230
+ upstream_status: providerError.upstreamStatus,
1231
+ retry_attempts: autoRetry.attempts()
1177
1232
  }
1178
1233
  }
1179
1234
  });
1180
1235
  };
1181
1236
  session.subscribe((event) => {
1182
1237
  const ev = event;
1238
+ autoRetry.observe(ev);
1183
1239
  const endedMessage = ev.message ?? (Array.isArray(ev.messages) ? ev.messages[ev.messages.length - 1] : null);
1184
1240
  if (endedMessage?.stopReason === "error" && typeof endedMessage.errorMessage === "string" && endedMessage.errorMessage.length > 0) capturedModelError = endedMessage.errorMessage;
1185
1241
  if (ev.type !== "message_update") return;
@@ -1379,6 +1435,65 @@ function create$2(options) {
1379
1435
  };
1380
1436
  }
1381
1437
  //#endregion
1438
+ //#region src/billing-blocked-provider-signal.ts
1439
+ const BILLING_BLOCKED_PROVIDER_SIGNAL_PREFIX = "ANYONE_BILLING_BLOCKED_V1:";
1440
+ /**
1441
+ * Duplicated from the billing gate's `BlockReason` (apps/anyone/billing
1442
+ * gate/block-reason.ts): pi-server runs inside the sandbox and must not
1443
+ * depend on platform packages. A reason the proxy sends that predates this
1444
+ * build fails the enum and degrades to the untyped `billing_blocked`
1445
+ * handling — never a crash. Exported so agent-lifecycle's chat.test.ts can
1446
+ * pin this copy against its own (which billing's block-reason.test.ts in
1447
+ * turn pins against the gate), keeping every copy drift-checked.
1448
+ */
1449
+ const BILLING_BLOCK_REASONS = [
1450
+ "insufficient_balance",
1451
+ "payment_failed",
1452
+ "hard_spend_limit_reached"
1453
+ ];
1454
+ const payloadSchema = z.object({
1455
+ blockReason: z.enum(BILLING_BLOCK_REASONS),
1456
+ message: z.string()
1457
+ }).strict();
1458
+ const nestedProxyEnvelopeSchema = z.object({
1459
+ error: z.object({
1460
+ type: z.literal("billing_blocked"),
1461
+ code: z.literal("billing_blocked"),
1462
+ message: z.string()
1463
+ }).strict(),
1464
+ blockReason: z.enum(BILLING_BLOCK_REASONS),
1465
+ message: z.string()
1466
+ }).strict();
1467
+ function parsePrefixedSignal(message) {
1468
+ const normalized = message.startsWith("402 ") ? message.slice(4) : message;
1469
+ if (!normalized.startsWith(BILLING_BLOCKED_PROVIDER_SIGNAL_PREFIX)) return null;
1470
+ try {
1471
+ const parsed = payloadSchema.safeParse(JSON.parse(normalized.slice(26)));
1472
+ return parsed.success ? parsed.data : null;
1473
+ } catch {
1474
+ return null;
1475
+ }
1476
+ }
1477
+ /**
1478
+ * Decode only the versioned platform envelope. Anthropic and OpenAI prefix the
1479
+ * nested error message with HTTP 402. Google's SDK instead preserves the full
1480
+ * proxy response as JSON, so that outer shape is validated separately.
1481
+ */
1482
+ function parseBillingBlockedProviderSignal(message) {
1483
+ const direct = parsePrefixedSignal(message);
1484
+ if (direct) return direct;
1485
+ try {
1486
+ const envelope = nestedProxyEnvelopeSchema.safeParse(JSON.parse(message));
1487
+ if (!envelope.success) return null;
1488
+ const nested = parsePrefixedSignal(envelope.data.error.message);
1489
+ const topLevel = parsePrefixedSignal(envelope.data.message);
1490
+ if (!nested || nested.blockReason !== envelope.data.blockReason || envelope.data.message !== nested.message && (!topLevel || topLevel.blockReason !== nested.blockReason || topLevel.message !== nested.message)) return null;
1491
+ return nested;
1492
+ } catch {
1493
+ return null;
1494
+ }
1495
+ }
1496
+ //#endregion
1382
1497
  //#region src/protocols/chat-completions.ts
1383
1498
  /**
1384
1499
  * OpenAI Chat Completions–compatible protocol handler.
@@ -1605,6 +1720,10 @@ async function loadHistoryIntoSession({ sm, messages, upToIdxExclusive, modelNam
1605
1720
  }
1606
1721
  }
1607
1722
  }
1723
+ function messageTimestampMs(m) {
1724
+ const ts = m?.timestamp;
1725
+ return typeof ts === "number" && Number.isFinite(ts) ? ts : null;
1726
+ }
1608
1727
  function piMessagesToOpenAI(messages) {
1609
1728
  const out = [];
1610
1729
  for (const m of messages) {
@@ -1633,6 +1752,8 @@ function piMessagesToOpenAI(messages) {
1633
1752
  };
1634
1753
  if (toolCalls.length) msg.tool_calls = toolCalls;
1635
1754
  if (thinking.length) msg.x_thinking = thinking;
1755
+ const createdAtMs = messageTimestampMs(m);
1756
+ if (createdAtMs !== null) msg.x_created_at = createdAtMs;
1636
1757
  out.push(msg);
1637
1758
  continue;
1638
1759
  }
@@ -1644,6 +1765,8 @@ function piMessagesToOpenAI(messages) {
1644
1765
  content: text
1645
1766
  };
1646
1767
  if (m.isError) tm.x_is_error = true;
1768
+ const createdAtMs = messageTimestampMs(m);
1769
+ if (createdAtMs !== null) tm.x_created_at = createdAtMs;
1647
1770
  out.push(tm);
1648
1771
  continue;
1649
1772
  }
@@ -1788,6 +1911,7 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1788
1911
  let usage = null;
1789
1912
  let lastFollowUpCount = 0;
1790
1913
  let capturedModelError = null;
1914
+ const autoRetry = createAutoRetryObserver(log);
1791
1915
  const sendChunk = (delta, finishReason) => {
1792
1916
  if (firstChunkAt === null) {
1793
1917
  firstChunkAt = performance.now();
@@ -1818,6 +1942,7 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1818
1942
  let _evCount = 0;
1819
1943
  session.subscribe((event) => {
1820
1944
  const ev = event;
1945
+ autoRetry.observe(ev);
1821
1946
  const endedMessage = ev.message ?? (Array.isArray(ev.messages) ? ev.messages[ev.messages.length - 1] : null);
1822
1947
  if (endedMessage?.stopReason === "error" && typeof endedMessage.errorMessage === "string" && endedMessage.errorMessage.length > 0) capturedModelError = endedMessage.errorMessage;
1823
1948
  if (ev.type === "queue_update") {
@@ -1922,6 +2047,22 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1922
2047
  postPrompt
1923
2048
  });
1924
2049
  if (capturedModelError !== null) {
2050
+ const billingBlocked = parseBillingBlockedProviderSignal(capturedModelError);
2051
+ if (billingBlocked) {
2052
+ log.warn({
2053
+ event: "billing_blocked",
2054
+ chatcmpl_id: sessionId,
2055
+ source: "stop_reason_error"
2056
+ }, "forwarding platform billing block to client");
2057
+ emitBillingBlocked({
2058
+ writer,
2059
+ sessionId,
2060
+ created,
2061
+ billingBlocked
2062
+ });
2063
+ writer.write("data: [DONE]\n\n");
2064
+ return;
2065
+ }
1925
2066
  const providerError = toModelProviderError(new Error(capturedModelError));
1926
2067
  log.warn({
1927
2068
  event: "model_provider_error",
@@ -1929,13 +2070,15 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1929
2070
  code: providerError.code,
1930
2071
  upstream_status: providerError.upstreamStatus,
1931
2072
  provider: providerError.provider,
2073
+ retry_attempts: autoRetry.attempts(),
1932
2074
  source: "stop_reason_error"
1933
2075
  }, "forwarding model-provider error to client");
1934
2076
  emitModelProviderError({
1935
2077
  writer,
1936
2078
  sessionId,
1937
2079
  created,
1938
- providerError
2080
+ providerError,
2081
+ retryAttempts: autoRetry.attempts()
1939
2082
  });
1940
2083
  writer.write("data: [DONE]\n\n");
1941
2084
  } else {
@@ -1957,19 +2100,32 @@ function runStream$1({ session, sm, prompt, images, sessionId, created, reqStart
1957
2100
  err
1958
2101
  }, "chat error");
1959
2102
  if (isModelProviderError(err)) {
2103
+ const billingBlocked = parseBillingBlockedProviderSignal(err instanceof Error ? err.message : String(err));
2104
+ if (billingBlocked) {
2105
+ emitBillingBlocked({
2106
+ writer,
2107
+ sessionId,
2108
+ created,
2109
+ billingBlocked
2110
+ });
2111
+ writer.write("data: [DONE]\n\n");
2112
+ return;
2113
+ }
1960
2114
  const providerError = toModelProviderError(err);
1961
2115
  log.warn({
1962
2116
  event: "model_provider_error",
1963
2117
  chatcmpl_id: sessionId,
1964
2118
  code: providerError.code,
1965
2119
  upstream_status: providerError.upstreamStatus,
1966
- provider: providerError.provider
2120
+ provider: providerError.provider,
2121
+ retry_attempts: autoRetry.attempts()
1967
2122
  }, "forwarding model-provider error to client");
1968
2123
  emitModelProviderError({
1969
2124
  writer,
1970
2125
  sessionId,
1971
2126
  created,
1972
- providerError
2127
+ providerError,
2128
+ retryAttempts: autoRetry.attempts()
1973
2129
  });
1974
2130
  } else sendChunk({ content: `\n[error: ${err?.message ?? err}]` }, "stop");
1975
2131
  writer.write("data: [DONE]\n\n");
@@ -2010,7 +2166,7 @@ function emitSessionMessagesTrailer({ writer, sm, baselineMessageCount, sessionI
2010
2166
  * cleanly closes the stream for any OpenAI-shaped reader that ignores the
2011
2167
  * extension field.
2012
2168
  */
2013
- function emitModelProviderError({ writer, sessionId, created, providerError }) {
2169
+ function emitModelProviderError({ writer, sessionId, created, providerError, retryAttempts }) {
2014
2170
  const chunk = {
2015
2171
  id: sessionId,
2016
2172
  object: "chat.completion.chunk",
@@ -2025,7 +2181,25 @@ function emitModelProviderError({ writer, sessionId, created, providerError }) {
2025
2181
  message: providerError.message,
2026
2182
  provider: providerError.provider,
2027
2183
  type: providerError.type,
2028
- upstream_status: providerError.upstreamStatus
2184
+ upstream_status: providerError.upstreamStatus,
2185
+ retry_attempts: retryAttempts
2186
+ }
2187
+ };
2188
+ writer.write(`data: ${JSON.stringify(chunk)}\n\n`);
2189
+ }
2190
+ function emitBillingBlocked({ writer, sessionId, created, billingBlocked }) {
2191
+ const chunk = {
2192
+ id: sessionId,
2193
+ object: "chat.completion.chunk",
2194
+ created,
2195
+ choices: [{
2196
+ index: 0,
2197
+ delta: {},
2198
+ finish_reason: "stop"
2199
+ }],
2200
+ x_billing_blocked: {
2201
+ block_reason: billingBlocked.blockReason,
2202
+ message: billingBlocked.message
2029
2203
  }
2030
2204
  };
2031
2205
  writer.write(`data: ${JSON.stringify(chunk)}\n\n`);
@@ -2388,6 +2562,7 @@ function runStream({ session, prompt, images, responseId, sessionId, modelName,
2388
2562
  const tcByContentIdx = /* @__PURE__ */ new Map();
2389
2563
  let nextOutputIndex = 0;
2390
2564
  let capturedModelError = null;
2565
+ const autoRetry = createAutoRetryObserver(log);
2391
2566
  const send = (event) => {
2392
2567
  writer.write(`data: ${JSON.stringify(event)}\n\n`);
2393
2568
  };
@@ -2396,7 +2571,8 @@ function runStream({ session, prompt, images, responseId, sessionId, modelName,
2396
2571
  event: "model_provider_error",
2397
2572
  code: providerError.code,
2398
2573
  upstream_status: providerError.upstreamStatus,
2399
- provider: providerError.provider
2574
+ provider: providerError.provider,
2575
+ retry_attempts: autoRetry.attempts()
2400
2576
  }, "forwarding model-provider error to client");
2401
2577
  send({
2402
2578
  type: "response.failed",
@@ -2410,7 +2586,8 @@ function runStream({ session, prompt, images, responseId, sessionId, modelName,
2410
2586
  x_model_provider_error: {
2411
2587
  provider: providerError.provider,
2412
2588
  type: providerError.type,
2413
- upstream_status: providerError.upstreamStatus
2589
+ upstream_status: providerError.upstreamStatus,
2590
+ retry_attempts: autoRetry.attempts()
2414
2591
  }
2415
2592
  }
2416
2593
  }
@@ -2446,6 +2623,7 @@ function runStream({ session, prompt, images, responseId, sessionId, modelName,
2446
2623
  };
2447
2624
  session.subscribe((event) => {
2448
2625
  const ev = event;
2626
+ autoRetry.observe(ev);
2449
2627
  const endedMessage = ev.message ?? (Array.isArray(ev.messages) ? ev.messages[ev.messages.length - 1] : null);
2450
2628
  if (endedMessage?.stopReason === "error" && typeof endedMessage.errorMessage === "string" && endedMessage.errorMessage.length > 0) capturedModelError = endedMessage.errorMessage;
2451
2629
  if (ev.type !== "message_update") return;
@@ -2851,4 +3029,4 @@ function chainMiddleware(middlewares) {
2851
3029
  };
2852
3030
  }
2853
3031
  //#endregion
2854
- export { DEFAULT_MODEL, DEFAULT_PROVIDER, DEFAULT_THINKING_LEVEL, KNOWN_PI_PROVIDERS, PI_AGENT_DIR, VALID_THINKING_LEVELS, buildAgentCard, buildModelFromSpec, chainMiddleware, composeHandlers, createAgentExecutor, createMapSessionRegistry, createPrewarm, createProtocolHandlers, createProtocols, deriveTraceContext, getCurrentTraceparent, logger, modelSpecSchema, mountAt, newTraceContext, parseModelSpec, parseTraceId, requestHeaders, requestLogger, requestUrl, resolveRequestModel, runInTraceContext, setCurrentTraceparent, webHandlerToMiddleware, withSpecApiKey };
3032
+ export { BILLING_BLOCK_REASONS, DEFAULT_MODEL, DEFAULT_PROVIDER, DEFAULT_THINKING_LEVEL, KNOWN_PI_PROVIDERS, PI_AGENT_DIR, VALID_THINKING_LEVELS, buildAgentCard, buildModelFromSpec, chainMiddleware, composeHandlers, createAgentExecutor, createMapSessionRegistry, createPrewarm, createProtocolHandlers, createProtocols, deriveTraceContext, getCurrentTraceparent, logger, modelSpecSchema, mountAt, newTraceContext, parseModelSpec, parseTraceId, requestHeaders, requestLogger, requestUrl, resolveRequestModel, runInTraceContext, setCurrentTraceparent, webHandlerToMiddleware, withSpecApiKey };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skydiveai/pi-server",
3
- "version": "0.1.0-beta.165",
3
+ "version": "0.1.0-beta.1738",
4
4
  "homepage": "https://skydive.com",
5
5
  "license": "MIT",
6
6
  "author": "Create, Inc.",
@@ -16,21 +16,20 @@
16
16
  }
17
17
  },
18
18
  "publishConfig": {
19
- "access": "public",
20
19
  "exports": {
21
20
  ".": {
22
21
  "types": "./dist/index.d.mts",
23
22
  "default": "./dist/index.mjs"
24
23
  }
25
24
  },
25
+ "access": "public",
26
26
  "registry": "https://registry.npmjs.org"
27
27
  },
28
28
  "scripts": {
29
29
  "build": "tsdown",
30
30
  "typecheck": "tsgo --noEmit",
31
31
  "test:unit": "vitest run --passWithNoTests",
32
- "test:ci": "vitest run --coverage --coverage.reporter=lcovonly --reporter=default --reporter=github-actions --minWorkers=1 --maxWorkers=2 --passWithNoTests",
33
- "publish:system-artifacts": "doppler run --preserve-env -- node ../../scripts/anyone/publish-system-artifact.mjs"
32
+ "test:ci": "vitest run --coverage --coverage.reporter=lcovonly --reporter=default --reporter=github-actions --minWorkers=1 --maxWorkers=2 --passWithNoTests"
34
33
  },
35
34
  "dependencies": {
36
35
  "@a2a-js/sdk": "^0.3.13",