confused-ai-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/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub tool implementation - TypeScript GithubTools
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { BaseTool, BaseToolConfig } from './base-tool.js';
|
|
7
|
+
import { ToolContext, ToolCategory } from './types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GitHub API types
|
|
11
|
+
*/
|
|
12
|
+
interface GitHubRepository {
|
|
13
|
+
full_name: string;
|
|
14
|
+
description: string | null;
|
|
15
|
+
html_url: string;
|
|
16
|
+
stargazers_count: number;
|
|
17
|
+
forks_count: number;
|
|
18
|
+
language: string | null;
|
|
19
|
+
open_issues_count: number;
|
|
20
|
+
default_branch: string;
|
|
21
|
+
private: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface GitHubIssue {
|
|
25
|
+
number: number;
|
|
26
|
+
title: string;
|
|
27
|
+
state: string;
|
|
28
|
+
html_url: string;
|
|
29
|
+
user: { login: string };
|
|
30
|
+
body: string | null;
|
|
31
|
+
labels: Array<{ name: string }>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface GitHubPullRequest {
|
|
35
|
+
number: number;
|
|
36
|
+
title: string;
|
|
37
|
+
state: string;
|
|
38
|
+
html_url: string;
|
|
39
|
+
user: { login: string };
|
|
40
|
+
body: string | null;
|
|
41
|
+
head: { ref: string };
|
|
42
|
+
base: { ref: string };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface GitHubSearchResult {
|
|
46
|
+
items: Array<{
|
|
47
|
+
full_name: string;
|
|
48
|
+
description: string | null;
|
|
49
|
+
html_url: string;
|
|
50
|
+
stargazers_count: number;
|
|
51
|
+
forks_count: number;
|
|
52
|
+
language: string | null;
|
|
53
|
+
}>;
|
|
54
|
+
total_count: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface GitHubResult {
|
|
58
|
+
data?: unknown;
|
|
59
|
+
error?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Base GitHub API URL
|
|
63
|
+
const GITHUB_API_BASE = 'https://api.github.com';
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Helper function to make authenticated GitHub API requests
|
|
67
|
+
*/
|
|
68
|
+
async function githubRequest(
|
|
69
|
+
endpoint: string,
|
|
70
|
+
token?: string,
|
|
71
|
+
options: RequestInit = {}
|
|
72
|
+
): Promise<Response> {
|
|
73
|
+
const headers: Record<string, string> = {
|
|
74
|
+
Accept: 'application/vnd.github.v3+json',
|
|
75
|
+
'User-Agent': 'AgentFramework/1.0',
|
|
76
|
+
...((options.headers as Record<string, string>) || {}),
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (token) {
|
|
80
|
+
headers.Authorization = `Bearer ${token}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return fetch(`${GITHUB_API_BASE}${endpoint}`, {
|
|
84
|
+
...options,
|
|
85
|
+
headers,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Search repositories tool
|
|
91
|
+
*/
|
|
92
|
+
const GitHubSearchRepositoriesParameters = z.object({
|
|
93
|
+
query: z.string().describe('Search query for repositories'),
|
|
94
|
+
sort: z.enum(['stars', 'forks', 'updated']).optional().default('stars'),
|
|
95
|
+
order: z.enum(['asc', 'desc']).optional().default('desc'),
|
|
96
|
+
per_page: z.number().min(1).max(100).optional().default(30),
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
export class GitHubSearchRepositoriesTool extends BaseTool<typeof GitHubSearchRepositoriesParameters, GitHubResult> {
|
|
100
|
+
private token?: string;
|
|
101
|
+
|
|
102
|
+
constructor(
|
|
103
|
+
config?: Partial<Omit<BaseToolConfig<typeof GitHubSearchRepositoriesParameters>, 'parameters'>> & {
|
|
104
|
+
token?: string;
|
|
105
|
+
}
|
|
106
|
+
) {
|
|
107
|
+
super({
|
|
108
|
+
name: config?.name ?? 'github.search_repositories',
|
|
109
|
+
description: config?.description ?? 'Search for repositories on GitHub',
|
|
110
|
+
parameters: GitHubSearchRepositoriesParameters,
|
|
111
|
+
category: config?.category ?? ToolCategory.API,
|
|
112
|
+
permissions: {
|
|
113
|
+
allowNetwork: true,
|
|
114
|
+
maxExecutionTimeMs: 30000,
|
|
115
|
+
...config?.permissions,
|
|
116
|
+
},
|
|
117
|
+
...config,
|
|
118
|
+
});
|
|
119
|
+
this.token = config?.token || process.env.GITHUB_ACCESS_TOKEN;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
protected async performExecute(
|
|
123
|
+
params: z.infer<typeof GitHubSearchRepositoriesParameters>,
|
|
124
|
+
_context: ToolContext
|
|
125
|
+
): Promise<GitHubResult> {
|
|
126
|
+
try {
|
|
127
|
+
const response = await githubRequest(
|
|
128
|
+
`/search/repositories?q=${encodeURIComponent(params.query)}&sort=${params.sort}&order=${params.order}&per_page=${params.per_page}`,
|
|
129
|
+
this.token
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
throw new Error(`GitHub API error: ${response.status}`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const data = (await response.json()) as GitHubSearchResult;
|
|
137
|
+
return { data };
|
|
138
|
+
} catch (error) {
|
|
139
|
+
return {
|
|
140
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get repository tool
|
|
148
|
+
*/
|
|
149
|
+
const GitHubGetRepositoryParameters = z.object({
|
|
150
|
+
owner: z.string().describe('Repository owner (username or organization)'),
|
|
151
|
+
repo: z.string().describe('Repository name'),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
export class GitHubGetRepositoryTool extends BaseTool<typeof GitHubGetRepositoryParameters, GitHubResult> {
|
|
155
|
+
private token?: string;
|
|
156
|
+
|
|
157
|
+
constructor(
|
|
158
|
+
config?: Partial<Omit<BaseToolConfig<typeof GitHubGetRepositoryParameters>, 'parameters'>> & {
|
|
159
|
+
token?: string;
|
|
160
|
+
}
|
|
161
|
+
) {
|
|
162
|
+
super({
|
|
163
|
+
name: config?.name ?? 'github.get_repository',
|
|
164
|
+
description: config?.description ?? 'Get details of a specific repository',
|
|
165
|
+
parameters: GitHubGetRepositoryParameters,
|
|
166
|
+
category: config?.category ?? ToolCategory.API,
|
|
167
|
+
permissions: {
|
|
168
|
+
allowNetwork: true,
|
|
169
|
+
maxExecutionTimeMs: 30000,
|
|
170
|
+
...config?.permissions,
|
|
171
|
+
},
|
|
172
|
+
...config,
|
|
173
|
+
});
|
|
174
|
+
this.token = config?.token || process.env.GITHUB_ACCESS_TOKEN;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
protected async performExecute(
|
|
178
|
+
params: z.infer<typeof GitHubGetRepositoryParameters>,
|
|
179
|
+
_context: ToolContext
|
|
180
|
+
): Promise<GitHubResult> {
|
|
181
|
+
try {
|
|
182
|
+
const response = await githubRequest(
|
|
183
|
+
`/repos/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.repo)}`,
|
|
184
|
+
this.token
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
throw new Error(`GitHub API error: ${response.status}`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const data = (await response.json()) as GitHubRepository;
|
|
192
|
+
return { data };
|
|
193
|
+
} catch (error) {
|
|
194
|
+
return {
|
|
195
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* List issues tool
|
|
203
|
+
*/
|
|
204
|
+
const GitHubListIssuesParameters = z.object({
|
|
205
|
+
owner: z.string().describe('Repository owner'),
|
|
206
|
+
repo: z.string().describe('Repository name'),
|
|
207
|
+
state: z.enum(['open', 'closed', 'all']).optional().default('open'),
|
|
208
|
+
per_page: z.number().min(1).max(100).optional().default(30),
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
export class GitHubListIssuesTool extends BaseTool<typeof GitHubListIssuesParameters, GitHubResult> {
|
|
212
|
+
private token?: string;
|
|
213
|
+
|
|
214
|
+
constructor(
|
|
215
|
+
config?: Partial<Omit<BaseToolConfig<typeof GitHubListIssuesParameters>, 'parameters'>> & {
|
|
216
|
+
token?: string;
|
|
217
|
+
}
|
|
218
|
+
) {
|
|
219
|
+
super({
|
|
220
|
+
name: config?.name ?? 'github.list_issues',
|
|
221
|
+
description: config?.description ?? 'List issues in a repository',
|
|
222
|
+
parameters: GitHubListIssuesParameters,
|
|
223
|
+
category: config?.category ?? ToolCategory.API,
|
|
224
|
+
permissions: {
|
|
225
|
+
allowNetwork: true,
|
|
226
|
+
maxExecutionTimeMs: 30000,
|
|
227
|
+
...config?.permissions,
|
|
228
|
+
},
|
|
229
|
+
...config,
|
|
230
|
+
});
|
|
231
|
+
this.token = config?.token || process.env.GITHUB_ACCESS_TOKEN;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
protected async performExecute(
|
|
235
|
+
params: z.infer<typeof GitHubListIssuesParameters>,
|
|
236
|
+
_context: ToolContext
|
|
237
|
+
): Promise<GitHubResult> {
|
|
238
|
+
try {
|
|
239
|
+
const response = await githubRequest(
|
|
240
|
+
`/repos/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.repo)}/issues?state=${params.state}&per_page=${params.per_page}`,
|
|
241
|
+
this.token
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
if (!response.ok) {
|
|
245
|
+
throw new Error(`GitHub API error: ${response.status}`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const data = (await response.json()) as GitHubIssue[];
|
|
249
|
+
return { data };
|
|
250
|
+
} catch (error) {
|
|
251
|
+
return {
|
|
252
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Create issue tool
|
|
260
|
+
*/
|
|
261
|
+
const GitHubCreateIssueParameters = z.object({
|
|
262
|
+
owner: z.string().describe('Repository owner'),
|
|
263
|
+
repo: z.string().describe('Repository name'),
|
|
264
|
+
title: z.string().describe('Issue title'),
|
|
265
|
+
body: z.string().optional().describe('Issue body/description'),
|
|
266
|
+
labels: z.array(z.string()).optional().describe('Labels to apply to the issue'),
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
export class GitHubCreateIssueTool extends BaseTool<typeof GitHubCreateIssueParameters, GitHubResult> {
|
|
270
|
+
private token?: string;
|
|
271
|
+
|
|
272
|
+
constructor(
|
|
273
|
+
config?: Partial<Omit<BaseToolConfig<typeof GitHubCreateIssueParameters>, 'parameters'>> & {
|
|
274
|
+
token?: string;
|
|
275
|
+
}
|
|
276
|
+
) {
|
|
277
|
+
super({
|
|
278
|
+
name: config?.name ?? 'github.create_issue',
|
|
279
|
+
description: config?.description ?? 'Create a new issue in a repository',
|
|
280
|
+
parameters: GitHubCreateIssueParameters,
|
|
281
|
+
category: config?.category ?? ToolCategory.API,
|
|
282
|
+
permissions: {
|
|
283
|
+
allowNetwork: true,
|
|
284
|
+
maxExecutionTimeMs: 30000,
|
|
285
|
+
...config?.permissions,
|
|
286
|
+
},
|
|
287
|
+
...config,
|
|
288
|
+
});
|
|
289
|
+
this.token = config?.token || process.env.GITHUB_ACCESS_TOKEN;
|
|
290
|
+
|
|
291
|
+
if (!this.token) {
|
|
292
|
+
throw new Error('GitHub access token is required for creating issues');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
protected async performExecute(
|
|
297
|
+
params: z.infer<typeof GitHubCreateIssueParameters>,
|
|
298
|
+
_context: ToolContext
|
|
299
|
+
): Promise<GitHubResult> {
|
|
300
|
+
try {
|
|
301
|
+
const response = await githubRequest(
|
|
302
|
+
`/repos/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.repo)}/issues`,
|
|
303
|
+
this.token,
|
|
304
|
+
{
|
|
305
|
+
method: 'POST',
|
|
306
|
+
headers: {
|
|
307
|
+
'Content-Type': 'application/json',
|
|
308
|
+
},
|
|
309
|
+
body: JSON.stringify({
|
|
310
|
+
title: params.title,
|
|
311
|
+
body: params.body,
|
|
312
|
+
labels: params.labels,
|
|
313
|
+
}),
|
|
314
|
+
}
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
if (!response.ok) {
|
|
318
|
+
throw new Error(`GitHub API error: ${response.status}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const data = (await response.json()) as GitHubIssue;
|
|
322
|
+
return { data };
|
|
323
|
+
} catch (error) {
|
|
324
|
+
return {
|
|
325
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* List pull requests tool
|
|
333
|
+
*/
|
|
334
|
+
const GitHubListPullRequestsParameters = z.object({
|
|
335
|
+
owner: z.string().describe('Repository owner'),
|
|
336
|
+
repo: z.string().describe('Repository name'),
|
|
337
|
+
state: z.enum(['open', 'closed', 'all']).optional().default('open'),
|
|
338
|
+
per_page: z.number().min(1).max(100).optional().default(30),
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
export class GitHubListPullRequestsTool extends BaseTool<typeof GitHubListPullRequestsParameters, GitHubResult> {
|
|
342
|
+
private token?: string;
|
|
343
|
+
|
|
344
|
+
constructor(
|
|
345
|
+
config?: Partial<Omit<BaseToolConfig<typeof GitHubListPullRequestsParameters>, 'parameters'>> & {
|
|
346
|
+
token?: string;
|
|
347
|
+
}
|
|
348
|
+
) {
|
|
349
|
+
super({
|
|
350
|
+
name: config?.name ?? 'github.list_pull_requests',
|
|
351
|
+
description: config?.description ?? 'List pull requests in a repository',
|
|
352
|
+
parameters: GitHubListPullRequestsParameters,
|
|
353
|
+
category: config?.category ?? ToolCategory.API,
|
|
354
|
+
permissions: {
|
|
355
|
+
allowNetwork: true,
|
|
356
|
+
maxExecutionTimeMs: 30000,
|
|
357
|
+
...config?.permissions,
|
|
358
|
+
},
|
|
359
|
+
...config,
|
|
360
|
+
});
|
|
361
|
+
this.token = config?.token || process.env.GITHUB_ACCESS_TOKEN;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
protected async performExecute(
|
|
365
|
+
params: z.infer<typeof GitHubListPullRequestsParameters>,
|
|
366
|
+
_context: ToolContext
|
|
367
|
+
): Promise<GitHubResult> {
|
|
368
|
+
try {
|
|
369
|
+
const response = await githubRequest(
|
|
370
|
+
`/repos/${encodeURIComponent(params.owner)}/${encodeURIComponent(params.repo)}/pulls?state=${params.state}&per_page=${params.per_page}`,
|
|
371
|
+
this.token
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
if (!response.ok) {
|
|
375
|
+
throw new Error(`GitHub API error: ${response.status}`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const data = (await response.json()) as GitHubPullRequest[];
|
|
379
|
+
return { data };
|
|
380
|
+
} catch (error) {
|
|
381
|
+
return {
|
|
382
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* GitHub toolkit
|
|
390
|
+
*/
|
|
391
|
+
export class GitHubToolkit {
|
|
392
|
+
static create(options?: {
|
|
393
|
+
token?: string;
|
|
394
|
+
enableSearch?: boolean;
|
|
395
|
+
enableGetRepo?: boolean;
|
|
396
|
+
enableListIssues?: boolean;
|
|
397
|
+
enableCreateIssue?: boolean;
|
|
398
|
+
enableListPRs?: boolean;
|
|
399
|
+
}): Array<
|
|
400
|
+
| GitHubSearchRepositoriesTool
|
|
401
|
+
| GitHubGetRepositoryTool
|
|
402
|
+
| GitHubListIssuesTool
|
|
403
|
+
| GitHubCreateIssueTool
|
|
404
|
+
| GitHubListPullRequestsTool
|
|
405
|
+
> {
|
|
406
|
+
const tools: Array<
|
|
407
|
+
| GitHubSearchRepositoriesTool
|
|
408
|
+
| GitHubGetRepositoryTool
|
|
409
|
+
| GitHubListIssuesTool
|
|
410
|
+
| GitHubCreateIssueTool
|
|
411
|
+
| GitHubListPullRequestsTool
|
|
412
|
+
> = [];
|
|
413
|
+
|
|
414
|
+
if (options?.enableSearch !== false) {
|
|
415
|
+
tools.push(new GitHubSearchRepositoriesTool({ token: options?.token }));
|
|
416
|
+
}
|
|
417
|
+
if (options?.enableGetRepo !== false) {
|
|
418
|
+
tools.push(new GitHubGetRepositoryTool({ token: options?.token }));
|
|
419
|
+
}
|
|
420
|
+
if (options?.enableListIssues !== false) {
|
|
421
|
+
tools.push(new GitHubListIssuesTool({ token: options?.token }));
|
|
422
|
+
}
|
|
423
|
+
if (options?.enableCreateIssue !== false) {
|
|
424
|
+
tools.push(new GitHubCreateIssueTool({ token: options?.token }));
|
|
425
|
+
}
|
|
426
|
+
if (options?.enableListPRs !== false) {
|
|
427
|
+
tools.push(new GitHubListPullRequestsTool({ token: options?.token }));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return tools;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HackerNews tool implementation - TypeScript HackerNewsTools
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { BaseTool, BaseToolConfig } from './base-tool.js';
|
|
7
|
+
import { ToolContext, ToolCategory } from './types.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HackerNews story
|
|
11
|
+
*/
|
|
12
|
+
interface HackerNewsStory {
|
|
13
|
+
id: number;
|
|
14
|
+
title?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
score?: number;
|
|
17
|
+
by?: string;
|
|
18
|
+
time?: number;
|
|
19
|
+
descendants?: number;
|
|
20
|
+
type: string;
|
|
21
|
+
username?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* HackerNews user details
|
|
26
|
+
*/
|
|
27
|
+
interface HackerNewsUser {
|
|
28
|
+
id?: string;
|
|
29
|
+
karma?: number;
|
|
30
|
+
about?: string;
|
|
31
|
+
total_items_submitted?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface HackerNewsResult {
|
|
35
|
+
stories?: HackerNewsStory[];
|
|
36
|
+
user?: HackerNewsUser;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parameters for getting top stories
|
|
42
|
+
*/
|
|
43
|
+
const HackerNewsTopStoriesParameters = z.object({
|
|
44
|
+
num_stories: z.number().min(1).max(50).optional().default(10).describe('Number of stories to return'),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parameters for getting user details
|
|
49
|
+
*/
|
|
50
|
+
const HackerNewsUserParameters = z.object({
|
|
51
|
+
username: z.string().describe('Username of the Hacker News user'),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* HackerNews top stories tool
|
|
56
|
+
*/
|
|
57
|
+
export class HackerNewsTopStoriesTool extends BaseTool<typeof HackerNewsTopStoriesParameters, HackerNewsResult> {
|
|
58
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof HackerNewsTopStoriesParameters>, 'parameters'>>) {
|
|
59
|
+
super({
|
|
60
|
+
name: config?.name ?? 'hackernews.top_stories',
|
|
61
|
+
description: config?.description ?? 'Get top stories from Hacker News',
|
|
62
|
+
parameters: HackerNewsTopStoriesParameters,
|
|
63
|
+
category: config?.category ?? ToolCategory.WEB,
|
|
64
|
+
permissions: {
|
|
65
|
+
allowNetwork: true,
|
|
66
|
+
maxExecutionTimeMs: 30000,
|
|
67
|
+
...config?.permissions,
|
|
68
|
+
},
|
|
69
|
+
...config,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected async performExecute(
|
|
74
|
+
params: z.infer<typeof HackerNewsTopStoriesParameters>,
|
|
75
|
+
_context: ToolContext
|
|
76
|
+
): Promise<HackerNewsResult> {
|
|
77
|
+
try {
|
|
78
|
+
// Fetch top story IDs
|
|
79
|
+
const response = await fetch('https://hacker-news.firebaseio.com/v0/topstories.json');
|
|
80
|
+
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
throw new Error(`Failed to fetch top stories: ${response.status}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const storyIds = (await response.json()) as number[];
|
|
86
|
+
const topIds = storyIds.slice(0, params.num_stories);
|
|
87
|
+
|
|
88
|
+
// Fetch story details
|
|
89
|
+
const stories: HackerNewsStory[] = [];
|
|
90
|
+
for (const storyId of topIds) {
|
|
91
|
+
try {
|
|
92
|
+
const storyResponse = await fetch(`https://hacker-news.firebaseio.com/v0/item/${storyId}.json`);
|
|
93
|
+
if (storyResponse.ok) {
|
|
94
|
+
const story = (await storyResponse.json()) as HackerNewsStory;
|
|
95
|
+
story.username = story.by;
|
|
96
|
+
stories.push(story);
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
// Skip failed story fetches
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { stories };
|
|
104
|
+
} catch (error) {
|
|
105
|
+
return {
|
|
106
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* HackerNews user details tool
|
|
114
|
+
*/
|
|
115
|
+
export class HackerNewsUserTool extends BaseTool<typeof HackerNewsUserParameters, HackerNewsResult> {
|
|
116
|
+
constructor(config?: Partial<Omit<BaseToolConfig<typeof HackerNewsUserParameters>, 'parameters'>>) {
|
|
117
|
+
super({
|
|
118
|
+
name: config?.name ?? 'hackernews.user_details',
|
|
119
|
+
description: config?.description ?? 'Get details of a Hacker News user',
|
|
120
|
+
parameters: HackerNewsUserParameters,
|
|
121
|
+
category: config?.category ?? ToolCategory.WEB,
|
|
122
|
+
permissions: {
|
|
123
|
+
allowNetwork: true,
|
|
124
|
+
maxExecutionTimeMs: 30000,
|
|
125
|
+
...config?.permissions,
|
|
126
|
+
},
|
|
127
|
+
...config,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
protected async performExecute(
|
|
132
|
+
params: z.infer<typeof HackerNewsUserParameters>,
|
|
133
|
+
_context: ToolContext
|
|
134
|
+
): Promise<HackerNewsResult> {
|
|
135
|
+
try {
|
|
136
|
+
const response = await fetch(`https://hacker-news.firebaseio.com/v0/user/${params.username}.json`);
|
|
137
|
+
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
throw new Error(`Failed to fetch user details: ${response.status}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const userData = (await response.json()) as {
|
|
143
|
+
id?: string;
|
|
144
|
+
karma?: number;
|
|
145
|
+
about?: string;
|
|
146
|
+
submitted?: number[];
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
if (!userData) {
|
|
150
|
+
return {
|
|
151
|
+
error: `User ${params.username} not found`,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const user: HackerNewsUser = {
|
|
156
|
+
id: userData.id,
|
|
157
|
+
karma: userData.karma,
|
|
158
|
+
about: userData.about,
|
|
159
|
+
total_items_submitted: userData.submitted?.length || 0,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
return { user };
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return {
|
|
165
|
+
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* HackerNews toolkit
|
|
173
|
+
*/
|
|
174
|
+
export class HackerNewsToolkit {
|
|
175
|
+
static create(options?: { enableTopStories?: boolean; enableUserDetails?: boolean }): Array<HackerNewsTopStoriesTool | HackerNewsUserTool> {
|
|
176
|
+
const tools: Array<HackerNewsTopStoriesTool | HackerNewsUserTool> = [];
|
|
177
|
+
|
|
178
|
+
if (options?.enableTopStories !== false) {
|
|
179
|
+
tools.push(new HackerNewsTopStoriesTool());
|
|
180
|
+
}
|
|
181
|
+
if (options?.enableUserDetails !== false) {
|
|
182
|
+
tools.push(new HackerNewsUserTool());
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return tools;
|
|
186
|
+
}
|
|
187
|
+
}
|