linear-agent-bridge 0.1.2

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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +613 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +19 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/src/agent/context-builder.d.ts +9 -0
  8. package/dist/src/agent/context-builder.d.ts.map +1 -0
  9. package/dist/src/agent/context-builder.js +121 -0
  10. package/dist/src/agent/context-builder.js.map +1 -0
  11. package/dist/src/agent/plan-manager.d.ts +5 -0
  12. package/dist/src/agent/plan-manager.d.ts.map +1 -0
  13. package/dist/src/agent/plan-manager.js +11 -0
  14. package/dist/src/agent/plan-manager.js.map +1 -0
  15. package/dist/src/agent/response-tracker.d.ts +4 -0
  16. package/dist/src/agent/response-tracker.d.ts.map +1 -0
  17. package/dist/src/agent/response-tracker.js +11 -0
  18. package/dist/src/agent/response-tracker.js.map +1 -0
  19. package/dist/src/agent/session-token.d.ts +5 -0
  20. package/dist/src/agent/session-token.d.ts.map +1 -0
  21. package/dist/src/agent/session-token.js +15 -0
  22. package/dist/src/agent/session-token.js.map +1 -0
  23. package/dist/src/api/activity-ops.d.ts +2 -0
  24. package/dist/src/api/activity-ops.d.ts.map +1 -0
  25. package/dist/src/api/activity-ops.js +71 -0
  26. package/dist/src/api/activity-ops.js.map +1 -0
  27. package/dist/src/api/base-url.d.ts +3 -0
  28. package/dist/src/api/base-url.d.ts.map +1 -0
  29. package/dist/src/api/base-url.js +11 -0
  30. package/dist/src/api/base-url.js.map +1 -0
  31. package/dist/src/api/delegation-ops.d.ts +2 -0
  32. package/dist/src/api/delegation-ops.d.ts.map +1 -0
  33. package/dist/src/api/delegation-ops.js +51 -0
  34. package/dist/src/api/delegation-ops.js.map +1 -0
  35. package/dist/src/api/issue-ops.d.ts +2 -0
  36. package/dist/src/api/issue-ops.d.ts.map +1 -0
  37. package/dist/src/api/issue-ops.js +170 -0
  38. package/dist/src/api/issue-ops.js.map +1 -0
  39. package/dist/src/api/query-ops.d.ts +2 -0
  40. package/dist/src/api/query-ops.d.ts.map +1 -0
  41. package/dist/src/api/query-ops.js +77 -0
  42. package/dist/src/api/query-ops.js.map +1 -0
  43. package/dist/src/api/router.d.ts +12 -0
  44. package/dist/src/api/router.d.ts.map +1 -0
  45. package/dist/src/api/router.js +62 -0
  46. package/dist/src/api/router.js.map +1 -0
  47. package/dist/src/api/session-ops.d.ts +2 -0
  48. package/dist/src/api/session-ops.d.ts.map +1 -0
  49. package/dist/src/api/session-ops.js +96 -0
  50. package/dist/src/api/session-ops.js.map +1 -0
  51. package/dist/src/config.d.ts +3 -0
  52. package/dist/src/config.d.ts.map +1 -0
  53. package/dist/src/config.js +47 -0
  54. package/dist/src/config.js.map +1 -0
  55. package/dist/src/graphql/mutations.d.ts +9 -0
  56. package/dist/src/graphql/mutations.d.ts.map +1 -0
  57. package/dist/src/graphql/mutations.js +74 -0
  58. package/dist/src/graphql/mutations.js.map +1 -0
  59. package/dist/src/graphql/queries.d.ts +10 -0
  60. package/dist/src/graphql/queries.d.ts.map +1 -0
  61. package/dist/src/graphql/queries.js +121 -0
  62. package/dist/src/graphql/queries.js.map +1 -0
  63. package/dist/src/linear-client.d.ts +7 -0
  64. package/dist/src/linear-client.d.ts.map +1 -0
  65. package/dist/src/linear-client.js +72 -0
  66. package/dist/src/linear-client.js.map +1 -0
  67. package/dist/src/types.d.ts +85 -0
  68. package/dist/src/types.d.ts.map +1 -0
  69. package/dist/src/types.js +2 -0
  70. package/dist/src/types.js.map +1 -0
  71. package/dist/src/util.d.ts +13 -0
  72. package/dist/src/util.d.ts.map +1 -0
  73. package/dist/src/util.js +80 -0
  74. package/dist/src/util.js.map +1 -0
  75. package/dist/src/webhook/close-intent.d.ts +4 -0
  76. package/dist/src/webhook/close-intent.d.ts.map +1 -0
  77. package/dist/src/webhook/close-intent.js +37 -0
  78. package/dist/src/webhook/close-intent.js.map +1 -0
  79. package/dist/src/webhook/handler.d.ts +5 -0
  80. package/dist/src/webhook/handler.d.ts.map +1 -0
  81. package/dist/src/webhook/handler.js +441 -0
  82. package/dist/src/webhook/handler.js.map +1 -0
  83. package/dist/src/webhook/issue-policy.d.ts +7 -0
  84. package/dist/src/webhook/issue-policy.d.ts.map +1 -0
  85. package/dist/src/webhook/issue-policy.js +139 -0
  86. package/dist/src/webhook/issue-policy.js.map +1 -0
  87. package/dist/src/webhook/message-builder.d.ts +34 -0
  88. package/dist/src/webhook/message-builder.d.ts.map +1 -0
  89. package/dist/src/webhook/message-builder.js +144 -0
  90. package/dist/src/webhook/message-builder.js.map +1 -0
  91. package/dist/src/webhook/response-parser.d.ts +2 -0
  92. package/dist/src/webhook/response-parser.d.ts.map +1 -0
  93. package/dist/src/webhook/response-parser.js +51 -0
  94. package/dist/src/webhook/response-parser.js.map +1 -0
  95. package/dist/src/webhook/session-resolver.d.ts +6 -0
  96. package/dist/src/webhook/session-resolver.d.ts.map +1 -0
  97. package/dist/src/webhook/session-resolver.js +203 -0
  98. package/dist/src/webhook/session-resolver.js.map +1 -0
  99. package/dist/src/webhook/skip-filter.d.ts +4 -0
  100. package/dist/src/webhook/skip-filter.d.ts.map +1 -0
  101. package/dist/src/webhook/skip-filter.js +42 -0
  102. package/dist/src/webhook/skip-filter.js.map +1 -0
  103. package/dist/src/webhook/validation.d.ts +2 -0
  104. package/dist/src/webhook/validation.d.ts.map +1 -0
  105. package/dist/src/webhook/validation.js +11 -0
  106. package/dist/src/webhook/validation.js.map +1 -0
  107. package/openclaw.plugin.json +92 -0
  108. package/package.json +51 -0
