@agent-native/core 0.211.0 → 0.212.0-nightly-20261021010049
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.
- package/README.md +1 -1
- package/dist/app-config/analytics.d.ts +1 -0
- package/dist/app-config/analytics.js +7 -0
- package/dist/app-config/schema.d.ts +1 -0
- package/dist/chat-threads/store.d.ts +28 -2
- package/dist/chat-threads/store.js +75 -13
- package/dist/cli/template-baseline.js +18 -5
- package/dist/cli/template-sync.js +100 -19
- package/dist/client/agent-chat/index.d.ts +2 -1
- package/dist/client/agent-chat/index.js +2 -1
- package/dist/client/chat/agentkit-protocol.js +21 -1
- package/dist/client/chat/run-outcome.d.ts +1 -0
- package/dist/client/chat/runtime.js +6 -0
- package/dist/client/sharing/index.d.ts +2 -1
- package/dist/client/sharing/index.js +2 -1
- package/dist/client/sharing/share-controller-helpers.d.ts +14 -1
- package/dist/client/sharing/share-controller-helpers.js +46 -1
- package/dist/client/sharing/useShareButtonController.d.ts +12 -0
- package/dist/client/sharing/useShareButtonController.js +76 -57
- package/dist/client/sharing/useShareDialogController.d.ts +3 -0
- package/dist/client/sharing/useShareDialogController.js +77 -49
- package/dist/client/sharing/useShareVisibilityTransition.d.ts +68 -0
- package/dist/client/sharing/useShareVisibilityTransition.js +224 -0
- package/dist/client/use-chat-thread-list.d.ts +40 -0
- package/dist/client/use-chat-thread-list.js +210 -0
- package/dist/client/use-chat-threads.d.ts +67 -0
- package/dist/client/use-chat-threads.js +141 -23
- package/dist/client/use-db-sync.d.ts +1 -0
- package/dist/client/use-db-sync.js +13 -1
- package/dist/collab/__fixtures__/live-copy-tasks.d.ts +1 -0
- package/dist/collab/__fixtures__/live-copy-tasks.js +92 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/bounded-task-bundle.d.ts +17 -0
- package/dist/collab/bounded-task-bundle.js +39 -0
- package/dist/collab/bounded-task-source.d.ts +14 -0
- package/dist/collab/bounded-task-source.js +8 -0
- package/dist/collab/bounded-tasks.d.ts +67 -0
- package/dist/collab/bounded-tasks.js +439 -0
- package/dist/collab/client.js +2 -1
- package/dist/collab/index.d.ts +5 -2
- package/dist/collab/index.js +5 -2
- package/dist/collab/live-copy-tasks.d.ts +80 -0
- package/dist/collab/live-copy-tasks.js +330 -0
- package/dist/collab/live-copy.d.ts +188 -0
- package/dist/collab/live-copy.js +415 -0
- package/dist/collab/routes.d.ts +5 -0
- package/dist/collab/routes.js +24 -8
- package/dist/collab/storage.d.ts +53 -1
- package/dist/collab/storage.js +93 -5
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/collab/ydoc-manager.d.ts +92 -3
- package/dist/collab/ydoc-manager.js +447 -38
- package/dist/db/client.d.ts +6 -0
- package/dist/db/client.js +25 -5
- package/dist/deploy/build.js +2 -0
- package/dist/extensions/actions.js +1 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/mcp/agent-connected.js +5 -1
- package/dist/mcp/build-server.js +39 -10
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/org/index.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +10 -10
- package/dist/server/agent-chat-plugin.js +80 -17
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/analytics.d.ts +1 -0
- package/dist/server/analytics.js +18 -1
- package/dist/server/collab-plugin.d.ts +10 -1
- package/dist/server/collab-plugin.js +89 -20
- package/dist/server/index.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/shared/optional-node-builtins.d.ts +1 -0
- package/dist/shared/optional-node-builtins.js +3 -0
- package/dist/sharing/access.d.ts +1 -0
- package/dist/sharing/access.js +113 -95
- package/dist/tracking/providers.d.ts +1 -0
- package/dist/tracking/providers.js +2 -1
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/dist/vite/bounded-task-plugin.d.ts +22 -0
- package/dist/vite/bounded-task-plugin.js +44 -0
- package/dist/vite/client.js +2 -0
- package/dist/vitest-config.js +3 -0
- package/dist/workspace-connections/actions/list-workspace-user-groups.d.ts +1 -1
- package/docs/content/deployment-environment-variables.mdx +1 -0
- package/docs/content/environment-variables.mdx +1 -0
- package/docs/content/sharing.mdx +36 -0
- package/docs/content/toolkit-sharing.mdx +98 -12
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -280,7 +280,7 @@ Explore the [full app gallery](https://agent-native.com/apps?utm_source=npm&utm_
|
|
|
280
280
|
|
|
281
281
|
## Contributing
|
|
282
282
|
|
|
283
|
-
|
|
283
|
+
Want to send a change back? Start with [CONTRIBUTING.md](./CONTRIBUTING.md). [DEVELOPMENT.md](./DEVELOPMENT.md) covers local setup, workspace structure, and guard scripts.
|
|
284
284
|
|
|
285
285
|
## License
|
|
286
286
|
|
|
@@ -27,4 +27,11 @@ export const analyticsConfig = z.object({
|
|
|
27
27
|
],
|
|
28
28
|
doc: "Endpoint for first-party Agent-Native Analytics events.",
|
|
29
29
|
}),
|
|
30
|
+
headScriptSrc: z
|
|
31
|
+
.url({ protocol: /^https$/ })
|
|
32
|
+
.optional()
|
|
33
|
+
.meta({
|
|
34
|
+
env: "AGENT_NATIVE_HEAD_SCRIPT_SRC",
|
|
35
|
+
doc: "HTTPS URL of a script loaded with `defer` on every server-rendered page, for deployment-specific tooling such as support or feedback widgets.",
|
|
36
|
+
}),
|
|
30
37
|
});
|
|
@@ -44,6 +44,7 @@ export declare const appConfigSchema: z.ZodObject<{
|
|
|
44
44
|
authSessionReplay: z.ZodDefault<z.ZodBoolean>;
|
|
45
45
|
agentNativePublicKey: z.ZodOptional<z.ZodString>;
|
|
46
46
|
agentNativeEndpoint: z.ZodDefault<z.ZodString>;
|
|
47
|
+
headScriptSrc: z.ZodOptional<z.ZodURL>;
|
|
47
48
|
}, z.core.$strip>>;
|
|
48
49
|
app: z.ZodPrefault<z.ZodObject<{
|
|
49
50
|
id: z.ZodOptional<z.ZodString>;
|
|
@@ -58,8 +58,24 @@ export interface ChatThread {
|
|
|
58
58
|
orgId: string | null;
|
|
59
59
|
visibility: "private" | "org" | "public";
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Which of the caller's lists a thread belongs to. `mine` is ownership alone,
|
|
63
|
+
* so a chat the caller owns stays in it however widely it is shared; `shared`
|
|
64
|
+
* is accessible-but-owned-by-someone-else.
|
|
65
|
+
*/
|
|
66
|
+
export type ChatThreadOwnership = "all" | "mine" | "shared";
|
|
67
|
+
export declare const CHAT_THREAD_OWNERSHIPS: readonly ChatThreadOwnership[];
|
|
68
|
+
export declare function isChatThreadOwnership(value: unknown): value is ChatThreadOwnership;
|
|
69
|
+
/**
|
|
70
|
+
* Why the caller can see a thread. A direct per-user grant outranks
|
|
71
|
+
* organization access when both apply, so revoking the organization grant never
|
|
72
|
+
* looks like it removed access the person was given by name.
|
|
73
|
+
*/
|
|
74
|
+
export type ChatThreadAccessBasis = "owner" | "direct" | "organization";
|
|
61
75
|
export interface ChatThreadSummary {
|
|
62
76
|
id: string;
|
|
77
|
+
ownerEmail?: string;
|
|
78
|
+
accessBasis?: ChatThreadAccessBasis;
|
|
63
79
|
title: string;
|
|
64
80
|
preview: string;
|
|
65
81
|
messageCount: number;
|
|
@@ -72,6 +88,11 @@ export interface ChatThreadSummary {
|
|
|
72
88
|
orgId: string | null;
|
|
73
89
|
visibility: "private" | "org" | "public";
|
|
74
90
|
}
|
|
91
|
+
/** List and search rows always include the caller's ownership and access basis. */
|
|
92
|
+
export interface ChatThreadListRow extends ChatThreadSummary {
|
|
93
|
+
ownerEmail: string;
|
|
94
|
+
accessBasis: ChatThreadAccessBasis;
|
|
95
|
+
}
|
|
75
96
|
export interface ForkThreadSourceSnapshot {
|
|
76
97
|
threadData: string;
|
|
77
98
|
title?: string;
|
|
@@ -148,8 +169,10 @@ export interface ListThreadsOptions {
|
|
|
148
169
|
includeExternal?: boolean;
|
|
149
170
|
/** Current app id used by the local-only view. */
|
|
150
171
|
sourceAppId?: string | null;
|
|
172
|
+
/** Defaults to `all`. Narrowed in SQL, so LIMIT/OFFSET page within the list. */
|
|
173
|
+
ownership?: ChatThreadOwnership;
|
|
151
174
|
}
|
|
152
|
-
export declare function listThreads(ownerEmail: string, options?: ListThreadsOptions | number, legacyOffset?: number): Promise<
|
|
175
|
+
export declare function listThreads(ownerEmail: string, options?: ListThreadsOptions | number, legacyOffset?: number): Promise<ChatThreadListRow[]>;
|
|
153
176
|
export declare function searchThreads(ownerEmail: string, query: string, limit?: number, options?: {
|
|
154
177
|
scope?: {
|
|
155
178
|
type: string;
|
|
@@ -162,7 +185,10 @@ export declare function searchThreads(ownerEmail: string, query: string, limit?:
|
|
|
162
185
|
includeExternal?: boolean;
|
|
163
186
|
/** Current app id used by the local-only view. */
|
|
164
187
|
sourceAppId?: string | null;
|
|
165
|
-
|
|
188
|
+
/** See `ListThreadsOptions.ownership`. */
|
|
189
|
+
ownership?: ChatThreadOwnership;
|
|
190
|
+
offset?: number;
|
|
191
|
+
}): Promise<ChatThreadListRow[]>;
|
|
166
192
|
/**
|
|
167
193
|
* Scope a thread should carry after a run inside a resource: adopt when it has
|
|
168
194
|
* none, otherwise keep what it has. An unscoped thread reads as general, and a
|
|
@@ -12,7 +12,7 @@ import { fromMigrationEntries } from "../db/versioned-store-migrations.js";
|
|
|
12
12
|
import { widenIntColumnsToBigInt } from "../db/widen-columns.js";
|
|
13
13
|
import { getRequestOrgId } from "../server/request-context.js";
|
|
14
14
|
import { assertNoInlineImageBytes, stripInlineBytes, } from "../shared/inline-bytes.js";
|
|
15
|
-
import { resolveAccess } from "../sharing/access.js";
|
|
15
|
+
import { hasCurrentOrgMembership, resolveAccess, } from "../sharing/access.js";
|
|
16
16
|
import { registerShareableResource } from "../sharing/registry.js";
|
|
17
17
|
import { roleSatisfies } from "../sharing/schema.js";
|
|
18
18
|
import { emitChatThreadChange } from "./emitter.js";
|
|
@@ -226,6 +226,14 @@ export function threadScopeMismatch(existing, incoming) {
|
|
|
226
226
|
return isAppOwnedChatScope(existing);
|
|
227
227
|
return existing.type !== incoming.type || existing.id !== incoming.id;
|
|
228
228
|
}
|
|
229
|
+
export const CHAT_THREAD_OWNERSHIPS = [
|
|
230
|
+
"all",
|
|
231
|
+
"mine",
|
|
232
|
+
"shared",
|
|
233
|
+
];
|
|
234
|
+
export function isChatThreadOwnership(value) {
|
|
235
|
+
return CHAT_THREAD_OWNERSHIPS.includes(value);
|
|
236
|
+
}
|
|
229
237
|
function readScope(r) {
|
|
230
238
|
const type = r.scope_type;
|
|
231
239
|
const id = r.scope_id;
|
|
@@ -629,6 +637,12 @@ function rowToThread(r) {
|
|
|
629
637
|
visibility: readVisibility(r.visibility),
|
|
630
638
|
};
|
|
631
639
|
}
|
|
640
|
+
function readAccessBasis(value) {
|
|
641
|
+
if (value === "owner" || value === "direct" || value === "organization") {
|
|
642
|
+
return value;
|
|
643
|
+
}
|
|
644
|
+
throw new Error(`Unexpected chat thread access basis: ${String(value)}`);
|
|
645
|
+
}
|
|
632
646
|
function rowToSummary(r) {
|
|
633
647
|
// The summary path never loads `thread_data`; the count comes from the
|
|
634
648
|
// dedicated `message_count` column maintained on write. Empty threads are
|
|
@@ -638,6 +652,8 @@ function rowToSummary(r) {
|
|
|
638
652
|
return null;
|
|
639
653
|
return {
|
|
640
654
|
id: r.id,
|
|
655
|
+
ownerEmail: r.owner_email,
|
|
656
|
+
accessBasis: readAccessBasis(r.access_basis),
|
|
641
657
|
title: r.title,
|
|
642
658
|
preview: r.preview,
|
|
643
659
|
messageCount,
|
|
@@ -712,7 +728,7 @@ const THREAD_COLUMNS = `id, owner_email, title, preview, thread_data, message_co
|
|
|
712
728
|
// from the blob anymore — preview and message_count are dedicated columns
|
|
713
729
|
// (message_count is maintained on write). The detail path (`THREAD_COLUMNS` /
|
|
714
730
|
// `getThread`) still returns the full blob.
|
|
715
|
-
const SUMMARY_COLUMNS = `id, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, source_platform, source_app_id, source_url, org_id, visibility`;
|
|
731
|
+
const SUMMARY_COLUMNS = `id, owner_email, title, preview, message_count, created_at, updated_at, scope_type, scope_id, scope_label, pinned_at, archived_at, source_platform, source_app_id, source_url, org_id, visibility`;
|
|
716
732
|
export function registerChatThreadsShareable() {
|
|
717
733
|
registerShareableResource({
|
|
718
734
|
type: "chat_thread",
|
|
@@ -756,7 +772,7 @@ export async function resolveThreadsAccess(userEmail, threadIds, ctx = {}) {
|
|
|
756
772
|
if (!userEmail || ids.length === 0)
|
|
757
773
|
return threads;
|
|
758
774
|
await ensureTable();
|
|
759
|
-
const access = chatThreadAccessSql(userEmail, ctx.orgId);
|
|
775
|
+
const access = await chatThreadAccessSql(userEmail, ctx.orgId);
|
|
760
776
|
const client = getDbExec();
|
|
761
777
|
const placeholders = ids.map(() => "?").join(", ");
|
|
762
778
|
const { rows } = await client.execute({
|
|
@@ -896,14 +912,15 @@ export async function forkThread(sourceId, ownerEmail, opts) {
|
|
|
896
912
|
visibility: "private",
|
|
897
913
|
};
|
|
898
914
|
}
|
|
899
|
-
function chatThreadAccessSql(userEmail, orgId) {
|
|
900
|
-
const normalizedEmail = userEmail
|
|
915
|
+
async function chatThreadAccessSql(userEmail, orgId) {
|
|
916
|
+
const normalizedEmail = normalizeAccessEmail(userEmail);
|
|
901
917
|
const clauses = [
|
|
902
918
|
`LOWER(owner_email) = ?`,
|
|
903
919
|
`EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'user' AND LOWER(chat_thread_shares.principal_id) = ?)`,
|
|
904
920
|
];
|
|
905
921
|
const args = [normalizedEmail, normalizedEmail];
|
|
906
|
-
if (orgId
|
|
922
|
+
if (orgId &&
|
|
923
|
+
(await hasCurrentOrgMembership({ getDb: getChatThreadsDb }, orgId, normalizedEmail, { userEmail: normalizedEmail, orgId }))) {
|
|
907
924
|
clauses.push(`(visibility = 'org' AND org_id = ?)`);
|
|
908
925
|
args.push(orgId);
|
|
909
926
|
clauses.push(`EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'org' AND chat_thread_shares.principal_id = ?)`);
|
|
@@ -911,6 +928,33 @@ function chatThreadAccessSql(userEmail, orgId) {
|
|
|
911
928
|
}
|
|
912
929
|
return { sql: `(${clauses.join(" OR ")})`, args };
|
|
913
930
|
}
|
|
931
|
+
function normalizeAccessEmail(userEmail) {
|
|
932
|
+
return userEmail.trim().toLowerCase();
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Summary projection plus the caller's access basis, derived from the same
|
|
936
|
+
* owner and per-user-share comparisons the ACL uses. Anything that is neither
|
|
937
|
+
* owned nor directly granted reached the caller through the organization.
|
|
938
|
+
*/
|
|
939
|
+
function chatThreadSummarySelect(userEmail) {
|
|
940
|
+
const normalizedEmail = normalizeAccessEmail(userEmail);
|
|
941
|
+
return {
|
|
942
|
+
sql: `${SUMMARY_COLUMNS}, CASE WHEN LOWER(owner_email) = ? THEN 'owner' WHEN EXISTS (SELECT 1 FROM chat_thread_shares WHERE chat_thread_shares.resource_id = chat_threads.id AND chat_thread_shares.principal_type = 'user' AND LOWER(chat_thread_shares.principal_id) = ?) THEN 'direct' ELSE 'organization' END AS access_basis`,
|
|
943
|
+
args: [normalizedEmail, normalizedEmail],
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
function chatThreadOwnershipSql(userEmail, ownership) {
|
|
947
|
+
if (ownership === undefined || ownership === "all")
|
|
948
|
+
return null;
|
|
949
|
+
const normalizedEmail = normalizeAccessEmail(userEmail);
|
|
950
|
+
if (ownership === "mine") {
|
|
951
|
+
return { sql: `LOWER(owner_email) = ?`, args: [normalizedEmail] };
|
|
952
|
+
}
|
|
953
|
+
if (ownership === "shared") {
|
|
954
|
+
return { sql: `LOWER(owner_email) <> ?`, args: [normalizedEmail] };
|
|
955
|
+
}
|
|
956
|
+
throw new Error(`Unknown chat thread ownership: ${String(ownership)}`);
|
|
957
|
+
}
|
|
914
958
|
export async function listThreads(ownerEmail, options = {}, legacyOffset) {
|
|
915
959
|
await ensureTable();
|
|
916
960
|
// Back-compat shim: previous signature was (owner, limit, offset).
|
|
@@ -926,9 +970,15 @@ export async function listThreads(ownerEmail, options = {}, legacyOffset) {
|
|
|
926
970
|
// column, so nothing here may filter on `thread_data`. Matching that blob
|
|
927
971
|
// detoasts the whole message history for every scanned row — before LIMIT
|
|
928
972
|
// applies — which is what made this list cost seconds instead of milliseconds.
|
|
929
|
-
const access = chatThreadAccessSql(ownerEmail, opts.orgId
|
|
973
|
+
const access = await chatThreadAccessSql(ownerEmail, opts.orgId === undefined ? getRequestOrgId() : opts.orgId);
|
|
974
|
+
const ownershipFilter = chatThreadOwnershipSql(ownerEmail, opts.ownership);
|
|
975
|
+
const select = chatThreadSummarySelect(ownerEmail);
|
|
930
976
|
const filters = [access.sql, `message_count > 0`];
|
|
931
|
-
const args = [...access.args];
|
|
977
|
+
const args = [...select.args, ...access.args];
|
|
978
|
+
if (ownershipFilter) {
|
|
979
|
+
filters.push(ownershipFilter.sql);
|
|
980
|
+
args.push(...ownershipFilter.args);
|
|
981
|
+
}
|
|
932
982
|
if (!opts.includeArchived) {
|
|
933
983
|
filters.push(`archived_at IS NULL`);
|
|
934
984
|
}
|
|
@@ -948,7 +998,7 @@ export async function listThreads(ownerEmail, options = {}, legacyOffset) {
|
|
|
948
998
|
}
|
|
949
999
|
args.push(limit, offset);
|
|
950
1000
|
const { rows } = await client.execute({
|
|
951
|
-
sql: `SELECT ${
|
|
1001
|
+
sql: `SELECT ${select.sql} FROM chat_threads WHERE ${filters.join(" AND ")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC, id ASC LIMIT ? OFFSET ?`,
|
|
952
1002
|
args,
|
|
953
1003
|
});
|
|
954
1004
|
return rows
|
|
@@ -965,13 +1015,25 @@ export async function searchThreads(ownerEmail, query, limit = 50, options = {})
|
|
|
965
1015
|
// The count-guard uses the maintained `message_count` column (same as
|
|
966
1016
|
// listThreads). The content match still scans `thread_data` — search
|
|
967
1017
|
// legitimately needs to look inside message history.
|
|
968
|
-
const access = chatThreadAccessSql(ownerEmail, options.orgId
|
|
1018
|
+
const access = await chatThreadAccessSql(ownerEmail, options.orgId === undefined ? getRequestOrgId() : options.orgId);
|
|
1019
|
+
const ownershipFilter = chatThreadOwnershipSql(ownerEmail, options.ownership);
|
|
1020
|
+
const select = chatThreadSummarySelect(ownerEmail);
|
|
969
1021
|
const filters = [
|
|
970
1022
|
access.sql,
|
|
971
1023
|
`message_count > 0`,
|
|
972
1024
|
`(title LIKE ? ESCAPE '!' OR preview LIKE ? ESCAPE '!' OR thread_data LIKE ? ESCAPE '!')`,
|
|
973
1025
|
];
|
|
974
|
-
const args = [
|
|
1026
|
+
const args = [
|
|
1027
|
+
...select.args,
|
|
1028
|
+
...access.args,
|
|
1029
|
+
pattern,
|
|
1030
|
+
pattern,
|
|
1031
|
+
pattern,
|
|
1032
|
+
];
|
|
1033
|
+
if (ownershipFilter) {
|
|
1034
|
+
filters.push(ownershipFilter.sql);
|
|
1035
|
+
args.push(...ownershipFilter.args);
|
|
1036
|
+
}
|
|
975
1037
|
if (!options.includeArchived) {
|
|
976
1038
|
filters.push(`archived_at IS NULL`);
|
|
977
1039
|
}
|
|
@@ -986,9 +1048,9 @@ export async function searchThreads(ownerEmail, query, limit = 50, options = {})
|
|
|
986
1048
|
filters.push(`scope_type = ? AND scope_id = ?`);
|
|
987
1049
|
args.push(options.scope.type, options.scope.id);
|
|
988
1050
|
}
|
|
989
|
-
args.push(limit);
|
|
1051
|
+
args.push(limit, options.offset ?? 0);
|
|
990
1052
|
const { rows } = await client.execute({
|
|
991
|
-
sql: `SELECT ${
|
|
1053
|
+
sql: `SELECT ${select.sql} FROM chat_threads WHERE ${filters.join(" AND ")} ORDER BY CASE WHEN pinned_at IS NULL THEN 1 ELSE 0 END, pinned_at DESC, updated_at DESC, id ASC LIMIT ? OFFSET ?`,
|
|
992
1054
|
args,
|
|
993
1055
|
});
|
|
994
1056
|
return rows
|
|
@@ -10,6 +10,7 @@ const GIT_IDENTITY = {
|
|
|
10
10
|
GIT_COMMITTER_NAME: "agent-native",
|
|
11
11
|
GIT_COMMITTER_EMAIL: "noreply@agent-native.com",
|
|
12
12
|
};
|
|
13
|
+
const KEEP_LINE_ENDINGS = ["-c", "core.autocrlf=false", "-c", "core.eol=lf"];
|
|
13
14
|
export function resolveBaselineStore(appDir) {
|
|
14
15
|
const resolved = realpath(path.resolve(appDir));
|
|
15
16
|
const gitDir = findGitDir(resolved);
|
|
@@ -67,10 +68,15 @@ export function writeBaseline(store, sourceDir, slot, meta) {
|
|
|
67
68
|
copyPlainTree(sourceDir, target);
|
|
68
69
|
const indexFile = path.join(stage, "index");
|
|
69
70
|
const env = { ...process.env, ...GIT_IDENTITY, GIT_INDEX_FILE: indexFile };
|
|
70
|
-
git(store, [
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
git(store, [
|
|
72
|
+
...KEEP_LINE_ENDINGS,
|
|
73
|
+
"--work-tree",
|
|
74
|
+
stageRoot,
|
|
75
|
+
"add",
|
|
76
|
+
"-A",
|
|
77
|
+
"--force",
|
|
78
|
+
".",
|
|
79
|
+
], { cwd: stageRoot, env });
|
|
74
80
|
const tree = git(store, ["write-tree"], { cwd: stageRoot, env }).trim();
|
|
75
81
|
const ref = baselineRefName(store, slot);
|
|
76
82
|
const parent = revParse(store, ref);
|
|
@@ -142,7 +148,14 @@ export function materializeBaseline(store, slot) {
|
|
|
142
148
|
return null;
|
|
143
149
|
}
|
|
144
150
|
const tarPath = path.join(out, ".baseline.tar");
|
|
145
|
-
const args = [
|
|
151
|
+
const args = [
|
|
152
|
+
...KEEP_LINE_ENDINGS,
|
|
153
|
+
"archive",
|
|
154
|
+
"--format=tar",
|
|
155
|
+
"-o",
|
|
156
|
+
tarPath,
|
|
157
|
+
ref,
|
|
158
|
+
];
|
|
146
159
|
if (store.prefix)
|
|
147
160
|
args.push("--", store.prefix);
|
|
148
161
|
git(store, args);
|
|
@@ -149,12 +149,13 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
|
|
|
149
149
|
manual: [],
|
|
150
150
|
keptLocal: [],
|
|
151
151
|
};
|
|
152
|
-
const paths = new Set([
|
|
152
|
+
const paths = Array.from(new Set([
|
|
153
153
|
...listMergeableFiles(baseDir),
|
|
154
154
|
...listMergeableFiles(theirsDir),
|
|
155
155
|
...listMergeableFiles(appDir),
|
|
156
|
-
]);
|
|
157
|
-
|
|
156
|
+
])).sort();
|
|
157
|
+
const normalized = crlfNormalizedPaths(appDir, paths);
|
|
158
|
+
for (const rel of paths) {
|
|
158
159
|
const oursPath = path.join(appDir, rel);
|
|
159
160
|
if (isLocalSymlink(oursPath)) {
|
|
160
161
|
result.manual.push(`${rel} (local symlink)`);
|
|
@@ -162,7 +163,9 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
|
|
|
162
163
|
}
|
|
163
164
|
const base = readFileOrNull(path.join(baseDir, rel));
|
|
164
165
|
const theirs = readFileOrNull(path.join(theirsDir, rel));
|
|
165
|
-
const
|
|
166
|
+
const app = readAppFile(oursPath, normalized.has(rel) ? (base ?? theirs) : null);
|
|
167
|
+
const ours = app.content;
|
|
168
|
+
const writeOurs = (content) => writeFile(oursPath, app.crlf ? withCrlf(content) : content);
|
|
166
169
|
if (equalBuffers(base, theirs))
|
|
167
170
|
continue;
|
|
168
171
|
if (theirs === null) {
|
|
@@ -193,7 +196,7 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
|
|
|
193
196
|
continue;
|
|
194
197
|
if (equalBuffers(ours, base)) {
|
|
195
198
|
if (!options.dryRun)
|
|
196
|
-
|
|
199
|
+
writeOurs(theirs);
|
|
197
200
|
result.updated.push(rel);
|
|
198
201
|
continue;
|
|
199
202
|
}
|
|
@@ -206,8 +209,9 @@ export function mergeTemplateTrees(appDir, baseDir, theirsDir, options = {}) {
|
|
|
206
209
|
result.manual.push(`${rel} (merge failed)`);
|
|
207
210
|
continue;
|
|
208
211
|
}
|
|
209
|
-
if (!options.dryRun)
|
|
210
|
-
|
|
212
|
+
if (!options.dryRun && !equalBuffers(merged.content, ours)) {
|
|
213
|
+
writeOurs(merged.content);
|
|
214
|
+
}
|
|
211
215
|
if (merged.conflicts > 0)
|
|
212
216
|
result.conflicted.push(rel);
|
|
213
217
|
else
|
|
@@ -475,19 +479,21 @@ async function statusCommand(target, flags, io) {
|
|
|
475
479
|
try {
|
|
476
480
|
const local = countLocallyModified(target.appDir, baseDir);
|
|
477
481
|
lines.push(` locally modified files: ${local}`);
|
|
478
|
-
const targetRef = flags.to ?? target.provenance.templateRef ?? latest;
|
|
479
|
-
const theirs = await materializeForTarget(target, flags, targetRef);
|
|
480
482
|
try {
|
|
481
|
-
const
|
|
482
|
-
|
|
483
|
+
const targetRef = flags.to ?? target.provenance.templateRef ?? latest;
|
|
484
|
+
const theirs = await materializeForTarget(target, flags, targetRef);
|
|
485
|
+
try {
|
|
486
|
+
const changed = countUpstreamChanged(baseDir, theirs.dir);
|
|
487
|
+
lines.push(` upstream-changed files: ${changed} (at ${theirs.ref})`);
|
|
488
|
+
}
|
|
489
|
+
finally {
|
|
490
|
+
fs.rmSync(theirs.dir, { recursive: true, force: true });
|
|
491
|
+
}
|
|
483
492
|
}
|
|
484
|
-
|
|
485
|
-
|
|
493
|
+
catch (err) {
|
|
494
|
+
lines.push(` upstream-changed files: unavailable (${err instanceof Error ? err.message.split("\n")[0] : String(err)})`);
|
|
486
495
|
}
|
|
487
496
|
}
|
|
488
|
-
catch (err) {
|
|
489
|
-
lines.push(` upstream-changed files: unavailable (${err instanceof Error ? err.message.split("\n")[0] : String(err)})`);
|
|
490
|
-
}
|
|
491
497
|
finally {
|
|
492
498
|
fs.rmSync(baseDir, { recursive: true, force: true });
|
|
493
499
|
}
|
|
@@ -648,13 +654,19 @@ function backfillProvenance(target, template, materialized) {
|
|
|
648
654
|
shape: target.shape,
|
|
649
655
|
};
|
|
650
656
|
pkg["agent-native"] = agentNative;
|
|
651
|
-
|
|
657
|
+
const json = Buffer.from(`${JSON.stringify(pkg, null, 2)}\n`);
|
|
658
|
+
const app = readAppFile(pkgPath, json);
|
|
659
|
+
if (equalBuffers(app.content, json))
|
|
660
|
+
return;
|
|
661
|
+
fs.writeFileSync(pkgPath, app.crlf ? withCrlf(json) : json);
|
|
652
662
|
}
|
|
653
663
|
function countLocallyModified(appDir, baseDir) {
|
|
654
664
|
let count = 0;
|
|
655
|
-
|
|
665
|
+
const paths = Array.from(listMergeableFiles(baseDir));
|
|
666
|
+
const normalized = crlfNormalizedPaths(appDir, paths);
|
|
667
|
+
for (const rel of paths) {
|
|
656
668
|
const base = readFileOrNull(path.join(baseDir, rel));
|
|
657
|
-
const ours =
|
|
669
|
+
const ours = readAppFile(path.join(appDir, rel), normalized.has(rel) ? base : null).content;
|
|
658
670
|
if (!equalBuffers(base, ours))
|
|
659
671
|
count++;
|
|
660
672
|
}
|
|
@@ -809,6 +821,75 @@ function equalBuffers(a, b) {
|
|
|
809
821
|
return a === b;
|
|
810
822
|
return a.equals(b);
|
|
811
823
|
}
|
|
824
|
+
// CRLF that git normalizes on add is not a local edit.
|
|
825
|
+
function readAppFile(file, template) {
|
|
826
|
+
const content = readFileOrNull(file);
|
|
827
|
+
if (content === null ||
|
|
828
|
+
template === null ||
|
|
829
|
+
template.includes(0x0d) ||
|
|
830
|
+
!isTextBuffer(content) ||
|
|
831
|
+
!isTextBuffer(template)) {
|
|
832
|
+
return { content, crlf: false };
|
|
833
|
+
}
|
|
834
|
+
const text = content.toString("utf-8");
|
|
835
|
+
if (!text.includes("\r\n") || /\r(?!\n)/.test(text)) {
|
|
836
|
+
return { content, crlf: false };
|
|
837
|
+
}
|
|
838
|
+
return {
|
|
839
|
+
content: Buffer.from(text.replace(/\r\n/g, "\n")),
|
|
840
|
+
crlf: !/(^|[^\r])\n/.test(text),
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
// Paths whose CRLF git turns into LF on add; anywhere else a CR is content.
|
|
844
|
+
function crlfNormalizedPaths(appDir, rels) {
|
|
845
|
+
const normalized = new Set();
|
|
846
|
+
if (!resolveBaselineStore(appDir).gitDir)
|
|
847
|
+
return normalized;
|
|
848
|
+
const res = spawnSync("git", ["check-attr", "-z", "--stdin", "text", "crlf", "eol"], {
|
|
849
|
+
cwd: appDir,
|
|
850
|
+
input: rels.join("\0"),
|
|
851
|
+
encoding: "utf-8",
|
|
852
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
853
|
+
});
|
|
854
|
+
if (res.status !== 0) {
|
|
855
|
+
throw new Error(`git check-attr failed in ${appDir}: ${res.stderr || res.error?.message}`);
|
|
856
|
+
}
|
|
857
|
+
const config = spawnSync("git", ["config", "--get", "core.autocrlf"], {
|
|
858
|
+
cwd: appDir,
|
|
859
|
+
encoding: "utf-8",
|
|
860
|
+
});
|
|
861
|
+
if (config.status !== 0 && config.status !== 1) {
|
|
862
|
+
throw new Error(`git config core.autocrlf failed in ${appDir}: ${config.stderr || config.error?.message}`);
|
|
863
|
+
}
|
|
864
|
+
const byConfig = ["true", "yes", "on", "1", "input"].includes(config.stdout.trim().toLowerCase());
|
|
865
|
+
const attrs = new Map();
|
|
866
|
+
const fields = res.stdout.split("\0");
|
|
867
|
+
for (let i = 0; i + 2 < fields.length; i += 3) {
|
|
868
|
+
attrs.set(fields[i], {
|
|
869
|
+
...attrs.get(fields[i]),
|
|
870
|
+
[fields[i + 1]]: fields[i + 2],
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
for (const [rel, { text, crlf, eol }] of attrs) {
|
|
874
|
+
const byAttrs = conversion(text) ??
|
|
875
|
+
conversion(crlf) ??
|
|
876
|
+
(eol === "lf" || eol === "crlf" ? true : null);
|
|
877
|
+
if (byAttrs ?? byConfig)
|
|
878
|
+
normalized.add(rel);
|
|
879
|
+
}
|
|
880
|
+
return normalized;
|
|
881
|
+
}
|
|
882
|
+
// A text or crlf attribute as git reads it: convert, keep bytes, or no say.
|
|
883
|
+
function conversion(value) {
|
|
884
|
+
if (value === "set" || value === "auto" || value === "input")
|
|
885
|
+
return true;
|
|
886
|
+
return value === "unset" ? false : null;
|
|
887
|
+
}
|
|
888
|
+
function withCrlf(content) {
|
|
889
|
+
if (!isTextBuffer(content))
|
|
890
|
+
return content;
|
|
891
|
+
return Buffer.from(content.toString("utf-8").replace(/\r?\n/g, "\r\n"));
|
|
892
|
+
}
|
|
812
893
|
function isTextBuffer(buf) {
|
|
813
894
|
if (buf === null)
|
|
814
895
|
return true;
|
|
@@ -17,7 +17,8 @@ export { AGENT_NATIVE_MCP_APP_HOST_MESSAGE_TYPES, getMcpAppHostContext, initiali
|
|
|
17
17
|
export { buildDynamicAgentSuggestions, dedupeSuggestions, mergeAgentSuggestions, normalizeAgentDynamicSuggestionsConfig, useAgentDynamicSuggestions, useAgentDynamicSuggestionsResult, type AgentDynamicSuggestionContext, type AgentDynamicSuggestionsConfig, type AgentDynamicSuggestionsOption, } from "../dynamic-suggestions.js";
|
|
18
18
|
export { clearChatStorage } from "../chat/storage.js";
|
|
19
19
|
export { isAssistantChatHistoryVersion, coerceAssistantChatHistoryDate, type AssistantChatHistoryDate, type AssistantChatHistoryVersion, } from "../chat/assistant-chat-history-version.js";
|
|
20
|
-
export {
|
|
20
|
+
export { ChatThreadListConfigError, useChatThreadList, type UseChatThreadListOptions, type UseChatThreadListResult, } from "../use-chat-thread-list.js";
|
|
21
|
+
export { ChatThreadListError, fetchChatThreadListPage, notifyChatThreadsUpdated, useChatThreads, type ChatThreadAccessBasis, type ChatThreadListPage, type ChatThreadListRow, type ChatThreadListPageRequest, type ChatThreadOwnership, type ChatThreadVisibility, type ChatThreadScope, type ChatThreadSnapshot, type ChatThreadSummary, type ChatThreadData, type ChatThreadShareLink, type ChatThreadShareState, type UseChatThreadsOptions, } from "../use-chat-threads.js";
|
|
21
22
|
export { type AgentCallProgress, type ContentPart, } from "../sse-event-processor.js";
|
|
22
23
|
export { useRunStuckDetection, useAbortRun, type RunStuckState, type UseRunStuckDetectionOptions, } from "../use-run-stuck-detection.js";
|
|
23
24
|
export { AGENT_CHAT_HOME_HANDOFF_TTL_MS, AGENT_CHAT_VIEW_TRANSITION_CLASS, AGENT_CHAT_VIEW_TRANSITION_NAME, consumeAgentChatHomeHandoff, getAgentChatViewTransitionStyle, isAgentChatHomeHandoffActive, markAgentChatHomeHandoff, navigateWithAgentChatViewTransition, startAgentChatViewTransition, supportsAgentChatViewTransition, type AgentChatHomeHandoffOptions, type AgentChatViewTransition, type AgentChatViewTransitionOptions, } from "../chat-view-transition.js";
|
|
@@ -17,7 +17,8 @@ export { AGENT_NATIVE_MCP_APP_HOST_MESSAGE_TYPES, getMcpAppHostContext, initiali
|
|
|
17
17
|
export { buildDynamicAgentSuggestions, dedupeSuggestions, mergeAgentSuggestions, normalizeAgentDynamicSuggestionsConfig, useAgentDynamicSuggestions, useAgentDynamicSuggestionsResult, } from "../dynamic-suggestions.js";
|
|
18
18
|
export { clearChatStorage } from "../chat/storage.js";
|
|
19
19
|
export { isAssistantChatHistoryVersion, coerceAssistantChatHistoryDate, } from "../chat/assistant-chat-history-version.js";
|
|
20
|
-
export {
|
|
20
|
+
export { ChatThreadListConfigError, useChatThreadList, } from "../use-chat-thread-list.js";
|
|
21
|
+
export { ChatThreadListError, fetchChatThreadListPage, notifyChatThreadsUpdated, useChatThreads, } from "../use-chat-threads.js";
|
|
21
22
|
export { useRunStuckDetection, useAbortRun, } from "../use-run-stuck-detection.js";
|
|
22
23
|
export { AGENT_CHAT_HOME_HANDOFF_TTL_MS, AGENT_CHAT_VIEW_TRANSITION_CLASS, AGENT_CHAT_VIEW_TRANSITION_NAME, consumeAgentChatHomeHandoff, getAgentChatViewTransitionStyle, isAgentChatHomeHandoffActive, markAgentChatHomeHandoff, navigateWithAgentChatViewTransition, startAgentChatViewTransition, supportsAgentChatViewTransition, } from "../chat-view-transition.js";
|
|
23
24
|
export { useAgentChatHomeHandoff, useAgentChatHomeHandoffLinks, } from "../use-agent-chat-home-handoff.js";
|
|
@@ -1442,6 +1442,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1442
1442
|
runId: input.runId,
|
|
1443
1443
|
threadId: input.threadId,
|
|
1444
1444
|
session,
|
|
1445
|
+
...(state?.status !== "missing" && state?.startMessageId
|
|
1446
|
+
? { startMessageId: state.startMessageId }
|
|
1447
|
+
: {}),
|
|
1445
1448
|
turn: runAuthority
|
|
1446
1449
|
? turn
|
|
1447
1450
|
: {
|
|
@@ -1520,6 +1523,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1520
1523
|
runId,
|
|
1521
1524
|
threadId,
|
|
1522
1525
|
session,
|
|
1526
|
+
...(start.messageId === undefined
|
|
1527
|
+
? {}
|
|
1528
|
+
: { startMessageId: start.messageId }),
|
|
1523
1529
|
turn,
|
|
1524
1530
|
events: [],
|
|
1525
1531
|
firstRetainedSequence: 1,
|
|
@@ -1550,6 +1556,15 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
1550
1556
|
? findRun(threadId, runId)
|
|
1551
1557
|
: undefined;
|
|
1552
1558
|
if (existingRun) {
|
|
1559
|
+
if (start.messageId === undefined ||
|
|
1560
|
+
existingRun.startMessageId !== start.messageId) {
|
|
1561
|
+
await closeDiscardedTurnEvents(turn);
|
|
1562
|
+
throw new Error(`Duplicate AgentKit run id: ${runId}`);
|
|
1563
|
+
}
|
|
1564
|
+
if (turn.id !== undefined && existingRun.turn.id === turn.id) {
|
|
1565
|
+
await closeDiscardedTurnEvents(turn);
|
|
1566
|
+
return existingRun.runId;
|
|
1567
|
+
}
|
|
1553
1568
|
// A duplicate queued submission is answered with the run that already
|
|
1554
1569
|
// took it, replayed from its first event. This adapter reads that run
|
|
1555
1570
|
// already, so the replay is drained rather than indexed a second time.
|
|
@@ -3125,6 +3140,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3125
3140
|
});
|
|
3126
3141
|
return openStartedRun(input.threadId, session, turn, turnMetadata, undefined, {
|
|
3127
3142
|
attachReplayedRun: true,
|
|
3143
|
+
messageId: latestUserMessage?.id,
|
|
3128
3144
|
});
|
|
3129
3145
|
};
|
|
3130
3146
|
if (!queuePromotionKey) {
|
|
@@ -3427,6 +3443,9 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3427
3443
|
runId: nextRunId,
|
|
3428
3444
|
threadId: input.threadId,
|
|
3429
3445
|
session: run.session,
|
|
3446
|
+
...(run.startMessageId === undefined
|
|
3447
|
+
? {}
|
|
3448
|
+
: { startMessageId: run.startMessageId }),
|
|
3430
3449
|
turn: nextTurn,
|
|
3431
3450
|
events: [],
|
|
3432
3451
|
firstRetainedSequence: 1,
|
|
@@ -3541,7 +3560,8 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
|
|
|
3541
3560
|
...(attachments.length ? { attachments } : {}),
|
|
3542
3561
|
abortSignal: readers.signal,
|
|
3543
3562
|
});
|
|
3544
|
-
const
|
|
3563
|
+
const startMessageId = local?.startMessageId ?? state.startMessageId;
|
|
3564
|
+
const runId = await openStartedRun(input.threadId, session, turn, undefined, { continuedRunId: input.runId }, startMessageId === undefined ? {} : { messageId: startMessageId });
|
|
3545
3565
|
return { runId, capabilities };
|
|
3546
3566
|
};
|
|
3547
3567
|
}
|
|
@@ -65,6 +65,7 @@ export type ServerRunState = {
|
|
|
65
65
|
readonly status: "running" | "completed" | "truncated" | "errored" | "aborted";
|
|
66
66
|
readonly runId: string;
|
|
67
67
|
readonly turnId?: string;
|
|
68
|
+
readonly startMessageId?: string;
|
|
68
69
|
/** Server clock, epoch ms. */
|
|
69
70
|
readonly startedAt?: number;
|
|
70
71
|
readonly dispatchMode?: string;
|
|
@@ -3459,10 +3459,15 @@ export function createAgentNativeChatRuntime(options = {}) {
|
|
|
3459
3459
|
throw unreadable(`Agent chat run state is unreadable (run ${String(runId)}, status ${String(status)}).`, response.status);
|
|
3460
3460
|
}
|
|
3461
3461
|
const pendingConnectionRequestId = value?.pendingConnectionRequestId;
|
|
3462
|
+
const startMessageId = value?.startMessageId;
|
|
3462
3463
|
if (input.includePendingConnectionRequest &&
|
|
3463
3464
|
(!value || !Object.hasOwn(value, "pendingConnectionRequestId"))) {
|
|
3464
3465
|
throw unreadable("Agent chat run state is unreadable (pending connection request was not returned).", response.status);
|
|
3465
3466
|
}
|
|
3467
|
+
if (startMessageId !== undefined &&
|
|
3468
|
+
(typeof startMessageId !== "string" || !startMessageId.trim())) {
|
|
3469
|
+
throw unreadable("Agent chat run state is unreadable (start message ID is invalid).", response.status);
|
|
3470
|
+
}
|
|
3466
3471
|
if (pendingConnectionRequestId !== undefined &&
|
|
3467
3472
|
pendingConnectionRequestId !== null &&
|
|
3468
3473
|
(typeof pendingConnectionRequestId !== "string" ||
|
|
@@ -3475,6 +3480,7 @@ export function createAgentNativeChatRuntime(options = {}) {
|
|
|
3475
3480
|
...(typeof value?.turnId === "string" && value.turnId
|
|
3476
3481
|
? { turnId: value.turnId }
|
|
3477
3482
|
: {}),
|
|
3483
|
+
...(typeof startMessageId === "string" ? { startMessageId } : {}),
|
|
3478
3484
|
...(typeof value?.startedAt === "number" &&
|
|
3479
3485
|
Number.isFinite(value.startedAt)
|
|
3480
3486
|
? { startedAt: value.startedAt }
|
|
@@ -3,4 +3,5 @@ export { useAccessRequestDecisions, useAccessRequestReview, useResourceAccessReq
|
|
|
3
3
|
export { useResourceAccessGate, type ResourceAccessGateController, type ResourceAccessGateOptions, type ResourceAccessGateRequest, type ResourceAccessRequestFailure, type ResourceAccessGateRole, type ResourceAccessGateState, type ResourceAccessGateStatus, } from "./useResourceAccessGate.js";
|
|
4
4
|
export { useShareButtonController, type ShareButtonController, type ShareButtonControllerOptions, type ShareButtonOrgMember, type ShareButtonOrgMemberSearch, type ShareButtonRole, type ShareButtonShare, type ShareButtonSharesResponse, type ShareButtonVisibility, } from "./useShareButtonController.js";
|
|
5
5
|
export { useShareDialogController, type ResourceShare, type ResourceSharesResponse, type ShareDialogController, type ShareDialogControllerOptions, type ShareDialogPerson, type ShareDialogTab, type ShareOption, type ShareRole, type ShareVisibility, } from "./useShareDialogController.js";
|
|
6
|
-
export {
|
|
6
|
+
export { ShareVisibilityNotSavedError, useShareVisibilityTransition, visibilityNeedsConfirmation, type ShareVisibilityTransition, type ShareVisibilityTransitionOptions, type ShareVisibilityTransitionRequest, } from "./useShareVisibilityTransition.js";
|
|
7
|
+
export { createShareQueryKey, createShareQueryParams, extractShareErrorMessage, fetchOrgMemberPage, mergeOrgMembers, normalizeOrgMembers, notifyShareChanged, optimisticallyUpdateShareCache, rollbackShareCache, useShareMutationGuard, useShareMutations, useShareOrgMemberSearch, useShareQuery, type OrgMemberPage, type ShareOrgMember, type ShareOrgMemberSearchResult, type ShareQueryKey, type ShareQueryParams, } from "./share-controller-helpers.js";
|
|
@@ -3,4 +3,5 @@ export { useAccessRequestDecisions, useAccessRequestReview, useResourceAccessReq
|
|
|
3
3
|
export { useResourceAccessGate, } from "./useResourceAccessGate.js";
|
|
4
4
|
export { useShareButtonController, } from "./useShareButtonController.js";
|
|
5
5
|
export { useShareDialogController, } from "./useShareDialogController.js";
|
|
6
|
-
export {
|
|
6
|
+
export { ShareVisibilityNotSavedError, useShareVisibilityTransition, visibilityNeedsConfirmation, } from "./useShareVisibilityTransition.js";
|
|
7
|
+
export { createShareQueryKey, createShareQueryParams, extractShareErrorMessage, fetchOrgMemberPage, mergeOrgMembers, normalizeOrgMembers, notifyShareChanged, optimisticallyUpdateShareCache, rollbackShareCache, useShareMutationGuard, useShareMutations, useShareOrgMemberSearch, useShareQuery, } from "./share-controller-helpers.js";
|