fix: read resources from dist/ to prevent branch-drift in npm-link setups (#314)
* fix: read resources from dist/ to prevent branch-drift in npm-link setups
initResources() reads extensions, prompts, skills, and agents from
src/resources/ — which points into the live working tree when gsd is
installed via npm link. Switching branches in the gsd repo changes
src/resources/ for ALL projects using gsd, causing stale or broken
extensions to be synced to ~/.gsd/agent/ on next launch.
Fix: the build step now copies src/resources/ to dist/resources/.
At runtime, resource-loader.ts and loader.ts prefer dist/resources/
(stable, set at build time) over src/resources/ (live working tree).
Fallback to src/resources/ is preserved for setups without a build.
Also adds npm run dev watch-resources watcher that syncs src/resources/
to dist/resources/ on file changes, running alongside tsc --watch.
* fix: cache prompt templates per session to prevent cross-session invalidation
When two gsd sessions run concurrently, the second session's
initResources() overwrites ~/.gsd/agent/ templates on disk. The first
session then reads a newer template that expects variables its in-memory
code doesn't know about, causing 'template declares {{X}} but no value
was provided' crashes that hang auto-mode indefinitely.
Fix: cache each template on first read. A running session uses the
template versions from when it first loaded them, immune to later
disk overwrites by other sessions.
2026-03-14 18:47:03 +01:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Dev supervisor — runs tsc --watch and watch-resources.js in parallel.
|
|
|
|
|
*
|
|
|
|
|
* Both processes terminate together when either exits or when the parent
|
|
|
|
|
* receives SIGINT/SIGTERM. This avoids the problem with shell backgrounding
|
|
|
|
|
* (`&`) where the watcher can outlive tsc and orphan.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { spawn } from 'node:child_process'
|
|
|
|
|
import { resolve, dirname } from 'node:path'
|
|
|
|
|
import { fileURLToPath } from 'node:url'
|
2026-04-10 20:33:18 -05:00
|
|
|
import { createRequire } from 'node:module'
|
fix: read resources from dist/ to prevent branch-drift in npm-link setups (#314)
* fix: read resources from dist/ to prevent branch-drift in npm-link setups
initResources() reads extensions, prompts, skills, and agents from
src/resources/ — which points into the live working tree when gsd is
installed via npm link. Switching branches in the gsd repo changes
src/resources/ for ALL projects using gsd, causing stale or broken
extensions to be synced to ~/.gsd/agent/ on next launch.
Fix: the build step now copies src/resources/ to dist/resources/.
At runtime, resource-loader.ts and loader.ts prefer dist/resources/
(stable, set at build time) over src/resources/ (live working tree).
Fallback to src/resources/ is preserved for setups without a build.
Also adds npm run dev watch-resources watcher that syncs src/resources/
to dist/resources/ on file changes, running alongside tsc --watch.
* fix: cache prompt templates per session to prevent cross-session invalidation
When two gsd sessions run concurrently, the second session's
initResources() overwrites ~/.gsd/agent/ templates on disk. The first
session then reads a newer template that expects variables its in-memory
code doesn't know about, causing 'template declares {{X}} but no value
was provided' crashes that hang auto-mode indefinitely.
Fix: cache each template on first read. A running session uses the
template versions from when it first loaded them, immune to later
disk overwrites by other sessions.
2026-03-14 18:47:03 +01:00
|
|
|
|
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
|
|
|
const root = resolve(__dirname, '..')
|
2026-04-10 20:33:18 -05:00
|
|
|
const require = createRequire(import.meta.url)
|
|
|
|
|
const tscBin = require.resolve('typescript/bin/tsc')
|
fix: read resources from dist/ to prevent branch-drift in npm-link setups (#314)
* fix: read resources from dist/ to prevent branch-drift in npm-link setups
initResources() reads extensions, prompts, skills, and agents from
src/resources/ — which points into the live working tree when gsd is
installed via npm link. Switching branches in the gsd repo changes
src/resources/ for ALL projects using gsd, causing stale or broken
extensions to be synced to ~/.gsd/agent/ on next launch.
Fix: the build step now copies src/resources/ to dist/resources/.
At runtime, resource-loader.ts and loader.ts prefer dist/resources/
(stable, set at build time) over src/resources/ (live working tree).
Fallback to src/resources/ is preserved for setups without a build.
Also adds npm run dev watch-resources watcher that syncs src/resources/
to dist/resources/ on file changes, running alongside tsc --watch.
* fix: cache prompt templates per session to prevent cross-session invalidation
When two gsd sessions run concurrently, the second session's
initResources() overwrites ~/.gsd/agent/ templates on disk. The first
session then reads a newer template that expects variables its in-memory
code doesn't know about, causing 'template declares {{X}} but no value
was provided' crashes that hang auto-mode indefinitely.
Fix: cache each template on first read. A running session uses the
template versions from when it first loaded them, immune to later
disk overwrites by other sessions.
2026-03-14 18:47:03 +01:00
|
|
|
|
|
|
|
|
const procs = [
|
|
|
|
|
spawn('node', [resolve(__dirname, 'watch-resources.js')], {
|
|
|
|
|
cwd: root, stdio: 'inherit'
|
|
|
|
|
}),
|
2026-04-10 20:33:18 -05:00
|
|
|
spawn(process.execPath, [tscBin, '--watch'], {
|
fix: read resources from dist/ to prevent branch-drift in npm-link setups (#314)
* fix: read resources from dist/ to prevent branch-drift in npm-link setups
initResources() reads extensions, prompts, skills, and agents from
src/resources/ — which points into the live working tree when gsd is
installed via npm link. Switching branches in the gsd repo changes
src/resources/ for ALL projects using gsd, causing stale or broken
extensions to be synced to ~/.gsd/agent/ on next launch.
Fix: the build step now copies src/resources/ to dist/resources/.
At runtime, resource-loader.ts and loader.ts prefer dist/resources/
(stable, set at build time) over src/resources/ (live working tree).
Fallback to src/resources/ is preserved for setups without a build.
Also adds npm run dev watch-resources watcher that syncs src/resources/
to dist/resources/ on file changes, running alongside tsc --watch.
* fix: cache prompt templates per session to prevent cross-session invalidation
When two gsd sessions run concurrently, the second session's
initResources() overwrites ~/.gsd/agent/ templates on disk. The first
session then reads a newer template that expects variables its in-memory
code doesn't know about, causing 'template declares {{X}} but no value
was provided' crashes that hang auto-mode indefinitely.
Fix: cache each template on first read. A running session uses the
template versions from when it first loaded them, immune to later
disk overwrites by other sessions.
2026-03-14 18:47:03 +01:00
|
|
|
cwd: root, stdio: 'inherit'
|
|
|
|
|
})
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
function cleanup() {
|
|
|
|
|
for (const p of procs) {
|
|
|
|
|
try { p.kill() } catch {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If either child exits, kill the other and exit with its code
|
|
|
|
|
for (const p of procs) {
|
|
|
|
|
p.on('exit', (code) => {
|
|
|
|
|
cleanup()
|
|
|
|
|
process.exit(code ?? 1)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Forward signals to children
|
|
|
|
|
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
|
|
|
process.on(sig, () => {
|
|
|
|
|
cleanup()
|
|
|
|
|
process.exit(0)
|
|
|
|
|
})
|
|
|
|
|
}
|