ultra-builder-pro-cli 0.5.1 → 0.5.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/CHANGELOG.md +12 -1
- package/README.md +1 -1
- package/adapters/codex.js +85 -13
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.2] — 2026-07-16
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Preserved Codex hook entry points for already-running tasks across plugin
|
|
15
|
+
refreshes, including cache versions whose adapter file or entire cache
|
|
16
|
+
directory had already disappeared. Historical cache versions are now kept in
|
|
17
|
+
the managed runtime manifest and restored as validated forwarders to the
|
|
18
|
+
current adapter.
|
|
19
|
+
|
|
10
20
|
## [0.5.1] — 2026-07-16
|
|
11
21
|
|
|
12
22
|
### Changed
|
|
@@ -211,7 +221,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
211
221
|
skill manifest, CLI protocol + mapping table; 5 spec validators.
|
|
212
222
|
- **Phase 0 — skeleton**: multi-runtime installer scaffolding.
|
|
213
223
|
|
|
214
|
-
[Unreleased]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.5.
|
|
224
|
+
[Unreleased]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.5.2...HEAD
|
|
225
|
+
[0.5.2]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.5.1...v0.5.2
|
|
215
226
|
[0.5.1]: https://github.com/rocky2431/ultra-builder-pro-cli/compare/v0.5.0...v0.5.1
|
|
216
227
|
[0.5.0]: https://github.com/rocky2431/ultra-builder-pro-cli/releases/tag/v0.5.0
|
|
217
228
|
[0.4.0]: https://github.com/rocky2431/ultra-builder-pro-cli/releases/tag/v0.4.0
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ authoritative `.ultra/state.db`.
|
|
|
8
8
|
|
|
9
9
|
<div align="center">
|
|
10
10
|
|
|
11
|
-
[](./CHANGELOG.md)
|
|
12
12
|
[](#verification)
|
|
13
13
|
[](./LICENSE)
|
|
14
14
|
[](./package.json)
|
package/adapters/codex.js
CHANGED
|
@@ -191,14 +191,53 @@ function pluginCacheRoot(configDir, marketplaceName) {
|
|
|
191
191
|
return path.join(configDir, 'plugins', 'cache', marketplaceName, PLUGIN_NAME);
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
function
|
|
194
|
+
function normalizeHookCacheVersions(versions) {
|
|
195
|
+
const normalized = new Set();
|
|
196
|
+
for (const version of versions) {
|
|
197
|
+
if (typeof version !== 'string'
|
|
198
|
+
|| !/^[A-Za-z0-9][A-Za-z0-9.+_-]*$/.test(version)) {
|
|
199
|
+
throw new Error(`invalid Codex plugin cache version: ${String(version)}`);
|
|
200
|
+
}
|
|
201
|
+
normalized.add(version);
|
|
202
|
+
}
|
|
203
|
+
return [...normalized].sort();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function listKnownHookCacheVersions(configDir, marketplaceName, manifest = null) {
|
|
207
|
+
const root = pluginCacheRoot(configDir, marketplaceName);
|
|
208
|
+
const versions = [];
|
|
209
|
+
if (fs.existsSync(root)) {
|
|
210
|
+
versions.push(...fs.readdirSync(root, { withFileTypes: true })
|
|
211
|
+
.filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
|
|
212
|
+
.map((entry) => entry.name));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (manifest && manifest.source === SOURCE_TAG && manifest.adapter === 'codex') {
|
|
216
|
+
if (manifest.plugin && manifest.plugin.version !== undefined) {
|
|
217
|
+
versions.push(manifest.plugin.version);
|
|
218
|
+
}
|
|
219
|
+
if (manifest.hook_cache_versions !== undefined) {
|
|
220
|
+
if (!Array.isArray(manifest.hook_cache_versions)) {
|
|
221
|
+
throw new Error('invalid Codex runtime manifest hook_cache_versions');
|
|
222
|
+
}
|
|
223
|
+
versions.push(...manifest.hook_cache_versions);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return normalizeHookCacheVersions(versions);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function hookAdaptersForVersions(configDir, marketplaceName, versions) {
|
|
195
230
|
const root = pluginCacheRoot(configDir, marketplaceName);
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
231
|
+
return normalizeHookCacheVersions(versions)
|
|
232
|
+
.map((version) => path.join(root, version, HOOK_ADAPTER_RELATIVE));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function listCachedHookAdapters(configDir, marketplaceName, manifest = null) {
|
|
236
|
+
return hookAdaptersForVersions(
|
|
237
|
+
configDir,
|
|
238
|
+
marketplaceName,
|
|
239
|
+
listKnownHookCacheVersions(configDir, marketplaceName, manifest),
|
|
240
|
+
);
|
|
202
241
|
}
|
|
203
242
|
|
|
204
243
|
function hookForwarder(target) {
|
|
@@ -211,6 +250,20 @@ runpy.run_path(${JSON.stringify(path.resolve(target))}, run_name="__main__")
|
|
|
211
250
|
`;
|
|
212
251
|
}
|
|
213
252
|
|
|
253
|
+
function prepareHookAdapterPath(file) {
|
|
254
|
+
const versionRoot = path.dirname(path.dirname(path.dirname(file)));
|
|
255
|
+
try {
|
|
256
|
+
const stat = fs.lstatSync(versionRoot);
|
|
257
|
+
if (stat.isSymbolicLink()) {
|
|
258
|
+
fs.unlinkSync(versionRoot);
|
|
259
|
+
} else if (!stat.isDirectory()) {
|
|
260
|
+
throw new Error(`Codex plugin cache version is not a directory: ${versionRoot}`);
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error.code !== 'ENOENT') throw error;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
214
267
|
function restoreCachedHookAdapters(previousAdapters, target) {
|
|
215
268
|
const resolvedTarget = path.resolve(target);
|
|
216
269
|
if (!fs.existsSync(resolvedTarget)) {
|
|
@@ -219,6 +272,7 @@ function restoreCachedHookAdapters(previousAdapters, target) {
|
|
|
219
272
|
const restored = [];
|
|
220
273
|
for (const previous of previousAdapters) {
|
|
221
274
|
if (path.resolve(previous) === resolvedTarget || fs.existsSync(previous)) continue;
|
|
275
|
+
prepareHookAdapterPath(previous);
|
|
222
276
|
writeAtomic(previous, hookForwarder(resolvedTarget));
|
|
223
277
|
restored.push(previous);
|
|
224
278
|
}
|
|
@@ -239,6 +293,7 @@ function writeRuntimeManifest(configDir, data) {
|
|
|
239
293
|
plugin: data.plugin,
|
|
240
294
|
marketplace: data.marketplace,
|
|
241
295
|
agents: data.agents,
|
|
296
|
+
hook_cache_versions: data.hookCacheVersions,
|
|
242
297
|
}, null, 2) + '\n');
|
|
243
298
|
return file;
|
|
244
299
|
}
|
|
@@ -250,20 +305,25 @@ function install(ctx = {}) {
|
|
|
250
305
|
const marketplaceFile = resolveMarketplaceFile(ctx);
|
|
251
306
|
ensureDir(configDir);
|
|
252
307
|
|
|
308
|
+
const previousManifest = readRuntimeManifest(configDir);
|
|
253
309
|
const legacy = cleanupLegacyConfig(configDir);
|
|
254
310
|
const plugin = buildPlugin({ repoRoot, pluginRoot });
|
|
255
311
|
const agents = installAgents({ repoRoot, configDir });
|
|
256
312
|
const marketplace = upsertMarketplace(marketplaceFile);
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
marketplace
|
|
260
|
-
|
|
261
|
-
|
|
313
|
+
const previousVersions = listKnownHookCacheVersions(
|
|
314
|
+
configDir,
|
|
315
|
+
marketplace.name,
|
|
316
|
+
previousManifest,
|
|
317
|
+
);
|
|
262
318
|
|
|
263
319
|
let registration = null;
|
|
264
320
|
let hookCompatibility = null;
|
|
265
321
|
if (shouldRunPluginCli(ctx)) {
|
|
266
|
-
const previousAdapters =
|
|
322
|
+
const previousAdapters = hookAdaptersForVersions(
|
|
323
|
+
configDir,
|
|
324
|
+
marketplace.name,
|
|
325
|
+
previousVersions,
|
|
326
|
+
);
|
|
267
327
|
try {
|
|
268
328
|
registration = runPluginCli('add', marketplace.name, ctx);
|
|
269
329
|
} catch (registrationError) {
|
|
@@ -285,6 +345,16 @@ function install(ctx = {}) {
|
|
|
285
345
|
currentHookAdapter(configDir, marketplace.name, plugin),
|
|
286
346
|
);
|
|
287
347
|
}
|
|
348
|
+
const hookCacheVersions = normalizeHookCacheVersions([
|
|
349
|
+
...previousVersions,
|
|
350
|
+
plugin.version,
|
|
351
|
+
]);
|
|
352
|
+
const manifestFile = writeRuntimeManifest(configDir, {
|
|
353
|
+
plugin: { root: plugin.root, version: plugin.version },
|
|
354
|
+
marketplace: { file: marketplace.file, name: marketplace.name },
|
|
355
|
+
agents: agents.installed,
|
|
356
|
+
hookCacheVersions,
|
|
357
|
+
});
|
|
288
358
|
|
|
289
359
|
return {
|
|
290
360
|
target: configDir,
|
|
@@ -379,7 +449,9 @@ module.exports = {
|
|
|
379
449
|
removeMarketplaceEntry,
|
|
380
450
|
runPluginCli,
|
|
381
451
|
pluginCacheRoot,
|
|
452
|
+
listKnownHookCacheVersions,
|
|
382
453
|
listCachedHookAdapters,
|
|
454
|
+
prepareHookAdapterPath,
|
|
383
455
|
restoreCachedHookAdapters,
|
|
384
456
|
},
|
|
385
457
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ultra-builder-pro-cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Multi-runtime installer for the Ultra Builder Pro agent engineering system — deploys commands, agents, skills, hooks, and MCP server to Claude Code, OpenCode, Codex CLI, and Gemini CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ultra-builder-pro-cli": "bin/install.js",
|