@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
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"tools": [
|
|
4
|
+
{
|
|
5
|
+
"name": "outlook_calendar_list_events",
|
|
6
|
+
"description": "List upcoming Outlook Calendar events within a date range. Returns event summaries, times, and metadata.",
|
|
7
|
+
"category": "calendar",
|
|
8
|
+
"risk": "low",
|
|
9
|
+
"input_schema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"calendar_id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Calendar ID to query. If omitted, uses the default calendar."
|
|
15
|
+
},
|
|
16
|
+
"time_min": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"description": "Start of time range in ISO 8601 format (e.g. \"2024-01-15T00:00:00Z\"). Defaults to now."
|
|
19
|
+
},
|
|
20
|
+
"time_max": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"description": "End of time range in ISO 8601 format (e.g. \"2024-01-22T00:00:00Z\"). Defaults to 7 days from now."
|
|
23
|
+
},
|
|
24
|
+
"max_results": {
|
|
25
|
+
"type": "number",
|
|
26
|
+
"description": "Maximum number of events to return (default 25, max 250)"
|
|
27
|
+
},
|
|
28
|
+
"query": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "OData $filter expression to filter events"
|
|
31
|
+
},
|
|
32
|
+
"order_by": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "OData $orderby expression (default \"start/dateTime\")"
|
|
35
|
+
},
|
|
36
|
+
"account": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Email address of the Outlook account to use. Required when multiple Outlook accounts are connected. If omitted, uses the most recently connected account."
|
|
39
|
+
},
|
|
40
|
+
"activity": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"executor": "tools/outlook-calendar-list-events.ts",
|
|
47
|
+
"execution_target": "host"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "outlook_calendar_get_event",
|
|
51
|
+
"description": "Get the full details of a single Outlook Calendar event by its ID.",
|
|
52
|
+
"category": "calendar",
|
|
53
|
+
"risk": "low",
|
|
54
|
+
"input_schema": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {
|
|
57
|
+
"event_id": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "The Outlook Calendar event ID"
|
|
60
|
+
},
|
|
61
|
+
"calendar_id": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "Calendar ID. If omitted, uses the default calendar."
|
|
64
|
+
},
|
|
65
|
+
"account": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Email address of the Outlook account to use. Required when multiple Outlook accounts are connected. If omitted, uses the most recently connected account."
|
|
68
|
+
},
|
|
69
|
+
"activity": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"required": ["event_id"]
|
|
75
|
+
},
|
|
76
|
+
"executor": "tools/outlook-calendar-get-event.ts",
|
|
77
|
+
"execution_target": "host"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "outlook_calendar_create_event",
|
|
81
|
+
"description": "Create a new Outlook Calendar event. Include a confidence score (0-1) indicating how certain you are this action is correct.",
|
|
82
|
+
"category": "calendar",
|
|
83
|
+
"risk": "medium",
|
|
84
|
+
"input_schema": {
|
|
85
|
+
"type": "object",
|
|
86
|
+
"properties": {
|
|
87
|
+
"summary": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"description": "Event title (maps to the Outlook subject field)"
|
|
90
|
+
},
|
|
91
|
+
"start": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"description": "Start time in ISO 8601 format (e.g. \"2024-01-15T09:00:00-05:00\") or date for all-day events (\"2024-01-15\")"
|
|
94
|
+
},
|
|
95
|
+
"end": {
|
|
96
|
+
"type": "string",
|
|
97
|
+
"description": "End time in ISO 8601 format or date for all-day events"
|
|
98
|
+
},
|
|
99
|
+
"description": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "Event description or notes"
|
|
102
|
+
},
|
|
103
|
+
"location": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"description": "Event location"
|
|
106
|
+
},
|
|
107
|
+
"attendees": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": {
|
|
110
|
+
"type": "string"
|
|
111
|
+
},
|
|
112
|
+
"description": "Email addresses of attendees to invite"
|
|
113
|
+
},
|
|
114
|
+
"timezone": {
|
|
115
|
+
"type": "string",
|
|
116
|
+
"description": "IANA timezone (e.g. \"America/New_York\"). Required when start/end don't include timezone offset."
|
|
117
|
+
},
|
|
118
|
+
"calendar_id": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"description": "Calendar ID. If omitted, uses the default calendar."
|
|
121
|
+
},
|
|
122
|
+
"confidence": {
|
|
123
|
+
"type": "number",
|
|
124
|
+
"description": "Confidence score (0-1) for this action"
|
|
125
|
+
},
|
|
126
|
+
"account": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Email address of the Outlook account to use. Required when multiple Outlook accounts are connected. If omitted, uses the most recently connected account."
|
|
129
|
+
},
|
|
130
|
+
"activity": {
|
|
131
|
+
"type": "string",
|
|
132
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"required": ["summary", "start", "end", "confidence"]
|
|
136
|
+
},
|
|
137
|
+
"executor": "tools/outlook-calendar-create-event.ts",
|
|
138
|
+
"execution_target": "host"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"name": "outlook_calendar_check_availability",
|
|
142
|
+
"description": "Check free/busy status across one or more schedules to find available time slots.",
|
|
143
|
+
"category": "calendar",
|
|
144
|
+
"risk": "low",
|
|
145
|
+
"input_schema": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"properties": {
|
|
148
|
+
"time_min": {
|
|
149
|
+
"type": "string",
|
|
150
|
+
"description": "Start of time range in ISO 8601 format"
|
|
151
|
+
},
|
|
152
|
+
"time_max": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "End of time range in ISO 8601 format"
|
|
155
|
+
},
|
|
156
|
+
"schedules": {
|
|
157
|
+
"type": "array",
|
|
158
|
+
"items": {
|
|
159
|
+
"type": "string"
|
|
160
|
+
},
|
|
161
|
+
"description": "Email addresses of schedules to check. Defaults to the authenticated user."
|
|
162
|
+
},
|
|
163
|
+
"timezone": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"description": "IANA timezone for interpreting results (e.g. \"America/New_York\")"
|
|
166
|
+
},
|
|
167
|
+
"account": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"description": "Email address of the Outlook account to use. Required when multiple Outlook accounts are connected. If omitted, uses the most recently connected account."
|
|
170
|
+
},
|
|
171
|
+
"activity": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"required": ["time_min", "time_max"]
|
|
177
|
+
},
|
|
178
|
+
"executor": "tools/outlook-calendar-check-availability.ts",
|
|
179
|
+
"execution_target": "host"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"name": "outlook_calendar_rsvp",
|
|
183
|
+
"description": "Respond to an Outlook Calendar event invitation (accept, decline, or tentative). Include a confidence score (0-1).",
|
|
184
|
+
"category": "calendar",
|
|
185
|
+
"risk": "medium",
|
|
186
|
+
"input_schema": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"properties": {
|
|
189
|
+
"event_id": {
|
|
190
|
+
"type": "string",
|
|
191
|
+
"description": "The Outlook Calendar event ID"
|
|
192
|
+
},
|
|
193
|
+
"response": {
|
|
194
|
+
"type": "string",
|
|
195
|
+
"enum": ["accepted", "declined", "tentative"],
|
|
196
|
+
"description": "RSVP response"
|
|
197
|
+
},
|
|
198
|
+
"confidence": {
|
|
199
|
+
"type": "number",
|
|
200
|
+
"description": "Confidence score (0-1) for this action"
|
|
201
|
+
},
|
|
202
|
+
"calendar_id": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"description": "Calendar ID. If omitted, uses the default calendar."
|
|
205
|
+
},
|
|
206
|
+
"account": {
|
|
207
|
+
"type": "string",
|
|
208
|
+
"description": "Email address of the Outlook account to use. Required when multiple Outlook accounts are connected. If omitted, uses the most recently connected account."
|
|
209
|
+
},
|
|
210
|
+
"activity": {
|
|
211
|
+
"type": "string",
|
|
212
|
+
"description": "Brief non-technical explanation of why this tool is being called"
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
"required": ["event_id", "response", "confidence"]
|
|
216
|
+
},
|
|
217
|
+
"executor": "tools/outlook-calendar-rsvp.ts",
|
|
218
|
+
"execution_target": "host"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
OAuthConnection,
|
|
3
|
+
OAuthConnectionResponse,
|
|
4
|
+
} from "../../../oauth/connection.js";
|
|
5
|
+
import type {
|
|
6
|
+
OutlookCalendarEvent,
|
|
7
|
+
OutlookCalendarEventListResponse,
|
|
8
|
+
OutlookCalendarListResponse,
|
|
9
|
+
OutlookDateTimeZone,
|
|
10
|
+
OutlookScheduleResponse,
|
|
11
|
+
} from "./types.js";
|
|
12
|
+
|
|
13
|
+
export class OutlookCalendarApiError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
public readonly status: number,
|
|
16
|
+
public readonly statusText: string,
|
|
17
|
+
message: string,
|
|
18
|
+
) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "OutlookCalendarApiError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const MAX_RETRIES = 3;
|
|
25
|
+
const INITIAL_BACKOFF_MS = 1000;
|
|
26
|
+
|
|
27
|
+
function isRetryable(status: number): boolean {
|
|
28
|
+
return status === 429 || (status >= 500 && status < 600);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const IDEMPOTENT_METHODS = new Set([
|
|
32
|
+
"GET",
|
|
33
|
+
"HEAD",
|
|
34
|
+
"PUT",
|
|
35
|
+
"DELETE",
|
|
36
|
+
"OPTIONS",
|
|
37
|
+
"PATCH",
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
function isIdempotent(method: string): boolean {
|
|
41
|
+
return IDEMPOTENT_METHODS.has(method.toUpperCase());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Make an authenticated request to the Microsoft Graph API with retry logic.
|
|
46
|
+
*
|
|
47
|
+
* The OAuth provider's baseUrl is `https://graph.microsoft.com`, so all paths
|
|
48
|
+
* must include the full API version and resource prefix (e.g. `/v1.0/me/events`).
|
|
49
|
+
*/
|
|
50
|
+
async function request<T>(
|
|
51
|
+
connection: OAuthConnection,
|
|
52
|
+
path: string,
|
|
53
|
+
options?: RequestInit,
|
|
54
|
+
query?: Record<string, string | string[]>,
|
|
55
|
+
): Promise<T> {
|
|
56
|
+
const method = (options?.method ?? "GET").toUpperCase();
|
|
57
|
+
const canRetry = isIdempotent(method);
|
|
58
|
+
|
|
59
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
60
|
+
let resp: OAuthConnectionResponse;
|
|
61
|
+
try {
|
|
62
|
+
const extraHeaders =
|
|
63
|
+
options?.headers &&
|
|
64
|
+
typeof options.headers === "object" &&
|
|
65
|
+
!Array.isArray(options.headers)
|
|
66
|
+
? (options.headers as Record<string, string>)
|
|
67
|
+
: {};
|
|
68
|
+
resp = await connection.request({
|
|
69
|
+
method,
|
|
70
|
+
path,
|
|
71
|
+
query,
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
...extraHeaders,
|
|
75
|
+
},
|
|
76
|
+
body: options?.body ? JSON.parse(options.body as string) : undefined,
|
|
77
|
+
});
|
|
78
|
+
} catch (err) {
|
|
79
|
+
// Network-level errors from connection.request() are not retryable
|
|
80
|
+
throw err;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
84
|
+
if (canRetry && isRetryable(resp.status) && attempt < MAX_RETRIES) {
|
|
85
|
+
const retryAfter =
|
|
86
|
+
resp.headers["retry-after"] ?? resp.headers["Retry-After"];
|
|
87
|
+
const delayMs = retryAfter
|
|
88
|
+
? parseInt(retryAfter, 10) * 1000
|
|
89
|
+
: INITIAL_BACKOFF_MS * Math.pow(2, attempt);
|
|
90
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const bodyStr =
|
|
94
|
+
typeof resp.body === "string"
|
|
95
|
+
? resp.body
|
|
96
|
+
: JSON.stringify(resp.body ?? "");
|
|
97
|
+
throw new OutlookCalendarApiError(
|
|
98
|
+
resp.status,
|
|
99
|
+
"",
|
|
100
|
+
`Microsoft Graph API ${resp.status}: ${bodyStr}`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Success
|
|
105
|
+
if (resp.status === 204 || resp.body === undefined) {
|
|
106
|
+
return undefined as T;
|
|
107
|
+
}
|
|
108
|
+
return resp.body as T;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
throw new Error(
|
|
112
|
+
"Unreachable: retry loop exited without returning or throwing",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** List calendar events, optionally within a specific calendar. */
|
|
117
|
+
export async function listEvents(
|
|
118
|
+
connection: OAuthConnection,
|
|
119
|
+
calendarId?: string,
|
|
120
|
+
options?: {
|
|
121
|
+
top?: number;
|
|
122
|
+
skip?: number;
|
|
123
|
+
filter?: string;
|
|
124
|
+
orderby?: string;
|
|
125
|
+
select?: string;
|
|
126
|
+
},
|
|
127
|
+
): Promise<OutlookCalendarEventListResponse> {
|
|
128
|
+
const path =
|
|
129
|
+
calendarId && calendarId !== "primary"
|
|
130
|
+
? `/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events`
|
|
131
|
+
: "/v1.0/me/events";
|
|
132
|
+
|
|
133
|
+
const query: Record<string, string> = {};
|
|
134
|
+
if (options?.top !== undefined) query["$top"] = String(options.top);
|
|
135
|
+
if (options?.skip !== undefined) query["$skip"] = String(options.skip);
|
|
136
|
+
if (options?.filter) query["$filter"] = options.filter;
|
|
137
|
+
query["$orderby"] = options?.orderby ?? "start/dateTime";
|
|
138
|
+
if (options?.select) query["$select"] = options.select;
|
|
139
|
+
|
|
140
|
+
return request<OutlookCalendarEventListResponse>(
|
|
141
|
+
connection,
|
|
142
|
+
path,
|
|
143
|
+
undefined,
|
|
144
|
+
Object.keys(query).length > 0 ? query : undefined,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Get a single calendar event by ID. */
|
|
149
|
+
export async function getEvent(
|
|
150
|
+
connection: OAuthConnection,
|
|
151
|
+
eventId: string,
|
|
152
|
+
select?: string,
|
|
153
|
+
): Promise<OutlookCalendarEvent> {
|
|
154
|
+
const query: Record<string, string> = {};
|
|
155
|
+
if (select) query["$select"] = select;
|
|
156
|
+
|
|
157
|
+
return request<OutlookCalendarEvent>(
|
|
158
|
+
connection,
|
|
159
|
+
`/v1.0/me/events/${encodeURIComponent(eventId)}`,
|
|
160
|
+
undefined,
|
|
161
|
+
Object.keys(query).length > 0 ? query : undefined,
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Create a new calendar event. */
|
|
166
|
+
export async function createEvent(
|
|
167
|
+
connection: OAuthConnection,
|
|
168
|
+
event: Partial<OutlookCalendarEvent>,
|
|
169
|
+
calendarId?: string,
|
|
170
|
+
): Promise<OutlookCalendarEvent> {
|
|
171
|
+
const path =
|
|
172
|
+
calendarId && calendarId !== "primary"
|
|
173
|
+
? `/v1.0/me/calendars/${encodeURIComponent(calendarId)}/events`
|
|
174
|
+
: "/v1.0/me/events";
|
|
175
|
+
|
|
176
|
+
return request<OutlookCalendarEvent>(connection, path, {
|
|
177
|
+
method: "POST",
|
|
178
|
+
body: JSON.stringify(event),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Update (patch) an existing calendar event. */
|
|
183
|
+
export async function patchEvent(
|
|
184
|
+
connection: OAuthConnection,
|
|
185
|
+
eventId: string,
|
|
186
|
+
updates: Partial<OutlookCalendarEvent>,
|
|
187
|
+
): Promise<OutlookCalendarEvent> {
|
|
188
|
+
return request<OutlookCalendarEvent>(
|
|
189
|
+
connection,
|
|
190
|
+
`/v1.0/me/events/${encodeURIComponent(eventId)}`,
|
|
191
|
+
{
|
|
192
|
+
method: "PATCH",
|
|
193
|
+
body: JSON.stringify(updates),
|
|
194
|
+
},
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** RSVP to a calendar event (accept, decline, or tentatively accept). */
|
|
199
|
+
export async function rsvpEvent(
|
|
200
|
+
connection: OAuthConnection,
|
|
201
|
+
eventId: string,
|
|
202
|
+
response: "accepted" | "declined" | "tentative",
|
|
203
|
+
sendResponse?: boolean,
|
|
204
|
+
comment?: string,
|
|
205
|
+
): Promise<void> {
|
|
206
|
+
const endpointMap: Record<string, string> = {
|
|
207
|
+
accepted: "accept",
|
|
208
|
+
declined: "decline",
|
|
209
|
+
tentative: "tentativelyAccept",
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const action = endpointMap[response];
|
|
213
|
+
const body: Record<string, unknown> = {};
|
|
214
|
+
if (sendResponse !== undefined) body.sendResponse = sendResponse;
|
|
215
|
+
if (comment !== undefined) body.comment = comment;
|
|
216
|
+
|
|
217
|
+
await request<void>(
|
|
218
|
+
connection,
|
|
219
|
+
`/v1.0/me/events/${encodeURIComponent(eventId)}/${action}`,
|
|
220
|
+
{
|
|
221
|
+
method: "POST",
|
|
222
|
+
body: JSON.stringify(body),
|
|
223
|
+
},
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Get free/busy schedule for one or more users by email address. */
|
|
228
|
+
export async function getSchedule(
|
|
229
|
+
connection: OAuthConnection,
|
|
230
|
+
query: {
|
|
231
|
+
schedules: string[];
|
|
232
|
+
startTime: OutlookDateTimeZone;
|
|
233
|
+
endTime: OutlookDateTimeZone;
|
|
234
|
+
availabilityViewInterval?: number;
|
|
235
|
+
},
|
|
236
|
+
): Promise<OutlookScheduleResponse> {
|
|
237
|
+
return request<OutlookScheduleResponse>(
|
|
238
|
+
connection,
|
|
239
|
+
"/v1.0/me/calendar/getSchedule",
|
|
240
|
+
{
|
|
241
|
+
method: "POST",
|
|
242
|
+
body: JSON.stringify(query),
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** List all calendars in the user's mailbox. */
|
|
248
|
+
export async function listCalendars(
|
|
249
|
+
connection: OAuthConnection,
|
|
250
|
+
): Promise<OutlookCalendarListResponse> {
|
|
251
|
+
return request<OutlookCalendarListResponse>(connection, "/v1.0/me/calendars");
|
|
252
|
+
}
|
package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToolContext,
|
|
3
|
+
ToolExecutionResult,
|
|
4
|
+
} from "../../../../tools/types.js";
|
|
5
|
+
import * as calendar from "../calendar-client.js";
|
|
6
|
+
import { err, getCalendarConnection, ok } from "./shared.js";
|
|
7
|
+
|
|
8
|
+
export async function run(
|
|
9
|
+
input: Record<string, unknown>,
|
|
10
|
+
_context: ToolContext,
|
|
11
|
+
): Promise<ToolExecutionResult> {
|
|
12
|
+
const account = input.account as string | undefined;
|
|
13
|
+
const timeMin = input.time_min as string;
|
|
14
|
+
const timeMax = input.time_max as string;
|
|
15
|
+
let schedules = (input.schedules as string[] | undefined) ?? [];
|
|
16
|
+
const timezone = (input.timezone as string | undefined) ?? "UTC";
|
|
17
|
+
|
|
18
|
+
const connection = await getCalendarConnection(account);
|
|
19
|
+
|
|
20
|
+
if (schedules.length === 0) {
|
|
21
|
+
const resp = await connection.request({
|
|
22
|
+
method: "GET",
|
|
23
|
+
path: "/v1.0/me",
|
|
24
|
+
});
|
|
25
|
+
if (resp.status < 200 || resp.status >= 300) {
|
|
26
|
+
return err(
|
|
27
|
+
"Failed to retrieve your Microsoft profile. Cannot determine your email for availability lookup.",
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
const body = resp.body as Record<string, unknown>;
|
|
31
|
+
const email =
|
|
32
|
+
(body.mail as string | undefined) ??
|
|
33
|
+
(body.userPrincipalName as string | undefined);
|
|
34
|
+
if (email) {
|
|
35
|
+
schedules = [email];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (schedules.length === 0) {
|
|
40
|
+
return err(
|
|
41
|
+
"No schedules provided and could not determine your email address from your Microsoft profile. " +
|
|
42
|
+
"Please provide at least one email address in the schedules parameter.",
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const result = await calendar.getSchedule(connection, {
|
|
47
|
+
schedules,
|
|
48
|
+
startTime: { dateTime: timeMin, timeZone: timezone },
|
|
49
|
+
endTime: { dateTime: timeMax, timeZone: timezone },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return ok(JSON.stringify(result, null, 2));
|
|
53
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToolContext,
|
|
3
|
+
ToolExecutionResult,
|
|
4
|
+
} from "../../../../tools/types.js";
|
|
5
|
+
import * as calendar from "../calendar-client.js";
|
|
6
|
+
import { getCalendarConnection, ok } from "./shared.js";
|
|
7
|
+
|
|
8
|
+
export async function run(
|
|
9
|
+
input: Record<string, unknown>,
|
|
10
|
+
_context: ToolContext,
|
|
11
|
+
): Promise<ToolExecutionResult> {
|
|
12
|
+
const account = input.account as string | undefined;
|
|
13
|
+
const summary = input.summary as string;
|
|
14
|
+
const startRaw = input.start as string;
|
|
15
|
+
const endRaw = input.end as string;
|
|
16
|
+
const description = input.description as string | undefined;
|
|
17
|
+
const location = input.location as string | undefined;
|
|
18
|
+
const attendees = input.attendees as string[] | undefined;
|
|
19
|
+
const timezone = input.timezone as string | undefined;
|
|
20
|
+
const calendarId = input.calendar_id as string | undefined;
|
|
21
|
+
|
|
22
|
+
// Detect all-day events: if start string does not contain "T", treat as all-day
|
|
23
|
+
const isAllDay = !startRaw.includes("T");
|
|
24
|
+
|
|
25
|
+
// Determine the timeZone to send. If the caller provided an explicit IANA
|
|
26
|
+
// timezone, always use it. Otherwise, only fall back to UTC when the
|
|
27
|
+
// dateTime string does NOT already carry an offset (e.g. "-05:00" or "Z").
|
|
28
|
+
// Sending timeZone: "UTC" alongside a dateTime that contains a different
|
|
29
|
+
// offset would cause Microsoft Graph to ignore the offset and interpret the
|
|
30
|
+
// time as UTC, creating events at the wrong wall-clock time.
|
|
31
|
+
const hasOffset = (dt: string) => /[Zz]|[+-]\d{2}:\d{2}$/.test(dt);
|
|
32
|
+
const resolveTimeZone = (dt: string) =>
|
|
33
|
+
timezone ?? (hasOffset(dt) ? undefined : "UTC");
|
|
34
|
+
|
|
35
|
+
const start = isAllDay
|
|
36
|
+
? {
|
|
37
|
+
dateTime: `${startRaw}T00:00:00`,
|
|
38
|
+
timeZone: timezone ?? "UTC",
|
|
39
|
+
}
|
|
40
|
+
: { dateTime: startRaw, timeZone: resolveTimeZone(startRaw) };
|
|
41
|
+
|
|
42
|
+
const end = isAllDay
|
|
43
|
+
? {
|
|
44
|
+
dateTime: `${endRaw}T00:00:00`,
|
|
45
|
+
timeZone: timezone ?? "UTC",
|
|
46
|
+
}
|
|
47
|
+
: { dateTime: endRaw, timeZone: resolveTimeZone(endRaw) };
|
|
48
|
+
|
|
49
|
+
const eventBody: Parameters<typeof calendar.createEvent>[1] = {
|
|
50
|
+
subject: summary,
|
|
51
|
+
start,
|
|
52
|
+
end,
|
|
53
|
+
isAllDay,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (description) {
|
|
57
|
+
eventBody.body = { contentType: "text", content: description };
|
|
58
|
+
}
|
|
59
|
+
if (location) {
|
|
60
|
+
eventBody.location = { displayName: location };
|
|
61
|
+
}
|
|
62
|
+
if (attendees?.length) {
|
|
63
|
+
eventBody.attendees = attendees.map((email) => ({
|
|
64
|
+
emailAddress: { address: email },
|
|
65
|
+
type: "required" as const,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const connection = await getCalendarConnection(account);
|
|
70
|
+
const event = await calendar.createEvent(connection, eventBody, calendarId);
|
|
71
|
+
return ok(
|
|
72
|
+
`Event created (ID: ${event.id}).${event.webLink ? ` View it here: ${event.webLink}` : ""}`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToolContext,
|
|
3
|
+
ToolExecutionResult,
|
|
4
|
+
} from "../../../../tools/types.js";
|
|
5
|
+
import * as calendar from "../calendar-client.js";
|
|
6
|
+
import { getCalendarConnection, ok } from "./shared.js";
|
|
7
|
+
|
|
8
|
+
export async function run(
|
|
9
|
+
input: Record<string, unknown>,
|
|
10
|
+
_context: ToolContext,
|
|
11
|
+
): Promise<ToolExecutionResult> {
|
|
12
|
+
const account = input.account as string | undefined;
|
|
13
|
+
const eventId = input.event_id as string;
|
|
14
|
+
|
|
15
|
+
const connection = await getCalendarConnection(account);
|
|
16
|
+
const event = await calendar.getEvent(connection, eventId);
|
|
17
|
+
return ok(JSON.stringify(event, null, 2));
|
|
18
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToolContext,
|
|
3
|
+
ToolExecutionResult,
|
|
4
|
+
} from "../../../../tools/types.js";
|
|
5
|
+
import * as calendar from "../calendar-client.js";
|
|
6
|
+
import { getCalendarConnection, ok } from "./shared.js";
|
|
7
|
+
|
|
8
|
+
export async function run(
|
|
9
|
+
input: Record<string, unknown>,
|
|
10
|
+
_context: ToolContext,
|
|
11
|
+
): Promise<ToolExecutionResult> {
|
|
12
|
+
const account = input.account as string | undefined;
|
|
13
|
+
const calendarId = input.calendar_id as string | undefined;
|
|
14
|
+
const timeMin = (input.time_min as string) ?? new Date().toISOString();
|
|
15
|
+
const timeMax = input.time_max as string | undefined;
|
|
16
|
+
const maxResults = Math.min((input.max_results as number) ?? 25, 250);
|
|
17
|
+
const query = input.query as string | undefined;
|
|
18
|
+
const orderBy = input.order_by as string | undefined;
|
|
19
|
+
|
|
20
|
+
const connection = await getCalendarConnection(account);
|
|
21
|
+
|
|
22
|
+
// Build OData $filter from time range and optional user query
|
|
23
|
+
const filterParts: string[] = [];
|
|
24
|
+
if (timeMin) {
|
|
25
|
+
filterParts.push(`start/dateTime ge '${timeMin}'`);
|
|
26
|
+
}
|
|
27
|
+
if (timeMax) {
|
|
28
|
+
filterParts.push(`start/dateTime le '${timeMax}'`);
|
|
29
|
+
}
|
|
30
|
+
if (query) {
|
|
31
|
+
filterParts.push(query);
|
|
32
|
+
}
|
|
33
|
+
const filter = filterParts.length > 0 ? filterParts.join(" and ") : undefined;
|
|
34
|
+
|
|
35
|
+
const result = await calendar.listEvents(connection, calendarId, {
|
|
36
|
+
filter,
|
|
37
|
+
top: maxResults,
|
|
38
|
+
orderby: orderBy,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!result.value?.length) {
|
|
42
|
+
return ok("No events found in the specified time range.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return ok(JSON.stringify(result, null, 2));
|
|
46
|
+
}
|