@jini-ai/ui 0.4.7 → 0.4.8

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 (125) hide show
  1. package/README.md +2 -0
  2. package/dist/features/admin-widgets/components/InfoTip.d.ts +23 -2
  3. package/dist/features/admin-widgets/components/InfoTip.hooks.d.ts +22 -2
  4. package/dist/features/admin-widgets/components/InfoTip.hooks.js +75 -28
  5. package/dist/features/admin-widgets/components/InfoTip.js +12 -4
  6. package/dist/features/admin-widgets/components/InfoTip.rules.d.ts +72 -0
  7. package/dist/features/admin-widgets/components/InfoTip.rules.js +68 -0
  8. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.d.ts +36 -0
  9. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.d.ts +58 -0
  10. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.hooks.js +66 -0
  11. package/dist/features/admin-widgets/components/SuggestInput/SuggestInput.js +24 -0
  12. package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.d.ts +23 -0
  13. package/dist/features/admin-widgets/components/useDebouncedHtmlPreview.hooks.js +28 -0
  14. package/dist/features/admin-widgets/index.d.ts +9 -0
  15. package/dist/features/admin-widgets/index.js +5 -0
  16. package/dist/features/execution/constants.js +11 -10
  17. package/dist/features/execution/http-adapter.d.ts +3 -1
  18. package/dist/features/execution/http-adapter.js +9 -4
  19. package/dist/features/execution/index.d.ts +1 -1
  20. package/dist/features/execution/index.js +1 -1
  21. package/dist/features/execution/react/components/ByokProviderForm.d.ts +18 -1
  22. package/dist/features/execution/react/components/ByokProviderForm.js +14 -16
  23. package/dist/features/execution/react/components/LocalCliAgentCard.d.ts +5 -1
  24. package/dist/features/execution/react/components/LocalCliAgentCard.js +12 -87
  25. package/dist/features/execution/react/components/LocalCliAgentList.d.ts +4 -1
  26. package/dist/features/execution/react/components/LocalCliAgentList.js +13 -4
  27. package/dist/features/execution/react/components/LocalCliAgentSettings.d.ts +20 -0
  28. package/dist/features/execution/react/components/LocalCliAgentSettings.js +20 -0
  29. package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.d.ts +24 -0
  30. package/dist/features/execution/react/hooks/use-byok-field-validation.hooks.js +27 -0
  31. package/dist/features/execution/react/hooks/useExecutionTab.js +10 -1
  32. package/dist/features/execution/react/hooks/useLocalCliAgentCard.d.ts +48 -0
  33. package/dist/features/execution/react/hooks/useLocalCliAgentCard.js +110 -0
  34. package/dist/features/execution/react/hooks/useLocalCliAgentList.d.ts +19 -0
  35. package/dist/features/execution/react/hooks/useLocalCliAgentList.js +13 -0
  36. package/dist/features/execution/rules.d.ts +13 -0
  37. package/dist/features/execution/rules.js +14 -0
  38. package/dist/features/execution/types.d.ts +2 -0
  39. package/dist/features/html-editor/canvas-embed-placeholders.d.ts +13 -1
  40. package/dist/features/html-editor/canvas-embed-placeholders.js +61 -12
  41. package/dist/features/html-editor/dom.d.ts +5 -0
  42. package/dist/features/html-editor/dom.js +10 -0
  43. package/dist/features/html-editor/editor-blocks.d.ts +71 -0
  44. package/dist/features/html-editor/editor-blocks.js +185 -0
  45. package/dist/features/html-editor/editor-serialization.d.ts +24 -0
  46. package/dist/features/html-editor/editor-serialization.js +110 -0
  47. package/dist/features/html-editor/index.d.ts +5 -0
  48. package/dist/features/html-editor/index.js +3 -0
  49. package/dist/features/html-editor/protected-elements.d.ts +64 -0
  50. package/dist/features/html-editor/protected-elements.js +189 -0
  51. package/dist/features/html-editor/react/components/InteractiveHtmlEditor.d.ts +6 -4
  52. package/dist/features/html-editor/react/components/InteractiveHtmlEditor.js +3 -3
  53. package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.d.ts +9 -1
  54. package/dist/features/html-editor/react/hooks/useInteractiveHtmlEditor.js +107 -196
  55. package/dist/features/html-editor/source-splice.d.ts +23 -0
  56. package/dist/features/html-editor/source-splice.js +45 -0
  57. package/dist/features/i18n/dictionaries/settings-dialog.ar.js +4 -0
  58. package/dist/features/i18n/dictionaries/settings-dialog.bn.js +4 -0
  59. package/dist/features/i18n/dictionaries/settings-dialog.de.js +4 -0
  60. package/dist/features/i18n/dictionaries/settings-dialog.en.js +4 -0
  61. package/dist/features/i18n/dictionaries/settings-dialog.es.js +4 -0
  62. package/dist/features/i18n/dictionaries/settings-dialog.fa.js +4 -0
  63. package/dist/features/i18n/dictionaries/settings-dialog.fr.js +4 -0
  64. package/dist/features/i18n/dictionaries/settings-dialog.hi.js +4 -0
  65. package/dist/features/i18n/dictionaries/settings-dialog.hu.js +4 -0
  66. package/dist/features/i18n/dictionaries/settings-dialog.id.js +4 -0
  67. package/dist/features/i18n/dictionaries/settings-dialog.it.js +4 -0
  68. package/dist/features/i18n/dictionaries/settings-dialog.ja.js +4 -0
  69. package/dist/features/i18n/dictionaries/settings-dialog.ko.js +4 -0
  70. package/dist/features/i18n/dictionaries/settings-dialog.pl.js +4 -0
  71. package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +4 -0
  72. package/dist/features/i18n/dictionaries/settings-dialog.ru.js +4 -0
  73. package/dist/features/i18n/dictionaries/settings-dialog.th.js +4 -0
  74. package/dist/features/i18n/dictionaries/settings-dialog.tr.js +4 -0
  75. package/dist/features/i18n/dictionaries/settings-dialog.uk.js +4 -0
  76. package/dist/features/i18n/dictionaries/settings-dialog.ur.js +4 -0
  77. package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +4 -0
  78. package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +4 -0
  79. package/dist/features/interactive-ui/providers/shadcn/button.d.ts +1 -1
  80. package/dist/features/mcp-ui/escape.js +2 -6
  81. package/dist/features/mcp-ui/surfaces/bridge.js +4 -2
  82. package/dist/features/mcp-ui/surfaces/document.d.ts +11 -4
  83. package/dist/features/mcp-ui/surfaces/document.js +25 -3
  84. package/dist/features/mcp-ui/surfaces/outcome.js +1 -1
  85. package/dist/features/media-providers/constants.d.ts +0 -7
  86. package/dist/features/media-providers/constants.js +7 -15
  87. package/dist/features/media-providers/react/components/MediaProvidersTab.js +3 -2
  88. package/dist/features/media-providers/react/hooks/useMediaProvidersTab.js +6 -3
  89. package/dist/features/memory/dependencies.d.ts +2 -0
  90. package/dist/features/memory/dependencies.js +9 -25
  91. package/dist/features/memory/index.d.ts +1 -0
  92. package/dist/features/memory/index.js +1 -0
  93. package/dist/features/memory/react/MemoryPorts.d.ts +17 -0
  94. package/dist/features/memory/react/MemoryPorts.js +15 -0
  95. package/dist/features/memory/react/hooks/useMemoryConfig.hooks.d.ts +2 -2
  96. package/dist/features/memory/react/hooks/useMemoryConfig.hooks.js +7 -7
  97. package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.d.ts +2 -3
  98. package/dist/features/memory/react/hooks/useMemoryConnectors.hooks.js +4 -5
  99. package/dist/features/memory/react/hooks/useMemoryEntries.hooks.d.ts +2 -3
  100. package/dist/features/memory/react/hooks/useMemoryEntries.hooks.js +4 -5
  101. package/dist/features/memory/react/hooks/useMemoryExtractions.hooks.js +2 -2
  102. package/dist/features/panel-kit/fetch-query/adapter.react.d.ts +2 -2
  103. package/dist/features/panel-kit/fetch-query/adapter.react.js +2 -2
  104. package/dist/features/panel-kit/fetch-query/adapter.tanstack.d.ts +1 -1
  105. package/dist/features/panel-kit/fetch-query/adapter.tanstack.js +35 -13
  106. package/dist/features/panel-kit/fetch-query/binding.react.d.ts +1 -1
  107. package/dist/features/panel-kit/fetch-query/environment.browser.d.ts +1 -1
  108. package/dist/features/panel-kit/fetch-query/index.d.ts +4 -2
  109. package/dist/features/panel-kit/fetch-query/tanstack.d.ts +4 -2
  110. package/dist/features/panel-kit/helpers/standing-draft-recovery-message.d.ts +3 -1
  111. package/dist/features/panel-kit/helpers/standing-draft-recovery-message.js +9 -2
  112. package/dist/features/settings/dialog/styles/settings-dialog.css +169 -21
  113. package/dist/features/tabbed-dialog/styles/tabbed-dialog.css +91 -0
  114. package/dist/react/components/RemixIcon.d.ts +1 -41
  115. package/dist/react/components/RemixIcon.js +3 -176
  116. package/dist/react/components/RemixIcon.stylesheet.d.ts +84 -0
  117. package/dist/react/components/RemixIcon.stylesheet.js +208 -0
  118. package/dist/react/components/remixicon-font-recovery.d.ts +55 -0
  119. package/dist/react/components/remixicon-font-recovery.js +110 -0
  120. package/dist/styles/admin.css +8 -2
  121. package/package.json +12 -7
  122. package/dist/features/panel-kit/fetch-query/cache.d.ts +0 -125
  123. package/dist/features/panel-kit/fetch-query/cache.js +0 -232
  124. package/dist/features/panel-kit/fetch-query/types.d.ts +0 -93
  125. package/dist/features/panel-kit/fetch-query/types.js +0 -2
