@vellumai/assistant 0.5.16 → 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 +1 -1
- package/Dockerfile +0 -3
- package/knip.json +2 -1
- package/openapi.yaml +660 -80
- 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 +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 +25 -3
- package/src/__tests__/clawhub.test.ts +54 -24
- package/src/__tests__/cli-command-risk-guard.test.ts +14 -0
- package/src/__tests__/cli-memory.test.ts +74 -69
- package/src/__tests__/config-schema.test.ts +1 -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 +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-starter-routes.test.ts +20 -11
- package/src/__tests__/conversation-store.test.ts +2 -6
- package/src/__tests__/conversation-usage.test.ts +2 -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 +2 -0
- 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__/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__/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 +2 -6
- package/src/__tests__/managed-store.test.ts +38 -11
- 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__/non-member-access-request.test.ts +2 -6
- 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__/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__/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__/provider-error-scenarios.test.ts +21 -0
- 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 -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__/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-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__/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 +11 -11
- package/src/__tests__/skill-memory.test.ts +140 -98
- 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__/task-compiler.test.ts +2 -6
- package/src/__tests__/task-management-tools.test.ts +2 -6
- package/src/__tests__/task-memory-cleanup.test.ts +173 -229
- package/src/__tests__/task-runner.test.ts +2 -6
- package/src/__tests__/task-scheduler.test.ts +2 -6
- package/src/__tests__/test-preload.ts +3 -0
- package/src/__tests__/tool-approval-handler.test.ts +2 -6
- package/src/__tests__/tool-grant-request-escalation.test.ts +2 -6
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +276 -0
- 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 +2 -6
- 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-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 +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 -2
- package/src/cli/cli-memory.ts +67 -64
- 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__/status.test.ts +2 -2
- package/src/cli/commands/oauth/connect.ts +11 -6
- 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/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/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 +10 -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/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 +21 -124
- package/src/config/schemas/platform.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 +6 -2
- package/src/credential-execution/process-manager.ts +3 -1
- 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 +96 -61
- 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-runtime-assembly.ts +5 -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 +416 -202
- package/src/daemon/lifecycle.ts +40 -1
- package/src/daemon/main.ts +5 -1
- package/src/daemon/message-types/conversations.ts +4 -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 +5 -0
- package/src/daemon/server.ts +11 -2
- package/src/daemon/tool-side-effects.ts +27 -5
- 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 +30 -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.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/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 +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 +4 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/qdrant-client.ts +44 -17
- package/src/memory/schema/index.ts +1 -0
- package/src/memory/schema/memory-graph.ts +139 -0
- package/src/memory/search/semantic.ts +47 -91
- package/src/memory/task-memory-cleanup.ts +28 -50
- 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 +9 -0
- package/src/notifications/signal.ts +16 -0
- package/src/oauth/seed-providers.ts +2 -1
- package/src/permissions/checker.ts +24 -3
- package/src/permissions/defaults.ts +4 -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 +3 -29
- 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/route-policy.ts +7 -0
- package/src/runtime/guardian-reply-router.ts +5 -1
- 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-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/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 -14
- package/src/runtime/routes/memory-item-routes.ts +341 -388
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/skills-routes.ts +103 -37
- package/src/runtime/routes/work-items-routes.test.ts +2 -6
- package/src/schedule/scheduler.ts +8 -1
- 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 +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 +152 -77
- 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 -1
- package/src/tools/shared/filesystem/image-read.ts +22 -85
- 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/watcher/providers/outlook-calendar.ts +343 -0
- package/src/watcher/providers/outlook.ts +198 -0
- 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 -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
|
@@ -28,6 +28,12 @@ export interface OutlookItemBody {
|
|
|
28
28
|
content: string;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/** Internet message header (e.g. List-Unsubscribe, X-Mailer) */
|
|
32
|
+
export interface OutlookInternetMessageHeader {
|
|
33
|
+
name: string;
|
|
34
|
+
value: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
31
37
|
/** Full Outlook message from Microsoft Graph */
|
|
32
38
|
export interface OutlookMessage {
|
|
33
39
|
id: string;
|
|
@@ -46,6 +52,7 @@ export interface OutlookMessage {
|
|
|
46
52
|
flag: {
|
|
47
53
|
flagStatus: "notFlagged" | "flagged" | "complete";
|
|
48
54
|
};
|
|
55
|
+
internetMessageHeaders?: OutlookInternetMessageHeader[];
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
/** Outlook mail folder */
|
|
@@ -75,9 +82,120 @@ export interface OutlookSendMessagePayload {
|
|
|
75
82
|
saveToSentItems?: boolean;
|
|
76
83
|
}
|
|
77
84
|
|
|
85
|
+
/** Draft message for creating in Drafts folder */
|
|
86
|
+
export interface OutlookDraftMessage {
|
|
87
|
+
subject: string;
|
|
88
|
+
body: OutlookItemBody;
|
|
89
|
+
toRecipients?: OutlookRecipient[];
|
|
90
|
+
ccRecipients?: OutlookRecipient[];
|
|
91
|
+
bccRecipients?: OutlookRecipient[];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Forward message payload (Graph API's /createForward returns a draft) */
|
|
95
|
+
export interface OutlookForwardMessage {
|
|
96
|
+
toRecipients: OutlookRecipient[];
|
|
97
|
+
comment?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
78
100
|
/** Microsoft Graph user profile */
|
|
79
101
|
export interface OutlookUserProfile {
|
|
80
102
|
displayName: string;
|
|
81
103
|
mail: string;
|
|
82
104
|
userPrincipalName: string;
|
|
83
105
|
}
|
|
106
|
+
|
|
107
|
+
/** Outlook attachment metadata */
|
|
108
|
+
export interface OutlookAttachment {
|
|
109
|
+
id: string;
|
|
110
|
+
name: string;
|
|
111
|
+
contentType: string;
|
|
112
|
+
size: number;
|
|
113
|
+
isInline: boolean;
|
|
114
|
+
"@odata.type"?: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Outlook file attachment with base64-encoded content */
|
|
118
|
+
export interface OutlookFileAttachment extends OutlookAttachment {
|
|
119
|
+
contentBytes: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Outlook attachment list response (paginated) */
|
|
123
|
+
export interface OutlookAttachmentListResponse {
|
|
124
|
+
value?: OutlookAttachment[];
|
|
125
|
+
"@odata.nextLink"?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Outlook message flag with optional due/start dates */
|
|
129
|
+
export interface OutlookMessageFlag {
|
|
130
|
+
flagStatus: "notFlagged" | "flagged" | "complete";
|
|
131
|
+
dueDateTime?: { dateTime: string; timeZone: string };
|
|
132
|
+
startDateTime?: { dateTime: string; timeZone: string };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Outlook master category */
|
|
136
|
+
export interface OutlookMasterCategory {
|
|
137
|
+
displayName: string;
|
|
138
|
+
color: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Outlook master category list response */
|
|
142
|
+
export interface OutlookMasterCategoryListResponse {
|
|
143
|
+
value?: OutlookMasterCategory[];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Predicates for matching messages in a mail rule */
|
|
147
|
+
export interface OutlookMessageRulePredicates {
|
|
148
|
+
senderContains?: string[];
|
|
149
|
+
subjectContains?: string[];
|
|
150
|
+
bodyContains?: string[];
|
|
151
|
+
fromAddresses?: OutlookRecipient[];
|
|
152
|
+
hasAttachments?: boolean;
|
|
153
|
+
importance?: "low" | "normal" | "high";
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Actions to take when a mail rule matches */
|
|
157
|
+
export interface OutlookMessageRuleActions {
|
|
158
|
+
moveToFolder?: string;
|
|
159
|
+
delete?: boolean;
|
|
160
|
+
stopProcessingRules?: boolean;
|
|
161
|
+
markAsRead?: boolean;
|
|
162
|
+
forwardTo?: OutlookRecipient[];
|
|
163
|
+
markImportance?: "low" | "normal" | "high";
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** A mail rule for inbox message processing */
|
|
167
|
+
export interface OutlookMessageRule {
|
|
168
|
+
id?: string;
|
|
169
|
+
displayName: string;
|
|
170
|
+
sequence: number;
|
|
171
|
+
isEnabled: boolean;
|
|
172
|
+
conditions?: OutlookMessageRulePredicates;
|
|
173
|
+
actions?: OutlookMessageRuleActions;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Response from listing mail rules */
|
|
177
|
+
export interface OutlookMessageRuleListResponse {
|
|
178
|
+
value?: OutlookMessageRule[];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Automatic reply (out-of-office) settings */
|
|
182
|
+
export interface OutlookAutoReplySettings {
|
|
183
|
+
status: "disabled" | "alwaysEnabled" | "scheduled";
|
|
184
|
+
externalAudience: "none" | "contactsOnly" | "all";
|
|
185
|
+
internalReplyMessage?: string;
|
|
186
|
+
externalReplyMessage?: string;
|
|
187
|
+
scheduledStartDateTime?: { dateTime: string; timeZone: string };
|
|
188
|
+
scheduledEndDateTime?: { dateTime: string; timeZone: string };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Mailbox settings containing automatic replies configuration */
|
|
192
|
+
export interface OutlookMailboxSettings {
|
|
193
|
+
automaticRepliesSetting?: OutlookAutoReplySettings;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Delta query response with pagination support */
|
|
197
|
+
export interface OutlookDeltaResponse<T> {
|
|
198
|
+
value?: T[];
|
|
199
|
+
"@odata.deltaLink"?: string;
|
|
200
|
+
"@odata.nextLink"?: string;
|
|
201
|
+
}
|
|
@@ -353,6 +353,15 @@ const TEMPLATES: Partial<Record<NotificationSourceEventName, CopyTemplate>> = {
|
|
|
353
353
|
};
|
|
354
354
|
},
|
|
355
355
|
|
|
356
|
+
"guardian.channel_activation": (payload) => {
|
|
357
|
+
const code = str(payload.verificationCode, "------");
|
|
358
|
+
const channel = str(payload.sourceChannel, "a channel");
|
|
359
|
+
return {
|
|
360
|
+
title: "Guardian Verification Code",
|
|
361
|
+
body: `Your ${channel} verification code is: ${code}\n\nEnter this code in your ${channel} chat to verify your identity as guardian.`,
|
|
362
|
+
};
|
|
363
|
+
},
|
|
364
|
+
|
|
356
365
|
"ingress.access_request": (payload) => ({
|
|
357
366
|
title: "Access Request",
|
|
358
367
|
body: buildAccessRequestContractText(payload),
|
|
@@ -46,6 +46,11 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
46
46
|
id: "guardian.question",
|
|
47
47
|
description: "Guardian approval question requiring response",
|
|
48
48
|
},
|
|
49
|
+
{
|
|
50
|
+
id: "guardian.channel_activation",
|
|
51
|
+
description:
|
|
52
|
+
"Guardian channel activation code delivered for /start verification",
|
|
53
|
+
},
|
|
49
54
|
{ id: "ingress.access_request", description: "Non-member requesting access" },
|
|
50
55
|
{
|
|
51
56
|
id: "ingress.access_request.callback_handoff",
|
|
@@ -155,9 +160,20 @@ export interface AccessRequestContextPayload {
|
|
|
155
160
|
messagePreview: string | null;
|
|
156
161
|
}
|
|
157
162
|
|
|
163
|
+
export interface GuardianChannelActivationPayload {
|
|
164
|
+
verificationCode: string;
|
|
165
|
+
sourceChannel: string;
|
|
166
|
+
actorExternalId: string;
|
|
167
|
+
actorDisplayName: string | null;
|
|
168
|
+
actorUsername: string | null;
|
|
169
|
+
sessionId: string;
|
|
170
|
+
expiresAt: number;
|
|
171
|
+
}
|
|
172
|
+
|
|
158
173
|
export interface NotificationEventContextPayloadMap {
|
|
159
174
|
"guardian.question": GuardianQuestionPayload;
|
|
160
175
|
"ingress.access_request": AccessRequestContextPayload;
|
|
176
|
+
"guardian.channel_activation": GuardianChannelActivationPayload;
|
|
161
177
|
}
|
|
162
178
|
|
|
163
179
|
export type NotificationContextPayload<TEventName extends string = string> =
|
|
@@ -90,6 +90,7 @@ const PROVIDER_SEED_DATA: Record<
|
|
|
90
90
|
forbiddenScopes: [],
|
|
91
91
|
},
|
|
92
92
|
extraParams: { access_type: "offline", prompt: "consent" },
|
|
93
|
+
loopbackPort: 17321,
|
|
93
94
|
managedServiceConfigKey: "google-oauth",
|
|
94
95
|
injectionTemplates: [
|
|
95
96
|
{
|
|
@@ -619,6 +620,7 @@ const PROVIDER_SEED_DATA: Record<
|
|
|
619
620
|
"Mail.Send",
|
|
620
621
|
"Calendars.Read",
|
|
621
622
|
"Calendars.ReadWrite",
|
|
623
|
+
"MailboxSettings.ReadWrite",
|
|
622
624
|
],
|
|
623
625
|
scopePolicy: {
|
|
624
626
|
allowAdditionalScopes: true,
|
|
@@ -640,7 +642,6 @@ const PROVIDER_SEED_DATA: Record<
|
|
|
640
642
|
appType: "App registration",
|
|
641
643
|
identityUrl: "https://graph.microsoft.com/v1.0/me",
|
|
642
644
|
identityResponsePaths: ["mail", "userPrincipalName"],
|
|
643
|
-
featureFlag: "outlook-oauth-integration",
|
|
644
645
|
},
|
|
645
646
|
|
|
646
647
|
// Manual-token providers: these don't use OAuth2 flows but need provider
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
|
|
5
5
|
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
6
6
|
import { getConfig } from "../config/loader.js";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
looksLikePathOnlyInput,
|
|
20
20
|
} from "../tools/network/url-safety.js";
|
|
21
21
|
import { getTool } from "../tools/registry.js";
|
|
22
|
-
import { getWorkspaceHooksDir } from "../util/platform.js";
|
|
22
|
+
import { getDeprecatedDir, getWorkspaceHooksDir } from "../util/platform.js";
|
|
23
23
|
import {
|
|
24
24
|
buildShellAllowlistOptions,
|
|
25
25
|
buildShellCommandCandidates,
|
|
@@ -703,7 +703,13 @@ async function classifyRiskUncached(
|
|
|
703
703
|
preParsed?: ParsedCommand,
|
|
704
704
|
manifestOverride?: ManifestOverride,
|
|
705
705
|
): Promise<RiskLevel> {
|
|
706
|
-
if (toolName === "file_read")
|
|
706
|
+
if (toolName === "file_read") {
|
|
707
|
+
const filePath = getStringField(input, "path", "file_path");
|
|
708
|
+
if (isActorTokenSigningKeyPath(filePath, workingDir)) {
|
|
709
|
+
return RiskLevel.High;
|
|
710
|
+
}
|
|
711
|
+
return RiskLevel.Low;
|
|
712
|
+
}
|
|
707
713
|
if (toolName === "file_write" || toolName === "file_edit") {
|
|
708
714
|
const filePath = getStringField(input, "path", "file_path");
|
|
709
715
|
if (
|
|
@@ -937,6 +943,21 @@ async function classifyRiskUncached(
|
|
|
937
943
|
return RiskLevel.Medium;
|
|
938
944
|
}
|
|
939
945
|
|
|
946
|
+
function isActorTokenSigningKeyPath(
|
|
947
|
+
filePath: string | undefined,
|
|
948
|
+
workingDir?: string,
|
|
949
|
+
): boolean {
|
|
950
|
+
if (!filePath) return false;
|
|
951
|
+
const cwd = workingDir ?? process.cwd();
|
|
952
|
+
const resolvedPath = resolve(cwd, filePath);
|
|
953
|
+
const signingKeyPaths = [
|
|
954
|
+
join(homedir(), ".vellum", "protected", "actor-token-signing-key"),
|
|
955
|
+
join(getDeprecatedDir(), "actor-token-signing-key"),
|
|
956
|
+
resolve(cwd, "deprecated", "actor-token-signing-key"),
|
|
957
|
+
];
|
|
958
|
+
return signingKeyPaths.includes(resolvedPath);
|
|
959
|
+
}
|
|
960
|
+
|
|
940
961
|
export async function check(
|
|
941
962
|
toolName: string,
|
|
942
963
|
input: Record<string, unknown>,
|
|
@@ -287,11 +287,11 @@ export function getDefaultRuleTemplates(): DefaultRuleTemplate[] {
|
|
|
287
287
|
}),
|
|
288
288
|
);
|
|
289
289
|
|
|
290
|
-
//
|
|
290
|
+
// recall is a read-only tool — always allow without prompting.
|
|
291
291
|
const memoryRecallRule: DefaultRuleTemplate = {
|
|
292
|
-
id: "default:allow-
|
|
293
|
-
tool: "
|
|
294
|
-
pattern: "
|
|
292
|
+
id: "default:allow-recall-global",
|
|
293
|
+
tool: "recall",
|
|
294
|
+
pattern: "recall:*",
|
|
295
295
|
scope: "everywhere",
|
|
296
296
|
decision: "allow",
|
|
297
297
|
priority: 100,
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compile all active playbook
|
|
2
|
+
* Compile all active playbook graph nodes into a triage context block
|
|
3
3
|
* that can be injected into the system prompt alongside the contact
|
|
4
4
|
* graph.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { and,
|
|
7
|
+
import { and, eq, sql } from "drizzle-orm";
|
|
8
8
|
|
|
9
9
|
import { getDb } from "../memory/db.js";
|
|
10
|
-
import {
|
|
10
|
+
import { memoryGraphNodes } from "../memory/schema.js";
|
|
11
11
|
import type { Playbook } from "./types.js";
|
|
12
12
|
import { parsePlaybookStatement } from "./types.js";
|
|
13
13
|
|
|
14
14
|
export interface CompiledPlaybooks {
|
|
15
15
|
/** Formatted text block ready for system prompt injection. */
|
|
16
16
|
text: string;
|
|
17
|
-
/** Total number of active playbook
|
|
17
|
+
/** Total number of active playbook nodes found. */
|
|
18
18
|
totalCount: number;
|
|
19
19
|
/** Number of playbooks successfully parsed and included. */
|
|
20
20
|
includedCount: number;
|
|
@@ -26,8 +26,7 @@ export interface CompilePlaybooksOptions {
|
|
|
26
26
|
|
|
27
27
|
interface PlaybookRow {
|
|
28
28
|
id: string;
|
|
29
|
-
|
|
30
|
-
statement: string;
|
|
29
|
+
content: string;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
export function compilePlaybooks(
|
|
@@ -38,31 +37,33 @@ export function compilePlaybooks(
|
|
|
38
37
|
|
|
39
38
|
const rows: PlaybookRow[] = db
|
|
40
39
|
.select({
|
|
41
|
-
id:
|
|
42
|
-
|
|
43
|
-
statement: memoryItems.statement,
|
|
40
|
+
id: memoryGraphNodes.id,
|
|
41
|
+
content: memoryGraphNodes.content,
|
|
44
42
|
})
|
|
45
|
-
.from(
|
|
43
|
+
.from(memoryGraphNodes)
|
|
46
44
|
.where(
|
|
47
45
|
and(
|
|
48
|
-
eq(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
isNull(memoryItems.invalidAt),
|
|
46
|
+
eq(memoryGraphNodes.scopeId, scopeId),
|
|
47
|
+
sql`${memoryGraphNodes.sourceConversations} LIKE '%playbook:%'`,
|
|
48
|
+
sql`${memoryGraphNodes.fidelity} != 'gone'`,
|
|
52
49
|
),
|
|
53
50
|
)
|
|
54
|
-
.orderBy(
|
|
51
|
+
.orderBy(sql`${memoryGraphNodes.significance} DESC`)
|
|
55
52
|
.all();
|
|
56
53
|
|
|
57
54
|
if (rows.length === 0) {
|
|
58
55
|
return { text: "", totalCount: 0, includedCount: 0 };
|
|
59
56
|
}
|
|
60
57
|
|
|
61
|
-
const parsed: Array<{ id: string;
|
|
58
|
+
const parsed: Array<{ id: string; playbook: Playbook }> = [];
|
|
62
59
|
for (const row of rows) {
|
|
63
|
-
|
|
60
|
+
// Content format: "Playbook: <trigger>\n<json statement>"
|
|
61
|
+
const newlineIdx = row.content.indexOf("\n");
|
|
62
|
+
if (newlineIdx === -1) continue;
|
|
63
|
+
const statement = row.content.slice(newlineIdx + 1);
|
|
64
|
+
const playbook = parsePlaybookStatement(statement);
|
|
64
65
|
if (playbook) {
|
|
65
|
-
parsed.push({ id: row.id,
|
|
66
|
+
parsed.push({ id: row.id, playbook });
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
package/src/playbooks/types.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Action Playbook — a structured trigger→action rule that tells the
|
|
3
3
|
* triage engine how to handle incoming messages matching a pattern.
|
|
4
4
|
*
|
|
5
|
-
* Playbooks are stored as
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Playbooks are stored as memory_graph_nodes with
|
|
6
|
+
* sourceConversations containing a "playbook:{nodeId}" entry. The
|
|
7
|
+
* content column holds "Playbook: <trigger>\n<json>" where the JSON
|
|
8
|
+
* encodes the structured fields below.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
export interface Playbook {
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
|
|
11
11
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
12
|
-
import { getConfig } from "../config/loader.js";
|
|
13
12
|
import { listConnections } from "../oauth/oauth-store.js";
|
|
14
13
|
import { resolveBundledDir } from "../util/bundled-asset.js";
|
|
15
14
|
import { getLogger } from "../util/logger.js";
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
} from "../util/platform.js";
|
|
22
21
|
import { stripCommentLines } from "../util/strip-comment-lines.js";
|
|
23
22
|
import { SYSTEM_PROMPT_CACHE_BOUNDARY } from "./cache-boundary.js";
|
|
24
|
-
import { buildJournalContext } from "./journal-context.js";
|
|
25
23
|
|
|
26
24
|
export { SYSTEM_PROMPT_CACHE_BOUNDARY };
|
|
27
25
|
|
|
@@ -130,27 +128,7 @@ export function ensurePromptFiles(): void {
|
|
|
130
128
|
}
|
|
131
129
|
}
|
|
132
130
|
|
|
133
|
-
//
|
|
134
|
-
// this is a fresh install or not. Kept out of PROMPT_FILES because NOW.md is
|
|
135
|
-
// ephemeral state, not identity context.
|
|
136
|
-
const nowDest = getWorkspacePromptPath("NOW.md");
|
|
137
|
-
if (!existsSync(nowDest)) {
|
|
138
|
-
const nowSrc = join(templatesDir, "NOW.md");
|
|
139
|
-
try {
|
|
140
|
-
if (existsSync(nowSrc)) {
|
|
141
|
-
copyFileSync(nowSrc, nowDest);
|
|
142
|
-
log.info(
|
|
143
|
-
{ file: "NOW.md", dest: nowDest },
|
|
144
|
-
"Created NOW.md scratchpad from template",
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
} catch (err) {
|
|
148
|
-
log.warn(
|
|
149
|
-
{ err, file: "NOW.md" },
|
|
150
|
-
"Failed to create NOW.md from template",
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
131
|
+
// The `remember` tool handles scratchpad-style memory writes directly to the graph.
|
|
154
132
|
|
|
155
133
|
// Seed users/default.md persona template
|
|
156
134
|
try {
|
|
@@ -296,11 +274,8 @@ export function buildSystemPrompt(options?: BuildSystemPromptOptions): string {
|
|
|
296
274
|
const integrationSection = buildIntegrationSection();
|
|
297
275
|
if (integrationSection) dynamicParts.push(integrationSection);
|
|
298
276
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
options?.userSlug,
|
|
302
|
-
);
|
|
303
|
-
if (journalContext) dynamicParts.push(journalContext);
|
|
277
|
+
// Journal entries are extracted into graph nodes by the memory pipeline.
|
|
278
|
+
// Journal files remain writable on disk.
|
|
304
279
|
|
|
305
280
|
const dynamic = dynamicParts.join("\n\n");
|
|
306
281
|
|
|
@@ -489,4 +464,3 @@ export function buildCoreIdentityContext(opts?: {
|
|
|
489
464
|
if (opts?.userPersona) parts.push(opts.userPersona);
|
|
490
465
|
return parts.length > 0 ? parts.join("\n\n") : null;
|
|
491
466
|
}
|
|
492
|
-
|
|
@@ -101,6 +101,14 @@ export const PLACEHOLDER_EMPTY_TURN =
|
|
|
101
101
|
export const PLACEHOLDER_BLOCKS_OMITTED =
|
|
102
102
|
"\x00__PLACEHOLDER__[internal blocks omitted]";
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Synthetic placeholder injected as user-message content when Anthropic API
|
|
106
|
+
* alternation requires a user turn but no real user content exists. Uses the
|
|
107
|
+
* `__injected` XML tag convention so the LLM treats it as system metadata
|
|
108
|
+
* rather than user speech.
|
|
109
|
+
*/
|
|
110
|
+
const SYNTHETIC_CONTINUATION_TEXT = "<synthetic_continuation __injected />";
|
|
111
|
+
|
|
104
112
|
/** Type-guard for tool_use blocks in Anthropic-formatted content. */
|
|
105
113
|
function isToolUseBlock(block: unknown): block is Anthropic.ToolUseBlockParam {
|
|
106
114
|
return (
|
|
@@ -310,14 +318,24 @@ function expandCollapsedAssistantTurns(
|
|
|
310
318
|
if (nextIsUser) {
|
|
311
319
|
const remainingResults = Array.from(toolResultMap.values());
|
|
312
320
|
const rebuiltUserContent = [...remainingResults, ...nonToolResultContent];
|
|
313
|
-
// Replace the original user message with the rebuilt one
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
+
// Replace the original user message with the rebuilt one. When all
|
|
322
|
+
// tool_results were distributed to intermediate segments (empty rebuilt
|
|
323
|
+
// content), skip the synthetic placeholder if the next message is already
|
|
324
|
+
// a user turn — ensureToolPairing will pair the last assistant segment
|
|
325
|
+
// with that next user message naturally.
|
|
326
|
+
if (rebuiltUserContent.length > 0) {
|
|
327
|
+
result.push({ role: "user" as const, content: rebuiltUserContent });
|
|
328
|
+
} else {
|
|
329
|
+
const nextAfterUser = messages[mi + 2];
|
|
330
|
+
if (!nextAfterUser || nextAfterUser.role !== "user") {
|
|
331
|
+
result.push({
|
|
332
|
+
role: "user" as const,
|
|
333
|
+
content: [
|
|
334
|
+
{ type: "text" as const, text: SYNTHETIC_CONTINUATION_TEXT },
|
|
335
|
+
],
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
321
339
|
mi++; // skip the original user message
|
|
322
340
|
}
|
|
323
341
|
}
|
|
@@ -574,16 +592,26 @@ function ensureToolPairing(
|
|
|
574
592
|
role: "assistant" as const,
|
|
575
593
|
content: carryoverContent,
|
|
576
594
|
});
|
|
577
|
-
//
|
|
578
|
-
//
|
|
579
|
-
//
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}
|
|
595
|
+
// Emit a trailing user message when there is remaining content, or when
|
|
596
|
+
// alternation requires it (next message is assistant or end of array).
|
|
597
|
+
// Skip the synthetic placeholder if the next message is already a user
|
|
598
|
+
// turn — it will naturally maintain alternation.
|
|
599
|
+
if (normalized.remainingContent.length > 0) {
|
|
600
|
+
result.push({
|
|
601
|
+
role: "user" as const,
|
|
602
|
+
content: normalized.remainingContent,
|
|
603
|
+
});
|
|
604
|
+
} else {
|
|
605
|
+
const nextAfterPair = messages[i + 2];
|
|
606
|
+
if (!nextAfterPair || nextAfterPair.role !== "user") {
|
|
607
|
+
result.push({
|
|
608
|
+
role: "user" as const,
|
|
609
|
+
content: [
|
|
610
|
+
{ type: "text" as const, text: SYNTHETIC_CONTINUATION_TEXT },
|
|
611
|
+
],
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
}
|
|
587
615
|
} else {
|
|
588
616
|
// No carryover assistant text to restore, so preserve existing behavior
|
|
589
617
|
// and keep additional user blocks in the same message.
|
|
@@ -678,7 +706,7 @@ export class AnthropicProvider implements Provider {
|
|
|
678
706
|
this.client = new Anthropic({ apiKey, baseURL: options.baseURL });
|
|
679
707
|
this.model = model;
|
|
680
708
|
this.useNativeWebSearch = options.useNativeWebSearch ?? false;
|
|
681
|
-
this.streamTimeoutMs = options.streamTimeoutMs ??
|
|
709
|
+
this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
|
|
682
710
|
}
|
|
683
711
|
|
|
684
712
|
async sendMessage(
|
|
@@ -89,7 +89,7 @@ export class GeminiProvider implements Provider {
|
|
|
89
89
|
})
|
|
90
90
|
: new GoogleGenAI({ apiKey });
|
|
91
91
|
this.model = model;
|
|
92
|
-
this.streamTimeoutMs = options.streamTimeoutMs ??
|
|
92
|
+
this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
async sendMessage(
|
|
@@ -112,7 +112,7 @@ export class OpenAIProvider implements Provider {
|
|
|
112
112
|
baseURL: options.baseURL,
|
|
113
113
|
});
|
|
114
114
|
this.model = model;
|
|
115
|
-
this.streamTimeoutMs = options.streamTimeoutMs ??
|
|
115
|
+
this.streamTimeoutMs = options.streamTimeoutMs ?? 1_800_000;
|
|
116
116
|
this.extraCreateParams = options.extraCreateParams ?? {};
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -140,7 +140,7 @@ export async function initializeProviders(
|
|
|
140
140
|
routingSources.clear();
|
|
141
141
|
|
|
142
142
|
const streamTimeoutMs =
|
|
143
|
-
(config.timeouts?.providerStreamTimeoutSec ??
|
|
143
|
+
(config.timeouts?.providerStreamTimeoutSec ?? 1800) * 1000;
|
|
144
144
|
const inferenceMode = config.services.inference.mode;
|
|
145
145
|
const useNativeWebSearch =
|
|
146
146
|
config.services["web-search"].provider === "inference-provider-native";
|
package/src/providers/retry.ts
CHANGED
|
@@ -34,16 +34,30 @@ const RETRYABLE_STREAM_PATTERNS = [
|
|
|
34
34
|
"stream has ended, this shouldn't happen",
|
|
35
35
|
];
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Patterns that indicate a transient provider error even when no HTTP status
|
|
39
|
+
* code is available (e.g. overloaded errors delivered as SSE events mid-stream
|
|
40
|
+
* where the initial HTTP response was 200).
|
|
41
|
+
*/
|
|
42
|
+
const RETRYABLE_PROVIDER_MESSAGE_PATTERNS = [/overloaded/i];
|
|
43
|
+
|
|
37
44
|
function isRetryableStreamError(error: unknown): boolean {
|
|
38
45
|
if (!(error instanceof ProviderError)) return false;
|
|
39
46
|
if (error.statusCode !== undefined) return false; // has a real HTTP status — not a stream error
|
|
40
47
|
return RETRYABLE_STREAM_PATTERNS.some((p) => error.message.includes(p));
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
function isRetryableProviderMessage(error: unknown): boolean {
|
|
51
|
+
if (!(error instanceof ProviderError)) return false;
|
|
52
|
+
if (error.statusCode !== undefined) return false; // has a real HTTP status — handled by status check
|
|
53
|
+
return RETRYABLE_PROVIDER_MESSAGE_PATTERNS.some((p) => p.test(error.message));
|
|
54
|
+
}
|
|
55
|
+
|
|
43
56
|
function isRetryableError(error: unknown): boolean {
|
|
44
57
|
if (error instanceof ProviderError && error.statusCode !== undefined) {
|
|
45
58
|
if (error.statusCode === 429 || error.statusCode >= 500) return true;
|
|
46
59
|
}
|
|
60
|
+
if (isRetryableProviderMessage(error)) return true;
|
|
47
61
|
if (isRetryableStreamError(error)) return true;
|
|
48
62
|
return isRetryableNetworkError(error);
|
|
49
63
|
}
|
|
@@ -161,9 +175,11 @@ export class RetryProvider implements Provider {
|
|
|
161
175
|
error.statusCode !== undefined &&
|
|
162
176
|
error.statusCode >= 500
|
|
163
177
|
? `server_error_${error.statusCode}`
|
|
164
|
-
:
|
|
165
|
-
? "
|
|
166
|
-
:
|
|
178
|
+
: isRetryableProviderMessage(error)
|
|
179
|
+
? "provider_overloaded"
|
|
180
|
+
: isRetryableStreamError(error)
|
|
181
|
+
? "stream_corruption"
|
|
182
|
+
: "network_error";
|
|
167
183
|
log.warn(
|
|
168
184
|
{
|
|
169
185
|
attempt: attempt + 1,
|
|
@@ -48,7 +48,11 @@ export type TrustClass = "guardian" | "trusted_contact" | "unknown";
|
|
|
48
48
|
export function isUntrustedTrustClass(
|
|
49
49
|
trustClass: TrustClass | undefined,
|
|
50
50
|
): boolean {
|
|
51
|
-
return
|
|
51
|
+
return (
|
|
52
|
+
trustClass === "trusted_contact" ||
|
|
53
|
+
trustClass === "unknown" ||
|
|
54
|
+
trustClass === undefined
|
|
55
|
+
);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
/**
|
|
@@ -358,6 +358,13 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
|
|
|
358
358
|
{ endpoint: "conversations/wipe", scopes: ["chat.write"] },
|
|
359
359
|
{ endpoint: "conversations/reorder", scopes: ["chat.write"] },
|
|
360
360
|
|
|
361
|
+
// Conversation groups
|
|
362
|
+
{ endpoint: "groups:GET", scopes: ["chat.read"] },
|
|
363
|
+
{ endpoint: "groups:POST", scopes: ["chat.write"] },
|
|
364
|
+
{ endpoint: "groups:PATCH", scopes: ["chat.write"] },
|
|
365
|
+
{ endpoint: "groups:DELETE", scopes: ["chat.write"] },
|
|
366
|
+
{ endpoint: "groups/reorder", scopes: ["chat.write"] },
|
|
367
|
+
|
|
361
368
|
// Conversation search
|
|
362
369
|
{ endpoint: "conversations/search", scopes: ["chat.read"] },
|
|
363
370
|
|