@parlor/client 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +2 -0
  2. package/dist/action-client.d.ts +2 -0
  3. package/dist/action-client.d.ts.map +1 -1
  4. package/dist/action-client.js +13 -4
  5. package/dist/action-client.js.map +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugin-client.js.map +1 -1
  10. package/dist/query-keys.js.map +1 -1
  11. package/dist/react/action-query.d.ts +26 -0
  12. package/dist/react/action-query.d.ts.map +1 -0
  13. package/dist/react/action-query.js +33 -0
  14. package/dist/react/action-query.js.map +1 -0
  15. package/dist/react/agent-ui/activity-state.js.map +1 -1
  16. package/dist/react/agent-ui/chat-activity.js.map +1 -1
  17. package/dist/react/agent-ui/chat-confirm.js.map +1 -1
  18. package/dist/react/agent-ui/chat.js.map +1 -1
  19. package/dist/react/agent-ui/dev.js.map +1 -1
  20. package/dist/react/agent-ui/runtime.js.map +1 -1
  21. package/dist/react/agent-ui/use-agent-activity.js.map +1 -1
  22. package/dist/react/agent-ui/use-agent-confirmations.js.map +1 -1
  23. package/dist/react/agent-ui/use-agent-view.js.map +1 -1
  24. package/dist/react/chat/ask-fields.js.map +1 -1
  25. package/dist/react/chat/chat-ask.d.ts +3 -2
  26. package/dist/react/chat/chat-ask.d.ts.map +1 -1
  27. package/dist/react/chat/chat-ask.js +3 -2
  28. package/dist/react/chat/chat-ask.js.map +1 -1
  29. package/dist/react/chat/chat-composer.d.ts.map +1 -1
  30. package/dist/react/chat/chat-composer.js +1 -1
  31. package/dist/react/chat/chat-composer.js.map +1 -1
  32. package/dist/react/chat/chat-root.js.map +1 -1
  33. package/dist/react/chat/chat-thread.js.map +1 -1
  34. package/dist/react/chat/context.js.map +1 -1
  35. package/dist/react/chat/create.js.map +1 -1
  36. package/dist/react/chat/open-turns.js.map +1 -1
  37. package/dist/react/chat/runtime.d.ts +29 -4
  38. package/dist/react/chat/runtime.d.ts.map +1 -1
  39. package/dist/react/chat/runtime.js +82 -11
  40. package/dist/react/chat/runtime.js.map +1 -1
  41. package/dist/react/chat/use-chat.d.ts.map +1 -1
  42. package/dist/react/chat/use-chat.js +2 -0
  43. package/dist/react/chat/use-chat.js.map +1 -1
  44. package/dist/react/chat/use-device-setup.js.map +1 -1
  45. package/dist/react/hooks.d.ts +7 -1
  46. package/dist/react/hooks.d.ts.map +1 -1
  47. package/dist/react/hooks.js +17 -13
  48. package/dist/react/hooks.js.map +1 -1
  49. package/dist/react/index.d.ts +3 -2
  50. package/dist/react/index.d.ts.map +1 -1
  51. package/dist/react/index.js +2 -1
  52. package/dist/react/index.js.map +1 -1
  53. package/dist/react/provider.d.ts +6 -3
  54. package/dist/react/provider.d.ts.map +1 -1
  55. package/dist/react/provider.js +61 -11
  56. package/dist/react/provider.js.map +1 -1
  57. package/dist/react/retry.js.map +1 -1
  58. package/dist/react/sync-bridge.d.ts +4 -1
  59. package/dist/react/sync-bridge.d.ts.map +1 -1
  60. package/dist/react/sync-bridge.js.map +1 -1
  61. package/dist/react/sync.d.ts +41 -2
  62. package/dist/react/sync.d.ts.map +1 -1
  63. package/dist/react/sync.js +127 -9
  64. package/dist/react/sync.js.map +1 -1
  65. package/dist/react/use-capability.js.map +1 -1
  66. package/dist/react/use-devices.js.map +1 -1
  67. package/dist/react/use-link-device.js.map +1 -1
  68. package/dist/register.js.map +1 -1
  69. package/dist/router/errors.d.ts +13 -0
  70. package/dist/router/errors.d.ts.map +1 -0
  71. package/dist/router/errors.js +16 -0
  72. package/dist/router/errors.js.map +1 -0
  73. package/dist/router/index.d.ts +4 -0
  74. package/dist/router/index.d.ts.map +1 -0
  75. package/dist/router/index.js +4 -0
  76. package/dist/router/index.js.map +1 -0
  77. package/dist/router/mount.d.ts +22 -0
  78. package/dist/router/mount.d.ts.map +1 -0
  79. package/dist/router/mount.js +27 -0
  80. package/dist/router/mount.js.map +1 -0
  81. package/dist/router/router.d.ts +29 -0
  82. package/dist/router/router.d.ts.map +1 -0
  83. package/dist/router/router.js +44 -0
  84. package/dist/router/router.js.map +1 -0
  85. package/dist/session.d.ts +7 -1
  86. package/dist/session.d.ts.map +1 -1
  87. package/dist/session.js.map +1 -1
  88. package/dist/ssr/index.d.ts +2 -0
  89. package/dist/ssr/index.d.ts.map +1 -0
  90. package/dist/ssr/index.js +2 -0
  91. package/dist/ssr/index.js.map +1 -0
  92. package/dist/ssr/render.d.ts +18 -0
  93. package/dist/ssr/render.d.ts.map +1 -0
  94. package/dist/ssr/render.js +96 -0
  95. package/dist/ssr/render.js.map +1 -0
  96. package/package.json +15 -7
@@ -1,10 +1,16 @@
1
1
  import type { ActionError, ActionInput, ActionOutput } from "@parlor/core";
2
- import { type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult } from "@tanstack/react-query";
2
+ import { type UseMutationOptions, type UseMutationResult, type UseQueryOptions, type UseQueryResult, type UseSuspenseQueryOptions, type UseSuspenseQueryResult } from "@tanstack/react-query";
3
3
  import type { RegisteredActions } from "../register.js";
4
4
  type Actions = RegisteredActions;
5
5
  type Name = keyof Actions & string;
6
6
  export type ActionQueryOptions<K extends Name> = Omit<UseQueryOptions<ActionOutput<Actions[K]>, ActionError>, "queryKey" | "queryFn">;
7
7
  export declare function useActionQuery<K extends Name>(name: K, input: ActionInput<Actions[K]>, options?: ActionQueryOptions<K>): UseQueryResult<ActionOutput<Actions[K]>, ActionError>;
