@tempoxyz/patron 0.0.27 → 0.0.29
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/dist/bin.js +3 -3
- package/dist/chunks/{-PBBSDRMM.js → -OLVAZG3H.js} +236 -101
- package/dist/chunks/{chunk-TV5VLFTD.js → chunk-3CYJJJR3.js} +3 -2
- package/dist/chunks/{chunk-WZRGCKEK.js → chunk-EISHX7Q3.js} +54 -32
- package/dist/chunks/{chunk-HVTTV2A5.js → chunk-HQ2ZLUTT.js} +1 -1
- package/dist/chunks/chunk-OQXACACU.js +37 -0
- package/dist/chunks/chunk-SAEZ54SS.js +15496 -0
- package/dist/chunks/{chunk-F5CY5O7O.js → chunk-ZOQJ4CZE.js} +19132 -34415
- package/dist/chunks/{hook-3CYJEB2M.js → hook-HYV4BSCN.js} +16 -13
- package/dist/chunks/{hook-process-QQPBFRY6.js → hook-process-6WSLYXC7.js} +7 -7
- package/dist/chunks/{wallet-OJP2JREM.js → wallet-LOLL66ID.js} +5 -3
- package/package.json +1 -1
- package/dist/chunks/chunk-MZJEM2SE.js +0 -163
- package/dist/chunks/chunk-O64T22EK.js +0 -54
|
@@ -8,28 +8,28 @@ import {
|
|
|
8
8
|
parseHookInput,
|
|
9
9
|
payableDomain,
|
|
10
10
|
turnEnd
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HQ2ZLUTT.js";
|
|
12
12
|
import {
|
|
13
13
|
FileTokenStore,
|
|
14
14
|
codexHome,
|
|
15
|
-
loadIssuer,
|
|
16
15
|
needsRefill,
|
|
17
16
|
redeem,
|
|
18
|
-
refillSize
|
|
19
|
-
|
|
17
|
+
refillSize,
|
|
18
|
+
storedIssuer
|
|
19
|
+
} from "./chunk-SAEZ54SS.js";
|
|
20
20
|
import {
|
|
21
|
-
clampTokensPerPage,
|
|
22
21
|
settingsFor
|
|
23
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-OQXACACU.js";
|
|
24
23
|
import {
|
|
25
24
|
readConfig,
|
|
26
25
|
readUsage,
|
|
27
26
|
updateUsage,
|
|
28
27
|
writePrivateFile
|
|
29
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-ZOQJ4CZE.js";
|
|
30
29
|
import {
|
|
30
|
+
clampTokensPerPage,
|
|
31
31
|
withLock
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-EISHX7Q3.js";
|
|
33
33
|
import "./chunk-GTMLTZRN.js";
|
|
34
34
|
|
|
35
35
|
// src/hook.ts
|
|
@@ -250,11 +250,15 @@ async function payReads(dependencies, deadline) {
|
|
|
250
250
|
}
|
|
251
251
|
if (config.paused) return { paid: [], refill: false, skipped: "paused" };
|
|
252
252
|
if (domains.length === 0) return { paid: [], refill: false, skipped: "empty" };
|
|
253
|
+
const now = dependencies.now?.() ?? /* @__PURE__ */ new Date();
|
|
254
|
+
const stored = await storedIssuer(settings.home, settings.gatewayUrl, now.getTime());
|
|
255
|
+
if (!stored) {
|
|
256
|
+
dependencies.startRefill();
|
|
257
|
+
return { paid: [], refill: true, skipped: "no-issuer" };
|
|
258
|
+
}
|
|
259
|
+
const { issuer } = stored;
|
|
253
260
|
const store = new FileTokenStore(settings.home);
|
|
254
261
|
const boundedFetch = withDeadline(dependencies.fetch ?? fetch, deadline);
|
|
255
|
-
const issuer = await loadIssuer(settings.home, settings.gatewayUrl, {
|
|
256
|
-
fetch: boundedFetch
|
|
257
|
-
});
|
|
258
262
|
const perPage = clampTokensPerPage(config.tokensPerPage);
|
|
259
263
|
const taken = await store.takeWithRemaining(domains.length * perPage, domains.length);
|
|
260
264
|
const { empty, paid, unspent } = await redeemRounds(
|
|
@@ -269,7 +273,6 @@ async function payReads(dependencies, deadline) {
|
|
|
269
273
|
}
|
|
270
274
|
);
|
|
271
275
|
await store.add(unspent);
|
|
272
|
-
const now = dependencies.now?.() ?? /* @__PURE__ */ new Date();
|
|
273
276
|
if (paid.length > 0)
|
|
274
277
|
await updateUsage(
|
|
275
278
|
settings.home,
|
|
@@ -280,7 +283,7 @@ async function payReads(dependencies, deadline) {
|
|
|
280
283
|
},
|
|
281
284
|
now
|
|
282
285
|
);
|
|
283
|
-
const refill = needsRefill(taken.remaining + unspent.length) && refillSize(config, await readUsage(settings.home, now)) > 0;
|
|
286
|
+
const refill = stored.stale || needsRefill(taken.remaining + unspent.length) && refillSize(config, await readUsage(settings.home, now)) > 0;
|
|
284
287
|
if (refill) dependencies.startRefill();
|
|
285
288
|
return {
|
|
286
289
|
paid,
|
|
@@ -7,17 +7,17 @@ import {
|
|
|
7
7
|
isCursorPayload,
|
|
8
8
|
parseHookInput,
|
|
9
9
|
turnEnd
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HQ2ZLUTT.js";
|
|
11
11
|
import {
|
|
12
12
|
startDrain,
|
|
13
13
|
startRefill
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-3CYJJJR3.js";
|
|
15
15
|
import {
|
|
16
16
|
resolveSettings
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OQXACACU.js";
|
|
18
18
|
import {
|
|
19
19
|
tryLock
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-EISHX7Q3.js";
|
|
21
21
|
import "./chunk-GTMLTZRN.js";
|
|
22
22
|
|
|
23
23
|
// src/hook-process.ts
|
|
@@ -178,7 +178,7 @@ async function runHookProcess(argument = process.argv[3]) {
|
|
|
178
178
|
await payEvent(
|
|
179
179
|
event,
|
|
180
180
|
settings,
|
|
181
|
-
() => startRefill(),
|
|
181
|
+
() => startRefill({ delayed: true }),
|
|
182
182
|
started + HOOK_TIMEOUT_MS - Date.now()
|
|
183
183
|
);
|
|
184
184
|
}
|
|
@@ -191,7 +191,7 @@ async function runPayProcess() {
|
|
|
191
191
|
const refill = () => {
|
|
192
192
|
if (Date.now() - refilledAt < REFILL_RETRY_MS) return;
|
|
193
193
|
refilledAt = Date.now();
|
|
194
|
-
startRefill();
|
|
194
|
+
startRefill({ delayed: true });
|
|
195
195
|
};
|
|
196
196
|
await drainQueue(settings.home, {
|
|
197
197
|
deadline: Date.now() + DRAIN_MAX_MS,
|
|
@@ -202,7 +202,7 @@ async function runPayProcess() {
|
|
|
202
202
|
}
|
|
203
203
|
async function payEvent(event, settings, refill, timeoutMs) {
|
|
204
204
|
if (timeoutMs <= 0) return;
|
|
205
|
-
const { runHook } = await import("./hook-
|
|
205
|
+
const { runHook } = await import("./hook-HYV4BSCN.js");
|
|
206
206
|
await runHook(
|
|
207
207
|
{
|
|
208
208
|
readInput: async () => event.raw,
|
|
@@ -2,8 +2,10 @@ import { createRequire as __patronCreateRequire } from 'node:module'
|
|
|
2
2
|
const require = __patronCreateRequire(import.meta.url)
|
|
3
3
|
import {
|
|
4
4
|
statePaths
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import
|
|
5
|
+
} from "./chunk-ZOQJ4CZE.js";
|
|
6
|
+
import {
|
|
7
|
+
accessKeyLimitUnits
|
|
8
|
+
} from "./chunk-EISHX7Q3.js";
|
|
7
9
|
import "./chunk-GTMLTZRN.js";
|
|
8
10
|
|
|
9
11
|
// src/wallet.ts
|
|
@@ -137,7 +139,7 @@ async function openLinkWallet(config, maxUnits, output = process.stderr) {
|
|
|
137
139
|
}
|
|
138
140
|
function budgetLimit(budgetUnits, currency) {
|
|
139
141
|
return {
|
|
140
|
-
limit: toHex(budgetUnits),
|
|
142
|
+
limit: toHex(accessKeyLimitUnits(budgetUnits)),
|
|
141
143
|
period: BUDGET_PERIOD_SECONDS,
|
|
142
144
|
token: currency
|
|
143
145
|
};
|
package/package.json
CHANGED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
|
-
const require = __patronCreateRequire(import.meta.url)
|
|
3
|
-
import {
|
|
4
|
-
withLock
|
|
5
|
-
} from "./chunk-O64T22EK.js";
|
|
6
|
-
|
|
7
|
-
// src/state.ts
|
|
8
|
-
import { randomBytes } from "node:crypto";
|
|
9
|
-
import {
|
|
10
|
-
chmod,
|
|
11
|
-
lstat,
|
|
12
|
-
mkdir,
|
|
13
|
-
readFile,
|
|
14
|
-
readlink,
|
|
15
|
-
rename,
|
|
16
|
-
rm,
|
|
17
|
-
writeFile
|
|
18
|
-
} from "node:fs/promises";
|
|
19
|
-
import { dirname, join, resolve } from "node:path";
|
|
20
|
-
var AGENT_IDS = ["claude-code", "codex", "cursor", "amp"];
|
|
21
|
-
function statePaths(home) {
|
|
22
|
-
return {
|
|
23
|
-
config: join(home, "config.json"),
|
|
24
|
-
issuer: join(home, "issuer.json"),
|
|
25
|
-
key: join(home, "key"),
|
|
26
|
-
linkRefill: join(home, "link-refill.json"),
|
|
27
|
-
refillLock: join(home, "refill.lock"),
|
|
28
|
-
stateLock: join(home, "state.lock"),
|
|
29
|
-
tokens: join(home, "tokens.enc"),
|
|
30
|
-
usage: join(home, "usage.json"),
|
|
31
|
-
usageLock: join(home, "usage.lock"),
|
|
32
|
-
wallet: join(home, "wallet.json")
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function monthOf(now) {
|
|
36
|
-
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
37
|
-
}
|
|
38
|
-
async function ensureHome(home) {
|
|
39
|
-
await mkdir(home, { mode: 448, recursive: true });
|
|
40
|
-
}
|
|
41
|
-
async function readJson(path) {
|
|
42
|
-
try {
|
|
43
|
-
return JSON.parse(await readFile(path, "utf8"));
|
|
44
|
-
} catch (error) {
|
|
45
|
-
if (error.code === "ENOENT") return void 0;
|
|
46
|
-
throw error;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async function writePrivateFile(link, contents) {
|
|
50
|
-
const target = await symlinkTarget(link);
|
|
51
|
-
if (target !== link) {
|
|
52
|
-
try {
|
|
53
|
-
return await replaceFile(target, contents);
|
|
54
|
-
} catch (error) {
|
|
55
|
-
const code = error.code;
|
|
56
|
-
if (code !== "EACCES" && code !== "EROFS" && code !== "EPERM") throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
await replaceFile(link, contents);
|
|
60
|
-
}
|
|
61
|
-
async function symlinkTarget(path, depth = 0) {
|
|
62
|
-
if (depth > 8) return path;
|
|
63
|
-
try {
|
|
64
|
-
const stats = await lstat(path);
|
|
65
|
-
if (!stats.isSymbolicLink()) return path;
|
|
66
|
-
return symlinkTarget(resolve(dirname(path), await readlink(path)), depth + 1);
|
|
67
|
-
} catch {
|
|
68
|
-
return path;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
async function replaceFile(path, contents) {
|
|
72
|
-
const temporary = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
73
|
-
try {
|
|
74
|
-
await writeFile(temporary, contents, { mode: 384 });
|
|
75
|
-
await chmod(temporary, 384);
|
|
76
|
-
await rename(temporary, path);
|
|
77
|
-
} catch (error) {
|
|
78
|
-
await rm(temporary, { force: true }).catch(() => void 0);
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
async function readConfig(home) {
|
|
83
|
-
const value = await readJson(statePaths(home).config).catch(() => void 0);
|
|
84
|
-
if (!value || typeof value !== "object") return void 0;
|
|
85
|
-
const config = value;
|
|
86
|
-
if (config.version !== 1 || typeof config.address !== "string") return void 0;
|
|
87
|
-
return {
|
|
88
|
-
agents: Array.isArray(config.agents) ? config.agents.filter(
|
|
89
|
-
(agent) => AGENT_IDS.includes(agent)
|
|
90
|
-
) : [],
|
|
91
|
-
address: config.address,
|
|
92
|
-
gatewayUrl: String(config.gatewayUrl ?? ""),
|
|
93
|
-
monthlyBudgetUsd: Number(config.monthlyBudgetUsd ?? 0),
|
|
94
|
-
network: config.network === "testnet" ? "testnet" : "mainnet",
|
|
95
|
-
paused: config.paused === true,
|
|
96
|
-
relayUrl: String(config.relayUrl ?? ""),
|
|
97
|
-
version: 1,
|
|
98
|
-
wallet: config.wallet === "key" || config.wallet === "link" ? config.wallet : "tempo",
|
|
99
|
-
...typeof config.linkPaymentMethodId === "string" ? { linkPaymentMethodId: config.linkPaymentMethodId } : {},
|
|
100
|
-
...typeof config.name === "string" ? { name: config.name } : {},
|
|
101
|
-
...typeof config.tokensPerPage === "number" ? { tokensPerPage: config.tokensPerPage } : {}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
async function writeConfig(home, config) {
|
|
105
|
-
await ensureHome(home);
|
|
106
|
-
await writePrivateFile(
|
|
107
|
-
statePaths(home).config,
|
|
108
|
-
`${JSON.stringify(config, null, " ")}
|
|
109
|
-
`
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
function emptyUsage(month) {
|
|
113
|
-
return { boughtTokens: 0, domains: {}, month, paidPages: 0, tippedTokens: 0 };
|
|
114
|
-
}
|
|
115
|
-
async function readUsage(home, now = /* @__PURE__ */ new Date()) {
|
|
116
|
-
const month = monthOf(now);
|
|
117
|
-
const path = statePaths(home).usage;
|
|
118
|
-
const value = await readJson(path).catch(() => {
|
|
119
|
-
throw unreadableUsage(path);
|
|
120
|
-
});
|
|
121
|
-
if (value === void 0) return emptyUsage(month);
|
|
122
|
-
if (!isUsageRecord(value)) throw unreadableUsage(path);
|
|
123
|
-
if (value.month !== month) return emptyUsage(month);
|
|
124
|
-
return {
|
|
125
|
-
boughtTokens: value.boughtTokens,
|
|
126
|
-
domains: value.domains && typeof value.domains === "object" ? { ...value.domains } : {},
|
|
127
|
-
month,
|
|
128
|
-
paidPages: Number(value.paidPages ?? 0),
|
|
129
|
-
tippedTokens: Number(value.tippedTokens ?? 0)
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
function isUsageRecord(value) {
|
|
133
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
134
|
-
const usage = value;
|
|
135
|
-
return typeof usage.month === "string" && typeof usage.boughtTokens === "number" && Number.isFinite(usage.boughtTokens) && usage.boughtTokens >= 0;
|
|
136
|
-
}
|
|
137
|
-
function unreadableUsage(path) {
|
|
138
|
-
return new Error(
|
|
139
|
-
`${path} is unreadable, so Patron stops adding to your balance. Delete it to restart this month's budget count.`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
async function updateUsage(home, update, now = /* @__PURE__ */ new Date()) {
|
|
143
|
-
await ensureHome(home);
|
|
144
|
-
return withLock(statePaths(home).usageLock, async () => {
|
|
145
|
-
const usage = await readUsage(home, now);
|
|
146
|
-
update(usage);
|
|
147
|
-
await writePrivateFile(statePaths(home).usage, `${JSON.stringify(usage)}
|
|
148
|
-
`);
|
|
149
|
-
return usage;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export {
|
|
154
|
-
AGENT_IDS,
|
|
155
|
-
statePaths,
|
|
156
|
-
ensureHome,
|
|
157
|
-
readJson,
|
|
158
|
-
writePrivateFile,
|
|
159
|
-
readConfig,
|
|
160
|
-
writeConfig,
|
|
161
|
-
readUsage,
|
|
162
|
-
updateUsage
|
|
163
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
|
-
const require = __patronCreateRequire(import.meta.url)
|
|
3
|
-
|
|
4
|
-
// src/lock.ts
|
|
5
|
-
import { open, rm, stat } from "node:fs/promises";
|
|
6
|
-
async function withLock(path, fn, options = {}) {
|
|
7
|
-
const deadline = Date.now() + (options.timeoutMs ?? 3e3);
|
|
8
|
-
const staleMs = options.staleMs ?? 1e4;
|
|
9
|
-
for (; ; ) {
|
|
10
|
-
try {
|
|
11
|
-
const handle = await open(path, "wx", 384);
|
|
12
|
-
await handle.close();
|
|
13
|
-
break;
|
|
14
|
-
} catch (error) {
|
|
15
|
-
if (error.code !== "EEXIST") throw error;
|
|
16
|
-
const age = await stat(path).then(
|
|
17
|
-
(stats) => Date.now() - stats.mtimeMs,
|
|
18
|
-
() => 0
|
|
19
|
-
);
|
|
20
|
-
if (age > staleMs) {
|
|
21
|
-
await rm(path, { force: true });
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
if (Date.now() > deadline) throw new Error(`Patron state is busy: ${path}`);
|
|
25
|
-
await new Promise((resolve) => setTimeout(resolve, 10 + Math.random() * 20));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
try {
|
|
29
|
-
return await fn();
|
|
30
|
-
} finally {
|
|
31
|
-
await rm(path, { force: true });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async function tryLock(path, staleMs) {
|
|
35
|
-
try {
|
|
36
|
-
const handle = await open(path, "wx", 384);
|
|
37
|
-
await handle.close();
|
|
38
|
-
} catch (error) {
|
|
39
|
-
if (error.code !== "EEXIST") throw error;
|
|
40
|
-
const age = await stat(path).then(
|
|
41
|
-
(stats) => Date.now() - stats.mtimeMs,
|
|
42
|
-
() => 0
|
|
43
|
-
);
|
|
44
|
-
if (age <= staleMs) return void 0;
|
|
45
|
-
await rm(path, { force: true });
|
|
46
|
-
return tryLock(path, staleMs);
|
|
47
|
-
}
|
|
48
|
-
return () => rm(path, { force: true });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
withLock,
|
|
53
|
-
tryLock
|
|
54
|
-
};
|