@getverbal/cli 0.7.0 → 0.8.0
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/agent-hooks/claude.d.ts +10 -0
- package/dist/agent-hooks/claude.d.ts.map +1 -0
- package/dist/agent-hooks/claude.js +218 -0
- package/dist/agent-hooks/claude.js.map +1 -0
- package/dist/agent-hooks/cli.d.ts +2 -0
- package/dist/agent-hooks/cli.d.ts.map +1 -0
- package/dist/agent-hooks/cli.js +271 -0
- package/dist/agent-hooks/cli.js.map +1 -0
- package/dist/agent-hooks/codex.d.ts +9 -0
- package/dist/agent-hooks/codex.d.ts.map +1 -0
- package/dist/agent-hooks/codex.js +349 -0
- package/dist/agent-hooks/codex.js.map +1 -0
- package/dist/agent-hooks/config.d.ts +32 -0
- package/dist/agent-hooks/config.d.ts.map +1 -0
- package/dist/agent-hooks/config.js +176 -0
- package/dist/agent-hooks/config.js.map +1 -0
- package/dist/agent-hooks/ingest.d.ts +4 -0
- package/dist/agent-hooks/ingest.d.ts.map +1 -0
- package/dist/agent-hooks/ingest.js +22 -0
- package/dist/agent-hooks/ingest.js.map +1 -0
- package/dist/agent-hooks/launchagent.d.ts +7 -0
- package/dist/agent-hooks/launchagent.d.ts.map +1 -0
- package/dist/agent-hooks/launchagent.js +51 -0
- package/dist/agent-hooks/launchagent.js.map +1 -0
- package/dist/agent-hooks/runtime-context.d.ts +20 -0
- package/dist/agent-hooks/runtime-context.d.ts.map +1 -0
- package/dist/agent-hooks/runtime-context.js +90 -0
- package/dist/agent-hooks/runtime-context.js.map +1 -0
- package/dist/agent-hooks/state.d.ts +26 -0
- package/dist/agent-hooks/state.d.ts.map +1 -0
- package/dist/agent-hooks/state.js +67 -0
- package/dist/agent-hooks/state.js.map +1 -0
- package/dist/agent-hooks/tokscale.d.ts +70 -0
- package/dist/agent-hooks/tokscale.d.ts.map +1 -0
- package/dist/agent-hooks/tokscale.js +142 -0
- package/dist/agent-hooks/tokscale.js.map +1 -0
- package/dist/agent-hooks/tool-extraction.d.ts +7 -0
- package/dist/agent-hooks/tool-extraction.d.ts.map +1 -0
- package/dist/agent-hooks/tool-extraction.js +100 -0
- package/dist/agent-hooks/tool-extraction.js.map +1 -0
- package/dist/agent-hooks/trace.d.ts +17 -0
- package/dist/agent-hooks/trace.d.ts.map +1 -0
- package/dist/agent-hooks/trace.js +25 -0
- package/dist/agent-hooks/trace.js.map +1 -0
- package/dist/auth/browser-auth.d.ts +6 -0
- package/dist/auth/browser-auth.d.ts.map +1 -0
- package/dist/auth/browser-auth.js +202 -0
- package/dist/auth/browser-auth.js.map +1 -0
- package/dist/auth/credentials.d.ts +6 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +78 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +550 -148
- package/dist/cli.js.map +1 -0
- package/dist/commands/dashboard.d.ts +2 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +19 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/hooks.d.ts +2 -0
- package/dist/commands/hooks.d.ts.map +1 -0
- package/dist/commands/hooks.js +6 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/import.d.ts +2 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +129 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +262 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/logout.d.ts +2 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +17 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/mcp-serve.d.ts +2 -0
- package/dist/commands/mcp-serve.d.ts.map +1 -0
- package/dist/commands/mcp-serve.js +7 -0
- package/dist/commands/mcp-serve.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +43 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/uninstall.d.ts +2 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +43 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +58 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/configure/claude-code.d.ts +7 -0
- package/dist/configure/claude-code.d.ts.map +1 -0
- package/dist/configure/claude-code.js +11 -0
- package/dist/configure/claude-code.js.map +1 -0
- package/dist/configure/claude-desktop.d.ts +8 -0
- package/dist/configure/claude-desktop.d.ts.map +1 -0
- package/dist/configure/claude-desktop.js +28 -0
- package/dist/configure/claude-desktop.js.map +1 -0
- package/dist/configure/codex.d.ts +7 -0
- package/dist/configure/codex.d.ts.map +1 -0
- package/dist/configure/codex.js +12 -0
- package/dist/configure/codex.js.map +1 -0
- package/dist/configure/cursor.d.ts +7 -0
- package/dist/configure/cursor.d.ts.map +1 -0
- package/dist/configure/cursor.js +12 -0
- package/dist/configure/cursor.js.map +1 -0
- package/dist/configure/index.d.ts +34 -0
- package/dist/configure/index.d.ts.map +1 -0
- package/dist/configure/index.js +153 -0
- package/dist/configure/index.js.map +1 -0
- package/dist/detect/claude-code.d.ts +3 -0
- package/dist/detect/claude-code.d.ts.map +1 -0
- package/dist/detect/claude-code.js +82 -0
- package/dist/detect/claude-code.js.map +1 -0
- package/dist/detect/claude-desktop.d.ts +3 -0
- package/dist/detect/claude-desktop.d.ts.map +1 -0
- package/dist/detect/claude-desktop.js +89 -0
- package/dist/detect/claude-desktop.js.map +1 -0
- package/dist/detect/codex.d.ts +3 -0
- package/dist/detect/codex.d.ts.map +1 -0
- package/dist/detect/codex.js +64 -0
- package/dist/detect/codex.js.map +1 -0
- package/dist/detect/cursor.d.ts +3 -0
- package/dist/detect/cursor.d.ts.map +1 -0
- package/dist/detect/cursor.js +81 -0
- package/dist/detect/cursor.js.map +1 -0
- package/dist/detect/index.d.ts +3 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/detect/index.js +28 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/import/file-upload.d.ts +10 -0
- package/dist/import/file-upload.d.ts.map +1 -0
- package/dist/import/file-upload.js +37 -0
- package/dist/import/file-upload.js.map +1 -0
- package/dist/import/index.d.ts +11 -0
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +51 -0
- package/dist/import/index.js.map +1 -0
- package/dist/mcp/exports.d.ts +13 -0
- package/dist/mcp/exports.d.ts.map +1 -0
- package/dist/mcp/exports.js +13 -0
- package/dist/mcp/exports.js.map +1 -0
- package/dist/mcp/git-context.d.ts +17 -0
- package/dist/mcp/git-context.d.ts.map +1 -0
- package/dist/mcp/git-context.js +72 -0
- package/dist/mcp/git-context.js.map +1 -0
- package/dist/mcp/hooks/anthropic.d.ts +31 -0
- package/dist/mcp/hooks/anthropic.d.ts.map +1 -0
- package/dist/mcp/hooks/anthropic.js +137 -0
- package/dist/mcp/hooks/anthropic.js.map +1 -0
- package/dist/mcp/hooks/google.d.ts +53 -0
- package/dist/mcp/hooks/google.d.ts.map +1 -0
- package/dist/mcp/hooks/google.js +161 -0
- package/dist/mcp/hooks/google.js.map +1 -0
- package/dist/mcp/hooks/index.d.ts +9 -0
- package/dist/mcp/hooks/index.d.ts.map +1 -0
- package/dist/mcp/hooks/index.js +7 -0
- package/dist/mcp/hooks/index.js.map +1 -0
- package/dist/mcp/hooks/openai.d.ts +59 -0
- package/dist/mcp/hooks/openai.d.ts.map +1 -0
- package/dist/mcp/hooks/openai.js +158 -0
- package/dist/mcp/hooks/openai.js.map +1 -0
- package/dist/mcp/hooks/types.d.ts +8 -0
- package/dist/mcp/hooks/types.d.ts.map +1 -0
- package/dist/mcp/hooks/types.js +5 -0
- package/dist/mcp/hooks/types.js.map +1 -0
- package/dist/mcp/ingestor.d.ts +23 -0
- package/dist/mcp/ingestor.d.ts.map +1 -0
- package/dist/mcp/ingestor.js +310 -0
- package/dist/mcp/ingestor.js.map +1 -0
- package/dist/mcp/pricing.d.ts +19 -0
- package/dist/mcp/pricing.d.ts.map +1 -0
- package/dist/mcp/pricing.js +130 -0
- package/dist/mcp/pricing.js.map +1 -0
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +689 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/session-tracker.d.ts +52 -0
- package/dist/mcp/session-tracker.d.ts.map +1 -0
- package/dist/mcp/session-tracker.js +186 -0
- package/dist/mcp/session-tracker.js.map +1 -0
- package/dist/mcp/tools/analyze-spending-trend.d.ts +10 -0
- package/dist/mcp/tools/analyze-spending-trend.d.ts.map +1 -0
- package/dist/mcp/tools/analyze-spending-trend.js +126 -0
- package/dist/mcp/tools/analyze-spending-trend.js.map +1 -0
- package/dist/mcp/tools/get-budget-status.d.ts +9 -0
- package/dist/mcp/tools/get-budget-status.d.ts.map +1 -0
- package/dist/mcp/tools/get-budget-status.js +59 -0
- package/dist/mcp/tools/get-budget-status.js.map +1 -0
- package/dist/mcp/tools/get-cost-breakdown.d.ts +10 -0
- package/dist/mcp/tools/get-cost-breakdown.d.ts.map +1 -0
- package/dist/mcp/tools/get-cost-breakdown.js +52 -0
- package/dist/mcp/tools/get-cost-breakdown.js.map +1 -0
- package/dist/mcp/tools/get-model-efficiency.d.ts +9 -0
- package/dist/mcp/tools/get-model-efficiency.d.ts.map +1 -0
- package/dist/mcp/tools/get-model-efficiency.js +137 -0
- package/dist/mcp/tools/get-model-efficiency.js.map +1 -0
- package/dist/mcp/tools/get-recent-prompts.d.ts +13 -0
- package/dist/mcp/tools/get-recent-prompts.d.ts.map +1 -0
- package/dist/mcp/tools/get-recent-prompts.js +56 -0
- package/dist/mcp/tools/get-recent-prompts.js.map +1 -0
- package/dist/mcp/tools/get-roi-metrics.d.ts +9 -0
- package/dist/mcp/tools/get-roi-metrics.d.ts.map +1 -0
- package/dist/mcp/tools/get-roi-metrics.js +84 -0
- package/dist/mcp/tools/get-roi-metrics.js.map +1 -0
- package/dist/mcp/tools/get-usage-summary.d.ts +10 -0
- package/dist/mcp/tools/get-usage-summary.d.ts.map +1 -0
- package/dist/mcp/tools/get-usage-summary.js +47 -0
- package/dist/mcp/tools/get-usage-summary.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +221 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +161 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/list-projects.d.ts +6 -0
- package/dist/mcp/tools/list-projects.d.ts.map +1 -0
- package/dist/mcp/tools/list-projects.js +43 -0
- package/dist/mcp/tools/list-projects.js.map +1 -0
- package/dist/mcp/tools/optimize-prompt.d.ts +44 -0
- package/dist/mcp/tools/optimize-prompt.d.ts.map +1 -0
- package/dist/mcp/tools/optimize-prompt.js +95 -0
- package/dist/mcp/tools/optimize-prompt.js.map +1 -0
- package/dist/mcp/types.d.ts +118 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +5 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/update-check/check.d.ts +6 -0
- package/dist/update-check/check.d.ts.map +1 -0
- package/dist/update-check/check.js +64 -0
- package/dist/update-check/check.js.map +1 -0
- package/dist/update-check/notify.d.ts +6 -0
- package/dist/update-check/notify.d.ts.map +1 -0
- package/dist/update-check/notify.js +40 -0
- package/dist/update-check/notify.js.map +1 -0
- package/dist/verify.d.ts +7 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +40 -0
- package/dist/verify.js.map +1 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +21 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -113,7 +113,7 @@ function compareSemver(a, b) {
|
|
|
113
113
|
}
|
|
114
114
|
return 0;
|
|
115
115
|
}
|
|
116
|
-
var VERSION = "0.
|
|
116
|
+
var VERSION = "0.8.0";
|
|
117
117
|
|
|
118
118
|
// src/auth/credentials.ts
|
|
119
119
|
import { readFileSync, writeFileSync, rmSync, mkdirSync, chmodSync, renameSync } from "node:fs";
|
|
@@ -19231,7 +19231,7 @@ function readJsonLines(filePath) {
|
|
|
19231
19231
|
}
|
|
19232
19232
|
return results;
|
|
19233
19233
|
}
|
|
19234
|
-
function flattenContent(content) {
|
|
19234
|
+
function flattenContent(content, opts) {
|
|
19235
19235
|
if (!content)
|
|
19236
19236
|
return;
|
|
19237
19237
|
if (typeof content === "string")
|
|
@@ -19241,8 +19241,15 @@ function flattenContent(content) {
|
|
|
19241
19241
|
if (!item || typeof item !== "object")
|
|
19242
19242
|
return "";
|
|
19243
19243
|
const typed = item;
|
|
19244
|
-
if (typed.type === "
|
|
19244
|
+
if (typed.type === "tool_use")
|
|
19245
19245
|
return "";
|
|
19246
|
+
if (typed.type === "thinking" || typed.type === "reasoning") {
|
|
19247
|
+
if (opts?.includeThinking) {
|
|
19248
|
+
const thinkingText = typed.text ?? typed.input_text ?? typed.output_text ?? "";
|
|
19249
|
+
return thinkingText ? `[thinking]${thinkingText}[/thinking]` : "";
|
|
19250
|
+
}
|
|
19251
|
+
return "";
|
|
19252
|
+
}
|
|
19246
19253
|
return typed.text ?? typed.input_text ?? typed.output_text ?? "";
|
|
19247
19254
|
}).filter(Boolean);
|
|
19248
19255
|
return parts.length ? parts.join(`
|
|
@@ -19257,6 +19264,102 @@ function estimateTokens(prompt, response) {
|
|
|
19257
19264
|
}
|
|
19258
19265
|
var init_parsing_utils = () => {};
|
|
19259
19266
|
|
|
19267
|
+
// src/agent-hooks/tool-extraction.ts
|
|
19268
|
+
function parseToolInput(toolName, input) {
|
|
19269
|
+
const isShell = SHELL_TOOL_NAMES.has(toolName);
|
|
19270
|
+
const truncLimit = isShell ? TRUNCATION_BASH : TRUNCATION_DEFAULT;
|
|
19271
|
+
let raw;
|
|
19272
|
+
let command;
|
|
19273
|
+
if (typeof input === "string") {
|
|
19274
|
+
raw = input.slice(0, truncLimit);
|
|
19275
|
+
if (isShell) {
|
|
19276
|
+
if (input.length > 0) {
|
|
19277
|
+
try {
|
|
19278
|
+
const parsed = JSON.parse(input);
|
|
19279
|
+
command = extractCommandFromObject(parsed);
|
|
19280
|
+
} catch {
|
|
19281
|
+
command = input.slice(0, truncLimit);
|
|
19282
|
+
}
|
|
19283
|
+
}
|
|
19284
|
+
}
|
|
19285
|
+
} else if (input !== null && typeof input === "object") {
|
|
19286
|
+
if (isShell) {
|
|
19287
|
+
command = extractCommandFromObject(input);
|
|
19288
|
+
}
|
|
19289
|
+
try {
|
|
19290
|
+
raw = JSON.stringify(input).slice(0, truncLimit);
|
|
19291
|
+
} catch {
|
|
19292
|
+
raw = String(input).slice(0, truncLimit);
|
|
19293
|
+
}
|
|
19294
|
+
} else {
|
|
19295
|
+
raw = String(input ?? "").slice(0, truncLimit);
|
|
19296
|
+
}
|
|
19297
|
+
if (command !== undefined) {
|
|
19298
|
+
command = command.slice(0, truncLimit);
|
|
19299
|
+
}
|
|
19300
|
+
const command_type = command !== undefined ? detectCommandType(command) : undefined;
|
|
19301
|
+
return { raw, command, command_type };
|
|
19302
|
+
}
|
|
19303
|
+
function extractCommandFromObject(obj) {
|
|
19304
|
+
const cmd = obj["command"] ?? obj["cmd"] ?? obj["shell_command"];
|
|
19305
|
+
return typeof cmd === "string" ? cmd : undefined;
|
|
19306
|
+
}
|
|
19307
|
+
function detectCommandType(command) {
|
|
19308
|
+
const first = command.trim().split(/\s+/)[0] ?? "";
|
|
19309
|
+
const basename = first.split("/").pop() ?? first;
|
|
19310
|
+
return COMMAND_TYPE_MAP[basename.toLowerCase()] ?? "shell";
|
|
19311
|
+
}
|
|
19312
|
+
var SHELL_TOOL_NAMES, TRUNCATION_BASH = 2000, TRUNCATION_DEFAULT = 500, COMMAND_TYPE_MAP;
|
|
19313
|
+
var init_tool_extraction = __esm(() => {
|
|
19314
|
+
SHELL_TOOL_NAMES = new Set([
|
|
19315
|
+
"Bash",
|
|
19316
|
+
"bash",
|
|
19317
|
+
"shell",
|
|
19318
|
+
"Shell",
|
|
19319
|
+
"exec",
|
|
19320
|
+
"run_command",
|
|
19321
|
+
"computer"
|
|
19322
|
+
]);
|
|
19323
|
+
COMMAND_TYPE_MAP = {
|
|
19324
|
+
git: "git",
|
|
19325
|
+
npm: "npm",
|
|
19326
|
+
npx: "npm",
|
|
19327
|
+
bun: "bun",
|
|
19328
|
+
bunx: "bun",
|
|
19329
|
+
node: "node",
|
|
19330
|
+
python: "python",
|
|
19331
|
+
python3: "python",
|
|
19332
|
+
pip: "python",
|
|
19333
|
+
pip3: "python",
|
|
19334
|
+
tsc: "typescript",
|
|
19335
|
+
vitest: "test",
|
|
19336
|
+
jest: "test",
|
|
19337
|
+
pytest: "test",
|
|
19338
|
+
mocha: "test",
|
|
19339
|
+
curl: "http",
|
|
19340
|
+
wget: "http",
|
|
19341
|
+
cat: "file",
|
|
19342
|
+
ls: "file",
|
|
19343
|
+
find: "file",
|
|
19344
|
+
cp: "file",
|
|
19345
|
+
mv: "file",
|
|
19346
|
+
rm: "file",
|
|
19347
|
+
mkdir: "file",
|
|
19348
|
+
grep: "search",
|
|
19349
|
+
rg: "search",
|
|
19350
|
+
sed: "transform",
|
|
19351
|
+
awk: "transform",
|
|
19352
|
+
docker: "docker",
|
|
19353
|
+
"docker-compose": "docker",
|
|
19354
|
+
kubectl: "kubernetes",
|
|
19355
|
+
helm: "kubernetes",
|
|
19356
|
+
terraform: "infrastructure",
|
|
19357
|
+
gh: "github",
|
|
19358
|
+
supabase: "supabase",
|
|
19359
|
+
bd: "beads"
|
|
19360
|
+
};
|
|
19361
|
+
});
|
|
19362
|
+
|
|
19260
19363
|
// src/platforms/parsers/claude-code.ts
|
|
19261
19364
|
import fs7 from "node:fs";
|
|
19262
19365
|
import path6 from "node:path";
|
|
@@ -19296,6 +19399,101 @@ function findConversationFiles(baseDir) {
|
|
|
19296
19399
|
walk(baseDir);
|
|
19297
19400
|
return results;
|
|
19298
19401
|
}
|
|
19402
|
+
function extractToolCallTraces(entries) {
|
|
19403
|
+
const toolUseBlocks = new Map;
|
|
19404
|
+
for (const entry of entries) {
|
|
19405
|
+
const content = entry.message?.content;
|
|
19406
|
+
if (!Array.isArray(content))
|
|
19407
|
+
continue;
|
|
19408
|
+
if ((entry.message?.role ?? entry.type) !== "assistant")
|
|
19409
|
+
continue;
|
|
19410
|
+
for (const block of content) {
|
|
19411
|
+
if (!block || typeof block !== "object")
|
|
19412
|
+
continue;
|
|
19413
|
+
const b = block;
|
|
19414
|
+
if (b.type === "tool_use" && typeof b.id === "string") {
|
|
19415
|
+
toolUseBlocks.set(b.id, {
|
|
19416
|
+
id: b.id,
|
|
19417
|
+
name: b.name ?? "unknown",
|
|
19418
|
+
input: b.input,
|
|
19419
|
+
startTimestamp: b.start_timestamp,
|
|
19420
|
+
stopTimestamp: b.stop_timestamp,
|
|
19421
|
+
entryTimestamp: entry.timestamp
|
|
19422
|
+
});
|
|
19423
|
+
}
|
|
19424
|
+
}
|
|
19425
|
+
}
|
|
19426
|
+
const toolResults = new Map;
|
|
19427
|
+
for (const entry of entries) {
|
|
19428
|
+
const content = entry.message?.content ?? entry.content;
|
|
19429
|
+
if (!Array.isArray(content))
|
|
19430
|
+
continue;
|
|
19431
|
+
const role = entry.message?.role ?? entry.type;
|
|
19432
|
+
if (role !== "user" && role !== "human")
|
|
19433
|
+
continue;
|
|
19434
|
+
for (const block of content) {
|
|
19435
|
+
if (!block || typeof block !== "object")
|
|
19436
|
+
continue;
|
|
19437
|
+
const b = block;
|
|
19438
|
+
if (b.type === "tool_result" && typeof b.tool_use_id === "string") {
|
|
19439
|
+
const rawContent = b.content;
|
|
19440
|
+
let output = "";
|
|
19441
|
+
if (typeof rawContent === "string") {
|
|
19442
|
+
output = rawContent.slice(0, 500);
|
|
19443
|
+
} else if (Array.isArray(rawContent)) {
|
|
19444
|
+
output = rawContent.map((c) => {
|
|
19445
|
+
if (!c || typeof c !== "object")
|
|
19446
|
+
return "";
|
|
19447
|
+
return c.text ?? "";
|
|
19448
|
+
}).join(`
|
|
19449
|
+
`).slice(0, 500);
|
|
19450
|
+
}
|
|
19451
|
+
toolResults.set(b.tool_use_id, {
|
|
19452
|
+
toolUseId: b.tool_use_id,
|
|
19453
|
+
isError: Boolean(b.is_error),
|
|
19454
|
+
output
|
|
19455
|
+
});
|
|
19456
|
+
}
|
|
19457
|
+
}
|
|
19458
|
+
}
|
|
19459
|
+
const traces = [];
|
|
19460
|
+
for (const [id, toolUse] of toolUseBlocks) {
|
|
19461
|
+
const result = toolResults.get(id);
|
|
19462
|
+
const startTs = toolUse.startTimestamp ?? toolUse.entryTimestamp ?? new Date().toISOString();
|
|
19463
|
+
const stopTs = toolUse.stopTimestamp ?? startTs;
|
|
19464
|
+
const durationMs = startTs && stopTs ? Math.max(0, new Date(stopTs).getTime() - new Date(startTs).getTime()) : undefined;
|
|
19465
|
+
const parsed = parseToolInput(toolUse.name, toolUse.input);
|
|
19466
|
+
const startedMetadata = {
|
|
19467
|
+
tool: toolUse.name
|
|
19468
|
+
};
|
|
19469
|
+
if (parsed.command !== undefined)
|
|
19470
|
+
startedMetadata["command"] = parsed.command;
|
|
19471
|
+
if (parsed.command_type !== undefined)
|
|
19472
|
+
startedMetadata["command_type"] = parsed.command_type;
|
|
19473
|
+
traces.push({
|
|
19474
|
+
type: "step.started",
|
|
19475
|
+
step_id: id,
|
|
19476
|
+
name: toolUse.name,
|
|
19477
|
+
timestamp: startTs,
|
|
19478
|
+
input: parsed.raw,
|
|
19479
|
+
metadata: startedMetadata
|
|
19480
|
+
});
|
|
19481
|
+
traces.push({
|
|
19482
|
+
type: "step.completed",
|
|
19483
|
+
step_id: id,
|
|
19484
|
+
name: toolUse.name,
|
|
19485
|
+
timestamp: stopTs,
|
|
19486
|
+
output: result?.output,
|
|
19487
|
+
metadata: {
|
|
19488
|
+
tool: toolUse.name,
|
|
19489
|
+
success: result ? !result.isError : true,
|
|
19490
|
+
duration_ms: durationMs,
|
|
19491
|
+
...parsed.command_type !== undefined ? { command_type: parsed.command_type } : {}
|
|
19492
|
+
}
|
|
19493
|
+
});
|
|
19494
|
+
}
|
|
19495
|
+
return traces;
|
|
19496
|
+
}
|
|
19299
19497
|
|
|
19300
19498
|
class ClaudeCodeParser {
|
|
19301
19499
|
info = {
|
|
@@ -19316,6 +19514,7 @@ class ClaudeCodeParser {
|
|
|
19316
19514
|
const sessions = claudeState?.sessions ?? {};
|
|
19317
19515
|
const warnings = [];
|
|
19318
19516
|
const events = [];
|
|
19517
|
+
const toolCalls = [];
|
|
19319
19518
|
const files = this.discover();
|
|
19320
19519
|
for (const filePath of files) {
|
|
19321
19520
|
const relative = path6.relative(this.baseDir, filePath);
|
|
@@ -19381,6 +19580,8 @@ class ClaudeCodeParser {
|
|
|
19381
19580
|
events.push(event);
|
|
19382
19581
|
}
|
|
19383
19582
|
}
|
|
19583
|
+
const fileToolCalls = extractToolCallTraces(newEntries);
|
|
19584
|
+
toolCalls.push(...fileToolCalls);
|
|
19384
19585
|
const lastEntry = newEntries[newEntries.length - 1];
|
|
19385
19586
|
const lastEntryId = getEntryId(lastEntry);
|
|
19386
19587
|
if (lastEntryId) {
|
|
@@ -19392,11 +19593,12 @@ class ClaudeCodeParser {
|
|
|
19392
19593
|
sessions,
|
|
19393
19594
|
lastSyncTimestamp: new Date().toISOString()
|
|
19394
19595
|
};
|
|
19395
|
-
return { events, newState, warnings };
|
|
19596
|
+
return { events, newState, warnings, ...toolCalls.length > 0 ? { toolCalls } : {} };
|
|
19396
19597
|
}
|
|
19397
19598
|
}
|
|
19398
19599
|
var init_claude_code = __esm(() => {
|
|
19399
19600
|
init_parsing_utils();
|
|
19601
|
+
init_tool_extraction();
|
|
19400
19602
|
});
|
|
19401
19603
|
|
|
19402
19604
|
// src/platforms/parsers/codex.ts
|
|
@@ -20093,6 +20295,9 @@ async function syncPlatforms(config, options = {}) {
|
|
|
20093
20295
|
platformCost += event.cost ?? 0;
|
|
20094
20296
|
await ingestor.track(event);
|
|
20095
20297
|
}
|
|
20298
|
+
if (config.traceEnabled && config.traceUrl && result.toolCalls && result.toolCalls.length > 0) {
|
|
20299
|
+
await sendToolCallTraces(config, parser.info.id, result.toolCalls);
|
|
20300
|
+
}
|
|
20096
20301
|
savePlatformState(config.stateDir, parser.info.id, result.newState);
|
|
20097
20302
|
platformResults.push({
|
|
20098
20303
|
id: parser.info.id,
|
|
@@ -20117,6 +20322,31 @@ async function syncPlatforms(config, options = {}) {
|
|
|
20117
20322
|
ingestor.destroy();
|
|
20118
20323
|
return { platforms: platformResults, totalEvents, totalCost };
|
|
20119
20324
|
}
|
|
20325
|
+
async function sendToolCallTraces(config, platformId, toolCalls) {
|
|
20326
|
+
if (!config.traceUrl)
|
|
20327
|
+
return;
|
|
20328
|
+
const payload = {
|
|
20329
|
+
trace_id: `sync:${platformId}:${new Date().toISOString()}`,
|
|
20330
|
+
name: `${platformId}-tool-calls`,
|
|
20331
|
+
events: toolCalls
|
|
20332
|
+
};
|
|
20333
|
+
try {
|
|
20334
|
+
const response = await fetch(config.traceUrl, {
|
|
20335
|
+
method: "POST",
|
|
20336
|
+
headers: {
|
|
20337
|
+
"Content-Type": "application/json",
|
|
20338
|
+
Authorization: `Bearer ${config.apiKey}`
|
|
20339
|
+
},
|
|
20340
|
+
body: JSON.stringify(payload)
|
|
20341
|
+
});
|
|
20342
|
+
if (!response.ok) {
|
|
20343
|
+
const text = await response.text();
|
|
20344
|
+
console.warn(`[VerbalTrace] Tool call trace ingest failed (${response.status}): ${text}`);
|
|
20345
|
+
}
|
|
20346
|
+
} catch (error) {
|
|
20347
|
+
console.warn("[VerbalTrace] Tool call trace ingest failed:", error);
|
|
20348
|
+
}
|
|
20349
|
+
}
|
|
20120
20350
|
function mapParsedEventToUsageEvent(event, project) {
|
|
20121
20351
|
const cost = event.billing_type === "subscription" ? 0 : calculateCost(event.model, event.tokens_in, event.tokens_out, event.cache_read_tokens, event.cache_write_tokens);
|
|
20122
20352
|
return {
|
|
@@ -20437,6 +20667,234 @@ var init_update = __esm(() => {
|
|
|
20437
20667
|
import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
20438
20668
|
});
|
|
20439
20669
|
|
|
20670
|
+
// src/commands/keys.ts
|
|
20671
|
+
var exports_keys = {};
|
|
20672
|
+
__export(exports_keys, {
|
|
20673
|
+
runKeys: () => runKeys
|
|
20674
|
+
});
|
|
20675
|
+
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
20676
|
+
function isValidProvider(value) {
|
|
20677
|
+
return VALID_PROVIDERS.includes(value);
|
|
20678
|
+
}
|
|
20679
|
+
async function keysAdd(provider) {
|
|
20680
|
+
if (!isValidProvider(provider)) {
|
|
20681
|
+
console.error(import_picocolors8.default.red(`✗ Invalid provider: ${import_picocolors8.default.bold(provider)}`));
|
|
20682
|
+
console.log(import_picocolors8.default.dim(` Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
20683
|
+
process.exitCode = 1;
|
|
20684
|
+
return;
|
|
20685
|
+
}
|
|
20686
|
+
const credentials = await readCredentials();
|
|
20687
|
+
if (!credentials) {
|
|
20688
|
+
console.error(import_picocolors8.default.red("✗ Not authenticated. Run `getverbal init` first."));
|
|
20689
|
+
process.exitCode = 1;
|
|
20690
|
+
return;
|
|
20691
|
+
}
|
|
20692
|
+
const displayName = PROVIDER_DISPLAY[provider];
|
|
20693
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
20694
|
+
try {
|
|
20695
|
+
const apiKey = await rl.question(`Enter your ${displayName} Admin API key: `);
|
|
20696
|
+
if (!apiKey.trim()) {
|
|
20697
|
+
console.error(import_picocolors8.default.red("✗ API key cannot be empty."));
|
|
20698
|
+
process.exitCode = 1;
|
|
20699
|
+
return;
|
|
20700
|
+
}
|
|
20701
|
+
const res = await fetch(`${credentials.api_url}/api/v1/provider-keys`, {
|
|
20702
|
+
method: "POST",
|
|
20703
|
+
headers: {
|
|
20704
|
+
Authorization: `Bearer ${credentials.api_key}`,
|
|
20705
|
+
"Content-Type": "application/json"
|
|
20706
|
+
},
|
|
20707
|
+
body: JSON.stringify({ provider, key: apiKey.trim() })
|
|
20708
|
+
});
|
|
20709
|
+
if (!res.ok) {
|
|
20710
|
+
const body = await res.text().catch(() => "");
|
|
20711
|
+
let errorMessage = `HTTP ${res.status}`;
|
|
20712
|
+
try {
|
|
20713
|
+
const json = JSON.parse(body);
|
|
20714
|
+
if (json.error)
|
|
20715
|
+
errorMessage = json.error;
|
|
20716
|
+
} catch {}
|
|
20717
|
+
console.error(import_picocolors8.default.red(`✗ Failed to add ${displayName} key: ${errorMessage}`));
|
|
20718
|
+
process.exitCode = 1;
|
|
20719
|
+
return;
|
|
20720
|
+
}
|
|
20721
|
+
const data = await res.json();
|
|
20722
|
+
console.log();
|
|
20723
|
+
console.log(import_picocolors8.default.green(`✓ ${displayName} API key added`));
|
|
20724
|
+
console.log(import_picocolors8.default.dim(` Prefix: ${data.key_prefix}`));
|
|
20725
|
+
if (data.verified) {
|
|
20726
|
+
console.log(import_picocolors8.default.green(` ✓ Key verified`));
|
|
20727
|
+
} else {
|
|
20728
|
+
console.log(import_picocolors8.default.dim(` Key stored (verification pending)`));
|
|
20729
|
+
}
|
|
20730
|
+
} finally {
|
|
20731
|
+
rl.close();
|
|
20732
|
+
}
|
|
20733
|
+
}
|
|
20734
|
+
async function keysList() {
|
|
20735
|
+
const credentials = await readCredentials();
|
|
20736
|
+
if (!credentials) {
|
|
20737
|
+
console.error(import_picocolors8.default.red("✗ Not authenticated. Run `getverbal init` first."));
|
|
20738
|
+
process.exitCode = 1;
|
|
20739
|
+
return;
|
|
20740
|
+
}
|
|
20741
|
+
const res = await fetch(`${credentials.api_url}/api/v1/provider-keys`, {
|
|
20742
|
+
method: "GET",
|
|
20743
|
+
headers: {
|
|
20744
|
+
Authorization: `Bearer ${credentials.api_key}`
|
|
20745
|
+
}
|
|
20746
|
+
});
|
|
20747
|
+
if (!res.ok) {
|
|
20748
|
+
const body = await res.text().catch(() => "");
|
|
20749
|
+
let errorMessage = `HTTP ${res.status}`;
|
|
20750
|
+
try {
|
|
20751
|
+
const json2 = JSON.parse(body);
|
|
20752
|
+
if (json2.error)
|
|
20753
|
+
errorMessage = json2.error;
|
|
20754
|
+
} catch {}
|
|
20755
|
+
console.error(import_picocolors8.default.red(`✗ Failed to list provider keys: ${errorMessage}`));
|
|
20756
|
+
process.exitCode = 1;
|
|
20757
|
+
return;
|
|
20758
|
+
}
|
|
20759
|
+
const json = await res.json();
|
|
20760
|
+
const data = json.keys ?? [];
|
|
20761
|
+
if (data.length === 0) {
|
|
20762
|
+
console.log(import_picocolors8.default.dim("No provider keys configured. Run `getverbal keys add <provider>` to add one."));
|
|
20763
|
+
return;
|
|
20764
|
+
}
|
|
20765
|
+
console.log();
|
|
20766
|
+
console.log(import_picocolors8.default.bold("Provider Keys:"));
|
|
20767
|
+
console.log();
|
|
20768
|
+
const COL_PROVIDER = 12;
|
|
20769
|
+
const COL_PREFIX = 20;
|
|
20770
|
+
const COL_STATUS = 16;
|
|
20771
|
+
const header = import_picocolors8.default.dim("Provider".padEnd(COL_PROVIDER)) + import_picocolors8.default.dim("Key Prefix".padEnd(COL_PREFIX)) + import_picocolors8.default.dim("Sync Status".padEnd(COL_STATUS)) + import_picocolors8.default.dim("Last Synced");
|
|
20772
|
+
console.log(" " + header);
|
|
20773
|
+
console.log(" " + import_picocolors8.default.dim("─".repeat(64)));
|
|
20774
|
+
for (const key of data) {
|
|
20775
|
+
const lastSync = key.last_sync_at ? new Date(key.last_sync_at).toLocaleDateString() : import_picocolors8.default.dim("Never");
|
|
20776
|
+
const statusColor = key.sync_status === "ok" || key.sync_status === "active" ? import_picocolors8.default.green(key.sync_status) : import_picocolors8.default.yellow(key.sync_status);
|
|
20777
|
+
const row = key.provider.padEnd(COL_PROVIDER) + key.key_prefix.padEnd(COL_PREFIX) + statusColor.padEnd(COL_STATUS + 10) + lastSync;
|
|
20778
|
+
console.log(" " + row);
|
|
20779
|
+
}
|
|
20780
|
+
console.log();
|
|
20781
|
+
}
|
|
20782
|
+
async function keysRemove(provider) {
|
|
20783
|
+
if (!isValidProvider(provider)) {
|
|
20784
|
+
console.error(import_picocolors8.default.red(`✗ Invalid provider: ${import_picocolors8.default.bold(provider)}`));
|
|
20785
|
+
console.log(import_picocolors8.default.dim(` Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
20786
|
+
process.exitCode = 1;
|
|
20787
|
+
return;
|
|
20788
|
+
}
|
|
20789
|
+
const credentials = await readCredentials();
|
|
20790
|
+
if (!credentials) {
|
|
20791
|
+
console.error(import_picocolors8.default.red("✗ Not authenticated. Run `getverbal init` first."));
|
|
20792
|
+
process.exitCode = 1;
|
|
20793
|
+
return;
|
|
20794
|
+
}
|
|
20795
|
+
const displayName = PROVIDER_DISPLAY[provider];
|
|
20796
|
+
const rl = createInterface4({ input: process.stdin, output: process.stdout });
|
|
20797
|
+
try {
|
|
20798
|
+
const answer = await rl.question(`Remove ${import_picocolors8.default.bold(displayName)} key? (y/N) `);
|
|
20799
|
+
const trimmed = answer.trim().toLowerCase();
|
|
20800
|
+
if (trimmed !== "y" && trimmed !== "yes") {
|
|
20801
|
+
console.log(import_picocolors8.default.dim("Cancelled."));
|
|
20802
|
+
return;
|
|
20803
|
+
}
|
|
20804
|
+
const url = new URL(`${credentials.api_url}/api/v1/provider-keys`);
|
|
20805
|
+
url.searchParams.set("provider", provider);
|
|
20806
|
+
const res = await fetch(url.toString(), {
|
|
20807
|
+
method: "DELETE",
|
|
20808
|
+
headers: {
|
|
20809
|
+
Authorization: `Bearer ${credentials.api_key}`
|
|
20810
|
+
}
|
|
20811
|
+
});
|
|
20812
|
+
if (!res.ok) {
|
|
20813
|
+
const body = await res.text().catch(() => "");
|
|
20814
|
+
let errorMessage = `HTTP ${res.status}`;
|
|
20815
|
+
try {
|
|
20816
|
+
const json = JSON.parse(body);
|
|
20817
|
+
if (json.error)
|
|
20818
|
+
errorMessage = json.error;
|
|
20819
|
+
} catch {}
|
|
20820
|
+
console.error(import_picocolors8.default.red(`✗ Failed to remove ${displayName} key: ${errorMessage}`));
|
|
20821
|
+
process.exitCode = 1;
|
|
20822
|
+
return;
|
|
20823
|
+
}
|
|
20824
|
+
console.log(import_picocolors8.default.green(`✓ ${displayName} key removed`));
|
|
20825
|
+
} finally {
|
|
20826
|
+
rl.close();
|
|
20827
|
+
}
|
|
20828
|
+
}
|
|
20829
|
+
async function runKeys(args) {
|
|
20830
|
+
const subcommand = args[0];
|
|
20831
|
+
switch (subcommand) {
|
|
20832
|
+
case "add": {
|
|
20833
|
+
const provider = args[1];
|
|
20834
|
+
if (!provider) {
|
|
20835
|
+
console.error(import_picocolors8.default.red("✗ Missing provider. Usage: getverbal keys add <provider>"));
|
|
20836
|
+
console.log(import_picocolors8.default.dim(` Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
20837
|
+
process.exitCode = 1;
|
|
20838
|
+
return;
|
|
20839
|
+
}
|
|
20840
|
+
await keysAdd(provider);
|
|
20841
|
+
break;
|
|
20842
|
+
}
|
|
20843
|
+
case "list":
|
|
20844
|
+
await keysList();
|
|
20845
|
+
break;
|
|
20846
|
+
case "remove": {
|
|
20847
|
+
const provider = args[1];
|
|
20848
|
+
if (!provider) {
|
|
20849
|
+
console.error(import_picocolors8.default.red("✗ Missing provider. Usage: getverbal keys remove <provider>"));
|
|
20850
|
+
console.log(import_picocolors8.default.dim(` Valid providers: ${VALID_PROVIDERS.join(", ")}`));
|
|
20851
|
+
process.exitCode = 1;
|
|
20852
|
+
return;
|
|
20853
|
+
}
|
|
20854
|
+
await keysRemove(provider);
|
|
20855
|
+
break;
|
|
20856
|
+
}
|
|
20857
|
+
case "--help":
|
|
20858
|
+
case "-h":
|
|
20859
|
+
case undefined:
|
|
20860
|
+
console.log(KEYS_HELP);
|
|
20861
|
+
break;
|
|
20862
|
+
default:
|
|
20863
|
+
console.error(`${import_picocolors8.default.red("Unknown subcommand:")} ${subcommand}
|
|
20864
|
+
`);
|
|
20865
|
+
console.log(KEYS_HELP);
|
|
20866
|
+
process.exitCode = 1;
|
|
20867
|
+
}
|
|
20868
|
+
}
|
|
20869
|
+
var import_picocolors8, VALID_PROVIDERS, PROVIDER_DISPLAY, KEYS_HELP;
|
|
20870
|
+
var init_keys = __esm(() => {
|
|
20871
|
+
init_credentials();
|
|
20872
|
+
import_picocolors8 = __toESM(require_picocolors(), 1);
|
|
20873
|
+
VALID_PROVIDERS = ["anthropic", "openai", "google"];
|
|
20874
|
+
PROVIDER_DISPLAY = {
|
|
20875
|
+
anthropic: "Anthropic",
|
|
20876
|
+
openai: "OpenAI",
|
|
20877
|
+
google: "Google"
|
|
20878
|
+
};
|
|
20879
|
+
KEYS_HELP = `
|
|
20880
|
+
${import_picocolors8.default.bold("getverbal keys")} — Manage provider API keys
|
|
20881
|
+
|
|
20882
|
+
${import_picocolors8.default.dim("Usage:")} getverbal keys <subcommand> [provider]
|
|
20883
|
+
|
|
20884
|
+
${import_picocolors8.default.dim("Subcommands:")}
|
|
20885
|
+
add <provider> Add a provider API key
|
|
20886
|
+
list List all configured provider keys
|
|
20887
|
+
remove <provider> Remove a provider API key
|
|
20888
|
+
|
|
20889
|
+
${import_picocolors8.default.dim("Providers:")} ${VALID_PROVIDERS.join(", ")}
|
|
20890
|
+
|
|
20891
|
+
${import_picocolors8.default.dim("Examples:")}
|
|
20892
|
+
getverbal keys add anthropic
|
|
20893
|
+
getverbal keys list
|
|
20894
|
+
getverbal keys remove openai
|
|
20895
|
+
`.trim();
|
|
20896
|
+
});
|
|
20897
|
+
|
|
20440
20898
|
// src/commands/sync.ts
|
|
20441
20899
|
var exports_sync = {};
|
|
20442
20900
|
__export(exports_sync, {
|
|
@@ -20445,12 +20903,12 @@ __export(exports_sync, {
|
|
|
20445
20903
|
async function runSync() {
|
|
20446
20904
|
const creds = await readCredentials();
|
|
20447
20905
|
if (!creds) {
|
|
20448
|
-
console.error(
|
|
20906
|
+
console.error(import_picocolors9.default.red("Not authenticated. Run `getverbal init` first."));
|
|
20449
20907
|
process.exitCode = 1;
|
|
20450
20908
|
return;
|
|
20451
20909
|
}
|
|
20452
20910
|
console.log(`
|
|
20453
|
-
${
|
|
20911
|
+
${import_picocolors9.default.bold("Syncing AI tool usage...")}
|
|
20454
20912
|
`);
|
|
20455
20913
|
const stateDir = getDefaultStateDir();
|
|
20456
20914
|
let result;
|
|
@@ -20465,36 +20923,36 @@ ${import_picocolors8.default.bold("Syncing AI tool usage...")}
|
|
|
20465
20923
|
stateDir
|
|
20466
20924
|
});
|
|
20467
20925
|
} catch (err) {
|
|
20468
|
-
console.error(
|
|
20926
|
+
console.error(import_picocolors9.default.red(`Sync failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
20469
20927
|
process.exitCode = 1;
|
|
20470
20928
|
return;
|
|
20471
20929
|
}
|
|
20472
20930
|
for (const p of result.platforms) {
|
|
20473
20931
|
if (p.error) {
|
|
20474
|
-
console.log(` ${
|
|
20932
|
+
console.log(` ${import_picocolors9.default.dim(p.id.padEnd(14))} ${import_picocolors9.default.yellow("⚠")} ${import_picocolors9.default.dim(p.error)}`);
|
|
20475
20933
|
} else if (p.events === 0) {
|
|
20476
|
-
console.log(` ${
|
|
20934
|
+
console.log(` ${import_picocolors9.default.dim(p.id.padEnd(14))} ${import_picocolors9.default.dim("0 events")} ${import_picocolors9.default.green("✓")}`);
|
|
20477
20935
|
} else {
|
|
20478
|
-
const costStr = p.totalCost > 0 ? `$${p.totalCost.toFixed(2)}` :
|
|
20479
|
-
const billingNote = p.totalCost === 0 && p.events > 0 ?
|
|
20480
|
-
console.log(` ${
|
|
20936
|
+
const costStr = p.totalCost > 0 ? `$${p.totalCost.toFixed(2)}` : import_picocolors9.default.dim("—");
|
|
20937
|
+
const billingNote = p.totalCost === 0 && p.events > 0 ? import_picocolors9.default.dim(" (subscription)") : "";
|
|
20938
|
+
console.log(` ${import_picocolors9.default.dim(p.id.padEnd(14))} ${import_picocolors9.default.bold(String(p.events))} events ${costStr}${billingNote} ${import_picocolors9.default.green("✓")}`);
|
|
20481
20939
|
}
|
|
20482
20940
|
}
|
|
20483
20941
|
console.log();
|
|
20484
20942
|
if (result.totalEvents === 0) {
|
|
20485
|
-
console.log(
|
|
20943
|
+
console.log(import_picocolors9.default.dim("No new events since last sync."));
|
|
20486
20944
|
} else {
|
|
20487
20945
|
const costStr = result.totalCost > 0 ? `, $${result.totalCost.toFixed(2)} in spend` : "";
|
|
20488
|
-
console.log(`${
|
|
20946
|
+
console.log(`${import_picocolors9.default.green("✓")} ${import_picocolors9.default.bold(String(result.totalEvents))} events synced${costStr}`);
|
|
20489
20947
|
}
|
|
20490
20948
|
console.log();
|
|
20491
20949
|
}
|
|
20492
|
-
var
|
|
20950
|
+
var import_picocolors9, DEFAULT_BATCH_SIZE = 50, DEFAULT_FLUSH_MS = 0, DEFAULT_TIMEOUT_MS = 30000;
|
|
20493
20951
|
var init_sync = __esm(() => {
|
|
20494
20952
|
init_credentials();
|
|
20495
20953
|
init_orchestrator();
|
|
20496
20954
|
init_preflight_state();
|
|
20497
|
-
|
|
20955
|
+
import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
20498
20956
|
});
|
|
20499
20957
|
|
|
20500
20958
|
// node_modules/zod/v4/core/core.js
|
|
@@ -34918,102 +35376,6 @@ async function sendTrace(config3, traceId, name, events) {
|
|
|
34918
35376
|
}
|
|
34919
35377
|
}
|
|
34920
35378
|
|
|
34921
|
-
// src/agent-hooks/tool-extraction.ts
|
|
34922
|
-
function parseToolInput(toolName, input) {
|
|
34923
|
-
const isShell = SHELL_TOOL_NAMES.has(toolName);
|
|
34924
|
-
const truncLimit = isShell ? TRUNCATION_BASH : TRUNCATION_DEFAULT;
|
|
34925
|
-
let raw;
|
|
34926
|
-
let command;
|
|
34927
|
-
if (typeof input === "string") {
|
|
34928
|
-
raw = input.slice(0, truncLimit);
|
|
34929
|
-
if (isShell) {
|
|
34930
|
-
if (input.length > 0) {
|
|
34931
|
-
try {
|
|
34932
|
-
const parsed = JSON.parse(input);
|
|
34933
|
-
command = extractCommandFromObject(parsed);
|
|
34934
|
-
} catch {
|
|
34935
|
-
command = input.slice(0, truncLimit);
|
|
34936
|
-
}
|
|
34937
|
-
}
|
|
34938
|
-
}
|
|
34939
|
-
} else if (input !== null && typeof input === "object") {
|
|
34940
|
-
if (isShell) {
|
|
34941
|
-
command = extractCommandFromObject(input);
|
|
34942
|
-
}
|
|
34943
|
-
try {
|
|
34944
|
-
raw = JSON.stringify(input).slice(0, truncLimit);
|
|
34945
|
-
} catch {
|
|
34946
|
-
raw = String(input).slice(0, truncLimit);
|
|
34947
|
-
}
|
|
34948
|
-
} else {
|
|
34949
|
-
raw = String(input ?? "").slice(0, truncLimit);
|
|
34950
|
-
}
|
|
34951
|
-
if (command !== undefined) {
|
|
34952
|
-
command = command.slice(0, truncLimit);
|
|
34953
|
-
}
|
|
34954
|
-
const command_type = command !== undefined ? detectCommandType(command) : undefined;
|
|
34955
|
-
return { raw, command, command_type };
|
|
34956
|
-
}
|
|
34957
|
-
function extractCommandFromObject(obj) {
|
|
34958
|
-
const cmd = obj["command"] ?? obj["cmd"] ?? obj["shell_command"];
|
|
34959
|
-
return typeof cmd === "string" ? cmd : undefined;
|
|
34960
|
-
}
|
|
34961
|
-
function detectCommandType(command) {
|
|
34962
|
-
const first = command.trim().split(/\s+/)[0] ?? "";
|
|
34963
|
-
const basename = first.split("/").pop() ?? first;
|
|
34964
|
-
return COMMAND_TYPE_MAP[basename.toLowerCase()] ?? "shell";
|
|
34965
|
-
}
|
|
34966
|
-
var SHELL_TOOL_NAMES, TRUNCATION_BASH = 2000, TRUNCATION_DEFAULT = 500, COMMAND_TYPE_MAP;
|
|
34967
|
-
var init_tool_extraction = __esm(() => {
|
|
34968
|
-
SHELL_TOOL_NAMES = new Set([
|
|
34969
|
-
"Bash",
|
|
34970
|
-
"bash",
|
|
34971
|
-
"shell",
|
|
34972
|
-
"Shell",
|
|
34973
|
-
"exec",
|
|
34974
|
-
"run_command",
|
|
34975
|
-
"computer"
|
|
34976
|
-
]);
|
|
34977
|
-
COMMAND_TYPE_MAP = {
|
|
34978
|
-
git: "git",
|
|
34979
|
-
npm: "npm",
|
|
34980
|
-
npx: "npm",
|
|
34981
|
-
bun: "bun",
|
|
34982
|
-
bunx: "bun",
|
|
34983
|
-
node: "node",
|
|
34984
|
-
python: "python",
|
|
34985
|
-
python3: "python",
|
|
34986
|
-
pip: "python",
|
|
34987
|
-
pip3: "python",
|
|
34988
|
-
tsc: "typescript",
|
|
34989
|
-
vitest: "test",
|
|
34990
|
-
jest: "test",
|
|
34991
|
-
pytest: "test",
|
|
34992
|
-
mocha: "test",
|
|
34993
|
-
curl: "http",
|
|
34994
|
-
wget: "http",
|
|
34995
|
-
cat: "file",
|
|
34996
|
-
ls: "file",
|
|
34997
|
-
find: "file",
|
|
34998
|
-
cp: "file",
|
|
34999
|
-
mv: "file",
|
|
35000
|
-
rm: "file",
|
|
35001
|
-
mkdir: "file",
|
|
35002
|
-
grep: "search",
|
|
35003
|
-
rg: "search",
|
|
35004
|
-
sed: "transform",
|
|
35005
|
-
awk: "transform",
|
|
35006
|
-
docker: "docker",
|
|
35007
|
-
"docker-compose": "docker",
|
|
35008
|
-
kubectl: "kubernetes",
|
|
35009
|
-
helm: "kubernetes",
|
|
35010
|
-
terraform: "infrastructure",
|
|
35011
|
-
gh: "github",
|
|
35012
|
-
supabase: "supabase",
|
|
35013
|
-
bd: "beads"
|
|
35014
|
-
};
|
|
35015
|
-
});
|
|
35016
|
-
|
|
35017
35379
|
// src/agent-hooks/claude.ts
|
|
35018
35380
|
import fs13 from "node:fs";
|
|
35019
35381
|
async function ingestClaudeHookInput(input, config3) {
|
|
@@ -35189,28 +35551,9 @@ function readJsonLines2(filePath) {
|
|
|
35189
35551
|
function extractMessage3(entry) {
|
|
35190
35552
|
const message = entry.message;
|
|
35191
35553
|
const role = message?.role ?? entry.type;
|
|
35192
|
-
const content =
|
|
35554
|
+
const content = flattenContent(message?.content ?? entry.content);
|
|
35193
35555
|
return { role, content };
|
|
35194
35556
|
}
|
|
35195
|
-
function flattenContent2(content) {
|
|
35196
|
-
if (!content)
|
|
35197
|
-
return;
|
|
35198
|
-
if (typeof content === "string")
|
|
35199
|
-
return content;
|
|
35200
|
-
if (Array.isArray(content)) {
|
|
35201
|
-
const parts = content.map((item) => {
|
|
35202
|
-
if (!item || typeof item !== "object")
|
|
35203
|
-
return "";
|
|
35204
|
-
const typed = item;
|
|
35205
|
-
if (typed.type === "thinking" || typed.type === "tool_use")
|
|
35206
|
-
return "";
|
|
35207
|
-
return typed.text ?? typed.input_text ?? typed.output_text ?? "";
|
|
35208
|
-
}).filter(Boolean);
|
|
35209
|
-
return parts.length ? parts.join(`
|
|
35210
|
-
`) : undefined;
|
|
35211
|
-
}
|
|
35212
|
-
return;
|
|
35213
|
-
}
|
|
35214
35557
|
function getEntryId2(entry) {
|
|
35215
35558
|
return entry.uuid ?? entry.message?.id ?? entry.id ?? entry.messageId;
|
|
35216
35559
|
}
|
|
@@ -35222,6 +35565,7 @@ var init_claude = __esm(() => {
|
|
|
35222
35565
|
init_ingest();
|
|
35223
35566
|
init_state2();
|
|
35224
35567
|
init_tool_extraction();
|
|
35568
|
+
init_parsing_utils();
|
|
35225
35569
|
});
|
|
35226
35570
|
|
|
35227
35571
|
// src/agent-hooks/codex.ts
|
|
@@ -35501,22 +35845,22 @@ function extractMessage4(entry) {
|
|
|
35501
35845
|
const payload = entry.payload;
|
|
35502
35846
|
if (payload.type === "message") {
|
|
35503
35847
|
const role = payload.role;
|
|
35504
|
-
const content =
|
|
35848
|
+
const content = flattenContent2(payload.content);
|
|
35505
35849
|
if (role)
|
|
35506
35850
|
return { role, content };
|
|
35507
35851
|
}
|
|
35508
35852
|
}
|
|
35509
35853
|
if (entry.type === "message" && entry.role) {
|
|
35510
|
-
return { role: entry.role, content:
|
|
35854
|
+
return { role: entry.role, content: flattenContent2(entry.content) };
|
|
35511
35855
|
}
|
|
35512
35856
|
if (entry.type === "user" || entry.type === "assistant") {
|
|
35513
35857
|
const role = entry.type;
|
|
35514
|
-
const content =
|
|
35858
|
+
const content = flattenContent2(entry.content ?? entry.message);
|
|
35515
35859
|
return { role, content };
|
|
35516
35860
|
}
|
|
35517
35861
|
return null;
|
|
35518
35862
|
}
|
|
35519
|
-
function
|
|
35863
|
+
function flattenContent2(content) {
|
|
35520
35864
|
if (!content)
|
|
35521
35865
|
return;
|
|
35522
35866
|
if (typeof content === "string")
|
|
@@ -36141,8 +36485,8 @@ function printUpdateNotice(currentVersion) {
|
|
|
36141
36485
|
if (compareSemver(currentVersion, cache.latest) >= 0)
|
|
36142
36486
|
return;
|
|
36143
36487
|
const lines = [
|
|
36144
|
-
`Update available: ${
|
|
36145
|
-
`Run ${
|
|
36488
|
+
`Update available: ${import_picocolors10.default.dim(currentVersion)} → ${import_picocolors10.default.green(cache.latest)}`,
|
|
36489
|
+
`Run ${import_picocolors10.default.cyan("getverbal update")} to upgrade`
|
|
36146
36490
|
];
|
|
36147
36491
|
if (cache.message) {
|
|
36148
36492
|
lines.push("");
|
|
@@ -36160,14 +36504,14 @@ function printUpdateNotice(currentVersion) {
|
|
|
36160
36504
|
console.log(`└${border}┘`);
|
|
36161
36505
|
} catch {}
|
|
36162
36506
|
}
|
|
36163
|
-
var
|
|
36507
|
+
var import_picocolors10;
|
|
36164
36508
|
var init_notify = __esm(() => {
|
|
36165
36509
|
init_credentials();
|
|
36166
|
-
|
|
36510
|
+
import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
36167
36511
|
});
|
|
36168
36512
|
|
|
36169
36513
|
// src/cli.ts
|
|
36170
|
-
var
|
|
36514
|
+
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
36171
36515
|
|
|
36172
36516
|
// src/commands/init.ts
|
|
36173
36517
|
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
@@ -37095,6 +37439,58 @@ async function runInit() {
|
|
|
37095
37439
|
console.log(import_picocolors.default.yellow(" Cursor sync requires Bun runtime. Run via: bunx getverbal sync"));
|
|
37096
37440
|
}
|
|
37097
37441
|
}
|
|
37442
|
+
{
|
|
37443
|
+
console.log();
|
|
37444
|
+
console.log(import_picocolors.default.bold("Connect provider billing") + import_picocolors.default.dim(" (optional)"));
|
|
37445
|
+
console.log(import_picocolors.default.dim(" Verbal can pull your API spend directly from providers."));
|
|
37446
|
+
console.log();
|
|
37447
|
+
const providers = [
|
|
37448
|
+
{ id: "anthropic", label: "Anthropic" },
|
|
37449
|
+
{ id: "openai", label: "OpenAI" }
|
|
37450
|
+
];
|
|
37451
|
+
let keysAdded = 0;
|
|
37452
|
+
for (const provider of providers) {
|
|
37453
|
+
const connect = await confirm(rl, ` Connect ${provider.label} API billing?`, false);
|
|
37454
|
+
if (!connect) {
|
|
37455
|
+
console.log(import_picocolors.default.dim(` Skipped.`));
|
|
37456
|
+
continue;
|
|
37457
|
+
}
|
|
37458
|
+
const key = await rl.question(` Enter your ${provider.label} Admin API key: `);
|
|
37459
|
+
const trimmedKey = key.trim();
|
|
37460
|
+
if (!trimmedKey) {
|
|
37461
|
+
console.log(import_picocolors.default.dim(" No key entered. Skipped."));
|
|
37462
|
+
continue;
|
|
37463
|
+
}
|
|
37464
|
+
try {
|
|
37465
|
+
const res = await fetch(`${credentials.api_url}/api/v1/provider-keys`, {
|
|
37466
|
+
method: "POST",
|
|
37467
|
+
headers: {
|
|
37468
|
+
"Content-Type": "application/json",
|
|
37469
|
+
Authorization: `Bearer ${credentials.api_key}`
|
|
37470
|
+
},
|
|
37471
|
+
body: JSON.stringify({ provider: provider.id, key: trimmedKey })
|
|
37472
|
+
});
|
|
37473
|
+
if (res.ok) {
|
|
37474
|
+
const data = await res.json();
|
|
37475
|
+
const prefix = data.key_prefix ?? trimmedKey.slice(0, 10);
|
|
37476
|
+
console.log(import_picocolors.default.green(` ✓ ${provider.label} key added (prefix: ${prefix})`));
|
|
37477
|
+
keysAdded++;
|
|
37478
|
+
} else {
|
|
37479
|
+
const errData = await res.json().catch(() => ({}));
|
|
37480
|
+
const errMsg = errData.error ?? `HTTP ${res.status}`;
|
|
37481
|
+
console.log(import_picocolors.default.yellow(` ⚠ ${provider.label} key not saved: ${errMsg}`));
|
|
37482
|
+
}
|
|
37483
|
+
} catch (err) {
|
|
37484
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37485
|
+
console.log(import_picocolors.default.yellow(` ⚠ Could not save ${provider.label} key: ${msg}`));
|
|
37486
|
+
}
|
|
37487
|
+
}
|
|
37488
|
+
if (keysAdded > 0) {
|
|
37489
|
+
console.log();
|
|
37490
|
+
console.log(import_picocolors.default.green(` ✓ ${keysAdded} provider key${keysAdded > 1 ? "s" : ""} connected`) + import_picocolors.default.dim(" — billing data will sync automatically"));
|
|
37491
|
+
}
|
|
37492
|
+
console.log();
|
|
37493
|
+
}
|
|
37098
37494
|
process.stdout.write(import_picocolors.default.dim("Verifying connection..."));
|
|
37099
37495
|
try {
|
|
37100
37496
|
await verifyConnection(credentials);
|
|
@@ -37266,25 +37662,26 @@ async function runDashboard() {
|
|
|
37266
37662
|
|
|
37267
37663
|
// src/cli.ts
|
|
37268
37664
|
var HELP = `
|
|
37269
|
-
${
|
|
37665
|
+
${import_picocolors11.default.bold("getverbal")} — AI Spend Tracker
|
|
37270
37666
|
|
|
37271
|
-
${
|
|
37667
|
+
${import_picocolors11.default.dim("Usage:")} getverbal <command> [options]
|
|
37272
37668
|
|
|
37273
|
-
${
|
|
37669
|
+
${import_picocolors11.default.dim("Commands:")}
|
|
37274
37670
|
init Authenticate, detect tools, configure, and import history
|
|
37275
37671
|
status Show current configuration and connection status
|
|
37276
37672
|
dashboard Open your Verbal dashboard in the browser
|
|
37277
37673
|
import Bulk import from exports or local tool history
|
|
37674
|
+
keys Manage provider API keys (add, list, remove)
|
|
37278
37675
|
sync Sync usage data from all detected AI tools
|
|
37279
37676
|
update Update getverbal to the latest version
|
|
37280
37677
|
logout Remove stored credentials
|
|
37281
37678
|
uninstall Remove Verbal from all AI tools and delete credentials
|
|
37282
37679
|
|
|
37283
|
-
${
|
|
37680
|
+
${import_picocolors11.default.dim("Machine commands (invoked by AI tools):")}
|
|
37284
37681
|
mcp-serve Start MCP server (stdio)
|
|
37285
37682
|
hooks Agent hook utilities
|
|
37286
37683
|
|
|
37287
|
-
${
|
|
37684
|
+
${import_picocolors11.default.dim("Options:")}
|
|
37288
37685
|
--help, -h Show this help message
|
|
37289
37686
|
--version, -v Show version number
|
|
37290
37687
|
`.trim();
|
|
@@ -37316,6 +37713,11 @@ async function main2() {
|
|
|
37316
37713
|
await runUpdate2(VERSION);
|
|
37317
37714
|
break;
|
|
37318
37715
|
}
|
|
37716
|
+
case "keys": {
|
|
37717
|
+
const { runKeys: runKeys2 } = await Promise.resolve().then(() => (init_keys(), exports_keys));
|
|
37718
|
+
await runKeys2(process.argv.slice(3));
|
|
37719
|
+
break;
|
|
37720
|
+
}
|
|
37319
37721
|
case "sync": {
|
|
37320
37722
|
const { runSync: runSync2 } = await Promise.resolve().then(() => (init_sync(), exports_sync));
|
|
37321
37723
|
await runSync2();
|
|
@@ -37347,7 +37749,7 @@ async function main2() {
|
|
|
37347
37749
|
console.log(HELP);
|
|
37348
37750
|
return;
|
|
37349
37751
|
default:
|
|
37350
|
-
console.error(`${
|
|
37752
|
+
console.error(`${import_picocolors11.default.red("Unknown command:")} ${command}
|
|
37351
37753
|
`);
|
|
37352
37754
|
console.log(HELP);
|
|
37353
37755
|
process.exitCode = 1;
|
|
@@ -37360,6 +37762,6 @@ async function main2() {
|
|
|
37360
37762
|
}
|
|
37361
37763
|
}
|
|
37362
37764
|
main2().catch((err) => {
|
|
37363
|
-
console.error(
|
|
37765
|
+
console.error(import_picocolors11.default.red(err instanceof Error ? err.message : "An unexpected error occurred"));
|
|
37364
37766
|
process.exitCode = 1;
|
|
37365
37767
|
});
|