@vellumai/assistant 0.11.7 → 0.11.8-staging.1
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 +10 -10
- package/Dockerfile +1 -0
- package/docs/architecture/security.md +1 -1
- package/docs/error-handling.md +1 -2
- package/docs/guardian-request-flow.md +51 -5
- package/docs/trusted-contact-access.md +13 -12
- package/knip.json +1 -0
- package/node_modules/@vellumai/avatar-catalog/package.json +19 -0
- package/{src/avatar/character-components.ts → node_modules/@vellumai/avatar-catalog/src/catalog.ts} +12 -44
- package/node_modules/@vellumai/avatar-catalog/src/colors.ts +19 -0
- package/node_modules/@vellumai/avatar-catalog/src/index.ts +25 -0
- package/node_modules/@vellumai/avatar-catalog/src/types.ts +47 -0
- package/node_modules/@vellumai/avatar-catalog/tsconfig.json +20 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +7 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/no-response.ts +84 -0
- package/node_modules/@vellumai/credential-storage/src/static-credentials.ts +43 -12
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/test-path-guard.test.ts +89 -0
- package/node_modules/@vellumai/environments/src/test-path-guard.ts +113 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +7 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/no-response.ts +84 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +8 -18
- package/node_modules/@vellumai/gateway-client/src/__tests__/inbound-event-kind.test.ts +46 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/invite-contract.test.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +46 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +62 -21
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +14 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-event-kind.ts +53 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +11 -5
- package/node_modules/@vellumai/gateway-client/src/invite-contract.ts +1 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +7 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/no-response.ts +84 -0
- package/openapi.yaml +481 -9
- package/package.json +3 -1
- package/scripts/sync-llm-catalog.ts +3 -0
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +16 -0
- package/src/__tests__/agent-loop-compacted-history-transform.test.ts +304 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +3 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +56 -0
- package/src/__tests__/approval-cascade.test.ts +0 -13
- package/src/__tests__/attachments-store.test.ts +117 -6
- package/src/__tests__/attachments.test.ts +122 -0
- package/src/__tests__/bundled-asset.test.ts +22 -1
- package/src/__tests__/channel-approval.test.ts +14 -7
- package/src/__tests__/channel-approvals.test.ts +3 -3
- package/src/__tests__/channel-delivery-store.test.ts +58 -0
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +1 -0
- package/src/__tests__/channel-invite-transport.test.ts +1 -0
- package/src/__tests__/channel-readiness-slack-remote.test.ts +3 -3
- package/src/__tests__/compaction-events.test.ts +0 -12
- package/src/__tests__/compactor-call-site-logging.test.ts +7 -1
- package/src/__tests__/compactor-retained-image-validation.test.ts +15 -0
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/contacts-write.test.ts +141 -3
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -13
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -12
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -13
- package/src/__tests__/conversation-agent-loop.test.ts +95 -13
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -13
- package/src/__tests__/conversation-load-history-repair.test.ts +418 -0
- package/src/__tests__/conversation-media-retry.test.ts +33 -2
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-callsite.test.ts +0 -12
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -13
- package/src/__tests__/conversation-queue.test.ts +4 -13
- package/src/__tests__/conversation-retry-route.test.ts +5 -0
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-sight-frames.test.ts +615 -0
- package/src/__tests__/conversation-slash-queue.test.ts +0 -13
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -13
- package/src/__tests__/conversation-speed-override.test.ts +0 -12
- package/src/__tests__/conversation-store-ephemeral.test.ts +0 -12
- package/src/__tests__/conversation-summarize-route.test.ts +5 -0
- package/src/__tests__/conversation-summarize-up-to.test.ts +102 -0
- package/src/__tests__/conversation-wait-for-idle.test.ts +0 -12
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -5
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -17
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -17
- package/src/__tests__/credential-health-service.test.ts +45 -0
- package/src/__tests__/credential-record-retire.test.ts +256 -0
- package/src/__tests__/credential-record-write-through.test.ts +8 -4
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +0 -4
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +0 -4
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +0 -8
- package/src/__tests__/delete-propagation.test.ts +121 -3
- package/src/__tests__/evict-conversations-for-reload.test.ts +46 -6
- package/src/__tests__/file-ops-service.test.ts +8 -3
- package/src/__tests__/gemini-provider.test.ts +64 -0
- package/src/__tests__/guardian-action-service-scope.test.ts +118 -0
- package/src/__tests__/guardian-card-withdrawal.test.ts +299 -5
- package/src/__tests__/guardian-expiry-notifier.test.ts +117 -13
- package/src/__tests__/guardian-gateway-sim.test.ts +119 -0
- package/src/__tests__/guardian-gateway-sim.ts +56 -20
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +6 -0
- package/src/__tests__/guardian-request-status-sync.test.ts +162 -0
- package/src/__tests__/guardian-wait-controller.test.ts +6 -0
- package/src/__tests__/headless-browser-mode.test.ts +27 -0
- package/src/__tests__/helpers/mock-conversation.ts +2 -0
- package/src/__tests__/list-messages-system-card.test.ts +70 -0
- package/src/__tests__/llm-catalog-parity.test.ts +2 -0
- package/src/__tests__/managed-profile-guard.test.ts +2 -2
- package/src/__tests__/media-resolve-image-validation.test.ts +106 -0
- package/src/__tests__/media-stream-server-integration.test.ts +6 -0
- package/src/__tests__/non-member-access-request.test.ts +12 -0
- package/src/__tests__/notification-discord-adapter.test.ts +76 -4
- package/src/__tests__/oauth-commands-routes.test.ts +21 -0
- package/src/__tests__/openai-provider.test.ts +63 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +114 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +63 -1
- package/src/__tests__/persist-unsendable-image.test.ts +19 -0
- package/src/__tests__/plugin-app-serve-routes.test.ts +2 -2
- package/src/__tests__/plugin-import-boundary-guard.test.ts +1 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -1
- package/src/__tests__/process-message-display-content.test.ts +1 -1
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -5
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +0 -17
- package/src/__tests__/qdrant-manager.test.ts +6 -0
- package/src/__tests__/reaction-persistence.test.ts +58 -62
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +67 -0
- package/src/__tests__/server-history-render.test.ts +22 -0
- package/src/__tests__/sight-frame-retention.test.ts +362 -0
- package/src/__tests__/slack-reaction-approvals.test.ts +44 -24
- package/src/__tests__/slack-reaction-guardian-approval.test.ts +29 -1
- package/src/__tests__/subagent-fork-notifications.test.ts +2 -0
- package/src/__tests__/subagent-manager-notify.test.ts +2 -0
- package/src/__tests__/subagent-notify-parent.test.ts +2 -0
- package/src/__tests__/subagent-notify-stale-rebuild.test.ts +85 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +4 -4
- package/src/__tests__/terminal-tools.test.ts +9 -9
- package/src/__tests__/tool-result-spool.test.ts +5 -8
- package/src/__tests__/usage-attribution.test.ts +26 -0
- package/src/acp/__tests__/acp-auth-marker-store.test.ts +191 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +262 -0
- package/src/acp/__tests__/acp-connect-card-state.test.ts +17 -0
- package/src/acp/__tests__/helpers/acp-history-db.ts +10 -3
- package/src/acp/acp-auth-marker-store.ts +196 -0
- package/src/acp/acp-claude-oauth.ts +154 -4
- package/src/acp/acp-connect-card-state.ts +49 -8
- package/src/acp/agent-process.ts +1 -0
- package/src/acp/auto-install.ts +1 -0
- package/src/acp/client-handler.ts +1 -0
- package/src/acp/prepare-agent-env.ts +79 -1
- package/src/acp/resolve-agent.ts +12 -0
- package/src/acp/session-manager.test.ts +183 -0
- package/src/acp/session-manager.ts +110 -6
- package/src/acp/types.ts +17 -0
- package/src/agent/attachments.ts +7 -2
- package/src/agent/loop.ts +59 -1
- package/src/api/events/contact-form-closed.ts +32 -0
- package/src/api/events/contact-record-request.ts +63 -0
- package/src/api/events/contact-request.ts +10 -3
- package/src/api/index.ts +20 -0
- package/src/api/responses/conversation-message.ts +20 -0
- package/src/api/responses/home.ts +101 -0
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-card-withdrawal.ts +127 -30
- package/src/approvals/guardian-decision-primitive.ts +9 -0
- package/src/approvals/guardian-expiry-notifier.ts +22 -16
- package/src/approvals/guardian-request-status-sync.ts +98 -0
- package/src/avatar/svg-compositor.ts +1 -1
- package/src/avatar/traits-png-sync.ts +1 -1
- package/src/bundler/app-compiler.ts +1 -0
- package/src/bundler/compiler-tools.ts +1 -0
- package/src/bundler/package-resolver.ts +1 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +183 -3
- package/src/calls/guardian-action-sweep.ts +6 -1
- package/src/calls/voice-session-bridge.ts +46 -1
- package/src/channels/__tests__/gateway-guardian-requests.test.ts +13 -18
- package/src/channels/gateway-guardian-requests.ts +37 -18
- package/src/cli/__tests__/contacts-record-prompt-cli.test.ts +329 -0
- package/src/cli/commands/__tests__/browser.test.ts +65 -1
- package/src/cli/commands/browser.ts +30 -10
- package/src/cli/commands/contacts.help.ts +173 -11
- package/src/cli/commands/contacts.ts +343 -4
- package/src/cli/commands/db/refresh.ts +1 -0
- package/src/cli/commands/oauth/index.help.ts +6 -3
- package/src/cli/commands/oauth/request.test.ts +37 -0
- package/src/cli/commands/oauth/request.ts +7 -6
- package/src/cli/lib/bundled-marketplace.json +1 -1
- package/src/cli/lib/install-from-github.ts +20 -19
- package/src/cli/lib/install-plugin-dependencies.ts +3 -5
- package/src/cli/lib/merge-plugin-tree.ts +1 -0
- package/src/cli/lib/publish-plugin.ts +4 -1
- package/src/config/__tests__/balanced-model-experiment.test.ts +63 -31
- package/src/config/__tests__/default-profile-catalog.test.ts +2 -2
- package/src/config/balanced-model-experiment.ts +15 -9
- package/src/config/bundled-skills/contacts/SKILL.md +61 -18
- package/src/config/default-profile-catalog.ts +12 -11
- package/src/config/feature-flag-registry.json +22 -13
- package/src/config/schema.ts +2 -0
- package/src/config/schemas/__tests__/live-voice.test.ts +13 -0
- package/src/config/schemas/live-voice.ts +7 -0
- package/src/config/schemas/sight.ts +45 -0
- package/src/config/skills.ts +2 -1
- package/src/contacts/__tests__/mirror-reconciler.test.ts +352 -0
- package/src/contacts/contact-store.ts +47 -4
- package/src/contacts/contacts-write.ts +5 -2
- package/src/contacts/mirror-reconciler.ts +210 -0
- package/src/contacts/mirror-tombstones.ts +42 -0
- package/src/contacts/notify-contacts-changed.ts +11 -2
- package/src/context/compactor.ts +47 -19
- package/src/context/tool-result-spool.ts +21 -14
- package/src/conversations/message-consolidation.ts +2 -2
- package/src/credential-health/credential-health-service.ts +37 -6
- package/src/daemon/conversation-agent-loop-handlers.ts +19 -2
- package/src/daemon/conversation-agent-loop.ts +100 -1
- package/src/daemon/conversation-media-retry.ts +11 -6
- package/src/daemon/conversation-messaging.ts +293 -30
- package/src/daemon/conversation-runtime-assembly.ts +67 -0
- package/src/daemon/conversation-sight-frames.ts +187 -0
- package/src/daemon/conversation-store.ts +18 -28
- package/src/daemon/conversation-surfaces.ts +12 -2
- package/src/daemon/conversation-tool-setup.ts +39 -10
- package/src/daemon/conversation.ts +159 -16
- package/src/daemon/daemon-control.ts +6 -17
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/conversations.ts +10 -11
- package/src/daemon/install-assistant-command.ts +1 -0
- package/src/daemon/lifecycle.ts +10 -13
- package/src/daemon/message-types/sync.ts +4 -0
- package/src/daemon/process-message.ts +2 -17
- package/src/daemon/reaction-history-render.test.ts +162 -0
- package/src/daemon/reaction-history-render.ts +115 -0
- package/src/daemon/reaction-record.test.ts +162 -0
- package/src/daemon/reaction-record.ts +83 -0
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/summarize-boundary.ts +12 -0
- package/src/daemon/video-thumbnail.ts +1 -1
- package/src/home/feed-types.ts +4 -0
- package/src/home/feed-writer.ts +25 -0
- package/src/live-voice/__tests__/live-voice-attach-frame.test.ts +679 -0
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +8 -5
- package/src/live-voice/__tests__/live-voice-photo.test.ts +637 -1
- package/src/live-voice/__tests__/live-voice-sight-frame-inline.test.ts +787 -0
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +347 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +109 -0
- package/src/live-voice/live-voice-photo.ts +420 -65
- package/src/live-voice/live-voice-session.ts +311 -27
- package/src/live-voice/protocol.ts +147 -11
- package/src/messaging/provider-message-metadata.ts +7 -0
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +113 -1
- package/src/messaging/providers/channel-transport.ts +37 -0
- package/src/messaging/providers/discord/api.ts +4 -4
- package/src/messaging/providers/discord/send.test.ts +177 -2
- package/src/messaging/providers/discord/send.ts +197 -10
- package/src/messaging/providers/discord/transport.ts +10 -0
- package/src/messaging/providers/index.ts +42 -0
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +129 -3
- package/src/messaging/providers/slack/__tests__/auth.test.ts +35 -0
- package/src/messaging/providers/slack/__tests__/message-content.test.ts +152 -0
- package/src/messaging/providers/slack/adapter.ts +112 -27
- package/src/messaging/providers/slack/api.test.ts +10 -0
- package/src/messaging/providers/slack/auth.ts +32 -6
- package/src/messaging/providers/slack/client.ts +0 -15
- package/src/messaging/providers/slack/message-content.ts +137 -0
- package/src/messaging/providers/slack/send.test.ts +43 -2
- package/src/messaging/providers/slack/send.ts +18 -5
- package/src/messaging/providers/slack/transport.ts +10 -0
- package/src/messaging/providers/slack/types.ts +21 -2
- package/src/messaging/providers/telegram-bot/adapter.ts +5 -1
- package/src/messaging/providers/telegram-bot/send.test.ts +49 -2
- package/src/messaging/providers/telegram-bot/send.ts +41 -1
- package/src/messaging/providers/telegram-bot/transport.ts +10 -0
- package/src/messaging/providers/telegram-bot/withdraw.ts +13 -5
- package/src/messaging/reaction-envelopes.ts +79 -0
- package/src/monitoring/control.ts +2 -2
- package/src/monitoring/page-cache.ts +5 -1
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +360 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +8 -0
- package/src/notifications/adapters/discord.ts +62 -9
- package/src/notifications/conversation-pairing.ts +31 -4
- package/src/notifications/emit-signal.ts +8 -5
- package/src/notifications/guardian-delivery-recorder.ts +47 -6
- package/src/notifications/guardian-feed-projection.ts +492 -0
- package/src/notifications/home-feed-side-effect.ts +59 -11
- package/src/oauth/byo-connection.test.ts +22 -0
- package/src/oauth/byo-connection.ts +11 -5
- package/src/oauth/connection.ts +3 -2
- package/src/oauth/platform-connection.test.ts +35 -0
- package/src/oauth/platform-connection.ts +18 -13
- package/src/oauth/scope-utils.ts +48 -0
- package/src/oauth/seed-providers.ts +12 -0
- package/src/outbound-proxy/certs.ts +5 -4
- package/src/permissions/question-guardian-request.test.ts +7 -1
- package/src/persistence/attachments-store.ts +134 -31
- package/src/persistence/conversation-crud.ts +137 -4
- package/src/persistence/conversation-types.ts +109 -0
- package/src/persistence/db-connection.ts +3 -21
- package/src/persistence/delivery-crud.ts +42 -12
- package/src/persistence/embeddings/__tests__/embedding-local-lifecycle.test.ts +15 -2
- package/src/persistence/embeddings/embedding-local.ts +7 -112
- package/src/persistence/embeddings/qdrant-manager.ts +4 -1
- package/src/persistence/llm-request-log-store.ts +1 -1
- package/src/persistence/migrations/370-acp-session-history-auth-error-code.ts +36 -0
- package/src/persistence/migrations/371-acp-session-history-auth-error-credential.ts +40 -0
- package/src/persistence/migrations/372-create-acp-refused-credentials.ts +34 -0
- package/src/persistence/migrations/373-acp-auth-marker-index.ts +27 -0
- package/src/persistence/migrations/__tests__/370-acp-session-history-auth-error-code.test.ts +65 -0
- package/src/persistence/migrations/__tests__/371-acp-session-history-auth-error-credential.test.ts +68 -0
- package/src/persistence/migrations/__tests__/372-create-acp-refused-credentials.test.ts +64 -0
- package/src/persistence/migrations/__tests__/373-acp-auth-marker-index.test.ts +82 -0
- package/src/persistence/schema/acp.ts +25 -0
- package/src/persistence/steps.ts +8 -0
- package/src/platform/platform-patch-queue.test.ts +43 -41
- package/src/plugin-api/index.ts +12 -0
- package/src/plugins/defaults/compaction/window-manager.ts +2 -0
- package/src/plugins/defaults/image-recovery/recover.ts +12 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +166 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +3 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +3 -0
- package/src/plugins/defaults/memory/jobs-worker.ts +1 -2
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +53 -9
- package/src/plugins/defaults/memory/src/__tests__/memory-worker-routes.test.ts +4 -7
- package/src/plugins/defaults/memory/src/memory-worker-routes.ts +1 -1
- package/src/plugins/defaults/memory/v1/job-handlers/index-maintenance.ts +15 -1
- package/src/plugins/defaults/memory/worker-control.ts +1 -2
- package/src/providers/content-block-schema.ts +1 -0
- package/src/providers/fireworks/client.ts +9 -1
- package/src/providers/gemini/client.ts +22 -15
- package/src/providers/media-resolve.ts +24 -10
- package/src/providers/model-catalog.ts +91 -0
- package/src/providers/openai/chat-completions-provider.ts +44 -5
- package/src/providers/retry.ts +16 -11
- package/src/providers/types.ts +56 -0
- package/src/routes/__tests__/control.test.ts +4 -3
- package/src/routes/control.ts +1 -1
- package/src/routes/route-host-client.ts +1 -1
- package/src/runtime/AGENTS.md +30 -12
- package/src/runtime/__tests__/agent-wake.test.ts +71 -6
- package/src/runtime/__tests__/guardian-form-registry.test.ts +242 -0
- package/src/runtime/access-request-helper.ts +15 -7
- package/src/runtime/agent-wake.ts +16 -4
- package/src/runtime/channel-approval-types.ts +8 -5
- package/src/runtime/channel-invite-transport.ts +2 -0
- package/src/runtime/channel-invite-transports/discord.ts +27 -0
- package/src/runtime/channel-readiness-service.ts +4 -4
- package/src/runtime/channel-reply-delivery.ts +72 -28
- package/src/runtime/guardian-action-service.ts +9 -5
- package/src/runtime/guardian-form-registry.ts +256 -0
- package/src/runtime/guardian-reply-router.ts +33 -14
- package/src/runtime/invite-instruction-generator.ts +14 -2
- package/src/runtime/migrations/vbundle-metadata-merge.ts +4 -7
- package/src/runtime/no-response.ts +13 -74
- package/src/runtime/routes/__tests__/acp-routes.test.ts +527 -0
- package/src/runtime/routes/__tests__/app-management-shared-apps.test.ts +74 -0
- package/src/runtime/routes/__tests__/contact-form-kinds.test.ts +22 -0
- package/src/runtime/routes/__tests__/contact-record-prompt-route.test.ts +303 -0
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +3 -4
- package/src/runtime/routes/__tests__/pending-interactions-route.test.ts +6 -0
- package/src/runtime/routes/__tests__/route-host-worker-routes.test.ts +3 -4
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +5 -6
- package/src/runtime/routes/acp-routes-list.test.ts +58 -0
- package/src/runtime/routes/acp-routes.ts +253 -47
- package/src/runtime/routes/app-management-routes.ts +80 -47
- package/src/runtime/routes/approval-routes.ts +9 -0
- package/src/runtime/routes/archive-utils.ts +6 -1
- package/src/runtime/routes/avatar-routes.ts +1 -1
- package/src/runtime/routes/channel-route-shared.ts +18 -20
- package/src/runtime/routes/contact-prompt-routes.ts +271 -105
- package/src/runtime/routes/conversation-routes.ts +41 -32
- package/src/runtime/routes/credential-prompt-routes.ts +10 -1
- package/src/runtime/routes/debug-bash-routes.ts +1 -0
- package/src/runtime/routes/guardian-expiry-sweep.ts +89 -31
- package/src/runtime/routes/guardian-form-routes.ts +115 -0
- package/src/runtime/routes/inbound-message-handler.ts +82 -29
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +16 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +6 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +6 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +6 -1
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +50 -17
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +97 -94
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/channel.ts +39 -18
- package/src/runtime/routes/migration-routes.ts +1 -3
- package/src/runtime/routes/monitoring-routes.ts +0 -3
- package/src/runtime/routes/oauth-commands-routes.ts +18 -5
- package/src/runtime/routes/route-host-worker-routes.ts +1 -1
- package/src/runtime/routes/schedule-worker-routes.ts +1 -1
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/run-script.ts +1 -0
- package/src/schedule/scheduler.ts +1 -1
- package/src/schedule/worker-control.ts +2 -2
- package/src/security/oauth2.ts +2 -11
- package/src/security/secure-keys.ts +55 -8
- package/src/skills/catalog-install.ts +7 -4
- package/src/skills/clawhub.ts +1 -0
- package/src/skills/inline-command-runner.ts +1 -0
- package/src/stt/__tests__/room-noise-floor.test.ts +108 -0
- package/src/stt/room-noise-floor.ts +140 -0
- package/src/subagent/notify.ts +49 -3
- package/src/tools/__tests__/tool-input-schemas.test.ts +2 -0
- package/src/tools/acp/spawn.ts +2 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +9 -0
- package/src/tools/browser/browser-execution.ts +10 -43
- package/src/tools/browser/browser-manager.ts +1 -0
- package/src/tools/browser/browser-status-constants.ts +6 -5
- package/src/tools/browser/runtime-check.ts +2 -0
- package/src/tools/channel/react-to-message.test.ts +193 -0
- package/src/tools/channel/react-to-message.ts +159 -0
- package/src/tools/credentials/metadata-store.ts +115 -19
- package/src/tools/credentials/store.ts +0 -2
- package/src/tools/filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +24 -0
- package/src/tools/host-terminal/host-shell.ts +11 -38
- package/src/tools/shared/filesystem/file-ops-service.ts +10 -7
- package/src/tools/shared/shell-output.test.ts +104 -0
- package/src/tools/shared/shell-output.ts +112 -39
- package/src/tools/skills/sandbox-runner.ts +1 -0
- package/src/tools/system/request-permission.test.ts +34 -0
- package/src/tools/system/request-permission.ts +29 -5
- package/src/tools/terminal/shell.test.ts +63 -0
- package/src/tools/terminal/shell.ts +12 -44
- package/src/tools/tool-input-schemas.ts +2 -0
- package/src/tools/tool-manifest.ts +2 -0
- package/src/usage/attribution.ts +12 -4
- package/src/util/__tests__/worker-ownership.test.ts +77 -0
- package/src/util/__tests__/worker-process-command.test.ts +246 -1
- package/src/util/bun-runtime.ts +44 -13
- package/src/util/bundled-asset.ts +9 -1
- package/src/util/disk-usage.ts +1 -0
- package/src/util/file-use.ts +4 -1
- package/src/util/guardian-form-timeouts.ts +50 -0
- package/src/util/image-conversion.ts +1 -0
- package/src/util/oauth-request-body.test.ts +59 -0
- package/src/util/oauth-request-body.ts +56 -5
- package/src/util/platform.ts +69 -73
- package/src/util/process-table.ts +16 -5
- package/src/util/read-stdin.ts +5 -0
- package/src/util/spawn.ts +1 -0
- package/src/util/sqlite3-runtime.ts +25 -5
- package/src/util/worker-ownership.ts +193 -0
- package/src/util/worker-process.ts +375 -37
- package/src/workspace/git-service.ts +4 -12
- package/src/workspace/migrations/010-app-dir-rename.ts +1 -0
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Button, KnownBlock } from "@slack/types";
|
|
10
10
|
import type {
|
|
11
11
|
ApprovalUIMetadata,
|
|
12
|
+
ChannelDeliveryResult,
|
|
12
13
|
MessageAudience,
|
|
13
14
|
StreamOp,
|
|
14
15
|
} from "@vellumai/gateway-client";
|
|
@@ -382,30 +383,42 @@ function imageBlocksFor(text: string): KnownBlock[] | undefined {
|
|
|
382
383
|
|
|
383
384
|
/**
|
|
384
385
|
* Add or remove an emoji reaction on a Slack message.
|
|
385
|
-
*
|
|
386
|
+
*
|
|
387
|
+
* Non-throwing: failures are logged and reported through the result so a
|
|
388
|
+
* tool-driven react can tell the model the truth, while the activity
|
|
389
|
+
* fallback is free to ignore it. Colons are stripped from the name because
|
|
390
|
+
* `reactions.add` takes the bare emoji name, and `already_reacted` /
|
|
391
|
+
* `no_reaction` count as success: the requested end state already holds.
|
|
386
392
|
*/
|
|
387
393
|
export async function sendSlackReaction(
|
|
388
394
|
channel: string,
|
|
389
395
|
name: string,
|
|
390
396
|
messageTs: string,
|
|
391
397
|
action: "add" | "remove",
|
|
392
|
-
): Promise<
|
|
398
|
+
): Promise<ChannelDeliveryResult> {
|
|
393
399
|
const method = action === "add" ? "reactions.add" : "reactions.remove";
|
|
400
|
+
const bareName = name.replace(/^:+|:+$/g, "");
|
|
394
401
|
try {
|
|
395
|
-
await callSlackApi(method, {
|
|
402
|
+
await callSlackApi(method, {
|
|
403
|
+
channel,
|
|
404
|
+
name: bareName,
|
|
405
|
+
timestamp: messageTs,
|
|
406
|
+
});
|
|
407
|
+
return { ok: true };
|
|
396
408
|
} catch (err) {
|
|
397
409
|
if (err instanceof SlackApiError) {
|
|
398
410
|
if (
|
|
399
411
|
err.slackError === "already_reacted" ||
|
|
400
412
|
err.slackError === "no_reaction"
|
|
401
413
|
) {
|
|
402
|
-
return;
|
|
414
|
+
return { ok: true };
|
|
403
415
|
}
|
|
404
416
|
}
|
|
405
417
|
log.warn(
|
|
406
|
-
{ err, channel, method, name },
|
|
418
|
+
{ err, channel, method, name: bareName },
|
|
407
419
|
"Failed to deliver Slack reaction",
|
|
408
420
|
);
|
|
421
|
+
return { ok: false };
|
|
409
422
|
}
|
|
410
423
|
}
|
|
411
424
|
|
|
@@ -6,6 +6,7 @@ import type { ChannelTransport } from "../channel-transport.js";
|
|
|
6
6
|
import {
|
|
7
7
|
sendSlackAgentSessionStatus,
|
|
8
8
|
sendSlackAttachments,
|
|
9
|
+
sendSlackReaction,
|
|
9
10
|
sendSlackReply,
|
|
10
11
|
sendSlackStreamOp,
|
|
11
12
|
updateSlackMessage,
|
|
@@ -21,6 +22,15 @@ function mutedBlocks(text: string): KnownBlock[] {
|
|
|
21
22
|
export const slackTransport: ChannelTransport = {
|
|
22
23
|
channel: "slack",
|
|
23
24
|
|
|
25
|
+
async react(target) {
|
|
26
|
+
return sendSlackReaction(
|
|
27
|
+
target.chatId,
|
|
28
|
+
target.emoji,
|
|
29
|
+
target.messageId,
|
|
30
|
+
target.action,
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
|
|
24
34
|
async deliver(ctx, payload) {
|
|
25
35
|
const { chatId, text, attachments } = payload;
|
|
26
36
|
const threadTs = ctx.params.threadTs;
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/** Slack Web API response types. */
|
|
2
2
|
|
|
3
|
+
import type {
|
|
4
|
+
AnyBlock,
|
|
5
|
+
GenericMessageEvent,
|
|
6
|
+
MessageAttachment,
|
|
7
|
+
} from "@slack/types";
|
|
8
|
+
|
|
3
9
|
export interface SlackApiResponse {
|
|
4
10
|
ok: boolean;
|
|
5
11
|
error?: string;
|
|
@@ -61,7 +67,22 @@ export interface SlackMessage {
|
|
|
61
67
|
ts: string;
|
|
62
68
|
user?: string;
|
|
63
69
|
bot_id?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Display name for `bot_message`-subtype rows (incoming webhooks and
|
|
72
|
+
* legacy bot posts, which carry no `user` to resolve a name from).
|
|
73
|
+
*/
|
|
74
|
+
username?: string;
|
|
75
|
+
/** Profile of the posting app, attached to bot-authored rows. The type is
|
|
76
|
+
* indexed off the official message event because `@slack/types` does not
|
|
77
|
+
* export `BotProfile` from its root. */
|
|
78
|
+
bot_profile?: GenericMessageEvent["bot_profile"];
|
|
64
79
|
text: string;
|
|
80
|
+
/**
|
|
81
|
+
* Bot/webhook posts routinely leave `text` empty and put the visible
|
|
82
|
+
* content here or in `blocks`; see `slackMessageRawText`.
|
|
83
|
+
*/
|
|
84
|
+
attachments?: MessageAttachment[];
|
|
85
|
+
blocks?: AnyBlock[];
|
|
65
86
|
thread_ts?: string;
|
|
66
87
|
reply_count?: number;
|
|
67
88
|
reactions?: Array<{ name: string; count: number; users: string[] }>;
|
|
@@ -144,8 +165,6 @@ export interface SlackConversationsOpenResponse extends SlackApiResponse {
|
|
|
144
165
|
|
|
145
166
|
export type SlackConversationMarkResponse = SlackApiResponse;
|
|
146
167
|
|
|
147
|
-
export type SlackReactionsAddResponse = SlackApiResponse;
|
|
148
|
-
|
|
149
168
|
export interface SlackUsersListResponse extends SlackApiResponse {
|
|
150
169
|
members: SlackUser[];
|
|
151
170
|
response_metadata?: { next_cursor?: string };
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { OAuthConnection } from "../../../oauth/connection.js";
|
|
8
8
|
import { getConnectionByProvider } from "../../../oauth/oauth-store.js";
|
|
9
9
|
import { getOrCreateConversation } from "../../../persistence/conversation-key-store.js";
|
|
10
|
+
import { buildScopedConversationKey } from "../../../persistence/delivery-crud.js";
|
|
10
11
|
import { upsertOutboundBinding } from "../../../persistence/external-conversation-store.js";
|
|
11
12
|
import { credentialKey } from "../../../security/credential-key.js";
|
|
12
13
|
import { getSecureKeyAsync } from "../../../security/secure-keys.js";
|
|
@@ -107,7 +108,10 @@ export const telegramBotMessagingProvider: MessagingProvider = {
|
|
|
107
108
|
// conversation key mapping and binding exist for the next inbound.
|
|
108
109
|
try {
|
|
109
110
|
const sourceChannel = "telegram";
|
|
110
|
-
const conversationKey =
|
|
111
|
+
const conversationKey = buildScopedConversationKey(
|
|
112
|
+
sourceChannel,
|
|
113
|
+
conversationId,
|
|
114
|
+
);
|
|
111
115
|
const { conversationId: internalId } =
|
|
112
116
|
getOrCreateConversation(conversationKey);
|
|
113
117
|
upsertOutboundBinding({
|
|
@@ -30,8 +30,12 @@ mock.module("./api.js", () => ({
|
|
|
30
30
|
}));
|
|
31
31
|
|
|
32
32
|
const { TelegramNonRetryableError } = await import("./api.js");
|
|
33
|
-
const {
|
|
34
|
-
|
|
33
|
+
const {
|
|
34
|
+
editTelegramMessage,
|
|
35
|
+
sendTelegramReaction,
|
|
36
|
+
sendTelegramReply,
|
|
37
|
+
sendTelegramRichReply,
|
|
38
|
+
} = await import("./send.js");
|
|
35
39
|
const { telegramTransport } = await import("./transport.js");
|
|
36
40
|
|
|
37
41
|
const approval: ApprovalUIMetadata = {
|
|
@@ -323,6 +327,49 @@ describe("telegramTransport topic targeting", () => {
|
|
|
323
327
|
});
|
|
324
328
|
});
|
|
325
329
|
|
|
330
|
+
describe("sendTelegramReaction", () => {
|
|
331
|
+
test("add sends setMessageReaction with a single emoji entry", async () => {
|
|
332
|
+
const result = await sendTelegramReaction("12345", "👍", "678", "add");
|
|
333
|
+
expect(result).toEqual({ ok: true });
|
|
334
|
+
const calls = callsTo("setMessageReaction");
|
|
335
|
+
expect(calls).toHaveLength(1);
|
|
336
|
+
expect(calls[0][1]).toEqual({
|
|
337
|
+
chat_id: "12345",
|
|
338
|
+
message_id: 678,
|
|
339
|
+
reaction: [{ type: "emoji", emoji: "👍" }],
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test("remove clears the bot's reaction with the empty list", async () => {
|
|
344
|
+
await sendTelegramReaction("12345", "👍", "678", "remove");
|
|
345
|
+
const calls = callsTo("setMessageReaction");
|
|
346
|
+
expect(calls[0][1]).toEqual({
|
|
347
|
+
chat_id: "12345",
|
|
348
|
+
message_id: 678,
|
|
349
|
+
reaction: [],
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("a non-numeric message id reports ok false without calling the API", async () => {
|
|
354
|
+
const result = await sendTelegramReaction(
|
|
355
|
+
"12345",
|
|
356
|
+
"👍",
|
|
357
|
+
"not-an-id",
|
|
358
|
+
"add",
|
|
359
|
+
);
|
|
360
|
+
expect(result).toEqual({ ok: false });
|
|
361
|
+
expect(callsTo("setMessageReaction")).toHaveLength(0);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
test("an API rejection reports ok false without throwing", async () => {
|
|
365
|
+
callTelegramBotApiMock.mockImplementationOnce(async () => {
|
|
366
|
+
throw new TelegramNonRetryableError("400", "REACTION_INVALID");
|
|
367
|
+
});
|
|
368
|
+
const result = await sendTelegramReaction("12345", "👍", "678", "add");
|
|
369
|
+
expect(result).toEqual({ ok: false });
|
|
370
|
+
});
|
|
371
|
+
});
|
|
372
|
+
|
|
326
373
|
describe("editTelegramMessage", () => {
|
|
327
374
|
const ctx = { callbackUrl: "http://gw/deliver/telegram", params: {} };
|
|
328
375
|
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* and typing indicators by calling the Telegram Bot API directly via ./api.ts.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
ApprovalUIMetadata,
|
|
10
|
+
ChannelDeliveryResult,
|
|
11
|
+
} from "@vellumai/gateway-client";
|
|
9
12
|
|
|
10
13
|
import { getAttachmentContent } from "../../../persistence/attachments-store.js";
|
|
11
14
|
import type { RuntimeAttachmentMetadata } from "../../../runtime/http-types.js";
|
|
@@ -388,6 +391,43 @@ export async function sendTelegramAttachments(
|
|
|
388
391
|
* Send a typing indicator ("chat action") to a Telegram chat.
|
|
389
392
|
* Returns true on success, false on failure (non-throwing).
|
|
390
393
|
*/
|
|
394
|
+
/**
|
|
395
|
+
* Set or clear the bot's emoji reaction on a message.
|
|
396
|
+
*
|
|
397
|
+
* `setMessageReaction` semantics (Bot API): a bot holds at most one
|
|
398
|
+
* reaction per message, so `add` replaces any prior one and `remove`
|
|
399
|
+
* clears it by sending the empty reaction list. `emoji` is the unicode
|
|
400
|
+
* emoji itself, and Telegram accepts only its allowed set (the standard
|
|
401
|
+
* reaction emoji, narrowed further by a chat's allowed-reactions
|
|
402
|
+
* setting); a rejected emoji reports `ok: false` rather than throwing.
|
|
403
|
+
*/
|
|
404
|
+
export async function sendTelegramReaction(
|
|
405
|
+
chatId: string,
|
|
406
|
+
emoji: string,
|
|
407
|
+
messageId: string,
|
|
408
|
+
action: "add" | "remove",
|
|
409
|
+
): Promise<ChannelDeliveryResult> {
|
|
410
|
+
const messageIdNum = Number.parseInt(messageId, 10);
|
|
411
|
+
if (!Number.isFinite(messageIdNum)) {
|
|
412
|
+
log.warn({ chatId, messageId }, "Non-numeric Telegram reaction target");
|
|
413
|
+
return { ok: false };
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
await callTelegramBotApi("setMessageReaction", {
|
|
417
|
+
chat_id: chatId,
|
|
418
|
+
message_id: messageIdNum,
|
|
419
|
+
reaction: action === "add" ? [{ type: "emoji", emoji }] : [],
|
|
420
|
+
});
|
|
421
|
+
return { ok: true };
|
|
422
|
+
} catch (err) {
|
|
423
|
+
log.warn(
|
|
424
|
+
{ err, chatId, messageId, action },
|
|
425
|
+
"Failed to deliver Telegram reaction",
|
|
426
|
+
);
|
|
427
|
+
return { ok: false };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
391
431
|
export async function sendTelegramTypingIndicator(
|
|
392
432
|
chatId: string,
|
|
393
433
|
opts?: TelegramSendOptions,
|
|
@@ -10,6 +10,7 @@ import type { TelegramSendOptions } from "./send.js";
|
|
|
10
10
|
import {
|
|
11
11
|
editTelegramMessage,
|
|
12
12
|
sendTelegramAttachments,
|
|
13
|
+
sendTelegramReaction,
|
|
13
14
|
sendTelegramReply,
|
|
14
15
|
sendTelegramRichReply,
|
|
15
16
|
sendTelegramTypingIndicator,
|
|
@@ -32,6 +33,15 @@ export const telegramTransport: ChannelTransport = {
|
|
|
32
33
|
// Telegram clears a chat action after about five seconds.
|
|
33
34
|
activityRefreshMs: 4_000,
|
|
34
35
|
|
|
36
|
+
async react(target) {
|
|
37
|
+
return sendTelegramReaction(
|
|
38
|
+
target.chatId,
|
|
39
|
+
target.emoji,
|
|
40
|
+
target.messageId,
|
|
41
|
+
target.action,
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
|
|
35
45
|
async deliver(ctx, payload) {
|
|
36
46
|
const { chatId, text, attachments, approval } = payload;
|
|
37
47
|
const opts = threadOptions(ctx);
|
|
@@ -132,24 +132,31 @@ async function clearInlineKeyboard(
|
|
|
132
132
|
*
|
|
133
133
|
* Both steps are attempted independently, so a failed keyboard edit does not
|
|
134
134
|
* lose the durable outcome notice. Throws only if the status reply send
|
|
135
|
-
* fails, which
|
|
135
|
+
* fails, which decision-path callers treat as non-fatal. `complete` reports
|
|
136
|
+
* whether the keyboard is durably gone: false keeps the expiry sweep's
|
|
137
|
+
* receipt held back so the still-actionable card is retried. An invalid
|
|
138
|
+
* recorded message id reports complete, because no retry can ever address
|
|
139
|
+
* it; a tap on its leftover buttons gets the stale-request handling.
|
|
136
140
|
*/
|
|
137
141
|
export async function withdrawTelegramApprovalCard(
|
|
138
142
|
params: WithdrawTelegramApprovalCardParams,
|
|
139
|
-
): Promise<
|
|
143
|
+
): Promise<{ complete: boolean }> {
|
|
140
144
|
const parsedMessageId = Number(params.messageId);
|
|
141
145
|
if (!Number.isFinite(parsedMessageId)) {
|
|
142
146
|
log.warn(
|
|
143
147
|
{ chatId: params.chatId, messageId: params.messageId },
|
|
144
148
|
"Skipping Telegram card withdrawal due to invalid message id",
|
|
145
149
|
);
|
|
146
|
-
return;
|
|
150
|
+
return { complete: true };
|
|
147
151
|
}
|
|
148
152
|
|
|
149
|
-
await clearInlineKeyboard(
|
|
153
|
+
const keyboardCleared = await clearInlineKeyboard(
|
|
154
|
+
params.chatId,
|
|
155
|
+
parsedMessageId,
|
|
156
|
+
);
|
|
150
157
|
|
|
151
158
|
if (!params.postStatusReply) {
|
|
152
|
-
return;
|
|
159
|
+
return { complete: keyboardCleared };
|
|
153
160
|
}
|
|
154
161
|
|
|
155
162
|
// Silent (no push) reply quoting the card. `allow_sending_without_reply`
|
|
@@ -163,4 +170,5 @@ export async function withdrawTelegramApprovalCard(
|
|
|
163
170
|
},
|
|
164
171
|
disable_notification: true,
|
|
165
172
|
});
|
|
173
|
+
return { complete: keyboardCleared };
|
|
166
174
|
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two persisted envelope shapes of a reaction row, built from one set of
|
|
3
|
+
* facts so the inbound intercept and the assistant's own reaction records
|
|
4
|
+
* cannot drift apart.
|
|
5
|
+
*
|
|
6
|
+
* Slack keeps its own envelope because its transcript context builds
|
|
7
|
+
* provider history from rows and reads only `slackMeta`; every other channel
|
|
8
|
+
* writes the neutral shape `readProviderMetadata` serves to channel-agnostic
|
|
9
|
+
* readers.
|
|
10
|
+
*/
|
|
11
|
+
import type { ChannelId } from "../channels/types.js";
|
|
12
|
+
import type { ProviderMessageMetadata } from "./provider-message-metadata.js";
|
|
13
|
+
import type { SlackMessageMetadata } from "./providers/slack/message-metadata.js";
|
|
14
|
+
|
|
15
|
+
export interface ReactionEnvelopeFacts {
|
|
16
|
+
channel: ChannelId;
|
|
17
|
+
/** Provider id of the chat the reaction belongs to. */
|
|
18
|
+
chatId: string;
|
|
19
|
+
/** Target message id, in the channel's own id space. */
|
|
20
|
+
targetMessageId: string;
|
|
21
|
+
emoji: string;
|
|
22
|
+
op: "added" | "removed";
|
|
23
|
+
/** Absent on the assistant's own reactions. */
|
|
24
|
+
actorExternalId?: string;
|
|
25
|
+
/** Absent on the assistant's own reactions. */
|
|
26
|
+
actorDisplayName?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function buildNeutralReactionMeta(
|
|
30
|
+
facts: ReactionEnvelopeFacts,
|
|
31
|
+
): ProviderMessageMetadata {
|
|
32
|
+
return {
|
|
33
|
+
source: facts.channel,
|
|
34
|
+
conversationExternalId: facts.chatId,
|
|
35
|
+
eventKind: "reaction",
|
|
36
|
+
...(facts.actorExternalId
|
|
37
|
+
? { actorExternalId: facts.actorExternalId }
|
|
38
|
+
: {}),
|
|
39
|
+
...(facts.actorDisplayName ? { displayName: facts.actorDisplayName } : {}),
|
|
40
|
+
reaction: {
|
|
41
|
+
targetMessageId: facts.targetMessageId,
|
|
42
|
+
emoji: facts.emoji,
|
|
43
|
+
op: facts.op,
|
|
44
|
+
...(facts.actorDisplayName
|
|
45
|
+
? { actorDisplayName: facts.actorDisplayName }
|
|
46
|
+
: {}),
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function buildSlackReactionMeta(
|
|
52
|
+
facts: ReactionEnvelopeFacts,
|
|
53
|
+
): SlackMessageMetadata {
|
|
54
|
+
return {
|
|
55
|
+
source: "slack",
|
|
56
|
+
channelId: facts.chatId,
|
|
57
|
+
// A reaction row stores the reacted message's ts in `channelTs`, which
|
|
58
|
+
// is its target rather than an id of its own.
|
|
59
|
+
channelTs: facts.targetMessageId,
|
|
60
|
+
eventKind: "reaction",
|
|
61
|
+
// No `threadTs`: Slack sends none on a reaction, so any thread id in
|
|
62
|
+
// scope is the reacted message's own ts. It equals `channelTs`, which
|
|
63
|
+
// every reader treats as "not in a thread" anyway, and storing it makes
|
|
64
|
+
// the row false evidence that a thread belongs to this conversation
|
|
65
|
+
// (`legacySlackConversationHasThreadEvidence`).
|
|
66
|
+
...(facts.actorExternalId
|
|
67
|
+
? { actorExternalUserId: facts.actorExternalId }
|
|
68
|
+
: {}),
|
|
69
|
+
...(facts.actorDisplayName ? { displayName: facts.actorDisplayName } : {}),
|
|
70
|
+
reaction: {
|
|
71
|
+
emoji: facts.emoji,
|
|
72
|
+
targetChannelTs: facts.targetMessageId,
|
|
73
|
+
op: facts.op,
|
|
74
|
+
...(facts.actorDisplayName
|
|
75
|
+
? { actorDisplayName: facts.actorDisplayName }
|
|
76
|
+
: {}),
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -68,13 +68,13 @@ export function stopMonitoringWorkerProcess(): WorkerProcessStatus {
|
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* Daemon-lifecycle entry point: spawn the monitor as a child of the daemon
|
|
71
|
-
* (
|
|
71
|
+
* (so it appears in the daemon's process tree and is torn down on
|
|
72
72
|
* shutdown). Runs on every boot — the monitor is platform infrastructure,
|
|
73
73
|
* not an opt-in feature. Fire-and-forget — a monitor failure must never
|
|
74
74
|
* block boot.
|
|
75
75
|
*/
|
|
76
76
|
export function startMonitoring(): void {
|
|
77
|
-
void spawnMonitoringWorkerProcess(
|
|
77
|
+
void spawnMonitoringWorkerProcess()
|
|
78
78
|
.then((r) =>
|
|
79
79
|
log.info(
|
|
80
80
|
{ pid: r.pid, alreadyRunning: r.alreadyRunning },
|
|
@@ -143,7 +143,11 @@ export async function readFileResidency(
|
|
|
143
143
|
const { stdout } = await execFileAsync(
|
|
144
144
|
"fincore",
|
|
145
145
|
["--bytes", "--json", ...paths],
|
|
146
|
-
{
|
|
146
|
+
{
|
|
147
|
+
timeout: 10_000,
|
|
148
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
149
|
+
windowsHide: true,
|
|
150
|
+
},
|
|
147
151
|
);
|
|
148
152
|
return parseFincoreJson(stdout);
|
|
149
153
|
} catch {
|
|
@@ -10,4 +10,4 @@ Guardian-request producers (access requests, tool approvals, tool-grant escalati
|
|
|
10
10
|
|
|
11
11
|
Approval-card **source references** (the link back to the channel message that triggered a request) resolve only through `resolveApprovalSourceReference()` in `runtime/approval-source-link.ts` -- producers spread the result into the `guardian.question` context payload and never hand-build links. Channel-format knowledge (id shapes, permalinks, mrkdwn) lives only in `messaging/providers/<channel>/` and `notifications/adapters/<channel>`; the four-layer ownership map is documented at the top of `approval-source-link.ts`. Exception: access-request cards predate the registry and still derive their Slack permalink from payload `messageTs` in `access-request-copy.ts` -- converge them onto the registry rather than adding a third resolution path.
|
|
12
12
|
|
|
13
|
-
Guardian-request card rows are **not conversation history**.
|
|
13
|
+
Guardian-request card rows are **not conversation history**. Only the vellum delivery persists a message row (`pairDeliveryWithConversation` pins it to the conversation the request is _about_, via `buildVellumCardAffinity`); channel guardian cards are delivery projections and pair no conversation at all, with the gateway delivery row (chat id + channel-native message id) as their only persisted envelope. `isGuardianCardRow` in `approval-card-data.ts` is the single definition of which rows are guardian cards (including rows channel deliveries paired before the projection-only policy), derived from the card's own `ui_surface` id rather than a stored marker so old rows need no backfill. **Both** history assemblers must consult it -- `Conversation.loadFromDb` and `loadSlackChronologicalContext`, which re-reads rows rather than using `this.messages` -- or the unfiltered one replays the card between a parked turn's `tool_use` and its `tool_result` and history repair destroys the real result. Surface state is exempt on purpose: the card's buttons must still route after a restart. Full rationale in [docs/guardian-request-flow.md](../../docs/guardian-request-flow.md).
|