agent-issues 0.0.119

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 (208) hide show
  1. package/.github/agents/agent-issues.agent.md +54 -0
  2. package/.github/agents/agent-issues.claude.md +51 -0
  3. package/dist/agent-installer.d.ts +49 -0
  4. package/dist/agent-installer.js +171 -0
  5. package/dist/agent-installer.js.map +1 -0
  6. package/dist/auth-session.d.ts +40 -0
  7. package/dist/auth-session.js +107 -0
  8. package/dist/auth-session.js.map +1 -0
  9. package/dist/body-backfill.d.ts +26 -0
  10. package/dist/body-backfill.js +219 -0
  11. package/dist/body-backfill.js.map +1 -0
  12. package/dist/build-mode.d.ts +1 -0
  13. package/dist/build-mode.js +1 -0
  14. package/dist/build-mode.js.map +1 -0
  15. package/dist/cli/commands/auth.d.ts +61 -0
  16. package/dist/cli/commands/auth.js +134 -0
  17. package/dist/cli/commands/auth.js.map +1 -0
  18. package/dist/cli/commands/backfill.d.ts +8 -0
  19. package/dist/cli/commands/backfill.js +36 -0
  20. package/dist/cli/commands/backfill.js.map +1 -0
  21. package/dist/cli/commands/comments.d.ts +34 -0
  22. package/dist/cli/commands/comments.js +124 -0
  23. package/dist/cli/commands/comments.js.map +1 -0
  24. package/dist/cli/commands/context.d.ts +13 -0
  25. package/dist/cli/commands/context.js +156 -0
  26. package/dist/cli/commands/context.js.map +1 -0
  27. package/dist/cli/commands/entities.d.ts +91 -0
  28. package/dist/cli/commands/entities.js +420 -0
  29. package/dist/cli/commands/entities.js.map +1 -0
  30. package/dist/cli/commands/export.d.ts +20 -0
  31. package/dist/cli/commands/export.js +98 -0
  32. package/dist/cli/commands/export.js.map +1 -0
  33. package/dist/cli/commands/fallback.d.ts +6 -0
  34. package/dist/cli/commands/fallback.js +10 -0
  35. package/dist/cli/commands/fallback.js.map +1 -0
  36. package/dist/cli/commands/handoff.d.ts +1 -0
  37. package/dist/cli/commands/handoff.js +2 -0
  38. package/dist/cli/commands/handoff.js.map +1 -0
  39. package/dist/cli/commands/installers.d.ts +37 -0
  40. package/dist/cli/commands/installers.js +78 -0
  41. package/dist/cli/commands/installers.js.map +1 -0
  42. package/dist/cli/commands/kanban.d.ts +8 -0
  43. package/dist/cli/commands/kanban.js +83 -0
  44. package/dist/cli/commands/kanban.js.map +1 -0
  45. package/dist/cli/commands/meta.d.ts +14 -0
  46. package/dist/cli/commands/meta.js +33 -0
  47. package/dist/cli/commands/meta.js.map +1 -0
  48. package/dist/cli/commands/plan-entries.d.ts +30 -0
  49. package/dist/cli/commands/plan-entries.js +94 -0
  50. package/dist/cli/commands/plan-entries.js.map +1 -0
  51. package/dist/cli/commands/site.d.ts +29 -0
  52. package/dist/cli/commands/site.js +89 -0
  53. package/dist/cli/commands/site.js.map +1 -0
  54. package/dist/cli/commands/sql.d.ts +6 -0
  55. package/dist/cli/commands/sql.js +21 -0
  56. package/dist/cli/commands/sql.js.map +1 -0
  57. package/dist/cli/commands/synchronize.d.ts +12 -0
  58. package/dist/cli/commands/synchronize.js +31 -0
  59. package/dist/cli/commands/synchronize.js.map +1 -0
  60. package/dist/cli/commands/tenants.d.ts +29 -0
  61. package/dist/cli/commands/tenants.js +101 -0
  62. package/dist/cli/commands/tenants.js.map +1 -0
  63. package/dist/cli/index.d.ts +4 -0
  64. package/dist/cli/index.js +120 -0
  65. package/dist/cli/index.js.map +1 -0
  66. package/dist/cli/renderers.d.ts +250 -0
  67. package/dist/cli/renderers.js +286 -0
  68. package/dist/cli/renderers.js.map +1 -0
  69. package/dist/cli/shared.d.ts +97 -0
  70. package/dist/cli/shared.js +192 -0
  71. package/dist/cli/shared.js.map +1 -0
  72. package/dist/cli.d.ts +11 -0
  73. package/dist/cli.js +41 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/context-cli.d.ts +16 -0
  76. package/dist/context-cli.js +131 -0
  77. package/dist/context-cli.js.map +1 -0
  78. package/dist/daemon/daemon-lifecycle.d.ts +1 -0
  79. package/dist/daemon/daemon-lifecycle.js +2 -0
  80. package/dist/daemon/daemon-lifecycle.js.map +1 -0
  81. package/dist/daemon/daemon-main.d.ts +14 -0
  82. package/dist/daemon/daemon-main.js +30 -0
  83. package/dist/daemon/daemon-main.js.map +1 -0
  84. package/dist/daemon/local-daemon-store.d.ts +21 -0
  85. package/dist/daemon/local-daemon-store.js +31 -0
  86. package/dist/daemon/local-daemon-store.js.map +1 -0
  87. package/dist/entity-projection.d.ts +141 -0
  88. package/dist/entity-projection.js +147 -0
  89. package/dist/entity-projection.js.map +1 -0
  90. package/dist/entra-device-login.d.ts +12 -0
  91. package/dist/entra-device-login.js +40 -0
  92. package/dist/entra-device-login.js.map +1 -0
  93. package/dist/export-files.d.ts +24 -0
  94. package/dist/export-files.js +230 -0
  95. package/dist/export-files.js.map +1 -0
  96. package/dist/export-markdown.d.ts +24 -0
  97. package/dist/export-markdown.js +343 -0
  98. package/dist/export-markdown.js.map +1 -0
  99. package/dist/help.d.ts +112 -0
  100. package/dist/help.js +1430 -0
  101. package/dist/help.js.map +1 -0
  102. package/dist/kanban/assets.d.ts +3 -0
  103. package/dist/kanban/assets.js +37 -0
  104. package/dist/kanban/assets.js.map +1 -0
  105. package/dist/kanban/index.d.ts +1 -0
  106. package/dist/kanban/index.js +2 -0
  107. package/dist/kanban/index.js.map +1 -0
  108. package/dist/kanban/server.d.ts +28 -0
  109. package/dist/kanban/server.js +118 -0
  110. package/dist/kanban/server.js.map +1 -0
  111. package/dist/mcp-installer.d.ts +32 -0
  112. package/dist/mcp-installer.js +118 -0
  113. package/dist/mcp-installer.js.map +1 -0
  114. package/dist/mcp-server/index.d.ts +11 -0
  115. package/dist/mcp-server/index.js +504 -0
  116. package/dist/mcp-server/index.js.map +1 -0
  117. package/dist/mcp-server/index.test.d.ts +1 -0
  118. package/dist/mcp-server/index.test.js +746 -0
  119. package/dist/mcp-server/index.test.js.map +1 -0
  120. package/dist/mcp-server/mcp-tool-audit.d.ts +6 -0
  121. package/dist/mcp-server/mcp-tool-audit.js +47 -0
  122. package/dist/mcp-server/mcp-tool-audit.js.map +1 -0
  123. package/dist/mcp-server/stdio.d.ts +2 -0
  124. package/dist/mcp-server/stdio.js +7 -0
  125. package/dist/mcp-server/stdio.js.map +1 -0
  126. package/dist/mcp.d.ts +2 -0
  127. package/dist/mcp.js +19 -0
  128. package/dist/mcp.js.map +1 -0
  129. package/dist/open-storage-driver.d.ts +53 -0
  130. package/dist/open-storage-driver.js +71 -0
  131. package/dist/open-storage-driver.js.map +1 -0
  132. package/dist/open-synchronize-stores.d.ts +24 -0
  133. package/dist/open-synchronize-stores.js +34 -0
  134. package/dist/open-synchronize-stores.js.map +1 -0
  135. package/dist/project-identity.d.ts +23 -0
  136. package/dist/project-identity.js +121 -0
  137. package/dist/project-identity.js.map +1 -0
  138. package/dist/runtime-access-boundary.d.ts +7 -0
  139. package/dist/runtime-access-boundary.js +182 -0
  140. package/dist/runtime-access-boundary.js.map +1 -0
  141. package/dist/service-discovery.d.ts +10 -0
  142. package/dist/service-discovery.js +64 -0
  143. package/dist/service-discovery.js.map +1 -0
  144. package/dist/site/assets.d.ts +4 -0
  145. package/dist/site/assets.js +46 -0
  146. package/dist/site/assets.js.map +1 -0
  147. package/dist/site/cloud-events-relay.d.ts +18 -0
  148. package/dist/site/cloud-events-relay.js +78 -0
  149. package/dist/site/cloud-events-relay.js.map +1 -0
  150. package/dist/site/index.d.ts +1 -0
  151. package/dist/site/index.js +2 -0
  152. package/dist/site/index.js.map +1 -0
  153. package/dist/site/server.d.ts +42 -0
  154. package/dist/site/server.js +320 -0
  155. package/dist/site/server.js.map +1 -0
  156. package/dist/skill-installer.d.ts +35 -0
  157. package/dist/skill-installer.js +174 -0
  158. package/dist/skill-installer.js.map +1 -0
  159. package/dist/vitest-setup.d.ts +1 -0
  160. package/dist/vitest-setup.js +7 -0
  161. package/dist/vitest-setup.js.map +1 -0
  162. package/package.json +42 -0
  163. package/site/dist/assets/index-DKEVC0aQ.css +1 -0
  164. package/site/dist/assets/index-DSR4mIml.js +4396 -0
  165. package/site/dist/index.html +14 -0
  166. package/skills/agent-issues-language.md +5 -0
  167. package/skills/agent-issues-operating-contract.md +208 -0
  168. package/skills/ai-agent-issues/SKILL.md +127 -0
  169. package/skills/ai-domain-modeling/ADR-FORMAT.md +48 -0
  170. package/skills/ai-domain-modeling/CONTEXT-FORMAT.md +54 -0
  171. package/skills/ai-domain-modeling/SKILL.md +45 -0
  172. package/skills/ai-grill-with-docs/SKILL.md +28 -0
  173. package/skills/ai-handoff/SKILL.md +41 -0
  174. package/skills/ai-implement/SKILL.md +98 -0
  175. package/skills/ai-migrate-docs/SKILL.md +65 -0
  176. package/skills/ai-next-work/SKILL.md +43 -0
  177. package/skills/ai-plan/SKILL.md +41 -0
  178. package/skills/ai-prepare/SKILL.md +79 -0
  179. package/skills/ai-prototype/LOGIC.md +67 -0
  180. package/skills/ai-prototype/SKILL.md +31 -0
  181. package/skills/ai-prototype/UI.md +112 -0
  182. package/skills/ai-recipe-migration/SKILL.md +49 -0
  183. package/skills/ai-start-work/SKILL.md +56 -0
  184. package/skills/ai-tdd/SKILL.md +99 -0
  185. package/skills/ai-tdd/deep-modules.md +33 -0
  186. package/skills/ai-tdd/interface-design.md +20 -0
  187. package/skills/ai-tdd/mocking.md +28 -0
  188. package/skills/ai-tdd/refactoring.md +10 -0
  189. package/skills/ai-tdd/tests.md +74 -0
  190. package/skills/ai-to-issues/SKILL.md +70 -0
  191. package/skills/ai-to-prd/SKILL.md +33 -0
  192. package/skills/ai-wayfinder/SKILL.md +110 -0
  193. package/skills/recipes/README.md +29 -0
  194. package/skills/recipes/adr.md +21 -0
  195. package/skills/recipes/context-summary.md +17 -0
  196. package/skills/recipes/context-term.md +3 -0
  197. package/skills/recipes/debt.md +21 -0
  198. package/skills/recipes/epic.md +21 -0
  199. package/skills/recipes/handoff.md +29 -0
  200. package/skills/recipes/initiative.md +21 -0
  201. package/skills/recipes/issue-comment.md +15 -0
  202. package/skills/recipes/issue.md +33 -0
  203. package/skills/recipes/prd.md +29 -0
  204. package/skills/recipes/project.md +21 -0
  205. package/skills/recipes/user-story.md +15 -0
  206. package/skills/recipes/version.md +13 -0
  207. package/skills/recipes/wayfinder-map.md +25 -0
  208. package/skills/recipes/wayfinder-ticket.md +17 -0