8
+ export type ActionSuspenseQueryOptions<K extends Name> = Omit<UseSuspenseQueryOptions<ActionOutput<Actions[K]>, ActionError>, "queryKey" | "queryFn">;
9
+ /**
10
+ * `useActionQuery` as a TanStack Query `useSuspenseQuery`: `data` is always there. It suspends
11
+ * until the action answers, unless a route `loader` already ran `ensureActionQueryData`.
12
+ */
13
+ export declare function useActionSuspenseQuery<K extends Name>(name: K, input: ActionInput<Actions[K]>, options?: ActionSuspenseQueryOptions<K>): UseSuspenseQueryResult<ActionOutput<Actions[K]>, ActionError>;
8
14
  export type ActionMutationOptions<K extends Name> = Omit<UseMutationOptions<ActionOutput<Actions[K]>, ActionError, ActionInput<Actions[K]>>, "mutationFn">;
9
15
  export declare function useActionMutation<K extends Name>(name: K, options?: ActionMutationOptions<K>): UseMutationResult<ActionOutput<Actions[K]>, ActionError, ActionInput<Actions[K]>>;
10
16
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EAIpB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,KAAK,OAAO,GAAG,iBAAiB,CAAC;AACjC,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CACnD,eAAe,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EACtD,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,SAAS,IAAI,EAC3C,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC9B,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAcvD;AAED,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CACtD,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAClF,YAAY,CACb,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,IAAI,EAC9C,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAWnF"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAK5B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,KAAK,OAAO,GAAG,iBAAiB,CAAC;AACjC,KAAK,IAAI,GAAG,MAAM,OAAO,GAAG,MAAM,CAAC;AAEnC,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CACnD,eAAe,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EACtD,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF,wBAAgB,cAAc,CAAC,CAAC,SAAS,IAAI,EAC3C,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAC9B,cAAc,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAKvD;AAED,MAAM,MAAM,0BAA0B,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CAC3D,uBAAuB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,EAC9D,UAAU,GAAG,SAAS,CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,IAAI,EACnD,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAC9B,OAAO,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACtC,sBAAsB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAK/D;AAMD,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,IAAI,IAAI,IAAI,CACtD,kBAAkB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAClF,YAAY,CACb,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,IAAI,EAC9C,IAAI,EAAE,CAAC,EACP,OAAO,CAAC,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,iBAAiB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAWnF"}
@@ -1,22 +1,26 @@
1
- import { hashKey, useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
2
- import { ACTION_QUERY_PREFIX, actionQueryKey } from "../query-keys.js";
1
+ import { useMutation, useQuery, useQueryClient, useSuspenseQuery, } from "@tanstack/react-query";
2
+ import { ACTION_QUERY_PREFIX } from "../query-keys.js";
3
+ import { actionQueryOptions } from "./action-query.js";
3
4
  import { useFramework } from "./provider.js";
4
- import { actionRetry } from "./retry.js";
5
5
  export function useActionQuery(name, input, options) {
6
- const { client, readTags } = useFramework();
7
- const queryClient = useQueryClient();
8
- const queryKey = actionQueryKey(name, input);
9
6
  return useQuery({
7
+ ...actionQueryOptions(useActionQueryContext(), name, input),
8
+ ...options,
9
+ });
10
+ }
11
+ /**
12
+ * `useActionQuery` as a TanStack Query `useSuspenseQuery`: `data` is always there. It suspends
13
+ * until the action answers, unless a route `loader` already ran `ensureActionQueryData`.
14
+ */
15
+ export function useActionSuspenseQuery(name, input, options) {
16
+ return useSuspenseQuery({
17
+ ...actionQueryOptions(useActionQueryContext(), name, input),
10
18
  ...options,
11
- retry: options?.retry ?? actionRetry(queryClient.getDefaultOptions().queries?.retry),
12
- queryKey,
13
- queryFn: async ({ signal }) => {
14
- const envelope = await client.invoke(name, input, { signal });
15
- readTags.record(hashKey(queryKey), envelope.tags);
16
- return envelope.data;
17
- },
18
19
  });
19
20
  }
21
+ function useActionQueryContext() {
22
+ return { client: useFramework().client, queryClient: useQueryClient() };
23
+ }
20
24
  export function useActionMutation(name, options) {
21
25
  const { client } = useFramework();
22
26
  const queryClient = useQueryClient();
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,OAAO,EAKP,WAAW,EACX,QAAQ,EACR,cAAc,GACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAUzC,MAAM,UAAU,cAAc,CAC5B,IAAO,EACP,KAA8B,EAC9B,OAA+B;IAE/B,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC;QACd,GAAG,OAAO;QACV,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,WAAW,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC;QACpF,QAAQ;QACR,OAAO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;YAC5B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC9D,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAClD,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAC/B,IAAO,EACP,OAAkC;IAElC,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,GAAG,OAAO;QACV,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;QAC/C,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;YAC5D,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACvE,MAAM,OAAO,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,WAAW,EACX,QAAQ,EACR,cAAc,EACd,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAA2B,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAU7C,MAAM,UAAU,cAAc,CAC5B,IAAO,EACP,KAA8B,EAC9B,OAA+B;IAE/B,OAAO,QAAQ,CAAC;QACd,GAAG,kBAAkB,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC;QAC3D,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAOD;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAAO,EACP,KAA8B,EAC9B,OAAuC;IAEvC,OAAO,gBAAgB,CAAC;QACtB,GAAG,kBAAkB,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC;QAC3D,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB;IAC5B,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,EAAE,CAAC;AAC1E,CAAC;AAOD,MAAM,UAAU,iBAAiB,CAC/B,IAAO,EACP,OAAkC;IAElC,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,OAAO,WAAW,CAAC;QACjB,GAAG,OAAO;QACV,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;QAC/C,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE;YAC5D,MAAM,WAAW,CAAC,iBAAiB,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC,CAAC;YACvE,MAAM,OAAO,EAAE,SAAS,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ActionError, ActionInput, ActionOutput } from \"@parlor/core\";\nimport {\n type UseMutationOptions,\n type UseMutationResult,\n type UseQueryOptions,\n type UseQueryResult,\n type UseSuspenseQueryOptions,\n type UseSuspenseQueryResult,\n useMutation,\n useQuery,\n useQueryClient,\n useSuspenseQuery,\n} from \"@tanstack/react-query\";\n\nimport { ACTION_QUERY_PREFIX } from \"../query-keys.js\";\nimport type { RegisteredActions } from \"../register.js\";\nimport { type ActionQueryContext, actionQueryOptions } from \"./action-query.js\";\nimport { useFramework } from \"./provider.js\";\n\ntype Actions = RegisteredActions;\ntype Name = keyof Actions & string;\n\nexport type ActionQueryOptions<K extends Name> = Omit<\n UseQueryOptions<ActionOutput<Actions[K]>, ActionError>,\n \"queryKey\" | \"queryFn\"\n>;\n\nexport function useActionQuery<K extends Name>(\n name: K,\n input: ActionInput<Actions[K]>,\n options?: ActionQueryOptions<K>,\n): UseQueryResult<ActionOutput<Actions[K]>, ActionError> {\n return useQuery({\n ...actionQueryOptions(useActionQueryContext(), name, input),\n ...options,\n });\n}\n\nexport type ActionSuspenseQueryOptions<K extends Name> = Omit<\n UseSuspenseQueryOptions<ActionOutput<Actions[K]>, ActionError>,\n \"queryKey\" | \"queryFn\"\n>;\n\n/**\n * `useActionQuery` as a TanStack Query `useSuspenseQuery`: `data` is always there. It suspends\n * until the action answers, unless a route `loader` already ran `ensureActionQueryData`.\n */\nexport function useActionSuspenseQuery<K extends Name>(\n name: K,\n input: ActionInput<Actions[K]>,\n options?: ActionSuspenseQueryOptions<K>,\n): UseSuspenseQueryResult<ActionOutput<Actions[K]>, ActionError> {\n return useSuspenseQuery({\n ...actionQueryOptions(useActionQueryContext(), name, input),\n ...options,\n });\n}\n\nfunction useActionQueryContext(): ActionQueryContext {\n return { client: useFramework().client, queryClient: useQueryClient() };\n}\n\nexport type ActionMutationOptions<K extends Name> = Omit<\n UseMutationOptions<ActionOutput<Actions[K]>, ActionError, ActionInput<Actions[K]>>,\n \"mutationFn\"\n>;\n\nexport function useActionMutation<K extends Name>(\n name: K,\n options?: ActionMutationOptions<K>,\n): UseMutationResult<ActionOutput<Actions[K]>, ActionError, ActionInput<Actions[K]>> {\n const { client } = useFramework();\n const queryClient = useQueryClient();\n return useMutation({\n ...options,\n mutationFn: (input) => client.call(name, input),\n onSuccess: async (data, variables, onMutateResult, context) => {\n await queryClient.invalidateQueries({ queryKey: ACTION_QUERY_PREFIX });\n await options?.onSuccess?.(data, variables, onMutateResult, context);\n },\n });\n}\n"]}
@@ -4,7 +4,7 @@ export * as Chat from "./agent-ui/chat.js";
4
4
  export type { ChatAskChoiceProps, ChatAskFormProps, ChatAskProps, } from "./chat/chat-ask.js";
