matimo-examples 0.1.0-alpha.11
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/.env.example +49 -0
- package/LICENSE +21 -0
- package/README.md +525 -0
- package/agents/decorator-pattern-agent.ts +368 -0
- package/agents/factory-pattern-agent.ts +253 -0
- package/agents/langchain-agent.ts +146 -0
- package/edit/edit-decorator.ts +178 -0
- package/edit/edit-factory.ts +138 -0
- package/edit/edit-langchain.ts +292 -0
- package/execute/execute-decorator.ts +49 -0
- package/execute/execute-factory.ts +46 -0
- package/execute/execute-langchain.ts +232 -0
- package/github/github-decorator.ts +326 -0
- package/github/github-factory.ts +355 -0
- package/github/github-langchain.ts +206 -0
- package/github/github-with-approval.ts +228 -0
- package/gmail/README.md +345 -0
- package/gmail/gmail-decorator.ts +216 -0
- package/gmail/gmail-factory.ts +231 -0
- package/gmail/gmail-langchain.ts +201 -0
- package/hubspot/README.md +316 -0
- package/hubspot/hubspot-decorator.ts +180 -0
- package/hubspot/hubspot-factory.ts +188 -0
- package/hubspot/hubspot-langchain.ts +222 -0
- package/logger-example.ts +40 -0
- package/mailchimp/README.md +321 -0
- package/mailchimp/mailchimp-decorator.ts +277 -0
- package/mailchimp/mailchimp-factory.ts +187 -0
- package/mailchimp/mailchimp-langchain.ts +155 -0
- package/notion/README.md +293 -0
- package/notion/notion-decorator.ts +275 -0
- package/notion/notion-factory.ts +256 -0
- package/notion/notion-langchain.ts +237 -0
- package/package.json +79 -0
- package/postgres/README.md +188 -0
- package/postgres/postgres-decorator.ts +198 -0
- package/postgres/postgres-factory.ts +180 -0
- package/postgres/postgres-langchain.ts +213 -0
- package/postgres/postgres-with-approval.ts +344 -0
- package/read/read-decorator.ts +154 -0
- package/read/read-factory.ts +121 -0
- package/read/read-langchain.ts +273 -0
- package/search/search-decorator.ts +206 -0
- package/search/search-factory.ts +146 -0
- package/search/search-langchain.ts +255 -0
- package/slack/README.md +339 -0
- package/slack/slack-decorator.ts +245 -0
- package/slack/slack-factory.ts +226 -0
- package/slack/slack-langchain.ts +242 -0
- package/tsconfig.json +20 -0
- package/twilio/README.md +309 -0
- package/twilio/twilio-decorator.ts +288 -0
- package/twilio/twilio-factory.ts +238 -0
- package/twilio/twilio-langchain.ts +218 -0
- package/web/web-decorator.ts +52 -0
- package/web/web-factory.ts +70 -0
- package/web/web-langchain.ts +163 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ============================================================================
|
|
4
|
+
* GITHUB TOOLS - DECORATOR PATTERN EXAMPLE
|
|
5
|
+
* ============================================================================
|
|
6
|
+
*
|
|
7
|
+
* PATTERN: Decorator Pattern with @tool
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
9
|
+
* Uses TypeScript @tool decorators to wrap GitHub tool calls in a class.
|
|
10
|
+
*
|
|
11
|
+
* Use this pattern when:
|
|
12
|
+
* ✅ Building class-based applications
|
|
13
|
+
* ✅ Encapsulating tool logic in services
|
|
14
|
+
* ✅ Adding custom methods that combine multiple tools
|
|
15
|
+
* ✅ Need reusable tool wrappers
|
|
16
|
+
* ✅ Object-oriented design preferred
|
|
17
|
+
*
|
|
18
|
+
* SETUP:
|
|
19
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
20
|
+
* 1. Create .env file:
|
|
21
|
+
* GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
|
|
22
|
+
*
|
|
23
|
+
* 2. Get a GitHub Personal Access Token:
|
|
24
|
+
* https://github.com/settings/tokens
|
|
25
|
+
*
|
|
26
|
+
* USAGE:
|
|
27
|
+
* ─────────────────────────────────────────────────────────────────────────
|
|
28
|
+
* export GITHUB_TOKEN=your_token_here
|
|
29
|
+
* npm run github:decorator
|
|
30
|
+
*
|
|
31
|
+
* ============================================================================
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import 'dotenv/config';
|
|
35
|
+
import path from 'path';
|
|
36
|
+
import { fileURLToPath } from 'url';
|
|
37
|
+
import { MatimoInstance, tool, setGlobalMatimoInstance } from 'matimo';
|
|
38
|
+
|
|
39
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Decorator Pattern Agent - Uses @tool decorators for GitHub operations
|
|
43
|
+
*/
|
|
44
|
+
class GitHubDecoratorPatternAgent {
|
|
45
|
+
public matimo: MatimoInstance;
|
|
46
|
+
|
|
47
|
+
constructor(matimo: MatimoInstance) {
|
|
48
|
+
this.matimo = matimo;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* GitHub search repositories tool - manually execute with required parameters
|
|
53
|
+
*/
|
|
54
|
+
async searchRepositories(query: string): Promise<unknown> {
|
|
55
|
+
const result = await this.matimo.execute('github-search-repositories', {
|
|
56
|
+
query,
|
|
57
|
+
});
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* GitHub list-repositories tool - automatically executes via @tool decorator
|
|
63
|
+
*/
|
|
64
|
+
@tool('github-list-repositories')
|
|
65
|
+
async listRepositories(owner: string): Promise<unknown> {
|
|
66
|
+
// Decorator automatically calls: matimo.execute('github-list-repositories', { owner })
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* GitHub get-repository tool - automatically executes via @tool decorator
|
|
72
|
+
*/
|
|
73
|
+
@tool('github-get-repository')
|
|
74
|
+
async getRepository(owner: string, repo: string): Promise<unknown> {
|
|
75
|
+
// Decorator automatically calls: matimo.execute('github-get-repository', { owner, repo })
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* GitHub list-pull-requests tool - automatically executes via @tool decorator
|
|
81
|
+
*/
|
|
82
|
+
@tool('github-list-pull-requests')
|
|
83
|
+
async listPullRequests(owner: string, repo: string, state?: string): Promise<unknown> {
|
|
84
|
+
// Decorator automatically calls: matimo.execute('github-list-pull-requests', { owner, repo, state })
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* GitHub list-issues tool - automatically executes via @tool decorator
|
|
90
|
+
*/
|
|
91
|
+
@tool('github-list-issues')
|
|
92
|
+
async listIssues(owner: string, repo: string, state?: string): Promise<unknown> {
|
|
93
|
+
// Decorator automatically calls: matimo.execute('github-list-issues', { owner, repo, state })
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* GitHub list-commits tool - automatically executes via @tool decorator
|
|
99
|
+
*/
|
|
100
|
+
@tool('github-list-commits')
|
|
101
|
+
async listCommits(owner: string, repo: string): Promise<unknown> {
|
|
102
|
+
// Decorator automatically calls: matimo.execute('github-list-commits', { owner, repo })
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Run decorator pattern examples
|
|
109
|
+
*/
|
|
110
|
+
async function runDecoratorPatternExamples() {
|
|
111
|
+
const gitHubToken = process.env.GITHUB_TOKEN || 'ghp-default-fake-token';
|
|
112
|
+
|
|
113
|
+
console.info('╔════════════════════════════════════════════════════════╗');
|
|
114
|
+
console.info('║ GitHub Tools - Decorator Pattern ║');
|
|
115
|
+
console.info('║ (Uses @tool decorators for automatic execution) ║');
|
|
116
|
+
console.info('╚════════════════════════════════════════════════════════╝\n');
|
|
117
|
+
|
|
118
|
+
if (gitHubToken === 'ghp-default-fake-token') {
|
|
119
|
+
console.info('🔐 Warning: GITHUB_TOKEN not set in environment');
|
|
120
|
+
console.info(' Set it: export GITHUB_TOKEN="ghp_xxxx"');
|
|
121
|
+
console.info(' Get one from: https://github.com/settings/tokens\n');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.info(`🤖 GitHub Token: ${gitHubToken.substring(0, 10)}...\n`);
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Initialize Matimo with auto-discovery
|
|
128
|
+
console.info('🚀 Initializing Matimo...');
|
|
129
|
+
const matimo = await MatimoInstance.init({ autoDiscover: true });
|
|
130
|
+
setGlobalMatimoInstance(matimo);
|
|
131
|
+
|
|
132
|
+
const matimoTools = matimo.listTools();
|
|
133
|
+
const githubTools = matimoTools.filter((t) => t.name.startsWith('github'));
|
|
134
|
+
console.info(
|
|
135
|
+
`📦 Loaded ${matimoTools.length} total tools, ${githubTools.length} GitHub tools\n`
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// Create agent
|
|
139
|
+
const agent = new GitHubDecoratorPatternAgent(matimo);
|
|
140
|
+
|
|
141
|
+
console.info('🧪 Testing GitHub Tools with Decorator Pattern');
|
|
142
|
+
console.info('═'.repeat(60) + '\n');
|
|
143
|
+
|
|
144
|
+
// Example 1: Search repositories
|
|
145
|
+
console.info('🔍 Example 1: Search Repositories');
|
|
146
|
+
console.info('─'.repeat(60));
|
|
147
|
+
try {
|
|
148
|
+
const searchResult = await agent.searchRepositories('language:rust stars:>1000');
|
|
149
|
+
|
|
150
|
+
const searchData = (searchResult as any).data || searchResult;
|
|
151
|
+
|
|
152
|
+
if (
|
|
153
|
+
searchData.total_count !== undefined &&
|
|
154
|
+
searchData.items &&
|
|
155
|
+
Array.isArray(searchData.items)
|
|
156
|
+
) {
|
|
157
|
+
const totalPages = Math.ceil(searchData.total_count / searchData.items.length);
|
|
158
|
+
console.info(
|
|
159
|
+
`✅ Found ${searchData.total_count} Rust repositories (showing first ${Math.min(3, searchData.items.length)})`
|
|
160
|
+
);
|
|
161
|
+
searchData.items.slice(0, 3).forEach((repo: any, idx: number) => {
|
|
162
|
+
console.info(` ${idx + 1}. ${repo.full_name} (⭐ ${repo.stargazers_count})`);
|
|
163
|
+
});
|
|
164
|
+
if (searchData.items.length > 3) {
|
|
165
|
+
console.info(` ... and ${searchData.items.length - 3} more on this page`);
|
|
166
|
+
}
|
|
167
|
+
console.info(` 📄 Page 1 of ~${totalPages} pages`);
|
|
168
|
+
} else {
|
|
169
|
+
console.info(`❌ Failed: ${searchData.message || 'Unknown error'}`);
|
|
170
|
+
}
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Example 2: List organization repositories
|
|
176
|
+
console.info('\n📋 Example 2: List Organization Repositories');
|
|
177
|
+
console.info('─'.repeat(60));
|
|
178
|
+
try {
|
|
179
|
+
const listResult = await agent.listRepositories('rust-lang');
|
|
180
|
+
|
|
181
|
+
const listData = (listResult as any).data || listResult;
|
|
182
|
+
|
|
183
|
+
if (Array.isArray(listData)) {
|
|
184
|
+
console.info(`✅ Found ${listData.length} repositories in rust-lang:`);
|
|
185
|
+
listData.slice(0, 3).forEach((repo: any, idx: number) => {
|
|
186
|
+
console.info(` ${idx + 1}. ${repo.name}`);
|
|
187
|
+
});
|
|
188
|
+
if (listData.length > 3) {
|
|
189
|
+
console.info(` ... and ${listData.length - 3} more`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Use first repository for next examples
|
|
193
|
+
const firstRepo = listData[0];
|
|
194
|
+
console.info(`\n🎯 Using first repo: ${firstRepo.name}\n`);
|
|
195
|
+
|
|
196
|
+
// Example 3: Get repository details
|
|
197
|
+
console.info('🔎 Example 3: Get Repository Details');
|
|
198
|
+
console.info('─'.repeat(60));
|
|
199
|
+
try {
|
|
200
|
+
const repoResult = await agent.getRepository('rust-lang', firstRepo.name);
|
|
201
|
+
|
|
202
|
+
const repoData = (repoResult as any).data || repoResult;
|
|
203
|
+
if (repoData.id !== undefined) {
|
|
204
|
+
console.info(`✅ rust-lang/${firstRepo.name}`);
|
|
205
|
+
console.info(` Stars: ⭐ ${repoData.stargazers_count}`);
|
|
206
|
+
console.info(` Forks: 🍴 ${repoData.forks_count}`);
|
|
207
|
+
console.info(` Language: ${repoData.language || 'N/A'}`);
|
|
208
|
+
console.info(` Open Issues: ${repoData.open_issues_count}`);
|
|
209
|
+
} else {
|
|
210
|
+
console.info(`❌ Failed: ${repoData.message || 'Unknown error'}`);
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Example 4: List pull requests (manually execute to use per_page parameter)
|
|
217
|
+
console.info('\n🔀 Example 4: List Pull Requests');
|
|
218
|
+
console.info('─'.repeat(60));
|
|
219
|
+
console.info('📌 Checking: cli/cli (has active PRs)\n');
|
|
220
|
+
try {
|
|
221
|
+
const prsResult = await agent.matimo.execute('github-list-pull-requests', {
|
|
222
|
+
owner: 'cli',
|
|
223
|
+
repo: 'cli',
|
|
224
|
+
state: 'open',
|
|
225
|
+
per_page: 5,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
const prsData = (prsResult as any).data || prsResult;
|
|
229
|
+
const prList = Array.isArray(prsData) ? prsData : prsData?.pull_requests || [];
|
|
230
|
+
|
|
231
|
+
if (prList.length > 0) {
|
|
232
|
+
console.info(`✅ Found ${prList.length} open pull requests from cli/cli`);
|
|
233
|
+
prList.slice(0, 3).forEach((pr: any, idx: number) => {
|
|
234
|
+
console.info(` ${idx + 1}. #${pr.number}: ${pr.title}`);
|
|
235
|
+
console.info(` Created: ${new Date(pr.created_at).toLocaleDateString()}`);
|
|
236
|
+
});
|
|
237
|
+
if (prList.length > 3) {
|
|
238
|
+
console.info(` ... and ${prList.length - 3} more`);
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
console.info(`⚠️ No open pull requests found`);
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Example 5: List commits (manually execute to use per_page parameter)
|
|
248
|
+
console.info('\n📝 Example 5: List Commits');
|
|
249
|
+
console.info('─'.repeat(60));
|
|
250
|
+
console.info('📌 Checking: golang/go (has active commits)\n');
|
|
251
|
+
try {
|
|
252
|
+
const commitsResult = await agent.matimo.execute('github-list-commits', {
|
|
253
|
+
owner: 'golang',
|
|
254
|
+
repo: 'go',
|
|
255
|
+
per_page: 5,
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
const commitsData = (commitsResult as any).data || commitsResult;
|
|
259
|
+
const commitList = Array.isArray(commitsData) ? commitsData : commitsData?.commits || [];
|
|
260
|
+
|
|
261
|
+
if (commitList.length > 0) {
|
|
262
|
+
console.info(`✅ Found ${commitList.length} recent commits from golang/go`);
|
|
263
|
+
commitList.slice(0, 3).forEach((commit: any, idx: number) => {
|
|
264
|
+
const msg = commit.commit.message.split('\n')[0];
|
|
265
|
+
console.info(` ${idx + 1}. ${commit.commit.author?.name || 'Unknown'}`);
|
|
266
|
+
console.info(` ${msg}`);
|
|
267
|
+
console.info(` SHA: ${commit.sha.substring(0, 7)}`);
|
|
268
|
+
});
|
|
269
|
+
if (commitList.length > 3) {
|
|
270
|
+
console.info(` ... and ${commitList.length - 3} more`);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
console.info(`⚠️ No commits found`);
|
|
274
|
+
}
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Example 6: List releases (manually execute to use per_page parameter)
|
|
280
|
+
console.info('\n🎉 Example 6: List Releases');
|
|
281
|
+
console.info('─'.repeat(60));
|
|
282
|
+
try {
|
|
283
|
+
const releasesResult = await agent.matimo.execute('github-list-releases', {
|
|
284
|
+
owner: 'nodejs',
|
|
285
|
+
repo: 'node',
|
|
286
|
+
per_page: 5,
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
const releasesData = (releasesResult as any).data || releasesResult;
|
|
290
|
+
const releaseList = Array.isArray(releasesData) ? releasesData : [];
|
|
291
|
+
|
|
292
|
+
if (releaseList.length > 0) {
|
|
293
|
+
console.info(`✅ Found ${releaseList.length} releases from nodejs/node`);
|
|
294
|
+
releaseList.slice(0, 3).forEach((release: any, idx: number) => {
|
|
295
|
+
console.info(` ${idx + 1}. ${release.tag_name} - ${release.name || 'Unnamed'}`);
|
|
296
|
+
});
|
|
297
|
+
if (releaseList.length > 3) {
|
|
298
|
+
console.info(` ... and ${releaseList.length - 3} more`);
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
console.info(`⚠️ No releases found`);
|
|
302
|
+
}
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
console.info(`❌ Failed to list repositories: ${listData.message || 'Unknown error'}`);
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.info(`❌ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
console.info('\n' + '═'.repeat(60));
|
|
314
|
+
console.info('✨ Decorator Pattern Example Complete!');
|
|
315
|
+
console.info('═'.repeat(60) + '\n');
|
|
316
|
+
} catch (error) {
|
|
317
|
+
console.error('❌ Fatal error:', error instanceof Error ? error.message : String(error));
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Run the example
|
|
323
|
+
runDecoratorPatternExamples().catch((error) => {
|
|
324
|
+
console.error('❌ Unhandled error:', error);
|
|
325
|
+
process.exit(1);
|
|
326
|
+
});
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import 'dotenv/config';
|
|
4
|
+
import { MatimoInstance } from '@matimo/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* GitHub Factory Pattern Example
|
|
8
|
+
* ================================
|
|
9
|
+
*
|
|
10
|
+
* Demonstrates the simplest way to use Matimo tools: direct execution via matimo.execute().
|
|
11
|
+
* This pattern is best for:
|
|
12
|
+
* - Simple scripts and CLIs
|
|
13
|
+
* - Direct tool invocation
|
|
14
|
+
* - Learning Matimo basics
|
|
15
|
+
*
|
|
16
|
+
* Setup:
|
|
17
|
+
* ------
|
|
18
|
+
* 1. Get a GitHub Personal Access Token (PAT):
|
|
19
|
+
* Visit: https://github.com/settings/tokens
|
|
20
|
+
* Create token with: repo, read:org scopes (for public repo access)
|
|
21
|
+
*
|
|
22
|
+
* 2. Set environment variable:
|
|
23
|
+
* export GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
24
|
+
*
|
|
25
|
+
* 3. Run this example:
|
|
26
|
+
* pnpm github:factory
|
|
27
|
+
*
|
|
28
|
+
* Available GitHub Tools:
|
|
29
|
+
* -----------------------
|
|
30
|
+
* SEARCH:
|
|
31
|
+
* - github-search-repositories: Find repositories by query (language, stars, etc.)
|
|
32
|
+
* - github-search-code: Search code across repositories
|
|
33
|
+
* - github-search-issues: Find issues and pull requests
|
|
34
|
+
* - github-search-users: Find GitHub users
|
|
35
|
+
*
|
|
36
|
+
* REPOSITORIES:
|
|
37
|
+
* - github-list-repositories: List repos in an org/user
|
|
38
|
+
* - github-get-repository: Get detailed repo info
|
|
39
|
+
* - github-create-repository: Create new repo (write access required)
|
|
40
|
+
* - github-delete-repository: Delete a repo (write access required)
|
|
41
|
+
*
|
|
42
|
+
* ISSUES:
|
|
43
|
+
* - github-list-issues: List issues in a repo
|
|
44
|
+
* - github-create-issue: Create issue (write access required)
|
|
45
|
+
* - github-get-issue: Get issue details
|
|
46
|
+
* - github-update-issue: Update issue (write access required)
|
|
47
|
+
*
|
|
48
|
+
* PULL REQUESTS:
|
|
49
|
+
* - github-list-pull-requests: List PRs in a repo
|
|
50
|
+
* - github-create-pull-request: Create PR (write access required)
|
|
51
|
+
* - github-merge-pull-request: Merge PR (write access required)
|
|
52
|
+
*
|
|
53
|
+
* COMMITS:
|
|
54
|
+
* - github-list-commits: List commits in repo
|
|
55
|
+
*
|
|
56
|
+
* COLLABORATORS:
|
|
57
|
+
* - github-list-collaborators: List repo collaborators
|
|
58
|
+
* - github-add-collaborator: Add collaborator (admin access required)
|
|
59
|
+
*
|
|
60
|
+
* RELEASES:
|
|
61
|
+
* - github-list-releases: List releases
|
|
62
|
+
* - github-create-release: Create release (write access required)
|
|
63
|
+
*
|
|
64
|
+
* CODE SCANNING:
|
|
65
|
+
* - github-list-code-alerts: List security alerts (Advanced Security)
|
|
66
|
+
* - github-update-code-alert: Update alert status (Advanced Security)
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
// Type definitions for API responses
|
|
70
|
+
interface SearchRepositoryResult {
|
|
71
|
+
total_count: number;
|
|
72
|
+
items: Array<{
|
|
73
|
+
id: number;
|
|
74
|
+
name: string;
|
|
75
|
+
full_name: string;
|
|
76
|
+
description: string;
|
|
77
|
+
url: string;
|
|
78
|
+
stargazers_count: number;
|
|
79
|
+
forks_count: number;
|
|
80
|
+
language: string | null;
|
|
81
|
+
updated_at: string;
|
|
82
|
+
}>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface Repository {
|
|
86
|
+
id: number;
|
|
87
|
+
name: string;
|
|
88
|
+
full_name: string;
|
|
89
|
+
description: string | null;
|
|
90
|
+
url: string;
|
|
91
|
+
stargazers_count: number;
|
|
92
|
+
forks_count: number;
|
|
93
|
+
language: string | null;
|
|
94
|
+
open_issues_count: number;
|
|
95
|
+
topics: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface PullRequest {
|
|
99
|
+
id: number;
|
|
100
|
+
number: number;
|
|
101
|
+
title: string;
|
|
102
|
+
body: string | null;
|
|
103
|
+
state: string;
|
|
104
|
+
created_at: string;
|
|
105
|
+
updated_at: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface Commit {
|
|
109
|
+
sha: string;
|
|
110
|
+
commit: {
|
|
111
|
+
author: {
|
|
112
|
+
name: string;
|
|
113
|
+
email: string;
|
|
114
|
+
date: string;
|
|
115
|
+
};
|
|
116
|
+
message: string;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface Release {
|
|
121
|
+
id: number;
|
|
122
|
+
tag_name: string;
|
|
123
|
+
name: string | null;
|
|
124
|
+
body: string | null;
|
|
125
|
+
draft: boolean;
|
|
126
|
+
prerelease: boolean;
|
|
127
|
+
created_at: string;
|
|
128
|
+
published_at: string | null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function main() {
|
|
132
|
+
console.info('\n╔════════════════════════════════════════════════════════════╗');
|
|
133
|
+
console.info('║ 🐙 GitHub Factory Pattern Example ║');
|
|
134
|
+
console.info('║ Direct tool execution using matimo.execute() ║');
|
|
135
|
+
console.info('╚════════════════════════════════════════════════════════════╝\n');
|
|
136
|
+
|
|
137
|
+
// Check for GitHub token
|
|
138
|
+
const token = process.env.GITHUB_TOKEN;
|
|
139
|
+
if (!token) {
|
|
140
|
+
console.error('\n❌ Error: GITHUB_TOKEN environment variable not set');
|
|
141
|
+
console.info('\n📖 Setup Instructions:');
|
|
142
|
+
console.info(' 1. Create a GitHub Personal Access Token:');
|
|
143
|
+
console.info(' https://github.com/settings/tokens');
|
|
144
|
+
console.info(' 2. Set the environment variable:');
|
|
145
|
+
console.info(' export GITHUB_TOKEN="ghp_xxxx..."');
|
|
146
|
+
console.info(' 3. Run this example again:');
|
|
147
|
+
console.info(' pnpm github:factory\n');
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
// Initialize Matimo with auto-discovery
|
|
153
|
+
const matimo = await MatimoInstance.init({
|
|
154
|
+
autoDiscover: true,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Get all GitHub tools (filter by prefix)
|
|
158
|
+
const allTools = matimo.listTools();
|
|
159
|
+
const githubTools = allTools.filter((t) => t.name.startsWith('github-'));
|
|
160
|
+
console.info(`📚 Loaded ${githubTools.length} GitHub tools from Matimo\n`);
|
|
161
|
+
|
|
162
|
+
// Example 1: Search repositories
|
|
163
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
164
|
+
console.info('Example 1: Search TypeScript Repositories');
|
|
165
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
166
|
+
console.info('📦 Searching: language:typescript fork:false stars:>100\n');
|
|
167
|
+
try {
|
|
168
|
+
const searchResults = await matimo.execute('github-search-repositories', {
|
|
169
|
+
query: 'language:typescript fork:false stars:>100',
|
|
170
|
+
});
|
|
171
|
+
const searchData = (searchResults as any).data || searchResults;
|
|
172
|
+
console.info(`✅ Found ${searchData?.total_count} TypeScript repositories\n`);
|
|
173
|
+
if (searchData?.items && searchData.items.length > 0) {
|
|
174
|
+
console.info('Top 3 Results:');
|
|
175
|
+
searchData.items.slice(0, 3).forEach((repo: any, idx: number) => {
|
|
176
|
+
console.info(` ${idx + 1}. ${repo.full_name} ⭐ ${repo.stargazers_count}`);
|
|
177
|
+
console.info(` ${repo.description || 'No description'}\n`);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} catch (error: any) {
|
|
181
|
+
console.error(`❌ Search failed: ${error.message}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Example 2: Get repository details
|
|
185
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
186
|
+
console.info('Example 2: Get Repository Details');
|
|
187
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
188
|
+
console.info('🔎 Getting details for: kubernetes/kubernetes\n');
|
|
189
|
+
try {
|
|
190
|
+
const repo = await matimo.execute('github-get-repository', {
|
|
191
|
+
owner: 'kubernetes',
|
|
192
|
+
repo: 'kubernetes',
|
|
193
|
+
});
|
|
194
|
+
const repoData = (repo as any).data || repo;
|
|
195
|
+
if (repoData && repoData.full_name) {
|
|
196
|
+
console.info(`✅ Repository: ${repoData.full_name}`);
|
|
197
|
+
console.info(` Description: ${repoData.description}`);
|
|
198
|
+
console.info(` Stars: ⭐ ${repoData.stargazers_count?.toLocaleString()}`);
|
|
199
|
+
console.info(` Language: ${repoData.language || 'Mixed'}`);
|
|
200
|
+
console.info(` Open Issues: ${repoData.open_issues_count}`);
|
|
201
|
+
if (repoData.topics?.length > 0) {
|
|
202
|
+
console.info(` Topics: ${repoData.topics.join(', ')}`);
|
|
203
|
+
}
|
|
204
|
+
console.info();
|
|
205
|
+
} else {
|
|
206
|
+
console.error(
|
|
207
|
+
`❌ Get repository returned unexpected format: ${JSON.stringify(repoData).slice(0, 100)}`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
} catch (error: any) {
|
|
211
|
+
console.error(`❌ Get repository failed: ${error.message}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Example 3: List repositories
|
|
215
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
216
|
+
console.info('Example 3: List Organization Repositories');
|
|
217
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
218
|
+
console.info('📋 Listing top 5 Node.js repositories\n');
|
|
219
|
+
try {
|
|
220
|
+
const repos = await matimo.execute('github-list-repositories', {
|
|
221
|
+
owner: 'nodejs',
|
|
222
|
+
type: 'public',
|
|
223
|
+
per_page: 5,
|
|
224
|
+
});
|
|
225
|
+
const reposData = (repos as any).data || repos;
|
|
226
|
+
const repoList = Array.isArray(reposData) ? reposData : reposData?.repositories || [];
|
|
227
|
+
if (repoList.length > 0) {
|
|
228
|
+
console.info(`✅ Found ${repoList.length} repositories from nodejs org:\n`);
|
|
229
|
+
repoList.forEach((repo: any, idx: number) => {
|
|
230
|
+
console.info(` ${idx + 1}. ${repo.name} ⭐ ${repo.stargazers_count}`);
|
|
231
|
+
console.info(` Full Name: ${repo.full_name}`);
|
|
232
|
+
console.info(` Language: ${repo.language || 'Mixed'}`);
|
|
233
|
+
console.info();
|
|
234
|
+
});
|
|
235
|
+
} else {
|
|
236
|
+
console.info(`⚠️ No repositories found or unexpected response format`);
|
|
237
|
+
}
|
|
238
|
+
} catch (error: any) {
|
|
239
|
+
console.error(`❌ List repositories failed: ${error.message}`);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Example 4: List pull requests
|
|
243
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
244
|
+
console.info('Example 4: List Open Pull Requests');
|
|
245
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
246
|
+
console.info('🔀 Listing PRs from: cli/cli\n');
|
|
247
|
+
try {
|
|
248
|
+
const prs = await matimo.execute('github-list-pull-requests', {
|
|
249
|
+
owner: 'cli',
|
|
250
|
+
repo: 'cli',
|
|
251
|
+
state: 'open',
|
|
252
|
+
per_page: 5,
|
|
253
|
+
});
|
|
254
|
+
const prsData = (prs as any).data || prs;
|
|
255
|
+
const prList = Array.isArray(prsData) ? prsData : prsData?.pull_requests || [];
|
|
256
|
+
if (prList.length > 0) {
|
|
257
|
+
console.info(`✅ Found ${prList.length} open pull requests:\n`);
|
|
258
|
+
prList.forEach((pr: any, idx: number) => {
|
|
259
|
+
console.info(` ${idx + 1}. #${pr.number}: ${pr.title}`);
|
|
260
|
+
console.info(
|
|
261
|
+
` Status: ${pr.state} | Created: ${new Date(pr.created_at).toLocaleDateString()}`
|
|
262
|
+
);
|
|
263
|
+
console.info();
|
|
264
|
+
});
|
|
265
|
+
} else {
|
|
266
|
+
console.info(`⚠️ No open pull requests found or unexpected response format`);
|
|
267
|
+
}
|
|
268
|
+
} catch (error: any) {
|
|
269
|
+
console.error(`❌ List pull requests failed: ${error.message}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Example 5: List commits
|
|
273
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
274
|
+
console.info('Example 5: List Recent Commits');
|
|
275
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
276
|
+
console.info('📝 Listing commits from: golang/go\n');
|
|
277
|
+
try {
|
|
278
|
+
const commits = await matimo.execute('github-list-commits', {
|
|
279
|
+
owner: 'golang',
|
|
280
|
+
repo: 'go',
|
|
281
|
+
per_page: 5,
|
|
282
|
+
});
|
|
283
|
+
const commitsData = (commits as any).data || commits;
|
|
284
|
+
const commitList = Array.isArray(commitsData) ? commitsData : commitsData?.commits || [];
|
|
285
|
+
if (commitList.length > 0) {
|
|
286
|
+
console.info(`✅ Found ${commitList.length} recent commits:\n`);
|
|
287
|
+
commitList.slice(0, 3).forEach((commit: any, idx: number) => {
|
|
288
|
+
const msg = commit.commit.message.split('\n')[0];
|
|
289
|
+
console.info(` ${idx + 1}. ${commit.commit.author.name}`);
|
|
290
|
+
console.info(` ${msg}`);
|
|
291
|
+
console.info(` SHA: ${commit.sha.substring(0, 7)}`);
|
|
292
|
+
console.info();
|
|
293
|
+
});
|
|
294
|
+
} else {
|
|
295
|
+
console.info(`⚠️ No commits found or unexpected response format`);
|
|
296
|
+
}
|
|
297
|
+
} catch (error: any) {
|
|
298
|
+
console.error(`❌ List commits failed: ${error.message}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Example 6: List releases
|
|
302
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
303
|
+
console.info('Example 6: List Releases');
|
|
304
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
305
|
+
console.info('🎉 Listing releases from: nodejs/node\n');
|
|
306
|
+
try {
|
|
307
|
+
const releases = await matimo.execute('github-list-releases', {
|
|
308
|
+
owner: 'nodejs',
|
|
309
|
+
repo: 'node',
|
|
310
|
+
per_page: 5,
|
|
311
|
+
});
|
|
312
|
+
const releasesData = (releases as any).data || releases;
|
|
313
|
+
const releaseList = Array.isArray(releasesData) ? releasesData : releasesData?.releases || [];
|
|
314
|
+
if (releaseList.length > 0) {
|
|
315
|
+
console.info(`✅ Found ${releaseList.length} releases:\n`);
|
|
316
|
+
releaseList.slice(0, 3).forEach((release: any, idx: number) => {
|
|
317
|
+
console.info(` ${idx + 1}. ${release.tag_name} "${release.name}"`);
|
|
318
|
+
console.info(` Published: ${new Date(release.published_at!).toLocaleDateString()}`);
|
|
319
|
+
console.info();
|
|
320
|
+
});
|
|
321
|
+
} else {
|
|
322
|
+
console.info(`⚠️ No releases found or unexpected response format`);
|
|
323
|
+
}
|
|
324
|
+
} catch (error: any) {
|
|
325
|
+
console.error(`❌ List releases failed: ${error.message}`);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Example 7: Search code
|
|
329
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
330
|
+
console.info('Example 7: Search Code');
|
|
331
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
332
|
+
console.info('🔍 Searching for: "async function" in React\n');
|
|
333
|
+
try {
|
|
334
|
+
const codeResults = await matimo.execute('github-search-code', {
|
|
335
|
+
query: 'language:typescript "async function" repo:facebook/react',
|
|
336
|
+
});
|
|
337
|
+
const codeData = (codeResults as any).data || codeResults;
|
|
338
|
+
console.info(`✅ Found ${codeData?.total_count} code matches in React\n`);
|
|
339
|
+
} catch (error: any) {
|
|
340
|
+
console.error(`❌ Search code failed: ${error.message}`);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
344
|
+
console.info('✅ All factory pattern examples completed!');
|
|
345
|
+
console.info('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
|
|
346
|
+
} catch (error: any) {
|
|
347
|
+
console.error('\n❌ Fatal Error:', error.message);
|
|
348
|
+
if (error.details) {
|
|
349
|
+
console.error('Details:', JSON.stringify(error.details, null, 2));
|
|
350
|
+
}
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
main();
|