widgettdc-api / scripts /run_trigger_like.mjs
Kraft102's picture
fix: sql.js Docker/Alpine compatibility layer for PatternMemory and FailureMemory
5a81b95
import { EmailIngestor } from '../apps/backend/src/services/ingestors/EmailIngestor.js';
import { CalendarIngestor } from '../apps/backend/src/services/ingestors/CalendarIngestor.js';
import { neo4jAdapter } from '../apps/backend/src/adapters/Neo4jAdapter.js';
import { randomUUID } from 'crypto';
import fs from 'fs';
import path from 'path';
const loadEnvIfNeeded = () => {
if (process.env.NEO4J_URI && process.env.NEO4J_USERNAME && process.env.NEO4J_PASSWORD) return;
const envPath = path.join(process.cwd(), 'apps', 'backend', '.env');
if (fs.existsSync(envPath)) {
const lines = fs.readFileSync(envPath, 'utf-8').split(/\r?\n/);
for (const line of lines) {
const m = line.match(/^([A-Z0-9_]+)=(.*)$/);
if (m) {
const [, k, v] = m;
if (!process.env[k]) process.env[k] = v;
}
}
}
};
const persistNodes = async (nodes) => {
const persisted = [];
for (const node of nodes) {
const labels = (node.labels?.length ? node.labels : ['Private']).map((l) =>
l.replace(/[^A-Za-z0-9_]/g, '')
);
const labelString = labels.map((l) => `:${l}`).join('');
const props = { ...(node.properties || {}) };
if (!props.externalId) props.externalId = randomUUID();
if (node.ownerUid) {
props.belongsTo = node.ownerUid;
if (!labels.includes('Private')) labels.push('Private');
}
const cypher = `
MERGE (n${labelString} {externalId: $props.externalId})
SET n += $props
WITH n, $ownerUid AS ownerUid
OPTIONAL MATCH (u:User {uid: ownerUid})
WITH n, ownerUid, u
FOREACH (_ IN CASE WHEN ownerUid IS NULL THEN [] ELSE [1] END |
MERGE (u:User {uid: ownerUid})
ON CREATE SET u.name = 'Claus', u.role = 'Executive', u.access_level = 'god_mode'
MERGE (n)-[:BELONGS_TO]->(u)
)
RETURN n.externalId AS externalId
`;
const res = await neo4jAdapter.executeQuery(cypher, { props, ownerUid: node.ownerUid ?? null });
if (res && res[0]?.externalId) persisted.push(res[0].externalId);
}
return persisted;
};
const run = async () => {
loadEnvIfNeeded();
const ingest = async (ingestor) => {
await ingestor.connect();
const items = await ingestor.fetchRecent(2);
const nodes = items.map((i) => ingestor.transformToGraphNode(i));
return persistNodes(nodes);
};
await ingest(new EmailIngestor());
await ingest(new CalendarIngestor());
const res = await neo4jAdapter.executeQuery(
'MATCH (u:User)-[r:BELONGS_TO]-(n:Private) RETURN u.uid AS uid, type(r) AS rel, labels(n) AS labels, coalesce(n.title, n.subject, n.bodyPreview) AS title LIMIT 5'
);
console.log(JSON.stringify(res, null, 2));
};
run().catch((err) => {
console.error(err);
process.exit(1);
});