@meetopenbot/github 0.0.1 → 0.1.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 +23 -39
- package/dist/agent.js +191 -0
- package/dist/cloud-mode.js +10 -0
- package/dist/config.js +74 -0
- package/dist/credits-auth.js +53 -0
- package/dist/diff.js +346 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +101 -340
- package/dist/model.js +24 -0
- package/package.json +25 -13
- package/src/index.ts +0 -418
- package/tsconfig.json +0 -15
package/dist/index.js
CHANGED
|
@@ -1,110 +1,40 @@
|
|
|
1
1
|
import { definePlugin, shouldHandleInvoke, agentOutput, uiWidget, } from '@meetopenbot/plugin-sdk';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
org: z.string().optional().describe('The organization to create the repository in. If not provided, it will be created for the authenticated user.'),
|
|
18
|
-
description: z.string().optional().describe('A short description of the repository'),
|
|
19
|
-
private: z.boolean().optional().describe('Whether the repository is private'),
|
|
20
|
-
autoInit: z.boolean().optional().describe('Whether to create an initial commit with an empty README'),
|
|
21
|
-
});
|
|
22
|
-
export default definePlugin({
|
|
23
|
-
id: 'github',
|
|
24
|
-
name: 'GitHub',
|
|
25
|
-
description: 'Manage your GitHub repositories',
|
|
26
|
-
configSchema: {
|
|
27
|
-
type: 'object',
|
|
28
|
-
properties: {
|
|
29
|
-
githubToken: {
|
|
30
|
-
type: 'string',
|
|
31
|
-
description: 'GitHub Personal Access Token',
|
|
32
|
-
format: 'password',
|
|
33
|
-
},
|
|
34
|
-
openaiApiKey: {
|
|
35
|
-
type: 'string',
|
|
36
|
-
description: 'OpenAI API Key (optional if provided via environment)',
|
|
37
|
-
format: 'password',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
required: ['githubToken'],
|
|
41
|
-
},
|
|
42
|
-
toolDefinitions: {
|
|
43
|
-
list_repos: {
|
|
44
|
-
description: 'List repositories for the authenticated user',
|
|
45
|
-
inputSchema: {
|
|
46
|
-
type: 'object',
|
|
47
|
-
properties: {
|
|
48
|
-
limit: { type: 'number', description: 'Maximum number of repositories to return' },
|
|
49
|
-
visibility: { type: 'string', enum: ['all', 'public', 'private'], description: 'Filter by repository visibility' },
|
|
50
|
-
sort: { type: 'string', enum: ['created', 'updated', 'pushed', 'full_name'], description: 'How to sort the repositories' },
|
|
2
|
+
import { runGithubAgent } from './agent.js';
|
|
3
|
+
import { isCloudMode } from './cloud-mode.js';
|
|
4
|
+
import { CREDITS_NOT_CONFIGURED_MESSAGE, creditsErrorMessage, resolveCreditsAuthConfig, } from './credits-auth.js';
|
|
5
|
+
import { formatMissingCredentials, GITHUB_TOKEN_VAR, readGithubConfig, resolveGithubCredentials, } from './config.js';
|
|
6
|
+
const GITHUB_TOKEN_WIDGET_ID = 'github-token-form';
|
|
7
|
+
const githubPluginConfigSchema = {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
...(isCloudMode()
|
|
11
|
+
? {
|
|
12
|
+
authMode: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'Credits uses your workspace credit balance via OpenBot. BYOK uses `OPENAI_API_KEY` from workspace settings.',
|
|
15
|
+
enum: ['credits', 'byok'],
|
|
16
|
+
default: 'credits',
|
|
51
17
|
},
|
|
52
|
-
}
|
|
18
|
+
}
|
|
19
|
+
: {}),
|
|
20
|
+
githubToken: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'GitHub Personal Access Token',
|
|
23
|
+
format: 'password',
|
|
53
24
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
properties: {
|
|
59
|
-
owner: { type: 'string', description: 'The owner of the repository' },
|
|
60
|
-
repo: { type: 'string', description: 'The name of the repository' },
|
|
61
|
-
},
|
|
62
|
-
required: ['owner', 'repo'],
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
create_repo: {
|
|
66
|
-
description: 'Create a new repository',
|
|
67
|
-
inputSchema: {
|
|
68
|
-
type: 'object',
|
|
69
|
-
properties: {
|
|
70
|
-
name: { type: 'string', description: 'The name of the repository' },
|
|
71
|
-
org: { type: 'string', description: 'The organization to create the repository in' },
|
|
72
|
-
description: { type: 'string', description: 'A short description of the repository' },
|
|
73
|
-
private: { type: 'boolean', description: 'Whether the repository is private' },
|
|
74
|
-
autoInit: { type: 'boolean', description: 'Whether to create an initial commit with an empty README' },
|
|
75
|
-
},
|
|
76
|
-
required: ['name'],
|
|
77
|
-
},
|
|
25
|
+
model: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
description: 'OpenAI model for GitHub agent invocations',
|
|
28
|
+
default: 'openai/gpt-4o',
|
|
78
29
|
},
|
|
79
30
|
},
|
|
31
|
+
};
|
|
32
|
+
export default definePlugin({
|
|
33
|
+
name: 'GitHub',
|
|
34
|
+
description: 'Manage GitHub repositories, issues, and pull requests',
|
|
35
|
+
configSchema: githubPluginConfigSchema,
|
|
80
36
|
factory: (context) => {
|
|
81
|
-
const getCredentials = async () => {
|
|
82
|
-
const config = context.config;
|
|
83
|
-
const env = process.env;
|
|
84
|
-
const variables = await context.storage.getVariables();
|
|
85
|
-
const getVal = (key, envKey) => {
|
|
86
|
-
if (config[key])
|
|
87
|
-
return config[key];
|
|
88
|
-
if (env[envKey])
|
|
89
|
-
return env[envKey];
|
|
90
|
-
const v = variables[envKey];
|
|
91
|
-
return typeof v === 'string' ? v : v?.value;
|
|
92
|
-
};
|
|
93
|
-
return {
|
|
94
|
-
githubToken: config.githubToken,
|
|
95
|
-
openaiApiKey: getVal('openaiApiKey', 'OPENAI_API_KEY'),
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
const getOctokit = (githubToken) => {
|
|
99
|
-
return new Octokit({
|
|
100
|
-
auth: githubToken,
|
|
101
|
-
headers: {
|
|
102
|
-
'X-GitHub-Api-Version': '2022-11-28',
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
37
|
return (builder) => {
|
|
107
|
-
// Handle agent:invoke for natural language queries
|
|
108
38
|
builder.on('agent:invoke', async function* (event) {
|
|
109
39
|
if (!shouldHandleInvoke(event, context.agentId))
|
|
110
40
|
return;
|
|
@@ -112,272 +42,103 @@ export default definePlugin({
|
|
|
112
42
|
const threadId = event.meta?.threadId;
|
|
113
43
|
if (!userMessage)
|
|
114
44
|
return;
|
|
115
|
-
const
|
|
116
|
-
|
|
45
|
+
const githubConfig = readGithubConfig(context.config);
|
|
46
|
+
const auth = await resolveGithubCredentials(githubConfig, context.storage);
|
|
47
|
+
if (!auth.ok) {
|
|
48
|
+
if (auth.missing.includes('githubToken')) {
|
|
49
|
+
yield uiWidget({
|
|
50
|
+
agentId: context.agentId,
|
|
51
|
+
threadId,
|
|
52
|
+
widget: {
|
|
53
|
+
kind: 'form',
|
|
54
|
+
widgetId: GITHUB_TOKEN_WIDGET_ID,
|
|
55
|
+
title: 'GitHub Access Token',
|
|
56
|
+
description: 'Enter a GitHub Personal Access Token with repo scope to continue.',
|
|
57
|
+
fields: [
|
|
58
|
+
{
|
|
59
|
+
id: 'githubToken',
|
|
60
|
+
label: 'GitHub Access Token',
|
|
61
|
+
type: 'password',
|
|
62
|
+
placeholder: 'ghp_...',
|
|
63
|
+
required: true,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
submitLabel: 'Save Token',
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
117
71
|
yield agentOutput({
|
|
118
72
|
agentId: context.agentId,
|
|
119
|
-
content:
|
|
73
|
+
content: formatMissingCredentials(auth.missing, auth.authMode),
|
|
120
74
|
threadId,
|
|
121
75
|
});
|
|
122
|
-
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (auth.credentials.authMode === 'credits' &&
|
|
79
|
+
!resolveCreditsAuthConfig()) {
|
|
80
|
+
yield agentOutput({
|
|
123
81
|
agentId: context.agentId,
|
|
82
|
+
content: CREDITS_NOT_CONFIGURED_MESSAGE,
|
|
124
83
|
threadId,
|
|
125
|
-
widget: {
|
|
126
|
-
kind: 'form',
|
|
127
|
-
widgetId: 'github-config-form',
|
|
128
|
-
title: 'OpenAI Configuration',
|
|
129
|
-
description: 'Enter your OpenAI API key to get started.',
|
|
130
|
-
fields: [
|
|
131
|
-
{
|
|
132
|
-
id: 'openaiApiKey',
|
|
133
|
-
label: 'OpenAI API Key',
|
|
134
|
-
type: 'text',
|
|
135
|
-
placeholder: 'sk-...',
|
|
136
|
-
required: true,
|
|
137
|
-
},
|
|
138
|
-
],
|
|
139
|
-
submitLabel: 'Save Configuration',
|
|
140
|
-
},
|
|
141
84
|
});
|
|
142
85
|
return;
|
|
143
86
|
}
|
|
144
|
-
const octokit = getOctokit(githubToken);
|
|
145
|
-
const openai = createOpenAI({ apiKey: openaiApiKey });
|
|
146
87
|
try {
|
|
147
|
-
|
|
148
|
-
model: openai('gpt-4o'),
|
|
149
|
-
stopWhen: stepCountIs(5),
|
|
150
|
-
system: `You are a GitHub management assistant. Help users manage their repositories.
|
|
151
|
-
- Use list_repos to see the authenticated user's repositories.
|
|
152
|
-
- Use get_repo to get details about a repository.
|
|
153
|
-
- Use create_repo to create a new repository.
|
|
154
|
-
When a tool requires an owner and repo, parse them from the "owner/repo" format the user provides.
|
|
155
|
-
If a tool returns an error, explain it to the user or try an alternative approach if appropriate.
|
|
156
|
-
Be concise and helpful.`,
|
|
88
|
+
for await (const chunk of runGithubAgent({
|
|
157
89
|
prompt: userMessage,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return { error: error.message, status: error.status };
|
|
173
|
-
}
|
|
174
|
-
},
|
|
175
|
-
}),
|
|
176
|
-
get_repo: tool({
|
|
177
|
-
description: 'Get details of a specific repository',
|
|
178
|
-
inputSchema: getRepoSchema,
|
|
179
|
-
execute: async ({ owner, repo }) => {
|
|
180
|
-
try {
|
|
181
|
-
const result = await octokit.repos.get({ owner, repo });
|
|
182
|
-
return result.data;
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
return { error: error.message, status: error.status };
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
}),
|
|
189
|
-
create_repo: tool({
|
|
190
|
-
description: 'Create a new repository',
|
|
191
|
-
inputSchema: createRepoSchema,
|
|
192
|
-
execute: async ({ name, org, description, private: isPrivate, autoInit }) => {
|
|
193
|
-
try {
|
|
194
|
-
const params = {
|
|
195
|
-
name,
|
|
196
|
-
description,
|
|
197
|
-
private: isPrivate,
|
|
198
|
-
auto_init: autoInit,
|
|
199
|
-
};
|
|
200
|
-
const result = org
|
|
201
|
-
? await octokit.repos.createInOrg({ ...params, org })
|
|
202
|
-
: await octokit.repos.createForAuthenticatedUser(params);
|
|
203
|
-
return result.data;
|
|
204
|
-
}
|
|
205
|
-
catch (error) {
|
|
206
|
-
return {
|
|
207
|
-
error: error.message,
|
|
208
|
-
status: error.status,
|
|
209
|
-
details: error.response?.data,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
}),
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
if (text.trim()) {
|
|
90
|
+
githubToken: auth.credentials.githubToken,
|
|
91
|
+
authMode: auth.credentials.authMode,
|
|
92
|
+
openaiApiKey: auth.credentials.openaiApiKey,
|
|
93
|
+
model: auth.credentials.model,
|
|
94
|
+
})) {
|
|
95
|
+
if (chunk.kind === 'widget') {
|
|
96
|
+
yield uiWidget({
|
|
97
|
+
agentId: context.agentId,
|
|
98
|
+
threadId,
|
|
99
|
+
widget: chunk.widget,
|
|
100
|
+
meta: event.meta,
|
|
101
|
+
});
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
217
104
|
yield agentOutput({
|
|
218
105
|
agentId: context.agentId,
|
|
219
|
-
content:
|
|
106
|
+
content: chunk.content,
|
|
220
107
|
threadId,
|
|
108
|
+
meta: event.meta,
|
|
221
109
|
});
|
|
222
110
|
}
|
|
223
|
-
for (const step of steps) {
|
|
224
|
-
for (const toolResult of step.toolResults) {
|
|
225
|
-
if (toolResult.toolName === 'list_repos') {
|
|
226
|
-
const repos = toolResult.output;
|
|
227
|
-
yield uiWidget({
|
|
228
|
-
agentId: context.agentId,
|
|
229
|
-
threadId,
|
|
230
|
-
widget: {
|
|
231
|
-
kind: 'list',
|
|
232
|
-
title: 'GitHub Repositories',
|
|
233
|
-
items: (repos || []).map((r) => ({
|
|
234
|
-
id: String(r.id),
|
|
235
|
-
label: r.full_name,
|
|
236
|
-
description: r.description || (r.private ? 'Private' : 'Public'),
|
|
237
|
-
status: 'done',
|
|
238
|
-
})),
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
111
|
}
|
|
245
112
|
catch (error) {
|
|
113
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
114
|
+
const creditsMessage = auth.credentials.authMode === 'credits'
|
|
115
|
+
? creditsErrorMessage(message)
|
|
116
|
+
: undefined;
|
|
246
117
|
yield agentOutput({
|
|
247
118
|
agentId: context.agentId,
|
|
248
|
-
content:
|
|
119
|
+
content: (creditsMessage ?? message)
|
|
120
|
+
? `I encountered an error: ${creditsMessage ?? message}`
|
|
121
|
+
: 'GitHub agent failed for an unknown reason. Please try again.',
|
|
249
122
|
threadId,
|
|
250
123
|
});
|
|
251
124
|
}
|
|
252
125
|
});
|
|
253
126
|
builder.on('client:ui:widget:response', async function* (event) {
|
|
254
|
-
if (event.data?.widgetId !==
|
|
127
|
+
if (event.data?.widgetId !== GITHUB_TOKEN_WIDGET_ID)
|
|
255
128
|
return;
|
|
256
|
-
const
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
// Handle tool calls
|
|
271
|
-
builder.on('action:list_repos', async function* (event) {
|
|
272
|
-
const { githubToken } = await getCredentials();
|
|
273
|
-
const octokit = getOctokit(githubToken);
|
|
274
|
-
const { limit, visibility, sort } = (event.data || {});
|
|
275
|
-
try {
|
|
276
|
-
const result = await octokit.repos.listForAuthenticatedUser({
|
|
277
|
-
per_page: limit || 20,
|
|
278
|
-
visibility: visibility || 'all',
|
|
279
|
-
sort: sort || 'updated',
|
|
280
|
-
});
|
|
281
|
-
yield uiWidget({
|
|
282
|
-
agentId: context.agentId,
|
|
283
|
-
threadId: event.meta?.threadId,
|
|
284
|
-
widget: {
|
|
285
|
-
kind: 'list',
|
|
286
|
-
title: 'GitHub Repositories',
|
|
287
|
-
items: result.data.map((r) => ({
|
|
288
|
-
id: String(r.id),
|
|
289
|
-
label: r.full_name,
|
|
290
|
-
description: r.description || (r.private ? 'Private' : 'Public'),
|
|
291
|
-
status: 'done',
|
|
292
|
-
})),
|
|
293
|
-
},
|
|
294
|
-
});
|
|
295
|
-
yield {
|
|
296
|
-
type: 'action:list_repos:result',
|
|
297
|
-
data: {
|
|
298
|
-
...result.data,
|
|
299
|
-
output: `Successfully listed ${result.data.length} repositories.`,
|
|
300
|
-
},
|
|
301
|
-
meta: event.meta,
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
catch (error) {
|
|
305
|
-
yield {
|
|
306
|
-
type: 'action:list_repos:result',
|
|
307
|
-
data: {
|
|
308
|
-
error: error.message,
|
|
309
|
-
status: error.status,
|
|
310
|
-
details: error.response?.data,
|
|
311
|
-
output: `Failed to list repositories: ${error.message}`,
|
|
312
|
-
},
|
|
313
|
-
meta: event.meta,
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
builder.on('action:get_repo', async function* (event) {
|
|
318
|
-
const { githubToken } = await getCredentials();
|
|
319
|
-
const octokit = getOctokit(githubToken);
|
|
320
|
-
const { owner, repo } = (event.data || {});
|
|
321
|
-
try {
|
|
322
|
-
const result = await octokit.repos.get({ owner, repo });
|
|
323
|
-
yield {
|
|
324
|
-
type: 'action:get_repo:result',
|
|
325
|
-
data: {
|
|
326
|
-
...result.data,
|
|
327
|
-
output: `Successfully retrieved details for ${owner}/${repo}.`,
|
|
328
|
-
},
|
|
329
|
-
meta: event.meta,
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
catch (error) {
|
|
333
|
-
yield {
|
|
334
|
-
type: 'action:get_repo:result',
|
|
335
|
-
data: {
|
|
336
|
-
error: error.message,
|
|
337
|
-
status: error.status,
|
|
338
|
-
details: error.response?.data,
|
|
339
|
-
output: `Failed to get repository ${owner}/${repo}: ${error.message}`,
|
|
340
|
-
},
|
|
341
|
-
meta: event.meta,
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
});
|
|
345
|
-
builder.on('action:create_repo', async function* (event) {
|
|
346
|
-
console.log('action:create_repo', event);
|
|
347
|
-
const { githubToken } = await getCredentials();
|
|
348
|
-
const octokit = getOctokit(githubToken);
|
|
349
|
-
const { name, org, description, private: isPrivate, autoInit } = (event.data || {});
|
|
350
|
-
try {
|
|
351
|
-
const params = {
|
|
352
|
-
name,
|
|
353
|
-
description,
|
|
354
|
-
private: isPrivate,
|
|
355
|
-
auto_init: autoInit,
|
|
356
|
-
};
|
|
357
|
-
const result = org
|
|
358
|
-
? await octokit.repos.createInOrg({ ...params, org })
|
|
359
|
-
: await octokit.repos.createForAuthenticatedUser(params);
|
|
360
|
-
yield {
|
|
361
|
-
type: 'action:create_repo:result',
|
|
362
|
-
data: {
|
|
363
|
-
...result.data,
|
|
364
|
-
output: `Successfully created repository ${result.data.full_name}.`,
|
|
365
|
-
},
|
|
366
|
-
meta: event.meta,
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
catch (error) {
|
|
370
|
-
yield {
|
|
371
|
-
type: 'action:create_repo:result',
|
|
372
|
-
data: {
|
|
373
|
-
error: error.message,
|
|
374
|
-
status: error.status,
|
|
375
|
-
details: error.response?.data,
|
|
376
|
-
output: `Failed to create repository ${name}: ${error.message}`,
|
|
377
|
-
},
|
|
378
|
-
meta: event.meta,
|
|
379
|
-
};
|
|
380
|
-
}
|
|
129
|
+
const githubToken = event.data.values?.githubToken;
|
|
130
|
+
if (typeof githubToken !== 'string' || !githubToken.trim())
|
|
131
|
+
return;
|
|
132
|
+
await context.storage.createVariable({
|
|
133
|
+
key: GITHUB_TOKEN_VAR,
|
|
134
|
+
value: githubToken.trim(),
|
|
135
|
+
secret: true,
|
|
136
|
+
});
|
|
137
|
+
yield agentOutput({
|
|
138
|
+
agentId: context.agentId,
|
|
139
|
+
content: 'GitHub access token saved. Retry your last request.',
|
|
140
|
+
threadId: event.meta?.threadId,
|
|
141
|
+
});
|
|
381
142
|
});
|
|
382
143
|
};
|
|
383
144
|
},
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
2
|
+
import { CREDITS_API_KEY_PLACEHOLDER, INTEGRATIONS_TOKEN_HEADER, creditsProviderBaseUrl, resolveCreditsAuthConfig, shouldUseCreditsAuth, } from "./credits-auth.js";
|
|
3
|
+
function normalizeOpenAiModelId(model) {
|
|
4
|
+
return model.includes("/") ? model.split("/").slice(1).join("/") : model;
|
|
5
|
+
}
|
|
6
|
+
export function resolveOpenAiModel(model, options) {
|
|
7
|
+
const modelId = normalizeOpenAiModelId(model);
|
|
8
|
+
const useCredits = shouldUseCreditsAuth(options);
|
|
9
|
+
if (useCredits) {
|
|
10
|
+
const config = resolveCreditsAuthConfig();
|
|
11
|
+
if (!config) {
|
|
12
|
+
throw new Error("OpenBot Credits is not configured. The cloud host must set OPENBOT_INTEGRATIONS_BASE_URL and OPENBOT_INTEGRATIONS_TOKEN.");
|
|
13
|
+
}
|
|
14
|
+
const baseURL = creditsProviderBaseUrl(config);
|
|
15
|
+
const headers = { [INTEGRATIONS_TOKEN_HEADER]: config.token };
|
|
16
|
+
const apiKey = config.token || CREDITS_API_KEY_PLACEHOLDER;
|
|
17
|
+
return createOpenAI({ baseURL, apiKey, headers })(modelId);
|
|
18
|
+
}
|
|
19
|
+
const apiKey = options?.openaiApiKey?.trim();
|
|
20
|
+
if (!apiKey) {
|
|
21
|
+
throw new Error("OpenAI API key is required in BYOK mode. Add `OPENAI_API_KEY` under workspace settings or switch `authMode` to `credits` on cloud.");
|
|
22
|
+
}
|
|
23
|
+
return createOpenAI({ apiKey })(modelId);
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/github",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Manage
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Manage GitHub repositories, issues, and pull requests from OpenBot",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"start": "node dist/index.js",
|
|
10
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
-
},
|
|
6
|
+
"main": "./dist/index.js",
|
|
12
7
|
"publishConfig": {
|
|
13
8
|
"access": "public"
|
|
14
9
|
},
|
|
15
10
|
"dependencies": {
|
|
16
|
-
"@ai-sdk/
|
|
17
|
-
"@
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"zod": "^4.4.3"
|
|
11
|
+
"@ai-sdk/mcp": "^2.0.14",
|
|
12
|
+
"@ai-sdk/openai": "^4.0.15",
|
|
13
|
+
"ai": "^7.0.29",
|
|
14
|
+
"@meetopenbot/plugin-sdk": "^0.2.0"
|
|
21
15
|
},
|
|
22
16
|
"devDependencies": {
|
|
23
17
|
"@types/node": "^25.9.1",
|
|
24
18
|
"ts-node": "^10.9.2",
|
|
25
19
|
"typescript": "^6.0.3"
|
|
20
|
+
},
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsc && node ../../scripts/write-plugin-declaration.mjs",
|
|
34
|
+
"start": "node dist/index.js",
|
|
35
|
+
"dev": "tsc --watch --preserveWatchOutput",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"test": "node --experimental-strip-types --test src/diff.test.ts"
|
|
26
38
|
}
|
|
27
39
|
}
|