@opentabs-dev/opentabs-plugin-linear 0.0.74

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 (100) hide show
  1. package/dist/adapter.iife.js +15582 -0
  2. package/dist/adapter.iife.js.map +7 -0
  3. package/dist/index.d.ts +14 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +60 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/linear-api.d.ts +4 -0
  8. package/dist/linear-api.d.ts.map +1 -0
  9. package/dist/linear-api.js +144 -0
  10. package/dist/linear-api.js.map +1 -0
  11. package/dist/tools/archive-issue.d.ts +7 -0
  12. package/dist/tools/archive-issue.d.ts.map +1 -0
  13. package/dist/tools/archive-issue.js +28 -0
  14. package/dist/tools/archive-issue.js.map +1 -0
  15. package/dist/tools/create-comment.d.ts +15 -0
  16. package/dist/tools/create-comment.d.ts.map +1 -0
  17. package/dist/tools/create-comment.js +34 -0
  18. package/dist/tools/create-comment.js.map +1 -0
  19. package/dist/tools/create-issue.d.ts +38 -0
  20. package/dist/tools/create-issue.d.ts.map +1 -0
  21. package/dist/tools/create-issue.js +77 -0
  22. package/dist/tools/create-issue.js.map +1 -0
  23. package/dist/tools/create-label.d.ts +17 -0
  24. package/dist/tools/create-label.d.ts.map +1 -0
  25. package/dist/tools/create-label.js +47 -0
  26. package/dist/tools/create-label.js.map +1 -0
  27. package/dist/tools/create-project.d.ts +22 -0
  28. package/dist/tools/create-project.d.ts.map +1 -0
  29. package/dist/tools/create-project.js +52 -0
  30. package/dist/tools/create-project.js.map +1 -0
  31. package/dist/tools/delete-issue.d.ts +7 -0
  32. package/dist/tools/delete-issue.d.ts.map +1 -0
  33. package/dist/tools/delete-issue.js +28 -0
  34. package/dist/tools/delete-issue.js.map +1 -0
  35. package/dist/tools/get-issue.d.ts +27 -0
  36. package/dist/tools/get-issue.d.ts.map +1 -0
  37. package/dist/tools/get-issue.js +59 -0
  38. package/dist/tools/get-issue.js.map +1 -0
  39. package/dist/tools/get-project.d.ts +18 -0
  40. package/dist/tools/get-project.d.ts.map +1 -0
  41. package/dist/tools/get-project.js +30 -0
  42. package/dist/tools/get-project.js.map +1 -0
  43. package/dist/tools/get-viewer.d.ts +14 -0
  44. package/dist/tools/get-viewer.d.ts.map +1 -0
  45. package/dist/tools/get-viewer.js +32 -0
  46. package/dist/tools/get-viewer.js.map +1 -0
  47. package/dist/tools/list-comments.d.ts +20 -0
  48. package/dist/tools/list-comments.d.ts.map +1 -0
  49. package/dist/tools/list-comments.js +46 -0
  50. package/dist/tools/list-comments.js.map +1 -0
  51. package/dist/tools/list-cycles.d.ts +21 -0
  52. package/dist/tools/list-cycles.d.ts.map +1 -0
  53. package/dist/tools/list-cycles.js +45 -0
  54. package/dist/tools/list-cycles.js.map +1 -0
  55. package/dist/tools/list-issue-relations.d.ts +16 -0
  56. package/dist/tools/list-issue-relations.d.ts.map +1 -0
  57. package/dist/tools/list-issue-relations.js +77 -0
  58. package/dist/tools/list-issue-relations.js.map +1 -0
  59. package/dist/tools/list-labels.d.ts +12 -0
  60. package/dist/tools/list-labels.d.ts.map +1 -0
  61. package/dist/tools/list-labels.js +30 -0
  62. package/dist/tools/list-labels.js.map +1 -0
  63. package/dist/tools/list-projects.d.ts +23 -0
  64. package/dist/tools/list-projects.d.ts.map +1 -0
  65. package/dist/tools/list-projects.js +45 -0
  66. package/dist/tools/list-projects.js.map +1 -0
  67. package/dist/tools/list-teams.d.ts +10 -0
  68. package/dist/tools/list-teams.d.ts.map +1 -0
  69. package/dist/tools/list-teams.js +29 -0
  70. package/dist/tools/list-teams.js.map +1 -0
  71. package/dist/tools/list-users.d.ts +19 -0
  72. package/dist/tools/list-users.d.ts.map +1 -0
  73. package/dist/tools/list-users.js +42 -0
  74. package/dist/tools/list-users.js.map +1 -0
  75. package/dist/tools/list-workflow-states.d.ts +13 -0
  76. package/dist/tools/list-workflow-states.d.ts.map +1 -0
  77. package/dist/tools/list-workflow-states.js +36 -0
  78. package/dist/tools/list-workflow-states.js.map +1 -0
  79. package/dist/tools/schemas.d.ts +269 -0
  80. package/dist/tools/schemas.d.ts.map +1 -0
  81. package/dist/tools/schemas.js +165 -0
  82. package/dist/tools/schemas.js.map +1 -0
  83. package/dist/tools/search-issues.d.ts +40 -0
  84. package/dist/tools/search-issues.d.ts.map +1 -0
  85. package/dist/tools/search-issues.js +95 -0
  86. package/dist/tools/search-issues.js.map +1 -0
  87. package/dist/tools/update-comment.d.ts +15 -0
  88. package/dist/tools/update-comment.d.ts.map +1 -0
  89. package/dist/tools/update-comment.js +36 -0
  90. package/dist/tools/update-comment.js.map +1 -0
  91. package/dist/tools/update-issue.d.ts +39 -0
  92. package/dist/tools/update-issue.d.ts.map +1 -0
  93. package/dist/tools/update-issue.js +76 -0
  94. package/dist/tools/update-issue.js.map +1 -0
  95. package/dist/tools/update-project.d.ts +23 -0
  96. package/dist/tools/update-project.d.ts.map +1 -0
  97. package/dist/tools/update-project.js +53 -0
  98. package/dist/tools/update-project.js.map +1 -0
  99. package/dist/tools.json +2064 -0
  100. package/package.json +55 -0
