@vellumai/assistant 0.5.0 → 0.5.2
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 +54 -54
- package/docs/architecture/integrations.md +62 -67
- package/docs/credential-execution-service.md +3 -3
- 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__/assistant-feature-flags-integration.test.ts +7 -9
- 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 +149 -5
- package/src/__tests__/conversation-agent-loop.test.ts +290 -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-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-workspace-cache-state.test.ts +44 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
- package/src/__tests__/credential-execution-feature-gates.test.ts +3 -3
- 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__/diagnostics-export.test.ts +70 -1
- package/src/__tests__/filesystem-tools.test.ts +4 -2
- 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 +103 -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__/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-lifecycle-e2e.test.ts +3 -1
- package/src/__tests__/memory-recall-quality.test.ts +5 -5
- 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__/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-feature-flags-integration.test.ts +18 -17
- package/src/__tests__/skill-feature-flags.test.ts +13 -13
- package/src/__tests__/skill-load-feature-flag.test.ts +4 -4
- 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__/system-prompt.test.ts +8 -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__/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/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 +16 -0
- package/src/config/loader.ts +64 -0
- package/src/config/raw-config-utils.ts +30 -0
- package/src/config/schema-utils.ts +28 -7
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +18 -0
- package/src/config/schemas/memory-lifecycle.ts +4 -2
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/services.ts +8 -6
- 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 +46 -42
- package/src/daemon/conversation-agent-loop.ts +56 -19
- 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 +39 -15
- package/src/daemon/conversation-messaging.ts +70 -26
- package/src/daemon/conversation-process.ts +58 -34
- package/src/daemon/conversation-runtime-assembly.ts +21 -38
- package/src/daemon/conversation-slash.ts +121 -256
- package/src/daemon/conversation-surfaces.ts +143 -20
- package/src/daemon/conversation-tool-setup.ts +0 -6
- package/src/daemon/conversation-workspace.ts +21 -1
- package/src/daemon/conversation.ts +51 -29
- package/src/daemon/first-greeting.ts +35 -0
- package/src/daemon/handlers/config-embeddings.ts +148 -0
- package/src/daemon/handlers/config-model.ts +71 -26
- package/src/daemon/handlers/conversations.ts +0 -23
- package/src/daemon/handlers/recording.ts +26 -21
- package/src/daemon/history-repair.ts +28 -8
- package/src/daemon/host-cu-proxy.ts +2 -2
- package/src/daemon/lifecycle.ts +106 -64
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +19 -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/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/attachments-store.ts +558 -130
- package/src/memory/conversation-attention-store.ts +70 -0
- package/src/memory/conversation-crud.ts +442 -3
- 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 +28 -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 +9 -7
- 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 +1 -4
- 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/index.ts +7 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +601 -2
- package/src/memory/retriever.ts +85 -9
- package/src/memory/schema/conversations.ts +6 -0
- package/src/memory/schema/infrastructure.ts +13 -7
- package/src/memory/schema/oauth.ts +6 -0
- 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 +97 -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 +62 -19
- package/src/prompts/system-prompt.ts +2 -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 +68 -0
- package/src/runtime/routes/conversation-query-routes.ts +180 -10
- package/src/runtime/routes/conversation-routes.ts +222 -28
- package/src/runtime/routes/conversation-starter-routes.ts +9 -11
- package/src/runtime/routes/diagnostics-routes.ts +1 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
- package/src/runtime/routes/llm-context-normalization.ts +1199 -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 +4 -0
- 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 +28 -1
- package/src/runtime/routes/settings-routes.ts +14 -0
- package/src/runtime/routes/trace-event-routes.ts +4 -1
- package/src/schedule/schedule-store.ts +9 -21
- package/src/security/secure-keys.ts +21 -0
- package/src/signals/bash.ts +1 -1
- package/src/swarm/backend-claude-code.ts +3 -6
- 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/schedule/list.ts +2 -7
- package/src/tools/schema-transforms.ts +5 -0
- package/src/tools/shared/filesystem/format-diff.ts +4 -21
- package/src/tools/skills/execute.ts +1 -1
- 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 +6 -0
- package/src/util/pricing.ts +1 -0
- package/src/util/retry.ts +1 -3
- package/src/workspace/migrations/002-backfill-installation-id.ts +23 -12
- 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/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 +10 -0
- 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,
|