5
5
  export type { ChatRootProps } from "./chat/chat-root.js";
6
6
  export type { ChatThreadProps } from "./chat/chat-thread.js";
7
- export type { AgentChoice, ChatCommands, ChatState, ChatStatus, ChatWait, ConnectOption, DeviceSetup, DeviceSetupCommands, LinkState, } from "./chat/runtime.js";
7
+ export type { AgentChoice, AgentChoiceOption, ChatCommands, ChatState, ChatStatus, ChatUnavailable, ChatWait, ConnectOption, DeviceSetup, DeviceSetupCommands, LinkState, } from "./chat/runtime.js";
8
8
  export { useChat } from "./chat/use-chat.js";
9
9
  export { useDeviceSetup } from "./chat/use-device-setup.js";
10
10
  export { type RemoveDeviceState, useDevices } from "./use-devices.js";
@@ -13,7 +13,8 @@ export type { ChatItem } from "@parlor/chat";
13
13
  export { useAgentActivity } from "./agent-ui/use-agent-activity.js";
14
14
  export { useAgentConfirmations } from "./agent-ui/use-agent-confirmations.js";
15
15
  export { type AgentViewHandle, useAgentView } from "./agent-ui/use-agent-view.js";
16
- export { type ActionMutationOptions, type ActionQueryOptions, useActionMutation, useActionQuery, } from "./hooks.js";
16
+ export { type ActionQueryContext, actionQueryOptions, ensureActionQueryData, } from "./action-query.js";
17
+ export { type ActionMutationOptions, type ActionQueryOptions, type ActionSuspenseQueryOptions, useActionMutation, useActionQuery, useActionSuspenseQuery, } from "./hooks.js";
17
18
  export { FrameworkProvider, type FrameworkProviderProps, useActionClient, useSession, } from "./provider.js";
18
19
  export { type CapabilityState, useCapability } from "./use-capability.js";
19
20
  export { invalidateForEvents, ReadTagRegistry } from "./sync.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;AAC3C,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,KAAK,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,eAAe,EACf,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;AAC3C,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,SAAS,EACT,UAAU,EACV,eAAe,EACf,QAAQ,EACR,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC3E,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAE,KAAK,eAAe,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EACL,KAAK,kBAAkB,EACvB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,iBAAiB,EACjB,cAAc,EACd,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,eAAe,EACf,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
@@ -6,7 +6,8 @@ export { useLinkDevice } from "./use-link-device.js";
6
6
  export { useAgentActivity } from "./agent-ui/use-agent-activity.js";
7
7
  export { useAgentConfirmations } from "./agent-ui/use-agent-confirmations.js";
8
8
  export { useAgentView } from "./agent-ui/use-agent-view.js";
9
- export { useActionMutation, useActionQuery, } from "./hooks.js";
9
+ export { actionQueryOptions, ensureActionQueryData, } from "./action-query.js";
10
+ export { useActionMutation, useActionQuery, useActionSuspenseQuery, } from "./hooks.js";
10
11
  export { FrameworkProvider, useActionClient, useSession, } from "./provider.js";
11
12
  export { useCapability } from "./use-capability.js";
