om-memory-system 5.5.0 → 5.6.1

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 (76) hide show
  1. package/README.md +1 -1
  2. package/dist/adapters/pi/extension.js +5 -0
  3. package/dist/cli/space-command.d.ts +6 -5
  4. package/dist/cli/space-command.js +154 -13
  5. package/dist/cli/space-transfer-command.d.ts +25 -0
  6. package/dist/cli/space-transfer-command.js +79 -0
  7. package/dist/core/memory-operations.d.ts +12 -2
  8. package/dist/core/memory-operations.js +14 -4
  9. package/dist/core/recall-summary.js +7 -5
  10. package/dist/core/retrieval.js +5 -2
  11. package/dist/core/space-tool.d.ts +9 -4
  12. package/dist/core/space-tool.js +35 -3
  13. package/dist/services/active-space-access.d.ts +6 -0
  14. package/dist/services/active-space-access.js +8 -0
  15. package/dist/services/chat/chat-runtime.js +1 -1
  16. package/dist/services/client.d.ts +6 -16
  17. package/dist/services/client.js +54 -62
  18. package/dist/services/context.d.ts +2 -0
  19. package/dist/services/context.js +12 -1
  20. package/dist/services/linked-search.d.ts +108 -0
  21. package/dist/services/linked-search.js +219 -0
  22. package/dist/services/space-routes.d.ts +2 -0
  23. package/dist/services/space-routes.js +4 -3
  24. package/dist/services/space-transfer-routes.d.ts +10 -0
  25. package/dist/services/space-transfer-routes.js +344 -0
  26. package/dist/services/spaces/active-space.js +14 -7
  27. package/dist/services/spaces/delete.d.ts +2 -0
  28. package/dist/services/spaces/delete.js +4 -0
  29. package/dist/services/spaces/export-space.d.ts +60 -0
  30. package/dist/services/spaces/export-space.js +367 -0
  31. package/dist/services/spaces/identifier-scrub.d.ts +26 -0
  32. package/dist/services/spaces/identifier-scrub.js +40 -0
  33. package/dist/services/spaces/import-space.d.ts +85 -0
  34. package/dist/services/spaces/import-space.js +349 -0
  35. package/dist/services/spaces/operations.d.ts +57 -5
  36. package/dist/services/spaces/operations.js +161 -5
  37. package/dist/services/spaces/read-store-cache.d.ts +13 -0
  38. package/dist/services/spaces/read-store-cache.js +34 -0
  39. package/dist/services/spaces/registry-store.d.ts +4 -0
  40. package/dist/services/spaces/registry-store.js +15 -1
  41. package/dist/services/spaces/registry.d.ts +32 -0
  42. package/dist/services/spaces/registry.js +81 -7
  43. package/dist/services/spaces/space-store.d.ts +50 -0
  44. package/dist/services/spaces/space-store.js +72 -0
  45. package/dist/services/spaces/transfer-service.d.ts +41 -0
  46. package/dist/services/spaces/transfer-service.js +408 -0
  47. package/dist/services/spaces/transfer-types.d.ts +163 -0
  48. package/dist/services/spaces/transfer-types.js +10 -0
  49. package/dist/services/spaces/transfer.d.ts +31 -0
  50. package/dist/services/spaces/transfer.js +276 -0
  51. package/dist/services/turso/connection-manager.d.ts +4 -2
  52. package/dist/services/turso/connection-manager.js +11 -5
  53. package/dist/services/turso/cross-process-write-lock.d.ts +1 -1
  54. package/dist/services/turso/cross-process-write-lock.js +5 -5
  55. package/dist/services/turso/operation-lock.d.ts +2 -2
  56. package/dist/services/turso/operation-lock.js +5 -5
  57. package/dist/services/turso/shard-manager.d.ts +8 -0
  58. package/dist/services/turso/shard-manager.js +23 -22
  59. package/dist/services/turso/vector-search.d.ts +6 -2
  60. package/dist/services/turso/vector-search.js +8 -4
  61. package/dist/services/user-profile/user-profile-manager.d.ts +5 -1
  62. package/dist/services/user-profile/user-profile-manager.js +13 -10
  63. package/dist/services/web-route-modules.d.ts +5 -1
  64. package/dist/services/web-route-modules.js +4 -0
  65. package/dist/services/web-server.js +1 -1
  66. package/dist/shared/api/space-export-schemas.d.ts +159 -0
  67. package/dist/shared/api/space-export-schemas.js +72 -0
  68. package/dist/v2/adapter.d.ts +15 -0
  69. package/dist/v2/adapter.js +5 -0
  70. package/dist/web/assets/index-2BNRLGqe.css +2 -0
  71. package/dist/web/assets/index-C6WnDE6h.js +170 -0
  72. package/dist/web/index.html +2 -2
  73. package/package.json +1 -1
  74. package/skills/omms-memory/SKILL.md +16 -14
  75. package/dist/web/assets/index-Dcvz3EXt.js +0 -170
  76. package/dist/web/assets/index-b8k5Tuei.css +0 -2
