@opendatalabs/personal-server-ts-server 0.0.1-canary.de6bc6f → 0.0.1-canary.dfa1648
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.
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
import type { SchemaRegistrarPort } from "@opendatalabs/personal-server-ts-core/ports";
|
|
2
|
-
import type { ServerSigner } from "@opendatalabs/personal-server-ts-core/signing";
|
|
3
|
-
import type { Logger } from "pino";
|
|
4
1
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* The no-schema registrar now lives in core so the in-browser PS-Lite runtime
|
|
3
|
+
* can register schemas for binary uploads too (see
|
|
4
|
+
* `packages/core/src/api/schema-registrar.ts`). Re-exported here for backwards
|
|
5
|
+
* compatibility with existing server imports.
|
|
8
6
|
*/
|
|
9
|
-
export
|
|
10
|
-
export declare const NO_SCHEMA_DEFINITION_URL = "https://schemas.vana.org/no-schema/v1.json";
|
|
11
|
-
export declare const NO_SCHEMA_DIALECT = "none";
|
|
12
|
-
export interface SchemaRegistrarDeps {
|
|
13
|
-
gatewayUrl: string;
|
|
14
|
-
signer: ServerSigner;
|
|
15
|
-
logger?: Logger;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Registers (idempotently, by scope) a permissive "no-schema" schema with the
|
|
19
|
-
* gateway via POST /v1/schemas, signing an EIP-712 SchemaRegistration message.
|
|
20
|
-
*
|
|
21
|
-
* The gateway requires the EIP-712 signer to equal the registered ownerAddress
|
|
22
|
-
* (no server-delegation branch for schemas), so the schema is owned by the
|
|
23
|
-
* server signing account.
|
|
24
|
-
*/
|
|
25
|
-
export declare function createSchemaRegistrar(deps: SchemaRegistrarDeps): SchemaRegistrarPort;
|
|
7
|
+
export { createSchemaRegistrar, NO_SCHEMA_DEFINITION_URL, NO_SCHEMA_DIALECT, NO_SCHEMA_NAME, type SchemaRegistrarDeps, } from "@opendatalabs/personal-server-ts-core/api";
|
|
26
8
|
//# sourceMappingURL=schema-registrar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-registrar.d.ts","sourceRoot":"","sources":["../src/schema-registrar.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schema-registrar.d.ts","sourceRoot":"","sources":["../src/schema-registrar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,2CAA2C,CAAC"}
|
package/dist/schema-registrar.js
CHANGED
|
@@ -1,61 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The no-schema registrar now lives in core so the in-browser PS-Lite runtime
|
|
3
|
+
* can register schemas for binary uploads too (see
|
|
4
|
+
* `packages/core/src/api/schema-registrar.ts`). Re-exported here for backwards
|
|
5
|
+
* compatibility with existing server imports.
|
|
5
6
|
*/
|
|
6
|
-
export
|
|
7
|
-
export const NO_SCHEMA_DEFINITION_URL = "https://schemas.vana.org/no-schema/v1.json";
|
|
8
|
-
export const NO_SCHEMA_DIALECT = "none";
|
|
9
|
-
function extractSchemaId(body) {
|
|
10
|
-
return (body.schemaId ??
|
|
11
|
-
body.id ??
|
|
12
|
-
body.data?.schemaId ??
|
|
13
|
-
body.data?.id ??
|
|
14
|
-
undefined);
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Registers (idempotently, by scope) a permissive "no-schema" schema with the
|
|
18
|
-
* gateway via POST /v1/schemas, signing an EIP-712 SchemaRegistration message.
|
|
19
|
-
*
|
|
20
|
-
* The gateway requires the EIP-712 signer to equal the registered ownerAddress
|
|
21
|
-
* (no server-delegation branch for schemas), so the schema is owned by the
|
|
22
|
-
* server signing account.
|
|
23
|
-
*/
|
|
24
|
-
export function createSchemaRegistrar(deps) {
|
|
25
|
-
const base = deps.gatewayUrl.replace(/\/+$/, "");
|
|
26
|
-
return {
|
|
27
|
-
async registerNoSchema(scope) {
|
|
28
|
-
const ownerAddress = deps.signer.address;
|
|
29
|
-
const message = {
|
|
30
|
-
ownerAddress,
|
|
31
|
-
name: NO_SCHEMA_NAME,
|
|
32
|
-
definitionUrl: NO_SCHEMA_DEFINITION_URL,
|
|
33
|
-
scope,
|
|
34
|
-
dialect: NO_SCHEMA_DIALECT,
|
|
35
|
-
};
|
|
36
|
-
const signature = await deps.signer.signSchemaRegistration(message);
|
|
37
|
-
const res = await fetch(`${base}/v1/schemas`, {
|
|
38
|
-
method: "POST",
|
|
39
|
-
headers: {
|
|
40
|
-
"Content-Type": "application/json",
|
|
41
|
-
Authorization: `Web3Signed ${signature}`,
|
|
42
|
-
},
|
|
43
|
-
body: JSON.stringify(message),
|
|
44
|
-
});
|
|
45
|
-
if (!res.ok) {
|
|
46
|
-
const detail = await res.text().catch(() => res.statusText);
|
|
47
|
-
throw new Error(`Schema registration failed: ${res.status} ${detail}`);
|
|
48
|
-
}
|
|
49
|
-
const body = (await res
|
|
50
|
-
.json()
|
|
51
|
-
.catch(() => ({})));
|
|
52
|
-
const schemaId = extractSchemaId(body);
|
|
53
|
-
if (!schemaId) {
|
|
54
|
-
throw new Error(`Schema registration for "${scope}" did not return a schemaId`);
|
|
55
|
-
}
|
|
56
|
-
deps.logger?.info({ scope, schemaId }, "Registered no-schema schema with gateway");
|
|
57
|
-
return { schemaId, definitionUrl: NO_SCHEMA_DEFINITION_URL };
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
}
|
|
7
|
+
export { createSchemaRegistrar, NO_SCHEMA_DEFINITION_URL, NO_SCHEMA_DIALECT, NO_SCHEMA_NAME, } from "@opendatalabs/personal-server-ts-core/api";
|
|
61
8
|
//# sourceMappingURL=schema-registrar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-registrar.js","sourceRoot":"","sources":["../src/schema-registrar.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema-registrar.js","sourceRoot":"","sources":["../src/schema-registrar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,GAEf,MAAM,2CAA2C,CAAC"}
|
package/dist/ui/ps-lite-debug.js
CHANGED
|
@@ -105446,6 +105446,12 @@ function deleteMapPrefix(map2, pathPrefix) {
|
|
|
105446
105446
|
}
|
|
105447
105447
|
}
|
|
105448
105448
|
}
|
|
105449
|
+
function describeStorageError(error51) {
|
|
105450
|
+
if (error51 instanceof Error) {
|
|
105451
|
+
return { errorClass: error51.name, message: error51.message };
|
|
105452
|
+
}
|
|
105453
|
+
return { errorClass: typeof error51, message: String(error51) };
|
|
105454
|
+
}
|
|
105449
105455
|
async function getOrCreateOpfsDirectory(root, parts) {
|
|
105450
105456
|
let dir = root;
|
|
105451
105457
|
for (const part of parts) {
|
|
@@ -105640,8 +105646,8 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
105640
105646
|
const snapshot = {
|
|
105641
105647
|
...state,
|
|
105642
105648
|
envelopes: fileStore.kind === "indexeddb" ? Array.from(fallbackEnvelopes.values()) : [],
|
|
105643
|
-
blockManifests:
|
|
105644
|
-
blockPayloads:
|
|
105649
|
+
blockManifests: Array.from(fallbackBlockManifests.entries()).map(([path, manifest]) => ({ path, manifest })),
|
|
105650
|
+
blockPayloads: Array.from(fallbackBlockPayloads.entries()).map(([path, block]) => ({ path, block }))
|
|
105645
105651
|
};
|
|
105646
105652
|
const write = persistQueue.then(() => persistence.write(snapshot));
|
|
105647
105653
|
persistQueue = write.catch(() => void 0);
|
|
@@ -105749,15 +105755,34 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
105749
105755
|
return Boolean(manifest);
|
|
105750
105756
|
},
|
|
105751
105757
|
async writeBlockManifest(scope, collectedAt2, manifest, blocks) {
|
|
105752
|
-
|
|
105753
|
-
|
|
105754
|
-
|
|
105755
|
-
|
|
105756
|
-
|
|
105757
|
-
|
|
105758
|
-
|
|
105759
|
-
|
|
105760
|
-
|
|
105758
|
+
const writeTree = async (store) => {
|
|
105759
|
+
if (!store.writeBlockManifest || !store.writeBlockPayload) {
|
|
105760
|
+
throw new Error("Block sidecar storage is not available");
|
|
105761
|
+
}
|
|
105762
|
+
await store.deleteBlockTree?.(blockTreePath(scope, collectedAt2));
|
|
105763
|
+
for (const block of blocks) {
|
|
105764
|
+
await store.writeBlockPayload(blockPayloadPath(scope, collectedAt2, block.id), block);
|
|
105765
|
+
}
|
|
105766
|
+
await store.writeBlockManifest(blockManifestPath(scope, collectedAt2), manifest);
|
|
105767
|
+
};
|
|
105768
|
+
let wrotePrimary = false;
|
|
105769
|
+
try {
|
|
105770
|
+
await writeTree(fileStore);
|
|
105771
|
+
wrotePrimary = true;
|
|
105772
|
+
} catch (error51) {
|
|
105773
|
+
if (fileStore === fallbackStore) {
|
|
105774
|
+
throw error51;
|
|
105775
|
+
}
|
|
105776
|
+
console.warn({
|
|
105777
|
+
scope,
|
|
105778
|
+
collectedAt: collectedAt2,
|
|
105779
|
+
fileStoreKind: fileStore.kind,
|
|
105780
|
+
fallbackStoreKind: fallbackStore.kind,
|
|
105781
|
+
...describeStorageError(error51)
|
|
105782
|
+
}, "Primary block sidecar write failed; using IndexedDB fallback");
|
|
105783
|
+
await writeTree(fallbackStore);
|
|
105784
|
+
}
|
|
105785
|
+
if (wrotePrimary && fileStore.kind !== "indexeddb") {
|
|
105761
105786
|
await fallbackStore.deleteBlockTree?.(blockTreePath(scope, collectedAt2));
|
|
105762
105787
|
}
|
|
105763
105788
|
await persist();
|
|
@@ -107803,6 +107828,49 @@ async function syncFileContract(input) {
|
|
|
107803
107828
|
return contractOk({ fileId: input.fileId, status: "started" }, 202);
|
|
107804
107829
|
}
|
|
107805
107830
|
|
|
107831
|
+
// ../core/dist/api/schema-registrar.js
|
|
107832
|
+
var NO_SCHEMA_NAME = "No Schema";
|
|
107833
|
+
var NO_SCHEMA_DEFINITION_URL = "https://schemas.vana.org/no-schema/v1.json";
|
|
107834
|
+
var NO_SCHEMA_DIALECT = "none";
|
|
107835
|
+
function extractSchemaId(body) {
|
|
107836
|
+
return body.schemaId ?? body.id ?? body.data?.schemaId ?? body.data?.id ?? void 0;
|
|
107837
|
+
}
|
|
107838
|
+
function createSchemaRegistrar(deps) {
|
|
107839
|
+
const base = deps.gatewayUrl.replace(/\/+$/, "");
|
|
107840
|
+
return {
|
|
107841
|
+
async registerNoSchema(scope) {
|
|
107842
|
+
const ownerAddress = deps.signer.address;
|
|
107843
|
+
const message = {
|
|
107844
|
+
ownerAddress,
|
|
107845
|
+
name: NO_SCHEMA_NAME,
|
|
107846
|
+
definitionUrl: NO_SCHEMA_DEFINITION_URL,
|
|
107847
|
+
scope,
|
|
107848
|
+
dialect: NO_SCHEMA_DIALECT
|
|
107849
|
+
};
|
|
107850
|
+
const signature = await deps.signer.signSchemaRegistration(message);
|
|
107851
|
+
const res = await fetch(`${base}/v1/schemas`, {
|
|
107852
|
+
method: "POST",
|
|
107853
|
+
headers: {
|
|
107854
|
+
"Content-Type": "application/json",
|
|
107855
|
+
Authorization: `Web3Signed ${signature}`
|
|
107856
|
+
},
|
|
107857
|
+
body: JSON.stringify(message)
|
|
107858
|
+
});
|
|
107859
|
+
if (!res.ok) {
|
|
107860
|
+
const detail = await res.text().catch(() => res.statusText);
|
|
107861
|
+
throw new Error(`Schema registration failed: ${res.status} ${detail}`);
|
|
107862
|
+
}
|
|
107863
|
+
const body = await res.json().catch(() => ({}));
|
|
107864
|
+
const schemaId = extractSchemaId(body);
|
|
107865
|
+
if (!schemaId) {
|
|
107866
|
+
throw new Error(`Schema registration for "${scope}" did not return a schemaId`);
|
|
107867
|
+
}
|
|
107868
|
+
deps.logger?.info({ scope, schemaId }, "Registered no-schema schema with gateway");
|
|
107869
|
+
return { schemaId, definitionUrl: NO_SCHEMA_DEFINITION_URL };
|
|
107870
|
+
}
|
|
107871
|
+
};
|
|
107872
|
+
}
|
|
107873
|
+
|
|
107806
107874
|
// ../core/dist/api/index.js
|
|
107807
107875
|
function jsonResponse(body, init) {
|
|
107808
107876
|
const headers = new Headers(init?.headers);
|
|
@@ -110827,6 +110895,23 @@ function uniqueSources(connection) {
|
|
|
110827
110895
|
}
|
|
110828
110896
|
return Array.from(set2).sort();
|
|
110829
110897
|
}
|
|
110898
|
+
function normalizeScopeListInput(value) {
|
|
110899
|
+
if (!Array.isArray(value))
|
|
110900
|
+
return [];
|
|
110901
|
+
const scopes = [];
|
|
110902
|
+
const seen = /* @__PURE__ */ new Set();
|
|
110903
|
+
for (const raw of value) {
|
|
110904
|
+
if (typeof raw !== "string")
|
|
110905
|
+
continue;
|
|
110906
|
+
const scope = raw.trim();
|
|
110907
|
+
if (!scope || scope.length > SEARCH_SCOPE_MAX_CHARS || seen.has(scope)) {
|
|
110908
|
+
continue;
|
|
110909
|
+
}
|
|
110910
|
+
seen.add(scope);
|
|
110911
|
+
scopes.push(scope);
|
|
110912
|
+
}
|
|
110913
|
+
return scopes;
|
|
110914
|
+
}
|
|
110830
110915
|
var DEFAULT_SEARCH_LIMIT = 5;
|
|
110831
110916
|
var MAX_SEARCH_LIMIT = 50;
|
|
110832
110917
|
var MAX_SEARCH_SCOPES = 200;
|
|
@@ -111189,6 +111274,36 @@ var listGrantedScopes = {
|
|
|
111189
111274
|
return textResult({ scopes: scopeEntries });
|
|
111190
111275
|
}
|
|
111191
111276
|
};
|
|
111277
|
+
var requestScopeAccess = {
|
|
111278
|
+
name: "request_scope_access",
|
|
111279
|
+
title: "Request scope access",
|
|
111280
|
+
description: "Check which requested scopes are missing from this MCP grant and tell the user to approve them in Vana.",
|
|
111281
|
+
inputSchema: {
|
|
111282
|
+
scopes: external_exports.array(external_exports.string().min(1).max(SEARCH_SCOPE_MAX_CHARS)).min(1).max(SEARCH_REQUESTED_SCOPES_LIMIT).describe("Exact scope ids the MCP client wants to read."),
|
|
111283
|
+
reason: external_exports.string().max(500).optional().describe("Brief reason to show the user.")
|
|
111284
|
+
},
|
|
111285
|
+
async handler(args, { connection }) {
|
|
111286
|
+
const requestedScopes = normalizeScopeListInput(args.scopes);
|
|
111287
|
+
const grantedRequestedScopes = requestedScopes.filter((scope) => Boolean(resolveGrantForScope(connection, scope)));
|
|
111288
|
+
const missingScopes = requestedScopes.filter((scope) => !resolveGrantForScope(connection, scope));
|
|
111289
|
+
const reason = typeof args.reason === "string" ? args.reason.trim() : "";
|
|
111290
|
+
const approvalRequired = missingScopes.length > 0;
|
|
111291
|
+
return textResult({
|
|
111292
|
+
approvalRequired,
|
|
111293
|
+
client: {
|
|
111294
|
+
id: connection.id,
|
|
111295
|
+
displayName: connection.displayName,
|
|
111296
|
+
status: connection.status
|
|
111297
|
+
},
|
|
111298
|
+
requestedScopes,
|
|
111299
|
+
grantedRequestedScopes,
|
|
111300
|
+
missingScopes,
|
|
111301
|
+
grantedScopes: uniqueScopes(connection),
|
|
111302
|
+
reason: reason || void 0,
|
|
111303
|
+
nextAction: approvalRequired ? "Ask the user to open Vana's Personal Server page and add the missing scopes to this MCP client. This tool cannot grant access by itself." : "No new grant is needed for the requested scopes."
|
|
111304
|
+
});
|
|
111305
|
+
}
|
|
111306
|
+
};
|
|
111192
111307
|
var readScope = {
|
|
111193
111308
|
name: "read_scope",
|
|
111194
111309
|
title: "Read scope",
|
|
@@ -111661,6 +111776,7 @@ var getScopeFile = {
|
|
|
111661
111776
|
var MCP_TOOLS = [
|
|
111662
111777
|
listGrantedSources,
|
|
111663
111778
|
listGrantedScopes,
|
|
111779
|
+
requestScopeAccess,
|
|
111664
111780
|
readScope,
|
|
111665
111781
|
getScopeFile,
|
|
111666
111782
|
searchPersonalContext
|
|
@@ -123177,6 +123293,15 @@ function createPsLiteRuntime(options) {
|
|
|
123177
123293
|
}
|
|
123178
123294
|
const tokenStore = options.tokenStore ?? createDefaultTokenStore();
|
|
123179
123295
|
const saveConfig = options.saveConfig ?? createDefaultSaveConfig();
|
|
123296
|
+
const schemaRegistrarSigner = options.serverSigner;
|
|
123297
|
+
const schemaRegistrarGatewayUrl = options.config?.gateway?.url;
|
|
123298
|
+
const schemaRegistrar = schemaRegistrarSigner?.signSchemaRegistration && schemaRegistrarSigner.address && schemaRegistrarGatewayUrl ? createSchemaRegistrar({
|
|
123299
|
+
gatewayUrl: schemaRegistrarGatewayUrl,
|
|
123300
|
+
signer: {
|
|
123301
|
+
address: schemaRegistrarSigner.address,
|
|
123302
|
+
signSchemaRegistration: schemaRegistrarSigner.signSchemaRegistration
|
|
123303
|
+
}
|
|
123304
|
+
}) : void 0;
|
|
123180
123305
|
const deviceSessions = createMemoryDeviceSessionStore();
|
|
123181
123306
|
const mcpOAuthAuthorizationStore = options.mcpOAuthAuthorizationStore ?? createInMemoryMcpOAuthAuthorizationStore();
|
|
123182
123307
|
const activityRecorder = options.mcpConnectionStore ? new McpActivityRecorder() : void 0;
|
|
@@ -123389,6 +123514,7 @@ function createPsLiteRuntime(options) {
|
|
|
123389
123514
|
storage: dataStorage,
|
|
123390
123515
|
auth,
|
|
123391
123516
|
schemaResolver: options.gateway,
|
|
123517
|
+
schemaRegistrar,
|
|
123392
123518
|
accessLogWriter,
|
|
123393
123519
|
syncManager: options.syncManager ?? null,
|
|
123394
123520
|
now,
|
|
@@ -124043,9 +124169,17 @@ async function downloadOne(deps, record2) {
|
|
|
124043
124169
|
const { storage, storageAdapter, gateway, masterKey, logger, diagnostics } = deps;
|
|
124044
124170
|
const existing = storage.findByFileId(record2.fileId);
|
|
124045
124171
|
if (existing) {
|
|
124046
|
-
await repairMissingBlockSidecars(storage, logger, record2, existing, diagnostics);
|
|
124047
|
-
|
|
124048
|
-
|
|
124172
|
+
const repairResult = await repairMissingBlockSidecars(storage, logger, record2, existing, diagnostics);
|
|
124173
|
+
if (repairResult === "missing-envelope") {
|
|
124174
|
+
logger.warn({
|
|
124175
|
+
fileId: record2.fileId,
|
|
124176
|
+
scope: existing.scope,
|
|
124177
|
+
collectedAt: existing.collectedAt
|
|
124178
|
+
}, "Local index entry was missing its envelope; re-downloading file");
|
|
124179
|
+
} else {
|
|
124180
|
+
logger.debug({ fileId: record2.fileId }, "File already in index, skipping");
|
|
124181
|
+
return null;
|
|
124182
|
+
}
|
|
124049
124183
|
}
|
|
124050
124184
|
diagnostics?.onDownloadStart(record2.fileId);
|
|
124051
124185
|
let encrypted;
|
|
@@ -124101,17 +124235,24 @@ async function downloadOne(deps, record2) {
|
|
|
124101
124235
|
if (existingByVersion.fileId !== record2.fileId) {
|
|
124102
124236
|
await storage.updateFileId(existingByVersion.path, record2.fileId);
|
|
124103
124237
|
}
|
|
124104
|
-
await repairMissingBlockSidecars(storage, logger, record2, {
|
|
124238
|
+
const repairResult = await repairMissingBlockSidecars(storage, logger, record2, {
|
|
124105
124239
|
...existingByVersion,
|
|
124106
124240
|
fileId: record2.fileId,
|
|
124107
124241
|
schemaId: existingByVersion.schemaId ?? record2.schemaId
|
|
124108
124242
|
}, diagnostics);
|
|
124109
|
-
|
|
124243
|
+
if (repairResult !== "missing-envelope") {
|
|
124244
|
+
logger.debug({
|
|
124245
|
+
fileId: record2.fileId,
|
|
124246
|
+
scope: envelope.scope,
|
|
124247
|
+
collectedAt: envelope.collectedAt
|
|
124248
|
+
}, "File version already exists locally, skipping");
|
|
124249
|
+
return null;
|
|
124250
|
+
}
|
|
124251
|
+
logger.warn({
|
|
124110
124252
|
fileId: record2.fileId,
|
|
124111
124253
|
scope: envelope.scope,
|
|
124112
124254
|
collectedAt: envelope.collectedAt
|
|
124113
|
-
}, "
|
|
124114
|
-
return null;
|
|
124255
|
+
}, "Local version entry was missing its envelope; rewriting downloaded file");
|
|
124115
124256
|
}
|
|
124116
124257
|
diagnostics?.onIndexStart(record2.fileId, envelope.scope);
|
|
124117
124258
|
let relativePath;
|
|
@@ -124150,8 +124291,11 @@ async function downloadOne(deps, record2) {
|
|
|
124150
124291
|
async function downloadAll(deps) {
|
|
124151
124292
|
const { gateway, cursor, serverOwner, logger } = deps;
|
|
124152
124293
|
const syncRunId = createSyncRunId();
|
|
124153
|
-
await repairLocalMissingBlockSidecars(deps);
|
|
124154
|
-
const lastProcessedTimestamp = await cursor.read();
|
|
124294
|
+
const repairSummary = await repairLocalMissingBlockSidecars(deps);
|
|
124295
|
+
const lastProcessedTimestamp = repairSummary.missingEnvelopeEntries > 0 ? null : await cursor.read();
|
|
124296
|
+
if (repairSummary.missingEnvelopeEntries > 0) {
|
|
124297
|
+
logger.warn({ missingEnvelopeEntries: repairSummary.missingEnvelopeEntries }, "Resetting this sync listing to repair stale local index entries");
|
|
124298
|
+
}
|
|
124155
124299
|
const { files, cursor: nextCursor } = await gateway.listFilesSince(serverOwner, lastProcessedTimestamp, { includeDeleted: true });
|
|
124156
124300
|
const results = [];
|
|
124157
124301
|
let failed = false;
|
|
@@ -124210,13 +124354,16 @@ async function downloadAll(deps) {
|
|
|
124210
124354
|
}
|
|
124211
124355
|
async function repairLocalMissingBlockSidecars(deps) {
|
|
124212
124356
|
const { storage, logger, diagnostics } = deps;
|
|
124213
|
-
if (!storage.writeBlockManifest || !storage.hasScopeBlocks)
|
|
124214
|
-
return 0;
|
|
124357
|
+
if (!storage.writeBlockManifest || !storage.hasScopeBlocks) {
|
|
124358
|
+
return { repaired: 0, missingEnvelopeEntries: 0 };
|
|
124359
|
+
}
|
|
124215
124360
|
let repaired = 0;
|
|
124361
|
+
let missingEnvelopeEntries = 0;
|
|
124216
124362
|
let offset = 0;
|
|
124217
124363
|
const limit = 100;
|
|
124218
124364
|
while (true) {
|
|
124219
124365
|
const page = storage.listScopes({ limit, offset });
|
|
124366
|
+
let deletedEntryInPage = false;
|
|
124220
124367
|
for (const scopeSummary of page.scopes) {
|
|
124221
124368
|
const entry = storage.findEntry({
|
|
124222
124369
|
scope: scopeSummary.scope,
|
|
@@ -124224,24 +124371,33 @@ async function repairLocalMissingBlockSidecars(deps) {
|
|
|
124224
124371
|
});
|
|
124225
124372
|
if (!entry)
|
|
124226
124373
|
continue;
|
|
124227
|
-
const
|
|
124374
|
+
const repairResult = await repairMissingBlockSidecars(storage, logger, {
|
|
124228
124375
|
fileId: entry.fileId ?? entry.path,
|
|
124229
124376
|
owner: "",
|
|
124230
124377
|
url: "",
|
|
124231
124378
|
schemaId: entry.schemaId ?? "",
|
|
124232
124379
|
createdAt: entry.createdAt
|
|
124233
124380
|
}, entry, diagnostics);
|
|
124234
|
-
if (
|
|
124381
|
+
if (repairResult === "repaired")
|
|
124235
124382
|
repaired += 1;
|
|
124383
|
+
if (repairResult === "missing-envelope") {
|
|
124384
|
+
missingEnvelopeEntries += 1;
|
|
124385
|
+
deletedEntryInPage = true;
|
|
124386
|
+
}
|
|
124387
|
+
}
|
|
124388
|
+
if (!deletedEntryInPage) {
|
|
124389
|
+
offset += page.scopes.length;
|
|
124236
124390
|
}
|
|
124237
|
-
offset += page.scopes.length;
|
|
124238
124391
|
if (offset >= page.total || page.scopes.length === 0)
|
|
124239
124392
|
break;
|
|
124240
124393
|
}
|
|
124241
124394
|
if (repaired > 0) {
|
|
124242
124395
|
logger.info({ repaired }, "Repaired missing bounded block sidecars for local indexed data");
|
|
124243
124396
|
}
|
|
124244
|
-
|
|
124397
|
+
if (missingEnvelopeEntries > 0) {
|
|
124398
|
+
logger.warn({ missingEnvelopeEntries }, "Removed stale local index entries missing local envelopes");
|
|
124399
|
+
}
|
|
124400
|
+
return { repaired, missingEnvelopeEntries };
|
|
124245
124401
|
}
|
|
124246
124402
|
function createSyncRunId() {
|
|
124247
124403
|
return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `download-${Date.now().toString(36)}`;
|
|
@@ -124299,8 +124455,9 @@ async function writeBlockSidecars2(storage, envelope, logger, record2, relativeP
|
|
|
124299
124455
|
}
|
|
124300
124456
|
}
|
|
124301
124457
|
async function repairMissingBlockSidecars(storage, logger, record2, entry, diagnostics) {
|
|
124302
|
-
if (!storage.writeBlockManifest || !storage.hasScopeBlocks)
|
|
124303
|
-
return
|
|
124458
|
+
if (!storage.writeBlockManifest || !storage.hasScopeBlocks) {
|
|
124459
|
+
return "not-repaired";
|
|
124460
|
+
}
|
|
124304
124461
|
let hasBlocks = false;
|
|
124305
124462
|
try {
|
|
124306
124463
|
hasBlocks = await storage.hasScopeBlocks(entry.scope, entry.collectedAt);
|
|
@@ -124311,10 +124468,10 @@ async function repairMissingBlockSidecars(storage, logger, record2, entry, diagn
|
|
|
124311
124468
|
collectedAt: entry.collectedAt,
|
|
124312
124469
|
error: error51.message
|
|
124313
124470
|
}, "Bounded block sidecar repair skipped after readiness check failed");
|
|
124314
|
-
return
|
|
124471
|
+
return "not-repaired";
|
|
124315
124472
|
}
|
|
124316
124473
|
if (hasBlocks)
|
|
124317
|
-
return
|
|
124474
|
+
return "already-ready";
|
|
124318
124475
|
diagnostics?.onRepair(entry.scope, "indexed entry missing block manifest; rebuilding from local envelope");
|
|
124319
124476
|
let envelope;
|
|
124320
124477
|
try {
|
|
@@ -124326,7 +124483,18 @@ async function repairMissingBlockSidecars(storage, logger, record2, entry, diagn
|
|
|
124326
124483
|
collectedAt: entry.collectedAt,
|
|
124327
124484
|
error: error51.message
|
|
124328
124485
|
}, "Bounded block sidecar repair skipped because local envelope is unavailable");
|
|
124329
|
-
|
|
124486
|
+
if (entry.fileId) {
|
|
124487
|
+
diagnostics?.onRepair(entry.scope, "index exists without local payload; removing stale local index entry");
|
|
124488
|
+
const removed = await storage.deleteByFileId(entry.fileId);
|
|
124489
|
+
logger.warn({
|
|
124490
|
+
fileId: entry.fileId,
|
|
124491
|
+
scope: entry.scope,
|
|
124492
|
+
collectedAt: entry.collectedAt,
|
|
124493
|
+
removed
|
|
124494
|
+
}, "Removed stale local index entry missing local envelope");
|
|
124495
|
+
return removed ? "missing-envelope" : "not-repaired";
|
|
124496
|
+
}
|
|
124497
|
+
return "not-repaired";
|
|
124330
124498
|
}
|
|
124331
124499
|
await writeBlockSidecars2(storage, envelope, logger, {
|
|
124332
124500
|
...record2,
|
|
@@ -124334,7 +124502,7 @@ async function repairMissingBlockSidecars(storage, logger, record2, entry, diagn
|
|
|
124334
124502
|
schemaId: entry.schemaId ?? record2.schemaId
|
|
124335
124503
|
}, entry.path, diagnostics);
|
|
124336
124504
|
try {
|
|
124337
|
-
return await storage.hasScopeBlocks(entry.scope, entry.collectedAt);
|
|
124505
|
+
return await storage.hasScopeBlocks(entry.scope, entry.collectedAt) ? "repaired" : "not-repaired";
|
|
124338
124506
|
} catch (error51) {
|
|
124339
124507
|
logger.warn({
|
|
124340
124508
|
fileId: entry.fileId ?? record2.fileId,
|
|
@@ -124342,7 +124510,7 @@ async function repairMissingBlockSidecars(storage, logger, record2, entry, diagn
|
|
|
124342
124510
|
collectedAt: entry.collectedAt,
|
|
124343
124511
|
error: error51.message
|
|
124344
124512
|
}, "Bounded block sidecar repair completed but readiness could not be verified");
|
|
124345
|
-
return
|
|
124513
|
+
return "not-repaired";
|
|
124346
124514
|
}
|
|
124347
124515
|
}
|
|
124348
124516
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendatalabs/personal-server-ts-server",
|
|
3
|
-
"version": "0.0.1-canary.
|
|
3
|
+
"version": "0.0.1-canary.dfa1648",
|
|
4
4
|
"description": "Hono HTTP server for the Vana Personal Server — routes, middleware, composition root",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@hono/node-server": "^1.19.13",
|
|
47
|
-
"@opendatalabs/personal-server-ts-core": "0.0.1-canary.
|
|
48
|
-
"@opendatalabs/personal-server-ts-lite": "0.0.1-canary.
|
|
47
|
+
"@opendatalabs/personal-server-ts-core": "0.0.1-canary.dfa1648",
|
|
48
|
+
"@opendatalabs/personal-server-ts-lite": "0.0.1-canary.dfa1648",
|
|
49
49
|
"@opendatalabs/vana-sdk": "^3.4.1",
|
|
50
50
|
"better-sqlite3": "^12.9.0",
|
|
51
51
|
"hono": "^4.12.18",
|