@deepstrike/sdk 0.2.52 → 0.2.61

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 (151) hide show
  1. package/README.md +28 -28
  2. package/dist/agent-ir.d.ts +103 -0
  3. package/dist/agent-ir.js +134 -0
  4. package/dist/agent.d.ts +67 -0
  5. package/dist/agent.js +36 -0
  6. package/dist/collaboration/harness.js +1 -1
  7. package/dist/collaboration/modes/creator-verifier.d.ts +2 -7
  8. package/dist/collaboration/modes/creator-verifier.js +4 -6
  9. package/dist/collaboration/pool.d.ts +8 -20
  10. package/dist/collaboration/pool.js +27 -97
  11. package/dist/compat/anthropic/mcp.d.ts +15 -0
  12. package/dist/compat/anthropic/mcp.js +10 -0
  13. package/dist/compat/openai/agent.d.ts +34 -0
  14. package/dist/compat/openai/agent.js +24 -0
  15. package/dist/governance.d.ts +1 -17
  16. package/dist/governance.js +1 -34
  17. package/dist/guardrail.d.ts +6 -0
  18. package/dist/guardrail.js +1 -0
  19. package/dist/handoff-target.d.ts +12 -0
  20. package/dist/handoff-target.js +1 -0
  21. package/dist/harness/manifest.js +0 -4
  22. package/dist/index.d.ts +19 -7
  23. package/dist/index.js +8 -5
  24. package/dist/kernel.d.ts +2 -20
  25. package/dist/knowledge/public.d.ts +29 -0
  26. package/dist/knowledge/public.js +1 -0
  27. package/dist/mcp-server.d.ts +28 -0
  28. package/dist/mcp-server.js +1 -0
  29. package/dist/memory/agent.d.ts +2 -2
  30. package/dist/memory/agent.js +2 -2
  31. package/dist/memory/durable.d.ts +16 -0
  32. package/dist/memory/durable.js +46 -0
  33. package/dist/memory/in-memory-store.d.ts +9 -7
  34. package/dist/memory/in-memory-store.js +8 -2
  35. package/dist/memory/protocols.d.ts +22 -4
  36. package/dist/memory/public.d.ts +4 -3
  37. package/dist/memory/public.js +3 -2
  38. package/dist/os/public.d.ts +1 -1
  39. package/dist/os/public.js +1 -1
  40. package/dist/providers/anthropic-adapter.d.ts +59 -0
  41. package/dist/providers/anthropic-adapter.js +530 -0
  42. package/dist/providers/anthropic-compatible.d.ts +2 -3
  43. package/dist/providers/anthropic-compatible.js +8 -5
  44. package/dist/providers/anthropic.d.ts +20 -23
  45. package/dist/providers/anthropic.js +176 -395
  46. package/dist/providers/base.d.ts +2 -2
  47. package/dist/providers/base.js +50 -8
  48. package/dist/providers/capability-router.d.ts +29 -0
  49. package/dist/providers/capability-router.js +43 -0
  50. package/dist/providers/catalog.d.ts +16 -4
  51. package/dist/providers/catalog.js +112 -36
  52. package/dist/providers/content-normalization.d.ts +57 -0
  53. package/dist/providers/content-normalization.js +238 -0
  54. package/dist/providers/content-policy.d.ts +16 -0
  55. package/dist/providers/content-policy.js +39 -0
  56. package/dist/providers/credentials.d.ts +83 -0
  57. package/dist/providers/credentials.js +190 -0
  58. package/dist/providers/endpoints.d.ts +137 -0
  59. package/dist/providers/endpoints.js +128 -0
  60. package/dist/providers/factories.js +25 -9
  61. package/dist/providers/gemini-adapter.d.ts +33 -0
  62. package/dist/providers/gemini-adapter.js +264 -0
  63. package/dist/providers/gemini.d.ts +16 -3
  64. package/dist/providers/gemini.js +97 -195
  65. package/dist/providers/model-catalog.d.ts +37 -0
  66. package/dist/providers/model-catalog.js +62 -0
  67. package/dist/providers/model-registry.d.ts +119 -0
  68. package/dist/providers/model-registry.js +379 -0
  69. package/dist/providers/ollama-adapter.d.ts +65 -0
  70. package/dist/providers/ollama-adapter.js +188 -0
  71. package/dist/providers/ollama.d.ts +9 -4
  72. package/dist/providers/ollama.js +96 -109
  73. package/dist/providers/openai-chat-dialects.d.ts +154 -0
  74. package/dist/providers/openai-chat-dialects.js +179 -0
  75. package/dist/providers/openai-chat.d.ts +46 -18
  76. package/dist/providers/openai-chat.js +416 -51
  77. package/dist/providers/openai-responses-adapter.d.ts +42 -0
  78. package/dist/providers/openai-responses-adapter.js +343 -0
  79. package/dist/providers/openai-responses.d.ts +19 -33
  80. package/dist/providers/openai-responses.js +164 -264
  81. package/dist/providers/openai.d.ts +29 -76
  82. package/dist/providers/openai.js +195 -292
  83. package/dist/providers/protocol-adapter.d.ts +39 -0
  84. package/dist/providers/protocol-adapter.js +13 -0
  85. package/dist/providers/protocol-capabilities.d.ts +34 -0
  86. package/dist/providers/protocol-capabilities.js +44 -0
  87. package/dist/providers/provider-error.d.ts +31 -0
  88. package/dist/providers/provider-error.js +153 -0
  89. package/dist/providers/public.d.ts +26 -3
  90. package/dist/providers/public.js +13 -1
  91. package/dist/providers/registry.d.ts +7 -6
  92. package/dist/providers/registry.js +47 -20
  93. package/dist/providers/request-plan.d.ts +89 -0
  94. package/dist/providers/request-plan.js +199 -0
  95. package/dist/providers/usage-normalizer.d.ts +48 -0
  96. package/dist/providers/usage-normalizer.js +139 -0
  97. package/dist/providers/vendor-profiles.d.ts +2 -15
  98. package/dist/providers/vendor-profiles.js +14 -60
  99. package/dist/runtime/canonical-kernel-step.d.ts +1 -2
  100. package/dist/runtime/canonical-kernel-step.js +47 -12
  101. package/dist/runtime/context-policy.d.ts +10 -12
  102. package/dist/runtime/context-policy.js +6 -8
  103. package/dist/runtime/durable-content.d.ts +50 -0
  104. package/dist/runtime/durable-content.js +159 -0
  105. package/dist/runtime/execution-plane.d.ts +2 -2
  106. package/dist/runtime/execution-plane.js +2 -2
  107. package/dist/runtime/kernel-event-log.js +0 -1
  108. package/dist/runtime/kernel-step.d.ts +0 -1
  109. package/dist/runtime/kernel-step.js +4 -2
  110. package/dist/runtime/mcp-proxy-plane.d.ts +25 -1
  111. package/dist/runtime/mcp-proxy-plane.js +44 -6
  112. package/dist/runtime/output-schema.d.ts +1 -2
  113. package/dist/runtime/provider-replay.d.ts +5 -1
  114. package/dist/runtime/provider-replay.js +26 -27
  115. package/dist/runtime/reactive-session.d.ts +1 -1
  116. package/dist/runtime/reactive-session.js +2 -3
  117. package/dist/runtime/run-group.d.ts +1 -1
  118. package/dist/runtime/runner.d.ts +31 -45
  119. package/dist/runtime/runner.js +178 -63
  120. package/dist/runtime/session-log.d.ts +8 -1
  121. package/dist/runtime/session-log.js +42 -2
  122. package/dist/runtime/session-repair.d.ts +1 -1
  123. package/dist/runtime/session-repair.js +1 -1
  124. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  125. package/dist/runtime/sub-agent-orchestrator.js +8 -11
  126. package/dist/runtime/workflow-control-flow.d.ts +0 -4
  127. package/dist/runtime/workflow-control-flow.js +0 -16
  128. package/dist/session.d.ts +11 -0
  129. package/dist/session.js +1 -0
  130. package/dist/skill.d.ts +17 -0
  131. package/dist/skill.js +16 -0
  132. package/dist/skills/loader.d.ts +3 -0
  133. package/dist/tools/errors.d.ts +1 -3
  134. package/dist/tools/errors.js +1 -3
  135. package/dist/tools/index.d.ts +3 -0
  136. package/dist/types/agent.d.ts +21 -9
  137. package/dist/types/agent.js +30 -4
  138. package/dist/types.d.ts +135 -17
  139. package/package.json +4 -4
  140. package/dist/providers/deepseek.d.ts +0 -46
  141. package/dist/providers/deepseek.js +0 -97
  142. package/dist/providers/glm.d.ts +0 -25
  143. package/dist/providers/glm.js +0 -48
  144. package/dist/providers/kimi.d.ts +0 -23
  145. package/dist/providers/kimi.js +0 -30
  146. package/dist/providers/minimax.d.ts +0 -49
  147. package/dist/providers/minimax.js +0 -98
  148. package/dist/providers/profiles.d.ts +0 -1992
  149. package/dist/providers/profiles.js +0 -796
  150. package/dist/providers/qwen.d.ts +0 -38
  151. package/dist/providers/qwen.js +0 -97
