@vellumai/assistant 0.8.1 → 0.8.3
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/ARCHITECTURE.md +13 -19
- package/Dockerfile +75 -1
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +17 -0
- package/docker-init-apt-root.sh +167 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- package/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +642 -5
- package/package.json +3 -1
- package/scripts/generate-openapi.ts +83 -10
- package/scripts/sync-llm-catalog.ts +2 -2
- package/scripts/sync-web-search-catalog.ts +47 -25
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-loop-exit-reason.test.ts +272 -0
- package/src/__tests__/agent-loop-provider-error-recording.test.ts +195 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +45 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/channel-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/compactor-tail-resolution.test.ts +147 -0
- package/src/__tests__/config-get-vision-flag.test.ts +136 -0
- package/src/__tests__/config-loader-backfill.test.ts +115 -18
- package/src/__tests__/config-schema.test.ts +21 -0
- package/src/__tests__/config-set-route.test.ts +80 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
- package/src/__tests__/context-search-conversations-source.test.ts +117 -2
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +31 -65
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +92 -92
- package/src/__tests__/conversation-agent-loop.test.ts +59 -1
- package/src/__tests__/conversation-error.test.ts +42 -3
- package/src/__tests__/conversation-fork-crud.test.ts +82 -0
- package/src/__tests__/conversation-inference-profile-route.test.ts +40 -4
- package/src/__tests__/conversation-lifecycle.test.ts +173 -0
- package/src/__tests__/conversation-media-retry.test.ts +19 -8
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-callsite.test.ts +4 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +102 -13
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +3 -2
- package/src/__tests__/date-context.test.ts +45 -0
- package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +151 -55
- package/src/__tests__/filing-service.test.ts +140 -0
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/guardian-action-no-hardcoded-copy.test.ts +0 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +43 -62
- package/src/__tests__/heartbeat-service.test.ts +24 -164
- package/src/__tests__/helpers/channel-test-adapter.ts +0 -2
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +73 -0
- package/src/__tests__/host-app-control-proxy.test.ts +507 -10
- package/src/__tests__/host-proxy-preactivation.test.ts +200 -13
- package/src/__tests__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +1 -1
- package/src/__tests__/inference-profile-reaper.test.ts +4 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +18 -6
- package/src/__tests__/inference-profile-session-ipc.test.ts +17 -5
- package/src/__tests__/injector-background-turn.test.ts +153 -0
- package/src/__tests__/injector-chain.test.ts +15 -8
- package/src/__tests__/install-skill-routing.test.ts +155 -37
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +99 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +25 -0
- package/src/__tests__/llm-catalog-parity.test.ts +58 -13
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +116 -0
- package/src/__tests__/llm-request-log-error-payload.test.ts +138 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +36 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +29 -53
- package/src/__tests__/llm-resolver.test.ts +255 -2
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +41 -29
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/notification-decision-fallback.test.ts +0 -91
- package/src/__tests__/notification-decision-strategy.test.ts +14 -31
- package/src/__tests__/notification-deep-link.test.ts +15 -0
- package/src/__tests__/notification-guardian-path.test.ts +1 -2
- package/src/__tests__/notification-platform-adapter.test.ts +5 -4
- package/src/__tests__/notification-telegram-adapter.test.ts +1 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +113 -0
- package/src/__tests__/oauth-commands-routes.test.ts +168 -16
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/openai-provider.test.ts +242 -3
- package/src/__tests__/openai-responses-cutover-guard.test.ts +17 -9
- package/src/__tests__/openrouter-provider-only.test.ts +51 -3
- package/src/__tests__/openrouter-token-estimation.test.ts +34 -25
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +7 -2
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +10 -36
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +0 -1
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +16 -15
- package/src/__tests__/plugin-types.test.ts +3 -13
- package/src/__tests__/process-message-background-slack.test.ts +8 -1
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +158 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +33 -31
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-routes.test.ts +50 -3
- package/src/__tests__/schedule-store.test.ts +94 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +54 -7
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +1 -1
- package/src/__tests__/server-history-render.test.ts +43 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -12
- package/src/__tests__/skill-load-tool.test.ts +27 -89
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/system-prompt.test.ts +670 -63
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -0
- package/src/__tests__/user-plugin-loader.test.ts +0 -7
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +32 -10
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +115 -3
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +50 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
- package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-087-memory-router-balanced-profile.test.ts +228 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/a2a/__tests__/agent-card.test.ts +98 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +597 -0
- package/src/a2a/__tests__/protocol-helpers.test.ts +113 -0
- package/src/a2a/__tests__/task-store.test.ts +246 -0
- package/src/a2a/agent-card.ts +58 -0
- package/src/a2a/feature-gate.ts +8 -0
- package/src/a2a/protocol-constants.ts +21 -0
- package/src/a2a/protocol-errors.ts +50 -0
- package/src/a2a/protocol-types.ts +162 -0
- package/src/a2a/task-store.ts +168 -0
- package/src/acp/resolve-agent.ts +1 -1
- package/src/agent/image-optimize.ts +13 -5
- package/src/agent/loop.ts +167 -18
- package/src/calls/voice-session-bridge.ts +61 -42
- package/src/channels/config.ts +9 -0
- package/src/channels/types.ts +122 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/changelog.test.ts +304 -319
- package/src/cli/{__tests__ → commands/__tests__}/notifications.test.ts +201 -28
- package/src/cli/commands/__tests__/schedules.test.ts +960 -0
- package/src/cli/commands/changelog.ts +106 -42
- package/src/cli/commands/conversations.ts +102 -17
- package/src/cli/commands/default-action.ts +10 -53
- package/src/cli/commands/notifications.ts +388 -346
- package/src/cli/commands/plugins.ts +252 -0
- package/src/cli/commands/schedules.ts +683 -0
- package/src/cli/commands/telemetry.ts +40 -0
- package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +261 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/install-from-github.ts +303 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/search-plugins.ts +163 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +52 -2
- package/src/config/assistant-feature-flags.ts +24 -54
- package/src/config/bundled-skills/app-builder/SKILL.md +140 -22
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- package/src/config/bundled-skills/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- package/src/config/bundled-skills/phone-calls/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -0
- package/src/config/call-site-defaults.ts +105 -0
- package/src/config/feature-flag-registry.json +41 -9
- package/src/config/llm-resolver.ts +52 -1
- package/src/config/loader.ts +64 -38
- package/src/config/schema.ts +9 -10
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +3 -3
- package/src/config/schemas/channels.ts +17 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/conversations.ts +10 -0
- package/src/config/schemas/heartbeat.ts +23 -0
- package/src/config/schemas/llm-request-logs.ts +31 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/memory-retrospective.ts +1 -1
- package/src/config/schemas/memory-v2.ts +4 -4
- package/src/config/schemas/memory.ts +3 -1
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/seed-inference-profiles.ts +99 -29
- package/src/config/skills.ts +3 -96
- package/src/context/compactor.ts +1107 -0
- package/src/context/token-estimator.ts +34 -36
- package/src/context/window-manager.ts +197 -1520
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +33 -18
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +74 -0
- package/src/daemon/approval-generators.ts +8 -6
- package/src/daemon/config-watcher.ts +94 -31
- package/src/daemon/conversation-agent-loop-handlers.ts +78 -0
- package/src/daemon/conversation-agent-loop.ts +198 -11
- package/src/daemon/conversation-error.ts +171 -37
- package/src/daemon/conversation-lifecycle.ts +53 -40
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +49 -12
- package/src/daemon/conversation-runtime-assembly.ts +25 -1
- package/src/daemon/conversation-slash.ts +12 -5
- package/src/daemon/conversation-store.ts +11 -4
- package/src/daemon/conversation-tool-setup.ts +39 -7
- package/src/daemon/conversation.ts +33 -8
- package/src/daemon/date-context.ts +40 -0
- package/src/daemon/external-plugins-bootstrap.ts +217 -181
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/guardian-action-generators.ts +1 -125
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +248 -0
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +154 -0
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +133 -0
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +95 -0
- package/src/daemon/handlers/config-a2a.ts +289 -0
- package/src/daemon/handlers/config-model.ts +6 -5
- package/src/daemon/handlers/config-slack-channel.ts +15 -3
- package/src/daemon/handlers/conversations.ts +1 -0
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +111 -108
- package/src/daemon/history-repair.ts +28 -1
- package/src/daemon/host-app-control-proxy.ts +153 -27
- package/src/daemon/host-proxy-preactivation.ts +85 -18
- package/src/daemon/lifecycle.ts +89 -91
- package/src/daemon/meet-host-supervisor.ts +5 -4
- package/src/daemon/memory-v2-startup.ts +85 -0
- package/src/daemon/message-protocol.ts +1 -0
- package/src/daemon/message-types/conversations.ts +25 -0
- package/src/daemon/message-types/messages.ts +61 -0
- package/src/daemon/message-types/notifications.ts +21 -0
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/pkb-reminder-builder.test.ts +11 -54
- package/src/daemon/pkb-reminder-builder.ts +5 -20
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +24 -3
- package/src/daemon/server.ts +11 -2
- package/src/daemon/skill-memory-refresh.ts +33 -0
- package/src/daemon/wake-target-adapter.ts +2 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/export/__tests__/transcript-formatter.test.ts +121 -0
- package/src/export/transcript-formatter.ts +54 -20
- package/src/filing/filing-service.ts +39 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +135 -6
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +73 -189
- package/src/home/__tests__/feed-types.test.ts +80 -0
- package/src/home/feed-types.ts +36 -2
- package/src/home/post-connect-feed.ts +1 -0
- package/src/index.ts +18 -1
- package/src/ipc/cli-client.ts +147 -45
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
- package/src/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +33 -27
- package/src/memory/__tests__/conversation-queries.test.ts +483 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +2 -50
- package/src/memory/__tests__/memory-retrospective-job.test.ts +87 -4
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +119 -14
- package/src/memory/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +42 -10
- package/src/memory/context-search/sources/conversations.ts +62 -2
- package/src/memory/context-search/sources/workspace.ts +4 -0
- package/src/memory/conversation-crud.ts +63 -19
- package/src/memory/conversation-queries.ts +197 -11
- package/src/memory/conversation-title-service.ts +26 -4
- package/src/memory/db-init.ts +12 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +4 -4
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +150 -12
- package/src/memory/graph/conversation-graph-memory.ts +49 -21
- package/src/memory/graph/tools.ts +9 -40
- package/src/memory/indexer.ts +34 -29
- package/src/memory/invite-store.ts +53 -0
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +73 -0
- package/src/memory/jobs/embed-concept-page.ts +20 -11
- package/src/memory/jobs-worker.ts +6 -1
- package/src/memory/llm-request-log-source-clickhouse.ts +24 -12
- package/src/memory/llm-request-log-source.ts +19 -52
- package/src/memory/llm-request-log-store.ts +92 -1
- package/src/memory/llm-usage-store.ts +125 -5
- package/src/memory/memory-retrospective-enqueue.ts +1 -20
- package/src/memory/memory-retrospective-job.ts +33 -6
- package/src/memory/memory-retrospective-startup-cleanup.ts +72 -5
- package/src/memory/message-content.ts +1 -1
- package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
- package/src/memory/migrations/229-delete-private-conversations.test.ts +38 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +7 -0
- package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
- package/src/memory/migrations/250-provider-connection-base-url-and-models.ts +28 -0
- package/src/memory/migrations/251-a2a-tasks.ts +49 -0
- package/src/memory/migrations/252-llm-request-log-agent-loop-exit-reason.ts +32 -0
- package/src/memory/migrations/index.ts +9 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/schema/a2a.ts +15 -0
- package/src/memory/schema/bookmarks.ts +0 -2
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/inference.ts +3 -3
- package/src/memory/schema/infrastructure.ts +13 -0
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/activation-store.test.ts +25 -23
- package/src/memory/v2/__tests__/activation.test.ts +0 -8
- package/src/memory/v2/__tests__/cli-command-store.test.ts +404 -0
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +25 -4
- package/src/memory/v2/__tests__/injection.test.ts +288 -11
- package/src/memory/v2/__tests__/migration.test.ts +87 -0
- package/src/memory/v2/__tests__/page-index.test.ts +83 -0
- package/src/memory/v2/__tests__/prompts-router.test.ts +58 -6
- package/src/memory/v2/__tests__/qdrant.test.ts +66 -3
- package/src/memory/v2/__tests__/router.test.ts +15 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +387 -8
- package/src/memory/v2/__tests__/static-context.test.ts +12 -1
- package/src/memory/v2/activation-store.ts +14 -16
- package/src/memory/v2/cli-command-content.ts +19 -0
- package/src/memory/v2/cli-command-store.ts +304 -0
- package/src/memory/v2/frontmatter-sweep.ts +7 -1
- package/src/memory/v2/injection.ts +81 -26
- package/src/memory/v2/migration.ts +49 -19
- package/src/memory/v2/page-index.ts +63 -8
- package/src/memory/v2/prompts/router.ts +11 -8
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +135 -7
- package/src/memory/v2/router.ts +9 -8
- package/src/memory/v2/skill-store.ts +120 -35
- package/src/memory/v2/static-context.ts +4 -4
- package/src/memory/v2/types.ts +23 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +274 -0
- package/src/messaging/providers/a2a/deliver.ts +156 -0
- package/src/messaging/providers/gmail/client.ts +9 -2
- package/src/messaging/providers/index.ts +11 -2
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- package/src/notifications/__tests__/broadcaster.test.ts +203 -0
- package/src/notifications/__tests__/decision-engine.test.ts +283 -0
- package/src/notifications/__tests__/deterministic-checks.test.ts +286 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +430 -7
- package/src/notifications/adapters/macos.ts +12 -2
- package/src/notifications/broadcaster.ts +29 -4
- package/src/notifications/conversation-pairing.ts +2 -1
- package/src/notifications/copy-composer.ts +17 -64
- package/src/notifications/decision-engine.ts +113 -45
- package/src/notifications/deterministic-checks.ts +96 -0
- package/src/notifications/emit-signal.ts +21 -1
- package/src/notifications/home-feed-side-effect.ts +138 -5
- package/src/notifications/signal.ts +3 -5
- package/src/notifications/types.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.test.ts +43 -3
- package/src/oauth/platform-connection.ts +19 -6
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +2 -0
- package/src/permissions/ipc-risk-types.ts +1 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +34 -1
- package/src/plugin-api/types.ts +104 -22
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +74 -22
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +187 -42
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +40 -26
- package/src/plugins/user-loader.ts +21 -2
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +37 -5
- package/src/prompts/__tests__/system-prompt.test.ts +10 -43
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +95 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +63 -174
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +164 -0
- package/src/providers/__tests__/inference.test.ts +24 -7
- package/src/providers/anthropic/client.ts +28 -28
- package/src/providers/call-site-routing.ts +24 -6
- package/src/providers/connection-resolution.ts +68 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +74 -0
- package/src/providers/inference/__tests__/connections-openai-compatible.test.ts +175 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +15 -0
- package/src/providers/inference/adapter-factory.ts +32 -6
- package/src/providers/inference/auth.ts +12 -0
- package/src/providers/inference/backfill.ts +14 -1
- package/src/providers/inference/connections.ts +159 -34
- package/src/providers/inference/resolve-auth.ts +14 -4
- package/src/providers/model-catalog.ts +249 -12
- package/src/providers/model-intents.ts +3 -3
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +235 -0
- package/src/providers/openai/chat-completions-provider.ts +169 -8
- package/src/providers/openrouter/client.ts +49 -4
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -2
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +38 -0
- package/src/providers/provider-send-message.ts +27 -12
- package/src/providers/registry.ts +52 -15
- package/src/providers/retry.ts +47 -1
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/agent-wake.ts +103 -15
- package/src/runtime/auth/route-policy.ts +21 -1
- package/src/runtime/btw-sidechain.ts +2 -0
- package/src/runtime/http-server.ts +7 -16
- package/src/runtime/http-types.ts +19 -47
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +17 -0
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +258 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +172 -23
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +275 -44
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +64 -1
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +5 -3
- package/src/runtime/routes/auth-routes.ts +1 -1
- package/src/runtime/routes/bookmark-routes.ts +5 -3
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +126 -0
- package/src/runtime/routes/consolidation-routes.ts +100 -0
- package/src/runtime/routes/conversation-cli-routes.ts +44 -3
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +17 -42
- package/src/runtime/routes/conversation-query-routes.ts +99 -35
- package/src/runtime/routes/conversation-routes.ts +97 -11
- package/src/runtime/routes/documents-routes.ts +25 -86
- package/src/runtime/routes/group-routes.ts +5 -0
- package/src/runtime/routes/inbound-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +111 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +32 -1
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/index.ts +8 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +17 -44
- package/src/runtime/routes/inference-profile-session-reaper.ts +7 -21
- package/src/runtime/routes/inference-provider-connection-routes.ts +199 -22
- package/src/runtime/routes/integrations/a2a.ts +235 -0
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +6 -13
- package/src/runtime/routes/llm-call-sites-routes.ts +11 -1
- package/src/runtime/routes/notification-routes.ts +1 -1
- package/src/runtime/routes/oauth-commands-routes.ts +105 -15
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- package/src/runtime/routes/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +4 -7
- package/src/runtime/routes/subagents-routes.ts +98 -18
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +27 -2
- package/src/runtime/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +93 -1
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +9 -1
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +17 -7
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/browser-execution.ts +15 -11
- package/src/tools/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/memory/register.ts +1 -9
- package/src/tools/permission-checker.ts +1 -1
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +107 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/watcher/__tests__/engine.test.ts +22 -0
- package/src/watcher/engine.ts +6 -2
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +80 -15
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +35 -22
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +3 -1
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +91 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/migrations/runner.ts +39 -9
- package/src/workspace/migrations/types.ts +4 -0
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-window-manager.test.ts +0 -2481
- package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -441
- package/src/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +0 -55
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- package/src/runtime/guardian-action-conversation-turn.ts +0 -99
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
loadRawConfig,
|
|
29
29
|
saveRawConfig,
|
|
30
30
|
setNestedValue,
|
|
31
|
+
withSuppressedConfigDiskWrites,
|
|
32
|
+
withSuppressedConfigDiskWritesSync,
|
|
31
33
|
} from "../../config/loader.js";
|
|
32
34
|
import { AssistantConfigSchema } from "../../config/schema.js";
|
|
33
35
|
import { getSchemaAtPath } from "../../config/schema-utils.js";
|
|
@@ -57,12 +59,20 @@ import {
|
|
|
57
59
|
getConversation,
|
|
58
60
|
getMessageById,
|
|
59
61
|
} from "../../memory/conversation-crud.js";
|
|
62
|
+
import { getDb } from "../../memory/db-connection.js";
|
|
60
63
|
import { clearEmbeddingBackendCache } from "../../memory/embedding-backend.js";
|
|
61
64
|
import { getLlmRequestLogSource } from "../../memory/llm-request-log-source.js";
|
|
62
65
|
import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
|
|
63
66
|
import { getMemoryV2ActivationLogByMessageIds } from "../../memory/memory-v2-activation-log-store.js";
|
|
64
67
|
import { MEMORY_V2_CONSOLIDATION_SOURCE } from "../../memory/v2/constants.js";
|
|
68
|
+
import {
|
|
69
|
+
createConnection,
|
|
70
|
+
listConnections,
|
|
71
|
+
PROVIDERS_REQUIRING_BASE_URL_AND_MODELS,
|
|
72
|
+
} from "../../providers/inference/connections.js";
|
|
73
|
+
import { PROVIDER_CATALOG } from "../../providers/model-catalog.js";
|
|
65
74
|
import { initializeProviders } from "../../providers/registry.js";
|
|
75
|
+
import { credentialKey } from "../../security/credential-key.js";
|
|
66
76
|
import { validateAllowlistFile } from "../../security/secret-allowlist.js";
|
|
67
77
|
import { resolvePricingForUsage } from "../../util/pricing.js";
|
|
68
78
|
import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
|
|
@@ -229,7 +239,7 @@ function getModelSetContext(): ModelSetContext {
|
|
|
229
239
|
watcher.suppressConfigReload = value;
|
|
230
240
|
},
|
|
231
241
|
updateConfigFingerprint() {
|
|
232
|
-
watcher.updateFingerprint();
|
|
242
|
+
withSuppressedConfigDiskWritesSync(() => watcher.updateFingerprint());
|
|
233
243
|
},
|
|
234
244
|
debounceTimers: watcher.timers,
|
|
235
245
|
};
|
|
@@ -377,13 +387,42 @@ function readPlainObject(value: unknown): Record<string, unknown> | undefined {
|
|
|
377
387
|
|
|
378
388
|
function handleGetConfig() {
|
|
379
389
|
try {
|
|
380
|
-
|
|
390
|
+
const config = applyContextDefaultsToRawConfig(loadRawConfig());
|
|
391
|
+
enrichProfilesWithVisionFlag(config);
|
|
392
|
+
return config;
|
|
381
393
|
} catch (err) {
|
|
382
394
|
const message = err instanceof Error ? err.message : String(err);
|
|
383
395
|
throw new InternalError(`Failed to read config: ${message}`);
|
|
384
396
|
}
|
|
385
397
|
}
|
|
386
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Annotate each profile in `config.llm.profiles` with `supportsVision`
|
|
401
|
+
* resolved from the model catalog. The flag is wire-only — it is never
|
|
402
|
+
* persisted to disk. Unknown (provider, model) pairs default to `true`
|
|
403
|
+
* (fail-open) so image upload remains available for custom / unlisted models.
|
|
404
|
+
*/
|
|
405
|
+
function enrichProfilesWithVisionFlag(config: unknown): void {
|
|
406
|
+
const root = readPlainObject(config);
|
|
407
|
+
if (!root) return;
|
|
408
|
+
const llm = readPlainObject(root.llm);
|
|
409
|
+
if (!llm) return;
|
|
410
|
+
const profiles = readPlainObject(llm.profiles);
|
|
411
|
+
if (!profiles) return;
|
|
412
|
+
|
|
413
|
+
for (const profile of Object.values(profiles)) {
|
|
414
|
+
const entry = readPlainObject(profile);
|
|
415
|
+
if (!entry) continue;
|
|
416
|
+
const provider = entry.provider;
|
|
417
|
+
const model = entry.model;
|
|
418
|
+
if (typeof provider !== "string" || typeof model !== "string") continue;
|
|
419
|
+
|
|
420
|
+
const catalogProvider = PROVIDER_CATALOG.find((p) => p.id === provider);
|
|
421
|
+
const catalogModel = catalogProvider?.models.find((m) => m.id === model);
|
|
422
|
+
entry.supportsVision = catalogModel?.supportsVision ?? true;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
|
|
387
426
|
/**
|
|
388
427
|
* Return the JSON Schema for the assistant config (full or scoped).
|
|
389
428
|
*
|
|
@@ -471,15 +510,14 @@ async function commitConfigWrite(
|
|
|
471
510
|
|
|
472
511
|
clearEmbeddingBackendCache();
|
|
473
512
|
invalidateConfigCache();
|
|
474
|
-
// Reinitialize providers so the live registry reflects the new config
|
|
475
|
-
//
|
|
476
|
-
//
|
|
477
|
-
// Only advance the config fingerprint on success - if reinit failed, leave
|
|
478
|
-
// it stale so the watcher can detect the saved config on the next event
|
|
479
|
-
// and retry provider initialization.
|
|
513
|
+
// Reinitialize providers so the live registry reflects the new config.
|
|
514
|
+
// Suppress disk writes inside loadConfig() — we just wrote the raw config
|
|
515
|
+
// and the first-launch seed path would overwrite it with full defaults.
|
|
480
516
|
try {
|
|
481
|
-
await
|
|
482
|
-
|
|
517
|
+
await withSuppressedConfigDiskWrites(async () => {
|
|
518
|
+
await initializeProviders(getConfig());
|
|
519
|
+
configWatcher.updateFingerprint();
|
|
520
|
+
});
|
|
483
521
|
} catch (err) {
|
|
484
522
|
const message = err instanceof Error ? err.message : String(err);
|
|
485
523
|
log.error({ err }, `${opLabel} config: provider reinit failed: ${message}`);
|
|
@@ -577,7 +615,7 @@ function handleValidateAllowlist() {
|
|
|
577
615
|
}
|
|
578
616
|
}
|
|
579
617
|
|
|
580
|
-
function handleReplaceInferenceProfile({
|
|
618
|
+
async function handleReplaceInferenceProfile({
|
|
581
619
|
pathParams = {},
|
|
582
620
|
body,
|
|
583
621
|
}: RouteHandlerArgs) {
|
|
@@ -616,32 +654,58 @@ function handleReplaceInferenceProfile({
|
|
|
616
654
|
);
|
|
617
655
|
}
|
|
618
656
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
657
|
+
// When the UI sends provider but no provider_connection ("Any active X
|
|
658
|
+
// connection"), derive the connection now so the config deep-merge doesn't
|
|
659
|
+
// inherit a stale connection from the default layer.
|
|
660
|
+
const fragment = parsed.data as Record<string, unknown>;
|
|
661
|
+
if (!isManaged && fragment.provider && !fragment.provider_connection) {
|
|
662
|
+
const provider = fragment.provider as string;
|
|
663
|
+
const db = getDb();
|
|
664
|
+
const candidates = listConnections(db, { provider });
|
|
665
|
+
const active = candidates.find((c) => c.status === "active");
|
|
666
|
+
if (active) {
|
|
667
|
+
fragment.provider_connection = active.name;
|
|
668
|
+
} else if (!PROVIDERS_REQUIRING_BASE_URL_AND_MODELS.has(provider)) {
|
|
669
|
+
const connectionName = `${provider}-personal`;
|
|
670
|
+
const isKeyless = provider === "ollama";
|
|
671
|
+
const result = createConnection(db, {
|
|
672
|
+
name: connectionName,
|
|
673
|
+
provider,
|
|
674
|
+
auth: isKeyless
|
|
675
|
+
? { type: "none" }
|
|
676
|
+
: {
|
|
677
|
+
type: "api_key",
|
|
678
|
+
credential: credentialKey(provider, "api_key"),
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
if (result.ok) {
|
|
682
|
+
fragment.provider_connection = connectionName;
|
|
683
|
+
}
|
|
638
684
|
}
|
|
639
|
-
saveRawConfig(raw);
|
|
640
|
-
return { ok: true };
|
|
641
|
-
} catch (err) {
|
|
642
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
643
|
-
throw new InternalError(`Failed to replace inference profile: ${message}`);
|
|
644
685
|
}
|
|
686
|
+
|
|
687
|
+
const raw = loadRawConfig();
|
|
688
|
+
if (isManaged) {
|
|
689
|
+
// Partial overlay: keep every existing key intact, only update label
|
|
690
|
+
// and/or status from the fragment. Using `replaceInferenceProfileConfig`
|
|
691
|
+
// here would wipe the UI-owned seed fields (provider, model, advanced
|
|
692
|
+
// params) because that function assumes the body carries the full UI
|
|
693
|
+
// surface.
|
|
694
|
+
patchManagedProfileFields(raw, name, fragment);
|
|
695
|
+
} else {
|
|
696
|
+
replaceInferenceProfileConfig(raw, name, fragment);
|
|
697
|
+
}
|
|
698
|
+
// Route through `commitConfigWrite` so profile edits flow through the
|
|
699
|
+
// post-write side effects shared with `handlePatchConfig` /
|
|
700
|
+
// `handleSetConfig`: file-watcher suppression so the in-process reload
|
|
701
|
+
// doesn't race the explicit reinit, embedding backend cache clear,
|
|
702
|
+
// in-process `getConfig` cache invalidation, and provider registry
|
|
703
|
+
// reinitialization. `status: "disabled"` on a managed profile (and any
|
|
704
|
+
// `provider` / `model` / `provider_connection` change on a custom
|
|
705
|
+
// profile) must take effect immediately rather than waiting for the
|
|
706
|
+
// next watcher tick.
|
|
707
|
+
await commitConfigWrite(raw, "replace inference profile");
|
|
708
|
+
return { ok: true };
|
|
645
709
|
}
|
|
646
710
|
|
|
647
711
|
/**
|
|
@@ -90,18 +90,24 @@ import {
|
|
|
90
90
|
getOrCreateConversation,
|
|
91
91
|
} from "../../memory/conversation-key-store.js";
|
|
92
92
|
import { searchConversations } from "../../memory/conversation-queries.js";
|
|
93
|
+
import { recordOnboardingEvent } from "../../memory/onboarding-events-store.js";
|
|
94
|
+
import { buildSlackMessageDeepLinks } from "../../messaging/providers/slack/deep-link.js";
|
|
95
|
+
import {
|
|
96
|
+
readSlackMetadataFromMessageMetadata,
|
|
97
|
+
type SlackMessageMetadata,
|
|
98
|
+
} from "../../messaging/providers/slack/message-metadata.js";
|
|
93
99
|
import { normalizeOnboardingContext } from "../../prompts/normalize-onboarding.js";
|
|
94
100
|
import { writeOnboardingSection } from "../../prompts/persona-resolver.js";
|
|
95
101
|
import { getConfiguredProvider } from "../../providers/provider-send-message.js";
|
|
96
102
|
import type { Provider } from "../../providers/types.js";
|
|
97
103
|
import { checkIngressForSecrets } from "../../security/secret-ingress.js";
|
|
104
|
+
import { getSubagentManager } from "../../subagent/index.js";
|
|
98
105
|
import { getLogger } from "../../util/logger.js";
|
|
99
106
|
import {
|
|
100
107
|
getInterfacesDir,
|
|
101
108
|
getWorkspacePromptPath,
|
|
102
109
|
} from "../../util/platform.js";
|
|
103
110
|
import { silentlyWithLog } from "../../util/silently.js";
|
|
104
|
-
import { buildAssistantEvent } from "../assistant-event.js";
|
|
105
111
|
import { assistantEventHub, broadcastMessage } from "../assistant-event-hub.js";
|
|
106
112
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
107
113
|
import { routeGuardianReply } from "../guardian-reply-router.js";
|
|
@@ -114,6 +120,10 @@ import type {
|
|
|
114
120
|
} from "../http-types.js";
|
|
115
121
|
import { resolveLocalTrustContext } from "../local-actor-identity.js";
|
|
116
122
|
import * as pendingInteractions from "../pending-interactions.js";
|
|
123
|
+
import {
|
|
124
|
+
publishConversationListAndMetadataChanged,
|
|
125
|
+
publishConversationMessagesChanged,
|
|
126
|
+
} from "../sync/resource-sync-events.js";
|
|
117
127
|
import {
|
|
118
128
|
resolveTrustContext,
|
|
119
129
|
withSourceChannel,
|
|
@@ -138,6 +148,36 @@ function isValidRiskThreshold(value: unknown): value is RiskThreshold {
|
|
|
138
148
|
);
|
|
139
149
|
}
|
|
140
150
|
|
|
151
|
+
function buildSlackHistoryMessage(
|
|
152
|
+
slackMeta: SlackMessageMetadata | null,
|
|
153
|
+
): RuntimeMessagePayload["slackMessage"] | undefined {
|
|
154
|
+
if (!slackMeta) return undefined;
|
|
155
|
+
|
|
156
|
+
const slackConfig = getConfig().slack;
|
|
157
|
+
const messageLink = buildSlackMessageDeepLinks({
|
|
158
|
+
teamId: slackConfig?.teamId,
|
|
159
|
+
teamUrl: slackConfig?.teamUrl,
|
|
160
|
+
channelId: slackMeta.channelId,
|
|
161
|
+
messageTs: slackMeta.channelTs,
|
|
162
|
+
});
|
|
163
|
+
const threadLink = slackMeta.threadTs
|
|
164
|
+
? buildSlackMessageDeepLinks({
|
|
165
|
+
teamId: slackConfig?.teamId,
|
|
166
|
+
teamUrl: slackConfig?.teamUrl,
|
|
167
|
+
channelId: slackMeta.channelId,
|
|
168
|
+
messageTs: slackMeta.threadTs,
|
|
169
|
+
})
|
|
170
|
+
: undefined;
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
channelId: slackMeta.channelId,
|
|
174
|
+
channelTs: slackMeta.channelTs,
|
|
175
|
+
...(slackMeta.threadTs ? { threadTs: slackMeta.threadTs } : {}),
|
|
176
|
+
...(messageLink ? { messageLink } : {}),
|
|
177
|
+
...(threadLink ? { threadLink } : {}),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
141
181
|
function collectCanonicalGuardianRequestHintIds(
|
|
142
182
|
conversationId: string,
|
|
143
183
|
sourceChannel: string,
|
|
@@ -339,6 +379,7 @@ async function tryConsumeCanonicalGuardianReply(params: {
|
|
|
339
379
|
});
|
|
340
380
|
onEvent({ type: "message_complete", conversationId: conversationId });
|
|
341
381
|
}
|
|
382
|
+
publishConversationMessagesChanged(conversationId);
|
|
342
383
|
} catch (err) {
|
|
343
384
|
log.warn(
|
|
344
385
|
{ err, conversationId },
|
|
@@ -506,6 +547,9 @@ export function handleListMessages(
|
|
|
506
547
|
...(typeof n.conversationId === "string"
|
|
507
548
|
? { conversationId: n.conversationId }
|
|
508
549
|
: {}),
|
|
550
|
+
...(typeof n.objective === "string"
|
|
551
|
+
? { objective: n.objective }
|
|
552
|
+
: {}),
|
|
509
553
|
};
|
|
510
554
|
}
|
|
511
555
|
}
|
|
@@ -513,6 +557,9 @@ export function handleListMessages(
|
|
|
513
557
|
// Ignore malformed metadata
|
|
514
558
|
}
|
|
515
559
|
}
|
|
560
|
+
const slackMessage = buildSlackHistoryMessage(
|
|
561
|
+
readSlackMetadataFromMessageMetadata(msg.metadata),
|
|
562
|
+
);
|
|
516
563
|
|
|
517
564
|
// Strip <no_response/> markers from assistant messages so web/API
|
|
518
565
|
// clients never see the raw sentinel. Only assistant messages produce
|
|
@@ -552,6 +599,7 @@ export function handleListMessages(
|
|
|
552
599
|
textSegments: filteredSegments,
|
|
553
600
|
contentOrder: filteredContentOrder,
|
|
554
601
|
surfaces: rendered.surfaces,
|
|
602
|
+
slackMessage,
|
|
555
603
|
...(rendered.thinkingSegments.length > 0
|
|
556
604
|
? { thinkingSegments: rendered.thinkingSegments }
|
|
557
605
|
: {}),
|
|
@@ -570,6 +618,7 @@ export function handleListMessages(
|
|
|
570
618
|
textSegments: rendered.textSegments,
|
|
571
619
|
contentOrder: rendered.contentOrder,
|
|
572
620
|
surfaces: rendered.surfaces,
|
|
621
|
+
slackMessage,
|
|
573
622
|
...(rendered.thinkingSegments.length > 0
|
|
574
623
|
? { thinkingSegments: rendered.thinkingSegments }
|
|
575
624
|
: {}),
|
|
@@ -678,6 +727,7 @@ export function handleListMessages(
|
|
|
678
727
|
...(m.subagentNotification
|
|
679
728
|
? { subagentNotification: m.subagentNotification }
|
|
680
729
|
: {}),
|
|
730
|
+
...(m.slackMessage ? { slackMessage: m.slackMessage } : {}),
|
|
681
731
|
};
|
|
682
732
|
});
|
|
683
733
|
|
|
@@ -1117,6 +1167,8 @@ export async function handleSendMessage(
|
|
|
1117
1167
|
tone: string;
|
|
1118
1168
|
userName?: string;
|
|
1119
1169
|
assistantName?: string;
|
|
1170
|
+
googleConnected?: boolean;
|
|
1171
|
+
googleScopes?: string[];
|
|
1120
1172
|
};
|
|
1121
1173
|
};
|
|
1122
1174
|
|
|
@@ -1293,16 +1345,10 @@ export async function handleSendMessage(
|
|
|
1293
1345
|
// that other clients don't yet know about.
|
|
1294
1346
|
if (mapping.conversationType === "standard") {
|
|
1295
1347
|
if (!hasMessages(mapping.conversationId)) {
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
reason: "created",
|
|
1301
|
-
}),
|
|
1302
|
-
)
|
|
1303
|
-
.catch((err) => {
|
|
1304
|
-
log.warn({ err }, "Failed to publish conversation_list_invalidated");
|
|
1305
|
-
});
|
|
1348
|
+
publishConversationListAndMetadataChanged(
|
|
1349
|
+
"created",
|
|
1350
|
+
mapping.conversationId,
|
|
1351
|
+
);
|
|
1306
1352
|
}
|
|
1307
1353
|
}
|
|
1308
1354
|
|
|
@@ -1447,6 +1493,12 @@ export async function handleSendMessage(
|
|
|
1447
1493
|
// that can service host_browser_request events; we restore that single
|
|
1448
1494
|
// proxy explicitly below without relaxing `hasNoClient`.
|
|
1449
1495
|
conversation.updateClient(broadcastMessage, !isInteractive);
|
|
1496
|
+
if (isInteractive) {
|
|
1497
|
+
getSubagentManager().updateParentSender(
|
|
1498
|
+
mapping.conversationId,
|
|
1499
|
+
broadcastMessage,
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1450
1502
|
|
|
1451
1503
|
// ── Canned first-greeting fast path ──
|
|
1452
1504
|
// On a completely fresh workspace, skip LLM inference for the macOS
|
|
@@ -1509,6 +1561,18 @@ export async function handleSendMessage(
|
|
|
1509
1561
|
|
|
1510
1562
|
if (isFirstOnboarding) {
|
|
1511
1563
|
persistOnboardingArtifacts(body.onboarding!);
|
|
1564
|
+
try {
|
|
1565
|
+
recordOnboardingEvent({
|
|
1566
|
+
screen: "complete",
|
|
1567
|
+
tools: body.onboarding!.tools,
|
|
1568
|
+
tasks: body.onboarding!.tasks,
|
|
1569
|
+
tone: body.onboarding!.tone,
|
|
1570
|
+
googleConnected: body.onboarding!.googleConnected,
|
|
1571
|
+
googleScopes: body.onboarding!.googleScopes,
|
|
1572
|
+
});
|
|
1573
|
+
} catch (err) {
|
|
1574
|
+
log.warn({ err }, "Failed to record onboarding telemetry event");
|
|
1575
|
+
}
|
|
1512
1576
|
}
|
|
1513
1577
|
|
|
1514
1578
|
setTimeout(() => {
|
|
@@ -1525,6 +1589,7 @@ export async function handleSendMessage(
|
|
|
1525
1589
|
conversationId,
|
|
1526
1590
|
});
|
|
1527
1591
|
broadcastMessage({ type: "message_complete", conversationId });
|
|
1592
|
+
publishConversationMessagesChanged(conversationId);
|
|
1528
1593
|
conversation.processing = false;
|
|
1529
1594
|
silentlyWithLog(
|
|
1530
1595
|
conversation.drainQueue(),
|
|
@@ -1550,6 +1615,18 @@ export async function handleSendMessage(
|
|
|
1550
1615
|
|
|
1551
1616
|
if (isFirstOnboarding) {
|
|
1552
1617
|
persistOnboardingArtifacts(body.onboarding!);
|
|
1618
|
+
try {
|
|
1619
|
+
recordOnboardingEvent({
|
|
1620
|
+
screen: "complete",
|
|
1621
|
+
tools: body.onboarding!.tools,
|
|
1622
|
+
tasks: body.onboarding!.tasks,
|
|
1623
|
+
tone: body.onboarding!.tone,
|
|
1624
|
+
googleConnected: body.onboarding!.googleConnected,
|
|
1625
|
+
googleScopes: body.onboarding!.googleScopes,
|
|
1626
|
+
});
|
|
1627
|
+
} catch (err) {
|
|
1628
|
+
log.warn({ err }, "Failed to record onboarding telemetry event");
|
|
1629
|
+
}
|
|
1553
1630
|
}
|
|
1554
1631
|
|
|
1555
1632
|
const attachments = hasAttachments
|
|
@@ -1828,6 +1905,7 @@ export async function handleSendMessage(
|
|
|
1828
1905
|
type: "message_complete",
|
|
1829
1906
|
conversationId: conversationId,
|
|
1830
1907
|
});
|
|
1908
|
+
publishConversationMessagesChanged(conversationId);
|
|
1831
1909
|
conversation.processing = false;
|
|
1832
1910
|
silentlyWithLog(conversation.drainQueue(), "slash-command queue drain");
|
|
1833
1911
|
}, 0);
|
|
@@ -1869,6 +1947,7 @@ export async function handleSendMessage(
|
|
|
1869
1947
|
// forceCompact() makes an LLM call that can exceed the client's
|
|
1870
1948
|
// HTTP timeout on large contexts, causing a false "Failed to send".
|
|
1871
1949
|
(async () => {
|
|
1950
|
+
let assistantMessagePersisted = false;
|
|
1872
1951
|
try {
|
|
1873
1952
|
broadcastMessage({
|
|
1874
1953
|
type: "user_message_echo",
|
|
@@ -1877,6 +1956,7 @@ export async function handleSendMessage(
|
|
|
1877
1956
|
messageId: persisted.id,
|
|
1878
1957
|
clientMessageId,
|
|
1879
1958
|
});
|
|
1959
|
+
publishConversationMessagesChanged(conversationId);
|
|
1880
1960
|
conversation.emitActivityState(
|
|
1881
1961
|
"thinking",
|
|
1882
1962
|
"context_compacting",
|
|
@@ -1894,6 +1974,7 @@ export async function handleSendMessage(
|
|
|
1894
1974
|
JSON.stringify(assistantMsg.content),
|
|
1895
1975
|
channelMeta,
|
|
1896
1976
|
);
|
|
1977
|
+
assistantMessagePersisted = true;
|
|
1897
1978
|
conversation.getMessages().push(assistantMsg);
|
|
1898
1979
|
|
|
1899
1980
|
broadcastMessage({
|
|
@@ -1902,7 +1983,11 @@ export async function handleSendMessage(
|
|
|
1902
1983
|
conversationId,
|
|
1903
1984
|
});
|
|
1904
1985
|
broadcastMessage({ type: "message_complete", conversationId });
|
|
1986
|
+
publishConversationMessagesChanged(conversationId);
|
|
1905
1987
|
} catch (err) {
|
|
1988
|
+
if (assistantMessagePersisted) {
|
|
1989
|
+
publishConversationMessagesChanged(conversationId);
|
|
1990
|
+
}
|
|
1906
1991
|
log.error({ err, conversationId }, "Compact command failed");
|
|
1907
1992
|
broadcastMessage({
|
|
1908
1993
|
type: "conversation_error",
|
|
@@ -1950,6 +2035,7 @@ export async function handleSendMessage(
|
|
|
1950
2035
|
requestId,
|
|
1951
2036
|
clientMessageId,
|
|
1952
2037
|
});
|
|
2038
|
+
publishConversationMessagesChanged(mapping.conversationId);
|
|
1953
2039
|
|
|
1954
2040
|
// Fire-and-forget the agent loop; events flow to the hub via broadcastMessage.
|
|
1955
2041
|
conversation
|
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
getDocumentById,
|
|
11
|
+
getDocumentsForConversation,
|
|
12
|
+
saveDocument,
|
|
13
|
+
} from "../../documents/document-store.js";
|
|
14
|
+
import { rawAll } from "../../memory/raw-query.js";
|
|
11
15
|
import { getLogger } from "../../util/logger.js";
|
|
12
16
|
import { renderMarkdownToPDF } from "./document-pdf-renderer.js";
|
|
13
17
|
import { BadRequestError, InternalError, NotFoundError } from "./errors.js";
|
|
@@ -16,65 +20,16 @@ import { RouteResponse } from "./types.js";
|
|
|
16
20
|
|
|
17
21
|
const log = getLogger("documents-routes");
|
|
18
22
|
|
|
19
|
-
interface
|
|
23
|
+
interface DocumentListRow {
|
|
20
24
|
surface_id: string;
|
|
21
25
|
conversation_id: string;
|
|
22
26
|
title: string;
|
|
23
|
-
content: string;
|
|
24
27
|
word_count: number;
|
|
25
28
|
created_at: number;
|
|
26
29
|
updated_at: number;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
function loadDocument(surfaceId: string):
|
|
32
|
-
| {
|
|
33
|
-
success: true;
|
|
34
|
-
surfaceId: string;
|
|
35
|
-
conversationId: string;
|
|
36
|
-
title: string;
|
|
37
|
-
content: string;
|
|
38
|
-
wordCount: number;
|
|
39
|
-
createdAt: number;
|
|
40
|
-
updatedAt: number;
|
|
41
|
-
}
|
|
42
|
-
| { success: false; error: string } {
|
|
43
|
-
try {
|
|
44
|
-
const result = rawGet<DocumentRow>(
|
|
45
|
-
/*sql*/ `
|
|
46
|
-
SELECT surface_id, conversation_id, title, content, word_count, created_at, updated_at
|
|
47
|
-
FROM documents
|
|
48
|
-
WHERE surface_id = ?
|
|
49
|
-
`,
|
|
50
|
-
surfaceId,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
if (result) {
|
|
54
|
-
log.info({ surfaceId }, "Loaded document");
|
|
55
|
-
return {
|
|
56
|
-
success: true,
|
|
57
|
-
surfaceId: result.surface_id,
|
|
58
|
-
conversationId: result.conversation_id,
|
|
59
|
-
title: result.title,
|
|
60
|
-
content: result.content,
|
|
61
|
-
wordCount: result.word_count,
|
|
62
|
-
createdAt: result.created_at,
|
|
63
|
-
updatedAt: result.updated_at,
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
log.info({ surfaceId }, "Document not found");
|
|
67
|
-
return { success: false, error: "Document not found" };
|
|
68
|
-
} catch (error) {
|
|
69
|
-
log.error({ err: error, surfaceId }, "Load error");
|
|
70
|
-
return {
|
|
71
|
-
success: false,
|
|
72
|
-
error: error instanceof Error ? error.message : "Unknown error",
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function listDocuments(conversationId?: string): Array<{
|
|
32
|
+
function listAllDocuments(): Array<{
|
|
78
33
|
surfaceId: string;
|
|
79
34
|
conversationId: string;
|
|
80
35
|
title: string;
|
|
@@ -83,29 +38,11 @@ function listDocuments(conversationId?: string): Array<{
|
|
|
83
38
|
updatedAt: number;
|
|
84
39
|
}> {
|
|
85
40
|
try {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
results = rawAll<DocumentListRow>(
|
|
92
|
-
/*sql*/ `
|
|
93
|
-
SELECT d.surface_id, dc.conversation_id AS conversation_id,
|
|
94
|
-
d.title, d.word_count, d.created_at, d.updated_at
|
|
95
|
-
FROM documents d
|
|
96
|
-
INNER JOIN document_conversations dc ON d.surface_id = dc.surface_id
|
|
97
|
-
WHERE dc.conversation_id = ?
|
|
98
|
-
ORDER BY d.updated_at DESC
|
|
99
|
-
`,
|
|
100
|
-
conversationId,
|
|
101
|
-
);
|
|
102
|
-
} else {
|
|
103
|
-
results = rawAll<DocumentListRow>(/*sql*/ `
|
|
104
|
-
SELECT surface_id, conversation_id, title, word_count, created_at, updated_at
|
|
105
|
-
FROM documents
|
|
106
|
-
ORDER BY updated_at DESC
|
|
107
|
-
`);
|
|
108
|
-
}
|
|
41
|
+
const results = rawAll<DocumentListRow>(/*sql*/ `
|
|
42
|
+
SELECT surface_id, conversation_id, title, word_count, created_at, updated_at
|
|
43
|
+
FROM documents
|
|
44
|
+
ORDER BY updated_at DESC
|
|
45
|
+
`);
|
|
109
46
|
|
|
110
47
|
log.info({ count: results.length }, "Listed documents");
|
|
111
48
|
return results.map((row) => ({
|
|
@@ -148,7 +85,9 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
148
85
|
}),
|
|
149
86
|
handler: ({ queryParams }) => {
|
|
150
87
|
const conversationId = queryParams?.conversationId ?? undefined;
|
|
151
|
-
const documents =
|
|
88
|
+
const documents = conversationId
|
|
89
|
+
? getDocumentsForConversation(conversationId)
|
|
90
|
+
: listAllDocuments();
|
|
152
91
|
return { documents };
|
|
153
92
|
},
|
|
154
93
|
},
|
|
@@ -173,11 +112,11 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
173
112
|
updatedAt: z.number(),
|
|
174
113
|
}),
|
|
175
114
|
handler: ({ pathParams }) => {
|
|
176
|
-
const
|
|
177
|
-
if (!
|
|
178
|
-
throw new NotFoundError(
|
|
115
|
+
const doc = getDocumentById(pathParams!.id);
|
|
116
|
+
if (!doc) {
|
|
117
|
+
throw new NotFoundError("Document not found");
|
|
179
118
|
}
|
|
180
|
-
return
|
|
119
|
+
return { success: true, ...doc };
|
|
181
120
|
},
|
|
182
121
|
},
|
|
183
122
|
|
|
@@ -252,13 +191,13 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
252
191
|
description: "Render a document to PDF and return the binary content.",
|
|
253
192
|
tags: ["documents"],
|
|
254
193
|
handler: async ({ pathParams }) => {
|
|
255
|
-
const
|
|
256
|
-
if (!
|
|
257
|
-
throw new NotFoundError(
|
|
194
|
+
const doc = getDocumentById(pathParams!.id);
|
|
195
|
+
if (!doc) {
|
|
196
|
+
throw new NotFoundError("Document not found");
|
|
258
197
|
}
|
|
259
|
-
const pdfBuffer = await renderMarkdownToPDF(
|
|
198
|
+
const pdfBuffer = await renderMarkdownToPDF(doc.title, doc.content);
|
|
260
199
|
const filename =
|
|
261
|
-
|
|
200
|
+
doc.title
|
|
262
201
|
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
263
202
|
.replace(/-+/g, "-")
|
|
264
203
|
.replace(/^-|-$/g, "") || "document";
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
reorderGroups,
|
|
19
19
|
updateGroup,
|
|
20
20
|
} from "../../memory/group-crud.js";
|
|
21
|
+
import { publishConversationListChanged } from "../sync/resource-sync-events.js";
|
|
21
22
|
import { BadRequestError, ForbiddenError, NotFoundError } from "./errors.js";
|
|
22
23
|
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
23
24
|
|
|
@@ -47,6 +48,7 @@ function handleCreateGroup({ body = {} }: RouteHandlerArgs) {
|
|
|
47
48
|
}
|
|
48
49
|
try {
|
|
49
50
|
const group = createGroup(name);
|
|
51
|
+
publishConversationListChanged("created");
|
|
50
52
|
return serializeGroup(group);
|
|
51
53
|
} catch (err) {
|
|
52
54
|
if (
|
|
@@ -90,6 +92,7 @@ function handleUpdateGroup({ pathParams = {}, body = {} }: RouteHandlerArgs) {
|
|
|
90
92
|
if (!updated) {
|
|
91
93
|
throw new NotFoundError("Group not found");
|
|
92
94
|
}
|
|
95
|
+
publishConversationListChanged("reordered");
|
|
93
96
|
return serializeGroup(updated);
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -103,6 +106,7 @@ function handleDeleteGroup({ pathParams = {} }: RouteHandlerArgs) {
|
|
|
103
106
|
throw new ForbiddenError("System groups cannot be deleted");
|
|
104
107
|
}
|
|
105
108
|
deleteGroup(groupId);
|
|
109
|
+
publishConversationListChanged("reordered");
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
function handleReorderGroups({ body = {} }: RouteHandlerArgs) {
|
|
@@ -131,6 +135,7 @@ function handleReorderGroups({ body = {} }: RouteHandlerArgs) {
|
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
reorderGroups(updates);
|
|
138
|
+
publishConversationListChanged("reordered");
|
|
134
139
|
return { ok: true };
|
|
135
140
|
}
|
|
136
141
|
|