Cowork D: artifact side panel with per-kind renderers #65

Merged
ryan merged 4 commits from feat/cowork-artifact-panel into main 2026-10-12 18:41:43 -04:00

4 Commits

Author SHA1 Message Date
Ryan Chen b6bb9ec8cf Merge artifact scenarios into the shared Cowork mock server
One mock server now serves both the timeline scenarios and the artifact
panel's: per-kind fixtures from artifacts/<kind>.json, an "everything"
conversation with one saved tool message per kind, keyword scenarios
(recipe, budget, trend, philz, everything, broken, mystery, ...), a
500ing "broken" artifact, and small delays on /api/artifacts* so the
panel's loading states are visible. SPENDING now uses positive amounts
like the backend.

Also: renderers reuse ArtifactSourceRef, and the collapsed rail's
buttons say "Show <title>" so they don't share the timeline chip's
"Open <title>" accessible name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:40:31 -04:00
Ryan Chen d065b70667 Reconcile artifact renderers and fixtures with the backend shapes
Workers A/B are merged, so match what blueprints/ynab/tools.py and
conversation/agents.py actually emit:

- ynab.spending_report rows and ynab.summary.spent are positive for
  spending; bars use the positive amount and a net refund (negative
  row) sorts last with no bar.
- ynab.transactions start_date may be null (open-ended search); the
  header reads "Through Oct 12, 2026". Amounts stay signed with
  outflows as −$, and total is the net.
- Recipe image_url is never sent, search.documents has no source_ref,
  memo/age_of_money/goal_target are optional; fixtures now match
  (backend titles, ordering, float quantities, no empty fields).
- Mock server: drop the placeholder recipe image, positive month
  spending, and a "philz" open-ended transactions scenario.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:37:36 -04:00
Ryan Chen 0ae87ee610 Add artifact panel with per-kind renderers
Right-hand pane (440px, lg and up) with tabs, collapse rail and a
library of the conversation's artifacts; a bottom sheet below lg.
useArtifactPanel holds tabs/active and caches fetched artifacts by id;
tabs reset on conversation change.

Artifacts from tool_end auto-open on windows >= 1280px (newest wins,
and a panel the user collapsed stays collapsed). ChatScreen exposes
openArtifact for the activity timeline's onOpenArtifact and adds an
Artifacts button to the chat header.

One renderer per v1 kind (YNAB summary, category budget, spending
report, transactions; Mealie recipe, meal plan, shopping lists;
Obsidian note; document search) using CSS bars only, plus a JSON
fallback for unknown kinds or renderer errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:37:33 -04:00
Ryan Chen 396e24f2f0 Add artifact API service, per-kind fixtures and Cowork mock server
artifactTypes.ts mirrors the contract (worker C creates the same file).
artifactService.ts wraps GET /api/artifacts and /api/artifacts/<id>
with the shared fetchWithAuth helper.

test-fixtures/cowork/artifacts/<kind>.json holds one ToolArtifact per
v1 kind. mock-server.mjs is a dependency-free Node server that serves
dist/ and speaks the contract (SSE v2 tool events, artifacts API) for
Playwright checks without Docker or OIDC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:37:07 -04:00