@acnlabs/paperclip-plugin-acn 0.1.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/LICENSE +21 -0
- package/README.md +161 -0
- package/dist/constants.d.ts +17 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +17 -0
- package/dist/constants.js.map +1 -0
- package/dist/lib/echo-guard.d.ts +28 -0
- package/dist/lib/echo-guard.d.ts.map +1 -0
- package/dist/lib/echo-guard.js +40 -0
- package/dist/lib/echo-guard.js.map +1 -0
- package/dist/lib/secrets.d.ts +28 -0
- package/dist/lib/secrets.d.ts.map +1 -0
- package/dist/lib/secrets.js +33 -0
- package/dist/lib/secrets.js.map +1 -0
- package/dist/lib/signature.d.ts +26 -0
- package/dist/lib/signature.d.ts.map +1 -0
- package/dist/lib/signature.js +45 -0
- package/dist/lib/signature.js.map +1 -0
- package/dist/manifest.d.ts +4 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +97 -0
- package/dist/manifest.js.map +1 -0
- package/dist/ui/index.d.ts +19 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +287 -0
- package/dist/ui/index.js.map +7 -0
- package/dist/worker.d.ts +27 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +491 -0
- package/dist/worker.js.map +1 -0
- package/package.json +61 -0
package/dist/worker.js
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACN Plugin Worker
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities:
|
|
5
|
+
* P0-1 Startup : register webhook URL as ACN subnet harness
|
|
6
|
+
* P0-2 Startup : full sync — pull open ACN tasks → Paperclip issues
|
|
7
|
+
* P0-3 ACN→PC : task.* webhook events → sync Paperclip issue status / comments
|
|
8
|
+
* P0-4 PC→ACN : Paperclip issue done/cancelled → ACN review (approve / reject)
|
|
9
|
+
* P0-5 PC→ACN : Paperclip issue created (not from ACN) → ACN task
|
|
10
|
+
*/
|
|
11
|
+
import { definePlugin, runWorker } from "@paperclipai/plugin-sdk";
|
|
12
|
+
import { ACNClient } from "acn-client";
|
|
13
|
+
import { PLUGIN_ID, STATE_KEYS, WEBHOOK_KEYS } from "./constants.js";
|
|
14
|
+
import { verifyAcnSignature } from "./lib/signature.js";
|
|
15
|
+
import { shouldSkipPluginEcho } from "./lib/echo-guard.js";
|
|
16
|
+
import { resolveSecretOrLiteral } from "./lib/secrets.js";
|
|
17
|
+
// ── Module-level worker state (populated once in setup) ───────────────────────
|
|
18
|
+
// onWebhook() is a sibling lifecycle hook without its own ctx, so the handler
|
|
19
|
+
// is stashed here after setup() resolves.
|
|
20
|
+
let _ctx = null;
|
|
21
|
+
let _cfg = null;
|
|
22
|
+
let _client = null;
|
|
23
|
+
/** Resolved HMAC secret for verifying X-ACN-Signature on inbound webhooks. */
|
|
24
|
+
let _harnessSecret = null;
|
|
25
|
+
/**
|
|
26
|
+
* ACN agent_id of the API key the plugin is configured with. Used to detect
|
|
27
|
+
* — and skip — webhook events fired for tasks the plugin itself just
|
|
28
|
+
* created (PC issue → plugin createTask → ACN fires task.created → plugin
|
|
29
|
+
* would otherwise mirror it back into a ghost duplicate issue).
|
|
30
|
+
*/
|
|
31
|
+
let _selfAgentId = null;
|
|
32
|
+
async function loadMap(ctx, key, companyId) {
|
|
33
|
+
// Paperclip's plugin_state.value_json is a jsonb column, so the host can
|
|
34
|
+
// return either a parsed object or a JSON string depending on how the
|
|
35
|
+
// value was originally written. Accept both shapes — naively assuming
|
|
36
|
+
// string and JSON.parse-ing on an object yielded an empty map and silently
|
|
37
|
+
// broke task-id ↔ issue-id round trips for every event handler.
|
|
38
|
+
const raw = await ctx.state.get({ scopeKind: "company", scopeId: companyId, stateKey: key });
|
|
39
|
+
if (!raw)
|
|
40
|
+
return {};
|
|
41
|
+
try {
|
|
42
|
+
return typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return {};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function saveMap(ctx, key, companyId, map) {
|
|
49
|
+
await ctx.state.set({ scopeKind: "company", scopeId: companyId, stateKey: key }, JSON.stringify(map));
|
|
50
|
+
}
|
|
51
|
+
/** Reverse-lookup: find the key whose value equals `val` */
|
|
52
|
+
function reverseLookup(map, val) {
|
|
53
|
+
return Object.entries(map).find(([, v]) => v === val)?.[0];
|
|
54
|
+
}
|
|
55
|
+
// ── ACN client factory ────────────────────────────────────────────────────────
|
|
56
|
+
function buildClient(cfg, apiKey) {
|
|
57
|
+
return new ACNClient({
|
|
58
|
+
baseUrl: cfg.acnBaseUrl ?? "https://acn.agentplanet.io",
|
|
59
|
+
apiKey,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Construct the Paperclip webhook URL for ACN harness registration. */
|
|
63
|
+
function harnessWebhookUrl(cfg) {
|
|
64
|
+
if (!cfg.paperclipBaseUrl)
|
|
65
|
+
return null;
|
|
66
|
+
const base = cfg.paperclipBaseUrl.replace(/\/$/, "");
|
|
67
|
+
return `${base}/api/plugins/${PLUGIN_ID}/webhooks/${WEBHOOK_KEYS.acnEvents}`;
|
|
68
|
+
}
|
|
69
|
+
// ── Issue body helpers ────────────────────────────────────────────────────────
|
|
70
|
+
function taskIssueDescription(task) {
|
|
71
|
+
const lines = [task.description ?? ""];
|
|
72
|
+
lines.push("", `**ACN Task ID:** \`${task.task_id}\``);
|
|
73
|
+
const rewardVal = parseFloat(task.reward ?? "0");
|
|
74
|
+
if (rewardVal > 0) {
|
|
75
|
+
lines.push(`**Reward:** ${task.reward} ${task.reward_currency ?? ""}`);
|
|
76
|
+
}
|
|
77
|
+
return lines.join("\n");
|
|
78
|
+
}
|
|
79
|
+
// ── Full sync helpers ─────────────────────────────────────────────────────────
|
|
80
|
+
async function syncTasks(ctx, client, cfg, companyId, taskIssueMap) {
|
|
81
|
+
// ACN task statuses (mirrors backend `TaskStatus` enum): open | in_progress
|
|
82
|
+
// | submitted | completed | rejected | cancelled. We sync everything that
|
|
83
|
+
// is not yet terminal.
|
|
84
|
+
const [openRes, inProgressRes, submittedRes] = await Promise.all([
|
|
85
|
+
client.listTasks({ status: "open", limit: 100 }),
|
|
86
|
+
client.listTasks({ status: "in_progress", limit: 100 }),
|
|
87
|
+
client.listTasks({ status: "submitted", limit: 100 }),
|
|
88
|
+
]);
|
|
89
|
+
const allTasks = [...openRes.tasks, ...inProgressRes.tasks, ...submittedRes.tasks];
|
|
90
|
+
const updated = { ...taskIssueMap };
|
|
91
|
+
for (const task of allTasks) {
|
|
92
|
+
if (task.subnet_id !== cfg.acnSubnetId)
|
|
93
|
+
continue;
|
|
94
|
+
if (updated[task.task_id])
|
|
95
|
+
continue;
|
|
96
|
+
try {
|
|
97
|
+
const issue = await ctx.issues.create({
|
|
98
|
+
companyId,
|
|
99
|
+
title: `[ACN] ${task.title}`,
|
|
100
|
+
description: taskIssueDescription(task),
|
|
101
|
+
status: "todo",
|
|
102
|
+
originKind: `plugin:${PLUGIN_ID}:task`,
|
|
103
|
+
originId: task.task_id,
|
|
104
|
+
});
|
|
105
|
+
updated[task.task_id] = issue.id;
|
|
106
|
+
ctx.logger.info("acn-plugin: synced task → issue", {
|
|
107
|
+
task_id: task.task_id,
|
|
108
|
+
issue_id: issue.id,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
ctx.logger.warn("acn-plugin: failed to create issue for task", {
|
|
113
|
+
task_id: task.task_id,
|
|
114
|
+
error: String(err),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return updated;
|
|
119
|
+
}
|
|
120
|
+
// ── ACN webhook event handler ─────────────────────────────────────────────────
|
|
121
|
+
async function handleAcnWebhook(ctx, cfg, client, rawBody) {
|
|
122
|
+
let payload;
|
|
123
|
+
try {
|
|
124
|
+
payload = JSON.parse(rawBody);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
ctx.logger.warn("acn-plugin: received unparseable webhook body");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!payload.event)
|
|
131
|
+
return;
|
|
132
|
+
ctx.logger.info("acn-plugin: received ACN event", { event: payload.event });
|
|
133
|
+
const companies = await ctx.companies.list();
|
|
134
|
+
const companyId = companies[0]?.id;
|
|
135
|
+
if (!companyId)
|
|
136
|
+
return;
|
|
137
|
+
const taskIssueMap = await loadMap(ctx, STATE_KEYS.issueTaskMap, companyId);
|
|
138
|
+
const { task_id, data } = payload;
|
|
139
|
+
switch (payload.event) {
|
|
140
|
+
case "task.created": {
|
|
141
|
+
if (!cfg.autoCreateIssues)
|
|
142
|
+
break;
|
|
143
|
+
if (taskIssueMap[task_id])
|
|
144
|
+
break;
|
|
145
|
+
// Echo guard: skip tasks the bridge agent itself created. The plugin's
|
|
146
|
+
// `handleIssueCreated` path also calls ACN createTask synchronously,
|
|
147
|
+
// which fires this very `task.created` webhook *before* `saveMap` has
|
|
148
|
+
// had a chance to persist the mapping. The map check above will miss
|
|
149
|
+
// and we'd ghost-mirror our own outbound task back into a second
|
|
150
|
+
// Paperclip issue. Comparing against `_selfAgentId` closes that race.
|
|
151
|
+
if (_selfAgentId && data.creator_id === _selfAgentId) {
|
|
152
|
+
ctx.logger.info("acn-plugin: skipping task.created (self-created, echo guard)", {
|
|
153
|
+
task_id,
|
|
154
|
+
});
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
const task = await client.getTask(task_id).catch(() => null);
|
|
158
|
+
if (!task)
|
|
159
|
+
break;
|
|
160
|
+
const issue = await ctx.issues.create({
|
|
161
|
+
companyId,
|
|
162
|
+
title: `[ACN] ${task.title ?? task_id}`,
|
|
163
|
+
description: taskIssueDescription(task),
|
|
164
|
+
status: "todo",
|
|
165
|
+
originKind: `plugin:${PLUGIN_ID}:task`,
|
|
166
|
+
originId: task_id,
|
|
167
|
+
});
|
|
168
|
+
taskIssueMap[task_id] = issue.id;
|
|
169
|
+
await saveMap(ctx, STATE_KEYS.issueTaskMap, companyId, taskIssueMap);
|
|
170
|
+
ctx.logger.info("acn-plugin: task.created → issue created", {
|
|
171
|
+
task_id,
|
|
172
|
+
issue_id: issue.id,
|
|
173
|
+
});
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case "task.accepted": {
|
|
177
|
+
const issueId = taskIssueMap[task_id];
|
|
178
|
+
if (!issueId)
|
|
179
|
+
break;
|
|
180
|
+
// Paperclip's `in_progress` status requires either an `assigneeUserId`
|
|
181
|
+
// or `assigneeAgentId` — neither of which exists in ACN's identity
|
|
182
|
+
// space. Pushing the ACN agent_id directly would fail Paperclip's
|
|
183
|
+
// `assertAssignableAgent` check. We therefore record the acceptance as
|
|
184
|
+
// a comment and leave the issue status as-is; users see the activity
|
|
185
|
+
// and the Paperclip status moves on `task.submitted` (in_review) and
|
|
186
|
+
// `task.completed` (done), which carry no assignee requirement.
|
|
187
|
+
await ctx.issues.createComment(issueId, `Agent \`${data.assignee_id ?? "unknown"}\` accepted this task on ACN.`, companyId);
|
|
188
|
+
ctx.logger.info("acn-plugin: task.accepted → comment posted", {
|
|
189
|
+
task_id,
|
|
190
|
+
issue_id: issueId,
|
|
191
|
+
assignee_id: data.assignee_id,
|
|
192
|
+
});
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "task.submitted": {
|
|
196
|
+
const issueId = taskIssueMap[task_id];
|
|
197
|
+
if (!issueId)
|
|
198
|
+
break;
|
|
199
|
+
await ctx.issues.update(issueId, { status: "in_review" }, companyId);
|
|
200
|
+
await ctx.issues.createComment(issueId, [
|
|
201
|
+
`**Submission received** — open the **ACN tab** on this issue to review and approve or reject.`,
|
|
202
|
+
].join("\n"), companyId);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case "task.completed": {
|
|
206
|
+
const issueId = taskIssueMap[task_id];
|
|
207
|
+
if (!issueId)
|
|
208
|
+
break;
|
|
209
|
+
await ctx.issues.update(issueId, { status: "done" }, companyId);
|
|
210
|
+
await ctx.issues.createComment(issueId, "Task completed and payment settled via ACN.", companyId);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "task.rejected": {
|
|
214
|
+
const issueId = taskIssueMap[task_id];
|
|
215
|
+
if (!issueId)
|
|
216
|
+
break;
|
|
217
|
+
await ctx.issues.update(issueId, { status: "cancelled" }, companyId);
|
|
218
|
+
await ctx.issues.createComment(issueId, "ACN task was rejected by the creator.", companyId);
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
case "task.cancelled": {
|
|
222
|
+
const issueId = taskIssueMap[task_id];
|
|
223
|
+
if (!issueId)
|
|
224
|
+
break;
|
|
225
|
+
await ctx.issues.update(issueId, { status: "cancelled" }, companyId);
|
|
226
|
+
await ctx.issues.createComment(issueId, "ACN task was cancelled.", companyId);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
case "participation.rejected": {
|
|
230
|
+
const issueId = taskIssueMap[task_id];
|
|
231
|
+
if (!issueId)
|
|
232
|
+
break;
|
|
233
|
+
const parts = [
|
|
234
|
+
`Submission rejected (attempt ${data.resubmit_count ?? "?"}/${data.max_resubmit_attempts ?? "?"}) — agent will resubmit.`,
|
|
235
|
+
];
|
|
236
|
+
if (data.rejection_reason)
|
|
237
|
+
parts.push(`\n**Reason:** ${data.rejection_reason}`);
|
|
238
|
+
await ctx.issues.createComment(issueId, parts.join(""), companyId);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
default:
|
|
242
|
+
ctx.logger.debug("acn-plugin: unhandled task event", { event: payload.event });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// ── Paperclip issue event handlers ────────────────────────────────────────────
|
|
246
|
+
export async function handleIssueUpdated(ctx, cfg, client, event) {
|
|
247
|
+
if (shouldSkipPluginEcho(event, PLUGIN_ID))
|
|
248
|
+
return;
|
|
249
|
+
// See handleIssueCreated: Paperclip carries the issue id on the event
|
|
250
|
+
// envelope, while `payload` holds the change summary (status, previousStatus,
|
|
251
|
+
// identifier, ...). There is no nested `changes` object — fields are flat.
|
|
252
|
+
if (event.entityType !== "issue" || !event.entityId)
|
|
253
|
+
return;
|
|
254
|
+
const issueId = event.entityId;
|
|
255
|
+
const payload = (event.payload ?? {});
|
|
256
|
+
const status = payload.status;
|
|
257
|
+
if (!status)
|
|
258
|
+
return;
|
|
259
|
+
const companyId = event.companyId;
|
|
260
|
+
const taskIssueMap = await loadMap(ctx, STATE_KEYS.issueTaskMap, companyId);
|
|
261
|
+
const taskId = reverseLookup(taskIssueMap, issueId);
|
|
262
|
+
if (!taskId)
|
|
263
|
+
return;
|
|
264
|
+
if (status !== "done" && status !== "cancelled")
|
|
265
|
+
return;
|
|
266
|
+
// Only call /review when ACN considers the task to be awaiting review
|
|
267
|
+
// (`submitted`). For other statuses (open / in_progress / completed /...)
|
|
268
|
+
// the review endpoint will 400.
|
|
269
|
+
const acnTask = await client.getTask(taskId).catch(() => null);
|
|
270
|
+
if (!acnTask || acnTask.status !== "submitted")
|
|
271
|
+
return;
|
|
272
|
+
if (status === "done" && cfg.autoApproveOnDone) {
|
|
273
|
+
try {
|
|
274
|
+
await client.reviewTask(taskId, true, "Approved via Paperclip");
|
|
275
|
+
ctx.logger.info("acn-plugin: auto-approved task", { task_id: taskId });
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
ctx.logger.error("acn-plugin: review(approve) failed", { task_id: taskId, error: String(err) });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (status === "cancelled") {
|
|
282
|
+
try {
|
|
283
|
+
await client.reviewTask(taskId, false, "Rejected via Paperclip");
|
|
284
|
+
ctx.logger.info("acn-plugin: rejected task", { task_id: taskId });
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
ctx.logger.error("acn-plugin: review(reject) failed", { task_id: taskId, error: String(err) });
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
export async function handleIssueCreated(ctx, cfg, client, event) {
|
|
292
|
+
if (shouldSkipPluginEcho(event, PLUGIN_ID))
|
|
293
|
+
return;
|
|
294
|
+
// Paperclip carries entity identity at the event envelope level
|
|
295
|
+
// (`event.entityId` / `event.entityType`); the `payload` only contains
|
|
296
|
+
// change summary fields (title, identifier, status, …) and intentionally
|
|
297
|
+
// omits the description and other long-form content. So we read the id
|
|
298
|
+
// off the envelope and pull the full issue body via `ctx.issues.get`.
|
|
299
|
+
if (event.entityType !== "issue" || !event.entityId)
|
|
300
|
+
return;
|
|
301
|
+
const issueId = event.entityId;
|
|
302
|
+
const companyId = event.companyId;
|
|
303
|
+
const taskIssueMap = await loadMap(ctx, STATE_KEYS.issueTaskMap, companyId);
|
|
304
|
+
if (reverseLookup(taskIssueMap, issueId))
|
|
305
|
+
return;
|
|
306
|
+
const payload = (event.payload ?? {});
|
|
307
|
+
let description = "";
|
|
308
|
+
try {
|
|
309
|
+
const full = (await ctx.issues.get(issueId, companyId));
|
|
310
|
+
description = full?.description?.trim() ?? "";
|
|
311
|
+
}
|
|
312
|
+
catch (err) {
|
|
313
|
+
ctx.logger.warn("acn-plugin: failed to fetch issue body, falling back to title", {
|
|
314
|
+
issue_id: issueId,
|
|
315
|
+
error: String(err),
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
const task = await client.createTask({
|
|
320
|
+
title: payload.title ?? issueId,
|
|
321
|
+
description: description || "Task created from Paperclip issue.",
|
|
322
|
+
reward: "0",
|
|
323
|
+
deadline_hours: 168,
|
|
324
|
+
subnet_id: cfg.acnSubnetId ?? null,
|
|
325
|
+
reward_currency: "credits",
|
|
326
|
+
});
|
|
327
|
+
// Persist the mapping IMMEDIATELY: ACN's `task.created` webhook (which
|
|
328
|
+
// mirrors ACN-side tasks back into Paperclip) fires synchronously from
|
|
329
|
+
// `createTask`, so the webhook handler will race this code path. If we
|
|
330
|
+
// don't have the map in place before the webhook arrives, the handler
|
|
331
|
+
// sees an unknown task_id and creates a ghost duplicate issue.
|
|
332
|
+
const fresh = await loadMap(ctx, STATE_KEYS.issueTaskMap, companyId);
|
|
333
|
+
fresh[task.task_id] = issueId;
|
|
334
|
+
await saveMap(ctx, STATE_KEYS.issueTaskMap, companyId, fresh);
|
|
335
|
+
ctx.logger.info("acn-plugin: issue.created → ACN task created", {
|
|
336
|
+
issue_id: issueId,
|
|
337
|
+
task_id: task.task_id,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
ctx.logger.error("acn-plugin: failed to create ACN task for issue", {
|
|
342
|
+
issue_id: issueId,
|
|
343
|
+
error: String(err),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// ── Plugin definition ─────────────────────────────────────────────────────────
|
|
348
|
+
const plugin = definePlugin({
|
|
349
|
+
async setup(ctx) {
|
|
350
|
+
const cfg = (await ctx.config.get());
|
|
351
|
+
if (!cfg.acnApiKeyRef || !cfg.acnSubnetId) {
|
|
352
|
+
ctx.logger.warn("acn-plugin: acnApiKeyRef or acnSubnetId not configured — skipping setup");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const apiKey = await resolveSecretOrLiteral(cfg.acnApiKeyRef, ctx.secrets);
|
|
356
|
+
const client = buildClient(cfg, apiKey);
|
|
357
|
+
// Resolve the HMAC secret used for X-ACN-Signature verification.
|
|
358
|
+
let harnessSecret = null;
|
|
359
|
+
if (cfg.acnHarnessSecretRef) {
|
|
360
|
+
try {
|
|
361
|
+
harnessSecret = await resolveSecretOrLiteral(cfg.acnHarnessSecretRef, ctx.secrets);
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
ctx.logger.error("acn-plugin: failed to resolve harness secret ref", {
|
|
365
|
+
ref: cfg.acnHarnessSecretRef,
|
|
366
|
+
error: String(err),
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
ctx.logger.warn("acn-plugin: acnHarnessSecretRef not configured — inbound webhook signatures will NOT be verified (insecure)");
|
|
372
|
+
}
|
|
373
|
+
// Stash for onWebhook()
|
|
374
|
+
_ctx = ctx;
|
|
375
|
+
_cfg = cfg;
|
|
376
|
+
_client = client;
|
|
377
|
+
_harnessSecret = harnessSecret;
|
|
378
|
+
// Resolve the configured bridge agent's identity. This lets the ACN
|
|
379
|
+
// webhook handler distinguish events fired for tasks we created
|
|
380
|
+
// ourselves from events fired for tasks created by other ACN agents,
|
|
381
|
+
// so we don't mirror plugin-issued tasks back into ghost duplicate
|
|
382
|
+
// Paperclip issues. Failure is non-fatal: we simply lose the ghost-
|
|
383
|
+
// mirror guard and fall back to the slower map-based dedup.
|
|
384
|
+
try {
|
|
385
|
+
const me = await client.getMyAgent();
|
|
386
|
+
_selfAgentId = me.agent_id;
|
|
387
|
+
ctx.logger.info("acn-plugin: bridge agent identity resolved", {
|
|
388
|
+
agent_id: _selfAgentId,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
catch (err) {
|
|
392
|
+
ctx.logger.warn("acn-plugin: failed to resolve bridge agent identity (echo guard degraded)", {
|
|
393
|
+
error: String(err),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// ── P0-1 Register harness webhook ────────────────────────────────────────
|
|
397
|
+
const webhookUrl = harnessWebhookUrl(cfg);
|
|
398
|
+
if (webhookUrl) {
|
|
399
|
+
try {
|
|
400
|
+
await client.registerSubnetHarness(cfg.acnSubnetId, webhookUrl, harnessSecret);
|
|
401
|
+
ctx.logger.info("acn-plugin: registered harness", {
|
|
402
|
+
subnet_id: cfg.acnSubnetId,
|
|
403
|
+
webhook_url: webhookUrl,
|
|
404
|
+
signed: harnessSecret !== null,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
catch (err) {
|
|
408
|
+
ctx.logger.error("acn-plugin: harness registration failed", { error: String(err) });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
ctx.logger.warn("acn-plugin: paperclipBaseUrl not set — skipping harness registration");
|
|
413
|
+
}
|
|
414
|
+
// ── P0-2 Full initial task sync ──────────────────────────────────────────
|
|
415
|
+
const companies = await ctx.companies.list();
|
|
416
|
+
const companyId = companies[0]?.id;
|
|
417
|
+
if (companyId) {
|
|
418
|
+
let taskIssueMap = await loadMap(ctx, STATE_KEYS.issueTaskMap, companyId);
|
|
419
|
+
try {
|
|
420
|
+
taskIssueMap = await syncTasks(ctx, client, cfg, companyId, taskIssueMap);
|
|
421
|
+
await saveMap(ctx, STATE_KEYS.issueTaskMap, companyId, taskIssueMap);
|
|
422
|
+
}
|
|
423
|
+
catch (err) {
|
|
424
|
+
ctx.logger.error("acn-plugin: task full sync failed", { error: String(err) });
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// ── P0-4 Paperclip issue status → ACN review ────────────────────────────
|
|
428
|
+
ctx.events.on("issue.updated", async (event) => {
|
|
429
|
+
await handleIssueUpdated(ctx, cfg, client, event);
|
|
430
|
+
});
|
|
431
|
+
// ── P0-5 Paperclip issue created → ACN task ──────────────────────────────
|
|
432
|
+
ctx.events.on("issue.created", async (event) => {
|
|
433
|
+
await handleIssueCreated(ctx, cfg, client, event);
|
|
434
|
+
});
|
|
435
|
+
// ── Bridge: getData for ACN tab ────────────────────────────────────────────
|
|
436
|
+
ctx.data.register("acn-task-info", async (params) => {
|
|
437
|
+
const issueId = params.issueId;
|
|
438
|
+
const cid = params.companyId;
|
|
439
|
+
if (!issueId || !cid)
|
|
440
|
+
return null;
|
|
441
|
+
const map = await loadMap(ctx, STATE_KEYS.issueTaskMap, cid);
|
|
442
|
+
const taskId = reverseLookup(map, issueId);
|
|
443
|
+
if (!taskId)
|
|
444
|
+
return null;
|
|
445
|
+
const [task, participations] = await Promise.all([
|
|
446
|
+
client.getTask(taskId),
|
|
447
|
+
client.getTaskParticipations(taskId),
|
|
448
|
+
]);
|
|
449
|
+
return {
|
|
450
|
+
task_id: task.task_id,
|
|
451
|
+
title: task.title,
|
|
452
|
+
status: task.status,
|
|
453
|
+
reward: task.reward,
|
|
454
|
+
reward_currency: task.reward_currency,
|
|
455
|
+
participations,
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
// ── Bridge: performAction for manual review ────────────────────────────────
|
|
459
|
+
ctx.actions.register("acn-review", async (params) => {
|
|
460
|
+
const taskId = params.taskId;
|
|
461
|
+
const approved = params.approved;
|
|
462
|
+
const feedback = params.feedback;
|
|
463
|
+
await client.reviewTask(taskId, approved, feedback);
|
|
464
|
+
return { ok: true };
|
|
465
|
+
});
|
|
466
|
+
ctx.logger.info("acn-plugin: setup complete", { subnet_id: cfg.acnSubnetId });
|
|
467
|
+
},
|
|
468
|
+
async onHealth() {
|
|
469
|
+
return { status: "ok", message: "ACN plugin running" };
|
|
470
|
+
},
|
|
471
|
+
// ── P0-3 Inbound ACN webhook events ──────────────────────────────────────────
|
|
472
|
+
async onWebhook(input) {
|
|
473
|
+
if (input.endpointKey !== WEBHOOK_KEYS.acnEvents)
|
|
474
|
+
return;
|
|
475
|
+
if (!_ctx || !_cfg || !_client) {
|
|
476
|
+
// setup() hasn't completed yet — rare, but guard it
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
if (!verifyAcnSignature(input.headers, input.rawBody, _harnessSecret)) {
|
|
480
|
+
_ctx.logger.warn("acn-plugin: rejected webhook with invalid signature", {
|
|
481
|
+
request_id: input.requestId,
|
|
482
|
+
});
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
await handleAcnWebhook(_ctx, _cfg, _client, input.rawBody);
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
// ── Entry point ───────────────────────────────────────────────────────────────
|
|
489
|
+
export default plugin;
|
|
490
|
+
runWorker(plugin, import.meta.url);
|
|
491
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@acnlabs/paperclip-plugin-acn",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Paperclip plugin that connects ACN (Agent Collaboration Network) as the identity, communication, and settlement layer",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "ACN Labs",
|
|
7
|
+
"homepage": "https://github.com/acnlabs/paperclip-acn-plugin",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/acnlabs/paperclip-acn-plugin.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/acnlabs/paperclip-acn-plugin/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"paperclip",
|
|
17
|
+
"paperclip-plugin",
|
|
18
|
+
"acn",
|
|
19
|
+
"agent-collaboration-network",
|
|
20
|
+
"agents"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"paperclipPlugin": {
|
|
29
|
+
"manifest": "./dist/manifest.js",
|
|
30
|
+
"worker": "./dist/worker.js",
|
|
31
|
+
"ui": "./dist/ui/"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc && node ./scripts/build-ui.mjs",
|
|
35
|
+
"clean": "rm -rf dist",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
37
|
+
"dev": "tsc --watch",
|
|
38
|
+
"test": "node --import tsx --test tests/*.test.ts",
|
|
39
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@paperclipai/plugin-sdk": "^2026.512.0",
|
|
43
|
+
"acn-client": "^0.12.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^24.0.0",
|
|
47
|
+
"@types/react": "^19.0.0",
|
|
48
|
+
"@types/react-dom": "^19.0.0",
|
|
49
|
+
"esbuild": "^0.27.0",
|
|
50
|
+
"react": "^19.0.0",
|
|
51
|
+
"react-dom": "^19.0.0",
|
|
52
|
+
"tsx": "^4.21.0",
|
|
53
|
+
"typescript": "^5.7.0"
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"react": ">=18"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|