@agi-cli/sdk 0.1.110 → 0.1.112

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.
@@ -5,6 +5,7 @@ import { promisify } from 'node:util';
5
5
  import { join } from 'node:path';
6
6
  import DESCRIPTION from './grep.txt' with { type: 'text' };
7
7
  import { defaultIgnoreGlobs } from './ignore.ts';
8
+ import { createToolError, type ToolResponse } from '../error.ts';
8
9
 
9
10
  const execAsync = promisify(exec);
10
11
 
@@ -39,9 +40,24 @@ export function buildGrepTool(projectRoot: string): {
39
40
  .optional()
40
41
  .describe('Glob patterns to exclude from search'),
41
42
  }),
42
- async execute(params) {
43
+ async execute(params: {
44
+ pattern: string;
45
+ path?: string;
46
+ include?: string;
47
+ ignore?: string[];
48
+ }): Promise<
49
+ ToolResponse<{
50
+ count: number;
51
+ matches: Array<{ file: string; line: number; text: string }>;
52
+ }>
53
+ > {
43
54
  const pattern = String(params.pattern || '');
44
- if (!pattern) throw new Error('pattern is required');
55
+ if (!pattern) {
56
+ return createToolError('pattern is required', 'validation', {
57
+ parameter: 'pattern',
58
+ suggestion: 'Provide a regex pattern to search for',
59
+ });
60
+ }
45
61
 
46
62
  const p = expandTilde(String(params.path || '')).trim();
47
63
  const isAbs = p.startsWith('/') || /^[A-Za-z]:[\\/]/.test(p);
@@ -63,10 +79,19 @@ export function buildGrepTool(projectRoot: string): {
63
79
  } catch (error: unknown) {
64
80
  const err = error as { code?: number; stderr?: string };
65
81
  if (err.code === 1) {
66
- return { count: 0, matches: [] };
82
+ return { ok: true, count: 0, matches: [] };
67
83
  }
68
84
  const err2 = error as { stderr?: string; message?: string };
69
- throw new Error(`ripgrep failed: ${err2.stderr || err2.message}`);
85
+ return createToolError(
86
+ `ripgrep failed: ${err2.stderr || err2.message}`,
87
+ 'execution',
88
+ {
89
+ parameter: 'pattern',
90
+ value: pattern,
91
+ suggestion:
92
+ 'Check if ripgrep (rg) is installed and the pattern is valid',
93
+ },
94
+ );
70
95
  }
71
96
 
72
97
  const lines = output.trim().split('\n');
@@ -94,6 +119,7 @@ export function buildGrepTool(projectRoot: string): {
94
119
  const finalMatches = truncated ? matches.slice(0, limit) : matches;
95
120
 
96
121
  return {
122
+ ok: true,
97
123
  count: finalMatches.length,
98
124
  matches: finalMatches,
99
125
  };
@@ -3,6 +3,7 @@ import { z } from 'zod';
3
3
  import { spawn } from 'node:child_process';
4
4
  import { join } from 'node:path';
5
5
  import DESCRIPTION from './ripgrep.txt' with { type: 'text' };
6
+ import { createToolError, type ToolResponse } from '../error.ts';
6
7
 
7
8
  export function buildRipgrepTool(projectRoot: string): {
8
9
  name: string;
@@ -36,7 +37,12 @@ export function buildRipgrepTool(projectRoot: string): {
36
37
  ignoreCase?: boolean;
37
38
  glob?: string[];
38
39
  maxResults?: number;
39
- }) {
40
+ }): Promise<
41
+ ToolResponse<{
42
+ count: number;
43
+ matches: Array<{ file: string; line: number; text: string }>;
44
+ }>
45
+ > {
40
46
  function expandTilde(p: string) {
41
47
  const home = process.env.HOME || process.env.USERPROFILE || '';
42
48
  if (!home) return p;
@@ -70,7 +76,16 @@ export function buildRipgrepTool(projectRoot: string): {
70
76
 
71
77
  proc.on('close', (code) => {
72
78
  if (code !== 0 && code !== 1) {
73
- resolve({ count: 0, matches: [], error: stderr.trim() });
79
+ resolve(
80
+ createToolError(
81
+ stderr.trim() || 'ripgrep failed',
82
+ 'execution',
83
+ {
84
+ suggestion:
85
+ 'Check if ripgrep (rg) is installed and the query is valid',
86
+ },
87
+ ),
88
+ );
74
89
  return;
75
90
  }
76
91
 
@@ -86,15 +101,21 @@ export function buildRipgrepTool(projectRoot: string): {
86
101
  const text = parts.slice(2).join(':');
87
102
  return { file, line, text };
88
103
  });
89
- resolve({ count: matches.length, matches });
104
+ resolve({ ok: true, count: matches.length, matches });
90
105
  });
91
106
 
92
107
  proc.on('error', (err) => {
93
- resolve({ count: 0, matches: [], error: String(err) });
108
+ resolve(
109
+ createToolError(String(err), 'execution', {
110
+ suggestion: 'Ensure ripgrep (rg) is installed',
111
+ }),
112
+ );
94
113
  });
95
114
  });
96
115
  } catch (err) {
97
- return { count: 0, matches: [], error: String(err) };
116
+ return createToolError(String(err), 'execution', {
117
+ suggestion: 'Ensure ripgrep (rg) is installed',
118
+ });
98
119
  }
99
120
  },
100
121
  });
@@ -1,6 +1,7 @@
1
1
  import { tool, type Tool } from 'ai';
2
2
  import { z } from 'zod';
