studiograph 1.1.2 → 1.2.0-beta.1
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 +191 -0
- package/README.md +301 -10
- package/dist/agent/orchestrator.d.ts +17 -9
- package/dist/agent/orchestrator.js +142 -97
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/system.md +186 -0
- package/dist/agent/skill-loader.d.ts +48 -0
- package/dist/agent/skill-loader.js +166 -0
- package/dist/agent/skill-loader.js.map +1 -0
- package/dist/agent/skills/enrich-entities.md +136 -0
- package/dist/agent/skills/entity-schema.md +502 -0
- package/dist/agent/skills/gather-context.md +46 -0
- package/dist/agent/skills/obsidian-source-setup.md +246 -0
- package/dist/agent/skills/skill-loader.d.ts +48 -0
- package/dist/agent/skills/skill-loader.js +166 -0
- package/dist/agent/skills/skill-loader.js.map +1 -0
- package/dist/agent/skills/sync-configuration.md +144 -0
- package/dist/agent/skills/sync-setup.md +68 -0
- package/dist/agent/tools/connector-tools.d.ts +37 -0
- package/dist/agent/tools/connector-tools.js +132 -0
- package/dist/agent/tools/connector-tools.js.map +1 -0
- package/dist/agent/tools/fs-tools.d.ts +39 -0
- package/dist/agent/tools/fs-tools.js +106 -0
- package/dist/agent/tools/fs-tools.js.map +1 -0
- package/dist/agent/tools/graph-tools.d.ts +30 -2
- package/dist/agent/tools/graph-tools.js +154 -37
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/load-skill.d.ts +42 -0
- package/dist/agent/tools/load-skill.js +45 -0
- package/dist/agent/tools/load-skill.js.map +1 -0
- package/dist/agent/tools/sync-tools.d.ts +25 -0
- package/dist/agent/tools/sync-tools.js +691 -0
- package/dist/agent/tools/sync-tools.js.map +1 -0
- package/dist/agent/tools/tool-loader.d.ts +25 -0
- package/dist/agent/tools/tool-loader.js +73 -0
- package/dist/agent/tools/tool-loader.js.map +1 -0
- package/dist/auth/github.d.ts +11 -8
- package/dist/auth/github.js +56 -75
- package/dist/auth/github.js.map +1 -1
- package/dist/cli/colors.d.ts +54 -0
- package/dist/cli/colors.js +133 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/commands/app.d.ts +7 -0
- package/dist/cli/commands/app.js +167 -0
- package/dist/cli/commands/app.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +1 -1
- package/dist/cli/commands/auth.js +26 -10
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/clone.d.ts +9 -0
- package/dist/cli/commands/clone.js +167 -0
- package/dist/cli/commands/clone.js.map +1 -0
- package/dist/cli/commands/commit.d.ts +8 -0
- package/dist/cli/commands/commit.js +43 -0
- package/dist/cli/commands/commit.js.map +1 -0
- package/dist/cli/commands/config.d.ts +13 -0
- package/dist/cli/commands/config.js +276 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/connector.d.ts +33 -0
- package/dist/cli/commands/connector.js +178 -0
- package/dist/cli/commands/connector.js.map +1 -0
- package/dist/cli/commands/deploy.d.ts +11 -0
- package/dist/cli/commands/deploy.js +153 -0
- package/dist/cli/commands/deploy.js.map +1 -0
- package/dist/cli/commands/enrich.d.ts +11 -0
- package/dist/cli/commands/enrich.js +135 -0
- package/dist/cli/commands/enrich.js.map +1 -0
- package/dist/cli/commands/graphrag.d.ts +12 -0
- package/dist/cli/commands/graphrag.js +122 -0
- package/dist/cli/commands/graphrag.js.map +1 -0
- package/dist/cli/commands/index.d.ts +15 -0
- package/dist/cli/commands/index.js +117 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.js +110 -210
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/join.js +89 -24
- package/dist/cli/commands/join.js.map +1 -1
- package/dist/cli/commands/lint.d.ts +8 -0
- package/dist/cli/commands/lint.js +70 -0
- package/dist/cli/commands/lint.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +27 -0
- package/dist/cli/commands/mcp.js +56 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/orphans.d.ts +8 -0
- package/dist/cli/commands/orphans.js +125 -0
- package/dist/cli/commands/orphans.js.map +1 -0
- package/dist/cli/commands/provision.d.ts +8 -0
- package/dist/cli/commands/provision.js +116 -0
- package/dist/cli/commands/provision.js.map +1 -0
- package/dist/cli/commands/r2.d.ts +2 -0
- package/dist/cli/commands/r2.js +87 -6
- package/dist/cli/commands/r2.js.map +1 -1
- package/dist/cli/commands/reset.d.ts +12 -0
- package/dist/cli/commands/reset.js +137 -0
- package/dist/cli/commands/reset.js.map +1 -0
- package/dist/cli/commands/review.d.ts +19 -0
- package/dist/cli/commands/review.js +128 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/cli/commands/serve.js +47 -2
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/source.d.ts +16 -0
- package/dist/cli/commands/source.js +159 -0
- package/dist/cli/commands/source.js.map +1 -0
- package/dist/cli/commands/start.js +472 -103
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/sync-entities.d.ts +13 -0
- package/dist/cli/commands/sync-entities.js +242 -0
- package/dist/cli/commands/sync-entities.js.map +1 -0
- package/dist/cli/commands/sync.js +40 -9
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/commands/update.d.ts +8 -0
- package/dist/cli/commands/update.js +155 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.js +114 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scaffolding.d.ts +10 -0
- package/dist/cli/scaffolding.js +302 -0
- package/dist/cli/scaffolding.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +30 -0
- package/dist/cli/setup-wizard.js +244 -0
- package/dist/cli/setup-wizard.js.map +1 -0
- package/dist/cli/sync-review-interactive.d.ts +31 -0
- package/dist/cli/sync-review-interactive.js +393 -0
- package/dist/cli/sync-review-interactive.js.map +1 -0
- package/dist/cli/theme.d.ts +31 -0
- package/dist/cli/theme.js +116 -0
- package/dist/cli/theme.js.map +1 -0
- package/dist/core/graph.d.ts +16 -9
- package/dist/core/graph.js +263 -145
- package/dist/core/graph.js.map +1 -1
- package/dist/core/migration-runner.d.ts +42 -0
- package/dist/core/migration-runner.js +232 -0
- package/dist/core/migration-runner.js.map +1 -0
- package/dist/core/migration-types.d.ts +101 -0
- package/dist/core/migration-types.js +21 -0
- package/dist/core/migration-types.js.map +1 -0
- package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
- package/dist/core/migrations/index.d.ts +11 -0
- package/dist/core/migrations/index.js +23 -0
- package/dist/core/migrations/index.js.map +1 -0
- package/dist/core/schema-registry.d.ts +36 -0
- package/dist/core/schema-registry.js +161 -0
- package/dist/core/schema-registry.js.map +1 -0
- package/dist/core/types.d.ts +242 -3
- package/dist/core/types.js +21 -2
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +16 -0
- package/dist/core/user-config.js +8 -0
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +973 -32
- package/dist/core/validation.js +163 -4
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +26 -2
- package/dist/core/workspace-manager.js +113 -15
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +20 -11
- package/dist/core/workspace.js +123 -34
- package/dist/core/workspace.js.map +1 -1
- package/dist/mcp/connector-manager.d.ts +65 -0
- package/dist/mcp/connector-manager.js +223 -0
- package/dist/mcp/connector-manager.js.map +1 -0
- package/dist/mcp/connectors/asana.d.ts +2 -0
- package/dist/mcp/connectors/asana.js +20 -0
- package/dist/mcp/connectors/asana.js.map +1 -0
- package/dist/mcp/connectors/definitions.d.ts +45 -0
- package/dist/mcp/connectors/definitions.js +32 -0
- package/dist/mcp/connectors/definitions.js.map +1 -0
- package/dist/mcp/connectors/figma.d.ts +5 -0
- package/dist/mcp/connectors/figma.js +21 -0
- package/dist/mcp/connectors/figma.js.map +1 -0
- package/dist/mcp/connectors/gdrive.d.ts +2 -0
- package/dist/mcp/connectors/gdrive.js +20 -0
- package/dist/mcp/connectors/gdrive.js.map +1 -0
- package/dist/mcp/connectors/granola.d.ts +2 -0
- package/dist/mcp/connectors/granola.js +12 -0
- package/dist/mcp/connectors/granola.js.map +1 -0
- package/dist/mcp/connectors/linear.d.ts +2 -0
- package/dist/mcp/connectors/linear.js +19 -0
- package/dist/mcp/connectors/linear.js.map +1 -0
- package/dist/mcp/connectors/obsidian.d.ts +2 -0
- package/dist/mcp/connectors/obsidian.js +19 -0
- package/dist/mcp/connectors/obsidian.js.map +1 -0
- package/dist/mcp/connectors/pipedrive.d.ts +2 -0
- package/dist/mcp/connectors/pipedrive.js +20 -0
- package/dist/mcp/connectors/pipedrive.js.map +1 -0
- package/dist/mcp/connectors/slack.d.ts +2 -0
- package/dist/mcp/connectors/slack.js +21 -0
- package/dist/mcp/connectors/slack.js.map +1 -0
- package/dist/mcp/oauth-provider.d.ts +41 -0
- package/dist/mcp/oauth-provider.js +160 -0
- package/dist/mcp/oauth-provider.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -0
- package/dist/mcp/server.js +28 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.d.ts +14 -0
- package/dist/mcp/tools.js +172 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/server/index.js +17 -4
- package/dist/server/index.js.map +1 -1
- package/dist/server/plugin-loader.d.ts +15 -0
- package/dist/server/plugin-loader.js +68 -2
- package/dist/server/plugin-loader.js.map +1 -1
- package/dist/server/routes/graph-api.js +1 -1
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/webhook.js +33 -0
- package/dist/server/routes/webhook.js.map +1 -1
- package/dist/services/github-provisioner.d.ts +9 -3
- package/dist/services/github-provisioner.js +46 -8
- package/dist/services/github-provisioner.js.map +1 -1
- package/dist/services/lint-service.d.ts +27 -0
- package/dist/services/lint-service.js +83 -0
- package/dist/services/lint-service.js.map +1 -0
- package/dist/services/markdown.d.ts +9 -0
- package/dist/services/markdown.js +26 -5
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +1 -2
- package/dist/services/memory-service.js +5 -4
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/orphan-service.d.ts +31 -0
- package/dist/services/orphan-service.js +100 -0
- package/dist/services/orphan-service.js.map +1 -0
- package/dist/services/sync/commit.d.ts +58 -0
- package/dist/services/sync/commit.js +350 -0
- package/dist/services/sync/commit.js.map +1 -0
- package/dist/services/sync/context-index.d.ts +69 -0
- package/dist/services/sync/context-index.js +280 -0
- package/dist/services/sync/context-index.js.map +1 -0
- package/dist/services/sync/derive.d.ts +34 -0
- package/dist/services/sync/derive.js +164 -0
- package/dist/services/sync/derive.js.map +1 -0
- package/dist/services/sync/enrichment-state.d.ts +31 -0
- package/dist/services/sync/enrichment-state.js +63 -0
- package/dist/services/sync/enrichment-state.js.map +1 -0
- package/dist/services/sync/enrichment.d.ts +25 -0
- package/dist/services/sync/enrichment.js +121 -0
- package/dist/services/sync/enrichment.js.map +1 -0
- package/dist/services/sync/frontmatter-extractor.d.ts +40 -0
- package/dist/services/sync/frontmatter-extractor.js +273 -0
- package/dist/services/sync/frontmatter-extractor.js.map +1 -0
- package/dist/services/sync/graph-match-state.d.ts +33 -0
- package/dist/services/sync/graph-match-state.js +61 -0
- package/dist/services/sync/graph-match-state.js.map +1 -0
- package/dist/services/sync/graph-match.d.ts +53 -0
- package/dist/services/sync/graph-match.js +316 -0
- package/dist/services/sync/graph-match.js.map +1 -0
- package/dist/services/sync/graphrag-client.d.ts +43 -0
- package/dist/services/sync/graphrag-client.js +94 -0
- package/dist/services/sync/graphrag-client.js.map +1 -0
- package/dist/services/sync/graphrag-config.d.ts +16 -0
- package/dist/services/sync/graphrag-config.js +39 -0
- package/dist/services/sync/graphrag-config.js.map +1 -0
- package/dist/services/sync/graphrag-context.d.ts +14 -0
- package/dist/services/sync/graphrag-context.js +109 -0
- package/dist/services/sync/graphrag-context.js.map +1 -0
- package/dist/services/sync/graphrag-indexer.d.ts +30 -0
- package/dist/services/sync/graphrag-indexer.js +358 -0
- package/dist/services/sync/graphrag-indexer.js.map +1 -0
- package/dist/services/sync/llm.d.ts +32 -0
- package/dist/services/sync/llm.js +115 -0
- package/dist/services/sync/llm.js.map +1 -0
- package/dist/services/sync/mcp-client.d.ts +59 -0
- package/dist/services/sync/mcp-client.js +285 -0
- package/dist/services/sync/mcp-client.js.map +1 -0
- package/dist/services/sync/model-factory.d.ts +10 -0
- package/dist/services/sync/model-factory.js +24 -0
- package/dist/services/sync/model-factory.js.map +1 -0
- package/dist/services/sync/name-quality.d.ts +31 -0
- package/dist/services/sync/name-quality.js +60 -0
- package/dist/services/sync/name-quality.js.map +1 -0
- package/dist/services/sync/output-schemas.d.ts +92 -0
- package/dist/services/sync/output-schemas.js +43 -0
- package/dist/services/sync/output-schemas.js.map +1 -0
- package/dist/services/sync/prompts.d.ts +19 -0
- package/dist/services/sync/prompts.js +128 -0
- package/dist/services/sync/prompts.js.map +1 -0
- package/dist/services/sync/reconciler.d.ts +48 -0
- package/dist/services/sync/reconciler.js +295 -0
- package/dist/services/sync/reconciler.js.map +1 -0
- package/dist/services/sync/source-config.d.ts +45 -0
- package/dist/services/sync/source-config.js +208 -0
- package/dist/services/sync/source-config.js.map +1 -0
- package/dist/services/sync/source-definitions/asana.d.ts +15 -0
- package/dist/services/sync/source-definitions/asana.js +48 -0
- package/dist/services/sync/source-definitions/asana.js.map +1 -0
- package/dist/services/sync/source-definitions/definitions.d.ts +21 -0
- package/dist/services/sync/source-definitions/definitions.js +26 -0
- package/dist/services/sync/source-definitions/definitions.js.map +1 -0
- package/dist/services/sync/source-definitions/gdrive.d.ts +16 -0
- package/dist/services/sync/source-definitions/gdrive.js +68 -0
- package/dist/services/sync/source-definitions/gdrive.js.map +1 -0
- package/dist/services/sync/source-definitions/granola.d.ts +2 -0
- package/dist/services/sync/source-definitions/granola.js +28 -0
- package/dist/services/sync/source-definitions/granola.js.map +1 -0
- package/dist/services/sync/source-definitions/linear.d.ts +2 -0
- package/dist/services/sync/source-definitions/linear.js +60 -0
- package/dist/services/sync/source-definitions/linear.js.map +1 -0
- package/dist/services/sync/source-definitions/obsidian.d.ts +2 -0
- package/dist/services/sync/source-definitions/obsidian.js +55 -0
- package/dist/services/sync/source-definitions/obsidian.js.map +1 -0
- package/dist/services/sync/source-definitions/pipedrive.d.ts +2 -0
- package/dist/services/sync/source-definitions/pipedrive.js +52 -0
- package/dist/services/sync/source-definitions/pipedrive.js.map +1 -0
- package/dist/services/sync/staging.d.ts +53 -0
- package/dist/services/sync/staging.js +131 -0
- package/dist/services/sync/staging.js.map +1 -0
- package/dist/services/sync/structured-extractor.d.ts +49 -0
- package/dist/services/sync/structured-extractor.js +344 -0
- package/dist/services/sync/structured-extractor.js.map +1 -0
- package/dist/services/sync/sync-runner.d.ts +32 -0
- package/dist/services/sync/sync-runner.js +195 -0
- package/dist/services/sync/sync-runner.js.map +1 -0
- package/dist/services/sync/sync-state.d.ts +43 -0
- package/dist/services/sync/sync-state.js +154 -0
- package/dist/services/sync/sync-state.js.map +1 -0
- package/dist/services/sync/types.d.ts +203 -0
- package/dist/services/sync/types.js +8 -0
- package/dist/services/sync/types.js.map +1 -0
- package/dist/services/sync/unstructured-extractor.d.ts +29 -0
- package/dist/services/sync/unstructured-extractor.js +197 -0
- package/dist/services/sync/unstructured-extractor.js.map +1 -0
- package/dist/services/vector-service.d.ts +88 -0
- package/dist/services/vector-service.js +322 -0
- package/dist/services/vector-service.js.map +1 -0
- package/dist/utils/git.d.ts +26 -4
- package/dist/utils/git.js +55 -7
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/merge-resolver.d.ts +34 -0
- package/dist/utils/merge-resolver.js +201 -0
- package/dist/utils/merge-resolver.js.map +1 -0
- package/dist/utils/preflight.d.ts +2 -1
- package/dist/utils/preflight.js +8 -1
- package/dist/utils/preflight.js.map +1 -1
- package/dist/utils/version-checker.d.ts +23 -0
- package/dist/utils/version-checker.js +116 -0
- package/dist/utils/version-checker.js.map +1 -0
- package/dist/utils/workspace-config.d.ts +8 -0
- package/dist/utils/workspace-config.js +22 -0
- package/dist/utils/workspace-config.js.map +1 -0
- package/package.json +24 -11
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph Match
|
|
3
|
+
*
|
|
4
|
+
* Compares reconciled records against existing graph entities to prevent
|
|
5
|
+
* duplicate creates. Uses heuristic scoring first (string similarity,
|
|
6
|
+
* shared wikilinks), then LLM for ambiguous candidates.
|
|
7
|
+
*
|
|
8
|
+
* Inserted between reconciliation and staging in the sync pipeline:
|
|
9
|
+
* extract → derive → reconcile → graph-match → staging → commit
|
|
10
|
+
*/
|
|
11
|
+
import { existsSync, readdirSync, statSync } from 'fs';
|
|
12
|
+
import { join, basename } from 'path';
|
|
13
|
+
import pc from 'picocolors';
|
|
14
|
+
import { MarkdownService } from '../../services/markdown.js';
|
|
15
|
+
import { GraphMatchState } from './graph-match-state.js';
|
|
16
|
+
import { llmGraphMatch } from './llm.js';
|
|
17
|
+
import { loadWorkspaceConfig } from '../../utils/workspace-config.js';
|
|
18
|
+
// ── Public API ──────────────────────────────────────────────────────────────
|
|
19
|
+
export async function graphMatch(matches, options, onEvent) {
|
|
20
|
+
const emit = onEvent ?? (() => { });
|
|
21
|
+
const threshold = options.similarityThreshold ?? 0.4;
|
|
22
|
+
const { workspacePath } = options;
|
|
23
|
+
// 1. Load graph index
|
|
24
|
+
const graphIndex = buildGraphIndex(workspacePath, emit);
|
|
25
|
+
if (graphIndex.size === 0) {
|
|
26
|
+
return matches.map(m => ({ match: m }));
|
|
27
|
+
}
|
|
28
|
+
// Report index stats
|
|
29
|
+
let totalEntities = 0;
|
|
30
|
+
for (const entities of graphIndex.values())
|
|
31
|
+
totalEntities += entities.length;
|
|
32
|
+
emit({ type: 'index-loaded', entityCount: totalEntities, typeCount: graphIndex.size });
|
|
33
|
+
// 2. Load cached decisions
|
|
34
|
+
const state = new GraphMatchState(workspacePath);
|
|
35
|
+
const results = [];
|
|
36
|
+
let candidatesEvaluated = 0;
|
|
37
|
+
let matchesFound = 0;
|
|
38
|
+
for (let i = 0; i < matches.length; i++) {
|
|
39
|
+
const match = matches[i];
|
|
40
|
+
if (i > 0 && i % 500 === 0) {
|
|
41
|
+
emit({ type: 'progress', current: i, total: matches.length });
|
|
42
|
+
}
|
|
43
|
+
// Skip if already an update (reconciler found exact match on disk)
|
|
44
|
+
if (match.action === 'update') {
|
|
45
|
+
results.push({ match });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// Only try to match creates
|
|
49
|
+
const existingEntities = graphIndex.get(match.entity_type) ?? [];
|
|
50
|
+
if (existingEntities.length === 0) {
|
|
51
|
+
results.push({ match });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
// 3. Heuristic pre-filter: score against all same-type entities
|
|
55
|
+
const candidates = [];
|
|
56
|
+
for (const existing of existingEntities) {
|
|
57
|
+
// Skip if same ID (reconciler already handles this)
|
|
58
|
+
if (existing.entity_id === match.entity_id)
|
|
59
|
+
continue;
|
|
60
|
+
const score = heuristicScore({ entity_id: match.entity_id, frontmatter: match.merged_frontmatter }, { entity_id: existing.entity_id, frontmatter: existing.frontmatter });
|
|
61
|
+
if (score >= threshold) {
|
|
62
|
+
candidates.push({ entity: existing, score });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (candidates.length === 0) {
|
|
66
|
+
results.push({ match });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Sort by score descending — best candidate first
|
|
70
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
71
|
+
// 4. Check cache, then LLM for top candidates
|
|
72
|
+
let matched = false;
|
|
73
|
+
for (const candidate of candidates) {
|
|
74
|
+
candidatesEvaluated++;
|
|
75
|
+
const cached = state.getDecision(match.entity_id, candidate.entity.entity_id);
|
|
76
|
+
if (cached === false) {
|
|
77
|
+
// Previously decided: not the same
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (cached === true) {
|
|
81
|
+
// Previously decided: same entity
|
|
82
|
+
const updated = applyMatch(match, candidate.entity, 'cached');
|
|
83
|
+
emit({ type: 'matched', stagedId: match.entity_id, existingId: candidate.entity.entity_id, method: 'cached' });
|
|
84
|
+
results.push(updated);
|
|
85
|
+
matched = true;
|
|
86
|
+
matchesFound++;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
// No cached decision — ask LLM
|
|
90
|
+
try {
|
|
91
|
+
const llmResult = await llmGraphMatch(match.merged_frontmatter, candidate.entity.frontmatter, match.entity_type);
|
|
92
|
+
state.record(match.entity_id, candidate.entity.entity_id, llmResult.is_same);
|
|
93
|
+
if (llmResult.is_same) {
|
|
94
|
+
const updated = applyMatch(match, candidate.entity, 'llm', llmResult.reasoning);
|
|
95
|
+
emit({ type: 'matched', stagedId: match.entity_id, existingId: candidate.entity.entity_id, method: 'llm', reasoning: llmResult.reasoning });
|
|
96
|
+
results.push(updated);
|
|
97
|
+
matched = true;
|
|
98
|
+
matchesFound++;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104
|
+
emit({ type: 'error', stagedId: match.entity_id, existingId: candidate.entity.entity_id, error: msg });
|
|
105
|
+
// On error, skip this candidate but don't cache the decision
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!matched) {
|
|
109
|
+
results.push({ match });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Emit summary
|
|
113
|
+
emit({ type: 'summary', candidatesEvaluated, matchesFound });
|
|
114
|
+
// Persist cached decisions
|
|
115
|
+
state.save();
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
// ── Event Formatting ────────────────────────────────────────────────────────
|
|
119
|
+
/**
|
|
120
|
+
* Format a GraphMatchEvent into a colored CLI string.
|
|
121
|
+
*/
|
|
122
|
+
export function formatGraphMatchEvent(event) {
|
|
123
|
+
switch (event.type) {
|
|
124
|
+
case 'index-scan':
|
|
125
|
+
return ` Scanning ${event.stagedId} (${event.entityCount} entities)...`;
|
|
126
|
+
case 'index-loaded':
|
|
127
|
+
return ` Loaded ${pc.bold(String(event.entityCount))} entities across ${pc.bold(String(event.typeCount))} types`;
|
|
128
|
+
case 'matched':
|
|
129
|
+
if (event.method === 'cached') {
|
|
130
|
+
return ` ${pc.green('✓')} ${pc.cyan(event.stagedId)} ${pc.dim('→')} ${pc.green(event.existingId)} ${pc.dim('(cached)')}`;
|
|
131
|
+
}
|
|
132
|
+
return ` ${pc.green('✓')} ${pc.cyan(event.stagedId)} ${pc.dim('→')} ${pc.green(event.existingId)}`;
|
|
133
|
+
case 'summary':
|
|
134
|
+
return ` Evaluated ${pc.bold(String(event.candidatesEvaluated))} candidates, ${pc.bold(String(event.matchesFound))} matched`;
|
|
135
|
+
case 'progress':
|
|
136
|
+
return ` Matching ${event.current}/${event.total}...`;
|
|
137
|
+
case 'error':
|
|
138
|
+
return ` ${pc.red('!')} ${pc.cyan(event.stagedId)} ${pc.red(event.error)}`;
|
|
139
|
+
default:
|
|
140
|
+
return '';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ── Graph Index ─────────────────────────────────────────────────────────────
|
|
144
|
+
function buildGraphIndex(workspacePath, emit) {
|
|
145
|
+
const index = new Map();
|
|
146
|
+
const repoDirs = findRepoDirs(workspacePath);
|
|
147
|
+
const markdownService = new MarkdownService();
|
|
148
|
+
for (const repoDir of repoDirs) {
|
|
149
|
+
const repoName = basename(repoDir);
|
|
150
|
+
const subdirs = listSubDirs(repoDir);
|
|
151
|
+
if (emit) {
|
|
152
|
+
emit({ type: 'index-scan', stagedId: repoName, entityCount: subdirs.length });
|
|
153
|
+
}
|
|
154
|
+
for (const entityId of subdirs) {
|
|
155
|
+
const mainPath = join(repoDir, entityId, 'main.md');
|
|
156
|
+
if (!existsSync(mainPath))
|
|
157
|
+
continue;
|
|
158
|
+
try {
|
|
159
|
+
const doc = markdownService.parseFile(mainPath);
|
|
160
|
+
const entityType = doc.frontmatter.entity_type ?? repoName;
|
|
161
|
+
if (!index.has(entityType)) {
|
|
162
|
+
index.set(entityType, []);
|
|
163
|
+
}
|
|
164
|
+
index.get(entityType).push({
|
|
165
|
+
entity_id: entityId,
|
|
166
|
+
entity_type: entityType,
|
|
167
|
+
frontmatter: doc.frontmatter,
|
|
168
|
+
repo: repoName,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
// Log but don't fail — unparseable files shouldn't block the index
|
|
173
|
+
if (emit)
|
|
174
|
+
emit({ type: 'error', stagedId: entityId, error: `Failed to parse ${mainPath}: ${err instanceof Error ? err.message : 'unknown error'}` });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return index;
|
|
179
|
+
}
|
|
180
|
+
function findRepoDirs(workspacePath) {
|
|
181
|
+
const config = loadWorkspaceConfig(workspacePath);
|
|
182
|
+
if (config?.repos && Array.isArray(config.repos)) {
|
|
183
|
+
return config.repos
|
|
184
|
+
.map((r) => join(workspacePath, r.path))
|
|
185
|
+
.filter((p) => existsSync(p));
|
|
186
|
+
}
|
|
187
|
+
// Fallback: scan top-level directories
|
|
188
|
+
return listSubDirs(workspacePath)
|
|
189
|
+
.map(d => join(workspacePath, d))
|
|
190
|
+
.filter(d => !d.includes('.studiograph') && !d.includes('node_modules') && !d.includes('.git'));
|
|
191
|
+
}
|
|
192
|
+
function listSubDirs(dir) {
|
|
193
|
+
if (!existsSync(dir))
|
|
194
|
+
return [];
|
|
195
|
+
return readdirSync(dir).filter(f => {
|
|
196
|
+
if (f.startsWith('.'))
|
|
197
|
+
return false;
|
|
198
|
+
try {
|
|
199
|
+
return statSync(join(dir, f)).isDirectory();
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// ── Heuristic Scoring ───────────────────────────────────────────────────────
|
|
207
|
+
export function heuristicScore(staged, existing) {
|
|
208
|
+
let score = 0;
|
|
209
|
+
// Name similarity via Dice coefficient on bigrams (0–1), weighted 0.5
|
|
210
|
+
score += diceCoefficient(staged.entity_id, existing.entity_id) * 0.5;
|
|
211
|
+
// Shared client/organization reference
|
|
212
|
+
if (staged.frontmatter.client && existing.frontmatter.client &&
|
|
213
|
+
extractId(staged.frontmatter.client) === extractId(existing.frontmatter.client)) {
|
|
214
|
+
score += 0.3;
|
|
215
|
+
}
|
|
216
|
+
// Shared team members (Jaccard similarity on wikilink arrays)
|
|
217
|
+
const stagedTeam = extractIds(staged.frontmatter.team ?? staged.frontmatter.attendees);
|
|
218
|
+
const existingTeam = extractIds(existing.frontmatter.team ?? existing.frontmatter.attendees);
|
|
219
|
+
if (stagedTeam.length > 0 && existingTeam.length > 0) {
|
|
220
|
+
score += jaccard(stagedTeam, existingTeam) * 0.2;
|
|
221
|
+
}
|
|
222
|
+
// One name contains the other (e.g. "existence" ⊂ "existence-dataviz-redesign")
|
|
223
|
+
if (staged.entity_id.includes(existing.entity_id) ||
|
|
224
|
+
existing.entity_id.includes(staged.entity_id)) {
|
|
225
|
+
score += 0.3;
|
|
226
|
+
}
|
|
227
|
+
return Math.min(score, 1);
|
|
228
|
+
}
|
|
229
|
+
// ── String Similarity Helpers ───────────────────────────────────────────────
|
|
230
|
+
/** Dice coefficient on character bigrams. Returns 0–1. */
|
|
231
|
+
export function diceCoefficient(a, b) {
|
|
232
|
+
if (a === b)
|
|
233
|
+
return 1;
|
|
234
|
+
if (a.length < 2 || b.length < 2)
|
|
235
|
+
return 0;
|
|
236
|
+
const bigramsA = new Map();
|
|
237
|
+
for (let i = 0; i < a.length - 1; i++) {
|
|
238
|
+
const bigram = a.substring(i, i + 2);
|
|
239
|
+
bigramsA.set(bigram, (bigramsA.get(bigram) ?? 0) + 1);
|
|
240
|
+
}
|
|
241
|
+
const bigramsB = new Map();
|
|
242
|
+
for (let i = 0; i < b.length - 1; i++) {
|
|
243
|
+
const bigram = b.substring(i, i + 2);
|
|
244
|
+
bigramsB.set(bigram, (bigramsB.get(bigram) ?? 0) + 1);
|
|
245
|
+
}
|
|
246
|
+
let intersection = 0;
|
|
247
|
+
for (const [bigram, count] of bigramsA) {
|
|
248
|
+
intersection += Math.min(count, bigramsB.get(bigram) ?? 0);
|
|
249
|
+
}
|
|
250
|
+
return (2 * intersection) / (a.length - 1 + b.length - 1);
|
|
251
|
+
}
|
|
252
|
+
/** Extract entity ID from a wikilink string like "[[entity-id]]" or "[[entity-id|Name]]" */
|
|
253
|
+
function extractId(value) {
|
|
254
|
+
if (typeof value !== 'string')
|
|
255
|
+
return null;
|
|
256
|
+
const match = value.match(/\[\[([^\]|]+)/);
|
|
257
|
+
if (match)
|
|
258
|
+
return match[1];
|
|
259
|
+
if (/^[a-z0-9_-]+$/.test(value))
|
|
260
|
+
return value;
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
/** Extract entity IDs from an array of wikilink strings */
|
|
264
|
+
function extractIds(value) {
|
|
265
|
+
if (!Array.isArray(value))
|
|
266
|
+
return [];
|
|
267
|
+
return value
|
|
268
|
+
.map(v => extractId(v))
|
|
269
|
+
.filter((id) => id !== null);
|
|
270
|
+
}
|
|
271
|
+
/** Jaccard similarity of two string arrays */
|
|
272
|
+
function jaccard(a, b) {
|
|
273
|
+
const setA = new Set(a);
|
|
274
|
+
const setB = new Set(b);
|
|
275
|
+
let intersection = 0;
|
|
276
|
+
for (const item of setA) {
|
|
277
|
+
if (setB.has(item))
|
|
278
|
+
intersection++;
|
|
279
|
+
}
|
|
280
|
+
const union = setA.size + setB.size - intersection;
|
|
281
|
+
return union === 0 ? 0 : intersection / union;
|
|
282
|
+
}
|
|
283
|
+
// ── Match Application ───────────────────────────────────────────────────────
|
|
284
|
+
/** Fields where the existing graph value is authoritative over the source value */
|
|
285
|
+
const GRAPH_AUTHORITATIVE_FIELDS = new Set(['name', 'entity_id', 'entity_type']);
|
|
286
|
+
function applyMatch(match, existing, method, reasoning) {
|
|
287
|
+
// Merge frontmatter: existing graph fields win for identity fields,
|
|
288
|
+
// staged fields fill in anything the graph doesn't have
|
|
289
|
+
const mergedFrontmatter = { ...match.merged_frontmatter };
|
|
290
|
+
for (const [key, value] of Object.entries(existing.frontmatter)) {
|
|
291
|
+
if (key.startsWith('_'))
|
|
292
|
+
continue; // skip staging metadata
|
|
293
|
+
if (GRAPH_AUTHORITATIVE_FIELDS.has(key)) {
|
|
294
|
+
// Identity fields: graph always wins (user may have curated these)
|
|
295
|
+
mergedFrontmatter[key] = value;
|
|
296
|
+
}
|
|
297
|
+
else if (mergedFrontmatter[key] === undefined || mergedFrontmatter[key] === null) {
|
|
298
|
+
// Other fields: staged wins if present, otherwise fill from graph
|
|
299
|
+
mergedFrontmatter[key] = value;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const matchNote = `Matched ${match.entity_id} → ${existing.entity_id} via ${method}${reasoning ? ': ' + reasoning : ''}`;
|
|
303
|
+
const updatedMatch = {
|
|
304
|
+
...match,
|
|
305
|
+
entity_id: existing.entity_id,
|
|
306
|
+
action: 'update',
|
|
307
|
+
merged_frontmatter: mergedFrontmatter,
|
|
308
|
+
notes: match.notes ? `${match.notes}; ${matchNote}` : matchNote,
|
|
309
|
+
};
|
|
310
|
+
return {
|
|
311
|
+
match: updatedMatch,
|
|
312
|
+
matched_to: existing.entity_id,
|
|
313
|
+
match_method: method,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=graph-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-match.js","sourceRoot":"","sources":["../../../src/services/sync/graph-match.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphRAG Client — in-process Graphology knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the LightRAG HTTP client. Loads a serialized Graphology graph
|
|
5
|
+
* from disk, provides entity context via neighbor traversal.
|
|
6
|
+
*/
|
|
7
|
+
import Graph from 'graphology';
|
|
8
|
+
import type { GraphRAGConfig } from './graphrag-config.js';
|
|
9
|
+
import type { EntityContext } from './graphrag-context.js';
|
|
10
|
+
export declare class GraphRAGClient {
|
|
11
|
+
private graph;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config: GraphRAGConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the graph has any nodes (i.e., has been indexed).
|
|
16
|
+
*/
|
|
17
|
+
isAvailable(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Query the graph for context about an entity mentioned in source content.
|
|
20
|
+
* Scans source content for known node names, traverses neighbors.
|
|
21
|
+
*/
|
|
22
|
+
getEntityContext(name: string, type: string, content: string): EntityContext;
|
|
23
|
+
/**
|
|
24
|
+
* Get stats about the current graph.
|
|
25
|
+
*/
|
|
26
|
+
getStats(): {
|
|
27
|
+
nodes: number;
|
|
28
|
+
edges: number;
|
|
29
|
+
types: string[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Look up a node by name and return its neighbors.
|
|
33
|
+
*/
|
|
34
|
+
queryNode(name: string): {
|
|
35
|
+
node: Record<string, any>;
|
|
36
|
+
neighbors: Record<string, any>[];
|
|
37
|
+
edges: Record<string, any>[];
|
|
38
|
+
} | null;
|
|
39
|
+
/**
|
|
40
|
+
* Access the underlying graph (for testing / advanced use).
|
|
41
|
+
*/
|
|
42
|
+
getGraph(): Graph;
|
|
43
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphRAG Client — in-process Graphology knowledge graph.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the LightRAG HTTP client. Loads a serialized Graphology graph
|
|
5
|
+
* from disk, provides entity context via neighbor traversal.
|
|
6
|
+
*/
|
|
7
|
+
import Graph from 'graphology';
|
|
8
|
+
import { existsSync, readFileSync } from 'fs';
|
|
9
|
+
import { getEntityContext } from './graphrag-context.js';
|
|
10
|
+
export class GraphRAGClient {
|
|
11
|
+
graph;
|
|
12
|
+
config;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.graph = new Graph();
|
|
16
|
+
if (existsSync(config.graph_path)) {
|
|
17
|
+
try {
|
|
18
|
+
const data = JSON.parse(readFileSync(config.graph_path, 'utf-8'));
|
|
19
|
+
this.graph.import(data);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Start with empty graph if file is corrupted
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if the graph has any nodes (i.e., has been indexed).
|
|
28
|
+
*/
|
|
29
|
+
async isAvailable() {
|
|
30
|
+
return this.graph.order > 0;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Query the graph for context about an entity mentioned in source content.
|
|
34
|
+
* Scans source content for known node names, traverses neighbors.
|
|
35
|
+
*/
|
|
36
|
+
getEntityContext(name, type, content) {
|
|
37
|
+
return getEntityContext(this.graph, name, type, content);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get stats about the current graph.
|
|
41
|
+
*/
|
|
42
|
+
getStats() {
|
|
43
|
+
const typeSet = new Set();
|
|
44
|
+
this.graph.forEachNode((_node, attrs) => {
|
|
45
|
+
if (attrs.type)
|
|
46
|
+
typeSet.add(attrs.type);
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
nodes: this.graph.order,
|
|
50
|
+
edges: this.graph.size,
|
|
51
|
+
types: [...typeSet].sort(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Look up a node by name and return its neighbors.
|
|
56
|
+
*/
|
|
57
|
+
queryNode(name) {
|
|
58
|
+
const nameLower = name.toLowerCase();
|
|
59
|
+
let foundKey;
|
|
60
|
+
this.graph.forEachNode((node, attrs) => {
|
|
61
|
+
if (foundKey)
|
|
62
|
+
return;
|
|
63
|
+
const nodeName = attrs.name ?? node;
|
|
64
|
+
if (nodeName.toLowerCase() === nameLower) {
|
|
65
|
+
foundKey = node;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
if (!foundKey)
|
|
69
|
+
return null;
|
|
70
|
+
const nodeAttrs = this.graph.getNodeAttributes(foundKey);
|
|
71
|
+
const neighbors = [];
|
|
72
|
+
const edges = [];
|
|
73
|
+
this.graph.forEachNeighbor(foundKey, (_neighbor, attrs) => {
|
|
74
|
+
neighbors.push({ ...attrs });
|
|
75
|
+
});
|
|
76
|
+
this.graph.forEachEdge(foundKey, (_edge, attrs, source, target) => {
|
|
77
|
+
const sourceAttrs = this.graph.getNodeAttributes(source);
|
|
78
|
+
const targetAttrs = this.graph.getNodeAttributes(target);
|
|
79
|
+
edges.push({
|
|
80
|
+
source: sourceAttrs.name ?? source,
|
|
81
|
+
target: targetAttrs.name ?? target,
|
|
82
|
+
...attrs,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
return { node: { ...nodeAttrs }, neighbors, edges };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Access the underlying graph (for testing / advanced use).
|
|
89
|
+
*/
|
|
90
|
+
getGraph() {
|
|
91
|
+
return this.graph;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=graphrag-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphrag-client.js","sourceRoot":"","sources":["../../../src/services/sync/graphrag-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphRAG configuration — in-process Graphology graph.
|
|
3
|
+
*
|
|
4
|
+
* Config stored at ~/.studiograph/graphrag/config.json.
|
|
5
|
+
* Graph data stored at ~/.studiograph/graphrag/graph.json.
|
|
6
|
+
*/
|
|
7
|
+
export interface GraphRAGConfig {
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
graph_path: string;
|
|
10
|
+
last_indexed?: string;
|
|
11
|
+
files_indexed?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const GRAPHRAG_CONFIG_PATH: string;
|
|
14
|
+
export declare function loadGraphRAGConfig(): GraphRAGConfig;
|
|
15
|
+
export declare function saveGraphRAGConfig(config: GraphRAGConfig): void;
|
|
16
|
+
export declare function isGraphRAGEnabled(): boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphRAG configuration — in-process Graphology graph.
|
|
3
|
+
*
|
|
4
|
+
* Config stored at ~/.studiograph/graphrag/config.json.
|
|
5
|
+
* Graph data stored at ~/.studiograph/graphrag/graph.json.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
const GRAPHRAG_DIR = join(homedir(), '.studiograph', 'graphrag');
|
|
11
|
+
export const GRAPHRAG_CONFIG_PATH = join(GRAPHRAG_DIR, 'config.json');
|
|
12
|
+
function defaultGraphPath() {
|
|
13
|
+
return join(GRAPHRAG_DIR, 'graph.json');
|
|
14
|
+
}
|
|
15
|
+
export function loadGraphRAGConfig() {
|
|
16
|
+
if (!existsSync(GRAPHRAG_CONFIG_PATH)) {
|
|
17
|
+
return { enabled: false, graph_path: defaultGraphPath() };
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const raw = JSON.parse(readFileSync(GRAPHRAG_CONFIG_PATH, 'utf-8'));
|
|
21
|
+
return {
|
|
22
|
+
enabled: raw.enabled ?? false,
|
|
23
|
+
graph_path: raw.graph_path ?? defaultGraphPath(),
|
|
24
|
+
last_indexed: raw.last_indexed,
|
|
25
|
+
files_indexed: raw.files_indexed,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return { enabled: false, graph_path: defaultGraphPath() };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function saveGraphRAGConfig(config) {
|
|
33
|
+
mkdirSync(GRAPHRAG_DIR, { recursive: true });
|
|
34
|
+
writeFileSync(GRAPHRAG_CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
|
|
35
|
+
}
|
|
36
|
+
export function isGraphRAGEnabled() {
|
|
37
|
+
return loadGraphRAGConfig().enabled;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=graphrag-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphrag-config.js","sourceRoot":"","sources":["../../../src/services/sync/graphrag-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAS7B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAEtE,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC;QACpE,OAAO;YACL,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,KAAK;YAC7B,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,gBAAgB,EAAE;YAChD,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,aAAa,EAAE,GAAG,CAAC,aAAa;SACjC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,EAAE,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAsB;IACvD,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,aAAa,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,kBAAkB,EAAE,CAAC,OAAO,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphRAG context builder — synchronous graph traversal.
|
|
3
|
+
*
|
|
4
|
+
* Scans source content for known node names, collects neighbors
|
|
5
|
+
* and edge descriptions, and formats as markdown context sections.
|
|
6
|
+
*/
|
|
7
|
+
import type Graph from 'graphology';
|
|
8
|
+
export interface EntityContext {
|
|
9
|
+
formattedContext: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Find entities mentioned in source content and collect their graph neighbors.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getEntityContext(graph: Graph, entityName: string, entityType: string, sourceContent: string): EntityContext;
|