costlayers 0.8.13 → 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.
- package/README.md +4 -4
- package/bin/agentspend.js +40 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ One-command setup:
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
cd your-repo
|
|
11
|
-
npx -y
|
|
11
|
+
npx -y costlayers@latest start --email you@example.com
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
@@ -24,7 +24,7 @@ Launch Codex with CostLayers context:
|
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
cd your-repo
|
|
27
|
-
npx -y
|
|
27
|
+
npx -y costlayers@latest start --email you@example.com -- codex
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
This gives Codex `.agentspend/repo-pack.md` and `.agentspend/runtime-plan.md`
|
|
@@ -44,7 +44,7 @@ API write permission:
|
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
export OPENAI_API_KEY=sk-proj-...
|
|
47
|
-
npx -y
|
|
47
|
+
npx -y costlayers@latest start --email you@example.com --codex-proxy -- codex
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
ChatGPT-login Codex can be metered, but it does not create per-request OpenAI
|
|
@@ -59,7 +59,7 @@ Platform invoice savings because it is not billed through your Platform API key.
|
|
|
59
59
|
To install only the Codex profile after signup:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
npx -y
|
|
62
|
+
npx -y costlayers@latest codex-profile
|
|
63
63
|
codex --profile costlayers
|
|
64
64
|
```
|
|
65
65
|
|
package/bin/agentspend.js
CHANGED
|
@@ -9,8 +9,8 @@ const https = require("https");
|
|
|
9
9
|
const os = require("os");
|
|
10
10
|
const { spawnSync } = require("child_process");
|
|
11
11
|
|
|
12
|
-
const VERSION = "0.8.
|
|
13
|
-
const INSTALL_SPEC = "
|
|
12
|
+
const VERSION = "0.8.15";
|
|
13
|
+
const INSTALL_SPEC = "costlayers@latest";
|
|
14
14
|
const DEFAULT_RUNS_PER_WEEK = 20;
|
|
15
15
|
const WEEKS_PER_MONTH = 4.33;
|
|
16
16
|
const DEFAULT_EXCLUDES = new Set([
|
|
@@ -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
|
-
|
|
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