@@ -0,0 +1,121 @@
1
+ import { buildMessage } from "../webhook/message-builder.js";
2
+ export function buildEnrichedMessage(params) {
3
+ const baseMessage = buildMessage(params);
4
+ const linearTools = `
5
+ ## Linear API — Available Operations
6
+
7
+ You can perform Linear operations by making HTTP POST requests during your execution.
8
+ All requests go to a single endpoint. Use the "action" field in the JSON body to select the operation.
9
+
10
+ **Endpoint:** POST ${params.apiBaseUrl}
11
+ **Authorization:** Bearer ${params.apiToken}
12
+ **Content-Type:** application/json
13
+
14
+ Every request body MUST include an "action" field. Example:
15
+ \`\`\`json
16
+ { "action": "query/viewer" }
17
+ \`\`\`
18
+
19
+ **Current context (used as defaults when fields are omitted):**
20
+ - Issue: ${params.id} (ID: ${params.issueId})
21
+ - Session: ${params.session}
22
+ - Team ID: ${params.teamId}
23
+
24
+ ---
25
+
26
+ ### Issue Management
27
+
28
+ **action: "issue/create"** — Create a new issue
29
+ { action: "issue/create", teamId?, title, description?, priority? (0-4), labelIds?: string[], assigneeId?, parentId?, stateId? }
30
+
31
+ **action: "issue/update"** — Update issue fields
32
+ { action: "issue/update", issueId?, title?, description?, stateId?, priority?, labelIds?, assigneeId?, delegateId? }
33
+
34
+ **action: "issue/close"** — Close an issue (moves to "completed" state)
35
+ { action: "issue/close", issueId? }
36
+
37
+ **action: "issue/create-sub-issue"** — Create a child issue under the current issue
38
+ { action: "issue/create-sub-issue", title, description?, priority?, labelIds?, assigneeId? }
39
+
40
+ **action: "issue/link"** — Link two issues together
41
+ { action: "issue/link", issueId?, relatedIssueId, type: "blocks" | "blocked_by" | "related" | "duplicate" }
42
+
43
+ ---
44
+
45
+ ### Communication — Agent Activities
46
+
47
+ Post activities to the Linear session to communicate with users.
48
+
49
+ **action: "activity/thought"** — Share your reasoning (shown as internal thought)
50
+ { action: "activity/thought", body: "markdown text", ephemeral?: boolean }
51
+
52
+ **action: "activity/action"** — Show a tool call or operation
53
+ { action: "activity/action", activityAction: "verb", parameter?: "subject", result?: "markdown result" }
54
+
55
+ **action: "activity/elicitation"** — Ask the user a question
56
+ { action: "activity/elicitation", body: "question", signal?: "select", signalMeta?: { options: [{ value: "..." }] } }
57
+ When using signal: "select", present options for the user to choose from.
58
+
59
+ **action: "activity/response"** — Post a final response (marks session as complete)
60
+ { action: "activity/response", body: "markdown text" }
61
+
62
+ **action: "activity/error"** — Report an error
63
+ { action: "activity/error", body: "error description" }
64
+
65
+ ---
66
+
67
+ ### Session Management
68
+
69
+ **action: "session/plan"** — Update session progress checklist
70
+ { action: "session/plan", plan: [{ content: "Step description", status: "pending" | "inProgress" | "completed" | "canceled" }] }
71
+ Note: replaces the entire plan each time. Include all steps.
72
+
73
+ **action: "session/create-on-issue"** — Proactively create a session on another issue
74
+ { action: "session/create-on-issue", issueId }
75
+
76
+ **action: "session/create-on-comment"** — Create session on a comment
77
+ { action: "session/create-on-comment", commentId }
78
+
79
+ **action: "session/external-url"** — Set an external URL on the session
80
+ { action: "session/external-url", url, label }
81
+
82
+ ---
83
+
84
+ ### Delegation
85
+
86
+ **action: "delegate/assign"** — Delegate issue to another agent or user
87
+ { action: "delegate/assign", issueId?, delegateId }
88
+
89
+ **action: "delegate/reassign"** — Change issue assignee
90
+ { action: "delegate/reassign", issueId?, assigneeId }
91
+
92
+ ---
93
+
94
+ ### Queries
95
+
96
+ **action: "query/issue"** — Get full issue details (labels, state, assignee, comments, relations, children)
97
+ { action: "query/issue", issueId? }
98
+
99
+ **action: "query/team"** — Get team info (workflow states, labels, members)
100
+ { action: "query/team", teamId? }
101
+
102
+ **action: "query/repo-suggestions"** — Get AI-ranked repository suggestions
103
+ { action: "query/repo-suggestions", issueId?, candidateRepositories: [{ hostname, repositoryFullName }] }
104
+
105
+ **action: "query/viewer"** — Get the current app identity
106
+ { action: "query/viewer" }
107
+
108
+ ---
109
+
110
+ ### Tips
111
+
112
+ - Use @mentions by including plain Linear URLs: https://linear.app/TEAM/profiles/USERNAME
113
+ - Reference issues via URLs: https://linear.app/TEAM/issue/IDENTIFIER — they render as mentions
114
+ - Post thoughts and actions to show progress during long-running tasks
115
+ - Update the session plan as you complete steps
116
+ - Use elicitation with the "select" signal to present options to the user
117
+ - Post a response activity when your work is complete
118
+ `;
119
+ return [baseMessage, linearTools].join("\n\n");
120
+ }
121
+ //# sourceMappingURL=context-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-builder.js","sourceRoot":"","sources":["../../../src/agent/context-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAsB,MAAM,+BAA+B,CAAC;AASjF,MAAM,UAAU,oBAAoB,CAAC,MAA6B;IAChE,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEzC,MAAM,WAAW,GAAG;;;;;;qBAMD,MAAM,CAAC,UAAU;4BACV,MAAM,CAAC,QAAQ;;;;;;;;;WAShC,MAAM,CAAC,EAAE,SAAS,MAAM,CAAC,OAAO;aAC9B,MAAM,CAAC,OAAO;aACd,MAAM,CAAC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGzB,CAAC;IAEA,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { PlanStep } from "../types.js";
2
+ export declare function getPlan(sessionId: string): PlanStep[];
3
+ export declare function setPlan(sessionId: string, plan: PlanStep[]): void;
4
+ export declare function cleanupSession(sessionId: string): void;
5
+ //# sourceMappingURL=plan-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-manager.d.ts","sourceRoot":"","sources":["../../../src/agent/plan-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAI5C,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAErD;AAED,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAEjE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,11 @@
1
+ const plansBySession = new Map();
2
+ export function getPlan(sessionId) {
3
+ return plansBySession.get(sessionId) ?? [];
4
+ }
5
+ export function setPlan(sessionId, plan) {
6
+ plansBySession.set(sessionId, plan);
7
+ }
8
+ export function cleanupSession(sessionId) {
9
+ plansBySession.delete(sessionId);
10
+ }
11
+ //# sourceMappingURL=plan-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-manager.js","sourceRoot":"","sources":["../../../src/agent/plan-manager.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsB,CAAC;AAErD,MAAM,UAAU,OAAO,CAAC,SAAiB;IACvC,OAAO,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,SAAiB,EAAE,IAAgB;IACzD,cAAc,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function markResponsePosted(sessionId: string): void;
2
+ export declare function hasPostedResponse(sessionId: string): boolean;
3
+ export declare function clearResponseFlag(sessionId: string): void;
4
+ //# sourceMappingURL=response-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-tracker.d.ts","sourceRoot":"","sources":["../../../src/agent/response-tracker.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5D;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAEzD"}
@@ -0,0 +1,11 @@
1
+ const posted = new Set();
2
+ export function markResponsePosted(sessionId) {
3
+ posted.add(sessionId);
4
+ }
5
+ export function hasPostedResponse(sessionId) {
6
+ return posted.has(sessionId);
7
+ }
8
+ export function clearResponseFlag(sessionId) {
9
+ posted.delete(sessionId);
10
+ }
11
+ //# sourceMappingURL=response-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-tracker.js","sourceRoot":"","sources":["../../../src/agent/response-tracker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;AAEjC,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { SessionContext } from "../types.js";
2
+ export declare function createSessionToken(context: SessionContext): string;
3
+ export declare function validateSessionToken(token: string): SessionContext | null;
4
+ export declare function revokeSessionToken(token: string): void;
5
+ //# sourceMappingURL=session-token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-token.d.ts","sourceRoot":"","sources":["../../../src/agent/session-token.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAKlE;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GACZ,cAAc,GAAG,IAAI,CAEvB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,15 @@
1
+ import { randomBytes } from "node:crypto";
2
+ const activeTokens = new Map();
3
+ export function createSessionToken(context) {
4
+ const token = randomBytes(32).toString("hex");
5
+ context.apiToken = token;
6
+ activeTokens.set(token, context);
7
+ return token;
8
+ }
9
+ export function validateSessionToken(token) {
10
+ return activeTokens.get(token) ?? null;
11
+ }
12
+ export function revokeSessionToken(token) {
13
+ activeTokens.delete(token);
14
+ }
15
+ //# sourceMappingURL=session-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-token.js","sourceRoot":"","sources":["../../../src/agent/session-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,YAAY,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEvD,MAAM,UAAU,kBAAkB,CAAC,OAAuB;IACxD,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,OAAO,CAAC,QAAQ,GAAG,KAAK,CAAC;IACzB,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAAa;IAEb,OAAO,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=activity-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-ops.d.ts","sourceRoot":"","sources":["../../../src/api/activity-ops.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { registerApiHandler } from "./router.js";
2
+ import { postActivity } from "../webhook/handler.js";
3
+ import { readString, sendJson } from "../util.js";
4
+ import { markResponsePosted } from "../agent/response-tracker.js";
5
+ // POST /activity/thought
6
+ registerApiHandler("/activity/thought", async ({ api, cfg, context, body, res }) => {
7
+ const text = readString(body.body);
8
+ if (!text) {
9
+ sendJson(res, 400, { ok: false, error: "body is required" });
10
+ return;
11
+ }
12
+ await postActivity(api, cfg, context.sessionId, { type: "thought", body: text }, { ephemeral: body.ephemeral === true });
13
+ sendJson(res, 200, { ok: true });
14
+ });
15
+ // POST /activity/action
16
+ registerApiHandler("/activity/action", async ({ api, cfg, context, body, res }) => {
17
+ const activityAction = readString(body.activityAction);
18
+ if (!activityAction) {
19
+ sendJson(res, 400, { ok: false, error: "activityAction is required" });
20
+ return;
21
+ }
22
+ await postActivity(api, cfg, context.sessionId, {
23
+ type: "action",
24
+ action: activityAction,
25
+ parameter: readString(body.parameter),
26
+ result: readString(body.result),
27
+ });
28
+ sendJson(res, 200, { ok: true });
29
+ });
30
+ // POST /activity/elicitation
31
+ registerApiHandler("/activity/elicitation", async ({ api, cfg, context, body, res }) => {
32
+ const text = readString(body.body);
33
+ if (!text) {
34
+ sendJson(res, 400, { ok: false, error: "body is required" });
35
+ return;
36
+ }
37
+ await postActivity(api, cfg, context.sessionId, { type: "elicitation", body: text }, {
38
+ signal: readString(body.signal),
39
+ signalMeta: body.signalMeta,
40
+ });
41
+ sendJson(res, 200, { ok: true });
42
+ });
43
+ // POST /activity/response
44
+ registerApiHandler("/activity/response", async ({ api, cfg, context, body, res }) => {
45
+ const text = readString(body.body);
46
+ if (!text) {
47
+ sendJson(res, 400, { ok: false, error: "body is required" });
48
+ return;
49
+ }
50
+ await postActivity(api, cfg, context.sessionId, {
51
+ type: "response",
52
+ body: text,
53
+ });
54
+ markResponsePosted(context.sessionId);
55
+ sendJson(res, 200, { ok: true });
56
+ });
57
+ // POST /activity/error
58
+ registerApiHandler("/activity/error", async ({ api, cfg, context, body, res }) => {
59
+ const text = readString(body.body);
60
+ if (!text) {
61
+ sendJson(res, 400, { ok: false, error: "body is required" });
62
+ return;
63
+ }
64
+ await postActivity(api, cfg, context.sessionId, {
65
+ type: "error",
66
+ body: text,
67
+ });
68
+ markResponsePosted(context.sessionId);
69
+ sendJson(res, 200, { ok: true });
70
+ });
71
+ //# sourceMappingURL=activity-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activity-ops.js","sourceRoot":"","sources":["../../../src/api/activity-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function captureBaseUrl(host: string): void;
2
+ export declare function getBaseUrl(): string;
3
+ //# sourceMappingURL=base-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-url.d.ts","sourceRoot":"","sources":["../../../src/api/base-url.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIjD;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -0,0 +1,11 @@
1
+ let detectedBaseUrl = "";
2
+ export function captureBaseUrl(host) {
3
+ if (detectedBaseUrl)
4
+ return;
5
+ const proto = host.endsWith(".ts.net") ? "https" : "https";
6
+ detectedBaseUrl = `${proto}://${host}/plugins/linear/api`;
7
+ }
8
+ export function getBaseUrl() {
9
+ return detectedBaseUrl;
10
+ }
11
+ //# sourceMappingURL=base-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-url.js","sourceRoot":"","sources":["../../../src/api/base-url.ts"],"names":[],"mappings":"AAAA,IAAI,eAAe,GAAG,EAAE,CAAC;AAEzB,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,IAAI,eAAe;QAAE,OAAO;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC3D,eAAe,GAAG,GAAG,KAAK,MAAM,IAAI,qBAAqB,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=delegation-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-ops.d.ts","sourceRoot":"","sources":["../../../src/api/delegation-ops.ts"],"names":[],"mappings":""}
@@ -0,0 +1,51 @@
1
+ import { registerApiHandler } from "./router.js";
2
+ import { callLinear } from "../linear-client.js";
3
+ import { ISSUE_UPDATE_MUTATION } from "../graphql/mutations.js";
4
+ import { readObject, readString, sendJson } from "../util.js";
5
+ // POST /delegate/assign
6
+ registerApiHandler("/delegate/assign", async ({ api, cfg, context, body, res }) => {
7
+ const issueId = readString(body.issueId) || context.issueId;
8
+ const delegateId = readString(body.delegateId);
9
+ if (!issueId) {
10
+ sendJson(res, 400, { ok: false, error: "issueId is required" });
11
+ return;
12
+ }
13
+ if (!delegateId) {
14
+ sendJson(res, 400, { ok: false, error: "delegateId is required" });
15
+ return;
16
+ }
17
+ const result = await callLinear(api, cfg, "issueUpdate(delegate)", {
18
+ query: ISSUE_UPDATE_MUTATION,
19
+ variables: { id: issueId, input: { delegateId } },
20
+ });
21
+ if (!result.ok) {
22
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
23
+ return;
24
+ }
25
+ const root = readObject(result.data.issueUpdate);
26
+ sendJson(res, 200, { ok: root?.success === true });
27
+ });
28
+ // POST /delegate/reassign
29
+ registerApiHandler("/delegate/reassign", async ({ api, cfg, context, body, res }) => {
30
+ const issueId = readString(body.issueId) || context.issueId;
31
+ const assigneeId = readString(body.assigneeId);
32
+ if (!issueId) {
33
+ sendJson(res, 400, { ok: false, error: "issueId is required" });
34
+ return;
35
+ }
36
+ if (!assigneeId) {
37
+ sendJson(res, 400, { ok: false, error: "assigneeId is required" });
38
+ return;
39
+ }
40
+ const result = await callLinear(api, cfg, "issueUpdate(assignee)", {
41
+ query: ISSUE_UPDATE_MUTATION,
42
+ variables: { id: issueId, input: { assigneeId } },
43
+ });
44
+ if (!result.ok) {
45
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
46
+ return;
47
+ }
48
+ const root = readObject(result.data.issueUpdate);
49
+ sendJson(res, 200, { ok: root?.success === true });
50
+ });
51
+ //# sourceMappingURL=delegation-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-ops.js","sourceRoot":"","sources":["../../../src/api/delegation-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=issue-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-ops.d.ts","sourceRoot":"","sources":["../../../src/api/issue-ops.ts"],"names":[],"mappings":""}
@@ -0,0 +1,170 @@
1
+ import { registerApiHandler } from "./router.js";
2
+ import { callLinear } from "../linear-client.js";
3
+ import { ISSUE_CREATE_MUTATION, ISSUE_UPDATE_MUTATION, ISSUE_RELATION_CREATE_MUTATION, } from "../graphql/mutations.js";
4
+ import { readObject, readString, sendJson } from "../util.js";
5
+ import { resolveCompletedState, resolveIssueInfo } from "../webhook/issue-policy.js";
6
+ // POST /issue/create
7
+ registerApiHandler("/issue/create", async ({ api, cfg, context, body, res }) => {
8
+ const input = {
9
+ teamId: readString(body.teamId) || context.teamId,
10
+ title: readString(body.title) ?? "",
11
+ };
12
+ if (body.description)
13
+ input.description = body.description;
14
+ if (typeof body.priority === "number")
15
+ input.priority = body.priority;
16
+ if (Array.isArray(body.labelIds))
17
+ input.labelIds = body.labelIds;
18
+ if (body.assigneeId)
19
+ input.assigneeId = body.assigneeId;
20
+ if (body.parentId)
21
+ input.parentId = body.parentId;
22
+ if (body.stateId)
23
+ input.stateId = body.stateId;
24
+ if (!input.title) {
25
+ sendJson(res, 400, { ok: false, error: "title is required" });
26
+ return;
27
+ }
28
+ const result = await callLinear(api, cfg, "issueCreate", {
29
+ query: ISSUE_CREATE_MUTATION,
30
+ variables: { input },
31
+ });
32
+ if (!result.ok) {
33
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
34
+ return;
35
+ }
36
+ const root = readObject(result.data.issueCreate);
37
+ sendJson(res, 200, { ok: root?.success === true, data: root });
38
+ });
39
+ // POST /issue/update
40
+ registerApiHandler("/issue/update", async ({ api, cfg, context, body, res }) => {
41
+ const issueId = readString(body.issueId) || context.issueId;
42
+ if (!issueId) {
43
+ sendJson(res, 400, { ok: false, error: "issueId is required" });
44
+ return;
45
+ }
46
+ const input = {};
47
+ if (body.title !== undefined)
48
+ input.title = body.title;
49
+ if (body.description !== undefined)
50
+ input.description = body.description;
51
+ if (body.stateId !== undefined)
52
+ input.stateId = body.stateId;
53
+ if (typeof body.priority === "number")
54
+ input.priority = body.priority;
55
+ if (Array.isArray(body.labelIds))
56
+ input.labelIds = body.labelIds;
57
+ if (body.assigneeId !== undefined)
58
+ input.assigneeId = body.assigneeId;
59
+ if (body.delegateId !== undefined)
60
+ input.delegateId = body.delegateId;
61
+ const result = await callLinear(api, cfg, "issueUpdate", {
62
+ query: ISSUE_UPDATE_MUTATION,
63
+ variables: { id: issueId, input },
64
+ });
65
+ if (!result.ok) {
66
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
67
+ return;
68
+ }
69
+ const root = readObject(result.data.issueUpdate);
70
+ sendJson(res, 200, { ok: root?.success === true, data: root });
71
+ });
72
+ // POST /issue/close
73
+ registerApiHandler("/issue/close", async ({ api, cfg, context, body, res }) => {
74
+ const issueId = readString(body.issueId) || context.issueId;
75
+ if (!issueId) {
76
+ sendJson(res, 400, { ok: false, error: "issueId is required" });
77
+ return;
78
+ }
79
+ const info = await resolveIssueInfo(api, cfg, issueId);
80
+ if (!info) {
81
+ sendJson(res, 404, { ok: false, error: "Issue not found" });
82
+ return;
83
+ }
84
+ if (info.stateType === "completed" || info.stateType === "canceled") {
85
+ sendJson(res, 200, { ok: true, alreadyClosed: true });
86
+ return;
87
+ }
88
+ if (!info.teamId) {
89
+ sendJson(res, 400, { ok: false, error: "Cannot determine team" });
90
+ return;
91
+ }
92
+ const stateId = await resolveCompletedState(api, cfg, info.teamId);
93
+ if (!stateId) {
94
+ sendJson(res, 400, { ok: false, error: "No completed state found" });
95
+ return;
96
+ }
97
+ const result = await callLinear(api, cfg, "issueUpdate(close)", {
98
+ query: ISSUE_UPDATE_MUTATION,
99
+ variables: { id: issueId, input: { stateId } },
100
+ });
101
+ if (!result.ok) {
102
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
103
+ return;
104
+ }
105
+ const root = readObject(result.data.issueUpdate);
106
+ sendJson(res, 200, { ok: root?.success === true });
107
+ });
108
+ // POST /issue/create-sub-issue
109
+ registerApiHandler("/issue/create-sub-issue", async ({ api, cfg, context, body, res }) => {
110
+ const parentId = readString(body.parentId) || context.issueId;
111
+ if (!parentId) {
112
+ sendJson(res, 400, { ok: false, error: "parentId is required" });
113
+ return;
114
+ }
115
+ const input = {
116
+ teamId: readString(body.teamId) || context.teamId,
117
+ title: readString(body.title) ?? "",
118
+ parentId,
119
+ };
120
+ if (body.description)
121
+ input.description = body.description;
122
+ if (typeof body.priority === "number")
123
+ input.priority = body.priority;
124
+ if (Array.isArray(body.labelIds))
125
+ input.labelIds = body.labelIds;
126
+ if (body.assigneeId)
127
+ input.assigneeId = body.assigneeId;
128
+ if (!input.title) {
129
+ sendJson(res, 400, { ok: false, error: "title is required" });
130
+ return;
131
+ }
132
+ const result = await callLinear(api, cfg, "issueCreate(sub)", {
133
+ query: ISSUE_CREATE_MUTATION,
134
+ variables: { input },
135
+ });
136
+ if (!result.ok) {
137
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
138
+ return;
139
+ }
140
+ const root = readObject(result.data.issueCreate);
141
+ sendJson(res, 200, { ok: root?.success === true, data: root });
142
+ });
143
+ // POST /issue/link
144
+ registerApiHandler("/issue/link", async ({ api, cfg, context, body, res }) => {
145
+ const issueId = readString(body.issueId) || context.issueId;
146
+ const relatedIssueId = readString(body.relatedIssueId);
147
+ const type = readString(body.type);
148
+ if (!issueId || !relatedIssueId) {
149
+ sendJson(res, 400, { ok: false, error: "issueId and relatedIssueId are required" });
150
+ return;
151
+ }
152
+ if (!type || !["blocks", "blocked_by", "related", "duplicate"].includes(type)) {
153
+ sendJson(res, 400, {
154
+ ok: false,
155
+ error: "type must be one of: blocks, blocked_by, related, duplicate",
156
+ });
157
+ return;
158
+ }
159
+ const result = await callLinear(api, cfg, "issueRelationCreate", {
160
+ query: ISSUE_RELATION_CREATE_MUTATION,
161
+ variables: { input: { issueId, relatedIssueId, type } },
162
+ });
163
+ if (!result.ok) {
164
+ sendJson(res, 502, { ok: false, error: "Linear API error" });
165
+ return;
166
+ }
167
+ const root = readObject(result.data.issueRelationCreate);
168
+ sendJson(res, 200, { ok: root?.success === true, data: root });
169
+ });
170
+ //# sourceMappingURL=issue-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-ops.js","sourceRoot":"","sources":["../../../src/api/issue-ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=query-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-ops.d.ts","sourceRoot":"","sources":["../../../src/api/query-ops.ts"],"names":[],"mappings":""}