@eldrforge/ai-service 0.1.13 → 0.1.14

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.
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Example 5: Custom Tool Integration
4
+ *
5
+ * This example demonstrates how to create and register custom tools
6
+ * that extend the AI's capabilities for your specific use case.
7
+ *
8
+ * Usage:
9
+ * npx tsx examples/05-custom-tools.ts
10
+ */
11
+
12
+ /* eslint-disable no-console */
13
+
14
+ import {
15
+ createToolRegistry,
16
+ runAgentic,
17
+ type Tool,
18
+ type ToolContext,
19
+ } from '@eldrforge/ai-service';
20
+ import { execSync } from 'child_process';
21
+ import * as fs from 'fs/promises';
22
+ import * as path from 'path';
23
+
24
+ /**
25
+ * Custom tool: Check test coverage
26
+ */
27
+ const checkTestCoverage: Tool = {
28
+ name: 'check_test_coverage',
29
+ description: 'Check test coverage for the project or specific files',
30
+ parameters: {
31
+ type: 'object',
32
+ properties: {
33
+ filePath: {
34
+ type: 'string',
35
+ description: 'Optional specific file to check coverage for',
36
+ },
37
+ },
38
+ },
39
+ execute: async (params: { filePath?: string }, context?: ToolContext) => {
40
+ try {
41
+ const cmd = params.filePath
42
+ ? `npm test -- --coverage --testPathPattern="${params.filePath}"`
43
+ : 'npm test -- --coverage --silent 2>&1';
44
+
45
+ const output = execSync(cmd, {
46
+ encoding: 'utf8',
47
+ cwd: context?.workingDirectory || process.cwd(),
48
+ });
49
+
50
+ // Parse coverage from output
51
+ const coverageMatch = output.match(/All files.*?(\d+\.?\d*)/);
52
+ const coverage = coverageMatch ? parseFloat(coverageMatch[1]) : 0;
53
+
54
+ return {
55
+ success: true,
56
+ coverage: `${coverage}%`,
57
+ message: `Test coverage: ${coverage}%`,
58
+ };
59
+ } catch (error) {
60
+ return {
61
+ success: false,
62
+ error: error instanceof Error ? error.message : 'Unknown error',
63
+ };
64
+ }
65
+ },
66
+ };
67
+
68
+ /**
69
+ * Custom tool: Check for linter errors
70
+ */
71
+ const checkLinterErrors: Tool = {
72
+ name: 'check_linter_errors',
73
+ description: 'Check for linter/ESLint errors in the codebase',
74
+ parameters: {
75
+ type: 'object',
76
+ properties: {
77
+ filePath: {
78
+ type: 'string',
79
+ description: 'Optional specific file to lint',
80
+ },
81
+ },
82
+ },
83
+ execute: async (params: { filePath?: string }, context?: ToolContext) => {
84
+ try {
85
+ const target = params.filePath || '.';
86
+ const cmd = `npx eslint ${target} --format json`;
87
+
88
+ const output = execSync(cmd, {
89
+ encoding: 'utf8',
90
+ cwd: context?.workingDirectory || process.cwd(),
91
+ });
92
+
93
+ const results = JSON.parse(output);
94
+ const errorCount = results.reduce((sum: number, file: any) => sum + file.errorCount, 0);
95
+ const warningCount = results.reduce((sum: number, file: any) => sum + file.warningCount, 0);
96
+
97
+ return {
98
+ success: errorCount === 0,
99
+ errors: errorCount,
100
+ warnings: warningCount,
101
+ message: `Found ${errorCount} errors and ${warningCount} warnings`,
102
+ };
103
+ } catch (error) {
104
+ return {
105
+ success: false,
106
+ error: error instanceof Error ? error.message : 'Unknown error',
107
+ };
108
+ }
109
+ },
110
+ };
111
+
112
+ /**
113
+ * Custom tool: Analyze package dependencies
114
+ */
115
+ const analyzePackageDeps: Tool = {
116
+ name: 'analyze_package_dependencies',
117
+ description: 'Analyze package.json dependencies and check for outdated packages',
118
+ parameters: {
119
+ type: 'object',
120
+ properties: {},
121
+ },
122
+ execute: async (_params: any, context?: ToolContext) => {
123
+ try {
124
+ const packageJsonPath = path.join(
125
+ context?.workingDirectory || process.cwd(),
126
+ 'package.json'
127
+ );
128
+
129
+ const packageJson = JSON.parse(
130
+ await fs.readFile(packageJsonPath, 'utf8')
131
+ );
132
+
133
+ const deps = packageJson.dependencies || {};
134
+ const devDeps = packageJson.devDependencies || {};
135
+ const totalDeps = Object.keys(deps).length + Object.keys(devDeps).length;
136
+
137
+ // Check for outdated packages
138
+ let outdatedOutput = '';
139
+ try {
140
+ outdatedOutput = execSync('npm outdated --json', {
141
+ encoding: 'utf8',
142
+ cwd: context?.workingDirectory || process.cwd(),
143
+ });
144
+ } catch {
145
+ // npm outdated exits with code 1 if there are outdated packages
146
+ }
147
+
148
+ const outdated = outdatedOutput ? JSON.parse(outdatedOutput) : {};
149
+ const outdatedCount = Object.keys(outdated).length;
150
+
151
+ return {
152
+ success: true,
153
+ totalDependencies: totalDeps,
154
+ outdatedPackages: outdatedCount,
155
+ dependencies: Object.keys(deps),
156
+ devDependencies: Object.keys(devDeps),
157
+ outdatedDetails: outdated,
158
+ };
159
+ } catch (error) {
160
+ return {
161
+ success: false,
162
+ error: error instanceof Error ? error.message : 'Unknown error',
163
+ };
164
+ }
165
+ },
166
+ };
167
+
168
+ async function main() {
169
+ try {
170
+ console.log('🔧 Creating tool registry with custom tools...\n');
171
+
172
+ // Create tool registry
173
+ const registry = createToolRegistry({
174
+ workingDirectory: process.cwd(),
175
+ });
176
+
177
+ // Register custom tools
178
+ registry.register(checkTestCoverage);
179
+ registry.register(checkLinterErrors);
180
+ registry.register(analyzePackageDeps);
181
+
182
+ console.log('✅ Registered custom tools:');
183
+ console.log(' - check_test_coverage');
184
+ console.log(' - check_linter_errors');
185
+ console.log(' - analyze_package_dependencies');
186
+ console.log('');
187
+
188
+ // Create a conversation that uses these tools
189
+ const messages = [
190
+ {
191
+ role: 'system' as const,
192
+ content: `You are a code quality analyst. Use the available tools to assess the project's health.
193
+
194
+ Your task:
195
+ 1. Check test coverage
196
+ 2. Check for linter errors
197
+ 3. Analyze package dependencies
198
+
199
+ Then provide a summary report of the project's code quality status.`,
200
+ },
201
+ {
202
+ role: 'user' as const,
203
+ content: 'Please analyze the current project and provide a code quality report.',
204
+ },
205
+ ];
206
+
207
+ console.log('🤖 Running AI analysis with custom tools...\n');
208
+
209
+ const result = await runAgentic({
210
+ messages,
211
+ tools: registry,
212
+ model: 'gpt-4o-mini',
213
+ maxIterations: 10,
214
+ });
215
+
216
+ console.log('✨ Analysis Complete!\n');
217
+ console.log('═'.repeat(70));
218
+ console.log(result.finalMessage);
219
+ console.log('═'.repeat(70));
220
+ console.log('');
221
+ console.log(`📊 Tool calls made: ${result.toolCallsExecuted}`);
222
+ console.log(`🔄 Iterations: ${result.iterations}`);
223
+ console.log('');
224
+
225
+ // Show which tools were used
226
+ const toolUsage: Record<string, number> = {};
227
+ result.toolMetrics.forEach(metric => {
228
+ toolUsage[metric.name] = (toolUsage[metric.name] || 0) + 1;
229
+ });
230
+
231
+ console.log('🔧 Tools used:');
232
+ Object.entries(toolUsage).forEach(([tool, count]) => {
233
+ console.log(` - ${tool}: ${count}x`);
234
+ });
235
+
236
+ } catch (error) {
237
+ console.error('❌ Error:', error instanceof Error ? error.message : String(error));
238
+ process.exit(1);
239
+ }
240
+ }
241
+
242
+ main();
243
+
@@ -0,0 +1,320 @@
1
+ # Examples
2
+
3
+ This directory contains practical examples demonstrating how to use `@eldrforge/ai-service` as a standalone library.
4
+
5
+ ## Prerequisites
6
+
7
+ Before running these examples, ensure you have:
8
+
9
+ 1. **Node.js** (v18 or later)
10
+ 2. **OpenAI API Key** set as environment variable:
11
+ ```bash
12
+ export OPENAI_API_KEY=sk-...
13
+ ```
14
+ 3. **tsx** for running TypeScript (or compile with `tsc` first):
15
+ ```bash
16
+ npm install -g tsx
17
+ ```
18
+
19
+ ## Examples Overview
20
+
21
+ ### 1. Simple Commit Message Generation
22
+ **File:** `01-simple-commit.ts`
23
+
24
+ The most basic example - generates a commit message from staged git changes.
25
+
26
+ ```bash
27
+ # Stage some changes
28
+ git add .
29
+
30
+ # Run the example
31
+ npx tsx examples/01-simple-commit.ts
32
+ ```
33
+
34
+ **Features:**
35
+ - Reads staged git changes
36
+ - Generates commit message using agentic AI
37
+ - Shows tool usage statistics
38
+ - Suggests commit splits if appropriate
39
+
40
+ **Use Case:** Quick commit message generation without interaction
41
+
42
+ ---
43
+
44
+ ### 2. Release Notes Generation
45
+ **File:** `02-release-notes.ts`
46
+
47
+ Generates comprehensive release notes by analyzing changes between two git references.
48
+
49
+ ```bash
50
+ # Generate release notes from v1.0.0 to v1.1.0
51
+ npx tsx examples/02-release-notes.ts v1.0.0 v1.1.0
52
+
53
+ # Or from a tag to HEAD
54
+ npx tsx examples/02-release-notes.ts v1.0.0 HEAD
55
+ ```
56
+
57
+ **Features:**
58
+ - Analyzes commit history and diffs
59
+ - Uses 13 specialized tools for deep analysis
60
+ - Generates detailed markdown release notes
61
+ - Saves output to files
62
+ - Shows tool usage metrics
63
+
64
+ **Use Case:** Automated release note generation for GitHub releases, changelogs, etc.
65
+
66
+ ---
67
+
68
+ ### 3. Interactive Commit Workflow
69
+ **File:** `03-interactive-commit.ts`
70
+
71
+ An interactive workflow that lets users review, edit, and approve commit messages.
72
+
73
+ ```bash
74
+ # Stage changes first
75
+ git add .
76
+
77
+ # Run interactive workflow
78
+ npx tsx examples/03-interactive-commit.ts
79
+ ```
80
+
81
+ **Features:**
82
+ - Generates initial commit message
83
+ - Interactive review loop:
84
+ - **[c]** Confirm and create commit
85
+ - **[e]** Edit in your editor
86
+ - **[s]** Skip and cancel
87
+ - Automatically creates the git commit
88
+ - Full TTY support
89
+
90
+ **Use Case:** Daily development workflow with human oversight
91
+
92
+ **Requirements:** Must run in a terminal (TTY), not in piped or non-interactive environments.
93
+
94
+ ---
95
+
96
+ ### 4. Custom Storage Adapter
97
+ **File:** `04-custom-storage.ts`
98
+
99
+ Demonstrates how to implement custom storage adapters for saving AI-generated content.
100
+
101
+ ```bash
102
+ npx tsx examples/04-custom-storage.ts
103
+ ```
104
+
105
+ **Features:**
106
+ - Custom storage adapter implementation
107
+ - Structured output directory
108
+ - Saves multiple artifacts:
109
+ - Commit message
110
+ - Metadata (JSON)
111
+ - Tool metrics (JSON)
112
+ - Example cloud storage adapter structure
113
+ - Timestamped output organization
114
+
115
+ **Use Case:**
116
+ - Integrating with cloud storage (S3, Google Cloud Storage)
117
+ - Saving AI artifacts for auditing
118
+ - Custom file organization
119
+
120
+ ---
121
+
122
+ ### 5. Custom Tool Integration
123
+ **File:** `05-custom-tools.ts`
124
+
125
+ Shows how to create and register custom tools that extend the AI's capabilities.
126
+
127
+ ```bash
128
+ npx tsx examples/05-custom-tools.ts
129
+ ```
130
+
131
+ **Features:**
132
+ - Three custom tools:
133
+ - `check_test_coverage` - Analyze test coverage
134
+ - `check_linter_errors` - Find ESLint errors
135
+ - `analyze_package_dependencies` - Check dependencies
136
+ - Tool registry management
137
+ - Custom AI workflows
138
+ - Code quality analysis example
139
+
140
+ **Use Case:**
141
+ - Domain-specific code analysis
142
+ - Custom CI/CD integrations
143
+ - Project-specific quality checks
144
+
145
+ ---
146
+
147
+ ## Running the Examples
148
+
149
+ ### Option 1: Using tsx (Recommended)
150
+
151
+ ```bash
152
+ # Run directly with tsx
153
+ npx tsx examples/01-simple-commit.ts
154
+ ```
155
+
156
+ ### Option 2: Compile then run
157
+
158
+ ```bash
159
+ # Compile TypeScript
160
+ npx tsc examples/*.ts --outDir examples/dist
161
+
162
+ # Run compiled JavaScript
163
+ node examples/dist/01-simple-commit.js
164
+ ```
165
+
166
+ ### Option 3: Install tsx globally
167
+
168
+ ```bash
169
+ # Install tsx globally
170
+ npm install -g tsx
171
+
172
+ # Run examples
173
+ tsx examples/01-simple-commit.ts
174
+ ```
175
+
176
+ ## Configuration
177
+
178
+ All examples can be configured by:
179
+
180
+ 1. **Environment Variables:**
181
+ ```bash
182
+ export OPENAI_API_KEY=sk-...
183
+ export EDITOR=code --wait
184
+ ```
185
+
186
+ 2. **Modifying the code:**
187
+ - Change `model` parameter (e.g., `gpt-4o-mini`, `gpt-4o`)
188
+ - Adjust `maxIterations` for more/less thorough analysis
189
+ - Add custom logic specific to your needs
190
+
191
+ ## Integration Patterns
192
+
193
+ ### As a CLI Tool
194
+
195
+ Add to your `package.json`:
196
+
197
+ ```json
198
+ {
199
+ "scripts": {
200
+ "commit": "tsx examples/01-simple-commit.ts",
201
+ "release": "tsx examples/02-release-notes.ts"
202
+ }
203
+ }
204
+ ```
205
+
206
+ Then use:
207
+ ```bash
208
+ npm run commit
209
+ npm run release v1.0.0 v1.1.0
210
+ ```
211
+
212
+ ### In Your Own Scripts
213
+
214
+ ```typescript
215
+ import { runAgenticCommit } from '@eldrforge/ai-service';
216
+
217
+ // Your custom logic here
218
+ const result = await runAgenticCommit({
219
+ changedFiles,
220
+ diffContent,
221
+ model: 'gpt-4o-mini',
222
+ });
223
+
224
+ // Do something with result.commitMessage
225
+ ```
226
+
227
+ ### In a Web Service
228
+
229
+ ```typescript
230
+ import express from 'express';
231
+ import { runAgenticCommit } from '@eldrforge/ai-service';
232
+
233
+ const app = express();
234
+
235
+ app.post('/api/commit-message', async (req, res) => {
236
+ const { changedFiles, diffContent } = req.body;
237
+
238
+ const result = await runAgenticCommit({
239
+ changedFiles,
240
+ diffContent,
241
+ model: 'gpt-4o-mini',
242
+ });
243
+
244
+ res.json({ message: result.commitMessage });
245
+ });
246
+ ```
247
+
248
+ ## Cost Considerations
249
+
250
+ Approximate token usage and costs (as of 2024, with GPT-4o):
251
+
252
+ | Example | Tokens | Est. Cost | Time |
253
+ |---------|--------|-----------|------|
254
+ | Simple Commit | 5,000-20,000 | $0.05-$0.20 | 10-30s |
255
+ | Release Notes | 20,000-100,000 | $0.20-$1.00 | 30-180s |
256
+ | Interactive Commit | 5,000-30,000 | $0.05-$0.30 | 10-60s |
257
+ | Custom Storage | 5,000-20,000 | $0.05-$0.20 | 10-30s |
258
+ | Custom Tools | 10,000-40,000 | $0.10-$0.40 | 20-60s |
259
+
260
+ Use `gpt-4o-mini` for 60% cost reduction with slightly lower quality.
261
+
262
+ ## Troubleshooting
263
+
264
+ ### "OpenAI API key not found"
265
+
266
+ Set your API key:
267
+ ```bash
268
+ export OPENAI_API_KEY=sk-...
269
+ ```
270
+
271
+ ### "No staged changes found"
272
+
273
+ Stage changes first:
274
+ ```bash
275
+ git add .
276
+ # or
277
+ git add <specific-files>
278
+ ```
279
+
280
+ ### "Interactive mode requires a terminal"
281
+
282
+ Examples 03 requires a real terminal. Don't pipe input or run in CI. Use example 01 instead for non-interactive use.
283
+
284
+ ### "Invalid git reference"
285
+
286
+ Ensure the git references exist:
287
+ ```bash
288
+ git tag # List available tags
289
+ git log --oneline # See commits
290
+ ```
291
+
292
+ ### npm/npx issues
293
+
294
+ Install dependencies:
295
+ ```bash
296
+ npm install @eldrforge/ai-service openai @riotprompt/riotprompt
297
+ ```
298
+
299
+ ## Next Steps
300
+
301
+ After exploring these examples:
302
+
303
+ 1. **Integrate into your workflow** - Add to package.json scripts
304
+ 2. **Customize for your needs** - Modify models, parameters, prompts
305
+ 3. **Create custom tools** - Extend with domain-specific capabilities
306
+ 4. **Build automation** - Use in CI/CD pipelines
307
+ 5. **Explore the API** - See [main README](../README.md) for full API documentation
308
+
309
+ ## Additional Resources
310
+
311
+ - [Main README](../README.md) - Full API documentation
312
+ - [OpenAI API Docs](https://platform.openai.com/docs) - OpenAI reference
313
+ - [kodrdriv](https://github.com/calenvarek/kodrdriv) - Full automation toolkit
314
+
315
+ ## Questions or Issues?
316
+
317
+ - 🐛 [Report bugs](https://github.com/calenvarek/ai-service/issues)
318
+ - 💬 [Discussions](https://github.com/calenvarek/ai-service/discussions)
319
+ - 📖 [Documentation](../README.md)
320
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eldrforge/ai-service",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "AI-powered content generation for automation - OpenAI integration with structured prompts",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -11,7 +11,8 @@
11
11
  }
12
12
  },
13
13
  "files": [
14
- "dist"
14
+ "dist",
15
+ "examples"
15
16
  ],
16
17
  "repository": {
17
18
  "type": "git",
@@ -42,7 +43,7 @@
42
43
  "author": "Calen Varek <calenvarek@gmail.com>",
43
44
  "license": "Apache-2.0",
44
45
  "dependencies": {
45
- "@eldrforge/git-tools": "^0.1.13",
46
+ "@eldrforge/git-tools": "^0.1.14",
46
47
  "@riotprompt/riotprompt": "^0.0.8",
47
48
  "openai": "^6.3.0"
48
49
  },