@kroxy/kroxy 1.0.0 → 1.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kroxy/kroxy",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "description": "Trustless agent-to-agent payments via USDC escrow on Base blockchain",
6
6
  "license": "MIT",
@@ -10,12 +10,15 @@
10
10
  ".": "./dist/index.js"
11
11
  },
12
12
  "openclaw": {
13
- "extensions": ["./index.ts"]
14
- },
15
- "scripts": {
16
- "build": "tsc",
17
- "dev": "tsc --watch"
13
+ "extensions": [
14
+ "./index.ts"
15
+ ]
18
16
  },
17
+ "files": [
18
+ "dist",
19
+ "index.ts",
20
+ "openclaw.plugin.json"
21
+ ],
19
22
  "dependencies": {
20
23
  "@sinclair/typebox": "^0.32.0"
21
24
  },
@@ -25,5 +28,9 @@
25
28
  },
26
29
  "peerDependencies": {
27
30
  "openclaw": "*"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc",
34
+ "dev": "tsc --watch"
28
35
  }
29
- }
36
+ }
package/api.ts DELETED
@@ -1,3 +0,0 @@
1
- // Public exports for external consumers of this plugin.
2
- // Internal plugin code should import from ./src/* directly.
3
- export type { AgentProfile, Job, Bid, ConditionsDefinition, ReputationResult } from './src/client.js';
package/src/client.ts DELETED
@@ -1,154 +0,0 @@
1
- /**
2
- * Kroxy REST API client.
3
- * Reads KROXY_API_URL and KROXY_API_KEY from process.env at call time,
4
- * so runtime-injected env vars are always used.
5
- */
6
-
7
- export interface AgentProfile {
8
- walletAddress: string;
9
- name: string;
10
- capabilities: string[];
11
- pricingUsdc: string;
12
- endpoint: string;
13
- }
14
-
15
- export interface Job {
16
- id: string;
17
- status: 'OPEN' | 'AWARDED' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED';
18
- bids?: Bid[];
19
- deliverable?: Record<string, unknown> | null;
20
- escrowId?: string | null;
21
- posterWallet: string;
22
- description: string;
23
- }
24
-
25
- export interface Bid {
26
- id: string;
27
- providerWallet: string;
28
- priceUsdc: string;
29
- status: 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'WITHDRAWN';
30
- }
31
-
32
- export interface ConditionsDefinition {
33
- version: '1.0';
34
- escrowId: string;
35
- conditions: Condition[];
36
- windowSeconds: number;
37
- checkIntervalSeconds: number;
38
- requiredPassRate: number;
39
- }
40
-
41
- export interface Condition {
42
- type: 'http_status' | 'json_field' | 'latency_ms' | 'uptime_percent';
43
- endpoint: string;
44
- field?: string;
45
- operator: 'eq' | 'gte' | 'lte' | 'contains';
46
- expected: string | number | boolean;
47
- }
48
-
49
- export interface ReputationResult {
50
- walletAddress: string;
51
- successCount: number;
52
- disputeCount: number;
53
- totalEarned: string;
54
- score: number;
55
- }
56
-
57
- function apiBase(): string {
58
- return process.env.KROXY_API_URL ?? 'http://localhost:3001';
59
- }
60
-
61
- function authHeaders(): Record<string, string> {
62
- const key = process.env.KROXY_API_KEY ?? '';
63
- return {
64
- 'Content-Type': 'application/json',
65
- 'X-Kroxy-API-Key': key,
66
- };
67
- }
68
-
69
- async function apiGet<T>(path: string): Promise<T> {
70
- const res = await fetch(`${apiBase()}${path}`, { headers: authHeaders() });
71
- if (!res.ok) throw new Error(`GET ${path} → ${res.status}: ${await res.text()}`);
72
- return res.json() as Promise<T>;
73
- }
74
-
75
- async function apiPost<T>(path: string, body: unknown): Promise<T> {
76
- const res = await fetch(`${apiBase()}${path}`, {
77
- method: 'POST',
78
- headers: authHeaders(),
79
- body: JSON.stringify(body),
80
- });
81
- if (!res.ok) throw new Error(`POST ${path} → ${res.status}: ${await res.text()}`);
82
- return res.json() as Promise<T>;
83
- }
84
-
85
- export function findAgents(capability: string, maxPrice: number): Promise<AgentProfile[]> {
86
- return apiGet(`/api/agents/find?capability=${encodeURIComponent(capability)}&maxPrice=${maxPrice}`);
87
- }
88
-
89
- export function postJob(
90
- jobId: string,
91
- description: string,
92
- capability: string,
93
- budgetUsdc: number,
94
- conditionsJson: ConditionsDefinition,
95
- posterWallet: string,
96
- ): Promise<Job> {
97
- const deadline = new Date(Date.now() + 30 * 60 * 1000).toISOString();
98
- return apiPost('/api/jobs', {
99
- id: jobId,
100
- posterWallet,
101
- description,
102
- budgetMaxUsdc: budgetUsdc,
103
- requiredCaps: [capability],
104
- deadline,
105
- conditionsJson,
106
- });
107
- }
108
-
109
- export function acceptBid(
110
- jobId: string,
111
- bidId: string,
112
- payerPrivateKey: string,
113
- ): Promise<{ jobId: string; bidId: string; escrowId: string; txHash: string }> {
114
- return apiPost(`/api/jobs/${jobId}/accept/${bidId}`, { payerPrivateKey });
115
- }
116
-
117
- export async function pollJob(
118
- jobId: string,
119
- condition: (job: Job) => boolean,
120
- maxMs = 300_000,
121
- intervalMs = 5_000,
122
- ): Promise<Job | null> {
123
- const deadline = Date.now() + maxMs;
124
- while (Date.now() < deadline) {
125
- const job = await apiGet<Job>(`/api/jobs/${jobId}`);
126
- if (condition(job)) return job;
127
- await new Promise<void>((r) => setTimeout(r, intervalMs));
128
- }
129
- return null;
130
- }
131
-
132
- export function getReputation(walletAddress: string): Promise<ReputationResult> {
133
- return apiGet(`/api/reputation/${walletAddress}`);
134
- }
135
-
136
- export function registerProvider(opts: {
137
- walletAddress: string;
138
- name: string;
139
- endpoint: string;
140
- capabilities: string[];
141
- pricingUsdc: number;
142
- modelName?: string;
143
- }): Promise<AgentProfile> {
144
- return apiPost('/api/agents/register', {
145
- walletAddress: opts.walletAddress,
146
- name: opts.name,
147
- endpoint: opts.endpoint,
148
- modelName: opts.modelName,
149
- capabilities: opts.capabilities,
150
- pricingUsdc: opts.pricingUsdc,
151
- slaUptimePct: 99,
152
- slaResponseMs: 30000,
153
- });
154
- }
package/src/tools/hire.ts DELETED
@@ -1,111 +0,0 @@
1
- import { randomBytes } from 'node:crypto';
2
- import { Type } from '@sinclair/typebox';
3
- import type { ConditionsDefinition } from '../client.js';
4
- import {
5
- findAgents,
6
- postJob,
7
- acceptBid,
8
- pollJob,
9
- } from '../client.js';
10
-
11
- export const hireParams = Type.Object({
12
- task: Type.String({ description: 'What you want the hired agent to do, e.g. "Research the top AI payment startups"' }),
13
- maxPrice: Type.Optional(Type.Number({ minimum: 0.01, description: 'Maximum USDC budget, default 5.00' })),
14
- capability: Type.Optional(Type.String({ description: 'Agent capability to match: research, writing, coding. Auto-detected from task if omitted.' })),
15
- });
16
-
17
- function detectCapability(task: string): string {
18
- if (/research|find|search|analyz|summariz|look up/i.test(task)) return 'research';
19
- if (/write|draft|essay|blog|article|copy/i.test(task)) return 'writing';
20
- if (/code|script|function|implement|build|program/i.test(task)) return 'coding';
21
- return 'research';
22
- }
23
-
24
- function buildConditions(nexusUrl: string, jobId: string): ConditionsDefinition {
25
- return {
26
- version: '1.0',
27
- escrowId: '',
28
- conditions: [
29
- { type: 'http_status', endpoint: `${nexusUrl}/health`, operator: 'eq', expected: 200 },
30
- {
31
- type: 'json_field',
32
- endpoint: `${nexusUrl}/quality-check?jobId=${encodeURIComponent(jobId)}`,
33
- field: 'wordCount',
34
- operator: 'gte',
35
- expected: 100,
36
- },
37
- {
38
- type: 'json_field',
39
- endpoint: `${nexusUrl}/quality-check?jobId=${encodeURIComponent(jobId)}`,
40
- field: 'confidence',
41
- operator: 'gte',
42
- expected: 0.7,
43
- },
44
- ],
45
- windowSeconds: 120,
46
- checkIntervalSeconds: 10,
47
- requiredPassRate: 0.8,
48
- };
49
- }
50
-
51
- export async function executeHire(
52
- params: { task: string; maxPrice?: number; capability?: string },
53
- ): Promise<{ content: [{ type: 'text'; text: string }]; details: unknown }> {
54
- const wallet = process.env.KROXY_AGENT_WALLET;
55
- const privateKey = process.env.KROXY_AGENT_PRIVATE_KEY;
56
- const nexusUrl = process.env.NEXUS_URL ?? 'http://localhost:3003';
57
- const demoMode = process.env.KROXY_DEMO_MODE === '1';
58
-
59
- if (!wallet) throw new Error('KROXY_AGENT_WALLET is not configured');
60
- if (!demoMode && !privateKey) throw new Error('KROXY_AGENT_PRIVATE_KEY is not configured');
61
-
62
- const task = params.task;
63
- const maxPrice = params.maxPrice ?? 5.0;
64
- const capability = params.capability ?? detectCapability(task);
65
- const payerPrivateKey = privateKey ?? 'demo-private-key';
66
- const jobId = `job_${Date.now()}_${randomBytes(3).toString('hex')}`;
67
-
68
- // 1. Find matching agents
69
- const agents = await findAgents(capability, maxPrice);
70
- if (!agents.length) {
71
- throw new Error(`No agents available for "${capability}" within $${maxPrice} USDC`);
72
- }
73
-
74
- // 2. Post job with verifier conditions pointing at Nexus
75
- const conditions = buildConditions(nexusUrl, jobId);
76
- const job = await postJob(jobId, task, capability, maxPrice, conditions, wallet);
77
-
78
- // 3. Wait for a bid (up to 60s)
79
- const jobWithBid = await pollJob(job.id, (j) => Boolean(j.bids?.length), 60_000);
80
- if (!jobWithBid?.bids?.length) {
81
- throw new Error(`No bids received within 60 seconds (jobId: ${job.id})`);
82
- }
83
-
84
- const bid = jobWithBid.bids[0];
85
-
86
- // 4. Accept bid — locks USDC in escrow on Base
87
- const escrowResult = await acceptBid(job.id, bid.id, payerPrivateKey);
88
-
89
- // 5. Poll for completion (up to 5 minutes)
90
- const completed = await pollJob(job.id, (j) => j.status === 'COMPLETED', 300_000);
91
- if (!completed) {
92
- throw new Error(
93
- `Job timed out (jobId: ${job.id}, escrowId: ${escrowResult.escrowId}). ` +
94
- `Funds are in escrow — check status at /api/jobs/${job.id}`,
95
- );
96
- }
97
-
98
- const result = {
99
- summary: (completed.deliverable as any)?.summary ?? '(no summary)',
100
- keyFindings: (completed.deliverable as any)?.keyFindings ?? [],
101
- sources: (completed.deliverable as any)?.sources ?? [],
102
- agent: bid.providerWallet,
103
- amountPaid: `${bid.priceUsdc} USDC`,
104
- auditTrail: `https://kroxy.ai/audit/${escrowResult.escrowId}`,
105
- };
106
-
107
- return {
108
- content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
109
- details: result,
110
- };
111
- }
@@ -1,41 +0,0 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { registerProvider } from '../client.js';
3
-
4
- export const offerParams = Type.Object({
5
- capability: Type.String({ description: 'Capability to offer: research, writing, coding, analysis, etc.' }),
6
- price: Type.Number({ minimum: 0.01, description: 'Price per job in USDC, e.g. 2.50' }),
7
- endpoint: Type.String({ description: 'Public URL where your agent receives job webhooks, e.g. https://myagent.example.com' }),
8
- name: Type.Optional(Type.String({ description: 'Display name for your agent on the Kroxy job board' })),
9
- });
10
-
11
- export async function executeOffer(
12
- params: { capability: string; price: number; endpoint: string; name?: string },
13
- ): Promise<{ content: [{ type: 'text'; text: string }]; details: unknown }> {
14
- const wallet = process.env.KROXY_AGENT_WALLET;
15
- if (!wallet) throw new Error('KROXY_AGENT_WALLET is not configured');
16
-
17
- const agent = await registerProvider({
18
- walletAddress: wallet,
19
- name: params.name ?? 'MyAgent',
20
- endpoint: params.endpoint,
21
- capabilities: [params.capability],
22
- pricingUsdc: params.price,
23
- });
24
-
25
- const result = {
26
- registered: true,
27
- walletAddress: agent.walletAddress ?? wallet,
28
- name: agent.name ?? params.name,
29
- capabilities: agent.capabilities ?? [params.capability],
30
- pricingUsdc: agent.pricingUsdc ?? params.price,
31
- endpoint: params.endpoint,
32
- };
33
-
34
- return {
35
- content: [{
36
- type: 'text',
37
- text: JSON.stringify(result, null, 2),
38
- }],
39
- details: result,
40
- };
41
- }
@@ -1,41 +0,0 @@
1
- import { Type } from '@sinclair/typebox';
2
- import { getReputation } from '../client.js';
3
-
4
- export const reputationParams = Type.Object({
5
- wallet: Type.Optional(Type.String({
6
- description: 'Wallet address to look up. Defaults to KROXY_AGENT_WALLET (your own agent).',
7
- pattern: '^0x[0-9a-fA-F]{40}$',
8
- })),
9
- });
10
-
11
- export async function executeReputation(
12
- params: { wallet?: string },
13
- ): Promise<{ content: [{ type: 'text'; text: string }]; details: unknown }> {
14
- const walletAddress = params.wallet ?? process.env.KROXY_AGENT_WALLET;
15
- if (!walletAddress) throw new Error('No wallet address provided and KROXY_AGENT_WALLET is not configured');
16
-
17
- const rep = await getReputation(walletAddress);
18
- const score = rep.score ?? 0;
19
- const interpretation =
20
- score >= 80 ? 'Excellent — highly trusted agent' :
21
- score >= 60 ? 'Good — established track record' :
22
- score >= 20 ? 'New — building reputation' :
23
- 'Low — exercise caution';
24
-
25
- const result = {
26
- address: walletAddress,
27
- score,
28
- successCount: rep.successCount ?? 0,
29
- disputeCount: rep.disputeCount ?? 0,
30
- totalEarned: rep.totalEarned ?? '0',
31
- interpretation,
32
- };
33
-
34
- return {
35
- content: [{
36
- type: 'text',
37
- text: JSON.stringify(result, null, 2),
38
- }],
39
- details: result,
40
- };
41
- }
package/tsconfig.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "forceConsistentCasingInFileNames": true,
10
- "declaration": true,
11
- "declarationMap": true,
12
- "sourceMap": true,
13
- "rootDir": ".",
14
- "outDir": "./dist"
15
- },
16
- "include": ["index.ts", "api.ts", "src/**/*.ts"],
17
- "exclude": ["dist", "node_modules"]
18
- }