studiograph 1.3.47 → 1.3.48-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/README.md +26 -16
- package/dist/agent/agent-pool.d.ts +117 -0
- package/dist/agent/agent-pool.js +287 -0
- package/dist/agent/agent-pool.js.map +1 -0
- package/dist/agent/followups.d.ts +34 -0
- package/dist/agent/followups.js +52 -0
- package/dist/agent/followups.js.map +1 -0
- package/dist/agent/orchestrator.d.ts +113 -22
- package/dist/agent/orchestrator.js +573 -181
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/entity-types-section.d.ts +36 -0
- package/dist/agent/prompts/entity-types-section.js +90 -0
- package/dist/agent/prompts/entity-types-section.js.map +1 -0
- package/dist/agent/prompts/system.md +148 -69
- package/dist/agent/skill-loader.d.ts +30 -17
- package/dist/agent/skill-loader.js +63 -30
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/skills/entity-schema.md +77 -433
- package/dist/agent/skills/interview/entity-templates.md +193 -0
- package/dist/agent/skills/interview/question-domains.md +391 -0
- package/dist/agent/skills/interview/skill.md +204 -0
- package/dist/agent/skills/schema-rules.md +54 -0
- package/dist/agent/tools/capture-tools.d.ts +31 -0
- package/dist/agent/tools/capture-tools.js +40 -0
- package/dist/agent/tools/capture-tools.js.map +1 -0
- package/dist/agent/tools/folder-tools.d.ts +47 -0
- package/dist/agent/tools/folder-tools.js +249 -0
- package/dist/agent/tools/folder-tools.js.map +1 -0
- package/dist/agent/tools/fs-tools.d.ts +7 -6
- package/dist/agent/tools/fs-tools.js +5 -4
- package/dist/agent/tools/fs-tools.js.map +1 -1
- package/dist/agent/tools/graph-tools.d.ts +21 -58
- package/dist/agent/tools/graph-tools.js +635 -332
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/history-tools.d.ts +95 -0
- package/dist/agent/tools/history-tools.js +461 -0
- package/dist/agent/tools/history-tools.js.map +1 -0
- package/dist/agent/tools/load-skill.d.ts +6 -5
- package/dist/agent/tools/load-skill.js +3 -3
- package/dist/agent/tools/load-skill.js.map +1 -1
- package/dist/agent/tools/ops-tools.d.ts +5 -4
- package/dist/agent/tools/ops-tools.js +130 -236
- package/dist/agent/tools/ops-tools.js.map +1 -1
- package/dist/agent/tools/permission-tools.d.ts +87 -17
- package/dist/agent/tools/permission-tools.js +233 -38
- package/dist/agent/tools/permission-tools.js.map +1 -1
- package/dist/agent/tools/tool-loader.js +5 -4
- package/dist/agent/tools/tool-loader.js.map +1 -1
- package/dist/agent/tools/web-tools.d.ts +18 -0
- package/dist/agent/tools/web-tools.js +283 -0
- package/dist/agent/tools/web-tools.js.map +1 -0
- package/dist/cli/commands/about.d.ts +1 -0
- package/dist/cli/commands/about.js +55 -3
- package/dist/cli/commands/about.js.map +1 -1
- package/dist/cli/commands/admin/audit-workspace.d.ts +23 -0
- package/dist/cli/commands/admin/audit-workspace.js +133 -0
- package/dist/cli/commands/admin/audit-workspace.js.map +1 -0
- package/dist/cli/commands/admin/audit.d.ts +21 -0
- package/dist/cli/commands/admin/audit.js +174 -0
- package/dist/cli/commands/admin/audit.js.map +1 -0
- package/dist/cli/commands/admin/backup.d.ts +54 -0
- package/dist/cli/commands/admin/backup.js +207 -0
- package/dist/cli/commands/admin/backup.js.map +1 -0
- package/dist/cli/commands/admin/folder.d.ts +11 -0
- package/dist/cli/commands/admin/folder.js +186 -0
- package/dist/cli/commands/admin/folder.js.map +1 -0
- package/dist/cli/commands/admin/index.d.ts +16 -0
- package/dist/cli/commands/admin/index.js +46 -0
- package/dist/cli/commands/admin/index.js.map +1 -0
- package/dist/cli/commands/admin/migrate-assets.d.ts +53 -0
- package/dist/cli/commands/admin/migrate-assets.js +184 -0
- package/dist/cli/commands/admin/migrate-assets.js.map +1 -0
- package/dist/cli/commands/admin/migrate.d.ts +56 -0
- package/dist/cli/commands/admin/migrate.js +263 -0
- package/dist/cli/commands/admin/migrate.js.map +1 -0
- package/dist/cli/commands/admin/restore.d.ts +24 -0
- package/dist/cli/commands/admin/restore.js +228 -0
- package/dist/cli/commands/admin/restore.js.map +1 -0
- package/dist/cli/commands/admin/secrets.d.ts +23 -0
- package/dist/cli/commands/admin/secrets.js +256 -0
- package/dist/cli/commands/admin/secrets.js.map +1 -0
- package/dist/cli/commands/admin/settings.d.ts +28 -0
- package/dist/cli/commands/admin/settings.js +284 -0
- package/dist/cli/commands/admin/settings.js.map +1 -0
- package/dist/cli/commands/admin/token.d.ts +42 -0
- package/dist/cli/commands/admin/token.js +126 -0
- package/dist/cli/commands/admin/token.js.map +1 -0
- package/dist/cli/commands/admin/transfer-ownership.d.ts +15 -0
- package/dist/cli/commands/admin/transfer-ownership.js +106 -0
- package/dist/cli/commands/admin/transfer-ownership.js.map +1 -0
- package/dist/cli/commands/admin/user.d.ts +11 -0
- package/dist/cli/commands/admin/user.js +187 -0
- package/dist/cli/commands/admin/user.js.map +1 -0
- package/dist/cli/commands/clone.d.ts +25 -3
- package/dist/cli/commands/clone.js +142 -36
- package/dist/cli/commands/clone.js.map +1 -1
- package/dist/cli/commands/commit.d.ts +1 -1
- package/dist/cli/commands/commit.js +24 -11
- package/dist/cli/commands/commit.js.map +1 -1
- package/dist/cli/commands/config.d.ts +23 -107
- package/dist/cli/commands/config.js +52 -260
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/connector.d.ts +10 -13
- package/dist/cli/commands/connector.js +16 -58
- package/dist/cli/commands/connector.js.map +1 -1
- package/dist/cli/commands/deploy.js +215 -68
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/index.js +2 -2
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.js +10 -30
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/mcp.js +12 -4
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/orphans.js +14 -30
- package/dist/cli/commands/orphans.js.map +1 -1
- package/dist/cli/commands/r2.d.ts +3 -0
- package/dist/cli/commands/r2.js +223 -204
- package/dist/cli/commands/r2.js.map +1 -1
- package/dist/cli/commands/redeploy.js +65 -12
- package/dist/cli/commands/redeploy.js.map +1 -1
- package/dist/cli/commands/reset.d.ts +22 -6
- package/dist/cli/commands/reset.js +142 -63
- package/dist/cli/commands/reset.js.map +1 -1
- package/dist/cli/commands/serve.js +209 -24
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +372 -202
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/crypto-bundle.d.ts +39 -0
- package/dist/cli/crypto-bundle.js +94 -0
- package/dist/cli/crypto-bundle.js.map +1 -0
- package/dist/cli/index.js +24 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/railway-pin.d.ts +68 -0
- package/dist/cli/railway-pin.js +96 -0
- package/dist/cli/railway-pin.js.map +1 -0
- package/dist/cli/railway-provisioning.d.ts +53 -0
- package/dist/cli/railway-provisioning.js +85 -0
- package/dist/cli/railway-provisioning.js.map +1 -0
- package/dist/cli/setup-wizard.d.ts +33 -52
- package/dist/cli/setup-wizard.js +43 -68
- package/dist/cli/setup-wizard.js.map +1 -1
- package/dist/core/accent-palette.d.ts +22 -0
- package/dist/core/accent-palette.js +47 -0
- package/dist/core/accent-palette.js.map +1 -0
- package/dist/core/cell-anchor.d.ts +29 -0
- package/dist/core/cell-anchor.js +53 -0
- package/dist/core/cell-anchor.js.map +1 -0
- package/dist/core/comment-anchor.d.ts +41 -0
- package/dist/core/comment-anchor.js +147 -0
- package/dist/core/comment-anchor.js.map +1 -0
- package/dist/core/commit-messages.d.ts +57 -0
- package/dist/core/commit-messages.js +85 -0
- package/dist/core/commit-messages.js.map +1 -0
- package/dist/core/embeds.d.ts +56 -0
- package/dist/core/embeds.js +103 -0
- package/dist/core/embeds.js.map +1 -0
- package/dist/core/entity-body-templates.d.ts +21 -0
- package/dist/core/entity-body-templates.js +53 -0
- package/dist/core/entity-body-templates.js.map +1 -0
- package/dist/core/entity-types-catalog.d.ts +65 -0
- package/dist/core/entity-types-catalog.js +140 -0
- package/dist/core/entity-types-catalog.js.map +1 -0
- package/dist/core/folder-paths.d.ts +41 -0
- package/dist/core/folder-paths.js +95 -0
- package/dist/core/folder-paths.js.map +1 -0
- package/dist/core/folder-sidecar.d.ts +36 -0
- package/dist/core/folder-sidecar.js +91 -0
- package/dist/core/folder-sidecar.js.map +1 -0
- package/dist/core/graph.d.ts +675 -14
- package/dist/core/graph.js +2118 -314
- package/dist/core/graph.js.map +1 -1
- package/dist/core/history-diff.d.ts +35 -0
- package/dist/core/history-diff.js +114 -0
- package/dist/core/history-diff.js.map +1 -0
- package/dist/core/schema-registry.d.ts +59 -0
- package/dist/core/schema-registry.js +198 -0
- package/dist/core/schema-registry.js.map +1 -1
- package/dist/core/schemas/connector.d.ts +67 -0
- package/dist/core/schemas/connector.js +100 -0
- package/dist/core/schemas/connector.js.map +1 -0
- package/dist/core/schemas/workspace.d.ts +122 -0
- package/dist/core/schemas/workspace.js +211 -0
- package/dist/core/schemas/workspace.js.map +1 -0
- package/dist/core/secrets/SecretStore.d.ts +77 -0
- package/dist/core/secrets/SecretStore.js +13 -0
- package/dist/core/secrets/SecretStore.js.map +1 -0
- package/dist/core/secrets/SettingsResolver.d.ts +54 -0
- package/dist/core/secrets/SettingsResolver.js +80 -0
- package/dist/core/secrets/SettingsResolver.js.map +1 -0
- package/dist/core/secrets/SettingsStore.d.ts +30 -0
- package/dist/core/secrets/SettingsStore.js +9 -0
- package/dist/core/secrets/SettingsStore.js.map +1 -0
- package/dist/core/secrets/SqliteEncryptedStore.d.ts +90 -0
- package/dist/core/secrets/SqliteEncryptedStore.js +598 -0
- package/dist/core/secrets/SqliteEncryptedStore.js.map +1 -0
- package/dist/core/secrets/audit.d.ts +36 -0
- package/dist/core/secrets/audit.js +60 -0
- package/dist/core/secrets/audit.js.map +1 -0
- package/dist/core/secrets/auth-db-migration.d.ts +129 -0
- package/dist/core/secrets/auth-db-migration.js +653 -0
- package/dist/core/secrets/auth-db-migration.js.map +1 -0
- package/dist/core/secrets/bundle.d.ts +141 -0
- package/dist/core/secrets/bundle.js +435 -0
- package/dist/core/secrets/bundle.js.map +1 -0
- package/dist/core/secrets/dual-write.d.ts +81 -0
- package/dist/core/secrets/dual-write.js +247 -0
- package/dist/core/secrets/dual-write.js.map +1 -0
- package/dist/core/secrets/encryption.d.ts +44 -0
- package/dist/core/secrets/encryption.js +97 -0
- package/dist/core/secrets/encryption.js.map +1 -0
- package/dist/core/secrets/index.d.ts +49 -0
- package/dist/core/secrets/index.js +74 -0
- package/dist/core/secrets/index.js.map +1 -0
- package/dist/core/secrets/master-key.d.ts +38 -0
- package/dist/core/secrets/master-key.js +122 -0
- package/dist/core/secrets/master-key.js.map +1 -0
- package/dist/core/secrets/probes/anthropic.d.ts +98 -0
- package/dist/core/secrets/probes/anthropic.js +300 -0
- package/dist/core/secrets/probes/anthropic.js.map +1 -0
- package/dist/core/secrets/probes/brave.d.ts +9 -0
- package/dist/core/secrets/probes/brave.js +15 -0
- package/dist/core/secrets/probes/brave.js.map +1 -0
- package/dist/core/secrets/probes/r2.d.ts +15 -0
- package/dist/core/secrets/probes/r2.js +14 -0
- package/dist/core/secrets/probes/r2.js.map +1 -0
- package/dist/core/secrets/probes/voyage.d.ts +13 -0
- package/dist/core/secrets/probes/voyage.js +52 -0
- package/dist/core/secrets/probes/voyage.js.map +1 -0
- package/dist/core/secrets/r2-structural-migration.d.ts +39 -0
- package/dist/core/secrets/r2-structural-migration.js +109 -0
- package/dist/core/secrets/r2-structural-migration.js.map +1 -0
- package/dist/core/secrets/read-flip.d.ts +59 -0
- package/dist/core/secrets/read-flip.js +87 -0
- package/dist/core/secrets/read-flip.js.map +1 -0
- package/dist/core/secrets/registry.d.ts +188 -0
- package/dist/core/secrets/registry.js +598 -0
- package/dist/core/secrets/registry.js.map +1 -0
- package/dist/core/types.d.ts +77 -455
- package/dist/core/types.js +17 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +75 -7
- package/dist/core/user-config.js +155 -7
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +717 -1791
- package/dist/core/validation.js +357 -228
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +79 -12
- package/dist/core/workspace-manager.js +213 -73
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +19 -5
- package/dist/core/workspace.js +69 -35
- package/dist/core/workspace.js.map +1 -1
- package/dist/mcp/comment-virtual-entity.d.ts +36 -0
- package/dist/mcp/comment-virtual-entity.js +71 -0
- package/dist/mcp/comment-virtual-entity.js.map +1 -0
- package/dist/mcp/connector-manager.d.ts +94 -13
- package/dist/mcp/connector-manager.js +283 -62
- package/dist/mcp/connector-manager.js.map +1 -1
- package/dist/mcp/oauth-provider.d.ts +27 -33
- package/dist/mcp/oauth-provider.js +65 -134
- package/dist/mcp/oauth-provider.js.map +1 -1
- package/dist/mcp/oauth-registry.d.ts +62 -0
- package/dist/mcp/oauth-registry.js +85 -0
- package/dist/mcp/oauth-registry.js.map +1 -0
- package/dist/mcp/server.d.ts +11 -3
- package/dist/mcp/server.js +30 -5
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/state-signer.d.ts +41 -0
- package/dist/mcp/state-signer.js +120 -0
- package/dist/mcp/state-signer.js.map +1 -0
- package/dist/mcp/tools.d.ts +35 -2
- package/dist/mcp/tools.js +1051 -117
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/__tests__/helpers/graph-api.d.ts +18 -0
- package/dist/server/__tests__/helpers/graph-api.js +16 -0
- package/dist/server/__tests__/helpers/graph-api.js.map +1 -0
- package/dist/server/body-write-coordinator.d.ts +151 -0
- package/dist/server/body-write-coordinator.js +161 -0
- package/dist/server/body-write-coordinator.js.map +1 -0
- package/dist/server/cloud-billing-flow.d.ts +32 -0
- package/dist/server/cloud-billing-flow.js +75 -0
- package/dist/server/cloud-billing-flow.js.map +1 -0
- package/dist/server/commit-audit.d.ts +26 -0
- package/dist/server/commit-audit.js +30 -0
- package/dist/server/commit-audit.js.map +1 -0
- package/dist/server/index.d.ts +14 -3
- package/dist/server/index.js +451 -193
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/sanitize.d.ts +46 -0
- package/dist/server/middleware/sanitize.js +171 -0
- package/dist/server/middleware/sanitize.js.map +1 -0
- package/dist/server/routes/asset-api.d.ts +10 -0
- package/dist/server/routes/asset-api.js +294 -0
- package/dist/server/routes/asset-api.js.map +1 -0
- package/dist/server/routes/audit-api.d.ts +24 -0
- package/dist/server/routes/audit-api.js +117 -0
- package/dist/server/routes/audit-api.js.map +1 -0
- package/dist/server/routes/auth-api.d.ts +3 -2
- package/dist/server/routes/auth-api.js +519 -38
- package/dist/server/routes/auth-api.js.map +1 -1
- package/dist/server/routes/capture-api.d.ts +18 -0
- package/dist/server/routes/capture-api.js +257 -0
- package/dist/server/routes/capture-api.js.map +1 -0
- package/dist/server/routes/chat.d.ts +4 -1
- package/dist/server/routes/chat.js +298 -88
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/comments-api.d.ts +15 -0
- package/dist/server/routes/comments-api.js +444 -0
- package/dist/server/routes/comments-api.js.map +1 -0
- package/dist/server/routes/config-api.d.ts +21 -0
- package/dist/server/routes/config-api.js +256 -0
- package/dist/server/routes/config-api.js.map +1 -0
- package/dist/server/routes/connectors-api.d.ts +17 -0
- package/dist/server/routes/connectors-api.js +410 -0
- package/dist/server/routes/connectors-api.js.map +1 -0
- package/dist/server/routes/event-ingest-api.d.ts +15 -0
- package/dist/server/routes/event-ingest-api.js +125 -0
- package/dist/server/routes/event-ingest-api.js.map +1 -0
- package/dist/server/routes/git-http.d.ts +3 -3
- package/dist/server/routes/git-http.js +86 -38
- package/dist/server/routes/git-http.js.map +1 -1
- package/dist/server/routes/graph-api-access.d.ts +35 -0
- package/dist/server/routes/graph-api-access.js +105 -0
- package/dist/server/routes/graph-api-access.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +3 -2
- package/dist/server/routes/graph-api.js +1321 -263
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/health.d.ts +18 -0
- package/dist/server/routes/health.js +74 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/insights-api.d.ts +1 -2
- package/dist/server/routes/insights-api.js +149 -41
- package/dist/server/routes/insights-api.js.map +1 -1
- package/dist/server/routes/mcp.d.ts +7 -3
- package/dist/server/routes/mcp.js +22 -6
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/permissions-api.d.ts +9 -2
- package/dist/server/routes/permissions-api.js +87 -30
- package/dist/server/routes/permissions-api.js.map +1 -1
- package/dist/server/routes/r2-api.d.ts +25 -0
- package/dist/server/routes/r2-api.js +276 -0
- package/dist/server/routes/r2-api.js.map +1 -0
- package/dist/server/routes/secrets-api.d.ts +36 -0
- package/dist/server/routes/secrets-api.js +308 -0
- package/dist/server/routes/secrets-api.js.map +1 -0
- package/dist/server/routes/settings-api.d.ts +29 -0
- package/dist/server/routes/settings-api.js +180 -0
- package/dist/server/routes/settings-api.js.map +1 -0
- package/dist/server/routes/url-api.d.ts +7 -0
- package/dist/server/routes/url-api.js +74 -0
- package/dist/server/routes/url-api.js.map +1 -0
- package/dist/server/routes/views-api.js +81 -7
- package/dist/server/routes/views-api.js.map +1 -1
- package/dist/server/routes/workspace-api.d.ts +2 -1
- package/dist/server/routes/workspace-api.js +124 -35
- package/dist/server/routes/workspace-api.js.map +1 -1
- package/dist/server/routes/ws.d.ts +2 -1
- package/dist/server/routes/ws.js +64 -16
- package/dist/server/routes/ws.js.map +1 -1
- package/dist/server/session-manager.d.ts +48 -5
- package/dist/server/session-manager.js +182 -15
- package/dist/server/session-manager.js.map +1 -1
- package/dist/server/ws-hub.d.ts +138 -14
- package/dist/server/ws-hub.js +0 -0
- package/dist/server/ws-hub.js.map +1 -1
- package/dist/server/yjs-manager.d.ts +285 -7
- package/dist/server/yjs-manager.js +907 -36
- package/dist/server/yjs-manager.js.map +1 -1
- package/dist/server/yjs-persistence.d.ts +165 -0
- package/dist/server/yjs-persistence.js +557 -0
- package/dist/server/yjs-persistence.js.map +1 -0
- package/dist/server/yjs-text-diff.d.ts +32 -0
- package/dist/server/yjs-text-diff.js +61 -0
- package/dist/server/yjs-text-diff.js.map +1 -0
- package/dist/services/access-control.d.ts +73 -0
- package/dist/services/access-control.js +146 -0
- package/dist/services/access-control.js.map +1 -0
- package/dist/services/asset-listing.d.ts +39 -0
- package/dist/services/asset-listing.js +125 -0
- package/dist/services/asset-listing.js.map +1 -0
- package/dist/services/asset-upload-service.d.ts +53 -0
- package/dist/services/asset-upload-service.js +201 -0
- package/dist/services/asset-upload-service.js.map +1 -0
- package/dist/services/assets/asset-index-service.d.ts +82 -0
- package/dist/services/assets/asset-index-service.js +167 -0
- package/dist/services/assets/asset-index-service.js.map +1 -0
- package/dist/services/assets/base.d.ts +44 -0
- package/dist/services/assets/base.js +55 -0
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +69 -1
- package/dist/services/assets/index.js +125 -0
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/assets/local.d.ts +12 -1
- package/dist/services/assets/local.js +100 -1
- package/dist/services/assets/local.js.map +1 -1
- package/dist/services/assets/r2-sync.d.ts +88 -0
- package/dist/services/assets/r2-sync.js +412 -0
- package/dist/services/assets/r2-sync.js.map +1 -0
- package/dist/services/assets/r2.d.ts +34 -1
- package/dist/services/assets/r2.js +93 -1
- package/dist/services/assets/r2.js.map +1 -1
- package/dist/services/auth-service.d.ts +314 -36
- package/dist/services/auth-service.js +1126 -139
- package/dist/services/auth-service.js.map +1 -1
- package/dist/services/bookmark-import-service.d.ts +49 -0
- package/dist/services/bookmark-import-service.js +250 -0
- package/dist/services/bookmark-import-service.js.map +1 -0
- package/dist/services/cloud-inference-billing.d.ts +64 -0
- package/dist/services/cloud-inference-billing.js +313 -0
- package/dist/services/cloud-inference-billing.js.map +1 -0
- package/dist/services/comment-service.d.ts +97 -0
- package/dist/services/comment-service.js +341 -0
- package/dist/services/comment-service.js.map +1 -0
- package/dist/services/csv-service.d.ts +22 -17
- package/dist/services/csv-service.js +55 -92
- package/dist/services/csv-service.js.map +1 -1
- package/dist/services/entity-mutations.d.ts +161 -0
- package/dist/services/entity-mutations.js +296 -0
- package/dist/services/entity-mutations.js.map +1 -0
- package/dist/services/event-processor.d.ts +104 -0
- package/dist/services/event-processor.js +441 -0
- package/dist/services/event-processor.js.map +1 -0
- package/dist/services/folder-creation.d.ts +33 -0
- package/dist/services/folder-creation.js +103 -0
- package/dist/services/folder-creation.js.map +1 -0
- package/dist/services/git.d.ts +54 -0
- package/dist/services/git.js +188 -54
- package/dist/services/git.js.map +1 -1
- package/dist/services/graph-maintenance.d.ts +42 -0
- package/dist/services/graph-maintenance.js +143 -0
- package/dist/services/graph-maintenance.js.map +1 -0
- package/dist/services/import-service.d.ts +45 -2
- package/dist/services/import-service.js +304 -100
- package/dist/services/import-service.js.map +1 -1
- package/dist/services/lint-service.js +9 -16
- package/dist/services/lint-service.js.map +1 -1
- package/dist/services/markdown.d.ts +12 -1
- package/dist/services/markdown.js +71 -6
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +22 -14
- package/dist/services/memory-service.js +53 -35
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/mention-detector.d.ts +23 -0
- package/dist/services/mention-detector.js +47 -0
- package/dist/services/mention-detector.js.map +1 -0
- package/dist/services/notification-broadcast.d.ts +32 -0
- package/dist/services/notification-broadcast.js +38 -0
- package/dist/services/notification-broadcast.js.map +1 -0
- package/dist/services/notification-service.d.ts +41 -0
- package/dist/services/notification-service.js +100 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/personal-folder.d.ts +40 -0
- package/dist/services/personal-folder.js +101 -0
- package/dist/services/personal-folder.js.map +1 -0
- package/dist/services/user-person-bridge.d.ts +118 -0
- package/dist/services/user-person-bridge.js +306 -0
- package/dist/services/user-person-bridge.js.map +1 -0
- package/dist/services/vector-service.d.ts +146 -6
- package/dist/services/vector-service.js +276 -13
- package/dist/services/vector-service.js.map +1 -1
- package/dist/services/workspace-access.d.ts +106 -0
- package/dist/services/workspace-access.js +149 -0
- package/dist/services/workspace-access.js.map +1 -0
- package/dist/utils/git.d.ts +17 -2
- package/dist/utils/git.js +23 -7
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/log.d.ts +42 -0
- package/dist/utils/log.js +137 -0
- package/dist/utils/log.js.map +1 -0
- package/dist/utils/preflight.js +2 -2
- package/dist/utils/preflight.js.map +1 -1
- package/dist/utils/version-checker.d.ts +12 -19
- package/dist/utils/version-checker.js +14 -104
- package/dist/utils/version-checker.js.map +1 -1
- package/dist/web/_app/immutable/assets/0.DOumm94J.css +2 -0
- package/dist/web/_app/immutable/assets/13.DlIf1mKh.css +1 -0
- package/dist/web/_app/immutable/assets/14.7d-Q37wc.css +1 -0
- package/dist/web/_app/immutable/assets/15.CmLrbzZp.css +1 -0
- package/dist/web/_app/immutable/assets/2.BftNiAA4.css +1 -0
- package/dist/web/_app/immutable/assets/3.CV0abekd.css +1 -0
- package/dist/web/_app/immutable/assets/4.BgXzUTTk.css +1 -0
- package/dist/web/_app/immutable/assets/9.gsF-Ne6_.css +1 -0
- package/dist/web/_app/immutable/assets/AgentOverlay.CpvH9rhf.css +1 -0
- package/dist/web/_app/immutable/assets/AssetManagerModal.BKJfPAPk.css +1 -0
- package/dist/web/_app/immutable/assets/CalendarView.bNewSxkH.css +1 -0
- package/dist/web/_app/immutable/assets/ChevronDown.Bz0FjM7b.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMembersPanel.DX1oBeF_.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
- package/dist/web/_app/immutable/assets/FolderPicker.B5KdvRYl.css +1 -0
- package/dist/web/_app/immutable/assets/GalleryView.DgvSjS0I.css +1 -0
- package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
- package/dist/web/_app/immutable/assets/KanbanView.D0QbZFd6.css +1 -0
- package/dist/web/_app/immutable/assets/SettingsDialog.DYWYMFSO.css +1 -0
- package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
- package/dist/web/_app/immutable/assets/StopFilledAlt.CkPrHdPD.css +1 -0
- package/dist/web/_app/immutable/assets/TimelineView.DA-H6dvv.css +1 -0
- package/dist/web/_app/immutable/assets/WorkspaceView.BS1ildu7.css +1 -0
- package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
- package/dist/web/_app/immutable/assets/formatting.vV0ne105.css +1 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.CB9ihrfo.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-mono-latin-500-normal.DSY6xOcd.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CZTNEAuW.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-italic.CsGl1sm0.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.BNK2_mGO.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-italic.DpEwFAQM.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.6ng42L7E.woff2 +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-500-normal.BgVn5rGT.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff +0 -0
- package/dist/web/_app/immutable/assets/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2 +0 -0
- package/dist/web/_app/immutable/assets/inline-list.cqga56xT.css +1 -0
- package/dist/web/_app/immutable/assets/list-columns.BrRrAiZ7.css +1 -0
- package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
- package/dist/web/_app/immutable/assets/sheet.DJPuqnTg.css +1 -0
- package/dist/web/_app/immutable/assets/speech-dictation.C5CYFhS1.css +1 -0
- package/dist/web/_app/immutable/chunks/0edH8sO82.js +1 -0
- package/dist/web/_app/immutable/chunks/0iDDDyaZ.js +1 -0
- package/dist/web/_app/immutable/chunks/7-y0CE1z.js +1 -0
- package/dist/web/_app/immutable/chunks/7Bu427my2.js +184 -0
- package/dist/web/_app/immutable/chunks/B-V5eMSw2.js +1 -0
- package/dist/web/_app/immutable/chunks/B-i9_YVM.js +1 -0
- package/dist/web/_app/immutable/chunks/B15-kvCe.js +1 -0
- package/dist/web/_app/immutable/chunks/B4cFqqUS.js +3 -0
- package/dist/web/_app/immutable/chunks/B6Lt-qaJ.js +1 -0
- package/dist/web/_app/immutable/chunks/B7hznOQp.js +1 -0
- package/dist/web/_app/immutable/chunks/B7tbGyiU2.js +1 -0
- package/dist/web/_app/immutable/chunks/B8-Lm86o2.js +1 -0
- package/dist/web/_app/immutable/chunks/BBxt8lpa.js +1 -0
- package/dist/web/_app/immutable/chunks/BCaRi2AF.js +1 -0
- package/dist/web/_app/immutable/chunks/BJReLGMs.js +1 -0
- package/dist/web/_app/immutable/chunks/BKzV82vD2.js +83 -0
- package/dist/web/_app/immutable/chunks/BLHrJvbG.js +1 -0
- package/dist/web/_app/immutable/chunks/BQULA6er.js +4 -0
- package/dist/web/_app/immutable/chunks/BQW-EDgP2.js +224 -0
- package/dist/web/_app/immutable/chunks/BR6jMpLB.js +1 -0
- package/dist/web/_app/immutable/chunks/BUBMGU8t2.js +2 -0
- package/dist/web/_app/immutable/chunks/BVnuLlVg.js +1 -0
- package/dist/web/_app/immutable/chunks/BYokDzwE.js +1 -0
- package/dist/web/_app/immutable/chunks/B_Avv9jQ2.js +1 -0
- package/dist/web/_app/immutable/chunks/Bbp76jaT2.js +1 -0
- package/dist/web/_app/immutable/chunks/BddNmQ8j.js +1 -0
- package/dist/web/_app/immutable/chunks/BiJjH5mJ.js +2 -0
- package/dist/web/_app/immutable/chunks/BlyFGPFV.js +22 -0
- package/dist/web/_app/immutable/chunks/Bt88HrRx.js +1 -0
- package/dist/web/_app/immutable/chunks/Bu2iU6hh.js +67 -0
- package/dist/web/_app/immutable/chunks/Buih1pxI.js +1 -0
- package/dist/web/_app/immutable/chunks/BwwLJVvR.js +1 -0
- package/dist/web/_app/immutable/chunks/C0RpyyYZ.js +7 -0
- package/dist/web/_app/immutable/chunks/C2l-EXsT2.js +1 -0
- package/dist/web/_app/immutable/chunks/C35TIzaB.js +1 -0
- package/dist/web/_app/immutable/chunks/C3OdK8z_2.js +1 -0
- package/dist/web/_app/immutable/chunks/C6Nx0jpM.js +1 -0
- package/dist/web/_app/immutable/chunks/CA7O0J_u2.js +1 -0
- package/dist/web/_app/immutable/chunks/CAwjrHdk.js +23 -0
- package/dist/web/_app/immutable/chunks/CCLR-AJL2.js +185 -0
- package/dist/web/_app/immutable/chunks/CD0X7XPW.js +6 -0
- package/dist/web/_app/immutable/chunks/CDTjuBSm2.js +1 -0
- package/dist/web/_app/immutable/chunks/CSUrYOis.js +1 -0
- package/dist/web/_app/immutable/chunks/CUPSJObs.js +1 -0
- package/dist/web/_app/immutable/chunks/CUoGvuxK2.js +2 -0
- package/dist/web/_app/immutable/chunks/CWh8aehb.js +1 -0
- package/dist/web/_app/immutable/chunks/CY4XVBP0.js +1 -0
- package/dist/web/_app/immutable/chunks/CYTTTma0.js +3 -0
- package/dist/web/_app/immutable/chunks/CaoriuNq.js +1 -0
- package/dist/web/_app/immutable/chunks/CcsSt9AW2.js +1 -0
- package/dist/web/_app/immutable/chunks/Cd4VfAZC.js +2 -0
- package/dist/web/_app/immutable/chunks/CePZ1985.js +1 -0
- package/dist/web/_app/immutable/chunks/Cei8CKT4.js +1 -0
- package/dist/web/_app/immutable/chunks/CheXrbDk.js +1 -0
- package/dist/web/_app/immutable/chunks/CkLfUXwy.js +1 -0
- package/dist/web/_app/immutable/chunks/Cl-W0JYt.js +2 -0
- package/dist/web/_app/immutable/chunks/Cna7tYp-.js +1 -0
- package/dist/web/_app/immutable/chunks/Czwe4sGU2.js +3 -0
- package/dist/web/_app/immutable/chunks/D41CbXmM.js +1 -0
- package/dist/web/_app/immutable/chunks/D83_Ss42.js +1 -0
- package/dist/web/_app/immutable/chunks/D9NgbGbO2.js +9 -0
- package/dist/web/_app/immutable/chunks/DA-BuZei.js +2 -0
- package/dist/web/_app/immutable/chunks/DAXW5iLp.js +1 -0
- package/dist/web/_app/immutable/chunks/DCNJWlho2.js +1 -0
- package/dist/web/_app/immutable/chunks/DCtgLRl52.js +1 -0
- package/dist/web/_app/immutable/chunks/DH0epITQ2.js +1 -0
- package/dist/web/_app/immutable/chunks/DIb5rAPU2.js +1 -0
- package/dist/web/_app/immutable/chunks/DOmH4G9o2.js +14 -0
- package/dist/web/_app/immutable/chunks/DQMWa2t7.js +1 -0
- package/dist/web/_app/immutable/chunks/DQ_Xokap2.js +1 -0
- package/dist/web/_app/immutable/chunks/DR1K6PIm.js +1 -0
- package/dist/web/_app/immutable/chunks/DTCHhxD5.js +1 -0
- package/dist/web/_app/immutable/chunks/DU7XA-cL2.js +1 -0
- package/dist/web/_app/immutable/chunks/DVcy5Pp82.js +1 -0
- package/dist/web/_app/immutable/chunks/DWygwzcO2.js +1 -0
- package/dist/web/_app/immutable/chunks/DYXDRmoo2.js +1 -0
- package/dist/web/_app/immutable/chunks/DZEmjBTb.js +5 -0
- package/dist/web/_app/immutable/chunks/DaoOQFPb.js +1 -0
- package/dist/web/_app/immutable/chunks/DdfvtDOY.js +1 -0
- package/dist/web/_app/immutable/chunks/DevZTY1l.js +1 -0
- package/dist/web/_app/immutable/chunks/DiMQob8p.js +1 -0
- package/dist/web/_app/immutable/chunks/DiQJ9DLy.js +1 -0
- package/dist/web/_app/immutable/chunks/Dj5oP_ik.js +2 -0
- package/dist/web/_app/immutable/chunks/DjTJ4D_0.js +3 -0
- package/dist/web/_app/immutable/chunks/Dk4TeNwu.js +1 -0
- package/dist/web/_app/immutable/chunks/Dng3OcRd2.js +1 -0
- package/dist/web/_app/immutable/chunks/Do1OCNEG.js +1 -0
- package/dist/web/_app/immutable/chunks/Do6qOOng.js +1 -0
- package/dist/web/_app/immutable/chunks/DoQwt-f9.js +1 -0
- package/dist/web/_app/immutable/chunks/Dqg3k9HI2.js +1 -0
- package/dist/web/_app/immutable/chunks/DsnqOT222.js +1 -0
- package/dist/web/_app/immutable/chunks/DvJSCDuZ2.js +1 -0
- package/dist/web/_app/immutable/chunks/DvPuaTCl.js +5 -0
- package/dist/web/_app/immutable/chunks/DvYQu1SV.js +1 -0
- package/dist/web/_app/immutable/chunks/HdjeJPly2.js +1 -0
- package/dist/web/_app/immutable/chunks/JDw4tOUY.js +1 -0
- package/dist/web/_app/immutable/chunks/KBbDg4lS2.js +1 -0
- package/dist/web/_app/immutable/chunks/KQXQLJf32.js +1 -0
- package/dist/web/_app/immutable/chunks/LGnNalpn2.js +2 -0
- package/dist/web/_app/immutable/chunks/SH5Fg0Xu.js +1 -0
- package/dist/web/_app/immutable/chunks/Shyla9c12.js +2 -0
- package/dist/web/_app/immutable/chunks/VQbAelHN.js +1 -0
- package/dist/web/_app/immutable/chunks/apNT0aug2.js +1 -0
- package/dist/web/_app/immutable/chunks/e0ySQvQ6.js +1 -0
- package/dist/web/_app/immutable/chunks/eNB_sIHC2.js +1 -0
- package/dist/web/_app/immutable/chunks/g09ZrevW2.js +1 -0
- package/dist/web/_app/immutable/chunks/h4WWBpcD2.js +2692 -0
- package/dist/web/_app/immutable/chunks/kLub81jO.js +1 -0
- package/dist/web/_app/immutable/chunks/kW0z_eo62.js +1 -0
- package/dist/web/_app/immutable/chunks/oBQOivfH.js +1 -0
- package/dist/web/_app/immutable/chunks/ss8hcwTT.js +1 -0
- package/dist/web/_app/immutable/chunks/sub7ikQV.js +2 -0
- package/dist/web/_app/immutable/chunks/uuFM-ygL.js +1 -0
- package/dist/web/_app/immutable/chunks/v7me-ydg.js +2 -0
- package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/dist/web/_app/immutable/chunks/yWi6xIp8.js +1 -0
- package/dist/web/_app/immutable/chunks/zl16E4yc2.js +1 -0
- package/dist/web/_app/immutable/entry/app.Bgniax9U.js +2 -0
- package/dist/web/_app/immutable/entry/start.DeD3x0AC.js +1 -0
- package/dist/web/_app/immutable/nodes/0.D7f7eDDY.js +2 -0
- package/dist/web/_app/immutable/nodes/1.nDAGsQWA.js +1 -0
- package/dist/web/_app/immutable/nodes/10.DFbhcPKT.js +1 -0
- package/dist/web/_app/immutable/nodes/11.CDErrkBt.js +1 -0
- package/dist/web/_app/immutable/nodes/12.QmphOXE2.js +1 -0
- package/dist/web/_app/immutable/nodes/13.Bq5rDhPs.js +1 -0
- package/dist/web/_app/immutable/nodes/14.BlcHqgr6.js +1 -0
- package/dist/web/_app/immutable/nodes/15.COK_-D-x.js +1 -0
- package/dist/web/_app/immutable/nodes/2.DOsCYNHa.js +109 -0
- package/dist/web/_app/immutable/nodes/3.BgE1sIyr.js +2 -0
- package/dist/web/_app/immutable/nodes/4.DvgaHeI4.js +11 -0
- package/dist/web/_app/immutable/nodes/5.CrjeBZES.js +1 -0
- package/dist/web/_app/immutable/nodes/6.DoHxsiEE.js +1 -0
- package/dist/web/_app/immutable/nodes/7.04fnxKIo.js +1 -0
- package/dist/web/_app/immutable/nodes/8.D35_cY6C.js +1 -0
- package/dist/web/_app/immutable/nodes/9.BRionwW6.js +1 -0
- package/dist/web/_app/version.json +1 -1
- package/dist/web/favicon-16.png +0 -0
- package/dist/web/favicon-180.png +0 -0
- package/dist/web/favicon-32.png +0 -0
- package/dist/web/favicon-48.png +0 -0
- package/dist/web/favicon-512.png +0 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.svg +8 -0
- package/dist/web/index.html +56 -19
- package/dist/web/studiograph-logomark.svg +29 -0
- package/package.json +34 -14
- package/dist/agent/skills/enrich-entities.md +0 -136
- package/dist/agent/skills/obsidian-source-setup.md +0 -246
- package/dist/agent/skills/skill-loader.d.ts +0 -48
- package/dist/agent/skills/skill-loader.js +0 -166
- package/dist/agent/skills/skill-loader.js.map +0 -1
- package/dist/agent/skills/sync-configuration.md +0 -119
- package/dist/agent/skills/sync-setup.md +0 -82
- package/dist/agent/tools/sync-tools.d.ts +0 -35
- package/dist/agent/tools/sync-tools.js +0 -992
- package/dist/agent/tools/sync-tools.js.map +0 -1
- package/dist/auth/github.d.ts +0 -56
- package/dist/auth/github.js +0 -169
- package/dist/auth/github.js.map +0 -1
- package/dist/cli/commands/access.d.ts +0 -11
- package/dist/cli/commands/access.js +0 -156
- package/dist/cli/commands/access.js.map +0 -1
- package/dist/cli/commands/app.d.ts +0 -7
- package/dist/cli/commands/app.js +0 -268
- package/dist/cli/commands/app.js.map +0 -1
- package/dist/cli/commands/auth.d.ts +0 -10
- package/dist/cli/commands/auth.js +0 -79
- package/dist/cli/commands/auth.js.map +0 -1
- package/dist/cli/commands/clear.d.ts +0 -5
- package/dist/cli/commands/clear.js +0 -36
- package/dist/cli/commands/clear.js.map +0 -1
- package/dist/cli/commands/collection.d.ts +0 -10
- package/dist/cli/commands/collection.js +0 -187
- package/dist/cli/commands/collection.js.map +0 -1
- package/dist/cli/commands/enrich.d.ts +0 -11
- package/dist/cli/commands/enrich.js +0 -135
- package/dist/cli/commands/enrich.js.map +0 -1
- package/dist/cli/commands/graphrag.d.ts +0 -12
- package/dist/cli/commands/graphrag.js +0 -122
- package/dist/cli/commands/graphrag.js.map +0 -1
- package/dist/cli/commands/join.d.ts +0 -9
- package/dist/cli/commands/join.js +0 -255
- package/dist/cli/commands/join.js.map +0 -1
- package/dist/cli/commands/members.d.ts +0 -11
- package/dist/cli/commands/members.js +0 -230
- package/dist/cli/commands/members.js.map +0 -1
- package/dist/cli/commands/org.d.ts +0 -10
- package/dist/cli/commands/org.js +0 -132
- package/dist/cli/commands/org.js.map +0 -1
- package/dist/cli/commands/provision.d.ts +0 -8
- package/dist/cli/commands/provision.js +0 -116
- package/dist/cli/commands/provision.js.map +0 -1
- package/dist/cli/commands/resolve.d.ts +0 -8
- package/dist/cli/commands/resolve.js +0 -85
- package/dist/cli/commands/resolve.js.map +0 -1
- package/dist/cli/commands/review.d.ts +0 -19
- package/dist/cli/commands/review.js +0 -128
- package/dist/cli/commands/review.js.map +0 -1
- package/dist/cli/commands/source.d.ts +0 -16
- package/dist/cli/commands/source.js +0 -159
- package/dist/cli/commands/source.js.map +0 -1
- package/dist/cli/commands/start.d.ts +0 -7
- package/dist/cli/commands/start.js +0 -589
- package/dist/cli/commands/start.js.map +0 -1
- package/dist/cli/commands/sync-collection.d.ts +0 -14
- package/dist/cli/commands/sync-collection.js +0 -355
- package/dist/cli/commands/sync-collection.js.map +0 -1
- package/dist/cli/commands/sync-entities.d.ts +0 -13
- package/dist/cli/commands/sync-entities.js +0 -242
- package/dist/cli/commands/sync-entities.js.map +0 -1
- package/dist/cli/commands/team.d.ts +0 -12
- package/dist/cli/commands/team.js +0 -185
- package/dist/cli/commands/team.js.map +0 -1
- package/dist/cli/commands/update.d.ts +0 -8
- package/dist/cli/commands/update.js +0 -155
- package/dist/cli/commands/update.js.map +0 -1
- package/dist/cli/commands/user.d.ts +0 -7
- package/dist/cli/commands/user.js +0 -153
- package/dist/cli/commands/user.js.map +0 -1
- package/dist/cli/scaffolding.d.ts +0 -12
- package/dist/cli/scaffolding.js +0 -397
- package/dist/cli/scaffolding.js.map +0 -1
- package/dist/cli/sync-review-interactive.d.ts +0 -31
- package/dist/cli/sync-review-interactive.js +0 -393
- package/dist/cli/sync-review-interactive.js.map +0 -1
- package/dist/core/migration-runner.d.ts +0 -42
- package/dist/core/migration-runner.js +0 -232
- package/dist/core/migration-runner.js.map +0 -1
- package/dist/core/migration-types.d.ts +0 -101
- package/dist/core/migration-types.js +0 -21
- package/dist/core/migration-types.js.map +0 -1
- package/dist/core/migrations/20260219-formalize-memory-location.d.ts +0 -2
- package/dist/core/migrations/20260219-formalize-memory-location.js +0 -35
- package/dist/core/migrations/20260219-formalize-memory-location.js.map +0 -1
- package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +0 -12
- package/dist/core/migrations/20260220-add-workspace-metadata.js +0 -65
- package/dist/core/migrations/20260220-add-workspace-metadata.js.map +0 -1
- package/dist/core/migrations/20260220-add-workspace-readme.d.ts +0 -11
- package/dist/core/migrations/20260220-add-workspace-readme.js +0 -82
- package/dist/core/migrations/20260220-add-workspace-readme.js.map +0 -1
- package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +0 -9
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js +0 -64
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +0 -1
- package/dist/core/migrations/index.d.ts +0 -11
- package/dist/core/migrations/index.js +0 -23
- package/dist/core/migrations/index.js.map +0 -1
- package/dist/integrations/asana.d.ts +0 -26
- package/dist/integrations/asana.js +0 -78
- package/dist/integrations/asana.js.map +0 -1
- package/dist/integrations/figma-local.d.ts +0 -16
- package/dist/integrations/figma-local.js +0 -10
- package/dist/integrations/figma-local.js.map +0 -1
- package/dist/integrations/figma.d.ts +0 -17
- package/dist/integrations/figma.js +0 -17
- package/dist/integrations/figma.js.map +0 -1
- package/dist/integrations/granola.d.ts +0 -24
- package/dist/integrations/granola.js +0 -60
- package/dist/integrations/granola.js.map +0 -1
- package/dist/integrations/linear.d.ts +0 -14
- package/dist/integrations/linear.js +0 -80
- package/dist/integrations/linear.js.map +0 -1
- package/dist/integrations/paper-local.d.ts +0 -14
- package/dist/integrations/paper-local.js +0 -10
- package/dist/integrations/paper-local.js.map +0 -1
- package/dist/integrations/paper.d.ts +0 -2
- package/dist/integrations/paper.js +0 -10
- package/dist/integrations/paper.js.map +0 -1
- package/dist/integrations/pipedrive.d.ts +0 -26
- package/dist/integrations/pipedrive.js +0 -97
- package/dist/integrations/pipedrive.js.map +0 -1
- package/dist/integrations/registry.d.ts +0 -15
- package/dist/integrations/registry.js +0 -27
- package/dist/integrations/registry.js.map +0 -1
- package/dist/integrations/types.d.ts +0 -38
- package/dist/integrations/types.js +0 -9
- package/dist/integrations/types.js.map +0 -1
- package/dist/lib/lib/utils.d.ts +0 -2
- package/dist/lib/lib/utils.js +0 -6
- package/dist/lib/lib/utils.js.map +0 -1
- package/dist/mcp/connectors/asana.d.ts +0 -2
- package/dist/mcp/connectors/asana.js +0 -20
- package/dist/mcp/connectors/asana.js.map +0 -1
- package/dist/mcp/connectors/definitions.d.ts +0 -45
- package/dist/mcp/connectors/definitions.js +0 -32
- package/dist/mcp/connectors/definitions.js.map +0 -1
- package/dist/mcp/connectors/figma.d.ts +0 -5
- package/dist/mcp/connectors/figma.js +0 -21
- package/dist/mcp/connectors/figma.js.map +0 -1
- package/dist/mcp/connectors/gdrive.d.ts +0 -2
- package/dist/mcp/connectors/gdrive.js +0 -20
- package/dist/mcp/connectors/gdrive.js.map +0 -1
- package/dist/mcp/connectors/granola.d.ts +0 -2
- package/dist/mcp/connectors/granola.js +0 -12
- package/dist/mcp/connectors/granola.js.map +0 -1
- package/dist/mcp/connectors/linear.d.ts +0 -2
- package/dist/mcp/connectors/linear.js +0 -19
- package/dist/mcp/connectors/linear.js.map +0 -1
- package/dist/mcp/connectors/obsidian.d.ts +0 -2
- package/dist/mcp/connectors/obsidian.js +0 -19
- package/dist/mcp/connectors/obsidian.js.map +0 -1
- package/dist/mcp/connectors/pipedrive.d.ts +0 -2
- package/dist/mcp/connectors/pipedrive.js +0 -20
- package/dist/mcp/connectors/pipedrive.js.map +0 -1
- package/dist/mcp/connectors/slack.d.ts +0 -2
- package/dist/mcp/connectors/slack.js +0 -21
- package/dist/mcp/connectors/slack.js.map +0 -1
- package/dist/mcp/server-oauth-provider.d.ts +0 -56
- package/dist/mcp/server-oauth-provider.js +0 -142
- package/dist/mcp/server-oauth-provider.js.map +0 -1
- package/dist/server/chrome/chrome.css +0 -691
- package/dist/server/chrome/chrome.js +0 -374
- package/dist/server/collab-authority.d.ts +0 -70
- package/dist/server/collab-authority.js +0 -218
- package/dist/server/collab-authority.js.map +0 -1
- package/dist/server/collab.d.ts +0 -29
- package/dist/server/collab.js +0 -195
- package/dist/server/collab.js.map +0 -1
- package/dist/server/commit-scheduler.d.ts +0 -39
- package/dist/server/commit-scheduler.js +0 -113
- package/dist/server/commit-scheduler.js.map +0 -1
- package/dist/server/plugin-loader.d.ts +0 -53
- package/dist/server/plugin-loader.js +0 -155
- package/dist/server/plugin-loader.js.map +0 -1
- package/dist/server/routes/collab.d.ts +0 -6
- package/dist/server/routes/collab.js +0 -10
- package/dist/server/routes/collab.js.map +0 -1
- package/dist/server/routes/git-api.d.ts +0 -9
- package/dist/server/routes/git-api.js +0 -82
- package/dist/server/routes/git-api.js.map +0 -1
- package/dist/server/routes/meeting-ingest-api.d.ts +0 -15
- package/dist/server/routes/meeting-ingest-api.js +0 -323
- package/dist/server/routes/meeting-ingest-api.js.map +0 -1
- package/dist/server/routes/sync-api.d.ts +0 -26
- package/dist/server/routes/sync-api.js +0 -814
- package/dist/server/routes/sync-api.js.map +0 -1
- package/dist/server/routes/webhook.d.ts +0 -14
- package/dist/server/routes/webhook.js +0 -102
- package/dist/server/routes/webhook.js.map +0 -1
- package/dist/services/github-provisioner.d.ts +0 -36
- package/dist/services/github-provisioner.js +0 -126
- package/dist/services/github-provisioner.js.map +0 -1
- package/dist/services/github-service.d.ts +0 -99
- package/dist/services/github-service.js +0 -310
- package/dist/services/github-service.js.map +0 -1
- package/dist/services/insights.d.ts +0 -38
- package/dist/services/insights.js +0 -246
- package/dist/services/insights.js.map +0 -1
- package/dist/services/sync/collection-sync.d.ts +0 -60
- package/dist/services/sync/collection-sync.js +0 -509
- package/dist/services/sync/collection-sync.js.map +0 -1
- package/dist/services/sync/commit.d.ts +0 -60
- package/dist/services/sync/commit.js +0 -354
- package/dist/services/sync/commit.js.map +0 -1
- package/dist/services/sync/context-index.d.ts +0 -69
- package/dist/services/sync/context-index.js +0 -280
- package/dist/services/sync/context-index.js.map +0 -1
- package/dist/services/sync/data-fetcher.d.ts +0 -31
- package/dist/services/sync/data-fetcher.js +0 -12
- package/dist/services/sync/data-fetcher.js.map +0 -1
- package/dist/services/sync/derive.d.ts +0 -34
- package/dist/services/sync/derive.js +0 -164
- package/dist/services/sync/derive.js.map +0 -1
- package/dist/services/sync/enrichment-state.d.ts +0 -31
- package/dist/services/sync/enrichment-state.js +0 -63
- package/dist/services/sync/enrichment-state.js.map +0 -1
- package/dist/services/sync/enrichment.d.ts +0 -25
- package/dist/services/sync/enrichment.js +0 -121
- package/dist/services/sync/enrichment.js.map +0 -1
- package/dist/services/sync/entity-refresh.d.ts +0 -30
- package/dist/services/sync/entity-refresh.js +0 -275
- package/dist/services/sync/entity-refresh.js.map +0 -1
- package/dist/services/sync/frontmatter-extractor.d.ts +0 -40
- package/dist/services/sync/frontmatter-extractor.js +0 -279
- package/dist/services/sync/frontmatter-extractor.js.map +0 -1
- package/dist/services/sync/graph-match-state.d.ts +0 -33
- package/dist/services/sync/graph-match-state.js +0 -61
- package/dist/services/sync/graph-match-state.js.map +0 -1
- package/dist/services/sync/graph-match.d.ts +0 -53
- package/dist/services/sync/graph-match.js +0 -316
- package/dist/services/sync/graph-match.js.map +0 -1
- package/dist/services/sync/graphrag-client.d.ts +0 -43
- package/dist/services/sync/graphrag-client.js +0 -94
- package/dist/services/sync/graphrag-client.js.map +0 -1
- package/dist/services/sync/graphrag-config.d.ts +0 -16
- package/dist/services/sync/graphrag-config.js +0 -39
- package/dist/services/sync/graphrag-config.js.map +0 -1
- package/dist/services/sync/graphrag-context.d.ts +0 -14
- package/dist/services/sync/graphrag-context.js +0 -109
- package/dist/services/sync/graphrag-context.js.map +0 -1
- package/dist/services/sync/graphrag-indexer.d.ts +0 -30
- package/dist/services/sync/graphrag-indexer.js +0 -358
- package/dist/services/sync/graphrag-indexer.js.map +0 -1
- package/dist/services/sync/llm.d.ts +0 -32
- package/dist/services/sync/llm.js +0 -115
- package/dist/services/sync/llm.js.map +0 -1
- package/dist/services/sync/mcp-client.d.ts +0 -71
- package/dist/services/sync/mcp-client.js +0 -299
- package/dist/services/sync/mcp-client.js.map +0 -1
- package/dist/services/sync/model-factory.d.ts +0 -13
- package/dist/services/sync/model-factory.js +0 -38
- package/dist/services/sync/model-factory.js.map +0 -1
- package/dist/services/sync/name-quality.d.ts +0 -31
- package/dist/services/sync/name-quality.js +0 -60
- package/dist/services/sync/name-quality.js.map +0 -1
- package/dist/services/sync/output-schemas.d.ts +0 -92
- package/dist/services/sync/output-schemas.js +0 -43
- package/dist/services/sync/output-schemas.js.map +0 -1
- package/dist/services/sync/prompts.d.ts +0 -19
- package/dist/services/sync/prompts.js +0 -128
- package/dist/services/sync/prompts.js.map +0 -1
- package/dist/services/sync/reconciler.d.ts +0 -48
- package/dist/services/sync/reconciler.js +0 -294
- package/dist/services/sync/reconciler.js.map +0 -1
- package/dist/services/sync/rest-client.d.ts +0 -40
- package/dist/services/sync/rest-client.js +0 -100
- package/dist/services/sync/rest-client.js.map +0 -1
- package/dist/services/sync/source-config.d.ts +0 -67
- package/dist/services/sync/source-config.js +0 -304
- package/dist/services/sync/source-config.js.map +0 -1
- package/dist/services/sync/source-definitions/asana.d.ts +0 -14
- package/dist/services/sync/source-definitions/asana.js +0 -42
- package/dist/services/sync/source-definitions/asana.js.map +0 -1
- package/dist/services/sync/source-definitions/definitions.d.ts +0 -8
- package/dist/services/sync/source-definitions/definitions.js +0 -8
- package/dist/services/sync/source-definitions/definitions.js.map +0 -1
- package/dist/services/sync/source-definitions/gdrive.d.ts +0 -16
- package/dist/services/sync/source-definitions/gdrive.js +0 -68
- package/dist/services/sync/source-definitions/gdrive.js.map +0 -1
- package/dist/services/sync/source-definitions/granola.d.ts +0 -2
- package/dist/services/sync/source-definitions/granola.js +0 -21
- package/dist/services/sync/source-definitions/granola.js.map +0 -1
- package/dist/services/sync/source-definitions/linear.d.ts +0 -2
- package/dist/services/sync/source-definitions/linear.js +0 -62
- package/dist/services/sync/source-definitions/linear.js.map +0 -1
- package/dist/services/sync/source-definitions/obsidian.d.ts +0 -2
- package/dist/services/sync/source-definitions/obsidian.js +0 -55
- package/dist/services/sync/source-definitions/obsidian.js.map +0 -1
- package/dist/services/sync/source-definitions/pipedrive.d.ts +0 -2
- package/dist/services/sync/source-definitions/pipedrive.js +0 -43
- package/dist/services/sync/source-definitions/pipedrive.js.map +0 -1
- package/dist/services/sync/staging.d.ts +0 -53
- package/dist/services/sync/staging.js +0 -130
- package/dist/services/sync/staging.js.map +0 -1
- package/dist/services/sync/structured-extractor.d.ts +0 -57
- package/dist/services/sync/structured-extractor.js +0 -584
- package/dist/services/sync/structured-extractor.js.map +0 -1
- package/dist/services/sync/sync-runner.d.ts +0 -32
- package/dist/services/sync/sync-runner.js +0 -195
- package/dist/services/sync/sync-runner.js.map +0 -1
- package/dist/services/sync/sync-state.d.ts +0 -43
- package/dist/services/sync/sync-state.js +0 -154
- package/dist/services/sync/sync-state.js.map +0 -1
- package/dist/services/sync/types.d.ts +0 -381
- package/dist/services/sync/types.js +0 -8
- package/dist/services/sync/types.js.map +0 -1
- package/dist/services/sync/unstructured-extractor.d.ts +0 -27
- package/dist/services/sync/unstructured-extractor.js +0 -185
- package/dist/services/sync/unstructured-extractor.js.map +0 -1
- package/dist/utils/merge-resolver.d.ts +0 -59
- package/dist/utils/merge-resolver.js +0 -303
- package/dist/utils/merge-resolver.js.map +0 -1
- package/dist/utils/workspace-config.d.ts +0 -8
- package/dist/utils/workspace-config.js +0 -22
- package/dist/utils/workspace-config.js.map +0 -1
- package/dist/web/_app/immutable/assets/0.DdizXOKi.css +0 -1
- package/dist/web/_app/immutable/assets/10.BUrHkYry.css +0 -1
- package/dist/web/_app/immutable/assets/2.n7-yW_Fs.css +0 -1
- package/dist/web/_app/immutable/assets/3.BtaZagnv.css +0 -1
- package/dist/web/_app/immutable/assets/4.DT7X0x5S.css +0 -1
- package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
- package/dist/web/_app/immutable/assets/6.CquhUpOu.css +0 -1
- package/dist/web/_app/immutable/assets/7.CjbDRbuG.css +0 -1
- package/dist/web/_app/immutable/assets/8.S1QdUGNM.css +0 -1
- package/dist/web/_app/immutable/assets/9.CT4xL4K3.css +0 -1
- package/dist/web/_app/immutable/assets/Copy.FS8bdfxr.css +0 -1
- package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
- package/dist/web/_app/immutable/assets/ViewToolbar.D-QW2oKe.css +0 -1
- package/dist/web/_app/immutable/assets/index.D6tMDJWk.css +0 -1
- package/dist/web/_app/immutable/chunks/37NdyH6G.js +0 -32
- package/dist/web/_app/immutable/chunks/4Hhzb6pv.js +0 -1
- package/dist/web/_app/immutable/chunks/72bZS3G9.js +0 -1
- package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
- package/dist/web/_app/immutable/chunks/B-7hHz7B.js +0 -1
- package/dist/web/_app/immutable/chunks/B340SUKR.js +0 -1
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
- package/dist/web/_app/immutable/chunks/BDoWDZaG.js +0 -1
- package/dist/web/_app/immutable/chunks/BFyl1ZHO.js +0 -1
- package/dist/web/_app/immutable/chunks/BS2rFAVq.js +0 -1
- package/dist/web/_app/immutable/chunks/BSsDC_p4.js +0 -1
- package/dist/web/_app/immutable/chunks/BTX2Jr8_.js +0 -1
- package/dist/web/_app/immutable/chunks/BWNY8zw6.js +0 -2
- package/dist/web/_app/immutable/chunks/BdPUVvAi.js +0 -1
- package/dist/web/_app/immutable/chunks/BmsJVLyy.js +0 -1
- package/dist/web/_app/immutable/chunks/BoAosqzE.js +0 -1
- package/dist/web/_app/immutable/chunks/Bs-tL5OR.js +0 -1
- package/dist/web/_app/immutable/chunks/Bsacq2UX.js +0 -1
- package/dist/web/_app/immutable/chunks/BuewkNdS.js +0 -4
- package/dist/web/_app/immutable/chunks/ByunV8un.js +0 -1
- package/dist/web/_app/immutable/chunks/C7VoTosa.js +0 -2
- package/dist/web/_app/immutable/chunks/CDV5Q7RN.js +0 -1
- package/dist/web/_app/immutable/chunks/CJ8__CWt.js +0 -1
- package/dist/web/_app/immutable/chunks/CJUKmosC.js +0 -5
- package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
- package/dist/web/_app/immutable/chunks/CT6oIU-C.js +0 -1
- package/dist/web/_app/immutable/chunks/CTRxNfZk.js +0 -1
- package/dist/web/_app/immutable/chunks/CWQRQXxy.js +0 -1
- package/dist/web/_app/immutable/chunks/CXH6iFbA.js +0 -1
- package/dist/web/_app/immutable/chunks/CX_61fY8.js +0 -5
- package/dist/web/_app/immutable/chunks/CYrVHOHA.js +0 -1
- package/dist/web/_app/immutable/chunks/CdeYcEuU.js +0 -1
- package/dist/web/_app/immutable/chunks/CmCtpZ1Y.js +0 -1
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
- package/dist/web/_app/immutable/chunks/CrdV0ttd.js +0 -1
- package/dist/web/_app/immutable/chunks/CscoF-YL.js +0 -18
- package/dist/web/_app/immutable/chunks/Cx4YdFMk.js +0 -1
- package/dist/web/_app/immutable/chunks/D7ZqAKi9.js +0 -3
- package/dist/web/_app/immutable/chunks/DGbA7IXh.js +0 -2
- package/dist/web/_app/immutable/chunks/DbbB6Up5.js +0 -1
- package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
- package/dist/web/_app/immutable/chunks/DtM5cEDu.js +0 -1
- package/dist/web/_app/immutable/chunks/Eqahi7_S.js +0 -2
- package/dist/web/_app/immutable/chunks/FFlLQIiS.js +0 -1
- package/dist/web/_app/immutable/chunks/O9Eb9k00.js +0 -1
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
- package/dist/web/_app/immutable/chunks/QF8MAmnc.js +0 -1
- package/dist/web/_app/immutable/chunks/UjzxCpxn.js +0 -1
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
- package/dist/web/_app/immutable/chunks/Y90OgS-9.js +0 -1
- package/dist/web/_app/immutable/chunks/cLyZlkXv.js +0 -1
- package/dist/web/_app/immutable/chunks/iDtAARVW.js +0 -2
- package/dist/web/_app/immutable/chunks/oC_W7W7p.js +0 -1
- package/dist/web/_app/immutable/chunks/rJdWIgh-.js +0 -1
- package/dist/web/_app/immutable/chunks/tvOsokaa.js +0 -1
- package/dist/web/_app/immutable/chunks/uLEXaPwE.js +0 -1
- package/dist/web/_app/immutable/chunks/vSaooFHB.js +0 -1
- package/dist/web/_app/immutable/entry/app.DAR-mtfg.js +0 -2
- package/dist/web/_app/immutable/entry/start.xDnyRaR1.js +0 -1
- package/dist/web/_app/immutable/nodes/0.D0aV-Zro.js +0 -2
- package/dist/web/_app/immutable/nodes/1.C7QoM8qD.js +0 -1
- package/dist/web/_app/immutable/nodes/10.DrDOAjOD.js +0 -1
- package/dist/web/_app/immutable/nodes/2.B0OgNuKW.js +0 -168
- package/dist/web/_app/immutable/nodes/3.BZ4qHGZi.js +0 -1
- package/dist/web/_app/immutable/nodes/4.hm-mxuuj.js +0 -12
- package/dist/web/_app/immutable/nodes/5.Bdbt4fjx.js +0 -4
- package/dist/web/_app/immutable/nodes/6.BXrCI40c.js +0 -2
- package/dist/web/_app/immutable/nodes/7.Chd4i9bm.js +0 -2
- package/dist/web/_app/immutable/nodes/8.B8SF-aNs.js +0 -1
- package/dist/web/_app/immutable/nodes/9.YDeu-RnO.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -4,75 +4,180 @@
|
|
|
4
4
|
* Hosts:
|
|
5
5
|
* - Graph API (read-only REST over WorkspaceManager)
|
|
6
6
|
* - Agent chat via POST /api/chat and SSE GET /api/chat/stream
|
|
7
|
-
* -
|
|
7
|
+
* - Static web UI (SvelteKit build) with SPA fallback
|
|
8
8
|
*/
|
|
9
9
|
import Fastify from 'fastify';
|
|
10
10
|
import cookie from '@fastify/cookie';
|
|
11
11
|
import cors from '@fastify/cors';
|
|
12
|
+
import rateLimit from '@fastify/rate-limit';
|
|
12
13
|
import websocket from '@fastify/websocket';
|
|
14
|
+
import { sanitize } from './middleware/sanitize.js';
|
|
13
15
|
import { existsSync, readFileSync, createReadStream, statSync } from 'fs';
|
|
14
|
-
import { join, extname } from 'path';
|
|
16
|
+
import { join, extname, resolve, sep } from 'path';
|
|
15
17
|
import { Workspace } from '../core/workspace.js';
|
|
16
18
|
import { AgentOrchestrator } from '../agent/orchestrator.js';
|
|
17
|
-
import { PluginLoader, MIME_TYPES } from './plugin-loader.js';
|
|
18
19
|
import { registerGraphApiRoutes } from './routes/graph-api.js';
|
|
19
20
|
import { registerChatRoutes } from './routes/chat.js';
|
|
20
21
|
import { registerWorkspaceApiRoutes } from './routes/workspace-api.js';
|
|
22
|
+
import { registerHealthApiRoutes } from './routes/health.js';
|
|
21
23
|
import { registerPermissionsApiRoutes } from './routes/permissions-api.js';
|
|
22
24
|
import { registerAuthApiRoutes } from './routes/auth-api.js';
|
|
23
25
|
import { registerGitHttpRoutes } from './routes/git-http.js';
|
|
24
|
-
import { registerSyncApiRoutes } from './routes/sync-api.js';
|
|
25
26
|
import { registerViewsApiRoutes } from './routes/views-api.js';
|
|
26
27
|
import { registerInsightsApiRoutes } from './routes/insights-api.js';
|
|
27
28
|
import { registerMcpRoutes } from './routes/mcp.js';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
29
|
+
import { registerConnectorsApiRoutes } from './routes/connectors-api.js';
|
|
30
|
+
import { registerAssetApiRoutes } from './routes/asset-api.js';
|
|
31
|
+
import { registerR2ApiRoutes } from './routes/r2-api.js';
|
|
32
|
+
import multipart from '@fastify/multipart';
|
|
33
|
+
import { registerEventIngestRoutes } from './routes/event-ingest-api.js';
|
|
34
|
+
import { registerCaptureRoutes } from './routes/capture-api.js';
|
|
35
|
+
import { registerUrlRoutes } from './routes/url-api.js';
|
|
36
|
+
import { registerConfigApiRoutes } from './routes/config-api.js';
|
|
37
|
+
import { registerSettingsApiRoutes } from './routes/settings-api.js';
|
|
38
|
+
import { registerSecretsApiRoutes } from './routes/secrets-api.js';
|
|
39
|
+
import { registerAuditApiRoutes } from './routes/audit-api.js';
|
|
40
|
+
import { registerCommentsApiRoutes } from './routes/comments-api.js';
|
|
41
|
+
import { AuthService, isWorkspaceOwner } from '../services/auth-service.js';
|
|
30
42
|
import { MemoryService } from '../services/memory-service.js';
|
|
43
|
+
import { CommentService } from '../services/comment-service.js';
|
|
44
|
+
import { NotificationService } from '../services/notification-service.js';
|
|
31
45
|
import { WsHub } from './ws-hub.js';
|
|
32
46
|
import { registerWsRoute } from './routes/ws.js';
|
|
33
47
|
import { SessionManager } from './session-manager.js';
|
|
34
48
|
import { YjsManager } from './yjs-manager.js';
|
|
49
|
+
import { YjsPersistence, acquireYjsStateLock } from './yjs-persistence.js';
|
|
50
|
+
import { BodyWriteCoordinator } from './body-write-coordinator.js';
|
|
51
|
+
import { ensurePersonalFolder } from '../services/personal-folder.js';
|
|
52
|
+
/** Ensure every user has a personal "My Folder" folder + admin access on it (idempotent). */
|
|
53
|
+
async function ensureAllPersonalFolders(authService, workspacePath, workspaceManager) {
|
|
54
|
+
const users = authService.listUsers();
|
|
55
|
+
const workspace = new Workspace(workspacePath);
|
|
56
|
+
for (const user of users) {
|
|
57
|
+
try {
|
|
58
|
+
await ensurePersonalFolder(workspace, authService, user);
|
|
59
|
+
}
|
|
60
|
+
catch { /* non-fatal — skip and let the user re-authenticate */ }
|
|
61
|
+
}
|
|
62
|
+
workspaceManager.reloadConfig();
|
|
63
|
+
}
|
|
64
|
+
/** MIME types for static file serving (web UI assets). */
|
|
65
|
+
const MIME_TYPES = {
|
|
66
|
+
'.html': 'text/html',
|
|
67
|
+
'.css': 'text/css',
|
|
68
|
+
'.js': 'application/javascript',
|
|
69
|
+
'.mjs': 'application/javascript',
|
|
70
|
+
'.json': 'application/json',
|
|
71
|
+
'.png': 'image/png',
|
|
72
|
+
'.jpg': 'image/jpeg',
|
|
73
|
+
'.jpeg': 'image/jpeg',
|
|
74
|
+
'.gif': 'image/gif',
|
|
75
|
+
'.svg': 'image/svg+xml',
|
|
76
|
+
'.ico': 'image/x-icon',
|
|
77
|
+
'.woff': 'font/woff',
|
|
78
|
+
'.woff2': 'font/woff2',
|
|
79
|
+
'.ttf': 'font/ttf',
|
|
80
|
+
'.otf': 'font/otf',
|
|
81
|
+
'.webp': 'image/webp',
|
|
82
|
+
'.avif': 'image/avif',
|
|
83
|
+
'.mp4': 'video/mp4',
|
|
84
|
+
'.webm': 'video/webm',
|
|
85
|
+
};
|
|
86
|
+
export function resolveStaticFilePath(webDir, urlPath) {
|
|
87
|
+
let decodedPath;
|
|
88
|
+
try {
|
|
89
|
+
decodedPath = decodeURIComponent(urlPath);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const filePath = decodedPath === '/' ? '/index.html' : decodedPath;
|
|
95
|
+
const webRoot = resolve(webDir);
|
|
96
|
+
const fullPath = resolve(webRoot, `.${filePath}`);
|
|
97
|
+
if (fullPath !== webRoot && !fullPath.startsWith(webRoot + sep)) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return fullPath;
|
|
101
|
+
}
|
|
102
|
+
function normalizeOrigin(value) {
|
|
103
|
+
if (!value)
|
|
104
|
+
return null;
|
|
105
|
+
try {
|
|
106
|
+
return new URL(value).origin;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function buildAllowedCorsOrigins(workspaceConfig, port) {
|
|
113
|
+
const rawOrigins = [];
|
|
114
|
+
const envOrigins = process.env.STUDIOGRAPH_CORS_ORIGINS;
|
|
115
|
+
if (envOrigins)
|
|
116
|
+
rawOrigins.push(...envOrigins.split(',').map(o => o.trim()).filter(Boolean));
|
|
117
|
+
const configured = workspaceConfig.cors_origins;
|
|
118
|
+
if (Array.isArray(configured)) {
|
|
119
|
+
rawOrigins.push(...configured.filter((o) => typeof o === 'string'));
|
|
120
|
+
}
|
|
121
|
+
else if (typeof configured === 'string') {
|
|
122
|
+
rawOrigins.push(...configured.split(',').map(o => o.trim()).filter(Boolean));
|
|
123
|
+
}
|
|
124
|
+
const serverUrl = workspaceConfig.server_url;
|
|
125
|
+
if (typeof serverUrl === 'string')
|
|
126
|
+
rawOrigins.push(serverUrl);
|
|
127
|
+
rawOrigins.push(`http://localhost:${port}`, `http://127.0.0.1:${port}`, `http://[::1]:${port}`);
|
|
128
|
+
return new Set(rawOrigins.map(normalizeOrigin).filter((o) => Boolean(o)));
|
|
129
|
+
}
|
|
130
|
+
export function isCorsOriginAllowed(origin, allowedOrigins) {
|
|
131
|
+
if (!origin)
|
|
132
|
+
return true;
|
|
133
|
+
const normalized = normalizeOrigin(origin);
|
|
134
|
+
return Boolean(normalized && allowedOrigins.has(normalized));
|
|
135
|
+
}
|
|
136
|
+
function isTruthyEnv(value) {
|
|
137
|
+
return Boolean(value && ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase()));
|
|
138
|
+
}
|
|
35
139
|
/**
|
|
36
140
|
* Auth middleware — validates JWT cookie or Authorization: Bearer <key> header.
|
|
37
141
|
* When users exist in the auth database, all routes require authentication
|
|
38
142
|
* (except auth endpoints and static assets). When no users exist, everything
|
|
39
143
|
* is open (backward compatible).
|
|
40
144
|
*/
|
|
41
|
-
function createAuthHook(
|
|
145
|
+
function createAuthHook(authService) {
|
|
42
146
|
return async (req, reply) => {
|
|
43
147
|
// Always allow auth endpoints
|
|
44
148
|
if (req.url.startsWith('/api/auth/'))
|
|
45
149
|
return;
|
|
46
|
-
//
|
|
150
|
+
// Managed Cloud login handoff verifies its own short-lived token.
|
|
151
|
+
if (req.url.startsWith('/api/cloud/auth/'))
|
|
152
|
+
return;
|
|
153
|
+
// OAuth callbacks and claims identify the user via state/claim code, not cookies
|
|
47
154
|
if (req.url.startsWith('/api/oauth/callback/'))
|
|
48
155
|
return;
|
|
156
|
+
if (req.url.startsWith('/api/oauth/claim/'))
|
|
157
|
+
return;
|
|
49
158
|
// Git HTTP routes have their own Basic Auth
|
|
50
159
|
if (req.url.startsWith('/git/'))
|
|
51
160
|
return;
|
|
52
161
|
// WebSocket route handles its own auth
|
|
53
162
|
if (req.url.startsWith('/ws'))
|
|
54
163
|
return;
|
|
55
|
-
// Allow static assets (JS, CSS, fonts, images) — needed for login page
|
|
56
|
-
|
|
164
|
+
// Allow static assets (JS, CSS, fonts, images) — needed for login page.
|
|
165
|
+
// Covers SvelteKit-bundled output under /_app/ and root-level public
|
|
166
|
+
// files (favicon.ico, studiograph-logomark.svg, …) identified by a file
|
|
167
|
+
// extension on a non-API GET.
|
|
168
|
+
if (req.url.startsWith('/_app/'))
|
|
169
|
+
return;
|
|
170
|
+
if (req.method === 'GET' &&
|
|
171
|
+
!req.url.startsWith('/api/') &&
|
|
172
|
+
extname(req.url.split('?')[0]).length > 1)
|
|
57
173
|
return;
|
|
58
174
|
// Allow HTML page requests (SPA routing) — the app handles auth client-side
|
|
59
175
|
if (req.method === 'GET' && req.headers.accept?.includes('text/html'))
|
|
60
176
|
return;
|
|
61
|
-
// If no users configured, allow everything
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (apiKeys.length > 0) {
|
|
65
|
-
const authHeader = req.headers['authorization'];
|
|
66
|
-
const bearer = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : undefined;
|
|
67
|
-
if (bearer && apiKeys.includes(bearer))
|
|
68
|
-
return;
|
|
69
|
-
// For non-API routes (i.e. browser requests), allow without auth
|
|
70
|
-
if (!req.url.startsWith('/api/') || req.url.startsWith('/api/auth/'))
|
|
71
|
-
return;
|
|
72
|
-
// For API routes without a bearer token, allow if no users exist
|
|
73
|
-
}
|
|
177
|
+
// If no users configured, allow everything in local open mode. Managed
|
|
178
|
+
// Cloud workspaces still require auth before the first user handoff lands.
|
|
179
|
+
if (!authService.hasUsers() && !isTruthyEnv(process.env.STUDIOGRAPH_MANAGED_AUTH))
|
|
74
180
|
return;
|
|
75
|
-
}
|
|
76
181
|
// Check JWT cookie (web UI sessions)
|
|
77
182
|
const jwtToken = req.cookies?.['__sg_token'];
|
|
78
183
|
if (jwtToken) {
|
|
@@ -82,11 +187,26 @@ function createAuthHook(apiKeys, authService) {
|
|
|
82
187
|
return;
|
|
83
188
|
}
|
|
84
189
|
}
|
|
85
|
-
// Check Bearer token (API clients, MCP)
|
|
190
|
+
// Check Bearer token (API clients, MCP, CLI): JWT → per-user API token.
|
|
191
|
+
// Both yield a user identity. There is no shared workspace key — every
|
|
192
|
+
// caller must be identifiable so access control can enforce per-folder rules.
|
|
86
193
|
const authHeader = req.headers['authorization'];
|
|
87
194
|
const bearer = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : undefined;
|
|
88
|
-
if (bearer
|
|
89
|
-
|
|
195
|
+
if (bearer) {
|
|
196
|
+
const jwtUser = authService.verifyToken(bearer);
|
|
197
|
+
if (jwtUser) {
|
|
198
|
+
req.user = jwtUser;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const tokenMeta = authService.verifyApiTokenWithMeta(bearer);
|
|
202
|
+
if (tokenMeta) {
|
|
203
|
+
req.user = tokenMeta.user;
|
|
204
|
+
// Stash the token's user-set name so downstream surfaces (MCP, agent
|
|
205
|
+
// activity) can label the integration. Absent for cookie/JWT auth.
|
|
206
|
+
req.apiTokenName = tokenMeta.tokenName;
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
90
210
|
// Check Basic Auth (CLI join command)
|
|
91
211
|
if (authHeader?.startsWith('Basic ')) {
|
|
92
212
|
try {
|
|
@@ -105,22 +225,143 @@ function createAuthHook(apiKeys, authService) {
|
|
|
105
225
|
return reply.status(401).send({ error: 'Unauthorized' });
|
|
106
226
|
};
|
|
107
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Phase 11 — preSerialization payload sanitizer.
|
|
230
|
+
*
|
|
231
|
+
* The API has many routes that respond with `{ error: err.message }` from a
|
|
232
|
+
* catch block. Those messages can carry upstream provider errors, git
|
|
233
|
+
* stderr (with embedded credentials), or other free-form text that we
|
|
234
|
+
* don't want surfacing in HTTP responses. Walk the response payload,
|
|
235
|
+
* sanitize any string value at a "message" / "error" / "detail" key,
|
|
236
|
+
* and leave structured fields (status codes, IDs, classification flags)
|
|
237
|
+
* alone.
|
|
238
|
+
*
|
|
239
|
+
* Conservatively, we ONLY redact at keys that conventionally carry
|
|
240
|
+
* free-form text. Arbitrary string fields (entity names, IDs, etc.) are
|
|
241
|
+
* left untouched so we don't garble legitimate content. The Fastify
|
|
242
|
+
* logger sanitization (above) handles log-line redaction independently;
|
|
243
|
+
* this hook focuses on the wire response.
|
|
244
|
+
*/
|
|
245
|
+
const FREEFORM_ERROR_KEYS = new Set(['error', 'message', 'detail', 'stack', 'description', 'error_description']);
|
|
246
|
+
function sanitizeResponsePayload(value) {
|
|
247
|
+
if (typeof value === 'string')
|
|
248
|
+
return sanitize(value);
|
|
249
|
+
if (Array.isArray(value))
|
|
250
|
+
return value.map(sanitizeResponsePayload);
|
|
251
|
+
if (value && typeof value === 'object') {
|
|
252
|
+
const out = {};
|
|
253
|
+
for (const [k, v] of Object.entries(value)) {
|
|
254
|
+
if (FREEFORM_ERROR_KEYS.has(k) && typeof v === 'string') {
|
|
255
|
+
out[k] = sanitize(v);
|
|
256
|
+
}
|
|
257
|
+
else if (v && typeof v === 'object') {
|
|
258
|
+
out[k] = sanitizeResponsePayload(v);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
out[k] = v;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return out;
|
|
265
|
+
}
|
|
266
|
+
return value;
|
|
267
|
+
}
|
|
108
268
|
export async function createServer(config) {
|
|
269
|
+
// Phase 11: every Fastify log line flows through sanitize() before
|
|
270
|
+
// reaching stdout. A thin Writable wrapper passes each chunk through
|
|
271
|
+
// the redactor; pino accepts any `stream` with a `write()` method.
|
|
272
|
+
// STUDIOGRAPH_LOG_RAW=1 disables redaction for local debugging.
|
|
273
|
+
const shouldRedactFastifyLogs = process.env.STUDIOGRAPH_LOG_RAW !== '1' &&
|
|
274
|
+
(process.env.NODE_ENV === 'production' || !!process.env.RAILWAY_ENVIRONMENT);
|
|
275
|
+
const redactingStream = {
|
|
276
|
+
write(chunk) {
|
|
277
|
+
const out = shouldRedactFastifyLogs ? sanitize(chunk) : chunk;
|
|
278
|
+
process.stdout.write(out);
|
|
279
|
+
},
|
|
280
|
+
};
|
|
109
281
|
const fastify = Fastify({
|
|
110
282
|
logger: process.env.STUDIOGRAPH_LOG === '1'
|
|
111
|
-
?
|
|
112
|
-
: { level: 'warn' },
|
|
283
|
+
? { stream: redactingStream }
|
|
284
|
+
: { level: 'warn', stream: redactingStream },
|
|
113
285
|
bodyLimit: 10 * 1024 * 1024, // 10 MB — entities can be large (e.g. meeting transcripts)
|
|
114
286
|
});
|
|
287
|
+
// Phase 11: sanitize uncaught errors before serialization so neither
|
|
288
|
+
// err.message nor err.stack echoes upstream secrets. Stable error
|
|
289
|
+
// codes (err.code) pass through; we only redact freeform text.
|
|
290
|
+
fastify.setErrorHandler((error, _req, reply) => {
|
|
291
|
+
const sanitizedMsg = shouldRedactFastifyLogs ? sanitize(error.message) : error.message;
|
|
292
|
+
const status = error.statusCode ?? 500;
|
|
293
|
+
fastify.log.error({
|
|
294
|
+
err: { message: sanitizedMsg, code: error.code },
|
|
295
|
+
});
|
|
296
|
+
reply.status(status).send({
|
|
297
|
+
statusCode: status,
|
|
298
|
+
code: error.code,
|
|
299
|
+
error: status >= 500 ? 'Internal Server Error' : (error.name || 'Error'),
|
|
300
|
+
message: status >= 500 ? 'An internal error occurred.' : sanitizedMsg,
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
// Phase 11: pre-serialization hook scans every response body for
|
|
304
|
+
// freeform error/message strings and runs them through sanitize().
|
|
305
|
+
// This catches the many `reply.status(4xx).send({ error: err.message })`
|
|
306
|
+
// call sites scattered across the API routes — without this, an
|
|
307
|
+
// upstream provider error or git remote error would echo through to
|
|
308
|
+
// the API consumer with embedded credentials. Stable error codes pass
|
|
309
|
+
// through unchanged. Only kicks in when redaction is enabled.
|
|
310
|
+
if (shouldRedactFastifyLogs) {
|
|
311
|
+
fastify.addHook('preSerialization', async (_req, _reply, payload) => {
|
|
312
|
+
if (!payload || typeof payload !== 'object')
|
|
313
|
+
return payload;
|
|
314
|
+
return sanitizeResponsePayload(payload);
|
|
315
|
+
});
|
|
316
|
+
}
|
|
115
317
|
// CORS
|
|
318
|
+
const allowedCorsOrigins = buildAllowedCorsOrigins(config.workspaceConfig, config.port);
|
|
116
319
|
await fastify.register(cors, {
|
|
117
|
-
origin:
|
|
320
|
+
origin: (origin, cb) => {
|
|
321
|
+
cb(null, isCorsOriginAllowed(origin, allowedCorsOrigins));
|
|
322
|
+
},
|
|
118
323
|
credentials: true,
|
|
119
324
|
});
|
|
120
325
|
// Cookie support for web UI session auth
|
|
121
326
|
await fastify.register(cookie);
|
|
122
|
-
// WebSocket support for real-time notifications
|
|
123
|
-
|
|
327
|
+
// WebSocket support for real-time notifications.
|
|
328
|
+
//
|
|
329
|
+
// perMessageDeflate is enabled here on purpose. Our origin would otherwise
|
|
330
|
+
// leave compression off (ws lib default), but Railway's edge proxy
|
|
331
|
+
// negotiates `permessage-deflate` with the browser anyway and does its own
|
|
332
|
+
// inflate/deflate layer in the middle — which Safari/WebKit mis-decodes,
|
|
333
|
+
// producing truncated buffers and `RangeError: Length out of range of buffer`
|
|
334
|
+
// inside Yjs's varint reader, followed by WS disconnect loops.
|
|
335
|
+
//
|
|
336
|
+
// Negotiating compression at the origin forces end-to-end deflate (Node's
|
|
337
|
+
// zlib ↔ browser) and prevents the proxy from inserting its own layer.
|
|
338
|
+
// `noContextTakeover` on both sides keeps each frame independently
|
|
339
|
+
// decompressible, which avoids cross-frame state bugs that have historically
|
|
340
|
+
// hit Safari.
|
|
341
|
+
await fastify.register(websocket, {
|
|
342
|
+
options: {
|
|
343
|
+
perMessageDeflate: {
|
|
344
|
+
threshold: 1024,
|
|
345
|
+
serverNoContextTakeover: true,
|
|
346
|
+
clientNoContextTakeover: true,
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
// Multipart support for file uploads (images, assets)
|
|
351
|
+
await fastify.register(multipart, { limits: { fileSize: 10 * 1024 * 1024 } });
|
|
352
|
+
// Global rate-limit registration with a permissive default; individual
|
|
353
|
+
// routes opt into tighter limits via `config: { rateLimit: ... }`. Today
|
|
354
|
+
// only comment mutations apply tight limits — keeps the runtime in
|
|
355
|
+
// place without changing the rest of the API's request-rate behaviour.
|
|
356
|
+
await fastify.register(rateLimit, {
|
|
357
|
+
global: false,
|
|
358
|
+
max: 1000,
|
|
359
|
+
timeWindow: '1 minute',
|
|
360
|
+
keyGenerator: (req) => {
|
|
361
|
+
const u = req.user;
|
|
362
|
+
return u?.id ? `u:${u.id}` : (req.ip ?? 'unknown');
|
|
363
|
+
},
|
|
364
|
+
});
|
|
124
365
|
fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, (req, body, done) => {
|
|
125
366
|
try {
|
|
126
367
|
req.rawBody = body;
|
|
@@ -139,104 +380,135 @@ export async function createServer(config) {
|
|
|
139
380
|
done(null); // Don't consume the body — the route handler pipes req.raw directly
|
|
140
381
|
});
|
|
141
382
|
}
|
|
142
|
-
// Initialize auth service, WebSocket hub, session manager, and collab server
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
authService.
|
|
146
|
-
|
|
383
|
+
// Initialize auth service, WebSocket hub, session manager, and collab server.
|
|
384
|
+
// Phase 8: when the boot path provided master-key options, hand them through
|
|
385
|
+
// so OAuth tokens + per-user secret prefs use the encrypted column path.
|
|
386
|
+
const authService = new AuthService(config.workspacePath, config.authCryptoOptions);
|
|
387
|
+
// Ensure all users have their personal "My Folder" folder
|
|
388
|
+
await ensureAllPersonalFolders(authService, config.workspacePath, config.workspaceManager);
|
|
389
|
+
const { getCurrentVersion } = await import('../utils/version-checker.js');
|
|
390
|
+
const wsHub = new WsHub(getCurrentVersion());
|
|
391
|
+
const commentService = new CommentService(config.workspacePath);
|
|
392
|
+
const notificationService = new NotificationService(config.workspacePath);
|
|
147
393
|
const sessionManager = new SessionManager(config.workspaceManager, wsHub);
|
|
148
|
-
|
|
394
|
+
// Recover any dirty repos before accepting requests. Replays persisted
|
|
395
|
+
// pending commits from a previous process AND sweeps every working tree
|
|
396
|
+
// for uncommitted state. Catches anything dropped by a crash, OOM, or
|
|
397
|
+
// hard restart. Logs and continues on failure — recovery is best-effort
|
|
398
|
+
// and must never block server startup.
|
|
399
|
+
try {
|
|
400
|
+
await sessionManager.recoverOnBoot();
|
|
401
|
+
}
|
|
402
|
+
catch (err) {
|
|
403
|
+
console.warn('[server] sessionManager.recoverOnBoot failed:', err.message);
|
|
404
|
+
}
|
|
405
|
+
// Persistence layer: durable Y.Doc snapshot store across server restarts.
|
|
406
|
+
// Lives at `<workspace>/.studiograph/yjs-state/` — gitignored binary state
|
|
407
|
+
// separate from the .md files (which remain canonical for git, MCP, agents).
|
|
408
|
+
// See yjs-persistence.ts for the file format and concurrency model.
|
|
409
|
+
const yjsStateDir = join(config.workspacePath, '.studiograph', 'yjs-state');
|
|
410
|
+
// Single-instance lock. Throws if another studiograph server is already
|
|
411
|
+
// running against this workspace. We don't support horizontal scaling today
|
|
412
|
+
// (no shared Yjs pubsub), so the safe default is to fail fast on misuse
|
|
413
|
+
// rather than silently corrupt snapshots via concurrent writers.
|
|
414
|
+
const releaseYjsLock = acquireYjsStateLock(yjsStateDir);
|
|
415
|
+
const yjsPersistence = new YjsPersistence(yjsStateDir);
|
|
416
|
+
const yjsManager = new YjsManager(config.workspaceManager, yjsPersistence);
|
|
417
|
+
// Yjs configuration startup log. Surfacing the flags at boot lets operators
|
|
418
|
+
// verify the configuration without reading source. The fail-closed guards
|
|
419
|
+
// (`assertWritable`, 412 convergence gate) prevent silent data corruption
|
|
420
|
+
// regardless of how the flags are set, but `broadcast=off` while clients
|
|
421
|
+
// are connected degrades UX, so we warn explicitly.
|
|
422
|
+
const broadcastEnabled = process.env.STUDIOGRAPH_YJS_BROADCAST !== '0';
|
|
423
|
+
const allowDegradedWrites = process.env.STUDIOGRAPH_ALLOW_DEGRADED_WRITES === '1';
|
|
424
|
+
console.log(`[yjs] config: broadcast=${broadcastEnabled ? 'on' : 'OFF'} ` +
|
|
425
|
+
`allow-degraded-writes=${allowDegradedWrites ? 'on' : 'off'}`);
|
|
426
|
+
if (!broadcastEnabled && !allowDegradedWrites) {
|
|
427
|
+
console.warn('[yjs] STUDIOGRAPH_YJS_BROADCAST=0 without STUDIOGRAPH_ALLOW_DEGRADED_WRITES=1: ' +
|
|
428
|
+
'server-side body writes will REFUSE while clients are connected. ' +
|
|
429
|
+
'This is the fail-closed kill-switch path — intentional during incident response, ' +
|
|
430
|
+
'misconfiguration otherwise.');
|
|
431
|
+
}
|
|
432
|
+
// Wire the Yjs persistence layer to follow structural .md mutations.
|
|
433
|
+
// delete / rename / changeType all change a doc's identity (path on disk
|
|
434
|
+
// and its docName), so the snapshot file has to move with it. Without
|
|
435
|
+
// these hooks, snapshots leak (orphaned files for deleted entities) or
|
|
436
|
+
// serve stale state at the new identity (ghost content after a rename).
|
|
437
|
+
config.workspaceManager.setPersistenceCallbacks({
|
|
438
|
+
onDelete: (repo, entityType, entityId) => yjsPersistence.delete(`${repo}/${entityType}/${entityId}`),
|
|
439
|
+
onRename: (repo, entityType, oldId, newId) => yjsPersistence.rename(`${repo}/${entityType}/${oldId}`, `${repo}/${entityType}/${newId}`),
|
|
440
|
+
onChangeType: (repo, entityId, fromType, toType) => yjsPersistence.rename(`${repo}/${fromType}/${entityId}`, `${repo}/${toType}/${entityId}`),
|
|
441
|
+
});
|
|
442
|
+
// Body-write coordinator owns the single critical section for every body
|
|
443
|
+
// write (autosave PUT + MCP / agent / event-processor server-writes). Holds
|
|
444
|
+
// the per-doc lock, base-hash precondition, atomic disk write, commit +
|
|
445
|
+
// dirty recovery, post-commit applyAgentContent broadcast, and
|
|
446
|
+
// mdRevisionHash bookkeeping. Replaces the previous nine-callback shape on
|
|
447
|
+
// graph.update.
|
|
448
|
+
const bodyWriteCoordinator = new BodyWriteCoordinator({
|
|
449
|
+
// Narrow commit hook — keeps the coordinator from reaching back
|
|
450
|
+
// through WorkspaceManager. No-op when the repo has no GitService.
|
|
451
|
+
commit: async (coords, actor, message) => {
|
|
452
|
+
const gitService = config.workspaceManager.getGraph(coords.repo).getGitService();
|
|
453
|
+
if (!gitService)
|
|
454
|
+
return;
|
|
455
|
+
const tx = gitService.createTransaction();
|
|
456
|
+
tx.add({
|
|
457
|
+
operation: 'update',
|
|
458
|
+
entityType: coords.entityType,
|
|
459
|
+
entityId: coords.entityId,
|
|
460
|
+
filePath: coords.entityPath,
|
|
461
|
+
});
|
|
462
|
+
await tx.commit(actor, message);
|
|
463
|
+
},
|
|
464
|
+
}, yjsManager, sessionManager);
|
|
465
|
+
config.workspaceManager.setBodyWriteCoordinator(bodyWriteCoordinator);
|
|
149
466
|
// Register auth API routes (before the auth hook so they are always accessible)
|
|
150
|
-
await registerAuthApiRoutes(fastify, authService, config.workspaceConfig.team_name);
|
|
467
|
+
await registerAuthApiRoutes(fastify, authService, config.workspacePath, config.workspaceManager, config.workspaceConfig.team_name);
|
|
151
468
|
// Auth hook — applied to all routes
|
|
152
|
-
const authHook = createAuthHook(
|
|
469
|
+
const authHook = createAuthHook(authService);
|
|
153
470
|
fastify.addHook('preHandler', authHook);
|
|
154
471
|
// Register WebSocket route (real-time change notifications + cursor broadcasting)
|
|
155
|
-
await registerWsRoute(fastify, wsHub, authService, yjsManager);
|
|
156
|
-
// Register graph API routes (with per-
|
|
157
|
-
await registerGraphApiRoutes(fastify, config.workspaceManager, authService, wsHub, sessionManager);
|
|
472
|
+
await registerWsRoute(fastify, wsHub, authService, config.workspaceManager, yjsManager);
|
|
473
|
+
// Register graph API routes (with per-folder access filtering)
|
|
474
|
+
await registerGraphApiRoutes(fastify, config.workspaceManager, authService, wsHub, sessionManager, yjsManager);
|
|
158
475
|
// Register workspace API routes (git operations)
|
|
159
|
-
await registerWorkspaceApiRoutes(fastify, config.workspaceManager, config.gitUser);
|
|
160
|
-
// Register
|
|
476
|
+
await registerWorkspaceApiRoutes(fastify, config.workspaceManager, config.gitUser, authService);
|
|
477
|
+
// Register health endpoints (per-repo dirty status)
|
|
478
|
+
await registerHealthApiRoutes(fastify, config.workspaceManager, sessionManager);
|
|
479
|
+
// Register config + workspace data API routes (for `studiograph push/pull --remote`)
|
|
480
|
+
await registerConfigApiRoutes(fastify, config.workspaceManager, config.workspacePath, authService);
|
|
481
|
+
// Register Phase 7 settings/secrets/audit API routes. Owner-only via
|
|
482
|
+
// isWorkspaceOwner() inside each handler.
|
|
483
|
+
await registerSettingsApiRoutes(fastify, authService);
|
|
484
|
+
await registerSecretsApiRoutes(fastify, authService);
|
|
485
|
+
await registerAuditApiRoutes(fastify, authService);
|
|
486
|
+
// Register comments API + notifications feed (Comments-First Phase 1).
|
|
487
|
+
// The getAgent closure resolves the orchestrator lazily — it's
|
|
488
|
+
// initialised below at line ~613, AFTER routes register, so route
|
|
489
|
+
// handlers can't capture it eagerly. The closure binding to the outer
|
|
490
|
+
// `agent` variable picks up the value once the orchestrator is alive.
|
|
491
|
+
await registerCommentsApiRoutes(fastify, commentService, notificationService, authService, wsHub, config.workspaceManager, () => agent);
|
|
492
|
+
// Register permissions API routes (self-hosted folder access)
|
|
161
493
|
await registerPermissionsApiRoutes(fastify, authService, config.workspaceManager, wsHub);
|
|
494
|
+
// Messages API routes registered after agent init (below) so @agent invocation works
|
|
495
|
+
// Register connectors API routes (MCP connector management + OAuth)
|
|
496
|
+
await registerConnectorsApiRoutes(fastify, authService, config.workspacePath);
|
|
497
|
+
// Register asset upload routes (image upload to R2/local)
|
|
498
|
+
await registerAssetApiRoutes(fastify, config.workspaceManager, authService);
|
|
499
|
+
// Register R2 management routes (bucket creation, local-asset sync, status)
|
|
500
|
+
await registerR2ApiRoutes(fastify, config.workspaceManager, authService, config.gitUser);
|
|
162
501
|
// Register git Smart HTTP routes (clone/fetch/push with Basic Auth)
|
|
163
502
|
await registerGitHttpRoutes(fastify, config.workspaceManager, authService, config.workspacePath, wsHub);
|
|
164
|
-
// Register sync API routes (collection-scoped sync)
|
|
165
|
-
await registerSyncApiRoutes(fastify, config.workspaceManager, authService, config.workspacePath, wsHub);
|
|
166
503
|
// Register views API routes (per-user saved views)
|
|
167
504
|
await registerViewsApiRoutes(fastify, authService, config.workspaceManager);
|
|
168
505
|
// Register insights + preferences API routes
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const { createGraphTools } = await import('../agent/tools/graph-tools.js');
|
|
173
|
-
const { createSyncTools } = await import('../agent/tools/sync-tools.js');
|
|
174
|
-
const { createOpsTools } = await import('../agent/tools/ops-tools.js');
|
|
175
|
-
const dummyUser = { id: '0', name: 'system', email: 'system' };
|
|
176
|
-
const allTools = [
|
|
177
|
-
...createGraphTools(config.workspaceManager, dummyUser, config.workspacePath, undefined, undefined, () => null, authService),
|
|
178
|
-
...createSyncTools(config.workspacePath, config.workspaceConfig),
|
|
179
|
-
...createOpsTools(config.workspacePath, config.workspaceConfig),
|
|
180
|
-
];
|
|
181
|
-
for (const t of allTools) {
|
|
182
|
-
if (t.name && t.description) {
|
|
183
|
-
coreToolMeta.push({ name: t.name, description: t.description });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
console.warn('[insights] Failed to build tool metadata:', err);
|
|
189
|
-
}
|
|
190
|
-
const getToolsForUser = (userId) => {
|
|
191
|
-
const tools = [...coreToolMeta];
|
|
192
|
-
// Add connector tools based on user's actually connected services
|
|
193
|
-
try {
|
|
194
|
-
const connectedConnectors = authService.getUserConnectedConnectors(userId);
|
|
195
|
-
for (const c of connectedConnectors) {
|
|
196
|
-
tools.push({ name: `${c.connector_name}_connector`, description: `Connected ${c.connector_name} integration — can sync and access ${c.connector_name} data` });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
catch { /* no connector tools */ }
|
|
200
|
-
return tools;
|
|
201
|
-
};
|
|
202
|
-
await registerInsightsApiRoutes(fastify, config.workspaceManager, authService, config.workspacePath, wsHub, getToolsForUser);
|
|
203
|
-
// Register meeting ingest API (Chrome extension + other capture tools)
|
|
204
|
-
await registerMeetingIngestRoutes(fastify, config.workspaceManager, authService, wsHub);
|
|
506
|
+
await registerInsightsApiRoutes(fastify, config.workspaceManager, authService, config.workspacePath, wsHub);
|
|
507
|
+
// Register event ingest API (meeting capture from desktop and external sources)
|
|
508
|
+
await registerEventIngestRoutes(fastify, config.workspaceManager, authService, wsHub, yjsManager);
|
|
205
509
|
// Register MCP Streamable HTTP endpoint
|
|
206
|
-
await registerMcpRoutes(fastify, config.workspaceManager, authService);
|
|
207
|
-
//
|
|
208
|
-
const chromeDir = join(import.meta.dirname, 'chrome');
|
|
209
|
-
if (existsSync(chromeDir)) {
|
|
210
|
-
const CHROME_MIME = { '.js': 'application/javascript', '.css': 'text/css' };
|
|
211
|
-
fastify.get('/api/chrome/:file', async (req, reply) => {
|
|
212
|
-
const file = req.params.file;
|
|
213
|
-
if (file.includes('..') || file.includes('/')) {
|
|
214
|
-
return reply.status(400).send({ error: 'Invalid path' });
|
|
215
|
-
}
|
|
216
|
-
const filePath = join(chromeDir, file);
|
|
217
|
-
if (!existsSync(filePath) || !statSync(filePath).isFile()) {
|
|
218
|
-
return reply.status(404).send({ error: 'Not found' });
|
|
219
|
-
}
|
|
220
|
-
const ext = extname(filePath).toLowerCase();
|
|
221
|
-
reply.type(CHROME_MIME[ext] || 'application/octet-stream');
|
|
222
|
-
reply.header('Cache-Control', 'public, max-age=300');
|
|
223
|
-
return reply.send(createReadStream(filePath));
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
// Discover installed apps and collect their skill/tool dirs
|
|
227
|
-
const loader = new PluginLoader();
|
|
228
|
-
const manifests = loader.loadApps(config.appsDir);
|
|
229
|
-
const appSkillsDirs = [];
|
|
230
|
-
const appToolsDirs = [];
|
|
231
|
-
for (const manifest of manifests) {
|
|
232
|
-
const skillsDir = loader.getSkillsDir(config.appsDir, manifest);
|
|
233
|
-
if (skillsDir)
|
|
234
|
-
appSkillsDirs.push(skillsDir);
|
|
235
|
-
const toolsDir = loader.getToolsDir(config.appsDir, manifest);
|
|
236
|
-
if (toolsDir)
|
|
237
|
-
appToolsDirs.push(toolsDir);
|
|
238
|
-
}
|
|
239
|
-
// Initialize memory service and agent — non-fatal so the server can still serve graph API and apps
|
|
510
|
+
await registerMcpRoutes(fastify, config.workspaceManager, authService, wsHub, commentService);
|
|
511
|
+
// Initialize memory service and agent — non-fatal so the server can still serve graph API
|
|
240
512
|
const memoryService = new MemoryService();
|
|
241
513
|
let agent = null;
|
|
242
514
|
try {
|
|
@@ -245,12 +517,18 @@ export async function createServer(config) {
|
|
|
245
517
|
workspacePath: config.workspacePath,
|
|
246
518
|
workspaceConfig: config.workspaceConfig,
|
|
247
519
|
gitUser: config.gitUser,
|
|
248
|
-
skillsDirs: appSkillsDirs,
|
|
249
|
-
toolsDirs: appToolsDirs,
|
|
250
520
|
recentMemory,
|
|
251
521
|
workspaceManager: config.workspaceManager,
|
|
522
|
+
// Share the route-level AuthService. Without this the orchestrator
|
|
523
|
+
// constructs its own crypto-less copy and (a) errors when reading
|
|
524
|
+
// encrypted oauth_tokens rows, (b) subscribes to a different
|
|
525
|
+
// pubsub than the one the OAuth callback fires on — so per-user
|
|
526
|
+
// OAuth state changes never invalidate the agent pool.
|
|
527
|
+
authService,
|
|
252
528
|
});
|
|
253
|
-
await registerChatRoutes(fastify, agent, memoryService);
|
|
529
|
+
await registerChatRoutes(fastify, agent, wsHub, authService, memoryService);
|
|
530
|
+
await registerCaptureRoutes(fastify, agent);
|
|
531
|
+
await registerUrlRoutes(fastify);
|
|
254
532
|
}
|
|
255
533
|
catch (err) {
|
|
256
534
|
fastify.log.warn(`Agent not available: ${err.message ?? err} — chat routes will return setup message`);
|
|
@@ -268,55 +546,22 @@ export async function createServer(config) {
|
|
|
268
546
|
return reply.status(503).send({ error: 'The AI agent is not configured yet. Please set the API key for your model provider in the server environment variables and restart.' });
|
|
269
547
|
});
|
|
270
548
|
}
|
|
271
|
-
// GET /api/apps — list installed app manifests with resolved entity type names
|
|
272
|
-
const resolvedApps = manifests.map(m => {
|
|
273
|
-
let entityTypes = [];
|
|
274
|
-
try {
|
|
275
|
-
const etPath = join(config.appsDir, m.name, m.entityTypes);
|
|
276
|
-
if (existsSync(etPath)) {
|
|
277
|
-
const raw = JSON.parse(readFileSync(etPath, 'utf-8'));
|
|
278
|
-
if (Array.isArray(raw)) {
|
|
279
|
-
entityTypes = raw.map((item) => item.name).filter(Boolean);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
catch {
|
|
284
|
-
// gracefully degrade — return empty array
|
|
285
|
-
}
|
|
286
|
-
return { name: m.name, version: m.version, description: m.description, mountPath: m.mountPath, entityTypes };
|
|
287
|
-
});
|
|
288
|
-
fastify.get('/api/apps', async (_req, reply) => {
|
|
289
|
-
return reply.send(resolvedApps);
|
|
290
|
-
});
|
|
291
549
|
// GET /api/workspace — workspace metadata
|
|
292
550
|
fastify.get('/api/workspace', async (_req, reply) => {
|
|
293
551
|
const workspace = new Workspace(config.workspacePath);
|
|
294
552
|
const about = workspace.loadAbout();
|
|
295
|
-
return reply.send({ name: config.workspaceConfig.team_name, about
|
|
553
|
+
return reply.send({ name: config.workspaceConfig.team_name, about });
|
|
296
554
|
});
|
|
297
|
-
// PUT /api/workspace — update workspace identity (
|
|
555
|
+
// PUT /api/workspace — update workspace identity (owner only)
|
|
298
556
|
fastify.put('/api/workspace', async (req, reply) => {
|
|
299
557
|
const user = req.user;
|
|
300
|
-
if (user && user.role
|
|
301
|
-
return reply.status(403).send({ error: '
|
|
558
|
+
if (user && !isWorkspaceOwner(user.role)) {
|
|
559
|
+
return reply.status(403).send({ error: 'Workspace owner access required' });
|
|
302
560
|
}
|
|
303
|
-
const { name, about
|
|
561
|
+
const { name, about } = req.body ?? {};
|
|
304
562
|
const workspace = new Workspace(config.workspacePath);
|
|
305
|
-
let configChanged = false;
|
|
306
563
|
if (typeof name === 'string' && name.trim()) {
|
|
307
564
|
config.workspaceConfig.team_name = name.trim();
|
|
308
|
-
configChanged = true;
|
|
309
|
-
}
|
|
310
|
-
if (accent_color !== undefined) {
|
|
311
|
-
if (accent_color === null) {
|
|
312
|
-
delete config.workspaceConfig.accent_color;
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
config.workspaceConfig.accent_color = accent_color;
|
|
316
|
-
}
|
|
317
|
-
configChanged = true;
|
|
318
|
-
}
|
|
319
|
-
if (configChanged) {
|
|
320
565
|
workspace.writeConfig(config.workspaceConfig);
|
|
321
566
|
}
|
|
322
567
|
if (typeof about === 'string') {
|
|
@@ -324,28 +569,28 @@ export async function createServer(config) {
|
|
|
324
569
|
}
|
|
325
570
|
return reply.send({ success: true });
|
|
326
571
|
});
|
|
327
|
-
// GET /api/workspace/mcp-config — MCP client configuration snippet
|
|
572
|
+
// GET /api/workspace/mcp-config — MCP client configuration snippet.
|
|
573
|
+
// Returns a template with `<your-token-here>` in the Authorization header;
|
|
574
|
+
// the frontend fills it in after the user mints a personal token via
|
|
575
|
+
// POST /api/auth/tokens. We never embed a shared key here because doing so
|
|
576
|
+
// would leak a workspace-wide credential and re-introduce the bug the
|
|
577
|
+
// per-user-token model exists to solve.
|
|
328
578
|
fastify.get('/api/workspace/mcp-config', async (req, reply) => {
|
|
329
|
-
const user = req.user;
|
|
330
|
-
if (user && user.role !== 'admin') {
|
|
331
|
-
return reply.status(403).send({ error: 'Admin access required' });
|
|
332
|
-
}
|
|
333
579
|
const proto = req.headers['x-forwarded-proto'] === 'https' ? 'https' : (req.protocol ?? 'http');
|
|
334
580
|
const host = req.headers['x-forwarded-host'] || req.headers.host || 'localhost';
|
|
335
581
|
const baseUrl = `${proto}://${host}`;
|
|
336
|
-
const apiKey = authService.getApiKey();
|
|
337
582
|
const mcpConfig = {
|
|
338
583
|
mcpServers: {
|
|
339
584
|
studiograph: {
|
|
340
585
|
type: 'streamable-http',
|
|
341
586
|
url: `${baseUrl}/mcp`,
|
|
342
587
|
headers: {
|
|
343
|
-
Authorization:
|
|
588
|
+
Authorization: 'Bearer <your-token-here>',
|
|
344
589
|
},
|
|
345
590
|
},
|
|
346
591
|
},
|
|
347
592
|
};
|
|
348
|
-
return reply.send({ config: mcpConfig });
|
|
593
|
+
return reply.send({ config: mcpConfig, url: `${baseUrl}/mcp` });
|
|
349
594
|
});
|
|
350
595
|
// DELETE /api/memory — clear all agent memory files
|
|
351
596
|
fastify.delete('/api/memory', async (_req, reply) => {
|
|
@@ -357,19 +602,6 @@ export async function createServer(config) {
|
|
|
357
602
|
const count = agent?.clearSessions() ?? 0;
|
|
358
603
|
return reply.send({ cleared: count });
|
|
359
604
|
});
|
|
360
|
-
// Mount app plugins
|
|
361
|
-
for (const manifest of manifests) {
|
|
362
|
-
try {
|
|
363
|
-
await loader.mountPlugin(fastify, manifest, config.appsDir, {
|
|
364
|
-
workspaceManager: config.workspaceManager,
|
|
365
|
-
gitUser: config.gitUser,
|
|
366
|
-
});
|
|
367
|
-
fastify.log.info(`Mounted app "${manifest.name}" at ${manifest.mountPath}`);
|
|
368
|
-
}
|
|
369
|
-
catch (err) {
|
|
370
|
-
fastify.log.error(err, `Failed to mount app "${manifest.name}"`);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
605
|
// Serve web UI static files from dist/web/ with SPA fallback
|
|
374
606
|
// When running via tsx from source, import.meta.dirname is src/server/ so ../web doesn't exist.
|
|
375
607
|
// Fall back to dist/web/ relative to project root.
|
|
@@ -377,12 +609,34 @@ export async function createServer(config) {
|
|
|
377
609
|
const webDir = existsSync(webDirCandidate) ? webDirCandidate : join(import.meta.dirname, '..', '..', 'dist', 'web');
|
|
378
610
|
if (existsSync(webDir)) {
|
|
379
611
|
const indexPath = join(webDir, 'index.html');
|
|
380
|
-
// SPA fallback
|
|
381
|
-
//
|
|
382
|
-
// refreshes a URL like /documents/document/doc-123 — the app's greedy route
|
|
383
|
-
// catches it but fails because the params don't match its expectations.
|
|
612
|
+
// SPA fallback: if any API route returns a JSON error for a browser GET,
|
|
613
|
+
// serve the SPA instead so client-side routing can handle the URL.
|
|
384
614
|
// Read fresh from disk each time so rebuilds take effect without server restart.
|
|
385
615
|
const readIndexHtml = () => readFileSync(indexPath);
|
|
616
|
+
/**
|
|
617
|
+
* Cache policy for static assets:
|
|
618
|
+
* - `/_app/immutable/*` are content-hashed by SvelteKit, so the URL
|
|
619
|
+
* changes every time the file does — safe to cache forever.
|
|
620
|
+
* - `index.html` (and the SPA fallback) MUST revalidate every load,
|
|
621
|
+
* otherwise stale HTML keeps pointing at expired immutable hashes.
|
|
622
|
+
* - Other root assets (favicons, og images, etc.) get a modest TTL.
|
|
623
|
+
*
|
|
624
|
+
* Without these headers the upstream CDN (Fastly in front of Railway)
|
|
625
|
+
* forwards almost every request to origin, producing multi-second
|
|
626
|
+
* TTFB on cold edges and a 3-5s "black screen" while the SPA bundle
|
|
627
|
+
* loads.
|
|
628
|
+
*/
|
|
629
|
+
function setStaticCacheHeader(reply, urlPath) {
|
|
630
|
+
if (urlPath.startsWith('/_app/immutable/')) {
|
|
631
|
+
reply.header('Cache-Control', 'public, max-age=31536000, immutable');
|
|
632
|
+
}
|
|
633
|
+
else if (urlPath === '/' || urlPath === '/index.html' || !extname(urlPath)) {
|
|
634
|
+
reply.header('Cache-Control', 'no-cache');
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
reply.header('Cache-Control', 'public, max-age=3600');
|
|
638
|
+
}
|
|
639
|
+
}
|
|
386
640
|
fastify.addHook('onSend', async (request, reply, payload) => {
|
|
387
641
|
if (reply.sent)
|
|
388
642
|
return payload;
|
|
@@ -393,23 +647,24 @@ export async function createServer(config) {
|
|
|
393
647
|
typeof ct === 'string' && ct.includes('application/json')) {
|
|
394
648
|
reply.removeHeader('content-length');
|
|
395
649
|
reply.code(200).type('text/html');
|
|
650
|
+
reply.header('Cache-Control', 'no-cache');
|
|
396
651
|
return readIndexHtml();
|
|
397
652
|
}
|
|
398
653
|
return payload;
|
|
399
654
|
});
|
|
400
|
-
// Use setNotFoundHandler so
|
|
655
|
+
// Use setNotFoundHandler so API routes take priority over SPA fallback
|
|
401
656
|
fastify.setNotFoundHandler(async (req, reply) => {
|
|
402
657
|
const urlPath = req.url.split('?')[0];
|
|
403
|
-
const
|
|
404
|
-
|
|
658
|
+
const fullPath = resolveStaticFilePath(webDir, urlPath);
|
|
659
|
+
if (!fullPath) {
|
|
660
|
+
return reply.status(400).send({ error: 'Invalid path' });
|
|
661
|
+
}
|
|
405
662
|
// Serve the file if it exists (and is a file, not directory)
|
|
406
663
|
if (existsSync(fullPath) && statSync(fullPath).isFile()) {
|
|
407
|
-
if (fullPath.includes('..')) {
|
|
408
|
-
return reply.status(400).send({ error: 'Invalid path' });
|
|
409
|
-
}
|
|
410
664
|
const ext = extname(fullPath).toLowerCase();
|
|
411
665
|
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
412
666
|
reply.type(contentType);
|
|
667
|
+
setStaticCacheHeader(reply, urlPath);
|
|
413
668
|
return reply.send(createReadStream(fullPath));
|
|
414
669
|
}
|
|
415
670
|
// SPA fallback — serve index.html for client-side routing.
|
|
@@ -419,18 +674,21 @@ export async function createServer(config) {
|
|
|
419
674
|
const hasFileExt = extname(urlPath).length > 1;
|
|
420
675
|
if (req.method === 'GET' && !hasFileExt && existsSync(indexPath)) {
|
|
421
676
|
reply.type('text/html');
|
|
677
|
+
reply.header('Cache-Control', 'no-cache');
|
|
422
678
|
return reply.send(createReadStream(indexPath));
|
|
423
679
|
}
|
|
424
680
|
return reply.status(404).send({ error: 'Not found' });
|
|
425
681
|
});
|
|
426
682
|
fastify.log.info('Web UI enabled — serving from dist/web/');
|
|
427
683
|
}
|
|
428
|
-
// Graceful shutdown —
|
|
684
|
+
// Graceful shutdown — sessionManager.shutdown() flushes pending commits
|
|
685
|
+
// BEFORE tearing down the timer (the old destroy()-only path could lose
|
|
686
|
+
// dirty sessions if called without an explicit flush).
|
|
429
687
|
fastify.addHook('onClose', async () => {
|
|
430
|
-
await sessionManager.
|
|
431
|
-
|
|
432
|
-
yjsManager.destroy();
|
|
688
|
+
await sessionManager.shutdown();
|
|
689
|
+
await yjsManager.destroy();
|
|
433
690
|
wsHub.destroy();
|
|
691
|
+
releaseYjsLock();
|
|
434
692
|
});
|
|
435
693
|
return fastify;
|
|
436
694
|
}
|