callx402 0.0.0-stage → 1.0.0
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/LICENSE +21 -0
- package/README.md +227 -2
- package/SPEC.md +264 -0
- package/bin/callx402.js +257 -0
- package/core/config.js +104 -0
- package/core/envelope.js +80 -0
- package/core/index.js +364 -0
- package/core/pipeline.js +371 -0
- package/core/remote.js +242 -0
- package/core/subsystems.js +136 -0
- package/dist/callx402-1.0.0.tgz +0 -0
- package/docs/ACTION_LANGUAGE.md +23 -0
- package/docs/MCP_IDENTITY.md +27 -0
- package/docs/README.md +315 -0
- package/docs/action-reference.md +247 -0
- package/docs/cli-help-verified-2026-10-06.txt +39 -0
- package/docs/logo.png +0 -0
- package/docs/problem-map.md +65 -0
- package/docs/troubleshooting/cx402-402afterfail-001-402-after-failed-settle.md +143 -0
- package/docs/troubleshooting/cx402-agentcap-001-agent-spending.md +114 -0
- package/docs/troubleshooting/cx402-eip3009-001-authorization-checklist.md +124 -0
- package/docs/troubleshooting/cx402-paidnores-001-paid-no-result.md +97 -0
- package/docs/troubleshooting/cx402-safretry-001-retry-after-payment.md +106 -0
- package/docs/troubleshooting/cx402-settlepend-001-settlement-pending.md +92 -0
- package/docs/troubleshooting/cx402-solanafail-001-solana-settlement.md +119 -0
- package/docs/troubleshooting/cx402-verset-001-verify-ok-settle-fails.md +101 -0
- package/docs/visuals/01-action-map.png +0 -0
- package/docs/visuals/02-diagnose.png +0 -0
- package/docs/visuals/03-resolve.png +0 -0
- package/docs/visuals/04-route.png +0 -0
- package/docs/visuals/05-preflight.png +0 -0
- package/docs/visuals/06-inspect.png +0 -0
- package/docs/visuals/07-status.png +0 -0
- package/docs/visuals/08-architecture.svg +49 -0
- package/docs/visuals/MANIFEST.md +40 -0
- package/docs/visuals/raw/01-help.out +39 -0
- package/docs/visuals/raw/02-diagnose.out +2 -0
- package/docs/visuals/raw/03-resolve.out +4 -0
- package/docs/visuals/raw/04-route.out +2 -0
- package/docs/visuals/raw/05-preflight.out +2 -0
- package/docs/visuals/raw/06-inspect.out +23 -0
- package/docs/visuals/raw/07-status.out +16 -0
- package/docs/visuals/render_terminal.py +149 -0
- package/docs/what-is-callx402.md +251 -0
- package/integrations/README.md +62 -0
- package/integrations/core.py +329 -0
- package/integrations/crewai/callx402_crewai.py +109 -0
- package/integrations/facilitator/settle-guard.js +99 -0
- package/integrations/langchain/callx402_tools.py +180 -0
- package/integrations/mcp-clients/README.md +121 -0
- package/integrations/n8n/callx402-incident-guard.json +1 -0
- package/mcp/README.md +63 -0
- package/mcp/index.js +239 -0
- package/package.json +39 -4
- package/scripts/drift-check.js +202 -0
- package/sdk/js/index.js +207 -0
- package/sdk/python/README.md +67 -0
- package/sdk/python/callx402/__init__.py +317 -0
- package/sdk/python/callx402/cli.py +193 -0
- package/sdk/python/pyproject.toml +30 -0
- package/sdk/python/setup.py +56 -0
- package/server/index.js +520 -0
- package/server/openapi.yaml +537 -0
- package/server.json +1 -0
- package/test/cli-dispatch.test.js +248 -0
- package/test/helpers.js +103 -0
- package/test/integrity.test.js +43 -0
- package/test/intent-pipeline.test.js +205 -0
- package/test/remote.test.js +166 -0
- package/test/safety.test.js +234 -0
- package/test/sdk.test.js +198 -0
- package/test/server.test.js +190 -0
- package/test/subsystems.test.js +118 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Payload
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,228 @@
|
|
|
1
|
-
|
|
1
|
+
> **Payload** — Developer infrastructure for x402, agent payments, and programmable revenue.
|
|
2
|
+
> PAYLOAD → VEYLINE (flagship) → CALLX402 (action layer) → REVRULE (separate) → developer products → free utilities.
|
|
3
|
+
> This repo: **callx402 by Payload — the universal action layer into Veyline's x402 infrastructure.**
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<p align="center"><img src="docs/logo.png" alt="callx402 logo" width="200"></p>
|
|
6
|
+
# callx402 by Payload
|
|
7
|
+
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](package.json)
|
|
10
|
+
[](mcp/README.md)
|
|
11
|
+
|
|
12
|
+
**Powered by Veyline. When x402 breaks, callx402.**
|
|
13
|
+
|
|
14
|
+
callx402 is the universal action layer into Veyline's x402 infrastructure. Say what you need done in plain language (or hit an HTTP endpoint) and callx402 routes it to the production system that does the real work: diagnose a broken x402 payment, rescue a failed transaction, route an agent job to the cheapest viable path, resolve settlement state from on-chain evidence, or execute under an explicit budget with fail-closed safety rules.
|
|
15
|
+
|
|
16
|
+
**Why it exists:** x402 failures are expensive and opaque. A settlement attempt ends in `settlement_pending` and nobody knows whether the money moved. A 402 response your wallet misreads. A retry that signs a second authorization for the same intent and pays twice. callx402 exists for exactly those moments: `diagnose` pins the failure to a stage, `rescue` triages the incident, `resolve` settles the question from evidence, `route` finds the cheapest viable path, `execute` runs under a hard budget.
|
|
17
|
+
|
|
18
|
+
**Try it (one minute):**
|
|
19
|
+
```sh
|
|
20
|
+
git clone https://github.com/Payloadhq/callx402
|
|
21
|
+
cd callx402 && npm install && npm link
|
|
22
|
+
callx402 diagnose --target "https://api.example.com/x402/pay"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If it saves you one debugging session, star the repo and read on.
|
|
26
|
+
|
|
27
|
+
## MCP server: connect in 60 seconds
|
|
28
|
+
|
|
29
|
+
This repo ships a zero-dependency, read-only MCP server (`mcp/index.js`, node
|
|
30
|
+
stdlib only, stdio transport) exposing six `x402_*` diagnostic tools. Nothing
|
|
31
|
+
here charges, executes, retries, or repays.
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
git clone https://github.com/Payloadhq/callx402
|
|
35
|
+
# no npm install needed for the MCP server
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Add this block to your MCP client config (replace the path), then restart the
|
|
39
|
+
client:
|
|
40
|
+
|
|
41
|
+
| Client | Config file |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Claude Desktop | `claude_desktop_config.json` (`~/Library/Application Support/Claude/` on macOS, `%APPDATA%\Claude\` on Windows) |
|
|
44
|
+
| Cursor | `~/.cursor/mcp.json` (user scope) or `.cursor/mcp.json` (project scope) |
|
|
45
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"mcpServers": {
|
|
50
|
+
"callx402": {
|
|
51
|
+
"command": "node",
|
|
52
|
+
"args": ["/absolute/path/to/callx402/mcp/index.js"]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Ask the client to list its MCP tools: the six `x402_*` tools should appear.
|
|
59
|
+
Per-client notes and the raw stdio test handshake:
|
|
60
|
+
[`integrations/mcp-clients/`](integrations/mcp-clients/).
|
|
61
|
+
|
|
62
|
+
## The relationship
|
|
63
|
+
|
|
64
|
+
- **PAYLOAD** = the parent company.
|
|
65
|
+
- **VEYLINE** = production infrastructure for x402 + MCP. The flagship brand.
|
|
66
|
+
- **CALLX402 BY PAYLOAD** = the x402 response/action layer, powered by Veyline.
|
|
67
|
+
The entry action into Veyline's production infrastructure, not the flagship
|
|
68
|
+
name. Nothing here renames Veyline.
|
|
69
|
+
|
|
70
|
+
Discovery path: a developer searching for x402 finds callx402, uses it, and
|
|
71
|
+
learns Veyline. Payload is not affiliated with the x402 Foundation.
|
|
72
|
+
|
|
73
|
+
## What it does
|
|
74
|
+
|
|
75
|
+
- **Diagnose** an x402 or MCP failure
|
|
76
|
+
- **Rescue** a failed transaction (auth-gated)
|
|
77
|
+
- **Route** a paid agent job to the cheapest viable path
|
|
78
|
+
- **Resolve** settlement state from on-chain evidence
|
|
79
|
+
- **Execute** under an explicit budget, with fail-closed safety rules
|
|
80
|
+
|
|
81
|
+
Behavioral usage language (not trademark claims):
|
|
82
|
+
|
|
83
|
+
- "Need to diagnose x402? callx402."
|
|
84
|
+
- "Need to rescue a transaction? callx402."
|
|
85
|
+
- "Need to route a paid agent job? callx402."
|
|
86
|
+
- "Need settlement certainty? callx402."
|
|
87
|
+
- "Need to execute under a budget? callx402."
|
|
88
|
+
|
|
89
|
+
## Quickstart
|
|
90
|
+
|
|
91
|
+
**Current install route** (direct from GitHub; this path keeps working after the npm registry release):
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
npm install Payloadhq/callx402
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Once the package is published, the canonical path will be `npm install callx402`.
|
|
98
|
+
|
|
99
|
+
Alternative — clone and link for local development:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
git clone https://github.com/Payloadhq/callx402
|
|
103
|
+
cd callx402
|
|
104
|
+
npm install
|
|
105
|
+
npm link # exposes the `callx402` command
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
callx402 status
|
|
110
|
+
callx402 "complete this job for under $1"
|
|
111
|
+
callx402 diagnose --target "https://api.example.com/x402/pay"
|
|
112
|
+
callx402 rescue --incident inc_123
|
|
113
|
+
callx402 route --goal "fetch 100 product prices for under $0.50"
|
|
114
|
+
callx402 resolve --evidence '{"txHash":"0xabc..."}'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### JavaScript SDK
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
const { callx402 } = require('callx402');
|
|
121
|
+
|
|
122
|
+
const result = await callx402({
|
|
123
|
+
intent: 'complete this job for under $1',
|
|
124
|
+
maxBudget: 1.00,
|
|
125
|
+
networks: ['base'],
|
|
126
|
+
assets: ['USDC'],
|
|
127
|
+
approvalThreshold: 5.00,
|
|
128
|
+
idempotencyKey: 'job-42',
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Python SDK
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import callx402
|
|
136
|
+
|
|
137
|
+
result = callx402.callx402(
|
|
138
|
+
intent="complete this job for under $1",
|
|
139
|
+
max_budget=1.00,
|
|
140
|
+
networks=["base"],
|
|
141
|
+
assets=["USDC"],
|
|
142
|
+
approval_threshold=5.00,
|
|
143
|
+
idempotency_key="job-42",
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### HTTP server
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
CALLX402_PORT=8787 node server/index.js
|
|
151
|
+
curl -X POST http://127.0.0.1:8787/call \
|
|
152
|
+
-H 'Content-Type: application/json' \
|
|
153
|
+
-d '{"intent":"complete this job for under $1","maxBudget":1.00,"dryRun":true}'
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Full HTTP surface: `server/openapi.yaml` (served live at `GET /openapi.json`).
|
|
157
|
+
|
|
158
|
+
## Commands
|
|
159
|
+
|
|
160
|
+
| Command | What it does |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `callx402 "natural language intent"` | Intent mode: parse, plan, budget-check, route, execute |
|
|
163
|
+
| `callx402 status [--json]` | Subsystem reachability and flag state |
|
|
164
|
+
| `callx402 diagnose [--target ...]` | Diagnose an x402 / MCP failure |
|
|
165
|
+
| `callx402 rescue --incident <id>` | Rescue a transaction (auth-gated) |
|
|
166
|
+
| `callx402 route --goal <text>` | Route a paid job to the cheapest viable path |
|
|
167
|
+
| `callx402 resolve --evidence <json\|@file>` | Resolve settlement state from evidence |
|
|
168
|
+
| `callx402 doctor` | Run the MCP doctor checks |
|
|
169
|
+
| `callx402 execute --intent <text> [--max-budget N] [--dry-run]` | Execute under an explicit budget |
|
|
170
|
+
| `callx402 monitor [--once\|--watch]` | Watch subsystem/incident state |
|
|
171
|
+
| `callx402 preflight` | Preflight checks before a paid run |
|
|
172
|
+
| `callx402 inspect [--query <text>]` | Inspect capability graph / state |
|
|
173
|
+
| `callx402 config list \| get <k> \| set <k> <v>` | Manage local config |
|
|
174
|
+
|
|
175
|
+
## Integrations
|
|
176
|
+
|
|
177
|
+
Working entry points for agent frameworks, automation, MCP clients, and x402
|
|
178
|
+
facilitators — all in [`integrations/`](integrations/) and tested against the
|
|
179
|
+
live rail:
|
|
180
|
+
|
|
181
|
+
- **LangChain** — 9 tools (`integrations/langchain/`): diagnose, recover,
|
|
182
|
+
resolve, evidence, explain, safe-retry, duplicate-payment risk, preflight,
|
|
183
|
+
plus the free live fee schedule
|
|
184
|
+
- **CrewAI** — the same actions as CrewAI Tools (`integrations/crewai/`)
|
|
185
|
+
- **n8n** — importable incident-guard workflow (`integrations/n8n/`): maps an
|
|
186
|
+
incident to a callx402 action, fetches the free live quote, invokes when
|
|
187
|
+
credentialed, otherwise emits payment instructions — never auto-pays
|
|
188
|
+
- **MCP clients** — Claude Desktop / Cursor / Windsurf setup for the free
|
|
189
|
+
read-only MCP server (`integrations/mcp-clients/`)
|
|
190
|
+
- **x402 facilitators** — `settle-guard.js` (`integrations/facilitator/`):
|
|
191
|
+
resolve settlement state from evidence *before* re-broadcasting a payment
|
|
192
|
+
|
|
193
|
+
Problem → action map: [`docs/problem-map.md`](docs/problem-map.md).
|
|
194
|
+
Machine front door for agents: https://payloadhq.github.io/agents.json.
|
|
195
|
+
|
|
196
|
+
## Money-safety rules
|
|
197
|
+
|
|
198
|
+
- **Settlement UNKNOWN is never auto-retried and never repaid.**
|
|
199
|
+
- **Over-budget intents are refused with zero side effects.**
|
|
200
|
+
- **Approval thresholds fail closed.**
|
|
201
|
+
- **Idempotency keys dedupe** — repeats return the original, never re-execute.
|
|
202
|
+
- **Disabled or unreachable subsystems fail closed** — success is never faked.
|
|
203
|
+
- **Non-custodial** — callx402 dispatches work; it never holds funds or private keys.
|
|
204
|
+
|
|
205
|
+
## What callx402 is not
|
|
206
|
+
|
|
207
|
+
- Not the flagship product name. The product is **Veyline**.
|
|
208
|
+
- Not a broker, negotiator, or custodian. It dispatches; it never holds funds.
|
|
209
|
+
- The phrases above are usage language, not exclusivity claims.
|
|
210
|
+
|
|
211
|
+
## Links
|
|
212
|
+
|
|
213
|
+
- Canonical docs: https://payloadhq.github.io/
|
|
214
|
+
- Payload org profile: https://github.com/Payloadhq/Payloadhq
|
|
215
|
+
- RevRule by Payload (separate product): https://github.com/Payloadhq/revrule-console
|
|
216
|
+
|
|
217
|
+
Full subsystem reference: `docs/README.md`. Behavioral language: `docs/ACTION_LANGUAGE.md`.
|
|
218
|
+
Design spec: `SPEC.md`.
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
MIT. See `LICENSE`.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
**More from Payload** · [payloadhq.github.io](https://payloadhq.github.io/) · [all Payload repos](https://github.com/Payloadhq)
|
|
227
|
+
|
|
228
|
+
Related: [x402-manifest-check](https://github.com/Payloadhq/x402-manifest-check) · [x402-observatory](https://github.com/Payloadhq/x402-observatory) · [flow-agentic-demo](https://github.com/Payloadhq/flow-agentic-demo)
|
package/SPEC.md
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# callx402 — Universal Action Layer — Build Spec
|
|
2
|
+
|
|
3
|
+
**FUNDAMENTAL RULE: callx402 is the ACTION, not the product name.**
|
|
4
|
+
The flagship keeps a separate unique brand (forthcoming). Do NOT rename Sentinel,
|
|
5
|
+
Rescue, Doctor, Router, Valuator, SpendGuard, Settlement Resolver, MCP fabric,
|
|
6
|
+
RevRule, the Payload brand, or any marketplace listing. callx402 is an
|
|
7
|
+
access/dispatch layer that CALLS existing subsystems. Architecture:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
UNIQUE PRODUCT BRAND → accessed through → callx402
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 1. Non-negotiables
|
|
14
|
+
|
|
15
|
+
- **NEVER modify** `~/workspace/products/x402-paid-api-starter-kit/v2.0.0/`. Import from it
|
|
16
|
+
via relative require. Verify at the end with `git` status or a checksum spot-check
|
|
17
|
+
that the tree is untouched (it is not a git repo necessarily; at minimum do not
|
|
18
|
+
write any file under it).
|
|
19
|
+
- **Real working code only.** No placeholders, no stubs presented as functional.
|
|
20
|
+
If a subsystem is feature-flag disabled or needs live infra that isn't reachable,
|
|
21
|
+
the command must say so clearly and exit non-zero. Never fake success.
|
|
22
|
+
- **No logic duplication.** Every command dispatches into the existing subsystem.
|
|
23
|
+
- **Do NOT publish** to npm, PyPI, or Docker Hub. Packages must be publish-*ready*
|
|
24
|
+
only. (npm `payloadtools` account suspended until 2026-10-07 12:14 CDT;
|
|
25
|
+
PyPI blocked on owner's account + 2FA.)
|
|
26
|
+
- **Do NOT** create an MCP tool named exactly `call_x402` (collides with an existing
|
|
27
|
+
live tool on the fiatdock marketplace). MCP identity stays a DEFERRED decision doc.
|
|
28
|
+
- Behavioral language only ("Need to diagnose x402? callx402."). Never claim
|
|
29
|
+
exclusive trademark ownership of the phrase.
|
|
30
|
+
- Stdlib only for the core/CLI/HTTP server. No new external dependencies.
|
|
31
|
+
(Python SDK: stdlib only — `subprocess`, `json`, `argparse`, `shutil`.)
|
|
32
|
+
- Node >= 18 (runtime here is v24.20.0). Python >= 3.9 (runtime 3.12.3).
|
|
33
|
+
|
|
34
|
+
## 2. Directory layout (all under ~/workspace/products/callx402/)
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
SPEC.md
|
|
38
|
+
package.json # name: callx402, version 0.1.0, MIT, bin {callx402: ./bin/callx402.js},
|
|
39
|
+
# main ./sdk/js/index.js, homepage + repository
|
|
40
|
+
# https://github.com/Payloadhq/callx402
|
|
41
|
+
bin/callx402.js # CLI entry (shebang, stdlib only, requires ../core)
|
|
42
|
+
core/
|
|
43
|
+
index.js # runAction(name, args, opts), runIntent(text, opts), getStatus()
|
|
44
|
+
subsystems.js # lazy require map of v2.0.0 modules + enabled() checks
|
|
45
|
+
config.js # config file (~/.config/callx402/config.json, $CALLX402_CONFIG),
|
|
46
|
+
# env overrides (CALLX402_*), safe defaults
|
|
47
|
+
envelope.js # result envelope builders + exit codes
|
|
48
|
+
pipeline.js # intent pipeline stage orchestration
|
|
49
|
+
sdk/js/
|
|
50
|
+
index.js # callx402({...}) -> Promise<result envelope>
|
|
51
|
+
sdk/python/
|
|
52
|
+
pyproject.toml # name callx402, version 0.1.0, console_scripts callx402,
|
|
53
|
+
# bundles ../bin + ../core as package data, invokes via node
|
|
54
|
+
callx402/__init__.py # callx402(...) -> dict (subprocess to bundled CLI --json)
|
|
55
|
+
callx402/cli.py # argparse main() -> same path
|
|
56
|
+
server/
|
|
57
|
+
index.js # node:http server: GET /health, GET /openapi.json,
|
|
58
|
+
# POST /call /rescue /route /resolve /diagnose
|
|
59
|
+
openapi.yaml
|
|
60
|
+
docs/
|
|
61
|
+
README.md # callx402 is the action; flagship brand separate/forthcoming
|
|
62
|
+
ACTION_LANGUAGE.md # behavioral phrases
|
|
63
|
+
MCP_IDENTITY.md # DEFERRED decision doc
|
|
64
|
+
test/ # (test agent) node --test suite
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 3. Subsystem module map (v2.0.0 root = ../../x402-paid-api-starter-kit/v2.0.0)
|
|
68
|
+
|
|
69
|
+
Default v2Root: `path.resolve(__dirname, '../../x402-paid-api-starter-kit/v2.0.0')`.
|
|
70
|
+
Overridable via `CALLX402_V2_ROOT` env or config `v2Root`. All requires lazy (inside
|
|
71
|
+
functions) so `status` can report per-module reachability.
|
|
72
|
+
|
|
73
|
+
| Subsystem | Require path (from v2Root) | Key exports |
|
|
74
|
+
|--------------------|----------------------------------|-------------|
|
|
75
|
+
| Sentinel | `lib/sentinel/index.js` | `createSentinel(opts)`, `createInertSentinel()`, `INCIDENT_TYPES`, `FLAG` (`PAYLOAD_SENTINEL`?), `enabled()` |
|
|
76
|
+
| Rescue | `lib/rescue/index.js` | `createRescue({...})`, `incidents`, `detector`, `actions`, `autorescue`, `receipts`, `pricing`, `RESCUE_VERSION`, `FLAG='PAYLOAD_RESCUE'`, `enabled()` |
|
|
77
|
+
| Doctor | `lib/mcp/doctor.js` | `runMcpDoctor(evidence)`, `classifyMcpFailure`, `STAGES`, `FLAG='PAYLOAD_MCP_DOCTOR'`, `enabled()` |
|
|
78
|
+
| Router | `lib/mcp/smart-router.js` | `selectTool`, `rankTools`, `normalizeCandidate`, `totalCost`, `POLICIES`, `DEFAULTS`, `enabled()` |
|
|
79
|
+
| Router (paths) | `lib/mcp/route-decider.js` | `choosePath`, `selectPath`, `expectedCost`, `enabled()` |
|
|
80
|
+
| Valuator | `valuator/quote.js` | inspect before use |
|
|
81
|
+
| SpendGuard | `lib/mcp/spendguard.js` | `createTaskSpendGuard({...})`, `DEFAULT_PHASES`, `enabled()` |
|
|
82
|
+
| Settlement Resolver| `lib/settlement-resolver.js` | `resolve(evidence)`, `STATES`, `POLICY_MATRIX`, `createMockChain`, `createMockFacilitator`, `FLAG='PAYLOAD_SETTLEMENT_RESOLVER'`, `enabled()` |
|
|
83
|
+
| Intent Engine | `lib/mcp/intent-engine.js` | `parse(text)` / `parseIntent`, `createEngine`, `GOALS`, `enabled()` |
|
|
84
|
+
| Capability Graph | `lib/mcp/capability-graph.js` | `createGraph()` → `{upsertTool, getToolProfile, findTools, recordObservation, stats, save, load}`, `enabled()` |
|
|
85
|
+
| Economic Planner | `lib/mcp/economic-planner.js` | `planGoal(opts)`, `scorePlan`, `OBJECTIVES`, `DEFAULTS`, `enabled()` |
|
|
86
|
+
| MCP fabric | `lib/mcp/index.js` | `transactional, saga, spendguard, resultRecovery, effectProof, executionKernel, ...` |
|
|
87
|
+
| RevRule | `lib/revrule-events.js` | `createEmitter({sink, idempotencyRegistry})`, `buildEvent`, `createMemorySink`, `enabled()` |
|
|
88
|
+
| Preflight | `lib/mcp/preflight.js` | `runMcpPreflight`, `buildChecks`, `enabled()` |
|
|
89
|
+
| Effect Proof | `lib/mcp/effect-proof.js` | `issueEffectProof`, `verifyEffectProof`, `enabled()` |
|
|
90
|
+
| Execution Kernel | `lib/mcp/execution-kernel.js` | `createKernel`, `STATES`, `TERMINAL`, `enabled()` |
|
|
91
|
+
| Result Recovery | `lib/mcp/result-recovery.js` | `createRecoveryStore`, `createResultRecoveryCache`, `buildOperationIdentity`, `enabled()` |
|
|
92
|
+
|
|
93
|
+
**Flag rule:** every module exposes `enabled()` (checks `process.env[FLAG]==='1'`)
|
|
94
|
+
and `FLAG`. Before dispatch, call `enabled()`. If false, return
|
|
95
|
+
`subsystemStatus: 'disabled'` naming the flag — do NOT fake success.
|
|
96
|
+
(You may document that the user can export the flag; do not silently force-enable
|
|
97
|
+
anything that guards real money movement. Read-only/diagnostic modules may note
|
|
98
|
+
the flag to enable.)
|
|
99
|
+
|
|
100
|
+
**Status honesty:** `getStatus()` must report per subsystem: `reachable` (require
|
|
101
|
+
succeeded), `enabled` (flag on), `version` where available, and `note` for
|
|
102
|
+
prototype/stub status (e.g. rescue-service `_rescue-stub.js` exists — inspect and
|
|
103
|
+
report honestly; never present a stub as production).
|
|
104
|
+
|
|
105
|
+
## 4. Result envelope (JSON everywhere: CLI --json, SDKs, HTTP)
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"ok": true,
|
|
110
|
+
"action": "diagnose",
|
|
111
|
+
"disposition": "human-readable outcome",
|
|
112
|
+
"subsystem": "doctor",
|
|
113
|
+
"subsystemStatus": "ok | disabled | unreachable | prototype",
|
|
114
|
+
"data": {},
|
|
115
|
+
"settlement": "DEFINITELY_PAID | DEFINITELY_NOT_PAID | AUTHORIZED_NOT_SETTLED | PENDING | CONFLICT | UNKNOWN | null",
|
|
116
|
+
"txHash": "0x... | null",
|
|
117
|
+
"receipt": {},
|
|
118
|
+
"idempotencyKey": "string | null",
|
|
119
|
+
"deduped": false,
|
|
120
|
+
"error": { "code": "string", "message": "string" }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`error` is null on success. `ok:false` whenever `error` is set.
|
|
125
|
+
|
|
126
|
+
**Exit codes (CLI):** 0 ok · 1 generic failure · 2 usage/validation error ·
|
|
127
|
+
3 subsystem disabled or unreachable · 4 budget refused (SpendGuard) ·
|
|
128
|
+
5 settlement UNKNOWN (must never auto-retry/repay — surface and stop).
|
|
129
|
+
|
|
130
|
+
**Money-safety invariants (hard):**
|
|
131
|
+
- Settlement `UNKNOWN` → never auto-retry, never repay. Return exit 5 with
|
|
132
|
+
instructions for manual resolution.
|
|
133
|
+
- An explicit `--force-retry`/`retry` flag on execute MUST be rejected when the
|
|
134
|
+
prior settlement state is UNKNOWN (unsafe retry refusal).
|
|
135
|
+
- Over-budget intent → SpendGuard refusal, exit 4, zero execution side effects.
|
|
136
|
+
- Duplicate `idempotencyKey` → return the ORIGINAL stored result with
|
|
137
|
+
`deduped:true`; do not re-execute. Use result-recovery store.
|
|
138
|
+
|
|
139
|
+
## 5. Config (`core/config.js`)
|
|
140
|
+
|
|
141
|
+
- File: `~/.config/callx402/config.json`, overridable by `$CALLX402_CONFIG`.
|
|
142
|
+
- Env overrides: `CALLX402_V2_ROOT`, `CALLX402_MODE` (local|remote),
|
|
143
|
+
`CALLX402_REMOTE_URL`, `CALLX402_AUTH_TOKEN`, `CALLX402_DEFAULT_NETWORK`,
|
|
144
|
+
`CALLX402_DEFAULT_ASSET`, `CALLX402_DEFAULT_BUDGET_USD`, `CALLX402_APPROVAL_THRESHOLD_USD`.
|
|
145
|
+
- `config get|set|list` via CLI (`callx402 config list`, `callx402 config set key value`).
|
|
146
|
+
- Safe defaults: mode local, no auto-spend, budget default 1.00 USD, approval
|
|
147
|
+
threshold default 5.00 USD (above → require explicit `--approve` or fail closed).
|
|
148
|
+
- Remote mode: CLI/SDK dispatch via HTTP to a callx402 server (auth header when
|
|
149
|
+
`CALLX402_AUTH_TOKEN` set). Unreachable remote → clear error, non-zero exit.
|
|
150
|
+
|
|
151
|
+
## 6. Intent pipeline (`core/pipeline.js`)
|
|
152
|
+
|
|
153
|
+
`runIntent(text, opts)` stages (each honest about availability):
|
|
154
|
+
1. **Intent Engine** `parse(text)` → structured intent (extract budget like
|
|
155
|
+
"under $1" → maxBudget).
|
|
156
|
+
2. **Capability Graph** `findTools` → candidate tools.
|
|
157
|
+
3. **Economic Planner** `planGoal` → costed plan.
|
|
158
|
+
4. **SpendGuard** `createTaskSpendGuard` → budget check vs `maxBudget`
|
|
159
|
+
(opts override; default from config). Over → refuse (exit 4).
|
|
160
|
+
5. **Router** `selectTool`/`choosePath` → route.
|
|
161
|
+
6. **x402/MCP execution** via execution kernel — ONLY if a live executable route
|
|
162
|
+
exists; otherwise return `disposition: 'no executable route available'`
|
|
163
|
+
with `subsystemStatus` honest, no fake execution.
|
|
164
|
+
7. **Effect Proof** `issueEffectProof`/`verifyEffectProof`.
|
|
165
|
+
8. **Settlement** `resolve` → settlement state recorded; UNKNOWN → exit 5 path.
|
|
166
|
+
9. **Delivery + Reconciliation** → receipt.
|
|
167
|
+
10. **RevRule** `createEmitter` → emit economic event (idempotent).
|
|
168
|
+
|
|
169
|
+
Options: `maxBudget, deadline, speed ('fast'|'balanced'|'cheap'), risk
|
|
170
|
+
('low'|'medium'|'high'), networks[], assets[], providers[], approvalThreshold,
|
|
171
|
+
idempotencyKey, timeoutMs, dryRun`.
|
|
172
|
+
|
|
173
|
+
`runAction(name, args, {deps}={})` — `deps` is an internal/test seam allowing
|
|
174
|
+
subsystem handle overrides. Document as internal.
|
|
175
|
+
|
|
176
|
+
## 7. CLI contract (`bin/callx402.js`)
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
callx402 <command> [args] [options]
|
|
180
|
+
callx402 "natural language intent" # intent mode
|
|
181
|
+
callx402 --help | -h
|
|
182
|
+
callx402 --version | -v
|
|
183
|
+
callx402 status [--json]
|
|
184
|
+
callx402 diagnose [--target ...] [--json]
|
|
185
|
+
callx402 rescue --incident <id> [--json] # auth-gated; without auth -> clear error
|
|
186
|
+
callx402 route --goal <text> [--json]
|
|
187
|
+
callx402 resolve --evidence <json|@file> [--json]
|
|
188
|
+
callx402 doctor [--json]
|
|
189
|
+
callx402 execute --intent <text> [--max-budget 1.00] [--dry-run] [--idempotency-key K]
|
|
190
|
+
callx402 monitor [--once|--watch] [--json]
|
|
191
|
+
callx402 preflight [--json]
|
|
192
|
+
callx402 inspect [--query <text>] [--json]
|
|
193
|
+
callx402 config list | get <k> | set <k> <v>
|
|
194
|
+
```
|
|
195
|
+
- Global: `--json` (envelope on stdout), `--timeout <ms>`.
|
|
196
|
+
- Unknown command → usage error, exit 2, list valid commands.
|
|
197
|
+
- Malformed input (bad JSON, bad flags) → exit 2 with clear message.
|
|
198
|
+
- Default (no --json): concise human-readable summary + key fields.
|
|
199
|
+
|
|
200
|
+
## 8. JS SDK (`sdk/js/index.js`)
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
const { callx402 } = require('callx402'); // or require('./sdk/js')
|
|
204
|
+
const result = await callx402({
|
|
205
|
+
intent: 'complete this job for under $1',
|
|
206
|
+
maxBudget: 1.00, deadline: '2026-10-07T00:00:00Z',
|
|
207
|
+
speed: 'balanced', risk: 'low',
|
|
208
|
+
networks: ['base'], assets: ['USDC'], providers: [],
|
|
209
|
+
approvalThreshold: 5.00, idempotencyKey: '...', timeoutMs: 30000, dryRun: false,
|
|
210
|
+
});
|
|
211
|
+
// result: envelope (see §4). Also export: callx402.version, callx402.status(), sub-actions
|
|
212
|
+
// callx402.diagnose(), .rescue(), .route(), .resolve(), .doctor(), .execute(), .monitor(), .preflight(), .inspect()
|
|
213
|
+
```
|
|
214
|
+
Requires `../..` core directly (same process). No duplication.
|
|
215
|
+
|
|
216
|
+
## 9. Python SDK (`sdk/python/`)
|
|
217
|
+
|
|
218
|
+
- `pyproject.toml`: name `callx402`, version `0.1.0`, `console_scripts: callx402 =
|
|
219
|
+
callx402.cli:main`. Bundles `../../bin` + `../../core` as package data;
|
|
220
|
+
at runtime finds `node` via `shutil.which('node')` and invokes the bundled
|
|
221
|
+
`bin/callx402.js --json`. If node missing → clear RuntimeError.
|
|
222
|
+
- `callx402/__init__.py`: `def callx402(intent=None, max_budget=None, deadline=None,
|
|
223
|
+
speed=None, risk=None, networks=None, assets=None, providers=None,
|
|
224
|
+
approval_threshold=None, idempotency_key=None, timeout_ms=None, dry_run=False,
|
|
225
|
+
action=None, **kwargs) -> dict`. Maps kwargs → CLI argv, parses stdout JSON.
|
|
226
|
+
Internal helper module may be named `call_x402.py` ONLY if needed for
|
|
227
|
+
snake_case conventions; the PUBLIC import stays `callx402`.
|
|
228
|
+
- `callx402/cli.py`: `main()` with argparse mirroring the node CLI surface
|
|
229
|
+
(subset: command + common options + --json passthrough).
|
|
230
|
+
|
|
231
|
+
## 10. HTTP server (`server/index.js`, node:http only)
|
|
232
|
+
|
|
233
|
+
- `GET /health` → `{ok, version, subsystems: {...}}` (reuse getStatus).
|
|
234
|
+
- `GET /openapi.json` → serves openapi.yaml as JSON (convert or embed).
|
|
235
|
+
- `POST /call` → `{intent, maxBudget, deadline, speed, risk, networks, assets, providers, approvalThreshold, idempotencyKey, dryRun}` → runIntent.
|
|
236
|
+
- `POST /rescue` → `{incidentId, ...}` → rescue dispatch.
|
|
237
|
+
- `POST /route` → `{goal, ...}` → router dispatch.
|
|
238
|
+
- `POST /resolve` → `{evidence}` → settlement resolve.
|
|
239
|
+
- `POST /diagnose` → `{target/evidence}` → doctor dispatch.
|
|
240
|
+
- Auth: if `CALLX402_AUTH_TOKEN` set, require `Authorization: Bearer` — else 401.
|
|
241
|
+
- `openapi.yaml`: document all routes + envelope schema.
|
|
242
|
+
|
|
243
|
+
## 11. Docs
|
|
244
|
+
|
|
245
|
+
- `docs/README.md`: what callx402 is (the action), what it is not (not the product
|
|
246
|
+
name), architecture diagram (brand → callx402 → subsystems), quickstart
|
|
247
|
+
(install from GitHub, `callx402 status`, `callx402 "…"`, SDK snippets),
|
|
248
|
+
money-safety rules, link to v2.0.0 subsystem docs.
|
|
249
|
+
- `docs/ACTION_LANGUAGE.md`: the five behavioral phrases, framed as usage
|
|
250
|
+
language, explicitly NOT trademark claims.
|
|
251
|
+
- `docs/MCP_IDENTITY.md`: DEFERRED. Proposed pattern: server name tied to future
|
|
252
|
+
flagship brand; tool `[future_brand]_call`; description "Call x402
|
|
253
|
+
infrastructure for routing, rescue, diagnosis, settlement resolution and
|
|
254
|
+
execution." Rationale for avoiding bare `call_x402` (live collision on
|
|
255
|
+
fiatdock). Mark clearly: DO NOT FINALIZE until flagship brand chosen.
|
|
256
|
+
|
|
257
|
+
## 12. Definition of done (per builder)
|
|
258
|
+
|
|
259
|
+
- `node bin/callx402.js --help`, `--version`, `status` all work for real.
|
|
260
|
+
- Every command dispatches to the real subsystem or reports honestly why not.
|
|
261
|
+
- `npm install` works offline (zero deps). `npm link` exposes `callx402`.
|
|
262
|
+
- Python: `pip install -e ./sdk/python` works; `python -c "import callx402"`.
|
|
263
|
+
- No file written under v2.0.0. No publish attempted.
|
|
264
|
+
- Smoke-test every command you build and report the literal outputs.
|