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,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: obsidian-source-setup
|
|
3
|
+
description: Scaffold an Obsidian vault into a sync source config — explore vault structure, map directories to entity types, build field maps from frontmatter
|
|
4
|
+
loading: on-demand
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Obsidian Source Setup
|
|
8
|
+
|
|
9
|
+
Guide for mapping any Obsidian vault to a Studiograph sync source config. Every vault is different — follow these steps to explore the vault and build a config tailored to its structure.
|
|
10
|
+
|
|
11
|
+
## Step 1: Explore the Vault
|
|
12
|
+
|
|
13
|
+
Before writing any config, understand the vault's organization.
|
|
14
|
+
|
|
15
|
+
1. **List top-level directories** — use the Obsidian MCP connector or read the filesystem directly:
|
|
16
|
+
- Note every top-level folder name
|
|
17
|
+
- Identify which are content folders vs system folders (`.obsidian/`, `.smart-env/`, `Attachments/`, `Templates/`)
|
|
18
|
+
- Check for subdirectory structure (e.g., `Organizations/Clients/`, `Organizations/Vendors/`)
|
|
19
|
+
|
|
20
|
+
2. **Count files per directory** — understand the scale:
|
|
21
|
+
- Large directories (100+) are likely core entity types
|
|
22
|
+
- Small directories (<10) may not be worth a dedicated mapping
|
|
23
|
+
|
|
24
|
+
3. **Check for nested content** — some vaults use flat files, others use subfolders:
|
|
25
|
+
- `People/John Smith.md` (flat) — each file is one entity
|
|
26
|
+
- `Projects/Acme/Acme.md` + `Projects/Acme/SOW.md` (nested) — folder per entity with sub-documents
|
|
27
|
+
|
|
28
|
+
## Step 2: Sample Frontmatter
|
|
29
|
+
|
|
30
|
+
Read the first 25-30 lines of 2-3 files per directory to see what YAML frontmatter exists.
|
|
31
|
+
|
|
32
|
+
**Key things to look for:**
|
|
33
|
+
- Which fields are present (even if empty)
|
|
34
|
+
- Wikilink references: `client: "[[Acme Corp]]"` or `related_people: ["[[John Smith]]"]`
|
|
35
|
+
- Tag conventions: `tags: [project/active]`, `tags: ["#person"]`, `tags: [sop, operations]`
|
|
36
|
+
- Date formats: `date: 2026-01-15`, `start_date: 2026-01-15`
|
|
37
|
+
- Status encoding: frontmatter `status:` field vs tag-based `tags: [project/active]`
|
|
38
|
+
|
|
39
|
+
**Frontmatter vs no frontmatter:**
|
|
40
|
+
- Files WITH frontmatter (YAML between `---` fences) → use `frontmatter` extraction mode
|
|
41
|
+
- Files WITHOUT frontmatter (plain markdown) → use `unstructured` mode (LLM extraction, slower)
|
|
42
|
+
- If a directory has a mix, prefer `frontmatter` — files without frontmatter will be skipped, which is often acceptable
|
|
43
|
+
|
|
44
|
+
## Step 3: Map Directories to Entity Types
|
|
45
|
+
|
|
46
|
+
For each content directory, decide which Studiograph entity type it maps to. Use the directory name, file content, and frontmatter fields as signals.
|
|
47
|
+
|
|
48
|
+
### Entity Type Reference
|
|
49
|
+
|
|
50
|
+
**Project repo types** (time-bound, engagement-specific):
|
|
51
|
+
| Type | Use when | Key fields |
|
|
52
|
+
|------|----------|------------|
|
|
53
|
+
| `project` | Client engagements, initiatives | name, client, start_date, end_date, status, team |
|
|
54
|
+
| `meeting` | Meetings, events, conferences | name, date, attendees, agenda, action_items |
|
|
55
|
+
| `task` | Action items, tickets | name, assignee, due_date, status, priority |
|
|
56
|
+
| `deliverable` | Outputs, milestones | name, project, status, due_date |
|
|
57
|
+
| `brief` | Project briefs, RFPs | project_name, client, objectives |
|
|
58
|
+
| `artifact` | Files, documents, assets | name, type, project, url |
|
|
59
|
+
| `decision` | Architectural/business decisions | title, date, status, rationale |
|
|
60
|
+
|
|
61
|
+
**Function repo types** (operational, cross-project):
|
|
62
|
+
| Type | Use when | Key fields |
|
|
63
|
+
|------|----------|------------|
|
|
64
|
+
| `person` | People, contacts, team members | name, role, email, status, organization |
|
|
65
|
+
| `client` | Companies, organizations (as clients) | name, type, status, industry, contacts |
|
|
66
|
+
| `vendor` | Vendors, partners, freelancers | name, type, status, services |
|
|
67
|
+
| `deal` | Sales pipeline entries | name, client, stage, deal_value |
|
|
68
|
+
| `proposal` | Proposals, SOWs | name, client, status, deliverables |
|
|
69
|
+
| `contract` | Contracts, agreements | name, type, client, status |
|
|
70
|
+
| `financial-plan` | Budgets, rate cards, P&L | name, type, period |
|
|
71
|
+
| `role` | Job descriptions, org structure | title, department, level, type |
|
|
72
|
+
|
|
73
|
+
**Shared resource types** (reference, reusable):
|
|
74
|
+
| Type | Use when | Key fields |
|
|
75
|
+
|------|----------|------------|
|
|
76
|
+
| `process` | SOPs, workflows, methodologies | name, description, steps, owner |
|
|
77
|
+
| `standard` | Guidelines, conventions | name, category, guidelines |
|
|
78
|
+
| `template` | Reusable templates | name, category, template_content |
|
|
79
|
+
| `reference` | Articles, research, bookmarks | name, type, source, link |
|
|
80
|
+
| `technique` | Methods, frameworks | name, category, difficulty |
|
|
81
|
+
| `practice-area` | Service lines, capabilities | name, description, capabilities |
|
|
82
|
+
| `case-study` | Portfolio work, showcases | title, client, year, practice_areas |
|
|
83
|
+
|
|
84
|
+
### Common Obsidian Directory Mappings
|
|
85
|
+
|
|
86
|
+
These are patterns seen across vaults — adapt to the actual vault:
|
|
87
|
+
|
|
88
|
+
| Directory pattern | Likely entity type | Notes |
|
|
89
|
+
|-------------------|--------------------|-------|
|
|
90
|
+
| `Projects/` | `project` | May have sub-documents (see nested content below) |
|
|
91
|
+
| `People/`, `Contacts/` | `person` | Usually flat files |
|
|
92
|
+
| `Team/`, `Staff/` | `person` | Often richer frontmatter than external contacts |
|
|
93
|
+
| `Clients/`, `Companies/`, `Organizations/` | `client` | May have subdirectories by relationship type |
|
|
94
|
+
| `Meetings/`, `Meeting Notes/` | `meeting` | Date-prefixed filenames common |
|
|
95
|
+
| `Tasks/`, `Action Items/` | `task` | May overlap with a task manager integration |
|
|
96
|
+
| `SOPs/`, `Processes/`, `Workflows/` | `process` | Often has category/status/owner fields |
|
|
97
|
+
| `Areas/`, `Practice Areas/`, `Capabilities/` | `practice-area` | May lack frontmatter |
|
|
98
|
+
| `Case Studies/`, `Portfolio/`, `Work/` | `case-study` | Often has client, year, url fields |
|
|
99
|
+
| `Research/`, `References/`, `Resources/` | `reference` | Bookmarks, articles, links |
|
|
100
|
+
| `HR/`, `Roles/`, `Job Descriptions/` | `role` | Job postings, org structure |
|
|
101
|
+
| `Finances/`, `Finance/`, `Budgets/` | `financial-plan` | Rate cards, P&L, budgets |
|
|
102
|
+
| `Standards/`, `Guidelines/` | `standard` | Naming conventions, code standards |
|
|
103
|
+
| `Templates/` | `template` | Reusable document templates |
|
|
104
|
+
| `Proposals/`, `SOWs/` | `proposal` | Client proposals |
|
|
105
|
+
| `Contracts/` | `contract` | Agreements, NDAs |
|
|
106
|
+
| `Events/`, `Conferences/` | `meeting` | No dedicated event type — meeting is closest |
|
|
107
|
+
| `Emails/` | `artifact` | No dedicated email type |
|
|
108
|
+
| `Archive/` | same as active, disabled | Enable later if needed |
|
|
109
|
+
|
|
110
|
+
### Directories to Skip
|
|
111
|
+
|
|
112
|
+
- `.obsidian/` — Obsidian config
|
|
113
|
+
- `.smart-env/` — Smart Connections plugin data
|
|
114
|
+
- `Attachments/`, `Assets/`, `Media/` — binary files
|
|
115
|
+
- `Templates/` — often just scaffolding, not real entities (evaluate per vault)
|
|
116
|
+
- `Daily Notes/` — usually ephemeral, not entity-worthy
|
|
117
|
+
- `Clippings/` — web clippings, low signal
|
|
118
|
+
|
|
119
|
+
### Handling Nested Project Content
|
|
120
|
+
|
|
121
|
+
When a `Projects/` directory has subfolders with multiple files per project, ALL files get classified as the mapping's entity type. Sub-documents (meeting agendas, SOWs, concepts) become project entities.
|
|
122
|
+
|
|
123
|
+
**Options:**
|
|
124
|
+
1. **Accept and review** — the `studiograph review` step lets users fix misclassifications before committing
|
|
125
|
+
2. **Use `unstructured` mode** — the LLM can infer the correct entity type from content (slower, costs per file)
|
|
126
|
+
3. **Co-locate sub-files** — if sub-documents reference their parent project in frontmatter (e.g., `related_projects: ["[[My Project]]"]`), add `co_locate: { parent_field: "related_projects", subfolder: "notes" }` to write them as sub-content
|
|
127
|
+
|
|
128
|
+
## Step 4: Choose Extraction Mode Per Mapping
|
|
129
|
+
|
|
130
|
+
| Condition | Mode | Cost |
|
|
131
|
+
|-----------|------|------|
|
|
132
|
+
| Files have YAML frontmatter with useful fields | `frontmatter` | Free (no LLM) |
|
|
133
|
+
| Files are plain markdown, no frontmatter | `unstructured` | LLM call per file |
|
|
134
|
+
| Mix of both | `frontmatter` | Free — files without frontmatter are skipped |
|
|
135
|
+
| Small directory (<20 files) with no frontmatter | `unstructured` | Acceptable LLM cost |
|
|
136
|
+
| Large directory (100+) with no frontmatter | `frontmatter` or skip | `unstructured` would be expensive |
|
|
137
|
+
|
|
138
|
+
## Step 5: Build Field Maps
|
|
139
|
+
|
|
140
|
+
For each `frontmatter` mapping, build a `field_map` from the sampled YAML fields.
|
|
141
|
+
|
|
142
|
+
**Rules:**
|
|
143
|
+
- Keys are the Obsidian frontmatter field names (as they appear in the YAML)
|
|
144
|
+
- Values are the Studiograph entity field names (from the entity type reference above)
|
|
145
|
+
- Only map fields that actually exist in the frontmatter — don't invent mappings
|
|
146
|
+
- Wikilink fields (`"[[Entity Name]]"`) map naturally — the sync pipeline handles them
|
|
147
|
+
- Always include `tags` if the vault uses tags
|
|
148
|
+
- Use `id_from: "_filename"` and `content_from: "_body"` for all Obsidian mappings
|
|
149
|
+
|
|
150
|
+
**Common Obsidian frontmatter fields and their typical targets:**
|
|
151
|
+
|
|
152
|
+
| Obsidian field | Target field | Notes |
|
|
153
|
+
|----------------|-------------|-------|
|
|
154
|
+
| `title` / `name` | `name` or `title` | Entity display name |
|
|
155
|
+
| `status` | `status` | Map values with `status_map` if conventions differ |
|
|
156
|
+
| `client` | `client` | Often a wikilink |
|
|
157
|
+
| `date` | `date` | ISO date |
|
|
158
|
+
| `start_date` / `end_date` | `start_date` / `end_date` | Date range |
|
|
159
|
+
| `tags` | `tags` | Array of strings |
|
|
160
|
+
| `email` | `email` | |
|
|
161
|
+
| `role` / `title` (on person) | `role` | Obsidian often uses `title` for role |
|
|
162
|
+
| `related_people` | `contacts` or `attendees` | Usually wikilink array |
|
|
163
|
+
| `related_organizations` | `related_organizations` | Usually wikilink array |
|
|
164
|
+
| `related_projects` | `related_projects` | Usually wikilink array |
|
|
165
|
+
| `related_areas` | `related_areas` | Usually wikilink array |
|
|
166
|
+
| `url` / `website` | `website_url` or `link` | |
|
|
167
|
+
| `sectors` | `sectors` | Industry/domain tags |
|
|
168
|
+
| `practice_areas` | `practice_areas` | Service line references |
|
|
169
|
+
| `year` | `year` | For case studies |
|
|
170
|
+
|
|
171
|
+
## Step 6: Determine Target Repos
|
|
172
|
+
|
|
173
|
+
Check which repos exist in the workspace (`ls` the workspace directory or use `graph_list_repos`). Map entity types to existing repos:
|
|
174
|
+
|
|
175
|
+
| Entity types | Typical repo |
|
|
176
|
+
|-------------|-------------|
|
|
177
|
+
| project, case-study, deliverable, brief, artifact | `projects` |
|
|
178
|
+
| person, role | `people` |
|
|
179
|
+
| client, vendor | `clients` |
|
|
180
|
+
| meeting | `meetings` |
|
|
181
|
+
| process, standard, template, reference, technique, practice-area | A shared-resource repo if one exists, otherwise `projects` |
|
|
182
|
+
| deal, proposal, contract, financial-plan | A function repo if one exists, otherwise `projects` |
|
|
183
|
+
|
|
184
|
+
If a needed repo doesn't exist, the sync pipeline auto-creates it on `sync_apply`.
|
|
185
|
+
|
|
186
|
+
## Step 7: Write the Config
|
|
187
|
+
|
|
188
|
+
Generate `.studiograph/sources/obsidian.json` with all mappings. Present it to the user for review before writing.
|
|
189
|
+
|
|
190
|
+
**Template:**
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"name": "obsidian-<vault-name>",
|
|
194
|
+
"connector": "obsidian-<vault-name>",
|
|
195
|
+
"enabled": true,
|
|
196
|
+
"added_at": "<ISO timestamp>",
|
|
197
|
+
"entity_mappings": [
|
|
198
|
+
{
|
|
199
|
+
"source_type": "<descriptive-name>",
|
|
200
|
+
"entity_type": "<studiograph-type>",
|
|
201
|
+
"target_repo": "<repo-name>",
|
|
202
|
+
"extraction_mode": "frontmatter",
|
|
203
|
+
"enabled": true,
|
|
204
|
+
"directory_patterns": ["<VaultDir>/"],
|
|
205
|
+
"list_tool": "list_vault_files",
|
|
206
|
+
"read_tool": "get_vault_file",
|
|
207
|
+
"field_map": { ... },
|
|
208
|
+
"id_from": "_filename",
|
|
209
|
+
"content_from": "_body"
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Checklist before writing:**
|
|
216
|
+
- [ ] Every content directory has a mapping (or a reason to skip)
|
|
217
|
+
- [ ] `directory_patterns` use trailing slash and match the vault's exact directory names (case-sensitive)
|
|
218
|
+
- [ ] `list_tool` and `read_tool` are set to `"list_vault_files"` and `"get_vault_file"` for Obsidian
|
|
219
|
+
- [ ] Field maps only reference frontmatter fields that actually exist
|
|
220
|
+
- [ ] Directories with no frontmatter use `unstructured` mode or are skipped
|
|
221
|
+
- [ ] Subdirectories are handled (e.g., `Organizations/Clients/` not just `Organizations/`)
|
|
222
|
+
- [ ] `target_repo` values match existing repos or the user is aware new ones will be created
|
|
223
|
+
- [ ] Disabled mappings are marked `enabled: false` with a comment-like `source_type` explaining why
|
|
224
|
+
|
|
225
|
+
## Multiple Vaults
|
|
226
|
+
|
|
227
|
+
Each vault needs its own connector and source config. The MCP Tools binary is vault-specific — it connects to the Local REST API instance running in its vault.
|
|
228
|
+
|
|
229
|
+
1. Install both plugins (Local REST API + MCP Tools) in each vault
|
|
230
|
+
2. Create a connector per vault at `~/.studiograph/connectors/obsidian-<name>.json`, each pointing to that vault's `mcp-server` binary and API key
|
|
231
|
+
3. Create a source config per vault at `.studiograph/sources/obsidian-<name>.json` with directory patterns matching that vault's structure
|
|
232
|
+
4. Run `studiograph sync` (no arguments) to sync all enabled sources in one pass
|
|
233
|
+
|
|
234
|
+
**Port conflict:** Each vault's Local REST API runs on port 27124 by default. Only one vault can use a given port at a time. If both vaults need to be open simultaneously, change the port in one vault's Local REST API settings.
|
|
235
|
+
|
|
236
|
+
See `docs/obsidian-setup.md` for full connector setup and troubleshooting.
|
|
237
|
+
|
|
238
|
+
## After Setup
|
|
239
|
+
|
|
240
|
+
1. **Dry run:** `sync_run({ sources: ["obsidian"], dryRun: true })` — verify extraction counts look right
|
|
241
|
+
2. **Full run:** `sync_run({ sources: ["obsidian"] })` — extract to staging
|
|
242
|
+
3. **Review:** `sync_status` then `studiograph review` — spot-check entity types and field values
|
|
243
|
+
4. **Apply:** `sync_apply` — write entity files
|
|
244
|
+
5. **Commit:** `studiograph commit` — git commit across repos
|
|
245
|
+
|
|
246
|
+
See the `sync-setup` skill for the full sync workflow and the `sync-configuration` skill for field map syntax details.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Loader — prompt skills for the Studiograph agent.
|
|
3
|
+
*
|
|
4
|
+
* Skills are markdown files with YAML frontmatter that inject domain-specific
|
|
5
|
+
* knowledge into the agent's system prompt. Two formats supported:
|
|
6
|
+
*
|
|
7
|
+
* Directory skill:
|
|
8
|
+
* skills/create-deck/
|
|
9
|
+
* skill.md ← required entrypoint
|
|
10
|
+
* slide-types.md ← optional sub-files
|
|
11
|
+
*
|
|
12
|
+
* Single-file skill:
|
|
13
|
+
* skills/quick-tip.md
|
|
14
|
+
*
|
|
15
|
+
* Frontmatter fields:
|
|
16
|
+
* name: kebab-case identifier (defaults to directory/filename)
|
|
17
|
+
* description: shown in skill index so agent knows when to load it
|
|
18
|
+
* loading: "on-demand" (default) | "eager" (inlined in system prompt)
|
|
19
|
+
*/
|
|
20
|
+
export interface SkillMeta {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
loading: 'eager' | 'on-demand';
|
|
24
|
+
dir: string;
|
|
25
|
+
entrypoint: string;
|
|
26
|
+
isDirectory: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Scan one or more skill directories and return a de-duplicated skill index.
|
|
30
|
+
* Directories are processed in order — first occurrence of a name wins,
|
|
31
|
+
* so workspace-level skills override app-bundled skills.
|
|
32
|
+
*/
|
|
33
|
+
export declare function loadSkillIndex(skillsDirs: string[]): SkillMeta[];
|
|
34
|
+
/**
|
|
35
|
+
* Load the full content of a skill's entrypoint or a named sub-file.
|
|
36
|
+
* Sanitises the file parameter to prevent path traversal.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadSkillContent(meta: SkillMeta, file?: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Build the skill index section to append to the system prompt.
|
|
41
|
+
* Eager skills are inlined separately; this lists only on-demand skills.
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildSkillIndexPrompt(skills: SkillMeta[]): string;
|
|
44
|
+
/**
|
|
45
|
+
* Return the full content of all eager skills, to be injected directly
|
|
46
|
+
* into the system prompt at startup.
|
|
47
|
+
*/
|
|
48
|
+
export declare function loadEagerSkills(skills: SkillMeta[]): string;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Loader — prompt skills for the Studiograph agent.
|
|
3
|
+
*
|
|
4
|
+
* Skills are markdown files with YAML frontmatter that inject domain-specific
|
|
5
|
+
* knowledge into the agent's system prompt. Two formats supported:
|
|
6
|
+
*
|
|
7
|
+
* Directory skill:
|
|
8
|
+
* skills/create-deck/
|
|
9
|
+
* skill.md ← required entrypoint
|
|
10
|
+
* slide-types.md ← optional sub-files
|
|
11
|
+
*
|
|
12
|
+
* Single-file skill:
|
|
13
|
+
* skills/quick-tip.md
|
|
14
|
+
*
|
|
15
|
+
* Frontmatter fields:
|
|
16
|
+
* name: kebab-case identifier (defaults to directory/filename)
|
|
17
|
+
* description: shown in skill index so agent knows when to load it
|
|
18
|
+
* loading: "on-demand" (default) | "eager" (inlined in system prompt)
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readdirSync, readFileSync } from 'fs';
|
|
21
|
+
import { join, extname, basename } from 'path';
|
|
22
|
+
/**
|
|
23
|
+
* Minimal YAML frontmatter parser — handles the subset used by skills.
|
|
24
|
+
*/
|
|
25
|
+
function parseFrontmatter(content) {
|
|
26
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
27
|
+
if (!match) {
|
|
28
|
+
return { meta: {}, body: content };
|
|
29
|
+
}
|
|
30
|
+
const meta = {};
|
|
31
|
+
for (const line of match[1].split('\n')) {
|
|
32
|
+
const colon = line.indexOf(':');
|
|
33
|
+
if (colon === -1)
|
|
34
|
+
continue;
|
|
35
|
+
const key = line.slice(0, colon).trim();
|
|
36
|
+
const value = line.slice(colon + 1).trim();
|
|
37
|
+
if (key)
|
|
38
|
+
meta[key] = value;
|
|
39
|
+
}
|
|
40
|
+
return { meta, body: match[2] };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Scan one or more skill directories and return a de-duplicated skill index.
|
|
44
|
+
* Directories are processed in order — first occurrence of a name wins,
|
|
45
|
+
* so workspace-level skills override app-bundled skills.
|
|
46
|
+
*/
|
|
47
|
+
export function loadSkillIndex(skillsDirs) {
|
|
48
|
+
const skills = [];
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
for (const dir of skillsDirs) {
|
|
51
|
+
if (!existsSync(dir))
|
|
52
|
+
continue;
|
|
53
|
+
let entries;
|
|
54
|
+
try {
|
|
55
|
+
entries = readdirSync(dir);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
for (const entry of entries) {
|
|
61
|
+
if (entry.startsWith('.'))
|
|
62
|
+
continue;
|
|
63
|
+
const entryPath = join(dir, entry);
|
|
64
|
+
// Directory skill: subdirectory containing skill.md
|
|
65
|
+
const skillMd = join(entryPath, 'skill.md');
|
|
66
|
+
if (existsSync(skillMd)) {
|
|
67
|
+
try {
|
|
68
|
+
const content = readFileSync(skillMd, 'utf-8');
|
|
69
|
+
const { meta } = parseFrontmatter(content);
|
|
70
|
+
const name = meta.name || entry;
|
|
71
|
+
if (!seen.has(name)) {
|
|
72
|
+
seen.add(name);
|
|
73
|
+
skills.push({
|
|
74
|
+
name,
|
|
75
|
+
description: meta.description || '',
|
|
76
|
+
loading: meta.loading === 'eager' ? 'eager' : 'on-demand',
|
|
77
|
+
dir: entryPath,
|
|
78
|
+
entrypoint: skillMd,
|
|
79
|
+
isDirectory: true,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// skip malformed skill
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
// Single-file skill: top-level .md file with valid frontmatter
|
|
89
|
+
if (extname(entry) === '.md') {
|
|
90
|
+
try {
|
|
91
|
+
const content = readFileSync(entryPath, 'utf-8');
|
|
92
|
+
const { meta } = parseFrontmatter(content);
|
|
93
|
+
// Must have at least name or description to be a skill
|
|
94
|
+
if (!meta.name && !meta.description)
|
|
95
|
+
continue;
|
|
96
|
+
const name = meta.name || basename(entry, '.md');
|
|
97
|
+
if (!seen.has(name)) {
|
|
98
|
+
seen.add(name);
|
|
99
|
+
skills.push({
|
|
100
|
+
name,
|
|
101
|
+
description: meta.description || '',
|
|
102
|
+
loading: meta.loading === 'eager' ? 'eager' : 'on-demand',
|
|
103
|
+
dir,
|
|
104
|
+
entrypoint: entryPath,
|
|
105
|
+
isDirectory: false,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// skip
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return skills;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Load the full content of a skill's entrypoint or a named sub-file.
|
|
119
|
+
* Sanitises the file parameter to prevent path traversal.
|
|
120
|
+
*/
|
|
121
|
+
export function loadSkillContent(meta, file) {
|
|
122
|
+
if (file) {
|
|
123
|
+
if (!meta.isDirectory) {
|
|
124
|
+
return `Error: skill "${meta.name}" is a single-file skill with no sub-files.`;
|
|
125
|
+
}
|
|
126
|
+
// Allow only simple filenames — no slashes, no dots at start
|
|
127
|
+
const safeName = file.replace(/[^a-zA-Z0-9._-]/g, '');
|
|
128
|
+
if (!safeName || safeName.startsWith('.')) {
|
|
129
|
+
return `Error: invalid sub-file name "${file}".`;
|
|
130
|
+
}
|
|
131
|
+
const filePath = join(meta.dir, safeName);
|
|
132
|
+
if (!existsSync(filePath)) {
|
|
133
|
+
return `Error: sub-file "${safeName}" not found in skill "${meta.name}".`;
|
|
134
|
+
}
|
|
135
|
+
return readFileSync(filePath, 'utf-8');
|
|
136
|
+
}
|
|
137
|
+
return readFileSync(meta.entrypoint, 'utf-8');
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Build the skill index section to append to the system prompt.
|
|
141
|
+
* Eager skills are inlined separately; this lists only on-demand skills.
|
|
142
|
+
*/
|
|
143
|
+
export function buildSkillIndexPrompt(skills) {
|
|
144
|
+
const onDemand = skills.filter(s => s.loading === 'on-demand');
|
|
145
|
+
if (onDemand.length === 0)
|
|
146
|
+
return '';
|
|
147
|
+
const lines = [
|
|
148
|
+
'## Available Skills',
|
|
149
|
+
'',
|
|
150
|
+
'Call `load_skill` to load domain-specific guidance when it is relevant to the current task.',
|
|
151
|
+
'',
|
|
152
|
+
...onDemand.map(s => `- **${s.name}** — ${s.description}`),
|
|
153
|
+
];
|
|
154
|
+
return lines.join('\n');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Return the full content of all eager skills, to be injected directly
|
|
158
|
+
* into the system prompt at startup.
|
|
159
|
+
*/
|
|
160
|
+
export function loadEagerSkills(skills) {
|
|
161
|
+
return skills
|
|
162
|
+
.filter(s => s.loading === 'eager')
|
|
163
|
+
.map(s => loadSkillContent(s))
|
|
164
|
+
.join('\n\n---\n\n');
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=skill-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../../../src/agent/skills/skill-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync-configuration
|
|
3
|
+
description: Reference for building sync source configs — field maps, transforms, co-location, extraction modes
|
|
4
|
+
loading: eager
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Sync Configuration Reference
|
|
8
|
+
|
|
9
|
+
Use this reference when helping users build or modify source configs at `.studiograph/sources/<name>.json`.
|
|
10
|
+
|
|
11
|
+
## Source Config Structure
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"name": "linear",
|
|
16
|
+
"connector": "linear",
|
|
17
|
+
"enabled": true,
|
|
18
|
+
"added_at": "2026-02-15T10:00:00.000Z",
|
|
19
|
+
"entity_mappings": [ ... ],
|
|
20
|
+
"field_priority": { "email": "pipedrive" }
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `connector` references a connector in `~/.studiograph/connectors/`
|
|
25
|
+
- `field_priority` — optional per-field merge priority when multiple sources write the same entity
|
|
26
|
+
- `entity_mappings` — array of mappings, each maps one external entity type to a Studiograph type
|
|
27
|
+
|
|
28
|
+
## Entity Mapping Fields
|
|
29
|
+
|
|
30
|
+
| Field | Required | Description |
|
|
31
|
+
|-------|----------|-------------|
|
|
32
|
+
| `source_type` | Yes | What the source calls this type (e.g. `"deal"`, `"issue"`) |
|
|
33
|
+
| `entity_type` | Yes | Studiograph type (e.g. `"project"`, `"task"`, `"meeting"`) |
|
|
34
|
+
| `target_repo` | Yes | Repo to write to (e.g. `"projects"`) |
|
|
35
|
+
| `extraction_mode` | Yes | `"structured"`, `"frontmatter"`, or `"unstructured"` |
|
|
36
|
+
| `id_from` | No | Source field for entity_id (default `"title"`, or `"_filename"` for frontmatter mode) |
|
|
37
|
+
| `content_from` | No | Source field for markdown body (or `"_body"` for frontmatter mode) |
|
|
38
|
+
| `field_map` | No | Maps source fields to entity fields (see Field Map Syntax) |
|
|
39
|
+
| `status_map` | No | Maps source status values to entity statuses (case-insensitive) |
|
|
40
|
+
| `fetch_details` | No | Fetch full record per listed ID (for sparse list APIs) |
|
|
41
|
+
| `list_limit` | No | Override limit param for list tool |
|
|
42
|
+
| `list_params` | No | Extra params for list tool. Pass array for multiple list calls merged |
|
|
43
|
+
| `directory_patterns` | No | Directory patterns for file sources (frontmatter/unstructured) |
|
|
44
|
+
| `write_mode` | No | `"entity"` (default, `id/main.md` folder) or `"collection"` (flat `id.md` file) |
|
|
45
|
+
| `co_locate` | No | Co-locate as sub-content inside parent entity folder |
|
|
46
|
+
| `list_tool` | No | Explicit MCP tool name for listing records (bypasses heuristic matching) |
|
|
47
|
+
| `read_tool` | No | Explicit MCP tool name for reading records (bypasses heuristic matching) |
|
|
48
|
+
|
|
49
|
+
## Extraction Modes
|
|
50
|
+
|
|
51
|
+
- **`structured`** — API JSON → field_map → frontmatter. No LLM. For Pipedrive, Linear, Granola, Asana.
|
|
52
|
+
- **`frontmatter`** — Markdown files with YAML → field_map. No LLM. For Obsidian. Supports `_filename` and `_body` sentinels.
|
|
53
|
+
- **`unstructured`** — Freeform text → LLM extraction. Slow, expensive. Last resort when no structured metadata exists.
|
|
54
|
+
|
|
55
|
+
## Field Map Syntax
|
|
56
|
+
|
|
57
|
+
Keys are source field paths, values are entity field names or FieldTransform objects.
|
|
58
|
+
|
|
59
|
+
**Simple string:** `"title": "name"` — direct copy
|
|
60
|
+
**Dot-notation:** `"org_id.name": "organization"` — nested access
|
|
61
|
+
**Array index:** `"email[0].value": "email"` — specific array element
|
|
62
|
+
**FieldTransform object:**
|
|
63
|
+
```json
|
|
64
|
+
{ "org_name": { "field": "client", "transform": "wikilink" } }
|
|
65
|
+
```
|
|
66
|
+
FieldTransform fields: `field` (target name), `transform` (transform type), `subfield` (optional — extract nested path from each array element before transforming)
|
|
67
|
+
|
|
68
|
+
### Subfield example
|
|
69
|
+
Source returns: `[{ "details": { "person": { "name": "Alice" } } }, ...]`
|
|
70
|
+
Config: `{ "field": "attendees", "transform": "wikilink-array", "subfield": "details.person.name" }`
|
|
71
|
+
Result: `["[[alice]]", ...]`
|
|
72
|
+
|
|
73
|
+
## Transforms
|
|
74
|
+
|
|
75
|
+
| Transform | Input | Output |
|
|
76
|
+
|-----------|-------|--------|
|
|
77
|
+
| `direct` | `"hello"` | `"hello"` (passthrough) |
|
|
78
|
+
| `kebab-case` | `"Acme Corp"` | `"acme-corp"` |
|
|
79
|
+
| `date-iso` | `"2026-02-20T14:30:00Z"` | `"2026-02-20"` |
|
|
80
|
+
| `wikilink` | `"Acme Corp"` | `"[[acme-corp]]"` |
|
|
81
|
+
| `wikilink-array` | `["Alice", "Bob"]` | `["[[alice]]", "[[bob]]"]` |
|
|
82
|
+
|
|
83
|
+
## Co-Location
|
|
84
|
+
|
|
85
|
+
Writes entities as sub-content files inside a parent entity folder instead of standalone entity folders.
|
|
86
|
+
|
|
87
|
+
**Config:** Add `co_locate` to a mapping:
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"co_locate": { "parent_field": "project", "subfolder": "tasks" },
|
|
91
|
+
"field_map": { "project": { "field": "project", "transform": "wikilink" } }
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Result path:** `{target_repo}/{parent_id}/{subfolder}/{entity_id}.md`
|
|
96
|
+
Example: `projects/cooper-hewitt-brand-refresh/tasks/sch-101.md`
|
|
97
|
+
|
|
98
|
+
**Rules:**
|
|
99
|
+
- `parent_field` must be a wikilink target in `field_map` so the reference is available
|
|
100
|
+
- Entities without a parent value are **skipped** (not an error)
|
|
101
|
+
- Co-located files are sub-content, not graph entities (no `entity_id/main.md` folder)
|
|
102
|
+
- `target_repo` should be the repo where the **parent** entities live
|
|
103
|
+
|
|
104
|
+
## Write Mode
|
|
105
|
+
|
|
106
|
+
Controls how entities are written to disk:
|
|
107
|
+
|
|
108
|
+
- **`entity`** (default) — `repo/entity-id/main.md` folder. Fully indexed, supports sub-content. Use for core types (projects, clients, people).
|
|
109
|
+
- **`collection`** — `repo/entity-id.md` flat file. Simpler, no folder overhead. Use for high-volume types (meetings, notes, references).
|
|
110
|
+
|
|
111
|
+
## Explicit MCP Tool Selection
|
|
112
|
+
|
|
113
|
+
For file-based sources (frontmatter, unstructured), add `list_tool` and `read_tool` when the connector's tool names don't follow predictable patterns:
|
|
114
|
+
```json
|
|
115
|
+
{ "list_tool": "list_vault_files", "read_tool": "get_vault_file" }
|
|
116
|
+
```
|
|
117
|
+
When omitted, the pipeline uses heuristic matching (looking for tools containing "list", "read", "get", etc.).
|
|
118
|
+
|
|
119
|
+
## Sentinels (frontmatter mode only)
|
|
120
|
+
|
|
121
|
+
- `_filename` in `id_from` — entity ID from the file's name (slugified, `.md` stripped)
|
|
122
|
+
- `_body` in `content_from` — markdown body from file content below the `---` frontmatter fence
|
|
123
|
+
|
|
124
|
+
## Built-in Definitions
|
|
125
|
+
|
|
126
|
+
| Source | Mappings | Notes |
|
|
127
|
+
|--------|----------|-------|
|
|
128
|
+
| **Pipedrive** | deal→project, person→person, org→client | Ready to sync |
|
|
129
|
+
| **Granola** | document→meeting | `fetch_details: true`, `list_limit: 1000` |
|
|
130
|
+
| **Linear** | issue→task (co-located under projects), project→project | Issues use `co_locate` |
|
|
131
|
+
| **Asana** | task→task, project→project | Needs `list_params: { workspace: "GID" }` |
|
|
132
|
+
| **Obsidian** | Example mappings only (`.template` file) | Needs customization per vault |
|
|
133
|
+
|
|
134
|
+
## Configuration Patterns
|
|
135
|
+
|
|
136
|
+
**Adding co-location to any mapping:** Add `co_locate: { parent_field, subfolder }` and ensure `parent_field` is a wikilink target in `field_map`.
|
|
137
|
+
|
|
138
|
+
**Multiple list calls:** Set `list_params` as an array: `[{ workspace: "123", archived: false }, { workspace: "123", archived: true }]`
|
|
139
|
+
|
|
140
|
+
**Custom source (no built-in):** Create a source config with `entity_mappings` from scratch. Choose extraction_mode, define field_map targeting entity schema fields, set target_repo.
|
|
141
|
+
|
|
142
|
+
**Overriding built-in defaults:** Pass custom `entity_mappings` to `sync_setup_source` — they replace the defaults entirely. Or edit `.studiograph/sources/<name>.json` directly.
|
|
143
|
+
|
|
144
|
+
**Status maps:** Map source status strings (case-insensitive) to Studiograph enums. Common patterns: Pipedrive (`won→completed, lost→archived, open→active`), Linear issues (`Backlog→open, In Progress→in-progress, Done→done, Canceled→cancelled`).
|