@@ -0,0 +1,137 @@
1
+ export type ProviderId = "anthropic" | "openai" | "minimax" | "deepseek" | "kimi" | "qwen" | "gemini" | "glm" | "baai" | "ollama";
2
+ export type EndpointProtocol = "anthropic-messages" | "openai-chat" | "openai-responses" | "openai-embeddings" | "dashscope-multimodal-embeddings" | "gemini" | "gemini-embeddings" | "self-hosted-embeddings" | "ollama-chat";
3
+ export interface EndpointProfile {
4
+ id: string;
5
+ providerId: ProviderId;
6
+ protocol: EndpointProtocol;
7
+ baseURL: string;
8
+ }
9
+ export declare const endpointProfiles: {
10
+ readonly "anthropic.messages": {
11
+ readonly id: "anthropic.messages";
12
+ readonly providerId: "anthropic";
13
+ readonly protocol: "anthropic-messages";
14
+ readonly baseURL: "https://api.anthropic.com";
15
+ };
16
+ readonly "openai.chat": {
17
+ readonly id: "openai.chat";
18
+ readonly providerId: "openai";
19
+ readonly protocol: "openai-chat";
20
+ readonly baseURL: "https://api.openai.com/v1";
21
+ };
22
+ readonly "openai.responses": {
23
+ readonly id: "openai.responses";
24
+ readonly providerId: "openai";
25
+ readonly protocol: "openai-responses";
26
+ readonly baseURL: "https://api.openai.com/v1";
27
+ };
28
+ readonly "openai.embeddings": {
29
+ readonly id: "openai.embeddings";
30
+ readonly providerId: "openai";
31
+ readonly protocol: "openai-embeddings";
32
+ readonly baseURL: "https://api.openai.com/v1";
33
+ };
34
+ readonly "minimax.anthropic": {
35
+ readonly id: "minimax.anthropic";
36
+ readonly providerId: "minimax";
37
+ readonly protocol: "anthropic-messages";
38
+ readonly baseURL: "https://api.minimaxi.com/anthropic";
39
+ };
40
+ readonly "minimax.openai": {
41
+ readonly id: "minimax.openai";
42
+ readonly providerId: "minimax";
43
+ readonly protocol: "openai-chat";
44
+ readonly baseURL: "https://api.minimaxi.com/v1";
45
+ };
46
+ readonly "deepseek.anthropic": {
47
+ readonly id: "deepseek.anthropic";
48
+ readonly providerId: "deepseek";
49
+ readonly protocol: "anthropic-messages";
50
+ readonly baseURL: "https://api.deepseek.com/anthropic";
51
+ };
52
+ readonly "deepseek.openai": {
53
+ readonly id: "deepseek.openai";
54
+ readonly providerId: "deepseek";
55
+ readonly protocol: "openai-chat";
56
+ readonly baseURL: "https://api.deepseek.com";
57
+ };
58
+ readonly "kimi.anthropic": {
59
+ readonly id: "kimi.anthropic";
60
+ readonly providerId: "kimi";
61
+ readonly protocol: "anthropic-messages";
62
+ readonly baseURL: "https://api.moonshot.cn/anthropic";
63
+ };
64
+ readonly "kimi.openai": {
65
+ readonly id: "kimi.openai";
66
+ readonly providerId: "kimi";
67
+ readonly protocol: "openai-chat";
68
+ readonly baseURL: "https://api.moonshot.cn/v1";
69
+ };
70
+ readonly "qwen.anthropic": {
71
+ readonly id: "qwen.anthropic";
72
+ readonly providerId: "qwen";
73
+ readonly protocol: "anthropic-messages";
74
+ readonly baseURL: "https://dashscope-intl.aliyuncs.com/apps/anthropic";
75
+ };
76
+ readonly "qwen.dashscope": {
77
+ readonly id: "qwen.dashscope";
78
+ readonly providerId: "qwen";
79
+ readonly protocol: "openai-chat";
80
+ readonly baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1";
81
+ };
82
+ readonly "qwen.dashscope.embeddings": {
83
+ readonly id: "qwen.dashscope.embeddings";
84
+ readonly providerId: "qwen";
85
+ readonly protocol: "openai-embeddings";
86
+ readonly baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1";
87
+ };
88
+ readonly "qwen.dashscope.multimodal-embeddings": {
89
+ readonly id: "qwen.dashscope.multimodal-embeddings";
90
+ readonly providerId: "qwen";
91
+ readonly protocol: "dashscope-multimodal-embeddings";
92
+ readonly baseURL: "https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding";
93
+ };
94
+ readonly "gemini.google": {
95
+ readonly id: "gemini.google";
96
+ readonly providerId: "gemini";
97
+ readonly protocol: "gemini";
98
+ readonly baseURL: "https://generativelanguage.googleapis.com";
99
+ };
100
+ readonly "gemini.google.embeddings": {
101
+ readonly id: "gemini.google.embeddings";
102
+ readonly providerId: "gemini";
103
+ readonly protocol: "gemini-embeddings";
104
+ readonly baseURL: "https://generativelanguage.googleapis.com";
105
+ };
106
+ readonly "glm.anthropic": {
107
+ readonly id: "glm.anthropic";
108
+ readonly providerId: "glm";
109
+ readonly protocol: "anthropic-messages";
110
+ readonly baseURL: "https://open.bigmodel.cn/api/anthropic";
111
+ };
112
+ readonly "glm.openai": {
113
+ readonly id: "glm.openai";
114
+ readonly providerId: "glm";
115
+ readonly protocol: "openai-chat";
116
+ readonly baseURL: "https://open.bigmodel.cn/api/paas/v4";
117
+ };
118
+ readonly "glm.openai.embeddings": {
119
+ readonly id: "glm.openai.embeddings";
120
+ readonly providerId: "glm";
121
+ readonly protocol: "openai-embeddings";
122
+ readonly baseURL: "https://open.bigmodel.cn/api/paas/v4";
123
+ };
124
+ readonly "baai.self-hosted.embeddings": {
125
+ readonly id: "baai.self-hosted.embeddings";
126
+ readonly providerId: "baai";
127
+ readonly protocol: "self-hosted-embeddings";
128
+ readonly baseURL: "https://huggingface.co/BAAI";
129
+ };
130
+ readonly "ollama.local": {
131
+ readonly id: "ollama.local";
132
+ readonly providerId: "ollama";
133
+ readonly protocol: "ollama-chat";
134
+ readonly baseURL: "http://localhost:11434";
135
+ };
136
+ };
137
+ export type EndpointProfileId = keyof typeof endpointProfiles;
@@ -0,0 +1,128 @@
1
+ export const endpointProfiles = {
2
+ "anthropic.messages": {
3
+ id: "anthropic.messages",
4
+ providerId: "anthropic",
5
+ protocol: "anthropic-messages",
6
+ baseURL: "https://api.anthropic.com",
7
+ },
8
+ "openai.chat": {
9
+ id: "openai.chat",
10
+ providerId: "openai",
11
+ protocol: "openai-chat",
12
+ baseURL: "https://api.openai.com/v1",
13
+ },
14
+ "openai.responses": {
15
+ id: "openai.responses",
16
+ providerId: "openai",
17
+ protocol: "openai-responses",
18
+ baseURL: "https://api.openai.com/v1",
19
+ },
20
+ "openai.embeddings": {
21
+ id: "openai.embeddings",
22
+ providerId: "openai",
23
+ protocol: "openai-embeddings",
24
+ baseURL: "https://api.openai.com/v1",
25
+ },
26
+ "minimax.anthropic": {
27
+ id: "minimax.anthropic",
28
+ providerId: "minimax",
29
+ protocol: "anthropic-messages",
30
+ baseURL: "https://api.minimaxi.com/anthropic",
31
+ },
32
+ "minimax.openai": {
33
+ id: "minimax.openai",
34
+ providerId: "minimax",
35
+ protocol: "openai-chat",
36
+ baseURL: "https://api.minimaxi.com/v1",
37
+ },
38
+ "deepseek.anthropic": {
39
+ id: "deepseek.anthropic",
40
+ providerId: "deepseek",
41
+ protocol: "anthropic-messages",
42
+ baseURL: "https://api.deepseek.com/anthropic",
43
+ },
44
+ "deepseek.openai": {
45
+ id: "deepseek.openai",
46
+ providerId: "deepseek",
47
+ protocol: "openai-chat",
48
+ baseURL: "https://api.deepseek.com",
49
+ },
50
+ "kimi.anthropic": {
51
+ id: "kimi.anthropic",
52
+ providerId: "kimi",
53
+ protocol: "anthropic-messages",
54
+ baseURL: "https://api.moonshot.cn/anthropic",
55
+ },
56
+ "kimi.openai": {
57
+ id: "kimi.openai",
58
+ providerId: "kimi",
59
+ protocol: "openai-chat",
60
+ baseURL: "https://api.moonshot.cn/v1",
61
+ },
62
+ "qwen.anthropic": {
63
+ id: "qwen.anthropic",
64
+ providerId: "qwen",
65
+ protocol: "anthropic-messages",
66
+ baseURL: "https://dashscope-intl.aliyuncs.com/apps/anthropic",
67
+ },
68
+ "qwen.dashscope": {
69
+ id: "qwen.dashscope",
70
+ providerId: "qwen",
71
+ protocol: "openai-chat",
72
+ baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
73
+ },
74
+ "qwen.dashscope.embeddings": {
75
+ id: "qwen.dashscope.embeddings",
76
+ providerId: "qwen",
77
+ protocol: "openai-embeddings",
78
+ baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
79
+ },
80
+ "qwen.dashscope.multimodal-embeddings": {
81
+ id: "qwen.dashscope.multimodal-embeddings",
82
+ providerId: "qwen",
83
+ protocol: "dashscope-multimodal-embeddings",
84
+ baseURL: "https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding",
85
+ },
86
+ "gemini.google": {
87
+ id: "gemini.google",
88
+ providerId: "gemini",
89
+ protocol: "gemini",
90
+ baseURL: "https://generativelanguage.googleapis.com",
91
+ },
92
+ "gemini.google.embeddings": {
93
+ id: "gemini.google.embeddings",
94
+ providerId: "gemini",
95
+ protocol: "gemini-embeddings",
96
+ baseURL: "https://generativelanguage.googleapis.com",
97
+ },
98
+ "glm.anthropic": {
99
+ id: "glm.anthropic",
100
+ providerId: "glm",
101
+ protocol: "anthropic-messages",
102
+ baseURL: "https://open.bigmodel.cn/api/anthropic",
103
+ },
104
+ "glm.openai": {
105
+ id: "glm.openai",
106
+ providerId: "glm",
107
+ protocol: "openai-chat",
108
+ baseURL: "https://open.bigmodel.cn/api/paas/v4",
109
+ },
110
+ "glm.openai.embeddings": {
111
+ id: "glm.openai.embeddings",
112
+ providerId: "glm",
113
+ protocol: "openai-embeddings",
114
+ baseURL: "https://open.bigmodel.cn/api/paas/v4",
115
+ },
116
+ "baai.self-hosted.embeddings": {
117
+ id: "baai.self-hosted.embeddings",
118
+ providerId: "baai",
119
+ protocol: "self-hosted-embeddings",
120
+ baseURL: "https://huggingface.co/BAAI",
121
+ },
122
+ "ollama.local": {
123
+ id: "ollama.local",
124
+ providerId: "ollama",
125
+ protocol: "ollama-chat",
126
+ baseURL: "http://localhost:11434",
127
+ },
128
+ };
@@ -1,33 +1,49 @@
1
1
  import { PROVIDER_REGISTRY } from "./registry.js";
