@vellumai/assistant 0.5.1 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +163 -54
- package/docs/architecture/integrations.md +62 -67
- package/docs/credential-execution-service.md +3 -3
- package/docs/skills.md +100 -0
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +111 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
- package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
- package/src/__tests__/app-dir-path-guard.test.ts +78 -0
- package/src/__tests__/app-executors.test.ts +1 -291
- package/src/__tests__/app-git-history.test.ts +4 -4
- package/src/__tests__/app-routes-csp.test.ts +1 -0
- package/src/__tests__/app-store-dir-names.test.ts +426 -0
- package/src/__tests__/attachments-store.test.ts +169 -21
- package/src/__tests__/attachments.test.ts +115 -1
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/canonical-guardian-store.test.ts +38 -0
- package/src/__tests__/channel-reply-delivery.test.ts +55 -0
- package/src/__tests__/checker.test.ts +54 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/config-schema-cmd.test.ts +68 -21
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +156 -5
- package/src/__tests__/conversation-agent-loop.test.ts +297 -2
- package/src/__tests__/conversation-attachments.test.ts +17 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
- package/src/__tests__/conversation-disk-view.test.ts +810 -0
- package/src/__tests__/conversation-error.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +551 -0
- package/src/__tests__/conversation-fork-route.test.ts +386 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
- package/src/__tests__/conversation-media-retry.test.ts +8 -2
- package/src/__tests__/conversation-memory-dirty-tail.test.ts +150 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +7 -0
- package/src/__tests__/conversation-queue.test.ts +36 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
- package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
- package/src/__tests__/conversation-skill-tools.test.ts +4 -9
- package/src/__tests__/conversation-slash-commands.test.ts +149 -0
- package/src/__tests__/conversation-store.test.ts +24 -21
- package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
- package/src/__tests__/conversation-title-service.test.ts +137 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
- package/src/__tests__/conversation-wipe.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-vault-unit.test.ts +5 -10
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
- package/src/__tests__/db-memory-archive-migration.test.ts +372 -0
- package/src/__tests__/db-memory-brief-state-migration.test.ts +213 -0
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +273 -0
- package/src/__tests__/diagnostics-export.test.ts +70 -1
- package/src/__tests__/first-greeting.test.ts +80 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
- package/src/__tests__/history-repair.test.ts +32 -10
- package/src/__tests__/http-conversation-lineage.test.ts +251 -0
- package/src/__tests__/image-source-path-reinject.test.ts +136 -0
- package/src/__tests__/inline-command-runner.test.ts +311 -0
- package/src/__tests__/inline-skill-authoring-guard.test.ts +220 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +435 -0
- package/src/__tests__/list-messages-attachments.test.ts +96 -0
- package/src/__tests__/llm-context-normalization.test.ts +1116 -0
- package/src/__tests__/llm-context-route-provider.test.ts +217 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
- package/src/__tests__/media-generate-image.test.ts +47 -94
- package/src/__tests__/memory-brief-open-loops.test.ts +530 -0
- package/src/__tests__/memory-brief-time.test.ts +285 -0
- package/src/__tests__/memory-brief-wrapper.test.ts +311 -0
- package/src/__tests__/memory-chunk-archive.test.ts +400 -0
- package/src/__tests__/memory-chunk-dual-write.test.ts +453 -0
- package/src/__tests__/memory-episode-archive.test.ts +370 -0
- package/src/__tests__/memory-episode-dual-write.test.ts +626 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
- package/src/__tests__/memory-observation-archive.test.ts +375 -0
- package/src/__tests__/memory-observation-dual-write.test.ts +318 -0
- package/src/__tests__/memory-recall-quality.test.ts +7 -7
- package/src/__tests__/memory-reducer-store.test.ts +728 -0
- package/src/__tests__/memory-reducer-types.test.ts +699 -0
- package/src/__tests__/memory-reducer.test.ts +698 -0
- package/src/__tests__/memory-regressions.test.ts +6 -4
- package/src/__tests__/memory-simplified-config.test.ts +281 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
- package/src/__tests__/migration-export-http.test.ts +3 -1
- package/src/__tests__/migration-import-commit-http.test.ts +18 -4
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
- package/src/__tests__/mime-builder.test.ts +3 -2
- package/src/__tests__/non-member-access-request.test.ts +12 -1
- package/src/__tests__/notification-decision-identity.test.ts +52 -0
- package/src/__tests__/oauth-apps-routes.test.ts +103 -0
- package/src/__tests__/oauth-store.test.ts +115 -0
- package/src/__tests__/parse-identity-fields.test.ts +129 -0
- package/src/__tests__/provider-error-scenarios.test.ts +1 -3
- package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
- package/src/__tests__/recording-handler.test.ts +17 -0
- package/src/__tests__/registry.test.ts +3 -8
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
- package/src/__tests__/schema-transforms.test.ts +165 -5
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/skill-load-inline-command.test.ts +598 -0
- package/src/__tests__/skill-load-inline-includes.test.ts +644 -0
- package/src/__tests__/skills-inline-command-expansions.test.ts +301 -0
- package/src/__tests__/skills-transitive-hash.test.ts +333 -0
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -2
- package/src/__tests__/starter-task-flow.test.ts +1 -0
- package/src/__tests__/suggestion-routes.test.ts +443 -0
- package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
- package/src/__tests__/swarm-recursion.test.ts +1 -0
- package/src/__tests__/swarm-tool.test.ts +1 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
- package/src/__tests__/top-level-renderer.test.ts +22 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +320 -0
- package/src/__tests__/web-fetch.test.ts +6 -2
- package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
- package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
- package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
- package/src/agent/attachments.ts +27 -1
- package/src/agent/loop.ts +29 -1
- package/src/avatar/traits-png-sync.ts +80 -25
- package/src/bundler/app-bundler.ts +4 -4
- package/src/calls/call-domain.ts +1 -0
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/commands/auth.ts +92 -0
- package/src/cli/commands/avatar.ts +7 -6
- package/src/cli/commands/config.ts +2 -0
- package/src/cli/commands/oauth/providers.ts +29 -0
- package/src/cli/program.ts +12 -0
- package/src/cli.ts +15 -48
- package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
- package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
- package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
- package/src/config/bundled-tool-registry.ts +2 -14
- package/src/config/feature-flag-registry.json +24 -0
- package/src/config/loader.ts +65 -0
- package/src/config/raw-config-utils.ts +58 -0
- package/src/config/schema-utils.ts +28 -7
- package/src/config/schema.ts +20 -0
- package/src/config/schemas/elevenlabs.ts +18 -0
- package/src/config/schemas/memory-lifecycle.ts +4 -2
- package/src/config/schemas/memory-simplified.ts +101 -0
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +8 -6
- package/src/config/skills.ts +50 -4
- package/src/contacts/contact-store.ts +13 -6
- package/src/contacts/contacts-write.ts +0 -1
- package/src/context/window-manager.ts +13 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +54 -8
- package/src/daemon/conversation-agent-loop.ts +127 -20
- package/src/daemon/conversation-attachments.ts +18 -36
- package/src/daemon/conversation-error.ts +2 -1
- package/src/daemon/conversation-history.ts +18 -4
- package/src/daemon/conversation-lifecycle.ts +50 -16
- package/src/daemon/conversation-messaging.ts +70 -26
- package/src/daemon/conversation-process.ts +58 -34
- package/src/daemon/conversation-runtime-assembly.ts +22 -38
- package/src/daemon/conversation-slash.ts +121 -256
- package/src/daemon/conversation-surfaces.ts +170 -24
- package/src/daemon/conversation-tool-setup.ts +0 -6
- package/src/daemon/conversation-workspace.ts +21 -1
- package/src/daemon/conversation.ts +69 -30
- package/src/daemon/first-greeting.ts +35 -0
- package/src/daemon/handlers/config-embeddings.ts +156 -0
- package/src/daemon/handlers/config-model.ts +62 -26
- package/src/daemon/handlers/conversations.ts +0 -23
- package/src/daemon/handlers/identity.ts +12 -1
- package/src/daemon/handlers/recording.ts +26 -21
- package/src/daemon/host-cu-proxy.ts +2 -2
- package/src/daemon/lifecycle.ts +115 -65
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +18 -0
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/shared.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/upgrades.ts +23 -0
- package/src/daemon/server.ts +83 -12
- package/src/daemon/shutdown-handlers.ts +8 -5
- package/src/daemon/startup-error.ts +9 -0
- package/src/daemon/tool-side-effects.ts +11 -28
- package/src/events/tool-permission-telemetry-listener.ts +1 -3
- package/src/followups/followup-store.ts +47 -1
- package/src/instrument.ts +0 -4
- package/src/media/app-icon-generator.ts +2 -2
- package/src/memory/app-git-service.ts +28 -16
- package/src/memory/app-store.ts +230 -41
- package/src/memory/archive-store.ts +400 -0
- package/src/memory/attachments-store.ts +558 -130
- package/src/memory/brief-formatting.ts +33 -0
- package/src/memory/brief-open-loops.ts +266 -0
- package/src/memory/brief-time.ts +161 -0
- package/src/memory/brief.ts +75 -0
- package/src/memory/conversation-attention-store.ts +70 -0
- package/src/memory/conversation-crud.ts +591 -8
- package/src/memory/conversation-directories.ts +125 -0
- package/src/memory/conversation-disk-view.ts +390 -0
- package/src/memory/conversation-key-store.ts +17 -5
- package/src/memory/conversation-queries.ts +5 -1
- package/src/memory/conversation-title-service.ts +21 -49
- package/src/memory/db-init.ts +40 -0
- package/src/memory/embedding-backend.ts +42 -53
- package/src/memory/embedding-gemini.test.ts +4 -4
- package/src/memory/embedding-local.ts +1 -3
- package/src/memory/embedding-ollama.ts +1 -3
- package/src/memory/embedding-openai.ts +1 -3
- package/src/memory/indexer.ts +114 -21
- package/src/memory/items-extractor.ts +42 -13
- package/src/memory/job-handlers/conversation-starters.ts +6 -1
- package/src/memory/job-handlers/embedding.test.ts +2 -4
- package/src/memory/job-handlers/embedding.ts +83 -0
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +6 -0
- package/src/memory/jobs-worker.ts +12 -0
- package/src/memory/llm-request-log-store.ts +100 -1
- package/src/memory/migrations/102-alter-table-columns.ts +5 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
- package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
- package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
- package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
- package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
- package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
- package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
- package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
- package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
- package/src/memory/migrations/185-memory-brief-state.ts +52 -0
- package/src/memory/migrations/186-memory-archive.ts +109 -0
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +19 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/qdrant-client.ts +23 -4
- package/src/memory/reducer-store.ts +271 -0
- package/src/memory/reducer-types.ts +99 -0
- package/src/memory/reducer.ts +453 -0
- package/src/memory/retriever.test.ts +601 -2
- package/src/memory/retriever.ts +85 -9
- package/src/memory/schema/conversations.ts +9 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/infrastructure.ts +13 -7
- package/src/memory/schema/memory-archive.ts +121 -0
- package/src/memory/schema/memory-brief.ts +55 -0
- package/src/memory/schema/oauth.ts +6 -0
- package/src/memory/search/semantic.ts +17 -4
- package/src/messaging/providers/gmail/mime-builder.ts +3 -1
- package/src/notifications/copy-composer.ts +26 -0
- package/src/notifications/decision-engine.ts +14 -1
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +36 -0
- package/src/oauth/byo-connection.test.ts +1 -45
- package/src/oauth/byo-connection.ts +2 -8
- package/src/oauth/connect-orchestrator.ts +15 -11
- package/src/oauth/connection-resolver.test.ts +191 -0
- package/src/oauth/connection-resolver.ts +66 -38
- package/src/oauth/connection.ts +0 -1
- package/src/oauth/oauth-store.ts +99 -47
- package/src/oauth/platform-connection.test.ts +0 -1
- package/src/oauth/platform-connection.ts +11 -3
- package/src/oauth/seed-providers.ts +78 -3
- package/src/oauth/token-persistence.ts +16 -10
- package/src/permissions/checker.ts +160 -14
- package/src/permissions/defaults.ts +14 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -0
- package/src/providers/anthropic/client.ts +8 -1
- package/src/providers/failover.ts +4 -1
- package/src/providers/gemini/client.ts +50 -0
- package/src/providers/model-catalog.ts +92 -0
- package/src/providers/model-intents.ts +29 -20
- package/src/providers/openai/client.ts +49 -0
- package/src/providers/types.ts +2 -0
- package/src/runtime/access-request-helper.ts +16 -7
- package/src/runtime/auth/credential-service.ts +3 -1
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/btw-sidechain.ts +101 -0
- package/src/runtime/channel-reply-delivery.ts +17 -1
- package/src/runtime/http-router.ts +3 -1
- package/src/runtime/http-server.ts +196 -141
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/migrations/vbundle-builder.ts +5 -1
- package/src/runtime/routes/access-request-decision.ts +41 -0
- package/src/runtime/routes/app-management-routes.ts +6 -3
- package/src/runtime/routes/app-routes.ts +7 -3
- package/src/runtime/routes/approval-routes.ts +1 -0
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
- package/src/runtime/routes/attachment-routes.ts +45 -15
- package/src/runtime/routes/btw-routes.ts +21 -61
- package/src/runtime/routes/conversation-management-routes.ts +74 -0
- package/src/runtime/routes/conversation-query-routes.ts +187 -10
- package/src/runtime/routes/conversation-routes.ts +269 -28
- package/src/runtime/routes/conversation-starter-routes.ts +9 -11
- package/src/runtime/routes/diagnostics-routes.ts +1 -0
- package/src/runtime/routes/identity-routes.ts +2 -35
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
- package/src/runtime/routes/llm-context-normalization.ts +1212 -0
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/memory-item-routes.test.ts +34 -0
- package/src/runtime/routes/memory-item-routes.ts +94 -5
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/oauth-apps.ts +291 -0
- package/src/runtime/routes/secret-routes.ts +30 -1
- package/src/runtime/routes/settings-routes.ts +14 -0
- package/src/runtime/routes/surface-action-routes.ts +68 -1
- package/src/runtime/routes/trace-event-routes.ts +4 -1
- package/src/schedule/schedule-store.ts +30 -21
- package/src/security/secure-keys.ts +21 -0
- package/src/signals/bash.ts +1 -1
- package/src/skills/inline-command-expansions.ts +204 -0
- package/src/skills/inline-command-render.ts +127 -0
- package/src/skills/inline-command-runner.ts +242 -0
- package/src/skills/transitive-version-hash.ts +88 -0
- package/src/swarm/backend-claude-code.ts +3 -6
- package/src/tasks/task-store.ts +43 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +3 -1
- package/src/tools/AGENTS.md +6 -10
- package/src/tools/apps/executors.ts +17 -232
- package/src/tools/claude-code/claude-code.ts +2 -3
- package/src/tools/credentials/vault.ts +7 -12
- package/src/tools/host-filesystem/read.ts +13 -10
- package/src/tools/network/__tests__/web-search.test.ts +4 -2
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/schedule/list.ts +2 -7
- package/src/tools/schema-transforms.ts +5 -0
- package/src/tools/shared/filesystem/format-diff.ts +2 -7
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +140 -6
- package/src/tools/tool-manifest.ts +0 -6
- package/src/tools/ui-surface/definitions.ts +2 -2
- package/src/util/device-id.ts +28 -5
- package/src/util/platform.ts +24 -0
- package/src/util/pricing.ts +1 -0
- package/src/util/retry.ts +1 -3
- package/src/workspace/migrations/003-seed-device-id.ts +3 -4
- package/src/workspace/migrations/006-services-config.ts +5 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
- package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts} +24 -13
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
- package/src/workspace/migrations/registry.ts +11 -1
- package/src/workspace/top-level-renderer.ts +12 -0
- package/src/__tests__/asset-materialize-tool.test.ts +0 -523
- package/src/__tests__/asset-search-tool.test.ts +0 -536
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
- package/src/__tests__/media-visibility-policy.test.ts +0 -190
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
- package/src/daemon/media-visibility-policy.ts +0 -59
- package/src/tools/assets/materialize.ts +0 -248
- package/src/tools/assets/search.ts +0 -400
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
37
37
|
import { PairingStore } from "../daemon/pairing-store.js";
|
|
38
38
|
import {
|
|
39
|
+
type AttentionState,
|
|
39
40
|
type Confidence,
|
|
40
41
|
getAttentionStateByConversationIds,
|
|
41
42
|
markConversationUnread,
|
|
@@ -43,6 +44,8 @@ import {
|
|
|
43
44
|
type SignalType,
|
|
44
45
|
} from "../memory/conversation-attention-store.js";
|
|
45
46
|
import {
|
|
47
|
+
type ConversationRow,
|
|
48
|
+
forkConversation as forkConversationInStore,
|
|
46
49
|
getConversation,
|
|
47
50
|
getDisplayMetaForConversations,
|
|
48
51
|
} from "../memory/conversation-crud.js";
|
|
@@ -51,6 +54,7 @@ import {
|
|
|
51
54
|
countConversations,
|
|
52
55
|
listConversations,
|
|
53
56
|
} from "../memory/conversation-queries.js";
|
|
57
|
+
import type { ExternalConversationBinding } from "../memory/external-conversation-store.js";
|
|
54
58
|
import * as externalConversationStore from "../memory/external-conversation-store.js";
|
|
55
59
|
import {
|
|
56
60
|
consumeCallback,
|
|
@@ -122,7 +126,10 @@ import {
|
|
|
122
126
|
contactRouteDefinitions,
|
|
123
127
|
} from "./routes/contact-routes.js";
|
|
124
128
|
import { conversationAttentionRouteDefinitions } from "./routes/conversation-attention-routes.js";
|
|
125
|
-
import {
|
|
129
|
+
import {
|
|
130
|
+
type ConversationManagementDeps,
|
|
131
|
+
conversationManagementRouteDefinitions,
|
|
132
|
+
} from "./routes/conversation-management-routes.js";
|
|
126
133
|
import { conversationQueryRouteDefinitions } from "./routes/conversation-query-routes.js";
|
|
127
134
|
import { conversationRouteDefinitions } from "./routes/conversation-routes.js";
|
|
128
135
|
import { conversationStarterRouteDefinitions } from "./routes/conversation-starter-routes.js";
|
|
@@ -147,6 +154,7 @@ import { inviteRouteDefinitions } from "./routes/invite-routes.js";
|
|
|
147
154
|
import { logExportRouteDefinitions } from "./routes/log-export-routes.js";
|
|
148
155
|
import { memoryItemRouteDefinitions } from "./routes/memory-item-routes.js";
|
|
149
156
|
import { migrationRouteDefinitions } from "./routes/migration-routes.js";
|
|
157
|
+
import { oauthAppsRouteDefinitions } from "./routes/oauth-apps.js";
|
|
150
158
|
import type { PairingHandlerContext } from "./routes/pairing-routes.js";
|
|
151
159
|
import {
|
|
152
160
|
handlePairingRequest,
|
|
@@ -713,6 +721,175 @@ export class RuntimeHttpServer {
|
|
|
713
721
|
});
|
|
714
722
|
}
|
|
715
723
|
|
|
724
|
+
private buildAssistantAttention(attentionState: AttentionState | undefined):
|
|
725
|
+
| {
|
|
726
|
+
hasUnseenLatestAssistantMessage: boolean;
|
|
727
|
+
latestAssistantMessageAt?: number;
|
|
728
|
+
lastSeenAssistantMessageAt?: number;
|
|
729
|
+
lastSeenConfidence?: Confidence;
|
|
730
|
+
lastSeenSignalType?: SignalType;
|
|
731
|
+
}
|
|
732
|
+
| undefined {
|
|
733
|
+
if (!attentionState) return undefined;
|
|
734
|
+
|
|
735
|
+
return {
|
|
736
|
+
hasUnseenLatestAssistantMessage:
|
|
737
|
+
attentionState.latestAssistantMessageAt != null &&
|
|
738
|
+
(attentionState.lastSeenAssistantMessageAt == null ||
|
|
739
|
+
attentionState.lastSeenAssistantMessageAt <
|
|
740
|
+
attentionState.latestAssistantMessageAt),
|
|
741
|
+
...(attentionState.latestAssistantMessageAt != null
|
|
742
|
+
? {
|
|
743
|
+
latestAssistantMessageAt: attentionState.latestAssistantMessageAt,
|
|
744
|
+
}
|
|
745
|
+
: {}),
|
|
746
|
+
...(attentionState.lastSeenAssistantMessageAt != null
|
|
747
|
+
? {
|
|
748
|
+
lastSeenAssistantMessageAt:
|
|
749
|
+
attentionState.lastSeenAssistantMessageAt,
|
|
750
|
+
}
|
|
751
|
+
: {}),
|
|
752
|
+
...(attentionState.lastSeenConfidence != null
|
|
753
|
+
? { lastSeenConfidence: attentionState.lastSeenConfidence }
|
|
754
|
+
: {}),
|
|
755
|
+
...(attentionState.lastSeenSignalType != null
|
|
756
|
+
? { lastSeenSignalType: attentionState.lastSeenSignalType }
|
|
757
|
+
: {}),
|
|
758
|
+
};
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
private buildForkParent(
|
|
762
|
+
conversation: ConversationRow,
|
|
763
|
+
parentCache: Map<string, ConversationRow | null>,
|
|
764
|
+
): { conversationId: string; messageId: string; title: string } | undefined {
|
|
765
|
+
const parentConversationId = conversation.forkParentConversationId;
|
|
766
|
+
const parentMessageId = conversation.forkParentMessageId;
|
|
767
|
+
if (!parentConversationId || !parentMessageId) return undefined;
|
|
768
|
+
|
|
769
|
+
let parentConversation: ConversationRow | null | undefined =
|
|
770
|
+
parentCache.get(parentConversationId);
|
|
771
|
+
if (parentConversation === undefined) {
|
|
772
|
+
parentConversation = getConversation(parentConversationId);
|
|
773
|
+
parentCache.set(parentConversationId, parentConversation);
|
|
774
|
+
}
|
|
775
|
+
if (
|
|
776
|
+
!parentConversation ||
|
|
777
|
+
parentConversation.conversationType === "private"
|
|
778
|
+
) {
|
|
779
|
+
return undefined;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return {
|
|
783
|
+
conversationId: parentConversationId,
|
|
784
|
+
messageId: parentMessageId,
|
|
785
|
+
title: parentConversation.title ?? "Untitled",
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
private serializeConversationSummary(params: {
|
|
790
|
+
conversation: ConversationRow;
|
|
791
|
+
binding?: ExternalConversationBinding | null;
|
|
792
|
+
attentionState?: AttentionState;
|
|
793
|
+
displayMeta?: { displayOrder: number | null; isPinned: boolean };
|
|
794
|
+
parentCache: Map<string, ConversationRow | null>;
|
|
795
|
+
}) {
|
|
796
|
+
const { conversation, binding, attentionState, displayMeta, parentCache } =
|
|
797
|
+
params;
|
|
798
|
+
const originChannel = parseChannelId(conversation.originChannel);
|
|
799
|
+
const assistantAttention = this.buildAssistantAttention(attentionState);
|
|
800
|
+
const forkParent = this.buildForkParent(conversation, parentCache);
|
|
801
|
+
|
|
802
|
+
return {
|
|
803
|
+
id: conversation.id,
|
|
804
|
+
title: conversation.title ?? "Untitled",
|
|
805
|
+
createdAt: conversation.createdAt,
|
|
806
|
+
updatedAt: conversation.updatedAt,
|
|
807
|
+
conversationType:
|
|
808
|
+
conversation.conversationType === "private" ? "private" : "standard",
|
|
809
|
+
source: conversation.source ?? "user",
|
|
810
|
+
...(conversation.scheduleJobId
|
|
811
|
+
? { scheduleJobId: conversation.scheduleJobId }
|
|
812
|
+
: {}),
|
|
813
|
+
...(binding
|
|
814
|
+
? {
|
|
815
|
+
channelBinding: {
|
|
816
|
+
sourceChannel: binding.sourceChannel,
|
|
817
|
+
externalChatId: binding.externalChatId,
|
|
818
|
+
externalUserId: binding.externalUserId,
|
|
819
|
+
displayName: binding.displayName,
|
|
820
|
+
username: binding.username,
|
|
821
|
+
},
|
|
822
|
+
}
|
|
823
|
+
: {}),
|
|
824
|
+
...(originChannel ? { conversationOriginChannel: originChannel } : {}),
|
|
825
|
+
...(assistantAttention ? { assistantAttention } : {}),
|
|
826
|
+
...(displayMeta?.isPinned
|
|
827
|
+
? {
|
|
828
|
+
isPinned: true as const,
|
|
829
|
+
displayOrder: displayMeta.displayOrder,
|
|
830
|
+
}
|
|
831
|
+
: displayMeta?.displayOrder != null
|
|
832
|
+
? {
|
|
833
|
+
displayOrder: displayMeta.displayOrder,
|
|
834
|
+
}
|
|
835
|
+
: {}),
|
|
836
|
+
...(forkParent ? { forkParent } : {}),
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
private buildConversationDetailResponse(conversationId: string) {
|
|
841
|
+
const conversation = getConversation(conversationId);
|
|
842
|
+
if (!conversation) {
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
const bindings = externalConversationStore.getBindingsForConversations([
|
|
847
|
+
conversation.id,
|
|
848
|
+
]);
|
|
849
|
+
const attentionStates = getAttentionStateByConversationIds([
|
|
850
|
+
conversation.id,
|
|
851
|
+
]);
|
|
852
|
+
const displayMeta = getDisplayMetaForConversations([conversation.id]);
|
|
853
|
+
const parentCache = new Map<string, ConversationRow | null>();
|
|
854
|
+
|
|
855
|
+
return {
|
|
856
|
+
conversation: this.serializeConversationSummary({
|
|
857
|
+
conversation,
|
|
858
|
+
binding: bindings.get(conversation.id),
|
|
859
|
+
attentionState: attentionStates.get(conversation.id),
|
|
860
|
+
displayMeta: displayMeta.get(conversation.id),
|
|
861
|
+
parentCache,
|
|
862
|
+
}),
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
private getConversationManagementRouteDeps(): ConversationManagementDeps | null {
|
|
867
|
+
if (!this.conversationManagementDeps) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return {
|
|
872
|
+
...this.conversationManagementDeps,
|
|
873
|
+
forkConversation:
|
|
874
|
+
this.conversationManagementDeps.forkConversation ??
|
|
875
|
+
(async ({ conversationId, throughMessageId }) => {
|
|
876
|
+
const forkedConversation = forkConversationInStore({
|
|
877
|
+
conversationId,
|
|
878
|
+
throughMessageId,
|
|
879
|
+
});
|
|
880
|
+
const detail = this.buildConversationDetailResponse(
|
|
881
|
+
forkedConversation.id,
|
|
882
|
+
);
|
|
883
|
+
if (!detail) {
|
|
884
|
+
throw new Error(
|
|
885
|
+
`Forked conversation ${forkedConversation.id} could not be loaded`,
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
return detail.conversation;
|
|
889
|
+
}),
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
|
|
716
893
|
// ---------------------------------------------------------------------------
|
|
717
894
|
// Declarative route table
|
|
718
895
|
// ---------------------------------------------------------------------------
|
|
@@ -728,6 +905,8 @@ export class RuntimeHttpServer {
|
|
|
728
905
|
*/
|
|
729
906
|
private buildRouteTable(): RouteDefinition[] {
|
|
730
907
|
const assistantId = DAEMON_INTERNAL_ASSISTANT_ID;
|
|
908
|
+
const conversationManagementDeps =
|
|
909
|
+
this.getConversationManagementRouteDeps();
|
|
731
910
|
|
|
732
911
|
return [
|
|
733
912
|
...pairingRouteDefinitions({
|
|
@@ -823,84 +1002,25 @@ export class RuntimeHttpServer {
|
|
|
823
1002
|
);
|
|
824
1003
|
const attentionStates =
|
|
825
1004
|
getAttentionStateByConversationIds(conversationIds);
|
|
1005
|
+
const parentCache = new Map<string, ConversationRow | null>();
|
|
826
1006
|
return Response.json({
|
|
827
|
-
conversations: conversations.map((
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
attn.lastSeenAssistantMessageAt <
|
|
837
|
-
attn.latestAssistantMessageAt),
|
|
838
|
-
...(attn.latestAssistantMessageAt != null
|
|
839
|
-
? {
|
|
840
|
-
latestAssistantMessageAt:
|
|
841
|
-
attn.latestAssistantMessageAt,
|
|
842
|
-
}
|
|
843
|
-
: {}),
|
|
844
|
-
...(attn.lastSeenAssistantMessageAt != null
|
|
845
|
-
? {
|
|
846
|
-
lastSeenAssistantMessageAt:
|
|
847
|
-
attn.lastSeenAssistantMessageAt,
|
|
848
|
-
}
|
|
849
|
-
: {}),
|
|
850
|
-
...(attn.lastSeenConfidence != null
|
|
851
|
-
? { lastSeenConfidence: attn.lastSeenConfidence }
|
|
852
|
-
: {}),
|
|
853
|
-
...(attn.lastSeenSignalType != null
|
|
854
|
-
? { lastSeenSignalType: attn.lastSeenSignalType }
|
|
855
|
-
: {}),
|
|
856
|
-
}
|
|
857
|
-
: undefined;
|
|
858
|
-
return {
|
|
859
|
-
id: c.id,
|
|
860
|
-
title: c.title ?? "Untitled",
|
|
861
|
-
createdAt: c.createdAt,
|
|
862
|
-
updatedAt: c.updatedAt,
|
|
863
|
-
conversationType:
|
|
864
|
-
c.conversationType === "private" ? "private" : "standard",
|
|
865
|
-
source: c.source ?? "user",
|
|
866
|
-
...(c.scheduleJobId ? { scheduleJobId: c.scheduleJobId } : {}),
|
|
867
|
-
...(binding
|
|
868
|
-
? {
|
|
869
|
-
channelBinding: {
|
|
870
|
-
sourceChannel: binding.sourceChannel,
|
|
871
|
-
externalChatId: binding.externalChatId,
|
|
872
|
-
externalUserId: binding.externalUserId,
|
|
873
|
-
displayName: binding.displayName,
|
|
874
|
-
username: binding.username,
|
|
875
|
-
},
|
|
876
|
-
}
|
|
877
|
-
: {}),
|
|
878
|
-
...(originChannel
|
|
879
|
-
? { conversationOriginChannel: originChannel }
|
|
880
|
-
: {}),
|
|
881
|
-
...(assistantAttention ? { assistantAttention } : {}),
|
|
882
|
-
...(displayMeta.get(c.id)?.isPinned
|
|
883
|
-
? {
|
|
884
|
-
isPinned: true,
|
|
885
|
-
displayOrder: displayMeta.get(c.id)!.displayOrder,
|
|
886
|
-
}
|
|
887
|
-
: displayMeta.get(c.id)?.displayOrder != null
|
|
888
|
-
? {
|
|
889
|
-
displayOrder: displayMeta.get(c.id)!.displayOrder,
|
|
890
|
-
}
|
|
891
|
-
: {}),
|
|
892
|
-
};
|
|
893
|
-
}),
|
|
1007
|
+
conversations: conversations.map((conversation) =>
|
|
1008
|
+
this.serializeConversationSummary({
|
|
1009
|
+
conversation,
|
|
1010
|
+
binding: bindings.get(conversation.id),
|
|
1011
|
+
attentionState: attentionStates.get(conversation.id),
|
|
1012
|
+
displayMeta: displayMeta.get(conversation.id),
|
|
1013
|
+
parentCache,
|
|
1014
|
+
}),
|
|
1015
|
+
),
|
|
894
1016
|
hasMore: offset + conversations.length < totalCount,
|
|
895
1017
|
});
|
|
896
1018
|
},
|
|
897
1019
|
},
|
|
898
1020
|
...conversationAttentionRouteDefinitions(),
|
|
899
1021
|
|
|
900
|
-
...(
|
|
901
|
-
? conversationManagementRouteDefinitions(
|
|
902
|
-
this.conversationManagementDeps,
|
|
903
|
-
)
|
|
1022
|
+
...(conversationManagementDeps
|
|
1023
|
+
? conversationManagementRouteDefinitions(conversationManagementDeps)
|
|
904
1024
|
: []),
|
|
905
1025
|
|
|
906
1026
|
{
|
|
@@ -990,81 +1110,15 @@ export class RuntimeHttpServer {
|
|
|
990
1110
|
endpoint: "conversations/:id",
|
|
991
1111
|
method: "GET",
|
|
992
1112
|
handler: ({ params }) => {
|
|
993
|
-
const
|
|
994
|
-
if (!
|
|
1113
|
+
const detail = this.buildConversationDetailResponse(params.id);
|
|
1114
|
+
if (!detail) {
|
|
995
1115
|
return httpError(
|
|
996
1116
|
"NOT_FOUND",
|
|
997
1117
|
`Conversation ${params.id} not found`,
|
|
998
1118
|
404,
|
|
999
1119
|
);
|
|
1000
1120
|
}
|
|
1001
|
-
|
|
1002
|
-
externalConversationStore.getBindingsForConversations([
|
|
1003
|
-
conversation.id,
|
|
1004
|
-
]);
|
|
1005
|
-
const attentionStates = getAttentionStateByConversationIds([
|
|
1006
|
-
conversation.id,
|
|
1007
|
-
]);
|
|
1008
|
-
const binding = bindings.get(conversation.id);
|
|
1009
|
-
const originChannel = parseChannelId(conversation.originChannel);
|
|
1010
|
-
const attn = attentionStates.get(conversation.id);
|
|
1011
|
-
const assistantAttention = attn
|
|
1012
|
-
? {
|
|
1013
|
-
hasUnseenLatestAssistantMessage:
|
|
1014
|
-
attn.latestAssistantMessageAt != null &&
|
|
1015
|
-
(attn.lastSeenAssistantMessageAt == null ||
|
|
1016
|
-
attn.lastSeenAssistantMessageAt <
|
|
1017
|
-
attn.latestAssistantMessageAt),
|
|
1018
|
-
...(attn.latestAssistantMessageAt != null
|
|
1019
|
-
? {
|
|
1020
|
-
latestAssistantMessageAt: attn.latestAssistantMessageAt,
|
|
1021
|
-
}
|
|
1022
|
-
: {}),
|
|
1023
|
-
...(attn.lastSeenAssistantMessageAt != null
|
|
1024
|
-
? {
|
|
1025
|
-
lastSeenAssistantMessageAt:
|
|
1026
|
-
attn.lastSeenAssistantMessageAt,
|
|
1027
|
-
}
|
|
1028
|
-
: {}),
|
|
1029
|
-
...(attn.lastSeenConfidence != null
|
|
1030
|
-
? { lastSeenConfidence: attn.lastSeenConfidence }
|
|
1031
|
-
: {}),
|
|
1032
|
-
...(attn.lastSeenSignalType != null
|
|
1033
|
-
? { lastSeenSignalType: attn.lastSeenSignalType }
|
|
1034
|
-
: {}),
|
|
1035
|
-
}
|
|
1036
|
-
: undefined;
|
|
1037
|
-
return Response.json({
|
|
1038
|
-
conversation: {
|
|
1039
|
-
id: conversation.id,
|
|
1040
|
-
title: conversation.title ?? "Untitled",
|
|
1041
|
-
createdAt: conversation.createdAt,
|
|
1042
|
-
updatedAt: conversation.updatedAt,
|
|
1043
|
-
conversationType:
|
|
1044
|
-
conversation.conversationType === "private"
|
|
1045
|
-
? "private"
|
|
1046
|
-
: "standard",
|
|
1047
|
-
source: conversation.source ?? "user",
|
|
1048
|
-
...(conversation.scheduleJobId
|
|
1049
|
-
? { scheduleJobId: conversation.scheduleJobId }
|
|
1050
|
-
: {}),
|
|
1051
|
-
...(binding
|
|
1052
|
-
? {
|
|
1053
|
-
channelBinding: {
|
|
1054
|
-
sourceChannel: binding.sourceChannel,
|
|
1055
|
-
externalChatId: binding.externalChatId,
|
|
1056
|
-
externalUserId: binding.externalUserId,
|
|
1057
|
-
displayName: binding.displayName,
|
|
1058
|
-
username: binding.username,
|
|
1059
|
-
},
|
|
1060
|
-
}
|
|
1061
|
-
: {}),
|
|
1062
|
-
...(originChannel
|
|
1063
|
-
? { conversationOriginChannel: originChannel }
|
|
1064
|
-
: {}),
|
|
1065
|
-
...(assistantAttention ? { assistantAttention } : {}),
|
|
1066
|
-
},
|
|
1067
|
-
});
|
|
1121
|
+
return Response.json(detail);
|
|
1068
1122
|
},
|
|
1069
1123
|
},
|
|
1070
1124
|
|
|
@@ -1110,6 +1164,7 @@ export class RuntimeHttpServer {
|
|
|
1110
1164
|
...slackShareRouteDefinitions(),
|
|
1111
1165
|
...twilioRouteDefinitions(),
|
|
1112
1166
|
...channelReadinessRouteDefinitions(),
|
|
1167
|
+
...oauthAppsRouteDefinitions(),
|
|
1113
1168
|
...attachmentRouteDefinitions(),
|
|
1114
1169
|
|
|
1115
1170
|
...(this.getWatchDeps
|
|
@@ -447,7 +447,11 @@ export function buildExportVBundle(
|
|
|
447
447
|
|
|
448
448
|
// Walk the entire workspace directory, including binary files (DB,
|
|
449
449
|
// attachments) but skipping large/regenerable subdirectories.
|
|
450
|
-
if (
|
|
450
|
+
if (
|
|
451
|
+
workspaceDir &&
|
|
452
|
+
existsSync(workspaceDir) &&
|
|
453
|
+
lstatSync(workspaceDir).isDirectory()
|
|
454
|
+
) {
|
|
451
455
|
files.push(
|
|
452
456
|
...walkDirectory(workspaceDir, "workspace", {
|
|
453
457
|
includeBinary: true,
|
|
@@ -174,6 +174,47 @@ function resolveRequesterTarget(params: {
|
|
|
174
174
|
};
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Deliver the verification code directly to the requester's DM on Slack,
|
|
179
|
+
* removing the need for the guardian to manually share it.
|
|
180
|
+
*/
|
|
181
|
+
export async function deliverVerificationCodeToRequester(params: {
|
|
182
|
+
replyCallbackUrl: string;
|
|
183
|
+
requesterChatId: string;
|
|
184
|
+
verificationCode: string;
|
|
185
|
+
assistantId: string;
|
|
186
|
+
bearerToken?: string;
|
|
187
|
+
channel?: string;
|
|
188
|
+
requesterExternalUserId?: string;
|
|
189
|
+
}): Promise<DeliveryResult> {
|
|
190
|
+
const text =
|
|
191
|
+
`Great news — your access request was approved! ` +
|
|
192
|
+
`Your verification code is: ${params.verificationCode}. ` +
|
|
193
|
+
`Reply with it here to complete verification. The code expires in 10 minutes.`;
|
|
194
|
+
|
|
195
|
+
const target = resolveRequesterTarget(params);
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
await deliverChannelReply(
|
|
199
|
+
target.callbackUrl,
|
|
200
|
+
{
|
|
201
|
+
chatId: target.chatId,
|
|
202
|
+
text,
|
|
203
|
+
assistantId: params.assistantId,
|
|
204
|
+
},
|
|
205
|
+
params.bearerToken,
|
|
206
|
+
);
|
|
207
|
+
return { ok: true };
|
|
208
|
+
} catch (err) {
|
|
209
|
+
log.error(
|
|
210
|
+
{ err, requesterChatId: params.requesterChatId },
|
|
211
|
+
"Failed to deliver verification code to requester",
|
|
212
|
+
);
|
|
213
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
214
|
+
return { ok: false, reason };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
177
218
|
/**
|
|
178
219
|
* Notify the requester that the guardian has approved their access request
|
|
179
220
|
* and they should enter the verification code they receive from the guardian.
|
|
@@ -34,11 +34,12 @@ import {
|
|
|
34
34
|
deleteApp,
|
|
35
35
|
deleteAppRecord,
|
|
36
36
|
getApp,
|
|
37
|
+
getAppDirPath,
|
|
37
38
|
getAppPreview,
|
|
38
|
-
getAppsDir,
|
|
39
39
|
isMultifileApp,
|
|
40
40
|
listApps,
|
|
41
41
|
queryAppRecords,
|
|
42
|
+
resolveAppDir,
|
|
42
43
|
updateApp,
|
|
43
44
|
updateAppRecord,
|
|
44
45
|
} from "../../memory/app-store.js";
|
|
@@ -289,7 +290,7 @@ async function installGalleryApp(
|
|
|
289
290
|
});
|
|
290
291
|
|
|
291
292
|
if (galleryApp.formatVersion === 2 && galleryApp.sourceFiles) {
|
|
292
|
-
const appDir =
|
|
293
|
+
const appDir = getAppDirPath(app.id);
|
|
293
294
|
for (const [relPath, content] of Object.entries(galleryApp.sourceFiles)) {
|
|
294
295
|
const fullPath = join(appDir, relPath);
|
|
295
296
|
mkdirSync(dirname(fullPath), { recursive: true });
|
|
@@ -671,7 +672,7 @@ export function appManagementRouteDefinitions(): RouteDefinition[] {
|
|
|
671
672
|
let html = app.htmlDefinition;
|
|
672
673
|
|
|
673
674
|
if (isMultifileApp(app)) {
|
|
674
|
-
const appDir =
|
|
675
|
+
const appDir = getAppDirPath(appId);
|
|
675
676
|
const distIndex = join(appDir, "dist", "index.html");
|
|
676
677
|
if (!existsSync(distIndex)) {
|
|
677
678
|
const result = await compileApp(appDir);
|
|
@@ -689,8 +690,10 @@ export function appManagementRouteDefinitions(): RouteDefinition[] {
|
|
|
689
690
|
}
|
|
690
691
|
}
|
|
691
692
|
|
|
693
|
+
const { dirName } = resolveAppDir(app.id);
|
|
692
694
|
return Response.json({
|
|
693
695
|
appId: app.id,
|
|
696
|
+
dirName,
|
|
694
697
|
name: app.name,
|
|
695
698
|
html,
|
|
696
699
|
});
|
|
@@ -8,7 +8,11 @@ import { extname, join } from "node:path";
|
|
|
8
8
|
import JSZip from "jszip";
|
|
9
9
|
|
|
10
10
|
import type { AppManifest } from "../../bundler/manifest.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
getApp,
|
|
13
|
+
getAppDirPath,
|
|
14
|
+
isMultifileApp,
|
|
15
|
+
} from "../../memory/app-store.js";
|
|
12
16
|
import * as sharedAppLinksStore from "../../memory/shared-app-links-store.js";
|
|
13
17
|
import { getLogger } from "../../util/logger.js";
|
|
14
18
|
import { httpError } from "../http-errors.js";
|
|
@@ -109,7 +113,7 @@ ${noncedHtml}
|
|
|
109
113
|
* Falls back to a "not compiled yet" message if dist/index.html is missing.
|
|
110
114
|
*/
|
|
111
115
|
function serveMultifileApp(appId: string, appName: string): Response {
|
|
112
|
-
const distDir = join(
|
|
116
|
+
const distDir = join(getAppDirPath(appId), "dist");
|
|
113
117
|
const indexPath = join(distDir, "index.html");
|
|
114
118
|
|
|
115
119
|
if (!existsSync(indexPath)) {
|
|
@@ -203,7 +207,7 @@ export function handleServeDistFile(appId: string, filename: string): Response {
|
|
|
203
207
|
return httpError("BAD_REQUEST", "Invalid filename", 400);
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
const filePath = join(
|
|
210
|
+
const filePath = join(getAppDirPath(appId), "dist", filename);
|
|
207
211
|
if (!existsSync(filePath)) {
|
|
208
212
|
return httpError("NOT_FOUND", "File not found", 404);
|
|
209
213
|
}
|
|
@@ -27,6 +27,7 @@ import type {
|
|
|
27
27
|
} from "../../http-types.js";
|
|
28
28
|
import {
|
|
29
29
|
deliverVerificationCodeToGuardian,
|
|
30
|
+
deliverVerificationCodeToRequester,
|
|
30
31
|
type DeliveryResult,
|
|
31
32
|
handleAccessRequestDecision,
|
|
32
33
|
notifyRequesterOfApproval,
|
|
@@ -688,7 +689,38 @@ async function handleAccessRequestApproval(
|
|
|
688
689
|
}
|
|
689
690
|
}
|
|
690
691
|
|
|
691
|
-
|
|
692
|
+
// On Slack, auto-deliver the verification code directly to the requester's
|
|
693
|
+
// DM so the guardian doesn't have to manually share it. The identity binding
|
|
694
|
+
// still protects against abuse — only the bound user can consume the code.
|
|
695
|
+
let requesterCodeDelivered = false;
|
|
696
|
+
if (
|
|
697
|
+
codeDelivered &&
|
|
698
|
+
approval.channel === "slack" &&
|
|
699
|
+
decisionResult.verificationCode
|
|
700
|
+
) {
|
|
701
|
+
const requesterCodeResult = await deliverVerificationCodeToRequester({
|
|
702
|
+
replyCallbackUrl,
|
|
703
|
+
requesterChatId: approval.requesterChatId,
|
|
704
|
+
verificationCode: decisionResult.verificationCode,
|
|
705
|
+
assistantId,
|
|
706
|
+
bearerToken,
|
|
707
|
+
channel: approval.channel,
|
|
708
|
+
requesterExternalUserId: approval.requesterExternalUserId,
|
|
709
|
+
});
|
|
710
|
+
if (requesterCodeResult.ok) {
|
|
711
|
+
requesterCodeDelivered = true;
|
|
712
|
+
} else {
|
|
713
|
+
log.error(
|
|
714
|
+
{ reason: requesterCodeResult.reason, approvalId: approval.id },
|
|
715
|
+
"Failed to auto-deliver verification code to requester on Slack",
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Skip the separate approval notification when the requester already
|
|
721
|
+
// received the verification code directly (on Slack both messages go
|
|
722
|
+
// to the same DM, so sending both is redundant).
|
|
723
|
+
if (codeDelivered && !requesterCodeDelivered) {
|
|
692
724
|
await notifyRequesterOfApproval({
|
|
693
725
|
replyCallbackUrl,
|
|
694
726
|
requesterChatId: approval.requesterChatId,
|
|
@@ -697,7 +729,7 @@ async function handleAccessRequestApproval(
|
|
|
697
729
|
channel: approval.channel,
|
|
698
730
|
requesterExternalUserId: approval.requesterExternalUserId,
|
|
699
731
|
});
|
|
700
|
-
} else {
|
|
732
|
+
} else if (!codeDelivered) {
|
|
701
733
|
// Let the requester know something went wrong without revealing details
|
|
702
734
|
await notifyRequesterOfDeliveryFailure({
|
|
703
735
|
replyCallbackUrl,
|