okengine 0.6.0 → 0.7.0

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 (162) hide show
  1. package/AGENTS.md +2 -2
  2. package/README.md +98 -71
  3. package/package.json +4 -4
  4. package/site/content/docs/console/clock.mdx +25 -5
  5. package/site/content/docs/console/signals.mdx +13 -4
  6. package/site/content/docs/elements/ai.mdx +29 -2
  7. package/site/content/docs/elements/channel.mdx +90 -20
  8. package/site/content/docs/elements/clock.mdx +56 -24
  9. package/site/content/docs/elements/flow.mdx +2 -0
  10. package/site/content/docs/elements/gate.mdx +8 -1
  11. package/site/content/docs/elements/signal.mdx +173 -29
  12. package/site/content/docs/elements/store.mdx +464 -73
  13. package/site/content/docs/elements/vault.mdx +15 -5
  14. package/site/content/docs/get-started/basic-usage.mdx +13 -6
  15. package/site/content/docs/get-started/installation.mdx +49 -13
  16. package/site/content/docs/get-started/introduction.mdx +1 -1
  17. package/site/content/docs/reference/cli.md +30 -2
  18. package/site/content/docs/reference/configuration.mdx +18 -17
  19. package/site/content/docs/reference/environment-variables.mdx +44 -18
  20. package/site/content/docs/reference/errors.mdx +12 -11
  21. package/site/content/docs/reference/fx.mdx +15 -13
  22. package/site/content/docs/reference/security.md +3 -1
  23. package/src/cli/ai-setup/ai-setup.test.ts +144 -0
  24. package/src/cli/ai-setup/apply.ts +214 -0
  25. package/src/cli/ai-setup/catalog.ts +263 -0
  26. package/src/cli/ai-setup/detect-ollama.ts +166 -0
  27. package/src/cli/ai-setup/index.ts +228 -0
  28. package/src/cli/ai-setup/prompts.ts +649 -0
  29. package/src/cli/ai-setup/recommend.test.ts +100 -0
  30. package/src/cli/ai-setup/recommend.ts +203 -0
  31. package/src/cli/ai.ts +38 -0
  32. package/src/cli/db-auto-push.test.ts +6 -1
  33. package/src/cli/db-auto-push.ts +8 -3
  34. package/src/cli/dev-db-push.test.ts +59 -0
  35. package/src/cli/dev.test.ts +40 -0
  36. package/src/cli/dev.ts +55 -1
  37. package/src/cli/docker-clean.test.ts +179 -0
  38. package/src/cli/docker-clean.ts +406 -0
  39. package/src/cli/docker.ts +16 -4
  40. package/src/cli/ensure-drizzle-config.ts +1 -1
  41. package/src/cli/hero-meta.test.ts +6 -5
  42. package/src/cli/hero-meta.ts +7 -1
  43. package/src/cli/index.ts +5 -0
  44. package/src/cli/load-config.ts +4 -4
  45. package/src/cli/openbao-bootstrap.test.ts +1 -0
  46. package/src/cli/openbao-bootstrap.ts +9 -2
  47. package/src/cli/openbao-restart.integration.test.ts +106 -97
  48. package/src/cli/registry.ts +79 -1
  49. package/src/client/live-gap.test.ts +35 -0
  50. package/src/client/transport.test.ts +21 -0
  51. package/src/client/transport.ts +27 -5
  52. package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
  53. package/src/config/define-config.test.ts +6 -6
  54. package/src/config/index.ts +1 -1
  55. package/src/console/server/console.test.ts +45 -0
  56. package/src/console/server/flows.ts +39 -9
  57. package/src/console/server/i18n.ts +41 -0
  58. package/src/console/server/vault.ts +12 -38
  59. package/src/console/ui/dist/assets/index-ClX0ZCe5.js +10 -0
  60. package/src/console/ui/dist/assets/{panel-access-BGv45snf.js → panel-access-ri1X9Otj.js} +1 -1
  61. package/src/console/ui/dist/assets/{panel-ai-B2S7LEii.js → panel-ai-DLHjRoJk.js} +1 -1
  62. package/src/console/ui/dist/assets/{panel-architecture-D7UJh91v.js → panel-architecture-DI3bQF3J.js} +1 -1
  63. package/src/console/ui/dist/assets/{panel-channels-9T3ybqRu.js → panel-channels-BDYWX29p.js} +1 -1
  64. package/src/console/ui/dist/assets/{panel-clock-Cb1UXGRQ.js → panel-clock-i-JpTjVB.js} +1 -1
  65. package/src/console/ui/dist/assets/{panel-diff-DmYbKWmN.js → panel-diff-CFuWxiXy.js} +1 -1
  66. package/src/console/ui/dist/assets/{panel-flows-PiHwT55z.js → panel-flows-B8TRhcoe.js} +1 -1
  67. package/src/console/ui/dist/assets/{panel-gates-BQGYXvjT.js → panel-gates-CfkBgco7.js} +1 -1
  68. package/src/console/ui/dist/assets/{panel-overview-BBnRO18l.js → panel-overview-DONDzBd2.js} +1 -1
  69. package/src/console/ui/dist/assets/{panel-plugins-D0PsmVw2.js → panel-plugins-DDJwTehL.js} +1 -1
  70. package/src/console/ui/dist/assets/{panel-runs-CWuRDe0r.js → panel-runs-D5zf-D9c.js} +1 -1
  71. package/src/console/ui/dist/assets/{panel-signals-Bbg4ewpP.js → panel-signals-Dsxdu_AR.js} +1 -1
  72. package/src/console/ui/dist/assets/{panel-store-CPCbsDRa.js → panel-store-hy7O8HOs.js} +1 -1
  73. package/src/console/ui/dist/assets/{panel-traces-DVAzuA_S.js → panel-traces-CBiAe5go.js} +1 -1
  74. package/src/console/ui/dist/assets/{panel-vault-D1_MvOmo.js → panel-vault-Za1GyJfM.js} +1 -1
  75. package/src/console/ui/dist/index.html +1 -1
  76. package/src/console/ui/shell/components/ui.tsx +5 -1
  77. package/src/console/ui/shell/setup/Wizard.tsx +26 -5
  78. package/src/docker/cleanup.test.ts +193 -0
  79. package/src/docker/cleanup.ts +355 -0
  80. package/src/docker/docker.test.ts +4 -0
  81. package/src/docker/dockerfile.integration.test.ts +126 -119
  82. package/src/docker/index.ts +19 -0
  83. package/src/docker/recipes/ollama.ts +10 -5
  84. package/src/docker/stack.integration.test.ts +118 -102
  85. package/src/drivers/ai-ollama-tools.integration.test.ts +8 -6
  86. package/src/drivers/ai-ollama.integration.test.ts +3 -19
  87. package/src/drivers/ai-ollama.ts +45 -2
  88. package/src/drivers/ai-providers.test.ts +31 -0
  89. package/src/drivers/channel-fcm.ts +49 -53
  90. package/src/drivers/channel-msegat.ts +61 -0
  91. package/src/drivers/channel-sently-map.ts +57 -0
  92. package/src/drivers/channel-sently.test.ts +99 -0
  93. package/src/drivers/channel-sndr.ts +28 -0
  94. package/src/drivers/channel-taqnyat.ts +57 -0
  95. package/src/drivers/channel-types.ts +79 -2
  96. package/src/drivers/channel-unifonic.ts +26 -43
  97. package/src/drivers/channel-wa-cloud.ts +33 -47
  98. package/src/drivers/channel-webpush.ts +39 -239
  99. package/src/drivers/index.ts +7 -0
  100. package/src/drivers/signal-engine.ts +98 -25
  101. package/src/drivers/signal-nats.ts +4 -4
  102. package/src/drivers/signal-postgres.ts +158 -64
  103. package/src/drivers/signal-redis.ts +4 -4
  104. package/src/drivers/signal-types.ts +61 -2
  105. package/src/drivers/vault-driver-removal.test.ts +5 -1
  106. package/src/elements/channel/costs.test.ts +2 -2
  107. package/src/elements/channel/costs.ts +14 -2
  108. package/src/elements/channel/mime.ts +11 -0
  109. package/src/elements/channel/runtime.ts +94 -0
  110. package/src/elements/channel/sndr-webhooks.test.ts +26 -0
  111. package/src/elements/channel.ts +10 -1
  112. package/src/elements/clock/chaos-child.ts +150 -0
  113. package/src/elements/clock/chaos.test.ts +204 -0
  114. package/src/elements/clock/reconcile.ts +110 -0
  115. package/src/elements/clock/runtime.ts +11 -0
  116. package/src/elements/clock.test.ts +164 -2
  117. package/src/elements/clock.ts +1 -0
  118. package/src/elements/gate/runtime.ts +6 -0
  119. package/src/elements/index.ts +9 -0
  120. package/src/elements/signal/chaos-child.ts +41 -4
  121. package/src/elements/signal/declare.ts +4 -1
  122. package/src/elements/signal/delivery-modes.test.ts +179 -0
  123. package/src/elements/signal/key-ordering.test.ts +306 -0
  124. package/src/elements/signal/lease-reclaim.test.ts +123 -0
  125. package/src/elements/signal/optional-emit.test.ts +76 -0
  126. package/src/elements/signal/order-lifecycle.test.ts +130 -0
  127. package/src/elements/signal/orphan-messages.test.ts +152 -0
  128. package/src/elements/signal/runtime.ts +11 -4
  129. package/src/elements/signal/schema-emit.test.ts +107 -0
  130. package/src/elements/signal.test.ts +89 -5
  131. package/src/elements/store/files-fx.ts +104 -0
  132. package/src/elements/store/files-image.test.ts +251 -0
  133. package/src/elements/store/files-image.ts +494 -0
  134. package/src/elements/store/runtime.ts +60 -0
  135. package/src/elements/store.ts +24 -0
  136. package/src/elements/vault/boot-chain.ts +150 -0
  137. package/src/elements/vault/runtime.ts +8 -0
  138. package/src/kernel/app.ts +3 -1
  139. package/src/kernel/boot-bind/channel.test.ts +68 -3
  140. package/src/kernel/boot-bind/channel.ts +93 -2
  141. package/src/kernel/boot-bind/clock.ts +52 -7
  142. package/src/kernel/boot-bind/gate.ts +71 -3
  143. package/src/kernel/boot-bind/honor-config.test.ts +247 -0
  144. package/src/kernel/boot-bind/signal.ts +64 -7
  145. package/src/kernel/boot-bind/vault.ts +27 -8
  146. package/src/kernel/boot.ts +10 -2
  147. package/src/kernel/errors.ts +8 -2
  148. package/src/kernel/fx.test.ts +13 -0
  149. package/src/kernel/fx.ts +27 -4
  150. package/src/plugins/auth-delivery.mailpit.integration.test.ts +10 -4
  151. package/src/release/exports.test.ts +26 -0
  152. package/src/release/exports.ts +64 -5
  153. package/src/release/index.ts +5 -0
  154. package/src/release/measure.exports.test.ts +13 -1
  155. package/src/release/measure.ts +76 -13
  156. package/src/release/official-plugins.ts +46 -0
  157. package/src/release/readme.test.ts +30 -2
  158. package/src/runtime/dev-request-log.test.ts +20 -1
  159. package/src/runtime/dev-request-log.ts +38 -0
  160. package/src/term.test.ts +15 -0
  161. package/src/term.ts +8 -3
  162. package/src/console/ui/dist/assets/index-CjxwRGVv.js +0 -10
