@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
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@llm4ts/core",
3
+ "version": "0.1.0",
4
+ "description": "Effect-native LLM contracts, providers, tools, evaluation, and observability",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "sideEffects": false,
8
+ "engines": {
9
+ "node": ">=22"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "src"
14
+ ],
15
+ "exports": {
16
+ "./AgentSession": "./dist/AgentSession.js",
17
+ "./Capability": "./dist/Capability.js",
18
+ "./Connector": "./dist/Connector.js",
19
+ "./ConnectorConfig": "./dist/ConnectorConfig.js",
20
+ "./ConnectorRegistry": "./dist/ConnectorRegistry.js",
21
+ "./ContextManagement": "./dist/ContextManagement.js",
22
+ "./Conversation": "./dist/Conversation.js",
23
+ "./Errors": "./dist/Errors.js",
24
+ "./eval/Checks": "./dist/eval/Checks.js",
25
+ "./eval/Eval": "./dist/eval/Eval.js",
26
+ "./eval/Evaluator": "./dist/eval/Evaluator.js",
27
+ "./eval/EvalSuite": "./dist/eval/EvalSuite.js",
28
+ "./eval/Judge": "./dist/eval/Judge.js",
29
+ "./HttpClient": "./dist/HttpClient.js",
30
+ "./LlmService": "./dist/LlmService.js",
31
+ "./Models": "./dist/Models.js",
32
+ "./observability/Metrics": "./dist/observability/Metrics.js",
33
+ "./observability/MeteredLlmService": "./dist/observability/MeteredLlmService.js",
34
+ "./observability/Redaction": "./dist/observability/Redaction.js",
35
+ "./observability/StreamRecorder": "./dist/observability/StreamRecorder.js",
36
+ "./observability/StructuredLogger": "./dist/observability/StructuredLogger.js",
37
+ "./observability/Tracing": "./dist/observability/Tracing.js",
38
+ "./ProcessExecutor": "./dist/ProcessExecutor.js",
39
+ "./providers/AnthropicModels": "./dist/providers/AnthropicModels.js",
40
+ "./providers/AnthropicProvider": "./dist/providers/AnthropicProvider.js",
41
+ "./providers/AntigravityConnector": "./dist/providers/AntigravityConnector.js",
42
+ "./providers/ClaudeAgentSession": "./dist/providers/ClaudeAgentSession.js",
43
+ "./providers/ClaudeCliConnector": "./dist/providers/ClaudeCliConnector.js",
44
+ "./providers/CliSupport": "./dist/providers/CliSupport.js",
45
+ "./providers/CodexConnector": "./dist/providers/CodexConnector.js",
46
+ "./providers/ConnectorFactories": "./dist/providers/ConnectorFactories.js",
47
+ "./providers/CopilotConnector": "./dist/providers/CopilotConnector.js",
48
+ "./providers/CursorConnector": "./dist/providers/CursorConnector.js",
49
+ "./providers/GeminiApiProvider": "./dist/providers/GeminiApiProvider.js",
50
+ "./providers/GeminiCliProvider": "./dist/providers/GeminiCliProvider.js",
51
+ "./providers/GeminiModels": "./dist/providers/GeminiModels.js",
52
+ "./providers/LmStudioModels": "./dist/providers/LmStudioModels.js",
53
+ "./providers/LmStudioProvider": "./dist/providers/LmStudioProvider.js",
54
+ "./providers/MockProvider": "./dist/providers/MockProvider.js",
55
+ "./providers/GrokCliConnector": "./dist/providers/GrokCliConnector.js",
56
+ "./providers/OpenAIModels": "./dist/providers/OpenAIModels.js",
57
+ "./providers/OpenAIProvider": "./dist/providers/OpenAIProvider.js",
58
+ "./providers/OpenCodeCliConnector": "./dist/providers/OpenCodeCliConnector.js",
59
+ "./providers/OllamaModels": "./dist/providers/OllamaModels.js",
60
+ "./providers/OllamaProvider": "./dist/providers/OllamaProvider.js",
61
+ "./providers/OpenCodeModels": "./dist/providers/OpenCodeModels.js",
62
+ "./providers/OpenCodeProvider": "./dist/providers/OpenCodeProvider.js",
63
+ "./providers/PiConnector": "./dist/providers/PiConnector.js",
64
+ "./RateLimiter": "./dist/RateLimiter.js",
65
+ "./Streaming": "./dist/Streaming.js",
66
+ "./StructuredOutput": "./dist/StructuredOutput.js",
67
+ "./TemporaryFiles": "./dist/TemporaryFiles.js",
68
+ "./tools/Tool": "./dist/tools/Tool.js",
69
+ "./tools/ToolCallingExecutor": "./dist/tools/ToolCallingExecutor.js",
70
+ "./tools/ToolRegistry": "./dist/tools/ToolRegistry.js",
71
+ "./UsageLimits": "./dist/UsageLimits.js",
72
+ "./package.json": "./package.json"
73
+ },
74
+ "publishConfig": {
75
+ "access": "public",
76
+ "provenance": true
77
+ },
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "git+https://github.com/riccardomerolla/llm4ts.git",
81
+ "directory": "packages/core"
82
+ },
83
+ "homepage": "https://github.com/riccardomerolla/llm4ts#readme",
84
+ "bugs": {
85
+ "url": "https://github.com/riccardomerolla/llm4ts/issues"
86
+ },
87
+ "keywords": [
88
+ "llm",
89
+ "effect",
90
+ "ai",
91
+ "agents",
92
+ "workflow",
93
+ "typescript"
94
+ ],
95
+ "peerDependencies": {
96
+ "effect": "^4.0.0-beta.102"
97
+ },
98
+ "devDependencies": {
99
+ "effect": "^4.0.0-beta.102"
100
+ },
101
+ "scripts": {
102
+ "clean": "tsc -b tsconfig.json --clean",
103
+ "test": "vitest run test"
104
+ }
105
+ }
package/src/.gitkeep ADDED
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,69 @@
1
+ import type * as Effect from "effect/Effect"
2
+ import * as Schema from "effect/Schema"
3
+ import type * as Stream from "effect/Stream"
4
+ import type { LlmError } from "./Errors.ts"
5
+ import { TokenUsage } from "./Models.ts"
6
+
7
+ export class SessionTextDelta extends Schema.TaggedClass<SessionTextDelta>()("TextDelta", {
8
+ text: Schema.String
9
+ }) {}
10
+
11
+ export class SessionToolUse extends Schema.TaggedClass<SessionToolUse>()("ToolUse", {
12
+ tool: Schema.String,
13
+ rawInput: Schema.String,
14
+ id: Schema.String
15
+ }) {}
16
+
17
+ export class SessionToolResult extends Schema.TaggedClass<SessionToolResult>()("ToolResult", {
18
+ id: Schema.String,
19
+ status: Schema.String,
20
+ content: Schema.String
21
+ }) {}
22
+
23
+ export class SessionAskUser extends Schema.TaggedClass<SessionAskUser>()("AskUser", {
24
+ question: Schema.String
25
+ }) {}
26
+
27
+ export class SessionApprovalRequest extends Schema.TaggedClass<SessionApprovalRequest>()(
28
+ "ApprovalRequest",
29
+ {
30
+ tool: Schema.String,
31
+ rawInput: Schema.String,
32
+ id: Schema.String
33
+ }
34
+ ) {}
35
+
36
+ export class SessionUsage extends Schema.TaggedClass<SessionUsage>()("Usage", {
37
+ usage: TokenUsage,
38
+ model: Schema.optionalKey(Schema.String)
39
+ }) {}
40
+
41
+ export class SessionDone extends Schema.TaggedClass<SessionDone>()("Done", {
42
+ result: Schema.String
43
+ }) {}
44
+
45
+ export const SessionEvent = Schema.Union([
46
+ SessionTextDelta,
47
+ SessionToolUse,
48
+ SessionToolResult,
49
+ SessionAskUser,
50
+ SessionApprovalRequest,
51
+ SessionUsage,
52
+ SessionDone
53
+ ])
54
+ export type SessionEvent = typeof SessionEvent.Type
55
+
56
+ export class SessionResult extends Schema.Class<SessionResult>("SessionResult")({
57
+ text: Schema.String,
58
+ usage: Schema.optionalKey(TokenUsage),
59
+ model: Schema.optionalKey(Schema.String)
60
+ }) {}
61
+
62
+ export interface AgentSessionShape {
63
+ readonly events: Stream.Stream<SessionEvent, LlmError>
64
+ readonly sendUserMessage: (text: string) => Effect.Effect<void, LlmError>
65
+ readonly respondToAsk: (answer: string) => Effect.Effect<void, LlmError>
66
+ readonly respondToApproval: (id: string, approved: boolean) => Effect.Effect<void, LlmError>
67
+ readonly awaitResult: Effect.Effect<SessionResult, LlmError>
68
+ readonly cancel: Effect.Effect<void>
69
+ }
@@ -0,0 +1,240 @@
1
+ import * as Context from "effect/Context"
2
+ import * as Effect from "effect/Effect"
3
+ import * as Schema from "effect/Schema"
4
+
5
+ export class GitRead extends Schema.TaggedClass<GitRead>()("GitRead", {}) {}
6
+ export class GitWrite extends Schema.TaggedClass<GitWrite>()("GitWrite", {}) {}
7
+ export class GitPush extends Schema.TaggedClass<GitPush>()("GitPush", {}) {}
8
+ export class GhRead extends Schema.TaggedClass<GhRead>()("GhRead", {}) {}
9
+ export class GhWrite extends Schema.TaggedClass<GhWrite>()("GhWrite", {}) {}
10
+ export class AdoRead extends Schema.TaggedClass<AdoRead>()("AdoRead", {}) {}
11
+ export class AdoWrite extends Schema.TaggedClass<AdoWrite>()("AdoWrite", {}) {}
12
+ export class Exec extends Schema.TaggedClass<Exec>()("Exec", {
13
+ command: Schema.String
14
+ }) {}
15
+ export class UseCoder extends Schema.TaggedClass<UseCoder>()("UseCoder", {}) {}
16
+ export class UseReasoning extends Schema.TaggedClass<UseReasoning>()("UseReasoning", {}) {}
17
+ export class Declassify extends Schema.TaggedClass<Declassify>()("Declassify", {}) {}
18
+
19
+ export const Capability = Schema.Union([
20
+ GitRead,
21
+ GitWrite,
22
+ GitPush,
23
+ GhRead,
24
+ GhWrite,
25
+ AdoRead,
26
+ AdoWrite,
27
+ Exec,
28
+ UseCoder,
29
+ UseReasoning,
30
+ Declassify
31
+ ])
32
+ export type Capability = typeof Capability.Type
33
+
34
+ export const Capabilities = Object.freeze({
35
+ Schema: Capability,
36
+ GitRead: new GitRead(),
37
+ GitWrite: new GitWrite(),
38
+ GitPush: new GitPush(),
39
+ GhRead: new GhRead(),
40
+ GhWrite: new GhWrite(),
41
+ AdoRead: new AdoRead(),
42
+ AdoWrite: new AdoWrite(),
43
+ Exec: (command: string): Exec => new Exec({ command }),
44
+ UseCoder: new UseCoder(),
45
+ UseReasoning: new UseReasoning(),
46
+ Declassify: new Declassify()
47
+ })
48
+
49
+ export const GrantLevel = Schema.Literals(["None", "Read", "Write", "Push"])
50
+ export type GrantLevel = typeof GrantLevel.Type
51
+
52
+ const levelRank = (level: GrantLevel): number => {
53
+ switch (level) {
54
+ case "None":
55
+ return 0
56
+ case "Read":
57
+ return 1
58
+ case "Write":
59
+ return 2
60
+ case "Push":
61
+ return 3
62
+ }
63
+ }
64
+
65
+ const minLevel = (first: GrantLevel, second: GrantLevel): GrantLevel =>
66
+ levelRank(first) <= levelRank(second) ? first : second
67
+
68
+ const maxLevel = (first: GrantLevel, second: GrantLevel): GrantLevel =>
69
+ levelRank(first) >= levelRank(second) ? first : second
70
+
71
+ export class ExecDenied extends Schema.TaggedClass<ExecDenied>()("Denied", {}) {}
72
+ export class ExecAllow extends Schema.TaggedClass<ExecAllow>()("Allow", {
73
+ commands: Schema.ReadonlySet(Schema.String)
74
+ }) {}
75
+ export class ExecAll extends Schema.TaggedClass<ExecAll>()("All", {}) {}
76
+
77
+ export const ExecGrant = Schema.Union([ExecDenied, ExecAllow, ExecAll])
78
+ export type ExecGrant = typeof ExecGrant.Type
79
+
80
+ export const ExecGrants = Object.freeze({
81
+ Denied: new ExecDenied(),
82
+ All: new ExecAll()
83
+ })
84
+
85
+ export const allowExec = (commands: Iterable<string>): ExecAllow =>
86
+ new ExecAllow({ commands: new Set(commands) })
87
+
88
+ const intersectExec = (first: ExecGrant, second: ExecGrant): ExecGrant => {
89
+ if (first._tag === "Denied" || second._tag === "Denied") {
90
+ return ExecGrants.Denied
91
+ }
92
+ if (first._tag === "All") {
93
+ return second
94
+ }
95
+ if (second._tag === "All") {
96
+ return first
97
+ }
98
+ return allowExec([...first.commands].filter((command) => second.commands.has(command)))
99
+ }
100
+
101
+ const unionExec = (first: ExecGrant, second: ExecGrant): ExecGrant => {
102
+ if (first._tag === "All" || second._tag === "All") {
103
+ return ExecGrants.All
104
+ }
105
+ if (first._tag === "Denied") {
106
+ return second
107
+ }
108
+ if (second._tag === "Denied") {
109
+ return first
110
+ }
111
+ return allowExec(new Set([...first.commands, ...second.commands]))
112
+ }
113
+
114
+ export class Grants extends Schema.Class<Grants>("Grants")({
115
+ git: GrantLevel,
116
+ gh: GrantLevel,
117
+ ado: GrantLevel,
118
+ exec: ExecGrant,
119
+ coder: Schema.Boolean,
120
+ reasoning: Schema.Boolean,
121
+ declassify: Schema.Boolean
122
+ }) {}
123
+
124
+ export const allGrants = new Grants({
125
+ git: "Push",
126
+ gh: "Write",
127
+ ado: "Write",
128
+ exec: ExecGrants.All,
129
+ coder: true,
130
+ reasoning: true,
131
+ declassify: true
132
+ })
133
+
134
+ export const noneGrants = new Grants({
135
+ git: "None",
136
+ gh: "None",
137
+ ado: "None",
138
+ exec: ExecGrants.Denied,
139
+ coder: false,
140
+ reasoning: false,
141
+ declassify: false
142
+ })
143
+
144
+ export const intersectGrants = (first: Grants, second: Grants): Grants =>
145
+ new Grants({
146
+ git: minLevel(first.git, second.git),
147
+ gh: minLevel(first.gh, second.gh),
148
+ ado: minLevel(first.ado, second.ado),
149
+ exec: intersectExec(first.exec, second.exec),
150
+ coder: first.coder && second.coder,
151
+ reasoning: first.reasoning && second.reasoning,
152
+ declassify: first.declassify && second.declassify
153
+ })
154
+
155
+ export const unionGrants = (first: Grants, second: Grants): Grants =>
156
+ new Grants({
157
+ git: maxLevel(first.git, second.git),
158
+ gh: maxLevel(first.gh, second.gh),
159
+ ado: maxLevel(first.ado, second.ado),
160
+ exec: unionExec(first.exec, second.exec),
161
+ coder: first.coder || second.coder,
162
+ reasoning: first.reasoning || second.reasoning,
163
+ declassify: first.declassify || second.declassify
164
+ })
165
+
166
+ const execAllows = (grant: ExecGrant, command: string): boolean => {
167
+ switch (grant._tag) {
168
+ case "Denied":
169
+ return false
170
+ case "Allow":
171
+ return grant.commands.has(command)
172
+ case "All":
173
+ return true
174
+ }
175
+ }
176
+
177
+ export const allows = (grants: Grants, capability: Capability): boolean => {
178
+ switch (capability._tag) {
179
+ case "GitRead":
180
+ return levelRank(grants.git) >= levelRank("Read")
181
+ case "GitWrite":
182
+ return levelRank(grants.git) >= levelRank("Write")
183
+ case "GitPush":
184
+ return levelRank(grants.git) >= levelRank("Push")
185
+ case "GhRead":
186
+ return levelRank(grants.gh) >= levelRank("Read")
187
+ case "GhWrite":
188
+ return levelRank(grants.gh) >= levelRank("Write")
189
+ case "AdoRead":
190
+ return levelRank(grants.ado) >= levelRank("Read")
191
+ case "AdoWrite":
192
+ return levelRank(grants.ado) >= levelRank("Write")
193
+ case "Exec":
194
+ return execAllows(grants.exec, capability.command)
195
+ case "UseCoder":
196
+ return grants.coder
197
+ case "UseReasoning":
198
+ return grants.reasoning
199
+ case "Declassify":
200
+ return grants.declassify
201
+ }
202
+ }
203
+
204
+ const CurrentGrants = Context.Reference<Grants>("@llm4ts/core/CurrentGrants", {
205
+ defaultValue: () => allGrants
206
+ })
207
+
208
+ export const currentGrants: Effect.Effect<Grants> = Effect.map(CurrentGrants, (grants) => grants)
209
+
210
+ export const restricted =
211
+ (grants: Grants) =>
212
+ <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
213
+ Effect.flatMap(CurrentGrants, (current) =>
214
+ Effect.provideService(effect, CurrentGrants, intersectGrants(current, grants))
215
+ )
216
+
217
+ export class CapabilityDenied extends Schema.TaggedErrorClass<CapabilityDenied>()(
218
+ "CapabilityDenied",
219
+ {
220
+ required: Schema.Array(Capability),
221
+ granted: Grants
222
+ }
223
+ ) {
224
+ get message(): string {
225
+ const names = this.required.map((capability) =>
226
+ capability._tag === "Exec" ? `Exec(${capability.command})` : capability._tag
227
+ )
228
+ return `missing required capabilities: ${names.join(", ")}`
229
+ }
230
+ }
231
+
232
+ export const requireCapabilities =
233
+ (required: ReadonlyArray<Capability>) =>
234
+ <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E | CapabilityDenied, R> =>
235
+ Effect.flatMap(CurrentGrants, (granted): Effect.Effect<A, E | CapabilityDenied, R> => {
236
+ const missing = required.filter((capability) => !allows(granted, capability))
237
+ return missing.length === 0
238
+ ? effect
239
+ : Effect.fail(new CapabilityDenied({ required: missing, granted }))
240
+ })
@@ -0,0 +1,220 @@
1
+ import * as Clock from "effect/Clock"
2
+ import * as Duration from "effect/Duration"
3
+ import * as Effect from "effect/Effect"
4
+ import * as Schema from "effect/Schema"
5
+ import type * as Stream from "effect/Stream"
6
+ import { CliSandbox } from "./ConnectorConfig.ts"
7
+ import { InvalidRequestError, type LlmError } from "./Errors.ts"
8
+ import type { LlmServiceShape, StructuredResult } from "./LlmService.ts"
9
+ import {
10
+ ConnectorCapabilities,
11
+ HealthStatus,
12
+ type ConnectorId,
13
+ type ConnectorKind,
14
+ type InteractionSupport,
15
+ type JsonSchema,
16
+ type LlmChunk,
17
+ type Message,
18
+ type ToolCallResponse,
19
+ type ToolDefinition
20
+ } from "./Models.ts"
21
+ import type { ProcessExecutorShape } from "./ProcessExecutor.ts"
22
+ import { parseFromText, withSchemaHint } from "./StructuredOutput.ts"
23
+
24
+ export interface ConnectorShape extends LlmServiceShape {
25
+ readonly id: ConnectorId
26
+ readonly kind: ConnectorKind
27
+ readonly healthCheck: Effect.Effect<HealthStatus, LlmError>
28
+ readonly capabilities: ConnectorCapabilities
29
+ }
30
+
31
+ export interface ApiConnectorShape extends ConnectorShape {
32
+ readonly kind: "Api"
33
+ }
34
+
35
+ export class CliContext extends Schema.Class<CliContext>("CliContext")({
36
+ worktreePath: Schema.String,
37
+ repoPath: Schema.String,
38
+ envVars: Schema.Record(Schema.String, Schema.String).pipe(
39
+ Schema.withConstructorDefault(Effect.succeed(Object.freeze({})))
40
+ ),
41
+ sandbox: Schema.optionalKey(CliSandbox),
42
+ turnLimit: Schema.optionalKey(Schema.Int)
43
+ }) {}
44
+
45
+ export interface CliConnectorShape extends ConnectorShape {
46
+ readonly kind: "Cli"
47
+ readonly interactionSupport: InteractionSupport
48
+ readonly buildArgv: (prompt: string, context: CliContext) => ReadonlyArray<string>
49
+ readonly buildInteractiveArgv: (context: CliContext) => ReadonlyArray<string>
50
+ readonly complete: (prompt: string) => Effect.Effect<string, LlmError>
51
+ readonly completeStream: (prompt: string) => Stream.Stream<LlmChunk, LlmError>
52
+ }
53
+
54
+ export const apiConnectorCapabilities = (): ConnectorCapabilities => ConnectorCapabilities.make({})
55
+
56
+ export const timedHealthCheck = (
57
+ isAvailable: Effect.Effect<boolean>
58
+ ): Effect.Effect<HealthStatus, LlmError> =>
59
+ Effect.gen(function* () {
60
+ const startedAt = yield* Clock.currentTimeNanos
61
+ const available = yield* isAvailable
62
+ const completedAt = yield* Clock.currentTimeNanos
63
+ return HealthStatus.make({
64
+ availability: available ? "Healthy" : "Unhealthy",
65
+ authStatus: available ? "Valid" : "Invalid",
66
+ latency: Duration.nanos(completedAt - startedAt)
67
+ })
68
+ })
69
+
70
+ export interface ApiConnectorPrimitives {
71
+ readonly id: ConnectorId
72
+ readonly executeStream: (prompt: string) => Stream.Stream<LlmChunk, LlmError>
73
+ readonly executeStreamWithHistory: (
74
+ messages: ReadonlyArray<Message>
75
+ ) => Stream.Stream<LlmChunk, LlmError>
76
+ readonly executeWithTools: (
77
+ prompt: string,
78
+ tools: ReadonlyArray<ToolDefinition>
79
+ ) => Effect.Effect<ToolCallResponse, LlmError>
80
+ readonly executeStructuredWithUsage: <A, E, RD, RE>(
81
+ prompt: string,
82
+ schema: Schema.ConstraintCodec<A, E, RD, RE>,
83
+ jsonSchema: JsonSchema
84
+ ) => Effect.Effect<StructuredResult<A>, LlmError, RD>
85
+ readonly isAvailable: Effect.Effect<boolean>
86
+ readonly capabilities?: ConnectorCapabilities
87
+ }
88
+
89
+ export const makeApiConnector = (primitives: ApiConnectorPrimitives): ApiConnectorShape => {
90
+ const executeStructured = <A, E, RD, RE>(
91
+ prompt: string,
92
+ schema: Schema.ConstraintCodec<A, E, RD, RE>,
93
+ jsonSchema: JsonSchema
94
+ ): Effect.Effect<A, LlmError, RD> =>
95
+ Effect.map(
96
+ primitives.executeStructuredWithUsage(prompt, schema, jsonSchema),
97
+ ([value]) => value
98
+ )
99
+
100
+ return {
101
+ ...primitives,
102
+ kind: "Api",
103
+ capabilities: primitives.capabilities ?? apiConnectorCapabilities(),
104
+ healthCheck: timedHealthCheck(primitives.isAvailable),
105
+ executeStructured
106
+ }
107
+ }
108
+
109
+ export const cliConnectorCapabilities = (
110
+ interactionSupport: InteractionSupport
111
+ ): ConnectorCapabilities =>
112
+ ConnectorCapabilities.make({
113
+ interactiveSessions: interactionSupport === "InteractiveStdin"
114
+ })
115
+
116
+ export const flattenHistory = (messages: ReadonlyArray<Message>): string => {
117
+ const systemBlock = messages
118
+ .filter((message) => message.role === "System" && message.content.length > 0)
119
+ .map((message) => message.content)
120
+ .join("\n\n")
121
+ const turns = messages
122
+ .filter((message) => message.role !== "System")
123
+ .map((message) => `**${message.role}:** ${message.content}`)
124
+ .join("\n\n")
125
+
126
+ return `${systemBlock.length === 0 ? "" : `${systemBlock}\n\n`}${turns}`
127
+ }
128
+
129
+ export interface CliVersionProbe {
130
+ readonly executor: ProcessExecutorShape
131
+ readonly binary: string
132
+ readonly versionArgs?: ReadonlyArray<string>
133
+ readonly cwd?: string
134
+ }
135
+
136
+ const cliProbeHealthy = HealthStatus.make({ availability: "Healthy", authStatus: "Valid" })
137
+ const cliProbeUnhealthy = HealthStatus.make({ availability: "Unhealthy", authStatus: "Unknown" })
138
+
139
+ export const cliVersionProbeHealthCheck = (
140
+ probe: CliVersionProbe
141
+ ): Effect.Effect<HealthStatus, LlmError> =>
142
+ probe.executor
143
+ .run([probe.binary, ...(probe.versionArgs ?? ["--version"])], probe.cwd ?? ".", {})
144
+ .pipe(
145
+ Effect.as(cliProbeHealthy),
146
+ Effect.catch(() => Effect.succeed(cliProbeUnhealthy))
147
+ )
148
+
149
+ export interface CliConnectorPrimitives {
150
+ readonly id: ConnectorId
151
+ readonly interactionSupport: InteractionSupport
152
+ readonly buildArgv: (prompt: string, context: CliContext) => ReadonlyArray<string>
153
+ readonly buildInteractiveArgv: (context: CliContext) => ReadonlyArray<string>
154
+ readonly complete: (prompt: string) => Effect.Effect<string, LlmError>
155
+ readonly completeStream: (prompt: string) => Stream.Stream<LlmChunk, LlmError>
156
+ readonly versionProbe?: CliVersionProbe
157
+ readonly healthCheck?: Effect.Effect<HealthStatus, LlmError>
158
+ readonly isAvailable?: Effect.Effect<boolean>
159
+ readonly capabilities?: ConnectorCapabilities
160
+ }
161
+
162
+ const unsupportedTools = (
163
+ id: ConnectorId,
164
+ _prompt: string,
165
+ _tools: ReadonlyArray<ToolDefinition>
166
+ ): Effect.Effect<ToolCallResponse, LlmError> =>
167
+ Effect.fail(
168
+ InvalidRequestError.make({
169
+ message: `CLI connector ${id.value} does not support tool calling`
170
+ })
171
+ )
172
+
173
+ export const makeCliConnector = (primitives: CliConnectorPrimitives): CliConnectorShape => {
174
+ const executeStructured = <A, E, RD, RE>(
175
+ prompt: string,
176
+ schema: Schema.ConstraintCodec<A, E, RD, RE>,
177
+ jsonSchema: JsonSchema
178
+ ): Effect.Effect<A, LlmError, RD> =>
179
+ Effect.flatMap(primitives.complete(withSchemaHint(prompt, jsonSchema)), (text) =>
180
+ parseFromText(text, schema, jsonSchema)
181
+ )
182
+
183
+ const executeStructuredWithUsage = <A, E, RD, RE>(
184
+ prompt: string,
185
+ schema: Schema.ConstraintCodec<A, E, RD, RE>,
186
+ jsonSchema: JsonSchema
187
+ ): Effect.Effect<StructuredResult<A>, LlmError, RD> =>
188
+ Effect.map(executeStructured(prompt, schema, jsonSchema), (value) => [
189
+ value,
190
+ undefined,
191
+ undefined
192
+ ])
193
+
194
+ const healthCheck =
195
+ primitives.healthCheck ??
196
+ (primitives.versionProbe === undefined
197
+ ? Effect.succeed(HealthStatus.make({ availability: "Unknown", authStatus: "Unknown" }))
198
+ : cliVersionProbeHealthCheck(primitives.versionProbe))
199
+
200
+ const isAvailable =
201
+ primitives.isAvailable ??
202
+ healthCheck.pipe(
203
+ Effect.map((status) => status.availability === "Healthy"),
204
+ Effect.catch(() => Effect.succeed(false))
205
+ )
206
+
207
+ return {
208
+ ...primitives,
209
+ kind: "Cli",
210
+ capabilities:
211
+ primitives.capabilities ?? cliConnectorCapabilities(primitives.interactionSupport),
212
+ healthCheck,
213
+ isAvailable,
214
+ executeStream: primitives.completeStream,
215
+ executeStreamWithHistory: (messages) => primitives.completeStream(flattenHistory(messages)),
216
+ executeWithTools: (prompt, tools) => unsupportedTools(primitives.id, prompt, tools),
217
+ executeStructured,
218
+ executeStructuredWithUsage
219
+ }
220
+ }