@rockhopper-co/mcp-server 2.1.82-staging.65cfbf4 → 2.1.84-staging.bac34fe

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.
Files changed (92) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/account-link-providers.d.ts +42 -0
  3. package/dist/account-link-providers.d.ts.map +1 -0
  4. package/dist/account-link-providers.js +47 -0
  5. package/dist/account-link-providers.js.map +1 -0
  6. package/dist/api-client.d.ts +16 -1
  7. package/dist/api-client.d.ts.map +1 -1
  8. package/dist/api-client.js +26 -1
  9. package/dist/api-client.js.map +1 -1
  10. package/dist/cell-history-unavailable.d.ts +7 -0
  11. package/dist/cell-history-unavailable.d.ts.map +1 -1
  12. package/dist/cell-history-unavailable.js +28 -0
  13. package/dist/cell-history-unavailable.js.map +1 -1
  14. package/dist/comment-location.d.ts +18 -0
  15. package/dist/comment-location.d.ts.map +1 -0
  16. package/dist/comment-location.js +29 -0
  17. package/dist/comment-location.js.map +1 -0
  18. package/dist/document-changes.d.ts +11 -1
  19. package/dist/document-changes.d.ts.map +1 -1
  20. package/dist/document-changes.js +1 -1
  21. package/dist/document-changes.js.map +1 -1
  22. package/dist/drive-search.d.ts +4 -3
  23. package/dist/drive-search.d.ts.map +1 -1
  24. package/dist/drive-search.js +7 -7
  25. package/dist/drive-search.js.map +1 -1
  26. package/dist/file-changes.d.ts +52 -0
  27. package/dist/file-changes.d.ts.map +1 -0
  28. package/dist/file-changes.js +82 -0
  29. package/dist/file-changes.js.map +1 -0
  30. package/dist/prompts/change-sections.d.ts +11 -0
  31. package/dist/prompts/change-sections.d.ts.map +1 -0
  32. package/dist/prompts/change-sections.js +47 -0
  33. package/dist/prompts/change-sections.js.map +1 -0
  34. package/dist/prompts/index.d.ts.map +1 -1
  35. package/dist/prompts/index.js +18 -34
  36. package/dist/prompts/index.js.map +1 -1
  37. package/dist/resources/changes.d.ts.map +1 -1
  38. package/dist/resources/changes.js +19 -10
  39. package/dist/resources/changes.js.map +1 -1
  40. package/dist/resources/orchestration-guide.md +1 -1
  41. package/dist/tools/{connect-microsoft.d.ts → account-link.d.ts} +9 -3
  42. package/dist/tools/account-link.d.ts.map +1 -0
  43. package/dist/tools/account-link.js +155 -0
  44. package/dist/tools/account-link.js.map +1 -0
  45. package/dist/tools/anchor-history-read.d.ts +25 -0
  46. package/dist/tools/anchor-history-read.d.ts.map +1 -0
  47. package/dist/tools/anchor-history-read.js +73 -0
  48. package/dist/tools/anchor-history-read.js.map +1 -0
  49. package/dist/tools/drive-search.contract.d.ts +7 -2
  50. package/dist/tools/drive-search.contract.d.ts.map +1 -1
  51. package/dist/tools/drive-search.contract.js +15 -7
  52. package/dist/tools/drive-search.contract.js.map +1 -1
  53. package/dist/tools/drive-search.d.ts.map +1 -1
  54. package/dist/tools/drive-search.js +16 -17
  55. package/dist/tools/drive-search.js.map +1 -1
  56. package/dist/tools/get-cell-history.d.ts +15 -0
  57. package/dist/tools/get-cell-history.d.ts.map +1 -1
  58. package/dist/tools/get-cell-history.js +67 -18
  59. package/dist/tools/get-cell-history.js.map +1 -1
  60. package/dist/tools/get-comments.d.ts.map +1 -1
  61. package/dist/tools/get-comments.js +2 -1
  62. package/dist/tools/get-comments.js.map +1 -1
  63. package/dist/tools/index.d.ts.map +1 -1
  64. package/dist/tools/index.js +5 -4
  65. package/dist/tools/index.js.map +1 -1
  66. package/dist/tools/list-unenrolled-files.d.ts.map +1 -1
  67. package/dist/tools/list-unenrolled-files.js +18 -178
  68. package/dist/tools/list-unenrolled-files.js.map +1 -1
  69. package/dist/tools/list-unenrolled-render.d.ts +4 -0
  70. package/dist/tools/list-unenrolled-render.d.ts.map +1 -0
  71. package/dist/tools/list-unenrolled-render.js +219 -0
  72. package/dist/tools/list-unenrolled-render.js.map +1 -0
  73. package/dist/tools/search.d.ts.map +1 -1
  74. package/dist/tools/search.js +27 -57
  75. package/dist/tools/search.js.map +1 -1
  76. package/dist/tools/write-comments.d.ts.map +1 -1
  77. package/dist/tools/write-comments.js +58 -2
  78. package/dist/tools/write-comments.js.map +1 -1
  79. package/dist/types.d.ts +79 -1
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/zod-schemas.d.ts +57 -0
  82. package/dist/zod-schemas.d.ts.map +1 -1
  83. package/dist/zod-schemas.js +24 -1
  84. package/dist/zod-schemas.js.map +1 -1
  85. package/package.json +1 -1
  86. package/dist/tools/connect-microsoft.d.ts.map +0 -1
  87. package/dist/tools/connect-microsoft.js +0 -149
  88. package/dist/tools/connect-microsoft.js.map +0 -1
  89. package/dist/tools/document-changes-read.d.ts +0 -28
  90. package/dist/tools/document-changes-read.d.ts.map +0 -1
  91. package/dist/tools/document-changes-read.js +0 -34
  92. package/dist/tools/document-changes-read.js.map +0 -1
