@code-yeongyu/senpi-ai 2026.10.11 → 2026.10.12

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.
@@ -17,7 +17,13 @@ export function xaiProvider() {
17
17
  load: loadXaiOAuth,
18
18
  }),
19
19
  },
20
- models: Object.values(XAI_MODELS),
20
+ // xAI's Responses endpoint executes web_search in the same request.
21
+ // https://docs.x.ai/developers/tools/web-search
22
+ // Tool shape only: enable with supportsWebSearchPreview after verifying the route.
23
+ models: Object.values(XAI_MODELS).map((model) => ({
24
+ ...model,
25
+ compat: { ...model.compat, webSearchToolType: "web_search" },
26
+ })),
21
27
  api: openAIResponsesApi(),
22
28
  });
23
29
  }
package/dist/types.d.ts CHANGED
@@ -19,6 +19,13 @@ import type { AssistantMessageEventStream } from "./utils/event-stream.ts";
19
19
  export type { Model } from "./model.ts";
20
20
  export type { SessionAffinityFormat } from "./openai-responses-compat.ts";
21
21
  export type OpenAIResponsesCompat = BaseOpenAIResponsesCompat & {
22
+ /**
23
+ * Exact native search type for a compatible Responses endpoint.
24
+ * OpenAI supports both names; xAI documents only web_search.
25
+ * https://developers.openai.com/api/docs/guides/tools-web-search
26
+ * https://docs.x.ai/developers/tools/web-search
27
+ */
28
+ webSearchToolType?: "web_search" | "web_search_preview";
22
29
  /** Whether the model supports message-anchored `additional_tools` input items. Default: false. */
23
30
  supportsAdditionalTools?: boolean;
24
31
  /** Whether the exact model accepts developer or system messages after the conversation has started. When false, later system messages are folded into the leading system message. Default: false; the generated model catalog enables it for verified models. */
@@ -524,6 +531,11 @@ export interface AssistantMessage {
524
531
  stopDetails?: AssistantStopDetails;
525
532
  deferred?: DeferredHandle;
526
533
  errorMessage?: string;
534
+ /** Redaction-safe cause retained when a session projects a provider limit as user-facing advice. */
535
+ errorCause?: {
536
+ type: "usage_limit";
537
+ scope: "account" | "model";
538
+ };
527
539
  /** Structured provider failure family, minted only by a provider adapter from structured error metadata. */
528
540
  providerDiagnostic?: ProviderDiagnostic;
529
541
  /** Explicit owner for an abort initiated by the provider retry watchdog. */
@@ -786,6 +798,16 @@ export type AssistantMessageEvent = {
786
798
  * Use this to override URL-based auto-detection for custom providers.
787
799
  */
788
800
  export interface OpenAICompletionsCompat {
801
+ /**
802
+ * In-turn web search support on this exact endpoint. OpenRouter and Moonshot
803
+ * have documented native defaults; Z.AI PAYG chat requires explicit opt-in
804
+ * because its coding-plan endpoint documents remote MCP search instead.
805
+ * https://openrouter.ai/docs/guides/features/server-tools/web-search
806
+ * https://platform.kimi.ai/docs/guide/use-web-search
807
+ * https://docs.z.ai/guides/tools/web-search
808
+ * https://docs.z.ai/devpack/mcp/search-mcp-server
809
+ */
810
+ supportsWebSearch?: boolean;
789
811
  /** Whether the provider supports the `store` field. Default: auto-detected from URL. */
790
812
  supportsStore?: boolean;
791
813
  /** Whether the provider supports the `developer` role (vs `system`). Default: auto-detected from URL. */
@@ -24,7 +24,8 @@ export type PromptCacheLifetime = {
24
24
  };
25
25
  export declare function isAnthropicApiBaseUrl(baseUrl: string): boolean;
26
26
  export declare function getAnthropicCompat(model: Model<"anthropic-messages">): Required<Omit<AnthropicMessagesCompat, "forceAdaptiveThinking" | "supportsMidConvoEffort" | "sessionAffinityFormat">> & Pick<AnthropicMessagesCompat, "sessionAffinityFormat">;
27
- export type ResolvedOpenAICompletionsCompat = Omit<Required<OpenAICompletionsCompat>, "vllmPriority" | "cacheControlFormat" | "toolCallFormat" | "deferredToolsMode" | "toolSchemaFlavor" | "supportsPromptCacheKey" | "chatTemplateArgs" | "supportsThinkingTokenBudget" | "thinkingTokenBudgetField" | "veniceParameters" | "supportsForcedToolChoice"> & {
27
+ export type ResolvedOpenAICompletionsCompat = Omit<Required<OpenAICompletionsCompat>, "vllmPriority" | "cacheControlFormat" | "toolCallFormat" | "deferredToolsMode" | "toolSchemaFlavor" | "supportsPromptCacheKey" | "chatTemplateArgs" | "supportsThinkingTokenBudget" | "thinkingTokenBudgetField" | "veniceParameters" | "supportsForcedToolChoice" | "supportsWebSearch"> & {
28
+ supportsWebSearch?: OpenAICompletionsCompat["supportsWebSearch"];
28
29
  /** Declared forced tool_choice support; absent means supported. */
29
30
  supportsForcedToolChoice?: OpenAICompletionsCompat["supportsForcedToolChoice"];
30
31
  cacheControlFormat?: OpenAICompletionsCompat["cacheControlFormat"];
@@ -188,6 +188,7 @@ export function getOpenAICompletionsCompat(model) {
188
188
  if (!model.compat)
189
189
  return detected;
190
190
  return {
191
+ supportsWebSearch: model.compat.supportsWebSearch,
191
192
  supportsStore: model.compat.supportsStore ?? detected.supportsStore,
192
193
  supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
193
194
  supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
@@ -15,7 +15,9 @@ export declare function stripTurnRetrySuppressionPrefix(message: string): string
15
15
  * interruptions; returns undefined for failures that have no wording here so
16
16
  * the caller can fall back to the (marker-stripped) raw text.
17
17
  */
18
- export declare function describeProviderFailureForUser(errorMessage: string | undefined, options?: ProviderStallDescriptionOptions): string | undefined;
18
+ export declare function describeProviderFailureForUser(errorMessage: string | undefined, options?: ProviderStallDescriptionOptions & {
19
+ usageLimit?: "account" | "model";
20
+ }): string | undefined;
19
21
  /**
20
22
  * The turn-ending message for a provider module that can no longer be imported because the
21
23
  * installed package was replaced under the running process (#2358), or undefined for any other
@@ -44,6 +44,14 @@ export function describeProviderFailureForUser(errorMessage, options = {}) {
44
44
  const message = stripTurnRetrySuppressionPrefix(errorMessage).trim();
45
45
  if (!message)
46
46
  return undefined;
47
+ if (options.usageLimit === "account") {
48
+ const provider = options.model?.split("/")[0];
49
+ const reset = /\bresets?\s+([^"}\n]+)/i
50
+ .exec(message)?.[1]
51
+ ?.trim()
52
+ .replace(/[.;]+$/, "");
53
+ return `The ${provider ? `${provider} ` : ""}account usage limit has been reached${reset ? ` (resets ${reset})` : ""}. Switch to another provider with /model, or configure another provider in retry.fallbackChains.`;
54
+ }
47
55
  const stall = describeProviderStallForUser(message, options);
48
56
  if (stall !== undefined)
49
57
  return stall;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-ai",
3
- "version": "2026.10.11",
3
+ "version": "2026.10.12",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -80,7 +80,7 @@
80
80
  "check:model-data": "tsx scripts/check-model-data.ts",
81
81
  "build": "tsgo -p tsconfig.build.json && shx chmod +x dist/cli.js && shx rm -rf dist/providers/data && shx cp -r src/providers/data dist/providers/data",
82
82
  "build:offline": "npm run check:model-data && tsc -p tsconfig.build.json && shx chmod +x dist/cli.js && shx rm -rf dist/providers/data && shx cp -r src/providers/data dist/providers/data",
83
- "test": "vitest --run",
83
+ "test": "node ../../scripts/run-tests.mjs vitest --run",
84
84
  "prepublishOnly": "shx rm -rf dist && tsx scripts/generate-models.ts && tsc -p tsconfig.build.json && shx chmod +x dist/cli.js",
85
85
  "dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
86
86
  "dev:tsc": "tsc -p tsconfig.build.json --watch --preserveWatchOutput"
@@ -88,7 +88,7 @@
88
88
  "dependencies": {
89
89
  "@anthropic-ai/sdk": "0.127.0",
90
90
  "@aws-sdk/client-bedrock-runtime": "3.1136.0",
91
- "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.10.11",
91
+ "@earendil-works/pi-telemetry": "npm:@code-yeongyu/senpi-telemetry@2026.10.12",
92
92
  "@google/genai": "2.23.0",
93
93
  "@smithy/node-http-handler": "4.12.1",
94
94
  "http-proxy-agent": "9.1.0",