@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
|
@@ -16,7 +16,44 @@ Manage the user's contacts, relationship graph, access control (trusted contacts
|
|
|
16
16
|
|
|
17
17
|
## Contact Management
|
|
18
18
|
|
|
19
|
-
> **
|
|
19
|
+
> **Every contact write goes through the guardian.** You can list, search, and merge contacts on your own. To create, edit, or delete one, run the matching command below: each opens a form in the guardian's app, and the write happens only if they submit it. You are proposing, not writing. Say so: "I'll put that up for you to confirm," not "Done."
|
|
20
|
+
>
|
|
21
|
+
> Two things a contact record does **not** do: it grants no access (a record has no channels, so nobody can message the assistant through it), and it is not a channel. Use `assistant contacts prompt` to bind an address, or `assistant contacts invites create` to let someone bind their own.
|
|
22
|
+
>
|
|
23
|
+
> The form needs the guardian's desktop or web app to be open. If a command reports that it timed out, nobody answered: tell the user, and do not retry in a loop.
|
|
24
|
+
|
|
25
|
+
### Create a contact
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
assistant contacts create --name "Alice" --json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Opens an add-contact form prefilled with what you pass. The guardian can edit the name and notes before submitting, so treat the result as theirs, not yours: read the command's output rather than assuming the values you proposed were the ones written.
|
|
32
|
+
|
|
33
|
+
Optional flags:
|
|
34
|
+
|
|
35
|
+
- `--notes` -- proposed notes, prefilled into the form
|
|
36
|
+
- `--label` / `--description` -- what the form says about why you are asking
|
|
37
|
+
- `--timeout` -- how long the form stays open, in ms (default 300000)
|
|
38
|
+
|
|
39
|
+
Use this before creating an invite for someone who is not in the contact graph yet.
|
|
40
|
+
|
|
41
|
+
### Update a contact
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
assistant contacts update "<contact_id>" --name "Alice Chen" --json
|
|
45
|
+
assistant contacts update "<contact_id>" --notes "Moved to Berlin" --json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Opens an edit form showing the current name next to the proposed change. At least one of `--name` or `--notes` is required. This edits the record only. To revoke or block someone's access, use `assistant contacts channels update-status`.
|
|
49
|
+
|
|
50
|
+
### Delete a contact
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
assistant contacts delete "<contact_id>" --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Opens a confirmation showing the contact and its channels. Deleting a contact deletes its channels too, so anyone reaching the assistant through them loses access. A guardian contact cannot be deleted. When two records are the same person, merge them with the `contact_merge` tool instead: merging keeps the surviving contact's channels.
|
|
20
57
|
|
|
21
58
|
### Search contacts
|
|
22
59
|
|
|
@@ -97,12 +134,13 @@ The response contains `{ ok: true, contacts: [...] }` where each contact has:
|
|
|
97
134
|
|
|
98
135
|
### Allow a user (add trusted contact)
|
|
99
136
|
|
|
100
|
-
|
|
137
|
+
Access is granted per channel, not per contact, and it always takes proof that the person holds the address. Creating the contact record is only the first step.
|
|
101
138
|
|
|
102
|
-
1. **
|
|
103
|
-
2. **Invite link**
|
|
139
|
+
1. **Contact record** -- if they are not in the graph yet, `assistant contacts create --name "<name>"`. The guardian confirms it. This alone grants nothing.
|
|
140
|
+
2. **Invite link** -- `assistant contacts invites create --source-channel <channel> --contact-id <contact_id>`. The invitee redeems it from the address they actually control, which is what makes the channel trusted. This is the path to prefer: it works even when nobody knows the invitee's handle on that channel up front.
|
|
141
|
+
3. **Address the guardian already knows** -- `assistant contacts prompt --channel <channel>` opens a form for them to type it in. The channel lands unverified unless the guardian checks the verify box on that form, and an unverified channel cannot message the assistant.
|
|
104
142
|
|
|
105
|
-
|
|
143
|
+
Only the guardian's own submission can complete any of these, so never promise access is live until the command returns.
|
|
106
144
|
|
|
107
145
|
### Revoke a user (remove access)
|
|
108
146
|
|
|
@@ -132,12 +170,11 @@ assistant contacts channels update-status <channel_id> --status blocked --reason
|
|
|
132
170
|
|
|
133
171
|
Replace `<channel_id>` with the channel's `id` from the contact's `channels` array (visible in `assistant contacts list --json` output).
|
|
134
172
|
|
|
135
|
-
|
|
136
173
|
## Invite Links
|
|
137
174
|
|
|
138
|
-
Invite links let the guardian share a link or code that automatically grants access when used. Telegram invites use a deep link; voice invites use a phone number + numeric code; email, WhatsApp, and
|
|
175
|
+
Invite links let the guardian share a link or code that automatically grants access when used. Telegram invites use a deep link; voice invites use a phone number + numeric code; email, WhatsApp, Slack, and Discord invites use a 6-digit code that the invitee sends to the assistant on the respective channel. Discord invitees must share a server with the bot and have DMs from server members enabled before they can send it the code.
|
|
139
176
|
|
|
140
|
-
**Every invite must be bound to a contact.** Before creating an invite, look up the contact with `assistant contacts list` and pass the contact's `id` via the required `--contact-id` flag.
|
|
177
|
+
**Every invite must be bound to a contact.** Before creating an invite, look up the contact with `assistant contacts list` and pass the contact's `id` via the required `--contact-id` flag. If the target contact doesn't exist yet, create it first with `assistant contacts create --name "<name>"` and wait for the guardian to confirm; the invite needs only a name, never the invitee's address on that channel.
|
|
141
178
|
|
|
142
179
|
### Create a Telegram invite link
|
|
143
180
|
|
|
@@ -184,7 +221,7 @@ echo "$INVITE_URL"
|
|
|
184
221
|
Required flags:
|
|
185
222
|
|
|
186
223
|
- `--source-channel` -- must be `telegram`
|
|
187
|
-
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list
|
|
224
|
+
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list`, or create one with `assistant contacts create` if they are not in the graph yet.
|
|
188
225
|
|
|
189
226
|
Optional flags:
|
|
190
227
|
|
|
@@ -224,7 +261,7 @@ assistant contacts invites create --source-channel phone --contact-id "<contact_
|
|
|
224
261
|
Required flags:
|
|
225
262
|
|
|
226
263
|
- `--source-channel` -- must be `phone`
|
|
227
|
-
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list
|
|
264
|
+
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list`, or create one with `assistant contacts create` if they are not in the graph yet. The contact's `displayName` is used to personalize the voice greeting; the guardian label is resolved at runtime.
|
|
228
265
|
- `--expected-external-user-id` -- the invitee's phone number in E.164 format (e.g., `+15551234567`)
|
|
229
266
|
|
|
230
267
|
Optional flags:
|
|
@@ -267,7 +304,7 @@ assistant contacts invites create --source-channel email --contact-id "<contact_
|
|
|
267
304
|
Required flags:
|
|
268
305
|
|
|
269
306
|
- `--source-channel` -- must be `email`
|
|
270
|
-
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list
|
|
307
|
+
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list`, or create one with `assistant contacts create` if they are not in the graph yet.
|
|
271
308
|
|
|
272
309
|
The response contains `{ ok: true, invite: { id, token, inviteCode, guardianInstruction, channelHandle, ... } }`.
|
|
273
310
|
|
|
@@ -298,7 +335,7 @@ assistant contacts invites create --source-channel whatsapp --contact-id "<conta
|
|
|
298
335
|
Required flags:
|
|
299
336
|
|
|
300
337
|
- `--source-channel` -- must be `whatsapp`
|
|
301
|
-
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list
|
|
338
|
+
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list`, or create one with `assistant contacts create` if they are not in the graph yet.
|
|
302
339
|
|
|
303
340
|
The response contains `{ ok: true, invite: { id, token, inviteCode, guardianInstruction, channelHandle?, ... } }`.
|
|
304
341
|
|
|
@@ -331,7 +368,7 @@ assistant contacts invites create --source-channel slack --contact-id "<contact_
|
|
|
331
368
|
Required flags:
|
|
332
369
|
|
|
333
370
|
- `--source-channel` -- must be `slack`
|
|
334
|
-
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list
|
|
371
|
+
- `--contact-id` -- the ID of the contact this invite is for. Look up the contact first with `assistant contacts list`, or create one with `assistant contacts create` if they are not in the graph yet.
|
|
335
372
|
|
|
336
373
|
The response follows the same shape as email and WhatsApp invites (`inviteCode`, `guardianInstruction`, `channelHandle`).
|
|
337
374
|
|
|
@@ -460,7 +497,13 @@ Each channel has:
|
|
|
460
497
|
|
|
461
498
|
**"Who can message me?"** -- List all contacts with `assistant contacts list --json`, present active channels as a formatted list.
|
|
462
499
|
|
|
463
|
-
**"Add
|
|
500
|
+
**"Add Alice as a contact"** / **"Remember Bob's my dentist"** -- Search first with `assistant contacts list --query "<name>"` so you update an existing record instead of creating a duplicate. Then `assistant contacts create --name "<name>" --notes "<what they told you>"`, or `assistant contacts update <contact_id>` if they are already there. Tell the user the form is waiting for them, and report what the command returns rather than what you proposed.
|
|
501
|
+
|
|
502
|
+
**"Rename [name]"** / **"Update [name]'s notes"** -- Find the contact with `assistant contacts list --json`, then `assistant contacts update <contact_id> --name ... --notes ...`.
|
|
503
|
+
|
|
504
|
+
**"Delete [name]"** / **"Remove [name] from my contacts"** -- Find the contact, then `assistant contacts delete <contact_id>`. Mention that this drops their channels too. If the user actually means two records are the same person, merge instead with the `contact_merge` tool.
|
|
505
|
+
|
|
506
|
+
**"Add my friend to Telegram"** -- Create the contact with `assistant contacts create --name "<their name>"` and wait for the guardian to confirm the form. Then create an invite with `assistant contacts invites create --source-channel telegram --contact-id <contact_id>` and present the deep link. You never need their Telegram user ID: redeeming the invite is what binds their account.
|
|
464
507
|
|
|
465
508
|
**"Remove [name]'s access"** -- List contacts with `assistant contacts list --json` to find them, identify the channel to revoke, confirm the revocation, then run `assistant contacts channels update-status <channel_id> --status revoked --json`.
|
|
466
509
|
|
|
@@ -468,13 +511,13 @@ Each channel has:
|
|
|
468
511
|
|
|
469
512
|
**"Show me blocked contacts"** -- List contacts with `assistant contacts list --json` and filter for channels with `status: "blocked"`.
|
|
470
513
|
|
|
471
|
-
**"Create a Telegram invite link"** / **"Invite someone on Telegram"** -- Look up or create the
|
|
514
|
+
**"Create a Telegram invite link"** / **"Invite someone on Telegram"** -- Look up the contact, or create it with `assistant contacts create` and wait for the guardian to confirm, then create an invite with `assistant contacts invites create --source-channel telegram --contact-id <contact_id>`, look up the bot username, build the deep link, and present it with sharing instructions.
|
|
472
515
|
|
|
473
|
-
**"Invite someone by email"** / **"Send an email invite"** -- Look up or create the
|
|
516
|
+
**"Invite someone by email"** / **"Send an email invite"** -- Look up the contact, or create it with `assistant contacts create` and wait for the guardian to confirm, then create an invite with `assistant contacts invites create --source-channel email --contact-id <contact_id>`. Present the 6-digit invite code and the assistant's email address. Tell the guardian to share both with the invitee.
|
|
474
517
|
|
|
475
|
-
**"Invite someone on WhatsApp"** -- Look up or create the
|
|
518
|
+
**"Invite someone on WhatsApp"** -- Look up the contact, or create it with `assistant contacts create` and wait for the guardian to confirm, then create an invite with `assistant contacts invites create --source-channel whatsapp --contact-id <contact_id>`. Present the 6-digit invite code. If `channelHandle` is returned, also present the assistant's WhatsApp number; otherwise, tell the guardian to share the code and instruct the invitee to send it to the assistant on WhatsApp.
|
|
476
519
|
|
|
477
|
-
**"Invite someone on Slack"** -- Look up or create the
|
|
520
|
+
**"Invite someone on Slack"** -- Look up the contact, or create it with `assistant contacts create` and wait for the guardian to confirm, then create an invite with `assistant contacts invites create --source-channel slack --contact-id <contact_id>`. Present the 6-digit invite code and tell the guardian to have the invitee DM the code to the assistant's Slack bot.
|
|
478
521
|
|
|
479
522
|
**"Show my invites"** / **"List active invite links"** -- List invites with `assistant contacts invites list --source-channel telegram --json`, present active invites with uses remaining and expiration info. Use the appropriate `--source-channel` value for other channels.
|
|
480
523
|
|
|
@@ -86,7 +86,7 @@ type ProfileImpls = Record<DefaultProfileKey, DefaultProfileTemplate>;
|
|
|
86
86
|
*/
|
|
87
87
|
const VELLUM_PROFILE_IMPLS: ProfileImpls = {
|
|
88
88
|
balanced: {
|
|
89
|
-
model: "accounts/fireworks/models/glm-
|
|
89
|
+
model: "accounts/fireworks/models/glm-5p3-flash",
|
|
90
90
|
provider: "vellum",
|
|
91
91
|
source: "managed",
|
|
92
92
|
label: "Balanced",
|
|
@@ -241,25 +241,26 @@ const BACKUP_PROFILE_IMPLS: Record<BackupProfileKey, DefaultProfileTemplate> = {
|
|
|
241
241
|
};
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
|
-
* Arm to managed model pin for the `experiment-balanced-model-2026-08-
|
|
244
|
+
* Arm to managed model pin for the `experiment-balanced-model-2026-08-31` A/B
|
|
245
245
|
* test (`balanced-model-experiment.ts` owns the flag read). An arm repoints
|
|
246
246
|
* the model of the managed (`vellum`) implementation of `balanced` and nothing
|
|
247
247
|
* else: effort, thinking, token budget, label and description all stay on the
|
|
248
248
|
* shipped body, and the `chatgpt` and BYOK columns are untouched because those
|
|
249
249
|
* installs run the provider their user chose and sit outside the experiment.
|
|
250
250
|
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
* `
|
|
251
|
+
* An arm this build does not know, and an unset flag, both resolve to the
|
|
252
|
+
* shipped body, so no LaunchDarkly value can strand an install on a model that
|
|
253
|
+
* is not pinned here. A `Map` rather than an object literal keeps that true for
|
|
254
|
+
* every string LaunchDarkly can send: the arm is remote input, and an object
|
|
255
|
+
* lookup would resolve `constructor` or `toString` to an inherited
|
|
256
|
+
* `Object.prototype` member instead of missing.
|
|
257
257
|
*
|
|
258
|
-
* `glm-
|
|
259
|
-
* the arm keeps its meaning if the shipped pin moves again.
|
|
258
|
+
* `glm-5p3-flash` names the same model as the shipped pin and stays in the
|
|
259
|
+
* table so the arm keeps its meaning if the shipped pin moves again.
|
|
260
260
|
*/
|
|
261
261
|
const BALANCED_EXPERIMENT_MODELS = new Map<string, string>([
|
|
262
|
-
["
|
|
262
|
+
["glm-5p3-flash", "accounts/fireworks/models/glm-5p3-flash"],
|
|
263
|
+
["glm-5p3", "accounts/fireworks/models/glm-5p3"],
|
|
263
264
|
["glm-5p2", "accounts/fireworks/models/glm-5p2"],
|
|
264
265
|
]);
|
|
265
266
|
|
|
@@ -27,6 +27,15 @@
|
|
|
27
27
|
"defaultEnabled": "off",
|
|
28
28
|
"values": ["off", "on"]
|
|
29
29
|
},
|
|
30
|
+
{
|
|
31
|
+
"id": "vision-mode",
|
|
32
|
+
"scope": "client",
|
|
33
|
+
"key": "vision-mode",
|
|
34
|
+
"label": "Vision Mode",
|
|
35
|
+
"description": "Gates the Eyes camera surface in the web composer: the toggle, the floating viewfinder tile, and the send-frame path are all reachable only through the toggle. String-valued so future A/B arms can be added as new values.",
|
|
36
|
+
"defaultEnabled": "off",
|
|
37
|
+
"values": ["off", "on"]
|
|
38
|
+
},
|
|
30
39
|
{
|
|
31
40
|
"id": "experiment-activation-flow-2026-06-03",
|
|
32
41
|
"scope": "both",
|
|
@@ -373,21 +382,13 @@
|
|
|
373
382
|
"defaultEnabled": true
|
|
374
383
|
},
|
|
375
384
|
{
|
|
376
|
-
"id": "experiment-balanced-model-2026-08-
|
|
385
|
+
"id": "experiment-balanced-model-2026-08-31",
|
|
377
386
|
"scope": "assistant",
|
|
378
|
-
"key": "experiment-balanced-model-2026-08-
|
|
387
|
+
"key": "experiment-balanced-model-2026-08-31",
|
|
379
388
|
"label": "Experiment: Balanced Profile Model",
|
|
380
|
-
"description": "Multivariate experiment on the model the managed Balanced inference profile resolves to.
|
|
381
|
-
"defaultEnabled": "
|
|
382
|
-
"values": ["
|
|
383
|
-
},
|
|
384
|
-
{
|
|
385
|
-
"id": "obscure-credits",
|
|
386
|
-
"scope": "client",
|
|
387
|
-
"key": "obscure-credits",
|
|
388
|
-
"label": "Obscure Credits",
|
|
389
|
-
"description": "Obscures raw credit dollar amounts across the web billing surfaces in favor of a usage-relative view. The Plan section's current-plan tile trades its price footer for a Usage Balance bar and its credits spec chip reads \"<Package> usage, reset monthly\"; the plans takeover, custom-plan modal, and Pro provisioning takeover swap dollar credit wording for the catalog's usage labels; the Credits balance tile and the chat preferences menu show only credit bought or earned beyond the plan's included grants. Chat low-balance and daily-limit banners still name credits. Off leaves every surface exactly as it ships today.",
|
|
390
|
-
"defaultEnabled": false
|
|
389
|
+
"description": "Multivariate experiment on the model the managed Balanced inference profile resolves to. glm-5p3-flash = the shipped pin (accounts/fireworks/models/glm-5p3-flash); glm-5p3 = accounts/fireworks/models/glm-5p3; glm-5p2 = accounts/fireworks/models/glm-5p2. Replaces experiment-balanced-model-2026-08-06, which ended on 2026-08-31: the activation cohort keys a user on their first-ever assignment per flag, so a new arm on the old key could never enrol a user the old test already stamped. Only the managed (vellum) implementation moves: ChatGPT-subscription and BYOK installs run the provider the user chose and are outside the experiment. Rollout and targeting are managed in the LaunchDarkly dashboard; any value that is not an arm name resolves to the shipped pin.",
|
|
390
|
+
"defaultEnabled": "glm-5p3-flash",
|
|
391
|
+
"values": ["glm-5p3-flash", "glm-5p3", "glm-5p2"]
|
|
391
392
|
},
|
|
392
393
|
{
|
|
393
394
|
"id": "ios-avatar-app-icon",
|
|
@@ -420,6 +421,14 @@
|
|
|
420
421
|
"label": "ChatGPT Device Code Login",
|
|
421
422
|
"description": "Gates the device-code sign-in as the primary ChatGPT subscription connect flow in the web client. Off: the redirect-and-paste flow is the only flow the connect section shows, with no device code UI and no other-sign-in-options disclosure. On: device code leads, and the redirect-and-paste flow stays reachable behind that disclosure and takes the section over when the assistant has no device-auth route.",
|
|
422
423
|
"defaultEnabled": false
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
"id": "model-first-profile-create",
|
|
427
|
+
"scope": "client",
|
|
428
|
+
"key": "model-first-profile-create",
|
|
429
|
+
"label": "Model-First Profile Create",
|
|
430
|
+
"description": "Reverses the two questions the web client's New Model modal asks when creating an inference profile. Off: the modal asks for a provider first and then offers that provider's models. On: it opens on one searchable list of every catalog model the assistant can reach, deduplicated across providers, and only then asks which provider serves the chosen model. That second question is skipped when a single provider serves it, answered with radio cards when several do, and turned into an inline connect form (API key, setup, or ChatGPT sign-in) when the chosen route has no connection yet. Editing an existing profile is unchanged either way, and both flows persist the same profile shape.",
|
|
431
|
+
"defaultEnabled": false
|
|
423
432
|
}
|
|
424
433
|
]
|
|
425
434
|
}
|
package/src/config/schema.ts
CHANGED
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
import { PluginUpdatesConfigSchema } from "./schemas/plugin-updates.js";
|
|
55
55
|
import { SecretDetectionConfigSchema } from "./schemas/security.js";
|
|
56
56
|
import { ServicesSchema } from "./schemas/services.js";
|
|
57
|
+
import { SightConfigSchema } from "./schemas/sight.js";
|
|
57
58
|
import { SkillsConfigSchema } from "./schemas/skills.js";
|
|
58
59
|
import {
|
|
59
60
|
RateLimitConfigSchema,
|
|
@@ -118,6 +119,7 @@ export const AssistantConfigSchema = z.object({
|
|
|
118
119
|
twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
|
|
119
120
|
calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
|
|
120
121
|
liveVoice: LiveVoiceConfigSchema.default(LiveVoiceConfigSchema.parse({})),
|
|
122
|
+
sight: SightConfigSchema.default(SightConfigSchema.parse({})),
|
|
121
123
|
whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
|
|
122
124
|
telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
|
|
123
125
|
slack: SlackConfigSchema.default(SlackConfigSchema.parse({})),
|
|
@@ -40,6 +40,7 @@ describe("LiveVoiceVadConfigSchema", () => {
|
|
|
40
40
|
const parsed = LiveVoiceVadConfigSchema.parse({});
|
|
41
41
|
expect(parsed).toEqual({
|
|
42
42
|
speechEnergyThreshold: 800,
|
|
43
|
+
noiseFloorMargin: 3,
|
|
43
44
|
silenceThresholdMs: 1200,
|
|
44
45
|
maxTurnDurationMs: 30_000,
|
|
45
46
|
bargeInMinSpeechMs: 250,
|
|
@@ -62,6 +63,17 @@ describe("LiveVoiceVadConfigSchema", () => {
|
|
|
62
63
|
expect(parsed.bargeInMinSpeechMs).toBe(120);
|
|
63
64
|
});
|
|
64
65
|
|
|
66
|
+
test("accepts a noiseFloorMargin of 0 (adaptation disabled)", () => {
|
|
67
|
+
const parsed = LiveVoiceVadConfigSchema.parse({ noiseFloorMargin: 0 });
|
|
68
|
+
expect(parsed.noiseFloorMargin).toBe(0);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("rejects a negative noiseFloorMargin", () => {
|
|
72
|
+
expect(() =>
|
|
73
|
+
LiveVoiceVadConfigSchema.parse({ noiseFloorMargin: -1 }),
|
|
74
|
+
).toThrow();
|
|
75
|
+
});
|
|
76
|
+
|
|
65
77
|
test("accepts a bargeInMinSpeechMs of 0 (guard disabled)", () => {
|
|
66
78
|
const parsed = LiveVoiceVadConfigSchema.parse({ bargeInMinSpeechMs: 0 });
|
|
67
79
|
expect(parsed.bargeInMinSpeechMs).toBe(0);
|
|
@@ -317,6 +329,7 @@ describe("LiveVoiceConfigSchema", () => {
|
|
|
317
329
|
mode: "open-mic",
|
|
318
330
|
vad: {
|
|
319
331
|
speechEnergyThreshold: 800,
|
|
332
|
+
noiseFloorMargin: 3,
|
|
320
333
|
silenceThresholdMs: 1200,
|
|
321
334
|
maxTurnDurationMs: 30_000,
|
|
322
335
|
bargeInMinSpeechMs: 250,
|
|
@@ -16,6 +16,13 @@ export const LiveVoiceVadConfigSchema = z
|
|
|
16
16
|
.describe(
|
|
17
17
|
"Mean absolute amplitude (16-bit linear scale) above which a frame counts as speech — mirrors DEFAULT_SPEECH_ENERGY_THRESHOLD in stt/speech-energy.ts",
|
|
18
18
|
),
|
|
19
|
+
noiseFloorMargin: z
|
|
20
|
+
.number({ error: "liveVoice.vad.noiseFloorMargin must be a number" })
|
|
21
|
+
.nonnegative("liveVoice.vad.noiseFloorMargin must be nonnegative")
|
|
22
|
+
.default(3)
|
|
23
|
+
.describe(
|
|
24
|
+
"Multiple of the room's measured background noise level that the speech gate is raised to, so a noisy room does not read as continuous speech. The gate never falls below speechEnergyThreshold and never exceeds 4x it. 0 disables the adaptation and pins the gate to speechEnergyThreshold.",
|
|
25
|
+
),
|
|
19
26
|
silenceThresholdMs: z
|
|
20
27
|
.number({ error: "liveVoice.vad.silenceThresholdMs must be a number" })
|
|
21
28
|
.int("liveVoice.vad.silenceThresholdMs must be an integer")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How many camera frames stay in the model's context as real images, counted
|
|
5
|
+
* newest-first across the whole conversation so the frames from the last few
|
|
6
|
+
* moments are the ones that survive. Older frames become timestamped text
|
|
7
|
+
* stubs (`daemon/conversation-sight-frames.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Smaller than `RETRY_KEEP_LATEST_MEDIA_BLOCKS` (3, in
|
|
10
|
+
* `daemon/conversation-media-retry.ts`) because the two budgets answer
|
|
11
|
+
* different questions. That one is reactive and spends a rejected request's
|
|
12
|
+
* remaining room across every kind of media, including files the user
|
|
13
|
+
* deliberately sent. This one is proactive, applied to every assembly, and
|
|
14
|
+
* governs only frames the camera sampled by itself: background the model
|
|
15
|
+
* glances at, not something anyone chose to attach.
|
|
16
|
+
*/
|
|
17
|
+
export const KEEP_LATEST_SIGHT_FRAMES = 2;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Floor for `sight.keepLatestFrames`. A call whose camera is up keeps at least
|
|
21
|
+
* the current view live; stubbing every frame would leave the model reading
|
|
22
|
+
* timestamps about pictures it can no longer see.
|
|
23
|
+
*/
|
|
24
|
+
export const MIN_SIGHT_KEEP_LATEST_FRAMES = 1;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Ceiling for `sight.keepLatestFrames`. History resends every inline image on
|
|
28
|
+
* every later request, so the ceiling is what stops a long call from growing
|
|
29
|
+
* its own context until the provider rejects it.
|
|
30
|
+
*/
|
|
31
|
+
export const MAX_SIGHT_KEEP_LATEST_FRAMES = 6;
|
|
32
|
+
|
|
33
|
+
export const SightConfigSchema = z
|
|
34
|
+
.object({
|
|
35
|
+
keepLatestFrames: z
|
|
36
|
+
.number({ error: "sight.keepLatestFrames must be a number" })
|
|
37
|
+
.int("sight.keepLatestFrames must be an integer")
|
|
38
|
+
.default(KEEP_LATEST_SIGHT_FRAMES)
|
|
39
|
+
.describe(
|
|
40
|
+
`How many of the newest camera frames a live-voice call keeps in the model's context as images; older frames become timestamped text stubs. Clamped to ${MIN_SIGHT_KEEP_LATEST_FRAMES}..${MAX_SIGHT_KEEP_LATEST_FRAMES} when read.`,
|
|
41
|
+
),
|
|
42
|
+
})
|
|
43
|
+
.describe("Ambient camera frames sampled during a live-voice call");
|
|
44
|
+
|
|
45
|
+
export type SightConfig = z.infer<typeof SightConfigSchema>;
|
package/src/config/skills.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
import { parseToolManifestFile } from "../skills/tool-manifest.js";
|
|
33
33
|
import { computeSkillVersionHash } from "../skills/version-hash.js";
|
|
34
34
|
import type { OwnerInfo } from "../tools/types.js";
|
|
35
|
+
import { isBunVirtualPath } from "../util/bundled-asset.js";
|
|
35
36
|
import { getLogger } from "../util/logger.js";
|
|
36
37
|
import {
|
|
37
38
|
getWorkspaceDirDisplay,
|
|
@@ -230,7 +231,7 @@ export function getBundledSkillsDir(): string {
|
|
|
230
231
|
// In compiled Bun binaries, import.meta.dir points into the virtual
|
|
231
232
|
// /$bunfs/ filesystem where non-JS assets don't exist. Fall back to
|
|
232
233
|
// the macOS .app bundle Resources dir or next to the binary.
|
|
233
|
-
if (dir
|
|
234
|
+
if (isBunVirtualPath(dir)) {
|
|
234
235
|
const execDir = dirname(process.execPath);
|
|
235
236
|
// macOS .app bundle: binary is in Contents/MacOS/, resources in Contents/Resources/
|
|
236
237
|
const resourcesPath = join(execDir, "..", "Resources", "bundled-skills");
|