@agimon-ai/doompi-git 0.0.1-alpha.8 → 0.0.1-alpha.9
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.
- package/dist/_virtual/_rolldown/runtime.cjs +23 -1
- package/dist/api-contracts.cjs +7 -1
- package/dist/api-contracts.d.cts +1 -1
- package/dist/api-contracts.d.mts +1 -1
- package/dist/api-contracts.mjs +2 -1
- package/dist/extensions/pi.cjs +38 -1
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.cts +5 -4
- package/dist/extensions/pi.d.cts.map +1 -1
- package/dist/extensions/pi.d.mts +5 -4
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +33 -1
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +72 -1
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.cts +3 -3
- package/dist/extensions/server.d.cts.map +1 -1
- package/dist/extensions/server.d.mts +3 -3
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +67 -1
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +485 -0
- package/dist/extensions/web.mjs.map +1 -0
- package/dist/index.cjs +5 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +3 -1
- package/dist/src/constants/git.cjs +8 -0
- package/dist/src/constants/git.cjs.map +1 -0
- package/dist/src/constants/git.mjs +7 -0
- package/dist/src/constants/git.mjs.map +1 -0
- package/dist/src/extensions/(backend)/api/_lib/route.server.cjs +93 -0
- package/dist/src/extensions/(backend)/api/_lib/route.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/api/_lib/route.server.mjs +92 -0
- package/dist/src/extensions/(backend)/api/_lib/route.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/api/route.server.cjs +7 -0
- package/dist/src/extensions/(backend)/api/route.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/api/route.server.mjs +8 -0
- package/dist/src/extensions/(backend)/api/route.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/_lib/git-worktrees.server.cjs +195 -0
- package/dist/src/extensions/(backend)/channel/_lib/git-worktrees.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/_lib/git-worktrees.server.mjs +194 -0
- package/dist/src/extensions/(backend)/channel/_lib/git-worktrees.server.mjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/git-worktrees.server.cjs +7 -0
- package/dist/src/extensions/(backend)/channel/git-worktrees.server.cjs.map +1 -0
- package/dist/src/extensions/(backend)/channel/git-worktrees.server.mjs +8 -0
- package/dist/src/extensions/(backend)/channel/git-worktrees.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.server.cjs +71 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.server.mjs +70 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/root.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/_lib/git.cli.cjs +17 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/_lib/git.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/_lib/git.cli.mjs +16 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/_lib/git.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/git.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/git.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/git.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/command/git.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompi-use-git.cli.cjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompi-use-git.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompi-use-git.cli.mjs +15 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompi-use-git.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGit.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGit.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGit.server.mjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGit.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGitReadme.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGitReadme.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGitReadme.server.mjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiGitReadme.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseGit.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseGit.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseGit.server.mjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/_lib/doompiUseGit.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-git.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-git.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-git.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompi-use-git.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGit.server.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGit.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGit.server.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGit.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGitReadme.server.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGitReadme.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGitReadme.server.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiGitReadme.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiUseGit.server.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiUseGit.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiUseGit.server.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/resource/doompiUseGit.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/runWorktree.cli.cjs +38 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/runWorktree.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/runWorktree.cli.mjs +36 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/runWorktree.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.cli.cjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.cli.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.cli.mjs +8 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.cli.mjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.server.cjs +6 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.server.cjs.map +1 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.server.mjs +7 -0
- package/dist/src/extensions/workspaces/sessions/(backend)/tool/runWorktree.server.mjs.map +1 -0
- package/dist/src/schemas/apiContracts.cjs +138 -0
- package/dist/src/schemas/apiContracts.cjs.map +1 -0
- package/dist/{schemas → src/schemas}/apiContracts.d.cts.map +1 -1
- package/dist/{schemas → src/schemas}/apiContracts.d.mts.map +1 -1
- package/dist/src/schemas/apiContracts.mjs +135 -0
- package/dist/src/schemas/apiContracts.mjs.map +1 -0
- package/dist/src/schemas/runWorktreeTool.cjs +152 -0
- package/dist/src/schemas/runWorktreeTool.cjs.map +1 -0
- package/dist/src/schemas/runWorktreeTool.mjs +150 -0
- package/dist/src/schemas/runWorktreeTool.mjs.map +1 -0
- package/dist/src/services/atomicJson/index.cjs +42 -0
- package/dist/src/services/atomicJson/index.cjs.map +1 -0
- package/dist/src/services/atomicJson/index.mjs +38 -0
- package/dist/src/services/atomicJson/index.mjs.map +1 -0
- package/dist/src/services/compositionMirror/index.cjs +119 -0
- package/dist/src/services/compositionMirror/index.cjs.map +1 -0
- package/dist/src/services/compositionMirror/index.mjs +116 -0
- package/dist/src/services/compositionMirror/index.mjs.map +1 -0
- package/dist/src/services/errors/index.cjs +29 -0
- package/dist/src/services/errors/index.cjs.map +1 -0
- package/dist/src/services/errors/index.mjs +27 -0
- package/dist/src/services/errors/index.mjs.map +1 -0
- package/dist/src/services/extensionService/index.cjs +13 -0
- package/dist/src/services/extensionService/index.cjs.map +1 -0
- package/dist/src/services/extensionService/index.d.cts.map +1 -0
- package/dist/src/services/extensionService/index.d.mts.map +1 -0
- package/dist/src/services/extensionService/index.mjs +13 -0
- package/dist/src/services/extensionService/index.mjs.map +1 -0
- package/dist/src/services/gitCli/index.cjs +144 -0
- package/dist/src/services/gitCli/index.cjs.map +1 -0
- package/dist/src/services/gitCli/index.mjs +142 -0
- package/dist/src/services/gitCli/index.mjs.map +1 -0
- package/dist/src/services/gitDependencies/index.cjs +14 -0
- package/dist/src/services/gitDependencies/index.cjs.map +1 -0
- package/dist/src/services/gitDependencies/index.d.cts.map +1 -0
- package/dist/src/services/gitDependencies/index.d.mts.map +1 -0
- package/dist/src/services/gitDependencies/index.mjs +14 -0
- package/dist/src/services/gitDependencies/index.mjs.map +1 -0
- package/dist/src/services/paths/index.cjs +35 -0
- package/dist/src/services/paths/index.cjs.map +1 -0
- package/dist/src/services/paths/index.mjs +30 -0
- package/dist/src/services/paths/index.mjs.map +1 -0
- package/dist/src/services/repositoryIdentity/index.cjs +71 -0
- package/dist/src/services/repositoryIdentity/index.cjs.map +1 -0
- package/dist/src/services/repositoryIdentity/index.mjs +65 -0
- package/dist/src/services/repositoryIdentity/index.mjs.map +1 -0
- package/dist/src/services/runWorktree/index.cjs +145 -0
- package/dist/src/services/runWorktree/index.cjs.map +1 -0
- package/dist/src/services/runWorktree/index.mjs +142 -0
- package/dist/src/services/runWorktree/index.mjs.map +1 -0
- package/dist/src/services/worktreeEvents/index.cjs +64 -0
- package/dist/src/services/worktreeEvents/index.cjs.map +1 -0
- package/dist/src/services/worktreeEvents/index.d.cts.map +1 -0
- package/dist/src/services/worktreeEvents/index.d.mts.map +1 -0
- package/dist/src/services/worktreeEvents/index.mjs +60 -0
- package/dist/src/services/worktreeEvents/index.mjs.map +1 -0
- package/dist/src/services/worktreeNaming/index.cjs +99 -0
- package/dist/src/services/worktreeNaming/index.cjs.map +1 -0
- package/dist/src/services/worktreeNaming/index.d.cts.map +1 -0
- package/dist/src/services/worktreeNaming/index.d.mts.map +1 -0
- package/dist/src/services/worktreeNaming/index.mjs +94 -0
- package/dist/src/services/worktreeNaming/index.mjs.map +1 -0
- package/dist/src/services/worktreeOperations/index.cjs +263 -0
- package/dist/src/services/worktreeOperations/index.cjs.map +1 -0
- package/dist/src/services/worktreeOperations/index.d.cts.map +1 -0
- package/dist/src/services/worktreeOperations/index.d.mts.map +1 -0
- package/dist/src/services/worktreeOperations/index.mjs +261 -0
- package/dist/src/services/worktreeOperations/index.mjs.map +1 -0
- package/dist/src/services/worktreeRegistry/index.cjs +38 -0
- package/dist/src/services/worktreeRegistry/index.cjs.map +1 -0
- package/dist/src/services/worktreeRegistry/index.mjs +38 -0
- package/dist/src/services/worktreeRegistry/index.mjs.map +1 -0
- package/dist/src/types/extension.d.cts.map +1 -0
- package/dist/src/types/extension.d.mts.map +1 -0
- package/dist/src/types/webWorktrees.cjs +20 -0
- package/dist/src/types/webWorktrees.cjs.map +1 -0
- package/dist/src/types/webWorktrees.mjs +20 -0
- package/dist/src/types/webWorktrees.mjs.map +1 -0
- package/dist/src/types/worktreeRegistry.d.cts.map +1 -0
- package/dist/src/types/worktreeRegistry.d.mts.map +1 -0
- package/package.json +24 -19
- package/dist/constants/git.cjs +0 -2
- package/dist/constants/git.cjs.map +0 -1
- package/dist/constants/git.mjs +0 -2
- package/dist/constants/git.mjs.map +0 -1
- package/dist/controllers/gitCommand.cjs +0 -2
- package/dist/controllers/gitCommand.cjs.map +0 -1
- package/dist/controllers/gitCommand.mjs +0 -2
- package/dist/controllers/gitCommand.mjs.map +0 -1
- package/dist/controllers/gitSession.cjs +0 -2
- package/dist/controllers/gitSession.cjs.map +0 -1
- package/dist/controllers/gitSession.mjs +0 -2
- package/dist/controllers/gitSession.mjs.map +0 -1
- package/dist/controllers/hubApi.cjs +0 -2
- package/dist/controllers/hubApi.cjs.map +0 -1
- package/dist/controllers/hubApi.mjs +0 -2
- package/dist/controllers/hubApi.mjs.map +0 -1
- package/dist/controllers/worktreesChannel.cjs +0 -2
- package/dist/controllers/worktreesChannel.cjs.map +0 -1
- package/dist/controllers/worktreesChannel.mjs +0 -2
- package/dist/controllers/worktreesChannel.mjs.map +0 -1
- package/dist/schemas/apiContracts.cjs +0 -2
- package/dist/schemas/apiContracts.cjs.map +0 -1
- package/dist/schemas/apiContracts.mjs +0 -2
- package/dist/schemas/apiContracts.mjs.map +0 -1
- package/dist/schemas/runWorktreeTool.cjs +0 -2
- package/dist/schemas/runWorktreeTool.cjs.map +0 -1
- package/dist/schemas/runWorktreeTool.mjs +0 -2
- package/dist/schemas/runWorktreeTool.mjs.map +0 -1
- package/dist/services/atomicJson/index.cjs +0 -2
- package/dist/services/atomicJson/index.cjs.map +0 -1
- package/dist/services/atomicJson/index.mjs +0 -2
- package/dist/services/atomicJson/index.mjs.map +0 -1
- package/dist/services/compositionMirror/index.cjs +0 -2
- package/dist/services/compositionMirror/index.cjs.map +0 -1
- package/dist/services/compositionMirror/index.mjs +0 -2
- package/dist/services/compositionMirror/index.mjs.map +0 -1
- package/dist/services/errors/index.cjs +0 -2
- package/dist/services/errors/index.cjs.map +0 -1
- package/dist/services/errors/index.mjs +0 -2
- package/dist/services/errors/index.mjs.map +0 -1
- package/dist/services/extensionService/index.cjs +0 -2
- package/dist/services/extensionService/index.cjs.map +0 -1
- package/dist/services/extensionService/index.d.cts.map +0 -1
- package/dist/services/extensionService/index.d.mts.map +0 -1
- package/dist/services/extensionService/index.mjs +0 -2
- package/dist/services/extensionService/index.mjs.map +0 -1
- package/dist/services/gitCli/index.cjs +0 -4
- package/dist/services/gitCli/index.cjs.map +0 -1
- package/dist/services/gitCli/index.mjs +0 -4
- package/dist/services/gitCli/index.mjs.map +0 -1
- package/dist/services/gitDependencies/index.cjs +0 -2
- package/dist/services/gitDependencies/index.cjs.map +0 -1
- package/dist/services/gitDependencies/index.d.cts.map +0 -1
- package/dist/services/gitDependencies/index.d.mts.map +0 -1
- package/dist/services/gitDependencies/index.mjs +0 -2
- package/dist/services/gitDependencies/index.mjs.map +0 -1
- package/dist/services/paths/index.cjs +0 -2
- package/dist/services/paths/index.cjs.map +0 -1
- package/dist/services/paths/index.mjs +0 -2
- package/dist/services/paths/index.mjs.map +0 -1
- package/dist/services/repositoryIdentity/index.cjs +0 -2
- package/dist/services/repositoryIdentity/index.cjs.map +0 -1
- package/dist/services/repositoryIdentity/index.mjs +0 -2
- package/dist/services/repositoryIdentity/index.mjs.map +0 -1
- package/dist/services/runWorktree/index.cjs +0 -15
- package/dist/services/runWorktree/index.cjs.map +0 -1
- package/dist/services/runWorktree/index.mjs +0 -15
- package/dist/services/runWorktree/index.mjs.map +0 -1
- package/dist/services/worktreeEvents/index.cjs +0 -2
- package/dist/services/worktreeEvents/index.cjs.map +0 -1
- package/dist/services/worktreeEvents/index.d.cts.map +0 -1
- package/dist/services/worktreeEvents/index.d.mts.map +0 -1
- package/dist/services/worktreeEvents/index.mjs +0 -2
- package/dist/services/worktreeEvents/index.mjs.map +0 -1
- package/dist/services/worktreeNaming/index.cjs +0 -2
- package/dist/services/worktreeNaming/index.cjs.map +0 -1
- package/dist/services/worktreeNaming/index.d.cts.map +0 -1
- package/dist/services/worktreeNaming/index.d.mts.map +0 -1
- package/dist/services/worktreeNaming/index.mjs +0 -2
- package/dist/services/worktreeNaming/index.mjs.map +0 -1
- package/dist/services/worktreeOperations/index.cjs +0 -2
- package/dist/services/worktreeOperations/index.cjs.map +0 -1
- package/dist/services/worktreeOperations/index.d.cts.map +0 -1
- package/dist/services/worktreeOperations/index.d.mts.map +0 -1
- package/dist/services/worktreeOperations/index.mjs +0 -2
- package/dist/services/worktreeOperations/index.mjs.map +0 -1
- package/dist/services/worktreeRegistry/index.cjs +0 -2
- package/dist/services/worktreeRegistry/index.cjs.map +0 -1
- package/dist/services/worktreeRegistry/index.mjs +0 -2
- package/dist/services/worktreeRegistry/index.mjs.map +0 -1
- package/dist/tools/runWorktree.cjs +0 -2
- package/dist/tools/runWorktree.cjs.map +0 -1
- package/dist/tools/runWorktree.mjs +0 -2
- package/dist/tools/runWorktree.mjs.map +0 -1
- package/dist/types/extension.d.cts.map +0 -1
- package/dist/types/extension.d.mts.map +0 -1
- package/dist/types/webWorktrees.cjs +0 -2
- package/dist/types/webWorktrees.cjs.map +0 -1
- package/dist/types/webWorktrees.mjs +0 -2
- package/dist/types/webWorktrees.mjs.map +0 -1
- package/dist/types/worktreeRegistry.d.cts.map +0 -1
- package/dist/types/worktreeRegistry.d.mts.map +0 -1
- package/src/extensions/web.ts +0 -33
- package/src/types/webWorktrees.ts +0 -55
- package/src/types/worktreeRegistry.ts +0 -78
- package/src/web/components/RunWorktreeToolMessage.tsx +0 -45
- package/src/web/components/WorktreesActivitySection.tsx +0 -80
- package/src/web/components/WorktreesPanel.tsx +0 -175
- package/src/web/components/toolRenderers.ts +0 -8
- package/src/web/stores/worktreesActivityStore.ts +0 -125
- package/src/web/tsconfig.json +0 -22
- /package/dist/{schemas → src/schemas}/apiContracts.d.cts +0 -0
- /package/dist/{schemas → src/schemas}/apiContracts.d.mts +0 -0
- /package/dist/{services → src/services}/extensionService/index.d.cts +0 -0
- /package/dist/{services → src/services}/extensionService/index.d.mts +0 -0
- /package/dist/{services → src/services}/gitDependencies/index.d.cts +0 -0
- /package/dist/{services → src/services}/gitDependencies/index.d.mts +0 -0
- /package/dist/{services → src/services}/worktreeEvents/index.d.cts +0 -0
- /package/dist/{services → src/services}/worktreeEvents/index.d.mts +0 -0
- /package/dist/{services → src/services}/worktreeNaming/index.d.cts +0 -0
- /package/dist/{services → src/services}/worktreeNaming/index.d.mts +0 -0
- /package/dist/{services → src/services}/worktreeOperations/index.d.cts +0 -0
- /package/dist/{services → src/services}/worktreeOperations/index.d.mts +0 -0
- /package/dist/{types → src/types}/extension.d.cts +0 -0
- /package/dist/{types → src/types}/extension.d.mts +0 -0
- /package/dist/{types → src/types}/worktreeRegistry.d.cts +0 -0
- /package/dist/{types → src/types}/worktreeRegistry.d.mts +0 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const require_index = require("../atomicJson/index.cjs");
|
|
2
|
+
//#region src/services/worktreeRegistry/index.ts
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
if (typeof value !== "object" || value === null) return false;
|
|
5
|
+
const record = value;
|
|
6
|
+
return record.version === 1 && typeof record.id === "string" && record.id !== "" && typeof record.path === "string" && typeof record.branch === "string" && typeof record.sessionId === "string";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The worktree registry for one repository, as a single JSON file.
|
|
10
|
+
*
|
|
11
|
+
* One file rather than a file per worktree, and read-modify-write rather than
|
|
12
|
+
* merging: every write comes from a tool call in one session's turn, so there
|
|
13
|
+
* is no concurrent writer to reconcile with. Choosing the simpler shape now
|
|
14
|
+
* means a reader can see the whole registry in one place; if concurrent writers
|
|
15
|
+
* ever appear, that is the point to revisit, not before.
|
|
16
|
+
*
|
|
17
|
+
* A file that does not parse is treated as empty rather than fatal. Losing
|
|
18
|
+
* track of worktrees is recoverable through prune; refusing to run is not.
|
|
19
|
+
*/
|
|
20
|
+
function createWorktreeRegistry(file) {
|
|
21
|
+
return {
|
|
22
|
+
list() {
|
|
23
|
+
const parsed = require_index.readJson(file);
|
|
24
|
+
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) return [];
|
|
25
|
+
return parsed.entries.filter(isRecord);
|
|
26
|
+
},
|
|
27
|
+
replace(entries) {
|
|
28
|
+
require_index.writeJsonAtomic(file, {
|
|
29
|
+
version: 1,
|
|
30
|
+
entries
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.createWorktreeRegistry = createWorktreeRegistry;
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["readJson"],"sources":["../../../../src/services/worktreeRegistry/index.ts"],"sourcesContent":["import {\n WORKTREE_RECORD_VERSION,\n type WorktreeRecord,\n type WorktreeRegistryFile,\n type WorktreeRegistryStore,\n} from '../../types/worktreeRegistry';\nimport { readJson, writeJsonAtomic } from '../atomicJson';\n\nfunction isRecord(value: unknown): value is WorktreeRecord {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Partial<WorktreeRecord>;\n return (\n record.version === WORKTREE_RECORD_VERSION &&\n typeof record.id === 'string' &&\n record.id !== '' &&\n typeof record.path === 'string' &&\n typeof record.branch === 'string' &&\n typeof record.sessionId === 'string'\n );\n}\n\n/**\n * The worktree registry for one repository, as a single JSON file.\n *\n * One file rather than a file per worktree, and read-modify-write rather than\n * merging: every write comes from a tool call in one session's turn, so there\n * is no concurrent writer to reconcile with. Choosing the simpler shape now\n * means a reader can see the whole registry in one place; if concurrent writers\n * ever appear, that is the point to revisit, not before.\n *\n * A file that does not parse is treated as empty rather than fatal. Losing\n * track of worktrees is recoverable through prune; refusing to run is not.\n */\nexport function createWorktreeRegistry(file: string): WorktreeRegistryStore {\n return {\n list() {\n const parsed = readJson<WorktreeRegistryFile>(file);\n if (!parsed || parsed.version !== WORKTREE_RECORD_VERSION || !Array.isArray(parsed.entries)) return [];\n return parsed.entries.filter(isRecord);\n },\n replace(entries) {\n writeJsonAtomic(file, { version: WORKTREE_RECORD_VERSION, entries } satisfies WorktreeRegistryFile);\n },\n };\n}\n"],"mappings":";;AAQA,SAAS,SAAS,OAAyC;CACzD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,SAAS;CACf,OACE,OAAO,YAAA,KACP,OAAO,OAAO,OAAO,YACrB,OAAO,OAAO,MACd,OAAO,OAAO,SAAS,YACvB,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,cAAc;AAEhC;;;;;;;;;;;;;AAcA,SAAgB,uBAAuB,MAAqC;CAC1E,OAAO;EACL,OAAO;GACL,MAAM,SAASA,cAAAA,SAA+B,IAAI;GAClD,IAAI,CAAC,UAAU,OAAO,YAAA,KAAuC,CAAC,MAAM,QAAQ,OAAO,OAAO,GAAG,OAAO,CAAC;GACrG,OAAO,OAAO,QAAQ,OAAO,QAAQ;EACvC;EACA,QAAQ,SAAS;GACf,cAAA,gBAAgB,MAAM;IAAE,SAAA;IAAkC;GAAQ,CAAgC;EACpG;CACF;AACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readJson, writeJsonAtomic } from "../atomicJson/index.mjs";
|
|
2
|
+
//#region src/services/worktreeRegistry/index.ts
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
if (typeof value !== "object" || value === null) return false;
|
|
5
|
+
const record = value;
|
|
6
|
+
return record.version === 1 && typeof record.id === "string" && record.id !== "" && typeof record.path === "string" && typeof record.branch === "string" && typeof record.sessionId === "string";
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The worktree registry for one repository, as a single JSON file.
|
|
10
|
+
*
|
|
11
|
+
* One file rather than a file per worktree, and read-modify-write rather than
|
|
12
|
+
* merging: every write comes from a tool call in one session's turn, so there
|
|
13
|
+
* is no concurrent writer to reconcile with. Choosing the simpler shape now
|
|
14
|
+
* means a reader can see the whole registry in one place; if concurrent writers
|
|
15
|
+
* ever appear, that is the point to revisit, not before.
|
|
16
|
+
*
|
|
17
|
+
* A file that does not parse is treated as empty rather than fatal. Losing
|
|
18
|
+
* track of worktrees is recoverable through prune; refusing to run is not.
|
|
19
|
+
*/
|
|
20
|
+
function createWorktreeRegistry(file) {
|
|
21
|
+
return {
|
|
22
|
+
list() {
|
|
23
|
+
const parsed = readJson(file);
|
|
24
|
+
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) return [];
|
|
25
|
+
return parsed.entries.filter(isRecord);
|
|
26
|
+
},
|
|
27
|
+
replace(entries) {
|
|
28
|
+
writeJsonAtomic(file, {
|
|
29
|
+
version: 1,
|
|
30
|
+
entries
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createWorktreeRegistry };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/services/worktreeRegistry/index.ts"],"sourcesContent":["import {\n WORKTREE_RECORD_VERSION,\n type WorktreeRecord,\n type WorktreeRegistryFile,\n type WorktreeRegistryStore,\n} from '../../types/worktreeRegistry';\nimport { readJson, writeJsonAtomic } from '../atomicJson';\n\nfunction isRecord(value: unknown): value is WorktreeRecord {\n if (typeof value !== 'object' || value === null) return false;\n const record = value as Partial<WorktreeRecord>;\n return (\n record.version === WORKTREE_RECORD_VERSION &&\n typeof record.id === 'string' &&\n record.id !== '' &&\n typeof record.path === 'string' &&\n typeof record.branch === 'string' &&\n typeof record.sessionId === 'string'\n );\n}\n\n/**\n * The worktree registry for one repository, as a single JSON file.\n *\n * One file rather than a file per worktree, and read-modify-write rather than\n * merging: every write comes from a tool call in one session's turn, so there\n * is no concurrent writer to reconcile with. Choosing the simpler shape now\n * means a reader can see the whole registry in one place; if concurrent writers\n * ever appear, that is the point to revisit, not before.\n *\n * A file that does not parse is treated as empty rather than fatal. Losing\n * track of worktrees is recoverable through prune; refusing to run is not.\n */\nexport function createWorktreeRegistry(file: string): WorktreeRegistryStore {\n return {\n list() {\n const parsed = readJson<WorktreeRegistryFile>(file);\n if (!parsed || parsed.version !== WORKTREE_RECORD_VERSION || !Array.isArray(parsed.entries)) return [];\n return parsed.entries.filter(isRecord);\n },\n replace(entries) {\n writeJsonAtomic(file, { version: WORKTREE_RECORD_VERSION, entries } satisfies WorktreeRegistryFile);\n },\n };\n}\n"],"mappings":";;AAQA,SAAS,SAAS,OAAyC;CACzD,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,SAAS;CACf,OACE,OAAO,YAAA,KACP,OAAO,OAAO,OAAO,YACrB,OAAO,OAAO,MACd,OAAO,OAAO,SAAS,YACvB,OAAO,OAAO,WAAW,YACzB,OAAO,OAAO,cAAc;AAEhC;;;;;;;;;;;;;AAcA,SAAgB,uBAAuB,MAAqC;CAC1E,OAAO;EACL,OAAO;GACL,MAAM,SAAS,SAA+B,IAAI;GAClD,IAAI,CAAC,UAAU,OAAO,YAAA,KAAuC,CAAC,MAAM,QAAQ,OAAO,OAAO,GAAG,OAAO,CAAC;GACrG,OAAO,OAAO,QAAQ,OAAO,QAAQ;EACvC;EACA,QAAQ,SAAS;GACf,gBAAgB,MAAM;IAAE,SAAA;IAAkC;GAAQ,CAAgC;EACpG;CACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/types/extension.ts"],"mappings":";;YAGY;iBAEK;EACf;EACA,OAAO;;iBAGQ;EACf,WAAW,QAAQ;;iBAGJ;EACf,SAAS;EACT,YAAY"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/types/extension.ts"],"mappings":";;YAGY;iBAEK;EACf;EACA,OAAO;;iBAGQ;EACf,WAAW,QAAQ;;iBAGJ;EACf,SAAS;EACT,YAAY"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/types/webWorktrees.ts
|
|
2
|
+
/**
|
|
3
|
+
* The cockpit's view of this session's worktrees.
|
|
4
|
+
*
|
|
5
|
+
* DESIGN PATTERNS:
|
|
6
|
+
* - Declarations only. The channel frame type is a constant so the hub and the
|
|
7
|
+
* page cannot drift apart on a string.
|
|
8
|
+
* - A view is the subset of a record the dock needs, not the record. The
|
|
9
|
+
* registry may hold paths and provenance the page has no business rendering.
|
|
10
|
+
*
|
|
11
|
+
* AVOID:
|
|
12
|
+
* - Adding behaviour here. This file is imported by browser code, so it must
|
|
13
|
+
* stay free of node builtins.
|
|
14
|
+
*/
|
|
15
|
+
/** The data channel carrying one session's worktrees to the page. */
|
|
16
|
+
const GIT_WORKTREES_TYPE = "git_worktrees";
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.GIT_WORKTREES_TYPE = GIT_WORKTREES_TYPE;
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=webWorktrees.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webWorktrees.cjs","names":[],"sources":["../../../src/types/webWorktrees.ts"],"sourcesContent":["/**\n * The cockpit's view of this session's worktrees.\n *\n * DESIGN PATTERNS:\n * - Declarations only. The channel frame type is a constant so the hub and the\n * page cannot drift apart on a string.\n * - A view is the subset of a record the dock needs, not the record. The\n * registry may hold paths and provenance the page has no business rendering.\n *\n * AVOID:\n * - Adding behaviour here. This file is imported by browser code, so it must\n * stay free of node builtins.\n */\n\n/** The data channel carrying one session's worktrees to the page. */\nexport const GIT_WORKTREES_TYPE = 'git_worktrees';\n\n/** One worktree, as the activity dock and its panel render it. */\nexport interface WorktreeView {\n id: string;\n branch: string;\n path: string;\n /** The session the hub started for this worktree, when it is still live. */\n sessionId: string | null;\n /** True once the directory the record names has gone missing. */\n orphaned: boolean;\n /**\n * True when the session that asked for this worktree is gone.\n *\n * An owned worktree is only ever shown to its own session. This flag marks\n * the exception: once the parent is dead nobody would see the worktree at\n * all, so every session in the repository does, and may close it.\n */\n unowned: boolean;\n}\n\n/**\n * What the panel asks the hub channel to do.\n *\n * The dock acts through its own channel rather than through the agent: a\n * worktree made from the panel and one made by the tool take the same\n * `worktreeOperations` path, but the panel no longer has to spend a turn of\n * the conversation to get there.\n */\nexport type GitWorktreesCommand =\n | { action: 'create'; branch: string; baseRef?: string }\n | { action: 'close'; id: string; force?: boolean };\n\nexport interface GitWorktreesPayload {\n worktrees: WorktreeView[];\n /** Label of the operation in flight, absent when the session is idle. */\n pending?: string;\n /** The last failure, cleared when the next command starts. */\n error?: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAa,qBAAqB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/types/webWorktrees.ts
|
|
2
|
+
/**
|
|
3
|
+
* The cockpit's view of this session's worktrees.
|
|
4
|
+
*
|
|
5
|
+
* DESIGN PATTERNS:
|
|
6
|
+
* - Declarations only. The channel frame type is a constant so the hub and the
|
|
7
|
+
* page cannot drift apart on a string.
|
|
8
|
+
* - A view is the subset of a record the dock needs, not the record. The
|
|
9
|
+
* registry may hold paths and provenance the page has no business rendering.
|
|
10
|
+
*
|
|
11
|
+
* AVOID:
|
|
12
|
+
* - Adding behaviour here. This file is imported by browser code, so it must
|
|
13
|
+
* stay free of node builtins.
|
|
14
|
+
*/
|
|
15
|
+
/** The data channel carrying one session's worktrees to the page. */
|
|
16
|
+
const GIT_WORKTREES_TYPE = "git_worktrees";
|
|
17
|
+
//#endregion
|
|
18
|
+
export { GIT_WORKTREES_TYPE };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=webWorktrees.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webWorktrees.mjs","names":[],"sources":["../../../src/types/webWorktrees.ts"],"sourcesContent":["/**\n * The cockpit's view of this session's worktrees.\n *\n * DESIGN PATTERNS:\n * - Declarations only. The channel frame type is a constant so the hub and the\n * page cannot drift apart on a string.\n * - A view is the subset of a record the dock needs, not the record. The\n * registry may hold paths and provenance the page has no business rendering.\n *\n * AVOID:\n * - Adding behaviour here. This file is imported by browser code, so it must\n * stay free of node builtins.\n */\n\n/** The data channel carrying one session's worktrees to the page. */\nexport const GIT_WORKTREES_TYPE = 'git_worktrees';\n\n/** One worktree, as the activity dock and its panel render it. */\nexport interface WorktreeView {\n id: string;\n branch: string;\n path: string;\n /** The session the hub started for this worktree, when it is still live. */\n sessionId: string | null;\n /** True once the directory the record names has gone missing. */\n orphaned: boolean;\n /**\n * True when the session that asked for this worktree is gone.\n *\n * An owned worktree is only ever shown to its own session. This flag marks\n * the exception: once the parent is dead nobody would see the worktree at\n * all, so every session in the repository does, and may close it.\n */\n unowned: boolean;\n}\n\n/**\n * What the panel asks the hub channel to do.\n *\n * The dock acts through its own channel rather than through the agent: a\n * worktree made from the panel and one made by the tool take the same\n * `worktreeOperations` path, but the panel no longer has to spend a turn of\n * the conversation to get there.\n */\nexport type GitWorktreesCommand =\n | { action: 'create'; branch: string; baseRef?: string }\n | { action: 'close'; id: string; force?: boolean };\n\nexport interface GitWorktreesPayload {\n worktrees: WorktreeView[];\n /** Label of the operation in flight, absent when the session is idle. */\n pending?: string;\n /** The last failure, cleared when the next command starts. */\n error?: string;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,MAAa,qBAAqB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktreeRegistry.d.cts","names":[],"sources":["../../../src/types/worktreeRegistry.ts"],"mappings":";;;;;;;;;;;;;;;;YAgBY;qBAEC;iBAEI;EACf,gBAAgB;;EAEhB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA,QAAQ;;EAER"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktreeRegistry.d.mts","names":[],"sources":["../../../src/types/worktreeRegistry.ts"],"mappings":";;;;;;;;;;;;;;;;YAgBY;qBAEC;iBAEI;EACf,gBAAgB;;EAEhB;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;;EAEA;EACA,QAAQ;;EAER"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/doompi-git",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.9",
|
|
4
4
|
"description": "Git worktree sessions for DoomPi: spawn an isolated worktree with its own session and manage it from the parent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -25,21 +25,17 @@
|
|
|
25
25
|
"directory": "layers/source-control/doompi-git"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"LICENSE",
|
|
29
|
-
"README.md",
|
|
30
28
|
"dist",
|
|
31
|
-
"llms.txt",
|
|
32
|
-
"package.json",
|
|
33
|
-
"src/extensions/web.ts",
|
|
34
29
|
"src/prompts",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
30
|
+
"llms.txt",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"package.json"
|
|
39
34
|
],
|
|
40
35
|
"type": "module",
|
|
41
36
|
"main": "./dist/index.cjs",
|
|
42
|
-
"
|
|
37
|
+
"module": "./dist/index.mjs",
|
|
38
|
+
"types": "./dist/index.d.cts",
|
|
43
39
|
"jsnext:main": "./dist/index.mjs",
|
|
44
40
|
"exports": {
|
|
45
41
|
".": {
|
|
@@ -47,6 +43,11 @@
|
|
|
47
43
|
"import": "./dist/index.mjs",
|
|
48
44
|
"require": "./dist/index.cjs"
|
|
49
45
|
},
|
|
46
|
+
"./api-contracts": {
|
|
47
|
+
"types": "./dist/api-contracts.d.mts",
|
|
48
|
+
"import": "./dist/api-contracts.mjs",
|
|
49
|
+
"require": "./dist/api-contracts.cjs"
|
|
50
|
+
},
|
|
50
51
|
"./extensions/pi": {
|
|
51
52
|
"types": "./dist/extensions/pi.d.mts",
|
|
52
53
|
"import": "./dist/extensions/pi.mjs",
|
|
@@ -57,21 +58,25 @@
|
|
|
57
58
|
"import": "./dist/extensions/server.mjs",
|
|
58
59
|
"require": "./dist/extensions/server.cjs"
|
|
59
60
|
},
|
|
61
|
+
"./extensions/web": {
|
|
62
|
+
"import": "./dist/extensions/web.mjs"
|
|
63
|
+
},
|
|
60
64
|
"./package.json": "./package.json"
|
|
61
65
|
},
|
|
62
66
|
"publishConfig": {
|
|
63
67
|
"access": "public"
|
|
64
68
|
},
|
|
65
69
|
"dependencies": {
|
|
66
|
-
"@agimon-ai/doompi-core": "0.0.1-alpha.
|
|
67
|
-
"@agimon-ai/doompi-web-components": "0.0.1-alpha.
|
|
70
|
+
"@agimon-ai/doompi-core": "0.0.1-alpha.73",
|
|
71
|
+
"@agimon-ai/doompi-web-components": "0.0.1-alpha.31",
|
|
68
72
|
"@deepseek-ai/cordis": "4.0.2",
|
|
69
73
|
"@tanstack/react-store": "0.11.1",
|
|
70
74
|
"@tanstack/store": "0.11.1",
|
|
71
75
|
"typebox": "1.3.30"
|
|
72
76
|
},
|
|
73
77
|
"devDependencies": {
|
|
74
|
-
"@agimon-ai/
|
|
78
|
+
"@agimon-ai/doompi-build": "0.0.1-alpha.2",
|
|
79
|
+
"@agimon-ai/vibe-lint-plugin-doom-extension": "0.0.1-alpha.68",
|
|
75
80
|
"@earendil-works/pi-agent-core": "0.85.1",
|
|
76
81
|
"@earendil-works/pi-coding-agent": "0.85.1",
|
|
77
82
|
"@types/node": "26.5.1",
|
|
@@ -99,12 +104,12 @@
|
|
|
99
104
|
"node": ">=22.19.0"
|
|
100
105
|
},
|
|
101
106
|
"doompiServer": {
|
|
102
|
-
"entry": "./
|
|
107
|
+
"entry": "./generated/server.ts",
|
|
103
108
|
"dist": "./dist/extensions/server.mjs",
|
|
104
109
|
"scopes": [
|
|
105
|
-
"session",
|
|
106
110
|
"global",
|
|
107
|
-
"workspace"
|
|
111
|
+
"workspace",
|
|
112
|
+
"session"
|
|
108
113
|
],
|
|
109
114
|
"contracts": {
|
|
110
115
|
"entry": "./src/exports/apiContracts.ts",
|
|
@@ -116,7 +121,7 @@
|
|
|
116
121
|
"channels": [
|
|
117
122
|
"git_worktrees"
|
|
118
123
|
],
|
|
119
|
-
"client": "./
|
|
124
|
+
"client": "./dist/extensions/web.mjs",
|
|
120
125
|
"scopes": [
|
|
121
126
|
"session"
|
|
122
127
|
]
|
|
@@ -129,7 +134,7 @@
|
|
|
129
134
|
"scripts": {
|
|
130
135
|
"build": "tsdown",
|
|
131
136
|
"test": "vitest --run",
|
|
132
|
-
"typecheck": "tsc --noEmit",
|
|
137
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.web.json",
|
|
133
138
|
"lint": "oxlint . && oxfmt . --check",
|
|
134
139
|
"fixcode": "oxlint . --fix && oxfmt ."
|
|
135
140
|
}
|
package/dist/constants/git.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"git.cjs","names":[],"sources":["../../src/constants/git.ts"],"sourcesContent":["export const COMMAND_NAME = 'doom-git';\nexport const COMMAND_DESCRIPTION = 'Show git worktrees owned by this session';\n"],"mappings":""}
|
package/dist/constants/git.mjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"git.mjs","names":[],"sources":["../../src/constants/git.ts"],"sourcesContent":["export const COMMAND_NAME = 'doom-git';\nexport const COMMAND_DESCRIPTION = 'Show git worktrees owned by this session';\n"],"mappings":"AAAA,MAAa,EAAe,WACf,EAAsB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitCommand.cjs","names":["COMMAND_NAME","COMMAND_DESCRIPTION"],"sources":["../../src/controllers/gitCommand.ts"],"sourcesContent":["// @scaffold-generated\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { COMMAND_NAME, COMMAND_DESCRIPTION } from '../constants/git';\nimport type { GitExtensionService } from '../types/extension';\n\nexport function createGitCommand(\n service: GitExtensionService,\n): readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]] {\n return [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => {\n const result = await service.execute();\n if (ctx.hasUI) ctx.ui.notify(result.message, result.level);\n },\n },\n ];\n}\n"],"mappings":"wCAMA,SAAgB,EACd,EACmE,CACnE,MAAO,CACLA,EAAAA,aACA,CACE,YAAaC,EAAAA,oBACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,IAAM,EAAS,MAAM,EAAQ,QAAQ,EACjC,EAAI,OAAO,EAAI,GAAG,OAAO,EAAO,QAAS,EAAO,KAAK,CAC3D,CACF,CACF,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitCommand.mjs","names":[],"sources":["../../src/controllers/gitCommand.ts"],"sourcesContent":["// @scaffold-generated\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\n\nimport { COMMAND_NAME, COMMAND_DESCRIPTION } from '../constants/git';\nimport type { GitExtensionService } from '../types/extension';\n\nexport function createGitCommand(\n service: GitExtensionService,\n): readonly [string, Parameters<ExtensionAPI['registerCommand']>[1]] {\n return [\n COMMAND_NAME,\n {\n description: COMMAND_DESCRIPTION,\n handler: async (_args, ctx) => {\n const result = await service.execute();\n if (ctx.hasUI) ctx.ui.notify(result.message, result.level);\n },\n },\n ];\n}\n"],"mappings":"6EAMA,SAAgB,EACd,EACmE,CACnE,MAAO,CACL,EACA,CACE,YAAa,EACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,IAAM,EAAS,MAAM,EAAQ,QAAQ,EACjC,EAAI,OAAO,EAAI,GAAG,OAAO,EAAO,QAAS,EAAO,KAAK,CAC3D,CACF,CACF,CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../services/gitCli/index.cjs"),t=require("../services/worktreeEvents/index.cjs"),n=require("../services/worktreeOperations/index.cjs"),r=require("../schemas/runWorktreeTool.cjs"),i=require("../services/runWorktree/index.cjs");let a=require("node:fs/promises");const o=new URL(`../../`,require("url").pathToFileURL(__filename).href);async function s(e){try{return await(0,a.readFile)(new URL(e,o),`utf8`)}catch{return`(resource unavailable: ${e})`}}function c(e,t){return{content:[{type:`text`,text:t}],details:{action:e}}}function l({host:a}){if(a.context.directEvents===void 0)throw Error(`Git headless facet requires the session direct event bus.`);if(a.context.sessionId===void 0)throw Error(`Git headless facet requires a session identity.`);let o=a.context.sessionId,l=a.context.directEvents,u=t.createWorktreeMessageInbox(l,o),d=n.createWorktreeOperations({git:e.createWorktreeGit(),sessionService:a.context.sessionService,messageInbox:u});return{resources:[{name:`doompi-git`,kind:`context`,read:()=>s(`llms.txt`)},{name:`doompi-use-git`,kind:`skill`,read:()=>s(`src/prompts/doompi-use-git/SKILL.md`)},{name:`doompi-git-readme`,kind:`context`,read:()=>s(`README.md`)}],tools:[{name:i.RUN_WORKTREE_TOOL_NAME,label:`Worktree`,description:i.RUN_WORKTREE_DESCRIPTION,parameters:r.RunWorktreeToolSchema,promptSnippet:`Create and manage Git worktree sessions`,executionMode:`serial`,async execute(e,t,n,r,a){let o=i.validateParams(t);return i.executeRunWorktreeTool(o,d,a,{...n===void 0?{}:{signal:n},onProgress:e=>r?.(c(o.action,e))})}}],onDispose:()=>u.close()}}exports.createGitSession=l;
|
|
2
|
-
//# sourceMappingURL=gitSession.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitSession.cjs","names":["readFile","createWorktreeMessageInbox","createWorktreeOperations","createWorktreeGit","RUN_WORKTREE_TOOL_NAME","RUN_WORKTREE_DESCRIPTION","RunWorktreeToolSchema","validateParams","executeRunWorktreeTool"],"sources":["../../src/controllers/gitSession.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport {\n type DoomHeadlessResource,\n type DoomHeadlessTool,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { RunWorktreeToolSchema, type RunWorktreeToolParams } from '../schemas/runWorktreeTool';\nimport { createWorktreeGit } from '../services/gitCli';\nimport {\n executeRunWorktreeTool,\n RUN_WORKTREE_DESCRIPTION,\n RUN_WORKTREE_TOOL_NAME,\n validateParams,\n} from '../services/runWorktree';\nimport { createWorktreeMessageInbox } from '../services/worktreeEvents';\nimport { createWorktreeOperations } from '../services/worktreeOperations';\n\nconst PACKAGE_ROOT = new URL('../../', import.meta.url);\n\nasync function readPackageResource(name: string): Promise<string> {\n try {\n return await readFile(new URL(name, PACKAGE_ROOT), 'utf8');\n } catch {\n return `(resource unavailable: ${name})`;\n }\n}\n\nfunction progressResult(action: RunWorktreeToolParams['action'], label: string): DoomHeadlessToolResult {\n return { content: [{ type: 'text', text: label }], details: { action } };\n}\n\nexport function createGitSession({ host: serverHost }: DoomServerPluginContext): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Git headless facet requires the session direct event bus.');\n if (serverHost.context.sessionId === undefined) throw new Error('Git headless facet requires a session identity.');\n const sessionId = serverHost.context.sessionId;\n const directEvents = serverHost.context.directEvents;\n const messageInbox = createWorktreeMessageInbox(directEvents, sessionId);\n const operations = createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService: serverHost.context.sessionService,\n messageInbox,\n });\n const resources: DoomHeadlessResource[] = [\n { name: 'doompi-git', kind: 'context', read: () => readPackageResource('llms.txt') },\n {\n name: 'doompi-use-git',\n kind: 'skill',\n read: () => readPackageResource('src/prompts/doompi-use-git/SKILL.md'),\n },\n { name: 'doompi-git-readme', kind: 'context', read: () => readPackageResource('README.md') },\n ];\n\n const tool: DoomHeadlessTool<typeof RunWorktreeToolSchema> = {\n name: RUN_WORKTREE_TOOL_NAME,\n label: 'Worktree',\n description: RUN_WORKTREE_DESCRIPTION,\n parameters: RunWorktreeToolSchema,\n promptSnippet: 'Create and manage Git worktree sessions',\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, onUpdate, execution) {\n const params = validateParams(parameters) as RunWorktreeToolParams;\n return executeRunWorktreeTool(params, operations, execution, {\n ...(signal === undefined ? {} : { signal }),\n onProgress: (label) => onUpdate?.(progressResult(params.action, label)),\n });\n },\n };\n return { resources, tools: [tool], onDispose: () => messageInbox.close() };\n}\n"],"mappings":"qRAoBA,MAAM,EAAe,IAAI,IAAI,SAAA,QAAA,KAAA,CAAA,CAAA,cAAA,UAAA,CAAA,CAAA,IAAyB,EAEtD,eAAe,EAAoB,EAA+B,CAChE,GAAI,CACF,OAAO,MAAA,EAAMA,EAAAA,SAAAA,CAAS,IAAI,IAAI,EAAM,CAAY,EAAG,MAAM,CAC3D,MAAQ,CACN,MAAO,0BAA0B,EAAK,EACxC,CACF,CAEA,SAAS,EAAe,EAAyC,EAAuC,CACtG,MAAO,CAAE,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,CAAM,CAAC,EAAG,QAAS,CAAE,QAAO,CAAE,CACzE,CAEA,SAAgB,EAAiB,CAAE,KAAM,GAAgE,CACvG,GAAI,EAAW,QAAQ,eAAiB,IAAA,GACtC,MAAU,MAAM,2DAA2D,EAC7E,GAAI,EAAW,QAAQ,YAAc,IAAA,GAAW,MAAU,MAAM,iDAAiD,EACjH,IAAM,EAAY,EAAW,QAAQ,UAC/B,EAAe,EAAW,QAAQ,aAClC,EAAeC,EAAAA,2BAA2B,EAAc,CAAS,EACjE,EAAaC,EAAAA,yBAAyB,CAC1C,IAAKC,EAAAA,kBAAkB,EACvB,eAAgB,EAAW,QAAQ,eACnC,cACF,CAAC,EA0BD,MAAO,CAAE,UAAA,CAxBP,CAAE,KAAM,aAAc,KAAM,UAAW,SAAY,EAAoB,UAAU,CAAE,EACnF,CACE,KAAM,iBACN,KAAM,QACN,SAAY,EAAoB,qCAAqC,CACvE,EACA,CAAE,KAAM,oBAAqB,KAAM,UAAW,SAAY,EAAoB,WAAW,CAAE,CAkB5E,EAAG,MAAO,CAAC,CAd1B,KAAMC,EAAAA,uBACN,MAAO,WACP,YAAaC,EAAAA,yBACb,WAAYC,EAAAA,sBACZ,cAAe,0CACf,cAAe,SACf,MAAM,QAAQ,EAAa,EAAY,EAAQ,EAAU,EAAW,CAClE,IAAM,EAASC,EAAAA,eAAe,CAAU,EACxC,OAAOC,EAAAA,uBAAuB,EAAQ,EAAY,EAAW,CAC3D,GAAI,IAAW,IAAA,GAAY,CAAC,EAAI,CAAE,QAAO,EACzC,WAAa,GAAU,IAAW,EAAe,EAAO,OAAQ,CAAK,CAAC,CACxE,CAAC,CACH,CAE6B,CAAC,EAAG,cAAiB,EAAa,MAAM,CAAE,CAC3E"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createWorktreeGit as e}from"../services/gitCli/index.mjs";import{createWorktreeMessageInbox as t}from"../services/worktreeEvents/index.mjs";import{createWorktreeOperations as n}from"../services/worktreeOperations/index.mjs";import{RunWorktreeToolSchema as r}from"../schemas/runWorktreeTool.mjs";import{RUN_WORKTREE_DESCRIPTION as i,RUN_WORKTREE_TOOL_NAME as a,executeRunWorktreeTool as o,validateParams as s}from"../services/runWorktree/index.mjs";import{readFile as c}from"node:fs/promises";const l=new URL(`../../`,import.meta.url);async function u(e){try{return await c(new URL(e,l),`utf8`)}catch{return`(resource unavailable: ${e})`}}function d(e,t){return{content:[{type:`text`,text:t}],details:{action:e}}}function f({host:c}){if(c.context.directEvents===void 0)throw Error(`Git headless facet requires the session direct event bus.`);if(c.context.sessionId===void 0)throw Error(`Git headless facet requires a session identity.`);let l=c.context.sessionId,f=c.context.directEvents,p=t(f,l),m=n({git:e(),sessionService:c.context.sessionService,messageInbox:p});return{resources:[{name:`doompi-git`,kind:`context`,read:()=>u(`llms.txt`)},{name:`doompi-use-git`,kind:`skill`,read:()=>u(`src/prompts/doompi-use-git/SKILL.md`)},{name:`doompi-git-readme`,kind:`context`,read:()=>u(`README.md`)}],tools:[{name:a,label:`Worktree`,description:i,parameters:r,promptSnippet:`Create and manage Git worktree sessions`,executionMode:`serial`,async execute(e,t,n,r,i){let a=s(t);return o(a,m,i,{...n===void 0?{}:{signal:n},onProgress:e=>r?.(d(a.action,e))})}}],onDispose:()=>p.close()}}export{f as createGitSession};
|
|
2
|
-
//# sourceMappingURL=gitSession.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gitSession.mjs","names":[],"sources":["../../src/controllers/gitSession.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport {\n type DoomHeadlessResource,\n type DoomHeadlessTool,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport type { DoomServerPluginContext, DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport { RunWorktreeToolSchema, type RunWorktreeToolParams } from '../schemas/runWorktreeTool';\nimport { createWorktreeGit } from '../services/gitCli';\nimport {\n executeRunWorktreeTool,\n RUN_WORKTREE_DESCRIPTION,\n RUN_WORKTREE_TOOL_NAME,\n validateParams,\n} from '../services/runWorktree';\nimport { createWorktreeMessageInbox } from '../services/worktreeEvents';\nimport { createWorktreeOperations } from '../services/worktreeOperations';\n\nconst PACKAGE_ROOT = new URL('../../', import.meta.url);\n\nasync function readPackageResource(name: string): Promise<string> {\n try {\n return await readFile(new URL(name, PACKAGE_ROOT), 'utf8');\n } catch {\n return `(resource unavailable: ${name})`;\n }\n}\n\nfunction progressResult(action: RunWorktreeToolParams['action'], label: string): DoomHeadlessToolResult {\n return { content: [{ type: 'text', text: label }], details: { action } };\n}\n\nexport function createGitSession({ host: serverHost }: DoomServerPluginContext): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Git headless facet requires the session direct event bus.');\n if (serverHost.context.sessionId === undefined) throw new Error('Git headless facet requires a session identity.');\n const sessionId = serverHost.context.sessionId;\n const directEvents = serverHost.context.directEvents;\n const messageInbox = createWorktreeMessageInbox(directEvents, sessionId);\n const operations = createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService: serverHost.context.sessionService,\n messageInbox,\n });\n const resources: DoomHeadlessResource[] = [\n { name: 'doompi-git', kind: 'context', read: () => readPackageResource('llms.txt') },\n {\n name: 'doompi-use-git',\n kind: 'skill',\n read: () => readPackageResource('src/prompts/doompi-use-git/SKILL.md'),\n },\n { name: 'doompi-git-readme', kind: 'context', read: () => readPackageResource('README.md') },\n ];\n\n const tool: DoomHeadlessTool<typeof RunWorktreeToolSchema> = {\n name: RUN_WORKTREE_TOOL_NAME,\n label: 'Worktree',\n description: RUN_WORKTREE_DESCRIPTION,\n parameters: RunWorktreeToolSchema,\n promptSnippet: 'Create and manage Git worktree sessions',\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, onUpdate, execution) {\n const params = validateParams(parameters) as RunWorktreeToolParams;\n return executeRunWorktreeTool(params, operations, execution, {\n ...(signal === undefined ? {} : { signal }),\n onProgress: (label) => onUpdate?.(progressResult(params.action, label)),\n });\n },\n };\n return { resources, tools: [tool], onDispose: () => messageInbox.close() };\n}\n"],"mappings":"mfAoBA,MAAM,EAAe,IAAI,IAAI,SAAU,YAAY,GAAG,EAEtD,eAAe,EAAoB,EAA+B,CAChE,GAAI,CACF,OAAO,MAAM,EAAS,IAAI,IAAI,EAAM,CAAY,EAAG,MAAM,CAC3D,MAAQ,CACN,MAAO,0BAA0B,EAAK,EACxC,CACF,CAEA,SAAS,EAAe,EAAyC,EAAuC,CACtG,MAAO,CAAE,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,CAAM,CAAC,EAAG,QAAS,CAAE,QAAO,CAAE,CACzE,CAEA,SAAgB,EAAiB,CAAE,KAAM,GAAgE,CACvG,GAAI,EAAW,QAAQ,eAAiB,IAAA,GACtC,MAAU,MAAM,2DAA2D,EAC7E,GAAI,EAAW,QAAQ,YAAc,IAAA,GAAW,MAAU,MAAM,iDAAiD,EACjH,IAAM,EAAY,EAAW,QAAQ,UAC/B,EAAe,EAAW,QAAQ,aAClC,EAAe,EAA2B,EAAc,CAAS,EACjE,EAAa,EAAyB,CAC1C,IAAK,EAAkB,EACvB,eAAgB,EAAW,QAAQ,eACnC,cACF,CAAC,EA0BD,MAAO,CAAE,UAAA,CAxBP,CAAE,KAAM,aAAc,KAAM,UAAW,SAAY,EAAoB,UAAU,CAAE,EACnF,CACE,KAAM,iBACN,KAAM,QACN,SAAY,EAAoB,qCAAqC,CACvE,EACA,CAAE,KAAM,oBAAqB,KAAM,UAAW,SAAY,EAAoB,WAAW,CAAE,CAkB5E,EAAG,MAAO,CAAC,CAd1B,KAAM,EACN,MAAO,WACP,YAAa,EACb,WAAY,EACZ,cAAe,0CACf,cAAe,SACf,MAAM,QAAQ,EAAa,EAAY,EAAQ,EAAU,EAAW,CAClE,IAAM,EAAS,EAAe,CAAU,EACxC,OAAO,EAAuB,EAAQ,EAAY,EAAW,CAC3D,GAAI,IAAW,IAAA,GAAY,CAAC,EAAI,CAAE,QAAO,EACzC,WAAa,GAAU,IAAW,EAAe,EAAO,OAAQ,CAAK,CAAC,CACxE,CAAC,CACH,CAE6B,CAAC,EAAG,cAAiB,EAAa,MAAM,CAAE,CAC3E"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../services/gitCli/index.cjs"),t=require("../services/errors/index.cjs"),n=require("../services/worktreeEvents/index.cjs"),r=require("../services/worktreeOperations/index.cjs");function i(e){return Response.json({error:e},{status:400})}function a(e){return e instanceof t.DoomGitExpectedError?Response.json({error:e.message,code:e.code},{status:e.retryable?503:409}):Response.json({error:`The worktree operation failed.`},{status:500})}const o={basePath:`git`,start(t){if(t.directEvents===void 0)throw Error(`Git hub API requires the direct event bus.`);let o=t.directEvents,s=(e,t)=>{o.publish(n.GIT_WORKTREE_LIFECYCLE_EVENT,e,{version:1,repositoryRoot:t})},c=r.createWorktreeOperations({git:e.createWorktreeGit(),sessionService:t.sessionService}),l=e=>{let n=e.searchParams.get(`repositoryId`);if(n===null||n===``)return i(`A repositoryId is required.`);let r=t.resolveRepository?.(n);return r===void 0?i(`That repository is not admitted to this cockpit.`):r};return{async fetch(e){let n=new URL(e.url),r=l(n);if(r instanceof Response)return r;let o={cwd:r,sessionId:n.searchParams.get(`sessionId`)??``};if((e.method===`POST`&&n.pathname===`/worktrees`||e.method===`DELETE`&&/^\/worktrees\/[^/]+$/u.test(n.pathname))&&o.sessionId===``)return i(`A sessionId is required for worktree mutations.`);try{if(e.method===`GET`&&n.pathname===`/worktrees`)return Response.json({worktrees:await c.list(o)});if(e.method===`POST`&&n.pathname===`/worktrees`){let t=await e.json();if(typeof t.branch!=`string`||t.branch.trim()===``)return i(`A branch is required.`);let n=await c.spawn(o,{branch:t.branch,...t.baseRef===void 0?{}:{baseRef:t.baseRef},...t.name===void 0?{}:{name:t.name}});return s(o.sessionId,n.repositoryRoot),Response.json({worktree:n},{status:201})}let t=/^\/worktrees\/([^/]+)$/u.exec(n.pathname);if(e.method===`DELETE`&&t){let e=await c.close(o,decodeURIComponent(String(t[1])),n.searchParams.get(`force`)===`true`);return s(o.sessionId,e.repositoryRoot),Response.json({worktree:e})}return Response.json({error:`No such worktree route.`},{status:404})}catch(e){return t.onNotice(`worktree request failed: ${e.name}`),a(e)}},close(){}}}};exports.api=o;
|
|
2
|
-
//# sourceMappingURL=hubApi.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hubApi.cjs","names":["DoomGitExpectedError","GIT_WORKTREE_LIFECYCLE_EVENT","createWorktreeOperations","createWorktreeGit"],"sources":["../../src/controllers/hubApi.ts"],"sourcesContent":["import type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-core/package-api';\n\nimport { DoomGitExpectedError } from '../services/errors';\nimport { createWorktreeGit } from '../services/gitCli';\nimport { GIT_WORKTREE_LIFECYCLE_EVENT } from '../services/worktreeEvents';\nimport { createWorktreeOperations } from '../services/worktreeOperations';\n\n/**\n * The worktree surface the cockpit panel calls.\n *\n * Hub-scoped because worktrees are a property of a repository, not of one\n * session: the panel lists and creates them whether or not the session that\n * made them is focused, and a session-scoped API would disappear with it.\n *\n * The panel names a repository by the hub's opaque id and never by path.\n * `resolveRepository` turns that into an admitted root, so a browser cannot\n * point this at a directory the cockpit was never given.\n */\nfunction badRequest(message: string): Response {\n return Response.json({ error: message }, { status: 400 });\n}\n\nfunction failed(error: unknown): Response {\n if (error instanceof DoomGitExpectedError) {\n return Response.json({ error: error.message, code: error.code }, { status: error.retryable ? 503 : 409 });\n }\n // Never the raw message: a git failure can carry a remote URL with a token.\n return Response.json({ error: 'The worktree operation failed.' }, { status: 500 });\n}\n\nexport const api: DoomApi = {\n basePath: 'git',\n start(context: DoomApiContext): DoomApiHandler {\n if (context.directEvents === undefined) throw new Error('Git hub API requires the direct event bus.');\n const directEvents = context.directEvents;\n const publishLifecycle = (sessionId: string, repositoryRoot: string): void => {\n directEvents.publish(GIT_WORKTREE_LIFECYCLE_EVENT, sessionId, { version: 1 as const, repositoryRoot });\n };\n const operations = createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService: context.sessionService,\n });\n\n /** The admitted root for a request, or a response explaining why not. */\n const rootOf = (url: URL): string | Response => {\n const repositoryId = url.searchParams.get('repositoryId');\n if (repositoryId === null || repositoryId === '') return badRequest('A repositoryId is required.');\n const root = context.resolveRepository?.(repositoryId);\n if (root === undefined) return badRequest('That repository is not admitted to this cockpit.');\n return root;\n };\n\n return {\n async fetch(request) {\n const url = new URL(request.url);\n const root = rootOf(url);\n if (root instanceof Response) return root;\n // The operations layer works from a cwd, and an admitted repository\n // root is one.\n const callerContext = { cwd: root, sessionId: url.searchParams.get('sessionId') ?? '' };\n const isMutation =\n (request.method === 'POST' && url.pathname === '/worktrees') ||\n (request.method === 'DELETE' && /^\\/worktrees\\/[^/]+$/u.test(url.pathname));\n if (isMutation && callerContext.sessionId === '')\n return badRequest('A sessionId is required for worktree mutations.');\n\n try {\n if (request.method === 'GET' && url.pathname === '/worktrees') {\n return Response.json({ worktrees: await operations.list(callerContext) });\n }\n if (request.method === 'POST' && url.pathname === '/worktrees') {\n const body = (await request.json()) as { branch?: string; baseRef?: string; name?: string };\n if (typeof body.branch !== 'string' || body.branch.trim() === '') {\n return badRequest('A branch is required.');\n }\n const record = await operations.spawn(callerContext, {\n branch: body.branch,\n ...(body.baseRef === undefined ? {} : { baseRef: body.baseRef }),\n ...(body.name === undefined ? {} : { name: body.name }),\n });\n publishLifecycle(callerContext.sessionId, record.repositoryRoot);\n return Response.json({ worktree: record }, { status: 201 });\n }\n const closing = /^\\/worktrees\\/([^/]+)$/u.exec(url.pathname);\n if (request.method === 'DELETE' && closing) {\n const record = await operations.close(\n callerContext,\n decodeURIComponent(String(closing[1])),\n url.searchParams.get('force') === 'true',\n );\n publishLifecycle(callerContext.sessionId, record.repositoryRoot);\n return Response.json({ worktree: record });\n }\n return Response.json({ error: 'No such worktree route.' }, { status: 404 });\n } catch (error) {\n context.onNotice(`worktree request failed: ${(error as Error).name}`);\n return failed(error);\n }\n },\n close() {},\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}from"../services/errors/index.mjs";import{GIT_WORKTREE_LIFECYCLE_EVENT as n}from"../services/worktreeEvents/index.mjs";import{createWorktreeOperations as r}from"../services/worktreeOperations/index.mjs";function i(e){return Response.json({error:e},{status:400})}function a(e){return e instanceof t?Response.json({error:e.message,code:e.code},{status:e.retryable?503:409}):Response.json({error:`The worktree operation failed.`},{status:500})}const o={basePath:`git`,start(t){if(t.directEvents===void 0)throw Error(`Git hub API requires the direct event bus.`);let o=t.directEvents,s=(e,t)=>{o.publish(n,e,{version:1,repositoryRoot:t})},c=r({git:e(),sessionService:t.sessionService}),l=e=>{let n=e.searchParams.get(`repositoryId`);if(n===null||n===``)return i(`A repositoryId is required.`);let r=t.resolveRepository?.(n);return r===void 0?i(`That repository is not admitted to this cockpit.`):r};return{async fetch(e){let n=new URL(e.url),r=l(n);if(r instanceof Response)return r;let o={cwd:r,sessionId:n.searchParams.get(`sessionId`)??``};if((e.method===`POST`&&n.pathname===`/worktrees`||e.method===`DELETE`&&/^\/worktrees\/[^/]+$/u.test(n.pathname))&&o.sessionId===``)return i(`A sessionId is required for worktree mutations.`);try{if(e.method===`GET`&&n.pathname===`/worktrees`)return Response.json({worktrees:await c.list(o)});if(e.method===`POST`&&n.pathname===`/worktrees`){let t=await e.json();if(typeof t.branch!=`string`||t.branch.trim()===``)return i(`A branch is required.`);let n=await c.spawn(o,{branch:t.branch,...t.baseRef===void 0?{}:{baseRef:t.baseRef},...t.name===void 0?{}:{name:t.name}});return s(o.sessionId,n.repositoryRoot),Response.json({worktree:n},{status:201})}let t=/^\/worktrees\/([^/]+)$/u.exec(n.pathname);if(e.method===`DELETE`&&t){let e=await c.close(o,decodeURIComponent(String(t[1])),n.searchParams.get(`force`)===`true`);return s(o.sessionId,e.repositoryRoot),Response.json({worktree:e})}return Response.json({error:`No such worktree route.`},{status:404})}catch(e){return t.onNotice(`worktree request failed: ${e.name}`),a(e)}},close(){}}}};export{o as api};
|
|
2
|
-
//# sourceMappingURL=hubApi.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hubApi.mjs","names":[],"sources":["../../src/controllers/hubApi.ts"],"sourcesContent":["import type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-core/package-api';\n\nimport { DoomGitExpectedError } from '../services/errors';\nimport { createWorktreeGit } from '../services/gitCli';\nimport { GIT_WORKTREE_LIFECYCLE_EVENT } from '../services/worktreeEvents';\nimport { createWorktreeOperations } from '../services/worktreeOperations';\n\n/**\n * The worktree surface the cockpit panel calls.\n *\n * Hub-scoped because worktrees are a property of a repository, not of one\n * session: the panel lists and creates them whether or not the session that\n * made them is focused, and a session-scoped API would disappear with it.\n *\n * The panel names a repository by the hub's opaque id and never by path.\n * `resolveRepository` turns that into an admitted root, so a browser cannot\n * point this at a directory the cockpit was never given.\n */\nfunction badRequest(message: string): Response {\n return Response.json({ error: message }, { status: 400 });\n}\n\nfunction failed(error: unknown): Response {\n if (error instanceof DoomGitExpectedError) {\n return Response.json({ error: error.message, code: error.code }, { status: error.retryable ? 503 : 409 });\n }\n // Never the raw message: a git failure can carry a remote URL with a token.\n return Response.json({ error: 'The worktree operation failed.' }, { status: 500 });\n}\n\nexport const api: DoomApi = {\n basePath: 'git',\n start(context: DoomApiContext): DoomApiHandler {\n if (context.directEvents === undefined) throw new Error('Git hub API requires the direct event bus.');\n const directEvents = context.directEvents;\n const publishLifecycle = (sessionId: string, repositoryRoot: string): void => {\n directEvents.publish(GIT_WORKTREE_LIFECYCLE_EVENT, sessionId, { version: 1 as const, repositoryRoot });\n };\n const operations = createWorktreeOperations({\n git: createWorktreeGit(),\n sessionService: context.sessionService,\n });\n\n /** The admitted root for a request, or a response explaining why not. */\n const rootOf = (url: URL): string | Response => {\n const repositoryId = url.searchParams.get('repositoryId');\n if (repositoryId === null || repositoryId === '') return badRequest('A repositoryId is required.');\n const root = context.resolveRepository?.(repositoryId);\n if (root === undefined) return badRequest('That repository is not admitted to this cockpit.');\n return root;\n };\n\n return {\n async fetch(request) {\n const url = new URL(request.url);\n const root = rootOf(url);\n if (root instanceof Response) return root;\n // The operations layer works from a cwd, and an admitted repository\n // root is one.\n const callerContext = { cwd: root, sessionId: url.searchParams.get('sessionId') ?? '' };\n const isMutation =\n (request.method === 'POST' && url.pathname === '/worktrees') ||\n (request.method === 'DELETE' && /^\\/worktrees\\/[^/]+$/u.test(url.pathname));\n if (isMutation && callerContext.sessionId === '')\n return badRequest('A sessionId is required for worktree mutations.');\n\n try {\n if (request.method === 'GET' && url.pathname === '/worktrees') {\n return Response.json({ worktrees: await operations.list(callerContext) });\n }\n if (request.method === 'POST' && url.pathname === '/worktrees') {\n const body = (await request.json()) as { branch?: string; baseRef?: string; name?: string };\n if (typeof body.branch !== 'string' || body.branch.trim() === '') {\n return badRequest('A branch is required.');\n }\n const record = await operations.spawn(callerContext, {\n branch: body.branch,\n ...(body.baseRef === undefined ? {} : { baseRef: body.baseRef }),\n ...(body.name === undefined ? {} : { name: body.name }),\n });\n publishLifecycle(callerContext.sessionId, record.repositoryRoot);\n return Response.json({ worktree: record }, { status: 201 });\n }\n const closing = /^\\/worktrees\\/([^/]+)$/u.exec(url.pathname);\n if (request.method === 'DELETE' && closing) {\n const record = await operations.close(\n callerContext,\n decodeURIComponent(String(closing[1])),\n url.searchParams.get('force') === 'true',\n );\n publishLifecycle(callerContext.sessionId, record.repositoryRoot);\n return Response.json({ worktree: record });\n }\n return Response.json({ error: 'No such worktree route.' }, { status: 404 });\n } catch (error) {\n context.onNotice(`worktree request failed: ${(error as Error).name}`);\n return failed(error);\n }\n },\n close() {},\n };\n },\n};\n"],"mappings":"6SAkBA,SAAS,EAAW,EAA2B,CAC7C,OAAO,SAAS,KAAK,CAAE,MAAO,CAAQ,EAAG,CAAE,OAAQ,GAAI,CAAC,CAC1D,CAEA,SAAS,EAAO,EAA0B,CAKxC,OAJI,aAAiB,EACZ,SAAS,KAAK,CAAE,MAAO,EAAM,QAAS,KAAM,EAAM,IAAK,EAAG,CAAE,OAAQ,EAAM,UAAY,IAAM,GAAI,CAAC,EAGnG,SAAS,KAAK,CAAE,MAAO,gCAAiC,EAAG,CAAE,OAAQ,GAAI,CAAC,CACnF,CAEA,MAAa,EAAe,CAC1B,SAAU,MACV,MAAM,EAAyC,CAC7C,GAAI,EAAQ,eAAiB,IAAA,GAAW,MAAU,MAAM,4CAA4C,EACpG,IAAM,EAAe,EAAQ,aACvB,GAAoB,EAAmB,IAAiC,CAC5E,EAAa,QAAQ,EAA8B,EAAW,CAAE,QAAS,EAAY,gBAAe,CAAC,CACvG,EACM,EAAa,EAAyB,CAC1C,IAAK,EAAkB,EACvB,eAAgB,EAAQ,cAC1B,CAAC,EAGK,EAAU,GAAgC,CAC9C,IAAM,EAAe,EAAI,aAAa,IAAI,cAAc,EACxD,GAAI,IAAiB,MAAQ,IAAiB,GAAI,OAAO,EAAW,6BAA6B,EACjG,IAAM,EAAO,EAAQ,oBAAoB,CAAY,EAErD,OADI,IAAS,IAAA,GAAkB,EAAW,kDAAkD,EACrF,CACT,EAEA,MAAO,CACL,MAAM,MAAM,EAAS,CACnB,IAAM,EAAM,IAAI,IAAI,EAAQ,GAAG,EACzB,EAAO,EAAO,CAAG,EACvB,GAAI,aAAgB,SAAU,OAAO,EAGrC,IAAM,EAAgB,CAAE,IAAK,EAAM,UAAW,EAAI,aAAa,IAAI,WAAW,GAAK,EAAG,EAItF,IAFG,EAAQ,SAAW,QAAU,EAAI,WAAa,cAC9C,EAAQ,SAAW,UAAY,wBAAwB,KAAK,EAAI,QAAQ,IACzD,EAAc,YAAc,GAC5C,OAAO,EAAW,iDAAiD,EAErE,GAAI,CACF,GAAI,EAAQ,SAAW,OAAS,EAAI,WAAa,aAC/C,OAAO,SAAS,KAAK,CAAE,UAAW,MAAM,EAAW,KAAK,CAAa,CAAE,CAAC,EAE1E,GAAI,EAAQ,SAAW,QAAU,EAAI,WAAa,aAAc,CAC9D,IAAM,EAAQ,MAAM,EAAQ,KAAK,EACjC,GAAI,OAAO,EAAK,QAAW,UAAY,EAAK,OAAO,KAAK,IAAM,GAC5D,OAAO,EAAW,uBAAuB,EAE3C,IAAM,EAAS,MAAM,EAAW,MAAM,EAAe,CACnD,OAAQ,EAAK,OACb,GAAI,EAAK,UAAY,IAAA,GAAY,CAAC,EAAI,CAAE,QAAS,EAAK,OAAQ,EAC9D,GAAI,EAAK,OAAS,IAAA,GAAY,CAAC,EAAI,CAAE,KAAM,EAAK,IAAK,CACvD,CAAC,EAED,OADA,EAAiB,EAAc,UAAW,EAAO,cAAc,EACxD,SAAS,KAAK,CAAE,SAAU,CAAO,EAAG,CAAE,OAAQ,GAAI,CAAC,CAC5D,CACA,IAAM,EAAU,0BAA0B,KAAK,EAAI,QAAQ,EAC3D,GAAI,EAAQ,SAAW,UAAY,EAAS,CAC1C,IAAM,EAAS,MAAM,EAAW,MAC9B,EACA,mBAAmB,OAAO,EAAQ,EAAE,CAAC,EACrC,EAAI,aAAa,IAAI,OAAO,IAAM,MACpC,EAEA,OADA,EAAiB,EAAc,UAAW,EAAO,cAAc,EACxD,SAAS,KAAK,CAAE,SAAU,CAAO,CAAC,CAC3C,CACA,OAAO,SAAS,KAAK,CAAE,MAAO,yBAA0B,EAAG,CAAE,OAAQ,GAAI,CAAC,CAC5E,OAAS,EAAO,CAEd,OADA,EAAQ,SAAS,4BAA6B,EAAgB,MAAM,EAC7D,EAAO,CAAK,CACrB,CACF,EACA,OAAQ,CAAC,CACX,CACF,CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../services/gitCli/index.cjs"),t=require("../services/errors/index.cjs"),n=require("../services/paths/index.cjs"),r=require("../services/worktreeEvents/index.cjs"),i=require("../services/worktreeRegistry/index.cjs"),a=require("../services/worktreeOperations/index.cjs"),o=require("../types/webWorktrees.cjs");function s(e){return{worktrees:e.worktrees,...e.pending===void 0?{}:{pending:e.pending},...e.error===void 0?{}:{error:e.error}}}function c(e,t){try{return i.createWorktreeRegistry(n.registryFile(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 l(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 u(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 d(e){return e instanceof t.DoomGitExpectedError?e.message:`The worktree operation failed.`}function f(i={}){let f;return{frameType:o.GIT_WORKTREES_TYPE,start(o){let p=o.sessionService;if(p===void 0)throw new t.HubUnavailableError(`The cockpit session service is unavailable. Start the cockpit and try again.`);let m=i.operations??a.createWorktreeOperations({git:e.createWorktreeGit(),sessionService:p}),h={homeDir:i.homeDir,sessionService:p},g=new Map,_=new Map,v=new Set,y=(e,t)=>{let n=g.get(e.sessionId),r={worktrees:c(e,h),pending:n?.pending,error:n?.error};(t||n===void 0||!l(n.worktrees,r.worktrees)||n.pending!==r.pending||n.error!==r.error)&&(g.set(e.sessionId,r),o.publish(e.sessionId,s(r)))},b=(e,t,n)=>{let r=g.get(e.sessionId);g.set(e.sessionId,{worktrees:r?.worktrees??c(e,h),pending:t,error:n}),y(e,!0)},x=(e,t)=>{o.directEvents.publish(r.GIT_WORKTREE_LIFECYCLE_EVENT,e.sessionId,{version:1,repositoryRoot:t})},S=async(e,t)=>{let n={cwd:e.cwd,sessionId:e.sessionId};if(t.action===`create`){b(e,`creating ${t.branch}\u2026`,void 0);let r=await m.spawn(n,{branch:t.branch,...t.baseRef===void 0?{}:{baseRef:t.baseRef}},{onProgress:t=>b(e,t,void 0)});x(e,r.repositoryRoot);return}b(e,`closing ${t.id}…`,void 0);let r=await m.close(n,t.id,t.force??!1);x(e,r.repositoryRoot)};return f=(e,t)=>{let n=u(t);n!==void 0&&(v.has(e.sessionId)||(v.add(e.sessionId),S(e,n).then(()=>{b(e,void 0,void 0)}).catch(t=>{o.onNotice(`worktree command failed for ${e.sessionId} (${d(t)})`),b(e,void 0,d(t))}).finally(()=>{v.delete(e.sessionId)})))},{payloadFor(e){let t=g.get(e.sessionId);return t===void 0?void 0:s(t)},sessionAdded(e){y(e,!1);let t=o.directEvents.subscribe(r.GIT_WORKTREE_LIFECYCLE_EVENT,e.sessionId,t=>{if(!r.isWorktreeLifecycleEvent(t))return;let a=!1;try{a=n.registryFile(e.cwd,i.homeDir)===n.registryFile(t.repositoryRoot,i.homeDir)}catch{a=!1}a&&y(e,!1)});_.set(e.sessionId,t)},sessionRemoved(e){_.get(e)?.(),_.delete(e),g.delete(e),v.delete(e)},close(){for(let e of _.values())e();_.clear(),g.clear(),v.clear()}}},receive(e,t){f?.(e,t)}}}exports.createWorktreesChannel=f;
|
|
2
|
-
//# sourceMappingURL=worktreesChannel.cjs.map
|
|
@@ -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":"8iBA2BA,SAAS,EAAU,EAA8C,CAC/D,MAAO,CACL,UAAW,EAAM,UACjB,GAAI,EAAM,UAAY,IAAA,GAAY,CAAC,EAAI,CAAE,QAAS,EAAM,OAAQ,EAChE,GAAI,EAAM,QAAU,IAAA,GAAY,CAAC,EAAI,CAAE,MAAO,EAAM,KAAM,CAC5D,CACF,CAcA,SAAS,EAAS,EAA4B,EAAgC,CAC5E,GAAI,CACF,OAAO,EAAuB,EAAa,EAAM,IAAK,EAAK,OAAO,CAAC,CAAC,CACjE,KAAK,CAAC,CACN,QAAS,GAAW,CACnB,IAAM,EAAQ,EAAO,kBAAoB,EAAM,UACzC,EAAU,CAAC,GAAS,CAAC,EAAK,eAAe,OAAO,EAAO,eAAe,EAE5E,MADI,CAAC,GAAS,CAAC,EAAgB,CAAC,EACzB,CACL,CACE,GAAI,EAAO,GACX,OAAQ,EAAO,OACf,KAAM,EAAO,KACb,UAAW,EAAO,SAAW,WAAa,KAAO,EAAO,UACxD,SAAU,EAAO,SAAW,WAC5B,SACF,CACF,CACF,CAAC,CACL,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CAEA,SAAS,EAAS,EAA+B,EAAyC,CAExF,OADI,EAAK,SAAW,EAAM,QACnB,EAAK,OAAO,EAAO,IAAU,CAClC,IAAM,EAAQ,EAAM,GACpB,OACE,IAAU,IAAA,IACV,EAAM,KAAO,EAAM,IACnB,EAAM,SAAW,EAAM,QACvB,EAAM,YAAc,EAAM,WAC1B,EAAM,WAAa,EAAM,UACzB,EAAM,UAAY,EAAM,OAE5B,CAAC,CACH,CAGA,SAAS,EAAa,EAAmD,CACvE,GAAI,OAAO,GAAY,WAAY,EAAkB,OACrD,IAAM,EAAQ,EACd,GAAI,EAAM,SAAW,SAEnB,OADI,OAAO,EAAM,QAAW,UAAY,EAAM,OAAO,KAAK,IAAM,GAAI,OAC7D,CACL,OAAQ,SACR,OAAQ,EAAM,OAAO,KAAK,EAC1B,GAAI,OAAO,EAAM,SAAY,UAAY,EAAM,QAAQ,KAAK,IAAM,GAAK,CAAE,QAAS,EAAM,QAAQ,KAAK,CAAE,EAAI,CAAC,CAC9G,EAEF,GAAI,EAAM,SAAW,QAEnB,OADI,OAAO,EAAM,IAAO,UAAY,EAAM,KAAO,GAAI,OAC9C,CAAE,OAAQ,QAAS,GAAI,EAAM,GAAI,GAAI,EAAM,QAAU,GAAO,CAAE,MAAO,EAAK,EAAI,CAAC,CAAG,CAG7F,CAQA,SAAS,EAAY,EAAwB,CAC3C,OAAO,aAAiB,EAAuB,EAAM,QAAU,gCACjE,CAGA,SAAgB,EAAuB,EAAmC,CAAC,EAAmB,CAG5F,IAAI,EAEJ,MAAO,CACL,UAAW,EACX,MAAM,EAAM,CACV,IAAM,EAAiB,EAAK,eAC5B,GAAI,IAAmB,IAAA,GACrB,MAAM,IAAI,EAAoB,8EAA8E,EAE9G,IAAM,EACJ,EAAQ,YACR,EAAyB,CACvB,IAAK,EAAkB,EACvB,gBACF,CAAC,EACG,EAAkB,CAAE,QAAS,EAAQ,QAAS,gBAAe,EAC7D,EAAS,IAAI,IACb,EAAgB,IAAI,IACpB,EAAO,IAAI,IAGX,GAAW,EAA4B,IAAyB,CACpE,IAAM,EAAW,EAAO,IAAI,EAAM,SAAS,EACrC,EAAqB,CACzB,UAAW,EAAS,EAAO,CAAK,EAChC,QAAS,GAAU,QACnB,MAAO,GAAU,KACnB,GAEG,GACD,IAAa,IAAA,IACb,GAAS,EAAS,UAAW,EAAK,SAAS,GAC3C,EAAS,UAAY,EAAK,SAC1B,EAAS,QAAU,EAAK,SAI1B,EAAO,IAAI,EAAM,UAAW,CAAI,EAChC,EAAK,QAAQ,EAAM,UAAW,EAAU,CAAI,CAAC,EAC/C,EAEM,GAAQ,EAA4B,EAA6B,IAAoC,CACzG,IAAM,EAAW,EAAO,IAAI,EAAM,SAAS,EAC3C,EAAO,IAAI,EAAM,UAAW,CAC1B,UAAW,GAAU,WAAa,EAAS,EAAO,CAAK,EACvD,UACA,OACF,CAAC,EACD,EAAQ,EAAO,EAAI,CACrB,EAGM,GAAoB,EAA4B,IAAiC,CACrF,EAAK,aAAa,QAAQ,EAA8B,EAAM,UAAW,CACvE,QAAS,EACT,gBACF,CAAC,CACH,EAEM,EAAM,MAAO,EAA4B,IAAgD,CAC7F,IAAM,EAAU,CAAE,IAAK,EAAM,IAAK,UAAW,EAAM,SAAU,EAC7D,GAAI,EAAQ,SAAW,SAAU,CAC/B,EAAK,EAAO,YAAY,EAAQ,OAAO,QAAS,IAAA,EAAS,EACzD,IAAM,EAAS,MAAM,EAAU,MAC7B,EACA,CACE,OAAQ,EAAQ,OAChB,GAAI,EAAQ,UAAY,IAAA,GAAY,CAAC,EAAI,CAAE,QAAS,EAAQ,OAAQ,CACtE,EAGA,CAAE,WAAa,GAAU,EAAK,EAAO,EAAO,IAAA,EAAS,CAAE,CACzD,EACA,EAAiB,EAAO,EAAO,cAAc,EAC7C,MACF,CACA,EAAK,EAAO,WAAW,EAAQ,GAAG,GAAI,IAAA,EAAS,EAC/C,IAAM,EAAS,MAAM,EAAU,MAAM,EAAS,EAAQ,GAAI,EAAQ,OAAS,EAAK,EAChF,EAAiB,EAAO,EAAO,cAAc,CAC/C,EAuDA,MApBA,IAAkB,EAAO,IAAY,CACnC,IAAM,EAAU,EAAa,CAAO,EAChC,IAAY,IAAA,KAGZ,EAAK,IAAI,EAAM,SAAS,IAC5B,EAAK,IAAI,EAAM,SAAS,EACxB,EAAS,EAAO,CAAO,CAAC,CACrB,SAAW,CACV,EAAK,EAAO,IAAA,GAAW,IAAA,EAAS,CAClC,CAAC,CAAC,CACD,MAAO,GAAmB,CACzB,EAAK,SAAS,+BAA+B,EAAM,UAAU,IAAI,EAAY,CAAK,EAAE,EAAE,EACtF,EAAK,EAAO,IAAA,GAAW,EAAY,CAAK,CAAC,CAC3C,CAAC,CAAC,CACD,YAAc,CACb,EAAK,OAAO,EAAM,SAAS,CAC7B,CAAC,GACL,EAEO,CApDL,WAAW,EAAO,CAChB,IAAM,EAAQ,EAAO,IAAI,EAAM,SAAS,EACxC,OAAO,IAAU,IAAA,GAAY,IAAA,GAAY,EAAU,CAAK,CAC1D,EACA,aAAa,EAAO,CAClB,EAAQ,EAAO,EAAK,EACpB,IAAM,EAAc,EAAK,aAAa,UAAU,EAA8B,EAAM,UAAY,GAAY,CAC1G,GAAI,CAAC,EAAyB,CAAO,EAAG,OACxC,IAAI,EAAiB,GACrB,GAAI,CACF,EACE,EAAa,EAAM,IAAK,EAAQ,OAAO,IAAM,EAAa,EAAQ,eAAgB,EAAQ,OAAO,CACrG,MAAQ,CACN,EAAiB,EACnB,CACI,GAAgB,EAAQ,EAAO,EAAK,CAC1C,CAAC,EACD,EAAc,IAAI,EAAM,UAAW,CAAW,CAChD,EACA,eAAe,EAAW,CACxB,EAAc,IAAI,CAAS,CAAC,GAAG,EAC/B,EAAc,OAAO,CAAS,EAC9B,EAAO,OAAO,CAAS,EACvB,EAAK,OAAO,CAAS,CACvB,EACA,OAAQ,CACN,IAAK,IAAM,KAAe,EAAc,OAAO,EAAG,EAAY,EAC9D,EAAc,MAAM,EACpB,EAAO,MAAM,EACb,EAAK,MAAM,CACb,CAsBK,CACT,EACA,QAAQ,EAAO,EAAS,CACtB,IAAiB,EAAO,CAAO,CACjC,CACF,CACF"}
|
|
@@ -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,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});e.Type.Union([r,i,a,o,s,c,l,u]);function d(e){return Object.values(t).filter(t=>n[t].includes(e)).join(`, `)}const f=e.Type.Object({action:e.Type.String({enum:Object.values(t),description:`The operation to run. Every other field is accepted only by the actions its description names.`}),branch:e.Type.Optional(e.Type.String({minLength:1,description:`New branch to create. Actions: ${d(`branch`)}.`})),baseRef:e.Type.Optional(e.Type.String({minLength:1,description:`Base ref, defaulting to the current branch. Actions: ${d(`baseRef`)}.`})),task:e.Type.Optional(e.Type.String({minLength:1,description:`First message for the new session. Actions: ${d(`task`)}.`})),name:e.Type.Optional(e.Type.String({minLength:1,description:`Rail label for the worktree. Actions: ${d(`name`)}.`})),id:e.Type.Optional(e.Type.String({minLength:1,description:`Worktree id. Actions: ${d(`id`)}.`})),force:e.Type.Optional(e.Type.Boolean({description:`Close even when the tree is dirty. Actions: ${d(`force`)}.`})),message:e.Type.Optional(e.Type.String({minLength:1,description:`Merge commit message, or the text to send. Actions: ${d(`message`)}.`})),dryRun:e.Type.Optional(e.Type.Boolean({description:`Report the plan without destroying anything. Actions: ${d(`dryRun`)}.`}))},{additionalProperties:!1});exports.RunWorktreeToolSchema=f,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\n/** The actions that accept `field`, so the declared docs cannot drift from the validator. */\nfunction acceptingActions(field: string): string {\n return Object.values(WORKTREE_ACTIONS)\n .filter((action) => WORKTREE_ACTION_FIELDS[action].includes(field))\n .join(', ');\n}\n\n/**\n * The schema declared to the model.\n *\n * A flat object rather than `RunWorktreeParams` itself. A top-level union is\n * `{anyOf:[...]}` with no `properties`, and Pi's Anthropic Messages adapter\n * rebuilds tool input as `{type:'object', properties: schema.properties ?? {},\n * required: schema.required ?? []}`, so the union arrived at the model as an\n * empty object while the host went on validating calls against it. Nothing here\n * relaxes what is accepted: `validateParams` still rejects an unknown action, a\n * field the action does not take, and a missing required one.\n */\nexport const RunWorktreeToolSchema = Type.Object(\n {\n action: Type.String({\n enum: Object.values(WORKTREE_ACTIONS),\n description: 'The operation to run. Every other field is accepted only by the actions its description names.',\n }),\n branch: Type.Optional(\n Type.String({ minLength: 1, description: `New branch to create. Actions: ${acceptingActions('branch')}.` }),\n ),\n baseRef: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Base ref, defaulting to the current branch. Actions: ${acceptingActions('baseRef')}.`,\n }),\n ),\n task: Type.Optional(\n Type.String({\n minLength: 1,\n description: `First message for the new session. Actions: ${acceptingActions('task')}.`,\n }),\n ),\n name: Type.Optional(\n Type.String({ minLength: 1, description: `Rail label for the worktree. Actions: ${acceptingActions('name')}.` }),\n ),\n id: Type.Optional(Type.String({ minLength: 1, description: `Worktree id. Actions: ${acceptingActions('id')}.` })),\n force: Type.Optional(\n Type.Boolean({ description: `Close even when the tree is dirty. Actions: ${acceptingActions('force')}.` }),\n ),\n message: Type.Optional(\n Type.String({\n minLength: 1,\n description: `Merge commit message, or the text to send. Actions: ${acceptingActions('message')}.`,\n }),\n ),\n dryRun: Type.Optional(\n Type.Boolean({\n description: `Report the plan without destroying anything. Actions: ${acceptingActions('dryRun')}.`,\n }),\n ),\n },\n { additionalProperties: false },\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,EAEiCA,EAAAA,KAAK,MAAM,CAC1C,EACA,EACA,EACA,EACA,EACA,EACA,EACA,CACF,CAAC,EAGD,SAAS,EAAiB,EAAuB,CAC/C,OAAO,OAAO,OAAO,CAAgB,CAAC,CACnC,OAAQ,GAAW,EAAuB,EAAO,CAAC,SAAS,CAAK,CAAC,CAAC,CAClE,KAAK,IAAI,CACd,CAaA,MAAa,EAAwBA,EAAAA,KAAK,OACxC,CACE,OAAQA,EAAAA,KAAK,OAAO,CAClB,KAAM,OAAO,OAAO,CAAgB,EACpC,YAAa,gGACf,CAAC,EACD,OAAQA,EAAAA,KAAK,SACXA,EAAAA,KAAK,OAAO,CAAE,UAAW,EAAG,YAAa,kCAAkC,EAAiB,QAAQ,EAAE,EAAG,CAAC,CAC5G,EACA,QAASA,EAAAA,KAAK,SACZA,EAAAA,KAAK,OAAO,CACV,UAAW,EACX,YAAa,wDAAwD,EAAiB,SAAS,EAAE,EACnG,CAAC,CACH,EACA,KAAMA,EAAAA,KAAK,SACTA,EAAAA,KAAK,OAAO,CACV,UAAW,EACX,YAAa,+CAA+C,EAAiB,MAAM,EAAE,EACvF,CAAC,CACH,EACA,KAAMA,EAAAA,KAAK,SACTA,EAAAA,KAAK,OAAO,CAAE,UAAW,EAAG,YAAa,yCAAyC,EAAiB,MAAM,EAAE,EAAG,CAAC,CACjH,EACA,GAAIA,EAAAA,KAAK,SAASA,EAAAA,KAAK,OAAO,CAAE,UAAW,EAAG,YAAa,yBAAyB,EAAiB,IAAI,EAAE,EAAG,CAAC,CAAC,EAChH,MAAOA,EAAAA,KAAK,SACVA,EAAAA,KAAK,QAAQ,CAAE,YAAa,+CAA+C,EAAiB,OAAO,EAAE,EAAG,CAAC,CAC3G,EACA,QAASA,EAAAA,KAAK,SACZA,EAAAA,KAAK,OAAO,CACV,UAAW,EACX,YAAa,uDAAuD,EAAiB,SAAS,EAAE,EAClG,CAAC,CACH,EACA,OAAQA,EAAAA,KAAK,SACXA,EAAAA,KAAK,QAAQ,CACX,YAAa,yDAAyD,EAAiB,QAAQ,EAAE,EACnG,CAAC,CACH,CACF,EACA,CAAE,qBAAsB,EAAM,CAChC"}
|