@vellumai/assistant 0.5.15 → 0.6.0
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 +3 -3
- package/Dockerfile +0 -3
- package/docs/architecture/integrations.md +15 -14
- package/knip.json +4 -1
- package/openapi.yaml +670 -122
- package/package.json +1 -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 +57 -3
- package/src/__tests__/app-compiler.test.ts +120 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +5 -377
- 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__/ces-rpc-credential-backend.test.ts +4 -1
- 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 +84 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +108 -6
- package/src/__tests__/cli-memory.test.ts +377 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -2
- package/src/__tests__/config-schema.test.ts +1 -3
- package/src/__tests__/config-set-platform-guard.test.ts +302 -0
- package/src/__tests__/config-watcher-feature-flags.test.ts +211 -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 +9 -0
- package/src/__tests__/conversation-agent-loop.test.ts +9 -0
- 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 +5 -0
- 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 +7 -4
- package/src/__tests__/conversation-slash-commands.test.ts +2 -6
- package/src/__tests__/conversation-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +3 -6
- package/src/__tests__/conversation-wipe.test.ts +11 -408
- 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 +6 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +7 -73
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -7
- 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 +343 -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 +1 -3
- package/src/__tests__/inbound-invite-redemption.test.ts +2 -6
- package/src/__tests__/injection-block.test.ts +154 -0
- package/src/__tests__/install-meta.test.ts +506 -0
- package/src/__tests__/install-skill-routing.test.ts +292 -0
- package/src/__tests__/intent-routing.test.ts +6 -18
- 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 +2 -14
- package/src/__tests__/list-messages-attachments.test.ts +2 -6
- package/src/__tests__/llm-context-route-provider.test.ts +2 -6
- package/src/__tests__/llm-request-log-turn-query.test.ts +2 -6
- package/src/__tests__/llm-usage-store.test.ts +2 -6
- package/src/__tests__/log-export-workspace.test.ts +4 -34
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -37
- package/src/__tests__/managed-store.test.ts +40 -21
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +2 -8
- package/src/__tests__/memory-recall-log-store.test.ts +2 -6
- package/src/__tests__/memory-upsert-concurrency.test.ts +4 -112
- package/src/__tests__/messaging-send-tool.test.ts +6 -6
- package/src/__tests__/migration-cross-version-compatibility.test.ts +1 -29
- package/src/__tests__/migration-export-http.test.ts +3 -34
- package/src/__tests__/migration-import-commit-http.test.ts +1 -29
- package/src/__tests__/migration-import-preflight-http.test.ts +3 -34
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +2 -1
- package/src/__tests__/non-member-access-request.test.ts +2 -6
- package/src/__tests__/notification-guardian-path.test.ts +2 -6
- package/src/__tests__/oauth-apps-routes.test.ts +120 -10
- package/src/__tests__/oauth-cli.test.ts +364 -2
- package/src/__tests__/oauth-connect-orchestrator.test.ts +709 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +2 -1
- package/src/__tests__/oauth-provider-visibility.test.ts +149 -0
- package/src/__tests__/oauth-providers-routes.test.ts +5 -2
- package/src/__tests__/oauth-store.test.ts +0 -5
- package/src/__tests__/oauth2-gateway-transport.test.ts +18 -3
- 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 +1071 -0
- package/src/__tests__/outlook-trash.test.ts +77 -0
- package/src/__tests__/outlook-unsubscribe.test.ts +250 -0
- package/src/__tests__/path-policy.test.ts +2 -17
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/platform-callback-registration.test.ts +7 -11
- package/src/__tests__/playbook-execution.test.ts +76 -80
- package/src/__tests__/playbook-tools.test.ts +5 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- package/src/__tests__/provider-error-scenarios.test.ts +21 -2
- package/src/__tests__/qdrant-manager.test.ts +68 -21
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +273 -0
- package/src/__tests__/registry.test.ts +2 -2
- package/src/__tests__/require-fresh-approval.test.ts +64 -3
- 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-diagnostics.test.ts +20 -29
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +2 -10
- 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__/scoped-approval-grants.test.ts +2 -6
- package/src/__tests__/scoped-grant-security-matrix.test.ts +2 -6
- package/src/__tests__/search-skills-unified.test.ts +421 -0
- package/src/__tests__/secret-allowlist.test.ts +20 -35
- package/src/__tests__/secret-onetime-send.test.ts +2 -0
- package/src/__tests__/send-endpoint-busy.test.ts +2 -6
- package/src/__tests__/sequence-store.test.ts +2 -6
- package/src/__tests__/server-history-render.test.ts +2 -6
- package/src/__tests__/shell-credential-ref.test.ts +0 -5
- 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 +13 -54
- package/src/__tests__/skill-load-inline-command.test.ts +3 -65
- package/src/__tests__/skill-load-inline-includes.test.ts +3 -65
- package/src/__tests__/skill-load-tool.test.ts +3 -67
- package/src/__tests__/skill-memory.test.ts +480 -195
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +23 -50
- package/src/__tests__/slack-channel-config.test.ts +2 -21
- package/src/__tests__/slack-inbound-verification.test.ts +2 -6
- package/src/__tests__/starter-bundle.test.ts +2 -8
- package/src/__tests__/stt-hints.test.ts +7 -2
- package/src/__tests__/system-prompt.test.ts +25 -45
- package/src/__tests__/task-compiler.test.ts +2 -27
- package/src/__tests__/task-management-tools.test.ts +2 -27
- package/src/__tests__/task-memory-cleanup.test.ts +173 -250
- package/src/__tests__/task-runner.test.ts +2 -27
- package/src/__tests__/task-scheduler.test.ts +2 -27
- package/src/__tests__/terminal-tools.test.ts +1 -17
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +0 -79
- package/src/__tests__/tool-approval-handler.test.ts +4 -27
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +2 -11
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -25
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-grant-request-escalation.test.ts +4 -27
- package/src/__tests__/tool-preview-lifecycle.test.ts +0 -20
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- package/src/__tests__/trust-store.test.ts +10 -42
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +1 -30
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +3 -27
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -28
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -28
- package/src/__tests__/trusted-contact-verification.test.ts +2 -28
- package/src/__tests__/turn-boundary-resolution.test.ts +2 -34
- package/src/__tests__/twilio-provider.test.ts +0 -16
- package/src/__tests__/twilio-routes-twiml.test.ts +7 -12
- package/src/__tests__/twilio-routes.test.ts +0 -24
- package/src/__tests__/update-bulletin.test.ts +17 -89
- package/src/__tests__/usage-cache-backfill-migration.test.ts +1 -26
- package/src/__tests__/usage-routes.test.ts +2 -27
- package/src/__tests__/user-reference.test.ts +1 -5
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +4 -34
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +2 -53
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/voice-invite-redemption.test.ts +2 -27
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -30
- package/src/__tests__/voice-session-bridge.test.ts +2 -27
- 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 +4 -29
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +2 -2
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +4 -29
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +558 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +0 -6
- package/src/__tests__/workspace-policy.test.ts +1 -1
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/attachments.ts +7 -2
- package/src/agent/image-optimize.ts +165 -0
- package/src/agent/loop.ts +1 -15
- package/src/bundler/app-compiler.ts +179 -2
- package/src/bundler/package-resolver.ts +3 -5
- package/src/cli/__tests__/notifications.test.ts +1 -24
- package/src/cli/cli-memory.ts +179 -0
- package/src/cli/commands/avatar.ts +3 -3
- package/src/cli/commands/config.ts +26 -13
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/memory.ts +41 -55
- 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__/providers-update.test.ts +1 -1
- package/src/cli/commands/oauth/__tests__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +26 -6
- package/src/cli/commands/oauth/mode.ts +7 -0
- package/src/cli/commands/oauth/providers.ts +49 -42
- package/src/cli/commands/oauth/shared.ts +39 -3
- package/src/cli/commands/platform/__tests__/connect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +3 -49
- package/src/cli/commands/platform/__tests__/status.test.ts +5 -55
- package/src/cli/commands/platform/index.ts +16 -16
- package/src/cli/commands/skills.ts +88 -16
- package/src/cli/commands/trust.ts +2 -2
- package/src/cli/lib/daemon-credential-client.ts +2 -3
- package/src/config/bundled-skills/acp/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/TOOLS.json +7 -7
- 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 +2 -10
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -9
- package/src/config/bundled-skills/messaging/SKILL.md +26 -19
- 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/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/slack/SKILL.md +1 -7
- package/src/config/bundled-tool-registry.ts +56 -4
- package/src/config/env-registry.ts +15 -8
- package/src/config/feature-flag-registry.json +29 -116
- package/src/config/loader.ts +4 -0
- package/src/config/schemas/platform.ts +8 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +8 -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 +32 -9
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/process-manager.ts +3 -1
- package/src/daemon/config-watcher.ts +51 -0
- package/src/daemon/context-overflow-reducer.ts +46 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +123 -82
- package/src/daemon/conversation-agent-loop.ts +99 -63
- package/src/daemon/conversation-error.ts +31 -8
- package/src/daemon/conversation-lifecycle.ts +33 -0
- package/src/daemon/conversation-media-retry.ts +85 -7
- package/src/daemon/conversation-notifiers.ts +4 -1
- package/src/daemon/conversation-process.ts +1 -0
- package/src/daemon/conversation-runtime-assembly.ts +5 -0
- package/src/daemon/conversation-usage.ts +1 -0
- package/src/daemon/conversation.ts +41 -2
- package/src/daemon/daemon-control.ts +8 -2
- package/src/daemon/handlers/shared.ts +22 -12
- package/src/daemon/handlers/skills.ts +423 -201
- package/src/daemon/lifecycle.ts +52 -4
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +5 -1
- package/src/daemon/message-types/messages.ts +3 -1
- package/src/daemon/message-types/skills.ts +97 -36
- package/src/daemon/providers-setup.ts +7 -0
- package/src/daemon/server.ts +35 -22
- package/src/daemon/tool-side-effects.ts +27 -5
- package/src/events/domain-events.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- 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/memory/admin.ts +11 -45
- package/src/memory/conversation-bootstrap.ts +2 -0
- package/src/memory/conversation-crud.ts +242 -348
- package/src/memory/conversation-group-migration.ts +157 -0
- package/src/memory/conversation-queries.ts +4 -2
- package/src/memory/db-init.ts +39 -3
- 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 +512 -0
- package/src/memory/graph/capability-seed.ts +297 -0
- package/src/memory/graph/consolidation.ts +691 -0
- package/src/memory/graph/conversation-graph-memory.ts +630 -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 +69 -0
- package/src/memory/graph/extraction.test.ts +936 -0
- package/src/memory/graph/extraction.ts +1254 -0
- package/src/memory/graph/graph-search.ts +266 -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 +439 -0
- package/src/memory/graph/inspect.ts +534 -0
- package/src/memory/graph/narrative.ts +267 -0
- package/src/memory/graph/pattern-scan.ts +269 -0
- package/src/memory/graph/retriever.ts +1008 -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 +1050 -0
- package/src/memory/graph/store.ts +699 -0
- package/src/memory/graph/tool-handlers.ts +426 -0
- package/src/memory/graph/tools.ts +141 -0
- package/src/memory/graph/triggers.test.ts +487 -0
- package/src/memory/graph/triggers.ts +223 -0
- package/src/memory/graph/types.ts +271 -0
- package/src/memory/group-crud.ts +191 -0
- package/src/memory/indexer.ts +37 -19
- package/src/memory/job-handlers/cleanup.ts +0 -53
- package/src/memory/job-handlers/conversation-starters.ts +91 -53
- package/src/memory/job-handlers/embedding.test.ts +3 -27
- 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 +50 -70
- package/src/memory/jobs-worker.ts +147 -112
- package/src/memory/llm-usage-store.ts +35 -2
- package/src/memory/message-content.ts +1 -0
- package/src/memory/migrations/201-oauth-providers-feature-flag.ts +11 -0
- package/src/memory/migrations/202-drop-callback-transport-column.ts +13 -0
- package/src/memory/migrations/202-memory-graph-tables.ts +130 -0
- package/src/memory/migrations/203-drop-memory-items-tables.ts +23 -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/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/qdrant-manager.ts +26 -5
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/schema/oauth.ts +1 -1
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/slack-thread-store.ts +17 -0
- package/src/memory/task-memory-cleanup.ts +28 -50
- package/src/messaging/providers/outlook/adapter.ts +200 -0
- package/src/messaging/providers/outlook/client.ts +610 -0
- package/src/messaging/providers/outlook/types.ts +201 -0
- package/src/notifications/adapters/macos.ts +1 -0
- package/src/notifications/adapters/slack.ts +1 -1
- package/src/notifications/copy-composer.ts +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +1 -1
- package/src/oauth/connect-orchestrator.ts +10 -3
- package/src/oauth/oauth-store.ts +10 -11
- package/src/oauth/provider-serializer.ts +3 -0
- package/src/oauth/provider-visibility.ts +16 -0
- package/src/oauth/seed-providers.ts +50 -17
- package/src/permissions/checker.ts +62 -9
- package/src/permissions/defaults.ts +4 -4
- package/src/permissions/types.ts +2 -4
- package/src/permissions/workspace-policy.ts +1 -1
- package/src/playbooks/playbook-compiler.ts +19 -18
- package/src/playbooks/types.ts +4 -3
- package/src/prompts/system-prompt.ts +6 -93
- package/src/prompts/templates/UPDATES.md +6 -0
- package/src/providers/anthropic/client.ts +47 -19
- 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/__tests__/credential-service.test.ts +1 -27
- package/src/runtime/auth/__tests__/token-service.test.ts +1 -25
- package/src/runtime/auth/route-policy.ts +7 -4
- package/src/runtime/guardian-reply-router.ts +10 -2
- package/src/runtime/http-server.ts +23 -3
- package/src/runtime/middleware/auth.ts +20 -0
- package/src/runtime/routes/attachment-routes.test.ts +106 -0
- package/src/runtime/routes/attachment-routes.ts +106 -16
- package/src/runtime/routes/brain-graph-routes.ts +21 -22
- package/src/runtime/routes/btw-routes.ts +8 -0
- package/src/runtime/routes/conversation-management-routes.ts +2 -0
- package/src/runtime/routes/conversation-query-routes.ts +2 -58
- 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/inbound-message-handler.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +43 -2
- 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/memory-item-routes.test.ts +2 -31
- package/src/runtime/routes/memory-item-routes.ts +385 -341
- package/src/runtime/routes/oauth-apps.ts +18 -1
- package/src/runtime/routes/oauth-providers.ts +13 -1
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/settings-routes.ts +1 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/usage-routes.ts +19 -2
- package/src/runtime/routes/work-items-routes.test.ts +2 -27
- package/src/runtime/routes/workspace-routes.test.ts +3 -27
- package/src/schedule/scheduler.ts +8 -1
- package/src/security/oauth2.ts +1 -1
- package/src/security/secret-allowlist.ts +4 -4
- 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 +15 -14
- package/src/skills/clawhub.ts +134 -154
- package/src/skills/install-meta.ts +208 -0
- package/src/skills/managed-store.ts +27 -16
- package/src/skills/skill-memory.ts +210 -96
- package/src/skills/skillssh-registry.ts +19 -17
- package/src/tasks/task-runner.ts +3 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -5
- package/src/tools/browser/runtime-check.ts +3 -1
- package/src/tools/memory/register.ts +63 -46
- package/src/tools/permission-checker.ts +7 -19
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- package/src/tools/skills/skill-script-runner.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/tool-manifest.ts +3 -3
- package/src/util/browser.ts +25 -10
- package/src/util/bun-runtime.ts +172 -0
- package/src/util/device-id.ts +3 -65
- package/src/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- package/src/workspace/git-service.ts +27 -6
- 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/registry.ts +6 -0
- 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/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 -741
- package/src/memory/job-handlers/extraction.ts +0 -40
- package/src/memory/job-handlers/journal-carry-forward.test.ts +0 -383
- 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 -1590
- package/src/memory/retriever.ts +0 -1323
- package/src/memory/search/formatting.test.ts +0 -140
- package/src/memory/search/formatting.ts +0 -262
- package/src/memory/search/mmr.ts +0 -136
- 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 -156
- package/src/tools/memory/definitions.ts +0 -69
- package/src/tools/memory/handlers.test.ts +0 -590
- package/src/tools/memory/handlers.ts +0 -434
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HTTP route definitions for model configuration, embedding configuration,
|
|
3
|
-
*
|
|
3
|
+
* conversation search, message content, LLM
|
|
4
4
|
* context inspection, and queued message deletion.
|
|
5
5
|
*
|
|
6
6
|
* These routes expose conversation query functionality over the HTTP API.
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
* PUT /v1/model/image-gen — set image-gen model
|
|
11
11
|
* GET /v1/config/embeddings — current embedding config
|
|
12
12
|
* PUT /v1/config/embeddings — set embedding provider/model
|
|
13
|
-
* GET /v1/config/permissions/skip — dangerouslySkipPermissions status
|
|
14
|
-
* PUT /v1/config/permissions/skip — toggle dangerouslySkipPermissions
|
|
15
13
|
* GET /v1/config — full raw workspace config
|
|
16
14
|
* PATCH /v1/config — deep-merge partial config
|
|
17
15
|
* GET /v1/conversations/search — search conversations
|
|
@@ -24,7 +22,6 @@ import { z } from "zod";
|
|
|
24
22
|
|
|
25
23
|
import {
|
|
26
24
|
deepMergeOverwrite,
|
|
27
|
-
getConfig,
|
|
28
25
|
loadRawConfig,
|
|
29
26
|
saveRawConfig,
|
|
30
27
|
} from "../../config/loader.js";
|
|
@@ -113,9 +110,7 @@ function applyStoredProviderToLlmContextResult(
|
|
|
113
110
|
const mergedSummary = normalized.summary
|
|
114
111
|
? { ...normalized.summary, provider }
|
|
115
112
|
: { provider };
|
|
116
|
-
const summary = attachEstimatedCost(
|
|
117
|
-
mergedSummary as LlmContextSummary,
|
|
118
|
-
);
|
|
113
|
+
const summary = attachEstimatedCost(mergedSummary as LlmContextSummary);
|
|
119
114
|
return { ...normalized, summary };
|
|
120
115
|
}
|
|
121
116
|
|
|
@@ -324,57 +319,6 @@ export function conversationQueryRouteDefinitions(
|
|
|
324
319
|
},
|
|
325
320
|
},
|
|
326
321
|
|
|
327
|
-
// ── Permissions config ─────────────────────────────────────────────
|
|
328
|
-
{
|
|
329
|
-
endpoint: "config/permissions/skip",
|
|
330
|
-
method: "GET",
|
|
331
|
-
policyKey: "config/permissions/skip",
|
|
332
|
-
summary: "Get permission-skip flag",
|
|
333
|
-
description: "Return whether dangerouslySkipPermissions is enabled.",
|
|
334
|
-
tags: ["config"],
|
|
335
|
-
responseBody: z.object({
|
|
336
|
-
enabled: z.boolean(),
|
|
337
|
-
}),
|
|
338
|
-
handler: () => {
|
|
339
|
-
const config = getConfig();
|
|
340
|
-
return Response.json({
|
|
341
|
-
enabled: config.permissions.dangerouslySkipPermissions,
|
|
342
|
-
});
|
|
343
|
-
},
|
|
344
|
-
},
|
|
345
|
-
{
|
|
346
|
-
endpoint: "config/permissions/skip",
|
|
347
|
-
method: "PUT",
|
|
348
|
-
policyKey: "config/permissions/skip",
|
|
349
|
-
summary: "Set permission-skip flag",
|
|
350
|
-
description: "Enable or disable dangerouslySkipPermissions.",
|
|
351
|
-
tags: ["config"],
|
|
352
|
-
requestBody: z.object({
|
|
353
|
-
enabled: z.boolean(),
|
|
354
|
-
}),
|
|
355
|
-
handler: async ({ req }) => {
|
|
356
|
-
const body = (await req.json()) as { enabled?: unknown };
|
|
357
|
-
if (typeof body.enabled !== "boolean") {
|
|
358
|
-
return httpError(
|
|
359
|
-
"BAD_REQUEST",
|
|
360
|
-
"Missing or invalid field: enabled (boolean)",
|
|
361
|
-
400,
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
const raw = loadRawConfig();
|
|
365
|
-
const permissions: Record<string, unknown> =
|
|
366
|
-
raw.permissions != null &&
|
|
367
|
-
typeof raw.permissions === "object" &&
|
|
368
|
-
!Array.isArray(raw.permissions)
|
|
369
|
-
? (raw.permissions as Record<string, unknown>)
|
|
370
|
-
: {};
|
|
371
|
-
permissions.dangerouslySkipPermissions = body.enabled;
|
|
372
|
-
raw.permissions = permissions;
|
|
373
|
-
saveRawConfig(raw);
|
|
374
|
-
return Response.json({ enabled: body.enabled });
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
|
|
378
322
|
// ── Full config read ─────────────────────────────────────────────
|
|
379
323
|
{
|
|
380
324
|
endpoint: "config",
|
|
@@ -161,9 +161,9 @@ function handleListConversationStarters(url: URL): Response {
|
|
|
161
161
|
});
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
// No starters — check whether we have memory
|
|
164
|
+
// No starters — check whether we have memory graph nodes to generate from.
|
|
165
165
|
const memoryCount = rawGet<{ c: number }>(
|
|
166
|
-
`SELECT COUNT(*) AS c FROM
|
|
166
|
+
`SELECT COUNT(*) AS c FROM memory_graph_nodes WHERE fidelity != 'gone' AND scope_id = ?`,
|
|
167
167
|
scopeId,
|
|
168
168
|
);
|
|
169
169
|
|
|
@@ -32,7 +32,7 @@ function getDatabaseSizeBytes(): number | null {
|
|
|
32
32
|
function getMemoryItemCount(): number {
|
|
33
33
|
try {
|
|
34
34
|
const rows = rawAll<{ c: number }>(
|
|
35
|
-
"SELECT COUNT(*) AS c FROM
|
|
35
|
+
"SELECT COUNT(*) AS c FROM memory_graph_nodes",
|
|
36
36
|
);
|
|
37
37
|
return rows[0]?.c ?? 0;
|
|
38
38
|
} catch {
|
|
@@ -100,34 +100,36 @@ function searchMemoryItems(query: string, limit: number): GlobalSearchMemory[] {
|
|
|
100
100
|
|
|
101
101
|
interface MemoryRow {
|
|
102
102
|
id: string;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
subject: string;
|
|
103
|
+
type: string;
|
|
104
|
+
content: string;
|
|
106
105
|
confidence: number;
|
|
107
|
-
|
|
106
|
+
last_accessed: number;
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
// Search on both statement and subject for broader recall
|
|
111
109
|
const rows = rawAll<MemoryRow>(
|
|
112
|
-
`SELECT id,
|
|
113
|
-
FROM
|
|
114
|
-
WHERE
|
|
115
|
-
ORDER BY
|
|
110
|
+
`SELECT id, type, content, confidence, last_accessed
|
|
111
|
+
FROM memory_graph_nodes
|
|
112
|
+
WHERE content LIKE ? AND fidelity != 'gone'
|
|
113
|
+
ORDER BY last_accessed DESC
|
|
116
114
|
LIMIT ?`,
|
|
117
115
|
likePattern,
|
|
118
|
-
likePattern,
|
|
119
116
|
limit,
|
|
120
117
|
);
|
|
121
118
|
|
|
122
|
-
return rows.map((r) =>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
119
|
+
return rows.map((r) => {
|
|
120
|
+
const nl = r.content.indexOf("\n");
|
|
121
|
+
const subject = nl >= 0 ? r.content.slice(0, nl) : r.content;
|
|
122
|
+
const statement = nl >= 0 ? r.content.slice(nl + 1) : r.content;
|
|
123
|
+
return {
|
|
124
|
+
id: r.id,
|
|
125
|
+
kind: r.type,
|
|
126
|
+
text: statement,
|
|
127
|
+
subject: subject || null,
|
|
128
|
+
confidence: r.confidence,
|
|
129
|
+
updatedAt: r.last_accessed,
|
|
130
|
+
source: "lexical" as const,
|
|
131
|
+
};
|
|
132
|
+
});
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
async function searchMemoriesSemantic(
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handlers for conversation group management.
|
|
3
|
+
*
|
|
4
|
+
* GET /v1/groups — list all groups
|
|
5
|
+
* POST /v1/groups — create a custom group
|
|
6
|
+
* PATCH /v1/groups/:groupId — update a group
|
|
7
|
+
* DELETE /v1/groups/:groupId — delete a group
|
|
8
|
+
* POST /v1/groups/reorder — reorder groups
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
createGroup,
|
|
15
|
+
deleteGroup,
|
|
16
|
+
getGroup,
|
|
17
|
+
listGroups,
|
|
18
|
+
reorderGroups,
|
|
19
|
+
updateGroup,
|
|
20
|
+
} from "../../memory/group-crud.js";
|
|
21
|
+
import { httpError } from "../http-errors.js";
|
|
22
|
+
import type { RouteDefinition } from "../http-router.js";
|
|
23
|
+
|
|
24
|
+
function serializeGroup(group: ReturnType<typeof getGroup>) {
|
|
25
|
+
if (!group) return null;
|
|
26
|
+
return {
|
|
27
|
+
id: group.id,
|
|
28
|
+
name: group.name,
|
|
29
|
+
sortPosition: group.sortPosition,
|
|
30
|
+
isSystemGroup: group.isSystemGroup,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function groupRouteDefinitions(): RouteDefinition[] {
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
endpoint: "groups",
|
|
38
|
+
method: "GET",
|
|
39
|
+
policyKey: "groups",
|
|
40
|
+
summary: "List groups",
|
|
41
|
+
description: "Return all conversation groups.",
|
|
42
|
+
tags: ["groups"],
|
|
43
|
+
handler: () => {
|
|
44
|
+
const groups = listGroups();
|
|
45
|
+
return Response.json({
|
|
46
|
+
groups: groups.map(serializeGroup),
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
endpoint: "groups",
|
|
52
|
+
method: "POST",
|
|
53
|
+
policyKey: "groups",
|
|
54
|
+
summary: "Create group",
|
|
55
|
+
description:
|
|
56
|
+
"Create a new custom conversation group. Server assigns sort_position.",
|
|
57
|
+
tags: ["groups"],
|
|
58
|
+
requestBody: z.object({
|
|
59
|
+
name: z.string().describe("Group name"),
|
|
60
|
+
}),
|
|
61
|
+
handler: async ({ req }) => {
|
|
62
|
+
const body = (await req.json()) as { name?: string };
|
|
63
|
+
if (!body.name || typeof body.name !== "string") {
|
|
64
|
+
return httpError("BAD_REQUEST", "Missing or invalid name", 400);
|
|
65
|
+
}
|
|
66
|
+
const group = createGroup(body.name);
|
|
67
|
+
return Response.json(serializeGroup(group), { status: 201 });
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
endpoint: "groups/:groupId",
|
|
72
|
+
method: "PATCH",
|
|
73
|
+
policyKey: "groups",
|
|
74
|
+
summary: "Update group",
|
|
75
|
+
description: "Update a conversation group's name or sort position.",
|
|
76
|
+
tags: ["groups"],
|
|
77
|
+
requestBody: z.object({
|
|
78
|
+
name: z.string().optional(),
|
|
79
|
+
sortPosition: z.number().optional(),
|
|
80
|
+
}),
|
|
81
|
+
handler: async ({ req, params }) => {
|
|
82
|
+
const groupId = params.groupId;
|
|
83
|
+
const existing = getGroup(groupId);
|
|
84
|
+
if (!existing) {
|
|
85
|
+
return httpError("NOT_FOUND", "Group not found", 404);
|
|
86
|
+
}
|
|
87
|
+
const body = (await req.json()) as {
|
|
88
|
+
name?: string;
|
|
89
|
+
sortPosition?: number;
|
|
90
|
+
};
|
|
91
|
+
if (body.name !== undefined && typeof body.name !== "string") {
|
|
92
|
+
return httpError("BAD_REQUEST", "name must be a string", 400);
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
body.sortPosition !== undefined &&
|
|
96
|
+
typeof body.sortPosition !== "number"
|
|
97
|
+
) {
|
|
98
|
+
return httpError("BAD_REQUEST", "sortPosition must be a number", 400);
|
|
99
|
+
}
|
|
100
|
+
// System groups allow name changes but block sortPosition/delete.
|
|
101
|
+
if (existing.isSystemGroup && body.sortPosition !== undefined) {
|
|
102
|
+
return httpError(
|
|
103
|
+
"FORBIDDEN",
|
|
104
|
+
"System group sort position cannot be changed",
|
|
105
|
+
403,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
// Custom group sort_position must be >= 3
|
|
109
|
+
if (
|
|
110
|
+
body.sortPosition !== undefined &&
|
|
111
|
+
(typeof body.sortPosition !== "number" ||
|
|
112
|
+
!isFinite(body.sortPosition) ||
|
|
113
|
+
body.sortPosition < 3)
|
|
114
|
+
) {
|
|
115
|
+
return httpError(
|
|
116
|
+
"BAD_REQUEST",
|
|
117
|
+
"Custom group sort_position must be >= 3",
|
|
118
|
+
400,
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const updated = updateGroup(groupId, {
|
|
122
|
+
name: body.name,
|
|
123
|
+
sortPosition: body.sortPosition,
|
|
124
|
+
});
|
|
125
|
+
if (!updated) {
|
|
126
|
+
return httpError("NOT_FOUND", "Group not found", 404);
|
|
127
|
+
}
|
|
128
|
+
return Response.json(serializeGroup(updated));
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
endpoint: "groups/:groupId",
|
|
133
|
+
method: "DELETE",
|
|
134
|
+
policyKey: "groups",
|
|
135
|
+
summary: "Delete group",
|
|
136
|
+
description: "Delete a custom conversation group.",
|
|
137
|
+
tags: ["groups"],
|
|
138
|
+
handler: ({ params }) => {
|
|
139
|
+
const groupId = params.groupId;
|
|
140
|
+
const existing = getGroup(groupId);
|
|
141
|
+
if (!existing) {
|
|
142
|
+
return httpError("NOT_FOUND", "Group not found", 404);
|
|
143
|
+
}
|
|
144
|
+
// System groups cannot be deleted
|
|
145
|
+
if (existing.isSystemGroup) {
|
|
146
|
+
return httpError("FORBIDDEN", "System groups cannot be deleted", 403);
|
|
147
|
+
}
|
|
148
|
+
deleteGroup(groupId);
|
|
149
|
+
return new Response(null, { status: 204 });
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
endpoint: "groups/reorder",
|
|
154
|
+
method: "POST",
|
|
155
|
+
policyKey: "groups/reorder",
|
|
156
|
+
summary: "Reorder groups",
|
|
157
|
+
description: "Batch-update sort positions for conversation groups.",
|
|
158
|
+
tags: ["groups"],
|
|
159
|
+
requestBody: z.object({
|
|
160
|
+
updates: z
|
|
161
|
+
.array(
|
|
162
|
+
z.object({
|
|
163
|
+
groupId: z.string(),
|
|
164
|
+
sortPosition: z.number(),
|
|
165
|
+
}),
|
|
166
|
+
)
|
|
167
|
+
.describe("Array of { groupId, sortPosition } objects"),
|
|
168
|
+
}),
|
|
169
|
+
handler: async ({ req }) => {
|
|
170
|
+
const body = (await req.json()) as {
|
|
171
|
+
updates?: Array<{
|
|
172
|
+
groupId: string;
|
|
173
|
+
sortPosition: number;
|
|
174
|
+
}>;
|
|
175
|
+
};
|
|
176
|
+
if (!Array.isArray(body.updates)) {
|
|
177
|
+
return httpError("BAD_REQUEST", "Missing updates array", 400);
|
|
178
|
+
}
|
|
179
|
+
// Validate: no system group reordering, no sort_position < 3 for custom groups
|
|
180
|
+
for (const update of body.updates) {
|
|
181
|
+
const group = getGroup(update.groupId);
|
|
182
|
+
if (!group) continue;
|
|
183
|
+
if (group.isSystemGroup) {
|
|
184
|
+
return httpError(
|
|
185
|
+
"FORBIDDEN",
|
|
186
|
+
`Cannot reorder system group: ${update.groupId}`,
|
|
187
|
+
403,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
if (
|
|
191
|
+
typeof update.sortPosition !== "number" ||
|
|
192
|
+
!isFinite(update.sortPosition) ||
|
|
193
|
+
update.sortPosition < 3
|
|
194
|
+
) {
|
|
195
|
+
return httpError(
|
|
196
|
+
"BAD_REQUEST",
|
|
197
|
+
`Custom group sort_position must be >= 3 (got ${update.sortPosition} for ${update.groupId})`,
|
|
198
|
+
400,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
reorderGroups(body.updates);
|
|
203
|
+
return Response.json({ ok: true });
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
}
|
|
@@ -23,7 +23,10 @@ import { requireBoundGuardian } from "../auth/require-bound-guardian.js";
|
|
|
23
23
|
import type { AuthContext } from "../auth/types.js";
|
|
24
24
|
import { processGuardianDecision } from "../guardian-action-service.js";
|
|
25
25
|
import type { GuardianDecisionPrompt } from "../guardian-decision-types.js";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
buildDecisionActions,
|
|
28
|
+
GUARDIAN_DECISION_ACTIONS,
|
|
29
|
+
} from "../guardian-decision-types.js";
|
|
27
30
|
import { httpError } from "../http-errors.js";
|
|
28
31
|
import type { RouteDefinition } from "../http-router.js";
|
|
29
32
|
|
|
@@ -190,13 +193,15 @@ export function listGuardianDecisionPrompts(params: {
|
|
|
190
193
|
* Map a canonical guardian request to the client-facing prompt format.
|
|
191
194
|
*
|
|
192
195
|
* Generates kind-specific questionText and action sets:
|
|
193
|
-
* - `tool_approval`:
|
|
194
|
-
* - `pending_question`:
|
|
195
|
-
* - `access_request`:
|
|
196
|
-
*
|
|
196
|
+
* - `tool_approval`: temporal modes (approve_once, approve_10m, approve_conversation) + reject
|
|
197
|
+
* - `pending_question`: approve_once + reject only
|
|
198
|
+
* - `access_request`: approve_once + reject only, with text fallback instructions
|
|
199
|
+
* (request code + "open invite flow")
|
|
200
|
+
* - `tool_grant_request`: approve_once + reject only
|
|
197
201
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
202
|
+
* Only `tool_approval` receives temporal modes because time-scoped grants
|
|
203
|
+
* are meaningful only for tool execution. All other kinds get a simple
|
|
204
|
+
* approve_once/reject pair.
|
|
200
205
|
*/
|
|
201
206
|
function mapCanonicalRequestToPrompt(
|
|
202
207
|
req: CanonicalGuardianRequest,
|
|
@@ -204,9 +209,15 @@ function mapCanonicalRequestToPrompt(
|
|
|
204
209
|
): GuardianDecisionPrompt {
|
|
205
210
|
const questionText = buildKindAwareQuestionText(req);
|
|
206
211
|
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
const actions =
|
|
212
|
+
// Only tool_approval gets temporal modes (approve_10m, approve_conversation);
|
|
213
|
+
// all other kinds get a simple approve_once + reject pair.
|
|
214
|
+
const actions =
|
|
215
|
+
req.kind === "tool_approval"
|
|
216
|
+
? buildDecisionActions({ forGuardianOnBehalf: true })
|
|
217
|
+
: [
|
|
218
|
+
GUARDIAN_DECISION_ACTIONS.approve_once,
|
|
219
|
+
GUARDIAN_DECISION_ACTIONS.reject,
|
|
220
|
+
];
|
|
210
221
|
|
|
211
222
|
const expiresAt = req.expiresAt
|
|
212
223
|
? new Date(req.expiresAt).getTime()
|
|
@@ -19,7 +19,7 @@ import { getLogger } from "../../util/logger.js";
|
|
|
19
19
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
|
|
20
20
|
import { mintCredentialPair } from "../auth/credential-service.js";
|
|
21
21
|
import { httpError } from "../http-errors.js";
|
|
22
|
-
import { isPrivateAddress } from "../middleware/auth.js";
|
|
22
|
+
import { isLoopbackAddress, isPrivateAddress } from "../middleware/auth.js";
|
|
23
23
|
|
|
24
24
|
/** Bun server shape needed for requestIP -- avoids importing the full Bun type. */
|
|
25
25
|
type ServerWithRequestIP = {
|
|
@@ -87,30 +87,34 @@ export async function handleGuardianBootstrap(
|
|
|
87
87
|
req: Request,
|
|
88
88
|
server: ServerWithRequestIP,
|
|
89
89
|
): Promise<Response> {
|
|
90
|
-
//
|
|
90
|
+
// In non-containerized (bare-metal) mode, restrict to loopback only —
|
|
91
|
+
// the runtime binds to localhost and LAN peers should not be able to
|
|
92
|
+
// bootstrap even if they somehow reach the endpoint.
|
|
93
|
+
// In containerized (Docker) mode, accept any private-network peer because
|
|
94
|
+
// the gateway connects over the Docker bridge (e.g. 172.17.0.1) and the
|
|
95
|
+
// GUARDIAN_BOOTSTRAP_SECRET enforced at the gateway layer provides the
|
|
96
|
+
// real authentication.
|
|
91
97
|
const peerIp = server.requestIP(req)?.address;
|
|
92
|
-
|
|
98
|
+
const containerized = getIsContainerized();
|
|
99
|
+
const peerAllowed = containerized
|
|
100
|
+
? isPrivateAddress(peerIp ?? "")
|
|
101
|
+
: isLoopbackAddress(peerIp ?? "");
|
|
102
|
+
if (!peerAllowed && !isHttpAuthDisabled()) {
|
|
93
103
|
return httpError("FORBIDDEN", "Bootstrap endpoint is local-only", 403);
|
|
94
104
|
}
|
|
95
105
|
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
//
|
|
106
|
+
// In non-containerized mode, any x-forwarded-for header means the request
|
|
107
|
+
// came through the gateway from a non-loopback client. Legitimate bare-metal
|
|
108
|
+
// bootstrap clients connect from localhost; the gateway does not inject
|
|
109
|
+
// x-forwarded-for for loopback peers (see gateway/src/index.ts). Reject
|
|
110
|
+
// forwarded requests to prevent LAN-adjacent clients from bootstrapping.
|
|
100
111
|
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
// not meaningful for local-only enforcement in this topology.
|
|
112
|
+
// In containerized mode, skip this check: the peer IP was already validated
|
|
113
|
+
// above (Docker bridge network = private), and the x-forwarded-for header
|
|
114
|
+
// reflects the original external client which is not meaningful for
|
|
115
|
+
// local-only enforcement in this topology.
|
|
106
116
|
const forwarded = req.headers.get("x-forwarded-for");
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
forwardedIp &&
|
|
110
|
-
!isPrivateAddress(forwardedIp) &&
|
|
111
|
-
!isHttpAuthDisabled() &&
|
|
112
|
-
!getIsContainerized()
|
|
113
|
-
) {
|
|
117
|
+
if (forwarded && !isHttpAuthDisabled() && !getIsContainerized()) {
|
|
114
118
|
return httpError("FORBIDDEN", "Bootstrap endpoint is local-only", 403);
|
|
115
119
|
}
|
|
116
120
|
|
|
@@ -44,6 +44,7 @@ import { processChannelMessageInBackground } from "./inbound-stages/background-d
|
|
|
44
44
|
import { handleBootstrapIntercept } from "./inbound-stages/bootstrap-intercept.js";
|
|
45
45
|
import { handleEditIntercept } from "./inbound-stages/edit-intercept.js";
|
|
46
46
|
import { handleEscalationIntercept } from "./inbound-stages/escalation-intercept.js";
|
|
47
|
+
import { handleGuardianActivationIntercept } from "./inbound-stages/guardian-activation-intercept.js";
|
|
47
48
|
import { handleGuardianReplyIntercept } from "./inbound-stages/guardian-reply-intercept.js";
|
|
48
49
|
import { runSecretIngressCheck } from "./inbound-stages/secret-ingress-check.js";
|
|
49
50
|
import { tryTranscribeAudioAttachments } from "./inbound-stages/transcribe-audio.js";
|
|
@@ -199,6 +200,24 @@ export async function handleChannelInbound(
|
|
|
199
200
|
// ACL deny path rather than bypassing it.
|
|
200
201
|
const hasSenderIdentityClaim = rawSenderId !== undefined;
|
|
201
202
|
|
|
203
|
+
// ── Guardian channel activation ──
|
|
204
|
+
// When a bare /start arrives on a channel with no guardian, auto-initiate
|
|
205
|
+
// guardian verification so the first user can claim the channel.
|
|
206
|
+
const guardianActivationResponse = await handleGuardianActivationIntercept({
|
|
207
|
+
sourceChannel,
|
|
208
|
+
conversationExternalId,
|
|
209
|
+
rawSenderId,
|
|
210
|
+
canonicalSenderId,
|
|
211
|
+
actorDisplayName: body.actorDisplayName,
|
|
212
|
+
actorUsername: body.actorUsername,
|
|
213
|
+
sourceMetadata: body.sourceMetadata,
|
|
214
|
+
replyCallbackUrl: body.replyCallbackUrl,
|
|
215
|
+
mintBearerToken,
|
|
216
|
+
assistantId,
|
|
217
|
+
externalMessageId,
|
|
218
|
+
});
|
|
219
|
+
if (guardianActivationResponse) return guardianActivationResponse;
|
|
220
|
+
|
|
202
221
|
// ── Ingress ACL enforcement ──
|
|
203
222
|
const aclResult = await enforceIngressAcl({
|
|
204
223
|
canonicalSenderId,
|
|
@@ -15,6 +15,7 @@ import * as deliveryCrud from "../../../memory/delivery-crud.js";
|
|
|
15
15
|
import * as deliveryStatus from "../../../memory/delivery-status.js";
|
|
16
16
|
import {
|
|
17
17
|
extractChannelFromCallbackUrl,
|
|
18
|
+
extractMessageTsFromCallbackUrl,
|
|
18
19
|
extractThreadTsFromCallbackUrl,
|
|
19
20
|
setThreadTs,
|
|
20
21
|
} from "../../../memory/slack-thread-store.js";
|
|
@@ -328,9 +329,49 @@ export function setSlackThinkingStatus(
|
|
|
328
329
|
// the correct thread for the Assistants API status.
|
|
329
330
|
const threadTs = extractThreadTsFromCallbackUrl(callbackUrl);
|
|
330
331
|
|
|
331
|
-
//
|
|
332
|
+
// For non-threaded DMs, fall back to emoji reaction on the original message.
|
|
332
333
|
if (!threadTs) {
|
|
333
|
-
|
|
334
|
+
const messageTs = extractMessageTsFromCallbackUrl(callbackUrl);
|
|
335
|
+
if (!messageTs) return () => {};
|
|
336
|
+
|
|
337
|
+
const addPromise = deliverChannelReply(
|
|
338
|
+
callbackUrl,
|
|
339
|
+
{
|
|
340
|
+
chatId,
|
|
341
|
+
assistantId,
|
|
342
|
+
reaction: { action: "add", name: "eyes", messageTs },
|
|
343
|
+
},
|
|
344
|
+
mintBearerToken(),
|
|
345
|
+
).catch((err) => {
|
|
346
|
+
log.debug({ err, chatId, messageTs }, "Failed to add Slack eyes reaction");
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
const clearReaction = () => {
|
|
350
|
+
if (cleared) return;
|
|
351
|
+
cleared = true;
|
|
352
|
+
clearTimeout(safetyTimer);
|
|
353
|
+
void addPromise.then(() =>
|
|
354
|
+
deliverChannelReply(
|
|
355
|
+
callbackUrl,
|
|
356
|
+
{
|
|
357
|
+
chatId,
|
|
358
|
+
assistantId,
|
|
359
|
+
reaction: { action: "remove", name: "eyes", messageTs },
|
|
360
|
+
},
|
|
361
|
+
mintBearerToken(),
|
|
362
|
+
).catch((err) => {
|
|
363
|
+
log.debug(
|
|
364
|
+
{ err, chatId, messageTs },
|
|
365
|
+
"Failed to remove Slack eyes reaction",
|
|
366
|
+
);
|
|
367
|
+
}),
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
const safetyTimer = setTimeout(clearReaction, SLACK_THINKING_MAX_DURATION_MS);
|
|
372
|
+
(safetyTimer as { unref?: () => void }).unref?.();
|
|
373
|
+
|
|
374
|
+
return clearReaction;
|
|
334
375
|
}
|
|
335
376
|
|
|
336
377
|
// Track the set promise so clear waits for it to settle first,
|