@midhunxavier/code-flow 0.0.0-stage → 0.1.0-preview.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -2
  3. package/bin/codeflow.mjs +8 -0
  4. package/bin/launcher.mjs +127 -0
  5. package/dist/remote-host.json +1 -0
  6. package/licenses/inter.txt +92 -0
  7. package/licenses/preact.txt +21 -0
  8. package/licenses/signals-core.txt +21 -0
  9. package/licenses/signals.txt +21 -0
  10. package/licenses/typescript-notices.txt +193 -0
  11. package/licenses/typescript.txt +55 -0
  12. package/licenses/uqr.txt +22 -0
  13. package/licenses/xterm-fit.txt +19 -0
  14. package/licenses/xterm.txt +21 -0
  15. package/package.json +34 -4
  16. package/public/assets/changes-62ZIEQSN.js +1 -0
  17. package/public/assets/chunk-2PZVOKID.js +1 -0
  18. package/public/assets/chunk-4D5IENEB.js +1 -0
  19. package/public/assets/chunk-5SARP5MU.js +1 -0
  20. package/public/assets/chunk-63YLZ3PR.js +1 -0
  21. package/public/assets/chunk-7FUHKF2M.js +1 -0
  22. package/public/assets/chunk-APQEVJ2K.js +1 -0
  23. package/public/assets/chunk-CGOZQMEZ.js +2 -0
  24. package/public/assets/chunk-J4VYS3KV.js +2 -0
  25. package/public/assets/chunk-L7TUCIYF.js +1 -0
  26. package/public/assets/chunk-SIHDWM2Y.js +154 -0
  27. package/public/assets/chunk-TEJVYIKC.js +1 -0
  28. package/public/assets/code-browser-VB2HGZSG.js +4 -0
  29. package/public/assets/filtered-tasks-ES5CP4KV.js +1 -0
  30. package/public/assets/interactive-browser-7F5ZXRUV.js +7 -0
  31. package/public/assets/join-project-6RTFHNCA.js +1 -0
  32. package/public/assets/main-65EW73SB.js +1 -0
  33. package/public/assets/project-invitations-view-GMPWGWYM.js +1 -0
  34. package/public/assets/settings-UB5Q4AQM.js +9 -0
  35. package/public/assets/styles-18792BB4.css +32 -0
  36. package/public/assets/team-server-wizard-2GLDWS6D.js +8 -0
  37. package/public/assets/terminal-IWAIM4DE.js +62 -0
  38. package/public/assets.json +1 -0
  39. package/public/bundle-meta.json +1 -0
  40. package/public/docs/.nojekyll +0 -0
  41. package/public/docs/accessibility.html +19 -0
  42. package/public/docs/acp-agents.html +117 -0
  43. package/public/docs/agent-containers.html +79 -0
  44. package/public/docs/api.html +1130 -0
  45. package/public/docs/app.js +342 -0
  46. package/public/docs/application-improvements.html +275 -0
  47. package/public/docs/architecture-explorer.html +19 -0
  48. package/public/docs/architecture.html +149 -0
  49. package/public/docs/auto-team.html +148 -0
  50. package/public/docs/automations.html +109 -0
  51. package/public/docs/checkpoint-review.html +37 -0
  52. package/public/docs/code-hosts.html +35 -0
  53. package/public/docs/code-intelligence.html +35 -0
  54. package/public/docs/configuration.html +346 -0
  55. package/public/docs/context-inspection.html +23 -0
  56. package/public/docs/coordinated-changes.html +28 -0
  57. package/public/docs/deferred-runs.html +25 -0
  58. package/public/docs/dependency-discovery.html +19 -0
  59. package/public/docs/documentation.html +84 -0
  60. package/public/docs/dynamic-teams-evaluation.html +174 -0
  61. package/public/docs/dynamic-teams-implementation-plan.html +882 -0
  62. package/public/docs/dynamic-teams-implementation-review-1.html +141 -0
  63. package/public/docs/dynamic-teams-plan-review-0.html +204 -0
  64. package/public/docs/extensions.html +42 -0
  65. package/public/docs/external-sources.html +96 -0
  66. package/public/docs/filesystem-policy.html +26 -0
  67. package/public/docs/filtered-tasks.html +44 -0
  68. package/public/docs/font-license.txt +92 -0
  69. package/public/docs/getting-started.html +143 -0
  70. package/public/docs/github-review-threads.html +26 -0
  71. package/public/docs/github.html +157 -0
  72. package/public/docs/help.html +69 -0
  73. package/public/docs/index.html +88 -0
  74. package/public/docs/installation.html +80 -0
  75. package/public/docs/launch-profiles.html +48 -0
  76. package/public/docs/maintenance.html +60 -0
  77. package/public/docs/memory-claims.html +31 -0
  78. package/public/docs/memory-storage.html +58 -0
  79. package/public/docs/notifications.html +39 -0
  80. package/public/docs/patterns.html +195 -0
  81. package/public/docs/performance-results.html +210 -0
  82. package/public/docs/performance.html +166 -0
  83. package/public/docs/project-conventions.html +22 -0
  84. package/public/docs/project-first-navigation-plan.html +587 -0
  85. package/public/docs/project-teams-implementation-plan.html +772 -0
  86. package/public/docs/project-teams.html +129 -0
  87. package/public/docs/provider-compatibility.html +20 -0
  88. package/public/docs/releasing.html +65 -0
  89. package/public/docs/remote-workers.html +64 -0
  90. package/public/docs/review-inbox.html +26 -0
  91. package/public/docs/run-storage.html +23 -0
  92. package/public/docs/runs.html +141 -0
  93. package/public/docs/search.json +1 -0
  94. package/public/docs/security.html +133 -0
  95. package/public/docs/shared-projects.html +31 -0
  96. package/public/docs/ssh-projects.html +60 -0
  97. package/public/docs/style.css +768 -0
  98. package/public/docs/task-reruns.html +30 -0
  99. package/public/docs/team-collaboration.html +412 -0
  100. package/public/docs/verification.html +22 -0
  101. package/public/docs/vscode.html +53 -0
  102. package/public/docs/worker-permission-verification.html +131 -0
  103. package/public/index.html +17 -0
  104. package/scripts/check-node.mjs +7 -0
  105. package/scripts/codeflow.mjs +55 -0
  106. package/scripts/computer-use.swift +64 -0
  107. package/scripts/pty.py +273 -0
  108. package/src/acp-connections.js +110 -0
  109. package/src/adapters/acp-presets.js +37 -0
  110. package/src/adapters/acp-types.js +0 -0
  111. package/src/adapters/acp.js +328 -0
  112. package/src/adapters/agent-tools.js +28 -0
  113. package/src/adapters/agy-auth.js +67 -0
  114. package/src/adapters/agy-isolation.js +242 -0
  115. package/src/adapters/agy-tools.js +45 -0
  116. package/src/adapters/agy.js +326 -0
  117. package/src/adapters/claude-stream.js +58 -0
  118. package/src/adapters/claude.js +282 -0
  119. package/src/adapters/codex-app-server.js +555 -0
  120. package/src/adapters/codex.js +311 -0
  121. package/src/adapters/errors.js +57 -0
  122. package/src/adapters/index.js +91 -0
  123. package/src/adapters/managed-permissions.js +37 -0
  124. package/src/adapters/model-discovery.js +100 -0
  125. package/src/adapters/process.js +433 -0
  126. package/src/adapters/team-tools.js +103 -0
  127. package/src/adapters/types.js +0 -0
  128. package/src/agent-browser.js +688 -0
  129. package/src/agent-computer.js +88 -0
  130. package/src/agent-container.js +155 -0
  131. package/src/agent-team-definitions.js +131 -0
  132. package/src/agent-tool-client.mjs +79 -0
  133. package/src/agent-tools.js +296 -0
  134. package/src/approvals.js +134 -0
  135. package/src/architecture.js +456 -0
  136. package/src/assets.js +44 -0
  137. package/src/automation.js +901 -0
  138. package/src/browser-files.js +293 -0
  139. package/src/browser-ownership.js +150 -0
  140. package/src/certificate-renewal.js +75 -0
  141. package/src/chat-family.js +25 -0
  142. package/src/chat-handoff.js +87 -0
  143. package/src/checkpoint-review.js +72 -0
  144. package/src/checks.js +303 -0
  145. package/src/code-host-git.js +102 -0
  146. package/src/code-hosts-api.js +99 -0
  147. package/src/code-hosts.js +482 -0
  148. package/src/code-intelligence-worker.mjs +452 -0
  149. package/src/code-intelligence.js +141 -0
  150. package/src/collab/api.js +365 -0
  151. package/src/collab/checkpoints.js +198 -0
  152. package/src/collab/connections.js +139 -0
  153. package/src/collab/host-execution.js +347 -0
  154. package/src/collab/hub-client.js +210 -0
  155. package/src/collab/link-api.js +229 -0
  156. package/src/collab/link.js +595 -0
  157. package/src/collab/model.js +496 -0
  158. package/src/collab/runner.js +1014 -0
  159. package/src/collab/store.js +1452 -0
  160. package/src/collab/terminals.js +361 -0
  161. package/src/collaboration-reviews.js +116 -0
  162. package/src/config.js +48 -0
  163. package/src/context-budget.js +14 -0
  164. package/src/context-inspection.js +204 -0
  165. package/src/context.js +154 -0
  166. package/src/conventions.js +283 -0
  167. package/src/coordinated-api.js +247 -0
  168. package/src/deferred-launch.js +82 -0
  169. package/src/deferred-runs.js +515 -0
  170. package/src/dependency-health.js +35 -0
  171. package/src/diff.js +43 -0
  172. package/src/docs-help.js +316 -0
  173. package/src/doctor.js +232 -0
  174. package/src/documentation-changes.js +20 -0
  175. package/src/engine.js +5258 -0
  176. package/src/env.js +44 -0
  177. package/src/execution-budget.js +8 -0
  178. package/src/experience.js +50 -0
  179. package/src/extensions.js +144 -0
  180. package/src/filesystem-access.js +107 -0
  181. package/src/filesystem-policy.js +238 -0
  182. package/src/filtered-task-limits.js +93 -0
  183. package/src/filtered-tasks-api.js +53 -0
  184. package/src/filtered-tasks.js +576 -0
  185. package/src/frame-policy.js +66 -0
  186. package/src/fs.js +57 -0
  187. package/src/git.js +626 -0
  188. package/src/github-review-threads.js +181 -0
  189. package/src/github.js +538 -0
  190. package/src/http.js +69 -0
  191. package/src/improve-settings.js +38 -0
  192. package/src/improve.js +187 -0
  193. package/src/integrations.js +373 -0
  194. package/src/integrity.js +259 -0
  195. package/src/journey-api.js +77 -0
  196. package/src/journey-replay.js +65 -0
  197. package/src/journey-store.js +97 -0
  198. package/src/journeys.js +60 -0
  199. package/src/json.js +81 -0
  200. package/src/launch-profiles.js +292 -0
  201. package/src/learnings.js +80 -0
  202. package/src/local-app-url.js +19 -0
  203. package/src/log.js +39 -0
  204. package/src/maintenance.js +335 -0
  205. package/src/memory-analysis.js +182 -0
  206. package/src/memory-claims.js +153 -0
  207. package/src/memory-sqlite.js +236 -0
  208. package/src/memory.js +552 -0
  209. package/src/merge-validation.js +58 -0
  210. package/src/model-catalog.js +239 -0
  211. package/src/model-research.js +91 -0
  212. package/src/notes.js +176 -0
  213. package/src/notifications.js +413 -0
  214. package/src/patterns/auto-team-model.js +230 -0
  215. package/src/patterns/auto-team.js +816 -0
  216. package/src/patterns/council.js +199 -0
  217. package/src/patterns/debate.js +188 -0
  218. package/src/patterns/findings.js +141 -0
  219. package/src/patterns/index.js +21 -0
  220. package/src/patterns/loop.js +158 -0
  221. package/src/patterns/pipeline.js +125 -0
  222. package/src/patterns/prompts.js +181 -0
  223. package/src/patterns/race.js +147 -0
  224. package/src/patterns/schemas.js +40 -0
  225. package/src/patterns/solo.js +46 -0
  226. package/src/patterns/supervisor.js +235 -0
  227. package/src/patterns/task-draft.js +29 -0
  228. package/src/patterns/task-review.js +45 -0
  229. package/src/patterns/tdd.js +231 -0
  230. package/src/patterns/team-strategies.js +67 -0
  231. package/src/performance.js +43 -0
  232. package/src/persistence-status.js +35 -0
  233. package/src/phone-sessions.js +96 -0
  234. package/src/preview-overlay.js +392 -0
  235. package/src/preview.js +230 -0
  236. package/src/privacy.js +23 -0
  237. package/src/project-report.js +22 -0
  238. package/src/project-team-budget.js +22 -0
  239. package/src/project-team-model.js +225 -0
  240. package/src/project-team-policy.js +42 -0
  241. package/src/project-team-store.js +234 -0
  242. package/src/project-team-usage.js +24 -0
  243. package/src/project-teams-api.js +43 -0
  244. package/src/project-teams.js +644 -0
  245. package/src/projects.js +290 -0
  246. package/src/provider-eligibility.js +9 -0
  247. package/src/readiness.js +98 -0
  248. package/src/remote-tls.js +66 -0
  249. package/src/remote-workers/bundles.js +198 -0
  250. package/src/remote-workers/client.js +332 -0
  251. package/src/remote-workers/durability.js +37 -0
  252. package/src/remote-workers/protocol.js +68 -0
  253. package/src/remote-workers/stdio.js +138 -0
  254. package/src/remote-workers/worker.js +304 -0
  255. package/src/remote.js +204 -0
  256. package/src/repo-config.js +201 -0
  257. package/src/repo-coordination.js +725 -0
  258. package/src/repo-tree.js +106 -0
  259. package/src/repository-identity.js +13 -0
  260. package/src/retention-policy.js +466 -0
  261. package/src/review-inbox.js +38 -0
  262. package/src/routing.js +49 -0
  263. package/src/run-analysis.js +111 -0
  264. package/src/run-cold-store.js +231 -0
  265. package/src/run-environment.js +15 -0
  266. package/src/run-history.js +91 -0
  267. package/src/run-log.js +160 -0
  268. package/src/run-permissions.js +111 -0
  269. package/src/run-projection.js +77 -0
  270. package/src/run-recovery.js +53 -0
  271. package/src/run-status.js +56 -0
  272. package/src/serve.js +138 -0
  273. package/src/server.js +2871 -0
  274. package/src/shared-access.js +103 -0
  275. package/src/shared-accounts.js +381 -0
  276. package/src/shared-api.js +239 -0
  277. package/src/shell.js +346 -0
  278. package/src/ship.js +344 -0
  279. package/src/slots.js +74 -0
  280. package/src/snapshot.js +388 -0
  281. package/src/source-context.js +17 -0
  282. package/src/sse-writer.js +70 -0
  283. package/src/ssh-projects/bootstrap.mjs +95 -0
  284. package/src/ssh-projects/config.js +45 -0
  285. package/src/ssh-projects/gateway.js +143 -0
  286. package/src/ssh-projects/manager.js +320 -0
  287. package/src/ssh-projects/team-autostart.mjs +93 -0
  288. package/src/ssh-projects/team-remove.mjs +69 -0
  289. package/src/ssh-projects/team-status.mjs +39 -0
  290. package/src/ssh-projects/transport.js +133 -0
  291. package/src/stats.js +139 -0
  292. package/src/store.js +544 -0
  293. package/src/stream.js +91 -0
  294. package/src/sweeps.js +241 -0
  295. package/src/tailscale.js +101 -0
  296. package/src/task-draft.js +23 -0
  297. package/src/task-team.js +164 -0
  298. package/src/team-evaluation.js +243 -0
  299. package/src/team-mailbox.js +160 -0
  300. package/src/team-memory.js +84 -0
  301. package/src/team-rerun-graph.js +15 -0
  302. package/src/team-reruns.js +130 -0
  303. package/src/team-scheduler.js +121 -0
  304. package/src/team-steering.js +21 -0
  305. package/src/team-template-store.js +98 -0
  306. package/src/team-templates.js +117 -0
  307. package/src/team-tool-client.mjs +79 -0
  308. package/src/team-tools.js +235 -0
  309. package/src/teams.js +0 -0
  310. package/src/templates.js +62 -0
  311. package/src/transcript.js +134 -0
  312. package/src/verification-integrity.js +27 -0
  313. package/src/verification.js +183 -0
  314. package/src/watch.js +195 -0
  315. package/src/work-queue.js +47 -0
  316. package/src/workflow-control.js +83 -0
  317. package/src/workspace-api.js +207 -0
  318. package/src/workspace-changes.js +61 -0
  319. package/src/workspace.js +146 -0
