@tempoxyz/patron 0.0.26 → 0.0.28

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.
@@ -3,7 +3,7 @@ const require = __patronCreateRequire(import.meta.url)
3
3
  import {
4
4
  isExcludedByDefault,
5
5
  normalizePayee
6
- } from "./chunk-WZRGCKEK.js";
6
+ } from "./chunk-EISHX7Q3.js";
7
7
 
8
8
  // src/hook-input.ts
9
9
  var HOOK_TIMEOUT_MS = 2e3;
@@ -0,0 +1,37 @@
1
+ import { createRequire as __patronCreateRequire } from 'node:module'
2
+ const require = __patronCreateRequire(import.meta.url)
3
+
4
+ // src/settings.ts
5
+ import { homedir } from "node:os";
6
+ import { join } from "node:path";
7
+ var DEFAULT_GATEWAY_URL = "https://patron-gateway.tempo-dev.workers.dev";
8
+ var DEFAULT_RELAY_URL = "https://patron-relay.tempo-dev.workers.dev";
9
+ function resolveSettings(env = process.env) {
10
+ const key = env.PATRON_PRIVATE_KEY?.trim();
11
+ const privateKey = key && /^0x[0-9a-fA-F]{64}$/.test(key) ? key : void 0;
12
+ return {
13
+ gatewayUrl: env.PATRON_GATEWAY_URL || DEFAULT_GATEWAY_URL,
14
+ home: env.PATRON_HOME || join(homedir(), ".patron"),
15
+ network: env.PATRON_NETWORK === "testnet" ? "testnet" : "mainnet",
16
+ overridden: {
17
+ gatewayUrl: Boolean(env.PATRON_GATEWAY_URL),
18
+ network: Boolean(env.PATRON_NETWORK),
19
+ relayUrl: Boolean(env.PATRON_RELAY_URL)
20
+ },
21
+ relayUrl: env.PATRON_RELAY_URL || DEFAULT_RELAY_URL,
22
+ ...privateKey ? { privateKey } : {}
23
+ };
24
+ }
25
+ function settingsFor(settings, saved) {
26
+ return {
27
+ ...settings,
28
+ gatewayUrl: settings.overridden.gatewayUrl || !saved.gatewayUrl ? settings.gatewayUrl : saved.gatewayUrl,
29
+ network: settings.overridden.network ? settings.network : saved.network,
30
+ relayUrl: settings.overridden.relayUrl || !saved.relayUrl ? settings.relayUrl : saved.relayUrl
31
+ };
32
+ }
33
+
34
+ export {
35
+ resolveSettings,
36
+ settingsFor
37
+ };
@@ -8,7 +8,7 @@ import {
8
8
  parseHookInput,
9
9
  payableDomain,
10
10
  turnEnd
11
- } from "./chunk-HVTTV2A5.js";
11
+ } from "./chunk-HQ2ZLUTT.js";
12
12
  import {
13
13
  FileTokenStore,
14
14
  codexHome,
@@ -16,20 +16,20 @@ import {
16
16
  needsRefill,
17
17
  redeem,
18
18
  refillSize
19
- } from "./chunk-NQ6RRPM6.js";
19
+ } from "./chunk-EKFENOVR.js";
20
20
  import {
21
- clampTokensPerPage,
22
21
  settingsFor
23
- } from "./chunk-WZRGCKEK.js";
22
+ } from "./chunk-OQXACACU.js";
24
23
  import {
25
24
  readConfig,
26
25
  readUsage,
27
26
  updateUsage,
28
27
  writePrivateFile
29
- } from "./chunk-SGQ525FB.js";
28
+ } from "./chunk-EV7OA6GK.js";
30
29
  import {
30
+ clampTokensPerPage,
31
31
  withLock
32
- } from "./chunk-O64T22EK.js";
32
+ } from "./chunk-EISHX7Q3.js";
33
33
  import "./chunk-GTMLTZRN.js";
34
34
 
