@elizaos/plugin-relationships 2.0.3-beta.5 → 2.0.3-beta.7
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/dist/actions/entity.d.ts +72 -0
- package/dist/actions/entity.d.ts.map +1 -0
- package/dist/actions/entity.js +312 -0
- package/dist/actions/entity.js.map +1 -0
- package/dist/components/relationships/RelationshipsSpatialView.d.ts +72 -0
- package/dist/components/relationships/RelationshipsSpatialView.d.ts.map +1 -0
- package/dist/components/relationships/RelationshipsSpatialView.js +120 -0
- package/dist/components/relationships/RelationshipsSpatialView.js.map +1 -0
- package/dist/components/relationships/RelationshipsView.d.ts +70 -0
- package/dist/components/relationships/RelationshipsView.d.ts.map +1 -0
- package/dist/components/relationships/RelationshipsView.js +193 -0
- package/dist/components/relationships/RelationshipsView.js.map +1 -0
- package/dist/components/relationships/relationships-view-bundle.d.ts +2 -0
- package/dist/components/relationships/relationships-view-bundle.d.ts.map +1 -0
- package/dist/components/relationships/relationships-view-bundle.js +5 -0
- package/dist/components/relationships/relationships-view-bundle.js.map +1 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +2 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +240 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +49 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +23 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +33 -0
- package/dist/plugin.js.map +1 -0
- package/dist/providers/entity-graph.d.ts +20 -0
- package/dist/providers/entity-graph.d.ts.map +1 -0
- package/dist/providers/entity-graph.js +83 -0
- package/dist/providers/entity-graph.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +21 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +10 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +51 -0
- package/dist/types.js.map +1 -0
- package/dist/views/bundle.js +328 -0
- package/dist/views/bundle.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RelationshipsView — the single GUI/XR data wrapper for the entity /
|
|
3
|
+
* relationship knowledge-graph viewer.
|
|
4
|
+
*
|
|
5
|
+
* It owns the live graph data (the fetcher seam over the two read-only endpoints
|
|
6
|
+
* the personal-assistant routes serve, the quiet background poll, and the
|
|
7
|
+
* wire->display join) and renders the one presentational
|
|
8
|
+
* {@link RelationshipsSpatialView} inside a {@link SpatialSurface}. Omitting the
|
|
9
|
+
* `modality` prop lets `SpatialSurface` auto-detect GUI vs XR, so the SAME
|
|
10
|
+
* component serves both surfaces; the TUI surface renders the same
|
|
11
|
+
* `RelationshipsSpatialView` through the terminal registry (see
|
|
12
|
+
* `../../register-terminal-view.tsx`).
|
|
13
|
+
*
|
|
14
|
+
* Data source (the runtime owns the EntityStore / RelationshipStore persistence;
|
|
15
|
+
* this plugin only reads):
|
|
16
|
+
* GET {base}/api/lifeops/entities -> { entities: EntityWire[] }
|
|
17
|
+
* GET {base}/api/lifeops/relationships -> { relationships: RelationshipWire[] }
|
|
18
|
+
*
|
|
19
|
+
* The graph is read-only: the only owner actions are `add` (route an add-a-person
|
|
20
|
+
* request through the assistant chat — no fabricated people), `retry` (reload
|
|
21
|
+
* after an error), and `open:<id>` (focus an entity from chat). This plugin MUST
|
|
22
|
+
* NOT import from @elizaos/plugin-personal-assistant; the wire DTOs below are
|
|
23
|
+
* declared locally to match the JSON shape PA emits.
|
|
24
|
+
*/
|
|
25
|
+
import type { ReactNode } from "react";
|
|
26
|
+
interface EntityIdentityWire {
|
|
27
|
+
platform: string;
|
|
28
|
+
handle: string;
|
|
29
|
+
displayName?: string;
|
|
30
|
+
verified: boolean;
|
|
31
|
+
confidence: number;
|
|
32
|
+
}
|
|
33
|
+
interface EntityWire {
|
|
34
|
+
entityId: string;
|
|
35
|
+
type: string;
|
|
36
|
+
preferredName: string;
|
|
37
|
+
fullName?: string;
|
|
38
|
+
identities: EntityIdentityWire[];
|
|
39
|
+
}
|
|
40
|
+
interface EntitiesWire {
|
|
41
|
+
entities: EntityWire[];
|
|
42
|
+
}
|
|
43
|
+
interface RelationshipStateWire {
|
|
44
|
+
lastObservedAt?: string;
|
|
45
|
+
lastInteractionAt?: string;
|
|
46
|
+
}
|
|
47
|
+
interface RelationshipWire {
|
|
48
|
+
relationshipId: string;
|
|
49
|
+
fromEntityId: string;
|
|
50
|
+
toEntityId: string;
|
|
51
|
+
type: string;
|
|
52
|
+
metadata?: Record<string, unknown>;
|
|
53
|
+
state: RelationshipStateWire;
|
|
54
|
+
}
|
|
55
|
+
interface RelationshipsWire {
|
|
56
|
+
relationships: RelationshipWire[];
|
|
57
|
+
}
|
|
58
|
+
export interface RelationshipsFetchers {
|
|
59
|
+
fetchEntities: () => Promise<EntitiesWire>;
|
|
60
|
+
fetchRelationships: () => Promise<RelationshipsWire>;
|
|
61
|
+
}
|
|
62
|
+
export interface RelationshipsViewProps {
|
|
63
|
+
/** Owner display name. Accepted for host compatibility; not rendered. */
|
|
64
|
+
ownerName?: string;
|
|
65
|
+
/** Test/host injection seam. Defaults to the real graph GETs. */
|
|
66
|
+
fetchers?: RelationshipsFetchers;
|
|
67
|
+
}
|
|
68
|
+
export declare function RelationshipsView(props?: RelationshipsViewProps): ReactNode;
|
|
69
|
+
export default RelationshipsView;
|
|
70
|
+
//# sourceMappingURL=RelationshipsView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RelationshipsView.d.ts","sourceRoot":"","sources":["../../../src/components/relationships/RelationshipsView.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAkBvC,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,kBAAkB,EAAE,CAAC;CAClC;AAED,UAAU,YAAY;IACpB,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,UAAU,qBAAqB;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,UAAU,gBAAgB;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,EAAE,qBAAqB,CAAC;CAC9B;AAED,UAAU,iBAAiB;IACzB,aAAa,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAMD,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3C,kBAAkB,EAAE,MAAM,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACtD;AAyBD,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AA6HD,wBAAgB,iBAAiB,CAC/B,KAAK,GAAE,sBAA2B,GACjC,SAAS,CA6GX;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { client } from "@elizaos/ui";
|
|
3
|
+
import { SpatialSurface } from "@elizaos/ui/spatial";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { ENTITY_KIND_FILTERS, ENTITY_KIND_LABELS } from "../../types.js";
|
|
6
|
+
import {
|
|
7
|
+
EMPTY_RELATIONSHIPS,
|
|
8
|
+
RelationshipsSpatialView
|
|
9
|
+
} from "./RelationshipsSpatialView.js";
|
|
10
|
+
async function getEntities() {
|
|
11
|
+
const response = await fetch(`${client.getBaseUrl()}/api/lifeops/entities`);
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error(`Entities request failed (${response.status})`);
|
|
14
|
+
}
|
|
15
|
+
return await response.json();
|
|
16
|
+
}
|
|
17
|
+
async function getRelationships() {
|
|
18
|
+
const response = await fetch(
|
|
19
|
+
`${client.getBaseUrl()}/api/lifeops/relationships`
|
|
20
|
+
);
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new Error(`Relationships request failed (${response.status})`);
|
|
23
|
+
}
|
|
24
|
+
return await response.json();
|
|
25
|
+
}
|
|
26
|
+
const defaultFetchers = {
|
|
27
|
+
fetchEntities: getEntities,
|
|
28
|
+
fetchRelationships: getRelationships
|
|
29
|
+
};
|
|
30
|
+
function readCadenceDays(metadata) {
|
|
31
|
+
const value = metadata?.cadenceDays;
|
|
32
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
function readLastContact(state) {
|
|
36
|
+
return state.lastInteractionAt ?? state.lastObservedAt ?? null;
|
|
37
|
+
}
|
|
38
|
+
function formatDate(value) {
|
|
39
|
+
const date = new Date(value);
|
|
40
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
41
|
+
return date.toLocaleDateString(void 0, {
|
|
42
|
+
month: "short",
|
|
43
|
+
day: "numeric",
|
|
44
|
+
year: "numeric"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function edgeMeta(relationship, cadenceDays, lastContact) {
|
|
48
|
+
const parts = [relationship.type];
|
|
49
|
+
if (cadenceDays !== null) parts.push(`every ${cadenceDays}d`);
|
|
50
|
+
if (lastContact) parts.push(`last ${formatDate(lastContact)}`);
|
|
51
|
+
return parts.join(" \xB7 ");
|
|
52
|
+
}
|
|
53
|
+
function mapEdge(relationship, nameById) {
|
|
54
|
+
const cadenceDays = readCadenceDays(relationship.metadata);
|
|
55
|
+
const lastContact = readLastContact(relationship.state);
|
|
56
|
+
return {
|
|
57
|
+
id: relationship.relationshipId,
|
|
58
|
+
toName: nameById.get(relationship.toEntityId) ?? relationship.toEntityId,
|
|
59
|
+
meta: edgeMeta(relationship, cadenceDays, lastContact)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function identityLine(identities) {
|
|
63
|
+
return identities.map((identity) => `${identity.platform}:${identity.handle}`).join(" \xB7 ");
|
|
64
|
+
}
|
|
65
|
+
function buildNodes(entities, relationships) {
|
|
66
|
+
const nameById = new Map(
|
|
67
|
+
entities.map((entity) => [entity.entityId, entity.preferredName])
|
|
68
|
+
);
|
|
69
|
+
const edgesByFrom = /* @__PURE__ */ new Map();
|
|
70
|
+
for (const relationship of relationships) {
|
|
71
|
+
const edge = mapEdge(relationship, nameById);
|
|
72
|
+
const existing = edgesByFrom.get(relationship.fromEntityId);
|
|
73
|
+
if (existing) existing.push(edge);
|
|
74
|
+
else edgesByFrom.set(relationship.fromEntityId, [edge]);
|
|
75
|
+
}
|
|
76
|
+
return entities.map((entity) => ({
|
|
77
|
+
id: entity.entityId,
|
|
78
|
+
kind: entity.type,
|
|
79
|
+
kindLabel: ENTITY_KIND_LABELS[entity.type] ?? entity.type,
|
|
80
|
+
name: entity.preferredName,
|
|
81
|
+
identityLine: identityLine(entity.identities),
|
|
82
|
+
edges: edgesByFrom.get(entity.entityId) ?? []
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
const KIND_FILTERS = ENTITY_KIND_FILTERS.map((kind) => ({
|
|
86
|
+
kind,
|
|
87
|
+
label: ENTITY_KIND_LABELS[kind] ?? kind
|
|
88
|
+
}));
|
|
89
|
+
const RELATIONSHIPS_POLL_INTERVAL_MS = 2e4;
|
|
90
|
+
function requestAddPerson() {
|
|
91
|
+
const send = client.sendChatMessage;
|
|
92
|
+
send?.(
|
|
93
|
+
"Add someone to my relationships graph \u2014 tell me who you'd like to remember."
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function requestOpenEntity(entityId) {
|
|
97
|
+
const send = client.sendChatMessage;
|
|
98
|
+
send?.(`Tell me about ${entityId} in my relationships graph.`);
|
|
99
|
+
}
|
|
100
|
+
function RelationshipsView(props = {}) {
|
|
101
|
+
const fetchers = props.fetchers ?? defaultFetchers;
|
|
102
|
+
const [state, setState] = useState({ kind: "loading" });
|
|
103
|
+
const fetchersRef = useRef(fetchers);
|
|
104
|
+
fetchersRef.current = fetchers;
|
|
105
|
+
const load = useCallback(() => {
|
|
106
|
+
let cancelled = false;
|
|
107
|
+
setState({ kind: "loading" });
|
|
108
|
+
Promise.all([
|
|
109
|
+
fetchersRef.current.fetchEntities(),
|
|
110
|
+
fetchersRef.current.fetchRelationships()
|
|
111
|
+
]).then(([entitiesWire, relationshipsWire]) => {
|
|
112
|
+
if (cancelled) return;
|
|
113
|
+
setState({
|
|
114
|
+
kind: "ready",
|
|
115
|
+
nodes: buildNodes(
|
|
116
|
+
entitiesWire.entities,
|
|
117
|
+
relationshipsWire.relationships
|
|
118
|
+
)
|
|
119
|
+
});
|
|
120
|
+
}).catch((error) => {
|
|
121
|
+
if (cancelled) return;
|
|
122
|
+
setState({
|
|
123
|
+
kind: "error",
|
|
124
|
+
message: error instanceof Error ? error.message : "Could not load relationships."
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
return () => {
|
|
128
|
+
cancelled = true;
|
|
129
|
+
};
|
|
130
|
+
}, []);
|
|
131
|
+
useEffect(() => load(), [load]);
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
const id = setInterval(() => {
|
|
134
|
+
Promise.all([
|
|
135
|
+
fetchersRef.current.fetchEntities(),
|
|
136
|
+
fetchersRef.current.fetchRelationships()
|
|
137
|
+
]).then(([entitiesWire, relationshipsWire]) => {
|
|
138
|
+
setState(
|
|
139
|
+
(prev) => prev.kind === "error" ? prev : {
|
|
140
|
+
kind: "ready",
|
|
141
|
+
nodes: buildNodes(
|
|
142
|
+
entitiesWire.entities,
|
|
143
|
+
relationshipsWire.relationships
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}).catch(() => {
|
|
148
|
+
});
|
|
149
|
+
}, RELATIONSHIPS_POLL_INTERVAL_MS);
|
|
150
|
+
return () => clearInterval(id);
|
|
151
|
+
}, []);
|
|
152
|
+
const snapshot = useMemo(() => {
|
|
153
|
+
if (state.kind === "loading") {
|
|
154
|
+
return { ...EMPTY_RELATIONSHIPS, state: "loading" };
|
|
155
|
+
}
|
|
156
|
+
if (state.kind === "error") {
|
|
157
|
+
return {
|
|
158
|
+
state: "error",
|
|
159
|
+
nodes: [],
|
|
160
|
+
filters: KIND_FILTERS,
|
|
161
|
+
error: state.message
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (state.nodes.length === 0) {
|
|
165
|
+
return { state: "empty", nodes: [], filters: KIND_FILTERS };
|
|
166
|
+
}
|
|
167
|
+
return { state: "ready", nodes: state.nodes, filters: KIND_FILTERS };
|
|
168
|
+
}, [state]);
|
|
169
|
+
const onAction = useCallback(
|
|
170
|
+
(action) => {
|
|
171
|
+
if (action === "retry") {
|
|
172
|
+
load();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (action === "add") {
|
|
176
|
+
requestAddPerson();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (action.startsWith("open:")) {
|
|
180
|
+
requestOpenEntity(action.slice("open:".length));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
[load]
|
|
185
|
+
);
|
|
186
|
+
return /* @__PURE__ */ jsx(SpatialSurface, { children: /* @__PURE__ */ jsx(RelationshipsSpatialView, { snapshot, onAction }) });
|
|
187
|
+
}
|
|
188
|
+
var RelationshipsView_default = RelationshipsView;
|
|
189
|
+
export {
|
|
190
|
+
RelationshipsView,
|
|
191
|
+
RelationshipsView_default as default
|
|
192
|
+
};
|
|
193
|
+
//# sourceMappingURL=RelationshipsView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/relationships/RelationshipsView.tsx"],"sourcesContent":["/**\n * RelationshipsView — the single GUI/XR data wrapper for the entity /\n * relationship knowledge-graph viewer.\n *\n * It owns the live graph data (the fetcher seam over the two read-only endpoints\n * the personal-assistant routes serve, the quiet background poll, and the\n * wire->display join) and renders the one presentational\n * {@link RelationshipsSpatialView} inside a {@link SpatialSurface}. Omitting the\n * `modality` prop lets `SpatialSurface` auto-detect GUI vs XR, so the SAME\n * component serves both surfaces; the TUI surface renders the same\n * `RelationshipsSpatialView` through the terminal registry (see\n * `../../register-terminal-view.tsx`).\n *\n * Data source (the runtime owns the EntityStore / RelationshipStore persistence;\n * this plugin only reads):\n * GET {base}/api/lifeops/entities -> { entities: EntityWire[] }\n * GET {base}/api/lifeops/relationships -> { relationships: RelationshipWire[] }\n *\n * The graph is read-only: the only owner actions are `add` (route an add-a-person\n * request through the assistant chat — no fabricated people), `retry` (reload\n * after an error), and `open:<id>` (focus an entity from chat). This plugin MUST\n * NOT import from @elizaos/plugin-personal-assistant; the wire DTOs below are\n * declared locally to match the JSON shape PA emits.\n */\n\nimport { client } from \"@elizaos/ui\";\nimport { SpatialSurface } from \"@elizaos/ui/spatial\";\nimport type { ReactNode } from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { ENTITY_KIND_FILTERS, ENTITY_KIND_LABELS } from \"../../types.js\";\nimport {\n EMPTY_RELATIONSHIPS,\n type EntityNode,\n type KindFilter,\n type RelationshipEdge,\n type RelationshipsSnapshot,\n RelationshipsSpatialView,\n} from \"./RelationshipsSpatialView.js\";\n\n// ---------------------------------------------------------------------------\n// Wire DTOs — local mirror of the JSON shapes served by the PA graph routes.\n// Never import PA types here; keep this view's contract self-contained and\n// aligned by shape.\n// ---------------------------------------------------------------------------\n\ninterface EntityIdentityWire {\n platform: string;\n handle: string;\n displayName?: string;\n verified: boolean;\n confidence: number;\n}\n\ninterface EntityWire {\n entityId: string;\n type: string;\n preferredName: string;\n fullName?: string;\n identities: EntityIdentityWire[];\n}\n\ninterface EntitiesWire {\n entities: EntityWire[];\n}\n\ninterface RelationshipStateWire {\n lastObservedAt?: string;\n lastInteractionAt?: string;\n}\n\ninterface RelationshipWire {\n relationshipId: string;\n fromEntityId: string;\n toEntityId: string;\n type: string;\n metadata?: Record<string, unknown>;\n state: RelationshipStateWire;\n}\n\ninterface RelationshipsWire {\n relationships: RelationshipWire[];\n}\n\n// ---------------------------------------------------------------------------\n// Fetcher seam — default to two real GETs; tests inject offline fakes.\n// ---------------------------------------------------------------------------\n\nexport interface RelationshipsFetchers {\n fetchEntities: () => Promise<EntitiesWire>;\n fetchRelationships: () => Promise<RelationshipsWire>;\n}\n\nasync function getEntities(): Promise<EntitiesWire> {\n const response = await fetch(`${client.getBaseUrl()}/api/lifeops/entities`);\n if (!response.ok) {\n throw new Error(`Entities request failed (${response.status})`);\n }\n return (await response.json()) as EntitiesWire;\n}\n\nasync function getRelationships(): Promise<RelationshipsWire> {\n const response = await fetch(\n `${client.getBaseUrl()}/api/lifeops/relationships`,\n );\n if (!response.ok) {\n throw new Error(`Relationships request failed (${response.status})`);\n }\n return (await response.json()) as RelationshipsWire;\n}\n\nconst defaultFetchers: RelationshipsFetchers = {\n fetchEntities: getEntities,\n fetchRelationships: getRelationships,\n};\n\nexport interface RelationshipsViewProps {\n /** Owner display name. Accepted for host compatibility; not rendered. */\n ownerName?: string;\n /** Test/host injection seam. Defaults to the real graph GETs. */\n fetchers?: RelationshipsFetchers;\n}\n\n// ---------------------------------------------------------------------------\n// Wire -> display DTO mapping.\n// ---------------------------------------------------------------------------\n\n/** Read the per-edge cadence override (`metadata.cadenceDays`) when present. */\nfunction readCadenceDays(\n metadata: Record<string, unknown> | undefined,\n): number | null {\n const value = metadata?.cadenceDays;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n return null;\n}\n\n/**\n * The last interaction on an edge is the most recent of its two timestamps;\n * `lastInteractionAt` is the canonical contact, `lastObservedAt` the fallback.\n */\nfunction readLastContact(state: RelationshipStateWire): string | null {\n return state.lastInteractionAt ?? state.lastObservedAt ?? null;\n}\n\nfunction formatDate(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return date.toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n\n/** Build the meta line for an edge: type · cadence · last-contact. */\nfunction edgeMeta(\n relationship: RelationshipWire,\n cadenceDays: number | null,\n lastContact: string | null,\n): string {\n const parts: string[] = [relationship.type];\n if (cadenceDays !== null) parts.push(`every ${cadenceDays}d`);\n if (lastContact) parts.push(`last ${formatDate(lastContact)}`);\n return parts.join(\" · \");\n}\n\nfunction mapEdge(\n relationship: RelationshipWire,\n nameById: ReadonlyMap<string, string>,\n): RelationshipEdge {\n const cadenceDays = readCadenceDays(relationship.metadata);\n const lastContact = readLastContact(relationship.state);\n return {\n id: relationship.relationshipId,\n toName: nameById.get(relationship.toEntityId) ?? relationship.toEntityId,\n meta: edgeMeta(relationship, cadenceDays, lastContact),\n };\n}\n\nfunction identityLine(identities: EntityIdentityWire[]): string {\n return identities\n .map((identity) => `${identity.platform}:${identity.handle}`)\n .join(\" · \");\n}\n\n/**\n * Join the entity list with their outbound edges into per-entity nodes. The\n * server returns the full graph; this is a presentation-only fold.\n */\nfunction buildNodes(\n entities: EntityWire[],\n relationships: RelationshipWire[],\n): EntityNode[] {\n const nameById = new Map<string, string>(\n entities.map((entity) => [entity.entityId, entity.preferredName]),\n );\n const edgesByFrom = new Map<string, RelationshipEdge[]>();\n for (const relationship of relationships) {\n const edge = mapEdge(relationship, nameById);\n const existing = edgesByFrom.get(relationship.fromEntityId);\n if (existing) existing.push(edge);\n else edgesByFrom.set(relationship.fromEntityId, [edge]);\n }\n return entities.map((entity) => ({\n id: entity.entityId,\n kind: entity.type,\n kindLabel: ENTITY_KIND_LABELS[entity.type] ?? entity.type,\n name: entity.preferredName,\n identityLine: identityLine(entity.identities),\n edges: edgesByFrom.get(entity.entityId) ?? [],\n }));\n}\n\nconst KIND_FILTERS: KindFilter[] = ENTITY_KIND_FILTERS.map((kind) => ({\n kind,\n label: ENTITY_KIND_LABELS[kind] ?? kind,\n}));\n\n// ---------------------------------------------------------------------------\n// Fetch-driven state machine.\n// ---------------------------------------------------------------------------\n\nconst RELATIONSHIPS_POLL_INTERVAL_MS = 20_000;\n\ntype LoadState =\n | { kind: \"loading\" }\n | { kind: \"error\"; message: string }\n | { kind: \"ready\"; nodes: EntityNode[] };\n\nfunction requestAddPerson(): void {\n // The add-a-person affordance routes through the assistant chat. `client` does\n // not type `sendChatMessage`, so read it through a narrow optional-method view\n // and call it only when present — no fabricated people, best-effort dispatch.\n const send = (client as { sendChatMessage?: (text: string) => void })\n .sendChatMessage;\n send?.(\n \"Add someone to my relationships graph — tell me who you'd like to remember.\",\n );\n}\n\nfunction requestOpenEntity(entityId: string): void {\n const send = (client as { sendChatMessage?: (text: string) => void })\n .sendChatMessage;\n send?.(`Tell me about ${entityId} in my relationships graph.`);\n}\n\nexport function RelationshipsView(\n props: RelationshipsViewProps = {},\n): ReactNode {\n const fetchers = props.fetchers ?? defaultFetchers;\n const [state, setState] = useState<LoadState>({ kind: \"loading\" });\n\n const fetchersRef = useRef(fetchers);\n fetchersRef.current = fetchers;\n\n const load = useCallback(() => {\n let cancelled = false;\n setState({ kind: \"loading\" });\n Promise.all([\n fetchersRef.current.fetchEntities(),\n fetchersRef.current.fetchRelationships(),\n ])\n .then(([entitiesWire, relationshipsWire]) => {\n if (cancelled) return;\n setState({\n kind: \"ready\",\n nodes: buildNodes(\n entitiesWire.entities,\n relationshipsWire.relationships,\n ),\n });\n })\n .catch((error: unknown) => {\n if (cancelled) return;\n setState({\n kind: \"error\",\n message:\n error instanceof Error\n ? error.message\n : \"Could not load relationships.\",\n });\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => load(), [load]);\n\n // Background poll: refresh the graph on an interval without flashing the\n // loading state. Transient poll failures are ignored — the explicit Retry\n // path is what surfaces errors to the user.\n useEffect(() => {\n const id = setInterval(() => {\n Promise.all([\n fetchersRef.current.fetchEntities(),\n fetchersRef.current.fetchRelationships(),\n ])\n .then(([entitiesWire, relationshipsWire]) => {\n setState((prev) =>\n prev.kind === \"error\"\n ? prev\n : {\n kind: \"ready\",\n nodes: buildNodes(\n entitiesWire.entities,\n relationshipsWire.relationships,\n ),\n },\n );\n })\n .catch(() => {});\n }, RELATIONSHIPS_POLL_INTERVAL_MS);\n return () => clearInterval(id);\n }, []);\n\n const snapshot = useMemo<RelationshipsSnapshot>(() => {\n if (state.kind === \"loading\") {\n return { ...EMPTY_RELATIONSHIPS, state: \"loading\" };\n }\n if (state.kind === \"error\") {\n return {\n state: \"error\",\n nodes: [],\n filters: KIND_FILTERS,\n error: state.message,\n };\n }\n if (state.nodes.length === 0) {\n return { state: \"empty\", nodes: [], filters: KIND_FILTERS };\n }\n return { state: \"ready\", nodes: state.nodes, filters: KIND_FILTERS };\n }, [state]);\n\n const onAction = useCallback(\n (action: string) => {\n if (action === \"retry\") {\n load();\n return;\n }\n if (action === \"add\") {\n requestAddPerson();\n return;\n }\n if (action.startsWith(\"open:\")) {\n requestOpenEntity(action.slice(\"open:\".length));\n return;\n }\n },\n [load],\n );\n\n return (\n <SpatialSurface>\n <RelationshipsSpatialView snapshot={snapshot} onAction={onAction} />\n </SpatialSurface>\n );\n}\n\nexport default RelationshipsView;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationships-view-bundle.d.ts","sourceRoot":"","sources":["../../../src/components/relationships/relationships-view-bundle.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/relationships/relationships-view-bundle.ts"],"sourcesContent":["// Vite view-bundle entry. The built bundle (dist/views/bundle.js) exposes the\n// named export `RelationshipsView` the view loader reads via\n// __ELIZA_VIEW_EXPORT__. Kept separate from RelationshipsView.tsx so that file\n// exports only React components and stays Fast-Refresh-compatible in dev.\nexport { RelationshipsView } from \"./RelationshipsView.js\";\n"],"mappings":"AAIA,SAAS,yBAAyB;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/index.ts"],"sourcesContent":["export * from \"./schema.js\";\n"],"mappings":"AAAA,cAAc;","names":[]}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle schema for the relationships knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Backs the `@elizaos/plugin-relationships` plugin. The runtime registers
|
|
5
|
+
* migrations from this schema via the plugin object's `schema` field.
|
|
6
|
+
*
|
|
7
|
+
* Tables:
|
|
8
|
+
* - `entities` — nodes (person/org/place/project/concept)
|
|
9
|
+
* - `relationships` — typed edges between entities
|
|
10
|
+
*
|
|
11
|
+
* NOTE: This is a minimal scaffold. The full LifeOps EntityStore and
|
|
12
|
+
* RelationshipStore (see `plugins/plugin-personal-assistant/src/lifeops/entities/store.ts`
|
|
13
|
+
* and `plugins/plugin-personal-assistant/src/lifeops/relationships/store.ts`) carry
|
|
14
|
+
* richer per-row state (identities array, attributes map, retired status,
|
|
15
|
+
* sentiment trend, …). Migration of those columns lands in a follow-up.
|
|
16
|
+
*/
|
|
17
|
+
export declare const relationshipsSchema: import("drizzle-orm/pg-core").PgSchema<"app_relationships">;
|
|
18
|
+
export declare const entitiesTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
19
|
+
name: "entities";
|
|
20
|
+
schema: "app_relationships";
|
|
21
|
+
columns: {
|
|
22
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
23
|
+
name: "id";
|
|
24
|
+
tableName: "entities";
|
|
25
|
+
dataType: "string";
|
|
26
|
+
columnType: "PgUUID";
|
|
27
|
+
data: string;
|
|
28
|
+
driverParam: string;
|
|
29
|
+
notNull: true;
|
|
30
|
+
hasDefault: true;
|
|
31
|
+
isPrimaryKey: true;
|
|
32
|
+
isAutoincrement: false;
|
|
33
|
+
hasRuntimeDefault: false;
|
|
34
|
+
enumValues: undefined;
|
|
35
|
+
baseColumn: never;
|
|
36
|
+
identity: undefined;
|
|
37
|
+
generated: undefined;
|
|
38
|
+
}, {}, {}>;
|
|
39
|
+
kind: import("drizzle-orm/pg-core").PgColumn<{
|
|
40
|
+
name: "kind";
|
|
41
|
+
tableName: "entities";
|
|
42
|
+
dataType: "string";
|
|
43
|
+
columnType: "PgText";
|
|
44
|
+
data: string;
|
|
45
|
+
driverParam: string;
|
|
46
|
+
notNull: true;
|
|
47
|
+
hasDefault: false;
|
|
48
|
+
isPrimaryKey: false;
|
|
49
|
+
isAutoincrement: false;
|
|
50
|
+
hasRuntimeDefault: false;
|
|
51
|
+
enumValues: [string, ...string[]];
|
|
52
|
+
baseColumn: never;
|
|
53
|
+
identity: undefined;
|
|
54
|
+
generated: undefined;
|
|
55
|
+
}, {}, {}>;
|
|
56
|
+
displayName: import("drizzle-orm/pg-core").PgColumn<{
|
|
57
|
+
name: "display_name";
|
|
58
|
+
tableName: "entities";
|
|
59
|
+
dataType: "string";
|
|
60
|
+
columnType: "PgText";
|
|
61
|
+
data: string;
|
|
62
|
+
driverParam: string;
|
|
63
|
+
notNull: true;
|
|
64
|
+
hasDefault: false;
|
|
65
|
+
isPrimaryKey: false;
|
|
66
|
+
isAutoincrement: false;
|
|
67
|
+
hasRuntimeDefault: false;
|
|
68
|
+
enumValues: [string, ...string[]];
|
|
69
|
+
baseColumn: never;
|
|
70
|
+
identity: undefined;
|
|
71
|
+
generated: undefined;
|
|
72
|
+
}, {}, {}>;
|
|
73
|
+
attrs: import("drizzle-orm/pg-core").PgColumn<{
|
|
74
|
+
name: "attrs";
|
|
75
|
+
tableName: "entities";
|
|
76
|
+
dataType: "json";
|
|
77
|
+
columnType: "PgJsonb";
|
|
78
|
+
data: unknown;
|
|
79
|
+
driverParam: unknown;
|
|
80
|
+
notNull: true;
|
|
81
|
+
hasDefault: true;
|
|
82
|
+
isPrimaryKey: false;
|
|
83
|
+
isAutoincrement: false;
|
|
84
|
+
hasRuntimeDefault: false;
|
|
85
|
+
enumValues: undefined;
|
|
86
|
+
baseColumn: never;
|
|
87
|
+
identity: undefined;
|
|
88
|
+
generated: undefined;
|
|
89
|
+
}, {}, {}>;
|
|
90
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
91
|
+
name: "created_at";
|
|
92
|
+
tableName: "entities";
|
|
93
|
+
dataType: "date";
|
|
94
|
+
columnType: "PgTimestamp";
|
|
95
|
+
data: Date;
|
|
96
|
+
driverParam: string;
|
|
97
|
+
notNull: true;
|
|
98
|
+
hasDefault: true;
|
|
99
|
+
isPrimaryKey: false;
|
|
100
|
+
isAutoincrement: false;
|
|
101
|
+
hasRuntimeDefault: false;
|
|
102
|
+
enumValues: undefined;
|
|
103
|
+
baseColumn: never;
|
|
104
|
+
identity: undefined;
|
|
105
|
+
generated: undefined;
|
|
106
|
+
}, {}, {}>;
|
|
107
|
+
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
108
|
+
name: "updated_at";
|
|
109
|
+
tableName: "entities";
|
|
110
|
+
dataType: "date";
|
|
111
|
+
columnType: "PgTimestamp";
|
|
112
|
+
data: Date;
|
|
113
|
+
driverParam: string;
|
|
114
|
+
notNull: true;
|
|
115
|
+
hasDefault: true;
|
|
116
|
+
isPrimaryKey: false;
|
|
117
|
+
isAutoincrement: false;
|
|
118
|
+
hasRuntimeDefault: false;
|
|
119
|
+
enumValues: undefined;
|
|
120
|
+
baseColumn: never;
|
|
121
|
+
identity: undefined;
|
|
122
|
+
generated: undefined;
|
|
123
|
+
}, {}, {}>;
|
|
124
|
+
};
|
|
125
|
+
dialect: "pg";
|
|
126
|
+
}>;
|
|
127
|
+
export declare const relationshipsTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
128
|
+
name: "relationships";
|
|
129
|
+
schema: "app_relationships";
|
|
130
|
+
columns: {
|
|
131
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
132
|
+
name: "id";
|
|
133
|
+
tableName: "relationships";
|
|
134
|
+
dataType: "string";
|
|
135
|
+
columnType: "PgUUID";
|
|
136
|
+
data: string;
|
|
137
|
+
driverParam: string;
|
|
138
|
+
notNull: true;
|
|
139
|
+
hasDefault: true;
|
|
140
|
+
isPrimaryKey: true;
|
|
141
|
+
isAutoincrement: false;
|
|
142
|
+
hasRuntimeDefault: false;
|
|
143
|
+
enumValues: undefined;
|
|
144
|
+
baseColumn: never;
|
|
145
|
+
identity: undefined;
|
|
146
|
+
generated: undefined;
|
|
147
|
+
}, {}, {}>;
|
|
148
|
+
fromEntityId: import("drizzle-orm/pg-core").PgColumn<{
|
|
149
|
+
name: "from_entity_id";
|
|
150
|
+
tableName: "relationships";
|
|
151
|
+
dataType: "string";
|
|
152
|
+
columnType: "PgUUID";
|
|
153
|
+
data: string;
|
|
154
|
+
driverParam: string;
|
|
155
|
+
notNull: true;
|
|
156
|
+
hasDefault: false;
|
|
157
|
+
isPrimaryKey: false;
|
|
158
|
+
isAutoincrement: false;
|
|
159
|
+
hasRuntimeDefault: false;
|
|
160
|
+
enumValues: undefined;
|
|
161
|
+
baseColumn: never;
|
|
162
|
+
identity: undefined;
|
|
163
|
+
generated: undefined;
|
|
164
|
+
}, {}, {}>;
|
|
165
|
+
toEntityId: import("drizzle-orm/pg-core").PgColumn<{
|
|
166
|
+
name: "to_entity_id";
|
|
167
|
+
tableName: "relationships";
|
|
168
|
+
dataType: "string";
|
|
169
|
+
columnType: "PgUUID";
|
|
170
|
+
data: string;
|
|
171
|
+
driverParam: string;
|
|
172
|
+
notNull: true;
|
|
173
|
+
hasDefault: false;
|
|
174
|
+
isPrimaryKey: false;
|
|
175
|
+
isAutoincrement: false;
|
|
176
|
+
hasRuntimeDefault: false;
|
|
177
|
+
enumValues: undefined;
|
|
178
|
+
baseColumn: never;
|
|
179
|
+
identity: undefined;
|
|
180
|
+
generated: undefined;
|
|
181
|
+
}, {}, {}>;
|
|
182
|
+
kind: import("drizzle-orm/pg-core").PgColumn<{
|
|
183
|
+
name: "kind";
|
|
184
|
+
tableName: "relationships";
|
|
185
|
+
dataType: "string";
|
|
186
|
+
columnType: "PgText";
|
|
187
|
+
data: string;
|
|
188
|
+
driverParam: string;
|
|
189
|
+
notNull: true;
|
|
190
|
+
hasDefault: false;
|
|
191
|
+
isPrimaryKey: false;
|
|
192
|
+
isAutoincrement: false;
|
|
193
|
+
hasRuntimeDefault: false;
|
|
194
|
+
enumValues: [string, ...string[]];
|
|
195
|
+
baseColumn: never;
|
|
196
|
+
identity: undefined;
|
|
197
|
+
generated: undefined;
|
|
198
|
+
}, {}, {}>;
|
|
199
|
+
attrs: import("drizzle-orm/pg-core").PgColumn<{
|
|
200
|
+
name: "attrs";
|
|
201
|
+
tableName: "relationships";
|
|
202
|
+
dataType: "json";
|
|
203
|
+
columnType: "PgJsonb";
|
|
204
|
+
data: unknown;
|
|
205
|
+
driverParam: unknown;
|
|
206
|
+
notNull: true;
|
|
207
|
+
hasDefault: true;
|
|
208
|
+
isPrimaryKey: false;
|
|
209
|
+
isAutoincrement: false;
|
|
210
|
+
hasRuntimeDefault: false;
|
|
211
|
+
enumValues: undefined;
|
|
212
|
+
baseColumn: never;
|
|
213
|
+
identity: undefined;
|
|
214
|
+
generated: undefined;
|
|
215
|
+
}, {}, {}>;
|
|
216
|
+
lastObservedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
217
|
+
name: "last_observed_at";
|
|
218
|
+
tableName: "relationships";
|
|
219
|
+
dataType: "date";
|
|
220
|
+
columnType: "PgTimestamp";
|
|
221
|
+
data: Date;
|
|
222
|
+
driverParam: string;
|
|
223
|
+
notNull: false;
|
|
224
|
+
hasDefault: false;
|
|
225
|
+
isPrimaryKey: false;
|
|
226
|
+
isAutoincrement: false;
|
|
227
|
+
hasRuntimeDefault: false;
|
|
228
|
+
enumValues: undefined;
|
|
229
|
+
baseColumn: never;
|
|
230
|
+
identity: undefined;
|
|
231
|
+
generated: undefined;
|
|
232
|
+
}, {}, {}>;
|
|
233
|
+
};
|
|
234
|
+
dialect: "pg";
|
|
235
|
+
}>;
|
|
236
|
+
export type EntityRow = typeof entitiesTable.$inferSelect;
|
|
237
|
+
export type EntityInsert = typeof entitiesTable.$inferInsert;
|
|
238
|
+
export type RelationshipRow = typeof relationshipsTable.$inferSelect;
|
|
239
|
+
export type RelationshipInsert = typeof relationshipsTable.$inferInsert;
|
|
240
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,6DAAgC,CAAC;AAEjE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBzB,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAe9B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,OAAO,aAAa,CAAC,YAAY,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,OAAO,aAAa,CAAC,YAAY,CAAC;AAC7D,MAAM,MAAM,eAAe,GAAG,OAAO,kBAAkB,CAAC,YAAY,CAAC;AACrE,MAAM,MAAM,kBAAkB,GAAG,OAAO,kBAAkB,CAAC,YAAY,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import {
|
|
3
|
+
index,
|
|
4
|
+
jsonb,
|
|
5
|
+
pgSchema,
|
|
6
|
+
text,
|
|
7
|
+
timestamp,
|
|
8
|
+
uuid
|
|
9
|
+
} from "drizzle-orm/pg-core";
|
|
10
|
+
const relationshipsSchema = pgSchema("app_relationships");
|
|
11
|
+
const entitiesTable = relationshipsSchema.table(
|
|
12
|
+
"entities",
|
|
13
|
+
{
|
|
14
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
15
|
+
kind: text("kind").notNull(),
|
|
16
|
+
displayName: text("display_name").notNull(),
|
|
17
|
+
attrs: jsonb("attrs").default("{}").notNull(),
|
|
18
|
+
createdAt: timestamp("created_at").default(sql`now()`).notNull(),
|
|
19
|
+
updatedAt: timestamp("updated_at").default(sql`now()`).notNull()
|
|
20
|
+
},
|
|
21
|
+
(table) => ({
|
|
22
|
+
kindIdx: index("idx_relationships_entities_kind").on(table.kind),
|
|
23
|
+
displayNameIdx: index("idx_relationships_entities_display_name").on(
|
|
24
|
+
table.displayName
|
|
25
|
+
)
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
const relationshipsTable = relationshipsSchema.table(
|
|
29
|
+
"relationships",
|
|
30
|
+
{
|
|
31
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
32
|
+
fromEntityId: uuid("from_entity_id").notNull(),
|
|
33
|
+
toEntityId: uuid("to_entity_id").notNull(),
|
|
34
|
+
kind: text("kind").notNull(),
|
|
35
|
+
attrs: jsonb("attrs").default("{}").notNull(),
|
|
36
|
+
lastObservedAt: timestamp("last_observed_at")
|
|
37
|
+
},
|
|
38
|
+
(table) => ({
|
|
39
|
+
fromIdx: index("idx_relationships_from").on(table.fromEntityId),
|
|
40
|
+
toIdx: index("idx_relationships_to").on(table.toEntityId),
|
|
41
|
+
kindIdx: index("idx_relationships_kind").on(table.kind)
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
export {
|
|
45
|
+
entitiesTable,
|
|
46
|
+
relationshipsSchema,
|
|
47
|
+
relationshipsTable
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/db/schema.ts"],"sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n index,\n jsonb,\n pgSchema,\n text,\n timestamp,\n uuid,\n} from \"drizzle-orm/pg-core\";\n\n/**\n * Drizzle schema for the relationships knowledge graph.\n *\n * Backs the `@elizaos/plugin-relationships` plugin. The runtime registers\n * migrations from this schema via the plugin object's `schema` field.\n *\n * Tables:\n * - `entities` — nodes (person/org/place/project/concept)\n * - `relationships` — typed edges between entities\n *\n * NOTE: This is a minimal scaffold. The full LifeOps EntityStore and\n * RelationshipStore (see `plugins/plugin-personal-assistant/src/lifeops/entities/store.ts`\n * and `plugins/plugin-personal-assistant/src/lifeops/relationships/store.ts`) carry\n * richer per-row state (identities array, attributes map, retired status,\n * sentiment trend, …). Migration of those columns lands in a follow-up.\n */\nexport const relationshipsSchema = pgSchema(\"app_relationships\");\n\nexport const entitiesTable = relationshipsSchema.table(\n \"entities\",\n {\n id: uuid(\"id\").primaryKey().defaultRandom(),\n kind: text(\"kind\").notNull(),\n displayName: text(\"display_name\").notNull(),\n attrs: jsonb(\"attrs\").default(\"{}\").notNull(),\n createdAt: timestamp(\"created_at\").default(sql`now()`).notNull(),\n updatedAt: timestamp(\"updated_at\").default(sql`now()`).notNull(),\n },\n (table) => ({\n kindIdx: index(\"idx_relationships_entities_kind\").on(table.kind),\n displayNameIdx: index(\"idx_relationships_entities_display_name\").on(\n table.displayName,\n ),\n }),\n);\n\nexport const relationshipsTable = relationshipsSchema.table(\n \"relationships\",\n {\n id: uuid(\"id\").primaryKey().defaultRandom(),\n fromEntityId: uuid(\"from_entity_id\").notNull(),\n toEntityId: uuid(\"to_entity_id\").notNull(),\n kind: text(\"kind\").notNull(),\n attrs: jsonb(\"attrs\").default(\"{}\").notNull(),\n lastObservedAt: timestamp(\"last_observed_at\"),\n },\n (table) => ({\n fromIdx: index(\"idx_relationships_from\").on(table.fromEntityId),\n toIdx: index(\"idx_relationships_to\").on(table.toEntityId),\n kindIdx: index(\"idx_relationships_kind\").on(table.kind),\n }),\n);\n\nexport type EntityRow = typeof entitiesTable.$inferSelect;\nexport type EntityInsert = typeof entitiesTable.$inferInsert;\nexport type RelationshipRow = typeof relationshipsTable.$inferSelect;\nexport type RelationshipInsert = typeof relationshipsTable.$inferInsert;\n"],"mappings":"AAAA,SAAS,WAAW;AACpB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAkBA,MAAM,sBAAsB,SAAS,mBAAmB;AAExD,MAAM,gBAAgB,oBAAoB;AAAA,EAC/C;AAAA,EACA;AAAA,IACE,IAAI,KAAK,IAAI,EAAE,WAAW,EAAE,cAAc;AAAA,IAC1C,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,aAAa,KAAK,cAAc,EAAE,QAAQ;AAAA,IAC1C,OAAO,MAAM,OAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,IAC5C,WAAW,UAAU,YAAY,EAAE,QAAQ,UAAU,EAAE,QAAQ;AAAA,IAC/D,WAAW,UAAU,YAAY,EAAE,QAAQ,UAAU,EAAE,QAAQ;AAAA,EACjE;AAAA,EACA,CAAC,WAAW;AAAA,IACV,SAAS,MAAM,iCAAiC,EAAE,GAAG,MAAM,IAAI;AAAA,IAC/D,gBAAgB,MAAM,yCAAyC,EAAE;AAAA,MAC/D,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,MAAM,qBAAqB,oBAAoB;AAAA,EACpD;AAAA,EACA;AAAA,IACE,IAAI,KAAK,IAAI,EAAE,WAAW,EAAE,cAAc;AAAA,IAC1C,cAAc,KAAK,gBAAgB,EAAE,QAAQ;AAAA,IAC7C,YAAY,KAAK,cAAc,EAAE,QAAQ;AAAA,IACzC,MAAM,KAAK,MAAM,EAAE,QAAQ;AAAA,IAC3B,OAAO,MAAM,OAAO,EAAE,QAAQ,IAAI,EAAE,QAAQ;AAAA,IAC5C,gBAAgB,UAAU,kBAAkB;AAAA,EAC9C;AAAA,EACA,CAAC,WAAW;AAAA,IACV,SAAS,MAAM,wBAAwB,EAAE,GAAG,MAAM,YAAY;AAAA,IAC9D,OAAO,MAAM,sBAAsB,EAAE,GAAG,MAAM,UAAU;AAAA,IACxD,SAAS,MAAM,wBAAwB,EAAE,GAAG,MAAM,IAAI;AAAA,EACxD;AACF;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type { EntityActionParameters } from "./actions/entity.js";
|
|
2
|
+
export { entityAction } from "./actions/entity.js";
|
|
3
|
+
export { EMPTY_RELATIONSHIPS, type EntityNode, type KindFilter, type RelationshipEdge, type RelationshipsSnapshot, RelationshipsSpatialView, type RelationshipsViewState, } from "./components/relationships/RelationshipsSpatialView.js";
|
|
4
|
+
export { RelationshipsView } from "./components/relationships/RelationshipsView.js";
|
|
5
|
+
export { type EntityInsert, type EntityRow, entitiesTable, type RelationshipInsert, type RelationshipRow, relationshipsSchema, relationshipsTable, } from "./db/schema.js";
|
|
6
|
+
export { relationshipsPlugin } from "./plugin.js";
|
|
7
|
+
export { entityGraphProvider } from "./providers/entity-graph.js";
|
|
8
|
+
export { registerRelationshipsTerminalView, setRelationshipsTerminalSnapshot, } from "./register-terminal-view.js";
|
|
9
|
+
export * from "./types.js";
|
|
10
|
+
import { relationshipsPlugin } from "./plugin.js";
|
|
11
|
+
export default relationshipsPlugin;
|
|
12
|
+
import "./register.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,wBAAwB,EACxB,KAAK,sBAAsB,GAC5B,MAAM,wDAAwD,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iDAAiD,CAAC;AACpF,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,iCAAiC,EACjC,gCAAgC,GACjC,MAAM,6BAA6B,CAAC;AACrC,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,eAAe,mBAAmB,CAAC;AAKnC,OAAO,eAAe,CAAC"}
|