@hasna/economy 0.3.26 → 0.3.27

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.27
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [6176948]
8
+ - Updated dependencies [7575de8]
9
+ - @hasna/contracts@0.14.0
10
+ - @hasna/projects@1.0.0
11
+
3
12
  ## 0.3.26
4
13
 
5
14
  ### Patch Changes
package/dist/cli/index.js CHANGED
@@ -2374,21 +2374,124 @@ var init_database = __esm(() => {
2374
2374
  init_sqlite_adapter();
2375
2375
  });
2376
2376
 
2377
+ // package.json
2378
+ var package_default;
2379
+ var init_package = __esm(() => {
2380
+ package_default = {
2381
+ name: "@hasna/economy",
2382
+ version: "0.3.27",
2383
+ description: "AI coding cost tracker \u2014 CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
2384
+ repository: {
2385
+ type: "git",
2386
+ url: "git+https://github.com/hasna/economy.git"
2387
+ },
2388
+ bugs: {
2389
+ url: "https://github.com/hasna/economy/issues"
2390
+ },
2391
+ homepage: "https://github.com/hasna/economy#readme",
2392
+ type: "module",
2393
+ main: "dist/index.js",
2394
+ types: "dist/index.d.ts",
2395
+ bin: {
2396
+ economy: "dist/cli/index.js",
2397
+ "economy-mcp": "dist/mcp/index.js",
2398
+ "economy-serve": "dist/server/index.js",
2399
+ "economy-otel": "dist/otel/index.js"
2400
+ },
2401
+ exports: {
2402
+ ".": {
2403
+ types: "./dist/index.d.ts",
2404
+ import: "./dist/index.js"
2405
+ },
2406
+ "./sdk": {
2407
+ types: "./dist/index.d.ts",
2408
+ import: "./dist/index.js"
2409
+ }
2410
+ },
2411
+ files: [
2412
+ "dist",
2413
+ "docs",
2414
+ "dashboard/dist",
2415
+ "LICENSE",
2416
+ "README.md",
2417
+ "CHANGELOG.md",
2418
+ "SECURITY.md",
2419
+ "CONTRIBUTING.md",
2420
+ "CODE_OF_CONDUCT.md"
2421
+ ],
2422
+ scripts: {
2423
+ build: "cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.ts --outdir dist/cli --target bun --packages external && bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external && bun build src/server/index.ts --outdir dist/server --target bun --packages external && bun build src/db/pg-sync-worker.ts --outdir dist/server --target bun --packages external && bun build src/otel/index.ts --outdir dist/otel --target bun --packages external && bun build src/index.ts --outdir dist --target bun --packages external && tsc --emitDeclarationOnly --outDir dist",
2424
+ "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target bun --packages external",
2425
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external",
2426
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --packages external",
2427
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --packages external",
2428
+ "build:dashboard": "cd dashboard && bun run build",
2429
+ "artifact-scan": "bun scripts/contracts-cli.mjs artifact-scan dist",
2430
+ prepack: "bun run build && bun run artifact-scan",
2431
+ typecheck: "tsc --noEmit",
2432
+ test: "bun test",
2433
+ "dev:cli": "bun run src/cli/index.ts",
2434
+ "dev:mcp": "bun run src/mcp/index.ts",
2435
+ "dev:serve": "bun run src/server/index.ts",
2436
+ "dev:otel": "bun run src/otel/index.ts",
2437
+ postinstall: "mkdir -p $HOME/.hasna/economy/training 2>/dev/null || true"
2438
+ },
2439
+ keywords: [
2440
+ "economy",
2441
+ "cost",
2442
+ "ai",
2443
+ "claude",
2444
+ "codex",
2445
+ "gemini",
2446
+ "mcp",
2447
+ "cli",
2448
+ "budget",
2449
+ "tracking"
2450
+ ],
2451
+ author: "hasna",
2452
+ license: "Apache-2.0",
2453
+ publishConfig: {
2454
+ registry: "https://registry.npmjs.org",
2455
+ access: "public"
2456
+ },
2457
+ dependencies: {
2458
+ "@hasna/accounts": "0.2.23",
2459
+ "@hasna/agent-registry": "^0.1.0",
2460
+ "@hasna/contracts": "0.13.4",
2461
+ "@hasna/events": "^0.1.16",
2462
+ "@hasna/mcp-harness": "^0.1.0",
2463
+ "@hasna/projects": "1.0.0",
2464
+ "@modelcontextprotocol/sdk": "^1.12.1",
2465
+ chalk: "^5.4.1",
2466
+ commander: "^13.1.0",
2467
+ pg: "8.13.1",
2468
+ zod: "^3.24.2"
2469
+ },
2470
+ devDependencies: {
2471
+ "@types/bun": "latest",
2472
+ "@types/pg": "^8.20.0",
2473
+ "bun-types": "latest",
2474
+ typescript: "^5.7.2"
2475
+ },
2476
+ trustedDependencies: [
2477
+ "@hasna/projects"
2478
+ ]
2479
+ };
2480
+ });
2481
+
2377
2482
  // src/lib/package-metadata.ts
2378
- import { readFileSync } from "fs";
2379
2483
  function getPackageMetadata() {
2380
2484
  if (cachedMetadata)
2381
2485
  return cachedMetadata;
2382
- const raw = readFileSync(new URL("../../package.json", import.meta.url), "utf8");
2383
- const parsed = JSON.parse(raw);
2384
2486
  cachedMetadata = {
2385
- name: parsed.name ?? "@hasna/economy",
2386
- version: parsed.version ?? "0.0.0"
2487
+ name: package_default.name ?? "@hasna/economy",
2488
+ version: package_default.version ?? "0.0.0"
2387
2489
  };
2388
2490
  return cachedMetadata;
2389
2491
  }
2390
2492
  var cachedMetadata = null, packageMetadata;
2391
2493
  var init_package_metadata = __esm(() => {
2494
+ init_package();
2392
2495
  packageMetadata = getPackageMetadata();
2393
2496
  });
2394
2497
 
@@ -4128,7 +4231,7 @@ var init_accounts = __esm(() => {
4128
4231
  });
4129
4232
 
4130
4233
  // src/ingest/claude.ts