@@ -0,0 +1,14 @@
1
+ import { OpenTabsPlugin } from '@opentabs-dev/plugin-sdk';
2
+ import type { ToolDefinition } from '@opentabs-dev/plugin-sdk';
3
+ declare class LinearPlugin extends OpenTabsPlugin {
4
+ readonly name = "linear";
5
+ readonly description = "OpenTabs plugin for Linear";
6
+ readonly displayName = "Linear";
7
+ readonly urlPatterns: string[];
8
+ readonly homepage = "https://linear.app";
9
+ readonly tools: ToolDefinition[];
10
+ isReady(): Promise<boolean>;
11
+ }
12
+ declare const _default: LinearPlugin;
13
+ export default _default;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,cAAM,YAAa,SAAQ,cAAc;IACvC,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,WAAW,gCAAgC;IACpD,SAAkB,WAAW,YAAY;IACzC,QAAQ,CAAC,WAAW,WAAwB;IAC5C,SAAkB,QAAQ,wBAAwB;IAClD,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,CAsB9B;IAEI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAIlC;;AAED,wBAAkC"}
package/dist/index.js ADDED
@@ -0,0 +1,60 @@
1
+ import { isLinearAuthenticated, waitForLinearAuth } from './linear-api.js';
2
+ import { archiveIssue } from './tools/archive-issue.js';
3
+ import { createComment } from './tools/create-comment.js';
4
+ import { createIssue } from './tools/create-issue.js';
5
+ import { createLabel } from './tools/create-label.js';
6
+ import { createProject } from './tools/create-project.js';
7
+ import { deleteIssue } from './tools/delete-issue.js';
8
+ import { getIssue } from './tools/get-issue.js';
9
+ import { getProject } from './tools/get-project.js';
10
+ import { getViewer } from './tools/get-viewer.js';
11
+ import { listComments } from './tools/list-comments.js';
12
+ import { listCycles } from './tools/list-cycles.js';
13
+ import { listIssueRelations } from './tools/list-issue-relations.js';
14
+ import { listLabels } from './tools/list-labels.js';
15
+ import { listProjects } from './tools/list-projects.js';
16
+ import { listTeams } from './tools/list-teams.js';
17
+ import { listUsers } from './tools/list-users.js';
18
+ import { listWorkflowStates } from './tools/list-workflow-states.js';
19
+ import { searchIssues } from './tools/search-issues.js';
20
+ import { updateComment } from './tools/update-comment.js';
21
+ import { updateIssue } from './tools/update-issue.js';
22
+ import { updateProject } from './tools/update-project.js';
23
+ import { OpenTabsPlugin } from '@opentabs-dev/plugin-sdk';
24
+ class LinearPlugin extends OpenTabsPlugin {
25
+ name = 'linear';
26
+ description = 'OpenTabs plugin for Linear';
27
+ displayName = 'Linear';
28
+ urlPatterns = ['*://linear.app/*'];
29
+ homepage = 'https://linear.app';
30
+ tools = [
31
+ searchIssues,
32
+ getIssue,
33
+ createIssue,
34
+ updateIssue,
35
+ deleteIssue,
36
+ archiveIssue,
37
+ listIssueRelations,
38
+ createComment,
39
+ updateComment,
40
+ listComments,
41
+ listProjects,
42
+ getProject,
43
+ createProject,
44
+ updateProject,
45
+ listTeams,
46
+ listWorkflowStates,
47
+ listLabels,
48
+ createLabel,
49
+ getViewer,
50
+ listUsers,
51
+ listCycles,
52
+ ];
53
+ async isReady() {
54
+ if (isLinearAuthenticated())
55
+ return true;
56
+ return waitForLinearAuth();
57
+ }
58
+ }
59
+ export default new LinearPlugin();
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,MAAM,YAAa,SAAQ,cAAc;IAC9B,IAAI,GAAG,QAAQ,CAAC;IAChB,WAAW,GAAG,4BAA4B,CAAC;IAClC,WAAW,GAAG,QAAQ,CAAC;IAChC,WAAW,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC1B,QAAQ,GAAG,oBAAoB,CAAC;IACzC,KAAK,GAAqB;QACjC,YAAY;QACZ,QAAQ;QACR,WAAW;QACX,WAAW;QACX,WAAW;QACX,YAAY;QACZ,kBAAkB;QAClB,aAAa;QACb,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,UAAU;QACV,aAAa;QACb,aAAa;QACb,SAAS;QACT,kBAAkB;QAClB,UAAU;QACV,WAAW;QACX,SAAS;QACT,SAAS;QACT,UAAU;KACX,CAAC;IAEF,KAAK,CAAC,OAAO;QACX,IAAI,qBAAqB,EAAE;YAAE,OAAO,IAAI,CAAC;QACzC,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;CACF;AAED,eAAe,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const isLinearAuthenticated: () => boolean;
2
+ export declare const waitForLinearAuth: () => Promise<boolean>;
3
+ export declare const graphql: <T extends Record<string, unknown>>(query: string, variables?: Record<string, unknown>) => Promise<T>;
4
+ //# sourceMappingURL=linear-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-api.d.ts","sourceRoot":"","sources":["../src/linear-api.ts"],"names":[],"mappings":"AAoEA,eAAO,MAAM,qBAAqB,QAAO,OAA6B,CAAC;AAEvE,eAAO,MAAM,iBAAiB,QAAO,OAAO,CAAC,OAAO,CAIjD,CAAC;AASJ,eAAO,MAAM,OAAO,GAAU,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,MAAM,EACb,YAAY,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAClC,OAAO,CAAC,CAAC,CAoGX,CAAC"}
@@ -0,0 +1,144 @@
1
+ import { ToolError, clearAuthCache, getAuthCache, getCookie, getLocalStorage, parseRetryAfterMs, setAuthCache, waitUntil, } from '@opentabs-dev/plugin-sdk';
2
+ // Linear's GraphQL API is on a separate subdomain (client-api.linear.app) from
3
+ // the web app (linear.app). The CORS policy returns:
4
+ // access-control-allow-origin: https://linear.app
5
+ // access-control-allow-credentials: true
6
+ // This means in-page fetch() with credentials: 'include' sends the HttpOnly
7
+ // SameSite=Strict session cookies automatically. No fetchViaBackground needed.
8
+ const GRAPHQL_ENDPOINT = 'https://client-api.linear.app/graphql';
9
+ const getAuth = () => {
10
+ // Check persisted auth first (survives adapter re-injection)
11
+ const persisted = getAuthCache('linear');
12
+ if (persisted?.userAccountId && persisted?.userId)
13
+ return persisted;
14
+ // Check the non-HttpOnly 'loggedIn' indicator cookie
15
+ const loggedIn = getCookie('loggedIn');
16
+ if (loggedIn !== '1')
17
+ return null;
18
+ // Read user context from ApplicationStore in localStorage.
19
+ // The store contains: currentUserAccountId, currentUserId, and the user's
20
+ // organization ID nested under userAccounts[id].users[0].organization.id.
21
+ try {
22
+ const raw = getLocalStorage('ApplicationStore');
23
+ if (!raw)
24
+ return null;
25
+ const appStore = JSON.parse(raw);
26
+ const userAccountId = appStore.currentUserAccountId;
27
+ const userId = appStore.currentUserId;
28
+ if (!userAccountId || !userId)
29
+ return null;
30
+ // Resolve organization ID from the user account's first user entry
31
+ let organizationId = '';
32
+ const userAccounts = appStore.userAccounts;
33
+ if (userAccounts) {
34
+ const account = userAccounts[userAccountId];
35
+ const firstUser = account?.users?.[0];
36
+ organizationId = firstUser?.organization?.id ?? '';
37
+ }
38
+ // Read clientId for the linear-client-id header
39
+ const clientId = getLocalStorage('clientId') ?? '';
40
+ const auth = { userAccountId, userId, organizationId, clientId };
41
+ setAuthCache('linear', auth);
42
+ return auth;
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ };
48
+ export const isLinearAuthenticated = () => getAuth() !== null;
49
+ export const waitForLinearAuth = () => waitUntil(() => isLinearAuthenticated(), { interval: 500, timeout: 5000 }).then(() => true, () => false);
50
+ export const graphql = async (query, variables) => {
51
+ const auth = getAuth();
52
+ if (!auth)
53
+ throw ToolError.auth('Not authenticated — please log in to Linear.');
54
+ // Match the headers Linear's own web app sends to client-api.linear.app.
55
+ // The browser attaches HttpOnly session cookies via credentials: 'include'.
56
+ const headers = {
57
+ 'Content-Type': 'application/json',
58
+ useraccount: auth.userAccountId,
59
+ user: auth.userId,
60
+ };
61
+ if (auth.organizationId) {
62
+ headers.organization = auth.organizationId;
63
+ }
64
+ if (auth.clientId) {
65
+ headers['linear-client-id'] = auth.clientId;
66
+ }
67
+ let response;
68
+ try {
69
+ response = await fetch(GRAPHQL_ENDPOINT, {
70
+ method: 'POST',
71
+ headers,
72
+ body: JSON.stringify({ query, variables }),
73
+ credentials: 'include',
74
+ signal: AbortSignal.timeout(30_000),
75
+ });
76
+ }
77
+ catch (err) {
78
+ if (err instanceof DOMException && err.name === 'TimeoutError') {
79
+ throw ToolError.timeout('Linear API request timed out');
80
+ }
81
+ if (err instanceof DOMException && err.name === 'AbortError') {
82
+ throw new ToolError('Request was aborted', 'aborted');
83
+ }
84
+ throw new ToolError(`Network error: ${err instanceof Error ? err.message : String(err)}`, 'network_error', {
85
+ category: 'internal',
86
+ retryable: true,
87
+ });
88
+ }
89
+ // HTTP-level error classification
90
+ if (!response.ok) {
91
+ const errorBody = (await response.text().catch(() => '')).substring(0, 512);
92
+ if (response.status === 429) {
93
+ const retryAfter = response.headers.get('Retry-After');
94
+ const retryMs = retryAfter !== null ? parseRetryAfterMs(retryAfter) : undefined;
95
+ throw ToolError.rateLimited(`Rate limited — ${errorBody}`, retryMs);
96
+ }
97
+ if (response.status === 401 || response.status === 403) {
98
+ clearAuthCache('linear');
99
+ throw ToolError.auth(`Auth error (${response.status}): ${errorBody}`);
100
+ }
101
+ if (response.status === 404) {
102
+ throw ToolError.notFound(`Not found: ${errorBody}`);
103
+ }
104
+ throw ToolError.internal(`API error (${response.status}): ${errorBody}`);
105
+ }
106
+ let result;
107
+ try {
108
+ result = (await response.json());
109
+ }
110
+ catch {
111
+ throw ToolError.internal('Linear API returned non-JSON response');
112
+ }
113
+ // GraphQL-level error classification
114
+ if (result.errors && result.errors.length > 0) {
115
+ const firstError = result.errors[0];
116
+ if (!firstError)
117
+ throw ToolError.internal('Linear API returned unknown error');
118
+ const message = firstError.message;
119
+ const extensions = firstError.extensions ?? {};
120
+ const code = extensions.code;
121
+ const userPresentableMessage = extensions.userPresentableMessage;
122
+ const displayMessage = userPresentableMessage ?? message;
123
+ if (code === 'AUTHENTICATION_ERROR' || code === 'FORBIDDEN') {
124
+ clearAuthCache('linear');
125
+ throw ToolError.auth(displayMessage);
126
+ }
127
+ if (code === 'RATELIMITED') {
128
+ throw ToolError.rateLimited(displayMessage);
129
+ }
130
+ if (code === 'BAD_USER_INPUT' || code === 'GRAPHQL_VALIDATION_FAILED') {
131
+ throw ToolError.validation(displayMessage);
132
+ }
133
+ // Check message patterns for not-found
134
+ if (message.toLowerCase().includes('not found') || message.toLowerCase().includes('does not exist')) {
135
+ throw ToolError.notFound(displayMessage);
136
+ }
137
+ throw ToolError.internal(displayMessage);
138
+ }
139
+ if (!result.data) {
140
+ throw ToolError.internal('Linear API returned empty response');
141
+ }
142
+ return result.data;
143
+ };
144
+ //# sourceMappingURL=linear-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-api.js","sourceRoot":"","sources":["../src/linear-api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ export declare const archiveIssue: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ issue_id: z.ZodString;
4
+ }, z.core.$strip>, z.ZodObject<{
5
+ success: z.ZodBoolean;
6
+ }, z.core.$strip>>;
7
+ //# sourceMappingURL=archive-issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-issue.d.ts","sourceRoot":"","sources":["../../src/tools/archive-issue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,YAAY;;;;kBA6BvB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { graphql } from '../linear-api.js';
2
+ import { ToolError, defineTool } from '@opentabs-dev/plugin-sdk';
3
+ import { z } from 'zod';
4
+ export const archiveIssue = defineTool({
5
+ name: 'archive_issue',
6
+ displayName: 'Archive Issue',
7
+ description: 'Archive a Linear issue. Archived issues are hidden from default views but can be restored.',
8
+ summary: 'Archive an issue',
9
+ icon: 'archive',
10
+ group: 'Issues',
11
+ input: z.object({
12
+ issue_id: z.string().describe('Issue UUID to archive'),
13
+ }),
14
+ output: z.object({
15
+ success: z.boolean().describe('Whether the issue was successfully archived'),
16
+ }),
17
+ handle: async (params) => {
18
+ const data = await graphql(`mutation ArchiveIssue($id: String!) {
19
+ issueArchive(id: $id) {
20
+ success
21
+ }
22
+ }`, { id: params.issue_id });
23
+ if (!data.issueArchive)
24
+ throw ToolError.internal('Issue archive failed — no response');
25
+ return { success: data.issueArchive.success };
26
+ },
27
+ });
28
+ //# sourceMappingURL=archive-issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-issue.js","sourceRoot":"","sources":["../../src/tools/archive-issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;IACrC,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,eAAe;IAC5B,WAAW,EAAE,4FAA4F;IACzG,OAAO,EAAE,kBAAkB;IAC3B,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KACvD,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;KAC7E,CAAC;IACF,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,IAAI,GAAG,MAAM,OAAO,CAGxB;;;;QAIE,EACF,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,CACxB,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,YAAY;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,oCAAoC,CAAC,CAAC;QAEvF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;IAChD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ export declare const createComment: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ issue_id: z.ZodString;
4
+ body: z.ZodString;
5
+ }, z.core.$strip>, z.ZodObject<{
6
+ comment: z.ZodObject<{
7
+ id: z.ZodString;
8
+ body: z.ZodString;
9
+ user_name: z.ZodString;
10
+ created_at: z.ZodString;
11
+ updated_at: z.ZodString;
12
+ edited_at: z.ZodString;
13
+ }, z.core.$strip>;
14
+ }, z.core.$strip>>;
15
+ //# sourceMappingURL=create-comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-comment.d.ts","sourceRoot":"","sources":["../../src/tools/create-comment.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,aAAa;;;;;;;;;;;;kBAqCxB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { graphql } from '../linear-api.js';
2
+ import { ToolError, defineTool } from '@opentabs-dev/plugin-sdk';
3
+ import { z } from 'zod';
4
+ import { commentSchema, mapComment } from './schemas.js';
5
+ export const createComment = defineTool({
6
+ name: 'create_comment',
7
+ displayName: 'Create Comment',
8
+ description: 'Add a comment to an existing Linear issue.',
9
+ summary: 'Add a comment to an issue',
10
+ icon: 'message-square-plus',
11
+ group: 'Comments',
12
+ input: z.object({
13
+ issue_id: z.string().describe('Issue UUID to comment on'),
14
+ body: z.string().describe('Comment body in markdown'),
15
+ }),
16
+ output: z.object({
17
+ comment: commentSchema.describe('The newly created comment'),
18
+ }),
19
+ handle: async (params) => {
20
+ const data = await graphql(`mutation CreateComment($input: CommentCreateInput!) {
21
+ commentCreate(input: $input) {
22
+ success
23
+ comment {
24
+ id body createdAt updatedAt editedAt
25
+ user { name displayName }
26
+ }
27
+ }
28
+ }`, { input: { issueId: params.issue_id, body: params.body } });
29
+ if (!data.commentCreate?.comment)
30
+ throw ToolError.internal('Comment creation failed — no comment returned');
31
+ return { comment: mapComment(data.commentCreate.comment) };
32
+ },
33
+ });
34
+ //# sourceMappingURL=create-comment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-comment.js","sourceRoot":"","sources":["../../src/tools/create-comment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,CAAC;IACtC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EAAE,4CAA4C;IACzD,OAAO,EAAE,2BAA2B;IACpC,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,UAAU;IACjB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QACzD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;KACtD,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KAC7D,CAAC;IACF,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,IAAI,GAAG,MAAM,OAAO,CAMxB;;;;;;;;QAQE,EACF,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAC3D,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,+CAA+C,CAAC,CAAC;QAE5G,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,OAA2C,CAAC,EAAE,CAAC;IACjG,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { z } from 'zod';
2
+ export declare const createIssue: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ team_id: z.ZodString;
4
+ title: z.ZodString;
5
+ description: z.ZodOptional<z.ZodString>;
6
+ priority: z.ZodOptional<z.ZodNumber>;
7
+ assignee_id: z.ZodOptional<z.ZodString>;
8
+ state_id: z.ZodOptional<z.ZodString>;
9
+ label_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
10
+ project_id: z.ZodOptional<z.ZodString>;
11
+ cycle_id: z.ZodOptional<z.ZodString>;
12
+ due_date: z.ZodOptional<z.ZodString>;
13
+ estimate: z.ZodOptional<z.ZodNumber>;
14
+ parent_id: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>, z.ZodObject<{
16
+ issue: z.ZodObject<{
17
+ id: z.ZodString;
18
+ identifier: z.ZodString;
19
+ title: z.ZodString;
20
+ description: z.ZodString;
21
+ priority: z.ZodNumber;
22
+ priority_label: z.ZodString;
23
+ state_name: z.ZodString;
24
+ state_type: z.ZodString;
25
+ assignee_name: z.ZodString;
26
+ team_key: z.ZodString;
27
+ team_name: z.ZodString;
28
+ label_names: z.ZodArray<z.ZodString>;
29
+ project_name: z.ZodString;
30
+ cycle_number: z.ZodNumber;
31
+ due_date: z.ZodString;
32
+ estimate: z.ZodNumber;
33
+ url: z.ZodString;
34
+ created_at: z.ZodString;
35
+ updated_at: z.ZodString;
36
+ }, z.core.$strip>;
37
+ }, z.core.$strip>>;
38
+ //# sourceMappingURL=create-issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-issue.d.ts","sourceRoot":"","sources":["../../src/tools/create-issue.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAuEtB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { graphql } from '../linear-api.js';
2
+ import { ToolError, defineTool } from '@opentabs-dev/plugin-sdk';
3
+ import { z } from 'zod';
4
+ import { issueSchema, mapIssue } from './schemas.js';
5
+ export const createIssue = defineTool({
6
+ name: 'create_issue',
7
+ displayName: 'Create Issue',
8
+ description: 'Create a new issue in Linear. Requires a team ID and title at minimum.',
9
+ summary: 'Create a new issue in Linear',
10
+ icon: 'plus-circle',
11
+ group: 'Issues',
12
+ input: z.object({
13
+ team_id: z.string().describe('Team UUID to create the issue in (use list_teams to find team IDs)'),
14
+ title: z.string().describe('Issue title'),
15
+ description: z.string().optional().describe('Issue description in markdown'),
16
+ priority: z.number().optional().describe('Priority level (0=none, 1=urgent, 2=high, 3=medium, 4=low)'),
17
+ assignee_id: z.string().optional().describe('UUID of the user to assign (use list_users to find user IDs)'),
18
+ state_id: z.string().optional().describe('Workflow state UUID (use list_workflow_states to find state IDs)'),
19
+ label_ids: z
20
+ .array(z.string())
21
+ .optional()
22
+ .describe('Array of label UUIDs to apply (use list_labels to find label IDs)'),
23
+ project_id: z.string().optional().describe('Project UUID to add the issue to (use list_projects to find IDs)'),
24
+ cycle_id: z.string().optional().describe('Cycle UUID to add the issue to (use list_cycles to find IDs)'),
25
+ due_date: z.string().optional().describe('Due date in YYYY-MM-DD format'),
26
+ estimate: z.number().optional().describe('Estimate points'),
27
+ parent_id: z.string().optional().describe('Parent issue UUID for creating a sub-issue'),
28
+ }),
29
+ output: z.object({
30
+ issue: issueSchema.describe('The newly created issue'),
31
+ }),
32
+ handle: async (params) => {
33
+ const input = {
34
+ teamId: params.team_id,
35
+ title: params.title,
36
+ };
37
+ if (params.description !== undefined)
38
+ input.description = params.description;
39
+ if (params.priority !== undefined)
40
+ input.priority = params.priority;
41
+ if (params.assignee_id)
42
+ input.assigneeId = params.assignee_id;
43
+ if (params.state_id)
44
+ input.stateId = params.state_id;
45
+ if (params.label_ids)
46
+ input.labelIds = params.label_ids;
47
+ if (params.project_id)
48
+ input.projectId = params.project_id;
49
+ if (params.cycle_id)
50
+ input.cycleId = params.cycle_id;
51
+ if (params.due_date)
52
+ input.dueDate = params.due_date;
53
+ if (params.estimate !== undefined)
54
+ input.estimate = params.estimate;
55
+ if (params.parent_id)
56
+ input.parentId = params.parent_id;
57
+ const data = await graphql(`mutation CreateIssue($input: IssueCreateInput!) {
58
+ issueCreate(input: $input) {
59
+ success
60
+ issue {
61
+ id identifier title description priority priorityLabel url
62
+ createdAt updatedAt dueDate estimate
63
+ state { name type }
64
+ assignee { name displayName }
65
+ team { key name }
66
+ labels { nodes { name } }
67
+ project { name }
68
+ cycle { number }
69
+ }
70
+ }
71
+ }`, { input });
72
+ if (!data.issueCreate?.issue)
73
+ throw ToolError.internal('Issue creation failed — no issue returned');
74
+ return { issue: mapIssue(data.issueCreate.issue) };
75
+ },
76
+ });
77
+ //# sourceMappingURL=create-issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-issue.js","sourceRoot":"","sources":["../../src/tools/create-issue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export declare const createLabel: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ name: z.ZodString;
4
+ color: z.ZodOptional<z.ZodString>;
5
+ description: z.ZodOptional<z.ZodString>;
6
+ team_id: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strip>, z.ZodObject<{
8
+ label: z.ZodObject<{
9
+ id: z.ZodString;
10
+ name: z.ZodString;
11
+ color: z.ZodString;
12
+ description: z.ZodString;
13
+ is_group: z.ZodBoolean;
14
+ parent_name: z.ZodString;
15
+ }, z.core.$strip>;
16
+ }, z.core.$strip>>;
17
+ //# sourceMappingURL=create-label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-label.d.ts","sourceRoot":"","sources":["../../src/tools/create-label.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;kBA+CtB,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { graphql } from '../linear-api.js';
2
+ import { ToolError, defineTool } from '@opentabs-dev/plugin-sdk';
3
+ import { z } from 'zod';
4
+ import { labelSchema, mapLabel } from './schemas.js';
5
+ export const createLabel = defineTool({
6
+ name: 'create_label',
7
+ displayName: 'Create Label',
8
+ description: 'Create a new issue label in Linear.',
9
+ summary: 'Create a new label',
10
+ icon: 'tag',
11
+ group: 'Labels',
12
+ input: z.object({
13
+ name: z.string().describe('Label name'),
14
+ color: z.string().optional().describe('Label color as hex code (e.g. "#ff0000")'),
15
+ description: z.string().optional().describe('Label description'),
16
+ team_id: z.string().optional().describe('Team UUID to scope the label to a specific team'),
17
+ }),
18
+ output: z.object({
19
+ label: labelSchema.describe('The newly created label'),
20
+ }),
21
+ handle: async (params) => {
22
+ const input = {
23
+ name: params.name,
24
+ };
25
+ if (params.color)
26
+ input.color = params.color;
27
+ if (params.description !== undefined)
28
+ input.description = params.description;
29
+ if (params.team_id)
30
+ input.teamId = params.team_id;
31
+ const data = await graphql(`mutation CreateLabel($input: IssueLabelCreateInput!) {
32
+ issueLabelCreate(input: $input) {
33
+ success
34
+ issueLabel {
35
+ id name color description isGroup
36
+ parent { name }
37
+ }
38
+ }
39
+ }`, { input });
40
+ if (!data.issueLabelCreate?.success)
41
+ throw ToolError.internal('Label creation failed');
42
+ if (!data.issueLabelCreate.issueLabel)
43
+ throw ToolError.internal('Label creation failed — no label returned');
44
+ return { label: mapLabel(data.issueLabelCreate.issueLabel) };
45
+ },
46
+ });
47
+ //# sourceMappingURL=create-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-label.js","sourceRoot":"","sources":["../../src/tools/create-label.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAErD,MAAM,CAAC,MAAM,WAAW,GAAG,UAAU,CAAC;IACpC,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,cAAc;IAC3B,WAAW,EAAE,qCAAqC;IAClD,OAAO,EAAE,oBAAoB;IAC7B,IAAI,EAAE,KAAK;IACX,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QACjF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QAChE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;KAC3F,CAAC;IACF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KACvD,CAAC;IACF,MAAM,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACrB,MAAM,KAAK,GAA4B;YACrC,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,KAAK;YAAE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC7C,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS;YAAE,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAC7E,IAAI,MAAM,CAAC,OAAO;YAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;QAElD,MAAM,IAAI,GAAG,MAAM,OAAO,CAMxB;;;;;;;;QAQE,EACF,EAAE,KAAK,EAAE,CACV,CAAC;QAEF,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;QACvF,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAAU;YAAE,MAAM,SAAS,CAAC,QAAQ,CAAC,2CAA2C,CAAC,CAAC;QAE7G,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,UAA4C,CAAC,EAAE,CAAC;IACjG,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ export declare const createProject: import("@opentabs-dev/plugin-sdk").ToolDefinition<z.ZodObject<{
3
+ name: z.ZodString;
4
+ description: z.ZodOptional<z.ZodString>;
5
+ team_ids: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ state: z.ZodOptional<z.ZodString>;
7
+ target_date: z.ZodOptional<z.ZodString>;
8
+ }, z.core.$strip>, z.ZodObject<{
9
+ project: z.ZodObject<{
10
+ id: z.ZodString;
11
+ name: z.ZodString;
12
+ description: z.ZodString;
13
+ state: z.ZodString;
14
+ lead_name: z.ZodString;
15
+ target_date: z.ZodString;
16
+ start_date: z.ZodString;
17
+ url: z.ZodString;
18
+ created_at: z.ZodString;
19
+ updated_at: z.ZodString;
20
+ }, z.core.$strip>;
21
+ }, z.core.$strip>>;
22
+ //# sourceMappingURL=create-project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/tools/create-project.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;kBAmDxB,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { graphql } from '../linear-api.js';
2
+ import { ToolError, defineTool } from '@opentabs-dev/plugin-sdk';
3
+ import { z } from 'zod';
4
+ import { mapProject, projectSchema } from './schemas.js';
5
+ export const createProject = defineTool({
6
+ name: 'create_project',
7
+ displayName: 'Create Project',
8
+ description: 'Create a new project in Linear.',
9
+ summary: 'Create a new project',
10
+ icon: 'folder-plus',
11
+ group: 'Projects',
12
+ input: z.object({
13
+ name: z.string().describe('Project name'),
14
+ description: z.string().optional().describe('Project description'),
15
+ team_ids: z.array(z.string()).optional().describe('Array of team UUIDs to associate with the project'),
16
+ state: z.string().optional().describe('Project state (planned, started, paused, completed, canceled)'),
17
+ target_date: z.string().optional().describe('Target completion date in YYYY-MM-DD format'),
18
+ }),
19
+ output: z.object({
20
+ project: projectSchema.describe('The newly created project'),
21
+ }),
22
+ handle: async (params) => {
23
+ const input = {
24
+ name: params.name,
25
+ };
26
+ if (params.description !== undefined)
27
+ input.description = params.description;
28
+ if (params.team_ids)
29
+ input.teamIds = params.team_ids;
30
+ if (params.state)
31
+ input.state = params.state;
32
+ if (params.target_date)
33
+ input.targetDate = params.target_date;
34
+ const data = await graphql(`mutation CreateProject($input: ProjectCreateInput!) {
35
+ projectCreate(input: $input) {
36
+ success
37
+ project {
38
+ id name description url createdAt updatedAt
39
+ startDate targetDate
40
+ status { name }
41
+ lead { name displayName }
42
+ }
43
+ }
44
+ }`, { input });
45
+ if (!data.projectCreate?.success)
46
+ throw ToolError.internal('Project creation failed');
47
+ if (!data.projectCreate.project)
48
+ throw ToolError.internal('Project creation failed — no project returned');
49
+ return { project: mapProject(data.projectCreate.project) };
50
+ },
51
+ });
52
+ //# sourceMappingURL=create-project.js.map