@assistant-ui/core 0.2.9 → 0.2.10

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 (123) hide show
  1. package/dist/model-context/tool.d.ts +1 -1
  2. package/dist/model-context/tool.js +1 -1
  3. package/dist/model-context/tool.js.map +1 -1
  4. package/dist/model-context/types.js +17 -2
  5. package/dist/model-context/types.js.map +1 -1
  6. package/dist/react/adapters/LocalStorageThreadListAdapter.d.ts.map +1 -1
  7. package/dist/react/adapters/LocalStorageThreadListAdapter.js +12 -2
  8. package/dist/react/adapters/LocalStorageThreadListAdapter.js.map +1 -1
  9. package/dist/react/client/Tools.d.ts.map +1 -1
  10. package/dist/react/client/Tools.js +9 -3
  11. package/dist/react/client/Tools.js.map +1 -1
  12. package/dist/react/index.d.ts +7 -3
  13. package/dist/react/index.js +6 -2
  14. package/dist/react/model-context/define-mcp-toolkit.d.ts +12 -0
  15. package/dist/react/model-context/define-mcp-toolkit.d.ts.map +1 -0
  16. package/dist/react/model-context/define-mcp-toolkit.js +14 -0
  17. package/dist/react/model-context/define-mcp-toolkit.js.map +1 -0
  18. package/dist/react/model-context/define-toolkit.d.ts +4 -3
  19. package/dist/react/model-context/define-toolkit.d.ts.map +1 -1
  20. package/dist/react/model-context/define-toolkit.js +1 -14
  21. package/dist/react/model-context/define-toolkit.js.map +1 -1
  22. package/dist/react/model-context/hitl.d.ts +8 -4
  23. package/dist/react/model-context/hitl.d.ts.map +1 -1
  24. package/dist/react/model-context/hitl.js +9 -5
  25. package/dist/react/model-context/hitl.js.map +1 -1
  26. package/dist/react/model-context/makeAssistantTool.d.ts +8 -0
  27. package/dist/react/model-context/makeAssistantTool.d.ts.map +1 -1
  28. package/dist/react/model-context/makeAssistantTool.js +4 -0
  29. package/dist/react/model-context/makeAssistantTool.js.map +1 -1
  30. package/dist/react/model-context/makeAssistantToolUI.d.ts +8 -0
  31. package/dist/react/model-context/makeAssistantToolUI.d.ts.map +1 -1
  32. package/dist/react/model-context/makeAssistantToolUI.js +4 -0
  33. package/dist/react/model-context/makeAssistantToolUI.js.map +1 -1
  34. package/dist/react/model-context/provider-tool.d.ts +15 -0
  35. package/dist/react/model-context/provider-tool.d.ts.map +1 -0
  36. package/dist/react/model-context/provider-tool.js +12 -0
  37. package/dist/react/model-context/provider-tool.js.map +1 -0
  38. package/dist/react/model-context/stub-tool.d.ts +12 -0
  39. package/dist/react/model-context/stub-tool.d.ts.map +1 -0
  40. package/dist/react/model-context/stub-tool.js +15 -0
  41. package/dist/react/model-context/stub-tool.js.map +1 -0
  42. package/dist/react/model-context/toolbox.d.ts +62 -15
  43. package/dist/react/model-context/toolbox.d.ts.map +1 -1
  44. package/dist/react/model-context/toolbox.js +19 -1
  45. package/dist/react/model-context/toolbox.js.map +1 -1
  46. package/dist/react/model-context/useAssistantTool.d.ts +11 -1
  47. package/dist/react/model-context/useAssistantTool.d.ts.map +1 -1
  48. package/dist/react/model-context/useAssistantTool.js +12 -6
  49. package/dist/react/model-context/useAssistantTool.js.map +1 -1
  50. package/dist/react/model-context/useAssistantToolUI.d.ts +13 -4
  51. package/dist/react/model-context/useAssistantToolUI.d.ts.map +1 -1
  52. package/dist/react/model-context/useAssistantToolUI.js +6 -3
  53. package/dist/react/model-context/useAssistantToolUI.js.map +1 -1
  54. package/dist/react/model-context/useAuiToolOverrides.d.ts +22 -0
  55. package/dist/react/model-context/useAuiToolOverrides.d.ts.map +1 -0
  56. package/dist/react/model-context/useAuiToolOverrides.js +31 -0
  57. package/dist/react/model-context/useAuiToolOverrides.js.map +1 -0
  58. package/dist/react/primitives/part/PartMessages.d.ts +13 -11
  59. package/dist/react/primitives/part/PartMessages.d.ts.map +1 -1
  60. package/dist/react/primitives/part/PartMessages.js +13 -11
  61. package/dist/react/primitives/part/PartMessages.js.map +1 -1
  62. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts +1 -0
  63. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.d.ts.map +1 -1
  64. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js +28 -0
  65. package/dist/react/runtimes/RemoteThreadListThreadListRuntimeCore.js.map +1 -1
  66. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.d.ts.map +1 -1
  67. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js +9 -2
  68. package/dist/react/runtimes/cloud/useCloudThreadListAdapter.js.map +1 -1
  69. package/dist/runtime/api/thread-list-item-runtime.d.ts +2 -0
  70. package/dist/runtime/api/thread-list-item-runtime.d.ts.map +1 -1
  71. package/dist/runtime/api/thread-list-item-runtime.js +6 -0
  72. package/dist/runtime/api/thread-list-item-runtime.js.map +1 -1
  73. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts +1 -0
  74. package/dist/runtime/interfaces/thread-list-runtime-core.d.ts.map +1 -1
  75. package/dist/runtimes/external-store/external-store-adapter.d.ts +2 -0
  76. package/dist/runtimes/external-store/external-store-adapter.d.ts.map +1 -1
  77. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts +1 -0
  78. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.d.ts.map +1 -1
  79. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js +5 -0
  80. package/dist/runtimes/external-store/external-store-thread-list-runtime-core.js.map +1 -1
  81. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts +1 -0
  82. package/dist/runtimes/remote-thread-list/adapter/in-memory.d.ts.map +1 -1
  83. package/dist/runtimes/remote-thread-list/adapter/in-memory.js +3 -0
  84. package/dist/runtimes/remote-thread-list/adapter/in-memory.js.map +1 -1
  85. package/dist/runtimes/remote-thread-list/types.d.ts +1 -0
  86. package/dist/runtimes/remote-thread-list/types.d.ts.map +1 -1
  87. package/dist/store/runtime-clients/thread-list-item-runtime-client.js +1 -0
  88. package/dist/store/runtime-clients/thread-list-item-runtime-client.js.map +1 -1
  89. package/dist/store/scopes/thread-list-item.d.ts +1 -0
  90. package/dist/store/scopes/thread-list-item.d.ts.map +1 -1
  91. package/package.json +5 -5
  92. package/src/model-context/tool.ts +1 -1
  93. package/src/model-context/types.ts +21 -3
  94. package/src/react/adapters/LocalStorageThreadListAdapter.tsx +15 -2
  95. package/src/react/client/Tools.ts +22 -7
  96. package/src/react/index.ts +14 -3
  97. package/src/react/model-context/define-mcp-toolkit.ts +16 -0
  98. package/src/react/model-context/define-toolkit.test.ts +92 -4
  99. package/src/react/model-context/define-toolkit.ts +21 -3
  100. package/src/react/model-context/hitl.ts +10 -5
  101. package/src/react/model-context/makeAssistantTool.ts +8 -0
  102. package/src/react/model-context/makeAssistantToolUI.ts +8 -0
  103. package/src/react/model-context/provider-tool.ts +30 -0
  104. package/src/react/model-context/stub-tool.ts +14 -0
  105. package/src/react/model-context/toolbox.test.ts +182 -0
  106. package/src/react/model-context/toolbox.ts +189 -21
  107. package/src/react/model-context/useAssistantTool.ts +28 -8
  108. package/src/react/model-context/useAssistantToolUI.ts +13 -4
  109. package/src/react/model-context/useAuiToolOverrides.ts +38 -0
  110. package/src/react/primitives/part/PartMessages.tsx +13 -11
  111. package/src/react/runtimes/RemoteThreadListThreadListRuntimeCore.tsx +43 -0
  112. package/src/react/runtimes/cloud/useCloudThreadListAdapter.tsx +9 -0
  113. package/src/runtime/api/thread-list-item-runtime.ts +15 -0
  114. package/src/runtime/interfaces/thread-list-runtime-core.ts +4 -0
  115. package/src/runtimes/external-store/external-store-adapter.ts +7 -0
  116. package/src/runtimes/external-store/external-store-thread-list-runtime-core.ts +13 -0
  117. package/src/runtimes/remote-thread-list/adapter/in-memory.ts +4 -0
  118. package/src/runtimes/remote-thread-list/types.ts +4 -0
  119. package/src/store/clients/model-context-client.test.ts +87 -2
  120. package/src/store/runtime-clients/thread-list-item-runtime-client.ts +1 -0
  121. package/src/store/scopes/thread-list-item.ts +1 -0
  122. package/src/tests/RemoteThreadListThreadListRuntimeCore-custom-metadata.test.ts +69 -1
  123. package/src/tests/thread-list-runtime-getLoadThreadsPromise.test.ts +1 -0
