substrate-ai 0.9.0 → 0.10.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.
Files changed (35) hide show
  1. package/dist/adapter-registry-DXLMTmfD.js +0 -0
  2. package/dist/adapter-registry-neBZrkr3.js +4 -0
  3. package/dist/cli/index.js +5594 -5951
  4. package/dist/decisions-C0pz9Clx.js +0 -0
  5. package/dist/{decisions-BDLp3tJB.js → decisions-DQZW0h9X.js} +2 -1
  6. package/dist/dist-eNB_v7Iy.js +10205 -0
  7. package/dist/errors-BvyMlvCX.js +74 -0
  8. package/dist/experimenter-Dos3NsCg.js +3 -0
  9. package/dist/health-BvYILeQQ.js +6 -0
  10. package/dist/{health-C-VRJruD.js → health-CiDi90gC.js} +57 -1850
  11. package/dist/{helpers-CpMs8VZX.js → helpers-DTp3VJ2-.js} +31 -121
  12. package/dist/index.d.ts +672 -253
  13. package/dist/index.js +5 -3
  14. package/dist/{logger-D2fS2ccL.js → logger-KeHncl-f.js} +2 -42
  15. package/dist/routing-CcBOCuC9.js +0 -0
  16. package/dist/{routing-CD8bIci_.js → routing-HaYsjEIS.js} +2 -2
  17. package/dist/{run-ClxNDHbr.js → run-CAUhTR7Y.js} +594 -4249
  18. package/dist/run-DPZOQOvB.js +9 -0
  19. package/dist/{upgrade-B1S61VXJ.js → upgrade-DFGrqjGI.js} +3 -3
  20. package/dist/{upgrade-BK0HrKA6.js → upgrade-DYdYuuJK.js} +3 -3
  21. package/dist/version-manager-impl-BmOWu8ml.js +0 -0
  22. package/dist/version-manager-impl-CKv6I1S0.js +4 -0
  23. package/package.json +2 -2
  24. package/dist/adapter-registry-D2zdMwVu.js +0 -840
  25. package/dist/adapter-registry-WAyFydN5.js +0 -4
  26. package/dist/config-migrator-CtGelIsG.js +0 -250
  27. package/dist/decisions-DhAA2HG2.js +0 -397
  28. package/dist/experimenter-D_N_7ZF3.js +0 -503
  29. package/dist/git-utils-DxPx6erV.js +0 -365
  30. package/dist/health-DMbNP9bw.js +0 -5
  31. package/dist/operational-BdcdmDqS.js +0 -374
  32. package/dist/routing-BVrxrM6v.js +0 -832
  33. package/dist/run-MAQ3Wuju.js +0 -10
  34. package/dist/version-manager-impl-BIxOe7gZ.js +0 -372
  35. package/dist/version-manager-impl-RrWs-CI6.js +0 -4
