okengine 0.13.0 → 0.15.2

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.
Files changed (277) hide show
  1. package/manifest.v1.schema.json +7 -1
  2. package/package.json +4 -5
  3. package/site/content/docs/ai/mcp.mdx +27 -2
  4. package/site/content/docs/elements/ai.mdx +59 -11
  5. package/site/content/docs/elements/channel.mdx +1 -0
  6. package/site/content/docs/elements/clock.mdx +30 -12
  7. package/site/content/docs/elements/flow.mdx +9 -3
  8. package/site/content/docs/elements/gate.mdx +25 -22
  9. package/site/content/docs/elements/signal.mdx +71 -25
  10. package/site/content/docs/elements/store.mdx +87 -28
  11. package/site/content/docs/elements/vault.mdx +1 -0
  12. package/site/content/docs/get-started/basic-usage.mdx +22 -13
  13. package/site/content/docs/get-started/index.mdx +5 -0
  14. package/site/content/docs/get-started/installation.mdx +2 -2
  15. package/site/content/docs/get-started/introduction.mdx +11 -3
  16. package/site/content/docs/get-started/meta.json +1 -1
  17. package/site/content/docs/get-started/project-structure.mdx +932 -0
  18. package/site/content/docs/reference/cli.md +13 -10
  19. package/site/content/docs/reference/client.mdx +25 -21
  20. package/site/content/docs/reference/fx.mdx +27 -22
  21. package/site/content/docs/reference/security.md +1 -1
  22. package/src/auth/bindings.ts +14 -5
  23. package/src/auth/cross-plane.ts +10 -3
  24. package/src/cli/ai-setup/ai-setup.test.ts +62 -0
  25. package/src/cli/ai-setup/apply.ts +32 -1
  26. package/src/cli/ai-setup/recommend.test.ts +25 -0
  27. package/src/cli/ai-setup/recommend.ts +8 -3
  28. package/src/cli/attach-host-console.test.ts +3 -2
  29. package/src/cli/attach-host-console.ts +3 -0
  30. package/src/cli/build.test.ts +4 -2
  31. package/src/cli/db-seed.ts +48 -15
  32. package/src/cli/db.test.ts +104 -0
  33. package/src/cli/db.ts +122 -10
  34. package/src/cli/dev-controls.test.ts +20 -0
  35. package/src/cli/dev-controls.ts +13 -0
  36. package/src/cli/dev.test.ts +15 -4
  37. package/src/cli/dev.ts +102 -29
  38. package/src/cli/ensure-drizzle-config.ts +2 -1
  39. package/src/cli/tui/DevLive.tsx +12 -2
  40. package/src/cli/tui/keys.test.ts +2 -1
  41. package/src/cli/tui/keys.ts +3 -2
  42. package/src/compiler/aot.test.ts +1 -1
  43. package/src/compiler/effects-infer.ts +58 -3
  44. package/src/compiler/extract.test.ts +458 -29
  45. package/src/compiler/extract.ts +387 -69
  46. package/src/compiler/flow-path.test.ts +96 -0
  47. package/src/compiler/flow-path.ts +173 -0
  48. package/src/compiler/generate-adopt.test.ts +112 -3
  49. package/src/compiler/generate-adopt.ts +280 -26
  50. package/src/compiler/response.ts +45 -1
  51. package/src/compiler/schema-from-ast.ts +609 -0
  52. package/src/console/server/ai.ts +5 -2
  53. package/src/console/server/bind.ts +2 -2
  54. package/src/console/server/console.test.ts +3 -0
  55. package/src/console/server/flows.ts +121 -40
  56. package/src/console/server/invoke-user-flow.test.ts +3 -1
  57. package/src/console/server/invoke-user-flow.ts +17 -2
  58. package/src/console/server/iso-at.test.ts +9 -0
  59. package/src/console/server/iso-at.ts +11 -0
  60. package/src/console/server/security-headers.ts +6 -3
  61. package/src/console/server/serve.ts +17 -2
  62. package/src/console/server/spa-proxy.test.ts +1 -0
  63. package/src/console/server/sql-catalog.ts +147 -7
  64. package/src/console/server/sql-rls.test.ts +16 -0
  65. package/src/console/server/state.ts +8 -0
  66. package/src/console/server/store.test.ts +7 -4
  67. package/src/console/server/store.ts +142 -58
  68. package/src/console/ui-next/dist/assets/agent-disclosure-C0X1fbWF.js +1 -0
  69. package/src/console/ui-next/dist/assets/cache-glyph-F1FI122b.js +1 -0
  70. package/src/console/ui-next/dist/assets/{call-pii-button-bqkxMrJH.js → call-pii-button-DEDCl_j3.js} +1 -1
  71. package/src/console/ui-next/dist/assets/collapsible-LPqGvfoz.js +1 -0
  72. package/src/console/ui-next/dist/assets/{confirm-sheet-DDCRmG62.js → confirm-sheet-3ptDzXbz.js} +1 -1
  73. package/src/console/ui-next/dist/assets/{duration-tone-oiRxPVsZ.js → duration-tone-sC3lGABz.js} +1 -1
  74. package/src/console/ui-next/dist/assets/{explorer-empty-HjTnVQoR.js → explorer-empty-BvYrygyO.js} +1 -1
  75. package/src/console/ui-next/dist/assets/flows-page-Dluo1Bd7.js +1 -0
  76. package/src/console/ui-next/dist/assets/{highlighted-json-CvDPvveV.js → highlighted-json-CS_O8L-r.js} +1 -1
  77. package/src/console/ui-next/dist/assets/http-method--sWDdXSB.js +1 -0
  78. package/src/console/ui-next/dist/assets/index-Ca3HZMVq.js +66 -0
  79. package/src/console/ui-next/dist/assets/index-UtTDRQpS.css +2 -0
  80. package/src/console/ui-next/dist/assets/{link-DF7SZ9Ek.js → link-COeyggt-.js} +1 -1
  81. package/src/console/ui-next/dist/assets/observability-page-HK9-BO8z.js +4 -0
  82. package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +1 -0
  83. package/src/console/ui-next/dist/assets/replica-lag-DBIFFf7d.js +18 -0
  84. package/src/console/ui-next/dist/assets/sheet-form-Dnwa5oOR.js +1 -0
  85. package/src/console/ui-next/dist/assets/shortcut-keys-CoqwEIi0.js +1 -0
  86. package/src/console/ui-next/dist/assets/skeleton-BHcfDYcb.js +1 -0
  87. package/src/console/ui-next/dist/assets/store-page-BSohH3wM.js +41 -0
  88. package/src/console/ui-next/dist/assets/trace-detail-sheet-CFIGRnnA.js +2 -0
  89. package/src/console/ui-next/dist/assets/tree-expand-toggle-BgLl34w7.js +54 -0
  90. package/src/console/ui-next/dist/assets/units-page-B0cFE76A.js +1 -0
  91. package/src/console/ui-next/dist/assets/{use-vault-list-Cl79j_ku.js → use-vault-list-BLbZhzyF.js} +1 -1
  92. package/src/console/ui-next/dist/assets/vault-page-B1SbYe10.js +2 -0
  93. package/src/console/ui-next/dist/index.html +6 -6
  94. package/src/console/ui-next/seed-invoke-host.ts +2 -0
  95. package/src/console/ui-next/src/client.ts +35 -7
  96. package/src/console/ui-next/src/components/motion/table/index.tsx +16 -0
  97. package/src/console/ui-next/src/components/motion/table/types.ts +4 -0
  98. package/src/console/ui-next/src/components/ui/kbd.tsx +2 -2
  99. package/src/console/ui-next/src/features/flows/graph/build-flow-graph.test.ts +18 -0
  100. package/src/console/ui-next/src/features/flows/graph/build-flow-graph.ts +14 -1
  101. package/src/console/ui-next/src/features/flows/graph/neighborhood.test.ts +17 -0
  102. package/src/console/ui-next/src/features/flows/graph/neighborhood.ts +16 -3
  103. package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +3 -1
  104. package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +24 -0
  105. package/src/console/ui-next/src/features/flows/traces/http-method.ts +19 -0
  106. package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +9 -3
  107. package/src/console/ui-next/src/features/flows/traces/trace-detail.test.ts +29 -2
  108. package/src/console/ui-next/src/features/flows/traces/traces-pane.tsx +10 -3
  109. package/src/console/ui-next/src/features/observability/lib/ask-count.test.ts +25 -0
  110. package/src/console/ui-next/src/features/observability/lib/ask-count.ts +4 -1
  111. package/src/console/ui-next/src/features/store/detail/browse-section.tsx +45 -1
  112. package/src/console/ui-next/src/features/store/detail/resource-panel.tsx +78 -16
  113. package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +155 -14
  114. package/src/console/ui-next/src/features/store/explorer/store-tree.tsx +33 -133
  115. package/src/console/ui-next/src/features/store/files/file-preview.tsx +4 -1
  116. package/src/console/ui-next/src/features/store/grid/rls-policy-sheet.tsx +326 -165
  117. package/src/console/ui-next/src/features/store/grid/sql-insert-sheet.tsx +6 -0
  118. package/src/console/ui-next/src/features/store/grid/store-data-grid.tsx +50 -3
  119. package/src/console/ui-next/src/features/store/lib/files-meta.test.ts +3 -0
  120. package/src/console/ui-next/src/features/store/lib/files-meta.ts +12 -0
  121. package/src/console/ui-next/src/features/store/lib/query-defaults.test.ts +25 -0
  122. package/src/console/ui-next/src/features/store/lib/query-defaults.ts +85 -3
  123. package/src/console/ui-next/src/features/store/lib/query-gate.ts +30 -4
  124. package/src/console/ui-next/src/features/store/lib/rls-policy.test.ts +139 -0
  125. package/src/console/ui-next/src/features/store/lib/rls-policy.ts +223 -21
  126. package/src/console/ui-next/src/features/store/lib/schema-graph.ts +4 -0
  127. package/src/console/ui-next/src/features/store/lib/sql-catalog.test.ts +24 -0
  128. package/src/console/ui-next/src/features/store/lib/sql-catalog.ts +19 -0
  129. package/src/console/ui-next/src/features/store/lib/store-tree.test.ts +6 -0
  130. package/src/console/ui-next/src/features/store/lib/store-tree.ts +13 -0
  131. package/src/console/ui-next/src/features/store/query/query-console.tsx +48 -14
  132. package/src/console/ui-next/src/features/store/query/query-gate-menu.tsx +19 -20
  133. package/src/console/ui-next/src/features/store/query/query-gate-parts.tsx +2 -1
  134. package/src/console/ui-next/src/features/store/query/query-results.tsx +110 -83
  135. package/src/console/ui-next/src/features/store/schema/schema-table-node.tsx +17 -0
  136. package/src/console/ui-next/src/features/units/call/call-api-panel.tsx +112 -72
  137. package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +12 -4
  138. package/src/console/ui-next/src/features/units/lib/contract-input.test.ts +206 -1
  139. package/src/console/ui-next/src/features/units/lib/contract-input.ts +55 -0
  140. package/src/console/ui-next/src/features/vault/lib/types.ts +1 -1
  141. package/src/docker/compose-health.test.ts +27 -0
  142. package/src/docker/compose-health.ts +19 -3
  143. package/src/docker/docker.test.ts +4 -1
  144. package/src/docker/dockerfile.ts +1 -1
  145. package/src/docker/recipes/pgdog.ts +2 -0
  146. package/src/drivers/ai-anthropic.ts +5 -0
  147. package/src/drivers/ai-ollama.ts +49 -30
  148. package/src/drivers/ai-openai-compatible.ts +57 -46
  149. package/src/drivers/ai-providers.test.ts +3 -0
  150. package/src/drivers/bun-native-completeness.test.ts +7 -9
  151. package/src/drivers/clock-postgres.ts +13 -9
  152. package/src/drivers/instances-postgres.ts +4 -6
  153. package/src/drivers/journal-postgres.ts +13 -9
  154. package/src/drivers/pg-rls.test.ts +87 -0
  155. package/src/drivers/pg-rls.ts +233 -7
  156. package/src/drivers/pglite.ts +26 -3
  157. package/src/drivers/postgres.test.ts +23 -0
  158. package/src/drivers/postgres.ts +133 -9
  159. package/src/drivers/redis.ts +11 -4
  160. package/src/drivers/signal-redis.ts +24 -14
  161. package/src/drivers/signal-types.ts +2 -1
  162. package/src/drivers/types.ts +10 -0
  163. package/src/elements/ai/declare.ts +109 -0
  164. package/src/elements/ai/errors.test.ts +5 -1
  165. package/src/elements/ai/errors.ts +30 -2
  166. package/src/elements/ai/eval.ts +4 -6
  167. package/src/elements/ai/mcp-client.test.ts +206 -0
  168. package/src/elements/ai/mcp-client.ts +362 -0
  169. package/src/elements/ai/mcp-http.ts +159 -0
  170. package/src/elements/ai/mcp-mock.ts +134 -0
  171. package/src/elements/ai/mcp-protocol.ts +234 -0
  172. package/src/elements/ai/mcp-stdio.test.ts +50 -0
  173. package/src/elements/ai/mcp-stdio.ts +212 -0
  174. package/src/elements/ai/mcp-transport.ts +70 -0
  175. package/src/elements/ai/runtime.ts +159 -29
  176. package/src/elements/ai.test.ts +139 -0
  177. package/src/elements/ai.ts +16 -0
  178. package/src/elements/clock/declare.ts +26 -1
  179. package/src/elements/clock/health.test.ts +43 -0
  180. package/src/elements/clock/runtime.ts +55 -2
  181. package/src/elements/clock/schedule.ts +71 -142
  182. package/src/elements/clock.test.ts +9 -40
  183. package/src/elements/clock.ts +6 -1
  184. package/src/elements/gate/boot.ts +5 -5
  185. package/src/elements/gate/declare.ts +36 -4
  186. package/src/elements/gate/flatten.ts +1 -1
  187. package/src/elements/gate/runtime.ts +1 -1
  188. package/src/elements/index.ts +2 -0
  189. package/src/elements/signal/declare.ts +2 -1
  190. package/src/elements/signal/runtime.ts +16 -1
  191. package/src/elements/signal.ts +1 -0
  192. package/src/elements/store/cache.test.ts +2 -0
  193. package/src/elements/store/cache.ts +3 -3
  194. package/src/elements/store/declare.ts +9 -6
  195. package/src/elements/store/emit-drizzle.ts +44 -8
  196. package/src/elements/store/resource.test.ts +1 -1
  197. package/src/elements/store/rls-identity.test.ts +95 -0
  198. package/src/elements/store/rls-identity.ts +116 -0
  199. package/src/elements/store/runtime.ts +4 -0
  200. package/src/elements/store/schema-decl.test.ts +37 -0
  201. package/src/elements/store/schema-decl.ts +161 -0
  202. package/src/elements/store/seed.ts +1 -1
  203. package/src/elements/store/sql-condition.test.ts +12 -0
  204. package/src/elements/store/sql-condition.ts +26 -2
  205. package/src/elements/store/sql-rls-isolation.test.ts +165 -0
  206. package/src/elements/store/sql-rls-stamp.test.ts +117 -0
  207. package/src/elements/store/sql-session.ts +81 -3
  208. package/src/elements/store/upsert-app.test.ts +1 -1
  209. package/src/elements/store.ts +14 -0
  210. package/src/elements/vault/builtin-adapter.ts +17 -0
  211. package/src/full.ts +2 -0
  212. package/src/http.ts +20 -3
  213. package/src/index.ts +14 -1
  214. package/src/kernel/adopt-barrel-fresh.test.ts +1 -1
  215. package/src/kernel/adopt-routes.ts +30 -2
  216. package/src/kernel/app.ts +227 -77
  217. package/src/kernel/auto-cache.test.ts +8 -8
  218. package/src/kernel/auto-registry.test.ts +54 -9
  219. package/src/kernel/boot-bind/ai.ts +24 -0
  220. package/src/kernel/boot-bind/clock.ts +2 -0
  221. package/src/kernel/boot.test.ts +4 -4
  222. package/src/kernel/boot.ts +5 -3
  223. package/src/kernel/effects-stamping.test.ts +3 -3
  224. package/src/kernel/element-registries.ts +15 -5
  225. package/src/kernel/errors.ts +24 -0
  226. package/src/kernel/flow-units.ts +64 -0
  227. package/src/kernel/flow.ts +29 -17
  228. package/src/kernel/fx-dead-letters.test.ts +77 -0
  229. package/src/kernel/fx.test.ts +22 -0
  230. package/src/kernel/fx.ts +135 -6
  231. package/src/kernel/horizontal-child.ts +4 -4
  232. package/src/kernel/http-path-pending.ts +20 -0
  233. package/src/kernel/http-resource.ts +4 -0
  234. package/src/kernel/http-stream.test.ts +174 -0
  235. package/src/kernel/index.ts +2 -0
  236. package/src/kernel/pipeline.test.ts +2 -2
  237. package/src/kernel/plugin-elements.test.ts +1 -1
  238. package/src/kernel/plugin-needs.test.ts +1 -1
  239. package/src/kernel/ready.test.ts +2 -2
  240. package/src/kernel/resource-mount.test.ts +14 -0
  241. package/src/kernel/run-duration.test.ts +2 -2
  242. package/src/kernel/stamp-http.test.ts +79 -0
  243. package/src/kernel/stamp-http.ts +75 -0
  244. package/src/kernel/triggers.ts +52 -27
  245. package/src/manifest/mcp-ref.ts +88 -0
  246. package/src/manifest/types.ts +41 -2
  247. package/src/manifest/validate.test.ts +20 -0
  248. package/src/mcp/docs-server.ts +1 -1
  249. package/src/mcp/server.ts +1 -1
  250. package/src/plugins/compression.test.ts +21 -0
  251. package/src/plugins/compression.ts +1 -0
  252. package/src/release/measure.ts +2 -2
  253. package/src/runtime/bun.ts +41 -4
  254. package/src/runtime/json-code-block.test.ts +2 -2
  255. package/src/runtime/serve.test.ts +4 -4
  256. package/src/term.test.ts +52 -4
  257. package/src/term.ts +125 -17
  258. package/src/test/reset-element-registries.ts +10 -3
  259. package/src/cli/ask-seed.test.ts +0 -96
  260. package/src/cli/ask-seed.ts +0 -82
  261. package/src/console/ui-next/dist/assets/cache-glyph-CLPBqZeb.js +0 -1
  262. package/src/console/ui-next/dist/assets/collapsible-DYb0xU8C.js +0 -1
  263. package/src/console/ui-next/dist/assets/flows-page-Dg8CTE29.js +0 -1
  264. package/src/console/ui-next/dist/assets/http-method-BJ92Z_ke.js +0 -1
  265. package/src/console/ui-next/dist/assets/index-Bp-R7jtM.js +0 -66
  266. package/src/console/ui-next/dist/assets/index-D4Ldtj79.css +0 -2
  267. package/src/console/ui-next/dist/assets/observability-page-DAnpEaq1.js +0 -4
  268. package/src/console/ui-next/dist/assets/query-gate-parts-1m8m1iNp.js +0 -2
  269. package/src/console/ui-next/dist/assets/react-B1ML8gxg.js +0 -1
  270. package/src/console/ui-next/dist/assets/replica-lag-C8_BRt2x.js +0 -18
  271. package/src/console/ui-next/dist/assets/sheet-form-D-ata7jy.js +0 -1
  272. package/src/console/ui-next/dist/assets/shortcut-keys-DO4IsVqv.js +0 -1
  273. package/src/console/ui-next/dist/assets/skeleton-CL_X0GCj.js +0 -1
  274. package/src/console/ui-next/dist/assets/store-page-v3LXdYpr.js +0 -45
  275. package/src/console/ui-next/dist/assets/trace-detail-sheet-D16lWQMt.js +0 -2
  276. package/src/console/ui-next/dist/assets/units-page-BtQ0bqMe.js +0 -1
  277. package/src/console/ui-next/dist/assets/vault-page-Ca-MvcmJ.js +0 -2
