@world-engines/project-host 0.1.0-alpha.0
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/LICENSE +46 -0
- package/assets/gui/WELogo-title.svg +11 -0
- package/assets/gui/app.js +1326 -0
- package/assets/gui/index.html +118 -0
- package/assets/gui/local-preview-asset-urls.js +61 -0
- package/assets/gui/local-preview-bridge.js +393 -0
- package/assets/gui/spatial-template-panel.js +233 -0
- package/assets/gui/styles.css +115 -0
- package/assets/gui/terrain-render.js +120 -0
- package/assets/gui/workspace-status.css +17 -0
- package/assets/gui/workspace-status.js +255 -0
- package/assets/gui/world-map-globe.js +187 -0
- package/assets/gui/world-map-worker.js +62 -0
- package/assets/gui/world-map.css +30 -0
- package/assets/gui/world-map.js +2466 -0
- package/dist/account-model-proxy.d.ts +21 -0
- package/dist/account-model-proxy.js +470 -0
- package/dist/authoring-browser-runtime.d.ts +7 -0
- package/dist/authoring-browser-runtime.js +110 -0
- package/dist/authoring-ingestion.d.ts +38 -0
- package/dist/authoring-ingestion.js +410 -0
- package/dist/authoring-model-connection.d.ts +166 -0
- package/dist/authoring-model-connection.js +757 -0
- package/dist/chinese-lexical.d.ts +152 -0
- package/dist/chinese-lexical.js +555 -0
- package/dist/chromium-preview-browser-driver.d.ts +43 -0
- package/dist/chromium-preview-browser-driver.js +575 -0
- package/dist/cli/download.d.ts +12 -0
- package/dist/cli/download.js +50 -0
- package/dist/cli/dump.d.ts +32 -0
- package/dist/cli/dump.js +91 -0
- package/dist/cli/ingest.d.ts +49 -0
- package/dist/cli/ingest.js +225 -0
- package/dist/cli/review.d.ts +10 -0
- package/dist/cli/review.js +44 -0
- package/dist/cli/upload.d.ts +57 -0
- package/dist/cli/upload.js +112 -0
- package/dist/cli-command.d.ts +60 -0
- package/dist/cli-command.js +613 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +182 -0
- package/dist/desktop-authoring-runtime.d.ts +88 -0
- package/dist/desktop-authoring-runtime.js +1602 -0
- package/dist/desktop-sidecar.d.ts +11 -0
- package/dist/desktop-sidecar.js +143 -0
- package/dist/document-dump.d.ts +113 -0
- package/dist/document-dump.js +431 -0
- package/dist/document-graph-extractor.d.ts +125 -0
- package/dist/document-graph-extractor.js +588 -0
- package/dist/document-ingestion-journal.d.ts +68 -0
- package/dist/document-ingestion-journal.js +471 -0
- package/dist/document-ingestion.d.ts +183 -0
- package/dist/document-ingestion.js +976 -0
- package/dist/document-query-path-proof.d.ts +30 -0
- package/dist/document-query-path-proof.js +34 -0
- package/dist/document-query-path-renderer.d.ts +50 -0
- package/dist/document-query-path-renderer.js +75 -0
- package/dist/document-query-proof-paths.d.ts +22 -0
- package/dist/document-query-proof-paths.js +71 -0
- package/dist/document-query.d.ts +97 -0
- package/dist/document-query.js +1106 -0
- package/dist/document-relation-role.d.ts +14 -0
- package/dist/document-relation-role.js +86 -0
- package/dist/document-source.d.ts +107 -0
- package/dist/document-source.js +255 -0
- package/dist/embedding-cache.d.ts +35 -0
- package/dist/embedding-cache.js +317 -0
- package/dist/frozen-review-local-pipeline.d.ts +88 -0
- package/dist/frozen-review-local-pipeline.js +609 -0
- package/dist/frozen-review-source-capture.d.ts +15 -0
- package/dist/frozen-review-source-capture.js +551 -0
- package/dist/frozen-review-wasm-encryptor.d.ts +16 -0
- package/dist/frozen-review-wasm-encryptor.js +72 -0
- package/dist/frozen-review.d.ts +131 -0
- package/dist/frozen-review.js +802 -0
- package/dist/graph-traversal.d.ts +23 -0
- package/dist/graph-traversal.js +100 -0
- package/dist/gui/graph-layout-worker.js +1 -0
- package/dist/gui/graph-layout.wasm +0 -0
- package/dist/gui/graph.css +1 -0
- package/dist/gui/graph.js +76 -0
- package/dist/gui/plane-generation.js +112 -0
- package/dist/gui/plane-generator.js +310 -0
- package/dist/gui/plane-generator_bg.wasm +0 -0
- package/dist/gui/procedural-city.js +595 -0
- package/dist/gui/road-generation.js +129 -0
- package/dist/gui/road-parcels.js +1584 -0
- package/dist/gui/score.css +1 -0
- package/dist/gui/score.js +54 -0
- package/dist/gui/spatial-runtime.js +1231 -0
- package/dist/gui/spatial-templates.js +200 -0
- package/dist/gui/trigger.css +1 -0
- package/dist/gui/trigger.js +142 -0
- package/dist/harness-callback-transport.d.ts +17 -0
- package/dist/harness-callback-transport.js +128 -0
- package/dist/harness-document-ingestion.d.ts +77 -0
- package/dist/harness-document-ingestion.js +343 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +43 -0
- package/dist/ingestion-source-reconciliation.d.ts +88 -0
- package/dist/ingestion-source-reconciliation.js +253 -0
- package/dist/ladybug-runtime.d.ts +117 -0
- package/dist/ladybug-runtime.js +886 -0
- package/dist/local-account-embedding.d.ts +34 -0
- package/dist/local-account-embedding.js +294 -0
- package/dist/local-gallery.d.ts +35 -0
- package/dist/local-gallery.js +227 -0
- package/dist/local-gui-auth.d.ts +96 -0
- package/dist/local-gui-auth.js +703 -0
- package/dist/local-gui-contract.d.ts +53 -0
- package/dist/local-gui-contract.js +5 -0
- package/dist/local-gui-image-assets.d.ts +17 -0
- package/dist/local-gui-image-assets.js +96 -0
- package/dist/local-gui-preview-client.d.ts +3 -0
- package/dist/local-gui-preview-client.js +111 -0
- package/dist/local-gui-score.d.ts +72 -0
- package/dist/local-gui-score.js +184 -0
- package/dist/local-gui-server.d.ts +10 -0
- package/dist/local-gui-server.js +987 -0
- package/dist/local-gui-version.d.ts +17 -0
- package/dist/local-gui-version.js +147 -0
- package/dist/local-gui-workspace.d.ts +14 -0
- package/dist/local-gui-workspace.js +171 -0
- package/dist/local-model-settings.d.ts +28 -0
- package/dist/local-model-settings.js +124 -0
- package/dist/local-preview-assets.d.ts +28 -0
- package/dist/local-preview-assets.js +124 -0
- package/dist/local-preview-bound-resources.d.ts +12 -0
- package/dist/local-preview-bound-resources.js +80 -0
- package/dist/local-preview-message-store.d.ts +63 -0
- package/dist/local-preview-message-store.js +214 -0
- package/dist/local-preview-player-read-models.d.ts +47 -0
- package/dist/local-preview-player-read-models.js +90 -0
- package/dist/local-preview-projections.d.ts +61 -0
- package/dist/local-preview-projections.js +117 -0
- package/dist/local-preview-runtime.d.ts +105 -0
- package/dist/local-preview-runtime.js +553 -0
- package/dist/local-preview-session.d.ts +73 -0
- package/dist/local-preview-session.js +395 -0
- package/dist/local-preview-source.d.ts +40 -0
- package/dist/local-preview-source.js +192 -0
- package/dist/local-preview-view-events.d.ts +101 -0
- package/dist/local-preview-view-events.js +179 -0
- package/dist/local-preview-view-state-sqlite.d.ts +24 -0
- package/dist/local-preview-view-state-sqlite.js +263 -0
- package/dist/local-preview-view-state.d.ts +93 -0
- package/dist/local-preview-view-state.js +108 -0
- package/dist/local-preview-vite-config.d.ts +6 -0
- package/dist/local-preview-vite-config.js +122 -0
- package/dist/local-preview-world-effects.d.ts +9 -0
- package/dist/local-preview-world-effects.js +55 -0
- package/dist/local-preview-worldline-store.d.ts +47 -0
- package/dist/local-preview-worldline-store.js +282 -0
- package/dist/local-preview-worldlines.d.ts +95 -0
- package/dist/local-preview-worldlines.js +136 -0
- package/dist/mcp-async-dispatcher.d.ts +3 -0
- package/dist/mcp-async-dispatcher.js +129 -0
- package/dist/mcp-line-queue.d.ts +14 -0
- package/dist/mcp-line-queue.js +184 -0
- package/dist/mcp-pipe-internal.d.ts +6 -0
- package/dist/mcp-pipe-internal.js +151 -0
- package/dist/mcp-pipe-response.d.ts +14 -0
- package/dist/mcp-pipe-response.js +50 -0
- package/dist/mcp-stdio-response.d.ts +12 -0
- package/dist/mcp-stdio-response.js +27 -0
- package/dist/mcp.d.ts +27 -0
- package/dist/mcp.js +194 -0
- package/dist/prepared-embedding-cache.d.ts +38 -0
- package/dist/prepared-embedding-cache.js +238 -0
- package/dist/preview-browser-adapter.d.ts +53 -0
- package/dist/preview-browser-adapter.js +171 -0
- package/dist/preview-runtime.d.ts +67 -0
- package/dist/preview-runtime.js +460 -0
- package/dist/project-auth-transport.d.ts +27 -0
- package/dist/project-auth-transport.js +121 -0
- package/dist/project-auth.d.ts +51 -0
- package/dist/project-auth.js +108 -0
- package/dist/project-git-capture-recovery.d.ts +16 -0
- package/dist/project-git-capture-recovery.js +347 -0
- package/dist/project-git-cli.d.ts +5 -0
- package/dist/project-git-cli.js +40 -0
- package/dist/project-git-scenario-source.d.ts +10 -0
- package/dist/project-git-scenario-source.js +240 -0
- package/dist/project-git-view-source.d.ts +13 -0
- package/dist/project-git-view-source.js +134 -0
- package/dist/project-git.d.ts +97 -0
- package/dist/project-git.js +656 -0
- package/dist/project-host.d.ts +59 -0
- package/dist/project-host.js +471 -0
- package/dist/project-writer-lease.d.ts +18 -0
- package/dist/project-writer-lease.js +430 -0
- package/dist/public-error.d.ts +7 -0
- package/dist/public-error.js +61 -0
- package/dist/retrieval-benchmark.d.ts +46 -0
- package/dist/retrieval-benchmark.js +58 -0
- package/dist/safe-project-path.d.ts +8 -0
- package/dist/safe-project-path.js +93 -0
- package/dist/scenario-writer.d.ts +32 -0
- package/dist/scenario-writer.js +191 -0
- package/dist/transfer/download.d.ts +159 -0
- package/dist/transfer/download.js +598 -0
- package/dist/transfer/transport.d.ts +26 -0
- package/dist/transfer/transport.js +1 -0
- package/dist/transfer/upload.d.ts +162 -0
- package/dist/transfer/upload.js +354 -0
- package/dist/transfer-types.d.ts +95 -0
- package/dist/transfer-types.js +1 -0
- package/dist/transfer.d.ts +18 -0
- package/dist/transfer.js +273 -0
- package/dist/trigger-runtime.d.ts +121 -0
- package/dist/trigger-runtime.js +153 -0
- package/dist/vendor/wasm-core/asset-hashes.json +5 -0
- package/dist/vendor/wasm-core/wasm_core.d.ts +490 -0
- package/dist/vendor/wasm-core/wasm_core.js +1 -0
- package/dist/vendor/wasm-core/wasm_core_bg.wasm +0 -0
- package/dist/view-watcher.d.ts +9 -0
- package/dist/view-watcher.js +34 -0
- package/package.json +110 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { LadybugExtractionBatch } from "@world-engines/tmw/natural-language-ingestion";
|
|
2
|
+
type JsonRecord = Record<string, unknown>;
|
|
3
|
+
export type WorldApplyOperation = Readonly<{
|
|
4
|
+
type: "upsert_entity";
|
|
5
|
+
id: string;
|
|
6
|
+
kind: string;
|
|
7
|
+
props: Readonly<JsonRecord>;
|
|
8
|
+
}> | Readonly<{
|
|
9
|
+
type: "delete_entity";
|
|
10
|
+
id: string;
|
|
11
|
+
}> | Readonly<{
|
|
12
|
+
type: "upsert_relation";
|
|
13
|
+
src: string;
|
|
14
|
+
dst: string;
|
|
15
|
+
kind: string;
|
|
16
|
+
props: Readonly<JsonRecord>;
|
|
17
|
+
}> | Readonly<{
|
|
18
|
+
type: "delete_relation";
|
|
19
|
+
src: string;
|
|
20
|
+
dst: string;
|
|
21
|
+
kind: string;
|
|
22
|
+
}>;
|
|
23
|
+
export interface ReconciliationEntity {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly kind: string;
|
|
26
|
+
readonly props: Readonly<JsonRecord>;
|
|
27
|
+
}
|
|
28
|
+
export interface ReconciliationRelation {
|
|
29
|
+
readonly src: string;
|
|
30
|
+
readonly dst: string;
|
|
31
|
+
readonly kind: string;
|
|
32
|
+
readonly props: Readonly<JsonRecord>;
|
|
33
|
+
}
|
|
34
|
+
export interface IngestionSourceSnapshot {
|
|
35
|
+
readonly entities: readonly ReconciliationEntity[];
|
|
36
|
+
readonly relations: readonly ReconciliationRelation[];
|
|
37
|
+
}
|
|
38
|
+
type RelationIdentity = Readonly<{
|
|
39
|
+
src: string;
|
|
40
|
+
dst: string;
|
|
41
|
+
kind: string;
|
|
42
|
+
}>;
|
|
43
|
+
type SeenRevision = Readonly<{
|
|
44
|
+
source_revision: string;
|
|
45
|
+
content_sha256: string;
|
|
46
|
+
batch_id: string;
|
|
47
|
+
}>;
|
|
48
|
+
export interface IngestionSourceMarker {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly currentBatchId: string;
|
|
51
|
+
readonly currentSourceRevision: string;
|
|
52
|
+
readonly currentContentSha256: string;
|
|
53
|
+
readonly factIds: readonly string[];
|
|
54
|
+
readonly entityIds: readonly string[];
|
|
55
|
+
readonly relations: readonly RelationIdentity[];
|
|
56
|
+
readonly seenRevisions: readonly SeenRevision[];
|
|
57
|
+
}
|
|
58
|
+
export type IngestionSourceReconciliation = Readonly<{
|
|
59
|
+
status: "already_committed";
|
|
60
|
+
marker: IngestionSourceMarker;
|
|
61
|
+
operations: readonly WorldApplyOperation[];
|
|
62
|
+
}> | Readonly<{
|
|
63
|
+
status: "apply";
|
|
64
|
+
marker: IngestionSourceMarker;
|
|
65
|
+
operations: readonly WorldApplyOperation[];
|
|
66
|
+
}>;
|
|
67
|
+
export declare const INGESTION_SOURCE_CONTROL_KIND = "world_ingestion_source_control";
|
|
68
|
+
declare function factEntityId(scopeId: string, factId: string): string;
|
|
69
|
+
declare function markerId(scopeId: string, sourceId: string): string;
|
|
70
|
+
export declare const ingestionSourceMarkerId: typeof markerId;
|
|
71
|
+
export declare const ingestionFactEntityId: typeof factEntityId;
|
|
72
|
+
export declare function readIngestionSourceMarker(snapshot: IngestionSourceSnapshot, scopeId: string, sourceId: string): IngestionSourceMarker | null;
|
|
73
|
+
export declare function ingestionSourceReconciliationReadIds(input: Readonly<{
|
|
74
|
+
scopeId: string;
|
|
75
|
+
sourceId: string;
|
|
76
|
+
batch: LadybugExtractionBatch;
|
|
77
|
+
marker: IngestionSourceMarker | null;
|
|
78
|
+
}>): readonly string[];
|
|
79
|
+
export declare function reconcileIngestionSource(input: Readonly<{
|
|
80
|
+
scopeId: string;
|
|
81
|
+
sourceId: string;
|
|
82
|
+
sourceRevision: string;
|
|
83
|
+
batch: LadybugExtractionBatch;
|
|
84
|
+
/** 抽取开始前读取到的 source marker batch;world_apply 仍须使用同一 snapshot 的 project revision CAS。 */
|
|
85
|
+
expectedCurrentBatchId: string | null;
|
|
86
|
+
snapshot: IngestionSourceSnapshot;
|
|
87
|
+
}>): IngestionSourceReconciliation;
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
const MARKER_SCHEMA = "world-ingestion-source-marker.v1";
|
|
2
|
+
const MARKER_KIND = "world_ingestion_source_control";
|
|
3
|
+
export const INGESTION_SOURCE_CONTROL_KIND = MARKER_KIND;
|
|
4
|
+
const MANAGED_ENTITY_PROPS = new Set(["scopeId", "sourceEntityId", "label", "facts", "index_text", "embedding", "ingestion_sources"]);
|
|
5
|
+
const MANAGED_RELATION_PROPS = new Set(["scopeId", "factId", "qualifiers", "confidence", "provenance"]);
|
|
6
|
+
function record(value, code) {
|
|
7
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
8
|
+
throw new Error(code);
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function strings(value, code) {
|
|
12
|
+
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string"))
|
|
13
|
+
throw new Error(code);
|
|
14
|
+
return Object.freeze([...new Set(value)].sort());
|
|
15
|
+
}
|
|
16
|
+
function relationIdentity(value) {
|
|
17
|
+
const relation = record(value, "authoring_ingestion_source_marker_invalid");
|
|
18
|
+
if (typeof relation.src !== "string" || typeof relation.dst !== "string" || typeof relation.kind !== "string") {
|
|
19
|
+
throw new Error("authoring_ingestion_source_marker_invalid");
|
|
20
|
+
}
|
|
21
|
+
return Object.freeze({ src: relation.src, dst: relation.dst, kind: relation.kind });
|
|
22
|
+
}
|
|
23
|
+
function relationKey(value) {
|
|
24
|
+
return JSON.stringify([value.src, value.dst, value.kind]);
|
|
25
|
+
}
|
|
26
|
+
function sortedRelations(values) {
|
|
27
|
+
return Object.freeze([...new Map(values.map((value) => [relationKey(value), value])).values()]
|
|
28
|
+
.sort((left, right) => relationKey(left).localeCompare(relationKey(right))));
|
|
29
|
+
}
|
|
30
|
+
function factEntityId(scopeId, factId) {
|
|
31
|
+
return `${scopeId}:world-fact:${factId}`;
|
|
32
|
+
}
|
|
33
|
+
function markerId(scopeId, sourceId) {
|
|
34
|
+
return `world-ingestion-source:${encodeURIComponent(scopeId)}:${encodeURIComponent(sourceId)}`;
|
|
35
|
+
}
|
|
36
|
+
export const ingestionSourceMarkerId = markerId;
|
|
37
|
+
export const ingestionFactEntityId = factEntityId;
|
|
38
|
+
function factFrom(value) {
|
|
39
|
+
const fact = record(value, "authoring_ingestion_fact_invalid");
|
|
40
|
+
if (typeof fact.factId !== "string" || typeof fact.scopeId !== "string" || !Array.isArray(fact.provenance)) {
|
|
41
|
+
throw new Error("authoring_ingestion_fact_invalid");
|
|
42
|
+
}
|
|
43
|
+
return fact;
|
|
44
|
+
}
|
|
45
|
+
function factsFromBatch(batch, scopeId, sourceId) {
|
|
46
|
+
const facts = new Map();
|
|
47
|
+
for (const entity of batch.entities) {
|
|
48
|
+
const values = entity.props.facts;
|
|
49
|
+
if (!Array.isArray(values))
|
|
50
|
+
continue;
|
|
51
|
+
for (const value of values) {
|
|
52
|
+
const fact = factFrom(value);
|
|
53
|
+
if (fact.scopeId !== scopeId || !fact.provenance.some((entry) => entry.sourceId === sourceId)) {
|
|
54
|
+
throw new Error("authoring_ingestion_source_fact_mismatch");
|
|
55
|
+
}
|
|
56
|
+
facts.set(fact.factId, fact);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return Object.freeze([...facts.values()].sort((left, right) => left.factId.localeCompare(right.factId)));
|
|
60
|
+
}
|
|
61
|
+
function uniqueProvenance(facts) {
|
|
62
|
+
const values = facts.flatMap((fact) => fact.provenance);
|
|
63
|
+
return Object.freeze([...new Map(values.map((value) => [JSON.stringify(value), value])).values()]
|
|
64
|
+
.sort((left, right) => left.sourceId.localeCompare(right.sourceId)
|
|
65
|
+
|| left.startOffset - right.startOffset || left.endOffset - right.endOffset));
|
|
66
|
+
}
|
|
67
|
+
function withoutSource(fact, sourceId) {
|
|
68
|
+
const provenance = fact.provenance.filter((entry) => entry.sourceId !== sourceId);
|
|
69
|
+
return provenance.length === 0 ? null : Object.freeze({ ...fact, provenance: Object.freeze(provenance) });
|
|
70
|
+
}
|
|
71
|
+
function mergeFact(existing, incoming) {
|
|
72
|
+
if (existing === null)
|
|
73
|
+
return incoming;
|
|
74
|
+
return Object.freeze({ ...incoming, confidence: Math.max(existing.confidence, incoming.confidence), provenance: uniqueProvenance([existing, incoming]) });
|
|
75
|
+
}
|
|
76
|
+
function renderedFact(fact) {
|
|
77
|
+
const object = fact.object.type === "entity" ? fact.object.value.label
|
|
78
|
+
: fact.object.type === "json" ? JSON.stringify(fact.object.value) : String(fact.object.value);
|
|
79
|
+
return `${fact.subject.label}\n${fact.predicate}: ${object}`;
|
|
80
|
+
}
|
|
81
|
+
function markerFromEntity(entity, scopeId, sourceId) {
|
|
82
|
+
if (entity === undefined)
|
|
83
|
+
return null;
|
|
84
|
+
if (entity.kind !== MARKER_KIND)
|
|
85
|
+
throw new Error("authoring_ingestion_source_marker_conflict");
|
|
86
|
+
const props = entity.props;
|
|
87
|
+
if (props.schema !== MARKER_SCHEMA || props.scope_id !== scopeId || props.source_id !== sourceId
|
|
88
|
+
|| typeof props.current_batch_id !== "string" || typeof props.current_source_revision !== "string"
|
|
89
|
+
|| typeof props.current_content_sha256 !== "string" || !Array.isArray(props.relations)
|
|
90
|
+
|| !Array.isArray(props.seen_revisions))
|
|
91
|
+
throw new Error("authoring_ingestion_source_marker_invalid");
|
|
92
|
+
const seenRevisions = props.seen_revisions.map((value) => {
|
|
93
|
+
const seen = record(value, "authoring_ingestion_source_marker_invalid");
|
|
94
|
+
if (typeof seen.source_revision !== "string" || typeof seen.content_sha256 !== "string" || typeof seen.batch_id !== "string") {
|
|
95
|
+
throw new Error("authoring_ingestion_source_marker_invalid");
|
|
96
|
+
}
|
|
97
|
+
return Object.freeze({ source_revision: seen.source_revision, content_sha256: seen.content_sha256, batch_id: seen.batch_id });
|
|
98
|
+
});
|
|
99
|
+
return Object.freeze({
|
|
100
|
+
id: entity.id,
|
|
101
|
+
currentBatchId: props.current_batch_id,
|
|
102
|
+
currentSourceRevision: props.current_source_revision,
|
|
103
|
+
currentContentSha256: props.current_content_sha256,
|
|
104
|
+
factIds: strings(props.fact_ids, "authoring_ingestion_source_marker_invalid"),
|
|
105
|
+
entityIds: strings(props.entity_ids, "authoring_ingestion_source_marker_invalid"),
|
|
106
|
+
relations: sortedRelations(props.relations.map(relationIdentity)),
|
|
107
|
+
seenRevisions: Object.freeze(seenRevisions),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export function readIngestionSourceMarker(snapshot, scopeId, sourceId) {
|
|
111
|
+
const id = markerId(scopeId, sourceId);
|
|
112
|
+
return markerFromEntity(snapshot.entities.find((entity) => entity.id === id), scopeId, sourceId);
|
|
113
|
+
}
|
|
114
|
+
export function ingestionSourceReconciliationReadIds(input) {
|
|
115
|
+
const facts = factsFromBatch(input.batch, input.scopeId, input.sourceId);
|
|
116
|
+
return Object.freeze([...new Set([
|
|
117
|
+
markerId(input.scopeId, input.sourceId),
|
|
118
|
+
...(input.marker?.entityIds ?? []),
|
|
119
|
+
...(input.marker?.factIds.map((factId) => factEntityId(input.scopeId, factId)) ?? []),
|
|
120
|
+
...input.batch.entities.map((entity) => entity.id),
|
|
121
|
+
...facts.map((fact) => factEntityId(input.scopeId, fact.factId)),
|
|
122
|
+
])].sort());
|
|
123
|
+
}
|
|
124
|
+
function hasUnmanagedProps(props, managed) {
|
|
125
|
+
return Object.keys(props).some((key) => !managed.has(key));
|
|
126
|
+
}
|
|
127
|
+
function mergeEntityFacts(existing, incoming, sourceId) {
|
|
128
|
+
const merged = new Map();
|
|
129
|
+
const previous = existing?.props.facts;
|
|
130
|
+
if (Array.isArray(previous))
|
|
131
|
+
for (const value of previous) {
|
|
132
|
+
const retained = withoutSource(factFrom(value), sourceId);
|
|
133
|
+
if (retained !== null)
|
|
134
|
+
merged.set(retained.factId, retained);
|
|
135
|
+
}
|
|
136
|
+
const next = incoming?.props.facts;
|
|
137
|
+
if (Array.isArray(next))
|
|
138
|
+
for (const value of next) {
|
|
139
|
+
const fact = factFrom(value);
|
|
140
|
+
merged.set(fact.factId, mergeFact(merged.get(fact.factId) ?? null, fact));
|
|
141
|
+
}
|
|
142
|
+
return Object.freeze([...merged.values()].sort((left, right) => left.factId.localeCompare(right.factId)));
|
|
143
|
+
}
|
|
144
|
+
function markerEntity(marker, scopeId, sourceId) {
|
|
145
|
+
return Object.freeze({
|
|
146
|
+
type: "upsert_entity",
|
|
147
|
+
id: marker.id,
|
|
148
|
+
kind: MARKER_KIND,
|
|
149
|
+
props: Object.freeze({
|
|
150
|
+
schema: MARKER_SCHEMA,
|
|
151
|
+
scope_id: scopeId,
|
|
152
|
+
source_id: sourceId,
|
|
153
|
+
current_batch_id: marker.currentBatchId,
|
|
154
|
+
current_source_revision: marker.currentSourceRevision,
|
|
155
|
+
current_content_sha256: marker.currentContentSha256,
|
|
156
|
+
fact_ids: marker.factIds,
|
|
157
|
+
entity_ids: marker.entityIds,
|
|
158
|
+
relations: marker.relations,
|
|
159
|
+
seen_revisions: marker.seenRevisions,
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
export function reconcileIngestionSource(input) {
|
|
164
|
+
if (input.batch.source.sourceId !== input.sourceId)
|
|
165
|
+
throw new Error("authoring_ingestion_source_batch_mismatch");
|
|
166
|
+
const current = readIngestionSourceMarker(input.snapshot, input.scopeId, input.sourceId);
|
|
167
|
+
if (current?.currentBatchId === input.batch.batchId)
|
|
168
|
+
return Object.freeze({ status: "already_committed", marker: current, operations: Object.freeze([]) });
|
|
169
|
+
if (current?.seenRevisions.some((seen) => seen.batch_id === input.batch.batchId))
|
|
170
|
+
throw new Error("authoring_ingestion_source_revision_stale");
|
|
171
|
+
const seenRevision = current?.seenRevisions.find((seen) => seen.source_revision === input.sourceRevision);
|
|
172
|
+
if (seenRevision !== undefined) {
|
|
173
|
+
if (seenRevision.content_sha256 !== input.batch.source.contentSha256)
|
|
174
|
+
throw new Error("authoring_ingestion_source_revision_conflict");
|
|
175
|
+
throw new Error("authoring_ingestion_source_revision_stale");
|
|
176
|
+
}
|
|
177
|
+
if ((current?.currentBatchId ?? null) !== input.expectedCurrentBatchId)
|
|
178
|
+
throw new Error("authoring_ingestion_source_snapshot_stale");
|
|
179
|
+
const incomingFacts = factsFromBatch(input.batch, input.scopeId, input.sourceId);
|
|
180
|
+
const incomingFactIds = incomingFacts.map((fact) => fact.factId);
|
|
181
|
+
const incomingEntityIds = input.batch.entities.map((entity) => entity.id).sort();
|
|
182
|
+
const incomingRelations = sortedRelations(input.batch.relations);
|
|
183
|
+
const entityById = new Map(input.snapshot.entities.map((entity) => [entity.id, entity]));
|
|
184
|
+
const incomingEntityById = new Map(input.batch.entities.map((entity) => [entity.id, entity]));
|
|
185
|
+
const incomingFactById = new Map(incomingFacts.map((fact) => [fact.factId, fact]));
|
|
186
|
+
const operations = [];
|
|
187
|
+
for (const factId of [...new Set([...(current?.factIds ?? []), ...incomingFactIds])].sort()) {
|
|
188
|
+
const id = factEntityId(input.scopeId, factId);
|
|
189
|
+
const existing = entityById.get(id);
|
|
190
|
+
const existingFact = existing === undefined ? null : withoutSource(factFrom(existing.props.fact), input.sourceId);
|
|
191
|
+
const incoming = incomingFactById.get(factId);
|
|
192
|
+
const merged = incoming === undefined ? existingFact : mergeFact(existingFact, incoming);
|
|
193
|
+
if (merged === null)
|
|
194
|
+
operations.push(Object.freeze({ type: "delete_entity", id }));
|
|
195
|
+
else
|
|
196
|
+
operations.push(Object.freeze({ type: "upsert_entity", id, kind: "world_fact", props: Object.freeze({ ...(existing?.props ?? {}), scope_id: input.scopeId, fact_id: factId, fact: merged, index_text: renderedFact(merged) }) }));
|
|
197
|
+
}
|
|
198
|
+
for (const id of [...new Set([...(current?.entityIds ?? []), ...incomingEntityIds])].sort()) {
|
|
199
|
+
const existing = entityById.get(id);
|
|
200
|
+
const incoming = incomingEntityById.get(id);
|
|
201
|
+
const facts = mergeEntityFacts(existing, incoming, input.sourceId);
|
|
202
|
+
const owners = new Set(strings(existing?.props.ingestion_sources ?? [], "authoring_ingestion_entity_sources_invalid"));
|
|
203
|
+
owners.delete(input.sourceId);
|
|
204
|
+
if (incoming !== undefined)
|
|
205
|
+
owners.add(input.sourceId);
|
|
206
|
+
if (incoming === undefined && facts.length === 0 && owners.size === 0 && existing !== undefined && !hasUnmanagedProps(existing.props, MANAGED_ENTITY_PROPS)) {
|
|
207
|
+
operations.push(Object.freeze({ type: "delete_entity", id }));
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (incoming === undefined && existing === undefined)
|
|
211
|
+
continue;
|
|
212
|
+
const base = existing?.props ?? {};
|
|
213
|
+
const incomingProps = incoming?.props ?? {};
|
|
214
|
+
operations.push(Object.freeze({
|
|
215
|
+
type: "upsert_entity", id, kind: incoming?.kind ?? existing.kind,
|
|
216
|
+
props: Object.freeze({ ...base, ...incomingProps, facts, ingestion_sources: Object.freeze([...owners].sort()),
|
|
217
|
+
...(incoming === undefined ? {} : { index_text: incoming.text, ...(incoming.embedding === undefined ? {} : { embedding: incoming.embedding }) }) }),
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
const relationByKey = new Map(input.snapshot.relations.map((relation) => [relationKey(relation), relation]));
|
|
221
|
+
const incomingRelationByKey = new Map(input.batch.relations.map((relation) => [relationKey(relation), relation]));
|
|
222
|
+
for (const identity of sortedRelations([...(current?.relations ?? []), ...incomingRelations])) {
|
|
223
|
+
const existing = relationByKey.get(relationKey(identity));
|
|
224
|
+
const incoming = incomingRelationByKey.get(relationKey(identity));
|
|
225
|
+
const existingProvenance = Array.isArray(existing?.props.provenance) ? existing.props.provenance.map((value) => record(value, "authoring_ingestion_relation_provenance_invalid")) : [];
|
|
226
|
+
const retained = existingProvenance.filter((value) => value.sourceId !== input.sourceId);
|
|
227
|
+
const next = Array.isArray(incoming?.props.provenance) ? incoming.props.provenance.map((value) => record(value, "authoring_ingestion_relation_provenance_invalid")) : [];
|
|
228
|
+
const provenance = [...new Map([...retained, ...next].map((value) => [JSON.stringify(value), value])).values()];
|
|
229
|
+
if (incoming === undefined && provenance.length === 0 && existing !== undefined && !hasUnmanagedProps(existing.props, MANAGED_RELATION_PROPS)) {
|
|
230
|
+
operations.unshift(Object.freeze({ type: "delete_relation", ...identity }));
|
|
231
|
+
}
|
|
232
|
+
else if (incoming !== undefined || existing !== undefined) {
|
|
233
|
+
operations.push(Object.freeze({ type: "upsert_relation", ...identity, props: Object.freeze({ ...(existing?.props ?? {}), ...(incoming?.props ?? {}), provenance: Object.freeze(provenance) }) }));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const seenRevisions = Object.freeze([...(current?.seenRevisions ?? []), Object.freeze({
|
|
237
|
+
source_revision: input.sourceRevision,
|
|
238
|
+
content_sha256: input.batch.source.contentSha256,
|
|
239
|
+
batch_id: input.batch.batchId,
|
|
240
|
+
})]);
|
|
241
|
+
const marker = Object.freeze({
|
|
242
|
+
id: markerId(input.scopeId, input.sourceId),
|
|
243
|
+
currentBatchId: input.batch.batchId,
|
|
244
|
+
currentSourceRevision: input.sourceRevision,
|
|
245
|
+
currentContentSha256: input.batch.source.contentSha256,
|
|
246
|
+
factIds: Object.freeze(incomingFactIds),
|
|
247
|
+
entityIds: Object.freeze(incomingEntityIds),
|
|
248
|
+
relations: incomingRelations,
|
|
249
|
+
seenRevisions,
|
|
250
|
+
});
|
|
251
|
+
operations.push(markerEntity(marker, input.scopeId, input.sourceId));
|
|
252
|
+
return Object.freeze({ status: "apply", marker, operations: Object.freeze(operations) });
|
|
253
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { LadybugExtractionBatch, LadybugSourceProvenance } from "@world-engines/protocol-ts";
|
|
2
|
+
export type { LadybugExtractedEntity, LadybugExtractedRelation, LadybugExtractionBatch, LadybugSourceProvenance, } from "@world-engines/protocol-ts";
|
|
3
|
+
type JsonObject = Readonly<Record<string, unknown>>;
|
|
4
|
+
/**
|
|
5
|
+
* embedding 是独立 provider capability。实现可以调用本地或远端真实模型,
|
|
6
|
+
* 但不得在失败时返回 hash/random/零向量等替代品。
|
|
7
|
+
*/
|
|
8
|
+
export interface LadybugEmbeddingPort {
|
|
9
|
+
readonly providerId: string;
|
|
10
|
+
readonly modelId: string;
|
|
11
|
+
readonly dimensions: number;
|
|
12
|
+
embed(texts: readonly string[], options?: Readonly<{
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
inputKind?: "document" | "query";
|
|
15
|
+
}>): Promise<readonly (readonly number[])[]>;
|
|
16
|
+
}
|
|
17
|
+
export type LadybugRecallMode = "keyword" | "semantic" | "hybrid";
|
|
18
|
+
export type LadybugRecallRequest = Readonly<{
|
|
19
|
+
queryText: string;
|
|
20
|
+
mode: LadybugRecallMode;
|
|
21
|
+
scopeId?: string;
|
|
22
|
+
topK?: number;
|
|
23
|
+
/** 可由调用方显式给出;未给出时只能由配置的真实 provider 生成。 */
|
|
24
|
+
queryEmbedding?: readonly number[];
|
|
25
|
+
/** cosine distance 上限;超过即视为无关项,不以 topK 强行补齐。 */
|
|
26
|
+
maxVectorDistance?: number;
|
|
27
|
+
}>;
|
|
28
|
+
export type LadybugRecallHit = Readonly<{
|
|
29
|
+
id: string;
|
|
30
|
+
kind: string;
|
|
31
|
+
scopeId: string | null;
|
|
32
|
+
text: string;
|
|
33
|
+
props: JsonObject;
|
|
34
|
+
score: number;
|
|
35
|
+
channels: readonly ("keyword" | "semantic")[];
|
|
36
|
+
sources: readonly LadybugSourceProvenance[];
|
|
37
|
+
}>;
|
|
38
|
+
export type LadybugTraverseRequest = Readonly<{
|
|
39
|
+
startIds: readonly string[];
|
|
40
|
+
scopeId?: string;
|
|
41
|
+
direction?: "out" | "in" | "both";
|
|
42
|
+
maxHops?: number;
|
|
43
|
+
relationKinds?: readonly string[];
|
|
44
|
+
maxPaths?: number;
|
|
45
|
+
nodeBudget?: number;
|
|
46
|
+
semanticOnly?: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
export type LadybugTraverseEdge = Readonly<{
|
|
49
|
+
src: string;
|
|
50
|
+
dst: string;
|
|
51
|
+
kind: string;
|
|
52
|
+
props: JsonObject;
|
|
53
|
+
sources: readonly LadybugSourceProvenance[];
|
|
54
|
+
}>;
|
|
55
|
+
export type LadybugTraversePath = Readonly<{
|
|
56
|
+
nodeIds: readonly string[];
|
|
57
|
+
edges: readonly LadybugTraverseEdge[];
|
|
58
|
+
}>;
|
|
59
|
+
export type LadybugTraverseResult = Readonly<{
|
|
60
|
+
paths: readonly LadybugTraversePath[];
|
|
61
|
+
visitedNodeIds: readonly string[];
|
|
62
|
+
truncated: boolean;
|
|
63
|
+
}>;
|
|
64
|
+
export type LadybugGraphSnapshotRequest = Readonly<{
|
|
65
|
+
scopeId?: string;
|
|
66
|
+
}>;
|
|
67
|
+
export type LadybugGraphSnapshotNode = Readonly<{
|
|
68
|
+
id: string;
|
|
69
|
+
kind: string;
|
|
70
|
+
scopeId: string | null;
|
|
71
|
+
props: JsonObject;
|
|
72
|
+
}>;
|
|
73
|
+
export type LadybugGraphSnapshotEdge = Readonly<{
|
|
74
|
+
src: string;
|
|
75
|
+
dst: string;
|
|
76
|
+
kind: string;
|
|
77
|
+
props: JsonObject;
|
|
78
|
+
}>;
|
|
79
|
+
export type LadybugGraphSnapshot = Readonly<{
|
|
80
|
+
nodes: readonly LadybugGraphSnapshotNode[];
|
|
81
|
+
edges: readonly LadybugGraphSnapshotEdge[];
|
|
82
|
+
nodeCount: number;
|
|
83
|
+
edgeCount: number;
|
|
84
|
+
}>;
|
|
85
|
+
export type LadybugIngestReceipt = Readonly<{
|
|
86
|
+
batchId: string;
|
|
87
|
+
entityCount: number;
|
|
88
|
+
relationCount: number;
|
|
89
|
+
statePath: string;
|
|
90
|
+
}>;
|
|
91
|
+
export declare const LADYBUG_WORLD_FACT_QUERY_PROFILE_ID: "world-fact-query/zh-v1";
|
|
92
|
+
export declare const DEFAULT_LADYBUG_MAX_VECTOR_DISTANCE = 0.5;
|
|
93
|
+
/** 仅编码一条查询;corpus 向量由显式准备流程负责,不由该 seam 补齐。 */
|
|
94
|
+
export declare function embedLadybugQuery(port: LadybugEmbeddingPort, text: string): Promise<readonly number[]>;
|
|
95
|
+
export declare function normalizeLadybugGraphSnapshotProps(props: Readonly<Record<string, unknown>>): Record<string, unknown>;
|
|
96
|
+
/** 兼容并行接线中的旧名称;唯一实现仍由 normalizeLadybugGraphSnapshotProps 持有。 */
|
|
97
|
+
export declare const ladybugGraphSnapshotProps: typeof normalizeLadybugGraphSnapshotProps;
|
|
98
|
+
/**
|
|
99
|
+
* LocalProjectHost 可消费的独立 Ladybug runtime。
|
|
100
|
+
* JSON 文件是可重建 projection checkpoint;每次 open 都把它装入真实 LadybugDB 并创建 FTS/HNSW 索引。
|
|
101
|
+
*/
|
|
102
|
+
export declare class LadybugProjectRuntime {
|
|
103
|
+
#private;
|
|
104
|
+
private constructor();
|
|
105
|
+
static open(options: {
|
|
106
|
+
directory: string;
|
|
107
|
+
dimensions: number;
|
|
108
|
+
embeddingPort?: LadybugEmbeddingPort;
|
|
109
|
+
/** shared 仅供已有进程级 Ladybug owner 使用;默认由最后一个 runtime.close 终止 worker。 */
|
|
110
|
+
workerLifecycle?: "owned" | "shared";
|
|
111
|
+
}): Promise<LadybugProjectRuntime>;
|
|
112
|
+
close(): Promise<void>;
|
|
113
|
+
ingest(batch: LadybugExtractionBatch): Promise<LadybugIngestReceipt>;
|
|
114
|
+
recall(request: LadybugRecallRequest): Promise<LadybugRecallHit[]>;
|
|
115
|
+
traverse(request: LadybugTraverseRequest): Promise<LadybugTraverseResult>;
|
|
116
|
+
readGraphSnapshot(request?: LadybugGraphSnapshotRequest): Promise<LadybugGraphSnapshot>;
|
|
117
|
+
}
|