agentic-forge 0.0.0 → 0.7.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.
Files changed (212) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +64 -24
  3. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/SKILL.md +2 -2
  4. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/REFERENCE.md +9 -3
  5. package/{src/claude → dist/authoring}/.claude/skills/workflow-builder/references/workflow-example.yaml +15 -8
  6. package/dist/checkpoints/manager.d.ts +5 -0
  7. package/dist/checkpoints/manager.js +87 -0
  8. package/dist/checkpoints/manager.js.map +1 -0
  9. package/{src → dist}/claude/.claude/skills/analyze/SKILL.md +1 -1
  10. package/{src → dist}/claude/.claude/skills/create-checkpoint/SKILL.md +1 -1
  11. package/{src → dist}/claude/.claude/skills/create-log/SKILL.md +1 -1
  12. package/{src → dist}/claude/.claude/skills/fix-analyze/SKILL.md +1 -1
  13. package/{src → dist}/claude/.claude/skills/git-branch/SKILL.md +1 -1
  14. package/{src → dist}/claude/.claude/skills/git-commit/SKILL.md +1 -1
  15. package/{src → dist}/claude/.claude/skills/git-pr/SKILL.md +1 -1
  16. package/{src → dist}/claude/.claude/skills/sdlc-plan/SKILL.md +1 -1
  17. package/{src → dist}/claude/.claude/skills/sdlc-review/SKILL.md +1 -1
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.js +173 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands/authoring-dir.d.ts +2 -0
  22. package/dist/commands/authoring-dir.js +9 -0
  23. package/dist/commands/authoring-dir.js.map +1 -0
  24. package/dist/commands/config-cmd.d.ts +2 -0
  25. package/dist/commands/config-cmd.js +30 -0
  26. package/dist/commands/config-cmd.js.map +1 -0
  27. package/{src/commands/index.ts → dist/commands/index.d.ts} +2 -10
  28. package/dist/commands/index.js +14 -0
  29. package/dist/commands/index.js.map +1 -0
  30. package/dist/commands/init.d.ts +6 -0
  31. package/dist/commands/init.js +83 -0
  32. package/dist/commands/init.js.map +1 -0
  33. package/dist/commands/release-notes.d.ts +5 -0
  34. package/dist/commands/release-notes.js +68 -0
  35. package/dist/commands/release-notes.js.map +1 -0
  36. package/dist/commands/resume.d.ts +5 -0
  37. package/dist/commands/resume.js +79 -0
  38. package/dist/commands/resume.js.map +1 -0
  39. package/dist/commands/run.d.ts +27 -0
  40. package/dist/commands/run.js +243 -0
  41. package/dist/commands/run.js.map +1 -0
  42. package/dist/commands/shortcuts.d.ts +2 -0
  43. package/dist/commands/shortcuts.js +11 -0
  44. package/dist/commands/shortcuts.js.map +1 -0
  45. package/dist/commands/skills-dir.d.ts +2 -0
  46. package/dist/commands/skills-dir.js +9 -0
  47. package/dist/commands/skills-dir.js.map +1 -0
  48. package/dist/commands/status.d.ts +4 -0
  49. package/dist/commands/status.js +99 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/commands/update.d.ts +4 -0
  52. package/dist/commands/update.js +65 -0
  53. package/dist/commands/update.js.map +1 -0
  54. package/dist/commands/version.d.ts +3 -0
  55. package/dist/commands/version.js +26 -0
  56. package/dist/commands/version.js.map +1 -0
  57. package/dist/commands/workflows.d.ts +4 -0
  58. package/dist/commands/workflows.js +111 -0
  59. package/dist/commands/workflows.js.map +1 -0
  60. package/dist/config.d.ts +8 -0
  61. package/dist/config.js +110 -0
  62. package/dist/config.js.map +1 -0
  63. package/dist/console.d.ts +103 -0
  64. package/dist/console.js +670 -0
  65. package/dist/console.js.map +1 -0
  66. package/dist/executor.d.ts +27 -0
  67. package/dist/executor.js +236 -0
  68. package/dist/executor.js.map +1 -0
  69. package/dist/git/worktree.d.ts +23 -0
  70. package/dist/git/worktree.js +170 -0
  71. package/dist/git/worktree.js.map +1 -0
  72. package/dist/logging/logger.d.ts +27 -0
  73. package/dist/logging/logger.js +69 -0
  74. package/dist/logging/logger.js.map +1 -0
  75. package/dist/orchestrator.d.ts +44 -0
  76. package/dist/orchestrator.js +587 -0
  77. package/dist/orchestrator.js.map +1 -0
  78. package/dist/parser.d.ts +17 -0
  79. package/dist/parser.js +184 -0
  80. package/dist/parser.js.map +1 -0
  81. package/dist/progress.d.ts +29 -0
  82. package/dist/progress.js +275 -0
  83. package/dist/progress.js.map +1 -0
  84. package/dist/ralph-loop.d.ts +26 -0
  85. package/dist/ralph-loop.js +194 -0
  86. package/dist/ralph-loop.js.map +1 -0
  87. package/dist/renderer.d.ts +15 -0
  88. package/dist/renderer.js +123 -0
  89. package/dist/renderer.js.map +1 -0
  90. package/dist/runner.d.ts +84 -0
  91. package/dist/runner.js +529 -0
  92. package/dist/runner.js.map +1 -0
  93. package/dist/signal-manager.d.ts +16 -0
  94. package/dist/signal-manager.js +50 -0
  95. package/dist/signal-manager.js.map +1 -0
  96. package/dist/steps/base.d.ts +28 -0
  97. package/dist/steps/base.js +23 -0
  98. package/dist/steps/base.js.map +1 -0
  99. package/dist/steps/conditional-step.d.ts +12 -0
  100. package/dist/steps/conditional-step.js +106 -0
  101. package/dist/steps/conditional-step.js.map +1 -0
  102. package/{src/steps/index.ts → dist/steps/index.d.ts} +1 -9
  103. package/dist/steps/index.js +8 -0
  104. package/dist/steps/index.js.map +1 -0
  105. package/dist/steps/parallel-step.d.ts +11 -0
  106. package/dist/steps/parallel-step.js +166 -0
  107. package/dist/steps/parallel-step.js.map +1 -0
  108. package/dist/steps/prompt-step.d.ts +8 -0
  109. package/dist/steps/prompt-step.js +94 -0
  110. package/dist/steps/prompt-step.js.map +1 -0
  111. package/dist/steps/ralph-loop-step.d.ts +8 -0
  112. package/dist/steps/ralph-loop-step.js +132 -0
  113. package/dist/steps/ralph-loop-step.js.map +1 -0
  114. package/dist/steps/serial-step.d.ts +10 -0
  115. package/dist/steps/serial-step.js +57 -0
  116. package/dist/steps/serial-step.js.map +1 -0
  117. package/dist/types.d.ts +118 -0
  118. package/dist/types.js +10 -0
  119. package/dist/types.js.map +1 -0
  120. package/package.json +59 -2
  121. package/.gitattributes +0 -24
  122. package/.github/workflows/ci.yml +0 -70
  123. package/.markdownlint-cli2.jsonc +0 -16
  124. package/.prettierignore +0 -3
  125. package/.prettierrc +0 -6
  126. package/.vscode/agentic-forge.code-workspace +0 -26
  127. package/CHANGELOG.md +0 -100
  128. package/CLAUDE.md +0 -158
  129. package/CONTRIBUTING.md +0 -152
  130. package/biome.json +0 -21
  131. package/scripts/copy-assets.js +0 -21
  132. package/src/checkpoints/manager.ts +0 -119
  133. package/src/cli.ts +0 -182
  134. package/src/commands/config-cmd.ts +0 -28
  135. package/src/commands/init.ts +0 -96
  136. package/src/commands/release-notes.ts +0 -85
  137. package/src/commands/resume.ts +0 -103
  138. package/src/commands/run.ts +0 -234
  139. package/src/commands/shortcuts.ts +0 -11
  140. package/src/commands/skills-dir.ts +0 -11
  141. package/src/commands/status.ts +0 -112
  142. package/src/commands/update.ts +0 -64
  143. package/src/commands/version.ts +0 -27
  144. package/src/commands/workflows.ts +0 -129
  145. package/src/config.ts +0 -129
  146. package/src/console.ts +0 -790
  147. package/src/executor.ts +0 -354
  148. package/src/git/worktree.ts +0 -236
  149. package/src/logging/logger.ts +0 -95
  150. package/src/orchestrator.ts +0 -815
  151. package/src/parser.ts +0 -225
  152. package/src/progress.ts +0 -306
  153. package/src/ralph-loop.ts +0 -260
  154. package/src/renderer.ts +0 -164
  155. package/src/runner.ts +0 -634
  156. package/src/signal-manager.ts +0 -55
  157. package/src/steps/base.ts +0 -71
  158. package/src/steps/conditional-step.ts +0 -144
  159. package/src/steps/parallel-step.ts +0 -213
  160. package/src/steps/prompt-step.ts +0 -121
  161. package/src/steps/ralph-loop-step.ts +0 -186
  162. package/src/steps/serial-step.ts +0 -84
  163. package/src/types.ts +0 -141
  164. package/tests/config.test.ts +0 -219
  165. package/tests/console.test.ts +0 -506
  166. package/tests/executor.test.ts +0 -339
  167. package/tests/init.test.ts +0 -86
  168. package/tests/logger.test.ts +0 -110
  169. package/tests/parser.test.ts +0 -290
  170. package/tests/progress.test.ts +0 -345
  171. package/tests/ralph-loop.test.ts +0 -418
  172. package/tests/renderer.test.ts +0 -350
  173. package/tests/runner.test.ts +0 -497
  174. package/tests/setup.test.ts +0 -7
  175. package/tests/signal-manager.test.ts +0 -26
  176. package/tests/steps.test.ts +0 -412
  177. package/tests/worktree.test.ts +0 -411
  178. package/tsconfig.json +0 -18
  179. package/vitest.config.ts +0 -8
  180. /package/{src → dist}/agents/explorer.md +0 -0
  181. /package/{src → dist}/agents/reviewer.md +0 -0
  182. /package/{src → dist}/claude/.claude/skills/analyze/references/bug.md +0 -0
  183. /package/{src → dist}/claude/.claude/skills/analyze/references/debt.md +0 -0
  184. /package/{src → dist}/claude/.claude/skills/analyze/references/doc.md +0 -0
  185. /package/{src → dist}/claude/.claude/skills/analyze/references/security.md +0 -0
  186. /package/{src → dist}/claude/.claude/skills/analyze/references/style.md +0 -0
  187. /package/{src → dist}/claude/.claude/skills/orchestrate/SKILL.md +0 -0
  188. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/bug.md +0 -0
  189. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/chore.md +0 -0
  190. /package/{src → dist}/claude/.claude/skills/sdlc-plan/references/feature.md +0 -0
  191. /package/{src → dist}/prompts/agentic-system.md +0 -0
  192. /package/{src → dist}/templates/analysis/bug.md.j2 +0 -0
  193. /package/{src → dist}/templates/analysis/debt.md.j2 +0 -0
  194. /package/{src → dist}/templates/analysis/doc.md.j2 +0 -0
  195. /package/{src → dist}/templates/analysis/security.md.j2 +0 -0
  196. /package/{src → dist}/templates/analysis/style.md.j2 +0 -0
  197. /package/{src → dist}/templates/analysis-summary.md.j2 +0 -0
  198. /package/{src → dist}/templates/checkpoint.md.j2 +0 -0
  199. /package/{src → dist}/templates/implementation-report.md.j2 +0 -0
  200. /package/{src → dist}/templates/memory.md.j2 +0 -0
  201. /package/{src → dist}/templates/plan-bug.md.j2 +0 -0
  202. /package/{src → dist}/templates/plan-chore.md.j2 +0 -0
  203. /package/{src → dist}/templates/plan-feature.md.j2 +0 -0
  204. /package/{src → dist}/templates/progress.json.j2 +0 -0
  205. /package/{src → dist}/templates/ralph-report.md.j2 +0 -0
  206. /package/{src → dist}/workflows/analyze-codebase-merge.yaml +0 -0
  207. /package/{src → dist}/workflows/analyze-codebase.yaml +0 -0
  208. /package/{src → dist}/workflows/analyze-single.yaml +0 -0
  209. /package/{src → dist}/workflows/demo.yaml +0 -0
  210. /package/{src → dist}/workflows/one-shot.yaml +0 -0
  211. /package/{src → dist}/workflows/plan-build-review.yaml +0 -0
  212. /package/{src → dist}/workflows/ralph-loop.yaml +0 -0
