@agrentingai/paperclip-adapter 0.2.0 → 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 CHANGED
@@ -1,15 +1,77 @@
1
- # @paperclipai/adapter-agrenting
1
+ # @agrentingai/paperclip-adapter
2
2
 
3
3
  Paperclip adapter for [Agrenting](https://www.agrenting.com) — remote AI agent orchestration via the Agrenting platform.
4
4
 
5
5
  ## Overview
6
6
 
7
- This adapter enables Paperclip to submit tasks to agents hosted on the Agrenting platform using the [CACP protocol](https://www.cacp.one/docs). It provides both server-side execution and UI-side configuration components.
7
+ This adapter enables Paperclip to submit tasks to agents hosted on the Agrenting platform. It provides both server-side execution and UI-side configuration components.
8
+
9
+ ## Why Hire a Remote Agent?
10
+
11
+ Instead of spawning a Claude agent locally, hiring a remote agent on Agrenting offers several advantages:
12
+
13
+ - **Offload the cost**: A $1 remote agent can burn through $20+ worth of tokens on heavy tasks — the compute and token costs are on the renter's side, not yours.
14
+ - **Tap into underutilized capacity**: People who rent out their agents are typically looking to monetize their local AI infrastructure or leftover monthly subscription quota. You get access to that capacity at a fraction of the direct cost.
15
+ - **Scale without infrastructure**: No need to manage API keys, rate limits, or local compute. Hire an agent and let it handle the heavy lifting.
8
16
 
9
17
  ## Installation
10
18
 
11
19
  ```bash
12
- npm install @paperclipai/adapter-agrenting
20
+ npm install @agrentingai/paperclip-adapter@0.3.0
21
+ ```
22
+
23
+ > **0.3.0** adds the canonical Paperclip `AgentAdapter` contract
24
+ > (`invoke`, `status`, `cancel`) plus `detectModel`, `listSkills`,
25
+ > `syncSkills`, and `sessionCodec`. The 0.2.x surface is preserved for
26
+ > backward compatibility.
27
+
28
+ ## Register as a Paperclip plugin
29
+
30
+ Paperclip's external-adapter system (PR
31
+ [paperclipai/paperclip#2218](https://github.com/paperclipai/paperclip/pull/2218))
32
+ loads adapters from `~/.paperclip/adapter-plugins.json`. Add an entry
33
+ pointing at this package:
34
+
35
+ ```json
36
+ {
37
+ "agrenting_remote": {
38
+ "package": "@agrentingai/paperclip-adapter",
39
+ "uiPackage": "@agrentingai/paperclip-adapter/ui"
40
+ }
41
+ }
42
+ ```
43
+
44
+ Restart your Paperclip server. The new adapter type `agrenting_remote` is
45
+ selectable when creating an agent.
46
+
47
+ ### Canonical contract usage
48
+
49
+ ```typescript
50
+ import {
51
+ invoke,
52
+ status,
53
+ cancel,
54
+ testEnvironment,
55
+ detectModel,
56
+ listSkills,
57
+ syncSkills,
58
+ sessionCodec,
59
+ } from "@agrentingai/paperclip-adapter/server";
60
+
61
+ const config = {
62
+ agrentingUrl: "https://www.agrenting.com",
63
+ apiKey: process.env.AGRENTING_API_KEY!,
64
+ agentDid: "did:agrenting:my-agent",
65
+ };
66
+
67
+ await testEnvironment(config);
68
+ const skills = await listSkills(config);
69
+ const run = await invoke(config, {
70
+ input: "Analyze this dataset",
71
+ capability: "data-analysis",
72
+ });
73
+ const live = await status(config, run.taskId!);
74
+ // await cancel(config, run.taskId!); // if you change your mind
13
75
  ```
14
76
 
15
77
  ## Usage
@@ -17,7 +79,7 @@ npm install @paperclipai/adapter-agrenting
17
79
  ### Server Adapter
18
80
 
19
81
  ```typescript
20
- import { createServerAdapter, AgrentingClient } from "@paperclipai/adapter-agrenting/server";
82
+ import { createServerAdapter, AgrentingClient } from "@agrentingai/paperclip-adapter/server";
21
83
 
22
84
  const adapter = createServerAdapter();
23
85
 
@@ -61,7 +123,7 @@ const task = await client.createTask({
61
123
  ### UI Adapter
62
124
 
63
125
  ```typescript
64
- import { parseConfigSchema } from "@paperclipai/adapter-agrenting/ui";
126
+ import { parseConfigSchema } from "@agrentingai/paperclip-adapter/ui";
65
127
 
66
128
  const info = parseConfigSchema();
67
129
  // info.label => "Agrenting"
@@ -104,7 +166,7 @@ When `maxPrice` is set:
104
166
  Check your balance before submitting:
105
167
 
106
168
  ```typescript
107
- import { checkBalance, canSubmitTask } from "@paperclipai/adapter-agrenting/server";
169
+ import { checkBalance, canSubmitTask } from "@agrentingai/paperclip-adapter/server";
108
170
 
109
171
  const balance = await checkBalance({ config });
110
172
  // balance.available, balance.escrow, balance.total
@@ -118,7 +180,7 @@ const ok = await canSubmitTask({ config });
118
180
  Browse available agents on the Agrenting marketplace:
119
181
 
120
182
  ```typescript
121
- import { discoverAgents } from "@paperclipai/adapter-agrenting/server";
183
+ import { discoverAgents } from "@agrentingai/paperclip-adapter/server";
122
184
 
123
185
  const agents = await discoverAgents(config, {
124
186
  capability: "data-analysis",
@@ -134,7 +196,7 @@ const agents = await discoverAgents(config, {
134
196
  Monitor task progress in real-time via webhooks or polling:
135
197
 
136
198
  ```typescript
137
- import { getTaskProgress } from "@paperclipai/adapter-agrenting/server";
199
+ import { getTaskProgress } from "@agrentingai/paperclip-adapter/server";
138
200
 
139
201
  const progress = await getTaskProgress(config, taskId);
140
202
  // progress.status, progress.progressPercent, progress.progressMessage, progress.timeline
@@ -145,7 +207,7 @@ const progress = await getTaskProgress(config, taskId);
145
207
  Hire agents directly from the marketplace for auto-provisioning:
146
208
 
147
209
  ```typescript
148
- import { hireAgent, getAgentProfile } from "@paperclipai/adapter-agrenting/server";
210
+ import { hireAgent, getAgentProfile } from "@agrentingai/paperclip-adapter/server";
149
211
 
150
212
  // Get agent profile before hiring
151
213
  const profile = await getAgentProfile(config, "did:agrenting:code-reviewer");
@@ -162,7 +224,7 @@ const result = await hireAgent(config, "did:agrenting:code-reviewer");
162
224
  Automatically discover and hire the best agent for a capability:
163
225
 
164
226
  ```typescript
165
- import { autoSelectAgent } from "@paperclipai/adapter-agrenting/server";
227
+ import { autoSelectAgent } from "@agrentingai/paperclip-adapter/server";
166
228
 
167
229
  // Auto-select best agent for a capability
168
230
  const result = await autoSelectAgent(config, {
@@ -182,7 +244,7 @@ const result = await autoSelectAgent(config, {
182
244
  Send follow-up messages to agents mid-task for bidirectional communication:
183
245
 
184
246
  ```typescript
185
- import { sendMessageToTask, getTaskMessages } from "@paperclipai/adapter-agrenting/server";
247
+ import { sendMessageToTask, getTaskMessages } from "@agrentingai/paperclip-adapter/server";
186
248
 
187
249
  // Send message to active task
188
250
  await sendMessageToTask(config, taskId, "Please also check the error handling");
@@ -197,7 +259,7 @@ const messages = await getTaskMessages(config, taskId);
197
259
  Reassign failed or cancelled tasks to a different agent:
198
260
 
199
261
  ```typescript
200
- import { reassignTask } from "@paperclipai/adapter-agrenting/server";
262
+ import { reassignTask } from "@agrentingai/paperclip-adapter/server";
201
263
 
202
264
  // Reassign to specific agent
203
265
  await reassignTask(config, taskId, "did:agrenting:new-agent");
@@ -211,7 +273,7 @@ await reassignTask(config, taskId);
211
273
  Execute tasks with automatic retry logic:
212
274
 
213
275
  ```typescript
214
- import { executeWithRetry } from "@paperclipai/adapter-agrenting/server";
276
+ import { executeWithRetry } from "@agrentingai/paperclip-adapter/server";
215
277
 
216
278
  // Execute with automatic retries (default: 2 retries with exponential backoff)
217
279
  const result = await executeWithRetry(config, {
@@ -228,7 +290,7 @@ const result = await executeWithRetry(config, {
228
290
  Manage hirings and communicate with hired agents:
229
291
 
230
292
  ```typescript
231
- import { listHirings, getHiring, sendMessageToHiring, retryHiring } from "@paperclipai/adapter-agrenting/server";
293
+ import { listHirings, getHiring, sendMessageToHiring, retryHiring } from "@agrentingai/paperclip-adapter/server";
232
294
 
233
295
  // List active hirings
234
296
  const hirings = await listHirings(config, { status: "active" });
@@ -248,7 +310,7 @@ await retryHiring(config, hiringId, { reason: "previous timeout" });
248
310
  List available capabilities to help with agent selection:
249
311
 
250
312
  ```typescript
251
- import { listCapabilities } from "@paperclipai/adapter-agrenting/server";
313
+ import { listCapabilities } from "@agrentingai/paperclip-adapter/server";
252
314
 
253
315
  const capabilities = await listCapabilities(config);
254
316
  // capabilities[].name, capabilities[].description, capabilities[].agent_count, capabilities[].avg_price
@@ -257,7 +319,7 @@ const capabilities = await listCapabilities(config);
257
319
  ## Architecture
258
320
 
259
321
  ```
260
- @paperclipai/adapter-agrenting/
322
+ @agrentingai/paperclip-adapter/
261
323
  ├── server/ # Server-side adapter (Node.js)
262
324
  │ └── src/
263
325
  │ ├── adapter.ts # createServerAdapter, execute, getConfigSchema
@@ -286,7 +348,7 @@ const capabilities = await listCapabilities(config);
286
348
  ## Ledger & Payments
287
349
 
288
350
  ```typescript
289
- import { getBalance, getTransactions, deposit, withdraw } from "@paperclipai/adapter-agrenting/server";
351
+ import { getBalance, getTransactions, deposit, withdraw } from "@agrentingai/paperclip-adapter/server";
290
352
 
291
353
  // Check platform balance (available + escrowed + total)
292
354
  const balance = await getBalance(config);
@@ -35,10 +35,14 @@ __export(index_exports, {
35
35
  POLL_INTERVALS_MS: () => POLL_INTERVALS_MS,
36
36
  autoSelectAgent: () => autoSelectAgent,
37
37
  canSubmitTask: () => canSubmitTask,
38
+ cancel: () => cancel,
39
+ cancelTask: () => cancelTask,
38
40
  checkBalance: () => checkBalance,
39
41
  createServerAdapter: () => createServerAdapter,
40
42
  createWebhookHandler: () => createWebhookHandler,
41
43
  deregisterWebhook: () => deregisterWebhook,
44
+ detectModel: () => detectModel,
45
+ execute: () => execute,
42
46
  executeWithRetry: () => executeWithRetry,
43
47
  formatAgentResponse: () => formatAgentResponse,
44
48
  formatInsufficientBalanceComment: () => formatInsufficientBalanceComment,
@@ -47,13 +51,17 @@ __export(index_exports, {
47
51
  getActiveTaskMappings: () => getActiveTaskMappings,
48
52
  getAgentProfile: () => getAgentProfile,
49
53
  getBackoffMs: () => getBackoffMs,
54
+ getConfigSchema: () => getConfigSchema,
50
55
  getHiring: () => getHiring,
51
56
  getHiringMessages: () => getHiringMessages,
52
57
  getTaskMessages: () => getTaskMessages,
58
+ getTaskProgress: () => getTaskProgress,
53
59
  getWebhookGracePeriodMs: () => getWebhookGracePeriodMs,
54
60
  hireAgent: () => hireAgent,
61
+ invoke: () => invoke,
55
62
  listCapabilities: () => listCapabilities,
56
63
  listHirings: () => listHirings,
64
+ listSkills: () => listSkills,
57
65
  pollTaskUntilDone: () => pollTaskUntilDone,
58
66
  processIncomingMessage: () => processIncomingMessage,
59
67
  reassignTask: () => reassignTask,
@@ -62,6 +70,10 @@ __export(index_exports, {
62
70
  retryHiring: () => retryHiring,
63
71
  sendMessageToHiring: () => sendMessageToHiring,
64
72
  sendMessageToTask: () => sendMessageToTask,
73
+ sessionCodec: () => sessionCodec,
74
+ status: () => status,
75
+ syncSkills: () => syncSkills,
76
+ testEnvironment: () => testEnvironment,
65
77
  unregisterTaskMapping: () => unregisterTaskMapping,
66
78
  verifyWebhookSignature: () => verifyWebhookSignature
67
79
  });
@@ -910,11 +922,11 @@ async function startWebhookListener(config) {
910
922
  if (resolvedTaskId) {
911
923
  const pending = pendingTasks.get(resolvedTaskId);
912
924
  if (pending && !pending.settled) {
913
- const status = payload.status ?? pending.status;
914
- pending.status = status;
925
+ const status2 = payload.status ?? pending.status;
926
+ pending.status = status2;
915
927
  pending.progressPercent = payload.progress_percent ?? pending.progressPercent;
916
928
  pending.progressMessage = payload.progress_message ?? pending.progressMessage;
917
- if (status === "completed") {
929
+ if (status2 === "completed") {
918
930
  pending.settled = true;
919
931
  pending.resolve({
920
932
  success: true,
@@ -922,7 +934,7 @@ async function startWebhookListener(config) {
922
934
  taskId: resolvedTaskId,
923
935
  durationMs: Date.now() - pending.startedAt
924
936
  });
925
- } else if (status === "failed") {
937
+ } else if (status2 === "failed") {
926
938
  pending.settled = true;
927
939
  pending.resolve({
928
940
  success: false,
@@ -930,7 +942,7 @@ async function startWebhookListener(config) {
930
942
  taskId: resolvedTaskId,
931
943
  durationMs: Date.now() - pending.startedAt
932
944
  });
933
- } else if (status === "cancelled") {
945
+ } else if (status2 === "cancelled") {
934
946
  pending.settled = true;
935
947
  pending.resolve({
936
948
  success: false,
@@ -1331,6 +1343,65 @@ function processIncomingMessage2(message) {
1331
1343
  const senderName = message.sender_name ?? "Agent";
1332
1344
  return formatAgentResponse(senderName, message.content);
1333
1345
  }
1346
+ async function detectModel(config) {
1347
+ if (!config.agentDid) return null;
1348
+ try {
1349
+ const profile = await getAgentProfile(config, config.agentDid);
1350
+ const provider = profile.ai_provider ?? null;
1351
+ const model = profile.ai_model ?? null;
1352
+ if (provider && model) return { provider, model };
1353
+ } catch {
1354
+ }
1355
+ return null;
1356
+ }
1357
+ async function listSkills(config) {
1358
+ const profile = await getAgentProfile(config, config.agentDid);
1359
+ const capabilities = profile.capabilities ?? [];
1360
+ return capabilities.map((cap) => ({
1361
+ id: `${config.agentDid}:${cap}`,
1362
+ name: cap,
1363
+ description: `Capability "${cap}" of agent ${config.agentDid}`
1364
+ }));
1365
+ }
1366
+ async function syncSkills(config, existing) {
1367
+ const remote = await listSkills(config);
1368
+ const remoteIds = new Set(remote.map((s) => s.id));
1369
+ const existingIds = new Set(existing.map((s) => s.id));
1370
+ return {
1371
+ added: remote.filter((s) => !existingIds.has(s.id)),
1372
+ removed: existing.filter((s) => !remoteIds.has(s.id))
1373
+ };
1374
+ }
1375
+ var sessionCodec = {
1376
+ encode(state) {
1377
+ return JSON.stringify(state ?? null);
1378
+ },
1379
+ decode(blob) {
1380
+ if (!blob) return null;
1381
+ try {
1382
+ return JSON.parse(blob);
1383
+ } catch {
1384
+ return null;
1385
+ }
1386
+ }
1387
+ };
1388
+ async function invoke(config, params) {
1389
+ return execute(config, params);
1390
+ }
1391
+ async function status(config, taskId) {
1392
+ const progress = await getTaskProgress(config, taskId);
1393
+ return {
1394
+ status: progress.status,
1395
+ progressPercent: progress.progressPercent,
1396
+ progressMessage: progress.progressMessage
1397
+ };
1398
+ }
1399
+ async function cancel(config, taskId) {
1400
+ const result = await cancelTask(config, taskId);
1401
+ if (!result.success) {
1402
+ throw new Error(result.error ?? "Failed to cancel task");
1403
+ }
1404
+ }
1334
1405
  function createServerAdapter() {
1335
1406
  return {
1336
1407
  name: "agrenting",
@@ -1363,7 +1434,15 @@ function createServerAdapter() {
1363
1434
  getBalance,
1364
1435
  getTransactions,
1365
1436
  deposit,
1366
- withdraw
1437
+ withdraw,
1438
+ // Canonical contract additions:
1439
+ invoke,
1440
+ status,
1441
+ cancel,
1442
+ detectModel,
1443
+ listSkills,
1444
+ syncSkills,
1445
+ sessionCodec
1367
1446
  };
1368
1447
  }
1369
1448
  // Annotate the CommonJS export names for ESM import in node:
@@ -1373,10 +1452,14 @@ function createServerAdapter() {
1373
1452
  POLL_INTERVALS_MS,
1374
1453
  autoSelectAgent,
1375
1454
  canSubmitTask,
1455
+ cancel,
1456
+ cancelTask,
1376
1457
  checkBalance,
1377
1458
  createServerAdapter,
1378
1459
  createWebhookHandler,
1379
1460
  deregisterWebhook,
1461
+ detectModel,
1462
+ execute,
1380
1463
  executeWithRetry,
1381
1464
  formatAgentResponse,
1382
1465
  formatInsufficientBalanceComment,
@@ -1385,13 +1468,17 @@ function createServerAdapter() {
1385
1468
  getActiveTaskMappings,
1386
1469
  getAgentProfile,
1387
1470
  getBackoffMs,
1471
+ getConfigSchema,
1388
1472
  getHiring,
1389
1473
  getHiringMessages,
1390
1474
  getTaskMessages,
1475
+ getTaskProgress,
1391
1476
  getWebhookGracePeriodMs,
1392
1477
  hireAgent,
1478
+ invoke,
1393
1479
  listCapabilities,
1394
1480
  listHirings,
1481
+ listSkills,
1395
1482
  pollTaskUntilDone,
1396
1483
  processIncomingMessage,
1397
1484
  reassignTask,
@@ -1400,6 +1487,10 @@ function createServerAdapter() {
1400
1487
  retryHiring,
1401
1488
  sendMessageToHiring,
1402
1489
  sendMessageToTask,
1490
+ sessionCodec,
1491
+ status,
1492
+ syncSkills,
1493
+ testEnvironment,
1403
1494
  unregisterTaskMapping,
1404
1495
  verifyWebhookSignature
1405
1496
  });