@chainpearc/ai-tools 0.0.0-stage → 0.3.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/README.md +87 -2
- package/dist/index.d.ts +88 -0
- package/dist/index.js +71 -0
- package/dist/index.js.map +1 -0
- package/dist/langchain.d.ts +62 -0
- package/dist/langchain.js +90 -0
- package/dist/langchain.js.map +1 -0
- package/dist/vercel.d.ts +26 -0
- package/dist/vercel.js +85 -0
- package/dist/vercel.js.map +1 -0
- package/package.json +78 -4
package/README.md
CHANGED
|
@@ -1,3 +1,88 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @chainpearc/ai-tools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@chainpearc/ai-tools)
|
|
4
|
+
|
|
5
|
+
> **Use Arc testnet for now.** It is the default. ChainPe has not been tested with real USDC on Arc mainnet.
|
|
6
|
+
|
|
7
|
+
**Drop-in ChainPe tools for AI agents** — let any Vercel AI SDK or LangChain agent
|
|
8
|
+
**discover, pay for, and rate** HTTP APIs and other agents per request in USDC on
|
|
9
|
+
Arc. Thin adapters over [`@chainpearc/sdk`](../chainpe-sdk).
|
|
10
|
+
|
|
11
|
+
Two tools per framework:
|
|
12
|
+
|
|
13
|
+
- **`chainpeFetch` / `chainpe_fetch`** — call a URL; if it returns `402 Payment
|
|
14
|
+
Required`, pay it automatically in USDC and return the result.
|
|
15
|
+
- **`discoverService` / `discover_service`** — search Circle's Discovery API and
|
|
16
|
+
ChainPe's on-chain listings, ranked by ERC-8004 reputation.
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @chainpearc/ai-tools @chainpearc/sdk
|
|
20
|
+
# plus your framework: `ai` (Vercel AI SDK) or `@langchain/core`
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Vercel AI SDK
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { generateText, stepCountIs } from 'ai'
|
|
27
|
+
import { anthropic } from '@ai-sdk/anthropic'
|
|
28
|
+
import { createChainPeTools } from '@chainpearc/ai-tools/vercel'
|
|
29
|
+
|
|
30
|
+
const tools = createChainPeTools({
|
|
31
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
32
|
+
autoFeedback: true // leave on-chain reputation after each paid call
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const { text } = await generateText({
|
|
36
|
+
model: anthropic('claude-opus-4-8'),
|
|
37
|
+
tools,
|
|
38
|
+
stopWhen: stepCountIs(8),
|
|
39
|
+
prompt: 'Find a summarizer agent on ChainPe and summarize today\'s top AI news.'
|
|
40
|
+
})
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## LangChain
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { ChatAnthropic } from '@langchain/anthropic'
|
|
47
|
+
import { createReactAgent } from '@langchain/langgraph/prebuilt'
|
|
48
|
+
import { createChainPeLangChainTools } from '@chainpearc/ai-tools/langchain'
|
|
49
|
+
|
|
50
|
+
const { chainpeFetchTool, discoverServiceTool } = createChainPeLangChainTools({
|
|
51
|
+
privateKey: process.env.PRIVATE_KEY!,
|
|
52
|
+
autoFeedback: true
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const agent = createReactAgent({
|
|
56
|
+
llm: new ChatAnthropic({ model: 'claude-opus-4-8' }),
|
|
57
|
+
tools: [discoverServiceTool, chainpeFetchTool]
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Options
|
|
62
|
+
|
|
63
|
+
`createChainPeTools(options)` / `createChainPeLangChainTools(options)` take the same
|
|
64
|
+
options as [`new ChainPe(...)`](../chainpe-sdk#api) — `privateKey`, `network`,
|
|
65
|
+
`rails?`, `accountsAddress?`, `reputationRegistry?`, `maxPerCall?`, `autoFeedback?` — or a
|
|
66
|
+
pre-built client via `{ client }`:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { ChainPe } from '@chainpearc/sdk'
|
|
70
|
+
const client = new ChainPe({ privateKey })
|
|
71
|
+
const tools = createChainPeTools({ client })
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Custom frameworks
|
|
75
|
+
|
|
76
|
+
The framework-agnostic core is exported from the package root, so you can wire the
|
|
77
|
+
same logic into any tool-calling runtime:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { fetchInputSchema, runFetch, getClient } from '@chainpearc/ai-tools'
|
|
81
|
+
|
|
82
|
+
const client = getClient({ privateKey })
|
|
83
|
+
const result = await runFetch(client, { url: 'https://api.example.com/paid' })
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ChainPeOptions, ChainPe } from '@chainpearc/sdk';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Framework-agnostic core for the ChainPe agent tools.
|
|
6
|
+
*
|
|
7
|
+
* Both the Vercel AI SDK adapter (`./vercel`) and the LangChain adapter
|
|
8
|
+
* (`./langchain`) are thin wrappers over the `runFetch` / `runDiscover`
|
|
9
|
+
* functions here, which in turn wrap `@chainpearc/sdk`. The input schemas and
|
|
10
|
+
* serializable return shapes live here so the two adapters stay identical.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Either SDK constructor options, or a pre-built {@link ChainPe} instance. */
|
|
14
|
+
type ChainPeToolOptions = ChainPeOptions | {
|
|
15
|
+
client: ChainPe;
|
|
16
|
+
};
|
|
17
|
+
declare function getClient(options: ChainPeToolOptions): ChainPe;
|
|
18
|
+
declare const fetchInputSchema: z.ZodObject<{
|
|
19
|
+
url: z.ZodString;
|
|
20
|
+
method: z.ZodOptional<z.ZodEnum<["GET", "POST", "PUT", "DELETE", "PATCH"]>>;
|
|
21
|
+
headers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
22
|
+
body: z.ZodOptional<z.ZodString>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
url: string;
|
|
25
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
26
|
+
headers?: Record<string, string> | undefined;
|
|
27
|
+
body?: string | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
url: string;
|
|
30
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
31
|
+
headers?: Record<string, string> | undefined;
|
|
32
|
+
body?: string | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
declare const discoverInputSchema: z.ZodObject<{
|
|
35
|
+
query: z.ZodOptional<z.ZodString>;
|
|
36
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
37
|
+
maxPrice: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
query?: string | undefined;
|
|
40
|
+
tags?: string[] | undefined;
|
|
41
|
+
maxPrice?: string | undefined;
|
|
42
|
+
}, {
|
|
43
|
+
query?: string | undefined;
|
|
44
|
+
tags?: string[] | undefined;
|
|
45
|
+
maxPrice?: string | undefined;
|
|
46
|
+
}>;
|
|
47
|
+
type FetchInput = z.infer<typeof fetchInputSchema>;
|
|
48
|
+
type DiscoverInput = z.infer<typeof discoverInputSchema>;
|
|
49
|
+
interface FetchResult {
|
|
50
|
+
status: number;
|
|
51
|
+
ok: boolean;
|
|
52
|
+
/** Parsed response body (object for JSON, string otherwise). */
|
|
53
|
+
data: unknown;
|
|
54
|
+
/** Present when a USDC payment was made + settled. */
|
|
55
|
+
payment?: {
|
|
56
|
+
amount: string;
|
|
57
|
+
recipient: string;
|
|
58
|
+
network: string;
|
|
59
|
+
rail: string;
|
|
60
|
+
txHash?: string;
|
|
61
|
+
transferId?: string;
|
|
62
|
+
};
|
|
63
|
+
/** Present when ERC-8004 feedback was posted (autoFeedback). */
|
|
64
|
+
reputation?: {
|
|
65
|
+
agentId: string;
|
|
66
|
+
score: number;
|
|
67
|
+
txHash: string;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
interface DiscoverResultItem {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
endpoint: string;
|
|
74
|
+
pricePerRequest: string;
|
|
75
|
+
tags: string[];
|
|
76
|
+
walletAddress: string;
|
|
77
|
+
agentId?: string;
|
|
78
|
+
/** Aggregate ERC-8004 score (0–100) or null when unrated. */
|
|
79
|
+
reputationScore: number | null;
|
|
80
|
+
/** Number of distinct clients that left feedback. */
|
|
81
|
+
reputationCount: number;
|
|
82
|
+
}
|
|
83
|
+
declare const FETCH_TOOL_DESCRIPTION: string;
|
|
84
|
+
declare const DISCOVER_TOOL_DESCRIPTION: string;
|
|
85
|
+
declare function runFetch(client: ChainPe, input: FetchInput): Promise<FetchResult>;
|
|
86
|
+
declare function runDiscover(client: ChainPe, input: DiscoverInput): Promise<DiscoverResultItem[]>;
|
|
87
|
+
|
|
88
|
+
export { type ChainPeToolOptions, DISCOVER_TOOL_DESCRIPTION, type DiscoverInput, type DiscoverResultItem, FETCH_TOOL_DESCRIPTION, type FetchInput, type FetchResult, discoverInputSchema, fetchInputSchema, getClient, runDiscover, runFetch };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/core.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { ChainPe } from "@chainpearc/sdk";
|
|
4
|
+
function getClient(options) {
|
|
5
|
+
if ("client" in options) return options.client;
|
|
6
|
+
return new ChainPe(options);
|
|
7
|
+
}
|
|
8
|
+
var fetchInputSchema = z.object({
|
|
9
|
+
url: z.string().url().describe(
|
|
10
|
+
"The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically."
|
|
11
|
+
),
|
|
12
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().describe("HTTP method (default GET)."),
|
|
13
|
+
headers: z.record(z.string()).optional().describe("Optional request headers."),
|
|
14
|
+
body: z.string().optional().describe("Optional request body, as a string (e.g. a JSON payload).")
|
|
15
|
+
});
|
|
16
|
+
var discoverInputSchema = z.object({
|
|
17
|
+
query: z.string().optional().describe("Free-text search over service name, description, and tags."),
|
|
18
|
+
tags: z.array(z.string()).optional().describe("Filter by tags."),
|
|
19
|
+
maxPrice: z.string().optional().describe('Maximum price per request, in USDC (e.g. "0.05").')
|
|
20
|
+
});
|
|
21
|
+
var FETCH_TOOL_DESCRIPTION = 'Fetch a URL, automatically paying any x402 "402 Payment Required" response in USDC on Arc. Use this to call paid HTTP APIs or hire paid AI agents. Returns the response body plus payment + reputation details.';
|
|
22
|
+
var DISCOVER_TOOL_DESCRIPTION = "Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, ranked by ERC-8004 reputation (best first). Returns each service's endpoint, price, and reputation so you can pick one before paying.";
|
|
23
|
+
async function runFetch(client, input) {
|
|
24
|
+
const res = await client.pay(input.url, {
|
|
25
|
+
method: input.method,
|
|
26
|
+
headers: input.headers,
|
|
27
|
+
body: input.body
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
status: res.status,
|
|
31
|
+
ok: res.ok,
|
|
32
|
+
data: res.data,
|
|
33
|
+
payment: res.payment ? {
|
|
34
|
+
amount: res.payment.amount,
|
|
35
|
+
recipient: res.payment.recipient,
|
|
36
|
+
network: res.payment.network,
|
|
37
|
+
rail: res.payment.rail,
|
|
38
|
+
txHash: res.payment.txHash,
|
|
39
|
+
transferId: res.payment.transferId
|
|
40
|
+
} : void 0,
|
|
41
|
+
reputation: res.reputation
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function runDiscover(client, input) {
|
|
45
|
+
const services = await client.discover({
|
|
46
|
+
query: input.query,
|
|
47
|
+
tags: input.tags,
|
|
48
|
+
maxPrice: input.maxPrice
|
|
49
|
+
});
|
|
50
|
+
return services.map((s) => ({
|
|
51
|
+
name: s.name,
|
|
52
|
+
description: s.description,
|
|
53
|
+
endpoint: s.endpoint,
|
|
54
|
+
pricePerRequest: s.pricePerRequest,
|
|
55
|
+
tags: s.tags,
|
|
56
|
+
walletAddress: s.walletAddress,
|
|
57
|
+
agentId: s.agentId,
|
|
58
|
+
reputationScore: s.reputation?.score ?? null,
|
|
59
|
+
reputationCount: s.reputation?.count ?? 0
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
DISCOVER_TOOL_DESCRIPTION,
|
|
64
|
+
FETCH_TOOL_DESCRIPTION,
|
|
65
|
+
discoverInputSchema,
|
|
66
|
+
fetchInputSchema,
|
|
67
|
+
getClient,
|
|
68
|
+
runDiscover,
|
|
69
|
+
runFetch
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core.ts"],"sourcesContent":["/**\n * Framework-agnostic core for the ChainPe agent tools.\n *\n * Both the Vercel AI SDK adapter (`./vercel`) and the LangChain adapter\n * (`./langchain`) are thin wrappers over the `runFetch` / `runDiscover`\n * functions here, which in turn wrap `@chainpearc/sdk`. The input schemas and\n * serializable return shapes live here so the two adapters stay identical.\n */\nimport { z } from 'zod'\nimport { ChainPe, type ChainPeOptions } from '@chainpearc/sdk'\n\n/** Either SDK constructor options, or a pre-built {@link ChainPe} instance. */\nexport type ChainPeToolOptions = ChainPeOptions | { client: ChainPe }\n\nexport function getClient(options: ChainPeToolOptions): ChainPe {\n if ('client' in options) return options.client\n return new ChainPe(options)\n}\n\n// ─── Input schemas (shared by both frameworks) ───────────────────────────────\n\nexport const fetchInputSchema = z.object({\n url: z\n .string()\n .url()\n .describe(\n 'The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically.'\n ),\n method: z\n .enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])\n .optional()\n .describe('HTTP method (default GET).'),\n headers: z\n .record(z.string())\n .optional()\n .describe('Optional request headers.'),\n body: z\n .string()\n .optional()\n .describe('Optional request body, as a string (e.g. a JSON payload).')\n})\n\nexport const discoverInputSchema = z.object({\n query: z\n .string()\n .optional()\n .describe('Free-text search over service name, description, and tags.'),\n tags: z.array(z.string()).optional().describe('Filter by tags.'),\n maxPrice: z\n .string()\n .optional()\n .describe('Maximum price per request, in USDC (e.g. \"0.05\").')\n})\n\nexport type FetchInput = z.infer<typeof fetchInputSchema>\nexport type DiscoverInput = z.infer<typeof discoverInputSchema>\n\n// ─── Serializable results ────────────────────────────────────────────────────\n\nexport interface FetchResult {\n status: number\n ok: boolean\n /** Parsed response body (object for JSON, string otherwise). */\n data: unknown\n /** Present when a USDC payment was made + settled. */\n payment?: {\n amount: string\n recipient: string\n network: string\n rail: string\n txHash?: string\n transferId?: string\n }\n /** Present when ERC-8004 feedback was posted (autoFeedback). */\n reputation?: { agentId: string; score: number; txHash: string }\n}\n\nexport interface DiscoverResultItem {\n name: string\n description: string\n endpoint: string\n pricePerRequest: string\n tags: string[]\n walletAddress: string\n agentId?: string\n /** Aggregate ERC-8004 score (0–100) or null when unrated. */\n reputationScore: number | null\n /** Number of distinct clients that left feedback. */\n reputationCount: number\n}\n\n// ─── Tool descriptions (shared) ──────────────────────────────────────────────\n\nexport const FETCH_TOOL_DESCRIPTION =\n 'Fetch a URL, automatically paying any x402 \"402 Payment Required\" response in ' +\n 'USDC on Arc. Use this to call paid HTTP APIs or hire paid AI ' +\n 'agents. Returns the response body plus payment + reputation details.'\n\nexport const DISCOVER_TOOL_DESCRIPTION =\n \"Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, \" +\n 'ranked by ERC-8004 reputation (best first). Returns each service\\'s endpoint, ' +\n 'price, and reputation so you can pick one before paying.'\n\n// ─── Execution (shared) ──────────────────────────────────────────────────────\n\nexport async function runFetch(\n client: ChainPe,\n input: FetchInput\n): Promise<FetchResult> {\n const res = await client.pay(input.url, {\n method: input.method,\n headers: input.headers,\n body: input.body\n })\n return {\n status: res.status,\n ok: res.ok,\n data: res.data,\n payment: res.payment\n ? {\n amount: res.payment.amount,\n recipient: res.payment.recipient,\n network: res.payment.network,\n rail: res.payment.rail,\n txHash: res.payment.txHash,\n transferId: res.payment.transferId\n }\n : undefined,\n reputation: res.reputation\n }\n}\n\nexport async function runDiscover(\n client: ChainPe,\n input: DiscoverInput\n): Promise<DiscoverResultItem[]> {\n const services = await client.discover({\n query: input.query,\n tags: input.tags,\n maxPrice: input.maxPrice\n })\n return services.map(s => ({\n name: s.name,\n description: s.description,\n endpoint: s.endpoint,\n pricePerRequest: s.pricePerRequest,\n tags: s.tags,\n walletAddress: s.walletAddress,\n agentId: s.agentId,\n reputationScore: s.reputation?.score ?? null,\n reputationCount: s.reputation?.count ?? 0\n }))\n}\n"],"mappings":";AAQA,SAAS,SAAS;AAClB,SAAS,eAAoC;AAKtC,SAAS,UAAU,SAAsC;AAC9D,MAAI,YAAY,QAAS,QAAO,QAAQ;AACxC,SAAO,IAAI,QAAQ,OAAO;AAC5B;AAIO,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,KAAK,EACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EACL,KAAK,CAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,CAAC,EAC9C,SAAS,EACT,SAAS,4BAA4B;AAAA,EACxC,SAAS,EACN,OAAO,EAAE,OAAO,CAAC,EACjB,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,2DAA2D;AACzE,CAAC;AAEM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,OAAO,EACJ,OAAO,EACP,SAAS,EACT,SAAS,4DAA4D;AAAA,EACxE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,EAC/D,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AACjE,CAAC;AAyCM,IAAM,yBACX;AAIK,IAAM,4BACX;AAMF,eAAsB,SACpB,QACA,OACsB;AACtB,QAAM,MAAM,MAAM,OAAO,IAAI,MAAM,KAAK;AAAA,IACtC,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,EACd,CAAC;AACD,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,SAAS,IAAI,UACT;AAAA,MACE,QAAQ,IAAI,QAAQ;AAAA,MACpB,WAAW,IAAI,QAAQ;AAAA,MACvB,SAAS,IAAI,QAAQ;AAAA,MACrB,MAAM,IAAI,QAAQ;AAAA,MAClB,QAAQ,IAAI,QAAQ;AAAA,MACpB,YAAY,IAAI,QAAQ;AAAA,IAC1B,IACA;AAAA,IACJ,YAAY,IAAI;AAAA,EAClB;AACF;AAEA,eAAsB,YACpB,QACA,OAC+B;AAC/B,QAAM,WAAW,MAAM,OAAO,SAAS;AAAA,IACrC,OAAO,MAAM;AAAA,IACb,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,SAAO,SAAS,IAAI,QAAM;AAAA,IACxB,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,UAAU,EAAE;AAAA,IACZ,iBAAiB,EAAE;AAAA,IACnB,MAAM,EAAE;AAAA,IACR,eAAe,EAAE;AAAA,IACjB,SAAS,EAAE;AAAA,IACX,iBAAiB,EAAE,YAAY,SAAS;AAAA,IACxC,iBAAiB,EAAE,YAAY,SAAS;AAAA,EAC1C,EAAE;AACJ;","names":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as _langchain_core_tools from '@langchain/core/tools';
|
|
2
|
+
import * as zod from 'zod';
|
|
3
|
+
import { ChainPeToolOptions } from './index.js';
|
|
4
|
+
import '@chainpearc/sdk';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Builds the ChainPe LangChain `StructuredTool`s:
|
|
8
|
+
* `{ chainpeFetchTool, discoverServiceTool }`. Tool results are returned as
|
|
9
|
+
* JSON strings (LangChain tool outputs are strings).
|
|
10
|
+
*/
|
|
11
|
+
declare function createChainPeLangChainTools(options: ChainPeToolOptions): {
|
|
12
|
+
chainpeFetchTool: _langchain_core_tools.DynamicStructuredTool<zod.ZodObject<{
|
|
13
|
+
url: zod.ZodString;
|
|
14
|
+
method: zod.ZodOptional<zod.ZodEnum<["GET", "POST", "PUT", "DELETE", "PATCH"]>>;
|
|
15
|
+
headers: zod.ZodOptional<zod.ZodRecord<zod.ZodString, zod.ZodString>>;
|
|
16
|
+
body: zod.ZodOptional<zod.ZodString>;
|
|
17
|
+
}, "strip", zod.ZodTypeAny, {
|
|
18
|
+
url: string;
|
|
19
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
20
|
+
headers?: Record<string, string> | undefined;
|
|
21
|
+
body?: string | undefined;
|
|
22
|
+
}, {
|
|
23
|
+
url: string;
|
|
24
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
25
|
+
headers?: Record<string, string> | undefined;
|
|
26
|
+
body?: string | undefined;
|
|
27
|
+
}>, {
|
|
28
|
+
url: string;
|
|
29
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
30
|
+
headers?: Record<string, string> | undefined;
|
|
31
|
+
body?: string | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
url: string;
|
|
34
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
35
|
+
headers?: Record<string, string> | undefined;
|
|
36
|
+
body?: string | undefined;
|
|
37
|
+
}, string>;
|
|
38
|
+
discoverServiceTool: _langchain_core_tools.DynamicStructuredTool<zod.ZodObject<{
|
|
39
|
+
query: zod.ZodOptional<zod.ZodString>;
|
|
40
|
+
tags: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
|
|
41
|
+
maxPrice: zod.ZodOptional<zod.ZodString>;
|
|
42
|
+
}, "strip", zod.ZodTypeAny, {
|
|
43
|
+
query?: string | undefined;
|
|
44
|
+
tags?: string[] | undefined;
|
|
45
|
+
maxPrice?: string | undefined;
|
|
46
|
+
}, {
|
|
47
|
+
query?: string | undefined;
|
|
48
|
+
tags?: string[] | undefined;
|
|
49
|
+
maxPrice?: string | undefined;
|
|
50
|
+
}>, {
|
|
51
|
+
query?: string | undefined;
|
|
52
|
+
tags?: string[] | undefined;
|
|
53
|
+
maxPrice?: string | undefined;
|
|
54
|
+
}, {
|
|
55
|
+
query?: string | undefined;
|
|
56
|
+
tags?: string[] | undefined;
|
|
57
|
+
maxPrice?: string | undefined;
|
|
58
|
+
}, string>;
|
|
59
|
+
};
|
|
60
|
+
type ChainPeLangChainTools = ReturnType<typeof createChainPeLangChainTools>;
|
|
61
|
+
|
|
62
|
+
export { type ChainPeLangChainTools, ChainPeToolOptions, createChainPeLangChainTools };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/langchain.ts
|
|
2
|
+
import { tool } from "@langchain/core/tools";
|
|
3
|
+
|
|
4
|
+
// src/core.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { ChainPe } from "@chainpearc/sdk";
|
|
7
|
+
function getClient(options) {
|
|
8
|
+
if ("client" in options) return options.client;
|
|
9
|
+
return new ChainPe(options);
|
|
10
|
+
}
|
|
11
|
+
var fetchInputSchema = z.object({
|
|
12
|
+
url: z.string().url().describe(
|
|
13
|
+
"The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically."
|
|
14
|
+
),
|
|
15
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().describe("HTTP method (default GET)."),
|
|
16
|
+
headers: z.record(z.string()).optional().describe("Optional request headers."),
|
|
17
|
+
body: z.string().optional().describe("Optional request body, as a string (e.g. a JSON payload).")
|
|
18
|
+
});
|
|
19
|
+
var discoverInputSchema = z.object({
|
|
20
|
+
query: z.string().optional().describe("Free-text search over service name, description, and tags."),
|
|
21
|
+
tags: z.array(z.string()).optional().describe("Filter by tags."),
|
|
22
|
+
maxPrice: z.string().optional().describe('Maximum price per request, in USDC (e.g. "0.05").')
|
|
23
|
+
});
|
|
24
|
+
var FETCH_TOOL_DESCRIPTION = 'Fetch a URL, automatically paying any x402 "402 Payment Required" response in USDC on Arc. Use this to call paid HTTP APIs or hire paid AI agents. Returns the response body plus payment + reputation details.';
|
|
25
|
+
var DISCOVER_TOOL_DESCRIPTION = "Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, ranked by ERC-8004 reputation (best first). Returns each service's endpoint, price, and reputation so you can pick one before paying.";
|
|
26
|
+
async function runFetch(client, input) {
|
|
27
|
+
const res = await client.pay(input.url, {
|
|
28
|
+
method: input.method,
|
|
29
|
+
headers: input.headers,
|
|
30
|
+
body: input.body
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
status: res.status,
|
|
34
|
+
ok: res.ok,
|
|
35
|
+
data: res.data,
|
|
36
|
+
payment: res.payment ? {
|
|
37
|
+
amount: res.payment.amount,
|
|
38
|
+
recipient: res.payment.recipient,
|
|
39
|
+
network: res.payment.network,
|
|
40
|
+
rail: res.payment.rail,
|
|
41
|
+
txHash: res.payment.txHash,
|
|
42
|
+
transferId: res.payment.transferId
|
|
43
|
+
} : void 0,
|
|
44
|
+
reputation: res.reputation
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function runDiscover(client, input) {
|
|
48
|
+
const services = await client.discover({
|
|
49
|
+
query: input.query,
|
|
50
|
+
tags: input.tags,
|
|
51
|
+
maxPrice: input.maxPrice
|
|
52
|
+
});
|
|
53
|
+
return services.map((s) => ({
|
|
54
|
+
name: s.name,
|
|
55
|
+
description: s.description,
|
|
56
|
+
endpoint: s.endpoint,
|
|
57
|
+
pricePerRequest: s.pricePerRequest,
|
|
58
|
+
tags: s.tags,
|
|
59
|
+
walletAddress: s.walletAddress,
|
|
60
|
+
agentId: s.agentId,
|
|
61
|
+
reputationScore: s.reputation?.score ?? null,
|
|
62
|
+
reputationCount: s.reputation?.count ?? 0
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/langchain.ts
|
|
67
|
+
function createChainPeLangChainTools(options) {
|
|
68
|
+
const client = getClient(options);
|
|
69
|
+
const chainpeFetchTool = tool(
|
|
70
|
+
async (input) => JSON.stringify(await runFetch(client, input)),
|
|
71
|
+
{
|
|
72
|
+
name: "chainpe_fetch",
|
|
73
|
+
description: FETCH_TOOL_DESCRIPTION,
|
|
74
|
+
schema: fetchInputSchema
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
const discoverServiceTool = tool(
|
|
78
|
+
async (input) => JSON.stringify(await runDiscover(client, input)),
|
|
79
|
+
{
|
|
80
|
+
name: "discover_service",
|
|
81
|
+
description: DISCOVER_TOOL_DESCRIPTION,
|
|
82
|
+
schema: discoverInputSchema
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
return { chainpeFetchTool, discoverServiceTool };
|
|
86
|
+
}
|
|
87
|
+
export {
|
|
88
|
+
createChainPeLangChainTools
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=langchain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/langchain.ts","../src/core.ts"],"sourcesContent":["/**\n * ChainPe tools for **LangChain** (`@langchain/core`).\n *\n * @example\n * ```ts\n * import { ChatAnthropic } from '@langchain/anthropic'\n * import { createReactAgent } from '@langchain/langgraph/prebuilt'\n * import { createChainPeLangChainTools } from '@chainpearc/ai-tools/langchain'\n *\n * const { chainpeFetchTool, discoverServiceTool } = createChainPeLangChainTools({\n * privateKey, autoFeedback: true\n * })\n *\n * const agent = createReactAgent({\n * llm: new ChatAnthropic({ model: 'claude-opus-4-8' }),\n * tools: [discoverServiceTool, chainpeFetchTool]\n * })\n * ```\n */\nimport { tool } from '@langchain/core/tools'\nimport {\n getClient,\n fetchInputSchema,\n discoverInputSchema,\n runFetch,\n runDiscover,\n FETCH_TOOL_DESCRIPTION,\n DISCOVER_TOOL_DESCRIPTION,\n type ChainPeToolOptions\n} from './core.js'\n\n/**\n * Builds the ChainPe LangChain `StructuredTool`s:\n * `{ chainpeFetchTool, discoverServiceTool }`. Tool results are returned as\n * JSON strings (LangChain tool outputs are strings).\n */\nexport function createChainPeLangChainTools(options: ChainPeToolOptions) {\n const client = getClient(options)\n\n const chainpeFetchTool = tool(\n async input => JSON.stringify(await runFetch(client, input)),\n {\n name: 'chainpe_fetch',\n description: FETCH_TOOL_DESCRIPTION,\n schema: fetchInputSchema\n }\n )\n\n const discoverServiceTool = tool(\n async input => JSON.stringify(await runDiscover(client, input)),\n {\n name: 'discover_service',\n description: DISCOVER_TOOL_DESCRIPTION,\n schema: discoverInputSchema\n }\n )\n\n return { chainpeFetchTool, discoverServiceTool }\n}\n\nexport type ChainPeLangChainTools = ReturnType<\n typeof createChainPeLangChainTools\n>\nexport type { ChainPeToolOptions } from './core.js'\n","/**\n * Framework-agnostic core for the ChainPe agent tools.\n *\n * Both the Vercel AI SDK adapter (`./vercel`) and the LangChain adapter\n * (`./langchain`) are thin wrappers over the `runFetch` / `runDiscover`\n * functions here, which in turn wrap `@chainpearc/sdk`. The input schemas and\n * serializable return shapes live here so the two adapters stay identical.\n */\nimport { z } from 'zod'\nimport { ChainPe, type ChainPeOptions } from '@chainpearc/sdk'\n\n/** Either SDK constructor options, or a pre-built {@link ChainPe} instance. */\nexport type ChainPeToolOptions = ChainPeOptions | { client: ChainPe }\n\nexport function getClient(options: ChainPeToolOptions): ChainPe {\n if ('client' in options) return options.client\n return new ChainPe(options)\n}\n\n// ─── Input schemas (shared by both frameworks) ───────────────────────────────\n\nexport const fetchInputSchema = z.object({\n url: z\n .string()\n .url()\n .describe(\n 'The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically.'\n ),\n method: z\n .enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])\n .optional()\n .describe('HTTP method (default GET).'),\n headers: z\n .record(z.string())\n .optional()\n .describe('Optional request headers.'),\n body: z\n .string()\n .optional()\n .describe('Optional request body, as a string (e.g. a JSON payload).')\n})\n\nexport const discoverInputSchema = z.object({\n query: z\n .string()\n .optional()\n .describe('Free-text search over service name, description, and tags.'),\n tags: z.array(z.string()).optional().describe('Filter by tags.'),\n maxPrice: z\n .string()\n .optional()\n .describe('Maximum price per request, in USDC (e.g. \"0.05\").')\n})\n\nexport type FetchInput = z.infer<typeof fetchInputSchema>\nexport type DiscoverInput = z.infer<typeof discoverInputSchema>\n\n// ─── Serializable results ────────────────────────────────────────────────────\n\nexport interface FetchResult {\n status: number\n ok: boolean\n /** Parsed response body (object for JSON, string otherwise). */\n data: unknown\n /** Present when a USDC payment was made + settled. */\n payment?: {\n amount: string\n recipient: string\n network: string\n rail: string\n txHash?: string\n transferId?: string\n }\n /** Present when ERC-8004 feedback was posted (autoFeedback). */\n reputation?: { agentId: string; score: number; txHash: string }\n}\n\nexport interface DiscoverResultItem {\n name: string\n description: string\n endpoint: string\n pricePerRequest: string\n tags: string[]\n walletAddress: string\n agentId?: string\n /** Aggregate ERC-8004 score (0–100) or null when unrated. */\n reputationScore: number | null\n /** Number of distinct clients that left feedback. */\n reputationCount: number\n}\n\n// ─── Tool descriptions (shared) ──────────────────────────────────────────────\n\nexport const FETCH_TOOL_DESCRIPTION =\n 'Fetch a URL, automatically paying any x402 \"402 Payment Required\" response in ' +\n 'USDC on Arc. Use this to call paid HTTP APIs or hire paid AI ' +\n 'agents. Returns the response body plus payment + reputation details.'\n\nexport const DISCOVER_TOOL_DESCRIPTION =\n \"Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, \" +\n 'ranked by ERC-8004 reputation (best first). Returns each service\\'s endpoint, ' +\n 'price, and reputation so you can pick one before paying.'\n\n// ─── Execution (shared) ──────────────────────────────────────────────────────\n\nexport async function runFetch(\n client: ChainPe,\n input: FetchInput\n): Promise<FetchResult> {\n const res = await client.pay(input.url, {\n method: input.method,\n headers: input.headers,\n body: input.body\n })\n return {\n status: res.status,\n ok: res.ok,\n data: res.data,\n payment: res.payment\n ? {\n amount: res.payment.amount,\n recipient: res.payment.recipient,\n network: res.payment.network,\n rail: res.payment.rail,\n txHash: res.payment.txHash,\n transferId: res.payment.transferId\n }\n : undefined,\n reputation: res.reputation\n }\n}\n\nexport async function runDiscover(\n client: ChainPe,\n input: DiscoverInput\n): Promise<DiscoverResultItem[]> {\n const services = await client.discover({\n query: input.query,\n tags: input.tags,\n maxPrice: input.maxPrice\n })\n return services.map(s => ({\n name: s.name,\n description: s.description,\n endpoint: s.endpoint,\n pricePerRequest: s.pricePerRequest,\n tags: s.tags,\n walletAddress: s.walletAddress,\n agentId: s.agentId,\n reputationScore: s.reputation?.score ?? null,\n reputationCount: s.reputation?.count ?? 0\n }))\n}\n"],"mappings":";AAmBA,SAAS,YAAY;;;ACXrB,SAAS,SAAS;AAClB,SAAS,eAAoC;AAKtC,SAAS,UAAU,SAAsC;AAC9D,MAAI,YAAY,QAAS,QAAO,QAAQ;AACxC,SAAO,IAAI,QAAQ,OAAO;AAC5B;AAIO,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,KAAK,EACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EACL,KAAK,CAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,CAAC,EAC9C,SAAS,EACT,SAAS,4BAA4B;AAAA,EACxC,SAAS,EACN,OAAO,EAAE,OAAO,CAAC,EACjB,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,2DAA2D;AACzE,CAAC;AAEM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,OAAO,EACJ,OAAO,EACP,SAAS,EACT,SAAS,4DAA4D;AAAA,EACxE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,EAC/D,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AACjE,CAAC;AAyCM,IAAM,yBACX;AAIK,IAAM,4BACX;AAMF,eAAsB,SACpB,QACA,OACsB;AACtB,QAAM,MAAM,MAAM,OAAO,IAAI,MAAM,KAAK;AAAA,IACtC,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,EACd,CAAC;AACD,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,SAAS,IAAI,UACT;AAAA,MACE,QAAQ,IAAI,QAAQ;AAAA,MACpB,WAAW,IAAI,QAAQ;AAAA,MACvB,SAAS,IAAI,QAAQ;AAAA,MACrB,MAAM,IAAI,QAAQ;AAAA,MAClB,QAAQ,IAAI,QAAQ;AAAA,MACpB,YAAY,IAAI,QAAQ;AAAA,IAC1B,IACA;AAAA,IACJ,YAAY,IAAI;AAAA,EAClB;AACF;AAEA,eAAsB,YACpB,QACA,OAC+B;AAC/B,QAAM,WAAW,MAAM,OAAO,SAAS;AAAA,IACrC,OAAO,MAAM;AAAA,IACb,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,SAAO,SAAS,IAAI,QAAM;AAAA,IACxB,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,UAAU,EAAE;AAAA,IACZ,iBAAiB,EAAE;AAAA,IACnB,MAAM,EAAE;AAAA,IACR,eAAe,EAAE;AAAA,IACjB,SAAS,EAAE;AAAA,IACX,iBAAiB,EAAE,YAAY,SAAS;AAAA,IACxC,iBAAiB,EAAE,YAAY,SAAS;AAAA,EAC1C,EAAE;AACJ;;;ADpHO,SAAS,4BAA4B,SAA6B;AACvE,QAAM,SAAS,UAAU,OAAO;AAEhC,QAAM,mBAAmB;AAAA,IACvB,OAAM,UAAS,KAAK,UAAU,MAAM,SAAS,QAAQ,KAAK,CAAC;AAAA,IAC3D;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,sBAAsB;AAAA,IAC1B,OAAM,UAAS,KAAK,UAAU,MAAM,YAAY,QAAQ,KAAK,CAAC;AAAA,IAC9D;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO,EAAE,kBAAkB,oBAAoB;AACjD;","names":[]}
|
package/dist/vercel.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as ai from 'ai';
|
|
2
|
+
import { ChainPeToolOptions, FetchResult, DiscoverResultItem } from './index.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
import '@chainpearc/sdk';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Builds the ChainPe tools as a Vercel AI SDK tool set:
|
|
8
|
+
* `{ chainpeFetch, discoverService }`. Spread into `tools` on `generateText` /
|
|
9
|
+
* `streamText`.
|
|
10
|
+
*/
|
|
11
|
+
declare function createChainPeTools(options: ChainPeToolOptions): {
|
|
12
|
+
chainpeFetch: ai.Tool<{
|
|
13
|
+
url: string;
|
|
14
|
+
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
15
|
+
headers?: Record<string, string> | undefined;
|
|
16
|
+
body?: string | undefined;
|
|
17
|
+
}, FetchResult>;
|
|
18
|
+
discoverService: ai.Tool<{
|
|
19
|
+
query?: string | undefined;
|
|
20
|
+
tags?: string[] | undefined;
|
|
21
|
+
maxPrice?: string | undefined;
|
|
22
|
+
}, DiscoverResultItem[]>;
|
|
23
|
+
};
|
|
24
|
+
type ChainPeTools = ReturnType<typeof createChainPeTools>;
|
|
25
|
+
|
|
26
|
+
export { ChainPeToolOptions, type ChainPeTools, createChainPeTools };
|
package/dist/vercel.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/vercel.ts
|
|
2
|
+
import { tool } from "ai";
|
|
3
|
+
|
|
4
|
+
// src/core.ts
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { ChainPe } from "@chainpearc/sdk";
|
|
7
|
+
function getClient(options) {
|
|
8
|
+
if ("client" in options) return options.client;
|
|
9
|
+
return new ChainPe(options);
|
|
10
|
+
}
|
|
11
|
+
var fetchInputSchema = z.object({
|
|
12
|
+
url: z.string().url().describe(
|
|
13
|
+
"The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically."
|
|
14
|
+
),
|
|
15
|
+
method: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH"]).optional().describe("HTTP method (default GET)."),
|
|
16
|
+
headers: z.record(z.string()).optional().describe("Optional request headers."),
|
|
17
|
+
body: z.string().optional().describe("Optional request body, as a string (e.g. a JSON payload).")
|
|
18
|
+
});
|
|
19
|
+
var discoverInputSchema = z.object({
|
|
20
|
+
query: z.string().optional().describe("Free-text search over service name, description, and tags."),
|
|
21
|
+
tags: z.array(z.string()).optional().describe("Filter by tags."),
|
|
22
|
+
maxPrice: z.string().optional().describe('Maximum price per request, in USDC (e.g. "0.05").')
|
|
23
|
+
});
|
|
24
|
+
var FETCH_TOOL_DESCRIPTION = 'Fetch a URL, automatically paying any x402 "402 Payment Required" response in USDC on Arc. Use this to call paid HTTP APIs or hire paid AI agents. Returns the response body plus payment + reputation details.';
|
|
25
|
+
var DISCOVER_TOOL_DESCRIPTION = "Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, ranked by ERC-8004 reputation (best first). Returns each service's endpoint, price, and reputation so you can pick one before paying.";
|
|
26
|
+
async function runFetch(client, input) {
|
|
27
|
+
const res = await client.pay(input.url, {
|
|
28
|
+
method: input.method,
|
|
29
|
+
headers: input.headers,
|
|
30
|
+
body: input.body
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
status: res.status,
|
|
34
|
+
ok: res.ok,
|
|
35
|
+
data: res.data,
|
|
36
|
+
payment: res.payment ? {
|
|
37
|
+
amount: res.payment.amount,
|
|
38
|
+
recipient: res.payment.recipient,
|
|
39
|
+
network: res.payment.network,
|
|
40
|
+
rail: res.payment.rail,
|
|
41
|
+
txHash: res.payment.txHash,
|
|
42
|
+
transferId: res.payment.transferId
|
|
43
|
+
} : void 0,
|
|
44
|
+
reputation: res.reputation
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
async function runDiscover(client, input) {
|
|
48
|
+
const services = await client.discover({
|
|
49
|
+
query: input.query,
|
|
50
|
+
tags: input.tags,
|
|
51
|
+
maxPrice: input.maxPrice
|
|
52
|
+
});
|
|
53
|
+
return services.map((s) => ({
|
|
54
|
+
name: s.name,
|
|
55
|
+
description: s.description,
|
|
56
|
+
endpoint: s.endpoint,
|
|
57
|
+
pricePerRequest: s.pricePerRequest,
|
|
58
|
+
tags: s.tags,
|
|
59
|
+
walletAddress: s.walletAddress,
|
|
60
|
+
agentId: s.agentId,
|
|
61
|
+
reputationScore: s.reputation?.score ?? null,
|
|
62
|
+
reputationCount: s.reputation?.count ?? 0
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/vercel.ts
|
|
67
|
+
function createChainPeTools(options) {
|
|
68
|
+
const client = getClient(options);
|
|
69
|
+
return {
|
|
70
|
+
chainpeFetch: tool({
|
|
71
|
+
description: FETCH_TOOL_DESCRIPTION,
|
|
72
|
+
inputSchema: fetchInputSchema,
|
|
73
|
+
execute: (input) => runFetch(client, input)
|
|
74
|
+
}),
|
|
75
|
+
discoverService: tool({
|
|
76
|
+
description: DISCOVER_TOOL_DESCRIPTION,
|
|
77
|
+
inputSchema: discoverInputSchema,
|
|
78
|
+
execute: (input) => runDiscover(client, input)
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
createChainPeTools
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=vercel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vercel.ts","../src/core.ts"],"sourcesContent":["/**\n * ChainPe tools for the **Vercel AI SDK** (`ai`).\n *\n * @example\n * ```ts\n * import { generateText } from 'ai'\n * import { anthropic } from '@ai-sdk/anthropic'\n * import { createChainPeTools } from '@chainpearc/ai-tools/vercel'\n *\n * const tools = createChainPeTools({ privateKey, autoFeedback: true })\n *\n * const { text } = await generateText({\n * model: anthropic('claude-opus-4-8'),\n * tools,\n * prompt: 'Find a summarizer agent and summarize this article: …'\n * })\n * ```\n */\nimport { tool } from 'ai'\nimport {\n getClient,\n fetchInputSchema,\n discoverInputSchema,\n runFetch,\n runDiscover,\n FETCH_TOOL_DESCRIPTION,\n DISCOVER_TOOL_DESCRIPTION,\n type ChainPeToolOptions\n} from './core.js'\n\n/**\n * Builds the ChainPe tools as a Vercel AI SDK tool set:\n * `{ chainpeFetch, discoverService }`. Spread into `tools` on `generateText` /\n * `streamText`.\n */\nexport function createChainPeTools(options: ChainPeToolOptions) {\n const client = getClient(options)\n return {\n chainpeFetch: tool({\n description: FETCH_TOOL_DESCRIPTION,\n inputSchema: fetchInputSchema,\n execute: input => runFetch(client, input)\n }),\n discoverService: tool({\n description: DISCOVER_TOOL_DESCRIPTION,\n inputSchema: discoverInputSchema,\n execute: input => runDiscover(client, input)\n })\n }\n}\n\nexport type ChainPeTools = ReturnType<typeof createChainPeTools>\nexport type { ChainPeToolOptions } from './core.js'\n","/**\n * Framework-agnostic core for the ChainPe agent tools.\n *\n * Both the Vercel AI SDK adapter (`./vercel`) and the LangChain adapter\n * (`./langchain`) are thin wrappers over the `runFetch` / `runDiscover`\n * functions here, which in turn wrap `@chainpearc/sdk`. The input schemas and\n * serializable return shapes live here so the two adapters stay identical.\n */\nimport { z } from 'zod'\nimport { ChainPe, type ChainPeOptions } from '@chainpearc/sdk'\n\n/** Either SDK constructor options, or a pre-built {@link ChainPe} instance. */\nexport type ChainPeToolOptions = ChainPeOptions | { client: ChainPe }\n\nexport function getClient(options: ChainPeToolOptions): ChainPe {\n if ('client' in options) return options.client\n return new ChainPe(options)\n}\n\n// ─── Input schemas (shared by both frameworks) ───────────────────────────────\n\nexport const fetchInputSchema = z.object({\n url: z\n .string()\n .url()\n .describe(\n 'The URL to call. If it responds 402 Payment Required, the USDC payment is signed and sent automatically.'\n ),\n method: z\n .enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])\n .optional()\n .describe('HTTP method (default GET).'),\n headers: z\n .record(z.string())\n .optional()\n .describe('Optional request headers.'),\n body: z\n .string()\n .optional()\n .describe('Optional request body, as a string (e.g. a JSON payload).')\n})\n\nexport const discoverInputSchema = z.object({\n query: z\n .string()\n .optional()\n .describe('Free-text search over service name, description, and tags.'),\n tags: z.array(z.string()).optional().describe('Filter by tags.'),\n maxPrice: z\n .string()\n .optional()\n .describe('Maximum price per request, in USDC (e.g. \"0.05\").')\n})\n\nexport type FetchInput = z.infer<typeof fetchInputSchema>\nexport type DiscoverInput = z.infer<typeof discoverInputSchema>\n\n// ─── Serializable results ────────────────────────────────────────────────────\n\nexport interface FetchResult {\n status: number\n ok: boolean\n /** Parsed response body (object for JSON, string otherwise). */\n data: unknown\n /** Present when a USDC payment was made + settled. */\n payment?: {\n amount: string\n recipient: string\n network: string\n rail: string\n txHash?: string\n transferId?: string\n }\n /** Present when ERC-8004 feedback was posted (autoFeedback). */\n reputation?: { agentId: string; score: number; txHash: string }\n}\n\nexport interface DiscoverResultItem {\n name: string\n description: string\n endpoint: string\n pricePerRequest: string\n tags: string[]\n walletAddress: string\n agentId?: string\n /** Aggregate ERC-8004 score (0–100) or null when unrated. */\n reputationScore: number | null\n /** Number of distinct clients that left feedback. */\n reputationCount: number\n}\n\n// ─── Tool descriptions (shared) ──────────────────────────────────────────────\n\nexport const FETCH_TOOL_DESCRIPTION =\n 'Fetch a URL, automatically paying any x402 \"402 Payment Required\" response in ' +\n 'USDC on Arc. Use this to call paid HTTP APIs or hire paid AI ' +\n 'agents. Returns the response body plus payment + reputation details.'\n\nexport const DISCOVER_TOOL_DESCRIPTION =\n \"Discover paid services and AI agents through Circle's Discovery API and ChainPe's on-chain listings, \" +\n 'ranked by ERC-8004 reputation (best first). Returns each service\\'s endpoint, ' +\n 'price, and reputation so you can pick one before paying.'\n\n// ─── Execution (shared) ──────────────────────────────────────────────────────\n\nexport async function runFetch(\n client: ChainPe,\n input: FetchInput\n): Promise<FetchResult> {\n const res = await client.pay(input.url, {\n method: input.method,\n headers: input.headers,\n body: input.body\n })\n return {\n status: res.status,\n ok: res.ok,\n data: res.data,\n payment: res.payment\n ? {\n amount: res.payment.amount,\n recipient: res.payment.recipient,\n network: res.payment.network,\n rail: res.payment.rail,\n txHash: res.payment.txHash,\n transferId: res.payment.transferId\n }\n : undefined,\n reputation: res.reputation\n }\n}\n\nexport async function runDiscover(\n client: ChainPe,\n input: DiscoverInput\n): Promise<DiscoverResultItem[]> {\n const services = await client.discover({\n query: input.query,\n tags: input.tags,\n maxPrice: input.maxPrice\n })\n return services.map(s => ({\n name: s.name,\n description: s.description,\n endpoint: s.endpoint,\n pricePerRequest: s.pricePerRequest,\n tags: s.tags,\n walletAddress: s.walletAddress,\n agentId: s.agentId,\n reputationScore: s.reputation?.score ?? null,\n reputationCount: s.reputation?.count ?? 0\n }))\n}\n"],"mappings":";AAkBA,SAAS,YAAY;;;ACVrB,SAAS,SAAS;AAClB,SAAS,eAAoC;AAKtC,SAAS,UAAU,SAAsC;AAC9D,MAAI,YAAY,QAAS,QAAO,QAAQ;AACxC,SAAO,IAAI,QAAQ,OAAO;AAC5B;AAIO,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,KAAK,EACF,OAAO,EACP,IAAI,EACJ;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EACL,KAAK,CAAC,OAAO,QAAQ,OAAO,UAAU,OAAO,CAAC,EAC9C,SAAS,EACT,SAAS,4BAA4B;AAAA,EACxC,SAAS,EACN,OAAO,EAAE,OAAO,CAAC,EACjB,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,2DAA2D;AACzE,CAAC;AAEM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,OAAO,EACJ,OAAO,EACP,SAAS,EACT,SAAS,4DAA4D;AAAA,EACxE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,EAC/D,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,mDAAmD;AACjE,CAAC;AAyCM,IAAM,yBACX;AAIK,IAAM,4BACX;AAMF,eAAsB,SACpB,QACA,OACsB;AACtB,QAAM,MAAM,MAAM,OAAO,IAAI,MAAM,KAAK;AAAA,IACtC,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,EACd,CAAC;AACD,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,SAAS,IAAI,UACT;AAAA,MACE,QAAQ,IAAI,QAAQ;AAAA,MACpB,WAAW,IAAI,QAAQ;AAAA,MACvB,SAAS,IAAI,QAAQ;AAAA,MACrB,MAAM,IAAI,QAAQ;AAAA,MAClB,QAAQ,IAAI,QAAQ;AAAA,MACpB,YAAY,IAAI,QAAQ;AAAA,IAC1B,IACA;AAAA,IACJ,YAAY,IAAI;AAAA,EAClB;AACF;AAEA,eAAsB,YACpB,QACA,OAC+B;AAC/B,QAAM,WAAW,MAAM,OAAO,SAAS;AAAA,IACrC,OAAO,MAAM;AAAA,IACb,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,EAClB,CAAC;AACD,SAAO,SAAS,IAAI,QAAM;AAAA,IACxB,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,UAAU,EAAE;AAAA,IACZ,iBAAiB,EAAE;AAAA,IACnB,MAAM,EAAE;AAAA,IACR,eAAe,EAAE;AAAA,IACjB,SAAS,EAAE;AAAA,IACX,iBAAiB,EAAE,YAAY,SAAS;AAAA,IACxC,iBAAiB,EAAE,YAAY,SAAS;AAAA,EAC1C,EAAE;AACJ;;;ADrHO,SAAS,mBAAmB,SAA6B;AAC9D,QAAM,SAAS,UAAU,OAAO;AAChC,SAAO;AAAA,IACL,cAAc,KAAK;AAAA,MACjB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,SAAS,WAAS,SAAS,QAAQ,KAAK;AAAA,IAC1C,CAAC;AAAA,IACD,iBAAiB,KAAK;AAAA,MACpB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,SAAS,WAAS,YAAY,QAAQ,KAAK;AAAA,IAC7C,CAAC;AAAA,EACH;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,80 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainpearc/ai-tools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "ChainPe agent tools: drop-in x402 pay and discover tools for the Vercel AI SDK and LangChain, on Arc.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./vercel": {
|
|
15
|
+
"types": "./dist/vercel.d.ts",
|
|
16
|
+
"import": "./dist/vercel.js"
|
|
17
|
+
},
|
|
18
|
+
"./langchain": {
|
|
19
|
+
"types": "./dist/langchain.d.ts",
|
|
20
|
+
"import": "./dist/langchain.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md"
|
|
26
|
+
],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsup",
|
|
29
|
+
"dev": "tsup --watch",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"clean": "rm -rf dist",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@chainpearc/sdk": "^0.3.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@langchain/core": ">=0.3.0",
|
|
41
|
+
"ai": ">=4.0.0",
|
|
42
|
+
"zod": "^3.23.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependenciesMeta": {
|
|
45
|
+
"ai": {
|
|
46
|
+
"optional": true
|
|
47
|
+
},
|
|
48
|
+
"@langchain/core": {
|
|
49
|
+
"optional": true
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@langchain/core": "^0.3.0",
|
|
54
|
+
"@types/node": "^22.15.21",
|
|
55
|
+
"ai": "^6.0.0",
|
|
56
|
+
"tsup": "^8.5.0",
|
|
57
|
+
"typescript": "^5.8.3",
|
|
58
|
+
"vitest": "^3.2.1",
|
|
59
|
+
"zod": "^3.23.0"
|
|
60
|
+
},
|
|
61
|
+
"keywords": [
|
|
62
|
+
"x402",
|
|
63
|
+
"ai-agents",
|
|
64
|
+
"vercel-ai-sdk",
|
|
65
|
+
"langchain",
|
|
66
|
+
"tools",
|
|
67
|
+
"usdc",
|
|
68
|
+
"arc",
|
|
69
|
+
"payments",
|
|
70
|
+
"chainpe"
|
|
71
|
+
],
|
|
72
|
+
"license": "MIT",
|
|
73
|
+
"repository": {
|
|
74
|
+
"type": "git",
|
|
75
|
+
"url": "git+https://github.com/SamyaDeb/ChainPe.git"
|
|
76
|
+
},
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">=22.18"
|
|
79
|
+
}
|
|
80
|
+
}
|