@@ -1,64 +0,0 @@
1
- /** Update command handler. */
2
-
3
- import { execFileSync } from "node:child_process";
4
-
5
- import { getVersion } from "./version.js";
6
-
7
- function commandExists(cmd: string): boolean {
8
- try {
9
- execFileSync(process.platform === "win32" ? "where" : "which", [cmd], {
10
- stdio: "ignore",
11
- });
12
- return true;
13
- } catch {
14
- return false;
15
- }
16
- }
17
-
18
- export function cmdUpdate(options: { check?: boolean }): void {
19
- const currentVersion = getVersion();
20
- if (currentVersion === "unknown") {
21
- process.stderr.write("Error: agentic-forge is not installed\n");
22
- process.exit(1);
23
- }
24
-
25
- if (!commandExists("npm")) {
26
- process.stderr.write("Error: npm is required for updating agentic-forge\n");
27
- process.exit(1);
28
- }
29
-
30
- if (options.check) {
31
- process.stdout.write(`Current version: ${currentVersion}\n`);
32
- try {
33
- const result = execFileSync("npm", ["view", "agentic-forge", "version"], {
34
- encoding: "utf-8",
35
- stdio: ["pipe", "pipe", "pipe"],
36
- }).trim();
37
- if (result && result !== currentVersion) {
38
- process.stdout.write(`Latest version: ${result}\n`);
39
- } else {
40
- process.stdout.write("Already at the latest version.\n");
41
- }
42
- } catch {
43
- process.stdout.write("Could not check for updates.\n");
44
- }
45
- } else {
46
- process.stdout.write(`Current version: ${currentVersion}\n`);
47
- process.stdout.write("Upgrading...\n");
48
- try {
49
- execFileSync("npm", ["install", "-g", "agentic-forge"], {
50
- encoding: "utf-8",
51
- stdio: ["pipe", "pipe", "pipe"],
52
- });
53
- const newVersion = getVersion();
54
- if (newVersion !== currentVersion) {
55
- process.stdout.write(`Successfully updated to version ${newVersion}\n`);
56
- } else {
57
- process.stdout.write("Already at the latest version.\n");
58
- }
59
- } catch {
60
- process.stderr.write("Update failed.\n");
61
- process.exit(1);
62
- }
63
- }
64
- }
@@ -1,27 +0,0 @@
1
- /** Version command handler. */
2
-
3
- import { readFileSync } from "node:fs";
4
- import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
-
7
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
-
9
- export function cmdVersion(): void {
10
- try {
11
- const packageJsonPath = path.join(__dirname, "..", "..", "package.json");
12
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { version: string };
13
- process.stdout.write(`agentic-forge ${pkg.version}\n`);
14
- } catch {
15
- process.stdout.write("agentic-forge version unknown (package not installed)\n");
16
- }
17
- }
18
-
19
- export function getVersion(): string {
20
- try {
21
- const packageJsonPath = path.join(__dirname, "..", "..", "package.json");
22
- const pkg = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as { version: string };
23
- return pkg.version;
24
- } catch {
25
- return "unknown";
26
- }
27
- }
@@ -1,129 +0,0 @@
1
- /** Workflows command handler. */
2
-
3
- import { existsSync, readFileSync, readdirSync } from "node:fs";
4
- import path from "node:path";
5
- import yaml from "js-yaml";
6
-
7
- import { getBundledWorkflowsDir, getProjectWorkflowsDir, getUserWorkflowsDir } from "./run.js";
8
-
9
- interface WorkflowMetadata {
10
- name: string;
11
- description: string;
12
- variables: { name: string; required?: boolean }[];
13
- }
14
-
15
- function getWorkflowMetadata(filePath: string): WorkflowMetadata {
16
- try {
17
- const content = yaml.load(readFileSync(filePath, "utf-8")) as Record<string, unknown> | null;
18
- if (!content || typeof content !== "object") {
19
- return { name: path.basename(filePath, ".yaml"), description: "", variables: [] };
20
- }
21
- return {
22
- name: (content.name as string) ?? path.basename(filePath, ".yaml"),
23
- description: (content.description as string) ?? "",
24
- variables: (content.variables as WorkflowMetadata["variables"]) ?? [],
25
- };
26
- } catch {
27
- return { name: path.basename(filePath, ".yaml"), description: "", variables: [] };
28
- }
29
- }
30
-
31
- function listAllWorkflows(): [string, string, string, WorkflowMetadata][] {
32
- const workflows: [string, string, string, WorkflowMetadata][] = [];
33
-
34
- const searchLocations: [string, string][] = [
35
- [getProjectWorkflowsDir(), "project"],
36
- [getUserWorkflowsDir(), "user"],
37
- [getBundledWorkflowsDir(), "bundled"],
38
- ];
39
-
40
- for (const [directory, locationType] of searchLocations) {
41
- if (existsSync(directory)) {
42
- const files = readdirSync(directory)
43
- .filter((f) => f.endsWith(".yaml"))
44
- .sort();
45
- for (const file of files) {
46
- const fullPath = path.join(directory, file);
47
- const metadata = getWorkflowMetadata(fullPath);
48
- workflows.push([path.basename(file, ".yaml"), fullPath, locationType, metadata]);
49
- }
50
- }
51
- }
52
-
53
- return workflows;
54
- }
55
-
56
- export function cmdWorkflows(options: { verbose?: boolean }): void {
57
- const workflows = listAllWorkflows();
58
-
59
- if (workflows.length === 0) {
60
- process.stdout.write("No workflows found.\n");
61
- process.stdout.write("\nSearched locations:\n");
62
- process.stdout.write(` - Project: ${getProjectWorkflowsDir()}\n`);
63
- process.stdout.write(` - User: ${getUserWorkflowsDir()}\n`);
64
- process.stdout.write(` - Bundled: ${getBundledWorkflowsDir()}\n`);
65
- process.stdout.write("\nUse 'agentic-forge init' to copy bundled workflows locally.\n");
66
- return;
67
- }
68
-
69
- const verbose = options.verbose ?? false;
70
-
71
- // Group by location
72
- const byLocation: Record<string, [string, string, WorkflowMetadata][]> = {};
73
- for (const [name, wfPath, location, metadata] of workflows) {
74
- if (!byLocation[location]) {
75
- byLocation[location] = [];
76
- }
77
- byLocation[location].push([name, wfPath, metadata]);
78
- }
79
-
80
- process.stdout.write("Available Workflows\n");
81
- process.stdout.write(`${"=".repeat(50)}\n\n`);
82
-
83
- const locationOrder = ["project", "user", "bundled"];
84
- const locationLabels: Record<string, string> = {
85
- project: "Project",
86
- user: "User",
87
- bundled: "Bundled",
88
- };
89
-
90
- for (const location of locationOrder) {
91
- if (!byLocation[location]) {
92
- continue;
93
- }
94
-
95
- process.stdout.write(`${locationLabels[location]}:\n`);
96
- for (const [name, , metadata] of byLocation[location]) {
97
- let desc = metadata.description;
98
- if (desc) {
99
- if (desc.length > 60 && !verbose) {
100
- desc = `${desc.slice(0, 57)}...`;
101
- }
102
- process.stdout.write(` ${name.padEnd(25)} ${desc}\n`);
103
- } else {
104
- process.stdout.write(` ${name}\n`);
105
- }
106
-
107
- if (verbose && metadata.variables.length > 0) {
108
- const required = metadata.variables.filter((v) => v.required).map((v) => v.name);
109
- const optional = metadata.variables.filter((v) => !v.required).map((v) => v.name);
110
- if (required.length > 0) {
111
- process.stdout.write(` Required: ${required.join(", ")}\n`);
112
- }
113
- if (optional.length > 0) {
114
- process.stdout.write(` Optional: ${optional.join(", ")}\n`);
115
- }
116
- }
117
- }
118
- process.stdout.write("\n");
119
- }
120
-
121
- process.stdout.write(`Total: ${workflows.length} workflow(s)\n\n`);
122
- process.stdout.write("Usage:\n");
123
- process.stdout.write(" agentic-forge run <workflow-name>\n");
124
- process.stdout.write(" agentic-forge run <workflow-name> --var key=value\n\n");
125
- process.stdout.write("Examples:\n");
126
- process.stdout.write(' agentic-forge run one-shot --var task="Add login button"\n');
127
- process.stdout.write(" agentic-forge run analyze-single --var analysis_type=bug\n");
128
- process.stdout.write(' agentic-forge run plan-build-review --var task="Refactor auth"\n');
129
- }
package/src/config.ts DELETED
@@ -1,129 +0,0 @@
1
- /** Configuration management for agentic-forge. */
2
-
3
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
- import path from "node:path";
5
-
6
- const DEFAULT_CONFIG: Record<string, unknown> = {
7
- outputDirectory: "agentic",
8
- logging: {
9
- enabled: true,
10
- level: "Error",
11
- },
12
- git: {
13
- mainBranch: "main",
14
- autoCommit: true,
15
- autoPr: true,
16
- },
17
- defaults: {
18
- model: "sonnet",
19
- maxRetry: 3,
20
- timeoutMinutes: 60,
21
- trackProgress: true,
22
- terminalOutput: "base",
23
- },
24
- execution: {
25
- maxWorkers: 4,
26
- pollingIntervalSeconds: 5,
27
- },
28
- };
29
-
30
- export function getConfigPath(repoRoot?: string): string {
31
- const root = repoRoot ?? process.cwd();
32
- return path.join(root, "agentic", "config.json");
33
- }
34
-
35
- export function getDefaultConfig(): Record<string, unknown> {
36
- return deepCopy(DEFAULT_CONFIG);
37
- }
38
-
39
- export function loadConfig(repoRoot?: string): Record<string, unknown> {
40
- const configPath = getConfigPath(repoRoot);
41
-
42
- if (existsSync(configPath)) {
43
- const content = readFileSync(configPath, "utf-8");
44
- const userConfig = JSON.parse(content) as Record<string, unknown>;
45
- return deepMerge(getDefaultConfig(), userConfig);
46
- }
47
-
48
- return getDefaultConfig();
49
- }
50
-
51
- export function saveConfig(config: Record<string, unknown>, repoRoot?: string): void {
52
- const configPath = getConfigPath(repoRoot);
53
- const dir = path.dirname(configPath);
54
- mkdirSync(dir, { recursive: true });
55
- writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
56
- }
57
-
58
- export function getConfigValue(key: string, repoRoot?: string): unknown {
59
- const config = loadConfig(repoRoot);
60
- const parts = key.split(".");
61
- let value: unknown = config;
62
- for (const part of parts) {
63
- if (
64
- value !== null &&
65
- typeof value === "object" &&
66
- !Array.isArray(value) &&
67
- part in (value as Record<string, unknown>)
68
- ) {
69
- value = (value as Record<string, unknown>)[part];
70
- } else {
71
- return null;
72
- }
73
- }
74
- return value;
75
- }
76
-
77
- export function setConfigValue(key: string, value: string, repoRoot?: string): void {
78
- const config = loadConfig(repoRoot);
79
- const parts = key.split(".");
80
- let target = config;
81
- for (const part of parts.slice(0, -1)) {
82
- if (!(part in target)) {
83
- target[part] = {};
84
- }
85
- target = target[part] as Record<string, unknown>;
86
- }
87
-
88
- let parsedValue: unknown = value;
89
- if (value.toLowerCase() === "true") {
90
- parsedValue = true;
91
- } else if (value.toLowerCase() === "false") {
92
- parsedValue = false;
93
- } else if (/^\d+$/.test(value)) {
94
- parsedValue = Number.parseInt(value, 10);
95
- }
96
-
97
- target[parts[parts.length - 1]] = parsedValue;
98
- saveConfig(config, repoRoot);
99
- }
100
-
101
- export function deepMerge(
102
- base: Record<string, unknown>,
103
- override: Record<string, unknown>,
104
- ): Record<string, unknown> {
105
- const result = { ...base };
106
- for (const key of Object.keys(override)) {
107
- if (
108
- key in result &&
109
- typeof result[key] === "object" &&
110
- result[key] !== null &&
111
- !Array.isArray(result[key]) &&
112
- typeof override[key] === "object" &&
113
- override[key] !== null &&
114
- !Array.isArray(override[key])
115
- ) {
116
- result[key] = deepMerge(
117
- result[key] as Record<string, unknown>,
118
- override[key] as Record<string, unknown>,
119
- );
120
- } else {
121
- result[key] = override[key];
122
- }
123
- }
124
- return result;
125
- }
126
-
127
- function deepCopy(obj: Record<string, unknown>): Record<string, unknown> {
128
- return JSON.parse(JSON.stringify(obj)) as Record<string, unknown>;
129
- }