@aifinpay/mcp 1.5.3 → 2.0.0-rc.12
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/README.md +116 -69
- package/bin/aifinpay-mcp.js +119 -49
- package/dist/api.d.ts +2 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +6 -0
- package/dist/api.js.map +1 -0
- package/dist/config.d.ts +35 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +63 -0
- package/dist/config.js.map +1 -1
- package/dist/identity.d.ts +9 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +75 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +3 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/dist/safe-fetch.d.ts +2 -0
- package/dist/safe-fetch.d.ts.map +1 -1
- package/dist/safe-fetch.js +76 -17
- package/dist/safe-fetch.js.map +1 -1
- package/dist/server.d.ts +11 -8
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +106 -102
- package/dist/server.js.map +1 -1
- package/dist/tools/agent-address.d.ts.map +1 -1
- package/dist/tools/agent-address.js +6 -27
- package/dist/tools/agent-address.js.map +1 -1
- package/dist/tools/{payable-fetch.d.ts → agent-history.d.ts} +21 -23
- package/dist/tools/agent-history.d.ts.map +1 -0
- package/dist/tools/agent-history.js +73 -0
- package/dist/tools/agent-history.js.map +1 -0
- package/dist/tools/{agent-quote.d.ts → agent-quota.d.ts} +7 -8
- package/dist/tools/agent-quota.d.ts.map +1 -0
- package/dist/tools/agent-quota.js +95 -0
- package/dist/tools/agent-quota.js.map +1 -0
- package/dist/tools/dev-payment-quote.d.ts +39 -0
- package/dist/tools/dev-payment-quote.d.ts.map +1 -0
- package/dist/tools/dev-payment-quote.js +52 -0
- package/dist/tools/dev-payment-quote.js.map +1 -0
- package/dist/tools/{pay-with-split.d.ts → production-control.d.ts} +49 -34
- package/dist/tools/production-control.d.ts.map +1 -0
- package/dist/tools/production-control.js +132 -0
- package/dist/tools/production-control.js.map +1 -0
- package/package.json +7 -21
- package/skills/SKILL.md +143 -0
- package/dist/directory.d.ts +0 -55
- package/dist/directory.d.ts.map +0 -1
- package/dist/directory.js +0 -56
- package/dist/directory.js.map +0 -1
- package/dist/tools/agent-call.d.ts +0 -68
- package/dist/tools/agent-call.d.ts.map +0 -1
- package/dist/tools/agent-call.js +0 -129
- package/dist/tools/agent-call.js.map +0 -1
- package/dist/tools/agent-claim-self.d.ts +0 -66
- package/dist/tools/agent-claim-self.d.ts.map +0 -1
- package/dist/tools/agent-claim-self.js +0 -299
- package/dist/tools/agent-claim-self.js.map +0 -1
- package/dist/tools/agent-quote.d.ts.map +0 -1
- package/dist/tools/agent-quote.js +0 -81
- package/dist/tools/agent-quote.js.map +0 -1
- package/dist/tools/pay-with-split.d.ts.map +0 -1
- package/dist/tools/pay-with-split.js +0 -138
- package/dist/tools/pay-with-split.js.map +0 -1
- package/dist/tools/payable-fetch.d.ts.map +0 -1
- package/dist/tools/payable-fetch.js +0 -135
- package/dist/tools/payable-fetch.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-call.d.ts","sourceRoot":"","sources":["../../src/tools/agent-call.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgD5B;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GAkE9B"}
|
package/dist/tools/agent-call.js
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `agent_call` — unified registry-resolved paid HTTP call.
|
|
3
|
-
*
|
|
4
|
-
* The agent picks a provider by name ("exa", "io-net", "venice", …),
|
|
5
|
-
* the SDK looks up the bridge URL + price from the public AiFinPay
|
|
6
|
-
* registry, negotiates the 402 challenge, settles on Polygon via
|
|
7
|
-
* B2BSplitter.payMatic, retries with proof, and returns the upstream
|
|
8
|
-
* response body.
|
|
9
|
-
*
|
|
10
|
-
* Use this in preference to `payable_fetch` when you have a registered
|
|
11
|
-
* provider name — it auto-routes price, chain, and bridge URL.
|
|
12
|
-
*
|
|
13
|
-
* Requires the EVM address (from `agent_address`) to be funded with POL
|
|
14
|
-
* on Polygon mainnet (gas + payment), or USDC if the provider quotes in
|
|
15
|
-
* stablecoin.
|
|
16
|
-
*/
|
|
17
|
-
export function agentCallTool() {
|
|
18
|
-
return {
|
|
19
|
-
name: "agent_call",
|
|
20
|
-
description: "USE THIS TOOL whenever the user asks to call, pay, query, search via, " +
|
|
21
|
-
"or use any of these AiFinPay-registered paid providers: 'exa' (neural " +
|
|
22
|
-
"web search), 'io-net' (LLM inference, Llama-3.3-70B), 'venice' (image " +
|
|
23
|
-
"generation), or any other provider listed at " +
|
|
24
|
-
"https://aifinpay.io/api/providers. " +
|
|
25
|
-
"DO NOT use WebSearch or WebFetch for these providers — they are paid " +
|
|
26
|
-
"APIs accessible only through this MCP, and a plain web search will " +
|
|
27
|
-
"return public marketing pages instead of the actual API. " +
|
|
28
|
-
"Natural-language triggers that should invoke this tool: 'call exa for X', " +
|
|
29
|
-
"'search exa', 'pay venice to generate Y', 'use io-net to run inference', " +
|
|
30
|
-
"'query exa', 'ask io-net'. Provider name maps to the `provider` argument. " +
|
|
31
|
-
"Body is the provider-specific request shape (e.g. {messages:[...]} for " +
|
|
32
|
-
"io-net inference, {query:'...'} for exa search). Returns the upstream " +
|
|
33
|
-
"response with the Polygon tx hash + Polygonscan link prepended. " +
|
|
34
|
-
"Settlement is automatic — Polygon mainnet, atomic 99/1 split via B2BSplitter.",
|
|
35
|
-
inputSchema: {
|
|
36
|
-
type: "object",
|
|
37
|
-
properties: {
|
|
38
|
-
provider: {
|
|
39
|
-
type: "string",
|
|
40
|
-
description: "Registered provider name. Example: 'io-net', 'exa', 'venice'.",
|
|
41
|
-
},
|
|
42
|
-
body: {
|
|
43
|
-
type: "object",
|
|
44
|
-
description: "Provider-specific request body. Forwarded to the bridge after payment.",
|
|
45
|
-
additionalProperties: true,
|
|
46
|
-
},
|
|
47
|
-
method: {
|
|
48
|
-
type: "string",
|
|
49
|
-
enum: ["GET", "POST"],
|
|
50
|
-
default: "POST",
|
|
51
|
-
description: "HTTP method. Defaults to POST (matches all current providers).",
|
|
52
|
-
},
|
|
53
|
-
cost: {
|
|
54
|
-
type: "number",
|
|
55
|
-
description: "Optional override of the registry-quoted price (USD). Use to enforce a stricter budget cap.",
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
required: ["provider"],
|
|
59
|
-
},
|
|
60
|
-
// Settles a real on-chain payment to an arbitrary registered provider.
|
|
61
|
-
annotations: { readOnlyHint: false, openWorldHint: true, destructiveHint: true },
|
|
62
|
-
outputSchema: { type: "object" },
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
export async function runAgentCall(ctx, args) {
|
|
66
|
-
const provider = args.provider;
|
|
67
|
-
const body = args.body;
|
|
68
|
-
const method = args.method ?? "POST";
|
|
69
|
-
const cost = args.cost;
|
|
70
|
-
if (!provider) {
|
|
71
|
-
return {
|
|
72
|
-
isError: true,
|
|
73
|
-
content: [{ type: "text", text: "`provider` is required (e.g. 'exa', 'io-net')" }],
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
try {
|
|
77
|
-
const resp = await ctx.agent.call({
|
|
78
|
-
provider,
|
|
79
|
-
body,
|
|
80
|
-
method,
|
|
81
|
-
cost,
|
|
82
|
-
});
|
|
83
|
-
if (resp === null) {
|
|
84
|
-
return {
|
|
85
|
-
isError: true,
|
|
86
|
-
content: [{ type: "text", text: "Call skipped — budget cap exceeded (on_limit_exceeded='skip')." }],
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const text = await resp.text();
|
|
90
|
-
let parsed = text;
|
|
91
|
-
try {
|
|
92
|
-
parsed = JSON.parse(text);
|
|
93
|
-
}
|
|
94
|
-
catch { /* keep as text */ }
|
|
95
|
-
// Pull the @internal settlement metadata attached by AiFinPayAgent.call
|
|
96
|
-
// (see unifiedAgent.ts). Surfacing the tx hash here lets the agent show
|
|
97
|
-
// a clickable explorer link in chat without re-querying the chain.
|
|
98
|
-
const meta = resp;
|
|
99
|
-
const txHash = meta.aifinpayTx;
|
|
100
|
-
const txChain = meta.aifinpayChain;
|
|
101
|
-
const txLine = txHash
|
|
102
|
-
? `Paid on ${txChain ?? "polygon"}. Tx: ${txHash} → https://${txChain === "solana" ? "solscan.io/tx" : "polygonscan.com/tx"}/${txHash}\n\n`
|
|
103
|
-
: "";
|
|
104
|
-
const bodyText = typeof parsed === "string"
|
|
105
|
-
? parsed
|
|
106
|
-
: JSON.stringify({ status: resp.status, body: parsed }, null, 2);
|
|
107
|
-
return {
|
|
108
|
-
content: [
|
|
109
|
-
{
|
|
110
|
-
type: "text",
|
|
111
|
-
text: txLine + bodyText,
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
catch (err) {
|
|
117
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
118
|
-
const hint = message.toLowerCase().includes("budget")
|
|
119
|
-
? "Tip: increase the per-call cost cap or use `agent_quote` to preview before paying."
|
|
120
|
-
: message.toLowerCase().includes("revert") || message.toLowerCase().includes("insufficient")
|
|
121
|
-
? `Tip: ensure the EVM address ${ctx.agent.evmAddress} holds enough POL on Polygon for gas + payment.`
|
|
122
|
-
: `Provider may be misconfigured. Check https://aifinpay.io/api/providers.`;
|
|
123
|
-
return {
|
|
124
|
-
isError: true,
|
|
125
|
-
content: [{ type: "text", text: `agent_call failed: ${message}\n\n${hint}` }],
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
//# sourceMappingURL=agent-call.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-call.js","sourceRoot":"","sources":["../../src/tools/agent-call.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import type { ToolContext } from "../server.js";
|
|
2
|
-
/**
|
|
3
|
-
* `agent_claim_self` — agent attaches itself to a user's AiFinPay account
|
|
4
|
-
* autonomously by signing a claim challenge with its own key.
|
|
5
|
-
*
|
|
6
|
-
* Flow (executed inside the tool, no copy-paste between UIs):
|
|
7
|
-
* 1. User signs in to /login on aifinpay.io → gets a magic-link
|
|
8
|
-
* email with URL like `https://aifinpay.io/api/auth/verify?token=…`
|
|
9
|
-
* 2. User pastes that URL to the agent: "claim yourself on my account
|
|
10
|
-
* using this magic link"
|
|
11
|
-
* 3. Agent calls this tool with the magic_link_url
|
|
12
|
-
* 4. Tool hits the magic link → server issues session cookie
|
|
13
|
-
* 5. Tool POSTs to /api/me/agents/challenge with the agent's EVM address
|
|
14
|
-
* 6. Tool signs the returned message with the agent's EVM key (EIP-191)
|
|
15
|
-
* 7. Tool POSTs to /api/me/agents/claim → server verifies signature →
|
|
16
|
-
* agent attached to user's watchlist
|
|
17
|
-
*
|
|
18
|
-
* Optional `label` field gives the agent a friendly name in the user's UI.
|
|
19
|
-
*
|
|
20
|
-
* Security model:
|
|
21
|
-
* - Magic-link URL is one-shot, 15-min TTL, identifies the user
|
|
22
|
-
* - Signature proves the agent holds the EVM private key
|
|
23
|
-
* - Combination: "this user OWNS this agent". Either alone is
|
|
24
|
-
* insufficient (signature alone can't pick an account; magic link
|
|
25
|
-
* alone can't prove key control).
|
|
26
|
-
*/
|
|
27
|
-
export declare function agentClaimSelfTool(): {
|
|
28
|
-
name: string;
|
|
29
|
-
description: string;
|
|
30
|
-
inputSchema: {
|
|
31
|
-
type: string;
|
|
32
|
-
properties: {
|
|
33
|
-
magic_link_url: {
|
|
34
|
-
type: string;
|
|
35
|
-
description: string;
|
|
36
|
-
};
|
|
37
|
-
label: {
|
|
38
|
-
type: string;
|
|
39
|
-
description: string;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
required: string[];
|
|
43
|
-
};
|
|
44
|
-
annotations: {
|
|
45
|
-
readOnlyHint: boolean;
|
|
46
|
-
openWorldHint: boolean;
|
|
47
|
-
destructiveHint: boolean;
|
|
48
|
-
};
|
|
49
|
-
outputSchema: {
|
|
50
|
-
type: string;
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
export declare function runAgentClaimSelf(ctx: ToolContext, args: Record<string, unknown>): Promise<{
|
|
54
|
-
isError: boolean;
|
|
55
|
-
content: {
|
|
56
|
-
type: string;
|
|
57
|
-
text: string;
|
|
58
|
-
}[];
|
|
59
|
-
} | {
|
|
60
|
-
content: {
|
|
61
|
-
type: string;
|
|
62
|
-
text: string;
|
|
63
|
-
}[];
|
|
64
|
-
isError?: undefined;
|
|
65
|
-
}>;
|
|
66
|
-
//# sourceMappingURL=agent-claim-self.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-claim-self.d.ts","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;EAgCjC;AAiED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GA4L9B"}
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `agent_claim_self` — agent attaches itself to a user's AiFinPay account
|
|
3
|
-
* autonomously by signing a claim challenge with its own key.
|
|
4
|
-
*
|
|
5
|
-
* Flow (executed inside the tool, no copy-paste between UIs):
|
|
6
|
-
* 1. User signs in to /login on aifinpay.io → gets a magic-link
|
|
7
|
-
* email with URL like `https://aifinpay.io/api/auth/verify?token=…`
|
|
8
|
-
* 2. User pastes that URL to the agent: "claim yourself on my account
|
|
9
|
-
* using this magic link"
|
|
10
|
-
* 3. Agent calls this tool with the magic_link_url
|
|
11
|
-
* 4. Tool hits the magic link → server issues session cookie
|
|
12
|
-
* 5. Tool POSTs to /api/me/agents/challenge with the agent's EVM address
|
|
13
|
-
* 6. Tool signs the returned message with the agent's EVM key (EIP-191)
|
|
14
|
-
* 7. Tool POSTs to /api/me/agents/claim → server verifies signature →
|
|
15
|
-
* agent attached to user's watchlist
|
|
16
|
-
*
|
|
17
|
-
* Optional `label` field gives the agent a friendly name in the user's UI.
|
|
18
|
-
*
|
|
19
|
-
* Security model:
|
|
20
|
-
* - Magic-link URL is one-shot, 15-min TTL, identifies the user
|
|
21
|
-
* - Signature proves the agent holds the EVM private key
|
|
22
|
-
* - Combination: "this user OWNS this agent". Either alone is
|
|
23
|
-
* insufficient (signature alone can't pick an account; magic link
|
|
24
|
-
* alone can't prove key control).
|
|
25
|
-
*/
|
|
26
|
-
export function agentClaimSelfTool() {
|
|
27
|
-
return {
|
|
28
|
-
name: "agent_claim_self",
|
|
29
|
-
description: "Attach this agent to a user's AiFinPay account autonomously. " +
|
|
30
|
-
"Requires a magic-link URL the user got after signing in at " +
|
|
31
|
-
"https://aifinpay.io/login. The tool will use the link to " +
|
|
32
|
-
"establish a session, request a claim challenge for this agent's " +
|
|
33
|
-
"EVM address, sign it with the agent's key, and submit the proof. " +
|
|
34
|
-
"After this completes, the user's /me page lists this agent and " +
|
|
35
|
-
"they can view its activity at /agents/<evm-address>.",
|
|
36
|
-
inputSchema: {
|
|
37
|
-
type: "object",
|
|
38
|
-
properties: {
|
|
39
|
-
magic_link_url: {
|
|
40
|
-
type: "string",
|
|
41
|
-
description: "The URL the user received in the sign-in email. Looks like " +
|
|
42
|
-
"https://aifinpay.io/api/auth/verify?token=… — one-shot, " +
|
|
43
|
-
"expires 15 minutes after the user requested it.",
|
|
44
|
-
},
|
|
45
|
-
label: {
|
|
46
|
-
type: "string",
|
|
47
|
-
description: "Optional human-friendly label (e.g. 'claude-research-bot').",
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
required: ["magic_link_url"],
|
|
51
|
-
},
|
|
52
|
-
// Binds the agent to a user account (bounded to AiFinPay; not fund-moving).
|
|
53
|
-
annotations: { readOnlyHint: false, openWorldHint: false, destructiveHint: false },
|
|
54
|
-
outputSchema: { type: "object" },
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// ── Who this tool may talk to, and what it may sign ─────────────────────────
|
|
58
|
-
//
|
|
59
|
-
// This tool took the API host out of the URL it was handed, checked only that
|
|
60
|
-
// the string contained "/api/auth/verify?token=", fetched a challenge from that
|
|
61
|
-
// host, and signed whatever came back with the agent's EVM key AND its Solana
|
|
62
|
-
// secret — then posted both signatures back to the same host.
|
|
63
|
-
//
|
|
64
|
-
// That is a signing oracle with an SSRF in front of it. Anyone who can put a
|
|
65
|
-
// URL in front of the agent, prompt injection included, could name their own
|
|
66
|
-
// server, choose the text to be signed, and collect the signatures. Naming
|
|
67
|
-
// 127.0.0.1 or 169.254.169.254 instead reached whatever the host could reach.
|
|
68
|
-
//
|
|
69
|
-
// Two independent barriers below, because either alone is one mistake away
|
|
70
|
-
// from failing.
|
|
71
|
-
const DEFAULT_CLAIM_ORIGINS = [
|
|
72
|
-
"https://aifinpay.io",
|
|
73
|
-
"https://www.aifinpay.io",
|
|
74
|
-
"https://dash.aifinpay.io",
|
|
75
|
-
"https://api.aifinpay.io",
|
|
76
|
-
];
|
|
77
|
-
/** Origins this tool will contact. Override deliberately, for staging. */
|
|
78
|
-
function allowedOrigins() {
|
|
79
|
-
const raw = process.env.AIFINPAY_CLAIM_ORIGINS;
|
|
80
|
-
if (!raw)
|
|
81
|
-
return DEFAULT_CLAIM_ORIGINS;
|
|
82
|
-
return raw.split(",").map((o) => o.trim().replace(/\/+$/, "")).filter(Boolean);
|
|
83
|
-
}
|
|
84
|
-
/** null when the URL may be used; otherwise the reason it may not. */
|
|
85
|
-
function originRefusal(url) {
|
|
86
|
-
const origin = `${url.protocol}//${url.host}`;
|
|
87
|
-
const allowed = allowedOrigins();
|
|
88
|
-
if (!allowed.includes(origin)) {
|
|
89
|
-
return `refusing to use ${origin}: not an allowed AiFinPay origin. ` +
|
|
90
|
-
`Allowed: ${allowed.join(", ")}. Set AIFINPAY_CLAIM_ORIGINS to add one deliberately.`;
|
|
91
|
-
}
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* The only shape this agent will sign here.
|
|
96
|
-
*
|
|
97
|
-
* The server builds `AiFinPay-claim:<chain>:<address>:<nonce>` and nothing
|
|
98
|
-
* else. Checking that locally means even an allowed origin — compromised, or
|
|
99
|
-
* simply the wrong one — cannot choose the bytes. The address must be this
|
|
100
|
-
* agent's own, so a signature obtained here says only "I am this agent", which
|
|
101
|
-
* is the whole purpose of the exchange.
|
|
102
|
-
*
|
|
103
|
-
* EVM addresses compare case-insensitively because the server lowercases them.
|
|
104
|
-
* base58 is case-significant and compares exactly.
|
|
105
|
-
*/
|
|
106
|
-
function challengeIsWellFormed(message, address) {
|
|
107
|
-
if (typeof message !== "string")
|
|
108
|
-
return false;
|
|
109
|
-
const chain = address.startsWith("0x") ? "polygon" : "solana";
|
|
110
|
-
const prefix = `AiFinPay-claim:${chain}:${address}:`;
|
|
111
|
-
const matches = chain === "polygon"
|
|
112
|
-
? message.toLowerCase().startsWith(prefix.toLowerCase())
|
|
113
|
-
: message.startsWith(prefix);
|
|
114
|
-
if (!matches)
|
|
115
|
-
return false;
|
|
116
|
-
return /^[0-9a-f]{32}$/.test(message.slice(prefix.length));
|
|
117
|
-
}
|
|
118
|
-
export async function runAgentClaimSelf(ctx, args) {
|
|
119
|
-
const magicLinkUrl = typeof args.magic_link_url === "string" ? args.magic_link_url : "";
|
|
120
|
-
const label = typeof args.label === "string" ? args.label : null;
|
|
121
|
-
if (!magicLinkUrl || !magicLinkUrl.includes("/api/auth/verify?token=")) {
|
|
122
|
-
return {
|
|
123
|
-
isError: true,
|
|
124
|
-
content: [{ type: "text", text: "magic_link_url required — should look like https://aifinpay.io/api/auth/verify?token=…" }],
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
// Derive API base from the magic link itself so demo can run against
|
|
128
|
-
// staging / localhost without extra config.
|
|
129
|
-
let apiBase;
|
|
130
|
-
try {
|
|
131
|
-
const u = new URL(magicLinkUrl);
|
|
132
|
-
const refusal = originRefusal(u);
|
|
133
|
-
if (refusal) {
|
|
134
|
-
return { isError: true, content: [{ type: "text", text: refusal }] };
|
|
135
|
-
}
|
|
136
|
-
apiBase = `${u.protocol}//${u.host}`;
|
|
137
|
-
}
|
|
138
|
-
catch {
|
|
139
|
-
return {
|
|
140
|
-
isError: true,
|
|
141
|
-
content: [{ type: "text", text: "magic_link_url is not a valid URL" }],
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
// ── 1. Establish session by hitting the magic link ─────────────────
|
|
145
|
-
let setCookie = null;
|
|
146
|
-
try {
|
|
147
|
-
const res = await fetch(magicLinkUrl, { redirect: "manual" });
|
|
148
|
-
setCookie = res.headers.get("set-cookie");
|
|
149
|
-
if (!setCookie) {
|
|
150
|
-
return {
|
|
151
|
-
isError: true,
|
|
152
|
-
content: [{ type: "text", text: `Magic link did not return a session cookie (HTTP ${res.status}). Link may be expired or already used.` }],
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
157
|
-
return {
|
|
158
|
-
isError: true,
|
|
159
|
-
content: [{ type: "text", text: `Failed to fetch magic link: ${e.message}` }],
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
// Some setups split multiple cookies; grab the session one we care about.
|
|
163
|
-
const cookieHeader = setCookie.split(",").map((c) => c.trim().split(";")[0]).join("; ");
|
|
164
|
-
// Claim both chains (EVM + Solana). Each is its own challenge + sig.
|
|
165
|
-
// We try Polygon first because that's where live bridges settle today;
|
|
166
|
-
// Solana side is best-effort — if anything fails we still consider the
|
|
167
|
-
// overall claim successful as long as Polygon went through.
|
|
168
|
-
const evmAddr = ctx.agent.evmAddress;
|
|
169
|
-
const solAddr = ctx.agent.solanaAddress;
|
|
170
|
-
const innerAny = ctx.agent.inner;
|
|
171
|
-
const solSecret = innerAny.secretKey; // tweetnacl 64-byte secretKey
|
|
172
|
-
async function claimOne(address, sigFn) {
|
|
173
|
-
// 1) challenge
|
|
174
|
-
const cr = await fetch(`${apiBase}/api/me/agents/challenge`, {
|
|
175
|
-
method: "POST",
|
|
176
|
-
redirect: "error", // a redirect would leave the origin we vetted
|
|
177
|
-
headers: { "content-type": "application/json", cookie: cookieHeader },
|
|
178
|
-
body: JSON.stringify({ address }),
|
|
179
|
-
});
|
|
180
|
-
const cj = (await cr.json());
|
|
181
|
-
if (!cr.ok || !cj.challenge_id || !cj.message) {
|
|
182
|
-
return { ok: false, reason: cj.error || `challenge HTTP ${cr.status}` };
|
|
183
|
-
}
|
|
184
|
-
// 2) sign — but only the one shape this exchange is defined to produce.
|
|
185
|
-
if (!challengeIsWellFormed(cj.message, address)) {
|
|
186
|
-
return {
|
|
187
|
-
ok: false,
|
|
188
|
-
reason: "challenge is not a well-formed AiFinPay claim for this agent — refusing to sign it",
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
let sigPayload;
|
|
192
|
-
try {
|
|
193
|
-
sigPayload = await sigFn(cj.message);
|
|
194
|
-
}
|
|
195
|
-
catch (e) {
|
|
196
|
-
return { ok: false, reason: `sign: ${e.message}` };
|
|
197
|
-
}
|
|
198
|
-
// 3) submit
|
|
199
|
-
const sr = await fetch(`${apiBase}/api/me/agents/claim`, {
|
|
200
|
-
method: "POST",
|
|
201
|
-
redirect: "error", // a redirect would leave the origin we vetted
|
|
202
|
-
headers: { "content-type": "application/json", cookie: cookieHeader },
|
|
203
|
-
body: JSON.stringify({ challenge_id: cj.challenge_id, label, ...sigPayload }),
|
|
204
|
-
});
|
|
205
|
-
const sj = (await sr.json());
|
|
206
|
-
if (!sr.ok) {
|
|
207
|
-
return { ok: false, reason: sj.error + (sj.reason ? ` (${sj.reason})` : "") };
|
|
208
|
-
}
|
|
209
|
-
return { ok: true };
|
|
210
|
-
}
|
|
211
|
-
// ── 2. Claim Polygon EVM ───────────────────────────────────────────
|
|
212
|
-
const polRes = await claimOne(evmAddr, async (msg) => ({
|
|
213
|
-
signature: await ctx.agent.evmAccount.signMessage({ message: msg }),
|
|
214
|
-
}));
|
|
215
|
-
if (!polRes.ok) {
|
|
216
|
-
return {
|
|
217
|
-
isError: true,
|
|
218
|
-
content: [{ type: "text", text: `Polygon claim failed: ${polRes.reason}` }],
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
// ── 3. Claim Solana (best-effort) ──────────────────────────────────
|
|
222
|
-
let solRes;
|
|
223
|
-
try {
|
|
224
|
-
const nacl = (await import("tweetnacl")).default;
|
|
225
|
-
const bs58 = (await import("bs58")).default;
|
|
226
|
-
solRes = await claimOne(solAddr, async (msg) => {
|
|
227
|
-
const sig = nacl.sign.detached(Buffer.from(msg, "utf8"), solSecret);
|
|
228
|
-
return { signature_base58: bs58.encode(sig) };
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
catch (e) {
|
|
232
|
-
solRes = { ok: false, reason: `solana_signer_unavailable: ${e.message}` };
|
|
233
|
-
}
|
|
234
|
-
// ── 4. Balance check (best-effort) — drives funded-vs-unfunded copy ─
|
|
235
|
-
// Never block the claim flow on a balance check; if the RPC is down or
|
|
236
|
-
// balance() throws, fall back to the standard funding recommendation.
|
|
237
|
-
let polygonUsdc = 0;
|
|
238
|
-
let solanaUsdc = 0;
|
|
239
|
-
try {
|
|
240
|
-
const bal = await ctx.agent.balance();
|
|
241
|
-
polygonUsdc = bal.chains.polygon.usdc ?? 0;
|
|
242
|
-
solanaUsdc = bal.chains.solana.usdc ?? 0;
|
|
243
|
-
}
|
|
244
|
-
catch {
|
|
245
|
-
/* swallow — keep funding_recommendation as-is */
|
|
246
|
-
}
|
|
247
|
-
// ── 5. Report ──────────────────────────────────────────────────────
|
|
248
|
-
try {
|
|
249
|
-
// Dashboard URLs live at dashboard.aifinpay.io regardless of
|
|
250
|
-
// which host the user used for magic-link sign-in. apiBase is correct
|
|
251
|
-
// only for /me (which lives at whichever host the user signed in via).
|
|
252
|
-
const DASHBOARD_BASE = "https://dashboard.aifinpay.io";
|
|
253
|
-
// Funded threshold: 0.10 USDC (~4 io-net calls). Below this we still
|
|
254
|
-
// show the funding tip; at-or-above we show a "Funded" status so the
|
|
255
|
-
// agent doesn't tell the user to send money they already sent.
|
|
256
|
-
const FUNDED_USDC_THRESHOLD = 0.10;
|
|
257
|
-
const polygonFunded = polygonUsdc >= FUNDED_USDC_THRESHOLD;
|
|
258
|
-
const fundingFields = polygonFunded
|
|
259
|
-
? {
|
|
260
|
-
funding_status: `Funded — $${polygonUsdc.toFixed(2)} USDC available on Polygon`,
|
|
261
|
-
}
|
|
262
|
-
: {
|
|
263
|
-
// Live bridges (io.net, Exa, Venice) settle on Polygon — fund
|
|
264
|
-
// the Polygon address with USDC for autonomous calls today.
|
|
265
|
-
// Solana is claimed for visibility; SOL-native settlement is
|
|
266
|
-
// available on bridges that advertise pay_solana in their 402.
|
|
267
|
-
funding_recommendation: `Send USDC on Polygon to ${evmAddr} (~0.5 USDC ≈ 20 calls). Optionally fund the Solana address with SOL to use Solana-native bridges.`,
|
|
268
|
-
};
|
|
269
|
-
// Surface Solana USDC status when balance() exposes a non-zero value;
|
|
270
|
-
// schema doesn't currently include solana.usdc but future-proof here.
|
|
271
|
-
if (solanaUsdc >= FUNDED_USDC_THRESHOLD) {
|
|
272
|
-
fundingFields.funding_status_solana = `Funded — $${solanaUsdc.toFixed(2)} USDC available on Solana`;
|
|
273
|
-
}
|
|
274
|
-
return {
|
|
275
|
-
content: [
|
|
276
|
-
{
|
|
277
|
-
type: "text",
|
|
278
|
-
text: JSON.stringify({
|
|
279
|
-
ok: true,
|
|
280
|
-
polygon_address: evmAddr,
|
|
281
|
-
polygon_claim: "ok",
|
|
282
|
-
solana_address: solAddr,
|
|
283
|
-
solana_claim: solRes.ok ? "ok" : `skipped (${solRes.reason})`,
|
|
284
|
-
label: label || null,
|
|
285
|
-
...fundingFields,
|
|
286
|
-
next: `Visit ${DASHBOARD_BASE}/agents/${evmAddr} (Polygon view) or ${DASHBOARD_BASE}/agents/${solAddr} (Solana view). Watchlist: ${apiBase}/me.`,
|
|
287
|
-
}, null, 2),
|
|
288
|
-
},
|
|
289
|
-
],
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
catch (e) {
|
|
293
|
-
return {
|
|
294
|
-
isError: true,
|
|
295
|
-
content: [{ type: "text", text: `Claim POST failed: ${e.message}` }],
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
//# sourceMappingURL=agent-claim-self.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-claim-self.js","sourceRoot":"","sources":["../../src/tools/agent-claim-self.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-quote.d.ts","sourceRoot":"","sources":["../../src/tools/agent-quote.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;EAuB7B;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;GA2D9B"}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { detectFacilitator } from "@aifinpay/agent";
|
|
2
|
-
export function agentQuoteTool() {
|
|
3
|
-
return {
|
|
4
|
-
name: "agent_quote",
|
|
5
|
-
description: "Inspect a 402 challenge for a URL WITHOUT paying. Returns the detected " +
|
|
6
|
-
"facilitator flavor and the merchant's quoted amount + fee preview. " +
|
|
7
|
-
"Use before payable_fetch to decide whether the cost is acceptable.",
|
|
8
|
-
inputSchema: {
|
|
9
|
-
type: "object",
|
|
10
|
-
properties: {
|
|
11
|
-
url: { type: "string", description: "Target URL (https)." },
|
|
12
|
-
method: {
|
|
13
|
-
type: "string",
|
|
14
|
-
enum: ["GET", "POST"],
|
|
15
|
-
default: "GET",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
required: ["url"],
|
|
19
|
-
},
|
|
20
|
-
// Read-only probe, but reaches arbitrary external URLs → openWorldHint true.
|
|
21
|
-
annotations: { readOnlyHint: true, openWorldHint: true, destructiveHint: false },
|
|
22
|
-
outputSchema: { type: "object" },
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export async function runAgentQuote(ctx, args) {
|
|
26
|
-
const url = String(args.url ?? "");
|
|
27
|
-
if (!url)
|
|
28
|
-
return errorResult("missing required arg: url");
|
|
29
|
-
const method = String(args.method ?? "GET").toUpperCase();
|
|
30
|
-
const resp = await ctx.agent.inner.fetchImpl(url, { method });
|
|
31
|
-
if (resp.status !== 402) {
|
|
32
|
-
return {
|
|
33
|
-
content: [
|
|
34
|
-
{
|
|
35
|
-
type: "text",
|
|
36
|
-
text: JSON.stringify({
|
|
37
|
-
status: resp.status,
|
|
38
|
-
note: resp.status === 200
|
|
39
|
-
? "no payment required — you can hit this without paying"
|
|
40
|
-
: `unexpected status ${resp.status} on initial probe`,
|
|
41
|
-
}, null, 2),
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
try {
|
|
47
|
-
const facilitator = await detectFacilitator(resp);
|
|
48
|
-
let bodyPreview = null;
|
|
49
|
-
try {
|
|
50
|
-
bodyPreview = await resp.clone().json();
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
bodyPreview = (await resp.clone().text()).slice(0, 500);
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
content: [
|
|
57
|
-
{
|
|
58
|
-
type: "text",
|
|
59
|
-
text: JSON.stringify({
|
|
60
|
-
facilitator: facilitator.name,
|
|
61
|
-
status: 402,
|
|
62
|
-
note: "fee-on-top engine not yet wired — quote shows merchant terms only. " +
|
|
63
|
-
"AiFinPay fee will be added on top at payment time.",
|
|
64
|
-
merchant_terms: bodyPreview,
|
|
65
|
-
}, null, 2),
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
catch (e) {
|
|
71
|
-
const err = e;
|
|
72
|
-
return errorResult(`could not detect facilitator: ${err.message}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function errorResult(...lines) {
|
|
76
|
-
return {
|
|
77
|
-
isError: true,
|
|
78
|
-
content: lines.map((line) => ({ type: "text", text: line })),
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
//# sourceMappingURL=agent-quote.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent-quote.js","sourceRoot":"","sources":["../../src/tools/agent-quote.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pay-with-split.d.ts","sourceRoot":"","sources":["../../src/tools/pay-with-split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAahD,wBAAgB,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8C/B;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GAsC9B;AAED,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;EAuB7B;AAED,wBAAsB,aAAa,CACjC,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;GAoB9B"}
|