@w6w/embed 0.2.0 → 0.2.11

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 (119) hide show
  1. package/dist/{ConfirmModal-RLbZT5_k.js → ConfirmModal-BE-SdX-O.js} +53 -49
  2. package/dist/{ConfirmModal-RLbZT5_k.js.map → ConfirmModal-BE-SdX-O.js.map} +1 -1
  3. package/dist/{CreateFunctionModal-DRsFx-FB.js → CreateFunctionModal-D6CQLpa_.js} +25 -25
  4. package/dist/{CreateFunctionModal-DRsFx-FB.js.map → CreateFunctionModal-D6CQLpa_.js.map} +1 -1
  5. package/dist/{DocumentFormModal-BExK1V-B.js → DocumentFormModal-YauVdolr.js} +5 -5
  6. package/dist/{DocumentFormModal-BExK1V-B.js.map → DocumentFormModal-YauVdolr.js.map} +1 -1
  7. package/dist/{ImportSpecModal-BDQIf6rg.js → ImportSpecModal-B7qd1Km2.js} +3 -3
  8. package/dist/{ImportSpecModal-BDQIf6rg.js.map → ImportSpecModal-B7qd1Km2.js.map} +1 -1
  9. package/dist/ModelRoutesManager-BGESQahw.js +345 -0
  10. package/dist/ModelRoutesManager-BGESQahw.js.map +1 -0
  11. package/dist/WorkflowEditor-CwvmAGp2.js +925 -0
  12. package/dist/WorkflowEditor-CwvmAGp2.js.map +1 -0
  13. package/dist/{apps-1FNUwbGv.js → apps-CboASBKr.js} +14 -14
  14. package/dist/{apps-1FNUwbGv.js.map → apps-CboASBKr.js.map} +1 -1
  15. package/dist/{callables-3mFrMVG_.js → callables-tOlflvbl.js} +11 -11
  16. package/dist/{callables-3mFrMVG_.js.map → callables-tOlflvbl.js.map} +1 -1
  17. package/dist/chrome/ConfirmModal.d.ts +4 -1
  18. package/dist/chrome/workspace.d.ts +4 -0
  19. package/dist/{coerce-input-BicYr7nc.js → coerce-input-DttlcSdO.js} +70 -58
  20. package/dist/coerce-input-DttlcSdO.js.map +1 -0
  21. package/dist/connections-D7cgXhDS.js +119 -0
  22. package/dist/connections-D7cgXhDS.js.map +1 -0
  23. package/dist/credentials-DaQU3Ca_.js +171 -0
  24. package/dist/credentials-DaQU3Ca_.js.map +1 -0
  25. package/dist/document-sources-UCwe8x77.js +91 -0
  26. package/dist/document-sources-UCwe8x77.js.map +1 -0
  27. package/dist/draft.mjs +1 -1
  28. package/dist/editor/BindingBanner.d.ts +13 -0
  29. package/dist/editor/CallableEditorFrame.d.ts +7 -0
  30. package/dist/editor/EndpointCards.d.ts +4 -1
  31. package/dist/editor/PublishControl.d.ts +19 -0
  32. package/dist/editor/TargetSelector.d.ts +15 -0
  33. package/dist/editor/TargetSelector.types.d.ts +2 -0
  34. package/dist/editor/definition.d.ts +2 -0
  35. package/dist/{editor-apps-BdenSV1o.js → editor-apps-BUZWld-m.js} +5 -5
  36. package/dist/{editor-apps-BdenSV1o.js.map → editor-apps-BUZWld-m.js.map} +1 -1
  37. package/dist/{editor-tools-RxmY5iyi.js → editor-tools-B_Lfx3kw.js} +11 -11
  38. package/dist/editor-tools-B_Lfx3kw.js.map +1 -0
  39. package/dist/editor.mjs +1 -1
  40. package/dist/editors.mjs +769 -622
  41. package/dist/editors.mjs.map +1 -1
  42. package/dist/{endpoints-B2ynbZo-.js → endpoints-DSRo1Lc5.js} +113 -107
  43. package/dist/endpoints-DSRo1Lc5.js.map +1 -0
  44. package/dist/fields-DvS8XZFc.js +21 -0
  45. package/dist/fields-DvS8XZFc.js.map +1 -0
  46. package/dist/forms/ModelBudgetsManager.d.ts +9 -0
  47. package/dist/forms/ModelRoutesManager.d.ts +14 -0
  48. package/dist/forms.d.ts +4 -0
  49. package/dist/forms.mjs +611 -212
  50. package/dist/forms.mjs.map +1 -1
  51. package/dist/index.mjs +119 -112
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/lib/binding-problems.d.ts +38 -0
  54. package/dist/lib/code-rail.d.ts +4 -2
  55. package/dist/lib/index.d.ts +1 -0
  56. package/dist/lib/invoke-error.d.ts +1 -0
  57. package/dist/lib/sdk-snippets.d.ts +1 -1
  58. package/dist/lib/target-fields.d.ts +8 -0
  59. package/dist/lib/trigger-preview.d.ts +1 -0
  60. package/dist/lib/workflow-live-run.d.ts +9 -2
  61. package/dist/lib/workflow-nodes.d.ts +5 -0
  62. package/dist/lib/workflow-validity.d.ts +1 -0
  63. package/dist/lib.mjs +72 -70
  64. package/dist/lists/ConnectionDependents.d.ts +31 -0
  65. package/dist/lists/ConnectionDetail.d.ts +4 -1
  66. package/dist/lists/ConnectionList.d.ts +4 -1
  67. package/dist/lists/CredentialDetail.d.ts +15 -0
  68. package/dist/lists/CredentialList.d.ts +14 -0
  69. package/dist/lists/ModelCatalog.d.ts +12 -0
  70. package/dist/lists/ModelUsage.d.ts +12 -0
  71. package/dist/lists.d.ts +8 -0
  72. package/dist/lists.mjs +1322 -604
  73. package/dist/lists.mjs.map +1 -1
  74. package/dist/models-bAayQPJ_.js +270 -0
  75. package/dist/models-bAayQPJ_.js.map +1 -0
  76. package/dist/{project-context-BiCjv_E3.js → project-context-Tvp-La7A.js} +3 -3
  77. package/dist/{project-context-BiCjv_E3.js.map → project-context-Tvp-La7A.js.map} +1 -1
  78. package/dist/rail.mjs +4 -4
  79. package/dist/repos/agents-studio-agents.d.ts +52 -0
  80. package/dist/repos/agents-studio-assets.d.ts +68 -0
  81. package/dist/repos/connections.d.ts +30 -12
  82. package/dist/repos/credentials.d.ts +83 -0
  83. package/dist/repos/endpoints.d.ts +9 -3
  84. package/dist/repos/fields.d.ts +34 -0
  85. package/dist/repos/functions.d.ts +7 -5
  86. package/dist/repos/index.d.ts +5 -0
  87. package/dist/repos/models.d.ts +289 -0
  88. package/dist/repos.mjs +613 -176
  89. package/dist/repos.mjs.map +1 -1
  90. package/dist/{slug-C4ktDPdy.js → slug-BVdgiP_L.js} +64 -60
  91. package/dist/slug-BVdgiP_L.js.map +1 -0
  92. package/dist/{spec-export-Cf3VQSQS.js → spec-export-CBbloO_n.js} +7 -7
  93. package/dist/{spec-export-Cf3VQSQS.js.map → spec-export-CBbloO_n.js.map} +1 -1
  94. package/dist/{spec-import-CjmxyZDR.js → spec-import-CW6R_Wk1.js} +160 -156
  95. package/dist/spec-import-CW6R_Wk1.js.map +1 -0
  96. package/dist/theme-context-E2ZhlXDX.js +6 -0
  97. package/dist/theme-context-E2ZhlXDX.js.map +1 -0
  98. package/dist/theme-context.d.ts +2 -0
  99. package/dist/trigger-preview-DKxfjzUY.js +145 -0
  100. package/dist/trigger-preview-DKxfjzUY.js.map +1 -0
  101. package/dist/{use-callable-draft-zHLpcr-b.js → use-callable-draft-DsALnSfF.js} +22 -22
  102. package/dist/{use-callable-draft-zHLpcr-b.js.map → use-callable-draft-DsALnSfF.js.map} +1 -1
  103. package/dist/{workflow-blank-DyL3_RUA.js → workflow-blank-DFpGObrn.js} +6 -6
  104. package/dist/{workflow-blank-DyL3_RUA.js.map → workflow-blank-DFpGObrn.js.map} +1 -1
  105. package/package.json +1 -1
  106. package/src/styles.css +2 -6
  107. package/dist/WorkflowEditor-DlbVv6Fs.js +0 -854
  108. package/dist/WorkflowEditor-DlbVv6Fs.js.map +0 -1
  109. package/dist/coerce-input-BicYr7nc.js.map +0 -1
  110. package/dist/connections-CjjYeRqb.js +0 -78
  111. package/dist/connections-CjjYeRqb.js.map +0 -1
  112. package/dist/document-sources-C0grrtdq.js +0 -86
  113. package/dist/document-sources-C0grrtdq.js.map +0 -1
  114. package/dist/editor-tools-RxmY5iyi.js.map +0 -1
  115. package/dist/endpoints-B2ynbZo-.js.map +0 -1
  116. package/dist/slug-C4ktDPdy.js.map +0 -1
  117. package/dist/spec-import-CjmxyZDR.js.map +0 -1
  118. package/dist/trigger-preview-VPkrryDl.js +0 -120
  119. package/dist/trigger-preview-VPkrryDl.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/embed-status.ts","../src/W6WEmbedProvider.tsx"],"sourcesContent":["/**\n * The embed's public session status, as a pure total function over the `@w6w/react` session\n * store's status plus whether a terminal partner-token 401 has been seen. No React here, so\n * `node:test` covers it exhaustively.\n */\nimport type { W6WSessionStatus } from \"@w6w/react\";\n\nexport type EmbedStatusValue = \"connecting\" | \"ready\" | \"error\";\n\nexport interface EmbedStatus {\n status: EmbedStatusValue;\n /** `EmbedAuthError` for a terminal 401, else the session store's own error; `null` otherwise. */\n error: unknown;\n}\n\n/**\n * The terminal partner-token 401: the host's `getSession` minted a token the API refused, and a\n * renewal did not fix it. `cause` is the SDK `ApiError`.\n */\nexport class EmbedAuthError extends Error {\n constructor(cause: unknown) {\n super(\"The w6w API rejected the embed session token (401).\", { cause });\n this.name = \"EmbedAuthError\";\n }\n}\n\n/**\n * `loading -> connecting`, `ready|renewing -> ready`, `expired -> connecting` (the provider\n * re-acquires), `error -> error`. A seen 401 wins over everything: it is `error` with the\n * `EmbedAuthError`, whatever the store currently says.\n */\nexport function deriveEmbedStatus(\n sessionStatus: W6WSessionStatus,\n sessionError: unknown,\n authError: EmbedAuthError | null,\n): EmbedStatus {\n if (authError) return { status: \"error\", error: authError };\n switch (sessionStatus) {\n case \"ready\":\n case \"renewing\":\n return { status: \"ready\", error: null };\n case \"error\":\n return { status: \"error\", error: sessionError };\n case \"loading\":\n case \"expired\":\n return { status: \"connecting\", error: null };\n }\n}\n","import { QueryClient, QueryClientProvider, useQuery } from \"@tanstack/react-query\";\n/**\n * `<W6WEmbedProvider>` — everything an embedded w6w surface needs from a host, behind one\n * element: an identity-scoped `QueryClient`, a `@w6w/react` `<W6WProvider>` (client, session\n * renewal, per-request token) and `@w6w/ui`'s `<W6WUIProvider>` fed by `createW6WUiAdapter`.\n * It composes the three public pieces exactly as `@w6w/react`'s README bridge does: it never\n * spreads or patches the adapter, never reaches into `client.console`, and keeps no session\n * store of its own (`getSession` goes straight to `<W6WProvider>`).\n *\n * **Identity cache.** The `QueryClient` is owned here, not borrowed from the host, and it is a\n * NEW instance whenever `identityKey` changes — so a query cached while signed in as account A\n * is unreachable once the host switches to B. A new client alone is NOT enough: a mounted\n * `useQuery` keeps the `QueryObserver` it was born with, and that observer is bound to the client\n * it was created against, so a child that survives the swap would keep rendering A's cache. The\n * subtree is therefore also re-mounted (`key`), which drops every observer and every piece of\n * child state from the previous identity. The client, the `key` and the tuple handed to\n * `<W6WProvider>` all change in ONE state update: there is no render in which B's tree reads A's\n * cache. The old client is cleared once it is no longer mounted.\n *\n * **Identity switch (flush first).** A draft with a pending save must be written into the account\n * that produced the edit. When `identityKey` changes this provider therefore HOLDS the applied\n * tuple — `identityKey`, `apiOrigin`, `project`, `getSession`, the client — and keeps handing the\n * OLD one to `<W6WProvider>`, awaits `registry.flushAll()` (bounded, never rejects), and only then\n * applies the new tuple in a single update. `<W6WProvider>` swaps its client synchronously on a\n * new `identityKey` and detaches the old session store, so the flush must finish first; and the\n * new `getSession` is NOT forwarded early: `<W6WProvider>` reaches it through the stable wrapper\n * below, whose target is swapped in the same update as the tuple (forwarded early, the new\n * account's token would be minted on the old client). A flush that fails or times out still lets\n * the switch proceed (Q6) and is never retried with the new identity. A token rotation under an\n * unchanged `identityKey` is not a switch: it is forwarded at once, no hold.\n *\n * **No identity.** `identityKey={null}` mounts nothing but `fallback`: no `<W6WProvider>`, no\n * `QueryClientProvider`, no children — so no `getSession` call and no request. `null -> \"A\"`\n * applies at once (nothing can be pending); `\"A\" -> null` takes the SAME flush-first path as any\n * other switch before the fallback renders.\n *\n * **Default project.** `project={{ use: \"default\" }}` resolves ONCE per applied identity, through\n * one `client.projects.list()` query inside the identity-scoped `QueryClient`, to the row with\n * `isDefault === true` — never `list[0]`, never a fallback. `<W6WProvider>` gets no project until\n * it resolves; the client rebuild that follows reuses the cached answer (the query is keyed\n * without the client and lives in a component that stays mounted, so it is not re-issued).\n *\n * **Status.** `useEmbedStatus()` is `deriveEmbedStatus` over the `@w6w/react` session store plus a\n * terminal 401 seen through the forwarded `onUnauthorized`.\n */\nimport {\n W6WProvider,\n type W6WSession,\n createW6WUiAdapter,\n useW6WClient,\n useW6WSession,\n} from \"@w6w/react\";\nimport type { ApiError, FetchLike } from \"@w6w/sdk\";\nimport { type ThemeMode, type W6WApi, W6WUIProvider } from \"@w6w/ui\";\nimport {\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { DraftRegistryProvider, EmbedClientProvider, createDraftRegistry } from \"./draft/index.ts\";\nimport { EmbedAuthError, type EmbedStatus, deriveEmbedStatus } from \"./embed-status.ts\";\nimport { EmbedProjectContext, type EmbedProjectState } from \"./project-context.ts\";\nimport { updateConnection } from \"./repos/connections.ts\";\n\nexport interface W6WEmbedProviderProps {\n /** The w6w API origin, e.g. `\"https://api.w6w.io\"`. */\n apiOrigin: string;\n /**\n * Mints a session for the CURRENT host user (`{token, expiresAt, expiresIn?}`). Always the\n * latest callback; the provider caches and renews the result.\n */\n getSession: () => Promise<W6WSession>;\n /**\n * Which signed-in identity this provider speaks for (e.g. `${userId}:${accountId}`). Changing it\n * rebuilds the API client AND replaces the `QueryClient`, so nothing cached for the previous\n * identity is ever shown under the new one.\n */\n identityKey: string | null;\n /**\n * Rendered instead of the embed while `identityKey` is `null` (no signed-in user). Nothing of\n * the embed mounts then: no `getSession` call, no request. Default `null`.\n */\n fallback?: ReactNode;\n /**\n * Start acquiring a session on mount. Without it the session is acquired lazily, by the first\n * request a mounted surface makes, and `useEmbedStatus()` stays `\"connecting\"` until then.\n */\n eager?: boolean;\n /** Force the `@w6w/ui` theme to follow the host's. Omit to resolve it the library's default way. */\n theme?: ThemeMode;\n /** Gates every read hook while `false` (default `true`) — e.g. until the host has a user. */\n ready?: boolean;\n /**\n * Default project for project-scoped operations: a project id, or `{ use: \"default\" }` to use\n * the account's default project (resolved once per identity; see `useEmbedProject()`).\n */\n project?: string | { use: \"default\" };\n /** Transport override (tests, request recording). Defaults to `globalThis.fetch`. */\n fetch?: FetchLike;\n children: ReactNode;\n}\n\nfunction makeQueryClient(): QueryClient {\n // Same defaults as Studio's own client (`studio/src/main.tsx`).\n return new QueryClient({\n defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },\n });\n}\n\n/** The part of the tuple that changes only when a switch has been APPLIED (after the flush). */\ninterface Applied {\n identityKey: string | null;\n queryClient: QueryClient;\n}\n\n/** What `<W6WProvider>` is fed while no switch is in progress; frozen at the last such render. */\ninterface Forwarded {\n apiOrigin: string;\n project: string | { use: \"default\" } | undefined;\n getSession: () => Promise<W6WSession>;\n}\n\n/** Hands the SDK client of the nearest `<W6WProvider>` to `useWorkflowDraft`. */\nfunction ClientBridge({ children }: { children: ReactNode }) {\n return <EmbedClientProvider client={useW6WClient()}>{children}</EmbedClientProvider>;\n}\n\n/** The README bridge: `useW6WClient` -> `createW6WUiAdapter` -> `<W6WUIProvider>`. */\nfunction UiBridge({ theme, children }: { theme?: ThemeMode; children: ReactNode }) {\n const client = useW6WClient();\n // `createW6WUiAdapter` has no `updateConnection`; keep one if it ever gains it, else supply the\n // embed repo's write so the ui Edit modal can save.\n const api = useMemo(() => {\n const base: W6WApi = createW6WUiAdapter(client);\n if (typeof base.updateConnection === \"function\") return base;\n return { ...base, updateConnection: (id, body) => updateConnection(client, id, body) };\n }, [client]);\n return (\n <W6WUIProvider api={api} theme={theme}>\n {children}\n </W6WUIProvider>\n );\n}\n\nconst EmbedStatusContext = createContext<EmbedStatus>({ status: \"connecting\", error: null });\n\n/** The session status of the nearest `<W6WEmbedProvider>`. See `deriveEmbedStatus`. */\nexport function useEmbedStatus(): EmbedStatus {\n return useContext(EmbedStatusContext);\n}\n\n/** Publishes `useEmbedStatus()`, and starts the session on mount when `eager`. */\nfunction StatusBridge({\n eager,\n authError,\n onAcquire,\n children,\n}: {\n eager: boolean;\n authError: EmbedAuthError | null;\n onAcquire: () => void;\n children: ReactNode;\n}) {\n const { status, error, refresh } = useW6WSession();\n // `refresh` is per session store, so a rebuilt client (project resolved) is started again.\n useEffect(() => {\n if (eager) void refresh();\n }, [eager, refresh]);\n useEffect(() => {\n if (status === \"loading\" || status === \"renewing\") onAcquire();\n }, [status, onAcquire]);\n const value = useMemo(\n () => deriveEmbedStatus(status, error, authError),\n [status, error, authError],\n );\n return <EmbedStatusContext.Provider value={value}>{children}</EmbedStatusContext.Provider>;\n}\n\n/**\n * Resolves `{use:\"default\"}`. Lives INSIDE `<W6WProvider>` (it needs the client) but at a fixed\n * slot, so it survives the client rebuild that follows resolution; the query key carries no\n * client, so nothing refetches.\n */\nfunction DefaultProjectResolver({\n identityKey,\n enabled,\n onState,\n}: {\n identityKey: string;\n enabled: boolean;\n onState: (key: string, state: EmbedProjectState) => void;\n}) {\n const client = useW6WClient();\n const q = useQuery({\n queryKey: [\"w6w-embed\", \"default-project\"],\n enabled,\n queryFn: async () => {\n const rows = await client.projects.list();\n const home = rows.find((p) => p.isDefault === true);\n if (!home) throw new Error(\"The account has no default project.\");\n return home.id;\n },\n });\n const { isError, error, data } = q;\n const state = useMemo<EmbedProjectState>(\n () =>\n isError\n ? { project: null, status: \"error\", error }\n : data !== undefined\n ? { project: data, status: \"ready\" }\n : { project: null, status: \"resolving\" },\n [isError, error, data],\n );\n useEffect(() => {\n onState(identityKey, state);\n }, [identityKey, state, onState]);\n return null;\n}\n\nexport function W6WEmbedProvider({\n apiOrigin,\n getSession,\n identityKey,\n fallback = null,\n eager = false,\n theme,\n ready,\n project,\n fetch,\n children,\n}: W6WEmbedProviderProps): ReactNode {\n const [registry] = useState(createDraftRegistry);\n const [applied, setApplied] = useState<Applied>(() => ({\n identityKey,\n queryClient: makeQueryClient(),\n }));\n\n // While `identityKey` differs from the applied one a switch is pending: everything below keeps\n // using the values frozen at the last render that was not pending. Otherwise props flow straight\n // through (project / origin changes, token rotation). Idempotent latest-value writes, the same\n // pattern `<W6WProvider>` uses for its own refs.\n const switching = identityKey !== applied.identityKey;\n const forwardedRef = useRef<Forwarded>({ apiOrigin, project, getSession });\n if (!switching) forwardedRef.current = { apiOrigin, project, getSession };\n const forwarded = forwardedRef.current;\n\n // The stable `getSession` handed to `<W6WProvider>`: reads whatever is applied RIGHT NOW. Its\n // target changes in the same render that applies the new tuple, never before the flush settles.\n const sessionRef = useRef(forwarded.getSession);\n sessionRef.current = forwarded.getSession;\n const [stableGetSession] = useState(() => () => sessionRef.current());\n\n useEffect(() => {\n if (identityKey === applied.identityKey) return;\n let cancelled = false;\n const apply = () => {\n if (cancelled) return;\n setApplied({ identityKey, queryClient: makeQueryClient() });\n };\n // Nothing is mounted under a null identity, so nothing can be pending: apply at once.\n if (applied.identityKey === null) {\n apply();\n return () => {\n cancelled = true;\n };\n }\n // `flushAll` never rejects and is bounded; the switch proceeds either way (Q6).\n registry.flushAll().then(apply, apply);\n return () => {\n cancelled = true;\n };\n }, [identityKey, applied.identityKey, registry]);\n\n // The replaced client is dropped once nothing mounted reads it.\n const queryClient = applied.queryClient;\n useEffect(() => () => queryClient.clear(), [queryClient]);\n\n // Default-project resolution, tagged with the identity it was resolved for: a result for A is\n // never read once B is applied.\n const [resolved, setResolved] = useState<{ key: string; state: EmbedProjectState } | null>(null);\n const onResolved = useCallback((key: string, state: EmbedProjectState) => {\n setResolved((prev) =>\n prev &&\n prev.key === key &&\n prev.state.project === state.project &&\n prev.state.status === state.status &&\n prev.state.error === state.error\n ? prev\n : { key, state },\n );\n }, []);\n\n // The terminal partner-token 401, tagged with its identity; cleared when the next acquisition\n // starts (StatusBridge) or the identity changes (the tag no longer matches).\n const [authFailure, setAuthFailure] = useState<{\n key: QueryClient;\n error: EmbedAuthError;\n } | null>(null);\n // The handler is bound to the per-mount client it was created for: a late 401 from a previous\n // `<W6WProvider>` is tagged with ITS client, never the one applied by the time it fires — even\n // when the identity key came back (A -> B -> A mints a new client for the same key).\n const onUnauthorized = useMemo(() => {\n const key = applied.queryClient;\n return (error: ApiError) => {\n setAuthFailure({ key, error: new EmbedAuthError(error) });\n };\n }, [applied.queryClient]);\n const clearAuthFailure = useCallback(() => setAuthFailure(null), []);\n\n const appliedKey = applied.identityKey;\n const spec = forwarded.project;\n // Only exactly `{ use: \"default\" }` asks for the account default; null, `{}`, `[]` or any other\n // object (JS hosts, casts) is \"no project\" and makes no lookup.\n const wantsDefault =\n typeof spec === \"object\" && spec !== null && !Array.isArray(spec) && spec.use === \"default\";\n const projectState: EmbedProjectState = useMemo(() => {\n if (typeof spec === \"string\") return { project: spec, status: \"ready\" };\n if (!wantsDefault) return { project: null, status: \"ready\" };\n return resolved && resolved.key === appliedKey\n ? resolved.state\n : { project: null, status: \"resolving\" };\n }, [spec, wantsDefault, resolved, appliedKey]);\n\n if (appliedKey === null) return fallback;\n\n return (\n <DraftRegistryProvider registry={registry}>\n <QueryClientProvider key={appliedKey} client={queryClient}>\n <W6WProvider\n baseUrl={forwarded.apiOrigin}\n getSession={stableGetSession}\n identityKey={appliedKey}\n ready={ready}\n project={projectState.project ?? undefined}\n fetch={fetch}\n onUnauthorized={onUnauthorized}\n >\n {wantsDefault ? (\n <DefaultProjectResolver\n identityKey={appliedKey}\n enabled={ready !== false}\n onState={onResolved}\n />\n ) : null}\n <EmbedProjectContext.Provider value={projectState}>\n <StatusBridge\n eager={eager}\n authError={authFailure && authFailure.key === queryClient ? authFailure.error : null}\n onAcquire={clearAuthFailure}\n >\n <ClientBridge>\n <UiBridge theme={theme}>{children}</UiBridge>\n </ClientBridge>\n </StatusBridge>\n </EmbedProjectContext.Provider>\n </W6WProvider>\n </QueryClientProvider>\n </DraftRegistryProvider>\n );\n}\n"],"names":["EmbedAuthError","cause","deriveEmbedStatus","sessionStatus","sessionError","authError","makeQueryClient","QueryClient","ClientBridge","children","jsx","EmbedClientProvider","useW6WClient","UiBridge","theme","client","api","useMemo","base","createW6WUiAdapter","id","body","updateConnection","W6WUIProvider","EmbedStatusContext","createContext","useEmbedStatus","useContext","StatusBridge","eager","onAcquire","status","error","refresh","useW6WSession","useEffect","value","DefaultProjectResolver","identityKey","enabled","onState","q","useQuery","home","p","isError","data","state","W6WEmbedProvider","apiOrigin","getSession","fallback","ready","project","fetch","registry","useState","createDraftRegistry","applied","setApplied","switching","forwardedRef","useRef","forwarded","sessionRef","stableGetSession","cancelled","apply","queryClient","resolved","setResolved","onResolved","useCallback","key","prev","authFailure","setAuthFailure","onUnauthorized","clearAuthFailure","appliedKey","spec","wantsDefault","projectState","DraftRegistryProvider","QueryClientProvider","jsxs","W6WProvider","EmbedProjectContext"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/embed-status.ts","../src/W6WEmbedProvider.tsx"],"sourcesContent":["/**\n * The embed's public session status, as a pure total function over the `@w6w/react` session\n * store's status plus whether a terminal partner-token 401 has been seen. No React here, so\n * `node:test` covers it exhaustively.\n */\nimport type { W6WSessionStatus } from \"@w6w/react\";\n\nexport type EmbedStatusValue = \"connecting\" | \"ready\" | \"error\";\n\nexport interface EmbedStatus {\n status: EmbedStatusValue;\n /** `EmbedAuthError` for a terminal 401, else the session store's own error; `null` otherwise. */\n error: unknown;\n}\n\n/**\n * The terminal partner-token 401: the host's `getSession` minted a token the API refused, and a\n * renewal did not fix it. `cause` is the SDK `ApiError`.\n */\nexport class EmbedAuthError extends Error {\n constructor(cause: unknown) {\n super(\"The w6w API rejected the embed session token (401).\", { cause });\n this.name = \"EmbedAuthError\";\n }\n}\n\n/**\n * `loading -> connecting`, `ready|renewing -> ready`, `expired -> connecting` (the provider\n * re-acquires), `error -> error`. A seen 401 wins over everything: it is `error` with the\n * `EmbedAuthError`, whatever the store currently says.\n */\nexport function deriveEmbedStatus(\n sessionStatus: W6WSessionStatus,\n sessionError: unknown,\n authError: EmbedAuthError | null,\n): EmbedStatus {\n if (authError) return { status: \"error\", error: authError };\n switch (sessionStatus) {\n case \"ready\":\n case \"renewing\":\n return { status: \"ready\", error: null };\n case \"error\":\n return { status: \"error\", error: sessionError };\n case \"loading\":\n case \"expired\":\n return { status: \"connecting\", error: null };\n }\n}\n","import { QueryClient, QueryClientProvider, useQuery } from \"@tanstack/react-query\";\n/**\n * `<W6WEmbedProvider>` — everything an embedded w6w surface needs from a host, behind one\n * element: an identity-scoped `QueryClient`, a `@w6w/react` `<W6WProvider>` (client, session\n * renewal, per-request token) and `@w6w/ui`'s `<W6WUIProvider>` fed by `createW6WUiAdapter`.\n * It composes the three public pieces exactly as `@w6w/react`'s README bridge does: it never\n * spreads or patches the adapter, never reaches into `client.console`, and keeps no session\n * store of its own (`getSession` goes straight to `<W6WProvider>`).\n *\n * **Identity cache.** The `QueryClient` is owned here, not borrowed from the host, and it is a\n * NEW instance whenever `identityKey` changes — so a query cached while signed in as account A\n * is unreachable once the host switches to B. A new client alone is NOT enough: a mounted\n * `useQuery` keeps the `QueryObserver` it was born with, and that observer is bound to the client\n * it was created against, so a child that survives the swap would keep rendering A's cache. The\n * subtree is therefore also re-mounted (`key`), which drops every observer and every piece of\n * child state from the previous identity. The client, the `key` and the tuple handed to\n * `<W6WProvider>` all change in ONE state update: there is no render in which B's tree reads A's\n * cache. The old client is cleared once it is no longer mounted.\n *\n * **Identity switch (flush first).** A draft with a pending save must be written into the account\n * that produced the edit. When `identityKey` changes this provider therefore HOLDS the applied\n * tuple — `identityKey`, `apiOrigin`, `project`, `getSession`, the client — and keeps handing the\n * OLD one to `<W6WProvider>`, awaits `registry.flushAll()` (bounded, never rejects), and only then\n * applies the new tuple in a single update. `<W6WProvider>` swaps its client synchronously on a\n * new `identityKey` and detaches the old session store, so the flush must finish first; and the\n * new `getSession` is NOT forwarded early: `<W6WProvider>` reaches it through the stable wrapper\n * below, whose target is swapped in the same update as the tuple (forwarded early, the new\n * account's token would be minted on the old client). A flush that fails or times out still lets\n * the switch proceed (Q6) and is never retried with the new identity. A token rotation under an\n * unchanged `identityKey` is not a switch: it is forwarded at once, no hold.\n *\n * **No identity.** `identityKey={null}` mounts nothing but `fallback`: no `<W6WProvider>`, no\n * `QueryClientProvider`, no children — so no `getSession` call and no request. `null -> \"A\"`\n * applies at once (nothing can be pending); `\"A\" -> null` takes the SAME flush-first path as any\n * other switch before the fallback renders.\n *\n * **Default project.** `project={{ use: \"default\" }}` resolves ONCE per applied identity, through\n * one `client.projects.list()` query inside the identity-scoped `QueryClient`, to the row with\n * `isDefault === true` — never `list[0]`, never a fallback. `<W6WProvider>` gets no project until\n * it resolves; the client rebuild that follows reuses the cached answer (the query is keyed\n * without the client and lives in a component that stays mounted, so it is not re-issued).\n *\n * **Status.** `useEmbedStatus()` is `deriveEmbedStatus` over the `@w6w/react` session store plus a\n * terminal 401 seen through the forwarded `onUnauthorized`.\n */\nimport {\n W6WProvider,\n type W6WSession,\n createW6WUiAdapter,\n useW6WClient,\n useW6WSession,\n} from \"@w6w/react\";\nimport type { ApiError, FetchLike } from \"@w6w/sdk\";\nimport { type ThemeMode, type W6WApi, W6WUIProvider } from \"@w6w/ui\";\nimport {\n type ReactNode,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { DraftRegistryProvider, EmbedClientProvider, createDraftRegistry } from \"./draft/index.ts\";\nimport { EmbedAuthError, type EmbedStatus, deriveEmbedStatus } from \"./embed-status.ts\";\nimport {\n EmbedProjectContext,\n type EmbedProjectState,\n useProvidedProject,\n} from \"./project-context.ts\";\nimport { updateConnection } from \"./repos/connections.ts\";\nimport { withCredentialMethods } from \"./repos/credentials.ts\";\nimport { resolveActionFields } from \"./repos/fields.ts\";\nimport { listModelRoutes } from \"./repos/models.ts\";\nimport { EmbedThemeContext } from \"./theme-context.ts\";\n\nexport interface W6WEmbedProviderProps {\n /** The w6w API origin, e.g. `\"https://api.w6w.io\"`. */\n apiOrigin: string;\n /**\n * Mints a session for the CURRENT host user (`{token, expiresAt, expiresIn?}`). Always the\n * latest callback; the provider caches and renews the result.\n */\n getSession: () => Promise<W6WSession>;\n /**\n * Which signed-in identity this provider speaks for (e.g. `${userId}:${accountId}`). Changing it\n * rebuilds the API client AND replaces the `QueryClient`, so nothing cached for the previous\n * identity is ever shown under the new one.\n */\n identityKey: string | null;\n /**\n * Rendered instead of the embed while `identityKey` is `null` (no signed-in user). Nothing of\n * the embed mounts then: no `getSession` call, no request. Default `null`.\n */\n fallback?: ReactNode;\n /**\n * Start acquiring a session on mount. Without it the session is acquired lazily, by the first\n * request a mounted surface makes, and `useEmbedStatus()` stays `\"connecting\"` until then.\n */\n eager?: boolean;\n /** Force the `@w6w/ui` theme to follow the host's. Omit to resolve it the library's default way. */\n theme?: ThemeMode;\n /** Gates every read hook while `false` (default `true`) — e.g. until the host has a user. */\n ready?: boolean;\n /**\n * Default project for project-scoped operations: a project id, or `{ use: \"default\" }` to use\n * the account's default project (resolved once per identity; see `useEmbedProject()`).\n */\n project?: string | { use: \"default\" };\n /** Transport override (tests, request recording). Defaults to `globalThis.fetch`. */\n fetch?: FetchLike;\n children: ReactNode;\n}\n\nfunction makeQueryClient(): QueryClient {\n // Same defaults as Studio's own client (`studio/src/main.tsx`).\n return new QueryClient({\n defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } },\n });\n}\n\n/** The part of the tuple that changes only when a switch has been APPLIED (after the flush). */\ninterface Applied {\n identityKey: string | null;\n queryClient: QueryClient;\n}\n\n/** What `<W6WProvider>` is fed while no switch is in progress; frozen at the last such render. */\ninterface Forwarded {\n apiOrigin: string;\n project: string | { use: \"default\" } | undefined;\n getSession: () => Promise<W6WSession>;\n}\n\n/** Hands the SDK client of the nearest `<W6WProvider>` to `useWorkflowDraft`. */\nfunction ClientBridge({ children }: { children: ReactNode }) {\n return <EmbedClientProvider client={useW6WClient()}>{children}</EmbedClientProvider>;\n}\n\n/** The README bridge: `useW6WClient` -> `createW6WUiAdapter` -> `<W6WUIProvider>`. */\nfunction UiBridge({ theme, children }: { theme?: ThemeMode; children: ReactNode }) {\n const client = useW6WClient();\n const provided = useProvidedProject();\n // `createW6WUiAdapter` has no `updateConnection` or `listModelRoutes`; keep them if it ever\n // gains them, else supply the embed repo's own so the ui Edit modal can save and the\n // `@w6w/model` node's Route field offers the project's routes (not free text) in any host.\n const api = useMemo(() => {\n const adapter: W6WApi = createW6WUiAdapter(client);\n if (typeof adapter.updateConnection !== \"function\") {\n adapter.updateConnection = (id, body) => updateConnection(client, id, body);\n }\n withCredentialMethods(adapter, client);\n if (typeof adapter.listModelRoutes !== \"function\") {\n adapter.listModelRoutes = async (editorProject) => {\n const project = editorProject || provided;\n if (!project) return [];\n const routes = await listModelRoutes(client, project);\n return routes.map((r) => ({ name: r.name, model: r.modelId, status: r.status }));\n };\n }\n if (typeof adapter.resolveActionFields !== \"function\") {\n adapter.resolveActionFields = (appId, actionKey, body, opts) =>\n resolveActionFields(client, appId, actionKey, body, opts);\n }\n return adapter;\n }, [client, provided]);\n return (\n <W6WUIProvider api={api} theme={theme}>\n <EmbedThemeContext.Provider value={theme}>{children}</EmbedThemeContext.Provider>\n </W6WUIProvider>\n );\n}\n\nconst EmbedStatusContext = createContext<EmbedStatus>({ status: \"connecting\", error: null });\n\n/** The session status of the nearest `<W6WEmbedProvider>`. See `deriveEmbedStatus`. */\nexport function useEmbedStatus(): EmbedStatus {\n return useContext(EmbedStatusContext);\n}\n\n/** Publishes `useEmbedStatus()`, and starts the session on mount when `eager`. */\nfunction StatusBridge({\n eager,\n authError,\n onAcquire,\n children,\n}: {\n eager: boolean;\n authError: EmbedAuthError | null;\n onAcquire: () => void;\n children: ReactNode;\n}) {\n const { status, error, refresh } = useW6WSession();\n // `refresh` is per session store, so a rebuilt client (project resolved) is started again.\n useEffect(() => {\n if (eager) void refresh();\n }, [eager, refresh]);\n useEffect(() => {\n if (status === \"loading\" || status === \"renewing\") onAcquire();\n }, [status, onAcquire]);\n const value = useMemo(\n () => deriveEmbedStatus(status, error, authError),\n [status, error, authError],\n );\n return <EmbedStatusContext.Provider value={value}>{children}</EmbedStatusContext.Provider>;\n}\n\n/**\n * Resolves `{use:\"default\"}`. Lives INSIDE `<W6WProvider>` (it needs the client) but at a fixed\n * slot, so it survives the client rebuild that follows resolution; the query key carries no\n * client, so nothing refetches.\n */\nfunction DefaultProjectResolver({\n identityKey,\n enabled,\n onState,\n}: {\n identityKey: string;\n enabled: boolean;\n onState: (key: string, state: EmbedProjectState) => void;\n}) {\n const client = useW6WClient();\n const q = useQuery({\n queryKey: [\"w6w-embed\", \"default-project\"],\n enabled,\n queryFn: async () => {\n const rows = await client.projects.list();\n const home = rows.find((p) => p.isDefault === true);\n if (!home) throw new Error(\"The account has no default project.\");\n return home.id;\n },\n });\n const { isError, error, data } = q;\n const state = useMemo<EmbedProjectState>(\n () =>\n isError\n ? { project: null, status: \"error\", error }\n : data !== undefined\n ? { project: data, status: \"ready\" }\n : { project: null, status: \"resolving\" },\n [isError, error, data],\n );\n useEffect(() => {\n onState(identityKey, state);\n }, [identityKey, state, onState]);\n return null;\n}\n\nexport function W6WEmbedProvider({\n apiOrigin,\n getSession,\n identityKey,\n fallback = null,\n eager = false,\n theme,\n ready,\n project,\n fetch,\n children,\n}: W6WEmbedProviderProps): ReactNode {\n const [registry] = useState(createDraftRegistry);\n const [applied, setApplied] = useState<Applied>(() => ({\n identityKey,\n queryClient: makeQueryClient(),\n }));\n\n // While `identityKey` differs from the applied one a switch is pending: everything below keeps\n // using the values frozen at the last render that was not pending. Otherwise props flow straight\n // through (project / origin changes, token rotation). Idempotent latest-value writes, the same\n // pattern `<W6WProvider>` uses for its own refs.\n const switching = identityKey !== applied.identityKey;\n const forwardedRef = useRef<Forwarded>({ apiOrigin, project, getSession });\n if (!switching) forwardedRef.current = { apiOrigin, project, getSession };\n const forwarded = forwardedRef.current;\n\n // The stable `getSession` handed to `<W6WProvider>`: reads whatever is applied RIGHT NOW. Its\n // target changes in the same render that applies the new tuple, never before the flush settles.\n const sessionRef = useRef(forwarded.getSession);\n sessionRef.current = forwarded.getSession;\n const [stableGetSession] = useState(() => () => sessionRef.current());\n\n useEffect(() => {\n if (identityKey === applied.identityKey) return;\n let cancelled = false;\n const apply = () => {\n if (cancelled) return;\n setApplied({ identityKey, queryClient: makeQueryClient() });\n };\n // Nothing is mounted under a null identity, so nothing can be pending: apply at once.\n if (applied.identityKey === null) {\n apply();\n return () => {\n cancelled = true;\n };\n }\n // `flushAll` never rejects and is bounded; the switch proceeds either way (Q6).\n registry.flushAll().then(apply, apply);\n return () => {\n cancelled = true;\n };\n }, [identityKey, applied.identityKey, registry]);\n\n // The replaced client is dropped once nothing mounted reads it.\n const queryClient = applied.queryClient;\n useEffect(() => () => queryClient.clear(), [queryClient]);\n\n // Default-project resolution, tagged with the identity it was resolved for: a result for A is\n // never read once B is applied.\n const [resolved, setResolved] = useState<{ key: string; state: EmbedProjectState } | null>(null);\n const onResolved = useCallback((key: string, state: EmbedProjectState) => {\n setResolved((prev) =>\n prev &&\n prev.key === key &&\n prev.state.project === state.project &&\n prev.state.status === state.status &&\n prev.state.error === state.error\n ? prev\n : { key, state },\n );\n }, []);\n\n // The terminal partner-token 401, tagged with its identity; cleared when the next acquisition\n // starts (StatusBridge) or the identity changes (the tag no longer matches).\n const [authFailure, setAuthFailure] = useState<{\n key: QueryClient;\n error: EmbedAuthError;\n } | null>(null);\n // The handler is bound to the per-mount client it was created for: a late 401 from a previous\n // `<W6WProvider>` is tagged with ITS client, never the one applied by the time it fires — even\n // when the identity key came back (A -> B -> A mints a new client for the same key).\n const onUnauthorized = useMemo(() => {\n const key = applied.queryClient;\n return (error: ApiError) => {\n setAuthFailure({ key, error: new EmbedAuthError(error) });\n };\n }, [applied.queryClient]);\n const clearAuthFailure = useCallback(() => setAuthFailure(null), []);\n\n const appliedKey = applied.identityKey;\n const spec = forwarded.project;\n // Only exactly `{ use: \"default\" }` asks for the account default; null, `{}`, `[]` or any other\n // object (JS hosts, casts) is \"no project\" and makes no lookup.\n const wantsDefault =\n typeof spec === \"object\" && spec !== null && !Array.isArray(spec) && spec.use === \"default\";\n const projectState: EmbedProjectState = useMemo(() => {\n if (typeof spec === \"string\") return { project: spec, status: \"ready\" };\n if (!wantsDefault) return { project: null, status: \"ready\" };\n return resolved && resolved.key === appliedKey\n ? resolved.state\n : { project: null, status: \"resolving\" };\n }, [spec, wantsDefault, resolved, appliedKey]);\n\n if (appliedKey === null) return fallback;\n\n return (\n <DraftRegistryProvider registry={registry}>\n <QueryClientProvider key={appliedKey} client={queryClient}>\n <W6WProvider\n baseUrl={forwarded.apiOrigin}\n getSession={stableGetSession}\n identityKey={appliedKey}\n ready={ready}\n project={projectState.project ?? undefined}\n fetch={fetch}\n onUnauthorized={onUnauthorized}\n >\n {wantsDefault ? (\n <DefaultProjectResolver\n identityKey={appliedKey}\n enabled={ready !== false}\n onState={onResolved}\n />\n ) : null}\n <EmbedProjectContext.Provider value={projectState}>\n <StatusBridge\n eager={eager}\n authError={authFailure && authFailure.key === queryClient ? authFailure.error : null}\n onAcquire={clearAuthFailure}\n >\n <ClientBridge>\n <UiBridge theme={theme}>{children}</UiBridge>\n </ClientBridge>\n </StatusBridge>\n </EmbedProjectContext.Provider>\n </W6WProvider>\n </QueryClientProvider>\n </DraftRegistryProvider>\n );\n}\n"],"names":["EmbedAuthError","cause","deriveEmbedStatus","sessionStatus","sessionError","authError","makeQueryClient","QueryClient","ClientBridge","children","jsx","EmbedClientProvider","useW6WClient","UiBridge","theme","client","provided","useProvidedProject","api","useMemo","adapter","createW6WUiAdapter","id","body","updateConnection","withCredentialMethods","editorProject","project","listModelRoutes","r","appId","actionKey","opts","resolveActionFields","W6WUIProvider","EmbedThemeContext","EmbedStatusContext","createContext","useEmbedStatus","useContext","StatusBridge","eager","onAcquire","status","error","refresh","useW6WSession","useEffect","value","DefaultProjectResolver","identityKey","enabled","onState","q","useQuery","home","p","isError","data","state","W6WEmbedProvider","apiOrigin","getSession","fallback","ready","fetch","registry","useState","createDraftRegistry","applied","setApplied","switching","forwardedRef","useRef","forwarded","sessionRef","stableGetSession","cancelled","apply","queryClient","resolved","setResolved","onResolved","useCallback","key","prev","authFailure","setAuthFailure","onUnauthorized","clearAuthFailure","appliedKey","spec","wantsDefault","projectState","DraftRegistryProvider","QueryClientProvider","jsxs","W6WProvider","EmbedProjectContext"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ export type AppConnections = {
2
+ state: "loading";
3
+ } | {
4
+ state: "error";
5
+ } | {
6
+ state: "ready";
7
+ ids: ReadonlySet<string>;
8
+ };
9
+ export interface BindingSite {
10
+ id: string;
11
+ uses?: {
12
+ app?: string;
13
+ connection?: string | null;
14
+ };
15
+ }
16
+ export interface BindingProblem {
17
+ siteId: string;
18
+ app: string;
19
+ connection: string;
20
+ code: "unknown_connection";
21
+ }
22
+ /** A problem iff app + connection are non-empty and the app's list is `ready` without the id.
23
+ * `loading`, `error` and `undefined` (internal app / not fetched) never report — no false red. */
24
+ export declare function findBindingProblems(sites: readonly BindingSite[], byApp: (app: string) => AppConnections | undefined): BindingProblem[];
25
+ export interface DisabledBannerInput {
26
+ enabled: boolean | undefined;
27
+ problemCount: number;
28
+ dirty: boolean;
29
+ hadProblems: boolean;
30
+ }
31
+ export interface DisabledBannerState {
32
+ show: boolean;
33
+ canEnable: boolean;
34
+ problemCount: number;
35
+ }
36
+ /** Show iff disabled AND (problems now OR problems seen this mount). Enable only once every
37
+ * binding is fixed AND saved. `enabled` undefined (versions not loaded) never shows. */
38
+ export declare function disabledBannerState(input: DisabledBannerInput): DisabledBannerState;
@@ -23,18 +23,20 @@ export type RailCallable = {
23
23
  } | {
24
24
  kind: "connection";
25
25
  id: string;
26
+ action?: string;
27
+ params?: readonly SnippetInput[];
26
28
  } | null;
27
29
  /**
28
30
  * Is a "Call from code" panel meaningful for this context? Mirrors
29
31
  * `alias-rail.ts`'s `targetForCallable` fail-closed shape exactly (its own
30
32
  * comment: *"'connection' and no resource at all both fail closed to null —
31
- * house style"*) — `"connection"` and `null` both answer `false`.
33
+ * house style"*) — a bare `"connection"` (no `action`) and `null` both answer `false`.
32
34
  */
33
35
  export declare function isAvailable(ctx: RailCallable): boolean;
34
36
  /**
35
37
  * The widened-union -> `SnippetCallable` conversion `CodeTool.Panel` hands to
36
38
  * `CallFromCodeBody`. `null` for a context this tool has no snippet for
37
- * (`"connection"`, or no resource at all) — defensive, since `isAvailable`
39
+ * (a connection without an `action`, or no resource at all) — defensive, since `isAvailable`
38
40
  * already keeps the tool off the strip for those.
39
41
  *
40
42
  * The one easy-to-miss field: `WorkspaceCallable`'s `label` maps to
@@ -22,3 +22,4 @@ export * from './input-seeding.ts';
22
22
  export * from './input-coverage.ts';
23
23
  export * from './coerce-input.ts';
24
24
  export * from './callable-record.ts';
25
+ export * from './binding-problems.ts';
@@ -0,0 +1 @@
1
+ export declare function invokeErrorCopy(e: unknown): string;
@@ -49,7 +49,7 @@ export type SnippetCallable = {
49
49
  kind: "connection";
50
50
  id: string;
51
51
  action: string;
52
- params?: string[];
52
+ params?: readonly SnippetInput[];
53
53
  } | {
54
54
  kind: "var";
55
55
  name: string;
@@ -104,6 +104,7 @@ export interface WorkflowStepLike {
104
104
  }
105
105
  /** A workflow definition, just enough of it for the trigger-field union. */
106
106
  export interface WorkflowLike {
107
+ nodes?: unknown;
107
108
  steps?: unknown;
108
109
  }
109
110
  /** Everything `fieldsFromWorkflow` needs from `@w6w/ui/flow` but cannot import itself. */
@@ -153,6 +154,13 @@ export declare function implToTarget(impl: FunctionImplLike | undefined): Action
153
154
  * `{}`, not absent, on a CallableRef impl too.
154
155
  */
155
156
  export declare function targetToImpl(target: ActionTargetLike | CallableTargetLike): FunctionImplLike;
157
+ /**
158
+ * The `impl` a re-pick produces. `outputMap` adapts ONE binding's vendor response, so it survives
159
+ * only while the binding identity is unchanged: the same `uses.app` + `uses.action` (action arm),
160
+ * or the same callable kind + id (ref arm). Connection and `with` edits keep it; a different
161
+ * action or callee drops it (rfcs/function.md: switching provider replaces `impl` wholesale).
162
+ */
163
+ export declare function implAfterRebind(prev: FunctionImplLike | undefined, target: ActionTargetLike | CallableTargetLike): FunctionImplLike;
156
164
  /** Project a list of action/function params into the normalized `TargetField[]` (A5). */
157
165
  export declare function paramsToFields(params: ParamLike[]): TargetField[];
158
166
  /**
@@ -44,6 +44,7 @@ export interface WorkflowStepLike {
44
44
  }
45
45
  /** A workflow definition, just enough of it for this preview. */
46
46
  export interface WorkflowLike {
47
+ nodes?: WorkflowStepLike[];
47
48
  steps?: WorkflowStepLike[];
48
49
  }
49
50
  /**
@@ -56,17 +56,24 @@ export interface RunErrorSourceLike {
56
56
  status?: string;
57
57
  error?: unknown;
58
58
  stepErrors?: ReadonlyArray<{
59
- stepId: string;
59
+ nodeId?: string;
60
+ stepId?: string;
60
61
  error: unknown;
61
62
  }>;
62
63
  }
64
+ /** The per-node execution map of a run record, in either shape — `nodes`
65
+ * preferred, else the legacy `steps`. */
66
+ export declare function runNodeMap(run: {
67
+ nodes?: unknown;
68
+ steps?: unknown;
69
+ } | undefined | null): Record<string, StepExecutionLike> | undefined;
63
70
  /** The slice of a saved step-test fixture (`StepTest`) {@link latestFixtureInput}
64
71
  * reads — `with` is what the trigger's Test tab invokes it with. */
65
72
  export interface StepTestFixtureLike {
66
73
  with?: unknown;
67
74
  }
68
75
  /** The row-level fallback for a `failed` step that carries no `error` at all. */
69
- export declare const STEP_FAILED_NO_REASON = "Step failed without reporting a reason.";
76
+ export declare const STEP_FAILED_NO_REASON = "Node failed without reporting a reason.";
70
77
  /** The run-level fallback for a `failed` run where nothing carries a reason. */
71
78
  export declare const RUN_FAILED_NO_REASON = "Run failed without reporting a reason.";
72
79
  /** One `ExecutionLogPanel` row — field-for-field `@w6w/ui`'s
@@ -0,0 +1,5 @@
1
+ /** The vertex array of a workflow definition, in either shape — `nodes` wins, `steps` is the legacy name. */
2
+ export declare function workflowNodes<T = unknown>(def: {
3
+ nodes?: T[];
4
+ steps?: T[];
5
+ } | null | undefined): T[];
@@ -49,6 +49,7 @@ export interface WorkflowStepLike {
49
49
  }
50
50
  /** A workflow definition, just enough of it for this gate. */
51
51
  export interface WorkflowLike {
52
+ nodes?: WorkflowStepLike[];
52
53
  steps?: WorkflowStepLike[];
53
54
  /**
54
55
  * Present on real definitions, never read here — graph well-formedness
package/dist/lib.mjs CHANGED
@@ -1,84 +1,86 @@
1
1
  "use client";
2
- import { d as n, i as d, a as c, r as p, b as u, c as m, e as f, s as S, t as g, f as v, v as b, g as w, w as F, h as R } from "./trigger-preview-VPkrryDl.js";
3
- import { d as x, e as y, i as I, p as A, t as E } from "./document-sources-C0grrtdq.js";
4
- import { e as P, h as D, a as T, b as C, i as U, m as V, p as k, r as L, s as W, v as _, w as H } from "./rail-settings-XYGToh00.js";
5
- import { c as j, d as q, i as B, p as G } from "./settings-rail--GdRMusb.js";
6
- import { A as Y, b as $, f as z, i as J, a as M, c as Q, s as X, u as Z } from "./slug-C4ktDPdy.js";
7
- import { i as ea, s as sa } from "./spec-import-invalidation-D3retX4Q.js";
8
- import { b as ta } from "./workflow-blank-DyL3_RUA.js";
9
- import { I as oa, c as la, f as na, i as da, a as ca, m as pa, p as ua, s as ma, t as fa, b as Sa, d as ga, u as va, e as ba, g as wa } from "./coerce-input-BicYr7nc.js";
10
- function t(s) {
2
+ import { d as l, a as d, f as c, i as p, b as u, r as m, c as f, e as S, g, s as b, t as v, h as w, v as F, j as R, w as h, k as x } from "./trigger-preview-DKxfjzUY.js";
3
+ import { d as I, e as A, i as P, p as E, t as K } from "./document-sources-UCwe8x77.js";
4
+ import { e as T, h as k, a as C, b as U, i as V, m as L, p as W, r as _, s as B, v as j, w as H } from "./rail-settings-XYGToh00.js";
5
+ import { c as q, d as G, i as O, p as Y } from "./settings-rail--GdRMusb.js";
6
+ import { A as z, b as J, f as M, i as Q, a as X, c as Z, s as aa, u as ea } from "./slug-BVdgiP_L.js";
7
+ import { i as ra, s as ia } from "./spec-import-invalidation-D3retX4Q.js";
8
+ import { b as oa } from "./workflow-blank-DFpGObrn.js";
9
+ import { I as la, c as da, f as ca, i as pa, a as ua, m as ma, p as fa, s as Sa, t as ga, b as ba, d as va, u as wa, e as Fa, g as Ra } from "./coerce-input-DttlcSdO.js";
10
+ function i(s) {
11
11
  const e = new URLSearchParams(s), a = e.get("edit");
12
12
  if (a === null || a === "") return null;
13
13
  e.delete("edit");
14
14
  const r = e.toString();
15
15
  return { id: a, search: r === "" ? "" : `?${r}` };
16
16
  }
17
- function i(s) {
17
+ function t(s) {
18
18
  const a = new URLSearchParams(s).get("run");
19
19
  return a != null && a.startsWith("run_") ? a : null;
20
20
  }
21
21
  export {
22
- Y as ACCOUNT_SLUG_RE,
23
- oa as INPUT_TYPES,
24
- ta as blankDefinition,
25
- $ as buildSnippet,
26
- j as callableRecord,
27
- la as coerceInput,
28
- q as definitionWithPolicy,
29
- x as documentSampleValues,
30
- n as duplicateKeyIndexes,
31
- y as errorHandlerSelfDecision,
32
- P as evaluateEdit,
33
- na as fieldsFromWorkflow,
34
- z as filterKeyInput,
35
- D as hasDefinitionActions,
36
- T as hasDelete,
37
- C as hasVersionHistory,
38
- da as implToTarget,
39
- ca as inputsForSave,
40
- d as invalidReason,
41
- ea as invalidateImportedCallable,
42
- I as isCodeRailAvailable,
43
- J as isEndpointKey,
44
- c as isExprDefault,
45
- U as isRowArchived,
46
- B as isSettingsRailAvailable,
47
- M as isUrnAddressable,
48
- Q as isValidAccountSlug,
49
- t as legacyEditRedirect,
50
- pa as mergeSeed,
51
- V as metadataFieldsForKind,
52
- ua as paramsToFields,
53
- k as parseImportPaste,
54
- G as policyFromDefinition,
55
- A as projectDocumentSources,
56
- p as readSettings,
57
- u as readVariables,
58
- m as readWorkflowStatus,
59
- L as restoreRailState,
60
- f as runFormFields,
61
- i as runParamFromSearch,
62
- ma as shouldSeed,
63
- X as slugify,
64
- W as specCollectionForKind,
65
- sa as specImportListKey,
66
- S as stepValid,
67
- fa as targetIsBound,
68
- Sa as targetRef,
69
- ga as targetToImpl,
70
- E as toSnippetCallable,
71
- g as triggerInputSeed,
72
- v as triggerPreviews,
73
- Z as unavailableReason,
74
- va as uncoveredForEndpoint,
75
- ba as uncoveredForFunction,
76
- wa as uncoveredRequiredKeys,
77
- b as variablesForSave,
78
- w as varsRailFor,
79
- _ as visibleRows,
22
+ z as ACCOUNT_SLUG_RE,
23
+ la as INPUT_TYPES,
24
+ oa as blankDefinition,
25
+ J as buildSnippet,
26
+ q as callableRecord,
27
+ da as coerceInput,
28
+ G as definitionWithPolicy,
29
+ l as disabledBannerState,
30
+ I as documentSampleValues,
31
+ d as duplicateKeyIndexes,
32
+ A as errorHandlerSelfDecision,
33
+ T as evaluateEdit,
34
+ ca as fieldsFromWorkflow,
35
+ M as filterKeyInput,
36
+ c as findBindingProblems,
37
+ k as hasDefinitionActions,
38
+ C as hasDelete,
39
+ U as hasVersionHistory,
40
+ pa as implToTarget,
41
+ ua as inputsForSave,
42
+ p as invalidReason,
43
+ ra as invalidateImportedCallable,
44
+ P as isCodeRailAvailable,
45
+ Q as isEndpointKey,
46
+ u as isExprDefault,
47
+ V as isRowArchived,
48
+ O as isSettingsRailAvailable,
49
+ X as isUrnAddressable,
50
+ Z as isValidAccountSlug,
51
+ i as legacyEditRedirect,
52
+ ma as mergeSeed,
53
+ L as metadataFieldsForKind,
54
+ fa as paramsToFields,
55
+ W as parseImportPaste,
56
+ Y as policyFromDefinition,
57
+ E as projectDocumentSources,
58
+ m as readSettings,
59
+ f as readVariables,
60
+ S as readWorkflowStatus,
61
+ _ as restoreRailState,
62
+ g as runFormFields,
63
+ t as runParamFromSearch,
64
+ Sa as shouldSeed,
65
+ aa as slugify,
66
+ B as specCollectionForKind,
67
+ ia as specImportListKey,
68
+ b as stepValid,
69
+ ga as targetIsBound,
70
+ ba as targetRef,
71
+ va as targetToImpl,
72
+ K as toSnippetCallable,
73
+ v as triggerInputSeed,
74
+ w as triggerPreviews,
75
+ ea as unavailableReason,
76
+ wa as uncoveredForEndpoint,
77
+ Fa as uncoveredForFunction,
78
+ Ra as uncoveredRequiredKeys,
79
+ F as variablesForSave,
80
+ R as varsRailFor,
81
+ j as visibleRows,
80
82
  H as workflowKeyEditAllowed,
81
- F as workflowValid,
82
- R as writeSetting
83
+ h as workflowValid,
84
+ x as writeSetting
83
85
  };
84
86
  //# sourceMappingURL=lib.mjs.map
@@ -0,0 +1,31 @@
1
+ import { ConnectionDependentCallable } from '@w6w/sdk/console';
2
+ export type OpenCallable = (kind: string, id: string) => void;
3
+ /** `sites` is `unknown[]` on the wire; render each as a short id string. */
4
+ export declare function siteLabel(site: unknown): string;
5
+ /**
6
+ * A model route that reaches the model through this connection. `broken` means the route stopped
7
+ * resolving — typically this connection was removed or stopped working — and gets a reconnect.
8
+ */
9
+ export interface ConnectionDependentRoute {
10
+ id: string;
11
+ name: string;
12
+ status: "active" | "broken";
13
+ /** The route's own project; Reconnect opens the editor there, whatever project the host is in. */
14
+ project?: string;
15
+ }
16
+ /**
17
+ * The `routes` section of a dependents payload. A `broken` route offers "Reconnect", which opens
18
+ * the model-route editor for that route so a replacement connection can be picked (the editor
19
+ * PATCHes `connection`). Active routes are listed without the action. `projectId` is passed
20
+ * through to the editor; omitted, the provider's project applies.
21
+ */
22
+ export declare function ConnectionDependentRoutes({ routes, projectId, }: {
23
+ routes: ConnectionDependentRoute[];
24
+ projectId?: string | null;
25
+ }): import("react").JSX.Element | null;
26
+ export declare function ConnectionDependentRows({ callables, onOpenCallable, routes, projectId, }: {
27
+ callables: ConnectionDependentCallable[];
28
+ onOpenCallable?: OpenCallable;
29
+ routes?: ConnectionDependentRoute[];
30
+ projectId?: string | null;
31
+ }): import("react").JSX.Element;
@@ -1,8 +1,11 @@
1
1
  import { ReactNode } from 'react';
2
+ import { OpenCallable } from './ConnectionDependents.tsx';
2
3
  export interface ConnectionDetailProps {
3
4
  connectionId: string;
4
5
  /** An action row calls `(actionKey)`; one of its saved tests calls `(actionKey, savedTestId)`. */
5
6
  onOpenAction: (actionKey: string, savedTestId?: string) => void;
7
+ /** A "Used by" row opens the callable's editor; rows are plain text without it. */
8
+ onOpenCallable?: OpenCallable;
6
9
  /** The back affordance renders only when given. */
7
10
  onBack?: () => void;
8
11
  slots?: {
@@ -14,4 +17,4 @@ export interface ConnectionDetailProps {
14
17
  empty?: ReactNode;
15
18
  };
16
19
  }
17
- export declare function ConnectionDetail({ connectionId, onOpenAction, onBack, slots, }: ConnectionDetailProps): import("react").JSX.Element;
20
+ export declare function ConnectionDetail({ connectionId, onOpenAction, onBack, onOpenCallable, slots, }: ConnectionDetailProps): import("react").JSX.Element;
@@ -1,5 +1,6 @@
1
1
  import { ConnectionListProps as UiConnectionListProps } from '@w6w/ui';
2
2
  import { MouseEvent } from 'react';
3
+ import { OpenCallable } from './ConnectionDependents.tsx';
3
4
  export interface ConnectionListProps {
4
5
  /** Row click; the host decides whether to `preventDefault` when it also passes `getHref`. */
5
6
  onOpen?: (id: string, event: MouseEvent<Element>) => void;
@@ -12,5 +13,7 @@ export interface ConnectionListProps {
12
13
  * Add button.
13
14
  */
14
15
  slots?: UiConnectionListProps["slots"];
16
+ /** When set, dependent rows in the delete confirm open the callable's editor. */
17
+ onOpenCallable?: OpenCallable;
15
18
  }
16
- export declare function ConnectionList({ onOpen, getHref, addLabel, slots }: ConnectionListProps): import("react").JSX.Element;
19
+ export declare function ConnectionList({ onOpen, getHref, addLabel, slots, onOpenCallable, }: ConnectionListProps): import("react").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { ReactNode } from 'react';
2
+ export interface CredentialDetailProps {
3
+ credentialId: string;
4
+ /** A connected-app row calls `(connectionId)`; rows are plain text without it. */
5
+ onOpenConnection?: (id: string) => void;
6
+ /** Called after a delete succeeds. */
7
+ onDeleted?: () => void;
8
+ /** The back affordance renders only when given. */
9
+ onBack?: () => void;
10
+ slots?: {
11
+ /** Replaces the not-found state. */
12
+ empty?: ReactNode;
13
+ };
14
+ }
15
+ export declare function CredentialDetail({ credentialId, onOpenConnection, onDeleted, onBack, slots, }: CredentialDetailProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ export interface CredentialListProps {
3
+ /** Narrow the list to one credential contract. */
4
+ contract?: string;
5
+ /** Row click. */
6
+ onOpen?: (id: string) => void;
7
+ slots?: {
8
+ /** Replaces the heading. */
9
+ header?: ReactNode;
10
+ /** Replaces the empty state. */
11
+ empty?: ReactNode;
12
+ };
13
+ }
14
+ export declare function CredentialList({ contract, onOpen, slots }: CredentialListProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { ModelCatalogFilter } from '../repos/models.ts';
3
+ export interface ModelCatalogProps {
4
+ /**
5
+ * The project the Models tab is scoped to. Kept for a uniform tab API: the catalog never sends
6
+ * it (a tenant-wide list), so it changes nothing here.
7
+ */
8
+ projectId?: string | null;
9
+ /** Narrow the list (`provider`, `status`, `limit`). `cursor` is keyset paging, managed here. */
10
+ filter?: Omit<ModelCatalogFilter, "cursor">;
11
+ }
12
+ export declare function ModelCatalog(props: ModelCatalogProps): ReactNode;
@@ -0,0 +1,12 @@
1
+ import { ReactNode } from 'react';
2
+ import { ModelUsageFilter } from '../repos/models.ts';
3
+ export interface ModelUsageProps {
4
+ /**
5
+ * The project whose usage is shown. Omitted: the `<W6WEmbedProvider project>`. `null` or `""`:
6
+ * no project — nothing is requested.
7
+ */
8
+ projectId?: string | null;
9
+ /** Narrow the report (`route`, `model`, `from`, `to`, `groupBy`, `limit`). `cursor` is paging. */
10
+ filter?: Omit<ModelUsageFilter, "cursor">;
11
+ }
12
+ export declare function ModelUsage(props: ModelUsageProps): ReactNode;
package/dist/lists.d.ts CHANGED
@@ -18,3 +18,11 @@ export { ConnectionList } from './lists/ConnectionList.tsx';
18
18
  export type { ConnectionListProps } from './lists/ConnectionList.tsx';
19
19
  export { ConnectionDetail } from './lists/ConnectionDetail.tsx';
20
20
  export type { ConnectionDetailProps } from './lists/ConnectionDetail.tsx';
21
+ export { ModelCatalog } from './lists/ModelCatalog.tsx';
22
+ export type { ModelCatalogProps } from './lists/ModelCatalog.tsx';
23
+ export { ModelUsage } from './lists/ModelUsage.tsx';
24
+ export type { ModelUsageProps } from './lists/ModelUsage.tsx';
25
+ export { CredentialList } from './lists/CredentialList.tsx';
26
+ export type { CredentialListProps } from './lists/CredentialList.tsx';
27
+ export { CredentialDetail } from './lists/CredentialDetail.tsx';
28
+ export type { CredentialDetailProps } from './lists/CredentialDetail.tsx';