arc-builder-kit 0.2.0__py3-none-any.whl
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.
- arc_builder_kit/__init__.py +4 -0
- arc_builder_kit/__main__.py +6 -0
- arc_builder_kit/_paths.py +47 -0
- arc_builder_kit/cli.py +277 -0
- arc_builder_kit/config/arc_testnet.facts.json +31 -0
- arc_builder_kit/doctor.py +936 -0
- arc_builder_kit/examples/agent-commerce-components/components.js +200 -0
- arc_builder_kit/examples/agent-commerce-components/index.html +120 -0
- arc_builder_kit/examples/agent-commerce-flows/flows.js +271 -0
- arc_builder_kit/examples/agent-commerce-flows/index.html +114 -0
- arc_builder_kit/examples/agent-commerce-live/commerce-live.js +190 -0
- arc_builder_kit/examples/agent-commerce-live/index.html +105 -0
- arc_builder_kit/examples/agent-commerce-review-packet/index.html +96 -0
- arc_builder_kit/examples/agent-commerce-review-packet/packet.js +125 -0
- arc_builder_kit/examples/agent-identity-profile-preview/identity.js +126 -0
- arc_builder_kit/examples/agent-identity-profile-preview/index.html +104 -0
- arc_builder_kit/examples/arc-agent-treasury-lab/index.html +152 -0
- arc_builder_kit/examples/arc-agent-treasury-lab/treasury.js +532 -0
- arc_builder_kit/examples/arc-testnet-operator-evidence/evidence.example.json +47 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/index.html +233 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/live-infrastructure-policy.example.json +59 -0
- arc_builder_kit/examples/arc-testnet-wallet-send-gate/wallet-send-gate.js +472 -0
- arc_builder_kit/examples/circle-wallet-integration/index.html +155 -0
- arc_builder_kit/examples/circle-wallet-integration/wallet-lab.js +91 -0
- arc_builder_kit/examples/job-escrow-simulator/index.html +121 -0
- arc_builder_kit/examples/job-escrow-simulator/simulator.js +162 -0
- arc_builder_kit/examples/payment-intent-demo/index.html +132 -0
- arc_builder_kit/examples/payment-intent-playground/index.html +301 -0
- arc_builder_kit/examples/payment-intent-playground/playground.js +835 -0
- arc_builder_kit/examples/payment-intent-receipt-matcher/index.html +157 -0
- arc_builder_kit/examples/payment-intent-receipt-matcher/matcher.js +877 -0
- arc_builder_kit/examples/receipt-verifier-playground/index.html +120 -0
- arc_builder_kit/examples/receipt-verifier-playground/verifier.js +226 -0
- arc_builder_kit/examples/receipt-viewer/index.html +138 -0
- arc_builder_kit/examples/receipt-viewer/receipt-viewer.js +472 -0
- arc_builder_kit/examples/transaction-status-playground/index.html +135 -0
- arc_builder_kit/examples/transaction-status-playground/status.js +518 -0
- arc_builder_kit/examples/x402-local-challenge-server/.env.example +25 -0
- arc_builder_kit/examples/x402-local-challenge-server/README.md +111 -0
- arc_builder_kit/examples/x402-local-challenge-server/server.py +711 -0
- arc_builder_kit/mcp_server.py +463 -0
- arc_builder_kit/release_packet.py +469 -0
- arc_builder_kit/templates/README.md +25 -0
- arc_builder_kit/templates/job-escrow-starter/README.md +25 -0
- arc_builder_kit/templates/job-escrow-starter/index.html +41 -0
- arc_builder_kit/templates/job-escrow-starter/index.js +14 -0
- arc_builder_kit/templates/payment-intent-starter/README.md +25 -0
- arc_builder_kit/templates/payment-intent-starter/index.html +42 -0
- arc_builder_kit/templates/payment-intent-starter/index.js +7 -0
- arc_builder_kit/templates/x402-agent-starter/README.md +29 -0
- arc_builder_kit/templates/x402-agent-starter/server.py +201 -0
- arc_builder_kit/validate_repo.py +2212 -0
- arc_builder_kit-0.2.0.dist-info/METADATA +543 -0
- arc_builder_kit-0.2.0.dist-info/RECORD +58 -0
- arc_builder_kit-0.2.0.dist-info/WHEEL +5 -0
- arc_builder_kit-0.2.0.dist-info/entry_points.txt +3 -0
- arc_builder_kit-0.2.0.dist-info/licenses/LICENSE +21 -0
- arc_builder_kit-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Path resolution that works both in editable installs and in wheels."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
_PACKAGE_DIR = Path(__file__).resolve().parent
|
|
8
|
+
|
|
9
|
+
# A source checkout has the canonical scripts beside this package. An installed
|
|
10
|
+
# wheel has its reviewed resources inside the package directory instead.
|
|
11
|
+
_SOURCE_ROOT = _PACKAGE_DIR.parent
|
|
12
|
+
IS_SOURCE_CHECKOUT = (
|
|
13
|
+
(_SOURCE_ROOT / "scripts" / "validate_repo.py").is_file()
|
|
14
|
+
and (_SOURCE_ROOT / "config" / "arc_testnet.facts.json").is_file()
|
|
15
|
+
)
|
|
16
|
+
REPO_ROOT = _SOURCE_ROOT if IS_SOURCE_CHECKOUT else _PACKAGE_DIR
|
|
17
|
+
DEFAULT_OUTPUT_ROOT = REPO_ROOT if IS_SOURCE_CHECKOUT else Path.cwd().resolve()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _resolve_resource_dir(name: str) -> Path:
|
|
21
|
+
"""Find a resource directory in installed wheel or editable/development layout.
|
|
22
|
+
|
|
23
|
+
In a built wheel, resources live next to this module under arc_builder_kit/.
|
|
24
|
+
In a clone/editable install, resources live in the repository root, one level
|
|
25
|
+
above this package.
|
|
26
|
+
"""
|
|
27
|
+
installed = _PACKAGE_DIR / name
|
|
28
|
+
if installed.exists() and installed.is_dir():
|
|
29
|
+
return installed
|
|
30
|
+
dev = _SOURCE_ROOT / name
|
|
31
|
+
if dev.exists() and dev.is_dir():
|
|
32
|
+
return dev
|
|
33
|
+
raise FileNotFoundError(
|
|
34
|
+
f"Could not locate {name!r} directory. "
|
|
35
|
+
f"Tried {installed} and {dev}."
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
PACKAGE_DIR = _PACKAGE_DIR
|
|
40
|
+
TEMPLATES_DIR = _resolve_resource_dir("templates")
|
|
41
|
+
CONFIG_DIR = _resolve_resource_dir("config")
|
|
42
|
+
EXAMPLES_DIR = _resolve_resource_dir("examples")
|
|
43
|
+
|
|
44
|
+
# Other scripts live in the repo scripts/ directory. In a wheel they are not
|
|
45
|
+
# shipped as standalone subprocess targets; the CLI/MCP tools import their
|
|
46
|
+
# functions directly.
|
|
47
|
+
SCRIPTS_DIR = REPO_ROOT / "scripts"
|
arc_builder_kit/cli.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Arc Builder CLI: unified command-line tooling for the Arc MCP Builder Assistant.
|
|
3
|
+
|
|
4
|
+
This is a dependency-free orchestrator over existing builder-kit scripts and
|
|
5
|
+
resources. It stays local-only by default and never connects a wallet, signs, or
|
|
6
|
+
broadcasts transactions. Network calls happen only through explicit opt-in flags
|
|
7
|
+
passed to underlying scripts.
|
|
8
|
+
|
|
9
|
+
Subcommands:
|
|
10
|
+
doctor Run Arc Builder Doctor and print a structured verdict.
|
|
11
|
+
validate Run repository validation.
|
|
12
|
+
templates List available project starter templates.
|
|
13
|
+
scaffold Copy a starter template into a new project directory.
|
|
14
|
+
facts Print the reviewed Arc Testnet facts object.
|
|
15
|
+
manifest Print the local x402 paid-agent manifest.
|
|
16
|
+
release-packet Generate a local maintainer release packet.
|
|
17
|
+
mcp Start the local Arc Builder MCP server (stdio).
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import json
|
|
24
|
+
import shutil
|
|
25
|
+
import subprocess
|
|
26
|
+
import sys
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any, Sequence
|
|
29
|
+
|
|
30
|
+
from arc_builder_kit import __version__
|
|
31
|
+
from arc_builder_kit._paths import (
|
|
32
|
+
CONFIG_DIR,
|
|
33
|
+
DEFAULT_OUTPUT_ROOT,
|
|
34
|
+
EXAMPLES_DIR,
|
|
35
|
+
REPO_ROOT,
|
|
36
|
+
TEMPLATES_DIR,
|
|
37
|
+
)
|
|
38
|
+
from arc_builder_kit.doctor import main as doctor_main
|
|
39
|
+
from arc_builder_kit.mcp_server import main as mcp_main
|
|
40
|
+
from arc_builder_kit.release_packet import main as release_packet_main
|
|
41
|
+
from arc_builder_kit.validate_repo import main as validate_main
|
|
42
|
+
|
|
43
|
+
X402_SERVER = EXAMPLES_DIR / "x402-local-challenge-server" / "server.py"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CliError(Exception):
|
|
47
|
+
"""User-facing error that should exit with a clean message."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, message: str, exit_code: int = 1) -> None:
|
|
50
|
+
super().__init__(message)
|
|
51
|
+
self.message = message
|
|
52
|
+
self.exit_code = exit_code
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _run_script(
|
|
56
|
+
script: Path,
|
|
57
|
+
args: Sequence[str] = (),
|
|
58
|
+
*,
|
|
59
|
+
capture: bool = True,
|
|
60
|
+
timeout: float | None = 300,
|
|
61
|
+
) -> subprocess.CompletedProcess[str]:
|
|
62
|
+
"""Run a Python script as an argument list.
|
|
63
|
+
|
|
64
|
+
Kept for the x402 manifest example, which is a standalone server file that
|
|
65
|
+
remains easier to invoke as a subprocess than to import.
|
|
66
|
+
"""
|
|
67
|
+
if not script.exists():
|
|
68
|
+
raise CliError(f"script not found: {script}")
|
|
69
|
+
cmd = [sys.executable, str(script), *args]
|
|
70
|
+
return subprocess.run(
|
|
71
|
+
cmd,
|
|
72
|
+
capture_output=capture,
|
|
73
|
+
text=True,
|
|
74
|
+
timeout=timeout,
|
|
75
|
+
check=False,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _load_json(path: Path) -> Any:
|
|
80
|
+
if not path.exists():
|
|
81
|
+
raise CliError(f"file not found: {path}")
|
|
82
|
+
try:
|
|
83
|
+
with path.open("r", encoding="utf-8") as fh:
|
|
84
|
+
return json.load(fh)
|
|
85
|
+
except json.JSONDecodeError as exc:
|
|
86
|
+
raise CliError(f"invalid JSON in {path}: {exc}") from exc
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _list_templates() -> list[str]:
|
|
90
|
+
if not TEMPLATES_DIR.exists():
|
|
91
|
+
return []
|
|
92
|
+
return sorted(
|
|
93
|
+
d.name for d in TEMPLATES_DIR.iterdir() if d.is_dir() and (d / "README.md").exists()
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def cmd_doctor(args: argparse.Namespace) -> int:
|
|
98
|
+
flags = ["--json"]
|
|
99
|
+
if args.full:
|
|
100
|
+
flags.append("--full")
|
|
101
|
+
if args.include_arc_rpc:
|
|
102
|
+
flags.append("--include-arc-rpc")
|
|
103
|
+
if args.include_public_site:
|
|
104
|
+
flags.append("--include-public-site")
|
|
105
|
+
return doctor_main(flags)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def cmd_validate(args: argparse.Namespace) -> int:
|
|
109
|
+
validate_main()
|
|
110
|
+
return 0
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def cmd_templates(args: argparse.Namespace) -> int:
|
|
114
|
+
names = _list_templates()
|
|
115
|
+
output: dict[str, Any] = {
|
|
116
|
+
"templates": names,
|
|
117
|
+
"templates_dir": str(TEMPLATES_DIR.relative_to(REPO_ROOT) if TEMPLATES_DIR.is_relative_to(REPO_ROOT) else TEMPLATES_DIR),
|
|
118
|
+
"count": len(names),
|
|
119
|
+
}
|
|
120
|
+
for name in names:
|
|
121
|
+
readme = TEMPLATES_DIR / name / "README.md"
|
|
122
|
+
if readme.exists():
|
|
123
|
+
first = readme.read_text(encoding="utf-8").splitlines()[0].lstrip("# ").strip()
|
|
124
|
+
output.setdefault("titles", {})[name] = first
|
|
125
|
+
if args.json:
|
|
126
|
+
print(json.dumps(output, indent=2))
|
|
127
|
+
else:
|
|
128
|
+
print("Available Arc builder starter templates:")
|
|
129
|
+
if not names:
|
|
130
|
+
print(" (none)")
|
|
131
|
+
for name in names:
|
|
132
|
+
title = output.get("titles", {}).get(name, name)
|
|
133
|
+
print(f" - {name}: {title}")
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def cmd_scaffold(args: argparse.Namespace) -> int:
|
|
138
|
+
available = _list_templates()
|
|
139
|
+
if args.template not in available:
|
|
140
|
+
raise CliError(
|
|
141
|
+
f"unknown template: {args.template}\n"
|
|
142
|
+
f"available: {', '.join(available) if available else '(none)'}"
|
|
143
|
+
)
|
|
144
|
+
source = TEMPLATES_DIR / args.template
|
|
145
|
+
dest = Path(args.output).expanduser().resolve()
|
|
146
|
+
if dest.exists() and not args.force:
|
|
147
|
+
raise CliError(f"output already exists: {dest}; use --force to overwrite")
|
|
148
|
+
if dest.exists() and args.force:
|
|
149
|
+
shutil.rmtree(dest)
|
|
150
|
+
shutil.copytree(source, dest)
|
|
151
|
+
print(f"scaffolded '{args.template}' -> {dest}")
|
|
152
|
+
print(f"next: cd {dest.relative_to(Path.cwd()) if dest.is_relative_to(Path.cwd()) else dest}")
|
|
153
|
+
return 0
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def cmd_facts(args: argparse.Namespace) -> int:
|
|
157
|
+
facts = _load_json(CONFIG_DIR / "arc_testnet.facts.json")
|
|
158
|
+
if args.json:
|
|
159
|
+
print(json.dumps(facts, indent=2))
|
|
160
|
+
else:
|
|
161
|
+
print(json.dumps(facts, indent=2))
|
|
162
|
+
return 0
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def cmd_manifest(args: argparse.Namespace) -> int:
|
|
166
|
+
result = _run_script(X402_SERVER, ["--print-manifest"], timeout=60)
|
|
167
|
+
if result.stdout:
|
|
168
|
+
sys.stdout.write(result.stdout)
|
|
169
|
+
if result.stderr:
|
|
170
|
+
sys.stderr.write(result.stderr)
|
|
171
|
+
return result.returncode if result.returncode else 0
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def cmd_mcp(args: argparse.Namespace) -> int:
|
|
175
|
+
return mcp_main()
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def cmd_release_packet(args: argparse.Namespace) -> int:
|
|
179
|
+
out = (
|
|
180
|
+
Path(args.output).expanduser().resolve()
|
|
181
|
+
if args.output
|
|
182
|
+
else DEFAULT_OUTPUT_ROOT / ".arc-release-packet"
|
|
183
|
+
)
|
|
184
|
+
argv = ["--out", str(out)]
|
|
185
|
+
if args.force:
|
|
186
|
+
argv.append("--force")
|
|
187
|
+
return release_packet_main(argv)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
191
|
+
parser = argparse.ArgumentParser(
|
|
192
|
+
prog="arc-builder",
|
|
193
|
+
description="Unified CLI for the Arc MCP Builder Assistant kit.",
|
|
194
|
+
)
|
|
195
|
+
parser.add_argument(
|
|
196
|
+
"--version",
|
|
197
|
+
action="version",
|
|
198
|
+
version=f"%(prog)s {__version__}",
|
|
199
|
+
)
|
|
200
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
201
|
+
|
|
202
|
+
doctor = sub.add_parser("doctor", help="Run Arc Builder Doctor.")
|
|
203
|
+
doctor.add_argument("--full", action="store_true", help="Run full local verification.")
|
|
204
|
+
doctor.add_argument(
|
|
205
|
+
"--include-arc-rpc",
|
|
206
|
+
action="store_true",
|
|
207
|
+
help="Opt-in read-only Arc Testnet RPC chain-id check.",
|
|
208
|
+
)
|
|
209
|
+
doctor.add_argument(
|
|
210
|
+
"--include-public-site",
|
|
211
|
+
action="store_true",
|
|
212
|
+
help="Opt-in public GitHub Pages health check.",
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
sub.add_parser("validate", help="Run repository validation.")
|
|
216
|
+
|
|
217
|
+
templates = sub.add_parser("templates", help="List available starter templates.")
|
|
218
|
+
templates.add_argument("--json", action="store_true", help="Output machine-readable JSON.")
|
|
219
|
+
|
|
220
|
+
scaffold = sub.add_parser("scaffold", help="Copy a starter template to a new project.")
|
|
221
|
+
scaffold.add_argument("template", help="Template name (see 'templates').")
|
|
222
|
+
scaffold.add_argument("output", help="Destination directory.")
|
|
223
|
+
scaffold.add_argument("--force", action="store_true", help="Overwrite existing directory.")
|
|
224
|
+
|
|
225
|
+
facts = sub.add_parser("facts", help="Print reviewed Arc Testnet facts.")
|
|
226
|
+
facts.add_argument("--json", action="store_true", help="Output machine-readable JSON.")
|
|
227
|
+
|
|
228
|
+
sub.add_parser("manifest", help="Print the local x402 paid-agent manifest.")
|
|
229
|
+
sub.add_parser("mcp", help="Start the local Arc Builder MCP server (stdio).")
|
|
230
|
+
|
|
231
|
+
release_packet = sub.add_parser(
|
|
232
|
+
"release-packet", help="Generate a local maintainer release packet."
|
|
233
|
+
)
|
|
234
|
+
release_packet.add_argument(
|
|
235
|
+
"--output",
|
|
236
|
+
default="",
|
|
237
|
+
help="Output directory (default: .arc-release-packet/).",
|
|
238
|
+
)
|
|
239
|
+
release_packet.add_argument(
|
|
240
|
+
"--force",
|
|
241
|
+
action="store_true",
|
|
242
|
+
help="Overwrite existing packet directory.",
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
return parser
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
COMMANDS = {
|
|
249
|
+
"doctor": cmd_doctor,
|
|
250
|
+
"validate": cmd_validate,
|
|
251
|
+
"templates": cmd_templates,
|
|
252
|
+
"scaffold": cmd_scaffold,
|
|
253
|
+
"facts": cmd_facts,
|
|
254
|
+
"manifest": cmd_manifest,
|
|
255
|
+
"mcp": cmd_mcp,
|
|
256
|
+
"release-packet": cmd_release_packet,
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
261
|
+
parser = build_parser()
|
|
262
|
+
args = parser.parse_args(argv)
|
|
263
|
+
handler = COMMANDS.get(args.command)
|
|
264
|
+
if handler is None:
|
|
265
|
+
parser.error(f"unknown command: {args.command}")
|
|
266
|
+
try:
|
|
267
|
+
return handler(args)
|
|
268
|
+
except CliError as exc:
|
|
269
|
+
print(f"error: {exc.message}", file=sys.stderr)
|
|
270
|
+
return exc.exit_code
|
|
271
|
+
except subprocess.TimeoutExpired as exc:
|
|
272
|
+
print(f"error: timed out running {exc.cmd}", file=sys.stderr)
|
|
273
|
+
return 1
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
if __name__ == "__main__":
|
|
277
|
+
sys.exit(main())
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"scope": "arc-testnet-facts",
|
|
4
|
+
"network": {
|
|
5
|
+
"name": "Arc Testnet",
|
|
6
|
+
"chainId": 5042002,
|
|
7
|
+
"chainIdHex": "0x4cef52",
|
|
8
|
+
"rpcUrl": "https://rpc.testnet.arc.network",
|
|
9
|
+
"explorerUrl": "https://testnet.arcscan.app"
|
|
10
|
+
},
|
|
11
|
+
"nativeGas": {
|
|
12
|
+
"symbol": "USDC",
|
|
13
|
+
"decimals": 18
|
|
14
|
+
},
|
|
15
|
+
"erc20Usdc": {
|
|
16
|
+
"symbol": "USDC",
|
|
17
|
+
"address": "0x3600000000000000000000000000000000000000",
|
|
18
|
+
"decimals": 6
|
|
19
|
+
},
|
|
20
|
+
"policy": {
|
|
21
|
+
"mainnetSupported": false,
|
|
22
|
+
"walletRequired": false,
|
|
23
|
+
"networkChecksOptIn": true,
|
|
24
|
+
"recheckBeforePublication": true
|
|
25
|
+
},
|
|
26
|
+
"sources": {
|
|
27
|
+
"connect": "https://docs.arc.io/arc/references/connect-to-arc",
|
|
28
|
+
"contracts": "https://docs.arc.io/arc/references/contract-addresses",
|
|
29
|
+
"deploymentModel": "https://docs.arc.io/arc/concepts/deployment-model"
|
|
30
|
+
}
|
|
31
|
+
}
|