@lucascouts/claude-agent-acp-plus 0.15.0 → 0.15.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"quota-cache.d.ts","sourceRoot":"","sources":["../src/quota-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAK5D;6EAC6E;AAC7E,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAyB7C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;sDAGsD;AACtD,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAqB9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqB/F"}
1
+ {"version":3,"file":"quota-cache.d.ts","sourceRoot":"","sources":["../src/quota-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAK5D;6EAC6E;AAC7E,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAwC7C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;sDAGsD;AACtD,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,GAAG,GAAE,MAAmB,GACvB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB9B;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB/F"}
@@ -29,23 +29,35 @@ import { promises as fs } from "node:fs";
29
29
  import * as os from "node:os";
30
30
  import * as path from "node:path";
31
31
  /**
32
- * A cache is only shareable between processes answering for the SAME account.
32
+ * Whether this session may share a sample at all.
33
33
  *
34
- * The api-key entry is the case that makes this mandatory rather than tidy: a
35
- * session authenticated by `ANTHROPIC_API_KEY` reports `rate_limits_available:
36
- * false` and no windows at all. Sharing one file with a subscription session
37
- * would let it publish that emptiness to every other window on the desktop.
34
+ * It may not when `ANTHROPIC_API_KEY` is set, and the reason is the measurement
35
+ * behind R8.1 rather than caution: an API-key session reports
36
+ * `rate_limits_available: false` and emits ZERO `_claude/rateLimit` frames. It
37
+ * has no plan window to publish and none to gain, so the cache has nothing to do
38
+ * for it.
38
39
  *
39
- * The key is a digest. The API key itself is hashed before it contributes, so
40
- * two different keys cannot collide while neither appears in a filename.
40
+ * That also settles a question the first version answered badly. Two different
41
+ * API keys can be two different accounts, so they must not share a file --
42
+ * which the first version enforced by folding a digest of the key into the
43
+ * filename. CodeQL flagged it (`js/insufficient-password-hash`, alert 27) and
44
+ * was right to: the rule guards stored, verified credentials, and this was
45
+ * neither, but "not exploitable" is the argument that ages badly. Excluding the
46
+ * whole case is stronger than hashing it well -- the credential never reaches a
47
+ * hash, and the behaviour is the one the wire already described.
48
+ */
49
+ function sharingDisabled() {
50
+ return Boolean(process.env.ANTHROPIC_API_KEY);
51
+ }
52
+ /**
53
+ * A cache is only shareable between processes answering for the SAME account.
54
+ *
55
+ * With API keys excluded above, what remains to separate is the configuration
56
+ * directory: two config scopes can be two logins, and neither should publish
57
+ * the other's windows.
41
58
  */
42
59
  function scopeKey() {
43
- const apiKey = process.env.ANTHROPIC_API_KEY;
44
- const scope = [
45
- process.env.ANTHROPIC_CONFIG_DIR ?? "",
46
- process.env.CLAUDE_CONFIG_DIR ?? "",
47
- apiKey ? createHash("sha256").update(apiKey).digest("hex") : "",
48
- ].join("\0");
60
+ const scope = [process.env.ANTHROPIC_CONFIG_DIR ?? "", process.env.CLAUDE_CONFIG_DIR ?? ""].join("\0");
49
61
  return createHash("sha256").update(scope).digest("hex").slice(0, 16);
50
62
  }
51
63
  /**
@@ -82,6 +94,9 @@ export function quotaCachePath() {
82
94
  * broken cache degrades to exactly the behaviour that existed before it.
83
95
  */
84
96
  export async function readFreshLimits(maxAgeMs, now = Date.now()) {
97
+ if (sharingDisabled()) {
98
+ return null;
99
+ }
85
100
  try {
86
101
  const raw = await fs.readFile(quotaCachePath(), "utf8");
87
102
  const parsed = JSON.parse(raw);
@@ -114,6 +129,9 @@ export async function readFreshLimits(maxAgeMs, now = Date.now()) {
114
129
  * are idempotent and the loser's work is simply discarded.
115
130
  */
116
131
  export async function writeLimits(limits, now = Date.now()) {
132
+ if (sharingDisabled()) {
133
+ return;
134
+ }
117
135
  const target = quotaCachePath();
118
136
  // Unique per WRITE, not per process. One adapter process serves several
119
137
  // sessions, so a turn ending in one can coincide with another's tick: sharing
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.15.0",
6
+ "version": "0.15.1",
7
7
  "description": "ACP adapter for the Claude Agent SDK with VS Code-parity UX for Zed and other ACP clients — checkbox multi-select questions, refusal consent dialog, dynamic agent name. Fork of claude-agent-acp.",
8
8
  "main": "dist/lib.js",
9
9
  "types": "dist/lib.d.ts",