@jaypie/llm 1.3.0 → 1.3.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.
Files changed (86) hide show
  1. package/README.md +9 -0
  2. package/dist/cjs/constants.d.ts +82 -30
  3. package/dist/cjs/index.cjs +3081 -578
  4. package/dist/cjs/index.cjs.map +1 -1
  5. package/dist/cjs/index.d.ts +5 -1
  6. package/dist/cjs/observability/llmobs.d.ts +72 -0
  7. package/dist/cjs/operate/OperateLoop.d.ts +7 -0
  8. package/dist/cjs/operate/StreamLoop.d.ts +3 -0
  9. package/dist/cjs/operate/adapters/AnthropicAdapter.d.ts +36 -5
  10. package/dist/cjs/operate/adapters/BedrockAdapter.d.ts +78 -0
  11. package/dist/cjs/operate/adapters/{GeminiAdapter.d.ts → GoogleAdapter.d.ts} +19 -9
  12. package/dist/cjs/operate/adapters/OpenAiAdapter.d.ts +13 -3
  13. package/dist/cjs/operate/adapters/OpenRouterAdapter.d.ts +55 -8
  14. package/dist/cjs/operate/adapters/ProviderAdapter.interface.d.ts +5 -3
  15. package/dist/cjs/operate/adapters/XaiAdapter.d.ts +14 -0
  16. package/dist/cjs/operate/adapters/index.d.ts +3 -1
  17. package/dist/cjs/operate/index.d.ts +1 -1
  18. package/dist/cjs/operate/retry/RetryExecutor.d.ts +6 -3
  19. package/dist/cjs/operate/retry/createStaleRejectionGuard.d.ts +19 -0
  20. package/dist/cjs/operate/retry/index.d.ts +1 -0
  21. package/dist/cjs/operate/retry/isTransientNetworkError.d.ts +18 -0
  22. package/dist/cjs/operate/types.d.ts +2 -0
  23. package/dist/cjs/providers/anthropic/utils.d.ts +1 -1
  24. package/dist/cjs/providers/bedrock/BedrockProvider.class.d.ts +21 -0
  25. package/dist/cjs/providers/bedrock/index.d.ts +1 -0
  26. package/dist/cjs/providers/bedrock/utils.d.ts +6 -0
  27. package/dist/cjs/providers/{gemini/GeminiProvider.class.d.ts → google/GoogleProvider.class.d.ts} +1 -1
  28. package/dist/cjs/providers/google/index.d.ts +3 -0
  29. package/dist/{esm/providers/gemini → cjs/providers/google}/types.d.ts +1 -0
  30. package/dist/cjs/providers/{gemini → google}/utils.d.ts +1 -1
  31. package/dist/cjs/providers/openai/utils.d.ts +1 -1
  32. package/dist/cjs/providers/openrouter/utils.d.ts +1 -1
  33. package/dist/{esm/providers/gemini/GeminiProvider.class.d.ts → cjs/providers/xai/XaiProvider.class.d.ts} +1 -1
  34. package/dist/cjs/providers/xai/index.d.ts +1 -0
  35. package/dist/cjs/providers/xai/utils.d.ts +5 -0
  36. package/dist/cjs/types/LlmProvider.interface.d.ts +1 -1
  37. package/dist/cjs/types/LlmStreamChunk.interface.d.ts +2 -0
  38. package/dist/cjs/util/fillFormatArrays.d.ts +17 -0
  39. package/dist/cjs/util/index.d.ts +2 -0
  40. package/dist/cjs/util/jsonSchemaToOpenApi3.d.ts +10 -0
  41. package/dist/cjs/util/logger.d.ts +1 -2
  42. package/dist/cjs/util/maxTurnsFromOptions.d.ts +1 -1
  43. package/dist/esm/constants.d.ts +82 -30
  44. package/dist/esm/index.d.ts +5 -1
  45. package/dist/esm/index.js +3077 -578
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/observability/llmobs.d.ts +72 -0
  48. package/dist/esm/operate/OperateLoop.d.ts +7 -0
  49. package/dist/esm/operate/StreamLoop.d.ts +3 -0
  50. package/dist/esm/operate/adapters/AnthropicAdapter.d.ts +36 -5
  51. package/dist/esm/operate/adapters/BedrockAdapter.d.ts +78 -0
  52. package/dist/esm/operate/adapters/{GeminiAdapter.d.ts → GoogleAdapter.d.ts} +19 -9
  53. package/dist/esm/operate/adapters/OpenAiAdapter.d.ts +13 -3
  54. package/dist/esm/operate/adapters/OpenRouterAdapter.d.ts +55 -8
  55. package/dist/esm/operate/adapters/ProviderAdapter.interface.d.ts +5 -3
  56. package/dist/esm/operate/adapters/XaiAdapter.d.ts +14 -0
  57. package/dist/esm/operate/adapters/index.d.ts +3 -1
  58. package/dist/esm/operate/index.d.ts +1 -1
  59. package/dist/esm/operate/retry/RetryExecutor.d.ts +6 -3
  60. package/dist/esm/operate/retry/createStaleRejectionGuard.d.ts +19 -0
  61. package/dist/esm/operate/retry/index.d.ts +1 -0
  62. package/dist/esm/operate/retry/isTransientNetworkError.d.ts +18 -0
  63. package/dist/esm/operate/types.d.ts +2 -0
  64. package/dist/esm/providers/anthropic/utils.d.ts +1 -1
  65. package/dist/esm/providers/bedrock/BedrockProvider.class.d.ts +21 -0
  66. package/dist/esm/providers/bedrock/index.d.ts +1 -0
  67. package/dist/esm/providers/bedrock/utils.d.ts +6 -0
  68. package/dist/esm/providers/google/GoogleProvider.class.d.ts +21 -0
  69. package/dist/esm/providers/google/index.d.ts +3 -0
  70. package/dist/{cjs/providers/gemini → esm/providers/google}/types.d.ts +1 -0
  71. package/dist/esm/providers/{gemini → google}/utils.d.ts +1 -1
  72. package/dist/esm/providers/openai/utils.d.ts +1 -1
  73. package/dist/esm/providers/openrouter/utils.d.ts +1 -1
  74. package/dist/esm/providers/xai/XaiProvider.class.d.ts +21 -0
  75. package/dist/esm/providers/xai/index.d.ts +1 -0
  76. package/dist/esm/providers/xai/utils.d.ts +5 -0
  77. package/dist/esm/types/LlmProvider.interface.d.ts +1 -1
  78. package/dist/esm/types/LlmStreamChunk.interface.d.ts +2 -0
  79. package/dist/esm/util/fillFormatArrays.d.ts +17 -0
  80. package/dist/esm/util/index.d.ts +2 -0
  81. package/dist/esm/util/jsonSchemaToOpenApi3.d.ts +10 -0
  82. package/dist/esm/util/logger.d.ts +1 -2
  83. package/dist/esm/util/maxTurnsFromOptions.d.ts +1 -1
  84. package/package.json +8 -1
  85. package/dist/cjs/providers/gemini/index.d.ts +0 -3
  86. package/dist/esm/providers/gemini/index.d.ts +0 -3
