paperclip-github-plugin 0.8.9 → 0.8.11
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 +29 -1
- package/dist/manifest.js +63 -1
- package/dist/ui/index.js +20 -8
- package/dist/ui/index.js.map +4 -4
- package/dist/worker.js +348 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -227,7 +227,7 @@ The plugin exposes GitHub workflow tools to Paperclip agents, including:
|
|
|
227
227
|
|
|
228
228
|
- repository-scoped search for issues and pull requests
|
|
229
229
|
- issue reads, comment reads, comment writes, metadata updates, and `assign_to_current_user` assignment to the saved token owner
|
|
230
|
-
- pull request creation, reads, updates, changed-file inspection,
|
|
230
|
+
- pull request creation, reads, updates, changed-file inspection, CI-check inspection, and asset upload for PR visual evidence
|
|
231
231
|
- review-thread reads, replies, resolve and unresolve actions, and `request_pull_request_reviewers` reviewer requests
|
|
232
232
|
- organization-level GitHub Project search/listing and pull-request-to-project association
|
|
233
233
|
|
|
@@ -272,6 +272,34 @@ Current host caveat: on authenticated Paperclip deployments, the Paperclip host
|
|
|
272
272
|
|
|
273
273
|
Because the KPI attribution endpoint is a native plugin JSON route rather than a plugin tool, authenticated agent runs can still call it directly with `PAPERCLIP_API_KEY` even while that host bug blocks the GitHub Sync tool surface.
|
|
274
274
|
|
|
275
|
+
### Pull request asset upload
|
|
276
|
+
|
|
277
|
+
For PRs that need durable assets in the description, agents can call the `upload_pull_request_asset` tool. The tool accepts a PR target plus `fileName` and either `contentBase64` or a `dataUrl`; optional fields include `label`, `alt` (an alias for image alt text), `caption`, `mimeType`, and `artifactBranch`. Common MIME types are inferred from filenames, including images and PDFs. Unknown types are stored as `application/octet-stream`. Assets are limited to 10 MiB.
|
|
278
|
+
|
|
279
|
+
The plugin writes the asset to a non-merge artifact branch named `paperclip-artifacts-pr-<number>` by default, stores it under `assets/pr-<number>/<head-sha>/`, and returns immutable raw GitHub URLs plus Markdown suitable for a PR description. Images return image Markdown; PDFs and other files return normal Markdown links.
|
|
280
|
+
|
|
281
|
+
Authenticated agent runs that cannot call plugin tools can post the same JSON payload to `/api/plugins/paperclip-github-plugin/api/pull-request-assets` with `Authorization: Bearer ${PAPERCLIP_API_KEY}`. The native plugin route is agent-authenticated by the Paperclip host before worker dispatch.
|
|
282
|
+
|
|
283
|
+
Example:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
contentBase64="$(base64 -w0 /tmp/review-report.pdf)"
|
|
287
|
+
payload="$(jq -n \
|
|
288
|
+
--arg repository paperclipai/example-repo \
|
|
289
|
+
--argjson pullRequestNumber 21 \
|
|
290
|
+
--arg fileName review-report.pdf \
|
|
291
|
+
--arg label 'Review report PDF' \
|
|
292
|
+
--arg contentBase64 "$contentBase64" \
|
|
293
|
+
'{repository:$repository,pullRequestNumber:$pullRequestNumber,fileName:$fileName,label:$label,contentBase64:$contentBase64,mimeType:"application/pdf"}')"
|
|
294
|
+
|
|
295
|
+
curl -X POST "${PAPERCLIP_API_URL%/}/api/plugins/paperclip-github-plugin/api/pull-request-assets" \
|
|
296
|
+
-H "content-type: application/json" \
|
|
297
|
+
-H "authorization: Bearer ${PAPERCLIP_API_KEY}" \
|
|
298
|
+
-d "${payload}"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The response body contains `asset.markdown`, `asset.rawUrl`, `asset.artifactBranch`, `asset.path`, and `asset.commitSha`.
|
|
302
|
+
|
|
275
303
|
### Issue link API route
|
|
276
304
|
|
|
277
305
|
Authenticated agent runs can link the current Paperclip issue to a GitHub issue or pull request by posting to `/api/plugins/paperclip-github-plugin/api/issue-link`. This is useful after creating a PR with `gh` in a repository that is not mapped to a Paperclip project.
|
package/dist/manifest.js
CHANGED
|
@@ -523,6 +523,58 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
},
|
|
526
|
+
{
|
|
527
|
+
name: "upload_pull_request_asset",
|
|
528
|
+
displayName: "Upload Pull Request Asset",
|
|
529
|
+
description: "Upload a PR-visible asset such as an image, PDF, log, archive, or report to a non-merge artifact branch and return durable markdown that can be embedded in the PR body.",
|
|
530
|
+
parametersSchema: {
|
|
531
|
+
type: "object",
|
|
532
|
+
additionalProperties: false,
|
|
533
|
+
required: ["fileName"],
|
|
534
|
+
allOf: [pullRequestTargetSchema],
|
|
535
|
+
anyOf: [
|
|
536
|
+
{ required: ["contentBase64"] },
|
|
537
|
+
{ required: ["dataUrl"] }
|
|
538
|
+
],
|
|
539
|
+
properties: {
|
|
540
|
+
repository: repositoryProperty,
|
|
541
|
+
pullRequestNumber: pullRequestNumberProperty,
|
|
542
|
+
paperclipIssueId: paperclipIssueIdProperty,
|
|
543
|
+
fileName: {
|
|
544
|
+
type: "string",
|
|
545
|
+
description: "Asset filename. The plugin sanitizes it and preserves a safe extension."
|
|
546
|
+
},
|
|
547
|
+
label: {
|
|
548
|
+
type: "string",
|
|
549
|
+
description: "Human-readable link text for the returned Markdown. Defaults to the sanitized filename."
|
|
550
|
+
},
|
|
551
|
+
alt: {
|
|
552
|
+
type: "string",
|
|
553
|
+
description: "Backward-compatible alias for label, useful as image alt text."
|
|
554
|
+
},
|
|
555
|
+
caption: {
|
|
556
|
+
type: "string",
|
|
557
|
+
description: "Optional human-facing caption returned with the uploaded asset metadata."
|
|
558
|
+
},
|
|
559
|
+
contentBase64: {
|
|
560
|
+
type: "string",
|
|
561
|
+
description: "Base64-encoded asset bytes. Assets are limited to 10 MiB."
|
|
562
|
+
},
|
|
563
|
+
dataUrl: {
|
|
564
|
+
type: "string",
|
|
565
|
+
description: "Alternative base64 data URL input such as data:application/pdf;base64,... or data:image/png;base64,... ."
|
|
566
|
+
},
|
|
567
|
+
mimeType: {
|
|
568
|
+
type: "string",
|
|
569
|
+
description: "Optional MIME type such as application/pdf or image/png. If omitted, the plugin infers common types from fileName and otherwise uses application/octet-stream."
|
|
570
|
+
},
|
|
571
|
+
artifactBranch: {
|
|
572
|
+
type: "string",
|
|
573
|
+
description: "Optional artifact branch name. Defaults to paperclip-artifacts-pr-<pullRequestNumber>."
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
},
|
|
526
578
|
{
|
|
527
579
|
name: "link_github_item",
|
|
528
580
|
displayName: "Link GitHub Item",
|
|
@@ -582,12 +634,15 @@ var COMPANY_METRIC_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/a
|
|
|
582
634
|
var ISSUE_LINK_API_ROUTE_KEY = "link-github-item";
|
|
583
635
|
var ISSUE_LINK_API_ROUTE_PATH = "/issue-link";
|
|
584
636
|
var ISSUE_LINK_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/api${ISSUE_LINK_API_ROUTE_PATH}`;
|
|
637
|
+
var PULL_REQUEST_ASSET_API_ROUTE_KEY = "upload-pull-request-asset";
|
|
638
|
+
var PULL_REQUEST_ASSET_API_ROUTE_PATH = "/pull-request-assets";
|
|
639
|
+
var PULL_REQUEST_ASSET_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/api${PULL_REQUEST_ASSET_API_ROUTE_PATH}`;
|
|
585
640
|
|
|
586
641
|
// src/manifest.ts
|
|
587
642
|
var require2 = createRequire(import.meta.url);
|
|
588
643
|
var packageJson = require2("../package.json");
|
|
589
644
|
var SCHEDULE_TICK_CRON = "* * * * *";
|
|
590
|
-
var MANIFEST_VERSION = "0.8.
|
|
645
|
+
var MANIFEST_VERSION = "0.8.11"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
|
|
591
646
|
var manifest = {
|
|
592
647
|
id: GITHUB_SYNC_PLUGIN_ID,
|
|
593
648
|
apiVersion: 1,
|
|
@@ -666,6 +721,13 @@ var manifest = {
|
|
|
666
721
|
path: ISSUE_LINK_API_ROUTE_PATH,
|
|
667
722
|
auth: "agent",
|
|
668
723
|
capability: "api.routes.register"
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
routeKey: PULL_REQUEST_ASSET_API_ROUTE_KEY,
|
|
727
|
+
method: "POST",
|
|
728
|
+
path: PULL_REQUEST_ASSET_API_ROUTE_PATH,
|
|
729
|
+
auth: "agent",
|
|
730
|
+
capability: "api.routes.register"
|
|
669
731
|
}
|
|
670
732
|
],
|
|
671
733
|
tools: GITHUB_AGENT_TOOLS,
|
package/dist/ui/index.js
CHANGED
|
@@ -366,7 +366,7 @@ import {
|
|
|
366
366
|
usePluginToast
|
|
367
367
|
} from "@paperclipai/plugin-sdk/ui";
|
|
368
368
|
|
|
369
|
-
// node_modules/.pnpm/@ungap+structured-clone@1.3.
|
|
369
|
+
// node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/types.js
|
|
370
370
|
var VOID = -1;
|
|
371
371
|
var PRIMITIVE = 0;
|
|
372
372
|
var ARRAY = 1;
|
|
@@ -378,8 +378,20 @@ var SET = 6;
|
|
|
378
378
|
var ERROR = 7;
|
|
379
379
|
var BIGINT = 8;
|
|
380
380
|
|
|
381
|
-
// node_modules/.pnpm/@ungap+structured-clone@1.3.
|
|
381
|
+
// node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/deserialize.js
|
|
382
382
|
var env = typeof self === "object" ? self : globalThis;
|
|
383
|
+
var guard = (name2, init) => {
|
|
384
|
+
switch (name2) {
|
|
385
|
+
case "Function":
|
|
386
|
+
case "SharedWorker":
|
|
387
|
+
case "Worker":
|
|
388
|
+
case "eval":
|
|
389
|
+
case "setInterval":
|
|
390
|
+
case "setTimeout":
|
|
391
|
+
throw new TypeError("unable to deserialize " + name2);
|
|
392
|
+
}
|
|
393
|
+
return new env[name2](init);
|
|
394
|
+
};
|
|
383
395
|
var deserializer = ($2, _) => {
|
|
384
396
|
const as = (out, index2) => {
|
|
385
397
|
$2.set(index2, out);
|
|
@@ -425,7 +437,7 @@ var deserializer = ($2, _) => {
|
|
|
425
437
|
}
|
|
426
438
|
case ERROR: {
|
|
427
439
|
const { name: name2, message } = value;
|
|
428
|
-
return as(
|
|
440
|
+
return as(guard(name2, message), index2);
|
|
429
441
|
}
|
|
430
442
|
case BIGINT:
|
|
431
443
|
return as(BigInt(value), index2);
|
|
@@ -438,13 +450,13 @@ var deserializer = ($2, _) => {
|
|
|
438
450
|
return as(new DataView(buffer), value);
|
|
439
451
|
}
|
|
440
452
|
}
|
|
441
|
-
return as(
|
|
453
|
+
return as(guard(type, value), index2);
|
|
442
454
|
};
|
|
443
455
|
return unpair;
|
|
444
456
|
};
|
|
445
457
|
var deserialize = (serialized) => deserializer(/* @__PURE__ */ new Map(), serialized)(0);
|
|
446
458
|
|
|
447
|
-
// node_modules/.pnpm/@ungap+structured-clone@1.3.
|
|
459
|
+
// node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/serialize.js
|
|
448
460
|
var EMPTY = "";
|
|
449
461
|
var { toString } = {};
|
|
450
462
|
var { keys } = Object;
|
|
@@ -577,7 +589,7 @@ var serialize = (value, { json, lossy } = {}) => {
|
|
|
577
589
|
return serializer(!(json || lossy), !!json, /* @__PURE__ */ new Map(), _)(value), _;
|
|
578
590
|
};
|
|
579
591
|
|
|
580
|
-
// node_modules/.pnpm/@ungap+structured-clone@1.3.
|
|
592
|
+
// node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/index.js
|
|
581
593
|
var esm_default = typeof structuredClone === "function" ? (
|
|
582
594
|
/* c8 ignore start */
|
|
583
595
|
(any, options) => options && ("json" in options || "lossy" in options) ? deserialize(serialize(any, options)) : structuredClone(any)
|
|
@@ -11984,7 +11996,7 @@ var urlAttributes = {
|
|
|
11984
11996
|
]
|
|
11985
11997
|
};
|
|
11986
11998
|
|
|
11987
|
-
// node_modules/.pnpm/react-markdown@10.1.0_@types+react@19.2.14_react@19.2.
|
|
11999
|
+
// node_modules/.pnpm/react-markdown@10.1.0_@types+react@19.2.14_react@19.2.6/node_modules/react-markdown/lib/index.js
|
|
11988
12000
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11989
12001
|
import { useEffect, useState } from "react";
|
|
11990
12002
|
|
|
@@ -19140,7 +19152,7 @@ function isUint8Array2(value) {
|
|
|
19140
19152
|
);
|
|
19141
19153
|
}
|
|
19142
19154
|
|
|
19143
|
-
// node_modules/.pnpm/react-markdown@10.1.0_@types+react@19.2.14_react@19.2.
|
|
19155
|
+
// node_modules/.pnpm/react-markdown@10.1.0_@types+react@19.2.14_react@19.2.6/node_modules/react-markdown/lib/index.js
|
|
19144
19156
|
var changelog = "https://github.com/remarkjs/react-markdown/blob/main/changelog.md";
|
|
19145
19157
|
var emptyPlugins = [];
|
|
19146
19158
|
var emptyRemarkRehypeOptions = { allowDangerousHtml: true };
|