@henryqw/pi-herdr-clone 0.2.0 → 0.2.1

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.
@@ -18,7 +18,11 @@ import {
18
18
 
19
19
  type WorkspaceInfo = {
20
20
  workspace_id?: unknown;
21
- worktree?: { checkout_path?: unknown } | null;
21
+ worktree?: {
22
+ checkout_path?: unknown;
23
+ repo_root?: unknown;
24
+ is_linked_worktree?: unknown;
25
+ } | null;
22
26
  };
23
27
 
24
28
  const errorMessage = (error: unknown) => error instanceof Error ? error.message : String(error);
@@ -33,6 +37,8 @@ type SourceContext = {
33
37
  leafId: string;
34
38
  workspaceId: string;
35
39
  checkout: string | undefined;
40
+ repoRoot: string | undefined;
41
+ isLinkedWorktree: boolean;
36
42
  };
37
43
 
38
44
  async function resolveSource(
@@ -70,7 +76,14 @@ async function resolveSource(
70
76
  const checkout = workspace?.worktree == null
71
77
  ? undefined
72
78
  : requiredString(workspace.worktree.checkout_path, "Herdr workspace response checkout_path");
73
- return { sessionFile, leafId, workspaceId, checkout };
79
+ const repoRoot = typeof workspace?.worktree?.repo_root === "string" && workspace.worktree.repo_root.trim()
80
+ ? workspace.worktree.repo_root
81
+ : undefined;
82
+ const isLinkedWorktree = workspace?.worktree?.is_linked_worktree === true;
83
+ if (isLinkedWorktree && !repoRoot) {
84
+ throw new Error("Herdr workspace response is missing worktree.repo_root for a linked worktree.");
85
+ }
86
+ return { sessionFile, leafId, workspaceId, checkout, repoRoot, isLinkedWorktree };
74
87
  }
75
88
 
76
89
  async function createBranchedClone(
@@ -195,10 +208,23 @@ export default function herdrCloneExtension(pi: ExtensionAPI): void {
195
208
  await ctx.waitForIdle();
196
209
  const source = await resolveSource("clone-worktree", herdr, ctx);
197
210
 
211
+ // Herdr only creates worktrees from the repo parent workspace; running
212
+ // /clone-worktree inside a linked worktree must retarget the parent.
213
+ let targetWorkspaceId = source.workspaceId;
214
+ if (source.isLinkedWorktree) {
215
+ const listing = await herdr.json(["workspace", "list"], { cwd: ctx.cwd });
216
+ const result = (listing as { result?: { workspaces?: WorkspaceInfo[] } }).result;
217
+ const parent = (Array.isArray(result?.workspaces) ? result.workspaces : []).find((entry) =>
218
+ entry.worktree != null && !entry.worktree.is_linked_worktree &&
219
+ entry.worktree.checkout_path === source.repoRoot);
220
+ targetWorkspaceId = typeof parent?.workspace_id === "string"
221
+ ? parent.workspace_id
222
+ : requiredString(undefined, `Repo parent workspace for ${source.repoRoot} in herdr workspace list`);
223
+ }
198
224
  // Create the worktree before the clone so the session header can be
199
225
  // stamped with the fresh checkout cwd. A killed or incomplete create is
200
226
  // ambiguous: Herdr may have retained partial worktree state.
201
- const worktreeCreateArgs = ["worktree", "create", "--workspace", source.workspaceId, "--no-focus"] as const;
227
+ const worktreeCreateArgs = ["worktree", "create", "--workspace", targetWorkspaceId, "--no-focus"] as const;
202
228
  const createdWorktree = await herdr.exec(worktreeCreateArgs, { cwd: ctx.cwd });
203
229
  if (createdWorktree.code !== 0 && !createdWorktree.killed) {
204
230
  throw new Error(herdrCommandFailure(worktreeCreateArgs, createdWorktree));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-herdr-clone",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Clone the current Pi conversation path into a new Herdr tab.",
5
5
  "keywords": [
6
6
  "pi-package",