@vellumai/assistant 0.11.8 → 0.11.9-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +2 -2
- package/Dockerfile +8 -48
- package/docker-entrypoint.sh +5 -1
- package/docker-kata-apt-env.sh +3 -0
- package/docker-kata-apt-shims.sh +127 -0
- package/docker-kata-apt-wrapper.sh +45 -0
- package/docker-kata-chroot-exec.sh +35 -0
- package/docker-kata-pip.sh +8 -2
- package/docs/architecture/memory.md +8 -4
- package/docs/guardian-request-flow.md +18 -14
- package/docs/trusted-contact-access.md +1 -7
- package/node_modules/@vellumai/avatar-catalog/src/catalog.ts +7 -1
- package/node_modules/@vellumai/avatar-catalog/src/index.ts +1 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +4 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +18 -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/platform-credential.ts +41 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/reactions.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +4 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +18 -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/platform-credential.ts +41 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/reactions.ts +60 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +0 -18
- package/node_modules/@vellumai/gateway-client/src/__tests__/inbound-event-kind.test.ts +110 -5
- package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +5 -33
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +3 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-event-kind.ts +100 -9
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -2
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +9 -0
- package/node_modules/@vellumai/service-contracts/package.json +4 -1
- package/node_modules/@vellumai/service-contracts/src/guardian-requests.ts +18 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/platform-credential.ts +41 -0
- package/node_modules/@vellumai/service-contracts/src/reactions.ts +60 -0
- package/openapi.yaml +193 -4
- package/package.json +2 -2
- package/src/__tests__/access-request-card-view.test.ts +6 -5
- package/src/__tests__/access-request-seed-content-blocks.test.ts +5 -2
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +43 -82
- package/src/__tests__/always-loaded-tools-guard.test.ts +8 -2
- package/src/__tests__/attachment-stored-path-annotation.test.ts +80 -0
- package/src/__tests__/attachments-store.test.ts +27 -0
- package/src/__tests__/attachments.test.ts +43 -0
- package/src/__tests__/canned-reply-release.test.ts +48 -5
- package/src/__tests__/channel-delivery-store.test.ts +129 -18
- package/src/__tests__/channel-reply-delivery.test.ts +553 -93
- package/src/__tests__/channel-retry-sweep.test.ts +199 -0
- package/src/__tests__/client-os-metadata-persistence.test.ts +32 -3
- package/src/__tests__/conversation-error.test.ts +15 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +118 -0
- package/src/__tests__/conversation-pairing.test.ts +141 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +28 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +125 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +79 -0
- package/src/__tests__/conversation-store-ephemeral.test.ts +323 -10
- package/src/__tests__/conversation-sync-tags.test.ts +2 -37
- package/src/__tests__/credential-health-service.test.ts +98 -10
- package/src/__tests__/delete-propagation.test.ts +469 -0
- package/src/__tests__/dm-persistence.test.ts +16 -0
- package/src/__tests__/docker-kata-apt-shims.test.ts +135 -0
- package/src/__tests__/forbidden-legacy-symbols.test.ts +12 -0
- package/src/__tests__/gemini-provider.test.ts +46 -0
- package/src/__tests__/guardian-card-withdrawal.test.ts +0 -22
- package/src/__tests__/guardian-gateway-sim.ts +0 -23
- package/src/__tests__/guardian-question-mode.test.ts +108 -0
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +0 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +26 -12
- package/src/__tests__/host-proxy-interface.test.ts +10 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +16 -0
- package/src/__tests__/injector-v3-suppression.test.ts +43 -9
- package/src/__tests__/list-messages-page-latest.test.ts +127 -0
- package/src/__tests__/list-messages-system-card.test.ts +103 -0
- package/src/__tests__/media-resolve-image-validation.test.ts +77 -0
- package/src/__tests__/notification-decision-fallback.test.ts +199 -77
- package/src/__tests__/notification-decision-strategy.test.ts +198 -213
- package/src/__tests__/notification-discord-adapter.test.ts +25 -0
- package/src/__tests__/notification-slack-adapter.test.ts +133 -0
- package/src/__tests__/notification-telegram-adapter.test.ts +36 -0
- package/src/__tests__/openai-provider.test.ts +5 -5
- package/src/__tests__/outbound-slack-persistence.test.ts +85 -72
- package/src/__tests__/persist-user-message-set-processing-failure.test.ts +83 -65
- package/src/__tests__/platform-client-verify-credential.test.ts +100 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +1 -1
- package/src/__tests__/pricing.test.ts +11 -0
- package/src/__tests__/process-message-display-content.test.ts +20 -9
- package/src/__tests__/processing-acquire-fenced-guard.test.ts +56 -0
- package/src/__tests__/provider-meta-persistence.test.ts +67 -0
- package/src/__tests__/reaction-persistence.test.ts +22 -198
- package/src/__tests__/run-conversation-turn-persistence.test.ts +5 -2
- package/src/__tests__/scripted-turn-metadata-persistence.test.ts +16 -0
- package/src/__tests__/skill-load-tool.test.ts +27 -0
- package/src/__tests__/skills.test.ts +34 -1
- package/src/__tests__/strip-memory-injections.test.ts +3 -4
- package/src/__tests__/terminal-tools.test.ts +9 -0
- package/src/__tests__/thread-backfill.test.ts +5 -3
- package/src/__tests__/unified-turn-context-location.test.ts +76 -0
- package/src/__tests__/voice-session-bridge.test.ts +18 -0
- package/src/__tests__/watch-retro-report-payload.test.ts +185 -0
- package/src/__tests__/watch-retro-tool-availability.test.ts +82 -0
- package/src/__tests__/workspace-migration-151-repair-renamed-fireworks-deepseek-pro-model-id.test.ts +235 -0
- package/src/__tests__/workspace-migration-152-repair-retired-fireworks-minimax-m2p7-model-id.test.ts +233 -0
- package/src/agent/attachments.ts +13 -2
- package/src/agent/loop.ts +3 -19
- package/src/api/README.md +9 -5
- package/src/api/index.ts +9 -8
- package/src/api/package.json +1 -0
- package/src/api/responses/conversation-message.ts +8 -0
- package/src/api/responses/home.ts +7 -18
- package/src/api/surfaces.ts +114 -7
- package/src/approvals/AGENTS.md +1 -1
- package/src/channels/__tests__/gateway-guardian-requests.test.ts +1 -23
- package/src/channels/__tests__/types.test.ts +22 -1
- package/src/channels/gateway-guardian-requests.ts +0 -22
- package/src/channels/types.ts +8 -6
- package/src/cli/__tests__/catalog-search-help.test.ts +18 -0
- package/src/cli/commands/channels/__tests__/channels.test.ts +26 -0
- package/src/cli/commands/channels/index.help.ts +19 -6
- package/src/cli/commands/channels/index.ts +6 -2
- package/src/cli/commands/db/__tests__/status.test.ts +22 -0
- package/src/cli/commands/db/index.help.ts +1 -1
- package/src/cli/commands/db/status.ts +172 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +29 -0
- package/src/cli/commands/platform/connect.ts +14 -5
- package/src/cli/commands/plugins.help.ts +6 -5
- package/src/cli/lib/__tests__/install-from-github.test.ts +0 -8
- package/src/cli/lib/__tests__/install-from-platform.test.ts +72 -0
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +33 -0
- package/src/cli/lib/bundled-marketplace.json +14 -0
- package/src/cli/lib/install-from-github.ts +9 -5
- package/src/cli/lib/install-from-platform.ts +12 -1
- package/src/config/__tests__/assistant-initiated-threads-gate.test.ts +61 -0
- package/src/config/assistant-initiated-threads-gate.ts +50 -0
- package/src/config/bundled-skills/acp/SKILL.md +10 -3
- package/src/config/bundled-skills/schedule/SKILL.md +25 -11
- package/src/config/bundled-skills/schedule/references/SCRIPT_MODE_PATTERNS.md +3 -1
- package/src/config/call-site-defaults.ts +4 -1
- package/src/config/feature-flag-registry.json +21 -4
- package/src/config/schemas/memory-v3.ts +4 -3
- package/src/context/strip-injections.ts +17 -56
- package/src/conversations/__tests__/message-consolidation.test.ts +39 -0
- package/src/conversations/message-consolidation.ts +4 -3
- package/src/credential-health/credential-health-service.ts +130 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +31 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +55 -59
- package/src/daemon/conversation-error.ts +2 -0
- package/src/daemon/conversation-messaging.ts +195 -47
- package/src/daemon/conversation-process.ts +20 -5
- package/src/daemon/conversation-runtime-assembly.ts +48 -39
- package/src/daemon/conversation-store.ts +159 -11
- package/src/daemon/conversation-tool-setup.ts +9 -2
- package/src/daemon/conversation.ts +290 -19
- package/src/daemon/dictation-text-processing.ts +2 -7
- package/src/daemon/handlers/config-channels.ts +33 -3
- package/src/daemon/handlers/config-model.test.ts +1 -0
- package/src/daemon/handlers/shared.ts +9 -0
- package/src/daemon/port-oversized-content.test.ts +117 -0
- package/src/daemon/port-oversized-content.ts +110 -0
- package/src/daemon/process-message.ts +87 -16
- package/src/daemon/reaction-record.test.ts +23 -11
- package/src/daemon/reaction-record.ts +6 -9
- package/src/documents/document-store.ts +1 -5
- package/src/home/conversation-starter-validation.ts +1 -5
- package/src/live-voice/__tests__/live-voice-photo.test.ts +910 -50
- package/src/live-voice/__tests__/live-voice-sight-frame-inline.test.ts +31 -25
- package/src/live-voice/__tests__/live-voice-sight-frame.test.ts +70 -1
- package/src/live-voice/live-voice-photo.ts +544 -61
- package/src/live-voice/live-voice-session.ts +6 -2
- package/src/live-voice/protocol.ts +20 -1
- package/src/messaging/provider-message-metadata.ts +40 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +10 -2
- package/src/messaging/providers/channel-transport.ts +28 -0
- package/src/messaging/providers/discord/send.ts +3 -2
- package/src/messaging/providers/slack/api.ts +11 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +133 -0
- package/src/messaging/providers/slack/message-metadata.ts +141 -1
- package/src/messaging/providers/slack/send.test.ts +58 -0
- package/src/messaging/providers/slack/send.ts +4 -4
- package/src/messaging/providers/slack/transport.ts +28 -2
- package/src/messaging/providers/telegram-bot/send.test.ts +159 -0
- package/src/messaging/providers/telegram-bot/send.ts +93 -0
- package/src/messaging/providers/telegram-bot/transport.ts +71 -0
- package/src/messaging/reaction-envelopes.test.ts +73 -0
- package/src/messaging/reaction-envelopes.ts +33 -5
- package/src/messaging/read-provider-metadata.ts +4 -3
- package/src/monitoring/recovery/__tests__/stranded-delivery-events.test.ts +208 -0
- package/src/monitoring/recovery/db.ts +35 -0
- package/src/monitoring/recovery/orphaned-channel-events.ts +3 -22
- package/src/monitoring/recovery/run-recovery.ts +6 -2
- package/src/monitoring/recovery/stale-processing.ts +3 -20
- package/src/monitoring/recovery/stranded-delivery-events.ts +68 -0
- package/src/notifications/AGENTS.md +2 -2
- package/src/notifications/README.md +2 -2
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +11 -9
- package/src/notifications/__tests__/broadcaster.test.ts +35 -4
- package/src/notifications/__tests__/notification-utils.test.ts +31 -0
- package/src/notifications/access-request-copy.ts +126 -114
- package/src/notifications/adapters/discord.ts +9 -5
- package/src/notifications/adapters/shared.ts +17 -4
- package/src/notifications/adapters/slack.ts +14 -4
- package/src/notifications/adapters/telegram.ts +8 -4
- package/src/notifications/approval-card-data.ts +5 -2
- package/src/notifications/assistant-reply-producer.ts +7 -7
- package/src/notifications/broadcaster.ts +57 -25
- package/src/notifications/conversation-pairing.ts +68 -2
- package/src/notifications/copy-composer.ts +13 -32
- package/src/notifications/decision-engine.ts +56 -237
- package/src/notifications/guardian-delivery-recorder.ts +5 -9
- package/src/notifications/guardian-feed-projection.ts +0 -15
- package/src/notifications/guardian-question-mode.ts +147 -6
- package/src/notifications/notification-utils.ts +117 -1
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -1
- package/src/persistence/conversation-crud.ts +93 -14
- package/src/persistence/conversation-queries.ts +144 -17
- package/src/persistence/conversation-types.ts +39 -5
- package/src/persistence/delivery-crud.ts +224 -28
- package/src/persistence/delivery-status.ts +21 -2
- package/src/persistence/migrations/374-channel-inbound-message-id-index.ts +26 -0
- package/src/persistence/migrations/375-create-channel-outbound-posts.ts +52 -0
- package/src/persistence/migrations/__tests__/375-create-channel-outbound-posts.test.ts +84 -0
- package/src/persistence/schema/conversations.ts +71 -2
- package/src/persistence/schema-contract.test.ts +78 -0
- package/src/persistence/schema-contract.ts +96 -0
- package/src/persistence/steps.ts +4 -0
- package/src/platform/client.ts +55 -0
- package/src/plugins/__tests__/mcp-servers.test.ts +46 -0
- package/src/plugins/defaults/injector-order.ts +2 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +2 -2
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +13 -15
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +10 -0
- package/src/plugins/defaults/memory/injectors.ts +1 -1
- package/src/plugins/defaults/memory/memory-marker.ts +17 -7
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +1 -5
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +17 -0
- package/src/plugins/defaults/memory/substrate/skill-content.ts +7 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +54 -41
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +3 -3
- package/src/plugins/defaults/memory/v3/__tests__/render-injection.test.ts +22 -0
- package/src/plugins/defaults/memory/v3/injector.ts +14 -15
- package/src/plugins/defaults/memory/v3/prune.test.ts +20 -2
- package/src/plugins/defaults/memory/v3/render-injection.ts +10 -1
- package/src/plugins/defaults/memory/v3/types.ts +15 -4
- package/src/plugins/defaults/turn-context/injectors.ts +3 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +24 -0
- package/src/plugins/mcp-servers.ts +14 -2
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +50 -0
- package/src/providers/__tests__/registry-native-web-search.test.ts +49 -2
- package/src/providers/anthropic/client.ts +21 -24
- package/src/providers/call-site-routing.ts +5 -4
- package/src/providers/connection-resolution.ts +29 -1
- package/src/providers/content-block-size.test.ts +82 -0
- package/src/providers/content-block-size.ts +99 -0
- package/src/providers/file-block-text.test.ts +64 -0
- package/src/providers/file-block-text.ts +28 -0
- package/src/providers/gemini/client.ts +15 -9
- package/src/providers/inference/auth.ts +6 -6
- package/src/providers/media-resolve.ts +14 -0
- package/src/providers/model-catalog.ts +47 -34
- package/src/providers/openai/chat-completions-provider.ts +9 -25
- package/src/providers/openai/responses-provider.ts +11 -18
- package/src/providers/registry.ts +10 -7
- package/src/providers/routing-identity.ts +2 -1
- package/src/providers/types.ts +1 -4
- package/src/providers/vellum-model-routing.ts +3 -2
- package/src/runtime/AGENTS.md +40 -15
- package/src/runtime/approval-message-composer.ts +1 -6
- package/src/runtime/assistant-event-hub.ts +2 -39
- package/src/runtime/channel-approval-types.ts +1 -5
- package/src/runtime/channel-reply-delivery.ts +182 -115
- package/src/runtime/{slack-reply-session.test.ts → channel-reply-session.test.ts} +294 -156
- package/src/runtime/{slack-reply-session.ts → channel-reply-session.ts} +107 -86
- package/src/runtime/channel-retry-sweep.ts +102 -1
- package/src/runtime/finalize-event-delivery.ts +4 -4
- package/src/runtime/guardian-action-message-composer.ts +1 -4
- package/src/runtime/guardian-reply-router.ts +4 -75
- package/src/runtime/http-router.ts +1 -5
- package/src/runtime/question-request-guardian-bridge.ts +2 -3
- package/src/runtime/routes/__tests__/conversation-list-assistant-section.test.ts +359 -0
- package/src/runtime/routes/__tests__/dictation-command-mode.test.ts +120 -0
- package/src/runtime/routes/__tests__/sight-frame-routes.test.ts +487 -0
- package/src/runtime/routes/acp-routes.ts +1 -1
- package/src/runtime/routes/canned-reply-release.ts +19 -9
- package/src/runtime/routes/channel-route-shared.ts +0 -39
- package/src/runtime/routes/channel-verification-routes.ts +4 -1
- package/src/runtime/routes/conversation-list-routes.ts +44 -3
- package/src/runtime/routes/conversation-management-routes.ts +2 -1
- package/src/runtime/routes/conversation-routes.ts +138 -59
- package/src/runtime/routes/diagnostics-routes.ts +111 -60
- package/src/runtime/routes/guardian-action-routes.ts +10 -14
- package/src/runtime/routes/guardian-approval-interception.ts +0 -5
- package/src/runtime/routes/inbound-message-handler.ts +170 -48
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +4 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +169 -8
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +82 -14
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +23 -48
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +454 -94
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +309 -102
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/platform-routes.ts +99 -10
- package/src/runtime/routes/sight-frame-routes.ts +136 -0
- package/src/runtime/sync/resource-sync-events.ts +14 -37
- package/src/runtime/sync/sync-publisher.test.ts +5 -4
- package/src/tools/__tests__/tool-input-schemas.test.ts +2 -0
- package/src/tools/client-os.ts +11 -1
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/skills/load.ts +1 -1
- package/src/tools/terminal/safe-env.ts +4 -0
- package/src/tools/tool-input-schemas.ts +2 -0
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/ui-surface/definitions.ts +4 -3
- package/src/tools/watch/watch-retro-report.ts +205 -0
- package/src/watch/__tests__/watch-retro.test.ts +268 -40
- package/src/watch/watch-retro.ts +190 -77
- package/src/workspace/migrations/151-repair-renamed-fireworks-deepseek-pro-model-id.ts +195 -0
- package/src/workspace/migrations/152-repair-retired-fireworks-minimax-m2p7-model-id.ts +198 -0
- package/src/workspace/migrations/__tests__/150-stt-flux-provider-to-model-family.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +4 -0
- package/docker-kata-pip-chroot.sh +0 -22
- package/src/__tests__/slack-reaction-approvals.test.ts +0 -97
- package/src/__tests__/slack-reaction-guardian-approval.test.ts +0 -307
- package/src/api/events/conversation-list-invalidated.ts +0 -38
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical vocabulary for a reaction's emoji, shared by every service that
|
|
3
|
+
* handles one: the gateway that normalizes it, the daemon that stores and
|
|
4
|
+
* projects it, and the web that renders it.
|
|
5
|
+
*
|
|
6
|
+
* The kind is said by the channel rather than inferred from how the emoji
|
|
7
|
+
* is spelled. Modelled on Zulip's `reaction_type`, the one surveyed system
|
|
8
|
+
* that separates the namespace from the name.
|
|
9
|
+
*
|
|
10
|
+
* `shortcode` is a name in a channel's own namespace whose kind the channel
|
|
11
|
+
* does not disclose: Slack sends `+1` for the standard emoji and `blob_wave`
|
|
12
|
+
* for a workspace upload with nothing to tell them apart, and only the
|
|
13
|
+
* workspace token can resolve the second. It is a distinct kind from
|
|
14
|
+
* `unicode`, not a stand-in for an unknown one.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
|
|
18
|
+
export const REACTION_EMOJI_KINDS = ["unicode", "shortcode", "custom"] as const;
|
|
19
|
+
export type ReactionEmojiKind = (typeof REACTION_EMOJI_KINDS)[number];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The typed emoji fields every schema that carries a reaction spreads in,
|
|
23
|
+
* so the wire contract, the stored envelopes, and the response projection
|
|
24
|
+
* describe one shape. Optional throughout: a persisted row or a replayed
|
|
25
|
+
* payload may carry only the spelling.
|
|
26
|
+
*/
|
|
27
|
+
export const ReactionEmojiFieldsSchema = z.object({
|
|
28
|
+
/** Which namespace the emoji was drawn from. */
|
|
29
|
+
emojiKind: z.enum(REACTION_EMOJI_KINDS).optional(),
|
|
30
|
+
/**
|
|
31
|
+
* The emoji's name in that namespace: the character itself for `unicode`,
|
|
32
|
+
* the bare name for `shortcode` and `custom`. Never a mention form.
|
|
33
|
+
*/
|
|
34
|
+
emojiName: z.string().optional(),
|
|
35
|
+
/** The channel's id for a `custom` emoji, absent for every other kind. */
|
|
36
|
+
emojiId: z.string().optional(),
|
|
37
|
+
/** Whether a `custom` emoji animates. Absent for every other kind. */
|
|
38
|
+
emojiAnimated: z.boolean().optional(),
|
|
39
|
+
});
|
|
40
|
+
export type ReactionEmojiFields = z.infer<typeof ReactionEmojiFieldsSchema>;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The typed emoji fields a source actually carries, with undefined ones
|
|
44
|
+
* omitted: an absent key and a present-but-undefined one serialize alike, but the
|
|
45
|
+
* stored envelope and the response should carry only what was declared. Every writer of a reaction shape (the wire
|
|
46
|
+
* payload, both stored envelopes, the response projection) copies the
|
|
47
|
+
* fields through this rather than restating the four-way pick.
|
|
48
|
+
*/
|
|
49
|
+
export function pickReactionEmojiFields(
|
|
50
|
+
source: ReactionEmojiFields,
|
|
51
|
+
): ReactionEmojiFields {
|
|
52
|
+
return {
|
|
53
|
+
...(source.emojiKind !== undefined ? { emojiKind: source.emojiKind } : {}),
|
|
54
|
+
...(source.emojiName !== undefined ? { emojiName: source.emojiName } : {}),
|
|
55
|
+
...(source.emojiId !== undefined ? { emojiId: source.emojiId } : {}),
|
|
56
|
+
...(source.emojiAnimated !== undefined
|
|
57
|
+
? { emojiAnimated: source.emojiAnimated }
|
|
58
|
+
: {}),
|
|
59
|
+
};
|
|
60
|
+
}
|
package/openapi.yaml
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
openapi: 3.1.0
|
|
4
4
|
info:
|
|
5
5
|
title: Vellum Assistant API
|
|
6
|
-
version: 0.11.
|
|
6
|
+
version: 0.11.9
|
|
7
7
|
description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
|
|
8
8
|
servers:
|
|
9
9
|
- url: http://127.0.0.1:7821
|
|
@@ -4076,6 +4076,59 @@ paths:
|
|
|
4076
4076
|
responses:
|
|
4077
4077
|
"200":
|
|
4078
4078
|
description: Successful response
|
|
4079
|
+
content:
|
|
4080
|
+
application/json:
|
|
4081
|
+
schema:
|
|
4082
|
+
type: object
|
|
4083
|
+
properties:
|
|
4084
|
+
success:
|
|
4085
|
+
type: boolean
|
|
4086
|
+
bound:
|
|
4087
|
+
type: boolean
|
|
4088
|
+
channel:
|
|
4089
|
+
type: string
|
|
4090
|
+
enum:
|
|
4091
|
+
- telegram
|
|
4092
|
+
- phone
|
|
4093
|
+
- vellum
|
|
4094
|
+
- whatsapp
|
|
4095
|
+
- slack
|
|
4096
|
+
- email
|
|
4097
|
+
- platform
|
|
4098
|
+
- a2a
|
|
4099
|
+
- discord
|
|
4100
|
+
- plugin
|
|
4101
|
+
assistantId:
|
|
4102
|
+
type: string
|
|
4103
|
+
hasPendingChallenge:
|
|
4104
|
+
type: boolean
|
|
4105
|
+
guardianExternalUserId:
|
|
4106
|
+
type: string
|
|
4107
|
+
guardianDeliveryChatId:
|
|
4108
|
+
type: string
|
|
4109
|
+
guardianUsername:
|
|
4110
|
+
type: string
|
|
4111
|
+
guardianDisplayName:
|
|
4112
|
+
type: string
|
|
4113
|
+
verificationSessionId:
|
|
4114
|
+
type: string
|
|
4115
|
+
expiresAt:
|
|
4116
|
+
type: number
|
|
4117
|
+
nextResendAt:
|
|
4118
|
+
anyOf:
|
|
4119
|
+
- type: number
|
|
4120
|
+
- type: "null"
|
|
4121
|
+
sendCount:
|
|
4122
|
+
type: number
|
|
4123
|
+
pendingBootstrap:
|
|
4124
|
+
type: boolean
|
|
4125
|
+
required:
|
|
4126
|
+
- success
|
|
4127
|
+
- bound
|
|
4128
|
+
- channel
|
|
4129
|
+
- assistantId
|
|
4130
|
+
- hasPendingChallenge
|
|
4131
|
+
additionalProperties: false
|
|
4079
4132
|
/v1/channels/available:
|
|
4080
4133
|
get:
|
|
4081
4134
|
operationId: channels_available_get
|
|
@@ -4210,6 +4263,18 @@ paths:
|
|
|
4210
4263
|
- removed
|
|
4211
4264
|
emoji:
|
|
4212
4265
|
type: string
|
|
4266
|
+
emojiKind:
|
|
4267
|
+
type: string
|
|
4268
|
+
enum:
|
|
4269
|
+
- unicode
|
|
4270
|
+
- shortcode
|
|
4271
|
+
- custom
|
|
4272
|
+
emojiName:
|
|
4273
|
+
type: string
|
|
4274
|
+
emojiId:
|
|
4275
|
+
type: string
|
|
4276
|
+
emojiAnimated:
|
|
4277
|
+
type: boolean
|
|
4213
4278
|
targetMessageId:
|
|
4214
4279
|
type: string
|
|
4215
4280
|
required:
|
|
@@ -8136,6 +8201,54 @@ paths:
|
|
|
8136
8201
|
description: The assistant is currently responding
|
|
8137
8202
|
"422":
|
|
8138
8203
|
description: No user message exists to retry from
|
|
8204
|
+
/v1/conversations/{id}/sight-frame:
|
|
8205
|
+
post:
|
|
8206
|
+
operationId: conversations_by_id_sightframe_post
|
|
8207
|
+
summary: Persist an ambient camera frame
|
|
8208
|
+
description:
|
|
8209
|
+
Add an already-uploaded camera frame to a conversation as its own message, tagged so retention can age the
|
|
8210
|
+
image out of the model's context while the transcript keeps it. No reply is generated. Returns persisted=false
|
|
8211
|
+
when the frame was dropped, in which case the assistant owns the upload and there is nothing to clean up.
|
|
8212
|
+
tags:
|
|
8213
|
+
- conversations
|
|
8214
|
+
parameters:
|
|
8215
|
+
- name: id
|
|
8216
|
+
in: path
|
|
8217
|
+
required: true
|
|
8218
|
+
schema:
|
|
8219
|
+
type: string
|
|
8220
|
+
requestBody:
|
|
8221
|
+
required: true
|
|
8222
|
+
content:
|
|
8223
|
+
application/json:
|
|
8224
|
+
schema:
|
|
8225
|
+
type: object
|
|
8226
|
+
properties:
|
|
8227
|
+
attachmentId:
|
|
8228
|
+
type: string
|
|
8229
|
+
description: Id of the uploaded attachment holding the frame.
|
|
8230
|
+
required:
|
|
8231
|
+
- attachmentId
|
|
8232
|
+
responses:
|
|
8233
|
+
"200":
|
|
8234
|
+
description: Successful response
|
|
8235
|
+
content:
|
|
8236
|
+
application/json:
|
|
8237
|
+
schema:
|
|
8238
|
+
type: object
|
|
8239
|
+
properties:
|
|
8240
|
+
persisted:
|
|
8241
|
+
type: boolean
|
|
8242
|
+
messageId:
|
|
8243
|
+
description: The message the frame landed on, when one was written.
|
|
8244
|
+
type: string
|
|
8245
|
+
required:
|
|
8246
|
+
- persisted
|
|
8247
|
+
additionalProperties: false
|
|
8248
|
+
"400":
|
|
8249
|
+
description: Missing or empty attachmentId
|
|
8250
|
+
"404":
|
|
8251
|
+
description: Conversation not found
|
|
8139
8252
|
/v1/conversations/{id}/slash:
|
|
8140
8253
|
post:
|
|
8141
8254
|
operationId: conversations_by_id_slash_post
|
|
@@ -9865,7 +9978,11 @@ paths:
|
|
|
9865
9978
|
unassigned conversations, Chats) with total and unread counts and no conversation rows. Lets a client know which
|
|
9866
9979
|
sections exist, and what their badges say, without fetching any conversation list. Totals follow the standard
|
|
9867
9980
|
listing visibility; unread applies the same rules as GET /v1/conversations/unread-count scoped to the section.
|
|
9868
|
-
Chats is always present, even at zero: it is the leftover bucket and renders regardless.
|
|
9981
|
+
Chats is always present, even at zero: it is the leftover bucket and renders regardless. Under the
|
|
9982
|
+
`assistant-initiated-threads` flag an `assistant` section is also present at every count — the threads the
|
|
9983
|
+
assistant started on its own, selectable as a list via `groupId=system:assistant` — and its rows are withheld
|
|
9984
|
+
from Chats so the buckets stay disjoint. With the flag off no `assistant` row is emitted and those conversations
|
|
9985
|
+
are counted in Chats as before."
|
|
9869
9986
|
tags:
|
|
9870
9987
|
- conversations
|
|
9871
9988
|
responses:
|
|
@@ -9894,6 +10011,20 @@ paths:
|
|
|
9894
10011
|
- total
|
|
9895
10012
|
- unread
|
|
9896
10013
|
additionalProperties: false
|
|
10014
|
+
- type: object
|
|
10015
|
+
properties:
|
|
10016
|
+
kind:
|
|
10017
|
+
type: string
|
|
10018
|
+
const: assistant
|
|
10019
|
+
total:
|
|
10020
|
+
type: number
|
|
10021
|
+
unread:
|
|
10022
|
+
type: number
|
|
10023
|
+
required:
|
|
10024
|
+
- kind
|
|
10025
|
+
- total
|
|
10026
|
+
- unread
|
|
10027
|
+
additionalProperties: false
|
|
9897
10028
|
- type: object
|
|
9898
10029
|
properties:
|
|
9899
10030
|
kind:
|
|
@@ -10966,7 +11097,9 @@ paths:
|
|
|
10966
11097
|
description: Processed text output
|
|
10967
11098
|
mode:
|
|
10968
11099
|
type: string
|
|
10969
|
-
description:
|
|
11100
|
+
description:
|
|
11101
|
+
"Detected mode: dictation, command, action, or question (selected text the words asked about rather than
|
|
11102
|
+
changed; text is the transcription)"
|
|
10970
11103
|
actionPlan:
|
|
10971
11104
|
description: Action plan (only when mode is action)
|
|
10972
11105
|
type: string
|
|
@@ -20963,6 +21096,18 @@ paths:
|
|
|
20963
21096
|
properties:
|
|
20964
21097
|
emoji:
|
|
20965
21098
|
type: string
|
|
21099
|
+
emojiKind:
|
|
21100
|
+
type: string
|
|
21101
|
+
enum:
|
|
21102
|
+
- unicode
|
|
21103
|
+
- shortcode
|
|
21104
|
+
- custom
|
|
21105
|
+
emojiName:
|
|
21106
|
+
type: string
|
|
21107
|
+
emojiId:
|
|
21108
|
+
type: string
|
|
21109
|
+
emojiAnimated:
|
|
21110
|
+
type: boolean
|
|
20966
21111
|
op:
|
|
20967
21112
|
type: string
|
|
20968
21113
|
enum:
|
|
@@ -21032,6 +21177,18 @@ paths:
|
|
|
21032
21177
|
properties:
|
|
21033
21178
|
emoji:
|
|
21034
21179
|
type: string
|
|
21180
|
+
emojiKind:
|
|
21181
|
+
type: string
|
|
21182
|
+
enum:
|
|
21183
|
+
- unicode
|
|
21184
|
+
- shortcode
|
|
21185
|
+
- custom
|
|
21186
|
+
emojiName:
|
|
21187
|
+
type: string
|
|
21188
|
+
emojiId:
|
|
21189
|
+
type: string
|
|
21190
|
+
emojiAnimated:
|
|
21191
|
+
type: boolean
|
|
21035
21192
|
op:
|
|
21036
21193
|
type: string
|
|
21037
21194
|
enum:
|
|
@@ -21050,6 +21207,8 @@ paths:
|
|
|
21050
21207
|
- channelId
|
|
21051
21208
|
- channelTs
|
|
21052
21209
|
additionalProperties: false
|
|
21210
|
+
deletedAt:
|
|
21211
|
+
type: number
|
|
21053
21212
|
queueStatus:
|
|
21054
21213
|
type: string
|
|
21055
21214
|
enum:
|
|
@@ -24269,7 +24428,9 @@ paths:
|
|
|
24269
24428
|
post:
|
|
24270
24429
|
operationId: platform_connect_post
|
|
24271
24430
|
summary: Connect to the Vellum Platform
|
|
24272
|
-
description:
|
|
24431
|
+
description:
|
|
24432
|
+
Checks whether the stored platform credentials still connect. Reports a stored key the platform rejects as
|
|
24433
|
+
credentialRejected, so the caller can direct the user to sign in again and replace it.
|
|
24273
24434
|
tags:
|
|
24274
24435
|
- platform
|
|
24275
24436
|
responses:
|
|
@@ -24286,6 +24447,8 @@ paths:
|
|
|
24286
24447
|
type: string
|
|
24287
24448
|
showPlatformLogin:
|
|
24288
24449
|
type: boolean
|
|
24450
|
+
credentialRejected:
|
|
24451
|
+
type: boolean
|
|
24289
24452
|
additionalProperties: false
|
|
24290
24453
|
/v1/platform/credits:
|
|
24291
24454
|
get:
|
|
@@ -24654,6 +24817,32 @@ paths:
|
|
|
24654
24817
|
- package
|
|
24655
24818
|
- entitlements
|
|
24656
24819
|
additionalProperties: false
|
|
24820
|
+
/v1/platform/verify-credential:
|
|
24821
|
+
post:
|
|
24822
|
+
operationId: platform_verifycredential_post
|
|
24823
|
+
summary: Verify the Vellum-managed credential against the platform
|
|
24824
|
+
description:
|
|
24825
|
+
Asks the platform whether the stored assistant API key authenticates. POST because it performs a check; the
|
|
24826
|
+
result is returned, not stored.
|
|
24827
|
+
tags:
|
|
24828
|
+
- platform
|
|
24829
|
+
responses:
|
|
24830
|
+
"200":
|
|
24831
|
+
description: Successful response
|
|
24832
|
+
content:
|
|
24833
|
+
application/json:
|
|
24834
|
+
schema:
|
|
24835
|
+
type: object
|
|
24836
|
+
properties:
|
|
24837
|
+
status:
|
|
24838
|
+
type: string
|
|
24839
|
+
enum:
|
|
24840
|
+
- valid
|
|
24841
|
+
- rejected
|
|
24842
|
+
- unknown
|
|
24843
|
+
required:
|
|
24844
|
+
- status
|
|
24845
|
+
additionalProperties: false
|
|
24657
24846
|
/v1/playground/seed-conversation:
|
|
24658
24847
|
post:
|
|
24659
24848
|
operationId: playground_seedconversation_post
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vellumai/assistant",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.9-staging.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"remark-parse": "11.0.0",
|
|
75
75
|
"rrule": "2.8.1",
|
|
76
76
|
"semver": "7.8.0",
|
|
77
|
-
"sharp": "0.
|
|
77
|
+
"sharp": "0.35.4",
|
|
78
78
|
"stemmer": "2.0.1",
|
|
79
79
|
"tar-stream": "3.1.7",
|
|
80
80
|
"tldts": "7.0.25",
|
|
@@ -2,7 +2,8 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildAccessRequestCardView,
|
|
5
|
-
|
|
5
|
+
buildAccessRequestContextText,
|
|
6
|
+
buildAccessRequestReplyMechanics,
|
|
6
7
|
parseAccessRequestPayload,
|
|
7
8
|
} from "../notifications/access-request-copy.js";
|
|
8
9
|
|
|
@@ -111,10 +112,10 @@ describe("admitted-mode introduction nudge copy", () => {
|
|
|
111
112
|
senderIdentifier: "Alice",
|
|
112
113
|
sourceChannel: "telegram",
|
|
113
114
|
};
|
|
114
|
-
expect(
|
|
115
|
+
expect(buildAccessRequestContextText(base)).toContain(
|
|
115
116
|
"is requesting access to the assistant.",
|
|
116
117
|
);
|
|
117
|
-
const admitted =
|
|
118
|
+
const admitted = buildAccessRequestContextText({
|
|
118
119
|
...base,
|
|
119
120
|
trigger: "admitted",
|
|
120
121
|
});
|
|
@@ -122,8 +123,8 @@ describe("admitted-mode introduction nudge copy", () => {
|
|
|
122
123
|
expect(admitted).not.toContain("is requesting access");
|
|
123
124
|
});
|
|
124
125
|
|
|
125
|
-
test("admitted
|
|
126
|
-
const text =
|
|
126
|
+
test("admitted reply mechanics keep the decision directives", () => {
|
|
127
|
+
const text = buildAccessRequestReplyMechanics({
|
|
127
128
|
actorDisplayName: "Alice",
|
|
128
129
|
sourceChannel: "telegram",
|
|
129
130
|
requestCode: "ab12cd",
|
|
@@ -136,10 +136,13 @@ describe("buildAccessRequestSeedContentBlocks", () => {
|
|
|
136
136
|
);
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
test("text fallback block
|
|
139
|
+
test("text fallback block is the text-only rendering: context, invite directive, and the typed directive", () => {
|
|
140
140
|
const textBlock = textOf(buildAccessRequestSeedContentBlocks(basePayload));
|
|
141
141
|
expect(textBlock.text).toContain("requesting access to the assistant");
|
|
142
|
-
expect(textBlock.text).toContain("
|
|
142
|
+
expect(textBlock.text).toContain('Reply "open invite flow"');
|
|
143
|
+
// A client that cannot draw the card's buttons still gets the directive.
|
|
144
|
+
expect(textBlock.text).toContain('"ABC123 trust"');
|
|
145
|
+
expect(textBlock.text).toContain('"ABC123 block"');
|
|
143
146
|
});
|
|
144
147
|
|
|
145
148
|
test("body shows fallback when no preview/warnings/permalink", () => {
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Verifies
|
|
3
|
-
*
|
|
2
|
+
* Verifies that a persisted memory-v3 spotlight already in history is sent
|
|
3
|
+
* as-is and does not flag the turn-start message as volatile.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* message carries a memory-v3 `<memory_spotlight>` block, the one injected
|
|
8
|
-
* block that is strip-and-replaced on the tail every turn. Every other injected
|
|
9
|
-
* block is frozen into history and re-renders byte-identically, so turns
|
|
10
|
-
* without a spotlight keep a normal cache anchor even when memory-v3 is live.
|
|
11
|
-
*
|
|
12
|
-
* When no spotlight is present the field is omitted entirely (not `false`) so
|
|
13
|
-
* the wire stays byte-identical for conversations that never see one.
|
|
5
|
+
* Spotlight stays on the user message that was sent. The loop must not
|
|
6
|
+
* attach, strip, or mark that message mutable.
|
|
14
7
|
*/
|
|
15
8
|
|
|
16
9
|
import { describe, expect, test } from "bun:test";
|
|
@@ -25,17 +18,18 @@ import type {
|
|
|
25
18
|
ToolDefinition,
|
|
26
19
|
} from "../providers/types.js";
|
|
27
20
|
|
|
21
|
+
const spotlightText = wrapMemorySpotlightBlock("recalled: Alice's plan");
|
|
22
|
+
|
|
28
23
|
const userMessage: Message = {
|
|
29
24
|
role: "user",
|
|
30
25
|
content: [{ type: "text", text: "hi" }],
|
|
31
26
|
};
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
const spotlightUserMessage: Message = {
|
|
28
|
+
const userMessageWithSpotlight: Message = {
|
|
35
29
|
role: "user",
|
|
36
30
|
content: [
|
|
37
31
|
{ type: "text", text: "hi" },
|
|
38
|
-
{ type: "text", text:
|
|
32
|
+
{ type: "text", text: spotlightText },
|
|
39
33
|
],
|
|
40
34
|
};
|
|
41
35
|
|
|
@@ -64,22 +58,25 @@ function toolUseResponse(
|
|
|
64
58
|
function makeRecordingProvider(responses: ProviderResponse[]): {
|
|
65
59
|
provider: Provider;
|
|
66
60
|
configs: () => Array<Record<string, unknown> | undefined>;
|
|
61
|
+
sent: () => Message[][];
|
|
67
62
|
} {
|
|
68
63
|
const configs: Array<Record<string, unknown> | undefined> = [];
|
|
64
|
+
const sent: Message[][] = [];
|
|
69
65
|
let i = 0;
|
|
70
66
|
const provider: Provider = {
|
|
71
67
|
name: "mock",
|
|
72
68
|
async sendMessage(
|
|
73
|
-
|
|
69
|
+
messages: Message[],
|
|
74
70
|
options?: SendMessageOptions,
|
|
75
71
|
): Promise<ProviderResponse> {
|
|
72
|
+
sent.push(messages);
|
|
76
73
|
configs.push(options?.config as Record<string, unknown> | undefined);
|
|
77
74
|
const response = responses[i] ?? responses[responses.length - 1];
|
|
78
75
|
i++;
|
|
79
76
|
return response;
|
|
80
77
|
},
|
|
81
78
|
};
|
|
82
|
-
return { provider, configs: () => configs };
|
|
79
|
+
return { provider, configs: () => configs, sent: () => sent };
|
|
83
80
|
}
|
|
84
81
|
|
|
85
82
|
const echoTool: ToolDefinition = {
|
|
@@ -91,34 +88,11 @@ const echoTool: ToolDefinition = {
|
|
|
91
88
|
},
|
|
92
89
|
};
|
|
93
90
|
|
|
94
|
-
describe("AgentLoop.run:
|
|
95
|
-
test("
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
provider,
|
|
100
|
-
systemPrompt: "system",
|
|
101
|
-
conversationId: "test-conversation",
|
|
102
|
-
config: { maxTokens: 1024 },
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// WHEN the loop runs over a history whose tail carries the spotlight
|
|
106
|
-
await loop.run({
|
|
107
|
-
requestId: "test-request",
|
|
108
|
-
messages: [spotlightUserMessage],
|
|
109
|
-
onEvent: () => {},
|
|
110
|
-
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
111
|
-
callSite: "mainAgent",
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// THEN the send carries the cache-anchor signal
|
|
115
|
-
expect(configs()).toHaveLength(1);
|
|
116
|
-
expect(configs()[0]?.mutableLatestUserMessage).toBe(true);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test("omits mutableLatestUserMessage when the latest user message carries no spotlight", async () => {
|
|
120
|
-
// GIVEN a provider that records the config of each LLM call
|
|
121
|
-
const { provider, configs } = makeRecordingProvider([textResponse("hi")]);
|
|
91
|
+
describe("AgentLoop.run: persisted spotlight in history", () => {
|
|
92
|
+
test("sends a spotlight already in history and does not flag the turn-start as volatile", async () => {
|
|
93
|
+
const { provider, configs, sent } = makeRecordingProvider([
|
|
94
|
+
textResponse("done"),
|
|
95
|
+
]);
|
|
122
96
|
const loop = new AgentLoop({
|
|
123
97
|
provider,
|
|
124
98
|
systemPrompt: "system",
|
|
@@ -126,24 +100,26 @@ describe("AgentLoop.run: mutableLatestUserMessage from spotlight presence", () =
|
|
|
126
100
|
config: { maxTokens: 1024 },
|
|
127
101
|
});
|
|
128
102
|
|
|
129
|
-
|
|
130
|
-
// produces whenever it selects nothing to spotlight
|
|
131
|
-
await loop.run({
|
|
103
|
+
const result = await loop.run({
|
|
132
104
|
requestId: "test-request",
|
|
133
|
-
messages: [
|
|
105
|
+
messages: [userMessageWithSpotlight],
|
|
134
106
|
onEvent: () => {},
|
|
135
107
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
136
108
|
callSite: "mainAgent",
|
|
137
109
|
});
|
|
138
110
|
|
|
139
|
-
|
|
140
|
-
expect(
|
|
111
|
+
expect(sent()).toHaveLength(1);
|
|
112
|
+
expect(sent()[0]![0]!.content).toEqual(userMessageWithSpotlight.content);
|
|
113
|
+
expect(result.history[0]!.content).toEqual(
|
|
114
|
+
userMessageWithSpotlight.content,
|
|
115
|
+
);
|
|
141
116
|
expect("mutableLatestUserMessage" in (configs()[0] ?? {})).toBe(false);
|
|
142
117
|
});
|
|
143
118
|
|
|
144
|
-
test("
|
|
145
|
-
|
|
146
|
-
|
|
119
|
+
test("does not set mutableLatestUserMessage when history has no spotlight", async () => {
|
|
120
|
+
const { provider, sent, configs } = makeRecordingProvider([
|
|
121
|
+
textResponse("hi"),
|
|
122
|
+
]);
|
|
147
123
|
const loop = new AgentLoop({
|
|
148
124
|
provider,
|
|
149
125
|
systemPrompt: "system",
|
|
@@ -151,34 +127,20 @@ describe("AgentLoop.run: mutableLatestUserMessage from spotlight presence", () =
|
|
|
151
127
|
config: { maxTokens: 1024 },
|
|
152
128
|
});
|
|
153
129
|
|
|
154
|
-
// WHEN the loop runs
|
|
155
130
|
await loop.run({
|
|
156
131
|
requestId: "test-request",
|
|
157
|
-
messages: [
|
|
158
|
-
{
|
|
159
|
-
role: "user",
|
|
160
|
-
content: [
|
|
161
|
-
{
|
|
162
|
-
type: "text",
|
|
163
|
-
text: "<memory_spotlight>\nwhat does this tag do?",
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
},
|
|
167
|
-
],
|
|
132
|
+
messages: [userMessage],
|
|
168
133
|
onEvent: () => {},
|
|
169
134
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
170
135
|
callSite: "mainAgent",
|
|
171
136
|
});
|
|
172
137
|
|
|
173
|
-
|
|
174
|
-
// requirement the per-turn strip applies
|
|
175
|
-
expect(configs()).toHaveLength(1);
|
|
138
|
+
expect(sent()[0]).toEqual([userMessage]);
|
|
176
139
|
expect("mutableLatestUserMessage" in (configs()[0] ?? {})).toBe(false);
|
|
177
140
|
});
|
|
178
141
|
|
|
179
|
-
test("
|
|
180
|
-
|
|
181
|
-
const { provider, configs } = makeRecordingProvider([
|
|
142
|
+
test("keeps a persisted spotlight on the opening user message through a tool loop", async () => {
|
|
143
|
+
const { provider, sent, configs } = makeRecordingProvider([
|
|
182
144
|
toolUseResponse("t1", "echo", { value: "first" }),
|
|
183
145
|
textResponse("done"),
|
|
184
146
|
]);
|
|
@@ -191,22 +153,21 @@ describe("AgentLoop.run: mutableLatestUserMessage from spotlight presence", () =
|
|
|
191
153
|
toolExecutor: async () => ({ content: "ok", isError: false }),
|
|
192
154
|
});
|
|
193
155
|
|
|
194
|
-
|
|
195
|
-
await loop.run({
|
|
156
|
+
const result = await loop.run({
|
|
196
157
|
requestId: "test-request",
|
|
197
|
-
messages: [
|
|
158
|
+
messages: [userMessageWithSpotlight],
|
|
198
159
|
onEvent: () => {},
|
|
199
160
|
trust: { sourceChannel: "vellum", trustClass: "unknown" },
|
|
200
161
|
callSite: "mainAgent",
|
|
201
162
|
});
|
|
202
163
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
expect(configs()[0]
|
|
210
|
-
expect(configs()[1]
|
|
164
|
+
expect(sent()).toHaveLength(2);
|
|
165
|
+
expect(sent()[0]![0]!.content).toEqual(userMessageWithSpotlight.content);
|
|
166
|
+
expect(sent()[1]![0]!.content).toEqual(userMessageWithSpotlight.content);
|
|
167
|
+
expect(result.history[0]!.content).toEqual(
|
|
168
|
+
userMessageWithSpotlight.content,
|
|
169
|
+
);
|
|
170
|
+
expect("mutableLatestUserMessage" in (configs()[0] ?? {})).toBe(false);
|
|
171
|
+
expect("mutableLatestUserMessage" in (configs()[1] ?? {})).toBe(false);
|
|
211
172
|
});
|
|
212
173
|
});
|
|
@@ -26,7 +26,7 @@ afterAll(() => {
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
describe("always-loaded tool count", () => {
|
|
29
|
-
test("should be exactly
|
|
29
|
+
test("should be exactly 11 with recall occupying the existing slot", async () => {
|
|
30
30
|
await initializeTools();
|
|
31
31
|
const allDefs = getAllToolDefinitions();
|
|
32
32
|
|
|
@@ -47,6 +47,11 @@ describe("always-loaded tool count", () => {
|
|
|
47
47
|
// Host tools (host_bash, host_file_*) are excluded when no client is
|
|
48
48
|
// connected — without a human in the loop, the guardian auto-approve
|
|
49
49
|
// path would allow unchecked host command execution.
|
|
50
|
+
//
|
|
51
|
+
// `watch_retro_report` is here for the same reason the ui_surface tools are
|
|
52
|
+
// NOT: a watch retrospective runs clientless, so it can only report through
|
|
53
|
+
// a tool that survives this baseline. Its description and schema are kept
|
|
54
|
+
// deliberately terse because that is the cost of the slot.
|
|
50
55
|
const expectedNames = [
|
|
51
56
|
"bash",
|
|
52
57
|
"file_edit",
|
|
@@ -56,12 +61,13 @@ describe("always-loaded tool count", () => {
|
|
|
56
61
|
"remember",
|
|
57
62
|
"skill_execute",
|
|
58
63
|
"skill_load",
|
|
64
|
+
"watch_retro_report",
|
|
59
65
|
"web_fetch",
|
|
60
66
|
"web_search",
|
|
61
67
|
].sort();
|
|
62
68
|
|
|
63
69
|
expect(activeNames).toEqual(expectedNames);
|
|
64
70
|
expect(activeNames.filter((name) => name === "recall")).toHaveLength(1);
|
|
65
|
-
expect(activeTools.length).toBe(
|
|
71
|
+
expect(activeTools.length).toBe(11);
|
|
66
72
|
});
|
|
67
73
|
});
|