@agimon-ai/doompi-git 0.0.1-alpha.6 → 0.0.1-alpha.61

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 +32 -2
  2. package/dist/apiContracts.cjs +387 -0
  3. package/dist/apiContracts.cjs.map +1 -0
  4. package/dist/{schemas/apiContracts.d.mts → apiContracts.d.mts} +2 -2
  5. package/dist/{schemas/apiContracts.d.mts.map → apiContracts.d.mts.map} +1 -1
  6. package/dist/apiContracts.mjs +382 -0
  7. package/dist/apiContracts.mjs.map +1 -0
  8. package/dist/extensions/pi.cjs +104 -1
  9. package/dist/extensions/pi.cjs.map +1 -1
  10. package/dist/extensions/pi.d.mts +4 -4
  11. package/dist/extensions/pi.d.mts.map +1 -1
  12. package/dist/extensions/pi.mjs +99 -1
  13. package/dist/extensions/pi.mjs.map +1 -1
  14. package/dist/extensions/server.cjs +1827 -1
  15. package/dist/extensions/server.cjs.map +1 -1
  16. package/dist/extensions/server.d.mts +3 -3
  17. package/dist/extensions/server.d.mts.map +1 -1
  18. package/dist/extensions/server.mjs +1819 -1
  19. package/dist/extensions/server.mjs.map +1 -1
  20. package/dist/extensions/web.mjs +2639 -0
  21. package/dist/extensions/web.mjs.map +1 -0
  22. package/dist/gitDependencies-BoG74oMf.mjs +22 -0
  23. package/dist/gitDependencies-BoG74oMf.mjs.map +1 -0
  24. package/dist/gitDependencies-Dfgseruc.cjs +33 -0
  25. package/dist/gitDependencies-Dfgseruc.cjs.map +1 -0
  26. package/dist/index-D79MSCee.d.mts +145 -0
  27. package/dist/index-D79MSCee.d.mts.map +1 -0
  28. package/dist/index.cjs +4 -1
  29. package/dist/index.d.mts +1 -3
  30. package/dist/index.mjs +2 -1
  31. package/dist/runWorktree-B8p9ImZj.mjs +303 -0
  32. package/dist/runWorktree-B8p9ImZj.mjs.map +1 -0
  33. package/dist/runWorktree-B_UUez5g.cjs +374 -0
  34. package/dist/runWorktree-B_UUez5g.cjs.map +1 -0
  35. package/dist/worktreeOperations-CLhK9OWr.cjs +1236 -0
  36. package/dist/worktreeOperations-CLhK9OWr.cjs.map +1 -0
  37. package/dist/worktreeOperations-CaawSXAN.mjs +1080 -0
  38. package/dist/worktreeOperations-CaawSXAN.mjs.map +1 -0
  39. package/llms.txt +4 -0
  40. package/package.json +43 -34
  41. package/src/prompts/doompi-use-git/SKILL.md +21 -1
  42. package/dist/_virtual/_rolldown/runtime.cjs +0 -1
  43. package/dist/api-contracts.cjs +0 -1
  44. package/dist/api-contracts.d.cts +0 -2
  45. package/dist/api-contracts.d.mts +0 -2
  46. package/dist/api-contracts.mjs +0 -1
  47. package/dist/constants/git.cjs +0 -2
  48. package/dist/constants/git.cjs.map +0 -1
  49. package/dist/constants/git.mjs +0 -2
  50. package/dist/constants/git.mjs.map +0 -1
  51. package/dist/controllers/gitCommand.cjs +0 -2
  52. package/dist/controllers/gitCommand.cjs.map +0 -1
  53. package/dist/controllers/gitCommand.mjs +0 -2
  54. package/dist/controllers/gitCommand.mjs.map +0 -1
  55. package/dist/controllers/gitSession.cjs +0 -2
  56. package/dist/controllers/gitSession.cjs.map +0 -1
  57. package/dist/controllers/gitSession.mjs +0 -2
  58. package/dist/controllers/gitSession.mjs.map +0 -1
  59. package/dist/controllers/hubApi.cjs +0 -2
  60. package/dist/controllers/hubApi.cjs.map +0 -1
  61. package/dist/controllers/hubApi.mjs +0 -2
  62. package/dist/controllers/hubApi.mjs.map +0 -1
  63. package/dist/controllers/worktreesChannel.cjs +0 -2
  64. package/dist/controllers/worktreesChannel.cjs.map +0 -1
  65. package/dist/controllers/worktreesChannel.mjs +0 -2
  66. package/dist/controllers/worktreesChannel.mjs.map +0 -1
  67. package/dist/extensions/pi.d.cts +0 -6
  68. package/dist/extensions/pi.d.cts.map +0 -1
  69. package/dist/extensions/server.d.cts +0 -5
  70. package/dist/extensions/server.d.cts.map +0 -1
  71. package/dist/index.d.cts +0 -4
  72. package/dist/schemas/apiContracts.cjs +0 -2
  73. package/dist/schemas/apiContracts.cjs.map +0 -1
  74. package/dist/schemas/apiContracts.d.cts +0 -53
  75. package/dist/schemas/apiContracts.d.cts.map +0 -1
  76. package/dist/schemas/apiContracts.mjs +0 -2
  77. package/dist/schemas/apiContracts.mjs.map +0 -1
  78. package/dist/schemas/runWorktreeTool.cjs +0 -2
  79. package/dist/schemas/runWorktreeTool.cjs.map +0 -1
  80. package/dist/schemas/runWorktreeTool.mjs +0 -2
  81. package/dist/schemas/runWorktreeTool.mjs.map +0 -1
  82. package/dist/services/atomicJson/index.cjs +0 -2
  83. package/dist/services/atomicJson/index.cjs.map +0 -1
  84. package/dist/services/atomicJson/index.mjs +0 -2
  85. package/dist/services/atomicJson/index.mjs.map +0 -1
  86. package/dist/services/compositionMirror/index.cjs +0 -2
  87. package/dist/services/compositionMirror/index.cjs.map +0 -1
  88. package/dist/services/compositionMirror/index.mjs +0 -2
  89. package/dist/services/compositionMirror/index.mjs.map +0 -1
  90. package/dist/services/errors/index.cjs +0 -2
  91. package/dist/services/errors/index.cjs.map +0 -1
  92. package/dist/services/errors/index.mjs +0 -2
  93. package/dist/services/errors/index.mjs.map +0 -1
  94. package/dist/services/extensionService/index.cjs +0 -2
  95. package/dist/services/extensionService/index.cjs.map +0 -1
  96. package/dist/services/extensionService/index.d.cts +0 -8
  97. package/dist/services/extensionService/index.d.cts.map +0 -1
  98. package/dist/services/extensionService/index.d.mts +0 -8
  99. package/dist/services/extensionService/index.d.mts.map +0 -1
  100. package/dist/services/extensionService/index.mjs +0 -2
  101. package/dist/services/extensionService/index.mjs.map +0 -1
  102. package/dist/services/gitCli/index.cjs +0 -4
  103. package/dist/services/gitCli/index.cjs.map +0 -1
  104. package/dist/services/gitCli/index.mjs +0 -4
  105. package/dist/services/gitCli/index.mjs.map +0 -1
  106. package/dist/services/gitDependencies/index.cjs +0 -2
  107. package/dist/services/gitDependencies/index.cjs.map +0 -1
  108. package/dist/services/gitDependencies/index.d.cts +0 -6
  109. package/dist/services/gitDependencies/index.d.cts.map +0 -1
  110. package/dist/services/gitDependencies/index.d.mts +0 -6
  111. package/dist/services/gitDependencies/index.d.mts.map +0 -1
  112. package/dist/services/gitDependencies/index.mjs +0 -2
  113. package/dist/services/gitDependencies/index.mjs.map +0 -1
  114. package/dist/services/paths/index.cjs +0 -2
  115. package/dist/services/paths/index.cjs.map +0 -1
  116. package/dist/services/paths/index.mjs +0 -2
  117. package/dist/services/paths/index.mjs.map +0 -1
  118. package/dist/services/repositoryIdentity/index.cjs +0 -2
  119. package/dist/services/repositoryIdentity/index.cjs.map +0 -1
  120. package/dist/services/repositoryIdentity/index.mjs +0 -2
  121. package/dist/services/repositoryIdentity/index.mjs.map +0 -1
  122. package/dist/services/runWorktree/index.cjs +0 -15
  123. package/dist/services/runWorktree/index.cjs.map +0 -1
  124. package/dist/services/runWorktree/index.mjs +0 -15
  125. package/dist/services/runWorktree/index.mjs.map +0 -1
  126. package/dist/services/worktreeEvents/index.cjs +0 -2
  127. package/dist/services/worktreeEvents/index.cjs.map +0 -1
  128. package/dist/services/worktreeEvents/index.d.cts +0 -15
  129. package/dist/services/worktreeEvents/index.d.cts.map +0 -1
  130. package/dist/services/worktreeEvents/index.d.mts +0 -15
  131. package/dist/services/worktreeEvents/index.d.mts.map +0 -1
  132. package/dist/services/worktreeEvents/index.mjs +0 -2
  133. package/dist/services/worktreeEvents/index.mjs.map +0 -1
  134. package/dist/services/worktreeNaming/index.cjs +0 -2
  135. package/dist/services/worktreeNaming/index.cjs.map +0 -1
  136. package/dist/services/worktreeNaming/index.d.cts +0 -34
  137. package/dist/services/worktreeNaming/index.d.cts.map +0 -1
  138. package/dist/services/worktreeNaming/index.d.mts +0 -34
  139. package/dist/services/worktreeNaming/index.d.mts.map +0 -1
  140. package/dist/services/worktreeNaming/index.mjs +0 -2
  141. package/dist/services/worktreeNaming/index.mjs.map +0 -1
  142. package/dist/services/worktreeOperations/index.cjs +0 -2
  143. package/dist/services/worktreeOperations/index.cjs.map +0 -1
  144. package/dist/services/worktreeOperations/index.d.cts +0 -38
  145. package/dist/services/worktreeOperations/index.d.cts.map +0 -1
  146. package/dist/services/worktreeOperations/index.d.mts +0 -38
  147. package/dist/services/worktreeOperations/index.d.mts.map +0 -1
  148. package/dist/services/worktreeOperations/index.mjs +0 -2
  149. package/dist/services/worktreeOperations/index.mjs.map +0 -1
  150. package/dist/services/worktreeRegistry/index.cjs +0 -2
  151. package/dist/services/worktreeRegistry/index.cjs.map +0 -1
  152. package/dist/services/worktreeRegistry/index.mjs +0 -2
  153. package/dist/services/worktreeRegistry/index.mjs.map +0 -1
  154. package/dist/tools/runWorktree.cjs +0 -2
  155. package/dist/tools/runWorktree.cjs.map +0 -1
  156. package/dist/tools/runWorktree.mjs +0 -2
  157. package/dist/tools/runWorktree.mjs.map +0 -1
  158. package/dist/types/extension.d.cts +0 -17
  159. package/dist/types/extension.d.cts.map +0 -1
  160. package/dist/types/extension.d.mts +0 -17
  161. package/dist/types/extension.d.mts.map +0 -1
  162. package/dist/types/webWorktrees.cjs +0 -2
  163. package/dist/types/webWorktrees.cjs.map +0 -1
  164. package/dist/types/webWorktrees.mjs +0 -2
  165. package/dist/types/webWorktrees.mjs.map +0 -1
  166. package/dist/types/worktreeRegistry.d.cts +0 -41
  167. package/dist/types/worktreeRegistry.d.cts.map +0 -1
  168. package/dist/types/worktreeRegistry.d.mts +0 -41
  169. package/dist/types/worktreeRegistry.d.mts.map +0 -1
  170. package/src/extensions/web.ts +0 -33
  171. package/src/types/webWorktrees.ts +0 -55
  172. package/src/types/worktreeRegistry.ts +0 -78
  173. package/src/web/components/RunWorktreeToolMessage.tsx +0 -45
  174. package/src/web/components/WorktreesActivitySection.tsx +0 -80
  175. package/src/web/components/WorktreesPanel.tsx +0 -175
  176. package/src/web/components/toolRenderers.ts +0 -8
  177. package/src/web/stores/worktreesActivityStore.ts +0 -125
  178. package/src/web/tsconfig.json +0 -22