@@ -0,0 +1,52 @@
1
+ import type { ApiClient } from './api-client.js';
2
+ import { type DocumentChangesUnavailableReason } from './document-changes.js';
3
+ import type { DocumentChangesResponse, EnrolledFile, PaginatedUnattributedResponse, UnattributedChange } from './types.js';
4
+ /**
5
+ * ENG-6431 — THE change read, returned as DATA, for every surface that reports
6
+ * a file's changes since its last saved version.
7
+ *
8
+ * ENG-5397 wrote this dispatch inline in `get_unattributed_changes`, and the
9
+ * `…/changes` resource and the `summarize-file-changes` / `file-overview`
10
+ * prompts kept calling the spreadsheet-only lane for every file type — so a
11
+ * `.docx`, `.pptx`, Google Doc or Google Slides file read `totalCount: 0` there
12
+ * by construction. Every surface now calls this one function and does only its
13
+ * own formatting.
14
+ *
15
+ * EVERY EXIT IS REAL ROWS OR A NAMED REFUSAL. A withheld document window is
16
+ * `unavailable`, never a served empty one — the backend's DTO says a client
17
+ * MUST render the two differently. Not-ready states still THROW
18
+ * (`ChangeHistoryNotReadyError`), exactly as before.
19
+ */
20
+ export type FileChangesRead = {
21
+ kind: 'spreadsheet';
22
+ file: EnrolledFile;
23
+ page: PaginatedUnattributedResponse;
24
+ } | {
25
+ kind: 'spreadsheet_sheet';
26
+ file: EnrolledFile;
27
+ sheetName: string;
28
+ changes: UnattributedChange[];
29
+ } | {
30
+ kind: 'document';
31
+ file: EnrolledFile;
32
+ response: DocumentChangesResponse;
33
+ } | {
34
+ kind: 'unavailable';
35
+ file: EnrolledFile;
36
+ fileMsId: string;
37
+ reason: DocumentChangesUnavailableReason;
38
+ declineReason: string | null;
39
+ };
40
+ export declare function readFileChanges(api: ApiClient, fileMsId: string, opts?: {
41
+ sheetName?: string;
42
+ cursor?: string;
43
+ }): Promise<FileChangesRead>;
44
+ /**
45
+ * The refusal as the text every surface shows. A tool returns it as an
46
+ * `isError` result; a prompt embeds it; a resource, which has no `isError`
47
+ * channel, throws it.
48
+ */
49
+ export declare function fileChangesUnavailableText(read: Extract<FileChangesRead, {
50
+ kind: 'unavailable';
51
+ }>): string;
52
+ //# sourceMappingURL=file-changes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-changes.d.ts","sourceRoot":"","sources":["../src/file-changes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAKjD,OAAO,EAGL,KAAK,gCAAgC,EACtC,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EACV,uBAAuB,EACvB,YAAY,EACZ,6BAA6B,EAC7B,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,6BAA6B,CAAA;CAAE,GAChF;IACE,IAAI,EAAE,mBAAmB,CAAC;IAC1B,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B,GACD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,EAAE,uBAAuB,CAAA;CAAE,GAC3E;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,gCAAgC,CAAC;IACzC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEN,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,eAAe,CAAC,CAsE1B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,GACtD,MAAM,CAOR"}
@@ -0,0 +1,82 @@
1
+ import { assertChangeHistoryComplete, assertEnrollmentComplete, } from './not-ready.js';
2
+ import { changeModelForFileType, documentChangesUnavailableToolResult, } from './document-changes.js';
3
+ import { assertSheetExists } from './sheet-catalogue.js';
4
+ export async function readFileChanges(api, fileMsId, opts = {}) {
5
+ const file = await api.getEnrolledFile(fileMsId);
6
+ const model = changeModelForFileType(file.fileType);
7
+ if (model === null) {
8
+ return {
9
+ kind: 'unavailable',
10
+ file,
11
+ fileMsId,
12
+ reason: 'unknown_file_type',
13
+ declineReason: null,
14
+ };
15
+ }
16
+ if (model !== 'spreadsheet') {
17
+ // A worksheet filter over a file with no worksheets. Refusing beats
18
+ // quietly dropping it: the caller would otherwise be handed the WHOLE
19
+ // file's changes believing they were one sheet's.
20
+ if (opts.sheetName) {
21
+ return {
22
+ kind: 'unavailable',
23
+ file,
24
+ fileMsId,
25
+ reason: 'sheet_filter_not_applicable',
26
+ declineReason: null,
27
+ };
28
+ }
29
+ // ENG-2824 — a file whose first read has not landed has no versions, and
30
+ // an empty window over it is a premature absence.
31
+ assertEnrollmentComplete(fileMsId, await api.getFileVersions(fileMsId));
32
+ const response = await api.getDocumentChanges(fileMsId);
33
+ if (response.declineReason !== null) {
34
+ return {
35
+ kind: 'unavailable',
36
+ file,
37
+ fileMsId,
38
+ reason: 'window_withheld',
39
+ declineReason: response.declineReason,
40
+ };
41
+ }
42
+ return { kind: 'document', file, response };
43
+ }
44
+ // Plan 02 ruling 5 (STRICT): gate BOTH spreadsheet modes. The commit-diff
45
+ // fold retracts and rewrites the uncommitted window, so a pending fold means
46
+ // this list is mid-rewrite in either shape.
47
+ await assertChangeHistoryComplete(api, fileMsId);
48
+ if (opts.sheetName) {
49
+ const changes = await api.getUnattributedChangesBySheet(fileMsId, opts.sheetName);
50
+ // ENG-2824 / ENG-4347 — only an empty answer is ambiguous, so only it pays
51
+ // for the version read and then the sheet-existence check, in that order.
52
+ if (changes.length === 0) {
53
+ assertEnrollmentComplete(fileMsId, await api.getFileVersions(fileMsId));
54
+ await assertSheetExists(api, file, opts.sheetName);
55
+ }
56
+ return { kind: 'spreadsheet_sheet', file, sheetName: opts.sheetName, changes };
57
+ }
58
+ // ENG-4346 — `totalCount` is a FILE total only when no cursor is passed.
59
+ // Pass `cursor` through only when the caller supplied the key (the tool
60
+ // does, possibly as undefined); the resource and prompts never page.
61
+ const page = 'cursor' in opts
62
+ ? await api.getUnattributedChangesPaginated(fileMsId, opts.cursor)
63
+ : await api.getUnattributedChangesPaginated(fileMsId);
64
+ if (page.changes.length === 0 && page.totalCount === 0) {
65
+ assertEnrollmentComplete(fileMsId, await api.getFileVersions(fileMsId));
66
+ }
67
+ return { kind: 'spreadsheet', file, page };
68
+ }
69
+ /**
70
+ * The refusal as the text every surface shows. A tool returns it as an
71
+ * `isError` result; a prompt embeds it; a resource, which has no `isError`
72
+ * channel, throws it.
73
+ */
74
+ export function fileChangesUnavailableText(read) {
75
+ return documentChangesUnavailableToolResult({
76
+ reason: read.reason,
77
+ fileMsId: read.fileMsId,
78
+ fileName: read.file.name,
79
+ declineReason: read.declineReason,
80
+ }).content[0].text;
81
+ }
82
+ //# sourceMappingURL=file-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-changes.js","sourceRoot":"","sources":["../src/file-changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { type FileChangesRead } from '../file-changes.js';
2
+ /**
3
+ * ENG-6431 — the prompts' own formatting of the shared change read. Documents
4
+ * reuse `formatDocumentChanges` (no second summariser); a refusal reuses the
5
+ * tool's refusal text, so a withheld window is NAMED and never rendered as 0.
6
+ */
7
+ /** The `## Unattributed Changes …` section of `summarize-file-changes`. */
8
+ export declare function changeSummarySection(read: FileChangesRead): string;
9
+ /** The single-line change count of `file-overview`. */
10
+ export declare function changeCountLine(read: FileChangesRead): string;
11
+ //# sourceMappingURL=change-sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-sections.d.ts","sourceRoot":"","sources":["../../src/prompts/change-sections.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AAEH,2EAA2E;AAC3E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAwBlE;AAED,uDAAuD;AACvD,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAc7D"}
@@ -0,0 +1,47 @@
1
+ import { formatDocumentChanges } from '../document-changes.js';
2
+ import { fileChangesUnavailableText, } from '../file-changes.js';
3
+ /**
4
+ * ENG-6431 — the prompts' own formatting of the shared change read. Documents
5
+ * reuse `formatDocumentChanges` (no second summariser); a refusal reuses the
6
+ * tool's refusal text, so a withheld window is NAMED and never rendered as 0.
7
+ */
8
+ /** The `## Unattributed Changes …` section of `summarize-file-changes`. */
9
+ export function changeSummarySection(read) {
10
+ switch (read.kind) {
11
+ case 'unavailable':
12
+ return `## Unattributed Changes: unavailable\n${fileChangesUnavailableText(read)}`;
13
+ case 'document':
14
+ return `## Unattributed Changes\n${formatDocumentChanges(read.response, read.file.name)}`;
15
+ case 'spreadsheet_sheet':
16
+ case 'spreadsheet': {
17
+ // KI-097 / ENG-4346 — the prompt reads the UNSCOPED first page, so
18
+ // `totalCount` is a file total; the preview uses up to 20 rows of it.
19
+ const rows = read.kind === 'spreadsheet' ? read.page.changes : read.changes;
20
+ const total = read.kind === 'spreadsheet' ? read.page.totalCount : rows.length;
21
+ const body = rows.length
22
+ ? rows
23
+ .slice(0, 20)
24
+ .map((c) => `- ${c.sheetName}!${c.cellAddress}: ${JSON.stringify(c.oldValue)} → ${JSON.stringify(c.newValue)}`)
25
+ .join('\n')
26
+ : 'None';
27
+ return `## Unattributed Changes (${total} total)\n${body}`;
28
+ }
29
+ }
30
+ }
31
+ /** The single-line change count of `file-overview`. */
32
+ export function changeCountLine(read) {
33
+ switch (read.kind) {
34
+ case 'unavailable':
35
+ return `## Unattributed Changes: unavailable\n${fileChangesUnavailableText(read)}`;
36
+ case 'document':
37
+ // A truncated window is a LOWER bound, and says so.
38
+ return read.response.truncated
39
+ ? `## Unattributed Changes: more than ${read.response.rows.length}`
40
+ : `## Unattributed Changes: ${read.response.rows.length}`;
41
+ case 'spreadsheet':
42
+ return `## Unattributed Changes: ${read.page.totalCount}`;
43
+ case 'spreadsheet_sheet':
44
+ return `## Unattributed Changes: ${read.changes.length}`;
45
+ }
46
+ }
47
+ //# sourceMappingURL=change-sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"change-sections.js","sourceRoot":"","sources":["../../src/prompts/change-sections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACL,0BAA0B,GAE3B,MAAM,oBAAoB,CAAC;AAE5B;;;;GAIG;AAEH,2EAA2E;AAC3E,MAAM,UAAU,oBAAoB,CAAC,IAAqB;IACxD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,yCAAyC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;QACrF,KAAK,UAAU;YACb,OAAO,4BAA4B,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5F,KAAK,mBAAmB,CAAC;QACzB,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,mEAAmE;YACnE,sEAAsE;YACtE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM;gBACtB,CAAC,CAAC,IAAI;qBACD,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;qBACZ,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CACrG;qBACA,IAAI,CAAC,IAAI,CAAC;gBACf,CAAC,CAAC,MAAM,CAAC;YACX,OAAO,4BAA4B,KAAK,YAAY,IAAI,EAAE,CAAC;QAC7D,CAAC;IACH,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,eAAe,CAAC,IAAqB;IACnD,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,yCAAyC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;QACrF,KAAK,UAAU;YACb,oDAAoD;YACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS;gBAC5B,CAAC,CAAC,sCAAsC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE;gBACnE,CAAC,CAAC,4BAA4B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC9D,KAAK,aAAa;YAChB,OAAO,4BAA4B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5D,KAAK,mBAAmB;YACtB,OAAO,4BAA4B,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IAC7D,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAMlD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CA2OvE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,CAmNvE"}
@@ -1,6 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { assertChangeHistoryComplete } from '../not-ready.js';
2
+ import { readFileChanges } from '../file-changes.js';
3
+ import { changeCountLine, changeSummarySection } from './change-sections.js';
3
4
  import { renderMentions } from '../mentions.js';
