symbio 0.3.0-beta.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
- // Worker workspaces. In a git project each worker gets its own worktree on its
2
- // own branch (isolated copy of the committed files); without git, workers share
3
- // the project folder and rely on shared-asset grants alone.
1
+ // Worker workspaces. In a git project a worker gets its own worktree on its own
2
+ // branch (isolated copy of the committed files), unless it is set to share the
3
+ // project folder. Without git, workers always share it. Workers in the project
4
+ // folder rely on shared-asset grants alone.
4
5
  import { existsSync, promises as fs } from "node:fs";
5
6
  import path from "node:path";
6
7
  import { git } from "./git.js";
@@ -8,8 +9,13 @@ import { globalDir } from "./store.js";
8
9
  export async function isGitRepo(dir) {
9
10
  return existsSync(path.join(dir, ".git"));
10
11
  }
11
- export async function createWorkspace(project, agentName) {
12
- if (!(await isGitRepo(project.directory))) {
12
+ /** Whether an agent works in the project folder itself (always true for the coordinator). */
13
+ export function inProjectFolder(project, agent) {
14
+ const norm = (p) => (process.platform === "win32" ? path.resolve(p).toLowerCase() : path.resolve(p));
15
+ return norm(agent.directory) === norm(project.directory);
16
+ }
17
+ export async function createWorkspace(project, agentName, mode = "own") {
18
+ if (mode === "shared" || !(await isGitRepo(project.directory))) {
13
19
  return { directory: project.directory, branch: null, base: null };
14
20
  }
15
21
  const slug = agentName.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
@@ -114,6 +120,24 @@ export async function removeWorkspace(project, agent) {
114
120
  return;
115
121
  await git(project.directory, "worktree", "remove", "--force", agent.directory).catch(() => { });
116
122
  }
123
+ /**
124
+ * Takes a helper out of its own worktree so it can work in the project folder. Refuses while
125
+ * the worktree holds work that isn't in the project yet. The branch is deleted only when git
126
+ * agrees it is fully merged (`branch -d`); otherwise it stays, like any other kept branch.
127
+ */
128
+ export async function leaveWorkspace(project, agent) {
129
+ if (!agent.branch)
130
+ return;
131
+ const { committed, uncommitted } = await changedFiles(agent);
132
+ if (committed.length || uncommitted.length) {
133
+ const files = [...new Set([...committed, ...uncommitted])];
134
+ throw new Error(`${agent.name}'s own folder has work that isn't in the project yet (${files.slice(0, 8).join(", ")}${files.length > 8 ? ", …" : ""}). ` +
135
+ "Merge it (or discard it) first.");
136
+ }
137
+ await git(project.directory, "worktree", "remove", "--force", agent.directory).catch(() => { });
138
+ await git(project.directory, "worktree", "prune").catch(() => { });
139
+ await git(project.directory, "branch", "-d", agent.branch).catch(() => { });
140
+ }
117
141
  /**
118
142
  * Deletes helper folders left behind by projects that no longer exist (removing a project
119
143
  * deletes them, but on Windows an open file can make that fail halfway). Only Symbio's own