openclaw/scripts/generate-native-session-catalogs.mjs
Peter Steinberger 64bf824613
feat(onboarding): require explicit AI provider selection (#139675)
* feat(onboarding): require explicit AI provider selection

Worked on by:
- @steipete

Co-authored-by: steipete <58493+steipete@users.noreply.github.com>

* feat(onboarding): require explicit AI provider selection

Keep detection passive and route native and guided CLI setup through an explicit
provider choice. Include the official install catalog and local custom endpoints
in the shared setup flow, preserve selected runtimes and installer-owned facts,
and initialize native conversation discovery through its configuration owner.

Make skipped onboarding prepare a resumable, owner-fenced baseline. Preserve
existing authored discovery preferences and the named legacy upgrade contract.

* fix(onboarding): complete managed provider activation

Carry approved installation facts through provider discovery, verification,
and final selection without replacing the running Gateway inventory. Compare
authored configuration separately from materialized runtime defaults and bind
the exact provider artifact before and after its connection test.

Keep preparation cancellable at client prompts, honor pending expiry, and
protect credential and configuration persistence together at the final commit.

* fix(onboarding): honor discovery opt-outs in validation

Treat first-write native catalog preferences as privacy settings without
suppressing diagnostics for explicit plugin usage. Keep the existing warning
deduplication contract across subsequent writes and reads.

Remove inert native fallback state and preserve explicit selection, activation
receipt ownership, and unrelated config fields in the native flow fixtures.

* fix(onboarding): complete native validation coverage

Apply canonical formatting to the onboarding view and keep the localization
inventory test anchored to visible consent copy. Pass the existing fixture
model explicitly at both configured-agent response call sites.

* fix(onboarding): preserve bound conversations with discovery disabled

---------

Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
2026-09-06 08:04:28 -07:00

77 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
// Projects native catalog declarations into fresh-config defaults and the macOS resource.
import fs from "node:fs";
import path from "node:path";
const check = process.argv.includes("--check");
const root = process.cwd();
const catalogs = [];
const localOwners = new Set();
for (const dir of fs.readdirSync(path.join(root, "extensions")).toSorted()) {
const file = path.join(root, "extensions", dir, "openclaw.plugin.json");
if (!fs.existsSync(file)) {
continue;
}
const manifest = JSON.parse(fs.readFileSync(file, "utf8"));
if (manifest.id) {
localOwners.add(manifest.id);
}
const catalog = manifest.setup?.nativeSessionCatalog;
if (!catalog) {
continue;
}
if (!manifest.id || !catalog.label?.trim()) {
throw new Error(`Invalid native catalog declaration in ${file}`);
}
catalogs.push({ pluginId: manifest.id, ...catalog });
}
catalogs.sort((a, b) => a.pluginId.localeCompare(b.pluginId, "en"));
const byId = new Map(catalogs.map(({ pluginId, ...catalog }) => [pluginId, catalog]));
const outputs = new Map();
for (const name of ["plugin", "provider", "channel"]) {
const file = `scripts/lib/official-external-${name}-catalog.json`;
const original = fs.readFileSync(path.join(root, file), "utf8");
const feed = JSON.parse(original);
let changed = false;
for (const entry of feed.entries) {
const pluginId = entry.openclaw?.plugin?.id;
if (!localOwners.has(pluginId)) {
continue;
}
const catalog = byId.get(pluginId);
const previous = entry.openclaw.setup?.nativeSessionCatalog;
if (JSON.stringify(previous) === JSON.stringify(catalog)) {
continue;
}
if (catalog) {
entry.openclaw.setup = { ...entry.openclaw.setup, nativeSessionCatalog: catalog };
} else {
const setup = { ...entry.openclaw.setup };
delete setup.nativeSessionCatalog;
if (Object.keys(setup).length > 0) {
entry.openclaw.setup = setup;
} else {
delete entry.openclaw.setup;
}
}
changed = true;
}
outputs.set(file, changed ? `${JSON.stringify(feed, null, 2)}\n` : original);
}
const rendered = `${JSON.stringify(catalogs, null, 2)}\n`;
outputs.set("scripts/lib/native-session-catalogs.json", rendered);
outputs.set("apps/macos/Sources/OpenClaw/Resources/NativeSessionCatalogs.json", rendered);
for (const [relative, text] of outputs) {
const file = path.join(root, relative);
const current = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : undefined;
if (current === text) {
continue;
}
if (check) {
console.error(`${relative} is stale; run pnpm native-catalogs:gen`);
process.exitCode = 1;
} else {
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, text);
}
}