From adc8bd185b54935e7a31aae04da3175b7989927a Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Wed, 20 May 2026 15:04:26 +0900 Subject: feat: phase 3 — config, skills, model groups, task list, and sidebar UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Config system: TOML-based dispatch.toml with hot-reload via chokidar - Model/key resolution: tag-based model selection, key fallback chains - Skills system: directory loader with TOML frontmatter, agent mappings - Task list tool: add/update/list/get operations with WebSocket events - API routes: GET /config, /skills, /skills/:name, /models, /models/resolve - Frontend: sidebar with model status, task list, config viewer, skills browser, permission log - Sliding sidebar animation using CSS transitions (not Svelte transitions) --- .../frontend/src/lib/components/ConfigPanel.svelte | 244 +++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 packages/frontend/src/lib/components/ConfigPanel.svelte (limited to 'packages/frontend/src/lib/components/ConfigPanel.svelte') diff --git a/packages/frontend/src/lib/components/ConfigPanel.svelte b/packages/frontend/src/lib/components/ConfigPanel.svelte new file mode 100644 index 0000000..25cbe98 --- /dev/null +++ b/packages/frontend/src/lib/components/ConfigPanel.svelte @@ -0,0 +1,244 @@ + + +
+ + Configuration + {#if modelCount > 0 || keyCount > 0} + {modelCount} models + {keyCount} keys + {/if} + {#if loading} + + {/if} + + +
+ {#if error} +
+ Failed to load config: {error} +
+ {/if} + +
+ +
+ + + {#if configData?.agents && Object.keys(configData.agents).length > 0} +
+
Agent Templates
+ {#each Object.entries(configData.agents) as [name, template]} +
+
+ {name} + {#if template.model_tag} + {template.model_tag} + {/if} +
+ {#if template.description} +

{template.description}

+ {/if} + {#if template.tools && template.tools.length > 0} +
+ {#each template.tools as tool} + {tool} + {/each} +
+ {/if} +
+ {/each} +
+ {/if} + + + {#if modelsData?.models && modelsData.models.length > 0} +
+
Models
+ {#each modelsData.models as model} +
+ {model.id} + {#if model.provider} + {model.provider} + {/if} + {#if model.tags && model.tags.length > 0} + {#each model.tags as tag} + {tag} + {/each} + {/if} +
+ {/each} +
+ {/if} + + + {#if modelsData?.keys && modelsData.keys.length > 0} +
+
API Keys
+ {#each modelsData.keys as key} +
+
+ {key.id} + {#if key.provider} + {key.provider} + {/if} + {#if key.status === "exhausted"} + exhausted + {:else} + active + {/if} +
+ {#if key.status === "exhausted" && key.lastError} +

{key.lastError}

+ {/if} + {#if key.exhaustedAt} +

Since {formatDate(key.exhaustedAt)}

+ {/if} +
+ {/each} +
+ {/if} + + + {#if configData?.fallback && configData.fallback.length > 0} +
+
Fallback Order
+
    + {#each configData.fallback as keyId, i} +
  1. + {i + 1} + {keyId} +
  2. + {/each} +
+
+ {/if} + + + {#if configData?.permissions && Object.keys(configData.permissions).length > 0} +
+
Permissions
+ {#each permissionEntries(configData.permissions) as entry} +
+ {entry.name} + {#if isSimpleRule(entry.value)} + {entry.value.action} + {:else if isPatternRule(entry.value)} + {#each Object.entries(entry.value) as [pattern, rule]} +
+ {pattern} + {#if typeof rule === "object" && rule !== null && "action" in rule} + {(rule as { action: string }).action} + {/if} +
+ {/each} + {:else} + {JSON.stringify(entry.value)} + {/if} +
+ {/each} +
+ {/if} + + {#if !loading && !error && !configData && !modelsData} +

No configuration loaded.

+ {/if} +
+
-- cgit v1.2.3