@shawnstack/quickforge 1.7.8 → 1.7.9

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.
@@ -305,7 +305,9 @@ async function fetchHealth(timeoutMs = 800) {
305
305
  }
306
306
  }
307
307
 
308
- async function waitForHealth({ expectedPid = null, previousBootId = null, requireChanged = false, timeoutMs = 15000 } = {}) {
308
+ const STARTUP_HEALTH_TIMEOUT_MS = 300000
309
+
310
+ async function waitForHealth({ expectedPid = null, previousBootId = null, requireChanged = false, timeoutMs = STARTUP_HEALTH_TIMEOUT_MS } = {}) {
309
311
  const deadline = Date.now() + timeoutMs
310
312
  while (Date.now() < deadline) {
311
313
  const health = await fetchHealth()
@@ -314,6 +316,13 @@ async function waitForHealth({ expectedPid = null, previousBootId = null, requir
314
316
  const bootChanged = !requireChanged || !previousBootId || health.bootId !== previousBootId
315
317
  if (pidMatches && bootChanged) return health
316
318
  }
319
+ if (expectedPid && !isProcessRunning(expectedPid)) {
320
+ // The spawned server is gone. Give the async 'exit' event a moment to
321
+ // dispatch so the caller can report the real exit code/signal instead
322
+ // of a generic timeout.
323
+ await sleep(300)
324
+ return null
325
+ }
317
326
  await sleep(300)
318
327
  }
319
328
  return null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shawnstack/quickforge",
3
- "version": "1.7.8",
3
+ "version": "1.7.9",
4
4
  "description": "AI chat application with Agent access modes for local workspace tools. React + Vite + Tailwind CSS frontend, local Node.js storage server.",
5
5
  "keywords": [
6
6
  "ai",
@@ -13,6 +13,17 @@ function sleep(ms) {
13
13
  return new Promise((resolve) => setTimeout(resolve, ms))
14
14
  }
15
15
 
16
+ const STARTUP_HEALTH_TIMEOUT_MS = 300000
17
+
18
+ function isProcessRunning(pid) {
19
+ try {
20
+ process.kill(pid, 0)
21
+ return true
22
+ } catch {
23
+ return false
24
+ }
25
+ }
26
+
16
27
  function normalizeHost(host) {
17
28
  return host || '127.0.0.1'
18
29
  }
@@ -135,12 +146,20 @@ export async function checkQuickForgeHealth(options = {}) {
135
146
  }
136
147
 
137
148
  async function waitForQuickForge(options = {}) {
138
- const timeoutMs = options.timeoutMs || 15000
149
+ const timeoutMs = options.timeoutMs || STARTUP_HEALTH_TIMEOUT_MS
139
150
  const deadline = Date.now() + timeoutMs
151
+ const expectedPid = options.expectedPid || null
140
152
 
141
153
  while (Date.now() < deadline) {
142
154
  const health = await checkQuickForgeHealth(options)
143
155
  if (health) return health
156
+ if (expectedPid && !isProcessRunning(expectedPid)) {
157
+ // The spawned server exited. Give the async 'exit' event a moment to
158
+ // dispatch so startQuickForge can report the real exit code/signal
159
+ // instead of a generic timeout.
160
+ await sleep(300)
161
+ return null
162
+ }
144
163
  await sleep(options.pollIntervalMs || 300)
145
164
  }
146
165
 
@@ -213,7 +232,7 @@ export async function startQuickForge(options = {}) {
213
232
  child.once('error', reject)
214
233
  })
215
234
 
216
- const health = await waitForQuickForge(options)
235
+ const health = await waitForQuickForge({ ...options, expectedPid: child.pid })
217
236
  if (!health) {
218
237
  if (!child.killed && exitInfo === null) {
219
238
  try {