@aiviatic/kindling 0.1.1 → 0.1.2
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.
- package/bootstrap/setup.ps1 +47 -8
- package/bootstrap/setup.sh +1 -1
- package/dist/{chunk-6VTQGOJR.js → chunk-DZ2RR3SP.js} +136 -78
- package/dist/chunk-DZ2RR3SP.js.map +1 -0
- package/dist/cli/main.js +3 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/engine/index.d.ts +15 -0
- package/dist/engine/index.js +6 -17
- package/dist/engine/index.js.map +1 -1
- package/dist/ui/assets/index-QhMuWZCb.js +40 -0
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
- package/dist/chunk-6VTQGOJR.js.map +0 -1
- package/dist/ui/assets/index-BF3LDvt7.js +0 -40
package/bootstrap/setup.ps1
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
$ErrorActionPreference = 'Stop'
|
|
11
11
|
|
|
12
12
|
$KindlingNodeVersion = '24.16.0' # == pins.node
|
|
13
|
-
$KindlingVersion = '0.1.
|
|
13
|
+
$KindlingVersion = '0.1.2' # == pins.kindling
|
|
14
14
|
$NodeFloorMajor = 20
|
|
15
15
|
|
|
16
16
|
# --- Inline helpers (were bootstrap/lib/common.ps1; inlined for the file-less delivery) ----------
|
|
@@ -39,19 +39,24 @@ Say " - This window already runs with -ExecutionPolicy Bypass for THIS process o
|
|
|
39
39
|
# $NodeExe stays $null when a system Node is reused (launch via PATH); the portable-install path
|
|
40
40
|
# sets it to the absolute node.exe so the launch never depends on PATH (clean-runtime rule, AR6).
|
|
41
41
|
$NodeExe = $null
|
|
42
|
+
$arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } else { 'x64' }
|
|
43
|
+
$distName = "node-v$KindlingNodeVersion-win-$arch"
|
|
44
|
+
$nodeRoot = Join-Path $env:LOCALAPPDATA 'kindling\node'
|
|
45
|
+
$portableNode = Join-Path $nodeRoot "$distName\node.exe"
|
|
42
46
|
if (Test-NodeOk $NodeFloorMajor) {
|
|
43
47
|
Say "Node is already installed - reusing it."
|
|
48
|
+
} elseif (Test-Path $portableNode) {
|
|
49
|
+
# Portable Node from a previous run is already extracted here - reuse it, don't re-download the
|
|
50
|
+
# 30 MB. (The portable dir is never persisted to PATH, so Test-NodeOk alone can't see it.)
|
|
51
|
+
Say "Node is already installed - reusing it."
|
|
52
|
+
$NodeExe = $portableNode
|
|
44
53
|
} else {
|
|
45
54
|
Say "Setting up Node - the engine your project runs on. This downloads about 30 MB, one time."
|
|
46
55
|
# Portable Node: download the pinned Windows zip from nodejs.org, VERIFY its SHA-256 against Node's
|
|
47
56
|
# published SHASUMS256.txt before touching it, extract, and point the launch at the absolute
|
|
48
57
|
# node.exe (clean-runtime rule AR6 — never rely on a mutated PATH). Mirrors node-windows.ts.
|
|
49
|
-
# NOTE: newly implemented; validate on real Windows (proxy/TLS-interception, extract, non-admin exec).
|
|
50
58
|
$ProgressPreference = 'SilentlyContinue' # a visible progress bar makes Invoke-WebRequest ~10x slower
|
|
51
59
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
52
|
-
$arch = if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { 'arm64' } else { 'x64' }
|
|
53
|
-
$distName = "node-v$KindlingNodeVersion-win-$arch"
|
|
54
|
-
$nodeRoot = Join-Path $env:LOCALAPPDATA 'kindling\node'
|
|
55
60
|
$zipPath = Join-Path $nodeRoot "$distName.zip"
|
|
56
61
|
$baseUrl = "https://nodejs.org/dist/v$KindlingNodeVersion"
|
|
57
62
|
New-Item -ItemType Directory -Force -Path $nodeRoot | Out-Null
|
|
@@ -73,12 +78,43 @@ if (Test-NodeOk $NodeFloorMajor) {
|
|
|
73
78
|
Say "Node is ready."
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
# --- Git (portable)
|
|
81
|
+
# --- Git (pinned, portable MinGit) -------------------------------------------
|
|
82
|
+
# $GitCmdDir stays $null when a system Git is reused (already on PATH); the portable path sets it to
|
|
83
|
+
# MinGit's cmd\ dir, prepended to PATH at launch so the engine can `git init` the new project.
|
|
84
|
+
$GitCmdDir = $null
|
|
85
|
+
$gitRoot = Join-Path $env:LOCALAPPDATA 'kindling\git'
|
|
86
|
+
$portableGitCmd = Join-Path $gitRoot 'cmd'
|
|
77
87
|
if (Test-Cmd 'git') {
|
|
78
88
|
Say "Git is already installed - reusing it."
|
|
89
|
+
} elseif (Test-Path (Join-Path $portableGitCmd 'git.exe')) {
|
|
90
|
+
# Portable MinGit from a previous run is already extracted here - reuse it, don't re-download.
|
|
91
|
+
Say "Git is already installed - reusing it."
|
|
92
|
+
$GitCmdDir = $portableGitCmd
|
|
79
93
|
} else {
|
|
80
|
-
Say "Setting up Git - it keeps the history of your project."
|
|
81
|
-
#
|
|
94
|
+
Say "Setting up Git - it keeps the history of your project. This downloads about 35 MB, one time."
|
|
95
|
+
# Portable MinGit (the ZIP build made for bundling): download the pinned release, VERIFY its SHA-256
|
|
96
|
+
# before touching it, extract, and expose cmd\ on PATH. Mirrors the Node block. Pinned version +
|
|
97
|
+
# hash below MUST be bumped together (git-for-windows publishes the digest on each release asset).
|
|
98
|
+
$ProgressPreference = 'SilentlyContinue'
|
|
99
|
+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
|
100
|
+
$gitVersion = '2.55.0.2'
|
|
101
|
+
$gitZip = Join-Path $env:LOCALAPPDATA 'kindling\mingit.zip'
|
|
102
|
+
$gitUrl = "https://github.com/git-for-windows/git/releases/download/v2.55.0.windows.2/MinGit-$gitVersion-64-bit.zip"
|
|
103
|
+
$gitSha = 'e3ea2944cea4b3fabcd69c7c1669ef69b1b66c05ac7806d81224d0abad2dec31'
|
|
104
|
+
New-Item -ItemType Directory -Force -Path $gitRoot | Out-Null
|
|
105
|
+
try {
|
|
106
|
+
Invoke-WebRequest -Uri $gitUrl -OutFile $gitZip -UseBasicParsing
|
|
107
|
+
$actual = (Get-FileHash -Path $gitZip -Algorithm SHA256).Hash.ToLower()
|
|
108
|
+
if ($actual -ne $gitSha) {
|
|
109
|
+
throw "downloaded Git failed its integrity check (expected '$gitSha', got '$actual')"
|
|
110
|
+
}
|
|
111
|
+
Expand-Archive -Path $gitZip -DestinationPath $gitRoot -Force
|
|
112
|
+
} catch {
|
|
113
|
+
throw "Couldn't set up Git ($($_.Exception.Message)). Check your internet connection, then run this again - it's safe to re-run."
|
|
114
|
+
}
|
|
115
|
+
$GitCmdDir = $portableGitCmd
|
|
116
|
+
if (-not (Test-Path (Join-Path $GitCmdDir 'git.exe'))) { throw "Git was downloaded but git.exe wasn't found at $GitCmdDir." }
|
|
117
|
+
Say "Git is ready."
|
|
82
118
|
}
|
|
83
119
|
|
|
84
120
|
# --- Launch Kindling (clean-runtime: absolute node when portable, else npx on PATH) -----------
|
|
@@ -91,6 +127,9 @@ Say "Starting Kindling..."
|
|
|
91
127
|
$launchDir = Join-Path $env:LOCALAPPDATA 'kindling'
|
|
92
128
|
New-Item -ItemType Directory -Force -Path $launchDir | Out-Null
|
|
93
129
|
Set-Location -LiteralPath $launchDir
|
|
130
|
+
# Portable Git on PATH (the engine spawns `git` by name to scaffold the project's history). Applies
|
|
131
|
+
# to both launch branches; the provisioned Node dir is added inside the portable-Node branch below.
|
|
132
|
+
if ($GitCmdDir) { $env:Path = "$GitCmdDir;$env:Path" }
|
|
94
133
|
if ($null -eq $NodeExe) {
|
|
95
134
|
& npx -y "@aiviatic/kindling@$KindlingVersion"
|
|
96
135
|
} else {
|
package/bootstrap/setup.sh
CHANGED
|
@@ -7,108 +7,80 @@ import {
|
|
|
7
7
|
expandTilde
|
|
8
8
|
} from "./chunk-OU3WSB6B.js";
|
|
9
9
|
|
|
10
|
-
// engine/emitter.ts
|
|
11
|
-
var EngineEmitter = class {
|
|
12
|
-
log = [];
|
|
13
|
-
listeners = /* @__PURE__ */ new Set();
|
|
14
|
-
/** Subscribe to events. Returns an unsubscribe function. */
|
|
15
|
-
on(listener) {
|
|
16
|
-
this.listeners.add(listener);
|
|
17
|
-
return () => {
|
|
18
|
-
this.listeners.delete(listener);
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
/** Emit an event: freeze it, append to the log, then notify listeners in subscription order. */
|
|
22
|
-
emit(event) {
|
|
23
|
-
const frozen = Object.freeze({ ...event });
|
|
24
|
-
this.log.push(frozen);
|
|
25
|
-
for (const listener of [...this.listeners]) {
|
|
26
|
-
try {
|
|
27
|
-
listener(frozen);
|
|
28
|
-
} catch {
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
/** A snapshot of the append-only event log, in emission order. */
|
|
33
|
-
events() {
|
|
34
|
-
return [...this.log];
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
10
|
// engine/pins.ts
|
|
39
11
|
var pins = Object.freeze({
|
|
40
12
|
node: "24.16.0",
|
|
41
13
|
bmad: "6.9.0",
|
|
42
14
|
// frozen for the Cohort #1 cycle (matches this repo's BMad install; tools + install flags verified vs the real 6.9.0 CLI 2026-07-02); bump between cohorts
|
|
43
|
-
kindling: "0.1.
|
|
15
|
+
kindling: "0.1.2"
|
|
44
16
|
});
|
|
45
17
|
|
|
46
18
|
// engine/messages.ts
|
|
47
19
|
var stepMessages = {
|
|
48
|
-
[StepId.ProvisionNode]: "Setting up Node
|
|
49
|
-
[StepId.ProvisionGit]: "Setting up Git
|
|
50
|
-
[StepId.ProvisionXcodeClt]: "macOS is installing some developer tools. A system dialog popped up
|
|
20
|
+
[StepId.ProvisionNode]: "Setting up Node - the engine your project runs on.",
|
|
21
|
+
[StepId.ProvisionGit]: "Setting up Git - it keeps the history of your project safe.",
|
|
22
|
+
[StepId.ProvisionXcodeClt]: "macOS is installing some developer tools. A system dialog popped up: click Install. This is completely normal and usually takes about 5 minutes. You can grab a coffee.",
|
|
51
23
|
[StepId.ScaffoldGitInit]: "Creating your project folder and starting its history.",
|
|
52
|
-
[StepId.InstallBmad]: "Installing BMad
|
|
24
|
+
[StepId.InstallBmad]: "Installing BMad - the toolkit that powers your project. This is a sizeable download, so it can take a couple of minutes. Nothing is stuck; hang tight.",
|
|
53
25
|
[StepId.InstallAgentCli]: "Installing your AI coding assistant so it\u2019s ready to run right after setup.",
|
|
54
26
|
[StepId.FinalizeSelfCheck]: "Double-checking everything is in place."
|
|
55
27
|
};
|
|
56
28
|
var agentCliMessages = {
|
|
57
29
|
working: (name) => `Installing ${name} so you can start right away.`,
|
|
58
30
|
done: (name) => `${name} is installed and ready to run.`,
|
|
59
|
-
skipped: (name) => `${name} is already installed
|
|
60
|
-
failed: (name) => `${name} didn\u2019t finish installing
|
|
31
|
+
skipped: (name) => `${name} is already installed, reusing it.`,
|
|
32
|
+
failed: (name) => `${name} didn\u2019t finish installing - your project is still set up and ready. You can press Retry, or install it yourself later.`,
|
|
61
33
|
manualInstall: (pkg) => `To install it yourself later, run: npm install -g ${pkg}`
|
|
62
34
|
};
|
|
63
35
|
var scaffoldMessages = {
|
|
64
36
|
done: "Your project folder is ready.",
|
|
65
|
-
skipped: "Project already set up
|
|
66
|
-
blocked: "This folder already has files in it. Kindling won\u2019t change anything without your OK
|
|
37
|
+
skipped: "Project already set up, nothing to do.",
|
|
38
|
+
blocked: "This folder already has files in it. Kindling won\u2019t change anything without your OK, pick an empty folder, or confirm before continuing.",
|
|
67
39
|
failed: "Setting up your project folder ran into a problem. Check the details, then press Retry."
|
|
68
40
|
};
|
|
69
41
|
var provisionMessages = {
|
|
70
|
-
nodePresent: "Node is already installed
|
|
71
|
-
nodeQueued: "Node needs setting up
|
|
72
|
-
gitPresent: "Git is already installed
|
|
73
|
-
gitQueued: "Git needs setting up
|
|
42
|
+
nodePresent: "Node is already installed, reusing it.",
|
|
43
|
+
nodeQueued: "Node needs setting up - the engine your project runs on.",
|
|
44
|
+
gitPresent: "Git is already installed, reusing it.",
|
|
45
|
+
gitQueued: "Git needs setting up - it keeps the history of your project.",
|
|
74
46
|
gitInstalled: "Git is set up.",
|
|
75
|
-
xcodeWaiting: "Still installing developer tools\u2026 the macOS dialog is doing its thing. This can take a few minutes
|
|
76
|
-
xcodeDone: "Developer tools are ready
|
|
47
|
+
xcodeWaiting: "Still installing developer tools\u2026 the macOS dialog is doing its thing. This can take a few minutes, hang tight, nothing is stuck.",
|
|
48
|
+
xcodeDone: "Developer tools are ready - Git is set up.",
|
|
77
49
|
xcodeTimeout: "The developer-tools install is taking longer than expected. If the macOS dialog is still open, let it finish, then press Retry.",
|
|
78
50
|
xcodeInstallFailed: "We couldn\u2019t start the developer-tools install. Make sure you\u2019re connected, then press Retry.",
|
|
79
|
-
gitInstallFailed: "Setting up Git ran into a problem
|
|
51
|
+
gitInstallFailed: "Setting up Git ran into a problem, it may need permission to install. Check the details, then press Retry."
|
|
80
52
|
};
|
|
81
53
|
var selfCheckMessages = {
|
|
82
|
-
done: "Everything checks out
|
|
83
|
-
failed: "Some checks didn\u2019t pass
|
|
54
|
+
done: "Everything checks out, you\u2019re ready.",
|
|
55
|
+
failed: "Some checks didn\u2019t pass, see the readiness details."
|
|
84
56
|
};
|
|
85
57
|
var installMessages = {
|
|
86
|
-
notPinned: "BMad isn\u2019t pinned to a version yet
|
|
58
|
+
notPinned: "BMad isn\u2019t pinned to a version yet, set the cohort version before installing.",
|
|
87
59
|
done: (version) => `BMad ${version} installed.`
|
|
88
60
|
};
|
|
89
61
|
var errorMessages = {
|
|
90
|
-
[ErrorCode.ExecFailed]: "Something needs a quick fix
|
|
62
|
+
[ErrorCode.ExecFailed]: "Something needs a quick fix: a step did not finish. Check the next step below, then press Retry.",
|
|
91
63
|
[ErrorCode.NetworkLost]: "We lost the connection. Reconnect to the internet, then press Retry.",
|
|
92
|
-
[ErrorCode.BmadInstallFailed]: "BMad didn\u2019t finish installing. The details are below
|
|
93
|
-
[ErrorCode.AgentCliInstallFailed]: "Your AI coding assistant didn\u2019t finish installing
|
|
94
|
-
[ErrorCode.ExecPolicyBlocked]: "Windows blocked the script because it\u2019s unsigned
|
|
95
|
-
[ErrorCode.SmartScreenBlocked]: "Windows SmartScreen (or your antivirus) paused the script
|
|
64
|
+
[ErrorCode.BmadInstallFailed]: "BMad didn\u2019t finish installing. The details are below, press Retry.",
|
|
65
|
+
[ErrorCode.AgentCliInstallFailed]: "Your AI coding assistant didn\u2019t finish installing - your project is still ready. Press Retry, or install it yourself later.",
|
|
66
|
+
[ErrorCode.ExecPolicyBlocked]: "Windows blocked the script because it\u2019s unsigned, that\u2019s expected, safe, and reversible.",
|
|
67
|
+
[ErrorCode.SmartScreenBlocked]: "Windows SmartScreen (or your antivirus) paused the script, that\u2019s expected, safe, and reversible.",
|
|
96
68
|
[ErrorCode.ProjectConflict]: "That folder already has files in it that Kindling didn\u2019t create."
|
|
97
69
|
};
|
|
98
70
|
var recoveryGuidance = {
|
|
99
71
|
[ErrorCode.ExecFailed]: {
|
|
100
72
|
title: "Something needs a quick fix.",
|
|
101
|
-
detail: "A step didn\u2019t finish. This usually clears up on a second try
|
|
73
|
+
detail: "A step didn\u2019t finish. This usually clears up on a second try, press Retry.",
|
|
102
74
|
recovery: "retry"
|
|
103
75
|
},
|
|
104
76
|
[ErrorCode.NetworkLost]: {
|
|
105
77
|
title: "We lost the connection.",
|
|
106
|
-
detail: "A download was interrupted. Reconnect to the internet, then press Retry
|
|
78
|
+
detail: "A download was interrupted. Reconnect to the internet, then press Retry, Kindling resumes where it left off.",
|
|
107
79
|
recovery: "retry"
|
|
108
80
|
},
|
|
109
81
|
[ErrorCode.BmadInstallFailed]: {
|
|
110
82
|
title: "BMad didn\u2019t install.",
|
|
111
|
-
detail: "The install step didn\u2019t finish. This is usually temporary
|
|
83
|
+
detail: "The install step didn\u2019t finish. This is usually temporary, press Retry. The step details below show what happened.",
|
|
112
84
|
recovery: "retry"
|
|
113
85
|
},
|
|
114
86
|
[ErrorCode.AgentCliInstallFailed]: {
|
|
@@ -116,18 +88,18 @@ var recoveryGuidance = {
|
|
|
116
88
|
// concrete, copy-pasteable `npm install -g <package>` line ships in the failed step's own
|
|
117
89
|
// message (agentCliMessages.manualInstall) rather than in this static, error-code-keyed entry.
|
|
118
90
|
title: "Your AI assistant didn\u2019t install.",
|
|
119
|
-
detail: "Your project is set up and ready either way
|
|
91
|
+
detail: "Your project is set up and ready either way, this step is optional. Press Retry to try again, or install it yourself later using the command shown in the step details below.",
|
|
120
92
|
recovery: "retry"
|
|
121
93
|
},
|
|
122
94
|
[ErrorCode.ExecPolicyBlocked]: {
|
|
123
95
|
title: "Something needs a quick fix.",
|
|
124
|
-
detail: "Windows blocked the script because it\u2019s unsigned
|
|
96
|
+
detail: "Windows blocked the script because it\u2019s unsigned, that\u2019s expected, and it\u2019s safe and reversible. Run this one line in PowerShell, then come back and press Retry:",
|
|
125
97
|
fixCommand: "Set-ExecutionPolicy -Scope Process Bypass",
|
|
126
98
|
recovery: "retry"
|
|
127
99
|
},
|
|
128
100
|
[ErrorCode.SmartScreenBlocked]: {
|
|
129
101
|
title: "Windows asked you to confirm.",
|
|
130
|
-
detail: "SmartScreen or your antivirus paused the script
|
|
102
|
+
detail: "SmartScreen or your antivirus paused the script, this is expected and safe. Choose \u201CMore info\u201D, then \u201CRun anyway\u201D, and press Retry. Nothing was changed on your computer.",
|
|
131
103
|
recovery: "retry"
|
|
132
104
|
},
|
|
133
105
|
[ErrorCode.ProjectConflict]: {
|
|
@@ -137,6 +109,34 @@ var recoveryGuidance = {
|
|
|
137
109
|
}
|
|
138
110
|
};
|
|
139
111
|
|
|
112
|
+
// engine/emitter.ts
|
|
113
|
+
var EngineEmitter = class {
|
|
114
|
+
log = [];
|
|
115
|
+
listeners = /* @__PURE__ */ new Set();
|
|
116
|
+
/** Subscribe to events. Returns an unsubscribe function. */
|
|
117
|
+
on(listener) {
|
|
118
|
+
this.listeners.add(listener);
|
|
119
|
+
return () => {
|
|
120
|
+
this.listeners.delete(listener);
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/** Emit an event: freeze it, append to the log, then notify listeners in subscription order. */
|
|
124
|
+
emit(event) {
|
|
125
|
+
const frozen = Object.freeze({ ...event });
|
|
126
|
+
this.log.push(frozen);
|
|
127
|
+
for (const listener of [...this.listeners]) {
|
|
128
|
+
try {
|
|
129
|
+
listener(frozen);
|
|
130
|
+
} catch {
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/** A snapshot of the append-only event log, in emission order. */
|
|
135
|
+
events() {
|
|
136
|
+
return [...this.log];
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
140
|
// engine/orchestrate/scaffold.ts
|
|
141
141
|
import { mkdir, readdir, writeFile } from "fs/promises";
|
|
142
142
|
import { join } from "path";
|
|
@@ -261,13 +261,29 @@ function composeInstallArgs(config, action = "install") {
|
|
|
261
261
|
return args;
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
+
// engine/orchestrate/launch.ts
|
|
265
|
+
import { dirname, join as join2 } from "path";
|
|
266
|
+
function npxCliPath(nodeExe) {
|
|
267
|
+
return join2(dirname(nodeExe), "node_modules", "npm", "bin", "npx-cli.js");
|
|
268
|
+
}
|
|
269
|
+
function npmCliPath(nodeExe) {
|
|
270
|
+
return join2(dirname(nodeExe), "node_modules", "npm", "bin", "npm-cli.js");
|
|
271
|
+
}
|
|
272
|
+
function composeLaunchCommand({ nodeExe, kindlingVersion }) {
|
|
273
|
+
const spec = `@aiviatic/kindling@${kindlingVersion}`;
|
|
274
|
+
if (nodeExe === null) {
|
|
275
|
+
return { cmd: "npx", args: ["-y", spec] };
|
|
276
|
+
}
|
|
277
|
+
return { cmd: nodeExe, args: [npxCliPath(nodeExe), "-y", spec] };
|
|
278
|
+
}
|
|
279
|
+
|
|
264
280
|
// engine/orchestrate/bmad-install.ts
|
|
265
281
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
266
282
|
import { stat } from "fs/promises";
|
|
267
|
-
import { join as
|
|
283
|
+
import { join as join3 } from "path";
|
|
268
284
|
async function defaultBmadInstalled(projectDir) {
|
|
269
285
|
try {
|
|
270
|
-
return (await stat(
|
|
286
|
+
return (await stat(join3(projectDir, "_bmad"))).isDirectory();
|
|
271
287
|
} catch {
|
|
272
288
|
return false;
|
|
273
289
|
}
|
|
@@ -304,14 +320,30 @@ async function runBmadInstall(opts) {
|
|
|
304
320
|
const alreadyInstalled = opts.bmadAlreadyInstalled ?? defaultBmadInstalled;
|
|
305
321
|
action = await alreadyInstalled(opts.config.projectDir) ? "update" : "install";
|
|
306
322
|
}
|
|
307
|
-
const args = [
|
|
323
|
+
const args = [
|
|
324
|
+
...opts.npxPrefixArgs ?? [],
|
|
325
|
+
`bmad-method@${versionTag}`,
|
|
326
|
+
...composeInstallArgs(opts.config, action)
|
|
327
|
+
];
|
|
308
328
|
result = await exec2(npx, args);
|
|
309
329
|
} catch (err) {
|
|
310
|
-
|
|
330
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
331
|
+
emit(
|
|
332
|
+
Status.Failed,
|
|
333
|
+
`${errorMessages[ErrorCode.BmadInstallFailed]} (${detail})`,
|
|
334
|
+
"error",
|
|
335
|
+
ErrorCode.BmadInstallFailed
|
|
336
|
+
);
|
|
311
337
|
throw err;
|
|
312
338
|
}
|
|
313
339
|
if (result.code !== 0) {
|
|
314
|
-
|
|
340
|
+
const raw = (result.stderr.trim() ? result.stderr : result.stdout).trim();
|
|
341
|
+
const detail = raw.slice(-600).trim();
|
|
342
|
+
const humanMessage = detail ? `${errorMessages[ErrorCode.BmadInstallFailed]}
|
|
343
|
+
|
|
344
|
+
Details:
|
|
345
|
+
${detail}` : errorMessages[ErrorCode.BmadInstallFailed];
|
|
346
|
+
emit(Status.Failed, humanMessage, "error", ErrorCode.BmadInstallFailed);
|
|
315
347
|
return { ok: false, bmadVersion: versionTag };
|
|
316
348
|
}
|
|
317
349
|
emit(Status.Done, installMessages.done(versionTag));
|
|
@@ -373,16 +405,32 @@ async function installAgentCli(opts) {
|
|
|
373
405
|
emit(Status.Working, agentCliMessages.working(name));
|
|
374
406
|
const failMessage = `${agentCliMessages.failed(name)} ${agentCliMessages.manualInstall(pkg)}`;
|
|
375
407
|
try {
|
|
376
|
-
const result = await exec2(npm, ["install", "-g", pkg]);
|
|
408
|
+
const result = await exec2(npm, [...opts.npmPrefixArgs ?? [], "install", "-g", pkg]);
|
|
377
409
|
if (result.code === 0) {
|
|
378
410
|
emit(Status.Done, agentCliMessages.done(name));
|
|
379
411
|
installed.push(id);
|
|
380
412
|
} else {
|
|
381
|
-
|
|
413
|
+
const raw = (result.stderr.trim() ? result.stderr : result.stdout).trim();
|
|
414
|
+
const detail = raw.slice(-600).trim();
|
|
415
|
+
emit(
|
|
416
|
+
Status.Failed,
|
|
417
|
+
detail ? `${failMessage}
|
|
418
|
+
|
|
419
|
+
Details:
|
|
420
|
+
${detail}` : failMessage,
|
|
421
|
+
"error",
|
|
422
|
+
ErrorCode.AgentCliInstallFailed
|
|
423
|
+
);
|
|
382
424
|
failed.push(id);
|
|
383
425
|
}
|
|
384
|
-
} catch {
|
|
385
|
-
|
|
426
|
+
} catch (err) {
|
|
427
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
428
|
+
emit(
|
|
429
|
+
Status.Failed,
|
|
430
|
+
`${failMessage} (${detail})`,
|
|
431
|
+
"error",
|
|
432
|
+
ErrorCode.AgentCliInstallFailed
|
|
433
|
+
);
|
|
386
434
|
failed.push(id);
|
|
387
435
|
}
|
|
388
436
|
}
|
|
@@ -391,11 +439,11 @@ async function installAgentCli(opts) {
|
|
|
391
439
|
|
|
392
440
|
// engine/bmad-manifest.ts
|
|
393
441
|
import { readFile } from "fs/promises";
|
|
394
|
-
import { join as
|
|
442
|
+
import { join as join4 } from "path";
|
|
395
443
|
import { load } from "js-yaml";
|
|
396
444
|
async function readInstalledBmadVersion(projectDir) {
|
|
397
445
|
try {
|
|
398
|
-
const raw = await readFile(
|
|
446
|
+
const raw = await readFile(join4(projectDir, "_bmad", "_config", "manifest.yaml"), "utf8");
|
|
399
447
|
const doc = load(raw);
|
|
400
448
|
if (typeof doc !== "object" || doc === null) return null;
|
|
401
449
|
const installation = doc.installation;
|
|
@@ -625,14 +673,14 @@ async function provisionGitUnix(opts) {
|
|
|
625
673
|
|
|
626
674
|
// engine/log.ts
|
|
627
675
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
628
|
-
import { join as
|
|
676
|
+
import { join as join5 } from "path";
|
|
629
677
|
import { homedir } from "os";
|
|
630
678
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
631
679
|
function defaultLogDir() {
|
|
632
680
|
if (process.platform === "win32" && process.env.LOCALAPPDATA) {
|
|
633
|
-
return
|
|
681
|
+
return join5(process.env.LOCALAPPDATA, "kindling", "logs");
|
|
634
682
|
}
|
|
635
|
-
return
|
|
683
|
+
return join5(homedir(), ".kindling", "logs");
|
|
636
684
|
}
|
|
637
685
|
function render(entry, timestamp) {
|
|
638
686
|
const lines = [
|
|
@@ -644,7 +692,7 @@ function render(entry, timestamp) {
|
|
|
644
692
|
entry.error,
|
|
645
693
|
``,
|
|
646
694
|
`Event log:`,
|
|
647
|
-
...entry.events.map((e) => ` [${e.status}] ${e.step}
|
|
695
|
+
...entry.events.map((e) => ` [${e.status}] ${e.step} - ${e.humanMessage}`),
|
|
648
696
|
``
|
|
649
697
|
];
|
|
650
698
|
return lines.join("\n");
|
|
@@ -655,7 +703,7 @@ async function writeFailureLog(entry, opts = {}) {
|
|
|
655
703
|
const safeStamp = timestamp.replace(/[:.]/g, "-");
|
|
656
704
|
const suffix = randomUUID7().slice(0, 8);
|
|
657
705
|
await mkdir2(dir, { recursive: true });
|
|
658
|
-
const path =
|
|
706
|
+
const path = join5(dir, `kindling-report-${safeStamp}-${suffix}.log`);
|
|
659
707
|
await writeFile2(path, render(entry, timestamp));
|
|
660
708
|
return path;
|
|
661
709
|
}
|
|
@@ -733,7 +781,11 @@ var Engine = class {
|
|
|
733
781
|
{
|
|
734
782
|
id: StepId.InstallBmad,
|
|
735
783
|
run: async () => {
|
|
736
|
-
const result = await this.deps.runBmadInstall({
|
|
784
|
+
const result = await this.deps.runBmadInstall({
|
|
785
|
+
config: this.config,
|
|
786
|
+
emitter: this.emitter,
|
|
787
|
+
...this.deps.platform === "win32" ? { npxCommand: process.execPath, npxPrefixArgs: [npxCliPath(process.execPath)] } : {}
|
|
788
|
+
});
|
|
737
789
|
this.bmadInstalled = result.ok;
|
|
738
790
|
return result.ok;
|
|
739
791
|
}
|
|
@@ -748,7 +800,11 @@ var Engine = class {
|
|
|
748
800
|
// CLI-presence guidance (retry() skips the already-completed self-check). See deferred-work.md.
|
|
749
801
|
id: StepId.InstallAgentCli,
|
|
750
802
|
run: async () => {
|
|
751
|
-
await this.deps.installAgentCli({
|
|
803
|
+
await this.deps.installAgentCli({
|
|
804
|
+
config: this.config,
|
|
805
|
+
emitter: this.emitter,
|
|
806
|
+
...this.deps.platform === "win32" ? { npmCommand: process.execPath, npmPrefixArgs: [npmCliPath(process.execPath)] } : {}
|
|
807
|
+
});
|
|
752
808
|
return true;
|
|
753
809
|
}
|
|
754
810
|
},
|
|
@@ -859,14 +915,16 @@ var Engine = class {
|
|
|
859
915
|
};
|
|
860
916
|
|
|
861
917
|
export {
|
|
862
|
-
EngineEmitter,
|
|
863
918
|
pins,
|
|
864
919
|
stepMessages,
|
|
865
920
|
provisionMessages,
|
|
866
921
|
errorMessages,
|
|
867
922
|
recoveryGuidance,
|
|
923
|
+
EngineEmitter,
|
|
868
924
|
scaffold,
|
|
869
925
|
composeInstallArgs,
|
|
926
|
+
npxCliPath,
|
|
927
|
+
composeLaunchCommand,
|
|
870
928
|
defaultBmadInstalled,
|
|
871
929
|
runBmadInstall,
|
|
872
930
|
AGENT_CLI_TABLE,
|
|
@@ -887,4 +945,4 @@ export {
|
|
|
887
945
|
writeFailureLog,
|
|
888
946
|
Engine
|
|
889
947
|
};
|
|
890
|
-
//# sourceMappingURL=chunk-
|
|
948
|
+
//# sourceMappingURL=chunk-DZ2RR3SP.js.map
|