ai-spend-agent 0.4.2 → 0.4.4

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.
Files changed (2) hide show
  1. package/dist/index.js +22 -17
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -144,8 +144,8 @@ function quickstartNextSteps(mode, detected) {
144
144
  steps.push(`Found local key${detected.length === 1 ? "" : "s"}: ${names}`);
145
145
  steps.push(`npx ai-spend-agent connect ${detected[0].provider} use it — note: COST data needs an ADMIN/owner key`);
146
146
  }
147
- steps.push("npx ai-spend-agent report write a shareable Markdown + HTML report");
148
- steps.push("npx ai-spend-agent --group-by project see which project burns the most");
147
+ steps.push("npx aibill report write a shareable Markdown + HTML report");
148
+ steps.push("npx aibill --group-by project see which project burns the most");
149
149
  steps.push("Want this watched while your laptop is off? Hosted beta waitlist: https://ai-spend-agent.vercel.app");
150
150
  return steps;
151
151
  }
@@ -841,7 +841,7 @@ async function reportCommand(args) {
841
841
  "next:",
842
842
  ` open ${htmlPath} view the full report in your browser`,
843
843
  ` less ${markdownPath} read it in the terminal`,
844
- " npx ai-spend-agent apply-artifact print the paste-ready coding-agent prompt"
844
+ " npx aibill apply print the paste-ready coding-agent prompt"
845
845
  ].join("\n"));
846
846
  }
847
847
  catch (error) {
@@ -923,25 +923,30 @@ async function applyArtifactCommand(args) {
923
923
  async function buildReportInput(stateDir, rootPath) {
924
924
  let spendState = await readOptionalJson(join(stateDir, "spend.json"), undefined);
925
925
  let mappings = await readOptionalJson(join(stateDir, "mappings.json"), undefined);
926
- // The quickstart intentionally writes nothing so `report`/`apply-artifact`
927
- // right after a first run must fall back to the SAME live local-log read
928
- // (never sample data), then persist it so subsequent runs are consistent.
929
- if (!spendState?.summary || !spendState.records || spendState.records.length === 0) {
926
+ // Local-log state is a CACHE, not a source of truth: the quickstart always
927
+ // re-reads the logs fresh, so report/apply must too otherwise yesterday's
928
+ // persisted snapshot makes the artifact's numbers disagree with the screen.
929
+ // Persisted state stays authoritative only for connected/sample data.
930
+ const needsFreshLogs = !spendState?.summary || !spendState.records || spendState.records.length === 0 || spendState.mode === "local_logs";
931
+ if (needsFreshLogs) {
930
932
  const logs = await loadLocalAgentUsage({
931
933
  claudeProjectsDir: process.env.AI_SPEND_CLAUDE_LOGS_DIR,
932
934
  codexSessionsDir: process.env.AI_SPEND_CODEX_LOGS_DIR
933
935
  }).catch(() => undefined);
934
- if (!logs || logs.records.length === 0) {
935
- throw new Error("no persisted spend state and no local Claude Code/Codex logs found. " +
936
- "Run `npx ai-spend-agent` first (or `npx ai-spend-agent scan --sample --path <dir>` for a demo-data report).");
936
+ if (logs && logs.records.length > 0) {
937
+ const records = logs.records;
938
+ const summary = analyzeSpend(records);
939
+ const liveMappings = attributeUsageRecords(records);
940
+ await mkdir(stateDir, { recursive: true });
941
+ await writeLocalSpendState(stateDir, records, summary, liveMappings, "local_logs");
942
+ spendState = { summary, records, mode: "local_logs" };
943
+ mappings = liveMappings;
937
944
  }
938
- const records = logs.records;
939
- const summary = analyzeSpend(records);
940
- const liveMappings = attributeUsageRecords(records);
941
- await mkdir(stateDir, { recursive: true });
942
- await writeLocalSpendState(stateDir, records, summary, liveMappings, "local_logs");
943
- spendState = { summary, records, mode: "local_logs" };
944
- mappings = liveMappings;
945
+ // else: logs vanished — an existing local_logs snapshot (if any) is used below.
946
+ }
947
+ if (!spendState?.summary || !spendState.records || spendState.records.length === 0) {
948
+ throw new Error("no persisted spend state and no local Claude Code/Codex logs found. " +
949
+ "Run `npx aibill` first (or `npx aibill scan --sample --path <dir>` for a demo-data report).");
945
950
  }
946
951
  const [discovery, sourceRegistry, missingSourcePrompts, confirmedMappings, providerRecordsState] = await Promise.all([
947
952
  readOptionalJson(join(stateDir, "discovery.json"), emptyDiscovery(rootPath)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-spend-agent",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Your AI spend in one view, in 90 seconds — local-first CLI for OpenAI, Anthropic, Cursor, Copilot + Claude Code/Codex session logs, with a ranked savings cut list, and flags the tools your agent loads but never uses (dead context).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,8 +49,8 @@
49
49
  "prepack": "npm run build"
50
50
  },
51
51
  "dependencies": {
52
- "@agent-finops/core": "0.4.2",
53
- "@agent-finops/report": "0.4.2",
52
+ "@agent-finops/core": "0.4.4",
53
+ "@agent-finops/report": "0.4.4",
54
54
  "yocto-spinner": "^1.2.0"
55
55
  }
56
56
  }