Extract + Drizzle agents aggregate (preserve onAgentDelete hook) #844

Closed
opened 2026-05-04 20:29:04 +00:00 by claude-desktop · 1 comment
Collaborator

As a maintainer, I want the core agents + agent_provider_state + agent_provider_events tables split out and Drizzled, so that the most-imported DB surface gets type-safe column refs without breaking the registerOnAgentDelete lifecycle hook.

Acceptance criteria

Extraction

  • agents-store.ts + agent-provider.ts (split by table cluster).
  • All ~20 fns moved: listAgents, getAgent, listAgentsByType, createAgent, updateAgent, deleteAgent, getProviderState, listProviderStates, bumpTier, resetTier, setProviderPaused, listProviderEvents, parseMatchLabels, parsePlugins, seedDefaultAgents, ensureDefaultForTypes, migrateForLegacyTypeRenames, migrateSecretsForLegacyTypeRenames, migrateTokenFilesForLegacyTypeRenames, dropOrphanAgentDefault, applyDefaultMatchLabels, applyGlobalCavemanModeFlip, clearModelOverrideForType.
  • All callers updated.

Hooks preserved

  • registerOnAgentDelete(fn) API unchanged.
  • Drizzle-based deleteAgent still fires registered callbacks before/after delete (verify with existing tests).

Drizzle

  • schema/agents.ts + schema/agent-provider.ts.
  • match_labels, plugins, notes JSON-encoded TEXT columns — text({ mode: "json" }).$type<...>() with explicit NULL handling for tri-state plugins (NULL = inherit, [] = empty override, array = explicit list). Document in schema file.
  • Field-level inheritance resolver (row override (non-null) → type default) preserved.

Tests

  • Relevant db.test.ts slices extracted, green.
  • onAgentDelete callback fires once per delete (not zero, not twice).

Out of scope

  • Resolver layer (domain/agent-config/resolver.ts) — separate story (#845).

References

  • apps/server/src/infrastructure/database/db.ts:600-1500.
  • db.ts:862registerOnAgentDelete.
  • Foundation story (#839) must merge first.
**As a** maintainer, **I want** the core `agents` + `agent_provider_state` + `agent_provider_events` tables split out and Drizzled, **so that** the most-imported DB surface gets type-safe column refs without breaking the `registerOnAgentDelete` lifecycle hook. ## Acceptance criteria ### Extraction - [ ] `agents-store.ts` + `agent-provider.ts` (split by table cluster). - [ ] All ~20 fns moved: `listAgents`, `getAgent`, `listAgentsByType`, `createAgent`, `updateAgent`, `deleteAgent`, `getProviderState`, `listProviderStates`, `bumpTier`, `resetTier`, `setProviderPaused`, `listProviderEvents`, `parseMatchLabels`, `parsePlugins`, `seedDefaultAgents`, `ensureDefaultForTypes`, `migrateForLegacyTypeRenames`, `migrateSecretsForLegacyTypeRenames`, `migrateTokenFilesForLegacyTypeRenames`, `dropOrphanAgentDefault`, `applyDefaultMatchLabels`, `applyGlobalCavemanModeFlip`, `clearModelOverrideForType`. - [ ] All callers updated. ### Hooks preserved - [ ] `registerOnAgentDelete(fn)` API unchanged. - [ ] Drizzle-based `deleteAgent` still fires registered callbacks before/after delete (verify with existing tests). ### Drizzle - [ ] `schema/agents.ts` + `schema/agent-provider.ts`. - [ ] `match_labels`, `plugins`, `notes` JSON-encoded TEXT columns — `text({ mode: "json" }).$type<...>()` with explicit NULL handling for tri-state `plugins` (NULL = inherit, `[]` = empty override, array = explicit list). Document in schema file. - [ ] Field-level inheritance resolver (`row override (non-null) → type default`) preserved. ### Tests - [ ] Relevant `db.test.ts` slices extracted, green. - [ ] `onAgentDelete` callback fires once per delete (not zero, not twice). ## Out of scope - Resolver layer (`domain/agent-config/resolver.ts`) — separate story (#845). ## References - `apps/server/src/infrastructure/database/db.ts:600-1500`. - `db.ts:862` — `registerOnAgentDelete`. - Foundation story (#839) must merge first.
Collaborator

🤖 Auto-assigned to code-lead (heuristic: default → code-lead (no specific label match; safer than code)). Reply /unassign to reroute.

🤖 Auto-assigned to **code-lead** (heuristic: default → code-lead (no specific label match; safer than code)). Reply `/unassign` to reroute.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
charles/claude-hooks#844
No description provided.