@iloom/cli 0.3.4 → 0.4.0

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 (178) hide show
  1. package/README.md +13 -3
  2. package/dist/{BranchNamingService-A77VI6AI.js → BranchNamingService-TOM2KAUT.js} +4 -3
  3. package/dist/ClaudeContextManager-VEGJTS5E.js +16 -0
  4. package/dist/ClaudeService-ICSHJMQ5.js +15 -0
  5. package/dist/GitHubService-RPM27GWD.js +12 -0
  6. package/dist/{LoomLauncher-ZV3ZZIBA.js → LoomLauncher-SJBZFZXE.js} +25 -22
  7. package/dist/LoomLauncher-SJBZFZXE.js.map +1 -0
  8. package/dist/PromptTemplateManager-2TDZAUC6.js +9 -0
  9. package/dist/README.md +13 -3
  10. package/dist/{SettingsManager-I2LRCW2A.js → SettingsManager-FJFU6JJD.js} +7 -3
  11. package/dist/SettingsMigrationManager-EH3J2TCN.js +10 -0
  12. package/dist/{chunk-UJL4HI2R.js → chunk-3NFBZRPR.js} +2 -2
  13. package/dist/chunk-6UIGZD2N.js +20 -0
  14. package/dist/chunk-6UIGZD2N.js.map +1 -0
  15. package/dist/{chunk-RIEO2WML.js → chunk-74VMN2KC.js} +26 -2
  16. package/dist/chunk-74VMN2KC.js.map +1 -0
  17. package/dist/{chunk-OYF4VIFI.js → chunk-75B2HZZ5.js} +147 -22
  18. package/dist/chunk-75B2HZZ5.js.map +1 -0
  19. package/dist/{chunk-PGPI5LR4.js → chunk-ADDNFQJ4.js} +7 -21
  20. package/dist/chunk-ADDNFQJ4.js.map +1 -0
  21. package/dist/{chunk-AKUJXDNW.js → chunk-F4J6KEL6.js} +3 -3
  22. package/dist/{chunk-DLHA5VQ3.js → chunk-HD5SUKI2.js} +36 -179
  23. package/dist/chunk-HD5SUKI2.js.map +1 -0
  24. package/dist/chunk-HHDSIE72.js +667 -0
  25. package/dist/chunk-HHDSIE72.js.map +1 -0
  26. package/dist/{chunk-OXAM2WVC.js → chunk-HVGQP44L.js} +21 -1
  27. package/dist/chunk-HVGQP44L.js.map +1 -0
  28. package/dist/{chunk-RW54ZMBM.js → chunk-JJUPY5MM.js} +2 -2
  29. package/dist/{chunk-UAN4A3YU.js → chunk-KM3W7YQX.js} +11 -11
  30. package/dist/{chunk-3RUPPQRG.js → chunk-KO2FOMHL.js} +43 -2
  31. package/dist/{chunk-3RUPPQRG.js.map → chunk-KO2FOMHL.js.map} +1 -1
  32. package/dist/{chunk-2MAIX45J.js → chunk-LTNDJMTH.js} +104 -43
  33. package/dist/chunk-LTNDJMTH.js.map +1 -0
  34. package/dist/{chunk-2CXREBLZ.js → chunk-M5XUCTTJ.js} +8 -6
  35. package/dist/chunk-M5XUCTTJ.js.map +1 -0
  36. package/dist/{chunk-4XIDC3NF.js → chunk-MD6HA5IK.js} +2 -2
  37. package/dist/chunk-MLS5FAV7.js +189 -0
  38. package/dist/chunk-MLS5FAV7.js.map +1 -0
  39. package/dist/{chunk-2IJEMXOB.js → chunk-NFVFVYAP.js} +419 -427
  40. package/dist/chunk-NFVFVYAP.js.map +1 -0
  41. package/dist/{chunk-OC4H6HJD.js → chunk-O7WHXLCB.js} +2 -2
  42. package/dist/{chunk-M7JJCX53.js → chunk-OEGECBFS.js} +20 -20
  43. package/dist/chunk-OEGECBFS.js.map +1 -0
  44. package/dist/{chunk-MKWYLDFK.js → chunk-OF7BNW4D.js} +43 -3
  45. package/dist/chunk-OF7BNW4D.js.map +1 -0
  46. package/dist/{chunk-SUOXY5WJ.js → chunk-P2WZIDF3.js} +5 -5
  47. package/dist/chunk-P2WZIDF3.js.map +1 -0
  48. package/dist/{chunk-PA6Q6AWM.js → chunk-PSFVTBM7.js} +2 -2
  49. package/dist/chunk-QHA67Q7A.js +281 -0
  50. package/dist/chunk-QHA67Q7A.js.map +1 -0
  51. package/dist/{chunk-ZM3CFL5L.js → chunk-QRBOPFAA.js} +3 -3
  52. package/dist/{chunk-IFB4Z76W.js → chunk-S44CHE3G.js} +13 -12
  53. package/dist/chunk-S44CHE3G.js.map +1 -0
  54. package/dist/{chunk-CE26YH2U.js → chunk-SJ2GZ6RF.js} +48 -50
  55. package/dist/chunk-SJ2GZ6RF.js.map +1 -0
  56. package/dist/{chunk-SSCQCCJ7.js → chunk-THF25ICZ.js} +2 -2
  57. package/dist/{chunk-5Q3NDNNV.js → chunk-TR5MC2U6.js} +153 -6
  58. package/dist/chunk-TR5MC2U6.js.map +1 -0
  59. package/dist/{chunk-5VK4NRSF.js → chunk-UNXRACJ7.js} +35 -36
  60. package/dist/chunk-UNXRACJ7.js.map +1 -0
  61. package/dist/{chunk-GEHQXLEI.js → chunk-UYVWLISQ.js} +18 -35
  62. package/dist/chunk-UYVWLISQ.js.map +1 -0
  63. package/dist/{chunk-OSCLCMDG.js → chunk-UYWAESOT.js} +3 -3
  64. package/dist/{chunk-ZT3YZB4K.js → chunk-VBFDVGAE.js} +12 -12
  65. package/dist/chunk-VBFDVGAE.js.map +1 -0
  66. package/dist/{chunk-CDZERT7Z.js → chunk-VWNS6DH5.js} +48 -4
  67. package/dist/chunk-VWNS6DH5.js.map +1 -0
  68. package/dist/{chunk-CFFQ2Z7A.js → chunk-WUQQNE63.js} +2 -2
  69. package/dist/{claude-W52VKI6L.js → claude-X7EBJRB2.js} +8 -5
  70. package/dist/{cleanup-H4VXU3C3.js → cleanup-7QVPYBJJ.js} +133 -122
  71. package/dist/cleanup-7QVPYBJJ.js.map +1 -0
  72. package/dist/cli.js +901 -425
  73. package/dist/cli.js.map +1 -1
  74. package/dist/{color-F7RU6B6Z.js → color-ZPIIUADB.js} +3 -3
  75. package/dist/{contribute-Y7IQV5QY.js → contribute-RZYCYUDX.js} +8 -6
  76. package/dist/{contribute-Y7IQV5QY.js.map → contribute-RZYCYUDX.js.map} +1 -1
  77. package/dist/dev-server-LOY7YWCP.js +298 -0
  78. package/dist/dev-server-LOY7YWCP.js.map +1 -0
  79. package/dist/{feedback-XTUCKJNT.js → feedback-562KPG5U.js} +13 -12
  80. package/dist/{feedback-XTUCKJNT.js.map → feedback-562KPG5U.js.map} +1 -1
  81. package/dist/{git-IYA53VIC.js → git-OXJACVAU.js} +16 -4
  82. package/dist/hooks/iloom-hook.js +258 -0
  83. package/dist/{ignite-T74RYXCA.js → ignite-VSIPGKKG.js} +245 -39
  84. package/dist/ignite-VSIPGKKG.js.map +1 -0
  85. package/dist/index.d.ts +459 -124
  86. package/dist/index.js +740 -210
  87. package/dist/index.js.map +1 -1
  88. package/dist/init-SCR2LQ4A.js +21 -0
  89. package/dist/{installation-detector-VARGFFRZ.js → installation-detector-6R6YOFVZ.js} +3 -3
  90. package/dist/mcp/issue-management-server.js +2 -1
  91. package/dist/mcp/issue-management-server.js.map +1 -1
  92. package/dist/neon-helpers-L5CXQ5CT.js +11 -0
  93. package/dist/{open-UMXANW5S.js → open-CX7HUE26.js} +12 -10
  94. package/dist/{open-UMXANW5S.js.map → open-CX7HUE26.js.map} +1 -1
  95. package/dist/projects-6DTNDVLH.js +73 -0
  96. package/dist/projects-6DTNDVLH.js.map +1 -0
  97. package/dist/{prompt-QALMYTVC.js → prompt-A7GGRHSY.js} +3 -3
  98. package/dist/prompts/init-prompt.txt +49 -0
  99. package/dist/prompts/issue-prompt.txt +110 -8
  100. package/dist/prompts/regular-prompt.txt +90 -0
  101. package/dist/prompts/session-summary-prompt.txt +82 -0
  102. package/dist/{rebase-VJ2VKR6R.js → rebase-55URTXZC.js} +11 -9
  103. package/dist/{rebase-VJ2VKR6R.js.map → rebase-55URTXZC.js.map} +1 -1
  104. package/dist/{remote-VUNCQZ6J.js → remote-73TZ2ADI.js} +3 -3
  105. package/dist/{run-MJYY4PUT.js → run-DP2U2CA2.js} +12 -10
  106. package/dist/{run-MJYY4PUT.js.map → run-DP2U2CA2.js.map} +1 -1
  107. package/dist/schema/settings.schema.json +49 -0
  108. package/dist/summary-J3CJSM7L.js +244 -0
  109. package/dist/summary-J3CJSM7L.js.map +1 -0
  110. package/dist/{test-git-IT5EWQ5C.js → test-git-QLAIBJLX.js} +6 -4
  111. package/dist/{test-git-IT5EWQ5C.js.map → test-git-QLAIBJLX.js.map} +1 -1
  112. package/dist/{test-prefix-NPWDPUUH.js → test-prefix-6YM2ZOON.js} +6 -4
  113. package/dist/{test-prefix-NPWDPUUH.js.map → test-prefix-6YM2ZOON.js.map} +1 -1
  114. package/dist/{test-tabs-PRMRSHKI.js → test-tabs-JGO3VOXJ.js} +4 -4
  115. package/dist/{test-webserver-DAHONWCS.js → test-webserver-VPNLAFZ3.js} +2 -2
  116. package/dist/{update-4TDDUR5K.js → update-LETF5ASC.js} +4 -4
  117. package/dist/{update-notifier-QEX3CJHA.js → update-notifier-H55ZK7NU.js} +3 -3
  118. package/package.json +6 -6
  119. package/dist/ClaudeContextManager-BN7RE5ZQ.js +0 -15
  120. package/dist/ClaudeService-DLYLJUPA.js +0 -14
  121. package/dist/GitHubService-FZHHBOFG.js +0 -11
  122. package/dist/LoomLauncher-ZV3ZZIBA.js.map +0 -1
  123. package/dist/PromptTemplateManager-6HH3PVXV.js +0 -9
  124. package/dist/SettingsMigrationManager-TJ7UWZG5.js +0 -10
  125. package/dist/chunk-2CXREBLZ.js.map +0 -1
  126. package/dist/chunk-2IJEMXOB.js.map +0 -1
  127. package/dist/chunk-2MAIX45J.js.map +0 -1
  128. package/dist/chunk-5Q3NDNNV.js.map +0 -1
  129. package/dist/chunk-5VK4NRSF.js.map +0 -1
  130. package/dist/chunk-CDZERT7Z.js.map +0 -1
  131. package/dist/chunk-CE26YH2U.js.map +0 -1
  132. package/dist/chunk-DLHA5VQ3.js.map +0 -1
  133. package/dist/chunk-GEHQXLEI.js.map +0 -1
  134. package/dist/chunk-IFB4Z76W.js.map +0 -1
  135. package/dist/chunk-M7JJCX53.js.map +0 -1
  136. package/dist/chunk-MKWYLDFK.js.map +0 -1
  137. package/dist/chunk-OXAM2WVC.js.map +0 -1
  138. package/dist/chunk-OYF4VIFI.js.map +0 -1
  139. package/dist/chunk-PGPI5LR4.js.map +0 -1
  140. package/dist/chunk-RIEO2WML.js.map +0 -1
  141. package/dist/chunk-SUOXY5WJ.js.map +0 -1
  142. package/dist/chunk-ZT3YZB4K.js.map +0 -1
  143. package/dist/cleanup-H4VXU3C3.js.map +0 -1
  144. package/dist/ignite-T74RYXCA.js.map +0 -1
  145. package/dist/init-4FHTAM3F.js +0 -19
  146. package/dist/logger-MKYH4UDV.js +0 -12
  147. package/dist/neon-helpers-77PBPGJ5.js +0 -10
  148. package/dist/update-notifier-QEX3CJHA.js.map +0 -1
  149. /package/dist/{BranchNamingService-A77VI6AI.js.map → BranchNamingService-TOM2KAUT.js.map} +0 -0
  150. /package/dist/{ClaudeContextManager-BN7RE5ZQ.js.map → ClaudeContextManager-VEGJTS5E.js.map} +0 -0
  151. /package/dist/{ClaudeService-DLYLJUPA.js.map → ClaudeService-ICSHJMQ5.js.map} +0 -0
  152. /package/dist/{GitHubService-FZHHBOFG.js.map → GitHubService-RPM27GWD.js.map} +0 -0
  153. /package/dist/{PromptTemplateManager-6HH3PVXV.js.map → PromptTemplateManager-2TDZAUC6.js.map} +0 -0
  154. /package/dist/{SettingsManager-I2LRCW2A.js.map → SettingsManager-FJFU6JJD.js.map} +0 -0
  155. /package/dist/{SettingsMigrationManager-TJ7UWZG5.js.map → SettingsMigrationManager-EH3J2TCN.js.map} +0 -0
  156. /package/dist/{chunk-UJL4HI2R.js.map → chunk-3NFBZRPR.js.map} +0 -0
  157. /package/dist/{chunk-AKUJXDNW.js.map → chunk-F4J6KEL6.js.map} +0 -0
  158. /package/dist/{chunk-RW54ZMBM.js.map → chunk-JJUPY5MM.js.map} +0 -0
  159. /package/dist/{chunk-UAN4A3YU.js.map → chunk-KM3W7YQX.js.map} +0 -0
  160. /package/dist/{chunk-4XIDC3NF.js.map → chunk-MD6HA5IK.js.map} +0 -0
  161. /package/dist/{chunk-OC4H6HJD.js.map → chunk-O7WHXLCB.js.map} +0 -0
  162. /package/dist/{chunk-PA6Q6AWM.js.map → chunk-PSFVTBM7.js.map} +0 -0
  163. /package/dist/{chunk-ZM3CFL5L.js.map → chunk-QRBOPFAA.js.map} +0 -0
  164. /package/dist/{chunk-SSCQCCJ7.js.map → chunk-THF25ICZ.js.map} +0 -0
  165. /package/dist/{chunk-OSCLCMDG.js.map → chunk-UYWAESOT.js.map} +0 -0
  166. /package/dist/{chunk-CFFQ2Z7A.js.map → chunk-WUQQNE63.js.map} +0 -0
  167. /package/dist/{claude-W52VKI6L.js.map → claude-X7EBJRB2.js.map} +0 -0
  168. /package/dist/{color-F7RU6B6Z.js.map → color-ZPIIUADB.js.map} +0 -0
  169. /package/dist/{git-IYA53VIC.js.map → git-OXJACVAU.js.map} +0 -0
  170. /package/dist/{init-4FHTAM3F.js.map → init-SCR2LQ4A.js.map} +0 -0
  171. /package/dist/{installation-detector-VARGFFRZ.js.map → installation-detector-6R6YOFVZ.js.map} +0 -0
  172. /package/dist/{logger-MKYH4UDV.js.map → neon-helpers-L5CXQ5CT.js.map} +0 -0
  173. /package/dist/{neon-helpers-77PBPGJ5.js.map → prompt-A7GGRHSY.js.map} +0 -0
  174. /package/dist/{prompt-QALMYTVC.js.map → remote-73TZ2ADI.js.map} +0 -0
  175. /package/dist/{test-tabs-PRMRSHKI.js.map → test-tabs-JGO3VOXJ.js.map} +0 -0
  176. /package/dist/{test-webserver-DAHONWCS.js.map → test-webserver-VPNLAFZ3.js.map} +0 -0
  177. /package/dist/{update-4TDDUR5K.js.map → update-LETF5ASC.js.map} +0 -0
  178. /package/dist/{remote-VUNCQZ6J.js.map → update-notifier-H55ZK7NU.js.map} +0 -0
