dsh-mnemon-source-memory-spaces 0.5.17 → 0.5.19
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/lib/client.js +271 -141
- package/lib/contracts.d.ts +30 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.js +368 -3
- package/lib/types/client/api.d.ts +3 -1
- package/lib/types/contracts.d.ts +29 -0
- package/package.json +4 -4
- package/presentation/locales.json +22 -2
- package/presentation/page.module.css +7 -0
package/lib/contracts.d.ts
CHANGED
|
@@ -334,6 +334,35 @@ interface MemorySpaceCatalog {
|
|
|
334
334
|
generatedAt: string;
|
|
335
335
|
/** Present only when body-directory receives a supported writeScope request. Older Sources omit it. */
|
|
336
336
|
writeScope?: MemorySpaceWriteScope;
|
|
337
|
+
/** Provider namespaces asked for again in this process: whether a pass is running, and the last one. Older Sources omit it. */
|
|
338
|
+
rediscovery?: {
|
|
339
|
+
running: boolean;
|
|
340
|
+
last?: MemorySpaceRediscovery;
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
/** What one Provider answered when its namespaces were asked for again. */
|
|
344
|
+
interface MemorySpaceRediscoveryResult {
|
|
345
|
+
providerId: MemoryProviderId;
|
|
346
|
+
label: string;
|
|
347
|
+
/** Namespaces the Provider reported. */
|
|
348
|
+
found: number;
|
|
349
|
+
/** Spaces mounted for namespaces this directory had never held. They start inactive. */
|
|
350
|
+
added: Array<{
|
|
351
|
+
id: string;
|
|
352
|
+
name: string;
|
|
353
|
+
}>;
|
|
354
|
+
/** Reported namespaces a person disconnected here; they stay disconnected. */
|
|
355
|
+
disconnected: number;
|
|
356
|
+
/** Why the Provider could not be asked, as it said. Its spaces stay as they were. */
|
|
357
|
+
error?: string;
|
|
358
|
+
/** The Provider said nothing within the time it was given. */
|
|
359
|
+
timedOut?: boolean;
|
|
360
|
+
}
|
|
361
|
+
/** One pass over every enabled Provider service, when the Host starts or from the Memory Spaces page. */
|
|
362
|
+
interface MemorySpaceRediscovery {
|
|
363
|
+
at: string;
|
|
364
|
+
trigger: 'startup' | 'manual';
|
|
365
|
+
results: MemorySpaceRediscoveryResult[];
|
|
337
366
|
}
|
|
338
367
|
interface MemoryGraphNode extends Insight {
|
|
339
368
|
color: string;
|
|
@@ -574,4 +603,4 @@ type MemoryBodyView = MemorySpaceView;
|
|
|
574
603
|
/** @deprecated Use OpenVikingSpaceConnection. The wire shape is unchanged. */
|
|
575
604
|
type OpenVikingBodyConnection = OpenVikingSpaceConnection;
|
|
576
605
|
//#endregion
|
|
577
|
-
export { AutomaticMemoryPlacementRequest, CATEGORIES, Category, CreateMemoryBodyRequest, CreateMemorySpaceRequest, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, EMBEDDING_PROTOCOL_AUTO, EMBEDDING_PROTOCOL_OLLAMA, EMBEDDING_PROTOCOL_OPENAI, EdgeType, EntityMemoriesView, EntityRelatedView, EntityView, INTENTS, Insight, Intent, type JsonValue, LlmMemoryPlacementSelection, MNEMON_EMBEDDING_PROTOCOLS, MemoryBody, MemoryBodyCatalog, MemoryBodyMetadataMaintenanceResult, MemoryBodyMetadataSample, MemoryBodyMetadataUpdate, MemoryBodyProvider, MemoryBodyStats, MemoryBodyView, MemoryGraphEdge, MemoryGraphNode, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryPersistenceStrategy, MemoryPlacementCandidate, MemoryPlacementCapability, MemoryPlacementDecision, MemoryPlacementPreference, MemoryPlacementRules, MemoryProviderCapabilities, MemoryProviderConfigField, MemoryProviderConfigOption, MemoryProviderConnection, MemoryProviderConnectionValue, MemoryProviderDescriptor, MemoryProviderIcon, MemoryProviderId, MemoryProviderRuntimeStatus, MemoryProviderServiceCatalog, MemoryProviderServiceView, MemoryReadMode, MemoryReadSource, MemoryReadStatus, MemorySpace, MemorySpaceCatalog, MemorySpaceMetadataMaintenanceResult, MemorySpaceMetadataSample, MemorySpaceMetadataUpdate, MemorySpaceProvider, MemorySpaceStats, MemorySpaceView, MemorySpaceWriteScope, MemorySpaceWriteScopeRequest, MemorySpacesStatus, MnemonEmbeddingConfig, MnemonEmbeddingProtocol, MnemonEmbeddingStatus, OpenVikingBodyConnection, OpenVikingSpaceConnection, PreparedMemoryPlacement, RecallQualityConfig, RecallQualityStats, RecallRelevanceTier, RememberRequest, ResolvedMemoryPersistenceStrategy, ResolvedMnemonEmbeddingConfig, ResolvedRecallQualityConfig, SOURCES, SearchRequest, Source, UpdateMemoryBodyRequest, UpdateMemoryProviderServiceRequest, UpdateMemorySpaceRequest, normalizeEntityKey };
|
|
606
|
+
export { AutomaticMemoryPlacementRequest, CATEGORIES, Category, CreateMemoryBodyRequest, CreateMemorySpaceRequest, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, EMBEDDING_PROTOCOL_AUTO, EMBEDDING_PROTOCOL_OLLAMA, EMBEDDING_PROTOCOL_OPENAI, EdgeType, EntityMemoriesView, EntityRelatedView, EntityView, INTENTS, Insight, Intent, type JsonValue, LlmMemoryPlacementSelection, MNEMON_EMBEDDING_PROTOCOLS, MemoryBody, MemoryBodyCatalog, MemoryBodyMetadataMaintenanceResult, MemoryBodyMetadataSample, MemoryBodyMetadataUpdate, MemoryBodyProvider, MemoryBodyStats, MemoryBodyView, MemoryGraphEdge, MemoryGraphNode, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryPersistenceStrategy, MemoryPlacementCandidate, MemoryPlacementCapability, MemoryPlacementDecision, MemoryPlacementPreference, MemoryPlacementRules, MemoryProviderCapabilities, MemoryProviderConfigField, MemoryProviderConfigOption, MemoryProviderConnection, MemoryProviderConnectionValue, MemoryProviderDescriptor, MemoryProviderIcon, MemoryProviderId, MemoryProviderRuntimeStatus, MemoryProviderServiceCatalog, MemoryProviderServiceView, MemoryReadMode, MemoryReadSource, MemoryReadStatus, MemorySpace, MemorySpaceCatalog, MemorySpaceMetadataMaintenanceResult, MemorySpaceMetadataSample, MemorySpaceMetadataUpdate, MemorySpaceProvider, MemorySpaceRediscovery, MemorySpaceRediscoveryResult, MemorySpaceStats, MemorySpaceView, MemorySpaceWriteScope, MemorySpaceWriteScopeRequest, MemorySpacesStatus, MnemonEmbeddingConfig, MnemonEmbeddingProtocol, MnemonEmbeddingStatus, OpenVikingBodyConnection, OpenVikingSpaceConnection, PreparedMemoryPlacement, RecallQualityConfig, RecallQualityStats, RecallRelevanceTier, RememberRequest, ResolvedMemoryPersistenceStrategy, ResolvedMnemonEmbeddingConfig, ResolvedRecallQualityConfig, SOURCES, SearchRequest, Source, UpdateMemoryBodyRequest, UpdateMemoryProviderServiceRequest, UpdateMemorySpaceRequest, normalizeEntityKey };
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AutomaticMemoryPlacementRequest, CATEGORIES, Category, CreateMemoryBodyRequest, CreateMemorySpaceRequest, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, EMBEDDING_PROTOCOL_AUTO, EMBEDDING_PROTOCOL_OLLAMA, EMBEDDING_PROTOCOL_OPENAI, EdgeType, EntityMemoriesView, EntityRelatedView, EntityView, INTENTS, Insight, Intent, JsonValue, LlmMemoryPlacementSelection, MNEMON_EMBEDDING_PROTOCOLS, MemoryBody, MemoryBodyCatalog, MemoryBodyMetadataMaintenanceResult, MemoryBodyMetadataSample, MemoryBodyMetadataUpdate, MemoryBodyProvider, MemoryBodyStats, MemoryBodyView, MemoryGraphEdge, MemoryGraphNode, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryPersistenceStrategy, MemoryPlacementCandidate, MemoryPlacementCapability, MemoryPlacementDecision, MemoryPlacementPreference, MemoryPlacementRules, MemoryProviderCapabilities, MemoryProviderConfigField, MemoryProviderConfigOption, MemoryProviderConnection, MemoryProviderConnectionValue, MemoryProviderDescriptor, MemoryProviderIcon, MemoryProviderId, MemoryProviderRuntimeStatus, MemoryProviderServiceCatalog, MemoryProviderServiceView, MemoryReadMode, MemoryReadSource, MemoryReadStatus, MemorySpace, MemorySpaceCatalog, MemorySpaceMetadataMaintenanceResult, MemorySpaceMetadataSample, MemorySpaceMetadataUpdate, MemorySpaceProvider, MemorySpaceStats, MemorySpaceView, MemorySpaceWriteScope, MemorySpaceWriteScopeRequest, MemorySpacesStatus, MnemonEmbeddingConfig, MnemonEmbeddingProtocol, MnemonEmbeddingStatus, OpenVikingBodyConnection, OpenVikingSpaceConnection, PreparedMemoryPlacement, RecallQualityConfig, RecallQualityStats, RecallRelevanceTier, RememberRequest, ResolvedMemoryPersistenceStrategy, ResolvedMnemonEmbeddingConfig, ResolvedRecallQualityConfig, SOURCES, SearchRequest, Source, UpdateMemoryBodyRequest, UpdateMemoryProviderServiceRequest, UpdateMemorySpaceRequest, normalizeEntityKey } from "./contracts.js";
|
|
1
|
+
import { AutomaticMemoryPlacementRequest, CATEGORIES, Category, CreateMemoryBodyRequest, CreateMemorySpaceRequest, DEFAULT_EMBEDDING_ENDPOINT, DEFAULT_EMBEDDING_MODEL, DEFAULT_EMBEDDING_PROTOCOL, EDGE_TYPES, EMBEDDING_PROTOCOL_AUTO, EMBEDDING_PROTOCOL_OLLAMA, EMBEDDING_PROTOCOL_OPENAI, EdgeType, EntityMemoriesView, EntityRelatedView, EntityView, INTENTS, Insight, Intent, JsonValue, LlmMemoryPlacementSelection, MNEMON_EMBEDDING_PROTOCOLS, MemoryBody, MemoryBodyCatalog, MemoryBodyMetadataMaintenanceResult, MemoryBodyMetadataSample, MemoryBodyMetadataUpdate, MemoryBodyProvider, MemoryBodyStats, MemoryBodyView, MemoryGraphEdge, MemoryGraphNode, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryPersistenceStrategy, MemoryPlacementCandidate, MemoryPlacementCapability, MemoryPlacementDecision, MemoryPlacementPreference, MemoryPlacementRules, MemoryProviderCapabilities, MemoryProviderConfigField, MemoryProviderConfigOption, MemoryProviderConnection, MemoryProviderConnectionValue, MemoryProviderDescriptor, MemoryProviderIcon, MemoryProviderId, MemoryProviderRuntimeStatus, MemoryProviderServiceCatalog, MemoryProviderServiceView, MemoryReadMode, MemoryReadSource, MemoryReadStatus, MemorySpace, MemorySpaceCatalog, MemorySpaceMetadataMaintenanceResult, MemorySpaceMetadataSample, MemorySpaceMetadataUpdate, MemorySpaceProvider, MemorySpaceRediscovery, MemorySpaceRediscoveryResult, MemorySpaceStats, MemorySpaceView, MemorySpaceWriteScope, MemorySpaceWriteScopeRequest, MemorySpacesStatus, MnemonEmbeddingConfig, MnemonEmbeddingProtocol, MnemonEmbeddingStatus, OpenVikingBodyConnection, OpenVikingSpaceConnection, PreparedMemoryPlacement, RecallQualityConfig, RecallQualityStats, RecallRelevanceTier, RememberRequest, ResolvedMemoryPersistenceStrategy, ResolvedMnemonEmbeddingConfig, ResolvedRecallQualityConfig, SOURCES, SearchRequest, Source, UpdateMemoryBodyRequest, UpdateMemoryProviderServiceRequest, UpdateMemorySpaceRequest, normalizeEntityKey } from "./contracts.js";
|
|
2
2
|
import { i as MemorySpaceProviderEntry } from "./definitions-CtjNSwBS.js";
|
|
3
3
|
import z from "@deepseek-ai/schemastery";
|
|
4
4
|
import { Context } from "@deepseek-ai/cordis";
|
|
@@ -59,4 +59,4 @@ declare function resolveMemorySpaceProviderEntries(ctx: Context, declarations: r
|
|
|
59
59
|
declare function installMemorySpaces(ctx: Context, entries: readonly MemorySpaceProviderEntry[], options?: InstallMemorySpacesOptions): Promise<void>;
|
|
60
60
|
declare function apply(ctx: Context, config?: Config): Promise<void>;
|
|
61
61
|
//#endregion
|
|
62
|
-
export { type AutomaticMemoryPlacementRequest, type CATEGORIES, type Category, Config, type CreateMemoryBodyRequest, type CreateMemorySpaceRequest, type DEFAULT_EMBEDDING_ENDPOINT, type DEFAULT_EMBEDDING_MODEL, type DEFAULT_EMBEDDING_PROTOCOL, type EDGE_TYPES, type EMBEDDING_PROTOCOL_AUTO, type EMBEDDING_PROTOCOL_OLLAMA, type EMBEDDING_PROTOCOL_OPENAI, type EdgeType, type EntityMemoriesView, type EntityRelatedView, type EntityView, type INTENTS, type Insight, InstallMemorySpacesOptions, type Intent, type JsonValue, type LlmMemoryPlacementSelection, type MNEMON_EMBEDDING_PROTOCOLS, type MemoryBody, type MemoryBodyCatalog, type MemoryBodyMetadataMaintenanceResult, type MemoryBodyMetadataSample, type MemoryBodyMetadataUpdate, type MemoryBodyProvider, type MemoryBodyStats, type MemoryBodyView, type MemoryGraphEdge, type MemoryGraphNode, type MemoryGraphSnapshot, type MemoryListRequest, type MemoryListView, type MemoryPersistenceStrategy, type MemoryPlacementCandidate, type MemoryPlacementCapability, type MemoryPlacementDecision, type MemoryPlacementPreference, type MemoryPlacementRules, type MemoryProviderCapabilities, type MemoryProviderConfigField, type MemoryProviderConfigOption, type MemoryProviderConnection, type MemoryProviderConnectionValue, type MemoryProviderDescriptor, type MemoryProviderIcon, type MemoryProviderId, type MemoryProviderRuntimeStatus, type MemoryProviderServiceCatalog, type MemoryProviderServiceView, type MemoryReadMode, type MemoryReadSource, type MemoryReadStatus, type MemorySpace, type MemorySpaceCatalog, type MemorySpaceMetadataMaintenanceResult, type MemorySpaceMetadataSample, type MemorySpaceMetadataUpdate, type MemorySpaceProvider, MemorySpaceProviderDeclaration, MemorySpaceProviderDeclarationSchema, type MemorySpaceStats, type MemorySpaceView, type MemorySpaceWriteScope, type MemorySpaceWriteScopeRequest, type MemorySpacesStatus, type MnemonEmbeddingConfig, type MnemonEmbeddingProtocol, type MnemonEmbeddingStatus, type OpenVikingBodyConnection, type OpenVikingSpaceConnection, type PreparedMemoryPlacement, type RecallQualityConfig, type RecallQualityStats, type RecallRelevanceTier, type RememberRequest, type ResolvedMemoryPersistenceStrategy, type ResolvedMnemonEmbeddingConfig, type ResolvedRecallQualityConfig, type SOURCES, type SearchRequest, type Source, type UpdateMemoryBodyRequest, type UpdateMemoryProviderServiceRequest, type UpdateMemorySpaceRequest, apply, inject, installMemorySpaces, memoryPlugin, name, type normalizeEntityKey, resolveEmbedding, resolveMemorySpaceProviderEntries, resolvePersistenceStrategy, resolveRecallQuality };
|
|
62
|
+
export { type AutomaticMemoryPlacementRequest, type CATEGORIES, type Category, Config, type CreateMemoryBodyRequest, type CreateMemorySpaceRequest, type DEFAULT_EMBEDDING_ENDPOINT, type DEFAULT_EMBEDDING_MODEL, type DEFAULT_EMBEDDING_PROTOCOL, type EDGE_TYPES, type EMBEDDING_PROTOCOL_AUTO, type EMBEDDING_PROTOCOL_OLLAMA, type EMBEDDING_PROTOCOL_OPENAI, type EdgeType, type EntityMemoriesView, type EntityRelatedView, type EntityView, type INTENTS, type Insight, InstallMemorySpacesOptions, type Intent, type JsonValue, type LlmMemoryPlacementSelection, type MNEMON_EMBEDDING_PROTOCOLS, type MemoryBody, type MemoryBodyCatalog, type MemoryBodyMetadataMaintenanceResult, type MemoryBodyMetadataSample, type MemoryBodyMetadataUpdate, type MemoryBodyProvider, type MemoryBodyStats, type MemoryBodyView, type MemoryGraphEdge, type MemoryGraphNode, type MemoryGraphSnapshot, type MemoryListRequest, type MemoryListView, type MemoryPersistenceStrategy, type MemoryPlacementCandidate, type MemoryPlacementCapability, type MemoryPlacementDecision, type MemoryPlacementPreference, type MemoryPlacementRules, type MemoryProviderCapabilities, type MemoryProviderConfigField, type MemoryProviderConfigOption, type MemoryProviderConnection, type MemoryProviderConnectionValue, type MemoryProviderDescriptor, type MemoryProviderIcon, type MemoryProviderId, type MemoryProviderRuntimeStatus, type MemoryProviderServiceCatalog, type MemoryProviderServiceView, type MemoryReadMode, type MemoryReadSource, type MemoryReadStatus, type MemorySpace, type MemorySpaceCatalog, type MemorySpaceMetadataMaintenanceResult, type MemorySpaceMetadataSample, type MemorySpaceMetadataUpdate, type MemorySpaceProvider, MemorySpaceProviderDeclaration, MemorySpaceProviderDeclarationSchema, type MemorySpaceRediscovery, type MemorySpaceRediscoveryResult, type MemorySpaceStats, type MemorySpaceView, type MemorySpaceWriteScope, type MemorySpaceWriteScopeRequest, type MemorySpacesStatus, type MnemonEmbeddingConfig, type MnemonEmbeddingProtocol, type MnemonEmbeddingStatus, type OpenVikingBodyConnection, type OpenVikingSpaceConnection, type PreparedMemoryPlacement, type RecallQualityConfig, type RecallQualityStats, type RecallRelevanceTier, type RememberRequest, type ResolvedMemoryPersistenceStrategy, type ResolvedMnemonEmbeddingConfig, type ResolvedRecallQualityConfig, type SOURCES, type SearchRequest, type Source, type UpdateMemoryBodyRequest, type UpdateMemoryProviderServiceRequest, type UpdateMemorySpaceRequest, apply, inject, installMemorySpaces, memoryPlugin, name, type normalizeEntityKey, resolveEmbedding, resolveMemorySpaceProviderEntries, resolvePersistenceStrategy, resolveRecallQuality };
|
package/lib/index.js
CHANGED
|
@@ -103,9 +103,40 @@ const NATIVE_REGISTRY_VERSION = 1;
|
|
|
103
103
|
const PROVIDER_REGISTRY_VERSION = 4;
|
|
104
104
|
const ID_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
105
105
|
const PROVIDER_ID_PATTERN = /^[a-z][a-z0-9-]{0,127}$/u;
|
|
106
|
+
const DISCONNECTS_VERSION = 1;
|
|
107
|
+
/** Settings whose value can name a namespace: a bank, workspace, user, tag, URI or folder. */
|
|
108
|
+
const IDENTITY_INPUTS = /* @__PURE__ */ new Set([
|
|
109
|
+
"text",
|
|
110
|
+
"url",
|
|
111
|
+
"path"
|
|
112
|
+
]);
|
|
106
113
|
function storedProviderId(value) {
|
|
107
114
|
return typeof value === "string" && PROVIDER_ID_PATTERN.test(value);
|
|
108
115
|
}
|
|
116
|
+
/** Disconnected namespaces as a file holds them: sound entries only, newest last. */
|
|
117
|
+
function storedDisconnects(value) {
|
|
118
|
+
if (!Array.isArray(value)) return [];
|
|
119
|
+
return value.flatMap((item) => {
|
|
120
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) return [];
|
|
121
|
+
const fields = item;
|
|
122
|
+
const externalId = typeof fields.externalId === "string" && fields.externalId.trim() !== "" && fields.externalId.trim().length <= 2e3 ? fields.externalId.trim() : void 0;
|
|
123
|
+
const connection = storedProviderConnection(fields.connection);
|
|
124
|
+
const entry = {
|
|
125
|
+
...externalId === void 0 ? {} : { externalId },
|
|
126
|
+
...Object.keys(connection).length === 0 ? {} : { connection }
|
|
127
|
+
};
|
|
128
|
+
return Object.keys(entry).length === 0 ? [] : [entry];
|
|
129
|
+
}).slice(-1e3);
|
|
130
|
+
}
|
|
131
|
+
/** JSON with every object's keys in order, so two equal connections compare equal. */
|
|
132
|
+
function canonicalJson(value) {
|
|
133
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
134
|
+
if (value !== null && typeof value === "object") {
|
|
135
|
+
const fields = value;
|
|
136
|
+
return `{${Object.keys(fields).filter((key) => fields[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(fields[key])}`).join(",")}}`;
|
|
137
|
+
}
|
|
138
|
+
return JSON.stringify(value) ?? "null";
|
|
139
|
+
}
|
|
109
140
|
function storedProviderConnection(value) {
|
|
110
141
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return {};
|
|
111
142
|
return Object.fromEntries(Object.entries(value).filter((entry) => {
|
|
@@ -216,6 +247,8 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
216
247
|
directory;
|
|
217
248
|
registryPath;
|
|
218
249
|
providerRegistryPath;
|
|
250
|
+
/** The namespaces a person disconnected, which asking a Provider again leaves out (#373). */
|
|
251
|
+
disconnectsPath;
|
|
219
252
|
refreshing = false;
|
|
220
253
|
state;
|
|
221
254
|
constructor(runner, persistent = true, now = () => /* @__PURE__ */ new Date(), providerCatalog = EMPTY_MEMORY_PROVIDER_CATALOG, sharedState) {
|
|
@@ -226,11 +259,13 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
226
259
|
this.state = sharedState ?? {
|
|
227
260
|
spaces: [],
|
|
228
261
|
services: {},
|
|
229
|
-
serviceEnabled: {}
|
|
262
|
+
serviceEnabled: {},
|
|
263
|
+
disconnected: {}
|
|
230
264
|
};
|
|
231
265
|
this.directory = join(runner.effectiveDataDir(), "data");
|
|
232
266
|
this.registryPath = join(this.directory, ".dsh-memory-bodies.json");
|
|
233
267
|
this.providerRegistryPath = join(runner.effectiveDataDir(), "state", "memory-providers.json");
|
|
268
|
+
this.disconnectsPath = join(runner.effectiveDataDir(), "state", "memory-provider-disconnects.json");
|
|
234
269
|
if (sharedState === void 0) this.reload();
|
|
235
270
|
}
|
|
236
271
|
get spaces() {
|
|
@@ -251,6 +286,12 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
251
286
|
set serviceEnabled(value) {
|
|
252
287
|
this.state.serviceEnabled = value;
|
|
253
288
|
}
|
|
289
|
+
get disconnected() {
|
|
290
|
+
return this.state.disconnected;
|
|
291
|
+
}
|
|
292
|
+
set disconnected(value) {
|
|
293
|
+
this.state.disconnected = value;
|
|
294
|
+
}
|
|
254
295
|
/** One generation-local descriptor view over the same persistent authority. */
|
|
255
296
|
withProviderCatalog(providerCatalog) {
|
|
256
297
|
return new MemorySpaceRegistry(this.runner, this.persistent, this.now, providerCatalog, this.state);
|
|
@@ -400,8 +441,181 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
400
441
|
this.serviceEnabled[providerId] = true;
|
|
401
442
|
this.spaces = [...this.spaces.filter((body) => body.providerId !== providerId), ...projections];
|
|
402
443
|
this.save();
|
|
444
|
+
this.forgetDisconnected(providerId, this.reportedNamespaces(providerId, normalizedService, discovered));
|
|
403
445
|
return this.providerServices().items.find((item) => item.providerId === providerId);
|
|
404
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Mount the namespaces a Provider reports that this directory has never held, as asking a
|
|
449
|
+
* Provider again finds them (#373). A space already mounted is left exactly as it is, and so is
|
|
450
|
+
* a namespace a person disconnected. A new space starts inactive: recall reads it only once a
|
|
451
|
+
* person turns it on. A space counts as a reported namespace when it has its externalId, or the
|
|
452
|
+
* settings that name it (see `holds`): a space made by hand for the same bank, or one whose
|
|
453
|
+
* externalId the Provider now writes differently. A Provider switched off, or saved with other
|
|
454
|
+
* settings since `service` was read, gets nothing: that save decides. Nothing is written when
|
|
455
|
+
* nothing is new.
|
|
456
|
+
*/
|
|
457
|
+
mountDiscovered(providerId, service, discovered) {
|
|
458
|
+
this.refreshIfChanged();
|
|
459
|
+
if (this.isNative(providerId)) throw new Error("Mnemon Native Stores are discovered from disk");
|
|
460
|
+
const current = this.services[providerId];
|
|
461
|
+
if (current === void 0 || !this.providerServiceEnabled(providerId) || canonicalJson(current) !== canonicalJson(this.providerCatalog.normalizeService(providerId, service))) return {
|
|
462
|
+
added: [],
|
|
463
|
+
disconnected: 0
|
|
464
|
+
};
|
|
465
|
+
const held = this.spaces.filter((body) => body.providerId === providerId).map((body) => ({
|
|
466
|
+
...body.externalId === void 0 ? {} : { externalId: body.externalId },
|
|
467
|
+
...body.connection === void 0 ? {} : { connection: body.connection }
|
|
468
|
+
}));
|
|
469
|
+
const disconnected = this.disconnected[providerId] ?? [];
|
|
470
|
+
const reservedIds = new Set(this.spaces.map((body) => body.id));
|
|
471
|
+
const timestamp = this.now().toISOString();
|
|
472
|
+
const added = [];
|
|
473
|
+
let stillDisconnected = 0;
|
|
474
|
+
for (const reported of this.reportedNamespaces(providerId, current, discovered)) {
|
|
475
|
+
if (held.some((body) => this.holds(providerId, current, body, reported)) || added.some((body) => body.externalId === reported.externalId)) continue;
|
|
476
|
+
if (disconnected.some((entry) => this.holds(providerId, current, entry, reported))) {
|
|
477
|
+
stillDisconnected += 1;
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
const { externalId, connection, candidate } = reported;
|
|
481
|
+
let id = validateMemorySpaceId(`${providerId}-${createHash("sha256").update(externalId).digest("hex").slice(0, 24)}`);
|
|
482
|
+
let suffix = 1;
|
|
483
|
+
while (reservedIds.has(id)) {
|
|
484
|
+
id = validateMemorySpaceId(`${providerId}-${createHash("sha256").update(`${externalId}:${suffix}`).digest("hex").slice(0, 24)}`);
|
|
485
|
+
suffix += 1;
|
|
486
|
+
}
|
|
487
|
+
const metadata = providerProjectionMetadata(this.providerCatalog, providerId, candidate);
|
|
488
|
+
added.push({
|
|
489
|
+
id,
|
|
490
|
+
externalId,
|
|
491
|
+
name: metadata.name,
|
|
492
|
+
description: metadata.description,
|
|
493
|
+
metadataSource: "provider",
|
|
494
|
+
active: false,
|
|
495
|
+
providerId,
|
|
496
|
+
connection,
|
|
497
|
+
createdAt: timestamp,
|
|
498
|
+
updatedAt: timestamp
|
|
499
|
+
});
|
|
500
|
+
reservedIds.add(id);
|
|
501
|
+
}
|
|
502
|
+
if (added.length > 0) {
|
|
503
|
+
this.spaces = [...this.spaces, ...added];
|
|
504
|
+
this.save();
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
added: added.map((body) => this.view(body)),
|
|
508
|
+
disconnected: stillDisconnected
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
/** The namespaces in one Provider answer this directory could hold; the others are left out. */
|
|
512
|
+
reportedNamespaces(providerId, service, discovered) {
|
|
513
|
+
const reported = discovered.flatMap((candidate) => {
|
|
514
|
+
try {
|
|
515
|
+
const externalId = requiredText(candidate.externalId, "provider externalId", 2e3);
|
|
516
|
+
const connection = this.providerCatalog.normalizeMemory(providerId, candidate.connection);
|
|
517
|
+
this.providerCatalog.normalize(providerId, {
|
|
518
|
+
...service,
|
|
519
|
+
...connection
|
|
520
|
+
});
|
|
521
|
+
const identity = this.namespaceIdentity(providerId, connection);
|
|
522
|
+
const whole = identity === void 0 ? this.wholeConnection(providerId, service, connection) : void 0;
|
|
523
|
+
return [{
|
|
524
|
+
candidate,
|
|
525
|
+
externalId,
|
|
526
|
+
connection,
|
|
527
|
+
...identity === void 0 ? {} : { identity },
|
|
528
|
+
...whole === void 0 ? {} : { whole },
|
|
529
|
+
distinct: false
|
|
530
|
+
}];
|
|
531
|
+
} catch {
|
|
532
|
+
return [];
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
const signature = (namespace) => namespace.identity !== void 0 ? `identity:${canonicalJson(namespace.identity)}` : namespace.whole === void 0 ? void 0 : `connection:${namespace.whole}`;
|
|
536
|
+
const counts = /* @__PURE__ */ new Map();
|
|
537
|
+
for (const namespace of reported) {
|
|
538
|
+
const key = signature(namespace);
|
|
539
|
+
if (key !== void 0) counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
540
|
+
}
|
|
541
|
+
for (const namespace of reported) {
|
|
542
|
+
const key = signature(namespace);
|
|
543
|
+
namespace.distinct = key !== void 0 && counts.get(key) === 1;
|
|
544
|
+
}
|
|
545
|
+
return reported;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* What names a namespace in a space's own settings: each text, address or path set for it. A
|
|
549
|
+
* wildcard (`*`) names nothing, and neither does a choice, a switch, a number such as a recall
|
|
550
|
+
* budget or a trust floor, or a secret.
|
|
551
|
+
*/
|
|
552
|
+
namespaceIdentity(providerId, connection) {
|
|
553
|
+
if (connection === void 0) return void 0;
|
|
554
|
+
const identity = {};
|
|
555
|
+
for (const field of this.providerCatalog.memoryFields(providerId)) {
|
|
556
|
+
if (!IDENTITY_INPUTS.has(field.input)) continue;
|
|
557
|
+
const value = connection[field.key];
|
|
558
|
+
if (typeof value !== "string") continue;
|
|
559
|
+
const text = value.trim();
|
|
560
|
+
if (text === "" || text === "*") continue;
|
|
561
|
+
identity[field.key] = text;
|
|
562
|
+
}
|
|
563
|
+
return Object.keys(identity).length === 0 ? void 0 : identity;
|
|
564
|
+
}
|
|
565
|
+
/** A whole connection, defaults filled in; one whose own part is empty compares by externalId alone. */
|
|
566
|
+
wholeConnection(providerId, service, memory) {
|
|
567
|
+
if (memory === void 0 || Object.keys(memory).length === 0) return void 0;
|
|
568
|
+
try {
|
|
569
|
+
return canonicalJson(this.providerCatalog.normalize(providerId, {
|
|
570
|
+
...service,
|
|
571
|
+
...memory
|
|
572
|
+
}));
|
|
573
|
+
} catch {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Whether `held`, a mounted space or a namespace a person disconnected, already reads the
|
|
579
|
+
* namespace a Provider reported: the same externalId, or every setting that names the namespace,
|
|
580
|
+
* whatever else differs; a `*` held reads every value. A hand-made Hindsight space for bank
|
|
581
|
+
* `team` with another recall budget reads bank `team`; a Honcho space for one peer of workspace
|
|
582
|
+
* `w1` reads workspace `w1`. Asking again only adds what nothing here reads yet.
|
|
583
|
+
*/
|
|
584
|
+
holds(providerId, service, held, reported) {
|
|
585
|
+
if (held.externalId !== void 0 && held.externalId === reported.externalId) return true;
|
|
586
|
+
if (!reported.distinct || held.connection === void 0) return false;
|
|
587
|
+
if (reported.identity !== void 0) {
|
|
588
|
+
const connection = held.connection;
|
|
589
|
+
return Object.entries(reported.identity).every(([key, value]) => {
|
|
590
|
+
const setting = connection[key];
|
|
591
|
+
return typeof setting === "string" && (setting.trim() === value || setting.trim() === "*");
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
return reported.whole !== void 0 && this.wholeConnection(providerId, service, held.connection) === reported.whole;
|
|
595
|
+
}
|
|
596
|
+
/** Remember a namespace a person disconnected, so asking its Provider again leaves it out. */
|
|
597
|
+
rememberDisconnected(providerId, body) {
|
|
598
|
+
const connection = body.connection === void 0 ? {} : this.providerCatalog.publicScoped(providerId, "memory", body.connection).settings;
|
|
599
|
+
const entry = {
|
|
600
|
+
...body.externalId === void 0 ? {} : { externalId: body.externalId },
|
|
601
|
+
...Object.keys(connection).length === 0 ? {} : { connection }
|
|
602
|
+
};
|
|
603
|
+
if (Object.keys(entry).length === 0) return;
|
|
604
|
+
const key = canonicalJson(entry);
|
|
605
|
+
this.disconnected[providerId] = [...(this.disconnected[providerId] ?? []).filter((item) => canonicalJson(item) !== key), entry].slice(-1e3);
|
|
606
|
+
this.saveDisconnects();
|
|
607
|
+
}
|
|
608
|
+
/** Forget the disconnected namespaces a save of the Provider's settings mounted again. */
|
|
609
|
+
forgetDisconnected(providerId, reported) {
|
|
610
|
+
const remembered = this.disconnected[providerId];
|
|
611
|
+
if (remembered === void 0) return;
|
|
612
|
+
const service = this.services[providerId] ?? {};
|
|
613
|
+
const remaining = remembered.filter((entry) => !reported.some((namespace) => this.holds(providerId, service, entry, namespace)));
|
|
614
|
+
if (remaining.length === remembered.length) return;
|
|
615
|
+
if (remaining.length === 0) delete this.disconnected[providerId];
|
|
616
|
+
else this.disconnected[providerId] = remaining;
|
|
617
|
+
this.saveDisconnects();
|
|
618
|
+
}
|
|
405
619
|
placementCandidates(request) {
|
|
406
620
|
return this.providerCatalog.providers.map((descriptor) => {
|
|
407
621
|
const providerTypeId = descriptor.typeId ?? descriptor.id;
|
|
@@ -556,8 +770,10 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
556
770
|
async remove(id, signal) {
|
|
557
771
|
const body = this.get(id);
|
|
558
772
|
if (!this.isNative(body.provider.id)) {
|
|
773
|
+
const stored = this.spaces.find((entry) => entry.id === body.id);
|
|
559
774
|
this.spaces = this.spaces.filter((entry) => entry.id !== body.id);
|
|
560
775
|
this.save();
|
|
776
|
+
if (stored !== void 0) this.rememberDisconnected(body.provider.id, stored);
|
|
561
777
|
return body;
|
|
562
778
|
}
|
|
563
779
|
const nativeStoreIds = this.nativeStoreIds();
|
|
@@ -621,6 +837,7 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
621
837
|
this.spaces = [];
|
|
622
838
|
this.services = {};
|
|
623
839
|
this.serviceEnabled = {};
|
|
840
|
+
this.disconnected = {};
|
|
624
841
|
this.loadAndReconcile();
|
|
625
842
|
this.state.diskRevision = this.diskRevision();
|
|
626
843
|
} finally {
|
|
@@ -629,7 +846,11 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
629
846
|
}
|
|
630
847
|
diskRevision() {
|
|
631
848
|
if (!this.persistent) return "ephemeral";
|
|
632
|
-
return [
|
|
849
|
+
return [
|
|
850
|
+
this.registryPath,
|
|
851
|
+
this.providerRegistryPath,
|
|
852
|
+
this.disconnectsPath
|
|
853
|
+
].map((path) => {
|
|
633
854
|
try {
|
|
634
855
|
const stat = statSync(path, { bigint: true });
|
|
635
856
|
return `${stat.ino}:${stat.mtimeNs}:${stat.size}`;
|
|
@@ -748,6 +969,13 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
748
969
|
}));
|
|
749
970
|
}
|
|
750
971
|
} catch {}
|
|
972
|
+
if (this.persistent && existsSync(this.disconnectsPath)) try {
|
|
973
|
+
const parsed = JSON.parse(readFileSync(this.disconnectsPath, "utf8"));
|
|
974
|
+
if (parsed.version === DISCONNECTS_VERSION && typeof parsed.providers === "object" && parsed.providers !== null) for (const [providerId, entries] of Object.entries(parsed.providers)) {
|
|
975
|
+
const remembered = storedDisconnects(entries);
|
|
976
|
+
if (storedProviderId(providerId) && remembered.length > 0) this.disconnected[providerId] = remembered;
|
|
977
|
+
}
|
|
978
|
+
} catch {}
|
|
751
979
|
const retainedBodies = this.spaces.filter((body) => !this.providerCatalog.has(body.providerId) || this.isNative(body.providerId) || this.providerServiceEnabled(body.providerId));
|
|
752
980
|
if (retainedBodies.length !== this.spaces.length) {
|
|
753
981
|
this.spaces = retainedBodies;
|
|
@@ -849,6 +1077,22 @@ var MemorySpaceRegistry = class MemorySpaceRegistry {
|
|
|
849
1077
|
});
|
|
850
1078
|
this.state.diskRevision = this.diskRevision();
|
|
851
1079
|
}
|
|
1080
|
+
saveDisconnects() {
|
|
1081
|
+
if (!this.persistent) return;
|
|
1082
|
+
const providers = Object.fromEntries(Object.entries(this.disconnected).filter(([, entries]) => entries !== void 0 && entries.length > 0));
|
|
1083
|
+
if (Object.keys(providers).length === 0) rmSync(this.disconnectsPath, { force: true });
|
|
1084
|
+
else {
|
|
1085
|
+
mkdirSync(dirname(this.disconnectsPath), {
|
|
1086
|
+
recursive: true,
|
|
1087
|
+
mode: 448
|
|
1088
|
+
});
|
|
1089
|
+
this.writeRegistry(this.disconnectsPath, {
|
|
1090
|
+
version: DISCONNECTS_VERSION,
|
|
1091
|
+
providers
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
this.state.diskRevision = this.diskRevision();
|
|
1095
|
+
}
|
|
852
1096
|
writeRegistry(path, file) {
|
|
853
1097
|
const temporary = join(dirname(path), `.${basename(path)}.${process.pid}.tmp`);
|
|
854
1098
|
writeFileSync(temporary, `${JSON.stringify(file, null, 2)}\n`, {
|
|
@@ -1300,6 +1544,25 @@ function number(value) {
|
|
|
1300
1544
|
const ENTITY_SELECTION_STATUS_REUSE_MS = 1e4;
|
|
1301
1545
|
/** How long an index that statistics cannot check is reused; a write through this Source still drops it. */
|
|
1302
1546
|
const ENTITY_INDEX_UNCHECKED_REUSE_MS = 1e4;
|
|
1547
|
+
/** How long one Provider may take to list its namespaces when they are asked for again. */
|
|
1548
|
+
const MEMORY_SPACES_REDISCOVERY_PROVIDER_TIMEOUT_MS = 3e4;
|
|
1549
|
+
/**
|
|
1550
|
+
* Rediscovery per data directory, shared by every generation in this process: the pass now
|
|
1551
|
+
* running, which a second request joins, and the last one, which the Memory Spaces page shows.
|
|
1552
|
+
*/
|
|
1553
|
+
const rediscoveries = /* @__PURE__ */ new Map();
|
|
1554
|
+
/** Settle with `work`, or reject once `signal` aborts, whichever comes first. */
|
|
1555
|
+
function untilAborted(work, signal) {
|
|
1556
|
+
if (signal.aborted) {
|
|
1557
|
+
work.catch(() => {});
|
|
1558
|
+
return Promise.reject(signal.reason);
|
|
1559
|
+
}
|
|
1560
|
+
return new Promise((resolve, reject) => {
|
|
1561
|
+
const abort = () => reject(signal.reason);
|
|
1562
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
1563
|
+
work.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1303
1566
|
function entityName(entity) {
|
|
1304
1567
|
const name = entity.trim();
|
|
1305
1568
|
if (name.length > 200) throw new Error("entity is too long (max 200 characters)");
|
|
@@ -1624,7 +1887,15 @@ var MemorySpacesService = class {
|
|
|
1624
1887
|
total: items.length,
|
|
1625
1888
|
activeCount: items.filter((body) => body.active && body.providerEnabled !== false).length,
|
|
1626
1889
|
directory: this.memorySpaces.directory,
|
|
1627
|
-
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1890
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1891
|
+
rediscovery: this.rediscoveryState()
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
rediscoveryState() {
|
|
1895
|
+
const entry = rediscoveries.get(this.memorySpaces.providerRegistryPath);
|
|
1896
|
+
return {
|
|
1897
|
+
running: entry?.running !== void 0,
|
|
1898
|
+
...entry?.last === void 0 ? {} : { last: entry.last }
|
|
1628
1899
|
};
|
|
1629
1900
|
}
|
|
1630
1901
|
/** Stable, secret-free checkpoint for the projected Memory Space authority. */
|
|
@@ -2509,6 +2780,89 @@ var MemorySpacesService = class {
|
|
|
2509
2780
|
const discovered = await provider.discover(connection, signal);
|
|
2510
2781
|
return this.memorySpaces.syncProviderService(providerId, connection, discovered);
|
|
2511
2782
|
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Ask every enabled Provider service again for its namespaces, as saving its settings does, and
|
|
2785
|
+
* mount the ones this directory has never held, inactive (#373). Nothing mounted changes and a
|
|
2786
|
+
* namespace a person disconnected stays disconnected. Providers are asked side by side, each
|
|
2787
|
+
* for at most 30 seconds; one that cannot answer keeps its spaces and says why. A pass already
|
|
2788
|
+
* running for this directory, at start-up or from the page, is joined rather than run twice; a
|
|
2789
|
+
* request that joined one its starter then stopped asks again, unless it was stopped itself.
|
|
2790
|
+
*/
|
|
2791
|
+
async rediscoverProviders(trigger, signal, providerTimeoutMs = MEMORY_SPACES_REDISCOVERY_PROVIDER_TIMEOUT_MS) {
|
|
2792
|
+
this.assertWritable();
|
|
2793
|
+
const key = this.memorySpaces.providerRegistryPath;
|
|
2794
|
+
const entry = rediscoveries.get(key) ?? {};
|
|
2795
|
+
rediscoveries.set(key, entry);
|
|
2796
|
+
const joined = entry.running;
|
|
2797
|
+
if (joined !== void 0) try {
|
|
2798
|
+
return await (signal === void 0 ? joined : untilAborted(joined, signal));
|
|
2799
|
+
} catch {
|
|
2800
|
+
signal?.throwIfAborted();
|
|
2801
|
+
const next = entry.running;
|
|
2802
|
+
if (next !== void 0 && next !== joined) return await (signal === void 0 ? next : untilAborted(next, signal));
|
|
2803
|
+
}
|
|
2804
|
+
const running = this.runRediscovery(trigger, signal, providerTimeoutMs);
|
|
2805
|
+
entry.running = running;
|
|
2806
|
+
try {
|
|
2807
|
+
const outcome = await running;
|
|
2808
|
+
entry.last = outcome;
|
|
2809
|
+
return outcome;
|
|
2810
|
+
} finally {
|
|
2811
|
+
if (entry.running === running) delete entry.running;
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
async runRediscovery(trigger, signal, providerTimeoutMs) {
|
|
2815
|
+
const services = this.memorySpaces.providerServices().items.filter((item) => item.enabled && !this.isNativeProvider(item.providerId));
|
|
2816
|
+
const results = await Promise.all(services.map(async (item) => {
|
|
2817
|
+
const provider = this.providers.get(item.providerId);
|
|
2818
|
+
if (provider?.discover === void 0) return void 0;
|
|
2819
|
+
const label = this.providerCatalog.descriptor(item.providerId).label;
|
|
2820
|
+
const timeout = AbortSignal.timeout(providerTimeoutMs);
|
|
2821
|
+
const bounded = signal === void 0 ? timeout : AbortSignal.any([signal, timeout]);
|
|
2822
|
+
try {
|
|
2823
|
+
const connection = this.memorySpaces.resolveProviderService(item.providerId, {});
|
|
2824
|
+
const discovered = await untilAborted(provider.discover(connection, bounded), bounded);
|
|
2825
|
+
signal?.throwIfAborted();
|
|
2826
|
+
const mounted = this.memorySpaces.mountDiscovered(item.providerId, connection, discovered);
|
|
2827
|
+
return {
|
|
2828
|
+
providerId: item.providerId,
|
|
2829
|
+
label,
|
|
2830
|
+
found: discovered.length,
|
|
2831
|
+
added: mounted.added.map((body) => ({
|
|
2832
|
+
id: body.id,
|
|
2833
|
+
name: body.name
|
|
2834
|
+
})),
|
|
2835
|
+
disconnected: mounted.disconnected
|
|
2836
|
+
};
|
|
2837
|
+
} catch (error) {
|
|
2838
|
+
signal?.throwIfAborted();
|
|
2839
|
+
const failure = {
|
|
2840
|
+
providerId: item.providerId,
|
|
2841
|
+
label,
|
|
2842
|
+
found: 0,
|
|
2843
|
+
added: [],
|
|
2844
|
+
disconnected: 0
|
|
2845
|
+
};
|
|
2846
|
+
if (timeout.aborted) {
|
|
2847
|
+
const limit = providerTimeoutMs < 1e3 ? `${providerTimeoutMs} ms` : `${Math.round(providerTimeoutMs / 1e3)} seconds`;
|
|
2848
|
+
return {
|
|
2849
|
+
...failure,
|
|
2850
|
+
timedOut: true,
|
|
2851
|
+
error: `did not answer within ${limit}`
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
return {
|
|
2855
|
+
...failure,
|
|
2856
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2857
|
+
};
|
|
2858
|
+
}
|
|
2859
|
+
}));
|
|
2860
|
+
return {
|
|
2861
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2862
|
+
trigger,
|
|
2863
|
+
results: results.filter((result) => result !== void 0)
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2512
2866
|
updateSpace(id, request) {
|
|
2513
2867
|
this.assertWritable();
|
|
2514
2868
|
return this.memorySpaces.update(id, request);
|
|
@@ -3180,6 +3534,7 @@ async function manageMemorySpaces(service, request) {
|
|
|
3180
3534
|
case "reload":
|
|
3181
3535
|
service.memorySpaces.reload();
|
|
3182
3536
|
return managementResult(service, { reloaded: true });
|
|
3537
|
+
case "provider-rediscover": return managementResult(service, await service.rediscoverProviders(input.trigger === "startup" ? "startup" : "manual", request.signal));
|
|
3183
3538
|
case "body-delete": return managementResult(service, await service.deleteSpace(memoryInputText(input.memoryBodyId, "memoryBodyId", 300), request.signal));
|
|
3184
3539
|
default: throw new Error(`unsupported Memory Spaces management mutation operation: ${request.operation}`);
|
|
3185
3540
|
}
|
|
@@ -3800,7 +4155,17 @@ async function installMemorySpaces(ctx, entries, options = {}) {
|
|
|
3800
4155
|
throw error;
|
|
3801
4156
|
}
|
|
3802
4157
|
}
|
|
4158
|
+
/**
|
|
4159
|
+
* dshmarket's client-only mount of a Memory Spaces package installed on its own
|
|
4160
|
+
* in a profile, `include:dsh-market:mkt-client-<package>`: it is meant to run no
|
|
4161
|
+
* host code, and the Starter's own Entry composes the Source with its Providers (#359).
|
|
4162
|
+
*/
|
|
4163
|
+
function isMarketClientShim(ctx) {
|
|
4164
|
+
const loader = ctx.get("loader", false);
|
|
4165
|
+
return /(?:^|:)mkt-client-[^:]*$/u.test(loader?.locate(ctx.fiber)?.trim() ?? "");
|
|
4166
|
+
}
|
|
3803
4167
|
async function apply(ctx, config = { providers: [] }) {
|
|
4168
|
+
if (isMarketClientShim(ctx)) return;
|
|
3804
4169
|
const { providers, ...sourceConfig } = config;
|
|
3805
4170
|
await installMemorySpaces(ctx, await resolveMemorySpaceProviderEntries(ctx, providers), { config: sourceConfig });
|
|
3806
4171
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CreateMemorySpaceRequest, EntityMemoriesView, EntityRelatedView, EntityView, Insight, MemorySpace, MemorySpaceView, MemorySpaceMetadataMaintenanceResult, MemorySpaceCatalog, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryReadSource, RememberRequest, SearchRequest, UpdateMemorySpaceRequest } from '../contracts.ts';
|
|
1
|
+
import type { CreateMemorySpaceRequest, EntityMemoriesView, EntityRelatedView, EntityView, Insight, MemorySpace, MemorySpaceView, MemorySpaceMetadataMaintenanceResult, MemorySpaceCatalog, MemorySpaceRediscovery, MemoryGraphSnapshot, MemoryListRequest, MemoryListView, MemoryReadSource, RememberRequest, SearchRequest, UpdateMemorySpaceRequest } from '../contracts.ts';
|
|
2
2
|
/**
|
|
3
3
|
* Source-owned structural page API; the default bundle may supply agent-assisted callbacks.
|
|
4
4
|
* body/bodies method and wire-field spellings remain compatible with existing
|
|
@@ -33,6 +33,8 @@ export interface MemorySpacesPageClient {
|
|
|
33
33
|
reconnectBody(memoryBodyId: string): Promise<MemorySpaceView>;
|
|
34
34
|
maintainBodyMetadata(memoryBodyIds: string[]): Promise<MemorySpaceMetadataMaintenanceResult>;
|
|
35
35
|
deleteBody(memoryBodyId: string): Promise<MemorySpace>;
|
|
36
|
+
/** Ask every enabled Provider again for namespaces it gained; optional for page clients written against an older Source. */
|
|
37
|
+
rediscoverBodies?(): Promise<MemorySpaceRediscovery>;
|
|
36
38
|
}
|
|
37
39
|
export interface SearchResponse {
|
|
38
40
|
results: Insight[];
|
package/lib/types/contracts.d.ts
CHANGED
|
@@ -340,6 +340,35 @@ export interface MemorySpaceCatalog {
|
|
|
340
340
|
generatedAt: string;
|
|
341
341
|
/** Present only when body-directory receives a supported writeScope request. Older Sources omit it. */
|
|
342
342
|
writeScope?: MemorySpaceWriteScope;
|
|
343
|
+
/** Provider namespaces asked for again in this process: whether a pass is running, and the last one. Older Sources omit it. */
|
|
344
|
+
rediscovery?: {
|
|
345
|
+
running: boolean;
|
|
346
|
+
last?: MemorySpaceRediscovery;
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
/** What one Provider answered when its namespaces were asked for again. */
|
|
350
|
+
export interface MemorySpaceRediscoveryResult {
|
|
351
|
+
providerId: MemoryProviderId;
|
|
352
|
+
label: string;
|
|
353
|
+
/** Namespaces the Provider reported. */
|
|
354
|
+
found: number;
|
|
355
|
+
/** Spaces mounted for namespaces this directory had never held. They start inactive. */
|
|
356
|
+
added: Array<{
|
|
357
|
+
id: string;
|
|
358
|
+
name: string;
|
|
359
|
+
}>;
|
|
360
|
+
/** Reported namespaces a person disconnected here; they stay disconnected. */
|
|
361
|
+
disconnected: number;
|
|
362
|
+
/** Why the Provider could not be asked, as it said. Its spaces stay as they were. */
|
|
363
|
+
error?: string;
|
|
364
|
+
/** The Provider said nothing within the time it was given. */
|
|
365
|
+
timedOut?: boolean;
|
|
366
|
+
}
|
|
367
|
+
/** One pass over every enabled Provider service, when the Host starts or from the Memory Spaces page. */
|
|
368
|
+
export interface MemorySpaceRediscovery {
|
|
369
|
+
at: string;
|
|
370
|
+
trigger: 'startup' | 'manual';
|
|
371
|
+
results: MemorySpaceRediscoveryResult[];
|
|
343
372
|
}
|
|
344
373
|
export interface MemoryGraphNode extends Insight {
|
|
345
374
|
color: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mnemon-source-memory-spaces",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
4
4
|
"description": "Memory Spaces Source and its private Provider SDK.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -65,14 +65,14 @@
|
|
|
65
65
|
"@types/node": "^22.0.0",
|
|
66
66
|
"@types/react": "^18.3.0",
|
|
67
67
|
"@types/react-dom": "^18.3.0",
|
|
68
|
-
"dsh-mnemon": "^0.5.
|
|
68
|
+
"dsh-mnemon": "^0.5.29",
|
|
69
69
|
"dsh-mnemon-provider-byterover": "^0.5.5",
|
|
70
|
-
"dsh-mnemon-provider-hindsight": "^0.5.
|
|
70
|
+
"dsh-mnemon-provider-hindsight": "^0.5.6",
|
|
71
71
|
"dsh-mnemon-provider-holographic": "^0.5.6",
|
|
72
72
|
"dsh-mnemon-provider-honcho": "^0.5.5",
|
|
73
73
|
"dsh-mnemon-provider-mem0": "^0.5.5",
|
|
74
74
|
"dsh-mnemon-provider-mnemon-native": "^0.5.9",
|
|
75
|
-
"dsh-mnemon-provider-openviking": "^0.5.
|
|
75
|
+
"dsh-mnemon-provider-openviking": "^0.5.8",
|
|
76
76
|
"dsh-mnemon-provider-retaindb": "^0.5.5",
|
|
77
77
|
"dsh-mnemon-provider-supermemory": "^0.5.5",
|
|
78
78
|
"jsdom": "^26.0.0",
|