@@ -14,6 +14,7 @@ import { InMemoryThreadListAdapter } from "../../../runtimes/remote-thread-list/
14
14
  import { useAssistantCloudThreadHistoryAdapter } from "./AssistantCloudThreadHistoryAdapter";
15
15
  import { RuntimeAdapterProvider } from "../RuntimeAdapterProvider";
16
16
  import { CloudFileAttachmentAdapter } from "./CloudFileAttachmentAdapter";
17
+ import { isRecord } from "../../../utils/json/is-json";
17
18
 
18
19
  type ThreadData = {
19
20
  externalId: string | undefined;
@@ -26,6 +27,9 @@ type CloudThreadListAdapterOptions = {
26
27
  delete?: ((threadId: string) => Promise<void>) | undefined;
27
28
  };
28
29
 
30
+ const toCustom = (value: unknown): Record<string, unknown> | undefined =>
31
+ isRecord(value) ? value : undefined;
32
+
29
33
  const baseUrl =
30
34
  typeof process !== "undefined" &&
31
35
  process?.env?.NEXT_PUBLIC_ASSISTANT_BASE_URL;
@@ -91,6 +95,7 @@ export const useCloudThreadListAdapter = (
91
95
  remoteId: t.id,
92
96
  title: t.title,
93
97
  externalId: t.external_id ?? undefined,
98
+ custom: toCustom(t.metadata),
94
99
  })),
