or3-provider-sqlite 0.0.14 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -291,6 +291,10 @@ The canonical-history qualification lane defaults to a sibling `../or3-chat` che
|
|
|
291
291
|
|
|
292
292
|
## Workspace Files and Trash admission
|
|
293
293
|
|
|
294
|
+
Persistent Projects uses this same capability for opaque `or3:project-settings`, `or3:project-memory`, and `or3:project-source` posts. Preserve their JSON, metadata, and every original/extraction `file_hashes` reference. The project-aware canonical reader resolves `threads.project_id` or a single legacy membership in its authorized SQLite snapshot, returning `project_ownership: resolved | conflict`. String entries and JSON-encoded membership arrays remain supported; malformed or ambiguous memberships do not grant server execution. Hosts without this result must refuse project-sensitive server admission rather than infer ownership from the visible UI.
|
|
295
|
+
|
|
296
|
+
Version 0.0.15 declares `projectOwnership: 'v1'` on the native canonical-history adapter. D1 does not advertise this contract. Projects qualification: `OR3_PROJECT_HOST_ROOT=/absolute/path/to/or3-chat bun x vitest run src/runtime/__tests__/sqlite-sync-gateway-adapter.test.ts`. This explicit lane uses the host's canonical-reader query contract while retaining the pinned standalone fixture for existing contracts. Qualify the published exact version with the disposable host cloud journey.
|
|
297
|
+
|
|
294
298
|
Native synchronous adapters advertise workspace-item capability v1. Canonical
|
|
295
299
|
posts/projects with catalog, logical Trash, or file-membership semantics require
|
|
296
300
|
a current writer even when the incoming update omits those fields. Admission is
|
package/dist/module.json
CHANGED
|
@@ -17,12 +17,14 @@ export declare class SqliteSyncGatewayAdapter implements SyncGatewayAdapter {
|
|
|
17
17
|
readonly historyRetention: "snapshot-v1";
|
|
18
18
|
readonly backgroundGenerationHistory?: undefined;
|
|
19
19
|
readonly canonicalChatHistory?: undefined;
|
|
20
|
+
readonly projectOwnership?: undefined;
|
|
20
21
|
readonly workspaceItems?: undefined;
|
|
21
22
|
} | {
|
|
22
23
|
readonly snapshotBootstrap: "snapshot-v1";
|
|
23
24
|
readonly historyRetention: "snapshot-v1";
|
|
24
25
|
readonly backgroundGenerationHistory: "v1";
|
|
25
26
|
readonly canonicalChatHistory: "v1";
|
|
27
|
+
readonly projectOwnership: "v1";
|
|
26
28
|
readonly workspaceItems: "v1";
|
|
27
29
|
};
|
|
28
30
|
private get db();
|
|
@@ -433,6 +433,7 @@ export class SqliteSyncGatewayAdapter {
|
|
|
433
433
|
historyRetention: "snapshot-v1",
|
|
434
434
|
backgroundGenerationHistory: "v1",
|
|
435
435
|
canonicalChatHistory: "v1",
|
|
436
|
+
projectOwnership: "v1",
|
|
436
437
|
workspaceItems: "v1"
|
|
437
438
|
};
|
|
438
439
|
}
|
|
@@ -458,7 +459,26 @@ export class SqliteSyncGatewayAdapter {
|
|
|
458
459
|
if (query.kind === "thread") {
|
|
459
460
|
const threadRevision = raw.prepare("SELECT value FROM chat_history_revisions WHERE workspace_id = ? AND thread_id = ?").get(actor.workspaceId, query.thread_id);
|
|
460
461
|
const row = raw.prepare("SELECT id, data_json, clock, deleted FROM s_threads WHERE workspace_id = ? AND id = ?").get(actor.workspaceId, query.thread_id);
|
|
461
|
-
|
|
462
|
+
const thread = row ? parse(row) : void 0;
|
|
463
|
+
if (!thread || thread.project_id) return {
|
|
464
|
+
status: "ok",
|
|
465
|
+
project_ownership: "resolved",
|
|
466
|
+
revision: String(threadRevision?.value ?? 0),
|
|
467
|
+
thread
|
|
468
|
+
};
|
|
469
|
+
const projects = raw.prepare("SELECT id, data_json FROM s_projects WHERE workspace_id = ? AND COALESCE(deleted, 0) = 0").all(actor.workspaceId);
|
|
470
|
+
const owners = projects.filter((project) => {
|
|
471
|
+
const payload = JSON.parse(project.data_json);
|
|
472
|
+
const entries = typeof payload.data === "string" ? JSON.parse(payload.data) : payload.data ?? [];
|
|
473
|
+
if (!Array.isArray(entries)) throw new Error("Canonical project membership is unresolved.");
|
|
474
|
+
return entries.some((entry) => typeof entry === "string" ? entry === query.thread_id : entry && typeof entry === "object" && !Array.isArray(entry) && (entry.kind === void 0 || entry.kind === "chat") && entry.id === query.thread_id);
|
|
475
|
+
});
|
|
476
|
+
return {
|
|
477
|
+
status: "ok",
|
|
478
|
+
project_ownership: owners.length > 1 ? "conflict" : "resolved",
|
|
479
|
+
revision: String(threadRevision?.value ?? 0),
|
|
480
|
+
thread: { ...thread, project_id: owners[0]?.id ?? null }
|
|
481
|
+
};
|
|
462
482
|
}
|
|
463
483
|
if (query.kind === "messages") {
|
|
464
484
|
if (!query.message_ids.length) return { status: "ok", revision, messages: [] };
|