@@ -1,183 +1,25 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ LinearServiceError,
4
+ createLinearIssue,
5
+ fetchLinearIssue,
6
+ updateLinearIssueState
7
+ } from "./chunk-QHA67Q7A.js";
2
8
  import {
3
9
  GitHubService
4
- } from "./chunk-M7JJCX53.js";
10
+ } from "./chunk-OEGECBFS.js";
5
11
  import {
6
12
  getRepoInfo
7
- } from "./chunk-3RUPPQRG.js";
13
+ } from "./chunk-KO2FOMHL.js";
8
14
  import {
9
15
  promptConfirmation
10
- } from "./chunk-CE26YH2U.js";
16
+ } from "./chunk-SJ2GZ6RF.js";
17
+ import {
18
+ getLogger
19
+ } from "./chunk-6UIGZD2N.js";
11
20
  import {
12
21
  logger
13
- } from "./chunk-GEHQXLEI.js";
14
-
15
- // src/types/linear.ts
16
- var LinearServiceError = class _LinearServiceError extends Error {
17
- constructor(code, message, details) {
18
- super(message);
19
- this.code = code;
20
- this.details = details;
21
- this.name = "LinearServiceError";
22
- if (Error.captureStackTrace) {
23
- Error.captureStackTrace(this, _LinearServiceError);
24
- }
25
- }
26
- };
27
-
28
- // src/utils/linear.ts
29
- import { LinearClient } from "@linear/sdk";
30
- function slugifyTitle(title, maxLength = 50) {
31
- const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
32
- if (slug.length <= maxLength) {
33
- return slug;
34
- }
35
- const parts = slug.split("-");
36
- let result = "";
37
- for (const part of parts) {
38
- const candidate = result ? `${result}-${part}` : part;
39
- if (candidate.length > maxLength) {
40
- break;
41
- }
42
- result = candidate;
43
- }
44
- return result || slug.slice(0, maxLength);
45
- }
46
- function buildLinearIssueUrl(identifier, title) {
47
- const base = `https://linear.app/issue/${identifier}`;
48
- if (title) {
49
- const slug = slugifyTitle(title);
50
- return slug ? `${base}/${slug}` : base;
51
- }
52
- return base;
53
- }
54
- function getLinearApiToken() {
55
- const token = process.env.LINEAR_API_TOKEN;
56
- if (!token) {
57
- throw new LinearServiceError(
58
- "UNAUTHORIZED",
59
- "LINEAR_API_TOKEN not set. Configure in settings.local.json or set environment variable."
60
- );
61
- }
62
- return token;
63
- }
64
- function createLinearClient() {
65
- return new LinearClient({ apiKey: getLinearApiToken() });
66
- }
67
- function handleLinearError(error, context) {
68
- logger.debug(`${context}: Handling error`, { error });
69
- const errorMessage = error instanceof Error ? error.message : String(error);
70
- if (errorMessage.includes("not found") || errorMessage.includes("Not found")) {
71
- throw new LinearServiceError("NOT_FOUND", "Linear issue or resource not found", { error });
72
- }
73
- if (errorMessage.includes("unauthorized") || errorMessage.includes("Unauthorized") || errorMessage.includes("Invalid API key")) {
74
- throw new LinearServiceError(
75
- "UNAUTHORIZED",
76
- "Linear authentication failed. Check LINEAR_API_TOKEN.",
77
- { error }
78
- );
79
- }
80
- if (errorMessage.includes("rate limit")) {
81
- throw new LinearServiceError("RATE_LIMITED", "Linear API rate limit exceeded", { error });
82
- }
83
- throw new LinearServiceError("CLI_ERROR", `Linear SDK error: ${errorMessage}`, { error });
84
- }
85
- async function fetchLinearIssue(identifier) {
86
- try {
87
- logger.debug(`Fetching Linear issue: ${identifier}`);
88
- const client = createLinearClient();
89
- const issue = await client.issue(identifier);
90
- if (!issue) {
91
- throw new LinearServiceError("NOT_FOUND", `Linear issue ${identifier} not found`);
92
- }
93
- const result = {
94
- id: issue.id,
95
- identifier: issue.identifier,
96
- title: issue.title,
97
- url: issue.url,
98
- createdAt: issue.createdAt.toISOString(),
99
- updatedAt: issue.updatedAt.toISOString()
100
- };
101
- if (issue.description) {
102
- result.description = issue.description;
103
- }
104
- if (issue.state) {
105
- const state = await issue.state;
106
- if (state == null ? void 0 : state.name) {
107
- result.state = state.name;
108
- }
109
- }
110
- return result;
111
- } catch (error) {
112
- if (error instanceof LinearServiceError) {
113
- throw error;
114
- }
115
- handleLinearError(error, "fetchLinearIssue");
116
- }
117
- }
118
- async function createLinearIssue(title, body, teamKey, _labels) {
119
- try {
120
- logger.debug(`Creating Linear issue in team ${teamKey}: ${title}`);
121
- const client = createLinearClient();
122
- const teams = await client.teams();
123
- const team = teams.nodes.find((t) => t.key === teamKey);
124
- if (!team) {
125
- throw new LinearServiceError("NOT_FOUND", `Linear team ${teamKey} not found`);
126
- }
127
- const issueInput = {
128
- teamId: team.id,
129
- title
130
- };
131
- if (body) {
132
- issueInput.description = body;
133
- }
134
- const payload = await client.createIssue(issueInput);
135
- const issue = await payload.issue;
136
- if (!issue) {
137
- throw new LinearServiceError("CLI_ERROR", "Failed to create Linear issue");
138
- }
139
- const url = issue.url ?? buildLinearIssueUrl(issue.identifier, title);
140
- return {
141
- identifier: issue.identifier,
142
- url
143
- };
144
- } catch (error) {
145
- if (error instanceof LinearServiceError) {
146
- throw error;
147
- }
148
- handleLinearError(error, "createLinearIssue");
149
- }
150
- }
151
- async function updateLinearIssueState(identifier, stateName) {
152
- try {
153
- logger.debug(`Updating Linear issue ${identifier} state to: ${stateName}`);
154
- const client = createLinearClient();
155
- const issue = await client.issue(identifier);
156
- if (!issue) {
157
- throw new LinearServiceError("NOT_FOUND", `Linear issue ${identifier} not found`);
158
- }
159
- const team = await issue.team;
160
- if (!team) {
161
- throw new LinearServiceError("CLI_ERROR", "Issue has no team");
162
- }
163
- const states = await team.states();
164
- const state = states.nodes.find((s) => s.name === stateName);
165
- if (!state) {
166
- throw new LinearServiceError(
167
- "NOT_FOUND",
168
- `State "${stateName}" not found in team ${team.key}`
169
- );
170
- }
171
- await client.updateIssue(issue.id, {
172
- stateId: state.id
173
- });
174
- } catch (error) {
175
- if (error instanceof LinearServiceError) {
176
- throw error;
177
- }
178
- handleLinearError(error, "updateLinearIssueState");
179
- }
180
- }
22
+ } from "./chunk-UYVWLISQ.js";
181
23
 
