paperclip-github-plugin 0.8.5 → 0.8.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/dist/manifest.js CHANGED
@@ -535,7 +535,7 @@ var COMPANY_METRIC_API_ROUTE_URL_PATH = `/api/plugins/${GITHUB_SYNC_PLUGIN_ID}/a
535
535
  var require2 = createRequire(import.meta.url);
536
536
  var packageJson = require2("../package.json");
537
537
  var SCHEDULE_TICK_CRON = "* * * * *";
538
- var MANIFEST_VERSION = "0.8.5"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
538
+ var MANIFEST_VERSION = "0.8.6"?.trim() || typeof packageJson.version === "string" && packageJson.version.trim() || process.env.npm_package_version?.trim() || "0.0.0-dev";
539
539
  var manifest = {
540
540
  id: GITHUB_SYNC_PLUGIN_ID,
541
541
  apiVersion: 1,
package/dist/worker.js CHANGED
@@ -1498,6 +1498,88 @@ function getErrorResponseDataMessage(error) {
1498
1498
  const message = data.message;
1499
1499
  return typeof message === "string" && message.trim() ? message.trim() : void 0;
1500
1500
  }
1501
+ function getGitHubRequestId(error) {
1502
+ const requestId = getErrorResponseHeaders(error)["x-github-request-id"]?.trim();
1503
+ return requestId || void 0;
1504
+ }
1505
+ function buildGitHubOctokitLogMetadata(context) {
1506
+ const metadata = {};
1507
+ const companyId = normalizeCompanyId(context.companyId);
1508
+ const operation = normalizeOptionalString2(context.operation);
1509
+ const repositoryUrl = normalizeOptionalString2(context.repositoryUrl);
1510
+ const toolName = normalizeOptionalString2(context.toolName);
1511
+ if (companyId) {
1512
+ metadata.companyId = companyId;
1513
+ }
1514
+ if (operation) {
1515
+ metadata.operation = operation;
1516
+ }
1517
+ if (repositoryUrl) {
1518
+ metadata.repositoryUrl = repositoryUrl;
1519
+ }
1520
+ if (context.syncTrigger) {
1521
+ metadata.syncTrigger = context.syncTrigger;
1522
+ }
1523
+ if (toolName) {
1524
+ metadata.toolName = toolName;
1525
+ }
1526
+ return metadata;
1527
+ }
1528
+ function getGitHubOctokitRequestPath(url, baseUrl) {
1529
+ if (typeof url !== "string" || !url.trim()) {
1530
+ return void 0;
1531
+ }
1532
+ const trimmedUrl = url.trim();
1533
+ if (typeof baseUrl === "string" && baseUrl.trim() && trimmedUrl.startsWith(baseUrl.trim())) {
1534
+ return trimmedUrl.slice(baseUrl.trim().length) || "/";
1535
+ }
1536
+ try {
1537
+ const parsed = new URL(trimmedUrl);
1538
+ return `${parsed.pathname}${parsed.search}`;
1539
+ } catch {
1540
+ return trimmedUrl;
1541
+ }
1542
+ }
1543
+ function createGitHubOctokit(ctx, token, context = {}) {
1544
+ const octokit = new Octokit({
1545
+ auth: token,
1546
+ log: {
1547
+ debug: () => void 0,
1548
+ info: () => void 0,
1549
+ warn: (message) => {
1550
+ ctx.logger.warn("GitHub Octokit warning.", {
1551
+ ...buildGitHubOctokitLogMetadata(context),
1552
+ message
1553
+ });
1554
+ },
1555
+ error: () => void 0
1556
+ }
1557
+ });
1558
+ if (context.logFailures === false) {
1559
+ return octokit;
1560
+ }
1561
+ octokit.hook.wrap("request", async (request, options) => {
1562
+ const start = Date.now();
1563
+ const requestOptions = octokit.request.endpoint.parse(options);
1564
+ try {
1565
+ return await request(options);
1566
+ } catch (error) {
1567
+ const responseMessage = getErrorResponseDataMessage(error);
1568
+ ctx.logger.warn("GitHub API request failed.", {
1569
+ ...buildGitHubOctokitLogMetadata(context),
1570
+ method: requestOptions.method,
1571
+ path: getGitHubOctokitRequestPath(requestOptions.url, options.baseUrl),
1572
+ status: getErrorStatus(error) ?? null,
1573
+ requestId: getGitHubRequestId(error) ?? null,
1574
+ durationMs: Date.now() - start,
1575
+ error: getErrorMessage(error),
1576
+ ...responseMessage ? { responseMessage } : {}
1577
+ });
1578
+ throw error;
1579
+ }
1580
+ });
1581
+ return octokit;
1582
+ }
1501
1583
  function getErrorResponseDataErrors(error) {
1502
1584
  if (!error || typeof error !== "object" || !("response" in error)) {
1503
1585
  return [];
@@ -9778,12 +9860,16 @@ async function handleCompanyMetricApiRoute(ctx, input) {
9778
9860
  }
9779
9861
  };
9780
9862
  }
9781
- async function createGitHubToolOctokit(ctx, companyId) {
9863
+ async function createGitHubToolOctokit(ctx, companyId, context = {}) {
9782
9864
  const token = (await resolveGithubToken(ctx, { companyId })).trim();
9783
9865
  if (!token) {
9784
9866
  throw new Error(MISSING_GITHUB_TOKEN_SYNC_MESSAGE);
9785
9867
  }
9786
- return new Octokit({ auth: token });
9868
+ return createGitHubOctokit(ctx, token, {
9869
+ companyId,
9870
+ operation: "github-api",
9871
+ ...context
9872
+ });
9787
9873
  }
9788
9874
  async function listGitHubRepositoryOpenPullRequestNumbers(octokit, repository) {
9789
9875
  const response = await octokit.rest.pulls.list({
@@ -12684,8 +12770,11 @@ function mergeNamedValues(currentValues, params) {
12684
12770
  }
12685
12771
  return [...values.values()];
12686
12772
  }
12687
- async function validateGithubToken(token) {
12688
- const octokit = new Octokit({ auth: token.trim() });
12773
+ async function validateGithubToken(ctx, token) {
12774
+ const octokit = createGitHubOctokit(ctx, token.trim(), {
12775
+ logFailures: false,
12776
+ operation: "settings.validateToken"
12777
+ });
12689
12778
  try {
12690
12779
  const response = await octokit.rest.users.getAuthenticated();
12691
12780
  return {
@@ -12797,7 +12886,12 @@ async function performSync(ctx, trigger, options = {}) {
12797
12886
  return saveSettingsSyncState(ctx, settings, next.syncState, targetCompanyId);
12798
12887
  }
12799
12888
  activePaperclipApiAuthTokensByCompanyId = await resolvePaperclipApiAuthTokens(ctx, settings, config, mappings);
12800
- const octokit = new Octokit({ auth: token });
12889
+ const octokitLogContext = {
12890
+ companyId: targetCompanyId,
12891
+ operation: "sync.github-issues",
12892
+ syncTrigger: trigger
12893
+ };
12894
+ const octokit = createGitHubOctokit(ctx, token, octokitLogContext);
12801
12895
  let syncedIssuesCount = 0;
12802
12896
  let createdIssuesCount = 0;
12803
12897
  let skippedIssuesCount = 0;
@@ -12947,6 +13041,7 @@ async function performSync(ctx, trigger, options = {}) {
12947
13041
  await throwIfSyncCancelled();
12948
13042
  try {
12949
13043
  const repository = requireRepositoryReference(mapping.repositoryUrl);
13044
+ octokitLogContext.repositoryUrl = repository.url;
12950
13045
  const importedIssueRecords = nextRegistry.filter((entry) => doesImportedIssueRecordMatchMapping(entry, mapping)).filter((entry) => doesImportedIssueMatchTarget(entry, options.target));
12951
13046
  const shouldLoadClosedIssues = options.target?.kind === "issue" || importedIssueRecords.length > 0;
12952
13047
  currentProgress = {
@@ -13068,6 +13163,7 @@ async function performSync(ctx, trigger, options = {}) {
13068
13163
  await throwIfSyncCancelled();
13069
13164
  try {
13070
13165
  const { mapping, advancedSettings, repository, repositoryIndex, allIssuesById, issues, pullRequestLinks } = plan;
13166
+ octokitLogContext.repositoryUrl = repository.url;
13071
13167
  const companyId = mapping.companyId;
13072
13168
  let availableLabels = companyId ? companyLabelDirectoryCache.get(companyId) : void 0;
13073
13169
  if (!availableLabels) {
@@ -13509,13 +13605,19 @@ async function startSync(ctx, trigger, options = {}) {
13509
13605
  }
13510
13606
  }
13511
13607
  function registerGitHubAgentTools(ctx) {
13608
+ async function createAgentToolOctokit(runCtx, toolName, repository) {
13609
+ return createGitHubToolOctokit(ctx, runCtx.companyId, {
13610
+ toolName,
13611
+ ...repository ? { repositoryUrl: repository.url } : {}
13612
+ });
13613
+ }
13512
13614
  ctx.tools.register(
13513
13615
  "search_repository_items",
13514
13616
  getGitHubAgentToolDeclaration("search_repository_items"),
13515
13617
  async (params, runCtx) => executeGitHubTool(async () => {
13516
13618
  const input = getToolInputRecord(params);
13517
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13518
13619
  const repository = await resolveGitHubToolRepository(ctx, runCtx, input);
13620
+ const octokit = await createAgentToolOctokit(runCtx, "search_repository_items", repository);
13519
13621
  const rawQuery = normalizeOptionalToolString(input.query);
13520
13622
  if (!rawQuery) {
13521
13623
  throw new Error("query is required.");
@@ -13583,7 +13685,7 @@ function registerGitHubAgentTools(ctx) {
13583
13685
  async (params, runCtx) => executeGitHubTool(async () => {
13584
13686
  const input = getToolInputRecord(params);
13585
13687
  const target = await resolveGitHubIssueToolTarget(ctx, runCtx, input);
13586
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13688
+ const octokit = await createAgentToolOctokit(runCtx, "get_issue", target.repository);
13587
13689
  const response = await octokit.rest.issues.get({
13588
13690
  owner: target.repository.owner,
13589
13691
  repo: target.repository.repo,
@@ -13630,7 +13732,7 @@ function registerGitHubAgentTools(ctx) {
13630
13732
  async (params, runCtx) => executeGitHubTool(async () => {
13631
13733
  const input = getToolInputRecord(params);
13632
13734
  const target = await resolveGitHubIssueToolTarget(ctx, runCtx, input);
13633
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13735
+ const octokit = await createAgentToolOctokit(runCtx, "list_issue_comments", target.repository);
13634
13736
  const comments = await listAllGitHubIssueComments(octokit, target.repository, target.issueNumber);
13635
13737
  return buildToolSuccessResult(
13636
13738
  `Loaded ${comments.length} GitHub ${comments.length === 1 ? "comment" : "comments"} from issue #${target.issueNumber}.`,
