@llm4ts/core 0.1.0

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 (284) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/AgentSession.d.ts +66 -0
  4. package/dist/AgentSession.d.ts.map +1 -0
  5. package/dist/AgentSession.js +53 -0
  6. package/dist/AgentSession.js.map +1 -0
  7. package/dist/Capability.d.ts +101 -0
  8. package/dist/Capability.d.ts.map +1 -0
  9. package/dist/Capability.js +210 -0
  10. package/dist/Capability.js.map +1 -0
  11. package/dist/Connector.d.ts +69 -0
  12. package/dist/Connector.d.ts.map +1 -0
  13. package/dist/Connector.js +86 -0
  14. package/dist/Connector.js.map +1 -0
  15. package/dist/ConnectorConfig.d.ts +70 -0
  16. package/dist/ConnectorConfig.d.ts.map +1 -0
  17. package/dist/ConnectorConfig.js +110 -0
  18. package/dist/ConnectorConfig.js.map +1 -0
  19. package/dist/ConnectorRegistry.d.ts +28 -0
  20. package/dist/ConnectorRegistry.d.ts.map +1 -0
  21. package/dist/ConnectorRegistry.js +87 -0
  22. package/dist/ConnectorRegistry.js.map +1 -0
  23. package/dist/ContextManagement.d.ts +78 -0
  24. package/dist/ContextManagement.d.ts.map +1 -0
  25. package/dist/ContextManagement.js +221 -0
  26. package/dist/ContextManagement.js.map +1 -0
  27. package/dist/Conversation.d.ts +18 -0
  28. package/dist/Conversation.d.ts.map +1 -0
  29. package/dist/Conversation.js +17 -0
  30. package/dist/Conversation.js.map +1 -0
  31. package/dist/Errors.d.ts +64 -0
  32. package/dist/Errors.d.ts.map +1 -0
  33. package/dist/Errors.js +76 -0
  34. package/dist/Errors.js.map +1 -0
  35. package/dist/HttpClient.d.ts +43 -0
  36. package/dist/HttpClient.d.ts.map +1 -0
  37. package/dist/HttpClient.js +99 -0
  38. package/dist/HttpClient.js.map +1 -0
  39. package/dist/LlmService.d.ts +24 -0
  40. package/dist/LlmService.d.ts.map +1 -0
  41. package/dist/LlmService.js +4 -0
  42. package/dist/LlmService.js.map +1 -0
  43. package/dist/Models.d.ts +138 -0
  44. package/dist/Models.d.ts.map +1 -0
  45. package/dist/Models.js +209 -0
  46. package/dist/Models.js.map +1 -0
  47. package/dist/ProcessExecutor.d.ts +57 -0
  48. package/dist/ProcessExecutor.d.ts.map +1 -0
  49. package/dist/ProcessExecutor.js +71 -0
  50. package/dist/ProcessExecutor.js.map +1 -0
  51. package/dist/RateLimiter.d.ts +44 -0
  52. package/dist/RateLimiter.d.ts.map +1 -0
  53. package/dist/RateLimiter.js +155 -0
  54. package/dist/RateLimiter.js.map +1 -0
  55. package/dist/Streaming.d.ts +17 -0
  56. package/dist/Streaming.d.ts.map +1 -0
  57. package/dist/Streaming.js +65 -0
  58. package/dist/Streaming.js.map +1 -0
  59. package/dist/StructuredOutput.d.ts +10 -0
  60. package/dist/StructuredOutput.d.ts.map +1 -0
  61. package/dist/StructuredOutput.js +97 -0
  62. package/dist/StructuredOutput.js.map +1 -0
  63. package/dist/TemporaryFiles.d.ts +20 -0
  64. package/dist/TemporaryFiles.d.ts.map +1 -0
  65. package/dist/TemporaryFiles.js +18 -0
  66. package/dist/TemporaryFiles.js.map +1 -0
  67. package/dist/UsageLimits.d.ts +5 -0
  68. package/dist/UsageLimits.d.ts.map +1 -0
  69. package/dist/UsageLimits.js +187 -0
  70. package/dist/UsageLimits.js.map +1 -0
  71. package/dist/eval/Checks.d.ts +6 -0
  72. package/dist/eval/Checks.d.ts.map +1 -0
  73. package/dist/eval/Checks.js +39 -0
  74. package/dist/eval/Checks.js.map +1 -0
  75. package/dist/eval/Eval.d.ts +57 -0
  76. package/dist/eval/Eval.d.ts.map +1 -0
  77. package/dist/eval/Eval.js +91 -0
  78. package/dist/eval/Eval.js.map +1 -0
  79. package/dist/eval/EvalSuite.d.ts +21 -0
  80. package/dist/eval/EvalSuite.d.ts.map +1 -0
  81. package/dist/eval/EvalSuite.js +30 -0
  82. package/dist/eval/EvalSuite.js.map +1 -0
  83. package/dist/eval/Evaluator.d.ts +10 -0
  84. package/dist/eval/Evaluator.d.ts.map +1 -0
  85. package/dist/eval/Evaluator.js +14 -0
  86. package/dist/eval/Evaluator.js.map +1 -0
  87. package/dist/eval/Judge.d.ts +15 -0
  88. package/dist/eval/Judge.d.ts.map +1 -0
  89. package/dist/eval/Judge.js +73 -0
  90. package/dist/eval/Judge.js.map +1 -0
  91. package/dist/observability/MeteredLlmService.d.ts +16 -0
  92. package/dist/observability/MeteredLlmService.d.ts.map +1 -0
  93. package/dist/observability/MeteredLlmService.js +66 -0
  94. package/dist/observability/MeteredLlmService.js.map +1 -0
  95. package/dist/observability/Metrics.d.ts +71 -0
  96. package/dist/observability/Metrics.d.ts.map +1 -0
  97. package/dist/observability/Metrics.js +147 -0
  98. package/dist/observability/Metrics.js.map +1 -0
  99. package/dist/observability/Redaction.d.ts +8 -0
  100. package/dist/observability/Redaction.d.ts.map +1 -0
  101. package/dist/observability/Redaction.js +38 -0
  102. package/dist/observability/Redaction.js.map +1 -0
  103. package/dist/observability/StreamRecorder.d.ts +9 -0
  104. package/dist/observability/StreamRecorder.d.ts.map +1 -0
  105. package/dist/observability/StreamRecorder.js +10 -0
  106. package/dist/observability/StreamRecorder.js.map +1 -0
  107. package/dist/observability/StructuredLogger.d.ts +31 -0
  108. package/dist/observability/StructuredLogger.d.ts.map +1 -0
  109. package/dist/observability/StructuredLogger.js +34 -0
  110. package/dist/observability/StructuredLogger.js.map +1 -0
  111. package/dist/observability/Tracing.d.ts +38 -0
  112. package/dist/observability/Tracing.d.ts.map +1 -0
  113. package/dist/observability/Tracing.js +75 -0
  114. package/dist/observability/Tracing.js.map +1 -0
  115. package/dist/providers/AnthropicModels.d.ts +95 -0
  116. package/dist/providers/AnthropicModels.d.ts.map +1 -0
  117. package/dist/providers/AnthropicModels.js +83 -0
  118. package/dist/providers/AnthropicModels.js.map +1 -0
  119. package/dist/providers/AnthropicProvider.d.ts +13 -0
  120. package/dist/providers/AnthropicProvider.d.ts.map +1 -0
  121. package/dist/providers/AnthropicProvider.js +177 -0
  122. package/dist/providers/AnthropicProvider.js.map +1 -0
  123. package/dist/providers/AntigravityConnector.d.ts +7 -0
  124. package/dist/providers/AntigravityConnector.d.ts.map +1 -0
  125. package/dist/providers/AntigravityConnector.js +52 -0
  126. package/dist/providers/AntigravityConnector.js.map +1 -0
  127. package/dist/providers/ClaudeAgentSession.d.ts +11 -0
  128. package/dist/providers/ClaudeAgentSession.d.ts.map +1 -0
  129. package/dist/providers/ClaudeAgentSession.js +158 -0
  130. package/dist/providers/ClaudeAgentSession.js.map +1 -0
  131. package/dist/providers/ClaudeCliConnector.d.ts +9 -0
  132. package/dist/providers/ClaudeCliConnector.d.ts.map +1 -0
  133. package/dist/providers/ClaudeCliConnector.js +123 -0
  134. package/dist/providers/ClaudeCliConnector.js.map +1 -0
  135. package/dist/providers/CliSupport.d.ts +21 -0
  136. package/dist/providers/CliSupport.d.ts.map +1 -0
  137. package/dist/providers/CliSupport.js +62 -0
  138. package/dist/providers/CliSupport.js.map +1 -0
  139. package/dist/providers/CodexConnector.d.ts +12 -0
  140. package/dist/providers/CodexConnector.d.ts.map +1 -0
  141. package/dist/providers/CodexConnector.js +175 -0
  142. package/dist/providers/CodexConnector.js.map +1 -0
  143. package/dist/providers/ConnectorFactories.d.ts +15 -0
  144. package/dist/providers/ConnectorFactories.d.ts.map +1 -0
  145. package/dist/providers/ConnectorFactories.js +74 -0
  146. package/dist/providers/ConnectorFactories.js.map +1 -0
  147. package/dist/providers/CopilotConnector.d.ts +6 -0
  148. package/dist/providers/CopilotConnector.d.ts.map +1 -0
  149. package/dist/providers/CopilotConnector.js +35 -0
  150. package/dist/providers/CopilotConnector.js.map +1 -0
  151. package/dist/providers/CursorConnector.d.ts +8 -0
  152. package/dist/providers/CursorConnector.d.ts.map +1 -0
  153. package/dist/providers/CursorConnector.js +82 -0
  154. package/dist/providers/CursorConnector.js.map +1 -0
  155. package/dist/providers/GeminiApiProvider.d.ts +9 -0
  156. package/dist/providers/GeminiApiProvider.d.ts.map +1 -0
  157. package/dist/providers/GeminiApiProvider.js +181 -0
  158. package/dist/providers/GeminiApiProvider.js.map +1 -0
  159. package/dist/providers/GeminiCliProvider.d.ts +106 -0
  160. package/dist/providers/GeminiCliProvider.d.ts.map +1 -0
  161. package/dist/providers/GeminiCliProvider.js +596 -0
  162. package/dist/providers/GeminiCliProvider.js.map +1 -0
  163. package/dist/providers/GeminiModels.d.ts +92 -0
  164. package/dist/providers/GeminiModels.d.ts.map +1 -0
  165. package/dist/providers/GeminiModels.js +80 -0
  166. package/dist/providers/GeminiModels.js.map +1 -0
  167. package/dist/providers/GrokCliConnector.d.ts +8 -0
  168. package/dist/providers/GrokCliConnector.d.ts.map +1 -0
  169. package/dist/providers/GrokCliConnector.js +82 -0
  170. package/dist/providers/GrokCliConnector.js.map +1 -0
  171. package/dist/providers/LmStudioModels.d.ts +114 -0
  172. package/dist/providers/LmStudioModels.d.ts.map +1 -0
  173. package/dist/providers/LmStudioModels.js +102 -0
  174. package/dist/providers/LmStudioModels.js.map +1 -0
  175. package/dist/providers/LmStudioProvider.d.ts +13 -0
  176. package/dist/providers/LmStudioProvider.d.ts.map +1 -0
  177. package/dist/providers/LmStudioProvider.js +158 -0
  178. package/dist/providers/LmStudioProvider.js.map +1 -0
  179. package/dist/providers/MockProvider.d.ts +6 -0
  180. package/dist/providers/MockProvider.d.ts.map +1 -0
  181. package/dist/providers/MockProvider.js +271 -0
  182. package/dist/providers/MockProvider.js.map +1 -0
  183. package/dist/providers/OllamaModels.d.ts +68 -0
  184. package/dist/providers/OllamaModels.d.ts.map +1 -0
  185. package/dist/providers/OllamaModels.js +59 -0
  186. package/dist/providers/OllamaModels.js.map +1 -0
  187. package/dist/providers/OllamaProvider.d.ts +7 -0
  188. package/dist/providers/OllamaProvider.d.ts.map +1 -0
  189. package/dist/providers/OllamaProvider.js +134 -0
  190. package/dist/providers/OllamaProvider.js.map +1 -0
  191. package/dist/providers/OpenAIModels.d.ts +139 -0
  192. package/dist/providers/OpenAIModels.d.ts.map +1 -0
  193. package/dist/providers/OpenAIModels.js +123 -0
  194. package/dist/providers/OpenAIModels.js.map +1 -0
  195. package/dist/providers/OpenAIProvider.d.ts +9 -0
  196. package/dist/providers/OpenAIProvider.d.ts.map +1 -0
  197. package/dist/providers/OpenAIProvider.js +185 -0
  198. package/dist/providers/OpenAIProvider.js.map +1 -0
  199. package/dist/providers/OpenCodeCliConnector.d.ts +8 -0
  200. package/dist/providers/OpenCodeCliConnector.d.ts.map +1 -0
  201. package/dist/providers/OpenCodeCliConnector.js +93 -0
  202. package/dist/providers/OpenCodeCliConnector.js.map +1 -0
  203. package/dist/providers/OpenCodeModels.d.ts +61 -0
  204. package/dist/providers/OpenCodeModels.d.ts.map +1 -0
  205. package/dist/providers/OpenCodeModels.js +53 -0
  206. package/dist/providers/OpenCodeModels.js.map +1 -0
  207. package/dist/providers/OpenCodeProvider.d.ts +10 -0
  208. package/dist/providers/OpenCodeProvider.d.ts.map +1 -0
  209. package/dist/providers/OpenCodeProvider.js +154 -0
  210. package/dist/providers/OpenCodeProvider.js.map +1 -0
  211. package/dist/providers/PiConnector.d.ts +8 -0
  212. package/dist/providers/PiConnector.d.ts.map +1 -0
  213. package/dist/providers/PiConnector.js +99 -0
  214. package/dist/providers/PiConnector.js.map +1 -0
  215. package/dist/tools/Tool.d.ts +83 -0
  216. package/dist/tools/Tool.d.ts.map +1 -0
  217. package/dist/tools/Tool.js +278 -0
  218. package/dist/tools/Tool.js.map +1 -0
  219. package/dist/tools/ToolCallingExecutor.d.ts +18 -0
  220. package/dist/tools/ToolCallingExecutor.d.ts.map +1 -0
  221. package/dist/tools/ToolCallingExecutor.js +64 -0
  222. package/dist/tools/ToolCallingExecutor.js.map +1 -0
  223. package/dist/tools/ToolRegistry.d.ts +45 -0
  224. package/dist/tools/ToolRegistry.d.ts.map +1 -0
  225. package/dist/tools/ToolRegistry.js +133 -0
  226. package/dist/tools/ToolRegistry.js.map +1 -0
  227. package/package.json +105 -0
  228. package/src/.gitkeep +1 -0
  229. package/src/AgentSession.ts +69 -0
  230. package/src/Capability.ts +240 -0
  231. package/src/Connector.ts +220 -0
  232. package/src/ConnectorConfig.ts +146 -0
  233. package/src/ConnectorRegistry.ts +184 -0
  234. package/src/ContextManagement.ts +372 -0
  235. package/src/Conversation.ts +21 -0
  236. package/src/Errors.ts +87 -0
  237. package/src/HttpClient.ts +202 -0
  238. package/src/LlmService.ts +45 -0
  239. package/src/Models.ts +250 -0
  240. package/src/ProcessExecutor.ts +157 -0
  241. package/src/RateLimiter.ts +238 -0
  242. package/src/Streaming.ts +164 -0
  243. package/src/StructuredOutput.ts +138 -0
  244. package/src/TemporaryFiles.ts +51 -0
  245. package/src/UsageLimits.ts +242 -0
  246. package/src/eval/Checks.ts +68 -0
  247. package/src/eval/Eval.ts +112 -0
  248. package/src/eval/EvalSuite.ts +63 -0
  249. package/src/eval/Evaluator.ts +31 -0
  250. package/src/eval/Judge.ts +92 -0
  251. package/src/observability/MeteredLlmService.ts +156 -0
  252. package/src/observability/Metrics.ts +195 -0
  253. package/src/observability/Redaction.ts +55 -0
  254. package/src/observability/StreamRecorder.ts +32 -0
  255. package/src/observability/StructuredLogger.ts +62 -0
  256. package/src/observability/Tracing.ts +141 -0
  257. package/src/providers/AnthropicModels.ts +96 -0
  258. package/src/providers/AnthropicProvider.ts +320 -0
  259. package/src/providers/AntigravityConnector.ts +77 -0
  260. package/src/providers/ClaudeAgentSession.ts +226 -0
  261. package/src/providers/ClaudeCliConnector.ts +201 -0
  262. package/src/providers/CliSupport.ts +100 -0
  263. package/src/providers/CodexConnector.ts +251 -0
  264. package/src/providers/ConnectorFactories.ts +142 -0
  265. package/src/providers/CopilotConnector.ts +47 -0
  266. package/src/providers/CursorConnector.ts +120 -0
  267. package/src/providers/GeminiApiProvider.ts +337 -0
  268. package/src/providers/GeminiCliProvider.ts +793 -0
  269. package/src/providers/GeminiModels.ts +97 -0
  270. package/src/providers/GrokCliConnector.ts +117 -0
  271. package/src/providers/LmStudioModels.ts +117 -0
  272. package/src/providers/LmStudioProvider.ts +260 -0
  273. package/src/providers/MockProvider.ts +322 -0
  274. package/src/providers/OllamaModels.ts +64 -0
  275. package/src/providers/OllamaProvider.ts +236 -0
  276. package/src/providers/OpenAIModels.ts +152 -0
  277. package/src/providers/OpenAIProvider.ts +331 -0
  278. package/src/providers/OpenCodeCliConnector.ts +135 -0
  279. package/src/providers/OpenCodeModels.ts +60 -0
  280. package/src/providers/OpenCodeProvider.ts +278 -0
  281. package/src/providers/PiConnector.ts +142 -0
  282. package/src/tools/Tool.ts +379 -0
  283. package/src/tools/ToolCallingExecutor.ts +106 -0
  284. package/src/tools/ToolRegistry.ts +224 -0
