diff --git a/plans/2026-07-17-codebase-review-and-cleanup.md b/plans/2026-07-17-codebase-review-and-cleanup.md index 8cc70c9..414a750 100644 --- a/plans/2026-07-17-codebase-review-and-cleanup.md +++ b/plans/2026-07-17-codebase-review-and-cleanup.md @@ -397,8 +397,8 @@ behavior; tracked as R6. | ID | Action | Effort | Risk | | -- | ------ | ------ | ---- | -| R1 | Delete dead Go: `notifier.VerifyApprovalToken`, `httpapi/stubs.go`; unexport 4 `checkdefaults` symbols | S | Low | -| R2 | Delete dead web: 21-file tool-renderer registry, 5 dead components, 2 dead store exports, 2 dead npm deps | S | Low | +| R1 | Delete dead Go: `notifier.VerifyApprovalToken`, `httpapi/stubs.go`; unexport 4 `checkdefaults` symbols | S | Low | ✅ done (c3973e7) | +| R2 | Delete dead web: 21-file tool-renderer registry, 5 dead components, 2 dead store exports, 2 dead npm deps | S | Low | ✅ done (c3973e7+1) | | R3 | Decide sqlc vs raw SQL: delete 17 dead queries OR migrate inline SQL to use them | M | Medium | | R4 | Split `phase3.go` (2627 lines) into per-resource files; refactor `newServer` (708 lines) to a tool registry | M | Medium | | R5 | Rewrite `.agents/domains/knowledge/schema.md` + `.agents/shared/llm-wiki.md` for the DB-native model; delete/deprecate root `inventory.yaml` | M | Low | diff --git a/web/package.json b/web/package.json index df77b14..e7b9023 100644 --- a/web/package.json +++ b/web/package.json @@ -12,14 +12,12 @@ "lint": "svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { - "@internationalized/date": "^3.12.2", "@lucide/svelte": "^1.23.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", "@tailwindcss/vite": "^4.3.2", "@tsconfig/svelte": "^5.0.0", "@types/d3-force": "^3.0.10", "bits-ui": "^2.18.1", - "mode-watcher": "^1.1.0", "svelte": "^5.0.0", "svelte-check": "^4.0.0", "svelte-sonner": "^1.1.1", diff --git a/web/src/lib/api.ts b/web/src/lib/api.ts index 1178004..2845888 100644 --- a/web/src/lib/api.ts +++ b/web/src/lib/api.ts @@ -351,21 +351,6 @@ export async function fetchRecentActivity(limit = 50): Promise { return data.items ?? [] } -export interface SessionDigest { - session_id: string - total_executions: number - by_status: Record - entities_touched: string[] - executions: { target: string; verb: string; summary: string; risk_class: string; status: string }[] - knowledge_created: string[] -} - -export async function fetchSessionDigest(sessionId: string): Promise { - const res = await fetchWithAuth(`${API}/activity/session/${sessionId}`) - if (!res.ok) return null - return res.json() -} - export interface CapabilityTimelineItem { verb: string first_success: string | null diff --git a/web/src/lib/components/GoalHeader.svelte b/web/src/lib/components/GoalHeader.svelte deleted file mode 100644 index eed55cf..0000000 --- a/web/src/lib/components/GoalHeader.svelte +++ /dev/null @@ -1,38 +0,0 @@ - - -{#if $currentTask} - {@const st = statusStyle($currentTask.status, $currentTask.outcome)} -
-
- - {st.label} -
-

- {$currentTask.goal || $currentTask.title || 'Untitled task'} -

