@haseebuchiha/silvr 2026.3.20 → 2026.3.21

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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2026.3.20",
3
- "commit": "149bf740dd2e98a58464d30bb46cce079db62ac5",
4
- "builtAt": "2026-03-21T00:37:40.541Z"
2
+ "version": "2026.3.21",
3
+ "commit": "e7a4691091667d1d0802ec2f9d411eee305c3174",
4
+ "builtAt": "2026-03-23T09:07:09.500Z"
5
5
  }
@@ -1 +1 @@
1
- 56ed79869a7a3215dc207f017f348d241ea7358cfab36a3f5977c63f6301a678
1
+ 13f6f0963b0ca231799f0756ceae15f9853c082e2d9ef138c571f2bb579509b1
@@ -1,4 +1,4 @@
1
- import{i as e,n as t}from"./lit-BZwq2xLD.js";import{l as n}from"./format-DeRVtGzv.js";import{C as r,D as i,E as a,O as o,S as s,T as c,_ as l,a as u,b as d,d as f,f as p,g as m,h,k as g,m as _,n as v,p as y,r as b,t as x,u as S,v as C,w,x as T,y as E}from"./index-5bbJdGkA.js";import{r as D}from"./channel-config-extras-UBRJa-vU.js";import{i as O,n as k,r as A,t as j}from"./skills-shared-CPLqvR1x.js";function M(n){let{agent:r,configForm:i,agentFilesList:a,configLoading:o,configSaving:c,configDirty:u,onConfigReload:f,onConfigSave:m,onModelChange:h,onModelFallbacksChange:g,onSelectPanel:_}=n,v=E(i,r.id),y=(a&&a.agentId===r.id?a.workspace:null)||v.entry?.workspace||v.defaults?.workspace||`default`,b=v.entry?.model?T(v.entry?.model):T(v.defaults?.model),x=T(v.defaults?.model),S=s(v.entry?.model),w=s(v.defaults?.model)||(x===`-`?null:l(x)),D=S??w??null,O=d(v.entry?.model)??[],k=Array.isArray(v.entry?.skills)?v.entry?.skills:null,A=k?.length??null,j=!!(n.defaultId&&r.id===n.defaultId),M=!i||o||c,N=e=>{let t=O.filter((t,n)=>n!==e);g(r.id,t)};return e`
1
+ import{i as e,n as t}from"./lit-BZwq2xLD.js";import{l as n}from"./format-DeRVtGzv.js";import{C as r,D as i,E as a,O as o,S as s,T as c,_ as l,a as u,b as d,d as f,f as p,g as m,h,k as g,m as _,n as v,p as y,r as b,t as x,u as S,v as C,w,x as T,y as E}from"./index-UVvtebBp.js";import{r as D}from"./channel-config-extras-UBRJa-vU.js";import{i as O,n as k,r as A,t as j}from"./skills-shared-CPLqvR1x.js";function M(n){let{agent:r,configForm:i,agentFilesList:a,configLoading:o,configSaving:c,configDirty:u,onConfigReload:f,onConfigSave:m,onModelChange:h,onModelFallbacksChange:g,onSelectPanel:_}=n,v=E(i,r.id),y=(a&&a.agentId===r.id?a.workspace:null)||v.entry?.workspace||v.defaults?.workspace||`default`,b=v.entry?.model?T(v.entry?.model):T(v.defaults?.model),x=T(v.defaults?.model),S=s(v.entry?.model),w=s(v.defaults?.model)||(x===`-`?null:l(x)),D=S??w??null,O=d(v.entry?.model)??[],k=Array.isArray(v.entry?.skills)?v.entry?.skills:null,A=k?.length??null,j=!!(n.defaultId&&r.id===n.defaultId),M=!i||o||c,N=e=>{let t=O.filter((t,n)=>n!==e);g(r.id,t)};return e`
2
2
  <section class="card">
3
3
  <div class="card-title">Overview</div>
4
4
  <div class="card-sub">Workspace paths and identity metadata.</div>
@@ -675,4 +675,4 @@ import{i as e,n as t}from"./lit-BZwq2xLD.js";import{l as n}from"./format-DeRVtGz
675
675
  `)}
676
676
  </div>
677
677
  `}export{q as renderAgents};