@@ -30,3 +30,7 @@ export declare const unarchiveStoredSpace: (files: SpaceFiles, idOrName: string)
30
30
  export declare const switchStoredSpace: (files: SpaceFiles, idOrName: string) => Promise<SpaceRegistry>;
31
31
  export declare const removeStoredSpace: (files: SpaceFiles, idOrName: string) => Promise<SpaceRegistry>;
32
32
  export declare function renameStoredSpace(files: SpaceFiles, idOrName: string, name: string): Promise<SpaceRegistry>;
33
+ /** Adds a link between two stored spaces under the lock (design D5). */
34
+ export declare function linkStoredSpace(files: SpaceFiles, idOrName: string, targetIdOrName: string): Promise<SpaceRegistry>;
35
+ /** Removes a link between two stored spaces under the lock (design D5). */
36
+ export declare function unlinkStoredSpace(files: SpaceFiles, idOrName: string, targetIdOrName: string): Promise<SpaceRegistry>;
@@ -1,6 +1,6 @@
1
1
  import { existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
- import { SpaceError, archiveSpace, createSpace, readRegistryFile, removeSpace, renameSpace, switchSpace, unarchiveSpace, } from "./registry.js";
3
+ import { SpaceError, archiveSpace, createSpace, linkSpace, readRegistryFile, removeSpace, renameSpace, switchSpace, unarchiveSpace, unlinkSpace, } from "./registry.js";
4
4
  /**
5
5
  * The one write path for `spaces.json` (design D5). The web server, the CLI and the
6
6
  * `memory` tool all change the registry through `updateRegistry`. Readers never lock.
@@ -132,3 +132,17 @@ export async function renameStoredSpace(files, idOrName, name) {
132
132
  result: 0,
133
133
  }))).registry;
134
134
  }
135
+ /** Adds a link between two stored spaces under the lock (design D5). */
136
+ export async function linkStoredSpace(files, idOrName, targetIdOrName) {
137
+ return (await updateRegistry(files, (registry) => ({
138
+ registry: linkSpace(registry, idOrName, targetIdOrName),
139
+ result: 0,
140
+ }))).registry;
141
+ }
142
+ /** Removes a link between two stored spaces under the lock (design D5). */
143
+ export async function unlinkStoredSpace(files, idOrName, targetIdOrName) {
144
+ return (await updateRegistry(files, (registry) => ({
145
+ registry: unlinkSpace(registry, idOrName, targetIdOrName),
146
+ result: 0,
147
+ }))).registry;
148
+ }
@@ -17,10 +17,14 @@ export interface SpaceEntry {
17
17
  archived: boolean;
18
18
  /** ISO 8601 time of the archive. Absent for a space archived before OMMS recorded it. */
19
19
  archivedAt?: string;
20
+ /** Ids of linked spaces (design D5). A link is one-way and read-only. */
21
+ links?: string[];
20
22
  }
21
23
  export interface SpaceRegistry {
22
24
  version: number;
23
25
  activeSpaceId: string;
26
+ /** Custom display name of the Default space. Absent means "Default". */
27
+ defaultName?: string;
24
28
  /** User-created spaces only. Default is added by `listSpaces`. */
25
29
  spaces: SpaceEntry[];
26
30
  }
@@ -56,6 +60,34 @@ export declare function unarchiveSpace(registry: SpaceRegistry, idOrName: string
56
60
  export declare function switchSpace(registry: SpaceRegistry, idOrName: string): SpaceRegistry;
57
61
  /** Removes an entry. The caller checks backup and folder removal (D8). */
58
62
  export declare function removeSpace(registry: SpaceRegistry, idOrName: string): SpaceRegistry;
63
+ /**
64
+ * Adds a one-way link from one space to another (design D5). The linked space must
65
+ * exist, must not be the linking space itself and must not repeat. The link is
66
+ * stored on the linking space only, and the linked space's own links are not
67
+ * copied: the registry holds one level, and search follows no further.
68
+ *
69
+ * The Default space holds no links because it has no entry in `spaces.json`.
70
+ */
71
+ export declare function linkSpace(registry: SpaceRegistry, idOrName: string, targetIdOrName: string): SpaceRegistry;
72
+ /**
73
+ * Removes a link. The linked space may be gone from the registry, so its id is
74
+ * matched by id or name when it still exists and as a raw id otherwise. Removing
75
+ * a link deletes no memory and leaves every other link alone.
76
+ */
77
+ export declare function unlinkSpace(registry: SpaceRegistry, idOrName: string, targetIdOrName: string): SpaceRegistry;
78
+ export interface SpaceLinkInfo {
79
+ id: string;
80
+ /** The display name, or the id when the linked space is gone from the registry. */
81
+ name: string;
82
+ /** False when the linked space was deleted or archived. The link itself stays. */
83
+ available: boolean;
84
+ }
85
+ /**
86
+ * The links of a space with their availability, for the read paths (web layer, CLI
87
+ * listing). A link to a deleted or archived space stays in the registry and reads
88
+ * as unavailable here; search-time code skips it with a warning.
89
+ */
90
+ export declare function spaceLinks(registry: SpaceRegistry, idOrName: string): SpaceLinkInfo[];
59
91
  /** The folder of a space. Refuses an id that is not safe, so a path cannot leave the spaces root. */
60
92
  export declare function resolveSpaceFolder(id: string, paths: SpacePaths): string;
61
93
  export interface RegistryReadResult {
@@ -24,12 +24,17 @@ export class SpaceError extends Error {
24
24
  export function emptyRegistry() {
25
25
  return { version: REGISTRY_VERSION, activeSpaceId: DEFAULT_SPACE_ID, spaces: [] };
26
26
  }
27
- function defaultEntry() {
28
- return { id: DEFAULT_SPACE_ID, name: DEFAULT_SPACE_NAME, createdAt: "", archived: false };
27
+ function defaultEntry(registry) {
28
+ return {
29
+ id: DEFAULT_SPACE_ID,
30
+ name: registry.defaultName ?? DEFAULT_SPACE_NAME,
31
+ createdAt: "",
32
+ archived: false,
33
+ };
29
34
  }
30
35
  /** Every space in display order: Default first, then user spaces in creation order. */
31
36
  export function listSpaces(registry) {
32
- return [defaultEntry(), ...registry.spaces];
37
+ return [defaultEntry(registry), ...registry.spaces];
33
38
  }
34
39
  /** Lowercase letters, digits and single hyphens, at most 40 characters. Empty when the name has none. */
35
40
  export function spaceIdFromName(name) {
@@ -103,14 +108,19 @@ function updateSpace(registry, id, change) {
103
108
  }
104
109
  export function renameSpace(registry, idOrName, name) {
105
110
  const space = requireSpace(registry, idOrName);
106
- if (space.id === DEFAULT_SPACE_ID) {
107
- throw new SpaceError("protected", "The Default space cannot be renamed.");
108
- }
109
111
  const display = checkedName(name);
110
112
  const clash = findByName(registry, display);
111
113
  if (clash && clash.id !== space.id) {
112
114
  throw new SpaceError("name-taken", `A space named "${clash.name}" already exists.`);
113
115
  }
116
+ if (space.id === DEFAULT_SPACE_ID) {
117
+ if (display.toLowerCase() === DEFAULT_SPACE_NAME.toLowerCase()) {
118
+ // "Default" means no custom name: the field is removed, not stored (design D2).
119
+ const { defaultName: _drop, ...rest } = registry;
120
+ return rest;
121
+ }
122
+ return { ...registry, defaultName: display };
123
+ }
114
124
  return updateSpace(registry, space.id, { name: display });
115
125
  }
116
126
  export function archiveSpace(registry, idOrName, now = new Date().toISOString()) {
@@ -148,6 +158,62 @@ export function removeSpace(registry, idOrName) {
148
158
  }
149
159
  return { ...registry, spaces: registry.spaces.filter((s) => s.id !== space.id) };
150
160
  }
161
+ /**
162
+ * Adds a one-way link from one space to another (design D5). The linked space must
163
+ * exist, must not be the linking space itself and must not repeat. The link is
164
+ * stored on the linking space only, and the linked space's own links are not
165
+ * copied: the registry holds one level, and search follows no further.
166
+ *
167
+ * The Default space holds no links because it has no entry in `spaces.json`.
168
+ */
169
+ export function linkSpace(registry, idOrName, targetIdOrName) {
170
+ const space = requireSpace(registry, idOrName);
171
+ if (space.id === DEFAULT_SPACE_ID) {
172
+ throw new SpaceError("protected", "The Default space cannot link other spaces.");
173
+ }
174
+ const target = requireSpace(registry, targetIdOrName);
175
+ if (target.id === space.id) {
176
+ // Code "protected" follows the "cannot do this to itself/Default" refusals.
177
+ throw new SpaceError("protected", `"${space.name}" cannot link to itself.`);
178
+ }
179
+ const links = space.links ?? [];
180
+ if (links.includes(target.id)) {
181
+ // Code "name-taken" is the duplicate refusal; a repeated link is the same conflict.
182
+ throw new SpaceError("name-taken", `"${space.name}" already links "${target.name}".`);
183
+ }
184
+ return updateSpace(registry, space.id, { links: [...links, target.id] });
185
+ }
186
+ /**
187
+ * Removes a link. The linked space may be gone from the registry, so its id is
188
+ * matched by id or name when it still exists and as a raw id otherwise. Removing
189
+ * a link deletes no memory and leaves every other link alone.
190
+ */
191
+ export function unlinkSpace(registry, idOrName, targetIdOrName) {
192
+ const space = requireSpace(registry, idOrName);
193
+ if (space.id === DEFAULT_SPACE_ID) {
194
+ throw new SpaceError("protected", "The Default space cannot link other spaces.");
195
+ }
196
+ const target = findSpace(registry, targetIdOrName);
197
+ const linkedId = target ? target.id : targetIdOrName.trim();
198
+ const links = space.links ?? [];
199
+ if (!links.includes(linkedId)) {
200
+ throw new SpaceError("unknown", `"${space.name}" does not link "${targetIdOrName}".`);
201
+ }
202
+ const rest = links.filter((id) => id !== linkedId);
203
+ return updateSpace(registry, space.id, { links: rest.length > 0 ? rest : undefined });
204
+ }
205
+ /**
206
+ * The links of a space with their availability, for the read paths (web layer, CLI
207
+ * listing). A link to a deleted or archived space stays in the registry and reads
208
+ * as unavailable here; search-time code skips it with a warning.
209
+ */
210
+ export function spaceLinks(registry, idOrName) {
211
+ const space = requireSpace(registry, idOrName);
212
+ return (space.links ?? []).map((id) => {
213
+ const target = findSpace(registry, id);
214
+ return { id, name: target?.name ?? id, available: target !== undefined && !target.archived };
215
+ });
216
+ }
151
217
  /** The folder of a space. Refuses an id that is not safe, so a path cannot leave the spaces root. */
152
218
  export function resolveSpaceFolder(id, paths) {
153
219
  if (id === DEFAULT_SPACE_ID)
@@ -162,6 +228,9 @@ export function resolveSpaceFolder(id, paths) {
162
228
  }
163
229
  return join(paths.spacesRoot, id);
164
230
  }
231
+ function isLinkIdList(value) {
232
+ return Array.isArray(value) && value.every((id) => typeof id === "string");
233
+ }
165
234
  function parseEntry(raw) {
166
235
  if (typeof raw !== "object" || raw === null)
167
236
  return undefined;
@@ -173,7 +242,8 @@ function parseEntry(raw) {
173
242
  entry.name.trim() === "" ||
174
243
  typeof entry.createdAt !== "string" ||
175
244
  typeof entry.archived !== "boolean" ||
176
- (entry.archivedAt !== undefined && typeof entry.archivedAt !== "string")) {
245
+ (entry.archivedAt !== undefined && typeof entry.archivedAt !== "string") ||
246
+ (entry.links !== undefined && !isLinkIdList(entry.links))) {
177
247
  return undefined;
178
248
  }
179
249
  return {
@@ -182,6 +252,7 @@ function parseEntry(raw) {
182
252
  createdAt: entry.createdAt,
183
253
  archived: entry.archived,
184
254
  ...(typeof entry.archivedAt === "string" ? { archivedAt: entry.archivedAt } : {}),
255
+ ...(isLinkIdList(entry.links) ? { links: entry.links } : {}),
185
256
  };
186
257
  }
187
258
  /**
@@ -219,6 +290,9 @@ export function readRegistryFile(path) {
219
290
  version: typeof file.version === "number" ? file.version : REGISTRY_VERSION,
220
291
  activeSpaceId: file.activeSpaceId,
221
292
  spaces,
293
+ ...(typeof file.defaultName === "string" && file.defaultName.trim() !== ""
294
+ ? { defaultName: file.defaultName }
295
+ : {}),
222
296
  };
223
297
  if (!listSpaces(registry).some((space) => space.id === registry.activeSpaceId)) {
224
298
  return unusable(`active space "${registry.activeSpaceId}" is not in the list`);
@@ -0,0 +1,50 @@
1
+ import { TursoConnectionManager } from "../turso/connection-manager.js";
2
+ import { TursoShardManager } from "../turso/shard-manager.js";
3
+ import type { ShardInfo } from "../turso/types.js";
4
+ import type { TursoDb } from "../turso/turso-db.js";
5
+ export type SpaceStoreMode = "read" | "write";
6
+ /** What both modes share: the folder, a private connection manager, and a close. */
7
+ export interface SpaceStoreBase {
8
+ /** The space folder this store is bound to (design D1). */
9
+ readonly folder: string;
10
+ /** This store's own connections, allowed only inside `folder`. Closed by `close`. */
11
+ readonly connections: TursoConnectionManager;
12
+ /** Closes every connection this store opened. Call once, when the operation ends. */
13
+ close(): Promise<void>;
14
+ }
15
+ /**
16
+ * Write store (design D2): transfer targets, import targets and move sources.
17
+ * It creates shards on demand and takes the write and migration locks of `folder`,
18
+ * so it excludes a host that has the same space active.
19
+ */
20
+ export interface SpaceWriteStore extends SpaceStoreBase {
21
+ readonly mode: "write";
22
+ /** Shard manager rooted at `folder`; its locks and migration check use the same root. */
23
+ readonly shards: TursoShardManager;
24
+ }
25
+ /**
26
+ * Read store (design D2): transfer copy sources, previews and linked searches.
27
+ * It opens only files that exist, sets `query_only`, creates no file, changes no
28
+ * schema and takes no lock. A missing metadata.db means an empty space.
29
+ */
30
+ export interface SpaceReadStore extends SpaceStoreBase {
31
+ readonly mode: "read";
32
+ /** False when the folder holds no metadata.db: the space has no memories. */
33
+ readonly hasMetadata: boolean;
34
+ /**
35
+ * The registered shards of one scope. An empty `scopeHash` lists every hash of
36
+ * the scope, like `TursoShardManager.getAllShards`.
37
+ */
38
+ listShards(scope: "user" | "project", scopeHash: string): Promise<ShardInfo[]>;
39
+ /** Opens one shard database with `query_only` set. Refuses a file that is missing. */
40
+ openShard(dbPath: string): Promise<TursoDb>;
41
+ }
42
+ export type SpaceStore = SpaceWriteStore | SpaceReadStore;
43
+ /**
44
+ * Opens a store bound to one space folder (design D1 and D2). The store shares no
45
+ * state with the active space: it brings its own connections, shard manager and
46
+ * locks, all rooted at `folder`. Write stores live for one operation and are closed
47
+ * in `finally`; read stores of linked spaces are cached (see read-store-cache.ts).
48
+ */
49
+ export declare function openSpaceStore(folder: string, mode: "write"): SpaceWriteStore;
50
+ export declare function openSpaceStore(folder: string, mode: "read"): SpaceReadStore;
@@ -0,0 +1,72 @@
1
+ import { createClient } from "@libsql/client";
2
+ import { existsSync } from "node:fs";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { TursoConnectionManager } from "../turso/connection-manager.js";
5
+ import { TursoShardManager } from "../turso/shard-manager.js";
6
+ const METADATA_DB_NAME = "metadata.db";
7
+ /** Read mode keeps a connection read-only, so pragmas match the host defaults plus this. */
8
+ const READ_ONLY_PRAGMAS = [
9
+ "PRAGMA busy_timeout = 5000",
10
+ "PRAGMA foreign_keys = ON",
11
+ "PRAGMA query_only = ON",
12
+ ];
13
+ /** Maps one metadata.db `shards` row onto a ShardInfo whose path is resolved at `folder`. */
14
+ function rowToShardInfo(folder, row) {
15
+ const scope = String(row.scope);
16
+ return {
17
+ id: Number(row.id),
18
+ scope,
19
+ scopeHash: String(row.scope_hash),
20
+ shardIndex: Number(row.shard_index),
21
+ dbPath: resolve(join(folder, `${scope}s`, basename(String(row.db_path)))),
22
+ vectorCount: Number(row.vector_count),
23
+ isActive: Number(row.is_active) === 1,
24
+ createdAt: Number(row.created_at),
25
+ };
26
+ }
27
+ export function openSpaceStore(folder, mode) {
28
+ const root = resolve(folder);
29
+ const connections = new TursoConnectionManager(createClient, () => [root]);
30
+ if (mode === "write") {
31
+ const shards = new TursoShardManager({
32
+ root: () => root,
33
+ connections,
34
+ });
35
+ return {
36
+ mode,
37
+ folder: root,
38
+ connections,
39
+ shards,
40
+ close: () => connections.closeAll(),
41
+ };
42
+ }
43
+ // Read mode never calls the shard manager: its initialisation writes schema.
44
+ const hasMetadata = existsSync(join(root, METADATA_DB_NAME));
45
+ const openReadExisting = async (dbPath) => {
46
+ const db = await connections.getConnection(dbPath);
47
+ await db.setConnectionPragmas(READ_ONLY_PRAGMAS);
48
+ return db;
49
+ };
50
+ return {
51
+ mode,
52
+ folder: root,
53
+ connections,
54
+ hasMetadata,
55
+ listShards: async (scope, scopeHash) => {
56
+ if (!hasMetadata)
57
+ return [];
58
+ const db = await openReadExisting(join(root, METADATA_DB_NAME));
59
+ const rows = scopeHash === ""
60
+ ? await db.all(`SELECT * FROM shards WHERE scope = ? ORDER BY shard_index ASC`, [scope])
61
+ : await db.all(`SELECT * FROM shards WHERE scope = ? AND scope_hash = ? ORDER BY shard_index ASC`, [scope, scopeHash]);
62
+ return rows.map((row) => rowToShardInfo(root, row));
63
+ },
64
+ openShard: async (dbPath) => {
65
+ if (!existsSync(dbPath)) {
66
+ throw new Error(`Space shard file is missing: ${dbPath}`);
67
+ }
68
+ return openReadExisting(resolve(dbPath));
69
+ },
70
+ close: () => connections.closeAll(),
71
+ };
72
+ }
@@ -0,0 +1,41 @@
1
+ import { type SpacePaths } from "./registry.js";
2
+ import type { SpaceFiles } from "./registry-store.js";
3
+ import type { EmbeddingInfo, TransferApplyResult, TransferFilter, TransferMode, TransferPreview } from "./transfer-types.js";
4
+ export type TransferRefusalCode = "unknown-space" | "same-space" | "archived-space" | "registry-problem";
5
+ export interface TransferRefusal {
6
+ ok: false;
7
+ code: TransferRefusalCode;
8
+ error: string;
9
+ }
10
+ export type SpaceTransferPreviewOutcome = TransferRefusal | {
11
+ ok: true;
12
+ preview: TransferPreview;
13
+ };
14
+ export type SpaceTransferApplyOutcome = TransferRefusal | {
15
+ ok: true;
16
+ result: TransferApplyResult;
17
+ };
18
+ export interface SpaceTransferPreviewRequest {
19
+ from: string;
20
+ to: string;
21
+ filter: TransferFilter;
22
+ }
23
+ export interface SpaceTransferApplyRequest extends SpaceTransferPreviewRequest {
24
+ mode: TransferMode;
25
+ previewMatched?: number;
26
+ }
27
+ export interface SpaceTransferContext {
28
+ files: SpaceFiles;
29
+ paths: SpacePaths;
30
+ embedding: EmbeddingInfo;
31
+ maxVectorsPerShard: number;
32
+ embed?: (text: string) => Promise<Float32Array>;
33
+ }
34
+ /** Previews a transfer without changing either space: read stores, no locks. */
35
+ export declare function previewSpaceTransfer(request: SpaceTransferPreviewRequest, context: SpaceTransferContext): Promise<SpaceTransferPreviewOutcome>;
36
+ /**
37
+ * Runs a copy or a move. The target opens in write mode; the source opens in
38
+ * write mode only for a move. Engine failures land in `result.error`; the call
39
+ * throws only on an unexpected store failure, after logging its name.
40
+ */
41
+ export declare function applySpaceTransfer(request: SpaceTransferApplyRequest, context: SpaceTransferContext): Promise<SpaceTransferApplyOutcome>;