@@ -1,365 +0,0 @@
1
- import { createLogger } from "./logger-D2fS2ccL.js";
2
- import { spawn } from "node:child_process";
3
- import * as path from "node:path";
4
- import { access, readdir } from "node:fs/promises";
5
-
6
- //#region src/modules/git-worktree/git-utils.ts
7
- const logger = createLogger("git-utils");
8
- const MIN_GIT_MAJOR = 2;
9
- const MIN_GIT_MINOR = 20;
10
- /**
11
- * Spawn a git subprocess with the given args.
12
- *
13
- * @param args - Arguments to pass to git (e.g., ['worktree', 'add', ...])
14
- * @param options - Optional spawn options (cwd, env)
15
- * @returns - Object with stdout, stderr, and exit code
16
- */
17
- function spawnGit(args, options) {
18
- return new Promise((resolve$1) => {
19
- logger.debug({
20
- args,
21
- cwd: options?.cwd
22
- }, "spawnGit");
23
- const proc = spawn("git", args, {
24
- cwd: options?.cwd,
25
- env: options?.env ?? process.env,
26
- stdio: [
27
- "ignore",
28
- "pipe",
29
- "pipe"
30
- ]
31
- });
32
- let stdout = "";
33
- let stderr = "";
34
- proc.stdout?.on("data", (chunk) => {
35
- stdout += chunk.toString();
36
- });
37
- proc.stderr?.on("data", (chunk) => {
38
- stderr += chunk.toString();
39
- });
40
- proc.on("close", (code) => {
41
- resolve$1({
42
- stdout: stdout.trim(),
43
- stderr: stderr.trim(),
44
- code: code ?? 1
45
- });
46
- });
47
- proc.on("error", (err) => {
48
- resolve$1({
49
- stdout: "",
50
- stderr: err.message,
51
- code: 1
52
- });
53
- });
54
- });
55
- }
56
- /**
57
- * Get the installed git version string.
58
- *
59
- * @returns Version string like "2.42.0"
60
- * @throws Error if git is not installed or version cannot be parsed
61
- */
62
- async function getGitVersion() {
63
- const result = await spawnGit(["--version"]);
64
- if (result.code !== 0) throw new Error(`git --version failed: ${result.stderr}`);
65
- const match = /git version\s+(\d+\.\d+(?:\.\d+)?)/.exec(result.stdout);
66
- if (match === null || match[1] === void 0) throw new Error(`Unable to parse git version from output: "${result.stdout}"`);
67
- return match[1];
68
- }
69
- /**
70
- * Parse a git version string into major/minor/patch components.
71
- *
72
- * @param versionString - Version string like "2.42.0" or "2.20"
73
- * @returns - Parsed version components
74
- */
75
- function parseGitVersion(versionString) {
76
- const parts = versionString.split(".").map(Number);
77
- return {
78
- major: parts[0] ?? 0,
79
- minor: parts[1] ?? 0,
80
- patch: parts[2] ?? 0
81
- };
82
- }
83
- /**
84
- * Check if the given git version string is >= 2.20.0.
85
- *
86
- * @param version - Version string like "2.42.0"
87
- * @returns - true if version >= 2.20.0
88
- */
89
- function isGitVersionSupported(version) {
90
- const { major, minor } = parseGitVersion(version);
91
- if (major > MIN_GIT_MAJOR) return true;
92
- if (major === MIN_GIT_MAJOR && minor >= MIN_GIT_MINOR) return true;
93
- return false;
94
- }
95
- /**
96
- * Verify that git is installed and version >= 2.20.
97
- *
98
- * @throws Error with clear message if git is not installed or too old
99
- */
100
- async function verifyGitVersion() {
101
- let version;
102
- try {
103
- version = await getGitVersion();
104
- } catch (err) {
105
- throw new Error(`git is not installed or could not be executed. Please install git 2.20 or newer. Details: ${String(err)}`);
106
- }
107
- if (!isGitVersionSupported(version)) {
108
- const { major, minor, patch } = parseGitVersion(version);
109
- throw new Error(`Git version ${major}.${minor}.${patch} is too old. Substrate requires git 2.20 or newer. Please upgrade git: https://git-scm.com/downloads`);
110
- }
111
- logger.debug({ version }, "git version verified");
112
- }
113
- /**
114
- * Create a git worktree and its associated branch.
115
- *
116
- * Uses a single `git worktree add {worktreePath} -b {branchName} {baseBranch}`
117
- * command to create the worktree with a new branch in one step.
118
- *
119
- * @param projectRoot - Absolute path to the git repository root
120
- * @param taskId - Task identifier (used in path derivation)
121
- * @param branchName - Branch name to create (e.g., "substrate/task-abc123")
122
- * @param baseBranch - Branch to base the worktree on (e.g., "main")
123
- * @returns - Object with the worktreePath
124
- * @throws - Error if git command fails
125
- */
126
- async function createWorktree(projectRoot, taskId, branchName, baseBranch) {
127
- const worktreePath = path.join(projectRoot, ".substrate-worktrees", taskId);
128
- logger.debug({
129
- projectRoot,
130
- taskId,
131
- branchName,
132
- baseBranch,
133
- worktreePath
134
- }, "createWorktree");
135
- const addResult = await spawnGit([
136
- "worktree",
137
- "add",
138
- worktreePath,
139
- "-b",
140
- branchName,
141
- baseBranch
142
- ], { cwd: projectRoot });
143
- if (addResult.code !== 0) throw new Error(`git worktree add failed for task "${taskId}": ${addResult.stderr || addResult.stdout}`);
144
- logger.info({
145
- taskId,
146
- branchName,
147
- worktreePath
148
- }, "Worktree created");
149
- return { worktreePath };
150
- }
151
- /**
152
- * Remove a git worktree by path.
153
- *
154
- * Uses `git worktree remove --force` to handle unclean worktrees.
155
- *
156
- * @param worktreePath - Absolute path to the worktree directory
157
- * @param projectRoot - Absolute path to the git repository root
158
- * @throws - Error if git command fails
159
- */
160
- async function removeWorktree(worktreePath, projectRoot) {
161
- logger.debug({ worktreePath }, "removeWorktree");
162
- const spawnOpts = {};
163
- if (projectRoot !== void 0) spawnOpts.cwd = projectRoot;
164
- const result = await spawnGit([
165
- "worktree",
166
- "remove",
167
- "--force",
168
- worktreePath
169
- ], spawnOpts);
170
- if (result.code !== 0) throw new Error(`git worktree remove failed for "${worktreePath}": ${result.stderr || result.stdout}`);
171
- logger.debug({ worktreePath }, "Worktree removed");
172
- }
173
- /**
174
- * Delete a git branch using `git branch -D`.
175
- *
176
- * @param branchName - Branch name to delete (e.g., "substrate/task-abc123")
177
- * @param projectRoot - Absolute path to the git repository root
178
- * @returns - true if branch was successfully deleted, false otherwise
179
- */
180
- async function removeBranch(branchName, projectRoot) {
181
- logger.debug({ branchName }, "removeBranch");
182
- const spawnOpts = {};
183
- if (projectRoot !== void 0) spawnOpts.cwd = projectRoot;
184
- const result = await spawnGit([
185
- "branch",
186
- "-D",
187
- branchName
188
- ], spawnOpts);
189
- if (result.code !== 0) {
190
- logger.warn({
191
- branchName,
192
- stderr: result.stderr
193
- }, "git branch -D failed (may already be deleted)");
194
- return false;
195
- }
196
- logger.debug({ branchName }, "Branch deleted");
197
- return true;
198
- }
199
- /**
200
- * Scan the worktrees base directory and return paths of all found worktree directories.
201
- *
202
- * @param projectRoot - Absolute path to the git repository root
203
- * @param baseDirectory - Relative directory name for worktrees (default: '.substrate-worktrees')
204
- * @returns - Array of absolute worktree directory paths
205
- */
206
- async function getOrphanedWorktrees(projectRoot, baseDirectory = ".substrate-worktrees") {
207
- const worktreesDir = path.join(projectRoot, baseDirectory);
208
- try {
209
- await access(worktreesDir);
210
- } catch {
211
- return [];
212
- }
213
- let entries;
214
- try {
215
- entries = await readdir(worktreesDir, { withFileTypes: true });
216
- } catch (err) {
217
- logger.warn({
218
- worktreesDir,
219
- err
220
- }, "getOrphanedWorktrees: failed to read directory");
221
- return [];
222
- }
223
- return entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(worktreesDir, entry.name));
224
- }
225
- /**
226
- * Simulate a merge using git merge --no-commit --no-ff without committing.
227
- *
228
- * This runs in the target branch's working directory (the project root or
229
- * worktree path). The simulation must be aborted after checking conflicts
230
- * via abortMerge().
231
- *
232
- * @param branchName - The source branch to simulate merging
233
- * @param cwd - Working directory (must be on the target branch)
234
- * @returns - true if merge would be clean, false if there are conflicts
235
- */
236
- async function simulateMerge(branchName, cwd) {
237
- logger.debug({
238
- branchName,
239
- cwd
240
- }, "simulateMerge");
241
- const result = await spawnGit([
242
- "merge",
243
- "--no-commit",
244
- "--no-ff",
245
- branchName
246
- ], { cwd });
247
- if (result.code === 0) return true;
248
- return false;
249
- }
250
- /**
251
- * Abort a merge in progress using git merge --abort.
252
- *
253
- * Should be called after simulateMerge() to clean up the merge state,
254
- * regardless of whether conflicts were found.
255
- *
256
- * @param cwd - Working directory (same as used for simulateMerge)
257
- */
258
- async function abortMerge(cwd) {
259
- logger.debug({ cwd }, "abortMerge");
260
- const result = await spawnGit(["merge", "--abort"], { cwd });
261
- if (result.code !== 0) logger.warn({
262
- cwd,
263
- stderr: result.stderr
264
- }, "abortMerge: git merge --abort returned non-zero (may have been nothing to abort)");
265
- logger.debug({ cwd }, "Merge aborted");
266
- }
267
- /**
268
- * Get a list of files with conflicts during a merge.
269
- *
270
- * Must be called while a merge is in progress (after simulateMerge() and
271
- * before abortMerge()).
272
- *
273
- * @param cwd - Working directory of the repository
274
- * @returns - Array of conflicting file paths
275
- */
276
- async function getConflictingFiles(cwd) {
277
- logger.debug({ cwd }, "getConflictingFiles");
278
- const result = await spawnGit([
279
- "diff",
280
- "--name-only",
281
- "--diff-filter=U"
282
- ], { cwd });
283
- if (result.code !== 0) {
284
- logger.warn({
285
- cwd,
286
- stderr: result.stderr
287
- }, "getConflictingFiles: git diff returned non-zero");
288
- return [];
289
- }
290
- if (result.stdout.trim() === "") return [];
291
- return result.stdout.trim().split("\n").filter((f) => f.trim().length > 0);
292
- }
293
- /**
294
- * Perform an actual merge using git merge --no-ff.
295
- *
296
- * Should only be called after detectConflicts() confirms there are no conflicts.
297
- * Creates a merge commit even if fast-forward is possible (--no-ff ensures history).
298
- *
299
- * @param branchName - The source branch to merge
300
- * @param cwd - Working directory (must be on the target branch)
301
- * @returns - true if merge succeeded, false otherwise
302
- */
303
- async function performMerge(branchName, cwd) {
304
- logger.debug({
305
- branchName,
306
- cwd
307
- }, "performMerge");
308
- const result = await spawnGit([
309
- "merge",
310
- "--no-ff",
311
- branchName
312
- ], { cwd });
313
- if (result.code !== 0) {
314
- logger.warn({
315
- branchName,
316
- cwd,
317
- stderr: result.stderr
318
- }, "performMerge: git merge --no-ff failed");
319
- return false;
320
- }
321
- logger.debug({
322
- branchName,
323
- cwd
324
- }, "Merge completed");
325
- return true;
326
- }
327
- /**
328
- * Get a list of files changed in the most recent merge.
329
- *
330
- * Uses git diff --name-only HEAD~1..HEAD to find files in the merge commit.
331
- * Falls back to empty array if commit history is insufficient.
332
- *
333
- * @param cwd - Working directory of the repository
334
- * @returns - Array of file paths that were merged
335
- */
336
- async function getMergedFiles(cwd) {
337
- logger.debug({ cwd }, "getMergedFiles");
338
- const result = await spawnGit([
339
- "diff",
340
- "--name-only",
341
- "HEAD~1..HEAD"
342
- ], { cwd });
343
- if (result.code !== 0) {
344
- const altResult = await spawnGit([
345
- "show",
346
- "--name-only",
347
- "--format=",
348
- "HEAD"
349
- ], { cwd });
350
- if (altResult.code !== 0) {
351
- logger.warn({
352
- cwd,
353
- stderr: altResult.stderr
354
- }, "getMergedFiles: failed to get merged file list");
355
- return [];
356
- }
357
- return altResult.stdout.trim().split("\n").filter((f) => f.trim().length > 0);
358
- }
359
- if (result.stdout.trim() === "") return [];
360
- return result.stdout.trim().split("\n").filter((f) => f.trim().length > 0);
361
- }
362
-
363
- //#endregion
364
- export { abortMerge, createWorktree, getConflictingFiles, getMergedFiles, getOrphanedWorktrees, performMerge, removeBranch, removeWorktree, simulateMerge, spawnGit, verifyGitVersion };
365
- //# sourceMappingURL=git-utils-DxPx6erV.js.map
@@ -1,5 +0,0 @@
1
- import { DEFAULT_STALL_THRESHOLD_SECONDS, getAllDescendantPids, getAutoHealthData, inspectProcessTree, isOrchestratorProcessLine, registerHealthCommand, runHealthAction } from "./health-C-VRJruD.js";
2
- import "./logger-D2fS2ccL.js";
3
- import "./decisions-DhAA2HG2.js";
4
-
5
- export { inspectProcessTree };