@vellumai/assistant 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +0 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
*
|
|
24
24
|
* - `host.events.buildEvent` — deterministic helper. Params
|
|
25
25
|
* `{ message, conversationId? }`. Returns the `AssistantEvent` envelope a
|
|
26
|
-
* skill would otherwise construct
|
|
27
|
-
*
|
|
26
|
+
* skill would otherwise construct locally — keeping event-id allocation
|
|
27
|
+
* and timestamp generation on the daemon side
|
|
28
28
|
* so skill processes do not drift on UUID / clock sources.
|
|
29
29
|
*/
|
|
30
30
|
|
|
@@ -32,9 +32,8 @@ import { z } from "zod";
|
|
|
32
32
|
|
|
33
33
|
import { buildAssistantEvent } from "../../runtime/assistant-event.js";
|
|
34
34
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
35
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
36
35
|
import type { SkillIpcRoute } from "../skill-ipc-types.js";
|
|
37
|
-
import type { SkillIpcStreamingRoute } from "../skill-
|
|
36
|
+
import type { SkillIpcStreamingRoute } from "../skill-ipc-types.js";
|
|
38
37
|
|
|
39
38
|
// ---------------------------------------------------------------------------
|
|
40
39
|
// Param schemas
|
|
@@ -42,14 +41,13 @@ import type { SkillIpcStreamingRoute } from "../skill-server.js";
|
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
43
|
* `AssistantEvent` wire shape accepted by `host.events.publish`. The
|
|
45
|
-
* envelope fields (`id`, `
|
|
46
|
-
*
|
|
47
|
-
*
|
|
44
|
+
* envelope fields (`id`, `emittedAt`, `message`) are required;
|
|
45
|
+
* `conversationId` is optional. The `message` payload is an opaque JSON
|
|
46
|
+
* object — the daemon does not narrow it before handing it to
|
|
48
47
|
* `assistantEventHub.publish`, matching the in-process hub contract.
|
|
49
48
|
*/
|
|
50
49
|
const AssistantEventSchema = z.object({
|
|
51
50
|
id: z.string().min(1),
|
|
52
|
-
assistantId: z.string().min(1),
|
|
53
51
|
conversationId: z.string().optional(),
|
|
54
52
|
emittedAt: z.string().min(1),
|
|
55
53
|
message: z.record(z.string(), z.unknown()),
|
|
@@ -60,7 +58,6 @@ const PublishParams = z.object({
|
|
|
60
58
|
});
|
|
61
59
|
|
|
62
60
|
const FilterSchema = z.object({
|
|
63
|
-
assistantId: z.string().min(1),
|
|
64
61
|
conversationId: z.string().optional(),
|
|
65
62
|
});
|
|
66
63
|
|
|
@@ -90,11 +87,7 @@ async function handlePublish(
|
|
|
90
87
|
|
|
91
88
|
function handleBuildEvent(params?: Record<string, unknown>): unknown {
|
|
92
89
|
const { message, conversationId } = BuildEventParams.parse(params);
|
|
93
|
-
return buildAssistantEvent(
|
|
94
|
-
DAEMON_INTERNAL_ASSISTANT_ID,
|
|
95
|
-
message as never,
|
|
96
|
-
conversationId,
|
|
97
|
-
);
|
|
90
|
+
return buildAssistantEvent(message as never, conversationId);
|
|
98
91
|
}
|
|
99
92
|
|
|
100
93
|
// ---------------------------------------------------------------------------
|
|
@@ -111,18 +104,14 @@ export const eventsStreamingRoutes: SkillIpcStreamingRoute[] = [
|
|
|
111
104
|
method: "host.events.subscribe",
|
|
112
105
|
handler: (stream, params) => {
|
|
113
106
|
const { filter } = SubscribeParams.parse(params);
|
|
114
|
-
const subscription = assistantEventHub.subscribe(
|
|
107
|
+
const subscription = assistantEventHub.subscribe({
|
|
108
|
+
type: "process",
|
|
115
109
|
filter,
|
|
116
|
-
(event) => {
|
|
110
|
+
callback: (event) => {
|
|
117
111
|
stream.send(event);
|
|
118
112
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// while the client still believed it was subscribed. Mirror the SSE
|
|
122
|
-
// route's behavior by tearing the stream down with a terminal error
|
|
123
|
-
// frame so the client can resubscribe.
|
|
124
|
-
{ onEvict: () => stream.close("subscription evicted by hub cap") },
|
|
125
|
-
);
|
|
113
|
+
onEvict: () => stream.close("subscription evicted by hub cap"),
|
|
114
|
+
});
|
|
126
115
|
return () => {
|
|
127
116
|
subscription.dispose();
|
|
128
117
|
};
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Skill IPC
|
|
3
|
-
* `host.identity.getInternalAssistantId`.
|
|
2
|
+
* Skill IPC route: `host.identity.getAssistantName`.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* `null` over JSON, which clients translate back to `undefined`).
|
|
9
|
-
* - `getInternalAssistantId` returns the `DAEMON_INTERNAL_ASSISTANT_ID`
|
|
10
|
-
* constant (`"self"`) so skill-side code uses the same internal scope.
|
|
4
|
+
* Reads the assistant's display name from IDENTITY.md, normalizing the
|
|
5
|
+
* daemon helper's `null` to `undefined` (serialized as `null` over JSON,
|
|
6
|
+
* which clients translate back to `undefined`).
|
|
11
7
|
*/
|
|
12
8
|
|
|
13
9
|
import { getAssistantName } from "../../daemon/identity-helpers.js";
|
|
14
|
-
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
|
|
15
10
|
import type { SkillIpcRoute } from "../skill-ipc-types.js";
|
|
16
11
|
|
|
17
12
|
export const hostIdentityGetAssistantNameRoute: SkillIpcRoute = {
|
|
@@ -21,14 +16,6 @@ export const hostIdentityGetAssistantNameRoute: SkillIpcRoute = {
|
|
|
21
16
|
},
|
|
22
17
|
};
|
|
23
18
|
|
|
24
|
-
export const hostIdentityGetInternalAssistantIdRoute: SkillIpcRoute = {
|
|
25
|
-
method: "host.identity.getInternalAssistantId",
|
|
26
|
-
handler: () => {
|
|
27
|
-
return DAEMON_INTERNAL_ASSISTANT_ID;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
19
|
export const identityRoutes: SkillIpcRoute[] = [
|
|
32
20
|
hostIdentityGetAssistantNameRoute,
|
|
33
|
-
hostIdentityGetInternalAssistantIdRoute,
|
|
34
21
|
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SkillIpcRoute } from "../skill-ipc-types.js";
|
|
2
|
-
import type { SkillIpcStreamingRoute } from "../skill-
|
|
2
|
+
import type { SkillIpcStreamingRoute } from "../skill-ipc-types.js";
|
|
3
3
|
import { configRoutes } from "./config.js";
|
|
4
4
|
import { eventsRoutes, eventsStreamingRoutes } from "./events.js";
|
|
5
5
|
import { identityRoutes } from "./identity.js";
|
package/src/ipc/skill-server.ts
CHANGED
|
@@ -50,7 +50,11 @@ import { getLogger } from "../util/logger.js";
|
|
|
50
50
|
import type { IpcRequest, IpcResponse } from "./assistant-server.js";
|
|
51
51
|
|
|
52
52
|
export type { SkillIpcRoute, SkillMethodHandler } from "./skill-ipc-types.js";
|
|
53
|
-
import type {
|
|
53
|
+
import type {
|
|
54
|
+
SkillIpcStream,
|
|
55
|
+
SkillIpcStreamingHandler,
|
|
56
|
+
SkillMethodHandler,
|
|
57
|
+
} from "./skill-ipc-types.js";
|
|
54
58
|
import {
|
|
55
59
|
skillIpcRoutes,
|
|
56
60
|
skillIpcStreamingRoutes,
|
|
@@ -82,28 +86,6 @@ const DEFAULT_SEND_REQUEST_TIMEOUT_MS = 30_000;
|
|
|
82
86
|
const SKILL_IPC_SUBSCRIBE_CLOSE_METHOD = "host.events.subscribe.close" as const;
|
|
83
87
|
|
|
84
88
|
/** Stream handle passed to streaming-handler implementations. */
|
|
85
|
-
export interface SkillIpcStream {
|
|
86
|
-
/** The original request id that opened this stream (used as the stream id). */
|
|
87
|
-
readonly id: string;
|
|
88
|
-
/**
|
|
89
|
-
* Send a delivery frame to the client. No-op after the stream has been
|
|
90
|
-
* closed (client disconnect, explicit close, or server shutdown).
|
|
91
|
-
*/
|
|
92
|
-
send(payload: unknown): void;
|
|
93
|
-
/**
|
|
94
|
-
* Terminate the stream from the server side. Sends a final error frame to
|
|
95
|
-
* the client (if `errorMessage` is provided and the socket is still
|
|
96
|
-
* writable), invokes the handler-returned dispose, and unregisters the
|
|
97
|
-
* stream from the per-socket subscription map. Idempotent — subsequent
|
|
98
|
-
* calls are no-ops. Use from `onEvict`-style callbacks where the upstream
|
|
99
|
-
* source has decided to terminate the subscription, or to surface
|
|
100
|
-
* unrecoverable conditions like backpressure.
|
|
101
|
-
*/
|
|
102
|
-
close(errorMessage?: string): void;
|
|
103
|
-
/** True until the stream has been disposed. */
|
|
104
|
-
readonly active: boolean;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
89
|
/**
|
|
108
90
|
* Maximum bytes Node may have queued in the socket's outbound buffer before
|
|
109
91
|
* the next streaming `send` will close the stream with a backpressure error.
|
|
@@ -115,22 +97,7 @@ export interface SkillIpcStream {
|
|
|
115
97
|
*/
|
|
116
98
|
const STREAM_BACKPRESSURE_BYTES = 1024 * 1024;
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
* Handler signature for long-lived streaming methods (e.g.
|
|
120
|
-
* `host.events.subscribe`). Runs synchronously with the opening request and
|
|
121
|
-
* returns a dispose callback that the server invokes on client disconnect,
|
|
122
|
-
* explicit close, or server shutdown.
|
|
123
|
-
*/
|
|
124
|
-
export type SkillIpcStreamingHandler = (
|
|
125
|
-
stream: SkillIpcStream,
|
|
126
|
-
params?: Record<string, unknown>,
|
|
127
|
-
) => () => void;
|
|
128
|
-
|
|
129
|
-
/** Long-lived streaming route — method name + handler function. */
|
|
130
|
-
export type SkillIpcStreamingRoute = {
|
|
131
|
-
method: string;
|
|
132
|
-
handler: SkillIpcStreamingHandler;
|
|
133
|
-
};
|
|
100
|
+
|
|
134
101
|
|
|
135
102
|
// ---------------------------------------------------------------------------
|
|
136
103
|
// Per-connection context
|
|
@@ -97,7 +97,6 @@ type JsonFrame = Record<string, unknown>;
|
|
|
97
97
|
|
|
98
98
|
const savedAuthEnv = {
|
|
99
99
|
DISABLE_HTTP_AUTH: process.env.DISABLE_HTTP_AUTH,
|
|
100
|
-
VELLUM_UNSAFE_AUTH_BYPASS: process.env.VELLUM_UNSAFE_AUTH_BYPASS,
|
|
101
100
|
};
|
|
102
101
|
|
|
103
102
|
function mintGatewayToken(): string {
|
|
@@ -238,7 +237,6 @@ describe("RuntimeHttpServer live voice WebSocket shell", () => {
|
|
|
238
237
|
|
|
239
238
|
beforeEach(async () => {
|
|
240
239
|
delete process.env.DISABLE_HTTP_AUTH;
|
|
241
|
-
delete process.env.VELLUM_UNSAFE_AUTH_BYPASS;
|
|
242
240
|
resolveStreamingTranscriberImpl = async () => createResolvedTranscriber();
|
|
243
241
|
resolveStreamingTranscriberMock.mockClear();
|
|
244
242
|
resolvedTranscribers.length = 0;
|
|
@@ -260,12 +258,6 @@ describe("RuntimeHttpServer live voice WebSocket shell", () => {
|
|
|
260
258
|
} else {
|
|
261
259
|
process.env.DISABLE_HTTP_AUTH = savedAuthEnv.DISABLE_HTTP_AUTH;
|
|
262
260
|
}
|
|
263
|
-
if (savedAuthEnv.VELLUM_UNSAFE_AUTH_BYPASS === undefined) {
|
|
264
|
-
delete process.env.VELLUM_UNSAFE_AUTH_BYPASS;
|
|
265
|
-
} else {
|
|
266
|
-
process.env.VELLUM_UNSAFE_AUTH_BYPASS =
|
|
267
|
-
savedAuthEnv.VELLUM_UNSAFE_AUTH_BYPASS;
|
|
268
|
-
}
|
|
269
261
|
});
|
|
270
262
|
|
|
271
263
|
function openLiveVoiceClient(token = mintGatewayToken()): WebSocket {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const LIVE_VOICE_CLIENT_FRAME_TYPES = [
|
|
2
2
|
"start",
|
|
3
3
|
"audio",
|
|
4
4
|
"ptt_release",
|
|
@@ -9,7 +9,7 @@ export const LIVE_VOICE_CLIENT_FRAME_TYPES = [
|
|
|
9
9
|
export type LiveVoiceClientFrameType =
|
|
10
10
|
(typeof LIVE_VOICE_CLIENT_FRAME_TYPES)[number];
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
const _LIVE_VOICE_SERVER_FRAME_TYPES = [
|
|
13
13
|
"ready",
|
|
14
14
|
"busy",
|
|
15
15
|
"stt_partial",
|
|
@@ -24,7 +24,7 @@ export const LIVE_VOICE_SERVER_FRAME_TYPES = [
|
|
|
24
24
|
] as const;
|
|
25
25
|
|
|
26
26
|
export type LiveVoiceServerFrameType =
|
|
27
|
-
(typeof
|
|
27
|
+
(typeof _LIVE_VOICE_SERVER_FRAME_TYPES)[number];
|
|
28
28
|
|
|
29
29
|
export const LiveVoiceProtocolErrorCode = {
|
|
30
30
|
InvalidJson: "invalid_json",
|
|
@@ -38,15 +38,6 @@ export const LiveVoiceProtocolErrorCode = {
|
|
|
38
38
|
export type LiveVoiceProtocolErrorCode =
|
|
39
39
|
(typeof LiveVoiceProtocolErrorCode)[keyof typeof LiveVoiceProtocolErrorCode];
|
|
40
40
|
|
|
41
|
-
export const LIVE_VOICE_PROTOCOL_ERROR_CODES = [
|
|
42
|
-
LiveVoiceProtocolErrorCode.InvalidJson,
|
|
43
|
-
LiveVoiceProtocolErrorCode.InvalidFrame,
|
|
44
|
-
LiveVoiceProtocolErrorCode.UnknownType,
|
|
45
|
-
LiveVoiceProtocolErrorCode.MissingRequiredField,
|
|
46
|
-
LiveVoiceProtocolErrorCode.InvalidField,
|
|
47
|
-
LiveVoiceProtocolErrorCode.InvalidAudioPayload,
|
|
48
|
-
] as const satisfies readonly LiveVoiceProtocolErrorCode[];
|
|
49
|
-
|
|
50
41
|
export interface LiveVoiceProtocolError {
|
|
51
42
|
readonly code: LiveVoiceProtocolErrorCode;
|
|
52
43
|
readonly message: string;
|
|
@@ -208,7 +199,7 @@ export type LiveVoiceServerFramePayload =
|
|
|
208
199
|
| WithoutSeq<LiveVoiceArchivedServerFrame>
|
|
209
200
|
| WithoutSeq<LiveVoiceErrorServerFrame>;
|
|
210
201
|
|
|
211
|
-
|
|
202
|
+
class LiveVoiceServerFrameSequencer {
|
|
212
203
|
private seq: number;
|
|
213
204
|
|
|
214
205
|
constructor(initialSeq = 0) {
|
package/src/mcp/manager.ts
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MemoryV2ConceptRowRecord,
|
|
3
|
+
MemoryV2ConfigSnapshot,
|
|
4
|
+
MemoryV2SkillRowRecord,
|
|
5
|
+
} from "../../memory-v2-activation-log-store.js";
|
|
6
|
+
|
|
7
|
+
export const sampleConcepts: MemoryV2ConceptRowRecord[] = [
|
|
8
|
+
{
|
|
9
|
+
slug: "concept-a",
|
|
10
|
+
finalActivation: 0.9,
|
|
11
|
+
ownActivation: 0.7,
|
|
12
|
+
priorActivation: 0.5,
|
|
13
|
+
simUser: 0.6,
|
|
14
|
+
simAssistant: 0.4,
|
|
15
|
+
simNow: 0.3,
|
|
16
|
+
spreadContribution: 0.2,
|
|
17
|
+
source: "both",
|
|
18
|
+
status: "injected",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
slug: "concept-b",
|
|
22
|
+
finalActivation: 0.4,
|
|
23
|
+
ownActivation: 0.3,
|
|
24
|
+
priorActivation: 0.1,
|
|
25
|
+
simUser: 0.2,
|
|
26
|
+
simAssistant: 0.1,
|
|
27
|
+
simNow: 0.05,
|
|
28
|
+
spreadContribution: 0.0,
|
|
29
|
+
source: "ann_top50",
|
|
30
|
+
status: "not_injected",
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const sampleSkills: MemoryV2SkillRowRecord[] = [
|
|
35
|
+
{
|
|
36
|
+
id: "skill-1",
|
|
37
|
+
activation: 0.8,
|
|
38
|
+
simUser: 0.5,
|
|
39
|
+
simAssistant: 0.4,
|
|
40
|
+
simNow: 0.3,
|
|
41
|
+
status: "injected",
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export const sampleConfig: MemoryV2ConfigSnapshot = {
|
|
46
|
+
d: 0.85,
|
|
47
|
+
c_user: 1.0,
|
|
48
|
+
c_assistant: 0.5,
|
|
49
|
+
c_now: 0.25,
|
|
50
|
+
k: 5,
|
|
51
|
+
hops: 2,
|
|
52
|
+
top_k: 10,
|
|
53
|
+
top_k_skills: 3,
|
|
54
|
+
epsilon: 0.001,
|
|
55
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
mock.module("../../util/logger.js", () => ({
|
|
4
|
+
getLogger: () =>
|
|
5
|
+
new Proxy({} as Record<string, unknown>, {
|
|
6
|
+
get: () => () => {},
|
|
7
|
+
}),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
mock.module("../../config/loader.js", () => ({
|
|
11
|
+
getConfig: () => ({
|
|
12
|
+
ui: {},
|
|
13
|
+
model: "test",
|
|
14
|
+
provider: "test",
|
|
15
|
+
memory: { enabled: false },
|
|
16
|
+
rateLimit: { maxRequestsPerMinute: 0 },
|
|
17
|
+
secretDetection: { enabled: false },
|
|
18
|
+
}),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
import { getDb } from "../db-connection.js";
|
|
22
|
+
import { initializeDb } from "../db-init.js";
|
|
23
|
+
import {
|
|
24
|
+
backfillMemoryV2ActivationMessageId,
|
|
25
|
+
getMemoryV2ActivationLogByMessageIds,
|
|
26
|
+
recordMemoryV2ActivationLog,
|
|
27
|
+
} from "../memory-v2-activation-log-store.js";
|
|
28
|
+
import { memoryV2ActivationLogs } from "../schema.js";
|
|
29
|
+
import {
|
|
30
|
+
sampleConcepts,
|
|
31
|
+
sampleConfig,
|
|
32
|
+
sampleSkills,
|
|
33
|
+
} from "./fixtures/memory-v2-activation-fixtures.js";
|
|
34
|
+
|
|
35
|
+
initializeDb();
|
|
36
|
+
|
|
37
|
+
function resetTables(): void {
|
|
38
|
+
const db = getDb();
|
|
39
|
+
db.delete(memoryV2ActivationLogs).run();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("memory-v2-activation-log-store", () => {
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
resetTables();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("round-trip: record → backfill messageId → query by messageId", () => {
|
|
48
|
+
const conversationId = "conv-1";
|
|
49
|
+
const messageId = "msg-1";
|
|
50
|
+
|
|
51
|
+
recordMemoryV2ActivationLog({
|
|
52
|
+
conversationId,
|
|
53
|
+
turn: 3,
|
|
54
|
+
mode: "per-turn",
|
|
55
|
+
concepts: sampleConcepts,
|
|
56
|
+
skills: sampleSkills,
|
|
57
|
+
config: sampleConfig,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
backfillMemoryV2ActivationMessageId(conversationId, messageId);
|
|
61
|
+
|
|
62
|
+
const result = getMemoryV2ActivationLogByMessageIds([messageId]);
|
|
63
|
+
expect(result).not.toBeNull();
|
|
64
|
+
expect(result!.conversationId).toBe(conversationId);
|
|
65
|
+
expect(result!.turn).toBe(3);
|
|
66
|
+
expect(result!.mode).toBe("per-turn");
|
|
67
|
+
expect(result!.concepts).toEqual(sampleConcepts);
|
|
68
|
+
expect(result!.skills).toEqual(sampleSkills);
|
|
69
|
+
expect(result!.config).toEqual(sampleConfig);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("returns null for empty messageIds array", () => {
|
|
73
|
+
const result = getMemoryV2ActivationLogByMessageIds([]);
|
|
74
|
+
expect(result).toBeNull();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("backfill only updates rows with NULL messageId", () => {
|
|
78
|
+
const conversationId = "conv-2";
|
|
79
|
+
|
|
80
|
+
recordMemoryV2ActivationLog({
|
|
81
|
+
conversationId,
|
|
82
|
+
turn: 1,
|
|
83
|
+
mode: "context-load",
|
|
84
|
+
concepts: sampleConcepts,
|
|
85
|
+
skills: sampleSkills,
|
|
86
|
+
config: sampleConfig,
|
|
87
|
+
});
|
|
88
|
+
recordMemoryV2ActivationLog({
|
|
89
|
+
conversationId,
|
|
90
|
+
turn: 2,
|
|
91
|
+
mode: "per-turn",
|
|
92
|
+
concepts: sampleConcepts,
|
|
93
|
+
skills: sampleSkills,
|
|
94
|
+
config: sampleConfig,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// First backfill: both rows should now have msg-a.
|
|
98
|
+
backfillMemoryV2ActivationMessageId(conversationId, "msg-a");
|
|
99
|
+
|
|
100
|
+
const db = getDb();
|
|
101
|
+
const afterFirstBackfill = db.select().from(memoryV2ActivationLogs).all();
|
|
102
|
+
expect(afterFirstBackfill).toHaveLength(2);
|
|
103
|
+
for (const row of afterFirstBackfill) {
|
|
104
|
+
expect(row.messageId).toBe("msg-a");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Record a third row (messageId is NULL initially).
|
|
108
|
+
recordMemoryV2ActivationLog({
|
|
109
|
+
conversationId,
|
|
110
|
+
turn: 3,
|
|
111
|
+
mode: "per-turn",
|
|
112
|
+
concepts: sampleConcepts,
|
|
113
|
+
skills: sampleSkills,
|
|
114
|
+
config: sampleConfig,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Second backfill with msg-b should only set the third row,
|
|
118
|
+
// and must not overwrite the first two rows already set to msg-a.
|
|
119
|
+
backfillMemoryV2ActivationMessageId(conversationId, "msg-b");
|
|
120
|
+
|
|
121
|
+
const afterSecondBackfill = db.select().from(memoryV2ActivationLogs).all();
|
|
122
|
+
const byTurn = new Map(afterSecondBackfill.map((r) => [r.turn, r]));
|
|
123
|
+
expect(byTurn.get(1)!.messageId).toBe("msg-a");
|
|
124
|
+
expect(byTurn.get(2)!.messageId).toBe("msg-a");
|
|
125
|
+
expect(byTurn.get(3)!.messageId).toBe("msg-b");
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -132,38 +132,6 @@ function validateRelativePath(path: string): void {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Initialization & commit
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Eagerly initialize the app git repo so that the "Initial commit" is
|
|
141
|
-
* created before any app files are written. Without this, the first
|
|
142
|
-
* mutation's files get absorbed into WorkspaceGitService's bootstrap
|
|
143
|
-
* commit and the "Create app: ..." commit ends up empty.
|
|
144
|
-
*
|
|
145
|
-
* Safe to call multiple times -- ensureInitialized() is idempotent.
|
|
146
|
-
* Commit app changes to the apps git repository.
|
|
147
|
-
*
|
|
148
|
-
* This is fire-and-forget: errors are logged but never thrown.
|
|
149
|
-
* The caller should not await the returned promise unless it needs
|
|
150
|
-
* to guarantee the commit completed (e.g. in tests).
|
|
151
|
-
*/
|
|
152
|
-
export async function commitAppChange(message: string): Promise<void> {
|
|
153
|
-
try {
|
|
154
|
-
const appsDir = getAppsDir();
|
|
155
|
-
|
|
156
|
-
// Re-check .gitignore rules every call in case the apps dir was
|
|
157
|
-
// recreated while the process was running.
|
|
158
|
-
ensureAppGitignoreRules(appsDir);
|
|
159
|
-
|
|
160
|
-
const gitService = getWorkspaceGitService(appsDir);
|
|
161
|
-
await gitService.commitChanges(message);
|
|
162
|
-
} catch (err) {
|
|
163
|
-
log.error({ err, message }, "Failed to commit app change");
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
135
|
/**
|
|
168
136
|
* Commit app changes at turn boundaries.
|
|
169
137
|
*
|
package/src/memory/app-store.ts
CHANGED
|
@@ -36,7 +36,9 @@ import {
|
|
|
36
36
|
|
|
37
37
|
import type { EditEngineResult } from "../tools/shared/filesystem/edit-engine.js";
|
|
38
38
|
import { applyEdit } from "../tools/shared/filesystem/edit-engine.js";
|
|
39
|
+
import { getLogger } from "../util/logger.js";
|
|
39
40
|
import { getDataDir } from "../util/platform.js";
|
|
41
|
+
import { rawAll } from "./raw-query.js";
|
|
40
42
|
|
|
41
43
|
export interface AppDefinition {
|
|
42
44
|
id: string;
|
|
@@ -55,6 +57,8 @@ export interface AppDefinition {
|
|
|
55
57
|
formatVersion?: number;
|
|
56
58
|
/** Filesystem directory/file stem. Frozen at creation -- never changes on rename. */
|
|
57
59
|
dirName?: string;
|
|
60
|
+
/** Conversation IDs that have interacted with this app (create/open/refresh). */
|
|
61
|
+
conversationIds?: string[];
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
/**
|
|
@@ -901,4 +905,154 @@ export function editAppFile(
|
|
|
901
905
|
return result;
|
|
902
906
|
}
|
|
903
907
|
|
|
908
|
+
// ---------------------------------------------------------------------------
|
|
909
|
+
// Conversation association helpers
|
|
910
|
+
// ---------------------------------------------------------------------------
|
|
911
|
+
|
|
912
|
+
/**
|
|
913
|
+
* Associate a conversation with an app. Writes directly to the JSON metadata
|
|
914
|
+
* file without bumping `updatedAt` so the app list ordering is preserved.
|
|
915
|
+
*
|
|
916
|
+
* @returns `true` if the association was added, `false` if the app was not
|
|
917
|
+
* found or the conversationId was already present (dedup).
|
|
918
|
+
*/
|
|
919
|
+
export function addAppConversationId(
|
|
920
|
+
appId: string,
|
|
921
|
+
conversationId: string,
|
|
922
|
+
): boolean {
|
|
923
|
+
const app = getApp(appId);
|
|
924
|
+
if (!app) return false;
|
|
925
|
+
|
|
926
|
+
const { dirName } = resolveAppDir(appId);
|
|
927
|
+
const dir = getAppsDir();
|
|
928
|
+
const jsonPath = join(dir, `${dirName}.json`);
|
|
929
|
+
|
|
930
|
+
// Atomic read-modify-write: re-read the file immediately before writing
|
|
931
|
+
// so concurrent callers (e.g. two tool_result handlers for the same app
|
|
932
|
+
// in different conversations) merge against the latest on-disk state.
|
|
933
|
+
// Because readFileSync → JSON.parse → writeFileSync is a synchronous
|
|
934
|
+
// chain with no async gaps, Node/Bun's single-threaded event loop
|
|
935
|
+
// guarantees no interleaving between the read and the write.
|
|
936
|
+
const raw = readFileSync(jsonPath, "utf-8");
|
|
937
|
+
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
938
|
+
const onDiskIds = Array.isArray(parsed.conversationIds)
|
|
939
|
+
? (parsed.conversationIds as string[])
|
|
940
|
+
: [];
|
|
941
|
+
|
|
942
|
+
if (onDiskIds.includes(conversationId)) return false;
|
|
943
|
+
|
|
944
|
+
parsed.conversationIds = [...onDiskIds, conversationId];
|
|
945
|
+
writeFileSync(jsonPath, JSON.stringify(parsed, null, 2));
|
|
946
|
+
|
|
947
|
+
return true;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* Return all apps associated with a given conversation ID.
|
|
952
|
+
*/
|
|
953
|
+
export function listAppsByConversation(
|
|
954
|
+
conversationId: string,
|
|
955
|
+
): AppDefinition[] {
|
|
956
|
+
return listApps().filter((app) =>
|
|
957
|
+
app.conversationIds?.includes(conversationId),
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// ---------------------------------------------------------------------------
|
|
962
|
+
// Backfill: scan message history for ui_surface blocks referencing apps
|
|
963
|
+
// ---------------------------------------------------------------------------
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Single-pass scan over the messages table to populate `conversationIds` on
|
|
967
|
+
* existing app definitions. Finds messages containing `ui_surface` blocks
|
|
968
|
+
* with a `data.appId`, then calls `addAppConversationId` for each pair.
|
|
969
|
+
*
|
|
970
|
+
* Runs once per workspace: after a successful backfill a sentinel file
|
|
971
|
+
* (`<appsDir>/.conversation-ids-backfilled`) is written. Subsequent daemon
|
|
972
|
+
* startups skip the scan entirely. If the apps directory is wiped the
|
|
973
|
+
* sentinel disappears and the backfill re-runs — which is correct behavior.
|
|
974
|
+
*
|
|
975
|
+
* Wrapped in try/catch so failures never block daemon start.
|
|
976
|
+
*/
|
|
977
|
+
export function backfillAppConversationIds(): void {
|
|
978
|
+
const log = getLogger("app-store");
|
|
979
|
+
|
|
980
|
+
// Check sentinel — skip the potentially expensive scan when already done.
|
|
981
|
+
const sentinelPath = join(getAppsDir(), ".conversation-ids-backfilled");
|
|
982
|
+
if (existsSync(sentinelPath)) {
|
|
983
|
+
log.debug("Skipping backfillAppConversationIds — sentinel exists");
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
try {
|
|
988
|
+
const rows = rawAll<{ conversation_id: string; content: string }>(
|
|
989
|
+
`SELECT conversation_id, content FROM messages WHERE content LIKE '%"type":"ui_surface"%'`,
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
// Build appId → Set<conversationId> map in a single pass
|
|
993
|
+
const appConvMap = new Map<string, Set<string>>();
|
|
994
|
+
|
|
995
|
+
for (const row of rows) {
|
|
996
|
+
let parsed: unknown;
|
|
997
|
+
try {
|
|
998
|
+
parsed = JSON.parse(row.content);
|
|
999
|
+
} catch {
|
|
1000
|
+
// Skip rows that fail to parse
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
if (!Array.isArray(parsed)) continue;
|
|
1005
|
+
|
|
1006
|
+
for (const block of parsed) {
|
|
1007
|
+
if (
|
|
1008
|
+
block &&
|
|
1009
|
+
typeof block === "object" &&
|
|
1010
|
+
(block as Record<string, unknown>).type === "ui_surface"
|
|
1011
|
+
) {
|
|
1012
|
+
const data = (block as Record<string, unknown>).data;
|
|
1013
|
+
if (data && typeof data === "object") {
|
|
1014
|
+
const appId = (data as Record<string, unknown>).appId;
|
|
1015
|
+
if (typeof appId === "string" && appId.length > 0) {
|
|
1016
|
+
let convIds = appConvMap.get(appId);
|
|
1017
|
+
if (!convIds) {
|
|
1018
|
+
convIds = new Set<string>();
|
|
1019
|
+
appConvMap.set(appId, convIds);
|
|
1020
|
+
}
|
|
1021
|
+
convIds.add(row.conversation_id);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Apply associations
|
|
1029
|
+
let appsUpdated = 0;
|
|
1030
|
+
let associationsAdded = 0;
|
|
1031
|
+
|
|
1032
|
+
for (const [appId, conversationIds] of appConvMap) {
|
|
1033
|
+
let appHadNewAssociation = false;
|
|
1034
|
+
for (const conversationId of conversationIds) {
|
|
1035
|
+
const added = addAppConversationId(appId, conversationId);
|
|
1036
|
+
if (added) {
|
|
1037
|
+
associationsAdded++;
|
|
1038
|
+
appHadNewAssociation = true;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
if (appHadNewAssociation) {
|
|
1042
|
+
appsUpdated++;
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
log.info(
|
|
1047
|
+
{ appsUpdated, associationsAdded },
|
|
1048
|
+
`Backfilled app conversationIds: ${appsUpdated} apps, ${associationsAdded} associations`,
|
|
1049
|
+
);
|
|
1050
|
+
|
|
1051
|
+
// Write sentinel so subsequent startups skip this scan.
|
|
1052
|
+
writeFileSync(sentinelPath, new Date().toISOString(), "utf-8");
|
|
1053
|
+
} catch (err) {
|
|
1054
|
+
log.error({ err }, "Failed to backfill app conversationIds");
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
904
1058
|
export type { EditEngineResult };
|