12
13
  export { invalidateForEvents, ReadTagRegistry } from "./sync.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;AAmB3C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAA0B,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAwB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAwB,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAGL,iBAAiB,EACjB,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EAEjB,eAAe,EACf,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAwB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,IAAI,MAAM,oBAAoB,CAAC;AAqB3C,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAA0B,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAwB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAC9E,OAAO,EAAwB,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAEL,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAIL,iBAAiB,EACjB,cAAc,EACd,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EAEjB,eAAe,EACf,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAwB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC","sourcesContent":["export type {\n AgentActivity,\n AgentActivityKind,\n AgentOutcome,\n AgentConfirmation,\n} from \"@parlor/agent-ui/client\";\nexport type { AgentActivityState } from \"./agent-ui/activity-state.js\";\nexport * as Chat from \"./agent-ui/chat.js\";\nexport type {\n ChatAskChoiceProps,\n ChatAskFormProps,\n ChatAskProps,\n} from \"./chat/chat-ask.js\";\nexport type { ChatRootProps } from \"./chat/chat-root.js\";\nexport type { ChatThreadProps } from \"./chat/chat-thread.js\";\nexport type {\n AgentChoice,\n AgentChoiceOption,\n ChatCommands,\n ChatState,\n ChatStatus,\n ChatUnavailable,\n ChatWait,\n ConnectOption,\n DeviceSetup,\n DeviceSetupCommands,\n LinkState,\n} from \"./chat/runtime.js\";\nexport { useChat } from \"./chat/use-chat.js\";\nexport { useDeviceSetup } from \"./chat/use-device-setup.js\";\nexport { type RemoveDeviceState, useDevices } from \"./use-devices.js\";\nexport { type LinkDeviceState, useLinkDevice } from \"./use-link-device.js\";\nexport type { ChatItem } from \"@parlor/chat\";\nexport { useAgentActivity } from \"./agent-ui/use-agent-activity.js\";\nexport { useAgentConfirmations } from \"./agent-ui/use-agent-confirmations.js\";\nexport { type AgentViewHandle, useAgentView } from \"./agent-ui/use-agent-view.js\";\nexport {\n type ActionQueryContext,\n actionQueryOptions,\n ensureActionQueryData,\n} from \"./action-query.js\";\nexport {\n type ActionMutationOptions,\n type ActionQueryOptions,\n type ActionSuspenseQueryOptions,\n useActionMutation,\n useActionQuery,\n useActionSuspenseQuery,\n} from \"./hooks.js\";\nexport {\n FrameworkProvider,\n type FrameworkProviderProps,\n useActionClient,\n useSession,\n} from \"./provider.js\";\nexport { type CapabilityState, useCapability } from \"./use-capability.js\";\nexport { invalidateForEvents, ReadTagRegistry } from \"./sync.js\";\n"]}
@@ -6,7 +6,7 @@ import type { ActionClient } from "../action-client.js";
6
6
  import type { RegisteredActions } from "../register.js";
7
7
  import type { FrameworkAuth, SessionSnapshot } from "../session.js";
8
8
  import { type FrameworkSync, SyncBridge } from "./sync-bridge.js";