5
+ import { commentLocation } from '../comment-location.js';
4
6
  import { formatVersion } from '../version-format.js';
5
7
  import { displayUserName } from '../user-display-name.js';
6
8
  export function registerPrompts(server, api) {
@@ -12,30 +14,17 @@ export function registerPrompts(server, api) {
12
14
  }),
13
15
  }, async ({ fileMsId }) => {
14
16
  // Plan 02 ruling 5 (STRICT) — a prompt is the highest-risk surface: its
15
- // whole product is a model narrating these rows as fact. Refuse before
16
- // assembling anything; a prompt has no error channel but its own throw.
17
- await assertChangeHistoryComplete(api, fileMsId);
18
- const [file, versions, changesPage] = await Promise.all([
19
- api.getEnrolledFile(fileMsId),
20
- api.getFileVersions(fileMsId),
21
- // KI-097: switched to cursor-paginated route. Top-of-prompt summary
22
- // uses `totalCount` for the full file count; the per-cell preview
23
- // uses up to 20 rows from this first page (sufficient for a recap).
24
- // ENG-4346 - `totalCount` counts rows remaining from the cursor
25
- // onward, so it is a FILE total only on this unscoped read. Passing a
26
- // cursor here would make the "total" label below false.
27
- api.getUnattributedChangesPaginated(fileMsId),
28
- ]);
17
+ // whole product is a model narrating these rows as fact. The shared read
18
+ // refuses (throws) before anything is assembled; a prompt has no error
19
+ // channel but its own throw. ENG-6431 — it also routes a document to the
20
+ // document lane instead of the spreadsheet-only one that read 0.
21
+ const changes = await readFileChanges(api, fileMsId);
22
+ const file = changes.file;
23
+ const versions = await api.getFileVersions(fileMsId);
29
24
  const recentVersions = versions.slice(0, 5);
30
25
  const versionSummary = recentVersions
31
26
  .map((v) => `- ${formatVersion(v)}: ${v.description || 'No description'} (${v.createdAt})`)
32
27
  .join('\n');
33
- const changeSummary = changesPage.changes.length
34
- ? changesPage.changes
35
- .slice(0, 20)
36
- .map((c) => `- ${c.sheetName}!${c.cellAddress}: ${JSON.stringify(c.oldValue)} → ${JSON.stringify(c.newValue)}`)
37
- .join('\n')
38
- : 'None';
39
28
  return {
40
29
  messages: [
41
30
  {
@@ -44,7 +33,7 @@ export function registerPrompts(server, api) {
44
33
  type: 'text',
45
34
  text: `Summarize the recent activity on the file "${file.name}".\n\n` +
46
35
  `## Recent Versions (last ${recentVersions.length} of ${versions.length})\n${versionSummary}\n\n` +
47
- `## Unattributed Changes (${changesPage.totalCount} total)\n${changeSummary}\n\n` +
36
+ `${changeSummarySection(changes)}\n\n` +
48
37
  `Provide a concise summary of what has changed recently, who made changes, and any notable patterns.`,
49
38
  },
50
39
  },
@@ -107,7 +96,7 @@ export function registerPrompts(server, api) {
107
96
  ? unresolved
108
97
  .map((c) => {
109
98
  const author = c.authorName || c.authorEmail || 'Unknown';
110
- const cell = c.cellReference ? ` [${c.cellReference}]` : '';
99
+ const cell = commentLocation(c);
111
100
  const replyCount = c.replies?.length || 0;
112
101
  return (`- **${author}**${cell}: "${renderMentions(c.message)}" (${c.createdAt})` +
113
102
  (replyCount ? ` — ${replyCount} replies` : ''));
@@ -136,18 +125,13 @@ export function registerPrompts(server, api) {
136
125
  }),
137
126
  }, async ({ fileMsId }) => {
138
127
  // Plan 02 ruling 5 (STRICT) — this prompt reports a change COUNT, which
139
- // is the same factual claim in one number instead of many rows.
140
- await assertChangeHistoryComplete(api, fileMsId);
141
- const [file, versions, comments, changesPage] = await Promise.all([
142
- api.getEnrolledFile(fileMsId),
128
+ // is the same factual claim in one number instead of many rows, so the
129
+ // shared read refuses first. ENG-6431 — and routes by file type.
130
+ const changes = await readFileChanges(api, fileMsId);
131
+ const file = changes.file;
132
+ const [versions, comments] = await Promise.all([
143
133
  api.getFileVersions(fileMsId),
144
134
  api.getFileComments(fileMsId),
145
- // KI-097: switched to cursor-paginated route. The file-overview
146
- // prompt only displays a total count, so we use `totalCount` from
147
- // the first page — no need to fetch every row. ENG-4346 - that is
148
- // sound only because no cursor is passed: `totalCount` counts rows
149
- // remaining from the cursor onward, not rows in the file.
150
- api.getUnattributedChangesPaginated(fileMsId),
151
135
  ]);
152
136
  const latestVersion = versions[0];
153
137
  let reviews = [];
@@ -178,7 +162,7 @@ export function registerPrompts(server, api) {
178
162
  : 'No versions yet.\n') +
179
163
  `\n## Comments: ${comments.length} total, ${unresolvedComments.length} unresolved\n` +
180
164
  `## Reviews: ${reviews.length} total, ${pendingReviews.length} pending\n` +
181
- `## Unattributed Changes: ${changesPage.totalCount}\n\n` +
165
+ `${changeCountLine(changes)}\n\n` +
182
166
  `Provide a status report highlighting anything that needs attention.`,
183
167
  },
184
168
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAMlD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAmDN"}
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAGlD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAuDN"}
@@ -1,5 +1,5 @@
1
1
  import { ResourceTemplate } from '@modelcontextprotocol/server';
2
- import { assertChangeHistoryComplete, assertEnrollmentComplete, } from '../not-ready.js';
2
+ import { fileChangesUnavailableText, readFileChanges } from '../file-changes.js';
3
3
  export function registerChangeResources(server, api) {
4
4
  // KI-078 (ENG-1381): template only, no per-file expansion into resources/list.
5
5
  // Previously this enumerated only files with `hasUncommittedChanges === true` —
@@ -8,7 +8,9 @@ export function registerChangeResources(server, api) {
8
8
  list: undefined,
9
9
  }), {
10
10
  title: 'Unattributed Changes',
11
- description: 'Pending cell-level changes not yet attributed to a version for a file',
11
+ description: 'Changes since the last saved version: cell changes for a workbook ' +
12
+ '(the paginated envelope), paragraph or shape changes for a document ' +
13
+ 'or deck (the document-change window).',
12
14
  mimeType: 'application/json',
13
15
  }, async (uri, { fileMsId }) => {
14
16
  // KI-097: switched to cursor-paginated route. Resource returns the
@@ -21,20 +23,27 @@ export function registerChangeResources(server, api) {
21
23
  // so an incomplete window must THROW. The SDK renders that as a protocol
22
24
  // error, which is the only shape here that cannot be mistaken for an
23
25
  // empty change set.
24
- await assertChangeHistoryComplete(api, fileMsId);
25
- const page = await api.getUnattributedChangesPaginated(fileMsId);
26
- // ENG-2824 — the fold probe above cannot see a file that is still being
27
- // read for the first time (enrolment enqueues no fold), so an empty
28
- // envelope is checked against the version list before it is served.
29
- if (page.totalCount === 0) {
30
- assertEnrollmentComplete(fileMsId, await api.getFileVersions(fileMsId));
26
+ // ENG-2824 (enrolment) is enforced inside the shared read as well.
27
+ // ENG-6431 — the SAME dispatch `get_unattributed_changes` uses, so a
28
+ // document no longer reads the spreadsheet-only lane and serves
29
+ // `totalCount: 0`. A refusal (unknown type, withheld window) THROWS: a
30
+ // resource has no `isError` channel, and an empty body is the one shape
31
+ // that would be read as "nothing changed".
32
+ const read = await readFileChanges(api, fileMsId);
33
+ if (read.kind === 'unavailable') {
34
+ throw new Error(fileChangesUnavailableText(read));
31
35
  }
36
+ const body = read.kind === 'document'
37
+ ? read.response
38
+ : read.kind === 'spreadsheet'
39
+ ? read.page
40
+ : read.changes;
32
41
  return {
33
42
  contents: [
34
43
  {
35
44
  uri: uri.href,
36
45
  mimeType: 'application/json',
37
- text: JSON.stringify(page, null, 2),
46
+ text: JSON.stringify(body, null, 2),
38
47
  },
39
48
  ],
40
49
  };
@@ -1 +1 @@
1
- {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,GAAc;IAEd,+EAA+E;IAC/E,gFAAgF;IAChF,+DAA+D;IAC/D,MAAM,CAAC,gBAAgB,CACrB,sBAAsB,EACtB,IAAI,gBAAgB,CAAC,uCAAuC,EAAE;QAC5D,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,uEAAuE;QACzE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,mEAAmE;QACnE,uEAAuE;QACvE,8DAA8D;QAC9D,8DAA8D;QAC9D,iEAAiE;QACjE,gBAAgB;QAChB,wEAAwE;QACxE,yEAAyE;QACzE,qEAAqE;QACrE,oBAAoB;QACpB,MAAM,2BAA2B,CAAC,GAAG,EAAE,QAAkB,CAAC,CAAC;QAE3D,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,+BAA+B,CACpD,QAAkB,CACnB,CAAC;QACF,wEAAwE;QACxE,oEAAoE;QACpE,oEAAoE;QACpE,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YAC1B,wBAAwB,CACtB,QAAkB,EAClB,MAAM,GAAG,CAAC,eAAe,CAAC,QAAkB,CAAC,CAC9C,CAAC;QACJ,CAAC;QACD,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../../src/resources/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEjF,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,GAAc;IAEd,+EAA+E;IAC/E,gFAAgF;IAChF,+DAA+D;IAC/D,MAAM,CAAC,gBAAgB,CACrB,sBAAsB,EACtB,IAAI,gBAAgB,CAAC,uCAAuC,EAAE;QAC5D,IAAI,EAAE,SAAS;KAChB,CAAC,EACF;QACE,KAAK,EAAE,sBAAsB;QAC7B,WAAW,EACT,oEAAoE;YACpE,sEAAsE;YACtE,uCAAuC;QACzC,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC1B,mEAAmE;QACnE,uEAAuE;QACvE,8DAA8D;QAC9D,8DAA8D;QAC9D,iEAAiE;QACjE,gBAAgB;QAChB,wEAAwE;QACxE,yEAAyE;QACzE,qEAAqE;QACrE,oBAAoB;QACpB,mEAAmE;QACnE,qEAAqE;QACrE,gEAAgE;QAChE,uEAAuE;QACvE,wEAAwE;QACxE,2CAA2C;QAC3C,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,QAAkB,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,IAAI,GACR,IAAI,CAAC,IAAI,KAAK,UAAU;YACtB,CAAC,CAAC,IAAI,CAAC,QAAQ;YACf,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,aAAa;gBAC3B,CAAC,CAAC,IAAI,CAAC,IAAI;gBACX,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QACrB,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -197,7 +197,7 @@ If you need to know which cloud a file is in, inspect `fileType`, or read `provi
197
197
 
198
198
  **Adding a file differs by cloud, and it is the one place it matters.** A Microsoft file can be added by link or by the `driveMsId` + `msId` pair `search_drive_files` returns. A Google file is added **by link only** — there is no id pair to pass. `search_drive_files` returns the link for a confirmed Google candidate; hand it to `enroll_file` as `url`.
199
199
 
200
- `search_drive_files` takes a `provider` argument (`microsoft` or `google`). Each needs its own connected account. Ask the user which cloud their file is in rather than guessing: searching the wrong one returns an empty list that reads exactly like "no such file".
200
+ `search_drive_files` takes a `provider` argument (`microsoft` or `google`). Each needs its own connected account: `connect_microsoft` / `microsoft_link_status` / `disconnect_microsoft` for Microsoft, `connect_google` / `google_link_status` / `disconnect_google` for Google Drive. Ask the user which cloud their file is in rather than guessing: searching the wrong one returns an empty list that reads exactly like "no such file".
201
201
 
202
202
  ## 9. Error handling
203
203
 
@@ -1,6 +1,12 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/server';
2
- import type { ApiClient } from '../api-client.js';
2
+ import { type ApiClient } from '../api-client.js';
3
3
  /**
4
+ * The account-link tools — `connect_<provider>`, `<provider>_link_status` and
5
+ * `disconnect_<provider>` — registered ONCE per row of
6
+ * `ACCOUNT_LINK_PROVIDERS` (ENG-6414 widened this from Microsoft alone to
7
+ * Microsoft and Google). Everything below is written about Microsoft, where it
8
+ * started; every word of it holds for Google too.
9
+ *
4
10
  * `connect_microsoft` — the local half of SP07 §3.
5
11
  *
6
12
  * A REPAIR PATH, NOT A SETUP PATH, since ENG-2790. A user who signs in
@@ -28,5 +34,5 @@ import type { ApiClient } from '../api-client.js';
28
34
  * server-side when it redeems the code. Two independent places refuse to take
29
35
  * the caller's word for it.
30
36
  */
31
- export declare function registerConnectMicrosoftTool(server: McpServer, api: ApiClient): void;
32
- //# sourceMappingURL=connect-microsoft.d.ts.map
37
+ export declare function registerAccountLinkTools(server: McpServer, api: ApiClient): void;
38
+ //# sourceMappingURL=account-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-link.d.ts","sourceRoot":"","sources":["../../src/tools/account-link.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,SAAS,GACb,IAAI,CAIN"}
@@ -0,0 +1,155 @@
1
+ import { z } from 'zod';
2
+ import { RockhopperApiError } from '../api-client.js';
3
+ import { ACCOUNT_LINK_PROVIDERS, connectToolName, statusToolName, } from '../account-link-providers.js';
4
+ /**
5
+ * The account-link tools — `connect_<provider>`, `<provider>_link_status` and
6
+ * `disconnect_<provider>` — registered ONCE per row of
7
+ * `ACCOUNT_LINK_PROVIDERS` (ENG-6414 widened this from Microsoft alone to
8
+ * Microsoft and Google). Everything below is written about Microsoft, where it
9
+ * started; every word of it holds for Google too.
10
+ *
11
+ * `connect_microsoft` — the local half of SP07 §3.
12
+ *
13
+ * A REPAIR PATH, NOT A SETUP PATH, since ENG-2790. A user who signs in
14
+ * through `mcp.rockhopper.co` gets the delegated Graph grant in the same
15
+ * consent that signs them in, so this tool is no longer the way anyone
16
+ * normally arrives at a working link. It stays because the grant can end
17
+ * up missing for reasons sign-in cannot fix on its own — the user revoked
18
+ * it in Microsoft, the handover at sign-in failed, or the session is a
19
+ * local stdio one with a personal access token, which carries no Microsoft
20
+ * sign-in of its own and therefore still needs this.
21
+ *
22
+ * Deleting it would have left `disconnect_microsoft` as a one-way door.
23
+ *
24
+ * WHAT THIS TOOL DELIBERATELY CANNOT DO, and why the shape matters more than
25
+ * the feature. It takes NO authorize URL, no redirect URI, no client id and no
26
+ * scope list. It asks the backend to build the consent URL and relays what
27
+ * comes back.
28
+ *
29
+ * The reason is the threat this tool sits inside. An MCP tool's arguments are
30
+ * chosen by a language model, and that model reads content it did not author —
31
+ * file names, comments, review text. A tool that accepted a URL would let
32
+ * anything that model reads steer where a user's Microsoft consent is sent,
33
+ * and the user would see a real Microsoft consent screen the whole way. So the
34
+ * URL is not a parameter, and the callback re-pins the client id and redirect
35
+ * server-side when it redeems the code. Two independent places refuse to take
36
+ * the caller's word for it.
37
+ */
38
+ export function registerAccountLinkTools(server, api) {
39
+ for (const provider of ACCOUNT_LINK_PROVIDERS) {
40
+ registerProviderLinkTools(server, api, provider);
41
+ }
42
+ }
43
+ const failure = (text) => ({
44
+ content: [{ type: 'text', text }],
45
+ isError: true,
46
+ });
47
+ const errorText = (error) => error instanceof Error ? error.message : String(error);
48
+ function registerProviderLinkTools(server, api, p) {
49
+ const connectName = connectToolName(p);
50
+ const statusName = statusToolName(p);
51
+ server.registerTool(connectName, {
52
+ title: `Connect ${p.label} Account`,
53
+ description: `Start connecting the user's ${p.label} account so Rockhopper can ` +
54
+ `${p.purpose} as them. Returns a ${p.label} sign-in link the USER must ` +
55
+ `open themselves. Call \`${statusName}\` afterwards to confirm they ` +
56
+ `finished. Use this when a file search reports that no ${p.label} ` +
57
+ 'account is connected.',
58
+ inputSchema: z.object({}),
59
+ annotations: {
60
+ // Creates no Rockhopper data by itself — it hands back a link. The
61
+ // grant only exists once the USER completes the consent.
62
+ readOnlyHint: true,
63
+ // It sends the user to the provider.
64
+ openWorldHint: true,
65
+ },
66
+ }, async () => {
67
+ try {
68
+ const handoff = await p.begin(api);
69
+ return {
70
+ content: [
71
+ {
72
+ type: 'text',
73
+ text: `Open this link to connect your ${p.label} account:\n\n` +
74
+ `${handoff.authorizeUrl}\n\n` +
75
+ `The link expires at ${handoff.expiresAt}. ` +
76
+ (p.readOnlyConsent
77
+ ? 'Rockhopper asks only to READ your files. '
78
+ : '') +
79
+ `After you approve, run \`${statusName}\` to confirm.`,
80
+ },
81
+ ],
82
+ };
83
+ }
84
+ catch (error) {
85
+ return failure(`Failed to start the ${p.label} connection: ${errorText(error)}`);
86
+ }
87
+ });
88
+ server.registerTool(statusName, {
89
+ title: `${p.label} Connection Status`,
90
+ description: p.statusDescription,
91
+ inputSchema: z.object({}),
92
+ annotations: { readOnlyHint: true, openWorldHint: false },
93
+ }, async () => {
94
+ try {
95
+ const status = await p.status(api);
96
+ return {
97
+ content: [
98
+ {
99
+ type: 'text',
100
+ text: status.linked
101
+ ? `Connected${status.account ? ` as ${status.account}` : ''}.` +
102
+ (status.grantedScopes.length
103
+ ? ` Granted: ${status.grantedScopes.join(', ')}.`
104
+ : '') +
105
+ (status.linkedAt ? ` Connected on ${status.linkedAt}.` : '')
106
+ : `No ${p.label} account is connected. Run \`${connectName}\` to connect one.`,
107
+ },
108
+ ],
109
+ };
110
+ }
111
+ catch (error) {
112
+ return failure(`Failed to read the ${p.label} connection: ${errorText(error)}`);
113
+ }
114
+ });
115
+ server.registerTool(`disconnect_${p.key}`, {
116
+ title: `Disconnect ${p.label} Account`,
117
+ description: `Remove the stored ${p.label} connection, deleting the credential Rockhopper ` +
118
+ 'holds for this user. Requires an interactive login; a personal access token ' +
119
+ 'cannot sever a connection it did not create.',
120
+ inputSchema: z.object({}),
121
+ annotations: {
122
+ readOnlyHint: false,
123
+ destructiveHint: true,
124
+ idempotentHint: true,
125
+ openWorldHint: false,
126
+ },
127
+ }, async () => {
128
+ try {
129
+ const result = await p.unlink(api);
130
+ return {
131
+ content: [
132
+ {
133
+ type: 'text',
134
+ text: result.removed
135
+ ? `${p.label} account disconnected. The stored credential has been deleted.`
136
+ : `No ${p.label} account was connected.`,
137
+ },
138
+ ],
139
+ };
140
+ }
141
+ catch (error) {
142
+ // The backend refuses a disconnect from a personal access token or API
143
+ // key with a 403 (`requireInteractiveAuth`). Said plainly, so the
144
+ // model does not relay a raw HTTP body or report a success.
145
+ if (error instanceof RockhopperApiError && error.status === 403) {
146
+ return failure(`Nothing was disconnected. Rockhopper removes a ${p.label} ` +
147
+ 'connection only for someone signed in interactively, and this ' +
148
+ 'session uses a personal access token. Ask the user to ' +
149
+ `disconnect ${p.label} from Rockhopper in their browser.`);
150
+ }
151
+ return failure(`Failed to disconnect: ${errorText(error)}`);
152
+ }
153
+ });
154
+ }
155
+ //# sourceMappingURL=account-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-link.js","sourceRoot":"","sources":["../../src/tools/account-link.ts"],"names":[],"mappings":"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"}