costlayers 0.8.14 → 0.8.15

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/bin/agentspend.js +39 -2
  2. package/package.json +1 -1
package/bin/agentspend.js CHANGED
@@ -9,7 +9,7 @@ const https = require("https");
9
9
  const os = require("os");
10
10
  const { spawnSync } = require("child_process");
11
11
 
12
- const VERSION = "0.8.14";
12
+ const VERSION = "0.8.15";
13
13
  const INSTALL_SPEC = "costlayers@latest";
14
14
  const DEFAULT_RUNS_PER_WEEK = 20;
15
15
  const WEEKS_PER_MONTH = 4.33;
@@ -145,6 +145,10 @@ function readJsonIfExists(file) {
145
145
  }
146
146
  }
147
147
 
148
+ function normalizedEmail(value) {
149
+ return String(value || "").trim().toLowerCase();
150
+ }
151
+
148
152
  function estimateTokens(text) {
149
153
  return Math.ceil(String(text || "").length / 4);
150
154
  }
@@ -639,16 +643,49 @@ async function signupConnection(repo, args) {
639
643
  engine_url: result.engine_url || engineUrl,
640
644
  api_key: result.api_key,
641
645
  gateway_url: result.gateway_url,
646
+ email: normalizedEmail(payload.email),
647
+ label: payload.label,
642
648
  connected_utc: new Date().toISOString()
643
649
  };
644
650
  fs.writeFileSync(path.join(outDir, "connection.json"), JSON.stringify(connection, null, 2) + "\n", "utf8");
645
651
  return connection;
646
652
  }
647
653
 
654
+ function saveConnection(repo, connection) {
655
+ const outDir = path.join(repo, ".agentspend");
656
+ ensureDir(outDir);
657
+ fs.writeFileSync(path.join(outDir, "connection.json"), JSON.stringify(connection, null, 2) + "\n", "utf8");
658
+ }
659
+
648
660
  async function ensureConnection(repo, args) {
649
661
  const outDir = path.join(repo, ".agentspend");
650
662
  const saved = readJsonIfExists(path.join(outDir, "connection.json"));
651
- if (saved && saved.engine_url && saved.api_key) return saved;
663
+ const requestedEmail = normalizedEmail(args.email);
664
+ if (saved && saved.engine_url && saved.api_key) {
665
+ if (!requestedEmail) return saved;
666
+ const savedEmail = normalizedEmail(saved.email);
667
+ if (savedEmail === requestedEmail) return saved;
668
+ if (savedEmail && savedEmail !== requestedEmail) {
669
+ process.stdout.write(`CostLayers email changed from ${savedEmail} to ${requestedEmail}; creating a new repo key.\n`);
670
+ return signupConnection(repo, args);
671
+ }
672
+ try {
673
+ const status = await postJson(`${String(saved.engine_url).replace(/\/+$/, "")}/v1/me`, {}, saved.api_key);
674
+ const remoteEmail = normalizedEmail(status.email);
675
+ if (remoteEmail && remoteEmail !== requestedEmail) {
676
+ process.stdout.write(`CostLayers saved key belongs to ${remoteEmail}; creating a new repo key for ${requestedEmail}.\n`);
677
+ return signupConnection(repo, args);
678
+ }
679
+ if (remoteEmail === requestedEmail) {
680
+ const updated = { ...saved, email: remoteEmail };
681
+ saveConnection(repo, updated);
682
+ return updated;
683
+ }
684
+ } catch (err) {
685
+ process.stdout.write(`CostLayers could not verify the saved key email (${err.message}); creating a new repo key for ${requestedEmail}.\n`);
686
+ return signupConnection(repo, args);
687
+ }
688
+ }
652
689
  return signupConnection(repo, args);
653
690
  }
654
691
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "costlayers",
3
- "version": "0.8.14",
3
+ "version": "0.8.15",
4
4
  "description": "CostLayers cost control for AI coding agents. Build compact repo context packs, gateway reports, and savings dashboards.",
5
5
  "bin": {
6
6
  "agentspend": "bin/agentspend.js",