Update the sample command
This commit is contained in:
parent
ac45c5c949
commit
a779177958
19
bun.lock
19
bun.lock
|
|
@ -5,9 +5,10 @@
|
|||
"": {
|
||||
"name": "natural-language-agreement-extension",
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "^2.0.50",
|
||||
"@ai-sdk/anthropic": "^3.0.2",
|
||||
"@ai-sdk/openai": "^3.0.2",
|
||||
"@viem/anvil": "^0.0.10",
|
||||
"ai": "^5.0.68",
|
||||
"ai": "^6.0.5",
|
||||
"alkahest-ts": "git+https://github.com/VAR-META-Tech/alkahest.git#ts-package",
|
||||
"arktype": "^2.1.23",
|
||||
"viem": "^2.42.1",
|
||||
|
|
@ -24,13 +25,15 @@
|
|||
"packages": {
|
||||
"@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="],
|
||||
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
|
||||
"@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-D6iSsrOYryBSPsFtOiEDv54jnjVCU/flIuXdjuRY7LdikB0KGjpazN8Dt4ONXzL+ux69ds2nzFNKke/w/fgLAA=="],
|
||||
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@2.0.86", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-obsLIOyA93lbQiSt1rvBItoVQp1U2RDPs0bNG0JYhm6Gku8Dg/0Cm8e4NUWT5p5PN10/doKSb3SMSKCixwIAKA=="],
|
||||
"@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.4", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OlccjNYZ5+4FaNyvs0kb3N5H6U/QCKlKPTGsgUo8IZkqfMQu8ALI1XD6l/BCuTKto+OO9xUPObT/W7JhbqJ5nA=="],
|
||||
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="],
|
||||
"@ai-sdk/openai": ["@ai-sdk/openai@3.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-GONwavgSWtcWO+t9+GpGK8l7nIYh+zNtCL/NYDSeHxHiw6ksQS9XMRWrZyE5NpJ0EXNxSAWCHIDmb1WvTqhq9Q=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.19", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA=="],
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.1", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-2lR4w7mr9XrydzxBSjir4N6YMGdXD+Np1Sh0RXABh7tWdNFFwIeRI1Q+SaYZMbfL8Pg8RRLcrxQm51yxTLhokg=="],
|
||||
|
||||
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.2", "", { "dependencies": { "@ai-sdk/provider": "3.0.1", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-KaykkuRBdF/ffpI5bwpL4aSCmO/99p8/ci+VeHwJO8tmvXtiVAb99QeyvvvXmL61e9Zrvv4GBGoajW19xdjkVQ=="],
|
||||
|
||||
"@ark/schema": ["@ark/schema@0.56.0", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA=="],
|
||||
|
||||
|
|
@ -50,7 +53,7 @@
|
|||
|
||||
"@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="],
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="],
|
||||
|
||||
|
|
@ -62,7 +65,7 @@
|
|||
|
||||
"abitype": ["abitype@1.1.0", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A=="],
|
||||
|
||||
"ai": ["ai@5.0.113", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g=="],
|
||||
"ai": ["ai@6.0.5", "", { "dependencies": { "@ai-sdk/gateway": "3.0.4", "@ai-sdk/provider": "3.0.1", "@ai-sdk/provider-utils": "4.0.2", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-CKL3dDHedWskC6EY67LrULonZBU9vL+Bwa+xQEcprBhJfxpogntG3utjiAkYuy5ZQatyWk+SmWG8HLvcnhvbRg=="],
|
||||
|
||||
"alkahest-ts": ["alkahest-ts@github:VAR-META-Tech/alkahest#d40de37", {}, "VAR-META-Tech-alkahest-d40de37"],
|
||||
|
||||
|
|
|
|||
|
|
@ -167,17 +167,11 @@ async function main() {
|
|||
deployment.addresses
|
||||
);
|
||||
|
||||
// Extend with LLM client
|
||||
// Extend with LLM client (only for encoding the demand, no API calls needed)
|
||||
const llmClient = client.extend((c) => ({
|
||||
llm: makeLLMClient([]),
|
||||
}));
|
||||
|
||||
// Add OpenAI provider (needed for encoding demands)
|
||||
llmClient.llm.addProvider({
|
||||
providerName: "OpenAI",
|
||||
apiKey: process.env.OPENAI_API_KEY || "",
|
||||
});
|
||||
|
||||
// Check token balance
|
||||
const tokenBalance = await walletClient.readContract({
|
||||
address: tokenAddress as `0x${string}`,
|
||||
|
|
@ -228,10 +222,16 @@ Fulfillment: {{obligation}}`,
|
|||
console.log(` Recipient: ${escrow.recipient}`);
|
||||
|
||||
console.log("🎯 Next Steps:");
|
||||
console.log("1. Wait for someone to fulfill the obligation");
|
||||
console.log("2. The oracle will arbitrate the fulfillment");
|
||||
console.log("3. If approved, you can collect the escrow");
|
||||
console.log(`\n Escrow UID: ${escrow.uid}`);
|
||||
console.log("1. Someone fulfills the obligation:");
|
||||
console.log(` nla escrow:fulfill \\`);
|
||||
console.log(` --escrow-uid ${escrow.uid} \\`);
|
||||
console.log(` --fulfillment "Yes, the sky is blue" \\`);
|
||||
console.log(` --oracle ${oracleAddress}`);
|
||||
console.log("\n2. The oracle will arbitrate the fulfillment automatically");
|
||||
console.log("\n3. If approved, collect the escrow:");
|
||||
console.log(` nla escrow:collect \\`);
|
||||
console.log(` --escrow-uid ${escrow.uid} \\`);
|
||||
console.log(` --fulfillment-uid <fulfillment-uid>`);
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to create escrow:", error);
|
||||
|
|
|
|||
|
|
@ -178,9 +178,10 @@ async function main() {
|
|||
console.log("✨ Arbitration requested successfully!\n");
|
||||
console.log("🎯 Next Steps:");
|
||||
console.log("1. Wait for the oracle to arbitrate (usually a few seconds)");
|
||||
console.log("2. Check the result with the oracle");
|
||||
console.log("3. If approved, collect the escrow");
|
||||
console.log(`\n Fulfillment UID: ${fulfillmentAttestation.uid}`);
|
||||
console.log("\n2. If approved, collect the escrow:");
|
||||
console.log(` nla escrow:collect \\`);
|
||||
console.log(` --escrow-uid ${escrowUid} \\`);
|
||||
console.log(` --fulfillment-uid ${fulfillmentAttestation.uid}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to fulfill escrow:", error);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"network": "localhost",
|
||||
"chainId": 31337,
|
||||
"rpcUrl": "http://localhost:8545",
|
||||
"deployedAt": "2026-01-02T04:20:18.975Z",
|
||||
"deployedAt": "2026-01-02T05:54:03.735Z",
|
||||
"deployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
"addresses": {
|
||||
"easSchemaRegistry": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
|
||||
|
|
|
|||
|
|
@ -363,9 +363,15 @@ async function main() {
|
|||
|
||||
console.log("\n🎯 Next steps:");
|
||||
console.log("1. Start the oracle:");
|
||||
console.log(" ./scripts/start-oracle.sh " + network);
|
||||
console.log("\n2. Create an escrow:");
|
||||
console.log(` bun run escrow:create --demand "Your demand" --amount 10 --token ${addresses.mockERC20A} --oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 --private-key 0xac09...`);
|
||||
console.log(` nla start-oracle`);
|
||||
console.log("\n2. Export your private key (use a test account private key):");
|
||||
console.log(` export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80`);
|
||||
console.log("\n3. Create an escrow:");
|
||||
console.log(` nla escrow:create \\`);
|
||||
console.log(` --demand "The sky is blue" \\`);
|
||||
console.log(` --amount 10 \\`);
|
||||
console.log(` --token ${addresses.mockERC20A} \\`);
|
||||
console.log(` --oracle 0x70997970C51812dc3A010C7d01b50e0d17dc79C8`);
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
|
|
|
|||
123
nla.ts
123
nla.ts
|
|
@ -1,3 +1,49 @@
|
|||
/**
|
||||
* Natural Language Agreement (NLA) Client
|
||||
*
|
||||
* Supports multiple LLM providers for arbitration:
|
||||
*
|
||||
* 1. OpenAI:
|
||||
* - providerName: "OpenAI"
|
||||
* - models: "gpt-4", "gpt-4-turbo", "gpt-3.5-turbo", etc.
|
||||
* - Get API key from: https://platform.openai.com/api-keys
|
||||
*
|
||||
* 2. Anthropic (Claude):
|
||||
* - providerName: "Anthropic" or "Claude"
|
||||
* - models: "claude-3-5-sonnet-20241022", "claude-3-opus-20240229", etc.
|
||||
* - Get API key from: https://console.anthropic.com/
|
||||
*
|
||||
* 3. OpenRouter:
|
||||
* - providerName: "OpenRouter"
|
||||
* - models: Any model available on OpenRouter (e.g., "openai/gpt-4", "anthropic/claude-3-opus")
|
||||
* - Get API key from: https://openrouter.ai/keys
|
||||
* - baseURL: "https://openrouter.ai/api/v1" (default)
|
||||
*
|
||||
* Example usage:
|
||||
* ```typescript
|
||||
* const llmClient = makeLLMClient([]);
|
||||
*
|
||||
* // Add OpenAI provider
|
||||
* llmClient.addProvider({
|
||||
* providerName: "OpenAI",
|
||||
* apiKey: "sk-..."
|
||||
* });
|
||||
*
|
||||
* // Add Anthropic provider
|
||||
* llmClient.addProvider({
|
||||
* providerName: "Anthropic",
|
||||
* apiKey: "sk-ant-..."
|
||||
* });
|
||||
*
|
||||
* // Add OpenRouter provider
|
||||
* llmClient.addProvider({
|
||||
* providerName: "OpenRouter",
|
||||
* apiKey: "sk-or-...",
|
||||
* baseURL: "https://openrouter.ai/api/v1"
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
|
||||
import {
|
||||
decodeAbiParameters,
|
||||
encodeAbiParameters,
|
||||
|
|
@ -5,11 +51,13 @@ import {
|
|||
} from "viem";
|
||||
import { generateText } from "ai";
|
||||
import { createOpenAI } from "@ai-sdk/openai";
|
||||
import { createAnthropic } from "@ai-sdk/anthropic";
|
||||
|
||||
|
||||
export type LLMProvider = {
|
||||
providerName: string;
|
||||
apiKey?: string;
|
||||
baseURL?: string; // For OpenRouter or custom endpoints
|
||||
};
|
||||
|
||||
export type LLMDemand = {
|
||||
|
|
@ -47,32 +95,69 @@ export const makeLLMClient = (
|
|||
}
|
||||
|
||||
console.log(`Using provider: ${selectedProvider.providerName} for arbitration demand: ${JSON.stringify(demand)}`);
|
||||
if (selectedProvider.providerName.toLowerCase() === 'openai') {
|
||||
|
||||
// Replace placeholders with actual values
|
||||
const promptTemplate = `${demand.arbitrationPrompt}`
|
||||
.replace(/\{\{demand\}\}/g, demand.demand)
|
||||
.replace(/\{\{obligation\}\}/g, obligation);
|
||||
|
||||
const systemPrompt = "You are an arbitrator that always tells the truth. You must respond with only 'true' or 'false' - no other words or explanations.";
|
||||
const userPrompt = `${promptTemplate}
|
||||
Based on the above information, determine if the fulfillment satisfies the demand.
|
||||
Answer ONLY with 'true' or 'false' - no explanations or additional text.`;
|
||||
|
||||
let text: string;
|
||||
const providerName = selectedProvider.providerName.toLowerCase();
|
||||
|
||||
if (providerName === 'openai' || providerName.includes('openai')) {
|
||||
const openai = createOpenAI({
|
||||
apiKey: selectedProvider.apiKey,
|
||||
})
|
||||
|
||||
// Replace placeholders with actual values
|
||||
const promptTemplate = `${demand.arbitrationPrompt}`
|
||||
.replace(/\{\{demand\}\}/g, demand.demand)
|
||||
.replace(/\{\{obligation\}\}/g, obligation);
|
||||
|
||||
|
||||
const { text } = await generateText({
|
||||
model: openai(demand.arbitrationModel),
|
||||
system: "You are an arbitrator that always tells the truth. You must respond with only 'true' or 'false' - no other words or explanations.",
|
||||
prompt: `${promptTemplate}
|
||||
Based on the above information, determine if the fulfillment satisfies the demand.
|
||||
Answer ONLY with 'true' or 'false' - no explanations or additional text.`
|
||||
baseURL: selectedProvider.baseURL,
|
||||
});
|
||||
|
||||
console.log(`LLM Response: ${text}`);
|
||||
const result = await generateText({
|
||||
model: openai(demand.arbitrationModel),
|
||||
system: systemPrompt,
|
||||
prompt: userPrompt,
|
||||
});
|
||||
text = result.text;
|
||||
|
||||
const cleanedResponse = text.trim().toLowerCase();
|
||||
return cleanedResponse === 'true';
|
||||
} else if (providerName === 'anthropic' || providerName.includes('anthropic') || providerName.includes('claude')) {
|
||||
const anthropic = createAnthropic({
|
||||
apiKey: selectedProvider.apiKey,
|
||||
baseURL: selectedProvider.baseURL,
|
||||
});
|
||||
|
||||
const result = await generateText({
|
||||
model: anthropic(demand.arbitrationModel),
|
||||
system: systemPrompt,
|
||||
prompt: userPrompt,
|
||||
});
|
||||
text = result.text;
|
||||
|
||||
} else if (providerName === 'openrouter' || providerName.includes('openrouter')) {
|
||||
// OpenRouter uses OpenAI-compatible API
|
||||
const openrouter = createOpenAI({
|
||||
apiKey: selectedProvider.apiKey,
|
||||
baseURL: selectedProvider.baseURL,
|
||||
});
|
||||
|
||||
const result = await generateText({
|
||||
model: openrouter(demand.arbitrationModel),
|
||||
system: systemPrompt,
|
||||
prompt: userPrompt,
|
||||
});
|
||||
text = result.text;
|
||||
|
||||
} else {
|
||||
throw new Error(`Unsupported provider: ${selectedProvider.providerName}`);
|
||||
}
|
||||
return false;
|
||||
|
||||
console.log(`LLM Response: ${text}`);
|
||||
|
||||
const cleanedResponse = text.trim().toLowerCase();
|
||||
return cleanedResponse === 'true';
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error in LLM arbitration:', error);
|
||||
throw new Error(`LLM arbitration failed: ${error}`);
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@
|
|||
"typescript": "^5.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "^2.0.50",
|
||||
"@ai-sdk/anthropic": "^3.0.2",
|
||||
"@ai-sdk/openai": "^3.0.2",
|
||||
"@viem/anvil": "^0.0.10",
|
||||
"ai": "^5.0.68",
|
||||
"ai": "^6.0.5",
|
||||
"alkahest-ts": "git+https://github.com/VAR-META-Tech/alkahest.git#ts-package",
|
||||
"arktype": "^2.1.23",
|
||||
"viem": "^2.42.1",
|
||||
|
|
|
|||
Loading…
Reference in New Issue