feat(sdk): WS3b — remaining SDK client primitives (useJsonFetch, ConfirmDialog, useAvailableModels, formatters, EmptyState, toneBadge)#502
Open
markhayden wants to merge 10 commits into
Open
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…reimplementations Adds formatDuration(ms) and formatDateTime(ts) to packages/core/src/format.ts (re-exported via @makinbakin/sdk/utils next to formatAge), extracted verbatim from task-run-history's relativeTime (the calendar variant: Today/Yesterday + short-date + prior-year disambiguation) and its formatDuration. Migrates task-run-history onto the shared functions and deletes the health plugin's byte-identical local formatAge. Scope note: the audit's '7 reimpls' count predated a prior migration — the three assets/versioned sites (atoms, VersionedAssetGrid, VersionRow) already import formatAge from the SDK. The two remaining relative-age variants (models formatRelativeTime, team formatRelative) are intentionally left in place: they are NOT byte-identical to formatAge (seconds tier, date fallback) and folding them in would change rendering, violating the 'render identically' acceptance bar. They are candidates for a separate behavior-changing pass, not this extraction. New unit tests cover formatDuration + formatDateTime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ory maps Adds toneBadgeClass(tone) to @makinbakin/sdk/utils — a literal-string lookup (Tailwind @source-scanned) for the bg-X-500/10 text-X-400 border-X-500/20 outline-badge idiom across five tones (success/pending/error/muted/info). Migrates the two sites using that exact idiom: task-run-history's STATUS_CLASS + OUTCOME_CLASS and schedule run-history's status map. The settled=info(blue) vs done=success(green) distinction (#476) is preserved. Scope note: health-page's STATUS_TONE (border-less, yellow) and models-page's TIER_STYLES (border-less, purple) use a DIFFERENT badge idiom with off-palette colors — not the three-class outline idiom this helper encodes — so migrating them would change rendering. Left in place; documented as a distinct idiom. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
schedule run-history's local formatTime was an 8th calendar-variant reimpl the audit's count missed — identical to formatDateTime for current-year dates but lacking prior-year disambiguation. Replace it with the shared formatDateTime (the strictly-better source per WS3 A4); prior-year runs now carry the year. No change for same-year timestamps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e fork The team plugin maintained a forked EmptyState with a larger rounded-2xl icon chip + semibold title (for full-tab empty surfaces) alongside a dead fillHeight prop. Fold the visual variant into the SDK EmptyState behind a new variant='panel' prop: the default keeps the exact original SDK look (its 6 prior consumers render unchanged), and panel reproduces team's look exactly. Widen icon to ComponentType and description to ReactNode (both backward-compatible supertypes). Repoint team's 3 importers (heartbeat-tab, active-context-tab, agent-detail ×3) to @makinbakin/sdk/components with variant='panel', and delete plugins/team/components/empty-state.tsx. Dropped (not promoted to the published SDK): the fillHeight prop had zero importers repo-wide — promoting dead API to the SDK surface is worse than dropping unused code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a controlled ConfirmDialog to @makinbakin/sdk/components — busy/error aware, with a confirm-while-busy self-close guard — consolidating six near-identical hand-rolled delete dialogs. Migrates all six: schedule/delete-schedule-dialog and tasks/delete-task-dialog become thin wrappers; workflows/workflow-delete-action (keeps its trigger button + close-on-success logic), team/team-manager, team/agent-detail, and assets TagFolderGrid swap their inline Dialog blocks for ConfirmDialog. Props cover every observed variation: confirmLabel, busyLabel (+ spinner), cancelVariant (TagFolderGrid's ghost), error, confirmTestId (preserves folder-delete-confirm), and a className width override. Busy now consistently shows a spinner + disables both buttons (a minor enhancement for schedule/workflow, exact match for agent-detail/TagFolderGrid). Tests: new ConfirmDialog unit test (open gating, labels, busy, error, backdrop-close guard, testid). delete-schedule-dialog.test rewired to mock the shared ConfirmDialog. workflow-actions (real Radix) and the dialog-mocking schedule-page/kanban-dnd tests pass unchanged. 28 tests green across the 5 affected files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds useJsonFetch<T>(url, opts?) → { data, loading, error, refresh } to
@makinbakin/sdk/hooks — an AbortController-based cancellable JSON GET that replaces the
'let cancelled = false' fetch-in-useEffect boilerplate. url=null skips fetching; opts is
read per-request without re-triggering on identity. Unit-tested (load, skip, non-2xx,
network error, refresh).
Migrates the three clean-fit consumers: memory/tier-overview-cards (plain JSON→data) and
team's heartbeat-tab + active-context-tab (the {ok,payload,error} envelope, unwrapped via a
small derive). Existing component tests for all three pass unchanged.
Left as opportunistic (genuine non-fits for a single-URL read-only hook, noted in
tasks/plan.md): team-grid (best-effort badge, no loading/error, derived Set),
lesson-toggle-list (mutates lessons after fetch — needs writable state), overview-tab
(4-way Promise.all), and node-type-palette / assets AssetPreview / use-notification-channels
(module-cache hook) / PluginHost.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds useAvailableModels() to @makinbakin/sdk/hooks (impl in plugins/models/hooks/), a module-cached + single-flight read-only catalog of GET /api/plugins/models/available — mirroring the useNotificationChannels precedent (cache + test-only reset, returns the array directly, empty until loaded). Migrates the two model-picker consumers: team's agent-detail (clean swap) and agent-form (the /available fetch + default-model selection splits into the hook + a set-if-empty effect; the sibling /teams fetch stays). models-page is intentionally not migrated: it owns the live /refresh mutation flow and keeps its own mutable state — a read-only cached hook would break refresh-updates-the-list (the same boundary useNotificationChannels draws). Noted in tasks/plan.md. Existing agent-detail + models-page tests pass unchanged (34 across 5 files). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
task-detail-dialog hand-rolled WorkflowInstance/WorkflowDefinition independently. Re-base
them on the SDK wire types (WS1 single-sourced the shape — instanceId, not id) via
interface extension, narrowing only the fields this component reads (typed steps[] and
stepStates) that the SDK intentionally leaves open. The base wire fields now track one
source; drift on instanceId/workflowId/taskId/status can't recur.
Left as-is (deliberate, noted in tasks/plan.md):
- The local Workflow summary type ({filename, name, stepCount}) — the definitions-list
shape has no SDK equivalent.
- The instance/definition fetches — they are chained and imperatively re-fetched after
approve/reject/retry; useJsonFetch (A2) is not cleaner here, and the plan marks that
adoption optional.
typecheck + lint clean; task-detail-dialog + kanban tests pass (12).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mark all seven WS3b tasks complete with per-task scope notes, and document the new SDK client primitives (useJsonFetch, useAvailableModels, ConfirmDialog, EmptyState panel variant, toneBadgeClass, formatDateTime/formatDuration) in plugin-system.md's sub-path table + a 'Shared client primitives' section. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WS3b — the follow-up to WS3 (PR #501, A1 SSE consolidation only). Adds the remaining
client-side SDK primitives the audit found plugins reinventing, and migrates the genuine
duplicated consumers. One commit per finding; each green on typecheck.
Spec:
.claude/specs/audit-2026-06/REPORT.md. Plan:tasks/plan.md(archived WS3 plan attasks/plan-ws3-sdk-gaps.md).What's in it
formatDuration/formatDateTime(core/format →@makinbakin/sdk/utils). Migratedtask-run-history (the canonical calendar variant) + deleted health's byte-identical
formatAge;supplemental migration of schedule run-history's weaker
formatTime. Unit-tested.toneBadgeClass(SDK utils). Thebg-X-500/10 text-X-400 border-X-500/20outline-badgeidiom across 5 tones; migrated task-run-history + schedule run-history.
behind
variant='panel'; deleted the team fork. Default look unchanged (6 prior consumers intact).ConfirmDialog(SDK components). Consolidated all 6 hand-rolled delete dialogs(schedule, tasks, workflows, assets TagFolderGrid, team-manager, agent-detail). New unit test.
useJsonFetchhook (cancellable JSON GET). Migrated the 3 clean-fit consumers(memory tier-overview-cards, team heartbeat-tab + active-context-tab). Unit-tested.
useAvailableModelshook (module-cached, mirrorsuseNotificationChannels). Migratedthe agent-form + agent-detail model pickers.
WorkflowInstance/WorkflowDefinitionvia interface extension (single-sources the wire shape; WS1 fixed
instanceId).Scope discipline
The audit's 2026-06-13 recon predated #500/#501; several counts were stale and a few "migrations"
would have changed rendering/behavior. In each case I migrated the genuine fits and documented the
deliberate exclusions in the commit body +
tasks/plan.mdrather than forcing a lossy change —e.g. 3 assets sites already on
formatAge; health/models use a different border-less badge idiom;models-page owns the live
/refreshflow; the task-drawer's imperative instance fetches.Verification
bun run test: 5093 pass / 0 fail (5102 across 490 files).bun run typecheck: clean.bun run lint: clean (one pre-existing team-grid warning, untouched).bun run build: 3 binaries; build-stamp generated files reverted (tree clean).real-Radix, schedule-page, kanban-dnd, agent-detail ×5, tier-overview, etc.) pass unchanged.
per the plan. Logic is covered by the suite; visual/SSE parity wants the E2E before merge.
🤖 Generated with Claude Code