@limo-labs/deity-adapter-copilot 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +285 -0
- package/dist/index.cjs +255 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +72 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +253 -0
- package/dist/index.js.map +1 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# @limo-labs/deity-adapter-copilot
|
|
2
|
+
|
|
3
|
+
GitHub Copilot SDK adapter for the Deity framework.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This adapter enables Deity agents to use GitHub Copilot's language models (GPT-4o, Claude Opus, o1, etc.) through the Copilot SDK. It implements Deity's `LLMAdapter` interface and handles the conversion between Deity's tool format and Copilot SDK's native tool calling.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Native Tool Support**: Uses Copilot SDK's built-in tool calling for reliable execution
|
|
12
|
+
- **Disposable Sessions**: Creates fresh sessions for each request, optimized for Deity's stateless design
|
|
13
|
+
- **Multiple Models**: Support for GPT-4o, Claude Opus 4.6, o1, o1-mini, and other Copilot-supported models
|
|
14
|
+
- **Tool Call Tracking**: Automatically tracks tool executions via hooks
|
|
15
|
+
- **Environment Isolation**: Blocks environment tools to ensure only registered tools are used
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @limo-labs/deity-adapter-copilot
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Peer Dependencies:**
|
|
24
|
+
- `@limo-labs/deity`: ^0.1.3-alpha.2
|
|
25
|
+
- `@github/copilot-sdk`: ^0.1.25
|
|
26
|
+
|
|
27
|
+
## Basic Usage
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { CopilotSDKAdapter } from '@limo-labs/deity-adapter-copilot';
|
|
31
|
+
import { Agent, createTool } from '@limo-labs/deity';
|
|
32
|
+
import { z } from 'zod';
|
|
33
|
+
|
|
34
|
+
// Create adapter
|
|
35
|
+
const adapter = new CopilotSDKAdapter({
|
|
36
|
+
model: 'claude-opus-4.6', // or 'gpt-4o', 'o1', etc.
|
|
37
|
+
debug: true // Enable logging
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Initialize adapter
|
|
41
|
+
await adapter.initialize();
|
|
42
|
+
|
|
43
|
+
// Define a tool
|
|
44
|
+
const searchTool = createTool({
|
|
45
|
+
name: 'search',
|
|
46
|
+
description: 'Search for information',
|
|
47
|
+
inputSchema: z.object({
|
|
48
|
+
query: z.string()
|
|
49
|
+
}),
|
|
50
|
+
execute: async (input, ctx) => {
|
|
51
|
+
// Your search implementation
|
|
52
|
+
return `Results for: ${input.query}`;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Create agent with adapter
|
|
57
|
+
const agent = new Agent({
|
|
58
|
+
name: 'research-agent',
|
|
59
|
+
systemPrompt: 'You are a helpful research assistant.',
|
|
60
|
+
tools: [searchTool],
|
|
61
|
+
llmAdapter: adapter
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Execute agent
|
|
65
|
+
const result = await agent.execute({
|
|
66
|
+
input: { topic: 'AI agents' }
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Cleanup
|
|
70
|
+
await adapter.cleanup();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Configuration Options
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
interface CopilotSDKAdapterConfig {
|
|
77
|
+
/**
|
|
78
|
+
* Model to use (default: 'gpt-4o')
|
|
79
|
+
* Options: 'gpt-4o', 'claude-opus-4.6', 'o1', 'o1-mini', etc.
|
|
80
|
+
*/
|
|
81
|
+
model?: string;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Custom Copilot CLI URL (optional)
|
|
85
|
+
* If not provided, SDK will auto-manage the CLI
|
|
86
|
+
*/
|
|
87
|
+
cliUrl?: string;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Callback for streaming response chunks (optional)
|
|
91
|
+
*/
|
|
92
|
+
onStreamChunk?: (chunk: string) => void;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Callback for reasoning/thinking chunks (optional)
|
|
96
|
+
*/
|
|
97
|
+
onReasoningChunk?: (chunk: string) => void;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Enable debug logging (default: false)
|
|
101
|
+
*/
|
|
102
|
+
debug?: boolean;
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Architecture
|
|
107
|
+
|
|
108
|
+
### Disposable Session Pattern
|
|
109
|
+
|
|
110
|
+
This adapter uses a **disposable session pattern** optimized for Deity's stateless design:
|
|
111
|
+
|
|
112
|
+
1. **Create**: A new session is created for each `generate()` call
|
|
113
|
+
2. **Use**: Session executes the request and tool calls
|
|
114
|
+
3. **Destroy**: Session is immediately destroyed in a `finally` block
|
|
115
|
+
|
|
116
|
+
**Why disposable sessions?**
|
|
117
|
+
|
|
118
|
+
- Deity uses an intelligent memory system instead of traditional chat history
|
|
119
|
+
- Retaining full chat history consumes significant context with low information density
|
|
120
|
+
- Each request should be self-contained based on dynamically reconstructed context
|
|
121
|
+
- Sessions are lightweight to create/destroy
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
async generate(messages, tools, config, ctx) {
|
|
125
|
+
const session = await this.client.createSession({...});
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
// Execute request
|
|
129
|
+
const result = await session.sendAndWait({ prompt });
|
|
130
|
+
return result;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
await session.destroy();
|
|
133
|
+
throw error;
|
|
134
|
+
} finally {
|
|
135
|
+
// Always destroy session
|
|
136
|
+
await session.destroy();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Tool Execution Model
|
|
142
|
+
|
|
143
|
+
The adapter uses Copilot SDK's native tool support:
|
|
144
|
+
|
|
145
|
+
1. **Registration**: Deity tools are converted to SDK tools using `defineTool()`
|
|
146
|
+
2. **Execution**: SDK handles the tool calling loop automatically
|
|
147
|
+
3. **Tracking**: `onPostToolUse` hook tracks tool calls for Deity compatibility
|
|
148
|
+
4. **Return**: Tool calls are marked as `_alreadyExecuted` to prevent re-execution
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// Tool conversion
|
|
152
|
+
const copilotTool = defineTool(tool.name, {
|
|
153
|
+
description: tool.description,
|
|
154
|
+
parameters: tool.inputSchema, // Zod schema (v4 has native toJSONSchema())
|
|
155
|
+
handler: async (args) => {
|
|
156
|
+
// Execute Deity tool
|
|
157
|
+
return await tool.execute(args, ctx);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Hook for tracking
|
|
162
|
+
hooks: {
|
|
163
|
+
onPostToolUse: async (input) => {
|
|
164
|
+
this.toolCallHistory.push({
|
|
165
|
+
id: `call_${Date.now()}_${Math.random()}`,
|
|
166
|
+
name: input.toolName,
|
|
167
|
+
arguments: input.toolArgs,
|
|
168
|
+
_alreadyExecuted: true // Prevent re-execution
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Environment Tool Isolation
|
|
175
|
+
|
|
176
|
+
The adapter excludes all environment tools to ensure only registered tools are used:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
excludedTools: [
|
|
180
|
+
'bash', 'shell', 'view', 'create', 'edit',
|
|
181
|
+
'web_fetch', 'sql', 'grep', 'glob', 'task',
|
|
182
|
+
// ... and more
|
|
183
|
+
]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
This prevents the LLM from calling tools you haven't explicitly registered.
|
|
187
|
+
|
|
188
|
+
## Supported Models
|
|
189
|
+
|
|
190
|
+
- `gpt-4o` (default)
|
|
191
|
+
- `claude-opus-4.6`
|
|
192
|
+
- `o1`
|
|
193
|
+
- `o1-mini`
|
|
194
|
+
- Other models supported by Copilot SDK
|
|
195
|
+
|
|
196
|
+
## Advanced Usage
|
|
197
|
+
|
|
198
|
+
### Custom CLI Management
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const adapter = new CopilotSDKAdapter({
|
|
202
|
+
cliUrl: 'http://localhost:9090', // Custom CLI server
|
|
203
|
+
model: 'gpt-4o'
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Streaming Responses
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const adapter = new CopilotSDKAdapter({
|
|
211
|
+
model: 'gpt-4o',
|
|
212
|
+
onStreamChunk: (chunk) => {
|
|
213
|
+
process.stdout.write(chunk);
|
|
214
|
+
},
|
|
215
|
+
onReasoningChunk: (chunk) => {
|
|
216
|
+
console.log('[Reasoning]', chunk);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Debug Logging
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
const adapter = new CopilotSDKAdapter({
|
|
225
|
+
debug: true // Enables detailed logging
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Validation
|
|
230
|
+
|
|
231
|
+
This adapter has been validated with:
|
|
232
|
+
|
|
233
|
+
- ✅ Multi-turn tool calling conversations
|
|
234
|
+
- ✅ Long system messages (~20k characters)
|
|
235
|
+
- ✅ Multiple tool registrations (5+ tools)
|
|
236
|
+
- ✅ Complex Zod schemas with nested objects
|
|
237
|
+
- ✅ Error handling and recovery
|
|
238
|
+
|
|
239
|
+
## Troubleshooting
|
|
240
|
+
|
|
241
|
+
### Tools not being called
|
|
242
|
+
|
|
243
|
+
1. Check that `excludedTools` includes environment tools
|
|
244
|
+
2. Verify tool schemas are valid Zod v4 schemas
|
|
245
|
+
3. Enable debug logging to see tool registration
|
|
246
|
+
|
|
247
|
+
### Session errors
|
|
248
|
+
|
|
249
|
+
1. Ensure `initialize()` is called before `generate()`
|
|
250
|
+
2. Check that CLI is accessible (if using custom cliUrl)
|
|
251
|
+
3. Verify Copilot SDK is properly installed
|
|
252
|
+
|
|
253
|
+
### Tool execution failures
|
|
254
|
+
|
|
255
|
+
1. Check that ExecutionContext is available
|
|
256
|
+
2. Verify tool handler implementation
|
|
257
|
+
3. Enable debug logging to see execution details
|
|
258
|
+
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Install dependencies
|
|
263
|
+
npm install
|
|
264
|
+
|
|
265
|
+
# Build
|
|
266
|
+
npm run build
|
|
267
|
+
|
|
268
|
+
# Type check
|
|
269
|
+
npm run type-check
|
|
270
|
+
|
|
271
|
+
# Lint
|
|
272
|
+
npm run lint
|
|
273
|
+
|
|
274
|
+
# Test
|
|
275
|
+
npm test
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
MIT
|
|
281
|
+
|
|
282
|
+
## Related
|
|
283
|
+
|
|
284
|
+
- [Deity Framework](https://github.com/limo-labs/deity)
|
|
285
|
+
- [GitHub Copilot SDK](https://github.com/github/copilot-sdk)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var copilotSdk = require('@github/copilot-sdk');
|
|
4
|
+
|
|
5
|
+
// src/adapter.ts
|
|
6
|
+
var CopilotSDKAdapter = class {
|
|
7
|
+
client;
|
|
8
|
+
model;
|
|
9
|
+
sessionCounter = 0;
|
|
10
|
+
isInitialized = false;
|
|
11
|
+
onStreamChunk;
|
|
12
|
+
currentContext;
|
|
13
|
+
debugEnabled;
|
|
14
|
+
// Track tool calls for Deity compatibility
|
|
15
|
+
toolCallHistory = [];
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.model = config.model || "gpt-4o";
|
|
18
|
+
this.onStreamChunk = config.onStreamChunk;
|
|
19
|
+
this.debugEnabled = config.debug || false;
|
|
20
|
+
this.client = new copilotSdk.CopilotClient({
|
|
21
|
+
cliUrl: config.cliUrl,
|
|
22
|
+
cliArgs: ["--disable-builtin-mcps"]
|
|
23
|
+
});
|
|
24
|
+
this.log("CopilotSDKAdapter created:", {
|
|
25
|
+
model: this.model,
|
|
26
|
+
mode: config.cliUrl ? "external-server" : "auto-managed",
|
|
27
|
+
streaming: !!this.onStreamChunk,
|
|
28
|
+
nativeToolSupport: true
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
log(...args) {
|
|
32
|
+
if (this.debugEnabled) {
|
|
33
|
+
console.log("[CopilotSDKAdapter]", ...args);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async initialize() {
|
|
37
|
+
if (this.isInitialized) {
|
|
38
|
+
this.log("Client already initialized, skipping");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.log("Starting Copilot client...");
|
|
42
|
+
await this.client.start();
|
|
43
|
+
this.isInitialized = true;
|
|
44
|
+
this.log("Copilot client started successfully");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Generate LLM response using Copilot SDK's native tool support
|
|
48
|
+
*
|
|
49
|
+
* Copilot SDK handles:
|
|
50
|
+
* - Tool definition injection
|
|
51
|
+
* - Tool call generation
|
|
52
|
+
* - Tool execution via handlers
|
|
53
|
+
* - Multi-turn tool calling loop
|
|
54
|
+
*
|
|
55
|
+
* Architecture notes:
|
|
56
|
+
* - Creates a disposable session for each call
|
|
57
|
+
* - Session is destroyed after use (in finally block)
|
|
58
|
+
* - Tool calls are tracked via onPostToolUse hook
|
|
59
|
+
* - Returns toolCalls array marked as already executed
|
|
60
|
+
*/
|
|
61
|
+
async generate(messages, tools, _config, ctx) {
|
|
62
|
+
if (!this.isInitialized) {
|
|
63
|
+
await this.initialize();
|
|
64
|
+
}
|
|
65
|
+
this.currentContext = ctx;
|
|
66
|
+
this.toolCallHistory = [];
|
|
67
|
+
const startTime = Date.now();
|
|
68
|
+
const sessionId = `deity-session-${Date.now()}-${this.sessionCounter++}`;
|
|
69
|
+
this.log("Creating disposable session:", sessionId);
|
|
70
|
+
const copilotTools = tools ? this.convertTools(tools) : void 0;
|
|
71
|
+
const toolNames = copilotTools?.map((t) => t.name) || [];
|
|
72
|
+
this.log("Session tools:", {
|
|
73
|
+
count: toolNames.length,
|
|
74
|
+
names: toolNames
|
|
75
|
+
});
|
|
76
|
+
const sessionConfig = {
|
|
77
|
+
sessionId,
|
|
78
|
+
model: this.model,
|
|
79
|
+
tools: copilotTools,
|
|
80
|
+
// Exclude ALL environment tools to ensure only registered tools are used
|
|
81
|
+
excludedTools: [
|
|
82
|
+
"bash",
|
|
83
|
+
"write_bash",
|
|
84
|
+
"read_bash",
|
|
85
|
+
"stop_bash",
|
|
86
|
+
"list_bash",
|
|
87
|
+
"shell",
|
|
88
|
+
"view",
|
|
89
|
+
"create",
|
|
90
|
+
"edit",
|
|
91
|
+
"web_fetch",
|
|
92
|
+
"report_intent",
|
|
93
|
+
"read_file",
|
|
94
|
+
"write_file",
|
|
95
|
+
"sql",
|
|
96
|
+
"read_agent",
|
|
97
|
+
"list_agents",
|
|
98
|
+
"grep",
|
|
99
|
+
"glob",
|
|
100
|
+
"task"
|
|
101
|
+
],
|
|
102
|
+
// Add hooks to track tool calls for Deity compatibility
|
|
103
|
+
hooks: {
|
|
104
|
+
onPostToolUse: (input) => {
|
|
105
|
+
const toolCall = {
|
|
106
|
+
id: `call_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
108
|
+
name: input.toolName,
|
|
109
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
110
|
+
arguments: input.toolArgs,
|
|
111
|
+
_alreadyExecuted: true,
|
|
112
|
+
// Mark as already executed by SDK
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
114
|
+
_executionResult: JSON.stringify(input.toolResult)
|
|
115
|
+
// Store result for reference
|
|
116
|
+
};
|
|
117
|
+
this.toolCallHistory.push(toolCall);
|
|
118
|
+
this.log("Tool call tracked:", {
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
120
|
+
name: input.toolName,
|
|
121
|
+
totalCalls: this.toolCallHistory.length
|
|
122
|
+
});
|
|
123
|
+
return void 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const session = await this.client.createSession(sessionConfig);
|
|
128
|
+
this.log("Session created:", sessionId);
|
|
129
|
+
try {
|
|
130
|
+
const prompt = this.messagesToPrompt(messages);
|
|
131
|
+
this.log("Sending prompt:", {
|
|
132
|
+
promptLength: prompt.length,
|
|
133
|
+
sessionId: session.sessionId,
|
|
134
|
+
toolsCount: tools?.length || 0
|
|
135
|
+
});
|
|
136
|
+
let responseContent = "";
|
|
137
|
+
try {
|
|
138
|
+
const result = await session.sendAndWait({ prompt }, 12e6);
|
|
139
|
+
if (result) {
|
|
140
|
+
responseContent = result.data.content || "";
|
|
141
|
+
this.log("Response received:", {
|
|
142
|
+
length: responseContent.length
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error("[CopilotSDKAdapter] sendAndWait error:", error.message);
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
const elapsed = Date.now() - startTime;
|
|
150
|
+
this.log(`API response received in ${elapsed}ms`);
|
|
151
|
+
if (this.toolCallHistory.length > 0) {
|
|
152
|
+
this.log(`Session executed ${this.toolCallHistory.length} tool calls`);
|
|
153
|
+
}
|
|
154
|
+
const response = {
|
|
155
|
+
content: responseContent,
|
|
156
|
+
toolCalls: this.toolCallHistory.length > 0 ? this.toolCallHistory : void 0
|
|
157
|
+
};
|
|
158
|
+
return response;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
await session.destroy();
|
|
161
|
+
throw error;
|
|
162
|
+
} finally {
|
|
163
|
+
await session.destroy();
|
|
164
|
+
this.log("Session destroyed:", sessionId);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Convert Deity Tool to Copilot SDK Tool using defineTool
|
|
169
|
+
*
|
|
170
|
+
* Uses SDK's defineTool() function which properly registers tools.
|
|
171
|
+
* Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.
|
|
172
|
+
*/
|
|
173
|
+
convertTools(deityTools) {
|
|
174
|
+
this.log("Converting Deity tools to Copilot SDK format:", {
|
|
175
|
+
count: deityTools.length,
|
|
176
|
+
names: deityTools.map((t) => t.name)
|
|
177
|
+
});
|
|
178
|
+
const converted = deityTools.map((tool) => {
|
|
179
|
+
const parameters = tool.inputSchema;
|
|
180
|
+
return copilotSdk.defineTool(tool.name, {
|
|
181
|
+
description: tool.description || `Tool: ${tool.name}`,
|
|
182
|
+
parameters,
|
|
183
|
+
handler: async (args) => {
|
|
184
|
+
this.log("Executing tool via SDK handler:", {
|
|
185
|
+
name: tool.name
|
|
186
|
+
});
|
|
187
|
+
try {
|
|
188
|
+
if (!this.currentContext) {
|
|
189
|
+
throw new Error("Execution context not available for tool handler");
|
|
190
|
+
}
|
|
191
|
+
const result = await tool.execute(args, this.currentContext);
|
|
192
|
+
this.log("Tool execution successful:", tool.name);
|
|
193
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
196
|
+
console.error("[CopilotSDKAdapter] Tool execution failed:", {
|
|
197
|
+
tool: tool.name,
|
|
198
|
+
error: errorMsg
|
|
199
|
+
});
|
|
200
|
+
return JSON.stringify({
|
|
201
|
+
success: false,
|
|
202
|
+
error: errorMsg
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
this.log("Tool conversion complete:", {
|
|
209
|
+
convertedCount: converted.length,
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
211
|
+
toolNames: converted.map((t) => t.name || "unknown")
|
|
212
|
+
});
|
|
213
|
+
return converted;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Convert Deity messages to Copilot prompt format
|
|
217
|
+
*
|
|
218
|
+
* Note: Copilot SDK uses a simple string prompt format.
|
|
219
|
+
* All message types are concatenated into a single prompt.
|
|
220
|
+
*/
|
|
221
|
+
messagesToPrompt(messages) {
|
|
222
|
+
let prompt = "";
|
|
223
|
+
for (const msg of messages) {
|
|
224
|
+
switch (msg.role) {
|
|
225
|
+
case "system":
|
|
226
|
+
prompt += msg.content + "\n\n";
|
|
227
|
+
break;
|
|
228
|
+
case "user":
|
|
229
|
+
prompt += `User: ${msg.content}
|
|
230
|
+
|
|
231
|
+
`;
|
|
232
|
+
break;
|
|
233
|
+
case "assistant":
|
|
234
|
+
prompt += `Assistant: ${msg.content}
|
|
235
|
+
|
|
236
|
+
`;
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return prompt;
|
|
241
|
+
}
|
|
242
|
+
async cleanup() {
|
|
243
|
+
if (!this.isInitialized) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
this.log("Stopping Copilot client...");
|
|
247
|
+
await this.client.stop();
|
|
248
|
+
this.isInitialized = false;
|
|
249
|
+
this.log("Copilot client stopped");
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
exports.CopilotSDKAdapter = CopilotSDKAdapter;
|
|
254
|
+
//# sourceMappingURL=index.cjs.map
|
|
255
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts"],"names":["CopilotClient","defineTool"],"mappings":"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","file":"index.cjs","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n/**\n * Copilot SDK Adapter for Deity Framework\n *\n * Uses Copilot SDK's native tool support for reliable tool calling.\n *\n * Architecture:\n * - Deity passes tools to generate()\n * - Adapter converts Deity tools to Copilot SDK tools\n * - Copilot SDK handles tool calling loop automatically\n * - Adapter returns final response with tool call information\n *\n * Session Management:\n * - Uses disposable session pattern (create → use → destroy)\n * - Each generate() call creates a fresh session\n * - Sessions are destroyed in finally block to ensure cleanup\n * - This pattern is optimized for Deity's stateless design\n */\n\nimport { CopilotClient, defineTool, type Tool as CopilotTool } from '@github/copilot-sdk';\nimport type {\n LLMAdapter,\n LLMResponse,\n Message,\n Tool,\n GenerationConfig,\n ExecutionContext,\n ToolCall,\n} from '@limo-labs/deity';\n\nexport interface CopilotSDKAdapterConfig {\n /**\n * Model to use (default: 'gpt-4o')\n * Options: 'gpt-4o', 'claude-opus-4.6', 'o1', 'o1-mini', etc.\n */\n model?: string;\n\n /**\n * Custom Copilot CLI URL (optional)\n * If not provided, SDK will auto-manage the CLI\n */\n cliUrl?: string;\n\n /**\n * Callback for streaming response chunks (optional)\n */\n onStreamChunk?: (chunk: string) => void;\n\n /**\n * Callback for reasoning/thinking chunks (optional)\n */\n onReasoningChunk?: (chunk: string) => void;\n\n /**\n * Enable debug logging (default: false)\n */\n debug?: boolean;\n}\n\nexport class CopilotSDKAdapter implements LLMAdapter {\n private client: CopilotClient;\n private model: string;\n private sessionCounter = 0;\n private isInitialized = false;\n private onStreamChunk?: (chunk: string) => void;\n private currentContext?: ExecutionContext;\n private debugEnabled: boolean;\n\n // Track tool calls for Deity compatibility\n private toolCallHistory: ToolCall[] = [];\n\n constructor(config: CopilotSDKAdapterConfig = {}) {\n this.model = config.model || 'gpt-4o';\n this.onStreamChunk = config.onStreamChunk;\n this.debugEnabled = config.debug || false;\n\n // CRITICAL FIX: Disable built-in GitHub MCP server\n // GitHub MCP server auto-activates in git repos and overrides SDK tools\n this.client = new CopilotClient({\n cliUrl: config.cliUrl,\n cliArgs: ['--disable-builtin-mcps'],\n });\n\n this.log('CopilotSDKAdapter created:', {\n model: this.model,\n mode: config.cliUrl ? 'external-server' : 'auto-managed',\n streaming: !!this.onStreamChunk,\n nativeToolSupport: true,\n });\n }\n\n private log(...args: any[]): void {\n if (this.debugEnabled) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n console.log('[CopilotSDKAdapter]', ...args);\n }\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n this.log('Client already initialized, skipping');\n return;\n }\n\n this.log('Starting Copilot client...');\n await this.client.start();\n this.isInitialized = true;\n this.log('Copilot client started successfully');\n }\n\n /**\n * Generate LLM response using Copilot SDK's native tool support\n *\n * Copilot SDK handles:\n * - Tool definition injection\n * - Tool call generation\n * - Tool execution via handlers\n * - Multi-turn tool calling loop\n *\n * Architecture notes:\n * - Creates a disposable session for each call\n * - Session is destroyed after use (in finally block)\n * - Tool calls are tracked via onPostToolUse hook\n * - Returns toolCalls array marked as already executed\n */\n async generate(\n messages: Message[],\n tools?: Tool[],\n _config?: GenerationConfig,\n ctx?: ExecutionContext\n ): Promise<LLMResponse> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n\n // Store context for tool handlers\n this.currentContext = ctx;\n\n // Reset tool call history for this generation\n this.toolCallHistory = [];\n\n const startTime = Date.now();\n\n // Disposable session pattern: create new session for each call\n const sessionId = `deity-session-${Date.now()}-${this.sessionCounter++}`;\n this.log('Creating disposable session:', sessionId);\n\n // Convert Deity tools to Copilot SDK tools\n const copilotTools = tools ? this.convertTools(tools) : undefined;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n const toolNames = copilotTools?.map((t) => (t as any).name) || [];\n\n this.log('Session tools:', {\n count: toolNames.length,\n names: toolNames,\n });\n\n // Create session with hooks to track tool calls\n const sessionConfig: any = {\n sessionId,\n model: this.model,\n tools: copilotTools,\n // Exclude ALL environment tools to ensure only registered tools are used\n excludedTools: [\n 'bash',\n 'write_bash',\n 'read_bash',\n 'stop_bash',\n 'list_bash',\n 'shell',\n 'view',\n 'create',\n 'edit',\n 'web_fetch',\n 'report_intent',\n 'read_file',\n 'write_file',\n 'sql',\n 'read_agent',\n 'list_agents',\n 'grep',\n 'glob',\n 'task',\n ],\n // Add hooks to track tool calls for Deity compatibility\n hooks: {\n onPostToolUse: (input: any) => {\n // Record tool call in history with execution metadata\n const toolCall: any = {\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n name: input.toolName,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n arguments: input.toolArgs,\n _alreadyExecuted: true, // Mark as already executed by SDK\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n _executionResult: JSON.stringify(input.toolResult), // Store result for reference\n };\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this.toolCallHistory.push(toolCall);\n\n this.log('Tool call tracked:', {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n name: input.toolName,\n totalCalls: this.toolCallHistory.length,\n });\n\n // Don't modify anything, just track\n return undefined;\n },\n },\n };\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n const session = await this.client.createSession(sessionConfig);\n this.log('Session created:', sessionId);\n\n try {\n // Convert ALL messages to prompt (including system messages)\n const prompt = this.messagesToPrompt(messages);\n\n this.log('Sending prompt:', {\n promptLength: prompt.length,\n sessionId: session.sessionId,\n toolsCount: tools?.length || 0,\n });\n\n let responseContent = '';\n\n // Use sendAndWait() to get the response\n try {\n const result = await session.sendAndWait({ prompt }, 12000000); // 12000s timeout\n\n if (result) {\n responseContent = result.data.content || '';\n this.log('Response received:', {\n length: responseContent.length,\n });\n }\n } catch (error: any) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n console.error('[CopilotSDKAdapter] sendAndWait error:', error.message);\n throw error;\n }\n\n const elapsed = Date.now() - startTime;\n this.log(`API response received in ${elapsed}ms`);\n\n if (this.toolCallHistory.length > 0) {\n this.log(`Session executed ${this.toolCallHistory.length} tool calls`);\n }\n\n // Return result with toolCalls marked as already executed\n // Deity llm-loop will check _alreadyExecuted flag and skip re-execution\n const response: LLMResponse = {\n content: responseContent,\n toolCalls: this.toolCallHistory.length > 0 ? this.toolCallHistory : undefined,\n };\n\n return response;\n } catch (error) {\n // Clean up session on error\n await session.destroy();\n throw error;\n } finally {\n // Always destroy disposable session\n await session.destroy();\n this.log('Session destroyed:', sessionId);\n }\n }\n\n /**\n * Convert Deity Tool to Copilot SDK Tool using defineTool\n *\n * Uses SDK's defineTool() function which properly registers tools.\n * Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.\n */\n private convertTools(deityTools: Tool[]): CopilotTool[] {\n this.log('Converting Deity tools to Copilot SDK format:', {\n count: deityTools.length,\n names: deityTools.map((t) => t.name),\n });\n\n const converted = deityTools.map((tool) => {\n // Pass Zod schema directly - Zod v4 has native toJSONSchema() method\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parameters = tool.inputSchema as any;\n\n // Use SDK's defineTool function (critical for proper registration)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return\n return defineTool(tool.name, {\n description: tool.description || `Tool: ${tool.name}`,\n parameters,\n handler: async (args: unknown) => {\n this.log('Executing tool via SDK handler:', {\n name: tool.name,\n });\n\n try {\n if (!this.currentContext) {\n throw new Error('Execution context not available for tool handler');\n }\n\n // Execute Deity tool\n const result = await tool.execute(args, this.currentContext);\n\n this.log('Tool execution successful:', tool.name);\n\n // Return result in format expected by Copilot SDK\n return typeof result === 'string' ? result : JSON.stringify(result);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.error('[CopilotSDKAdapter] Tool execution failed:', {\n tool: tool.name,\n error: errorMsg,\n });\n\n // Return error result\n return JSON.stringify({\n success: false,\n error: errorMsg,\n });\n }\n },\n });\n });\n\n this.log('Tool conversion complete:', {\n convertedCount: converted.length,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n toolNames: converted.map((t: any) => t.name || 'unknown'),\n });\n\n return converted;\n }\n\n /**\n * Convert Deity messages to Copilot prompt format\n *\n * Note: Copilot SDK uses a simple string prompt format.\n * All message types are concatenated into a single prompt.\n */\n private messagesToPrompt(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n switch (msg.role) {\n case 'system':\n prompt += msg.content + '\\n\\n';\n break;\n case 'user':\n prompt += `User: ${msg.content}\\n\\n`;\n break;\n case 'assistant':\n prompt += `Assistant: ${msg.content}\\n\\n`;\n break;\n case 'tool':\n // Skip tool messages - SDK handles them internally\n break;\n }\n }\n\n return prompt;\n }\n\n async cleanup(): Promise<void> {\n if (!this.isInitialized) {\n return;\n }\n\n // No sessions to clean up (disposable session pattern)\n this.log('Stopping Copilot client...');\n await this.client.stop();\n this.isInitialized = false;\n this.log('Copilot client stopped');\n }\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { LLMAdapter, Message, Tool, GenerationConfig, ExecutionContext, LLMResponse } from '@limo-labs/deity';
|
|
2
|
+
|
|
3
|
+
interface CopilotSDKAdapterConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Model to use (default: 'gpt-4o')
|
|
6
|
+
* Options: 'gpt-4o', 'claude-opus-4.6', 'o1', 'o1-mini', etc.
|
|
7
|
+
*/
|
|
8
|
+
model?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Custom Copilot CLI URL (optional)
|
|
11
|
+
* If not provided, SDK will auto-manage the CLI
|
|
12
|
+
*/
|
|
13
|
+
cliUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Callback for streaming response chunks (optional)
|
|
16
|
+
*/
|
|
17
|
+
onStreamChunk?: (chunk: string) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Callback for reasoning/thinking chunks (optional)
|
|
20
|
+
*/
|
|
21
|
+
onReasoningChunk?: (chunk: string) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Enable debug logging (default: false)
|
|
24
|
+
*/
|
|
25
|
+
debug?: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare class CopilotSDKAdapter implements LLMAdapter {
|
|
28
|
+
private client;
|
|
29
|
+
private model;
|
|
30
|
+
private sessionCounter;
|
|
31
|
+
private isInitialized;
|
|
32
|
+
private onStreamChunk?;
|
|
33
|
+
private currentContext?;
|
|
34
|
+
private debugEnabled;
|
|
35
|
+
private toolCallHistory;
|
|
36
|
+
constructor(config?: CopilotSDKAdapterConfig);
|
|
37
|
+
private log;
|
|
38
|
+
initialize(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate LLM response using Copilot SDK's native tool support
|
|
41
|
+
*
|
|
42
|
+
* Copilot SDK handles:
|
|
43
|
+
* - Tool definition injection
|
|
44
|
+
* - Tool call generation
|
|
45
|
+
* - Tool execution via handlers
|
|
46
|
+
* - Multi-turn tool calling loop
|
|
47
|
+
*
|
|
48
|
+
* Architecture notes:
|
|
49
|
+
* - Creates a disposable session for each call
|
|
50
|
+
* - Session is destroyed after use (in finally block)
|
|
51
|
+
* - Tool calls are tracked via onPostToolUse hook
|
|
52
|
+
* - Returns toolCalls array marked as already executed
|
|
53
|
+
*/
|
|
54
|
+
generate(messages: Message[], tools?: Tool[], _config?: GenerationConfig, ctx?: ExecutionContext): Promise<LLMResponse>;
|
|
55
|
+
/**
|
|
56
|
+
* Convert Deity Tool to Copilot SDK Tool using defineTool
|
|
57
|
+
*
|
|
58
|
+
* Uses SDK's defineTool() function which properly registers tools.
|
|
59
|
+
* Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.
|
|
60
|
+
*/
|
|
61
|
+
private convertTools;
|
|
62
|
+
/**
|
|
63
|
+
* Convert Deity messages to Copilot prompt format
|
|
64
|
+
*
|
|
65
|
+
* Note: Copilot SDK uses a simple string prompt format.
|
|
66
|
+
* All message types are concatenated into a single prompt.
|
|
67
|
+
*/
|
|
68
|
+
private messagesToPrompt;
|
|
69
|
+
cleanup(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { CopilotSDKAdapter, type CopilotSDKAdapterConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { LLMAdapter, Message, Tool, GenerationConfig, ExecutionContext, LLMResponse } from '@limo-labs/deity';
|
|
2
|
+
|
|
3
|
+
interface CopilotSDKAdapterConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Model to use (default: 'gpt-4o')
|
|
6
|
+
* Options: 'gpt-4o', 'claude-opus-4.6', 'o1', 'o1-mini', etc.
|
|
7
|
+
*/
|
|
8
|
+
model?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Custom Copilot CLI URL (optional)
|
|
11
|
+
* If not provided, SDK will auto-manage the CLI
|
|
12
|
+
*/
|
|
13
|
+
cliUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Callback for streaming response chunks (optional)
|
|
16
|
+
*/
|
|
17
|
+
onStreamChunk?: (chunk: string) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Callback for reasoning/thinking chunks (optional)
|
|
20
|
+
*/
|
|
21
|
+
onReasoningChunk?: (chunk: string) => void;
|
|
22
|
+
/**
|
|
23
|
+
* Enable debug logging (default: false)
|
|
24
|
+
*/
|
|
25
|
+
debug?: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare class CopilotSDKAdapter implements LLMAdapter {
|
|
28
|
+
private client;
|
|
29
|
+
private model;
|
|
30
|
+
private sessionCounter;
|
|
31
|
+
private isInitialized;
|
|
32
|
+
private onStreamChunk?;
|
|
33
|
+
private currentContext?;
|
|
34
|
+
private debugEnabled;
|
|
35
|
+
private toolCallHistory;
|
|
36
|
+
constructor(config?: CopilotSDKAdapterConfig);
|
|
37
|
+
private log;
|
|
38
|
+
initialize(): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate LLM response using Copilot SDK's native tool support
|
|
41
|
+
*
|
|
42
|
+
* Copilot SDK handles:
|
|
43
|
+
* - Tool definition injection
|
|
44
|
+
* - Tool call generation
|
|
45
|
+
* - Tool execution via handlers
|
|
46
|
+
* - Multi-turn tool calling loop
|
|
47
|
+
*
|
|
48
|
+
* Architecture notes:
|
|
49
|
+
* - Creates a disposable session for each call
|
|
50
|
+
* - Session is destroyed after use (in finally block)
|
|
51
|
+
* - Tool calls are tracked via onPostToolUse hook
|
|
52
|
+
* - Returns toolCalls array marked as already executed
|
|
53
|
+
*/
|
|
54
|
+
generate(messages: Message[], tools?: Tool[], _config?: GenerationConfig, ctx?: ExecutionContext): Promise<LLMResponse>;
|
|
55
|
+
/**
|
|
56
|
+
* Convert Deity Tool to Copilot SDK Tool using defineTool
|
|
57
|
+
*
|
|
58
|
+
* Uses SDK's defineTool() function which properly registers tools.
|
|
59
|
+
* Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.
|
|
60
|
+
*/
|
|
61
|
+
private convertTools;
|
|
62
|
+
/**
|
|
63
|
+
* Convert Deity messages to Copilot prompt format
|
|
64
|
+
*
|
|
65
|
+
* Note: Copilot SDK uses a simple string prompt format.
|
|
66
|
+
* All message types are concatenated into a single prompt.
|
|
67
|
+
*/
|
|
68
|
+
private messagesToPrompt;
|
|
69
|
+
cleanup(): Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { CopilotSDKAdapter, type CopilotSDKAdapterConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { CopilotClient, defineTool } from '@github/copilot-sdk';
|
|
2
|
+
|
|
3
|
+
// src/adapter.ts
|
|
4
|
+
var CopilotSDKAdapter = class {
|
|
5
|
+
client;
|
|
6
|
+
model;
|
|
7
|
+
sessionCounter = 0;
|
|
8
|
+
isInitialized = false;
|
|
9
|
+
onStreamChunk;
|
|
10
|
+
currentContext;
|
|
11
|
+
debugEnabled;
|
|
12
|
+
// Track tool calls for Deity compatibility
|
|
13
|
+
toolCallHistory = [];
|
|
14
|
+
constructor(config = {}) {
|
|
15
|
+
this.model = config.model || "gpt-4o";
|
|
16
|
+
this.onStreamChunk = config.onStreamChunk;
|
|
17
|
+
this.debugEnabled = config.debug || false;
|
|
18
|
+
this.client = new CopilotClient({
|
|
19
|
+
cliUrl: config.cliUrl,
|
|
20
|
+
cliArgs: ["--disable-builtin-mcps"]
|
|
21
|
+
});
|
|
22
|
+
this.log("CopilotSDKAdapter created:", {
|
|
23
|
+
model: this.model,
|
|
24
|
+
mode: config.cliUrl ? "external-server" : "auto-managed",
|
|
25
|
+
streaming: !!this.onStreamChunk,
|
|
26
|
+
nativeToolSupport: true
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
log(...args) {
|
|
30
|
+
if (this.debugEnabled) {
|
|
31
|
+
console.log("[CopilotSDKAdapter]", ...args);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async initialize() {
|
|
35
|
+
if (this.isInitialized) {
|
|
36
|
+
this.log("Client already initialized, skipping");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
this.log("Starting Copilot client...");
|
|
40
|
+
await this.client.start();
|
|
41
|
+
this.isInitialized = true;
|
|
42
|
+
this.log("Copilot client started successfully");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Generate LLM response using Copilot SDK's native tool support
|
|
46
|
+
*
|
|
47
|
+
* Copilot SDK handles:
|
|
48
|
+
* - Tool definition injection
|
|
49
|
+
* - Tool call generation
|
|
50
|
+
* - Tool execution via handlers
|
|
51
|
+
* - Multi-turn tool calling loop
|
|
52
|
+
*
|
|
53
|
+
* Architecture notes:
|
|
54
|
+
* - Creates a disposable session for each call
|
|
55
|
+
* - Session is destroyed after use (in finally block)
|
|
56
|
+
* - Tool calls are tracked via onPostToolUse hook
|
|
57
|
+
* - Returns toolCalls array marked as already executed
|
|
58
|
+
*/
|
|
59
|
+
async generate(messages, tools, _config, ctx) {
|
|
60
|
+
if (!this.isInitialized) {
|
|
61
|
+
await this.initialize();
|
|
62
|
+
}
|
|
63
|
+
this.currentContext = ctx;
|
|
64
|
+
this.toolCallHistory = [];
|
|
65
|
+
const startTime = Date.now();
|
|
66
|
+
const sessionId = `deity-session-${Date.now()}-${this.sessionCounter++}`;
|
|
67
|
+
this.log("Creating disposable session:", sessionId);
|
|
68
|
+
const copilotTools = tools ? this.convertTools(tools) : void 0;
|
|
69
|
+
const toolNames = copilotTools?.map((t) => t.name) || [];
|
|
70
|
+
this.log("Session tools:", {
|
|
71
|
+
count: toolNames.length,
|
|
72
|
+
names: toolNames
|
|
73
|
+
});
|
|
74
|
+
const sessionConfig = {
|
|
75
|
+
sessionId,
|
|
76
|
+
model: this.model,
|
|
77
|
+
tools: copilotTools,
|
|
78
|
+
// Exclude ALL environment tools to ensure only registered tools are used
|
|
79
|
+
excludedTools: [
|
|
80
|
+
"bash",
|
|
81
|
+
"write_bash",
|
|
82
|
+
"read_bash",
|
|
83
|
+
"stop_bash",
|
|
84
|
+
"list_bash",
|
|
85
|
+
"shell",
|
|
86
|
+
"view",
|
|
87
|
+
"create",
|
|
88
|
+
"edit",
|
|
89
|
+
"web_fetch",
|
|
90
|
+
"report_intent",
|
|
91
|
+
"read_file",
|
|
92
|
+
"write_file",
|
|
93
|
+
"sql",
|
|
94
|
+
"read_agent",
|
|
95
|
+
"list_agents",
|
|
96
|
+
"grep",
|
|
97
|
+
"glob",
|
|
98
|
+
"task"
|
|
99
|
+
],
|
|
100
|
+
// Add hooks to track tool calls for Deity compatibility
|
|
101
|
+
hooks: {
|
|
102
|
+
onPostToolUse: (input) => {
|
|
103
|
+
const toolCall = {
|
|
104
|
+
id: `call_${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
106
|
+
name: input.toolName,
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
108
|
+
arguments: input.toolArgs,
|
|
109
|
+
_alreadyExecuted: true,
|
|
110
|
+
// Mark as already executed by SDK
|
|
111
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
112
|
+
_executionResult: JSON.stringify(input.toolResult)
|
|
113
|
+
// Store result for reference
|
|
114
|
+
};
|
|
115
|
+
this.toolCallHistory.push(toolCall);
|
|
116
|
+
this.log("Tool call tracked:", {
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
118
|
+
name: input.toolName,
|
|
119
|
+
totalCalls: this.toolCallHistory.length
|
|
120
|
+
});
|
|
121
|
+
return void 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const session = await this.client.createSession(sessionConfig);
|
|
126
|
+
this.log("Session created:", sessionId);
|
|
127
|
+
try {
|
|
128
|
+
const prompt = this.messagesToPrompt(messages);
|
|
129
|
+
this.log("Sending prompt:", {
|
|
130
|
+
promptLength: prompt.length,
|
|
131
|
+
sessionId: session.sessionId,
|
|
132
|
+
toolsCount: tools?.length || 0
|
|
133
|
+
});
|
|
134
|
+
let responseContent = "";
|
|
135
|
+
try {
|
|
136
|
+
const result = await session.sendAndWait({ prompt }, 12e6);
|
|
137
|
+
if (result) {
|
|
138
|
+
responseContent = result.data.content || "";
|
|
139
|
+
this.log("Response received:", {
|
|
140
|
+
length: responseContent.length
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error("[CopilotSDKAdapter] sendAndWait error:", error.message);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
const elapsed = Date.now() - startTime;
|
|
148
|
+
this.log(`API response received in ${elapsed}ms`);
|
|
149
|
+
if (this.toolCallHistory.length > 0) {
|
|
150
|
+
this.log(`Session executed ${this.toolCallHistory.length} tool calls`);
|
|
151
|
+
}
|
|
152
|
+
const response = {
|
|
153
|
+
content: responseContent,
|
|
154
|
+
toolCalls: this.toolCallHistory.length > 0 ? this.toolCallHistory : void 0
|
|
155
|
+
};
|
|
156
|
+
return response;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
await session.destroy();
|
|
159
|
+
throw error;
|
|
160
|
+
} finally {
|
|
161
|
+
await session.destroy();
|
|
162
|
+
this.log("Session destroyed:", sessionId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Convert Deity Tool to Copilot SDK Tool using defineTool
|
|
167
|
+
*
|
|
168
|
+
* Uses SDK's defineTool() function which properly registers tools.
|
|
169
|
+
* Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.
|
|
170
|
+
*/
|
|
171
|
+
convertTools(deityTools) {
|
|
172
|
+
this.log("Converting Deity tools to Copilot SDK format:", {
|
|
173
|
+
count: deityTools.length,
|
|
174
|
+
names: deityTools.map((t) => t.name)
|
|
175
|
+
});
|
|
176
|
+
const converted = deityTools.map((tool) => {
|
|
177
|
+
const parameters = tool.inputSchema;
|
|
178
|
+
return defineTool(tool.name, {
|
|
179
|
+
description: tool.description || `Tool: ${tool.name}`,
|
|
180
|
+
parameters,
|
|
181
|
+
handler: async (args) => {
|
|
182
|
+
this.log("Executing tool via SDK handler:", {
|
|
183
|
+
name: tool.name
|
|
184
|
+
});
|
|
185
|
+
try {
|
|
186
|
+
if (!this.currentContext) {
|
|
187
|
+
throw new Error("Execution context not available for tool handler");
|
|
188
|
+
}
|
|
189
|
+
const result = await tool.execute(args, this.currentContext);
|
|
190
|
+
this.log("Tool execution successful:", tool.name);
|
|
191
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
192
|
+
} catch (error) {
|
|
193
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
194
|
+
console.error("[CopilotSDKAdapter] Tool execution failed:", {
|
|
195
|
+
tool: tool.name,
|
|
196
|
+
error: errorMsg
|
|
197
|
+
});
|
|
198
|
+
return JSON.stringify({
|
|
199
|
+
success: false,
|
|
200
|
+
error: errorMsg
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
this.log("Tool conversion complete:", {
|
|
207
|
+
convertedCount: converted.length,
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
|
209
|
+
toolNames: converted.map((t) => t.name || "unknown")
|
|
210
|
+
});
|
|
211
|
+
return converted;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Convert Deity messages to Copilot prompt format
|
|
215
|
+
*
|
|
216
|
+
* Note: Copilot SDK uses a simple string prompt format.
|
|
217
|
+
* All message types are concatenated into a single prompt.
|
|
218
|
+
*/
|
|
219
|
+
messagesToPrompt(messages) {
|
|
220
|
+
let prompt = "";
|
|
221
|
+
for (const msg of messages) {
|
|
222
|
+
switch (msg.role) {
|
|
223
|
+
case "system":
|
|
224
|
+
prompt += msg.content + "\n\n";
|
|
225
|
+
break;
|
|
226
|
+
case "user":
|
|
227
|
+
prompt += `User: ${msg.content}
|
|
228
|
+
|
|
229
|
+
`;
|
|
230
|
+
break;
|
|
231
|
+
case "assistant":
|
|
232
|
+
prompt += `Assistant: ${msg.content}
|
|
233
|
+
|
|
234
|
+
`;
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return prompt;
|
|
239
|
+
}
|
|
240
|
+
async cleanup() {
|
|
241
|
+
if (!this.isInitialized) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
this.log("Stopping Copilot client...");
|
|
245
|
+
await this.client.stop();
|
|
246
|
+
this.isInitialized = false;
|
|
247
|
+
this.log("Copilot client stopped");
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export { CopilotSDKAdapter };
|
|
252
|
+
//# sourceMappingURL=index.js.map
|
|
253
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n\n/**\n * Copilot SDK Adapter for Deity Framework\n *\n * Uses Copilot SDK's native tool support for reliable tool calling.\n *\n * Architecture:\n * - Deity passes tools to generate()\n * - Adapter converts Deity tools to Copilot SDK tools\n * - Copilot SDK handles tool calling loop automatically\n * - Adapter returns final response with tool call information\n *\n * Session Management:\n * - Uses disposable session pattern (create → use → destroy)\n * - Each generate() call creates a fresh session\n * - Sessions are destroyed in finally block to ensure cleanup\n * - This pattern is optimized for Deity's stateless design\n */\n\nimport { CopilotClient, defineTool, type Tool as CopilotTool } from '@github/copilot-sdk';\nimport type {\n LLMAdapter,\n LLMResponse,\n Message,\n Tool,\n GenerationConfig,\n ExecutionContext,\n ToolCall,\n} from '@limo-labs/deity';\n\nexport interface CopilotSDKAdapterConfig {\n /**\n * Model to use (default: 'gpt-4o')\n * Options: 'gpt-4o', 'claude-opus-4.6', 'o1', 'o1-mini', etc.\n */\n model?: string;\n\n /**\n * Custom Copilot CLI URL (optional)\n * If not provided, SDK will auto-manage the CLI\n */\n cliUrl?: string;\n\n /**\n * Callback for streaming response chunks (optional)\n */\n onStreamChunk?: (chunk: string) => void;\n\n /**\n * Callback for reasoning/thinking chunks (optional)\n */\n onReasoningChunk?: (chunk: string) => void;\n\n /**\n * Enable debug logging (default: false)\n */\n debug?: boolean;\n}\n\nexport class CopilotSDKAdapter implements LLMAdapter {\n private client: CopilotClient;\n private model: string;\n private sessionCounter = 0;\n private isInitialized = false;\n private onStreamChunk?: (chunk: string) => void;\n private currentContext?: ExecutionContext;\n private debugEnabled: boolean;\n\n // Track tool calls for Deity compatibility\n private toolCallHistory: ToolCall[] = [];\n\n constructor(config: CopilotSDKAdapterConfig = {}) {\n this.model = config.model || 'gpt-4o';\n this.onStreamChunk = config.onStreamChunk;\n this.debugEnabled = config.debug || false;\n\n // CRITICAL FIX: Disable built-in GitHub MCP server\n // GitHub MCP server auto-activates in git repos and overrides SDK tools\n this.client = new CopilotClient({\n cliUrl: config.cliUrl,\n cliArgs: ['--disable-builtin-mcps'],\n });\n\n this.log('CopilotSDKAdapter created:', {\n model: this.model,\n mode: config.cliUrl ? 'external-server' : 'auto-managed',\n streaming: !!this.onStreamChunk,\n nativeToolSupport: true,\n });\n }\n\n private log(...args: any[]): void {\n if (this.debugEnabled) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n console.log('[CopilotSDKAdapter]', ...args);\n }\n }\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n this.log('Client already initialized, skipping');\n return;\n }\n\n this.log('Starting Copilot client...');\n await this.client.start();\n this.isInitialized = true;\n this.log('Copilot client started successfully');\n }\n\n /**\n * Generate LLM response using Copilot SDK's native tool support\n *\n * Copilot SDK handles:\n * - Tool definition injection\n * - Tool call generation\n * - Tool execution via handlers\n * - Multi-turn tool calling loop\n *\n * Architecture notes:\n * - Creates a disposable session for each call\n * - Session is destroyed after use (in finally block)\n * - Tool calls are tracked via onPostToolUse hook\n * - Returns toolCalls array marked as already executed\n */\n async generate(\n messages: Message[],\n tools?: Tool[],\n _config?: GenerationConfig,\n ctx?: ExecutionContext\n ): Promise<LLMResponse> {\n if (!this.isInitialized) {\n await this.initialize();\n }\n\n // Store context for tool handlers\n this.currentContext = ctx;\n\n // Reset tool call history for this generation\n this.toolCallHistory = [];\n\n const startTime = Date.now();\n\n // Disposable session pattern: create new session for each call\n const sessionId = `deity-session-${Date.now()}-${this.sessionCounter++}`;\n this.log('Creating disposable session:', sessionId);\n\n // Convert Deity tools to Copilot SDK tools\n const copilotTools = tools ? this.convertTools(tools) : undefined;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n const toolNames = copilotTools?.map((t) => (t as any).name) || [];\n\n this.log('Session tools:', {\n count: toolNames.length,\n names: toolNames,\n });\n\n // Create session with hooks to track tool calls\n const sessionConfig: any = {\n sessionId,\n model: this.model,\n tools: copilotTools,\n // Exclude ALL environment tools to ensure only registered tools are used\n excludedTools: [\n 'bash',\n 'write_bash',\n 'read_bash',\n 'stop_bash',\n 'list_bash',\n 'shell',\n 'view',\n 'create',\n 'edit',\n 'web_fetch',\n 'report_intent',\n 'read_file',\n 'write_file',\n 'sql',\n 'read_agent',\n 'list_agents',\n 'grep',\n 'glob',\n 'task',\n ],\n // Add hooks to track tool calls for Deity compatibility\n hooks: {\n onPostToolUse: (input: any) => {\n // Record tool call in history with execution metadata\n const toolCall: any = {\n id: `call_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n name: input.toolName,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n arguments: input.toolArgs,\n _alreadyExecuted: true, // Mark as already executed by SDK\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n _executionResult: JSON.stringify(input.toolResult), // Store result for reference\n };\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n this.toolCallHistory.push(toolCall);\n\n this.log('Tool call tracked:', {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n name: input.toolName,\n totalCalls: this.toolCallHistory.length,\n });\n\n // Don't modify anything, just track\n return undefined;\n },\n },\n };\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n const session = await this.client.createSession(sessionConfig);\n this.log('Session created:', sessionId);\n\n try {\n // Convert ALL messages to prompt (including system messages)\n const prompt = this.messagesToPrompt(messages);\n\n this.log('Sending prompt:', {\n promptLength: prompt.length,\n sessionId: session.sessionId,\n toolsCount: tools?.length || 0,\n });\n\n let responseContent = '';\n\n // Use sendAndWait() to get the response\n try {\n const result = await session.sendAndWait({ prompt }, 12000000); // 12000s timeout\n\n if (result) {\n responseContent = result.data.content || '';\n this.log('Response received:', {\n length: responseContent.length,\n });\n }\n } catch (error: any) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n console.error('[CopilotSDKAdapter] sendAndWait error:', error.message);\n throw error;\n }\n\n const elapsed = Date.now() - startTime;\n this.log(`API response received in ${elapsed}ms`);\n\n if (this.toolCallHistory.length > 0) {\n this.log(`Session executed ${this.toolCallHistory.length} tool calls`);\n }\n\n // Return result with toolCalls marked as already executed\n // Deity llm-loop will check _alreadyExecuted flag and skip re-execution\n const response: LLMResponse = {\n content: responseContent,\n toolCalls: this.toolCallHistory.length > 0 ? this.toolCallHistory : undefined,\n };\n\n return response;\n } catch (error) {\n // Clean up session on error\n await session.destroy();\n throw error;\n } finally {\n // Always destroy disposable session\n await session.destroy();\n this.log('Session destroyed:', sessionId);\n }\n }\n\n /**\n * Convert Deity Tool to Copilot SDK Tool using defineTool\n *\n * Uses SDK's defineTool() function which properly registers tools.\n * Zod schemas are passed directly - Zod v4 has native toJSONSchema() method.\n */\n private convertTools(deityTools: Tool[]): CopilotTool[] {\n this.log('Converting Deity tools to Copilot SDK format:', {\n count: deityTools.length,\n names: deityTools.map((t) => t.name),\n });\n\n const converted = deityTools.map((tool) => {\n // Pass Zod schema directly - Zod v4 has native toJSONSchema() method\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parameters = tool.inputSchema as any;\n\n // Use SDK's defineTool function (critical for proper registration)\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return\n return defineTool(tool.name, {\n description: tool.description || `Tool: ${tool.name}`,\n parameters,\n handler: async (args: unknown) => {\n this.log('Executing tool via SDK handler:', {\n name: tool.name,\n });\n\n try {\n if (!this.currentContext) {\n throw new Error('Execution context not available for tool handler');\n }\n\n // Execute Deity tool\n const result = await tool.execute(args, this.currentContext);\n\n this.log('Tool execution successful:', tool.name);\n\n // Return result in format expected by Copilot SDK\n return typeof result === 'string' ? result : JSON.stringify(result);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n console.error('[CopilotSDKAdapter] Tool execution failed:', {\n tool: tool.name,\n error: errorMsg,\n });\n\n // Return error result\n return JSON.stringify({\n success: false,\n error: errorMsg,\n });\n }\n },\n });\n });\n\n this.log('Tool conversion complete:', {\n convertedCount: converted.length,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access\n toolNames: converted.map((t: any) => t.name || 'unknown'),\n });\n\n return converted;\n }\n\n /**\n * Convert Deity messages to Copilot prompt format\n *\n * Note: Copilot SDK uses a simple string prompt format.\n * All message types are concatenated into a single prompt.\n */\n private messagesToPrompt(messages: Message[]): string {\n let prompt = '';\n\n for (const msg of messages) {\n switch (msg.role) {\n case 'system':\n prompt += msg.content + '\\n\\n';\n break;\n case 'user':\n prompt += `User: ${msg.content}\\n\\n`;\n break;\n case 'assistant':\n prompt += `Assistant: ${msg.content}\\n\\n`;\n break;\n case 'tool':\n // Skip tool messages - SDK handles them internally\n break;\n }\n }\n\n return prompt;\n }\n\n async cleanup(): Promise<void> {\n if (!this.isInitialized) {\n return;\n }\n\n // No sessions to clean up (disposable session pattern)\n this.log('Stopping Copilot client...');\n await this.client.stop();\n this.isInitialized = false;\n this.log('Copilot client stopped');\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@limo-labs/deity-adapter-copilot",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "GitHub Copilot SDK adapter for Deity framework",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Limo-Deity/Limo-Deity.git",
|
|
19
|
+
"directory": "packages/adapter-copilot"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/Limo-Deity/Limo-Deity/issues"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/Limo-Deity/Limo-Deity/tree/main/packages/adapter-copilot#readme",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"require": {
|
|
28
|
+
"types": "./dist/index.d.cts",
|
|
29
|
+
"default": "./dist/index.cjs"
|
|
30
|
+
},
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"prepublishOnly": "npm run build",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest watch",
|
|
42
|
+
"test:coverage": "vitest run --coverage",
|
|
43
|
+
"type-check": "tsc --noEmit",
|
|
44
|
+
"lint": "eslint src --ext .ts",
|
|
45
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
46
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
47
|
+
"format:check": "prettier --check \"src/**/*.ts\""
|
|
48
|
+
},
|
|
49
|
+
"keywords": [
|
|
50
|
+
"deity",
|
|
51
|
+
"adapter",
|
|
52
|
+
"copilot",
|
|
53
|
+
"github",
|
|
54
|
+
"llm",
|
|
55
|
+
"ai"
|
|
56
|
+
],
|
|
57
|
+
"author": "Limo Labs",
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@limo-labs/deity": "^0.1.3-alpha.2",
|
|
61
|
+
"@github/copilot-sdk": "^0.1.25"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@limo-labs/deity": "^0.1.3-alpha.2",
|
|
65
|
+
"@github/copilot-sdk": "^0.1.25",
|
|
66
|
+
"@types/node": "^20.11.0",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
|
68
|
+
"@typescript-eslint/parser": "^6.19.0",
|
|
69
|
+
"@vitest/coverage-v8": "^1.2.0",
|
|
70
|
+
"eslint": "^8.56.0",
|
|
71
|
+
"prettier": "^3.2.4",
|
|
72
|
+
"tsup": "^8.0.1",
|
|
73
|
+
"tsx": "^4.7.0",
|
|
74
|
+
"typescript": "^5.3.3",
|
|
75
|
+
"vitest": "^1.2.0"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=18.0.0"
|
|
79
|
+
}
|
|
80
|
+
}
|