182
24
  // src/lib/LinearService.ts
183
25
  var LinearService = class {
@@ -341,11 +183,11 @@ var IssueTrackerFactory = class {
341
183
  static create(settings) {
342
184
  var _a, _b;
343
185
  const provider = ((_a = settings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
344
- logger.debug(`IssueTrackerFactory: Creating tracker for provider "${provider}"`);
345
- logger.debug(`IssueTrackerFactory: issueManagement settings:`, JSON.stringify(settings.issueManagement, null, 2));
186
+ getLogger().debug(`IssueTrackerFactory: Creating tracker for provider "${provider}"`);
187
+ getLogger().debug(`IssueTrackerFactory: issueManagement settings:`, JSON.stringify(settings.issueManagement, null, 2));
346
188
  switch (provider) {
347
189
  case "github":
348
- logger.debug("IssueTrackerFactory: Creating GitHubService");
190
+ getLogger().debug("IssueTrackerFactory: Creating GitHubService");
349
191
  return new GitHubService();
350
192
  case "linear": {
351
193
  const linearSettings = (_b = settings.issueManagement) == null ? void 0 : _b.linear;
@@ -356,7 +198,7 @@ var IssueTrackerFactory = class {
356
198
  if (linearSettings == null ? void 0 : linearSettings.branchFormat) {
357
199
  linearConfig.branchFormat = linearSettings.branchFormat;
358
200
  }
359
- logger.debug(`IssueTrackerFactory: Creating LinearService with config:`, JSON.stringify(linearConfig, null, 2));
201
+ getLogger().debug(`IssueTrackerFactory: Creating LinearService with config:`, JSON.stringify(linearConfig, null, 2));
360
202
  return new LinearService(linearConfig);
361
203
  }
362
204
  default:
@@ -395,6 +237,18 @@ var FirstRunManager = class {
395
237
  getProjectsDir() {
396
238
  return path.join(this.configDir, "projects");
397
239
  }
240
+ /**
241
+ * Resolve symlinks in project path to get canonical path
242
+ * Falls back to original path on errors (broken symlinks, permissions, etc.)
243
+ */
244
+ async resolveProjectPath(projectPath) {
245
+ try {
246
+ return await fs.realpath(projectPath);
247
+ } catch {
248
+ logger.debug("resolveProjectPath: Failed to resolve symlink, using original path", { projectPath });
249
+ return projectPath;
250
+ }
251
+ }
398
252
  /**
399
253
  * Convert a project path to a readable filename
400
254
  * /Users/adam/Projects/my-app -> Users__adam__Projects__my-app
@@ -420,7 +274,8 @@ var FirstRunManager = class {
420
274
  * Returns true if project marker file exists
421
275
  */
422
276
  async isProjectConfigured(projectPath) {
423
- const resolvedPath = projectPath ?? process.cwd();
277
+ const inputPath = projectPath ?? process.cwd();
278
+ const resolvedPath = await this.resolveProjectPath(inputPath);
424
279
  const markerPath = this.getProjectMarkerPath(resolvedPath);
425
280
  logger.debug("isProjectConfigured: Checking for marker file", { markerPath });
426
281
  try {
@@ -469,7 +324,8 @@ var FirstRunManager = class {
469
324
  * This combined return avoids duplicate isProjectConfigured() calls in needsFirstRunSetup()
470
325
  */
471
326
  async fixupLegacyProject(projectPath) {
472
- const resolvedPath = projectPath ?? process.cwd();
327
+ const inputPath = projectPath ?? process.cwd();
328
+ const resolvedPath = await this.resolveProjectPath(inputPath);
473
329
  logger.debug("fixupLegacyProject: Checking for legacy project", { projectPath: resolvedPath });
474
330
  const hasMarker = await this.isProjectConfigured(resolvedPath);
475
331
  if (hasMarker) {
@@ -490,7 +346,8 @@ var FirstRunManager = class {
490
346
  * Creates a marker file with project metadata
491
347
  */
492
348
  async markProjectAsConfigured(projectPath) {
493
- const resolvedPath = projectPath ?? process.cwd();
349
+ const inputPath = projectPath ?? process.cwd();
350
+ const resolvedPath = await this.resolveProjectPath(inputPath);
494
351
  const markerPath = this.getProjectMarkerPath(resolvedPath);
495
352
  logger.debug("markProjectAsConfigured: Creating marker file", { markerPath });
496
353
  try {
@@ -610,4 +467,4 @@ export {
610
467
  FirstRunManager,
611
468
  generateIssueManagementMcpConfig
612
469
  };
613
- //# sourceMappingURL=chunk-DLHA5VQ3.js.map
470
+ //# sourceMappingURL=chunk-HD5SUKI2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/LinearService.ts","../src/lib/IssueTrackerFactory.ts","../src/utils/FirstRunManager.ts","../src/utils/mcp.ts"],"sourcesContent":["/**\n * LinearService - IssueTracker implementation for Linear\n * Implements issue tracking operations using the @linear/sdk\n */\n\nimport type { Issue, PullRequest, IssueTrackerInputDetection } from '../types/index.js'\nimport type { LinearIssue } from '../types/linear.js'\nimport { LinearServiceError } from '../types/linear.js'\nimport {\n fetchLinearIssue,\n createLinearIssue,\n updateLinearIssueState,\n} from '../utils/linear.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport type { IssueTracker } from './IssueTracker.js'\nimport { logger } from '../utils/logger.js'\n\n/**\n * Linear service configuration options\n */\nexport interface LinearServiceConfig {\n /** Linear team key (e.g., \"ENG\", \"PLAT\") */\n teamId?: string\n /** Branch naming template (e.g., \"feat/{{key}}__{{title}}\") */\n branchFormat?: string\n}\n\n/**\n * Linear implementation of IssueTracker interface\n */\nexport class LinearService implements IssueTracker {\n // IssueTracker interface implementation\n readonly providerName = 'linear'\n readonly supportsPullRequests = false // Linear doesn't have pull requests\n\n private config: LinearServiceConfig\n private prompter: (message: string) => Promise<boolean>\n\n constructor(\n config?: LinearServiceConfig,\n options?: { prompter?: (message: string) => Promise<boolean> },\n ) {\n this.config = config ?? {}\n this.prompter = options?.prompter ?? promptConfirmation\n }\n\n /**\n * Detect if input matches Linear identifier format (TEAM-NUMBER)\n * @param input - User input string\n * @param _repo - Repository (unused for Linear)\n * @returns Detection result with type and identifier\n */\n public async detectInputType(\n input: string,\n _repo?: string,\n ): Promise<IssueTrackerInputDetection> {\n logger.debug(`LinearService.detectInputType called with input: \"${input}\"`)\n\n // Pattern: TEAM-NUMBER (e.g., ENG-123, PLAT-456)\n // Requires at least 2 letters before dash to avoid conflict with PR-123 format\n const linearPattern = /^([A-Z]{2,}-\\d+)$/i\n const match = input.match(linearPattern)\n\n if (!match?.[1]) {\n logger.debug(`LinearService: Input \"${input}\" does not match Linear pattern`)\n return { type: 'unknown', identifier: null, rawInput: input }\n }\n\n const identifier = match[1].toUpperCase()\n logger.debug(`LinearService: Matched Linear identifier: ${identifier}`)\n\n // Validate the issue exists in Linear\n logger.debug(`LinearService: Checking if ${identifier} is a valid Linear issue via SDK`)\n const issue = await this.isValidIssue(identifier)\n\n if (issue) {\n logger.debug(`LinearService: Issue ${identifier} found: \"${issue.title}\"`)\n return { type: 'issue', identifier, rawInput: input }\n }\n\n // Not found\n logger.debug(`LinearService: Issue ${identifier} NOT found by SDK`)\n return { type: 'unknown', identifier: null, rawInput: input }\n }\n\n /**\n * Fetch a Linear issue by identifier\n * @param identifier - Linear issue identifier (string or number)\n * @param _repo - Repository (unused for Linear)\n * @returns Generic Issue type\n * @throws LinearServiceError if issue not found\n */\n public async fetchIssue(identifier: string | number, _repo?: string): Promise<Issue> {\n const linearIssue = await fetchLinearIssue(String(identifier))\n return this.mapLinearIssueToIssue(linearIssue)\n }\n\n /**\n * Check if an issue identifier is valid (silent validation)\n * @param identifier - Linear issue identifier\n * @param _repo - Repository (unused for Linear)\n * @returns Issue if valid, false if not found\n */\n public async isValidIssue(identifier: string | number, _repo?: string): Promise<Issue | false> {\n try {\n return await this.fetchIssue(identifier)\n } catch (error) {\n // Return false for NOT_FOUND errors (expected during detection)\n if (error instanceof LinearServiceError && error.code === 'NOT_FOUND') {\n return false\n }\n // Re-throw unexpected errors\n throw error\n }\n }\n\n /**\n * Validate issue state and prompt user if closed\n * @param issue - Issue to validate\n * @throws LinearServiceError if user cancels due to closed issue\n */\n public async validateIssueState(issue: Issue): Promise<void> {\n if (issue.state === 'closed') {\n const shouldContinue = await this.prompter(\n `Issue ${issue.number} is closed. Continue anyway?`,\n )\n\n if (!shouldContinue) {\n throw new LinearServiceError('INVALID_STATE', 'User cancelled due to closed issue')\n }\n }\n }\n\n /**\n * Create a new Linear issue\n * @param title - Issue title\n * @param body - Issue description (markdown)\n * @param _repository - Repository (unused for Linear)\n * @param labels - Optional label names\n * @returns Created issue identifier and URL\n * @throws LinearServiceError if teamId not configured or creation fails\n */\n public async createIssue(\n title: string,\n body: string,\n _repository?: string,\n labels?: string[],\n ): Promise<{ number: string | number; url: string }> {\n // Require teamId configuration\n if (!this.config.teamId) {\n throw new LinearServiceError(\n 'INVALID_STATE',\n 'Linear teamId not configured. Run `il init` to configure Linear settings.',\n )\n }\n\n logger.info(`Creating Linear issue in team ${this.config.teamId}: ${title}`)\n\n const result = await createLinearIssue(title, body, this.config.teamId, labels)\n\n return {\n number: result.identifier,\n url: result.url,\n }\n }\n\n /**\n * Get the web URL for a Linear issue\n * @param identifier - Linear issue identifier\n * @param _repo - Repository (unused for Linear)\n * @returns Issue URL\n */\n public async getIssueUrl(identifier: string | number, _repo?: string): Promise<string> {\n const issue = await this.fetchIssue(identifier)\n return issue.url\n }\n\n /**\n * Move a Linear issue to \"In Progress\" state\n * @param identifier - Linear issue identifier\n * @throws LinearServiceError if state update fails\n */\n public async moveIssueToInProgress(identifier: string | number): Promise<void> {\n logger.info(`Moving Linear issue ${identifier} to In Progress`)\n await updateLinearIssueState(String(identifier), 'In Progress')\n }\n\n /**\n * Extract issue context for AI prompts\n * @param entity - Issue (Linear doesn't have PRs)\n * @returns Formatted context string\n */\n public extractContext(entity: Issue | PullRequest): string {\n // Linear doesn't have PRs, always an issue\n const issue = entity as Issue\n return `Linear Issue ${issue.number}: ${issue.title}\\nState: ${issue.state}\\n\\n${issue.body}`\n }\n\n /**\n * Map Linear API issue to generic Issue type\n * @param linear - Linear issue from SDK\n * @returns Generic Issue type\n */\n private mapLinearIssueToIssue(linear: LinearIssue): Issue {\n return {\n number: linear.identifier, // Keep as string (e.g., \"ENG-123\")\n title: linear.title,\n body: linear.description ?? '',\n state: linear.state ? (linear.state.toLowerCase().includes('done') || linear.state.toLowerCase().includes('completed') || linear.state.toLowerCase().includes('canceled') ? 'closed' : 'open') : 'open',\n labels: [],\n assignees: [],\n url: linear.url,\n }\n }\n}\n","// IssueTrackerFactory - creates appropriate IssueTracker based on settings\n// Follows pattern from database provider instantiation\n\nimport type { IssueTracker } from './IssueTracker.js'\nimport { GitHubService } from './GitHubService.js'\nimport { LinearService, type LinearServiceConfig } from './LinearService.js'\nimport type { IloomSettings } from './SettingsManager.js'\nimport { getLogger } from '../utils/logger-context.js'\n\nexport type IssueTrackerProviderType = 'github' | 'linear'\n\n/**\n * Factory for creating IssueTracker instances based on settings\n * Provides a single point of provider instantiation\n *\n * Usage:\n * const tracker = IssueTrackerFactory.create(settings, { useClaude: true })\n * const issue = await tracker.fetchIssue(123)\n */\nexport class IssueTrackerFactory {\n\t/**\n\t * Create an IssueTracker instance based on settings configuration\n\t * Defaults to GitHub if no provider specified\n\t *\n\t * @param settings - iloom settings containing issueManagement.provider\n\t * @returns IssueTracker instance configured for the specified provider\n\t * @throws Error if provider type is not supported\n\t */\n\tstatic create(settings: IloomSettings): IssueTracker {\n\t\tconst provider = settings.issueManagement?.provider ?? 'github'\n\n\t\tgetLogger().debug(`IssueTrackerFactory: Creating tracker for provider \"${provider}\"`)\n\t\tgetLogger().debug(`IssueTrackerFactory: issueManagement settings:`, JSON.stringify(settings.issueManagement, null, 2))\n\n\t\tswitch (provider) {\n\t\t\tcase 'github':\n\t\t\t\tgetLogger().debug('IssueTrackerFactory: Creating GitHubService')\n\t\t\t\treturn new GitHubService()\n\t\t\tcase 'linear': {\n\t\t\t\tconst linearSettings = settings.issueManagement?.linear\n\t\t\t\tconst linearConfig: LinearServiceConfig = {}\n\n\t\t\t\tif (linearSettings?.teamId) {\n\t\t\t\t\tlinearConfig.teamId = linearSettings.teamId\n\t\t\t\t}\n\t\t\t\tif (linearSettings?.branchFormat) {\n\t\t\t\t\tlinearConfig.branchFormat = linearSettings.branchFormat\n\t\t\t\t}\n\n\t\t\t\tgetLogger().debug(`IssueTrackerFactory: Creating LinearService with config:`, JSON.stringify(linearConfig, null, 2))\n\t\t\t\treturn new LinearService(linearConfig)\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported issue tracker provider: ${provider}`)\n\t\t}\n\t}\n\n\t/**\n\t * Get the configured provider name from settings\n\t * Defaults to 'github' if not configured\n\t *\n\t * @param settings - iloom settings\n\t * @returns Provider type string\n\t */\n\tstatic getProviderName(settings: IloomSettings): IssueTrackerProviderType {\n\t\treturn (settings.issueManagement?.provider ?? 'github') as IssueTrackerProviderType\n\t}\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs-extra'\nimport { logger } from './logger.js'\n\n/**\n * FirstRunManager: Detect and track first-time spin usage via marker file\n *\n * Follows the same pattern as UpdateNotifier for file-based state tracking\n * in ~/.config/iloom-ai/ directory.\n *\n * Also supports project-level tracking for config wizard completion using\n * individual marker files per project in ~/.config/iloom-ai/projects/\n */\nexport class FirstRunManager {\n\tprivate markerFilePath: string\n\tprivate configDir: string\n\n\tconstructor(feature: string = 'spin') {\n\t\tthis.configDir = path.join(os.homedir(), '.config', 'iloom-ai')\n\t\tthis.markerFilePath = path.join(this.configDir, `${feature}-first-run`)\n\t\tlogger.debug('FirstRunManager initialized', {\n\t\t\tfeature,\n\t\t\tmarkerFilePath: this.markerFilePath\n\t\t})\n\t}\n\n\t/**\n\t * Get the directory for project marker files\n\t */\n\tprivate getProjectsDir(): string {\n\t\treturn path.join(this.configDir, 'projects')\n\t}\n\n\t/**\n\t * Resolve symlinks in project path to get canonical path\n\t * Falls back to original path on errors (broken symlinks, permissions, etc.)\n\t */\n\tprivate async resolveProjectPath(projectPath: string): Promise<string> {\n\t\ttry {\n\t\t\treturn await fs.realpath(projectPath)\n\t\t} catch {\n\t\t\tlogger.debug('resolveProjectPath: Failed to resolve symlink, using original path', { projectPath })\n\t\t\treturn projectPath\n\t\t}\n\t}\n\n\t/**\n\t * Convert a project path to a readable filename\n\t * /Users/adam/Projects/my-app -> Users__adam__Projects__my-app\n\t */\n\tprivate projectPathToFileName(projectPath: string): string {\n\t\tconst normalized = path.normalize(projectPath)\n\t\treturn normalized.replace(/^[/\\\\]+/, '').replace(/[/\\\\]+/g, '__')\n\t}\n\n\t/**\n\t * Get full path to a project's marker file\n\t */\n\tprivate getProjectMarkerPath(projectPath: string): string {\n\t\treturn path.join(this.getProjectsDir(), this.projectPathToFileName(projectPath))\n\t}\n\n\t/**\n\t * Extract project name from path\n\t */\n\tprivate getProjectName(projectPath: string): string {\n\t\treturn path.basename(projectPath)\n\t}\n\n\t/**\n\t * Check if a project has been configured\n\t * Returns true if project marker file exists\n\t */\n\tasync isProjectConfigured(projectPath?: string): Promise<boolean> {\n\t\tconst inputPath = projectPath ?? process.cwd()\n\t\tconst resolvedPath = await this.resolveProjectPath(inputPath)\n\t\tconst markerPath = this.getProjectMarkerPath(resolvedPath)\n\t\tlogger.debug('isProjectConfigured: Checking for marker file', { markerPath })\n\t\ttry {\n\t\t\tconst exists = await fs.pathExists(markerPath)\n\t\t\tlogger.debug(`isProjectConfigured: Marker file exists=${exists}`)\n\t\t\treturn exists\n\t\t} catch (error) {\n\t\t\t// On error, treat as not configured to allow wizard to run\n\t\t\tlogger.debug(`isProjectConfigured: Error checking marker file, treating as not configured: ${error}`)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Check if a project has local .iloom settings files\n\t * Returns true if .iloom/settings.json or .iloom/settings.local.json exists with content\n\t */\n\tprivate async hasLocalSettings(projectPath: string): Promise<boolean> {\n\t\tconst iloomDir = path.join(projectPath, '.iloom')\n\t\tconst settingsPath = path.join(iloomDir, 'settings.json')\n\t\tconst settingsLocalPath = path.join(iloomDir, 'settings.local.json')\n\n\t\tconst hasSettings = await this.hasNonEmptySettingsFile(settingsPath)\n\t\tconst hasLocalSettings = await this.hasNonEmptySettingsFile(settingsLocalPath)\n\n\t\treturn hasSettings || hasLocalSettings\n\t}\n\n\t/**\n\t * Check if a settings file exists and has non-empty content\n\t */\n\tprivate async hasNonEmptySettingsFile(filePath: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst exists = await fs.pathExists(filePath)\n\t\t\tif (!exists) return false\n\t\t\tconst content = await fs.readFile(filePath, 'utf8')\n\t\t\tconst parsed = JSON.parse(content)\n\t\t\treturn Object.keys(parsed).length > 0\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Fixup legacy projects that have local config but lack the global marker file\n\t * This handles projects configured before global project tracking was implemented\n\t *\n\t * Returns object with:\n\t * - isConfigured: true if project is configured (either already had marker or fixup created one)\n\t * - wasFixedUp: true if fixup was performed (marker was created by this call)\n\t *\n\t * This combined return avoids duplicate isProjectConfigured() calls in needsFirstRunSetup()\n\t */\n\tasync fixupLegacyProject(projectPath?: string): Promise<{ isConfigured: boolean; wasFixedUp: boolean }> {\n\t\tconst inputPath = projectPath ?? process.cwd()\n\t\tconst resolvedPath = await this.resolveProjectPath(inputPath)\n\t\tlogger.debug('fixupLegacyProject: Checking for legacy project', { projectPath: resolvedPath })\n\n\t\t// Check if already has global marker - no fixup needed, but project IS configured\n\t\tconst hasMarker = await this.isProjectConfigured(resolvedPath)\n\t\tif (hasMarker) {\n\t\t\tlogger.debug('fixupLegacyProject: Project already has global marker')\n\t\t\treturn { isConfigured: true, wasFixedUp: false }\n\t\t}\n\n\t\t// Check if has local settings files - this indicates a legacy configured project\n\t\tconst hasLocal = await this.hasLocalSettings(resolvedPath)\n\t\tif (!hasLocal) {\n\t\t\tlogger.debug('fixupLegacyProject: No local settings found, not a legacy project')\n\t\t\treturn { isConfigured: false, wasFixedUp: false }\n\t\t}\n\n\t\t// Legacy project found - create the missing global marker\n\t\tlogger.debug('fixupLegacyProject: Legacy project detected, creating global marker')\n\t\tawait this.markProjectAsConfigured(resolvedPath)\n\t\treturn { isConfigured: true, wasFixedUp: true }\n\t}\n\n\t/**\n\t * Mark a project as configured\n\t * Creates a marker file with project metadata\n\t */\n\tasync markProjectAsConfigured(projectPath?: string): Promise<void> {\n\t\tconst inputPath = projectPath ?? process.cwd()\n\t\tconst resolvedPath = await this.resolveProjectPath(inputPath)\n\t\tconst markerPath = this.getProjectMarkerPath(resolvedPath)\n\t\tlogger.debug('markProjectAsConfigured: Creating marker file', { markerPath })\n\t\ttry {\n\t\t\tawait fs.ensureDir(this.getProjectsDir())\n\t\t\tconst markerContent = {\n\t\t\t\tconfiguredAt: new Date().toISOString(),\n\t\t\t\tprojectPath: resolvedPath,\n\t\t\t\tprojectName: this.getProjectName(resolvedPath)\n\t\t\t}\n\t\t\tawait fs.writeFile(markerPath, JSON.stringify(markerContent, null, 2), 'utf8')\n\t\t\tlogger.debug('markProjectAsConfigured: Marker file created successfully')\n\t\t} catch (error) {\n\t\t\t// Don't throw on errors - just log debug message\n\t\t\tlogger.debug(`markProjectAsConfigured: Failed to create marker file: ${error}`)\n\t\t}\n\t}\n\n\t/**\n\t * Check if this is the first run of the feature\n\t * Returns true if marker file doesn't exist\n\t * Handles errors gracefully by returning true (treat as first-run on error)\n\t */\n\tasync isFirstRun(): Promise<boolean> {\n\t\tlogger.debug('isFirstRun: Checking for marker file', { markerFilePath: this.markerFilePath })\n\t\ttry {\n\t\t\tconst exists = await fs.pathExists(this.markerFilePath)\n\t\t\tlogger.debug(`isFirstRun: Marker file exists=${exists}`)\n\t\t\treturn !exists\n\t\t} catch (error) {\n\t\t\t// On error, gracefully degrade by treating as first-run\n\t\t\tlogger.debug(`isFirstRun: Error checking marker file, treating as first-run: ${error}`)\n\t\t\treturn true\n\t\t}\n\t}\n\n\t/**\n\t * Mark the feature as having been run\n\t * Creates the marker file in config directory\n\t * Handles errors gracefully without throwing\n\t */\n\tasync markAsRun(): Promise<void> {\n\t\tlogger.debug('markAsRun: Attempting to create marker file', { markerFilePath: this.markerFilePath })\n\t\ttry {\n\t\t\t// Ensure directory exists\n\t\t\tconst configDir = path.dirname(this.markerFilePath)\n\t\t\tlogger.debug(`markAsRun: Ensuring config directory exists: ${configDir}`)\n\t\t\tawait fs.ensureDir(configDir)\n\n\t\t\t// Write marker file with timestamp for debugging\n\t\t\tconst markerContent = {\n\t\t\t\tfirstRun: new Date().toISOString(),\n\t\t\t}\n\t\t\tawait fs.writeFile(this.markerFilePath, JSON.stringify(markerContent, null, 2), 'utf8')\n\t\t\tlogger.debug('markAsRun: Marker file created successfully')\n\t\t} catch (error) {\n\t\t\t// Don't throw on errors - just log debug message\n\t\t\t// Failing to write marker shouldn't break the workflow\n\t\t\tlogger.debug(`markAsRun: Failed to create marker file: ${error}`)\n\t\t}\n\t}\n}\n","import path from 'path'\nimport { getRepoInfo } from './github.js'\nimport { logger } from './logger.js'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\n\n/**\n * Generate MCP configuration for issue management\n * Uses a single server that can handle both issues and pull requests\n * Returns array of MCP server config objects\n * @param contextType - Optional context type (issue or pr)\n * @param repo - Optional repo in \"owner/repo\" format. If not provided, will auto-detect from git.\n * @param provider - Issue management provider (default: 'github')\n * @param settings - Optional settings to extract Linear API token from\n */\nexport async function generateIssueManagementMcpConfig(\n\tcontextType?: 'issue' | 'pr',\n\trepo?: string,\n\tprovider: 'github' | 'linear' = 'github',\n\tsettings?: IloomSettings\n): Promise<Record<string, unknown>[]> {\n\t// Build provider-specific environment variables\n\tlet envVars: Record<string, string> = {\n\t\tISSUE_PROVIDER: provider,\n\t}\n\n\tif (provider === 'github') {\n\t\t// Get repository information for GitHub - either from provided repo string or auto-detect\n\t\tlet owner: string\n\t\tlet name: string\n\n\t\tif (repo) {\n\t\t\tconst parts = repo.split('/')\n\t\t\tif (parts.length !== 2 || !parts[0] || !parts[1]) {\n\t\t\t\tthrow new Error(`Invalid repo format: ${repo}. Expected \"owner/repo\"`)\n\t\t\t}\n\t\t\towner = parts[0]\n\t\t\tname = parts[1]\n\t\t} else {\n\t\t\tconst repoInfo = await getRepoInfo()\n\t\t\towner = repoInfo.owner\n\t\t\tname = repoInfo.name\n\t\t}\n\n\t\t// Map logical types to GitHub's webhook event names (handle GitHub's naming quirk here)\n\t\tconst githubEventName = contextType === 'issue' ? 'issues' : contextType === 'pr' ? 'pull_request' : undefined\n\n\t\tenvVars = {\n\t\t\t...envVars,\n\t\t\tREPO_OWNER: owner,\n\t\t\tREPO_NAME: name,\n\t\t\tGITHUB_API_URL: 'https://api.github.com/',\n\t\t\t...(githubEventName && { GITHUB_EVENT_NAME: githubEventName }),\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for GitHub issue management', {\n\t\t\tprovider,\n\t\t\trepoOwner: owner,\n\t\t\trepoName: name,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t\tgithubEventName: githubEventName ?? 'auto-detect'\n\t\t})\n\t} else {\n\t\t// Linear needs API token passed through\n\t\tconst apiToken = settings?.issueManagement?.linear?.apiToken ?? process.env.LINEAR_API_TOKEN\n\n\t\tif (apiToken) {\n\t\t\tenvVars.LINEAR_API_TOKEN = apiToken\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for Linear issue management', {\n\t\t\tprovider,\n\t\t\thasApiToken: !!apiToken,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t})\n\t}\n\n\t// Generate single MCP server config\n\tconst mcpServerConfig = {\n\t\tmcpServers: {\n\t\t\tissue_management: {\n\t\t\t\ttransport: 'stdio',\n\t\t\t\tcommand: 'node',\n\t\t\t\targs: [path.join(path.dirname(new globalThis.URL(import.meta.url).pathname), '../dist/mcp/issue-management-server.js')],\n\t\t\t\tenv: envVars,\n\t\t\t},\n\t\t},\n\t}\n\n\treturn [mcpServerConfig]\n}"],"mappings":"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","names":["path","path"]}