@@ -1,3 +1,4 @@
1
+ import { findProvider, canonicalMediaProviderId } from '@jini-ai/integrations/media-providers/catalog';
1
2
  /**
2
3
  * A small, vendor-shaped starting catalog — same convention as `execution/constants.ts`'s
3
4
  * `DEFAULT_PROVIDER_PRESETS`. Sourced by driving Open Design's own Settings → Media providers
@@ -5,17 +6,15 @@
5
6
  * models. Pass your own `catalog` to `MediaProvidersTab` to replace this wholesale; Zana or any
6
7
  * other host is expected to do so once it has its own provider roster.
7
8
  */
8
- export const DEFAULT_MEDIA_PROVIDER_CATALOG = [
9
+ const starterCatalog = [
9
10
  {
10
11
  id: 'nano-banana',
11
12
  label: 'Nano Banana',
12
- defaultBaseUrl: 'https://generativelanguage.googleapis.com',
13
13
  models: ['gemini-3.1-flash-image-preview'],
14
14
  },
15
15
  {
16
16
  id: 'aihubmix',
17
17
  label: 'AIHubMix',
18
- defaultBaseUrl: 'https://aihubmix.com/v1',
19
18
  models: ['gemini-3.1-flash-image-preview'],
20
19
  },
21
20
  {
@@ -26,65 +25,58 @@ export const DEFAULT_MEDIA_PROVIDER_CATALOG = [
26
25
  {
27
26
  id: 'elevenlabs',
28
27
  label: 'ElevenLabs',
29
- defaultBaseUrl: 'https://api.elevenlabs.io',
30
28
  },
31
29
  {
32
30
  id: 'fal-ai',
33
31
  label: 'Fal.ai',
34
- defaultBaseUrl: 'https://fal.run',
35
32
  models: ['gemini-3.1-flash-image-preview'],
36
33
  },
37
34
  {
38
35
  id: 'fishaudio',
39
36
  label: 'FishAudio',
40
- defaultBaseUrl: 'https://api.fish.audio',
41
37
  },
42
38
  {
43
39
  id: 'imagerouter',
44
40
  label: 'ImageRouter',
45
- defaultBaseUrl: 'https://api.imagerouter.io/v1/openai',
46
41
  models: ['gemini-3.1-flash-image-preview'],
47
42
  },
48
43
  {
49
44
  id: 'leonardo-ai',
50
45
  label: 'Leonardo.ai',
51
- defaultBaseUrl: 'https://cloud.leonardo.ai/api/rest/v1',
52
46
  },
53
47
  {
54
48
  id: 'minimax',
55
49
  label: 'MiniMax',
56
- defaultBaseUrl: 'https://api.minimaxi.chat/v1',
57
50
  },
58
51
  {
59
52
  id: 'openai',
60
53
  label: 'OpenAI',
61
- defaultBaseUrl: 'https://api.openai.com/v1',
62
54
  models: ['gpt-image-2', 'dall-e-3'],
63
55
  },
64
56
  {
65
57
  id: 'openrouter',
66
58
  label: 'OpenRouter',
67
- defaultBaseUrl: 'https://openrouter.ai/api/v1',
68
59
  },
69
60
  {
70
61
  id: 'senseaudio',
71
62
  label: 'SenseAudio',
72
- defaultBaseUrl: 'https://api.senseaudio.cn',
73
63
  },
74
64
  {
75
65
  id: 'tavily-search',
76
66
  label: 'Tavily Search',
77
- defaultBaseUrl: 'https://api.tavily.com',
78
67
  },
79
68
  {
80
69
  id: 'volcengine-ark',
81
70
  label: 'Volcengine Ark (Doubao)',
82
- defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
83
71
  },
84
72
  {
85
73
  id: 'xai-grok-imagine',
86
74
  label: 'xAI Grok Imagine',
87
- defaultBaseUrl: 'https://api.x.ai/v1',
88
75
  },
89
76
  ];
77
+ export const DEFAULT_MEDIA_PROVIDER_CATALOG = starterCatalog.map((entry) => {
78
+ const id = canonicalMediaProviderId({ id: entry.id });
79
+ const provider = findProvider({ id });
80
+ return { ...entry, id, label: provider.label, ...(provider.defaultBaseUrl ? { defaultBaseUrl: provider.defaultBaseUrl } : {}) };
81
+ });
90
82
  //# sourceMappingURL=constants.js.map
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { canonicalMediaProviderId } from '@jini-ai/integrations/media-providers/catalog';
2
3
  import { Fragment, useState } from 'react';
3
4
  import { agentHandleProps, buildAgentListHandles } from '@jini-ai/agentic';
4
5
  import { useT } from '../../../i18n/index.js';
@@ -55,7 +56,7 @@ export function MediaProvidersTab({ port, catalog = DEFAULT_MEDIA_PROVIDER_CATAL
55
56
  return next;
56
57
  });
57
58
  };
58
- const orderedCatalog = sortProvidersByConfigured(catalog, providers, pinnedProviderIds);
59
+ const orderedCatalog = sortProvidersByConfigured(catalog.map((entry) => ({ ...entry, id: canonicalMediaProviderId({ id: entry.id }) })), providers, pinnedProviderIds?.map((id) => canonicalMediaProviderId({ id })));
59
60
  const providerHandles = agentHandle
60
61
  ? buildAgentListHandles({ prefix: agentHandle, ids: orderedCatalog.map((option) => option.id) })
61
62
  : undefined;
@@ -63,7 +64,7 @@ export function MediaProvidersTab({ port, catalog = DEFAULT_MEDIA_PROVIDER_CATAL
63
64
  // pinned id absent from `catalog` never appears in `orderedCatalog` either (see
64
65
  // `sortProvidersByConfigured`'s own "silently skipped" doc), so this stays correct without
65
66
  // re-deriving which pinned ids actually resolved to a real card.
66
- const pinnedIdSet = new Set(pinnedProviderIds ?? []);
67
+ const pinnedIdSet = new Set(pinnedProviderIds?.map((id) => canonicalMediaProviderId({ id })) ?? []);
67
68
  const hasPendingChanges = pendingProviderIds.size > 0;
68
69
  // Save writes every provider at once, so ONE unacceptable endpoint blocks the
69
70
  // whole button rather than being silently persisted alongside the good ones.
@@ -1,3 +1,4 @@
1
+ import { normalizeMediaProviderMap, canonicalMediaProviderId } from '@jini-ai/integrations/media-providers/catalog';
1
2
  import { useCallback, useEffect, useRef, useState } from 'react';
2
3
  import { hasAnyConfiguredProvider, isEntryEmpty, mergeDaemonProviders, shouldSyncLocalProvidersToDaemon, } from '../../rules.js';
3
4
  /**
@@ -18,7 +19,7 @@ import { hasAnyConfiguredProvider, isEntryEmpty, mergeDaemonProviders, shouldSyn
18
19
  * server manages nothing" and silently wipe local edits.
19
20
  */
20
21
  export function useMediaProvidersTab({ port, initialProviders }) {
21
- const [providers, setProviders] = useState(() => ({ ...(initialProviders ?? {}) }));
22
+ const [providers, setProviders] = useState(() => normalizeMediaProviderMap({ providers: initialProviders ?? {} }));
22
23
  const [pendingProviderIds, setPendingProviderIds] = useState(() => new Set());
23
24
  const [load, setLoad] = useState({ status: 'loading' });
24
25
  const [save, setSave] = useState({ status: 'idle' });
@@ -113,7 +114,7 @@ export function useMediaProvidersTab({ port, initialProviders }) {
113
114
  if (!touched.has(providerId))
114
115
  clearedProviderIds.current.delete(providerId);
115
116
  }
116
- const next = { ...saved };
117
+ const next = normalizeMediaProviderMap({ providers: saved });
117
118
  for (const providerId of touched) {
118
119
  const local = providersRef.current[providerId];
119
120
  if (local === undefined)
@@ -205,7 +206,7 @@ export function useMediaProvidersTab({ port, initialProviders }) {
205
206
  setLoad({ status: 'unreachable' });
206
207
  return;
207
208
  }
208
- const merged = mergeDaemonProviders(providersRef.current, daemonResult, {
209
+ const merged = mergeDaemonProviders(providersRef.current, normalizeMediaProviderMap({ providers: daemonResult }), {
209
210
  preserveLocalProviderIds: pendingRef.current,
210
211
  dropProviderIds: clearedProviderIds.current,
211
212
  });
@@ -226,6 +227,7 @@ export function useMediaProvidersTab({ port, initialProviders }) {
226
227
  fetchAndReconcile(false);
227
228
  }, [fetchAndReconcile]);
228
229
  const updateProvider = useCallback((providerId, patch) => {
230
+ providerId = canonicalMediaProviderId({ id: providerId });
229
231
  const current = providersRef.current;
230
232
  const nextEntry = { ...(current[providerId] ?? {}), ...patch };
231
233
  const nextMap = { ...current };
@@ -242,6 +244,7 @@ export function useMediaProvidersTab({ port, initialProviders }) {
242
244
  mutatedSinceSend.current.add(providerId);
243
245
  }, [applyProviders, applyPending]);
244
246
  const clearProvider = useCallback((providerId) => {
247
+ providerId = canonicalMediaProviderId({ id: providerId });
245
248
  void (async () => {
246
249
  const previousEntry = providersRef.current[providerId];
247
250
  const next = { ...providersRef.current };
@@ -9,6 +9,7 @@ export declare function createMemoryHttpPorts(_required: Record<string, never>,
9
9
  entries: MemoryEntriesPort;
10
10
  extractions: MemoryExtractionsPort;
11
11
  };
12
+ /** @deprecated Explicit legacy REST binding. Host UI composition must use MemoryPortsProvider. */
12
13
  export declare const memoryConfigPort: MemoryConfigPort, memoryEntriesPort: MemoryEntriesPort, memoryExtractionsPort: MemoryExtractionsPort;
13
14
  /** Standalone default read shares the entries port's validated REST implementation. */
14
15
  export declare const fetchMemoryList: () => Promise<MemoryListResponse>;
@@ -25,5 +26,6 @@ export interface FakeMemoryConnectorsPortOptions {
25
26
  * above — only the connector catalogue/status/suggest transport is faked.
26
27
  */
27
28
  export declare function createFakeMemoryConnectorsPort(options?: FakeMemoryConnectorsPortOptions): MemoryConnectorsPort;
29
+ /** @deprecated Demo catalogue; hosts supply their own connectors port through MemoryPortsProvider. */
28
30
  export declare const memoryConnectorsPort: MemoryConnectorsPort;
29
31
  //# sourceMappingURL=dependencies.d.ts.map
@@ -1,29 +1,11 @@
1
1
  /**
2
- * The only file in this feature allowed to touch a concrete transport
3
- * adapter. Everything else in the slice depends on `ports.ts`.
4
- *
5
- * Split, deliberately, into two different defaults:
6
- *
7
- * - `memoryConfigPort`/`memoryEntriesPort`/`memoryExtractionsPort` bind REAL
8
- * `fetch`-based adapters against a plain `/api/memory*` REST surface (list/
9
- * tree/entry CRUD, config PATCH, extraction history CRUD). Unlike
10
- * `features/connectors`' data port — which fakes its transport by design,
11
- * because the real one is a specific third-party OAuth-catalog vendor's
12
- * API shape — this is a generic JSON/REST contract with no vendor coupling,
13
- * and the pinned source's one open bug (`fetchMemoryList()` trusting an
14
- * under-validated response — see the fix below and
15
- * `packages/ui/archived provenance ledger`) only exists to fix in a real, testable
16
- * adapter. A host is still free to supply its own binding; this default
17
- * just isn't a fake.
18
- * - `memoryConnectorsPort` binds a fake/in-memory connector catalogue (same
19
- * reasoning as `features/connectors`' own fake — the real catalogue is a
20
- * vendor-specific OAuth discovery transport this package doesn't assume),
21
- * plus REAL browser-only bridges for the two pieces that touch only
22
- * generic browser APIs: pending-authorization persistence (sessionStorage)
23
- * and the cross-tab "connectors changed" signal (a `CustomEvent`).
24
- * `saveMemoryEntry` on this port is the same real HTTP adapter the entries
25
- * cluster uses — saving a connector suggestion is an ordinary memory write,
26
- * not a connector-transport concern.
2
+ * Explicit legacy/test transport bindings; Memory's wired hooks never select them implicitly.
3
+ * Production hosts supply MemoryPortsProvider with authorized config/entries/extractions and
4
+ * connector ports. createMemoryHttpPorts binds a host-selected REST contract; exported singletons
5
+ * retain the old /api/memory* paths for compatibility only. memoryConnectorsPort is a demo catalogue
6
+ * with sessionStorage/CustomEvent bridges and real REST memory writes, not production discovery.
7
+ * Removal plan: migrate singleton consumers to host factories/providers, then remove deprecated
8
+ * defaults in an owner-approved breaking release. Do not silently turn a demo into a live port.
27
9
  */
28
10
  import { requestWithTimeout } from '../../utils/browser-request.js';
29
11
  import { DEFAULT_CONNECTOR_PROVIDER, MEMORY_CONNECTOR_PENDING_AUTH_STORAGE_KEY, } from './constants.js';
@@ -163,6 +145,7 @@ export function createMemoryHttpPorts(_required, { fetch } = {}) {
163
145
  };
164
146
  return { config: memoryConfigPort, entries: memoryEntriesPort, extractions: memoryExtractionsPort };
165
147
  }
148
+ /** @deprecated Explicit legacy REST binding. Host UI composition must use MemoryPortsProvider. */
166
149
  export const { config: memoryConfigPort, entries: memoryEntriesPort, extractions: memoryExtractionsPort } = createMemoryHttpPorts({});
167
150
  /** Standalone default read shares the entries port's validated REST implementation. */
168
151
  export const fetchMemoryList = memoryEntriesPort.fetchMemoryList;
@@ -251,5 +234,6 @@ function notifyConnectorsChanged() {
251
234
  return;
252
235
  window.dispatchEvent(new CustomEvent(CONNECTORS_CHANGED_EVENT));
253
236
  }
237
+ /** @deprecated Demo catalogue; hosts supply their own connectors port through MemoryPortsProvider. */
254
238
  export const memoryConnectorsPort = createFakeMemoryConnectorsPort();
255
239
  //# sourceMappingURL=dependencies.js.map
@@ -1,3 +1,4 @@
1
+ export { MemoryPortsProvider, useMemoryPorts, type MemoryPorts } from './react/MemoryPorts.js';
1
2
  export { FIELD_LABEL_STYLE } from './react/styles.js';
2
3
  export { type AsyncCommitGuard, createAsyncCommitGuard } from './async-commit-guard.js';
3
4
  export { CONNECTOR_CALLBACK_MESSAGE_TYPE, connectorAppLabel, DEFAULT_CONNECTOR_PROVIDER, EMPTY_DRAFT, MEMORY_CONNECTOR_APP_IDS, MEMORY_CONNECTOR_APP_LABELS, MEMORY_CONNECTOR_PENDING_AUTH_STORAGE_KEY, STARTERS, TYPES, } from './constants.js';
@@ -1,3 +1,4 @@
1
+ export { MemoryPortsProvider, useMemoryPorts } from './react/MemoryPorts.js';
1
2
  export { FIELD_LABEL_STYLE } from './react/styles.js';
2
3
  export { createAsyncCommitGuard } from './async-commit-guard.js';
3
4
  export { CONNECTOR_CALLBACK_MESSAGE_TYPE, connectorAppLabel, DEFAULT_CONNECTOR_PROVIDER, EMPTY_DRAFT, MEMORY_CONNECTOR_APP_IDS, MEMORY_CONNECTOR_APP_LABELS, MEMORY_CONNECTOR_PENDING_AUTH_STORAGE_KEY, STARTERS, TYPES, } from './constants.js';
@@ -0,0 +1,17 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { MemoryConfigPort, MemoryConnectorsPort, MemoryEntriesPort, MemoryExtractionsPort } from '../ports.js';
3
+ /** Hosts own authentication, endpoint paths and connector discovery; memory UI owns no transport. */
4
+ export interface MemoryPorts {
5
+ config: MemoryConfigPort;
6
+ entries: MemoryEntriesPort;
7
+ extractions: MemoryExtractionsPort;
8
+ connectors: MemoryConnectorsPort;
9
+ }
10
+ /** Bind one host's memory services to its subtree. Independent hosts never share these ports. */
11
+ export declare function MemoryPortsProvider({ ports, children }: {
12
+ ports: MemoryPorts;
13
+ children: ReactNode;
14
+ }): import("react").JSX.Element;
15
+ /** Fail at composition when no host was bound, before a hook can attempt network I/O. */
16
+ export declare function useMemoryPorts(_required?: Record<string, never>, _optional?: Record<string, never>): MemoryPorts;
17
+ //# sourceMappingURL=MemoryPorts.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ const MemoryPortsContext = createContext(null);
4
+ /** Bind one host's memory services to its subtree. Independent hosts never share these ports. */
5
+ export function MemoryPortsProvider({ ports, children }) {
6
+ return _jsx(MemoryPortsContext.Provider, { value: ports, children: children });
7
+ }
8
+ /** Fail at composition when no host was bound, before a hook can attempt network I/O. */
9
+ export function useMemoryPorts(_required = {}, _optional = {}) {
10
+ const ports = useContext(MemoryPortsContext);
11
+ if (!ports)
12
+ throw new Error('Memory hooks require MemoryPortsProvider');
13
+ return ports;
14
+ }
15
+ //# sourceMappingURL=MemoryPorts.js.map
@@ -22,8 +22,8 @@ export interface MemoryConfigController {
22
22
  }
23
23
  export declare function useMemoryConfig(port: MemoryConfigPort): MemoryConfigController;
24
24
  /**
25
- * Wirer: binds the real provider port and returns a ready-to-call hook. This is
26
- * the default a host injects; swap it via the component prop in tests.
25
+ * Reads the host-injected config port from MemoryPortsProvider (required).
26
+ * Hosts own authorization/transport; tests may inject a fake into useMemoryConfig.
27
27
  */
28
28
  export declare function useWiredMemoryConfig(): MemoryConfigController;
29
29
  //# sourceMappingURL=useMemoryConfig.hooks.d.ts.map
@@ -8,13 +8,13 @@
8
8
  // mocks, no global `fetch` stub.
9
9
  // - business logic (the pure `rules`) is imported directly; only the
10
10
  // side-effecting transport is injected.
11
- // - `useWiredMemoryConfig()` (the wirer, bottom of file) binds the real
12
- // provider port and is the default a host injects, so production callers
13
- // pass nothing while tests swap the whole hook.
11
+ // - useWiredMemoryConfig() (below) reads the host-injected config port from
12
+ // MemoryPortsProvider. Production hosts must mount that provider; tests inject
13
+ // a fake port directly or swap the hook. There is no implicit REST fallback.
14
14
  import { useCallback, useMemo, useRef, useState } from 'react';
15
15
  import { createAsyncCommitGuard } from '../../async-commit-guard.js';
16
16
  import { enabledPatch, singleFlagPatch } from '../../rules.js';
17
- import { memoryConfigPort } from '../../dependencies.js';
17
+ import { useMemoryPorts } from '../MemoryPorts.js';
18
18
  const CONFIG_SAVE_ERROR_MESSAGE = "Memory settings couldn't be saved. Try again shortly.";
19
19
  function newConfigWriteQueue() {
20
20
  return { inFlight: false, pending: null };
@@ -210,10 +210,10 @@ export function useMemoryConfig(port) {
210
210
  };
211
211
  }
212
212
  /**
213
- * Wirer: binds the real provider port and returns a ready-to-call hook. This is
214
- * the default a host injects; swap it via the component prop in tests.
213
+ * Reads the host-injected config port from MemoryPortsProvider (required).
214
+ * Hosts own authorization/transport; tests may inject a fake into useMemoryConfig.
215
215
  */
216
216
  export function useWiredMemoryConfig() {
217
- return useMemoryConfig(memoryConfigPort);
217
+ return useMemoryConfig(useMemoryPorts().config);
218
218
  }
219
219
  //# sourceMappingURL=useMemoryConfig.hooks.js.map
@@ -91,9 +91,8 @@ export declare function applyMemoryConnectorConnectResult({ connectorId, result,
91
91
  }): boolean;
92
92
  export declare function useMemoryConnectors(port: MemoryConnectorsPort, coord: MemoryConnectorsCoordination): MemoryConnectorsController;
93
93
  /**
94
- * Wirer: binds the real connectors transport + OAuth bridges and returns a
95
- * hook that still takes a host's runtime coordination. The default a host
96
- * injects; swap it via the component prop in tests.
94
+ * Reads the host-injected connector catalogue/OAuth bridges from MemoryPortsProvider
95
+ * (required), retaining runtime coordination. The deprecated demo catalogue is never a fallback.
97
96
  */
98
97
  export declare function useWiredMemoryConnectors(coord: MemoryConnectorsCoordination): MemoryConnectorsController;
99
98
  //# sourceMappingURL=useMemoryConnectors.hooks.d.ts.map
@@ -38,7 +38,7 @@ import { createAsyncCommitGuard } from '../../async-commit-guard.js';
38
38
  import { DEFAULT_CONNECTOR_PROVIDER, MEMORY_CONNECTOR_APP_IDS, MEMORY_CONNECTOR_APP_LABELS, } from '../../constants.js';
39
39
  import { describeExtractionFailure } from '../../formatters.js';
40
40
  import { applyMemoryConnectorStatus, connectorWithPendingAuthorization, memoryEntryIdForConnectorSuggestion, upsertMemoryConnector, } from '../../rules.js';
41
- import { memoryConnectorsPort } from '../../dependencies.js';
41
+ import { useMemoryPorts } from '../MemoryPorts.js';
42
42
  import { describeConnectorSuggestionOutcome, describeConnectorSuggestionsSaveOutcome, isRecentFailedConnectorExtraction, withoutKey, withoutSetMember, } from './useMemoryConnectors.rules.js';
43
43
  /** `onSaveConnectorSuggestions`'s save loop, isolated: writes each selected
44
44
  * suggestion as a memory entry in order, collecting which ones landed and
@@ -507,11 +507,10 @@ export function useMemoryConnectors(port, coord) {
507
507
  };
508
508
  }
509
509
  /**
510
- * Wirer: binds the real connectors transport + OAuth bridges and returns a
511
- * hook that still takes a host's runtime coordination. The default a host
512
- * injects; swap it via the component prop in tests.
510
+ * Reads the host-injected connector catalogue/OAuth bridges from MemoryPortsProvider
511
+ * (required), retaining runtime coordination. The deprecated demo catalogue is never a fallback.
513
512
  */
514
513
  export function useWiredMemoryConnectors(coord) {
515
- return useMemoryConnectors(memoryConnectorsPort, coord);
514
+ return useMemoryConnectors(useMemoryPorts().connectors, coord);
516
515
  }
517
516
  //# sourceMappingURL=useMemoryConnectors.hooks.js.map
@@ -44,9 +44,8 @@ export interface MemoryEntriesController {
44
44
  }
45
45
  export declare function useMemoryEntries(port: MemoryEntriesPort, coord: MemoryEntriesCoordination): MemoryEntriesController;
46
46
  /**
47
- * Wirer: binds the real entries transport and returns a hook that still takes
48
- * a host's runtime coordination. The default a host injects; swap it via the
49
- * component prop in tests.
47
+ * Reads the host-injected entries port from MemoryPortsProvider (required),
48
+ * retaining the host's runtime coordination. No /api/memory* transport is chosen implicitly.
50
49
  */
51
50
  export declare function useWiredMemoryEntries(coord: MemoryEntriesCoordination): MemoryEntriesController;
52
51
  //# sourceMappingURL=useMemoryEntries.hooks.d.ts.map
@@ -10,7 +10,7 @@ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
10
10
  import { copyToClipboard } from '../../../../utils/copy-to-clipboard.js';
11
11
  import { createAsyncCommitGuard } from '../../async-commit-guard.js';
12
12
  import { EMPTY_DRAFT } from '../../constants.js';
13
- import { memoryEntriesPort } from '../../dependencies.js';
13
+ import { useMemoryPorts } from '../MemoryPorts.js';
14
14
  const LOAD_ERROR_MESSAGE = "Memory data couldn't be loaded. Try again shortly.";
15
15
  const MUTATION_ERROR_MESSAGE = "Memory changes couldn't be saved. Try again shortly.";
16
16
  export function useMemoryEntries(port, coord) {
@@ -331,11 +331,10 @@ export function useMemoryEntries(port, coord) {
331
331
  };
332
332
  }
333
333
  /**
334
- * Wirer: binds the real entries transport and returns a hook that still takes
335
- * a host's runtime coordination. The default a host injects; swap it via the
336
- * component prop in tests.
334
+ * Reads the host-injected entries port from MemoryPortsProvider (required),
335
+ * retaining the host's runtime coordination. No /api/memory* transport is chosen implicitly.
337
336
  */
338
337
  export function useWiredMemoryEntries(coord) {
339
- return useMemoryEntries(memoryEntriesPort, coord);
338
+ return useMemoryEntries(useMemoryPorts().entries, coord);
340
339
  }
341
340
  //# sourceMappingURL=useMemoryEntries.hooks.js.map
@@ -13,7 +13,7 @@
13
13
  // store's synchronous transitions to React state.
14
14
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
15
15
  import { createAsyncCommitGuard } from '../../async-commit-guard.js';
16
- import { memoryExtractionsPort } from '../../dependencies.js';
16
+ import { useMemoryPorts } from '../MemoryPorts.js';
17
17
  import { createExtractionHistoryStore } from './useMemoryExtractions.store.js';
18
18
  const LOAD_ERROR_MESSAGE = "Memory extraction history couldn't be loaded. Try again shortly.";
19
19
  const MUTATION_ERROR_MESSAGE = "Memory extraction history couldn't be updated. Try again shortly.";
@@ -176,6 +176,6 @@ export function useMemoryExtractions(port) {
176
176
  };
177
177
  }
178
178
  export function useWiredMemoryExtractions() {
179
- return useMemoryExtractions(memoryExtractionsPort);
179
+ return useMemoryExtractions(useMemoryPorts().extractions);
180
180
  }
181
181
  //# sourceMappingURL=useMemoryExtractions.hooks.js.map
@@ -1,6 +1,6 @@
1
1
  import { type ReactNode } from 'react';
2
- import { type FetchQueryEnvironmentPort } from './cache.js';
3
- import type { CachedLoader, CachedLoaderOptions, FetchMutationOptions, FetchQueryOptions, MutationResult, QueryKey, QueryResult } from './types.js';
2
+ import { type FetchQueryEnvironmentPort } from '@jini-ai/core/fetch';
3
+ import type { CachedLoader, CachedLoaderOptions, FetchMutationOptions, FetchQueryOptions, MutationResult, QueryKey, QueryResult } from '@jini-ai/core/fetch';
4
4
  /** Isolated cache scope; no external provider or query-library singleton is needed. */
5
5
  export declare function FetchQueryProvider({ children, environment }: {
6
6
  children: ReactNode;
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
3
- import { DEFAULT_STALE_TIME, FetchQueryCache, toQueryError } from './cache.js';
3
+ import { DEFAULT_STALE_TIME, FetchQueryCache, toQueryError } from '@jini-ai/core/fetch';
4
4
  import { browserFetchQueryEnvironment } from './environment.browser.js';
5
5
  import { FetchQueryBinding } from './binding.react.js';
6
6
  const CacheContext = createContext(null);
@@ -109,7 +109,7 @@ export function useCachedLoader({ key, fetch }, { staleTime = DEFAULT_STALE_TIME
109
109
  const cache = useCache();
110
110
  return useMemo(() => ({
111
111
  peek: () => cache.entry({ key: key }, { staleTime: staleTime }).state.data,
112
- load: () => cache.load({ entry: cache.entry({ key: key }, { staleTime: staleTime }), fetch: fetch, staleTime: staleTime }),
112
+ load: (required = { key, fetch }) => cache.load({ entry: cache.entry({ key: required.key }, { staleTime }), fetch: required.fetch, staleTime }),
113
113
  replace: ({ value }) => cache.replace({ entry: cache.entry({ key: key }, { staleTime: staleTime }), data: value }),
114
114
  }), [cache, key, fetch, staleTime]);
115
115
  }
@@ -1,6 +1,6 @@
1
1
  /** Optional TanStack translation layer. No library types escape the fetch-query contract. */
2
2
  import { type ReactNode } from 'react';
3
- import { type FetchQueryEnvironmentPort } from './cache.js';
3
+ import { type FetchQueryEnvironmentPort } from '@jini-ai/core/fetch';
4
4
  /** Provider-owned TanStack cache and binding, compatible with hooks from the default entry.
5
5
  * @example <FetchQueryProvider><ResourceScreen /></FetchQueryProvider>
6
6
  * @param props Children and optional host connectivity/focus port. */
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  /** Optional TanStack translation layer. No library types escape the fetch-query contract. */
3
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useSyncExternalStore } from 'react';
4
4
  import { isCancelledError, QueryClient, QueryClientProvider, useMutation, useQuery } from '@tanstack/react-query';
5
- import { DEFAULT_STALE_TIME, FetchQueryCache, IDLE_RETENTION, toQueryError } from './cache.js';
5
+ import { DEFAULT_STALE_TIME, FetchQueryCache, IDLE_RETENTION, toQueryError } from '@jini-ai/core/fetch';
6
6
  import { browserFetchQueryEnvironment } from './environment.browser.js';
7
7
  import { resolveFetchQueryError, resolveFetchQueryStatus } from './adapter.react.js';
8
8
  import { FetchQueryBinding } from './binding.react.js';
@@ -106,13 +106,14 @@ function useFetchQuery({ key, fetch }, { enabled = true, staleTime = DEFAULT_STA
106
106
  const { refetch: refresh } = query;
107
107
  const refetch = useCallback(() => {
108
108
  if (scope.environment.isOnline()) {
109
+ supersedeInitialRead({ scope, key });
109
110
  void refresh();
110
111
  return;
111
112
  }
112
113
  // Reconnect may already have started a fetch (re-enabled observer or provider refetch);
113
114
  // that request postdates this one, so join it instead of cancelling it into a duplicate.
114
115
  void scope.gate.runOnline({ run: () => refresh({ cancelRefetch: false }) });
115
- }, [scope, refresh]);
116
+ }, [scope, refresh, JSON.stringify(key)]);
116
117
  useEffect(() => {
117
118
  if (!enabled || !refetchOnWindowFocus)
118
119
  return;
@@ -143,7 +144,7 @@ function useFetchMutation({ run }, { invalidates } = {}) {
143
144
  // Do not await dependent reads: the mutation promise means the write succeeded,
144
145
  // not that every list finished reloading. Refetches proceed on their own schedule.
145
146
  for (const key of invalidates ?? [])
146
- void scope.client.invalidateQueries({ queryKey: key });
147
+ invalidateResource({ scope, key });
147
148
  },
148
149
  }, scope.client);
149
150
  const { mutateAsync, reset } = mutation;
@@ -163,14 +164,21 @@ function useCachedLoader({ key, fetch }, { staleTime = DEFAULT_STALE_TIME } = {}
163
164
  const options = { queryKey: key, queryFn: () => read({ scope, key, fetch }), staleTime, gcTime: gcTimeFor({ staleTime }) };
164
165
  return {
165
166
  peek: () => scope.client.getQueryData(key),
166
- load: () => scope.client.fetchQuery(options).catch(error => {
167
- // A forced refresh can supersede a loader's request without aborting its transport.
168
- // Follow the new request instead of exposing TanStack's cancellation vocabulary.
169
- if (!isCancelledError(error))
170
- throw error;
171
- const query = scope.client.getQueryCache().find({ queryKey: key, exact: true });
172
- return (query.promise ?? scope.client.getQueryData(key));
173
- }),
167
+ load: (required = { key, fetch }) => {
168
+ const selected = { ...options, queryKey: required.key, queryFn: () => read({ scope, key: required.key, fetch: required.fetch }) };
169
+ return scope.client.fetchQuery(selected).catch(error => {
170
+ // A forced refresh can supersede a loader's request without aborting its transport.
171
+ // Follow the new request instead of exposing TanStack's cancellation vocabulary.
172
+ if (!isCancelledError(error))
173
+ throw error;
174
+ // Invalidation also supersedes loader-only reads. Join (or start) the post-write
175
+ // request rather than returning an obsolete value while the key is invalidated.
176
+ const query = scope.client.getQueryCache().find({ queryKey: required.key, exact: true });
177
+ if (query.state.isInvalidated)
178
+ return scope.client.fetchQuery(selected);
179
+ return (query.promise ?? scope.client.getQueryData(required.key));
180
+ });
181
+ },
174
182
  replace: ({ value }) => {
175
183
  const query = scope.client.getQueryCache().build(scope.client, options);
176
184
  const history = historyFor({ scope, query });
@@ -181,10 +189,24 @@ function useCachedLoader({ key, fetch }, { staleTime = DEFAULT_STALE_TIME } = {}
181
189
  };
182
190
  }, [scope, key, fetch, staleTime]);
183
191
  }
192
+ /** A host write/refresh postdates the initial GET as well as a background GET. TanStack
193
+ * normally joins an initial fetch with no data, which would let that pre-write snapshot win.
194
+ * Cancel its cache ownership before requesting the replacement; transports need no abort API. */
195
+ function supersedeInitialRead({ scope, key }, { exact = true } = {}) {
196
+ void scope.client.cancelQueries({ queryKey: key, exact, predicate: query => query.isActive() && query.state.data === undefined && query.state.fetchStatus === 'fetching' });
197
+ }
198
+ /** One invalidation path serves both imperative refreshes and accepted writes. */
199
+ function invalidateResource({ scope, key }, _optional = {}) {
200
+ // A loader-only detail request may feed an active parent query. It is just as stale
201
+ // after a write as an observed read, even though TanStack considers it inactive.
202
+ // Silent cancellation follows the replacement promise instead of resolving old cached data.
203
+ void scope.client.cancelQueries({ queryKey: key, predicate: query => query.state.fetchStatus === 'fetching' }, { silent: true });
204
+ void scope.client.invalidateQueries({ queryKey: key });
205
+ }
184
206
  /** Prefix invalidation also reaches child keys read by other mounted consumers. */
185
207
  function useInvalidate() {
186
- const { client } = useScope();
187
- return useCallback(({ key }) => { void client.invalidateQueries({ queryKey: key }); }, [client]);
208
+ const scope = useScope();
209
+ return useCallback(({ key }) => { invalidateResource({ scope, key }); }, [scope]);
188
210
  }
189
211
  const adapter = { useFetchQuery, useFetchMutation, useCachedLoader, useInvalidate };
190
212
  //# sourceMappingURL=adapter.tanstack.js.map
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { FetchQueryAdapter } from './types.js';
2
+ import type { FetchQueryAdapter } from '@jini-ai/core/fetch';
3
3
  /** Internal composition seam: hooks and imperative loaders always use the same provider.
4
4
  * Keep the adapter fixed for this provider's lifetime to preserve React hook ordering. */
5
5
  export declare function FetchQueryBinding({ adapter, children }: {
@@ -1,4 +1,4 @@
1
- import type { FetchQueryEnvironmentPort } from './cache.js';
1
+ import type { FetchQueryEnvironmentPort } from '@jini-ai/core/fetch';
2
2
  /** Browser-only adapter: subscriptions are owned by the provider effect, never module scope. */
3
3
  export declare const browserFetchQueryEnvironment: FetchQueryEnvironmentPort;
4
4
  //# sourceMappingURL=environment.browser.d.ts.map
@@ -1,5 +1,7 @@
1
1
  export { FetchQueryProvider } from './adapter.react.js';
2
2
  export { useFetchQuery, useFetchMutation, useCachedLoader, useInvalidate } from './binding.react.js';
3
- export type { FetchQueryEnvironmentPort } from './cache.js';
4
- export type { QueryKey, QueryStatus, QueryResult, FetchQueryOptions, MutationStatus, MutationResult, FetchMutationOptions, CachedLoaderOptions, CachedLoader, FetchQueryAdapter } from './types.js';
3
+ /** @deprecated Import the framework-neutral environment port from @jini-ai/core/fetch. */
4
+ export type { FetchQueryEnvironmentPort } from '@jini-ai/core/fetch';
5
+ /** @deprecated Import framework-neutral query contracts from @jini-ai/core/fetch. */
6
+ export type { QueryKey, QueryStatus, QueryResult, FetchQueryOptions, MutationStatus, MutationResult, FetchMutationOptions, CachedLoaderOptions, CachedLoader, FetchQueryAdapter } from '@jini-ai/core/fetch';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1,6 +1,8 @@
1
1
  /** Optional adapter entry. Importing the default entry never loads TanStack. */
2
2
  export { FetchQueryProvider } from './adapter.tanstack.js';
3
3
  export { useFetchQuery, useFetchMutation, useCachedLoader, useInvalidate } from './binding.react.js';
4
- export type { FetchQueryEnvironmentPort } from './cache.js';
5
- export type { QueryKey, QueryStatus, QueryResult, FetchQueryOptions, MutationStatus, MutationResult, FetchMutationOptions, CachedLoaderOptions, CachedLoader, FetchQueryAdapter } from './types.js';
4
+ /** @deprecated Import the framework-neutral environment port from @jini-ai/core/fetch. */
5
+ export type { FetchQueryEnvironmentPort } from '@jini-ai/core/fetch';
6
+ /** @deprecated Import framework-neutral query contracts from @jini-ai/core/fetch. */
7
+ export type { QueryKey, QueryStatus, QueryResult, FetchQueryOptions, MutationStatus, MutationResult, FetchMutationOptions, CachedLoaderOptions, CachedLoader, FetchQueryAdapter } from '@jini-ai/core/fetch';
6
8
  //# sourceMappingURL=tanstack.d.ts.map
@@ -4,5 +4,7 @@ export declare function standingDraftRecoveryMessage({ draft, t, serverUpdatedAt
4
4
  draft: StandingDraftAutosaveSnapshot;
5
5
  t: (key: string) => string;
6
6
  serverUpdatedAt?: string;
7
- }, _options?: {}): string;
7
+ }, { formatSavedAt }?: {
8
+ formatSavedAt?: (iso: string) => string;
9
+ }): string;
8
10
  //# sourceMappingURL=standing-draft-recovery-message.d.ts.map