@@ -8,5 +8,9 @@ export type { LlmStreamChunk, LlmStreamChunkDone, LlmStreamChunkError, LlmStream
8
8
  export { LlmStreamChunkType } from "./types/LlmStreamChunk.interface.js";
9
9
  export { JaypieToolkit, toolkit, Toolkit, tools } from "./tools/index.js";
10
10
  export { extractReasoning } from "./util/extractReasoning.js";
11
- export { GeminiProvider } from "./providers/gemini/index.js";
11
+ export { BedrockProvider } from "./providers/bedrock/index.js";
12
+ /** @deprecated Use GoogleProvider — "Google" is the provider; Gemini is the model family */
13
+ export { GoogleProvider as GeminiProvider } from "./providers/google/index.js";
14
+ export { GoogleProvider } from "./providers/google/index.js";
12
15
  export { OpenRouterProvider } from "./providers/openrouter/index.js";
16
+ export { XaiProvider } from "./providers/xai/index.js";
@@ -0,0 +1,72 @@
1
+ /**
2
+ * LLM Observability span kinds supported by Datadog's `llmobs` SDK.
3
+ * @see https://docs.datadoghq.com/llm_observability/setup/sdk/nodejs/
4
+ */
5
+ export type LlmObsSpanKind = "agent" | "embedding" | "llm" | "retrieval" | "task" | "tool" | "workflow";
6
+ export interface LlmObsSpanOptions {
7
+ kind: LlmObsSpanKind;
8
+ modelName?: string;
9
+ modelProvider?: string;
10
+ name: string;
11
+ }
12
+ export interface LlmObsAnnotation {
13
+ inputData?: unknown;
14
+ metadata?: Record<string, unknown>;
15
+ metrics?: Record<string, number>;
16
+ outputData?: unknown;
17
+ tags?: Record<string, unknown>;
18
+ }
19
+ /** Manual span handle for streaming, where a callback cannot enclose the work. */
20
+ export interface LlmObsSpanHandle {
21
+ annotate: (annotation: LlmObsAnnotation) => void;
22
+ finish: () => void;
23
+ }
24
+ /** Minimal shape of the dd-trace `llmobs` SDK surface this module uses. */
25
+ interface LlmObsSdk {
26
+ annotate: (span: unknown, annotation: LlmObsAnnotation) => void;
27
+ trace: (options: LlmObsSpanOptions, fn: (span: unknown) => unknown) => unknown;
28
+ }
29
+ /** Reset the cached SDK resolution. Exposed for tests. */
30
+ export declare function _resetLlmObs(): void;
31
+ /**
32
+ * Inject an SDK to bypass dd-trace resolution. Test-only: dd-trace is not a
33
+ * dependency, so the enabled path cannot otherwise be exercised in unit tests.
34
+ */
35
+ export declare function _setLlmObs(sdk: LlmObsSdk | null): void;
36
+ /**
37
+ * True when LLM Observability emission is opted in via `DD_LLMOBS_ENABLED`.
38
+ * Accepts any truthy value except "false"/"0".
39
+ */
40
+ export declare function isLlmObsEnabled(): boolean;
41
+ /**
42
+ * Run `fn` inside an LLM Observability span. When emission is disabled or
43
+ * dd-trace is absent, `fn` is invoked directly with no overhead. The active
44
+ * span is established for the duration of `fn`, so nested `withLlmObsSpan`
45
+ * calls (and `annotateLlmObs`) attach as children/annotations automatically.
46
+ */
47
+ export declare function withLlmObsSpan<T>(options: LlmObsSpanOptions, fn: () => Promise<T>): Promise<T>;
48
+ /**
49
+ * Annotate the currently active LLM Observability span. No-op when disabled.
50
+ */
51
+ export declare function annotateLlmObs(annotation: LlmObsAnnotation): void;
52
+ /**
53
+ * Open a manual span that is finished later. Used by streaming, where work is
54
+ * yielded incrementally and cannot be enclosed in a single callback. The span
55
+ * is kept open via a deferred promise resolved by `finish()`. Returns null when
56
+ * emission is disabled or dd-trace is absent.
57
+ *
58
+ * Note: because the span is held open across `yield` boundaries (outside the
59
+ * SDK's AsyncLocalStorage scope), manual spans are emitted flat rather than
60
+ * nested. Annotations are applied to the explicit span reference.
61
+ */
62
+ export declare function openLlmObsSpan(options: LlmObsSpanOptions): LlmObsSpanHandle | null;
63
+ /**
64
+ * Sum an `LlmUsage` array into LLM Observability metric keys. Returns undefined
65
+ * when there is no usage data so callers can omit the `metrics` field.
66
+ */
67
+ export declare function usageToLlmObsMetrics(usage?: Array<{
68
+ input?: number;
69
+ output?: number;
70
+ total?: number;
71
+ }>): Record<string, number> | undefined;
72
+ export {};
@@ -10,6 +10,7 @@ export interface OperateLoopConfig {
10
10
  inputProcessor?: InputProcessor;
11
11
  retryPolicy?: RetryPolicy;
12
12
  }
13
+ export declare const MAX_CONSECUTIVE_TOOL_ERRORS = 6;
13
14
  /**
14
15
  * OperateLoop implements the core multi-turn conversation loop.
15
16
  * It orchestrates provider adapters, retry logic, hook execution, and tool calling.
@@ -33,6 +34,12 @@ export declare class OperateLoop {
33
34
  private createContext;
34
35
  private buildInitialRequest;
35
36
  private executeOneTurn;
37
+ /**
38
+ * Backfill declared array fields when a `format` is supplied. A declared
39
+ * `format` is a schema contract: an empty array field should surface as `[]`
40
+ * rather than be dropped by a provider/model that omits empty lists.
41
+ */
42
+ private applyFormatArrayDefaults;
36
43
  /**
37
44
  * Sync the current input state from the updated provider request.
38
45
  * This is necessary because appendToolResult modifies the provider-specific request,
@@ -3,11 +3,13 @@ import { LlmStreamChunk } from "../types/LlmStreamChunk.interface.js";
3
3
  import { ProviderAdapter } from "./adapters/ProviderAdapter.interface.js";
4
4
  import { HookRunner } from "./hooks/index.js";
5
5
  import { InputProcessor } from "./input/index.js";
6
+ import { RetryPolicy } from "./retry/index.js";
6
7
  export interface StreamLoopConfig {
7
8
  adapter: ProviderAdapter;
8
9
  client: unknown;
9
10
  hookRunner?: HookRunner;
10
11
  inputProcessor?: InputProcessor;
12
+ retryPolicy?: RetryPolicy;
11
13
  }
12
14
  /**
13
15
  * StreamLoop implements streaming multi-turn conversation loop.
@@ -19,6 +21,7 @@ export declare class StreamLoop {
19
21
  private readonly client;
20
22
  private readonly hookRunnerInstance;
21
23
  private readonly inputProcessorInstance;
24
+ private readonly retryPolicy;
22
25
  constructor(config: StreamLoopConfig);
23
26
  /**
24
27
  * Execute the streaming loop for multi-turn conversations with tool calling.
@@ -6,6 +6,22 @@ import { LlmHistory, LlmOperateOptions, LlmUsageItem } from "../../types/LlmProv
6
6
  import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
7
7
  import { ClassifiedError, OperateRequest, ParsedResponse, ProviderToolDefinition, StandardToolCall, StandardToolResult } from "../types.js";
8
8
  import { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
9
+ /**
10
+ * Local extension of the SDK's `MessageCreateParams` to carry
11
+ * `output_config.format` (Anthropic native structured outputs). The SDK 0.71
12
+ * shipped with the older `output_format` field which the API has since
13
+ * deprecated in favor of `output_config.format`. We send the new shape via
14
+ * an untyped passthrough so callers don't need a newer SDK; remove this
15
+ * extension once the SDK types `output_config` directly.
16
+ */
17
+ type AnthropicRequestParams = Anthropic.MessageCreateParams & {
18
+ output_config?: {
19
+ format: {
20
+ type: "json_schema";
21
+ schema: JsonObject;
22
+ };
23
+ };
24
+ };
9
25
  /**
10
26
  * AnthropicAdapter implements the ProviderAdapter interface for Anthropic's API.
11
27
  * It handles request building, response parsing, and error classification
@@ -13,12 +29,26 @@ import { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
13
29
  */
14
30
  export declare class AnthropicAdapter extends BaseProviderAdapter {
15
31
  readonly name: "anthropic";
16
- readonly defaultModel: "claude-sonnet-4-5";
17
- buildRequest(request: OperateRequest): Anthropic.MessageCreateParams;
18
- formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
32
+ readonly defaultModel: "claude-sonnet-4-6";
33
+ private runtimeNoTemperatureModels;
34
+ private runtimeNoStructuredOutputModels;
35
+ rememberModelRejectsTemperature(model: string): void;
36
+ clearRuntimeNoTemperatureModels(): void;
37
+ rememberModelRejectsStructuredOutput(model: string): void;
38
+ clearRuntimeNoStructuredOutputModels(): void;
39
+ private supportsTemperature;
40
+ private supportsStructuredOutput;
41
+ buildRequest(request: OperateRequest): AnthropicRequestParams;
42
+ formatTools(toolkit: Toolkit, _outputSchema?: JsonObject): ProviderToolDefinition[];
19
43
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
20
- executeRequest(client: unknown, request: unknown): Promise<Anthropic.Message>;
21
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
44
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<Anthropic.Message>;
45
+ /**
46
+ * Rebuild a structured-output request without `output_format`, swapping in
47
+ * the legacy fake-tool emulation. Used as a runtime fallback when a model
48
+ * rejects native `output_config.format`.
49
+ */
50
+ private toFallbackStructuredOutputRequest;
51
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
22
52
  parseResponse(response: unknown, _options?: LlmOperateOptions): ParsedResponse;
23
53
  extractToolCalls(response: unknown): StandardToolCall[];
24
54
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -32,3 +62,4 @@ export declare class AnthropicAdapter extends BaseProviderAdapter {
32
62
  private extractContent;
33
63
  }
34
64
  export declare const anthropicAdapter: AnthropicAdapter;
65
+ export {};
@@ -0,0 +1,78 @@
1
+ import type { ConverseCommandInput, ConverseCommandOutput, DocumentFormat } from "@aws-sdk/client-bedrock-runtime";
2
+ import { JsonObject, NaturalSchema } from "@jaypie/types";
3
+ import { z } from "zod/v4";
4
+ import { Toolkit } from "../../tools/Toolkit.class.js";
5
+ import { LlmHistory, LlmOperateOptions, LlmUsageItem } from "../../types/LlmProvider.interface.js";
6
+ import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
7
+ import { ClassifiedError, OperateRequest, ParsedResponse, ProviderToolDefinition, StandardToolCall, StandardToolResult } from "../types.js";
8
+ import { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
9
+ type BedrockContentBlock = {
10
+ text: string;
11
+ } | {
12
+ toolUse: {
13
+ toolUseId: string;
14
+ name: string;
15
+ input: JsonObject;
16
+ };
17
+ } | {
18
+ toolResult: {
19
+ toolUseId: string;
20
+ content: Array<{
21
+ text: string;
22
+ }>;
23
+ };
24
+ } | {
25
+ image: {
26
+ format: string;
27
+ source: {
28
+ bytes: Uint8Array;
29
+ };
30
+ };
31
+ } | {
32
+ document: {
33
+ format: DocumentFormat;
34
+ name: string;
35
+ source: {
36
+ bytes: Uint8Array;
37
+ };
38
+ };
39
+ };
40
+ type BedrockMessage = {
41
+ role: "user" | "assistant";
42
+ content: BedrockContentBlock[];
43
+ };
44
+ type BedrockRequest = Omit<ConverseCommandInput, "messages"> & {
45
+ messages: BedrockMessage[];
46
+ };
47
+ type AnnotatedBedrockResponse = ConverseCommandOutput & {
48
+ __jaypieStructuredOutput?: boolean;
49
+ };
50
+ export declare class BedrockAdapter extends BaseProviderAdapter {
51
+ readonly name: "bedrock";
52
+ readonly defaultModel: "amazon.nova-lite-v1:0";
53
+ private _modelsFallbackToStructuredOutputTool;
54
+ private _modelsWithoutTemperature;
55
+ private rememberModelRejectsOutputConfig;
56
+ private useFakeToolForStructuredOutput;
57
+ private rememberModelRejectsTemperature;
58
+ private supportsTemperature;
59
+ buildRequest(request: OperateRequest): BedrockRequest;
60
+ formatTools(toolkit: Toolkit): ProviderToolDefinition[];
61
+ formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
62
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<AnnotatedBedrockResponse>;
63
+ private toFallbackStructuredOutputRequest;
64
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
65
+ parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
66
+ extractToolCalls(response: unknown): StandardToolCall[];
67
+ extractUsage(response: unknown, model: string): LlmUsageItem;
68
+ formatToolResult(toolCall: StandardToolCall, result: StandardToolResult): BedrockContentBlock;
69
+ appendToolResult(request: unknown, toolCall: StandardToolCall, result: StandardToolResult): BedrockRequest;
70
+ responseToHistoryItems(response: unknown): LlmHistory;
71
+ classifyError(error: unknown): ClassifiedError;
72
+ hasStructuredOutput(response: unknown): boolean;
73
+ extractStructuredOutput(response: unknown): JsonObject | undefined;
74
+ isComplete(response: unknown): boolean;
75
+ private extractContentFromMessage;
76
+ }
77
+ export declare const bedrockAdapter: BedrockAdapter;
78
+ export {};
@@ -5,20 +5,30 @@ import { LlmHistory, LlmOperateOptions, LlmUsageItem } from "../../types/LlmProv
5
5
  import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
6
6
  import { ClassifiedError, OperateRequest, ParsedResponse, ProviderToolDefinition, StandardToolCall, StandardToolResult } from "../types.js";
7
7
  import { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
8
- import { GeminiPart, GeminiRawResponse, GeminiRequest } from "../../providers/gemini/types.js";
8
+ import { GeminiPart, GeminiRawResponse, GeminiRequest } from "../../providers/google/types.js";
9
9
  /**
10
- * GeminiAdapter implements the ProviderAdapter interface for Google's Gemini API.
10
+ * GoogleAdapter implements the ProviderAdapter interface for Google's Gemini API.
11
11
  * It handles request building, response parsing, and error classification
12
12
  * specific to Gemini's generateContent API.
13
13
  */
14
- export declare class GeminiAdapter extends BaseProviderAdapter {
15
- readonly name: "gemini";
16
- readonly defaultModel: "gemini-3-pro-preview";
14
+ export declare class GoogleAdapter extends BaseProviderAdapter {
15
+ readonly name: "google";
16
+ readonly defaultModel: "gemini-3.1-pro-preview";
17
+ private runtimeNoStructuredOutputComboModels;
18
+ rememberModelRejectsStructuredOutputCombo(model: string): void;
19
+ clearRuntimeNoStructuredOutputComboModels(): void;
20
+ private supportsStructuredOutputCombo;
17
21
  buildRequest(request: OperateRequest): GeminiRequest;
18
- formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
22
+ formatTools(toolkit: Toolkit, _outputSchema?: JsonObject): ProviderToolDefinition[];
19
23
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
20
- executeRequest(client: unknown, request: unknown): Promise<GeminiRawResponse>;
21
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
24
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<GeminiRawResponse>;
25
+ /**
26
+ * Rebuild a Gemini 3 native-combo request without `responseJsonSchema`/
27
+ * `responseMimeType`, swapping in the legacy fake-tool emulation. Used as
28
+ * a runtime fallback when a Gemini 3 model rejects the combo.
29
+ */
30
+ private toFallbackStructuredOutputRequest;
31
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
22
32
  parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
23
33
  extractToolCalls(response: unknown): StandardToolCall[];
24
34
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -37,4 +47,4 @@ export declare class GeminiAdapter extends BaseProviderAdapter {
37
47
  private extractContent;
38
48
  private generateCallId;
39
49
  }
40
- export declare const geminiAdapter: GeminiAdapter;
50
+ export declare const googleAdapter: GoogleAdapter;
@@ -12,12 +12,16 @@ import { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
12
12
  */
13
13
  export declare class OpenAiAdapter extends BaseProviderAdapter {
14
14
  readonly name: "openai";
15
- readonly defaultModel: "gpt-5.2";
15
+ readonly defaultModel: "gpt-5.4";
16
+ private runtimeNoTemperatureModels;
17
+ rememberModelRejectsTemperature(model: string): void;
18
+ clearRuntimeNoTemperatureModels(): void;
19
+ private supportsTemperature;
16
20
  buildRequest(request: OperateRequest): unknown;
17
21
  formatTools(toolkit: Toolkit, _outputSchema?: JsonObject): ProviderToolDefinition[];
18
22
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
19
- executeRequest(client: unknown, request: unknown): Promise<unknown>;
20
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
23
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<unknown>;
24
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
21
25
  parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
22
26
  extractToolCalls(response: unknown): StandardToolCall[];
23
27
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -26,6 +30,12 @@ export declare class OpenAiAdapter extends BaseProviderAdapter {
26
30
  responseToHistoryItems(response: unknown): LlmHistory;
27
31
  classifyError(error: unknown): ClassifiedError;
28
32
  isComplete(response: unknown): boolean;
33
+ /**
34
+ * Sanitize history items for the OpenAI Responses API.
35
+ * Strips fields not accepted by specific item types (e.g., `name` on
36
+ * function_call_output items) to prevent 400 "Unknown parameter" errors.
37
+ */
38
+ private sanitizeInputItems;
29
39
  private hasToolCalls;
30
40
  private extractContent;
31
41
  }
@@ -59,22 +59,49 @@ interface OpenRouterTool {
59
59
  parameters: JsonObject;
60
60
  };
61
61
  }
62
+ interface OpenRouterJsonSchemaConfig {
63
+ name: string;
64
+ description?: string;
65
+ schema: JsonObject;
66
+ strict?: boolean;
67
+ }
68
+ type OpenRouterResponseFormat = {
69
+ type: "json_schema";
70
+ json_schema: OpenRouterJsonSchemaConfig;
71
+ } | {
72
+ type: "json_object";
73
+ } | {
74
+ type: "text";
75
+ };
62
76
  interface OpenRouterRequest {
63
77
  model: string;
64
78
  messages: OpenRouterMessage[];
65
79
  tools?: OpenRouterTool[];
66
80
  tool_choice?: "auto" | "none" | "required";
67
- response_format?: {
68
- type: "json_object" | "text";
69
- };
81
+ response_format?: OpenRouterResponseFormat;
70
82
  user?: string;
71
83
  }
72
84
  /**
73
- * OpenRouter content part types (text only - images/files not supported)
85
+ * OpenRouter content part types. OpenRouter follows the OpenAI Chat
86
+ * Completions multimodal schema and forwards `image_url` and `file` parts
87
+ * to vision/PDF-capable backends. The SDK accepts camelCase fields at the
88
+ * input boundary (`imageUrl`, `fileData`) and transforms to snake_case on
89
+ * the wire.
74
90
  */
75
91
  type OpenRouterContentPart = {
76
92
  type: "text";
77
93
  text: string;
94
+ } | {
95
+ type: "image_url";
96
+ imageUrl: {
97
+ url: string;
98
+ };
99
+ } | {
100
+ type: "file";
101
+ file: {
102
+ filename?: string;
103
+ fileData: string;
104
+ };
78
105
  };
79
106
  /**
80
107
  * OpenRouterAdapter implements the ProviderAdapter interface for OpenRouter's API.
@@ -84,12 +111,32 @@ type OpenRouterContentPart = {
84
111
  */
85
112
  export declare class OpenRouterAdapter extends BaseProviderAdapter {
86
113
  readonly name: "openrouter";
87
- readonly defaultModel: "z-ai/glm-4.7";
114
+ readonly defaultModel: "anthropic/claude-sonnet-4-6";
115
+ private runtimeNoStructuredOutputModels;
116
+ rememberModelRejectsStructuredOutput(model: string): void;
117
+ clearRuntimeNoStructuredOutputModels(): void;
118
+ private supportsStructuredOutput;
119
+ private runtimeNoTemperatureModels;
120
+ rememberModelRejectsTemperature(model: string): void;
121
+ clearRuntimeNoTemperatureModels(): void;
122
+ private supportsTemperature;
88
123
  buildRequest(request: OperateRequest): OpenRouterRequest;
89
- formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
124
+ formatTools(toolkit: Toolkit, _outputSchema?: JsonObject): ProviderToolDefinition[];
90
125
  formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
91
- executeRequest(client: unknown, request: unknown): Promise<OpenRouterResponse>;
92
- executeStreamRequest(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
126
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<OpenRouterResponse>;
127
+ /**
128
+ * Translate our internal snake_case `OpenRouterRequest` into the SDK's
129
+ * camelCase shape, forwarding only the fields we care about (the SDK
130
+ * silently strips unknown fields).
131
+ */
132
+ private toSdkChatParams;
133
+ /**
134
+ * Rebuild a structured-output request without `response_format`, swapping in
135
+ * the legacy fake-tool emulation. Used as a runtime fallback when a model
136
+ * rejects native json_schema.
137
+ */
138
+ private toFallbackStructuredOutputRequest;
139
+ executeStreamRequest(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
93
140
  parseResponse(response: unknown, _options?: LlmOperateOptions): ParsedResponse;
94
141
  extractToolCalls(response: unknown): StandardToolCall[];
95
142
  extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -47,17 +47,19 @@ export interface ProviderAdapter {
47
47
  *
48
48
  * @param client - The provider's SDK client instance
49
49
  * @param request - Provider-specific request object (from buildRequest)
50
+ * @param signal - Optional AbortSignal to cancel the request on retry
50
51
  * @returns Raw provider response
51
52
  */
52
- executeRequest(client: unknown, request: unknown): Promise<unknown>;
53
+ executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<unknown>;
53
54
  /**
54
55
  * Execute a streaming API request to the provider
55
56
  *
56
57
  * @param client - The provider's SDK client instance
57
58
  * @param request - Provider-specific request object (from buildRequest)
59
+ * @param signal - Optional AbortSignal to cancel the request on retry
58
60
  * @returns AsyncIterable of stream chunks
59
61
  */
60
- executeStreamRequest?(client: unknown, request: unknown): AsyncIterable<LlmStreamChunk>;
62
+ executeStreamRequest?(client: unknown, request: unknown, signal?: AbortSignal): AsyncIterable<LlmStreamChunk>;
61
63
  /**
62
64
  * Parse a provider response into standardized format
63
65
  *
@@ -158,7 +160,7 @@ export declare abstract class BaseProviderAdapter implements ProviderAdapter {
158
160
  abstract buildRequest(request: OperateRequest): unknown;
159
161
  abstract formatTools(toolkit: Toolkit, outputSchema?: JsonObject): ProviderToolDefinition[];
160
162
  abstract formatOutputSchema(schema: JsonObject | NaturalSchema | z.ZodType): JsonObject;
161
- abstract executeRequest(client: unknown, request: unknown): Promise<unknown>;
163
+ abstract executeRequest(client: unknown, request: unknown, signal?: AbortSignal): Promise<unknown>;
162
164
  abstract parseResponse(response: unknown, options?: LlmOperateOptions): ParsedResponse;
163
165
  abstract extractToolCalls(response: unknown): StandardToolCall[];
164
166
  abstract extractUsage(response: unknown, model: string): LlmUsageItem;
@@ -0,0 +1,14 @@
1
+ import { ClassifiedError } from "../types.js";
2
+ import { OpenAiAdapter } from "./OpenAiAdapter.js";
3
+ /**
4
+ * XaiAdapter extends OpenAiAdapter since xAI (Grok) uses an OpenAI-compatible API.
5
+ * Name, default model, and transient-ingest-error detection are overridden;
6
+ * all request building, response parsing, tool handling, and streaming are
7
+ * inherited.
8
+ */
9
+ export declare class XaiAdapter extends OpenAiAdapter {
10
+ readonly name: "xai";
11
+ readonly defaultModel: "grok-latest";
12
+ classifyError(error: unknown): ClassifiedError;
13
+ }
14
+ export declare const xaiAdapter: XaiAdapter;
@@ -1,6 +1,8 @@
1
1
  export { BaseProviderAdapter } from "./ProviderAdapter.interface.js";
2
2
  export type { ProviderAdapter } from "./ProviderAdapter.interface.js";
3
3
  export { AnthropicAdapter, anthropicAdapter } from "./AnthropicAdapter.js";
4
- export { GeminiAdapter, geminiAdapter } from "./GeminiAdapter.js";
4
+ export { BedrockAdapter, bedrockAdapter } from "./BedrockAdapter.js";
5
+ export { GoogleAdapter, googleAdapter } from "./GoogleAdapter.js";
5
6
  export { OpenAiAdapter, openAiAdapter } from "./OpenAiAdapter.js";
6
7
  export { OpenRouterAdapter, openRouterAdapter } from "./OpenRouterAdapter.js";
8
+ export { XaiAdapter, xaiAdapter } from "./XaiAdapter.js";
@@ -1,4 +1,4 @@
1
- export { AnthropicAdapter, anthropicAdapter, BaseProviderAdapter, GeminiAdapter, geminiAdapter, OpenAiAdapter, openAiAdapter, OpenRouterAdapter, openRouterAdapter, } from "./adapters/index.js";
1
+ export { AnthropicAdapter, anthropicAdapter, BaseProviderAdapter, BedrockAdapter, bedrockAdapter, GoogleAdapter, googleAdapter, OpenAiAdapter, openAiAdapter, OpenRouterAdapter, openRouterAdapter, XaiAdapter, xaiAdapter, } from "./adapters/index.js";
2
2
  export type { ProviderAdapter } from "./adapters/index.js";
3
3
  export { createOperateLoop, OperateLoop } from "./OperateLoop.js";
4
4
  export type { OperateLoopConfig } from "./OperateLoop.js";
@@ -28,12 +28,15 @@ export declare class RetryExecutor {
28
28
  private readonly errorClassifier;
29
29
  constructor(config: RetryExecutorConfig);
30
30
  /**
31
- * Execute an operation with retry logic
31
+ * Execute an operation with retry logic.
32
+ * Each attempt receives an AbortSignal. On failure, the signal is aborted
33
+ * before sleeping — this kills lingering socket callbacks from the previous
34
+ * request and prevents stale async errors from escaping the retry loop.
32
35
  *
33
- * @param operation - The async operation to execute
36
+ * @param operation - The async operation to execute (receives AbortSignal)
34
37
  * @param options - Execution options including context and hooks
35
38
  * @returns The result of the operation
36
39
  * @throws BadGatewayError if all retries are exhausted or error is not retryable
37
40
  */
38
- execute<T>(operation: () => Promise<T>, options: ExecuteOptions): Promise<T>;
41
+ execute<T>(operation: ((signal: AbortSignal) => Promise<T>) | (() => Promise<T>), options: ExecuteOptions): Promise<T>;
39
42
  }
@@ -0,0 +1,19 @@
1
+ export interface StaleRejectionGuard {
2
+ /** Install the unhandledRejection listener (idempotent) */
3
+ install(): void;
4
+ /** Remove the listener and forget recorded errors */
5
+ remove(): void;
6
+ /** Record an error the retry loop has caught and is handling */
7
+ recordCaught(error: unknown): void;
8
+ }
9
+ /**
10
+ * Create a guard that suppresses unhandled rejections firing as siblings of
11
+ * an error the retry loop has already caught. Provider SDKs occasionally
12
+ * surface a single upstream failure as twin rejections — the retry layer
13
+ * accepts responsibility for the first; this guard prevents the second from
14
+ * crashing the host while the retry is in flight.
15
+ *
16
+ * The guard also continues to suppress transient socket teardown errors
17
+ * (e.g. undici `TypeError: terminated`) emitted between attempts.
18
+ */
19
+ export declare function createStaleRejectionGuard(): StaleRejectionGuard;
@@ -1,4 +1,5 @@
1
1
  export { DEFAULT_BACKOFF_FACTOR, DEFAULT_INITIAL_DELAY_MS, DEFAULT_MAX_DELAY_MS, DEFAULT_MAX_RETRIES, defaultRetryPolicy, MAX_RETRIES_ABSOLUTE_LIMIT, RetryPolicy, } from "./RetryPolicy.js";
2
2
  export type { RetryPolicyConfig } from "./RetryPolicy.js";
3
+ export { isTransientNetworkError } from "./isTransientNetworkError.js";
3
4
  export { RetryExecutor } from "./RetryExecutor.js";
4
5
  export type { ErrorClassifier, ExecuteOptions, RetryContext, RetryExecutorConfig, } from "./RetryExecutor.js";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Transient network error detection utility.
3
+ *
4
+ * Detects low-level Node.js/undici network errors that indicate
5
+ * a temporary network issue (not a provider API error).
6
+ * These errors should always be retried.
7
+ */
8
+ /**
9
+ * Detect transient network errors by inspecting the error and its cause chain.
10
+ *
11
+ * Undici (Node.js fetch) wraps low-level errors like ECONNRESET inside
12
+ * `TypeError: terminated`. This function recursively walks `error.cause`
13
+ * to detect these wrapped errors.
14
+ *
15
+ * @param error - The error to inspect
16
+ * @returns true if the error (or any cause in its chain) is a transient network error
17
+ */
18
+ export declare function isTransientNetworkError(error: unknown): boolean;
@@ -117,6 +117,8 @@ import type { ResponseBuilder } from "./response/ResponseBuilder.js";
117
117
  * Internal state of the operate loop
118
118
  */
119
119
  export interface OperateLoopState {
120
+ /** Count of consecutive tool errors (resets on success) */
121
+ consecutiveToolErrors: number;
120
122
  /** Current conversation input/messages */
121
123
  currentInput: LlmHistory;
122
124
  /** Current turn number (0-indexed, incremented at start of each turn) */
@@ -3,7 +3,7 @@ import { LlmMessageOptions } from "../../types/LlmProvider.interface.js";
3
3
  import { z } from "zod/v4";
4
4
  import { JsonObject, NaturalSchema } from "@jaypie/types";
5
5
  export declare function loadSdk(): Promise<typeof import("@anthropic-ai/sdk")>;
6
- export declare const getLogger: () => any;
6
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger.js").default;
7
7
  export declare function initializeClient({ apiKey, }?: {
8
8
  apiKey?: string;
9
9
  }): Promise<Anthropic>;
@@ -0,0 +1,21 @@
1
+ import { JsonObject } from "@jaypie/types";
2
+ import { LlmHistory, LlmInputMessage, LlmMessageOptions, LlmOperateOptions, LlmOperateResponse, LlmProvider } from "../../types/LlmProvider.interface.js";
3
+ import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
4
+ export declare class BedrockProvider implements LlmProvider {
5
+ private model;
6
+ private region?;
7
+ private _client?;
8
+ private _operateLoop?;
9
+ private _streamLoop?;
10
+ private log;
11
+ private conversationHistory;
12
+ constructor(model?: string, { region }?: {
13
+ region?: string;
14
+ });
15
+ private getClient;
16
+ private getOperateLoop;
17
+ private getStreamLoop;
18
+ send(message: string, options?: LlmMessageOptions): Promise<string | JsonObject>;
19
+ operate(input: string | LlmHistory | LlmInputMessage, options?: LlmOperateOptions): Promise<LlmOperateResponse>;
20
+ stream(input: string | LlmHistory | LlmInputMessage, options?: LlmOperateOptions): AsyncIterable<LlmStreamChunk>;
21
+ }
@@ -0,0 +1 @@
1
+ export { BedrockProvider } from "./BedrockProvider.class.js";
@@ -0,0 +1,6 @@
1
+ import type { BedrockRuntimeClient } from "@aws-sdk/client-bedrock-runtime";
2
+ export declare function loadSdk(): Promise<typeof import("@aws-sdk/client-bedrock-runtime")>;
3
+ export declare const getLogger: () => import("@jaypie/logger/dist/esm/JaypieLogger").default;
4
+ export declare function initializeClient({ region, }?: {
5
+ region?: string;
6
+ }): Promise<BedrockRuntimeClient>;
@@ -1,7 +1,7 @@
1
1
  import { JsonObject } from "@jaypie/types";
2
2
  import { LlmHistory, LlmInputMessage, LlmMessageOptions, LlmOperateOptions, LlmOperateResponse, LlmProvider } from "../../types/LlmProvider.interface.js";
3
3
  import { LlmStreamChunk } from "../../types/LlmStreamChunk.interface.js";
4
- export declare class GeminiProvider implements LlmProvider {
4
+ export declare class GoogleProvider implements LlmProvider {
5
5
  private model;
6
6
  private _client?;
7
7
  private _operateLoop?;
@@ -0,0 +1,3 @@
1
+ export { GoogleProvider } from "./GoogleProvider.class.js";
2
+ export * from "./types.js";
3
+ export * from "./utils.js";
@@ -72,6 +72,7 @@ export interface GeminiGenerateContentConfig {
72
72
  };
73
73
  responseMimeType?: string;
74
74
  responseJsonSchema?: JsonObject;
75
+ responseSchema?: JsonObject;
75
76
  temperature?: number;
76
77
  topP?: number;
77
78
  topK?: number;