@console-agent/agent 1.1.1 → 1.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.
- package/dist/index.cjs +345 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -2
- package/dist/index.d.ts +39 -2
- package/dist/index.js +345 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
2
|
-
import { jsonSchema, Output, ToolLoopAgent } from 'ai';
|
|
2
|
+
import { jsonSchema, generateText, stepCountIs, Output, ToolLoopAgent } from 'ai';
|
|
3
|
+
import { existsSync, readFileSync } from 'fs';
|
|
4
|
+
import { extname, resolve, basename } from 'path';
|
|
3
5
|
import chalk from 'chalk';
|
|
4
6
|
import ora from 'ora';
|
|
5
7
|
|
|
8
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
9
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
10
|
+
}) : x)(function(x) {
|
|
11
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
12
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
13
|
+
});
|
|
14
|
+
|
|
6
15
|
// src/personas/debugger.ts
|
|
7
16
|
var debuggerPersona = {
|
|
8
17
|
name: "debugger",
|
|
@@ -203,6 +212,168 @@ function detectPersona(prompt, defaultPersona) {
|
|
|
203
212
|
function getPersona(name) {
|
|
204
213
|
return personas[name];
|
|
205
214
|
}
|
|
215
|
+
|
|
216
|
+
// src/tools/file-analysis.ts
|
|
217
|
+
function prepareFileContent(fileData, mimeType) {
|
|
218
|
+
const base64 = Buffer.from(fileData).toString("base64");
|
|
219
|
+
return {
|
|
220
|
+
type: "file",
|
|
221
|
+
data: base64,
|
|
222
|
+
mimeType
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// src/tools/index.ts
|
|
227
|
+
var TOOLS_MIN_TIMEOUT = 3e4;
|
|
228
|
+
function resolveTools(tools, google) {
|
|
229
|
+
const resolved = {};
|
|
230
|
+
for (const tool of tools) {
|
|
231
|
+
const name = typeof tool === "string" ? tool : tool.type;
|
|
232
|
+
const config2 = typeof tool === "object" ? tool.config : void 0;
|
|
233
|
+
switch (name) {
|
|
234
|
+
case "google_search":
|
|
235
|
+
resolved["google_search"] = google.tools.googleSearch(config2 ?? {});
|
|
236
|
+
break;
|
|
237
|
+
case "code_execution":
|
|
238
|
+
resolved["code_execution"] = google.tools.codeExecution(config2 ?? {});
|
|
239
|
+
break;
|
|
240
|
+
case "url_context":
|
|
241
|
+
resolved["url_context"] = google.tools.urlContext({});
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return resolved;
|
|
246
|
+
}
|
|
247
|
+
function hasExplicitTools(options) {
|
|
248
|
+
return !!(options?.tools && options.tools.length > 0);
|
|
249
|
+
}
|
|
250
|
+
var MAX_FILE_SIZE = 100 * 1024;
|
|
251
|
+
var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
252
|
+
".ts",
|
|
253
|
+
".tsx",
|
|
254
|
+
".js",
|
|
255
|
+
".jsx",
|
|
256
|
+
".mjs",
|
|
257
|
+
".cjs",
|
|
258
|
+
".py",
|
|
259
|
+
".rb",
|
|
260
|
+
".go",
|
|
261
|
+
".rs",
|
|
262
|
+
".java",
|
|
263
|
+
".kt",
|
|
264
|
+
".c",
|
|
265
|
+
".cpp",
|
|
266
|
+
".h",
|
|
267
|
+
".hpp",
|
|
268
|
+
".cs",
|
|
269
|
+
".swift",
|
|
270
|
+
".vue",
|
|
271
|
+
".svelte",
|
|
272
|
+
".astro",
|
|
273
|
+
".json",
|
|
274
|
+
".yaml",
|
|
275
|
+
".yml",
|
|
276
|
+
".toml",
|
|
277
|
+
".env",
|
|
278
|
+
".sql",
|
|
279
|
+
".graphql",
|
|
280
|
+
".gql",
|
|
281
|
+
".md",
|
|
282
|
+
".txt",
|
|
283
|
+
".html",
|
|
284
|
+
".css",
|
|
285
|
+
".scss"
|
|
286
|
+
]);
|
|
287
|
+
var INTERNAL_PATTERNS = [
|
|
288
|
+
"/console-agent/",
|
|
289
|
+
"/console_agent/",
|
|
290
|
+
"@console-agent/",
|
|
291
|
+
"/node_modules/",
|
|
292
|
+
"node:internal/",
|
|
293
|
+
"node:async_hooks",
|
|
294
|
+
"<anonymous>"
|
|
295
|
+
];
|
|
296
|
+
function parseStackFrames(stack) {
|
|
297
|
+
const frames = [];
|
|
298
|
+
const lines = stack.split("\n");
|
|
299
|
+
for (const line of lines) {
|
|
300
|
+
const match = line.match(/at\s+(?:.*?\s+)?\(?([^()]+):(\d+):(\d+)\)?/);
|
|
301
|
+
if (match) {
|
|
302
|
+
frames.push({
|
|
303
|
+
file: match[1],
|
|
304
|
+
line: parseInt(match[2], 10),
|
|
305
|
+
column: parseInt(match[3], 10)
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return frames;
|
|
310
|
+
}
|
|
311
|
+
function isInternalFrame(filePath) {
|
|
312
|
+
return INTERNAL_PATTERNS.some((pattern) => filePath.includes(pattern));
|
|
313
|
+
}
|
|
314
|
+
function isSourceFile(filePath) {
|
|
315
|
+
const ext = extname(filePath).toLowerCase();
|
|
316
|
+
return SOURCE_EXTENSIONS.has(ext);
|
|
317
|
+
}
|
|
318
|
+
function getCallerFile(skipFrames = 0) {
|
|
319
|
+
const err = new Error();
|
|
320
|
+
if (!err.stack) return null;
|
|
321
|
+
const frames = parseStackFrames(err.stack);
|
|
322
|
+
for (const frame of frames) {
|
|
323
|
+
if (isInternalFrame(frame.file)) continue;
|
|
324
|
+
if (!isSourceFile(frame.file)) continue;
|
|
325
|
+
return readSourceFile(frame.file, frame.line, frame.column);
|
|
326
|
+
}
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
function getErrorSourceFile(error) {
|
|
330
|
+
if (!error.stack) return null;
|
|
331
|
+
const frames = parseStackFrames(error.stack);
|
|
332
|
+
for (const frame of frames) {
|
|
333
|
+
if (frame.file.includes("node:internal/") || frame.file.includes("<anonymous>")) continue;
|
|
334
|
+
if (!isSourceFile(frame.file)) continue;
|
|
335
|
+
return readSourceFile(frame.file, frame.line, frame.column);
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
function readSourceFile(filePath, line, column) {
|
|
340
|
+
try {
|
|
341
|
+
const resolvedPath = resolve(filePath);
|
|
342
|
+
if (!existsSync(resolvedPath)) return null;
|
|
343
|
+
const { statSync } = __require("fs");
|
|
344
|
+
const stats = statSync(resolvedPath);
|
|
345
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
346
|
+
const content2 = readFileSync(resolvedPath, "utf-8").substring(0, MAX_FILE_SIZE);
|
|
347
|
+
return {
|
|
348
|
+
filePath: resolvedPath,
|
|
349
|
+
fileName: basename(resolvedPath),
|
|
350
|
+
line,
|
|
351
|
+
column,
|
|
352
|
+
content: content2 + "\n\n// [TRUNCATED \u2014 file exceeds 100KB limit]"
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const content = readFileSync(resolvedPath, "utf-8");
|
|
356
|
+
return {
|
|
357
|
+
filePath: resolvedPath,
|
|
358
|
+
fileName: basename(resolvedPath),
|
|
359
|
+
line,
|
|
360
|
+
column,
|
|
361
|
+
content
|
|
362
|
+
};
|
|
363
|
+
} catch {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function formatSourceForContext(source) {
|
|
368
|
+
const lines = source.content.split("\n");
|
|
369
|
+
const numbered = lines.map((line, i) => {
|
|
370
|
+
const lineNum = i + 1;
|
|
371
|
+
const marker = lineNum === source.line ? " \u2192 " : " ";
|
|
372
|
+
return `${marker}${String(lineNum).padStart(4)} | ${line}`;
|
|
373
|
+
});
|
|
374
|
+
return `--- Source File: ${source.fileName} (line ${source.line}) ---
|
|
375
|
+
${numbered.join("\n")}`;
|
|
376
|
+
}
|
|
206
377
|
var currentLogLevel = "info";
|
|
207
378
|
function setLogLevel(level) {
|
|
208
379
|
currentLogLevel = level;
|
|
@@ -211,8 +382,9 @@ function shouldLog(level) {
|
|
|
211
382
|
const levels = ["silent", "errors", "info", "debug"];
|
|
212
383
|
return levels.indexOf(currentLogLevel) >= levels.indexOf(level);
|
|
213
384
|
}
|
|
214
|
-
function startSpinner(persona, prompt) {
|
|
385
|
+
function startSpinner(persona, prompt, verbose = false) {
|
|
215
386
|
if (!shouldLog("info")) return null;
|
|
387
|
+
if (!verbose) return null;
|
|
216
388
|
const truncated = prompt.length > 60 ? prompt.substring(0, 57) + "..." : prompt;
|
|
217
389
|
const spinner = ora({
|
|
218
390
|
text: chalk.cyan(`${persona.icon} ${persona.label}... `) + chalk.dim(truncated),
|
|
@@ -228,8 +400,29 @@ function stopSpinner(spinner, success) {
|
|
|
228
400
|
spinner.fail();
|
|
229
401
|
}
|
|
230
402
|
}
|
|
231
|
-
function formatResult(result, persona) {
|
|
403
|
+
function formatResult(result, persona, verbose = false) {
|
|
232
404
|
if (!shouldLog("info")) return;
|
|
405
|
+
if (!verbose) {
|
|
406
|
+
formatResultQuiet(result);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
formatResultVerbose(result, persona);
|
|
410
|
+
}
|
|
411
|
+
function formatResultQuiet(result) {
|
|
412
|
+
console.log("");
|
|
413
|
+
console.log(result.summary);
|
|
414
|
+
const dataEntries = Object.entries(result.data);
|
|
415
|
+
const hasMeaningfulData = dataEntries.length > 0 && !(dataEntries.length === 1 && dataEntries[0][0] === "raw");
|
|
416
|
+
if (hasMeaningfulData) {
|
|
417
|
+
for (const [key, value] of dataEntries) {
|
|
418
|
+
if (key === "raw") continue;
|
|
419
|
+
const displayValue = typeof value === "string" ? value : JSON.stringify(value);
|
|
420
|
+
console.log(`${chalk.dim(key + ":")} ${displayValue}`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
console.log("");
|
|
424
|
+
}
|
|
425
|
+
function formatResultVerbose(result, persona) {
|
|
233
426
|
const prefix = chalk.gray("[AGENT]");
|
|
234
427
|
const confidenceColor = result.confidence >= 0.8 ? chalk.green : result.confidence >= 0.5 ? chalk.yellow : chalk.red;
|
|
235
428
|
const statusIcon = result.success ? chalk.green("\u2713") : chalk.red("\u2717");
|
|
@@ -259,12 +452,20 @@ function formatResult(result, persona) {
|
|
|
259
452
|
const confidence = confidenceColor(`confidence: ${result.confidence.toFixed(2)}`);
|
|
260
453
|
const latency = chalk.dim(`${result.metadata.latencyMs}ms`);
|
|
261
454
|
const tokens = chalk.dim(`${result.metadata.tokensUsed} tokens`);
|
|
455
|
+
const model = chalk.dim(`model: ${result.metadata.model}`);
|
|
262
456
|
const cached = result.metadata.cached ? chalk.green(" (cached)") : "";
|
|
263
|
-
|
|
457
|
+
const toolNames = result.metadata.toolCalls.length > 0 ? chalk.dim(` | tools: ${result.metadata.toolCalls.map((t) => t.name).join(", ")}`) : "";
|
|
458
|
+
console.log(`${prefix} \u2514\u2500 ${confidence} | ${latency} | ${tokens} | ${model}${cached}${toolNames}`);
|
|
264
459
|
console.log("");
|
|
265
460
|
}
|
|
266
|
-
function formatError(error, persona) {
|
|
461
|
+
function formatError(error, persona, verbose = false) {
|
|
267
462
|
if (!shouldLog("errors")) return;
|
|
463
|
+
if (!verbose) {
|
|
464
|
+
console.log("");
|
|
465
|
+
console.log(chalk.red(`Error: ${error.message}`));
|
|
466
|
+
console.log("");
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
268
469
|
const prefix = chalk.gray("[AGENT]");
|
|
269
470
|
console.log("");
|
|
270
471
|
console.log(`${prefix} ${persona.icon} ${chalk.red("Error:")} ${error.message}`);
|
|
@@ -273,18 +474,32 @@ function formatError(error, persona) {
|
|
|
273
474
|
}
|
|
274
475
|
console.log("");
|
|
275
476
|
}
|
|
276
|
-
function formatBudgetWarning(reason) {
|
|
477
|
+
function formatBudgetWarning(reason, verbose = false) {
|
|
277
478
|
if (!shouldLog("errors")) return;
|
|
479
|
+
if (!verbose) {
|
|
480
|
+
console.log(chalk.yellow(`Budget limit: ${reason}`));
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
278
483
|
const prefix = chalk.gray("[AGENT]");
|
|
279
484
|
console.log(`${prefix} ${chalk.yellow("\u26A0 Budget limit:")} ${reason}`);
|
|
280
485
|
}
|
|
281
|
-
function formatRateLimitWarning() {
|
|
486
|
+
function formatRateLimitWarning(verbose = false) {
|
|
282
487
|
if (!shouldLog("errors")) return;
|
|
488
|
+
if (!verbose) {
|
|
489
|
+
console.log(chalk.yellow("Rate limited: Too many calls. Try again later."));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
283
492
|
const prefix = chalk.gray("[AGENT]");
|
|
284
493
|
console.log(`${prefix} ${chalk.yellow("\u26A0 Rate limited:")} Too many calls. Try again later.`);
|
|
285
494
|
}
|
|
286
|
-
function formatDryRun(prompt, persona, context) {
|
|
495
|
+
function formatDryRun(prompt, persona, context, verbose = false) {
|
|
287
496
|
if (!shouldLog("info")) return;
|
|
497
|
+
if (!verbose) {
|
|
498
|
+
console.log("");
|
|
499
|
+
console.log(chalk.magenta("[DRY RUN]") + ` Would execute with ${persona.name} persona`);
|
|
500
|
+
console.log("");
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
288
503
|
const prefix = chalk.gray("[AGENT]");
|
|
289
504
|
console.log("");
|
|
290
505
|
console.log(`${prefix} ${chalk.magenta("DRY RUN")} ${persona.icon} ${persona.label}`);
|
|
@@ -327,7 +542,37 @@ var agentOutputSchema = jsonSchema({
|
|
|
327
542
|
required: ["success", "summary", "data", "actions", "confidence"],
|
|
328
543
|
additionalProperties: false
|
|
329
544
|
});
|
|
330
|
-
|
|
545
|
+
var JSON_RESPONSE_INSTRUCTION = `
|
|
546
|
+
|
|
547
|
+
IMPORTANT: You MUST respond with ONLY a valid JSON object (no markdown, no code fences, no extra text).
|
|
548
|
+
Use this exact format:
|
|
549
|
+
{"success": true, "summary": "one-line conclusion", "reasoning": "your thought process", "data": {"result": "primary finding"}, "actions": ["tools/steps used"], "confidence": 0.95}`;
|
|
550
|
+
function buildMessages(prompt, context, sourceFile, files) {
|
|
551
|
+
const parts = [];
|
|
552
|
+
parts.push({ type: "text", text: prompt });
|
|
553
|
+
if (context) {
|
|
554
|
+
parts.push({ type: "text", text: `
|
|
555
|
+
--- Context ---
|
|
556
|
+
${context}` });
|
|
557
|
+
}
|
|
558
|
+
if (sourceFile) {
|
|
559
|
+
const formatted = formatSourceForContext(sourceFile);
|
|
560
|
+
parts.push({ type: "text", text: `
|
|
561
|
+
${formatted}` });
|
|
562
|
+
}
|
|
563
|
+
if (files && files.length > 0) {
|
|
564
|
+
for (const file of files) {
|
|
565
|
+
const prepared = prepareFileContent(file.data, file.mediaType);
|
|
566
|
+
if (file.fileName) {
|
|
567
|
+
parts.push({ type: "text", text: `
|
|
568
|
+
--- Attached File: ${file.fileName} ---` });
|
|
569
|
+
}
|
|
570
|
+
parts.push(prepared);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return [{ role: "user", content: parts }];
|
|
574
|
+
}
|
|
575
|
+
async function callGoogle(prompt, context, persona, config2, options, sourceFile, files) {
|
|
331
576
|
const startTime = Date.now();
|
|
332
577
|
const modelName = options?.model ?? config2.model;
|
|
333
578
|
logDebug(`Using model: ${modelName}`);
|
|
@@ -348,14 +593,69 @@ async function callGoogle(prompt, context, persona, config2, options) {
|
|
|
348
593
|
if (Object.keys(googleOpts).length > 0) {
|
|
349
594
|
providerOptions["google"] = googleOpts;
|
|
350
595
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
logDebug(
|
|
596
|
+
const useTools = hasExplicitTools(options) && !config2.localOnly;
|
|
597
|
+
if (useTools) {
|
|
598
|
+
logDebug("Tools requested \u2014 using generateText path (no structured output)");
|
|
599
|
+
return callWithTools(prompt, context, persona, config2, options, google, modelName, startTime, providerOptions, sourceFile, files);
|
|
354
600
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
601
|
+
logDebug("No tools \u2014 using ToolLoopAgent with structured output");
|
|
602
|
+
return callWithStructuredOutput(prompt, context, persona, config2, options, google, modelName, startTime, providerOptions, sourceFile, files);
|
|
603
|
+
}
|
|
604
|
+
async function callWithTools(prompt, context, persona, config2, options, google, modelName, startTime, providerOptions, sourceFile, files) {
|
|
605
|
+
const resolvedTools = resolveTools(options.tools, google);
|
|
606
|
+
const toolNames = Object.keys(resolvedTools);
|
|
607
|
+
logDebug(`Tools enabled: ${toolNames.join(", ")}`);
|
|
608
|
+
const effectiveTimeout = Math.max(config2.timeout, TOOLS_MIN_TIMEOUT);
|
|
609
|
+
const messages = buildMessages(prompt, context, sourceFile, files);
|
|
610
|
+
const result = await generateText({
|
|
611
|
+
model: google(modelName),
|
|
612
|
+
system: persona.systemPrompt + JSON_RESPONSE_INSTRUCTION,
|
|
613
|
+
messages,
|
|
614
|
+
tools: resolvedTools,
|
|
615
|
+
stopWhen: stepCountIs(5),
|
|
616
|
+
// Allow multi-step: tool invocation → response
|
|
617
|
+
maxOutputTokens: config2.budget.maxTokensPerCall,
|
|
618
|
+
providerOptions: Object.keys(providerOptions).length > 0 ? providerOptions : void 0,
|
|
619
|
+
abortSignal: AbortSignal.timeout(effectiveTimeout)
|
|
620
|
+
});
|
|
621
|
+
const latencyMs = Date.now() - startTime;
|
|
622
|
+
const tokensUsed = result.usage?.totalTokens ?? 0;
|
|
623
|
+
logDebug(`Response received (tools path): ${latencyMs}ms, ${tokensUsed} tokens`);
|
|
624
|
+
const collectedToolCalls = [];
|
|
625
|
+
if (result.steps) {
|
|
626
|
+
for (const step of result.steps) {
|
|
627
|
+
if (step.toolCalls) {
|
|
628
|
+
for (const tc of step.toolCalls) {
|
|
629
|
+
collectedToolCalls.push({
|
|
630
|
+
name: tc.toolName,
|
|
631
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
632
|
+
args: tc.args ?? {},
|
|
633
|
+
result: tc.toolName
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
logDebug(`Tool calls collected: ${collectedToolCalls.length}`);
|
|
640
|
+
const parsed = parseResponse(result.text);
|
|
641
|
+
return {
|
|
642
|
+
success: parsed?.success ?? true,
|
|
643
|
+
summary: parsed?.summary ?? result.text.substring(0, 200),
|
|
644
|
+
reasoning: parsed?.reasoning,
|
|
645
|
+
data: parsed?.data ?? { raw: result.text },
|
|
646
|
+
actions: parsed?.actions ?? collectedToolCalls.map((tc) => tc.name),
|
|
647
|
+
confidence: parsed?.confidence ?? 0.5,
|
|
648
|
+
metadata: {
|
|
649
|
+
model: modelName,
|
|
650
|
+
tokensUsed,
|
|
651
|
+
latencyMs,
|
|
652
|
+
toolCalls: collectedToolCalls,
|
|
653
|
+
cached: false
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
async function callWithStructuredOutput(prompt, context, persona, config2, options, google, modelName, startTime, providerOptions, sourceFile, files) {
|
|
658
|
+
const messages = buildMessages(prompt, context, sourceFile, files);
|
|
359
659
|
const collectedToolCalls = [];
|
|
360
660
|
const useCustomSchema = !!(options?.schema || options?.responseFormat);
|
|
361
661
|
let outputConfig;
|
|
@@ -394,7 +694,7 @@ IMPORTANT: You must respond with structured data matching the requested output s
|
|
|
394
694
|
}
|
|
395
695
|
});
|
|
396
696
|
const result = await agent.generate({
|
|
397
|
-
|
|
697
|
+
messages,
|
|
398
698
|
timeout: config2.timeout
|
|
399
699
|
});
|
|
400
700
|
const latencyMs = Date.now() - startTime;
|
|
@@ -689,7 +989,9 @@ var DEFAULT_CONFIG = {
|
|
|
689
989
|
localOnly: false,
|
|
690
990
|
dryRun: false,
|
|
691
991
|
logLevel: "info",
|
|
692
|
-
|
|
992
|
+
verbose: false,
|
|
993
|
+
safetySettings: [],
|
|
994
|
+
includeCallerSource: true
|
|
693
995
|
};
|
|
694
996
|
var config = { ...DEFAULT_CONFIG };
|
|
695
997
|
var rateLimiter = new RateLimiter(config.budget.maxCallsPerDay);
|
|
@@ -708,18 +1010,19 @@ function getConfig() {
|
|
|
708
1010
|
async function executeAgent(prompt, context, options) {
|
|
709
1011
|
const personaName = options?.persona ?? config.persona;
|
|
710
1012
|
const persona = options?.persona ? getPersona(options.persona) : detectPersona(prompt, personaName);
|
|
1013
|
+
const verbose = options?.verbose ?? config.verbose;
|
|
711
1014
|
logDebug(`Selected persona: ${persona.name} (${persona.icon})`);
|
|
712
1015
|
if (config.dryRun) {
|
|
713
|
-
formatDryRun(prompt, persona, context);
|
|
1016
|
+
formatDryRun(prompt, persona, context, verbose);
|
|
714
1017
|
return createDryRunResult(persona.name);
|
|
715
1018
|
}
|
|
716
1019
|
if (!rateLimiter.tryConsume()) {
|
|
717
|
-
formatRateLimitWarning();
|
|
1020
|
+
formatRateLimitWarning(verbose);
|
|
718
1021
|
return createErrorResult("Rate limited \u2014 too many calls. Try again later.");
|
|
719
1022
|
}
|
|
720
1023
|
const budgetCheck = budgetTracker.canMakeCall();
|
|
721
1024
|
if (!budgetCheck.allowed) {
|
|
722
|
-
formatBudgetWarning(budgetCheck.reason);
|
|
1025
|
+
formatBudgetWarning(budgetCheck.reason, verbose);
|
|
723
1026
|
return createErrorResult(budgetCheck.reason);
|
|
724
1027
|
}
|
|
725
1028
|
let contextStr = "";
|
|
@@ -741,10 +1044,27 @@ async function executeAgent(prompt, context, options) {
|
|
|
741
1044
|
}
|
|
742
1045
|
}
|
|
743
1046
|
const processedPrompt = config.anonymize ? anonymizeValue(prompt) : prompt;
|
|
744
|
-
const
|
|
1047
|
+
const shouldIncludeSource = options?.includeCallerSource ?? config.includeCallerSource;
|
|
1048
|
+
let sourceFile = null;
|
|
1049
|
+
if (shouldIncludeSource) {
|
|
1050
|
+
if (context instanceof Error) {
|
|
1051
|
+
sourceFile = getErrorSourceFile(context);
|
|
1052
|
+
if (sourceFile) {
|
|
1053
|
+
logDebug(`Auto-detected error source file: ${sourceFile.fileName} (line ${sourceFile.line})`);
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
if (!sourceFile) {
|
|
1057
|
+
sourceFile = getCallerFile();
|
|
1058
|
+
if (sourceFile) {
|
|
1059
|
+
logDebug(`Auto-detected caller file: ${sourceFile.fileName} (line ${sourceFile.line})`);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
const files = options?.files;
|
|
1064
|
+
const spinner = startSpinner(persona, processedPrompt, verbose);
|
|
745
1065
|
try {
|
|
746
1066
|
const result = await Promise.race([
|
|
747
|
-
callGoogle(processedPrompt, contextStr, persona, config, options),
|
|
1067
|
+
callGoogle(processedPrompt, contextStr, persona, config, options, sourceFile, files),
|
|
748
1068
|
createTimeout(config.timeout)
|
|
749
1069
|
]);
|
|
750
1070
|
budgetTracker.recordUsage(
|
|
@@ -752,12 +1072,12 @@ async function executeAgent(prompt, context, options) {
|
|
|
752
1072
|
estimateCost(result.metadata.tokensUsed, result.metadata.model)
|
|
753
1073
|
);
|
|
754
1074
|
stopSpinner(spinner, result.success);
|
|
755
|
-
formatResult(result, persona);
|
|
1075
|
+
formatResult(result, persona, verbose);
|
|
756
1076
|
return result;
|
|
757
1077
|
} catch (error) {
|
|
758
1078
|
stopSpinner(spinner, false);
|
|
759
1079
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
760
|
-
formatError(err, persona);
|
|
1080
|
+
formatError(err, persona, verbose);
|
|
761
1081
|
return createErrorResult(err.message);
|
|
762
1082
|
}
|
|
763
1083
|
}
|