9
- import { ReadTagRegistry } from "./sync.js";
9
+ import { type ReadTagRegistry } from "./sync.js";
10
10
  interface FrameworkContextValue {
11
11
  readonly client: ActionClient<RegisteredActions>;
12
12
  readonly readTags: ReadTagRegistry;
@@ -17,12 +17,15 @@ interface FrameworkContextValue {
17
17
  }
18
18
  export interface FrameworkProviderProps {
19
19
  readonly client: ActionClient<RegisteredActions>;
20
+ /** Defaults to the router's `context.queryClient`, so loaders and hooks share one cache. */
20
21
  readonly queryClient?: QueryClient | undefined;
21
22
  readonly sync?: boolean | undefined;
22
23
  readonly router?: AnyRouter | undefined;
23
24
  /**
24
- * When the signed-in user changes, cached queries reset and sync reconnects as them. An
25
- * auth client that can also sign (`device`) and pair hosts (`authorizeHost`) gives the chat both.
25
+ * When the signed-in user changes, cached queries reset and sync reconnects as them. Sync
26
+ * waits for a signed-in or `anonymous` session, and after the server refuses it, for the
27
+ * session to change. An auth client that can also sign (`device`) and pair hosts
28
+ * (`authorizeHost`) gives the chat both.
26
29
  */
27
30
  readonly auth?: FrameworkAuth | undefined;
28
31
  readonly children: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAEL,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAEnF,OAAO,EAAE,KAAK,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAuB,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjE,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAID,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AAgCD,oFAAoF;AACpF,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,WAAW,EACX,IAAW,EACX,MAAM,EACN,IAAI,EACJ,QAAQ,GACT,EAAE,sBAAsB,+BAqDxB;AA2CD,wBAAgB,YAAY,IAAI,qBAAqB,CAIpD;AAED,wBAAgB,eAAe,IAAI,YAAY,CAAC,iBAAiB,CAAC,CAEjE;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,IAAI,eAAe,CAI5C"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAEL,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAiB,MAAM,eAAe,CAAC;AAEnF,OAAO,EAAE,KAAK,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,WAAW,CAAC;AAEnB,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAID,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjD,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC9B;AA6CD,oFAAoF;AACpF,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,WAAW,EACX,IAAW,EACX,MAAM,EACN,IAAI,EACJ,QAAQ,GACT,EAAE,sBAAsB,+BAsDxB;AAgFD,wBAAgB,YAAY,IAAI,qBAAqB,CAIpD;AAED,wBAAgB,eAAe,IAAI,YAAY,CAAC,iBAAiB,CAAC,CAEjE;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,IAAI,eAAe,CAI5C"}
@@ -4,9 +4,12 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
4
  import { createContext, useContext, useEffect, useLayoutEffect, useRef, useState, useSyncExternalStore, } from "react";
5
5
  import { createAgentUiRuntime } from "./agent-ui/runtime.js";
6
6
  import { SyncBridge } from "./sync-bridge.js";
7
- import { invalidateForEvents, ReadTagRegistry } from "./sync.js";
7
+ import { invalidateForEvents, invalidateForReset, readTagsOf, } from "./sync.js";
8
8
  const FrameworkContext = createContext(null);
9
9
  const SIGNED_OUT = { status: "signed-out" };
10
+ /** A server render does not know the session yet, and hydration must render what it rendered. */
11
+ const LOADING = { status: "loading" };
12
+ const serverSession = () => LOADING;
10
13
  const NO_SESSION = {
11
14
  current: () => SIGNED_OUT,
12
15
  subscribe: () => () => { },
@@ -14,10 +17,16 @@ const NO_SESSION = {
14
17
  function identityOf(session) {
15
18
  return session.status === "signed-in" ? `user:${session.user.id}` : session.status;
16
19
  }
20
+ function routerQueryClient(router) {
21
+ const context = router?.options.context;
22
+ if (typeof context !== "object" || context === null || !("queryClient" in context))
23
+ return undefined;
24
+ return context.queryClient instanceof QueryClient ? context.queryClient : undefined;
25
+ }
17
26
  /** Counts changes of the signed-in user after the first settled answer. */
18
27
  function useSettledIdentityEpoch(auth) {
19
28
  const source = auth ?? NO_SESSION;
20
- const identity = identityOf(useSyncExternalStore(source.subscribe, source.current));
29
+ const identity = identityOf(useSyncExternalStore(source.subscribe, source.current, serverSession));
21
30
  const [tracked, setTracked] = useState({ settled: undefined, epoch: 0 });
22
31
  if (identity !== "loading" && tracked.settled !== identity) {
23
32
  setTracked({
@@ -33,12 +42,12 @@ export function useIdentityEpoch() {
33
42
  return useContext(IdentityEpochContext);
34
43
  }
35
44
  export function FrameworkProvider({ client, queryClient, sync = true, router, auth, children, }) {
36
- const [ownQueryClient] = useState(() => queryClient ?? new QueryClient());
45
+ const [ownQueryClient] = useState(() => queryClient ?? routerQueryClient(router) ?? new QueryClient());
37
46
  const [value] = useState(() => {
38
47
  const bridge = new SyncBridge();
39
48
  return {
40
49
  client,
41
- readTags: new ReadTagRegistry(),
50
+ readTags: readTagsOf(ownQueryClient),
42
51
  agentUi: createAgentUiRuntime({ client, queryClient: ownQueryClient, router }),
43
52
  auth,
44
53
  sync: bridge,
@@ -52,9 +61,9 @@ export function FrameworkProvider({ client, queryClient, sync = true, router, au
52
61
  return;
53
62
  appliedEpoch.current = epoch;
54
63
  void ownQueryClient.resetQueries();
64
+ void router?.invalidate();
55
65
  value.agentUi.reset();
56
- }, [epoch, ownQueryClient, value]);
57
- useEffect(() => value.readTags.attach(ownQueryClient), [value, ownQueryClient]);
66
+ }, [epoch, ownQueryClient, router, value]);
58
67
  useEffect(() => value.agentUi.start(), [value]);
59
68
  useEffect(() => {
60
69
  if (!import.meta.env.DEV)
@@ -72,23 +81,62 @@ export function FrameworkProvider({ client, queryClient, sync = true, router, au
72
81
  }, [value]);
73
82
  return (_jsx(FrameworkContext.Provider, { value: value, children: _jsx(IdentityEpochContext.Provider, { value: epoch, children: _jsxs(QueryClientProvider, { client: ownQueryClient, children: [sync && (_jsx(SyncConnection, { value: value, queryClient: ownQueryClient }, epoch)), children] }) }) }));
74
83
  }
75
- /** One sync connection; remounted with a fresh cursor whenever the signed-in user changes. */
84
+ /** The server refuses a signed-out visitor sync, unless it signs nobody in (`anonymous`). */
85
+ function syncsAs(session) {
86
+ return !session || session.status === "signed-in" || session.status === "anonymous";
87
+ }
88
+ /**
89
+ * One sync connection; remounted with a fresh cursor whenever the signed-in user changes. It
90
+ * runs while the session can sync, and after the server refuses it, until the session changes.
91
+ */
76
92
  function SyncConnection({ value, queryClient, }) {
93
+ // Data loaded outside action queries (plugin calls, the auth client) has no cursor but is read after this render.
94
+ const [loadedAfter] = useState(() => value.readTags.latest());
77
95
  useEffect(() => {
78
- const { client } = value;
96
+ const { client, auth } = value;
97
+ let refused;
79
98
  const syncClient = createSyncClient({
80
99
  request: (path, init) => client.request(path, init),
81
100
  basePath: client.basePath,
82
101
  clientId: client.clientId,
102
+ startAt: () => value.readTags.position(loadedAfter),
83
103
  onEvents: (events) => {
84
104
  void invalidateForEvents(queryClient, value.readTags, events);
85
105
  value.bridge.emit(events);
86
106
  },
107
+ onReset: (cursor) => {
108
+ void invalidateForReset(queryClient, value.readTags, cursor);
109
+ value.bridge.resumed();
110
+ },
87
111
  isHidden: () => globalThis.document?.visibilityState === "hidden",
88
112
  channels: [value.agentUi],
89
113
  onNegotiated: (transport) => value.bridge.negotiated(transport),
90
114
  onResume: () => value.bridge.resumed(),
115
+ ...(auth
116
+ ? {
117
+ onUnauthorized: () => {
118
+ refused = auth.current();
119
+ syncClient.stop();
120
+ },
121
+ }
122
+ : {}),
91
123
  });
124
+ let settled;
125
+ const follow = () => {
126
+ const session = auth?.current();
127
+ if (session?.status === "loading")
128
+ return;
129
+ if (session !== refused)
130
+ refused = undefined;
131
+ if (session)
132
+ settled ??= identityOf(session);
133
+ // The provider remounts this connection for another user.
134
+ const anotherUser = session !== undefined && identityOf(session) !== settled;
135
+ if (syncsAs(session) && refused === undefined && !anotherUser)
136
+ syncClient.start();
137
+ else
138
+ syncClient.stop();
139
+ };
92
140
  const reconnectWhenVisible = () => {
93
141
  if (globalThis.document?.visibilityState !== "hidden")
94
142
  syncClient.reconnectNow();
@@ -97,14 +145,16 @@ function SyncConnection({ value, queryClient, }) {
97
145
  globalThis.addEventListener?.("online", reconnect);
98
146
  globalThis.document?.addEventListener("visibilitychange", reconnectWhenVisible);
99
147
  const detach = value.bridge.attach(syncClient);
100
- syncClient.start();
148
+ const unfollow = auth?.subscribe(follow);
149
+ follow();
101
150
  return () => {
151
+ unfollow?.();
102
152
  globalThis.removeEventListener?.("online", reconnect);
103
153
  globalThis.document?.removeEventListener("visibilitychange", reconnectWhenVisible);
104
154
  syncClient.stop();
105
155
  detach();
106
156
  };
107
- }, [value, queryClient]);
157
+ }, [value, queryClient, loadedAfter]);
108
158
  return null;
109
159
  }
110
160
  export function useFramework() {
@@ -121,6 +171,6 @@ export function useSession() {
121
171
  const { auth } = useFramework();
122
172
  if (!auth)
123
173
  throw new Error("useSession needs <FrameworkProvider auth={...}>");
124
- return useSyncExternalStore(auth.subscribe, auth.current);
174
+ return useSyncExternalStore(auth.subscribe, auth.current, serverSession);
125
175
  }
126
176
  //# sourceMappingURL=provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/react/provider.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { AgentUiClient } from \"@parlor/agent-ui/client\";\nimport { createSyncClient, type SyncClient } from \"@parlor/sync/client\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport type { AnyRouter } from \"@tanstack/react-router\";\nimport {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\n\nimport type { ActionClient } from \"../action-client.js\";\nimport type { RegisteredActions } from \"../register.js\";\nimport type { FrameworkAuth, SessionSnapshot, SessionSource } from \"../session.js\";\nimport { createAgentUiRuntime } from \"./agent-ui/runtime.js\";\nimport { type FrameworkSync, SyncBridge } from \"./sync-bridge.js\";\nimport {\n invalidateForEvents,\n invalidateForReset,\n type ReadTagRegistry,\n readTagsOf,\n} from \"./sync.js\";\n\ninterface FrameworkContextValue {\n readonly client: ActionClient<RegisteredActions>;\n readonly readTags: ReadTagRegistry;\n readonly agentUi: AgentUiClient;\n readonly auth: FrameworkAuth | undefined;\n readonly sync: FrameworkSync;\n readonly bridge: SyncBridge;\n}\n\nconst FrameworkContext = createContext<FrameworkContextValue | null>(null);\n\nexport interface FrameworkProviderProps {\n readonly client: ActionClient<RegisteredActions>;\n /** Defaults to the router's `context.queryClient`, so loaders and hooks share one cache. */\n readonly queryClient?: QueryClient | undefined;\n readonly sync?: boolean | undefined;\n readonly router?: AnyRouter | undefined;\n /**\n * When the signed-in user changes, cached queries reset and sync reconnects as them. Sync\n * waits for a signed-in or `anonymous` session, and after the server refuses it, for the\n * session to change. An auth client that can also sign (`device`) and pair hosts\n * (`authorizeHost`) gives the chat both.\n */\n readonly auth?: FrameworkAuth | undefined;\n readonly children: ReactNode;\n}\n\nconst SIGNED_OUT: SessionSnapshot = { status: \"signed-out\" };\n\n/** A server render does not know the session yet, and hydration must render what it rendered. */\nconst LOADING: SessionSnapshot = { status: \"loading\" };\nconst serverSession = () => LOADING;\n\nconst NO_SESSION: SessionSource = {\n current: () => SIGNED_OUT,\n subscribe: () => () => {},\n};\n\nfunction identityOf(session: SessionSnapshot): string {\n return session.status === \"signed-in\" ? `user:${session.user.id}` : session.status;\n}\n\nfunction routerQueryClient(router: AnyRouter | undefined): QueryClient | undefined {\n const context: unknown = router?.options.context;\n if (typeof context !== \"object\" || context === null || !(\"queryClient\" in context))\n return undefined;\n return context.queryClient instanceof QueryClient ? context.queryClient : undefined;\n}\n\n/** Counts changes of the signed-in user after the first settled answer. */\nfunction useSettledIdentityEpoch(auth: SessionSource | undefined): number {\n const source = auth ?? NO_SESSION;\n const identity = identityOf(\n useSyncExternalStore(source.subscribe, source.current, serverSession),\n );\n const [tracked, setTracked] = useState<{\n readonly settled: string | undefined;\n readonly epoch: number;\n }>({ settled: undefined, epoch: 0 });\n if (identity !== \"loading\" && tracked.settled !== identity) {\n setTracked({\n settled: identity,\n epoch: tracked.settled === undefined ? 0 : tracked.epoch + 1,\n });\n }\n return tracked.epoch;\n}\n\nconst IdentityEpochContext = createContext(0);\n\n/** Changes whenever the signed-in user does; state kept per user is keyed on it. */\nexport function useIdentityEpoch(): number {\n return useContext(IdentityEpochContext);\n}\n\nexport function FrameworkProvider({\n client,\n queryClient,\n sync = true,\n router,\n auth,\n children,\n}: FrameworkProviderProps) {\n const [ownQueryClient] = useState(\n () => queryClient ?? routerQueryClient(router) ?? new QueryClient(),\n );\n const [value] = useState<FrameworkContextValue>(() => {\n const bridge = new SyncBridge();\n return {\n client,\n readTags: readTagsOf(ownQueryClient),\n agentUi: createAgentUiRuntime({ client, queryClient: ownQueryClient, router }),\n auth,\n sync: bridge,\n bridge,\n };\n });\n const epoch = useSettledIdentityEpoch(auth);\n const appliedEpoch = useRef(epoch);\n\n useLayoutEffect(() => {\n if (appliedEpoch.current === epoch) return;\n appliedEpoch.current = epoch;\n void ownQueryClient.resetQueries();\n void router?.invalidate();\n value.agentUi.reset();\n }, [epoch, ownQueryClient, router, value]);\n\n useEffect(() => value.agentUi.start(), [value]);\n\n useEffect(() => {\n if (!import.meta.env.DEV) return;\n let uninstall: (() => void) | undefined;\n let active = true;\n void import(\"./agent-ui/dev.js\").then(({ installAgentUiDevtools }) => {\n if (active)\n uninstall = installAgentUiDevtools(value.agentUi, value.client.clientId);\n });\n return () => {\n active = false;\n uninstall?.();\n };\n }, [value]);\n\n return (\n <FrameworkContext.Provider value={value}>\n <IdentityEpochContext.Provider value={epoch}>\n <QueryClientProvider client={ownQueryClient}>\n {sync && (\n <SyncConnection key={epoch} value={value} queryClient={ownQueryClient} />\n )}\n {children}\n </QueryClientProvider>\n </IdentityEpochContext.Provider>\n </FrameworkContext.Provider>\n );\n}\n\n/** The server refuses a signed-out visitor sync, unless it signs nobody in (`anonymous`). */\nfunction syncsAs(session: SessionSnapshot | undefined): boolean {\n return !session || session.status === \"signed-in\" || session.status === \"anonymous\";\n}\n\n/**\n * One sync connection; remounted with a fresh cursor whenever the signed-in user changes. It\n * runs while the session can sync, and after the server refuses it, until the session changes.\n */\nfunction SyncConnection({\n value,\n queryClient,\n}: {\n readonly value: FrameworkContextValue;\n readonly queryClient: QueryClient;\n}) {\n // Data loaded outside action queries (plugin calls, the auth client) has no cursor but is read after this render.\n const [loadedAfter] = useState(() => value.readTags.latest());\n useEffect(() => {\n const { client, auth } = value;\n let refused: SessionSnapshot | undefined;\n const syncClient: SyncClient = createSyncClient({\n request: (path, init) => client.request(path, init),\n basePath: client.basePath,\n clientId: client.clientId,\n startAt: () => value.readTags.position(loadedAfter),\n onEvents: (events) => {\n void invalidateForEvents(queryClient, value.readTags, events);\n value.bridge.emit(events);\n },\n onReset: (cursor) => {\n void invalidateForReset(queryClient, value.readTags, cursor);\n value.bridge.resumed();\n },\n isHidden: () => globalThis.document?.visibilityState === \"hidden\",\n channels: [value.agentUi],\n onNegotiated: (transport) => value.bridge.negotiated(transport),\n onResume: () => value.bridge.resumed(),\n ...(auth\n ? {\n onUnauthorized: () => {\n refused = auth.current();\n syncClient.stop();\n },\n }\n : {}),\n });\n let settled: string | undefined;\n const follow = () => {\n const session = auth?.current();\n if (session?.status === \"loading\") return;\n if (session !== refused) refused = undefined;\n if (session) settled ??= identityOf(session);\n // The provider remounts this connection for another user.\n const anotherUser = session !== undefined && identityOf(session) !== settled;\n if (syncsAs(session) && refused === undefined && !anotherUser) syncClient.start();\n else syncClient.stop();\n };\n const reconnectWhenVisible = () => {\n if (globalThis.document?.visibilityState !== \"hidden\") syncClient.reconnectNow();\n };\n const reconnect = () => syncClient.reconnectNow();\n globalThis.addEventListener?.(\"online\", reconnect);\n globalThis.document?.addEventListener(\"visibilitychange\", reconnectWhenVisible);\n const detach = value.bridge.attach(syncClient);\n const unfollow = auth?.subscribe(follow);\n follow();\n return () => {\n unfollow?.();\n globalThis.removeEventListener?.(\"online\", reconnect);\n globalThis.document?.removeEventListener(\"visibilitychange\", reconnectWhenVisible);\n syncClient.stop();\n detach();\n };\n }, [value, queryClient, loadedAfter]);\n return null;\n}\n\nexport function useFramework(): FrameworkContextValue {\n const value = useContext(FrameworkContext);\n if (!value) throw new Error(\"useActionClient must be used inside <FrameworkProvider>\");\n return value;\n}\n\nexport function useActionClient(): ActionClient<RegisteredActions> {\n return useFramework().client;\n}\n\n/** The session of the `auth` given to `FrameworkProvider`. */\nexport function useSession(): SessionSnapshot {\n const { auth } = useFramework();\n if (!auth) throw new Error(\"useSession needs <FrameworkProvider auth={...}>\");\n return useSyncExternalStore(auth.subscribe, auth.current, serverSession);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/react/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,cAAc,CAAC;AAKjE,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,wBAAwB,GAA+C;IAC3E,SAAS,EAAE,KAAK;IAChB,aAAa,EAAE,KAAK;IACpB,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,IAAI;IAC1B,wBAAwB,EAAE,IAAI;IAC9B,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,IAAI;CACf,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAI,GAAU,eAAe;IACvD,OAAO,CAAC,YAAoB,EAAE,KAAY,EAAW,EAAE;QACrD,IAAI,KAAK,YAAY,WAAW,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,IAAI,CAAC;YACvE,OAAO,KAAK,CAAC;QACf,IAAI,OAAO,IAAI,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACjE,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,YAAY,GAAG,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/react/retry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,cAAc,CAAC;AAKjE,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,wBAAwB,GAA+C;IAC3E,SAAS,EAAE,KAAK;IAChB,aAAa,EAAE,KAAK;IACpB,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,IAAI;IAC1B,wBAAwB,EAAE,IAAI;IAC9B,eAAe,EAAE,KAAK;IACtB,SAAS,EAAE,KAAK;IAChB,QAAQ,EAAE,IAAI;CACf,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAI,GAAU,eAAe;IACvD,OAAO,CAAC,YAAoB,EAAE,KAAY,EAAW,EAAE;QACrD,IAAI,KAAK,YAAY,WAAW,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,IAAI,CAAC;YACvE,OAAO,KAAK,CAAC;QACf,IAAI,OAAO,IAAI,KAAK,UAAU;YAAE,OAAO,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACjE,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,YAAY,GAAG,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { ActionError, type ActionErrorCode } from \"@parlor/core\";\nimport type { UseQueryOptions } from \"@tanstack/react-query\";\n\ntype Retry = NonNullable<UseQueryOptions[\"retry\"]>;\n\nconst DEFAULT_RETRIES = 3;\n\nconst RETRY_CAN_CHANGE_OUTCOME: Readonly<Record<ActionErrorCode, boolean>> = {\n not_found: false,\n invalid_input: false,\n declined: false,\n confirmation_timeout: true,\n confirmation_unavailable: true,\n unauthenticated: false,\n forbidden: false,\n internal: true,\n};\n\nexport function actionRetry(base: Retry = DEFAULT_RETRIES) {\n return (failureCount: number, error: Error): boolean => {\n if (error instanceof ActionError && !RETRY_CAN_CHANGE_OUTCOME[error.code])\n return false;\n if (typeof base === \"function\") return base(failureCount, error);\n return base === true || (base !== false && failureCount < base);\n };\n}\n"]}
@@ -3,7 +3,10 @@ import type { SyncClient } from "@parlor/sync/client";
3
3
  export interface FrameworkSync {
4
4
  addChannel(channel: ClientChannel): () => void;
5
5
  onEvents(listener: (events: readonly SyncEvent[]) => void): () => void;
6
- /** The connection came back after a failure; reread what could have changed unseen. */
6
+ /**
7
+ * The connection came back after a failure, or the server could not replay every event
8
+ * this client missed; reread what could have changed unseen.
9
+ */
7
10
  onResume(listener: () => void): () => void;
8
11
  /** What the server negotiated; `undefined` until it has, and while no client is attached. */
9
12
  transport(): "sse" | "poll" | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sync-bridge.d.ts","sourceRoot":"","sources":["../../src/react/sync-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,IAAI,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3C,6FAA6F;IAC7F,SAAS,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,2DAA2D;IAC3D,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACzE;AAED,qBAAa,UAAW,YAAW,aAAa;;IAS9C,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,IAAI,CAQ7C;IAED,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAGrE;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGzC;IAED,SAAS,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,CAEtC;IAED,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAGtE;IAED,UAAU,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAG1C;IAED,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAEvC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,CAUrC;CAOF"}
1
+ {"version":3,"file":"sync-bridge.d.ts","sourceRoot":"","sources":["../../src/react/sync-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,IAAI,CAAC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3C,6FAA6F;IAC7F,SAAS,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,CAAC;IACxC,2DAA2D;IAC3D,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACzE;AAED,qBAAa,UAAW,YAAW,aAAa;;IAS9C,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,IAAI,CAQ7C;IAED,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,KAAK,IAAI,GAAG,MAAM,IAAI,CAGrE;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAGzC;IAED,SAAS,IAAI,KAAK,GAAG,MAAM,GAAG,SAAS,CAEtC;IAED,YAAY,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAGtE;IAED,UAAU,CAAC,SAAS,EAAE,KAAK,GAAG,MAAM,GAAG,IAAI,CAG1C;IAED,IAAI,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAEvC;IAED,OAAO,IAAI,IAAI,CAEd;IAED,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,CAUrC;CAOF"}
@@ -1 +1 @@
1
- {"version":3,"file":"sync-bridge.js","sourceRoot":"","sources":["../../src/react/sync-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync-bridge.js","sourceRoot":"","sources":["../../src/react/sync-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientChannel, SyncEvent } from \"@parlor/sync\";\nimport type { SyncClient } from \"@parlor/sync/client\";\n\nexport interface FrameworkSync {\n addChannel(channel: ClientChannel): () => void;\n onEvents(listener: (events: readonly SyncEvent[]) => void): () => void;\n /**\n * The connection came back after a failure, or the server could not replay every event\n * this client missed; reread what could have changed unseen.\n */\n onResume(listener: () => void): () => void;\n /** What the server negotiated; `undefined` until it has, and while no client is attached. */\n transport(): \"sse\" | \"poll\" | undefined;\n /** The server negotiated a transport, on every connect. */\n onNegotiated(listener: (transport: \"sse\" | \"poll\") => void): () => void;\n}\n\nexport class SyncBridge implements FrameworkSync {\n readonly #channels = new Set<ClientChannel>();\n readonly #listeners = new Set<(events: readonly SyncEvent[]) => void>();\n readonly #detachers = new Map<ClientChannel, () => void>();\n readonly #resumers = new Set<() => void>();\n readonly #negotiators = new Set<(transport: \"sse\" | \"poll\") => void>();\n #client: SyncClient | undefined;\n #transport: \"sse\" | \"poll\" | undefined;\n\n addChannel(channel: ClientChannel): () => void {\n this.#channels.add(channel);\n this.#join(channel);\n return () => {\n this.#channels.delete(channel);\n this.#detachers.get(channel)?.();\n this.#detachers.delete(channel);\n };\n }\n\n onEvents(listener: (events: readonly SyncEvent[]) => void): () => void {\n this.#listeners.add(listener);\n return () => this.#listeners.delete(listener);\n }\n\n onResume(listener: () => void): () => void {\n this.#resumers.add(listener);\n return () => this.#resumers.delete(listener);\n }\n\n transport(): \"sse\" | \"poll\" | undefined {\n return this.#transport;\n }\n\n onNegotiated(listener: (transport: \"sse\" | \"poll\") => void): () => void {\n this.#negotiators.add(listener);\n return () => this.#negotiators.delete(listener);\n }\n\n negotiated(transport: \"sse\" | \"poll\"): void {\n this.#transport = transport;\n for (const listener of [...this.#negotiators]) listener(transport);\n }\n\n emit(events: readonly SyncEvent[]): void {\n for (const listener of [...this.#listeners]) listener(events);\n }\n\n resumed(): void {\n for (const listener of [...this.#resumers]) listener();\n }\n\n attach(client: SyncClient): () => void {\n this.#client = client;\n for (const channel of this.#channels) this.#join(channel);\n return () => {\n if (this.#client === client) {\n this.#client = undefined;\n this.#transport = undefined;\n }\n this.#detachers.clear();\n };\n }\n\n #join(channel: ClientChannel): void {\n if (!this.#client) return;\n this.#detachers.get(channel)?.();\n this.#detachers.set(channel, this.#client.addChannel(channel));\n }\n}\n"]}
@@ -1,12 +1,51 @@
1
1
  import type { Tag } from "@parlor/core";
2
- import type { SyncEvent } from "@parlor/sync";
2
+ import { type SyncCursor, type SyncEvent } from "@parlor/sync";
3
3
  import type { QueryClient } from "@tanstack/react-query";
4
+ import type { ActionEnvelope } from "../action-client.js";
5
+ interface Read {
6
+ readonly tags: readonly Tag[];
7
+ /** Every event up to it is in the data; undefined when the server did not say. */
8
+ readonly cursor: SyncCursor | undefined;
9
+ }
10
+ /** One recorded read: its query hash, read tags and the encoded cursor its data reflects. */
11
+ export type ReadEntry = readonly [string, readonly Tag[], string?];
12
+ /**
13
+ * What each action query read and how far into the sync log its data reaches, so an event
14
+ * invalidates only the queries whose data it is newer than.
15
+ */
4
16
  export declare class ReadTagRegistry {
5
17
  #private;
6
18
  attach(queryClient: QueryClient): () => void;
7
- record(queryHash: string, tags: readonly Tag[]): void;
19
+ /**
20
+ * Runs one fetch of a query and records what its answer read. An event that arrived while
21
+ * it was in flight and is newer than the answer invalidates the data once it lands.
22
+ */
23
+ read<T>(queryHash: string, fetch: () => Promise<ActionEnvelope<T>>): Promise<T>;
24
+ record(queryHash: string, tags: readonly Tag[], cursor?: string): Read;
8
25
  tagsFor(queryHash: string): readonly Tag[] | undefined;
26
+ /** Every query's reads, to carry a server-rendered cache to the browser. */
27
+ entries(): ReadEntry[];
28
+ /** Sync events that arrived; fetches in flight keep them to check their answers against. */
29
+ observe(events: readonly SyncEvent[]): void;
9
30
  affected(events: readonly SyncEvent[]): Set<string>;
31
+ /**
32
+ * Sync was reset to `cursor` without the events before it: every query whose data may
33
+ * predate it, and fetches in flight, whose answers are checked when they land.
34
+ */
35
+ reset(cursor: SyncCursor): Set<string>;
36
+ /** The newest cursor any answer or event has shown, encoded; every later read reflects it. */
37
+ latest(): string;
38
+ /**
39
+ * The oldest point of the sync log that data held or being fetched may predate, and no
40
+ * later than `notAfter`, encoded. A stream that starts there misses nothing and replays
41
+ * no event that data already shows.
42
+ */
43
+ position(notAfter?: string): string;
10
44
  }
45
+ /** The one registry of `queryClient`, shared by hooks, loaders and sync; it lives as long as the client. */
46
+ export declare function readTagsOf(queryClient: QueryClient): ReadTagRegistry;
47
+ /** Invalidates every query whose data may predate the cursor sync was reset to. */
48
+ export declare function invalidateForReset(queryClient: QueryClient, registry: ReadTagRegistry, cursor: string): Promise<void>;
11
49
  export declare function invalidateForEvents(queryClient: QueryClient, registry: ReadTagRegistry, events: readonly SyncEvent[]): Promise<void>;
50
+ export {};
12
51
  //# sourceMappingURL=sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/react/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD,qBAAa,eAAe;;IAG1B,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,IAAI,CAI3C;IAED,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,GAAG,IAAI,CAEpD;IAED,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,EAAE,GAAG,SAAS,CAErD;IAED,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAYlD;CACF;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,SAAS,SAAS,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAOf"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/react/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAML,KAAK,UAAU,EACf,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,UAAU,IAAI;IACZ,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,CAAC;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC;CACzC;AAUD,6FAA6F;AAC7F,MAAM,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;AAkBnE;;;GAGG;AACH,qBAAa,eAAe;;IAM1B,MAAM,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,IAAI,CAiB3C;IAED;;;OAGG;IACG,IAAI,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBpF;IAED,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAQrE;IAED,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,EAAE,GAAG,SAAS,CAErD;IAED,4EAA4E;IAC5E,OAAO,IAAI,SAAS,EAAE,CAIrB;IAED,4FAA4F;IAC5F,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAG1C;IAED,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAQlD;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,EAAE,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrC;IAED,8FAA8F;IAC9F,MAAM,IAAI,MAAM,CAEf;IAED;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAUlC;CACF;AAID,4GAA4G;AAC5G,wBAAgB,UAAU,CAAC,WAAW,EAAE,WAAW,GAAG,eAAe,CAQpE;AAED,mFAAmF;AACnF,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,SAAS,SAAS,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf"}