@vellumai/assistant 0.12.1 → 0.12.2-dev.202609162314.7778bc8
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/.env.example +2 -0
- package/AGENTS.md +5 -1
- package/ARCHITECTURE.md +20 -21
- package/Dockerfile +7 -7
- package/docs/architecture/integrations.md +7 -0
- package/docs/architecture/memory.md +11 -2
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/credential-execution-service.md +1 -1
- package/docs/desktop-browser-cli.md +35 -0
- package/docs/guardian-request-flow.md +16 -0
- package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
- package/node_modules/@vellumai/environments/src/shell.ts +24 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
- package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
- package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
- package/openapi.yaml +579 -111
- package/package.json +7 -4
- package/scripts/bundled-plugin-packages.ts +154 -0
- package/scripts/generate-bundled-plugin-packages.ts +29 -0
- package/scripts/postinstall.ts +33 -0
- package/scripts/smoke-desktop-browser-cli.ts +280 -0
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/scripts/sync-llm-catalog.ts +3 -0
- package/scripts/test.ts +15 -13
- package/scripts/voice-ttft-spike.ts +2 -2
- package/src/__tests__/agent-loop.test.ts +259 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- package/src/__tests__/anthropic-provider.test.ts +55 -63
- package/src/__tests__/app-compiler.test.ts +6 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
- package/src/__tests__/app-dir-path-guard.test.ts +1 -3
- package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
- package/src/__tests__/assistant-event-hub.test.ts +44 -0
- package/src/__tests__/attachments-store.test.ts +22 -3
- package/src/__tests__/channel-approval.test.ts +9 -14
- package/src/__tests__/channel-reply-delivery.test.ts +56 -0
- package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
- package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
- package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
- package/src/__tests__/computer-use-tools.test.ts +19 -7
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +29 -30
- package/src/__tests__/config-sounds-sync.test.ts +23 -0
- package/src/__tests__/config-watcher.test.ts +23 -8
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop.test.ts +257 -6
- package/src/__tests__/conversation-attachments.test.ts +106 -0
- package/src/__tests__/conversation-error.test.ts +4 -1
- package/src/__tests__/conversation-fork-crud.test.ts +191 -0
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +26 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
- package/src/__tests__/conversation-queue.test.ts +48 -207
- package/src/__tests__/conversation-retry-discard.test.ts +54 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +33 -3
- package/src/__tests__/conversation-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
- package/src/__tests__/conversation-title-service.test.ts +14 -10
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
- package/src/__tests__/credential-execution-client.test.ts +70 -53
- package/src/__tests__/credential-record-retire.test.ts +171 -1
- package/src/__tests__/credential-routes.test.ts +250 -3
- package/src/__tests__/credential-security-invariants.test.ts +5 -3
- package/src/__tests__/cu-unified-flow.test.ts +14 -4
- package/src/__tests__/db-conversation-tool-surface.test.ts +144 -0
- package/src/__tests__/document-sync-tags.test.ts +25 -0
- package/src/__tests__/drain-kick-guard.test.ts +0 -2
- package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
- package/src/__tests__/events-tail-route.test.ts +33 -0
- package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/external-plugin-loader.test.ts +52 -0
- package/src/__tests__/git-porcelain.test.ts +47 -0
- package/src/__tests__/headless-browser-mode.test.ts +48 -0
- package/src/__tests__/heartbeat-service.test.ts +56 -40
- package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
- package/src/__tests__/history-repair.test.ts +53 -0
- package/src/__tests__/host-bash-proxy.test.ts +26 -45
- package/src/__tests__/host-browser-proxy.test.ts +6 -17
- package/src/__tests__/host-cu-proxy.test.ts +712 -18
- package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
- package/src/__tests__/host-file-proxy.test.ts +11 -23
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
- package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
- package/src/__tests__/list-all-apps.test.ts +40 -8
- package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
- package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
- package/src/__tests__/llm-catalog-parity.test.ts +51 -3
- package/src/__tests__/managed-store.test.ts +121 -0
- package/src/__tests__/mcp-auth-routes.test.ts +104 -8
- package/src/__tests__/mcp-client-auth.test.ts +54 -0
- package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
- package/src/__tests__/mcp-health-check.test.ts +40 -43
- package/src/__tests__/mcp-list-plugin-servers.test.ts +85 -42
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +4 -2
- package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
- package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
- package/src/__tests__/messaging-send-tool.test.ts +355 -548
- package/src/__tests__/model-intents.test.ts +3 -0
- package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
- package/src/__tests__/oauth-apps-routes.test.ts +1 -0
- package/src/__tests__/oauth-commands-routes.test.ts +282 -101
- package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +23 -0
- package/src/__tests__/oauth-providers-routes.test.ts +3 -0
- package/src/__tests__/openai-provider.test.ts +1 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- package/src/__tests__/persist-media-references.test.ts +50 -0
- package/src/__tests__/platform-callback-registration.test.ts +8 -16
- package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +13 -0
- package/src/__tests__/qdrant-manager.test.ts +132 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +317 -6
- package/src/__tests__/schedule-routes.test.ts +20 -0
- package/src/__tests__/scheduler-result-notification.test.ts +23 -4
- package/src/__tests__/script-proxy-certs.test.ts +35 -0
- package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
- package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
- package/src/__tests__/secret-routes-scrub.test.ts +22 -27
- package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
- package/src/__tests__/secure-keys.test.ts +7 -3
- package/src/__tests__/server-tool-pairing.test.ts +107 -0
- package/src/__tests__/service-account-token.test.ts +247 -0
- package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skills.test.ts +20 -4
- package/src/__tests__/source-fingerprint.test.ts +184 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +239 -3
- package/src/__tests__/subagent-tools.test.ts +3 -2
- package/src/__tests__/telephony-tts-guard.test.ts +38 -3
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/tool-result-follow-up.test.ts +99 -0
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +63 -0
- package/src/__tests__/ui-channel-variants.test.ts +1 -56
- package/src/__tests__/unicode.test.ts +49 -0
- package/src/__tests__/user-plugin-loader.test.ts +21 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
- package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
- package/src/__tests__/workspace-git-service.test.ts +26 -0
- package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
- package/src/acp/__tests__/acp-credentials.test.ts +13 -0
- package/src/acp/__tests__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -0
- package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
- package/src/acp/__tests__/client-handler.test.ts +90 -2
- package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
- package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
- package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
- package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
- package/src/acp/__tests__/session-manager.test.ts +895 -4
- package/src/acp/acp-claude-oauth.ts +328 -14
- package/src/acp/acp-credentials.ts +19 -0
- package/src/acp/agent-process.test.ts +4 -1
- package/src/acp/agent-process.ts +96 -10
- package/src/acp/auth-required.ts +50 -1
- package/src/acp/auto-install.test.ts +9 -7
- package/src/acp/claude-token-refresh.ts +150 -0
- package/src/acp/client-handler.ts +16 -3
- package/src/acp/model-config.test.ts +166 -0
- package/src/acp/model-config.ts +138 -0
- package/src/acp/prepare-agent-env.ts +21 -6
- package/src/acp/resolve-agent.test.ts +220 -6
- package/src/acp/resolve-agent.ts +88 -23
- package/src/acp/session-manager.test.ts +196 -3
- package/src/acp/session-manager.ts +441 -18
- package/src/acp/session-snapshot.ts +260 -0
- package/src/acp/types.ts +50 -5
- package/src/agent/loop.ts +38 -12
- package/src/agent/tool-result-follow-up.ts +70 -0
- package/src/api/attachment-provenance.test.ts +68 -0
- package/src/api/computer-use-tool.test.ts +55 -0
- package/src/api/computer-use-tool.ts +27 -0
- package/src/api/events/acp-session-model-update.test.ts +88 -0
- package/src/api/events/acp-session-model-update.ts +46 -0
- package/src/api/events/app-files-changed.ts +4 -3
- package/src/api/events/assistant-outbound-attachment.ts +3 -0
- package/src/api/events/desktop-activity-changed.ts +10 -0
- package/src/api/events/notification-intent.ts +2 -0
- package/src/api/events/question-request.ts +1 -0
- package/src/api/events/user-message-echo.ts +7 -1
- package/src/api/index.ts +17 -0
- package/src/api/responses/conversation-message.ts +8 -0
- package/src/approvals/approval-primitive.ts +5 -2
- package/src/approvals/scoped-approval-grants.ts +6 -2
- package/src/apps/app-store.ts +7 -6
- package/src/apps/resolve-app.ts +81 -0
- package/src/apps/source-fingerprint.ts +266 -0
- package/src/avatar/identity-avatar.ts +7 -2
- package/src/browser/operations.ts +2 -1
- package/src/browser/types.ts +7 -0
- package/src/browser/virtual-desktop-target.ts +34 -0
- package/src/bundler/app-compiler.ts +15 -0
- package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
- package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
- package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
- package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
- package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
- package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
- package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
- package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +27 -4
- package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
- package/src/calls/__tests__/voice-control-protocol.test.ts +151 -27
- package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
- package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
- package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
- package/src/calls/__tests__/voice-session-bridge.test.ts +140 -3
- package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
- package/src/calls/barge-in-guard.ts +118 -0
- package/src/calls/call-constants.ts +24 -4
- package/src/calls/call-controller.ts +499 -199
- package/src/calls/call-transport.ts +16 -0
- package/src/calls/media-stream-output.ts +32 -0
- package/src/calls/media-stream-server.ts +82 -30
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/{live-voice → calls}/progress-narration.ts +17 -4
- package/src/calls/resolve-call-tts-provider.ts +33 -2
- package/src/calls/tts-call-strategy.ts +9 -5
- package/src/calls/types.ts +2 -0
- package/src/calls/voice-control-protocol.ts +194 -21
- package/src/calls/voice-leg-coordinator.ts +189 -0
- package/src/calls/voice-progress-cadence.ts +423 -0
- package/src/calls/voice-session-bridge.ts +140 -76
- package/src/calls/voice-triage-escalate.ts +178 -59
- package/src/cli/commands/__tests__/apps.test.ts +245 -0
- package/src/cli/commands/__tests__/bash.test.ts +53 -0
- package/src/cli/commands/__tests__/browser.test.ts +84 -3
- package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
- package/src/cli/commands/__tests__/plugins.test.ts +85 -0
- package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
- package/src/cli/commands/__tests__/schedules.test.ts +14 -0
- package/src/cli/commands/apps.help.ts +67 -13
- package/src/cli/commands/apps.ts +183 -0
- package/src/cli/commands/bash.help.ts +9 -13
- package/src/cli/commands/bash.ts +7 -25
- package/src/cli/commands/browser.help.ts +47 -0
- package/src/cli/commands/browser.ts +52 -8
- package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
- package/src/cli/commands/channels/index.help.ts +70 -2
- package/src/cli/commands/channels/index.ts +16 -3
- package/src/cli/commands/channels/send.ts +128 -0
- package/src/cli/commands/credentials.help.ts +9 -5
- package/src/cli/commands/credentials.ts +2 -2
- package/src/cli/commands/mcp.help.ts +8 -8
- package/src/cli/commands/mcp.ts +1 -1
- package/src/cli/commands/oauth/index.help.ts +10 -0
- package/src/cli/commands/oauth/providers.ts +12 -0
- package/src/cli/commands/oauth/request.test.ts +179 -2
- package/src/cli/commands/oauth/request.ts +41 -10
- package/src/cli/commands/oauth/status.ts +5 -0
- package/src/cli/commands/plugins.ts +73 -23
- package/src/cli/commands/roadmap.help.ts +5 -1
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/commands/schedules.ts +2 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +219 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +77 -2
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +45 -3
- package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +251 -0
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +65 -2
- package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +14 -0
- package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +27 -1
- package/src/cli/lib/__tests__/plugin-details.test.ts +35 -2
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +20 -0
- package/src/cli/lib/__tests__/plugins-install-offline.test.ts +43 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +31 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +122 -5
- package/src/cli/lib/bundled-marketplace.json +962 -81
- package/src/cli/lib/bundled-plugin-packages.json +786 -0
- package/src/cli/lib/bundled-plugin-packages.ts +87 -0
- package/src/cli/lib/diff-plugin.ts +1 -1
- package/src/cli/lib/inspect-plugin.ts +87 -12
- package/src/cli/lib/install-from-github.ts +150 -94
- package/src/cli/lib/install-from-platform.ts +14 -9
- package/src/cli/lib/list-installed-plugins.ts +21 -35
- package/src/cli/lib/plugin-catalog-cache.ts +22 -3
- package/src/cli/lib/plugin-catalog-local.ts +13 -3
- package/src/cli/lib/plugin-catalog-platform.ts +6 -1
- package/src/cli/lib/plugin-catalog-resolve.ts +20 -0
- package/src/cli/lib/plugin-details.ts +33 -8
- package/src/cli/lib/plugin-marketplace.ts +121 -21
- package/src/cli/lib/plugin-pin-history.ts +5 -2
- package/src/cli/lib/search-plugins.ts +58 -16
- package/src/cli/lib/uninstall-plugin.ts +59 -1
- package/src/cli/lib/upgrade-plugin.ts +61 -8
- package/src/cli/output.ts +18 -4
- package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
- package/src/config/__tests__/default-provider.test.ts +4 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
- package/src/config/__tests__/platform-identity.test.ts +255 -0
- package/src/config/__tests__/platform-rehydration.test.ts +99 -9
- package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +21 -0
- package/src/config/acp-agent-write.ts +43 -0
- package/src/config/acp-defaults.test.ts +13 -3
- package/src/config/acp-defaults.ts +23 -6
- package/src/config/acp-schema.test.ts +81 -0
- package/src/config/acp-schema.ts +30 -2
- package/src/config/bundled-skills/acp/SKILL.md +23 -15
- package/src/config/bundled-skills/acp/TOOLS.json +7 -3
- package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
- package/src/config/bundled-skills/computer-use/SKILL.md +59 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +101 -2
- package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
- package/src/config/bundled-skills/messaging/SKILL.md +3 -3
- package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
- package/src/config/bundled-skills/schedule/SKILL.md +7 -8
- package/src/config/bundled-skills/screen-annotation/SKILL.md +10 -3
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +13 -9
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
- package/src/config/default-profile-catalog.ts +1 -1
- package/src/config/env.ts +2 -2
- package/src/config/feature-flag-registry.json +33 -13
- package/src/config/loader.ts +11 -17
- package/src/config/memory-v3-gate.test.ts +31 -0
- package/src/config/memory-v3-gate.ts +20 -16
- package/src/config/platform-identity.ts +201 -0
- package/src/config/platform-rehydration.ts +11 -27
- package/src/config/profile-text-generation.test.ts +51 -0
- package/src/config/profile-text-generation.ts +51 -0
- package/src/config/schema.ts +2 -2
- package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
- package/src/config/schemas/__tests__/voice.test.ts +148 -0
- package/src/config/schemas/calls.ts +1 -28
- package/src/config/schemas/live-voice.ts +1 -173
- package/src/config/schemas/llm.ts +7 -2
- package/src/config/schemas/mcp.ts +15 -9
- package/src/config/schemas/memory-retrospective.ts +10 -0
- package/src/config/schemas/monitoring.ts +9 -0
- package/src/config/schemas/services.ts +18 -0
- package/src/config/schemas/skills.ts +0 -14
- package/src/config/schemas/voice.ts +150 -0
- package/src/config/skills.ts +13 -21
- package/src/credential-execution/ces-runtime.ts +2 -2
- package/src/credential-execution/executable-discovery.ts +36 -134
- package/src/credential-execution/process-manager.test.ts +37 -42
- package/src/credential-execution/process-manager.ts +24 -19
- package/src/credential-health/credential-health-service.ts +11 -17
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +47 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -121
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +5 -1
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
- package/src/daemon/app-change-notify.ts +45 -0
- package/src/daemon/assistant-attachments.ts +20 -12
- package/src/daemon/config-watcher.ts +13 -194
- package/src/daemon/conversation-agent-loop-handlers.ts +74 -3
- package/src/daemon/conversation-agent-loop.ts +12 -0
- package/src/daemon/conversation-attachments.ts +93 -12
- package/src/daemon/conversation-client-surface.ts +26 -0
- package/src/daemon/conversation-error.ts +3 -2
- package/src/daemon/conversation-media-retry.ts +2 -1
- package/src/daemon/conversation-process.ts +35 -64
- package/src/daemon/conversation-runtime-assembly.ts +21 -8
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +21 -10
- package/src/daemon/conversation-tool-setup.ts +135 -109
- package/src/daemon/conversation-turn-finalize.ts +26 -13
- package/src/daemon/conversation.ts +17 -3
- package/src/daemon/daemon-control.ts +3 -7
- package/src/daemon/dictation-profile-store.ts +2 -1
- package/src/daemon/handlers/shared.ts +2 -1
- package/src/daemon/handlers/skills.ts +6 -3
- package/src/daemon/host-bash-proxy.ts +8 -12
- package/src/daemon/host-browser-proxy.ts +15 -1
- package/src/daemon/host-cu-proxy.ts +275 -45
- package/src/daemon/host-file-proxy.ts +8 -10
- package/src/daemon/host-proxy-preactivation.ts +4 -1
- package/src/daemon/host-transfer-proxy.ts +14 -18
- package/src/daemon/lifecycle.ts +4 -9
- package/src/daemon/mcp-reload-service.ts +13 -6
- package/src/daemon/message-types/shared.ts +1 -0
- package/src/daemon/message-types/sync.ts +2 -0
- package/src/daemon/orphan-reaper.ts +4 -3
- package/src/daemon/persist-media-references.ts +20 -3
- package/src/daemon/providers-setup.ts +5 -1
- package/src/daemon/reaction-history-render.ts +2 -1
- package/src/daemon/shutdown-handlers.ts +1 -9
- package/src/daemon/skill-memory-refresh.ts +64 -0
- package/src/daemon/tool-setup-types.ts +6 -0
- package/src/daemon/tool-side-effects.ts +7 -18
- package/src/daemon/wake-conversation-ops.ts +38 -15
- package/src/desktop/__tests__/fake-desktop.ts +123 -0
- package/src/desktop/desktop-automation-lease.test.ts +438 -0
- package/src/desktop/desktop-automation-lease.ts +355 -0
- package/src/desktop/desktop-browser-client.test.ts +413 -0
- package/src/desktop/desktop-browser-client.ts +430 -0
- package/src/desktop/desktop-browser-cursor.ts +40 -0
- package/src/desktop/desktop-browser-endpoint.test.ts +78 -0
- package/src/desktop/desktop-browser-endpoint.ts +145 -0
- package/src/desktop/desktop-browser-operations.ts +130 -0
- package/src/desktop/desktop-chrome-policy.test.ts +79 -0
- package/src/desktop/desktop-chrome-policy.ts +47 -0
- package/src/desktop/desktop-chrome-session.test.ts +48 -0
- package/src/desktop/desktop-chrome-session.ts +87 -0
- package/src/desktop/desktop-dependencies.test.ts +131 -0
- package/src/desktop/desktop-dependencies.ts +329 -0
- package/src/desktop/desktop-display.ts +9 -0
- package/src/desktop/desktop-help.ts +16 -0
- package/src/desktop/desktop-panel-config.test.ts +135 -0
- package/src/desktop/desktop-panel-config.ts +162 -0
- package/src/desktop/desktop-session-manager.test.ts +813 -0
- package/src/desktop/desktop-session-manager.ts +970 -0
- package/src/desktop/desktop-stream-bridge.test.ts +395 -0
- package/src/desktop/desktop-stream-bridge.ts +214 -0
- package/src/desktop/desktop-wallpaper.test.ts +191 -0
- package/src/desktop/desktop-wallpaper.ts +113 -0
- package/src/desktop/desktop-window-drag.ts +177 -0
- package/src/desktop/desktop-window-manager-config.test.ts +230 -0
- package/src/desktop/desktop-window-manager-config.ts +238 -0
- package/src/desktop/desktop-window-theme.ts +170 -0
- package/src/desktop/virtual-desktop-feature.ts +18 -0
- package/src/desktop/virtual-desktop-platform.test.ts +61 -0
- package/src/heartbeat/heartbeat-service.ts +21 -3
- package/src/home/__tests__/feed-writer.test.ts +22 -0
- package/src/home/feed-writer.ts +11 -2
- package/src/hooks/types.ts +33 -0
- package/src/i18n/AGENTS.md +22 -0
- package/src/i18n/__tests__/i18n.test.ts +112 -0
- package/src/i18n/index.ts +16 -0
- package/src/i18n/locales.ts +93 -0
- package/src/i18n/messages.ts +70 -0
- package/src/i18n/title.ts +25 -0
- package/src/inbound/platform-callback-registration.ts +4 -5
- package/src/ipc/__tests__/browser-ipc.test.ts +230 -2
- package/src/ipc/__tests__/cancel-on-disconnect.test.ts +54 -0
- package/src/ipc/assistant-server.ts +15 -1
- package/src/ipc/cli-client.ts +13 -5
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +143 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +9 -7
- package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +374 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +19 -0
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +660 -5
- package/src/live-voice/__tests__/protocol.test.ts +95 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/__tests__/session-controls.test.ts +156 -0
- package/src/live-voice/live-voice-metrics.ts +9 -0
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +1081 -760
- package/src/live-voice/protocol.ts +89 -2
- package/src/live-voice/session-controls.ts +197 -0
- package/src/mcp/__tests__/credential-target.test.ts +59 -0
- package/src/mcp/__tests__/effective-config.test.ts +13 -2
- package/src/mcp/__tests__/manager-state.test.ts +128 -0
- package/src/mcp/__tests__/manager-tool-caps.test.ts +111 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +20 -6
- package/src/mcp/__tests__/mcp-auth-state-target.test.ts +49 -0
- package/src/mcp/__tests__/plugin-mcp-oauth-cleanup.test.ts +107 -0
- package/src/mcp/__tests__/plugin-mcp-oauth-provider-isolation.test.ts +89 -0
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +63 -11
- package/src/mcp/__tests__/reload-signal-emission.test.ts +39 -2
- package/src/mcp/__tests__/startup.test.ts +30 -7
- package/src/mcp/__tests__/tool-caps.test.ts +107 -0
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
- package/src/mcp/client.ts +64 -16
- package/src/mcp/credential-target.ts +105 -0
- package/src/mcp/effective-config.ts +45 -18
- package/src/mcp/manager.ts +201 -81
- package/src/mcp/mcp-auth-orchestrator.ts +17 -4
- package/src/mcp/mcp-auth-state.ts +38 -6
- package/src/mcp/mcp-header-store.ts +29 -45
- package/src/mcp/mcp-oauth-provider.ts +101 -33
- package/src/mcp/spec-schema.ts +111 -0
- package/src/mcp/startup.ts +41 -17
- package/src/mcp/tool-caps.ts +176 -0
- package/src/mcp/workspace-mcp-config.ts +188 -0
- package/src/messaging/provider-message-metadata.ts +3 -3
- package/src/messaging/provider.ts +10 -3
- package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
- package/src/messaging/providers/callback-routing.ts +18 -0
- package/src/messaging/providers/channel-transport.ts +56 -0
- package/src/messaging/providers/discord/transport.ts +17 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
- package/src/messaging/providers/slack/adapter.ts +7 -44
- package/src/messaging/providers/slack/transport.ts +16 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
- package/src/messaging/providers/telegram-bot/client.ts +0 -26
- package/src/messaging/providers/telegram-bot/transport.ts +20 -0
- package/src/messaging/providers/whatsapp/adapter.ts +1 -48
- package/src/messaging/providers/whatsapp/transport.ts +18 -0
- package/src/monitoring/__tests__/mount-watch.test.ts +236 -0
- package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
- package/src/monitoring/mount-watch.ts +348 -0
- package/src/monitoring/plugin-auto-update.ts +6 -0
- package/src/monitoring/worker.ts +9 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
- package/src/notifications/__tests__/copy-composer.test.ts +70 -0
- package/src/notifications/__tests__/decision-engine.test.ts +175 -0
- package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
- package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
- package/src/notifications/adapters/macos.ts +3 -0
- package/src/notifications/assistant-reply-producer.ts +8 -3
- package/src/notifications/conversation-pairing.ts +36 -16
- package/src/notifications/copy-composer.ts +11 -3
- package/src/notifications/decision-engine.ts +43 -8
- package/src/notifications/delivered-post-record.ts +11 -1
- package/src/notifications/guardian-feed-projection.ts +125 -5
- package/src/notifications/home-feed-side-effect.ts +55 -7
- package/src/notifications/schedule-result-producer.ts +64 -22
- package/src/oauth/AGENTS.md +4 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
- package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
- package/src/oauth/byo-connection.test.ts +105 -0
- package/src/oauth/byo-connection.ts +36 -6
- package/src/oauth/connection-resolver.test.ts +100 -0
- package/src/oauth/connection-resolver.ts +120 -3
- package/src/oauth/identity-verifier.ts +24 -0
- package/src/oauth/oauth-store.ts +11 -1
- package/src/oauth/provider-serializer.ts +10 -0
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +367 -27
- package/src/onboarding/checkin-event.ts +2 -1
- package/src/outbound-proxy/certs.ts +3 -5
- package/src/permissions/checker.test.ts +11 -6
- package/src/permissions/confirmation-guardian-request.test.ts +16 -0
- package/src/permissions/confirmation-guardian-request.ts +2 -3
- package/src/permissions/question-prompter.test.ts +31 -0
- package/src/permissions/question-prompter.ts +2 -0
- package/src/persistence/attachments-store.ts +84 -44
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +182 -83
- package/src/persistence/conversation-lineage.ts +12 -4
- package/src/persistence/conversation-plugin-facade.ts +13 -0
- package/src/persistence/conversation-queries.ts +2 -2
- package/src/persistence/conversation-title-placeholders.ts +23 -0
- package/src/persistence/conversation-title-service.ts +9 -26
- package/src/persistence/conversation-tool-surface.ts +86 -0
- package/src/persistence/conversation-types.test.ts +32 -0
- package/src/persistence/conversation-types.ts +26 -4
- package/src/persistence/embeddings/qdrant-manager.ts +163 -18
- package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
- package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
- package/src/persistence/message-cursor.ts +78 -0
- package/src/persistence/message-reads.ts +30 -0
- package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
- package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
- package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
- package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
- package/src/persistence/schema/conversation-tool-surfaces.ts +22 -0
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/memory-core.ts +5 -0
- package/src/persistence/schema/oauth.ts +1 -0
- package/src/persistence/steps.ts +15 -3
- package/src/platform/client.test.ts +4 -2
- package/src/platform/client.ts +2 -10
- package/src/plugin-api/constants.ts +2 -0
- package/src/plugin-api/conversation-turn.ts +31 -7
- package/src/plugin-api/index.ts +10 -1
- package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
- package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
- package/src/plugin-api/types.ts +2 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +14 -1
- package/src/plugins/__tests__/mcp-servers.test.ts +38 -8
- package/src/plugins/defaults/index.ts +2 -0
- package/src/plugins/defaults/memory/AGENTS.md +14 -2
- package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +66 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +20 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
- package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
- package/src/plugins/defaults/memory/buffer-file.ts +354 -0
- package/src/plugins/defaults/memory/buffer-format.ts +40 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -3
- package/src/plugins/defaults/memory/context-search/format.ts +4 -2
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +7 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +4 -2
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -8
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -42
- package/src/plugins/defaults/memory/hooks/init.ts +10 -0
- package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
- package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
- package/src/plugins/defaults/memory/injectors.ts +4 -3
- package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
- package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
- package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +67 -184
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
- package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
- package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +1 -1
- package/src/plugins/defaults/memory/startup.ts +28 -2
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
- package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +7 -1
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +89 -49
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -1
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
- package/src/plugins/defaults/memory/v2/reranker.ts +7 -1
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
- package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
- package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -0
- package/src/plugins/defaults/memory/v3/card.ts +4 -2
- package/src/plugins/defaults/memory/v3/injector.ts +212 -178
- package/src/plugins/defaults/memory/v3/orchestrate.ts +86 -22
- package/src/plugins/defaults/memory/v3/pool-select.ts +13 -8
- package/src/plugins/defaults/memory/v3/sections.ts +10 -3
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +13 -1
- package/src/plugins/defaults/memory/worker.ts +6 -0
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +4 -1
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
- package/src/plugins/external-plugin-loader.ts +49 -86
- package/src/plugins/installed-plugin-dirs.ts +6 -4
- package/src/plugins/mcp-servers.ts +24 -90
- package/src/plugins/mtime-cache.ts +2 -1
- package/src/plugins/user-loader.ts +2 -1
- package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
- package/src/providers/__tests__/retry-callsite.test.ts +41 -0
- package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
- package/src/providers/anthropic/client.ts +0 -47
- package/src/providers/gemini/client.ts +9 -23
- package/src/providers/gemini-thought-signature.test.ts +63 -0
- package/src/providers/gemini-thought-signature.ts +44 -0
- package/src/providers/inference/__tests__/endpoint-probe.test.ts +87 -3
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- package/src/providers/inference/endpoint-probe.ts +36 -12
- package/src/providers/inference/resolve-auth.ts +22 -4
- package/src/providers/inference/service-account-token.ts +248 -0
- package/src/providers/jev/client.test.ts +260 -0
- package/src/providers/jev/client.ts +518 -0
- package/src/providers/model-catalog.ts +92 -3
- package/src/providers/model-intents.ts +10 -5
- package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
- package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
- package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
- package/src/providers/openai/chat-completions-provider.ts +212 -79
- package/src/providers/openai/codex-models.ts +0 -4
- package/src/providers/openai/google-thought-signature.ts +320 -0
- package/src/providers/openai/responses-provider.ts +9 -2
- package/src/providers/opencode/client.test.ts +240 -4
- package/src/providers/opencode/client.ts +129 -3
- package/src/providers/openrouter/client.ts +20 -0
- package/src/providers/outbound-request-sanitize.ts +96 -0
- package/src/providers/retry.ts +30 -19
- package/src/providers/server-tool-pairing.ts +16 -7
- package/src/providers/unparseable-tool-args.ts +5 -1
- package/src/runtime/AGENTS.md +9 -3
- package/src/runtime/__tests__/agent-wake.test.ts +86 -1
- package/src/runtime/__tests__/channel-send.test.ts +443 -0
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +132 -0
- package/src/runtime/__tests__/host-observe.test.ts +40 -1
- package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
- package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
- package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
- package/src/runtime/agent-wake.ts +22 -5
- package/src/runtime/assistant-event-hub.ts +21 -3
- package/src/runtime/auth/same-actor.ts +38 -3
- package/src/runtime/channel-send.ts +316 -0
- package/src/runtime/guardian-action-service.ts +2 -17
- package/src/runtime/guardian-reply-router.ts +1 -8
- package/src/runtime/host-observe.ts +11 -1
- package/src/runtime/http-server.ts +160 -151
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
- package/src/runtime/migrations/vbundle-import-policy.ts +33 -11
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
- package/src/runtime/routes/__tests__/acp-routes.test.ts +178 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
- package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
- package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
- package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +127 -3
- package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
- package/src/runtime/routes/acp-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +84 -165
- package/src/runtime/routes/app-management-routes.ts +90 -2
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/browser-context.ts +39 -0
- package/src/runtime/routes/browser-routes.ts +16 -47
- package/src/runtime/routes/browser-tabs-routes.ts +72 -29
- package/src/runtime/routes/channel-route-shared.ts +1 -9
- package/src/runtime/routes/channel-send-routes.ts +85 -0
- package/src/runtime/routes/conversation-list-routes.ts +14 -3
- package/src/runtime/routes/conversation-query-routes.ts +40 -0
- package/src/runtime/routes/conversation-routes.ts +45 -7
- package/src/runtime/routes/credential-routes.ts +20 -14
- package/src/runtime/routes/desktop-setup-routes.test.ts +89 -0
- package/src/runtime/routes/desktop-setup-routes.ts +41 -0
- package/src/runtime/routes/diagnostics-routes.ts +61 -4
- package/src/runtime/routes/events-routes.ts +4 -0
- package/src/runtime/routes/guardian-approval-interception.ts +24 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -0
- package/src/runtime/routes/inbound-message-handler.ts +2 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +1 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -4
- package/src/runtime/routes/index.ts +4 -2
- package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
- package/src/runtime/routes/inference-profiles-routes.ts +9 -0
- package/src/runtime/routes/log-export-routes.ts +2 -0
- package/src/runtime/routes/mcp-auth-routes.ts +141 -137
- package/src/runtime/routes/migration-routes.ts +6 -20
- package/src/runtime/routes/oauth-commands-routes.ts +98 -45
- package/src/runtime/routes/oauth-providers.ts +11 -0
- package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
- package/src/runtime/routes/oauth-request-hints.ts +149 -0
- package/src/runtime/routes/platform-routes.ts +18 -15
- package/src/runtime/routes/plugins-routes.ts +83 -50
- package/src/runtime/routes/schedule-routes.ts +2 -0
- package/src/runtime/routes/secret-routes.ts +99 -119
- package/src/runtime/routes/workspace-routes.test.ts +55 -26
- package/src/runtime/routes/workspace-routes.ts +46 -63
- package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
- package/src/runtime/routes/workspace-tree-walk.ts +240 -0
- package/src/runtime/routes/workspace-utils.ts +17 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +16 -3
- package/src/runtime/sync/resource-sync-events.ts +6 -1
- package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
- package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
- package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
- package/src/schedule/run-script.ts +4 -3
- package/src/schedule/schedule-store.ts +9 -2
- package/src/schedule/scheduler.ts +47 -11
- package/src/schedule/tool-surface-readiness.ts +65 -0
- package/src/schedule/worker-mcp.ts +85 -0
- package/src/schedule/worker.ts +9 -31
- package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
- package/src/security/ces-http-record-backend.ts +120 -0
- package/src/security/ces-rpc-record-backend.ts +7 -0
- package/src/security/secure-keys.ts +60 -48
- package/src/security/untrusted-content.ts +3 -1
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
- package/src/skills/managed-store.ts +153 -31
- package/src/skills/workspace-skill-md-signature.ts +50 -0
- package/src/subagent/consult-context.ts +12 -25
- package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
- package/src/tools/acp/list-agents.test.ts +3 -1
- package/src/tools/acp/spawn.test.ts +146 -11
- package/src/tools/acp/spawn.ts +21 -3
- package/src/tools/acp/status.test.ts +349 -0
- package/src/tools/acp/status.ts +112 -9
- package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +167 -5
- package/src/tools/ask-question/ask-question-tool.ts +119 -23
- package/src/tools/browser/browser-execution.ts +52 -15
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +69 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +1 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +5 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
- package/src/tools/browser/network-recorder.ts +2 -1
- package/src/tools/capability-offer.test.ts +22 -2
- package/src/tools/capability-offer.ts +16 -1
- package/src/tools/computer-use/definitions.ts +123 -5
- package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
- package/src/tools/credentials/metadata-store.ts +100 -0
- package/src/tools/filesystem/search.ts +2 -1
- package/src/tools/host-filesystem/edit.test.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +2 -2
- package/src/tools/host-filesystem/read.test.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -2
- package/src/tools/host-filesystem/transfer.test.ts +2 -1
- package/src/tools/host-filesystem/transfer.ts +2 -2
- package/src/tools/host-filesystem/write.test.ts +2 -1
- package/src/tools/host-filesystem/write.ts +2 -2
- package/src/tools/host-terminal/host-shell.test.ts +16 -0
- package/src/tools/host-terminal/host-shell.ts +16 -26
- package/src/tools/network/web-search.ts +6 -1
- package/src/tools/policy-context.ts +6 -7
- package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
- package/src/tools/shared/shell-output.test.ts +10 -0
- package/src/tools/shared/shell-output.ts +14 -2
- package/src/tools/skills/find-similar-skills.test.ts +214 -2
- package/src/tools/skills/find-similar-skills.ts +62 -9
- package/src/tools/skills/resolve-execute-invocation.ts +24 -0
- package/src/tools/skills/sandbox-runner.ts +13 -2
- package/src/tools/skills/scaffold-managed.ts +78 -16
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/safe-env.test.ts +33 -4
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +43 -0
- package/src/tools/terminal/safe-env.ts +35 -24
- package/src/tools/terminal/sanitized-bash.ts +118 -0
- package/src/tools/terminal/shell-launch.test.ts +162 -0
- package/src/tools/terminal/shell.test.ts +29 -0
- package/src/tools/terminal/shell.ts +13 -7
- package/src/tools/ui-surface/channel-variants.ts +10 -59
- package/src/tools/watch/watch-retro-report.ts +0 -8
- package/src/types/host-capabilities.ts +5 -3
- package/src/util/__tests__/language-subtag.test.ts +23 -1
- package/src/util/abort-reasons.ts +12 -1
- package/src/util/browser-human-verification.ts +14 -0
- package/src/util/ca-bundle.ts +13 -0
- package/src/util/host-process.test.ts +17 -1
- package/src/util/host-process.ts +24 -0
- package/src/util/language-subtag.ts +16 -0
- package/src/util/platform.ts +8 -0
- package/src/util/plugin-manifest.ts +203 -0
- package/src/util/unicode.ts +44 -1
- package/src/watch/watch-retro.ts +6 -8
- package/src/watch/watch-timeline.ts +2 -2
- package/src/workflows/run-manager.ts +2 -1
- package/src/workspace/git-porcelain.ts +66 -0
- package/src/workspace/git-service.ts +6 -55
- package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
- package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
- package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
- package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
- package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
- package/src/workspace/migrations/registry.ts +6 -0
- package/src/__tests__/app-source-watcher.test.ts +0 -218
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
- package/src/__tests__/speaker-identification.test.ts +0 -56
- package/src/calls/speaker-identification.ts +0 -233
- package/src/daemon/app-source-watcher.ts +0 -218
- package/src/messaging/providers/whatsapp/client.ts +0 -29
- package/src/runtime/routes/debug-bash-routes.ts +0 -173
- package/src/util/fs-watcher-error.ts +0 -36
- /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
package/.env.example
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
ANTHROPIC_API_KEY=sk-ant-...
|
|
3
3
|
OPENAI_API_KEY=sk-...
|
|
4
4
|
GEMINI_API_KEY=...
|
|
5
|
+
# Optional. TypeSafe / Jev System One decision model.
|
|
6
|
+
TYPESAFE_API_KEY=...
|
|
5
7
|
# Optional for authenticated/proxied Ollama deployments
|
|
6
8
|
OLLAMA_API_KEY=
|
|
7
9
|
# Optional override (defaults to http://127.0.0.1:11434/v1)
|
package/AGENTS.md
CHANGED
|
@@ -16,7 +16,7 @@ When you introduce a new env var that the assistant process needs to read at run
|
|
|
16
16
|
|
|
17
17
|
**Default to including it.** If the var doesn't contain secrets (e.g. a URL, a feature flag, a path, a mode string), add it. Only omit it if it carries credential material (tokens, passwords, private keys) — those must stay isolated to CES.
|
|
18
18
|
|
|
19
|
-
`
|
|
19
|
+
`CES_BOOTSTRAP_SOCKET_DIR` is forwarded so children can reach CES over IPC. `CES_SERVICE_TOKEN` and `CES_CREDENTIAL_URL` are also forwarded so children can fail over to CES HTTP until that transport is removed. Credential protection is rules-based access control inside CES, not socket-path secrecy (see root `AGENTS.md`).
|
|
20
20
|
|
|
21
21
|
## Daemon startup philosophy
|
|
22
22
|
|
|
@@ -87,6 +87,10 @@ The module-level dependency-injection pattern (`registerFooDeps()`) used by some
|
|
|
87
87
|
|
|
88
88
|
Telemetry event types are defined by a platform-generated wire contract (`src/telemetry/telemetry-wire.generated.ts`) that `src/telemetry/types.ts` layers over, with pre-flush validation against it. Adding a new event type starts platform-side, not here. The mechanics, the drift guards, and the cross-repo ordering are documented next to the code they govern: see [`src/telemetry/AGENTS.md`](src/telemetry/AGENTS.md).
|
|
89
89
|
|
|
90
|
+
## Daemon i18n
|
|
91
|
+
|
|
92
|
+
User-facing copy the daemon generates as a hardcoded constant goes through `src/i18n/`. Persist the message key. Resolve with `t(key, locale)` at the HTTP/CLI/channel edge. Never persist a translated string, and never match stored display strings back to keys. See [`src/i18n/AGENTS.md`](src/i18n/AGENTS.md).
|
|
93
|
+
|
|
90
94
|
## Code comments
|
|
91
95
|
|
|
92
96
|
When writing or updating comments, **do not reference code that has been removed.** Comments should describe the current state of the codebase, not narrate its history. Avoid phrases like "no longer does X", "previously used Y", or "was removed in PR Z" — future readers should not need to understand past implementations to understand the current code.
|
package/ARCHITECTURE.md
CHANGED
|
@@ -609,9 +609,11 @@ Every phone call connects over Twilio Media Streams: the voice webhook emits `<C
|
|
|
609
609
|
|
|
610
610
|
Transcription mode is selected once per session in `media-stream-stt-session.ts`:
|
|
611
611
|
|
|
612
|
-
- **Streaming** (default): when `calls.voice.telephonyStreaming` is enabled and the `telephony` role resolves a streaming transcriber (`resolveStreamingTranscriber({ role: "telephony" })`), inbound audio is decoded (mu-law → PCM16, resampled 8 kHz → 16 kHz) and fed to the provider's realtime adapter. Replies trigger only on utterance-boundary finals (for Deepgram, `speech_final`/`UtteranceEnd`, never mid-sentence `is_final` segments), and barge-in fires from local energy VAD, never from transcriber partials.
|
|
612
|
+
- **Streaming** (default): when `calls.voice.telephonyStreaming` is enabled and the `telephony` role resolves a streaming transcriber (`resolveStreamingTranscriber({ role: "telephony" })`), inbound audio is decoded (mu-law → PCM16, resampled 8 kHz → 16 kHz) and fed to the provider's realtime adapter. Replies trigger only on utterance-boundary finals (for Deepgram, `speech_final`/`UtteranceEnd`, never mid-sentence `is_final` segments), and barge-in fires from local energy VAD, never from transcriber partials. While something is interruptible (an assistant turn in flight, thinking or speaking, or a completed turn's tail still playing from Twilio's buffer), caller speech arms the shared sustained-speech barge-in guard (`src/calls/barge-in-guard.ts`, the same accounting live voice uses: speech accumulates toward 250 ms, short gaps are tolerated, a run that is mostly silence resets) and every inbound frame feeds it; outside that window the guard is dropped, so the caller's own utterance never carries into a turn that starts before the local VAD ends it. Only a fired guard reaches `CallController.handleBargeIn`, which interrupts a turn in either phase and ignores an idle controller (the playing tail is cleared instead).
|
|
613
613
|
- **Batch fallback**: otherwise the session segments turns with the energy-based `MediaTurnDetector` and transcribes each completed turn via the same role's batch API. Both halves of a call read the `telephony` role, which is why a role names its consumer rather than a boundary.
|
|
614
614
|
|
|
615
|
+
Every phone turn runs the same two-leg triage as live voice through `startVoiceTurn` (`src/calls/voice-session-bridge.ts`): `call-controller.ts` opens on a toolless front-door leg (`routingLeg: "front-door"`, the `voiceFrontDoor` call site) and drives it through the shared `createFrontDoorLegCoordinator` (`src/calls/voice-leg-coordinator.ts`), which reads the stream through the verdict machine and sequences the hand-off (pause narration, abort the leg, resolve and speak the bridge, mark it as the floor holder, start the escalated leg pinned to the conversation's own model, re-arm narration); each driver supplies only a host for how text and the bridge are spoken, how a leg is started or aborted, and (live voice only) the speculative hold and commit. Phone has no partial transcripts, so the hold verdict is never taught and routing is escalate-only. The controller also passes the bridge's turn callbacks (tool activity is recorded as `tool_use_started` / `tool_use_completed` call events, persisted row ids ride the `assistant_spoke` event), `launchedAtMs` for dispatch timing, and a `voiceTelemetry` bag keyed by the call session with a `phone_inbound` / `phone_outbound` entry. Both drivers share the spoken progress narration cadence (`src/calls/voice-progress-cadence.ts`, tuned by `voice.frontModel.progress`): the cadence owns the tool-activity log, the triggers (an ops burst, a long operation completing, a full interval of audible silence with news, the `maxSilenceMs` heartbeat) and the generated or static phrase, while each driver supplies its own view of audible silence (live voice from its TTS queue and playback-tail estimate; the media-stream transport from `isPlaybackIdle()` and a running sum of sent frame durations) and how to speak a phrase.
|
|
616
|
+
|
|
615
617
|
A credential preflight (`resolveTelephonyCredentialReadiness()` in `src/calls/telephony-credential-preflight.ts`) gates every call: it requires a credentialed, telephony-capable STT provider **and** a media-stream-playable TTS provider (the configured one or a credentialed playable fallback). Inbound calls that fail the preflight receive `<Say>` setup-required copy plus `<Hangup/>` instead of a doomed stream; outbound placement fails before dialing via `preflightVoiceIngress()` with the same user-facing message.
|
|
616
618
|
|
|
617
619
|
Key modules:
|
|
@@ -729,9 +731,9 @@ The assistant-side live voice module is intentionally bounded under `src/live-vo
|
|
|
729
731
|
| `live-voice-archive.ts` | Audio artifact creation/linking for user utterance and assistant response message IDs |
|
|
730
732
|
| `live-voice-metrics.ts` | Per-session and per-turn latency snapshots emitted as `metrics` frames |
|
|
731
733
|
|
|
732
|
-
Live voice STT uses the same `resolveStreamingTranscriber()` path as conversation streaming. For V1 latency-sensitive behavior,
|
|
734
|
+
Live voice STT uses the same `resolveStreamingTranscriber()` path as conversation streaming, dialed with the provider the `liveVoice` STT role resolves to after managed-speech defaulting (`resolveEffectiveSpeechProviders`, see `config/managed-speech-defaults.ts`). For V1 latency-sensitive behavior, that provider must resolve to a `daemon-streaming` transcriber whose catalog entry has `conversationStreamingMode: "realtime-ws"` and usable credentials. Providers that only support batch or incremental-batch transcription remain valid for other voice surfaces, but do not satisfy live voice's streaming STT requirement.
|
|
733
735
|
|
|
734
|
-
Live voice TTS uses `streamLiveVoiceTtsAudio()` and the configured `services.tts.provider
|
|
736
|
+
Live voice TTS uses `streamLiveVoiceTtsAudio()` and the TTS provider that `resolveEffectiveSpeechProviders` settles on (the configured `services.tts.provider`, or the managed `vellum` provider when the configured one has no usable credentials). The selected provider must be registered, catalog-compatible, and expose `capabilities.supportsStreaming` plus `synthesizeStream()`. Providers whose catalog entry advertises `supportsStreaming` (currently all five catalog providers: ElevenLabs, Fish Audio, Deepgram, xAI, and the managed Vellum provider) satisfy this requirement; a buffered-only provider would remain available for buffered message playback or other supported surfaces, but live voice reports a TTS error instead of silently falling back to buffered playback.
|
|
735
737
|
|
|
736
738
|
The `voiceFrontDoor` prompt skips current-turn legacy and v3 memory retrieval, while prior frozen memory cards and static memory context remain available. The front-door rule escalates rather than guessing when required personal context is absent. The escalated leg runs the ordinary memory pipeline against the latest visible caller prompt before the quality model, with low selector effort. This keeps memory work off the front-door TTFT path without cross-leg speculative state.
|
|
737
739
|
|
|
@@ -1294,9 +1296,8 @@ graph TB
|
|
|
1294
1296
|
RM_DIR["rmSync skill directory"]
|
|
1295
1297
|
end
|
|
1296
1298
|
|
|
1297
|
-
subgraph "
|
|
1298
|
-
|
|
1299
|
-
EVICT["Session eviction<br/>+ recreation"]
|
|
1299
|
+
subgraph "Capability reseed"
|
|
1300
|
+
RESEED["SKILL.md mtime poll<br/>reseeds capability cards"]
|
|
1300
1301
|
end
|
|
1301
1302
|
|
|
1302
1303
|
SNIPPET --> EVAL_TOOL
|
|
@@ -1309,14 +1310,12 @@ graph TB
|
|
|
1309
1310
|
SCAFFOLD --> MANAGED_STORE
|
|
1310
1311
|
MANAGED_STORE --> SKILL_DIR
|
|
1311
1312
|
|
|
1312
|
-
SKILL_DIR -->
|
|
1313
|
-
WATCHER --> EVICT
|
|
1314
|
-
|
|
1313
|
+
SKILL_DIR --> RESEED
|
|
1315
1314
|
SKILL_DIR --> SKILL_LOAD
|
|
1316
1315
|
SKILL_LOAD --> SESSION
|
|
1317
1316
|
|
|
1318
1317
|
DELETE --> RM_DIR
|
|
1319
|
-
RM_DIR -->
|
|
1318
|
+
RM_DIR --> RESEED
|
|
1320
1319
|
```
|
|
1321
1320
|
|
|
1322
1321
|
**Key design decisions:**
|
|
@@ -1324,7 +1323,7 @@ graph TB
|
|
|
1324
1323
|
- `evaluate_typescript_code` always forces `sandbox.enabled = true` regardless of global config.
|
|
1325
1324
|
- Snippet contract: must export `default` or `run` with signature `(input: unknown) => unknown | Promise<unknown>`.
|
|
1326
1325
|
- Managed-store writes are atomic (tmp file + rename) to prevent partial `SKILL.md` files.
|
|
1327
|
-
- After persist or delete,
|
|
1326
|
+
- After persist or delete, capability cards reseed from the `SKILL.md` set. The next turn continues in the same conversation.
|
|
1328
1327
|
- macOS UI shows Inspect and Delete controls for managed skills only (source = "managed").
|
|
1329
1328
|
- `skill_load` resolves the recursive include graph (via `include-graph.ts`) before emitting output. Missing children are listed as suggested skills without child `<loaded_skill>` markers; cycles still produce `isError: true` with no marker. Valid includes produce an "Included Skills (immediate)" metadata section showing child ID, name, description, and path.
|
|
1330
1329
|
|
|
@@ -1407,15 +1406,15 @@ skills/<skill-id>/
|
|
|
1407
1406
|
|
|
1408
1407
|
The following capabilities ship as bundled skills in `assistant/src/config/bundled-skills/`:
|
|
1409
1408
|
|
|
1410
|
-
| Skill ID | Tools
|
|
1411
|
-
| --------------- |
|
|
1412
|
-
| `browser` | `browser_navigate`, `browser_snapshot`, `browser_screenshot`, `browser_close`, `browser_click`, `browser_type`, `browser_press_key`, `browser_wait_for`, `browser_extract`, `browser_fill_credential`
|
|
1413
|
-
| `gmail` | Gmail search, archive, send, etc.
|
|
1414
|
-
| `computer-use` | `computer_use_observe`, `computer_use_click`, `computer_use_type_text`, `computer_use_key`, `computer_use_scroll`, `computer_use_drag`, `computer_use_wait`, `computer_use_open_app`, `computer_use_run_applescript`, `computer_use_done`, `computer_use_respond` | Computer-use proxy tools preactivated via `preactivatedSkillIds` in desktop sessions. Each tool forwards actions to a compatible connected desktop host via `HostCuProxy`, which handles request/resolve proxying, step counting, loop detection, and observation formatting in the same agent loop. |
|
|
1415
|
-
| `weather` | `get-weather`
|
|
1416
|
-
| `app-builder` | `app_create`, `app_delete`, `app_refresh`, `app_generate_icon`
|
|
1417
|
-
| `self-upgrade` | (instruction-only)
|
|
1418
|
-
| `start-the-day` | (instruction-only)
|
|
1409
|
+
| Skill ID | Tools | Purpose |
|
|
1410
|
+
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1411
|
+
| `browser` | `browser_navigate`, `browser_snapshot`, `browser_screenshot`, `browser_close`, `browser_click`, `browser_type`, `browser_press_key`, `browser_wait_for`, `browser_extract`, `browser_fill_credential` | Headless browser automation: web scraping, form filling, interaction (previously core-registered as `headless-browser`; now skill-provided with default allow rules) |
|
|
1412
|
+
| `gmail` | Gmail search, archive, send, etc. | Email management via OAuth2 integration |
|
|
1413
|
+
| `computer-use` | `computer_use_observe`, `computer_use_click`, `computer_use_type_text`, `computer_use_key`, `computer_use_scroll`, `computer_use_drag`, `computer_use_wait`, `computer_use_open_app`, `computer_use_run_applescript`, `computer_use_sequence`, `computer_use_done`, `computer_use_respond` | Computer-use proxy tools preactivated via `preactivatedSkillIds` in desktop sessions. Each tool forwards actions to a compatible connected desktop host via `HostCuProxy`, which handles request/resolve proxying, step counting, loop detection, and observation formatting in the same agent loop. |
|
|
1414
|
+
| `weather` | `get-weather` | Fetch current weather data |
|
|
1415
|
+
| `app-builder` | `app_create`, `app_delete`, `app_refresh`, `app_generate_icon` | Dynamic app authoring: create and manage persistent apps; file editing uses generic file tools plus `app_refresh` (activated via `skill_load app-builder`; `app_open` remains a core proxy tool) |
|
|
1416
|
+
| `self-upgrade` | (instruction-only) | Self-improvement workflow |
|
|
1417
|
+
| `start-the-day` | (instruction-only) | Morning briefing routine |
|
|
1419
1418
|
|
|
1420
1419
|
### Activation and Projection Flow
|
|
1421
1420
|
|
|
@@ -2192,7 +2191,7 @@ The `TtsUseCase` discriminator (`"phone-call"` or `"message-playback"`) lets pro
|
|
|
2192
2191
|
- **`native-twilio`** — the text-token path: spoken text is sent via `sendTextToken()`, which the media-stream transport re-synthesizes through daemon TTS. Collapsing this mode into `synthesized-play` is a documented deferred follow-up.
|
|
2193
2192
|
- **`synthesized-play`** — The assistant synthesises audio via the provider's HTTP API and streams it through the audio store / `sendPlayUrl()` path.
|
|
2194
2193
|
|
|
2195
|
-
**Phone call integration:** Phone calls run on the media-stream transport, where the daemon synthesises speech via the
|
|
2194
|
+
**Phone call integration:** Phone calls run on the media-stream transport, where the daemon synthesises speech via the effective TTS provider (the configured one after managed-speech defaulting, `resolveEffectiveSpeechProviders`, the same substitution live voice makes) and transcodes it to mu-law 8 kHz frames (`media-stream-output.ts`). Each catalog entry declares `mediaStreamPlayback.outputFormat` (`pcm`, `wav`, or `none`); `resolveTelephonyTtsCapability()` (`src/calls/telephony-tts-capability.ts`) combines that field with credential availability into a playable / not-playable verdict, and the call TTS resolver falls back to a credentialed playable provider rather than producing silence.
|
|
2196
2195
|
|
|
2197
2196
|
**Adding a new TTS provider (catalog-first checklist):**
|
|
2198
2197
|
|
package/Dockerfile
CHANGED
|
@@ -130,13 +130,13 @@ RUN bun run scripts/smoke-container-workspace-dependencies.ts
|
|
|
130
130
|
# The repo-root .dockerignore decides which skills (and files) ship.
|
|
131
131
|
COPY skills /app/skills
|
|
132
132
|
|
|
133
|
-
# Materialize the git-ignored offline
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
# Materialize the git-ignored offline marketplace and reviewed local packages.
|
|
134
|
+
# The build installs with --ignore-scripts, so the postinstall sync that creates
|
|
135
|
+
# these static imports in development never runs here.
|
|
136
|
+
COPY plugins /app/plugins
|
|
137
|
+
COPY meta/sync-bundled-copies.ts /app/meta/
|
|
138
|
+
RUN cd /app && bun run meta/sync-bundled-copies.ts --plugins-only && \
|
|
139
|
+
bun run assistant/scripts/generate-bundled-plugin-packages.ts
|
|
140
140
|
|
|
141
141
|
# Install assistant CLI launcher backed by the bundled assistant package
|
|
142
142
|
RUN printf '#!/usr/bin/env sh\nexec bun run /app/assistant/src/index.ts "$@"\n' > /usr/local/bin/assistant && \
|
|
@@ -552,6 +552,13 @@ Message content (stored as JSON `ContentBlock[]` in the DB) is flattened for the
|
|
|
552
552
|
|
|
553
553
|
Attachments are materialized into `conversations/<conversation>/attachments/` as soon as they are linked to a message. During disk-view sync, the JSONL record reuses those filenames directly and only falls back to materializing legacy rows that have not been projected yet. Filename collisions are still resolved by appending a numeric suffix (e.g., `photo-2.png`, `photo-3.png`).
|
|
554
554
|
|
|
555
|
+
Computer-use screenshot media is materialized while its tool-result row is
|
|
556
|
+
finalized, so earlier frames remain represented in tool history, JSONL, and
|
|
557
|
+
compaction inputs. The final screenshot-bearing invocation reuses that same
|
|
558
|
+
attachment ID for an additional reply link. A single attachment can therefore
|
|
559
|
+
appear on both a tool-result row and a reply row without creating a second
|
|
560
|
+
attachment-store object.
|
|
561
|
+
|
|
555
562
|
### Backfill Migration
|
|
556
563
|
|
|
557
564
|
Existing conversations created before the disk view was introduced are backfilled by workspace migration `009-backfill-conversation-disk-view`, which replays all conversations and their messages through the disk-view sync functions.
|
|
@@ -87,8 +87,17 @@ graph LR
|
|
|
87
87
|
nesting existed still parse, since an unindented body line that is not itself
|
|
88
88
|
entry-shaped is read as a continuation.
|
|
89
89
|
- **Consolidation** (`substrate/consolidation-job.ts`) is a background
|
|
90
|
-
agent conversation that files buffer entries into concept pages
|
|
91
|
-
the aggregate views
|
|
90
|
+
agent conversation that files buffer entries into concept pages and
|
|
91
|
+
rewrites the aggregate views. The agent never writes the buffer: the job
|
|
92
|
+
snapshots `buffer.md`, hands the run its pass's entries verbatim in the
|
|
93
|
+
prompt, and after the run removes exactly those entries itself through
|
|
94
|
+
`buffer-file.ts` (the module that also owns the append path, so the two
|
|
95
|
+
writers of the buffer share one protocol). Removal happens only when the
|
|
96
|
+
run's persisted messages hold a page-writing tool call with a non-error
|
|
97
|
+
result, the same evidence bar the retrospective's cursor advance uses; a
|
|
98
|
+
run that wrote nothing, failed, or timed out leaves the buffer intact for
|
|
99
|
+
the next pass. Entries deferred past the per-run cap and entries appended
|
|
100
|
+
while the run was in flight are therefore never lost. Scheduling
|
|
92
101
|
(`maybeEnqueueGraphMaintenanceJobs` in `jobs-worker.ts`):
|
|
93
102
|
- interval-based (`memory.v2.consolidation_interval_hours`, default 8h),
|
|
94
103
|
skipped below `MIN_BUFFER_LINES_FOR_CONSOLIDATION` (10) **unless** the
|
|
@@ -60,14 +60,21 @@ and restore the prior value afterwards, each guarding the restore so a turn that
|
|
|
60
60
|
started in between is not clobbered. They are supplying the acting actor for
|
|
61
61
|
their run, and are covered by this contract.
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
The queue drains are deliberately not in that set. `drainSingleMessage` and
|
|
64
|
+
`drainBatch` carry the queued sender on the per-turn field and into the run,
|
|
65
|
+
and leave the resting slot alone: at the point they stamp, the drain has not
|
|
66
|
+
yet proved it holds the processing lock. Its `isProcessing()` check is a
|
|
67
|
+
time-of-check guard whose documented backstop is the persist that can still
|
|
68
|
+
fail busy, and the requeue on that path restores the queue and the steer flag
|
|
69
|
+
only. A drain that stamped the slot would therefore leave the conversation
|
|
70
|
+
attributed to a sender whose turn never ran.
|
|
71
|
+
|
|
72
|
+
The consequence is that a cross-actor drain runs against history scoped for the
|
|
73
|
+
previous actor, because `ensureActorScopedHistory` reads the slot. That is a
|
|
74
|
+
real defect and it is LUM-3344's, which owns the fix: scope the transcript at
|
|
75
|
+
assembly time from the turn's actor, rather than mutating a shared transcript
|
|
76
|
+
and tracking who it was scoped for. Do not close it by making the drain stamp
|
|
77
|
+
the slot first.
|
|
71
78
|
|
|
72
79
|
`call-controller` keeps its own `trustContext` on its own object and never reads
|
|
73
80
|
the conversation's. It is outside this contract.
|
|
@@ -221,7 +221,7 @@ These invariants are enforced by guard tests and code review:
|
|
|
221
221
|
4. **Grants and audit logs are CES-internal**: The assistant cannot read CES grant tables or audit logs directly. CES exposes grant status and audit summaries via RPC responses.
|
|
222
222
|
5. **No generic authenticated HTTP clients in secure commands**: `curl`, `wget`, `httpie`, interpreters, and shell trampolines are structurally denied as secure command entrypoints. This is checked at manifest validation and re-checked at execution time.
|
|
223
223
|
6. **Managed CES container runs as non-root**: The CES Docker image runs as `uid 1001` (user `ces`). The CES data volume is owned by this user.
|
|
224
|
-
7. **
|
|
224
|
+
7. **Multi-connection bootstrap socket**: In managed mode, CES listens on the bootstrap socket as a concurrent multi-connection server and keeps the path bound. The assistant and its child processes each open their own RPC connection. CES is a long-lived sidecar: it stays up across assistant restarts and only exits on SIGTERM/SIGINT.
|
|
225
225
|
|
|
226
226
|
## Guarantees by deployment mode
|
|
227
227
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Virtual desktop browser CLI
|
|
2
|
+
|
|
3
|
+
`assistant browser --virtual-desktop` uses the browser CLI's shared operation handlers against the Chrome process owned by `DesktopSessionManager`. It requires a platform-hosted container, the `assistant-desktop` flag, completed automatic desktop installation and an identified guardian conversation. Availability is checked before starting or reusing control and after asynchronous startup; loss of the flag or installation readiness cancels active control. The first eligible browser command waits for the shared installation job, starts Chrome, and executes the original action exactly once. Cancellation and feature revocation stop the pending action while shared installation can finish for other viewers. Browser CLI requests allow ten minutes, with an eight-minute setup wait limit. Eligible web conversations receive browser guidance in the bash tool description, including the configured shell timeout; native clients retain their existing tool description. Opening the picture-in-picture panel also starts setup and shows progress automatically; failed installs retain a retry action. The persistent profile remains `data/desktop-profile`; no data migration or extension installation is required.
|
|
4
|
+
|
|
5
|
+
Automatic browser selection in platform-hosted web conversations uses the streamed Chrome when the desktop flag is enabled and the actor is an identified guardian. The macOS and Windows apps keep their existing browser selection and fallback behavior; they use the streamed desktop only with explicit `--virtual-desktop`. Their shared renderer reports a `web` transport, so selection also reads the active turn's frozen `clientOs`; it does not change transport identity or host capability checks. Explicit `--virtual-desktop`, `--browser-mode`, `--target-client-id` and active-tab requests override the default. Existing personal-browser sessions and tab pins remain on their selected browser. Tab commands use the same streamed-browser default as page commands. `--browser-mode local` selects assistant-side Playwright, not the user's Chrome.
|
|
6
|
+
|
|
7
|
+
The legacy `--desktop` option remains an alias. The deployment flag key `assistant-desktop`, API paths, sync tags and persistent profile path are unchanged for compatibility. The shared `isVirtualDesktopEnabled` gate rejects self-hosted assistants, including local Docker, for setup, streaming and control.
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
flowchart LR
|
|
11
|
+
CLI[assistant browser --virtual-desktop] --> IPC[Existing browser IPC routes]
|
|
12
|
+
IPC --> Lease[DesktopAutomationLease conversation and actor lease]
|
|
13
|
+
Lease --> Shared[Shared browser operation handlers]
|
|
14
|
+
Shared --> CDP[Scoped desktop CDP client]
|
|
15
|
+
CDP --> Chrome[Managed Chrome on display :99]
|
|
16
|
+
Chrome --> Stream[Existing desktop stream]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Chrome and its dock launcher share the managed profile and loopback debug port. For Chrome reopened from the dock, the profile singleton lock identifies a candidate PID, validated against the installed executable, profile and loopback debug arguments. Discovery checks `/proc` socket ownership against that browser PID, refuses redirects and validates the returned browser WebSocket endpoint. The connection stays within the container. No CDP endpoint or token is exposed to the renderer.
|
|
20
|
+
|
|
21
|
+
The desktop client bypasses personal-browser discovery, extension reconnect waits and backend fallback. It reuses the existing AX snapshot, DOM element resolution, mouse, keyboard, extraction and credential-fill implementations. Operation-scoped clients borrow the lease's connection; disposing one does not release the lease. `detach`, `close`, turn completion, cancellation, errors and idle expiry release control. Turn completion clears the activity indicator immediately and queues browser cleanup before the next automation session; it leaves Chrome and the current page open for the user. Only `tabs close` closes a Chrome tab.
|
|
22
|
+
|
|
23
|
+
`assistant browser --virtual-desktop screenshot --output /tmp/desktop-page.jpg` captures a color page image through CDP `Page.captureScreenshot`. It excludes the browser toolbar and desktop dock. `snapshot` returns semantic page structure. Agents should use these interfaces and let the manager start the desktop, including when older memory notes describe manual Xvnc, `xdotool` or scratch XWD conversion scripts.
|
|
24
|
+
|
|
25
|
+
Tab IDs are ephemeral numeric aliases for this managed browser's CDP target IDs. They are never personal extension tab IDs. Initial attachment selects an existing HTTP(S) page or opens a blank tab. Use `tabs list` and `tabs select --tab-id <id>` to choose explicitly. Navigation, tab selection, document replacement and release clear the desktop snapshot map. Personal-browser snapshots use a separate namespace.
|
|
26
|
+
|
|
27
|
+
CDP mouse events use page viewport CSS coordinates. Before dispatching them, the client animates a purple arrow overlay to the same point. The overlay is excluded from accessibility and hit testing. It appears in the existing desktop stream and is removed on release. It does not move the OS pointer, appear in browser toolbar UI or visualize every programmatic DOM operation. Native dialogs and other applications are outside the browser CLI; users can interact with them directly in the expanded desktop. The picture-in-picture preview is view-only. Direct user interaction does not pause automation. For logins, the assistant uses saved credentials first and securely collects missing credentials with `assistant credentials prompt`, then fills the login form itself. Every CAPTCHA and bot-detection challenge, including sliders and press-and-hold checks, is handed to the user before the assistant attempts it. When human interaction is needed, the assistant calls `ask_question` with `desktopHelp: { message, doneLabel, skipLabel }` in the user's language. The tool releases held browser input and reserves the desktop before publishing a question with `presentation: "virtual_desktop"`. The live viewer mounts only in the attended Electron window, with browser focus as a fallback on older shells and the web, so conversations release it when focus changes. A busy viewer offers Reconnect if the previous connection has not finished closing. The compact card lives in the scrolling message transcript, with expandable instructions and a preview capped at 384 pixels wide. It hosts the shared live viewer, with Step In opening its full desktop modal and Done or Skip resolving the existing question response. The assistant retains an exclusive human-help reservation while waiting. Done resumes the same conversation's automation lease for its fresh snapshot; Skip, closure, timeout and cancellation release it. The browser idle timer does not expire a pending human-help reservation. The live preview connects after Show live preview or Step In, and reuses an already-open picture-in-picture viewer. Other devices receiving the card do not automatically open a stream. When the request resolves, its interactive viewer closes or returns to the read-only PiP session that was open before the request. Skip does not imply the obstacle was resolved. Older clients show the same request as a normal Done/Skip question, with model-localized labels retained in history. Channels without dynamic UI return guidance to continue in the app rather than waiting on an unusable card.
|
|
28
|
+
|
|
29
|
+
The client records key and mouse presses before dispatch. On release it opens a fresh bounded cleanup connection, attaches to the same live targets, releases uncertain held input and removes overlays. A failed cleanup preserves state and the automation slot for retry. Turn-triggered cancellation retries cleanup automatically until it succeeds or ownership changes. Dispatched actions are never automatically retried. Closed targets need no input cleanup. Browser-process loss disposes the client, and later requests discover the replacement process.
|
|
30
|
+
|
|
31
|
+
`--use-active-tab` and personal browser targeting are rejected with `--virtual-desktop`. Download waiting is unsupported. Browser operations are bounded to two minutes and share the desktop lease's action budget and idle expiry.
|
|
32
|
+
|
|
33
|
+
Validation: focused client tests exercise shared snapshot/click behavior, namespace isolation, stale references, target changes, cancellation and uncertain-input cleanup. Lease tests cover browser ownership, cancellation and cleanup independently of native input. The Linux smoke script exercises real Chrome, the CLI and visible pointer feedback.
|
|
34
|
+
|
|
35
|
+
The desktop header icon pulses in the assistant's avatar accent color while a browser automation lease is active, including between browser commands. It shares the progress indicator's accent and neutral fallback. Reduced-motion clients show a solid accent. Setup status exposes the optional `automationActive` field; `desktop_activity_changed` events refresh it on acquisition and cancellation or release. Installation progress retains its `assistant:self:desktop` sync invalidations. The indicator reads status without starting installation, and reconnects refetch the current lease state.
|
|
@@ -72,6 +72,22 @@ it end to end:
|
|
|
72
72
|
same way a failed card edit does. The write-vs-resolve race converges
|
|
73
73
|
from the other side too: the feed writer re-checks canonical status
|
|
74
74
|
after its append.
|
|
75
|
+
- The receipt is the whole retire mechanism, so everything that must
|
|
76
|
+
stop happening lives in `writeGuardianFeedReceipt`: the terminal
|
|
77
|
+
`guardianRequest.status` withdraws every client affordance, urgency
|
|
78
|
+
drops to `medium` to leave the "Needs attention" treatment, and a
|
|
79
|
+
still-`new` item is marked `seen` (unread means the user has
|
|
80
|
+
something to review, which a resolved request is not). That clear
|
|
81
|
+
runs only on the edge into terminal, so re-running the fan-out
|
|
82
|
+
neither pulls a cleared receipt back into the bell nor undoes a user
|
|
83
|
+
who marked the receipt unread again.
|
|
84
|
+
- Terminal receipts that never passed the edge are cleared once for
|
|
85
|
+
each assistant by `healLegacyGuardianReceiptUnread`, which the sweep calls
|
|
86
|
+
ahead of its gateway read. One-shot rather than recurring: such a row
|
|
87
|
+
and a `new` the user set deliberately are indistinguishable, so a
|
|
88
|
+
completion sentinel in the daemon checkpoint ledger records the
|
|
89
|
+
boundary instead. The transition is re-evaluated inside the writer
|
|
90
|
+
queue and moves only `new`, exactly as the edge does.
|
|
75
91
|
- The feed writer's bulk-dismiss pass skips pending guardian items
|
|
76
92
|
(`isPendingGuardianFeedItem`), so "Clear all" can never retire an
|
|
77
93
|
unresolved request; only its receipt is clearable.
|
|
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
buildShellInvocation,
|
|
5
|
+
buildShellSpawnFlags,
|
|
5
6
|
pathListDelimiter,
|
|
6
7
|
prependUniquePathEntries,
|
|
7
8
|
} from "./shell.js";
|
|
@@ -38,6 +39,26 @@ describe("buildShellInvocation", () => {
|
|
|
38
39
|
});
|
|
39
40
|
});
|
|
40
41
|
|
|
42
|
+
describe("buildShellSpawnFlags", () => {
|
|
43
|
+
test("creates a POSIX process group and hides Windows consoles", () => {
|
|
44
|
+
expect(buildShellSpawnFlags("linux")).toEqual({
|
|
45
|
+
detached: true,
|
|
46
|
+
windowsHide: true,
|
|
47
|
+
});
|
|
48
|
+
expect(buildShellSpawnFlags("darwin")).toEqual({
|
|
49
|
+
detached: true,
|
|
50
|
+
windowsHide: true,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("does not detach Windows children that use piped stdio", () => {
|
|
55
|
+
expect(buildShellSpawnFlags("win32")).toEqual({
|
|
56
|
+
detached: false,
|
|
57
|
+
windowsHide: true,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
41
62
|
describe("path list handling", () => {
|
|
42
63
|
test("uses the platform delimiter", () => {
|
|
43
64
|
expect(pathListDelimiter("win32")).toBe(";");
|
|
@@ -5,6 +5,11 @@ export interface ShellInvocation {
|
|
|
5
5
|
args: string[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface ShellSpawnFlags {
|
|
9
|
+
detached: boolean;
|
|
10
|
+
windowsHide: true;
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
const WINDOWS_UTF8_PREAMBLE =
|
|
9
14
|
"try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}; " +
|
|
10
15
|
"$OutputEncoding = [System.Text.Encoding]::UTF8; " +
|
|
@@ -43,6 +48,25 @@ export function buildShellInvocation(
|
|
|
43
48
|
return { command: "bash", args: ["-c", "--", command] };
|
|
44
49
|
}
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Spawn flags for assistant-owned shell children (sandbox bash, local
|
|
53
|
+
* host_bash fallback, sanitized CLI bash, skill runners, scheduled scripts).
|
|
54
|
+
*
|
|
55
|
+
* POSIX uses a new process group so timeout/abort can SIGKILL the tree via
|
|
56
|
+
* `-pid`. Windows process trees are torn down with `taskkill /T`, which does
|
|
57
|
+
* not need a detached process. Combining `DETACHED_PROCESS`,
|
|
58
|
+
* `CREATE_NO_WINDOW`, and piped stdio on Windows can emit `close` with exit
|
|
59
|
+
* 0 and empty pipes without running the encoded command.
|
|
60
|
+
*/
|
|
61
|
+
export function buildShellSpawnFlags(
|
|
62
|
+
hostPlatform: NodeJS.Platform = process.platform,
|
|
63
|
+
): ShellSpawnFlags {
|
|
64
|
+
return {
|
|
65
|
+
detached: hostPlatform !== "win32",
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
46
70
|
export function pathListDelimiter(
|
|
47
71
|
hostPlatform: NodeJS.Platform = process.platform,
|
|
48
72
|
): string {
|
|
@@ -83,8 +83,14 @@ export const SourceMetadataSchema = z
|
|
|
83
83
|
clientTimezone: z.string().optional(),
|
|
84
84
|
/** Channel command intent (e.g. Telegram /start). */
|
|
85
85
|
commandIntent: CommandIntentSchema.optional(),
|
|
86
|
-
/**
|
|
87
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Whether the message addresses the assistant by name, an @-mention on
|
|
88
|
+
* the platforms that have one. Stated by the channel's normalizer only
|
|
89
|
+
* where it proved the answer; absent means "not established". Read to
|
|
90
|
+
* decide whether a reply is expected before any text exists, never to
|
|
91
|
+
* admit or deny: admission is the gate's job, upstream of this.
|
|
92
|
+
*/
|
|
93
|
+
botMentioned: z.boolean().optional(),
|
|
88
94
|
/**
|
|
89
95
|
* Slack-specific: the `edited.ts` float-string from a `message_changed`
|
|
90
96
|
* event. Used by the daemon to reject out-of-order edit deliveries whose
|
|
@@ -113,7 +113,7 @@ export async function buildSlackUserLabelMap(
|
|
|
113
113
|
// that label directly; only queue a lookup when the label is missing,
|
|
114
114
|
// empty, or ID-shaped. Mirrors the channel builder below.
|
|
115
115
|
const [, embeddedLabel] = splitSlackLabel(match[0].slice(1, -1));
|
|
116
|
-
const sanitizedEmbeddedLabel =
|
|
116
|
+
const sanitizedEmbeddedLabel = sanitizeEmbeddedSlackLabel(embeddedLabel);
|
|
117
117
|
if (sanitizedEmbeddedLabel && sanitizedEmbeddedLabel !== id) continue;
|
|
118
118
|
if (seen.has(id)) continue;
|
|
119
119
|
seen.add(id);
|
|
@@ -151,7 +151,7 @@ export async function buildSlackChannelLabelMap(
|
|
|
151
151
|
for (const match of text.matchAll(SLACK_CHANNEL_REFERENCE_RE)) {
|
|
152
152
|
const id = match[1];
|
|
153
153
|
const [, embeddedLabel] = splitSlackLabel(match[0].slice(1, -1));
|
|
154
|
-
const sanitizedEmbeddedLabel =
|
|
154
|
+
const sanitizedEmbeddedLabel = sanitizeEmbeddedSlackLabel(embeddedLabel);
|
|
155
155
|
if (sanitizedEmbeddedLabel && sanitizedEmbeddedLabel !== id) continue;
|
|
156
156
|
if (!seen.has(id)) {
|
|
157
157
|
seen.add(id);
|
|
@@ -192,9 +192,7 @@ function renderUserMention(
|
|
|
192
192
|
// prefer it over a lookup, mirroring renderChannelReference. The embedded
|
|
193
193
|
// label is Slack-sourced (part of the token), so entities decode before
|
|
194
194
|
// sanitization; the caller-resolved label below is not.
|
|
195
|
-
const embeddedLabel =
|
|
196
|
-
label === undefined ? undefined : decodeSlackHtmlEntities(label),
|
|
197
|
-
);
|
|
195
|
+
const embeddedLabel = sanitizeEmbeddedSlackLabel(label);
|
|
198
196
|
if (embeddedLabel && embeddedLabel !== id) {
|
|
199
197
|
return `@${embeddedLabel}`;
|
|
200
198
|
}
|
|
@@ -219,9 +217,7 @@ function renderChannelReference(
|
|
|
219
217
|
);
|
|
220
218
|
// The embedded label is Slack-sourced (part of the token), so entities
|
|
221
219
|
// decode before sanitization; the caller-resolved label below is not.
|
|
222
|
-
const embeddedLabel =
|
|
223
|
-
label === undefined ? undefined : decodeSlackHtmlEntities(label),
|
|
224
|
-
);
|
|
220
|
+
const embeddedLabel = sanitizeEmbeddedSlackLabel(label);
|
|
225
221
|
if (embeddedLabel && embeddedLabel !== channelId) {
|
|
226
222
|
return `#${embeddedLabel}`;
|
|
227
223
|
}
|
|
@@ -320,6 +316,15 @@ export function sanitizeSlackLabel(
|
|
|
320
316
|
return sanitized || undefined;
|
|
321
317
|
}
|
|
322
318
|
|
|
319
|
+
// Slack-sourced labels are decoded before validation in both lookup and render.
|
|
320
|
+
function sanitizeEmbeddedSlackLabel(
|
|
321
|
+
label: string | undefined,
|
|
322
|
+
): string | undefined {
|
|
323
|
+
return sanitizeOptionalLabel(
|
|
324
|
+
label === undefined ? undefined : decodeSlackHtmlEntities(label),
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
323
328
|
function sanitizeOptionalLabel(label: string | undefined): string | undefined {
|
|
324
329
|
return sanitizeSlackLabel(label);
|
|
325
330
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, test } from "bun:test";
|
|
3
|
+
import {
|
|
4
|
+
buildSlackChannelLabelMap,
|
|
5
|
+
buildSlackUserLabelMap,
|
|
6
|
+
renderSlackTextForModel,
|
|
7
|
+
} from "./index.js";
|
|
8
|
+
|
|
9
|
+
describe("Slack embedded-label lookup parity", () => {
|
|
10
|
+
const cases = [
|
|
11
|
+
{ id: "U123", prefix: "@", build: buildSlackUserLabelMap, mapKey: "userLabels" },
|
|
12
|
+
{
|
|
13
|
+
id: "C123",
|
|
14
|
+
prefix: "#",
|
|
15
|
+
build: buildSlackChannelLabelMap,
|
|
16
|
+
mapKey: "channelLabels",
|
|
17
|
+
},
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
for (const { id, prefix, build, mapKey } of cases) {
|
|
21
|
+
for (const label of ["<>", `<${id}>`, "< @# >"]) {
|
|
22
|
+
test(`${prefix} resolves label ${label} after Slack entity decoding`, async () => {
|
|
23
|
+
const text = `<${prefix}${id}|${label}>`;
|
|
24
|
+
const requested: string[] = [];
|
|
25
|
+
const labels = await build([text], async (value) => {
|
|
26
|
+
requested.push(value);
|
|
27
|
+
return "Example Name";
|
|
28
|
+
});
|
|
29
|
+
assert.deepEqual(requested, [id]);
|
|
30
|
+
assert.equal(
|
|
31
|
+
renderSlackTextForModel(text, { [mapKey]: labels }),
|
|
32
|
+
`${prefix}Example Name`,
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const label of ["<Example>", "R&D", "&lt;&gt;"]) {
|
|
38
|
+
test(`${prefix} keeps usable embedded label ${label} without lookup`, async () => {
|
|
39
|
+
const requested: string[] = [];
|
|
40
|
+
const text = `<${prefix}${id}|${label}>`;
|
|
41
|
+
const labels = await build([text], async (value) => {
|
|
42
|
+
requested.push(value);
|
|
43
|
+
return "Wrong Label";
|
|
44
|
+
});
|
|
45
|
+
assert.deepEqual(requested, []);
|
|
46
|
+
assert.deepEqual(labels, {});
|
|
47
|
+
const expected =
|
|
48
|
+
label === "<Example>"
|
|
49
|
+
? "Example"
|
|
50
|
+
: label === "R&D"
|
|
51
|
+
? "R&D"
|
|
52
|
+
: "<>";
|
|
53
|
+
assert.equal(
|
|
54
|
+
renderSlackTextForModel(text, { [mapKey]: labels }),
|
|
55
|
+
`${prefix}${expected}`,
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
test(`${prefix} deduplicates required lookups across encoded and bare mentions`, async () => {
|
|
61
|
+
const requested: string[] = [];
|
|
62
|
+
const labels = await build(
|
|
63
|
+
[`<${prefix}${id}|<>>`, `<${prefix}${id}>`],
|
|
64
|
+
async (value) => {
|
|
65
|
+
requested.push(value);
|
|
66
|
+
return "Example";
|
|
67
|
+
},
|
|
68
|
+
);
|
|
69
|
+
assert.deepEqual(requested, [id]);
|
|
70
|
+
assert.deepEqual(labels, { [id]: "Example" });
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test(`${prefix} does not decode caller-resolved entity text`, async () => {
|
|
74
|
+
const text = `<${prefix}${id}|<>>`;
|
|
75
|
+
const labels = await build([text], async () => "<Example>");
|
|
76
|
+
assert.equal(
|
|
77
|
+
renderSlackTextForModel(text, { [mapKey]: labels }),
|
|
78
|
+
`${prefix}<Example>`,
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test(`${prefix} preserves unknown fallback after a failed required lookup`, async () => {
|
|
83
|
+
let attempts = 0;
|
|
84
|
+
const text = `<${prefix}${id}|<>>`;
|
|
85
|
+
const labels = await build([text], async () => {
|
|
86
|
+
attempts++;
|
|
87
|
+
throw new Error("unavailable");
|
|
88
|
+
});
|
|
89
|
+
assert.equal(attempts, 1);
|
|
90
|
+
assert.deepEqual(labels, {});
|
|
91
|
+
const expected = prefix === "@" ? "@unknown-user" : "#unknown-channel";
|
|
92
|
+
assert.equal(renderSlackTextForModel(text, { [mapKey]: labels }), expected);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|