@tempoxyz/patron 0.0.28 → 0.0.30
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 +11 -3
- package/dist/chunks/{-5Q7V7W7W.js → -WRUP4P4C.js} +341 -116
- package/dist/chunks/{chunk-HQ2ZLUTT.js → chunk-23MZSDN6.js} +1 -1
- package/dist/chunks/{chunk-EKFENOVR.js → chunk-4SXIRXUL.js} +68 -28
- package/dist/chunks/{chunk-EISHX7Q3.js → chunk-AKOXBXV3.js} +207 -48
- package/dist/chunks/{chunk-OQXACACU.js → chunk-NDBTADXZ.js} +9 -2
- package/dist/chunks/{chunk-EV7OA6GK.js → chunk-ROVOCDKE.js} +7 -163
- package/dist/chunks/chunk-TC2WEQ25.js +179 -0
- package/dist/chunks/{hook-N2SVXVUR.js → hook-IE7INCPX.js} +17 -15
- package/dist/chunks/{hook-process-IMQMGXBT.js → hook-process-ETJ3UZZT.js} +62 -16
- package/dist/chunks/{wallet-6TDMXRWW.js → wallet-OTFEEKIG.js} +3 -4
- package/package.json +1 -1
- package/dist/chunks/chunk-TV5VLFTD.js +0 -55
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
2
|
const require = __patronCreateRequire(import.meta.url)
|
|
3
3
|
import {
|
|
4
|
-
MAX_TOKENS_PER_PURCHASE
|
|
5
|
-
|
|
6
|
-
} from "./chunk-EISHX7Q3.js";
|
|
4
|
+
MAX_TOKENS_PER_PURCHASE
|
|
5
|
+
} from "./chunk-AKOXBXV3.js";
|
|
7
6
|
import {
|
|
8
7
|
__export
|
|
9
8
|
} from "./chunk-GTMLTZRN.js";
|
|
@@ -5075,7 +5074,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5075
5074
|
var NONE = 0;
|
|
5076
5075
|
var ASSUMED = 1;
|
|
5077
5076
|
var PROVEN = 2;
|
|
5078
|
-
function isRecursive(inst, stack,
|
|
5077
|
+
function isRecursive(inst, stack, resolve) {
|
|
5079
5078
|
const cached2 = recursive.get(inst);
|
|
5080
5079
|
if (cached2 !== void 0)
|
|
5081
5080
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5085,7 +5084,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
5085
5084
|
let result = NONE;
|
|
5086
5085
|
const check2 = (child) => {
|
|
5087
5086
|
if (result !== PROVEN && child?._zod) {
|
|
5088
|
-
const answer = isRecursive(child, stack,
|
|
5087
|
+
const answer = isRecursive(child, stack, resolve);
|
|
5089
5088
|
if (answer > result)
|
|
5090
5089
|
result = answer;
|
|
5091
5090
|
}
|
|
@@ -5096,7 +5095,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
5096
5095
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5097
5096
|
if (spread && !desc.enumerable)
|
|
5098
5097
|
continue;
|
|
5099
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5098
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;
|
|
5100
5099
|
if (child > answer)
|
|
5101
5100
|
answer = child;
|
|
5102
5101
|
}
|
|
@@ -5160,7 +5159,7 @@ function isRecursive(inst, stack, resolve2) {
|
|
|
5160
5159
|
break;
|
|
5161
5160
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5162
5161
|
case "lazy": {
|
|
5163
|
-
const inner = def._cachedInner ?? (
|
|
5162
|
+
const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : void 0);
|
|
5164
5163
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5165
5164
|
break;
|
|
5166
5165
|
}
|
|
@@ -19861,166 +19860,11 @@ address: ${address2.toLowerCase()}
|
|
|
19861
19860
|
name: ${name}`;
|
|
19862
19861
|
}
|
|
19863
19862
|
|
|
19864
|
-
// src/state.ts
|
|
19865
|
-
import { randomBytes } from "node:crypto";
|
|
19866
|
-
import {
|
|
19867
|
-
chmod,
|
|
19868
|
-
lstat,
|
|
19869
|
-
mkdir,
|
|
19870
|
-
readFile,
|
|
19871
|
-
readlink,
|
|
19872
|
-
rename,
|
|
19873
|
-
rm,
|
|
19874
|
-
writeFile
|
|
19875
|
-
} from "node:fs/promises";
|
|
19876
|
-
import { dirname, join, resolve } from "node:path";
|
|
19877
|
-
var AGENT_IDS = ["claude-code", "codex", "cursor", "amp"];
|
|
19878
|
-
function statePaths(home) {
|
|
19879
|
-
return {
|
|
19880
|
-
config: join(home, "config.json"),
|
|
19881
|
-
issuer: join(home, "issuer.json"),
|
|
19882
|
-
key: join(home, "key"),
|
|
19883
|
-
linkRefill: join(home, "link-refill.json"),
|
|
19884
|
-
refillLock: join(home, "refill.lock"),
|
|
19885
|
-
stateLock: join(home, "state.lock"),
|
|
19886
|
-
tokens: join(home, "tokens.enc"),
|
|
19887
|
-
usage: join(home, "usage.json"),
|
|
19888
|
-
usageLock: join(home, "usage.lock"),
|
|
19889
|
-
wallet: join(home, "wallet.json")
|
|
19890
|
-
};
|
|
19891
|
-
}
|
|
19892
|
-
function monthOf(now) {
|
|
19893
|
-
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
|
19894
|
-
}
|
|
19895
|
-
async function ensureHome(home) {
|
|
19896
|
-
await mkdir(home, { mode: 448, recursive: true });
|
|
19897
|
-
}
|
|
19898
|
-
async function readJson(path) {
|
|
19899
|
-
try {
|
|
19900
|
-
return JSON.parse(await readFile(path, "utf8"));
|
|
19901
|
-
} catch (error62) {
|
|
19902
|
-
if (error62.code === "ENOENT") return void 0;
|
|
19903
|
-
throw error62;
|
|
19904
|
-
}
|
|
19905
|
-
}
|
|
19906
|
-
async function writePrivateFile(link, contents) {
|
|
19907
|
-
const target = await symlinkTarget(link);
|
|
19908
|
-
if (target !== link) {
|
|
19909
|
-
try {
|
|
19910
|
-
return await replaceFile(target, contents);
|
|
19911
|
-
} catch (error62) {
|
|
19912
|
-
const code = error62.code;
|
|
19913
|
-
if (code !== "EACCES" && code !== "EROFS" && code !== "EPERM") throw error62;
|
|
19914
|
-
}
|
|
19915
|
-
}
|
|
19916
|
-
await replaceFile(link, contents);
|
|
19917
|
-
}
|
|
19918
|
-
async function symlinkTarget(path, depth = 0) {
|
|
19919
|
-
if (depth > 8) return path;
|
|
19920
|
-
try {
|
|
19921
|
-
const stats = await lstat(path);
|
|
19922
|
-
if (!stats.isSymbolicLink()) return path;
|
|
19923
|
-
return symlinkTarget(resolve(dirname(path), await readlink(path)), depth + 1);
|
|
19924
|
-
} catch {
|
|
19925
|
-
return path;
|
|
19926
|
-
}
|
|
19927
|
-
}
|
|
19928
|
-
async function replaceFile(path, contents) {
|
|
19929
|
-
const temporary = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;
|
|
19930
|
-
try {
|
|
19931
|
-
await writeFile(temporary, contents, { mode: 384 });
|
|
19932
|
-
await chmod(temporary, 384);
|
|
19933
|
-
await rename(temporary, path);
|
|
19934
|
-
} catch (error62) {
|
|
19935
|
-
await rm(temporary, { force: true }).catch(() => void 0);
|
|
19936
|
-
throw error62;
|
|
19937
|
-
}
|
|
19938
|
-
}
|
|
19939
|
-
async function readConfig(home) {
|
|
19940
|
-
const value = await readJson(statePaths(home).config).catch(() => void 0);
|
|
19941
|
-
if (!value || typeof value !== "object") return void 0;
|
|
19942
|
-
const config2 = value;
|
|
19943
|
-
if (config2.version !== 1 || typeof config2.address !== "string") return void 0;
|
|
19944
|
-
return {
|
|
19945
|
-
agents: Array.isArray(config2.agents) ? config2.agents.filter(
|
|
19946
|
-
(agent) => AGENT_IDS.includes(agent)
|
|
19947
|
-
) : [],
|
|
19948
|
-
address: config2.address,
|
|
19949
|
-
gatewayUrl: String(config2.gatewayUrl ?? ""),
|
|
19950
|
-
monthlyBudgetUsd: Number(config2.monthlyBudgetUsd ?? 0),
|
|
19951
|
-
network: config2.network === "testnet" ? "testnet" : "mainnet",
|
|
19952
|
-
paused: config2.paused === true,
|
|
19953
|
-
relayUrl: String(config2.relayUrl ?? ""),
|
|
19954
|
-
version: 1,
|
|
19955
|
-
wallet: config2.wallet === "key" || config2.wallet === "link" ? config2.wallet : "tempo",
|
|
19956
|
-
...typeof config2.linkPaymentMethodId === "string" ? { linkPaymentMethodId: config2.linkPaymentMethodId } : {},
|
|
19957
|
-
...typeof config2.name === "string" ? { name: config2.name } : {},
|
|
19958
|
-
...typeof config2.tokensPerPage === "number" ? { tokensPerPage: config2.tokensPerPage } : {}
|
|
19959
|
-
};
|
|
19960
|
-
}
|
|
19961
|
-
async function writeConfig(home, config2) {
|
|
19962
|
-
await ensureHome(home);
|
|
19963
|
-
await writePrivateFile(
|
|
19964
|
-
statePaths(home).config,
|
|
19965
|
-
`${JSON.stringify(config2, null, " ")}
|
|
19966
|
-
`
|
|
19967
|
-
);
|
|
19968
|
-
}
|
|
19969
|
-
function emptyUsage(month) {
|
|
19970
|
-
return { boughtTokens: 0, domains: {}, month, paidPages: 0, tippedTokens: 0 };
|
|
19971
|
-
}
|
|
19972
|
-
async function readUsage(home, now = /* @__PURE__ */ new Date()) {
|
|
19973
|
-
const month = monthOf(now);
|
|
19974
|
-
const path = statePaths(home).usage;
|
|
19975
|
-
const value = await readJson(path).catch(() => {
|
|
19976
|
-
throw unreadableUsage(path);
|
|
19977
|
-
});
|
|
19978
|
-
if (value === void 0) return emptyUsage(month);
|
|
19979
|
-
if (!isUsageRecord(value)) throw unreadableUsage(path);
|
|
19980
|
-
if (value.month !== month) return emptyUsage(month);
|
|
19981
|
-
return {
|
|
19982
|
-
boughtTokens: value.boughtTokens,
|
|
19983
|
-
domains: value.domains && typeof value.domains === "object" ? { ...value.domains } : {},
|
|
19984
|
-
month,
|
|
19985
|
-
paidPages: Number(value.paidPages ?? 0),
|
|
19986
|
-
tippedTokens: Number(value.tippedTokens ?? 0)
|
|
19987
|
-
};
|
|
19988
|
-
}
|
|
19989
|
-
function isUsageRecord(value) {
|
|
19990
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
19991
|
-
const usage = value;
|
|
19992
|
-
return typeof usage.month === "string" && typeof usage.boughtTokens === "number" && Number.isFinite(usage.boughtTokens) && usage.boughtTokens >= 0;
|
|
19993
|
-
}
|
|
19994
|
-
function unreadableUsage(path) {
|
|
19995
|
-
return new Error(
|
|
19996
|
-
`${path} is unreadable, so Patron stops adding to your balance. Delete it to restart this month's budget count.`
|
|
19997
|
-
);
|
|
19998
|
-
}
|
|
19999
|
-
async function updateUsage(home, update, now = /* @__PURE__ */ new Date()) {
|
|
20000
|
-
await ensureHome(home);
|
|
20001
|
-
return withLock(statePaths(home).usageLock, async () => {
|
|
20002
|
-
const usage = await readUsage(home, now);
|
|
20003
|
-
update(usage);
|
|
20004
|
-
await writePrivateFile(statePaths(home).usage, `${JSON.stringify(usage)}
|
|
20005
|
-
`);
|
|
20006
|
-
return usage;
|
|
20007
|
-
});
|
|
20008
|
-
}
|
|
20009
|
-
|
|
20010
19863
|
export {
|
|
20011
19864
|
IssuerInfo,
|
|
20012
19865
|
IssueResponse,
|
|
20013
19866
|
RedeemResponse,
|
|
20014
19867
|
LeaderboardResponse,
|
|
20015
19868
|
PatronInfo,
|
|
20016
|
-
profileMessage
|
|
20017
|
-
AGENT_IDS,
|
|
20018
|
-
statePaths,
|
|
20019
|
-
ensureHome,
|
|
20020
|
-
readJson,
|
|
20021
|
-
writePrivateFile,
|
|
20022
|
-
readConfig,
|
|
20023
|
-
writeConfig,
|
|
20024
|
-
readUsage,
|
|
20025
|
-
updateUsage
|
|
19869
|
+
profileMessage
|
|
20026
19870
|
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
|
+
const require = __patronCreateRequire(import.meta.url)
|
|
3
|
+
import {
|
|
4
|
+
ensureHome,
|
|
5
|
+
readJson,
|
|
6
|
+
statePaths,
|
|
7
|
+
withLock,
|
|
8
|
+
writePrivateFile
|
|
9
|
+
} from "./chunk-AKOXBXV3.js";
|
|
10
|
+
|
|
11
|
+
// src/refill-process.ts
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
function startRefill(options = {}, script = process.argv[1]) {
|
|
15
|
+
try {
|
|
16
|
+
if (!script) return;
|
|
17
|
+
const [command, refillArgs] = refillCommand(script);
|
|
18
|
+
const args = options.delayed ? [...refillArgs, "--delay"] : refillArgs;
|
|
19
|
+
const child = spawn(command, args, {
|
|
20
|
+
detached: true,
|
|
21
|
+
env: process.env,
|
|
22
|
+
stdio: "ignore"
|
|
23
|
+
});
|
|
24
|
+
child.on("error", () => void 0);
|
|
25
|
+
child.unref();
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function refillCommand(script) {
|
|
30
|
+
try {
|
|
31
|
+
createRequire(script).resolve("mppx");
|
|
32
|
+
return [process.execPath, [...process.execArgv, script, "refill"]];
|
|
33
|
+
} catch {
|
|
34
|
+
return [
|
|
35
|
+
process.platform === "win32" ? "npx.cmd" : "npx",
|
|
36
|
+
["-y", "@tempoxyz/patron", "refill"]
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function startDrain(script = process.argv[1]) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
try {
|
|
43
|
+
if (!script) return resolve(false);
|
|
44
|
+
const child = spawn(process.execPath, [...process.execArgv, script, "pay"], {
|
|
45
|
+
detached: true,
|
|
46
|
+
env: process.env,
|
|
47
|
+
stdio: "ignore"
|
|
48
|
+
});
|
|
49
|
+
child.on("error", () => resolve(false));
|
|
50
|
+
child.on("spawn", () => {
|
|
51
|
+
child.unref();
|
|
52
|
+
resolve(true);
|
|
53
|
+
});
|
|
54
|
+
} catch {
|
|
55
|
+
resolve(false);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/spacing.ts
|
|
61
|
+
import { randomBytes } from "node:crypto";
|
|
62
|
+
var REDEEM_HOLD_MIN_MS = 2 * 6e4;
|
|
63
|
+
var REDEEM_HOLD_SPREAD_MS = 8 * 6e4;
|
|
64
|
+
var GATEWAY_QUIET_MS = 2 * 6e4;
|
|
65
|
+
var GATEWAY_WANT_MS = 10 * 6e4;
|
|
66
|
+
var GATEWAY_LEASE_MS = 15 * 6e4;
|
|
67
|
+
async function update(home, fn) {
|
|
68
|
+
await ensureHome(home);
|
|
69
|
+
const paths = statePaths(home);
|
|
70
|
+
return withLock(paths.spacingLock, async () => {
|
|
71
|
+
const value = await readJson(paths.spacing).catch(() => void 0);
|
|
72
|
+
const current = typeof value === "object" && value !== null ? value : {};
|
|
73
|
+
const { result, next } = fn(current);
|
|
74
|
+
if (next) await writePrivateFile(paths.spacing, JSON.stringify(next));
|
|
75
|
+
return result;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function redeemWait(spacing, now) {
|
|
79
|
+
const running = Object.values(spacing.gateways ?? {}).filter((until) => until > now);
|
|
80
|
+
const wanted = spacing.gatewayWanted !== void 0 && now >= spacing.gatewayWanted ? spacing.gatewayWanted + GATEWAY_WANT_MS : 0;
|
|
81
|
+
return Math.max(
|
|
82
|
+
0,
|
|
83
|
+
(spacing.redeemAfter ?? 0) - now,
|
|
84
|
+
wanted - now,
|
|
85
|
+
...running.map((until) => until - now)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
function claimRedemptions(home, now, leaseMs) {
|
|
89
|
+
return update(home, (spacing) => {
|
|
90
|
+
if (redeemWait(spacing, now) > 0) return { result: false };
|
|
91
|
+
const until = Math.max(spacing.redeemingUntil ?? 0, now + leaseMs);
|
|
92
|
+
return { result: true, next: { ...spacing, redeemingUntil: until } };
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function redemptionWait(home, now = Date.now()) {
|
|
96
|
+
return update(home, (spacing) => ({ result: redeemWait(spacing, now) }));
|
|
97
|
+
}
|
|
98
|
+
function claimGateway(home, now, random = Math.random) {
|
|
99
|
+
return update(home, (spacing) => {
|
|
100
|
+
const wait = Math.max(
|
|
101
|
+
0,
|
|
102
|
+
(spacing.redeemingUntil ?? Number.NEGATIVE_INFINITY) + GATEWAY_QUIET_MS - now
|
|
103
|
+
);
|
|
104
|
+
if (wait > 0) {
|
|
105
|
+
const active = spacing.gatewayWanted !== void 0 && now < spacing.gatewayWanted + GATEWAY_WANT_MS;
|
|
106
|
+
return {
|
|
107
|
+
result: wait,
|
|
108
|
+
...active ? {} : { next: { ...spacing, gatewayWanted: now } }
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const id = randomBytes(6).toString("hex");
|
|
112
|
+
const gateways = Object.fromEntries(
|
|
113
|
+
Object.entries(spacing.gateways ?? {}).filter(([, until]) => until > now)
|
|
114
|
+
);
|
|
115
|
+
const { gatewayWanted: _, ...rest } = spacing;
|
|
116
|
+
return {
|
|
117
|
+
result: id,
|
|
118
|
+
next: { ...rest, gateways: { ...gateways, [id]: now + GATEWAY_LEASE_MS } }
|
|
119
|
+
};
|
|
120
|
+
}).then(
|
|
121
|
+
(result) => typeof result === "number" ? result : () => update(home, (spacing) => {
|
|
122
|
+
const end = Date.now();
|
|
123
|
+
const { [result]: _, ...gateways } = spacing.gateways ?? {};
|
|
124
|
+
const hold = end + REDEEM_HOLD_MIN_MS + Math.floor(random() * REDEEM_HOLD_SPREAD_MS);
|
|
125
|
+
return {
|
|
126
|
+
result: void 0,
|
|
127
|
+
next: {
|
|
128
|
+
...spacing,
|
|
129
|
+
gateways,
|
|
130
|
+
redeemAfter: Math.max(spacing.redeemAfter ?? 0, hold)
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
})
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
137
|
+
var RECHECK_MS = 6e4;
|
|
138
|
+
async function gatewayTurn(home, fn, options = {}) {
|
|
139
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
140
|
+
let waited = 0;
|
|
141
|
+
for (; ; ) {
|
|
142
|
+
const claim = await claimGateway(home, Date.now(), options.random);
|
|
143
|
+
if (typeof claim !== "number") {
|
|
144
|
+
try {
|
|
145
|
+
return await fn();
|
|
146
|
+
} finally {
|
|
147
|
+
await claim();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (waited + claim > (options.maxWaitMs ?? Number.POSITIVE_INFINITY)) return void 0;
|
|
151
|
+
if (waited === 0) options.onWait?.(claim);
|
|
152
|
+
const ms = claim + 1e3;
|
|
153
|
+
await sleep(ms);
|
|
154
|
+
waited += ms;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function awaitRedemptions(home, leaseMs, options = {}) {
|
|
158
|
+
const sleep = options.sleep ?? defaultSleep;
|
|
159
|
+
let waited = 0;
|
|
160
|
+
for (; ; ) {
|
|
161
|
+
if (options.cancelled?.()) return false;
|
|
162
|
+
if (await claimRedemptions(home, Date.now(), leaseMs)) return true;
|
|
163
|
+
const wait = await redemptionWait(home);
|
|
164
|
+
if (waited + wait > (options.maxWaitMs ?? Number.POSITIVE_INFINITY)) return false;
|
|
165
|
+
if (waited === 0) options.onWait?.(wait);
|
|
166
|
+
const ms = Math.min(Math.max(wait, 1e3), RECHECK_MS);
|
|
167
|
+
await sleep(ms);
|
|
168
|
+
waited += ms;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export {
|
|
173
|
+
startRefill,
|
|
174
|
+
startDrain,
|
|
175
|
+
claimRedemptions,
|
|
176
|
+
redemptionWait,
|
|
177
|
+
gatewayTurn,
|
|
178
|
+
awaitRedemptions
|
|
179
|
+
};
|
|
@@ -8,28 +8,27 @@ import {
|
|
|
8
8
|
parseHookInput,
|
|
9
9
|
payableDomain,
|
|
10
10
|
turnEnd
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-23MZSDN6.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-4SXIRXUL.js";
|
|
20
20
|
import {
|
|
21
21
|
settingsFor
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-NDBTADXZ.js";
|
|
23
|
+
import "./chunk-ROVOCDKE.js";
|
|
23
24
|
import {
|
|
25
|
+
clampTokensPerPage,
|
|
24
26
|
readConfig,
|
|
25
27
|
readUsage,
|
|
26
28
|
updateUsage,
|
|
29
|
+
withLock,
|
|
27
30
|
writePrivateFile
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import {
|
|
30
|
-
clampTokensPerPage,
|
|
31
|
-
withLock
|
|
32
|
-
} from "./chunk-EISHX7Q3.js";
|
|
31
|
+
} from "./chunk-AKOXBXV3.js";
|
|
33
32
|
import "./chunk-GTMLTZRN.js";
|
|
34
33
|
|
|
35
34
|
// src/hook.ts
|
|
@@ -250,11 +249,15 @@ async function payReads(dependencies, deadline) {
|
|
|
250
249
|
}
|
|
251
250
|
if (config.paused) return { paid: [], refill: false, skipped: "paused" };
|
|
252
251
|
if (domains.length === 0) return { paid: [], refill: false, skipped: "empty" };
|
|
252
|
+
const now = dependencies.now?.() ?? /* @__PURE__ */ new Date();
|
|
253
|
+
const stored = await storedIssuer(settings.home, settings.gatewayUrl, now.getTime());
|
|
254
|
+
if (!stored) {
|
|
255
|
+
dependencies.startRefill();
|
|
256
|
+
return { paid: [], refill: true, skipped: "no-issuer" };
|
|
257
|
+
}
|
|
258
|
+
const { issuer } = stored;
|
|
253
259
|
const store = new FileTokenStore(settings.home);
|
|
254
260
|
const boundedFetch = withDeadline(dependencies.fetch ?? fetch, deadline);
|
|
255
|
-
const issuer = await loadIssuer(settings.home, settings.gatewayUrl, {
|
|
256
|
-
fetch: boundedFetch
|
|
257
|
-
});
|
|
258
261
|
const perPage = clampTokensPerPage(config.tokensPerPage);
|
|
259
262
|
const taken = await store.takeWithRemaining(domains.length * perPage, domains.length);
|
|
260
263
|
const { empty, paid, unspent } = await redeemRounds(
|
|
@@ -269,7 +272,6 @@ async function payReads(dependencies, deadline) {
|
|
|
269
272
|
}
|
|
270
273
|
);
|
|
271
274
|
await store.add(unspent);
|
|
272
|
-
const now = dependencies.now?.() ?? /* @__PURE__ */ new Date();
|
|
273
275
|
if (paid.length > 0)
|
|
274
276
|
await updateUsage(
|
|
275
277
|
settings.home,
|
|
@@ -280,7 +282,7 @@ async function payReads(dependencies, deadline) {
|
|
|
280
282
|
},
|
|
281
283
|
now
|
|
282
284
|
);
|
|
283
|
-
const refill = needsRefill(taken.remaining + unspent.length) && refillSize(config, await readUsage(settings.home, now)) > 0;
|
|
285
|
+
const refill = stored.stale || needsRefill(taken.remaining + unspent.length) && refillSize(config, await readUsage(settings.home, now)) > 0;
|
|
284
286
|
if (refill) dependencies.startRefill();
|
|
285
287
|
return {
|
|
286
288
|
paid,
|
|
@@ -7,20 +7,23 @@ import {
|
|
|
7
7
|
isCursorPayload,
|
|
8
8
|
parseHookInput,
|
|
9
9
|
turnEnd
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-23MZSDN6.js";
|
|
11
11
|
import {
|
|
12
|
+
claimRedemptions,
|
|
13
|
+
redemptionWait,
|
|
12
14
|
startDrain,
|
|
13
15
|
startRefill
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TC2WEQ25.js";
|
|
15
17
|
import {
|
|
16
18
|
resolveSettings
|
|
17
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-NDBTADXZ.js";
|
|
18
20
|
import {
|
|
19
21
|
tryLock
|
|
20
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-AKOXBXV3.js";
|
|
21
23
|
import "./chunk-GTMLTZRN.js";
|
|
22
24
|
|
|
23
25
|
// src/hook-process.ts
|
|
26
|
+
import { utimes as utimes2 } from "node:fs/promises";
|
|
24
27
|
import { homedir } from "node:os";
|
|
25
28
|
import { join as join2 } from "node:path";
|
|
26
29
|
|
|
@@ -41,7 +44,9 @@ function queuePaths(home) {
|
|
|
41
44
|
return {
|
|
42
45
|
dir: join(home, "pay-queue"),
|
|
43
46
|
lock: join(home, "pay.lock"),
|
|
44
|
-
start: join(home, "pay.start")
|
|
47
|
+
start: join(home, "pay.start"),
|
|
48
|
+
/** Held by a drainer waiting out a hold on redemptions (spacing.ts); touched each check. */
|
|
49
|
+
wait: join(home, "pay-wait.lock")
|
|
45
50
|
};
|
|
46
51
|
}
|
|
47
52
|
var MAX_QUEUED = 500;
|
|
@@ -82,10 +87,15 @@ async function take(path) {
|
|
|
82
87
|
}
|
|
83
88
|
}
|
|
84
89
|
async function drainerRunning(home, now = Date.now()) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
()
|
|
88
|
-
|
|
90
|
+
const paths = queuePaths(home);
|
|
91
|
+
for (const path of [paths.lock, paths.wait]) {
|
|
92
|
+
const live = await stat(path).then(
|
|
93
|
+
(stats) => now - stats.mtimeMs <= DRAIN_STALE_MS,
|
|
94
|
+
() => false
|
|
95
|
+
);
|
|
96
|
+
if (live) return true;
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
89
99
|
}
|
|
90
100
|
async function claimStart(home) {
|
|
91
101
|
return tryLock(queuePaths(home).start, START_STALE_MS).catch(() => void 0);
|
|
@@ -124,11 +134,16 @@ async function drainHeld(dir, lock, options, deadline) {
|
|
|
124
134
|
return name;
|
|
125
135
|
}
|
|
126
136
|
};
|
|
137
|
+
let held = false;
|
|
127
138
|
const worker = async () => {
|
|
128
139
|
for (; ; ) {
|
|
129
|
-
if (Date.now() >= deadline) return;
|
|
140
|
+
if (Date.now() >= deadline || held) return;
|
|
130
141
|
const name = await next();
|
|
131
142
|
if (!name) return;
|
|
143
|
+
if (options.ready && !await options.ready().catch(() => false)) {
|
|
144
|
+
held = true;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
132
147
|
const event = await take(join(dir, name));
|
|
133
148
|
if (!event) continue;
|
|
134
149
|
await options.pay(event).catch(() => void 0);
|
|
@@ -172,18 +187,24 @@ async function runHookProcess(argument = process.argv[3]) {
|
|
|
172
187
|
if (!claim) return;
|
|
173
188
|
if (await startDrain()) return;
|
|
174
189
|
await claim();
|
|
190
|
+
if (!await claimRedemptions(settings.home, Date.now(), HOOK_TIMEOUT_MS)) return;
|
|
175
191
|
const own = await take(path);
|
|
176
192
|
if (!own) return;
|
|
177
|
-
}
|
|
193
|
+
} else if (!await claimRedemptions(settings.home, Date.now(), HOOK_TIMEOUT_MS)) return;
|
|
178
194
|
await payEvent(
|
|
179
195
|
event,
|
|
180
196
|
settings,
|
|
181
|
-
() => startRefill(),
|
|
197
|
+
() => startRefill({ delayed: true }),
|
|
182
198
|
started + HOOK_TIMEOUT_MS - Date.now()
|
|
183
199
|
);
|
|
184
200
|
}
|
|
201
|
+
var HOLD_WAIT_MAX_MS = 30 * 6e4;
|
|
202
|
+
var HOLD_RECHECK_MS = 3e4;
|
|
185
203
|
async function runPayProcess() {
|
|
186
|
-
|
|
204
|
+
const hardStop = setTimeout(
|
|
205
|
+
() => process.exit(0),
|
|
206
|
+
DRAIN_MAX_MS + PAY_TIMEOUT_MS + 5e3
|
|
207
|
+
).unref();
|
|
187
208
|
const settings = resolveSettings();
|
|
188
209
|
const raw = await readStdin(HOOK_TIMEOUT_MS);
|
|
189
210
|
if (raw.trim()) await enqueue(settings.home, { raw });
|
|
@@ -191,18 +212,43 @@ async function runPayProcess() {
|
|
|
191
212
|
const refill = () => {
|
|
192
213
|
if (Date.now() - refilledAt < REFILL_RETRY_MS) return;
|
|
193
214
|
refilledAt = Date.now();
|
|
194
|
-
startRefill();
|
|
215
|
+
startRefill({ delayed: true });
|
|
195
216
|
};
|
|
196
217
|
await drainQueue(settings.home, {
|
|
197
218
|
deadline: Date.now() + DRAIN_MAX_MS,
|
|
198
|
-
pay: (event) => payEvent(event, settings, refill, PAY_TIMEOUT_MS)
|
|
219
|
+
pay: (event) => payEvent(event, settings, refill, PAY_TIMEOUT_MS),
|
|
220
|
+
ready: () => claimRedemptions(settings.home, Date.now(), PAY_TIMEOUT_MS)
|
|
199
221
|
});
|
|
222
|
+
if (await queuedCount(settings.home) === 0) return;
|
|
223
|
+
if (await redemptionWait(settings.home) > 0) {
|
|
224
|
+
clearTimeout(hardStop);
|
|
225
|
+
setTimeout(() => process.exit(0), HOLD_WAIT_MAX_MS + 5e3).unref();
|
|
226
|
+
if (!await waitForHold(settings.home)) return;
|
|
227
|
+
}
|
|
200
228
|
if (!await drainerRunning(settings.home) && await queuedCount(settings.home) > 0)
|
|
201
229
|
await startDrain();
|
|
202
230
|
}
|
|
231
|
+
async function waitForHold(home) {
|
|
232
|
+
const path = queuePaths(home).wait;
|
|
233
|
+
const release = await tryLock(path, DRAIN_STALE_MS).catch(() => void 0);
|
|
234
|
+
if (!release) return false;
|
|
235
|
+
try {
|
|
236
|
+
const deadline = Date.now() + HOLD_WAIT_MAX_MS;
|
|
237
|
+
for (; ; ) {
|
|
238
|
+
const wait = await redemptionWait(home);
|
|
239
|
+
if (wait <= 0) return true;
|
|
240
|
+
if (Date.now() + wait > deadline) return false;
|
|
241
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(wait, HOLD_RECHECK_MS)));
|
|
242
|
+
const now = /* @__PURE__ */ new Date();
|
|
243
|
+
await utimes2(path, now, now).catch(() => void 0);
|
|
244
|
+
}
|
|
245
|
+
} finally {
|
|
246
|
+
await release();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
203
249
|
async function payEvent(event, settings, refill, timeoutMs) {
|
|
204
250
|
if (timeoutMs <= 0) return;
|
|
205
|
-
const { runHook } = await import("./hook-
|
|
251
|
+
const { runHook } = await import("./hook-IE7INCPX.js");
|
|
206
252
|
await runHook(
|
|
207
253
|
{
|
|
208
254
|
readInput: async () => event.raw,
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
2
|
const require = __patronCreateRequire(import.meta.url)
|
|
3
|
+
import "./chunk-ROVOCDKE.js";
|
|
3
4
|
import {
|
|
5
|
+
accessKeyLimitUnits,
|
|
4
6
|
statePaths
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import {
|
|
7
|
-
accessKeyLimitUnits
|
|
8
|
-
} from "./chunk-EISHX7Q3.js";
|
|
7
|
+
} from "./chunk-AKOXBXV3.js";
|
|
9
8
|
import "./chunk-GTMLTZRN.js";
|
|
10
9
|
|
|
11
10
|
// src/wallet.ts
|
package/package.json
CHANGED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { createRequire as __patronCreateRequire } from 'node:module'
|
|
2
|
-
const require = __patronCreateRequire(import.meta.url)
|
|
3
|
-
|
|
4
|
-
// src/refill-process.ts
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import { createRequire } from "node:module";
|
|
7
|
-
function startRefill(script = process.argv[1]) {
|
|
8
|
-
try {
|
|
9
|
-
if (!script) return;
|
|
10
|
-
const [command, args] = refillCommand(script);
|
|
11
|
-
const child = spawn(command, args, {
|
|
12
|
-
detached: true,
|
|
13
|
-
env: process.env,
|
|
14
|
-
stdio: "ignore"
|
|
15
|
-
});
|
|
16
|
-
child.on("error", () => void 0);
|
|
17
|
-
child.unref();
|
|
18
|
-
} catch {
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function refillCommand(script) {
|
|
22
|
-
try {
|
|
23
|
-
createRequire(script).resolve("mppx");
|
|
24
|
-
return [process.execPath, [...process.execArgv, script, "refill"]];
|
|
25
|
-
} catch {
|
|
26
|
-
return [
|
|
27
|
-
process.platform === "win32" ? "npx.cmd" : "npx",
|
|
28
|
-
["-y", "@tempoxyz/patron", "refill"]
|
|
29
|
-
];
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
function startDrain(script = process.argv[1]) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
34
|
-
try {
|
|
35
|
-
if (!script) return resolve(false);
|
|
36
|
-
const child = spawn(process.execPath, [...process.execArgv, script, "pay"], {
|
|
37
|
-
detached: true,
|
|
38
|
-
env: process.env,
|
|
39
|
-
stdio: "ignore"
|
|
40
|
-
});
|
|
41
|
-
child.on("error", () => resolve(false));
|
|
42
|
-
child.on("spawn", () => {
|
|
43
|
-
child.unref();
|
|
44
|
-
resolve(true);
|
|
45
|
-
});
|
|
46
|
-
} catch {
|
|
47
|
-
resolve(false);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
startRefill,
|
|
54
|
-
startDrain
|
|
55
|
-
};
|