@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
|
@@ -189,10 +189,11 @@ export const GUARDIAN_REQUESTS_IPC_METHODS = {
|
|
|
189
189
|
decide: "guardian_requests_decide",
|
|
190
190
|
expire: "guardian_requests_expire",
|
|
191
191
|
expireInteractionBound: "guardian_requests_expire_interaction_bound",
|
|
192
|
-
|
|
192
|
+
listExpiredPending: "guardian_requests_list_expired_pending",
|
|
193
193
|
createDelivery: "guardian_requests_create_delivery",
|
|
194
194
|
updateDelivery: "guardian_requests_update_delivery",
|
|
195
195
|
listDeliveries: "guardian_requests_list_deliveries",
|
|
196
|
+
listDeliveriesByChat: "guardian_requests_list_deliveries_by_chat",
|
|
196
197
|
getByDestinationMessage: "guardian_requests_get_by_destination_message",
|
|
197
198
|
listPendingByDestination: "guardian_requests_list_pending_by_destination",
|
|
198
199
|
listPendingByScope: "guardian_requests_list_pending_by_scope",
|
|
@@ -201,6 +202,32 @@ export const GUARDIAN_REQUESTS_IPC_METHODS = {
|
|
|
201
202
|
getByPendingQuestion: "guardian_requests_get_by_pending_question",
|
|
202
203
|
} as const;
|
|
203
204
|
|
|
205
|
+
/**
|
|
206
|
+
* The delivery-row statuses this codebase writes and matches on.
|
|
207
|
+
*
|
|
208
|
+
* `GuardianRequestDeliverySchema.status` stays a plain `z.string()` rather
|
|
209
|
+
* than an enum built from these: the column is persisted, so a row written
|
|
210
|
+
* by a different build must still read rather than throw on parse. These
|
|
211
|
+
* constants exist so a call site names a value instead of spelling it, not
|
|
212
|
+
* to close the set.
|
|
213
|
+
*
|
|
214
|
+
* `pending` is the creation default; `sent` and `failed` carry the
|
|
215
|
+
* notification delivery result the recorder maps in; `expired` is stamped
|
|
216
|
+
* when the request itself expires; `withdrawn` is the daemon's per-surface
|
|
217
|
+
* receipt that a card was durably withdrawn, which the gateway's
|
|
218
|
+
* per-request expire preserves and a retrying withdrawal skips.
|
|
219
|
+
*/
|
|
220
|
+
export const DELIVERY_STATUS = {
|
|
221
|
+
pending: "pending",
|
|
222
|
+
sent: "sent",
|
|
223
|
+
failed: "failed",
|
|
224
|
+
expired: "expired",
|
|
225
|
+
withdrawn: "withdrawn",
|
|
226
|
+
} as const;
|
|
227
|
+
|
|
228
|
+
export type DeliveryStatus =
|
|
229
|
+
(typeof DELIVERY_STATUS)[keyof typeof DELIVERY_STATUS];
|
|
230
|
+
|
|
204
231
|
export type GuardianRequestsIpcMethod =
|
|
205
232
|
(typeof GUARDIAN_REQUESTS_IPC_METHODS)[keyof typeof GUARDIAN_REQUESTS_IPC_METHODS];
|
|
206
233
|
|
|
@@ -418,7 +445,7 @@ const OUTCOME_TYPES_BY_DECISION_STATUS: Record<
|
|
|
418
445
|
/**
|
|
419
446
|
* Request for `guardian_requests_decide` (status CAS + optional ACL outcome).
|
|
420
447
|
* Decisions only resolve a pending request to approved/denied — expiry has
|
|
421
|
-
* `guardian_requests_expire`/`
|
|
448
|
+
* `guardian_requests_expire`/`_list_expired_pending`, so a malformed call can never
|
|
422
449
|
* apply an `aclOutcome` while leaving the request decidable again. The
|
|
423
450
|
* outcome type must agree with the status: activation/minting only on
|
|
424
451
|
* approval, seeding/blocking only on denial.
|
|
@@ -508,26 +535,22 @@ export type ExpireInteractionBoundIpcResponse = z.infer<
|
|
|
508
535
|
typeof ExpireInteractionBoundIpcResponseSchema
|
|
509
536
|
>;
|
|
510
537
|
|
|
511
|
-
/** Request for `guardian_requests_sweep_expired` (`now` defaults gateway-side). */
|
|
512
|
-
export const SweepExpiredGuardianRequestsIpcParamsSchema = z.object({
|
|
513
|
-
now: z.number().optional(),
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
export type SweepExpiredGuardianRequestsIpcParams = z.infer<
|
|
517
|
-
typeof SweepExpiredGuardianRequestsIpcParamsSchema
|
|
518
|
-
>;
|
|
519
|
-
|
|
520
538
|
/**
|
|
521
|
-
*
|
|
522
|
-
*
|
|
523
|
-
*
|
|
539
|
+
* Request for `guardian_requests_list_expired_pending` (`now` defaults
|
|
540
|
+
* gateway-side; `limit` bounds the batch and is capped gateway-side).
|
|
541
|
+
* Read-only: the rows stay `pending` until the daemon has run each one's
|
|
542
|
+
* expiry side effects and confirms with `guardian_requests_expire`, so a
|
|
543
|
+
* lost response leaves the work discoverable by the next sweep round
|
|
544
|
+
* instead of silently done. Past-deadline pending rows are undecidable
|
|
545
|
+
* either way: every decision path checks `expiresAt` before any write.
|
|
524
546
|
*/
|
|
525
|
-
export const
|
|
526
|
-
|
|
547
|
+
export const ListExpiredPendingGuardianRequestsIpcParamsSchema = z.object({
|
|
548
|
+
now: z.number().optional(),
|
|
549
|
+
limit: z.number().optional(),
|
|
527
550
|
});
|
|
528
551
|
|
|
529
|
-
export type
|
|
530
|
-
typeof
|
|
552
|
+
export type ListExpiredPendingGuardianRequestsIpcParams = z.infer<
|
|
553
|
+
typeof ListExpiredPendingGuardianRequestsIpcParamsSchema
|
|
531
554
|
>;
|
|
532
555
|
|
|
533
556
|
// ---------------------------------------------------------------------------
|
|
@@ -575,6 +598,22 @@ export type ListGuardianRequestDeliveriesIpcParams = z.infer<
|
|
|
575
598
|
typeof ListGuardianRequestDeliveriesIpcParamsSchema
|
|
576
599
|
>;
|
|
577
600
|
|
|
601
|
+
/**
|
|
602
|
+
* Request for `guardian_requests_list_deliveries_by_chat`: every
|
|
603
|
+
* delivery row addressed to one channel-native chat, whatever request it
|
|
604
|
+
* belongs to. Lets transcript importers recognize guardian card
|
|
605
|
+
* messages (by their recorded message id) as delivery projections
|
|
606
|
+
* rather than conversation content.
|
|
607
|
+
*/
|
|
608
|
+
export const ListGuardianRequestDeliveriesByChatIpcParamsSchema = z.object({
|
|
609
|
+
channel: z.string().min(1),
|
|
610
|
+
chatId: z.string().min(1),
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
export type ListGuardianRequestDeliveriesByChatIpcParams = z.infer<
|
|
614
|
+
typeof ListGuardianRequestDeliveriesByChatIpcParamsSchema
|
|
615
|
+
>;
|
|
616
|
+
|
|
578
617
|
/** Response for `guardian_requests_list_deliveries`. */
|
|
579
618
|
export const GuardianRequestDeliveryListIpcResponseSchema = z.array(
|
|
580
619
|
GuardianRequestDeliverySchema,
|
|
@@ -640,13 +679,15 @@ export type ListPendingGuardianRequestsByScopeIpcParams = z.infer<
|
|
|
640
679
|
|
|
641
680
|
/**
|
|
642
681
|
* Request for `guardian_requests_in_scope`: is a decision from this
|
|
643
|
-
* conversation allowed for the request (source match, or delivery match
|
|
644
|
-
*
|
|
682
|
+
* conversation allowed for the request (source match, or delivery match)?
|
|
683
|
+
* Deliberately not narrowed by delivery channel: `destinationConversationId`
|
|
684
|
+
* is always an internal conversation id, and every delivery's paired
|
|
685
|
+
* conversation renders the same actionable in-app card, so a match on any
|
|
686
|
+
* delivery row legitimizes the conversation.
|
|
645
687
|
*/
|
|
646
688
|
export const GuardianRequestInScopeIpcParamsSchema = z.object({
|
|
647
689
|
requestId: z.string().min(1),
|
|
648
690
|
conversationId: z.string().min(1),
|
|
649
|
-
channel: z.string().optional(),
|
|
650
691
|
});
|
|
651
692
|
|
|
652
693
|
export type GuardianRequestInScopeIpcParams = z.infer<
|
|
@@ -139,6 +139,11 @@ export const SourceMetadataSchema = z
|
|
|
139
139
|
* "not provided", never as a decision.
|
|
140
140
|
*/
|
|
141
141
|
trustVerdict: TrustVerdictSchema.optional(),
|
|
142
|
+
/**
|
|
143
|
+
* The platform named no actor for this event; the actor id is the
|
|
144
|
+
* channel's synthetic system identity, never an identity claim.
|
|
145
|
+
*/
|
|
146
|
+
actorUnattributed: z.boolean().optional(),
|
|
142
147
|
|
|
143
148
|
// Email-specific fields
|
|
144
149
|
/**
|
|
@@ -172,6 +177,15 @@ export const RuntimeInboundPayloadSchema = z.object({
|
|
|
172
177
|
/** The named event family; absent only on replayed retry payloads,
|
|
173
178
|
* where resolveInboundEventKind derives it from the legacy fields. */
|
|
174
179
|
eventKind: z.enum(INBOUND_EVENT_KINDS).optional(),
|
|
180
|
+
/** Structured reaction payload; replayed retry payloads carry the
|
|
181
|
+
* callbackData string form resolveInboundReactionPayload reads. */
|
|
182
|
+
reaction: z
|
|
183
|
+
.object({
|
|
184
|
+
op: z.enum(["added", "removed"]),
|
|
185
|
+
emoji: z.string(),
|
|
186
|
+
targetMessageId: z.string(),
|
|
187
|
+
})
|
|
188
|
+
.optional(),
|
|
175
189
|
isEdit: z.boolean().optional(),
|
|
176
190
|
callbackQueryId: z.string().optional(),
|
|
177
191
|
callbackData: z.string().optional(),
|
|
@@ -73,3 +73,56 @@ export function inboundEventRefersToAnotherMessage(
|
|
|
73
73
|
): boolean {
|
|
74
74
|
return kind !== "message";
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
/** The structured payload of a reaction event. */
|
|
78
|
+
export interface InboundReactionPayload {
|
|
79
|
+
op: "added" | "removed";
|
|
80
|
+
/**
|
|
81
|
+
* The emoji as the channel names it: Slack a colon-name ("+1"), Telegram
|
|
82
|
+
* and Discord the unicode character, a Discord custom emoji its name.
|
|
83
|
+
* Decision vocabulary is product policy resolved in the daemon, never
|
|
84
|
+
* normalized here.
|
|
85
|
+
*/
|
|
86
|
+
emoji: string;
|
|
87
|
+
/**
|
|
88
|
+
* Provider id of the message reacted to, in the same namespace as
|
|
89
|
+
* `source.messageId`.
|
|
90
|
+
*/
|
|
91
|
+
targetMessageId: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The one reader of a reaction event's payload. A structured `reaction`
|
|
96
|
+
* field wins; a replayed retry payload persisted before the field carries
|
|
97
|
+
* the `"reaction:<emoji>"` / `"reaction_removed:<emoji>"` string in
|
|
98
|
+
* `callbackData` with the target on `sourceMetadata.messageId`, and is
|
|
99
|
+
* parsed here alone. Returns null when the event is not a reaction or
|
|
100
|
+
* names no emoji or target.
|
|
101
|
+
*/
|
|
102
|
+
export function resolveInboundReactionPayload(fields: {
|
|
103
|
+
eventKind?: string;
|
|
104
|
+
reaction?: InboundReactionPayload;
|
|
105
|
+
callbackData?: string;
|
|
106
|
+
sourceMetadata?: { messageId?: string };
|
|
107
|
+
}): InboundReactionPayload | null {
|
|
108
|
+
if (fields.reaction) {
|
|
109
|
+
const { op, emoji, targetMessageId } = fields.reaction;
|
|
110
|
+
return emoji.length > 0 && targetMessageId.length > 0
|
|
111
|
+
? { op, emoji, targetMessageId }
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
const cb = fields.callbackData;
|
|
115
|
+
const target = fields.sourceMetadata?.messageId;
|
|
116
|
+
if (cb === undefined || target === undefined || target.length === 0) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
const removed = cb.startsWith("reaction_removed:");
|
|
120
|
+
const added = !removed && cb.startsWith("reaction:");
|
|
121
|
+
if (!added && !removed) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const emoji = cb.slice(cb.indexOf(":") + 1);
|
|
125
|
+
return emoji.length > 0
|
|
126
|
+
? { op: removed ? "removed" : "added", emoji, targetMessageId: target }
|
|
127
|
+
: null;
|
|
128
|
+
}
|
|
@@ -88,8 +88,12 @@ export {
|
|
|
88
88
|
inboundEventRefersToAnotherMessage,
|
|
89
89
|
isInboundEventKind,
|
|
90
90
|
resolveInboundEventKind,
|
|
91
|
+
resolveInboundReactionPayload,
|
|
92
|
+
} from "./inbound-event-kind.js";
|
|
93
|
+
export type {
|
|
94
|
+
InboundEventKind,
|
|
95
|
+
InboundReactionPayload,
|
|
91
96
|
} from "./inbound-event-kind.js";
|
|
92
|
-
export type { InboundEventKind } from "./inbound-event-kind.js";
|
|
93
97
|
|
|
94
98
|
// Plugin admission-denied notice (gateway → plugin) — canned deny copy + envelope
|
|
95
99
|
export {
|
|
@@ -260,12 +264,13 @@ export {
|
|
|
260
264
|
GuardianRequestSourceTypeSchema,
|
|
261
265
|
GuardianRequestStatusSchema,
|
|
262
266
|
isGuardianRequestExpired,
|
|
267
|
+
ListGuardianRequestDeliveriesByChatIpcParamsSchema,
|
|
263
268
|
ListGuardianRequestDeliveriesIpcParamsSchema,
|
|
264
269
|
ListGuardianRequestsIpcParamsSchema,
|
|
265
270
|
ListPendingGuardianRequestsByDestinationIpcParamsSchema,
|
|
266
271
|
ListPendingGuardianRequestsByScopeIpcParamsSchema,
|
|
267
|
-
|
|
268
|
-
|
|
272
|
+
DELIVERY_STATUS,
|
|
273
|
+
ListExpiredPendingGuardianRequestsIpcParamsSchema,
|
|
269
274
|
UpdateGuardianRequestDeliveryIpcParamsSchema,
|
|
270
275
|
UpdateGuardianRequestIpcParamsSchema,
|
|
271
276
|
} from "./guardian-request-contract.js";
|
|
@@ -275,6 +280,7 @@ export type {
|
|
|
275
280
|
CreateGuardianRequestIpcParams,
|
|
276
281
|
DecideGuardianRequestIpcParams,
|
|
277
282
|
DecideGuardianRequestIpcResponse,
|
|
283
|
+
DeliveryStatus,
|
|
278
284
|
ExpireGuardianRequestIpcParams,
|
|
279
285
|
ExpireInteractionBoundIpcParams,
|
|
280
286
|
ExpireInteractionBoundIpcResponse,
|
|
@@ -298,12 +304,12 @@ export type {
|
|
|
298
304
|
GuardianRequestSourceType,
|
|
299
305
|
GuardianRequestStatus,
|
|
300
306
|
GuardianRequestWire,
|
|
307
|
+
ListGuardianRequestDeliveriesByChatIpcParams,
|
|
301
308
|
ListGuardianRequestDeliveriesIpcParams,
|
|
302
309
|
ListGuardianRequestsIpcParams,
|
|
303
310
|
ListPendingGuardianRequestsByDestinationIpcParams,
|
|
304
311
|
ListPendingGuardianRequestsByScopeIpcParams,
|
|
305
|
-
|
|
306
|
-
SweepExpiredGuardianRequestsIpcResponse,
|
|
312
|
+
ListExpiredPendingGuardianRequestsIpcParams,
|
|
307
313
|
UpdateGuardianRequestDeliveryIpcParams,
|
|
308
314
|
UpdateGuardianRequestIpcParams,
|
|
309
315
|
} from "./guardian-request-contract.js";
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"./client-metadata": "./src/client-metadata.ts",
|
|
12
12
|
"./credential-rpc": "./src/credential-rpc.ts",
|
|
13
13
|
"./ingress": "./src/ingress.ts",
|
|
14
|
+
"./no-response": "./src/no-response.ts",
|
|
14
15
|
"./remote-web-pairing": "./src/remote-web-pairing.ts",
|
|
15
16
|
"./twilio-ingress": "./src/twilio-ingress.ts",
|
|
16
17
|
"./trust-rules": "./src/trust-rules.ts",
|
|
@@ -66,6 +66,13 @@ export function isChannelId(value: unknown): value is ChannelId {
|
|
|
66
66
|
* That irregularity is why this is stated rather than derived from the key,
|
|
67
67
|
* and it is stated here because this file already owns what a channel is.
|
|
68
68
|
*
|
|
69
|
+
* Both senses can hold a user token, which is the sharpest edge. The `slack`
|
|
70
|
+
* integration's persisted token *is* the installer's user token, held on its
|
|
71
|
+
* OAuth connection. `slack_channel` holds an optional `user_token` in the
|
|
72
|
+
* credential store, beside its bot and app tokens. Same words, different
|
|
73
|
+
* homes, and only the second is a credential-store key: a pasted token is
|
|
74
|
+
* always the channel's, because the integration's never leaves the exchange.
|
|
75
|
+
*
|
|
69
76
|
* Deliberately only the key. What fields each credential requires is declared
|
|
70
77
|
* once already, per service, in the gateway's credential specs; restating it
|
|
71
78
|
* here would be a second copy of a different fact.
|
|
@@ -27,6 +27,7 @@ export * from "./handles.js";
|
|
|
27
27
|
export * from "./rpc.js";
|
|
28
28
|
export * from "./trust-rules.js";
|
|
29
29
|
export * from "./ingress.js";
|
|
30
|
+
export * from "./no-response.js";
|
|
30
31
|
export * from "./remote-web-pairing.js";
|
|
31
32
|
export * from "./twilio-ingress.js";
|
|
32
33
|
export * from "./url-normalization.js";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `<no_response/>` sentinel: the cross-service convention for a turn
|
|
3
|
+
* that deliberately produces no user-visible reply.
|
|
4
|
+
*
|
|
5
|
+
* The model emits it, the daemon stamps and strips it, channel delivery
|
|
6
|
+
* suppresses it, and clients hold live-streamed prefixes of it back from
|
|
7
|
+
* display. One definition here keeps every consumer's parsing identical;
|
|
8
|
+
* a hand-rolled copy in any one of them is how the case-sensitivity of a
|
|
9
|
+
* regex drifts.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** Matches a message whose entire content is the sentinel. */
|
|
13
|
+
const NO_RESPONSE_ONLY_RE = /^\s*<no_response\s*\/?>\s*$/i;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether `text` is nothing but the sentinel: the whole reply is a
|
|
17
|
+
* deliberate non-response, as opposed to real content with an inline
|
|
18
|
+
* sentinel mixed in.
|
|
19
|
+
*/
|
|
20
|
+
export function isNoResponseOnlyText(text: string): boolean {
|
|
21
|
+
return NO_RESPONSE_ONLY_RE.test(text);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Matches every sentinel occurrence for stripping it out of mixed content. */
|
|
25
|
+
export const NO_RESPONSE_INLINE_RE = /<no_response\s*\/?>/gi;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Detection variant without the `g` flag: a `g`-flagged regex is stateful
|
|
29
|
+
* under `.test()` (it resumes from `lastIndex`), so reusing
|
|
30
|
+
* {@link NO_RESPONSE_INLINE_RE} for detection would alternate between
|
|
31
|
+
* matches and misses across calls.
|
|
32
|
+
*/
|
|
33
|
+
const NO_RESPONSE_MARKER_RE = new RegExp(NO_RESPONSE_INLINE_RE.source, "i");
|
|
34
|
+
|
|
35
|
+
/** Whether `text` contains the sentinel anywhere. */
|
|
36
|
+
export function containsNoResponseMarker(text: string): boolean {
|
|
37
|
+
return NO_RESPONSE_MARKER_RE.test(text);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Removes every sentinel occurrence, trimming the leftover whitespace. */
|
|
41
|
+
export function stripNoResponseMarkers(text: string): string {
|
|
42
|
+
return text.replace(NO_RESPONSE_INLINE_RE, "").trim();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const NO_RESPONSE_SENTINEL_FORMS = [
|
|
46
|
+
"<no_response/>",
|
|
47
|
+
"<no_response />",
|
|
48
|
+
"<no_response>",
|
|
49
|
+
] as const;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Whether `text` could still grow into the sentinel, i.e. it is a leading
|
|
53
|
+
* substring of one of its forms. Holding on these keeps a slowly-streamed
|
|
54
|
+
* `<no_response/>` from surfacing as visible partial content.
|
|
55
|
+
*/
|
|
56
|
+
export function isPotentialNoResponsePrefix(text: string): boolean {
|
|
57
|
+
const lower = text.trim().toLowerCase();
|
|
58
|
+
if (lower.length === 0) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return NO_RESPONSE_SENTINEL_FORMS.some((sentinel) =>
|
|
62
|
+
sentinel.startsWith(lower),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether `text` carries user-visible content worth acting on now. Returns
|
|
68
|
+
* `false` for empty text, the standalone sentinel, and any prefix that could
|
|
69
|
+
* still complete into one; returns `true` once real content remains after
|
|
70
|
+
* stripping inline sentinels.
|
|
71
|
+
*/
|
|
72
|
+
export function hasDeliverableAssistantText(text: string): boolean {
|
|
73
|
+
const trimmed = text.trim();
|
|
74
|
+
if (trimmed.length === 0) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (NO_RESPONSE_ONLY_RE.test(trimmed)) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (isPotentialNoResponsePrefix(trimmed)) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return stripNoResponseMarkers(trimmed).length > 0;
|
|
84
|
+
}
|