678
- //# sourceMappingURL=agents-koDAA2JN.js.map
678
+ //# sourceMappingURL=agents-CRGOH5CC.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents-koDAA2JN.js","names":[],"sources":["../../../ui/src/ui/views/agents-panels-overview.ts","../../../ui/src/ui/views/agents-panels-status-files.ts","../../../ui/src/ui/views/agents-panels-tools-skills.ts","../../../ui/src/ui/views/agents.ts"],"sourcesContent":["import { html, nothing } from \"lit\";\nimport type { AgentIdentityResult, AgentsFilesListResult, AgentsListResult } from \"../types.ts\";\nimport {\n buildModelOptions,\n normalizeModelValue,\n parseFallbackList,\n resolveAgentConfig,\n resolveModelFallbacks,\n resolveModelLabel,\n resolveModelPrimary,\n} from \"./agents-utils.ts\";\nimport type { AgentsPanel } from \"./agents.ts\";\n\nexport function renderAgentOverview(params: {\n agent: AgentsListResult[\"agents\"][number];\n basePath: string;\n defaultId: string | null;\n configForm: Record<string, unknown> | null;\n agentFilesList: AgentsFilesListResult | null;\n agentIdentity: AgentIdentityResult | null;\n agentIdentityLoading: boolean;\n agentIdentityError: string | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n onConfigReload: () => void;\n onConfigSave: () => void;\n onModelChange: (agentId: string, modelId: string | null) => void;\n onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void;\n onSelectPanel: (panel: AgentsPanel) => void;\n}) {\n const {\n agent,\n configForm,\n agentFilesList,\n configLoading,\n configSaving,\n configDirty,\n onConfigReload,\n onConfigSave,\n onModelChange,\n onModelFallbacksChange,\n onSelectPanel,\n } = params;\n const config = resolveAgentConfig(configForm, agent.id);\n const workspaceFromFiles =\n agentFilesList && agentFilesList.agentId === agent.id ? agentFilesList.workspace : null;\n const workspace =\n workspaceFromFiles || config.entry?.workspace || config.defaults?.workspace || \"default\";\n const model = config.entry?.model\n ? resolveModelLabel(config.entry?.model)\n : resolveModelLabel(config.defaults?.model);\n const defaultModel = resolveModelLabel(config.defaults?.model);\n const entryPrimary = resolveModelPrimary(config.entry?.model);\n const defaultPrimary =\n resolveModelPrimary(config.defaults?.model) ||\n (defaultModel !== \"-\" ? normalizeModelValue(defaultModel) : null);\n const effectivePrimary = entryPrimary ?? defaultPrimary ?? null;\n const modelFallbacks = resolveModelFallbacks(config.entry?.model);\n const fallbackChips = modelFallbacks ?? [];\n const skillFilter = Array.isArray(config.entry?.skills) ? config.entry?.skills : null;\n const skillCount = skillFilter?.length ?? null;\n const isDefault = Boolean(params.defaultId && agent.id === params.defaultId);\n const disabled = !configForm || configLoading || configSaving;\n\n const removeChip = (index: number) => {\n const next = fallbackChips.filter((_, i) => i !== index);\n onModelFallbacksChange(agent.id, next);\n };\n\n const handleChipKeydown = (e: KeyboardEvent) => {\n const input = e.target as HTMLInputElement;\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const parsed = parseFallbackList(input.value);\n if (parsed.length > 0) {\n onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);\n input.value = \"\";\n }\n }\n };\n\n return html`\n <section class=\"card\">\n <div class=\"card-title\">Overview</div>\n <div class=\"card-sub\">Workspace paths and identity metadata.</div>\n\n <div class=\"agents-overview-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Workspace</div>\n <div>\n <button\n type=\"button\"\n class=\"workspace-link mono\"\n @click=${() => onSelectPanel(\"files\")}\n title=\"Open Files tab\"\n >${workspace}</button>\n </div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Primary Model</div>\n <div class=\"mono\">${model}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Skills Filter</div>\n <div>${skillFilter ? `${skillCount} selected` : \"all skills\"}</div>\n </div>\n </div>\n\n ${\n configDirty\n ? html`\n <div class=\"callout warn\" style=\"margin-top: 16px\">You have unsaved config changes.</div>\n `\n : nothing\n }\n\n <div class=\"agent-model-select\" style=\"margin-top: 20px;\">\n <div class=\"label\">Model Selection</div>\n <div class=\"agent-model-fields\">\n <label class=\"field\">\n <span>Primary model${isDefault ? \" (default)\" : \"\"}</span>\n <select\n .value=${isDefault ? (effectivePrimary ?? \"\") : (entryPrimary ?? \"\")}\n ?disabled=${disabled}\n @change=${(e: Event) =>\n onModelChange(agent.id, (e.target as HTMLSelectElement).value || null)}\n >\n ${\n isDefault\n ? nothing\n : html`\n <option value=\"\">\n ${defaultPrimary ? `Inherit default (${defaultPrimary})` : \"Inherit default\"}\n </option>\n `\n }\n ${buildModelOptions(configForm, effectivePrimary ?? undefined)}\n </select>\n </label>\n <div class=\"field\">\n <span>Fallbacks</span>\n <div class=\"agent-chip-input\" @click=${(e: Event) => {\n const container = e.currentTarget as HTMLElement;\n const input = container.querySelector(\"input\");\n if (input) {\n input.focus();\n }\n }}>\n ${fallbackChips.map(\n (chip, i) => html`\n <span class=\"chip\">\n ${chip}\n <button\n type=\"button\"\n class=\"chip-remove\"\n ?disabled=${disabled}\n @click=${() => removeChip(i)}\n >&times;</button>\n </span>\n `,\n )}\n <input\n ?disabled=${disabled}\n placeholder=${fallbackChips.length === 0 ? \"provider/model\" : \"\"}\n @keydown=${handleChipKeydown}\n @blur=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n const parsed = parseFallbackList(input.value);\n if (parsed.length > 0) {\n onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);\n input.value = \"\";\n }\n }}\n />\n </div>\n </div>\n </div>\n <div class=\"agent-model-actions\">\n <button type=\"button\" class=\"btn btn--sm\" ?disabled=${configLoading} @click=${onConfigReload}>\n Reload Config\n </button>\n <button\n type=\"button\"\n class=\"btn btn--sm primary\"\n ?disabled=${configSaving || !configDirty}\n @click=${onConfigSave}\n >\n ${configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n </section>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport { icons } from \"../icons.ts\";\nimport { toSanitizedMarkdownHtml } from \"../markdown.ts\";\nimport {\n formatCronPayload,\n formatCronSchedule,\n formatCronState,\n formatNextRun,\n} from \"../presenter.ts\";\nimport type {\n AgentFileEntry,\n AgentsFilesListResult,\n ChannelAccountSnapshot,\n ChannelsStatusSnapshot,\n CronJob,\n CronStatus,\n} from \"../types.ts\";\nimport { formatBytes, type AgentContext } from \"./agents-utils.ts\";\nimport { resolveChannelExtras as resolveChannelExtrasFromConfig } from \"./channel-config-extras.ts\";\n\nfunction renderAgentContextCard(context: AgentContext, subtitle: string) {\n return html`\n <section class=\"card\">\n <div class=\"card-title\">Agent Context</div>\n <div class=\"card-sub\">${subtitle}</div>\n <div class=\"agents-overview-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Workspace</div>\n <div class=\"mono\">${context.workspace}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Primary Model</div>\n <div class=\"mono\">${context.model}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Identity Name</div>\n <div>${context.identityName}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Identity Avatar</div>\n <div>${context.identityAvatar}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Skills Filter</div>\n <div>${context.skillsLabel}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Default</div>\n <div>${context.isDefault ? \"yes\" : \"no\"}</div>\n </div>\n </div>\n </section>\n `;\n}\n\ntype ChannelSummaryEntry = {\n id: string;\n label: string;\n accounts: ChannelAccountSnapshot[];\n};\n\nfunction resolveChannelLabel(snapshot: ChannelsStatusSnapshot, id: string) {\n const meta = snapshot.channelMeta?.find((entry) => entry.id === id);\n if (meta?.label) {\n return meta.label;\n }\n return snapshot.channelLabels?.[id] ?? id;\n}\n\nfunction resolveChannelEntries(snapshot: ChannelsStatusSnapshot | null): ChannelSummaryEntry[] {\n if (!snapshot) {\n return [];\n }\n const ids = new Set<string>();\n for (const id of snapshot.channelOrder ?? []) {\n ids.add(id);\n }\n for (const entry of snapshot.channelMeta ?? []) {\n ids.add(entry.id);\n }\n for (const id of Object.keys(snapshot.channelAccounts ?? {})) {\n ids.add(id);\n }\n const ordered: string[] = [];\n const seed = snapshot.channelOrder?.length ? snapshot.channelOrder : Array.from(ids);\n for (const id of seed) {\n if (!ids.has(id)) {\n continue;\n }\n ordered.push(id);\n ids.delete(id);\n }\n for (const id of ids) {\n ordered.push(id);\n }\n return ordered.map((id) => ({\n id,\n label: resolveChannelLabel(snapshot, id),\n accounts: snapshot.channelAccounts?.[id] ?? [],\n }));\n}\n\nconst CHANNEL_EXTRA_FIELDS = [\"groupPolicy\", \"streamMode\", \"dmPolicy\"] as const;\n\nfunction summarizeChannelAccounts(accounts: ChannelAccountSnapshot[]) {\n let connected = 0;\n let configured = 0;\n let enabled = 0;\n for (const account of accounts) {\n const probeOk =\n account.probe && typeof account.probe === \"object\" && \"ok\" in account.probe\n ? Boolean((account.probe as { ok?: unknown }).ok)\n : false;\n const isConnected = account.connected === true || account.running === true || probeOk;\n if (isConnected) {\n connected += 1;\n }\n if (account.configured) {\n configured += 1;\n }\n if (account.enabled) {\n enabled += 1;\n }\n }\n return {\n total: accounts.length,\n connected,\n configured,\n enabled,\n };\n}\n\nexport function renderAgentChannels(params: {\n context: AgentContext;\n configForm: Record<string, unknown> | null;\n snapshot: ChannelsStatusSnapshot | null;\n loading: boolean;\n error: string | null;\n lastSuccess: number | null;\n onRefresh: () => void;\n}) {\n const entries = resolveChannelEntries(params.snapshot);\n const lastSuccessLabel = params.lastSuccess\n ? formatRelativeTimestamp(params.lastSuccess)\n : \"never\";\n return html`\n <section class=\"grid grid-cols-2\">\n ${renderAgentContextCard(params.context, \"Workspace, identity, and model configuration.\")}\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Channels</div>\n <div class=\"card-sub\">Gateway-wide channel status snapshot.</div>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Refreshing…\" : \"Refresh\"}\n </button>\n </div>\n <div class=\"muted\" style=\"margin-top: 8px;\">\n Last refresh: ${lastSuccessLabel}\n </div>\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n ${\n !params.snapshot\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">Load channels to see live status.</div>\n `\n : nothing\n }\n ${\n entries.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No channels found.</div>\n `\n : html`\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${entries.map((entry) => {\n const summary = summarizeChannelAccounts(entry.accounts);\n const status = summary.total\n ? `${summary.connected}/${summary.total} connected`\n : \"no accounts\";\n const configLabel = summary.configured\n ? `${summary.configured} configured`\n : \"not configured\";\n const enabled = summary.total ? `${summary.enabled} enabled` : \"disabled\";\n const extras = resolveChannelExtrasFromConfig({\n configForm: params.configForm,\n channelId: entry.id,\n fields: CHANNEL_EXTRA_FIELDS,\n });\n return html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${entry.label}</div>\n <div class=\"list-sub mono\">${entry.id}</div>\n </div>\n <div class=\"list-meta\">\n <div>${status}</div>\n <div>${configLabel}</div>\n <div>${enabled}</div>\n ${\n summary.configured === 0\n ? html`\n <div>\n <a\n href=\"https://docs.openclaw.ai/channels\"\n target=\"_blank\"\n rel=\"noopener\"\n style=\"color: var(--accent); font-size: 12px\"\n >Setup guide</a\n >\n </div>\n `\n : nothing\n }\n ${\n extras.length > 0\n ? extras.map(\n (extra) => html`<div>${extra.label}: ${extra.value}</div>`,\n )\n : nothing\n }\n </div>\n </div>\n `;\n })}\n </div>\n `\n }\n </section>\n </section>\n `;\n}\n\nexport function renderAgentCron(params: {\n context: AgentContext;\n agentId: string;\n jobs: CronJob[];\n status: CronStatus | null;\n loading: boolean;\n error: string | null;\n onRefresh: () => void;\n onRunNow: (jobId: string) => void;\n}) {\n const jobs = params.jobs.filter((job) => job.agentId === params.agentId);\n return html`\n <section class=\"grid grid-cols-2\">\n ${renderAgentContextCard(params.context, \"Workspace and scheduling targets.\")}\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Scheduler</div>\n <div class=\"card-sub\">Gateway cron status.</div>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Refreshing…\" : \"Refresh\"}\n </button>\n </div>\n <div class=\"stat-grid\" style=\"margin-top: 16px;\">\n <div class=\"stat\">\n <div class=\"stat-label\">Enabled</div>\n <div class=\"stat-value\">\n ${params.status ? (params.status.enabled ? \"Yes\" : \"No\") : \"n/a\"}\n </div>\n </div>\n <div class=\"stat\">\n <div class=\"stat-label\">Jobs</div>\n <div class=\"stat-value\">${params.status?.jobs ?? \"n/a\"}</div>\n </div>\n <div class=\"stat\">\n <div class=\"stat-label\">Next wake</div>\n <div class=\"stat-value\">${formatNextRun(params.status?.nextWakeAtMs ?? null)}</div>\n </div>\n </div>\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n </section>\n </section>\n <section class=\"card\">\n <div class=\"card-title\">Agent Cron Jobs</div>\n <div class=\"card-sub\">Scheduled jobs targeting this agent.</div>\n ${\n jobs.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No jobs assigned.</div>\n `\n : html`\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${jobs.map(\n (job) => html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${job.name}</div>\n ${\n job.description\n ? html`<div class=\"list-sub\">${job.description}</div>`\n : nothing\n }\n <div class=\"chip-row\" style=\"margin-top: 6px;\">\n <span class=\"chip\">${formatCronSchedule(job)}</span>\n <span class=\"chip ${job.enabled ? \"chip-ok\" : \"chip-warn\"}\">\n ${job.enabled ? \"enabled\" : \"disabled\"}\n </span>\n <span class=\"chip\">${job.sessionTarget}</span>\n </div>\n </div>\n <div class=\"list-meta\">\n <div class=\"mono\">${formatCronState(job)}</div>\n <div class=\"muted\">${formatCronPayload(job)}</div>\n <button\n class=\"btn btn--sm\"\n style=\"margin-top: 6px;\"\n ?disabled=${!job.enabled}\n @click=${() => params.onRunNow(job.id)}\n >Run Now</button>\n </div>\n </div>\n `,\n )}\n </div>\n `\n }\n </section>\n `;\n}\n\nexport function renderAgentFiles(params: {\n agentId: string;\n agentFilesList: AgentsFilesListResult | null;\n agentFilesLoading: boolean;\n agentFilesError: string | null;\n agentFileActive: string | null;\n agentFileContents: Record<string, string>;\n agentFileDrafts: Record<string, string>;\n agentFileSaving: boolean;\n onLoadFiles: (agentId: string) => void;\n onSelectFile: (name: string) => void;\n onFileDraftChange: (name: string, content: string) => void;\n onFileReset: (name: string) => void;\n onFileSave: (name: string) => void;\n}) {\n const list = params.agentFilesList?.agentId === params.agentId ? params.agentFilesList : null;\n const files = list?.files ?? [];\n const active = params.agentFileActive ?? null;\n const activeEntry = active ? (files.find((file) => file.name === active) ?? null) : null;\n const baseContent = active ? (params.agentFileContents[active] ?? \"\") : \"\";\n const draft = active ? (params.agentFileDrafts[active] ?? baseContent) : \"\";\n const isDirty = active ? draft !== baseContent : false;\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Core Files</div>\n <div class=\"card-sub\">Bootstrap persona, identity, and tool guidance.</div>\n </div>\n <button\n class=\"btn btn--sm\"\n ?disabled=${params.agentFilesLoading}\n @click=${() => params.onLoadFiles(params.agentId)}\n >\n ${params.agentFilesLoading ? \"Loading…\" : \"Refresh\"}\n </button>\n </div>\n ${\n list\n ? html`<div class=\"muted mono\" style=\"margin-top: 8px;\">Workspace: ${list.workspace}</div>`\n : nothing\n }\n ${\n params.agentFilesError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.agentFilesError}</div>`\n : nothing\n }\n ${\n !list\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the agent workspace files to edit core instructions.\n </div>\n `\n : html`\n <div class=\"agent-files-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-files-list\">\n ${\n files.length === 0\n ? html`\n <div class=\"muted\">No files found.</div>\n `\n : files.map((file) =>\n renderAgentFileRow(file, active, () => params.onSelectFile(file.name)),\n )\n }\n </div>\n <div class=\"agent-files-editor\">\n ${\n !activeEntry\n ? html`\n <div class=\"muted\">Select a file to edit.</div>\n `\n : html`\n <div class=\"agent-file-header\">\n <div>\n <div class=\"agent-file-title mono\">${activeEntry.name}</div>\n <div class=\"agent-file-sub mono\">${activeEntry.path}</div>\n </div>\n <div class=\"agent-file-actions\">\n <button\n class=\"btn btn--sm\"\n title=\"Preview rendered markdown\"\n @click=${(e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n const dialog = btn\n .closest(\".agent-files-editor\")\n ?.querySelector(\"dialog\");\n if (dialog) {\n dialog.showModal();\n }\n }}\n >\n ${icons.eye} Preview\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!isDirty}\n @click=${() => params.onFileReset(activeEntry.name)}\n >\n Reset\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.agentFileSaving || !isDirty}\n @click=${() => params.onFileSave(activeEntry.name)}\n >\n ${params.agentFileSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n ${\n activeEntry.missing\n ? html`\n <div class=\"callout info\" style=\"margin-top: 10px\">\n This file is missing. Saving will create it in the agent workspace.\n </div>\n `\n : nothing\n }\n <label class=\"field agent-file-field\" style=\"margin-top: 12px;\">\n <span>Content</span>\n <textarea\n class=\"agent-file-textarea\"\n .value=${draft}\n @input=${(e: Event) =>\n params.onFileDraftChange(\n activeEntry.name,\n (e.target as HTMLTextAreaElement).value,\n )}\n ></textarea>\n </label>\n <dialog\n class=\"md-preview-dialog\"\n @click=${(e: Event) => {\n const dialog = e.currentTarget as HTMLDialogElement;\n if (e.target === dialog) {\n dialog.close();\n }\n }}\n >\n <div class=\"md-preview-dialog__panel\">\n <div class=\"md-preview-dialog__header\">\n <div class=\"md-preview-dialog__title mono\">${activeEntry.name}</div>\n <button\n class=\"btn btn--sm\"\n @click=${(e: Event) => {\n (e.currentTarget as HTMLElement).closest(\"dialog\")?.close();\n }}\n >${icons.x} Close</button>\n </div>\n <div class=\"md-preview-dialog__body sidebar-markdown\">\n ${unsafeHTML(toSanitizedMarkdownHtml(draft))}\n </div>\n </div>\n </dialog>\n `\n }\n </div>\n </div>\n `\n }\n </section>\n `;\n}\n\nfunction renderAgentFileRow(file: AgentFileEntry, active: string | null, onSelect: () => void) {\n const status = file.missing\n ? \"Missing\"\n : `${formatBytes(file.size)} · ${formatRelativeTimestamp(file.updatedAtMs ?? null)}`;\n return html`\n <button\n type=\"button\"\n class=\"agent-file-row ${active === file.name ? \"active\" : \"\"}\"\n @click=${onSelect}\n >\n <div>\n <div class=\"agent-file-name mono\">${file.name}</div>\n <div class=\"agent-file-meta\">${status}</div>\n </div>\n ${\n file.missing\n ? html`\n <span class=\"agent-pill warn\">missing</span>\n `\n : nothing\n }\n </button>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { normalizeToolName } from \"../../../../src/agents/tool-policy-shared.js\";\nimport type { SkillStatusEntry, SkillStatusReport, ToolsCatalogResult } from \"../types.ts\";\nimport {\n type AgentToolEntry,\n type AgentToolSection,\n isAllowedByPolicy,\n matchesList,\n resolveAgentConfig,\n resolveToolProfileOptions,\n resolveToolProfile,\n resolveToolSections,\n} from \"./agents-utils.ts\";\nimport type { SkillGroup } from \"./skills-grouping.ts\";\nimport { groupSkills } from \"./skills-grouping.ts\";\nimport {\n computeSkillMissing,\n computeSkillReasons,\n renderSkillStatusChips,\n} from \"./skills-shared.ts\";\n\nfunction renderToolBadges(section: AgentToolSection, tool: AgentToolEntry) {\n const source = tool.source ?? section.source;\n const pluginId = tool.pluginId ?? section.pluginId;\n const badges: string[] = [];\n if (source === \"plugin\" && pluginId) {\n badges.push(`plugin:${pluginId}`);\n } else if (source === \"core\") {\n badges.push(\"core\");\n }\n if (tool.optional) {\n badges.push(\"optional\");\n }\n if (badges.length === 0) {\n return nothing;\n }\n return html`\n <div style=\"display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px;\">\n ${badges.map((badge) => html`<span class=\"agent-pill\">${badge}</span>`)}\n </div>\n `;\n}\n\nexport function renderAgentTools(params: {\n agentId: string;\n configForm: Record<string, unknown> | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n toolsCatalogLoading: boolean;\n toolsCatalogError: string | null;\n toolsCatalogResult: ToolsCatalogResult | null;\n onProfileChange: (agentId: string, profile: string | null, clearAllow: boolean) => void;\n onOverridesChange: (agentId: string, alsoAllow: string[], deny: string[]) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n}) {\n const config = resolveAgentConfig(params.configForm, params.agentId);\n const agentTools = config.entry?.tools ?? {};\n const globalTools = config.globalTools ?? {};\n const profile = agentTools.profile ?? globalTools.profile ?? \"full\";\n const profileOptions = resolveToolProfileOptions(params.toolsCatalogResult);\n const toolSections = resolveToolSections(params.toolsCatalogResult);\n const profileSource = agentTools.profile\n ? \"agent override\"\n : globalTools.profile\n ? \"global default\"\n : \"default\";\n const hasAgentAllow = Array.isArray(agentTools.allow) && agentTools.allow.length > 0;\n const hasGlobalAllow = Array.isArray(globalTools.allow) && globalTools.allow.length > 0;\n const editable =\n Boolean(params.configForm) &&\n !params.configLoading &&\n !params.configSaving &&\n !hasAgentAllow &&\n !(params.toolsCatalogLoading && !params.toolsCatalogResult && !params.toolsCatalogError);\n const alsoAllow = hasAgentAllow\n ? []\n : Array.isArray(agentTools.alsoAllow)\n ? agentTools.alsoAllow\n : [];\n const deny = hasAgentAllow ? [] : Array.isArray(agentTools.deny) ? agentTools.deny : [];\n const basePolicy = hasAgentAllow\n ? { allow: agentTools.allow ?? [], deny: agentTools.deny ?? [] }\n : (resolveToolProfile(profile) ?? undefined);\n const toolIds = toolSections.flatMap((section) => section.tools.map((tool) => tool.id));\n\n const resolveAllowed = (toolId: string) => {\n const baseAllowed = isAllowedByPolicy(toolId, basePolicy);\n const extraAllowed = matchesList(toolId, alsoAllow);\n const denied = matchesList(toolId, deny);\n const allowed = (baseAllowed || extraAllowed) && !denied;\n return {\n allowed,\n baseAllowed,\n denied,\n };\n };\n const enabledCount = toolIds.filter((toolId) => resolveAllowed(toolId).allowed).length;\n\n const updateTool = (toolId: string, nextEnabled: boolean) => {\n const nextAllow = new Set(\n alsoAllow.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const nextDeny = new Set(\n deny.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const baseAllowed = resolveAllowed(toolId).baseAllowed;\n const normalized = normalizeToolName(toolId);\n if (nextEnabled) {\n nextDeny.delete(normalized);\n if (!baseAllowed) {\n nextAllow.add(normalized);\n }\n } else {\n nextAllow.delete(normalized);\n nextDeny.add(normalized);\n }\n params.onOverridesChange(params.agentId, [...nextAllow], [...nextDeny]);\n };\n\n const updateAll = (nextEnabled: boolean) => {\n const nextAllow = new Set(\n alsoAllow.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const nextDeny = new Set(\n deny.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n for (const toolId of toolIds) {\n const baseAllowed = resolveAllowed(toolId).baseAllowed;\n const normalized = normalizeToolName(toolId);\n if (nextEnabled) {\n nextDeny.delete(normalized);\n if (!baseAllowed) {\n nextAllow.add(normalized);\n }\n } else {\n nextAllow.delete(normalized);\n nextDeny.add(normalized);\n }\n }\n params.onOverridesChange(params.agentId, [...nextAllow], [...nextDeny]);\n };\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Tool Access</div>\n <div class=\"card-sub\">\n Profile + per-tool overrides for this agent.\n <span class=\"mono\">${enabledCount}/${toolIds.length}</span> enabled.\n </div>\n </div>\n <div class=\"row\" style=\"gap: 8px;\">\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => updateAll(true)}>\n Enable All\n </button>\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => updateAll(false)}>\n Disable All\n </button>\n <button class=\"btn btn--sm\" ?disabled=${params.configLoading} @click=${params.onConfigReload}>\n Reload Config\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.configSaving || !params.configDirty}\n @click=${params.onConfigSave}\n >\n ${params.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n\n ${\n !params.configForm\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the gateway config to adjust tool profiles.\n </div>\n `\n : nothing\n }\n ${\n hasAgentAllow\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n This agent is using an explicit allowlist in config. Tool overrides are managed in the Config tab.\n </div>\n `\n : nothing\n }\n ${\n hasGlobalAllow\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Global tools.allow is set. Agent overrides cannot enable tools that are globally blocked.\n </div>\n `\n : nothing\n }\n ${\n params.toolsCatalogLoading && !params.toolsCatalogResult && !params.toolsCatalogError\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">Loading runtime tool catalog…</div>\n `\n : nothing\n }\n ${\n params.toolsCatalogError\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Could not load runtime tool catalog. Showing built-in fallback list instead.\n </div>\n `\n : nothing\n }\n\n <div class=\"agent-tools-meta\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Profile</div>\n <div class=\"mono\">${profile}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Source</div>\n <div>${profileSource}</div>\n </div>\n ${\n params.configDirty\n ? html`\n <div class=\"agent-kv\">\n <div class=\"label\">Status</div>\n <div class=\"mono\">unsaved</div>\n </div>\n `\n : nothing\n }\n </div>\n\n <div class=\"agent-tools-presets\" style=\"margin-top: 16px;\">\n <div class=\"label\">Quick Presets</div>\n <div class=\"agent-tools-buttons\">\n ${profileOptions.map(\n (option) => html`\n <button\n class=\"btn btn--sm ${profile === option.id ? \"active\" : \"\"}\"\n ?disabled=${!editable}\n @click=${() => params.onProfileChange(params.agentId, option.id, true)}\n >\n ${option.label}\n </button>\n `,\n )}\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable}\n @click=${() => params.onProfileChange(params.agentId, null, false)}\n >\n Inherit\n </button>\n </div>\n </div>\n\n <div class=\"agent-tools-grid\" style=\"margin-top: 20px;\">\n ${toolSections.map(\n (section) =>\n html`\n <div class=\"agent-tools-section\">\n <div class=\"agent-tools-header\">\n ${section.label}\n ${\n section.source === \"plugin\" && section.pluginId\n ? html`<span class=\"agent-pill\" style=\"margin-left: 8px;\">plugin:${section.pluginId}</span>`\n : nothing\n }\n </div>\n <div class=\"agent-tools-list\">\n ${section.tools.map((tool) => {\n const { allowed } = resolveAllowed(tool.id);\n return html`\n <div class=\"agent-tool-row\">\n <div>\n <div class=\"agent-tool-title mono\">${tool.label}</div>\n <div class=\"agent-tool-sub\">${tool.description}</div>\n ${renderToolBadges(section, tool)}\n </div>\n <label class=\"cfg-toggle\">\n <input\n type=\"checkbox\"\n .checked=${allowed}\n ?disabled=${!editable}\n @change=${(e: Event) =>\n updateTool(tool.id, (e.target as HTMLInputElement).checked)}\n />\n <span class=\"cfg-toggle__track\"></span>\n </label>\n </div>\n `;\n })}\n </div>\n </div>\n `,\n )}\n </div>\n </section>\n `;\n}\n\nexport function renderAgentSkills(params: {\n agentId: string;\n report: SkillStatusReport | null;\n loading: boolean;\n error: string | null;\n activeAgentId: string | null;\n configForm: Record<string, unknown> | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n filter: string;\n onFilterChange: (next: string) => void;\n onRefresh: () => void;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n onClear: (agentId: string) => void;\n onDisableAll: (agentId: string) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n}) {\n const editable = Boolean(params.configForm) && !params.configLoading && !params.configSaving;\n const config = resolveAgentConfig(params.configForm, params.agentId);\n const allowlist = Array.isArray(config.entry?.skills) ? config.entry?.skills : undefined;\n const allowSet = new Set((allowlist ?? []).map((name) => name.trim()).filter(Boolean));\n const usingAllowlist = allowlist !== undefined;\n const reportReady = Boolean(params.report && params.activeAgentId === params.agentId);\n const rawSkills = reportReady ? (params.report?.skills ?? []) : [];\n const filter = params.filter.trim().toLowerCase();\n const filtered = filter\n ? rawSkills.filter((skill) =>\n [skill.name, skill.description, skill.source].join(\" \").toLowerCase().includes(filter),\n )\n : rawSkills;\n const groups = groupSkills(filtered);\n const enabledCount = usingAllowlist\n ? rawSkills.filter((skill) => allowSet.has(skill.name)).length\n : rawSkills.length;\n const totalCount = rawSkills.length;\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Skills</div>\n <div class=\"card-sub\">\n Per-agent skill allowlist and workspace skills.\n ${\n totalCount > 0\n ? html`<span class=\"mono\">${enabledCount}/${totalCount}</span>`\n : nothing\n }\n </div>\n </div>\n <div class=\"row\" style=\"gap: 8px; flex-wrap: wrap;\">\n <div class=\"row\" style=\"gap: 4px; border: 1px solid var(--border); border-radius: var(--radius-md); padding: 2px;\">\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => params.onClear(params.agentId)}>\n Enable All\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable}\n @click=${() => params.onDisableAll(params.agentId)}\n >\n Disable All\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable || !usingAllowlist}\n @click=${() => params.onClear(params.agentId)}\n title=\"Remove per-agent allowlist and use all skills\"\n >\n Reset\n </button>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.configLoading} @click=${params.onConfigReload}>\n Reload Config\n </button>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Loading…\" : \"Refresh\"}\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.configSaving || !params.configDirty}\n @click=${params.onConfigSave}\n >\n ${params.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n\n ${\n !params.configForm\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the gateway config to set per-agent skills.\n </div>\n `\n : nothing\n }\n ${\n usingAllowlist\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">This agent uses a custom skill allowlist.</div>\n `\n : html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n All skills are enabled. Disabling any skill will create a per-agent allowlist.\n </div>\n `\n }\n ${\n !reportReady && !params.loading\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load skills for this agent to view workspace-specific entries.\n </div>\n `\n : nothing\n }\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n\n <div class=\"filters\" style=\"margin-top: 14px;\">\n <label class=\"field\" style=\"flex: 1;\">\n <span>Filter</span>\n <input\n .value=${params.filter}\n @input=${(e: Event) => params.onFilterChange((e.target as HTMLInputElement).value)}\n placeholder=\"Search skills\"\n autocomplete=\"off\"\n name=\"agent-skills-filter\"\n />\n </label>\n <div class=\"muted\">${filtered.length} shown</div>\n </div>\n\n ${\n filtered.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No skills found.</div>\n `\n : html`\n <div class=\"agent-skills-groups\" style=\"margin-top: 16px;\">\n ${groups.map((group) =>\n renderAgentSkillGroup(group, {\n agentId: params.agentId,\n allowSet,\n usingAllowlist,\n editable,\n onToggle: params.onToggle,\n }),\n )}\n </div>\n `\n }\n </section>\n `;\n}\n\nfunction renderAgentSkillGroup(\n group: SkillGroup,\n params: {\n agentId: string;\n allowSet: Set<string>;\n usingAllowlist: boolean;\n editable: boolean;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n },\n) {\n const collapsedByDefault = group.id === \"workspace\" || group.id === \"built-in\";\n return html`\n <details class=\"agent-skills-group\" ?open=${!collapsedByDefault}>\n <summary class=\"agent-skills-header\">\n <span>${group.label}</span>\n <span class=\"muted\">${group.skills.length}</span>\n </summary>\n <div class=\"list skills-grid\">\n ${group.skills.map((skill) =>\n renderAgentSkillRow(skill, {\n agentId: params.agentId,\n allowSet: params.allowSet,\n usingAllowlist: params.usingAllowlist,\n editable: params.editable,\n onToggle: params.onToggle,\n }),\n )}\n </div>\n </details>\n `;\n}\n\nfunction renderAgentSkillRow(\n skill: SkillStatusEntry,\n params: {\n agentId: string;\n allowSet: Set<string>;\n usingAllowlist: boolean;\n editable: boolean;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n },\n) {\n const enabled = params.usingAllowlist ? params.allowSet.has(skill.name) : true;\n const missing = computeSkillMissing(skill);\n const reasons = computeSkillReasons(skill);\n return html`\n <div class=\"list-item agent-skill-row\">\n <div class=\"list-main\">\n <div class=\"list-title\">${skill.emoji ? `${skill.emoji} ` : \"\"}${skill.name}</div>\n <div class=\"list-sub\">${skill.description}</div>\n ${renderSkillStatusChips({ skill })}\n ${\n missing.length > 0\n ? html`<div class=\"muted\" style=\"margin-top: 6px;\">Missing: ${missing.join(\", \")}</div>`\n : nothing\n }\n ${\n reasons.length > 0\n ? html`<div class=\"muted\" style=\"margin-top: 6px;\">Reason: ${reasons.join(\", \")}</div>`\n : nothing\n }\n </div>\n <div class=\"list-meta\">\n <label class=\"cfg-toggle\">\n <input\n type=\"checkbox\"\n .checked=${enabled}\n ?disabled=${!params.editable}\n @change=${(e: Event) =>\n params.onToggle(params.agentId, skill.name, (e.target as HTMLInputElement).checked)}\n />\n <span class=\"cfg-toggle__track\"></span>\n </label>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type {\n AgentIdentityResult,\n AgentsFilesListResult,\n AgentsListResult,\n ChannelsStatusSnapshot,\n CronJob,\n CronStatus,\n SkillStatusReport,\n ToolsCatalogResult,\n} from \"../types.ts\";\nimport { renderAgentOverview } from \"./agents-panels-overview.ts\";\nimport {\n renderAgentFiles,\n renderAgentChannels,\n renderAgentCron,\n} from \"./agents-panels-status-files.ts\";\nimport { renderAgentTools, renderAgentSkills } from \"./agents-panels-tools-skills.ts\";\nimport { agentBadgeText, buildAgentContext, normalizeAgentLabel } from \"./agents-utils.ts\";\n\nexport type AgentsPanel = \"overview\" | \"files\" | \"tools\" | \"skills\" | \"channels\" | \"cron\";\n\nexport type ConfigState = {\n form: Record<string, unknown> | null;\n loading: boolean;\n saving: boolean;\n dirty: boolean;\n};\n\nexport type ChannelsState = {\n snapshot: ChannelsStatusSnapshot | null;\n loading: boolean;\n error: string | null;\n lastSuccess: number | null;\n};\n\nexport type CronState = {\n status: CronStatus | null;\n jobs: CronJob[];\n loading: boolean;\n error: string | null;\n};\n\nexport type AgentFilesState = {\n list: AgentsFilesListResult | null;\n loading: boolean;\n error: string | null;\n active: string | null;\n contents: Record<string, string>;\n drafts: Record<string, string>;\n saving: boolean;\n};\n\nexport type AgentSkillsState = {\n report: SkillStatusReport | null;\n loading: boolean;\n error: string | null;\n agentId: string | null;\n filter: string;\n};\n\nexport type ToolsCatalogState = {\n loading: boolean;\n error: string | null;\n result: ToolsCatalogResult | null;\n};\n\nexport type AgentsProps = {\n basePath: string;\n loading: boolean;\n error: string | null;\n agentsList: AgentsListResult | null;\n selectedAgentId: string | null;\n activePanel: AgentsPanel;\n config: ConfigState;\n channels: ChannelsState;\n cron: CronState;\n agentFiles: AgentFilesState;\n agentIdentityLoading: boolean;\n agentIdentityError: string | null;\n agentIdentityById: Record<string, AgentIdentityResult>;\n agentSkills: AgentSkillsState;\n toolsCatalog: ToolsCatalogState;\n onRefresh: () => void;\n onSelectAgent: (agentId: string) => void;\n onSelectPanel: (panel: AgentsPanel) => void;\n onLoadFiles: (agentId: string) => void;\n onSelectFile: (name: string) => void;\n onFileDraftChange: (name: string, content: string) => void;\n onFileReset: (name: string) => void;\n onFileSave: (name: string) => void;\n onToolsProfileChange: (agentId: string, profile: string | null, clearAllow: boolean) => void;\n onToolsOverridesChange: (agentId: string, alsoAllow: string[], deny: string[]) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n onModelChange: (agentId: string, modelId: string | null) => void;\n onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void;\n onChannelsRefresh: () => void;\n onCronRefresh: () => void;\n onCronRunNow: (jobId: string) => void;\n onSkillsFilterChange: (next: string) => void;\n onSkillsRefresh: () => void;\n onAgentSkillToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n onAgentSkillsClear: (agentId: string) => void;\n onAgentSkillsDisableAll: (agentId: string) => void;\n onSetDefault: (agentId: string) => void;\n};\n\nexport function renderAgents(props: AgentsProps) {\n const agents = props.agentsList?.agents ?? [];\n const defaultId = props.agentsList?.defaultId ?? null;\n const selectedId = props.selectedAgentId ?? defaultId ?? agents[0]?.id ?? null;\n const selectedAgent = selectedId\n ? (agents.find((agent) => agent.id === selectedId) ?? null)\n : null;\n const selectedSkillCount =\n selectedId && props.agentSkills.agentId === selectedId\n ? (props.agentSkills.report?.skills?.length ?? null)\n : null;\n\n const channelEntryCount = props.channels.snapshot\n ? Object.keys(props.channels.snapshot.channelAccounts ?? {}).length\n : null;\n const cronJobCount = selectedId\n ? props.cron.jobs.filter((j) => j.agentId === selectedId).length\n : null;\n const tabCounts: Record<string, number | null> = {\n files: props.agentFiles.list?.files?.length ?? null,\n skills: selectedSkillCount,\n channels: channelEntryCount,\n cron: cronJobCount || null,\n };\n\n return html`\n <div class=\"agents-layout\">\n <section class=\"agents-toolbar\">\n <div class=\"agents-toolbar-row\">\n <span class=\"agents-toolbar-label\">Agent</span>\n <div class=\"agents-control-row\">\n <div class=\"agents-control-select\">\n <select\n class=\"agents-select\"\n .value=${selectedId ?? \"\"}\n ?disabled=${props.loading || agents.length === 0}\n @change=${(e: Event) => props.onSelectAgent((e.target as HTMLSelectElement).value)}\n >\n ${\n agents.length === 0\n ? html`\n <option value=\"\">No agents</option>\n `\n : agents.map(\n (agent) => html`\n <option value=${agent.id} ?selected=${agent.id === selectedId}>\n ${normalizeAgentLabel(agent)}${agentBadgeText(agent.id, defaultId) ? ` (${agentBadgeText(agent.id, defaultId)})` : \"\"}\n </option>\n `,\n )\n }\n </select>\n </div>\n <div class=\"agents-control-actions\">\n ${\n selectedAgent\n ? html`\n <div class=\"agent-actions-wrap\">\n <button\n class=\"agent-actions-toggle\"\n type=\"button\"\n @click=${() => {\n actionsMenuOpen = !actionsMenuOpen;\n }}\n >⋯</button>\n ${\n actionsMenuOpen\n ? html`\n <div class=\"agent-actions-menu\">\n <button type=\"button\" @click=${() => {\n void navigator.clipboard.writeText(selectedAgent.id);\n actionsMenuOpen = false;\n }}>Copy agent ID</button>\n <button\n type=\"button\"\n ?disabled=${Boolean(defaultId && selectedAgent.id === defaultId)}\n @click=${() => {\n props.onSetDefault(selectedAgent.id);\n actionsMenuOpen = false;\n }}\n >\n ${defaultId && selectedAgent.id === defaultId ? \"Already default\" : \"Set as default\"}\n </button>\n </div>\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n <button class=\"btn btn--sm agents-refresh-btn\" ?disabled=${props.loading} @click=${props.onRefresh}>\n ${props.loading ? \"Loading…\" : \"Refresh\"}\n </button>\n </div>\n </div>\n </div>\n ${\n props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 8px;\">${props.error}</div>`\n : nothing\n }\n </section>\n <section class=\"agents-main\">\n ${\n !selectedAgent\n ? html`\n <div class=\"card\">\n <div class=\"card-title\">Select an agent</div>\n <div class=\"card-sub\">Pick an agent to inspect its workspace and tools.</div>\n </div>\n `\n : html`\n ${renderAgentTabs(props.activePanel, (panel) => props.onSelectPanel(panel), tabCounts)}\n ${\n props.activePanel === \"overview\"\n ? renderAgentOverview({\n agent: selectedAgent,\n basePath: props.basePath,\n defaultId,\n configForm: props.config.form,\n agentFilesList: props.agentFiles.list,\n agentIdentity: props.agentIdentityById[selectedAgent.id] ?? null,\n agentIdentityError: props.agentIdentityError,\n agentIdentityLoading: props.agentIdentityLoading,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n onModelChange: props.onModelChange,\n onModelFallbacksChange: props.onModelFallbacksChange,\n onSelectPanel: props.onSelectPanel,\n })\n : nothing\n }\n ${\n props.activePanel === \"files\"\n ? renderAgentFiles({\n agentId: selectedAgent.id,\n agentFilesList: props.agentFiles.list,\n agentFilesLoading: props.agentFiles.loading,\n agentFilesError: props.agentFiles.error,\n agentFileActive: props.agentFiles.active,\n agentFileContents: props.agentFiles.contents,\n agentFileDrafts: props.agentFiles.drafts,\n agentFileSaving: props.agentFiles.saving,\n onLoadFiles: props.onLoadFiles,\n onSelectFile: props.onSelectFile,\n onFileDraftChange: props.onFileDraftChange,\n onFileReset: props.onFileReset,\n onFileSave: props.onFileSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"tools\"\n ? renderAgentTools({\n agentId: selectedAgent.id,\n configForm: props.config.form,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n toolsCatalogLoading: props.toolsCatalog.loading,\n toolsCatalogError: props.toolsCatalog.error,\n toolsCatalogResult: props.toolsCatalog.result,\n onProfileChange: props.onToolsProfileChange,\n onOverridesChange: props.onToolsOverridesChange,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"skills\"\n ? renderAgentSkills({\n agentId: selectedAgent.id,\n report: props.agentSkills.report,\n loading: props.agentSkills.loading,\n error: props.agentSkills.error,\n activeAgentId: props.agentSkills.agentId,\n configForm: props.config.form,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n filter: props.agentSkills.filter,\n onFilterChange: props.onSkillsFilterChange,\n onRefresh: props.onSkillsRefresh,\n onToggle: props.onAgentSkillToggle,\n onClear: props.onAgentSkillsClear,\n onDisableAll: props.onAgentSkillsDisableAll,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"channels\"\n ? renderAgentChannels({\n context: buildAgentContext(\n selectedAgent,\n props.config.form,\n props.agentFiles.list,\n defaultId,\n props.agentIdentityById[selectedAgent.id] ?? null,\n ),\n configForm: props.config.form,\n snapshot: props.channels.snapshot,\n loading: props.channels.loading,\n error: props.channels.error,\n lastSuccess: props.channels.lastSuccess,\n onRefresh: props.onChannelsRefresh,\n })\n : nothing\n }\n ${\n props.activePanel === \"cron\"\n ? renderAgentCron({\n context: buildAgentContext(\n selectedAgent,\n props.config.form,\n props.agentFiles.list,\n defaultId,\n props.agentIdentityById[selectedAgent.id] ?? null,\n ),\n agentId: selectedAgent.id,\n jobs: props.cron.jobs,\n status: props.cron.status,\n loading: props.cron.loading,\n error: props.cron.error,\n onRefresh: props.onCronRefresh,\n onRunNow: props.onCronRunNow,\n })\n : nothing\n }\n `\n }\n </section>\n </div>\n `;\n}\n\nlet actionsMenuOpen = false;\n\nfunction renderAgentTabs(\n active: AgentsPanel,\n onSelect: (panel: AgentsPanel) => void,\n counts: Record<string, number | null>,\n) {\n const tabs: Array<{ id: AgentsPanel; label: string }> = [\n { id: \"overview\", label: \"Overview\" },\n { id: \"files\", label: \"Files\" },\n { id: \"tools\", label: \"Tools\" },\n { id: \"skills\", label: \"Skills\" },\n { id: \"channels\", label: \"Channels\" },\n { id: \"cron\", label: \"Cron Jobs\" },\n ];\n return html`\n <div class=\"agent-tabs\">\n ${tabs.map(\n (tab) => html`\n <button\n class=\"agent-tab ${active === tab.id ? \"active\" : \"\"}\"\n type=\"button\"\n @click=${() => onSelect(tab.id)}\n >\n ${tab.label}${counts[tab.id] != null ? html`<span class=\"agent-tab-count\">${counts[tab.id]}</span>` : nothing}\n </button>\n `,\n )}\n </div>\n `;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents-CRGOH5CC.js","names":[],"sources":["../../../ui/src/ui/views/agents-panels-overview.ts","../../../ui/src/ui/views/agents-panels-status-files.ts","../../../ui/src/ui/views/agents-panels-tools-skills.ts","../../../ui/src/ui/views/agents.ts"],"sourcesContent":["import { html, nothing } from \"lit\";\nimport type { AgentIdentityResult, AgentsFilesListResult, AgentsListResult } from \"../types.ts\";\nimport {\n buildModelOptions,\n normalizeModelValue,\n parseFallbackList,\n resolveAgentConfig,\n resolveModelFallbacks,\n resolveModelLabel,\n resolveModelPrimary,\n} from \"./agents-utils.ts\";\nimport type { AgentsPanel } from \"./agents.ts\";\n\nexport function renderAgentOverview(params: {\n agent: AgentsListResult[\"agents\"][number];\n basePath: string;\n defaultId: string | null;\n configForm: Record<string, unknown> | null;\n agentFilesList: AgentsFilesListResult | null;\n agentIdentity: AgentIdentityResult | null;\n agentIdentityLoading: boolean;\n agentIdentityError: string | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n onConfigReload: () => void;\n onConfigSave: () => void;\n onModelChange: (agentId: string, modelId: string | null) => void;\n onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void;\n onSelectPanel: (panel: AgentsPanel) => void;\n}) {\n const {\n agent,\n configForm,\n agentFilesList,\n configLoading,\n configSaving,\n configDirty,\n onConfigReload,\n onConfigSave,\n onModelChange,\n onModelFallbacksChange,\n onSelectPanel,\n } = params;\n const config = resolveAgentConfig(configForm, agent.id);\n const workspaceFromFiles =\n agentFilesList && agentFilesList.agentId === agent.id ? agentFilesList.workspace : null;\n const workspace =\n workspaceFromFiles || config.entry?.workspace || config.defaults?.workspace || \"default\";\n const model = config.entry?.model\n ? resolveModelLabel(config.entry?.model)\n : resolveModelLabel(config.defaults?.model);\n const defaultModel = resolveModelLabel(config.defaults?.model);\n const entryPrimary = resolveModelPrimary(config.entry?.model);\n const defaultPrimary =\n resolveModelPrimary(config.defaults?.model) ||\n (defaultModel !== \"-\" ? normalizeModelValue(defaultModel) : null);\n const effectivePrimary = entryPrimary ?? defaultPrimary ?? null;\n const modelFallbacks = resolveModelFallbacks(config.entry?.model);\n const fallbackChips = modelFallbacks ?? [];\n const skillFilter = Array.isArray(config.entry?.skills) ? config.entry?.skills : null;\n const skillCount = skillFilter?.length ?? null;\n const isDefault = Boolean(params.defaultId && agent.id === params.defaultId);\n const disabled = !configForm || configLoading || configSaving;\n\n const removeChip = (index: number) => {\n const next = fallbackChips.filter((_, i) => i !== index);\n onModelFallbacksChange(agent.id, next);\n };\n\n const handleChipKeydown = (e: KeyboardEvent) => {\n const input = e.target as HTMLInputElement;\n if (e.key === \"Enter\" || e.key === \",\") {\n e.preventDefault();\n const parsed = parseFallbackList(input.value);\n if (parsed.length > 0) {\n onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);\n input.value = \"\";\n }\n }\n };\n\n return html`\n <section class=\"card\">\n <div class=\"card-title\">Overview</div>\n <div class=\"card-sub\">Workspace paths and identity metadata.</div>\n\n <div class=\"agents-overview-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Workspace</div>\n <div>\n <button\n type=\"button\"\n class=\"workspace-link mono\"\n @click=${() => onSelectPanel(\"files\")}\n title=\"Open Files tab\"\n >${workspace}</button>\n </div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Primary Model</div>\n <div class=\"mono\">${model}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Skills Filter</div>\n <div>${skillFilter ? `${skillCount} selected` : \"all skills\"}</div>\n </div>\n </div>\n\n ${\n configDirty\n ? html`\n <div class=\"callout warn\" style=\"margin-top: 16px\">You have unsaved config changes.</div>\n `\n : nothing\n }\n\n <div class=\"agent-model-select\" style=\"margin-top: 20px;\">\n <div class=\"label\">Model Selection</div>\n <div class=\"agent-model-fields\">\n <label class=\"field\">\n <span>Primary model${isDefault ? \" (default)\" : \"\"}</span>\n <select\n .value=${isDefault ? (effectivePrimary ?? \"\") : (entryPrimary ?? \"\")}\n ?disabled=${disabled}\n @change=${(e: Event) =>\n onModelChange(agent.id, (e.target as HTMLSelectElement).value || null)}\n >\n ${\n isDefault\n ? nothing\n : html`\n <option value=\"\">\n ${defaultPrimary ? `Inherit default (${defaultPrimary})` : \"Inherit default\"}\n </option>\n `\n }\n ${buildModelOptions(configForm, effectivePrimary ?? undefined)}\n </select>\n </label>\n <div class=\"field\">\n <span>Fallbacks</span>\n <div class=\"agent-chip-input\" @click=${(e: Event) => {\n const container = e.currentTarget as HTMLElement;\n const input = container.querySelector(\"input\");\n if (input) {\n input.focus();\n }\n }}>\n ${fallbackChips.map(\n (chip, i) => html`\n <span class=\"chip\">\n ${chip}\n <button\n type=\"button\"\n class=\"chip-remove\"\n ?disabled=${disabled}\n @click=${() => removeChip(i)}\n >&times;</button>\n </span>\n `,\n )}\n <input\n ?disabled=${disabled}\n placeholder=${fallbackChips.length === 0 ? \"provider/model\" : \"\"}\n @keydown=${handleChipKeydown}\n @blur=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n const parsed = parseFallbackList(input.value);\n if (parsed.length > 0) {\n onModelFallbacksChange(agent.id, [...fallbackChips, ...parsed]);\n input.value = \"\";\n }\n }}\n />\n </div>\n </div>\n </div>\n <div class=\"agent-model-actions\">\n <button type=\"button\" class=\"btn btn--sm\" ?disabled=${configLoading} @click=${onConfigReload}>\n Reload Config\n </button>\n <button\n type=\"button\"\n class=\"btn btn--sm primary\"\n ?disabled=${configSaving || !configDirty}\n @click=${onConfigSave}\n >\n ${configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n </section>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport { icons } from \"../icons.ts\";\nimport { toSanitizedMarkdownHtml } from \"../markdown.ts\";\nimport {\n formatCronPayload,\n formatCronSchedule,\n formatCronState,\n formatNextRun,\n} from \"../presenter.ts\";\nimport type {\n AgentFileEntry,\n AgentsFilesListResult,\n ChannelAccountSnapshot,\n ChannelsStatusSnapshot,\n CronJob,\n CronStatus,\n} from \"../types.ts\";\nimport { formatBytes, type AgentContext } from \"./agents-utils.ts\";\nimport { resolveChannelExtras as resolveChannelExtrasFromConfig } from \"./channel-config-extras.ts\";\n\nfunction renderAgentContextCard(context: AgentContext, subtitle: string) {\n return html`\n <section class=\"card\">\n <div class=\"card-title\">Agent Context</div>\n <div class=\"card-sub\">${subtitle}</div>\n <div class=\"agents-overview-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Workspace</div>\n <div class=\"mono\">${context.workspace}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Primary Model</div>\n <div class=\"mono\">${context.model}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Identity Name</div>\n <div>${context.identityName}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Identity Avatar</div>\n <div>${context.identityAvatar}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Skills Filter</div>\n <div>${context.skillsLabel}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Default</div>\n <div>${context.isDefault ? \"yes\" : \"no\"}</div>\n </div>\n </div>\n </section>\n `;\n}\n\ntype ChannelSummaryEntry = {\n id: string;\n label: string;\n accounts: ChannelAccountSnapshot[];\n};\n\nfunction resolveChannelLabel(snapshot: ChannelsStatusSnapshot, id: string) {\n const meta = snapshot.channelMeta?.find((entry) => entry.id === id);\n if (meta?.label) {\n return meta.label;\n }\n return snapshot.channelLabels?.[id] ?? id;\n}\n\nfunction resolveChannelEntries(snapshot: ChannelsStatusSnapshot | null): ChannelSummaryEntry[] {\n if (!snapshot) {\n return [];\n }\n const ids = new Set<string>();\n for (const id of snapshot.channelOrder ?? []) {\n ids.add(id);\n }\n for (const entry of snapshot.channelMeta ?? []) {\n ids.add(entry.id);\n }\n for (const id of Object.keys(snapshot.channelAccounts ?? {})) {\n ids.add(id);\n }\n const ordered: string[] = [];\n const seed = snapshot.channelOrder?.length ? snapshot.channelOrder : Array.from(ids);\n for (const id of seed) {\n if (!ids.has(id)) {\n continue;\n }\n ordered.push(id);\n ids.delete(id);\n }\n for (const id of ids) {\n ordered.push(id);\n }\n return ordered.map((id) => ({\n id,\n label: resolveChannelLabel(snapshot, id),\n accounts: snapshot.channelAccounts?.[id] ?? [],\n }));\n}\n\nconst CHANNEL_EXTRA_FIELDS = [\"groupPolicy\", \"streamMode\", \"dmPolicy\"] as const;\n\nfunction summarizeChannelAccounts(accounts: ChannelAccountSnapshot[]) {\n let connected = 0;\n let configured = 0;\n let enabled = 0;\n for (const account of accounts) {\n const probeOk =\n account.probe && typeof account.probe === \"object\" && \"ok\" in account.probe\n ? Boolean((account.probe as { ok?: unknown }).ok)\n : false;\n const isConnected = account.connected === true || account.running === true || probeOk;\n if (isConnected) {\n connected += 1;\n }\n if (account.configured) {\n configured += 1;\n }\n if (account.enabled) {\n enabled += 1;\n }\n }\n return {\n total: accounts.length,\n connected,\n configured,\n enabled,\n };\n}\n\nexport function renderAgentChannels(params: {\n context: AgentContext;\n configForm: Record<string, unknown> | null;\n snapshot: ChannelsStatusSnapshot | null;\n loading: boolean;\n error: string | null;\n lastSuccess: number | null;\n onRefresh: () => void;\n}) {\n const entries = resolveChannelEntries(params.snapshot);\n const lastSuccessLabel = params.lastSuccess\n ? formatRelativeTimestamp(params.lastSuccess)\n : \"never\";\n return html`\n <section class=\"grid grid-cols-2\">\n ${renderAgentContextCard(params.context, \"Workspace, identity, and model configuration.\")}\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Channels</div>\n <div class=\"card-sub\">Gateway-wide channel status snapshot.</div>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Refreshing…\" : \"Refresh\"}\n </button>\n </div>\n <div class=\"muted\" style=\"margin-top: 8px;\">\n Last refresh: ${lastSuccessLabel}\n </div>\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n ${\n !params.snapshot\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">Load channels to see live status.</div>\n `\n : nothing\n }\n ${\n entries.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No channels found.</div>\n `\n : html`\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${entries.map((entry) => {\n const summary = summarizeChannelAccounts(entry.accounts);\n const status = summary.total\n ? `${summary.connected}/${summary.total} connected`\n : \"no accounts\";\n const configLabel = summary.configured\n ? `${summary.configured} configured`\n : \"not configured\";\n const enabled = summary.total ? `${summary.enabled} enabled` : \"disabled\";\n const extras = resolveChannelExtrasFromConfig({\n configForm: params.configForm,\n channelId: entry.id,\n fields: CHANNEL_EXTRA_FIELDS,\n });\n return html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${entry.label}</div>\n <div class=\"list-sub mono\">${entry.id}</div>\n </div>\n <div class=\"list-meta\">\n <div>${status}</div>\n <div>${configLabel}</div>\n <div>${enabled}</div>\n ${\n summary.configured === 0\n ? html`\n <div>\n <a\n href=\"https://docs.openclaw.ai/channels\"\n target=\"_blank\"\n rel=\"noopener\"\n style=\"color: var(--accent); font-size: 12px\"\n >Setup guide</a\n >\n </div>\n `\n : nothing\n }\n ${\n extras.length > 0\n ? extras.map(\n (extra) => html`<div>${extra.label}: ${extra.value}</div>`,\n )\n : nothing\n }\n </div>\n </div>\n `;\n })}\n </div>\n `\n }\n </section>\n </section>\n `;\n}\n\nexport function renderAgentCron(params: {\n context: AgentContext;\n agentId: string;\n jobs: CronJob[];\n status: CronStatus | null;\n loading: boolean;\n error: string | null;\n onRefresh: () => void;\n onRunNow: (jobId: string) => void;\n}) {\n const jobs = params.jobs.filter((job) => job.agentId === params.agentId);\n return html`\n <section class=\"grid grid-cols-2\">\n ${renderAgentContextCard(params.context, \"Workspace and scheduling targets.\")}\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Scheduler</div>\n <div class=\"card-sub\">Gateway cron status.</div>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Refreshing…\" : \"Refresh\"}\n </button>\n </div>\n <div class=\"stat-grid\" style=\"margin-top: 16px;\">\n <div class=\"stat\">\n <div class=\"stat-label\">Enabled</div>\n <div class=\"stat-value\">\n ${params.status ? (params.status.enabled ? \"Yes\" : \"No\") : \"n/a\"}\n </div>\n </div>\n <div class=\"stat\">\n <div class=\"stat-label\">Jobs</div>\n <div class=\"stat-value\">${params.status?.jobs ?? \"n/a\"}</div>\n </div>\n <div class=\"stat\">\n <div class=\"stat-label\">Next wake</div>\n <div class=\"stat-value\">${formatNextRun(params.status?.nextWakeAtMs ?? null)}</div>\n </div>\n </div>\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n </section>\n </section>\n <section class=\"card\">\n <div class=\"card-title\">Agent Cron Jobs</div>\n <div class=\"card-sub\">Scheduled jobs targeting this agent.</div>\n ${\n jobs.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No jobs assigned.</div>\n `\n : html`\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${jobs.map(\n (job) => html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${job.name}</div>\n ${\n job.description\n ? html`<div class=\"list-sub\">${job.description}</div>`\n : nothing\n }\n <div class=\"chip-row\" style=\"margin-top: 6px;\">\n <span class=\"chip\">${formatCronSchedule(job)}</span>\n <span class=\"chip ${job.enabled ? \"chip-ok\" : \"chip-warn\"}\">\n ${job.enabled ? \"enabled\" : \"disabled\"}\n </span>\n <span class=\"chip\">${job.sessionTarget}</span>\n </div>\n </div>\n <div class=\"list-meta\">\n <div class=\"mono\">${formatCronState(job)}</div>\n <div class=\"muted\">${formatCronPayload(job)}</div>\n <button\n class=\"btn btn--sm\"\n style=\"margin-top: 6px;\"\n ?disabled=${!job.enabled}\n @click=${() => params.onRunNow(job.id)}\n >Run Now</button>\n </div>\n </div>\n `,\n )}\n </div>\n `\n }\n </section>\n `;\n}\n\nexport function renderAgentFiles(params: {\n agentId: string;\n agentFilesList: AgentsFilesListResult | null;\n agentFilesLoading: boolean;\n agentFilesError: string | null;\n agentFileActive: string | null;\n agentFileContents: Record<string, string>;\n agentFileDrafts: Record<string, string>;\n agentFileSaving: boolean;\n onLoadFiles: (agentId: string) => void;\n onSelectFile: (name: string) => void;\n onFileDraftChange: (name: string, content: string) => void;\n onFileReset: (name: string) => void;\n onFileSave: (name: string) => void;\n}) {\n const list = params.agentFilesList?.agentId === params.agentId ? params.agentFilesList : null;\n const files = list?.files ?? [];\n const active = params.agentFileActive ?? null;\n const activeEntry = active ? (files.find((file) => file.name === active) ?? null) : null;\n const baseContent = active ? (params.agentFileContents[active] ?? \"\") : \"\";\n const draft = active ? (params.agentFileDrafts[active] ?? baseContent) : \"\";\n const isDirty = active ? draft !== baseContent : false;\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Core Files</div>\n <div class=\"card-sub\">Bootstrap persona, identity, and tool guidance.</div>\n </div>\n <button\n class=\"btn btn--sm\"\n ?disabled=${params.agentFilesLoading}\n @click=${() => params.onLoadFiles(params.agentId)}\n >\n ${params.agentFilesLoading ? \"Loading…\" : \"Refresh\"}\n </button>\n </div>\n ${\n list\n ? html`<div class=\"muted mono\" style=\"margin-top: 8px;\">Workspace: ${list.workspace}</div>`\n : nothing\n }\n ${\n params.agentFilesError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.agentFilesError}</div>`\n : nothing\n }\n ${\n !list\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the agent workspace files to edit core instructions.\n </div>\n `\n : html`\n <div class=\"agent-files-grid\" style=\"margin-top: 16px;\">\n <div class=\"agent-files-list\">\n ${\n files.length === 0\n ? html`\n <div class=\"muted\">No files found.</div>\n `\n : files.map((file) =>\n renderAgentFileRow(file, active, () => params.onSelectFile(file.name)),\n )\n }\n </div>\n <div class=\"agent-files-editor\">\n ${\n !activeEntry\n ? html`\n <div class=\"muted\">Select a file to edit.</div>\n `\n : html`\n <div class=\"agent-file-header\">\n <div>\n <div class=\"agent-file-title mono\">${activeEntry.name}</div>\n <div class=\"agent-file-sub mono\">${activeEntry.path}</div>\n </div>\n <div class=\"agent-file-actions\">\n <button\n class=\"btn btn--sm\"\n title=\"Preview rendered markdown\"\n @click=${(e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n const dialog = btn\n .closest(\".agent-files-editor\")\n ?.querySelector(\"dialog\");\n if (dialog) {\n dialog.showModal();\n }\n }}\n >\n ${icons.eye} Preview\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!isDirty}\n @click=${() => params.onFileReset(activeEntry.name)}\n >\n Reset\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.agentFileSaving || !isDirty}\n @click=${() => params.onFileSave(activeEntry.name)}\n >\n ${params.agentFileSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n ${\n activeEntry.missing\n ? html`\n <div class=\"callout info\" style=\"margin-top: 10px\">\n This file is missing. Saving will create it in the agent workspace.\n </div>\n `\n : nothing\n }\n <label class=\"field agent-file-field\" style=\"margin-top: 12px;\">\n <span>Content</span>\n <textarea\n class=\"agent-file-textarea\"\n .value=${draft}\n @input=${(e: Event) =>\n params.onFileDraftChange(\n activeEntry.name,\n (e.target as HTMLTextAreaElement).value,\n )}\n ></textarea>\n </label>\n <dialog\n class=\"md-preview-dialog\"\n @click=${(e: Event) => {\n const dialog = e.currentTarget as HTMLDialogElement;\n if (e.target === dialog) {\n dialog.close();\n }\n }}\n >\n <div class=\"md-preview-dialog__panel\">\n <div class=\"md-preview-dialog__header\">\n <div class=\"md-preview-dialog__title mono\">${activeEntry.name}</div>\n <button\n class=\"btn btn--sm\"\n @click=${(e: Event) => {\n (e.currentTarget as HTMLElement).closest(\"dialog\")?.close();\n }}\n >${icons.x} Close</button>\n </div>\n <div class=\"md-preview-dialog__body sidebar-markdown\">\n ${unsafeHTML(toSanitizedMarkdownHtml(draft))}\n </div>\n </div>\n </dialog>\n `\n }\n </div>\n </div>\n `\n }\n </section>\n `;\n}\n\nfunction renderAgentFileRow(file: AgentFileEntry, active: string | null, onSelect: () => void) {\n const status = file.missing\n ? \"Missing\"\n : `${formatBytes(file.size)} · ${formatRelativeTimestamp(file.updatedAtMs ?? null)}`;\n return html`\n <button\n type=\"button\"\n class=\"agent-file-row ${active === file.name ? \"active\" : \"\"}\"\n @click=${onSelect}\n >\n <div>\n <div class=\"agent-file-name mono\">${file.name}</div>\n <div class=\"agent-file-meta\">${status}</div>\n </div>\n ${\n file.missing\n ? html`\n <span class=\"agent-pill warn\">missing</span>\n `\n : nothing\n }\n </button>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { normalizeToolName } from \"../../../../src/agents/tool-policy-shared.js\";\nimport type { SkillStatusEntry, SkillStatusReport, ToolsCatalogResult } from \"../types.ts\";\nimport {\n type AgentToolEntry,\n type AgentToolSection,\n isAllowedByPolicy,\n matchesList,\n resolveAgentConfig,\n resolveToolProfileOptions,\n resolveToolProfile,\n resolveToolSections,\n} from \"./agents-utils.ts\";\nimport type { SkillGroup } from \"./skills-grouping.ts\";\nimport { groupSkills } from \"./skills-grouping.ts\";\nimport {\n computeSkillMissing,\n computeSkillReasons,\n renderSkillStatusChips,\n} from \"./skills-shared.ts\";\n\nfunction renderToolBadges(section: AgentToolSection, tool: AgentToolEntry) {\n const source = tool.source ?? section.source;\n const pluginId = tool.pluginId ?? section.pluginId;\n const badges: string[] = [];\n if (source === \"plugin\" && pluginId) {\n badges.push(`plugin:${pluginId}`);\n } else if (source === \"core\") {\n badges.push(\"core\");\n }\n if (tool.optional) {\n badges.push(\"optional\");\n }\n if (badges.length === 0) {\n return nothing;\n }\n return html`\n <div style=\"display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px;\">\n ${badges.map((badge) => html`<span class=\"agent-pill\">${badge}</span>`)}\n </div>\n `;\n}\n\nexport function renderAgentTools(params: {\n agentId: string;\n configForm: Record<string, unknown> | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n toolsCatalogLoading: boolean;\n toolsCatalogError: string | null;\n toolsCatalogResult: ToolsCatalogResult | null;\n onProfileChange: (agentId: string, profile: string | null, clearAllow: boolean) => void;\n onOverridesChange: (agentId: string, alsoAllow: string[], deny: string[]) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n}) {\n const config = resolveAgentConfig(params.configForm, params.agentId);\n const agentTools = config.entry?.tools ?? {};\n const globalTools = config.globalTools ?? {};\n const profile = agentTools.profile ?? globalTools.profile ?? \"full\";\n const profileOptions = resolveToolProfileOptions(params.toolsCatalogResult);\n const toolSections = resolveToolSections(params.toolsCatalogResult);\n const profileSource = agentTools.profile\n ? \"agent override\"\n : globalTools.profile\n ? \"global default\"\n : \"default\";\n const hasAgentAllow = Array.isArray(agentTools.allow) && agentTools.allow.length > 0;\n const hasGlobalAllow = Array.isArray(globalTools.allow) && globalTools.allow.length > 0;\n const editable =\n Boolean(params.configForm) &&\n !params.configLoading &&\n !params.configSaving &&\n !hasAgentAllow &&\n !(params.toolsCatalogLoading && !params.toolsCatalogResult && !params.toolsCatalogError);\n const alsoAllow = hasAgentAllow\n ? []\n : Array.isArray(agentTools.alsoAllow)\n ? agentTools.alsoAllow\n : [];\n const deny = hasAgentAllow ? [] : Array.isArray(agentTools.deny) ? agentTools.deny : [];\n const basePolicy = hasAgentAllow\n ? { allow: agentTools.allow ?? [], deny: agentTools.deny ?? [] }\n : (resolveToolProfile(profile) ?? undefined);\n const toolIds = toolSections.flatMap((section) => section.tools.map((tool) => tool.id));\n\n const resolveAllowed = (toolId: string) => {\n const baseAllowed = isAllowedByPolicy(toolId, basePolicy);\n const extraAllowed = matchesList(toolId, alsoAllow);\n const denied = matchesList(toolId, deny);\n const allowed = (baseAllowed || extraAllowed) && !denied;\n return {\n allowed,\n baseAllowed,\n denied,\n };\n };\n const enabledCount = toolIds.filter((toolId) => resolveAllowed(toolId).allowed).length;\n\n const updateTool = (toolId: string, nextEnabled: boolean) => {\n const nextAllow = new Set(\n alsoAllow.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const nextDeny = new Set(\n deny.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const baseAllowed = resolveAllowed(toolId).baseAllowed;\n const normalized = normalizeToolName(toolId);\n if (nextEnabled) {\n nextDeny.delete(normalized);\n if (!baseAllowed) {\n nextAllow.add(normalized);\n }\n } else {\n nextAllow.delete(normalized);\n nextDeny.add(normalized);\n }\n params.onOverridesChange(params.agentId, [...nextAllow], [...nextDeny]);\n };\n\n const updateAll = (nextEnabled: boolean) => {\n const nextAllow = new Set(\n alsoAllow.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n const nextDeny = new Set(\n deny.map((entry) => normalizeToolName(entry)).filter((entry) => entry.length > 0),\n );\n for (const toolId of toolIds) {\n const baseAllowed = resolveAllowed(toolId).baseAllowed;\n const normalized = normalizeToolName(toolId);\n if (nextEnabled) {\n nextDeny.delete(normalized);\n if (!baseAllowed) {\n nextAllow.add(normalized);\n }\n } else {\n nextAllow.delete(normalized);\n nextDeny.add(normalized);\n }\n }\n params.onOverridesChange(params.agentId, [...nextAllow], [...nextDeny]);\n };\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Tool Access</div>\n <div class=\"card-sub\">\n Profile + per-tool overrides for this agent.\n <span class=\"mono\">${enabledCount}/${toolIds.length}</span> enabled.\n </div>\n </div>\n <div class=\"row\" style=\"gap: 8px;\">\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => updateAll(true)}>\n Enable All\n </button>\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => updateAll(false)}>\n Disable All\n </button>\n <button class=\"btn btn--sm\" ?disabled=${params.configLoading} @click=${params.onConfigReload}>\n Reload Config\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.configSaving || !params.configDirty}\n @click=${params.onConfigSave}\n >\n ${params.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n\n ${\n !params.configForm\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the gateway config to adjust tool profiles.\n </div>\n `\n : nothing\n }\n ${\n hasAgentAllow\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n This agent is using an explicit allowlist in config. Tool overrides are managed in the Config tab.\n </div>\n `\n : nothing\n }\n ${\n hasGlobalAllow\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Global tools.allow is set. Agent overrides cannot enable tools that are globally blocked.\n </div>\n `\n : nothing\n }\n ${\n params.toolsCatalogLoading && !params.toolsCatalogResult && !params.toolsCatalogError\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">Loading runtime tool catalog…</div>\n `\n : nothing\n }\n ${\n params.toolsCatalogError\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Could not load runtime tool catalog. Showing built-in fallback list instead.\n </div>\n `\n : nothing\n }\n\n <div class=\"agent-tools-meta\" style=\"margin-top: 16px;\">\n <div class=\"agent-kv\">\n <div class=\"label\">Profile</div>\n <div class=\"mono\">${profile}</div>\n </div>\n <div class=\"agent-kv\">\n <div class=\"label\">Source</div>\n <div>${profileSource}</div>\n </div>\n ${\n params.configDirty\n ? html`\n <div class=\"agent-kv\">\n <div class=\"label\">Status</div>\n <div class=\"mono\">unsaved</div>\n </div>\n `\n : nothing\n }\n </div>\n\n <div class=\"agent-tools-presets\" style=\"margin-top: 16px;\">\n <div class=\"label\">Quick Presets</div>\n <div class=\"agent-tools-buttons\">\n ${profileOptions.map(\n (option) => html`\n <button\n class=\"btn btn--sm ${profile === option.id ? \"active\" : \"\"}\"\n ?disabled=${!editable}\n @click=${() => params.onProfileChange(params.agentId, option.id, true)}\n >\n ${option.label}\n </button>\n `,\n )}\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable}\n @click=${() => params.onProfileChange(params.agentId, null, false)}\n >\n Inherit\n </button>\n </div>\n </div>\n\n <div class=\"agent-tools-grid\" style=\"margin-top: 20px;\">\n ${toolSections.map(\n (section) =>\n html`\n <div class=\"agent-tools-section\">\n <div class=\"agent-tools-header\">\n ${section.label}\n ${\n section.source === \"plugin\" && section.pluginId\n ? html`<span class=\"agent-pill\" style=\"margin-left: 8px;\">plugin:${section.pluginId}</span>`\n : nothing\n }\n </div>\n <div class=\"agent-tools-list\">\n ${section.tools.map((tool) => {\n const { allowed } = resolveAllowed(tool.id);\n return html`\n <div class=\"agent-tool-row\">\n <div>\n <div class=\"agent-tool-title mono\">${tool.label}</div>\n <div class=\"agent-tool-sub\">${tool.description}</div>\n ${renderToolBadges(section, tool)}\n </div>\n <label class=\"cfg-toggle\">\n <input\n type=\"checkbox\"\n .checked=${allowed}\n ?disabled=${!editable}\n @change=${(e: Event) =>\n updateTool(tool.id, (e.target as HTMLInputElement).checked)}\n />\n <span class=\"cfg-toggle__track\"></span>\n </label>\n </div>\n `;\n })}\n </div>\n </div>\n `,\n )}\n </div>\n </section>\n `;\n}\n\nexport function renderAgentSkills(params: {\n agentId: string;\n report: SkillStatusReport | null;\n loading: boolean;\n error: string | null;\n activeAgentId: string | null;\n configForm: Record<string, unknown> | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n filter: string;\n onFilterChange: (next: string) => void;\n onRefresh: () => void;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n onClear: (agentId: string) => void;\n onDisableAll: (agentId: string) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n}) {\n const editable = Boolean(params.configForm) && !params.configLoading && !params.configSaving;\n const config = resolveAgentConfig(params.configForm, params.agentId);\n const allowlist = Array.isArray(config.entry?.skills) ? config.entry?.skills : undefined;\n const allowSet = new Set((allowlist ?? []).map((name) => name.trim()).filter(Boolean));\n const usingAllowlist = allowlist !== undefined;\n const reportReady = Boolean(params.report && params.activeAgentId === params.agentId);\n const rawSkills = reportReady ? (params.report?.skills ?? []) : [];\n const filter = params.filter.trim().toLowerCase();\n const filtered = filter\n ? rawSkills.filter((skill) =>\n [skill.name, skill.description, skill.source].join(\" \").toLowerCase().includes(filter),\n )\n : rawSkills;\n const groups = groupSkills(filtered);\n const enabledCount = usingAllowlist\n ? rawSkills.filter((skill) => allowSet.has(skill.name)).length\n : rawSkills.length;\n const totalCount = rawSkills.length;\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Skills</div>\n <div class=\"card-sub\">\n Per-agent skill allowlist and workspace skills.\n ${\n totalCount > 0\n ? html`<span class=\"mono\">${enabledCount}/${totalCount}</span>`\n : nothing\n }\n </div>\n </div>\n <div class=\"row\" style=\"gap: 8px; flex-wrap: wrap;\">\n <div class=\"row\" style=\"gap: 4px; border: 1px solid var(--border); border-radius: var(--radius-md); padding: 2px;\">\n <button class=\"btn btn--sm\" ?disabled=${!editable} @click=${() => params.onClear(params.agentId)}>\n Enable All\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable}\n @click=${() => params.onDisableAll(params.agentId)}\n >\n Disable All\n </button>\n <button\n class=\"btn btn--sm\"\n ?disabled=${!editable || !usingAllowlist}\n @click=${() => params.onClear(params.agentId)}\n title=\"Remove per-agent allowlist and use all skills\"\n >\n Reset\n </button>\n </div>\n <button class=\"btn btn--sm\" ?disabled=${params.configLoading} @click=${params.onConfigReload}>\n Reload Config\n </button>\n <button class=\"btn btn--sm\" ?disabled=${params.loading} @click=${params.onRefresh}>\n ${params.loading ? \"Loading…\" : \"Refresh\"}\n </button>\n <button\n class=\"btn btn--sm primary\"\n ?disabled=${params.configSaving || !params.configDirty}\n @click=${params.onConfigSave}\n >\n ${params.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </div>\n\n ${\n !params.configForm\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load the gateway config to set per-agent skills.\n </div>\n `\n : nothing\n }\n ${\n usingAllowlist\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">This agent uses a custom skill allowlist.</div>\n `\n : html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n All skills are enabled. Disabling any skill will create a per-agent allowlist.\n </div>\n `\n }\n ${\n !reportReady && !params.loading\n ? html`\n <div class=\"callout info\" style=\"margin-top: 12px\">\n Load skills for this agent to view workspace-specific entries.\n </div>\n `\n : nothing\n }\n ${\n params.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${params.error}</div>`\n : nothing\n }\n\n <div class=\"filters\" style=\"margin-top: 14px;\">\n <label class=\"field\" style=\"flex: 1;\">\n <span>Filter</span>\n <input\n .value=${params.filter}\n @input=${(e: Event) => params.onFilterChange((e.target as HTMLInputElement).value)}\n placeholder=\"Search skills\"\n autocomplete=\"off\"\n name=\"agent-skills-filter\"\n />\n </label>\n <div class=\"muted\">${filtered.length} shown</div>\n </div>\n\n ${\n filtered.length === 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 16px\">No skills found.</div>\n `\n : html`\n <div class=\"agent-skills-groups\" style=\"margin-top: 16px;\">\n ${groups.map((group) =>\n renderAgentSkillGroup(group, {\n agentId: params.agentId,\n allowSet,\n usingAllowlist,\n editable,\n onToggle: params.onToggle,\n }),\n )}\n </div>\n `\n }\n </section>\n `;\n}\n\nfunction renderAgentSkillGroup(\n group: SkillGroup,\n params: {\n agentId: string;\n allowSet: Set<string>;\n usingAllowlist: boolean;\n editable: boolean;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n },\n) {\n const collapsedByDefault = group.id === \"workspace\" || group.id === \"built-in\";\n return html`\n <details class=\"agent-skills-group\" ?open=${!collapsedByDefault}>\n <summary class=\"agent-skills-header\">\n <span>${group.label}</span>\n <span class=\"muted\">${group.skills.length}</span>\n </summary>\n <div class=\"list skills-grid\">\n ${group.skills.map((skill) =>\n renderAgentSkillRow(skill, {\n agentId: params.agentId,\n allowSet: params.allowSet,\n usingAllowlist: params.usingAllowlist,\n editable: params.editable,\n onToggle: params.onToggle,\n }),\n )}\n </div>\n </details>\n `;\n}\n\nfunction renderAgentSkillRow(\n skill: SkillStatusEntry,\n params: {\n agentId: string;\n allowSet: Set<string>;\n usingAllowlist: boolean;\n editable: boolean;\n onToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n },\n) {\n const enabled = params.usingAllowlist ? params.allowSet.has(skill.name) : true;\n const missing = computeSkillMissing(skill);\n const reasons = computeSkillReasons(skill);\n return html`\n <div class=\"list-item agent-skill-row\">\n <div class=\"list-main\">\n <div class=\"list-title\">${skill.emoji ? `${skill.emoji} ` : \"\"}${skill.name}</div>\n <div class=\"list-sub\">${skill.description}</div>\n ${renderSkillStatusChips({ skill })}\n ${\n missing.length > 0\n ? html`<div class=\"muted\" style=\"margin-top: 6px;\">Missing: ${missing.join(\", \")}</div>`\n : nothing\n }\n ${\n reasons.length > 0\n ? html`<div class=\"muted\" style=\"margin-top: 6px;\">Reason: ${reasons.join(\", \")}</div>`\n : nothing\n }\n </div>\n <div class=\"list-meta\">\n <label class=\"cfg-toggle\">\n <input\n type=\"checkbox\"\n .checked=${enabled}\n ?disabled=${!params.editable}\n @change=${(e: Event) =>\n params.onToggle(params.agentId, skill.name, (e.target as HTMLInputElement).checked)}\n />\n <span class=\"cfg-toggle__track\"></span>\n </label>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type {\n AgentIdentityResult,\n AgentsFilesListResult,\n AgentsListResult,\n ChannelsStatusSnapshot,\n CronJob,\n CronStatus,\n SkillStatusReport,\n ToolsCatalogResult,\n} from \"../types.ts\";\nimport { renderAgentOverview } from \"./agents-panels-overview.ts\";\nimport {\n renderAgentFiles,\n renderAgentChannels,\n renderAgentCron,\n} from \"./agents-panels-status-files.ts\";\nimport { renderAgentTools, renderAgentSkills } from \"./agents-panels-tools-skills.ts\";\nimport { agentBadgeText, buildAgentContext, normalizeAgentLabel } from \"./agents-utils.ts\";\n\nexport type AgentsPanel = \"overview\" | \"files\" | \"tools\" | \"skills\" | \"channels\" | \"cron\";\n\nexport type ConfigState = {\n form: Record<string, unknown> | null;\n loading: boolean;\n saving: boolean;\n dirty: boolean;\n};\n\nexport type ChannelsState = {\n snapshot: ChannelsStatusSnapshot | null;\n loading: boolean;\n error: string | null;\n lastSuccess: number | null;\n};\n\nexport type CronState = {\n status: CronStatus | null;\n jobs: CronJob[];\n loading: boolean;\n error: string | null;\n};\n\nexport type AgentFilesState = {\n list: AgentsFilesListResult | null;\n loading: boolean;\n error: string | null;\n active: string | null;\n contents: Record<string, string>;\n drafts: Record<string, string>;\n saving: boolean;\n};\n\nexport type AgentSkillsState = {\n report: SkillStatusReport | null;\n loading: boolean;\n error: string | null;\n agentId: string | null;\n filter: string;\n};\n\nexport type ToolsCatalogState = {\n loading: boolean;\n error: string | null;\n result: ToolsCatalogResult | null;\n};\n\nexport type AgentsProps = {\n basePath: string;\n loading: boolean;\n error: string | null;\n agentsList: AgentsListResult | null;\n selectedAgentId: string | null;\n activePanel: AgentsPanel;\n config: ConfigState;\n channels: ChannelsState;\n cron: CronState;\n agentFiles: AgentFilesState;\n agentIdentityLoading: boolean;\n agentIdentityError: string | null;\n agentIdentityById: Record<string, AgentIdentityResult>;\n agentSkills: AgentSkillsState;\n toolsCatalog: ToolsCatalogState;\n onRefresh: () => void;\n onSelectAgent: (agentId: string) => void;\n onSelectPanel: (panel: AgentsPanel) => void;\n onLoadFiles: (agentId: string) => void;\n onSelectFile: (name: string) => void;\n onFileDraftChange: (name: string, content: string) => void;\n onFileReset: (name: string) => void;\n onFileSave: (name: string) => void;\n onToolsProfileChange: (agentId: string, profile: string | null, clearAllow: boolean) => void;\n onToolsOverridesChange: (agentId: string, alsoAllow: string[], deny: string[]) => void;\n onConfigReload: () => void;\n onConfigSave: () => void;\n onModelChange: (agentId: string, modelId: string | null) => void;\n onModelFallbacksChange: (agentId: string, fallbacks: string[]) => void;\n onChannelsRefresh: () => void;\n onCronRefresh: () => void;\n onCronRunNow: (jobId: string) => void;\n onSkillsFilterChange: (next: string) => void;\n onSkillsRefresh: () => void;\n onAgentSkillToggle: (agentId: string, skillName: string, enabled: boolean) => void;\n onAgentSkillsClear: (agentId: string) => void;\n onAgentSkillsDisableAll: (agentId: string) => void;\n onSetDefault: (agentId: string) => void;\n};\n\nexport function renderAgents(props: AgentsProps) {\n const agents = props.agentsList?.agents ?? [];\n const defaultId = props.agentsList?.defaultId ?? null;\n const selectedId = props.selectedAgentId ?? defaultId ?? agents[0]?.id ?? null;\n const selectedAgent = selectedId\n ? (agents.find((agent) => agent.id === selectedId) ?? null)\n : null;\n const selectedSkillCount =\n selectedId && props.agentSkills.agentId === selectedId\n ? (props.agentSkills.report?.skills?.length ?? null)\n : null;\n\n const channelEntryCount = props.channels.snapshot\n ? Object.keys(props.channels.snapshot.channelAccounts ?? {}).length\n : null;\n const cronJobCount = selectedId\n ? props.cron.jobs.filter((j) => j.agentId === selectedId).length\n : null;\n const tabCounts: Record<string, number | null> = {\n files: props.agentFiles.list?.files?.length ?? null,\n skills: selectedSkillCount,\n channels: channelEntryCount,\n cron: cronJobCount || null,\n };\n\n return html`\n <div class=\"agents-layout\">\n <section class=\"agents-toolbar\">\n <div class=\"agents-toolbar-row\">\n <span class=\"agents-toolbar-label\">Agent</span>\n <div class=\"agents-control-row\">\n <div class=\"agents-control-select\">\n <select\n class=\"agents-select\"\n .value=${selectedId ?? \"\"}\n ?disabled=${props.loading || agents.length === 0}\n @change=${(e: Event) => props.onSelectAgent((e.target as HTMLSelectElement).value)}\n >\n ${\n agents.length === 0\n ? html`\n <option value=\"\">No agents</option>\n `\n : agents.map(\n (agent) => html`\n <option value=${agent.id} ?selected=${agent.id === selectedId}>\n ${normalizeAgentLabel(agent)}${agentBadgeText(agent.id, defaultId) ? ` (${agentBadgeText(agent.id, defaultId)})` : \"\"}\n </option>\n `,\n )\n }\n </select>\n </div>\n <div class=\"agents-control-actions\">\n ${\n selectedAgent\n ? html`\n <div class=\"agent-actions-wrap\">\n <button\n class=\"agent-actions-toggle\"\n type=\"button\"\n @click=${() => {\n actionsMenuOpen = !actionsMenuOpen;\n }}\n >⋯</button>\n ${\n actionsMenuOpen\n ? html`\n <div class=\"agent-actions-menu\">\n <button type=\"button\" @click=${() => {\n void navigator.clipboard.writeText(selectedAgent.id);\n actionsMenuOpen = false;\n }}>Copy agent ID</button>\n <button\n type=\"button\"\n ?disabled=${Boolean(defaultId && selectedAgent.id === defaultId)}\n @click=${() => {\n props.onSetDefault(selectedAgent.id);\n actionsMenuOpen = false;\n }}\n >\n ${defaultId && selectedAgent.id === defaultId ? \"Already default\" : \"Set as default\"}\n </button>\n </div>\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n <button class=\"btn btn--sm agents-refresh-btn\" ?disabled=${props.loading} @click=${props.onRefresh}>\n ${props.loading ? \"Loading…\" : \"Refresh\"}\n </button>\n </div>\n </div>\n </div>\n ${\n props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 8px;\">${props.error}</div>`\n : nothing\n }\n </section>\n <section class=\"agents-main\">\n ${\n !selectedAgent\n ? html`\n <div class=\"card\">\n <div class=\"card-title\">Select an agent</div>\n <div class=\"card-sub\">Pick an agent to inspect its workspace and tools.</div>\n </div>\n `\n : html`\n ${renderAgentTabs(props.activePanel, (panel) => props.onSelectPanel(panel), tabCounts)}\n ${\n props.activePanel === \"overview\"\n ? renderAgentOverview({\n agent: selectedAgent,\n basePath: props.basePath,\n defaultId,\n configForm: props.config.form,\n agentFilesList: props.agentFiles.list,\n agentIdentity: props.agentIdentityById[selectedAgent.id] ?? null,\n agentIdentityError: props.agentIdentityError,\n agentIdentityLoading: props.agentIdentityLoading,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n onModelChange: props.onModelChange,\n onModelFallbacksChange: props.onModelFallbacksChange,\n onSelectPanel: props.onSelectPanel,\n })\n : nothing\n }\n ${\n props.activePanel === \"files\"\n ? renderAgentFiles({\n agentId: selectedAgent.id,\n agentFilesList: props.agentFiles.list,\n agentFilesLoading: props.agentFiles.loading,\n agentFilesError: props.agentFiles.error,\n agentFileActive: props.agentFiles.active,\n agentFileContents: props.agentFiles.contents,\n agentFileDrafts: props.agentFiles.drafts,\n agentFileSaving: props.agentFiles.saving,\n onLoadFiles: props.onLoadFiles,\n onSelectFile: props.onSelectFile,\n onFileDraftChange: props.onFileDraftChange,\n onFileReset: props.onFileReset,\n onFileSave: props.onFileSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"tools\"\n ? renderAgentTools({\n agentId: selectedAgent.id,\n configForm: props.config.form,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n toolsCatalogLoading: props.toolsCatalog.loading,\n toolsCatalogError: props.toolsCatalog.error,\n toolsCatalogResult: props.toolsCatalog.result,\n onProfileChange: props.onToolsProfileChange,\n onOverridesChange: props.onToolsOverridesChange,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"skills\"\n ? renderAgentSkills({\n agentId: selectedAgent.id,\n report: props.agentSkills.report,\n loading: props.agentSkills.loading,\n error: props.agentSkills.error,\n activeAgentId: props.agentSkills.agentId,\n configForm: props.config.form,\n configLoading: props.config.loading,\n configSaving: props.config.saving,\n configDirty: props.config.dirty,\n filter: props.agentSkills.filter,\n onFilterChange: props.onSkillsFilterChange,\n onRefresh: props.onSkillsRefresh,\n onToggle: props.onAgentSkillToggle,\n onClear: props.onAgentSkillsClear,\n onDisableAll: props.onAgentSkillsDisableAll,\n onConfigReload: props.onConfigReload,\n onConfigSave: props.onConfigSave,\n })\n : nothing\n }\n ${\n props.activePanel === \"channels\"\n ? renderAgentChannels({\n context: buildAgentContext(\n selectedAgent,\n props.config.form,\n props.agentFiles.list,\n defaultId,\n props.agentIdentityById[selectedAgent.id] ?? null,\n ),\n configForm: props.config.form,\n snapshot: props.channels.snapshot,\n loading: props.channels.loading,\n error: props.channels.error,\n lastSuccess: props.channels.lastSuccess,\n onRefresh: props.onChannelsRefresh,\n })\n : nothing\n }\n ${\n props.activePanel === \"cron\"\n ? renderAgentCron({\n context: buildAgentContext(\n selectedAgent,\n props.config.form,\n props.agentFiles.list,\n defaultId,\n props.agentIdentityById[selectedAgent.id] ?? null,\n ),\n agentId: selectedAgent.id,\n jobs: props.cron.jobs,\n status: props.cron.status,\n loading: props.cron.loading,\n error: props.cron.error,\n onRefresh: props.onCronRefresh,\n onRunNow: props.onCronRunNow,\n })\n : nothing\n }\n `\n }\n </section>\n </div>\n `;\n}\n\nlet actionsMenuOpen = false;\n\nfunction renderAgentTabs(\n active: AgentsPanel,\n onSelect: (panel: AgentsPanel) => void,\n counts: Record<string, number | null>,\n) {\n const tabs: Array<{ id: AgentsPanel; label: string }> = [\n { id: \"overview\", label: \"Overview\" },\n { id: \"files\", label: \"Files\" },\n { id: \"tools\", label: \"Tools\" },\n { id: \"skills\", label: \"Skills\" },\n { id: \"channels\", label: \"Channels\" },\n { id: \"cron\", label: \"Cron Jobs\" },\n ];\n return html`\n <div class=\"agent-tabs\">\n ${tabs.map(\n (tab) => html`\n <button\n class=\"agent-tab ${active === tab.id ? \"active\" : \"\"}\"\n type=\"button\"\n @click=${() => onSelect(tab.id)}\n >\n ${tab.label}${counts[tab.id] != null ? html`<span class=\"agent-tab-count\">${counts[tab.id]}</span>` : nothing}\n </button>\n `,\n )}\n </div>\n `;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{i as e,n as t}from"./lit-BZwq2xLD.js";import{d as n,l as r}from"./format-DeRVtGzv.js";import{M as i,c as a,j as o,l as s}from"./index-5bbJdGkA.js";import{n as c,t as l}from"./channel-config-extras-UBRJa-vU.js";function u(e,t){let n=e;for(let e of t){if(!n)return null;let t=i(n);if(t===`object`){let t=n.properties??{};if(typeof e==`string`&&t[e]){n=t[e];continue}let r=n.additionalProperties;if(typeof e==`string`&&r&&typeof r==`object`){n=r;continue}return null}if(t===`array`){if(typeof e!=`number`)return null;n=(Array.isArray(n.items)?n.items[0]:n.items)??null;continue}return null}return n}function d(e,t){return c(e,t)??{}}var f=[`groupPolicy`,`streamMode`,`dmPolicy`];function p(t){let n=f.flatMap(e=>e in t?[[e,t[e]]]:[]);return n.length===0?null:e`
1
+ import{i as e,n as t}from"./lit-BZwq2xLD.js";import{d as n,l as r}from"./format-DeRVtGzv.js";import{M as i,c as a,j as o,l as s}from"./index-UVvtebBp.js";import{n as c,t as l}from"./channel-config-extras-UBRJa-vU.js";function u(e,t){let n=e;for(let e of t){if(!n)return null;let t=i(n);if(t===`object`){let t=n.properties??{};if(typeof e==`string`&&t[e]){n=t[e];continue}let r=n.additionalProperties;if(typeof e==`string`&&r&&typeof r==`object`){n=r;continue}return null}if(t===`array`){if(typeof e!=`number`)return null;n=(Array.isArray(n.items)?n.items[0]:n.items)??null;continue}return null}return n}function d(e,t){return c(e,t)??{}}var f=[`groupPolicy`,`streamMode`,`dmPolicy`];function p(t){let n=f.flatMap(e=>e in t?[[e,t[e]]]:[]);return n.length===0?null:e`
2
2
  <div class="status-list" style="margin-top: 12px;">
3
3
  ${n.map(([t,n])=>e`
4
4
  <div>
@@ -625,4 +625,4 @@ ${n.snapshot?JSON.stringify(n.snapshot,null,2):`No snapshot yet.`}
625
625
  </div>
626
626
  </div>
627
627
  `}export{O as renderChannels};
628
- //# sourceMappingURL=channels-CH1TfFn-.js.map
628
+ //# sourceMappingURL=channels-CtcAfpMH.js.map