95
100
  };
96
101
  },
@@ -110,6 +115,9 @@ export const useCloudThreadListAdapter = (
110
115
  rename: async (threadId, newTitle) => {
111
116
  return cloud.threads.update(threadId, { title: newTitle });
112
117
  },
118
+ updateCustom: async (threadId, custom) => {
119
+ return cloud.threads.update(threadId, { metadata: custom ?? null });
120
+ },
113
121
  archive: async (threadId) => {
114
122
  return cloud.threads.update(threadId, { is_archived: true });
115
123
  },
@@ -146,6 +154,7 @@ export const useCloudThreadListAdapter = (
146
154
  remoteId: thread.id,
147
155
  title: thread.title,
148
156
  externalId: thread.external_id ?? undefined,
157
+ custom: toCustom(thread.metadata),
149
158
  };
150
159
  },
151
160
 
@@ -38,6 +38,7 @@ export type ThreadListItemRuntime = {
38
38
 
39
39
  switchTo(options?: { unarchive?: boolean }): Promise<void>;
40
40
  rename(newTitle: string): Promise<void>;
41
+ updateCustom(custom: Record<string, unknown> | undefined): Promise<void>;
41
42
  archive(): Promise<void>;
42
43
  unarchive(): Promise<void>;
43
44
  delete(): Promise<void>;
@@ -74,6 +75,7 @@ export class ThreadListItemRuntimeImpl implements ThreadListItemRuntime {
74
75
  protected __internal_bindMethods() {
75
76
  this.switchTo = this.switchTo.bind(this);
76
77
  this.rename = this.rename.bind(this);
78
+ this.updateCustom = this.updateCustom.bind(this);
77
79
  this.archive = this.archive.bind(this);
78
80
  this.unarchive = this.unarchive.bind(this);
79
81
  this.delete = this.delete.bind(this);
@@ -100,6 +102,19 @@ export class ThreadListItemRuntimeImpl implements ThreadListItemRuntime {
100
102
  return this._threadListBinding.rename(state.id, newTitle);
101
103
  }
102
104
 
105
+ public updateCustom(
106
+ custom: Record<string, unknown> | undefined,
107
+ ): Promise<void> {
108
+ const state = this._core.getState();
109
+ if (!this._threadListBinding.updateCustom) {
110
+ throw new Error(
111
+ "Thread list runtime does not support updating custom metadata",
112
+ );
113
+ }
114
+
115
+ return this._threadListBinding.updateCustom(state.id, custom);
116
+ }
117
+
103
118
  public archive(): Promise<void> {
104
119
  const state = this._core.getState();
105
120
 
@@ -44,6 +44,10 @@ export type ThreadListRuntimeCore = {
44
44
 
45
45
  detach(threadId: string): Promise<void>;
46
46
  rename(threadId: string, newTitle: string): Promise<void>;
47
+ updateCustom?(
48
+ threadId: string,
49
+ custom: Record<string, unknown> | undefined,
50
+ ): Promise<void>;
47
51
  archive(threadId: string): Promise<void>;
48
52
  unarchive(threadId: string): Promise<void>;
49
53
  delete(threadId: string): Promise<void>;
@@ -24,6 +24,7 @@ export type ExternalStoreThreadData<TState extends "regular" | "archived"> = {
24
24
  remoteId?: string | undefined;
25
25
  externalId?: string | undefined;
26
26
  title?: string | undefined;
27
+ custom?: Record<string, unknown> | undefined;
27
28
  };
28
29
 
29
30
  export type ExternalStoreThreadListAdapter = {
@@ -46,6 +47,12 @@ export type ExternalStoreThreadListAdapter = {
46
47
  threadId: string,
47
48
  newTitle: string,
48
49
  ) => (Promise<void> | void) | undefined;
50
+ onUpdateCustom?:
51
+ | ((
52
+ threadId: string,
53
+ custom: Record<string, unknown> | undefined,
54
+ ) => Promise<void> | void)
55
+ | undefined;
49
56
  onArchive?: ((threadId: string) => Promise<void> | void) | undefined;
50
57
  onUnarchive?: ((threadId: string) => Promise<void> | void) | undefined;
51
58
  onDelete?: ((threadId: string) => Promise<void> | void) | undefined;
@@ -197,6 +197,19 @@ export class ExternalStoreThreadListRuntimeCore implements ThreadListRuntimeCore
197
197
  await onRename(threadId, newTitle);
198
198
  }
199
199
 
200
+ public async updateCustom(
201
+ threadId: string,
202
+ custom: Record<string, unknown> | undefined,
203
+ ): Promise<void> {
204
+ const onUpdateCustom = this.adapter.onUpdateCustom;
205
+ if (!onUpdateCustom)
206
+ throw new Error(
207
+ "External store adapter does not support updating custom metadata",
208
+ );
209
+
210
+ await onUpdateCustom(threadId, custom);
211
+ }
212
+
200
213
  public async detach(): Promise<void> {
201
214
  // no-op
202
215
  }
@@ -17,6 +17,10 @@ export class InMemoryThreadListAdapter implements RemoteThreadListAdapter {
17
17
  return Promise.resolve();
18
18
  }
19
19
 
20
+ updateCustom(): Promise<void> {
21
+ return Promise.resolve();
22
+ }
23
+
20
24
  archive(): Promise<void> {
21
25
  return Promise.resolve();
22
26
  }
@@ -29,6 +29,10 @@ export type RemoteThreadListAdapter = {
29
29
  list(params?: RemoteThreadListPageOptions): Promise<RemoteThreadListResponse>;
30
30
 
31
31
  rename(remoteId: string, newTitle: string): Promise<void>;
32
+ updateCustom?(
33
+ remoteId: string,
34
+ custom: Record<string, unknown> | undefined,
35
+ ): Promise<void>;
32
36
  archive(remoteId: string): Promise<void>;
33
37
  unarchive(remoteId: string): Promise<void>;
34
38
  delete(remoteId: string): Promise<void>;
@@ -6,6 +6,7 @@ import type {
6
6
  ModelContext as ModelContextValue,
7
7
  ModelContextProvider,
8
8
  } from "../../model-context/types";
9
+ import { mergeModelContexts } from "../../model-context/types";
9
10
 
10
11
  const tick = () => new Promise<void>((resolve) => setTimeout(resolve, 0));
11
12
 
@@ -13,7 +14,7 @@ const provider = (ctx: ModelContextValue): ModelContextProvider => ({
13
14
  getModelContext: () => ctx,
14
15
  });
15
16
 
16
- const stubTool = (): Tool<any, any> =>
17
+ const toolFixture = (): Tool<any, any> =>
17
18
  ({ description: "", parameters: {} as any }) as unknown as Tool<any, any>;
18
19
 
19
20
  const render = () => {
@@ -51,7 +52,9 @@ describe("ModelContext", () => {
51
52
  try {
52
53
  sub
53
54
  .getValue()
54
- .register(provider({ tools: { foo: stubTool(), bar: stubTool() } }));
55
+ .register(
56
+ provider({ tools: { foo: toolFixture(), bar: toolFixture() } }),
57
+ );
55
58
  await tick();
56
59
 
57
60
  expect(sub.getValue().getState().toolNames).toEqual(["bar", "foo"]);
@@ -106,3 +109,85 @@ describe("ModelContext", () => {
106
109
  }
107
110
  });
108
111
  });
112
+
113
+ describe("mergeModelContexts", () => {
114
+ it("merges a higher-priority tool override into an existing tool", () => {
115
+ const execute = async () => ({ ok: true });
116
+ const merged = mergeModelContexts(
117
+ new Set([
118
+ provider({
119
+ priority: 0,
120
+ tools: {
121
+ add_task: {
122
+ type: "frontend",
123
+ description: "Add a task",
124
+ parameters: { type: "object", properties: {} } as any,
125
+ renderText: { running: "Adding task" },
126
+ } as Tool<any, any>,
127
+ },
128
+ }),
129
+ provider({
130
+ priority: 1000,
131
+ tools: {
132
+ add_task: {
133
+ execute,
134
+ } as unknown as Tool<any, any>,
135
+ },
136
+ }),
137
+ ]),
138
+ );
139
+
140
+ expect(merged.tools?.add_task).toMatchObject({
141
+ type: "frontend",
142
+ description: "Add a task",
143
+ });
144
+ expect(merged.tools?.add_task?.execute).toBe(execute);
145
+ expect(merged.tools?.add_task?.parameters).toEqual({
146
+ type: "object",
147
+ properties: {},
148
+ });
149
+ });
150
+
151
+ it("still rejects duplicate tools at the same priority", () => {
152
+ expect(() =>
153
+ mergeModelContexts(
154
+ new Set([
155
+ provider({ tools: { duplicate: toolFixture() } }),
156
+ provider({ tools: { duplicate: toolFixture() } }),
157
+ ]),
158
+ ),
159
+ ).toThrow(/already exists/);
160
+ });
161
+
162
+ it("preserves the highest priority when a lower-priority provider reuses the same tool object", () => {
163
+ const shared = {
164
+ ...toolFixture(),
165
+ description: "high priority",
166
+ } as Tool<any, any>;
167
+ const execute = async () => ({ ok: true });
168
+ const merged = mergeModelContexts(
169
+ new Set([
170
+ provider({
171
+ priority: 1000,
172
+ tools: { shared },
173
+ }),
174
+ provider({
175
+ priority: 0,
176
+ tools: { shared },
177
+ }),
178
+ provider({
179
+ priority: 500,
180
+ tools: {
181
+ shared: {
182
+ description: "medium priority",
183
+ execute,
184
+ } as unknown as Tool<any, any>,
185
+ },
186
+ }),
187
+ ]),
188
+ );
189
+
190
+ expect(merged.tools?.shared?.description).toBe("high priority");
191
+ expect(merged.tools?.shared?.execute).toBe(execute);
192
+ });
193
+ });
@@ -44,6 +44,7 @@ export const ThreadListItemClient = resource(
44
44
  getState: () => state,
45
45
  switchTo: runtime.switchTo,
46
46
  rename: runtime.rename,
47
+ updateCustom: runtime.updateCustom,
47
48
  archive: runtime.archive,
48
49
  unarchive: runtime.unarchive,
49
50
  delete: runtime.delete,
@@ -14,6 +14,7 @@ export type ThreadListItemMethods = {
14
14
  getState(): ThreadListItemState;
15
15
  switchTo(options?: { unarchive?: boolean }): void;
16
16
  rename(newTitle: string): void;
17
+ updateCustom(custom: Record<string, unknown> | undefined): void;
17
18
  archive(): void;
18
19
  unarchive(): void;
19
20
  delete(): void;
@@ -1,5 +1,9 @@
1
1
  import { describe, it, expect, vi } from "vitest";
2
- import { createCore, makeAdapter } from "./remote-thread-list-test-helpers";
2
+ import {
3
+ createCore,
4
+ deferred,
5
+ makeAdapter,
6
+ } from "./remote-thread-list-test-helpers";
3
7
 
4
8
  describe("RemoteThreadListThreadListRuntimeCore custom metadata", () => {
5
9
  it("preserves custom field from list() through to threadItems", async () => {
@@ -120,4 +124,68 @@ describe("RemoteThreadListThreadListRuntimeCore custom metadata", () => {
120
124
  workspaceId: "ws-1",
121
125
  });
122
126
  });
127
+
128
+ it("updates custom through the adapter with optimistic state", async () => {
129
+ const updateDeferred = deferred<void>();
130
+ const adapter = makeAdapter({
131
+ list: vi.fn(async () => ({
132
+ threads: [
133
+ {
134
+ status: "regular" as const,
135
+ remoteId: "thread-6",
136
+ externalId: "ext-6",
137
+ title: "Test",
138
+ custom: { tag: "old" },
139
+ },
140
+ ],
141
+ })),
142
+ updateCustom: vi.fn(() => updateDeferred.promise),
143
+ });
144
+
145
+ const core = createCore(adapter);
146
+ await core.getLoadThreadsPromise();
147
+
148
+ const updateTask = core.updateCustom("thread-6", { tag: "new" });
149
+
150
+ await Promise.resolve();
151
+
152
+ expect(adapter.updateCustom).toHaveBeenCalledWith("thread-6", {
153
+ tag: "new",
154
+ });
155
+ expect(core.getItemById("thread-6")?.custom).toEqual({ tag: "new" });
156
+
157
+ updateDeferred.resolve();
158
+ await updateTask;
159
+
160
+ expect(core.getItemById("thread-6")?.custom).toEqual({ tag: "new" });
161
+ });
162
+
163
+ it("rolls back custom when adapter update fails", async () => {
164
+ const updateDeferred = deferred<void>();
165
+ const adapter = makeAdapter({
166
+ list: vi.fn(async () => ({
167
+ threads: [
168
+ {
169
+ status: "regular" as const,
170
+ remoteId: "thread-7",
171
+ externalId: "ext-7",
172
+ title: "Test",
173
+ custom: { tag: "old" },
174
+ },
175
+ ],
176
+ })),
177
+ updateCustom: vi.fn(() => updateDeferred.promise),
178
+ });
179
+
180
+ const core = createCore(adapter);
181
+ await core.getLoadThreadsPromise();
182
+
183
+ const updateTask = core.updateCustom("thread-7", { tag: "new" });
184
+ expect(core.getItemById("thread-7")?.custom).toEqual({ tag: "new" });
185
+
186
+ updateDeferred.reject(new Error("update failed"));
187
+ await expect(updateTask).rejects.toThrow("update failed");
188
+
189
+ expect(core.getItemById("thread-7")?.custom).toEqual({ tag: "old" });
190
+ });
123
191
  });
@@ -41,6 +41,7 @@ const createMockCore = (
41
41
  getLoadThreadsPromise: () => loadPromise,
42
42
  detach: () => Promise.resolve(),
43
43
  rename: () => Promise.resolve(),
44
+ updateCustom: () => Promise.resolve(),
44
45
  archive: () => Promise.resolve(),
45
46
  unarchive: () => Promise.resolve(),
46
47
  delete: () => Promise.resolve(),