studiograph 1.3.48-next.21 → 1.3.48-next.211
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 +87 -3
- package/dist/agent/agent-pool.js +188 -15
- package/dist/agent/agent-pool.js.map +1 -1
- 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 +101 -4
- package/dist/agent/orchestrator.js +464 -66
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/entity-types-section.d.ts +34 -0
- package/dist/agent/prompts/entity-types-section.js +76 -0
- package/dist/agent/prompts/entity-types-section.js.map +1 -0
- package/dist/agent/prompts/system.md +112 -54
- 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/artifact-canvas/skill.md +152 -0
- package/dist/agent/skills/entity-schema.md +75 -431
- package/dist/agent/skills/interview/entity-templates.md +38 -37
- package/dist/agent/skills/interview/question-domains.md +54 -49
- package/dist/agent/skills/interview/skill.md +84 -16
- package/dist/agent/skills/schema-rules.md +28 -28
- package/dist/agent/tools/artifact-tools.d.ts +124 -0
- package/dist/agent/tools/artifact-tools.js +207 -0
- package/dist/agent/tools/artifact-tools.js.map +1 -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 +6 -5
- package/dist/agent/tools/fs-tools.js +5 -5
- package/dist/agent/tools/fs-tools.js.map +1 -1
- package/dist/agent/tools/graph-tools.d.ts +48 -72
- package/dist/agent/tools/graph-tools.js +852 -329
- 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 -43
- 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.js +58 -9
- package/dist/agent/tools/web-tools.js.map +1 -1
- 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/{collection.js → admin/folder.js} +33 -32
- 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/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 +5 -1
- 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 +54 -6
- package/dist/cli/commands/mcp.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 +132 -34
- package/dist/cli/commands/reset.js.map +1 -1
- package/dist/cli/commands/serve.js +231 -26
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/sync.d.ts +1 -1
- package/dist/cli/commands/sync.js +237 -227
- 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 -26
- 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 +30 -49
- package/dist/cli/setup-wizard.js +39 -40
- 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/artifact-asset-urls.d.ts +51 -0
- package/dist/core/artifact-asset-urls.js +79 -0
- package/dist/core/artifact-asset-urls.js.map +1 -0
- package/dist/core/artifact-bundle.d.ts +69 -0
- package/dist/core/artifact-bundle.js +305 -0
- package/dist/core/artifact-bundle.js.map +1 -0
- package/dist/core/artifact-escape.d.ts +5 -0
- package/dist/core/artifact-escape.js +26 -0
- package/dist/core/artifact-escape.js.map +1 -0
- package/dist/core/artifact-export.d.ts +17 -0
- package/dist/core/artifact-export.js +529 -0
- package/dist/core/artifact-export.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 +96 -0
- package/dist/core/embeds.js +196 -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 +67 -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 +142 -0
- package/dist/core/entity-types-catalog.js.map +1 -0
- package/dist/core/field-library.d.ts +62 -0
- package/dist/core/field-library.js +129 -0
- package/dist/core/field-library.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/format-registry.d.ts +170 -0
- package/dist/core/format-registry.js +412 -0
- package/dist/core/format-registry.js.map +1 -0
- package/dist/core/graph.d.ts +773 -14
- package/dist/core/graph.js +2269 -308
- 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/refs.d.ts +41 -0
- package/dist/core/refs.js +80 -0
- package/dist/core/refs.js.map +1 -0
- package/dist/core/schema-registry.d.ts +66 -0
- package/dist/core/schema-registry.js +198 -37
- 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/tavily.d.ts +18 -0
- package/dist/core/secrets/probes/tavily.js +58 -0
- package/dist/core/secrets/probes/tavily.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 +616 -0
- package/dist/core/secrets/registry.js.map +1 -0
- package/dist/core/types.d.ts +77 -483
- package/dist/core/types.js +25 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +75 -12
- package/dist/core/user-config.js +155 -14
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +786 -1373
- package/dist/core/validation.js +458 -147
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +87 -14
- package/dist/core/workspace-manager.js +222 -94
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +19 -5
- package/dist/core/workspace.js +67 -39
- 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 +72 -2
- package/dist/mcp/connector-manager.js +211 -32
- package/dist/mcp/connector-manager.js.map +1 -1
- package/dist/mcp/oauth-provider.d.ts +0 -5
- package/dist/mcp/oauth-provider.js +10 -22
- package/dist/mcp/oauth-provider.js.map +1 -1
- package/dist/mcp/oauth-registry.d.ts +46 -8
- package/dist/mcp/oauth-registry.js +52 -13
- package/dist/mcp/oauth-registry.js.map +1 -1
- package/dist/mcp/server-discovery.d.ts +73 -0
- package/dist/mcp/server-discovery.js +164 -0
- package/dist/mcp/server-discovery.js.map +1 -0
- package/dist/mcp/server.d.ts +24 -3
- package/dist/mcp/server.js +53 -10
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/state-signer.d.ts +62 -0
- package/dist/mcp/state-signer.js +205 -0
- package/dist/mcp/state-signer.js.map +1 -0
- package/dist/mcp/stdio-proxy.d.ts +67 -0
- package/dist/mcp/stdio-proxy.js +149 -0
- package/dist/mcp/stdio-proxy.js.map +1 -0
- package/dist/mcp/tools.d.ts +65 -2
- package/dist/mcp/tools.js +1772 -124
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/__tests__/helpers/graph-api.d.ts +16 -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/artifact-asset-mint.d.ts +41 -0
- package/dist/server/artifact-asset-mint.js +59 -0
- package/dist/server/artifact-asset-mint.js.map +1 -0
- package/dist/server/asset-index-queue.d.ts +98 -0
- package/dist/server/asset-index-queue.js +193 -0
- package/dist/server/asset-index-queue.js.map +1 -0
- package/dist/server/body-write-coordinator.d.ts +161 -0
- package/dist/server/body-write-coordinator.js +182 -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 +29 -3
- package/dist/server/index.js +657 -269
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/sanitize.d.ts +46 -0
- package/dist/server/middleware/sanitize.js +182 -0
- package/dist/server/middleware/sanitize.js.map +1 -0
- package/dist/server/routes/artifact-export-api.d.ts +11 -0
- package/dist/server/routes/artifact-export-api.js +159 -0
- package/dist/server/routes/artifact-export-api.js.map +1 -0
- package/dist/server/routes/asset-api.d.ts +76 -1
- package/dist/server/routes/asset-api.js +761 -61
- package/dist/server/routes/asset-api.js.map +1 -1
- 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.js +532 -63
- package/dist/server/routes/auth-api.js.map +1 -1
- package/dist/server/routes/capture-api.d.ts +10 -3
- package/dist/server/routes/capture-api.js +213 -25
- package/dist/server/routes/capture-api.js.map +1 -1
- package/dist/server/routes/chat-sessions-api.d.ts +13 -0
- package/dist/server/routes/chat-sessions-api.js +455 -0
- package/dist/server/routes/chat-sessions-api.js.map +1 -0
- package/dist/server/routes/chat.d.ts +35 -1
- package/dist/server/routes/chat.js +699 -54
- 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 +3 -2
- package/dist/server/routes/config-api.js +179 -49
- package/dist/server/routes/config-api.js.map +1 -1
- package/dist/server/routes/connectors-api.js +177 -42
- package/dist/server/routes/connectors-api.js.map +1 -1
- package/dist/server/routes/event-ingest-api.d.ts +15 -0
- package/dist/server/routes/{meeting-ingest-api.js → event-ingest-api.js} +35 -20
- package/dist/server/routes/event-ingest-api.js.map +1 -0
- package/dist/server/routes/field-library-api.d.ts +28 -0
- package/dist/server/routes/field-library-api.js +126 -0
- package/dist/server/routes/field-library-api.js.map +1 -0
- package/dist/server/routes/git-http.d.ts +2 -2
- package/dist/server/routes/git-http.js +86 -39
- package/dist/server/routes/git-http.js.map +1 -1
- package/dist/server/routes/graph-api-access.d.ts +57 -0
- package/dist/server/routes/graph-api-access.js +112 -0
- package/dist/server/routes/graph-api-access.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +1 -1
- package/dist/server/routes/graph-api.js +1455 -325
- 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/import-batch.d.ts +24 -0
- package/dist/server/routes/import-batch.js +33 -0
- package/dist/server/routes/import-batch.js.map +1 -0
- package/dist/server/routes/insights-api.d.ts +9 -2
- package/dist/server/routes/insights-api.js +355 -61
- 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 +24 -8
- package/dist/server/routes/mcp.js.map +1 -1
- package/dist/server/routes/oauth-api.d.ts +67 -0
- package/dist/server/routes/oauth-api.js +421 -0
- package/dist/server/routes/oauth-api.js.map +1 -0
- package/dist/server/routes/permissions-api.d.ts +9 -2
- package/dist/server/routes/permissions-api.js +87 -31
- 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/share-api.d.ts +32 -0
- package/dist/server/routes/share-api.js +234 -0
- package/dist/server/routes/share-api.js.map +1 -0
- package/dist/server/routes/views-api.js +51 -0
- 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 +142 -23
- package/dist/server/routes/workspace-api.js.map +1 -1
- package/dist/server/routes/ws.d.ts +3 -2
- package/dist/server/routes/ws.js +68 -17
- 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 -14
- package/dist/server/session-manager.js.map +1 -1
- package/dist/server/ws-hub.d.ts +124 -37
- package/dist/server/ws-hub.js +0 -0
- package/dist/server/ws-hub.js.map +1 -1
- package/dist/server/yjs-manager.d.ts +278 -7
- package/dist/server/yjs-manager.js +830 -38
- 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 +165 -0
- package/dist/services/access-control.js.map +1 -0
- package/dist/services/artifact-asset-token.d.ts +69 -0
- package/dist/services/artifact-asset-token.js +94 -0
- package/dist/services/artifact-asset-token.js.map +1 -0
- package/dist/services/artifact-library-sources.d.ts +3 -0
- package/dist/services/artifact-library-sources.js +44 -0
- package/dist/services/artifact-library-sources.js.map +1 -0
- package/dist/services/artifact-render-export.d.ts +97 -0
- package/dist/services/artifact-render-export.js +467 -0
- package/dist/services/artifact-render-export.js.map +1 -0
- package/dist/services/asset-caption-service.d.ts +103 -0
- package/dist/services/asset-caption-service.js +186 -0
- package/dist/services/asset-caption-service.js.map +1 -0
- package/dist/services/asset-delete-authz.d.ts +31 -0
- package/dist/services/asset-delete-authz.js +61 -0
- package/dist/services/asset-delete-authz.js.map +1 -0
- package/dist/services/asset-finalize-service.d.ts +58 -0
- package/dist/services/asset-finalize-service.js +216 -0
- package/dist/services/asset-finalize-service.js.map +1 -0
- package/dist/services/asset-import-service.d.ts +111 -0
- package/dist/services/asset-import-service.js +394 -0
- package/dist/services/asset-import-service.js.map +1 -0
- package/dist/services/asset-index-sweep.d.ts +95 -0
- package/dist/services/asset-index-sweep.js +249 -0
- package/dist/services/asset-index-sweep.js.map +1 -0
- package/dist/services/asset-lifecycle-check.d.ts +22 -0
- package/dist/services/asset-lifecycle-check.js +80 -0
- package/dist/services/asset-lifecycle-check.js.map +1 -0
- package/dist/services/asset-listing.d.ts +72 -0
- package/dist/services/asset-listing.js +321 -0
- package/dist/services/asset-listing.js.map +1 -0
- package/dist/services/asset-presign-service.d.ts +68 -0
- package/dist/services/asset-presign-service.js +124 -0
- package/dist/services/asset-presign-service.js.map +1 -0
- package/dist/services/asset-sidecar-service.d.ts +28 -0
- package/dist/services/asset-sidecar-service.js +79 -0
- package/dist/services/asset-sidecar-service.js.map +1 -0
- package/dist/services/asset-upload-errors.d.ts +41 -0
- package/dist/services/asset-upload-errors.js +45 -0
- package/dist/services/asset-upload-errors.js.map +1 -0
- package/dist/services/asset-upload-service.d.ts +56 -0
- package/dist/services/asset-upload-service.js +200 -0
- package/dist/services/asset-upload-service.js.map +1 -0
- package/dist/services/asset-upload-token.d.ts +58 -0
- package/dist/services/asset-upload-token.js +75 -0
- package/dist/services/asset-upload-token.js.map +1 -0
- package/dist/services/assets/asset-index-service.d.ts +127 -0
- package/dist/services/assets/asset-index-service.js +227 -0
- package/dist/services/assets/asset-index-service.js.map +1 -0
- package/dist/services/assets/base.d.ts +128 -2
- package/dist/services/assets/base.js +98 -1
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +114 -1
- package/dist/services/assets/index.js +221 -0
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/assets/local.d.ts +16 -1
- package/dist/services/assets/local.js +110 -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 +87 -1
- package/dist/services/assets/r2.js +203 -1
- package/dist/services/assets/r2.js.map +1 -1
- package/dist/services/auth-service.d.ts +312 -45
- package/dist/services/auth-service.js +1011 -195
- package/dist/services/auth-service.js.map +1 -1
- package/dist/services/chat-session-service.d.ts +188 -0
- package/dist/services/chat-session-service.js +512 -0
- package/dist/services/chat-session-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/comment-virtual-entity.d.ts +36 -0
- package/dist/services/comment-virtual-entity.js +71 -0
- package/dist/services/comment-virtual-entity.js.map +1 -0
- package/dist/services/convert-service.d.ts +64 -0
- package/dist/services/convert-service.js +68 -0
- package/dist/services/convert-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 +213 -0
- package/dist/services/entity-mutations.js +380 -0
- package/dist/services/entity-mutations.js.map +1 -0
- package/dist/services/{meeting-processor.d.ts → event-processor.d.ts} +15 -8
- package/dist/services/{meeting-processor.js → event-processor.js} +124 -65
- package/dist/services/event-processor.js.map +1 -0
- package/dist/services/extract/docx.d.ts +1 -0
- package/dist/services/extract/docx.js +233 -0
- package/dist/services/extract/docx.js.map +1 -0
- package/dist/services/extract/index.d.ts +9 -0
- package/dist/services/extract/index.js +10 -0
- package/dist/services/extract/index.js.map +1 -0
- package/dist/services/extract/pdf.d.ts +13 -0
- package/dist/services/extract/pdf.js +69 -0
- package/dist/services/extract/pdf.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 +58 -0
- package/dist/services/git.js +194 -55
- package/dist/services/git.js.map +1 -1
- package/dist/services/graph-maintenance.js +4 -4
- package/dist/services/graph-maintenance.js.map +1 -1
- package/dist/services/import-service.d.ts +51 -2
- package/dist/services/import-service.js +254 -107
- package/dist/services/import-service.js.map +1 -1
- package/dist/services/lint-service.js +10 -17
- package/dist/services/lint-service.js.map +1 -1
- package/dist/services/markdown.d.ts +12 -1
- package/dist/services/markdown.js +77 -9
- package/dist/services/markdown.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/model-capabilities.d.ts +41 -0
- package/dist/services/model-capabilities.js +107 -0
- package/dist/services/model-capabilities.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/oauth-server-store.d.ts +147 -0
- package/dist/services/oauth-server-store.js +319 -0
- package/dist/services/oauth-server-store.js.map +1 -0
- package/dist/services/orphan-service.js +2 -2
- package/dist/services/orphan-service.js.map +1 -1
- 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/scratch-asset-promote.d.ts +57 -0
- package/dist/services/scratch-asset-promote.js +95 -0
- package/dist/services/scratch-asset-promote.js.map +1 -0
- package/dist/services/scratch-attachment-service.d.ts +196 -0
- package/dist/services/scratch-attachment-service.js +347 -0
- package/dist/services/scratch-attachment-service.js.map +1 -0
- package/dist/services/share-link-service.d.ts +57 -0
- package/dist/services/share-link-service.js +142 -0
- package/dist/services/share-link-service.js.map +1 -0
- package/dist/services/user-person-bridge.d.ts +136 -0
- package/dist/services/user-person-bridge.js +340 -0
- package/dist/services/user-person-bridge.js.map +1 -0
- package/dist/services/vector-service.d.ts +282 -5
- package/dist/services/vector-service.js +585 -29
- package/dist/services/vector-service.js.map +1 -1
- package/dist/services/workspace-access.d.ts +108 -0
- package/dist/services/workspace-access.js +149 -0
- package/dist/services/workspace-access.js.map +1 -0
- package/dist/services/workspace-assets-folder.d.ts +46 -0
- package/dist/services/workspace-assets-folder.js +75 -0
- package/dist/services/workspace-assets-folder.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.Bs_z3Z86.css +2 -0
- package/dist/web/_app/immutable/assets/12.DlIf1mKh.css +1 -0
- package/dist/web/_app/immutable/assets/14.7d-Q37wc.css +1 -0
- package/dist/web/_app/immutable/assets/15.BwBFdc1D.css +1 -0
- package/dist/web/_app/immutable/assets/16.CmLrbzZp.css +1 -0
- package/dist/web/_app/immutable/assets/17.DcuK5ZVm.css +1 -0
- package/dist/web/_app/immutable/assets/2.DATnR31c.css +1 -0
- package/dist/web/_app/immutable/assets/3.Cz4H8n_O.css +1 -0
- package/dist/web/_app/immutable/assets/4.aDHteTDy.css +1 -0
- package/dist/web/_app/immutable/assets/6.CF1i5Bon.css +1 -0
- package/dist/web/_app/immutable/assets/ArtifactEntityView.C4ooklFD.css +1 -0
- package/dist/web/_app/immutable/assets/AssetLibraryPicker.BOFW0MvF.css +1 -0
- package/dist/web/_app/immutable/assets/BulkActionsBar.cmKvHzRK.css +1 -0
- package/dist/web/_app/immutable/assets/CalendarView.lBCvS3X5.css +1 -0
- package/dist/web/_app/immutable/assets/CodeMirrorEditor.D6hf2pNJ.css +1 -0
- package/dist/web/_app/immutable/assets/CopyField.DVGZtw4U.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMembersPanel.kiYnDFHu.css +1 -0
- package/dist/web/_app/immutable/assets/FolderMutationDialogs.BMRF6Z3z.css +1 -0
- package/dist/web/_app/immutable/assets/FolderPicker.Cp46GHe2.css +1 -0
- package/dist/web/_app/immutable/assets/GalleryView.WBGxxUQc.css +1 -0
- package/dist/web/_app/immutable/assets/GraphView.BJtGL9py.css +1 -0
- package/dist/web/_app/immutable/assets/KanbanView.BOaI5KFL.css +1 -0
- package/dist/web/_app/immutable/assets/Link.vV0ne105.css +1 -0
- package/dist/web/_app/immutable/assets/Markdown.BZnsSOSf.css +1 -0
- package/dist/web/_app/immutable/assets/Rail.ilusFgD4.css +1 -0
- package/dist/web/_app/immutable/assets/SettingsDialog.D7-BO6S_.css +1 -0
- package/dist/web/_app/immutable/assets/Spinner.UBfl0pab.css +1 -0
- package/dist/web/_app/immutable/assets/StopFilledAlt.fNlDN65D.css +1 -0
- package/dist/web/_app/immutable/assets/TimelineView.xAZBJhHw.css +1 -0
- package/dist/web/_app/immutable/assets/WorkspaceView.C8ErUJAY.css +1 -0
- package/dist/web/_app/immutable/assets/button.BlLm4Dg1.css +1 -0
- package/dist/web/_app/immutable/assets/history-summary.LpmHXasl.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.BgnafZ4K.css +1 -0
- package/dist/web/_app/immutable/assets/realtime.DDCWxn3B.css +1 -0
- package/dist/web/_app/immutable/assets/select.B90KUqR4.css +1 -0
- package/dist/web/_app/immutable/assets/sheet.RF9RBmml.css +1 -0
- package/dist/web/_app/immutable/chunks/22qYtvr82.js +1 -0
- package/dist/web/_app/immutable/chunks/2f1VclTm.js +1 -0
- package/dist/web/_app/immutable/chunks/4xgUPoGj2.js +2 -0
- package/dist/web/_app/immutable/chunks/5CYQk4xR.js +1 -0
- package/dist/web/_app/immutable/chunks/6S9WOky52.js +1 -0
- package/dist/web/_app/immutable/chunks/9K8VREGP.js +1 -0
- package/dist/web/_app/immutable/chunks/B-n5q6ku.js +1 -0
- package/dist/web/_app/immutable/chunks/B0p2fSEV2.js +1 -0
- package/dist/web/_app/immutable/chunks/B2oi87jG.js +2 -0
- package/dist/web/_app/immutable/chunks/B5Rb52QU.js +1 -0
- package/dist/web/_app/immutable/chunks/B6Lt-qaJ.js +1 -0
- package/dist/web/_app/immutable/chunks/B6O-q2CN.js +1 -0
- package/dist/web/_app/immutable/chunks/B6qeIQZz.js +2 -0
- package/dist/web/_app/immutable/chunks/B9KfEsQw2.js +1 -0
- package/dist/web/_app/immutable/chunks/BB-RSeXQ.js +1 -0
- package/dist/web/_app/immutable/chunks/BCQQzpbj.js +1 -0
- package/dist/web/_app/immutable/chunks/BGdzd-Tc.js +1 -0
- package/dist/web/_app/immutable/chunks/BLs1h0Rh2.js +1 -0
- package/dist/web/_app/immutable/chunks/BPzV_xOS2.js +1 -0
- package/dist/web/_app/immutable/chunks/BT2C6q8n.js +1 -0
- package/dist/web/_app/immutable/chunks/BUesbLq2.js +1 -0
- package/dist/web/_app/immutable/chunks/BUrnwOw4.js +2 -0
- package/dist/web/_app/immutable/chunks/BV-iCKqa.js +1 -0
- package/dist/web/_app/immutable/chunks/BVCJtXyc.js +1 -0
- package/dist/web/_app/immutable/chunks/BY9a3GSt.js +6 -0
- package/dist/web/_app/immutable/chunks/BZi3uKF4.js +1 -0
- package/dist/web/_app/immutable/chunks/BbfHGU9n2.js +1 -0
- package/dist/web/_app/immutable/chunks/Bbqu2-5G2.js +1 -0
- package/dist/web/_app/immutable/chunks/BbsX1Slr.js +3 -0
- package/dist/web/_app/immutable/chunks/BcwjqHaZ2.js +1 -0
- package/dist/web/_app/immutable/chunks/BizeEpTx.js +2 -0
- package/dist/web/_app/immutable/chunks/BlgjVmFM2.js +14 -0
- package/dist/web/_app/immutable/chunks/BocSRgv12.js +1 -0
- package/dist/web/_app/immutable/chunks/BojBYqc3.js +1 -0
- package/dist/web/_app/immutable/chunks/BpCG9m962.js +1 -0
- package/dist/web/_app/immutable/chunks/BqvnBg_y.js +1 -0
- package/dist/web/_app/immutable/chunks/BsT0J1QD.js +1 -0
- package/dist/web/_app/immutable/chunks/BsW72fyR2.js +1 -0
- package/dist/web/_app/immutable/chunks/Bti_XKwx.js +2692 -0
- package/dist/web/_app/immutable/chunks/Bua97Had2.js +2 -0
- package/dist/web/_app/immutable/chunks/BuhW5Fr0.js +689 -0
- package/dist/web/_app/immutable/chunks/Bx74EEyn2.js +1 -0
- package/dist/web/_app/immutable/chunks/BxPN0T61.js +1 -0
- package/dist/web/_app/immutable/chunks/Bz9lrgGs.js +1 -0
- package/dist/web/_app/immutable/chunks/BzaxZ6j12.js +1 -0
- package/dist/web/_app/immutable/chunks/C1B4xDs0.js +1 -0
- package/dist/web/_app/immutable/chunks/C1trcC8M.js +7 -0
- package/dist/web/_app/immutable/chunks/C9tvkk7Y2.js +22 -0
- package/dist/web/_app/immutable/chunks/CBQjdDZf.js +1 -0
- package/dist/web/_app/immutable/chunks/CDeazMFW2.js +2 -0
- package/dist/web/_app/immutable/chunks/CEahbtnP.js +1 -0
- package/dist/web/_app/immutable/chunks/CGjVCd0e.js +8 -0
- package/dist/web/_app/immutable/chunks/CICK9maP.js +1 -0
- package/dist/web/_app/immutable/chunks/CIoNEHQ82.js +184 -0
- package/dist/web/_app/immutable/chunks/CP8_U450.js +1 -0
- package/dist/web/_app/immutable/chunks/CQ1eQ93t2.js +6 -0
- package/dist/web/_app/immutable/chunks/CUFQMEBn2.js +1 -0
- package/dist/web/_app/immutable/chunks/CYEYDNwO2.js +1 -0
- package/dist/web/_app/immutable/chunks/CYyIP7kP2.js +66 -0
- package/dist/web/_app/immutable/chunks/CZgFaimi2.js +83 -0
- package/dist/web/_app/immutable/chunks/CZqvCTCv.js +1 -0
- package/dist/web/_app/immutable/chunks/CcI9jYBV.js +1 -0
- package/dist/web/_app/immutable/chunks/CcWaWbrI2.js +1 -0
- package/dist/web/_app/immutable/chunks/CdtzRVZK.js +1 -0
- package/dist/web/_app/immutable/chunks/CfYG72Hc.js +1 -0
- package/dist/web/_app/immutable/chunks/Ch1kmm3J2.js +1 -0
- package/dist/web/_app/immutable/chunks/CmSSN61R2.js +1 -0
- package/dist/web/_app/immutable/chunks/Cqm5wAin.js +1 -0
- package/dist/web/_app/immutable/chunks/CuYPXpWU.js +1 -0
- package/dist/web/_app/immutable/chunks/CvSEodTA.js +1 -0
- package/dist/web/_app/immutable/chunks/CvqqrTrj.js +1 -0
- package/dist/web/_app/immutable/chunks/CwAmWt6h.js +1 -0
- package/dist/web/_app/immutable/chunks/CwP3Oa7F.js +1 -0
- package/dist/web/_app/immutable/chunks/CyTluew1.js +2 -0
- package/dist/web/_app/immutable/chunks/CzXdOgVl2.js +7 -0
- package/dist/web/_app/immutable/chunks/D0IAituJ.js +1 -0
- package/dist/web/_app/immutable/chunks/D0W7c6Sg.js +185 -0
- package/dist/web/_app/immutable/chunks/D0rBhnqB2.js +1 -0
- package/dist/web/_app/immutable/chunks/D1-GZSN1.js +1 -0
- package/dist/web/_app/immutable/chunks/D1yvtriI.js +1 -0
- package/dist/web/_app/immutable/chunks/D25NMRpl.js +1 -0
- package/dist/web/_app/immutable/chunks/D8wZ2xul.js +4 -0
- package/dist/web/_app/immutable/chunks/DA3HEX3X.js +1 -0
- package/dist/web/_app/immutable/chunks/DD9wj4ca2.js +1 -0
- package/dist/web/_app/immutable/chunks/DJ1YeiJL2.js +1 -0
- package/dist/web/_app/immutable/chunks/DKFZnpVC.js +5 -0
- package/dist/web/_app/immutable/chunks/DKJl40hl.js +1 -0
- package/dist/web/_app/immutable/chunks/DPUVu0T0.js +1 -0
- package/dist/web/_app/immutable/chunks/DQMWa2t7.js +1 -0
- package/dist/web/_app/immutable/chunks/DXsFrDer2.js +1 -0
- package/dist/web/_app/immutable/chunks/DYc5KW3F.js +1 -0
- package/dist/web/_app/immutable/chunks/DZcTwXBW.js +1 -0
- package/dist/web/_app/immutable/chunks/DcPrzUMJ.js +1 -0
- package/dist/web/_app/immutable/chunks/DdPO8kRu2.js +2 -0
- package/dist/web/_app/immutable/chunks/DeOXyJZw2.js +1 -0
- package/dist/web/_app/immutable/chunks/DfufUFR1.js +2 -0
- package/dist/web/_app/immutable/chunks/DiQg3ing.js +1 -0
- package/dist/web/_app/immutable/chunks/DjIqa1_y.js +2 -0
- package/dist/web/_app/immutable/chunks/DkJ1dkxV2.js +1 -0
- package/dist/web/_app/immutable/chunks/Dl63IUnH2.js +224 -0
- package/dist/web/_app/immutable/chunks/DmFdD6zT.js +1 -0
- package/dist/web/_app/immutable/chunks/Dn3R8S-U.js +1 -0
- package/dist/web/_app/immutable/chunks/DpNr1GQ2.js +1 -0
- package/dist/web/_app/immutable/chunks/DpVNDHXz.js +2 -0
- package/dist/web/_app/immutable/chunks/DuxziNnw.js +1 -0
- package/dist/web/_app/immutable/chunks/Dv3A3Wcj.js +1 -0
- package/dist/web/_app/immutable/chunks/FuiJnZG0.js +1 -0
- package/dist/web/_app/immutable/chunks/Izkulod7.js +1 -0
- package/dist/web/_app/immutable/chunks/KZY6ongq2.js +2 -0
- package/dist/web/_app/immutable/chunks/LYL8znYR2.js +23 -0
- package/dist/web/_app/immutable/chunks/PhN6tXuJ2.js +1 -0
- package/dist/web/_app/immutable/chunks/PyLyCpuL.js +1 -0
- package/dist/web/_app/immutable/chunks/RK4gCWN0.js +2 -0
- package/dist/web/_app/immutable/chunks/VsBngTf4.js +2 -0
- package/dist/web/_app/immutable/chunks/XcWejFm_.js +5 -0
- package/dist/web/_app/immutable/chunks/al_nidE9.js +1 -0
- package/dist/web/_app/immutable/chunks/e50-izZO2.js +1 -0
- package/dist/web/_app/immutable/chunks/hG-QCarB.js +1 -0
- package/dist/web/_app/immutable/chunks/hStvCHkX.js +1 -0
- package/dist/web/_app/immutable/chunks/iJVY9p0y.js +3 -0
- package/dist/web/_app/immutable/chunks/kNaey6uv.js +1 -0
- package/dist/web/_app/immutable/chunks/pIXNe0C1.js +1 -0
- package/dist/web/_app/immutable/chunks/pNSRq_1B.js +2 -0
- package/dist/web/_app/immutable/chunks/qwr5boV8.js +1 -0
- package/dist/web/_app/immutable/chunks/rjjyuGhb.js +1 -0
- package/dist/web/_app/immutable/chunks/sg-T-FoN.js +1 -0
- package/dist/web/_app/immutable/chunks/uBgoVlsx.js +3 -0
- package/dist/web/_app/immutable/chunks/ulshNz6x.js +2 -0
- package/dist/web/_app/immutable/chunks/xY0c-UfG.js +3 -0
- package/dist/web/_app/immutable/chunks/xeNvx4Bl2.js +1 -0
- package/dist/web/_app/immutable/chunks/xihTtKlq.js +1 -0
- package/dist/web/_app/immutable/entry/app.pNUW-q4U.js +2 -0
- package/dist/web/_app/immutable/entry/start.DxGtIGG_.js +1 -0
- package/dist/web/_app/immutable/nodes/0.D6ZCY_R6.js +2 -0
- package/dist/web/_app/immutable/nodes/1.BryH3TNr.js +1 -0
- package/dist/web/_app/immutable/nodes/10.CMZMvR17.js +1 -0
- package/dist/web/_app/immutable/nodes/11.QHx_JShx.js +1 -0
- package/dist/web/_app/immutable/nodes/12.CiRWbb4X.js +1 -0
- package/dist/web/_app/immutable/nodes/13.CYrHXCA8.js +1 -0
- package/dist/web/_app/immutable/nodes/14.K18eIE5Z.js +1 -0
- package/dist/web/_app/immutable/nodes/15.DxgnZ61h.js +1 -0
- package/dist/web/_app/immutable/nodes/16.Dn6iuWIo.js +1 -0
- package/dist/web/_app/immutable/nodes/17.viwS7vTR.js +77 -0
- package/dist/web/_app/immutable/nodes/2.BQkQ_uUM.js +122 -0
- package/dist/web/_app/immutable/nodes/3.B4pqXsqq.js +6 -0
- package/dist/web/_app/immutable/nodes/4.CKXEgIAP.js +11 -0
- package/dist/web/_app/immutable/nodes/5.A2TASl4Q.js +1 -0
- package/dist/web/_app/immutable/nodes/6.DaIRO3SI.js +6 -0
- package/dist/web/_app/immutable/nodes/7.ga2UvFm-.js +1 -0
- package/dist/web/_app/immutable/nodes/8.BTEWT81u.js +1 -0
- package/dist/web/_app/immutable/nodes/9.BVxo0E0c.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 -21
- package/dist/web/studiograph-logomark.svg +29 -0
- package/package.json +35 -14
- package/dist/agent/skills/enrich-entities.md +0 -136
- package/dist/agent/skills/sync-configuration.md +0 -119
- package/dist/agent/skills/sync-setup.md +0 -82
- package/dist/agent/tools/message-tools.d.ts +0 -42
- package/dist/agent/tools/message-tools.js +0 -106
- package/dist/agent/tools/message-tools.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/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.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/start.d.ts +0 -7
- package/dist/cli/commands/start.js +0 -584
- package/dist/cli/commands/start.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 -175
- 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/integrations/registry.d.ts +0 -8
- package/dist/integrations/registry.js +0 -7
- package/dist/integrations/registry.js.map +0 -1
- package/dist/integrations/types.d.ts +0 -43
- package/dist/integrations/types.js +0 -5
- 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/server/chrome/chrome.css +0 -691
- package/dist/server/chrome/chrome.js +0 -374
- 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/meeting-ingest-api.d.ts +0 -14
- package/dist/server/routes/meeting-ingest-api.js.map +0 -1
- package/dist/server/routes/messages-api.d.ts +0 -15
- package/dist/server/routes/messages-api.js +0 -385
- package/dist/server/routes/messages-api.js.map +0 -1
- package/dist/services/batch-processor.d.ts +0 -49
- package/dist/services/batch-processor.js +0 -166
- package/dist/services/batch-processor.js.map +0 -1
- package/dist/services/briefing.d.ts +0 -26
- package/dist/services/briefing.js +0 -230
- package/dist/services/briefing.js.map +0 -1
- package/dist/services/heartbeat.d.ts +0 -28
- package/dist/services/heartbeat.js +0 -183
- package/dist/services/heartbeat.js.map +0 -1
- package/dist/services/image-import-service.d.ts +0 -24
- package/dist/services/image-import-service.js +0 -108
- package/dist/services/image-import-service.js.map +0 -1
- package/dist/services/insights.d.ts +0 -38
- package/dist/services/insights.js +0 -269
- package/dist/services/insights.js.map +0 -1
- package/dist/services/meeting-processor.js.map +0 -1
- package/dist/services/message-service.d.ts +0 -68
- package/dist/services/message-service.js +0 -220
- package/dist/services/message-service.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.uPSqtsC5.css +0 -1
- package/dist/web/_app/immutable/assets/11.2jzI3cZY.css +0 -1
- package/dist/web/_app/immutable/assets/12.CT4xL4K3.css +0 -1
- package/dist/web/_app/immutable/assets/13.BUrHkYry.css +0 -1
- package/dist/web/_app/immutable/assets/2.DpQWr6q6.css +0 -1
- package/dist/web/_app/immutable/assets/3.BxdqT7zi.css +0 -1
- package/dist/web/_app/immutable/assets/4.DdNqjd0T.css +0 -1
- package/dist/web/_app/immutable/assets/5.DFeGxLYf.css +0 -1
- package/dist/web/_app/immutable/assets/6.DXZr_rI_.css +0 -1
- package/dist/web/_app/immutable/assets/GraphView.D9ePpZez.css +0 -1
- package/dist/web/_app/immutable/assets/Toaster.rN8r_Hzv.css +0 -1
- package/dist/web/_app/immutable/assets/ViewToolbar.BWE03S64.css +0 -1
- package/dist/web/_app/immutable/assets/WorkspaceView.CgGDi_Zb.css +0 -1
- package/dist/web/_app/immutable/assets/wikilinks.CzMBkUMB.css +0 -1
- package/dist/web/_app/immutable/chunks/-jG4Obyh.js +0 -4
- package/dist/web/_app/immutable/chunks/2nrc8f_O.js +0 -1
- package/dist/web/_app/immutable/chunks/7S2LGqoP.js +0 -2
- package/dist/web/_app/immutable/chunks/8Q3ZJIYu.js +0 -1
- package/dist/web/_app/immutable/chunks/B8ydT5xX.js +0 -2
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +0 -3383
- package/dist/web/_app/immutable/chunks/BEn6N5c2.js +0 -1
- package/dist/web/_app/immutable/chunks/BFNNbCAM.js +0 -1
- package/dist/web/_app/immutable/chunks/BFZZEUd5.js +0 -1
- package/dist/web/_app/immutable/chunks/BGk8kfOE.js +0 -2
- package/dist/web/_app/immutable/chunks/BIBCr278.js +0 -1
- package/dist/web/_app/immutable/chunks/BPCkkwqe.js +0 -1
- package/dist/web/_app/immutable/chunks/BhlvzGQx.js +0 -1
- package/dist/web/_app/immutable/chunks/BlMknQeF.js +0 -1
- package/dist/web/_app/immutable/chunks/BpjqrlCg.js +0 -1
- package/dist/web/_app/immutable/chunks/BrebtJNG.js +0 -18
- package/dist/web/_app/immutable/chunks/ByBZ7JIT.js +0 -1
- package/dist/web/_app/immutable/chunks/Bz0ZjVQE.js +0 -2
- package/dist/web/_app/immutable/chunks/BzJTZOK2.js +0 -1
- package/dist/web/_app/immutable/chunks/C0LVZhvn.js +0 -1
- package/dist/web/_app/immutable/chunks/C3uBrOS5.js +0 -1
- package/dist/web/_app/immutable/chunks/C8R1sDpW.js +0 -1
- package/dist/web/_app/immutable/chunks/CDRHrs0g.js +0 -1
- package/dist/web/_app/immutable/chunks/CN5_py1I.js +0 -1
- package/dist/web/_app/immutable/chunks/CPne482a.js +0 -1
- package/dist/web/_app/immutable/chunks/CSVbGg_b.js +0 -5
- package/dist/web/_app/immutable/chunks/CWyU-seV.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/ChsiIm-E.js +0 -1
- package/dist/web/_app/immutable/chunks/CojKppbh.js +0 -1
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +0 -1
- package/dist/web/_app/immutable/chunks/CtYLtD7K.js +0 -1
- package/dist/web/_app/immutable/chunks/D-HDy5qS.js +0 -1
- package/dist/web/_app/immutable/chunks/D5aIYSkd.js +0 -1
- package/dist/web/_app/immutable/chunks/DBBXARVf.js +0 -1
- package/dist/web/_app/immutable/chunks/DFYOFE3o.js +0 -1
- package/dist/web/_app/immutable/chunks/DKaafS50.js +0 -1
- package/dist/web/_app/immutable/chunks/DUMOo1Pn.js +0 -1
- package/dist/web/_app/immutable/chunks/DWX9f6AF.js +0 -1
- package/dist/web/_app/immutable/chunks/DY8-EONP.js +0 -1
- package/dist/web/_app/immutable/chunks/DkoHPElM.js +0 -1
- package/dist/web/_app/immutable/chunks/DnL9f0lc.js +0 -7
- package/dist/web/_app/immutable/chunks/DsnmJJEf.js +0 -1
- package/dist/web/_app/immutable/chunks/DujahU3W.js +0 -1
- package/dist/web/_app/immutable/chunks/FBn-ES5k.js +0 -1
- package/dist/web/_app/immutable/chunks/HQpwSOb3.js +0 -1
- package/dist/web/_app/immutable/chunks/KyjzlWRN.js +0 -2
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +0 -1
- package/dist/web/_app/immutable/chunks/UwYfmrPx.js +0 -2
- package/dist/web/_app/immutable/chunks/W25ZVI8L.js +0 -2
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +0 -1
- package/dist/web/_app/immutable/chunks/XjsuEnNE.js +0 -5
- package/dist/web/_app/immutable/chunks/ZD6ARAtb.js +0 -1
- package/dist/web/_app/immutable/chunks/pBTf4stg.js +0 -2
- package/dist/web/_app/immutable/chunks/rGIarcnp.js +0 -1
- package/dist/web/_app/immutable/chunks/vxEtkL8z.js +0 -1
- package/dist/web/_app/immutable/chunks/wDIGUaoU.js +0 -3
- package/dist/web/_app/immutable/entry/app.ZHiTM8WS.js +0 -2
- package/dist/web/_app/immutable/entry/start.C9-FfAVc.js +0 -1
- package/dist/web/_app/immutable/nodes/0.D92Orz8k.js +0 -2
- package/dist/web/_app/immutable/nodes/1.BMdyglM_.js +0 -1
- package/dist/web/_app/immutable/nodes/10.BilVDHSL.js +0 -1
- package/dist/web/_app/immutable/nodes/11.CS9E0Hic.js +0 -1
- package/dist/web/_app/immutable/nodes/12.D3BOxYzG.js +0 -1
- package/dist/web/_app/immutable/nodes/13.CClMKYtN.js +0 -1
- package/dist/web/_app/immutable/nodes/2.C8KKElPL.js +0 -267
- package/dist/web/_app/immutable/nodes/3.C5n5uiWU.js +0 -5
- package/dist/web/_app/immutable/nodes/4.DcGVvgiL.js +0 -11
- package/dist/web/_app/immutable/nodes/5.DxIjnFQO.js +0 -4
- package/dist/web/_app/immutable/nodes/6.lkh6kKLj.js +0 -1
- package/dist/web/_app/immutable/nodes/7.Bg7SbfhA.js +0 -1
- package/dist/web/_app/immutable/nodes/8.DcXWCNBE.js +0 -1
- package/dist/web/_app/immutable/nodes/9.Cefi8Jfm.js +0 -1
|
@@ -6,7 +6,346 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Single agent instance per server process (single-user v1).
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
import { validateArtifactBundle } from '../../core/artifact-bundle.js';
|
|
10
|
+
import { parseFollowups } from '../../agent/followups.js';
|
|
11
|
+
import * as access from '../../services/access-control.js';
|
|
12
|
+
import { reqGitUser } from './graph-api-access.js';
|
|
13
|
+
import { hashArtifactBody } from '../../agent/tools/artifact-tools.js';
|
|
14
|
+
import { log } from '../../utils/log.js';
|
|
15
|
+
import { addInferenceUsage, createCloudInferenceBillingClient, createInferenceUsageSummary, isStudiographCreditsMode, } from '../../services/cloud-inference-billing.js';
|
|
16
|
+
import { reserveCloudInference, settleCloudInference, releaseCloudInference, } from '../cloud-billing-flow.js';
|
|
17
|
+
import { prepareCreatePayload } from '../../services/entity-mutations.js';
|
|
18
|
+
import { resolveImageRefs, resolveDocContext, isValidAttachmentTurn, composeAttachmentMessageText, attachmentPlaceholder, normalizeAttachmentRef, } from '../../services/scratch-attachment-service.js';
|
|
19
|
+
/**
|
|
20
|
+
* A per-turn "today is …" context line so the agent always knows the current
|
|
21
|
+
* date and stops misfiling entries to the wrong day. Prefers the client's local
|
|
22
|
+
* date (correct timezone) and falls back to the server's UTC date for callers
|
|
23
|
+
* that don't send one. The label is sanitized (single line, length-capped)
|
|
24
|
+
* since it's free text from the request.
|
|
25
|
+
*/
|
|
26
|
+
export function buildDatePrefix(clientDate, clientDateLabel) {
|
|
27
|
+
const iso = clientDate && /^\d{4}-\d{2}-\d{2}$/.test(clientDate)
|
|
28
|
+
? clientDate
|
|
29
|
+
: new Date().toISOString().slice(0, 10);
|
|
30
|
+
const label = clientDateLabel
|
|
31
|
+
? clientDateLabel.replace(/[\r\n]+/g, ' ').trim().slice(0, 64) || iso
|
|
32
|
+
: iso;
|
|
33
|
+
return (`[Today is ${label} (${iso}).]\n\n` +
|
|
34
|
+
`Interpret relative dates ("today", "tomorrow", "yesterday", weekday names) ` +
|
|
35
|
+
`against this. When setting a date field, default to ${iso} (YYYY-MM-DD) ` +
|
|
36
|
+
`unless the user gives another date.\n\n`);
|
|
37
|
+
}
|
|
38
|
+
/** Cap on how many unresolved comments we fold into an entry's chat context.
|
|
39
|
+
* Keeps the prefix bounded on heavily-commented entries; the agent can still
|
|
40
|
+
* call list_entities/get_related for the full set. */
|
|
41
|
+
const MAX_CONTEXT_COMMENTS = 25;
|
|
42
|
+
function slugifyArtifactId(value) {
|
|
43
|
+
const slug = value
|
|
44
|
+
.toLowerCase()
|
|
45
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
46
|
+
.replace(/^-+|-+$/g, '')
|
|
47
|
+
.slice(0, 80);
|
|
48
|
+
return slug || 'artifact';
|
|
49
|
+
}
|
|
50
|
+
function parseEntityContext(context) {
|
|
51
|
+
if (!context || context.startsWith('folder:'))
|
|
52
|
+
return null;
|
|
53
|
+
const [repo, entityType, entityId] = context.split('/');
|
|
54
|
+
if (!repo || !entityType || !entityId)
|
|
55
|
+
return null;
|
|
56
|
+
return { repo, entityType, entityId };
|
|
57
|
+
}
|
|
58
|
+
function parseArtifactSelectionContext(parts) {
|
|
59
|
+
const marker = parts.slice(3).find((part) => part.startsWith('artifact-selection:'));
|
|
60
|
+
if (!marker)
|
|
61
|
+
return null;
|
|
62
|
+
const raw = marker.slice('artifact-selection:'.length);
|
|
63
|
+
try {
|
|
64
|
+
return decodeURIComponent(raw).slice(0, 1600);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return raw.slice(0, 1600);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function repoFromContext(context, user, agent, authService) {
|
|
71
|
+
const workspaceManager = agent.getWorkspaceManager();
|
|
72
|
+
if (context?.startsWith('folder:')) {
|
|
73
|
+
const repo = context.slice('folder:'.length);
|
|
74
|
+
return access.canWriteRepo(user, repo, workspaceManager, authService) ? repo : null;
|
|
75
|
+
}
|
|
76
|
+
const entityContext = parseEntityContext(context);
|
|
77
|
+
if (entityContext && access.canWriteRepo(user, entityContext.repo, workspaceManager, authService)) {
|
|
78
|
+
return entityContext.repo;
|
|
79
|
+
}
|
|
80
|
+
if (user) {
|
|
81
|
+
const personal = workspaceManager.getUserPersonalRepo(user.id);
|
|
82
|
+
if (personal && access.canWriteRepo(user, personal.name, workspaceManager, authService)) {
|
|
83
|
+
return personal.name;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return access.getAccessibleRepos(user, workspaceManager, authService)
|
|
87
|
+
.find((repo) => access.canWriteRepo(user, repo.name, workspaceManager, authService))
|
|
88
|
+
?.name ?? null;
|
|
89
|
+
}
|
|
90
|
+
function resolveArtifactToolTarget(target, user, agent, authService) {
|
|
91
|
+
if (!target?.entityId)
|
|
92
|
+
return null;
|
|
93
|
+
const workspaceManager = agent.getWorkspaceManager();
|
|
94
|
+
if (target.repo) {
|
|
95
|
+
if (!access.canWriteRepo(user, target.repo, workspaceManager, authService)) {
|
|
96
|
+
throw new Error(`No write access to artifact folder: ${target.repo}`);
|
|
97
|
+
}
|
|
98
|
+
const graph = workspaceManager.getGraph(target.repo);
|
|
99
|
+
if (!graph)
|
|
100
|
+
throw new Error(`Folder not found: ${target.repo}`);
|
|
101
|
+
graph.get('artifact', target.entityId);
|
|
102
|
+
return { repo: target.repo, entityId: target.entityId };
|
|
103
|
+
}
|
|
104
|
+
const matches = [];
|
|
105
|
+
for (const repo of access.getAccessibleRepos(user, workspaceManager, authService)) {
|
|
106
|
+
if (!access.canWriteRepo(user, repo.name, workspaceManager, authService))
|
|
107
|
+
continue;
|
|
108
|
+
const graph = workspaceManager.getGraph(repo.name);
|
|
109
|
+
if (!graph)
|
|
110
|
+
continue;
|
|
111
|
+
try {
|
|
112
|
+
graph.get('artifact', target.entityId);
|
|
113
|
+
matches.push({ repo: repo.name, entityId: target.entityId });
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Not in this folder.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (matches.length === 1)
|
|
120
|
+
return matches[0];
|
|
121
|
+
if (matches.length > 1) {
|
|
122
|
+
throw new Error(`Artifact target ${target.entityId} exists in multiple folders. Pass target.repo.`);
|
|
123
|
+
}
|
|
124
|
+
throw new Error(`Artifact target not found: ${target.entityId}`);
|
|
125
|
+
}
|
|
126
|
+
/** True when a bundle's entry document has no real content (the new-entry
|
|
127
|
+
* template ships a blank entrypoint). Mirrors the canvas's empty-artifact check. */
|
|
128
|
+
function bundleEntrypointBlank(bundle) {
|
|
129
|
+
const entry = bundle.files?.[bundle.entrypoint];
|
|
130
|
+
return typeof entry === 'string' && entry.trim().length === 0;
|
|
131
|
+
}
|
|
132
|
+
/** True when a stored artifact body parses to a bundle with a blank entrypoint.
|
|
133
|
+
* Unparseable bodies are treated as non-blank (conservative — the stale guard
|
|
134
|
+
* still applies rather than letting an unread overwrite through). */
|
|
135
|
+
function artifactBodyIsBlank(body) {
|
|
136
|
+
try {
|
|
137
|
+
const parsed = validateArtifactBundle(JSON.parse(body));
|
|
138
|
+
return parsed.ok && !!parsed.bundle && bundleEntrypointBlank(parsed.bundle);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export async function persistArtifactFromChat(params) {
|
|
145
|
+
const { bundle, context, target, user, agent, authService, gitUser, options } = params;
|
|
146
|
+
const validation = validateArtifactBundle(bundle);
|
|
147
|
+
if (!validation.ok || !validation.bundle) {
|
|
148
|
+
throw new Error(`Invalid artifact bundle: ${validation.errors.join('; ')}`);
|
|
149
|
+
}
|
|
150
|
+
const validBundle = validation.bundle;
|
|
151
|
+
const workspaceManager = agent.getWorkspaceManager();
|
|
152
|
+
const body = `${JSON.stringify(validBundle, null, 2)}\n`;
|
|
153
|
+
const entityContext = parseEntityContext(context);
|
|
154
|
+
const actor = gitUser ?? { id: 'agent', name: 'Studiograph Agent', email: 'agent@studiograph.local' };
|
|
155
|
+
const createData = {
|
|
156
|
+
name: validBundle.title,
|
|
157
|
+
kind: validBundle.kind,
|
|
158
|
+
status: 'draft',
|
|
159
|
+
viewport_width: validBundle.viewport.width,
|
|
160
|
+
viewport_height: validBundle.viewport.height,
|
|
161
|
+
viewport_mode: validBundle.viewport.mode,
|
|
162
|
+
};
|
|
163
|
+
const updateData = {
|
|
164
|
+
name: validBundle.title,
|
|
165
|
+
kind: validBundle.kind,
|
|
166
|
+
viewport_width: validBundle.viewport.width,
|
|
167
|
+
viewport_height: validBundle.viewport.height,
|
|
168
|
+
viewport_mode: validBundle.viewport.mode,
|
|
169
|
+
};
|
|
170
|
+
const explicitTarget = resolveArtifactToolTarget(target, user, agent, authService);
|
|
171
|
+
const updateTarget = explicitTarget
|
|
172
|
+
?? (entityContext?.entityType === 'artifact'
|
|
173
|
+
? { repo: entityContext.repo, entityId: entityContext.entityId }
|
|
174
|
+
: null);
|
|
175
|
+
if (updateTarget) {
|
|
176
|
+
if (!access.canWriteRepo(user, updateTarget.repo, workspaceManager, authService)) {
|
|
177
|
+
throw new Error(`No write access to artifact folder: ${updateTarget.repo}`);
|
|
178
|
+
}
|
|
179
|
+
const graph = workspaceManager.getGraph(updateTarget.repo);
|
|
180
|
+
if (!graph)
|
|
181
|
+
throw new Error(`Folder not found: ${updateTarget.repo}`);
|
|
182
|
+
// Stale-write + destructive-shrink guard. Only protects an artifact that
|
|
183
|
+
// already has real content — a fresh/empty canvas (new-entry template) can
|
|
184
|
+
// be filled freely without a prior read. Prefer the live editor body, so
|
|
185
|
+
// the hash matches what read_artifact returned.
|
|
186
|
+
let currentBody = null;
|
|
187
|
+
try {
|
|
188
|
+
const existing = graph.get('artifact', updateTarget.entityId);
|
|
189
|
+
currentBody = graph.getLiveBody('artifact', updateTarget.entityId) ?? existing.document.content;
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
currentBody = null; // artifact doesn't exist yet → nothing to protect
|
|
193
|
+
}
|
|
194
|
+
if (currentBody && !artifactBodyIsBlank(currentBody)) {
|
|
195
|
+
if (!options?.baseHash) {
|
|
196
|
+
throw new Error('This artifact already has content — call read_artifact first and pass its hash as baseHash before updating, so you do not overwrite the current source.');
|
|
197
|
+
}
|
|
198
|
+
if (options.baseHash !== hashArtifactBody(currentBody)) {
|
|
199
|
+
throw new Error('Artifact changed since you read it (baseHash mismatch). Call read_artifact again, re-apply your change to the current source, then retry.');
|
|
200
|
+
}
|
|
201
|
+
if (!options.replace && bundleEntrypointBlank(validBundle)) {
|
|
202
|
+
throw new Error('Refusing to blank a non-empty artifact. Include the full content, or pass replace: true to intentionally clear it.');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
await graph.update({
|
|
206
|
+
entityType: 'artifact',
|
|
207
|
+
entityId: updateTarget.entityId,
|
|
208
|
+
data: updateData,
|
|
209
|
+
content: body,
|
|
210
|
+
commitMessage: `Update artifact/${updateTarget.entityId} from agent`,
|
|
211
|
+
user: actor,
|
|
212
|
+
source: 'server-write',
|
|
213
|
+
});
|
|
214
|
+
return { repo: updateTarget.repo, entityType: 'artifact', entityId: updateTarget.entityId, action: 'updated' };
|
|
215
|
+
}
|
|
216
|
+
const repo = repoFromContext(context, user, agent, authService);
|
|
217
|
+
if (!repo)
|
|
218
|
+
throw new Error('No writable folder is available for the artifact.');
|
|
219
|
+
const graph = workspaceManager.getGraph(repo);
|
|
220
|
+
if (!graph)
|
|
221
|
+
throw new Error(`Folder not found: ${repo}`);
|
|
222
|
+
const baseId = slugifyArtifactId(validBundle.artifactId || validBundle.title);
|
|
223
|
+
let entityId = baseId;
|
|
224
|
+
let foundAvailableId = false;
|
|
225
|
+
for (let i = 2; i < 1000; i++) {
|
|
226
|
+
try {
|
|
227
|
+
graph.get('artifact', entityId);
|
|
228
|
+
entityId = `${baseId}-${i}`;
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
foundAvailableId = true;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (!foundAvailableId) {
|
|
236
|
+
entityId = `${baseId}-${Date.now().toString(36)}`;
|
|
237
|
+
}
|
|
238
|
+
await graph.create(prepareCreatePayload({
|
|
239
|
+
entityType: 'artifact',
|
|
240
|
+
entityId,
|
|
241
|
+
data: createData,
|
|
242
|
+
content: body,
|
|
243
|
+
commitMessage: `Create artifact/${entityId} from agent`,
|
|
244
|
+
}, actor));
|
|
245
|
+
return { repo, entityType: 'artifact', entityId, action: 'created' };
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Render an entry's open (unresolved, non-deleted) comments as a compact,
|
|
249
|
+
* newest-first block so the agent sees user feedback on the entry it's chatting
|
|
250
|
+
* about without having to call a tool. Each line carries the author, the text
|
|
251
|
+
* the comment is pinned to (anchor_quote), and the body. Returns '' when there
|
|
252
|
+
* are no open comments (or no service), so the caller can append unconditionally.
|
|
253
|
+
*/
|
|
254
|
+
export function formatEntryComments(commentService, repo, entryType, entryId) {
|
|
255
|
+
if (!commentService)
|
|
256
|
+
return '';
|
|
257
|
+
let comments;
|
|
258
|
+
try {
|
|
259
|
+
comments = commentService.list({ repo, entryType, entryId, resolved: false });
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return '';
|
|
263
|
+
}
|
|
264
|
+
if (comments.length === 0)
|
|
265
|
+
return '';
|
|
266
|
+
// list() returns oldest-first (ORDER BY thread_id, created_at); show the most
|
|
267
|
+
// recent feedback first and cap the count.
|
|
268
|
+
const ordered = [...comments]
|
|
269
|
+
.sort((a, b) => b.createdAt.localeCompare(a.createdAt))
|
|
270
|
+
.slice(0, MAX_CONTEXT_COMMENTS);
|
|
271
|
+
const lines = ordered.map(c => {
|
|
272
|
+
const anchor = c.anchorQuote ? ` (on "${c.anchorQuote}")` : '';
|
|
273
|
+
const body = c.body.replace(/\s+/g, ' ').trim();
|
|
274
|
+
return `- ${c.authorDisplayName}${anchor}: ${body}`;
|
|
275
|
+
});
|
|
276
|
+
const more = comments.length > ordered.length
|
|
277
|
+
? `\n(${comments.length - ordered.length} more unresolved — use get_related to see all)`
|
|
278
|
+
: '';
|
|
279
|
+
return (`\nUnresolved comments on this entry (newest first) — treat these as user ` +
|
|
280
|
+
`feedback to address:\n${lines.join('\n')}${more}\n`);
|
|
281
|
+
}
|
|
282
|
+
export function buildChatContextPrefix(context, user, agent, authService, commentService) {
|
|
283
|
+
if (!context)
|
|
284
|
+
return '';
|
|
285
|
+
const workspaceManager = agent.getWorkspaceManager();
|
|
286
|
+
if (context.startsWith('folder:')) {
|
|
287
|
+
const repo = context.slice('folder:'.length);
|
|
288
|
+
if (!access.hasRepoAccess(user, repo, workspaceManager, authService))
|
|
289
|
+
return '';
|
|
290
|
+
return `[Currently viewing folder: ${repo}]\n\nScope your help to this folder unless the user asks otherwise. Use list_entities or search_entities with repoNames: ["${repo}"] to explore its contents.\n\n`;
|
|
291
|
+
}
|
|
292
|
+
const parts = context.split('/');
|
|
293
|
+
if (parts.length < 3) {
|
|
294
|
+
return `[Currently viewing: ${context}]\n\n`;
|
|
295
|
+
}
|
|
296
|
+
const [repo, type, id] = parts;
|
|
297
|
+
const selectedArtifactTarget = parseArtifactSelectionContext(parts);
|
|
298
|
+
if (!access.hasRepoAccess(user, repo, workspaceManager, authService))
|
|
299
|
+
return '';
|
|
300
|
+
try {
|
|
301
|
+
const graph = workspaceManager.getGraph(repo);
|
|
302
|
+
if (graph) {
|
|
303
|
+
const entity = graph.get(type, id);
|
|
304
|
+
const fm = entity.data ?? {};
|
|
305
|
+
const entityContent = entity.document?.content ?? '';
|
|
306
|
+
const fmLines = Object.entries(fm)
|
|
307
|
+
.filter(([k]) => !['entity_type', 'entity_id', 'created_at', 'updated_at', 'created_by', 'updated_by'].includes(k))
|
|
308
|
+
.map(([k, v]) => `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)
|
|
309
|
+
.join('\n');
|
|
310
|
+
const commentsBlock = formatEntryComments(commentService, repo, type, id);
|
|
311
|
+
const isArtifact = type === 'artifact';
|
|
312
|
+
// For artifacts, the body IS the full ArtifactBundle JSON (all HTML/CSS/JS
|
|
313
|
+
// inlined). Re-sending it every turn overflows the model on larger
|
|
314
|
+
// artifacts, so inject a compact header instead and have the agent pull
|
|
315
|
+
// the source on demand via read_artifact. Use the live editor body so the
|
|
316
|
+
// hash matches what read_artifact / the write guard see.
|
|
317
|
+
let contentSection;
|
|
318
|
+
if (isArtifact) {
|
|
319
|
+
const liveBody = graph.getLiveBody('artifact', id) ?? entityContent;
|
|
320
|
+
let fileCount = 0;
|
|
321
|
+
try {
|
|
322
|
+
const parsed = JSON.parse(liveBody);
|
|
323
|
+
if (parsed?.files && typeof parsed.files === 'object')
|
|
324
|
+
fileCount = Object.keys(parsed.files).length;
|
|
325
|
+
}
|
|
326
|
+
catch { /* malformed body — header still useful */ }
|
|
327
|
+
contentSection = `Artifact source: ${fileCount} file(s), ${liveBody.length} bytes, hash ${hashArtifactBody(liveBody)}. The full source is omitted here to keep context small — call read_artifact to get the current ArtifactBundle before editing.`;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
contentSection = `Entity content:\n${entityContent}`;
|
|
331
|
+
}
|
|
332
|
+
const artifactInstruction = isArtifact
|
|
333
|
+
? `\nThis entry is an Artifact Canvas. To revise it, call read_artifact to get the current bundle and its hash, modify the full bundle, then call create_artifact with that bundle and the hash as baseHash (the bundle replaces the canvas). To fill an empty canvas from scratch, call create_artifact directly.\n`
|
|
334
|
+
: '';
|
|
335
|
+
const selectionInstruction = selectedArtifactTarget
|
|
336
|
+
? `\nSelected artifact target: ${selectedArtifactTarget}\nIf the user refers to "this", "the selected element", "this slide", or a similar scoped target, treat this selected artifact target as the intended area to modify.\n`
|
|
337
|
+
: '';
|
|
338
|
+
return `[Currently viewing entry: ${repo}/${type}/${id}]\n\nEntity frontmatter:\n${fmLines}\n\n${contentSection}\n${commentsBlock}${artifactInstruction}${selectionInstruction}\nAnswer questions about THIS entity. Use the information above.\n\n`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return `[Currently viewing entry: ${repo}/${type}/${id}]\n\n`;
|
|
343
|
+
}
|
|
344
|
+
return '';
|
|
345
|
+
}
|
|
346
|
+
export async function registerChatRoutes(fastify, agent, wsHub, authService, memoryService, commentService, chatSessionService) {
|
|
347
|
+
const cloudBilling = createCloudInferenceBillingClient();
|
|
348
|
+
const creditsGatewayMode = isStudiographCreditsMode();
|
|
10
349
|
// POST /api/chat — send message, get full response
|
|
11
350
|
fastify.post('/api/chat', async (req, reply) => {
|
|
12
351
|
const { message } = req.body;
|
|
@@ -15,20 +354,76 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
|
|
|
15
354
|
}
|
|
16
355
|
try {
|
|
17
356
|
const user = req.user ?? null;
|
|
18
|
-
const
|
|
19
|
-
|
|
357
|
+
const sessionId = user ? `user:${user.id}:default` : 'default';
|
|
358
|
+
let billingReservation = null;
|
|
359
|
+
try {
|
|
360
|
+
billingReservation = creditsGatewayMode
|
|
361
|
+
? null
|
|
362
|
+
: await reserveCloudInference(cloudBilling, agent, 'Hosted Studiograph chat inference.');
|
|
363
|
+
const response = await agent.chatInSession(sessionId, message, { user, userId: user?.id });
|
|
364
|
+
await settleCloudInference(cloudBilling, billingReservation, response.usage);
|
|
365
|
+
billingReservation = null;
|
|
366
|
+
return reply.send({ content: response.content, toolCalls: response.toolCalls });
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
await releaseCloudInference(cloudBilling, billingReservation, 'Inference request failed before billing settlement.');
|
|
370
|
+
throw err;
|
|
371
|
+
}
|
|
20
372
|
}
|
|
21
373
|
catch (err) {
|
|
22
374
|
fastify.log.error(err, 'Agent chat error');
|
|
23
375
|
return reply.status(500).send({ error: err.message || 'Agent error' });
|
|
24
376
|
}
|
|
25
377
|
});
|
|
26
|
-
// POST /api/chat/
|
|
27
|
-
|
|
28
|
-
|
|
378
|
+
// POST /api/chat/title — name a conversation from its opening exchange.
|
|
379
|
+
// Called by the client after the first assistant reply lands; the returned
|
|
380
|
+
// title replaces the truncated first-message title shown on the launcher.
|
|
381
|
+
// Best-effort: returns { title: null } when titling isn't possible (gateway
|
|
382
|
+
// mode, no key, empty result) so the client just keeps its fallback.
|
|
383
|
+
fastify.post('/api/chat/title', async (req, reply) => {
|
|
384
|
+
const message = req.body?.message;
|
|
385
|
+
const assistantReply = req.body?.reply ?? '';
|
|
29
386
|
if (!message || typeof message !== 'string' || !message.trim()) {
|
|
30
387
|
return reply.status(400).send({ error: 'message is required' });
|
|
31
388
|
}
|
|
389
|
+
try {
|
|
390
|
+
let billingReservation = null;
|
|
391
|
+
try {
|
|
392
|
+
billingReservation = creditsGatewayMode
|
|
393
|
+
? null
|
|
394
|
+
: await reserveCloudInference(cloudBilling, agent, 'Studiograph conversation title.');
|
|
395
|
+
const result = await agent.generateConversationTitle(message, assistantReply);
|
|
396
|
+
await settleCloudInference(cloudBilling, billingReservation, result?.usage);
|
|
397
|
+
billingReservation = null;
|
|
398
|
+
return reply.send({ title: result?.title ?? null });
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
await releaseCloudInference(cloudBilling, billingReservation, 'Title request failed before billing settlement.');
|
|
402
|
+
throw err;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
catch (err) {
|
|
406
|
+
fastify.log.error(err, 'Title generation error');
|
|
407
|
+
// Non-fatal — the client keeps its fallback title.
|
|
408
|
+
return reply.send({ title: null });
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
// POST /api/chat/stream — SSE stream of agent events
|
|
412
|
+
fastify.post('/api/chat/stream', async (req, reply) => {
|
|
413
|
+
const { message, context, sessionId, attachments, images, history, clientDate, clientDateLabel } = req.body;
|
|
414
|
+
// Unify the generic `attachments` field with the legacy `images` field
|
|
415
|
+
// (D10) so old clients keep working. The current turn's refs cover both
|
|
416
|
+
// images (→ vision) and docs (→ injected text).
|
|
417
|
+
const currentRefs = [
|
|
418
|
+
...(Array.isArray(attachments) ? attachments : []),
|
|
419
|
+
...(Array.isArray(images) ? images : []),
|
|
420
|
+
];
|
|
421
|
+
// #5: a turn is valid with text OR at least one attachment (image/doc-only
|
|
422
|
+
// sends are allowed); empty-everything is still rejected.
|
|
423
|
+
if (!isValidAttachmentTurn(message, currentRefs.length)) {
|
|
424
|
+
return reply.status(400).send({ error: 'message or attachments required' });
|
|
425
|
+
}
|
|
426
|
+
const messageText = typeof message === 'string' ? message : '';
|
|
32
427
|
const user = req.user ?? null;
|
|
33
428
|
const resolvedSessionId = sessionId
|
|
34
429
|
? (user ? `user:${user.id}:${sessionId}` : sessionId)
|
|
@@ -54,11 +449,216 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
|
|
|
54
449
|
// Detect client disconnect
|
|
55
450
|
reply.raw.on('close', () => { streamDead = true; });
|
|
56
451
|
reply.raw.on('error', () => { streamDead = true; });
|
|
452
|
+
// Internal-agent identity for activity + entity_change tagging. The web
|
|
453
|
+
// agent runs inside a user session, so the label reads as "<user>'s
|
|
454
|
+
// agent" — distinguishable in the sidebar from external MCP integrations
|
|
455
|
+
// which carry their token name (e.g. "Christian's Cursor").
|
|
456
|
+
const agentLabel = user?.displayName ? `${user.displayName}'s agent` : 'Agent';
|
|
457
|
+
const agentIdentity = {
|
|
458
|
+
kind: 'internal',
|
|
459
|
+
label: agentLabel,
|
|
460
|
+
userId: user?.id != null ? String(user.id) : undefined,
|
|
461
|
+
};
|
|
462
|
+
// Turn-scoped activity tracking. A single chat turn can fan out across
|
|
463
|
+
// multiple folders and intersperse tool calls with LLM "thinking" gaps.
|
|
464
|
+
// We want one continuous chip per touched folder for the whole turn —
|
|
465
|
+
// not a flicker per tool call. So:
|
|
466
|
+
// 1. The first `enter` for a repo broadcasts and adds the repo to a
|
|
467
|
+
// turn-local set; subsequent enters refresh it (server-side
|
|
468
|
+
// throttle drops sub-second repeats).
|
|
469
|
+
// 2. Per-tool `leave` events are suppressed — the chip is "pinned"
|
|
470
|
+
// until the turn ends.
|
|
471
|
+
// 3. A 2s heartbeat keeps the chip alive across multi-second LLM
|
|
472
|
+
// thinking gaps that would otherwise time out the client's
|
|
473
|
+
// MIN_VISIBLE floor.
|
|
474
|
+
// 4. The finally block below fires the actual `leave` for every
|
|
475
|
+
// touched folder when the turn completes (success, error, or
|
|
476
|
+
// client disconnect).
|
|
477
|
+
const activeRepos = new Set();
|
|
478
|
+
let activityHeartbeat = null;
|
|
479
|
+
function ensureActivityHeartbeat() {
|
|
480
|
+
if (activityHeartbeat)
|
|
481
|
+
return;
|
|
482
|
+
activityHeartbeat = setInterval(() => {
|
|
483
|
+
for (const repo of activeRepos) {
|
|
484
|
+
wsHub.handleAgentActivity('heartbeat', repo, agentIdentity);
|
|
485
|
+
}
|
|
486
|
+
}, 2_000);
|
|
487
|
+
}
|
|
488
|
+
function stopActivityHeartbeat() {
|
|
489
|
+
if (activityHeartbeat) {
|
|
490
|
+
clearInterval(activityHeartbeat);
|
|
491
|
+
activityHeartbeat = null;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
let billingReservation = null;
|
|
57
495
|
try {
|
|
496
|
+
billingReservation = creditsGatewayMode
|
|
497
|
+
? null
|
|
498
|
+
: await reserveCloudInference(cloudBilling, agent, 'Hosted Studiograph streaming chat inference.');
|
|
499
|
+
let artifactCount = 0;
|
|
500
|
+
const gitUser = reqGitUser(req);
|
|
501
|
+
const entityContext = parseEntityContext(context);
|
|
502
|
+
const currentArtifactTarget = entityContext?.entityType === 'artifact'
|
|
503
|
+
? { repo: entityContext.repo, entityId: entityContext.entityId }
|
|
504
|
+
: null;
|
|
505
|
+
// Resolve composer attachments. The client sends durable REFS, never
|
|
506
|
+
// bytes; we resolve from the asset/scratch ROW (A1) and re-authorize
|
|
507
|
+
// every call. Two transports, by type:
|
|
508
|
+
// - images → vision blocks (current turn only — prior images are held by
|
|
509
|
+
// the warm agent-pool, or re-attached on demand by the user, D7).
|
|
510
|
+
// - docs → injected TEXT, replayed EVERY turn from the session's prior
|
|
511
|
+
// user messages + the current turn (D7), so they survive reload and
|
|
512
|
+
// stay in context late in long chats. Doc text is already extracted +
|
|
513
|
+
// stored, so replay is just a row read (no re-parse).
|
|
514
|
+
// Denied/deleted/over-cap refs degrade to `[file: name]` notes, not errors.
|
|
515
|
+
let imageBlocks = [];
|
|
516
|
+
let imagePlaceholders = [];
|
|
517
|
+
let docContext = '';
|
|
518
|
+
let docPlaceholders = [];
|
|
519
|
+
// Doc refs replayed from history (prior user messages) — re-authorized in
|
|
520
|
+
// the resolver, so a revoked/deleted file silently drops.
|
|
521
|
+
const historyRefs = (user && sessionId && chatSessionService)
|
|
522
|
+
? chatSessionService.getSessionAttachmentRefs(user.id, sessionId)
|
|
523
|
+
.map(normalizeAttachmentRef)
|
|
524
|
+
.filter((r) => r !== null)
|
|
525
|
+
: [];
|
|
526
|
+
if (currentRefs.length > 0 || historyRefs.length > 0) {
|
|
527
|
+
const attWsm = agent.getWorkspaceManager();
|
|
528
|
+
const attIndex = attWsm.getAssetIndex?.();
|
|
529
|
+
// The scratch blob store is workspace-global — reach it via any graph.
|
|
530
|
+
const scratchGraph = (() => {
|
|
531
|
+
for (const cfg of attWsm.getAllRepoConfigs()) {
|
|
532
|
+
try {
|
|
533
|
+
const g = attWsm.getGraph(cfg.name);
|
|
534
|
+
if (g.getAssetService?.())
|
|
535
|
+
return g;
|
|
536
|
+
}
|
|
537
|
+
catch { /* next */ }
|
|
538
|
+
}
|
|
539
|
+
return null;
|
|
540
|
+
})();
|
|
541
|
+
const deps = {
|
|
542
|
+
getAssetRow: (id) => attIndex?.get(id) ?? null,
|
|
543
|
+
canAccessRepo: (repo) => access.hasRepoAccess(user ?? undefined, repo, attWsm, authService),
|
|
544
|
+
downloadAsset: (repo, id, filename) => attWsm.getGraph(repo).downloadAssetById(id, filename),
|
|
545
|
+
getScratchRow: (sid, fid) => chatSessionService?.getScratchFile(sid, fid) ?? null,
|
|
546
|
+
downloadScratch: (blobKey) => {
|
|
547
|
+
const svc = scratchGraph?.getAssetService?.();
|
|
548
|
+
if (!svc)
|
|
549
|
+
throw new Error('scratch backend unavailable');
|
|
550
|
+
return svc.download(blobKey);
|
|
551
|
+
},
|
|
552
|
+
currentUserId: user?.id,
|
|
553
|
+
};
|
|
554
|
+
// Images — current turn only. Gated on vision: a text-only model can't
|
|
555
|
+
// see pixels, so degrade every image ref to a text note.
|
|
556
|
+
if (currentRefs.length > 0) {
|
|
557
|
+
if (agent.supportsVision()) {
|
|
558
|
+
({ blocks: imageBlocks, placeholders: imagePlaceholders } = await resolveImageRefs(currentRefs, deps));
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
// Only IMAGE refs are "can't show" here — docs still go in as text
|
|
562
|
+
// via docContext below, so they must not also get a dropped note.
|
|
563
|
+
// Library `asset` refs are always images; a `scratch` ref's kind
|
|
564
|
+
// lives on its row, so look it up (cheap, rare text-only path).
|
|
565
|
+
imagePlaceholders = currentRefs
|
|
566
|
+
.filter((r) => r.kind === 'asset' || deps.getScratchRow(r.sessionId, r.fileId)?.kind === 'image')
|
|
567
|
+
.map((r) => attachmentPlaceholder(r.filename));
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
// Docs — current turn FIRST so a freshly-attached doc wins the file/char
|
|
571
|
+
// budget over older replayed history; deduped in the resolver. Not
|
|
572
|
+
// vision-gated (text works on any model). Synchronous (stored text).
|
|
573
|
+
({ docContext, placeholders: docPlaceholders } = resolveDocContext([...currentRefs, ...historyRefs], deps));
|
|
574
|
+
}
|
|
575
|
+
const attachmentPlaceholders = [...imagePlaceholders, ...docPlaceholders];
|
|
58
576
|
const response = await agent.getPool().withAgent(resolvedSessionId, {
|
|
59
577
|
user,
|
|
578
|
+
// Raw client session id (what scratch images are keyed by) so
|
|
579
|
+
// session-scoped tools target THIS conversation, not other chats.
|
|
580
|
+
clientSessionId: sessionId,
|
|
581
|
+
currentArtifactTarget,
|
|
60
582
|
onHighlight: (ids) => sendEvent({ type: 'highlight', entityIds: ids }),
|
|
61
|
-
|
|
583
|
+
onArtifact: async (bundle, target, writeOptions) => {
|
|
584
|
+
const location = await persistArtifactFromChat({
|
|
585
|
+
bundle,
|
|
586
|
+
context,
|
|
587
|
+
target,
|
|
588
|
+
user,
|
|
589
|
+
agent,
|
|
590
|
+
authService,
|
|
591
|
+
gitUser,
|
|
592
|
+
options: writeOptions,
|
|
593
|
+
});
|
|
594
|
+
artifactCount++;
|
|
595
|
+
sendEvent({ type: 'artifact', artifact: bundle, ...location });
|
|
596
|
+
sendEvent({
|
|
597
|
+
type: 'mutation',
|
|
598
|
+
action: location.action,
|
|
599
|
+
repo: location.repo,
|
|
600
|
+
entityType: location.entityType,
|
|
601
|
+
entityId: location.entityId,
|
|
602
|
+
});
|
|
603
|
+
wsHub.broadcast({
|
|
604
|
+
type: 'entity_change',
|
|
605
|
+
action: location.action,
|
|
606
|
+
repo: location.repo,
|
|
607
|
+
entityType: location.entityType,
|
|
608
|
+
entityId: location.entityId,
|
|
609
|
+
actor: user?.displayName ?? 'Agent',
|
|
610
|
+
source: 'api',
|
|
611
|
+
agent: agentIdentity,
|
|
612
|
+
timestamp: new Date().toISOString(),
|
|
613
|
+
});
|
|
614
|
+
return location;
|
|
615
|
+
},
|
|
616
|
+
onMutation: (m) => {
|
|
617
|
+
// Stream the event to the requesting user's chat (existing behavior).
|
|
618
|
+
sendEvent({ type: 'mutation', action: m.action, repo: m.repo, entityType: m.entityType, entityId: m.entityId });
|
|
619
|
+
// Broadcast to all connected workspace clients so OTHER users
|
|
620
|
+
// see live updates from this user's agent. Without this, the
|
|
621
|
+
// web agent's mutations are invisible to peers until they
|
|
622
|
+
// reload — MCP mutations already broadcast via src/mcp/tools.ts.
|
|
623
|
+
wsHub.broadcast({
|
|
624
|
+
type: 'entity_change',
|
|
625
|
+
action: m.action,
|
|
626
|
+
repo: m.repo,
|
|
627
|
+
entityType: m.entityType,
|
|
628
|
+
entityId: m.entityId,
|
|
629
|
+
actor: user?.displayName ?? 'Agent',
|
|
630
|
+
source: 'api',
|
|
631
|
+
agent: agentIdentity,
|
|
632
|
+
timestamp: new Date().toISOString(),
|
|
633
|
+
});
|
|
634
|
+
// Asset-only change (e.g. saving a chat image to the library):
|
|
635
|
+
// also emit repo_sync so asset views refresh — they don't track
|
|
636
|
+
// entity_change (free-standing assets aren't entities).
|
|
637
|
+
if (m.repoSync) {
|
|
638
|
+
wsHub.broadcast({
|
|
639
|
+
type: 'repo_sync',
|
|
640
|
+
repo: m.repo,
|
|
641
|
+
actor: user?.displayName ?? 'Agent',
|
|
642
|
+
source: 'api',
|
|
643
|
+
agent: agentIdentity,
|
|
644
|
+
timestamp: new Date().toISOString(),
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
onAgentActivity: (action, repo) => {
|
|
649
|
+
if (action === 'enter') {
|
|
650
|
+
activeRepos.add(repo);
|
|
651
|
+
wsHub.handleAgentActivity('enter', repo, agentIdentity);
|
|
652
|
+
ensureActivityHeartbeat();
|
|
653
|
+
}
|
|
654
|
+
// Per-tool `leave` is intentionally suppressed — the finally
|
|
655
|
+
// block at turn end fires a single `leave` per repo. `heartbeat`
|
|
656
|
+
// doesn't currently fire from tool wrappers, but if it did,
|
|
657
|
+
// pass through.
|
|
658
|
+
if (action === 'heartbeat' && activeRepos.has(repo)) {
|
|
659
|
+
wsHub.handleAgentActivity('heartbeat', repo, agentIdentity);
|
|
660
|
+
}
|
|
661
|
+
},
|
|
62
662
|
}, async (rawAgent) => {
|
|
63
663
|
// Subscribe to agent events for streaming
|
|
64
664
|
let hasContent = false;
|
|
@@ -86,82 +686,127 @@ export async function registerChatRoutes(fastify, agent, memoryService) {
|
|
|
86
686
|
}
|
|
87
687
|
}
|
|
88
688
|
});
|
|
89
|
-
// Build context
|
|
90
|
-
|
|
91
|
-
if (context) {
|
|
92
|
-
const parts = context.split('/');
|
|
93
|
-
if (parts.length >= 3) {
|
|
94
|
-
const [repo, type, id] = parts;
|
|
95
|
-
try {
|
|
96
|
-
const graph = agent.getWorkspaceManager().getGraph(repo);
|
|
97
|
-
if (graph) {
|
|
98
|
-
const entity = graph.get(type, id);
|
|
99
|
-
const fm = entity.data ?? {};
|
|
100
|
-
const entityContent = entity.document?.content ?? '';
|
|
101
|
-
const fmLines = Object.entries(fm)
|
|
102
|
-
.filter(([k]) => !['entity_type', 'entity_id', 'created_at', 'updated_at', 'created_by', 'updated_by'].includes(k))
|
|
103
|
-
.map(([k, v]) => `${k}: ${typeof v === 'object' ? JSON.stringify(v) : v}`)
|
|
104
|
-
.join('\n');
|
|
105
|
-
contextPrefix = `[Currently viewing: ${context}]\n\nEntity frontmatter:\n${fmLines}\n\nEntity content:\n${entityContent}\n\nAnswer questions about THIS entity. Use the information above.\n\n`;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
contextPrefix = `[Currently viewing: ${context}]\n\n`;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
contextPrefix = `[Currently viewing: ${context}]\n\n`;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
689
|
+
// Build scope-aware context prefix only after folder access passes.
|
|
690
|
+
const contextPrefix = buildChatContextPrefix(context, user ?? undefined, agent, authService, commentService);
|
|
116
691
|
const userPrefix = user ? `[Current user: ${user.displayName} (${user.email}, ${user.role})]\n\n` : '';
|
|
117
|
-
const
|
|
692
|
+
const datePrefix = buildDatePrefix(clientDate, clientDateLabel);
|
|
693
|
+
// #5: image/doc-only send → a minimal prompt so the agent looks at
|
|
694
|
+
// the attachment. Dropped-file notes (placeholders) ride along as text.
|
|
695
|
+
const hasAttachmentContent = imageBlocks.length > 0 || docContext.length > 0;
|
|
696
|
+
const userText = composeAttachmentMessageText(messageText, hasAttachmentContent, attachmentPlaceholders);
|
|
697
|
+
// Doc context (D12-wrapped, capped) goes BEFORE the user's text so the
|
|
698
|
+
// question can reference "the attached file"; the wrapper marks it as
|
|
699
|
+
// data, not instructions.
|
|
700
|
+
const docBlock = docContext ? `${docContext}\n\n` : '';
|
|
701
|
+
const fullMessage = userPrefix + datePrefix + contextPrefix + docBlock + userText;
|
|
118
702
|
// Send message and await response
|
|
119
703
|
const result = await new Promise((resolve, reject) => {
|
|
120
704
|
let content = '';
|
|
705
|
+
let assistantMessageCount = 0;
|
|
706
|
+
let toolCallCount = 0;
|
|
707
|
+
const blockTypeCounts = {};
|
|
708
|
+
let lastStopReason;
|
|
709
|
+
let lastErrorMessage;
|
|
710
|
+
const usage = createInferenceUsageSummary();
|
|
121
711
|
const endSub = rawAgent.subscribe((event) => {
|
|
122
712
|
if (event.type === 'message_end' && event.message?.role === 'assistant') {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
713
|
+
addInferenceUsage(usage, event.message.usage);
|
|
714
|
+
assistantMessageCount++;
|
|
715
|
+
const blocks = event.message.content ?? [];
|
|
716
|
+
for (const b of blocks) {
|
|
717
|
+
blockTypeCounts[b.type] = (blockTypeCounts[b.type] ?? 0) + 1;
|
|
718
|
+
}
|
|
719
|
+
const textBlocks = blocks.filter((b) => b.type === 'text');
|
|
720
|
+
const toolBlocks = blocks.filter((b) => b.type === 'toolCall');
|
|
721
|
+
toolCallCount += toolBlocks.length;
|
|
722
|
+
if (event.message.stopReason)
|
|
723
|
+
lastStopReason = event.message.stopReason;
|
|
724
|
+
if (event.message.errorMessage)
|
|
725
|
+
lastErrorMessage = event.message.errorMessage;
|
|
726
|
+
// Keep the LAST non-empty text seen, so a follow-up assistant
|
|
727
|
+
// turn that has only tool calls doesn't wipe out the text that
|
|
728
|
+
// was produced earlier in the same prompt run.
|
|
729
|
+
const turnText = textBlocks.map((b) => b.text).join('');
|
|
730
|
+
if (turnText.length > 0)
|
|
731
|
+
content = turnText;
|
|
127
732
|
}
|
|
128
733
|
else if (event.type === 'agent_end') {
|
|
129
734
|
endSub();
|
|
130
|
-
|
|
735
|
+
if (!content) {
|
|
736
|
+
log.warn(`[chat/stream] agent produced no text ` +
|
|
737
|
+
`(assistantMessages=${assistantMessageCount}, toolCalls=${toolCallCount}, ` +
|
|
738
|
+
`blockTypes=${JSON.stringify(blockTypeCounts)}, ` +
|
|
739
|
+
`stopReason=${lastStopReason ?? 'n/a'}, ` +
|
|
740
|
+
`errorMessage=${JSON.stringify(lastErrorMessage ?? null)}, ` +
|
|
741
|
+
`sessionId=${resolvedSessionId}) prompt="${messageText.slice(0, 80)}"`);
|
|
742
|
+
}
|
|
743
|
+
resolve({ content, usage });
|
|
131
744
|
}
|
|
132
745
|
});
|
|
133
|
-
rawAgent.prompt(fullMessage
|
|
746
|
+
rawAgent.prompt(fullMessage, imageBlocks.length ? imageBlocks : undefined)
|
|
747
|
+
.catch((err) => { endSub(); reject(err); });
|
|
134
748
|
});
|
|
135
749
|
unsubscribe();
|
|
136
750
|
return result;
|
|
137
751
|
}, { userId: user?.id, fallbackHistory: history });
|
|
752
|
+
await settleCloudInference(cloudBilling, billingReservation, response.usage);
|
|
753
|
+
billingReservation = null;
|
|
138
754
|
// Write brief entry to today's daily memory
|
|
139
755
|
if (memoryService && response.content) {
|
|
140
756
|
try {
|
|
141
|
-
const snippet = `User: ${
|
|
757
|
+
const snippet = `User: ${messageText.slice(0, 100)}${messageText.length > 100 ? '…' : ''}\nAgent: ${response.content.slice(0, 200)}${response.content.length > 200 ? '…' : ''}`;
|
|
142
758
|
memoryService.saveSessionSummary(snippet, { source: 'web-chat', sessionId }, user?.id);
|
|
143
759
|
}
|
|
144
760
|
catch { /* non-fatal */ }
|
|
145
761
|
}
|
|
146
|
-
// Parse follow-up suggestions from response
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
762
|
+
// Parse follow-up suggestions from response (shared with CLI transport)
|
|
763
|
+
const { content: parsedContent, suggestions } = parseFollowups(response.content);
|
|
764
|
+
let cleanContent = parsedContent;
|
|
765
|
+
// If the agent finished with no text AND no tool call, surface that
|
|
766
|
+
// explicitly so the UI doesn't look frozen. Users reported "silent
|
|
767
|
+
// failures" that were actually legitimately-empty assistant turns.
|
|
768
|
+
// The `fallback: true` flag lets the client decide what to do \u2014
|
|
769
|
+
// typed prompts render the message, system-initiated silent prompts
|
|
770
|
+
// (auto-greet) drop the placeholder so users don't see a confusing
|
|
771
|
+
// "Could you try rephrasing?" they didn't trigger.
|
|
772
|
+
let fallback = false;
|
|
773
|
+
if (!cleanContent.trim() && artifactCount === 0 && !streamDead) {
|
|
774
|
+
cleanContent = '_I didn\u2019t have a response for that. Could you try rephrasing?_';
|
|
775
|
+
fallback = true;
|
|
157
776
|
}
|
|
158
|
-
sendEvent({ type: 'done', message: cleanContent, suggestions });
|
|
777
|
+
sendEvent({ type: 'done', message: cleanContent, suggestions, fallback });
|
|
159
778
|
}
|
|
160
779
|
catch (err) {
|
|
780
|
+
await releaseCloudInference(cloudBilling, billingReservation, 'Inference request failed before billing settlement.');
|
|
781
|
+
// Log to stderr so silent agent failures show up in server logs —
|
|
782
|
+
// the SSE error event goes to the client but was invisible to ops.
|
|
783
|
+
log.error('[chat/stream] agent error:', err?.stack || err?.message || err);
|
|
161
784
|
sendEvent({ type: 'error', message: err.message || 'Agent error' });
|
|
162
785
|
}
|
|
786
|
+
finally {
|
|
787
|
+
// End-of-turn agent activity cleanup. Fires for every folder the
|
|
788
|
+
// agent touched during this turn — including paths through the
|
|
789
|
+
// catch branch above, so a crashed/aborted turn still releases
|
|
790
|
+
// its chips instead of relying on the 90s server TTL.
|
|
791
|
+
stopActivityHeartbeat();
|
|
792
|
+
for (const repo of activeRepos) {
|
|
793
|
+
wsHub.handleAgentActivity('leave', repo, agentIdentity);
|
|
794
|
+
}
|
|
795
|
+
activeRepos.clear();
|
|
796
|
+
}
|
|
163
797
|
reply.raw.end();
|
|
164
798
|
});
|
|
799
|
+
// GET /api/chat/capabilities — composer feature gating (vision attach).
|
|
800
|
+
fastify.get('/api/chat/capabilities', async (_req, reply) => {
|
|
801
|
+
try {
|
|
802
|
+
return { vision: agent.supportsVision() };
|
|
803
|
+
}
|
|
804
|
+
catch {
|
|
805
|
+
// Conservative default — hide/disable the affordance rather than offer a
|
|
806
|
+
// vision attach the model can't honor.
|
|
807
|
+
return reply.send({ vision: false });
|
|
808
|
+
}
|
|
809
|
+
});
|
|
165
810
|
// POST /api/chat/abort — abort the current agent run
|
|
166
811
|
fastify.post('/api/chat/abort', async (_req, reply) => {
|
|
167
812
|
try {
|