@@ -13648,7 +13750,7 @@ function registerGitHubAgentTools(ctx) {
13648
13750
  async (params, runCtx) => executeGitHubTool(async () => {
13649
13751
  const input = getToolInputRecord(params);
13650
13752
  const target = await resolveGitHubIssueToolTarget(ctx, runCtx, input);
13651
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13753
+ const octokit = await createAgentToolOctokit(runCtx, "update_issue", target.repository);
13652
13754
  const currentResponse = await octokit.rest.issues.get({
13653
13755
  owner: target.repository.owner,
13654
13756
  repo: target.repository.repo,
@@ -13721,7 +13823,7 @@ function registerGitHubAgentTools(ctx) {
13721
13823
  async (params, runCtx) => executeGitHubTool(async () => {
13722
13824
  const input = getToolInputRecord(params);
13723
13825
  const target = await resolveGitHubIssueToolTarget(ctx, runCtx, input);
13724
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13826
+ const octokit = await createAgentToolOctokit(runCtx, "assign_to_current_user", target.repository);
13725
13827
  const [currentResponse, authenticatedUserResponse] = await Promise.all([
13726
13828
  octokit.rest.issues.get({
13727
13829
  owner: target.repository.owner,
@@ -13781,7 +13883,7 @@ function registerGitHubAgentTools(ctx) {
13781
13883
  async (params, runCtx) => executeGitHubTool(async () => {
13782
13884
  const input = getToolInputRecord(params);
13783
13885
  const target = await resolveGitHubIssueToolTarget(ctx, runCtx, input);
13784
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13886
+ const octokit = await createAgentToolOctokit(runCtx, "add_issue_comment", target.repository);
13785
13887
  const body = appendAiAuthorshipFooter(String(input.body ?? ""), "comment", normalizeOptionalToolString(input.llmModel));
13786
13888
  const response = await octokit.rest.issues.createComment({
13787
13889
  owner: target.repository.owner,
@@ -13831,7 +13933,7 @@ function registerGitHubAgentTools(ctx) {
13831
13933
  "pull request description",
13832
13934
  normalizeOptionalToolString(input.llmModel)
13833
13935
  ) : void 0;
13834
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
13936
+ const octokit = await createAgentToolOctokit(runCtx, "create_pull_request", repository);
13835
13937
  const response = await octokit.rest.pulls.create({
13836
13938
  owner: repository.owner,
13837
13939
  repo: repository.repo,
@@ -13907,7 +14009,7 @@ function registerGitHubAgentTools(ctx) {
13907
14009
  async (params, runCtx) => executeGitHubTool(async () => {
13908
14010
  const input = getToolInputRecord(params);
13909
14011
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
13910
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14012
+ const octokit = await createAgentToolOctokit(runCtx, "get_pull_request", target.repository);
13911
14013
  const response = await octokit.rest.pulls.get({
13912
14014
  owner: target.repository.owner,
13913
14015
  repo: target.repository.repo,
@@ -13955,7 +14057,7 @@ function registerGitHubAgentTools(ctx) {
13955
14057
  async (params, runCtx) => executeGitHubTool(async () => {
13956
14058
  const input = getToolInputRecord(params);
13957
14059
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
13958
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14060
+ const octokit = await createAgentToolOctokit(runCtx, "update_pull_request", target.repository);
13959
14061
  let currentResponse = await octokit.rest.pulls.get({
13960
14062
  owner: target.repository.owner,
13961
14063
  repo: target.repository.repo,
@@ -14021,7 +14123,7 @@ function registerGitHubAgentTools(ctx) {
14021
14123
  async (params, runCtx) => executeGitHubTool(async () => {
14022
14124
  const input = getToolInputRecord(params);
14023
14125
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
14024
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14126
+ const octokit = await createAgentToolOctokit(runCtx, "list_pull_request_files", target.repository);
14025
14127
  const files = await listAllPullRequestFiles(octokit, target.repository, target.pullRequestNumber);
14026
14128
  return buildToolSuccessResult(
14027
14129
  `Loaded ${files.length} changed ${files.length === 1 ? "file" : "files"} from pull request #${target.pullRequestNumber}.`,
@@ -14039,7 +14141,7 @@ function registerGitHubAgentTools(ctx) {
14039
14141
  async (params, runCtx) => executeGitHubTool(async () => {
14040
14142
  const input = getToolInputRecord(params);
14041
14143
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
14042
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14144
+ const octokit = await createAgentToolOctokit(runCtx, "get_pull_request_checks", target.repository);
14043
14145
  const pullRequestResponse = await octokit.rest.pulls.get({
14044
14146
  owner: target.repository.owner,
14045
14147
  repo: target.repository.repo,
@@ -14138,7 +14240,7 @@ function registerGitHubAgentTools(ctx) {
14138
14240
  async (params, runCtx) => executeGitHubTool(async () => {
14139
14241
  const input = getToolInputRecord(params);
14140
14242
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
14141
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14243
+ const octokit = await createAgentToolOctokit(runCtx, "list_pull_request_review_threads", target.repository);
14142
14244
  const threads = await listDetailedPullRequestReviewThreads(octokit, target.repository, target.pullRequestNumber);
14143
14245
  return buildToolSuccessResult(
14144
14246
  `Loaded ${threads.length} review ${threads.length === 1 ? "thread" : "threads"} from pull request #${target.pullRequestNumber}.`,
@@ -14160,7 +14262,7 @@ function registerGitHubAgentTools(ctx) {
14160
14262
  throw new Error("threadId is required.");
14161
14263
  }
14162
14264
  const body = appendAiAuthorshipFooter(String(input.body ?? ""), "comment", normalizeOptionalToolString(input.llmModel));
14163
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14265
+ const octokit = await createAgentToolOctokit(runCtx, "reply_to_review_thread");
14164
14266
  const response = await octokit.graphql(
14165
14267
  GITHUB_ADD_PULL_REQUEST_REVIEW_THREAD_REPLY_MUTATION,
14166
14268
  {
@@ -14195,7 +14297,7 @@ function registerGitHubAgentTools(ctx) {
14195
14297
  if (!threadId) {
14196
14298
  throw new Error("threadId is required.");
14197
14299
  }
14198
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14300
+ const octokit = await createAgentToolOctokit(runCtx, "resolve_review_thread");
14199
14301
  const response = await octokit.graphql(
14200
14302
  GITHUB_RESOLVE_REVIEW_THREAD_MUTATION,
14201
14303
  {
@@ -14226,7 +14328,7 @@ function registerGitHubAgentTools(ctx) {
14226
14328
  if (!threadId) {
14227
14329
  throw new Error("threadId is required.");
14228
14330
  }
14229
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14331
+ const octokit = await createAgentToolOctokit(runCtx, "unresolve_review_thread");
14230
14332
  const response = await octokit.graphql(
14231
14333
  GITHUB_UNRESOLVE_REVIEW_THREAD_MUTATION,
14232
14334
  {
@@ -14259,7 +14361,7 @@ function registerGitHubAgentTools(ctx) {
14259
14361
  if (userReviewers.length === 0 && teamReviewers.length === 0) {
14260
14362
  throw new Error("Provide at least one user reviewer or team reviewer.");
14261
14363
  }
14262
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14364
+ const octokit = await createAgentToolOctokit(runCtx, "request_pull_request_reviewers", target.repository);
14263
14365
  const response = await octokit.rest.pulls.requestReviewers({
14264
14366
  owner: target.repository.owner,
14265
14367
  repo: target.repository.repo,
@@ -14290,7 +14392,7 @@ function registerGitHubAgentTools(ctx) {
14290
14392
  if (!organization) {
14291
14393
  throw new Error("organization is required.");
14292
14394
  }
14293
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14395
+ const octokit = await createAgentToolOctokit(runCtx, "list_organization_projects");
14294
14396
  const projects = await listGitHubOrganizationProjects(octokit, organization, {
14295
14397
  includeClosed: input.includeClosed === true,
14296
14398
  query: normalizeOptionalToolString(input.query),
@@ -14311,7 +14413,7 @@ function registerGitHubAgentTools(ctx) {
14311
14413
  async (params, runCtx) => executeGitHubTool(async () => {
14312
14414
  const input = getToolInputRecord(params);
14313
14415
  const target = await resolveGitHubPullRequestToolTarget(ctx, runCtx, input);
14314
- const octokit = await createGitHubToolOctokit(ctx, runCtx.companyId);
14416
+ const octokit = await createAgentToolOctokit(runCtx, "add_pull_request_to_project", target.repository);
14315
14417
  const projectTarget = await resolveGitHubProjectToolTarget(octokit, input);
14316
14418
  const pullRequest = await getGitHubPullRequestProjectItems(
14317
14419
  octokit,
@@ -14380,6 +14482,7 @@ function shouldStartWorkerHost(moduleUrl, entry = process.argv[1]) {
14380
14482
  }
14381
14483
  var __testing = {
14382
14484
  buildSyncFallbackExecutionStatePatch,
14485
+ createGitHubToolOctokit,
14383
14486
  hasUnresolvedPaperclipIssueBlocker,
14384
14487
  isHealthyMaintainerWaitTransition,
14385
14488
  resolveSyncTransitionAssignee
@@ -14681,7 +14784,7 @@ var plugin = definePlugin({
14681
14784
  if (!trimmedToken) {
14682
14785
  throw new Error("Enter a GitHub token.");
14683
14786
  }
14684
- return validateGithubToken(trimmedToken);
14787
+ return validateGithubToken(ctx, trimmedToken);
14685
14788
  });
14686
14789
  ctx.actions.register("project.pullRequests.createIssue", async (input) => {
14687
14790
  const record = input && typeof input === "object" ? input : {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paperclip-github-plugin",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Paperclip plugin for synchronizing GitHub issues into Paperclip projects.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",