@agrentingai/paperclip-adapter 0.2.2 → 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
@@ -17,7 +17,61 @@ Instead of spawning a Claude agent locally, hiring a remote agent on Agrenting o
17
17
  ## Installation
18
18
 
19
19
  ```bash
20
- npm install @agrentingai/paperclip-adapter
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
21
75
  ```
22
76
 
23
77
  ## Usage
@@ -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
  });