diff --git a/console/index.html b/console/index.html index 22acdf1..e1dada7 100644 --- a/console/index.html +++ b/console/index.html @@ -273,6 +273,19 @@ explicit auth error, not a silent drift.

+
+ +
+ — not set — + +
+

+ Local folder the New Fleet wizard mirrors each agent's generated + config.toml into (<folder>/<agent-name>/config.toml), + alongside the S3 copy it deploys from — this is what "view an + agent's config" reads from, no S3 round-trip. +

+
diff --git a/console/src/main.ts b/console/src/main.ts index 8875e51..7c108cc 100644 --- a/console/src/main.ts +++ b/console/src/main.ts @@ -174,6 +174,47 @@ const mcp = mcpEl ? createPane(mcpEl, () => flag("mcpio")) : null; }); })(); +// Local "Config folder" (studio#128) — where the New Fleet wizard mirrors +// each agent's generated config.toml (alongside the S3 copy it deploys +// from) and where the "view an agent's config" screen reads from, no S3 +// round-trip. Persisted like the theme/log-level settings above +// (localStorage), not Tauri's app-config-dir — this setting *points at* +// other local files, storing it in the hidden config dir would just be an +// extra layer of indirection for no reason. +(function setupConfigFolder(): void { + const pathEl = document.getElementById("config-folder-path"); + const pickBtn = document.getElementById("config-folder-pick"); + if (!pathEl || !pickBtn) return; + const KEY = "oab-studio.configFolder"; + + const render = (): void => { + let saved: string | null = null; + try { + saved = localStorage.getItem(KEY); + } catch { + /* storage unavailable — falls through to the placeholder */ + } + pathEl.textContent = saved || "— not set —"; + }; + render(); + + pickBtn.addEventListener("click", () => { + const invoke = tauriInvoke(); + if (!invoke) return; + invoke("plugin:dialog|open", { options: { directory: true } }) + .then((path) => { + if (!path) return; + try { + localStorage.setItem(KEY, path); + } catch { + /* storage unavailable — the choice still applies this session */ + } + render(); + }) + .catch((e) => note("error", `config folder pick failed: ${errText(e)}`)); + }); +})(); + // Build stamp (injected by vite) — shown under the brand and logged on launch, // so it's obvious which commit this build is. const BUILD = `v${__APP_VERSION__} · ${__BUILD_SHA__}`; diff --git a/console/src/styles.css b/console/src/styles.css index ea74ab1..03ec2d3 100644 --- a/console/src/styles.css +++ b/console/src/styles.css @@ -1244,6 +1244,38 @@ button.act:disabled { color: var(--muted); } +.config-folder { + display: flex; + flex-direction: column; + gap: 8px; + max-width: 420px; + margin-top: 20px; + padding-top: 16px; + border-top: 1px solid var(--border); +} +.config-folder > label { + font-size: 12px; + color: var(--muted); +} +.config-folder-row { + display: flex; + align-items: center; + gap: 12px; +} +.config-folder-path { + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + color: var(--text); + padding: 6px 8px; + border: 1px solid var(--border); + border-radius: 6px; + background: var(--bg); +} + /* Compose (agent-deployment ADR, slice 1): the deploy panel's bundle-preview step (`deploy.ts`'s `#deploy-compose`) — the standalone authoring tab this used to also style is gone, see compose.ts. */ diff --git a/crates/oab-mcp/src/lib.rs b/crates/oab-mcp/src/lib.rs index 0d34b5d..e08ae05 100644 --- a/crates/oab-mcp/src/lib.rs +++ b/crates/oab-mcp/src/lib.rs @@ -248,6 +248,17 @@ pub fn tools() -> Vec { "properties": {} })), ), + Tool::new( + "resolve_vendor_image_tags", + "Resolve a vendor's real, currently-published Stable/Beta image tags on ghcr.io/openabdev/openab (studio#128 — backs the New Fleet wizard's Vendor + Image tag fields). \"Beta\" is the hourly rolling pre-beta- build; \"Stable\" is the newest openab release whose matching - image is confirmed to actually exist (a release existing doesn't guarantee a matching image was ever built — the build workflow is a manual, disconnected step). Anonymous GHCR/GitHub access, no auth needed (public package/repo). Either or both fields come back null if nothing verified — not an error; the caller should fall back to a plain editable text field.", + as_map(json!({ + "type": "object", + "properties": { + "vendor": { "type": "string", "description": "Vendor name, e.g. \"claude\", \"codex\", \"cursor\", \"kiro\", \"antigravity\"." } + }, + "required": ["vendor"] + })), + ), Tool::new( "list_namespaces", "List namespaces in the cluster a kubeconfig context resolves to. Read-only; backs the New Fleet wizard's namespace