diff --git a/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx new file mode 100644 index 000000000..8271a056a --- /dev/null +++ b/apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx @@ -0,0 +1,125 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import React, { + useState, + useMemo, + useEffect, + useRef, + useCallback, +} from "react"; +import { Button, Intent } from "@blueprintjs/core"; +import BlocksPanel from "roamjs-components/components/ConfigPanels/BlocksPanel"; +import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel"; +import TextPanel from "roamjs-components/components/ConfigPanels/TextPanel"; +import getSubTree from "roamjs-components/util/getSubTree"; +import { DiscourseNode } from "~/utils/getDiscourseNodes"; +import extractRef from "roamjs-components/util/extractRef"; + +const BlockRenderer = ({ uid }: { uid: string }) => { + const containerRef = useRef(null); + + useEffect(() => { + const container = containerRef.current; + if (container) { + container.innerHTML = ""; + + window.roamAlphaAPI.ui.components.renderBlock({ + uid: uid, + el: container, + }); + } + }, [uid]); + + return
; +}; + +const DiscourseNodeSuggestiveRules = ({ + node, + parentUid, +}: { + node: DiscourseNode; + parentUid: string; +}) => { + const nodeUid = node.type; + + const [embeddingRef, setEmbeddingRef] = useState(node.embeddingRef); + + useEffect(() => { + setEmbeddingRef(node.embeddingRef || ""); + }, [node.embeddingRef]); + + const blockUidToRender = useMemo( + () => extractRef(embeddingRef), + [embeddingRef], + ); + + const templateUid = useMemo( + () => + getSubTree({ + parentUid: nodeUid, + key: "Template", + }).uid || "", + [nodeUid], + ); + + const handleEmbeddingRefChange = useCallback( + (e: React.ChangeEvent) => { + const newValue = e.target.value; + setEmbeddingRef(newValue); + }, + [], + ); + + return ( +
+ + + + + {blockUidToRender && ( +
+
Preview:
+ +
+ )} + + + + {/* TODO: Add a button to update embeddings in seperate PR */} +
+ ); +}; + +export default DiscourseNodeSuggestiveRules; diff --git a/apps/roam/src/components/settings/NodeConfig.tsx b/apps/roam/src/components/settings/NodeConfig.tsx index 1d0af9a80..4bed1469b 100644 --- a/apps/roam/src/components/settings/NodeConfig.tsx +++ b/apps/roam/src/components/settings/NodeConfig.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import React, { useState, useCallback, useRef, useEffect } from "react"; import { DiscourseNode } from "~/utils/getDiscourseNodes"; import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel"; @@ -22,6 +23,7 @@ import { OnloadArgs } from "roamjs-components/types"; import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; import createBlock from "roamjs-components/writes/createBlock"; import updateBlock from "roamjs-components/writes/updateBlock"; +import DiscourseNodeSuggestiveRules from "./DiscourseNodeSuggestiveRules"; const ValidatedInputPanel = ({ label, @@ -161,6 +163,7 @@ const NodeConfig = ({ const graphOverviewUid = getUid("Graph Overview"); const specificationUid = getUid("Specification"); const indexUid = getUid("Index"); + const suggestiveRulesUid = getUid("Suggestive Rules"); const attributeNode = getSubTree({ parentUid: node.type, key: "Attributes", @@ -383,6 +386,18 @@ const NodeConfig = ({
} /> + + + + } + /> ); diff --git a/apps/roam/src/components/settings/PageGroupPanel.tsx b/apps/roam/src/components/settings/PageGroupPanel.tsx new file mode 100644 index 000000000..fff680248 --- /dev/null +++ b/apps/roam/src/components/settings/PageGroupPanel.tsx @@ -0,0 +1,206 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import React, { useState, useCallback } from "react"; +import { Label, Button, Intent, Tag } from "@blueprintjs/core"; +import Description from "roamjs-components/components/Description"; +import AutocompleteInput from "roamjs-components/components/AutocompleteInput"; +import createBlock from "roamjs-components/writes/createBlock"; +import deleteBlock from "roamjs-components/writes/deleteBlock"; +import getAllPageNames from "roamjs-components/queries/getAllPageNames"; +import { type PageGroup } from "~/utils/getSuggestiveModeConfigSettings"; + +const PageGroupsPanel = ({ + uid, + initialGroups, +}: { + uid: string; + initialGroups: PageGroup[]; +}) => { + const [pageGroups, setPageGroups] = useState(initialGroups); + + const [newGroupName, setNewGroupName] = useState(""); + const [newPageInputs, setNewPageInputs] = useState>( + {}, + ); + const [autocompleteKeys, setAutocompleteKeys] = useState< + Record + >({}); + + const addGroup = async (name: string) => { + if (!name || pageGroups.some((g) => g.name === name)) return; + try { + const newGroupUid = await createBlock({ + parentUid: uid, + node: { text: name }, + }); + setPageGroups([...pageGroups, { uid: newGroupUid, name, pages: [] }]); + setNewGroupName(""); + } catch (e) { + console.error("Error adding group", e); + } + }; + + const removeGroup = async (groupUid: string) => { + try { + await deleteBlock(groupUid); + setPageGroups(pageGroups.filter((g) => g.uid !== groupUid)); + } catch (e) { + console.error("Error removing group", e); + } + }; + + const addPageToGroup = async (groupUid: string, page: string) => { + const group = pageGroups.find((g) => g.uid === groupUid); + if (!page || group?.pages.some((p) => p.name === page)) { + return; + } + try { + const newPageUid = await createBlock({ + parentUid: groupUid, + node: { text: page }, + }); + setPageGroups( + pageGroups.map((g) => + g.uid === groupUid + ? { ...g, pages: [...g.pages, { uid: newPageUid, name: page }] } + : g, + ), + ); + setNewPageInputs((prev) => ({ + ...prev, + [groupUid]: "", + })); + setAutocompleteKeys((prev) => ({ + ...prev, + [groupUid]: (prev[groupUid] || 0) + 1, + })); + } catch (e) { + console.error("Error adding page to group", e); + } + }; + + const removePageFromGroup = async (groupUid: string, pageUid: string) => { + try { + await deleteBlock(pageUid); + setPageGroups( + pageGroups.map((g) => + g.uid === groupUid + ? { ...g, pages: g.pages.filter((p) => p.uid !== pageUid) } + : g, + ), + ); + } catch (e) { + console.error("Error removing page from group", e); + } + }; + + const getPageInput = (groupUid: string) => newPageInputs[groupUid] || ""; + const setPageInput = useCallback((groupUid: string, value: string) => { + setTimeout(() => { + setNewPageInputs((prev) => ({ + ...prev, + [groupUid]: value, + })); + }, 0); + }, []); + const getAutocompleteKey = (groupUid: string) => + autocompleteKeys[groupUid] || 0; + + return ( + + ); +}; + +export default PageGroupsPanel; diff --git a/apps/roam/src/components/settings/Settings.tsx b/apps/roam/src/components/settings/Settings.tsx index 058c5f103..23742cf58 100644 --- a/apps/roam/src/components/settings/Settings.tsx +++ b/apps/roam/src/components/settings/Settings.tsx @@ -25,6 +25,7 @@ import sendErrorEmail from "~/utils/sendErrorEmail"; import HomePersonalSettings from "./HomePersonalSettings"; import refreshConfigTree from "~/utils/refreshConfigTree"; import { FeedbackWidget } from "~/components/BirdEatsBugs"; +import SuggestiveModeSettings from "./SuggestiveModeSettings"; import { getVersionWithDate } from "~/utils/getVersion"; type SectionHeaderProps = { @@ -161,6 +162,12 @@ export const SettingsDialog = ({ className="overflow-y-auto" panel={} /> + } + /> Grammar { + const settings = getFormattedConfigTree(); + + const [suggestiveModeUid, setSuggestiveModeUid] = useState( + settings.suggestiveMode.parentUid, + ); + useEffect(() => { + if (suggestiveModeUid) return; + void (async () => { + const smUid = await createBlock({ + parentUid: getPageUidByPageTitle(DISCOURSE_CONFIG_PAGE_TITLE), + node: { text: "Suggestive Mode" }, + }); + setSuggestiveModeUid(smUid); + })(); + }, [suggestiveModeUid]); + + const effectiveSuggestiveModeUid = + suggestiveModeUid || settings.suggestiveMode.parentUid; + + return ( +
+
+
+
+ + + {/* TODO: if "Include Current Page Relations" is checked "Include Parent and Child Blocks" + should be checked and disabled, use `selection` instead */} + +
+
+ +
+
+ ); +}; + +export default SuggestiveModeSettings; diff --git a/apps/roam/src/index.ts b/apps/roam/src/index.ts index 592e19ee7..5c852e57d 100644 --- a/apps/roam/src/index.ts +++ b/apps/roam/src/index.ts @@ -27,7 +27,7 @@ import { installDiscourseFloatingMenu, removeDiscourseFloatingMenu, } from "./components/DiscourseFloatingMenu"; -import { createOrUpdateDiscourseEmbedding } from "./utils/syncDgNodesToSupabase"; +import { initializeSupabaseSync } from "./utils/syncDgNodesToSupabase"; import { initPluginTimer } from "./utils/pluginTimer"; const initPostHog = () => { @@ -123,6 +123,8 @@ export default runExtension(async (onloadArgs) => { document.addEventListener("input", discourseNodeSearchTriggerListener); document.addEventListener("selectionchange", nodeCreationPopoverListener); + await initializeSupabaseSync(); + const { extensionAPI } = onloadArgs; window.roamjs.extension.queryBuilder = { runQuery: (parentUid: string) => @@ -139,9 +141,6 @@ export default runExtension(async (onloadArgs) => { getDiscourseNodes: getDiscourseNodes, }; - // TODO: REMOVE AFTER TESTING - // await createOrUpdateDiscourseEmbedding(onloadArgs.extensionAPI); - installDiscourseFloatingMenu(onloadArgs); return { diff --git a/apps/roam/src/utils/configPageTabs.ts b/apps/roam/src/utils/configPageTabs.ts index 0fdf8a4d6..1d43df445 100644 --- a/apps/roam/src/utils/configPageTabs.ts +++ b/apps/roam/src/utils/configPageTabs.ts @@ -14,6 +14,7 @@ import { CustomField, SelectField, } from "roamjs-components/components/ConfigPanels/types"; +import PageGroupsPanel from "~/components/settings/PageGroupPanel"; export const configPageTabs = (args: OnloadArgs): ConfigTab[] => [ { @@ -116,4 +117,31 @@ export const configPageTabs = (args: OnloadArgs): ConfigTab[] => [ }, ], }, + { + id: "Suggestive Mode", + fields: [ + { + title: "Include Current Page Relations", + // @ts-ignore + Panel: FlagPanel, + description: + "Include relations from pages referenced on the current page", + }, + { + title: "Include Parent And Child Blocks", + // @ts-ignore + Panel: FlagPanel, + description: "Include relations from parent and child blocks", + }, + // @ts-ignore + { + title: "Page Groups", + Panel: CustomPanel, + description: "Set page groups to use for discourse suggestions", + options: { + component: PageGroupsPanel, + }, + } as Field, + ], + }, ]; diff --git a/apps/roam/src/utils/discourseConfigRef.ts b/apps/roam/src/utils/discourseConfigRef.ts index 3cfc91cdc..48b2c1a1c 100644 --- a/apps/roam/src/utils/discourseConfigRef.ts +++ b/apps/roam/src/utils/discourseConfigRef.ts @@ -7,6 +7,10 @@ import { } from "./getExportSettings"; import { DISCOURSE_CONFIG_PAGE_TITLE } from "~/utils/renderNodeConfigPage"; import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle"; +import { + getSuggestiveModeConfigAndUids, + SuggestiveModeConfigWithUids, +} from "./getSuggestiveModeConfigSettings"; const configTreeRef: { tree: RoamBasicNode[]; @@ -21,6 +25,7 @@ type FormattedConfigTree = { trigger: StringSetting; export: ExportConfigWithUids; canvasPageFormat: StringSetting; + suggestiveMode: SuggestiveModeConfigWithUids; }; export const getFormattedConfigTree = (): FormattedConfigTree => { @@ -47,6 +52,7 @@ export const getFormattedConfigTree = (): FormattedConfigTree => { tree: configTreeRef.tree, text: "Canvas Page Format", }), + suggestiveMode: getSuggestiveModeConfigAndUids(configTreeRef.tree), }; }; export default configTreeRef; diff --git a/apps/roam/src/utils/getAllDiscourseNodesSince.ts b/apps/roam/src/utils/getAllDiscourseNodesSince.ts index 929d34e68..b74a0cc1c 100644 --- a/apps/roam/src/utils/getAllDiscourseNodesSince.ts +++ b/apps/roam/src/utils/getAllDiscourseNodesSince.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/naming-convention */ import getDiscourseNodes, { type DiscourseNode } from "./getDiscourseNodes"; import findDiscourseNode from "./findDiscourseNode"; -import { type OnloadArgs } from "roamjs-components/types"; import getDiscourseNodeFormatExpression from "./getDiscourseNodeFormatExpression"; +import { extractRef } from "roamjs-components/util"; type ISODateString = string; @@ -25,17 +25,10 @@ export type DiscourseNodesSinceResult = { export const getDiscourseNodeTypeWithSettingsBlockNodes = ( node: DiscourseNode, sinceMs: number, - extensionAPI: OnloadArgs["extensionAPI"], ): RoamDiscourseNodeData[] => { - const settingsKey = `discourse-graph-node-rule-${node.type}`; - const settings = extensionAPI.settings.get(settingsKey) as { - embeddingRef: string; - isFirstChild: boolean; - }; const regex = getDiscourseNodeFormatExpression(node.format); const regexPattern = regex.source.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); - const firstChildUid = - settings.embeddingRef?.match(/\(\((.*?)\)\)/)?.[1] ?? ""; + const firstChildUid = extractRef(node.embeddingRef); const queryBlock = `[ :find ?childString ?nodeUid ?nodeCreateTime ?nodeEditTime ?author_local_id ?type ?author_name ?node-title :keys text source_local_id created last_modified author_local_id type author_name node_title @@ -76,24 +69,10 @@ export const getDiscourseNodeTypeWithSettingsBlockNodes = ( export const getAllDiscourseNodesSince = async ( since: ISODateString, nodeTypes: DiscourseNode[], - extensionAPI: OnloadArgs["extensionAPI"], ): Promise => { const sinceMs = new Date(since).getTime(); const result: RoamDiscourseNodeData[] = []; - if (nodeTypes.length > 0) { - for (const node of nodeTypes) { - const blockNode = getDiscourseNodeTypeWithSettingsBlockNodes( - node, - sinceMs, - extensionAPI, - ); - if (blockNode) { - result.push(...blockNode); - } - } - } - const query = `[ :find ?node-title ?uid ?nodeCreateTime ?nodeEditTime ?author_local_id ?author_name :keys text source_local_id created last_modified author_local_id author_name @@ -117,7 +96,6 @@ export const getAllDiscourseNodesSince = async ( )) as unknown as RoamDiscourseNodeData[]; const discourseNodes = getDiscourseNodes(); - const nodeTypesSet = new Set(nodeTypes.map((nodeType) => nodeType.type)); result.push( ...allNodes.flatMap((entity) => { @@ -129,8 +107,7 @@ export const getAllDiscourseNodesSince = async ( !node || node.backedBy === "default" || !entity.text || - entity.text.trim() === "" || - nodeTypesSet.has(node.type) + entity.text.trim() === "" ) { return []; } @@ -142,6 +119,18 @@ export const getAllDiscourseNodesSince = async ( ]; }), ); + + if (nodeTypes.length > 0) { + for (const node of nodeTypes) { + const blockNode = getDiscourseNodeTypeWithSettingsBlockNodes( + node, + sinceMs, + ); + if (blockNode) { + result.push(...blockNode); + } + } + } return result; }; diff --git a/apps/roam/src/utils/getDiscourseNodes.ts b/apps/roam/src/utils/getDiscourseNodes.ts index e934237f5..affb06a45 100644 --- a/apps/roam/src/utils/getDiscourseNodes.ts +++ b/apps/roam/src/utils/getDiscourseNodes.ts @@ -26,6 +26,12 @@ export type DiscourseNode = { graphOverview?: boolean; description?: string; template?: InputTextNode[]; + embeddingRef?: string; + embeddingRefUid?: string; + isFirstChild?: { + uid: string; + value: boolean; + }; }; const DEFAULT_NODES: DiscourseNode[] = [ @@ -81,9 +87,33 @@ const getSpecification = (children: RoamBasicNode[] | undefined) => { return specs; }; +const getUidAndBooleanSetting = ({ + tree, + text, +}: { + tree: RoamBasicNode[]; + text: string; +}) => { + const node = tree.find((t) => t.text === text); + const value = !!node?.children?.length; + return { + uid: node?.uid || "", + value, + }; +}; + const getDiscourseNodes = (relations = getDiscourseRelations()) => { const configuredNodes = Object.entries(discourseConfigRef.nodes) .map(([type, { text, children }]): DiscourseNode => { + const suggestiveRules = getSubTree({ + tree: children, + key: "Suggestive Rules", + }); + const embeddingBlockRef = getSubTree({ + tree: suggestiveRules.children, + key: "Embedding Block Ref", + }).children?.[0]; + return { format: getSettingValueFromTree({ tree: children, key: "format" }), text, @@ -104,6 +134,12 @@ const getDiscourseNodes = (relations = getDiscourseRelations()) => { key: "description", }), template: getSubTree({ tree: children, key: "template" }).children, + embeddingRef: embeddingBlockRef?.text, + embeddingRefUid: embeddingBlockRef?.uid, + isFirstChild: getUidAndBooleanSetting({ + tree: suggestiveRules.children, + text: "First Child", + }), }; }) .concat( diff --git a/apps/roam/src/utils/getSuggestiveModeConfigSettings.ts b/apps/roam/src/utils/getSuggestiveModeConfigSettings.ts new file mode 100644 index 000000000..5dcb57135 --- /dev/null +++ b/apps/roam/src/utils/getSuggestiveModeConfigSettings.ts @@ -0,0 +1,55 @@ +import { getSubTree } from "roamjs-components/util"; +import { BooleanSetting, getUidAndBooleanSetting } from "./getExportSettings"; +import { RoamBasicNode } from "roamjs-components/types"; +import getBasicTreeByParentUid from "roamjs-components/queries/getBasicTreeByParentUid"; + +export type PageGroup = { + uid: string; + name: string; + pages: { uid: string; name: string }[]; +}; +export type SuggestiveModeConfigWithUids = { + parentUid: string; + includePageRelations: BooleanSetting; + includeParentAndChildren: BooleanSetting; + pageGroups: { + uid: string; + groups: PageGroup[]; + }; +}; + +export const getSuggestiveModeConfigAndUids = ( + tree: RoamBasicNode[], +): SuggestiveModeConfigWithUids => { + const suggestiveModeNode = getSubTree({ + tree, + key: "Suggestive Mode", + }); + const pageGroupsNode = getSubTree({ + parentUid: suggestiveModeNode.uid, + key: "Page Groups", + }); + const pageGroups = getBasicTreeByParentUid(pageGroupsNode.uid).map( + (node) => ({ + uid: node.uid, + name: node.text, + pages: node.children.map((c) => ({ uid: c.uid, name: c.text })), + }), + ); + + return { + parentUid: suggestiveModeNode.uid, + includePageRelations: getUidAndBooleanSetting({ + tree: suggestiveModeNode.children, + text: "Include Current Page Relations", + }), + includeParentAndChildren: getUidAndBooleanSetting({ + tree: suggestiveModeNode.children, + text: "Include Parent And Child Blocks", + }), + pageGroups: { + uid: pageGroupsNode.uid, + groups: pageGroups, + }, + }; +}; diff --git a/apps/roam/src/utils/renderNodeConfigPage.ts b/apps/roam/src/utils/renderNodeConfigPage.ts index de2ee07b6..0e5d223dc 100644 --- a/apps/roam/src/utils/renderNodeConfigPage.ts +++ b/apps/roam/src/utils/renderNodeConfigPage.ts @@ -24,6 +24,7 @@ import { } from "~/components"; import getDiscourseNodes from "~/utils/getDiscourseNodes"; import { render as configPageRender } from "roamjs-components/components/ConfigPage"; +import DiscourseNodeSuggestiveRules from "~/components/settings/DiscourseNodeSuggestiveRules"; export const DISCOURSE_CONFIG_PAGE_TITLE = "roam/js/discourse-graph"; export const NODE_CONFIG_PAGE_TITLE = "discourse-graph/nodes/"; @@ -147,6 +148,18 @@ export const renderNodeConfigPage = ({ description: `Whether to color the node in the graph overview based on canvas color. This is based on the node's plain title as described by a \`has title\` condition in its specification.`, defaultValue: true, } as FieldPanel, + // @ts-ignore + { + title: "Suggestive Rules", + Panel: CustomPanel, + options: { + component: ({ uid }) => + React.createElement(DiscourseNodeSuggestiveRules, { + node, + parentUid: uid, + }), + }, + } as Field, ], }); diff --git a/apps/roam/src/utils/syncDgNodesToSupabase.ts b/apps/roam/src/utils/syncDgNodesToSupabase.ts index 09a1ec9e1..a42852730 100644 --- a/apps/roam/src/utils/syncDgNodesToSupabase.ts +++ b/apps/roam/src/utils/syncDgNodesToSupabase.ts @@ -16,14 +16,16 @@ import { discourseNodeSchemaToLocalConcept, orderConceptsByDependency, } from "./conceptConversion"; -import { type OnloadArgs } from "roamjs-components/types"; import { fetchEmbeddingsForNodes } from "./upsertNodesAsContentWithEmbeddings"; import { convertRoamNodeToLocalContent } from "./upsertNodesAsContentWithEmbeddings"; +import { getRoamUrl } from "roamjs-components/dom"; +import { render as renderToast } from "roamjs-components/components/Toast"; import type { DGSupabaseClient } from "@repo/database/lib/client"; import type { Json, CompositeTypes } from "@repo/database/dbTypes"; type LocalContentDataInput = Partial>; type AccountLocalInput = CompositeTypes<"account_local_input">; +const { createClient } = require("@repo/database/lib/client"); const SYNC_FUNCTION = "embedding"; const SYNC_INTERVAL = "45s"; @@ -57,9 +59,37 @@ export const endSyncTask = async ( }); if (error) { console.error("endSyncTask: Error calling end_sync_task:", error); + renderToast({ + id: "discourse-embedding-error", + content: "Failed to complete discourse node embeddings sync", + intent: "danger", + timeout: 5000, + }); + } else { + if (status === "complete") { + renderToast({ + id: "discourse-embedding-complete", + content: "Successfully completed discourse node embeddings sync", + intent: "success", + timeout: 4000, + }); + } else if (status === "failed") { + renderToast({ + id: "discourse-embedding-failed", + content: "Discourse node embeddings sync failed", + intent: "danger", + timeout: 5000, + }); + } } } catch (error) { console.error("endSyncTask: Error calling end_sync_task:", error); + renderToast({ + id: "discourse-embedding-error", + content: "Failed to complete discourse node embeddings sync", + intent: "danger", + timeout: 5000, + }); } }; @@ -109,9 +139,6 @@ export const proposeSyncTask = async (): Promise => { const now = new Date(); if (timestamp > now) { - console.log( - "proposeSyncTask: Another worker is already running this task", - ); return { lastUpdateTime: null, spaceId, worker, shouldProceed: false }; } else { return { lastUpdateTime: data, spaceId, worker, shouldProceed: true }; @@ -293,19 +320,12 @@ export const upsertNodesToSupabaseAsContentWithEmbeddings = async ( await uploadBatches(chunk(nodesWithEmbeddings, BATCH_SIZE)); }; -const getDgNodeTypes = (extensionAPI: OnloadArgs["extensionAPI"]) => { +const getDgNodeTypes = () => { const allDgNodeTypes = getDiscourseNodes().filter( (n) => n.backedBy === "user", ); const dgNodeTypesWithSettings = allDgNodeTypes.filter((n) => { - const settingsKey = `discourse-graph-node-rule-${n.type}`; - const settings = extensionAPI.settings.get(settingsKey) as - | { - isFirstChild?: boolean; - embeddingRef?: string; - } - | undefined; - return settings?.isFirstChild || settings?.embeddingRef; + return n.isFirstChild?.value || n.embeddingRef !== undefined; }); return { allDgNodeTypes, dgNodeTypesWithSettings }; }; @@ -345,28 +365,21 @@ const upsertUsers = async ( } }; -export const createOrUpdateDiscourseEmbedding = async ( - extensionAPI: OnloadArgs["extensionAPI"], -) => { +export const createOrUpdateDiscourseEmbedding = async () => { const { shouldProceed, lastUpdateTime, worker } = await proposeSyncTask(); if (!shouldProceed) { - console.log( - "createOrUpdateDiscourseEmbedding: Task already running or failed to acquire lock. Exiting.", - ); return; } try { const allUsers = await getAllUsers(); const time = lastUpdateTime === null ? DEFAULT_TIME : lastUpdateTime; - const { allDgNodeTypes, dgNodeTypesWithSettings } = - getDgNodeTypes(extensionAPI); + const { allDgNodeTypes, dgNodeTypesWithSettings } = getDgNodeTypes(); const allNodeInstances = await getAllDiscourseNodesSince( time, dgNodeTypesWithSettings, - extensionAPI, ); const supabaseClient = await getLoggedInClient(); const context = await getSupabaseContext(); @@ -396,3 +409,17 @@ export const createOrUpdateDiscourseEmbedding = async ( throw error; } }; + +export const initializeSupabaseSync = async () => { + const supabase = createClient(); + const result = await supabase + .from("Space") + .select() + .eq("url", getRoamUrl()) + .maybeSingle(); + if (!result.data) { + return; + } else { + createOrUpdateDiscourseEmbedding(); + } +};