@ilya-lesikov/pi-pi 0.1.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 (271) hide show
  1. package/3p/pi-ask-user/index.ts +1835 -0
  2. package/3p/pi-ask-user/package.json +50 -0
  3. package/3p/pi-ask-user/single-select-layout.ts +203 -0
  4. package/3p/pi-lsp/extensions/lsp/client.ts +542 -0
  5. package/3p/pi-lsp/extensions/lsp/config.ts +135 -0
  6. package/3p/pi-lsp/extensions/lsp/effects/command.ts +42 -0
  7. package/3p/pi-lsp/extensions/lsp/effects/filesystem.ts +50 -0
  8. package/3p/pi-lsp/extensions/lsp/effects/runtime.ts +21 -0
  9. package/3p/pi-lsp/extensions/lsp/errors.ts +113 -0
  10. package/3p/pi-lsp/extensions/lsp/formatting.ts +315 -0
  11. package/3p/pi-lsp/extensions/lsp/index.ts +231 -0
  12. package/3p/pi-lsp/extensions/lsp/protocol.ts +209 -0
  13. package/3p/pi-lsp/extensions/lsp/retry.ts +39 -0
  14. package/3p/pi-lsp/extensions/lsp/tools/programs.ts +293 -0
  15. package/3p/pi-lsp/extensions/lsp/tools.ts +89 -0
  16. package/3p/pi-lsp/extensions/lsp/types.ts +243 -0
  17. package/3p/pi-lsp/package.json +54 -0
  18. package/3p/pi-plannotator/AGENTS.md +583 -0
  19. package/3p/pi-plannotator/apps/pi-extension/README.md +228 -0
  20. package/3p/pi-plannotator/apps/pi-extension/assistant-message.ts +128 -0
  21. package/3p/pi-plannotator/apps/pi-extension/config.test.ts +166 -0
  22. package/3p/pi-plannotator/apps/pi-extension/config.ts +318 -0
  23. package/3p/pi-plannotator/apps/pi-extension/current-pi-session.ts +147 -0
  24. package/3p/pi-plannotator/apps/pi-extension/index.ts +1279 -0
  25. package/3p/pi-plannotator/apps/pi-extension/package.json +56 -0
  26. package/3p/pi-plannotator/apps/pi-extension/plannotator-browser.test.ts +13 -0
  27. package/3p/pi-plannotator/apps/pi-extension/plannotator-browser.ts +616 -0
  28. package/3p/pi-plannotator/apps/pi-extension/plannotator-events.ts +342 -0
  29. package/3p/pi-plannotator/apps/pi-extension/plannotator.json +12 -0
  30. package/3p/pi-plannotator/apps/pi-extension/server/agent-jobs.ts +515 -0
  31. package/3p/pi-plannotator/apps/pi-extension/server/ai-runtime.ts +169 -0
  32. package/3p/pi-plannotator/apps/pi-extension/server/annotations.ts +85 -0
  33. package/3p/pi-plannotator/apps/pi-extension/server/external-annotations.ts +189 -0
  34. package/3p/pi-plannotator/apps/pi-extension/server/handlers.ts +210 -0
  35. package/3p/pi-plannotator/apps/pi-extension/server/helpers.ts +78 -0
  36. package/3p/pi-plannotator/apps/pi-extension/server/ide.ts +46 -0
  37. package/3p/pi-plannotator/apps/pi-extension/server/integrations.ts +195 -0
  38. package/3p/pi-plannotator/apps/pi-extension/server/network.test.ts +158 -0
  39. package/3p/pi-plannotator/apps/pi-extension/server/network.ts +268 -0
  40. package/3p/pi-plannotator/apps/pi-extension/server/pr.ts +126 -0
  41. package/3p/pi-plannotator/apps/pi-extension/server/project.ts +64 -0
  42. package/3p/pi-plannotator/apps/pi-extension/server/reference.ts +362 -0
  43. package/3p/pi-plannotator/apps/pi-extension/server/serverAnnotate.ts +199 -0
  44. package/3p/pi-plannotator/apps/pi-extension/server/serverPlan.ts +505 -0
  45. package/3p/pi-plannotator/apps/pi-extension/server/serverReview.ts +1229 -0
  46. package/3p/pi-plannotator/apps/pi-extension/server/vcs.ts +121 -0
  47. package/3p/pi-plannotator/apps/pi-extension/server.test.ts +966 -0
  48. package/3p/pi-plannotator/apps/pi-extension/server.ts +44 -0
  49. package/3p/pi-plannotator/apps/pi-extension/tool-scope.test.ts +88 -0
  50. package/3p/pi-plannotator/apps/pi-extension/tool-scope.ts +39 -0
  51. package/3p/pi-plannotator/apps/pi-extension/tsconfig.json +16 -0
  52. package/3p/pi-plannotator/apps/pi-extension/vendor.sh +48 -0
  53. package/3p/pi-plannotator/package.json +53 -0
  54. package/3p/pi-plannotator/packages/ai/ai.test.ts +1407 -0
  55. package/3p/pi-plannotator/packages/ai/base-session.ts +94 -0
  56. package/3p/pi-plannotator/packages/ai/context.ts +250 -0
  57. package/3p/pi-plannotator/packages/ai/endpoints.ts +326 -0
  58. package/3p/pi-plannotator/packages/ai/index.ts +105 -0
  59. package/3p/pi-plannotator/packages/ai/package.json +21 -0
  60. package/3p/pi-plannotator/packages/ai/provider.ts +103 -0
  61. package/3p/pi-plannotator/packages/ai/providers/claude-agent-sdk.ts +447 -0
  62. package/3p/pi-plannotator/packages/ai/providers/codex-sdk.ts +430 -0
  63. package/3p/pi-plannotator/packages/ai/providers/command-path.ts +115 -0
  64. package/3p/pi-plannotator/packages/ai/providers/opencode-sdk.ts +546 -0
  65. package/3p/pi-plannotator/packages/ai/providers/pi-events.ts +110 -0
  66. package/3p/pi-plannotator/packages/ai/providers/pi-sdk-node.ts +425 -0
  67. package/3p/pi-plannotator/packages/ai/providers/pi-sdk.ts +469 -0
  68. package/3p/pi-plannotator/packages/ai/session-manager.ts +195 -0
  69. package/3p/pi-plannotator/packages/ai/tsconfig.json +15 -0
  70. package/3p/pi-plannotator/packages/ai/types.ts +379 -0
  71. package/3p/pi-plannotator/packages/server/agent-jobs.ts +538 -0
  72. package/3p/pi-plannotator/packages/server/agent-review-message.test.ts +135 -0
  73. package/3p/pi-plannotator/packages/server/agent-review-message.ts +243 -0
  74. package/3p/pi-plannotator/packages/server/ai-runtime.ts +108 -0
  75. package/3p/pi-plannotator/packages/server/annotate.ts +401 -0
  76. package/3p/pi-plannotator/packages/server/browser.test.ts +87 -0
  77. package/3p/pi-plannotator/packages/server/browser.ts +245 -0
  78. package/3p/pi-plannotator/packages/server/claude-review.ts +352 -0
  79. package/3p/pi-plannotator/packages/server/code-nav.ts +73 -0
  80. package/3p/pi-plannotator/packages/server/codex-review-schema.json +41 -0
  81. package/3p/pi-plannotator/packages/server/codex-review.ts +330 -0
  82. package/3p/pi-plannotator/packages/server/config.ts +8 -0
  83. package/3p/pi-plannotator/packages/server/draft.ts +1 -0
  84. package/3p/pi-plannotator/packages/server/editor-annotations.ts +76 -0
  85. package/3p/pi-plannotator/packages/server/external-annotations.test.ts +18 -0
  86. package/3p/pi-plannotator/packages/server/external-annotations.ts +207 -0
  87. package/3p/pi-plannotator/packages/server/git.ts +141 -0
  88. package/3p/pi-plannotator/packages/server/goal-setup.test.ts +55 -0
  89. package/3p/pi-plannotator/packages/server/goal-setup.ts +248 -0
  90. package/3p/pi-plannotator/packages/server/ide.ts +43 -0
  91. package/3p/pi-plannotator/packages/server/image.test.ts +63 -0
  92. package/3p/pi-plannotator/packages/server/image.ts +66 -0
  93. package/3p/pi-plannotator/packages/server/index.ts +648 -0
  94. package/3p/pi-plannotator/packages/server/integrations.test.ts +172 -0
  95. package/3p/pi-plannotator/packages/server/integrations.ts +214 -0
  96. package/3p/pi-plannotator/packages/server/jj.test.ts +69 -0
  97. package/3p/pi-plannotator/packages/server/jj.ts +86 -0
  98. package/3p/pi-plannotator/packages/server/p4.ts +417 -0
  99. package/3p/pi-plannotator/packages/server/package.json +40 -0
  100. package/3p/pi-plannotator/packages/server/path-utils.ts +18 -0
  101. package/3p/pi-plannotator/packages/server/pr.ts +146 -0
  102. package/3p/pi-plannotator/packages/server/project.test.ts +115 -0
  103. package/3p/pi-plannotator/packages/server/project.ts +45 -0
  104. package/3p/pi-plannotator/packages/server/reference-handlers.ts +404 -0
  105. package/3p/pi-plannotator/packages/server/remote.test.ts +150 -0
  106. package/3p/pi-plannotator/packages/server/remote.ts +74 -0
  107. package/3p/pi-plannotator/packages/server/repo.ts +80 -0
  108. package/3p/pi-plannotator/packages/server/resolve-file.test.ts +310 -0
  109. package/3p/pi-plannotator/packages/server/review-workspace.test.ts +1032 -0
  110. package/3p/pi-plannotator/packages/server/review-workspace.ts +48 -0
  111. package/3p/pi-plannotator/packages/server/review.ts +1318 -0
  112. package/3p/pi-plannotator/packages/server/sessions.ts +111 -0
  113. package/3p/pi-plannotator/packages/server/share-url.ts +53 -0
  114. package/3p/pi-plannotator/packages/server/shared-handlers.test.ts +43 -0
  115. package/3p/pi-plannotator/packages/server/shared-handlers.ts +177 -0
  116. package/3p/pi-plannotator/packages/server/storage.test.ts +176 -0
  117. package/3p/pi-plannotator/packages/server/storage.ts +17 -0
  118. package/3p/pi-plannotator/packages/server/tour/tour-review.test.ts +146 -0
  119. package/3p/pi-plannotator/packages/server/tour/tour-review.ts +604 -0
  120. package/3p/pi-plannotator/packages/server/tsconfig.json +15 -0
  121. package/3p/pi-plannotator/packages/server/vcs.test.ts +48 -0
  122. package/3p/pi-plannotator/packages/server/vcs.ts +80 -0
  123. package/3p/pi-plannotator/packages/shared/agent-jobs.ts +132 -0
  124. package/3p/pi-plannotator/packages/shared/agents.ts +53 -0
  125. package/3p/pi-plannotator/packages/shared/annotate-args.test.ts +386 -0
  126. package/3p/pi-plannotator/packages/shared/annotate-args.ts +107 -0
  127. package/3p/pi-plannotator/packages/shared/at-reference.test.ts +99 -0
  128. package/3p/pi-plannotator/packages/shared/at-reference.ts +52 -0
  129. package/3p/pi-plannotator/packages/shared/checklist.ts +52 -0
  130. package/3p/pi-plannotator/packages/shared/code-file.test.ts +112 -0
  131. package/3p/pi-plannotator/packages/shared/code-file.ts +41 -0
  132. package/3p/pi-plannotator/packages/shared/code-nav.test.ts +515 -0
  133. package/3p/pi-plannotator/packages/shared/code-nav.ts +436 -0
  134. package/3p/pi-plannotator/packages/shared/compress.ts +51 -0
  135. package/3p/pi-plannotator/packages/shared/config.ts +262 -0
  136. package/3p/pi-plannotator/packages/shared/crypto.test.ts +172 -0
  137. package/3p/pi-plannotator/packages/shared/crypto.ts +97 -0
  138. package/3p/pi-plannotator/packages/shared/data-dir.ts +42 -0
  139. package/3p/pi-plannotator/packages/shared/diff-paths.test.ts +30 -0
  140. package/3p/pi-plannotator/packages/shared/diff-paths.ts +137 -0
  141. package/3p/pi-plannotator/packages/shared/draft.ts +64 -0
  142. package/3p/pi-plannotator/packages/shared/external-annotation.ts +397 -0
  143. package/3p/pi-plannotator/packages/shared/extract-code-paths.test.ts +59 -0
  144. package/3p/pi-plannotator/packages/shared/extract-code-paths.ts +66 -0
  145. package/3p/pi-plannotator/packages/shared/favicon.ts +5 -0
  146. package/3p/pi-plannotator/packages/shared/feedback-templates.test.ts +65 -0
  147. package/3p/pi-plannotator/packages/shared/feedback-templates.ts +29 -0
  148. package/3p/pi-plannotator/packages/shared/goal-setup.test.ts +231 -0
  149. package/3p/pi-plannotator/packages/shared/goal-setup.ts +336 -0
  150. package/3p/pi-plannotator/packages/shared/html-to-markdown.test.ts +62 -0
  151. package/3p/pi-plannotator/packages/shared/html-to-markdown.ts +32 -0
  152. package/3p/pi-plannotator/packages/shared/improvement-hooks.test.ts +135 -0
  153. package/3p/pi-plannotator/packages/shared/improvement-hooks.ts +115 -0
  154. package/3p/pi-plannotator/packages/shared/integrations-common.ts +243 -0
  155. package/3p/pi-plannotator/packages/shared/jj-core.test.ts +236 -0
  156. package/3p/pi-plannotator/packages/shared/jj-core.ts +433 -0
  157. package/3p/pi-plannotator/packages/shared/package.json +55 -0
  158. package/3p/pi-plannotator/packages/shared/pfm-reminder.test.ts +88 -0
  159. package/3p/pi-plannotator/packages/shared/pfm-reminder.ts +80 -0
  160. package/3p/pi-plannotator/packages/shared/pr-github.ts +661 -0
  161. package/3p/pi-plannotator/packages/shared/pr-gitlab.test.ts +202 -0
  162. package/3p/pi-plannotator/packages/shared/pr-gitlab.ts +620 -0
  163. package/3p/pi-plannotator/packages/shared/pr-provider.test.ts +266 -0
  164. package/3p/pi-plannotator/packages/shared/pr-provider.ts +123 -0
  165. package/3p/pi-plannotator/packages/shared/pr-stack.test.ts +104 -0
  166. package/3p/pi-plannotator/packages/shared/pr-stack.ts +194 -0
  167. package/3p/pi-plannotator/packages/shared/pr-types.ts +326 -0
  168. package/3p/pi-plannotator/packages/shared/project.ts +71 -0
  169. package/3p/pi-plannotator/packages/shared/prompts-integration.test.ts +421 -0
  170. package/3p/pi-plannotator/packages/shared/prompts.test.ts +504 -0
  171. package/3p/pi-plannotator/packages/shared/prompts.ts +247 -0
  172. package/3p/pi-plannotator/packages/shared/reference-common.ts +87 -0
  173. package/3p/pi-plannotator/packages/shared/repo.ts +71 -0
  174. package/3p/pi-plannotator/packages/shared/resolve-file.test.ts +113 -0
  175. package/3p/pi-plannotator/packages/shared/resolve-file.ts +509 -0
  176. package/3p/pi-plannotator/packages/shared/review-args.test.ts +64 -0
  177. package/3p/pi-plannotator/packages/shared/review-args.ts +85 -0
  178. package/3p/pi-plannotator/packages/shared/review-core.test.ts +286 -0
  179. package/3p/pi-plannotator/packages/shared/review-core.ts +895 -0
  180. package/3p/pi-plannotator/packages/shared/review-workspace-node.ts +230 -0
  181. package/3p/pi-plannotator/packages/shared/review-workspace.ts +436 -0
  182. package/3p/pi-plannotator/packages/shared/semantic-diff-types.ts +76 -0
  183. package/3p/pi-plannotator/packages/shared/semantic-diff.test.ts +322 -0
  184. package/3p/pi-plannotator/packages/shared/semantic-diff.ts +520 -0
  185. package/3p/pi-plannotator/packages/shared/storage.ts +378 -0
  186. package/3p/pi-plannotator/packages/shared/tour.ts +61 -0
  187. package/3p/pi-plannotator/packages/shared/tsconfig.json +15 -0
  188. package/3p/pi-plannotator/packages/shared/types.ts +29 -0
  189. package/3p/pi-plannotator/packages/shared/url-to-markdown.test.ts +177 -0
  190. package/3p/pi-plannotator/packages/shared/url-to-markdown.ts +351 -0
  191. package/3p/pi-plannotator/packages/shared/vcs-core.test.ts +332 -0
  192. package/3p/pi-plannotator/packages/shared/vcs-core.ts +482 -0
  193. package/3p/pi-plannotator/packages/shared/worktree-pool.test.ts +162 -0
  194. package/3p/pi-plannotator/packages/shared/worktree-pool.ts +103 -0
  195. package/3p/pi-plannotator/packages/shared/worktree.ts +119 -0
  196. package/3p/pi-subagents/package.json +50 -0
  197. package/3p/pi-subagents/src/agent-manager.ts +413 -0
  198. package/3p/pi-subagents/src/agent-runner.ts +502 -0
  199. package/3p/pi-subagents/src/agent-types.ts +248 -0
  200. package/3p/pi-subagents/src/context.ts +58 -0
  201. package/3p/pi-subagents/src/cross-extension-rpc.ts +135 -0
  202. package/3p/pi-subagents/src/custom-agents.ts +137 -0
  203. package/3p/pi-subagents/src/default-agents.ts +144 -0
  204. package/3p/pi-subagents/src/env.ts +33 -0
  205. package/3p/pi-subagents/src/group-join.ts +141 -0
  206. package/3p/pi-subagents/src/index.ts +1811 -0
  207. package/3p/pi-subagents/src/invocation-config.ts +40 -0
  208. package/3p/pi-subagents/src/memory.ts +165 -0
  209. package/3p/pi-subagents/src/model-resolver.ts +81 -0
  210. package/3p/pi-subagents/src/output-file.ts +77 -0
  211. package/3p/pi-subagents/src/prompts.ts +85 -0
  212. package/3p/pi-subagents/src/skill-loader.ts +79 -0
  213. package/3p/pi-subagents/src/types.ts +111 -0
  214. package/3p/pi-subagents/src/ui/agent-widget.ts +496 -0
  215. package/3p/pi-subagents/src/ui/conversation-viewer.ts +250 -0
  216. package/3p/pi-subagents/src/worktree.ts +162 -0
  217. package/3p/pi-tasks/package.json +52 -0
  218. package/3p/pi-tasks/src/auto-clear.ts +91 -0
  219. package/3p/pi-tasks/src/index.ts +1150 -0
  220. package/3p/pi-tasks/src/process-tracker.ts +140 -0
  221. package/3p/pi-tasks/src/reminder-cadence.ts +90 -0
  222. package/3p/pi-tasks/src/task-store.ts +324 -0
  223. package/3p/pi-tasks/src/tasks-config.ts +27 -0
  224. package/3p/pi-tasks/src/types.ts +40 -0
  225. package/3p/pi-tasks/src/ui/settings-menu.ts +152 -0
  226. package/3p/pi-tasks/src/ui/task-widget.ts +296 -0
  227. package/AGENTS.md +28 -0
  228. package/LICENSE +201 -0
  229. package/extensions/orchestrator/agents/brainstorm-reviewer.ts +77 -0
  230. package/extensions/orchestrator/agents/code-reviewer.ts +89 -0
  231. package/extensions/orchestrator/agents/explore.ts +33 -0
  232. package/extensions/orchestrator/agents/librarian.ts +43 -0
  233. package/extensions/orchestrator/agents/plan-reviewer.ts +75 -0
  234. package/extensions/orchestrator/agents/planner.ts +61 -0
  235. package/extensions/orchestrator/agents/registry.ts +156 -0
  236. package/extensions/orchestrator/agents/task.ts +50 -0
  237. package/extensions/orchestrator/agents/tool-routing.ts +84 -0
  238. package/extensions/orchestrator/ast-search.ts +85 -0
  239. package/extensions/orchestrator/cbm.ts +330 -0
  240. package/extensions/orchestrator/command-handlers.test.ts +163 -0
  241. package/extensions/orchestrator/command-handlers.ts +116 -0
  242. package/extensions/orchestrator/commands.test.ts +81 -0
  243. package/extensions/orchestrator/commands.ts +75 -0
  244. package/extensions/orchestrator/config.test.ts +221 -0
  245. package/extensions/orchestrator/config.ts +230 -0
  246. package/extensions/orchestrator/context.test.ts +293 -0
  247. package/extensions/orchestrator/context.ts +206 -0
  248. package/extensions/orchestrator/event-handlers.test.ts +190 -0
  249. package/extensions/orchestrator/event-handlers.ts +1416 -0
  250. package/extensions/orchestrator/exa.ts +104 -0
  251. package/extensions/orchestrator/flant-infra.ts +486 -0
  252. package/extensions/orchestrator/index.ts +80 -0
  253. package/extensions/orchestrator/integration.test.ts +1214 -0
  254. package/extensions/orchestrator/orchestrator.test.ts +252 -0
  255. package/extensions/orchestrator/orchestrator.ts +538 -0
  256. package/extensions/orchestrator/phases/brainstorm.test.ts +15 -0
  257. package/extensions/orchestrator/phases/brainstorm.ts +273 -0
  258. package/extensions/orchestrator/phases/implementation.ts +40 -0
  259. package/extensions/orchestrator/phases/machine.test.ts +293 -0
  260. package/extensions/orchestrator/phases/machine.ts +209 -0
  261. package/extensions/orchestrator/phases/planning.ts +255 -0
  262. package/extensions/orchestrator/phases/review.ts +193 -0
  263. package/extensions/orchestrator/plannotator.ts +56 -0
  264. package/extensions/orchestrator/pp-menu.ts +866 -0
  265. package/extensions/orchestrator/state.test.ts +343 -0
  266. package/extensions/orchestrator/state.ts +237 -0
  267. package/extensions/orchestrator/validate-artifacts.test.ts +88 -0
  268. package/extensions/orchestrator/validate-artifacts.ts +272 -0
  269. package/extensions/orchestrator/vendor.d.ts +26 -0
  270. package/package.json +73 -0
  271. package/scripts/postinstall.sh +18 -0
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Browser-safe PR/MR types and pure helpers.
3
+ *
4
+ * Split out from pr-provider.ts so the review UI can import types,
5
+ * label helpers, and URL parsing without dragging the GitHub/GitLab
6
+ * server implementations (and their Node-only dependencies) through
7
+ * the browser bundle. pr-provider.ts re-exports nothing from here;
8
+ * server-side dispatch lives there.
9
+ */
10
+
11
+ // --- Runtime Types ---
12
+
13
+ export interface CommandResult {
14
+ stdout: string;
15
+ stderr: string;
16
+ exitCode: number;
17
+ }
18
+
19
+ export interface PRRuntime {
20
+ runCommand: (
21
+ cmd: string,
22
+ args: string[],
23
+ ) => Promise<CommandResult>;
24
+ runCommandWithInput?: (
25
+ cmd: string,
26
+ args: string[],
27
+ input: string,
28
+ ) => Promise<CommandResult>;
29
+ }
30
+
31
+ // --- Platform Types ---
32
+
33
+ export type Platform = "github" | "gitlab";
34
+
35
+ /** GitHub PR reference */
36
+ export interface GithubPRRef {
37
+ platform: "github";
38
+ host: string;
39
+ owner: string;
40
+ repo: string;
41
+ number: number;
42
+ }
43
+
44
+ /** GitLab MR reference */
45
+ export interface GitlabMRRef {
46
+ platform: "gitlab";
47
+ host: string;
48
+ projectPath: string;
49
+ iid: number;
50
+ }
51
+
52
+ /** Discriminated union — auto-detected from URL */
53
+ export type PRRef = GithubPRRef | GitlabMRRef;
54
+
55
+ /** GitHub PR metadata */
56
+ export interface GithubPRMetadata {
57
+ platform: "github";
58
+ host: string;
59
+ owner: string;
60
+ repo: string;
61
+ number: number;
62
+ /** GraphQL node ID for the PR — used for markFileAsViewed mutations */
63
+ prNodeId?: string;
64
+ title: string;
65
+ author: string;
66
+ baseBranch: string;
67
+ headBranch: string;
68
+ /** Repository default branch, used to infer whether this PR targets another PR branch. */
69
+ defaultBranch?: string;
70
+ baseSha: string;
71
+ headSha: string;
72
+ /** Merge-base SHA — the common ancestor commit used to compute the PR diff. Differs from baseSha when the base branch has moved. */
73
+ mergeBaseSha?: string;
74
+ url: string;
75
+ }
76
+
77
+ /** GitLab MR metadata */
78
+ export interface GitlabMRMetadata {
79
+ platform: "gitlab";
80
+ host: string;
81
+ projectPath: string;
82
+ iid: number;
83
+ title: string;
84
+ author: string;
85
+ baseBranch: string;
86
+ headBranch: string;
87
+ /** Project default branch, used to infer whether this MR targets another MR branch. */
88
+ defaultBranch?: string;
89
+ baseSha: string;
90
+ headSha: string;
91
+ /** Merge-base SHA — the common ancestor commit used to compute the MR diff. */
92
+ mergeBaseSha?: string;
93
+ url: string;
94
+ }
95
+
96
+ /** Discriminated union — downstream gets type narrowing for free */
97
+ export type PRMetadata = GithubPRMetadata | GitlabMRMetadata;
98
+
99
+ // --- PR Context Types (platform-agnostic) ---
100
+
101
+ export interface PRComment {
102
+ id: string;
103
+ author: string;
104
+ body: string;
105
+ createdAt: string;
106
+ url: string;
107
+ }
108
+
109
+ export interface PRReview {
110
+ id: string;
111
+ author: string;
112
+ state: string;
113
+ body: string;
114
+ submittedAt: string;
115
+ url?: string;
116
+ }
117
+
118
+ export interface PRCheck {
119
+ name: string;
120
+ status: string;
121
+ conclusion: string | null;
122
+ workflowName: string;
123
+ detailsUrl: string;
124
+ }
125
+
126
+ export interface PRLinkedIssue {
127
+ number: number;
128
+ url: string;
129
+ repo: string;
130
+ }
131
+
132
+ export interface PRThreadComment {
133
+ id: string;
134
+ author: string;
135
+ body: string;
136
+ createdAt: string;
137
+ url: string;
138
+ diffHunk?: string;
139
+ }
140
+
141
+ export interface PRReviewThread {
142
+ id: string;
143
+ isResolved: boolean;
144
+ isOutdated: boolean;
145
+ path: string;
146
+ line: number | null;
147
+ startLine: number | null;
148
+ diffSide: 'LEFT' | 'RIGHT' | null;
149
+ comments: PRThreadComment[];
150
+ }
151
+
152
+ export interface PRContext {
153
+ body: string;
154
+ state: string;
155
+ isDraft: boolean;
156
+ labels: Array<{ name: string; color: string }>;
157
+ reviewDecision: string;
158
+ mergeable: string;
159
+ mergeStateStatus: string;
160
+ comments: PRComment[];
161
+ reviews: PRReview[];
162
+ reviewThreads: PRReviewThread[];
163
+ checks: PRCheck[];
164
+ linkedIssues: PRLinkedIssue[];
165
+ }
166
+
167
+ export interface PRReviewFileComment {
168
+ path: string;
169
+ line: number;
170
+ side: "LEFT" | "RIGHT";
171
+ body: string;
172
+ start_line?: number;
173
+ start_side?: "LEFT" | "RIGHT";
174
+ }
175
+
176
+ export type PRDiffScope = "layer" | "full-stack";
177
+
178
+ export interface PRDiffScopeOption {
179
+ id: PRDiffScope;
180
+ label: string;
181
+ description: string;
182
+ enabled: boolean;
183
+ }
184
+
185
+ export interface PRStackInfo {
186
+ isStacked: boolean;
187
+ baseBranch: string;
188
+ defaultBranch?: string;
189
+ label: string;
190
+ source: "branch-inferred" | "tree-discovered" | "github-native" | "gitlab-native" | "graphite" | "ghstack";
191
+ }
192
+
193
+ export interface PRStackNode {
194
+ branch: string;
195
+ number?: number;
196
+ title?: string;
197
+ url?: string;
198
+ isCurrent: boolean;
199
+ isDefaultBranch: boolean;
200
+ state?: 'open' | 'merged' | 'closed';
201
+ }
202
+
203
+ export interface PRStackTree {
204
+ nodes: PRStackNode[];
205
+ }
206
+
207
+ export interface PRListItem {
208
+ id: string;
209
+ number: number;
210
+ title: string;
211
+ author: string;
212
+ url: string;
213
+ baseBranch: string;
214
+ state: 'open' | 'closed' | 'merged';
215
+ }
216
+
217
+ // --- Label Helpers ---
218
+ // Accept either PRRef or PRMetadata (both have `platform` discriminant)
219
+
220
+ type HasPlatform = PRRef | PRMetadata;
221
+
222
+ /** "GitHub" or "GitLab" */
223
+ export function getPlatformLabel(m: HasPlatform): string {
224
+ return m.platform === "github" ? "GitHub" : "GitLab";
225
+ }
226
+
227
+ /** "PR" or "MR" */
228
+ export function getMRLabel(m: HasPlatform): string {
229
+ return m.platform === "github" ? "PR" : "MR";
230
+ }
231
+
232
+ /** "#123" or "!42" */
233
+ export function getMRNumberLabel(m: HasPlatform): string {
234
+ if (m.platform === "github") return `#${m.number}`;
235
+ return `!${m.iid}`;
236
+ }
237
+
238
+ /** "owner/repo" or "group/project" */
239
+ export function getDisplayRepo(m: HasPlatform): string {
240
+ if (m.platform === "github") return `${m.owner}/${m.repo}`;
241
+ return m.projectPath;
242
+ }
243
+
244
+ /** Reconstruct a PRRef from metadata */
245
+ export function prRefFromMetadata(m: PRMetadata): PRRef {
246
+ if (m.platform === "github") {
247
+ return { platform: "github", host: m.host, owner: m.owner, repo: m.repo, number: m.number };
248
+ }
249
+ return { platform: "gitlab", host: m.host, projectPath: m.projectPath, iid: m.iid };
250
+ }
251
+
252
+ export function isSameProject(a: PRRef, b: PRRef): boolean {
253
+ if (a.platform !== b.platform) return false;
254
+ if (a.platform === "github" && b.platform === "github") {
255
+ return a.host === b.host && a.owner === b.owner && a.repo === b.repo;
256
+ }
257
+ if (a.platform === "gitlab" && b.platform === "gitlab") {
258
+ return a.host === b.host && a.projectPath === b.projectPath;
259
+ }
260
+ return false;
261
+ }
262
+
263
+ /** CLI tool name for the platform */
264
+ export function getCliName(ref: PRRef): string {
265
+ return ref.platform === "github" ? "gh" : "glab";
266
+ }
267
+
268
+ /** Install URL for the platform CLI */
269
+ export function getCliInstallUrl(ref: PRRef): string {
270
+ return ref.platform === "github"
271
+ ? "https://cli.github.com"
272
+ : "https://gitlab.com/gitlab-org/cli";
273
+ }
274
+
275
+ /** Encode a file path for use in platform API URLs */
276
+ export function encodeApiFilePath(filePath: string): string {
277
+ return encodeURIComponent(filePath);
278
+ }
279
+
280
+ // --- URL Parsing ---
281
+
282
+ /**
283
+ * Parse a PR/MR URL into its components. Auto-detects platform.
284
+ *
285
+ * Handles:
286
+ * - GitHub: https://github.com/owner/repo/pull/123[/files|/commits]
287
+ * - GitHub Enterprise: https://ghe.company.com/owner/repo/pull/123
288
+ * - GitLab: https://gitlab.com/group/subgroup/project/-/merge_requests/42[/diffs]
289
+ * - Self-hosted GitLab: https://gitlab.mycompany.com/group/project/-/merge_requests/42
290
+ *
291
+ * GitLab is checked first because `/-/merge_requests/` is unambiguous,
292
+ * while `/pull/` could theoretically appear on any host.
293
+ */
294
+ export function parsePRUrl(url: string): PRRef | null {
295
+ if (!url) return null;
296
+
297
+ // GitLab: https://{host}/{projectPath}/-/merge_requests/{iid}[/...]
298
+ // Checked first — `/-/merge_requests/` is the most specific pattern.
299
+ const glMatch = url.match(
300
+ /^https?:\/\/([^/]+)\/(.+?)\/-\/merge_requests\/(\d+)/,
301
+ );
302
+ if (glMatch) {
303
+ return {
304
+ platform: "gitlab",
305
+ host: glMatch[1],
306
+ projectPath: glMatch[2],
307
+ iid: parseInt(glMatch[3], 10),
308
+ };
309
+ }
310
+
311
+ // GitHub (including GHE): https://{host}/{owner}/{repo}/pull/{number}[/...]
312
+ const ghMatch = url.match(
313
+ /^https?:\/\/([^/]+)\/([^/]+)\/([^/]+)\/pull\/(\d+)/,
314
+ );
315
+ if (ghMatch) {
316
+ return {
317
+ platform: "github",
318
+ host: ghMatch[1],
319
+ owner: ghMatch[2],
320
+ repo: ghMatch[3],
321
+ number: parseInt(ghMatch[4], 10),
322
+ };
323
+ }
324
+
325
+ return null;
326
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Project Utility — Pure Functions
3
+ *
4
+ * String sanitization and path extraction helpers.
5
+ * Runtime-agnostic: no Bun or Node-specific APIs.
6
+ */
7
+
8
+ /**
9
+ * Sanitize a string for use as a tag
10
+ * - lowercase
11
+ * - replace spaces/underscores with hyphens
12
+ * - remove special characters
13
+ * - trim to reasonable length
14
+ */
15
+ export function sanitizeTag(name: string): string | null {
16
+ if (!name || typeof name !== "string") return null;
17
+
18
+ const sanitized = name
19
+ .toLowerCase()
20
+ .trim()
21
+ .replace(/[\s_]+/g, "-") // spaces/underscores -> hyphens
22
+ .replace(/[^a-z0-9-]/g, "") // remove special chars
23
+ .replace(/-+/g, "-") // collapse multiple hyphens
24
+ .replace(/^-|-$/g, "") // trim leading/trailing hyphens
25
+ .slice(0, 30); // max 30 chars
26
+
27
+ return sanitized.length >= 2 ? sanitized : null;
28
+ }
29
+
30
+ /**
31
+ * Extract repo name from a git root path
32
+ */
33
+ export function extractRepoName(gitRootPath: string): string | null {
34
+ if (!gitRootPath || typeof gitRootPath !== "string") return null;
35
+
36
+ const trimmed = gitRootPath.trim().replace(/\/+$/, ""); // remove trailing slashes
37
+ const parts = trimmed.split("/");
38
+ const name = parts[parts.length - 1];
39
+
40
+ return sanitizeTag(name);
41
+ }
42
+
43
+ /**
44
+ * Extract directory name from a path
45
+ */
46
+ export function extractDirName(path: string): string | null {
47
+ if (!path || typeof path !== "string") return null;
48
+
49
+ const trimmed = path.trim().replace(/\/+$/, "");
50
+ if (trimmed === "" || trimmed === "/") return null;
51
+
52
+ const parts = trimmed.split("/");
53
+ const name = parts[parts.length - 1];
54
+
55
+ // Skip generic names
56
+ const skipNames = new Set(["home", "users", "user", "root", "tmp", "var"]);
57
+ if (skipNames.has(name.toLowerCase())) return null;
58
+
59
+ return sanitizeTag(name);
60
+ }
61
+
62
+ /**
63
+ * Extract hostname from a URL string, or return the original string on failure.
64
+ */
65
+ export function hostnameOrFallback(url: string): string {
66
+ try {
67
+ return new URL(url).hostname;
68
+ } catch {
69
+ return url;
70
+ }
71
+ }