chore: drop superseded admin-panel agent-config prototype after rebase onto main

main now ships the canonical org-scoped agent-config implementation
(OrganizationAgentRole/OrganizationAgentSkill + hub/src/agent/configuration.ts
+ hub/src/agent/skillStore.ts per ADR-0018, and envelope-encrypted
OrganizationProviderConnection per ADR-0024). The earlier admin-panel
prototype (OrgModel/OrgRole/simple ProviderConnection baseUrl+authToken,
modelRoutes.ts, agentConfig.ts, migration 20260710120000, admin-web
models/roles pages) is superseded and clashes with main's schema; drop it.

Follow-up still needed: rewire admin-web SPA to the new config APIs
(+layout.svelte nav still lists models/roles, RoleCard.svelte unused).
This commit is contained in:
2026-07-13 21:44:07 +08:00
parent 9c33a4e9b9
commit b1ddf32238
7 changed files with 0 additions and 1219 deletions
@@ -1,169 +0,0 @@
<script lang="ts">
import { page } from '$app/state';
import { api, type OrgModelRow } from '$lib/api';
import { fmtDateOnly } from '$lib/format';
import PageHeader from '$lib/components/PageHeader.svelte';
import LoadingState from '$lib/components/LoadingState.svelte';
import ErrorBanner from '$lib/components/ErrorBanner.svelte';
import EmptyState from '$lib/components/EmptyState.svelte';
import CheckboxControl from '$lib/components/CheckboxControl.svelte';
import { toastError, toastSuccess } from '$lib/toast';
const slug = $derived(page.params.slug ?? '');
let models = $state<OrgModelRow[]>([]);
let loading = $state(true);
let error = $state<string | null>(null);
let newModelId = $state('');
let newLabel = $state('');
let newSortKey = $state('');
let adding = $state(false);
async function load() {
loading = true;
error = null;
try {
const res = await api.models(slug);
models = res.models;
} catch (err) {
error = err instanceof Error ? err.message : String(err);
} finally {
loading = false;
}
}
async function add() {
if (!newModelId.trim() || !newLabel.trim()) return;
adding = true;
try {
const m = await api.createModel(slug, {
modelId: newModelId.trim(),
label: newLabel.trim(),
...(newSortKey.trim() ? { sortKey: newSortKey.trim() } : {})
});
models = [...models, m];
newModelId = '';
newLabel = '';
newSortKey = '';
toastSuccess('模型已添加');
} catch (err) {
toastError(err instanceof Error ? err.message : String(err));
} finally {
adding = false;
}
}
async function save(m: OrgModelRow, patch: Partial<OrgModelRow>) {
try {
const updated = await api.updateModel(slug, m.id, patch);
models = models.map((x) => (x.id === m.id ? updated : x));
toastSuccess('已保存');
} catch (err) {
toastError(err instanceof Error ? err.message : String(err));
await load();
}
}
async function remove(m: OrgModelRow) {
if (!confirm(`删除模型 ${m.label}?`)) return;
try {
await api.deleteModel(slug, m.id);
models = models.filter((x) => x.id !== m.id);
toastSuccess('模型已删除');
} catch (err) {
toastError(err instanceof Error ? err.message : String(err));
}
}
$effect(() => {
if (slug) load();
});
</script>
<PageHeader
title="模型"
description="本组织启用的模型清单。模型 ID 面向供应方接口;显示名面向教师侧切换。"
/>
{#if loading}
<LoadingState />
{:else if error}
<ErrorBanner message={error} onretry={load} />
{:else}
<div class="saas-card-pad mb-6">
<h2 class="saas-section-title mb-4">添加模型</h2>
<div class="grid gap-3 md:grid-cols-[1.4fr_1fr_auto_auto]">
<input
class="saas-input font-mono text-sm"
placeholder="模型 ID(如 anthropic/claude-sonnet-5"
bind:value={newModelId}
/>
<input class="saas-input" placeholder="显示名(如 Claude Sonnet 5" bind:value={newLabel} />
<input class="saas-input w-28" placeholder="排序" bind:value={newSortKey} />
<button class="saas-btn-primary" onclick={add} disabled={adding}>添加</button>
</div>
</div>
<div class="saas-card overflow-hidden">
<div class="flex items-center justify-between border-b border-surface-200 px-5 py-3">
<h2 class="text-sm font-semibold">已启用模型</h2>
<span class="saas-badge-neutral">{models.length}</span>
</div>
{#if models.length === 0}
<EmptyState title="暂无已启用模型" description="空清单时会回退到环境默认模型。" />
{:else}
<div class="overflow-x-auto">
<table class="data-table">
<thead>
<tr>
<th>显示名</th>
<th>模型 ID</th>
<th>工具能力</th>
<th>排序</th>
<th>创建</th>
<th></th>
</tr>
</thead>
<tbody>
{#each models as m (m.id)}
<tr>
<td>
<input
class="saas-input py-1.5"
value={m.label}
onchange={(e) => save(m, { label: (e.target as HTMLInputElement).value })}
/>
</td>
<td>
<input
class="saas-input py-1.5 font-mono text-xs"
value={m.modelId}
onchange={(e) => save(m, { modelId: (e.target as HTMLInputElement).value })}
/>
</td>
<td>
<CheckboxControl
checked={m.toolCapable}
onchange={(toolCapable) => save(m, { toolCapable })}
/>
</td>
<td>
<input
class="saas-input w-20 py-1.5"
value={m.sortKey}
onchange={(e) => save(m, { sortKey: (e.target as HTMLInputElement).value })}
/>
</td>
<td class="text-xs text-surface-600">{fmtDateOnly(m.createdAt)}</td>
<td class="text-right">
<button class="saas-btn-danger !py-1 text-xs" onclick={() => remove(m)}>删除</button>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
</div>
{/if}
@@ -1,106 +0,0 @@
<script lang="ts">
import { page } from '$app/state';
import { api, type OrgRoleRow, type OrgModelRow } from '$lib/api';
import PageHeader from '$lib/components/PageHeader.svelte';
import LoadingState from '$lib/components/LoadingState.svelte';
import ErrorBanner from '$lib/components/ErrorBanner.svelte';
import EmptyState from '$lib/components/EmptyState.svelte';
import RoleCard from '$lib/components/RoleCard.svelte';
import { toastError, toastSuccess } from '$lib/toast';
const slug = $derived(page.params.slug ?? '');
let roles = $state<OrgRoleRow[]>([]);
let models = $state<OrgModelRow[]>([]);
let loading = $state(true);
let error = $state<string | null>(null);
let newRoleId = $state('');
let newLabel = $state('');
let adding = $state(false);
async function load() {
loading = true;
error = null;
try {
const [r, m] = await Promise.all([api.roles(slug), api.models(slug)]);
roles = r.roles;
models = m.models;
} catch (err) {
error = err instanceof Error ? err.message : String(err);
} finally {
loading = false;
}
}
async function add() {
if (!newRoleId.trim() || !newLabel.trim()) return;
adding = true;
try {
const r = await api.createRole(slug, { roleId: newRoleId.trim(), label: newLabel.trim() });
roles = [...roles, r];
newRoleId = '';
newLabel = '';
toastSuccess('角色已创建');
} catch (err) {
toastError(err instanceof Error ? err.message : String(err));
} finally {
adding = false;
}
}
async function remove(r: OrgRoleRow) {
if (!confirm(`删除角色 ${r.label} (${r.roleId})?`)) return;
try {
await api.deleteRole(slug, r.id);
roles = roles.filter((x) => x.id !== r.id);
toastSuccess('角色已删除');
} catch (err) {
toastError(err instanceof Error ? err.message : String(err));
}
}
$effect(() => {
if (slug) load();
});
</script>
<PageHeader
title="角色"
description="角色按数据配置。角色 ID 同时是斜杠命令(如 /draft),可绑定默认模型、工具白名单与系统提示词。"
/>
{#if loading}
<LoadingState />
{:else if error}
<ErrorBanner message={error} onretry={load} />
{:else}
<div class="saas-card-pad mb-6">
<h2 class="saas-section-title mb-4">新建角色</h2>
<div class="grid gap-3 sm:grid-cols-[10rem_1fr_auto]">
<input class="saas-input font-mono text-sm" placeholder="角色 ID(如 draft" bind:value={newRoleId} />
<input class="saas-input" placeholder="显示名(如 草稿)" bind:value={newLabel} />
<button class="saas-btn-primary" onclick={add} disabled={adding}>新建</button>
</div>
</div>
{#if roles.length === 0}
<div class="saas-card">
<EmptyState title="暂无角色" description="未配置时回退环境默认角色(draft / review)。" />
</div>
{:else}
<div class="space-y-4">
{#each roles as r (r.id)}
<RoleCard
{r}
{models}
{slug}
onremoved={() => remove(r)}
onupdated={(updated: OrgRoleRow) => {
roles = roles.map((x) => (x.id === r.id ? updated : x));
}}
/>
{/each}
</div>
{/if}
{/if}