@@ -17,8 +17,6 @@ import {
17
17
  ShieldOff,
18
18
  SourceCodeIcon,
19
19
  TableIcon,
20
- ViewIcon,
21
- ViewOffSlashIcon,
22
20
  ZapIcon,
23
21
  } from "@hugeicons/core-free-icons";
24
22
  import { HugeiconsIcon } from "@hugeicons/react";
@@ -33,7 +31,6 @@ import {
33
31
  EXPLORER_GROUP_ROW_CLASS,
34
32
  EXPLORER_ICON_BUTTON_CLASS,
35
33
  EXPLORER_ICON_CLASS,
36
- EXPLORER_STRIP_TOKEN_ACTIVE_CLASS,
37
34
  EXPLORER_LIST_EMPTY_CLASS,
38
35
  EXPLORER_RAIL_ACTIVE_CLASS,
39
36
  EXPLORER_RAIL_CLASS,
@@ -45,16 +42,6 @@ import {
45
42
  import { ExplorerSearch } from "@/components/explorer/explorer-search.tsx";
46
43
  import { TreeExpandToggle } from "@/components/explorer/tree-expand-toggle.tsx";
47
44
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
48
- import {
49
- DropdownMenu,
50
- DropdownMenuCheckboxItem,
51
- DropdownMenuContent,
52
- DropdownMenuGroup,
53
- DropdownMenuItem,
54
- DropdownMenuLabel,
55
- DropdownMenuSeparator,
56
- DropdownMenuTrigger,
57
- } from "@/components/ui/dropdown-menu";
58
45
  import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
59
46
  import type { ElementHugeIcon } from "@/lib/element-icons.ts";
60
47
  import { cn } from "@/lib/utils";
@@ -65,6 +52,7 @@ import {
65
52
  loadHiddenFacets,
66
53
  saveHiddenFacets,
67
54
  STORE_FACET_SPECS,
55
+ STORE_FACETS,
68
56
  isSingletonStoreLeaf,
69
57
  storeTreeAncestorKeys,
70
58
  storeTreeFacetKey,
@@ -127,7 +115,6 @@ export function StoreTree({
127
115
  const [query, setQuery] = useState("");
128
116
  const [openByKey, setOpenByKey] = useState<Readonly<Record<string, boolean>>>({});
129
117
  const [hiddenFacets, setHiddenFacets] = useState<ReadonlySet<StoreFacet>>(loadHiddenFacets);
130
- const allBands = useMemo(() => bandStoreTree(stores), [stores]);
131
118
  const bands = useMemo(() => bandStoreTree(filterStoreTree(stores, query)), [stores, query]);
132
119
  const visibleBands = useMemo(() => visibleFacetBands(bands, hiddenFacets), [bands, hiddenFacets]);
133
120
  const keys = useMemo(() => storeTreeOpenKeys(visibleBands), [visibleBands]);
@@ -172,15 +159,6 @@ export function StoreTree({
172
159
  });
173
160
  };
174
161
 
175
- const showAllFacets = (): void => {
176
- setHiddenFacets((prev) => {
177
- if (prev.size === 0) return prev;
178
- const next = new Set<StoreFacet>();
179
- saveHiddenFacets(next);
180
- return next;
181
- });
182
- };
183
-
184
162
  const toggleAll = (): void => {
185
163
  const next = !allOpen;
186
164
  setOpenByKey((prev) => {
@@ -201,12 +179,7 @@ export function StoreTree({
201
179
  aria-label="Search stores"
202
180
  data-slot="store-search"
203
181
  />
204
- <FacetVisibilityMenu
205
- bands={allBands}
206
- hiddenFacets={hiddenFacets}
207
- onHiddenChange={setFacetHidden}
208
- onShowAll={showAllFacets}
209
- />
182
+ <FacetIconToggles hiddenFacets={hiddenFacets} onHiddenChange={setFacetHidden} />
210
183
  <TreeExpandToggle
211
184
  allOpen={allOpen}
212
185
  disabled={keys.length === 0}
@@ -229,7 +202,6 @@ export function StoreTree({
229
202
  <FacetBand
230
203
  key={band.facet}
231
204
  band={band}
232
- onHide={() => setFacetHidden(band.facet, true)}
233
205
  open={storeTreeIsOpen(facetKey, openByKey)}
234
206
  onOpenChange={(open) => setKeyOpen(facetKey, open)}
235
207
  storeOpen={(ref) =>
@@ -267,79 +239,53 @@ export function StoreTree({
267
239
  }
268
240
 
269
241
  /**
270
- * Search-bar control to show or hide Store facet bands.
242
+ * Toolbar tokens for the four Store facets — press to show or hide the band.
271
243
  *
272
- * @param props - Present bands + hidden set + toggles
244
+ * @param props - Hidden set + toggle
273
245
  */
274
- function FacetVisibilityMenu({
275
- bands,
246
+ function FacetIconToggles({
276
247
  hiddenFacets,
277
248
  onHiddenChange,
278
- onShowAll,
279
249
  }: {
280
- readonly bands: readonly StoreFacetBand[];
281
250
  readonly hiddenFacets: ReadonlySet<StoreFacet>;
282
251
  readonly onHiddenChange: (facet: StoreFacet, hidden: boolean) => void;
283
- readonly onShowAll: () => void;
284
252
  }): JSX.Element {
285
- const hiddenCount = bands.filter((band) => hiddenFacets.has(band.facet)).length;
286
- const anyHidden = hiddenCount > 0;
287
-
288
253
  return (
289
- <DropdownMenu>
290
- <ToolbarTip label="Show and hide facets" className="flex self-stretch">
291
- <DropdownMenuTrigger
292
- render={(props) => (
254
+ <div
255
+ className="flex h-full shrink-0 items-stretch"
256
+ role="group"
257
+ aria-label="Store facets"
258
+ data-slot="store-tree-facet-toggles"
259
+ >
260
+ {STORE_FACETS.map((facet) => {
261
+ const spec = STORE_FACET_SPECS[facet];
262
+ const visible = !hiddenFacets.has(facet);
263
+ return (
264
+ <ToolbarTip
265
+ key={facet}
266
+ label={visible ? `Hide ${spec.label}` : `Show ${spec.label}`}
267
+ className="flex self-stretch"
268
+ >
293
269
  <button
294
- {...props}
295
270
  type="button"
296
- aria-label="Show and hide facets"
297
- data-slot="store-tree-visibility"
298
- disabled={bands.length === 0}
271
+ aria-label={visible ? `Hide ${spec.label}` : `Show ${spec.label}`}
272
+ aria-pressed={visible}
273
+ data-slot="store-tree-facet-toggle"
274
+ data-facet={facet}
275
+ onClick={() => onHiddenChange(facet, visible)}
299
276
  className={cn(
300
277
  EXPLORER_ICON_BUTTON_CLASS,
301
- anyHidden && EXPLORER_STRIP_TOKEN_ACTIVE_CLASS,
278
+ visible
279
+ ? explorerIconInk(spec.wellClass)
280
+ : "text-muted-foreground/40 hover:text-muted-foreground",
302
281
  )}
303
282
  >
304
- <HugeiconsIcon
305
- icon={anyHidden ? ViewOffSlashIcon : ViewIcon}
306
- className="size-3.5"
307
- aria-hidden
308
- />
283
+ <HugeiconsIcon icon={spec.icon} className={EXPLORER_ICON_CLASS} aria-hidden />
309
284
  </button>
310
- )}
311
- />
312
- </ToolbarTip>
313
- <DropdownMenuContent align="end" className="w-44">
314
- <DropdownMenuGroup>
315
- <DropdownMenuLabel>Facets</DropdownMenuLabel>
316
- {bands.map((band) => {
317
- const spec = STORE_FACET_SPECS[band.facet];
318
- const visible = !hiddenFacets.has(band.facet);
319
- return (
320
- <DropdownMenuCheckboxItem
321
- key={band.facet}
322
- checked={visible}
323
- data-slot="store-tree-visibility-facet"
324
- data-facet={band.facet}
325
- onCheckedChange={(checked) => onHiddenChange(band.facet, checked === false)}
326
- >
327
- <HugeiconsIcon icon={spec.icon} className="size-3.5" aria-hidden />
328
- {spec.label}
329
- </DropdownMenuCheckboxItem>
330
- );
331
- })}
332
- </DropdownMenuGroup>
333
- {anyHidden ? (
334
- <>
335
- <DropdownMenuSeparator />
336
- <DropdownMenuItem data-slot="store-tree-visibility-show-all" onClick={onShowAll}>
337
- Show all
338
- </DropdownMenuItem>
339
- </>
340
- ) : null}
341
- </DropdownMenuContent>
342
- </DropdownMenu>
285
+ </ToolbarTip>
286
+ );
287
+ })}
288
+ </div>
343
289
  );
344
290
  }
345
291
 
@@ -350,7 +296,6 @@ function FacetVisibilityMenu({
350
296
  */
351
297
  function FacetBand({
352
298
  band,
353
- onHide,
354
299
  open,
355
300
  onOpenChange,
356
301
  storeOpen,
@@ -365,7 +310,6 @@ function FacetBand({
365
310
  onOpenPerformance,
366
311
  }: {
367
312
  readonly band: StoreFacetBand;
368
- readonly onHide: () => void;
369
313
  readonly open: boolean;
370
314
  readonly onOpenChange: (open: boolean) => void;
371
315
  readonly storeOpen: (ref: string) => boolean;
@@ -444,7 +388,6 @@ function FacetBand({
444
388
  onOpen={onOpenQuery}
445
389
  />
446
390
  ) : null}
447
- <FacetVisibilityButton label={band.label} onHide={onHide} />
448
391
  <TreeExpandToggle
449
392
  allOpen={storesOpen}
450
393
  disabled={storeRefs.length === 0}
@@ -821,49 +764,6 @@ function PerformanceBandButton({
821
764
  );
822
765
  }
823
766
 
824
- /**
825
- * Hide a facet band from the explorer. Restore it from the search-bar menu.
826
- *
827
- * @param props - Band label + hide
828
- */
829
- function FacetVisibilityButton({
830
- label,
831
- onHide,
832
- }: {
833
- readonly label: string;
834
- readonly onHide: () => void;
835
- }): JSX.Element {
836
- const action = `Hide ${label}`;
837
- return (
838
- <Tooltip>
839
- <TooltipTrigger
840
- render={(props) => (
841
- <button
842
- {...props}
843
- type="button"
844
- aria-label={action}
845
- data-slot="store-facet-visibility"
846
- onClick={(event) => {
847
- event.stopPropagation();
848
- props.onClick?.(event);
849
- onHide();
850
- }}
851
- className={cn(
852
- "inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors",
853
- "hover:bg-muted/80 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/40 focus-visible:outline-none",
854
- )}
855
- >
856
- <HugeiconsIcon icon={ViewOffSlashIcon} className="size-3.5" aria-hidden />
857
- </button>
858
- )}
859
- />
860
- <TooltipContent side="bottom" className="text-[11px]">
861
- {action}
862
- </TooltipContent>
863
- </Tooltip>
864
- );
865
- }
866
-
867
767
  /**
868
768
  * Chevron well on a facet or store row — reads as the expand control.
869
769
  *
@@ -25,6 +25,7 @@ import {
25
25
  fileNameFromKey,
26
26
  filePreviewMode,
27
27
  formatFilePreviewText,
28
+ previewBlobType,
28
29
  type FileKind,
29
30
  type FilePreviewMode,
30
31
  } from "../lib/files-meta.ts";
@@ -82,7 +83,9 @@ export function FilePreview({
82
83
  const objectUrl = useMemo(() => {
83
84
  if (!object.data || !bytes || object.data.truncated) return null;
84
85
  if (mode !== "image" && mode !== "pdf" && mode !== "video" && mode !== "audio") return null;
85
- const blob = new Blob([bytesToArrayBuffer(bytes)], { type: object.data.contentType });
86
+ const blob = new Blob([bytesToArrayBuffer(bytes)], {
87
+ type: previewBlobType(mode, object.data.contentType),
88
+ });
86
89
  return URL.createObjectURL(blob);
87
90
  }, [object.data, bytes, mode]);
88
91