@@ -1 +0,0 @@
1
- {"version":3,"file":"worktreesChannel.cjs","names":["createWorktreeRegistry","registryFile","DoomGitExpectedError","GIT_WORKTREES_TYPE","HubUnavailableError","createWorktreeOperations","createWorktreeGit","GIT_WORKTREE_LIFECYCLE_EVENT","isWorktreeLifecycleEvent"],"sources":["../../src/controllers/worktreesChannel.ts"],"sourcesContent":["/**\n * The worktrees data channel, and the commands the dock sends back through it.\n *\n * The registry is durable state only. Live lifecycle changes arrive through the\n * hub-owned direct event bus, so this channel never polls or claims files.\n */\nimport type {\n DoomHubChannel,\n DoomHubChannelSource,\n DoomHubSessionScope,\n DoomHubSessionService,\n} from '@agimon-ai/doompi-core/hub-channel';\n\nimport { DoomGitExpectedError, HubUnavailableError } from '../services/errors';\nimport { createWorktreeGit } from '../services/gitCli';\nimport { registryFile } from '../services/paths';\nimport { GIT_WORKTREE_LIFECYCLE_EVENT, isWorktreeLifecycleEvent } from '../services/worktreeEvents';\nimport { createWorktreeOperations, type WorktreeOperations } from '../services/worktreeOperations';\nimport { createWorktreeRegistry } from '../services/worktreeRegistry';\nimport { GIT_WORKTREES_TYPE, type GitWorktreesCommand, type WorktreeView } from '../types/webWorktrees';\n\ninterface SessionState {\n worktrees: WorktreeView[];\n pending: string | undefined;\n error: string | undefined;\n}\n\nfunction payloadOf(state: SessionState): Record<string, unknown> {\n return {\n worktrees: state.worktrees,\n ...(state.pending === undefined ? {} : { pending: state.pending }),\n ...(state.error === undefined ? {} : { error: state.error }),\n };\n}\n\n/** What the channel needs from its surroundings, injected so tests stay off this machine. */\nexport interface WorktreesChannelOptions {\n operations?: WorktreeOperations;\n homeDir?: string;\n}\n\ninterface ViewDeps {\n homeDir: string | undefined;\n sessionService: DoomHubSessionService;\n}\n\n/** Worktrees visible to this session, using the hub's live session table for ownership. */\nfunction viewsFor(scope: DoomHubSessionScope, deps: ViewDeps): WorktreeView[] {\n try {\n return createWorktreeRegistry(registryFile(scope.cwd, deps.homeDir))\n .list()\n .flatMap((record) => {\n const owned = record.parentSessionId === scope.sessionId;\n const unowned = !owned && !deps.sessionService.isLive(record.parentSessionId);\n if (!owned && !unowned) return [];\n return [\n {\n id: record.id,\n branch: record.branch,\n path: record.path,\n sessionId: record.status === 'orphaned' ? null : record.sessionId,\n orphaned: record.status === 'orphaned',\n unowned,\n },\n ];\n });\n } catch {\n return [];\n }\n}\n\nfunction sameList(left: readonly WorktreeView[], right: readonly WorktreeView[]): boolean {\n if (left.length !== right.length) return false;\n return left.every((entry, index) => {\n const other = right[index];\n return (\n other !== undefined &&\n entry.id === other.id &&\n entry.branch === other.branch &&\n entry.sessionId === other.sessionId &&\n entry.orphaned === other.orphaned &&\n entry.unowned === other.unowned\n );\n });\n}\n\n/** A command the page sent, or undefined when the frame was not one. */\nfunction parseCommand(payload: unknown): GitWorktreesCommand | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const value = payload as Record<string, unknown>;\n if (value.action === 'create') {\n if (typeof value.branch !== 'string' || value.branch.trim() === '') return undefined;\n return {\n action: 'create',\n branch: value.branch.trim(),\n ...(typeof value.baseRef === 'string' && value.baseRef.trim() !== '' ? { baseRef: value.baseRef.trim() } : {}),\n };\n }\n if (value.action === 'close') {\n if (typeof value.id !== 'string' || value.id === '') return undefined;\n return { action: 'close', id: value.id, ...(value.force === true ? { force: true } : {}) };\n }\n return undefined;\n}\n\n/**\n * What the reader is told when a command fails.\n *\n * An expected failure explains itself. Anything else is summarised, never\n * echoed: a git error can carry a remote URL with a token in it.\n */\nfunction failureText(error: unknown): string {\n return error instanceof DoomGitExpectedError ? error.message : 'The worktree operation failed.';\n}\n\n/** Starts one direct-event subscription per managed session. */\nexport function createWorktreesChannel(options: WorktreesChannelOptions = {}): DoomHubChannel {\n // Assigned by start, because receive is reachable only while the channel is\n // running and the command needs the state the direct event subscriptions keep.\n let receiveCommand: ((scope: DoomHubSessionScope, payload: unknown) => void) | undefined;\n\n return {\n frameType: GIT_WORKTREES_TYPE,\n start(host) {\n const sessionService = host.sessionService;\n if (sessionService === undefined) {\n throw new HubUnavailableError('The cockpit session service is unavailable. Start the cockpit and try again.');\n }\n const worktrees =\n options.operations ??\n createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService,\n });\n const views: ViewDeps = { homeDir: options.homeDir, sessionService };\n const latest = new Map<string, SessionState>();\n const subscriptions = new Map<string, () => void>();\n const busy = new Set<string>();\n\n /** Republishes a session, skipping a frame that would say nothing new. */\n const publish = (scope: DoomHubSessionScope, force: boolean): void => {\n const previous = latest.get(scope.sessionId);\n const next: SessionState = {\n worktrees: viewsFor(scope, views),\n pending: previous?.pending,\n error: previous?.error,\n };\n if (\n !force &&\n previous !== undefined &&\n sameList(previous.worktrees, next.worktrees) &&\n previous.pending === next.pending &&\n previous.error === next.error\n ) {\n return;\n }\n latest.set(scope.sessionId, next);\n host.publish(scope.sessionId, payloadOf(next));\n };\n\n const mark = (scope: DoomHubSessionScope, pending: string | undefined, error: string | undefined): void => {\n const previous = latest.get(scope.sessionId);\n latest.set(scope.sessionId, {\n worktrees: previous?.worktrees ?? viewsFor(scope, views),\n pending,\n error,\n });\n publish(scope, true);\n };\n\n /** Announces a successful mutation to this session's lifecycle subscribers. */\n const publishLifecycle = (scope: DoomHubSessionScope, repositoryRoot: string): void => {\n host.directEvents.publish(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, {\n version: 1,\n repositoryRoot,\n });\n };\n\n const run = async (scope: DoomHubSessionScope, command: GitWorktreesCommand): Promise<void> => {\n const context = { cwd: scope.cwd, sessionId: scope.sessionId };\n if (command.action === 'create') {\n mark(scope, `creating ${command.branch}\\u2026`, undefined);\n const record = await worktrees.spawn(\n context,\n {\n branch: command.branch,\n ...(command.baseRef === undefined ? {} : { baseRef: command.baseRef }),\n },\n // Each phase replaces the label, so the panel says what is\n // happening instead of holding one line for the whole wait.\n { onProgress: (label) => mark(scope, label, undefined) },\n );\n publishLifecycle(scope, record.repositoryRoot);\n return;\n }\n mark(scope, `closing ${command.id}…`, undefined);\n const record = await worktrees.close(context, command.id, command.force ?? false);\n publishLifecycle(scope, record.repositoryRoot);\n };\n\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n const state = latest.get(scope.sessionId);\n return state === undefined ? undefined : payloadOf(state);\n },\n sessionAdded(scope) {\n publish(scope, false);\n const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, (payload) => {\n if (!isWorktreeLifecycleEvent(payload)) return;\n let sameRepository = false;\n try {\n sameRepository =\n registryFile(scope.cwd, options.homeDir) === registryFile(payload.repositoryRoot, options.homeDir);\n } catch {\n sameRepository = false;\n }\n if (sameRepository) publish(scope, false);\n });\n subscriptions.set(scope.sessionId, unsubscribe);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n latest.delete(sessionId);\n busy.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n latest.clear();\n busy.clear();\n },\n };\n receiveCommand = (scope, payload) => {\n const command = parseCommand(payload);\n if (command === undefined) return;\n // One operation per session. A create runs for minutes, and a second\n // click must not start a second worktree behind the first.\n if (busy.has(scope.sessionId)) return;\n busy.add(scope.sessionId);\n void run(scope, command)\n .then(() => {\n mark(scope, undefined, undefined);\n })\n .catch((error: unknown) => {\n host.onNotice(`worktree command failed for ${scope.sessionId} (${failureText(error)})`);\n mark(scope, undefined, failureText(error));\n })\n .finally(() => {\n busy.delete(scope.sessionId);\n });\n };\n\n return source;\n },\n receive(scope, payload) {\n receiveCommand?.(scope, payload);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{createWorktreeGit as e}from"../services/gitCli/index.mjs";import{DoomGitExpectedError as t,HubUnavailableError as n}from"../services/errors/index.mjs";import{registryFile as r}from"../services/paths/index.mjs";import{GIT_WORKTREE_LIFECYCLE_EVENT as i,isWorktreeLifecycleEvent as a}from"../services/worktreeEvents/index.mjs";import{createWorktreeRegistry as o}from"../services/worktreeRegistry/index.mjs";import{createWorktreeOperations as s}from"../services/worktreeOperations/index.mjs";import{GIT_WORKTREES_TYPE as c}from"../types/webWorktrees.mjs";function l(e){return{worktrees:e.worktrees,...e.pending===void 0?{}:{pending:e.pending},...e.error===void 0?{}:{error:e.error}}}function u(e,t){try{return o(r(e.cwd,t.homeDir)).list().flatMap(n=>{let r=n.parentSessionId===e.sessionId,i=!r&&!t.sessionService.isLive(n.parentSessionId);return!r&&!i?[]:[{id:n.id,branch:n.branch,path:n.path,sessionId:n.status===`orphaned`?null:n.sessionId,orphaned:n.status===`orphaned`,unowned:i}]})}catch{return[]}}function d(e,t){return e.length===t.length&&e.every((e,n)=>{let r=t[n];return r!==void 0&&e.id===r.id&&e.branch===r.branch&&e.sessionId===r.sessionId&&e.orphaned===r.orphaned&&e.unowned===r.unowned})}function f(e){if(typeof e!=`object`||!e)return;let t=e;if(t.action===`create`)return typeof t.branch!=`string`||t.branch.trim()===``?void 0:{action:`create`,branch:t.branch.trim(),...typeof t.baseRef==`string`&&t.baseRef.trim()!==``?{baseRef:t.baseRef.trim()}:{}};if(t.action===`close`)return typeof t.id!=`string`||t.id===``?void 0:{action:`close`,id:t.id,...t.force===!0?{force:!0}:{}}}function p(e){return e instanceof t?e.message:`The worktree operation failed.`}function m(t={}){let o;return{frameType:c,start(c){let m=c.sessionService;if(m===void 0)throw new n(`The cockpit session service is unavailable. Start the cockpit and try again.`);let h=t.operations??s({git:e(),sessionService:m}),g={homeDir:t.homeDir,sessionService:m},_=new Map,v=new Map,y=new Set,b=(e,t)=>{let n=_.get(e.sessionId),r={worktrees:u(e,g),pending:n?.pending,error:n?.error};(t||n===void 0||!d(n.worktrees,r.worktrees)||n.pending!==r.pending||n.error!==r.error)&&(_.set(e.sessionId,r),c.publish(e.sessionId,l(r)))},x=(e,t,n)=>{let r=_.get(e.sessionId);_.set(e.sessionId,{worktrees:r?.worktrees??u(e,g),pending:t,error:n}),b(e,!0)},S=(e,t)=>{c.directEvents.publish(i,e.sessionId,{version:1,repositoryRoot:t})},C=async(e,t)=>{let n={cwd:e.cwd,sessionId:e.sessionId};if(t.action===`create`){x(e,`creating ${t.branch}\u2026`,void 0);let r=await h.spawn(n,{branch:t.branch,...t.baseRef===void 0?{}:{baseRef:t.baseRef}},{onProgress:t=>x(e,t,void 0)});S(e,r.repositoryRoot);return}x(e,`closing ${t.id}…`,void 0);let r=await h.close(n,t.id,t.force??!1);S(e,r.repositoryRoot)};return o=(e,t)=>{let n=f(t);n!==void 0&&(y.has(e.sessionId)||(y.add(e.sessionId),C(e,n).then(()=>{x(e,void 0,void 0)}).catch(t=>{c.onNotice(`worktree command failed for ${e.sessionId} (${p(t)})`),x(e,void 0,p(t))}).finally(()=>{y.delete(e.sessionId)})))},{payloadFor(e){let t=_.get(e.sessionId);return t===void 0?void 0:l(t)},sessionAdded(e){b(e,!1);let n=c.directEvents.subscribe(i,e.sessionId,n=>{if(!a(n))return;let i=!1;try{i=r(e.cwd,t.homeDir)===r(n.repositoryRoot,t.homeDir)}catch{i=!1}i&&b(e,!1)});v.set(e.sessionId,n)},sessionRemoved(e){v.get(e)?.(),v.delete(e),_.delete(e),y.delete(e)},close(){for(let e of v.values())e();v.clear(),_.clear(),y.clear()}}},receive(e,t){o?.(e,t)}}}export{m as createWorktreesChannel};
2
- //# sourceMappingURL=worktreesChannel.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"worktreesChannel.mjs","names":[],"sources":["../../src/controllers/worktreesChannel.ts"],"sourcesContent":["/**\n * The worktrees data channel, and the commands the dock sends back through it.\n *\n * The registry is durable state only. Live lifecycle changes arrive through the\n * hub-owned direct event bus, so this channel never polls or claims files.\n */\nimport type {\n DoomHubChannel,\n DoomHubChannelSource,\n DoomHubSessionScope,\n DoomHubSessionService,\n} from '@agimon-ai/doompi-core/hub-channel';\n\nimport { DoomGitExpectedError, HubUnavailableError } from '../services/errors';\nimport { createWorktreeGit } from '../services/gitCli';\nimport { registryFile } from '../services/paths';\nimport { GIT_WORKTREE_LIFECYCLE_EVENT, isWorktreeLifecycleEvent } from '../services/worktreeEvents';\nimport { createWorktreeOperations, type WorktreeOperations } from '../services/worktreeOperations';\nimport { createWorktreeRegistry } from '../services/worktreeRegistry';\nimport { GIT_WORKTREES_TYPE, type GitWorktreesCommand, type WorktreeView } from '../types/webWorktrees';\n\ninterface SessionState {\n worktrees: WorktreeView[];\n pending: string | undefined;\n error: string | undefined;\n}\n\nfunction payloadOf(state: SessionState): Record<string, unknown> {\n return {\n worktrees: state.worktrees,\n ...(state.pending === undefined ? {} : { pending: state.pending }),\n ...(state.error === undefined ? {} : { error: state.error }),\n };\n}\n\n/** What the channel needs from its surroundings, injected so tests stay off this machine. */\nexport interface WorktreesChannelOptions {\n operations?: WorktreeOperations;\n homeDir?: string;\n}\n\ninterface ViewDeps {\n homeDir: string | undefined;\n sessionService: DoomHubSessionService;\n}\n\n/** Worktrees visible to this session, using the hub's live session table for ownership. */\nfunction viewsFor(scope: DoomHubSessionScope, deps: ViewDeps): WorktreeView[] {\n try {\n return createWorktreeRegistry(registryFile(scope.cwd, deps.homeDir))\n .list()\n .flatMap((record) => {\n const owned = record.parentSessionId === scope.sessionId;\n const unowned = !owned && !deps.sessionService.isLive(record.parentSessionId);\n if (!owned && !unowned) return [];\n return [\n {\n id: record.id,\n branch: record.branch,\n path: record.path,\n sessionId: record.status === 'orphaned' ? null : record.sessionId,\n orphaned: record.status === 'orphaned',\n unowned,\n },\n ];\n });\n } catch {\n return [];\n }\n}\n\nfunction sameList(left: readonly WorktreeView[], right: readonly WorktreeView[]): boolean {\n if (left.length !== right.length) return false;\n return left.every((entry, index) => {\n const other = right[index];\n return (\n other !== undefined &&\n entry.id === other.id &&\n entry.branch === other.branch &&\n entry.sessionId === other.sessionId &&\n entry.orphaned === other.orphaned &&\n entry.unowned === other.unowned\n );\n });\n}\n\n/** A command the page sent, or undefined when the frame was not one. */\nfunction parseCommand(payload: unknown): GitWorktreesCommand | undefined {\n if (typeof payload !== 'object' || payload === null) return undefined;\n const value = payload as Record<string, unknown>;\n if (value.action === 'create') {\n if (typeof value.branch !== 'string' || value.branch.trim() === '') return undefined;\n return {\n action: 'create',\n branch: value.branch.trim(),\n ...(typeof value.baseRef === 'string' && value.baseRef.trim() !== '' ? { baseRef: value.baseRef.trim() } : {}),\n };\n }\n if (value.action === 'close') {\n if (typeof value.id !== 'string' || value.id === '') return undefined;\n return { action: 'close', id: value.id, ...(value.force === true ? { force: true } : {}) };\n }\n return undefined;\n}\n\n/**\n * What the reader is told when a command fails.\n *\n * An expected failure explains itself. Anything else is summarised, never\n * echoed: a git error can carry a remote URL with a token in it.\n */\nfunction failureText(error: unknown): string {\n return error instanceof DoomGitExpectedError ? error.message : 'The worktree operation failed.';\n}\n\n/** Starts one direct-event subscription per managed session. */\nexport function createWorktreesChannel(options: WorktreesChannelOptions = {}): DoomHubChannel {\n // Assigned by start, because receive is reachable only while the channel is\n // running and the command needs the state the direct event subscriptions keep.\n let receiveCommand: ((scope: DoomHubSessionScope, payload: unknown) => void) | undefined;\n\n return {\n frameType: GIT_WORKTREES_TYPE,\n start(host) {\n const sessionService = host.sessionService;\n if (sessionService === undefined) {\n throw new HubUnavailableError('The cockpit session service is unavailable. Start the cockpit and try again.');\n }\n const worktrees =\n options.operations ??\n createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService,\n });\n const views: ViewDeps = { homeDir: options.homeDir, sessionService };\n const latest = new Map<string, SessionState>();\n const subscriptions = new Map<string, () => void>();\n const busy = new Set<string>();\n\n /** Republishes a session, skipping a frame that would say nothing new. */\n const publish = (scope: DoomHubSessionScope, force: boolean): void => {\n const previous = latest.get(scope.sessionId);\n const next: SessionState = {\n worktrees: viewsFor(scope, views),\n pending: previous?.pending,\n error: previous?.error,\n };\n if (\n !force &&\n previous !== undefined &&\n sameList(previous.worktrees, next.worktrees) &&\n previous.pending === next.pending &&\n previous.error === next.error\n ) {\n return;\n }\n latest.set(scope.sessionId, next);\n host.publish(scope.sessionId, payloadOf(next));\n };\n\n const mark = (scope: DoomHubSessionScope, pending: string | undefined, error: string | undefined): void => {\n const previous = latest.get(scope.sessionId);\n latest.set(scope.sessionId, {\n worktrees: previous?.worktrees ?? viewsFor(scope, views),\n pending,\n error,\n });\n publish(scope, true);\n };\n\n /** Announces a successful mutation to this session's lifecycle subscribers. */\n const publishLifecycle = (scope: DoomHubSessionScope, repositoryRoot: string): void => {\n host.directEvents.publish(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, {\n version: 1,\n repositoryRoot,\n });\n };\n\n const run = async (scope: DoomHubSessionScope, command: GitWorktreesCommand): Promise<void> => {\n const context = { cwd: scope.cwd, sessionId: scope.sessionId };\n if (command.action === 'create') {\n mark(scope, `creating ${command.branch}\\u2026`, undefined);\n const record = await worktrees.spawn(\n context,\n {\n branch: command.branch,\n ...(command.baseRef === undefined ? {} : { baseRef: command.baseRef }),\n },\n // Each phase replaces the label, so the panel says what is\n // happening instead of holding one line for the whole wait.\n { onProgress: (label) => mark(scope, label, undefined) },\n );\n publishLifecycle(scope, record.repositoryRoot);\n return;\n }\n mark(scope, `closing ${command.id}…`, undefined);\n const record = await worktrees.close(context, command.id, command.force ?? false);\n publishLifecycle(scope, record.repositoryRoot);\n };\n\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n const state = latest.get(scope.sessionId);\n return state === undefined ? undefined : payloadOf(state);\n },\n sessionAdded(scope) {\n publish(scope, false);\n const unsubscribe = host.directEvents.subscribe(GIT_WORKTREE_LIFECYCLE_EVENT, scope.sessionId, (payload) => {\n if (!isWorktreeLifecycleEvent(payload)) return;\n let sameRepository = false;\n try {\n sameRepository =\n registryFile(scope.cwd, options.homeDir) === registryFile(payload.repositoryRoot, options.homeDir);\n } catch {\n sameRepository = false;\n }\n if (sameRepository) publish(scope, false);\n });\n subscriptions.set(scope.sessionId, unsubscribe);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n latest.delete(sessionId);\n busy.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n latest.clear();\n busy.clear();\n },\n };\n receiveCommand = (scope, payload) => {\n const command = parseCommand(payload);\n if (command === undefined) return;\n // One operation per session. A create runs for minutes, and a second\n // click must not start a second worktree behind the first.\n if (busy.has(scope.sessionId)) return;\n busy.add(scope.sessionId);\n void run(scope, command)\n .then(() => {\n mark(scope, undefined, undefined);\n })\n .catch((error: unknown) => {\n host.onNotice(`worktree command failed for ${scope.sessionId} (${failureText(error)})`);\n mark(scope, undefined, failureText(error));\n })\n .finally(() => {\n busy.delete(scope.sessionId);\n });\n };\n\n return source;\n },\n receive(scope, payload) {\n receiveCommand?.(scope, payload);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,6 +0,0 @@
1
- import { GitExtensionDependencies } from "../types/extension.cjs";
2
- //#region src/extensions/pi.d.ts
3
- declare const activateGitExtension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<Partial<GitExtensionDependencies>>;
4
- //#endregion
5
- export { activateGitExtension, activateGitExtension as default };
6
- //# sourceMappingURL=pi.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pi.d.cts","names":[],"sources":["../../src/extensions/pi.ts"],"mappings":";;cAUa,4EAAoB,mBAAA,QAAA"}
@@ -1,5 +0,0 @@
1
- //#region src/extensions/server.d.ts
2
- declare const gitServerFacet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
3
- //#endregion
4
- export { gitServerFacet as default, gitServerFacet };
5
- //# sourceMappingURL=server.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.cts","names":[],"sources":["../../src/extensions/server.ts"],"mappings":";cAKa,8DAAc"}
package/dist/index.d.cts DELETED
@@ -1,4 +0,0 @@
1
- import { GitExtensionDependencies, GitExtensionResult, GitExtensionService } from "./types/extension.cjs";
2
- import { DefaultGitExtensionService } from "./services/extensionService/index.cjs";
3
- import { createGitDependencies } from "./services/gitDependencies/index.cjs";
4
- export { DefaultGitExtensionService, type GitExtensionDependencies, type GitExtensionResult, type GitExtensionService, createGitDependencies };
@@ -1,2 +0,0 @@
1
- let e=require("@agimon-ai/doompi-core/api-contracts"),t=require("typebox");const n=t.Type.String(),r=t.Type.Boolean(),i=t.Type.Optional,a=t.Type.Object({version:t.Type.Literal(1),id:n,branch:n,baseRef:n,path:n,repositoryRoot:n,sessionId:n,parentSessionId:n,status:(e=>t.Type.Union(e.map(e=>t.Type.Literal(e))))([`spawning`,`running`,`closing`,`orphaned`]),createdAt:n}),o=t.Type.Object({worktrees:t.Type.Array(t.Type.Object({id:n,branch:n,path:n,sessionId:t.Type.Union([n,t.Type.Null()]),orphaned:r,unowned:r})),pending:i(n),error:i(n)}),s=t.Type.Union([t.Type.Object({action:t.Type.Literal(`create`),branch:n,baseRef:i(n)}),t.Type.Object({action:t.Type.Literal(`close`),id:n,force:i(r)})]),c=[{name:`repositoryId`,in:`query`,required:!0,schema:n},{name:`sessionId`,in:`query`,required:!0,schema:n}],l=(0,e.defineApiContract)({version:1,dynamic:[],http:[`global`,`workspace`].flatMap(o=>[{id:`git.list`,scope:o,basePath:`git`,path:`/worktrees`,method:`GET`,authentication:`owner`,description:`List admitted repository worktrees.`,parameters:c.map(e=>({...e,required:e.name===`repositoryId`})),responses:(0,e.jsonApiResponses)(t.Type.Object({worktrees:t.Type.Array(a)}))},{id:`git.create`,scope:o,basePath:`git`,path:`/worktrees`,method:`POST`,authentication:`owner`,description:`Create a worktree and session.`,parameters:c,body:{required:!0,contentType:`application/json`,schema:t.Type.Object({branch:t.Type.String({minLength:1}),baseRef:i(n),name:i(n)})},responses:(0,e.jsonApiResponses)(t.Type.Object({worktree:a}),201)},{id:`git.close`,scope:o,basePath:`git`,path:`/worktrees/{id}`,method:`DELETE`,authentication:`owner`,description:`Close a worktree.`,parameters:[...c,{name:`force`,in:`query`,required:!1,schema:r}],responses:(0,e.jsonApiResponses)(t.Type.Object({worktree:a}))}]),sockets:[`global`,`workspace`].flatMap(e=>[{id:`git.channel`,scope:e,service:`doompi.hub.v1`,member:`git_worktrees`,kind:`channel`,direction:`server-to-client`,description:`Worktree channel payload.`,input:o},{id:`git.command`,scope:e,service:`doompi.hub.v1`,member:`git_worktrees`,kind:`channel`,direction:`client-to-server`,description:`Worktree channel command payload.`,input:s}])});exports.WorktreesCommandSchema=s,exports.WorktreesPayloadSchema=o,exports.apiContracts=l,exports.default=l;
2
- //# sourceMappingURL=apiContracts.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.cjs","names":["Type","defineApiContract","jsonApiResponses"],"sources":["../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/api-contracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst B = Type.Boolean();\nconst O = Type.Optional;\nconst literals = <T extends string>(values: T[]) => Type.Union(values.map((value) => Type.Literal(value)));\nconst RecordSchema = Type.Object({\n version: Type.Literal(1),\n id: S,\n branch: S,\n baseRef: S,\n path: S,\n repositoryRoot: S,\n sessionId: S,\n parentSessionId: S,\n status: literals(['spawning', 'running', 'closing', 'orphaned']),\n createdAt: S,\n});\nexport const WorktreesPayloadSchema = Type.Object({\n worktrees: Type.Array(\n Type.Object({ id: S, branch: S, path: S, sessionId: Type.Union([S, Type.Null()]), orphaned: B, unowned: B }),\n ),\n pending: O(S),\n error: O(S),\n});\nexport const WorktreesCommandSchema = Type.Union([\n Type.Object({ action: Type.Literal('create'), branch: S, baseRef: O(S) }),\n Type.Object({ action: Type.Literal('close'), id: S, force: O(B) }),\n]);\nconst query = [\n { name: 'repositoryId', in: 'query' as const, required: true, schema: S },\n { name: 'sessionId', in: 'query' as const, required: true, schema: S },\n];\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: [],\n http: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'git.list',\n scope,\n basePath: 'git',\n path: '/worktrees',\n method: 'GET',\n authentication: 'owner',\n description: 'List admitted repository worktrees.',\n parameters: query.map((item) => ({ ...item, required: item.name === 'repositoryId' })),\n responses: jsonApiResponses(Type.Object({ worktrees: Type.Array(RecordSchema) })),\n },\n {\n id: 'git.create',\n scope,\n basePath: 'git',\n path: '/worktrees',\n method: 'POST',\n authentication: 'owner',\n description: 'Create a worktree and session.',\n parameters: query,\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ branch: Type.String({ minLength: 1 }), baseRef: O(S), name: O(S) }),\n },\n responses: jsonApiResponses(Type.Object({ worktree: RecordSchema }), 201),\n },\n {\n id: 'git.close',\n scope,\n basePath: 'git',\n path: '/worktrees/{id}',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Close a worktree.',\n parameters: [...query, { name: 'force', in: 'query', required: false, schema: B }],\n responses: jsonApiResponses(Type.Object({ worktree: RecordSchema })),\n },\n ]),\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'git.channel',\n scope,\n service: 'doompi.hub.v1',\n member: 'git_worktrees',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Worktree channel payload.',\n input: WorktreesPayloadSchema,\n },\n {\n id: 'git.command',\n scope,\n service: 'doompi.hub.v1',\n member: 'git_worktrees',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Worktree channel command payload.',\n input: WorktreesCommandSchema,\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"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"}
@@ -1,53 +0,0 @@
1
- import "typebox";
2
- //#region src/schemas/apiContracts.d.ts
3
- declare const apiContracts: {
4
- version: 1;
5
- protocols?: Record<string, string> | undefined;
6
- schemas?: Record<string, boolean | object> | undefined;
7
- http: {
8
- id: string;
9
- scope: "global" | "session" | "workspace";
10
- basePath?: string | undefined;
11
- path: string;
12
- method: "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT";
13
- description: string;
14
- availability?: string | undefined;
15
- authentication: "device" | "none" | "owner";
16
- parameters?: {
17
- name: string;
18
- in: "header" | "path" | "query";
19
- required: boolean;
20
- schema: boolean | object;
21
- }[] | undefined;
22
- body?: {
23
- contentType: string;
24
- contentTypes?: string[] | undefined;
25
- required: boolean;
26
- schema: boolean | object;
27
- } | undefined;
28
- responses: Record<string, {
29
- description: string;
30
- contentType?: string | undefined;
31
- schema?: boolean | object | undefined;
32
- events?: Record<string, boolean | object> | undefined;
33
- }>;
34
- }[];
35
- sockets: {
36
- id: string;
37
- scope: "global" | "session" | "workspace";
38
- description: string;
39
- availability?: string | undefined;
40
- service: string;
41
- member: string;
42
- direction: "client-to-server" | "server-to-client";
43
- kind: "channel" | "method" | "state";
44
- input: boolean | object;
45
- output?: boolean | object | undefined;
46
- errors?: boolean | object | undefined;
47
- }[];
48
- dynamic: string[];
49
- gaps?: string[] | undefined;
50
- };
51
- //#endregion
52
- export { apiContracts, apiContracts as default };
53
- //# sourceMappingURL=apiContracts.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.d.cts","names":[],"sources":["../../src/schemas/apiContracts.ts"],"mappings":";;cAkCa"}
@@ -1,2 +0,0 @@
1
- import{defineApiContract as e,jsonApiResponses as t}from"@agimon-ai/doompi-core/api-contracts";import{Type as n}from"typebox";const r=n.String(),i=n.Boolean(),a=n.Optional,o=n.Object({version:n.Literal(1),id:r,branch:r,baseRef:r,path:r,repositoryRoot:r,sessionId:r,parentSessionId:r,status:(e=>n.Union(e.map(e=>n.Literal(e))))([`spawning`,`running`,`closing`,`orphaned`]),createdAt:r}),s=n.Object({worktrees:n.Array(n.Object({id:r,branch:r,path:r,sessionId:n.Union([r,n.Null()]),orphaned:i,unowned:i})),pending:a(r),error:a(r)}),c=n.Union([n.Object({action:n.Literal(`create`),branch:r,baseRef:a(r)}),n.Object({action:n.Literal(`close`),id:r,force:a(i)})]),l=[{name:`repositoryId`,in:`query`,required:!0,schema:r},{name:`sessionId`,in:`query`,required:!0,schema:r}],u=e({version:1,dynamic:[],http:[`global`,`workspace`].flatMap(e=>[{id:`git.list`,scope:e,basePath:`git`,path:`/worktrees`,method:`GET`,authentication:`owner`,description:`List admitted repository worktrees.`,parameters:l.map(e=>({...e,required:e.name===`repositoryId`})),responses:t(n.Object({worktrees:n.Array(o)}))},{id:`git.create`,scope:e,basePath:`git`,path:`/worktrees`,method:`POST`,authentication:`owner`,description:`Create a worktree and session.`,parameters:l,body:{required:!0,contentType:`application/json`,schema:n.Object({branch:n.String({minLength:1}),baseRef:a(r),name:a(r)})},responses:t(n.Object({worktree:o}),201)},{id:`git.close`,scope:e,basePath:`git`,path:`/worktrees/{id}`,method:`DELETE`,authentication:`owner`,description:`Close a worktree.`,parameters:[...l,{name:`force`,in:`query`,required:!1,schema:i}],responses:t(n.Object({worktree:o}))}]),sockets:[`global`,`workspace`].flatMap(e=>[{id:`git.channel`,scope:e,service:`doompi.hub.v1`,member:`git_worktrees`,kind:`channel`,direction:`server-to-client`,description:`Worktree channel payload.`,input:s},{id:`git.command`,scope:e,service:`doompi.hub.v1`,member:`git_worktrees`,kind:`channel`,direction:`client-to-server`,description:`Worktree channel command payload.`,input:c}])});export{c as WorktreesCommandSchema,s as WorktreesPayloadSchema,u as apiContracts,u as default};
2
- //# sourceMappingURL=apiContracts.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/api-contracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst B = Type.Boolean();\nconst O = Type.Optional;\nconst literals = <T extends string>(values: T[]) => Type.Union(values.map((value) => Type.Literal(value)));\nconst RecordSchema = Type.Object({\n version: Type.Literal(1),\n id: S,\n branch: S,\n baseRef: S,\n path: S,\n repositoryRoot: S,\n sessionId: S,\n parentSessionId: S,\n status: literals(['spawning', 'running', 'closing', 'orphaned']),\n createdAt: S,\n});\nexport const WorktreesPayloadSchema = Type.Object({\n worktrees: Type.Array(\n Type.Object({ id: S, branch: S, path: S, sessionId: Type.Union([S, Type.Null()]), orphaned: B, unowned: B }),\n ),\n pending: O(S),\n error: O(S),\n});\nexport const WorktreesCommandSchema = Type.Union([\n Type.Object({ action: Type.Literal('create'), branch: S, baseRef: O(S) }),\n Type.Object({ action: Type.Literal('close'), id: S, force: O(B) }),\n]);\nconst query = [\n { name: 'repositoryId', in: 'query' as const, required: true, schema: S },\n { name: 'sessionId', in: 'query' as const, required: true, schema: S },\n];\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: [],\n http: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'git.list',\n scope,\n basePath: 'git',\n path: '/worktrees',\n method: 'GET',\n authentication: 'owner',\n description: 'List admitted repository worktrees.',\n parameters: query.map((item) => ({ ...item, required: item.name === 'repositoryId' })),\n responses: jsonApiResponses(Type.Object({ worktrees: Type.Array(RecordSchema) })),\n },\n {\n id: 'git.create',\n scope,\n basePath: 'git',\n path: '/worktrees',\n method: 'POST',\n authentication: 'owner',\n description: 'Create a worktree and session.',\n parameters: query,\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ branch: Type.String({ minLength: 1 }), baseRef: O(S), name: O(S) }),\n },\n responses: jsonApiResponses(Type.Object({ worktree: RecordSchema }), 201),\n },\n {\n id: 'git.close',\n scope,\n basePath: 'git',\n path: '/worktrees/{id}',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Close a worktree.',\n parameters: [...query, { name: 'force', in: 'query', required: false, schema: B }],\n responses: jsonApiResponses(Type.Object({ worktree: RecordSchema })),\n },\n ]),\n sockets: (['global', 'workspace'] as const).flatMap((scope) => [\n {\n id: 'git.channel',\n scope,\n service: 'doompi.hub.v1',\n member: 'git_worktrees',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'Worktree channel payload.',\n input: WorktreesPayloadSchema,\n },\n {\n id: 'git.command',\n scope,\n service: 'doompi.hub.v1',\n member: 'git_worktrees',\n kind: 'channel',\n direction: 'client-to-server',\n description: 'Worktree channel command payload.',\n input: WorktreesCommandSchema,\n },\n ]),\n});\nexport default apiContracts;\n"],"mappings":"8HAGA,MAAM,EAAI,EAAK,OAAO,EAChB,EAAI,EAAK,QAAQ,EACjB,EAAI,EAAK,SAET,EAAe,EAAK,OAAO,CAC/B,QAAS,EAAK,QAAQ,CAAC,EACvB,GAAI,EACJ,OAAQ,EACR,QAAS,EACT,KAAM,EACN,eAAgB,EAChB,UAAW,EACX,gBAAiB,EACjB,QAVkC,GAAgB,EAAK,MAAM,EAAO,IAAK,GAAU,EAAK,QAAQ,CAAK,CAAC,CAAC,EAU/F,CAAS,CAAC,WAAY,UAAW,UAAW,UAAU,CAAC,EAC/D,UAAW,CACb,CAAC,EACY,EAAyB,EAAK,OAAO,CAChD,UAAW,EAAK,MACd,EAAK,OAAO,CAAE,GAAI,EAAG,OAAQ,EAAG,KAAM,EAAG,UAAW,EAAK,MAAM,CAAC,EAAG,EAAK,KAAK,CAAC,CAAC,EAAG,SAAU,EAAG,QAAS,CAAE,CAAC,CAC7G,EACA,QAAS,EAAE,CAAC,EACZ,MAAO,EAAE,CAAC,CACZ,CAAC,EACY,EAAyB,EAAK,MAAM,CAC/C,EAAK,OAAO,CAAE,OAAQ,EAAK,QAAQ,QAAQ,EAAG,OAAQ,EAAG,QAAS,EAAE,CAAC,CAAE,CAAC,EACxE,EAAK,OAAO,CAAE,OAAQ,EAAK,QAAQ,OAAO,EAAG,GAAI,EAAG,MAAO,EAAE,CAAC,CAAE,CAAC,CACnE,CAAC,EACK,EAAQ,CACZ,CAAE,KAAM,eAAgB,GAAI,QAAkB,SAAU,GAAM,OAAQ,CAAE,EACxE,CAAE,KAAM,YAAa,GAAI,QAAkB,SAAU,GAAM,OAAQ,CAAE,CACvE,EACa,EAAe,EAAkB,CAC5C,QAAS,EACT,QAAS,CAAC,EACV,KAAO,CAAC,SAAU,WAAW,CAAC,CAAW,QAAS,GAAU,CAC1D,CACE,GAAI,WACJ,QACA,SAAU,MACV,KAAM,aACN,OAAQ,MACR,eAAgB,QAChB,YAAa,sCACb,WAAY,EAAM,IAAK,IAAU,CAAE,GAAG,EAAM,SAAU,EAAK,OAAS,cAAe,EAAE,EACrF,UAAW,EAAiB,EAAK,OAAO,CAAE,UAAW,EAAK,MAAM,CAAY,CAAE,CAAC,CAAC,CAClF,EACA,CACE,GAAI,aACJ,QACA,SAAU,MACV,KAAM,aACN,OAAQ,OACR,eAAgB,QAChB,YAAa,iCACb,WAAY,EACZ,KAAM,CACJ,SAAU,GACV,YAAa,mBACb,OAAQ,EAAK,OAAO,CAAE,OAAQ,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAAG,QAAS,EAAE,CAAC,EAAG,KAAM,EAAE,CAAC,CAAE,CAAC,CAC1F,EACA,UAAW,EAAiB,EAAK,OAAO,CAAE,SAAU,CAAa,CAAC,EAAG,GAAG,CAC1E,EACA,CACE,GAAI,YACJ,QACA,SAAU,MACV,KAAM,kBACN,OAAQ,SACR,eAAgB,QAChB,YAAa,oBACb,WAAY,CAAC,GAAG,EAAO,CAAE,KAAM,QAAS,GAAI,QAAS,SAAU,GAAO,OAAQ,CAAE,CAAC,EACjF,UAAW,EAAiB,EAAK,OAAO,CAAE,SAAU,CAAa,CAAC,CAAC,CACrE,CACF,CAAC,EACD,QAAU,CAAC,SAAU,WAAW,CAAC,CAAW,QAAS,GAAU,CAC7D,CACE,GAAI,cACJ,QACA,QAAS,gBACT,OAAQ,gBACR,KAAM,UACN,UAAW,mBACX,YAAa,4BACb,MAAO,CACT,EACA,CACE,GAAI,cACJ,QACA,QAAS,gBACT,OAAQ,gBACR,KAAM,UACN,UAAW,mBACX,YAAa,oCACb,MAAO,CACT,CACF,CAAC,CACH,CAAC"}
@@ -1,2 +0,0 @@
1
- let e=require("typebox");const t={spawn_worktree:`spawn_worktree`,close_worktree:`close_worktree`,list:`list`,status:`status`,merge:`merge`,prune:`prune`,send:`send`,messages:`messages`},n={spawn_worktree:[`action`,`branch`,`baseRef`,`task`,`name`],close_worktree:[`action`,`id`,`force`],list:[`action`],status:[`action`,`id`],merge:[`action`,`id`,`message`],prune:[`action`,`dryRun`],send:[`action`,`id`,`message`],messages:[`action`,`id`]},r=e.Type.Object({action:e.Type.Literal(t.spawn_worktree),branch:e.Type.String({minLength:1}),baseRef:e.Type.Optional(e.Type.String({minLength:1})),task:e.Type.Optional(e.Type.String({minLength:1})),name:e.Type.Optional(e.Type.String({minLength:1}))},{additionalProperties:!1}),i=e.Type.Object({action:e.Type.Literal(t.close_worktree),id:e.Type.String({minLength:1}),force:e.Type.Optional(e.Type.Boolean())},{additionalProperties:!1}),a=e.Type.Object({action:e.Type.Literal(t.list)},{additionalProperties:!1}),o=e.Type.Object({action:e.Type.Literal(t.status),id:e.Type.String({minLength:1})},{additionalProperties:!1}),s=e.Type.Object({action:e.Type.Literal(t.merge),id:e.Type.String({minLength:1}),message:e.Type.Optional(e.Type.String({minLength:1}))},{additionalProperties:!1}),c=e.Type.Object({action:e.Type.Literal(t.prune),dryRun:e.Type.Optional(e.Type.Boolean())},{additionalProperties:!1}),l=e.Type.Object({action:e.Type.Literal(t.send),id:e.Type.String({minLength:1}),message:e.Type.String({minLength:1})},{additionalProperties:!1}),u=e.Type.Object({action:e.Type.Literal(t.messages),id:e.Type.String({minLength:1})},{additionalProperties:!1}),d=e.Type.Union([r,i,a,o,s,c,l,u]);exports.RunWorktreeParams=d,exports.WORKTREE_ACTIONS=t,exports.WORKTREE_ACTION_FIELDS=n;
2
- //# sourceMappingURL=runWorktreeTool.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runWorktreeTool.cjs","names":["Type"],"sources":["../../src/schemas/runWorktreeTool.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n"],"mappings":"yBASA,MAAa,EAAmB,CAC9B,eAAgB,iBAChB,eAAgB,iBAChB,KAAM,OACN,OAAQ,SACR,MAAO,QACP,MAAO,QACP,KAAM,OACN,SAAU,UACZ,EAWa,EAAoE,CAC/E,eAAgB,CAAC,SAAU,SAAU,UAAW,OAAQ,MAAM,EAC9D,eAAgB,CAAC,SAAU,KAAM,OAAO,EACxC,KAAM,CAAC,QAAQ,EACf,OAAQ,CAAC,SAAU,IAAI,EACvB,MAAO,CAAC,SAAU,KAAM,SAAS,EACjC,MAAO,CAAC,SAAU,QAAQ,EAC1B,KAAM,CAAC,SAAU,KAAM,SAAS,EAChC,SAAU,CAAC,SAAU,IAAI,CAC3B,EAEM,EAAcA,EAAAA,KAAK,OACvB,CACE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,cAAc,EACpD,OAAQA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EACpC,QAASA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,EACpD,KAAMA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,EACjD,KAAMA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,CACnD,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAcA,EAAAA,KAAK,OACvB,CACE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,cAAc,EACpD,GAAIA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,MAAOA,EAAAA,KAAK,SAASA,EAAAA,KAAK,QAAQ,CAAC,CACrC,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAaA,EAAAA,KAAK,OAAO,CAAE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,IAAI,CAAE,EAAG,CAAE,qBAAsB,EAAM,CAAC,EAEzG,EAAeA,EAAAA,KAAK,OACxB,CAAE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,MAAM,EAAG,GAAIA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAE,EACnF,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAcA,EAAAA,KAAK,OACvB,CACE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,KAAK,EAC3C,GAAIA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,QAASA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,CACtD,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAcA,EAAAA,KAAK,OACvB,CAAE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,KAAK,EAAG,OAAQA,EAAAA,KAAK,SAASA,EAAAA,KAAK,QAAQ,CAAC,CAAE,EACtF,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAaA,EAAAA,KAAK,OACtB,CACE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,IAAI,EAC1C,GAAIA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,QAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CACvC,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAiBA,EAAAA,KAAK,OAC1B,CAAE,OAAQA,EAAAA,KAAK,QAAQ,EAAiB,QAAQ,EAAG,GAAIA,EAAAA,KAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAE,EACrF,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAoBA,EAAAA,KAAK,MAAM,CAC1C,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC"}
@@ -1,2 +0,0 @@
1
- import{Type as e}from"typebox";const t={spawn_worktree:`spawn_worktree`,close_worktree:`close_worktree`,list:`list`,status:`status`,merge:`merge`,prune:`prune`,send:`send`,messages:`messages`},n={spawn_worktree:[`action`,`branch`,`baseRef`,`task`,`name`],close_worktree:[`action`,`id`,`force`],list:[`action`],status:[`action`,`id`],merge:[`action`,`id`,`message`],prune:[`action`,`dryRun`],send:[`action`,`id`,`message`],messages:[`action`,`id`]},r=e.Object({action:e.Literal(t.spawn_worktree),branch:e.String({minLength:1}),baseRef:e.Optional(e.String({minLength:1})),task:e.Optional(e.String({minLength:1})),name:e.Optional(e.String({minLength:1}))},{additionalProperties:!1}),i=e.Object({action:e.Literal(t.close_worktree),id:e.String({minLength:1}),force:e.Optional(e.Boolean())},{additionalProperties:!1}),a=e.Object({action:e.Literal(t.list)},{additionalProperties:!1}),o=e.Object({action:e.Literal(t.status),id:e.String({minLength:1})},{additionalProperties:!1}),s=e.Object({action:e.Literal(t.merge),id:e.String({minLength:1}),message:e.Optional(e.String({minLength:1}))},{additionalProperties:!1}),c=e.Object({action:e.Literal(t.prune),dryRun:e.Optional(e.Boolean())},{additionalProperties:!1}),l=e.Object({action:e.Literal(t.send),id:e.String({minLength:1}),message:e.String({minLength:1})},{additionalProperties:!1}),u=e.Object({action:e.Literal(t.messages),id:e.String({minLength:1})},{additionalProperties:!1}),d=e.Union([r,i,a,o,s,c,l,u]);export{d as RunWorktreeParams,t as WORKTREE_ACTIONS,n as WORKTREE_ACTION_FIELDS};
2
- //# sourceMappingURL=runWorktreeTool.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runWorktreeTool.mjs","names":[],"sources":["../../src/schemas/runWorktreeTool.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\n/**\n * The tool's action vocabulary.\n *\n * One tool with an action field rather than six tools, matching `subagent`:\n * the actions share a subject and are meaningless apart from it, and six\n * separate tools would spend six description budgets teaching the same nouns.\n */\nexport const WORKTREE_ACTIONS = {\n spawn_worktree: 'spawn_worktree',\n close_worktree: 'close_worktree',\n list: 'list',\n status: 'status',\n merge: 'merge',\n prune: 'prune',\n send: 'send',\n messages: 'messages',\n} as const;\n\nexport type WorktreeAction = (typeof WORKTREE_ACTIONS)[keyof typeof WORKTREE_ACTIONS];\n\n/**\n * Which fields each action accepts.\n *\n * Rejecting an unknown field is what stops a plausible-looking call from doing\n * something other than what it reads like: `close_worktree` with `branch`\n * instead of `id` would otherwise close whatever the default resolved to.\n */\nexport const WORKTREE_ACTION_FIELDS: Record<WorktreeAction, readonly string[]> = {\n spawn_worktree: ['action', 'branch', 'baseRef', 'task', 'name'],\n close_worktree: ['action', 'id', 'force'],\n list: ['action'],\n status: ['action', 'id'],\n merge: ['action', 'id', 'message'],\n prune: ['action', 'dryRun'],\n send: ['action', 'id', 'message'],\n messages: ['action', 'id'],\n};\n\nconst SpawnParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.spawn_worktree),\n branch: Type.String({ minLength: 1 }),\n baseRef: Type.Optional(Type.String({ minLength: 1 })),\n task: Type.Optional(Type.String({ minLength: 1 })),\n name: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst CloseParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.close_worktree),\n id: Type.String({ minLength: 1 }),\n force: Type.Optional(Type.Boolean()),\n },\n { additionalProperties: false },\n);\n\nconst ListParams = Type.Object({ action: Type.Literal(WORKTREE_ACTIONS.list) }, { additionalProperties: false });\n\nconst StatusParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.status), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nconst MergeParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.merge),\n id: Type.String({ minLength: 1 }),\n message: Type.Optional(Type.String({ minLength: 1 })),\n },\n { additionalProperties: false },\n);\n\nconst PruneParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.prune), dryRun: Type.Optional(Type.Boolean()) },\n { additionalProperties: false },\n);\n\nconst SendParams = Type.Object(\n {\n action: Type.Literal(WORKTREE_ACTIONS.send),\n id: Type.String({ minLength: 1 }),\n message: Type.String({ minLength: 1 }),\n },\n { additionalProperties: false },\n);\n\nconst MessagesParams = Type.Object(\n { action: Type.Literal(WORKTREE_ACTIONS.messages), id: Type.String({ minLength: 1 }) },\n { additionalProperties: false },\n);\n\nexport const RunWorktreeParams = Type.Union([\n SpawnParams,\n CloseParams,\n ListParams,\n StatusParams,\n MergeParams,\n PruneParams,\n SendParams,\n MessagesParams,\n]);\n\nexport type RunWorktreeToolParams = Static<typeof RunWorktreeParams>;\n"],"mappings":"+BASA,MAAa,EAAmB,CAC9B,eAAgB,iBAChB,eAAgB,iBAChB,KAAM,OACN,OAAQ,SACR,MAAO,QACP,MAAO,QACP,KAAM,OACN,SAAU,UACZ,EAWa,EAAoE,CAC/E,eAAgB,CAAC,SAAU,SAAU,UAAW,OAAQ,MAAM,EAC9D,eAAgB,CAAC,SAAU,KAAM,OAAO,EACxC,KAAM,CAAC,QAAQ,EACf,OAAQ,CAAC,SAAU,IAAI,EACvB,MAAO,CAAC,SAAU,KAAM,SAAS,EACjC,MAAO,CAAC,SAAU,QAAQ,EAC1B,KAAM,CAAC,SAAU,KAAM,SAAS,EAChC,SAAU,CAAC,SAAU,IAAI,CAC3B,EAEM,EAAc,EAAK,OACvB,CACE,OAAQ,EAAK,QAAQ,EAAiB,cAAc,EACpD,OAAQ,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EACpC,QAAS,EAAK,SAAS,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,EACpD,KAAM,EAAK,SAAS,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,EACjD,KAAM,EAAK,SAAS,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,CACnD,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAc,EAAK,OACvB,CACE,OAAQ,EAAK,QAAQ,EAAiB,cAAc,EACpD,GAAI,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,MAAO,EAAK,SAAS,EAAK,QAAQ,CAAC,CACrC,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAa,EAAK,OAAO,CAAE,OAAQ,EAAK,QAAQ,EAAiB,IAAI,CAAE,EAAG,CAAE,qBAAsB,EAAM,CAAC,EAEzG,EAAe,EAAK,OACxB,CAAE,OAAQ,EAAK,QAAQ,EAAiB,MAAM,EAAG,GAAI,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAE,EACnF,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAc,EAAK,OACvB,CACE,OAAQ,EAAK,QAAQ,EAAiB,KAAK,EAC3C,GAAI,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,QAAS,EAAK,SAAS,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAC,CACtD,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAc,EAAK,OACvB,CAAE,OAAQ,EAAK,QAAQ,EAAiB,KAAK,EAAG,OAAQ,EAAK,SAAS,EAAK,QAAQ,CAAC,CAAE,EACtF,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAa,EAAK,OACtB,CACE,OAAQ,EAAK,QAAQ,EAAiB,IAAI,EAC1C,GAAI,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,EAChC,QAAS,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CACvC,EACA,CAAE,qBAAsB,EAAM,CAChC,EAEM,EAAiB,EAAK,OAC1B,CAAE,OAAQ,EAAK,QAAQ,EAAiB,QAAQ,EAAG,GAAI,EAAK,OAAO,CAAE,UAAW,CAAE,CAAC,CAAE,EACrF,CAAE,qBAAsB,EAAM,CAChC,EAEa,EAAoB,EAAK,MAAM,CAC1C,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC"}
@@ -1,2 +0,0 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:path");n=e.__toESM(n,1);function r(e,r){let i=n.default.dirname(e);t.default.mkdirSync(i,{recursive:!0});let a=n.default.join(i,`.${n.default.basename(e)}.${String(process.pid)}.tmp`);t.default.writeFileSync(a,`${JSON.stringify(r,null,2)}\n`,{mode:384}),t.default.renameSync(a,e)}function i(e){try{return JSON.parse(t.default.readFileSync(e,`utf8`))}catch{return}}exports.readJson=i,exports.writeJsonAtomic=r;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["path","fs"],"sources":["../../../src/services/atomicJson/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst OWNER_ONLY_FILE = 0o600;\n\n/**\n * Writes JSON so a reader never sees a half-written file.\n *\n * The registry is read by the same process that writes it, and by a later\n * process after a crash. A plain write can be interrupted between the truncate\n * and the last byte, which leaves a file that parses as nothing and loses every\n * record in it. Writing beside the target and renaming makes the swap atomic on\n * the same filesystem, so a reader sees either the old file or the new one.\n */\nexport function writeJsonAtomic(file: string, value: unknown): void {\n const directory = path.dirname(file);\n fs.mkdirSync(directory, { recursive: true });\n const temporary = path.join(directory, `.${path.basename(file)}.${String(process.pid)}.tmp`);\n fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\\n`, { mode: OWNER_ONLY_FILE });\n fs.renameSync(temporary, file);\n}\n\n/**\n * Reads JSON, treating every failure as absent.\n *\n * A missing file and an unparseable one mean the same thing to every caller\n * here: there is nothing to act on. Distinguishing them would only offer a\n * choice no caller wants to make.\n */\nexport function readJson<T>(file: string): T | undefined {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as T;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"8IAcA,SAAgB,EAAgB,EAAc,EAAsB,CAClE,IAAM,EAAYA,EAAAA,QAAK,QAAQ,CAAI,EACnC,EAAA,QAAG,UAAU,EAAW,CAAE,UAAW,EAAK,CAAC,EAC3C,IAAM,EAAYA,EAAAA,QAAK,KAAK,EAAW,IAAIA,EAAAA,QAAK,SAAS,CAAI,EAAE,GAAG,OAAO,QAAQ,GAAG,EAAE,KAAK,EAC3F,EAAA,QAAG,cAAc,EAAW,GAAG,KAAK,UAAU,EAAO,KAAM,CAAC,EAAE,IAAK,CAAE,KAAM,GAAgB,CAAC,EAC5F,EAAA,QAAG,WAAW,EAAW,CAAI,CAC/B,CASA,SAAgB,EAAY,EAA6B,CACvD,GAAI,CACF,OAAO,KAAK,MAAMC,EAAAA,QAAG,aAAa,EAAM,MAAM,CAAC,CACjD,MAAQ,CACN,MACF,CACF"}
@@ -1,2 +0,0 @@
1
- import e from"node:fs";import t from"node:path";function n(n,r){let i=t.dirname(n);e.mkdirSync(i,{recursive:!0});let a=t.join(i,`.${t.basename(n)}.${String(process.pid)}.tmp`);e.writeFileSync(a,`${JSON.stringify(r,null,2)}\n`,{mode:384}),e.renameSync(a,n)}function r(t){try{return JSON.parse(e.readFileSync(t,`utf8`))}catch{return}}export{r as readJson,n as writeJsonAtomic};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/atomicJson/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst OWNER_ONLY_FILE = 0o600;\n\n/**\n * Writes JSON so a reader never sees a half-written file.\n *\n * The registry is read by the same process that writes it, and by a later\n * process after a crash. A plain write can be interrupted between the truncate\n * and the last byte, which leaves a file that parses as nothing and loses every\n * record in it. Writing beside the target and renaming makes the swap atomic on\n * the same filesystem, so a reader sees either the old file or the new one.\n */\nexport function writeJsonAtomic(file: string, value: unknown): void {\n const directory = path.dirname(file);\n fs.mkdirSync(directory, { recursive: true });\n const temporary = path.join(directory, `.${path.basename(file)}.${String(process.pid)}.tmp`);\n fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\\n`, { mode: OWNER_ONLY_FILE });\n fs.renameSync(temporary, file);\n}\n\n/**\n * Reads JSON, treating every failure as absent.\n *\n * A missing file and an unparseable one mean the same thing to every caller\n * here: there is nothing to act on. Distinguishing them would only offer a\n * choice no caller wants to make.\n */\nexport function readJson<T>(file: string): T | undefined {\n try {\n return JSON.parse(fs.readFileSync(file, 'utf8')) as T;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"gDAcA,SAAgB,EAAgB,EAAc,EAAsB,CAClE,IAAM,EAAY,EAAK,QAAQ,CAAI,EACnC,EAAG,UAAU,EAAW,CAAE,UAAW,EAAK,CAAC,EAC3C,IAAM,EAAY,EAAK,KAAK,EAAW,IAAI,EAAK,SAAS,CAAI,EAAE,GAAG,OAAO,QAAQ,GAAG,EAAE,KAAK,EAC3F,EAAG,cAAc,EAAW,GAAG,KAAK,UAAU,EAAO,KAAM,CAAC,EAAE,IAAK,CAAE,KAAM,GAAgB,CAAC,EAC5F,EAAG,WAAW,EAAW,CAAI,CAC/B,CASA,SAAgB,EAAY,EAA6B,CACvD,GAAI,CACF,OAAO,KAAK,MAAM,EAAG,aAAa,EAAM,MAAM,CAAC,CACjD,MAAQ,CACN,MACF,CACF"}
@@ -1,2 +0,0 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:path");n=e.__toESM(n,1);const r=`node_modules`;function i(e){let i={outputs:[],modules:[]},a=(o,s)=>{let c;try{c=t.default.readdirSync(n.default.join(e,o),{withFileTypes:!0})}catch{return}for(let e of c){if(!e.isDirectory())continue;let t=o===``?e.name:`${o}/${e.name}`;if(e.name!==`.git`){if(e.name===r){i.modules.push(t);continue}if(e.name===`dist`){i.outputs.push(t);continue}s<4&&a(t,s+1)}}};return a(``,1),i}function a(e,a){if(!t.default.existsSync(n.default.join(e,r)))return{kind:`skipped`,reason:`no-modules`};let o=i(e),s=0,c=0;for(let r of o.modules){let i=n.default.join(a,r);if(!t.default.existsSync(i))try{t.default.mkdirSync(n.default.dirname(i),{recursive:!0}),t.default.symlinkSync(n.default.join(e,r),i,`dir`),c+=1}catch{}}for(let r of o.outputs){let i=n.default.join(a,r);if(!t.default.existsSync(i))try{t.default.mkdirSync(n.default.dirname(i),{recursive:!0}),t.default.cpSync(n.default.join(e,r),i,{recursive:!0}),s+=1}catch{}}return{kind:`mirrored`,copied:s,linked:c}}exports.mirrorComposition=a;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["fs","path"],"sources":["../../../src/services/compositionMirror/index.ts"],"sourcesContent":["/**\n * Giving a new worktree the build output its parent checkout already has.\n *\n * DESIGN PATTERNS:\n * - Mirrors, never builds. Everything here is a copy or a symlink of something\n * the parent checkout already produced, so it costs seconds and cannot fail\n * the way a package manager or a compiler can.\n * - `node_modules` is linked, `dist` is copied. The module tree is gigabytes\n * and read-only in practice, so a link is right; build output is small and a\n * link would send a build run inside the worktree straight into the parent's\n * directory.\n * - Absent parent output means nothing to do. A repository with no\n * `node_modules` at its root is either not a JS project or not installed, and\n * either way this has no opinion about it, so a Rust, Go or Python worktree\n * pays nothing.\n *\n * WHY THIS EXISTS:\n * A DoomPi session composes the extensions its repository's config names, and\n * this repository names its own workspace packages by relative path. Those\n * packages declare `pi.extensions` under `dist/`, which git does not track, so\n * a fresh worktree resolves none of them and the session dies on start. The\n * parent checkout has already built exactly what the child needs.\n *\n * AVOID:\n * - Recursing into `node_modules`. The scan is bounded and skips it; without\n * that this walks a gigabyte to find nothing.\n * - Treating a mirror failure as fatal. The worktree is good either way; only\n * the session's composition is poorer for it.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** Directories that are build output worth copying into a new worktree. */\nconst OUTPUT_DIRECTORY = 'dist';\nconst MODULES_DIRECTORY = 'node_modules';\nconst GIT_DIRECTORY = '.git';\n/**\n * How deep the scan goes.\n *\n * Four levels reaches `layers/<group>/<package>/dist` in this repository's\n * layout, and a workspace that buries a package deeper than that gets a\n * partial mirror rather than a slow one.\n */\nconst MAX_DEPTH = 4;\n\nexport type MirrorOutcome =\n | { kind: 'skipped'; reason: 'no-modules' }\n | { kind: 'mirrored'; copied: number; linked: number };\n\ninterface Found {\n /** Paths relative to the source root. */\n outputs: string[];\n modules: string[];\n}\n\nfunction scan(root: string): Found {\n const found: Found = { outputs: [], modules: [] };\n const walk = (relative: string, depth: number): void => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(path.join(root, relative), { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const child = relative === '' ? entry.name : `${relative}/${entry.name}`;\n if (entry.name === GIT_DIRECTORY) continue;\n // Both of these are destinations, not places to look inside.\n if (entry.name === MODULES_DIRECTORY) {\n found.modules.push(child);\n continue;\n }\n if (entry.name === OUTPUT_DIRECTORY) {\n found.outputs.push(child);\n continue;\n }\n if (depth < MAX_DEPTH) walk(child, depth + 1);\n }\n };\n walk('', 1);\n return found;\n}\n\n/**\n * Copies the parent's build output into a worktree and links its modules.\n *\n * Individual failures are counted out rather than thrown: a mirror that lands\n * partly is still better than none, and the caller has a worktree either way.\n */\nexport function mirrorComposition(source: string, target: string): MirrorOutcome {\n if (!fs.existsSync(path.join(source, MODULES_DIRECTORY))) return { kind: 'skipped', reason: 'no-modules' };\n\n const found = scan(source);\n let copied = 0;\n let linked = 0;\n\n for (const relative of found.modules) {\n const destination = path.join(target, relative);\n if (fs.existsSync(destination)) continue;\n try {\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.symlinkSync(path.join(source, relative), destination, 'dir');\n linked += 1;\n } catch {\n // A link the filesystem refuses costs this package one resolution, not\n // the worktree.\n }\n }\n\n for (const relative of found.outputs) {\n const destination = path.join(target, relative);\n if (fs.existsSync(destination)) continue;\n try {\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.cpSync(path.join(source, relative), destination, { recursive: true });\n copied += 1;\n } catch {\n // Same reasoning as a failed link.\n }\n }\n\n return { kind: 'mirrored', copied, linked };\n}\n"],"mappings":"8IAiCA,MACM,EAAoB,eAqB1B,SAAS,EAAK,EAAqB,CACjC,IAAM,EAAe,CAAE,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,EAC1C,GAAQ,EAAkB,IAAwB,CACtD,IAAI,EACJ,GAAI,CACF,EAAUA,EAAAA,QAAG,YAAYC,EAAAA,QAAK,KAAK,EAAM,CAAQ,EAAG,CAAE,cAAe,EAAK,CAAC,CAC7E,MAAQ,CACN,MACF,CACA,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,CAAC,EAAM,YAAY,EAAG,SAC1B,IAAM,EAAQ,IAAa,GAAK,EAAM,KAAO,GAAG,EAAS,GAAG,EAAM,OAC9D,KAAM,OAAS,OAEnB,IAAI,EAAM,OAAS,EAAmB,CACpC,EAAM,QAAQ,KAAK,CAAK,EACxB,QACF,CACA,GAAI,EAAM,OAAS,OAAkB,CACnC,EAAM,QAAQ,KAAK,CAAK,EACxB,QACF,CACI,EAAQ,GAAW,EAAK,EAAO,EAAQ,CAAC,CAL5C,CAMF,CACF,EAEA,OADA,EAAK,GAAI,CAAC,EACH,CACT,CAQA,SAAgB,EAAkB,EAAgB,EAA+B,CAC/E,GAAI,CAACD,EAAAA,QAAG,WAAWC,EAAAA,QAAK,KAAK,EAAQ,CAAiB,CAAC,EAAG,MAAO,CAAE,KAAM,UAAW,OAAQ,YAAa,EAEzG,IAAM,EAAQ,EAAK,CAAM,EACrB,EAAS,EACT,EAAS,EAEb,IAAK,IAAM,KAAY,EAAM,QAAS,CACpC,IAAM,EAAcA,EAAAA,QAAK,KAAK,EAAQ,CAAQ,EAC1CD,MAAAA,QAAG,WAAW,CAAW,EAC7B,GAAI,CACF,EAAA,QAAG,UAAUC,EAAAA,QAAK,QAAQ,CAAW,EAAG,CAAE,UAAW,EAAK,CAAC,EAC3D,EAAA,QAAG,YAAYA,EAAAA,QAAK,KAAK,EAAQ,CAAQ,EAAG,EAAa,KAAK,EAC9D,GAAU,CACZ,MAAQ,CAGR,CACF,CAEA,IAAK,IAAM,KAAY,EAAM,QAAS,CACpC,IAAM,EAAcA,EAAAA,QAAK,KAAK,EAAQ,CAAQ,EAC1CD,MAAAA,QAAG,WAAW,CAAW,EAC7B,GAAI,CACF,EAAA,QAAG,UAAUC,EAAAA,QAAK,QAAQ,CAAW,EAAG,CAAE,UAAW,EAAK,CAAC,EAC3D,EAAA,QAAG,OAAOA,EAAAA,QAAK,KAAK,EAAQ,CAAQ,EAAG,EAAa,CAAE,UAAW,EAAK,CAAC,EACvE,GAAU,CACZ,MAAQ,CAER,CACF,CAEA,MAAO,CAAE,KAAM,WAAY,SAAQ,QAAO,CAC5C"}
@@ -1,2 +0,0 @@
1
- import e from"node:fs";import t from"node:path";const n=`node_modules`;function r(r){let i={outputs:[],modules:[]},a=(o,s)=>{let c;try{c=e.readdirSync(t.join(r,o),{withFileTypes:!0})}catch{return}for(let e of c){if(!e.isDirectory())continue;let t=o===``?e.name:`${o}/${e.name}`;if(e.name!==`.git`){if(e.name===n){i.modules.push(t);continue}if(e.name===`dist`){i.outputs.push(t);continue}s<4&&a(t,s+1)}}};return a(``,1),i}function i(i,a){if(!e.existsSync(t.join(i,n)))return{kind:`skipped`,reason:`no-modules`};let o=r(i),s=0,c=0;for(let n of o.modules){let r=t.join(a,n);if(!e.existsSync(r))try{e.mkdirSync(t.dirname(r),{recursive:!0}),e.symlinkSync(t.join(i,n),r,`dir`),c+=1}catch{}}for(let n of o.outputs){let r=t.join(a,n);if(!e.existsSync(r))try{e.mkdirSync(t.dirname(r),{recursive:!0}),e.cpSync(t.join(i,n),r,{recursive:!0}),s+=1}catch{}}return{kind:`mirrored`,copied:s,linked:c}}export{i as mirrorComposition};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/compositionMirror/index.ts"],"sourcesContent":["/**\n * Giving a new worktree the build output its parent checkout already has.\n *\n * DESIGN PATTERNS:\n * - Mirrors, never builds. Everything here is a copy or a symlink of something\n * the parent checkout already produced, so it costs seconds and cannot fail\n * the way a package manager or a compiler can.\n * - `node_modules` is linked, `dist` is copied. The module tree is gigabytes\n * and read-only in practice, so a link is right; build output is small and a\n * link would send a build run inside the worktree straight into the parent's\n * directory.\n * - Absent parent output means nothing to do. A repository with no\n * `node_modules` at its root is either not a JS project or not installed, and\n * either way this has no opinion about it, so a Rust, Go or Python worktree\n * pays nothing.\n *\n * WHY THIS EXISTS:\n * A DoomPi session composes the extensions its repository's config names, and\n * this repository names its own workspace packages by relative path. Those\n * packages declare `pi.extensions` under `dist/`, which git does not track, so\n * a fresh worktree resolves none of them and the session dies on start. The\n * parent checkout has already built exactly what the child needs.\n *\n * AVOID:\n * - Recursing into `node_modules`. The scan is bounded and skips it; without\n * that this walks a gigabyte to find nothing.\n * - Treating a mirror failure as fatal. The worktree is good either way; only\n * the session's composition is poorer for it.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** Directories that are build output worth copying into a new worktree. */\nconst OUTPUT_DIRECTORY = 'dist';\nconst MODULES_DIRECTORY = 'node_modules';\nconst GIT_DIRECTORY = '.git';\n/**\n * How deep the scan goes.\n *\n * Four levels reaches `layers/<group>/<package>/dist` in this repository's\n * layout, and a workspace that buries a package deeper than that gets a\n * partial mirror rather than a slow one.\n */\nconst MAX_DEPTH = 4;\n\nexport type MirrorOutcome =\n | { kind: 'skipped'; reason: 'no-modules' }\n | { kind: 'mirrored'; copied: number; linked: number };\n\ninterface Found {\n /** Paths relative to the source root. */\n outputs: string[];\n modules: string[];\n}\n\nfunction scan(root: string): Found {\n const found: Found = { outputs: [], modules: [] };\n const walk = (relative: string, depth: number): void => {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(path.join(root, relative), { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const child = relative === '' ? entry.name : `${relative}/${entry.name}`;\n if (entry.name === GIT_DIRECTORY) continue;\n // Both of these are destinations, not places to look inside.\n if (entry.name === MODULES_DIRECTORY) {\n found.modules.push(child);\n continue;\n }\n if (entry.name === OUTPUT_DIRECTORY) {\n found.outputs.push(child);\n continue;\n }\n if (depth < MAX_DEPTH) walk(child, depth + 1);\n }\n };\n walk('', 1);\n return found;\n}\n\n/**\n * Copies the parent's build output into a worktree and links its modules.\n *\n * Individual failures are counted out rather than thrown: a mirror that lands\n * partly is still better than none, and the caller has a worktree either way.\n */\nexport function mirrorComposition(source: string, target: string): MirrorOutcome {\n if (!fs.existsSync(path.join(source, MODULES_DIRECTORY))) return { kind: 'skipped', reason: 'no-modules' };\n\n const found = scan(source);\n let copied = 0;\n let linked = 0;\n\n for (const relative of found.modules) {\n const destination = path.join(target, relative);\n if (fs.existsSync(destination)) continue;\n try {\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.symlinkSync(path.join(source, relative), destination, 'dir');\n linked += 1;\n } catch {\n // A link the filesystem refuses costs this package one resolution, not\n // the worktree.\n }\n }\n\n for (const relative of found.outputs) {\n const destination = path.join(target, relative);\n if (fs.existsSync(destination)) continue;\n try {\n fs.mkdirSync(path.dirname(destination), { recursive: true });\n fs.cpSync(path.join(source, relative), destination, { recursive: true });\n copied += 1;\n } catch {\n // Same reasoning as a failed link.\n }\n }\n\n return { kind: 'mirrored', copied, linked };\n}\n"],"mappings":"gDAiCA,MACM,EAAoB,eAqB1B,SAAS,EAAK,EAAqB,CACjC,IAAM,EAAe,CAAE,QAAS,CAAC,EAAG,QAAS,CAAC,CAAE,EAC1C,GAAQ,EAAkB,IAAwB,CACtD,IAAI,EACJ,GAAI,CACF,EAAU,EAAG,YAAY,EAAK,KAAK,EAAM,CAAQ,EAAG,CAAE,cAAe,EAAK,CAAC,CAC7E,MAAQ,CACN,MACF,CACA,IAAK,IAAM,KAAS,EAAS,CAC3B,GAAI,CAAC,EAAM,YAAY,EAAG,SAC1B,IAAM,EAAQ,IAAa,GAAK,EAAM,KAAO,GAAG,EAAS,GAAG,EAAM,OAC9D,KAAM,OAAS,OAEnB,IAAI,EAAM,OAAS,EAAmB,CACpC,EAAM,QAAQ,KAAK,CAAK,EACxB,QACF,CACA,GAAI,EAAM,OAAS,OAAkB,CACnC,EAAM,QAAQ,KAAK,CAAK,EACxB,QACF,CACI,EAAQ,GAAW,EAAK,EAAO,EAAQ,CAAC,CAL5C,CAMF,CACF,EAEA,OADA,EAAK,GAAI,CAAC,EACH,CACT,CAQA,SAAgB,EAAkB,EAAgB,EAA+B,CAC/E,GAAI,CAAC,EAAG,WAAW,EAAK,KAAK,EAAQ,CAAiB,CAAC,EAAG,MAAO,CAAE,KAAM,UAAW,OAAQ,YAAa,EAEzG,IAAM,EAAQ,EAAK,CAAM,EACrB,EAAS,EACT,EAAS,EAEb,IAAK,IAAM,KAAY,EAAM,QAAS,CACpC,IAAM,EAAc,EAAK,KAAK,EAAQ,CAAQ,EAC1C,MAAG,WAAW,CAAW,EAC7B,GAAI,CACF,EAAG,UAAU,EAAK,QAAQ,CAAW,EAAG,CAAE,UAAW,EAAK,CAAC,EAC3D,EAAG,YAAY,EAAK,KAAK,EAAQ,CAAQ,EAAG,EAAa,KAAK,EAC9D,GAAU,CACZ,MAAQ,CAGR,CACF,CAEA,IAAK,IAAM,KAAY,EAAM,QAAS,CACpC,IAAM,EAAc,EAAK,KAAK,EAAQ,CAAQ,EAC1C,MAAG,WAAW,CAAW,EAC7B,GAAI,CACF,EAAG,UAAU,EAAK,QAAQ,CAAW,EAAG,CAAE,UAAW,EAAK,CAAC,EAC3D,EAAG,OAAO,EAAK,KAAK,EAAQ,CAAQ,EAAG,EAAa,CAAE,UAAW,EAAK,CAAC,EACvE,GAAU,CACZ,MAAQ,CAER,CACF,CAEA,MAAO,CAAE,KAAM,WAAY,SAAQ,QAAO,CAC5C"}
@@ -1,2 +0,0 @@
1
- var e=class extends Error{code;retryable;recovery;constructor(e,t,n,r){super(`[${e}] ${t}\nRecovery: ${r}`),this.code=e,this.retryable=n,this.recovery=r,this.name=`DoomGitExpectedError`}},t=class extends Error{constructor(e){super(e),this.name=`HubUnavailableError`}};function n(t,n){return new e(`invalid_request`,t,!1,n)}exports.DoomGitExpectedError=e,exports.HubUnavailableError=t,exports.invalidRequest=n;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/services/errors/index.ts"],"sourcesContent":["/**\n * Expected failures, kept private to this package.\n *\n * `@agimon-ai/doompi-core` does not export `invalidRequest` or\n * an expected-error base, so this mirrors doompi-team's shape rather than\n * reaching across a layer boundary for it. The duplication is deliberate and\n * small; a shared helper would be the better answer only once a third package\n * needs one.\n */\n\nexport type DoomGitErrorCode =\n | 'invalid_request'\n | 'not_a_repository'\n | 'worktree_exists'\n | 'worktree_not_found'\n | 'worktree_not_owned'\n | 'worktree_peer_unavailable'\n | 'worktree_dirty'\n | 'hub_unavailable'\n | 'spawn_cancelled'\n | 'registry_write_failed'\n | 'message_too_large'\n | 'git_failed';\n\nexport class DoomGitExpectedError extends Error {\n constructor(\n readonly code: DoomGitErrorCode,\n message: string,\n readonly retryable: boolean,\n readonly recovery: string,\n ) {\n // The recovery line rides in the message because a tool result is read as\n // text: an error the model cannot act on costs a turn to rediscover.\n super(`[${code}] ${message}\\nRecovery: ${recovery}`);\n this.name = 'DoomGitExpectedError';\n }\n}\n\n/** Raised when a worktree action needs the canonical hub but it is not injected. */\nexport class HubUnavailableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HubUnavailableError';\n }\n}\n\nexport function invalidRequest(message: string, recovery: string): DoomGitExpectedError {\n return new DoomGitExpectedError('invalid_request', message, false, recovery);\n}\n"],"mappings":"AAwBA,IAAa,EAAb,cAA0C,KAAM,CAEnC,KAEA,UACA,SAJX,YACE,EACA,EACA,EACA,EACA,CAGA,MAAM,IAAI,EAAK,IAAI,EAAQ,cAAc,GAAU,EAP1C,KAAA,KAAA,EAEA,KAAA,UAAA,EACA,KAAA,SAAA,EAKT,KAAK,KAAO,sBACd,CACF,EAGa,EAAb,cAAyC,KAAM,CAC7C,YAAY,EAAiB,CAC3B,MAAM,CAAO,EACb,KAAK,KAAO,qBACd,CACF,EAEA,SAAgB,EAAe,EAAiB,EAAwC,CACtF,OAAO,IAAI,EAAqB,kBAAmB,EAAS,GAAO,CAAQ,CAC7E"}
@@ -1,2 +0,0 @@
1
- var e=class extends Error{code;retryable;recovery;constructor(e,t,n,r){super(`[${e}] ${t}\nRecovery: ${r}`),this.code=e,this.retryable=n,this.recovery=r,this.name=`DoomGitExpectedError`}},t=class extends Error{constructor(e){super(e),this.name=`HubUnavailableError`}};function n(t,n){return new e(`invalid_request`,t,!1,n)}export{e as DoomGitExpectedError,t as HubUnavailableError,n as invalidRequest};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/errors/index.ts"],"sourcesContent":["/**\n * Expected failures, kept private to this package.\n *\n * `@agimon-ai/doompi-core` does not export `invalidRequest` or\n * an expected-error base, so this mirrors doompi-team's shape rather than\n * reaching across a layer boundary for it. The duplication is deliberate and\n * small; a shared helper would be the better answer only once a third package\n * needs one.\n */\n\nexport type DoomGitErrorCode =\n | 'invalid_request'\n | 'not_a_repository'\n | 'worktree_exists'\n | 'worktree_not_found'\n | 'worktree_not_owned'\n | 'worktree_peer_unavailable'\n | 'worktree_dirty'\n | 'hub_unavailable'\n | 'spawn_cancelled'\n | 'registry_write_failed'\n | 'message_too_large'\n | 'git_failed';\n\nexport class DoomGitExpectedError extends Error {\n constructor(\n readonly code: DoomGitErrorCode,\n message: string,\n readonly retryable: boolean,\n readonly recovery: string,\n ) {\n // The recovery line rides in the message because a tool result is read as\n // text: an error the model cannot act on costs a turn to rediscover.\n super(`[${code}] ${message}\\nRecovery: ${recovery}`);\n this.name = 'DoomGitExpectedError';\n }\n}\n\n/** Raised when a worktree action needs the canonical hub but it is not injected. */\nexport class HubUnavailableError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'HubUnavailableError';\n }\n}\n\nexport function invalidRequest(message: string, recovery: string): DoomGitExpectedError {\n return new DoomGitExpectedError('invalid_request', message, false, recovery);\n}\n"],"mappings":"AAwBA,IAAa,EAAb,cAA0C,KAAM,CAEnC,KAEA,UACA,SAJX,YACE,EACA,EACA,EACA,EACA,CAGA,MAAM,IAAI,EAAK,IAAI,EAAQ,cAAc,GAAU,EAP1C,KAAA,KAAA,EAEA,KAAA,UAAA,EACA,KAAA,SAAA,EAKT,KAAK,KAAO,sBACd,CACF,EAGa,EAAb,cAAyC,KAAM,CAC7C,YAAY,EAAiB,CAC3B,MAAM,CAAO,EACb,KAAK,KAAO,qBACd,CACF,EAEA,SAAgB,EAAe,EAAiB,EAAwC,CACtF,OAAO,IAAI,EAAqB,kBAAmB,EAAS,GAAO,CAAQ,CAC7E"}
@@ -1,2 +0,0 @@
1
- var e=class{async execute(){return{message:`Show git worktrees owned by this session`,level:`info`}}};exports.DefaultGitExtensionService=e;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/services/extensionService/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n"],"mappings":"AAGA,IAAa,EAAb,KAAuE,CACrE,MAAM,SAAuC,CAC3C,MAAO,CAAE,QAAS,2CAA4C,MAAO,MAAO,CAC9E,CACF"}
@@ -1,8 +0,0 @@
1
- import { GitExtensionResult, GitExtensionService } from "../../types/extension.cjs";
2
- //#region src/services/extensionService/index.d.ts
3
- declare class DefaultGitExtensionService implements GitExtensionService {
4
- execute(): Promise<GitExtensionResult>;
5
- }
6
- //#endregion
7
- export { DefaultGitExtensionService };
8
- //# sourceMappingURL=index.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/extensionService/index.ts"],"mappings":";;cAGa,sCAAsC;EAC3C,WAAW,QAAQ"}
@@ -1,8 +0,0 @@
1
- import { GitExtensionResult, GitExtensionService } from "../../types/extension.mjs";
2
- //#region src/services/extensionService/index.d.ts
3
- declare class DefaultGitExtensionService implements GitExtensionService {
4
- execute(): Promise<GitExtensionResult>;
5
- }
6
- //#endregion
7
- export { DefaultGitExtensionService };
8
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/services/extensionService/index.ts"],"mappings":";;cAGa,sCAAsC;EAC3C,WAAW,QAAQ"}
@@ -1,2 +0,0 @@
1
- var e=class{async execute(){return{message:`Show git worktrees owned by this session`,level:`info`}}};export{e as DefaultGitExtensionService};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/extensionService/index.ts"],"sourcesContent":["// @scaffold-generated\nimport type { GitExtensionResult, GitExtensionService } from '../../types/extension';\n\nexport class DefaultGitExtensionService implements GitExtensionService {\n async execute(): Promise<GitExtensionResult> {\n return { message: 'Show git worktrees owned by this session', level: 'info' };\n }\n}\n"],"mappings":"AAGA,IAAa,EAAb,KAAuE,CACrE,MAAM,SAAuC,CAC3C,MAAO,CAAE,QAAS,2CAA4C,MAAO,MAAO,CAC9E,CACF"}
@@ -1,4 +0,0 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:child_process"),n=require("node:fs");n=e.__toESM(n,1);const r=3e4;function i(e,n,r){return new Promise(i=>{(0,t.execFile)(`git`,[...n],{cwd:e,timeout:r,maxBuffer:1e6,env:{...process.env,LC_ALL:`C`}},(e,t,n)=>{i({code:e&&typeof e.code==`number`?e.code:+!!e,stdout:String(t),stderr:String(n)})})})}function a(e,t){return Error(`git ${e} failed (exit ${String(t.code)}, ${String(t.stderr.length)} bytes of stderr)`)}function o(e){let t=e.toLowerCase();return t.includes(`is not a working tree`)||t.includes(`cannot remove working tree`)}function s(){let e=async e=>{await i(e,[`worktree`,`prune`],15e3)};return{async addWorktree({repositoryRoot:e,path:t,branch:n,baseRef:r}){let o=await i(e,[`worktree`,`add`,`-b`,n,t,r],3e5);if(o.code!==0)throw a(`worktree add`,o)},async removeWorktree({repositoryRoot:t,path:r,force:s}){let c=await i(t,[`worktree`,`remove`,...s?[`--force`]:[],r],3e5);if(c.code!==0){if(o(c.stderr)&&!n.default.existsSync(r)){await e(t);return}throw a(`worktree remove`,c)}},async deleteBranch({repositoryRoot:e,branch:t}){return(await i(e,[`branch`,`-d`,t],r)).code===0},pruneWorktrees:e,async listWorktreePaths(e){let t=await i(e,[`worktree`,`list`,`--porcelain`],r);return t.code===0?t.stdout.split(`
2
- `).filter(e=>e.startsWith(`worktree `)).map(e=>e.slice(9).trim()).filter(e=>e!==``):[]},async dirtyFiles(e){let t=await i(e,[`status`,`--porcelain`],r);return t.code===0?t.stdout.split(`
3
- `).map(e=>e.slice(3).trim()).filter(e=>e!==``):[]},async repositoryRoot(e){let t=await i(e,[`rev-parse`,`--show-toplevel`],r);if(t.code!==0)return;let n=t.stdout.trim();return n===``?void 0:n},async currentBranch(e){let t=await i(e,[`rev-parse`,`--abbrev-ref`,`HEAD`],r);if(t.code!==0)return;let n=t.stdout.trim();return n===``?void 0:n},async mergeBranch({repositoryRoot:e,branch:t,message:n}){let o=await i(e,[`merge`,`--no-ff`,...n===void 0?[]:[`-m`,n],t],r);if(o.code!==0)throw a(`merge`,o)}}}exports.createWorktreeGit=s;
4
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["fs"],"sources":["../../../src/services/gitCli/index.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\n\nimport type { WorktreeGit } from '../../types/worktreeRegistry';\n\n/**\n * Git, as this package needs it.\n *\n * The timeouts are not uniform because the operations are not comparable. A\n * read answers in milliseconds; `worktree add` copies an entire checkout and\n * `worktree remove` deletes one, both bounded by the filesystem rather than by\n * git, and both minutes rather than seconds on a large repository or on\n * Windows. A single timeout would either fail honest work or hang on a wedged\n * one.\n */\nconst READ_TIMEOUT_MS = 30_000;\nconst ADD_TIMEOUT_MS = 300_000;\nconst REMOVE_TIMEOUT_MS = 300_000;\nconst PRUNE_TIMEOUT_MS = 15_000;\nconst MAX_OUTPUT_BYTES = 1_000_000;\n\ninterface GitResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Runs git and reports the outcome without ever throwing on a non-zero exit.\n *\n * LC_ALL is pinned because two callers below decide what to do by matching\n * git's own wording, and a translated message would silently turn a recognised\n * condition into an unrecognised failure.\n */\nfunction git(cwd: string, args: readonly string[], timeout: number): Promise<GitResult> {\n return new Promise((resolve) => {\n execFile(\n 'git',\n [...args],\n { cwd, timeout, maxBuffer: MAX_OUTPUT_BYTES, env: { ...process.env, LC_ALL: 'C' } },\n (error, stdout, stderr) => {\n const code = error && typeof error.code === 'number' ? error.code : error ? 1 : 0;\n resolve({ code, stdout: String(stdout), stderr: String(stderr) });\n },\n );\n });\n}\n\n/**\n * The message a failed git call is allowed to surface.\n *\n * Raw stderr never travels: it can carry a remote URL with a token in it, and\n * this text ends up in a tool result the model reads and may repeat.\n */\nfunction failure(operation: string, result: GitResult): Error {\n return new Error(\n `git ${operation} failed (exit ${String(result.code)}, ${String(result.stderr.length)} bytes of stderr)`,\n );\n}\n\n/** Git's own words for \"that worktree is not there any more\". */\nfunction missingWorktree(stderr: string): boolean {\n const normalized = stderr.toLowerCase();\n return normalized.includes('is not a working tree') || normalized.includes('cannot remove working tree');\n}\n\nexport function createWorktreeGit(): WorktreeGit {\n const prune = async (repositoryRoot: string): Promise<void> => {\n await git(repositoryRoot, ['worktree', 'prune'], PRUNE_TIMEOUT_MS);\n };\n\n return {\n async addWorktree({ repositoryRoot, path, branch, baseRef }) {\n const result = await git(repositoryRoot, ['worktree', 'add', '-b', branch, path, baseRef], ADD_TIMEOUT_MS);\n if (result.code !== 0) throw failure('worktree add', result);\n },\n\n async removeWorktree({ repositoryRoot, path, force }) {\n const args = ['worktree', 'remove', ...(force ? ['--force'] : []), path];\n const result = await git(repositoryRoot, args, REMOVE_TIMEOUT_MS);\n if (result.code === 0) return;\n // A directory deleted behind git's back leaves an administrative entry\n // that makes a later `worktree add` at the same path refuse. Treating\n // \"already gone\" as success and pruning is what keeps that path reusable,\n // and it makes remove idempotent for a caller retrying after a crash.\n if (missingWorktree(result.stderr) && !fs.existsSync(path)) {\n await prune(repositoryRoot);\n return;\n }\n throw failure('worktree remove', result);\n },\n\n async deleteBranch({ repositoryRoot, branch }) {\n // -d, never -D: git refuses a branch that still holds unmerged commits,\n // and that refusal is the whole safety property. A rollback that could\n // throw away work someone committed in the worktree is worse than a\n // branch left behind.\n const result = await git(repositoryRoot, ['branch', '-d', branch], READ_TIMEOUT_MS);\n return result.code === 0;\n },\n pruneWorktrees: prune,\n\n async listWorktreePaths(repositoryRoot) {\n const result = await git(repositoryRoot, ['worktree', 'list', '--porcelain'], READ_TIMEOUT_MS);\n if (result.code !== 0) return [];\n return result.stdout\n .split('\\n')\n .filter((line) => line.startsWith('worktree '))\n .map((line) => line.slice('worktree '.length).trim())\n .filter((line) => line !== '');\n },\n\n async dirtyFiles(path) {\n const result = await git(path, ['status', '--porcelain'], READ_TIMEOUT_MS);\n if (result.code !== 0) return [];\n return result.stdout\n .split('\\n')\n .map((line) => line.slice(3).trim())\n .filter((line) => line !== '');\n },\n\n async repositoryRoot(cwd) {\n const result = await git(cwd, ['rev-parse', '--show-toplevel'], READ_TIMEOUT_MS);\n if (result.code !== 0) return undefined;\n const root = result.stdout.trim();\n return root === '' ? undefined : root;\n },\n\n async currentBranch(cwd) {\n const result = await git(cwd, ['rev-parse', '--abbrev-ref', 'HEAD'], READ_TIMEOUT_MS);\n if (result.code !== 0) return undefined;\n const branch = result.stdout.trim();\n return branch === '' ? undefined : branch;\n },\n\n async mergeBranch({ repositoryRoot, branch, message }) {\n // --no-ff so the worktree's work stays identifiable as a unit after the\n // fact. A fast-forward would erase the fact that it was ever separate,\n // which is the one thing worth keeping about a worktree.\n const args = ['merge', '--no-ff', ...(message === undefined ? [] : ['-m', message]), branch];\n const result = await git(repositoryRoot, args, READ_TIMEOUT_MS);\n if (result.code === 0) return;\n // A conflicted merge leaves the parent mid-merge, which is a state the\n // person has to resolve; aborting for them would throw away the conflict\n // markers they need to see.\n throw failure('merge', result);\n },\n };\n}\n"],"mappings":"kIAeA,MAAM,EAAkB,IAmBxB,SAAS,EAAI,EAAa,EAAyB,EAAqC,CACtF,OAAO,IAAI,QAAS,GAAY,EAC9B,EAAA,EAAA,SAAA,CACE,MACA,CAAC,GAAG,CAAI,EACR,CAAE,MAAK,UAAS,UAAW,IAAkB,IAAK,CAAE,GAAG,QAAQ,IAAK,OAAQ,GAAI,CAAE,GACjF,EAAO,EAAQ,IAAW,CAEzB,EAAQ,CAAE,KADG,GAAS,OAAO,EAAM,MAAS,SAAW,EAAM,KAAO,KACpD,OAAQ,OAAO,CAAM,EAAG,OAAQ,OAAO,CAAM,CAAE,CAAC,CAClE,CACF,CACF,CAAC,CACH,CAQA,SAAS,EAAQ,EAAmB,EAA0B,CAC5D,OAAW,MACT,OAAO,EAAU,gBAAgB,OAAO,EAAO,IAAI,EAAE,IAAI,OAAO,EAAO,OAAO,MAAM,EAAE,kBACxF,CACF,CAGA,SAAS,EAAgB,EAAyB,CAChD,IAAM,EAAa,EAAO,YAAY,EACtC,OAAO,EAAW,SAAS,uBAAuB,GAAK,EAAW,SAAS,4BAA4B,CACzG,CAEA,SAAgB,GAAiC,CAC/C,IAAM,EAAQ,KAAO,IAA0C,CAC7D,MAAM,EAAI,EAAgB,CAAC,WAAY,OAAO,EAAG,IAAgB,CACnE,EAEA,MAAO,CACL,MAAM,YAAY,CAAE,iBAAgB,OAAM,SAAQ,WAAW,CAC3D,IAAM,EAAS,MAAM,EAAI,EAAgB,CAAC,WAAY,MAAO,KAAM,EAAQ,EAAM,CAAO,EAAG,GAAc,EACzG,GAAI,EAAO,OAAS,EAAG,MAAM,EAAQ,eAAgB,CAAM,CAC7D,EAEA,MAAM,eAAe,CAAE,iBAAgB,OAAM,SAAS,CAEpD,IAAM,EAAS,MAAM,EAAI,EAAgB,CAD3B,WAAY,SAAU,GAAI,EAAQ,CAAC,SAAS,EAAI,CAAC,EAAI,CACvB,EAAG,GAAiB,EAC5D,KAAO,OAAS,EAKpB,IAAI,EAAgB,EAAO,MAAM,GAAK,CAACA,EAAAA,QAAG,WAAW,CAAI,EAAG,CAC1D,MAAM,EAAM,CAAc,EAC1B,MACF,CACA,MAAM,EAAQ,kBAAmB,CAAM,CADvC,CAEF,EAEA,MAAM,aAAa,CAAE,iBAAgB,UAAU,CAM7C,OAAO,MADc,EAAI,EAAgB,CAAC,SAAU,KAAM,CAAM,EAAG,CAAe,EAAA,CACpE,OAAS,CACzB,EACA,eAAgB,EAEhB,MAAM,kBAAkB,EAAgB,CACtC,IAAM,EAAS,MAAM,EAAI,EAAgB,CAAC,WAAY,OAAQ,aAAa,EAAG,CAAe,EAE7F,OADI,EAAO,OAAS,EACb,EAAO,OACX,MAAM;CAAI,CAAC,CACX,OAAQ,GAAS,EAAK,WAAW,WAAW,CAAC,CAAC,CAC9C,IAAK,GAAS,EAAK,MAAM,CAAkB,CAAC,CAAC,KAAK,CAAC,CAAC,CACpD,OAAQ,GAAS,IAAS,EAAE,EALD,CAAC,CAMjC,EAEA,MAAM,WAAW,EAAM,CACrB,IAAM,EAAS,MAAM,EAAI,EAAM,CAAC,SAAU,aAAa,EAAG,CAAe,EAEzE,OADI,EAAO,OAAS,EACb,EAAO,OACX,MAAM;CAAI,CAAC,CACX,IAAK,GAAS,EAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnC,OAAQ,GAAS,IAAS,EAAE,EAJD,CAAC,CAKjC,EAEA,MAAM,eAAe,EAAK,CACxB,IAAM,EAAS,MAAM,EAAI,EAAK,CAAC,YAAa,iBAAiB,EAAG,CAAe,EAC/E,GAAI,EAAO,OAAS,EAAG,OACvB,IAAM,EAAO,EAAO,OAAO,KAAK,EAChC,OAAO,IAAS,GAAK,IAAA,GAAY,CACnC,EAEA,MAAM,cAAc,EAAK,CACvB,IAAM,EAAS,MAAM,EAAI,EAAK,CAAC,YAAa,eAAgB,MAAM,EAAG,CAAe,EACpF,GAAI,EAAO,OAAS,EAAG,OACvB,IAAM,EAAS,EAAO,OAAO,KAAK,EAClC,OAAO,IAAW,GAAK,IAAA,GAAY,CACrC,EAEA,MAAM,YAAY,CAAE,iBAAgB,SAAQ,WAAW,CAKrD,IAAM,EAAS,MAAM,EAAI,EAAgB,CAD3B,QAAS,UAAW,GAAI,IAAY,IAAA,GAAY,CAAC,EAAI,CAAC,KAAM,CAAO,EAAI,CACzC,EAAG,CAAe,EAC1D,KAAO,OAAS,EAIpB,MAAM,EAAQ,QAAS,CAAM,CAC/B,CACF,CACF"}
@@ -1,4 +0,0 @@
1
- import{execFile as e}from"node:child_process";import t from"node:fs";const n=3e4;function r(t,n,r){return new Promise(i=>{e(`git`,[...n],{cwd:t,timeout:r,maxBuffer:1e6,env:{...process.env,LC_ALL:`C`}},(e,t,n)=>{i({code:e&&typeof e.code==`number`?e.code:+!!e,stdout:String(t),stderr:String(n)})})})}function i(e,t){return Error(`git ${e} failed (exit ${String(t.code)}, ${String(t.stderr.length)} bytes of stderr)`)}function a(e){let t=e.toLowerCase();return t.includes(`is not a working tree`)||t.includes(`cannot remove working tree`)}function o(){let e=async e=>{await r(e,[`worktree`,`prune`],15e3)};return{async addWorktree({repositoryRoot:e,path:t,branch:n,baseRef:a}){let o=await r(e,[`worktree`,`add`,`-b`,n,t,a],3e5);if(o.code!==0)throw i(`worktree add`,o)},async removeWorktree({repositoryRoot:n,path:o,force:s}){let c=await r(n,[`worktree`,`remove`,...s?[`--force`]:[],o],3e5);if(c.code!==0){if(a(c.stderr)&&!t.existsSync(o)){await e(n);return}throw i(`worktree remove`,c)}},async deleteBranch({repositoryRoot:e,branch:t}){return(await r(e,[`branch`,`-d`,t],n)).code===0},pruneWorktrees:e,async listWorktreePaths(e){let t=await r(e,[`worktree`,`list`,`--porcelain`],n);return t.code===0?t.stdout.split(`
2
- `).filter(e=>e.startsWith(`worktree `)).map(e=>e.slice(9).trim()).filter(e=>e!==``):[]},async dirtyFiles(e){let t=await r(e,[`status`,`--porcelain`],n);return t.code===0?t.stdout.split(`
3
- `).map(e=>e.slice(3).trim()).filter(e=>e!==``):[]},async repositoryRoot(e){let t=await r(e,[`rev-parse`,`--show-toplevel`],n);if(t.code!==0)return;let i=t.stdout.trim();return i===``?void 0:i},async currentBranch(e){let t=await r(e,[`rev-parse`,`--abbrev-ref`,`HEAD`],n);if(t.code!==0)return;let i=t.stdout.trim();return i===``?void 0:i},async mergeBranch({repositoryRoot:e,branch:t,message:a}){let o=await r(e,[`merge`,`--no-ff`,...a===void 0?[]:[`-m`,a],t],n);if(o.code!==0)throw i(`merge`,o)}}}export{o as createWorktreeGit};
4
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/gitCli/index.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport fs from 'node:fs';\n\nimport type { WorktreeGit } from '../../types/worktreeRegistry';\n\n/**\n * Git, as this package needs it.\n *\n * The timeouts are not uniform because the operations are not comparable. A\n * read answers in milliseconds; `worktree add` copies an entire checkout and\n * `worktree remove` deletes one, both bounded by the filesystem rather than by\n * git, and both minutes rather than seconds on a large repository or on\n * Windows. A single timeout would either fail honest work or hang on a wedged\n * one.\n */\nconst READ_TIMEOUT_MS = 30_000;\nconst ADD_TIMEOUT_MS = 300_000;\nconst REMOVE_TIMEOUT_MS = 300_000;\nconst PRUNE_TIMEOUT_MS = 15_000;\nconst MAX_OUTPUT_BYTES = 1_000_000;\n\ninterface GitResult {\n code: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Runs git and reports the outcome without ever throwing on a non-zero exit.\n *\n * LC_ALL is pinned because two callers below decide what to do by matching\n * git's own wording, and a translated message would silently turn a recognised\n * condition into an unrecognised failure.\n */\nfunction git(cwd: string, args: readonly string[], timeout: number): Promise<GitResult> {\n return new Promise((resolve) => {\n execFile(\n 'git',\n [...args],\n { cwd, timeout, maxBuffer: MAX_OUTPUT_BYTES, env: { ...process.env, LC_ALL: 'C' } },\n (error, stdout, stderr) => {\n const code = error && typeof error.code === 'number' ? error.code : error ? 1 : 0;\n resolve({ code, stdout: String(stdout), stderr: String(stderr) });\n },\n );\n });\n}\n\n/**\n * The message a failed git call is allowed to surface.\n *\n * Raw stderr never travels: it can carry a remote URL with a token in it, and\n * this text ends up in a tool result the model reads and may repeat.\n */\nfunction failure(operation: string, result: GitResult): Error {\n return new Error(\n `git ${operation} failed (exit ${String(result.code)}, ${String(result.stderr.length)} bytes of stderr)`,\n );\n}\n\n/** Git's own words for \"that worktree is not there any more\". */\nfunction missingWorktree(stderr: string): boolean {\n const normalized = stderr.toLowerCase();\n return normalized.includes('is not a working tree') || normalized.includes('cannot remove working tree');\n}\n\nexport function createWorktreeGit(): WorktreeGit {\n const prune = async (repositoryRoot: string): Promise<void> => {\n await git(repositoryRoot, ['worktree', 'prune'], PRUNE_TIMEOUT_MS);\n };\n\n return {\n async addWorktree({ repositoryRoot, path, branch, baseRef }) {\n const result = await git(repositoryRoot, ['worktree', 'add', '-b', branch, path, baseRef], ADD_TIMEOUT_MS);\n if (result.code !== 0) throw failure('worktree add', result);\n },\n\n async removeWorktree({ repositoryRoot, path, force }) {\n const args = ['worktree', 'remove', ...(force ? ['--force'] : []), path];\n const result = await git(repositoryRoot, args, REMOVE_TIMEOUT_MS);\n if (result.code === 0) return;\n // A directory deleted behind git's back leaves an administrative entry\n // that makes a later `worktree add` at the same path refuse. Treating\n // \"already gone\" as success and pruning is what keeps that path reusable,\n // and it makes remove idempotent for a caller retrying after a crash.\n if (missingWorktree(result.stderr) && !fs.existsSync(path)) {\n await prune(repositoryRoot);\n return;\n }\n throw failure('worktree remove', result);\n },\n\n async deleteBranch({ repositoryRoot, branch }) {\n // -d, never -D: git refuses a branch that still holds unmerged commits,\n // and that refusal is the whole safety property. A rollback that could\n // throw away work someone committed in the worktree is worse than a\n // branch left behind.\n const result = await git(repositoryRoot, ['branch', '-d', branch], READ_TIMEOUT_MS);\n return result.code === 0;\n },\n pruneWorktrees: prune,\n\n async listWorktreePaths(repositoryRoot) {\n const result = await git(repositoryRoot, ['worktree', 'list', '--porcelain'], READ_TIMEOUT_MS);\n if (result.code !== 0) return [];\n return result.stdout\n .split('\\n')\n .filter((line) => line.startsWith('worktree '))\n .map((line) => line.slice('worktree '.length).trim())\n .filter((line) => line !== '');\n },\n\n async dirtyFiles(path) {\n const result = await git(path, ['status', '--porcelain'], READ_TIMEOUT_MS);\n if (result.code !== 0) return [];\n return result.stdout\n .split('\\n')\n .map((line) => line.slice(3).trim())\n .filter((line) => line !== '');\n },\n\n async repositoryRoot(cwd) {\n const result = await git(cwd, ['rev-parse', '--show-toplevel'], READ_TIMEOUT_MS);\n if (result.code !== 0) return undefined;\n const root = result.stdout.trim();\n return root === '' ? undefined : root;\n },\n\n async currentBranch(cwd) {\n const result = await git(cwd, ['rev-parse', '--abbrev-ref', 'HEAD'], READ_TIMEOUT_MS);\n if (result.code !== 0) return undefined;\n const branch = result.stdout.trim();\n return branch === '' ? undefined : branch;\n },\n\n async mergeBranch({ repositoryRoot, branch, message }) {\n // --no-ff so the worktree's work stays identifiable as a unit after the\n // fact. A fast-forward would erase the fact that it was ever separate,\n // which is the one thing worth keeping about a worktree.\n const args = ['merge', '--no-ff', ...(message === undefined ? [] : ['-m', message]), branch];\n const result = await git(repositoryRoot, args, READ_TIMEOUT_MS);\n if (result.code === 0) return;\n // A conflicted merge leaves the parent mid-merge, which is a state the\n // person has to resolve; aborting for them would throw away the conflict\n // markers they need to see.\n throw failure('merge', result);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- const e=require("../extensionService/index.cjs"),t=require("../gitCli/index.cjs"),n=require("../worktreeOperations/index.cjs");function r(r={}){return{service:r.service??new e.DefaultGitExtensionService,operations:r.operations??n.createWorktreeOperations({git:t.createWorktreeGit()})}}exports.createGitDependencies=r;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["DefaultGitExtensionService","createWorktreeOperations","createWorktreeGit"],"sources":["../../../src/services/gitDependencies/index.ts"],"sourcesContent":["import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":"+HAMA,SAAgB,EAAsB,EAA+C,CAAC,EAA6B,CACjH,MAAO,CACL,QAAS,EAAU,SAAW,IAAIA,EAAAA,2BAClC,WAAY,EAAU,YAAcC,EAAAA,yBAAyB,CAAE,IAAKC,EAAAA,kBAAkB,CAAE,CAAC,CAC3F,CACF"}
@@ -1,6 +0,0 @@
1
- import { GitExtensionDependencies } from "../../types/extension.cjs";
2
- //#region src/services/gitDependencies/index.d.ts
3
- declare function createGitDependencies(overrides?: Partial<GitExtensionDependencies>): GitExtensionDependencies;
4
- //#endregion
5
- export { createGitDependencies };
6
- //# sourceMappingURL=index.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../../src/services/gitDependencies/index.ts"],"mappings":";;iBAMgB,sBAAsB,YAAW,QAAQ,4BAAiC"}
@@ -1,6 +0,0 @@
1
- import { GitExtensionDependencies } from "../../types/extension.mjs";
2
- //#region src/services/gitDependencies/index.d.ts
3
- declare function createGitDependencies(overrides?: Partial<GitExtensionDependencies>): GitExtensionDependencies;
4
- //#endregion
5
- export { createGitDependencies };
6
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../src/services/gitDependencies/index.ts"],"mappings":";;iBAMgB,sBAAsB,YAAW,QAAQ,4BAAiC"}
@@ -1,2 +0,0 @@
1
- import{DefaultGitExtensionService as e}from"../extensionService/index.mjs";import{createWorktreeGit as t}from"../gitCli/index.mjs";import{createWorktreeOperations as n}from"../worktreeOperations/index.mjs";function r(r={}){return{service:r.service??new e,operations:r.operations??n({git:t()})}}export{r as createGitDependencies};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/gitDependencies/index.ts"],"sourcesContent":["import type { GitExtensionDependencies } from '../../types/extension';\nimport { DefaultGitExtensionService } from '../extensionService';\n// @scaffold-generated\nimport { createWorktreeGit } from '../gitCli';\nimport { createWorktreeOperations } from '../worktreeOperations';\n\nexport function createGitDependencies(overrides: Partial<GitExtensionDependencies> = {}): GitExtensionDependencies {\n return {\n service: overrides.service ?? new DefaultGitExtensionService(),\n operations: overrides.operations ?? createWorktreeOperations({ git: createWorktreeGit() }),\n };\n}\n"],"mappings":"8MAMA,SAAgB,EAAsB,EAA+C,CAAC,EAA6B,CACjH,MAAO,CACL,QAAS,EAAU,SAAW,IAAI,EAClC,WAAY,EAAU,YAAc,EAAyB,CAAE,IAAK,EAAkB,CAAE,CAAC,CAC3F,CACF"}
@@ -1,2 +0,0 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../repositoryIdentity/index.cjs");let n=require("node:path");n=e.__toESM(n,1);let r=require("node:os");r=e.__toESM(r,1),require("@agimon-ai/doompi-core/web");function i(e=r.default.homedir()){return n.default.join(e,`.pi`,`.doom`,`git`)}function a(e=r.default.homedir()){return n.default.join(i(e),`worktrees`)}function o(e,a=r.default.homedir()){let o=`${t.repositoryLabel(e)}--${t.repositoryId(e)}`;return n.default.join(i(a),`registry`,o,`worktrees.json`)}exports.doomGitRoot=i,exports.registryFile=o,exports.worktreesRoot=a;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["os","path","repositoryLabel","repositoryId"],"sources":["../../../src/services/paths/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { REGISTRY_DIR_ENV, resolveRegistryDir } from '@agimon-ai/doompi-core/web';\n\nimport { repositoryId, repositoryLabel } from '../repositoryIdentity';\n\nconst REGISTRY_DIR_FLAG = '--registry-dir';\n\n/**\n * Where this package keeps its own state.\n *\n * Outside the repository on purpose. A worktree directory inside the checkout\n * would be found by every glob the repository's own tooling runs, and would\n * resolve workspace imports against the parent checkout rather than the\n * worktree, so a session there would build the wrong source while appearing to\n * work.\n */\nexport function doomGitRoot(homeDir: string = os.homedir()): string {\n return path.join(homeDir, '.pi', '.doom', 'git');\n}\n\n/** The directory every worktree for every repository is created under. */\nexport function worktreesRoot(homeDir: string = os.homedir()): string {\n return path.join(doomGitRoot(homeDir), 'worktrees');\n}\n\n/** One registry file per repository, keyed by the shared git directory. */\n\nexport function registryFile(repositoryRoot: string, homeDir: string = os.homedir()): string {\n const key = `${repositoryLabel(repositoryRoot)}--${repositoryId(repositoryRoot)}`;\n return path.join(doomGitRoot(homeDir), 'registry', key, 'worktrees.json');\n}\n\n/**\n * The session registry directory this process's hub is watching.\n *\n * A spawned session only appears in the rail if it registers in the same\n * directory the hub watches, and the hub passes that directory to its children\n * as `--registry-dir` while also inheriting the env var. Recovering it from\n * this process's own argv and env, in the same precedence the hub and the\n * session server use, is what makes a worktree session visible rather than\n * silently invisible.\n */\nexport function hubRegistryDir(\n argv: readonly string[] = process.argv,\n env: NodeJS.ProcessEnv = process.env,\n homeDir: string = os.homedir(),\n): string {\n const index = argv.indexOf(REGISTRY_DIR_FLAG);\n const flagValue = index >= 0 ? argv[index + 1] : undefined;\n return resolveRegistryDir({\n ...(flagValue === undefined ? {} : { flagValue }),\n ...(env[REGISTRY_DIR_ENV] === undefined ? {} : { envValue: env[REGISTRY_DIR_ENV] }),\n homeDir,\n });\n}\n"],"mappings":"iOAkBA,SAAgB,EAAY,EAAkBA,EAAAA,QAAG,QAAQ,EAAW,CAClE,OAAOC,EAAAA,QAAK,KAAK,EAAS,MAAO,QAAS,KAAK,CACjD,CAGA,SAAgB,EAAc,EAAkBD,EAAAA,QAAG,QAAQ,EAAW,CACpE,OAAOC,EAAAA,QAAK,KAAK,EAAY,CAAO,EAAG,WAAW,CACpD,CAIA,SAAgB,EAAa,EAAwB,EAAkBD,EAAAA,QAAG,QAAQ,EAAW,CAC3F,IAAM,EAAM,GAAGE,EAAAA,gBAAgB,CAAc,EAAE,IAAIC,EAAAA,aAAa,CAAc,IAC9E,OAAOF,EAAAA,QAAK,KAAK,EAAY,CAAO,EAAG,WAAY,EAAK,gBAAgB,CAC1E"}
@@ -1,2 +0,0 @@
1
- import{repositoryId as e,repositoryLabel as t}from"../repositoryIdentity/index.mjs";import n from"node:path";import r from"node:os";import"@agimon-ai/doompi-core/web";function i(e=r.homedir()){return n.join(e,`.pi`,`.doom`,`git`)}function a(e=r.homedir()){return n.join(i(e),`worktrees`)}function o(a,o=r.homedir()){let s=`${t(a)}--${e(a)}`;return n.join(i(o),`registry`,s,`worktrees.json`)}export{i as doomGitRoot,o as registryFile,a as worktreesRoot};
2
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/services/paths/index.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\n\nimport { REGISTRY_DIR_ENV, resolveRegistryDir } from '@agimon-ai/doompi-core/web';\n\nimport { repositoryId, repositoryLabel } from '../repositoryIdentity';\n\nconst REGISTRY_DIR_FLAG = '--registry-dir';\n\n/**\n * Where this package keeps its own state.\n *\n * Outside the repository on purpose. A worktree directory inside the checkout\n * would be found by every glob the repository's own tooling runs, and would\n * resolve workspace imports against the parent checkout rather than the\n * worktree, so a session there would build the wrong source while appearing to\n * work.\n */\nexport function doomGitRoot(homeDir: string = os.homedir()): string {\n return path.join(homeDir, '.pi', '.doom', 'git');\n}\n\n/** The directory every worktree for every repository is created under. */\nexport function worktreesRoot(homeDir: string = os.homedir()): string {\n return path.join(doomGitRoot(homeDir), 'worktrees');\n}\n\n/** One registry file per repository, keyed by the shared git directory. */\n\nexport function registryFile(repositoryRoot: string, homeDir: string = os.homedir()): string {\n const key = `${repositoryLabel(repositoryRoot)}--${repositoryId(repositoryRoot)}`;\n return path.join(doomGitRoot(homeDir), 'registry', key, 'worktrees.json');\n}\n\n/**\n * The session registry directory this process's hub is watching.\n *\n * A spawned session only appears in the rail if it registers in the same\n * directory the hub watches, and the hub passes that directory to its children\n * as `--registry-dir` while also inheriting the env var. Recovering it from\n * this process's own argv and env, in the same precedence the hub and the\n * session server use, is what makes a worktree session visible rather than\n * silently invisible.\n */\nexport function hubRegistryDir(\n argv: readonly string[] = process.argv,\n env: NodeJS.ProcessEnv = process.env,\n homeDir: string = os.homedir(),\n): string {\n const index = argv.indexOf(REGISTRY_DIR_FLAG);\n const flagValue = index >= 0 ? argv[index + 1] : undefined;\n return resolveRegistryDir({\n ...(flagValue === undefined ? {} : { flagValue }),\n ...(env[REGISTRY_DIR_ENV] === undefined ? {} : { envValue: env[REGISTRY_DIR_ENV] }),\n homeDir,\n });\n}\n"],"mappings":"uKAkBA,SAAgB,EAAY,EAAkB,EAAG,QAAQ,EAAW,CAClE,OAAO,EAAK,KAAK,EAAS,MAAO,QAAS,KAAK,CACjD,CAGA,SAAgB,EAAc,EAAkB,EAAG,QAAQ,EAAW,CACpE,OAAO,EAAK,KAAK,EAAY,CAAO,EAAG,WAAW,CACpD,CAIA,SAAgB,EAAa,EAAwB,EAAkB,EAAG,QAAQ,EAAW,CAC3F,IAAM,EAAM,GAAG,EAAgB,CAAc,EAAE,IAAI,EAAa,CAAc,IAC9E,OAAO,EAAK,KAAK,EAAY,CAAO,EAAG,WAAY,EAAK,gBAAgB,CAC1E"}
@@ -1,2 +0,0 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs");let t=require("node:fs");t=e.__toESM(t,1);let n=require("node:crypto"),r=require("node:path");r=e.__toESM(r,1);function i(e){let n=r.default.join(e,`.git`),i;try{i=t.default.statSync(n)}catch{return}if(i.isDirectory())return n;let a;try{a=t.default.readFileSync(n,`utf8`).trim()}catch{return}if(!a.startsWith(`gitdir:`))return;let o=r.default.resolve(e,a.slice(7).trim());try{let e=t.default.readFileSync(r.default.join(o,`commondir`),`utf8`).trim();return r.default.resolve(o,e)}catch{return o}}function a(e){let t=r.default.basename(e).toLowerCase().replace(/[^a-z0-9]+/gu,`-`).replace(/^-+|-+$/gu,``).slice(0,32);return t===``?`repository`:t}function o(e){let t=i(e),a=t===void 0?`root:${r.default.resolve(e)}`:`git:${t}`;return(0,n.createHash)(`sha256`).update(a).digest(`hex`).slice(0,12)}function s(e){return(0,n.createHash)(`sha256`).update(e).digest(`hex`).slice(0,8)}exports.gitCommonDirectory=i,exports.repositoryId=o,exports.repositoryLabel=a,exports.shortId=s;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":["path","fs","createHash"],"sources":["../../../src/services/repositoryIdentity/index.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nconst ID_LENGTH = 12;\nconst MAX_LABEL_LENGTH = 32;\n\n/**\n * The git directory shared by a repository and all of its worktrees.\n *\n * A normal checkout has a `.git` directory. A linked worktree has a `.git`\n * FILE pointing at `<common>/worktrees/<name>`, whose `commondir` points back\n * at the shared directory. Following that chain is what makes every worktree of\n * one repository agree on the repository's identity, which matters here because\n * the registry is per repository and must be found from inside a worktree too.\n */\nexport function gitCommonDirectory(root: string): string | undefined {\n const marker = path.join(root, '.git');\n let stat: fs.Stats;\n try {\n stat = fs.statSync(marker);\n } catch {\n return undefined;\n }\n if (stat.isDirectory()) return marker;\n let pointer: string;\n try {\n pointer = fs.readFileSync(marker, 'utf8').trim();\n } catch {\n return undefined;\n }\n if (!pointer.startsWith('gitdir:')) return undefined;\n const gitDir = path.resolve(root, pointer.slice('gitdir:'.length).trim());\n try {\n const common = fs.readFileSync(path.join(gitDir, 'commondir'), 'utf8').trim();\n return path.resolve(gitDir, common);\n } catch {\n // A submodule's .git file has no commondir; its gitdir is already common.\n return gitDir;\n }\n}\n\n/** A directory name that is recognisable to a person and safe on a filesystem. */\nexport function repositoryLabel(root: string): string {\n const label = path\n .basename(root)\n .toLowerCase()\n .replace(/[^a-z0-9]+/gu, '-')\n .replace(/^-+|-+$/gu, '')\n .slice(0, MAX_LABEL_LENGTH);\n return label === '' ? 'repository' : label;\n}\n\n/**\n * A stable id for the repository a directory belongs to.\n *\n * Keyed on the common git directory rather than the given path, so the main\n * checkout and every worktree of it resolve to one id and therefore to one\n * registry. Falling back to the path keeps a non-repository directory usable\n * instead of failing, though nothing here should reach that case.\n */\nexport function repositoryId(root: string): string {\n const common = gitCommonDirectory(root);\n const token = common === undefined ? `root:${path.resolve(root)}` : `git:${common}`;\n return createHash('sha256').update(token).digest('hex').slice(0, ID_LENGTH);\n}\n\n/** A short, collision-resistant suffix for one worktree directory. */\nexport function shortId(seed: string): string {\n return createHash('sha256').update(seed).digest('hex').slice(0, 8);\n}\n"],"mappings":"uKAgBA,SAAgB,EAAmB,EAAkC,CACnE,IAAM,EAASA,EAAAA,QAAK,KAAK,EAAM,MAAM,EACjC,EACJ,GAAI,CACF,EAAOC,EAAAA,QAAG,SAAS,CAAM,CAC3B,MAAQ,CACN,MACF,CACA,GAAI,EAAK,YAAY,EAAG,OAAO,EAC/B,IAAI,EACJ,GAAI,CACF,EAAUA,EAAAA,QAAG,aAAa,EAAQ,MAAM,CAAC,CAAC,KAAK,CACjD,MAAQ,CACN,MACF,CACA,GAAI,CAAC,EAAQ,WAAW,SAAS,EAAG,OACpC,IAAM,EAASD,EAAAA,QAAK,QAAQ,EAAM,EAAQ,MAAM,CAAgB,CAAC,CAAC,KAAK,CAAC,EACxE,GAAI,CACF,IAAM,EAASC,EAAAA,QAAG,aAAaD,EAAAA,QAAK,KAAK,EAAQ,WAAW,EAAG,MAAM,CAAC,CAAC,KAAK,EAC5E,OAAOA,EAAAA,QAAK,QAAQ,EAAQ,CAAM,CACpC,MAAQ,CAEN,OAAO,CACT,CACF,CAGA,SAAgB,EAAgB,EAAsB,CACpD,IAAM,EAAQA,EAAAA,QACX,SAAS,CAAI,CAAC,CACd,YAAY,CAAC,CACb,QAAQ,eAAgB,GAAG,CAAC,CAC5B,QAAQ,YAAa,EAAE,CAAC,CACxB,MAAM,EAAG,EAAgB,EAC5B,OAAO,IAAU,GAAK,aAAe,CACvC,CAUA,SAAgB,EAAa,EAAsB,CACjD,IAAM,EAAS,EAAmB,CAAI,EAChC,EAAQ,IAAW,IAAA,GAAY,QAAQA,EAAAA,QAAK,QAAQ,CAAI,IAAM,OAAO,IAC3E,OAAA,EAAOE,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAS,CAC5E,CAGA,SAAgB,EAAQ,EAAsB,CAC5C,OAAA,EAAOA,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,CAAC,CACnE"}