@vellumai/assistant 0.12.1 → 0.12.2-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/ARCHITECTURE.md +20 -21
- package/docs/architecture/turn-actor.md +15 -8
- package/docs/guardian-request-flow.md +16 -0
- package/openapi.yaml +327 -52
- package/package.json +3 -1
- package/scripts/smoke-desktop-window-theme.ts +186 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
- package/src/__tests__/anthropic-provider.test.ts +0 -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__/assistant-event-hub-machine-name.test.ts +6 -7
- package/src/__tests__/assistant-event-hub.test.ts +44 -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 +28 -29
- package/src/__tests__/config-watcher.test.ts +23 -8
- package/src/__tests__/connection-model-compat.test.ts +2 -2
- 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-skill-tools.test.ts +27 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
- 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-record-retire.test.ts +171 -1
- package/src/__tests__/credential-routes.test.ts +212 -3
- package/src/__tests__/credential-security-invariants.test.ts +4 -2
- package/src/__tests__/cu-unified-flow.test.ts +8 -2
- 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__/evict-conversations-for-reload.test.ts +1 -1
- package/src/__tests__/git-porcelain.test.ts +47 -0
- package/src/__tests__/heartbeat-service.test.ts +56 -40
- package/src/__tests__/helpers/set-workspace-mcp.ts +11 -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 +539 -0
- 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__/list-messages-camera-frame.test.ts +121 -0
- package/src/__tests__/llm-catalog-parity.test.ts +25 -0
- package/src/__tests__/mcp-auth-routes.test.ts +6 -9
- package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
- package/src/__tests__/mcp-health-check.test.ts +8 -11
- package/src/__tests__/mcp-list-plugin-servers.test.ts +8 -10
- 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-commands-routes.test.ts +113 -0
- package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
- package/src/__tests__/openai-provider.test.ts +1 -0
- package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
- 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 +14 -0
- package/src/__tests__/qdrant-manager.test.ts +132 -0
- package/src/__tests__/resolve-app.test.ts +135 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +229 -6
- package/src/__tests__/script-proxy-certs.test.ts +35 -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 +9 -4
- package/src/__tests__/source-fingerprint.test.ts +184 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +19 -3
- package/src/__tests__/subagent-tools.test.ts +3 -2
- package/src/__tests__/telephony-tts-guard.test.ts +38 -3
- package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
- package/src/__tests__/unicode.test.ts +13 -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__/agent-process.test.ts +258 -4
- package/src/acp/__tests__/auth-required.test.ts +96 -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__/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/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/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/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/types.ts +50 -5
- package/src/agent/loop.ts +1 -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/notification-intent.ts +2 -0
- package/src/api/events/user-message-echo.ts +7 -1
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +1 -1
- 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/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 +4 -4
- package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
- package/src/calls/__tests__/voice-control-protocol.test.ts +58 -25
- 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 +37 -1
- 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 +2 -2
- 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 +53 -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 +59 -46
- package/src/calls/voice-triage-escalate.ts +175 -56
- 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__/roadmap.help.test.ts +19 -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 +8 -13
- package/src/cli/commands/bash.ts +7 -25
- 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 +6 -2
- 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/roadmap.help.ts +5 -1
- package/src/cli/commands/roadmap.ts +1 -1
- package/src/cli/lib/bundled-marketplace.json +103 -90
- package/src/config/__tests__/default-profile-catalog.test.ts +22 -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/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 +22 -14
- package/src/config/bundled-skills/acp/TOOLS.json +5 -1
- 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 +20 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +99 -0
- 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 +3 -4
- package/src/config/bundled-skills/screen-annotation/SKILL.md +8 -1
- package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +6 -2
- 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 +24 -12
- package/src/config/loader.ts +1 -0
- 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/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/mcp.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +10 -0
- package/src/config/schemas/services.ts +8 -0
- package/src/config/schemas/skills.ts +0 -14
- package/src/config/schemas/voice.ts +150 -0
- package/src/credential-execution/process-manager.test.ts +18 -19
- package/src/credential-health/credential-health-service.ts +11 -17
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -121
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +4 -1
- package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
- package/src/daemon/app-change-notify.ts +45 -0
- package/src/daemon/config-watcher.ts +13 -194
- 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 +2 -1
- package/src/daemon/conversation-skill-tools.ts +13 -31
- package/src/daemon/conversation-store.ts +1 -1
- package/src/daemon/conversation-surfaces.ts +15 -9
- package/src/daemon/conversation-tool-setup.ts +37 -43
- package/src/daemon/conversation.ts +0 -3
- 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 +186 -19
- package/src/daemon/host-file-proxy.ts +8 -10
- package/src/daemon/host-proxy-preactivation.ts +2 -1
- package/src/daemon/host-transfer-proxy.ts +14 -18
- package/src/daemon/lifecycle.ts +0 -5
- package/src/daemon/mcp-reload-service.ts +5 -5
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/orphan-reaper.ts +1 -1
- package/src/daemon/providers-setup.ts +1 -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-side-effects.ts +7 -18
- package/src/desktop/__tests__/fake-desktop.ts +122 -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.ts +37 -0
- package/src/desktop/desktop-dependencies.test.ts +102 -0
- package/src/desktop/desktop-dependencies.ts +308 -0
- package/src/desktop/desktop-feature.test.ts +18 -0
- package/src/desktop/desktop-feature.ts +19 -0
- package/src/desktop/desktop-panel-config.test.ts +135 -0
- package/src/desktop/desktop-panel-config.ts +149 -0
- package/src/desktop/desktop-session-manager.test.ts +730 -0
- package/src/desktop/desktop-session-manager.ts +850 -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/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 +108 -0
- package/src/i18n/index.ts +16 -0
- package/src/i18n/locales.ts +93 -0
- package/src/i18n/messages.ts +61 -0
- package/src/i18n/title.ts +25 -0
- package/src/inbound/platform-callback-registration.ts +4 -5
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +15 -15
- package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
- package/src/live-voice/__tests__/live-voice-vad.test.ts +2 -2
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
- package/src/live-voice/live-voice-photo.ts +25 -6
- package/src/live-voice/live-voice-session.ts +213 -693
- package/src/live-voice/protocol.ts +0 -2
- package/src/mcp/__tests__/effective-config.test.ts +2 -2
- package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
- package/src/mcp/effective-config.ts +3 -3
- package/src/mcp/mcp-header-store.ts +29 -45
- package/src/mcp/spec-schema.ts +111 -0
- package/src/mcp/startup.ts +8 -4
- package/src/mcp/workspace-mcp-config.ts +188 -0
- 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__/workspace-git-heartbeat.test.ts +8 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -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/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 +66 -22
- package/src/oauth/AGENTS.md +2 -0
- package/src/oauth/__tests__/seed-providers-managed.test.ts +54 -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 +73 -0
- package/src/oauth/connection-resolver.ts +95 -2
- package/src/oauth/scope-utils.ts +24 -0
- package/src/oauth/seed-providers.ts +204 -25
- package/src/outbound-proxy/certs.ts +3 -5
- package/src/permissions/checker.test.ts +11 -6
- package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
- package/src/persistence/conversation-crud.ts +71 -63
- package/src/persistence/conversation-lineage.ts +12 -4
- 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/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/__tests__/157-invite-contact-id.test.ts +149 -0
- package/src/persistence/schema/memory-core.ts +5 -0
- 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/index.ts +1 -0
- package/src/plugin-api/types.ts +2 -0
- package/src/plugins/defaults/index.ts +2 -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 +20 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +5 -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__/shutdown-hook.test.ts +4 -0
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -2
- package/src/plugins/defaults/memory/context-search/format.ts +3 -2
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +6 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +3 -2
- package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -7
- 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/host-utils.ts +10 -0
- 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 +12 -3
- 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/skill-md-mtime-poll.ts +9 -0
- package/src/plugins/defaults/memory/startup.ts +28 -2
- package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
- package/src/plugins/defaults/memory/substrate/page-index.ts +6 -1
- package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -2
- package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
- package/src/plugins/defaults/memory/v2/reranker.ts +6 -1
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -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 +30 -0
- package/src/plugins/defaults/memory/v3/card.ts +3 -2
- package/src/plugins/defaults/memory/v3/pool-select.ts +5 -3
- package/src/plugins/defaults/memory/v3/sections.ts +9 -3
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +5 -2
- package/src/plugins/defaults/memory/worker.ts +6 -0
- package/src/plugins/mcp-servers.ts +15 -75
- 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 +42 -3
- package/src/providers/inference/auth.ts +2 -3
- package/src/providers/inference/connection-availability.ts +27 -8
- package/src/providers/inference/endpoint-probe.ts +10 -1
- package/src/providers/inference/resolve-auth.ts +22 -4
- package/src/providers/inference/service-account-token.ts +248 -0
- package/src/providers/model-catalog.ts +34 -0
- 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/opencode/client.test.ts +73 -4
- package/src/providers/opencode/client.ts +60 -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/unparseable-tool-args.ts +5 -1
- package/src/runtime/AGENTS.md +3 -1
- package/src/runtime/__tests__/channel-send.test.ts +443 -0
- package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +89 -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 +2 -1
- 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/host-observe.ts +11 -1
- package/src/runtime/http-server.ts +160 -151
- package/src/runtime/routes/__tests__/acp-routes.test.ts +159 -4
- package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +205 -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__/mcp-add-default-risk.test.ts +16 -12
- package/src/runtime/routes/acp-routes.test.ts +15 -0
- package/src/runtime/routes/acp-routes.ts +72 -9
- package/src/runtime/routes/app-management-routes.ts +73 -0
- package/src/runtime/routes/app-routes.ts +1 -1
- 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 +16 -3
- package/src/runtime/routes/credential-routes.ts +19 -10
- package/src/runtime/routes/desktop-setup-routes.test.ts +74 -0
- package/src/runtime/routes/desktop-setup-routes.ts +35 -0
- package/src/runtime/routes/diagnostics-routes.ts +61 -4
- package/src/runtime/routes/events-routes.ts +4 -0
- package/src/runtime/routes/host-cu-routes.ts +6 -0
- package/src/runtime/routes/index.ts +4 -2
- package/src/runtime/routes/log-export-routes.ts +2 -0
- package/src/runtime/routes/mcp-auth-routes.ts +39 -47
- package/src/runtime/routes/migration-routes.ts +6 -20
- package/src/runtime/routes/oauth-commands-routes.ts +36 -0
- package/src/runtime/routes/platform-routes.ts +18 -15
- 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 +2 -1
- package/src/schedule/run-script.ts +2 -1
- package/src/schedule/schedule-store.ts +9 -2
- package/src/schedule/worker.ts +1 -1
- 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/untrusted-content.ts +3 -1
- package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
- 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 +94 -0
- package/src/tools/acp/status.ts +40 -3
- package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
- 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 +121 -2
- 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 +4 -20
- package/src/tools/network/web-search.ts +6 -1
- package/src/tools/policy-context.ts +6 -7
- package/src/tools/skills/scaffold-managed.ts +61 -3
- package/src/tools/subagent/spawn.ts +5 -8
- package/src/tools/terminal/__tests__/sanitized-bash.test.ts +57 -0
- package/src/tools/terminal/sanitized-bash.ts +105 -0
- 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/ca-bundle.ts +13 -0
- package/src/util/language-subtag.ts +16 -0
- package/src/util/platform.ts +8 -0
- package/src/util/unicode.ts +15 -1
- 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
|
@@ -4,25 +4,30 @@ import type { CliCommandHelp } from "../lib/cli-command-help.js";
|
|
|
4
4
|
|
|
5
5
|
export const appsHelp: CliCommandHelp = {
|
|
6
6
|
name: "apps",
|
|
7
|
-
description: "
|
|
7
|
+
description: "List, inspect, and compile apps",
|
|
8
8
|
helpText: `
|
|
9
9
|
Apps are mini-applications the assistant can surface. Each has a name and a
|
|
10
10
|
source directory holding its HTML/TSX definition, pages, and records.
|
|
11
11
|
|
|
12
12
|
Apps come from two places, distinguished by their source path:
|
|
13
|
-
workspace User-created apps under the workspace apps directory
|
|
14
|
-
(~/.vellum/apps/<slug>/).
|
|
13
|
+
workspace User-created apps under the workspace apps directory.
|
|
15
14
|
plugin Apps bundled by an installed plugin, each a directory under
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
the plugin's apps/ folder. Stray directories without a plugin
|
|
16
|
+
package.json, and disabled plugins, contribute nothing.
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
Create and delete workspace apps through the app-builder skill and its tools
|
|
19
|
+
(app_create, app_delete). This command lists apps, inspects whether source
|
|
20
|
+
has changed since the last compile, and compiles an app once you are done
|
|
21
|
+
editing. File edits do not compile on their own.
|
|
22
|
+
|
|
23
|
+
list and inspect read the workspace directly (the assistant does not need to
|
|
24
|
+
be running). refresh compiles inside the running assistant so open surfaces
|
|
25
|
+
pick up the new build, including plugin apps with local source changes.
|
|
22
26
|
|
|
23
27
|
Examples:
|
|
24
28
|
$ assistant apps list
|
|
25
|
-
$ assistant apps
|
|
29
|
+
$ assistant apps inspect Budget
|
|
30
|
+
$ assistant apps refresh Budget`,
|
|
26
31
|
subcommands: [
|
|
27
32
|
{
|
|
28
33
|
name: "list",
|
|
@@ -31,10 +36,10 @@ Examples:
|
|
|
31
36
|
{ flags: "--json", description: "Machine-readable JSON output" },
|
|
32
37
|
],
|
|
33
38
|
helpText: `
|
|
34
|
-
Lists every app with its name and the absolute path to its source directory
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
Lists every app with its name and the absolute path to its source directory.
|
|
40
|
+
The path itself shows whether the app is a workspace app or bundled by a
|
|
41
|
+
plugin. Workspace apps are listed first, then plugin-bundled apps; both are
|
|
42
|
+
sorted by name.
|
|
38
43
|
|
|
39
44
|
Pass --json for machine-readable output.
|
|
40
45
|
|
|
@@ -42,5 +47,54 @@ Examples:
|
|
|
42
47
|
$ assistant apps list
|
|
43
48
|
$ assistant apps list --json`,
|
|
44
49
|
},
|
|
50
|
+
{
|
|
51
|
+
name: "inspect",
|
|
52
|
+
args: "<app_name>",
|
|
53
|
+
description:
|
|
54
|
+
"Show whether an app's source has changed since the last compile",
|
|
55
|
+
options: [
|
|
56
|
+
{ flags: "--json", description: "Machine-readable JSON output" },
|
|
57
|
+
],
|
|
58
|
+
helpText: `
|
|
59
|
+
Arguments:
|
|
60
|
+
app_name App display name, directory slug, or id. Run 'assistant apps list'
|
|
61
|
+
to see available apps.
|
|
62
|
+
|
|
63
|
+
Compares the on-disk source against the fingerprint recorded in dist/ at the
|
|
64
|
+
last successful compile. Reports clean (no changes), stale (source drifted),
|
|
65
|
+
never compiled, or unknown baseline (compiled before fingerprints existed).
|
|
66
|
+
|
|
67
|
+
Does not compile. Use 'assistant apps refresh <app_name>' after inspect when
|
|
68
|
+
source has changed.
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
$ assistant apps inspect Budget
|
|
72
|
+
$ assistant apps inspect Budget --json`,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "refresh",
|
|
76
|
+
args: "<app_name>",
|
|
77
|
+
description:
|
|
78
|
+
"Compile an app and refresh open surfaces. Requires a running assistant",
|
|
79
|
+
options: [
|
|
80
|
+
{ flags: "--json", description: "Machine-readable JSON output" },
|
|
81
|
+
],
|
|
82
|
+
helpText: `
|
|
83
|
+
Arguments:
|
|
84
|
+
app_name App display name, directory slug, or id. Run 'assistant apps list'
|
|
85
|
+
to see available apps.
|
|
86
|
+
|
|
87
|
+
Compiles src/ into dist/ inside the running assistant, then refreshes any
|
|
88
|
+
open surfaces and published deployments. Call this once after a batch of
|
|
89
|
+
edits, not after every file write. Workspace and plugin apps are both
|
|
90
|
+
accepted so local plugin source changes can be compiled without waiting
|
|
91
|
+
for the plugin watcher.
|
|
92
|
+
|
|
93
|
+
The assistant must be running.
|
|
94
|
+
|
|
95
|
+
Examples:
|
|
96
|
+
$ assistant apps refresh Budget
|
|
97
|
+
$ assistant apps refresh Budget --json`,
|
|
98
|
+
},
|
|
45
99
|
],
|
|
46
100
|
};
|
package/src/cli/commands/apps.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
cliIpcCall,
|
|
5
|
+
exitCodeFromIpcResult,
|
|
6
|
+
} from "../../ipc/cli-client.js";
|
|
3
7
|
import { applyCommandHelp, subcommand } from "../lib/cli-command-help.js";
|
|
4
8
|
import { registerCommand } from "../lib/register-command.js";
|
|
5
9
|
import { log } from "../logger.js";
|
|
10
|
+
import { shouldOutputJson, writeError, writeOutput } from "../output.js";
|
|
6
11
|
import { appsHelp } from "./apps.help.js";
|
|
7
12
|
|
|
8
13
|
interface AppListEntry {
|
|
@@ -10,6 +15,36 @@ interface AppListEntry {
|
|
|
10
15
|
source: string;
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
interface AppsRefreshResponse {
|
|
19
|
+
ok: true;
|
|
20
|
+
appId: string;
|
|
21
|
+
name: string;
|
|
22
|
+
compiled: boolean;
|
|
23
|
+
compile_duration_ms: number;
|
|
24
|
+
compile_errors?: Array<{
|
|
25
|
+
text: string;
|
|
26
|
+
location?: { file: string; line: number; column: number };
|
|
27
|
+
}>;
|
|
28
|
+
compile_warnings?: Array<{
|
|
29
|
+
text: string;
|
|
30
|
+
location?: { file: string; line: number; column: number };
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function refreshHint(appId: string): string {
|
|
35
|
+
return `Run 'assistant apps refresh ${appId}' to compile.`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function formatDiagnostic(diag: {
|
|
39
|
+
text: string;
|
|
40
|
+
location?: { file: string; line: number; column: number };
|
|
41
|
+
}): string {
|
|
42
|
+
if (!diag.location) {
|
|
43
|
+
return diag.text;
|
|
44
|
+
}
|
|
45
|
+
return `${diag.location.file}:${diag.location.line}: ${diag.text}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
13
48
|
export function registerAppsCommand(program: Command): void {
|
|
14
49
|
registerCommand(program, {
|
|
15
50
|
name: appsHelp.name,
|
|
@@ -46,6 +81,154 @@ export function registerAppsCommand(program: Command): void {
|
|
|
46
81
|
log.info(` ${e.name.padEnd(nameWidth)} ${e.source}`);
|
|
47
82
|
}
|
|
48
83
|
});
|
|
84
|
+
|
|
85
|
+
subcommand(apps, "inspect").action(
|
|
86
|
+
async (appName: string, opts: { json?: boolean }, cmd: Command) => {
|
|
87
|
+
const { resolveAppQuery, appNotFoundMessage, appAmbiguousMessage } =
|
|
88
|
+
await import("../../apps/resolve-app.js");
|
|
89
|
+
const { inspectAppSource } = await import(
|
|
90
|
+
"../../apps/source-fingerprint.js"
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const resolved = resolveAppQuery(appName);
|
|
94
|
+
if (!resolved.ok) {
|
|
95
|
+
const message =
|
|
96
|
+
resolved.reason === "ambiguous"
|
|
97
|
+
? appAmbiguousMessage(resolved.query, resolved.matches)
|
|
98
|
+
: appNotFoundMessage(resolved.query);
|
|
99
|
+
writeError(cmd, message);
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const { app } = resolved;
|
|
105
|
+
const inspect = inspectAppSource(app.sourcePath);
|
|
106
|
+
const origin =
|
|
107
|
+
app.origin.kind === "plugin"
|
|
108
|
+
? { kind: "plugin" as const, plugin: app.origin.pluginName }
|
|
109
|
+
: { kind: "workspace" as const };
|
|
110
|
+
|
|
111
|
+
if (opts.json || shouldOutputJson(cmd)) {
|
|
112
|
+
writeOutput(cmd, {
|
|
113
|
+
ok: true,
|
|
114
|
+
app: {
|
|
115
|
+
id: app.id,
|
|
116
|
+
name: app.name,
|
|
117
|
+
source: app.sourcePath,
|
|
118
|
+
origin,
|
|
119
|
+
},
|
|
120
|
+
compile: inspect,
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const originLabel =
|
|
126
|
+
origin.kind === "plugin"
|
|
127
|
+
? `plugin ${origin.plugin}`
|
|
128
|
+
: "workspace";
|
|
129
|
+
log.info(`App: ${app.name} (${originLabel})`);
|
|
130
|
+
log.info(`Id: ${app.id}`);
|
|
131
|
+
log.info(`Source: ${app.sourcePath}`);
|
|
132
|
+
|
|
133
|
+
if (inspect.status === "clean") {
|
|
134
|
+
const when = inspect.compiledAt
|
|
135
|
+
? ` (compiled ${inspect.compiledAt})`
|
|
136
|
+
: "";
|
|
137
|
+
log.info(`Compile: up to date${when}`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (inspect.status === "never_compiled") {
|
|
141
|
+
log.info("Compile: never compiled");
|
|
142
|
+
log.info(refreshHint(app.id));
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (inspect.status === "unknown_baseline") {
|
|
146
|
+
log.info(
|
|
147
|
+
"Compile: compiled, but no source fingerprint is recorded.",
|
|
148
|
+
);
|
|
149
|
+
log.info(
|
|
150
|
+
`Run 'assistant apps refresh ${app.id}' to record one and rebuild.`,
|
|
151
|
+
);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const when = inspect.compiledAt
|
|
156
|
+
? ` (last compiled ${inspect.compiledAt})`
|
|
157
|
+
: "";
|
|
158
|
+
log.info(`Compile: source changed since last compile${when}`);
|
|
159
|
+
if (inspect.modified.length > 0) {
|
|
160
|
+
log.info("Modified:");
|
|
161
|
+
for (const path of inspect.modified) {
|
|
162
|
+
log.info(` ${path}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (inspect.added.length > 0) {
|
|
166
|
+
log.info("Added:");
|
|
167
|
+
for (const path of inspect.added) {
|
|
168
|
+
log.info(` ${path}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (inspect.removed.length > 0) {
|
|
172
|
+
log.info("Removed:");
|
|
173
|
+
for (const path of inspect.removed) {
|
|
174
|
+
log.info(` ${path}`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
log.info(refreshHint(app.id));
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
subcommand(apps, "refresh").action(
|
|
182
|
+
async (appName: string, opts: { json?: boolean }, cmd: Command) => {
|
|
183
|
+
const { resolveAppQuery, appNotFoundMessage, appAmbiguousMessage } =
|
|
184
|
+
await import("../../apps/resolve-app.js");
|
|
185
|
+
|
|
186
|
+
const resolved = resolveAppQuery(appName);
|
|
187
|
+
if (!resolved.ok) {
|
|
188
|
+
const message =
|
|
189
|
+
resolved.reason === "ambiguous"
|
|
190
|
+
? appAmbiguousMessage(resolved.query, resolved.matches)
|
|
191
|
+
: appNotFoundMessage(resolved.query);
|
|
192
|
+
writeError(cmd, message);
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const result = await cliIpcCall<AppsRefreshResponse>("apps_refresh", {
|
|
198
|
+
pathParams: { id: resolved.app.id },
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (!result.ok || !result.result) {
|
|
202
|
+
writeError(cmd, result.error ?? "Refresh failed");
|
|
203
|
+
process.exitCode = exitCodeFromIpcResult(result);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const payload = result.result;
|
|
208
|
+
if (opts.json || shouldOutputJson(cmd)) {
|
|
209
|
+
writeOutput(cmd, payload);
|
|
210
|
+
if (!payload.compiled) {
|
|
211
|
+
process.exitCode = 1;
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (!payload.compiled) {
|
|
217
|
+
log.error(
|
|
218
|
+
`Compile failed for "${payload.name}" (${payload.compile_duration_ms}ms).`,
|
|
219
|
+
);
|
|
220
|
+
for (const diag of payload.compile_errors ?? []) {
|
|
221
|
+
log.error(` ${formatDiagnostic(diag)}`);
|
|
222
|
+
}
|
|
223
|
+
process.exitCode = 1;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
log.info(
|
|
228
|
+
`Compiled "${payload.name}" in ${payload.compile_duration_ms}ms.`,
|
|
229
|
+
);
|
|
230
|
+
},
|
|
231
|
+
);
|
|
49
232
|
},
|
|
50
233
|
});
|
|
51
234
|
}
|
|
@@ -6,7 +6,7 @@ export const bashHelp: CliCommandHelp = {
|
|
|
6
6
|
name: "bash",
|
|
7
7
|
args: "<command>",
|
|
8
8
|
description:
|
|
9
|
-
"Execute a shell command
|
|
9
|
+
"Execute a shell command with the same sanitized environment as the bash tool",
|
|
10
10
|
options: [
|
|
11
11
|
{
|
|
12
12
|
flags: "-t, --timeout <ms>",
|
|
@@ -15,24 +15,19 @@ export const bashHelp: CliCommandHelp = {
|
|
|
15
15
|
},
|
|
16
16
|
],
|
|
17
17
|
helpText: `
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
observes shell commands. The command runs with the assistant's environment, working
|
|
24
|
-
directory, and process context — not the caller's shell.
|
|
25
|
-
|
|
26
|
-
Requires the assistant to be running with VELLUM_DEBUG=1. When debug mode is off
|
|
27
|
-
(the default), the assistant returns an error immediately.
|
|
18
|
+
Spawns the command with the same sanitized environment, working directory,
|
|
19
|
+
and platform shell the bash tool uses for tool-call subprocesses. Vault
|
|
20
|
+
bearers such as CES_SERVICE_TOKEN are stripped; CES_LOCAL_SOCKET and workspace
|
|
21
|
+
paths are forwarded. The command does not go through the assistant HTTP or IPC
|
|
22
|
+
API, and does not require a running assistant process.
|
|
28
23
|
|
|
29
24
|
Arguments:
|
|
30
25
|
command The shell command string to execute (e.g. "echo hello", "ls -la").
|
|
31
|
-
Runs
|
|
26
|
+
Runs via the same platform shell invocation the bash tool uses.
|
|
32
27
|
|
|
33
28
|
Examples:
|
|
34
29
|
$ assistant bash "echo hello"
|
|
35
30
|
$ assistant bash "which node"
|
|
36
31
|
$ assistant bash "env | grep PATH" --timeout 10000
|
|
37
|
-
$ assistant bash "
|
|
32
|
+
$ assistant bash "assistant oauth request --provider outlook --json https://graph.microsoft.com/v1.0/me"`,
|
|
38
33
|
};
|
package/src/cli/commands/bash.ts
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `assistant bash`
|
|
3
|
-
*
|
|
2
|
+
* `assistant bash` runs a shell command with the same sanitized environment
|
|
3
|
+
* the bash tool forwards to tool-call subprocesses.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { Command } from "commander";
|
|
7
7
|
|
|
8
|
-
import { cliIpcCall } from "../../ipc/cli-client.js";
|
|
9
8
|
import { applyCommandHelp, commandSpec } from "../lib/cli-command-help.js";
|
|
10
9
|
import { registerCommand } from "../lib/register-command.js";
|
|
11
10
|
import { log } from "../logger.js";
|
|
12
11
|
import { bashHelp } from "./bash.help.js";
|
|
13
12
|
|
|
14
|
-
interface DebugBashResult {
|
|
15
|
-
stdout: string;
|
|
16
|
-
stderr: string;
|
|
17
|
-
exitCode: number | null;
|
|
18
|
-
timedOut: boolean;
|
|
19
|
-
error?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
13
|
export function registerBashCommand(program: Command): void {
|
|
23
14
|
registerCommand(program, {
|
|
24
15
|
name: commandSpec(bashHelp),
|
|
25
|
-
transport: "
|
|
16
|
+
transport: "local",
|
|
26
17
|
description: bashHelp.description,
|
|
27
18
|
build: (cmd) => {
|
|
28
19
|
applyCommandHelp(cmd, bashHelp);
|
|
@@ -34,19 +25,10 @@ export function registerBashCommand(program: Command): void {
|
|
|
34
25
|
return;
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
const
|
|
38
|
-
"
|
|
39
|
-
{ body: { command, timeoutMs } },
|
|
40
|
-
{ timeoutMs: timeoutMs + 10_000 },
|
|
28
|
+
const { runSanitizedBash } = await import(
|
|
29
|
+
"../../tools/terminal/sanitized-bash.js"
|
|
41
30
|
);
|
|
42
|
-
|
|
43
|
-
if (!result.ok) {
|
|
44
|
-
log.error(result.error ?? "Failed to reach the assistant.");
|
|
45
|
-
process.exitCode = 1;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const data = result.result!;
|
|
31
|
+
const data = await runSanitizedBash(command, timeoutMs);
|
|
50
32
|
|
|
51
33
|
if (data.error) {
|
|
52
34
|
log.error(data.error);
|
|
@@ -69,7 +51,7 @@ export function registerBashCommand(program: Command): void {
|
|
|
69
51
|
}
|
|
70
52
|
|
|
71
53
|
if (data.timedOut) {
|
|
72
|
-
log.info(
|
|
54
|
+
log.info("Command timed out.");
|
|
73
55
|
}
|
|
74
56
|
|
|
75
57
|
if (data.exitCode != null && data.exitCode !== 0) {
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
// The command is a door onto the daemon's one send implementation, so what
|
|
4
|
+
// matters is the request it hands the route and what it does with the
|
|
5
|
+
// answer. IPC is stubbed to capture that request; the exit-code helper
|
|
6
|
+
// stays real, so the tests assert the mapping that ships.
|
|
7
|
+
|
|
8
|
+
const ipcCalls: Array<{
|
|
9
|
+
method: string;
|
|
10
|
+
params: Record<string, unknown>;
|
|
11
|
+
opts?: Record<string, unknown>;
|
|
12
|
+
}> = [];
|
|
13
|
+
let ipcResult: Record<string, unknown> = {
|
|
14
|
+
ok: true,
|
|
15
|
+
result: {
|
|
16
|
+
channel: "slack",
|
|
17
|
+
chatId: "C0123456789",
|
|
18
|
+
messageIds: ["1700000000.000100"],
|
|
19
|
+
lastMessageId: "1700000000.000100",
|
|
20
|
+
recordedIn: "conv-home",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const actualCliClient = await import("../../../../ipc/cli-client.js");
|
|
25
|
+
mock.module("../../../../ipc/cli-client.js", () => ({
|
|
26
|
+
...actualCliClient,
|
|
27
|
+
cliIpcCall: async (
|
|
28
|
+
method: string,
|
|
29
|
+
params: Record<string, unknown>,
|
|
30
|
+
opts?: Record<string, unknown>,
|
|
31
|
+
) => {
|
|
32
|
+
ipcCalls.push({ method, params, ...(opts ? { opts } : {}) });
|
|
33
|
+
return ipcResult;
|
|
34
|
+
},
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
// Imported after the mock is installed, so the command module under test
|
|
38
|
+
// binds the stubbed IPC call rather than the real one.
|
|
39
|
+
const { runCliCommand } = await import("../../__tests__/cli-test-harness.js");
|
|
40
|
+
const { registerChannelsCommand } = await import("../index.js");
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
ipcCalls.length = 0;
|
|
44
|
+
ipcResult = {
|
|
45
|
+
ok: true,
|
|
46
|
+
result: {
|
|
47
|
+
channel: "slack",
|
|
48
|
+
chatId: "C0123456789",
|
|
49
|
+
messageIds: ["1700000000.000100"],
|
|
50
|
+
lastMessageId: "1700000000.000100",
|
|
51
|
+
recordedIn: "conv-home",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// The shipped registration as-is: `send` declares its own `--json`, which is
|
|
57
|
+
// why the program's global leaf-option pass skips it.
|
|
58
|
+
function runSend(args: string[]) {
|
|
59
|
+
return runCliCommand(registerChannelsCommand, ["channels", "send", ...args]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The body the command handed the route on its one call. */
|
|
63
|
+
function sentBody(): Record<string, unknown> {
|
|
64
|
+
expect(ipcCalls).toHaveLength(1);
|
|
65
|
+
expect(ipcCalls[0]!.method).toBe("channels_send_post");
|
|
66
|
+
return ipcCalls[0]!.params.body as Record<string, unknown>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
describe("the request the command makes", () => {
|
|
70
|
+
test("names the chat and asks for the channel's rich rendering", async () => {
|
|
71
|
+
const r = await runSend([
|
|
72
|
+
"slack",
|
|
73
|
+
"C0123456789",
|
|
74
|
+
"--text",
|
|
75
|
+
"deploy is green",
|
|
76
|
+
]);
|
|
77
|
+
expect(r.exitCode).toBe(0);
|
|
78
|
+
expect(sentBody()).toEqual({
|
|
79
|
+
channel: "slack",
|
|
80
|
+
target: { kind: "chat", chatId: "C0123456789" },
|
|
81
|
+
text: "deploy is green",
|
|
82
|
+
renderRichly: true,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("carries a named thread as the target's thread", async () => {
|
|
87
|
+
await runSend([
|
|
88
|
+
"slack",
|
|
89
|
+
"C0123456789",
|
|
90
|
+
"--thread",
|
|
91
|
+
"1700000000.000001",
|
|
92
|
+
"--text",
|
|
93
|
+
"and the smoke tests passed",
|
|
94
|
+
]);
|
|
95
|
+
expect(sentBody().target).toEqual({
|
|
96
|
+
kind: "chat",
|
|
97
|
+
chatId: "C0123456789",
|
|
98
|
+
threadId: "1700000000.000001",
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("--plain asks for the text verbatim", async () => {
|
|
103
|
+
await runSend(["telegram", "123456789", "--text", "morning", "--plain"]);
|
|
104
|
+
const body = sentBody();
|
|
105
|
+
expect(body.renderRichly).toBeUndefined();
|
|
106
|
+
expect(body.channel).toBe("telegram");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("sends the text as the caller wrote it, whitespace included", async () => {
|
|
110
|
+
await runSend([
|
|
111
|
+
"slack",
|
|
112
|
+
"C0123456789",
|
|
113
|
+
"--text",
|
|
114
|
+
" indented ",
|
|
115
|
+
"--plain",
|
|
116
|
+
]);
|
|
117
|
+
expect(sentBody().text).toBe(" indented ");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("waits longer than the IPC default, since the send itself retries", async () => {
|
|
121
|
+
await runSend(["slack", "C0123456789", "--text", "hi"]);
|
|
122
|
+
expect(ipcCalls[0]!.opts).toMatchObject({ timeoutMs: 120_000 });
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("refuses an empty text before it sends anything", async () => {
|
|
126
|
+
for (const args of [
|
|
127
|
+
["slack", "C0123456789"],
|
|
128
|
+
["slack", "C0123456789", "--text", " "],
|
|
129
|
+
]) {
|
|
130
|
+
ipcCalls.length = 0;
|
|
131
|
+
const r = await runSend(args);
|
|
132
|
+
expect(r.exitCode).toBe(1);
|
|
133
|
+
expect(r.stderr).toContain("--text is required");
|
|
134
|
+
expect(ipcCalls).toEqual([]);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("what the command reports", () => {
|
|
140
|
+
test("names where the post landed and the conversation it was recorded in", async () => {
|
|
141
|
+
const r = await runSend(["slack", "C0123456789", "--text", "hello"]);
|
|
142
|
+
expect(r.stdout).toContain("C0123456789");
|
|
143
|
+
expect(r.stdout).toContain("1700000000.000100");
|
|
144
|
+
expect(r.stdout).toContain("conv-home");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("says so when the channel split the text", async () => {
|
|
148
|
+
ipcResult = {
|
|
149
|
+
ok: true,
|
|
150
|
+
result: {
|
|
151
|
+
channel: "telegram",
|
|
152
|
+
chatId: "123456789",
|
|
153
|
+
messageIds: ["10", "11", "12"],
|
|
154
|
+
lastMessageId: "12",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
const r = await runSend(["telegram", "123456789", "--text", "a long one"]);
|
|
158
|
+
expect(r.stdout).toContain("3 posts");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("--json answers with the route's own result", async () => {
|
|
162
|
+
const r = await runSend([
|
|
163
|
+
"slack",
|
|
164
|
+
"C0123456789",
|
|
165
|
+
"--text",
|
|
166
|
+
"hello",
|
|
167
|
+
"--json",
|
|
168
|
+
]);
|
|
169
|
+
expect(JSON.parse(r.stdout)).toEqual({
|
|
170
|
+
channel: "slack",
|
|
171
|
+
chatId: "C0123456789",
|
|
172
|
+
messageIds: ["1700000000.000100"],
|
|
173
|
+
lastMessageId: "1700000000.000100",
|
|
174
|
+
recordedIn: "conv-home",
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("a refused send reports the route's reason and its exit code", async () => {
|
|
179
|
+
ipcResult = {
|
|
180
|
+
ok: false,
|
|
181
|
+
error: 'Channel "email" is not addressable',
|
|
182
|
+
statusCode: 400,
|
|
183
|
+
};
|
|
184
|
+
const r = await runSend(["email", "someone", "--text", "hello"]);
|
|
185
|
+
expect(r.exitCode).toBe(
|
|
186
|
+
actualCliClient.exitCodeFromIpcResult({ statusCode: 400 }),
|
|
187
|
+
);
|
|
188
|
+
expect(r.stderr).toContain("not addressable");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("a timeout is reported as an unknown outcome, not a failure to retry", async () => {
|
|
192
|
+
ipcResult = { ok: false, error: "Request timed out", timedOut: true };
|
|
193
|
+
const r = await runSend(["slack", "C0123456789", "--text", "hello"]);
|
|
194
|
+
expect(r.stderr).toContain("may still be in flight");
|
|
195
|
+
expect(r.stderr).toContain("before sending again");
|
|
196
|
+
expect(r.stderr).not.toContain("The send failed");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("a refusal in --json mode is a JSON error envelope", async () => {
|
|
200
|
+
ipcResult = {
|
|
201
|
+
ok: false,
|
|
202
|
+
error: 'Channel "slack" did not acknowledge the send',
|
|
203
|
+
statusCode: 502,
|
|
204
|
+
};
|
|
205
|
+
const r = await runSend([
|
|
206
|
+
"slack",
|
|
207
|
+
"C0123456789",
|
|
208
|
+
"--text",
|
|
209
|
+
"hello",
|
|
210
|
+
"--json",
|
|
211
|
+
]);
|
|
212
|
+
expect(JSON.parse(r.stdout)).toEqual({
|
|
213
|
+
ok: false,
|
|
214
|
+
error: 'Channel "slack" did not acknowledge the send',
|
|
215
|
+
});
|
|
216
|
+
expect(r.exitCode).toBe(3);
|
|
217
|
+
});
|
|
218
|
+
});
|