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,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Runner
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the full sync pipeline:
|
|
5
|
+
* 1. Load source configs
|
|
6
|
+
* 2. Connect to each source's MCP server
|
|
7
|
+
* 3. Extract (structured or unstructured per mapping)
|
|
8
|
+
* 4. Detect derivation needs, derive secondary entities
|
|
9
|
+
* 5. Reconcile all records
|
|
10
|
+
* 6. Write to staging
|
|
11
|
+
*/
|
|
12
|
+
export interface SyncOptions {
|
|
13
|
+
workspacePath: string;
|
|
14
|
+
sources?: string[];
|
|
15
|
+
dryRun?: boolean;
|
|
16
|
+
incremental?: boolean;
|
|
17
|
+
schemaExtensions?: Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
export interface SyncResult {
|
|
20
|
+
sources_processed: number;
|
|
21
|
+
records_extracted: number;
|
|
22
|
+
records_derived: number;
|
|
23
|
+
records_reconciled: number;
|
|
24
|
+
records_graph_matched: number;
|
|
25
|
+
staging_written: number;
|
|
26
|
+
by_source: Record<string, {
|
|
27
|
+
extracted: number;
|
|
28
|
+
errors: number;
|
|
29
|
+
}>;
|
|
30
|
+
by_entity_type: Record<string, number>;
|
|
31
|
+
}
|
|
32
|
+
export declare function runSync(options: SyncOptions, onProgress?: (msg: string) => void): Promise<SyncResult>;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Runner
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the full sync pipeline:
|
|
5
|
+
* 1. Load source configs
|
|
6
|
+
* 2. Connect to each source's MCP server
|
|
7
|
+
* 3. Extract (structured or unstructured per mapping)
|
|
8
|
+
* 4. Detect derivation needs, derive secondary entities
|
|
9
|
+
* 5. Reconcile all records
|
|
10
|
+
* 6. Write to staging
|
|
11
|
+
*/
|
|
12
|
+
import { ConnectorManager } from '../../mcp/connector-manager.js';
|
|
13
|
+
import { SchemaRegistry } from '../../core/schema-registry.js';
|
|
14
|
+
import { SourceConfigManager } from './source-config.js';
|
|
15
|
+
import { SyncStateManager } from './sync-state.js';
|
|
16
|
+
import { SyncMCPClient } from './mcp-client.js';
|
|
17
|
+
import { StructuredExtractor } from './structured-extractor.js';
|
|
18
|
+
import { UnstructuredExtractor } from './unstructured-extractor.js';
|
|
19
|
+
import { FrontmatterExtractor } from './frontmatter-extractor.js';
|
|
20
|
+
import { DerivationEngine } from './derive.js';
|
|
21
|
+
import { Reconciler } from './reconciler.js';
|
|
22
|
+
import { graphMatch, formatGraphMatchEvent } from './graph-match.js';
|
|
23
|
+
import { StagingManager } from './staging.js';
|
|
24
|
+
import { loadGraphRAGConfig, isGraphRAGEnabled } from './graphrag-config.js';
|
|
25
|
+
import { GraphRAGClient } from './graphrag-client.js';
|
|
26
|
+
export async function runSync(options, onProgress) {
|
|
27
|
+
const log = onProgress ?? (() => { });
|
|
28
|
+
const { workspacePath } = options;
|
|
29
|
+
// Load source configs
|
|
30
|
+
const configMgr = new SourceConfigManager(workspacePath);
|
|
31
|
+
let allConfigs = configMgr.getAll().filter(c => c.enabled);
|
|
32
|
+
if (options.sources && options.sources.length > 0) {
|
|
33
|
+
allConfigs = allConfigs.filter(c => options.sources.includes(c.name));
|
|
34
|
+
}
|
|
35
|
+
if (allConfigs.length === 0) {
|
|
36
|
+
log('No enabled sources found.');
|
|
37
|
+
return emptyResult();
|
|
38
|
+
}
|
|
39
|
+
// Load connectors
|
|
40
|
+
const connectors = ConnectorManager.loadConfigs();
|
|
41
|
+
// Initialize managers
|
|
42
|
+
const syncState = new SyncStateManager(workspacePath);
|
|
43
|
+
const schemaRegistry = new SchemaRegistry(options.schemaExtensions);
|
|
44
|
+
const staging = new StagingManager(workspacePath);
|
|
45
|
+
// Initialize GraphRAG client if enabled
|
|
46
|
+
let graphrag;
|
|
47
|
+
if (isGraphRAGEnabled()) {
|
|
48
|
+
const graphragConfig = loadGraphRAGConfig();
|
|
49
|
+
graphrag = new GraphRAGClient(graphragConfig);
|
|
50
|
+
const available = await graphrag.isAvailable();
|
|
51
|
+
if (available) {
|
|
52
|
+
const stats = graphrag.getStats();
|
|
53
|
+
log(`GraphRAG enabled: ${stats.nodes} nodes, ${stats.edges} edges`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
log('GraphRAG enabled but graph is empty — run: studiograph graphrag index <path>');
|
|
57
|
+
graphrag = undefined;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const result = {
|
|
61
|
+
sources_processed: 0,
|
|
62
|
+
records_extracted: 0,
|
|
63
|
+
records_derived: 0,
|
|
64
|
+
records_reconciled: 0,
|
|
65
|
+
records_graph_matched: 0,
|
|
66
|
+
staging_written: 0,
|
|
67
|
+
by_source: {},
|
|
68
|
+
by_entity_type: {},
|
|
69
|
+
};
|
|
70
|
+
const allRecords = [];
|
|
71
|
+
// Phase 1: Extract from all sources
|
|
72
|
+
for (const sourceConfig of allConfigs) {
|
|
73
|
+
log(`Extracting from ${sourceConfig.name}...`);
|
|
74
|
+
const sourceResult = { extracted: 0, errors: 0 };
|
|
75
|
+
const connector = connectors.find(c => c.name === sourceConfig.connector);
|
|
76
|
+
if (!connector) {
|
|
77
|
+
log(` Connector "${sourceConfig.connector}" not found — skipping`);
|
|
78
|
+
sourceResult.errors++;
|
|
79
|
+
result.by_source[sourceConfig.name] = sourceResult;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const client = new SyncMCPClient(connector);
|
|
83
|
+
try {
|
|
84
|
+
await client.connect();
|
|
85
|
+
log(` Connected to ${sourceConfig.connector}`);
|
|
86
|
+
for (const mapping of sourceConfig.entity_mappings) {
|
|
87
|
+
log(` Extracting ${mapping.source_type} → ${mapping.entity_type}...`);
|
|
88
|
+
try {
|
|
89
|
+
let records;
|
|
90
|
+
if (mapping.extraction_mode === 'structured') {
|
|
91
|
+
const extractor = new StructuredExtractor(client, sourceConfig, syncState);
|
|
92
|
+
records = await extractor.extract(mapping, options.incremental, log);
|
|
93
|
+
}
|
|
94
|
+
else if (mapping.extraction_mode === 'frontmatter') {
|
|
95
|
+
const extractor = new FrontmatterExtractor(client, sourceConfig);
|
|
96
|
+
records = await extractor.extract(mapping, log);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const extractor = new UnstructuredExtractor(client, sourceConfig, schemaRegistry, graphrag);
|
|
100
|
+
records = await extractor.extract(mapping, log);
|
|
101
|
+
}
|
|
102
|
+
allRecords.push(...records);
|
|
103
|
+
sourceResult.extracted += records.length;
|
|
104
|
+
log(` Extracted ${records.length} ${mapping.entity_type} records`);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
+
log(` Error: ${msg}`);
|
|
109
|
+
sourceResult.errors++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Update last sync timestamp
|
|
113
|
+
syncState.setLastSync(sourceConfig.name, new Date().toISOString());
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
117
|
+
log(` Connection failed: ${msg}`);
|
|
118
|
+
sourceResult.errors++;
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
await client.close();
|
|
122
|
+
}
|
|
123
|
+
result.by_source[sourceConfig.name] = sourceResult;
|
|
124
|
+
result.sources_processed++;
|
|
125
|
+
}
|
|
126
|
+
result.records_extracted = allRecords.length;
|
|
127
|
+
log(`\nExtracted ${allRecords.length} total records from ${result.sources_processed} sources`);
|
|
128
|
+
// Phase 2: Derivation
|
|
129
|
+
log('Detecting derivation needs...');
|
|
130
|
+
const allMappings = allConfigs.flatMap(c => c.entity_mappings);
|
|
131
|
+
const derivationEngine = new DerivationEngine(schemaRegistry);
|
|
132
|
+
const rules = derivationEngine.detectDerivationNeeds(allMappings);
|
|
133
|
+
let derivedRecords = [];
|
|
134
|
+
if (rules.length > 0) {
|
|
135
|
+
log(` Deriving: ${rules.map(r => r.entity_type).join(', ')}`);
|
|
136
|
+
derivedRecords = derivationEngine.derive(allRecords, rules);
|
|
137
|
+
allRecords.push(...derivedRecords);
|
|
138
|
+
log(` Derived ${derivedRecords.length} secondary entities`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
log(' No derivation needed');
|
|
142
|
+
}
|
|
143
|
+
result.records_derived = derivedRecords.length;
|
|
144
|
+
// Phase 3: Reconciliation
|
|
145
|
+
log('Reconciling records...');
|
|
146
|
+
const reconciler = new Reconciler(workspacePath, schemaRegistry, syncState, allConfigs);
|
|
147
|
+
const matches = reconciler.reconcile(allRecords);
|
|
148
|
+
result.records_reconciled = matches.length;
|
|
149
|
+
log(` ${matches.length} unique entities after reconciliation`);
|
|
150
|
+
// Phase 3.5: Graph matching
|
|
151
|
+
log('Matching against existing graph...');
|
|
152
|
+
const graphResults = await graphMatch(matches, {
|
|
153
|
+
workspacePath,
|
|
154
|
+
schemaExtensions: options.schemaExtensions,
|
|
155
|
+
}, (event) => log(formatGraphMatchEvent(event)));
|
|
156
|
+
const finalMatches = graphResults.map(r => r.match);
|
|
157
|
+
result.records_graph_matched = graphResults.filter(r => r.matched_to).length;
|
|
158
|
+
// Count by entity type
|
|
159
|
+
for (const match of finalMatches) {
|
|
160
|
+
result.by_entity_type[match.entity_type] = (result.by_entity_type[match.entity_type] ?? 0) + 1;
|
|
161
|
+
}
|
|
162
|
+
// Phase 4: Write staging
|
|
163
|
+
if (options.dryRun) {
|
|
164
|
+
log('\nDry run — skipping staging write');
|
|
165
|
+
result.staging_written = 0;
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
log('Writing staging files...');
|
|
169
|
+
staging.clear();
|
|
170
|
+
const { written } = staging.writeStaging(finalMatches);
|
|
171
|
+
result.staging_written = written;
|
|
172
|
+
log(` ${written} files written to .studiograph/staging/`);
|
|
173
|
+
}
|
|
174
|
+
// Persist provenance mappings
|
|
175
|
+
for (const match of finalMatches) {
|
|
176
|
+
for (const record of match.records) {
|
|
177
|
+
syncState.setEntityMapping(record.source_name, match.entity_id, record.source_ref);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
log('\nSync complete.');
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
function emptyResult() {
|
|
184
|
+
return {
|
|
185
|
+
sources_processed: 0,
|
|
186
|
+
records_extracted: 0,
|
|
187
|
+
records_derived: 0,
|
|
188
|
+
records_reconciled: 0,
|
|
189
|
+
records_graph_matched: 0,
|
|
190
|
+
staging_written: 0,
|
|
191
|
+
by_source: {},
|
|
192
|
+
by_entity_type: {},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=sync-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-runner.js","sourceRoot":"","sources":["../../../src/services/sync/sync-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncStateManager
|
|
3
|
+
*
|
|
4
|
+
* Persistent sync state at .studiograph/sync-state.json.
|
|
5
|
+
* Tracks cursors for incremental sync, entity provenance mappings,
|
|
6
|
+
* and tombstones for entities deliberately deleted by the user.
|
|
7
|
+
*/
|
|
8
|
+
import type { SyncState } from './types.js';
|
|
9
|
+
export declare class SyncStateManager {
|
|
10
|
+
private statePath;
|
|
11
|
+
private state;
|
|
12
|
+
constructor(workspacePath: string);
|
|
13
|
+
/**
|
|
14
|
+
* Load sync state from disk. Creates empty state if file doesn't exist.
|
|
15
|
+
*/
|
|
16
|
+
load(): SyncState;
|
|
17
|
+
/**
|
|
18
|
+
* Save sync state to disk.
|
|
19
|
+
*/
|
|
20
|
+
save(state: SyncState): void;
|
|
21
|
+
getLastSync(source: string): string | null;
|
|
22
|
+
setLastSync(source: string, timestamp: string): void;
|
|
23
|
+
getCursor(source: string, entityType: string): string | null;
|
|
24
|
+
setCursor(source: string, entityType: string, cursor: string): void;
|
|
25
|
+
setEntityMapping(source: string, entityId: string, sourceRef: string): void;
|
|
26
|
+
getEntityMapping(source: string, entityId: string): string | null;
|
|
27
|
+
findBySourceRef(source: string, sourceRef: string): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Record which source wrote each field for an entity.
|
|
30
|
+
* Stored under state.sources[sourceName].field_origins[entityId].
|
|
31
|
+
*/
|
|
32
|
+
setFieldOrigins(sourceName: string, entityId: string, fieldSources: Record<string, string>): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get aggregated field origins for an entity across all sources.
|
|
35
|
+
* Returns field_name → source_name map.
|
|
36
|
+
*/
|
|
37
|
+
getFieldOrigins(entityId: string): Record<string, string>;
|
|
38
|
+
addTombstone(entityId: string): void;
|
|
39
|
+
isTombstoned(entityId: string): boolean;
|
|
40
|
+
removeTombstone(entityId: string): void;
|
|
41
|
+
private emptyState;
|
|
42
|
+
private ensureSource;
|
|
43
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SyncStateManager
|
|
3
|
+
*
|
|
4
|
+
* Persistent sync state at .studiograph/sync-state.json.
|
|
5
|
+
* Tracks cursors for incremental sync, entity provenance mappings,
|
|
6
|
+
* and tombstones for entities deliberately deleted by the user.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
9
|
+
import { join, dirname } from 'path';
|
|
10
|
+
export class SyncStateManager {
|
|
11
|
+
statePath;
|
|
12
|
+
state = null;
|
|
13
|
+
constructor(workspacePath) {
|
|
14
|
+
this.statePath = join(workspacePath, '.studiograph', 'sync-state.json');
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Load sync state from disk. Creates empty state if file doesn't exist.
|
|
18
|
+
*/
|
|
19
|
+
load() {
|
|
20
|
+
if (this.state)
|
|
21
|
+
return this.state;
|
|
22
|
+
if (existsSync(this.statePath)) {
|
|
23
|
+
try {
|
|
24
|
+
this.state = JSON.parse(readFileSync(this.statePath, 'utf-8'));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
this.state = this.emptyState();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
this.state = this.emptyState();
|
|
32
|
+
}
|
|
33
|
+
return this.state;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Save sync state to disk.
|
|
37
|
+
*/
|
|
38
|
+
save(state) {
|
|
39
|
+
this.state = state;
|
|
40
|
+
const dir = dirname(this.statePath);
|
|
41
|
+
if (!existsSync(dir)) {
|
|
42
|
+
mkdirSync(dir, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
writeFileSync(this.statePath, JSON.stringify(state, null, 2) + '\n', 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
// ── Source cursor tracking ────────────────────────────────────────────────
|
|
47
|
+
getLastSync(source) {
|
|
48
|
+
const state = this.load();
|
|
49
|
+
return state.sources[source]?.last_sync ?? null;
|
|
50
|
+
}
|
|
51
|
+
setLastSync(source, timestamp) {
|
|
52
|
+
const state = this.load();
|
|
53
|
+
this.ensureSource(state, source);
|
|
54
|
+
state.sources[source].last_sync = timestamp;
|
|
55
|
+
this.save(state);
|
|
56
|
+
}
|
|
57
|
+
getCursor(source, entityType) {
|
|
58
|
+
const state = this.load();
|
|
59
|
+
return state.sources[source]?.cursors[entityType] ?? null;
|
|
60
|
+
}
|
|
61
|
+
setCursor(source, entityType, cursor) {
|
|
62
|
+
const state = this.load();
|
|
63
|
+
this.ensureSource(state, source);
|
|
64
|
+
state.sources[source].cursors[entityType] = cursor;
|
|
65
|
+
this.save(state);
|
|
66
|
+
}
|
|
67
|
+
// ── Provenance mapping ────────────────────────────────────────────────────
|
|
68
|
+
setEntityMapping(source, entityId, sourceRef) {
|
|
69
|
+
const state = this.load();
|
|
70
|
+
this.ensureSource(state, source);
|
|
71
|
+
state.sources[source].entity_map[entityId] = sourceRef;
|
|
72
|
+
this.save(state);
|
|
73
|
+
}
|
|
74
|
+
getEntityMapping(source, entityId) {
|
|
75
|
+
const state = this.load();
|
|
76
|
+
return state.sources[source]?.entity_map[entityId] ?? null;
|
|
77
|
+
}
|
|
78
|
+
findBySourceRef(source, sourceRef) {
|
|
79
|
+
const state = this.load();
|
|
80
|
+
const entityMap = state.sources[source]?.entity_map;
|
|
81
|
+
if (!entityMap)
|
|
82
|
+
return null;
|
|
83
|
+
for (const [entityId, ref] of Object.entries(entityMap)) {
|
|
84
|
+
if (ref === sourceRef)
|
|
85
|
+
return entityId;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
// ── Field Origins ────────────────────────────────────────────────────────────
|
|
90
|
+
/**
|
|
91
|
+
* Record which source wrote each field for an entity.
|
|
92
|
+
* Stored under state.sources[sourceName].field_origins[entityId].
|
|
93
|
+
*/
|
|
94
|
+
setFieldOrigins(sourceName, entityId, fieldSources) {
|
|
95
|
+
const state = this.load();
|
|
96
|
+
this.ensureSource(state, sourceName);
|
|
97
|
+
const src = state.sources[sourceName];
|
|
98
|
+
if (!src.field_origins)
|
|
99
|
+
src.field_origins = {};
|
|
100
|
+
src.field_origins[entityId] = { ...src.field_origins[entityId], ...fieldSources };
|
|
101
|
+
this.save(state);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get aggregated field origins for an entity across all sources.
|
|
105
|
+
* Returns field_name → source_name map.
|
|
106
|
+
*/
|
|
107
|
+
getFieldOrigins(entityId) {
|
|
108
|
+
const state = this.load();
|
|
109
|
+
const merged = {};
|
|
110
|
+
for (const [sourceName, srcState] of Object.entries(state.sources)) {
|
|
111
|
+
const origins = srcState.field_origins?.[entityId];
|
|
112
|
+
if (origins) {
|
|
113
|
+
for (const [field, src] of Object.entries(origins)) {
|
|
114
|
+
merged[field] = src;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return merged;
|
|
119
|
+
}
|
|
120
|
+
// ── Tombstones ─────────────────────────────────────────────────────────────
|
|
121
|
+
addTombstone(entityId) {
|
|
122
|
+
const state = this.load();
|
|
123
|
+
if (!state.tombstones.includes(entityId)) {
|
|
124
|
+
state.tombstones.push(entityId);
|
|
125
|
+
this.save(state);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
isTombstoned(entityId) {
|
|
129
|
+
const state = this.load();
|
|
130
|
+
return state.tombstones.includes(entityId);
|
|
131
|
+
}
|
|
132
|
+
removeTombstone(entityId) {
|
|
133
|
+
const state = this.load();
|
|
134
|
+
const idx = state.tombstones.indexOf(entityId);
|
|
135
|
+
if (idx !== -1) {
|
|
136
|
+
state.tombstones.splice(idx, 1);
|
|
137
|
+
this.save(state);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// ── Private helpers ────────────────────────────────────────────────────────
|
|
141
|
+
emptyState() {
|
|
142
|
+
return { sources: {}, tombstones: [] };
|
|
143
|
+
}
|
|
144
|
+
ensureSource(state, source) {
|
|
145
|
+
if (!state.sources[source]) {
|
|
146
|
+
state.sources[source] = {
|
|
147
|
+
last_sync: '',
|
|
148
|
+
cursors: {},
|
|
149
|
+
entity_map: {},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=sync-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-state.js","sourceRoot":"","sources":["../../../src/services/sync/sync-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the entity sync system.
|
|
3
|
+
*
|
|
4
|
+
* Defines source configs, extraction records, sync state, reconciliation
|
|
5
|
+
* results, and staging metadata used across all sync pipeline stages.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Source configuration stored at .studiograph/sources/<name>.json.
|
|
9
|
+
* Defines how to map external data to Studiograph entities.
|
|
10
|
+
*/
|
|
11
|
+
export interface SourceConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
/** References a connector in ~/.studiograph/connectors/ */
|
|
14
|
+
connector: string;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
added_at: string;
|
|
17
|
+
entity_mappings: EntityMapping[];
|
|
18
|
+
/**
|
|
19
|
+
* Field-level merge priority: which source wins for which fields.
|
|
20
|
+
* e.g. { "email": "pipedrive", "status": "granola" }
|
|
21
|
+
* Default: structured API sources > derived data.
|
|
22
|
+
*/
|
|
23
|
+
field_priority?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Maps one external entity type to a Studiograph entity type.
|
|
27
|
+
*/
|
|
28
|
+
export interface EntityMapping {
|
|
29
|
+
/** What the source calls it (e.g. "deal", "document") */
|
|
30
|
+
source_type: string;
|
|
31
|
+
/** Studiograph entity type (e.g. "project", "meeting") */
|
|
32
|
+
entity_type: string;
|
|
33
|
+
/** Repo to write to (e.g. "projects", "meetings") */
|
|
34
|
+
target_repo: string;
|
|
35
|
+
/** Structured: field map driven. Unstructured: LLM extraction. */
|
|
36
|
+
extraction_mode: 'structured' | 'unstructured' | 'frontmatter';
|
|
37
|
+
/** Maps source field paths to entity field names or transforms */
|
|
38
|
+
field_map?: Record<string, string | FieldTransform>;
|
|
39
|
+
/** Maps source status values to entity status values */
|
|
40
|
+
status_map?: Record<string, string>;
|
|
41
|
+
/** Source field to slugify for entity_id */
|
|
42
|
+
id_from?: string;
|
|
43
|
+
/** Source field whose value becomes the entity markdown body (structured mode) */
|
|
44
|
+
content_from?: string;
|
|
45
|
+
/** If true, fetch full record via get tool for each listed ID (for APIs where list is sparse) */
|
|
46
|
+
fetch_details?: boolean;
|
|
47
|
+
/** Override the limit param sent to the list tool (e.g. 1000 to get all Granola docs) */
|
|
48
|
+
list_limit?: number;
|
|
49
|
+
/** Extra params passed to the list/search tool (e.g. { workspace: "12345" } for Asana).
|
|
50
|
+
* Pass an array to make multiple list calls and merge results
|
|
51
|
+
* (e.g. [{ archived: false }, { archived: true }]). */
|
|
52
|
+
list_params?: Record<string, any> | Record<string, any>[];
|
|
53
|
+
/** How entities are written to disk. 'entity' (default): repo/id/main.md. 'collection': repo/id.md */
|
|
54
|
+
write_mode?: 'entity' | 'collection';
|
|
55
|
+
/** Co-locate entities as sub-content inside a parent entity folder. */
|
|
56
|
+
co_locate?: {
|
|
57
|
+
/** Frontmatter field that references the parent entity (e.g., "project"). Value is a wikilink like "[[my-project]]". */
|
|
58
|
+
parent_field: string;
|
|
59
|
+
/** Subfolder name inside the parent entity folder (e.g., "tasks"). */
|
|
60
|
+
subfolder: string;
|
|
61
|
+
};
|
|
62
|
+
/** Fetch body content per record via a separate MCP tool call (e.g. readGoogleDoc).
|
|
63
|
+
* The result text becomes the entity's markdown body. */
|
|
64
|
+
content_tool?: {
|
|
65
|
+
/** MCP tool name to call (e.g. "readGoogleDoc") */
|
|
66
|
+
tool: string;
|
|
67
|
+
/** Param name for the record ID (e.g. "documentId") */
|
|
68
|
+
id_param: string;
|
|
69
|
+
/** Record field to use as the ID value. Default: "id" */
|
|
70
|
+
id_from?: string;
|
|
71
|
+
/** Extra args to pass to the tool (e.g. { format: "markdown" }) */
|
|
72
|
+
extra_args?: Record<string, any>;
|
|
73
|
+
};
|
|
74
|
+
/** Directory patterns to match source files */
|
|
75
|
+
directory_patterns?: string[];
|
|
76
|
+
/** Explicit MCP tool name for listing files (e.g. "list_vault_files"). Falls back to heuristic matching. */
|
|
77
|
+
list_tool?: string;
|
|
78
|
+
/** Explicit MCP tool name for reading a file (e.g. "get_vault_file"). Falls back to heuristic matching. */
|
|
79
|
+
read_tool?: string;
|
|
80
|
+
/** Maximum recursion depth for directory listing. 0 = files directly in the pattern dir, 1 = one level of subdirs, etc. Undefined = unlimited. */
|
|
81
|
+
max_depth?: number;
|
|
82
|
+
/** Glob pattern matched against filename (without .md extension). Only matching files are included. Supports * and ? wildcards. E.g. "dec-*", "*.project". */
|
|
83
|
+
file_pattern?: string;
|
|
84
|
+
/** Match mode for filename. 'folder' = only files whose stem equals parent folder name. */
|
|
85
|
+
name_match?: 'folder';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Describes how to transform a source field into an entity field.
|
|
89
|
+
*/
|
|
90
|
+
export interface FieldTransform {
|
|
91
|
+
/** Target entity field name */
|
|
92
|
+
field: string;
|
|
93
|
+
/** Transform type to apply */
|
|
94
|
+
transform: 'direct' | 'kebab-case' | 'date-iso' | 'wikilink' | 'wikilink-array';
|
|
95
|
+
/** For array-of-objects: extract this sub-path from each element before transforming */
|
|
96
|
+
subfield?: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Metadata fields prefixed with _ in staging frontmatter, stripped on commit.
|
|
100
|
+
*/
|
|
101
|
+
export interface StagingMetadata {
|
|
102
|
+
_action: 'create' | 'update' | 'skip';
|
|
103
|
+
_confidence: number;
|
|
104
|
+
_sources: string[];
|
|
105
|
+
_notes: string;
|
|
106
|
+
_field_sources?: Record<string, string>;
|
|
107
|
+
/** Explains how this entity was matched to an existing graph entity */
|
|
108
|
+
_match_note?: string;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Internal representation of an extracted record, before reconciliation.
|
|
112
|
+
*/
|
|
113
|
+
export interface ExtractedRecord {
|
|
114
|
+
entity_type: string;
|
|
115
|
+
entity_id: string;
|
|
116
|
+
target_repo: string;
|
|
117
|
+
frontmatter: Record<string, any>;
|
|
118
|
+
content: string;
|
|
119
|
+
source_name: string;
|
|
120
|
+
source_ref: string;
|
|
121
|
+
confidence: number;
|
|
122
|
+
/** Co-location config from the entity mapping, if present. */
|
|
123
|
+
co_locate?: {
|
|
124
|
+
parent_field: string;
|
|
125
|
+
subfolder: string;
|
|
126
|
+
};
|
|
127
|
+
/** Write mode from the entity mapping, if present. */
|
|
128
|
+
write_mode?: 'entity' | 'collection';
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Persistent sync state at .studiograph/sync-state.json.
|
|
132
|
+
* Survives across sync runs. Tracks cursors, provenance, and tombstones.
|
|
133
|
+
*/
|
|
134
|
+
export interface SyncState {
|
|
135
|
+
sources: Record<string, SourceSyncState>;
|
|
136
|
+
/** Entity IDs deliberately deleted by the user */
|
|
137
|
+
tombstones: string[];
|
|
138
|
+
}
|
|
139
|
+
export interface SourceSyncState {
|
|
140
|
+
/** ISO timestamp of last successful sync */
|
|
141
|
+
last_sync: string;
|
|
142
|
+
/** Per-entity-type pagination cursors */
|
|
143
|
+
cursors: Record<string, string>;
|
|
144
|
+
/** Maps local entity_id to external source ref for provenance */
|
|
145
|
+
entity_map: Record<string, string>;
|
|
146
|
+
/** Which source wrote each field, per entity. entity_id → field_name → source_name */
|
|
147
|
+
field_origins?: Record<string, Record<string, string>>;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Result of reconciling multiple extracted records into one entity.
|
|
151
|
+
*/
|
|
152
|
+
export interface ReconciliationMatch {
|
|
153
|
+
entity_id: string;
|
|
154
|
+
entity_type: string;
|
|
155
|
+
target_repo: string;
|
|
156
|
+
records: ExtractedRecord[];
|
|
157
|
+
match_type: 'exact-id' | 'email' | 'name-variant' | 'fuzzy-name' | 'single';
|
|
158
|
+
action: 'create' | 'update';
|
|
159
|
+
merged_frontmatter: Record<string, any>;
|
|
160
|
+
merged_content: string;
|
|
161
|
+
confidence: number;
|
|
162
|
+
notes: string;
|
|
163
|
+
field_sources?: Record<string, string>;
|
|
164
|
+
/** Co-location config, if this entity should be written as sub-content. */
|
|
165
|
+
co_locate?: {
|
|
166
|
+
parent_field: string;
|
|
167
|
+
subfolder: string;
|
|
168
|
+
};
|
|
169
|
+
/** Write mode: 'entity' (default) or 'collection' (loose file). */
|
|
170
|
+
write_mode?: 'entity' | 'collection';
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Entity type detected from MCP tool inspection during source setup.
|
|
174
|
+
*/
|
|
175
|
+
export interface DetectedEntityType {
|
|
176
|
+
source_type: string;
|
|
177
|
+
list_tool: string;
|
|
178
|
+
get_tool?: string;
|
|
179
|
+
suggested_entity_type?: string;
|
|
180
|
+
suggested_repo?: string;
|
|
181
|
+
count?: number;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* A file discovered from a file-based source (e.g. Obsidian).
|
|
185
|
+
*/
|
|
186
|
+
export interface SourceFile {
|
|
187
|
+
path: string;
|
|
188
|
+
name: string;
|
|
189
|
+
content?: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Rule describing how to derive secondary entities from primary records.
|
|
193
|
+
*/
|
|
194
|
+
export interface DerivationRule {
|
|
195
|
+
/** The entity type to derive (e.g. "person") */
|
|
196
|
+
entity_type: string;
|
|
197
|
+
/** Schema fields that reference this type (e.g. "attendees") */
|
|
198
|
+
source_fields: string[];
|
|
199
|
+
/** Entity types whose records contain those fields */
|
|
200
|
+
from_entity_types: string[];
|
|
201
|
+
/** Repo to write derived entities to */
|
|
202
|
+
target_repo: string;
|
|
203
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/sync/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|