@@ -0,0 +1,201 @@
1
+ import { closeSync, constants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readSync, realpathSync, renameSync, unlinkSync, writeSync } from "node:fs";
2
+ import { randomBytes } from "node:crypto";
3
+ import { lstat, readdir, readFile, realpath, writeFile } from "node:fs/promises";
4
+ import { basename, dirname, join, resolve, sep } from "node:path";
5
+ import { COPIED_FILES, git, gitWithInput, worktreeGit } from "./git.js";
6
+ const CONFIG_PATH = ".codeflow/config.json";
7
+ async function readRepoConfig(repo) {
8
+ const file = join(repo, CONFIG_PATH);
9
+ if (!existsSync(file)) return { config: {}, found: false };
10
+ try {
11
+ const raw = JSON.parse(await readFile(file, "utf8"));
12
+ const config = {};
13
+ const str = (v) => typeof v === "string" && v.trim() ? v.trim() : void 0;
14
+ config.check = str(raw.check);
15
+ config.setup = str(raw.setup);
16
+ if (Array.isArray(raw.copy)) config.copy = raw.copy.filter((p) => typeof p === "string" && !!p.trim());
17
+ if (raw.run && str(raw.run.command)) config.run = { command: str(raw.run.command), port: Number(raw.run.port) || void 0 };
18
+ if (raw.models && typeof raw.models === "object") config.models = raw.models;
19
+ if (raw.limits && typeof raw.limits === "object") {
20
+ const positive = (v) => Number.isFinite(Number(v)) && Number(v) > 0 ? Number(v) : void 0;
21
+ const steps = positive(raw.limits.maxSteps);
22
+ config.limits = { maxMinutes: positive(raw.limits.maxMinutes), maxSteps: steps === void 0 ? void 0 : Math.max(1, Math.round(steps)) };
23
+ }
24
+ if (["safe", "standard", "trusted"].includes(raw.trust)) config.trust = raw.trust;
25
+ if (typeof raw.image === "string" && /^[\w./:@-]{1,200}$/.test(raw.image.trim())) config.image = raw.image.trim();
26
+ if (typeof raw.learn === "boolean") config.learn = raw.learn;
27
+ if (typeof raw.prove === "boolean") config.prove = raw.prove;
28
+ return { config, found: true };
29
+ } catch (err) {
30
+ return { config: {}, found: true, error: `${CONFIG_PATH}: ${err.message}` };
31
+ }
32
+ }
33
+ async function copyIntoWorktree(repo, worktree, patterns) {
34
+ const copied = [];
35
+ const refused = [];
36
+ const root = await realpath(repo);
37
+ const destination = resolve(worktree);
38
+ const destinationRoot = await realpath(worktree);
39
+ const candidates = /* @__PURE__ */ new Set();
40
+ for (const raw of patterns) {
41
+ const pattern = raw.replace(/\\/g, "/").replace(/^\.\//, "");
42
+ if (!pattern || pattern.startsWith("/") || pattern.includes("\0") || pattern.split("/").some((part) => !part || part === ".." || part === ".")) continue;
43
+ for (const rel of await expand(repo, pattern)) {
44
+ const from = join(repo, rel);
45
+ const info = await lstat(from).catch(() => null);
46
+ if (!info) continue;
47
+ if (info.isSymbolicLink()) {
48
+ refused.push({ path: rel, why: "it's a symbolic link" });
49
+ continue;
50
+ }
51
+ if (!info.isFile()) continue;
52
+ const real = await realpath(from).catch(() => "");
53
+ if (!real.startsWith(root + sep)) {
54
+ refused.push({ path: rel, why: "it's outside the repository" });
55
+ continue;
56
+ }
57
+ candidates.add(rel);
58
+ }
59
+ }
60
+ const ignored = new Set(
61
+ candidates.size ? (await gitWithInput(["check-ignore", "--stdin", "-z"], repo, [...candidates].join("\0") + "\0")).stdout.split("\0").filter(Boolean) : []
62
+ );
63
+ for (const rel of candidates) {
64
+ if (!ignored.has(rel)) {
65
+ refused.push({ path: rel, why: "git doesn't ignore it, so it would be committed with the agents' work" });
66
+ continue;
67
+ }
68
+ const result = copyWithoutLinks(root, destination, destinationRoot, rel);
69
+ if (result === "copied") copied.push(rel);
70
+ else if (result !== "exists") refused.push({ path: rel, why: result });
71
+ }
72
+ await recordCopied(repo, worktree, copied);
73
+ return { copied, refused };
74
+ }
75
+ function copyWithoutLinks(sourceRoot, destination, destinationRoot, rel, opts = {}) {
76
+ let from;
77
+ let to;
78
+ let created;
79
+ const target = join(destinationRoot, rel);
80
+ let output = target;
81
+ try {
82
+ if (lstatSync(destination).isSymbolicLink() || !lstatSync(destination).isDirectory() || realpathSync(destination) !== destinationRoot) return "the worktree root is a symbolic link or has changed";
83
+ verifyParents(sourceRoot, dirname(opts.sourcePath ?? rel), false);
84
+ verifyParents(destinationRoot, dirname(rel), true);
85
+ const source = join(sourceRoot, opts.sourcePath ?? rel);
86
+ const sourceInfo = lstatSync(source);
87
+ if (sourceInfo.isSymbolicLink()) return "it's a symbolic link";
88
+ if (!sourceInfo.isFile() || !realpathSync(source).startsWith(sourceRoot + sep)) return "it's outside the repository or isn't a regular file";
89
+ from = openSync(source, constants.O_RDONLY | constants.O_NOFOLLOW);
90
+ if (!sameFile(sourceInfo, fstatSync(from))) return "the source file changed while preparing the copy";
91
+ const existing = statIfPresent(target);
92
+ if (existing?.isSymbolicLink()) return "the destination is a symbolic link";
93
+ if (existing && !existing.isFile()) return "the destination isn't a regular file";
94
+ if (existing && !opts.overwrite) return "exists";
95
+ if (opts.overwrite) output = `${target}.codeflow-copy-${randomBytes(10).toString("hex")}`;
96
+ to = openSync(output, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 384);
97
+ created = fstatSync(to);
98
+ verifyParents(destinationRoot, dirname(rel), false);
99
+ if (!sameFile(created, lstatSync(output))) throw new Error("the destination changed while preparing the copy");
100
+ const buffer = Buffer.allocUnsafe(64 * 1024);
101
+ let bytes;
102
+ while (bytes = readSync(from, buffer, 0, buffer.length, null)) {
103
+ let written = 0;
104
+ while (written < bytes) written += writeSync(to, buffer, written, bytes - written);
105
+ }
106
+ if (output !== target) {
107
+ closeSync(to);
108
+ to = void 0;
109
+ verifyParents(destinationRoot, dirname(rel), false);
110
+ if (statIfPresent(target)?.isSymbolicLink()) throw new Error("the destination is a symbolic link");
111
+ renameSync(output, target);
112
+ }
113
+ return "copied";
114
+ } catch (error) {
115
+ if (!created && error.code === "EEXIST") return "exists";
116
+ if (created && sameFile(created, statIfPresent(output))) {
117
+ try {
118
+ unlinkSync(output);
119
+ } catch {
120
+ }
121
+ }
122
+ return error.message;
123
+ } finally {
124
+ if (from !== void 0) closeSync(from);
125
+ if (to !== void 0) closeSync(to);
126
+ }
127
+ }
128
+ function verifyParents(root, relative, create) {
129
+ let path = root;
130
+ const expectedRoot = lstatSync(root);
131
+ if (!expectedRoot.isDirectory() || expectedRoot.isSymbolicLink()) throw new Error("the copy root is not a regular directory");
132
+ for (const part of relative === "." ? [] : relative.split(sep)) {
133
+ path = join(path, part);
134
+ if (create) {
135
+ try {
136
+ mkdirSync(path, { mode: 448 });
137
+ } catch (error) {
138
+ if (error.code !== "EEXIST") throw error;
139
+ }
140
+ }
141
+ const info = lstatSync(path);
142
+ if (info.isSymbolicLink()) throw new Error(`a parent directory is a symbolic link at \`${path.slice(root.length + 1).split(sep).join("/")}\``);
143
+ if (!info.isDirectory() || realpathSync(path) !== path) throw new Error("a parent directory is outside the copy root or isn't a directory");
144
+ }
145
+ if (!sameFile(expectedRoot, lstatSync(root))) throw new Error("the copy root changed while preparing the copy");
146
+ }
147
+ function statIfPresent(path) {
148
+ try {
149
+ return lstatSync(path);
150
+ } catch (error) {
151
+ if (error.code !== "ENOENT") throw error;
152
+ }
153
+ }
154
+ const sameFile = (a, b) => !!b && a.dev === b.dev && a.ino === b.ino;
155
+ async function recordCopied(repo, worktree, copied) {
156
+ if (!copied.length) return;
157
+ const at = await worktreeGit(repo, worktree).catch(() => void 0);
158
+ if (!at) return;
159
+ const res = await git(["rev-parse", "--git-path", COPIED_FILES], at);
160
+ if (res.code !== 0 || !res.stdout.trim()) return;
161
+ const file = resolve(worktree, res.stdout.trim());
162
+ const known = (await readFile(file, "utf8").catch(() => "")).split("\0").filter(Boolean);
163
+ await writeFile(file, [.../* @__PURE__ */ new Set([...known, ...copied])].map((p) => `${p}\0`).join(""));
164
+ }
165
+ async function copyFileInside(root, rel, from, opts = {}) {
166
+ const parts = rel.split(/[\\/]+/).filter((p) => p && p !== ".");
167
+ if (!parts.length || parts.includes("..") || /^[\\/]|^[a-z]:/i.test(rel)) return { copied: false, why: `\`${rel}\` isn't a path inside the worktree` };
168
+ try {
169
+ const [realRoot, sourceRoot] = await Promise.all([realpath(root), realpath(dirname(from))]);
170
+ const result = copyWithoutLinks(sourceRoot, resolve(root), realRoot, parts.join("/"), { sourcePath: basename(from), overwrite: opts.overwrite !== false });
171
+ return result === "copied" ? { copied: true } : { copied: false, ...result === "exists" ? {} : { why: result } };
172
+ } catch (error) {
173
+ return { copied: false, why: error.message };
174
+ }
175
+ }
176
+ async function expand(repo, pattern) {
177
+ if (!pattern.includes("*")) return [pattern];
178
+ const parts = pattern.split("/");
179
+ let current = [""];
180
+ for (const part of parts) {
181
+ const next = [];
182
+ for (const base of current) {
183
+ if (!part.includes("*")) {
184
+ next.push(base ? `${base}/${part}` : part);
185
+ continue;
186
+ }
187
+ const re = new RegExp(`^${part.split("*").map(escape).join("[^/]*")}$`);
188
+ const entries = await readdir(join(repo, base)).catch(() => []);
189
+ for (const e of entries) if (re.test(e)) next.push(base ? `${base}/${e}` : e);
190
+ }
191
+ current = next;
192
+ }
193
+ return current;
194
+ }
195
+ const escape = (s) => s.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
196
+ export {
197
+ CONFIG_PATH,
198
+ copyFileInside,
199
+ copyIntoWorktree,
200
+ readRepoConfig
201
+ };