Skip to content

Commit 027457f

Browse files
committed
feat: add WIP x402 client SDK and stackflow agent scaffolds
1 parent e64b83a commit 027457f

23 files changed

+3816
-0
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,9 @@ This repo includes a starter x402-style gateway at
550550
Detailed technical design and production guidance:
551551

552552
- `server/X402_GATEWAY_DESIGN.md`
553+
- `server/X402_CLIENT_SDK_DESIGN.md`
554+
- `packages/x402-client/` (SDK scaffold with SQLite-backed client state store)
555+
- `server/STACKFLOW_AGENT_DESIGN.md` (simple agent runtime without local node)
553556

554557
Run it with:
555558

@@ -705,6 +708,26 @@ Current scaffold scope:
705708
2. one-time proof consumption per method/path within replay TTL
706709
3. single protected route configuration (expand to route policy map as next step)
707710

711+
## Agent Scaffold
712+
713+
This repo includes an agent-first Stackflow scaffold at
714+
`packages/stackflow-agent/` for deployments that do not run local
715+
`stacks-node`/`stackflow-node`.
716+
717+
It provides:
718+
719+
1. SQLite persistence for tracked pipes and latest signatures
720+
2. AIBTC MCP wallet adapter hooks for `sip018_sign`, `call_contract`, and
721+
read-only `get-pipe`
722+
3. hourly closure watcher (default `60 * 60 * 1000`) that polls tracked pipes
723+
via read-only `get-pipe` and can auto-submit
724+
disputes when a newer beneficial local signature state exists
725+
726+
See:
727+
728+
1. `packages/stackflow-agent/README.md`
729+
2. `server/STACKFLOW_AGENT_DESIGN.md`
730+
708731
Integration tests for the HTTP server are opt-in (they spawn a real process and
709732
bind a local port):
710733

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"init:stackflow": "node scripts/init-stackflow.js",
1010
"build:ui": "node scripts/build-ui.js",
1111
"test": "vitest run",
12+
"test:node-utils": "vitest run -c vitest.node.config.js tests/x402-client.test.ts tests/stackflow-agent.test.ts",
1213
"test:stackflow-node:http": "STACKFLOW_NODE_HTTP_INTEGRATION=1 vitest run tests/stackflow-node-http.integration.test.ts",
1314
"test:report": "vitest run -- --coverage --costs",
1415
"test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\"",

packages/stackflow-agent/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# @stackflow/agent (scaffold)
2+
3+
Simple Stackflow agent runtime for AI agents that do **not** run `stacks-node`
4+
or `stackflow-node`.
5+
6+
Current model:
7+
8+
1. SQLite local state for tracked pipes and latest signatures
9+
2. signer + contract call adapter backed by AIBTC MCP wallet tools
10+
3. hourly chain watcher to detect force-close/force-cancel and dispute
11+
12+
## Runtime Components
13+
14+
1. `AgentStateStore`: SQLite persistence
15+
2. `StackflowAgentService`: pipe tracking + signature state + dispute logic
16+
3. `AibtcWalletAdapter`: wrapper around AIBTC MCP tools
17+
4. `HourlyClosureWatcher`: periodic closure scan (default every hour)
18+
19+
## Example Wiring
20+
21+
```js
22+
import {
23+
AgentStateStore,
24+
AibtcPipeStateSource,
25+
AibtcWalletAdapter,
26+
HourlyClosureWatcher,
27+
StackflowAgentService,
28+
} from "./src/index.js";
29+
30+
const stateStore = new AgentStateStore({
31+
dbFile: "./tmp/stackflow-agent.db",
32+
});
33+
34+
// You provide invokeTool using your MCP client runtime.
35+
const wallet = new AibtcWalletAdapter({
36+
invokeTool: async (toolName, args) => {
37+
// Example:
38+
// return mcpClient.callTool({ name: toolName, arguments: args });
39+
throw new Error("implement invokeTool");
40+
},
41+
});
42+
43+
const agent = new StackflowAgentService({
44+
stateStore,
45+
signer: wallet,
46+
network: "devnet",
47+
disputeOnlyBeneficial: true,
48+
});
49+
50+
const pipeSource = new AibtcPipeStateSource({
51+
walletAdapter: wallet,
52+
contractId: "ST...stackflow",
53+
network: "devnet",
54+
});
55+
56+
const watcher = new HourlyClosureWatcher({
57+
agentService: agent,
58+
// Simpler mode: poll each tracked pipe via read-only `get-pipe`.
59+
getPipeState: (args) => pipeSource.getPipeState(args),
60+
intervalMs: 60 * 60 * 1000, // 1 hour
61+
});
62+
63+
watcher.start();
64+
```
65+
66+
## Core Operations
67+
68+
1. `trackPipe(...)`
69+
2. `recordSignedState(...)`
70+
3. `openPipe(...)` (via wallet `call_contract`)
71+
4. `buildOutgoingTransfer(...)`
72+
5. `validateIncomingTransfer(...)`
73+
6. `acceptIncomingTransfer(...)` (validate + sign + persist)
74+
7. `evaluateClosureForDispute(...)`
75+
8. `disputeClosure(...)`
76+
9. `watcher.runOnce()` or `watcher.start()` for hourly checks
77+
78+
## Notes
79+
80+
1. This scaffold intentionally avoids observer endpoints and local chain node.
81+
2. The watcher interval defaults to one hour; dispute window is still 144 BTC blocks.
82+
3. `HourlyClosureWatcher` supports two sources:
83+
- `getPipeState` (recommended): per-pipe read-only polling (`get-pipe`)
84+
- `listClosureEvents`: event scan mode
85+
4. For production hardening, add alerting, signer balance checks, and idempotency audit logs.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@stackflow/agent",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"main": "./src/index.js",
7+
"exports": {
8+
".": "./src/index.js"
9+
}
10+
}

0 commit comments

Comments
 (0)