4131
- import { readdirSync as readdirSync2, readFileSync as readFileSync3, existsSync as existsSync4, statSync as statSync2 } from "fs";
4234
+ import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync4, statSync as statSync2 } from "fs";
4132
4235
  import { homedir as homedir3 } from "os";
4133
4236
  import { join as join6, basename } from "path";
4134
4237
  function autoDetectProject(cwd, projects) {
@@ -4188,7 +4291,7 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
4188
4291
  continue;
4189
4292
  let lines;
4190
4293
  try {
4191
- lines = readFileSync3(filePath, "utf-8").split(`
4294
+ lines = readFileSync2(filePath, "utf-8").split(`
4192
4295
  `).filter((l) => l.trim());
4193
4296
  } catch {
4194
4297
  continue;
@@ -4314,7 +4417,7 @@ var init_claude = __esm(() => {
4314
4417
  });
4315
4418
 
4316
4419
  // src/ingest/codex.ts
4317
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
4420
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
4318
4421
  import { homedir as homedir4 } from "os";
4319
4422
  import { join as join7, basename as basename2 } from "path";
4320
4423
  import { Database as BunDatabase } from "bun:sqlite";
@@ -4361,7 +4464,7 @@ function readCodexModel(configPath = codexConfigPath()) {
4361
4464
  if (!existsSync5(configPath))
4362
4465
  return "gpt-5-codex";
4363
4466
  try {
4364
- const content = readFileSync4(configPath, "utf-8");
4467
+ const content = readFileSync3(configPath, "utf-8");
4365
4468
  const match = content.match(/^model\s*=\s*"([^"]+)"/m);
4366
4469
  return match?.[1] ?? "gpt-5-codex";
4367
4470
  } catch {
@@ -4404,7 +4507,7 @@ function readTokenEvents(rolloutPath) {
4404
4507
  const fallbackUsages = new Map;
4405
4508
  let fallbackTimestamp;
4406
4509
  let aggregate = null;
4407
- for (const line of readFileSync4(rolloutPath, "utf-8").split(`
4510
+ for (const line of readFileSync3(rolloutPath, "utf-8").split(`
4408
4511
  `)) {
4409
4512
  if (!line.trim())
4410
4513
  continue;
@@ -4569,7 +4672,7 @@ var init_codex = __esm(() => {
4569
4672
  });
4570
4673
 
4571
4674
  // src/ingest/gemini.ts
4572
- import { readdirSync as readdirSync3, readFileSync as readFileSync5, existsSync as existsSync6, statSync as statSync3 } from "fs";
4675
+ import { readdirSync as readdirSync3, readFileSync as readFileSync4, existsSync as existsSync6, statSync as statSync3 } from "fs";
4573
4676
  import { homedir as homedir5 } from "os";
4574
4677
  import { join as join8, basename as basename3 } from "path";
4575
4678
  function geminiTmpDir() {
@@ -4607,7 +4710,7 @@ function projectRoot(projectDir, chatData) {
4607
4710
  const rootFile = join8(projectDir, ".project_root");
4608
4711
  try {
4609
4712
  if (existsSync6(rootFile))
4610
- return readFileSync5(rootFile, "utf-8").trim();
4713
+ return readFileSync4(rootFile, "utf-8").trim();
4611
4714
  } catch {}
4612
4715
  return "";
4613
4716
  }
@@ -4648,7 +4751,7 @@ async function ingestGemini(db, verbose) {
4648
4751
  continue;
4649
4752
  let chatData;
4650
4753
  try {
4651
- chatData = JSON.parse(readFileSync5(filePath, "utf-8"));
4754
+ chatData = JSON.parse(readFileSync4(filePath, "utf-8"));
4652
4755
  } catch {
4653
4756
  continue;
4654
4757
  }
@@ -4732,7 +4835,7 @@ var init_gemini = __esm(() => {
4732
4835
  });
4733
4836
 
4734
4837
  // src/ingest/opencode.ts
4735
- import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
4838
+ import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
4736
4839
  import { homedir as homedir6 } from "os";
4737
4840
  import { join as join9 } from "path";
4738
4841
  function walkJsonFiles(dir, acc = []) {
@@ -4774,7 +4877,7 @@ async function ingestOpenCode(db, verbose = false) {
4774
4877
  continue;
4775
4878
  let parsed;
4776
4879
  try {
4777
- parsed = JSON.parse(readFileSync6(file, "utf-8"));
4880
+ parsed = JSON.parse(readFileSync5(file, "utf-8"));
4778
4881
  } catch {
4779
4882
  continue;
4780
4883
  }
@@ -4970,7 +5073,7 @@ var init_cursor = __esm(() => {
4970
5073
  });
4971
5074
 
4972
5075
  // src/ingest/pi.ts
4973
- import { existsSync as existsSync8, readFileSync as readFileSync7, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
5076
+ import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
4974
5077
  import { homedir as homedir7 } from "os";
4975
5078
  import { join as join10 } from "path";
4976
5079
  function walkSessions(dir, acc = []) {
@@ -4999,7 +5102,7 @@ async function ingestPi(db, verbose = false) {
4999
5102
  continue;
5000
5103
  let data;
5001
5104
  try {
5002
- data = JSON.parse(readFileSync7(file, "utf-8"));
5105
+ data = JSON.parse(readFileSync6(file, "utf-8"));
5003
5106
  } catch {
5004
5107
  continue;
5005
5108
  }
@@ -5352,7 +5455,7 @@ var init_loops = __esm(() => {
5352
5455
  });
5353
5456
 
5354
5457
  // src/ingest/claude-quota.ts
5355
- import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
5458
+ import { existsSync as existsSync11, readFileSync as readFileSync7 } from "fs";
5356
5459
  function readClaudeToken() {
5357
5460
  const fromEnv = process.env["CLAUDE_OAUTH_TOKEN"] ?? process.env["ANTHROPIC_OAUTH_TOKEN"];
5358
5461
  if (fromEnv)
@@ -5360,7 +5463,7 @@ function readClaudeToken() {
5360
5463
  if (!existsSync11(CREDENTIALS_PATH))
5361
5464
  return null;
5362
5465
  try {
5363
- const creds = JSON.parse(readFileSync8(CREDENTIALS_PATH, "utf-8"));
5466
+ const creds = JSON.parse(readFileSync7(CREDENTIALS_PATH, "utf-8"));
5364
5467
  const oauth = creds.claudeAiOauth;
5365
5468
  if (!oauth?.accessToken)
5366
5469
  return null;
@@ -5501,7 +5604,7 @@ var init_claude_quota = __esm(() => {
5501
5604
  });
5502
5605
 
5503
5606
  // src/ingest/codex-quota.ts
5504
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
5607
+ import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
5505
5608
  function readCodexAuth() {
5506
5609
  const fromEnv = process.env["CODEX_OAUTH_TOKEN"];
5507
5610
  if (fromEnv)
@@ -5510,7 +5613,7 @@ function readCodexAuth() {
5510
5613
  if (!existsSync12(authPath))
5511
5614
  return null;
5512
5615
  try {
5513
- const auth = JSON.parse(readFileSync9(authPath, "utf-8"));
5616
+ const auth = JSON.parse(readFileSync8(authPath, "utf-8"));
5514
5617
  const token = auth.tokens?.access_token;
5515
5618
  if (!token)
5516
5619
  return null;
@@ -5695,7 +5798,7 @@ __export(exports_billing, {
5695
5798
  syncGeminiBilling: () => syncGeminiBilling,
5696
5799
  syncAnthropicBilling: () => syncAnthropicBilling
5697
5800
  });
5698
- import { readFileSync as readFileSync10 } from "fs";
5801
+ import { readFileSync as readFileSync9 } from "fs";
5699
5802
  function getAnthropicAdminKey() {
5700
5803
  return process.env["HASNAXYZ_ANTHROPIC_LIVE_ADMIN_API_KEY"] ?? process.env["ANTHROPIC_ADMIN_API_KEY"] ?? null;
5701
5804
  }
@@ -5922,7 +6025,7 @@ async function syncGeminiBilling(db, opts = {}) {
5922
6025
  const start = opts.fromDate ? new Date(opts.fromDate) : new Date(end.getTime() - days * 24 * 3600000);
5923
6026
  const fromDateStr = toISODate(start);
5924
6027
  const toDateStr = toISODate(end);
5925
- const rows = parseBillingRows(readFileSync10(exportPath, "utf-8"));
6028
+ const rows = parseBillingRows(readFileSync9(exportPath, "utf-8"));
5926
6029
  clearBillingRange(db, "gemini", fromDateStr, toDateStr);
5927
6030
  const updatedAt = new Date().toISOString();
5928
6031
  let totalUsd = 0;
@@ -5993,7 +6096,7 @@ __export(exports_config, {
5993
6096
  loadConfig: () => loadConfig2,
5994
6097
  getConfigValue: () => getConfigValue
5995
6098
  });
5996
- import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
6099
+ import { existsSync as existsSync13, readFileSync as readFileSync10, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
5997
6100
  import { dirname as dirname2, join as join14 } from "path";
5998
6101
  function getConfigPath() {
5999
6102
  return process.env["HASNA_ECONOMY_CONFIG_PATH"] ?? join14(getDataDir(), "config.json");
@@ -6002,7 +6105,7 @@ function loadConfig2() {
6002
6105
  try {
6003
6106
  const configPath = getConfigPath();
6004
6107
  if (existsSync13(configPath)) {
6005
- const raw = readFileSync11(configPath, "utf-8");
6108
+ const raw = readFileSync10(configPath, "utf-8");
6006
6109
  return { ...DEFAULTS, ...JSON.parse(raw) };
6007
6110
  }
6008
6111
  } catch {}
@@ -9207,7 +9310,7 @@ ${goals.map((g) => `- ${g.period} goal (${g.project_path ?? g.agent ?? "global"}
9207
9310
 
9208
9311
  // src/lib/model-config.ts
9209
9312
  init_database();
9210
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
9313
+ import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
9211
9314
  import { dirname, join as join2 } from "path";
9212
9315
  var DEFAULT_MODEL = "gpt-4o-mini";
9213
9316
  function getModelConfigPath() {
@@ -9217,7 +9320,7 @@ function loadConfig() {
9217
9320
  try {
9218
9321
  const configPath = getModelConfigPath();
9219
9322
  if (existsSync2(configPath)) {
9220
- return JSON.parse(readFileSync2(configPath, "utf-8"));
9323
+ return JSON.parse(readFileSync(configPath, "utf-8"));
9221
9324
  }
9222
9325
  } catch {}
9223
9326
  return {};
package/dist/index.js CHANGED
@@ -1990,18 +1990,116 @@ function isAgent(value) {
1990
1990
  init_database();
1991
1991
  init_pricing();
1992
1992
  import { randomUUID } from "crypto";
1993
+ // package.json
1994
+ var package_default = {
1995
+ name: "@hasna/economy",
1996
+ version: "0.3.27",
1997
+ description: "AI coding cost tracker \u2014 CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
1998
+ repository: {
1999
+ type: "git",
2000
+ url: "git+https://github.com/hasna/economy.git"
2001
+ },
2002
+ bugs: {
2003
+ url: "https://github.com/hasna/economy/issues"
2004
+ },
2005
+ homepage: "https://github.com/hasna/economy#readme",
2006
+ type: "module",
2007
+ main: "dist/index.js",
2008
+ types: "dist/index.d.ts",
2009
+ bin: {
2010
+ economy: "dist/cli/index.js",
2011
+ "economy-mcp": "dist/mcp/index.js",
2012
+ "economy-serve": "dist/server/index.js",
2013
+ "economy-otel": "dist/otel/index.js"
2014
+ },
2015
+ exports: {
2016
+ ".": {
2017
+ types: "./dist/index.d.ts",
2018
+ import: "./dist/index.js"
2019
+ },
2020
+ "./sdk": {
2021
+ types: "./dist/index.d.ts",
2022
+ import: "./dist/index.js"
2023
+ }
2024
+ },
2025
+ files: [
2026
+ "dist",
2027
+ "docs",
2028
+ "dashboard/dist",
2029
+ "LICENSE",
2030
+ "README.md",
2031
+ "CHANGELOG.md",
2032
+ "SECURITY.md",
2033
+ "CONTRIBUTING.md",
2034
+ "CODE_OF_CONDUCT.md"
2035
+ ],
2036
+ scripts: {
2037
+ build: "cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.ts --outdir dist/cli --target bun --packages external && bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external && bun build src/server/index.ts --outdir dist/server --target bun --packages external && bun build src/db/pg-sync-worker.ts --outdir dist/server --target bun --packages external && bun build src/otel/index.ts --outdir dist/otel --target bun --packages external && bun build src/index.ts --outdir dist --target bun --packages external && tsc --emitDeclarationOnly --outDir dist",
2038
+ "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target bun --packages external",
2039
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external",
2040
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --packages external",
2041
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --packages external",
2042
+ "build:dashboard": "cd dashboard && bun run build",
2043
+ "artifact-scan": "bun scripts/contracts-cli.mjs artifact-scan dist",
2044
+ prepack: "bun run build && bun run artifact-scan",
2045
+ typecheck: "tsc --noEmit",
2046
+ test: "bun test",
2047
+ "dev:cli": "bun run src/cli/index.ts",
2048
+ "dev:mcp": "bun run src/mcp/index.ts",
2049
+ "dev:serve": "bun run src/server/index.ts",
2050
+ "dev:otel": "bun run src/otel/index.ts",
2051
+ postinstall: "mkdir -p $HOME/.hasna/economy/training 2>/dev/null || true"
2052
+ },
2053
+ keywords: [
2054
+ "economy",
2055
+ "cost",
2056
+ "ai",
2057
+ "claude",
2058
+ "codex",
2059
+ "gemini",
2060
+ "mcp",
2061
+ "cli",
2062
+ "budget",
2063
+ "tracking"
2064
+ ],
2065
+ author: "hasna",
2066
+ license: "Apache-2.0",
2067
+ publishConfig: {
2068
+ registry: "https://registry.npmjs.org",
2069
+ access: "public"
2070
+ },
2071
+ dependencies: {
2072
+ "@hasna/accounts": "0.2.23",
2073
+ "@hasna/agent-registry": "^0.1.0",
2074
+ "@hasna/contracts": "0.13.4",
2075
+ "@hasna/events": "^0.1.16",
2076
+ "@hasna/mcp-harness": "^0.1.0",
2077
+ "@hasna/projects": "1.0.0",
2078
+ "@modelcontextprotocol/sdk": "^1.12.1",
2079
+ chalk: "^5.4.1",
2080
+ commander: "^13.1.0",
2081
+ pg: "8.13.1",
2082
+ zod: "^3.24.2"
2083
+ },
2084
+ devDependencies: {
2085
+ "@types/bun": "latest",
2086
+ "@types/pg": "^8.20.0",
2087
+ "bun-types": "latest",
2088
+ typescript: "^5.7.2"
2089
+ },
2090
+ trustedDependencies: [
2091
+ "@hasna/projects"
2092
+ ]
2093
+ };
1993
2094
 
1994
2095
  // src/lib/package-metadata.ts
1995
- import { readFileSync } from "fs";
1996
2096
  var cachedMetadata = null;
1997
2097
  function getPackageMetadata() {
1998
2098
  if (cachedMetadata)
1999
2099
  return cachedMetadata;
2000
- const raw = readFileSync(new URL("../../package.json", import.meta.url), "utf8");
2001
- const parsed = JSON.parse(raw);
2002
2100
  cachedMetadata = {
2003
- name: parsed.name ?? "@hasna/economy",
2004
- version: parsed.version ?? "0.0.0"
2101
+ name: package_default.name ?? "@hasna/economy",
2102
+ version: package_default.version ?? "0.0.0"
2005
2103
  };
2006
2104
  return cachedMetadata;
2007
2105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"package-metadata.d.ts","sourceRoot":"","sources":["../../src/lib/package-metadata.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,wBAAgB,kBAAkB,IAAI,eAAe,CAYpD;AAED,eAAO,MAAM,eAAe,iBAAuB,CAAA"}
1
+ {"version":3,"file":"package-metadata.d.ts","sourceRoot":"","sources":["../../src/lib/package-metadata.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,wBAAgB,kBAAkB,IAAI,eAAe,CASpD;AAED,eAAO,MAAM,eAAe,iBAAuB,CAAA"}
package/dist/mcp/index.js CHANGED
@@ -2082,18 +2082,116 @@ var init_database = __esm(() => {
2082
2082
 
2083
2083
  // src/mcp/index.ts
2084
2084
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2085
+ // package.json
2086
+ var package_default = {
2087
+ name: "@hasna/economy",
2088
+ version: "0.3.27",
2089
+ description: "AI coding cost tracker \u2014 CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
2090
+ repository: {
2091
+ type: "git",
2092
+ url: "git+https://github.com/hasna/economy.git"
2093
+ },
2094
+ bugs: {
2095
+ url: "https://github.com/hasna/economy/issues"
2096
+ },
2097
+ homepage: "https://github.com/hasna/economy#readme",
2098
+ type: "module",
2099
+ main: "dist/index.js",
2100
+ types: "dist/index.d.ts",
2101
+ bin: {
2102
+ economy: "dist/cli/index.js",
2103
+ "economy-mcp": "dist/mcp/index.js",
2104
+ "economy-serve": "dist/server/index.js",
2105
+ "economy-otel": "dist/otel/index.js"
2106
+ },
2107
+ exports: {
2108
+ ".": {
2109
+ types: "./dist/index.d.ts",
2110
+ import: "./dist/index.js"
2111
+ },
2112
+ "./sdk": {
2113
+ types: "./dist/index.d.ts",
2114
+ import: "./dist/index.js"
2115
+ }
2116
+ },
2117
+ files: [
2118
+ "dist",
2119
+ "docs",
2120
+ "dashboard/dist",
2121
+ "LICENSE",
2122
+ "README.md",
2123
+ "CHANGELOG.md",
2124
+ "SECURITY.md",
2125
+ "CONTRIBUTING.md",
2126
+ "CODE_OF_CONDUCT.md"
2127
+ ],
2128
+ scripts: {
2129
+ build: "cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.ts --outdir dist/cli --target bun --packages external && bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external && bun build src/server/index.ts --outdir dist/server --target bun --packages external && bun build src/db/pg-sync-worker.ts --outdir dist/server --target bun --packages external && bun build src/otel/index.ts --outdir dist/otel --target bun --packages external && bun build src/index.ts --outdir dist --target bun --packages external && tsc --emitDeclarationOnly --outDir dist",
2130
+ "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target bun --packages external",
2131
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external",
2132
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --packages external",
2133
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --packages external",
2134
+ "build:dashboard": "cd dashboard && bun run build",
2135
+ "artifact-scan": "bun scripts/contracts-cli.mjs artifact-scan dist",
2136
+ prepack: "bun run build && bun run artifact-scan",
2137
+ typecheck: "tsc --noEmit",
2138
+ test: "bun test",
2139
+ "dev:cli": "bun run src/cli/index.ts",
2140
+ "dev:mcp": "bun run src/mcp/index.ts",
2141
+ "dev:serve": "bun run src/server/index.ts",
2142
+ "dev:otel": "bun run src/otel/index.ts",
2143
+ postinstall: "mkdir -p $HOME/.hasna/economy/training 2>/dev/null || true"
2144
+ },
2145
+ keywords: [
2146
+ "economy",
2147
+ "cost",
2148
+ "ai",
2149
+ "claude",
2150
+ "codex",
2151
+ "gemini",
2152
+ "mcp",
2153
+ "cli",
2154
+ "budget",
2155
+ "tracking"
2156
+ ],
2157
+ author: "hasna",
2158
+ license: "Apache-2.0",
2159
+ publishConfig: {
2160
+ registry: "https://registry.npmjs.org",
2161
+ access: "public"
2162
+ },
2163
+ dependencies: {
2164
+ "@hasna/accounts": "0.2.23",
2165
+ "@hasna/agent-registry": "^0.1.0",
2166
+ "@hasna/contracts": "0.13.4",
2167
+ "@hasna/events": "^0.1.16",
2168
+ "@hasna/mcp-harness": "^0.1.0",
2169
+ "@hasna/projects": "1.0.0",
2170
+ "@modelcontextprotocol/sdk": "^1.12.1",
2171
+ chalk: "^5.4.1",
2172
+ commander: "^13.1.0",
2173
+ pg: "8.13.1",
2174
+ zod: "^3.24.2"
2175
+ },
2176
+ devDependencies: {
2177
+ "@types/bun": "latest",
2178
+ "@types/pg": "^8.20.0",
2179
+ "bun-types": "latest",
2180
+ typescript: "^5.7.2"
2181
+ },
2182
+ trustedDependencies: [
2183
+ "@hasna/projects"
2184
+ ]
2185
+ };
2085
2186
 
2086
2187
  // src/lib/package-metadata.ts
2087
- import { readFileSync } from "fs";
2088
2188
  var cachedMetadata = null;
2089
2189
  function getPackageMetadata() {
2090
2190
  if (cachedMetadata)
2091
2191
  return cachedMetadata;
2092
- const raw = readFileSync(new URL("../../package.json", import.meta.url), "utf8");
2093
- const parsed = JSON.parse(raw);
2094
2192
  cachedMetadata = {
2095
- name: parsed.name ?? "@hasna/economy",
2096
- version: parsed.version ?? "0.0.0"
2193
+ name: package_default.name ?? "@hasna/economy",
2194
+ version: package_default.version ?? "0.0.0"
2097
2195
  };
2098
2196
  return cachedMetadata;
2099
2197
  }
@@ -2108,7 +2206,7 @@ import { z } from "zod";
2108
2206
  // src/ingest/claude.ts
2109
2207
  init_database();
2110
2208
  init_pricing();
2111
- import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync2, statSync as statSync2 } from "fs";
2209
+ import { readdirSync as readdirSync2, readFileSync, existsSync as existsSync2, statSync as statSync2 } from "fs";
2112
2210
  import { homedir as homedir2 } from "os";
2113
2211
  import { join as join2, basename } from "path";
2114
2212
 
@@ -2437,7 +2535,7 @@ async function ingestJsonlProjects(db, projectsDir, agentName, verbose = false)
2437
2535
  continue;
2438
2536
  let lines;
2439
2537
  try {
2440
- lines = readFileSync2(filePath, "utf-8").split(`
2538
+ lines = readFileSync(filePath, "utf-8").split(`
2441
2539
  `).filter((l) => l.trim());
2442
2540
  } catch {
2443
2541
  continue;
@@ -2557,7 +2655,7 @@ function supportsClaudeDataResidencyPricing(model) {
2557
2655
  // src/ingest/codex.ts
2558
2656
  init_database();
2559
2657
  init_pricing();
2560
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
2658
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
2561
2659
  import { homedir as homedir3 } from "os";
2562
2660
  import { join as join3, basename as basename2 } from "path";
2563
2661
  import { Database as BunDatabase } from "bun:sqlite";
@@ -2609,7 +2707,7 @@ function readCodexModel(configPath = codexConfigPath()) {
2609
2707
  if (!existsSync3(configPath))
2610
2708
  return "gpt-5-codex";
2611
2709
  try {
2612
- const content = readFileSync3(configPath, "utf-8");
2710
+ const content = readFileSync2(configPath, "utf-8");
2613
2711
  const match = content.match(/^model\s*=\s*"([^"]+)"/m);
2614
2712
  return match?.[1] ?? "gpt-5-codex";
2615
2713
  } catch {
@@ -2652,7 +2750,7 @@ function readTokenEvents(rolloutPath) {
2652
2750
  const fallbackUsages = new Map;
2653
2751
  let fallbackTimestamp;
2654
2752
  let aggregate = null;
2655
- for (const line of readFileSync3(rolloutPath, "utf-8").split(`
2753
+ for (const line of readFileSync2(rolloutPath, "utf-8").split(`
2656
2754
  `)) {
2657
2755
  if (!line.trim())
2658
2756
  continue;
@@ -2809,7 +2907,7 @@ async function ingestCodex(db, verbose = false) {
2809
2907
  // src/ingest/gemini.ts
2810
2908
  init_database();
2811
2909
  init_pricing();
2812
- import { readdirSync as readdirSync3, readFileSync as readFileSync4, existsSync as existsSync4, statSync as statSync3 } from "fs";
2910
+ import { readdirSync as readdirSync3, readFileSync as readFileSync3, existsSync as existsSync4, statSync as statSync3 } from "fs";
2813
2911
  import { homedir as homedir4 } from "os";
2814
2912
  import { join as join4, basename as basename3 } from "path";
2815
2913
  var DEFAULT_GEMINI_TMP_DIR = join4(homedir4(), ".gemini", "tmp");
@@ -2849,7 +2947,7 @@ function projectRoot(projectDir, chatData) {
2849
2947
  const rootFile = join4(projectDir, ".project_root");
2850
2948
  try {
2851
2949
  if (existsSync4(rootFile))
2852
- return readFileSync4(rootFile, "utf-8").trim();
2950
+ return readFileSync3(rootFile, "utf-8").trim();
2853
2951
  } catch {}
2854
2952
  return "";
2855
2953
  }
@@ -2890,7 +2988,7 @@ async function ingestGemini(db, verbose) {
2890
2988
  continue;
2891
2989
  let chatData;
2892
2990
  try {
2893
- chatData = JSON.parse(readFileSync4(filePath, "utf-8"));
2991
+ chatData = JSON.parse(readFileSync3(filePath, "utf-8"));
2894
2992
  } catch {
2895
2993
  continue;
2896
2994
  }
@@ -2968,7 +3066,7 @@ async function ingestGemini(db, verbose) {
2968
3066
  // src/ingest/opencode.ts
2969
3067
  init_database();
2970
3068
  init_pricing();
2971
- import { existsSync as existsSync5, readFileSync as readFileSync5, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
3069
+ import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
2972
3070
  import { homedir as homedir5 } from "os";
2973
3071
  import { join as join5 } from "path";
2974
3072
  var OPENCODE_STORAGE = join5(homedir5(), ".local", "share", "opencode", "storage");
@@ -3011,7 +3109,7 @@ async function ingestOpenCode(db, verbose = false) {
3011
3109
  continue;
3012
3110
  let parsed;
3013
3111
  try {
3014
- parsed = JSON.parse(readFileSync5(file, "utf-8"));
3112
+ parsed = JSON.parse(readFileSync4(file, "utf-8"));
3015
3113
  } catch {
3016
3114
  continue;
3017
3115
  }
@@ -3198,7 +3296,7 @@ async function ingestCursor(db, verbose = false) {
3198
3296
 
3199
3297
  // src/ingest/pi.ts
3200
3298
  init_database();
3201
- import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
3299
+ import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync5, statSync as statSync5 } from "fs";
3202
3300
  import { homedir as homedir6 } from "os";
3203
3301
  import { join as join6 } from "path";
3204
3302
  var PI_SESSION_DIR = process.env["PI_CODING_AGENT_SESSION_DIR"] ?? join6(homedir6(), ".pi", "agent", "sessions");
@@ -3228,7 +3326,7 @@ async function ingestPi(db, verbose = false) {
3228
3326
  continue;
3229
3327
  let data;
3230
3328
  try {
3231
- data = JSON.parse(readFileSync6(file, "utf-8"));
3329
+ data = JSON.parse(readFileSync5(file, "utf-8"));
3232
3330
  } catch {
3233
3331
  continue;
3234
3332
  }
@@ -3570,7 +3668,7 @@ async function ingestLoops(db, verbose = false) {
3570
3668
 
3571
3669
  // src/ingest/claude-quota.ts
3572
3670
  init_database();
3573
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
3671
+ import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
3574
3672
 
3575
3673
  // src/lib/paths.ts
3576
3674
  import { homedir as homedir9 } from "os";
@@ -3608,7 +3706,7 @@ function readClaudeToken() {
3608
3706
  if (!existsSync9(CREDENTIALS_PATH))
3609
3707
  return null;
3610
3708
  try {
3611
- const creds = JSON.parse(readFileSync7(CREDENTIALS_PATH, "utf-8"));
3709
+ const creds = JSON.parse(readFileSync6(CREDENTIALS_PATH, "utf-8"));
3612
3710
  const oauth = creds.claudeAiOauth;
3613
3711
  if (!oauth?.accessToken)
3614
3712
  return null;
@@ -3744,7 +3842,7 @@ async function ingestClaudeQuota(db, verbose = false) {
3744
3842
 
3745
3843
  // src/ingest/codex-quota.ts
3746
3844
  init_database();
3747
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
3845
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
3748
3846
  var WHAM_USAGE_URL = process.env["CODEX_USAGE_URL"] ?? "https://chatgpt.com/backend-api/wham/usage";
3749
3847
  function readCodexAuth() {
3750
3848
  const fromEnv = process.env["CODEX_OAUTH_TOKEN"];
@@ -3754,7 +3852,7 @@ function readCodexAuth() {
3754
3852
  if (!existsSync10(authPath))
3755
3853
  return null;
3756
3854
  try {
3757
- const auth = JSON.parse(readFileSync8(authPath, "utf-8"));
3855
+ const auth = JSON.parse(readFileSync7(authPath, "utf-8"));
3758
3856
  const token = auth.tokens?.access_token;
3759
3857
  if (!token)
3760
3858
  return null;
@@ -1385,18 +1385,116 @@ async function ingestOtelRows(db, rows) {
1385
1385
  rollupSession(db, sessionId);
1386
1386
  return { requests, sessions: sessions.size };
1387
1387
  }
1388
+ // package.json
1389
+ var package_default = {
1390
+ name: "@hasna/economy",
1391
+ version: "0.3.27",
1392
+ description: "AI coding cost tracker \u2014 CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
1393
+ repository: {
1394
+ type: "git",
1395
+ url: "git+https://github.com/hasna/economy.git"
1396
+ },
1397
+ bugs: {
1398
+ url: "https://github.com/hasna/economy/issues"
1399
+ },
1400
+ homepage: "https://github.com/hasna/economy#readme",
1401
+ type: "module",
1402
+ main: "dist/index.js",
1403
+ types: "dist/index.d.ts",
1404
+ bin: {
1405
+ economy: "dist/cli/index.js",
1406
+ "economy-mcp": "dist/mcp/index.js",
1407
+ "economy-serve": "dist/server/index.js",
1408
+ "economy-otel": "dist/otel/index.js"
1409
+ },
1410
+ exports: {
1411
+ ".": {
1412
+ types: "./dist/index.d.ts",
1413
+ import: "./dist/index.js"
1414
+ },
1415
+ "./sdk": {
1416
+ types: "./dist/index.d.ts",
1417
+ import: "./dist/index.js"
1418
+ }
1419
+ },
1420
+ files: [
1421
+ "dist",
1422
+ "docs",
1423
+ "dashboard/dist",
1424
+ "LICENSE",
1425
+ "README.md",
1426
+ "CHANGELOG.md",
1427
+ "SECURITY.md",
1428
+ "CONTRIBUTING.md",
1429
+ "CODE_OF_CONDUCT.md"
1430
+ ],
1431
+ scripts: {
1432
+ build: "cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.ts --outdir dist/cli --target bun --packages external && bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external && bun build src/server/index.ts --outdir dist/server --target bun --packages external && bun build src/db/pg-sync-worker.ts --outdir dist/server --target bun --packages external && bun build src/otel/index.ts --outdir dist/otel --target bun --packages external && bun build src/index.ts --outdir dist --target bun --packages external && tsc --emitDeclarationOnly --outDir dist",
1433
+ "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target bun --packages external",
1434
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external",
1435
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --packages external",
1436
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --packages external",
1437
+ "build:dashboard": "cd dashboard && bun run build",
1438
+ "artifact-scan": "bun scripts/contracts-cli.mjs artifact-scan dist",
1439
+ prepack: "bun run build && bun run artifact-scan",
1440
+ typecheck: "tsc --noEmit",
1441
+ test: "bun test",
1442
+ "dev:cli": "bun run src/cli/index.ts",
1443
+ "dev:mcp": "bun run src/mcp/index.ts",
1444
+ "dev:serve": "bun run src/server/index.ts",
1445
+ "dev:otel": "bun run src/otel/index.ts",
1446
+ postinstall: "mkdir -p $HOME/.hasna/economy/training 2>/dev/null || true"
1447
+ },
1448
+ keywords: [
1449
+ "economy",
1450
+ "cost",
1451
+ "ai",
1452
+ "claude",
1453
+ "codex",
1454
+ "gemini",
1455
+ "mcp",
1456
+ "cli",
1457
+ "budget",
1458
+ "tracking"
1459
+ ],
1460
+ author: "hasna",
1461
+ license: "Apache-2.0",
1462
+ publishConfig: {
1463
+ registry: "https://registry.npmjs.org",
1464
+ access: "public"
1465
+ },
1466
+ dependencies: {
1467
+ "@hasna/accounts": "0.2.23",
1468
+ "@hasna/agent-registry": "^0.1.0",
1469
+ "@hasna/contracts": "0.13.4",
1470
+ "@hasna/events": "^0.1.16",
1471
+ "@hasna/mcp-harness": "^0.1.0",
1472
+ "@hasna/projects": "1.0.0",
1473
+ "@modelcontextprotocol/sdk": "^1.12.1",
1474
+ chalk: "^5.4.1",
1475
+ commander: "^13.1.0",
1476
+ pg: "8.13.1",
1477
+ zod: "^3.24.2"
1478
+ },
1479
+ devDependencies: {
1480
+ "@types/bun": "latest",
1481
+ "@types/pg": "^8.20.0",
1482
+ "bun-types": "latest",
1483
+ typescript: "^5.7.2"
1484
+ },
1485
+ trustedDependencies: [
1486
+ "@hasna/projects"
1487
+ ]
1488
+ };
1388
1489
 
1389
1490
  // src/lib/package-metadata.ts
1390
- import { readFileSync } from "fs";
1391
1491
  var cachedMetadata = null;
1392
1492
  function getPackageMetadata() {
1393
1493
  if (cachedMetadata)
1394
1494
  return cachedMetadata;
1395
- const raw = readFileSync(new URL("../../package.json", import.meta.url), "utf8");
1396
- const parsed = JSON.parse(raw);
1397
1495
  cachedMetadata = {
1398
- name: parsed.name ?? "@hasna/economy",
1399
- version: parsed.version ?? "0.0.0"
1496
+ name: package_default.name ?? "@hasna/economy",
1497
+ version: package_default.version ?? "0.0.0"
1400
1498
  };
1401
1499
  return cachedMetadata;
1402
1500
  }
@@ -2874,7 +2874,7 @@ __export(exports_billing, {
2874
2874
  syncGeminiBilling: () => syncGeminiBilling,
2875
2875
  syncAnthropicBilling: () => syncAnthropicBilling
2876
2876
  });
2877
- import { readFileSync as readFileSync9 } from "fs";
2877
+ import { readFileSync as readFileSync8 } from "fs";
2878
2878
  function getAnthropicAdminKey() {
2879
2879
  return process.env["HASNAXYZ_ANTHROPIC_LIVE_ADMIN_API_KEY"] ?? process.env["ANTHROPIC_ADMIN_API_KEY"] ?? null;
2880
2880
  }
@@ -3101,7 +3101,7 @@ async function syncGeminiBilling(db, opts = {}) {
3101
3101
  const start = opts.fromDate ? new Date(opts.fromDate) : new Date(end.getTime() - days * 24 * 3600000);
3102
3102
  const fromDateStr = toISODate(start);
3103
3103
  const toDateStr = toISODate(end);
3104
- const rows = parseBillingRows(readFileSync9(exportPath, "utf-8"));
3104
+ const rows = parseBillingRows(readFileSync8(exportPath, "utf-8"));
3105
3105
  clearBillingRange(db, "gemini", fromDateStr, toDateStr);
3106
3106
  const updatedAt = new Date().toISOString();
3107
3107
  let totalUsd = 0;
@@ -3165,7 +3165,7 @@ var init_open_projects = __esm(() => {
3165
3165
  });
3166
3166
 
3167
3167
  // src/lib/config.ts
3168
- import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
3168
+ import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
3169
3169
  import { dirname as dirname2, join as join11 } from "path";
3170
3170
  function getConfigPath() {
3171
3171
  return process.env["HASNA_ECONOMY_CONFIG_PATH"] ?? join11(getDataDir(), "config.json");
@@ -3174,7 +3174,7 @@ function loadConfig() {
3174
3174
  try {
3175
3175
  const configPath = getConfigPath();
3176
3176
  if (existsSync12(configPath)) {
3177
- const raw = readFileSync10(configPath, "utf-8");
3177
+ const raw = readFileSync9(configPath, "utf-8");
3178
3178
  return { ...DEFAULTS, ...JSON.parse(raw) };
3179
3179
  }
3180
3180
  } catch {}
@@ -5976,18 +5976,116 @@ function isAuthorizedRequest(req, path) {
5976
5976
  import { randomUUID } from "crypto";
5977
5977
  import { existsSync as existsSync13 } from "fs";
5978
5978
  import { resolve, sep } from "path";
5979
+ // package.json
5980
+ var package_default = {
5981
+ name: "@hasna/economy",
5982
+ version: "0.3.27",
5983
+ description: "AI coding cost tracker \u2014 CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
5984
+ repository: {
5985
+ type: "git",
5986
+ url: "git+https://github.com/hasna/economy.git"
5987
+ },
5988
+ bugs: {
5989
+ url: "https://github.com/hasna/economy/issues"
5990
+ },
5991
+ homepage: "https://github.com/hasna/economy#readme",
5992
+ type: "module",
5993
+ main: "dist/index.js",
5994
+ types: "dist/index.d.ts",
5995
+ bin: {
5996
+ economy: "dist/cli/index.js",
5997
+ "economy-mcp": "dist/mcp/index.js",
5998
+ "economy-serve": "dist/server/index.js",
5999
+ "economy-otel": "dist/otel/index.js"
6000
+ },
6001
+ exports: {
6002
+ ".": {
6003
+ types: "./dist/index.d.ts",
6004
+ import: "./dist/index.js"
6005
+ },
6006
+ "./sdk": {
6007
+ types: "./dist/index.d.ts",
6008
+ import: "./dist/index.js"
6009
+ }
6010
+ },
6011
+ files: [
6012
+ "dist",
6013
+ "docs",
6014
+ "dashboard/dist",
6015
+ "LICENSE",
6016
+ "README.md",
6017
+ "CHANGELOG.md",
6018
+ "SECURITY.md",
6019
+ "CONTRIBUTING.md",
6020
+ "CODE_OF_CONDUCT.md"
6021
+ ],
6022
+ scripts: {
6023
+ build: "cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.ts --outdir dist/cli --target bun --packages external && bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external && bun build src/server/index.ts --outdir dist/server --target bun --packages external && bun build src/db/pg-sync-worker.ts --outdir dist/server --target bun --packages external && bun build src/otel/index.ts --outdir dist/otel --target bun --packages external && bun build src/index.ts --outdir dist --target bun --packages external && tsc --emitDeclarationOnly --outDir dist",
6024
+ "build:cli": "bun build src/cli/index.ts --outdir dist/cli --target bun --packages external",
6025
+ "build:mcp": "bun build src/mcp/index.ts --outdir dist/mcp --target bun --packages external",
6026
+ "build:server": "bun build src/server/index.ts --outdir dist/server --target bun --packages external",
6027
+ "build:lib": "bun build src/index.ts --outdir dist --target bun --packages external",
6028
+ "build:dashboard": "cd dashboard && bun run build",
6029
+ "artifact-scan": "bun scripts/contracts-cli.mjs artifact-scan dist",
6030
+ prepack: "bun run build && bun run artifact-scan",
6031
+ typecheck: "tsc --noEmit",
6032
+ test: "bun test",
6033
+ "dev:cli": "bun run src/cli/index.ts",
6034
+ "dev:mcp": "bun run src/mcp/index.ts",
6035
+ "dev:serve": "bun run src/server/index.ts",
6036
+ "dev:otel": "bun run src/otel/index.ts",
6037
+ postinstall: "mkdir -p $HOME/.hasna/economy/training 2>/dev/null || true"
6038
+ },
6039
+ keywords: [
6040
+ "economy",
6041
+ "cost",
6042
+ "ai",
6043
+ "claude",
6044
+ "codex",
6045
+ "gemini",
6046
+ "mcp",
6047
+ "cli",
6048
+ "budget",
6049
+ "tracking"
6050
+ ],
6051
+ author: "hasna",
6052
+ license: "Apache-2.0",
6053
+ publishConfig: {
6054
+ registry: "https://registry.npmjs.org",
6055
+ access: "public"
6056
+ },
6057
+ dependencies: {
6058
+ "@hasna/accounts": "0.2.23",
6059
+ "@hasna/agent-registry": "^0.1.0",
6060
+ "@hasna/contracts": "0.13.4",
6061
+ "@hasna/events": "^0.1.16",
6062
+ "@hasna/mcp-harness": "^0.1.0",
6063
+ "@hasna/projects": "1.0.0",
6064
+ "@modelcontextprotocol/sdk": "^1.12.1",
6065
+ chalk: "^5.4.1",
6066
+ commander: "^13.1.0",
6067
+ pg: "8.13.1",
6068
+ zod: "^3.24.2"
6069
+ },
6070
+ devDependencies: {
6071
+ "@types/bun": "latest",
6072
+ "@types/pg": "^8.20.0",
6073
+ "bun-types": "latest",
6074
+ typescript: "^5.7.2"
6075
+ },
6076
+ trustedDependencies: [
6077
+ "@hasna/projects"
6078
+ ]
6079
+ };
5979
6080
 
5980
6081
  // src/lib/package-metadata.ts
5981
- import { readFileSync as readFileSync8 } from "fs";
5982
6082
  var cachedMetadata = null;
5983
6083
  function getPackageMetadata() {
5984
6084
  if (cachedMetadata)
5985
6085
  return cachedMetadata;
5986
- const raw = readFileSync8(new URL("../../package.json", import.meta.url), "utf8");
5987
- const parsed = JSON.parse(raw);
5988
6086
  cachedMetadata = {
5989
- name: parsed.name ?? "@hasna/economy",
5990
- version: parsed.version ?? "0.0.0"
6087
+ name: package_default.name ?? "@hasna/economy",
6088
+ version: package_default.version ?? "0.0.0"
5991
6089
  };
5992
6090
  return cachedMetadata;
5993
6091
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/economy",
3
- "version": "0.3.26",
3
+ "version": "0.3.27",
4
4
  "description": "AI coding cost tracker — CLI + MCP server + REST API + web dashboard for Claude Code, Codex, OpenCode, Cursor, Pi, and Hermes, with legacy Gemini CLI session and Gemini API billing ingestion",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,6 +23,10 @@
23
23
  ".": {
24
24
  "types": "./dist/index.d.ts",
25
25
  "import": "./dist/index.js"
26
+ },
27
+ "./sdk": {
28
+ "types": "./dist/index.d.ts",
29
+ "import": "./dist/index.js"
26
30
  }
27
31
  },
28
32
  "files": [