-
-{/if} diff --git a/web/src/lib/components/InlineApproval.svelte b/web/src/lib/components/InlineApproval.svelte deleted file mode 100644 index d81d003..0000000 --- a/web/src/lib/components/InlineApproval.svelte +++ /dev/null @@ -1,261 +0,0 @@ - - -{#each approvals as approval (approval.executionId)} - {@const p = phase.get(approval.executionId)} - {@const e = exec.get(approval.executionId)} - {#if p === 'completed'} -
-
- - Completed{e?.duration_ms ? ` in ${Math.round(e.duration_ms / 1000)}s` : ''} on {approval.target}. -
- {#if outputText(e)} -
{outputText(e)}
- {/if} -
- {:else if p === 'failed'} -
-
- - Execution failed - -
-
{errorText(e)}
-
- {:else if p === 'denied'} -
- Denied. -
- {:else if p === 'running' || p === 'deciding'} - {@const secs = elapsedSeconds(e)} -
-
- - - {#if p === 'deciding'} - Submitting approval… - {:else} - Running on {approval.target}{secs !== null ? ` — ${fmtDuration(secs)} elapsed` : '…'} - {/if} - -
- {#if p === 'running' && approval.command} - {approval.command} - {/if} - {#if p === 'running'} - - Execution {approval.executionId.slice(0, 8)} — long installs can take several minutes; this - will resolve on its own (capped at 10 min) or you can check the Operations page for live output. - - {/if} -
- {:else if p === 'stalled'} -
-
- - No update from the server in over 14 minutes. - -
- - The command itself is capped at 10 minutes server-side, so this is unusual — the API may be unreachable. - Execution {approval.executionId}. Check the Operations page directly. - -
- {:else if approval.destructive} - {@const affected = blastRadius.get(approval.executionId)} -
-
- - - DESTRUCTIVE — {approval.action} on {approval.target}. Type - "I confirm" in chat, or use the button. - - - -
- {#if approval.command} - {approval.command} - {/if} - {#if affected} -
- - Affects {affected.length} downstream: {affected.join(', ')} -
- {/if} -
- {:else} - {@const affected = blastRadius.get(approval.executionId)} -
-
- - {approval.action} on {approval.target} requires approval - - -
- {#if affected} -
- - Affects {affected.length} downstream: {affected.join(', ')} -
- {/if} -
- {/if} -{/each} diff --git a/web/src/lib/components/PlanProgress.svelte b/web/src/lib/components/PlanProgress.svelte deleted file mode 100644 index b9ee6bf..0000000 --- a/web/src/lib/components/PlanProgress.svelte +++ /dev/null @@ -1,116 +0,0 @@ - - -{#if total > 0} -
-
- Plan - {done}/{total} -
-
-
-
- - {#each byGeneration as [gen, steps] (gen)} - {@const isLatest = gen === latestGen} - {#if byGeneration.length > 1} - - {/if} - {#if isLatest || openGens.has(gen)} -
    - {#each steps as step (step.id)} -
  1. - -
  2. - {/each} -
- {/if} - {/each} -
-{/if} - - diff --git a/web/src/lib/components/SessionDigest.svelte b/web/src/lib/components/SessionDigest.svelte deleted file mode 100644 index 9ff2cbb..0000000 --- a/web/src/lib/components/SessionDigest.svelte +++ /dev/null @@ -1,215 +0,0 @@ - - -{#if $streaming && $currentSession} -
- - {toolCount} tool{toolCount === 1 ? '' : 's'} · {runningCount} running -
-{/if} - -{#if $currentTask?.outcome} -
- {#if $currentTask.outcome === 'failure'} - - {:else} - - {/if} - {$currentTask.summary || `Task ${$currentTask.outcome}.`} -
-{/if} - -{#if $planSteps.length > 0} -
-
- Plan - {planDone}/{planTotal} -
-
-
-
-
    - {#each $planSteps as step (step.id)} -
  1. - - {#if step.status === 'done'} - - {:else if step.status === 'running'} - - {:else if step.status === 'failed'} - - {:else} - - {/if} - - {step.title} -
  2. - {/each} -
-
-{/if} - -{#if toolCount > 0} -
- - {#if openTools} -
- {#each toolGroups as group} - {@const isLatest = group.msgIndex === toolGroups[toolGroups.length - 1]?.msgIndex} -
- {#each group.entries as t (t.id)} -
- - {#if t.type === 'tool_result' && t.error} - - {:else if t.type === 'tool_result'} - - {:else} - - {/if} - - {toolSummary(t)} -
- {/each} -
- {/each} -
- {/if} -
-{/if} - -{#if digest && digest.total_executions > 0} -
- - - {#if open} -
-
- {#each Object.entries(digest.by_status) as [status, count]} - {status} × {count} - {/each} -
- - {#if digest.knowledge_created.length} -
-
- Learned this session -
-
    - {#each digest.knowledge_created as title} -
  • {title}
  • - {/each} -
-
- {/if} -
- {/if} -
-{/if} diff --git a/web/src/lib/components/ToolCallGroup.svelte b/web/src/lib/components/ToolCallGroup.svelte deleted file mode 100644 index afcab06..0000000 --- a/web/src/lib/components/ToolCallGroup.svelte +++ /dev/null @@ -1,90 +0,0 @@ - - -{#if bodyTools.length} - - - - {#if active && doneCount < total} - - {:else if hasError} - - - - {#if active && doneCount < total} - {doneCount}/{total} - {:else} - {total} tool{total === 1 ? '' : 's'} - {/if} - {#if inlineCount > 0} - · {inlineCount} inline - {/if} - - - {#if active && runningTool} - {toolLabel(runningTool)} - {/if} - - - - -
- {#each bodyTools as tool (tool.id)} -
- {#if tool.type === 'tool_result' && tool.error} - - {:else if tool.type === 'tool_result'} - - {:else} - - {/if} - {toolLabel(tool)} -
- {/each} -
-
-
-{/if} diff --git a/web/src/lib/renderers/BlastRadius.svelte b/web/src/lib/renderers/BlastRadius.svelte deleted file mode 100644 index 52dc5cc..0000000 --- a/web/src/lib/renderers/BlastRadius.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if grouped && total > 0} -
-
-
-
- {#each Object.entries(grouped).sort(([a], [b]) => Number(a) - Number(b)) as [depth, slugs]} -
-
- {Number(depth) === 1 ? 'Directly affected' : `${depth} hops`} ({slugs.length}) -
-
- {#each slugs as slug} - {slug} - {/each} -
-
- {/each} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/ChangeLog.svelte b/web/src/lib/renderers/ChangeLog.svelte deleted file mode 100644 index c25210b..0000000 --- a/web/src/lib/renderers/ChangeLog.svelte +++ /dev/null @@ -1,92 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if activityRows && activityRows.length > 0} -
-
-
-
- {#each activityRows as row} -
- {row.time} - {#if row.date !== activityRows[0].date} - {row.date} - {/if} - {row.action} - {row.toolName} - {row.actor} - {#if row.status === 'true'} - - {:else if row.status === 'false'} - - {/if} -
- {/each} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/EntityCard.svelte b/web/src/lib/renderers/EntityCard.svelte deleted file mode 100644 index 38f6bbd..0000000 --- a/web/src/lib/renderers/EntityCard.svelte +++ /dev/null @@ -1,118 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if entity} -
- - -
-
-
- {#if entity.type} - {entity.type} - {/if} - {#if entity.state} - {entity.state} - {/if} - {#if entity.health && entity.health !== 'unknown'} - - - {entity.health} - - {/if} - {#if entity.last_check} - · {relativeTime(entity.last_check)} - {/if} -
- {#if keyAttrs.length > 0} -
- {#each keyAttrs as [k, v]} - {k}: {v} - {/each} -
- {/if} -
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/EntityTable.svelte b/web/src/lib/renderers/EntityTable.svelte deleted file mode 100644 index af92d0a..0000000 --- a/web/src/lib/renderers/EntityTable.svelte +++ /dev/null @@ -1,60 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if rows && rows.length > 0} -
-
- - - - {#each cols as col} - - {/each} - - - - {#each rows as row} - - {#each cols as col} - - {/each} - - {/each} - -
{col}
{row[col] ?? '—'}
-
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/ExecutionStatus.svelte b/web/src/lib/renderers/ExecutionStatus.svelte deleted file mode 100644 index c1801fc..0000000 --- a/web/src/lib/renderers/ExecutionStatus.svelte +++ /dev/null @@ -1,108 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if executions && executions.length > 0} -
-
- {#each executions as exec (exec.execution_id ?? exec.id)} - {@const status = exec.status ?? 'unknown'} - {@const color = statusColors[status] ?? 'var(--muted-foreground)'} - {@const isRunning = status === 'running' || status === 'approved'} -
- {#if status === 'completed'} -
- {#if exec.result || exec.error} -
- {#if exec.error} -
{exec.error}
- {:else if exec.result} -
{typeof exec.result === 'string' ? exec.result : JSON.stringify(exec.result, null, 2)}
- {/if} -
- {/if} - {/each} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/FleetSnapshot.svelte b/web/src/lib/renderers/FleetSnapshot.svelte deleted file mode 100644 index d884468..0000000 --- a/web/src/lib/renderers/FleetSnapshot.svelte +++ /dev/null @@ -1,93 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if summary && summary.total > 0} -
-
-
-
- -
-
Health
-
- {#each ['healthy', 'degraded', 'down', 'unknown'] as h} - {#if summary.health[h]} -
- - {h} - {summary.health[h]} -
- {/if} - {/each} -
-
- - {#if Object.keys(summary.types).length > 0} -
-
By type
-
- {#each Object.entries(summary.types).sort(([,a], [,b]) => b - a) as [type, count]} -
- {type} - {count} -
- {/each} -
-
- {/if} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/HealthSummary.svelte b/web/src/lib/renderers/HealthSummary.svelte deleted file mode 100644 index 22b995f..0000000 --- a/web/src/lib/renderers/HealthSummary.svelte +++ /dev/null @@ -1,82 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if counts && total > 0} -
-
-
-
- {#each bars as bar} - {#if bar.count > 0} -
- {bar.count} -
- {/if} - {/each} -
-
- {#each bars as bar} - {#if bar.count > 0} - - - {bar.label} {bar.count} - - {/if} - {/each} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/KnowledgeResults.svelte b/web/src/lib/renderers/KnowledgeResults.svelte deleted file mode 100644 index a8c424c..0000000 --- a/web/src/lib/renderers/KnowledgeResults.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if rows && rows.length > 0} -
-
-
-
- {#each rows as row} -
-
- -
-
{row.title}
- {#if row.snippet || row.headline} -
- {row.snippet || row.headline} -
- {/if} -
- {#if row.source} - {row.source} - {/if} - {#if row.slug} - {row.slug} - {/if} -
-
-
-
- {/each} -
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/LXCList.svelte b/web/src/lib/renderers/LXCList.svelte deleted file mode 100644 index 0c7fe6f..0000000 --- a/web/src/lib/renderers/LXCList.svelte +++ /dev/null @@ -1,85 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if rows && rows.length > 0} -
-
-
-
- - - - - - - - - - - {#each rows as row} - - - - - - - {/each} - -
NameIDIPHealth
{shortName(row.slug)}{row.pve_id ?? '—'}{row.lan_ip ?? '—'} - {#if row.health} - - - {row.health} - - {:else} - - {/if} -
-
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/MetricChart.svelte b/web/src/lib/renderers/MetricChart.svelte deleted file mode 100644 index d673e7f..0000000 --- a/web/src/lib/renderers/MetricChart.svelte +++ /dev/null @@ -1,68 +0,0 @@ - - -{#if loading} -
-
-{:else if error} - -{:else if rows && rows.length > 0} -
-
-
-
- - - - - - - - - - - - {#each rows as row} - - - - - - - - {/each} - -
TimeMetricAvgMinMax
{row.bucket?.slice(11, 16) ?? row.bucket?.slice(0, 19) ?? '—'}{row.metric ?? '—'}{row.avg ?? '—'}{row.min ?? '—'}{row.max ?? '—'}
-
-
-{:else} -
-
-{/if} diff --git a/web/src/lib/renderers/blast-radius.ts b/web/src/lib/renderers/blast-radius.ts deleted file mode 100644 index ca434f9..0000000 --- a/web/src/lib/renderers/blast-radius.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import BlastRadius from './BlastRadius.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'get_blast_radius' || t.result?.__renderer === 'blast_radius', - component: BlastRadius, - }) -} diff --git a/web/src/lib/renderers/change-log.ts b/web/src/lib/renderers/change-log.ts deleted file mode 100644 index ace0ae4..0000000 --- a/web/src/lib/renderers/change-log.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import ChangeLog from './ChangeLog.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => - t.name === 'get_change_history' || - t.name === 'get_agent_activity' || - t.result?.__renderer === 'change_log', - component: ChangeLog, - }) -} diff --git a/web/src/lib/renderers/entity-card.ts b/web/src/lib/renderers/entity-card.ts deleted file mode 100644 index 333597a..0000000 --- a/web/src/lib/renderers/entity-card.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import EntityCard from './EntityCard.svelte' - -const TOOLS = ['get_entity', 'whoami', 'explain'] - -export function init() { - registerToolRenderer({ - match: (t) => TOOLS.includes(t.name) || t.result?.__renderer === 'entity_card', - component: EntityCard, - }) -} diff --git a/web/src/lib/renderers/entity-table.ts b/web/src/lib/renderers/entity-table.ts deleted file mode 100644 index 26a8dad..0000000 --- a/web/src/lib/renderers/entity-table.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import EntityTable from './EntityTable.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'list_entities' || t.result?.__renderer === 'entity_table', - component: EntityTable, - }) -} diff --git a/web/src/lib/renderers/execution-status.ts b/web/src/lib/renderers/execution-status.ts deleted file mode 100644 index a5716e4..0000000 --- a/web/src/lib/renderers/execution-status.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import ExecutionStatus from './ExecutionStatus.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'get_execution_status', - component: ExecutionStatus, - }) -} diff --git a/web/src/lib/renderers/fleet-snapshot.ts b/web/src/lib/renderers/fleet-snapshot.ts deleted file mode 100644 index 725a74e..0000000 --- a/web/src/lib/renderers/fleet-snapshot.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import FleetSnapshot from './FleetSnapshot.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'get_state_snapshot' || t.result?.__renderer === 'fleet_snapshot', - component: FleetSnapshot, - }) -} diff --git a/web/src/lib/renderers/health-summary.ts b/web/src/lib/renderers/health-summary.ts deleted file mode 100644 index a5cf71f..0000000 --- a/web/src/lib/renderers/health-summary.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import HealthSummary from './HealthSummary.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'get_health_summary' || t.result?.__renderer === 'health_summary', - component: HealthSummary, - }) -} diff --git a/web/src/lib/renderers/index.ts b/web/src/lib/renderers/index.ts deleted file mode 100644 index 248c953..0000000 --- a/web/src/lib/renderers/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { init as initEntityCard } from './entity-card' -import { init as initHealthSummary } from './health-summary' -import { init as initLXCList } from './lxc-list' -import { init as initEntityTable } from './entity-table' -import { init as initKnowledgeResults } from './knowledge-results' -import { init as initBlastRadius } from './blast-radius' -import { init as initChangeLog } from './change-log' -import { init as initFleetSnapshot } from './fleet-snapshot' -import { init as initMetricChart } from './metric-chart' -import { init as initExecutionStatus } from './execution-status' - -initEntityCard() -initHealthSummary() -initLXCList() -initEntityTable() -initKnowledgeResults() -initBlastRadius() -initChangeLog() -initFleetSnapshot() -initMetricChart() -initExecutionStatus() diff --git a/web/src/lib/renderers/knowledge-results.ts b/web/src/lib/renderers/knowledge-results.ts deleted file mode 100644 index 852c56a..0000000 --- a/web/src/lib/renderers/knowledge-results.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import KnowledgeResults from './KnowledgeResults.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => - t.name === 'search_knowledge' || - t.name === 'get_entity_knowledge' || - t.result?.__renderer === 'knowledge_results', - component: KnowledgeResults, - }) -} diff --git a/web/src/lib/renderers/lxc-list.ts b/web/src/lib/renderers/lxc-list.ts deleted file mode 100644 index 1aeea6b..0000000 --- a/web/src/lib/renderers/lxc-list.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import LXCList from './LXCList.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'list_lxcs' || t.result?.__renderer === 'lxc_list', - component: LXCList, - }) -} diff --git a/web/src/lib/renderers/metric-chart.ts b/web/src/lib/renderers/metric-chart.ts deleted file mode 100644 index 0df054a..0000000 --- a/web/src/lib/renderers/metric-chart.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { registerToolRenderer } from '$lib/tool-renderers' -import MetricChart from './MetricChart.svelte' - -export function init() { - registerToolRenderer({ - match: (t) => t.name === 'query_metrics' || t.result?.__renderer === 'metric_chart', - component: MetricChart, - }) -} diff --git a/web/src/lib/stores/activity.ts b/web/src/lib/stores/activity.ts index 2bdd74e..66f5cfd 100644 --- a/web/src/lib/stores/activity.ts +++ b/web/src/lib/stores/activity.ts @@ -161,7 +161,7 @@ export const activityLog = derived([messages, planSteps, currentTask], ([$msgs, // which caused the AgentIndicator to latch onto a stale "Approval: ..." // entry and never clear — even after the session completed. Approvals // are tracked via the REST /approvals endpoint (context.ts, Ops.svelte) - // and rendered as InlineApproval cards in the chat (or Ops page), not + // and rendered as inline approval cards in the chat (or Ops page), not // in the activity log. // Sort oldest first diff --git a/web/src/lib/stores/context.ts b/web/src/lib/stores/context.ts index 89dc28b..8421ca3 100644 --- a/web/src/lib/stores/context.ts +++ b/web/src/lib/stores/context.ts @@ -1,5 +1,5 @@ import { writable, get } from 'svelte/store' -import { fetchDashboardSummary, fetchApprovals, type DashboardSummary, type Approval } from '$lib/api' +import { fetchDashboardSummary, fetchApprovals, type DashboardSummary } from '$lib/api' import { liveEvents, subscribeEvents, type OikosEvent } from './events' // Shared operational context: dashboard summary + pending approvals, @@ -7,7 +7,6 @@ import { liveEvents, subscribeEvents, type OikosEvent } from './events' // so the poll only runs while something on screen displays it. export const summary = writable(null) -export const pendingApprovals = writable([]) let refs = 0 let pollTimer: ReturnType | null = null @@ -16,9 +15,8 @@ let unsubscribeStore: (() => void) | null = null let lastSeenEventId = 0 export async function refreshContext() { - const [s, approvals] = await Promise.all([fetchDashboardSummary(), fetchApprovals('pending')]) + const [s] = await Promise.all([fetchDashboardSummary(), fetchApprovals('pending')]) if (s) summary.set(s) - pendingApprovals.set(approvals) } function onEvent(ev: OikosEvent) { diff --git a/web/src/lib/stores/events.ts b/web/src/lib/stores/events.ts index 482b2e0..b030650 100644 --- a/web/src/lib/stores/events.ts +++ b/web/src/lib/stores/events.ts @@ -15,20 +15,16 @@ export interface OikosEvent { const MAX_BUFFERED = 200 export const liveEvents = writable([]) -export const connectionState = writable<'connecting' | 'open' | 'closed'>('connecting') let source: EventSource | null = null let subscriberCount = 0 async function connect() { if (source) return - connectionState.set('connecting') // The browser's EventSource sends Last-event-ID automatically on reconnect. // sseUrl is async so the OIDC access token is refreshed if expired. source = new EventSource(await sseUrl('/api/v1/events/stream')) - source.onopen = () => connectionState.set('open') - source.onmessage = (ev) => { try { const parsed: OikosEvent = JSON.parse(ev.data) @@ -39,7 +35,7 @@ async function connect() { } source.onerror = () => { - connectionState.set('closed') + // browser will auto-reconnect; nothing to surface here } } diff --git a/web/src/lib/stores/workspace.ts b/web/src/lib/stores/workspace.ts index 3157c12..fbfd636 100644 --- a/web/src/lib/stores/workspace.ts +++ b/web/src/lib/stores/workspace.ts @@ -83,7 +83,7 @@ function applyEvent(ev: { type: string; correlation_id?: string | null; data?: u const data = (ev.data ?? {}) as any // Task fields (status/goal/outcome) live on the session row — refetch the - // (cheap) session list so GoalHeader picks up the change without a + // (cheap) session list so the UI picks up the change without a // dedicated endpoint. Every event that can change agent_sessions.status // (goal.set → planning, propose_plan → executing, ask_operator → // awaiting_input, answerQuestion → executing, complete_task → done/failed) @@ -138,8 +138,7 @@ function applyEvent(ev: { type: string; correlation_id?: string | null; data?: u } break case 'knowledge.recorded': - // No dedicated store yet — the outcome/knowledge card reads this task's - // digest (fetchSessionDigest) on completion, which already lists it. + // No dedicated store — knowledge cards refetch on completion signal. break } } diff --git a/web/src/lib/tool-renderers.ts b/web/src/lib/tool-renderers.ts deleted file mode 100644 index 19f1fc3..0000000 --- a/web/src/lib/tool-renderers.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Component } from 'svelte' -import type { ToolCallResult } from '$lib/stores/chat' - -export interface ToolRenderer { - match: (tool: ToolCallResult) => boolean - component: Component<{ tool: ToolCallResult }> -} - -const registry: ToolRenderer[] = [] - -export function registerToolRenderer(r: ToolRenderer) { - registry.push(r) -} - -export function getToolRenderer(tool: ToolCallResult): ToolRenderer | undefined { - return registry.find((r) => r.match(tool)) -} diff --git a/web/src/main.ts b/web/src/main.ts index 312046a..8f42272 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -22,8 +22,6 @@ function start() { initConfig() handleDesktopToken() - requestAnimationFrame(() => import('./lib/renderers')) - mount(App, { target: document.getElementById('app')! }) }