3
3
  import DESCRIPTION from './websearch.txt' with { type: 'text' };
4
+ import { createToolError, type ToolResponse } from '../error.ts';
4
5
 
5
6
  export function buildWebSearchTool(): {
6
7
  name: string;
@@ -42,7 +43,22 @@ export function buildWebSearchTool(): {
42
43
  url?: string;
43
44
  query?: string;
44
45
  maxLength?: number;
45
- }) {
46
+ }): Promise<
47
+ ToolResponse<
48
+ | {
49
+ url: string;
50
+ content: string;
51
+ contentLength: number;
52
+ truncated: boolean;
53
+ contentType: string;
54
+ }
55
+ | {
56
+ query: string;
57
+ results: Array<{ title: string; url: string; snippet: string }>;
58
+ count: number;
59
+ }
60
+ >
61
+ > {
46
62
  const maxLen = maxLength ?? 50000;
47
63
 
48
64
  if (url) {
@@ -76,9 +92,11 @@ export function buildWebSearchTool(): {
76
92
  ) {
77
93
  content = await response.text();
78
94
  } else {
79
- return {
80
- error: `Unsupported content type: ${contentType}. Only text-based content can be fetched.`,
81
- };
95
+ return createToolError(
96
+ `Unsupported content type: ${contentType}. Only text-based content can be fetched.`,
97
+ 'unsupported',
98
+ { contentType },
99
+ );
82
100
  }
83
101
 
84
102
  // Strip HTML tags for better readability (basic cleaning)
@@ -93,6 +111,7 @@ export function buildWebSearchTool(): {
93
111
  const wasTruncated = cleanContent.length > maxLen;
94
112
 
95
113
  return {
114
+ ok: true,
96
115
  url,
97
116
  content: truncated,
98
117
  contentLength: cleanContent.length,
@@ -102,9 +121,11 @@ export function buildWebSearchTool(): {
102
121
  } catch (error) {
103
122
  const errorMessage =
104
123
  error instanceof Error ? error.message : String(error);
105
- return {
106
- error: `Failed to fetch URL: ${errorMessage}`,
107
- };
124
+ return createToolError(
125
+ `Failed to fetch URL: ${errorMessage}`,
126
+ 'execution',
127
+ { url },
128
+ );
108
129
  }
109
130
  }
110
131
 
@@ -183,16 +204,19 @@ export function buildWebSearchTool(): {
183
204
  }
184
205
 
185
206
  if (results.length === 0) {
186
- return {
187
- error:
188
- 'No search results found. The search service may have changed its format or blocked the request.',
189
- query,
190
- suggestion:
191
- 'Try using the url parameter to fetch a specific webpage instead.',
192
- };
207
+ return createToolError(
208
+ 'No search results found. The search service may have changed its format or blocked the request.',
209
+ 'execution',
210
+ {
211
+ query,
212
+ suggestion:
213
+ 'Try using the url parameter to fetch a specific webpage instead.',
214
+ },
215
+ );
193
216
  }
194
217
 
195
218
  return {
219
+ ok: true,
196
220
  query,
197
221
  results,
198
222
  count: results.length,
@@ -200,18 +224,25 @@ export function buildWebSearchTool(): {
200
224
  } catch (error) {
201
225
  const errorMessage =
202
226
  error instanceof Error ? error.message : String(error);
203
- return {
204
- error: `Search failed: ${errorMessage}`,
205
- query,
206
- suggestion:
207
- 'Search services may be temporarily unavailable. Try using the url parameter to fetch a specific webpage instead.',
208
- };
227
+ return createToolError(
228
+ `Search failed: ${errorMessage}`,
229
+ 'execution',
230
+ {
231
+ query,
232
+ suggestion:
233
+ 'Search services may be temporarily unavailable. Try using the url parameter to fetch a specific webpage instead.',
234
+ },
235
+ );
209
236
  }
210
237
  }
211
238
 
212
- return {
213
- error: 'Must provide either url or query parameter',
214
- };
239
+ return createToolError(
240
+ 'Must provide either url or query parameter',
241
+ 'validation',
242
+ {
243
+ suggestion: 'Provide either a url to fetch or a query to search',
244
+ },
245
+ );
215
246
  },
216
247
  });
217
248
 
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ export {
40
40
  providerIds,
41
41
  defaultModelFor,
42
42
  hasModel,
43
+ getFastModel,
43
44
  } from './providers/src/index.ts';
44
45
  export {
45
46
  isProviderAuthorized,
@@ -60,6 +61,11 @@ export type {
60
61
  SolforgeAuth,
61
62
  SolforgeProviderOptions,
62
63
  } from './providers/src/index.ts';
64
+ export {
65
+ createOpenAIOAuthFetch,
66
+ createOpenAIOAuthModel,
67
+ } from './providers/src/index.ts';
68
+ export type { OpenAIOAuthConfig } from './providers/src/index.ts';
63
69
 
64
70
  // =======================
65
71
  // Authentication (from internal auth module)
@@ -75,6 +81,14 @@ export {
75
81
  openAuthUrl,
76
82
  createApiKey,
77
83
  } from './auth/src/index.ts';
84
+ export {
85
+ authorizeOpenAI,
86
+ exchangeOpenAI,
87
+ refreshOpenAIToken,
88
+ openOpenAIAuthUrl,
89
+ obtainOpenAIApiKey,
90
+ } from './auth/src/index.ts';
91
+ export type { OpenAIOAuthResult } from './auth/src/index.ts';
78
92
 
79
93
  // =======================
80
94
  // Configuration (from internal config module)