35
35
  // src/hook.ts
@@ -7,17 +7,17 @@ import {
7
7
  isCursorPayload,
8
8
  parseHookInput,
9
9
  turnEnd
10
- } from "./chunk-HVTTV2A5.js";
10
+ } from "./chunk-HQ2ZLUTT.js";
11
11
  import {
12
12
  startDrain,
13
13
  startRefill
14
14
  } from "./chunk-TV5VLFTD.js";
15
15
  import {
16
16
  resolveSettings
17
- } from "./chunk-WZRGCKEK.js";
17
+ } from "./chunk-OQXACACU.js";
18
18
  import {
19
19
  tryLock
20
- } from "./chunk-O64T22EK.js";
20
+ } from "./chunk-EISHX7Q3.js";
21
21
  import "./chunk-GTMLTZRN.js";
22
22
 
23
23
  // src/hook-process.ts
@@ -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-OZRD6I6F.js");
205
+ const { runHook } = await import("./hook-N2SVXVUR.js");
206
206
  await runHook(
207
207
  {
208
208
  readInput: async () => event.raw,
@@ -86,7 +86,7 @@ async function createLinkSpt(options) {
86
86
  "--currency",
87
87
  "usd",
88
88
  "--context",
89
- `Patron: buying $${usd} of seals (1,000 per dollar) that pay the websites your AI agents and browser read, $0.001 per page, privately. Started by npx @tempoxyz/patron on this computer.`,
89
+ `Patron: adding $${usd} to the balance that pays the websites your AI agents and browser read, $0.001 per page, privately. Started by npx @tempoxyz/patron on this computer.`,
90
90
  "--idempotency-key",
91
91
  options.idempotencyKey,
92
92
  "--request-approval",
@@ -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-SGQ525FB.js";
6
- import "./chunk-O64T22EK.js";
5
+ } from "./chunk-EV7OA6GK.js";
6
+ import {
7
+ accessKeyLimitUnits
8
+ } from "./chunk-EISHX7Q3.js";
7
9
  import "./chunk-GTMLTZRN.js";
8
10
 
9
11
  // src/wallet.ts
@@ -121,7 +123,7 @@ async function openWallet(settings, wallet, issuer, maxUnits, output = process.s
121
123
  }
122
124
  var UNITS_PER_CENT = 10000n;
123
125
  async function openLinkWallet(config, maxUnits, output = process.stderr) {
124
- const { linkCli, linkFetch } = await import("./link-OU7W7IT6.js");
126
+ const { linkCli, linkFetch } = await import("./link-VK7VCE2R.js");
125
127
  return {
126
128
  address: "0x0000000000000000000000000000000000000000",
127
129
  fetch: linkFetch({
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "@tempoxyz/patron",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "description": "Pay the websites your AI agents read, privately",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
- };
@@ -1,162 +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 };
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
- };
130
- }
131
- function isUsageRecord(value) {
132
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
133
- const usage = value;
134
- return typeof usage.month === "string" && typeof usage.boughtTokens === "number" && Number.isFinite(usage.boughtTokens) && usage.boughtTokens >= 0;
135
- }
136
- function unreadableUsage(path) {
137
- return new Error(
138
- `${path} is unreadable, so Patron stops buying seals. Delete it to restart this month's budget count.`
139
- );
140
- }
141
- async function updateUsage(home, update, now = /* @__PURE__ */ new Date()) {
142
- await ensureHome(home);
143
- return withLock(statePaths(home).usageLock, async () => {
144
- const usage = await readUsage(home, now);
145
- update(usage);
146
- await writePrivateFile(statePaths(home).usage, `${JSON.stringify(usage)}
147
- `);
148
- return usage;
149
- });
150
- }
151
-
152
- export {
153
- AGENT_IDS,
154
- statePaths,
155
- ensureHome,
156
- readJson,
157
- writePrivateFile,
158
- readConfig,
159
- writeConfig,
160
- readUsage,
161
- updateUsage
162
- };