@@ -0,0 +1,219 @@
1
+ export const BACKFILLABLE_BODY_KINDS = ["project", "epic", "version", "initiative", "issue", "prd", "userStory", "adr"];
2
+ const DERIVED_CONTENT_MARKER = "Not derived from tracker metadata.";
3
+ export function isBackfillableBodyKind(value) {
4
+ return BACKFILLABLE_BODY_KINDS.includes(value);
5
+ }
6
+ export function parseBackfillableBodyKinds(values) {
7
+ if (values.length === 0) {
8
+ return [...BACKFILLABLE_BODY_KINDS];
9
+ }
10
+ const kinds = [];
11
+ const invalid = [];
12
+ for (const value of values) {
13
+ if (!isBackfillableBodyKind(value)) {
14
+ invalid.push(value);
15
+ continue;
16
+ }
17
+ if (!kinds.includes(value)) {
18
+ kinds.push(value);
19
+ }
20
+ }
21
+ if (invalid.length > 0) {
22
+ throw new Error(`Unsupported backfill kinds: ${invalid.join(", ")}. Supported kinds: ${BACKFILLABLE_BODY_KINDS.join(", ")}.`);
23
+ }
24
+ return kinds;
25
+ }
26
+ export async function backfillBodies(store, input = {}) {
27
+ const snapshot = await store.getDatabaseSnapshot();
28
+ const kinds = input.kinds ?? [...BACKFILLABLE_BODY_KINDS];
29
+ const byKind = [];
30
+ for (const kind of kinds) {
31
+ const entities = sortEntities(snapshot.entities.filter((entity) => entity.kind === kind));
32
+ let updated = 0;
33
+ let skipped = 0;
34
+ for (const entity of entities) {
35
+ const body = buildBody(kind);
36
+ if (body.trim().length === 0) {
37
+ skipped += 1;
38
+ continue;
39
+ }
40
+ const hasStoredBody = entity.body.trim().length > 0;
41
+ const matchesGeneratedBody = hasStoredBody && entity.body === body;
42
+ if (!input.force && hasStoredBody && !matchesGeneratedBody) {
43
+ skipped += 1;
44
+ continue;
45
+ }
46
+ if (!input.force && matchesGeneratedBody && entity.bodySource === "generated") {
47
+ skipped += 1;
48
+ continue;
49
+ }
50
+ if (!input.dryRun) {
51
+ await store.setEntityBody({ entityId: entity.id, body, bodySource: "generated", expectedRevision: entity.revision, expectedContentHash: entity.contentHash });
52
+ }
53
+ updated += 1;
54
+ }
55
+ byKind.push({
56
+ kind,
57
+ considered: entities.length,
58
+ updated,
59
+ skipped
60
+ });
61
+ }
62
+ return {
63
+ tenantId: store.tenantId,
64
+ dryRun: input.dryRun ?? false,
65
+ force: input.force ?? false,
66
+ kinds,
67
+ considered: byKind.reduce((sum, item) => sum + item.considered, 0),
68
+ updated: byKind.reduce((sum, item) => sum + item.updated, 0),
69
+ skipped: byKind.reduce((sum, item) => sum + item.skipped, 0),
70
+ byKind
71
+ };
72
+ }
73
+ function buildBody(kind) {
74
+ switch (kind) {
75
+ case "project":
76
+ return buildManagementBody();
77
+ case "epic":
78
+ return buildManagementBody();
79
+ case "version":
80
+ return buildVersionBody();
81
+ case "initiative":
82
+ return buildInitiativeBody();
83
+ case "issue":
84
+ return buildIssueBody();
85
+ case "prd":
86
+ return buildPrdBody();
87
+ case "userStory":
88
+ return buildUserStoryBody();
89
+ case "adr":
90
+ return buildAdrBody();
91
+ }
92
+ }
93
+ function buildManagementBody() {
94
+ return [
95
+ "## Purpose",
96
+ "",
97
+ DERIVED_CONTENT_MARKER,
98
+ "",
99
+ "## Scope",
100
+ "",
101
+ `- ${DERIVED_CONTENT_MARKER}`,
102
+ "",
103
+ "## Success Conditions",
104
+ "",
105
+ `- ${DERIVED_CONTENT_MARKER}`,
106
+ "",
107
+ "## Non-Goals",
108
+ "",
109
+ `- ${DERIVED_CONTENT_MARKER}`
110
+ ].join("\n");
111
+ }
112
+ function buildVersionBody() {
113
+ return [
114
+ "## Release Intent",
115
+ "",
116
+ DERIVED_CONTENT_MARKER,
117
+ "",
118
+ "## Compatibility and Migration Notes",
119
+ "",
120
+ `- ${DERIVED_CONTENT_MARKER}`
121
+ ].join("\n");
122
+ }
123
+ function buildInitiativeBody() {
124
+ return buildManagementBody();
125
+ }
126
+ function buildIssueBody() {
127
+ return [
128
+ "## Work Mode",
129
+ "",
130
+ DERIVED_CONTENT_MARKER,
131
+ "",
132
+ "## Outcome",
133
+ "",
134
+ DERIVED_CONTENT_MARKER,
135
+ "",
136
+ "## Scope",
137
+ "",
138
+ `- ${DERIVED_CONTENT_MARKER}`,
139
+ "",
140
+ "## Work Plan",
141
+ "",
142
+ `- ${DERIVED_CONTENT_MARKER}`,
143
+ "",
144
+ "## Acceptance Criteria",
145
+ "",
146
+ `- ${DERIVED_CONTENT_MARKER}`,
147
+ "",
148
+ "## Verification",
149
+ "",
150
+ `- ${DERIVED_CONTENT_MARKER}`,
151
+ "",
152
+ "## Notes",
153
+ "",
154
+ DERIVED_CONTENT_MARKER
155
+ ].join("\n");
156
+ }
157
+ function buildPrdBody() {
158
+ return [
159
+ "## Problem Statement",
160
+ "",
161
+ DERIVED_CONTENT_MARKER,
162
+ "",
163
+ "## Solution",
164
+ "",
165
+ DERIVED_CONTENT_MARKER,
166
+ "",
167
+ "## Implementation Decisions",
168
+ "",
169
+ `- ${DERIVED_CONTENT_MARKER}`,
170
+ "",
171
+ "## Testing Decisions",
172
+ "",
173
+ `- ${DERIVED_CONTENT_MARKER}`,
174
+ "",
175
+ "## Out of Scope",
176
+ "",
177
+ `- ${DERIVED_CONTENT_MARKER}`,
178
+ "",
179
+ "## Further Notes",
180
+ "",
181
+ DERIVED_CONTENT_MARKER
182
+ ].join("\n");
183
+ }
184
+ function buildUserStoryBody() {
185
+ return [
186
+ `As an actor, I want ${DERIVED_CONTENT_MARKER}, so that ${DERIVED_CONTENT_MARKER}`,
187
+ "",
188
+ "## Acceptance Criteria",
189
+ "",
190
+ `- ${DERIVED_CONTENT_MARKER}`,
191
+ "",
192
+ "## Boundaries",
193
+ "",
194
+ `- ${DERIVED_CONTENT_MARKER}`
195
+ ].join("\n");
196
+ }
197
+ function buildAdrBody() {
198
+ return [
199
+ "## Status",
200
+ "",
201
+ DERIVED_CONTENT_MARKER,
202
+ "",
203
+ "## Context",
204
+ "",
205
+ DERIVED_CONTENT_MARKER,
206
+ "",
207
+ "## Decision",
208
+ "",
209
+ DERIVED_CONTENT_MARKER,
210
+ "",
211
+ "## Consequences",
212
+ "",
213
+ `- ${DERIVED_CONTENT_MARKER}`
214
+ ].join("\n");
215
+ }
216
+ function sortEntities(entities) {
217
+ return [...entities].sort((left, right) => left.id.localeCompare(right.id, undefined, { numeric: true }));
218
+ }
219
+ //# sourceMappingURL=body-backfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-backfill.js","sourceRoot":"","sources":["../src/body-backfill.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,CAAU,CAAC;AACjI,MAAM,sBAAsB,GAAG,oCAAoC,CAAC;AAsBpE,MAAM,UAAU,sBAAsB,CAAC,KAAa;IACnD,OAAO,uBAAuB,CAAC,QAAQ,CAAC,KAA6B,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,MAAgB;IAC1D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,uBAAuB,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS;QACV,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC;IACF,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACd,+BAA+B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC5G,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAoB,EACpB,KAAK,GAA0E,EAAE;IAEjF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,mBAAmB,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,GAAG,uBAAuB,CAAC,CAAC;IAC1D,MAAM,MAAM,GAA+B,EAAE,CAAC;IAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;QAC1F,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9B,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;YACV,CAAC;YAED,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;YACpD,MAAM,oBAAoB,GAAG,aAAa,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC;YAEnE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,aAAa,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC5D,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;YACV,CAAC;YAED,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,oBAAoB,IAAI,MAAM,CAAC,UAAU,KAAK,WAAW,EAAE,CAAC;gBAC/E,OAAO,IAAI,CAAC,CAAC;gBACb,SAAS;YACV,CAAC;YAED,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACnB,MAAM,KAAK,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC/J,CAAC;YACD,OAAO,IAAI,CAAC,CAAC;QACd,CAAC;QAED,MAAM,CAAC,IAAI,CAAC;YACX,IAAI;YACJ,UAAU,EAAE,QAAQ,CAAC,MAAM;YAC3B,OAAO;YACP,OAAO;SACP,CAAC,CAAC;IACJ,CAAC;IAED,OAAO;QACN,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK;QAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK;QAC3B,KAAK;QACL,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,MAAM;KACN,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAA0B;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,SAAS;YACb,OAAO,mBAAmB,EAAE,CAAC;QAC9B,KAAK,MAAM;YACV,OAAO,mBAAmB,EAAE,CAAC;QAC9B,KAAK,SAAS;YACb,OAAO,gBAAgB,EAAE,CAAC;QAC3B,KAAK,YAAY;YAChB,OAAO,mBAAmB,EAAE,CAAC;QAC9B,KAAK,OAAO;YACX,OAAO,cAAc,EAAE,CAAC;QACzB,KAAK,KAAK;YACT,OAAO,YAAY,EAAE,CAAC;QACvB,KAAK,WAAW;YACf,OAAO,kBAAkB,EAAE,CAAC;QAC7B,KAAK,KAAK;YACT,OAAO,YAAY,EAAE,CAAC;IACxB,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB;IAC3B,OAAO;QACN,YAAY;QACZ,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,UAAU;QACV,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,uBAAuB;QACvB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,cAAc;QACd,EAAE;QACF,KAAK,sBAAsB,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB;IACxB,OAAO;QACN,mBAAmB;QACnB,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,sCAAsC;QACtC,EAAE;QACF,KAAK,sBAAsB,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB;IAC3B,OAAO,mBAAmB,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,cAAc;IACtB,OAAO;QACN,cAAc;QACd,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,YAAY;QACZ,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,UAAU;QACV,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,cAAc;QACd,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,UAAU;QACV,EAAE;QACF,sBAAsB;KACtB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY;IACpB,OAAO;QACN,sBAAsB;QACtB,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,aAAa;QACb,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,6BAA6B;QAC7B,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,kBAAkB;QAClB,EAAE;QACF,sBAAsB;KACtB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB;IAC1B,OAAO;QACN,uBAAuB,sBAAsB,aAAa,sBAAsB,EAAE;QAClF,EAAE;QACF,wBAAwB;QACxB,EAAE;QACF,KAAK,sBAAsB,EAAE;QAC7B,EAAE;QACF,eAAe;QACf,EAAE;QACF,KAAK,sBAAsB,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY;IACpB,OAAO;QACN,WAAW;QACX,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,YAAY;QACZ,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,aAAa;QACb,EAAE;QACF,sBAAsB;QACtB,EAAE;QACF,iBAAiB;QACjB,EAAE;QACF,KAAK,sBAAsB,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAyB,QAAa;IAC1D,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC3G,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const BUILD_MODE: "development" | "production";
@@ -0,0 +1 @@
1
+ export const BUILD_MODE = "production";
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-mode.js","sourceRoot":"","sources":["../src/build-mode.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAiC,aAAa,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { type SavedLoginStoreOptions, type RemoteSavedLogin } from "../../auth-session.js";
2
+ import { BaseCommand } from "../shared.js";
3
+ export type DeviceCodeLoginResult = {
4
+ tenantId: string;
5
+ userId: string;
6
+ displayName?: string;
7
+ accessToken: string;
8
+ expiresAt: string;
9
+ };
10
+ /** Reports the human-readable device-code instructions Entra returns (e.g. "go to microsoft.com/devicelogin and enter code ABCD-EFGH"). */
11
+ export type DeviceCodePrompt = (message: string) => void;
12
+ /**
13
+ * Runs the interactive Entra ID device-code exchange and resolves the
14
+ * identity + token it produced. The real implementation
15
+ * (`../../entra-device-login.js`) is the genuine HITL gap this repo cannot
16
+ * exercise: it requires a human to complete a device-code login in a
17
+ * browser against a real Azure tenant (ISS32's acceptance criteria).
18
+ */
19
+ export type DeviceCodeLoginFn = (options: {
20
+ tenantId: string;
21
+ clientId: string;
22
+ onDeviceCode: DeviceCodePrompt;
23
+ }) => Promise<DeviceCodeLoginResult>;
24
+ export type RemoteLoginDependencies = {
25
+ deviceCodeLogin: DeviceCodeLoginFn;
26
+ fetch?: typeof globalThis.fetch;
27
+ onDeviceCode: DeviceCodePrompt;
28
+ storeOptions?: SavedLoginStoreOptions;
29
+ };
30
+ export declare function performRemoteLogin(input: {
31
+ name: string;
32
+ serviceUrl: string;
33
+ }, dependencies: RemoteLoginDependencies): Promise<RemoteSavedLogin>;
34
+ export declare class AuthLoginCommand extends BaseCommand {
35
+ static paths: string[][];
36
+ name: string | undefined;
37
+ serviceUrl: string | undefined;
38
+ execute(): Promise<number>;
39
+ private loginRemote;
40
+ private resolveRemoteInput;
41
+ private prompt;
42
+ }
43
+ export declare class AuthListCommand extends BaseCommand {
44
+ static paths: string[][];
45
+ execute(): Promise<number>;
46
+ }
47
+ export declare class AuthLogoutCommand extends BaseCommand {
48
+ static paths: string[][];
49
+ positionals: string[];
50
+ execute(): Promise<number>;
51
+ }
52
+ export declare class AuthStatusCommand extends BaseCommand {
53
+ static paths: string[][];
54
+ execute(): Promise<number>;
55
+ }
56
+ export declare class AuthSwitchCommand extends BaseCommand {
57
+ static paths: string[][];
58
+ positionals: string[];
59
+ execute(): Promise<number>;
60
+ private getNextSavedLoginName;
61
+ }
@@ -0,0 +1,134 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import { Option } from "clipanion";
3
+ import { getActiveSavedLogin, listSavedLogins, removeSavedLogin, saveSavedLogin, setActiveSavedLogin, toSavedLoginView } from "../../auth-session.js";
4
+ import { discoverServiceAuth } from "../../service-discovery.js";
5
+ import { renderAuthList, renderAuthLogin, renderAuthLogout, renderAuthStatus, renderAuthSwitch } from "../renderers.js";
6
+ import { BaseCommand } from "../shared.js";
7
+ export async function performRemoteLogin(input, dependencies) {
8
+ if (input.name === "local") {
9
+ throw new Error('Saved-login name "local" is reserved.');
10
+ }
11
+ const discovered = await discoverServiceAuth(input.serviceUrl, dependencies.fetch);
12
+ const result = await dependencies.deviceCodeLogin({
13
+ tenantId: discovered.auth.tenantId,
14
+ clientId: discovered.auth.clientId,
15
+ onDeviceCode: dependencies.onDeviceCode
16
+ });
17
+ const login = {
18
+ name: input.name,
19
+ kind: "remote",
20
+ serviceUrl: discovered.serviceUrl,
21
+ tenantId: result.tenantId,
22
+ userId: result.userId,
23
+ displayName: result.displayName,
24
+ accessToken: result.accessToken,
25
+ expiresAt: result.expiresAt
26
+ };
27
+ await saveSavedLogin(login, dependencies.storeOptions);
28
+ return login;
29
+ }
30
+ export class AuthLoginCommand extends BaseCommand {
31
+ static paths = [["auth", "login"]];
32
+ name = Option.String("--name");
33
+ serviceUrl = Option.String("--url");
34
+ async execute() {
35
+ const login = await this.loginRemote();
36
+ const view = toSavedLoginView(login);
37
+ this.print({ command: "auth-login", login: view }, renderAuthLogin(view));
38
+ return 0;
39
+ }
40
+ async loginRemote() {
41
+ const { name, serviceUrl } = await this.resolveRemoteInput();
42
+ const dependencies = this.context.authLoginDependencies;
43
+ const deviceCodeLogin = dependencies?.deviceCodeLogin
44
+ ?? (await import("../../entra-device-login.js")).acquireEntraDeviceCodeSession;
45
+ return performRemoteLogin({ name, serviceUrl }, {
46
+ deviceCodeLogin,
47
+ fetch: dependencies?.fetch,
48
+ onDeviceCode: (message) => this.context.stdout.write(`${message}\n`),
49
+ storeOptions: this.context.credentialStoreOptions
50
+ });
51
+ }
52
+ async resolveRemoteInput() {
53
+ let name = this.name?.trim();
54
+ let serviceUrl = this.serviceUrl?.trim();
55
+ if (this.asJson) {
56
+ if (!name)
57
+ throw new Error("`auth login --json` requires --name <name>.");
58
+ if (!serviceUrl)
59
+ throw new Error("`auth login --json` requires --url <url>.");
60
+ return { name, serviceUrl };
61
+ }
62
+ const dependencies = this.context.authLoginDependencies;
63
+ const interactive = dependencies?.interactive ?? (process.stdin.isTTY === true && process.stdout.isTTY === true);
64
+ if ((!name || !serviceUrl) && !interactive) {
65
+ throw new Error("`auth login` requires --name <name> and --url <url> outside an interactive terminal.");
66
+ }
67
+ const prompt = dependencies?.prompt ?? ((question) => this.prompt(question));
68
+ name ||= (await prompt("Saved login name: ")).trim();
69
+ serviceUrl ||= (await prompt("Service URL: ")).trim();
70
+ if (!name)
71
+ throw new Error("Saved-login name cannot be empty.");
72
+ if (!serviceUrl)
73
+ throw new Error("Service URL cannot be empty.");
74
+ return { name, serviceUrl };
75
+ }
76
+ async prompt(question) {
77
+ const readline = createInterface({ input: process.stdin, output: this.context.stdout, terminal: true });
78
+ try {
79
+ return await readline.question(question);
80
+ }
81
+ finally {
82
+ readline.close();
83
+ }
84
+ }
85
+ }
86
+ export class AuthListCommand extends BaseCommand {
87
+ static paths = [["auth", "list"]];
88
+ async execute() {
89
+ const logins = await listSavedLogins(this.context.credentialStoreOptions);
90
+ const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
91
+ const views = logins.map((login) => ({ login: toSavedLoginView(login), active: login.name === active.name }));
92
+ this.print({ command: "auth-list", logins: views }, renderAuthList(views));
93
+ return 0;
94
+ }
95
+ }
96
+ export class AuthLogoutCommand extends BaseCommand {
97
+ static paths = [["auth", "logout"]];
98
+ positionals = Option.Rest();
99
+ async execute() {
100
+ const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
101
+ const name = this.positionals[0] ?? active.name;
102
+ await removeSavedLogin(name, this.context.credentialStoreOptions);
103
+ this.print({ command: "auth-logout", name }, renderAuthLogout(name));
104
+ return 0;
105
+ }
106
+ }
107
+ export class AuthStatusCommand extends BaseCommand {
108
+ static paths = [["auth", "status"]];
109
+ async execute() {
110
+ const login = await getActiveSavedLogin(this.context.credentialStoreOptions);
111
+ const view = toSavedLoginView(login);
112
+ this.print({ command: "auth-status", login: view }, renderAuthStatus(view));
113
+ return 0;
114
+ }
115
+ }
116
+ export class AuthSwitchCommand extends BaseCommand {
117
+ static paths = [["auth", "switch"]];
118
+ positionals = Option.Rest();
119
+ async execute() {
120
+ const name = this.positionals[0] ?? (await this.getNextSavedLoginName());
121
+ await setActiveSavedLogin(name, this.context.credentialStoreOptions);
122
+ const login = await getActiveSavedLogin(this.context.credentialStoreOptions);
123
+ const view = toSavedLoginView(login);
124
+ this.print({ command: "auth-switch", login: view }, renderAuthSwitch(view));
125
+ return 0;
126
+ }
127
+ async getNextSavedLoginName() {
128
+ const logins = await listSavedLogins(this.context.credentialStoreOptions);
129
+ const active = await getActiveSavedLogin(this.context.credentialStoreOptions);
130
+ const activeIndex = logins.findIndex(({ name }) => name === active.name);
131
+ return logins[(activeIndex + 1) % logins.length].name;
132
+ }
133
+ }
134
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { MutableTenantCommand } from "../shared.js";
2
+ export declare class BackfillBodiesCommand extends MutableTenantCommand {
3
+ static paths: string[][];
4
+ allTenants: boolean;
5
+ dryRun: boolean;
6
+ kinds: string | undefined;
7
+ execute(): Promise<number>;
8
+ }
@@ -0,0 +1,36 @@
1
+ import { Option } from "clipanion";
2
+ import { backfillBodies, parseBackfillableBodyKinds } from "@agent-issues/core";
3
+ import { renderBackfillBodies } from "../renderers.js";
4
+ import { MutableTenantCommand, parseCsvOption, withStore } from "../shared.js";
5
+ export class BackfillBodiesCommand extends MutableTenantCommand {
6
+ static paths = [["backfill-bodies"]];
7
+ allTenants = Option.Boolean("--all-tenants", false);
8
+ dryRun = Option.Boolean("--dry-run", false);
9
+ kinds = Option.String("--kinds");
10
+ async execute() {
11
+ return withStore(this.dbPath, this.withStoreOptions(), async (store, dbPath) => {
12
+ const kinds = parseBackfillableBodyKinds(parseCsvOption(this.kinds));
13
+ const tenantIds = this.allTenants ? (await store.listTenants()).map((tenant) => tenant.id) : [store.tenantId];
14
+ const tenants = [];
15
+ for (const tenantId of tenantIds) {
16
+ if (tenantId === store.tenantId) {
17
+ tenants.push(await backfillBodies(store, { dryRun: this.dryRun, force: this.force, kinds }));
18
+ continue;
19
+ }
20
+ tenants.push(await withStore(this.dbPath, this.withStoreOptions({ tenant: tenantId }), (tenantStore) => backfillBodies(tenantStore, { dryRun: this.dryRun, force: this.force, kinds })));
21
+ }
22
+ const result = {
23
+ command: "backfill-bodies",
24
+ dbPath,
25
+ dryRun: this.dryRun,
26
+ force: this.force,
27
+ kinds,
28
+ scope: this.allTenants ? "all-tenants" : "current-tenant",
29
+ tenants
30
+ };
31
+ this.print(result, renderBackfillBodies(result));
32
+ return 0;
33
+ });
34
+ }
35
+ }
36
+ //# sourceMappingURL=backfill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../../src/cli/commands/backfill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE/E,MAAM,OAAO,qBAAsB,SAAQ,oBAAoB;IACvD,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAErC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACpD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC5C,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEjC,KAAK,CAAC,OAAO;QACnB,OAAO,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YAC9E,MAAM,KAAK,GAAG,0BAA0B,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE9G,MAAM,OAAO,GAAG,EAAE,CAAC;YACnB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBAClC,IAAI,QAAQ,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;oBACjC,OAAO,CAAC,IAAI,CAAC,MAAM,cAAc,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;oBAC7F,SAAS;gBACV,CAAC;gBAED,OAAO,CAAC,IAAI,CACX,MAAM,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CACzF,cAAc,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAC9E,CACD,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG;gBACd,OAAO,EAAE,iBAA0B;gBACnC,MAAM;gBACN,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK;gBACL,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,aAAuB,CAAC,CAAC,CAAE,gBAA0B;gBAC/E,OAAO;aACP,CAAC;YAEF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;YACjD,OAAO,CAAC,CAAC;QACV,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -0,0 +1,34 @@
1
+ import { BaseCommand, BodyTenantCommand, TenantCommand } from "../shared.js";
2
+ export declare class IssueCommentCommand extends BaseCommand {
3
+ static paths: string[][];
4
+ execute(): Promise<number>;
5
+ }
6
+ export declare class AddIssueCommentCommand extends BodyTenantCommand {
7
+ static paths: string[][];
8
+ positionals: string[];
9
+ references: string[] | undefined;
10
+ execute(): Promise<number>;
11
+ }
12
+ export declare class EditIssueCommentCommand extends BodyTenantCommand {
13
+ static paths: string[][];
14
+ positionals: string[];
15
+ references: string[] | undefined;
16
+ execute(): Promise<number>;
17
+ }
18
+ export declare class DeleteIssueCommentCommand extends TenantCommand {
19
+ static paths: string[][];
20
+ positionals: string[];
21
+ execute(): Promise<number>;
22
+ }
23
+ export declare class IssueCommentHistoryCommand extends TenantCommand {
24
+ static paths: string[][];
25
+ positionals: string[];
26
+ execute(): Promise<number>;
27
+ }
28
+ export declare class ListIssueCommentsCommand extends TenantCommand {
29
+ static paths: string[][];
30
+ all: boolean;
31
+ before: string | undefined;
32
+ positionals: string[];
33
+ execute(): Promise<number>;
34
+ }
@@ -0,0 +1,124 @@
1
+ import { Option } from "clipanion";
2
+ import { getHelpPayload, renderHelp } from "../../help.js";
3
+ import { BaseCommand, BodyTenantCommand, TenantCommand, requireOption, requirePositional, withStore } from "../shared.js";
4
+ export class IssueCommentCommand extends BaseCommand {
5
+ static paths = [["comment"]];
6
+ async execute() {
7
+ const payload = getHelpPayload("comment");
8
+ this.print(payload, renderHelp(payload));
9
+ return 0;
10
+ }
11
+ }
12
+ export class AddIssueCommentCommand extends BodyTenantCommand {
13
+ static paths = [["comment", "add"]];
14
+ positionals = Option.Rest();
15
+ references = Option.Array("--reference");
16
+ async execute() {
17
+ return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
18
+ const referencedIssueIds = await resolveReferencedIssueIds(store, this.references ?? []);
19
+ const comment = await store.createIssueComment({
20
+ issueId: requirePositional(this.positionals, 0, "comment add <issueId> --body-file <path|-> [--reference <issueId>]"),
21
+ body: requireOption(await this.resolveBody(), "--body-file is required for comment add."),
22
+ referencedIssueIds
23
+ });
24
+ this.print(comment, renderIssueComment(comment));
25
+ return 0;
26
+ });
27
+ }
28
+ }
29
+ export class EditIssueCommentCommand extends BodyTenantCommand {
30
+ static paths = [["comment", "edit"]];
31
+ positionals = Option.Rest();
32
+ references = Option.Array("--reference");
33
+ async execute() {
34
+ return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
35
+ const issueId = requirePositional(this.positionals, 0, "comment edit <issueId> <commentId> --body-file <path|-> [--reference <issueId>]");
36
+ const commentId = requirePositional(this.positionals, 1, "comment edit <issueId> <commentId> --body-file <path|-> [--reference <issueId>]");
37
+ const comment = await getIssueComment(store, issueId, commentId);
38
+ const referencedIssueIds = this.references === undefined
39
+ ? undefined
40
+ : await resolveReferencedIssueIds(store, this.references);
41
+ const updated = await store.updateIssueComment({
42
+ commentId,
43
+ body: requireOption(await this.resolveBody(), "--body-file is required for comment edit."),
44
+ referencedIssueIds,
45
+ expectedRevision: comment.revision,
46
+ expectedContentHash: comment.contentHash
47
+ });
48
+ this.print(updated, renderIssueComment(updated));
49
+ return 0;
50
+ });
51
+ }
52
+ }
53
+ export class DeleteIssueCommentCommand extends TenantCommand {
54
+ static paths = [["comment", "delete"]];
55
+ positionals = Option.Rest();
56
+ async execute() {
57
+ return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
58
+ const issueId = requirePositional(this.positionals, 0, "comment delete <issueId> <commentId>");
59
+ const commentId = requirePositional(this.positionals, 1, "comment delete <issueId> <commentId>");
60
+ const comment = await getIssueComment(store, issueId, commentId);
61
+ const deleted = await store.deleteIssueComment({
62
+ commentId,
63
+ expectedRevision: comment.revision,
64
+ expectedContentHash: comment.contentHash
65
+ });
66
+ this.print(deleted, renderIssueComment(deleted));
67
+ return 0;
68
+ });
69
+ }
70
+ }
71
+ export class IssueCommentHistoryCommand extends TenantCommand {
72
+ static paths = [["comment", "history"]];
73
+ positionals = Option.Rest();
74
+ async execute() {
75
+ return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
76
+ const history = await store.listIssueCommentHistory({
77
+ commentId: requirePositional(this.positionals, 0, "comment history <commentId>")
78
+ });
79
+ this.print(history, history.map(renderIssueCommentHistory).join("\n") || "No comment history found.");
80
+ return 0;
81
+ });
82
+ }
83
+ }
84
+ export class ListIssueCommentsCommand extends TenantCommand {
85
+ static paths = [["comment", "list"]];
86
+ all = Option.Boolean("--all", false);
87
+ before = Option.String("--before");
88
+ positionals = Option.Rest();
89
+ async execute() {
90
+ return withStore(this.dbPath, this.withStoreOptions(), async (store) => {
91
+ const page = await store.listIssueComments({
92
+ issueId: requirePositional(this.positionals, 0, "comment list <issueId> [--before <cursor>] [--all]"),
93
+ before: this.before,
94
+ all: this.all
95
+ });
96
+ this.print(page, page.comments.map(renderIssueComment).join("\n") || "No comments found.");
97
+ return 0;
98
+ });
99
+ }
100
+ }
101
+ function renderIssueComment(comment) {
102
+ if (comment.tombstone) {
103
+ return `${comment.reference} deleted ${comment.updatedAt}`;
104
+ }
105
+ return `${comment.reference} by ${comment.createdBy}\n${comment.body}`;
106
+ }
107
+ function renderIssueCommentHistory(entry) {
108
+ return `revision ${entry.targetRevision}/${entry.headRevision} by ${entry.author} ${entry.createdAt}${entry.tombstone ? " deleted" : ""}\n${entry.body}`;
109
+ }
110
+ async function getIssueComment(store, issueId, commentId) {
111
+ const issue = await store.getEntityDetails(issueId);
112
+ const comment = (await store.listIssueComments({ issueId: issue.entity.id, all: true })).comments
113
+ .find((candidate) => candidate.id === commentId || candidate.reference === commentId);
114
+ if (!comment) {
115
+ throw new Error(`Issue comment not found: ${commentId}`);
116
+ }
117
+ return comment;
118
+ }
119
+ async function resolveReferencedIssueIds(store, references) {
120
+ return await Promise.all(references.map(async (reference) => {
121
+ return (await store.getEntityDetails(reference)).entity.id;
122
+ }));
123
+ }
124
+ //# sourceMappingURL=comments.js.map