@iambarryking/ag 3.2.5 → 4.2.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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Grep tool — code search and file finding
3
+ * Primary: ripgrep (rg) via execFileSync
4
+ * Fallback: native Node.js when rg is not installed
5
+ */
6
+ import { Tool } from '../core/types.js';
7
+ export declare function grepTool(cwd: string): Tool;
8
+ //# sourceMappingURL=grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AA8NxC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CA+B1C"}
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Grep tool — code search and file finding
3
+ * Primary: ripgrep (rg) via execFileSync
4
+ * Fallback: native Node.js when rg is not installed
5
+ */
6
+ import { execFile } from 'node:child_process';
7
+ import { promisify } from 'node:util';
8
+ import { readdirSync, readFileSync, openSync, readSync, closeSync, statSync } from 'node:fs';
9
+ import { join, resolve, relative } from 'node:path';
10
+ const execFileAsync = promisify(execFile);
11
+ const DEFAULT_IGNORE = new Set([
12
+ '.git', 'node_modules', 'dist', 'build', '.next', '.nuxt',
13
+ 'coverage', '.cache', '__pycache__', '.venv', 'venv',
14
+ ]);
15
+ const MAX_SEARCH_LINES = 250;
16
+ const MAX_FIND_RESULTS = 100;
17
+ const MAX_FILE_SIZE = 1_048_576; // 1 MB
18
+ // ── Ripgrep helpers ──────────────────────────────────────────────────────
19
+ async function tryRg(args, cwd) {
20
+ try {
21
+ const { stdout } = await execFileAsync('rg', args, {
22
+ cwd, encoding: 'utf-8', timeout: 30_000, maxBuffer: 2 * 1024 * 1024,
23
+ });
24
+ return { ok: true, out: stdout.trim(), notFound: false };
25
+ }
26
+ catch (e) {
27
+ if (e.code === 'ENOENT')
28
+ return { ok: false, out: '', notFound: true };
29
+ // rg exits 1 for no matches, 2 for errors
30
+ const out = ((e.stdout ?? '') + (e.stderr ?? '')).trim();
31
+ if (e.code === 1 || e.status === 1)
32
+ return { ok: true, out: '', notFound: false }; // no matches
33
+ return { ok: false, out, notFound: false };
34
+ }
35
+ }
36
+ async function rgSearch(cwd, pattern, path, glob, caseInsensitive, context) {
37
+ const args = [pattern, '--line-number', '--no-heading', '--color', 'never', '--max-count', String(MAX_SEARCH_LINES)];
38
+ if (glob)
39
+ args.push('--glob', glob);
40
+ if (caseInsensitive)
41
+ args.push('--ignore-case');
42
+ if (context && context > 0)
43
+ args.push('--context', String(context));
44
+ if (path)
45
+ args.push(path);
46
+ const result = await tryRg(args, cwd);
47
+ if (result.notFound)
48
+ return ''; // signal to use fallback
49
+ if (!result.ok)
50
+ return `Error: ${result.out}`;
51
+ return result.out || 'No matches found.';
52
+ }
53
+ async function rgFind(cwd, pattern, path) {
54
+ const args = ['--files', '--glob', pattern];
55
+ if (path)
56
+ args.push(path);
57
+ const result = await tryRg(args, cwd);
58
+ if (result.notFound)
59
+ return ''; // signal to use fallback
60
+ if (!result.ok)
61
+ return `Error: ${result.out}`;
62
+ if (!result.out)
63
+ return 'No matches found.';
64
+ const lines = result.out.split('\n');
65
+ if (lines.length > MAX_FIND_RESULTS) {
66
+ return lines.slice(0, MAX_FIND_RESULTS).join('\n')
67
+ + `\n... (${MAX_FIND_RESULTS} of ${lines.length} files shown. Narrow with path.)`;
68
+ }
69
+ return result.out;
70
+ }
71
+ // ── Native fallback helpers ──────────────────────────────────────────────
72
+ function walkDir(root, maxDepth = 20) {
73
+ const files = [];
74
+ function walk(dir, depth) {
75
+ if (depth > maxDepth)
76
+ return;
77
+ let entries;
78
+ try {
79
+ entries = readdirSync(dir, { withFileTypes: true });
80
+ }
81
+ catch {
82
+ return;
83
+ }
84
+ for (const entry of entries) {
85
+ if (DEFAULT_IGNORE.has(entry.name))
86
+ continue;
87
+ if (entry.name.startsWith('.') && entry.name !== '.')
88
+ continue;
89
+ const full = join(dir, entry.name);
90
+ if (entry.isSymbolicLink())
91
+ continue;
92
+ if (entry.isDirectory()) {
93
+ walk(full, depth + 1);
94
+ continue;
95
+ }
96
+ if (entry.isFile())
97
+ files.push(full);
98
+ }
99
+ }
100
+ walk(root, 0);
101
+ return files;
102
+ }
103
+ function isBinary(filePath) {
104
+ try {
105
+ const fd = openSync(filePath, 'r');
106
+ const buf = Buffer.alloc(512);
107
+ const bytesRead = readSync(fd, buf, 0, 512, 0);
108
+ closeSync(fd);
109
+ for (let i = 0; i < bytesRead; i++) {
110
+ if (buf[i] === 0)
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+ catch {
116
+ return true; // treat unreadable files as binary
117
+ }
118
+ }
119
+ function matchesGlob(filepath, glob) {
120
+ // Convert glob to regex: * -> [^/]*, ** -> .*, ? -> ., {a,b} -> (a|b), escape dots
121
+ let re = glob
122
+ .replace(/\./g, '\\.')
123
+ .replace(/\*\*/g, '{{GLOBSTAR}}')
124
+ .replace(/\*/g, '[^/]*')
125
+ .replace(/\{\{GLOBSTAR\}\}/g, '.*')
126
+ .replace(/\?/g, '.')
127
+ .replace(/\{([^}]+)\}/g, (_m, group) => `(${group.replace(/,/g, '|')})`);
128
+ // If pattern has no path separators, match against basename only
129
+ if (!glob.includes('/')) {
130
+ const basename = filepath.split('/').pop() || filepath;
131
+ return new RegExp(`^${re}$`).test(basename);
132
+ }
133
+ return new RegExp(`^${re}$`).test(filepath) || new RegExp(`${re}$`).test(filepath);
134
+ }
135
+ function fallbackSearch(cwd, pattern, searchRoot, glob, caseInsensitive, context) {
136
+ let regex;
137
+ try {
138
+ regex = new RegExp(pattern, caseInsensitive ? 'i' : '');
139
+ }
140
+ catch (e) {
141
+ return `Error: invalid regex — ${e.message}`;
142
+ }
143
+ const ctx = context && context > 0 ? context : 0;
144
+ const files = walkDir(searchRoot);
145
+ const output = [];
146
+ let matchCount = 0;
147
+ let truncated = false;
148
+ for (const file of files) {
149
+ if (matchCount >= MAX_SEARCH_LINES) {
150
+ truncated = true;
151
+ break;
152
+ }
153
+ try {
154
+ const stat = statSync(file);
155
+ if (stat.size > MAX_FILE_SIZE)
156
+ continue;
157
+ }
158
+ catch {
159
+ continue;
160
+ }
161
+ if (isBinary(file))
162
+ continue;
163
+ if (glob && !matchesGlob(relative(cwd, file), glob))
164
+ continue;
165
+ let content;
166
+ try {
167
+ content = readFileSync(file, 'utf-8');
168
+ }
169
+ catch {
170
+ continue;
171
+ }
172
+ const lines = content.split('\n');
173
+ const relPath = relative(cwd, file);
174
+ const fileMatches = [];
175
+ for (let i = 0; i < lines.length; i++) {
176
+ if (regex.test(lines[i])) {
177
+ const start = Math.max(0, i - ctx);
178
+ const end = Math.min(lines.length - 1, i + ctx);
179
+ for (let j = start; j <= end; j++) {
180
+ fileMatches.push(`${relPath}:${j + 1}:${lines[j]}`);
181
+ matchCount++;
182
+ if (matchCount >= MAX_SEARCH_LINES) {
183
+ truncated = true;
184
+ break;
185
+ }
186
+ }
187
+ if (truncated)
188
+ break;
189
+ }
190
+ }
191
+ if (fileMatches.length > 0) {
192
+ if (output.length > 0)
193
+ output.push('');
194
+ output.push(...fileMatches);
195
+ }
196
+ if (truncated)
197
+ break;
198
+ }
199
+ if (output.length === 0)
200
+ return 'No matches found.';
201
+ let result = output.join('\n');
202
+ if (truncated)
203
+ result += `\n... (${MAX_SEARCH_LINES} lines shown. Narrow with path or glob.)`;
204
+ return result;
205
+ }
206
+ function fallbackFind(cwd, pattern, searchRoot) {
207
+ const files = walkDir(searchRoot);
208
+ const matches = [];
209
+ for (const file of files) {
210
+ const relPath = relative(cwd, file);
211
+ if (matchesGlob(relPath, pattern)) {
212
+ matches.push(relPath);
213
+ if (matches.length >= MAX_FIND_RESULTS)
214
+ break;
215
+ }
216
+ }
217
+ if (matches.length === 0)
218
+ return 'No matches found.';
219
+ let result = matches.join('\n');
220
+ if (matches.length >= MAX_FIND_RESULTS) {
221
+ result += `\n... (${MAX_FIND_RESULTS} files shown. Narrow with path.)`;
222
+ }
223
+ return result;
224
+ }
225
+ // ── Action handlers ──────────────────────────────────────────────────────
226
+ async function doSearch(cwd, pattern, path, glob, caseInsensitive, context) {
227
+ const searchRoot = path ? resolve(cwd, path) : cwd;
228
+ if (!searchRoot.startsWith(cwd))
229
+ return 'Error: path must be within the project directory.';
230
+ // Try ripgrep first
231
+ const rgResult = await rgSearch(cwd, pattern, path, glob, caseInsensitive, context);
232
+ if (rgResult !== '')
233
+ return rgResult; // '' means rg not found
234
+ // Fallback to native Node.js
235
+ return fallbackSearch(cwd, pattern, searchRoot, glob, caseInsensitive, context);
236
+ }
237
+ async function doFind(cwd, pattern, path) {
238
+ const searchRoot = path ? resolve(cwd, path) : cwd;
239
+ if (!searchRoot.startsWith(cwd))
240
+ return 'Error: path must be within the project directory.';
241
+ // Try ripgrep first
242
+ const rgResult = await rgFind(cwd, pattern, path);
243
+ if (rgResult !== '')
244
+ return rgResult; // '' means rg not found
245
+ // Fallback to native Node.js
246
+ return fallbackFind(cwd, pattern, searchRoot);
247
+ }
248
+ // ── Exported tool ────────────────────────────────────────────────────────
249
+ export function grepTool(cwd) {
250
+ return {
251
+ type: 'function',
252
+ function: {
253
+ name: 'grep',
254
+ description: 'Search code and find files. Actions: search (find pattern in file contents, regex), find (locate files by name/glob pattern).',
255
+ parameters: {
256
+ type: 'object',
257
+ properties: {
258
+ action: { type: 'string', enum: ['search', 'find'], description: 'search = content regex, find = file name glob.' },
259
+ pattern: { type: 'string', description: 'Regex for search, glob for find (e.g. "*.ts", "TODO", "function\\s+\\w+").' },
260
+ path: { type: 'string', description: 'Subdirectory to scope (relative to project root). Omit to search everywhere.' },
261
+ glob: { type: 'string', description: 'File type filter for action=search (e.g. "*.ts", "*.py"). Not needed for find.' },
262
+ case_insensitive: { type: 'boolean', description: 'Case-insensitive matching (search only). Default: false.' },
263
+ context: { type: 'number', description: 'Lines of context before and after each match (search only). Default: 0.' }
264
+ },
265
+ required: ['action', 'pattern']
266
+ }
267
+ },
268
+ execute: async ({ action, pattern, path, glob, case_insensitive, context }) => {
269
+ if (!pattern)
270
+ return 'Error: pattern is required.';
271
+ switch (action) {
272
+ case 'search': return doSearch(cwd, pattern, path, glob, case_insensitive, context);
273
+ case 'find': return doFind(cwd, pattern, path);
274
+ default: return `Unknown action "${action}". Use: search, find.`;
275
+ }
276
+ }
277
+ };
278
+ }
279
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGxC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAsC1C"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAGxC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAmD1C"}
@@ -1,14 +1,14 @@
1
- import { savePlan, listPlans, loadPlanByName } from '../memory/memory.js';
1
+ import { savePlan, listPlans, loadPlanByName, appendPlan, setActivePlan } from '../memory/memory.js';
2
2
  export function planTool(cwd) {
3
3
  return {
4
4
  type: 'function',
5
5
  function: {
6
6
  name: 'plan',
7
- description: 'Manage task plans. Save a new plan, list all plans, or read a specific plan by name. Plans are timestamped and the latest is automatically loaded as context.',
7
+ description: 'Manage task plans. Save a new plan, append to the latest plan, switch the active plan, list all plans, or read a specific plan by name. Plans are timestamped and the latest is automatically loaded as context.',
8
8
  parameters: {
9
9
  type: 'object',
10
10
  properties: {
11
- action: { type: 'string', enum: ['save', 'list', 'read'], description: '"save" to create a new plan, "list" to see all plans, "read" to view a specific plan.' },
11
+ action: { type: 'string', enum: ['save', 'list', 'read', 'append', 'switch'], description: '"save" to create a new plan, "append" to add content to the latest plan, "switch" to activate a different plan by name, "list" to see all plans, "read" to view a specific plan.' },
12
12
  content: { type: 'string', description: 'Plan content (required for action=save).' },
13
13
  name: { type: 'string', description: 'Plan name for save (e.g. "refactor-cli") or read (e.g. "2026-04-13T12-31-22-refactor-cli").' }
14
14
  },
@@ -23,6 +23,22 @@ export function planTool(cwd) {
23
23
  const filePath = savePlan(content, name, cwd);
24
24
  return `Plan saved: ${filePath}`;
25
25
  }
26
+ case 'append': {
27
+ if (!content)
28
+ return 'Error: content is required for action=append.';
29
+ const filePath = appendPlan(content, cwd);
30
+ return `Appended to plan: ${filePath}`;
31
+ }
32
+ case 'switch': {
33
+ if (!name)
34
+ return 'Error: name is required for action=switch. Use action=list to see available plans.';
35
+ const plans = listPlans(cwd);
36
+ const match = plans.find(p => p.name.includes(name));
37
+ if (!match)
38
+ return `No plan matching "${name}". Use action=list to see available plans.`;
39
+ setActivePlan(match.name, cwd);
40
+ return `Switched to plan: ${match.name}`;
41
+ }
26
42
  case 'list': {
27
43
  const plans = listPlans(cwd);
28
44
  if (plans.length === 0)
@@ -36,7 +52,7 @@ export function planTool(cwd) {
36
52
  return result || `No plan found with name "${name}".`;
37
53
  }
38
54
  default:
39
- return `Unknown action "${action}". Use "save", "list", or "read".`;
55
+ return `Unknown action "${action}". Use "save", "append", "switch", "list", or "read".`;
40
56
  }
41
57
  }
42
58
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1E,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,+JAA+J;YAC5K,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,uFAAuF,EAAE;oBAChK,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;oBACpF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6FAA6F,EAAE;iBACrI;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;QACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAuD,EAAU,EAAE;YAClG,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,IAAI,CAAC,OAAO;wBAAE,OAAO,6CAA6C,CAAC;oBACnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC9C,OAAO,eAAe,QAAQ,EAAE,CAAC;gBACnC,CAAC;gBACD,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;oBAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,qBAAqB,CAAC;oBACrD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3D,CAAC;gBACD,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,IAAI,CAAC,IAAI;wBAAE,OAAO,kFAAkF,CAAC;oBACrG,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBACzC,OAAO,MAAM,IAAI,4BAA4B,IAAI,IAAI,CAAC;gBACxD,CAAC;gBACD;oBACE,OAAO,mBAAmB,MAAM,mCAAmC,CAAC;YACxE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAErG,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,kNAAkN;YAC/N,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE,kLAAkL,EAAE;oBAC/Q,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0CAA0C,EAAE;oBACpF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,6FAA6F,EAAE;iBACrI;gBACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;aACrB;SACF;QACD,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAuD,EAAU,EAAE;YAClG,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,IAAI,CAAC,OAAO;wBAAE,OAAO,6CAA6C,CAAC;oBACnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC9C,OAAO,eAAe,QAAQ,EAAE,CAAC;gBACnC,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,IAAI,CAAC,OAAO;wBAAE,OAAO,+CAA+C,CAAC;oBACrE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;oBAC1C,OAAO,qBAAqB,QAAQ,EAAE,CAAC;gBACzC,CAAC;gBACD,KAAK,QAAQ,CAAC,CAAC,CAAC;oBACd,IAAI,CAAC,IAAI;wBAAE,OAAO,oFAAoF,CAAC;oBACvG,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;oBAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;oBACrD,IAAI,CAAC,KAAK;wBAAE,OAAO,qBAAqB,IAAI,4CAA4C,CAAC;oBACzF,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBAC/B,OAAO,qBAAqB,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC3C,CAAC;gBACD,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;oBAC7B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,qBAAqB,CAAC;oBACrD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC3D,CAAC;gBACD,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,IAAI,CAAC,IAAI;wBAAE,OAAO,kFAAkF,CAAC;oBACrG,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;oBACzC,OAAO,MAAM,IAAI,4BAA4B,IAAI,IAAI,CAAC;gBACxD,CAAC;gBACD;oBACE,OAAO,mBAAmB,MAAM,uDAAuD,CAAC;YAC5F,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iambarryking/ag",
3
- "version": "3.2.5",
3
+ "version": "4.2.1",
4
4
  "description": "Persistent AI coding agent with memory - any model via OpenRouter",
5
5
  "type": "module",
6
6
  "bin": {