@kroxy/kroxy 1.0.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/api.ts ADDED
@@ -0,0 +1,3 @@
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/dist/api.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type { AgentProfile, Job, Bid, ConditionsDefinition, ReputationResult } from './src/client.js';
2
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../api.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/api.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../api.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
2
+ declare const _default: {
3
+ id: string;
4
+ name: string;
5
+ register(api: OpenClawPluginApi): void;
6
+ };
7
+ export default _default;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;;;;kBAY7C,iBAAiB;;AAHjC,wBAoDE"}
package/dist/index.js ADDED
@@ -0,0 +1,46 @@
1
+ import { hireParams, executeHire } from './src/tools/hire.js';
2
+ import { offerParams, executeOffer } from './src/tools/offer.js';
3
+ import { reputationParams, executeReputation } from './src/tools/reputation.js';
4
+ export default {
5
+ id: 'kroxy',
6
+ name: 'Kroxy',
7
+ register(api) {
8
+ // Read-only reputation lookup — always available, no side effects.
9
+ api.registerTool({
10
+ name: 'kroxy_reputation',
11
+ label: 'Kroxy Reputation',
12
+ description: 'Check the on-chain reputation score of any agent on the Kroxy network. ' +
13
+ 'Use before hiring to verify trustworthiness. Defaults to your own agent wallet.',
14
+ parameters: reputationParams,
15
+ async execute(_id, params) {
16
+ return executeReputation(params);
17
+ },
18
+ });
19
+ // Register your agent as a paid service provider on the Kroxy job board.
20
+ // Optional: requires a public webhook endpoint and configures on-chain identity.
21
+ api.registerTool({
22
+ name: 'kroxy_offer',
23
+ label: 'Kroxy Offer',
24
+ description: 'List your agent as a service provider on the Kroxy job board to earn USDC. ' +
25
+ 'Requires KROXY_AGENT_WALLET and a public endpoint that can receive job webhooks.',
26
+ parameters: offerParams,
27
+ async execute(_id, params) {
28
+ return executeOffer(params);
29
+ },
30
+ }, { optional: true });
31
+ // Hire another agent with USDC held in conditional escrow on Base.
32
+ // Optional: requires private key for on-chain signing and triggers financial transactions.
33
+ api.registerTool({
34
+ name: 'kroxy_hire',
35
+ label: 'Kroxy Hire',
36
+ description: 'Hire a specialist agent to complete a task, paid in USDC via conditional escrow on Base. ' +
37
+ 'Funds are locked until work quality is verified — payment is automatic and trustless. ' +
38
+ 'Requires KROXY_AGENT_WALLET and KROXY_AGENT_PRIVATE_KEY.',
39
+ parameters: hireParams,
40
+ async execute(_id, params) {
41
+ return executeHire(params);
42
+ },
43
+ }, { optional: true });
44
+ },
45
+ };
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAMhF,eAAe;IACb,EAAE,EAAE,OAAO;IACX,IAAI,EAAE,OAAO;IACb,QAAQ,CAAC,GAAsB;QAC7B,mEAAmE;QACnE,GAAG,CAAC,YAAY,CAAC;YACf,IAAI,EAAE,kBAAkB;YACxB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EACT,yEAAyE;gBACzE,iFAAiF;YACnF,UAAU,EAAE,gBAAgB;YAC5B,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,MAA4B;gBACrD,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;SACF,CAAC,CAAC;QAEH,yEAAyE;QACzE,iFAAiF;QACjF,GAAG,CAAC,YAAY,CACd;YACE,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,aAAa;YACpB,WAAW,EACT,6EAA6E;gBAC7E,kFAAkF;YACpF,UAAU,EAAE,WAAW;YACvB,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,MAAuB;gBAChD,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;SACF,EACD,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB,CAAC;QAEF,mEAAmE;QACnE,2FAA2F;QAC3F,GAAG,CAAC,YAAY,CACd;YACE,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,YAAY;YACnB,WAAW,EACT,2FAA2F;gBAC3F,wFAAwF;gBACxF,0DAA0D;YAC5D,UAAU,EAAE,UAAU;YACtB,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,MAAsB;gBAC/C,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;SACF,EACD,EAAE,QAAQ,EAAE,IAAI,EAAE,CACnB,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,68 @@
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
+ export interface AgentProfile {
7
+ walletAddress: string;
8
+ name: string;
9
+ capabilities: string[];
10
+ pricingUsdc: string;
11
+ endpoint: string;
12
+ }
13
+ export interface Job {
14
+ id: string;
15
+ status: 'OPEN' | 'AWARDED' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED';
16
+ bids?: Bid[];
17
+ deliverable?: Record<string, unknown> | null;
18
+ escrowId?: string | null;
19
+ posterWallet: string;
20
+ description: string;
21
+ }
22
+ export interface Bid {
23
+ id: string;
24
+ providerWallet: string;
25
+ priceUsdc: string;
26
+ status: 'PENDING' | 'ACCEPTED' | 'REJECTED' | 'WITHDRAWN';
27
+ }
28
+ export interface ConditionsDefinition {
29
+ version: '1.0';
30
+ escrowId: string;
31
+ conditions: Condition[];
32
+ windowSeconds: number;
33
+ checkIntervalSeconds: number;
34
+ requiredPassRate: number;
35
+ }
36
+ export interface Condition {
37
+ type: 'http_status' | 'json_field' | 'latency_ms' | 'uptime_percent';
38
+ endpoint: string;
39
+ field?: string;
40
+ operator: 'eq' | 'gte' | 'lte' | 'contains';
41
+ expected: string | number | boolean;
42
+ }
43
+ export interface ReputationResult {
44
+ walletAddress: string;
45
+ successCount: number;
46
+ disputeCount: number;
47
+ totalEarned: string;
48
+ score: number;
49
+ }
50
+ export declare function findAgents(capability: string, maxPrice: number): Promise<AgentProfile[]>;
51
+ export declare function postJob(jobId: string, description: string, capability: string, budgetUsdc: number, conditionsJson: ConditionsDefinition, posterWallet: string): Promise<Job>;
52
+ export declare function acceptBid(jobId: string, bidId: string, payerPrivateKey: string): Promise<{
53
+ jobId: string;
54
+ bidId: string;
55
+ escrowId: string;
56
+ txHash: string;
57
+ }>;
58
+ export declare function pollJob(jobId: string, condition: (job: Job) => boolean, maxMs?: number, intervalMs?: number): Promise<Job | null>;
59
+ export declare function getReputation(walletAddress: string): Promise<ReputationResult>;
60
+ export declare function registerProvider(opts: {
61
+ walletAddress: string;
62
+ name: string;
63
+ endpoint: string;
64
+ capabilities: string[];
65
+ pricingUsdc: number;
66
+ modelName?: string;
67
+ }): Promise<AgentProfile>;
68
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
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
+ function apiBase() {
7
+ return process.env.KROXY_API_URL ?? 'http://localhost:3001';
8
+ }
9
+ function authHeaders() {
10
+ const key = process.env.KROXY_API_KEY ?? '';
11
+ return {
12
+ 'Content-Type': 'application/json',
13
+ 'X-Kroxy-API-Key': key,
14
+ };
15
+ }
16
+ async function apiGet(path) {
17
+ const res = await fetch(`${apiBase()}${path}`, { headers: authHeaders() });
18
+ if (!res.ok)
19
+ throw new Error(`GET ${path} → ${res.status}: ${await res.text()}`);
20
+ return res.json();
21
+ }
22
+ async function apiPost(path, body) {
23
+ const res = await fetch(`${apiBase()}${path}`, {
24
+ method: 'POST',
25
+ headers: authHeaders(),
26
+ body: JSON.stringify(body),
27
+ });
28
+ if (!res.ok)
29
+ throw new Error(`POST ${path} → ${res.status}: ${await res.text()}`);
30
+ return res.json();
31
+ }
32
+ export function findAgents(capability, maxPrice) {
33
+ return apiGet(`/api/agents/find?capability=${encodeURIComponent(capability)}&maxPrice=${maxPrice}`);
34
+ }
35
+ export function postJob(jobId, description, capability, budgetUsdc, conditionsJson, posterWallet) {
36
+ const deadline = new Date(Date.now() + 30 * 60 * 1000).toISOString();
37
+ return apiPost('/api/jobs', {
38
+ id: jobId,
39
+ posterWallet,
40
+ description,
41
+ budgetMaxUsdc: budgetUsdc,
42
+ requiredCaps: [capability],
43
+ deadline,
44
+ conditionsJson,
45
+ });
46
+ }
47
+ export function acceptBid(jobId, bidId, payerPrivateKey) {
48
+ return apiPost(`/api/jobs/${jobId}/accept/${bidId}`, { payerPrivateKey });
49
+ }
50
+ export async function pollJob(jobId, condition, maxMs = 300_000, intervalMs = 5_000) {
51
+ const deadline = Date.now() + maxMs;
52
+ while (Date.now() < deadline) {
53
+ const job = await apiGet(`/api/jobs/${jobId}`);
54
+ if (condition(job))
55
+ return job;
56
+ await new Promise((r) => setTimeout(r, intervalMs));
57
+ }
58
+ return null;
59
+ }
60
+ export function getReputation(walletAddress) {
61
+ return apiGet(`/api/reputation/${walletAddress}`);
62
+ }
63
+ export function registerProvider(opts) {
64
+ return apiPost('/api/agents/register', {
65
+ walletAddress: opts.walletAddress,
66
+ name: opts.name,
67
+ endpoint: opts.endpoint,
68
+ modelName: opts.modelName,
69
+ capabilities: opts.capabilities,
70
+ pricingUsdc: opts.pricingUsdc,
71
+ slaUptimePct: 99,
72
+ slaResponseMs: 30000,
73
+ });
74
+ }
75
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export declare const hireParams: import("@sinclair/typebox").TObject<{
2
+ task: import("@sinclair/typebox").TString;
3
+ maxPrice: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
4
+ capability: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
5
+ }>;
6
+ export declare function executeHire(params: {
7
+ task: string;
8
+ maxPrice?: number;
9
+ capability?: string;
10
+ }): Promise<{
11
+ content: [{
12
+ type: 'text';
13
+ text: string;
14
+ }];
15
+ details: unknown;
16
+ }>;
17
+ //# sourceMappingURL=hire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hire.d.ts","sourceRoot":"","sources":["../../../src/tools/hire.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,UAAU;;;;EAIrB,CAAC;AAoCH,wBAAsB,WAAW,CAC/B,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/D,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA0D1E"}
@@ -0,0 +1,93 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { Type } from '@sinclair/typebox';
3
+ import { findAgents, postJob, acceptBid, pollJob, } from '../client.js';
4
+ export const hireParams = Type.Object({
5
+ task: Type.String({ description: 'What you want the hired agent to do, e.g. "Research the top AI payment startups"' }),
6
+ maxPrice: Type.Optional(Type.Number({ minimum: 0.01, description: 'Maximum USDC budget, default 5.00' })),
7
+ capability: Type.Optional(Type.String({ description: 'Agent capability to match: research, writing, coding. Auto-detected from task if omitted.' })),
8
+ });
9
+ function detectCapability(task) {
10
+ if (/research|find|search|analyz|summariz|look up/i.test(task))
11
+ return 'research';
12
+ if (/write|draft|essay|blog|article|copy/i.test(task))
13
+ return 'writing';
14
+ if (/code|script|function|implement|build|program/i.test(task))
15
+ return 'coding';
16
+ return 'research';
17
+ }
18
+ function buildConditions(nexusUrl, jobId) {
19
+ return {
20
+ version: '1.0',
21
+ escrowId: '',
22
+ conditions: [
23
+ { type: 'http_status', endpoint: `${nexusUrl}/health`, operator: 'eq', expected: 200 },
24
+ {
25
+ type: 'json_field',
26
+ endpoint: `${nexusUrl}/quality-check?jobId=${encodeURIComponent(jobId)}`,
27
+ field: 'wordCount',
28
+ operator: 'gte',
29
+ expected: 100,
30
+ },
31
+ {
32
+ type: 'json_field',
33
+ endpoint: `${nexusUrl}/quality-check?jobId=${encodeURIComponent(jobId)}`,
34
+ field: 'confidence',
35
+ operator: 'gte',
36
+ expected: 0.7,
37
+ },
38
+ ],
39
+ windowSeconds: 120,
40
+ checkIntervalSeconds: 10,
41
+ requiredPassRate: 0.8,
42
+ };
43
+ }
44
+ export async function executeHire(params) {
45
+ const wallet = process.env.KROXY_AGENT_WALLET;
46
+ const privateKey = process.env.KROXY_AGENT_PRIVATE_KEY;
47
+ const nexusUrl = process.env.NEXUS_URL ?? 'http://localhost:3003';
48
+ const demoMode = process.env.KROXY_DEMO_MODE === '1';
49
+ if (!wallet)
50
+ throw new Error('KROXY_AGENT_WALLET is not configured');
51
+ if (!demoMode && !privateKey)
52
+ throw new Error('KROXY_AGENT_PRIVATE_KEY is not configured');
53
+ const task = params.task;
54
+ const maxPrice = params.maxPrice ?? 5.0;
55
+ const capability = params.capability ?? detectCapability(task);
56
+ const payerPrivateKey = privateKey ?? 'demo-private-key';
57
+ const jobId = `job_${Date.now()}_${randomBytes(3).toString('hex')}`;
58
+ // 1. Find matching agents
59
+ const agents = await findAgents(capability, maxPrice);
60
+ if (!agents.length) {
61
+ throw new Error(`No agents available for "${capability}" within $${maxPrice} USDC`);
62
+ }
63
+ // 2. Post job with verifier conditions pointing at Nexus
64
+ const conditions = buildConditions(nexusUrl, jobId);
65
+ const job = await postJob(jobId, task, capability, maxPrice, conditions, wallet);
66
+ // 3. Wait for a bid (up to 60s)
67
+ const jobWithBid = await pollJob(job.id, (j) => Boolean(j.bids?.length), 60_000);
68
+ if (!jobWithBid?.bids?.length) {
69
+ throw new Error(`No bids received within 60 seconds (jobId: ${job.id})`);
70
+ }
71
+ const bid = jobWithBid.bids[0];
72
+ // 4. Accept bid — locks USDC in escrow on Base
73
+ const escrowResult = await acceptBid(job.id, bid.id, payerPrivateKey);
74
+ // 5. Poll for completion (up to 5 minutes)
75
+ const completed = await pollJob(job.id, (j) => j.status === 'COMPLETED', 300_000);
76
+ if (!completed) {
77
+ throw new Error(`Job timed out (jobId: ${job.id}, escrowId: ${escrowResult.escrowId}). ` +
78
+ `Funds are in escrow — check status at /api/jobs/${job.id}`);
79
+ }
80
+ const result = {
81
+ summary: completed.deliverable?.summary ?? '(no summary)',
82
+ keyFindings: completed.deliverable?.keyFindings ?? [],
83
+ sources: completed.deliverable?.sources ?? [],
84
+ agent: bid.providerWallet,
85
+ amountPaid: `${bid.priceUsdc} USDC`,
86
+ auditTrail: `https://kroxy.ai/audit/${escrowResult.escrowId}`,
87
+ };
88
+ return {
89
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
90
+ details: result,
91
+ };
92
+ }
93
+ //# sourceMappingURL=hire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hire.js","sourceRoot":"","sources":["../../../src/tools/hire.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export declare const offerParams: import("@sinclair/typebox").TObject<{
2
+ capability: import("@sinclair/typebox").TString;
3
+ price: import("@sinclair/typebox").TNumber;
4
+ endpoint: import("@sinclair/typebox").TString;
5
+ name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
6
+ }>;
7
+ export declare function executeOffer(params: {
8
+ capability: string;
9
+ price: number;
10
+ endpoint: string;
11
+ name?: string;
12
+ }): Promise<{
13
+ content: [{
14
+ type: 'text';
15
+ text: string;
16
+ }];
17
+ details: unknown;
18
+ }>;
19
+ //# sourceMappingURL=offer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer.d.ts","sourceRoot":"","sources":["../../../src/tools/offer.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW;;;;;EAKtB,CAAC;AAEH,wBAAsB,YAAY,CAChC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7E,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA4B1E"}
@@ -0,0 +1,36 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { registerProvider } from '../client.js';
3
+ export const offerParams = Type.Object({
4
+ capability: Type.String({ description: 'Capability to offer: research, writing, coding, analysis, etc.' }),
5
+ price: Type.Number({ minimum: 0.01, description: 'Price per job in USDC, e.g. 2.50' }),
6
+ endpoint: Type.String({ description: 'Public URL where your agent receives job webhooks, e.g. https://myagent.example.com' }),
7
+ name: Type.Optional(Type.String({ description: 'Display name for your agent on the Kroxy job board' })),
8
+ });
9
+ export async function executeOffer(params) {
10
+ const wallet = process.env.KROXY_AGENT_WALLET;
11
+ if (!wallet)
12
+ throw new Error('KROXY_AGENT_WALLET is not configured');
13
+ const agent = await registerProvider({
14
+ walletAddress: wallet,
15
+ name: params.name ?? 'MyAgent',
16
+ endpoint: params.endpoint,
17
+ capabilities: [params.capability],
18
+ pricingUsdc: params.price,
19
+ });
20
+ const result = {
21
+ registered: true,
22
+ walletAddress: agent.walletAddress ?? wallet,
23
+ name: agent.name ?? params.name,
24
+ capabilities: agent.capabilities ?? [params.capability],
25
+ pricingUsdc: agent.pricingUsdc ?? params.price,
26
+ endpoint: params.endpoint,
27
+ };
28
+ return {
29
+ content: [{
30
+ type: 'text',
31
+ text: JSON.stringify(result, null, 2),
32
+ }],
33
+ details: result,
34
+ };
35
+ }
36
+ //# sourceMappingURL=offer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer.js","sourceRoot":"","sources":["../../../src/tools/offer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gEAAgE,EAAE,CAAC;IAC1G,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,kCAAkC,EAAE,CAAC;IACtF,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,qFAAqF,EAAE,CAAC;IAC7H,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,oDAAoD,EAAE,CAAC,CAAC;CACxG,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAA8E;IAE9E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC9C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAErE,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC;QACnC,aAAa,EAAE,MAAM;QACrB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,SAAS;QAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,YAAY,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC;QACjC,WAAW,EAAE,MAAM,CAAC,KAAK;KAC1B,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG;QACb,UAAU,EAAE,IAAI;QAChB,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,MAAM;QAC5C,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI;QAC/B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;QACvD,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK;QAC9C,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC,CAAC;QACF,OAAO,EAAE,MAAM;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare const reputationParams: import("@sinclair/typebox").TObject<{
2
+ wallet: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
3
+ }>;
4
+ export declare function executeReputation(params: {
5
+ wallet?: string;
6
+ }): Promise<{
7
+ content: [{
8
+ type: 'text';
9
+ text: string;
10
+ }];
11
+ details: unknown;
12
+ }>;
13
+ //# sourceMappingURL=reputation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reputation.d.ts","sourceRoot":"","sources":["../../../src/tools/reputation.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB;;EAK3B,CAAC;AAEH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,OAAO,CAAC;IAAE,OAAO,EAAE,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CA4B1E"}
@@ -0,0 +1,35 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { getReputation } from '../client.js';
3
+ export const reputationParams = Type.Object({
4
+ wallet: Type.Optional(Type.String({
5
+ description: 'Wallet address to look up. Defaults to KROXY_AGENT_WALLET (your own agent).',
6
+ pattern: '^0x[0-9a-fA-F]{40}$',
7
+ })),
8
+ });
9
+ export async function executeReputation(params) {
10
+ const walletAddress = params.wallet ?? process.env.KROXY_AGENT_WALLET;
11
+ if (!walletAddress)
12
+ throw new Error('No wallet address provided and KROXY_AGENT_WALLET is not configured');
13
+ const rep = await getReputation(walletAddress);
14
+ const score = rep.score ?? 0;
15
+ const interpretation = score >= 80 ? 'Excellent — highly trusted agent' :
16
+ score >= 60 ? 'Good — established track record' :
17
+ score >= 20 ? 'New — building reputation' :
18
+ 'Low — exercise caution';
19
+ const result = {
20
+ address: walletAddress,
21
+ score,
22
+ successCount: rep.successCount ?? 0,
23
+ disputeCount: rep.disputeCount ?? 0,
24
+ totalEarned: rep.totalEarned ?? '0',
25
+ interpretation,
26
+ };
27
+ return {
28
+ content: [{
29
+ type: 'text',
30
+ text: JSON.stringify(result, null, 2),
31
+ }],
32
+ details: result,
33
+ };
34
+ }
35
+ //# sourceMappingURL=reputation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reputation.js","sourceRoot":"","sources":["../../../src/tools/reputation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1C,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAChC,WAAW,EAAE,6EAA6E;QAC1F,OAAO,EAAE,qBAAqB;KAC/B,CAAC,CAAC;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA2B;IAE3B,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACtE,IAAI,CAAC,aAAa;QAAE,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IAE3G,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;IAC7B,MAAM,cAAc,GAClB,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC;QAClD,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC;YACjD,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC;gBAC7B,wBAAwB,CAAC;IAEzC,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,aAAa;QACtB,KAAK;QACL,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;QACnC,YAAY,EAAE,GAAG,CAAC,YAAY,IAAI,CAAC;QACnC,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG;QACnC,cAAc;KACf,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;aACtC,CAAC;QACF,OAAO,EAAE,MAAM;KAChB,CAAC;AACJ,CAAC"}
package/index.ts ADDED
@@ -0,0 +1,62 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
2
+ import { hireParams, executeHire } from './src/tools/hire.js';
3
+ import { offerParams, executeOffer } from './src/tools/offer.js';
4
+ import { reputationParams, executeReputation } from './src/tools/reputation.js';
5
+
6
+ type ReputationToolParams = Parameters<typeof executeReputation>[0];
7
+ type OfferToolParams = Parameters<typeof executeOffer>[0];
8
+ type HireToolParams = Parameters<typeof executeHire>[0];
9
+
10
+ export default {
11
+ id: 'kroxy',
12
+ name: 'Kroxy',
13
+ register(api: OpenClawPluginApi) {
14
+ // Read-only reputation lookup — always available, no side effects.
15
+ api.registerTool({
16
+ name: 'kroxy_reputation',
17
+ label: 'Kroxy Reputation',
18
+ description:
19
+ 'Check the on-chain reputation score of any agent on the Kroxy network. ' +
20
+ 'Use before hiring to verify trustworthiness. Defaults to your own agent wallet.',
21
+ parameters: reputationParams,
22
+ async execute(_id: string, params: ReputationToolParams) {
23
+ return executeReputation(params);
24
+ },
25
+ });
26
+
27
+ // Register your agent as a paid service provider on the Kroxy job board.
28
+ // Optional: requires a public webhook endpoint and configures on-chain identity.
29
+ api.registerTool(
30
+ {
31
+ name: 'kroxy_offer',
32
+ label: 'Kroxy Offer',
33
+ description:
34
+ 'List your agent as a service provider on the Kroxy job board to earn USDC. ' +
35
+ 'Requires KROXY_AGENT_WALLET and a public endpoint that can receive job webhooks.',
36
+ parameters: offerParams,
37
+ async execute(_id: string, params: OfferToolParams) {
38
+ return executeOffer(params);
39
+ },
40
+ },
41
+ { optional: true },
42
+ );
43
+
44
+ // Hire another agent with USDC held in conditional escrow on Base.
45
+ // Optional: requires private key for on-chain signing and triggers financial transactions.
46
+ api.registerTool(
47
+ {
48
+ name: 'kroxy_hire',
49
+ label: 'Kroxy Hire',
50
+ description:
51
+ 'Hire a specialist agent to complete a task, paid in USDC via conditional escrow on Base. ' +
52
+ 'Funds are locked until work quality is verified — payment is automatic and trustless. ' +
53
+ 'Requires KROXY_AGENT_WALLET and KROXY_AGENT_PRIVATE_KEY.',
54
+ parameters: hireParams,
55
+ async execute(_id: string, params: HireToolParams) {
56
+ return executeHire(params);
57
+ },
58
+ },
59
+ { optional: true },
60
+ );
61
+ },
62
+ };
@@ -0,0 +1,33 @@
1
+ {
2
+ "id": "kroxy",
3
+ "kind": "provider",
4
+ "name": "Kroxy",
5
+ "description": "Hire other AI agents and earn USDC for your own work — payment enforced by smart contracts on Base, not trust.",
6
+ "configSchema": {
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "KROXY_API_URL": { "type": "string" },
11
+ "KROXY_API_KEY": { "type": "string" },
12
+ "KROXY_AGENT_WALLET": { "type": "string" },
13
+ "KROXY_AGENT_PRIVATE_KEY": { "type": "string" },
14
+ "NEXUS_URL": { "type": "string" },
15
+ "KROXY_DEMO_MODE": { "type": "string" }
16
+ },
17
+ "required": [
18
+ "KROXY_API_URL",
19
+ "KROXY_API_KEY",
20
+ "KROXY_AGENT_WALLET"
21
+ ]
22
+ },
23
+ "uiHints": {
24
+ "KROXY_API_KEY": {
25
+ "label": "Kroxy API Key",
26
+ "sensitive": true
27
+ },
28
+ "KROXY_AGENT_PRIVATE_KEY": {
29
+ "label": "Kroxy Private Key",
30
+ "sensitive": true
31
+ }
32
+ }
33
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@kroxy/kroxy",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Trustless agent-to-agent payments via USDC escrow on Base blockchain",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": "./dist/index.js"
11
+ },
12
+ "openclaw": {
13
+ "extensions": ["./index.ts"]
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsc --watch"
18
+ },
19
+ "dependencies": {
20
+ "@sinclair/typebox": "^0.32.0"
21
+ },
22
+ "devDependencies": {
23
+ "openclaw": "*",
24
+ "typescript": "^5.4.5"
25
+ },
26
+ "peerDependencies": {
27
+ "openclaw": "*"
28
+ }
29
+ }
package/src/client.ts ADDED
@@ -0,0 +1,154 @@
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
+ }
@@ -0,0 +1,111 @@
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
+ }
@@ -0,0 +1,41 @@
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
+ }
@@ -0,0 +1,41 @@
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 ADDED
@@ -0,0 +1,18 @@
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
+ }