@@ -1 +1 @@
1
- import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,a,b as o,d as s,et as c,g as l,nt as u,o as d,r as f,tt as p,u as m,w as h,y as g}from"./panel-access-BGv45snf.js";import{r as _}from"./panel-runs-CWuRDe0r.js";import{n as v}from"./panel-channels-9T3ybqRu.js";var y=g({q:o().optional(),ref:o().optional(),child:o().optional(),tenant:o().optional(),view:l([`browse`,`cache`,`sql`,`probe`]).optional(),prefix:o().optional()});function b(e){let t=y.safeParse(e);return t.success?t.data:{}}function x(e){let t={};return e.q&&(t.q=e.q),e.ref&&(t.ref=e.ref),e.child&&(t.child=e.child),e.tenant&&(t.tenant=e.tenant),e.view&&e.view!==`browse`&&(t.view=e.view),e.prefix&&(t.prefix=e.prefix),t}function S(e,t){return{...e,ref:t,child:void 0,view:`browse`}}function C(e,t){return{...e,child:t,view:`browse`}}var w=[`sql`,`kv`,`files`,`index`],T={sql:`SQL`,kv:`KV`,files:`Files`,index:`Index`};function E(e,t=``){let n=t.trim().toLowerCase(),r=n?e.filter(e=>e.name.toLowerCase().includes(n)||e.ref.toLowerCase().includes(n)||e.children.some(e=>e.name.toLowerCase().includes(n))):e;return w.map(e=>({facet:e,label:T[e],stores:r.filter(t=>t.facet===e)})).filter(e=>e.stores.length>0)}function D(e={production:!0}){return e.production?{kind:`typed`,phrase:`EDIT`,requireReason:!0}:{kind:`undo`,windowMs:f}}function O(e={production:!0}){return e.production?{kind:`typed`,phrase:`DELETE`,requireReason:!0}:{kind:`undo`,windowMs:f}}function k(e={production:!0}){return e.production?{kind:`typed`,phrase:`PURGE`,requireReason:!0}:{kind:`undo`,windowMs:f}}function A(e){let t=[];for(let n of e.signals)t.push(`Signal \`${n}\` will not be emitted`);for(let n of e.channels)t.push(`Channel \`${n}\` will not fire`);return e.writerFlowIds.length>0&&t.push(`Owning flow(s): ${e.writerFlowIds.map(e=>`\`${e}\``).join(`, `)} — not executed`),{headline:`Direct edit is not a flow execution — the following will NOT happen:`,lines:t,empty:t.length===0}}function j(e){return e.facet===`index`?{ok:!1,reason:`Index facet has no bulk-update preview — similarity probe is read-only.`}:{ok:!0}}function ee(e){let t=e.cache,n=t.invalidatedByWrites,r=t.invalidatingFlowIds,i=n.length===0?`Read key \`${t.producedByRead}\` — no write invalidators declared.`:`Read key \`${t.producedByRead}\` — invalidated by writes to ${n.map(e=>`\`${e}\``).join(`, `)}.`;return{producedByRead:t.producedByRead,invalidatedBy:n,invalidatingFlows:r,summary:i}}var M=e(u(),1),N=p();function P(){let e=h({from:`/store`}),t=n({from:`/store`}),o=c(),[l,u]=(0,M.useState)(``),[d,f]=(0,M.useState)(``),[p,g]=(0,M.useState)(`{}`),[_,y]=(0,M.useState)(`SELECT * FROM "bookings" LIMIT 50`),[b,C]=(0,M.useState)(`0.1,0.2,0.3`),[w,T]=(0,M.useState)(null),P=e=>{t({search:x(e),replace:!0})},I=r({queryKey:[`console.store.list`],queryFn:async()=>{let e=await s.storeList();if(e.error)throw Error(e.error.code);return e.data},refetchInterval:1e4}),L=I.data?.tenancyDeclared??!1,te=I.data?.tenants??[],R=I.data?.stores??[],ne=(0,M.useMemo)(()=>E(R,e.q??``),[R,e.q]),z=R.find(t=>t.ref===e.ref),B=z?.children.find(t=>t.name===e.child)??z?.children[0],V=e.view??`browse`,H=D({production:!0}),U=O({production:!0}),W=k({production:!0}),G=z?j(z):null,re=B?A(B.willNotFire):null,ie=B?ee(B):null,K=r({queryKey:[`console.store.query`,e.ref,B?.name,e.tenant,e.prefix,V,b],enabled:!!z&&!!B&&V===`browse`&&(!L||!!e.tenant),queryFn:async()=>{if(!z||!B)return null;let t=z.facet===`index`?b.split(`,`).map(e=>Number(e.trim())).filter(e=>!Number.isNaN(e)):void 0,n=await s.storeQuery({ref:z.ref,child:B.name,tenant:e.tenant,prefix:e.prefix,vector:t,topK:5});if(n.error)throw Error(n.error.code);return n.data}});(0,M.useEffect)(()=>{u(``),f(``),T(null)},[z?.ref,B?.name]);let q=()=>{o.invalidateQueries({queryKey:[`console.store.list`]}),o.invalidateQueries({queryKey:[`console.store.query`]})},J=i({mutationFn:async()=>{if(!z||!B)return;if(G&&!G.ok)throw Error(G.reason);let t={};try{t=JSON.parse(p)}catch{throw Error(`Patch must be valid JSON`)}let n=await s.storePreview({ref:z.ref,child:B.name,tenant:e.tenant,id:String(t.id??`preview`),key:typeof t.key==`string`?t.key:void 0,patch:t});if(n.error)throw Error(n.error.code);let r=n.data;return T(A(r.willNotFire).lines),r}}),Y=i({mutationFn:async()=>{if(!z||!B)return;if(H.kind===`typed`){let e=a({typed:l,reason:d,phrase:H.phrase});if(e)throw Error(e.typed??e.reason)}let t={};try{t=JSON.parse(p)}catch{throw Error(`Patch must be valid JSON`)}let n=await s.storeEdit({ref:z.ref,child:B.name,tenant:e.tenant,id:String(t.id??``),key:typeof t.key==`string`?t.key:void 0,patch:t,confirmation:l,reason:d,commit:!0});if(n.error)throw Error(n.error.code);return n.data},onSuccess:q}),X=i({mutationFn:async t=>{if(!z||!B)return;if(U.kind===`typed`){let e=a({typed:l,reason:d,phrase:U.phrase});if(e)throw Error(e.typed??e.reason)}let n=await s.storeDelete({ref:z.ref,child:B.name,tenant:e.tenant,ids:z.facet===`sql`||z.facet===`index`?t:void 0,keys:z.facet===`kv`||z.facet===`files`?t:void 0,confirmation:l,reason:d});if(n.error)throw Error(n.error.code);return n.data},onSuccess:q}),Z=i({mutationFn:async()=>{if(!B)return;if(W.kind===`typed`){let e=a({typed:l,reason:d,phrase:W.phrase});if(e)throw Error(e.typed??e.reason)}let e=await s.storePurgeCache({resource:B.effectRef,confirmation:l,reason:d});if(e.error)throw Error(e.error.code);return e.data},onSuccess:q}),Q=i({mutationFn:async()=>{if(!z||z.facet!==`sql`)return;let t=await s.storeSql({ref:z.ref,sql:_,tenant:e.tenant,allowWrite:!1});if(t.error)throw Error(t.error.code);return t.data}}),$=i({mutationFn:async t=>{if(!z||!B)return;let n=await s.storeReveal({ref:z.ref,child:B.name,tenant:e.tenant,id:t.id,column:t.column});if(n.error)throw Error(n.error.code);return n.data}});return(0,N.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,N.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-3 border-b border-[var(--oke-line)] px-4 py-3`,children:[(0,N.jsxs)(`div`,{className:`mr-auto`,children:[(0,N.jsx)(`h1`,{className:`text-lg font-medium`,children:`Store`}),(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`One list, grouped by facet — direct edits are not flow executions`})]}),L?(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Tenant`}),(0,N.jsxs)(`select`,{"aria-label":`Tenant`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:e.tenant??``,onChange:t=>P({...e,tenant:t.target.value||void 0}),children:[(0,N.jsx)(`option`,{value:``,children:`Select tenant…`}),te.map(e=>(0,N.jsx)(`option`,{value:e,children:e},e))]})]}):null,(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter`}),(0,N.jsx)(`input`,{"aria-label":`Filter stores`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:e.q??``,onChange:t=>P({...e,q:t.target.value||void 0})})]})]}),(0,N.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,N.jsxs)(`section`,{"aria-label":`Store list`,className:`w-72 shrink-0 overflow-y-auto border-r border-[var(--oke-line)]`,children:[I.isLoading?(0,N.jsx)(`p`,{className:`p-3 text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,ne.map(t=>(0,N.jsxs)(`div`,{className:`border-b border-[var(--oke-line)]`,children:[(0,N.jsx)(`h2`,{className:`px-3 py-2 text-xs tracking-wide text-[var(--oke-muted)]`,children:t.label}),(0,N.jsx)(`ul`,{children:t.stores.map(t=>(0,N.jsx)(`li`,{children:(0,N.jsxs)(`button`,{type:`button`,"aria-pressed":t.ref===e.ref,className:m(`flex min-h-8 w-full flex-col items-start px-3 py-2 text-left text-sm`,t.ref===e.ref?`bg-[var(--oke-line)]/40`:`hover:bg-[var(--oke-line)]/20`),onClick:()=>P(S(e,t.ref)),children:[(0,N.jsx)(`span`,{children:v(t.name,t.description)}),t.description?(0,N.jsx)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:t.name}):null,(0,N.jsxs)(`span`,{className:`text-xs text-[var(--oke-muted)]`,children:[t.children.length,` resource(s)`,t.replicaLagMs==null?``:` · lag ${t.replicaLagMs}ms`,t.migrationDrift?.drifted?` · drift`:``,t.warnings.length>0?` · ${t.warnings.length} warn`:``]})]})},t.ref))})]},t.facet))]}),(0,N.jsx)(`section`,{"aria-label":`Store detail`,className:`min-w-0 flex-1 overflow-y-auto p-4`,"aria-live":`polite`,children:z?L&&!e.tenant?(0,N.jsx)(`p`,{role:`status`,className:`text-sm`,children:`Select a tenant in the header before browsing — compliance boundary, not a display filter.`}):(0,N.jsx)(F,{open:z,childName:B?.name,view:V,search:e,setSearch:P,browse:K.data,browseLoading:K.isLoading,cache:ie,willNot:re,willNotPreview:w,patchJson:p,setPatchJson:g,typed:l,setTyped:u,reason:d,setReason:f,sqlText:_,setSqlText:y,probeVector:b,setProbeVector:C,onPreview:()=>J.mutate(),onCommit:()=>Y.mutate(),onDelete:e=>X.mutate(e),onPurge:()=>Z.mutate(),onSql:()=>Q.mutate(),sqlResult:Q.data,onReveal:(e,t)=>$.mutate({id:e,column:t}),revealValue:$.data?.value,error:J.error?.message??Y.error?.message??X.error?.message??Z.error?.message??Q.error?.message??$.error?.message}):(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a store. Tenant selector appears only when tenancy is declared on the Manifest.`})})]})]})}function F(e){let{open:t,childName:n,view:r,search:i,setSearch:a,browse:o,browseLoading:s,cache:c,willNot:l,willNotPreview:u,patchJson:f,setPatchJson:p,typed:h,setTyped:g,reason:y,setReason:b,sqlText:x,setSqlText:S,probeVector:w,setProbeVector:T,onPreview:E,onCommit:D,onDelete:O,onPurge:k,onSql:A,sqlResult:j,onReveal:ee,revealValue:M,error:P}=e,F=t.children.find(e=>e.name===n);return(0,N.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,N.jsx)(`h2`,{className:`text-base font-medium`,children:v(t.name,t.description)}),(0,N.jsxs)(`span`,{className:`text-sm text-[var(--oke-muted)]`,children:[t.description?`${t.name} · `:``,t.ref]}),t.contentAddressed?(0,N.jsx)(`span`,{role:`status`,className:`text-xs text-[var(--oke-muted)]`,children:`content-addressed keys`}):null]}),(0,N.jsx)(`div`,{className:`flex flex-wrap gap-2`,role:`tablist`,"aria-label":`Views`,children:[[`browse`,`Browse`],[`cache`,`Cache`],...t.facet===`sql`?[[`sql`,`SQL`]]:[],...t.facet===`index`?[[`probe`,`Probe`]]:[]].map(([e,t])=>(0,N.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":r===e,className:m(`min-h-8 px-2 text-sm`,r===e?`text-[var(--oke-fg)] underline`:`text-[var(--oke-muted)]`),onClick:()=>a({...i,view:e}),children:t},e))}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Resource`}),(0,N.jsx)(`select`,{"aria-label":`Store resource`,className:`min-h-8 max-w-xs border border-[var(--oke-line)] bg-transparent px-2`,value:n??``,onChange:e=>a(C(i,e.target.value)),children:t.children.map(e=>(0,N.jsx)(`option`,{value:e.name,children:e.name},e.name))})]}),F?(0,N.jsxs)(`p`,{className:`text-sm`,role:`status`,children:[`Writers:`,` `,F.writers.map(e=>(0,N.jsx)(_,{to:`/flows`,search:{flow:e},className:`mr-2 underline`,children:e},e)),F.writers.length===0?`none`:null,` · `,`Readers: `,F.readers.join(`, `)||`none`,F.piiColumns.length>0?` · PII columns: ${F.piiColumns.join(`, `)}`:``]}):null,t.migrationDrift?(0,N.jsxs)(`p`,{className:`text-sm`,role:`status`,children:[`Migration: declared `,t.migrationDrift.declared.slice(0,12),`…`,t.migrationDrift.applied?` / applied ${t.migrationDrift.applied.slice(0,12)}…`:` / applied (none)`,t.migrationDrift.drifted?` — drifted`:` — in sync`]}):null,t.warnings.length>0?(0,N.jsx)(`ul`,{"aria-label":`Operational warnings`,className:`text-sm`,children:t.warnings.map(e=>(0,N.jsxs)(`li`,{role:`status`,children:[e.key,`: `,e.message]},`${e.key}:${e.code}`))}):null,r===`cache`&&c?(0,N.jsxs)(`section`,{"aria-label":`Cache`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`Cache`}),(0,N.jsx)(`p`,{className:`text-sm`,role:`status`,children:c.summary}),(0,N.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[`Invalidating flows: `,c.invalidatingFlows.join(`, `)||`none`]}),(0,N.jsx)(d,{type:`button`,onClick:k,children:`Purge cache namespace`})]}):null,r===`sql`&&t.facet===`sql`?(0,N.jsxs)(`section`,{"aria-label":`SQL console`,className:`flex flex-col gap-2`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`SQL console (read-only)`}),(0,N.jsx)(`textarea`,{"aria-label":`SQL console`,className:`min-h-24 border border-[var(--oke-line)] bg-transparent p-2 font-mono text-sm`,value:x,onChange:e=>S(e.target.value)}),(0,N.jsx)(d,{type:`button`,onClick:A,children:`Run`}),j?(0,N.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[j.rows.length,` row(s) · routed `,j.routedRole,j.masked?` · PII masked`:``]}):null]}):null,(r===`browse`||r===`probe`)&&(0,N.jsxs)(`section`,{"aria-label":`Browse`,children:[t.facet===`index`?(0,N.jsxs)(`label`,{className:`mb-2 flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{children:`Probe vector`}),(0,N.jsx)(`input`,{"aria-label":`Probe vector`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2 font-mono`,value:w,onChange:e=>T(e.target.value)})]}):null,s?(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,o?.rows?(0,N.jsxs)(`table`,{className:`w-full text-left text-sm`,children:[(0,N.jsx)(`thead`,{children:(0,N.jsxs)(`tr`,{children:[Object.keys(o.rows[0]??{id:1}).map(e=>(0,N.jsx)(`th`,{scope:`col`,className:`border-b px-2 py-1`,children:v(e,F?.columnDescriptions[e])},e)),(0,N.jsx)(`th`,{scope:`col`,className:`border-b px-2 py-1`,children:`Actions`})]})}),(0,N.jsx)(`tbody`,{children:o.rows.map((e,t)=>(0,N.jsxs)(`tr`,{children:[Object.entries(e).map(([t,n])=>(0,N.jsxs)(`td`,{className:`border-b px-2 py-1 font-mono`,children:[String(n),F?.piiColumns.includes(t)?(0,N.jsx)(`button`,{type:`button`,className:`ml-2 underline`,style:{minHeight:32},onClick:()=>ee(String(e.id??``),t),children:`Reveal`}):null]},t)),(0,N.jsx)(`td`,{className:`border-b px-2 py-1`,children:(0,N.jsx)(d,{type:`button`,onClick:()=>O([String(e.id??``)]),children:`Delete`})})]},t))})]}):null,o?.keys?(0,N.jsx)(`ul`,{"aria-label":`Keys`,className:`text-sm`,children:o.keys.map(e=>(0,N.jsxs)(`li`,{className:`flex min-h-8 items-center gap-2`,children:[(0,N.jsx)(`span`,{className:`font-mono`,children:e.key}),e.value===void 0?null:(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:JSON.stringify(e.value)}),e.warnings?.map(e=>(0,N.jsx)(`span`,{role:`status`,className:`text-xs`,children:e.message},e.code)),(0,N.jsx)(d,{type:`button`,onClick:()=>O([e.key]),children:`Delete`})]},e.key))}):null,o?.hits?(0,N.jsx)(`ul`,{"aria-label":`Similarity hits`,className:`text-sm`,children:o.hits.map(e=>(0,N.jsxs)(`li`,{children:[e.id,` · score `,e.score.toFixed(3)]},e.id))}):null,M===void 0?null:(0,N.jsxs)(`p`,{role:`status`,className:`text-sm`,children:[`Revealed: `,String(M)]})]}),(0,N.jsxs)(`section`,{"aria-label":`Direct edit`,className:`flex flex-col gap-2 border-t border-[var(--oke-line)] pt-4`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`Direct edit`}),(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Not a flow execution. Before saving, preview names what will not fire.`}),l&&!l.empty?(0,N.jsx)(`ul`,{className:`text-sm`,children:(u??l.lines).map(e=>(0,N.jsx)(`li`,{children:e},e))}):(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`No owning-flow emissions declared for this resource.`}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Patch (JSON)`,(0,N.jsx)(`textarea`,{"aria-label":`Edit patch JSON`,className:`min-h-20 border border-[var(--oke-line)] bg-transparent p-2 font-mono text-sm`,value:f,onChange:e=>p(e.target.value)})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Type EDIT / DELETE / PURGE`,(0,N.jsx)(`input`,{"aria-label":`Confirmation phrase`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:h,onChange:e=>g(e.target.value)})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Reason`,(0,N.jsx)(`input`,{"aria-label":`Confirmation reason`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:y,onChange:e=>b(e.target.value)})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsx)(d,{type:`button`,onClick:E,children:`Preview`}),(0,N.jsx)(d,{type:`button`,onClick:D,children:`Save edit`})]}),P?(0,N.jsx)(`p`,{role:`alert`,className:`text-sm text-red-600`,children:P}):null]})]})}var I=t({default:()=>P});export{b as n,I as t};
1
+ import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,a,b as o,d as s,et as c,g as l,nt as u,o as d,r as f,tt as p,u as m,w as h,y as g}from"./panel-access-ri1X9Otj.js";import{r as _}from"./panel-runs-D5zf-D9c.js";import{n as v}from"./panel-channels-BDYWX29p.js";var y=g({q:o().optional(),ref:o().optional(),child:o().optional(),tenant:o().optional(),view:l([`browse`,`cache`,`sql`,`probe`]).optional(),prefix:o().optional()});function b(e){let t=y.safeParse(e);return t.success?t.data:{}}function x(e){let t={};return e.q&&(t.q=e.q),e.ref&&(t.ref=e.ref),e.child&&(t.child=e.child),e.tenant&&(t.tenant=e.tenant),e.view&&e.view!==`browse`&&(t.view=e.view),e.prefix&&(t.prefix=e.prefix),t}function S(e,t){return{...e,ref:t,child:void 0,view:`browse`}}function C(e,t){return{...e,child:t,view:`browse`}}var w=[`sql`,`kv`,`files`,`index`],T={sql:`SQL`,kv:`KV`,files:`Files`,index:`Index`};function E(e,t=``){let n=t.trim().toLowerCase(),r=n?e.filter(e=>e.name.toLowerCase().includes(n)||e.ref.toLowerCase().includes(n)||e.children.some(e=>e.name.toLowerCase().includes(n))):e;return w.map(e=>({facet:e,label:T[e],stores:r.filter(t=>t.facet===e)})).filter(e=>e.stores.length>0)}function D(e={production:!0}){return e.production?{kind:`typed`,phrase:`EDIT`,requireReason:!0}:{kind:`undo`,windowMs:f}}function O(e={production:!0}){return e.production?{kind:`typed`,phrase:`DELETE`,requireReason:!0}:{kind:`undo`,windowMs:f}}function k(e={production:!0}){return e.production?{kind:`typed`,phrase:`PURGE`,requireReason:!0}:{kind:`undo`,windowMs:f}}function A(e){let t=[];for(let n of e.signals)t.push(`Signal \`${n}\` will not be emitted`);for(let n of e.channels)t.push(`Channel \`${n}\` will not fire`);return e.writerFlowIds.length>0&&t.push(`Owning flow(s): ${e.writerFlowIds.map(e=>`\`${e}\``).join(`, `)} — not executed`),{headline:`Direct edit is not a flow execution — the following will NOT happen:`,lines:t,empty:t.length===0}}function j(e){return e.facet===`index`?{ok:!1,reason:`Index facet has no bulk-update preview — similarity probe is read-only.`}:{ok:!0}}function ee(e){let t=e.cache,n=t.invalidatedByWrites,r=t.invalidatingFlowIds,i=n.length===0?`Read key \`${t.producedByRead}\` — no write invalidators declared.`:`Read key \`${t.producedByRead}\` — invalidated by writes to ${n.map(e=>`\`${e}\``).join(`, `)}.`;return{producedByRead:t.producedByRead,invalidatedBy:n,invalidatingFlows:r,summary:i}}var M=e(u(),1),N=p();function P(){let e=h({from:`/store`}),t=n({from:`/store`}),o=c(),[l,u]=(0,M.useState)(``),[d,f]=(0,M.useState)(``),[p,g]=(0,M.useState)(`{}`),[_,y]=(0,M.useState)(`SELECT * FROM "bookings" LIMIT 50`),[b,C]=(0,M.useState)(`0.1,0.2,0.3`),[w,T]=(0,M.useState)(null),P=e=>{t({search:x(e),replace:!0})},I=r({queryKey:[`console.store.list`],queryFn:async()=>{let e=await s.storeList();if(e.error)throw Error(e.error.code);return e.data},refetchInterval:1e4}),L=I.data?.tenancyDeclared??!1,te=I.data?.tenants??[],R=I.data?.stores??[],ne=(0,M.useMemo)(()=>E(R,e.q??``),[R,e.q]),z=R.find(t=>t.ref===e.ref),B=z?.children.find(t=>t.name===e.child)??z?.children[0],V=e.view??`browse`,H=D({production:!0}),U=O({production:!0}),W=k({production:!0}),G=z?j(z):null,re=B?A(B.willNotFire):null,ie=B?ee(B):null,K=r({queryKey:[`console.store.query`,e.ref,B?.name,e.tenant,e.prefix,V,b],enabled:!!z&&!!B&&V===`browse`&&(!L||!!e.tenant),queryFn:async()=>{if(!z||!B)return null;let t=z.facet===`index`?b.split(`,`).map(e=>Number(e.trim())).filter(e=>!Number.isNaN(e)):void 0,n=await s.storeQuery({ref:z.ref,child:B.name,tenant:e.tenant,prefix:e.prefix,vector:t,topK:5});if(n.error)throw Error(n.error.code);return n.data}});(0,M.useEffect)(()=>{u(``),f(``),T(null)},[z?.ref,B?.name]);let q=()=>{o.invalidateQueries({queryKey:[`console.store.list`]}),o.invalidateQueries({queryKey:[`console.store.query`]})},J=i({mutationFn:async()=>{if(!z||!B)return;if(G&&!G.ok)throw Error(G.reason);let t={};try{t=JSON.parse(p)}catch{throw Error(`Patch must be valid JSON`)}let n=await s.storePreview({ref:z.ref,child:B.name,tenant:e.tenant,id:String(t.id??`preview`),key:typeof t.key==`string`?t.key:void 0,patch:t});if(n.error)throw Error(n.error.code);let r=n.data;return T(A(r.willNotFire).lines),r}}),Y=i({mutationFn:async()=>{if(!z||!B)return;if(H.kind===`typed`){let e=a({typed:l,reason:d,phrase:H.phrase});if(e)throw Error(e.typed??e.reason)}let t={};try{t=JSON.parse(p)}catch{throw Error(`Patch must be valid JSON`)}let n=await s.storeEdit({ref:z.ref,child:B.name,tenant:e.tenant,id:String(t.id??``),key:typeof t.key==`string`?t.key:void 0,patch:t,confirmation:l,reason:d,commit:!0});if(n.error)throw Error(n.error.code);return n.data},onSuccess:q}),X=i({mutationFn:async t=>{if(!z||!B)return;if(U.kind===`typed`){let e=a({typed:l,reason:d,phrase:U.phrase});if(e)throw Error(e.typed??e.reason)}let n=await s.storeDelete({ref:z.ref,child:B.name,tenant:e.tenant,ids:z.facet===`sql`||z.facet===`index`?t:void 0,keys:z.facet===`kv`||z.facet===`files`?t:void 0,confirmation:l,reason:d});if(n.error)throw Error(n.error.code);return n.data},onSuccess:q}),Z=i({mutationFn:async()=>{if(!B)return;if(W.kind===`typed`){let e=a({typed:l,reason:d,phrase:W.phrase});if(e)throw Error(e.typed??e.reason)}let e=await s.storePurgeCache({resource:B.effectRef,confirmation:l,reason:d});if(e.error)throw Error(e.error.code);return e.data},onSuccess:q}),Q=i({mutationFn:async()=>{if(!z||z.facet!==`sql`)return;let t=await s.storeSql({ref:z.ref,sql:_,tenant:e.tenant,allowWrite:!1});if(t.error)throw Error(t.error.code);return t.data}}),$=i({mutationFn:async t=>{if(!z||!B)return;let n=await s.storeReveal({ref:z.ref,child:B.name,tenant:e.tenant,id:t.id,column:t.column});if(n.error)throw Error(n.error.code);return n.data}});return(0,N.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,N.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-3 border-b border-[var(--oke-line)] px-4 py-3`,children:[(0,N.jsxs)(`div`,{className:`mr-auto`,children:[(0,N.jsx)(`h1`,{className:`text-lg font-medium`,children:`Store`}),(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`One list, grouped by facet — direct edits are not flow executions`})]}),L?(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Tenant`}),(0,N.jsxs)(`select`,{"aria-label":`Tenant`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:e.tenant??``,onChange:t=>P({...e,tenant:t.target.value||void 0}),children:[(0,N.jsx)(`option`,{value:``,children:`Select tenant…`}),te.map(e=>(0,N.jsx)(`option`,{value:e,children:e},e))]})]}):null,(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter`}),(0,N.jsx)(`input`,{"aria-label":`Filter stores`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:e.q??``,onChange:t=>P({...e,q:t.target.value||void 0})})]})]}),(0,N.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,N.jsxs)(`section`,{"aria-label":`Store list`,className:`w-72 shrink-0 overflow-y-auto border-r border-[var(--oke-line)]`,children:[I.isLoading?(0,N.jsx)(`p`,{className:`p-3 text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,ne.map(t=>(0,N.jsxs)(`div`,{className:`border-b border-[var(--oke-line)]`,children:[(0,N.jsx)(`h2`,{className:`px-3 py-2 text-xs tracking-wide text-[var(--oke-muted)]`,children:t.label}),(0,N.jsx)(`ul`,{children:t.stores.map(t=>(0,N.jsx)(`li`,{children:(0,N.jsxs)(`button`,{type:`button`,"aria-pressed":t.ref===e.ref,className:m(`flex min-h-8 w-full flex-col items-start px-3 py-2 text-left text-sm`,t.ref===e.ref?`bg-[var(--oke-line)]/40`:`hover:bg-[var(--oke-line)]/20`),onClick:()=>P(S(e,t.ref)),children:[(0,N.jsx)(`span`,{children:v(t.name,t.description)}),t.description?(0,N.jsx)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:t.name}):null,(0,N.jsxs)(`span`,{className:`text-xs text-[var(--oke-muted)]`,children:[t.children.length,` resource(s)`,t.replicaLagMs==null?``:` · lag ${t.replicaLagMs}ms`,t.migrationDrift?.drifted?` · drift`:``,t.warnings.length>0?` · ${t.warnings.length} warn`:``]})]})},t.ref))})]},t.facet))]}),(0,N.jsx)(`section`,{"aria-label":`Store detail`,className:`min-w-0 flex-1 overflow-y-auto p-4`,"aria-live":`polite`,children:z?L&&!e.tenant?(0,N.jsx)(`p`,{role:`status`,className:`text-sm`,children:`Select a tenant in the header before browsing — compliance boundary, not a display filter.`}):(0,N.jsx)(F,{open:z,childName:B?.name,view:V,search:e,setSearch:P,browse:K.data,browseLoading:K.isLoading,cache:ie,willNot:re,willNotPreview:w,patchJson:p,setPatchJson:g,typed:l,setTyped:u,reason:d,setReason:f,sqlText:_,setSqlText:y,probeVector:b,setProbeVector:C,onPreview:()=>J.mutate(),onCommit:()=>Y.mutate(),onDelete:e=>X.mutate(e),onPurge:()=>Z.mutate(),onSql:()=>Q.mutate(),sqlResult:Q.data,onReveal:(e,t)=>$.mutate({id:e,column:t}),revealValue:$.data?.value,error:J.error?.message??Y.error?.message??X.error?.message??Z.error?.message??Q.error?.message??$.error?.message}):(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a store. Tenant selector appears only when tenancy is declared on the Manifest.`})})]})]})}function F(e){let{open:t,childName:n,view:r,search:i,setSearch:a,browse:o,browseLoading:s,cache:c,willNot:l,willNotPreview:u,patchJson:f,setPatchJson:p,typed:h,setTyped:g,reason:y,setReason:b,sqlText:x,setSqlText:S,probeVector:w,setProbeVector:T,onPreview:E,onCommit:D,onDelete:O,onPurge:k,onSql:A,sqlResult:j,onReveal:ee,revealValue:M,error:P}=e,F=t.children.find(e=>e.name===n);return(0,N.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,N.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-2`,children:[(0,N.jsx)(`h2`,{className:`text-base font-medium`,children:v(t.name,t.description)}),(0,N.jsxs)(`span`,{className:`text-sm text-[var(--oke-muted)]`,children:[t.description?`${t.name} · `:``,t.ref]}),t.contentAddressed?(0,N.jsx)(`span`,{role:`status`,className:`text-xs text-[var(--oke-muted)]`,children:`content-addressed keys`}):null]}),(0,N.jsx)(`div`,{className:`flex flex-wrap gap-2`,role:`tablist`,"aria-label":`Views`,children:[[`browse`,`Browse`],[`cache`,`Cache`],...t.facet===`sql`?[[`sql`,`SQL`]]:[],...t.facet===`index`?[[`probe`,`Probe`]]:[]].map(([e,t])=>(0,N.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":r===e,className:m(`min-h-8 px-2 text-sm`,r===e?`text-[var(--oke-fg)] underline`:`text-[var(--oke-muted)]`),onClick:()=>a({...i,view:e}),children:t},e))}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Resource`}),(0,N.jsx)(`select`,{"aria-label":`Store resource`,className:`min-h-8 max-w-xs border border-[var(--oke-line)] bg-transparent px-2`,value:n??``,onChange:e=>a(C(i,e.target.value)),children:t.children.map(e=>(0,N.jsx)(`option`,{value:e.name,children:e.name},e.name))})]}),F?(0,N.jsxs)(`p`,{className:`text-sm`,role:`status`,children:[`Writers:`,` `,F.writers.map(e=>(0,N.jsx)(_,{to:`/flows`,search:{flow:e},className:`mr-2 underline`,children:e},e)),F.writers.length===0?`none`:null,` · `,`Readers: `,F.readers.join(`, `)||`none`,F.piiColumns.length>0?` · PII columns: ${F.piiColumns.join(`, `)}`:``]}):null,t.migrationDrift?(0,N.jsxs)(`p`,{className:`text-sm`,role:`status`,children:[`Migration: declared `,t.migrationDrift.declared.slice(0,12),`…`,t.migrationDrift.applied?` / applied ${t.migrationDrift.applied.slice(0,12)}…`:` / applied (none)`,t.migrationDrift.drifted?` — drifted`:` — in sync`]}):null,t.warnings.length>0?(0,N.jsx)(`ul`,{"aria-label":`Operational warnings`,className:`text-sm`,children:t.warnings.map(e=>(0,N.jsxs)(`li`,{role:`status`,children:[e.key,`: `,e.message]},`${e.key}:${e.code}`))}):null,r===`cache`&&c?(0,N.jsxs)(`section`,{"aria-label":`Cache`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`Cache`}),(0,N.jsx)(`p`,{className:`text-sm`,role:`status`,children:c.summary}),(0,N.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[`Invalidating flows: `,c.invalidatingFlows.join(`, `)||`none`]}),(0,N.jsx)(d,{type:`button`,onClick:k,children:`Purge cache namespace`})]}):null,r===`sql`&&t.facet===`sql`?(0,N.jsxs)(`section`,{"aria-label":`SQL console`,className:`flex flex-col gap-2`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`SQL console (read-only)`}),(0,N.jsx)(`textarea`,{"aria-label":`SQL console`,className:`min-h-24 border border-[var(--oke-line)] bg-transparent p-2 font-mono text-sm`,value:x,onChange:e=>S(e.target.value)}),(0,N.jsx)(d,{type:`button`,onClick:A,children:`Run`}),j?(0,N.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[j.rows.length,` row(s) · routed `,j.routedRole,j.masked?` · PII masked`:``]}):null]}):null,(r===`browse`||r===`probe`)&&(0,N.jsxs)(`section`,{"aria-label":`Browse`,children:[t.facet===`index`?(0,N.jsxs)(`label`,{className:`mb-2 flex flex-col gap-1 text-sm`,children:[(0,N.jsx)(`span`,{children:`Probe vector`}),(0,N.jsx)(`input`,{"aria-label":`Probe vector`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2 font-mono`,value:w,onChange:e=>T(e.target.value)})]}):null,s?(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,o?.rows?(0,N.jsxs)(`table`,{className:`w-full text-left text-sm`,children:[(0,N.jsx)(`thead`,{children:(0,N.jsxs)(`tr`,{children:[Object.keys(o.rows[0]??{id:1}).map(e=>(0,N.jsx)(`th`,{scope:`col`,className:`border-b px-2 py-1`,children:v(e,F?.columnDescriptions[e])},e)),(0,N.jsx)(`th`,{scope:`col`,className:`border-b px-2 py-1`,children:`Actions`})]})}),(0,N.jsx)(`tbody`,{children:o.rows.map((e,t)=>(0,N.jsxs)(`tr`,{children:[Object.entries(e).map(([t,n])=>(0,N.jsxs)(`td`,{className:`border-b px-2 py-1 font-mono`,children:[String(n),F?.piiColumns.includes(t)?(0,N.jsx)(`button`,{type:`button`,className:`ml-2 underline`,style:{minHeight:32},onClick:()=>ee(String(e.id??``),t),children:`Reveal`}):null]},t)),(0,N.jsx)(`td`,{className:`border-b px-2 py-1`,children:(0,N.jsx)(d,{type:`button`,onClick:()=>O([String(e.id??``)]),children:`Delete`})})]},t))})]}):null,o?.keys?(0,N.jsx)(`ul`,{"aria-label":`Keys`,className:`text-sm`,children:o.keys.map(e=>(0,N.jsxs)(`li`,{className:`flex min-h-8 items-center gap-2`,children:[(0,N.jsx)(`span`,{className:`font-mono`,children:e.key}),e.value===void 0?null:(0,N.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:JSON.stringify(e.value)}),e.warnings?.map(e=>(0,N.jsx)(`span`,{role:`status`,className:`text-xs`,children:e.message},e.code)),(0,N.jsx)(d,{type:`button`,onClick:()=>O([e.key]),children:`Delete`})]},e.key))}):null,o?.hits?(0,N.jsx)(`ul`,{"aria-label":`Similarity hits`,className:`text-sm`,children:o.hits.map(e=>(0,N.jsxs)(`li`,{children:[e.id,` · score `,e.score.toFixed(3)]},e.id))}):null,M===void 0?null:(0,N.jsxs)(`p`,{role:`status`,className:`text-sm`,children:[`Revealed: `,String(M)]})]}),(0,N.jsxs)(`section`,{"aria-label":`Direct edit`,className:`flex flex-col gap-2 border-t border-[var(--oke-line)] pt-4`,children:[(0,N.jsx)(`h3`,{className:`text-sm font-medium`,children:`Direct edit`}),(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Not a flow execution. Before saving, preview names what will not fire.`}),l&&!l.empty?(0,N.jsx)(`ul`,{className:`text-sm`,children:(u??l.lines).map(e=>(0,N.jsx)(`li`,{children:e},e))}):(0,N.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`No owning-flow emissions declared for this resource.`}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Patch (JSON)`,(0,N.jsx)(`textarea`,{"aria-label":`Edit patch JSON`,className:`min-h-20 border border-[var(--oke-line)] bg-transparent p-2 font-mono text-sm`,value:f,onChange:e=>p(e.target.value)})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Type EDIT / DELETE / PURGE`,(0,N.jsx)(`input`,{"aria-label":`Confirmation phrase`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:h,onChange:e=>g(e.target.value)})]}),(0,N.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[`Reason`,(0,N.jsx)(`input`,{"aria-label":`Confirmation reason`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2`,value:y,onChange:e=>b(e.target.value)})]}),(0,N.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,N.jsx)(d,{type:`button`,onClick:E,children:`Preview`}),(0,N.jsx)(d,{type:`button`,onClick:D,children:`Save edit`})]}),P?(0,N.jsx)(`p`,{role:`alert`,className:`text-sm text-red-600`,children:P}):null]})]})}var I=t({default:()=>P});export{b as n,I as t};
@@ -1 +1 @@
1
- import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,b as a,d as o,et as s,l as c,nt as l,o as u,tt as d,u as f,w as p,y as m}from"./panel-access-BGv45snf.js";import{r as h}from"./panel-runs-CWuRDe0r.js";import{n as g,t as _}from"./panel-flows-PiHwT55z.js";var v=e(l(),1);function y(e,t){if(!t)return!0;switch(t.kind){case`wrote`:return e.effects.some(e=>e.kind===`write`&&e.resource===t.resource);case`asked`:return e.effects.some(e=>e.kind===`ask`);case`sent`:return e.effects.some(e=>e.kind===`send`&&(t.resource===void 0||e.resource===t.resource));case`secret`:return e.effects.some(e=>e.kind===`secret`&&(t.resource===void 0||e.resource===t.resource));case`cost`:return(e.cost??0)>t.min}}function b(e,t){return!t||e.some(e=>y(e,t))}function x(e){if(!e?.trim())return null;let t=e.trim();if(t===`asked`)return{kind:`asked`};if(t===`sent`)return{kind:`sent`};if(t.startsWith(`wrote:`))return{kind:`wrote`,resource:t.slice(6)};if(t.startsWith(`sent:`))return{kind:`sent`,resource:t.slice(5)};if(t.startsWith(`secret:`))return{kind:`secret`,resource:t.slice(7)};if(t===`secret`)return{kind:`secret`};if(t.startsWith(`cost:`)){let e=Number(t.slice(5));return Number.isFinite(e)?{kind:`cost`,min:e}:null}return null}function S(e){if(e)switch(e.kind){case`wrote`:return`wrote:${e.resource}`;case`asked`:return`asked`;case`sent`:return e.resource?`sent:${e.resource}`:`sent`;case`secret`:return e.resource?`secret:${e.resource}`:`secret`;case`cost`:return`cost:${e.min}`}}var C=m({trace:a().optional(),span:a().optional(),effect:a().optional(),q:a().optional(),folds:a().optional(),boost:a().optional()});function w(e){let t=C.safeParse(e??{});return t.success?t.data:C.parse({})}function T(e){let t={};return e.trace&&(t.trace=e.trace),e.span&&(t.span=e.span),e.effect&&(t.effect=e.effect),e.q&&(t.q=e.q),e.folds&&(t.folds=e.folds),e.boost&&(t.boost=e.boost),t}function E(e){return e.folds?new Set(e.folds.split(`,`).map(e=>e.trim()).filter(Boolean)):new Set}function D(e,t,n){return{...e,trace:t,span:n}}function ee(e){return{...e,trace:void 0,span:void 0,folds:void 0}}function te(e,t){let n=E(e);n.has(t)?n.delete(t):n.add(t);let r=[...n].join(`,`);return{...e,folds:r||void 0}}function O(e,t){return{...e,effect:S(t)}}function k(e){let t=new Map,n=new Map;for(let n of e)t.set(n.id,n);for(let t of e){if(!t.parentId)continue;let e=n.get(t.parentId)??[];e.push(t),n.set(t.parentId,e)}for(let[,e]of n)e.sort((e,t)=>e.startedAt-t.startedAt);return{byId:t,childrenOf:n}}function A(e,t){let{byId:n,childrenOf:r}=k(e),i=n.get(t);if(!i)return null;let a=[],o=i,s=new Set;for(;o?.parentId&&!s.has(o.parentId);){s.add(o.parentId);let e=n.get(o.parentId);if(!e)break;a.unshift(e),o=e}return{parents:a,current:i,children:r.get(i.id)??[],connected:N((a[0]??i).id,n,r)}}function j(e){let{byId:t,childrenOf:n}=k(e),r=e.filter(e=>!e.parentId||!t.has(e.parentId));return r.sort((e,t)=>t.startedAt-e.startedAt),r.map(e=>({rootId:e.id,root:e,spans:N(e.id,t,n)}))}function M(e,t){if(t&&e.some(e=>e.id===t))return t;let n=e.find(e=>e.errorCode!=null&&e.errorCode!==``);return n?n.id:e.find(t=>!t.parentId||!e.some(e=>e.id===t.parentId))?.id??e[0]?.id}function N(e,t,n){let r=[],i=e=>{let a=t.get(e);if(a){r.push(a);for(let t of n.get(e)??[])i(t.id)}};return i(e),r.sort((e,t)=>e.startedAt-t.startedAt),r}function P(e){if(e.length===0)return new Set;let{byId:t,childrenOf:n}=k(e),r=e.filter(e=>!e.parentId||!t.has(e.parentId)),i=[],a=-1,o=(e,r,s)=>{let c=n.get(e)??[],l=t.get(e);if(!l)return;let u=s+F(l),d=[...r,e];if(c.length===0){u>a&&(a=u,i=d);return}for(let e of c)o(e.id,d,u)};for(let e of r)o(e.id,[],0);return new Set(i)}function F(e){return e.effects.length===0?Math.max(0,e.durationMs):e.effects.reduce((e,t)=>e+Math.max(0,t.duration),0)}function I(e){switch(e){case`read`:return`reads`;case`write`:return`writes`;case`emit`:return`emits`;case`send`:case`ask`:return`external`;case`secret`:return`capabilities`;case`call`:return`reads`}}function L(e){let t=`none`;for(let n of e){let e=I(n.kind);z(e)>z(t)&&(t=e)}return t}function R(e){return e.some(e=>L(e.effects)===`external`)}function z(e){switch(e){case`external`:return 5;case`capabilities`:return 4;case`emits`:return 3;case`writes`:return 2;case`reads`:return 1;case`none`:return 0}}function B(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms idle`;let n=t/1e3;if(n<60)return`${U(n)}s idle`;let r=n/60;if(r<60)return`${U(r)}m idle`;let i=r/60;return i<48?`${U(i)}h idle`:`${U(i/24)}d idle`}function V(e,t={},n=new Set){let r=t.foldThresholdMs??50,i=t.expandedFolds??new Set,a=[...e].sort((e,t)=>e.startMs-t.startMs);if(a.length===0)return{segments:[],displayDurationMs:0,wallDurationMs:0};let o=a[0],s=a[a.length-1];if(!o||!s)return{segments:[],displayDurationMs:0,wallDurationMs:0};let c=o.startMs,l=Math.max(...a.map(e=>e.endMs)),u=[],d=c;for(let e of a){let t=e.startMs-d;if(t>=r){let n=`fold:${d}:${e.startMs}`,r=i.has(n),a=t;u.push({kind:`fold`,id:n,startMs:d,endMs:e.startMs,durationMs:a,label:B(a),expanded:r,displayMs:r?a:40})}let a=Math.max(0,e.endMs-e.startMs);u.push({kind:`work`,id:e.id,label:e.label,startMs:e.startMs,endMs:e.endMs,durationMs:a,tier:e.tier,spanId:e.spanId,critical:n.has(e.spanId),failed:e.failed===!0,displayMs:Math.max(1,a)}),d=Math.max(d,e.endMs)}let f=u.reduce((e,t)=>e+t.displayMs,0);return{segments:u,displayDurationMs:Math.max(1,f),wallDurationMs:l-c}}function H(e){let t=[];for(let n of e)if(n.effects.length>0)for(let e of n.effects)t.push({id:`${n.id}:${e.kind}:${e.resource}:${e.timestamp}`,label:`${e.kind} ${e.resource}`,startMs:e.timestamp,endMs:e.timestamp+Math.max(1,e.duration),tier:I(e.kind),spanId:n.id,failed:n.errorCode!=null&&e===n.effects[n.effects.length-1]});else t.push({id:n.id,label:n.flow,startMs:n.startedAt,endMs:n.endedAt,tier:`none`,spanId:n.id,failed:n.errorCode!=null});return t}function U(e){let t=Math.round(e*10)/10;return Number.isInteger(t)?String(t):t.toFixed(1)}function W(e){if(e.length===0)return[];let t=Math.min(...e.map(e=>e.startedAt)),n=Math.max(...e.map(e=>e.endedAt)),r=Math.max(1,n-t);if(e.every(e=>e.effects.length===0))return e.map(e=>({start:(e.startedAt-t)/r,width:Math.max(.02,e.durationMs/r),tier:L(e.effects),failed:e.errorCode!=null}));let i=[];for(let n of e){if(n.effects.length===0){i.push({start:(n.startedAt-t)/r,width:Math.max(.02,n.durationMs/r),tier:`none`,failed:n.errorCode!=null});continue}for(let e=0;e<n.effects.length;e++){let a=n.effects[e];a&&i.push({start:(a.timestamp-t)/r,width:Math.max(.02,a.duration/r),tier:I(a.kind),failed:n.errorCode!=null&&e===n.effects.length-1})}}return i}function G(e){for(let t of e)if(t.errorCode)return t.errorCode;return null}function K(e){return R(e)?{mode:`dry-run`,reason:`This trace contains an external effect. Replay runs as a dry run with external effects stubbed.`}:{mode:`replay`}}var q=`10% + all errors`,J=6e5;function Y(e,t=Date.now()){let n=e.filter(e=>e.until>t);return n.length===0?q:`${q} · full: ${n.map(e=>e.flow).join(`, `)}`}function X(e,t,n=Date.now()){let r=n+J;return[...e.filter(e=>e.flow!==t&&e.until>n),{flow:t,until:r}]}function ne(e,t=Date.now()){return e.filter(e=>e.until>t)}var Z=d();function Q(){let e=p({from:`/traces`}),t=n({from:`/traces`}),a=s(),[l,d]=(0,v.useState)([]),[m]=(0,v.useState)(()=>_()),[y,S]=(0,v.useState)(0),[,C]=(0,v.useState)(0),w=e=>{t({search:T(e),replace:!0})},k=r({queryKey:[`console.runs.list`],queryFn:async()=>{let e=await o.runsList();if(e.error)throw Error(e.error.code);return e.data.runs},refetchInterval:5e3}),N=(0,v.useMemo)(()=>(k.data??[]).map(re),[k.data]);(0,v.useEffect)(()=>{if(N.length===0)return;if(m.visible.length===0){for(let e of N)m.offer({id:e.id,value:e,arrivedAt:e.startedAt});m.flush(),S(0),C(e=>e+1);return}let e=new Set(m.visible.map(e=>e.id));for(let t of m.pending)e.add(t.id);for(let t of N)e.has(t.id)?m.updateInPlace(t.id,t):m.offer({id:t.id,value:t,arrivedAt:Date.now()});S(m.pendingCount),C(e=>e+1)},[N,m]);let F=m.visible.map(e=>e.value),I=x(e.effect),R=(0,v.useMemo)(()=>j(F).filter(t=>{let n=g([t.root.flow,t.root.id,G(t.spans)??``],e.q),r=b(t.spans,I);return n&&r}),[F,e.q,I]),z=R.find(t=>t.rootId===e.trace)??(e.trace?j(F).find(t=>t.rootId===e.trace):void 0),B=z?M(z.spans,e.span):void 0,U=B?A(F,B):null,q=U?P(U.connected):new Set,J=U?V(H(U.connected),{expandedFolds:E(e)},q):null,Q=U?K(U.connected):null,$=i({mutationFn:async()=>{if(!U||!Q)return;let e=await o.tracesReplay({rootId:U.connected[0]?.id??U.current.id,dryRun:Q.mode===`dry-run`});if(e.error)throw Error(e.error.code);return e.data},onSuccess:()=>{a.invalidateQueries({queryKey:[`console.runs.list`]})}}),ae=ne(l);return(0,Z.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,Z.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-4 border-b border-[var(--oke-line)] px-6 py-4`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,Z.jsx)(`p`,{className:`text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]`,children:`Traces`}),(0,Z.jsx)(`h1`,{className:`text-xl font-semibold tracking-tight`,children:`Causal chain`}),(0,Z.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[`Sampling: `,Y(ae)]})]}),(0,Z.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,Z.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter by effect`}),(0,Z.jsxs)(`select`,{"aria-label":`Filter by effect`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2 text-sm`,value:e.effect??``,onChange:t=>{let n=t.target.value;w(O(e,n?x(n):null))},children:[(0,Z.jsx)(`option`,{value:``,children:`All effects`}),(0,Z.jsx)(`option`,{value:`wrote:sql:bookings`,children:`Wrote sql:bookings`}),(0,Z.jsx)(`option`,{value:`sent`,children:`Sent (channel)`}),(0,Z.jsx)(`option`,{value:`asked`,children:`Asked a model`}),(0,Z.jsx)(`option`,{value:`secret`,children:`Read a secret`}),(0,Z.jsx)(`option`,{value:`cost:0.05`,children:`Cost > $0.05`})]})]}),(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Z.jsx)(u,{type:`button`,variant:`ghost`,onClick:()=>{let e=z?.root.flow??R[0]?.root.flow??`bookings.create`;d(t=>X(t,e))},children:`Trace flow fully for 10 minutes`}),(0,Z.jsx)(c,{count:y,onFlush:()=>{m.flush(),S(0),C(e=>e+1)}})]})]}),(0,Z.jsxs)(`div`,{className:`grid min-h-0 flex-1 grid-cols-1 md:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[(0,Z.jsx)(`section`,{"aria-label":`Trace list`,className:`min-h-0 overflow-auto border-r border-[var(--oke-line)]`,children:k.isLoading?(0,Z.jsx)(`p`,{className:`px-6 py-8 text-sm text-[var(--oke-muted)]`,children:`Loading traces…`}):R.length===0?(0,Z.jsx)(`p`,{className:`px-6 py-8 text-sm text-[var(--oke-muted)]`,children:`No traces yet. Invoke a flow or wait for traffic.`}):(0,Z.jsx)(`ul`,{className:`divide-y divide-[var(--oke-line)]`,children:R.map(t=>{let n=G(t.spans),r=W(t.spans),i=t.rootId===e.trace;return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,"aria-pressed":i,className:f(`flex w-full min-h-10 flex-col gap-1 px-4 py-3 text-left text-sm`,i?`bg-[color-mix(in_oklab,var(--oke-fg)_6%,transparent)]`:`hover:bg-[color-mix(in_oklab,var(--oke-fg)_3%,transparent)]`),onClick:()=>{let n=M(t.spans);w(D(e,t.rootId,n))},children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,Z.jsx)(`span`,{className:`font-medium`,children:t.root.flow}),n?(0,Z.jsx)(`span`,{role:`status`,className:`font-mono text-xs text-[var(--oke-danger)]`,children:n}):(0,Z.jsxs)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:[t.root.durationMs,`ms`]})]}),(0,Z.jsx)(ie,{bars:r})]})},t.rootId)})})}),(0,Z.jsx)(`section`,{"aria-label":`Trace detail`,className:`min-h-0 overflow-auto px-6 py-6`,"aria-live":`polite`,children:!U||!J?(0,Z.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a trace to see the causal chain and folded-time waterfall.`}):(0,Z.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h2`,{className:`text-lg font-semibold`,children:U.current.flow}),(0,Z.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[U.connected.length,` span`,U.connected.length===1?``:`s`,` · wall `,J.wallDurationMs,`ms · display scale `,Math.round(J.displayDurationMs),`ms`]})]}),(0,Z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,Z.jsx)(h,{to:`/runs`,search:{run:U.current.id},className:`inline-flex min-h-8 items-center border border-[var(--oke-line)] px-3 text-sm`,children:`Open in Runs`}),(0,Z.jsx)(u,{type:`button`,variant:Q?.mode===`dry-run`?`external`:`primary`,disabled:$.isPending,title:Q?.mode===`dry-run`?Q.reason:`Replay from the journal`,onClick:()=>$.mutate(),children:Q?.mode===`dry-run`?`Dry-run replay`:`Replay`}),(0,Z.jsx)(u,{type:`button`,variant:`ghost`,onClick:()=>w(ee(e)),children:`Close`})]})]}),Q?.mode===`dry-run`?(0,Z.jsx)(`p`,{role:`note`,className:`text-sm text-[var(--oke-external)]`,children:Q.reason}):null,(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Causal chain`}),(0,Z.jsxs)(`ol`,{className:`flex flex-col gap-1 border-l border-[var(--oke-line)] pl-4`,children:[U.parents.map(t=>(0,Z.jsx)(`li`,{children:(0,Z.jsx)(`button`,{type:`button`,className:`min-h-8 text-sm text-[var(--oke-muted)]`,onClick:()=>w({...e,span:t.id}),children:t.flow})},t.id)),(0,Z.jsxs)(`li`,{"aria-current":`true`,children:[(0,Z.jsx)(`span`,{className:`text-sm font-medium`,children:U.current.flow}),U.current.errorCode?(0,Z.jsx)(`span`,{role:`status`,className:`ml-2 font-mono text-xs text-[var(--oke-danger)]`,children:U.current.errorCode}):null,L(U.current.effects)===`external`?(0,Z.jsx)(`span`,{"aria-label":`external effect`,children:` ↗`}):null]}),U.children.map(t=>(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,className:`min-h-8 text-sm text-[var(--oke-muted)]`,onClick:()=>w({...e,span:t.id}),children:[t.flow,L(t.effects)===`external`?(0,Z.jsx)(`span`,{"aria-label":`external effect`,children:` ↗`}):null]})},t.id))]})]}),(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h3`,{id:`waterfall-heading`,className:`mb-2 text-sm font-medium`,children:`Waterfall`}),(0,Z.jsx)(`ul`,{"aria-labelledby":`waterfall-heading`,className:`flex min-h-10 list-none items-stretch gap-0.5 p-0`,children:J.segments.map(t=>t.kind===`fold`?(0,Z.jsx)(`li`,{style:{flex:`${t.displayMs} 1 0`,minWidth:24},children:(0,Z.jsx)(`button`,{type:`button`,"aria-expanded":t.expanded,className:`h-full min-h-10 w-full border border-dashed border-[var(--oke-line)] px-1 font-mono text-[10px] text-[var(--oke-muted)]`,onClick:()=>w(te(e,t.id)),children:t.label})},t.id):(0,Z.jsx)(`li`,{title:t.label,className:f(`min-h-10 px-1 text-[10px] leading-10`,t.tier===`external`?`bg-[var(--oke-external)] text-black`:`bg-[color-mix(in_oklab,var(--oke-accent)_55%,transparent)]`,t.failed&&`outline outline-2 outline-[var(--oke-danger)]`),style:{flex:`${t.displayMs} 1 0`,opacity:t.critical?1:.38,minWidth:4},children:(0,Z.jsxs)(`span`,{className:`sr-only`,children:[t.label,t.critical?` (critical path)`:``,t.failed?` (failed)`:``]})},t.id))}),(0,Z.jsx)(`p`,{className:`mt-2 text-xs text-[var(--oke-muted)]`,children:`Critical path at full opacity · dead time folded into expandable bars`})]})]})})]})]})}function re(e){return{id:e.id,...e.parentId?{parentId:e.parentId}:{},flow:e.flow,...e.unit?{unit:e.unit}:{},trigger:e.trigger,startedAt:e.startedAt,endedAt:e.endedAt,durationMs:e.durationMs,errorCode:e.error,cost:e.cost??void 0,sampled:e.sampled??(e.error?`error`:`sample`),effects:e.effects??[]}}function ie({bars:e}){return(0,Z.jsx)(`div`,{"aria-hidden":`true`,className:`relative h-2 w-full overflow-hidden bg-[color-mix(in_oklab,var(--oke-fg)_6%,transparent)]`,children:e.map((e,t)=>(0,Z.jsx)(`span`,{className:f(`absolute inset-y-0`,e.tier===`external`?`bg-[var(--oke-external)]`:e.failed?`bg-[var(--oke-danger)]`:`bg-[var(--oke-accent)]`),style:{left:`${e.start*100}%`,width:`${Math.max(2,e.width*100)}%`}},t))})}var $=t({default:()=>Q});export{w as n,$ as t};
1
+ import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,b as a,d as o,et as s,l as c,nt as l,o as u,tt as d,u as f,w as p,y as m}from"./panel-access-ri1X9Otj.js";import{r as h}from"./panel-runs-D5zf-D9c.js";import{n as g,t as _}from"./panel-flows-B8TRhcoe.js";var v=e(l(),1);function y(e,t){if(!t)return!0;switch(t.kind){case`wrote`:return e.effects.some(e=>e.kind===`write`&&e.resource===t.resource);case`asked`:return e.effects.some(e=>e.kind===`ask`);case`sent`:return e.effects.some(e=>e.kind===`send`&&(t.resource===void 0||e.resource===t.resource));case`secret`:return e.effects.some(e=>e.kind===`secret`&&(t.resource===void 0||e.resource===t.resource));case`cost`:return(e.cost??0)>t.min}}function b(e,t){return!t||e.some(e=>y(e,t))}function x(e){if(!e?.trim())return null;let t=e.trim();if(t===`asked`)return{kind:`asked`};if(t===`sent`)return{kind:`sent`};if(t.startsWith(`wrote:`))return{kind:`wrote`,resource:t.slice(6)};if(t.startsWith(`sent:`))return{kind:`sent`,resource:t.slice(5)};if(t.startsWith(`secret:`))return{kind:`secret`,resource:t.slice(7)};if(t===`secret`)return{kind:`secret`};if(t.startsWith(`cost:`)){let e=Number(t.slice(5));return Number.isFinite(e)?{kind:`cost`,min:e}:null}return null}function S(e){if(e)switch(e.kind){case`wrote`:return`wrote:${e.resource}`;case`asked`:return`asked`;case`sent`:return e.resource?`sent:${e.resource}`:`sent`;case`secret`:return e.resource?`secret:${e.resource}`:`secret`;case`cost`:return`cost:${e.min}`}}var C=m({trace:a().optional(),span:a().optional(),effect:a().optional(),q:a().optional(),folds:a().optional(),boost:a().optional()});function w(e){let t=C.safeParse(e??{});return t.success?t.data:C.parse({})}function T(e){let t={};return e.trace&&(t.trace=e.trace),e.span&&(t.span=e.span),e.effect&&(t.effect=e.effect),e.q&&(t.q=e.q),e.folds&&(t.folds=e.folds),e.boost&&(t.boost=e.boost),t}function E(e){return e.folds?new Set(e.folds.split(`,`).map(e=>e.trim()).filter(Boolean)):new Set}function D(e,t,n){return{...e,trace:t,span:n}}function ee(e){return{...e,trace:void 0,span:void 0,folds:void 0}}function te(e,t){let n=E(e);n.has(t)?n.delete(t):n.add(t);let r=[...n].join(`,`);return{...e,folds:r||void 0}}function O(e,t){return{...e,effect:S(t)}}function k(e){let t=new Map,n=new Map;for(let n of e)t.set(n.id,n);for(let t of e){if(!t.parentId)continue;let e=n.get(t.parentId)??[];e.push(t),n.set(t.parentId,e)}for(let[,e]of n)e.sort((e,t)=>e.startedAt-t.startedAt);return{byId:t,childrenOf:n}}function A(e,t){let{byId:n,childrenOf:r}=k(e),i=n.get(t);if(!i)return null;let a=[],o=i,s=new Set;for(;o?.parentId&&!s.has(o.parentId);){s.add(o.parentId);let e=n.get(o.parentId);if(!e)break;a.unshift(e),o=e}return{parents:a,current:i,children:r.get(i.id)??[],connected:N((a[0]??i).id,n,r)}}function j(e){let{byId:t,childrenOf:n}=k(e),r=e.filter(e=>!e.parentId||!t.has(e.parentId));return r.sort((e,t)=>t.startedAt-e.startedAt),r.map(e=>({rootId:e.id,root:e,spans:N(e.id,t,n)}))}function M(e,t){if(t&&e.some(e=>e.id===t))return t;let n=e.find(e=>e.errorCode!=null&&e.errorCode!==``);return n?n.id:e.find(t=>!t.parentId||!e.some(e=>e.id===t.parentId))?.id??e[0]?.id}function N(e,t,n){let r=[],i=e=>{let a=t.get(e);if(a){r.push(a);for(let t of n.get(e)??[])i(t.id)}};return i(e),r.sort((e,t)=>e.startedAt-t.startedAt),r}function P(e){if(e.length===0)return new Set;let{byId:t,childrenOf:n}=k(e),r=e.filter(e=>!e.parentId||!t.has(e.parentId)),i=[],a=-1,o=(e,r,s)=>{let c=n.get(e)??[],l=t.get(e);if(!l)return;let u=s+F(l),d=[...r,e];if(c.length===0){u>a&&(a=u,i=d);return}for(let e of c)o(e.id,d,u)};for(let e of r)o(e.id,[],0);return new Set(i)}function F(e){return e.effects.length===0?Math.max(0,e.durationMs):e.effects.reduce((e,t)=>e+Math.max(0,t.duration),0)}function I(e){switch(e){case`read`:return`reads`;case`write`:return`writes`;case`emit`:return`emits`;case`send`:case`ask`:return`external`;case`secret`:return`capabilities`;case`call`:return`reads`}}function L(e){let t=`none`;for(let n of e){let e=I(n.kind);z(e)>z(t)&&(t=e)}return t}function R(e){return e.some(e=>L(e.effects)===`external`)}function z(e){switch(e){case`external`:return 5;case`capabilities`:return 4;case`emits`:return 3;case`writes`:return 2;case`reads`:return 1;case`none`:return 0}}function B(e){let t=Math.max(0,Math.round(e));if(t<1e3)return`${t}ms idle`;let n=t/1e3;if(n<60)return`${U(n)}s idle`;let r=n/60;if(r<60)return`${U(r)}m idle`;let i=r/60;return i<48?`${U(i)}h idle`:`${U(i/24)}d idle`}function V(e,t={},n=new Set){let r=t.foldThresholdMs??50,i=t.expandedFolds??new Set,a=[...e].sort((e,t)=>e.startMs-t.startMs);if(a.length===0)return{segments:[],displayDurationMs:0,wallDurationMs:0};let o=a[0],s=a[a.length-1];if(!o||!s)return{segments:[],displayDurationMs:0,wallDurationMs:0};let c=o.startMs,l=Math.max(...a.map(e=>e.endMs)),u=[],d=c;for(let e of a){let t=e.startMs-d;if(t>=r){let n=`fold:${d}:${e.startMs}`,r=i.has(n),a=t;u.push({kind:`fold`,id:n,startMs:d,endMs:e.startMs,durationMs:a,label:B(a),expanded:r,displayMs:r?a:40})}let a=Math.max(0,e.endMs-e.startMs);u.push({kind:`work`,id:e.id,label:e.label,startMs:e.startMs,endMs:e.endMs,durationMs:a,tier:e.tier,spanId:e.spanId,critical:n.has(e.spanId),failed:e.failed===!0,displayMs:Math.max(1,a)}),d=Math.max(d,e.endMs)}let f=u.reduce((e,t)=>e+t.displayMs,0);return{segments:u,displayDurationMs:Math.max(1,f),wallDurationMs:l-c}}function H(e){let t=[];for(let n of e)if(n.effects.length>0)for(let e of n.effects)t.push({id:`${n.id}:${e.kind}:${e.resource}:${e.timestamp}`,label:`${e.kind} ${e.resource}`,startMs:e.timestamp,endMs:e.timestamp+Math.max(1,e.duration),tier:I(e.kind),spanId:n.id,failed:n.errorCode!=null&&e===n.effects[n.effects.length-1]});else t.push({id:n.id,label:n.flow,startMs:n.startedAt,endMs:n.endedAt,tier:`none`,spanId:n.id,failed:n.errorCode!=null});return t}function U(e){let t=Math.round(e*10)/10;return Number.isInteger(t)?String(t):t.toFixed(1)}function W(e){if(e.length===0)return[];let t=Math.min(...e.map(e=>e.startedAt)),n=Math.max(...e.map(e=>e.endedAt)),r=Math.max(1,n-t);if(e.every(e=>e.effects.length===0))return e.map(e=>({start:(e.startedAt-t)/r,width:Math.max(.02,e.durationMs/r),tier:L(e.effects),failed:e.errorCode!=null}));let i=[];for(let n of e){if(n.effects.length===0){i.push({start:(n.startedAt-t)/r,width:Math.max(.02,n.durationMs/r),tier:`none`,failed:n.errorCode!=null});continue}for(let e=0;e<n.effects.length;e++){let a=n.effects[e];a&&i.push({start:(a.timestamp-t)/r,width:Math.max(.02,a.duration/r),tier:I(a.kind),failed:n.errorCode!=null&&e===n.effects.length-1})}}return i}function G(e){for(let t of e)if(t.errorCode)return t.errorCode;return null}function K(e){return R(e)?{mode:`dry-run`,reason:`This trace contains an external effect. Replay runs as a dry run with external effects stubbed.`}:{mode:`replay`}}var q=`10% + all errors`,J=6e5;function Y(e,t=Date.now()){let n=e.filter(e=>e.until>t);return n.length===0?q:`${q} · full: ${n.map(e=>e.flow).join(`, `)}`}function X(e,t,n=Date.now()){let r=n+J;return[...e.filter(e=>e.flow!==t&&e.until>n),{flow:t,until:r}]}function ne(e,t=Date.now()){return e.filter(e=>e.until>t)}var Z=d();function Q(){let e=p({from:`/traces`}),t=n({from:`/traces`}),a=s(),[l,d]=(0,v.useState)([]),[m]=(0,v.useState)(()=>_()),[y,S]=(0,v.useState)(0),[,C]=(0,v.useState)(0),w=e=>{t({search:T(e),replace:!0})},k=r({queryKey:[`console.runs.list`],queryFn:async()=>{let e=await o.runsList();if(e.error)throw Error(e.error.code);return e.data.runs},refetchInterval:5e3}),N=(0,v.useMemo)(()=>(k.data??[]).map(re),[k.data]);(0,v.useEffect)(()=>{if(N.length===0)return;if(m.visible.length===0){for(let e of N)m.offer({id:e.id,value:e,arrivedAt:e.startedAt});m.flush(),S(0),C(e=>e+1);return}let e=new Set(m.visible.map(e=>e.id));for(let t of m.pending)e.add(t.id);for(let t of N)e.has(t.id)?m.updateInPlace(t.id,t):m.offer({id:t.id,value:t,arrivedAt:Date.now()});S(m.pendingCount),C(e=>e+1)},[N,m]);let F=m.visible.map(e=>e.value),I=x(e.effect),R=(0,v.useMemo)(()=>j(F).filter(t=>{let n=g([t.root.flow,t.root.id,G(t.spans)??``],e.q),r=b(t.spans,I);return n&&r}),[F,e.q,I]),z=R.find(t=>t.rootId===e.trace)??(e.trace?j(F).find(t=>t.rootId===e.trace):void 0),B=z?M(z.spans,e.span):void 0,U=B?A(F,B):null,q=U?P(U.connected):new Set,J=U?V(H(U.connected),{expandedFolds:E(e)},q):null,Q=U?K(U.connected):null,$=i({mutationFn:async()=>{if(!U||!Q)return;let e=await o.tracesReplay({rootId:U.connected[0]?.id??U.current.id,dryRun:Q.mode===`dry-run`});if(e.error)throw Error(e.error.code);return e.data},onSuccess:()=>{a.invalidateQueries({queryKey:[`console.runs.list`]})}}),ae=ne(l);return(0,Z.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,Z.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-4 border-b border-[var(--oke-line)] px-6 py-4`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,Z.jsx)(`p`,{className:`text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]`,children:`Traces`}),(0,Z.jsx)(`h1`,{className:`text-xl font-semibold tracking-tight`,children:`Causal chain`}),(0,Z.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[`Sampling: `,Y(ae)]})]}),(0,Z.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,Z.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter by effect`}),(0,Z.jsxs)(`select`,{"aria-label":`Filter by effect`,className:`min-h-8 border border-[var(--oke-line)] bg-transparent px-2 text-sm`,value:e.effect??``,onChange:t=>{let n=t.target.value;w(O(e,n?x(n):null))},children:[(0,Z.jsx)(`option`,{value:``,children:`All effects`}),(0,Z.jsx)(`option`,{value:`wrote:sql:bookings`,children:`Wrote sql:bookings`}),(0,Z.jsx)(`option`,{value:`sent`,children:`Sent (channel)`}),(0,Z.jsx)(`option`,{value:`asked`,children:`Asked a model`}),(0,Z.jsx)(`option`,{value:`secret`,children:`Read a secret`}),(0,Z.jsx)(`option`,{value:`cost:0.05`,children:`Cost > $0.05`})]})]}),(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,Z.jsx)(u,{type:`button`,variant:`ghost`,onClick:()=>{let e=z?.root.flow??R[0]?.root.flow??`bookings.create`;d(t=>X(t,e))},children:`Trace flow fully for 10 minutes`}),(0,Z.jsx)(c,{count:y,onFlush:()=>{m.flush(),S(0),C(e=>e+1)}})]})]}),(0,Z.jsxs)(`div`,{className:`grid min-h-0 flex-1 grid-cols-1 md:grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]`,children:[(0,Z.jsx)(`section`,{"aria-label":`Trace list`,className:`min-h-0 overflow-auto border-r border-[var(--oke-line)]`,children:k.isLoading?(0,Z.jsx)(`p`,{className:`px-6 py-8 text-sm text-[var(--oke-muted)]`,children:`Loading traces…`}):R.length===0?(0,Z.jsx)(`p`,{className:`px-6 py-8 text-sm text-[var(--oke-muted)]`,children:`No traces yet. Invoke a flow or wait for traffic.`}):(0,Z.jsx)(`ul`,{className:`divide-y divide-[var(--oke-line)]`,children:R.map(t=>{let n=G(t.spans),r=W(t.spans),i=t.rootId===e.trace;return(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,"aria-pressed":i,className:f(`flex w-full min-h-10 flex-col gap-1 px-4 py-3 text-left text-sm`,i?`bg-[color-mix(in_oklab,var(--oke-fg)_6%,transparent)]`:`hover:bg-[color-mix(in_oklab,var(--oke-fg)_3%,transparent)]`),onClick:()=>{let n=M(t.spans);w(D(e,t.rootId,n))},children:[(0,Z.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,Z.jsx)(`span`,{className:`font-medium`,children:t.root.flow}),n?(0,Z.jsx)(`span`,{role:`status`,className:`font-mono text-xs text-[var(--oke-danger)]`,children:n}):(0,Z.jsxs)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:[t.root.durationMs,`ms`]})]}),(0,Z.jsx)(ie,{bars:r})]})},t.rootId)})})}),(0,Z.jsx)(`section`,{"aria-label":`Trace detail`,className:`min-h-0 overflow-auto px-6 py-6`,"aria-live":`polite`,children:!U||!J?(0,Z.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a trace to see the causal chain and folded-time waterfall.`}):(0,Z.jsxs)(`div`,{className:`flex flex-col gap-6`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-wrap items-start justify-between gap-3`,children:[(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h2`,{className:`text-lg font-semibold`,children:U.current.flow}),(0,Z.jsxs)(`p`,{className:`text-xs text-[var(--oke-muted)]`,children:[U.connected.length,` span`,U.connected.length===1?``:`s`,` · wall `,J.wallDurationMs,`ms · display scale `,Math.round(J.displayDurationMs),`ms`]})]}),(0,Z.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,Z.jsx)(h,{to:`/runs`,search:{run:U.current.id},className:`inline-flex min-h-8 items-center border border-[var(--oke-line)] px-3 text-sm`,children:`Open in Runs`}),(0,Z.jsx)(u,{type:`button`,variant:Q?.mode===`dry-run`?`external`:`primary`,disabled:$.isPending,title:Q?.mode===`dry-run`?Q.reason:`Replay from the journal`,onClick:()=>$.mutate(),children:Q?.mode===`dry-run`?`Dry-run replay`:`Replay`}),(0,Z.jsx)(u,{type:`button`,variant:`ghost`,onClick:()=>w(ee(e)),children:`Close`})]})]}),Q?.mode===`dry-run`?(0,Z.jsx)(`p`,{role:`note`,className:`text-sm text-[var(--oke-external)]`,children:Q.reason}):null,(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Causal chain`}),(0,Z.jsxs)(`ol`,{className:`flex flex-col gap-1 border-l border-[var(--oke-line)] pl-4`,children:[U.parents.map(t=>(0,Z.jsx)(`li`,{children:(0,Z.jsx)(`button`,{type:`button`,className:`min-h-8 text-sm text-[var(--oke-muted)]`,onClick:()=>w({...e,span:t.id}),children:t.flow})},t.id)),(0,Z.jsxs)(`li`,{"aria-current":`true`,children:[(0,Z.jsx)(`span`,{className:`text-sm font-medium`,children:U.current.flow}),U.current.errorCode?(0,Z.jsx)(`span`,{role:`status`,className:`ml-2 font-mono text-xs text-[var(--oke-danger)]`,children:U.current.errorCode}):null,L(U.current.effects)===`external`?(0,Z.jsx)(`span`,{"aria-label":`external effect`,children:` ↗`}):null]}),U.children.map(t=>(0,Z.jsx)(`li`,{children:(0,Z.jsxs)(`button`,{type:`button`,className:`min-h-8 text-sm text-[var(--oke-muted)]`,onClick:()=>w({...e,span:t.id}),children:[t.flow,L(t.effects)===`external`?(0,Z.jsx)(`span`,{"aria-label":`external effect`,children:` ↗`}):null]})},t.id))]})]}),(0,Z.jsxs)(`div`,{children:[(0,Z.jsx)(`h3`,{id:`waterfall-heading`,className:`mb-2 text-sm font-medium`,children:`Waterfall`}),(0,Z.jsx)(`ul`,{"aria-labelledby":`waterfall-heading`,className:`flex min-h-10 list-none items-stretch gap-0.5 p-0`,children:J.segments.map(t=>t.kind===`fold`?(0,Z.jsx)(`li`,{style:{flex:`${t.displayMs} 1 0`,minWidth:24},children:(0,Z.jsx)(`button`,{type:`button`,"aria-expanded":t.expanded,className:`h-full min-h-10 w-full border border-dashed border-[var(--oke-line)] px-1 font-mono text-[10px] text-[var(--oke-muted)]`,onClick:()=>w(te(e,t.id)),children:t.label})},t.id):(0,Z.jsx)(`li`,{title:t.label,className:f(`min-h-10 px-1 text-[10px] leading-10`,t.tier===`external`?`bg-[var(--oke-external)] text-black`:`bg-[color-mix(in_oklab,var(--oke-accent)_55%,transparent)]`,t.failed&&`outline outline-2 outline-[var(--oke-danger)]`),style:{flex:`${t.displayMs} 1 0`,opacity:t.critical?1:.38,minWidth:4},children:(0,Z.jsxs)(`span`,{className:`sr-only`,children:[t.label,t.critical?` (critical path)`:``,t.failed?` (failed)`:``]})},t.id))}),(0,Z.jsx)(`p`,{className:`mt-2 text-xs text-[var(--oke-muted)]`,children:`Critical path at full opacity · dead time folded into expandable bars`})]})]})})]})]})}function re(e){return{id:e.id,...e.parentId?{parentId:e.parentId}:{},flow:e.flow,...e.unit?{unit:e.unit}:{},trigger:e.trigger,startedAt:e.startedAt,endedAt:e.endedAt,durationMs:e.durationMs,errorCode:e.error,cost:e.cost??void 0,sampled:e.sampled??(e.error?`error`:`sample`),effects:e.effects??[]}}function ie({bars:e}){return(0,Z.jsx)(`div`,{"aria-hidden":`true`,className:`relative h-2 w-full overflow-hidden bg-[color-mix(in_oklab,var(--oke-fg)_6%,transparent)]`,children:e.map((e,t)=>(0,Z.jsx)(`span`,{className:f(`absolute inset-y-0`,e.tier===`external`?`bg-[var(--oke-external)]`:e.failed?`bg-[var(--oke-danger)]`:`bg-[var(--oke-accent)]`),style:{left:`${e.start*100}%`,width:`${Math.max(2,e.width*100)}%`}},t))})}var $=t({default:()=>Q});export{w as n,$ as t};
@@ -1 +1 @@
1
- import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,a,b as o,c as s,d as c,et as l,g as u,nt as d,o as f,tt as p,u as m,w as h,y as g}from"./panel-access-BGv45snf.js";import{n as _}from"./panel-channels-9T3ybqRu.js";var v=g({q:o().optional(),name:o().optional(),action:u([`set`,`rotate`]).optional()});function y(e){let t=v.safeParse(e);return t.success?t.data:{}}function b(e){let t={};return e.q&&(t.q=e.q),e.name&&(t.name=e.name),e.action&&(t.action=e.action),t}function x(e,t){return{...e,name:t,action:void 0}}function S(e,t=``){let n=t.trim().toLowerCase(),r=n?e.filter(e=>e.name.toLowerCase().includes(n)||(e.description?.toLowerCase().includes(n)??!1)):e,i=[`secret`,`config`],a={secret:`Secrets`,config:`Config`};return i.map(e=>({kind:e,label:a[e],secrets:r.filter(t=>t.kind===e)})).filter(e=>e.secrets.length>0)}function C(e={production:!0}){return e.production?{kind:`typed`,phrase:`SET`,requireReason:!0}:{kind:`undo`,windowMs:15e3}}function w(e={production:!0}){return{kind:`typed`,phrase:`ROTATE`,requireReason:!0}}function T(e){if(e.count===0)return{summary:`No in-flight durable runs hold this secret`,detail:null,warn:!1};let t=e.longestOutstandingMs==null?null:E(e.longestOutstandingMs);return{summary:`${e.count} in-flight durable run(s) will wake holding a new key`,detail:t?`Longest outstanding wake in ${t}`:e.longestWakeAt==null?null:`Longest wake at ${new Date(e.longestWakeAt).toISOString()}`,warn:!0}}function E(e){if(e<1e3)return`${e}ms`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);if(n<60)return`${n}m`;let r=Math.floor(n/60);return r<48?`${r}h`:`${Math.floor(r/24)}d`}function D(e){return{name:e.name,kind:e.kind,sensitive:e.sensitive,description:e.description??null,rotate:e.rotate??null,fingerprints:{...e.fingerprints},fingerprint:e.fingerprint,cleartext:e.sensitive?null:e.cleartext,winner:e.winner,resolution:e.resolution.map(e=>({...e})),readers:[...e.readers],blastRadius:{count:e.blastRadius.count,longestWakeAt:e.blastRadius.longestWakeAt,longestOutstandingMs:e.blastRadius.longestOutstandingMs,runIds:[...e.blastRadius.runIds]},lastReadAt:e.lastReadAt,sharedFingerprintEnvs:[...e.sharedFingerprintEnvs]}}function O(e){return JSON.stringify(e.map(e=>D(e)),null,2)}var k=e(d(),1),A=p();function j(){let e=h({from:`/vault`}),t=n({from:`/vault`}),o=l(),[u,d]=(0,k.useState)(``),[p,g]=(0,k.useState)(``),[v,y]=(0,k.useState)(``),[E,D]=(0,k.useState)(null),j=e=>{t({search:b(e),replace:!0})},M=r({queryKey:[`console.vault.list`],queryFn:async()=>{let e=await c.vaultList();if(e.error)throw Error(e.error.code);return e.data},refetchInterval:1e4}),N=M.data?.secrets??[],P=M.data?.env??`local`,F=(0,k.useMemo)(()=>S(N,e.q??``),[N,e.q]),I=N.find(t=>t.name===e.name),L=I?T(I.blastRadius):null,R=C({production:!0}),z=w({production:!0}),B=e.action;(0,k.useEffect)(()=>{d(``),g(``),y(``),D(null)},[I?.name,B]);let V=i({mutationFn:async()=>{if(!I)throw Error(`no secret`);if(R.kind===`typed`){let e=a({typed:u,reason:p,phrase:R.phrase});if(e)throw Error(e.typed??e.reason??`confirm`)}let e=await c.vaultSet({name:I.name,value:v,confirmation:R.kind===`typed`?u:void 0,reason:p||void 0});if(e.error)throw Error(e.error.code);return e.data},onSuccess:async()=>{y(``),d(``),g(``),j({...e,action:void 0}),await o.invalidateQueries({queryKey:[`console.vault.list`]})}}),H=i({mutationFn:async()=>{if(!I)throw Error(`no secret`);let e=a({typed:u,reason:p,phrase:z.kind===`typed`?z.phrase:`ROTATE`});if(e)throw Error(e.typed??e.reason??`confirm`);let t=await c.vaultRotate({name:I.name,value:v,confirmation:u,reason:p});if(t.error)throw Error(t.error.code);return t.data},onSuccess:async()=>{y(``),d(``),g(``),j({...e,action:void 0}),await o.invalidateQueries({queryKey:[`console.vault.list`]})}});return(0,A.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,A.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-3 border-b border-[var(--oke-line)] px-4 py-3`,children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`h1`,{className:`text-lg font-medium text-[var(--oke-fg)]`,children:`Vault`}),(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Fingerprints only — secrets are write-only`})]}),(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,role:`status`,children:[`Environment `,P]}),(0,A.jsxs)(`label`,{className:`ml-auto flex min-w-[12rem] flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter vault`}),(0,A.jsx)(s,{"aria-label":`Filter vault`,value:e.q??``,onChange:t=>j({...e,q:t.currentTarget.value||void 0})})]}),(0,A.jsx)(f,{type:`button`,variant:`ghost`,onClick:()=>{let e=O(N);navigator.clipboard?.writeText(e),D(`Exported fingerprints only (no secret values)`)},children:`Export`})]}),E?(0,A.jsx)(`p`,{className:`px-4 py-2 text-sm text-[var(--oke-muted)]`,role:`status`,children:E}):null,(0,A.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,A.jsxs)(`section`,{"aria-label":`Vault list`,className:`w-80 shrink-0 overflow-y-auto border-r border-[var(--oke-line)]`,children:[(0,A.jsx)(`h2`,{className:`sr-only`,children:`Contracts`}),M.isLoading?(0,A.jsx)(`p`,{className:`p-4 text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,F.map(t=>(0,A.jsxs)(`section`,{"aria-label":t.label,className:`py-2`,children:[(0,A.jsx)(`h3`,{className:`px-4 py-1 text-xs uppercase tracking-wide text-[var(--oke-muted)]`,children:t.label}),(0,A.jsx)(`ul`,{children:t.secrets.map(t=>(0,A.jsx)(`li`,{children:(0,A.jsxs)(`button`,{type:`button`,"aria-pressed":t.name===I?.name,className:m(`flex min-h-10 w-full flex-col items-start px-4 py-2 text-left text-sm`,t.name===I?.name?`bg-[var(--oke-line)] text-[var(--oke-fg)]`:`text-[var(--oke-muted)] hover:text-[var(--oke-fg)]`),onClick:()=>j(x(e,t.name)),children:[(0,A.jsx)(`span`,{children:_(t.name,t.description)}),t.description?(0,A.jsx)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:t.name}):null,(0,A.jsx)(`span`,{className:`truncate text-xs`,children:t.sensitive?t.fingerprint??`unset`:t.cleartext??`unset`}),t.blastRadius.count>0?(0,A.jsxs)(`span`,{role:`status`,className:`text-xs text-[var(--oke-danger)]`,children:[`blast `,t.blastRadius.count]}):null,t.sharedFingerprintEnvs.length>0?(0,A.jsx)(`span`,{role:`status`,className:`text-xs`,children:`shared fingerprint`}):null]})},t.name))})]},t.kind))]}),(0,A.jsx)(`section`,{"aria-label":`Vault detail`,"aria-live":`polite`,className:`min-w-0 flex-1 overflow-y-auto p-4`,children:I?(0,A.jsxs)(`div`,{className:`flex max-w-2xl flex-col gap-6`,children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`h2`,{className:`text-lg text-[var(--oke-fg)]`,children:_(I.name,I.description)}),I.description?(0,A.jsx)(`p`,{className:`font-mono text-sm text-[var(--oke-muted)]`,children:I.name}):null,I.rotate?(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:[`Rotate hint: `,I.rotate]}):null]}),(0,A.jsxs)(`section`,{"aria-label":`Fingerprints by environment`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Fingerprints`}),I.sensitive?(0,A.jsxs)(`ul`,{className:`space-y-1 font-mono text-sm`,children:[Object.entries(I.fingerprints).map(([e,t])=>(0,A.jsxs)(`li`,{children:[(0,A.jsxs)(`span`,{className:`text-[var(--oke-muted)]`,children:[e,`:`]}),` `,t,I.sharedFingerprintEnvs.includes(e)?(0,A.jsxs)(`span`,{role:`status`,className:`ml-2 text-[var(--oke-warn,var(--oke-muted))]`,children:[`(matches `,P,` — warning, may be deliberate)`]}):null]},e)),Object.keys(I.fingerprints).length===0?(0,A.jsx)(`li`,{className:`text-[var(--oke-muted)]`,children:`Unset`}):null]}):(0,A.jsx)(`p`,{className:`font-mono text-sm`,role:`status`,children:I.cleartext??`unset`})]}),(0,A.jsxs)(`section`,{"aria-label":`Resolution chain`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Resolution chain`}),(0,A.jsx)(`ol`,{className:`list-decimal space-y-1 pl-5 text-sm`,children:I.resolution.map(e=>(0,A.jsxs)(`li`,{className:e.won?`text-[var(--oke-fg)]`:`text-[var(--oke-muted)]`,children:[(0,A.jsx)(`span`,{className:`font-mono`,children:e.source}),e.won?` — won`:e.present?` — present (lost)`:` — absent`]},e.source))}),(0,A.jsxs)(`p`,{className:`mt-2 text-sm`,role:`status`,children:[`Winner: `,(0,A.jsx)(`span`,{className:`font-mono`,children:I.winner??`none`})]})]}),(0,A.jsxs)(`section`,{"aria-label":`Readers`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Readers`}),(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:[`Flows that declare `,(0,A.jsxs)(`code`,{className:`font-mono`,children:[`fx.vault(`,I.name,`)`]})]}),(0,A.jsx)(`ul`,{className:`mt-1 list-disc pl-5 font-mono text-sm`,children:I.readers.length===0?(0,A.jsx)(`li`,{className:`text-[var(--oke-muted)]`,children:`none`}):I.readers.map(e=>(0,A.jsx)(`li`,{children:e},e))})]}),(0,A.jsxs)(`section`,{"aria-label":`Rotation blast radius`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Rotation blast radius`}),L?(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`p`,{className:`text-sm`,role:L.warn?`alert`:`status`,children:L.summary}),L.detail?(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:L.detail}):null,I.blastRadius.runIds.length>0?(0,A.jsx)(`p`,{className:`mt-1 font-mono text-xs text-[var(--oke-muted)]`,children:I.blastRadius.runIds.join(`, `)}):null]}):null]}),(0,A.jsxs)(`section`,{"aria-label":`Last read`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Last read`}),(0,A.jsx)(`p`,{className:`text-sm`,role:`status`,children:I.lastReadAt==null?`Never read — possible dead secret`:new Date(I.lastReadAt).toISOString()})]}),(0,A.jsxs)(`section`,{"aria-label":`Set or rotate`,className:`space-y-3`,children:[(0,A.jsx)(`h3`,{className:`text-sm font-medium`,children:`Set / rotate`}),(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Write-only. Values are never revealed after submit. No preview.`}),(0,A.jsxs)(`div`,{className:`flex gap-2`,children:[(0,A.jsx)(f,{type:`button`,variant:B===`set`?`primary`:`ghost`,"aria-pressed":B===`set`,onClick:()=>j({...e,action:`set`}),children:`Set`}),(0,A.jsx)(f,{type:`button`,variant:B===`rotate`?`danger`:`ghost`,"aria-pressed":B===`rotate`,onClick:()=>j({...e,action:`rotate`}),children:`Rotate`})]}),B?(0,A.jsxs)(`div`,{className:`space-y-3 border border-[var(--oke-line)] p-3`,children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{children:`New value`}),(0,A.jsx)(s,{"aria-label":`New vault value`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.currentTarget.value)})]}),(B===`rotate`||R.kind===`typed`)&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsxs)(`span`,{children:[`Type`,` `,B===`rotate`?z.kind===`typed`?z.phrase:`ROTATE`:R.kind===`typed`?R.phrase:`SET`,` `,`to confirm`]}),(0,A.jsx)(s,{"aria-label":`Confirmation phrase`,value:u,onChange:e=>d(e.currentTarget.value)})]}),(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{children:`Reason`}),(0,A.jsx)(s,{"aria-label":`Reason for vault write`,value:p,onChange:e=>g(e.currentTarget.value)})]})]}),(0,A.jsx)(f,{type:`button`,variant:B===`rotate`?`danger`:`primary`,disabled:!v||(B===`set`?V.isPending:H.isPending),onClick:()=>{B===`set`?V.mutate():H.mutate()},children:B===`set`?`Commit set`:`Commit rotate`}),(V.isError||H.isError)&&(0,A.jsx)(`p`,{role:`alert`,className:`text-sm text-[var(--oke-danger)]`,children:(V.error??H.error)?.message??`Failed`})]}):null]})]}):(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a contract to inspect fingerprints, resolution, and readers.`})})]})]})}var M=t({default:()=>j});export{y as n,M as t};
1
+ import{a as e,r as t}from"./rolldown-runtime-B0Z9INg1.js";import{C as n,Q as r,Z as i,a,b as o,c as s,d as c,et as l,g as u,nt as d,o as f,tt as p,u as m,w as h,y as g}from"./panel-access-ri1X9Otj.js";import{n as _}from"./panel-channels-BDYWX29p.js";var v=g({q:o().optional(),name:o().optional(),action:u([`set`,`rotate`]).optional()});function y(e){let t=v.safeParse(e);return t.success?t.data:{}}function b(e){let t={};return e.q&&(t.q=e.q),e.name&&(t.name=e.name),e.action&&(t.action=e.action),t}function x(e,t){return{...e,name:t,action:void 0}}function S(e,t=``){let n=t.trim().toLowerCase(),r=n?e.filter(e=>e.name.toLowerCase().includes(n)||(e.description?.toLowerCase().includes(n)??!1)):e,i=[`secret`,`config`],a={secret:`Secrets`,config:`Config`};return i.map(e=>({kind:e,label:a[e],secrets:r.filter(t=>t.kind===e)})).filter(e=>e.secrets.length>0)}function C(e={production:!0}){return e.production?{kind:`typed`,phrase:`SET`,requireReason:!0}:{kind:`undo`,windowMs:15e3}}function w(e={production:!0}){return{kind:`typed`,phrase:`ROTATE`,requireReason:!0}}function T(e){if(e.count===0)return{summary:`No in-flight durable runs hold this secret`,detail:null,warn:!1};let t=e.longestOutstandingMs==null?null:E(e.longestOutstandingMs);return{summary:`${e.count} in-flight durable run(s) will wake holding a new key`,detail:t?`Longest outstanding wake in ${t}`:e.longestWakeAt==null?null:`Longest wake at ${new Date(e.longestWakeAt).toISOString()}`,warn:!0}}function E(e){if(e<1e3)return`${e}ms`;let t=Math.floor(e/1e3);if(t<60)return`${t}s`;let n=Math.floor(t/60);if(n<60)return`${n}m`;let r=Math.floor(n/60);return r<48?`${r}h`:`${Math.floor(r/24)}d`}function D(e){return{name:e.name,kind:e.kind,sensitive:e.sensitive,description:e.description??null,rotate:e.rotate??null,fingerprints:{...e.fingerprints},fingerprint:e.fingerprint,cleartext:e.sensitive?null:e.cleartext,winner:e.winner,resolution:e.resolution.map(e=>({...e})),readers:[...e.readers],blastRadius:{count:e.blastRadius.count,longestWakeAt:e.blastRadius.longestWakeAt,longestOutstandingMs:e.blastRadius.longestOutstandingMs,runIds:[...e.blastRadius.runIds]},lastReadAt:e.lastReadAt,sharedFingerprintEnvs:[...e.sharedFingerprintEnvs]}}function O(e){return JSON.stringify(e.map(e=>D(e)),null,2)}var k=e(d(),1),A=p();function j(){let e=h({from:`/vault`}),t=n({from:`/vault`}),o=l(),[u,d]=(0,k.useState)(``),[p,g]=(0,k.useState)(``),[v,y]=(0,k.useState)(``),[E,D]=(0,k.useState)(null),j=e=>{t({search:b(e),replace:!0})},M=r({queryKey:[`console.vault.list`],queryFn:async()=>{let e=await c.vaultList();if(e.error)throw Error(e.error.code);return e.data},refetchInterval:1e4}),N=M.data?.secrets??[],P=M.data?.env??`local`,F=(0,k.useMemo)(()=>S(N,e.q??``),[N,e.q]),I=N.find(t=>t.name===e.name),L=I?T(I.blastRadius):null,R=C({production:!0}),z=w({production:!0}),B=e.action;(0,k.useEffect)(()=>{d(``),g(``),y(``),D(null)},[I?.name,B]);let V=i({mutationFn:async()=>{if(!I)throw Error(`no secret`);if(R.kind===`typed`){let e=a({typed:u,reason:p,phrase:R.phrase});if(e)throw Error(e.typed??e.reason??`confirm`)}let e=await c.vaultSet({name:I.name,value:v,confirmation:R.kind===`typed`?u:void 0,reason:p||void 0});if(e.error)throw Error(e.error.code);return e.data},onSuccess:async()=>{y(``),d(``),g(``),j({...e,action:void 0}),await o.invalidateQueries({queryKey:[`console.vault.list`]})}}),H=i({mutationFn:async()=>{if(!I)throw Error(`no secret`);let e=a({typed:u,reason:p,phrase:z.kind===`typed`?z.phrase:`ROTATE`});if(e)throw Error(e.typed??e.reason??`confirm`);let t=await c.vaultRotate({name:I.name,value:v,confirmation:u,reason:p});if(t.error)throw Error(t.error.code);return t.data},onSuccess:async()=>{y(``),d(``),g(``),j({...e,action:void 0}),await o.invalidateQueries({queryKey:[`console.vault.list`]})}});return(0,A.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[(0,A.jsxs)(`header`,{className:`flex shrink-0 flex-wrap items-end gap-3 border-b border-[var(--oke-line)] px-4 py-3`,children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`h1`,{className:`text-lg font-medium text-[var(--oke-fg)]`,children:`Vault`}),(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Fingerprints only — secrets are write-only`})]}),(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,role:`status`,children:[`Environment `,P]}),(0,A.jsxs)(`label`,{className:`ml-auto flex min-w-[12rem] flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{className:`text-[var(--oke-muted)]`,children:`Filter vault`}),(0,A.jsx)(s,{"aria-label":`Filter vault`,value:e.q??``,onChange:t=>j({...e,q:t.currentTarget.value||void 0})})]}),(0,A.jsx)(f,{type:`button`,variant:`ghost`,onClick:()=>{let e=O(N);navigator.clipboard?.writeText(e),D(`Exported fingerprints only (no secret values)`)},children:`Export`})]}),E?(0,A.jsx)(`p`,{className:`px-4 py-2 text-sm text-[var(--oke-muted)]`,role:`status`,children:E}):null,(0,A.jsxs)(`div`,{className:`flex min-h-0 flex-1`,children:[(0,A.jsxs)(`section`,{"aria-label":`Vault list`,className:`w-80 shrink-0 overflow-y-auto border-r border-[var(--oke-line)]`,children:[(0,A.jsx)(`h2`,{className:`sr-only`,children:`Contracts`}),M.isLoading?(0,A.jsx)(`p`,{className:`p-4 text-sm text-[var(--oke-muted)]`,children:`Loading…`}):null,F.map(t=>(0,A.jsxs)(`section`,{"aria-label":t.label,className:`py-2`,children:[(0,A.jsx)(`h3`,{className:`px-4 py-1 text-xs uppercase tracking-wide text-[var(--oke-muted)]`,children:t.label}),(0,A.jsx)(`ul`,{children:t.secrets.map(t=>(0,A.jsx)(`li`,{children:(0,A.jsxs)(`button`,{type:`button`,"aria-pressed":t.name===I?.name,className:m(`flex min-h-10 w-full flex-col items-start px-4 py-2 text-left text-sm`,t.name===I?.name?`bg-[var(--oke-line)] text-[var(--oke-fg)]`:`text-[var(--oke-muted)] hover:text-[var(--oke-fg)]`),onClick:()=>j(x(e,t.name)),children:[(0,A.jsx)(`span`,{children:_(t.name,t.description)}),t.description?(0,A.jsx)(`span`,{className:`font-mono text-xs text-[var(--oke-muted)]`,children:t.name}):null,(0,A.jsx)(`span`,{className:`truncate text-xs`,children:t.sensitive?t.fingerprint??`unset`:t.cleartext??`unset`}),t.blastRadius.count>0?(0,A.jsxs)(`span`,{role:`status`,className:`text-xs text-[var(--oke-danger)]`,children:[`blast `,t.blastRadius.count]}):null,t.sharedFingerprintEnvs.length>0?(0,A.jsx)(`span`,{role:`status`,className:`text-xs`,children:`shared fingerprint`}):null]})},t.name))})]},t.kind))]}),(0,A.jsx)(`section`,{"aria-label":`Vault detail`,"aria-live":`polite`,className:`min-w-0 flex-1 overflow-y-auto p-4`,children:I?(0,A.jsxs)(`div`,{className:`flex max-w-2xl flex-col gap-6`,children:[(0,A.jsxs)(`div`,{children:[(0,A.jsx)(`h2`,{className:`text-lg text-[var(--oke-fg)]`,children:_(I.name,I.description)}),I.description?(0,A.jsx)(`p`,{className:`font-mono text-sm text-[var(--oke-muted)]`,children:I.name}):null,I.rotate?(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:[`Rotate hint: `,I.rotate]}):null]}),(0,A.jsxs)(`section`,{"aria-label":`Fingerprints by environment`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Fingerprints`}),I.sensitive?(0,A.jsxs)(`ul`,{className:`space-y-1 font-mono text-sm`,children:[Object.entries(I.fingerprints).map(([e,t])=>(0,A.jsxs)(`li`,{children:[(0,A.jsxs)(`span`,{className:`text-[var(--oke-muted)]`,children:[e,`:`]}),` `,t,I.sharedFingerprintEnvs.includes(e)?(0,A.jsxs)(`span`,{role:`status`,className:`ml-2 text-[var(--oke-warn,var(--oke-muted))]`,children:[`(matches `,P,` — warning, may be deliberate)`]}):null]},e)),Object.keys(I.fingerprints).length===0?(0,A.jsx)(`li`,{className:`text-[var(--oke-muted)]`,children:`Unset`}):null]}):(0,A.jsx)(`p`,{className:`font-mono text-sm`,role:`status`,children:I.cleartext??`unset`})]}),(0,A.jsxs)(`section`,{"aria-label":`Resolution chain`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Resolution chain`}),(0,A.jsx)(`ol`,{className:`list-decimal space-y-1 pl-5 text-sm`,children:I.resolution.map(e=>(0,A.jsxs)(`li`,{className:e.won?`text-[var(--oke-fg)]`:`text-[var(--oke-muted)]`,children:[(0,A.jsx)(`span`,{className:`font-mono`,children:e.source}),e.won?` — won`:e.present?` — present (lost)`:` — absent`]},e.source))}),(0,A.jsxs)(`p`,{className:`mt-2 text-sm`,role:`status`,children:[`Winner: `,(0,A.jsx)(`span`,{className:`font-mono`,children:I.winner??`none`})]})]}),(0,A.jsxs)(`section`,{"aria-label":`Readers`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Readers`}),(0,A.jsxs)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:[`Flows that declare `,(0,A.jsxs)(`code`,{className:`font-mono`,children:[`fx.vault(`,I.name,`)`]})]}),(0,A.jsx)(`ul`,{className:`mt-1 list-disc pl-5 font-mono text-sm`,children:I.readers.length===0?(0,A.jsx)(`li`,{className:`text-[var(--oke-muted)]`,children:`none`}):I.readers.map(e=>(0,A.jsx)(`li`,{children:e},e))})]}),(0,A.jsxs)(`section`,{"aria-label":`Rotation blast radius`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Rotation blast radius`}),L?(0,A.jsxs)(A.Fragment,{children:[(0,A.jsx)(`p`,{className:`text-sm`,role:L.warn?`alert`:`status`,children:L.summary}),L.detail?(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:L.detail}):null,I.blastRadius.runIds.length>0?(0,A.jsx)(`p`,{className:`mt-1 font-mono text-xs text-[var(--oke-muted)]`,children:I.blastRadius.runIds.join(`, `)}):null]}):null]}),(0,A.jsxs)(`section`,{"aria-label":`Last read`,children:[(0,A.jsx)(`h3`,{className:`mb-2 text-sm font-medium`,children:`Last read`}),(0,A.jsx)(`p`,{className:`text-sm`,role:`status`,children:I.lastReadAt==null?`Never read — possible dead secret`:new Date(I.lastReadAt).toISOString()})]}),(0,A.jsxs)(`section`,{"aria-label":`Set or rotate`,className:`space-y-3`,children:[(0,A.jsx)(`h3`,{className:`text-sm font-medium`,children:`Set / rotate`}),(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Write-only. Values are never revealed after submit. No preview.`}),(0,A.jsxs)(`div`,{className:`flex gap-2`,children:[(0,A.jsx)(f,{type:`button`,variant:B===`set`?`primary`:`ghost`,"aria-pressed":B===`set`,onClick:()=>j({...e,action:`set`}),children:`Set`}),(0,A.jsx)(f,{type:`button`,variant:B===`rotate`?`danger`:`ghost`,"aria-pressed":B===`rotate`,onClick:()=>j({...e,action:`rotate`}),children:`Rotate`})]}),B?(0,A.jsxs)(`div`,{className:`space-y-3 border border-[var(--oke-line)] p-3`,children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{children:`New value`}),(0,A.jsx)(s,{"aria-label":`New vault value`,type:`password`,autoComplete:`off`,value:v,onChange:e=>y(e.currentTarget.value)})]}),(B===`rotate`||R.kind===`typed`)&&(0,A.jsxs)(A.Fragment,{children:[(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsxs)(`span`,{children:[`Type`,` `,B===`rotate`?z.kind===`typed`?z.phrase:`ROTATE`:R.kind===`typed`?R.phrase:`SET`,` `,`to confirm`]}),(0,A.jsx)(s,{"aria-label":`Confirmation phrase`,value:u,onChange:e=>d(e.currentTarget.value)})]}),(0,A.jsxs)(`label`,{className:`flex flex-col gap-1 text-sm`,children:[(0,A.jsx)(`span`,{children:`Reason`}),(0,A.jsx)(s,{"aria-label":`Reason for vault write`,value:p,onChange:e=>g(e.currentTarget.value)})]})]}),(0,A.jsx)(f,{type:`button`,variant:B===`rotate`?`danger`:`primary`,disabled:!v||(B===`set`?V.isPending:H.isPending),onClick:()=>{B===`set`?V.mutate():H.mutate()},children:B===`set`?`Commit set`:`Commit rotate`}),(V.isError||H.isError)&&(0,A.jsx)(`p`,{role:`alert`,className:`text-sm text-[var(--oke-danger)]`,children:(V.error??H.error)?.message??`Failed`})]}):null]})]}):(0,A.jsx)(`p`,{className:`text-sm text-[var(--oke-muted)]`,children:`Select a contract to inspect fingerprints, resolution, and readers.`})})]})]})}var M=t({default:()=>j});export{y as n,M as t};
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
7
7
  <title>oke Console</title>
8
- <script type="module" crossorigin src="/assets/index-CjxwRGVv.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-ClX0ZCe5.js"></script>
9
9
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-B0Z9INg1.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/style-C8MxEWPd.css">
11
11
  </head>
@@ -58,14 +58,16 @@ export function Input({ className, ...props }: ComponentProps<typeof BaseInput>)
58
58
  /**
59
59
  * Field label + control.
60
60
  *
61
- * @param props - Label text, optional error, children
61
+ * @param props - Label text, optional hint/error, children
62
62
  */
63
63
  export function Field({
64
64
  label,
65
+ hint,
65
66
  error,
66
67
  children,
67
68
  }: {
68
69
  readonly label: string;
70
+ readonly hint?: string;
69
71
  readonly error?: string;
70
72
  readonly children: ReactNode;
71
73
  }) {
@@ -77,6 +79,8 @@ export function Field({
77
79
  <span role="alert" className="text-xs text-[var(--oke-danger)]">
78
80
  {error}
79
81
  </span>
82
+ ) : hint ? (
83
+ <span className="text-xs text-[var(--oke-muted)]">{hint}</span>
80
84
  ) : null}
81
85
  </label>
82
86
  );
@@ -9,6 +9,27 @@ import { consoleCalls, setAccessToken } from "../client.ts";
9
9
  import { OkeLogo } from "../components/oke-logo.tsx";
10
10
  import { Button, Field, Input } from "../components/ui.tsx";
11
11
 
12
+ /** Prefer human message / reason over a bare error code. */
13
+ function clientErrorText(error: {
14
+ readonly code: string;
15
+ readonly message?: string;
16
+ readonly data?: unknown;
17
+ }): string {
18
+ if (typeof error.message === "string" && error.message.trim().length > 0) {
19
+ return error.message;
20
+ }
21
+ if (error.data !== null && typeof error.data === "object") {
22
+ const data = error.data as { message?: unknown; reason?: unknown };
23
+ if (typeof data.message === "string" && data.message.trim().length > 0) {
24
+ return data.message;
25
+ }
26
+ if (error.code === "TransportError" && typeof data.message === "string") {
27
+ return data.message;
28
+ }
29
+ }
30
+ return error.code;
31
+ }
32
+
12
33
  /**
13
34
  * Setup wizard page.
14
35
  */
@@ -18,7 +39,7 @@ export function SetupWizard() {
18
39
  queryKey: ["console.setup.status"],
19
40
  queryFn: async () => {
20
41
  const res = await consoleCalls.setupStatus();
21
- if (res.error) throw new Error(res.error.code);
42
+ if (res.error) throw new Error(clientErrorText(res.error));
22
43
  return res.data as { setupClosed: boolean; claimRequired: boolean };
23
44
  },
24
45
  });
@@ -37,7 +58,7 @@ export function SetupWizard() {
37
58
  name,
38
59
  password,
39
60
  });
40
- if (res.error) throw new Error(res.error.code);
61
+ if (res.error) throw new Error(clientErrorText(res.error));
41
62
  return res.data as { accessToken: string };
42
63
  },
43
64
  onSuccess: (data) => {
@@ -110,13 +131,13 @@ export function SetupWizard() {
110
131
  required
111
132
  />
112
133
  </Field>
113
- <Field label="Password">
134
+ <Field label="Password" hint="At least 12 characters, with a letter and a number.">
114
135
  <Input
115
136
  name="password"
116
137
  type="password"
117
138
  value={password}
118
139
  onValueChange={(v) => setPassword(String(v ?? ""))}
119
- minLength={8}
140
+ minLength={12}
120
141
  autoComplete="new-password"
121
142
  required
122
143
  />
@@ -142,7 +163,7 @@ function LoginForm() {
142
163
  const login = useMutation({
143
164
  mutationFn: async () => {
144
165
  const res = await consoleCalls.sessionLogin({ email, password });
145
- if (res.error) throw new Error(res.error.code);
166
+ if (res.error) throw new Error(clientErrorText(res.error));
146
167
  return res.data as { accessToken: string };
147
168
  },
148
169
  onSuccess: (data) => {
@@ -0,0 +1,193 @@
1
+ /**
2
+ * OKE docker stack discovery / selection helpers.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+ import { mkdtemp } from "node:fs/promises";
7
+ import { tmpdir } from "node:os";
8
+ import { join } from "node:path";
9
+ import {
10
+ composeProjectName,
11
+ downStack,
12
+ isOkeDevProject,
13
+ isOkeProjectRoot,
14
+ listOkeComposeProjects,
15
+ parseJsonRecords,
16
+ projectFromResourceName,
17
+ projectsFromContainerSelection,
18
+ resolveSelection,
19
+ selectionKey,
20
+ type DockerRunner,
21
+ type OkeContainer,
22
+ } from "./cleanup.ts";
23
+ import { stackAppSlug } from "./stack-id.ts";
24
+
25
+ describe("oke docker cleanup helpers", () => {
26
+ test("composeProjectName matches oke-${stackAppSlug}", async () => {
27
+ const dir = await mkdtemp(join(tmpdir(), "oke-clean-id-"));
28
+ expect(composeProjectName(dir)).toBe(`oke-${stackAppSlug(dir)}`);
29
+ expect(isOkeDevProject(composeProjectName(dir))).toBe(true);
30
+ });
31
+
32
+ test("isOkeDevProject accepts only oke-dev-<6hex>", () => {
33
+ expect(isOkeDevProject("oke-dev-a3f791")).toBe(true);
34
+ expect(isOkeDevProject("oke-app")).toBe(false);
35
+ expect(isOkeDevProject("oke-dev-ABCDEF")).toBe(false);
36
+ expect(isOkeDevProject("other-dev-a3f791")).toBe(false);
37
+ });
38
+
39
+ test("projectFromResourceName strips volume/network suffixes", () => {
40
+ expect(projectFromResourceName("oke-dev-a3f791_oke")).toBe("oke-dev-a3f791");
41
+ expect(projectFromResourceName("oke-dev-a3f791_store-sql-data")).toBe("oke-dev-a3f791");
42
+ expect(projectFromResourceName("oke-dev-a3f791")).toBe("oke-dev-a3f791");
43
+ expect(projectFromResourceName("bridge")).toBeNull();
44
+ });
45
+
46
+ test("isOkeProjectRoot detects oke.config.ts", async () => {
47
+ const dir = await mkdtemp(join(tmpdir(), "oke-clean-root-"));
48
+ expect(await isOkeProjectRoot(dir)).toBe(false);
49
+ await Bun.write(join(dir, "oke.config.ts"), "export default {};\n");
50
+ expect(await isOkeProjectRoot(dir)).toBe(true);
51
+ });
52
+
53
+ test("parseJsonRecords handles array and NDJSON", () => {
54
+ expect(parseJsonRecords('[{"Name":"a"},{"Name":"b"}]')).toEqual([{ Name: "a" }, { Name: "b" }]);
55
+ expect(parseJsonRecords('{"Name":"a"}\n{"Name":"b"}\n')).toEqual([
56
+ { Name: "a" },
57
+ { Name: "b" },
58
+ ]);
59
+ expect(parseJsonRecords("")).toEqual([]);
60
+ });
61
+
62
+ test("projectsFromContainerSelection dedupes", () => {
63
+ const containers: OkeContainer[] = [
64
+ {
65
+ id: "1",
66
+ name: "oke-dev-a3f791-store-sql-1",
67
+ service: "store-sql",
68
+ state: "running",
69
+ project: "oke-dev-a3f791",
70
+ },
71
+ {
72
+ id: "2",
73
+ name: "oke-dev-a3f791-store-kv-1",
74
+ service: "store-kv",
75
+ state: "exited",
76
+ project: "oke-dev-a3f791",
77
+ },
78
+ {
79
+ id: "3",
80
+ name: "oke-dev-b0b0b0-store-sql-1",
81
+ service: "store-sql",
82
+ state: "running",
83
+ project: "oke-dev-b0b0b0",
84
+ },
85
+ ];
86
+ expect(projectsFromContainerSelection(containers)).toEqual([
87
+ "oke-dev-a3f791",
88
+ "oke-dev-b0b0b0",
89
+ ]);
90
+ });
91
+
92
+ test("resolveSelection maps keys to projects", () => {
93
+ const stacks = [
94
+ {
95
+ project: "oke-dev-a3f791",
96
+ containers: [
97
+ {
98
+ id: "1",
99
+ name: "c1",
100
+ service: "store-sql",
101
+ state: "running",
102
+ project: "oke-dev-a3f791",
103
+ },
104
+ ],
105
+ },
106
+ { project: "oke-dev-b0b0b0", containers: [] },
107
+ ];
108
+ const { projects, containers } = resolveSelection(
109
+ [selectionKey("oke-dev-a3f791", "c1"), selectionKey("oke-dev-b0b0b0")],
110
+ stacks,
111
+ );
112
+ expect(projects).toEqual(["oke-dev-a3f791", "oke-dev-b0b0b0"]);
113
+ expect(containers).toHaveLength(1);
114
+ expect(containers[0]!.name).toBe("c1");
115
+ });
116
+
117
+ test("listOkeComposeProjects merges compose ls + containers + volumes", async () => {
118
+ const run: DockerRunner = async (args) => {
119
+ const key = args.join(" ");
120
+ if (key.startsWith("compose ls")) {
121
+ return {
122
+ exitCode: 0,
123
+ stdout: JSON.stringify([{ Name: "oke-dev-aaaaaa", Status: "exited(1)" }]),
124
+ stderr: "",
125
+ };
126
+ }
127
+ if (key.includes("label=com.docker.compose.project=") && key.startsWith("ps")) {
128
+ const filter = args[args.indexOf("--filter")! + 1]!;
129
+ const project = filter.replace(/^label=com\.docker\.compose\.project=/, "");
130
+ if (project === "oke-dev-bbbbbb") {
131
+ return {
132
+ exitCode: 0,
133
+ stdout: JSON.stringify({
134
+ ID: "x",
135
+ Names: "oke-dev-bbbbbb-store-sql-1",
136
+ State: "exited",
137
+ Labels:
138
+ "com.docker.compose.project=oke-dev-bbbbbb,com.docker.compose.service=store-sql",
139
+ }),
140
+ stderr: "",
141
+ };
142
+ }
143
+ return { exitCode: 0, stdout: "", stderr: "" };
144
+ }
145
+ if (key.startsWith("ps -a --filter label=com.docker.compose.project --format")) {
146
+ return {
147
+ exitCode: 0,
148
+ stdout: JSON.stringify({
149
+ ID: "x",
150
+ Names: "oke-dev-bbbbbb-store-sql-1",
151
+ State: "exited",
152
+ Labels:
153
+ "com.docker.compose.project=oke-dev-bbbbbb,com.docker.compose.service=store-sql",
154
+ }),
155
+ stderr: "",
156
+ };
157
+ }
158
+ if (key.startsWith("volume ls")) {
159
+ return {
160
+ exitCode: 0,
161
+ stdout: JSON.stringify({ Name: "oke-dev-cccccc_store-files-data" }),
162
+ stderr: "",
163
+ };
164
+ }
165
+ if (key.startsWith("network ls")) {
166
+ return { exitCode: 0, stdout: "", stderr: "" };
167
+ }
168
+ return { exitCode: 1, stdout: "", stderr: `unexpected: ${key}` };
169
+ };
170
+
171
+ const stacks = await listOkeComposeProjects(run);
172
+ expect(stacks.map((s) => s.project)).toEqual([
173
+ "oke-dev-aaaaaa",
174
+ "oke-dev-bbbbbb",
175
+ "oke-dev-cccccc",
176
+ ]);
177
+ expect(stacks.find((s) => s.project === "oke-dev-bbbbbb")!.containers).toHaveLength(1);
178
+ expect(stacks.find((s) => s.project === "oke-dev-cccccc")!.containers).toHaveLength(0);
179
+ });
180
+
181
+ test("downStack refuses non-OKE names and runs down -v", async () => {
182
+ await expect(
183
+ downStack("evil", async () => ({ exitCode: 0, stdout: "", stderr: "" })),
184
+ ).rejects.toThrow(/refusing/);
185
+
186
+ const calls: string[][] = [];
187
+ await downStack("oke-dev-a3f791", async (args) => {
188
+ calls.push([...args]);
189
+ return { exitCode: 0, stdout: "", stderr: "" };
190
+ });
191
+ expect(calls).toEqual([["compose", "-p", "oke-dev-a3f791", "down", "-v", "--remove-orphans"]]);
192
+ });
193
+ });