paperclip-github-plugin 0.4.4 → 0.4.6
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 +6 -5
- package/dist/manifest.js +23 -15
- package/dist/ui/index.js +60 -11
- package/dist/ui/index.js.map +2 -2
- package/dist/worker.js +171 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ The plugin adds a full in-host workflow instead of a one-off import script:
|
|
|
34
34
|
- saved sync diagnostics that let operators inspect the latest per-issue failures, raw errors, and suggested next steps
|
|
35
35
|
- a project sidebar item that opens a live project-scoped Pull Requests page for the mapped repository and can show the open PR count through a lightweight badge read
|
|
36
36
|
- manual sync actions from global, project, and issue toolbar surfaces
|
|
37
|
-
- a GitHub detail tab on synced Paperclip issues
|
|
37
|
+
- a GitHub detail tab on synced Paperclip issues that stays hidden for Paperclip issues with no linked GitHub issue
|
|
38
38
|
- GitHub link annotations on sync-generated status transition comments when the host supports comment annotations
|
|
39
39
|
|
|
40
40
|
## How it works
|
|
@@ -47,7 +47,7 @@ During sync, the plugin imports one top-level Paperclip issue per GitHub issue,
|
|
|
47
47
|
|
|
48
48
|
When the host exposes plugin issue creation, imported GitHub issues are created through the Paperclip plugin SDK path so they are not attributed to the connected board user. The worker still uses direct local Paperclip REST calls for label sync and for description or status repair paths when those routes are available.
|
|
49
49
|
|
|
50
|
-
Long-running syncs continue in the background, so quick actions do not have to wait for the whole import to finish. Once a sync has started, the settings page, dashboard widget, and toolbar actions can request cancellation; the worker stops cooperatively after the current repository or issue step finishes.
|
|
50
|
+
Long-running syncs continue in the background, so quick actions do not have to wait for the whole import to finish. Once a sync has started, the settings page, dashboard widget, and toolbar actions can request cancellation; the worker stops cooperatively after the current repository or issue step finishes. If the worker restarts mid-run, GitHub Sync now recovers that orphaned `running` state on the next read or control action instead of leaving the UI stuck in `running` or silently restarting the old run.
|
|
51
51
|
|
|
52
52
|
## Highlights
|
|
53
53
|
|
|
@@ -71,7 +71,7 @@ Paperclip issue linkage on the queue prefers the GitHub issue that the pull requ
|
|
|
71
71
|
|
|
72
72
|
### Agent workflows built in
|
|
73
73
|
|
|
74
|
-
Paperclip agents can search GitHub for duplicates, read and update issues, post comments, create pull requests, inspect changed files and CI, reply to review threads, resolve or unresolve threads, request reviewers,
|
|
74
|
+
Paperclip agents can search GitHub for duplicates, read and update issues, post comments, create pull requests, inspect changed files and CI, reply to review threads, resolve or unresolve threads, request reviewers, search org-level GitHub Projects, and associate pull requests with those projects without leaving the Paperclip plugin surface.
|
|
75
75
|
|
|
76
76
|
## Requirements
|
|
77
77
|
|
|
@@ -185,9 +185,9 @@ The plugin exposes GitHub workflow tools to Paperclip agents, including:
|
|
|
185
185
|
- issue reads, comment reads, comment writes, and metadata updates
|
|
186
186
|
- pull request creation, reads, updates, changed-file inspection, and CI-check inspection
|
|
187
187
|
- review-thread reads, replies, resolve and unresolve actions, and reviewer requests
|
|
188
|
-
- organization-level GitHub Project listing and pull-request-to-project association
|
|
188
|
+
- organization-level GitHub Project search/listing and pull-request-to-project association
|
|
189
189
|
|
|
190
|
-
When an agent
|
|
190
|
+
When an agent sends GitHub body content through the plugin, including issue bodies, pull request descriptions, comments, and review-thread replies, the plugin adds a GitHub-flavored Markdown footer with a horizontal rule and compact heading that discloses AI authorship. If the tool caller supplies `llmModel`, the footer also includes the model name, for example `###### ✨ This comment was AI-generated using gpt-5.4`.
|
|
191
191
|
|
|
192
192
|
Current host caveat: on authenticated Paperclip deployments, the Paperclip host currently guards `GET /api/plugins/tools` and `POST /api/plugins/tools/execute` with board authentication before dispatching to any plugin worker. If an agent run does not have board access for the target company, GitHub Sync tool discovery and execution fail with `403 {"error":"Board access required"}` before this plugin's worker code runs.
|
|
193
193
|
|
|
@@ -203,6 +203,7 @@ Current host caveat: on authenticated Paperclip deployments, the Paperclip host
|
|
|
203
203
|
- If a GitHub-linked project does not show the **Pull requests** sidebar entry, reopen the plugin settings and re-save the mapping. The project pull request surfaces also recover older mappings when saved ids are missing, and they can fall back to the active project's bound GitHub repository when the project already has a GitHub workspace configured.
|
|
204
204
|
- If GitHub rate limiting is hit, the plugin pauses sync until the reported reset time instead of retrying pointlessly.
|
|
205
205
|
- If a manual sync takes longer than the host action window, it continues in the background and updates the UI when it finishes or when a cancellation request stops it.
|
|
206
|
+
- If a sync shows `running` after the worker has restarted, the next settings read, toolbar read, cancel action, or scheduler tick will reconcile that stale run into an interrupted error or a cancelled result so you can retry cleanly.
|
|
206
207
|
|
|
207
208
|
## Development
|
|
208
209
|
|
package/dist/manifest.js
CHANGED
|
@@ -35,7 +35,7 @@ var projectNumberProperty = {
|
|
|
35
35
|
};
|
|
36
36
|
var llmModelProperty = {
|
|
37
37
|
type: "string",
|
|
38
|
-
description: "Exact LLM name used to draft the
|
|
38
|
+
description: "Exact LLM name used to draft the GitHub content. When provided, the plugin includes it in the mandatory AI-authorship footer."
|
|
39
39
|
};
|
|
40
40
|
var issueTargetSchema = {
|
|
41
41
|
anyOf: [
|
|
@@ -149,7 +149,7 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
149
149
|
{
|
|
150
150
|
name: "update_issue",
|
|
151
151
|
displayName: "Update Issue",
|
|
152
|
-
description: "Update GitHub issue fields such as title, body, state, labels, assignees, or milestone.",
|
|
152
|
+
description: "Update GitHub issue fields such as title, body, state, labels, assignees, or milestone. When a non-empty body is provided, the plugin appends an AI-authorship footer and includes llmModel when supplied.",
|
|
153
153
|
parametersSchema: {
|
|
154
154
|
type: "object",
|
|
155
155
|
additionalProperties: false,
|
|
@@ -162,8 +162,10 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
162
162
|
type: "string"
|
|
163
163
|
},
|
|
164
164
|
body: {
|
|
165
|
-
type: "string"
|
|
165
|
+
type: "string",
|
|
166
|
+
description: "Optional human-facing issue description body. If provided, it must remain non-empty after trimming and removing any existing AI footer."
|
|
166
167
|
},
|
|
168
|
+
llmModel: llmModelProperty,
|
|
167
169
|
state: {
|
|
168
170
|
type: "string",
|
|
169
171
|
enum: ["open", "closed"]
|
|
@@ -215,11 +217,11 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
215
217
|
{
|
|
216
218
|
name: "add_issue_comment",
|
|
217
219
|
displayName: "Add Issue Comment",
|
|
218
|
-
description: "Post a comment on a GitHub issue or pull request. Provide only the human-facing message body;
|
|
220
|
+
description: "Post a comment on a GitHub issue or pull request. Provide only the human-facing message body; it must remain non-empty after trimming and removing any existing AI footer. The plugin appends the required AI-authorship footer and includes llmModel when supplied.",
|
|
219
221
|
parametersSchema: {
|
|
220
222
|
type: "object",
|
|
221
223
|
additionalProperties: false,
|
|
222
|
-
required: ["body"
|
|
224
|
+
required: ["body"],
|
|
223
225
|
...issueTargetSchema,
|
|
224
226
|
properties: {
|
|
225
227
|
repository: repositoryProperty,
|
|
@@ -227,7 +229,8 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
227
229
|
paperclipIssueId: paperclipIssueIdProperty,
|
|
228
230
|
body: {
|
|
229
231
|
type: "string",
|
|
230
|
-
|
|
232
|
+
minLength: 1,
|
|
233
|
+
description: "Human-facing comment body without the AI footer. It must remain non-empty after trimming and removing any existing AI footer."
|
|
231
234
|
},
|
|
232
235
|
llmModel: llmModelProperty
|
|
233
236
|
}
|
|
@@ -236,7 +239,7 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
236
239
|
{
|
|
237
240
|
name: "create_pull_request",
|
|
238
241
|
displayName: "Create Pull Request",
|
|
239
|
-
description: "Open a GitHub pull request once the implementation branch is pushed.",
|
|
242
|
+
description: "Open a GitHub pull request once the implementation branch is pushed. When a non-empty body is provided, the plugin appends an AI-authorship footer and includes llmModel when supplied.",
|
|
240
243
|
parametersSchema: {
|
|
241
244
|
type: "object",
|
|
242
245
|
additionalProperties: false,
|
|
@@ -255,8 +258,10 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
255
258
|
type: "string"
|
|
256
259
|
},
|
|
257
260
|
body: {
|
|
258
|
-
type: "string"
|
|
261
|
+
type: "string",
|
|
262
|
+
description: "Optional human-facing pull request description. If provided, it must remain non-empty after trimming and removing any existing AI footer."
|
|
259
263
|
},
|
|
264
|
+
llmModel: llmModelProperty,
|
|
260
265
|
draft: {
|
|
261
266
|
type: "boolean"
|
|
262
267
|
}
|
|
@@ -281,7 +286,7 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
281
286
|
{
|
|
282
287
|
name: "update_pull_request",
|
|
283
288
|
displayName: "Update Pull Request",
|
|
284
|
-
description: "Edit pull request title, body, base branch, open or close it, or convert between draft and ready for review.",
|
|
289
|
+
description: "Edit pull request title, body, base branch, open or close it, or convert between draft and ready for review. When a non-empty body is provided, the plugin appends an AI-authorship footer and includes llmModel when supplied.",
|
|
285
290
|
parametersSchema: {
|
|
286
291
|
type: "object",
|
|
287
292
|
additionalProperties: false,
|
|
@@ -294,8 +299,10 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
294
299
|
type: "string"
|
|
295
300
|
},
|
|
296
301
|
body: {
|
|
297
|
-
type: "string"
|
|
302
|
+
type: "string",
|
|
303
|
+
description: "Optional human-facing pull request description. If provided, it must remain non-empty after trimming and removing any existing AI footer."
|
|
298
304
|
},
|
|
305
|
+
llmModel: llmModelProperty,
|
|
299
306
|
base: {
|
|
300
307
|
type: "string"
|
|
301
308
|
},
|
|
@@ -358,11 +365,11 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
358
365
|
{
|
|
359
366
|
name: "reply_to_review_thread",
|
|
360
367
|
displayName: "Reply To Review Thread",
|
|
361
|
-
description: "Reply to an existing pull request review thread. Provide only the human-facing body;
|
|
368
|
+
description: "Reply to an existing pull request review thread. Provide only the human-facing body; the plugin appends the required AI-authorship footer and includes llmModel when supplied.",
|
|
362
369
|
parametersSchema: {
|
|
363
370
|
type: "object",
|
|
364
371
|
additionalProperties: false,
|
|
365
|
-
required: ["threadId", "body"
|
|
372
|
+
required: ["threadId", "body"],
|
|
366
373
|
properties: {
|
|
367
374
|
threadId: {
|
|
368
375
|
type: "string",
|
|
@@ -370,7 +377,8 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
370
377
|
},
|
|
371
378
|
body: {
|
|
372
379
|
type: "string",
|
|
373
|
-
|
|
380
|
+
minLength: 1,
|
|
381
|
+
description: "Human-facing reply body without the AI footer. It must remain non-empty after trimming and removing any existing AI footer."
|
|
374
382
|
},
|
|
375
383
|
llmModel: llmModelProperty
|
|
376
384
|
}
|
|
@@ -454,7 +462,7 @@ var GITHUB_AGENT_TOOLS = [
|
|
|
454
462
|
{
|
|
455
463
|
name: "list_organization_projects",
|
|
456
464
|
displayName: "List Organization Projects",
|
|
457
|
-
description: "
|
|
465
|
+
description: "Search or list GitHub organization-level Projects so an agent can choose where to associate pull requests.",
|
|
458
466
|
parametersSchema: {
|
|
459
467
|
type: "object",
|
|
460
468
|
additionalProperties: false,
|
|
@@ -503,7 +511,7 @@ var require2 = createRequire(import.meta.url);
|
|
|
503
511
|
var packageJson = require2("../package.json");
|
|
504
512
|
var DASHBOARD_WIDGET_CAPABILITY = "ui.dashboardWidget.register";
|
|
505
513
|
var SCHEDULE_TICK_CRON = "* * * * *";
|
|
506
|
-
var MANIFEST_VERSION = "0.4.
|
|
514
|
+
var MANIFEST_VERSION = "0.4.6"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
|
|
507
515
|
var manifest = {
|
|
508
516
|
id: "paperclip-github-plugin",
|
|
509
517
|
apiVersion: 1,
|
package/dist/ui/index.js
CHANGED
|
@@ -23091,6 +23091,21 @@ function getActiveRateLimitPause(syncState, referenceTimeMs = Date.now()) {
|
|
|
23091
23091
|
function isSyncCancellationRequested(syncState) {
|
|
23092
23092
|
return syncState.status === "running" && Boolean(syncState.cancelRequestedAt?.trim());
|
|
23093
23093
|
}
|
|
23094
|
+
function resolveToolbarButtonState(params) {
|
|
23095
|
+
const syncPersistedRunning = params.syncState.status === "running";
|
|
23096
|
+
const syncStartPending = params.runningSync && !syncPersistedRunning;
|
|
23097
|
+
const cancellationRequested = syncPersistedRunning && (params.cancellingSync || isSyncCancellationRequested(params.syncState));
|
|
23098
|
+
const loadingVisible = params.loading && !syncPersistedRunning;
|
|
23099
|
+
return {
|
|
23100
|
+
busy: loadingVisible || syncStartPending || cancellationRequested || !params.allowToolbarCancellation && syncPersistedRunning,
|
|
23101
|
+
disabled: loadingVisible || syncStartPending || (syncPersistedRunning ? params.allowToolbarCancellation ? cancellationRequested : true : !params.effectiveCanRun),
|
|
23102
|
+
label: syncPersistedRunning && params.allowToolbarCancellation ? "Cancel sync" : params.effectiveLabel,
|
|
23103
|
+
busyLabel: syncPersistedRunning ? cancellationRequested ? "Cancelling\u2026" : "Syncing\u2026" : loadingVisible ? "Loading\u2026" : "Syncing\u2026",
|
|
23104
|
+
cancellationRequested,
|
|
23105
|
+
syncPersistedRunning,
|
|
23106
|
+
syncStartPending
|
|
23107
|
+
};
|
|
23108
|
+
}
|
|
23094
23109
|
function getSyncToastTitle(syncState) {
|
|
23095
23110
|
if (getActiveRateLimitPause(syncState)) {
|
|
23096
23111
|
return "GitHub sync is paused";
|
|
@@ -33162,13 +33177,25 @@ function GitHubSyncToolbarButtonSurface(props) {
|
|
|
33162
33177
|
const effectiveCanRun = state.canRun && !boardAccessSetupIssue;
|
|
33163
33178
|
const effectiveMessage = boardAccessSetupIssue ? getSyncSetupMessage(boardAccessSetupIssue, hasCompanyContext) : state.message;
|
|
33164
33179
|
const effectiveLabel = boardAccessSetupIssue ? "Board access required" : state.label;
|
|
33165
|
-
const syncPersistedRunning = effectiveSyncState.status === "running";
|
|
33166
|
-
const syncStartPending = runningSync && !syncPersistedRunning;
|
|
33167
33180
|
const allowToolbarCancellation = Boolean(props.entityType);
|
|
33168
|
-
const
|
|
33169
|
-
|
|
33170
|
-
|
|
33171
|
-
|
|
33181
|
+
const toolbarButtonState = resolveToolbarButtonState({
|
|
33182
|
+
loading: toolbarState.loading,
|
|
33183
|
+
runningSync,
|
|
33184
|
+
cancellingSync,
|
|
33185
|
+
syncState: effectiveSyncState,
|
|
33186
|
+
allowToolbarCancellation,
|
|
33187
|
+
effectiveCanRun,
|
|
33188
|
+
effectiveLabel
|
|
33189
|
+
});
|
|
33190
|
+
const {
|
|
33191
|
+
busy: toolbarButtonBusy,
|
|
33192
|
+
disabled: toolbarButtonDisabled,
|
|
33193
|
+
label: toolbarButtonLabel,
|
|
33194
|
+
busyLabel: toolbarButtonBusyLabel,
|
|
33195
|
+
syncPersistedRunning,
|
|
33196
|
+
syncStartPending,
|
|
33197
|
+
cancellationRequested
|
|
33198
|
+
} = toolbarButtonState;
|
|
33172
33199
|
const armSyncCompletionToast = useSyncCompletionToast(effectiveSyncState, toast);
|
|
33173
33200
|
useEffect2(() => {
|
|
33174
33201
|
if (effectiveSyncState.status !== "running") {
|
|
@@ -33343,7 +33370,7 @@ function GitHubSyncToolbarButtonSurface(props) {
|
|
|
33343
33370
|
"data-variant": "outline",
|
|
33344
33371
|
"data-size": "sm",
|
|
33345
33372
|
className: props.entityType ? HOST_ENTITY_BUTTON_CLASSNAME : HOST_GLOBAL_BUTTON_CLASSNAME,
|
|
33346
|
-
disabled:
|
|
33373
|
+
disabled: toolbarButtonDisabled,
|
|
33347
33374
|
onClick: syncPersistedRunning && allowToolbarCancellation ? handleCancelSync : handleRunSync,
|
|
33348
33375
|
children: /* @__PURE__ */ jsx2(
|
|
33349
33376
|
LoadingButtonContent,
|
|
@@ -33385,6 +33412,12 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
33385
33412
|
...props.issueId ? { issueId: props.issueId } : {}
|
|
33386
33413
|
});
|
|
33387
33414
|
const issueDetails = details.data?.paperclipIssueId === props.issueId ? details.data : null;
|
|
33415
|
+
const detailTabState = resolveGitHubIssueDetailTabState({
|
|
33416
|
+
loadingIssueId: props.loadingIssueId,
|
|
33417
|
+
detailsLoading: details.loading,
|
|
33418
|
+
detailsError: Boolean(details.error),
|
|
33419
|
+
issueDetails
|
|
33420
|
+
});
|
|
33388
33421
|
useEffect2(() => {
|
|
33389
33422
|
if (!props.companyId || !props.issueId) {
|
|
33390
33423
|
return;
|
|
@@ -33395,12 +33428,14 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
33395
33428
|
return;
|
|
33396
33429
|
}
|
|
33397
33430
|
}, [details.refresh, props.companyId, props.issueId]);
|
|
33431
|
+
if (detailTabState === "hidden") {
|
|
33432
|
+
return null;
|
|
33433
|
+
}
|
|
33398
33434
|
return /* @__PURE__ */ jsxs2("section", { className: "ghsync-issue-detail", style: props.themeVars, children: [
|
|
33399
33435
|
/* @__PURE__ */ jsx2("style", { children: EXTENSION_SURFACE_STYLES }),
|
|
33400
|
-
|
|
33401
|
-
details.error ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: details.error.message }) : null,
|
|
33402
|
-
|
|
33403
|
-
issueDetails ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
33436
|
+
detailTabState === "loading" ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: "Loading GitHub sync details\u2026" }) : null,
|
|
33437
|
+
detailTabState === "error" && details.error ? /* @__PURE__ */ jsx2("p", { className: "ghsync-extension-empty", children: details.error.message }) : null,
|
|
33438
|
+
detailTabState === "ready" && issueDetails ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
33404
33439
|
/* @__PURE__ */ jsxs2("div", { className: "ghsync-extension-heading", children: [
|
|
33405
33440
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
33406
33441
|
/* @__PURE__ */ jsxs2("h4", { children: [
|
|
@@ -33479,6 +33514,18 @@ function GitHubSyncIssueDetailTabContent(props) {
|
|
|
33479
33514
|
] }) : null
|
|
33480
33515
|
] });
|
|
33481
33516
|
}
|
|
33517
|
+
function resolveGitHubIssueDetailTabState(params) {
|
|
33518
|
+
if (params.loadingIssueId || params.detailsLoading && !params.issueDetails) {
|
|
33519
|
+
return "loading";
|
|
33520
|
+
}
|
|
33521
|
+
if (params.issueDetails) {
|
|
33522
|
+
return "ready";
|
|
33523
|
+
}
|
|
33524
|
+
if (params.detailsError) {
|
|
33525
|
+
return "error";
|
|
33526
|
+
}
|
|
33527
|
+
return "hidden";
|
|
33528
|
+
}
|
|
33482
33529
|
function GitHubSyncIssueTaskDetailView() {
|
|
33483
33530
|
const context = useHostContext();
|
|
33484
33531
|
const themeMode = useResolvedThemeMode();
|
|
@@ -33553,8 +33600,10 @@ export {
|
|
|
33553
33600
|
GitHubSyncProjectPullRequestsSidebarItem,
|
|
33554
33601
|
GitHubSyncSettingsPage,
|
|
33555
33602
|
index_default as default,
|
|
33603
|
+
resolveGitHubIssueDetailTabState,
|
|
33556
33604
|
resolveOrCreateProject,
|
|
33557
33605
|
resolveSavedTokenUiState,
|
|
33606
|
+
resolveToolbarButtonState,
|
|
33558
33607
|
syncGitHubTokenPropagationForAgents
|
|
33559
33608
|
};
|
|
33560
33609
|
//# sourceMappingURL=index.js.map
|