@really-knows-ai/foundry 3.2.0 → 3.2.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.
|
@@ -131,6 +131,54 @@ function runConfigBootstrap(worktree, pkgRoot) {
|
|
|
131
131
|
return changed || guideWritten;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
function runPluginBootstrap(worktree, pkgRoot) {
|
|
135
|
+
// Skip if FOUNDRY_SKIP_BOOTSTRAP is set to prevent infinite recursion
|
|
136
|
+
// when this plugin spawns `opencode models` as a child process.
|
|
137
|
+
if (process.env.FOUNDRY_SKIP_BOOTSTRAP === '1') return false;
|
|
138
|
+
try {
|
|
139
|
+
return runConfigBootstrap(worktree, pkgRoot);
|
|
140
|
+
} catch (err) {
|
|
141
|
+
console.error('Foundry bootstrap error:', err.message);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const defaultSleep = ms => new Promise(resolve => { setTimeout(resolve, ms); });
|
|
147
|
+
|
|
148
|
+
function resolveOpt(opts, key, fallback) {
|
|
149
|
+
return (opts && opts[key] !== undefined) ? opts[key] : fallback;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function retryUntilReady(fn, opts) {
|
|
153
|
+
const sleep = resolveOpt(opts, 'sleep', defaultSleep);
|
|
154
|
+
const now = resolveOpt(opts, 'now', Date.now);
|
|
155
|
+
const maxMs = resolveOpt(opts, 'maxMs', 30000);
|
|
156
|
+
const deadline = now() + maxMs;
|
|
157
|
+
while (now() < deadline) {
|
|
158
|
+
try {
|
|
159
|
+
await fn();
|
|
160
|
+
return;
|
|
161
|
+
} catch {
|
|
162
|
+
await sleep(500);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function showStartupMessage(needsRestart, directory, client, timerFns) {
|
|
168
|
+
if (!client) return;
|
|
169
|
+
if (needsRestart) {
|
|
170
|
+
await retryUntilReady(() => client.tui.appendPrompt({
|
|
171
|
+
body: { text: 'Foundry initialised. Restart OpenCode so the Foundry agent registers, then switch to it to author and run workflows.' },
|
|
172
|
+
}), timerFns);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (existsSync(path.join(directory, 'foundry'))) {
|
|
176
|
+
await retryUntilReady(() => client.tui.showToast({
|
|
177
|
+
body: { message: 'Foundry is active', variant: 'info' },
|
|
178
|
+
}), timerFns);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
134
182
|
export { buildCyclePromptExtras } from './foundry-tools/helpers.js';
|
|
135
183
|
|
|
136
184
|
function buildTools(createTool, pending) {
|
|
@@ -167,7 +215,7 @@ function getFirstUserWithParts(output) {
|
|
|
167
215
|
return firstUser;
|
|
168
216
|
}
|
|
169
217
|
|
|
170
|
-
export const FoundryPlugin = async ({ directory }) => {
|
|
218
|
+
export const FoundryPlugin = async ({ directory, client }) => {
|
|
171
219
|
// Pending store is per-plugin-instance (shared across all tool invocations).
|
|
172
220
|
const pending = createPendingStore();
|
|
173
221
|
|
|
@@ -181,12 +229,8 @@ export const FoundryPlugin = async ({ directory }) => {
|
|
|
181
229
|
config.skills.paths.push(allSkillsDir);
|
|
182
230
|
}
|
|
183
231
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
restartNeeded = runConfigBootstrap(directory, packageRoot);
|
|
187
|
-
} catch (err) {
|
|
188
|
-
console.error('Foundry bootstrap error:', err.message);
|
|
189
|
-
}
|
|
232
|
+
restartNeeded = runPluginBootstrap(directory, packageRoot);
|
|
233
|
+
await showStartupMessage(restartNeeded, directory, client);
|
|
190
234
|
},
|
|
191
235
|
|
|
192
236
|
'experimental.chat.messages.transform': async (_input, output) => {
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.2.2] - 2026-05-14
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Immediate startup feedback via TUI.** Instead of waiting for the first
|
|
8
|
+
user prompt to inject the Foundry context message, the config hook now
|
|
9
|
+
shows feedback immediately. When a restart is needed, the message is
|
|
10
|
+
appended directly to the prompt bar via `client.tui.appendPrompt`. When
|
|
11
|
+
Foundry is already active, a non-intrusive toast notification confirms
|
|
12
|
+
readiness via `client.tui.showToast`. The `messages.transform` hook
|
|
13
|
+
remains as a fallback for AI context injection.
|
|
14
|
+
- **Injectable timer for startup retry logic.** `retryUntilReady` accepts
|
|
15
|
+
injectable `sleep`, `now`, and `maxMs` functions so tests can control
|
|
16
|
+
timing without real delays. `showStartupMessage` bails early when the
|
|
17
|
+
TUI client is unavailable to avoid hanging in environments without a
|
|
18
|
+
client.
|
|
19
|
+
|
|
20
|
+
## [3.2.1] - 2026-05-14
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **Plugin hangs on startup due to infinite recursion.** The config hook's
|
|
25
|
+
`refreshAgents` call spawns `opencode models` via `execFileSync`. When the
|
|
26
|
+
project directory has the foundry plugin configured, the child process
|
|
27
|
+
loads plugins too, triggering another `opencode models` — infinite
|
|
28
|
+
synchronous recursion that hangs the parent. The plugin now sets
|
|
29
|
+
`FOUNDRY_SKIP_BOOTSTRAP=1` in the child process environment and skips the
|
|
30
|
+
bootstrap in the config hook when that variable is set.
|
|
31
|
+
|
|
3
32
|
## [3.2.0] - 2026-05-14
|
|
4
33
|
|
|
5
34
|
Plugin auto-bootstrapping release. Foundry now ensures the guide agent is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@really-knows-ai/foundry",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.2",
|
|
4
4
|
"description": "A skill-driven framework for governed artefact generation with AI coding tools. Define your own artefact types, laws, and flows — Foundry handles the forge → quench → appraise pipeline with deterministic routing, quality gates, and iterative refinement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/.opencode/plugins/foundry.js",
|