@vellumai/assistant 0.5.16 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/ARCHITECTURE.md +69 -16
- package/Dockerfile +2 -5
- package/bun.lock +6 -2
- package/docker-entrypoint.sh +32 -1
- package/docs/architecture/integrations.md +1 -1
- package/docs/architecture/memory.md +21 -24
- package/knip.json +2 -1
- package/openapi.yaml +1198 -83
- package/package.json +5 -1
- package/src/__tests__/actor-token-service.test.ts +68 -0
- package/src/__tests__/agent-loop.test.ts +0 -32
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
- package/src/__tests__/anthropic-provider.test.ts +217 -98
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/app-dir-path-guard.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +47 -1
- package/src/__tests__/app-source-watcher.test.ts +159 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +2 -2
- package/src/__tests__/call-conversation-messages.test.ts +2 -6
- package/src/__tests__/call-domain.test.ts +2 -6
- package/src/__tests__/call-pointer-messages.test.ts +2 -14
- package/src/__tests__/call-recovery.test.ts +2 -6
- package/src/__tests__/call-routes-http.test.ts +2 -6
- package/src/__tests__/call-store.test.ts +2 -6
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +2 -6
- package/src/__tests__/canonical-guardian-store.test.ts +2 -6
- package/src/__tests__/channel-delivery-store.test.ts +2 -6
- package/src/__tests__/channel-retry-sweep.test.ts +2 -6
- package/src/__tests__/checker.test.ts +63 -9
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/config-schema.test.ts +6 -1
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -6
- package/src/__tests__/contacts-tools.test.ts +31 -0
- package/src/__tests__/context-overflow-reducer.test.ts +86 -0
- package/src/__tests__/context-token-estimator.test.ts +175 -10
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +13 -6
- package/src/__tests__/conversation-agent-loop.test.ts +13 -51
- package/src/__tests__/conversation-attachments.test.ts +2 -6
- package/src/__tests__/conversation-attention-store.test.ts +2 -6
- package/src/__tests__/conversation-clear-safety.test.ts +2 -6
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +4 -10
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -6
- package/src/__tests__/conversation-disk-view.test.ts +2 -6
- package/src/__tests__/conversation-error.test.ts +33 -2
- package/src/__tests__/conversation-fork-crud.test.ts +2 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +5 -1
- package/src/__tests__/conversation-media-retry.test.ts +91 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +653 -832
- package/src/__tests__/conversation-runtime-workspace.test.ts +1 -93
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +17 -4
- package/src/__tests__/conversation-usage.test.ts +2 -6
- package/src/__tests__/conversation-wipe.test.ts +13 -414
- package/src/__tests__/conversation-workspace-cache-state.test.ts +6 -12
- package/src/__tests__/conversation-workspace-injection.test.ts +25 -26
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -1
- package/src/__tests__/copy-composer-tc-templates.test.ts +335 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +2 -2
- package/src/__tests__/credential-security-e2e.test.ts +2 -0
- package/src/__tests__/date-context.test.ts +76 -210
- package/src/__tests__/db-schedule-syntax-migration.test.ts +16 -1
- package/src/__tests__/file-list-tool.test.ts +219 -0
- package/src/__tests__/first-greeting.test.ts +1 -1
- package/src/__tests__/followup-tools.test.ts +2 -6
- package/src/__tests__/graph-extraction-event-date.test.ts +186 -0
- package/src/__tests__/guardian-action-conversation-turn.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-executor.test.ts +2 -6
- package/src/__tests__/guardian-action-followup-store.test.ts +2 -6
- package/src/__tests__/guardian-action-grant-mint-consume.test.ts +2 -6
- package/src/__tests__/guardian-action-late-reply.test.ts +2 -6
- package/src/__tests__/guardian-action-store.test.ts +2 -6
- package/src/__tests__/guardian-binding-drift-heal.test.ts +2 -6
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +8 -8
- package/src/__tests__/guardian-dispatch.test.ts +2 -6
- package/src/__tests__/guardian-grant-minting.test.ts +2 -14
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +2 -6
- package/src/__tests__/guardian-routing-invariants.test.ts +192 -6
- package/src/__tests__/guardian-routing-state.test.ts +2 -6
- package/src/__tests__/guardian-verification-voice-binding.test.ts +2 -6
- package/src/__tests__/heartbeat-service.test.ts +180 -3
- package/src/__tests__/identity-routes.test.ts +328 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +178 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +293 -0
- package/src/__tests__/invite-redemption-service.test.ts +2 -6
- package/src/__tests__/invite-routes-http.test.ts +2 -6
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +17 -28
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/list-messages-tool-merge.test.ts +300 -0
- package/src/__tests__/llm-context-normalization.test.ts +18 -18
- package/src/__tests__/llm-context-route-provider.test.ts +103 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +164 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +74 -111
- package/src/__tests__/managed-store.test.ts +38 -11
- package/src/__tests__/mcp-abort-signal.test.ts +5 -0
- package/src/__tests__/mcp-client-auth.test.ts +5 -0
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +134 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/migration-export-streaming.test.ts +304 -0
- package/src/__tests__/migration-import-commit-http.test.ts +11 -10
- package/src/__tests__/mock-fetch.ts +87 -0
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-decision-recipient-context.test.ts +282 -0
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- package/src/__tests__/onboarding-template-contract.test.ts +62 -14
- package/src/__tests__/outlook-attachments.test.ts +301 -0
- package/src/__tests__/outlook-automation-tools.test.ts +425 -0
- package/src/__tests__/outlook-categories.test.ts +212 -0
- package/src/__tests__/outlook-client-automation.test.ts +246 -0
- package/src/__tests__/outlook-compose-tools.test.ts +325 -0
- package/src/__tests__/outlook-declutter-tools.test.ts +585 -0
- package/src/__tests__/outlook-email-watcher.test.ts +322 -0
- package/src/__tests__/outlook-follow-up.test.ts +196 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +498 -3
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/parser.test.ts +32 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +452 -0
- package/src/__tests__/permission-controls-v2-flag.test.ts +55 -0
- package/src/__tests__/permission-mode-sse.test.ts +418 -0
- package/src/__tests__/permission-mode-store.test.ts +277 -0
- package/src/__tests__/permission-mode.test.ts +101 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +359 -0
- package/src/__tests__/platform-callback-registration.test.ts +4 -4
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/profiler-routes.test.ts +502 -0
- package/src/__tests__/profiler-run-store.test.ts +441 -0
- package/src/__tests__/provider-error-scenarios.test.ts +21 -0
- package/src/__tests__/proxy-approval-callback.test.ts +4 -75
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +3 -3
- package/src/__tests__/require-fresh-approval.test.ts +64 -2
- package/src/__tests__/runtime-events-sse-parity.test.ts +2 -6
- package/src/__tests__/runtime-events-sse.test.ts +2 -6
- package/src/__tests__/sandbox-host-parity.test.ts +5 -4
- package/src/__tests__/schedule-store.test.ts +2 -6
- package/src/__tests__/schedule-tools.test.ts +2 -6
- package/src/__tests__/scheduler-recurrence.test.ts +1 -5
- package/src/__tests__/scheduler-reuse-conversation.test.ts +368 -0
- package/src/__tests__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/scrub-corrupted-image-attachments.test.ts +278 -0
- package/src/__tests__/search-skills-unified.test.ts +422 -0
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +44 -9
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/set-permission-mode.test.ts +274 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +38 -31
- package/src/__tests__/skill-feature-flags.test.ts +6 -6
- package/src/__tests__/skill-load-feature-flag.test.ts +23 -11
- package/src/__tests__/skill-memory.test.ts +2 -741
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +1 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/strip-memory-injections.test.ts +187 -0
- package/src/__tests__/subagent-detail.test.ts +84 -0
- package/src/__tests__/subagent-disposal.test.ts +308 -0
- package/src/__tests__/subagent-manager-notify.test.ts +19 -10
- package/src/__tests__/subagent-notify-parent.test.ts +390 -0
- package/src/__tests__/subagent-role-registry.test.ts +108 -0
- package/src/__tests__/subagent-tool-filtering.test.ts +71 -0
- package/src/__tests__/subagent-tools.test.ts +464 -4
- package/src/__tests__/system-prompt-ask-mode.test.ts +139 -0
- package/src/__tests__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +185 -241
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/terminal-tools.test.ts +17 -27
- package/src/__tests__/test-preload.ts +7 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-executor.test.ts +4 -26
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +277 -0
- package/src/__tests__/top-level-renderer.test.ts +10 -13
- package/src/__tests__/trust-store.test.ts +1 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +2 -6
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +118 -8
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -6
- package/src/__tests__/trusted-contact-verification.test.ts +2 -6
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -6
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -6
- package/src/__tests__/usage-routes.test.ts +2 -6
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -6
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -6
- package/src/__tests__/voice-session-bridge.test.ts +2 -6
- package/src/__tests__/volume-security-guard.test.ts +2 -0
- package/src/__tests__/workspace-lifecycle.test.ts +29 -1
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +2 -6
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +387 -0
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +7 -15
- package/src/approvals/guardian-request-resolvers.ts +24 -0
- package/src/avatar/traits-png-sync.ts +3 -3
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -2
- package/src/cli/__tests__/run-assistant-command.ts +29 -0
- package/src/cli/commands/__tests__/email-download.test.ts +245 -0
- package/src/cli/commands/__tests__/email-list.test.ts +192 -0
- package/src/cli/commands/__tests__/email-register.test.ts +186 -0
- package/src/cli/commands/__tests__/email-send.test.ts +291 -0
- package/src/cli/commands/__tests__/email-status.test.ts +181 -0
- package/src/cli/commands/__tests__/email-unregister.test.ts +139 -0
- package/src/cli/commands/__tests__/routes.test.ts +562 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/conversations.ts +1 -8
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/email.ts +584 -835
- package/src/cli/commands/memory.ts +37 -84
- package/src/cli/commands/notifications.ts +7 -2
- package/src/cli/commands/oauth/__tests__/connect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +2 -2
- package/src/cli/commands/oauth/__tests__/mode.test.ts +8 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +25 -11
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -5
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/routes.ts +396 -0
- package/src/cli/commands/skills.ts +218 -36
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +1 -120
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +4 -1
- package/src/config/bundled-skills/contacts/SKILL.md +0 -1
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -8
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -4
- package/src/config/bundled-skills/gmail/SKILL.md +4 -12
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +17 -18
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +40 -33
- package/src/config/bundled-skills/outlook/SKILL.md +189 -0
- package/src/config/bundled-skills/outlook/TOOLS.json +530 -0
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +85 -0
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +77 -0
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +84 -0
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +94 -0
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +49 -0
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +237 -0
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +161 -0
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +32 -0
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +272 -0
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +29 -0
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +129 -0
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +87 -0
- package/src/config/bundled-skills/outlook/tools/shared.ts +20 -0
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +51 -0
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +221 -0
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +252 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +53 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +74 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +18 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +46 -0
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +36 -0
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +17 -0
- package/src/config/bundled-skills/outlook-calendar/types.ts +120 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +47 -40
- package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +16 -29
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +16 -18
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +39 -47
- package/src/config/bundled-skills/schedule/SKILL.md +22 -2
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/settings/tools/avatar-get.ts +3 -13
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +2 -4
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +5 -2
- package/src/config/bundled-skills/slack/SKILL.md +3 -7
- package/src/config/bundled-skills/subagent/SKILL.md +43 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +29 -4
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +78 -8
- package/src/config/feature-flag-registry.json +38 -125
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/filing.ts +51 -0
- package/src/config/schemas/heartbeat.ts +15 -12
- package/src/config/schemas/memory-lifecycle.ts +12 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +14 -0
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/config/skills.ts +18 -7
- package/src/context/token-estimator.ts +25 -18
- package/src/context/window-manager.ts +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/app-source-watcher.ts +93 -0
- package/src/daemon/config-watcher.ts +79 -1
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +143 -82
- package/src/daemon/conversation-agent-loop.ts +236 -108
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-history.ts +4 -19
- package/src/daemon/conversation-lifecycle.ts +36 -9
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +13 -7
- package/src/daemon/conversation-runtime-assembly.ts +305 -306
- package/src/daemon/conversation-tool-setup.ts +44 -14
- package/src/daemon/conversation-workspace.ts +1 -2
- package/src/daemon/conversation.ts +59 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/date-context.ts +26 -53
- package/src/daemon/first-greeting.ts +1 -1
- package/src/daemon/handlers/conversations.ts +4 -7
- package/src/daemon/handlers/shared.test.ts +143 -0
- package/src/daemon/handlers/shared.ts +85 -17
- package/src/daemon/handlers/skills.ts +416 -209
- package/src/daemon/lifecycle.ts +212 -131
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +29 -7
- package/src/daemon/message-types/messages.ts +12 -2
- package/src/daemon/message-types/schedules.ts +1 -0
- package/src/daemon/message-types/settings.ts +6 -0
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/profiler-run-store.ts +557 -0
- package/src/daemon/providers-setup.ts +5 -0
- package/src/daemon/server.ts +100 -11
- package/src/daemon/shutdown-handlers.ts +5 -0
- package/src/daemon/tool-side-effects.ts +50 -8
- package/src/export/transcript-formatter.ts +148 -0
- package/src/filing/filing-service.ts +228 -0
- package/src/heartbeat/heartbeat-service.ts +97 -7
- package/src/hooks/cli.ts +2 -2
- package/src/hooks/runner.ts +15 -38
- package/src/inbound/platform-callback-registration.ts +14 -14
- package/src/mcp/client.ts +6 -0
- package/src/mcp/mcp-oauth-provider.ts +149 -27
- package/src/memory/admin.ts +42 -75
- package/src/memory/app-store.ts +69 -0
- package/src/memory/conversation-bootstrap.ts +3 -1
- package/src/memory/conversation-crud.ts +211 -288
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +61 -13
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/db-init.ts +194 -361
- package/src/memory/embed.ts +73 -0
- package/src/memory/embedding-backend.ts +8 -14
- package/src/memory/embedding-runtime-manager.ts +12 -114
- package/src/memory/fingerprint.ts +2 -2
- package/src/memory/graph/bootstrap.ts +521 -0
- package/src/memory/graph/capability-seed.ts +449 -0
- package/src/memory/graph/consolidation.ts +725 -0
- package/src/memory/graph/conversation-graph-memory.ts +659 -0
- package/src/memory/graph/decay.test.ts +208 -0
- package/src/memory/graph/decay.ts +195 -0
- package/src/memory/graph/extraction-job.ts +74 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1297 -0
- package/src/memory/graph/graph-memory-state-store.ts +37 -0
- package/src/memory/graph/graph-search.ts +280 -0
- package/src/memory/graph/image-ref-utils.ts +29 -0
- package/src/memory/graph/injection.test.ts +513 -0
- package/src/memory/graph/injection.ts +469 -0
- package/src/memory/graph/inspect.ts +543 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1111 -0
- package/src/memory/graph/scoring.test.ts +548 -0
- package/src/memory/graph/scoring.ts +232 -0
- package/src/memory/graph/serendipity.ts +65 -0
- package/src/memory/graph/store.test.ts +1098 -0
- package/src/memory/graph/store.ts +838 -0
- package/src/memory/graph/tool-handlers.ts +301 -0
- package/src/memory/graph/tools.ts +97 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +295 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +32 -42
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.ts +5 -31
- package/src/memory/job-handlers/index-maintenance.ts +23 -11
- package/src/memory/job-handlers/summarization.ts +32 -17
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +21 -31
- package/src/memory/jobs-worker.ts +180 -129
- package/src/memory/llm-request-log-store.ts +96 -12
- package/src/memory/memory-recall-log-store.ts +49 -5
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +55 -0
- package/src/memory/migrations/204-rename-memory-graph-type-values.ts +46 -0
- package/src/memory/migrations/205-memory-graph-image-refs.ts +11 -0
- package/src/memory/migrations/206-memory-graph-node-edits.ts +19 -0
- package/src/memory/migrations/206-scrub-corrupted-image-attachments.ts +131 -0
- package/src/memory/migrations/207-conversation-graph-memory-state.ts +20 -0
- package/src/memory/migrations/208-conversations-last-message-at.ts +35 -0
- package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +85 -0
- package/src/memory/migrations/210-schedule-reuse-conversation.ts +13 -0
- package/src/memory/migrations/211-memory-recall-logs-query-context.ts +21 -0
- package/src/memory/migrations/212-llm-request-logs-created-at-index.ts +19 -0
- package/src/memory/migrations/index.ts +12 -0
- package/src/memory/migrations/registry.ts +16 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/conversations.ts +14 -0
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/infrastructure.ts +8 -1
- package/src/memory/schema/memory-core.ts +0 -51
- package/src/memory/schema/memory-graph.ts +154 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +58 -61
- package/src/messaging/providers/outlook/adapter.ts +8 -1
- package/src/messaging/providers/outlook/client.ts +299 -0
- package/src/messaging/providers/outlook/types.ts +118 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/copy-composer.ts +95 -0
- package/src/notifications/decision-engine.ts +35 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +36 -4
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/permission-mode-store.ts +180 -0
- package/src/permissions/permission-mode.ts +31 -0
- package/src/permissions/workspace-policy.ts +10 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +62 -36
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +100 -0
- package/src/prompts/templates/BOOTSTRAP.md +70 -165
- package/src/prompts/templates/HEARTBEAT.md +3 -1
- package/src/prompts/templates/SOUL.md +25 -4
- package/src/prompts/templates/UPDATES.md +8 -0
- package/src/providers/anthropic/client.ts +136 -220
- package/src/providers/gemini/client.ts +1 -1
- package/src/providers/openai/client.ts +1 -1
- package/src/providers/registry.ts +1 -1
- package/src/providers/retry.ts +19 -3
- package/src/runtime/actor-trust-resolver.ts +5 -1
- package/src/runtime/auth/route-policy.ts +30 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- package/src/runtime/http-server.ts +55 -5
- package/src/runtime/http-types.ts +12 -1
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/migrations/vbundle-builder.ts +389 -3
- package/src/runtime/migrations/vbundle-importer.ts +8 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +378 -0
- package/src/runtime/routes/app-management-routes.ts +1 -11
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +26 -0
- package/src/runtime/routes/archive-utils.ts +29 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/avatar-routes.ts +2 -9
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +22 -1
- package/src/runtime/routes/conversation-analysis-routes.ts +173 -0
- package/src/runtime/routes/conversation-management-routes.ts +3 -14
- package/src/runtime/routes/conversation-query-routes.ts +49 -3
- package/src/runtime/routes/conversation-routes.ts +264 -44
- package/src/runtime/routes/conversation-starter-routes.ts +2 -2
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/global-search-routes.ts +21 -19
- package/src/runtime/routes/group-routes.ts +207 -0
- package/src/runtime/routes/guardian-action-routes.ts +21 -10
- package/src/runtime/routes/guardian-bootstrap-routes.ts +23 -19
- package/src/runtime/routes/heartbeat-routes.ts +4 -10
- package/src/runtime/routes/identity-routes.ts +53 -18
- package/src/runtime/routes/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +292 -0
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +207 -0
- package/src/runtime/routes/llm-context-normalization.ts +14 -10
- package/src/runtime/routes/log-export-routes.ts +23 -275
- package/src/runtime/routes/memory-item-routes.test.ts +170 -247
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/migration-routes.ts +18 -7
- package/src/runtime/routes/profiler-routes.ts +350 -0
- package/src/runtime/routes/schedule-routes.ts +28 -11
- package/src/runtime/routes/settings-routes.ts +95 -8
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/subagents-routes.ts +28 -7
- package/src/runtime/routes/user-route-dispatcher.ts +223 -0
- package/src/runtime/routes/user-routes.ts +41 -0
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/runtime/routes/workspace-routes.ts +0 -1
- package/src/schedule/schedule-store.ts +30 -0
- package/src/schedule/scheduler.ts +52 -18
- package/src/security/oauth2.ts +1 -1
- package/src/security/secure-keys.ts +4 -8
- package/src/shared/provider-env-vars.ts +19 -0
- package/src/skills/catalog-cache.ts +5 -0
- package/src/skills/catalog-install.ts +25 -16
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +29 -18
- package/src/skills/skill-memory.ts +12 -229
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/subagent/index.ts +13 -3
- package/src/subagent/manager.ts +308 -29
- package/src/subagent/types.ts +68 -0
- package/src/tasks/task-runner.ts +7 -5
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/apps/executors.ts +29 -4
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/filesystem/list.ts +93 -0
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +85 -1
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +3 -0
- package/src/tools/schedule/list.ts +1 -0
- package/src/tools/schedule/update.ts +6 -0
- package/src/tools/shared/filesystem/errors.ts +5 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +90 -2
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/shared/filesystem/types.ts +17 -0
- package/src/tools/shared/shell-output.ts +31 -2
- package/src/tools/subagent/abort.ts +12 -2
- package/src/tools/subagent/message.ts +9 -2
- package/src/tools/subagent/notify-parent.ts +79 -0
- package/src/tools/subagent/read.ts +29 -8
- package/src/tools/subagent/resolve.ts +21 -0
- package/src/tools/subagent/spawn.ts +2 -0
- package/src/tools/subagent/status.ts +11 -1
- package/src/tools/system/avatar-generator.ts +3 -3
- package/src/tools/system/register.ts +23 -0
- package/src/tools/system/set-permission-mode.ts +103 -0
- package/src/tools/terminal/parser.ts +30 -5
- package/src/tools/terminal/safe-env.ts +17 -1
- package/src/tools/tool-manifest.ts +9 -3
- package/src/tools/types.ts +2 -0
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/logger.ts +1 -1
- package/src/util/platform.ts +50 -17
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +2 -2
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +76 -0
- package/src/workspace/migrations/026-backfill-install-meta.ts +325 -0
- package/src/workspace/migrations/027-remove-orphaned-optimized-images-cache.ts +42 -0
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +270 -0
- package/src/workspace/migrations/029-seed-pkb.ts +84 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/top-level-renderer.ts +5 -9
- package/src/__tests__/cli-memory.test.ts +0 -372
- package/src/__tests__/clipboard.test.ts +0 -88
- package/src/__tests__/context-memory-e2e.test.ts +0 -415
- package/src/__tests__/journal-context.test.ts +0 -268
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -297
- package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -459
- package/src/__tests__/memory-query-builder.test.ts +0 -59
- package/src/__tests__/memory-recall-quality.test.ts +0 -1046
- package/src/__tests__/memory-regressions.experimental.test.ts +0 -629
- package/src/__tests__/memory-regressions.test.ts +0 -3696
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -295
- package/src/cli/cli-memory.ts +0 -176
- package/src/daemon/conversation-memory.ts +0 -207
- package/src/memory/conversation-starters-cadence.ts +0 -74
- package/src/memory/items-extractor.ts +0 -860
- package/src/memory/job-handlers/batch-extraction.ts +0 -753
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -355
- package/src/memory/job-handlers/journal-carry-forward.ts +0 -255
- package/src/memory/journal-memory.ts +0 -224
- package/src/memory/query-builder.ts +0 -47
- package/src/memory/query-expansion.ts +0 -83
- package/src/memory/retriever.test.ts +0 -1592
- package/src/memory/retriever.ts +0 -1331
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -139
- package/src/memory/search/ranking.ts +0 -15
- package/src/memory/search/staleness.ts +0 -40
- package/src/memory/search/tier-classifier.ts +0 -18
- package/src/memory/search/types.ts +0 -121
- package/src/prompts/journal-context.ts +0 -154
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -562
- package/src/tools/memory/handlers.ts +0 -434
- package/src/util/clipboard.ts +0 -34
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Route handlers for attachment upload, download, and deletion.
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, statSync } from "node:fs";
|
|
4
|
+
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
5
|
+
import { join, resolve, sep } from "node:path";
|
|
5
6
|
|
|
6
7
|
import { z } from "zod";
|
|
7
8
|
|
|
@@ -11,12 +12,82 @@ import {
|
|
|
11
12
|
getFilePathForAttachment,
|
|
12
13
|
validateAttachmentUpload,
|
|
13
14
|
} from "../../memory/attachments-store.js";
|
|
15
|
+
import { getWorkspaceDir } from "../../util/platform.js";
|
|
14
16
|
import { httpError } from "../http-errors.js";
|
|
15
17
|
import type { RouteDefinition } from "../http-router.js";
|
|
16
18
|
|
|
17
19
|
/** 150 MB — base64-encoded 100 MB attachment ≈ 134 MB plus JSON wrapper overhead. */
|
|
18
20
|
const MAX_UPLOAD_BODY_BYTES = 150 * 1024 * 1024;
|
|
19
21
|
|
|
22
|
+
function resolveCanonicalPath(filePath: string): string {
|
|
23
|
+
try {
|
|
24
|
+
return realpathSync(filePath);
|
|
25
|
+
} catch {
|
|
26
|
+
return resolve(filePath);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isPathWithinDirectory(filePath: string, allowedDir: string): boolean {
|
|
31
|
+
return filePath === allowedDir || filePath.startsWith(allowedDir + sep);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function resolveAllowedAttachmentDirectories(): string[] {
|
|
35
|
+
const workspaceAttachmentsDir = join(
|
|
36
|
+
getWorkspaceDir(),
|
|
37
|
+
"data",
|
|
38
|
+
"attachments",
|
|
39
|
+
);
|
|
40
|
+
const recordingsDir = join(
|
|
41
|
+
process.env.HOME ?? "",
|
|
42
|
+
"Library/Application Support/vellum-assistant/recordings",
|
|
43
|
+
);
|
|
44
|
+
return [workspaceAttachmentsDir, recordingsDir].map((dir) => {
|
|
45
|
+
try {
|
|
46
|
+
return realpathSync(dir);
|
|
47
|
+
} catch {
|
|
48
|
+
return resolve(dir);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if a resolved path is inside a conversation attachments subdirectory.
|
|
55
|
+
* Matches: <conversationsDir>/<conversationId>/attachments/...
|
|
56
|
+
*/
|
|
57
|
+
function isConversationAttachmentPath(resolvedPath: string): boolean {
|
|
58
|
+
const conversationsDir = join(getWorkspaceDir(), "conversations");
|
|
59
|
+
let resolvedConversationsDir: string;
|
|
60
|
+
try {
|
|
61
|
+
resolvedConversationsDir = realpathSync(conversationsDir);
|
|
62
|
+
} catch {
|
|
63
|
+
resolvedConversationsDir = resolve(conversationsDir);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!isPathWithinDirectory(resolvedPath, resolvedConversationsDir)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Extract the relative path after conversations/ and verify it contains
|
|
71
|
+
// an "attachments" segment: <conversationId>/attachments/...
|
|
72
|
+
const relativePath = resolvedPath.slice(resolvedConversationsDir.length + 1);
|
|
73
|
+
const segments = relativePath.split(sep);
|
|
74
|
+
return segments.length >= 3 && segments[1] === "attachments";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function resolveAllowedFileBackedAttachmentPath(
|
|
78
|
+
filePath: string,
|
|
79
|
+
): string | null {
|
|
80
|
+
const resolvedPath = resolveCanonicalPath(filePath);
|
|
81
|
+
const allowedDirs = resolveAllowedAttachmentDirectories();
|
|
82
|
+
if (allowedDirs.some((dir) => isPathWithinDirectory(resolvedPath, dir))) {
|
|
83
|
+
return resolvedPath;
|
|
84
|
+
}
|
|
85
|
+
if (isConversationAttachmentPath(resolvedPath)) {
|
|
86
|
+
return resolvedPath;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
20
91
|
export async function handleUploadAttachment(req: Request): Promise<Response> {
|
|
21
92
|
const rawBody = await req.arrayBuffer();
|
|
22
93
|
if (rawBody.byteLength > MAX_UPLOAD_BODY_BYTES) {
|
|
@@ -56,14 +127,22 @@ export async function handleUploadAttachment(req: Request): Promise<Response> {
|
|
|
56
127
|
// This supports retry of file-backed attachments (e.g. recordings) where the
|
|
57
128
|
// client no longer holds the inline data but the file still exists on disk.
|
|
58
129
|
if (filePath && typeof filePath === "string" && (!data || data === "")) {
|
|
59
|
-
|
|
130
|
+
const resolvedPath = resolveAllowedFileBackedAttachmentPath(filePath);
|
|
131
|
+
if (!resolvedPath) {
|
|
132
|
+
return httpError(
|
|
133
|
+
"BAD_REQUEST",
|
|
134
|
+
"filePath is outside allowed upload directories",
|
|
135
|
+
400,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
if (!existsSync(resolvedPath)) {
|
|
60
139
|
return httpError("BAD_REQUEST", "filePath does not exist on disk", 400);
|
|
61
140
|
}
|
|
62
|
-
const sizeBytes = statSync(
|
|
141
|
+
const sizeBytes = statSync(resolvedPath).size;
|
|
63
142
|
attachment = attachmentsStore.uploadFileBackedAttachment(
|
|
64
143
|
filename,
|
|
65
144
|
mimeType,
|
|
66
|
-
|
|
145
|
+
resolvedPath,
|
|
67
146
|
sizeBytes,
|
|
68
147
|
);
|
|
69
148
|
} else {
|
|
@@ -130,24 +209,29 @@ export async function handleDeleteAttachment(req: Request): Promise<Response> {
|
|
|
130
209
|
}
|
|
131
210
|
|
|
132
211
|
function handleGetAttachment(attachmentId: string): Response {
|
|
212
|
+
// Use the file_path column to detect file-backed attachments, not string
|
|
213
|
+
// truthiness of dataBase64 (which would also match valid zero-byte uploads).
|
|
214
|
+
const isFileBacked = !!getFilePathForAttachment(attachmentId);
|
|
215
|
+
|
|
216
|
+
// Skip hydrating file data for file-backed attachments — clients should
|
|
217
|
+
// fetch content via GET /attachments/:id/content (which validates the path
|
|
218
|
+
// against the directory allowlist).
|
|
133
219
|
const attachment = attachmentsStore.getAttachmentById(attachmentId, {
|
|
134
|
-
hydrateFileData:
|
|
220
|
+
hydrateFileData: !isFileBacked,
|
|
135
221
|
});
|
|
136
222
|
if (!attachment) {
|
|
137
223
|
return httpError("NOT_FOUND", "Attachment not found", 404);
|
|
138
224
|
}
|
|
139
225
|
|
|
140
|
-
// Use the file_path column to detect file-backed attachments, not string
|
|
141
|
-
// truthiness of dataBase64 (which would also match valid zero-byte uploads).
|
|
142
|
-
const isFileBacked = !!getFilePathForAttachment(attachmentId);
|
|
143
|
-
|
|
144
226
|
return Response.json({
|
|
145
227
|
id: attachment.id,
|
|
146
228
|
filename: attachment.originalFilename,
|
|
147
229
|
mimeType: attachment.mimeType,
|
|
148
230
|
sizeBytes: attachment.sizeBytes,
|
|
149
231
|
kind: attachment.kind,
|
|
150
|
-
|
|
232
|
+
// Return null for file-backed attachments so the gateway's hydration check
|
|
233
|
+
// (payload.data == null) triggers a fetch from the /content endpoint.
|
|
234
|
+
data: isFileBacked ? null : attachment.dataBase64,
|
|
151
235
|
// Signal to clients that they should fetch content via the /content endpoint
|
|
152
236
|
...(isFileBacked ? { fileBacked: true } : {}),
|
|
153
237
|
});
|
|
@@ -162,21 +246,27 @@ export function handleGetAttachmentContent(
|
|
|
162
246
|
attachmentId: string,
|
|
163
247
|
req: Request,
|
|
164
248
|
): Response {
|
|
249
|
+
// Check for file-backed attachment first so we can skip hydration — file-backed
|
|
250
|
+
// content is served directly from disk via Bun.file, not from the hydrated base64.
|
|
251
|
+
const filePath = getFilePathForAttachment(attachmentId);
|
|
252
|
+
const isFileBacked = !!filePath;
|
|
253
|
+
|
|
165
254
|
const attachment = attachmentsStore.getAttachmentById(attachmentId, {
|
|
166
|
-
hydrateFileData:
|
|
255
|
+
hydrateFileData: !isFileBacked,
|
|
167
256
|
});
|
|
168
257
|
if (!attachment) {
|
|
169
258
|
return httpError("NOT_FOUND", "Attachment not found", 404);
|
|
170
259
|
}
|
|
171
|
-
|
|
172
|
-
// Check for file-backed attachment
|
|
173
|
-
const filePath = getFilePathForAttachment(attachmentId);
|
|
174
260
|
if (filePath) {
|
|
175
|
-
|
|
261
|
+
const resolvedPath = resolveAllowedFileBackedAttachmentPath(filePath);
|
|
262
|
+
if (!resolvedPath) {
|
|
263
|
+
return httpError("NOT_FOUND", "Attachment content not found", 404);
|
|
264
|
+
}
|
|
265
|
+
if (!existsSync(resolvedPath)) {
|
|
176
266
|
return httpError("NOT_FOUND", "Recording file not found on disk", 404);
|
|
177
267
|
}
|
|
178
268
|
|
|
179
|
-
const file = Bun.file(
|
|
269
|
+
const file = Bun.file(resolvedPath);
|
|
180
270
|
const rangeHeader = req.headers.get("Range");
|
|
181
271
|
|
|
182
272
|
if (rangeHeader) {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { join } from "node:path";
|
|
2
|
-
|
|
3
1
|
import { z } from "zod";
|
|
4
2
|
|
|
5
3
|
import { getCharacterComponents } from "../../avatar/character-components.js";
|
|
@@ -8,7 +6,7 @@ import {
|
|
|
8
6
|
writeTraitsAndRenderAvatar,
|
|
9
7
|
} from "../../avatar/traits-png-sync.js";
|
|
10
8
|
import { getLogger } from "../../util/logger.js";
|
|
11
|
-
import {
|
|
9
|
+
import { getAvatarImagePath } from "../../util/platform.js";
|
|
12
10
|
import { buildAssistantEvent } from "../assistant-event.js";
|
|
13
11
|
import { assistantEventHub } from "../assistant-event-hub.js";
|
|
14
12
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
@@ -18,12 +16,7 @@ import type { RouteDefinition } from "../http-router.js";
|
|
|
18
16
|
const log = getLogger("avatar-routes");
|
|
19
17
|
|
|
20
18
|
function publishAvatarUpdated(): void {
|
|
21
|
-
const avatarPath =
|
|
22
|
-
getWorkspaceDir(),
|
|
23
|
-
"data",
|
|
24
|
-
"avatar",
|
|
25
|
-
"avatar-image.png",
|
|
26
|
-
);
|
|
19
|
+
const avatarPath = getAvatarImagePath();
|
|
27
20
|
assistantEventHub
|
|
28
21
|
.publish(
|
|
29
22
|
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Route handlers for the brain graph visualization endpoint.
|
|
3
3
|
*
|
|
4
4
|
* Queries the memory database to return a knowledge graph shaped for brain-lobe
|
|
5
|
-
* visualization, with memory items mapped to brain regions based on their
|
|
5
|
+
* visualization, with memory items mapped to brain regions based on their type.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
@@ -12,24 +12,28 @@ import { count } from "drizzle-orm";
|
|
|
12
12
|
import { z } from "zod";
|
|
13
13
|
|
|
14
14
|
import { getDb } from "../../memory/db.js";
|
|
15
|
-
import {
|
|
15
|
+
import { memoryGraphNodes } from "../../memory/schema.js";
|
|
16
16
|
import { resolveBundledDir } from "../../util/bundled-asset.js";
|
|
17
17
|
import type { RouteDefinition } from "../http-router.js";
|
|
18
18
|
|
|
19
19
|
function getMemoryKindColor(kind: string): string {
|
|
20
20
|
switch (kind) {
|
|
21
|
-
case "
|
|
22
|
-
return "#
|
|
23
|
-
case "
|
|
24
|
-
return "#3b82f6";
|
|
25
|
-
case "
|
|
26
|
-
return "#10b981";
|
|
27
|
-
case "
|
|
28
|
-
return "#
|
|
29
|
-
case "
|
|
30
|
-
return "#
|
|
31
|
-
case "
|
|
32
|
-
return "#
|
|
21
|
+
case "episodic":
|
|
22
|
+
return "#ec4899"; // pink — specific moments/events
|
|
23
|
+
case "semantic":
|
|
24
|
+
return "#3b82f6"; // blue — facts/knowledge
|
|
25
|
+
case "procedural":
|
|
26
|
+
return "#10b981"; // green — skills/how-to
|
|
27
|
+
case "emotional":
|
|
28
|
+
return "#ef4444"; // red — feelings
|
|
29
|
+
case "prospective":
|
|
30
|
+
return "#f59e0b"; // amber — future-oriented
|
|
31
|
+
case "behavioral":
|
|
32
|
+
return "#8b5cf6"; // violet — behavioral patterns
|
|
33
|
+
case "narrative":
|
|
34
|
+
return "#6366f1"; // indigo — stories
|
|
35
|
+
case "shared":
|
|
36
|
+
return "#14b8a6"; // teal — relationship memories
|
|
33
37
|
default:
|
|
34
38
|
return "#94a3b8";
|
|
35
39
|
}
|
|
@@ -41,11 +45,11 @@ function handleGetBrainGraph(): Response {
|
|
|
41
45
|
|
|
42
46
|
const kindCountRows = db
|
|
43
47
|
.select({
|
|
44
|
-
kind:
|
|
48
|
+
kind: memoryGraphNodes.type,
|
|
45
49
|
count: count(),
|
|
46
50
|
})
|
|
47
|
-
.from(
|
|
48
|
-
.groupBy(
|
|
51
|
+
.from(memoryGraphNodes)
|
|
52
|
+
.groupBy(memoryGraphNodes.type)
|
|
49
53
|
.all();
|
|
50
54
|
|
|
51
55
|
const memorySummary = kindCountRows.map((row) => ({
|
|
@@ -86,9 +90,6 @@ export function handleServeBrainGraphUI(bearerToken?: string): Response {
|
|
|
86
90
|
);
|
|
87
91
|
let html = readFileSync(join(brainGraphDir, "brain-graph.html"), "utf-8");
|
|
88
92
|
if (bearerToken) {
|
|
89
|
-
// Inject token as a meta tag for client-side fetch authentication.
|
|
90
|
-
// HTML-escape the token value to guard against injection if the token
|
|
91
|
-
// comes from an environment variable with special characters.
|
|
92
93
|
const escapedToken = bearerToken
|
|
93
94
|
.replace(/&/g, "&")
|
|
94
95
|
.replace(/"/g, """)
|
|
@@ -99,8 +100,6 @@ export function handleServeBrainGraphUI(bearerToken?: string): Response {
|
|
|
99
100
|
` <meta name="api-token" content="${escapedToken}">\n</head>`,
|
|
100
101
|
);
|
|
101
102
|
}
|
|
102
|
-
// CSP permits the CDN sources required by D3.js and Three.js.
|
|
103
|
-
// 'unsafe-eval' is needed by Three.js's shader compilation path.
|
|
104
103
|
const csp = [
|
|
105
104
|
"default-src 'self'",
|
|
106
105
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://d3js.org",
|
|
@@ -16,6 +16,8 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
16
16
|
|
|
17
17
|
import { z } from "zod";
|
|
18
18
|
|
|
19
|
+
import { getConfig } from "../../config/loader.js";
|
|
20
|
+
import { readNowScratchpad } from "../../daemon/conversation-runtime-assembly.js";
|
|
19
21
|
import { getConversationByKey } from "../../memory/conversation-key-store.js";
|
|
20
22
|
import {
|
|
21
23
|
resolveChannelPersona,
|
|
@@ -35,6 +37,9 @@ const log = getLogger("btw-routes");
|
|
|
35
37
|
/** Conversation key used by the client for identity intro generation. */
|
|
36
38
|
const IDENTITY_INTRO_KEY = "identity-intro";
|
|
37
39
|
|
|
40
|
+
/** Conversation key used by the client for empty-state greeting generation. */
|
|
41
|
+
const GREETING_KEY = "greeting";
|
|
42
|
+
|
|
38
43
|
/**
|
|
39
44
|
* Parse the `## Identity Intro` section from SOUL.md.
|
|
40
45
|
* Returns the first non-empty line under that heading, or null.
|
|
@@ -132,6 +137,18 @@ async function handleBtw(
|
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
|
|
140
|
+
// ----- Greeting context enrichment -----
|
|
141
|
+
// Inject NOW.md scratchpad so the model has contextual awareness (mood,
|
|
142
|
+
// current activity) and produces varied, relevant greetings instead of
|
|
143
|
+
// the same deterministic output each time.
|
|
144
|
+
let effectiveContent = trimmedContent;
|
|
145
|
+
if (conversationKey === GREETING_KEY) {
|
|
146
|
+
const now = readNowScratchpad();
|
|
147
|
+
if (now) {
|
|
148
|
+
effectiveContent = `${trimmedContent}\n\n<context>\n${now}\n</context>`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
135
152
|
// Look up an existing conversation — never create one. BTW is ephemeral
|
|
136
153
|
// (the file header promises "No messages are persisted"), so we must not
|
|
137
154
|
// call getOrCreateConversation which would insert a DB row. When no
|
|
@@ -150,14 +167,18 @@ async function handleBtw(
|
|
|
150
167
|
(async () => {
|
|
151
168
|
try {
|
|
152
169
|
const isIntroRequest = conversationKey === IDENTITY_INTRO_KEY;
|
|
170
|
+
const isGreeting = conversationKey === GREETING_KEY;
|
|
153
171
|
const userPersona = resolveGuardianPersona();
|
|
154
172
|
const channelPersona = resolveChannelPersona(undefined);
|
|
155
173
|
const result = await runBtwSidechain({
|
|
156
|
-
content:
|
|
174
|
+
content: effectiveContent,
|
|
157
175
|
conversation,
|
|
158
176
|
signal: req.signal,
|
|
159
177
|
userPersona,
|
|
160
178
|
channelPersona,
|
|
179
|
+
...(isGreeting
|
|
180
|
+
? { modelIntent: getConfig().ui.greetingModelIntent }
|
|
181
|
+
: {}),
|
|
161
182
|
onEvent: (event) => {
|
|
162
183
|
if (event.type === "text_delta") {
|
|
163
184
|
controller.enqueue(
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handler for conversation analysis.
|
|
3
|
+
*
|
|
4
|
+
* POST /v1/conversations/:id/analyze — analyze a conversation via a new
|
|
5
|
+
* agent loop that produces a structured self-assessment.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
9
|
+
import {
|
|
10
|
+
addMessage,
|
|
11
|
+
createConversation,
|
|
12
|
+
getConversation,
|
|
13
|
+
getMessages,
|
|
14
|
+
} from "../../memory/conversation-crud.js";
|
|
15
|
+
import { resolveConversationId } from "../../memory/conversation-key-store.js";
|
|
16
|
+
import { getLogger } from "../../util/logger.js";
|
|
17
|
+
import { buildAssistantEvent } from "../assistant-event.js";
|
|
18
|
+
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
19
|
+
import { httpError } from "../http-errors.js";
|
|
20
|
+
import type { RouteDefinition } from "../http-router.js";
|
|
21
|
+
import type { SendMessageDeps } from "../http-types.js";
|
|
22
|
+
import { resolveLocalTrustContext } from "../local-actor-identity.js";
|
|
23
|
+
|
|
24
|
+
const log = getLogger("conversation-analysis-routes");
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Dependency types — injected by the daemon at wiring time
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
export interface ConversationAnalysisDeps {
|
|
31
|
+
sendMessageDeps: SendMessageDeps;
|
|
32
|
+
buildConversationDetailResponse: (
|
|
33
|
+
id: string,
|
|
34
|
+
) => Record<string, unknown> | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Route definitions
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
export function conversationAnalysisRouteDefinitions(
|
|
42
|
+
deps: ConversationAnalysisDeps,
|
|
43
|
+
): RouteDefinition[] {
|
|
44
|
+
return [
|
|
45
|
+
{
|
|
46
|
+
endpoint: "conversations/:id/analyze",
|
|
47
|
+
method: "POST",
|
|
48
|
+
policyKey: "conversations/analyze",
|
|
49
|
+
summary: "Analyze a conversation",
|
|
50
|
+
description:
|
|
51
|
+
"Create a new conversation with a structured self-assessment of an existing conversation.",
|
|
52
|
+
tags: ["conversations"],
|
|
53
|
+
handler: async ({ params }) => {
|
|
54
|
+
// a. Resolve conversation ID
|
|
55
|
+
const resolvedId = resolveConversationId(params.id);
|
|
56
|
+
if (!resolvedId) {
|
|
57
|
+
return httpError(
|
|
58
|
+
"NOT_FOUND",
|
|
59
|
+
`Conversation ${params.id} not found`,
|
|
60
|
+
404,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// b. Load the conversation
|
|
65
|
+
const conversation = getConversation(resolvedId);
|
|
66
|
+
if (!conversation) {
|
|
67
|
+
return httpError(
|
|
68
|
+
"NOT_FOUND",
|
|
69
|
+
`Conversation ${resolvedId} not found`,
|
|
70
|
+
404,
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// c. Reject private conversations
|
|
75
|
+
if (conversation.conversationType === "private") {
|
|
76
|
+
return httpError(
|
|
77
|
+
"FORBIDDEN",
|
|
78
|
+
"Private conversations cannot be analyzed",
|
|
79
|
+
403,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// d. Check for messages
|
|
84
|
+
const existingMessages = getMessages(resolvedId);
|
|
85
|
+
if (existingMessages.length === 0) {
|
|
86
|
+
return httpError(
|
|
87
|
+
"BAD_REQUEST",
|
|
88
|
+
"Conversation has no messages to analyze",
|
|
89
|
+
400,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// e. Build the analysis transcript
|
|
94
|
+
const { buildAnalysisTranscript } =
|
|
95
|
+
await import("../../export/transcript-formatter.js");
|
|
96
|
+
const transcript = buildAnalysisTranscript(resolvedId);
|
|
97
|
+
|
|
98
|
+
// f. Create a new conversation for the analysis
|
|
99
|
+
const newConv = createConversation({
|
|
100
|
+
title: `Analysis: ${conversation.title ?? "Untitled"}`,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// g. Build the analysis prompt
|
|
104
|
+
const prompt = `<transcript>
|
|
105
|
+
${transcript}
|
|
106
|
+
</transcript>
|
|
107
|
+
|
|
108
|
+
Analyze the conversation above. Provide a structured self-assessment:
|
|
109
|
+
|
|
110
|
+
1. **Summary**: What was the user trying to accomplish? What was the outcome?
|
|
111
|
+
2. **What went well**: Effective tool usage, good reasoning, helpful responses, problem-solving patterns.
|
|
112
|
+
3. **What went wrong**: Errors, unnecessary tool calls, incorrect assumptions, wasted turns, misunderstandings.
|
|
113
|
+
4. **Root causes**: Why did failures happen? Missing context? Wrong approach? Tool limitations?
|
|
114
|
+
5. **Recommendations**: Specific, actionable improvements for similar conversations next time.
|
|
115
|
+
|
|
116
|
+
Be honest and specific. Reference particular moments in the transcript. Focus on patterns that generalize beyond this specific conversation.
|
|
117
|
+
|
|
118
|
+
If you identify insights worth remembering for future conversations, use your memory tools to save them.`;
|
|
119
|
+
|
|
120
|
+
// h. Persist the user message
|
|
121
|
+
const message = await addMessage(
|
|
122
|
+
newConv.id,
|
|
123
|
+
"user",
|
|
124
|
+
JSON.stringify([{ type: "text", text: prompt }]),
|
|
125
|
+
{ provenanceTrustClass: "guardian" as const },
|
|
126
|
+
);
|
|
127
|
+
const messageId = message.id;
|
|
128
|
+
|
|
129
|
+
// i. Load the conversation into memory and set guardian trust context
|
|
130
|
+
const analysisConversation =
|
|
131
|
+
await deps.sendMessageDeps.getOrCreateConversation(newConv.id);
|
|
132
|
+
analysisConversation.setTrustContext(resolveLocalTrustContext("vellum"));
|
|
133
|
+
await analysisConversation.ensureActorScopedHistory();
|
|
134
|
+
|
|
135
|
+
// j. Build onEvent using inline hub publisher
|
|
136
|
+
const onEvent = (msg: ServerMessage) => {
|
|
137
|
+
deps.sendMessageDeps.assistantEventHub.publish(
|
|
138
|
+
buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, msg, newConv.id),
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// k. Set up processing state (required by runAgentLoop guard)
|
|
143
|
+
analysisConversation.processing = true;
|
|
144
|
+
analysisConversation.abortController = new AbortController();
|
|
145
|
+
analysisConversation.currentRequestId = crypto.randomUUID();
|
|
146
|
+
|
|
147
|
+
// l. Fire-and-forget the agent loop
|
|
148
|
+
analysisConversation
|
|
149
|
+
.runAgentLoop(prompt, messageId, onEvent, {
|
|
150
|
+
isInteractive: false,
|
|
151
|
+
isUserMessage: true,
|
|
152
|
+
})
|
|
153
|
+
.catch((err) => {
|
|
154
|
+
log.error(
|
|
155
|
+
{ err, conversationId: newConv.id },
|
|
156
|
+
"Analysis agent loop failed",
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// m. Return the new conversation detail
|
|
161
|
+
const detail = deps.buildConversationDetailResponse(newConv.id);
|
|
162
|
+
if (!detail) {
|
|
163
|
+
return httpError(
|
|
164
|
+
"INTERNAL_ERROR",
|
|
165
|
+
`Analysis conversation ${newConv.id} could not be loaded`,
|
|
166
|
+
500,
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
return Response.json(detail);
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
}
|
|
@@ -344,12 +344,6 @@ export function conversationManagementRouteDefinitions(
|
|
|
344
344
|
targetId: segId,
|
|
345
345
|
});
|
|
346
346
|
}
|
|
347
|
-
for (const itemId of result.orphanedItemIds) {
|
|
348
|
-
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
349
|
-
targetType: "item",
|
|
350
|
-
targetId: itemId,
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
347
|
for (const summaryId of result.deletedSummaryIds) {
|
|
354
348
|
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
355
349
|
targetType: "summary",
|
|
@@ -359,7 +353,6 @@ export function conversationManagementRouteDefinitions(
|
|
|
359
353
|
log.info(
|
|
360
354
|
{
|
|
361
355
|
conversationId: resolvedId,
|
|
362
|
-
unsuperseded: result.unsupersededItemIds.length,
|
|
363
356
|
summariesDeleted: result.deletedSummaryIds.length,
|
|
364
357
|
jobsCancelled: result.cancelledJobCount,
|
|
365
358
|
},
|
|
@@ -367,7 +360,7 @@ export function conversationManagementRouteDefinitions(
|
|
|
367
360
|
);
|
|
368
361
|
return Response.json({
|
|
369
362
|
wiped: true,
|
|
370
|
-
unsupersededItems:
|
|
363
|
+
unsupersededItems: 0,
|
|
371
364
|
deletedSummaries: result.deletedSummaryIds.length,
|
|
372
365
|
cancelledJobs: result.cancelledJobCount,
|
|
373
366
|
});
|
|
@@ -417,12 +410,6 @@ export function conversationManagementRouteDefinitions(
|
|
|
417
410
|
targetId: segId,
|
|
418
411
|
});
|
|
419
412
|
}
|
|
420
|
-
for (const itemId of deleted.orphanedItemIds) {
|
|
421
|
-
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
422
|
-
targetType: "item",
|
|
423
|
-
targetId: itemId,
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
413
|
for (const summaryId of deleted.deletedSummaryIds) {
|
|
427
414
|
enqueueMemoryJob("delete_qdrant_vectors", {
|
|
428
415
|
targetType: "summary",
|
|
@@ -528,6 +515,7 @@ export function conversationManagementRouteDefinitions(
|
|
|
528
515
|
conversationId: string;
|
|
529
516
|
displayOrder?: number;
|
|
530
517
|
isPinned?: boolean;
|
|
518
|
+
groupId?: string | null;
|
|
531
519
|
}>;
|
|
532
520
|
};
|
|
533
521
|
if (!Array.isArray(body.updates)) {
|
|
@@ -538,6 +526,7 @@ export function conversationManagementRouteDefinitions(
|
|
|
538
526
|
id: u.conversationId,
|
|
539
527
|
displayOrder: u.displayOrder ?? null,
|
|
540
528
|
isPinned: u.isPinned ?? false,
|
|
529
|
+
groupId: u.groupId,
|
|
541
530
|
})),
|
|
542
531
|
);
|
|
543
532
|
return Response.json({ ok: true });
|
|
@@ -43,7 +43,10 @@ import {
|
|
|
43
43
|
} from "../../daemon/handlers/conversation-history.js";
|
|
44
44
|
import { deleteQueuedMessage } from "../../daemon/handlers/conversations.js";
|
|
45
45
|
import { getAssistantMessageIdsInTurn } from "../../memory/conversation-crud.js";
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
getRequestLogById,
|
|
48
|
+
getRequestLogsByMessageId,
|
|
49
|
+
} from "../../memory/llm-request-log-store.js";
|
|
47
50
|
import { getMemoryRecallLogByMessageIds } from "../../memory/memory-recall-log-store.js";
|
|
48
51
|
import { resolvePricingForUsage } from "../../util/pricing.js";
|
|
49
52
|
import { httpError } from "../http-errors.js";
|
|
@@ -487,8 +490,8 @@ export function conversationQueryRouteDefinitions(
|
|
|
487
490
|
);
|
|
488
491
|
return {
|
|
489
492
|
id: log.id,
|
|
490
|
-
requestPayload,
|
|
491
|
-
responsePayload,
|
|
493
|
+
requestPayload: null,
|
|
494
|
+
responsePayload: null,
|
|
492
495
|
createdAt: log.createdAt,
|
|
493
496
|
...result,
|
|
494
497
|
};
|
|
@@ -498,6 +501,49 @@ export function conversationQueryRouteDefinitions(
|
|
|
498
501
|
},
|
|
499
502
|
},
|
|
500
503
|
|
|
504
|
+
// ── Raw payload for a single LLM request log ─────────────────────
|
|
505
|
+
{
|
|
506
|
+
endpoint: "llm-request-logs/:id/payload",
|
|
507
|
+
method: "GET",
|
|
508
|
+
policyKey: "llm-request-logs/payload",
|
|
509
|
+
summary: "Get raw payload for a single LLM request log",
|
|
510
|
+
description:
|
|
511
|
+
"Return the full request and response payloads for a specific log entry.",
|
|
512
|
+
tags: ["messages"],
|
|
513
|
+
responseBody: z.object({
|
|
514
|
+
id: z.string(),
|
|
515
|
+
requestPayload: z.unknown(),
|
|
516
|
+
responsePayload: z.unknown(),
|
|
517
|
+
}),
|
|
518
|
+
handler: ({ params }) => {
|
|
519
|
+
const logId = params.id;
|
|
520
|
+
if (!logId) {
|
|
521
|
+
return httpError("BAD_REQUEST", "log id is required", 400);
|
|
522
|
+
}
|
|
523
|
+
const log = getRequestLogById(logId);
|
|
524
|
+
if (!log) {
|
|
525
|
+
return httpError("NOT_FOUND", "log not found", 404);
|
|
526
|
+
}
|
|
527
|
+
let requestPayload: unknown;
|
|
528
|
+
try {
|
|
529
|
+
requestPayload = JSON.parse(log.requestPayload);
|
|
530
|
+
} catch {
|
|
531
|
+
requestPayload = log.requestPayload;
|
|
532
|
+
}
|
|
533
|
+
let responsePayload: unknown;
|
|
534
|
+
try {
|
|
535
|
+
responsePayload = JSON.parse(log.responsePayload);
|
|
536
|
+
} catch {
|
|
537
|
+
responsePayload = log.responsePayload;
|
|
538
|
+
}
|
|
539
|
+
return Response.json({
|
|
540
|
+
id: log.id,
|
|
541
|
+
requestPayload,
|
|
542
|
+
responsePayload,
|
|
543
|
+
});
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
|
|
501
547
|
// ── Delete queued message ─────────────────────────────────────────
|
|
502
548
|
{
|
|
503
549
|
endpoint: "messages/queued/:id",
|