@@ -0,0 +1,96 @@
1
+ import * as Schema from "effect/Schema"
2
+ import { JsonSchema } from "../Models.ts"
3
+
4
+ export class AnthropicMessage extends Schema.Class<AnthropicMessage>("AnthropicMessage")({
5
+ role: Schema.String,
6
+ content: Schema.String
7
+ }) {}
8
+
9
+ export class AnthropicRequest extends Schema.Class<AnthropicRequest>("AnthropicRequest")({
10
+ model: Schema.String,
11
+ max_tokens: Schema.Int,
12
+ messages: Schema.Array(AnthropicMessage),
13
+ temperature: Schema.optionalKey(Schema.Number),
14
+ system: Schema.optionalKey(Schema.String),
15
+ stream: Schema.optionalKey(Schema.Boolean)
16
+ }) {}
17
+
18
+ export class AnthropicContentBlock extends Schema.Class<AnthropicContentBlock>(
19
+ "AnthropicContentBlock"
20
+ )({
21
+ type: Schema.String,
22
+ text: Schema.optionalKey(Schema.NullOr(Schema.String))
23
+ }) {}
24
+
25
+ export class AnthropicUsage extends Schema.Class<AnthropicUsage>("AnthropicUsage")({
26
+ input_tokens: Schema.optionalKey(Schema.Int),
27
+ output_tokens: Schema.optionalKey(Schema.Int)
28
+ }) {}
29
+
30
+ export class AnthropicResponse extends Schema.Class<AnthropicResponse>("AnthropicResponse")({
31
+ id: Schema.optionalKey(Schema.String),
32
+ content: Schema.Array(AnthropicContentBlock),
33
+ model: Schema.optionalKey(Schema.String),
34
+ usage: Schema.optionalKey(AnthropicUsage),
35
+ stop_reason: Schema.optionalKey(Schema.NullOr(Schema.String))
36
+ }) {}
37
+
38
+ export class AnthropicToolInputSchema extends Schema.Class<AnthropicToolInputSchema>(
39
+ "AnthropicToolInputSchema"
40
+ )({
41
+ type: Schema.String,
42
+ properties: JsonSchema,
43
+ required: Schema.optionalKey(Schema.Array(Schema.String))
44
+ }) {}
45
+
46
+ export class AnthropicTool extends Schema.Class<AnthropicTool>("AnthropicTool")({
47
+ name: Schema.String,
48
+ description: Schema.String,
49
+ input_schema: AnthropicToolInputSchema
50
+ }) {}
51
+
52
+ export class AnthropicContentBlockFull extends Schema.Class<AnthropicContentBlockFull>(
53
+ "AnthropicContentBlockFull"
54
+ )({
55
+ type: Schema.String,
56
+ text: Schema.optionalKey(Schema.NullOr(Schema.String)),
57
+ id: Schema.optionalKey(Schema.String),
58
+ name: Schema.optionalKey(Schema.String),
59
+ input: Schema.optionalKey(Schema.Json)
60
+ }) {}
61
+
62
+ export class AnthropicRequestWithTools extends Schema.Class<AnthropicRequestWithTools>(
63
+ "AnthropicRequestWithTools"
64
+ )({
65
+ model: Schema.String,
66
+ max_tokens: Schema.Int,
67
+ messages: Schema.Array(AnthropicMessage),
68
+ tools: Schema.Array(AnthropicTool),
69
+ temperature: Schema.optionalKey(Schema.Number),
70
+ system: Schema.optionalKey(Schema.String)
71
+ }) {}
72
+
73
+ export class AnthropicResponseWithTools extends Schema.Class<AnthropicResponseWithTools>(
74
+ "AnthropicResponseWithTools"
75
+ )({
76
+ id: Schema.optionalKey(Schema.String),
77
+ content: Schema.Array(AnthropicContentBlockFull),
78
+ model: Schema.optionalKey(Schema.String),
79
+ usage: Schema.optionalKey(AnthropicUsage),
80
+ stop_reason: Schema.optionalKey(Schema.NullOr(Schema.String))
81
+ }) {}
82
+
83
+ export class AnthropicStreamChunkDelta extends Schema.Class<AnthropicStreamChunkDelta>(
84
+ "AnthropicStreamChunkDelta"
85
+ )({
86
+ type: Schema.optionalKey(Schema.String),
87
+ text: Schema.optionalKey(Schema.NullOr(Schema.String)),
88
+ stop_reason: Schema.optionalKey(Schema.NullOr(Schema.String))
89
+ }) {}
90
+
91
+ export class AnthropicStreamChunk extends Schema.Class<AnthropicStreamChunk>(
92
+ "AnthropicStreamChunk"
93
+ )({
94
+ type: Schema.String,
95
+ delta: Schema.optionalKey(AnthropicStreamChunkDelta)
96
+ }) {}
@@ -0,0 +1,320 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as Redacted from "effect/Redacted"
3
+ import * as Schema from "effect/Schema"
4
+ import * as Stream from "effect/Stream"
5
+ import { makeApiConnector, type ApiConnectorShape } from "../Connector.ts"
6
+ import { AuthenticationError, ConfigError, ParseError, type LlmError } from "../Errors.ts"
7
+ import type { HttpClientShape } from "../HttpClient.ts"
8
+ import type { StructuredResult } from "../LlmService.ts"
9
+ import {
10
+ ConnectorIds,
11
+ LlmChunk,
12
+ ToolCall,
13
+ ToolCallResponse,
14
+ type JsonSchema,
15
+ type LlmConfig,
16
+ type Message,
17
+ type ToolDefinition
18
+ } from "../Models.ts"
19
+ import { collect } from "../Streaming.ts"
20
+ import { parseFromText } from "../StructuredOutput.ts"
21
+ import type { AnthropicContentBlockFull } from "./AnthropicModels.ts"
22
+ import {
23
+ AnthropicMessage,
24
+ AnthropicRequest,
25
+ AnthropicRequestWithTools,
26
+ AnthropicResponse,
27
+ AnthropicResponseWithTools,
28
+ AnthropicStreamChunk,
29
+ AnthropicTool,
30
+ AnthropicToolInputSchema
31
+ } from "./AnthropicModels.ts"
32
+
33
+ interface AnthropicRequiredConfig {
34
+ readonly baseUrl: string
35
+ readonly apiKey: string
36
+ }
37
+
38
+ const normalizedBaseUrl = (baseUrl: string): string => baseUrl.replace(/\/+$/, "")
39
+
40
+ const decodeResponse = (raw: string): Effect.Effect<AnthropicResponse, ParseError> =>
41
+ Schema.decodeUnknownEffect(Schema.fromJsonString(AnthropicResponse))(raw).pipe(
42
+ Effect.mapError((error) =>
43
+ ParseError.make({
44
+ message: `Failed to decode Anthropic response: ${String(error)}`,
45
+ raw
46
+ })
47
+ )
48
+ )
49
+
50
+ const decodeToolResponse = (raw: string): Effect.Effect<AnthropicResponseWithTools, ParseError> =>
51
+ Schema.decodeUnknownEffect(Schema.fromJsonString(AnthropicResponseWithTools))(raw).pipe(
52
+ Effect.mapError((error) =>
53
+ ParseError.make({
54
+ message: `Failed to decode Anthropic tool response: ${String(error)}`,
55
+ raw
56
+ })
57
+ )
58
+ )
59
+
60
+ const decodeStreamChunk = (raw: string): Effect.Effect<AnthropicStreamChunk, ParseError> =>
61
+ Schema.decodeUnknownEffect(Schema.fromJsonString(AnthropicStreamChunk))(raw).pipe(
62
+ Effect.mapError((error) =>
63
+ ParseError.make({
64
+ message: `Failed to parse Anthropic stream chunk: ${String(error)}`,
65
+ raw
66
+ })
67
+ )
68
+ )
69
+
70
+ export interface AnthropicHistory {
71
+ readonly messages: ReadonlyArray<AnthropicMessage>
72
+ readonly system: string | undefined
73
+ }
74
+
75
+ export const anthropicHistory = (messages: ReadonlyArray<Message>): AnthropicHistory => ({
76
+ system: messages.find((message) => message.role === "System")?.content,
77
+ messages: messages
78
+ .filter((message) => message.role !== "System")
79
+ .map((message) =>
80
+ AnthropicMessage.make({
81
+ role: message.role === "Assistant" ? "assistant" : "user",
82
+ content: message.content
83
+ })
84
+ )
85
+ })
86
+
87
+ export const buildAnthropicRequest = (
88
+ config: LlmConfig,
89
+ messages: ReadonlyArray<AnthropicMessage>,
90
+ stream: boolean,
91
+ system?: string
92
+ ): AnthropicRequest =>
93
+ AnthropicRequest.make({
94
+ model: config.model,
95
+ max_tokens: config.maxTokens ?? 4096,
96
+ messages,
97
+ stream,
98
+ ...(config.temperature === undefined ? {} : { temperature: config.temperature }),
99
+ ...(system === undefined ? {} : { system })
100
+ })
101
+
102
+ export const buildAnthropicToolRequest = (
103
+ config: LlmConfig,
104
+ prompt: string,
105
+ tools: ReadonlyArray<ToolDefinition>
106
+ ): AnthropicRequestWithTools =>
107
+ AnthropicRequestWithTools.make({
108
+ model: config.model,
109
+ max_tokens: config.maxTokens ?? 4096,
110
+ messages: [
111
+ AnthropicMessage.make({
112
+ role: "user",
113
+ content: prompt
114
+ })
115
+ ],
116
+ tools: tools.map((tool) =>
117
+ AnthropicTool.make({
118
+ name: tool.name,
119
+ description: tool.description,
120
+ input_schema: AnthropicToolInputSchema.make({
121
+ type: "object",
122
+ properties: tool.parameters
123
+ })
124
+ })
125
+ ),
126
+ ...(config.temperature === undefined ? {} : { temperature: config.temperature })
127
+ })
128
+
129
+ const contentFromResponse = (
130
+ response: AnthropicResponse,
131
+ raw: string
132
+ ): Effect.Effect<string, ParseError> => {
133
+ const content = response.content[0]?.text?.trim()
134
+ return content === undefined || content === null || content.length === 0
135
+ ? Effect.fail(
136
+ ParseError.make({
137
+ message: "Anthropic response missing content[0].text",
138
+ raw
139
+ })
140
+ )
141
+ : Effect.succeed(content)
142
+ }
143
+
144
+ const jsonString = (value: typeof Schema.Json.Type): string => JSON.stringify(value) ?? "{}"
145
+
146
+ export const makeAnthropicProvider = (
147
+ config: LlmConfig,
148
+ httpClient: HttpClientShape
149
+ ): ApiConnectorShape => {
150
+ const requiredConfig: Effect.Effect<AnthropicRequiredConfig, LlmError> =
151
+ config.baseUrl === undefined
152
+ ? Effect.fail(
153
+ ConfigError.make({
154
+ message: "Missing baseUrl for Anthropic provider"
155
+ })
156
+ )
157
+ : config.apiKey === undefined
158
+ ? Effect.fail(
159
+ AuthenticationError.make({
160
+ message:
161
+ "Missing API key for Anthropic provider (set ANTHROPIC_API_KEY or pass apiKey in the connector config)"
162
+ })
163
+ )
164
+ : Effect.succeed({
165
+ baseUrl: normalizedBaseUrl(config.baseUrl),
166
+ apiKey: Redacted.value(config.apiKey)
167
+ })
168
+
169
+ const authHeaders = (apiKey: string): Readonly<Record<string, string>> => ({
170
+ "x-api-key": apiKey,
171
+ "anthropic-version": "2023-06-01"
172
+ })
173
+
174
+ const executeRequest = (
175
+ messages: ReadonlyArray<AnthropicMessage>,
176
+ system?: string
177
+ ): Effect.Effect<readonly [response: AnthropicResponse, raw: string], LlmError> =>
178
+ Effect.gen(function* () {
179
+ const { apiKey, baseUrl } = yield* requiredConfig
180
+ const request = buildAnthropicRequest(config, messages, false, system)
181
+ const raw = yield* httpClient.postJson(
182
+ `${baseUrl}/messages`,
183
+ JSON.stringify(request),
184
+ authHeaders(apiKey),
185
+ config.timeout
186
+ )
187
+ const response = yield* decodeResponse(raw)
188
+ return [response, raw]
189
+ })
190
+
191
+ const executeStreamRequest = (
192
+ messages: ReadonlyArray<AnthropicMessage>,
193
+ system?: string
194
+ ): Stream.Stream<LlmChunk, LlmError> =>
195
+ Stream.unwrap(
196
+ Effect.map(requiredConfig, ({ apiKey, baseUrl }) => {
197
+ const request = buildAnthropicRequest(config, messages, true, system)
198
+ return httpClient
199
+ .postJsonStreamSSE(
200
+ `${baseUrl}/messages`,
201
+ JSON.stringify(request),
202
+ authHeaders(apiKey),
203
+ config.timeout
204
+ )
205
+ .pipe(
206
+ Stream.mapEffect(decodeStreamChunk),
207
+ Stream.flatMap((chunk) => {
208
+ if (chunk.type === "content_block_delta") {
209
+ const delta = chunk.delta?.text ?? ""
210
+ return delta.length === 0
211
+ ? Stream.empty
212
+ : Stream.succeed(
213
+ LlmChunk.make({
214
+ delta,
215
+ metadata: {
216
+ provider: "anthropic",
217
+ model: config.model
218
+ }
219
+ })
220
+ )
221
+ }
222
+ const finishReason =
223
+ chunk.type === "message_delta" ? (chunk.delta?.stop_reason ?? undefined) : undefined
224
+ return finishReason === undefined
225
+ ? Stream.empty
226
+ : Stream.succeed(
227
+ LlmChunk.make({
228
+ delta: "",
229
+ finishReason,
230
+ metadata: {
231
+ provider: "anthropic",
232
+ model: config.model
233
+ }
234
+ })
235
+ )
236
+ })
237
+ )
238
+ })
239
+ )
240
+
241
+ const executeStructuredWithUsage = <A, E, RD, RE>(
242
+ prompt: string,
243
+ schema: Schema.ConstraintCodec<A, E, RD, RE>,
244
+ jsonSchema: JsonSchema
245
+ ): Effect.Effect<StructuredResult<A>, LlmError, RD> =>
246
+ Effect.gen(function* () {
247
+ const [response, raw] = yield* executeRequest([
248
+ AnthropicMessage.make({
249
+ role: "user",
250
+ content: `${prompt}\n\n` + "Please respond with valid JSON matching the provided schema."
251
+ })
252
+ ])
253
+ const content = yield* contentFromResponse(response, raw)
254
+ const value = yield* parseFromText(content, schema, jsonSchema)
255
+ const result: StructuredResult<A> = [value, undefined, undefined]
256
+ return result
257
+ })
258
+
259
+ const executeWithTools = (
260
+ prompt: string,
261
+ tools: ReadonlyArray<ToolDefinition>
262
+ ): Effect.Effect<ToolCallResponse, LlmError> =>
263
+ Effect.gen(function* () {
264
+ const { apiKey, baseUrl } = yield* requiredConfig
265
+ const request = buildAnthropicToolRequest(config, prompt, tools)
266
+ const raw = yield* httpClient.postJson(
267
+ `${baseUrl}/messages`,
268
+ JSON.stringify(request),
269
+ authHeaders(apiKey),
270
+ config.timeout
271
+ )
272
+ const response = yield* decodeToolResponse(raw)
273
+ const toolCalls = response.content
274
+ .filter((block) => block.type === "tool_use")
275
+ .map((block) =>
276
+ ToolCall.make({
277
+ id: block.id ?? "",
278
+ name: block.name ?? "",
279
+ arguments: block.input === undefined ? "{}" : jsonString(block.input)
280
+ })
281
+ )
282
+ const content = response.content.find(
283
+ (block): block is AnthropicContentBlockFull =>
284
+ block.type === "text" && block.text !== undefined && block.text !== null
285
+ )?.text
286
+
287
+ return ToolCallResponse.make({
288
+ toolCalls,
289
+ finishReason: response.stop_reason ?? "stop",
290
+ ...(content === undefined || content === null ? {} : { content })
291
+ })
292
+ })
293
+
294
+ const executeStream = (prompt: string): Stream.Stream<LlmChunk, LlmError> =>
295
+ executeStreamRequest([
296
+ AnthropicMessage.make({
297
+ role: "user",
298
+ content: prompt
299
+ })
300
+ ])
301
+
302
+ const isAvailable: Effect.Effect<boolean> = collect(executeStream("health check")).pipe(
303
+ Effect.match({
304
+ onFailure: () => false,
305
+ onSuccess: () => true
306
+ })
307
+ )
308
+
309
+ return makeApiConnector({
310
+ id: ConnectorIds.Anthropic,
311
+ executeStream,
312
+ executeStreamWithHistory: (messages) => {
313
+ const history = anthropicHistory(messages)
314
+ return executeStreamRequest(history.messages, history.system)
315
+ },
316
+ executeWithTools,
317
+ executeStructuredWithUsage,
318
+ isAvailable
319
+ })
320
+ }
@@ -0,0 +1,77 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as Stream from "effect/Stream"
3
+ import { makeCliConnector, type CliConnectorShape } from "../Connector.ts"
4
+ import type { CliConnectorConfig } from "../ConnectorConfig.ts"
5
+ import { ProviderError } from "../Errors.ts"
6
+ import { ConnectorIds, HealthStatus, LlmChunk } from "../Models.ts"
7
+ import type { ProcessExecutorShape } from "../ProcessExecutor.ts"
8
+ import { optionalModelArgs, sortedFlagArgs } from "./CliSupport.ts"
9
+
10
+ const healthy = HealthStatus.make({
11
+ availability: "Healthy",
12
+ authStatus: "Valid"
13
+ })
14
+
15
+ const unhealthy = HealthStatus.make({
16
+ availability: "Unhealthy",
17
+ authStatus: "Unknown"
18
+ })
19
+
20
+ export const antigravityExtraArgs = (config: CliConnectorConfig): ReadonlyArray<string> => {
21
+ const workspaceArgs = config.workingDir === undefined ? [] : ["--add-dir", config.workingDir]
22
+ const effectiveFlags = config.readOnly
23
+ ? {
24
+ ...config.flags,
25
+ mode: "plan"
26
+ }
27
+ : config.flags
28
+
29
+ return [...workspaceArgs, ...optionalModelArgs(config.model), ...sortedFlagArgs(effectiveFlags)]
30
+ }
31
+
32
+ export const buildAntigravityArgv = (
33
+ config: CliConnectorConfig,
34
+ prompt: string
35
+ ): ReadonlyArray<string> => ["agy", ...antigravityExtraArgs(config), "--print", prompt]
36
+
37
+ export const makeAntigravityConnector = (
38
+ config: CliConnectorConfig,
39
+ executor: ProcessExecutorShape
40
+ ): CliConnectorShape => {
41
+ const cwd = config.workingDir ?? "."
42
+ const healthCheck = executor.run(["agy", "--version"], cwd, {}).pipe(
43
+ Effect.map((result) => (result.exitCode === 0 ? healthy : unhealthy)),
44
+ Effect.catch(() => Effect.succeed(unhealthy))
45
+ )
46
+
47
+ const complete = Effect.fn("@llm4ts/core/providers/AntigravityConnector.complete")(function* (
48
+ prompt: string
49
+ ) {
50
+ const result = yield* executor.run(buildAntigravityArgv(config, prompt), cwd, config.envVars)
51
+ if (result.exitCode !== 0) {
52
+ const detail = [...result.stderr, ...result.stdout].join("\n")
53
+ return yield* ProviderError.make({
54
+ message: `agy exited with code ${result.exitCode}: ${detail}`
55
+ })
56
+ }
57
+ return result.stdout.join("\n")
58
+ })
59
+
60
+ const completeStream = (prompt: string) =>
61
+ Stream.concat(
62
+ executor
63
+ .runStreaming(buildAntigravityArgv(config, prompt), cwd, config.envVars)
64
+ .pipe(Stream.map((line) => LlmChunk.make({ delta: line }))),
65
+ Stream.make(LlmChunk.make({ delta: "", finishReason: "stop" }))
66
+ )
67
+
68
+ return makeCliConnector({
69
+ id: ConnectorIds.AntigravityCli,
70
+ interactionSupport: "InteractiveStdin",
71
+ buildArgv: (prompt, _context) => buildAntigravityArgv(config, prompt),
72
+ buildInteractiveArgv: (_context) => ["agy", ...antigravityExtraArgs(config)],
73
+ complete,
74
+ completeStream,
75
+ healthCheck
76
+ })
77
+ }