@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.
- package/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/AgentSession.d.ts +66 -0
- package/dist/AgentSession.d.ts.map +1 -0
- package/dist/AgentSession.js +53 -0
- package/dist/AgentSession.js.map +1 -0
- package/dist/Capability.d.ts +101 -0
- package/dist/Capability.d.ts.map +1 -0
- package/dist/Capability.js +210 -0
- package/dist/Capability.js.map +1 -0
- package/dist/Connector.d.ts +69 -0
- package/dist/Connector.d.ts.map +1 -0
- package/dist/Connector.js +86 -0
- package/dist/Connector.js.map +1 -0
- package/dist/ConnectorConfig.d.ts +70 -0
- package/dist/ConnectorConfig.d.ts.map +1 -0
- package/dist/ConnectorConfig.js +110 -0
- package/dist/ConnectorConfig.js.map +1 -0
- package/dist/ConnectorRegistry.d.ts +28 -0
- package/dist/ConnectorRegistry.d.ts.map +1 -0
- package/dist/ConnectorRegistry.js +87 -0
- package/dist/ConnectorRegistry.js.map +1 -0
- package/dist/ContextManagement.d.ts +78 -0
- package/dist/ContextManagement.d.ts.map +1 -0
- package/dist/ContextManagement.js +221 -0
- package/dist/ContextManagement.js.map +1 -0
- package/dist/Conversation.d.ts +18 -0
- package/dist/Conversation.d.ts.map +1 -0
- package/dist/Conversation.js +17 -0
- package/dist/Conversation.js.map +1 -0
- package/dist/Errors.d.ts +64 -0
- package/dist/Errors.d.ts.map +1 -0
- package/dist/Errors.js +76 -0
- package/dist/Errors.js.map +1 -0
- package/dist/HttpClient.d.ts +43 -0
- package/dist/HttpClient.d.ts.map +1 -0
- package/dist/HttpClient.js +99 -0
- package/dist/HttpClient.js.map +1 -0
- package/dist/LlmService.d.ts +24 -0
- package/dist/LlmService.d.ts.map +1 -0
- package/dist/LlmService.js +4 -0
- package/dist/LlmService.js.map +1 -0
- package/dist/Models.d.ts +138 -0
- package/dist/Models.d.ts.map +1 -0
- package/dist/Models.js +209 -0
- package/dist/Models.js.map +1 -0
- package/dist/ProcessExecutor.d.ts +57 -0
- package/dist/ProcessExecutor.d.ts.map +1 -0
- package/dist/ProcessExecutor.js +71 -0
- package/dist/ProcessExecutor.js.map +1 -0
- package/dist/RateLimiter.d.ts +44 -0
- package/dist/RateLimiter.d.ts.map +1 -0
- package/dist/RateLimiter.js +155 -0
- package/dist/RateLimiter.js.map +1 -0
- package/dist/Streaming.d.ts +17 -0
- package/dist/Streaming.d.ts.map +1 -0
- package/dist/Streaming.js +65 -0
- package/dist/Streaming.js.map +1 -0
- package/dist/StructuredOutput.d.ts +10 -0
- package/dist/StructuredOutput.d.ts.map +1 -0
- package/dist/StructuredOutput.js +97 -0
- package/dist/StructuredOutput.js.map +1 -0
- package/dist/TemporaryFiles.d.ts +20 -0
- package/dist/TemporaryFiles.d.ts.map +1 -0
- package/dist/TemporaryFiles.js +18 -0
- package/dist/TemporaryFiles.js.map +1 -0
- package/dist/UsageLimits.d.ts +5 -0
- package/dist/UsageLimits.d.ts.map +1 -0
- package/dist/UsageLimits.js +187 -0
- package/dist/UsageLimits.js.map +1 -0
- package/dist/eval/Checks.d.ts +6 -0
- package/dist/eval/Checks.d.ts.map +1 -0
- package/dist/eval/Checks.js +39 -0
- package/dist/eval/Checks.js.map +1 -0
- package/dist/eval/Eval.d.ts +57 -0
- package/dist/eval/Eval.d.ts.map +1 -0
- package/dist/eval/Eval.js +91 -0
- package/dist/eval/Eval.js.map +1 -0
- package/dist/eval/EvalSuite.d.ts +21 -0
- package/dist/eval/EvalSuite.d.ts.map +1 -0
- package/dist/eval/EvalSuite.js +30 -0
- package/dist/eval/EvalSuite.js.map +1 -0
- package/dist/eval/Evaluator.d.ts +10 -0
- package/dist/eval/Evaluator.d.ts.map +1 -0
- package/dist/eval/Evaluator.js +14 -0
- package/dist/eval/Evaluator.js.map +1 -0
- package/dist/eval/Judge.d.ts +15 -0
- package/dist/eval/Judge.d.ts.map +1 -0
- package/dist/eval/Judge.js +73 -0
- package/dist/eval/Judge.js.map +1 -0
- package/dist/observability/MeteredLlmService.d.ts +16 -0
- package/dist/observability/MeteredLlmService.d.ts.map +1 -0
- package/dist/observability/MeteredLlmService.js +66 -0
- package/dist/observability/MeteredLlmService.js.map +1 -0
- package/dist/observability/Metrics.d.ts +71 -0
- package/dist/observability/Metrics.d.ts.map +1 -0
- package/dist/observability/Metrics.js +147 -0
- package/dist/observability/Metrics.js.map +1 -0
- package/dist/observability/Redaction.d.ts +8 -0
- package/dist/observability/Redaction.d.ts.map +1 -0
- package/dist/observability/Redaction.js +38 -0
- package/dist/observability/Redaction.js.map +1 -0
- package/dist/observability/StreamRecorder.d.ts +9 -0
- package/dist/observability/StreamRecorder.d.ts.map +1 -0
- package/dist/observability/StreamRecorder.js +10 -0
- package/dist/observability/StreamRecorder.js.map +1 -0
- package/dist/observability/StructuredLogger.d.ts +31 -0
- package/dist/observability/StructuredLogger.d.ts.map +1 -0
- package/dist/observability/StructuredLogger.js +34 -0
- package/dist/observability/StructuredLogger.js.map +1 -0
- package/dist/observability/Tracing.d.ts +38 -0
- package/dist/observability/Tracing.d.ts.map +1 -0
- package/dist/observability/Tracing.js +75 -0
- package/dist/observability/Tracing.js.map +1 -0
- package/dist/providers/AnthropicModels.d.ts +95 -0
- package/dist/providers/AnthropicModels.d.ts.map +1 -0
- package/dist/providers/AnthropicModels.js +83 -0
- package/dist/providers/AnthropicModels.js.map +1 -0
- package/dist/providers/AnthropicProvider.d.ts +13 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/providers/AnthropicProvider.js +177 -0
- package/dist/providers/AnthropicProvider.js.map +1 -0
- package/dist/providers/AntigravityConnector.d.ts +7 -0
- package/dist/providers/AntigravityConnector.d.ts.map +1 -0
- package/dist/providers/AntigravityConnector.js +52 -0
- package/dist/providers/AntigravityConnector.js.map +1 -0
- package/dist/providers/ClaudeAgentSession.d.ts +11 -0
- package/dist/providers/ClaudeAgentSession.d.ts.map +1 -0
- package/dist/providers/ClaudeAgentSession.js +158 -0
- package/dist/providers/ClaudeAgentSession.js.map +1 -0
- package/dist/providers/ClaudeCliConnector.d.ts +9 -0
- package/dist/providers/ClaudeCliConnector.d.ts.map +1 -0
- package/dist/providers/ClaudeCliConnector.js +123 -0
- package/dist/providers/ClaudeCliConnector.js.map +1 -0
- package/dist/providers/CliSupport.d.ts +21 -0
- package/dist/providers/CliSupport.d.ts.map +1 -0
- package/dist/providers/CliSupport.js +62 -0
- package/dist/providers/CliSupport.js.map +1 -0
- package/dist/providers/CodexConnector.d.ts +12 -0
- package/dist/providers/CodexConnector.d.ts.map +1 -0
- package/dist/providers/CodexConnector.js +175 -0
- package/dist/providers/CodexConnector.js.map +1 -0
- package/dist/providers/ConnectorFactories.d.ts +15 -0
- package/dist/providers/ConnectorFactories.d.ts.map +1 -0
- package/dist/providers/ConnectorFactories.js +74 -0
- package/dist/providers/ConnectorFactories.js.map +1 -0
- package/dist/providers/CopilotConnector.d.ts +6 -0
- package/dist/providers/CopilotConnector.d.ts.map +1 -0
- package/dist/providers/CopilotConnector.js +35 -0
- package/dist/providers/CopilotConnector.js.map +1 -0
- package/dist/providers/CursorConnector.d.ts +8 -0
- package/dist/providers/CursorConnector.d.ts.map +1 -0
- package/dist/providers/CursorConnector.js +82 -0
- package/dist/providers/CursorConnector.js.map +1 -0
- package/dist/providers/GeminiApiProvider.d.ts +9 -0
- package/dist/providers/GeminiApiProvider.d.ts.map +1 -0
- package/dist/providers/GeminiApiProvider.js +181 -0
- package/dist/providers/GeminiApiProvider.js.map +1 -0
- package/dist/providers/GeminiCliProvider.d.ts +106 -0
- package/dist/providers/GeminiCliProvider.d.ts.map +1 -0
- package/dist/providers/GeminiCliProvider.js +596 -0
- package/dist/providers/GeminiCliProvider.js.map +1 -0
- package/dist/providers/GeminiModels.d.ts +92 -0
- package/dist/providers/GeminiModels.d.ts.map +1 -0
- package/dist/providers/GeminiModels.js +80 -0
- package/dist/providers/GeminiModels.js.map +1 -0
- package/dist/providers/GrokCliConnector.d.ts +8 -0
- package/dist/providers/GrokCliConnector.d.ts.map +1 -0
- package/dist/providers/GrokCliConnector.js +82 -0
- package/dist/providers/GrokCliConnector.js.map +1 -0
- package/dist/providers/LmStudioModels.d.ts +114 -0
- package/dist/providers/LmStudioModels.d.ts.map +1 -0
- package/dist/providers/LmStudioModels.js +102 -0
- package/dist/providers/LmStudioModels.js.map +1 -0
- package/dist/providers/LmStudioProvider.d.ts +13 -0
- package/dist/providers/LmStudioProvider.d.ts.map +1 -0
- package/dist/providers/LmStudioProvider.js +158 -0
- package/dist/providers/LmStudioProvider.js.map +1 -0
- package/dist/providers/MockProvider.d.ts +6 -0
- package/dist/providers/MockProvider.d.ts.map +1 -0
- package/dist/providers/MockProvider.js +271 -0
- package/dist/providers/MockProvider.js.map +1 -0
- package/dist/providers/OllamaModels.d.ts +68 -0
- package/dist/providers/OllamaModels.d.ts.map +1 -0
- package/dist/providers/OllamaModels.js +59 -0
- package/dist/providers/OllamaModels.js.map +1 -0
- package/dist/providers/OllamaProvider.d.ts +7 -0
- package/dist/providers/OllamaProvider.d.ts.map +1 -0
- package/dist/providers/OllamaProvider.js +134 -0
- package/dist/providers/OllamaProvider.js.map +1 -0
- package/dist/providers/OpenAIModels.d.ts +139 -0
- package/dist/providers/OpenAIModels.d.ts.map +1 -0
- package/dist/providers/OpenAIModels.js +123 -0
- package/dist/providers/OpenAIModels.js.map +1 -0
- package/dist/providers/OpenAIProvider.d.ts +9 -0
- package/dist/providers/OpenAIProvider.d.ts.map +1 -0
- package/dist/providers/OpenAIProvider.js +185 -0
- package/dist/providers/OpenAIProvider.js.map +1 -0
- package/dist/providers/OpenCodeCliConnector.d.ts +8 -0
- package/dist/providers/OpenCodeCliConnector.d.ts.map +1 -0
- package/dist/providers/OpenCodeCliConnector.js +93 -0
- package/dist/providers/OpenCodeCliConnector.js.map +1 -0
- package/dist/providers/OpenCodeModels.d.ts +61 -0
- package/dist/providers/OpenCodeModels.d.ts.map +1 -0
- package/dist/providers/OpenCodeModels.js +53 -0
- package/dist/providers/OpenCodeModels.js.map +1 -0
- package/dist/providers/OpenCodeProvider.d.ts +10 -0
- package/dist/providers/OpenCodeProvider.d.ts.map +1 -0
- package/dist/providers/OpenCodeProvider.js +154 -0
- package/dist/providers/OpenCodeProvider.js.map +1 -0
- package/dist/providers/PiConnector.d.ts +8 -0
- package/dist/providers/PiConnector.d.ts.map +1 -0
- package/dist/providers/PiConnector.js +99 -0
- package/dist/providers/PiConnector.js.map +1 -0
- package/dist/tools/Tool.d.ts +83 -0
- package/dist/tools/Tool.d.ts.map +1 -0
- package/dist/tools/Tool.js +278 -0
- package/dist/tools/Tool.js.map +1 -0
- package/dist/tools/ToolCallingExecutor.d.ts +18 -0
- package/dist/tools/ToolCallingExecutor.d.ts.map +1 -0
- package/dist/tools/ToolCallingExecutor.js +64 -0
- package/dist/tools/ToolCallingExecutor.js.map +1 -0
- package/dist/tools/ToolRegistry.d.ts +45 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -0
- package/dist/tools/ToolRegistry.js +133 -0
- package/dist/tools/ToolRegistry.js.map +1 -0
- package/package.json +105 -0
- package/src/.gitkeep +1 -0
- package/src/AgentSession.ts +69 -0
- package/src/Capability.ts +240 -0
- package/src/Connector.ts +220 -0
- package/src/ConnectorConfig.ts +146 -0
- package/src/ConnectorRegistry.ts +184 -0
- package/src/ContextManagement.ts +372 -0
- package/src/Conversation.ts +21 -0
- package/src/Errors.ts +87 -0
- package/src/HttpClient.ts +202 -0
- package/src/LlmService.ts +45 -0
- package/src/Models.ts +250 -0
- package/src/ProcessExecutor.ts +157 -0
- package/src/RateLimiter.ts +238 -0
- package/src/Streaming.ts +164 -0
- package/src/StructuredOutput.ts +138 -0
- package/src/TemporaryFiles.ts +51 -0
- package/src/UsageLimits.ts +242 -0
- package/src/eval/Checks.ts +68 -0
- package/src/eval/Eval.ts +112 -0
- package/src/eval/EvalSuite.ts +63 -0
- package/src/eval/Evaluator.ts +31 -0
- package/src/eval/Judge.ts +92 -0
- package/src/observability/MeteredLlmService.ts +156 -0
- package/src/observability/Metrics.ts +195 -0
- package/src/observability/Redaction.ts +55 -0
- package/src/observability/StreamRecorder.ts +32 -0
- package/src/observability/StructuredLogger.ts +62 -0
- package/src/observability/Tracing.ts +141 -0
- package/src/providers/AnthropicModels.ts +96 -0
- package/src/providers/AnthropicProvider.ts +320 -0
- package/src/providers/AntigravityConnector.ts +77 -0
- package/src/providers/ClaudeAgentSession.ts +226 -0
- package/src/providers/ClaudeCliConnector.ts +201 -0
- package/src/providers/CliSupport.ts +100 -0
- package/src/providers/CodexConnector.ts +251 -0
- package/src/providers/ConnectorFactories.ts +142 -0
- package/src/providers/CopilotConnector.ts +47 -0
- package/src/providers/CursorConnector.ts +120 -0
- package/src/providers/GeminiApiProvider.ts +337 -0
- package/src/providers/GeminiCliProvider.ts +793 -0
- package/src/providers/GeminiModels.ts +97 -0
- package/src/providers/GrokCliConnector.ts +117 -0
- package/src/providers/LmStudioModels.ts +117 -0
- package/src/providers/LmStudioProvider.ts +260 -0
- package/src/providers/MockProvider.ts +322 -0
- package/src/providers/OllamaModels.ts +64 -0
- package/src/providers/OllamaProvider.ts +236 -0
- package/src/providers/OpenAIModels.ts +152 -0
- package/src/providers/OpenAIProvider.ts +331 -0
- package/src/providers/OpenCodeCliConnector.ts +135 -0
- package/src/providers/OpenCodeModels.ts +60 -0
- package/src/providers/OpenCodeProvider.ts +278 -0
- package/src/providers/PiConnector.ts +142 -0
- package/src/tools/Tool.ts +379 -0
- package/src/tools/ToolCallingExecutor.ts +106 -0
- 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
|
+
})
|
package/src/Connector.ts
ADDED
|
@@ -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
|
+
}
|