@arp-protocol/cli 0.0.3 → 0.0.5
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/CHANGELOG.md +36 -1
- package/README.md +5 -2
- package/dist/chunks/{backfill-awengrsd.js → backfill-kzgeaffa.js} +3 -1
- package/dist/chunks/check-k4qnc9ee.js +2011 -0
- package/dist/chunks/cli-7c393v47.js +173 -0
- package/dist/chunks/{cli-wev0jgf7.js → cli-g3q6fxm0.js} +929 -983
- package/dist/chunks/{cli-10wacn76.js → cli-jew4syvf.js} +15 -173
- package/dist/chunks/cli-kda5hz4w.js +23 -0
- package/dist/chunks/cli-zehr6kdx.js +719 -0
- package/dist/chunks/{commands-157bms70.js → commands-vvrdahbr.js} +43 -13
- package/dist/chunks/{line-691gbaha.js → line-wra91qkr.js} +54 -5
- package/dist/chunks/{node-m0mx4y5k.js → node-2rw44jrf.js} +2 -1
- package/dist/chunks/{node-init-rcepfyeh.js → node-init-rmrmmg59.js} +2 -1
- package/dist/chunks/{server-59zry2jp.js → server-bcsxfd7q.js} +197 -112
- package/dist/chunks/share-k1dnzsna.js +219 -0
- package/dist/cli.js +69 -19
- package/dist/hook.js +949 -167
- package/package.json +2 -2
- package/dist/chunks/share-vtbkzs5f.js +0 -104
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
statSync,
|
|
14
14
|
writeFileSync
|
|
15
15
|
} from "node:fs";
|
|
16
|
-
import { dirname, join as join2 } from "node:path";
|
|
16
|
+
import { dirname as dirname2, join as join2 } from "node:path";
|
|
17
17
|
|
|
18
18
|
// ../../packages/protocol/src/share-offer.ts
|
|
19
19
|
var SHARE_OFFER = {
|
|
@@ -28,9 +28,15 @@ function shareOfferLines() {
|
|
|
28
28
|
return [SHARE_OFFER.sends, SHARE_OFFER.signer, SHARE_OFFER.never, SHARE_OFFER.service, SHARE_OFFER.later];
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// ../../packages/protocol/src/sharing-state.ts
|
|
32
|
+
function sharingFileText(on, how, at) {
|
|
33
|
+
return `${JSON.stringify({ failures: on, at: at.toISOString(), how })}
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
// src/install/targets.ts
|
|
32
38
|
import { existsSync, readFileSync } from "node:fs";
|
|
33
|
-
import { join } from "node:path";
|
|
39
|
+
import { dirname, join } from "node:path";
|
|
34
40
|
|
|
35
41
|
// src/install/edits.ts
|
|
36
42
|
function isRecord(value) {
|
|
@@ -64,10 +70,12 @@ function withMcpServer(config, name, entry) {
|
|
|
64
70
|
var CLAUDE_HOOKS = {
|
|
65
71
|
shape: "nested",
|
|
66
72
|
events: [
|
|
67
|
-
{ name: "PostToolUse", matcher: "
|
|
73
|
+
{ name: "PostToolUse", matcher: "^(?!Skill$)" },
|
|
74
|
+
{ name: "PostToolUse", matcher: "Skill", sync: true, timeout: 5 },
|
|
68
75
|
{ name: "PostToolUseFailure", matcher: "*", sync: true },
|
|
69
76
|
{ name: "PreToolUse", matcher: "Bash", sync: true, timeout: 15, if: "Bash(*skills*)" },
|
|
70
|
-
{ name: "Stop", sync: true, timeout: 10 }
|
|
77
|
+
{ name: "Stop", sync: true, timeout: 10 },
|
|
78
|
+
{ name: "SessionEnd", sync: true, timeout: 5 }
|
|
71
79
|
],
|
|
72
80
|
entry: (command, event) => ({
|
|
73
81
|
type: "command",
|
|
@@ -243,10 +251,10 @@ function read(path) {
|
|
|
243
251
|
return null;
|
|
244
252
|
}
|
|
245
253
|
}
|
|
246
|
-
function npxLaunch(pkg) {
|
|
254
|
+
function npxLaunch(pkg, command = "mcp") {
|
|
247
255
|
return {
|
|
248
256
|
command: "sh",
|
|
249
|
-
args: ["-c", `export ARP_PROJECT_DIR="$PWD"; cd / && exec npx --prefix / -y --fetch-retries=0 --fetch-timeout=5000 ${pkg}
|
|
257
|
+
args: ["-c", `export ARP_PROJECT_DIR="$PWD"; cd / && exec npx --prefix / -y --fetch-retries=0 --fetch-timeout=5000 ${pkg} ${command}`]
|
|
250
258
|
};
|
|
251
259
|
}
|
|
252
260
|
var SERVER_ENV = { ARP_TARGET: "testnet" };
|
|
@@ -265,7 +273,8 @@ function commandsFor(env, cliPath, capture = false, sponsored = false, force = f
|
|
|
265
273
|
env: sponsored ? SPONSORED_ENV : SERVER_ENV
|
|
266
274
|
};
|
|
267
275
|
const hook = `"${env.node}" "${hookFile}"${capture ? " --capture" : ""}`;
|
|
268
|
-
|
|
276
|
+
const send = fromNpx ? npxLaunch(`@arp-protocol/cli@${env.version}`, "share send --auto") : { command: env.node, args: [cliPath, "share", "send", "--auto"] };
|
|
277
|
+
return { mcp, hook, hookFile, sendFile: join(dirname(hookFile), "send.json"), send, cliPath, capture, force };
|
|
269
278
|
}
|
|
270
279
|
function diffLines(before, after) {
|
|
271
280
|
const lines = (value, sign) => value === undefined || typeof value === "object" && value !== null && Object.keys(value).length === 0 ? [] : JSON.stringify(value, null, 2).split(`
|
|
@@ -356,8 +365,17 @@ function claudeMcpSteps(env, commands, project, remove, allowCli) {
|
|
|
356
365
|
jsonStep(files.mcp, (config) => withMcpServer(config, SERVER_NAME, remove ? null : mcpEntry(commands.mcp, false)), remove ? "mcpServers.arp removed" : `mcpServers.arp → ${commands.mcp.command} ${commands.mcp.args.join(" ")}`, (config) => serversOf(config)[SERVER_NAME])
|
|
357
366
|
];
|
|
358
367
|
}
|
|
368
|
+
function waitedLabel(event) {
|
|
369
|
+
if (event.sync !== true)
|
|
370
|
+
return "";
|
|
371
|
+
if (event.if !== undefined)
|
|
372
|
+
return " (waited on, Bash skills installs only)";
|
|
373
|
+
if (event.matcher !== undefined && event.matcher !== "*")
|
|
374
|
+
return ` (waited on, ${event.matcher} calls only)`;
|
|
375
|
+
return " (waited on)";
|
|
376
|
+
}
|
|
359
377
|
function claudeHookStep(env, commands, project, remove) {
|
|
360
|
-
return jsonStep(claudeFiles(env, project).settings, (settings) => withHooks(settings, CLAUDE_HOOKS, remove ? null : commands.hook, commands.hookFile), remove ? `hooks: arp removed from ${eventNames(CLAUDE_HOOKS).join(", ")}` : `hooks: arp on ${CLAUDE_HOOKS.events.map((event) => `${event.name}${event
|
|
378
|
+
return jsonStep(claudeFiles(env, project).settings, (settings) => withHooks(settings, CLAUDE_HOOKS, remove ? null : commands.hook, commands.hookFile), remove ? `hooks: arp removed from ${eventNames(CLAUDE_HOOKS).join(", ")}` : `hooks: arp on ${CLAUDE_HOOKS.events.map((event) => `${event.name}${waitedLabel(event)}`).join(", ")}`, (settings) => hooksOf(settings, CLAUDE_HOOKS, commands.hookFile));
|
|
361
379
|
}
|
|
362
380
|
var CLAUDE_HOOKS_SEEN_FROM = [2, 1, 316];
|
|
363
381
|
function claudeVersionCheck(env) {
|
|
@@ -659,7 +677,7 @@ function apply(env, step) {
|
|
|
659
677
|
rmSync(step.path, { force: true });
|
|
660
678
|
return null;
|
|
661
679
|
}
|
|
662
|
-
mkdirSync(
|
|
680
|
+
mkdirSync(dirname2(step.path), { recursive: true });
|
|
663
681
|
const mode = step.before === null ? undefined : statSync(step.path).mode & 511;
|
|
664
682
|
const temp = `${step.path}.arp-tmp`;
|
|
665
683
|
writeFileSync(temp, step.after, mode === undefined ? undefined : { mode });
|
|
@@ -690,6 +708,19 @@ function hookFileStep(env, commands, remove) {
|
|
|
690
708
|
diff: []
|
|
691
709
|
};
|
|
692
710
|
}
|
|
711
|
+
function sendFileStep(commands, remove) {
|
|
712
|
+
const before = read2(commands.sendFile);
|
|
713
|
+
const after = remove ? null : `${JSON.stringify(commands.send, null, 2)}
|
|
714
|
+
`;
|
|
715
|
+
return {
|
|
716
|
+
kind: "file",
|
|
717
|
+
path: commands.sendFile,
|
|
718
|
+
before,
|
|
719
|
+
after,
|
|
720
|
+
summary: remove ? "removed" : "how the hook starts `arp share send --auto` when sharing is on",
|
|
721
|
+
diff: []
|
|
722
|
+
};
|
|
723
|
+
}
|
|
693
724
|
async function consent(env, flags, question) {
|
|
694
725
|
if (flags.yes)
|
|
695
726
|
return true;
|
|
@@ -765,7 +796,7 @@ async function init(env, flags, cliPath) {
|
|
|
765
796
|
steps: runtime.install(env, commands, flags.project)
|
|
766
797
|
}));
|
|
767
798
|
if (installsHook(runtimes, flags.capture)) {
|
|
768
|
-
plan.push({ runtime: "hook", steps: [hookFileStep(env, commands, false)] });
|
|
799
|
+
plan.push({ runtime: "hook", steps: [hookFileStep(env, commands, false), sendFileStep(commands, false)] });
|
|
769
800
|
}
|
|
770
801
|
const code = await change(env, flags, plan, "Install");
|
|
771
802
|
if ((code === EXIT.ok || code === EXIT.partly) && !flags.dryRun)
|
|
@@ -777,8 +808,7 @@ async function offerSharing(env, flags) {
|
|
|
777
808
|
const file = join2(home, "sharing.json");
|
|
778
809
|
const save = (on) => {
|
|
779
810
|
mkdirSync(home, { recursive: true });
|
|
780
|
-
writeFileSync(file,
|
|
781
|
-
`);
|
|
811
|
+
writeFileSync(file, sharingFileText(on, "init", env.now()));
|
|
782
812
|
};
|
|
783
813
|
if (flags.share !== null) {
|
|
784
814
|
save(flags.share);
|
|
@@ -803,7 +833,7 @@ async function uninstall(env, flags, cliPath) {
|
|
|
803
833
|
runtime: runtime.name,
|
|
804
834
|
steps: runtime.remove(env, commands, flags.project)
|
|
805
835
|
}));
|
|
806
|
-
plan.push({ runtime: "hook", steps: [hookFileStep(env, commands, true)] });
|
|
836
|
+
plan.push({ runtime: "hook", steps: [hookFileStep(env, commands, true), sendFileStep(commands, true)] });
|
|
807
837
|
const code = await change(env, flags, plan, "Remove");
|
|
808
838
|
const captures = join2(env.home, ".arp", "captures");
|
|
809
839
|
if (existsSync2(captures))
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
loopConfig,
|
|
8
8
|
sponsorApproval,
|
|
9
9
|
writeLine
|
|
10
|
-
} from "./cli-
|
|
10
|
+
} from "./cli-jew4syvf.js";
|
|
11
|
+
import"./cli-7c393v47.js";
|
|
11
12
|
import"./cli-00qp1sj2.js";
|
|
12
13
|
import"./cli-n4qagybd.js";
|
|
13
14
|
import {
|
|
@@ -22,11 +23,13 @@ import {
|
|
|
22
23
|
needShapeProblem,
|
|
23
24
|
normaliseCategoryLabel,
|
|
24
25
|
readDomainTree,
|
|
26
|
+
redactEndpointUrl,
|
|
25
27
|
resolveDomain,
|
|
26
28
|
transfersIn,
|
|
27
29
|
x402NetworksFrom,
|
|
28
30
|
x402Reading
|
|
29
|
-
} from "./cli-
|
|
31
|
+
} from "./cli-g3q6fxm0.js";
|
|
32
|
+
import"./cli-zehr6kdx.js";
|
|
30
33
|
import"./cli-0gsbnq5w.js";
|
|
31
34
|
import"./cli-fbwpcfvp.js";
|
|
32
35
|
import"./cli-mhzh9z8k.js";
|
|
@@ -58,8 +61,22 @@ function lineFromArgs(args, env = process.env) {
|
|
|
58
61
|
}
|
|
59
62
|
if (args.paymentTx !== undefined && !/^0x[0-9a-fA-F]{64}$/.test(args.paymentTx))
|
|
60
63
|
return new Error("--payment-tx is a 32-byte transaction hash");
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
const terms = termsFromArgs(args);
|
|
65
|
+
if (terms instanceof Error)
|
|
66
|
+
return terms;
|
|
67
|
+
if (args.reason === "no-delivery" && args.paymentTx === undefined) {
|
|
68
|
+
return new Error("--reason no-delivery means paid, nothing received: it takes --payment-tx and --network");
|
|
69
|
+
}
|
|
70
|
+
let toolUrl = args.toolUrl;
|
|
71
|
+
if (args.paymentTx !== undefined) {
|
|
72
|
+
if (!isExactEndpointUrl(args.toolUrl)) {
|
|
73
|
+
return new Error("with --payment-tx, --tool is the exact URL you paid, scheme included, as you called it");
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
toolUrl = redactEndpointUrl(args.toolUrl);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
79
|
+
}
|
|
63
80
|
}
|
|
64
81
|
if (args.parent !== undefined && args.domain === undefined)
|
|
65
82
|
return new Error("--parent and --why add a --domain");
|
|
@@ -85,15 +102,42 @@ function lineFromArgs(args, env = process.env) {
|
|
|
85
102
|
return new Error("--needs and --with name a skill's word; a paid endpoint has no SKILL.md");
|
|
86
103
|
}
|
|
87
104
|
return {
|
|
88
|
-
toolUrl
|
|
105
|
+
toolUrl,
|
|
89
106
|
outcome: args.outcome,
|
|
90
107
|
...args.domain === undefined ? {} : { domain: args.domain },
|
|
91
108
|
...args.reason === undefined ? {} : { reason: args.reason },
|
|
92
109
|
...args.parent === undefined || args.why === undefined ? {} : { newDomain: { parent: args.parent, why: args.why.trim() } },
|
|
93
110
|
...args.paymentTx === undefined || args.network === undefined ? {} : { payment: { network: args.network, txHash: args.paymentTx.toLowerCase() } },
|
|
111
|
+
...terms === null ? {} : { terms },
|
|
94
112
|
...need === undefined ? {} : { need }
|
|
95
113
|
};
|
|
96
114
|
}
|
|
115
|
+
var TERMS_FLAGS = ["--pay-to", "--asset", "--price", "--terms-at"];
|
|
116
|
+
function termsFromArgs(args) {
|
|
117
|
+
const given = [args.payTo, args.asset, args.price, args.termsAt];
|
|
118
|
+
if (args.paymentTx === undefined) {
|
|
119
|
+
return given.every((value) => value === undefined) ? null : new Error(`${TERMS_FLAGS.join(", ")} follow --payment-tx`);
|
|
120
|
+
}
|
|
121
|
+
if (given.some((value) => value === undefined)) {
|
|
122
|
+
return new Error(`with --payment-tx, name the terms the 402 gave and you paid against: ${TERMS_FLAGS.join(" ")}`);
|
|
123
|
+
}
|
|
124
|
+
const { payTo, asset, price, termsAt } = args;
|
|
125
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(payTo))
|
|
126
|
+
return new Error("--pay-to is the 402's payTo address");
|
|
127
|
+
if (!/^0x[0-9a-fA-F]{40}$/.test(asset))
|
|
128
|
+
return new Error("--asset is the 402's asset address");
|
|
129
|
+
if (!/^[1-9][0-9]{0,77}$/.test(price))
|
|
130
|
+
return new Error("--price is the 402's amount, a positive integer in the asset's smallest unit");
|
|
131
|
+
const receivedAt = /^[0-9]+$/.test(termsAt) ? Number(termsAt) : Math.floor(Date.parse(termsAt) / 1000);
|
|
132
|
+
if (!Number.isSafeInteger(receivedAt) || receivedAt <= 0)
|
|
133
|
+
return new Error("--terms-at is when the 402 was received: unix seconds or ISO 8601");
|
|
134
|
+
if (receivedAt > Math.floor(Date.now() / 1000) + 300)
|
|
135
|
+
return new Error("--terms-at is in the future");
|
|
136
|
+
return { payTo, asset, price, receivedAt };
|
|
137
|
+
}
|
|
138
|
+
function matchesTerms(payment, terms) {
|
|
139
|
+
return payment.transfers.some((transfer) => transfer.payTo.toLowerCase() === terms.payTo.toLowerCase() && transfer.asset.toLowerCase() === terms.asset.toLowerCase() && BigInt(transfer.amount) >= BigInt(terms.price));
|
|
140
|
+
}
|
|
97
141
|
async function readLinePayment(input, reading) {
|
|
98
142
|
if (input.payment === undefined)
|
|
99
143
|
return null;
|
|
@@ -125,6 +169,11 @@ async function writeLineChecked(steps, input) {
|
|
|
125
169
|
if (steps.payments === undefined)
|
|
126
170
|
throw new Error("this build reads no payment network");
|
|
127
171
|
payment = await readLinePayment(input, steps.payments);
|
|
172
|
+
if (input.terms === undefined)
|
|
173
|
+
throw new Error("a line with a payment names the terms it paid against");
|
|
174
|
+
if (payment !== null && !matchesTerms(payment, input.terms)) {
|
|
175
|
+
throw new Error(`no transfer in ${input.payment.txHash} pays ${input.terms.payTo} at least ${input.terms.price} of ${input.terms.asset}: check --pay-to, --asset and --price`);
|
|
176
|
+
}
|
|
128
177
|
}
|
|
129
178
|
if (input.domain !== undefined) {
|
|
130
179
|
const domain = normaliseCategoryLabel(input.domain);
|