2
2
  import { OllamaProvider } from "./ollama.js";
3
- function build(providerId, protocol, o) {
4
- return PROVIDER_REGISTRY[`${providerId}:${protocol}`](o.apiKey, o.model, o.retry, o.baseURL);
3
+ import { defaultEndpointForProvider, defaultModelForProvider, getRuntimePolicy, isKnownProviderId } from "./model-registry.js";
4
+ import { endpointProfiles } from "./endpoints.js";
5
+ function build(providerId, o) {
6
+ if (!isKnownProviderId(providerId))
7
+ throw new Error(`Unknown provider: ${providerId}`);
8
+ const defaultProtocol = endpointProfiles[defaultEndpointForProvider(providerId)].protocol;
9
+ const protocol = o.protocol === "openai"
10
+ ? "openai-chat"
11
+ : o.protocol === "anthropic"
12
+ ? "anthropic-messages"
13
+ : defaultProtocol;
14
+ if (protocol !== "openai-chat" && protocol !== "anthropic-messages") {
15
+ throw new Error(`Provider ${providerId} does not use an OpenAI- or Anthropic-compatible default`);
16
+ }
17
+ const model = o.model ?? defaultModelForProvider(providerId);
18
+ return PROVIDER_REGISTRY[`${providerId}:${protocol}`](o.apiKey, model, o.retry, o.baseURL, getRuntimePolicy(providerId, model));
5
19
  }
6
20
  /** DeepSeek. Defaults to the OpenAI-compatible wire (richer reasoning-replay handling). */
7
21
  export function deepseek(o) {
8
- return build("deepseek", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
22
+ return build("deepseek", o);
9
23
  }
10
24
  /** Moonshot Kimi. Defaults to the OpenAI-compatible wire. */
11
25
  export function kimi(o) {
12
- return build("kimi", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
26
+ return build("kimi", o);
13
27
  }
14
28
  /** Alibaba Qwen / DashScope. Defaults to the OpenAI-compatible (DashScope) wire. */
15
29
  export function qwen(o) {
16
- return build("qwen", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
30
+ return build("qwen", o);
17
31
  }
18
32
  /** Zhipu GLM. Defaults to the OpenAI-compatible wire. */
19
33
  export function glm(o) {
20
- return build("glm", o.protocol === "anthropic" ? "anthropic-messages" : "openai-chat", o);
34
+ return build("glm", o);
21
35
  }
22
36
  /** MiniMax. Defaults to the Anthropic-compatible wire (the primary M2.x path). */
23
37
  export function minimax(o) {
24
- return build("minimax", o.protocol === "openai" ? "openai-chat" : "anthropic-messages", o);
38
+ return build("minimax", o);
25
39
  }
26
40
  /** Google Gemini (single wire). */
27
41
  export function gemini(o) {
28
- return PROVIDER_REGISTRY["gemini:gemini"](o.apiKey, o.model, o.retry, o.baseURL);
42
+ const model = o.model ?? defaultModelForProvider("gemini");
43
+ return PROVIDER_REGISTRY["gemini:gemini"](o.apiKey, model, o.retry, o.baseURL, getRuntimePolicy("gemini", model));
29
44
  }
30
45
  /** Local Ollama (single wire, no API key). */
31
46
  export function ollama(o = {}) {
32
- return new OllamaProvider(o.model, o.baseURL);
47
+ const model = o.model ?? defaultModelForProvider("ollama");
48
+ return new OllamaProvider(model, o.baseURL, getRuntimePolicy("ollama", model));
33
49
  }
@@ -0,0 +1,33 @@
1
+ import type { Content, GenerateContentRequest, GenerateContentResponse, ModelParams, Tool } from "@google/generative-ai";
2
+ import type { Message, ProviderUsage } from "../types.js";
3
+ import type { CanonicalAdapterInput } from "./content-normalization.js";
4
+ import { type AdapterDecodeInput, type AdapterOutput, type AdapterStreamInput, type CanonicalStopReason, type ProtocolAdapter } from "./protocol-adapter.js";
5
+ export interface GeminiRequestPlan {
6
+ modelParams: ModelParams & Record<string, unknown>;
7
+ request: GenerateContentRequest;
8
+ }
9
+ export interface GeminiStreamState {
10
+ readonly input: CanonicalAdapterInput;
11
+ readonly toolCalls: Array<{
12
+ name: string;
13
+ args: Record<string, unknown>;
14
+ }>;
15
+ }
16
+ export declare function canonicalGeminiContents(context: CanonicalAdapterInput["context"]): Content[];
17
+ export declare function geminiVendorConfig(extensions: Readonly<Record<string, unknown>>): {
18
+ tools?: Tool[];
19
+ generationConfig?: Record<string, unknown>;
20
+ };
21
+ export declare class GeminiAdapter implements ProtocolAdapter<GeminiRequestPlan, GenerateContentResponse, GenerateContentResponse, GeminiStreamState, GenerateContentResponse> {
22
+ readonly protocol: "gemini";
23
+ readonly protocolCapabilities: import("./protocol-capabilities.js").ProtocolRuntimeCapabilities;
24
+ buildRequest(input: CanonicalAdapterInput): GeminiRequestPlan;
25
+ decodeComplete(raw: GenerateContentResponse, _input: AdapterDecodeInput): {
26
+ message: Message;
27
+ };
28
+ createStreamState(input: AdapterStreamInput): GeminiStreamState;
29
+ pushStreamChunk(chunk: GenerateContentResponse, state: GeminiStreamState): AdapterOutput;
30
+ finishStream(state: GeminiStreamState, final: GenerateContentResponse): AdapterOutput;
31
+ normalizeUsage(raw: unknown): ProviderUsage | undefined;
32
+ normalizeStopReason(raw: string | undefined): CanonicalStopReason | undefined;
33
+ }
@@ -0,0 +1,264 @@
1
+ import { projectToolOutputToText } from "./content-normalization.js";
2
+ import { normalizeToolCall } from "./base.js";
3
+ import { normalizeGeminiUsage } from "./usage-normalizer.js";
4
+ import { ProtocolResponseError, GEMINI_PROTOCOL_CAPABILITIES, } from "./protocol-adapter.js";
5
+ // Google Generate Content streams response chunks, while @google/generative-ai 0.24.1 exposes
6
+ // a separate promise for the aggregated response. Candidate finishReason and aggregate usage are
7
+ // therefore decoded only by finishStream.
8
+ // Source: https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent
9
+ // Source: https://github.com/google-gemini/deprecated-generative-ai-js/blob/v0.24.1/types/responses.ts
10
+ function parseArguments(argumentsJson) {
11
+ try {
12
+ const value = JSON.parse(argumentsJson);
13
+ return value && typeof value === "object" && !Array.isArray(value)
14
+ ? value
15
+ : {};
16
+ }
17
+ catch {
18
+ return {};
19
+ }
20
+ }
21
+ function toolName(callId, messages) {
22
+ for (let index = messages.length - 1; index >= 0; index--) {
23
+ const match = messages[index].toolCalls?.find(call => call.id === callId);
24
+ if (match)
25
+ return match.name;
26
+ }
27
+ return callId;
28
+ }
29
+ function toolResultPart(result, messages) {
30
+ return {
31
+ functionResponse: {
32
+ name: toolName(result.callId, messages),
33
+ response: { output: projectToolOutputToText(result.blocks) },
34
+ },
35
+ };
36
+ }
37
+ function contentPart(block) {
38
+ if (block.type === "text")
39
+ return block.text ? { text: block.text } : undefined;
40
+ if (block.type === "image" || block.type === "audio") {
41
+ if (block.source.kind === "base64") {
42
+ return {
43
+ inlineData: {
44
+ mimeType: block.mediaType ?? (block.type === "image" ? "image/png" : "audio/wav"),
45
+ data: block.source.data,
46
+ },
47
+ };
48
+ }
49
+ if (block.source.kind === "url") {
50
+ return {
51
+ fileData: {
52
+ mimeType: block.mediaType ?? (block.type === "image" ? "image/png" : "audio/wav"),
53
+ fileUri: block.source.url,
54
+ },
55
+ };
56
+ }
57
+ }
58
+ if (block.type === "video" || block.type === "file") {
59
+ throw new ProtocolResponseError("gemini", `cannot serialize ${block.type}`);
60
+ }
61
+ throw new ProtocolResponseError("gemini", `cannot serialize ${block.type} source`);
62
+ }
63
+ export function canonicalGeminiContents(context) {
64
+ const messages = context.stateTurn ? [...context.turns, context.stateTurn] : context.turns;
65
+ const contents = [];
66
+ for (const message of messages) {
67
+ const parts = [];
68
+ for (const call of message.toolCalls ?? []) {
69
+ parts.push({
70
+ functionCall: { name: call.name, args: parseArguments(call.arguments) },
71
+ });
72
+ }
73
+ for (const block of message.blocks) {
74
+ if (block.type === "tool_result") {
75
+ parts.push(toolResultPart(block, messages));
76
+ }
77
+ else {
78
+ const part = contentPart(block);
79
+ if (part)
80
+ parts.push(part);
81
+ }
82
+ }
83
+ if (!parts.length)
84
+ continue;
85
+ contents.push({
86
+ role: message.role === "assistant" ? "model" : "user",
87
+ parts,
88
+ });
89
+ }
90
+ return contents;
91
+ }
92
+ function buildTools(tools) {
93
+ if (!tools.length)
94
+ return [];
95
+ return [{
96
+ functionDeclarations: tools.map(tool => ({
97
+ name: tool.name,
98
+ description: tool.description,
99
+ parameters: JSON.parse(tool.parameters),
100
+ })),
101
+ }];
102
+ }
103
+ function modelExtensions(extensions) {
104
+ const { model: _model, systemInstruction: _systemInstruction, tools: _tools, google_search: _googleSearch, response_mime_type: _responseMimeType, response_schema: _responseSchema, generationConfig: _generationConfig, ...rest } = extensions;
105
+ return rest;
106
+ }
107
+ export function geminiVendorConfig(extensions) {
108
+ const tools = [];
109
+ if (extensions.google_search) {
110
+ tools.push({
111
+ googleSearch: typeof extensions.google_search === "object"
112
+ ? extensions.google_search
113
+ : {},
114
+ });
115
+ }
116
+ const generationConfig = {
117
+ ...extensions.generationConfig,
118
+ };
119
+ if (extensions.response_mime_type != null) {
120
+ generationConfig.responseMimeType = extensions.response_mime_type;
121
+ }
122
+ if (extensions.response_schema != null) {
123
+ generationConfig.responseSchema = extensions.response_schema;
124
+ }
125
+ return {
126
+ ...(tools.length ? { tools } : {}),
127
+ ...(Object.keys(generationConfig).length ? { generationConfig } : {}),
128
+ };
129
+ }
130
+ function decodeParts(raw) {
131
+ const candidate = raw.candidates?.[0];
132
+ let content = "";
133
+ const toolCalls = [];
134
+ for (const part of candidate?.content.parts ?? []) {
135
+ if (part.text)
136
+ content += part.text;
137
+ else if (part.functionCall) {
138
+ const call = normalizeToolCall(part.functionCall.name, part.functionCall.name, part.functionCall.args);
139
+ if (call)
140
+ toolCalls.push(call);
141
+ }
142
+ }
143
+ return { content, toolCalls };
144
+ }
145
+ function numberField(raw, field) {
146
+ const value = raw[field];
147
+ if (value === undefined)
148
+ return undefined;
149
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
150
+ throw new ProtocolResponseError("gemini", `usage.${field} must be a non-negative safe integer`);
151
+ }
152
+ return value;
153
+ }
154
+ export class GeminiAdapter {
155
+ protocol = "gemini";
156
+ protocolCapabilities = GEMINI_PROTOCOL_CAPABILITIES;
157
+ buildRequest(input) {
158
+ const extensions = input.extensions;
159
+ const vendor = geminiVendorConfig(extensions);
160
+ const tools = [...buildTools(input.tools), ...(vendor.tools ?? [])];
161
+ return {
162
+ modelParams: {
163
+ ...modelExtensions(extensions),
164
+ model: input.resolved.identity.modelId,
165
+ ...(input.context.systemText ? { systemInstruction: input.context.systemText } : {}),
166
+ ...(tools.length ? { tools } : {}),
167
+ ...(vendor.generationConfig ? { generationConfig: vendor.generationConfig } : {}),
168
+ },
169
+ request: { contents: canonicalGeminiContents(input.context) },
170
+ };
171
+ }
172
+ decodeComplete(raw, _input) {
173
+ const decoded = decodeParts(raw);
174
+ const usage = this.normalizeUsage(raw.usageMetadata);
175
+ const rawUsage = raw.usageMetadata;
176
+ const tokenCount = usage?.outputTokens
177
+ ?? (rawUsage ? numberField(rawUsage, "totalTokenCount") : undefined);
178
+ return {
179
+ message: {
180
+ role: "assistant",
181
+ content: decoded.content,
182
+ ...(tokenCount !== undefined ? { tokenCount } : {}),
183
+ toolCalls: decoded.toolCalls,
184
+ },
185
+ };
186
+ }
187
+ createStreamState(input) {
188
+ return { input: input.input, toolCalls: [] };
189
+ }
190
+ pushStreamChunk(chunk, state) {
191
+ const events = [];
192
+ for (const part of chunk.candidates?.[0]?.content.parts ?? []) {
193
+ if (part.text)
194
+ events.push({ type: "text_delta", delta: part.text });
195
+ else if (part.functionCall) {
196
+ state.toolCalls.push({
197
+ name: part.functionCall.name,
198
+ args: part.functionCall.args,
199
+ });
200
+ }
201
+ }
202
+ return { events };
203
+ }
204
+ finishStream(state, final) {
205
+ const events = state.toolCalls.map((call, index) => ({
206
+ type: "tool_call",
207
+ id: `call_${index + 1}`,
208
+ name: call.name,
209
+ arguments: call.args,
210
+ }));
211
+ const usage = this.normalizeUsage(final.usageMetadata);
212
+ const rawStopReason = final.candidates?.[0]?.finishReason;
213
+ const stopReason = this.normalizeStopReason(rawStopReason);
214
+ if (usage) {
215
+ const raw = final.usageMetadata;
216
+ const totalTokens = numberField(raw, "totalTokenCount")
217
+ ?? usage.inputTokens + usage.outputTokens;
218
+ events.push({
219
+ type: "usage",
220
+ totalTokens,
221
+ inputTokens: usage.inputTokens,
222
+ outputTokens: usage.outputTokens,
223
+ ...(usage.cacheReadInputTokens
224
+ ? { cacheReadInputTokens: usage.cacheReadInputTokens }
225
+ : {}),
226
+ ...(usage.cacheTelemetryStatus ? { cacheTelemetryStatus: usage.cacheTelemetryStatus } : {}),
227
+ ...(usage.cacheTelemetrySource ? { cacheTelemetrySource: usage.cacheTelemetrySource } : {}),
228
+ providerUsage: usage,
229
+ ...(stopReason ? { stopReason } : {}),
230
+ ...(rawStopReason ? { rawStopReason } : {}),
231
+ });
232
+ }
233
+ return { events };
234
+ }
235
+ normalizeUsage(raw) {
236
+ if (raw === undefined || raw === null)
237
+ return undefined;
238
+ if (typeof raw !== "object" || Array.isArray(raw)) {
239
+ throw new ProtocolResponseError("gemini", "usage must be an object");
240
+ }
241
+ const usage = raw;
242
+ numberField(usage, "totalTokenCount");
243
+ return normalizeGeminiUsage(usage);
244
+ }
245
+ normalizeStopReason(raw) {
246
+ if (raw === undefined)
247
+ return undefined;
248
+ switch (raw) {
249
+ case "STOP":
250
+ case "FINISH_REASON_STOP":
251
+ return "end_turn";
252
+ case "MAX_TOKENS":
253
+ return "max_tokens";
254
+ case "SAFETY":
255
+ case "RECITATION":
256
+ case "BLOCKLIST":
257
+ case "PROHIBITED_CONTENT":
258
+ case "SPII":
259
+ return "content_filter";
260
+ default:
261
+ return "other";
262
+ }
263
+ }
264
+ }
@@ -1,21 +1,33 @@
1
1
  import { type Content } from "@google/generative-ai";
2
- import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy } from "../types.js";
2
+ import type { Message, RenderedContext, ToolSchema, StreamEvent, LLMProvider, RuntimePolicy, PromptMeasurement } from "../types.js";
3
+ import { type CanonicalAdapterInput } from "./content-normalization.js";
4
+ type ResolvedGeminiRuntime = CanonicalAdapterInput["resolved"];
3
5
  export declare function buildContents(turns: Message[]): Content[];
4
6
  export declare class GeminiProvider implements LLMProvider {
5
7
  private readonly model;
8
+ private resolvedRuntime?;
6
9
  private genAI;
7
10
  private circuit;
8
11
  private maxRetries;
9
12
  private baseDelay;
10
13
  private requestOptions;
14
+ private readonly resolvedRuntimePolicy;
15
+ private readonly adapter;
11
16
  constructor(apiKey: string, model?: string, retry?: {
12
17
  maxRetries: number;
13
18
  baseDelay: number;
14
- }, baseURL?: string);
19
+ }, baseURL?: string, runtimePolicy?: RuntimePolicy, resolvedRuntime?: ResolvedGeminiRuntime | undefined);
15
20
  runtimePolicy(): RuntimePolicy;
21
+ bindResolvedRuntime(resolved: ResolvedGeminiRuntime): void;
22
+ private adapterInput;
16
23
  complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
17
24
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
18
- private modelExtensions;
25
+ /**
26
+ * spc_011-C-05: preflight native token count via `GenerativeModel.countTokens` — reuses the
27
+ * same contents/tools/vendorConfig construction `complete()` uses so the counted request and
28
+ * the sent request never diverge.
29
+ */
30
+ countTokens(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<PromptMeasurement>;
19
31
  /**
20
32
  * Gemini vendor features from extensions, mapped to the Node SDK shape (mirrors the Python provider's
21
33
  * extension keys for a consistent cross-SDK API):
@@ -29,3 +41,4 @@ export declare class GeminiProvider implements LLMProvider {
29
41
  generationConfig?: Record<string, unknown>;
30
42
  };
31
43
  }
44
+ export {};